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
  • 24794 discussions
[PATCH OLK-6.6] null_blk: serialize configfs attribute stores with the lock
by Zhou Minqiang 17 Sep '26

17 Sep '26
mainline inclusion from mainline-v7.3-rc1 commit 7e7fff51808237703a3a1df6dd5cae1dfd1db86d category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/10007 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?… -------------------------------- The NULLB_DEVICE_ATTR _store takes no lock: apply_fn attributes (submit_queues, poll_queues) get dev->NAME written again after apply_fn returns, outside its lock; APPLY=NULL attributes are entirely lockless. configfs only serializes stores per-open-file, so concurrent stores on separate fds race. For apply_fn attributes, once one store's apply_fn has reconfigured the hardware, a second (losing) store can still overwrite dev->NAME afterwards. This leaves dev->submit_queues out of sync with the live queue count, which is later caught by the WARN_ON_ONCE() in null_map_queues(). For !apply_fn attributes, power_store()'s null_add_dev() validates and builds the device under "lock" but only sets CONFIGURED afterwards. A store slipping in during this window can change a field mid-setup -- for example, zone_nr_conv can be pushed above nr_zones after it has already been clamped, leading to an out-of-bounds dev->zones[] access. Take "lock" in the macro around the apply_fn call, the CONFIGURED test and the field write, and move it out of nullb_apply_submit_queues()/ nullb_apply_poll_queues() so both paths are covered once. This serializes stores with power_store's setup and with each other. Fixes: 45919fbfe1c4 ("null_blk: Enable modifying 'submit_queues' after an instance has been configured") Suggested-by: Bart Van Assche <bvanassche(a)acm.org> Signed-off-by: Zizhi Wo <wozizhi(a)huawei.com> Reviewed-by: Nilay Shroff <nilay(a)linux.ibm.com> Link: https://patch.msgid.link/20260725022509.714271-10-wozizhi@huaweicloud.com Signed-off-by: Jens Axboe <axboe(a)kernel.dk> Signed-off-by: Zhou Minqiang <zhouminqiang2(a)huawei.com> --- drivers/block/null_blk/main.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c index b42b0c3f3d59..7db8af00c468 100644 --- a/drivers/block/null_blk/main.c +++ b/drivers/block/null_blk/main.c @@ -331,6 +331,7 @@ nullb_device_##NAME##_store(struct config_item *item, const char *page, \ ret = nullb_device_##TYPE##_attr_store(&new_value, page, count);\ if (ret < 0) \ return ret; \ + guard(mutex)(&lock); \ if (apply_fn) \ ret = apply_fn(dev, new_value); \ else if (test_bit(NULLB_DEV_FL_CONFIGURED, &dev->flags)) \ @@ -392,25 +393,13 @@ static int nullb_update_nr_hw_queues(struct nullb_device *dev, static int nullb_apply_submit_queues(struct nullb_device *dev, unsigned int submit_queues) { - int ret; - - mutex_lock(&lock); - ret = nullb_update_nr_hw_queues(dev, submit_queues, dev->poll_queues); - mutex_unlock(&lock); - - return ret; + return nullb_update_nr_hw_queues(dev, submit_queues, dev->poll_queues); } static int nullb_apply_poll_queues(struct nullb_device *dev, unsigned int poll_queues) { - int ret; - - mutex_lock(&lock); - ret = nullb_update_nr_hw_queues(dev, dev->submit_queues, poll_queues); - mutex_unlock(&lock); - - return ret; + return nullb_update_nr_hw_queues(dev, dev->submit_queues, poll_queues); } NULLB_DEVICE_ATTR(size, ulong, NULL); -- 2.52.0
2 1
0 0
[PATCH OLK-6.6] md: Fix the null-ptr-deref of 'mddev->private' while submitting IO
by Zhou Minqiang 17 Sep '26

17 Sep '26
hulk inclusion category: bugfix bugzilla: https://atomgit.com/openeuler/kernel/issues/10008 Reference: https://lore.kernel.org/linux-raid/20260917024205.2331019-1-chengzhihao1@hu… -------------------------------- Concurrent processes md_stop and IO submitting could trigger a null-ptr-deref of 'mddev->private': BUG: kernel NULL pointer dereference, address: 0000000000000070 RIP: 0010:_wait_barrier+0x2f/0x250 Call Trace: raid1_make_request+0x150/0xf50 md_handle_request+0x104/0x530 md_submit_bio+0x76/0x130 submit_bio+0xdd/0x250 submit_bio_wait+0x1f/0x40 __blkdev_direct_IO_simple+0x1f6/0x370 blkdev_write_iter+0x3b2/0x520 ksys_write+0x7d/0x190 P1 fd = open(/dev/md0, O_RDWR) P2 (forked from P1, fd' <= fd) write(fd) submit_bio md_handle_request raid1_make_request raid1_write_request ioctl(fd, STOP_ARRAY) mddev_set_closing_and_sync_blockdev // check passed, mddev->openers = 1, // because md_open() is only called // once in P1->open do_md_stop __md_stop mddev->private = NULL conf = mddev->private // NULL wait_barrier(conf, sector) // null-ptr-deref ! It is a common problem for raid0/1/10/5, and __md_stop could be triggered by several paths(eg. ioctl, sysfs, ->dtr). Fix it by replacing mddev_lock() with mddev_suspend_and_lock() for all __md_stop() callers. The caller dm_table_destroy() is guaranteed being invoked with device suspended, so raid_dtr() could keep using mddev_lock_nointr(). Besides, fail the submitting IO in md_handle_request() if the 'mddev->pers' becomes NULL. Fetch a reproducer in https://bugzilla.kernel.org/show_bug.cgi?id=222020 Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Reported-by: syzbot+3fe892ea5fc292e1353f(a)syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=3fe892ea5fc292e1353f Signed-off-by: Zhihao Cheng <chengzhihao1(a)huawei.com> Signed-off-by: Zhou Minqiang <zhouminqiang2(a)huawei.com> --- drivers/md/md.c | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/drivers/md/md.c b/drivers/md/md.c index 2a32de5f5b64..60fd3494a527 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c @@ -404,6 +404,20 @@ bool md_handle_request(struct mddev *mddev, struct bio *bio) if (!percpu_ref_tryget_live(&mddev->active_io)) goto check_suspended; } + if (!mddev->pers) { + /* + * The __md_stop() sets 'mddev->private' to NULL during + * the IO submitting, check 'mddev->pers' before the IO + * being processed by specific driver to avoid the + * null-ptr-deref of 'mddev-><member>'. The check is + * safe because the IO has got the 'mddev->active_io' + * reference, and all __md_stop() callers will wait for + * the reference to be zero. + */ + bio_io_error(bio); + percpu_ref_put(&mddev->active_io); + return true; + } if (!mddev->pers->make_request(mddev, bio)) { percpu_ref_put(&mddev->active_io); if (!mddev->gendisk && mddev->pers->prepare_suspend) @@ -4543,6 +4557,8 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) { int err = 0; enum array_state st = match_word(buf, array_states); + unsigned int noio_flags = 0; + bool suspend = false; /* No lock dependent actions */ switch (st) { @@ -4552,9 +4568,11 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) case broken: /* cannot be set */ case bad_word: return -EINVAL; + case inactive: case clear: + suspend = true; + fallthrough; case readonly: - case inactive: case read_auto: if (!mddev->pers || !md_is_rdwr(mddev)) break; @@ -4588,9 +4606,11 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) spin_unlock(&mddev->lock); return err ?: len; } - err = mddev_lock(mddev); + err = suspend ? mddev_suspend_and_lock(mddev) : mddev_lock(mddev); if (err) return err; + if (suspend) + noio_flags = memalloc_noio_save(); switch (st) { case inactive: @@ -4661,7 +4681,12 @@ array_state_store(struct mddev *mddev, const char *buf, size_t len) mddev->hold_active = 0; sysfs_notify_dirent_safe(mddev->sysfs_state); } - mddev_unlock(mddev); + if (suspend) { + mddev_unlock_and_resume(mddev); + memalloc_noio_restore(noio_flags); + } else { + mddev_unlock(mddev); + } if (st == readonly || st == read_auto || st == inactive || (err && st == clear)) @@ -7750,6 +7775,7 @@ static bool md_ioctl_need_suspend(unsigned int cmd) case HOT_REMOVE_DISK: case SET_BITMAP_FILE: case SET_ARRAY_INFO: + case STOP_ARRAY: return true; default: return false; -- 2.52.0
2 1
0 0
[PATCH OLK-6.6] nvmet-tcp: bound SGL data length before allocating command buffers
by Yifan Qiao 17 Sep '26

17 Sep '26
From: Ibrahim Hashimov <security(a)auditcode.ai> mainline inclusion from mainline-v7.3-rc1 commit 4a3f00262a044e8e15064b1a6860968bf0500bf4 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18635 CVE: CVE-2026-80789 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?… -------------------------------- nvmet_tcp_map_data() reads the host-controlled 32-bit sgl->length and, for the in-capsule offset descriptor (type 0x01), checks it against port->inline_data_size before use. Any other SGL descriptor type -- including the non-inline transport SGL data-block descriptor (type (NVME_TRANSPORT_SGL_DATA_DESC << 4) | NVME_SGL_FMT_TRANSPORT_A, the type a real host uses for out-of-capsule writes) skips that check entirely and falls straight through to: cmd->req.sg = sgl_alloc(len, GFP_KERNEL, &cmd->req.sg_cnt); with len taken directly from the wire, unbounded up to 4 GiB. nvmet_req_init() only parses the command and never inspects sgl->length, and nvmet_check_transfer_len() -- the only other place transfer_len is validated -- runs later, from req->execute(), after the allocation has already happened. For a write command the target responds with an R2T and parks the command waiting for the host to send the data; if the host (or an unauthenticated peer that simply never follows up) never does, the sgl_alloc() buffer stays resident for the life of the command. NVMe/TCP has no mandatory authentication in the default configuration, so any peer able to reach the target portal and complete a Fabrics connect can drive this with a single crafted command, repeatable across queues and connections for amplification. This is unbounded kernel memory allocation triggered by a remote, effectively unauthenticated peer. Validate len against the same NVMET_TCP_MAXH2CDATA ceiling this file already uses to bound per-PDU H2C data, for every SGL descriptor type, before doing any allocation. This closes the gap for the non-inline descriptor while leaving the existing, tighter inline_data_size check in place for the in-capsule case. Runtime-verified on a v6.19 KASAN stand: with this bound in place, a crafted write command carrying an oversized non-inline SGL length is rejected before sgl_alloc() runs, where the same request previously drove an unbounded ~256 MiB kernel allocation (up to 4 GiB) that stayed resident pending an R2T the host never satisfies. Fixes: 872d26a391da ("nvmet-tcp: add NVMe over TCP target driver") Cc: stable(a)vger.kernel.org Reviewed-by: Christoph Hellwig <hch(a)lst.de> Signed-off-by: Ibrahim Hashimov <security(a)auditcode.ai> Assisted-by: AuditCode-AI:2026.07 Signed-off-by: Keith Busch <kbusch(a)kernel.org> Signed-off-by: Yifan Qiao <qiaoyifan4(a)huawei.com> --- drivers/nvme/target/tcp.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/nvme/target/tcp.c b/drivers/nvme/target/tcp.c index 85dfec2adb26..a5a4443241cd 100644 --- a/drivers/nvme/target/tcp.c +++ b/drivers/nvme/target/tcp.c @@ -417,6 +417,19 @@ static int nvmet_tcp_map_data(struct nvmet_tcp_cmd *cmd) if (!len) return 0; + /* + * inline_data_size only bounds the in-capsule (type 0x01) SGL + * descriptor below. A non-inline transport SGL data-block + * descriptor skips that check entirely and would otherwise reach + * sgl_alloc() with an attacker-controlled len of up to 4 GiB, + * pinning that much kernel memory for a command that may never + * complete. Bound every descriptor type here, before allocating + * anything, using the same ceiling this file already applies to + * per-PDU H2C data. + */ + if (len > NVMET_TCP_MAXH2CDATA) + return NVME_SC_SGL_INVALID_DATA | NVME_SC_DNR; + if (sgl->type == ((NVME_SGL_FMT_DATA_DESC << 4) | NVME_SGL_FMT_OFFSET)) { if (!nvme_is_write(cmd->req.cmd)) -- 2.52.0
2 1
0 0
[PATCH openEuler-1.0-LTS 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 | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index a41858db1441..aefa036c9a91 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,12 +485,16 @@ 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; @@ -500,6 +505,8 @@ BPF_CALL_4(bpf_get_stack, struct pt_regs *, regs, void *, buf, u32, size, else memcpy(buf, ips, copy_len); + preempt_enable(); + if (size > copy_len) memset(buf + copy_len, 0, size - copy_len); return copy_len; -- 2.34.1
2 1
0 0
[PATCH OLK-6.6 v3] 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..e496da6e5ddf 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,11 +454,15 @@ 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; @@ -468,6 +473,8 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task, else memcpy(buf, ips, copy_len); + preempt_enable(); + if (size > copy_len) memset(buf + copy_len, 0, size - copy_len); return copy_len; -- 2.34.1
2 1
0 0
[PATCH OLK-5.10 v3] 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..30fd2bd4a997 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,11 +628,15 @@ 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; @@ -643,6 +648,8 @@ static long __bpf_get_stack(struct pt_regs *regs, struct task_struct *task, else memcpy(buf, ips, copy_len); + preempt_enable(); + if (size > copy_len) memset(buf + copy_len, 0, size - copy_len); return copy_len; -- 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> Conflicts: fs/ceph/export.c [ctx conflict] 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
2 1
0 0
[PATCH OLK-5.10] smb: client: fix OOB read/write from unvalidated DataOffset in coalesce_t2()
by Yifan Qiao 17 Sep '26

17 Sep '26
From: Frank Sorenson <sorenson(a)redhat.com> mainline inclusion from mainline-v7.3-rc1 commit 6343c1da561962688f203362d80d6a3bfa39fa1b category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18919 CVE: CVE-2026-89633 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id… -------------------------------- coalesce_t2() computes data pointers directly from server-supplied DataOffset fields with no validation against buffer bounds: data_area_of_tgt = (char *)&pSMBt->hdr.Protocol + get_unaligned_le16(&pSMBt->t2_rsp.DataOffset); data_area_of_src = (char *)&pSMBs->hdr.Protocol + get_unaligned_le16(&pSMBs->t2_rsp.DataOffset); data_area_of_tgt += total_in_tgt; ... memcpy(data_area_of_tgt, data_area_of_src, total_in_src); A small DataOffset can push a pointer below the actual byte area, overwriting header fields; a large one can push it past the buffer end, causing out-of-bounds heap reads (source) or writes (target). The BCC overflow guard does not prevent this: BCC reflects how much data is present, while DataOffset controls where in the buffer it starts. The "validate target area" comment present since the function was first written in 2005 was a placeholder that was never implemented. Add lower- and upper-bound checks for both data pointers before the memcpy, and before any target header fields are modified. Fixes: e4eb295d38b5 ("[PATCH] cifs: Handle multiple response transact2 part 1 of 2") Cc: stable(a)vger.kernel.org Reported-by: Shen Yongchao <grayhat(a)foxmail.com> Signed-off-by: Frank Sorenson <sorenson(a)redhat.com> Signed-off-by: Namjae Jeon <linkinjeon(a)kernel.org> Signed-off-by: Paulo Alcantara <pc(a)manguebit.org> Conflicts: fs/cifs/smb1ops.c fs/smb/client/smb1ops.c [different files] Signed-off-by: Yifan Qiao <qiaoyifan4(a)huawei.com> --- fs/cifs/smb1ops.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/fs/cifs/smb1ops.c b/fs/cifs/smb1ops.c index e540908bae43..6bcd2805cead 100644 --- a/fs/cifs/smb1ops.c +++ b/fs/cifs/smb1ops.c @@ -324,6 +324,26 @@ coalesce_t2(char *second_buf, struct smb_hdr *target_hdr) data_area_of_tgt += total_in_tgt; + /* + * DataOffset fields are server-supplied and not validated against + * buffer bounds; check both data pointers before mutating the + * target header. + */ + if (data_area_of_tgt < (char *)target_hdr + + sizeof(struct smb_t2_rsp) + sizeof(__le16) || + data_area_of_tgt + total_in_src > + (char *)target_hdr + CIFSMaxBufSize + MAX_CIFS_HDR_SIZE) { + cifs_dbg(VFS, "%s: target data area out of bounds\n", __func__); + return -EPROTO; + } + if (data_area_of_src < second_buf + + sizeof(struct smb_t2_rsp) + sizeof(__le16) || + data_area_of_src + total_in_src > + second_buf + smbCalcSize((struct smb_hdr *)second_buf, NULL)) { + cifs_dbg(VFS, "%s: secondary data area out of bounds\n", __func__); + return -EPROTO; + } + total_in_tgt += total_in_src; /* is the result too big for the field? */ if (total_in_tgt > USHRT_MAX) { -- 2.52.0
2 1
0 0
[PATCH OLK-5.10] smb: client: clear ce->tgthint in free_tgts()
by Yifan Qiao 17 Sep '26

17 Sep '26
From: Fredric Cover <fredric.cover.lkernel(a)gmail.com> mainline inclusion from mainline-v7.3-rc1 commit b1b741cf8e7ce1b91d937e23decd3d3358748700 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/18921 CVE: CVE-2026-89636 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?… -------------------------------- When free_tgts() frees all structures in ce->tlist, ce->tgthint is left pointing to one of the freed cache_dfs_tgt structures. If ce->tgthint is not reset before it is used later, it results in a use-after-free. Set ce->tgthint to NULL in free_tgts() after the elements are freed to reflect that no elements remain. Fixes: 54be1f6c1c37 ("cifs: Add DFS cache routines") Cc: stable(a)vger.kernel.org # depends on: smb: client: harden DFS cache against invalid target hints Signed-off-by: Fredric Cover <fredric.cover.lkernel(a)gmail.com> Reviewed-by: ChenXiaoSong <chenxiaosong(a)kylinos.cn> Signed-off-by: Namjae Jeon <linkinjeon(a)kernel.org> Signed-off-by: Paulo Alcantara <pc(a)manguebit.org> Conflicts: fs/cifs/dfs_cache.c fs/smb/client/dfs_cache.c [different files] Signed-off-by: Yifan Qiao <qiaoyifan4(a)huawei.com> --- fs/cifs/dfs_cache.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/cifs/dfs_cache.c b/fs/cifs/dfs_cache.c index b83932175c83..9bdc9918b12e 100644 --- a/fs/cifs/dfs_cache.c +++ b/fs/cifs/dfs_cache.c @@ -118,6 +118,8 @@ static inline void free_tgts(struct cache_entry *ce) kfree(t->name); kfree(t); } + + WRITE_ONCE(ce->tgthint, NULL); } static inline void flush_cache_ent(struct cache_entry *ce) -- 2.52.0
2 2
0 0
[PATCH openEuler-1.0-LTS] 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 CVE: CVE-2026-89652 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 __get_snap_name() function and fscrypt support, so only the ceph_export_copy_name() helper and the ceph_get_name() change were applied while keeping the tree's simpler (non-encrypted) get_name structure.] Signed-off-by: Chen Yuxi <chenyuxi19(a)huawei.com> --- fs/ceph/export.c | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/fs/ceph/export.c b/fs/ceph/export.c index 3c59ad180ef0..1d087cf1770c 100644 --- a/fs/ceph/export.c +++ b/fs/ceph/export.c @@ -194,6 +194,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 ceph_get_name(struct dentry *parent, char *name, struct dentry *child) { @@ -221,10 +231,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(d_inode(child)), 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(d_inode(child)), err); -- 2.34.1
2 1
0 0
  • ← Newer
  • 1
  • 2
  • 3
  • 4
  • ...
  • 2480
  • Older →

HyperKitty Powered by HyperKitty