5.10.269-rc1 review
Greg Kroah-Hartman
maintainercover 5.10.269-rc1 review
This is the start of the stable review cycle for the 5.10.269 release. There are 43 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 02 Sep 2026 13:32:19 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.269-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 5.10.269-rc1
Miguel Peñaranda <[email protected]>
usb: usbfs: fix use-after-free of usb_device in usbdev_release()
Shuangpeng Bai <[email protected]>
USB: c67x00: fix use-after-free in c67x00_add_iso_urb()
Johan Hovold <[email protected]>
USB: serial: spcp8x5: drop broken carrier detect support
Jiale Yao <[email protected]>
USB: serial: option: fix slab OOB read in interrupt URB callback
Marouane El Moufid <[email protected]>
ALSA: usb-audio: fix OOB write in snd_usbmidi_novation_output()
Griffin Kroah-Hartman <[email protected]>
usb: core: Strengthen error handling in hub_hub_status()
Griffin Kroah-Hartman <[email protected]>
usb: core: Add lock to usb_wakeup_notification()
Christian Borntraeger <[email protected]>
KVM: s390: vsie: zero stale crypto bits
Thorsten Blum <[email protected]>
crypto: mxs-dcp - fix source scatterlist length access
Thorsten Blum <[email protected]>
crypto: atmel-tdes - use scatterlist length before DMA mapping
Eric Biggers <[email protected]>
mm/swap: reject swapon() on filesystem-level encrypted files
Kyle Zeng <[email protected]>
ipv6: seg6: clear IPv4 control block on IPIP decapsulation
Zihan Xi <[email protected]>
xfrm: fix xfrm_state_construct() auth-trunc leak
Asim Viladi Oglu Manizada <[email protected]>
xfrm: ah6: validate routing header segments_left
Zhiling Zou <[email protected]>
xfrm: drop ESP-in-TCP packets with no ingress device
Sabrina Dubroca <[email protected]>
xfrm: espintcp: fix UAF during close
Shuangpeng Bai <[email protected]>
usb: gadget: f_tcm: keep port count until LUN teardown completes
Aleksandr Nogikh <[email protected]>
usb: usbtest: disable dynamic ID support
Haoxiang Li <[email protected]>
accessibility: speakup: unregister tty ldisc on later init failures
Griffin Kroah-Hartman <[email protected]>
fpga: dfl: fme: add error handling
Jose Villaseñor Montfort <[email protected]>
HID: input: read battery capacity from its actual report offset
Ibrahim Hashimov <[email protected]>
nvmet-tcp: bound SGL data length before allocating command buffers
Bryam Vargas <[email protected]>
nfc: nci: add data_len bound checks to activation parameter extractors
Jose Villaseñor Montfort <[email protected]>
HID: magicmouse: do not keep a stale msc->input if no input is claimed
Samuel Page <[email protected]>
nfc: nci: fix uninit-value in the RF discover/activated NTF handlers
Ryusuke Konishi <[email protected]>
nilfs2: reject invalid block index in GC ioctl
Guanghui Yang <[email protected]>
ext4: propagate errors from fast commit range replay
Tetsuo Handa <[email protected]>
kcov: fix data corruption and race conditions on PREEMPT_RT
Eric Dumazet <[email protected]>
ipv4: igmp: Fix potential UAF in igmp_gq_start_timer()
Sasha Levin <[email protected]>
Revert "smb: client: use kvzalloc() for megabyte buffer in simple fallocate"
Sasha Levin <[email protected]>
Revert "mtd: maps: vmu-flash: fix fault in unaligned fixup"
Stephen Smalley <[email protected]>
selinux: switch two allocations to use kzalloc_objs()
Sasha Levin <[email protected]>
Revert "PM: sleep: Use complete() in device_pm_sleep_init()"
Jiayuan Chen <[email protected]>
bpf: Fix use-after-free in offloaded map/prog info fill
Oliver Upton <[email protected]>
KVM: arm64: Prevent access to vCPU events before init
Vasiliy Kovalev <[email protected]>
jfs: add check read-only before txBeginAnon() call
Vasiliy Kovalev <[email protected]>
jfs: add check read-only before truncation in jfs_truncate_nolock()
Sebastian Andrzej Siewior <[email protected]>
bpf: Remove tst_run from lwt_seg6local_prog_ops.
Vishnu Razdan <[email protected]>
io_uring/io-wq: fix worker accounting when canceling creation callbacks
Florian Westphal <[email protected]>
ipvs: reload ip header after head reallocation
Eric Biggers <[email protected]>
ext4: don't enable DAX on new encrypted files
Ido Schimmel <[email protected]>
ipv6: mcast: Fix use-after-free when processing MLD queries
Peiyang He <[email protected]>
RDMA/rxe: Fix OOB in free_rd_atomic_resources()
-------------
Diffstat:
Documentation/filesystems/fscrypt.rst | 4 ++ Makefile | 4 +- arch/arm64/kvm/arm.c | 6 ++ arch/s390/kvm/vsie.c | 1 + drivers/accessibility/speakup/main.c | 1 + drivers/base/power/main.c | 6 +- drivers/crypto/atmel-tdes.c | 5 +- drivers/crypto/mxs-dcp.c | 2 +- drivers/fpga/dfl-fme-perf.c | 2 + drivers/hid/hid-input.c | 17 +++-- drivers/hid/hid-magicmouse.c | 10 +++ drivers/infiniband/sw/rxe/rxe_qp.c | 3 +- drivers/mtd/maps/vmu-flash.c | 8 ++- drivers/nvme/target/tcp.c | 13 ++++ drivers/target/target_core_fabric_configfs.c | 8 +++ drivers/usb/c67x00/c67x00-sched.c | 4 +- drivers/usb/core/devio.c | 2 +- drivers/usb/core/hub.c | 7 ++- drivers/usb/gadget/function/f_tcm.c | 2 +- drivers/usb/misc/usbtest.c | 1 + drivers/usb/serial/option.c | 20 +++++- drivers/usb/serial/spcp8x5.c | 13 ---- fs/cifs/smb2ops.c | 4 +- fs/ext4/fast_commit.c | 10 ++- fs/ext4/ialloc.c | 4 ++ fs/ext4/super.c | 40 ++++++------ fs/jfs/inode.c | 2 +- fs/jfs/jfs_extent.c | 10 +++ fs/nilfs2/ioctl.c | 21 ++++++- include/linux/hid.h | 1 + include/linux/inetdevice.h | 5 ++ include/linux/sched.h | 8 +++ include/target/target_core_fabric.h | 2 + io_uring/io-wq.c | 9 ++- kernel/bpf/offload.c | 10 ++- kernel/kcov.c | 93 ++++++++++++++-------------- lib/Kconfig.debug | 5 +- mm/swapfile.c | 7 +++ net/core/filter.c | 1 - net/ipv4/igmp.c | 14 +++-- net/ipv6/ah6.c | 29 +++++---- net/ipv6/mcast.c | 8 +-- net/ipv6/seg6_local.c | 7 +++ net/netfilter/ipvs/ip_vs_xmit.c | 6 +- net/nfc/nci/ntf.c | 32 ++++++++-- net/xfrm/espintcp.c | 9 ++- net/xfrm/xfrm_user.c | 2 +- security/selinux/ss/conditional.c | 12 ++-- sound/usb/midi.c | 2 + 49 files changed, 326 insertions(+), 166 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/43 RDMA/rxe: Fix OOB in free_rd_atomic_resources()
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peiyang He <[email protected]>
commit de329533792a373186d79dca1ca120f8fa0afd05 upstream.
free_rd_atomic_resources() iterates using qp->attr.max_dest_rd_atomic. Updating max_dest_rd_atomic before freeing the old array can make the free path walk past the old allocation and trigger a slab out-of-bounds write catched by KASAN:
==================================================================
BUG: KASAN: slab-out-of-bounds in free_rd_atomic_resource drivers/infiniband/sw/rxe/rxe_qp.c:180 [inline] BUG: KASAN: slab-out-of-bounds in free_rd_atomic_resources drivers/infiniband/sw/rxe/rxe_qp.c:171 [inline] BUG: KASAN: slab-out-of-bounds in free_rd_atomic_resources drivers/infiniband/sw/rxe/rxe_qp.c:163 [inline] BUG: KASAN: slab-out-of-bounds in rxe_qp_from_attr+0x1e88/0x2150 drivers/infiniband/sw/rxe/rxe_qp.c:712 Write of size 4 at addr ffff88802b8dddb8 by task syz.3.451/11063 CPU: 0 UID: 0 PID: 11063 Comm: syz.3.451 Not tainted 7.1.0 #2 PREEMPT(full) Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 Call Trace: <TASK> __dump_stack lib/dump_stack.c:94 [inline] dump_stack_lvl+0x10e/0x1f0 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:378 [inline] print_report+0xf7/0x600 mm/kasan/report.c:482 kasan_report+0xe4/0x120 mm/kasan/report.c:595 free_rd_atomic_resource drivers/infiniband/sw/rxe/rxe_qp.c:180 [inline] free_rd_atomic_resources drivers/infiniband/sw/rxe/rxe_qp.c:171 [inline] free_rd_atomic_resources drivers/infiniband/sw/rxe/rxe_qp.c:163 [inline] rxe_qp_from_attr+0x1e88/0x2150 drivers/infiniband/sw/rxe/rxe_qp.c:712 rxe_modify_qp+0x1e2/0x530 drivers/infiniband/sw/rxe/rxe_verbs.c:623 ib_security_modify_qp+0x223/0xfa0 drivers/infiniband/core/security.c:625 _ib_modify_qp+0x333/0xec0 drivers/infiniband/core/verbs.c:1915 modify_qp+0x13ca/0x1940 drivers/infiniband/core/uverbs_cmd.c:1932 ib_uverbs_modify_qp+0xcb/0x120 drivers/infiniband/core/uverbs_cmd.c:1958 ib_uverbs_write+0xb86/0x1030 drivers/infiniband/core/uverbs_main.c:680 vfs_write+0x2aa/0x1070 fs/read_write.c:686 ksys_write+0x1f8/0x250 fs/read_write.c:740 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0x116/0x800 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7fefc75a70cd Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007fefc8495018 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 00007fefc7835fa0 RCX: 00007fefc75a70cd RDX: 0000000000000078 RSI: 0000200000000240 RDI: 0000000000000007 RBP: 00007fefc764f10f R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 00007fefc7836038 R14: 00007fefc7835fa0 R15: 00007ffcf0586aa0 </TASK> Allocated by task 11063: kasan_save_stack+0x33/0x60 mm/kasan/common.c:57 kasan_save_track+0x14/0x30 mm/kasan/common.c:78 poison_kmalloc_redzone mm/kasan/common.c:398 [inline] __kasan_kmalloc+0xaa/0xb0 mm/kasan/common.c:415 kasan_kmalloc include/linux/kasan.h:263 [inline] __do_kmalloc_node mm/slub.c:5296 [inline] __kmalloc_noprof+0x32a/0x850 mm/slub.c:5308 kmalloc_noprof include/linux/slab.h:954 [inline] kzalloc_noprof include/linux/slab.h:1188 [inline] alloc_rd_atomic_resources drivers/infiniband/sw/rxe/rxe_qp.c:155 [inline] rxe_qp_from_attr+0x3f8/0x2150 drivers/infiniband/sw/rxe/rxe_qp.c:714 rxe_modify_qp+0x1e2/0x530 drivers/infiniband/sw/rxe/rxe_verbs.c:623 ib_security_modify_qp+0x223/0xfa0 drivers/infiniband/core/security.c:625 _ib_modify_qp+0x333/0xec0 drivers/infiniband/core/verbs.c:1915 modify_qp+0x13ca/0x1940 drivers/infiniband/core/uverbs_cmd.c:1932 ib_uverbs_modify_qp+0xcb/0x120 drivers/infiniband/core/uverbs_cmd.c:1958 ib_uverbs_write+0xb86/0x1030 drivers/infiniband/core/uverbs_main.c:680 vfs_write+0x2aa/0x1070 fs/read_write.c:686 ksys_write+0x1f8/0x250 fs/read_write.c:740 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0x116/0x800 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f The buggy address belongs to the object at ffff88802b8ddd80 which belongs to the cache kmalloc-64 of size 64
The buggy address is located 0 bytes to the right of
allocated 56-byte region [ffff88802b8ddd80, ffff88802b8dddb8)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x2b8dd
flags: 0xfff00000000000(node=0|zone=1|lastcpupid=0x7ff)
page_type: f5(slab)
raw: 00fff00000000000 ffff888015c418c0 dead000000000100 dead000000000122
raw: 0000000000000000 0000000800200020 00000000f5000000 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as allocated
page last allocated via order 0, migratetype Unmovable, gfp_mask 0xd2c40(GFP_NOFS|__GFP_NOWARN|__GFP_NORETRY|__GFP_COMP|__GFP_NOMEMALLOC), pid 4651, tgid 4651 ((udev-worker)), ts 123427165316, free_ts 123425874255
set_page_owner include/linux/page_owner.h:32 [inline]
post_alloc_hook+0xfc/0x120 mm/page_alloc.c:1853
prep_new_page mm/page_alloc.c:1861 [inline]
get_page_from_freelist+0x75b/0x3220 mm/page_alloc.c:3941
__alloc_frozen_pages_noprof+0x27e/0x2b00 mm/page_alloc.c:5221
alloc_slab_page mm/slub.c:3278 [inline]
allocate_slab mm/slub.c:3467 [inline]
new_slab+0xa6/0x670 mm/slub.c:3525
refill_objects+0x278/0x420 mm/slub.c:7272
refill_sheaf mm/slub.c:2816 [inline]
__pcs_replace_empty_main+0x2ed/0x640 mm/slub.c:4652
alloc_from_pcs mm/slub.c:4750 [inline]
slab_alloc_node mm/slub.c:4884 [inline]
__do_kmalloc_node mm/slub.c:5295 [inline]
__kmalloc_noprof+0x68d/0x850 mm/slub.c:5308
kmalloc_noprof include/linux/slab.h:954 [inline]
kzalloc_noprof include/linux/slab.h:1188 [inline]
tomoyo_encode2+0x100/0x3e0 security/tomoyo/realpath.c:45
tomoyo_encode+0x29/0x50 security/tomoyo/realpath.c:80
tomoyo_realpath_from_path+0x18c/0x690 security/tomoyo/realpath.c:283
tomoyo_get_realpath security/tomoyo/file.c:151 [inline]
tomoyo_check_open_permission+0x2ab/0x3c0 security/tomoyo/file.c:776
tomoyo_file_open+0x6b/0x90 security/tomoyo/tomoyo.c:334
security_file_open+0x7a/0x1b0 security/security.c:2739
do_dentry_open+0x57e/0x1690 fs/open.c:924
vfs_open+0x82/0x3f0 fs/open.c:1079
do_open fs/namei.c:4699 [inline]
path_openat+0x218a/0x3190 fs/namei.c:4858
page last free pid 1 tgid 1 stack trace:
reset_page_owner include/linux/page_owner.h:25 [inline]
__free_pages_prepare mm/page_alloc.c:1397 [inline]
__free_frozen_pages+0x763/0xfc0 mm/page_alloc.c:2938
selinux_genfs_get_sid security/selinux/hooks.c:1364 [inline]
inode_doinit_with_dentry+0x903/0x1320 security/selinux/hooks.c:1563
selinux_d_instantiate+0x26/0x30 security/selinux/hooks.c:6658
security_d_instantiate+0x123/0x190 security/security.c:3704
d_splice_alias_ops+0x92/0x850 fs/dcache.c:3141
kernfs_iop_lookup+0x23f/0x2d0 fs/kernfs/dir.c:1289
lookup_open.isra.0+0x659/0x1080 fs/namei.c:4484
open_last_lookups fs/namei.c:4611 [inline]
path_openat+0x17dd/0x3190 fs/namei.c:4855
do_file_open+0x20c/0x430 fs/namei.c:4887
do_sys_openat2+0x101/0x1d0 fs/open.c:1364
do_sys_open fs/open.c:1370 [inline]
__do_sys_openat fs/open.c:1386 [inline]
__se_sys_openat fs/open.c:1381 [inline]
__x64_sys_openat+0x141/0x200 fs/open.c:1381
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x116/0x800 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Memory state around the buggy address:
ffff88802b8ddc80: 00 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc
ffff88802b8ddd00: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
>ffff88802b8ddd80: 00 00 00 00 00 00 00 fc fc fc fc fc fc fc fc fc
^
ffff88802b8dde00: 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc fc
ffff88802b8dde80: 00 00 00 00 00 fc fc fc fc fc fc fc fc fc fc fcFix the OOB by moving the assignment after free_rd_atomic_resources() so the old array is freed using the old bound. This matches the original ordering in commit 8700e3e7c485 ("Soft RoCE driver").
--- drivers/infiniband/sw/rxe/rxe_qp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/infiniband/sw/rxe/rxe_qp.c +1 -2
@@ -580,10 +580,9 @@ int rxe_qp_from_attr(struct rxe_qp *qp, struct ib_qp_attr *attr, int mask,int max_dest_rd_atomic = attr->max_dest_rd_atomic ?roundup_pow_of_two (attr->max_dest_rd_atomic) :0 ; - qp->attr.max_dest_rd_atomic = max_dest_rd_atomic; -free_rd_atomic_resources (qp); + qp->attr.max_dest_rd_atomic = max_dest_rd_atomic; err =alloc_rd_atomic_resources (qp, max_dest_rd_atomic);if (err)return err;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 2/43 ipv6: mcast: Fix use-after-free when processing MLD queries
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
commit 791c91dc7a9dfb2457d5e29b8216a6484b9c4b40 upstream.
When processing an MLD query, a pointer to the multicast group address is retrieved when initially parsing the packet. This pointer is later dereferenced without being reloaded despite the fact that the skb header might have been reallocated following the pskb_may_pull() calls, leading to a use-after-free [1].
Fix by copying the multicast group address when the packet is initially parsed.
[1]
BUG: KASAN: slab-use-after-free in __mld_query_work (net/ipv6/mcast.c:1512) Read of size 8 at addr ffff8881154b8e90 by task kworker/4:1/118 Workqueue: mld mld_query_work Call Trace: <TASK> dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
print_address_description.constprop.0 (mm/kasan/report.c:378) print_report (mm/kasan/report.c:482)kasan_report (mm/kasan/report.c:595)__mld_query_work (net/ipv6/mcast.c:1512) mld_query_work (net/ipv6/mcast.c:1563) process_one_work (kernel/workqueue.c:3314) worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478) kthread (kernel/kthread.c:436)ret_from_fork (arch/x86/kernel/process.c:158) ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
</TASK>
[...]
Freed by task 118: kasan_save_stack (mm/kasan/common.c:57) kasan_save_track (mm/kasan/common.c:78) kasan_save_free_info (mm/kasan/generic.c:584) __kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285) kfree (./include/linux/kasan.h:235 mm/slub.c:2689 mm/slub.c:6251 mm/slub.c:6566) pskb_expand_head (net/core/skbuff.c:2335) __pskb_pull_tail (net/core/skbuff.c:2878 (discriminator 4)) __mld_query_work (net/ipv6/mcast.c:1495 (discriminator 1))
mld_query_work (net/ipv6/mcast.c:1563) process_one_work (kernel/workqueue.c:3314) worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478) kthread (kernel/kthread.c:436)ret_from_fork (arch/x86/kernel/process.c:158) ret_from_fork_asm (arch/x86/entry/entry_64.S:245)
--- net/ipv6/mcast.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/ipv6/mcast.c +4 -4
@@ -1414,9 +1414,9 @@ void igmp6_event_query(struct sk_buff *skb)static void __mld_query_work (struct sk_buff *skb) {struct mld2_query *mlh2 =NULL ; -const struct in6_addr *group;unsigned long max_delay;struct inet6_dev *idev; +struct in6_addr group;struct ifmcaddr6 *ma;struct mld_msg *mld;int group_type;
@@ -1448,8 +1448,8 @@ static void __mld_query_work(struct sk_buff *skb) goto kfree_skb; mld = (struct mld_msg *)icmp6_hdr (skb); - group = &mld->mld_mca; - group_type =ipv6_addr_type (group); + group = mld->mld_mca; + group_type =ipv6_addr_type (&group);if (group_type !=IPV6_ADDR_ANY && !(group_type&IPV6_ADDR_MULTICAST ))
@@ -1501,7 +1501,7 @@ static void __mld_query_work(struct sk_buff *skb) } }else {for_each_mc_mclock (idev, ma) { -if (!ipv6_addr_equal (group, &ma->mca_addr)) +if (!ipv6_addr_equal (&group, &ma->mca_addr))continue ;if (ma->mca_flags &MAF_TIMER_RUNNING ) {/* gsquery <- gsquery && mark */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 3/43 ext4: dont enable DAX on new encrypted files
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers <[email protected]>
commit da32af420d6d466e247c43ac0b829edeac7ae0ad upstream.
Currently, when a new encrypted regular file is created, the call to ext4_set_inode_flags(inode, init=true) in __ext4_new_inode() is made before EXT4_INODE_ENCRYPT is set. As a result, it can set S_DAX if the filesystem is mounted with "-o dax=always".
EXT4_INODE_ENCRYPT then actually gets set a bit later in __ext4_new_inode(), when it calls fscrypt_set_context() which calls ext4_set_context(). ext4_set_context() sets EXT4_INODE_ENCRYPT and calls ext4_set_inode_flags(inode, init=false) to set S_ENCRYPTED too.
This was intended to clear S_DAX as well. However, this was broken by commit 043546e46dc7 ("fs/ext4: Only change S_DAX on inode load"). This causes data written to the file to bypass encryption, also causing xfstests failures such as generic/548 (when "-o dax=always" is used).
Fix this by simplifying the flow by making __ext4_new_inode() set EXT4_INODE_ENCRYPT earlier. This makes it take effect in ext4_set_inode_flags(inode, init=true), making S_DAX never be set.
Similarly, make EXT4_STATE_MAY_INLINE_DATA never be set in the first place on new encrypted inodes. Then it doesn't need to be cleared.
As a result of these simplifications, ext4_set_context() no longer needs to change inode flags or state when 'handle != NULL'. Remove that too.
--- fs/ext4/ialloc.c | 4 ++++ fs/ext4/super.c | 40 ++++++++++++++++++++-------------------- 2 files changed, 24 insertions(+), 20 deletions(-)
fs/ext4/ialloc.c +4 -0
@@ -994,6 +994,8 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir, err =fscrypt_prepare_new_inode (dir, inode, &encrypt);if (err) goto out; +if (encrypt) + i_flags |=EXT4_ENCRYPT_FL ; } err =dquot_initialize (inode);
@@ -1307,6 +1309,8 @@ struct inode *__ext4_new_inode(handle_t *handle, struct inode *dir, ei->i_extra_isize = sbi->s_want_extra_isize; ei->i_inline_off =0 ;if (ext4_has_feature_inline_data (sb) && +/* Encrypted inodes cannot have inline data */ + !(ei->i_flags &EXT4_ENCRYPT_FL ) && (!(ei->i_flags &EXT4_DAX_FL ) ||S_ISDIR (mode)))ext4_set_inode_state (inode,EXT4_STATE_MAY_INLINE_DATA ); ret = inode;
fs/ext4/super.c +20 -20
@@ -1494,7 +1494,13 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,if (inode->i_ino ==EXT4_ROOT_INO )return -EPERM ; -if (WARN_ON_ONCE (IS_DAX (inode) &&i_size_read (inode))) +/* +* For new encrypted inodes, S_DAX is never set in the first place. +* +* For existing inodes, this is called only on empty directories. ext4 +* never sets S_DAX on directories. +*/ +if (WARN_ON_ONCE (IS_DAX (inode)))return -EINVAL ;if (ext4_test_inode_flag (inode,EXT4_INODE_DAX ))
@@ -1513,21 +1519,18 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,*/ if (handle) { - res =ext4_xattr_set_handle (handle, inode, -EXT4_XATTR_INDEX_ENCRYPTION , -EXT4_XATTR_NAME_ENCRYPTION_CONTEXT , - ctx, len,0 ); -if (!res) { -ext4_set_inode_flag (inode,EXT4_INODE_ENCRYPT ); -ext4_clear_inode_state (inode, -EXT4_STATE_MAY_INLINE_DATA ); -/* -* Update inode->i_flags - S_ENCRYPTED will be enabled, -* S_DAX may be disabled -*/ -ext4_set_inode_flags (inode, false); - } -return res; +/* +* __ext4_new_inode() should have already set the encrypt flag +* on the inode and avoided enabling inline data. +*/ +if (WARN_ON_ONCE (!IS_ENCRYPTED (inode))) +return -EINVAL ; +if (WARN_ON_ONCE (ext4_test_inode_state (inode,EXT4_STATE_MAY_INLINE_DATA ))) +return -EINVAL ; +return ext4_xattr_set_handle (handle, inode, +EXT4_XATTR_INDEX_ENCRYPTION , +EXT4_XATTR_NAME_ENCRYPTION_CONTEXT , + ctx, len,0 ); } res =dquot_initialize (inode);
@@ -1548,10 +1551,7 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len, ctx, len, 0);if (!res) {ext4_set_inode_flag (inode,EXT4_INODE_ENCRYPT ); -/* -* Update inode->i_flags - S_ENCRYPTED will be enabled, -* S_DAX may be disabled -*/ +/* Update inode->i_flags to set S_ENCRYPTED. */ ext4_set_inode_flags (inode, false); res =ext4_mark_inode_dirty (handle, inode);if (res)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 4/43 ipvs: reload ip header after head reallocation
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
commit a2f57827bf7c695b8c72dc4511cae8e86582369d upstream.
__ip_vs_get_out_rt() calls skb_ensure_writable() which may reallocate skb->head.
[Denis Arefev: adapted for 5.10/6.1: keep EnterFunction/LeaveFunction instrumentation]
--- net/netfilter/ipvs/ip_vs_xmit.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
net/netfilter/ipvs/ip_vs_xmit.c +2 -4
@@ -718,15 +718,13 @@ int ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, struct ip_vs_iphdr *ipvsh) { - struct iphdr *iph = ip_hdr(skb); - EnterFunction(10); -if (__ip_vs_get_out_rt (cp->ipvs, cp->af, skb,NULL , iph->daddr, +if (__ip_vs_get_out_rt (cp->ipvs, cp->af, skb,NULL ,ip_hdr (skb)->daddr,IP_VS_RT_MODE_NON_LOCAL ,NULL , ipvsh) <0 ) goto tx_error; -ip_send_check (iph); +ip_send_check (ip_hdr (skb));/* Another hack: avoid icmp_send in ip_fragment */ skb->ignore_df =1 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 5/43 io_uring/io-wq: fix worker accounting when canceling creation callbacks
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vishnu Razdan <[email protected]>
commit 297b5ccea4acacaa47c150f043bce695202afbf1 upstream.
create_worker_cb() reserves an io-wq worker slot only after its task-work callback runs. If the callback is canceled before then, io_worker_cancel_cb() still decrements acct->nr_workers. When an existing worker retires with its creation callback pending, that worker has already decremented the same account's worker count.
The resulting undercount permits worker creation beyond the account's configured limit. On an AST2600 OpenBMC system, an unchanged sensor daemon reached 4,291 threads with the original kernel. With an equivalent downstream fix, 25 passive samples under its normal workload showed 6-9 threads.
Decrement nr_workers only when the canceled callback is not create_worker_cb(). Continuation callbacks still release their reserved slot, and both callback types retain the existing running-count, reference-count, and create-state cleanup.
[ Backport: retain the existing worker->wqe->lock protecting worker
accounting. ]
--- io_uring/io-wq.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
io_uring/io-wq.c +6 -3
@@ -195,9 +195,12 @@ static void io_worker_cancel_cb(struct io_worker *worker)struct io_wq *wq = wqe->wq;atomic_dec (&acct->nr_running); -raw_spin_lock (&worker->wqe->lock); - acct->nr_workers--; -raw_spin_unlock (&worker->wqe->lock); +/* create_worker_cb() has not reserved a worker slot yet. */ +if (worker->create_work.func != create_worker_cb) { +raw_spin_lock (&worker->wqe->lock); + acct->nr_workers--; +raw_spin_unlock (&worker->wqe->lock); + }io_worker_ref_put (wq);clear_bit_unlock (0 , &worker->create_state);io_worker_release (worker);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 6/43 bpf: Remove tst_run from lwt_seg6local_prog_ops.
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Andrzej Siewior <[email protected]>
[ Upstream commit c13fda93aca118b8e5cd202e339046728ee7dddb ]
The syzbot reported that the lwt_seg6 related BPF ops can be invoked via bpf_test_run() without without entering input_action_end_bpf() first.
Martin KaFai Lau said that self test for BPF_PROG_TYPE_LWT_SEG6LOCAL probably didn't work since it was introduced in commit 04d4b274e2a ("ipv6: sr: Add seg6local action End.BPF"). The reason is that the per-CPU variable seg6_bpf_srh_states::srh is never assigned in the self test case but each BPF function expects it.
Remove test_run for BPF_PROG_TYPE_LWT_SEG6LOCAL.
--- net/core/filter.c | 1 - 1 file changed, 1 deletion(-)
net/core/filter.c +0 -1
@@ -9920,7 +9920,6 @@ const struct bpf_verifier_ops lwt_seg6local_verifier_ops = { };const struct bpf_prog_ops lwt_seg6local_prog_ops = { - .test_run = bpf_prog_test_run_skb, };const struct bpf_verifier_ops cg_sock_verifier_ops = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 7/43 jfs: add check read-only before truncation in jfs_truncate_nolock()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vasiliy Kovalev <[email protected]>
[ Upstream commit b5799dd77054c1ec49b0088b006c9908e256843b ]
Added a check for "read-only" mode in the jfs_truncate_nolock function to avoid errors related to writing to a read-only filesystem.
Call stack:
block_write_begin() {
jfs_write_failed() {
jfs_truncate() {
jfs_truncate_nolock() {
txEnd() {
...
log = JFS_SBI(tblk->sb)->log;
// (log == NULL)If the isReadOnly(ip) condition is triggered in jfs_truncate_nolock, the function execution will stop, and no further data modification will occur. Instead, the xtTruncate function will be called with the "COMMIT_WMAP" flag, preventing modifications in "read-only" mode.
--- fs/jfs/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/jfs/inode.c +1 -1
@@ -385,7 +385,7 @@ void jfs_truncate_nolock(struct inode *ip, loff_t length)ASSERT (length >=0 ); -if (test_cflag (COMMIT_Nolink, ip)) { +if (test_cflag (COMMIT_Nolink, ip) ||isReadOnly (ip)) {xtTruncate (0 , ip, length,COMMIT_WMAP );return ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 8/43 jfs: add check read-only before txBeginAnon() call
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vasiliy Kovalev <[email protected]>
[ Upstream commit 0176e69743ecc02961f2ae1ea42439cd2bf9ed58 ]
Added a read-only check before calling txBeginAnon in extAlloc and extRecord. This prevents modification attempts on a read-only mounted filesystem, avoiding potential errors or crashes.
Call trace: txBeginAnon+0xac/0x154 extAlloc+0xe8/0xdec fs/jfs/jfs_extent.c:78 jfs_get_block+0x340/0xb98 fs/jfs/inode.c:248 __block_write_begin_int+0x580/0x166c fs/buffer.c:2128 __block_write_begin fs/buffer.c:2177 [inline] block_write_begin+0x98/0x11c fs/buffer.c:2236 jfs_write_begin+0x44/0x88 fs/jfs/inode.c:299
--- fs/jfs/jfs_extent.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
fs/jfs/jfs_extent.c +10 -0
@@ -77,6 +77,11 @@ extAlloc(struct inode *ip, s64 xlen, s64 pno, xad_t * xp, bool abnr)int rc;int xflag; +if (isReadOnly (ip)) { +jfs_error (ip->i_sb,"read-only filesystem\n" ); +return -EIO ; + } +/* This blocks if we are low on resources */ txBeginAnon (ip->i_sb);
@@ -412,6 +417,11 @@ int extRecord(struct inode *ip, xad_t * xp) {int rc; +if (isReadOnly (ip)) { +jfs_error (ip->i_sb,"read-only filesystem\n" ); +return -EIO ; + } +txBeginAnon (ip->i_sb);mutex_lock (&JFS_IP (ip)->commit_mutex);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 9/43 KVM: arm64: Prevent access to vCPU events before init
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Upton <[email protected]>
[ Upstream commit 0aa1b76fe1429629215a7c79820e4b96233ac4a3 ]
Another day, another syzkaller bug. KVM erroneously allows userspace to pend vCPU events for a vCPU that hasn't been initialized yet, leading to KVM interpreting a bunch of uninitialized garbage for routing / injecting the exception.
In one case the injection code and the hyp disagree on whether the vCPU has a 32bit EL1 and put the vCPU into an illegal mode for AArch64, tripping the BUG() in exception_target_el() during the next injection:
kernel BUG at arch/arm64/kvm/inject_fault.c:40!
Internal error: Oops - BUG: 00000000f2000800 [#1] SMP CPU: 3 UID: 0 PID: 318 Comm: repro Not tainted 6.17.0-rc4-00104-g10fd0285305d #6 PREEMPT Hardware name: linux,dummy-virt (DT) pstate: 21402009 (nzCv daif +PAN -UAO -TCO +DIT -SSBS BTYPE=--) pc : exception_target_el+0x88/0x8c lr : pend_serror_exception+0x18/0x13c sp : ffff800082f03a10 x29: ffff800082f03a10 x28: ffff0000cb132280 x27: 0000000000000000 x26: 0000000000000000 x25: ffff0000c2a99c20 x24: 0000000000000000 x23: 0000000000008000 x22: 0000000000000002 x21: 0000000000000004 x20: 0000000000008000 x19: ffff0000c2a99c20 x18: 0000000000000000 x17: 0000000000000000 x16: 0000000000000000 x15: 00000000200000c0 x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000 x11: 0000000000000000 x10: 0000000000000000 x9 : 0000000000000000 x8 : ffff800082f03af8 x7 : 0000000000000000 x6 : 0000000000000000 x5 : ffff800080f621f0 x4 : 0000000000000000 x3 : 0000000000000000 x2 : 000000000040009b x1 : 0000000000000003 x0 : ffff0000c2a99c20 Call trace: exception_target_el+0x88/0x8c (P) kvm_inject_serror_esr+0x40/0x3b4 __kvm_arm_vcpu_set_events+0xf0/0x100 kvm_arch_vcpu_ioctl+0x180/0x9d4 kvm_vcpu_ioctl+0x60c/0x9f4 __arm64_sys_ioctl+0xac/0x104 invoke_syscall+0x48/0x110 el0_svc_common.constprop.0+0x40/0xe0 do_el0_svc+0x1c/0x28 el0_svc+0x34/0xf0 el0t_64_sync_handler+0xa0/0xe4 el0t_64_sync+0x198/0x19c Code: f946bc01 b4fffe61 9101e020 17fffff2 (d4210000)
Reject the ioctls outright as no sane VMM would call these before KVM_ARM_VCPU_INIT anyway. Even if it did the exception would've been thrown away by the eventual reset of the vCPU's state.
--- arch/arm64/kvm/arm.c | 6 ++++++ 1 file changed, 6 insertions(+)
arch/arm64/kvm/arm.c +6 -0
@@ -1209,6 +1209,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp,case KVM_GET_VCPU_EVENTS : {struct kvm_vcpu_events events; +if (!kvm_vcpu_initialized (vcpu)) +return -ENOEXEC ; +if (kvm_arm_vcpu_get_events (vcpu, &events))return -EINVAL ;
@@ -1220,6 +1223,9 @@ long kvm_arch_vcpu_ioctl(struct file *filp,case KVM_SET_VCPU_EVENTS : {struct kvm_vcpu_events events; +if (!kvm_vcpu_initialized (vcpu)) +return -ENOEXEC ; +if (copy_from_user (&events, argp,sizeof (events)))return -EFAULT ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 10/43 bpf: Fix use-after-free in offloaded map/prog info fill
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <[email protected]>
[ Upstream commit a0c584fc18056709c8e047a82a6045d6c209f4ce ]
When querying info for an offloaded BPF map or program, bpf_map_offload_info_fill_ns() and bpf_prog_offload_info_fill_ns() obtain the network namespace with get_net(dev_net(offmap->netdev)). However, the associated netdev's netns may be racing with teardown during netns destruction. If the netns refcount has already reached 0, get_net() performs a refcount_t increment on 0, triggering:
refcount_t: addition on 0; use-after-free.
Although rtnl_lock and bpf_devs_lock ensure the netdev pointer remains valid, they cannot prevent the netns refcount from reaching zero.
Fix this by using maybe_get_net() instead of get_net(). maybe_get_net() uses refcount_inc_not_zero() and returns NULL if the refcount is already zero, which causes ns_get_path_cb() to fail and the caller to return -ENOENT -- the correct behavior when the netns is being destroyed.
--- kernel/bpf/offload.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
kernel/bpf/offload.c +4 -6
@@ -277,9 +277,8 @@ static struct ns_common *bpf_prog_offload_info_fill_ns(void *private_data)if (aux->offload) { args->info->ifindex = aux->offload->netdev->ifindex; - net =dev_net (aux->offload->netdev); -get_net (net); - ns = &net->ns; + net =maybe_get_net (dev_net (aux->offload->netdev)); + ns = net ? &net->ns :NULL ; }else { args->info->ifindex =0 ; ns =NULL ;
@@ -504,9 +503,8 @@ static struct ns_common *bpf_map_offload_info_fill_ns(void *private_data)if (args->offmap->netdev) { args->info->ifindex = args->offmap->netdev->ifindex; - net =dev_net (args->offmap->netdev); -get_net (net); - ns = &net->ns; + net =maybe_get_net (dev_net (args->offmap->netdev)); + ns = net ? &net->ns :NULL ; }else { args->info->ifindex =0 ; ns =NULL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 11/43 Revert "PM: sleep: Use complete() in device_pm_sleep_init()"
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit d77b629876f15ebf9d9987e60b6747fd73ca8148.
--- drivers/base/power/main.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/base/power/main.c +1 -5
@@ -102,7 +102,7 @@ void device_pm_sleep_init(struct device *dev) dev->power.is_noirq_suspended = false; dev->power.is_late_suspended = false;init_completion (&dev->power.completion); -complete (&dev->power.completion); +complete_all (&dev->power.completion); dev->power.wakeup =NULL ;INIT_LIST_HEAD (&dev->power.entry); }
@@ -242,10 +242,6 @@ static void dpm_wait(struct device *dev, bool async)if (!dev)return ; -/* Devices with no PM support don't use the completion. */ -if (dev->power.no_pm) -return ; -if (async || (pm_async_enabled && dev->power.async_suspend))wait_for_completion (&dev->power.completion); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 12/43 selinux: switch two allocations to use kzalloc_objs()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephen Smalley <[email protected]>
[ Upstream commit cf6a513f1937581eb012a217b29817e025a1a0ef ]
These were the only two allocations in the policy loading logic that were not already using kzalloc_objs() for the policy data structures. Fix these to be consistent with the rest and to protect against ill-formed policy.
--- security/selinux/ss/conditional.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
security/selinux/ss/conditional.c +6 -6
@@ -166,9 +166,9 @@ void cond_policydb_destroy(struct policydb *p)int cond_init_bool_indexes (struct policydb *p) {kfree (p->bool_val_to_struct); - p->bool_val_to_struct =kmalloc_array (p->p_bools.nprim, -sizeof (*p->bool_val_to_struct), -GFP_KERNEL ); + p->bool_val_to_struct =kcalloc (p->p_bools.nprim, +sizeof (*p->bool_val_to_struct), +GFP_KERNEL );if (!p->bool_val_to_struct)return -ENOMEM ;return 0 ;
@@ -714,9 +714,9 @@ static int duplicate_policydb_bools(struct policydb *newdb,struct cond_bool_datum **cond_bool_array;int rc; - cond_bool_array =kmalloc_array (orig->p_bools.nprim, -sizeof (*orig->bool_val_to_struct), -GFP_KERNEL ); + cond_bool_array =kcalloc (orig->p_bools.nprim, +sizeof (*orig->bool_val_to_struct), +GFP_KERNEL );if (!cond_bool_array)return -ENOMEM ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 13/43 Revert "mtd: maps: vmu-flash: fix fault in unaligned fixup"
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit f781e80c9f1e52d92535c076573b0cdafab04864.
--- drivers/mtd/maps/vmu-flash.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/mtd/maps/vmu-flash.c +5 -3
@@ -610,7 +610,7 @@ static int vmu_connect(struct maple_device *mdev) basic_flash_data =be32_to_cpu (mdev->devinfo.function_data[c -1 ]); - card = kzalloc_obj(struct memcard); + card =kmalloc (sizeof (struct memcard ),GFP_KERNEL );if (!card) { error = -ENOMEM ; goto fail_nomem;
@@ -628,13 +628,15 @@ static int vmu_connect(struct maple_device *mdev)* Not sure there are actually any multi-partition devices in the * real world, but the hardware supports them, so, so will we */ - card->parts = kzalloc_objs(struct vmupart, card->partitions); + card->parts =kmalloc_array (card->partitions,sizeof (struct vmupart ), +GFP_KERNEL );if (!card->parts) { error = -ENOMEM ; goto fail_partitions; } - card->mtd = kzalloc_objs(struct mtd_info, card->partitions); + card->mtd =kmalloc_array (card->partitions,sizeof (struct mtd_info ), +GFP_KERNEL );if (!card->mtd) { error = -ENOMEM ; goto fail_mtd_info;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 14/43 Revert "smb: client: use kvzalloc() for megabyte buffer in simple fallocate"
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit a0c4a3e5387421ae252126a7bc29f3cd95b3cf06.
--- fs/cifs/smb2ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/cifs/smb2ops.c +2 -2
@@ -3568,7 +3568,7 @@ static int smb3_simple_fallocate_range(unsigned int xid,if (rc) goto out; - buf =kvzalloc (1024 *1024 ,GFP_KERNEL ); + buf =kzalloc (1024 *1024 ,GFP_KERNEL );if (buf ==NULL ) { rc = -ENOMEM ; goto out;
@@ -3635,7 +3635,7 @@ static int smb3_simple_fallocate_range(unsigned int xid, out:kfree (out_data); -kvfree (buf); +kfree (buf);return rc; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 15/43 ipv4: igmp: Fix potential UAF in igmp_gq_start_timer()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 7b19c0f81ed1fdaec6bc522569be367199a9edf3 upstream.
A race condition exists between device teardown (inetdev_destroy) and incoming IGMP query processing (igmp_rcv), leading to a Use-After-Free in the IGMP timer callback.
During device destruction, inetdev_destroy() drops the primary reference to in_device, which can drop its refcount to 0. The actual freeing of in_device memory is deferred via RCU (using call_rcu()).
Concurrently, igmp_rcv() runs under RCU read lock and obtains the in_device pointer. Because the memory is RCU-protected, CPU-0 can safely dereference in_device even if its refcount has hit 0.
However, if CPU-0 calls igmp_gq_start_timer() and re-arms the timer, it attempts to acquire a reference using in_dev_hold(). This increments the refcount from 0 to 1, triggering a "refcount_t: addition on 0" warning. Since the in_device memory is still scheduled to be freed after the RCU grace period (as the free callback does not check the refcount again), the device is freed while the timer is still armed. When the timer expires, it accesses the freed memory, causing a kernel panic.
Fix this by using refcount_inc_not_zero() (via a new helper in_dev_hold_safe()) to prevent acquiring a reference if the device is already being destroyed. If the refcount is 0, we do not arm the timer.
A similar issue in IPv6 MLD is fixed in a subsequent patch.
[Denis Arefev: adapted for 5.10/5.15: keep prandom_u32(), get_random_u32_below() not used here]
--- include/linux/inetdevice.h | 5 +++++ net/ipv4/igmp.c | 14 +++++++++----- 2 files changed, 14 insertions(+), 5 deletions(-)
include/linux/inetdevice.h +5 -0
@@ -277,6 +277,11 @@ static inline void in_dev_put(struct in_#define __in_dev_put (idev) refcount_dec(&(idev)->refcnt)#define in_dev_hold (idev) refcount_inc(&(idev)->refcnt) +static inline bool in_dev_hold_safe (struct in_device *idev) +{ +return refcount_inc_not_zero (&idev->refcnt); +} +#endif /* __KERNEL__ */ static __inline____be32 inet_make_mask (int logmask)
net/ipv4/igmp.c +9 -5
@@ -232,16 +232,20 @@ static void igmp_gq_start_timer(struct ireturn ; in_dev->mr_gq_running =1 ; -if (!mod_timer (&in_dev->mr_gq_timer, exp)) -in_dev_hold (in_dev); +if (in_dev_hold_safe (in_dev)) { +if (mod_timer (&in_dev->mr_gq_timer, exp)) +in_dev_put (in_dev); + } }static void igmp_ifc_start_timer (struct in_device *in_dev,int delay) { -int tv =prandom_u32 () % delay; +if (in_dev_hold_safe (in_dev)) { +int tv =prandom_u32 () % delay; -if (!mod_timer (&in_dev->mr_ifc_timer, jiffies+tv+2 )) -in_dev_hold (in_dev); +if (mod_timer (&in_dev->mr_ifc_timer, jiffies + tv +2 )) +in_dev_put (in_dev); + } }static void igmp_mod_timer (struct ip_mc_list *im,int max_delay)
Greg Kroah-Hartman
maintainerPATCH 16/43 kcov: fix data corruption and race conditions on PREEMPT_RT
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tetsuo Handa <[email protected]>
[ Upstream commit 2eed77fdcb0cc48e8eccb2bcd4b7f2c6d650e84c ]
syzbot is reporting KCOV state corruption on PREEMPT_RT kernels, for the temporary storage used for saving/restoring remote KCOV state is currently allocated as the per-CPU area.
On PREEMPT_RT kernels, softirq handlers run as preemptible task threads (e.g., ksoftirqd). If a softirq context preempts a task running a remote KCOV session, it safely saves the task's state into the per-CPU area. However, if that softirq thread is subsequently preempted by a higher- priority softirq thread on the same CPU, the second softirq will overwrite the same per-CPU area, permanently destroying the original task's KCOV state.
Fix this data corruption by moving the temporary storage from the per-CPU area to the per-thread area. Since each softirq thread now owns its own task context, nested softirq preemption no longer causes data overwrites.
Note that while the temporary storage is now on a per-thread basis, the per-CPU kcov_percpu_data.lock must be retained, for we need to ensure that kcov_remote_start() and kcov_remote_stop() operate atomically without racing against asynchronous interrupts that manipulate the current task's KCOV state.
It is likely that GFP_KERNEL allocation by vmalloc_node() in kcov_init() has already called panic() before returning NULL, for there will be no OOM-killable userspace processes when __init function of built-in module runs. But this patch also fixes crashing the kernel when vmalloc_node() in kcov_init() returned NULL, for kcov_init() left per-CPU irq_area == NULL but kcov_remote_start() depends on per-CPU irq_area != NULL, resulting in
(1) doing vmalloc() in kcov_remote_start() despite !in_task() context
(2) out-of-array-bounds access if (1) succeeded but
kcov->remote_size < CONFIG_KCOV_IRQ_AREA_SIZE
(3) always leak memory allocated by (1), eventually killing all OOM-killable userspace processes
problems.
--- include/linux/sched.h | 8 ++++ kernel/kcov.c | 93 ++++++++++++++++++++++++-------------------------- lib/Kconfig.debug | 5 +- 3 files changed, 57 insertions(+), 49 deletions(-)
include/linux/sched.h +8 -0
@@ -1295,6 +1295,14 @@ struct task_struct {/* Collect coverage from softirq context: */ unsigned int kcov_softirq; + +/* Temporary storage for preempting remote coverage collection: */ +unsigned int kcov_saved_mode; +unsigned int kcov_saved_size; +void *kcov_saved_area; +struct kcov *kcov_saved_kcov; +int kcov_saved_sequence; +#endif #ifdef CONFIG_MEMCG
kernel/kcov.c +46 -47
170 lines not on this page · raw message
lib/Kconfig.debug +3 -2
@@ -1952,10 +1952,11 @@ config KCOV_INSTRUMENT_ALL config KCOV_IRQ_AREA_SIZE hex "Size of interrupt coverage collection area in words" depends on KCOV + range 0x80 0x1000000 default 0x40000 help - KCOV uses preallocated per-cpu areas to collect coverage from - soft interrupts. This specifies the size of those areas in the + KCOV uses preallocated areas to collect coverage from soft + interrupts. This specifies the size of those areas in the number of unsigned long words. menuconfig RUNTIME_TESTING_MENU
Greg Kroah-Hartman
maintainerPATCH 17/43 ext4: propagate errors from fast commit range replay
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guanghui Yang <[email protected]>
[ Upstream commit d8b8dd3530bf41e14b118702cdaf9de64bb96885 ]
ext4_fc_replay() stops replaying fast commit tags only when a tag handler returns a negative error. However, ext4_fc_replay_add_range() and ext4_fc_replay_del_range() currently return 0 from their common exit paths even after internal failures.
This hides errors from ext4_fc_record_modified_inode(), ext4_map_blocks(), ext4_find_extent(), ext4_ext_insert_extent(), ext4_ext_replay_update_ex(), and ext4_ext_remove_space(). As a result, a failed ADD_RANGE or DEL_RANGE replay can be treated as successful and the replay code may continue with subsequent fast commit tags.
This is particularly problematic for DEL_RANGE because it may already have marked blocks as free before ext4_ext_remove_space() fails. If the error is swallowed, replay may continue from a partially applied range operation.
Return the saved error from the common exit paths and make the ERR_PTR() cases in ADD_RANGE store PTR_ERR() before jumping to out.
--- fs/ext4/fast_commit.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
fs/ext4/fast_commit.c +7 -3
@@ -1678,8 +1678,10 @@ static int ext4_fc_replay_add_range(struif (ret ==0 ) {/* Range is not mapped */ path =ext4_find_extent (inode, cur,NULL ,0 ); -if (IS_ERR (path)) +if (IS_ERR (path)) { + ret =PTR_ERR (path); goto out; + }memset (&newex,0 ,sizeof (newex)); newex.ee_block =cpu_to_le32 (cur); ext4_ext_store_pblock(
@@ -1741,9 +1743,10 @@ next: }ext4_ext_replay_shrink_inode (inode,i_size_read (inode) >> sb->s_blocksize_bits); + ret =0 ; out:iput (inode); -return 0 ; +return ret; }/* Replay DEL_RANGE tag */
@@ -1804,9 +1807,10 @@ ext4_fc_replay_del_range(struct super_blext4_ext_replay_shrink_inode (inode,i_size_read (inode) >> sb->s_blocksize_bits);ext4_mark_inode_dirty (NULL , inode); + ret =0 ; out:iput (inode); -return 0 ; +return ret; }static inline const char *tag2str (u16 tag)
Greg Kroah-Hartman
maintainerPATCH 18/43 nilfs2: reject invalid block index in GC ioctl
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryusuke Konishi <[email protected]>
[ Upstream commit a1735eae55448bc79c2da6593455791e886f6ed8 ]
Syzbot reported list corruption caused by a double list_add_tail() call on bh->b_assoc_buffers within nilfs_lookup_dirty_data_buffers().
Analysis revealed that the root cause was the insertion of a page/folio with a page index of ULONG_MAX into the page cache via the GC ioctl. filemap_get_folios_tag(), called by nilfs_lookup_dirty_data_buffers(), repeatedly detects a dirty folio with a page index of ULONG_MAX due to index wrap-around, leading to duplicate processing of dirty buffers.
As a preparatory step, the GC ioctl loads the page/folio of the block to be moved during GC and inserts it into the page cache based on information in the nilfs_vdesc structure passed as an argument. Normally, this does not cause issues because the user-space GC library configures the nilfs_vdesc structure properly. However, since there is no range check on the parameters determining the page index, a request with artificially crafted parameters -- such as those generated by Syzbot -- can result in a page/folio being inserted with a page index of ULONG_MAX, triggering the above problem.
This resolves the issue by checking the ranges of 'vd_offset' and 'vd_vblocknr' in the nilfs_vdesc structure that determine the page index, thereby preventing the invalid page/folio insertions.
--- fs/nilfs2/ioctl.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-)
fs/nilfs2/ioctl.c +19 -2
@@ -544,6 +544,8 @@ static int nilfs_ioctl_get_bdescs(struct* Return Value: On success, 0 is returned. On error, one of the following * negative error codes is returned. * +* %-EINVAL - Invalid virtual block descriptor. +* * %-EIO - I/O error. * * %-ENOMEM - Insufficient amount of memory available.
@@ -557,15 +559,30 @@ static int nilfs_ioctl_move_inode_block( struct list_head *buffers) {struct buffer_head *bh; +__u64 limit_blkidx = (__u64 )inode->i_sb->s_maxbytes >> inode->i_blkbits;int ret; -if (vdesc->vd_flags ==0 ) +/* +* vblocknr 0 is reserved as an invalid pointer. Also, limit_blkidx +* ensures that the page index converted from vd_vblocknr never +* overflows the page cache limit and respects the architecture's bmap +* key width. +*/ +if (unlikely (vdesc->vd_vblocknr ==0 || + vdesc->vd_vblocknr >= limit_blkidx)) +return -EINVAL ; + +if (vdesc->vd_flags ==0 ) { +if (unlikely (vdesc->vd_offset >= limit_blkidx)) +return -EINVAL ; + ret =nilfs_gccache_submit_read_data ( inode, vdesc->vd_offset, vdesc->vd_blocknr, vdesc->vd_vblocknr, &bh); -else + }else { ret =nilfs_gccache_submit_read_node ( inode, vdesc->vd_blocknr, vdesc->vd_vblocknr, &bh); + }if (unlikely (ret <0 )) {if (ret == -ENOENT )
Greg Kroah-Hartman
maintainerPATCH 19/43 nfc: nci: fix uninit-value in the RF discover/activated NTF handlers
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Samuel Page <[email protected]>
[ Upstream commit 8cbe06c1e699c0a165dae5093a2550e65f914818 ]
nci_rf_discover_ntf_packet() and nci_rf_intf_activated_ntf_packet() each parse a notification into an on-stack struct (nci_rf_discover_ntf / nci_rf_intf_activated_ntf) that is not initialised. The RF technology-specific parameters are only extracted when rf_tech_specific_params_len is non-zero, so a notification that reports a zero length leaves the rf_tech_specific_params union uninitialised - and both handlers then pass it to nci_add_new_protocol(), which reads it:
- discover: nci_add_new_target() -> nci_add_new_protocol();
- activated: nci_target_auto_activated() -> nci_add_new_protocol().
nci_add_new_protocol() uses nfca_poll->nfcid1_len as both a branch condition and a memcpy() length and copies nfcid1/sens_res/sel_res into ndev->targets, which is later exposed to user space via NFC_CMD_GET_TARGET.
BUG: KMSAN: uninit-value in nci_add_new_protocol+0x624/0x6c0 nci_add_new_protocol+0x624/0x6c0 nci_ntf_packet+0x25b2/0x3c30 nci_rx_work+0x318/0x5d0 process_scheduled_works+0x84b/0x17a0 worker_thread+0xc10/0x11b0 kthread+0x376/0x500 Local variable ntf.i created at: nci_ntf_packet+0xbc2/0x3c30
Zero-initialise both on-stack notifications so the union reads back as zero when no technology-specific parameters are present.
--- net/nfc/nci/ntf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/nfc/nci/ntf.c +2 -2
@@ -310,7 +310,7 @@ void nci_clear_target_list(struct nci_destatic void nci_rf_discover_ntf_packet (struct nci_dev *ndev,struct sk_buff *skb) { -struct nci_rf_discover_ntf ntf; +struct nci_rf_discover_ntf ntf = {};__u8 *data = skb->data;bool add_target = true;
@@ -517,7 +517,7 @@ static void nci_rf_intf_activated_ntf_pa struct sk_buff *skb) {struct nci_conn_info *conn_info; -struct nci_rf_intf_activated_ntf ntf; +struct nci_rf_intf_activated_ntf ntf = {};__u8 *data = skb->data;int err =NCI_STATUS_OK ;
Greg Kroah-Hartman
maintainerPATCH 20/43 HID: magicmouse: do not keep a stale msc->input if no input is claimed
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jose Villaseñor Montfort <[email protected]>
[ Upstream commit 0af3b89705688af01aa06025b84fa7a1e06ba6cc ]
magicmouse_input_mapping() caches the first hid_input's input_dev in msc->input while the report descriptor is parsed, and the rest of the driver treats a non-NULL msc->input as proof that an input device was registered.
That does not hold on the hid-input error path. If hidinput_connect() fails -- for instance because input_register_device() returns an error -- it unwinds through hidinput_disconnect(), which frees every input_dev it created, including the one cached in msc->input.
The failure does not abort the probe. hid_connect() only skips the claim:
if ((connect_mask & HID_CONNECT_HIDINPUT) && !hidinput_connect(hdev, connect_mask & HID_CONNECT_HIDINPUT_FORCE)) hdev->claimed |= HID_CLAIMED_INPUT;
and the "device has no listeners" bailout below it does not fire for this driver, which sets ->raw_event; on the USB Magic Mouse 2 / Magic Trackpad 2 paths hidraw and hiddev are claimed as well. hid_hw_start() therefore returns 0 and magicmouse_probe() continues with msc->input pointing at freed memory. Being non-NULL, it passes the "input not registered" check in probe and the NULL checks in ->raw_event and ->event, so the next input report dereferences freed memory.
Clear msc->input when the HID core did not claim an input device, so the existing NULL checks cover this case as well.
--- drivers/hid/hid-magicmouse.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/hid/hid-magicmouse.c +10 -0
@@ -643,6 +643,16 @@ static int magicmouse_probe(struct hid_dreturn ret; } +/* +* When hidinput_connect() fails it frees every input device it +* created, but that does not fail hid_hw_start(): the core simply +* does not claim an input. msc->input, cached in ->input_mapping +* while the report descriptor was parsed, would then be a dangling +* pointer that passes every NULL check. Trust the core's claim. +*/ +if (!(hdev->claimed &HID_CLAIMED_INPUT )) + msc->input =NULL ; +if (!msc->input) {hid_err (hdev,"magicmouse input not registered\n" ); ret = -ENOMEM ;
Greg Kroah-Hartman
maintainerPATCH 21/43 nfc: nci: add data_len bound checks to activation parameter extractors
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
[ Upstream commit 0428fa2c22e2ba0cff766d3b80d461e149102045 ]
nci_extract_activation_params_iso_dep() and nci_extract_activation_params_nfc_dep() read an inner length byte from the NCI RF_INTF_ACTIVATED_NTF payload and use it to memcpy() into fixed kernel buffers, but neither function receives the caller-validated activation_params_len. A crafted NCI notification with activation_params_len=1 and an inner length byte of up to 20 (NFC-A) or 50 (NFC-B) causes memcpy() to read that many bytes past the one valid byte in the activation params region -- a slab out-of-bounds read of kernel memory adjacent to the NCI skb.
The sibling nci_extract_rf_params_*() family was given equivalent protection by commit 571dcbeb8e63 ("net: nfc: nci: Fix parameter validation for packet data"), but the two activation parameter extractors were not updated at that time.
Add a data_len parameter to both functions, guard against an empty region before consuming the inner length byte, decrement the remaining count after consuming it, and clamp the copy length to what is actually available. Update both call sites to pass ntf.activation_params_len, which is already validated against the skb at ntf.c:801.
--- net/nfc/nci/ntf.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-)
net/nfc/nci/ntf.c +24 -4
@@ -371,15 +371,20 @@ static void nci_rf_discover_ntf_packet(s }static int nci_extract_activation_params_iso_dep (struct nci_dev *ndev, -struct nci_rf_intf_activated_ntf *ntf,__u8 *data) +struct nci_rf_intf_activated_ntf *ntf,__u8 *data, +__u8 data_len) {struct activation_params_nfca_poll_iso_dep *nfca_poll;struct activation_params_nfcb_poll_iso_dep *nfcb_poll;switch (ntf->activation_rf_tech_and_mode) {case NCI_NFC_A_PASSIVE_POLL_MODE : +if (data_len <1 ) +return NCI_STATUS_RF_PROTOCOL_ERROR ; nfca_poll = &ntf->activation_params.nfca_poll_iso_dep; nfca_poll->rats_res_len =min_t (__u8, *data++,20 ); + data_len--; + nfca_poll->rats_res_len =min_t (__u8, nfca_poll->rats_res_len, data_len);pr_debug ("rats_res_len %d\n" , nfca_poll->rats_res_len);if (nfca_poll->rats_res_len >0 ) { memcpy(nfca_poll->rats_res,
@@ -388,8 +393,12 @@ static int nci_extract_activation_paramsbreak ;case NCI_NFC_B_PASSIVE_POLL_MODE : +if (data_len <1 ) +return NCI_STATUS_RF_PROTOCOL_ERROR ; nfcb_poll = &ntf->activation_params.nfcb_poll_iso_dep; nfcb_poll->attrib_res_len =min_t (__u8, *data++,50 ); + data_len--; + nfcb_poll->attrib_res_len =min_t (__u8, nfcb_poll->attrib_res_len, data_len);pr_debug ("attrib_res_len %d\n" , nfcb_poll->attrib_res_len);if (nfcb_poll->attrib_res_len >0 ) { memcpy(nfcb_poll->attrib_res,
@@ -407,7 +416,8 @@ static int nci_extract_activation_params }static int nci_extract_activation_params_nfc_dep (struct nci_dev *ndev, -struct nci_rf_intf_activated_ntf *ntf,__u8 *data) +struct nci_rf_intf_activated_ntf *ntf,__u8 *data, +__u8 data_len) {struct activation_params_poll_nfc_dep *poll;struct activation_params_listen_nfc_dep *listen;
@@ -415,9 +425,13 @@ static int nci_extract_activation_paramsswitch (ntf->activation_rf_tech_and_mode) {case NCI_NFC_A_PASSIVE_POLL_MODE :case NCI_NFC_F_PASSIVE_POLL_MODE : +if (data_len <1 ) +return NCI_STATUS_RF_PROTOCOL_ERROR ; poll = &ntf->activation_params.poll_nfc_dep; poll->atr_res_len =min_t (__u8, *data++,NFC_ATR_RES_MAXSIZE -2 ); + data_len--; + poll->atr_res_len =min_t (__u8, poll->atr_res_len, data_len);pr_debug ("atr_res_len %d\n" , poll->atr_res_len);if (poll->atr_res_len >0 )memcpy (poll->atr_res, data, poll->atr_res_len);
@@ -425,9 +439,13 @@ static int nci_extract_activation_paramscase NCI_NFC_A_PASSIVE_LISTEN_MODE :case NCI_NFC_F_PASSIVE_LISTEN_MODE : +if (data_len <1 ) +return NCI_STATUS_RF_PROTOCOL_ERROR ; listen = &ntf->activation_params.listen_nfc_dep; listen->atr_req_len =min_t (__u8, *data++,NFC_ATR_REQ_MAXSIZE -2 ); + data_len--; + listen->atr_req_len =min_t (__u8, listen->atr_req_len, data_len);pr_debug ("atr_req_len %d\n" , listen->atr_req_len);if (listen->atr_req_len >0 )memcpy (listen->atr_req, data, listen->atr_req_len);
@@ -603,12 +621,14 @@ static void nci_rf_intf_activated_ntf_paswitch (ntf.rf_interface) {case NCI_RF_INTERFACE_ISO_DEP : err =nci_extract_activation_params_iso_dep (ndev, - &ntf, data); + &ntf, data, + ntf.activation_params_len);break ;case NCI_RF_INTERFACE_NFC_DEP : err =nci_extract_activation_params_nfc_dep (ndev, - &ntf, data); + &ntf, data, + ntf.activation_params_len);break ;case NCI_RF_INTERFACE_FRAME :
Greg Kroah-Hartman
maintainerPATCH 22/43 nvmet-tcp: bound SGL data length before allocating command buffers
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ibrahim Hashimov <[email protected]>
[ Upstream commit 4a3f00262a044e8e15064b1a6860968bf0500bf4 ]
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.
--- drivers/nvme/target/tcp.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
drivers/nvme/target/tcp.c +13 -0
@@ -382,6 +382,19 @@ static int nvmet_tcp_map_data(struct nvmif (!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))
Greg Kroah-Hartman
maintainerPATCH 23/43 HID: input: read battery capacity from its actual report offset
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jose Villaseñor Montfort <[email protected]>
[ Upstream commit d07644524b6511b622ee7b0e2e68c9ee43d522a4 ]
hidinput_query_battery_capacity() assumes the state-of-charge value is the first byte following the report ID (buf[1]) and ignores where the battery field actually sits within the report.
An Apple Magic Trackpad 2 precedes the AbsoluteStateOfCharge byte with a byte of status flags in its battery reports, so this query returns the flags byte instead of the charge level.
The device happens to make that easy to observe, because it exposes the same cell twice: its report descriptor declares AbsoluteStateOfCharge in two reports (0x90 and 0x9b), so hidinput_setup_battery() registers two power supplies. Only the first one is refreshed by hid-magicmouse -- it uses hid_get_battery(), which returns the first battery of the list -- and that refresh goes through the report event path, which parses the field correctly. Nothing ever reports the second one, so every read of its capacity takes the query path above. On a USB-C Magic Trackpad over USB, on an unpatched 7.1.5:
hid-<serial>-battery-144 = 100% (Charging) <- report event path hid-<serial>-battery-155 = 3% (Discharging) <- query path
Both are the same physical battery. A raw HIDIOCGINPUT of the two reports at that same moment:
report 0x90 -> [90 03 64]
report 0x9b -> [9b 03 64 64 00 00 10 00 00 00 00 00 00 00]
^flags ^SoC = 0x64 = 100%
The device answers correctly in both cases; only the offset the kernel reads the capacity from is wrong. 0x03 is the flags byte (present, charging), reported as "3%".
Bluetooth takes the same query path for its capacity, where the trackpad reported a bogus near-constant ~4% -- 0b100, the FullyCharged flag -- regardless of the real charge.
Store the battery field's offset within the report at setup time and use it when querying, so the capacity is read from its real position. The report event path already parses the field correctly through the HID core; only the explicit GET_REPORT query was wrong.
Devices whose capacity field is the first field in the report have a report_offset of 0 and are unaffected (buf[1 + 0] == buf[1]).
--- drivers/hid/hid-input.c | 17 +++++++++++++---- include/linux/hid.h | 1 + 2 files changed, 14 insertions(+), 4 deletions(-)
drivers/hid/hid-input.c +13 -4
@@ -358,19 +358,27 @@ static int hidinput_query_battery_capaci {u8 *buf;int ret; +/* +* The capacity field may not be the first field in the report: some +* devices (e.g. the Apple Magic Trackpad 2 over Bluetooth) precede it +* with status flags. Read it from its actual byte offset in the report +* (report_offset is in bits; the leading byte is the report id). +*/ +int offset =1 + dev->battery_report_offset /8 ; +int len = offset +1 ; - buf =kmalloc (4 ,GFP_KERNEL ); + buf =kmalloc (max (len,4 ),GFP_KERNEL );if (!buf)return -ENOMEM ; - ret =hid_hw_raw_request (dev, dev->battery_report_id, buf,4 , + ret =hid_hw_raw_request (dev, dev->battery_report_id, buf,max (len,4 ), dev->battery_report_type,HID_REQ_GET_REPORT ); -if (ret <2 ) { +if (ret < len) {kfree (buf);return -ENODATA ; } - ret =hidinput_scale_battery_capacity (dev, buf[1 ]); + ret =hidinput_scale_battery_capacity (dev, buf[offset]);kfree (buf);return ret; }
@@ -487,6 +495,7 @@ static int hidinput_setup_battery(struct dev->battery_max = max; dev->battery_report_type = report_type; dev->battery_report_id = field->report->id; + dev->battery_report_offset = field->report_offset;/* * Stylus is normally not connected to the device and thus we
include/linux/hid.h +1 -0
@@ -616,6 +616,7 @@ struct hid_device { /* device repo__s32 battery_max;__s32 battery_report_type;__s32 battery_report_id; +__s32 battery_report_offset;/* bit offset of the capacity field within its report */ enum hid_battery_status battery_status;bool battery_avoid_query;#endif
Greg Kroah-Hartman
maintainerPATCH 24/43 fpga: dfl: fme: add error handling
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Griffin Kroah-Hartman <[email protected]>
commit b5ba63e247075087ab8a6a087622c762dc4172e9 upstream.
Add error handling to devm_kasprint in fme_perf_pmu_register().
--- drivers/fpga/dfl-fme-perf.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/fpga/dfl-fme-perf.c +2 -0
@@ -925,6 +925,8 @@ static int fme_perf_pmu_register(structPERF_PMU_CAP_NO_EXCLUDE ; name =devm_kasprintf (priv->dev,GFP_KERNEL ,"dfl_fme%d" , pdev->id); +if (!name) +return -ENOMEM ; ret =perf_pmu_register (pmu, name,-1 );if (ret)
Greg Kroah-Hartman
maintainerPATCH 25/43 accessibility: speakup: unregister tty ldisc on later init failures
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
commit a76acbaec9b8fd74413646984d2e3626d0543e39 upstream.
The ldisc registration is intentionally non-fatal, since some synth drivers do not use tty/ldisc. However, once speakup_init() continues past the registration point and later fails, the init unwind path should mirror speakup_exit() and call spk_ttyio_unregister_ldisc().
Add the missing unregister call to the error path after synth_release(), matching the normal module exit cleanup order.
--- drivers/accessibility/speakup/main.c | 1 + 1 file changed, 1 insertion(+)
drivers/accessibility/speakup/main.c +1 -0
@@ -2432,6 +2432,7 @@ error_kbdnotifier:mutex_lock (&spk_mutex);synth_release ();mutex_unlock (&spk_mutex); +spk_ttyio_unregister_ldisc ();speakup_kobj_exit (); error_kobjects:
Greg Kroah-Hartman
maintainerPATCH 26/43 usb: usbtest: disable dynamic ID support
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Nogikh <[email protected]>
commit 00e2071f6d5621a5ddea311a5e6b143ae6e474af upstream.
The usbtest driver relies on the driver_info field of struct usb_device_id to point to a valid struct usbtest_info descriptor. This structure contains essential test configurations, such as endpoint addresses and test modes, which are required during probe.
When a user dynamically adds a new device ID via the sysfs new_id interface without specifying a reference device, the USB core initializes driver_info to 0 (NULL). When a matching device is subsequently probed, usbtest_probe() unconditionally casts driver_info to a struct usbtest_info pointer and dereferences it, leading to a NULL pointer dereference crash:
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] SMP KASAN NOPTI KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] RIP: 0010:usbtest_probe+0x3b9/0x1280 drivers/usb/misc/usbtest.c:2822
Because usbtest strictly requires pre-defined usbtest_info descriptors to function, dynamic ID binding via sysfs is fundamentally unsupported for this driver.
Fix this by setting .no_dynamic_id = 1 on usbtest_driver. This instructs the USB core to skip creating the new_id and remove_id sysfs interfaces for usbtest, preventing invalid dynamic ID entries from being created.
--- drivers/usb/misc/usbtest.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/misc/usbtest.c +1 -0
@@ -3053,6 +3053,7 @@ static struct usb_driver usbtest_driver .disconnect = usbtest_disconnect, .suspend = usbtest_suspend, .resume = usbtest_resume, + .no_dynamic_id = 1, };/*-------------------------------------------------------------------------*/
Greg Kroah-Hartman
maintainerPATCH 27/43 usb: gadget: f_tcm: keep port count until LUN teardown completes
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuangpeng Bai <[email protected]>
commit c39d0916da47d94909391876c9e5bd429ea7b1b9 upstream.
tcm_usbg_drop_nexus() permits session removal once tpg_port_count reaches zero. However, usbg_port_unlink() currently decrements that count from the fabric_pre_unlink() callback, before core_dev_del_lun() waits for active se_lun references to drain.
If removal of the last LUN races a nexus removal, the latter can observe a zero port count and call target_remove_session(). This frees sess_cmd_map while an in-flight struct usbg_cmd, including its work item, can still be accessed.
Overlapping the last-LUN unlink with nexus removal reproduces this lifetime violation as a DEBUG_OBJECTS "free active" warning for usbg_cmd_work, followed by a target-core BUG/Oops.
The generic target-core unlink path has no callback after core_dev_del_lun() completes. Add an optional fabric_post_unlink() callback and use it for the f_tcm port count. The count now remains nonzero until core_dev_del_lun() has finished draining active LUN references, preventing nexus removal from freeing the session during command completion.
--- drivers/target/target_core_fabric_configfs.c | 8 ++++++++ drivers/usb/gadget/function/f_tcm.c | 2 +- include/target/target_core_fabric.h | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-)
drivers/target/target_core_fabric_configfs.c +8 -0
@@ -689,6 +689,14 @@ static void target_fabric_port_unlink( }core_dev_del_lun (se_tpg, lun); + +if (tf->tf_ops->fabric_post_unlink) { +/* +* Allow fabrics to release state that must remain valid until +* core_dev_del_lun() has drained all active LUN references. +*/ + tf->tf_ops->fabric_post_unlink (se_tpg, lun); + } }static void target_fabric_port_release (struct config_item *item)
drivers/usb/gadget/function/f_tcm.c +1 -1
@@ -1732,7 +1732,7 @@ static const struct target_core_fabric_o .fabric_make_tpg = usbg_make_tpg, .fabric_drop_tpg = usbg_drop_tpg, .fabric_post_link = usbg_port_link, - .fabric_pre_unlink = usbg_port_unlink, + .fabric_post_unlink = usbg_port_unlink, .fabric_init_nodeacl = usbg_init_nodeacl, .tfc_wwn_attrs = usbg_wwn_attrs,
include/target/target_core_fabric.h +2 -0
@@ -94,6 +94,8 @@ struct target_core_fabric_ops { struct se_lun *);void (*fabric_pre_unlink)(struct se_portal_group *,struct se_lun *); +void (*fabric_post_unlink)(struct se_portal_group *se_tpg, +struct se_lun *lun);struct se_tpg_np *(*fabric_make_np)(struct se_portal_group *,struct config_group *,const char *);void (*fabric_drop_np)(struct se_tpg_np *);
Greg Kroah-Hartman
maintainerPATCH 28/43 xfrm: espintcp: fix UAF during close
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <[email protected]>
commit deb232e884877bf10b4ce2580909eedec986c284 upstream.
ZDI reported and analyzed a race condition during close for espintcp sockets:
espintcp_close() frees emsg->skb via kfree_skb() without holding
any socket lock. Concurrently, the xfrm_trans_reinject work queue
invokes esp_output_tcp_finish() -> espintcp_push_skb() ->
espintcp_push_msgs() -> skb_send_sock_locked(), which reads the
same skb as a data source.Fix this by adding a synchronize_rcu() call after resetting sk_prot, since esp_output_tcp_finish() runs under RCU and won't use a socket with sk_prot == &tcp_prot. Simply taking the socket lock in espintcp_close() could lead to leaks, if esp_output_tcp_finish() re-adds an skb in the slot we just freed. After this, the existing barrier() is no longer needed.
--- net/xfrm/espintcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/xfrm/espintcp.c +2 -1
@@ -506,7 +506,8 @@ static void espintcp_close(struct sock *strp_stop (&ctx->strp); sk->sk_prot = &tcp_prot; -barrier (); + +synchronize_rcu ();cancel_work_sync (&ctx->work);strp_done (&ctx->strp);
Re: [PATCH 5.10 28/43] xfrm: espintcp: fix UAF during close
Quoted 38 lines · Greg Kroah-Hartman
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <[email protected]>
commit
deb232e884877bf10b4ce2580909eedec986c284upstream.ZDI reported and analyzed a race condition during close for espintcp sockets:
espintcp_close() frees emsg->skb via kfree_skb() without holding any socket lock. Concurrently, the xfrm_trans_reinject work queue invokes esp_output_tcp_finish() -> espintcp_push_skb() -> espintcp_push_msgs() -> skb_send_sock_locked(), which reads the same skb as a data source.Fix this by adding a
synchronize_rcu()call after resettingsk_prot, sinceesp_output_tcp_finish()runs under RCU and won't use a socket withsk_prot==&tcp_prot. Simply taking the socket lock inespintcp_close()could lead to leaks, ifesp_output_tcp_finish()re-adds an skb in the slot we just freed. After this, the existingbarrier()is no longer needed.Fixes e27cca96cd68 ("xfrm: add espintcp (RFC 8229)")Reported-by [email protected]Signed-off-by Sabrina Dubroca <[email protected]>Reviewed-by Breno Leitao <[email protected]>Signed-off-by Steffen Klassert <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- net/xfrm/espintcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/xfrm/espintcp.c static void espintcp_close(struct sock * · line 510
Quoted 6 lines
net/xfrm/espintcp.c +2
-1@@ -506,7 +506,8 @@ static void espintcp_close(struct sock *strp_stop (&ctx->strp); sk->sk_prot = &tcp_prot; -barrier (); + +synchronize_rcu ();
This backport depends on upstream028363685bd0 ("espintcp: remove encap socket caching to avoid reference leak"), which is not in 5.15.y. Without it, esp_find_tcp_sk() still returns the cached x->encap_sk based only on sk_state == TCP_ESTABLISHED (no tcp_is_ulp_esp() check), so new readers keep racing with espintcp_close()'s kfree_skb on ctx->partial.emsg->skb — the UAF issue this patch is supposed to fix.
Reproduced on 5.15.219+ (with this patch applied), KASAN trimmed:
BUG: KASAN: use-after-free in __skb_send_sock+0x6cf/0x7b0 Workqueue: events xfrm_trans_reinject
Reader:
__skb_send_sock <- espintcp_push_msgs <- espintcp_push_skb <- esp_output_tcp_encap_cb <- xfrm_trans_reinject
Free:
espintcp_close <- inet_release <- __sock_release <- sock_close <- __fput
Object: skbuff_head_cache (size 224), i.e. struct sk_buff.
Provenance: the static analysis (missing-prerequisite chain, code-path derivation) and the KASAN reproducer above were both produced by our internal AI-assisted backport triage pipeline. I have personally reviewed the reasoning line-by-line against the 5.15.y source, re-ran the reproducer end-to-end, and confirm the finding — sending it upstream on that basis.
Thanks,
D. Wythe
Quoted 5 lines
net/xfrm/espintcp.c +0
-0cancel_work_sync (&ctx->work);strp_done (&ctx->strp);
Greg Kroah-Hartman
maintainerRe: [PATCH 5.10 28/43] xfrm: espintcp: fix UAF during close
Quoted 68 lines · D. Wythe
Quoted 38 lines · Greg Kroah-Hartman
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <[email protected]>
commit
deb232e884877bf10b4ce2580909eedec986c284upstream.ZDI reported and analyzed a race condition during close for espintcp sockets:
espintcp_close() frees emsg->skb via kfree_skb() without holding any socket lock. Concurrently, the xfrm_trans_reinject work queue invokes esp_output_tcp_finish() -> espintcp_push_skb() -> espintcp_push_msgs() -> skb_send_sock_locked(), which reads the same skb as a data source.Fix this by adding a
synchronize_rcu()call after resettingsk_prot, sinceesp_output_tcp_finish()runs under RCU and won't use a socket withsk_prot==&tcp_prot. Simply taking the socket lock inespintcp_close()could lead to leaks, ifesp_output_tcp_finish()re-adds an skb in the slot we just freed. After this, the existingbarrier()is no longer needed.Fixes e27cca96cd68 ("xfrm: add espintcp (RFC 8229)")Reported-by [email protected]Signed-off-by Sabrina Dubroca <[email protected]>Reviewed-by Breno Leitao <[email protected]>Signed-off-by Steffen Klassert <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- net/xfrm/espintcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)net/xfrm/espintcp.c static void espintcp_close(struct sock * · line 510
Quoted 6 lines
net/xfrm/espintcp.c +2
-1@@ -506,7 +506,8 @@ static void espintcp_close(struct sock *strp_stop (&ctx->strp); sk->sk_prot = &tcp_prot; -barrier (); + +synchronize_rcu ();This backport depends on upstream
028363685bd0("espintcp: remove encap socket caching to avoid reference leak"), which is not in 5.15.y. Without it,esp_find_tcp_sk()still returns the cachedx->encap_skbased only onsk_state==TCP_ESTABLISHED(notcp_is_ulp_esp()check), so new readers keep racing with espintcp_close()'skfree_skbonctx->partial.emsg->skb— the UAF issue this patch is supposed to fix.Reproduced on 5.15.219+ (with this patch applied), KASAN trimmed:
BUG: KASAN: use-after-free in __skb_send_sock+0x6cf/0x7b0 Workqueue: events xfrm_trans_reinjectReader:
__skb_send_sock<-espintcp_push_msgs<-espintcp_push_skb<-esp_output_tcp_encap_cb<-xfrm_trans_reinjectFree:
espintcp_close<-inet_release<-__sock_release<-sock_close<-__fput
Quoted 8 lines
Object:
skbuff_head_cache(size 224), i.e. structsk_buff.Provenance: the static analysis (missing-prerequisite chain, code-path derivation) and the KASAN reproducer above were both produced by our internal AI-assisted backport triage pipeline. I have personally reviewed the reasoning line-by-line against the 5.15.y source, re-ran the reproducer end-to-end, and confirm the finding — sending it upstream on that basis.
That's LLM output, what do you mean to say here to fix this? Please send a patch...
thanks,
greg k-h
Re: [PATCH 5.10 28/43] xfrm: espintcp: fix UAF during close
Quoted 78 lines · Greg Kroah-Hartman
Quoted 68 lines · D. Wythe
Quoted 38 lines · Greg Kroah-Hartman
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <[email protected]>
commit
deb232e884877bf10b4ce2580909eedec986c284upstream.ZDI reported and analyzed a race condition during close for espintcp sockets:
espintcp_close() frees emsg->skb via kfree_skb() without holding any socket lock. Concurrently, the xfrm_trans_reinject work queue invokes esp_output_tcp_finish() -> espintcp_push_skb() -> espintcp_push_msgs() -> skb_send_sock_locked(), which reads the same skb as a data source.Fix this by adding a
synchronize_rcu()call after resettingsk_prot, sinceesp_output_tcp_finish()runs under RCU and won't use a socket withsk_prot==&tcp_prot. Simply taking the socket lock inespintcp_close()could lead to leaks, ifesp_output_tcp_finish()re-adds an skb in the slot we just freed. After this, the existingbarrier()is no longer needed.Fixes e27cca96cd68 ("xfrm: add espintcp (RFC 8229)")Reported-by [email protected]Signed-off-by Sabrina Dubroca <[email protected]>Reviewed-by Breno Leitao <[email protected]>Signed-off-by Steffen Klassert <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- net/xfrm/espintcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)net/xfrm/espintcp.c static void espintcp_close(struct sock * · line 510
Quoted 6 lines
net/xfrm/espintcp.c +2
-1@@ -506,7 +506,8 @@ static void espintcp_close(struct sock *strp_stop (&ctx->strp); sk->sk_prot = &tcp_prot; -barrier (); + +synchronize_rcu ();This backport depends on upstream
028363685bd0("espintcp: remove encap socket caching to avoid reference leak"), which is not in 5.15.y. Without it,esp_find_tcp_sk()still returns the cachedx->encap_skbased only onsk_state==TCP_ESTABLISHED(notcp_is_ulp_esp()check), so new readers keep racing with espintcp_close()'skfree_skbonctx->partial.emsg->skb— the UAF issue this patch is supposed to fix.Reproduced on 5.15.219+ (with this patch applied), KASAN trimmed:
BUG: KASAN: use-after-free in __skb_send_sock+0x6cf/0x7b0 Workqueue: events xfrm_trans_reinjectReader:
__skb_send_sock<-espintcp_push_msgs<-espintcp_push_skb<-esp_output_tcp_encap_cb<-xfrm_trans_reinjectFree:
espintcp_close<-inet_release<-__sock_release<-sock_close<-__fputQuoted 8 lines
Object:
skbuff_head_cache(size 224), i.e. structsk_buff.Provenance: the static analysis (missing-prerequisite chain, code-path derivation) and the KASAN reproducer above were both produced by our internal AI-assisted backport triage pipeline. I have personally reviewed the reasoning line-by-line against the 5.15.y source, re-ran the reproducer end-to-end, and confirm the finding — sending it upstream on that basis.
Quoted 2 lines
That's LLM output, what do you mean to say here to fix this? Please send a patch...
Hi Greg,
Sorry about the confusion. Just to clarify, this is not raw LLM output. I only included that note to be transparent and avoid any controversy, as the issue wasn't initially discovered by myself.
We actually already have a patch prepared for this, but the situation is a bit more complicated.
The fix actually has two prerequisite dependencies:
Commit 028363685bd0 ("espintcp: remove encap socket caching to avoid reference leak"), as mentioned earlier. Commit e1512c1db9e8 ("espintcp: Fix race condition in espintcp_close()"), which relies on disable_work_sync() — an API that does not exist in the 5.10 tree.
To avoid expanding the blast radius, we chose to use an alternative approach in espintcp to replace the implementation of commite1512c1db9e8: introducing a stopped flag and protecting both the flag check and schedule_work() under the existing out_queue.lock spinlock, achieving the same atomic synchronization effect as disable_work_sync().
However, doing this inevitably leads to code divergence between upstream and this tree for xfrm. I'm not sure what the xfrm folks' stance is on this. If the community feels this is overly complicated, I think it's also totally fine to just leave the patch here.
Thanks,
D. Wythe
Quoted 4 lines
thanks,
greg k-h
Greg Kroah-Hartman
maintainerRe: [PATCH 5.10 28/43] xfrm: espintcp: fix UAF during close
Quoted 104 lines · D. Wythe
Quoted 78 lines · Greg Kroah-Hartman
Quoted 68 lines · D. Wythe
Quoted 38 lines · Greg Kroah-Hartman
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sabrina Dubroca <[email protected]>
commit
deb232e884877bf10b4ce2580909eedec986c284upstream.ZDI reported and analyzed a race condition during close for espintcp sockets:
espintcp_close() frees emsg->skb via kfree_skb() without holding any socket lock. Concurrently, the xfrm_trans_reinject work queue invokes esp_output_tcp_finish() -> espintcp_push_skb() -> espintcp_push_msgs() -> skb_send_sock_locked(), which reads the same skb as a data source.Fix this by adding a
synchronize_rcu()call after resettingsk_prot, sinceesp_output_tcp_finish()runs under RCU and won't use a socket withsk_prot==&tcp_prot. Simply taking the socket lock inespintcp_close()could lead to leaks, ifesp_output_tcp_finish()re-adds an skb in the slot we just freed. After this, the existingbarrier()is no longer needed.Fixes e27cca96cd68 ("xfrm: add espintcp (RFC 8229)")Reported-by [email protected]Signed-off-by Sabrina Dubroca <[email protected]>Reviewed-by Breno Leitao <[email protected]>Signed-off-by Steffen Klassert <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- net/xfrm/espintcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)net/xfrm/espintcp.c static void espintcp_close(struct sock * · line 510
Quoted 6 lines
net/xfrm/espintcp.c +2
-1@@ -506,7 +506,8 @@ static void espintcp_close(struct sock *strp_stop (&ctx->strp); sk->sk_prot = &tcp_prot; -barrier (); + +synchronize_rcu ();This backport depends on upstream
028363685bd0("espintcp: remove encap socket caching to avoid reference leak"), which is not in 5.15.y. Without it,esp_find_tcp_sk()still returns the cachedx->encap_skbased only onsk_state==TCP_ESTABLISHED(notcp_is_ulp_esp()check), so new readers keep racing with espintcp_close()'skfree_skbonctx->partial.emsg->skb— the UAF issue this patch is supposed to fix.Reproduced on 5.15.219+ (with this patch applied), KASAN trimmed:
BUG: KASAN: use-after-free in __skb_send_sock+0x6cf/0x7b0 Workqueue: events xfrm_trans_reinjectReader:
__skb_send_sock<-espintcp_push_msgs<-espintcp_push_skb<-esp_output_tcp_encap_cb<-xfrm_trans_reinjectFree:
espintcp_close<-inet_release<-__sock_release<-sock_close<-__fputQuoted 8 lines
Object:
skbuff_head_cache(size 224), i.e. structsk_buff.Provenance: the static analysis (missing-prerequisite chain, code-path derivation) and the KASAN reproducer above were both produced by our internal AI-assisted backport triage pipeline. I have personally reviewed the reasoning line-by-line against the 5.15.y source, re-ran the reproducer end-to-end, and confirm the finding — sending it upstream on that basis.
Quoted 2 lines
That's LLM output, what do you mean to say here to fix this? Please send a patch...
Hi Greg,
Sorry about the confusion. Just to clarify, this is not raw LLM output. I only included that note to be transparent and avoid any controversy, as the issue wasn't initially discovered by myself.
We actually already have a patch prepared for this, but the situation is a bit more complicated.
The fix actually has two prerequisite dependencies:
Commit
028363685bd0("espintcp: remove encap socket caching to avoid reference leak"), as mentioned earlier. Commite1512c1db9e8("espintcp: Fix race condition inespintcp_close()"), which relies ondisable_work_sync()— an API that does not exist in the 5.10 tree.To avoid expanding the blast radius, we chose to use an alternative approach in espintcp to replace the implementation of commit
e1512c1db9e8: introducing a stopped flag and protecting both the flag check andschedule_work()under the existing out_queue.lock spinlock, achieving the same atomic synchronization effect asdisable_work_sync().
Quoted 4 lines
However, doing this inevitably leads to code divergence between upstream and this tree for xfrm. I'm not sure what the xfrm folks' stance is on this. If the community feels this is overly complicated, I think it's also totally fine to just leave the patch here.
Please always take the upstream commits when ever possible. But the disable_work_sync() stuff is messier, so if you just wait a few more months, it's not going to be an issue as the 5.10.y tree will be end-of-life by then :)
So, why not move to a newer kernel tree now?
thanks,
greg k-h
Sasha Levin
maintainerRe: [PATCH 5.10 28/43] xfrm: espintcp: fix UAF during close
In reply to D. WytheQuoted 5 lines
The fix actually has two prerequisite dependencies:
Commit
028363685bd0("espintcp: remove encap socket caching to avoid reference leak"), as mentioned earlier. Commite1512c1db9e8("espintcp: Fix race condition inespintcp_close()"), which relies ondisable_work_sync()— an API that does not exist in the 5.10 tree.
028363685bd0 is now queued for 5.15 and 5.10 alongside the original fix, thanks for catching the gap.
e1512c1db9e8 is a separate issue and is still open. disable_work_sync() isn't available on 6.6/6.1/5.15/5.10 either, so it needs its own resolution rather than a straight cherry-pick. Still looking at options there.
Signature · 2 lines
Thanks, Sasha
Sasha Levin
maintainerRe: [PATCH 5.10 28/43] xfrm: espintcp: fix UAF during close
In reply to D. WytheQuoted 5 lines
This backport depends on upstream
028363685bd0("espintcp: remove encap socket caching to avoid reference leak"), which is not in 5.15.y. Without it,esp_find_tcp_sk()still returns the cachedx->encap_skbased only onsk_state==TCP_ESTABLISHED(notcp_is_ulp_esp()check), so new readers keep racing with
Thanks for the repro!
028363685bd0 ("espintcp: remove encap socket caching to avoid reference leak") doesn't cherry-pick cleanly onto 5.15.y or 5.10.y though:
esp_find_tcp_sk()/esp6_find_tcp_sk() there still open-code &tcp_hashinfo instead of the netns-ified tcp_death_row.hashinfo, so it needs a real hand-adapted patch rather than an automatic conflict resolution. Could you post 5.15/5.10 backports for it?
On the second prerequisite, e1512c1db9e8 ("espintcp: Fix race condition in espintcp_close()"): that needs disable_work_sync(), which only exists from v6.10's workqueue disable/enable series. Backporting that whole chain to 6.6/6.1/5.15/5.10 just to unlock one espintcp fix isn't proportionate.
Signature · 2 lines
Thanks, Sasha
Greg Kroah-Hartman
maintainerPATCH 29/43 xfrm: drop ESP-in-TCP packets with no ingress device
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhiling Zou <[email protected]>
commit e1d7c5ac1c246ce5775f604515de0a59fbf2116e upstream.
ESP-in-TCP receives records through the TCP strparser. handle_esp() restores skb->dev from the saved skb_iif before passing the packet into the XFRM input path.
Queued TCP data can be processed after the original ingress device has been removed, for example during veth or net namespace teardown. In that case dev_get_by_index_rcu() returns NULL. The XFRM IPv4 and IPv6 input paths both expect skb->dev to be valid while building the route lookup, so queued ESP-in-TCP data can dereference a NULL device.
Drop the packet if the saved ingress device can no longer be resolved. Such a packet can no longer be routed through the normal XFRM receive path, and this preserves the existing behaviour for packets whose ingress device still exists.
--- net/xfrm/espintcp.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/xfrm/espintcp.c +6 -0
@@ -38,6 +38,11 @@ static void handle_esp(struct sk_buff *srcu_read_lock (); skb->dev =dev_get_by_index_rcu (sock_net (sk), skb->skb_iif); +if (!skb->dev) { +XFRM_INC_STATS (sock_net (sk),LINUX_MIB_XFRMINERROR ); +kfree_skb (skb); + goto out; + }local_bh_disable ();#if IS_ENABLED (CONFIG_IPV6 )if (sk->sk_family ==AF_INET6 )
@@ -46,6 +51,7 @@ static void handle_esp(struct sk_buff *s#endif xfrm4_rcv_encap (skb,IPPROTO_ESP ,0 ,TCP_ENCAP_ESPINTCP );local_bh_enable (); +out:rcu_read_unlock (); }
Greg Kroah-Hartman
maintainerPATCH 30/43 xfrm: ah6: validate routing header segments_left
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Asim Viladi Oglu Manizada <[email protected]>
commit 7bad4bda74dc4713f398d3b7624ff05478e3a568 upstream.
AH6 rearranges routing-header addresses before computing or verifying the ICV. ipv6_rearrange_rthdr() assumes that segments_left is not larger than the number of addresses described by the routing header's hdrlen field.
That assumption does not hold for raw IPv6 HDRINCL packets. A packet with hdrlen equal to 2 describes one address, but can carry an arbitrary segments_left value. With segments_left equal to 255, the function moves its address pointer 4,064 bytes backwards and passes a 4,064-byte length to memmove(), resulting in an out-of-bounds access.
Validate the invariant locally before modifying the routing header or performing any address-pointer arithmetic, and propagate malformed-header errors to the existing AH6 input and output error paths.
--- net/ipv6/ah6.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-)
net/ipv6/ah6.c +18 -11
@@ -238,26 +238,28 @@ static void ipv6_rearrange_destopt(struc* Rearrange the destination address in @iph and the addresses in @rthdr * so that they appear in the order they will at the final destination. * See Appendix A2 of RFC 2402 for details. +* +* Return: 0 on success, -EINVAL if segments_left exceeds the number of +* addresses described by hdrlen. */ -static void ipv6_rearrange_rthdr (struct ipv6hdr *iph,struct ipv6_rt_hdr *rthdr) +static int ipv6_rearrange_rthdr (struct ipv6hdr *iph,struct ipv6_rt_hdr *rthdr) { -int segments, segments_left; +unsigned int segments, segments_left;struct in6_addr *addrs;struct in6_addr final_addr; segments_left = rthdr->segments_left;if (segments_left ==0 ) -return ; - rthdr->segments_left =0 ; +return 0 ; -/* The value of rthdr->hdrlen has been verified either by the system -* call if it is locally generated, or by ipv6_rthdr_rcv() for incoming -* packets. So we can assume that it is even and that segments is -* greater than or equal to segments_left. -* -* For the same reason we can assume that this option is of type 0. +/* Raw locally generated packets can reach AH6 without the invariant +* required by the rt0-style address rearrangement below. */ segments = rthdr->hdrlen >>1 ; +if (segments_left > segments) +return -EINVAL ; + + rthdr->segments_left =0 ; addrs = ((struct rt0_hdr *)rthdr)->addr; final_addr = addrs[segments -1 ];
@@ -267,6 +269,8 @@ static void ipv6_rearrange_rthdr(struct addrs[0 ] = iph->daddr; iph->daddr = final_addr; + +return 0 ; }static int ipv6_clear_mutable_options (struct ipv6hdr *iph,int len,int dir)
@@ -279,6 +283,7 @@ static int ipv6_clear_mutable_options(st } exthdr = { .iph = iph };char *end = exthdr.raw + len;int nexthdr = iph->nexthdr; +int err; exthdr.iph++;
@@ -298,7 +303,9 @@ static int ipv6_clear_mutable_options(stbreak ;case NEXTHDR_ROUTING : -ipv6_rearrange_rthdr (iph, exthdr.rth); + err =ipv6_rearrange_rthdr (iph, exthdr.rth); +if (err) +return err;break ;default :
Greg Kroah-Hartman
maintainerPATCH 31/43 xfrm: fix xfrm_state_construct() auth-trunc leak
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zihan Xi <[email protected]>
commit c12cbf56320fb633484ee0ca1fb7d68d6b64b213 upstream.
attach_auth_trunc() can allocate x->aalg while leaving x->props.aalgo at zero when the selected auth algorithm has no sadb_alg_id. One real case is cmac(aes).
xfrm_state_construct() then treats !x->props.aalgo as "no auth algorithm attached yet" and calls attach_auth(). That overwrites x->aalg and loses the first allocation. Any later failure or teardown only frees the replacement pointer.
Check whether x->aalg is already attached instead of inferring that state from x->props.aalgo.
--- net/xfrm/xfrm_user.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/xfrm/xfrm_user.c +1 -1
@@ -614,7 +614,7 @@ static struct xfrm_state *xfrm_state_conif ((err =attach_auth_trunc (&x->aalg, &x->props.aalgo, attrs[XFRMA_ALG_AUTH_TRUNC ]))) goto error; -if (!x->props.aalgo) { +if (!x->aalg) {if ((err =attach_auth (&x->aalg, &x->props.aalgo, attrs[XFRMA_ALG_AUTH ]))) goto error;
Greg Kroah-Hartman
maintainerPATCH 32/43 ipv6: seg6: clear IPv4 control block on IPIP decapsulation
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyle Zeng <[email protected]>
commit 44930446dde45a7a90fe1446fa38eb0e2c561646 upstream.
End.DX4 and End.DT4 decapsulate an IPv4 packet through decap_and_validate() and send it directly to IPv4 routing. The inner packet therefore bypasses ip_rcv_core(), which normally clears IPCB before IPv4 interprets skb->cb.
The skb instead retains IP6CB data from the outer packet. IP6CB and IPCB use the same skb->cb storage, so IP6CB(skb)->lastopt overlaps IPCB(skb)->opt.optlen and srr, while IP6CB(skb)->nhoff overlaps rr and ts.
The sender can make the stale optlen byte nonzero with a valid outer extension-header chain. The reproducers put an eight-byte Destination Options header immediately after the 40-byte IPv6 header and before the Segment Routing Header. ipv6_destopt_rcv() records the sender-controlled Destination Options offset in both lastopt and nhoff, setting them to
40. On the reproduced little-endian x86-64 kernel, IPv4 therefore sees optlen = 40 and rr = 40.
Both tcp_v4_save_options() and __ip_options_echo() skip option copying when optlen is zero. Here optlen is 40, so the TCP SYN path allocates room for 40 bytes of option data and calls __ip_options_echo(). The stale rr value makes that function read inner packet byte 41 as the Record Route option length. The reproducers set that sender-controlled byte to 255, so __ip_options_echo() copies 255 bytes into the 40-byte option-data area.
Separate End.DX4 and End.DT4 reproducers on the unpatched v7.2-rc5 kernel both produced:
BUG: KASAN: slab-out-of-bounds in __ip_options_echo() Write of size 255
The relevant End.DX4 call path is:
__ip_options_echo
tcp_v4_route_req
tcp_conn_request
tcp_v4_conn_request
tcp_rcv_state_process
tcp_v4_do_rcv
tcp_v4_rcv
ip_protocol_deliver_rcu
ip_local_deliver_finish
ip_local_deliver
input_action_end_dx4_finish
input_action_end_dx4
The relevant End.DT4 call path is:
__ip_options_echo
tcp_v4_route_req
tcp_conn_request
tcp_v4_conn_request
tcp_rcv_state_process
tcp_v4_do_rcv
tcp_v4_rcv
ip_protocol_deliver_rcu
ip_local_deliver_finish
ip_local_deliver
input_action_end_dt4
tcp_v4_save_options() is inlined into the tcp_v4_route_req() path, so it does not appear as a separate frame.
When decap_and_validate() handles IPPROTO_IPIP, save the ingress interface from IP6CB, clear IPCB, and restore the saved value. Doing this in the common decapsulation path covers End.DX4, End.DT4, and End.DT46's IPv4 arm.
Use IP6CB(skb)->iif rather than skb->skb_iif. These actions run after l3mdev processing, which can replace skb_iif with the L3 master; IP6CB iif still records the receiving interface set at IPv6 ingress.
--- net/ipv6/seg6_local.c | 7 +++++++ 1 file changed, 7 insertions(+)
net/ipv6/seg6_local.c +7 -0
@@ -139,6 +139,13 @@ static bool decap_and_validate(struct skif (iptunnel_pull_offloads (skb))return false; +if (proto ==IPPROTO_IPIP ) { +int iif =IP6CB (skb)->iif; + +memset (IPCB (skb),0 ,sizeof (*IPCB (skb))); +IPCB (skb)->iif = iif; + } +return true; }
Greg Kroah-Hartman
maintainerPATCH 33/43 mm/swap: reject swapon() on filesystem-level encrypted files
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Biggers <[email protected]>
commit c310a8932a3107c9bc8f01d473e9d085f8aa9c98 upstream.
ext4 and f2fs don't prevent filesystem-level encrypted files from being set up directly as swap files. In this case, encryption is bypassed.
No one should be doing this, vs. the methods of encrypted swap that actually do work (such as swapping to a dm-crypt device, or swapping to a loopback device on top of a filesystem-level encrypted file).
Nevertheless, to prevent user error, make swapon() explicitly reject this case. Document this behavior in fscrypt.rst as well.
--- Documentation/filesystems/fscrypt.rst | 4 ++++ mm/swapfile.c | 7 +++++++ 2 files changed, 11 insertions(+)
Documentation/filesystems/fscrypt.rst +4 -0
@@ -1068,6 +1068,10 @@ astute users may notice some differences give the length of the ciphertext, which will be slightly longer than the plaintext due to NUL-padding and an extra 2-byte overhead. +- Encrypted files cannot be used directly as swap files. To swap to + an encrypted file, set up a loopback device on top of it. + Alternatively, encrypted swap can use a dm-crypt device. + - The maximum length of an encrypted symlink is 2 bytes shorter than the maximum length of an unencrypted symlink. For example, on an EXT4 filesystem with a 4K block size, unencrypted symlinks can be up
mm/swapfile.c +7 -0
@@ -3234,6 +3234,13 @@ SYSCALL_DEFINE2(swapon, const char __use error = -EBUSY ; goto bad_swap_unlock_inode; } +if (IS_ENCRYPTED (inode)) { +pr_warn_once ( +"Filesystem-level encrypted swapfile '%s' is unsupported. Create a loop device over it, or use dm-crypt\n" , + name->name); + error = -EINVAL ; + goto bad_swap_unlock_inode; + }/* * Read the swap header.
Greg Kroah-Hartman
maintainerPATCH 34/43 crypto: atmel-tdes - use scatterlist length before DMA mapping
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
commit ba199bdaa80b09a7dd92f28751de7f3dbb06c510 upstream.
Using sg_dma_len() is only valid after mapping the scatterlist with dma_map_sg(). However, atmel_tdes_crypt_start() uses it before mapping to compare input/output lengths and to compute the transfer count.
Use the original scatterlist lengths before DMA mapping to avoid reading stale or uninitialized DMA lengths when CONFIG_NEED_SG_DMA_LENGTH=y.
Drop the output scatterlist length in the fast path since it is equal to ->in_sg->length and does not change the transfer count.
--- drivers/crypto/atmel-tdes.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/crypto/atmel-tdes.c +2 -3
@@ -509,14 +509,13 @@ static int atmel_tdes_crypt_start(structIS_ALIGNED (dd->out_sg->length, dd->ctx->block_size); fast = in && out; -if (sg_dma_len (dd->in_sg) !=sg_dma_len (dd->out_sg)) +if (dd->in_sg->length != dd->out_sg->length) fast =0 ; }if (fast) { - count =min_t (size_t, dd->total,sg_dma_len (dd->in_sg)); - count =min_t (size_t, count,sg_dma_len (dd->out_sg)); + count =min_t (size_t, dd->total, dd->in_sg->length); err =dma_map_sg (dd->dev, dd->in_sg,1 ,DMA_TO_DEVICE );if (!err) {
Greg Kroah-Hartman
maintainerPATCH 35/43 crypto: mxs-dcp - fix source scatterlist length access
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
commit c5bcb084a9871e5b62afb5f48b60adfa13b5d9f8 upstream.
mxs_dcp_aes_block_crypt() uses sg_dma_len() without mapping the source scatterlist with dma_map_sg() first. Therefore, sg_dma_len() is invalid and could return zero or a stale DMA length, causing encryption and decryption to process the wrong number of bytes when CONFIG_NEED_SG_DMA_LENGTH=y.
Use the original scatterlist length instead.
--- drivers/crypto/mxs-dcp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/crypto/mxs-dcp.c +1 -1
@@ -332,7 +332,7 @@ static int mxs_dcp_aes_block_crypt(strucfor_each_sg (req->src, src,sg_nents (req->src), i) { src_buf =sg_virt (src); - len =sg_dma_len (src); + len = src->length; tlen += len; limit_hit = tlen > req->cryptlen;
Greg Kroah-Hartman
maintainerPATCH 36/43 KVM: s390: vsie: zero stale crypto bits
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Borntraeger <[email protected]>
commit 34d5b5b646c91cfb9338d7a12c955a70ffb8c66b upstream.
When shadowing crypto access bits from a format0 apcb (crycb 0 or 1), the bits 64..255 are unchanged from whatever is in the vsie page in the crycb and thus in the apcb. This gives a nested guest potential access to a device no longer available. Zero out the remaining bits.
Message-ID: <[email protected]>
--- arch/s390/kvm/vsie.c | 1 + 1 file changed, 1 insertion(+)
arch/s390/kvm/vsie.c +1 -0
@@ -144,6 +144,7 @@ static int setup_apcb10(struct kvm_vcpuif (read_guest_real (vcpu, apcb_o, &tmp,sizeof (struct kvm_s390_apcb0 )))return -EFAULT ; +memset (apcb_s,0 ,sizeof (*apcb_s)); apcb_s->apm[0 ] = apcb_h->apm[0 ] & tmp.apm[0 ]; apcb_s->aqm[0 ] = apcb_h->aqm[0 ] & tmp.aqm[0 ] &0xffff000000000000UL ; apcb_s->adm[0 ] = apcb_h->adm[0 ] & tmp.adm[0 ] &0xffff000000000000UL ;
Greg Kroah-Hartman
maintainerPATCH 37/43 usb: core: Add lock to usb_wakeup_notification()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Griffin Kroah-Hartman <[email protected]>
commit e263e18a9e7b1ff3e7301f0801c6ff87c31adfb6 upstream.
Add a spin lock to usb_wakeup notification to prevent a race condition with dereferencing freed memory. This could be hit by the xHCI driver as it calls this function from an IRQ and could race with the hub_disconnect() function, which properly grabs this lock to protect the state of the device.
--- drivers/usb/core/hub.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/usb/core/hub.c +3 -0
@@ -714,10 +714,12 @@ void usb_wakeup_notification(struct usb_ {struct usb_hub *hub;struct usb_port *port_dev; +unsigned long flags;if (!hdev)return ; +spin_lock_irqsave (&device_state_lock, flags); hub =usb_hub_to_struct_hub (hdev);if (hub) { port_dev = hub->ports[portnum -1 ];
@@ -727,6 +729,7 @@ void usb_wakeup_notification(struct usb_set_bit (portnum, hub->wakeup_bits);kick_hub_wq (hub); } +spin_unlock_irqrestore (&device_state_lock, flags); }EXPORT_SYMBOL_GPL (usb_wakeup_notification);
Greg Kroah-Hartman
maintainerPATCH 38/43 usb: core: Strengthen error handling in hub_hub_status()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Griffin Kroah-Hartman <[email protected]>
commit a29496745aa335d97f617385809583241e118610 upstream.
Add additional error handling after the call to get_hub_status() in hub_hub_status().
get_hub_status() uses usb_control_msg() which does not verify that the message is the correct length, substituting it for usb_control_msg_recv() would also solve this issue but increase memory allocations.
Instead, error handling is copied from the method used in hub_ext_port_status(), which shares the same flow of logic as hub_hub_status().
--- drivers/usb/core/hub.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/usb/core/hub.c +3 -1
@@ -955,10 +955,12 @@ static int hub_hub_status(struct usb_hubmutex_lock (&hub->status_mutex); ret =get_hub_status (hub->hdev, &hub->status->hub); -if (ret <0 ) { +if (ret < (int )sizeof (hub->status->hub)) {if (ret != -ENODEV )dev_err (hub->intfdev,"%s failed (err = %d)\n" , __func__, ret); +if (ret >=0 ) + ret = -EIO ; }else { *status =le16_to_cpu (hub->status->hub.wHubStatus); *change =le16_to_cpu (hub->status->hub.wHubChange);
Greg Kroah-Hartman
maintainerPATCH 39/43 ALSA: usb-audio: fix OOB write in snd_usbmidi_novation_output()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marouane El Moufid <[email protected]>
commit 1035a8f63bae28e498b0e7b5ac91d749844a7158 upstream.
snd_usbmidi_novation_output() lays out a two-byte header at transfer_buffer[0..1] and passes &transfer_buffer[2] together with a length of ep->max_transfer - 2 to snd_rawmidi_transmit():
count = snd_rawmidi_transmit(ep->ports[0].substream, &transfer_buffer[2], ep->max_transfer - 2);
ep->max_transfer comes from the output endpoint's wMaxPacketSize via usb_maxpacket(). A malformed or malicious device can advertise a bulk OUT endpoint with a wMaxPacketSize of 1 - the USB core only clamps this value downwards - so ep->max_transfer becomes 1 and the count argument becomes -1.
snd_rawmidi_transmit() passes the negative count on to __snd_rawmidi_transmit_peek(), where "if (count1 > count) count1 = count" leaves count1 negative; get_aligned_size() keeps it negative for a byte-stream substream, so the following memcpy(buffer, ..., count1) runs with a (size_t)-1 length and writes far past the transfer buffer, which was allocated with usb_alloc_coherent(ep->max_transfer).
This is the same class of bug that was fixed for snd_usbmidi_akai_output() in commit 0970274613fb ("ALSA: usb-audio: fix OOB write in snd_usbmidi_akai_output()"); the novation output routine was left unguarded. Bail out when the endpoint cannot hold the two-byte header plus at least one payload byte.
--- sound/usb/midi.c | 2 ++ 1 file changed, 2 insertions(+)
sound/usb/midi.c +2 -0
@@ -894,6 +894,8 @@ static void snd_usbmidi_novation_output(if (!ep->ports[0 ].active)return ; +if (ep->max_transfer <3 ) +return ; transfer_buffer = urb->transfer_buffer; count = snd_rawmidi_transmit(ep->ports[0].substream, &transfer_buffer[2],
Greg Kroah-Hartman
maintainerPATCH 40/43 USB: serial: option: fix slab OOB read in interrupt URB callback
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiale Yao <[email protected]>
commit 885d802f544ca7bfa8f3984d94233cce715bb6b3 upstream.
The interrupt URB buffer is allocated in setup_port_interrupt_in() based on the endpoint's wMaxPacketSize:
buffer_size = usb_endpoint_maxp(epd);
port->interrupt_in_buffer = kmalloc(buffer_size, GFP_KERNEL);When a USB device declares wMaxPacketSize = 8 on its interrupt IN endpoint, the buffer is allocated from kmalloc-8 cache (exactly 8 bytes).
If the device sends a short packet (actual_length < wMaxPacketSize), the URB completes with status == 0 and the callback proceeds to read:
data[sizeof(struct usb_ctrlrequest)]
which evaluates to data[8], accessing 1 byte beyond the allocated 8-byte buffer. This results in a slab out-of-bounds read.
Fix this by adding the missing bounds check: first verify that the actual length is large enough to contain the struct usb_ctrlrequest header before accessing req_pkt->bRequestType and req_pkt->bRequest, and then verify that there is an additional byte for the modem signal state before reading data[sizeof(struct usb_ctrlrequest)] inside the conditional. Use sizeof(*req_pkt) instead of sizeof(struct usb_ctrlrequest) for consistency.
--- drivers/usb/serial/option.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-)
drivers/usb/serial/option.c +17 -3
@@ -2693,12 +2693,26 @@ static void option_instat_callback(strucdev_dbg (dev,"%s: NULL req_pkt\n" , __func__);return ; } + +if (urb->actual_length <sizeof (*req_pkt)) { +dev_err (dev,"%s: short packet: %u bytes\n" , __func__, + urb->actual_length); +return ; + } +if ((req_pkt->bRequestType ==0xA1 ) && (req_pkt->bRequest ==0x20 )) { +unsigned char signals;int old_dcd_state; -unsigned char signals = *((unsigned char *) - urb->transfer_buffer + -sizeof (struct usb_ctrlrequest )); + +if (urb->actual_length <sizeof (*req_pkt) +1 ) { +dev_err (dev,"%s: short interrupt transfer: %u bytes\n" , + __func__, urb->actual_length); +return ; + } + + signals = *((unsigned char *)urb->transfer_buffer + +sizeof (*req_pkt));dev_dbg (dev,"%s: signal x%x\n" , __func__, signals);
Greg Kroah-Hartman
maintainerPATCH 41/43 USB: serial: spcp8x5: drop broken carrier detect support
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit d37186bd95a07e334447f47274a38a311dad2172 upstream.
The driver does not support modem status notifications and instead used to fetch the modem status once at open() and subsequently operate on and report stale state.
As part of fixing this, a call to fetch the status was added to carrier_raised(), which does not work as that callback must not sleep (e.g. unlike tiocmget()).
Drop the broken carrier detect support.
--- drivers/usb/serial/spcp8x5.c | 13 ------------- 1 file changed, 13 deletions(-)
drivers/usb/serial/spcp8x5.c +0 -13
@@ -249,18 +249,6 @@ static void spcp8x5_set_work_mode(structdev_err (&port->dev,"failed to set work mode: %d\n" , ret); } -static int spcp8x5_carrier_raised (struct usb_serial_port *port) -{ -u8 msr; -int ret; - - ret =spcp8x5_get_msr (port, &msr); -if (ret || msr &MSR_STATUS_LINE_DCD ) -return 1 ; - -return 0 ; -} -static void spcp8x5_dtr_rts (struct usb_serial_port *port,int on) {struct spcp8x5_private *priv =usb_get_serial_port_data (port);
@@ -472,7 +460,6 @@ static struct usb_serial_driver spcp8x5_ .num_bulk_out = 1, .open = spcp8x5_open, .dtr_rts = spcp8x5_dtr_rts, - .carrier_raised = spcp8x5_carrier_raised, .set_termios = spcp8x5_set_termios, .init_termios = spcp8x5_init_termios, .tiocmget = spcp8x5_tiocmget,
Greg Kroah-Hartman
maintainerPATCH 42/43 USB: c67x00: fix use-after-free in c67x00_add_iso_urb()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuangpeng Bai <[email protected]>
commit b1e24de475bf2d66fffc9103f3444b783527d55a upstream.
When TD creation fails for the last packet of an isochronous URB, c67x00_add_iso_urb() gives the URB back before updating the endpoint scheduling state.
c67x00_giveback_urb() frees the URB private data, and the completion callback may release the final URB reference. The following accesses to urbp->ep_data, urb->interval, and urbp->cnt can therefore use freed memory.
Update next_frame and cnt before giving back the failed final packet, making the giveback the last operation that uses the URB and its private data.
--- drivers/usb/c67x00/c67x00-sched.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/c67x00/c67x00-sched.c +2 -2
@@ -761,13 +761,13 @@ static int c67x00_add_iso_urb(struct c67 ret); urb->iso_frame_desc[urbp->cnt].actual_length =0 ; urb->iso_frame_desc[urbp->cnt].status = ret; -if (urbp->cnt +1 == urb->number_of_packets) -c67x00_giveback_urb (c67x00, urb,0 ); } urbp->ep_data->next_frame =frame_add (urbp->ep_data->next_frame, urb->interval); urbp->cnt++; +if (ret && urbp->cnt == urb->number_of_packets) +c67x00_giveback_urb (c67x00, urb,0 ); }return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 43/43 usb: usbfs: fix use-after-free of usb_device in usbdev_release()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miguel Peñaranda <[email protected]>
commit 0dd68b5d01d022fc9c5e71c82a82b0a94d3d0671 upstream.
usbdev_release() drops its reference to the struct usb_device before draining the list of completed async URBs, but that drain path reads back through the same object: free_async() calls dec_usb_memory_use_count() for any URB whose buffer came from the usbfs mmap() region, and its first statement is bus_to_hcd(ps->dev->bus).
After a disconnect the usbfs reference can be the last one, in which case usb_put_dev() frees the device and the subsequent loop reads offset 80 of freed memory and uses the result as a struct usb_hcd *, which hcd_buffer_free_pages() then dereferences.
This is reachable by an unprivileged process that has read/write access to a /dev/bus/usb node: mmap() the fd, submit one URB with a buffer inside the mapping, wait for the device to be unplugged, then munmap() and close(). It reproduces on every attempt rather than being a race, because a live MAP_SHARED vma holds a reference on the struct file, so usbdev_release() cannot run until the last vma is gone and the freeing branch of dec_usb_memory_use_count() is always taken.
BUG: KASAN: slab-use-after-free in dec_usb_memory_use_count+0x3ae/0x410 Read of size 8 at addr ffff8880122ee050 by task poc/769 CPU: 1 UID: 1000 PID: 769 Comm: poc Tainted: G B 6.12.94 #3 Call Trace: dec_usb_memory_use_count+0x3ae/0x410 free_async+0x2aa/0x4f0 usbdev_release+0x375/0x460 __fput+0x3ea/0xb50 __x64_sys_close+0x86/0x100 Allocated by task 11: usb_alloc_dev+0x55/0xd90 hub_event+0x2524/0x43d0 Freed by task 769: kfree+0x121/0x360 device_release+0xd2/0x280 usb_put_dev+0x23/0x30 usbdev_release+0x2d8/0x460
Release the device reference after the drain loop instead. Nothing between the two points requires it to have been dropped.
--- drivers/usb/core/devio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/core/devio.c +1 -1
@@ -1098,7 +1098,6 @@ static int usbdev_release(struct inode *if (!ps->suspend_allowed)usb_autosuspend_device (dev);usb_unlock_device (dev); -usb_put_dev (dev);put_pid (ps->disc_pid);put_cred (ps->cred);
@@ -1107,6 +1106,7 @@ static int usbdev_release(struct inode *free_async (as); as =async_getcompleted (ps); } +usb_put_dev (dev);kfree (ps);return 0 ;
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.269 release. There are 43 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 02 Sep 2026 13:32:19 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.269-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.10.y
and the diffstat can be found below.thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, build tested on BMIPS_GENERIC:
Signature · 1 line
Florian
# Librecast Test Results
020/020 [ OK ] liblcrq
010/010 [ OK ] libmld
120/120 [ OK ] liblibrecast
CPU/kernel: Linux auntie 5.10.269-rc1-01407-ga5b83a2b4fcc #1 SMP Mon Aug 31 19:17:25 -00 2026 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.269 release. There are 43 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Compiled an i386 kernel, installed and booted OK on a 32-bit EeePC. No problems noticed.
PS. Should the 5.10.269 patch include the fix from [email protected] [PATCH 5.10] Revert "USB: serial: keyspan_pda: fix information leak" ?
Greg Kroah-Hartman wrote on Mon, Aug 31, 2026 at 03:35:08PM +0200:
Quoted 5 lines
This is the start of the stable review cycle for the 5.10.269 release. There are 43 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Quoted 8 lines
Responses should be made by Wed, 02 Sep 2026 13:32:19 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.269-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.10.y
and the diffstat can be found below.
Tested a5b83a2b4fcc ("Linux 5.10.269-rc1") on:
- arm i.MX6ULL (Armadillo 640)
- arm64 i.MX8MP (Armadillo G4)
- arm64 i.MX8ULP (Armadillo IoT A9E)
No obvious regression in dmesg or basic tests:
Signature · 1 line
Dominique Martinet
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 5.10.269 release. There are 43 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
CIP testing did not find any problems here:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-5.10.y
Best regards,
Pavel
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.269 release. There are 43 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 02 Sep 2026 13:32:19 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.269-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.10.y
and the diffstat can be found below.thanks,
greg k-h
Compiled on my test system. No build regressions.
thanks,
-- Shuah
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 5.10.269 release. There are 43 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Wed, 02 Sep 2026 13:32:19 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.269-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-5.10.y
and the diffstat can be found below.thanks,
greg k-h
Tested on an amd64 laptop (Lenovo ThinkPad T14 Gen 1). Working well, no regressions observed.
Signature · 1 line
-Barry K. Nathan <[email protected]>