mailweb.openeuler.org
Manage this list

Keyboard Shortcuts

Thread View

  • j: Next unread message
  • k: Previous unread message
  • j a: Jump to all threads
  • j l: Jump to MailingList overview

Kernel

Threads by month
  • ----- 2026 -----
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2025 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2024 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2023 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2022 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2021 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2020 -----
  • December
  • November
  • October
  • September
  • August
  • July
  • June
  • May
  • April
  • March
  • February
  • January
  • ----- 2019 -----
  • December
kernel@openeuler.org

  • 39 participants
  • 24784 discussions
[PATCH OLK-6.6 v2] bpf: Disable preemption in __bpf_get_stack
by Pu Lehui 17 Sep '26

17 Sep '26
From: Daniel Borkmann <borkmann(a)iogearbox.net> mainline inclusion from mainline-v7.3-rc1 commit b1a47b2708d4e95dbd23aee2ec83752190897b3f category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18901 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- get_perf_callchain() returns a per-CPU perf_callchain_entry buffer and releases its recursion slot via put_callchain_entry() before returning, so nothing keeps the entry reserved while __bpf_get_stack() consumes it below. A preemptible BPF program (e.g. a non-sleepable raw tracepoint program on a PREEMPT kernel, which runs under migrate_disable() but not preempt_disable()) can be scheduled out between obtaining the entry and the copy. Another task scheduled on the same CPU then reuses the same per-CPU buffer and overwrites trace->nr with a larger value. copy_len is then computed from the inflated trace->nr and can exceed the caller's buffer, causing an out-of-bounds write in the memcpy() and in the build_id path. The rcu_read_lock() taken here alone does not prevent this. It is only taken on the may_fault path, and under CONFIG_PREEMPT_RCU it does not disable preemption; it merely keeps perf's callchain buffer array alive (freed via call_rcu()) and does nothing to stop another task from reusing the entry. Disable preemption around obtaining the callchain entry and copying it into the caller's buffer, so the entry cannot be reused underneath us and trace->nr stays bounded by max_depth. Build ID resolution may fault and is therefore deferred until after preemption is re-enabled; by then the instruction pointers have already been copied into buf, so it operates only on that private copy. Note, preempt_disable() also subsumes the buffer-lifetime guarantee the rcu_read_lock() provided, since a preempt-disabled section is an RCU read-side critical section for the callchain buffers' call_rcu() reclaim. Fixes: c195651e565a ("bpf: add bpf_get_stack helper") Reported-by: Tao Chen <chen.dylane(a)linux.dev> Reported-by: STAR Labs SG <info(a)starlabs.sg> Signed-off-by: Daniel Borkmann <borkmann(a)iogearbox.net> Signed-off-by: Jiri Olsa <jolsa(a)kernel.org> Signed-off-by: Andrii Nakryiko <andrii(a)kernel.org> Cc: stable(a)vger.kernel.org Link: https://lore.kernel.org/bpf/20260803210149.296496-11-jolsa@kernel.org Closes: https://lore.kernel.org/bpf/20260206090653.1336687-1-chen.dylane@linux.dev/ [ changed Fixes: commit ] Conflicts: kernel/bpf/stackmap.c [not refactor to callchain_store and callchain_finalize] Signed-off-by: Pu Lehui <pulehui(a)huawei.com> --- kernel/bpf/stackmap.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index 2a4070d0b594..3dc99abc1d51 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c @@ -444,6 +444,7 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task, max_depth = stack_map_calculate_max_depth(size, elem_size, flags); + preempt_disable(); if (trace_in) { trace = trace_in; trace->nr = min_t(u32, trace->nr, max_depth); @@ -453,16 +454,21 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task, trace = get_perf_callchain(regs, 0, kernel, user, max_depth, crosstask, false); } - if (unlikely(!trace)) + if (unlikely(!trace)) { + preempt_enable(); goto err_fault; + } - if (trace->nr < skip) + if (trace->nr < skip) { + preempt_enable(); goto err_fault; + } trace_nr = trace->nr - skip; copy_len = trace_nr * elem_size; ips = trace->ip + skip; + preempt_enable(); if (user && user_build_id) stack_map_get_build_id_offset(buf, ips, trace_nr, user); else -- 2.34.1
1 0
0 0
[PATCH OLK-5.10 v2] bpf: Disable preemption in __bpf_get_stack
by Pu Lehui 17 Sep '26

17 Sep '26
From: Daniel Borkmann <borkmann(a)iogearbox.net> mainline inclusion from mainline-v7.3-rc1 commit b1a47b2708d4e95dbd23aee2ec83752190897b3f category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18901 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- get_perf_callchain() returns a per-CPU perf_callchain_entry buffer and releases its recursion slot via put_callchain_entry() before returning, so nothing keeps the entry reserved while __bpf_get_stack() consumes it below. A preemptible BPF program (e.g. a non-sleepable raw tracepoint program on a PREEMPT kernel, which runs under migrate_disable() but not preempt_disable()) can be scheduled out between obtaining the entry and the copy. Another task scheduled on the same CPU then reuses the same per-CPU buffer and overwrites trace->nr with a larger value. copy_len is then computed from the inflated trace->nr and can exceed the caller's buffer, causing an out-of-bounds write in the memcpy() and in the build_id path. The rcu_read_lock() taken here alone does not prevent this. It is only taken on the may_fault path, and under CONFIG_PREEMPT_RCU it does not disable preemption; it merely keeps perf's callchain buffer array alive (freed via call_rcu()) and does nothing to stop another task from reusing the entry. Disable preemption around obtaining the callchain entry and copying it into the caller's buffer, so the entry cannot be reused underneath us and trace->nr stays bounded by max_depth. Build ID resolution may fault and is therefore deferred until after preemption is re-enabled; by then the instruction pointers have already been copied into buf, so it operates only on that private copy. Note, preempt_disable() also subsumes the buffer-lifetime guarantee the rcu_read_lock() provided, since a preempt-disabled section is an RCU read-side critical section for the callchain buffers' call_rcu() reclaim. Fixes: c195651e565a ("bpf: add bpf_get_stack helper") Reported-by: Tao Chen <chen.dylane(a)linux.dev> Reported-by: STAR Labs SG <info(a)starlabs.sg> Signed-off-by: Daniel Borkmann <borkmann(a)iogearbox.net> Signed-off-by: Jiri Olsa <jolsa(a)kernel.org> Signed-off-by: Andrii Nakryiko <andrii(a)kernel.org> Cc: stable(a)vger.kernel.org Link: https://lore.kernel.org/bpf/20260803210149.296496-11-jolsa@kernel.org Closes: https://lore.kernel.org/bpf/20260206090653.1336687-1-chen.dylane@linux.dev/ [ changed Fixes: commit ] Conflicts: kernel/bpf/stackmap.c [not refactor to callchain_store and callchain_finalize] Signed-off-by: Pu Lehui <pulehui(a)huawei.com> --- kernel/bpf/stackmap.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index 0c3504e598e3..44eccaf13aa0 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c @@ -620,6 +620,7 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task, if (sysctl_perf_event_max_stack < max_depth) max_depth = sysctl_perf_event_max_stack; + preempt_disable(); if (trace_in) trace = trace_in; else if (kernel && task) @@ -627,17 +628,22 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task, else trace = get_perf_callchain(regs, 0, kernel, user, max_depth, crosstask, false); - if (unlikely(!trace)) + if (unlikely(!trace)) { + preempt_enable(); goto err_fault; + } - if (trace->nr < skip) + if (trace->nr < skip) { + preempt_enable(); goto err_fault; + } trace_nr = trace->nr - skip; trace_nr = (trace_nr <= num_elem) ? trace_nr : num_elem; copy_len = trace_nr * elem_size; ips = trace->ip + skip; + preempt_enable(); if (user && user_build_id) stack_map_get_build_id_offset(buf, ips, trace_nr, user); else -- 2.34.1
1 0
0 0
[PATCH openEuler-1.0-LTS] bpf: Disable preemption in __bpf_get_stack
by Pu Lehui 17 Sep '26

17 Sep '26
From: Daniel Borkmann <borkmann(a)iogearbox.net> mainline inclusion from mainline-v7.3-rc1 commit b1a47b2708d4e95dbd23aee2ec83752190897b3f category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18901 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- get_perf_callchain() returns a per-CPU perf_callchain_entry buffer and releases its recursion slot via put_callchain_entry() before returning, so nothing keeps the entry reserved while __bpf_get_stack() consumes it below. A preemptible BPF program (e.g. a non-sleepable raw tracepoint program on a PREEMPT kernel, which runs under migrate_disable() but not preempt_disable()) can be scheduled out between obtaining the entry and the copy. Another task scheduled on the same CPU then reuses the same per-CPU buffer and overwrites trace->nr with a larger value. copy_len is then computed from the inflated trace->nr and can exceed the caller's buffer, causing an out-of-bounds write in the memcpy() and in the build_id path. The rcu_read_lock() taken here alone does not prevent this. It is only taken on the may_fault path, and under CONFIG_PREEMPT_RCU it does not disable preemption; it merely keeps perf's callchain buffer array alive (freed via call_rcu()) and does nothing to stop another task from reusing the entry. Disable preemption around obtaining the callchain entry and copying it into the caller's buffer, so the entry cannot be reused underneath us and trace->nr stays bounded by max_depth. Build ID resolution may fault and is therefore deferred until after preemption is re-enabled; by then the instruction pointers have already been copied into buf, so it operates only on that private copy. Note, preempt_disable() also subsumes the buffer-lifetime guarantee the rcu_read_lock() provided, since a preempt-disabled section is an RCU read-side critical section for the callchain buffers' call_rcu() reclaim. Fixes: c195651e565a ("bpf: add bpf_get_stack helper") Reported-by: Tao Chen <chen.dylane(a)linux.dev> Reported-by: STAR Labs SG <info(a)starlabs.sg> Signed-off-by: Daniel Borkmann <borkmann(a)iogearbox.net> Signed-off-by: Jiri Olsa <jolsa(a)kernel.org> Signed-off-by: Andrii Nakryiko <andrii(a)kernel.org> Cc: stable(a)vger.kernel.org Link: https://lore.kernel.org/bpf/20260803210149.296496-11-jolsa@kernel.org Closes: https://lore.kernel.org/bpf/20260206090653.1336687-1-chen.dylane@linux.dev/ [ changed Fixes: commit ] Conflicts: kernel/bpf/stackmap.c [not refactor to callchain_store and callchain_finalize] Signed-off-by: Pu Lehui <pulehui(a)huawei.com> --- kernel/bpf/stackmap.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index a41858db1441..beaf63f17d60 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c @@ -477,6 +477,7 @@ BPF_CALL_4(bpf_get_stack, struct pt_regs *, regs, void *, buf, u32, size, if (unlikely(size % elem_size)) goto clear; + preempt_disable(); num_elem = size / elem_size; if (sysctl_perf_event_max_stack < num_elem) init_nr = 0; @@ -484,17 +485,23 @@ BPF_CALL_4(bpf_get_stack, struct pt_regs *, regs, void *, buf, u32, size, init_nr = sysctl_perf_event_max_stack - num_elem; trace = get_perf_callchain(regs, init_nr, kernel, user, sysctl_perf_event_max_stack, false, false); - if (unlikely(!trace)) + if (unlikely(!trace)) { + preempt_enable(); goto err_fault; + } trace_nr = trace->nr - init_nr; - if (trace_nr < skip) + if (trace_nr < skip) { + preempt_enable(); goto err_fault; + } trace_nr -= skip; trace_nr = (trace_nr <= num_elem) ? trace_nr : num_elem; copy_len = trace_nr * elem_size; ips = trace->ip + skip + init_nr; + + preempt_enable(); if (user && user_build_id) stack_map_get_build_id_offset(buf, ips, trace_nr, user); else -- 2.34.1
1 0
0 0
[PATCH openEuler-1.0-LTS] ceph: bound num_export_targets array for mds info v2/v3
by Pu Lehui 17 Sep '26

17 Sep '26
From: Michael Bommarito <michael.bommarito(a)gmail.com> mainline inclusion from mainline-v7.3-rc1 commit a3eb169ee297aa99670ba927c659990bd1e453f3 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/19003 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- ceph_mdsmap_decode() in fs/ceph/mdsmap.c reads num_export_targets from each per-mds info record and advances the decode cursor by num_export_targets * sizeof(u32) without first checking that many bytes remain. The only upper-bound check that catches a runaway cursor (*p > info_end) is gated on info_v >= 4, because info_end is left NULL for info_v 2 and 3. When the monitor sends an MDS map whose per-mds info version is 2 or 3 with an oversized num_export_targets, the cursor moves past the message front buffer and the later export-targets loop calls the unchecked ceph_decode_32() on out-of-bounds memory. A kernel client processes CEPH_MSG_MDS_MAP from its monitor session (net/ceph/mon_client.c dispatches it; fs/ceph/super.c routes it to ceph_mdsc_handle_mdsmap(), which sets end to the front buffer bound and calls ceph_mdsmap_decode()). A malicious or compromised monitor, or an on-path attacker on an unsigned/unencrypted messenger session, can therefore drive an out-of-bounds read in the client kernel; on x86_64 with KASAN it is reported as a slab-out-of-bounds read in ceph_mdsmap_decode(). The decoded values land in the internal info->export_targets[] array, so the consequence is a kernel out-of-bounds read, not an information leak to the attacker. Impact: a malicious or compromised Ceph monitor sending an MDS map with a per-mds info version of 2 or 3 and an oversized num_export_targets field triggers an out-of-bounds read in the CephFS client kernel. Add a ceph_decode_need() for the export-targets array before advancing the cursor, so the bound is enforced for every info_v >= 2, not only info_v >= 4. This mirrors the count-then-need idiom already used for m_data_pg_pools later in the same function. Compute the export-targets byte count with size_mul() and reuse that checked length when advancing the cursor, so the attacker-controlled num_export_targets multiplication fails closed on overflow rather than relying on the later kcalloc() guard. Cc: stable(a)vger.kernel.org Fixes: d463a43d69f4 ("ceph: CEPH_FEATURE_MDSENC support") Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Michael Bommarito <michael.bommarito(a)gmail.com> Reviewed-by: Viacheslav Dubeyko <slava(a)dubeyko.com> Signed-off-by: Ilya Dryomov <idryomov(a)gmail.com> Conflicts: fs/ceph/mdsmap.c [ctx conflicts] Signed-off-by: Pu Lehui <pulehui(a)huawei.com> --- fs/ceph/mdsmap.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/ceph/mdsmap.c b/fs/ceph/mdsmap.c index 44e53abeb32a..5583f5e171af 100644 --- a/fs/ceph/mdsmap.c +++ b/fs/ceph/mdsmap.c @@ -3,6 +3,7 @@ #include <linux/bug.h> #include <linux/err.h> +#include <linux/overflow.h> #include <linux/random.h> #include <linux/slab.h> #include <linux/types.h> @@ -111,6 +112,7 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end) int err = -EINVAL; u8 mdsmap_v, mdsmap_cv; u16 mdsmap_ev; + size_t export_targets_len; m = kzalloc(sizeof(*m), GFP_NOFS); if (!m) @@ -192,8 +194,11 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end) *p += namelen; if (info_v >= 2) { ceph_decode_32_safe(p, end, num_export_targets, bad); + export_targets_len = size_mul(num_export_targets, + sizeof(u32)); + ceph_decode_need(p, end, export_targets_len, bad); pexport_targets = *p; - *p += num_export_targets * sizeof(u32); + *p += export_targets_len; } else { num_export_targets = 0; } -- 2.34.1
2 1
0 0
[PATCH OLK-6.6] ceph: bound copied dentry name length in NFS export get_name
by Chen Yuxi 17 Sep '26

17 Sep '26
From: Michael Bommarito <michael.bommarito(a)gmail.com> mainline inclusion from mainline-v7.3-rc1 commit eff8013c5a8916613c742ae5a2cc341cb605c0ae category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18968 Reference: https://web.git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/comm… -------------------------------- ceph_get_name() copies the MDS-supplied name into the caller's NAME_MAX-sized buffer with memcpy(name, rinfo->dname, rinfo->dname_len) and then writes name[rinfo->dname_len] = 0, without checking dname_len against NAME_MAX. A malicious or buggy MDS that returns a LOOKUPNAME reply with dname_len > NAME_MAX overflows the buffer. __get_snap_name() copies rde->name / rde->name_len the same unchecked way. Impact: a malicious or compromised Ceph MDS overflows the NAME_MAX name buffer in a client's NFS-export get_name path, a slab out-of-bounds write reported by KASAN. Reachable when a CephFS mount is re-exported over NFS. Add ceph_export_copy_name(), which rejects lengths above NAME_MAX with -ENAMETOOLONG before the copy, and use it in both ceph_get_name() and __get_snap_name(). Cc: stable(a)vger.kernel.org Fixes: 19913b4eac4a ("ceph: add get_name() NFS export callback") Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Michael Bommarito <michael.bommarito(a)gmail.com> Reviewed-by: Viacheslav Dubeyko <slava(a)dubeyko.com> Signed-off-by: Ilya Dryomov <idryomov(a)gmail.com> Signed-off-by: Chen Yuxi <chenyuxi19(a)huawei.com> --- fs/ceph/export.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 52c4daf2447d..e9cbd08a7dcb 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -434,6 +434,16 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb, return dentry; } +static int ceph_export_copy_name(char *name, const char *src, u32 len) +{ + if (len > NAME_MAX) + return -ENAMETOOLONG; + + memcpy(name, src, len); + name[len] = '\0'; + return 0; +} + static int __get_snap_name(struct dentry *parent, char *name, struct dentry *child) { @@ -499,9 +509,8 @@ static int __get_snap_name(struct dentry *parent, char *name, BUG_ON(!rde->inode.in); if (ceph_snap(inode) == le64_to_cpu(rde->inode.in->snapid)) { - memcpy(name, rde->name, rde->name_len); - name[rde->name_len] = '\0'; - err = 0; + err = ceph_export_copy_name(name, rde->name, + rde->name_len); goto out; } } @@ -566,8 +575,8 @@ static int ceph_get_name(struct dentry *parent, char *name, rinfo = &req->r_reply_info; if (!IS_ENCRYPTED(dir)) { - memcpy(name, rinfo->dname, rinfo->dname_len); - name[rinfo->dname_len] = 0; + err = ceph_export_copy_name(name, rinfo->dname, + rinfo->dname_len); } else { struct fscrypt_str oname = FSTR_INIT(NULL, 0); struct ceph_fname fname = { .dir = dir, @@ -581,10 +590,9 @@ static int ceph_get_name(struct dentry *parent, char *name, goto out; err = ceph_fname_to_usr(&fname, NULL, &oname, NULL); - if (!err) { - memcpy(name, oname.name, oname.len); - name[oname.len] = 0; - } + if (!err) + err = ceph_export_copy_name(name, oname.name, + oname.len); ceph_fname_free_buffer(dir, &oname); } out: -- 2.34.1
1 0
0 0
[PATCH OLK-5.10] ceph: bound copied dentry name length in NFS export get_name
by Chen Yuxi 17 Sep '26

17 Sep '26
From: Michael Bommarito <michael.bommarito(a)gmail.com> mainline inclusion from mainline-v7.3-rc1 commit eff8013c5a8916613c742ae5a2cc341cb605c0ae category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18968 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?… -------------------------------- ceph_get_name() copies the MDS-supplied name into the caller's NAME_MAX-sized buffer with memcpy(name, rinfo->dname, rinfo->dname_len) and then writes name[rinfo->dname_len] = 0, without checking dname_len against NAME_MAX. A malicious or buggy MDS that returns a LOOKUPNAME reply with dname_len > NAME_MAX overflows the buffer. __get_snap_name() copies rde->name / rde->name_len the same unchecked way. Impact: a malicious or compromised Ceph MDS overflows the NAME_MAX name buffer in a client's NFS-export get_name path, a slab out-of-bounds write reported by KASAN. Reachable when a CephFS mount is re-exported over NFS. Add ceph_export_copy_name(), which rejects lengths above NAME_MAX with -ENAMETOOLONG before the copy, and use it in both ceph_get_name() and __get_snap_name(). Cc: stable(a)vger.kernel.org Fixes: 19913b4eac4a ("ceph: add get_name() NFS export callback") Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Michael Bommarito <michael.bommarito(a)gmail.com> Reviewed-by: Viacheslav Dubeyko <slava(a)dubeyko.com> Signed-off-by: Ilya Dryomov <idryomov(a)gmail.com> Conflicts: fs/ceph/export.c [Downstream tree lacks the fscrypt support, so keep the tree's simpler (non-encrypted) get_name structure.] Signed-off-by: Chen Yuxi <chenyuxi19(a)huawei.com> --- fs/ceph/export.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 952a590dd4bc..54efb44fc89b 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -431,6 +431,16 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb, return dentry; } +static int ceph_export_copy_name(char *name, const char *src, u32 len) +{ + if (len > NAME_MAX) + return -ENAMETOOLONG; + + memcpy(name, src, len); + name[len] = '\0'; + return 0; +} + static int __get_snap_name(struct dentry *parent, char *name, struct dentry *child) { @@ -496,9 +506,8 @@ static int __get_snap_name(struct dentry *parent, char *name, BUG_ON(!rde->inode.in); if (ceph_snap(inode) == le64_to_cpu(rde->inode.in->snapid)) { - memcpy(name, rde->name, rde->name_len); - name[rde->name_len] = '\0'; - err = 0; + err = ceph_export_copy_name(name, rde->name, + rde->name_len); goto out; } } @@ -559,10 +568,11 @@ static int ceph_get_name(struct dentry *parent, char *name, if (!err) { struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info; - memcpy(name, rinfo->dname, rinfo->dname_len); - name[rinfo->dname_len] = 0; - dout("get_name %p ino %llx.%llx name %s\n", - child, ceph_vinop(inode), name); + err = ceph_export_copy_name(name, rinfo->dname, + rinfo->dname_len); + if (!err) + dout("get_name %p ino %llx.%llx name %s\n", + child, ceph_vinop(d_inode(child)), name); } else { dout("get_name %p ino %llx.%llx err %d\n", child, ceph_vinop(inode), err); -- 2.34.1
1 0
0 0
[PATCH OLK-5.10] bpf: Disable preemption in __bpf_get_stack
by Pu Lehui 17 Sep '26

17 Sep '26
From: Daniel Borkmann <borkmann(a)iogearbox.net> mainline inclusion from mainline-v7.3-rc1 commit b1a47b2708d4e95dbd23aee2ec83752190897b3f category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18901 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- get_perf_callchain() returns a per-CPU perf_callchain_entry buffer and releases its recursion slot via put_callchain_entry() before returning, so nothing keeps the entry reserved while __bpf_get_stack() consumes it below. A preemptible BPF program (e.g. a non-sleepable raw tracepoint program on a PREEMPT kernel, which runs under migrate_disable() but not preempt_disable()) can be scheduled out between obtaining the entry and the copy. Another task scheduled on the same CPU then reuses the same per-CPU buffer and overwrites trace->nr with a larger value. copy_len is then computed from the inflated trace->nr and can exceed the caller's buffer, causing an out-of-bounds write in the memcpy() and in the build_id path. The rcu_read_lock() taken here alone does not prevent this. It is only taken on the may_fault path, and under CONFIG_PREEMPT_RCU it does not disable preemption; it merely keeps perf's callchain buffer array alive (freed via call_rcu()) and does nothing to stop another task from reusing the entry. Disable preemption around obtaining the callchain entry and copying it into the caller's buffer, so the entry cannot be reused underneath us and trace->nr stays bounded by max_depth. Build ID resolution may fault and is therefore deferred until after preemption is re-enabled; by then the instruction pointers have already been copied into buf, so it operates only on that private copy. Note, preempt_disable() also subsumes the buffer-lifetime guarantee the rcu_read_lock() provided, since a preempt-disabled section is an RCU read-side critical section for the callchain buffers' call_rcu() reclaim. Fixes: c195651e565a ("bpf: add bpf_get_stack helper") Reported-by: Tao Chen <chen.dylane(a)linux.dev> Reported-by: STAR Labs SG <info(a)starlabs.sg> Signed-off-by: Daniel Borkmann <borkmann(a)iogearbox.net> Signed-off-by: Jiri Olsa <jolsa(a)kernel.org> Signed-off-by: Andrii Nakryiko <andrii(a)kernel.org> Cc: stable(a)vger.kernel.org Link: https://lore.kernel.org/bpf/20260803210149.296496-11-jolsa@kernel.org Closes: https://lore.kernel.org/bpf/20260206090653.1336687-1-chen.dylane@linux.dev/ [ changed Fixes: commit ] Conflicts: kernel/bpf/stackmap.c [not refactor to callchain_store and callchain_finalize] Signed-off-by: Pu Lehui <pulehui(a)huawei.com> --- kernel/bpf/stackmap.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index 0c3504e598e3..1f2547acf3d1 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c @@ -620,6 +620,7 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task, if (sysctl_perf_event_max_stack < max_depth) max_depth = sysctl_perf_event_max_stack; + preempt_disable(); if (trace_in) trace = trace_in; else if (kernel && task) @@ -627,16 +628,22 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task, else trace = get_perf_callchain(regs, 0, kernel, user, max_depth, crosstask, false); - if (unlikely(!trace)) + if (unlikely(!trace)) { + preempt_enable(); goto err_fault; + } - if (trace->nr < skip) + if (trace->nr < skip) { + preempt_enable(); goto err_fault; + } trace_nr = trace->nr - skip; trace_nr = (trace_nr <= num_elem) ? trace_nr : num_elem; copy_len = trace_nr * elem_size; + preempt_enable(); + ips = trace->ip + skip; if (user && user_build_id) stack_map_get_build_id_offset(buf, ips, trace_nr, user); -- 2.34.1
1 0
0 0
[PATCH OLK-6.6] bpf: Disable preemption in __bpf_get_stack
by Pu Lehui 17 Sep '26

17 Sep '26
From: Daniel Borkmann <borkmann(a)iogearbox.net> mainline inclusion from mainline-v7.3-rc1 commit b1a47b2708d4e95dbd23aee2ec83752190897b3f category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18901 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- get_perf_callchain() returns a per-CPU perf_callchain_entry buffer and releases its recursion slot via put_callchain_entry() before returning, so nothing keeps the entry reserved while __bpf_get_stack() consumes it below. A preemptible BPF program (e.g. a non-sleepable raw tracepoint program on a PREEMPT kernel, which runs under migrate_disable() but not preempt_disable()) can be scheduled out between obtaining the entry and the copy. Another task scheduled on the same CPU then reuses the same per-CPU buffer and overwrites trace->nr with a larger value. copy_len is then computed from the inflated trace->nr and can exceed the caller's buffer, causing an out-of-bounds write in the memcpy() and in the build_id path. The rcu_read_lock() taken here alone does not prevent this. It is only taken on the may_fault path, and under CONFIG_PREEMPT_RCU it does not disable preemption; it merely keeps perf's callchain buffer array alive (freed via call_rcu()) and does nothing to stop another task from reusing the entry. Disable preemption around obtaining the callchain entry and copying it into the caller's buffer, so the entry cannot be reused underneath us and trace->nr stays bounded by max_depth. Build ID resolution may fault and is therefore deferred until after preemption is re-enabled; by then the instruction pointers have already been copied into buf, so it operates only on that private copy. Note, preempt_disable() also subsumes the buffer-lifetime guarantee the rcu_read_lock() provided, since a preempt-disabled section is an RCU read-side critical section for the callchain buffers' call_rcu() reclaim. Fixes: c195651e565a ("bpf: add bpf_get_stack helper") Reported-by: Tao Chen <chen.dylane(a)linux.dev> Reported-by: STAR Labs SG <info(a)starlabs.sg> Signed-off-by: Daniel Borkmann <borkmann(a)iogearbox.net> Signed-off-by: Jiri Olsa <jolsa(a)kernel.org> Signed-off-by: Andrii Nakryiko <andrii(a)kernel.org> Cc: stable(a)vger.kernel.org Link: https://lore.kernel.org/bpf/20260803210149.296496-11-jolsa@kernel.org Closes: https://lore.kernel.org/bpf/20260206090653.1336687-1-chen.dylane@linux.dev/ [ changed Fixes: commit ] Conflicts: kernel/bpf/stackmap.c [not refactor to callchain_store and callchain_finalize] Signed-off-by: Pu Lehui <pulehui(a)huawei.com> --- kernel/bpf/stackmap.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index 2a4070d0b594..a30a136ea954 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c @@ -444,6 +444,7 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task, max_depth = stack_map_calculate_max_depth(size, elem_size, flags); + preempt_disable(); if (trace_in) { trace = trace_in; trace->nr = min_t(u32, trace->nr, max_depth); @@ -453,15 +454,21 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task, trace = get_perf_callchain(regs, 0, kernel, user, max_depth, crosstask, false); } - if (unlikely(!trace)) + if (unlikely(!trace)) { + preempt_enable(); goto err_fault; + } - if (trace->nr < skip) + if (trace->nr < skip) { + preempt_enable(); goto err_fault; + } trace_nr = trace->nr - skip; copy_len = trace_nr * elem_size; + preempt_enable(); + ips = trace->ip + skip; if (user && user_build_id) stack_map_get_build_id_offset(buf, ips, trace_nr, user); -- 2.34.1
1 0
0 0
[PATCH OLK-5.10] [Backport] ceph: bound copied dentry name length in NFS export get_name
by Chen Yuxi 17 Sep '26

17 Sep '26
From: Michael Bommarito <michael.bommarito(a)gmail.com> mainline inclusion from mainline-v7.3-rc1 commit eff8013c5a8916613c742ae5a2cc341cb605c0ae category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18968 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?… -------------------------------- ceph_get_name() copies the MDS-supplied name into the caller's NAME_MAX-sized buffer with memcpy(name, rinfo->dname, rinfo->dname_len) and then writes name[rinfo->dname_len] = 0, without checking dname_len against NAME_MAX. A malicious or buggy MDS that returns a LOOKUPNAME reply with dname_len > NAME_MAX overflows the buffer. __get_snap_name() copies rde->name / rde->name_len the same unchecked way. Impact: a malicious or compromised Ceph MDS overflows the NAME_MAX name buffer in a client's NFS-export get_name path, a slab out-of-bounds write reported by KASAN. Reachable when a CephFS mount is re-exported over NFS. Add ceph_export_copy_name(), which rejects lengths above NAME_MAX with -ENAMETOOLONG before the copy, and use it in both ceph_get_name() and __get_snap_name(). Cc: stable(a)vger.kernel.org Fixes: 19913b4eac4a ("ceph: add get_name() NFS export callback") Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Michael Bommarito <michael.bommarito(a)gmail.com> Reviewed-by: Viacheslav Dubeyko <slava(a)dubeyko.com> Signed-off-by: Ilya Dryomov <idryomov(a)gmail.com> Conflicts: fs/ceph/export.c [Downstream tree lacks the fscrypt support, so keep the tree's simpler (non-encrypted) get_name structure.] Signed-off-by: Chen Yuxi <chenyuxi19(a)huawei.com> --- fs/ceph/export.c | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 952a590dd4bc..54efb44fc89b 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -431,6 +431,16 @@ static struct dentry *ceph_fh_to_parent(struct super_block *sb, return dentry; } +static int ceph_export_copy_name(char *name, const char *src, u32 len) +{ + if (len > NAME_MAX) + return -ENAMETOOLONG; + + memcpy(name, src, len); + name[len] = '\0'; + return 0; +} + static int __get_snap_name(struct dentry *parent, char *name, struct dentry *child) { @@ -496,9 +506,8 @@ static int __get_snap_name(struct dentry *parent, char *name, BUG_ON(!rde->inode.in); if (ceph_snap(inode) == le64_to_cpu(rde->inode.in->snapid)) { - memcpy(name, rde->name, rde->name_len); - name[rde->name_len] = '\0'; - err = 0; + err = ceph_export_copy_name(name, rde->name, + rde->name_len); goto out; } } @@ -559,10 +568,11 @@ static int ceph_get_name(struct dentry *parent, char *name, if (!err) { struct ceph_mds_reply_info_parsed *rinfo = &req->r_reply_info; - memcpy(name, rinfo->dname, rinfo->dname_len); - name[rinfo->dname_len] = 0; - dout("get_name %p ino %llx.%llx name %s\n", - child, ceph_vinop(inode), name); + err = ceph_export_copy_name(name, rinfo->dname, + rinfo->dname_len); + if (!err) + dout("get_name %p ino %llx.%llx name %s\n", + child, ceph_vinop(d_inode(child)), name); } else { dout("get_name %p ino %llx.%llx err %d\n", child, ceph_vinop(inode), err); -- 2.34.1
1 0
0 0
[PATCH OLK-5.10] ceph: bound num_export_targets array for mds info v2/v3
by Pu Lehui 17 Sep '26

17 Sep '26
From: Michael Bommarito <michael.bommarito(a)gmail.com> mainline inclusion from mainline-v7.3-rc1 commit a3eb169ee297aa99670ba927c659990bd1e453f3 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/19003 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- ceph_mdsmap_decode() in fs/ceph/mdsmap.c reads num_export_targets from each per-mds info record and advances the decode cursor by num_export_targets * sizeof(u32) without first checking that many bytes remain. The only upper-bound check that catches a runaway cursor (*p > info_end) is gated on info_v >= 4, because info_end is left NULL for info_v 2 and 3. When the monitor sends an MDS map whose per-mds info version is 2 or 3 with an oversized num_export_targets, the cursor moves past the message front buffer and the later export-targets loop calls the unchecked ceph_decode_32() on out-of-bounds memory. A kernel client processes CEPH_MSG_MDS_MAP from its monitor session (net/ceph/mon_client.c dispatches it; fs/ceph/super.c routes it to ceph_mdsc_handle_mdsmap(), which sets end to the front buffer bound and calls ceph_mdsmap_decode()). A malicious or compromised monitor, or an on-path attacker on an unsigned/unencrypted messenger session, can therefore drive an out-of-bounds read in the client kernel; on x86_64 with KASAN it is reported as a slab-out-of-bounds read in ceph_mdsmap_decode(). The decoded values land in the internal info->export_targets[] array, so the consequence is a kernel out-of-bounds read, not an information leak to the attacker. Impact: a malicious or compromised Ceph monitor sending an MDS map with a per-mds info version of 2 or 3 and an oversized num_export_targets field triggers an out-of-bounds read in the CephFS client kernel. Add a ceph_decode_need() for the export-targets array before advancing the cursor, so the bound is enforced for every info_v >= 2, not only info_v >= 4. This mirrors the count-then-need idiom already used for m_data_pg_pools later in the same function. Compute the export-targets byte count with size_mul() and reuse that checked length when advancing the cursor, so the attacker-controlled num_export_targets multiplication fails closed on overflow rather than relying on the later kcalloc() guard. Cc: stable(a)vger.kernel.org Fixes: d463a43d69f4 ("ceph: CEPH_FEATURE_MDSENC support") Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Michael Bommarito <michael.bommarito(a)gmail.com> Reviewed-by: Viacheslav Dubeyko <slava(a)dubeyko.com> Signed-off-by: Ilya Dryomov <idryomov(a)gmail.com> Conflicts: fs/ceph/mdsmap.c [ctx conflicts] Signed-off-by: Pu Lehui <pulehui(a)huawei.com> --- fs/ceph/mdsmap.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/fs/ceph/mdsmap.c b/fs/ceph/mdsmap.c index 47f2903bacb9..05c25f1de6ad 100644 --- a/fs/ceph/mdsmap.c +++ b/fs/ceph/mdsmap.c @@ -3,6 +3,7 @@ #include <linux/bug.h> #include <linux/err.h> +#include <linux/overflow.h> #include <linux/random.h> #include <linux/slab.h> #include <linux/types.h> @@ -122,6 +123,7 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end) int err; u8 mdsmap_v; u16 mdsmap_ev; + size_t export_targets_len; m = kzalloc(sizeof(*m), GFP_NOFS); if (!m) @@ -219,8 +221,11 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end) *p += namelen; if (info_v >= 2) { ceph_decode_32_safe(p, end, num_export_targets, bad); + export_targets_len = size_mul(num_export_targets, + sizeof(u32)); + ceph_decode_need(p, end, export_targets_len, bad); pexport_targets = *p; - *p += num_export_targets * sizeof(u32); + *p += export_targets_len; } else { num_export_targets = 0; } -- 2.34.1
2 1
0 0
  • ← Newer
  • 1
  • 2
  • 3
  • 4
  • ...
  • 2479
  • Older →

HyperKitty Powered by HyperKitty