* [RFC PATCH] ceph: fix kernel memory exposure issue in ceph_netfs_issue_op_inline()
@ 2026-02-26 22:30 Viacheslav Dubeyko
2026-04-27 12:16 ` Alex Markuze
0 siblings, 1 reply; 5+ messages in thread
From: Viacheslav Dubeyko @ 2026-02-26 22:30 UTC (permalink / raw)
To: ceph-devel
Cc: idryomov, linux-fsdevel, pdonnell, amarkuze, Slava.Dubeyko, slava,
vdubeyko
From: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
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] <TASK>
[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 <Slava.Dubeyko@ibm.com>
cc: Alex Markuze <amarkuze@redhat.com>
cc: Ilya Dryomov <idryomov@gmail.com>
cc: Patrick Donnelly <pdonnell@redhat.com>
cc: Ceph Development <ceph-devel@vger.kernel.org>
---
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
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] ceph: fix kernel memory exposure issue in ceph_netfs_issue_op_inline()
2026-02-26 22:30 [RFC PATCH] ceph: fix kernel memory exposure issue in ceph_netfs_issue_op_inline() Viacheslav Dubeyko
@ 2026-04-27 12:16 ` Alex Markuze
2026-04-27 12:27 ` Alex Markuze
0 siblings, 1 reply; 5+ messages in thread
From: Alex Markuze @ 2026-04-27 12:16 UTC (permalink / raw)
To: Viacheslav Dubeyko
Cc: ceph-devel, idryomov, linux-fsdevel, pdonnell, Slava.Dubeyko,
vdubeyko
Reviewed-by: Alex Markuze <amarkuze@redhat.com>
On Fri, Feb 27, 2026 at 12:30 AM Viacheslav Dubeyko <slava@dubeyko.com> wrote:
>
> From: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
>
> 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] <TASK>
> [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 <Slava.Dubeyko@ibm.com>
> cc: Alex Markuze <amarkuze@redhat.com>
> cc: Ilya Dryomov <idryomov@gmail.com>
> cc: Patrick Donnelly <pdonnell@redhat.com>
> cc: Ceph Development <ceph-devel@vger.kernel.org>
> ---
> 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
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] ceph: fix kernel memory exposure issue in ceph_netfs_issue_op_inline()
2026-04-27 12:16 ` Alex Markuze
@ 2026-04-27 12:27 ` Alex Markuze
2026-04-27 22:00 ` Viacheslav Dubeyko
2026-04-28 22:34 ` Ilya Dryomov
0 siblings, 2 replies; 5+ messages in thread
From: Alex Markuze @ 2026-04-27 12:27 UTC (permalink / raw)
To: Viacheslav Dubeyko
Cc: ceph-devel, idryomov, linux-fsdevel, pdonnell, Slava.Dubeyko,
vdubeyko
Apologies, I acked the wrong patch here.
The Bug is real and needs fixing, but there is a problem:
1. subreq->start is silently dropped
The original code:
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);
The new code:
len = min_t(size_t, iinfo->inline_len, subreq->len);
err = copy_to_iter(iinfo->inline_data, len, &subreq->io_iter);
The subreq->start offset is completely removed. If subreq->start > 0
with valid inline data, the wrong bytes are copied (always from offset
0 instead of the requested offset).
While CephFS inline data is typically small and subreq->start is
likely 0 in practice, the fix is still semantically incorrect for the
general case.
2. -EFAULT is the wrong error code. When inline_len == 0, the data
was uninlined; there's no inline payload.
Returning -EFAULT signals a user-address fault, which is
misleading and will propagate as an I/O error instead of falling back
to the OSD path.
3. Coding style violation. The } else without braces:
} else
err = -EFAULT;
I suggest the following:
A cleaner approach would preserve the offset logic and handle the
edge cases properly:
if (iinfo->inline_len == 0 || subreq->start >= iinfo->inline_len) {
/* Nothing to copy; CLEAR_TAIL flag will zero-fill */
len = 0;
} else {
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)
err = -EFAULT;
else {
subreq->transferred += err;
err = 0;
}
}
Or alternatively, treat inline_len == 0 the same way as
inline_version == CEPH_INLINE_NONE and return false to let the caller
fall back to a normal OSD read.
Alex
On Mon, Apr 27, 2026 at 3:16 PM Alex Markuze <amarkuze@redhat.com> wrote:
>
> Reviewed-by: Alex Markuze <amarkuze@redhat.com>
>
> On Fri, Feb 27, 2026 at 12:30 AM Viacheslav Dubeyko <slava@dubeyko.com> wrote:
> >
> > From: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
> >
> > 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] <TASK>
> > [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 <Slava.Dubeyko@ibm.com>
> > cc: Alex Markuze <amarkuze@redhat.com>
> > cc: Ilya Dryomov <idryomov@gmail.com>
> > cc: Patrick Donnelly <pdonnell@redhat.com>
> > cc: Ceph Development <ceph-devel@vger.kernel.org>
> > ---
> > 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
> >
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] ceph: fix kernel memory exposure issue in ceph_netfs_issue_op_inline()
2026-04-27 12:27 ` Alex Markuze
@ 2026-04-27 22:00 ` Viacheslav Dubeyko
2026-04-28 22:34 ` Ilya Dryomov
1 sibling, 0 replies; 5+ messages in thread
From: Viacheslav Dubeyko @ 2026-04-27 22:00 UTC (permalink / raw)
To: Alex Markuze, Viacheslav Dubeyko
Cc: ceph-devel, idryomov, linux-fsdevel, pdonnell
On Mon, 2026-04-27 at 15:27 +0300, Alex Markuze wrote:
> Apologies, I acked the wrong patch here.
>
> The Bug is real and needs fixing, but there is a problem:
>
>
> 1. subreq->start is silently dropped
>
> The original code:
> 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);
The subreq->start is meaningless here. We cannot use subreq->start at all. We
need to know the offset inside of inline buffer. Mostly, it should be small
enough. If we would like to process it in the correct way, probably, we need to
introduce some special field in some structure. But subreq->start is completely
inapplicable in this calculation.
During testing I saw that subreq->start was 0. And I saw subreq->start == 32768
something for the case of issue.
>
> The new code:
> len = min_t(size_t, iinfo->inline_len, subreq->len);
> err = copy_to_iter(iinfo->inline_data, len, &subreq->io_iter);
>
> The subreq->start offset is completely removed. If subreq->start > 0
> with valid inline data, the wrong bytes are copied (always from offset
> 0 instead of the requested offset).
> While CephFS inline data is typically small and subreq->start is
> likely 0 in practice, the fix is still semantically incorrect for the
> general case.
>
> 2. -EFAULT is the wrong error code. When inline_len == 0, the data
> was uninlined; there's no inline payload.
> Returning -EFAULT signals a user-address fault, which is
> misleading and will propagate as an I/O error instead of falling back
> to the OSD path.
>
Which error code do you suggest to use here?
> 3. Coding style violation. The } else without braces:
> } else
> err = -EFAULT;
>
I can rework it.
> I suggest the following:
>
> A cleaner approach would preserve the offset logic and handle the
> edge cases properly:
>
> if (iinfo->inline_len == 0 || subreq->start >= iinfo->inline_len) {
> /* Nothing to copy; CLEAR_TAIL flag will zero-fill */
> len = 0;
> } else {
> 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)
> err = -EFAULT;
> else {
> subreq->transferred += err;
> err = 0;
> }
> }
>
> Or alternatively, treat inline_len == 0 the same way as
> inline_version == CEPH_INLINE_NONE and return false to let the caller
> fall back to a normal OSD read.
>
We can use subreq->start at all. We need to consider something else.
Thanks,
Slava.
> Alex
>
> On Mon, Apr 27, 2026 at 3:16 PM Alex Markuze <amarkuze@redhat.com> wrote:
> >
> > Reviewed-by: Alex Markuze <amarkuze@redhat.com>
> >
> > On Fri, Feb 27, 2026 at 12:30 AM Viacheslav Dubeyko <slava@dubeyko.com> wrote:
> > >
> > > From: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
> > >
> > > 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] <TASK>
> > > [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 <Slava.Dubeyko@ibm.com>
> > > cc: Alex Markuze <amarkuze@redhat.com>
> > > cc: Ilya Dryomov <idryomov@gmail.com>
> > > cc: Patrick Donnelly <pdonnell@redhat.com>
> > > cc: Ceph Development <ceph-devel@vger.kernel.org>
> > > ---
> > > 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
> > >
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [RFC PATCH] ceph: fix kernel memory exposure issue in ceph_netfs_issue_op_inline()
2026-04-27 12:27 ` Alex Markuze
2026-04-27 22:00 ` Viacheslav Dubeyko
@ 2026-04-28 22:34 ` Ilya Dryomov
1 sibling, 0 replies; 5+ messages in thread
From: Ilya Dryomov @ 2026-04-28 22:34 UTC (permalink / raw)
To: Alex Markuze
Cc: Viacheslav Dubeyko, ceph-devel, linux-fsdevel, pdonnell,
Slava.Dubeyko, vdubeyko
On Mon, Apr 27, 2026 at 2:27 PM Alex Markuze <amarkuze@redhat.com> wrote:
>
> Apologies, I acked the wrong patch here.
>
> The Bug is real and needs fixing, but there is a problem:
>
>
> 1. subreq->start is silently dropped
>
> The original code:
> 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);
>
> The new code:
> len = min_t(size_t, iinfo->inline_len, subreq->len);
> err = copy_to_iter(iinfo->inline_data, len, &subreq->io_iter);
>
> The subreq->start offset is completely removed. If subreq->start > 0
> with valid inline data, the wrong bytes are copied (always from offset
> 0 instead of the requested offset).
> While CephFS inline data is typically small and subreq->start is
> likely 0 in practice, the fix is still semantically incorrect for the
> general case.
>
> 2. -EFAULT is the wrong error code. When inline_len == 0, the data
> was uninlined; there's no inline payload.
> Returning -EFAULT signals a user-address fault, which is
> misleading and will propagate as an I/O error instead of falling back
> to the OSD path.
>
> 3. Coding style violation. The } else without braces:
> } else
> err = -EFAULT;
>
> I suggest the following:
>
> A cleaner approach would preserve the offset logic and handle the
> edge cases properly:
>
> if (iinfo->inline_len == 0 || subreq->start >= iinfo->inline_len) {
> /* Nothing to copy; CLEAR_TAIL flag will zero-fill */
> len = 0;
> } else {
> 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)
> err = -EFAULT;
> else {
> subreq->transferred += err;
> err = 0;
> }
> }
>
> Or alternatively, treat inline_len == 0 the same way as
> inline_version == CEPH_INLINE_NONE and return false to let the caller
> fall back to a normal OSD read.
Hi Slava, Alex,
I'd suggest digging into why ceph_netfs_issue_op_inline() got invoked
in the first place instead, in a vein similar to my comments on
"[PATCH] ceph: fix generic/639 xfstests failure". The call appears to
be conditioned on ceph_has_inline_data() so it won't be exactly the
same root cause but there is _got_ to be something else going on here.
I don't see how a file created by generic/013 (i.e. fsstress) on top of
the kernel client can legitimately have ceph_has_inline_data() return
false.
Thanks,
Ilya
>
> Alex
>
> On Mon, Apr 27, 2026 at 3:16 PM Alex Markuze <amarkuze@redhat.com> wrote:
> >
> > Reviewed-by: Alex Markuze <amarkuze@redhat.com>
> >
> > On Fri, Feb 27, 2026 at 12:30 AM Viacheslav Dubeyko <slava@dubeyko.com> wrote:
> > >
> > > From: Viacheslav Dubeyko <Slava.Dubeyko@ibm.com>
> > >
> > > 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] <TASK>
> > > [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 <Slava.Dubeyko@ibm.com>
> > > cc: Alex Markuze <amarkuze@redhat.com>
> > > cc: Ilya Dryomov <idryomov@gmail.com>
> > > cc: Patrick Donnelly <pdonnell@redhat.com>
> > > cc: Ceph Development <ceph-devel@vger.kernel.org>
> > > ---
> > > 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
> > >
>
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-04-28 22:34 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-26 22:30 [RFC PATCH] ceph: fix kernel memory exposure issue in ceph_netfs_issue_op_inline() Viacheslav Dubeyko
2026-04-27 12:16 ` Alex Markuze
2026-04-27 12:27 ` Alex Markuze
2026-04-27 22:00 ` Viacheslav Dubeyko
2026-04-28 22:34 ` Ilya Dryomov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox