From: Viacheslav Dubeyko Repeatable running of generic/013 test has revealed the kernel memory exposure attempt for 6.19.0-rc8+ in ceph_netfs_issue_op_inline(): while true; do sudo ./check generic/013 done [17660.888303] ceph: ceph_netfs_issue_op_inline():317 iinfo->inline_data ffff8881000b0112, iinfo->inline_len 0, subreq->start 328187904, subreq->len 4096, len 0 [17660.891728] usercopy: Kernel memory exposure attempt detected from SLUB object 'kmemleak_object' (offset 274, size 4096)! [17660.893370] ------------[ cut here ]------------ [17660.893377] kernel BUG at mm/usercopy.c:102! [17660.894426] Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI [17660.895749] CPU: 1 UID: 0 PID: 150873 Comm: fsstress Not tainted 6.19.0-rc8+ #13 PREEMPT(voluntary) [17660.896823] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.17.0-9.fc43 06/10/2025 [17660.897891] RIP: 0010:usercopy_abort+0x7a/0x7c [17660.898575] Code: 48 c7 c6 80 bb 3e 8c eb 0e 48 c7 c7 c0 bb 3e 8c 48 c7 c6 00 bc 3e 8c 52 48 89 fa 48 c7 c7 40 bc 3e 8c 50 41 52 e8 e6 00 fb ff <0f> 0b e8 ef 0e fb 00 4d 89 e0 31 c9 44 89 f2 48 c7 c6 c0 bd 3e 8c [17660.901225] RSP: 0018:ffff888179fbf340 EFLAGS: 00010246 [17660.901762] RAX: 000000000000006d RBX: ffff8881139ac112 RCX: 0000000000000000 [17660.902295] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000000 [17660.902813] RBP: ffff888179fbf358 R08: 0000000000000000 R09: 0000000000000000 [17660.903317] R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000001000 [17660.903820] R13: ffff8881139ad112 R14: 0000000000000001 R15: ffff888119da8bb0 [17660.904283] FS: 0000747714d62740(0000) GS:ffff888266112000(0000) knlGS:0000000000000000 [17660.904719] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [17660.905122] CR2: 00007477143ffff0 CR3: 00000001014f9005 CR4: 0000000000772ef0 [17660.905555] PKRU: 55555554 [17660.905743] Call Trace: [17660.905902] [17660.906042] __check_heap_object+0xf1/0x130 [17660.906372] ? __virt_addr_valid+0x26b/0x510 [17660.906667] __check_object_size+0x401/0x700 [17660.906959] ceph_netfs_issue_read.cold+0x295/0x2f1 [17660.907322] ? __pfx_ceph_netfs_issue_read+0x10/0x10 [17660.907657] ? __kasan_check_write+0x14/0x30 [17660.907940] ? kvm_sched_clock_read+0x11/0x20 [17660.908268] ? sched_clock_noinstr+0x9/0x10 [17660.908531] ? local_clock_noinstr+0xf/0x120 [17660.908817] netfs_read_to_pagecache+0x45a/0x10f0 [17660.909168] ? netfs_read_to_pagecache+0x45a/0x10f0 [17660.909482] netfs_write_begin+0x589/0xfc0 [17660.909761] ? __kasan_check_read+0x11/0x20 [17660.910019] ? __pfx_netfs_write_begin+0x10/0x10 [17660.910340] ? mark_held_locks+0x46/0x90 [17660.910629] ? inode_set_ctime_current+0x3d0/0x520 [17660.910965] ceph_write_begin+0x8c/0x1c0 [17660.911237] generic_perform_write+0x391/0x8f0 The reason of the issue is located in this code: err = copy_to_iter(iinfo->inline_data + subreq->start, len, &subreq->io_iter); We have valid pointer iinfo->inline_data ffff8881000b0112. The iinfo->inline_len has 0 size in bytes. However, subreq->start has really big value 328187904. Finally, the sum of iinfo->inline_data and subreq->start results in the pointer that is out of available memory area. This patch checks the iinfo->inline_len value. If it has zero value, then -EFAULT code error will be return. Otherwise, the copy_to_iter() logic will be executed. Signed-off-by: Viacheslav Dubeyko cc: Alex Markuze cc: Ilya Dryomov cc: Patrick Donnelly cc: Ceph Development --- fs/ceph/addr.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c index e87b3bb94ee8..426121e38f3f 100644 --- a/fs/ceph/addr.c +++ b/fs/ceph/addr.c @@ -314,14 +314,18 @@ static bool ceph_netfs_issue_op_inline(struct netfs_io_subrequest *subreq) return false; } - len = min_t(size_t, iinfo->inline_len - subreq->start, subreq->len); - err = copy_to_iter(iinfo->inline_data + subreq->start, len, &subreq->io_iter); - if (err == 0) { + if (iinfo->inline_len > 0) { + len = min_t(size_t, iinfo->inline_len, subreq->len); + + err = copy_to_iter(iinfo->inline_data, len, &subreq->io_iter); + if (err == 0) { + err = -EFAULT; + } else { + subreq->transferred += err; + err = 0; + } + } else err = -EFAULT; - } else { - subreq->transferred += err; - err = 0; - } ceph_mdsc_put_request(req); out: -- 2.53.0