Loading [MathJax]/jax/output/HTML-CSS/jax.js
110 Star 70 Fork 297

src-openEuler/kernel

 / 详情

CVE-2024-46734

已完成
CVE和安全问题 拥有者
创建于  
2024-09-18 18:25

一、漏洞信息
漏洞编号:CVE-2024-46734
漏洞归属组件:kernel
漏洞归属的版本:4.19.140,4.19.194,4.19.90,5.10.0,6.1.0,6.1.14,6.1.19,6.1.5,6.1.6,6.1.8,6.4.0,6.6.0
CVSS V2.0分值:
BaseScore:0.0 None
Vector:CVSS:2.0/
漏洞简述:
In the Linux kernel, the following vulnerability has been resolved:btrfs: fix race between direct IO write and fsync when using same fdIf we have 2 threads that are using the same file descriptor and one ofthem is doing direct IO writes while the other is doing fsync, we have arace where we can end up either:1) Attempt a fsync without holding the inode s lock, triggering an assertion failures when assertions are enabled;2) Do an invalid memory access from the fsync task because the file private points to memory allocated on stack by the direct IO task and it may be used by the fsync task after the stack was destroyed.The race happens like this:1) A user space program opens a file descriptor with O_DIRECT;2) The program spawns 2 threads using libpthread for example;3) One of the threads uses the file descriptor to do direct IO writes, while the other calls fsync using the same file descriptor.4) Call task A the thread doing direct IO writes and task B the thread doing fsyncs;5) Task A does a direct IO write, and at btrfs_direct_write() sets the file s private to an on stack allocated private with the member fsync_skip_inode_lock set to true;6) Task B enters btrfs_sync_file() and sees that there s a private structure associated to the file which has fsync_skip_inode_lock set to true, so it skips locking the inode s VFS lock;7) Task A completes the direct IO write, and resets the file s private to NULL since it had no prior private and our private was stack allocated. Then it unlocks the inode s VFS lock;8) Task B enters btrfs_get_ordered_extents_for_logging(), then the assertion that checks the inode s VFS lock is held fails, since task B never locked it and task A has already unlocked it.The stack trace produced is the following: assertion failed: inode_is_locked(&inode->vfs_inode), in fs/btrfs/ordered-data.c:983 ------------[ cut here ]------------ kernel BUG at fs/btrfs/ordered-data.c:983! Oops: invalid opcode: 0000 [#1] PREEMPT SMP PTI CPU: 9 PID: 5072 Comm: worker Tainted: G U OE 6.10.5-1-default #1 openSUSE Tumbleweed 69f48d427608e1c09e60ea24c6c55e2ca1b049e8 Hardware name: Acer Predator PH315-52/Covini_CFS, BIOS V1.12 07/28/2020 RIP: 0010:btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs] Code: 50 d6 86 c0 e8 (...) RSP: 0018:ffff9e4a03dcfc78 EFLAGS: 00010246 RAX: 0000000000000054 RBX: ffff9078a9868e98 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff907dce4a7800 RDI: ffff907dce4a7800 RBP: ffff907805518800 R08: 0000000000000000 R09: ffff9e4a03dcfb38 R10: ffff9e4a03dcfb30 R11: 0000000000000003 R12: ffff907684ae7800 R13: 0000000000000001 R14: ffff90774646b600 R15: 0000000000000000 FS: 00007f04b96006c0(0000) GS:ffff907dce480000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f32acbfc000 CR3: 00000001fd4fa005 CR4: 00000000003726f0 Call Trace: ? __die_body.cold+0x14/0x24 ? die+0x2e/0x50 ? do_trap+0xca/0x110 ? do_error_trap+0x6a/0x90 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? exc_invalid_op+0x50/0x70 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? asm_exc_invalid_op+0x1a/0x20 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] btrfs_sync_file+0x21a/0x4d0 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? __seccomp_filter+0x31d/0x4f0 __x64_sys_fdatasync+0x4f/0x90 do_syscall_64+0x82/0x160 ? do_futex+0xcb/0x190 ? __x64_sys_futex+0x10e/0x1d0 ? switch_fpu_return+0x4f/0xd0 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mod---truncated---
漏洞公开时间:2024-09-18 16:15:02
漏洞创建时间:2024-09-19 02:25:09
漏洞详情参考链接:
https://nvd.nist.gov/vuln/detail/CVE-2024-46734

更多参考(点击展开)
参考来源 参考链接 来源链接
416baaa9-dc9f-4396-8d5f-8c081fb06d67 https://git.kernel.org/stable/c/01681aa609b5f110502f56c4e3b2938efcf4a5bc
416baaa9-dc9f-4396-8d5f-8c081fb06d67 https://git.kernel.org/stable/c/7b5595f33c3c273613b590892a578d78186bb400
416baaa9-dc9f-4396-8d5f-8c081fb06d67 https://git.kernel.org/stable/c/cd3087582e4fa36e89be4e6f859e75a4400292b4
416baaa9-dc9f-4396-8d5f-8c081fb06d67 https://git.kernel.org/stable/c/cd9253c23aedd61eb5ff11f37a36247cd46faf86
416baaa9-dc9f-4396-8d5f-8c081fb06d67 https://git.kernel.org/stable/c/d116a0b0e02f395cedfb8c725bd67480aa7c428c
suse_bugzilla http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2024-46734 https://bugzilla.suse.com/show_bug.cgi?id=1230726
suse_bugzilla https://www.cve.org/CVERecord?id=CVE-2024-46734 https://bugzilla.suse.com/show_bug.cgi?id=1230726
suse_bugzilla https://git.kernel.org/stable/c/01681aa609b5f110502f56c4e3b2938efcf4a5bc https://bugzilla.suse.com/show_bug.cgi?id=1230726
suse_bugzilla https://git.kernel.org/stable/c/7b5595f33c3c273613b590892a578d78186bb400 https://bugzilla.suse.com/show_bug.cgi?id=1230726
suse_bugzilla https://git.kernel.org/stable/c/cd3087582e4fa36e89be4e6f859e75a4400292b4 https://bugzilla.suse.com/show_bug.cgi?id=1230726
suse_bugzilla https://git.kernel.org/stable/c/cd9253c23aedd61eb5ff11f37a36247cd46faf86 https://bugzilla.suse.com/show_bug.cgi?id=1230726
suse_bugzilla https://git.kernel.org/stable/c/d116a0b0e02f395cedfb8c725bd67480aa7c428c https://bugzilla.suse.com/show_bug.cgi?id=1230726
suse_bugzilla https://git.kernel.org/pub/scm/linux/security/vulns.git/plain/cve/published/2024/CVE-2024-46734.mbox https://bugzilla.suse.com/show_bug.cgi?id=1230726
redhat_bugzilla https://lore.kernel.org/linux-cve-announce/2024091830-CVE-2024-46734-9fe1@gregkh/T https://bugzilla.redhat.com/show_bug.cgi?id=2313082
debian https://security-tracker.debian.org/tracker/CVE-2024-46734
anolis https://anas.openanolis.cn/cves/detail/CVE-2024-46734
mageia http://advisories.mageia.org/MGASA-2024-0316.html
amazon_linux_explore https://access.redhat.com/security/cve/CVE-2024-46734 https://explore.alas.aws.amazon.com/CVE-2024-46734.html
amazon_linux_explore https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-46734 https://explore.alas.aws.amazon.com/CVE-2024-46734.html

漏洞分析指导链接:
https://gitee.com/openeuler/cve-manager/blob/master/cve-vulner-manager/doc/md/manual.md
漏洞数据来源:
openBrain开源漏洞感知系统
漏洞补丁信息:

详情(点击展开)

二、漏洞分析结构反馈
影响性分析说明:
In the Linux kernel, the following vulnerability has been resolved:btrfs: fix race between direct IO write and fsync when using same fdIf we have 2 threads that are using the same file descriptor and one ofthem is doing direct IO writes while the other is doing fsync, we have arace where we can end up either:1) Attempt a fsync without holding the inode's lock, triggering an assertion failures when assertions are enabled;2) Do an invalid memory access from the fsync task because the file private points to memory allocated on stack by the direct IO task and it may be used by the fsync task after the stack was destroyed.The race happens like this:1) A user space program opens a file descriptor with O_DIRECT;2) The program spawns 2 threads using libpthread for example;3) One of the threads uses the file descriptor to do direct IO writes, while the other calls fsync using the same file descriptor.4) Call task A the thread doing direct IO writes and task B the thread doing fsyncs;5) Task A does a direct IO write, and at btrfs_direct_write() sets the file's private to an on stack allocated private with the member 'fsync_skip_inode_lock' set to true;6) Task B enters btrfs_sync_file() and sees that there's a private structure associated to the file which has 'fsync_skip_inode_lock' set to true, so it skips locking the inode's VFS lock;7) Task A completes the direct IO write, and resets the file's private to NULL since it had no prior private and our private was stack allocated. Then it unlocks the inode's VFS lock;8) Task B enters btrfs_get_ordered_extents_for_logging(), then the assertion that checks the inode's VFS lock is held fails, since task B never locked it and task A has already unlocked it.The stack trace produced is the following: assertion failed: inode_is_locked(&inode->vfs_inode), in fs/btrfs/ordered-data.c:983 ------------[ cut here ]------------ kernel BUG at fs/btrfs/ordered-data.c:983! Oops: invalid opcode: 0000 [#1] PREEMPT SMP PTI CPU: 9 PID: 5072 Comm: worker Tainted: G U OE 6.10.5-1-default #1 openSUSE Tumbleweed 69f48d427608e1c09e60ea24c6c55e2ca1b049e8 Hardware name: Acer Predator PH315-52/Covini_CFS, BIOS V1.12 07/28/2020 RIP: 0010:btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs] Code: 50 d6 86 c0 e8 (...) RSP: 0018:ffff9e4a03dcfc78 EFLAGS: 00010246 RAX: 0000000000000054 RBX: ffff9078a9868e98 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff907dce4a7800 RDI: ffff907dce4a7800 RBP: ffff907805518800 R08: 0000000000000000 R09: ffff9e4a03dcfb38 R10: ffff9e4a03dcfb30 R11: 0000000000000003 R12: ffff907684ae7800 R13: 0000000000000001 R14: ffff90774646b600 R15: 0000000000000000 FS: 00007f04b96006c0(0000) GS:ffff907dce480000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f32acbfc000 CR3: 00000001fd4fa005 CR4: 00000000003726f0 Call Trace: <TASK> ? __die_body.cold+0x14/0x24 ? die+0x2e/0x50 ? do_trap+0xca/0x110 ? do_error_trap+0x6a/0x90 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? exc_invalid_op+0x50/0x70 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? asm_exc_invalid_op+0x1a/0x20 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] btrfs_sync_file+0x21a/0x4d0 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? __seccomp_filter+0x31d/0x4f0 __x64_sys_fdatasync+0x4f/0x90 do_syscall_64+0x82/0x160 ? do_futex+0xcb/0x190 ? __x64_sys_futex+0x10e/0x1d0 ? switch_fpu_return+0x4f/0xd0 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160
openEuler评分:
5.5
Vector:CVSS:2.0/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
受影响版本排查(受影响/不受影响):
1.openEuler-24.03-LTS(6.6.0):受影响
2.openEuler-20.03-LTS-SP4(4.19.90):不受影响
3.openEuler-22.03-LTS-SP1(5.10.0):不受影响
4.openEuler-22.03-LTS-SP3(5.10.0):不受影响
5.openEuler-22.03-LTS-SP4(5.10.0):不受影响
6.master(6.6.0):不受影响
7.openEuler-24.03-LTS-Next(6.6.0):不受影响

修复是否涉及abi变化(是/否):
1.openEuler-20.03-LTS-SP4(4.19.90):否
2.openEuler-22.03-LTS-SP1(5.10.0):否
3.openEuler-22.03-LTS-SP3(5.10.0):否
4.master(6.6.0):否
5.openEuler-24.03-LTS(6.6.0):否
6.openEuler-24.03-LTS-Next(6.6.0):否
7.openEuler-22.03-LTS-SP4(5.10.0):否

三、漏洞修复
安全公告链接:https://www.openeuler.org/zh/security/safety-bulletin/detail/?id=openEuler-SA-2024-2219

评论 (12)

openeuler-ci-bot 创建了CVE和安全问题 7个月前
openeuler-ci-bot 添加了
 
CVE/UNFIXED
标签
7个月前
展开全部操作日志

Hi openeuler-ci-bot, welcome to the openEuler Community.
I'm the Bot here serving you. You can find the instructions on how to interact with me at Here.
If you have any questions, please contact the SIG: Kernel, and any of the maintainers.

@yangyingliang ,@jiaoff ,@guohaocs2c ,@hanjun-guo ,@woqidaideshi ,@newbeats ,@zhangyi089 ,@colyli ,@thundertown ,@htforge ,@chiqijun ,@lengchao ,@zhujianwei001 ,@kylin-mayukun ,@wangxiongfeng ,@wkfxxx ,@SuperSix173 ,@jentlestea ,@oskernel0719 ,@gasonchen
issue处理注意事项:
1. 当前issue受影响的分支提交pr时, 须在pr描述中填写当前issue编号进行关联, 否则无法关闭当前issue;
2. 模板内容需要填写完整, 无论是受影响或者不受影响都需要填写完整内容,未引入的分支不需要填写, 否则无法关闭当前issue;
3. 以下为模板中需要填写完整的内容, 请复制到评论区回复, 注: 内容的标题名称(影响性分析说明, openEuler评分, 受影响版本排查(受影响/不受影响), 修复是否涉及abi变化(是/否))不能省略,省略后cve-manager将无法正常解析填写内容.


影响性分析说明:

openEuler评分: (评分和向量)

受影响版本排查(受影响/不受影响):
1.master(6.6.0):
2.openEuler-20.03-LTS-SP4(4.19.90):
3.openEuler-22.03-LTS-SP1(5.10.0):
4.openEuler-22.03-LTS-SP3(5.10.0):
5.openEuler-22.03-LTS-SP4(5.10.0):
6.openEuler-24.03-LTS(6.6.0):
7.openEuler-24.03-LTS-Next(6.6.0):

修复是否涉及abi变化(是/否):
1.master(6.6.0):
2.openEuler-20.03-LTS-SP4(4.19.90):
3.openEuler-22.03-LTS-SP1(5.10.0):
4.openEuler-22.03-LTS-SP3(5.10.0):
5.openEuler-22.03-LTS-SP4(5.10.0):
6.openEuler-24.03-LTS(6.6.0):
7.openEuler-24.03-LTS-Next(6.6.0):


issue处理具体操作请参考:
https://gitee.com/openeuler/cve-manager/blob/master/cve-vulner-manager/doc/md/manual.md
pr关联issue具体操作请参考:
https://gitee.com/help/articles/4142

openeuler-ci-bot 添加了
 
sig/Kernel
标签
7个月前
参考网址 关联pr 状态 补丁链接
https://nvd.nist.gov/vuln/detail/CVE-2024-46734NoneNonehttps://git.kernel.org/stable/c/d116a0b0e02f395cedfb8c725bd67480aa7c428c
https://git.kernel.org/stable/c/7b5595f33c3c273613b590892a578d78186bb400
https://git.kernel.org/stable/c/cd9253c23aedd61eb5ff11f37a36247cd46faf86
https://git.kernel.org/stable/c/01681aa609b5f110502f56c4e3b2938efcf4a5bc
https://git.kernel.org/stable/c/cd3087582e4fa36e89be4e6f859e75a4400292b4
https://ubuntu.com/security/CVE-2024-46734NoneNonehttps://discourse.ubuntu.com/c/ubuntu-pro
https://www.opencve.io/cve/CVE-2024-46734NoneNonehttps://git.kernel.org/stable/c/d116a0b0e02f395cedfb8c725bd67480aa7c428c
https://git.kernel.org/stable/c/7b5595f33c3c273613b590892a578d78186bb400
https://git.kernel.org/stable/c/cd9253c23aedd61eb5ff11f37a36247cd46faf86
https://git.kernel.org/stable/c/01681aa609b5f110502f56c4e3b2938efcf4a5bc
https://git.kernel.org/stable/c/cd3087582e4fa36e89be4e6f859e75a4400292b4
https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2024-46734
https://security-tracker.debian.org/tracker/CVE-2024-46734NoneNonehttps://git.kernel.org/linus/cd9253c23aedd61eb5ff11f37a36247cd46faf86

说明:补丁链接仅供初步排查参考,实际可用性请人工再次确认,补丁下载验证可使用CVE补丁工具
若补丁不准确,烦请在此issue下评论 '/report-patch 参考网址 补丁链接1,补丁链接2' 反馈正确信息,便于我们不断优化工具,不胜感激。
如 /report-patch https://security-tracker.debian.org/tracker/CVE-2021-3997 https://github.com/systemd/systemd/commit/5b1cf7a9be37e20133c0208005274ce4a5b5c6a1

openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前

CVE-2024-46734

影响性分析说明:
In the Linux kernel, the following vulnerability has been resolved:

btrfs: fix race between direct IO write and fsync when using same fd

If we have 2 threads that are using the same file descriptor and one of
them is doing direct IO writes while the other is doing fsync, we have a
race where we can end up either:

  1. Attempt a fsync without holding the inode's lock, triggering an
    assertion failures when assertions are enabled;

  2. Do an invalid memory access from the fsync task because the file private
    points to memory allocated on stack by the direct IO task and it may be
    used by the fsync task after the stack was destroyed.

The race happens like this:

  1. A user space program opens a file descriptor with O_DIRECT;

  2. The program spawns 2 threads using libpthread for example;

  3. One of the threads uses the file descriptor to do direct IO writes,
    while the other calls fsync using the same file descriptor.

  4. Call task A the thread doing direct IO writes and task B the thread
    doing fsyncs;

  5. Task A does a direct IO write, and at btrfs_direct_write() sets the
    file's private to an on stack allocated private with the member
    'fsync_skip_inode_lock' set to true;

  6. Task B enters btrfs_sync_file() and sees that there's a private
    structure associated to the file which has 'fsync_skip_inode_lock' set
    to true, so it skips locking the inode's VFS lock;

  7. Task A completes the direct IO write, and resets the file's private to
    NULL since it had no prior private and our private was stack allocated.
    Then it unlocks the inode's VFS lock;

  8. Task B enters btrfs_get_ordered_extents_for_logging(), then the
    assertion that checks the inode's VFS lock is held fails, since task B
    never locked it and task A has already unlocked it.

The stack trace produced is the following:

assertion failed: inode_is_locked(&inode->vfs_inode), in fs/btrfs/ordered-data.c:983
------------[ cut here ]------------
kernel BUG at fs/btrfs/ordered-data.c:983!
Oops: invalid opcode: 0000 [#1] PREEMPT SMP PTI
CPU: 9 PID: 5072 Comm: worker Tainted: G U OE 6.10.5-1-default #1 openSUSE Tumbleweed 69f48d427608e1c09e60ea24c6c55e2ca1b049e8
Hardware name: Acer Predator PH315-52/Covini_CFS, BIOS V1.12 07/28/2020
RIP: 0010:btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs]
Code: 50 d6 86 c0 e8 (...)
RSP: 0018:ffff9e4a03dcfc78 EFLAGS: 00010246
RAX: 0000000000000054 RBX: ffff9078a9868e98 RCX: 0000000000000000
RDX: 0000000000000000 RSI: ffff907dce4a7800 RDI: ffff907dce4a7800
RBP: ffff907805518800 R08: 0000000000000000 R09: ffff9e4a03dcfb38
R10: ffff9e4a03dcfb30 R11: 0000000000000003 R12: ffff907684ae7800
R13: 0000000000000001 R14: ffff90774646b600 R15: 0000000000000000
FS: 00007f04b96006c0(0000) GS:ffff907dce480000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f32acbfc000 CR3: 00000001fd4fa005 CR4: 00000000003726f0
Call Trace:
<TASK>
? __die_body.cold+0x14/0x24
? die+0x2e/0x50
? do_trap+0xca/0x110
? do_error_trap+0x6a/0x90
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? exc_invalid_op+0x50/0x70
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? asm_exc_invalid_op+0x1a/0x20
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
btrfs_sync_file+0x21a/0x4d0 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? __seccomp_filter+0x31d/0x4f0
__x64_sys_fdatasync+0x4f/0x90
do_syscall_64+0x82/0x160
? do_futex+0xcb/0x190
? __x64_sys_futex+0x10e/0x1d0
? switch_fpu_return+0x4f/0xd0
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
entry_SYSCALL_64_after_hwframe+0x76/0x7e

Another problem here is if task B grabs the private pointer and then uses
it after task A has finished, since the private was allocated in the stack
of task A, it results in some invalid memory access with a hard to predict
result.

This issue, triggering the assertion, was observed with QEMU workloads by
two users in the Link tags below.

Fix this by not relying on a file's private to pass information to fsync
that it should skip locking the inode and instead pass this information
through a special value stored in current->journal_info. This is safe
because in the relevant section of the direct IO write path we are not
holding a transaction handle, so current->journal_info is NULL.

The following C program triggers the issue:

$ cat repro.c
/* Get the O_DIRECT definition. */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>

static int fd;

static ssize_t do_write(int fd, const void *buf, size_t count, off_t offset)
{
while (count > 0) {
ssize_t ret;

       ret = pwrite(fd, buf, count, offset);
       if (ret &lt; 0) {
           if (errno == EINTR)
               continue;
           return ret;
       }
       count -= ret;
       buf += ret;
   }
   return 0;

}

static void *fsync_loop(void *arg)
{
while (1) {
int ret;

       ret = fsync(fd);
       if (ret != 0) {
           perror(&#34;Fsync failed&#34;);
           exit(6);
       }
   }

}

int main(int argc, char *argv[])
{
long pagesize;
void *write_buf;
pthread_t fsyncer;
int ret;

   if (argc != 2) {
       fprintf(stderr, &#34;Use: %s &lt;file path&gt;\n&#34;, argv[0]);
       return 1;
   }

   fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC | O_DIRECT, 0666);
   if (fd == -1) {
       perror(&#34;Failed to open/create file&#34;);
       return 1;
   }

   pagesize = sysconf(_SC_PAGE_SIZE);
   if (pagesize == -1) {
       perror(&#34;Failed to get page size&#34;);
       return 2;
   }

   ret = posix_memalign(&#38;write_buf, pagesize, pagesize);
   if (ret) {
       perror(&#34;Failed to allocate buffer&#34;);
       return 3;
   }

   ret = pthread_create(&#38;fsyncer, NULL, fsync_loop, NULL);
   if (ret != 0) {
       fprintf(stderr, &#34;Failed to create writer thread: %d\n&#34;, ret);
       return 4;
   }

   while (1) {
       ret = do_write(fd, write_buf, pagesize, 0);
       if (ret != 0) {
           perror(&#34;Write failed&#34;);
           exit(5);
       }
   }

   return 0;

}

mkfs.btrfsf/dev/sdi mount /dev/sdi /mnt/sdi
$ timeout 10 ./repro /mnt/sdi/foo

Usually the race is triggered within less than 1 second. A test case for
fstests will follow soon.

The Linux kernel CVE team has assigned CVE-2024-46734 to this issue.

openEuler评分:(评分和向量)
3.9
AV:L/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:L

受影响版本排查(受影响/不受影响):
1.openEuler-20.03-LTS-SP4:不受影响
2.openEuler-22.03-LTS-SP1:不受影响
3.openEuler-22.03-LTS-SP3:不受影响
4.openEuler-22.03-LTS-SP4:不受影响
5.master(6.1.0):不受影响
6.openEuler-24.03-LTS:不受影响
7.openEuler-24.03-LTS-Next:不受影响

修复是否涉及abi变化(是/否):
1.openEuler-20.03-LTS-SP4:否
2.openEuler-22.03-LTS-SP1:否
3.openEuler-22.03-LTS-SP3:否
4.master(6.1.0):否
5.openEuler-24.03-LTS:否
6.openEuler-24.03-LTS-Next:否
7.openEuler-22.03-LTS-SP4:否

@ 经过 cve-manager 解析, 已分析的内容如下表所示:

状态 需分析 内容
已分析 1.影响性分析说明 In the Linux kernel, the following vulnerability has been resolved:btrfs: fix race between direct IO write and fsync when using same fdIf we have 2 threads that are using the same file descriptor and one ofthem is doing direct IO writes while the other is doing fsync, we have arace where we can end up either:1) Attempt a fsync without holding the inode's lock, triggering an assertion failures when assertions are enabled;2) Do an invalid memory access from the fsync task because the file private points to memory allocated on stack by the direct IO task and it may be used by the fsync task after the stack was destroyed.The race happens like this:1) A user space program opens a file descriptor with O_DIRECT;2) The program spawns 2 threads using libpthread for example;3) One of the threads uses the file descriptor to do direct IO writes, while the other calls fsync using the same file descriptor.4) Call task A the thread doing direct IO writes and task B the thread doing fsyncs;5) Task A does a direct IO write, and at btrfs_direct_write() sets the file's private to an on stack allocated private with the member 'fsync_skip_inode_lock' set to true;6) Task B enters btrfs_sync_file() and sees that there's a private structure associated to the file which has 'fsync_skip_inode_lock' set to true, so it skips locking the inode's VFS lock;7) Task A completes the direct IO write, and resets the file's private to NULL since it had no prior private and our private was stack allocated. Then it unlocks the inode's VFS lock;8) Task B enters btrfs_get_ordered_extents_for_logging(), then the assertion that checks the inode's VFS lock is held fails, since task B never locked it and task A has already unlocked it.The stack trace produced is the following: assertion failed: inode_is_locked(&inode->vfs_inode), in fs/btrfs/ordered-data.c:983 ------------[ cut here ]------------ kernel BUG at fs/btrfs/ordered-data.c:983! Oops: invalid opcode: 0000 [#1] PREEMPT SMP PTI CPU: 9 PID: 5072 Comm: worker Tainted: G U OE 6.10.5-1-default #1 openSUSE Tumbleweed 69f48d427608e1c09e60ea24c6c55e2ca1b049e8 Hardware name: Acer Predator PH315-52/Covini_CFS, BIOS V1.12 07/28/2020 RIP: 0010:btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs] Code: 50 d6 86 c0 e8 (...) RSP: 0018:ffff9e4a03dcfc78 EFLAGS: 00010246 RAX: 0000000000000054 RBX: ffff9078a9868e98 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff907dce4a7800 RDI: ffff907dce4a7800 RBP: ffff907805518800 R08: 0000000000000000 R09: ffff9e4a03dcfb38 R10: ffff9e4a03dcfb30 R11: 0000000000000003 R12: ffff907684ae7800 R13: 0000000000000001 R14: ffff90774646b600 R15: 0000000000000000 FS: 00007f04b96006c0(0000) GS:ffff907dce480000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f32acbfc000 CR3: 00000001fd4fa005 CR4: 00000000003726f0 Call Trace: <TASK> ? __die_body.cold+0x14/0x24 ? die+0x2e/0x50 ? do_trap+0xca/0x110 ? do_error_trap+0x6a/0x90 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? exc_invalid_op+0x50/0x70 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? asm_exc_invalid_op+0x1a/0x20 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] btrfs_sync_file+0x21a/0x4d0 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? __seccomp_filter+0x31d/0x4f0 __x64_sys_fdatasync+0x4f/0x90 do_syscall_64+0x82/0x160 ? do_futex+0xcb/0x190 ? __x64_sys_futex+0x10e/0x1d0 ? switch_fpu_return+0x4f/0xd0 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 entry_SYSCALL_64_after_hwframe+0x76/0x7eAnother problem here is if task B grabs the private pointer and then usesit after task A has finished, since the private was allocated in the stackof task A, it results in some invalid memory access with a hard to predictresult.This issue, triggering the assertion, was observed with QEMU workloads bytwo users in the Link tags below.Fix this by not relying on a file's private to pass information to fsyncthat it should skip locking the inode and instead pass this informationthrough a special value stored in current->journal_info. This is safebecause in the relevant section of the direct IO write path we are notholding a transaction handle, so current->journal_info is NULL.The following C program triggers the issue: $ cat repro.c /* Get the O_DIRECT definition. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stdint.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <pthread.h> static int fd; static ssize_t do_write(int fd, const void *buf, size_t count, off_t offset) { while (count > 0) { ssize_t ret; ret = pwrite(fd, buf, count, offset); if (ret < 0) { if (errno == EINTR) continue; return ret; } count -= ret; buf += ret; } return 0; } static void *fsync_loop(void *arg) { while (1) { int ret; ret = fsync(fd); if (ret != 0) { perror("Fsync failed"); exit(6); } } } int main(int argc, char *argv[]) { long pagesize; void *write_buf; pthread_t fsyncer; int ret; if (argc != 2) { fprintf(stderr, "Use: %s <file path>\n", argv[0]); return 1; } fd = open(argv[1], O_WRONLY
已分析 2.openEulerScore 3.9
已分析 3.openEulerVector AV:L/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:L
已分析 4.受影响版本排查 openEuler-20.03-LTS-SP4:不受影响,openEuler-22.03-LTS-SP1:不受影响,openEuler-22.03-LTS-SP3:不受影响,openEuler-22.03-LTS-SP4:不受影响,master:不受影响,openEuler-24.03-LTS:不受影响,openEuler-24.03-LTS-Next:不受影响
已分析 5.修复是否涉及abi变化 openEuler-20.03-LTS-SP4:否,openEuler-22.03-LTS-SP1:否,openEuler-22.03-LTS-SP3:否,master:否,openEuler-24.03-LTS:否,openEuler-24.03-LTS-Next:否,openEuler-22.03-LTS-SP4:否

请确认分析内容的准确性, 确认无误后, 您可以进行后续步骤, 否则您可以继续分析.

openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前

CVE-2024-46734

影响性分析说明:
In the Linux kernel, the following vulnerability has been resolved:

btrfs: fix race between direct IO write and fsync when using same fd

If we have 2 threads that are using the same file descriptor and one of
them is doing direct IO writes while the other is doing fsync, we have a
race where we can end up either:

  1. Attempt a fsync without holding the inode's lock, triggering an
    assertion failures when assertions are enabled;

  2. Do an invalid memory access from the fsync task because the file private
    points to memory allocated on stack by the direct IO task and it may be
    used by the fsync task after the stack was destroyed.

The race happens like this:

  1. A user space program opens a file descriptor with O_DIRECT;

  2. The program spawns 2 threads using libpthread for example;

  3. One of the threads uses the file descriptor to do direct IO writes,
    while the other calls fsync using the same file descriptor.

  4. Call task A the thread doing direct IO writes and task B the thread
    doing fsyncs;

  5. Task A does a direct IO write, and at btrfs_direct_write() sets the
    file's private to an on stack allocated private with the member
    'fsync_skip_inode_lock' set to true;

  6. Task B enters btrfs_sync_file() and sees that there's a private
    structure associated to the file which has 'fsync_skip_inode_lock' set
    to true, so it skips locking the inode's VFS lock;

  7. Task A completes the direct IO write, and resets the file's private to
    NULL since it had no prior private and our private was stack allocated.
    Then it unlocks the inode's VFS lock;

  8. Task B enters btrfs_get_ordered_extents_for_logging(), then the
    assertion that checks the inode's VFS lock is held fails, since task B
    never locked it and task A has already unlocked it.

The stack trace produced is the following:

assertion failed: inode_is_locked(&inode->vfs_inode), in fs/btrfs/ordered-data.c:983
------------[ cut here ]------------
kernel BUG at fs/btrfs/ordered-data.c:983!
Oops: invalid opcode: 0000 [#1] PREEMPT SMP PTI
CPU: 9 PID: 5072 Comm: worker Tainted: G U OE 6.10.5-1-default #1 openSUSE Tumbleweed 69f48d427608e1c09e60ea24c6c55e2ca1b049e8
Hardware name: Acer Predator PH315-52/Covini_CFS, BIOS V1.12 07/28/2020
RIP: 0010:btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs]
Code: 50 d6 86 c0 e8 (...)
RSP: 0018:ffff9e4a03dcfc78 EFLAGS: 00010246
RAX: 0000000000000054 RBX: ffff9078a9868e98 RCX: 0000000000000000
RDX: 0000000000000000 RSI: ffff907dce4a7800 RDI: ffff907dce4a7800
RBP: ffff907805518800 R08: 0000000000000000 R09: ffff9e4a03dcfb38
R10: ffff9e4a03dcfb30 R11: 0000000000000003 R12: ffff907684ae7800
R13: 0000000000000001 R14: ffff90774646b600 R15: 0000000000000000
FS: 00007f04b96006c0(0000) GS:ffff907dce480000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f32acbfc000 CR3: 00000001fd4fa005 CR4: 00000000003726f0
Call Trace:
<TASK>
? __die_body.cold+0x14/0x24
? die+0x2e/0x50
? do_trap+0xca/0x110
? do_error_trap+0x6a/0x90
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? exc_invalid_op+0x50/0x70
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? asm_exc_invalid_op+0x1a/0x20
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
btrfs_sync_file+0x21a/0x4d0 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? __seccomp_filter+0x31d/0x4f0
__x64_sys_fdatasync+0x4f/0x90
do_syscall_64+0x82/0x160
? do_futex+0xcb/0x190
? __x64_sys_futex+0x10e/0x1d0
? switch_fpu_return+0x4f/0xd0
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
entry_SYSCALL_64_after_hwframe+0x76/0x7e

Another problem here is if task B grabs the private pointer and then uses
it after task A has finished, since the private was allocated in the stack
of task A, it results in some invalid memory access with a hard to predict
result.

This issue, triggering the assertion, was observed with QEMU workloads by
two users in the Link tags below.

Fix this by not relying on a file's private to pass information to fsync
that it should skip locking the inode and instead pass this information
through a special value stored in current->journal_info. This is safe
because in the relevant section of the direct IO write path we are not
holding a transaction handle, so current->journal_info is NULL.

The following C program triggers the issue:

$ cat repro.c
/* Get the O_DIRECT definition. */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>

static int fd;

static ssize_t do_write(int fd, const void *buf, size_t count, off_t offset)
{
while (count > 0) {
ssize_t ret;

       ret = pwrite(fd, buf, count, offset);
       if (ret &lt; 0) {
           if (errno == EINTR)
               continue;
           return ret;
       }
       count -= ret;
       buf += ret;
   }
   return 0;

}

static void *fsync_loop(void *arg)
{
while (1) {
int ret;

       ret = fsync(fd);
       if (ret != 0) {
           perror(&#34;Fsync failed&#34;);
           exit(6);
       }
   }

}

int main(int argc, char *argv[])
{
long pagesize;
void *write_buf;
pthread_t fsyncer;
int ret;

   if (argc != 2) {
       fprintf(stderr, &#34;Use: %s &lt;file path&gt;\n&#34;, argv[0]);
       return 1;
   }

   fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC | O_DIRECT, 0666);
   if (fd == -1) {
       perror(&#34;Failed to open/create file&#34;);
       return 1;
   }

   pagesize = sysconf(_SC_PAGE_SIZE);
   if (pagesize == -1) {
       perror(&#34;Failed to get page size&#34;);
       return 2;
   }

   ret = posix_memalign(&#38;write_buf, pagesize, pagesize);
   if (ret) {
       perror(&#34;Failed to allocate buffer&#34;);
       return 3;
   }

   ret = pthread_create(&#38;fsyncer, NULL, fsync_loop, NULL);
   if (ret != 0) {
       fprintf(stderr, &#34;Failed to create writer thread: %d\n&#34;, ret);
       return 4;
   }

   while (1) {
       ret = do_write(fd, write_buf, pagesize, 0);
       if (ret != 0) {
           perror(&#34;Write failed&#34;);
           exit(5);
       }
   }

   return 0;

}

mkfs.btrfsf/dev/sdi mount /dev/sdi /mnt/sdi
$ timeout 10 ./repro /mnt/sdi/foo

Usually the race is triggered within less than 1 second. A test case for
fstests will follow soon.

The Linux kernel CVE team has assigned CVE-2024-46734 to this issue.

openEuler评分:(评分和向量)
3.9
AV:L/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:L

受影响版本排查(受影响/不受影响):
1.openEuler-20.03-LTS-SP4:不受影响
2.openEuler-22.03-LTS-SP1:不受影响
3.openEuler-22.03-LTS-SP3:不受影响
4.openEuler-22.03-LTS-SP4:不受影响
5.master(6.1.0):不受影响
6.openEuler-24.03-LTS:受影响
7.openEuler-24.03-LTS-Next:不受影响

修复是否涉及abi变化(是/否):
1.openEuler-20.03-LTS-SP4:否
2.openEuler-22.03-LTS-SP1:否
3.openEuler-22.03-LTS-SP3:否
4.master(6.1.0):否
5.openEuler-24.03-LTS:否
6.openEuler-24.03-LTS-Next:否
7.openEuler-22.03-LTS-SP4:否

openeuler-ci-bot 修改了描述 7个月前

@ 经过 cve-manager 解析, 已分析的内容如下表所示:

状态 需分析 内容
已分析 1.影响性分析说明 In the Linux kernel, the following vulnerability has been resolved:btrfs: fix race between direct IO write and fsync when using same fdIf we have 2 threads that are using the same file descriptor and one ofthem is doing direct IO writes while the other is doing fsync, we have arace where we can end up either:1) Attempt a fsync without holding the inode's lock, triggering an assertion failures when assertions are enabled;2) Do an invalid memory access from the fsync task because the file private points to memory allocated on stack by the direct IO task and it may be used by the fsync task after the stack was destroyed.The race happens like this:1) A user space program opens a file descriptor with O_DIRECT;2) The program spawns 2 threads using libpthread for example;3) One of the threads uses the file descriptor to do direct IO writes, while the other calls fsync using the same file descriptor.4) Call task A the thread doing direct IO writes and task B the thread doing fsyncs;5) Task A does a direct IO write, and at btrfs_direct_write() sets the file's private to an on stack allocated private with the member 'fsync_skip_inode_lock' set to true;6) Task B enters btrfs_sync_file() and sees that there's a private structure associated to the file which has 'fsync_skip_inode_lock' set to true, so it skips locking the inode's VFS lock;7) Task A completes the direct IO write, and resets the file's private to NULL since it had no prior private and our private was stack allocated. Then it unlocks the inode's VFS lock;8) Task B enters btrfs_get_ordered_extents_for_logging(), then the assertion that checks the inode's VFS lock is held fails, since task B never locked it and task A has already unlocked it.The stack trace produced is the following: assertion failed: inode_is_locked(&inode->vfs_inode), in fs/btrfs/ordered-data.c:983 ------------[ cut here ]------------ kernel BUG at fs/btrfs/ordered-data.c:983! Oops: invalid opcode: 0000 [#1] PREEMPT SMP PTI CPU: 9 PID: 5072 Comm: worker Tainted: G U OE 6.10.5-1-default #1 openSUSE Tumbleweed 69f48d427608e1c09e60ea24c6c55e2ca1b049e8 Hardware name: Acer Predator PH315-52/Covini_CFS, BIOS V1.12 07/28/2020 RIP: 0010:btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs] Code: 50 d6 86 c0 e8 (...) RSP: 0018:ffff9e4a03dcfc78 EFLAGS: 00010246 RAX: 0000000000000054 RBX: ffff9078a9868e98 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff907dce4a7800 RDI: ffff907dce4a7800 RBP: ffff907805518800 R08: 0000000000000000 R09: ffff9e4a03dcfb38 R10: ffff9e4a03dcfb30 R11: 0000000000000003 R12: ffff907684ae7800 R13: 0000000000000001 R14: ffff90774646b600 R15: 0000000000000000 FS: 00007f04b96006c0(0000) GS:ffff907dce480000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f32acbfc000 CR3: 00000001fd4fa005 CR4: 00000000003726f0 Call Trace: <TASK> ? __die_body.cold+0x14/0x24 ? die+0x2e/0x50 ? do_trap+0xca/0x110 ? do_error_trap+0x6a/0x90 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? exc_invalid_op+0x50/0x70 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? asm_exc_invalid_op+0x1a/0x20 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] btrfs_sync_file+0x21a/0x4d0 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? __seccomp_filter+0x31d/0x4f0 __x64_sys_fdatasync+0x4f/0x90 do_syscall_64+0x82/0x160 ? do_futex+0xcb/0x190 ? __x64_sys_futex+0x10e/0x1d0 ? switch_fpu_return+0x4f/0xd0 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 entry_SYSCALL_64_after_hwframe+0x76/0x7eAnother problem here is if task B grabs the private pointer and then usesit after task A has finished, since the private was allocated in the stackof task A, it results in some invalid memory access with a hard to predictresult.This issue, triggering the assertion, was observed with QEMU workloads bytwo users in the Link tags below.Fix this by not relying on a file's private to pass information to fsyncthat it should skip locking the inode and instead pass this informationthrough a special value stored in current->journal_info. This is safebecause in the relevant section of the direct IO write path we are notholding a transaction handle, so current->journal_info is NULL.The following C program triggers the issue: $ cat repro.c /* Get the O_DIRECT definition. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stdint.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <pthread.h> static int fd; static ssize_t do_write(int fd, const void *buf, size_t count, off_t offset) { while (count > 0) { ssize_t ret; ret = pwrite(fd, buf, count, offset); if (ret < 0) { if (errno == EINTR) continue; return ret; } count -= ret; buf += ret; } return 0; } static void *fsync_loop(void *arg) { while (1) { int ret; ret = fsync(fd); if (ret != 0) { perror("Fsync failed"); exit(6); } } } int main(int argc, char *argv[]) { long pagesize; void *write_buf; pthread_t fsyncer; int ret; if (argc != 2) { fprintf(stderr, "Use: %s <file path>\n", argv[0]); return 1; } fd = open(argv[1], O_WRONLY
已分析 2.openEulerScore 3.9
已分析 3.openEulerVector AV:L/AC:H/PR:H/UI:N/S:U/C:L/I:L/A:L
已分析 4.受影响版本排查 openEuler-24.03-LTS:受影响,openEuler-20.03-LTS-SP4:不受影响,openEuler-22.03-LTS-SP1:不受影响,openEuler-22.03-LTS-SP3:不受影响,openEuler-22.03-LTS-SP4:不受影响,master:不受影响,openEuler-24.03-LTS-Next:不受影响
已分析 5.修复是否涉及abi变化 openEuler-20.03-LTS-SP4:否,openEuler-22.03-LTS-SP1:否,openEuler-22.03-LTS-SP3:否,master:否,openEuler-24.03-LTS:否,openEuler-24.03-LTS-Next:否,openEuler-22.03-LTS-SP4:否

请确认分析内容的准确性, 确认无误后, 您可以进行后续步骤, 否则您可以继续分析.

openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
ci-robot 通过合并 Pull Request !11919: btrfs: fix race between direct IO write and fsync when using same fd任务状态待办的 修改为已完成 7个月前
openeuler-ci-bot 任务状态已完成 修改为待办的 7个月前

@gatieme ,@xiexiuqi ,@yangyingliang ,@pi3orama ,@jiaoff ,@ci-robot
关闭issue前,需要将受影响的分支在合并pr时关联上当前issue编号: #IARY1Z
受影响分支: openEuler-24.03-LTS
具体操作参考: https://gitee.com/help/articles/4142

openeuler-ci-bot 移除了
 
CVE/UNFIXED
标签
7个月前
openeuler-ci-bot 移除了
 
sig/Kernel
标签
7个月前
openeuler-ci-bot 添加了
 
CVE/UNFIXED
标签
7个月前
openeuler-ci-bot 添加了
 
sig/Kernel
标签
7个月前

CVE-2024-46734

影响性分析说明:
In the Linux kernel, the following vulnerability has been resolved:

btrfs: fix race between direct IO write and fsync when using same fd

If we have 2 threads that are using the same file descriptor and one of
them is doing direct IO writes while the other is doing fsync, we have a
race where we can end up either:

  1. Attempt a fsync without holding the inode's lock, triggering an
    assertion failures when assertions are enabled;

  2. Do an invalid memory access from the fsync task because the file private
    points to memory allocated on stack by the direct IO task and it may be
    used by the fsync task after the stack was destroyed.

The race happens like this:

  1. A user space program opens a file descriptor with O_DIRECT;

  2. The program spawns 2 threads using libpthread for example;

  3. One of the threads uses the file descriptor to do direct IO writes,
    while the other calls fsync using the same file descriptor.

  4. Call task A the thread doing direct IO writes and task B the thread
    doing fsyncs;

  5. Task A does a direct IO write, and at btrfs_direct_write() sets the
    file's private to an on stack allocated private with the member
    'fsync_skip_inode_lock' set to true;

  6. Task B enters btrfs_sync_file() and sees that there's a private
    structure associated to the file which has 'fsync_skip_inode_lock' set
    to true, so it skips locking the inode's VFS lock;

  7. Task A completes the direct IO write, and resets the file's private to
    NULL since it had no prior private and our private was stack allocated.
    Then it unlocks the inode's VFS lock;

  8. Task B enters btrfs_get_ordered_extents_for_logging(), then the
    assertion that checks the inode's VFS lock is held fails, since task B
    never locked it and task A has already unlocked it.

The stack trace produced is the following:

assertion failed: inode_is_locked(&inode->vfs_inode), in fs/btrfs/ordered-data.c:983
------------[ cut here ]------------
kernel BUG at fs/btrfs/ordered-data.c:983!
Oops: invalid opcode: 0000 [#1] PREEMPT SMP PTI
CPU: 9 PID: 5072 Comm: worker Tainted: G U OE 6.10.5-1-default #1 openSUSE Tumbleweed 69f48d427608e1c09e60ea24c6c55e2ca1b049e8
Hardware name: Acer Predator PH315-52/Covini_CFS, BIOS V1.12 07/28/2020
RIP: 0010:btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs]
Code: 50 d6 86 c0 e8 (...)
RSP: 0018:ffff9e4a03dcfc78 EFLAGS: 00010246
RAX: 0000000000000054 RBX: ffff9078a9868e98 RCX: 0000000000000000
RDX: 0000000000000000 RSI: ffff907dce4a7800 RDI: ffff907dce4a7800
RBP: ffff907805518800 R08: 0000000000000000 R09: ffff9e4a03dcfb38
R10: ffff9e4a03dcfb30 R11: 0000000000000003 R12: ffff907684ae7800
R13: 0000000000000001 R14: ffff90774646b600 R15: 0000000000000000
FS: 00007f04b96006c0(0000) GS:ffff907dce480000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f32acbfc000 CR3: 00000001fd4fa005 CR4: 00000000003726f0
Call Trace:
<TASK>
? __die_body.cold+0x14/0x24
? die+0x2e/0x50
? do_trap+0xca/0x110
? do_error_trap+0x6a/0x90
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? exc_invalid_op+0x50/0x70
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? asm_exc_invalid_op+0x1a/0x20
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
btrfs_sync_file+0x21a/0x4d0 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? __seccomp_filter+0x31d/0x4f0
__x64_sys_fdatasync+0x4f/0x90
do_syscall_64+0x82/0x160
? do_futex+0xcb/0x190
? __x64_sys_futex+0x10e/0x1d0
? switch_fpu_return+0x4f/0xd0
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
entry_SYSCALL_64_after_hwframe+0x76/0x7e

Another problem here is if task B grabs the private pointer and then uses
it after task A has finished, since the private was allocated in the stack
of task A, it results in some invalid memory access with a hard to predict
result.

This issue, triggering the assertion, was observed with QEMU workloads by
two users in the Link tags below.

Fix this by not relying on a file's private to pass information to fsync
that it should skip locking the inode and instead pass this information
through a special value stored in current->journal_info. This is safe
because in the relevant section of the direct IO write path we are not
holding a transaction handle, so current->journal_info is NULL.

The following C program triggers the issue:

$ cat repro.c
/* Get the O_DIRECT definition. */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>

static int fd;

static ssize_t do_write(int fd, const void *buf, size_t count, off_t offset)
{
while (count > 0) {
ssize_t ret;

       ret = pwrite(fd, buf, count, offset);
       if (ret &lt; 0) {
           if (errno == EINTR)
               continue;
           return ret;
       }
       count -= ret;
       buf += ret;
   }
   return 0;

}

static void *fsync_loop(void *arg)
{
while (1) {
int ret;

       ret = fsync(fd);
       if (ret != 0) {
           perror(&#34;Fsync failed&#34;);
           exit(6);
       }
   }

}

int main(int argc, char *argv[])
{
long pagesize;
void *write_buf;
pthread_t fsyncer;
int ret;

   if (argc != 2) {
       fprintf(stderr, &#34;Use: %s &lt;file path&gt;\n&#34;, argv[0]);
       return 1;
   }

   fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC | O_DIRECT, 0666);
   if (fd == -1) {
       perror(&#34;Failed to open/create file&#34;);
       return 1;
   }

   pagesize = sysconf(_SC_PAGE_SIZE);
   if (pagesize == -1) {
       perror(&#34;Failed to get page size&#34;);
       return 2;
   }

   ret = posix_memalign(&#38;write_buf, pagesize, pagesize);
   if (ret) {
       perror(&#34;Failed to allocate buffer&#34;);
       return 3;
   }

   ret = pthread_create(&#38;fsyncer, NULL, fsync_loop, NULL);
   if (ret != 0) {
       fprintf(stderr, &#34;Failed to create writer thread: %d\n&#34;, ret);
       return 4;
   }

   while (1) {
       ret = do_write(fd, write_buf, pagesize, 0);
       if (ret != 0) {
           perror(&#34;Write failed&#34;);
           exit(5);
       }
   }

   return 0;

}

mkfs.btrfsf/dev/sdi mount /dev/sdi /mnt/sdi
$ timeout 10 ./repro /mnt/sdi/foo

Usually the race is triggered within less than 1 second. A test case for
fstests will follow soon.

The Linux kernel CVE team has assigned CVE-2024-46734 to this issue.

openEuler评分:(评分和向量)
5.5
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

受影响版本排查(受影响/不受影响):
1.openEuler-20.03-LTS-SP4:不受影响
2.openEuler-22.03-LTS-SP1:不受影响
3.openEuler-22.03-LTS-SP3:不受影响
4.openEuler-22.03-LTS-SP4:不受影响
5.master(6.1.0):不受影响
6.openEuler-24.03-LTS:受影响
7.openEuler-24.03-LTS-Next:不受影响

修复是否涉及abi变化(是/否):
1.openEuler-20.03-LTS-SP4:否
2.openEuler-22.03-LTS-SP1:否
3.openEuler-22.03-LTS-SP3:否
4.master(6.1.0):否
5.openEuler-24.03-LTS:否
6.openEuler-24.03-LTS-Next:否
7.openEuler-22.03-LTS-SP4:否

@ 经过 cve-manager 解析, 已分析的内容如下表所示:

状态 需分析 内容
已分析 1.影响性分析说明 In the Linux kernel, the following vulnerability has been resolved:btrfs: fix race between direct IO write and fsync when using same fdIf we have 2 threads that are using the same file descriptor and one ofthem is doing direct IO writes while the other is doing fsync, we have arace where we can end up either:1) Attempt a fsync without holding the inode's lock, triggering an assertion failures when assertions are enabled;2) Do an invalid memory access from the fsync task because the file private points to memory allocated on stack by the direct IO task and it may be used by the fsync task after the stack was destroyed.The race happens like this:1) A user space program opens a file descriptor with O_DIRECT;2) The program spawns 2 threads using libpthread for example;3) One of the threads uses the file descriptor to do direct IO writes, while the other calls fsync using the same file descriptor.4) Call task A the thread doing direct IO writes and task B the thread doing fsyncs;5) Task A does a direct IO write, and at btrfs_direct_write() sets the file's private to an on stack allocated private with the member 'fsync_skip_inode_lock' set to true;6) Task B enters btrfs_sync_file() and sees that there's a private structure associated to the file which has 'fsync_skip_inode_lock' set to true, so it skips locking the inode's VFS lock;7) Task A completes the direct IO write, and resets the file's private to NULL since it had no prior private and our private was stack allocated. Then it unlocks the inode's VFS lock;8) Task B enters btrfs_get_ordered_extents_for_logging(), then the assertion that checks the inode's VFS lock is held fails, since task B never locked it and task A has already unlocked it.The stack trace produced is the following: assertion failed: inode_is_locked(&inode->vfs_inode), in fs/btrfs/ordered-data.c:983 ------------[ cut here ]------------ kernel BUG at fs/btrfs/ordered-data.c:983! Oops: invalid opcode: 0000 [#1] PREEMPT SMP PTI CPU: 9 PID: 5072 Comm: worker Tainted: G U OE 6.10.5-1-default #1 openSUSE Tumbleweed 69f48d427608e1c09e60ea24c6c55e2ca1b049e8 Hardware name: Acer Predator PH315-52/Covini_CFS, BIOS V1.12 07/28/2020 RIP: 0010:btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs] Code: 50 d6 86 c0 e8 (...) RSP: 0018:ffff9e4a03dcfc78 EFLAGS: 00010246 RAX: 0000000000000054 RBX: ffff9078a9868e98 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff907dce4a7800 RDI: ffff907dce4a7800 RBP: ffff907805518800 R08: 0000000000000000 R09: ffff9e4a03dcfb38 R10: ffff9e4a03dcfb30 R11: 0000000000000003 R12: ffff907684ae7800 R13: 0000000000000001 R14: ffff90774646b600 R15: 0000000000000000 FS: 00007f04b96006c0(0000) GS:ffff907dce480000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f32acbfc000 CR3: 00000001fd4fa005 CR4: 00000000003726f0 Call Trace: <TASK> ? __die_body.cold+0x14/0x24 ? die+0x2e/0x50 ? do_trap+0xca/0x110 ? do_error_trap+0x6a/0x90 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? exc_invalid_op+0x50/0x70 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? asm_exc_invalid_op+0x1a/0x20 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] btrfs_sync_file+0x21a/0x4d0 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? __seccomp_filter+0x31d/0x4f0 __x64_sys_fdatasync+0x4f/0x90 do_syscall_64+0x82/0x160 ? do_futex+0xcb/0x190 ? __x64_sys_futex+0x10e/0x1d0 ? switch_fpu_return+0x4f/0xd0 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 entry_SYSCALL_64_after_hwframe+0x76/0x7eAnother problem here is if task B grabs the private pointer and then usesit after task A has finished, since the private was allocated in the stackof task A, it results in some invalid memory access with a hard to predictresult.This issue, triggering the assertion, was observed with QEMU workloads bytwo users in the Link tags below.Fix this by not relying on a file's private to pass information to fsyncthat it should skip locking the inode and instead pass this informationthrough a special value stored in current->journal_info. This is safebecause in the relevant section of the direct IO write path we are notholding a transaction handle, so current->journal_info is NULL.The following C program triggers the issue: $ cat repro.c /* Get the O_DIRECT definition. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stdint.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <pthread.h> static int fd; static ssize_t do_write(int fd, const void *buf, size_t count, off_t offset) { while (count > 0) { ssize_t ret; ret = pwrite(fd, buf, count, offset); if (ret < 0) { if (errno == EINTR) continue; return ret; } count -= ret; buf += ret; } return 0; } static void *fsync_loop(void *arg) { while (1) { int ret; ret = fsync(fd); if (ret != 0) { perror("Fsync failed"); exit(6); } } } int main(int argc, char *argv[]) { long pagesize; void *write_buf; pthread_t fsyncer; int ret; if (argc != 2) { fprintf(stderr, "Use: %s <file path>\n", argv[0]); return 1; } fd = open(argv[1], O_WRONLY
已分析 2.openEulerScore 5.5
已分析 3.openEulerVector AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
已分析 4.受影响版本排查 openEuler-24.03-LTS:受影响,openEuler-20.03-LTS-SP4:不受影响,openEuler-22.03-LTS-SP1:不受影响,openEuler-22.03-LTS-SP3:不受影响,openEuler-22.03-LTS-SP4:不受影响,master:不受影响,openEuler-24.03-LTS-Next:不受影响
已分析 5.修复是否涉及abi变化 openEuler-20.03-LTS-SP4:否,openEuler-22.03-LTS-SP1:否,openEuler-22.03-LTS-SP3:否,master:否,openEuler-24.03-LTS:否,openEuler-24.03-LTS-Next:否,openEuler-22.03-LTS-SP4:否

请确认分析内容的准确性, 确认无误后, 您可以进行后续步骤, 否则您可以继续分析.

openeuler-ci-bot 修改了描述 7个月前

CVE-2024-46734

影响性分析说明:
In the Linux kernel, the following vulnerability has been resolved:

btrfs: fix race between direct IO write and fsync when using same fd

If we have 2 threads that are using the same file descriptor and one of
them is doing direct IO writes while the other is doing fsync, we have a
race where we can end up either:

  1. Attempt a fsync without holding the inode's lock, triggering an
    assertion failures when assertions are enabled;

  2. Do an invalid memory access from the fsync task because the file private
    points to memory allocated on stack by the direct IO task and it may be
    used by the fsync task after the stack was destroyed.

The race happens like this:

  1. A user space program opens a file descriptor with O_DIRECT;

  2. The program spawns 2 threads using libpthread for example;

  3. One of the threads uses the file descriptor to do direct IO writes,
    while the other calls fsync using the same file descriptor.

  4. Call task A the thread doing direct IO writes and task B the thread
    doing fsyncs;

  5. Task A does a direct IO write, and at btrfs_direct_write() sets the
    file's private to an on stack allocated private with the member
    'fsync_skip_inode_lock' set to true;

  6. Task B enters btrfs_sync_file() and sees that there's a private
    structure associated to the file which has 'fsync_skip_inode_lock' set
    to true, so it skips locking the inode's VFS lock;

  7. Task A completes the direct IO write, and resets the file's private to
    NULL since it had no prior private and our private was stack allocated.
    Then it unlocks the inode's VFS lock;

  8. Task B enters btrfs_get_ordered_extents_for_logging(), then the
    assertion that checks the inode's VFS lock is held fails, since task B
    never locked it and task A has already unlocked it.

The stack trace produced is the following:

assertion failed: inode_is_locked(&inode->vfs_inode), in fs/btrfs/ordered-data.c:983
------------[ cut here ]------------
kernel BUG at fs/btrfs/ordered-data.c:983!
Oops: invalid opcode: 0000 [#1] PREEMPT SMP PTI
CPU: 9 PID: 5072 Comm: worker Tainted: G U OE 6.10.5-1-default #1 openSUSE Tumbleweed 69f48d427608e1c09e60ea24c6c55e2ca1b049e8
Hardware name: Acer Predator PH315-52/Covini_CFS, BIOS V1.12 07/28/2020
RIP: 0010:btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs]
Code: 50 d6 86 c0 e8 (...)
RSP: 0018:ffff9e4a03dcfc78 EFLAGS: 00010246
RAX: 0000000000000054 RBX: ffff9078a9868e98 RCX: 0000000000000000
RDX: 0000000000000000 RSI: ffff907dce4a7800 RDI: ffff907dce4a7800
RBP: ffff907805518800 R08: 0000000000000000 R09: ffff9e4a03dcfb38
R10: ffff9e4a03dcfb30 R11: 0000000000000003 R12: ffff907684ae7800
R13: 0000000000000001 R14: ffff90774646b600 R15: 0000000000000000
FS: 00007f04b96006c0(0000) GS:ffff907dce480000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f32acbfc000 CR3: 00000001fd4fa005 CR4: 00000000003726f0
Call Trace:
<TASK>
? __die_body.cold+0x14/0x24
? die+0x2e/0x50
? do_trap+0xca/0x110
? do_error_trap+0x6a/0x90
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? exc_invalid_op+0x50/0x70
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? asm_exc_invalid_op+0x1a/0x20
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
btrfs_sync_file+0x21a/0x4d0 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a]
? __seccomp_filter+0x31d/0x4f0
__x64_sys_fdatasync+0x4f/0x90
do_syscall_64+0x82/0x160
? do_futex+0xcb/0x190
? __x64_sys_futex+0x10e/0x1d0
? switch_fpu_return+0x4f/0xd0
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
? syscall_exit_to_user_mode+0x72/0x220
? do_syscall_64+0x8e/0x160
entry_SYSCALL_64_after_hwframe+0x76/0x7e

Another problem here is if task B grabs the private pointer and then uses
it after task A has finished, since the private was allocated in the stack
of task A, it results in some invalid memory access with a hard to predict
result.

This issue, triggering the assertion, was observed with QEMU workloads by
two users in the Link tags below.

Fix this by not relying on a file's private to pass information to fsync
that it should skip locking the inode and instead pass this information
through a special value stored in current->journal_info. This is safe
because in the relevant section of the direct IO write path we are not
holding a transaction handle, so current->journal_info is NULL.

The following C program triggers the issue:

$ cat repro.c
/* Get the O_DIRECT definition. */
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>

static int fd;

static ssize_t do_write(int fd, const void *buf, size_t count, off_t offset)
{
while (count > 0) {
ssize_t ret;

       ret = pwrite(fd, buf, count, offset);
       if (ret &lt; 0) {
           if (errno == EINTR)
               continue;
           return ret;
       }
       count -= ret;
       buf += ret;
   }
   return 0;

}

static void *fsync_loop(void *arg)
{
while (1) {
int ret;

       ret = fsync(fd);
       if (ret != 0) {
           perror(&#34;Fsync failed&#34;);
           exit(6);
       }
   }

}

int main(int argc, char *argv[])
{
long pagesize;
void *write_buf;
pthread_t fsyncer;
int ret;

   if (argc != 2) {
       fprintf(stderr, &#34;Use: %s &lt;file path&gt;\n&#34;, argv[0]);
       return 1;
   }

   fd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC | O_DIRECT, 0666);
   if (fd == -1) {
       perror(&#34;Failed to open/create file&#34;);
       return 1;
   }

   pagesize = sysconf(_SC_PAGE_SIZE);
   if (pagesize == -1) {
       perror(&#34;Failed to get page size&#34;);
       return 2;
   }

   ret = posix_memalign(&#38;write_buf, pagesize, pagesize);
   if (ret) {
       perror(&#34;Failed to allocate buffer&#34;);
       return 3;
   }

   ret = pthread_create(&#38;fsyncer, NULL, fsync_loop, NULL);
   if (ret != 0) {
       fprintf(stderr, &#34;Failed to create writer thread: %d\n&#34;, ret);
       return 4;
   }

   while (1) {
       ret = do_write(fd, write_buf, pagesize, 0);
       if (ret != 0) {
           perror(&#34;Write failed&#34;);
           exit(5);
       }
   }

   return 0;

}

mkfs.btrfsf/dev/sdi mount /dev/sdi /mnt/sdi
$ timeout 10 ./repro /mnt/sdi/foo

Usually the race is triggered within less than 1 second. A test case for
fstests will follow soon.

The Linux kernel CVE team has assigned CVE-2024-46734 to this issue.

openEuler评分:(评分和向量)
5.5
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H

受影响版本排查(受影响/不受影响):
1.openEuler-20.03-LTS-SP4:不受影响
2.openEuler-22.03-LTS-SP1:不受影响
3.openEuler-22.03-LTS-SP3:不受影响
4.openEuler-22.03-LTS-SP4:不受影响
5.master(6.1.0):不受影响
6.openEuler-24.03-LTS:受影响
7.openEuler-24.03-LTS-Next:不受影响

修复是否涉及abi变化(是/否):
1.openEuler-20.03-LTS-SP4:否
2.openEuler-22.03-LTS-SP1:否
3.openEuler-22.03-LTS-SP3:否
4.master(6.1.0):否
5.openEuler-24.03-LTS:否
6.openEuler-24.03-LTS-Next:否
7.openEuler-22.03-LTS-SP4:否

@ 经过 cve-manager 解析, 已分析的内容如下表所示:

状态 需分析 内容
已分析 1.影响性分析说明 In the Linux kernel, the following vulnerability has been resolved:btrfs: fix race between direct IO write and fsync when using same fdIf we have 2 threads that are using the same file descriptor and one ofthem is doing direct IO writes while the other is doing fsync, we have arace where we can end up either:1) Attempt a fsync without holding the inode's lock, triggering an assertion failures when assertions are enabled;2) Do an invalid memory access from the fsync task because the file private points to memory allocated on stack by the direct IO task and it may be used by the fsync task after the stack was destroyed.The race happens like this:1) A user space program opens a file descriptor with O_DIRECT;2) The program spawns 2 threads using libpthread for example;3) One of the threads uses the file descriptor to do direct IO writes, while the other calls fsync using the same file descriptor.4) Call task A the thread doing direct IO writes and task B the thread doing fsyncs;5) Task A does a direct IO write, and at btrfs_direct_write() sets the file's private to an on stack allocated private with the member 'fsync_skip_inode_lock' set to true;6) Task B enters btrfs_sync_file() and sees that there's a private structure associated to the file which has 'fsync_skip_inode_lock' set to true, so it skips locking the inode's VFS lock;7) Task A completes the direct IO write, and resets the file's private to NULL since it had no prior private and our private was stack allocated. Then it unlocks the inode's VFS lock;8) Task B enters btrfs_get_ordered_extents_for_logging(), then the assertion that checks the inode's VFS lock is held fails, since task B never locked it and task A has already unlocked it.The stack trace produced is the following: assertion failed: inode_is_locked(&inode->vfs_inode), in fs/btrfs/ordered-data.c:983 ------------[ cut here ]------------ kernel BUG at fs/btrfs/ordered-data.c:983! Oops: invalid opcode: 0000 [#1] PREEMPT SMP PTI CPU: 9 PID: 5072 Comm: worker Tainted: G U OE 6.10.5-1-default #1 openSUSE Tumbleweed 69f48d427608e1c09e60ea24c6c55e2ca1b049e8 Hardware name: Acer Predator PH315-52/Covini_CFS, BIOS V1.12 07/28/2020 RIP: 0010:btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs] Code: 50 d6 86 c0 e8 (...) RSP: 0018:ffff9e4a03dcfc78 EFLAGS: 00010246 RAX: 0000000000000054 RBX: ffff9078a9868e98 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffff907dce4a7800 RDI: ffff907dce4a7800 RBP: ffff907805518800 R08: 0000000000000000 R09: ffff9e4a03dcfb38 R10: ffff9e4a03dcfb30 R11: 0000000000000003 R12: ffff907684ae7800 R13: 0000000000000001 R14: ffff90774646b600 R15: 0000000000000000 FS: 00007f04b96006c0(0000) GS:ffff907dce480000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f32acbfc000 CR3: 00000001fd4fa005 CR4: 00000000003726f0 Call Trace: <TASK> ? __die_body.cold+0x14/0x24 ? die+0x2e/0x50 ? do_trap+0xca/0x110 ? do_error_trap+0x6a/0x90 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? exc_invalid_op+0x50/0x70 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? asm_exc_invalid_op+0x1a/0x20 ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? btrfs_get_ordered_extents_for_logging.cold+0x1f/0x42 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] btrfs_sync_file+0x21a/0x4d0 [btrfs bb26272d49b4cdc847cf3f7faadd459b62caee9a] ? __seccomp_filter+0x31d/0x4f0 __x64_sys_fdatasync+0x4f/0x90 do_syscall_64+0x82/0x160 ? do_futex+0xcb/0x190 ? __x64_sys_futex+0x10e/0x1d0 ? switch_fpu_return+0x4f/0xd0 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 ? syscall_exit_to_user_mode+0x72/0x220 ? do_syscall_64+0x8e/0x160 entry_SYSCALL_64_after_hwframe+0x76/0x7eAnother problem here is if task B grabs the private pointer and then usesit after task A has finished, since the private was allocated in the stackof task A, it results in some invalid memory access with a hard to predictresult.This issue, triggering the assertion, was observed with QEMU workloads bytwo users in the Link tags below.Fix this by not relying on a file's private to pass information to fsyncthat it should skip locking the inode and instead pass this informationthrough a special value stored in current->journal_info. This is safebecause in the relevant section of the direct IO write path we are notholding a transaction handle, so current->journal_info is NULL.The following C program triggers the issue: $ cat repro.c /* Get the O_DIRECT definition. */ #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <stdint.h> #include <fcntl.h> #include <errno.h> #include <string.h> #include <pthread.h> static int fd; static ssize_t do_write(int fd, const void *buf, size_t count, off_t offset) { while (count > 0) { ssize_t ret; ret = pwrite(fd, buf, count, offset); if (ret < 0) { if (errno == EINTR) continue; return ret; } count -= ret; buf += ret; } return 0; } static void *fsync_loop(void *arg) { while (1) { int ret; ret = fsync(fd); if (ret != 0) { perror("Fsync failed"); exit(6); } } } int main(int argc, char *argv[]) { long pagesize; void *write_buf; pthread_t fsyncer; int ret; if (argc != 2) { fprintf(stderr, "Use: %s <file path>\n", argv[0]); return 1; } fd = open(argv[1], O_WRONLY
已分析 2.openEulerScore 5.5
已分析 3.openEulerVector AV:L/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
已分析 4.受影响版本排查 openEuler-24.03-LTS:受影响,openEuler-20.03-LTS-SP4:不受影响,openEuler-22.03-LTS-SP1:不受影响,openEuler-22.03-LTS-SP3:不受影响,openEuler-22.03-LTS-SP4:不受影响,master:不受影响,openEuler-24.03-LTS-Next:不受影响
已分析 5.修复是否涉及abi变化 openEuler-20.03-LTS-SP4:否,openEuler-22.03-LTS-SP1:否,openEuler-22.03-LTS-SP3:否,master:否,openEuler-24.03-LTS:否,openEuler-24.03-LTS-Next:否,openEuler-22.03-LTS-SP4:否

请确认分析内容的准确性, 确认无误后, 您可以进行后续步骤, 否则您可以继续分析.

openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 负责人设置为sanglipeng 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 7个月前
openeuler-ci-bot 修改了描述 6个月前
openeuler-ci-bot 修改了描述 6个月前
仉鹏 通过合并 Pull Request !1773: release 6.6.0-46.0.0任务状态待办的 修改为已完成 6个月前
openeuler-ci-bot 移除了
 
CVE/UNFIXED
标签
6个月前
openeuler-ci-bot 移除了
 
sig/Kernel
标签
6个月前
openeuler-ci-bot 添加了
 
CVE/FIXED
标签
6个月前
openeuler-ci-bot 添加了
 
sig/Kernel
标签
6个月前
openeuler-ci-bot 修改了描述 6个月前

登录 后才可以发表评论

状态
负责人
项目
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
预计工期 (小时)
开始日期   -   截止日期
-
置顶选项
优先级
分支
参与者(2)
5329419 openeuler ci bot 1632792936 hulk-robot-zhixiuzhou
1
https://gitee.com/src-openeuler/kernel.git
git@gitee.com:src-openeuler/kernel.git
src-openeuler
kernel
kernel

搜索帮助