6.6.156-rc1 review
Greg Kroah-Hartman
maintainercover 6.6.156-rc1 review
This is the start of the stable review cycle for the 6.6.156 release. There are 91 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/v6.x/stable-review/patch-6.6.156-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-6.6.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 6.6.156-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
Will Porter <[email protected]>
ALSA: usb-audio: Complete cleanup after system-resume errors
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
Bartosz Golaszewski <[email protected]>
crypto: qce - Remove unsafe/deprecated algorithms
Thorsten Blum <[email protected]>
crypto: mxs-dcp - fix source scatterlist length access
Md Sadre Alam <[email protected]>
crypto: qce - fix CCM AAD buffer underallocation
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
Norbert Szetei <[email protected]>
net: bridge: mcast: fix use-after-free of a master VLAN's multicast context
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
Pratik Vishwakarma <[email protected]>
x86/CPU/AMD: Carve out a Zen5 models range
Perry Yuan <[email protected]>
x86/CPU/AMD: Add models 0x60-0x6f to the Zen5 range
Wenkuan Wang <[email protected]>
x86/CPU/AMD: Add models 0x10-0x1f to the Zen5 range
Mario Limonciello <[email protected]>
x86/CPU/AMD: Add more models to X86_FEATURE_ZEN5
Borislav Petkov (AMD) <[email protected]>
x86/CPU/AMD: Add X86_FEATURE_ZEN5
Jiayuan Chen <[email protected]>
tls: device: fix out-of-bounds write in tls_append_frag()
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
Baokun Li <[email protected]>
fuse: fix invalidate lock leak on open O_TRUNC DAX failure
Baokun Li <[email protected]>
fuse: fix invalidate lock leak on setattr writeback failure
Lucas De Marchi <[email protected]>
xhci: dbgtty: Fix unregister on tty_alloc_driver() failure
Lucas De Marchi <[email protected]>
xhci: dbgtty: Fix unregister on tty_register_driver() failure
Semih Baskan <[email protected]>
usb: xhci: Handle USB3 port events when there is one roothub
Haoxiang Li <[email protected]>
accessibility: speakup: unregister tty ldisc on later init failures
Griffin Kroah-Hartman <[email protected]>
fpga: dfl: fme: add error handling
Darrick J. Wong <[email protected]>
xfs: remove file_path tracepoint data
Chengfeng Ye <[email protected]>
Bluetooth: hci_sync: Fix accept list UAF during suspend
Zijun Hu <[email protected]>
Bluetooth: hci_sync: Use bt_dev_err() to log error message in hci_update_event_filter_sync()
Baul Lee <[email protected]>
HID: pidff: fix OOB write when hid->inputs is empty
Tomasz Pakuła <[email protected]>
HID: pidff: clang-format pass
Tomasz Pakuła <[email protected]>
HID: pidff: Support device error response from PID_BLOCK_LOAD
Ibrahim Hashimov <[email protected]>
HID: uclogic: fix use-after-free of inrange_timer on remove
Raman Varabets <[email protected]>
HID: ft260: fix stack-use-after-return write in I2C read race
Michael Zaidman <[email protected]>
HID: ft260: validate i2c input report length
Jiangshan Yi <[email protected]>
HID: nintendo: stop device IO before hid_hw_stop on probe failure
Ibrahim Hashimov <[email protected]>
nvmet-tcp: bound SGL data length before allocating command buffers
Weiwen Hu <[email protected]>
nvme: rename CDR/MORE/DNR to NVME_STATUS_*
Weiwen Hu <[email protected]>
nvme: fix status magic numbers
Weiwen Hu <[email protected]>
nvme: rename nvme_sc_to_pr_err to nvme_status_to_pr_err
Jose Villaseñor Montfort <[email protected]>
HID: magicmouse: prevent unbounded recursion in magicmouse_raw_event()
Christopher Kodama <[email protected]>
HID: magicmouse: re-enable multitouch after reset-resume
Bryam Vargas <[email protected]>
nfc: nci: add data_len bound checks to activation parameter extractors
Ryusuke Konishi <[email protected]>
nilfs2: reject invalid block index in GC ioctl
Ryusuke Konishi <[email protected]>
nilfs2: correct return value kernel-doc descriptions for ioctl functions
Guanghui Yang <[email protected]>
ext4: propagate errors from fast commit range replay
Baokun Li <[email protected]>
ext4: make some fast commit functions reuse extents path
Kemeng Shi <[email protected]>
ext4: make state in ext4_mb_mark_bb to be bool
DaeMyung Kang <[email protected]>
ksmbd: harden file lifetime during session teardown
Jia Jie Ho <[email protected]>
crypto: starfive - Do not free stack buffer
Aboorva Devarajan <[email protected]>
powerpc/hv-gpci: fix preempt count leak in sysfs show paths
Johannes Berg <[email protected]>
net/sched: initialize noop_qdisc owner
Eric Dumazet <[email protected]>
net/sched: Fix mirred deadlock on device recursion
Stephen Smalley <[email protected]>
selinux: switch two allocations to use kzalloc_objs()
Kuniyuki Iwashima <[email protected]>
smc: Use __sk_dst_get() and dst_dev_rcu() in smc_vlan_by_tcpsk().
Cristian Ciocaltea <[email protected]>
ASoC: nau8821: Cancel pending work before suspend
Sasha Levin <[email protected]>
Revert "PM: sleep: Use complete() in device_pm_sleep_init()"
Michael Neuling <[email protected]>
riscv: Fix register corruption from uninitialized cregs on error
Jiayuan Chen <[email protected]>
bpf: Fix use-after-free in offloaded map/prog info fill
Cristian Ciocaltea <[email protected]>
ASoC: nau8821: Cancel delayed work on component remove
Kuniyuki Iwashima <[email protected]>
smc: Use __sk_dst_get() and dst_dev_rcu() in smc_clc_prfx_match().
Kuniyuki Iwashima <[email protected]>
smc: Use __sk_dst_get() and dst_dev_rcu() in in smc_clc_prfx_set().
Oliver Upton <[email protected]>
KVM: arm64: Prevent access to vCPU events before init
Kuniyuki Iwashima <[email protected]>
smc: Fix use-after-free in __pnet_find_base_ndev().
Tetsuo Handa <[email protected]>
can: j1939: make j1939_sk_bind() fail if device is no longer registered
Tetsuo Handa <[email protected]>
can: j1939: add missing calls in NETDEV_UNREGISTER notification handler
Tetsuo Handa <[email protected]>
can: j1939: implement NETDEV_UNREGISTER notification handler
Vladimir Riabchun <[email protected]>
mISDN: hfcpci: Fix warning when deleting uninitialized timer
Wentao Liang <[email protected]>
media: platform: exynos4-is: Add hardware sync wait to fimc_is_hw_change_mode()
Namjae Jeon <[email protected]>
exfat: fix double free in delayed_free
Dylan Wolff <[email protected]>
jfs: Fix null-ptr-deref in jfs_ioc_trim
Nick Child <[email protected]>
ibmvnic: Use kernel helpers for hex dumps
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.
Kyle Zeng <[email protected]>
perf: Reject exited events as group leaders
Tao Lyu <[email protected]>
bpf: Ensure reg is PTR_TO_STACK in process_iter_arg
Ralf Lici <[email protected]>
Revert "usb: phy: fsl-usb: Fix use-after-free in delayed work during device removal"
Vishnu Razdan <[email protected]>
io_uring/io-wq: fix worker accounting when canceling creation callbacks
Eric Biggers <[email protected]>
ext4: don't enable DAX on new encrypted files
Jinu Kim <[email protected]>
KVM: x86/mmu: Check write tracking in all address spaces
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/powerpc/perf/hv-gpci.c | 24 +- arch/riscv/kernel/compat_signal.c | 2 + arch/riscv/kernel/ptrace.c | 4 +- arch/s390/kvm/vsie.c | 1 + arch/x86/include/asm/cpufeatures.h | 4 +- arch/x86/kernel/cpu/amd.c | 28 ++- arch/x86/kvm/mmu/page_track.c | 32 ++- 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/crypto/qce/aead.c | 58 +---- drivers/crypto/qce/common.c | 55 +---- drivers/crypto/qce/common.h | 16 +- drivers/crypto/qce/regs-v5.h | 4 - drivers/crypto/qce/sha.c | 30 +-- drivers/crypto/qce/sha.h | 1 - drivers/crypto/qce/skcipher.c | 97 +------- drivers/crypto/starfive/jh7110-rsa.c | 1 - drivers/fpga/dfl-fme-perf.c | 2 + drivers/hid/hid-ft260.c | 41 +++- drivers/hid/hid-magicmouse.c | 44 +++- drivers/hid/hid-nintendo.c | 13 +- drivers/hid/hid-uclogic-core.c | 12 +- drivers/hid/usbhid/hid-pidff.c | 21 +- drivers/infiniband/sw/rxe/rxe_qp.c | 3 +- drivers/isdn/hardware/mISDN/hfcpci.c | 12 +- .../platform/samsung/exynos4-is/fimc-is-regs.c | 1 + drivers/net/ethernet/ibm/ibmvnic.c | 30 ++- drivers/nvme/host/constants.c | 2 +- drivers/nvme/host/core.c | 32 +-- drivers/nvme/host/fabrics.c | 8 +- drivers/nvme/host/fault_inject.c | 2 +- drivers/nvme/host/fc.c | 8 +- drivers/nvme/host/multipath.c | 2 +- drivers/nvme/host/nvme.h | 4 +- drivers/nvme/host/pr.c | 10 +- drivers/nvme/target/admin-cmd.c | 24 +- drivers/nvme/target/core.c | 46 ++-- drivers/nvme/target/discovery.c | 14 +- drivers/nvme/target/fabrics-cmd-auth.c | 16 +- drivers/nvme/target/fabrics-cmd.c | 36 +-- drivers/nvme/target/io-cmd-bdev.c | 12 +- drivers/nvme/target/passthru.c | 10 +- drivers/nvme/target/rdma.c | 10 +- drivers/nvme/target/tcp.c | 17 +- drivers/nvme/target/zns.c | 30 +-- 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/host/xhci-dbgtty.c | 15 +- drivers/usb/host/xhci-ring.c | 2 +- drivers/usb/misc/usbtest.c | 1 + drivers/usb/phy/phy-fsl-usb.c | 1 - drivers/usb/serial/option.c | 20 +- drivers/usb/serial/spcp8x5.c | 13 -- fs/exfat/nls.c | 1 + fs/ext4/crypto.c | 40 ++-- fs/ext4/ext4.h | 2 +- fs/ext4/extents.c | 55 ++--- fs/ext4/fast_commit.c | 35 ++- fs/ext4/ialloc.c | 4 + fs/ext4/mballoc.c | 4 +- fs/fuse/dir.c | 9 +- fs/fuse/file.c | 4 +- fs/jfs/inode.c | 2 +- fs/jfs/jfs_discard.c | 3 +- fs/jfs/jfs_extent.c | 10 + fs/nilfs2/ioctl.c | 251 ++++++++++----------- fs/smb/server/smb2pdu.c | 6 +- fs/smb/server/vfs_cache.c | 179 +++++++++++++-- fs/smb/server/vfs_cache.h | 4 +- fs/xfs/scrub/trace.h | 12 +- include/linux/nvme.h | 16 +- include/net/sch_generic.h | 1 + include/target/target_core_fabric.h | 2 + io_uring/io-wq.c | 9 +- kernel/bpf/offload.c | 10 +- kernel/bpf/verifier.c | 5 + kernel/events/core.c | 10 + mm/swapfile.c | 7 + net/bluetooth/hci_sync.c | 48 +++- net/bridge/br_multicast.c | 4 +- net/can/j1939/j1939-priv.h | 1 + net/can/j1939/main.c | 5 + net/can/j1939/socket.c | 55 +++++ net/core/dev.c | 6 + net/core/filter.c | 1 - net/ipv6/ah6.c | 29 ++- net/ipv6/seg6_local.c | 7 + net/nfc/nci/ntf.c | 26 ++- net/sched/sch_generic.c | 2 + net/smc/smc_clc.c | 67 +++--- net/smc/smc_core.c | 27 +-- net/smc/smc_pnet.c | 43 ++-- net/tls/tls_device.c | 3 +- net/xfrm/espintcp.c | 9 +- net/xfrm/xfrm_user.c | 2 +- security/selinux/ss/conditional.c | 12 +- sound/soc/codecs/nau8821.c | 13 ++ sound/usb/card.c | 14 +- sound/usb/midi.c | 2 + 107 files changed, 1133 insertions(+), 846 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/91 RDMA/rxe: Fix OOB in free_rd_atomic_resources()
6.6-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
@@ -664,10 +664,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/91 KVM: x86/mmu: Check write tracking in all address spaces
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jinu Kim <[email protected]>
commit 0f38453cdb2e17566ccb7c0f3dabd5bd21caca26 upstream.
kvm_gfn_is_write_tracked() checks only the supplied memslot, but page tracking is per-address-space and shadow pages are shared across all address spaces. With SMM, a GFN can therefore be write-tracked in one address space and appear untracked through the other.
Check the supplied slot first, then the slot for the other address space. This ensures all callers honor write tracking regardless of the active address space. In particular, it prevents mmu_try_to_unsync_pages() from marking an upper-level shadow page unsync and eventually triggering the BUG in pte_list_remove().
Message-ID: <[email protected]>
[ artem: adapt to 6.6, which has neither KVM_MAX_NR_ADDRESS_SPACES nor
kvm_arch_nr_memslot_as_ids(); use KVM_ADDRESS_SPACE_NUM instead. That macro is CONFIG_KVM_SMM-conditional in 6.6, so the guard on KVM_ADDRESS_SPACE_NUM > 1 around the peer-slot lookup is retained ]
--- arch/x86/kvm/mmu/page_track.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-)
arch/x86/kvm/mmu/page_track.c +26 -6
@@ -117,13 +117,23 @@ void __kvm_write_track_remove_gfn(struct kvm *kvm,kvm_mmu_gfn_allow_lpage (slot, gfn); } -/* -* check if the corresponding access on the specified guest page is tracked. -*/ +static bool __kvm_gfn_is_write_tracked (const struct kvm_memory_slot *slot, +gfn_t gfn) +{ +int index; + +if (!slot) +return false; + + index =gfn_to_index (gfn, slot->base_gfn,PG_LEVEL_4K ); +return !!READ_ONCE (slot->arch.gfn_write_track[index]); +} + +/* check if write access is tracked on the specified guest page. */ bool kvm_gfn_is_write_tracked (struct kvm *kvm,const struct kvm_memory_slot *slot,gfn_t gfn) { -int index; +const struct kvm_memory_slot *other_slot;if (!slot)return false;
@@ -131,8 +141,18 @@ bool kvm_gfn_is_write_tracked(struct kvm *kvm,if (!kvm_page_track_write_tracking_enabled (kvm))return false; - index =gfn_to_index (gfn, slot->base_gfn,PG_LEVEL_4K ); -return !!READ_ONCE (slot->arch.gfn_write_track[index]); +BUILD_BUG_ON (KVM_ADDRESS_SPACE_NUM >2 ); + +if (__kvm_gfn_is_write_tracked (slot, gfn)) +return true; + +if (KVM_ADDRESS_SPACE_NUM >1 ) { + other_slot =__gfn_to_memslot (__kvm_memslots (kvm, slot->as_id ^1 ), gfn); +if (__kvm_gfn_is_write_tracked (other_slot, gfn)) +return true; + } + +return false; }#ifdef CONFIG_KVM_EXTERNAL_WRITE_TRACKING
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 3/91 ext4: dont enable DAX on new encrypted files
In reply to Greg Kroah-Hartman6.6-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/crypto.c | 40 ++++++++++++++++++++-------------------- fs/ext4/ialloc.c | 4 ++++ 2 files changed, 24 insertions(+), 20 deletions(-)
fs/ext4/crypto.c +20 -20
@@ -150,7 +150,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 ))
@@ -169,6 +175,14 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,*/ if (handle) { +/* +* __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 ;/* * Since the inode is new it is ok to pass the * XATTR_CREATE flag. This is necessary to match the
@@ -176,21 +190,10 @@ static int ext4_set_context(struct inode *inode, const void *ctx, size_t len,* function with the credits allocated for the new * inode. */ - res =ext4_xattr_set_handle (handle, inode, -EXT4_XATTR_INDEX_ENCRYPTION , -EXT4_XATTR_NAME_ENCRYPTION_CONTEXT , - ctx, len,XATTR_CREATE ); -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; +return ext4_xattr_set_handle (handle, inode, +EXT4_XATTR_INDEX_ENCRYPTION , +EXT4_XATTR_NAME_ENCRYPTION_CONTEXT , + ctx, len,XATTR_CREATE ); } res =dquot_initialize (inode);
@@ -211,10 +214,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)
fs/ext4/ialloc.c +4 -0
@@ -996,6 +996,8 @@ struct inode *__ext4_new_inode(struct mnt_idmap *idmap, err =fscrypt_prepare_new_inode (dir, inode, &encrypt);if (err) goto out; +if (encrypt) + i_flags |=EXT4_ENCRYPT_FL ; } err =dquot_initialize (inode);
@@ -1310,6 +1312,8 @@ struct inode *__ext4_new_inode(struct mnt_idmap *idmap, 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;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 4/91 io_uring/io-wq: fix worker accounting when canceling creation callbacks
In reply to Greg Kroah-Hartman6.6-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 wq->lock protecting worker accounting. ]
--- io_uring/io-wq.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
io_uring/io-wq.c +6 -3
@@ -193,9 +193,12 @@ static void io_worker_cancel_cb(struct io_worker *worker)struct io_wq *wq = worker->wq;atomic_dec (&acct->nr_running); -raw_spin_lock (&wq->lock); - acct->nr_workers--; -raw_spin_unlock (&wq->lock); +/* create_worker_cb() has not reserved a worker slot yet. */ +if (worker->create_work.func != create_worker_cb) { +raw_spin_lock (&wq->lock); + acct->nr_workers--; +raw_spin_unlock (&wq->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 5/91 Revert "usb: phy: fsl-usb: Fix use-after-free in delayed work during device removal"
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ralf Lici <[email protected]>
This reverts commit 319f7a85b3c4e34ac2fe083eb146fe129a556317.
The reverted commit uses disable_delayed_work_sync, which was introduced by commit 86898fa6b8cd ("workqueue: Implement disable/enable for (delayed) work items") in v6.10. The function is therefore unavailable in 6.6.y, causing configurations that enable CONFIG_FSL_USB2_OTG to fail to build.
The upstream commit is unaffected; only its incompatible stable backport is being reverted.
--- drivers/usb/phy/phy-fsl-usb.c | 1 - 1 file changed, 1 deletion(-)
drivers/usb/phy/phy-fsl-usb.c +0 -1
@@ -987,7 +987,6 @@ static void fsl_otg_remove(struct platform_device *pdev) {struct fsl_usb2_platform_data *pdata =dev_get_platdata (&pdev->dev); -disable_delayed_work_sync (&fsl_otg_dev->otg_event);usb_remove_phy (&fsl_otg_dev->phy);free_irq (fsl_otg_dev->irq, fsl_otg_dev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 6/91 bpf: Ensure reg is PTR_TO_STACK in process_iter_arg
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tao Lyu <[email protected]>
commit 12659d28615d606b36e382f4de2dd05550d202af upstream.
Currently, KF_ARG_PTR_TO_ITER handling missed checking the reg->type and ensuring it is PTR_TO_STACK. Instead of enforcing this in the caller of process_iter_arg, move the check into it instead so that all callers will gain the check by default. This is similar to process_dynptr_func.
An existing selftest in verifier_bits_iter.c fails due to this change, but it's because it was passing a NULL pointer into iter_next helper and getting an error further down the checks, but probably meant to pass an uninitialized iterator on the stack (as is done in the subsequent test below it). We will gain coverage for non-PTR_TO_STACK arguments in later patches hence just change the declaration to zero-ed stack object.
[ Xu Yunxiang: Resolve the verifier.c context conflict by retaining the
6.6.y BTF lookup and its regno diagnostic convention. Omit the verifier_bits_iter.c change because that selftest does not exist in 6.6.y. ]
[ sashal: print regno - 1 to match upstream and 6.6's own 0-based arg#
messages in check_kfunc_args(); supersedes the regno convention noted above ]
--- kernel/bpf/verifier.c | 5 +++++ 1 file changed, 5 insertions(+)
kernel/bpf/verifier.c +5 -0
@@ -7827,6 +7827,11 @@ static int process_iter_arg(struct bpf_verifier_env *env, int regno, int insn_idint spi, err, i, nr_slots;u32 btf_id; +if (reg->type !=PTR_TO_STACK ) { +verbose (env,"arg#%d expected pointer to an iterator on stack\n" , regno -1 ); +return -EINVAL ; + } +/* btf_check_iter_kfuncs() ensures we don't need to validate anything here */ arg = &btf_params (meta->func_proto)[0 ]; t =btf_type_skip_modifiers (meta->btf, arg->type,NULL );/* PTR */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 7/91 perf: Reject exited events as group leaders
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyle Zeng <[email protected]>
[ Upstream commit fa091f46c3833fb22384f10eade2b4e1e1d0b278 ]
perf_event_remove_on_exec() sets remove-on-exec events to the EXIT state and detaches their group relationships. The event's file descriptor can remain open, however, and perf_event_open() currently accepts that event as a group leader because its early validation rejects only REVOKED and DEAD events.
A new sibling can consequently be linked to the detached leader. When the leader is closed, perf_group_detach() observes that its PERF_ATTACH_GROUP bit is already clear and skips the new sibling. The sibling then retains a group_leader pointer to the freed event.
Reject group leaders in the EXIT state. Perform the check while holding the shared context mutex so that an exec in the target task cannot detach the leader between validation and group attachment.
--- kernel/events/core.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
kernel/events/core.c +10 -0
@@ -12692,6 +12692,10 @@ SYSCALL_DEFINE5(perf_event_open,if (err) goto err_fd; group_leader = group.file->private_data; +if (group_leader->state <=PERF_EVENT_STATE_EXIT ) { + err = -ENODEV ; + goto err_group_fd; + }if (flags &PERF_FLAG_FD_OUTPUT ) output_event = group_leader;if (flags &PERF_FLAG_FD_NO_GROUP )
@@ -12819,6 +12823,12 @@ SYSCALL_DEFINE5(perf_event_open,if (group_leader->ctx != ctx) goto err_locked; +/* Recheck under ctx::mutex to serialize against remove-on-exec. */ +if (group_leader->state <=PERF_EVENT_STATE_EXIT ) { + err = -ENODEV ; + goto err_locked; + } +/* * Only a group leader can be exclusive or pinned */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 8/91 bpf: Remove tst_run from lwt_seg6local_prog_ops.
In reply to Greg Kroah-Hartman6.6-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
@@ -11117,7 +11117,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 9/91 jfs: add check read-only before truncation in jfs_truncate_nolock()
In reply to Greg Kroah-Hartman6.6-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
@@ -375,7 +375,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 10/91 jfs: add check read-only before txBeginAnon() call
In reply to Greg Kroah-Hartman6.6-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
@@ -74,6 +74,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);
@@ -253,6 +258,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 11/91 ibmvnic: Use kernel helpers for hex dumps
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nick Child <[email protected]>
[ Upstream commit d93a6caab5d7d9b5ce034d75b1e1e993338e3852 ]
Previously, when the driver was printing hex dumps, the buffer was cast to an 8 byte long and printed using string formatters. If the buffer size was not a multiple of 8 then a read buffer overflow was possible.
Therefore, create a new ibmvnic function that loops over a buffer and calls hex_dump_to_buffer instead.
This patch address KASAN reports like the one below:
ibmvnic 30000003 env3: Login Buffer:
ibmvnic 30000003 env3: 01000000af000000 <...>
ibmvnic 30000003 env3: 2e6d62692e736261 ibmvnic 30000003 env3: 65050003006d6f63
==================================================================
BUG: KASAN: slab-out-of-bounds in ibmvnic_login+0xacc/0xffc [ibmvnic]
Read of size 8 at addr c0000001331a9aa8 by task ip/17681
<...>
Allocated by task 17681:
<...>
ibmvnic_login+0x2f0/0xffc [ibmvnic]
ibmvnic_open+0x148/0x308 [ibmvnic]
__dev_open+0x1ac/0x304
<...>
The buggy address is located 168 bytes inside of
allocated 175-byte region [c0000001331a9a00, c0000001331a9aaf)
<...>
=================================================================
ibmvnic 30000003 env3: 000000000033766e--- drivers/net/ethernet/ibm/ibmvnic.c | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-)
drivers/net/ethernet/ibm/ibmvnic.c +18 -12
@@ -4863,6 +4863,18 @@ static void vnic_add_client_data(struct ibmvnic_adapter *adapter,strscpy (vlcd->name, adapter->netdev->name, len); } +static void ibmvnic_print_hex_dump (struct net_device *dev,void *buf, +size_t len) +{ +unsigned char hex_str[16 *3 ]; + +for (size_t i =0 ; i < len; i +=16 ) { +hex_dump_to_buffer ((unsigned char *)buf + i, len - i,16 ,8 , + hex_str,sizeof (hex_str), false); +netdev_dbg (dev,"%s\n" , hex_str); + } +} +static int send_login (struct ibmvnic_adapter *adapter) {struct ibmvnic_login_rsp_buffer *login_rsp_buffer;
@@ -4973,10 +4985,8 @@ static int send_login(struct ibmvnic_adapter *adapter)vnic_add_client_data (adapter, vlcd);netdev_dbg (adapter->netdev,"Login Buffer:\n" ); -for (i =0 ; i < (adapter->login_buf_sz -1 ) /8 +1 ; i++) { -netdev_dbg (adapter->netdev,"%016lx\n" , - ((unsigned long *)(adapter->login_buf))[i]); - } +ibmvnic_print_hex_dump (adapter->netdev, adapter->login_buf, + adapter->login_buf_sz);memset (&crq,0 ,sizeof (crq)); crq.login.first =IBMVNIC_CRQ_CMD ;
@@ -5352,15 +5362,13 @@ static void handle_query_ip_offload_rsp(struct ibmvnic_adapter *adapter) {struct device *dev = &adapter->vdev->dev;struct ibmvnic_query_ip_offload_buffer *buf = &adapter->ip_offload_buf; -int i;dma_unmap_single (dev, adapter->ip_offload_tok,sizeof (adapter->ip_offload_buf),DMA_FROM_DEVICE );netdev_dbg (adapter->netdev,"Query IP Offload Buffer:\n" ); -for (i =0 ; i < (sizeof (adapter->ip_offload_buf) -1 ) /8 +1 ; i++) -netdev_dbg (adapter->netdev,"%016lx\n" , - ((unsigned long *)(buf))[i]); +ibmvnic_print_hex_dump (adapter->netdev, buf, +sizeof (adapter->ip_offload_buf));netdev_dbg (adapter->netdev,"ipv4_chksum = %d\n" , buf->ipv4_chksum);netdev_dbg (adapter->netdev,"ipv6_chksum = %d\n" , buf->ipv6_chksum);
@@ -5591,10 +5599,8 @@ static int handle_login_rsp(union ibmvnic_crq *login_rsp_crq, netdev->mtu = adapter->req_mtu -ETH_HLEN ;netdev_dbg (adapter->netdev,"Login Response Buffer:\n" ); -for (i =0 ; i < (adapter->login_rsp_buf_sz -1 ) /8 +1 ; i++) { -netdev_dbg (adapter->netdev,"%016lx\n" , - ((unsigned long *)(adapter->login_rsp_buf))[i]); - } +ibmvnic_print_hex_dump (netdev, adapter->login_rsp_buf, + adapter->login_rsp_buf_sz);/* Sanity checks */ if (login->num_txcomp_subcrqs != login_rsp->num_txsubm_subcrqs ||
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 12/91 jfs: Fix null-ptr-deref in jfs_ioc_trim
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dylan Wolff <[email protected]>
[ Upstream commit a4685408ff6c3e2af366ad9a7274f45ff3f394ee ]
[ Syzkaller Report ]
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000087: 0000 [#1 KASAN: null-ptr-deref in range [0x0000000000000438-0x000000000000043f] CPU: 2 UID: 0 PID: 10614 Comm: syz-executor.0 Not tainted 6.13.0-rc6-gfbfd64d25c7a-dirty #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014 Sched_ext: serialise (enabled+all), task: runnable_at=-30ms RIP: 0010:jfs_ioc_trim+0x34b/0x8f0 Code: e7 e8 59 a4 87 fe 4d 8b 24 24 4d 8d bc 24 38 04 00 00 48 8d 93 90 82 fe ff 4c 89 ff 31 f6 RSP: 0018:ffffc900055f7cd0 EFLAGS: 00010206 RAX: 0000000000000087 RBX: 00005866a9e67ff8 RCX: 000000000000000a RDX: 0000000000000001 RSI: 0000000000000004 RDI: 0000000000000001 RBP: dffffc0000000000 R08: ffff88807c180003 R09: 1ffff1100f830000 R10: dffffc0000000000 R11: ffffed100f830001 R12: 0000000000000000 R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000438 FS: 00007fe520225640(0000) GS:ffff8880b7e80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00005593c91b2c88 CR3: 000000014927c000 CR4: 00000000000006f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> ? __die_body+0x61/0xb0 ? die_addr+0xb1/0xe0 ? exc_general_protection+0x333/0x510 ? asm_exc_general_protection+0x26/0x30 ? jfs_ioc_trim+0x34b/0x8f0 jfs_ioctl+0x3c8/0x4f0 ? __pfx_jfs_ioctl+0x10/0x10 ? __pfx_jfs_ioctl+0x10/0x10 __se_sys_ioctl+0x269/0x350 ? __pfx___se_sys_ioctl+0x10/0x10 ? do_syscall_64+0xfb/0x210 do_syscall_64+0xee/0x210 ? syscall_exit_to_user_mode+0x1e0/0x330 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7fe51f4903ad Code: c3 e8 a7 2b 00 00 0f 1f 80 00 00 00 00 f3 0f 1e fa 48 89 f8 48
89 f7 48 89 d6 48 89 ca 4d
RSP: 002b:00007fe5202250c8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 00007fe51f5cbf80 RCX: 00007fe51f4903ad
RDX: 0000000020000680 RSI: 00000000c0185879 RDI: 0000000000000005
RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 00007fe520225640
R13: 000000000000000e R14: 00007fe51f44fca0 R15: 00007fe52021d000
</TASK> Modules linked in: ---[ end trace 0000000000000000 ]--- RIP: 0010:jfs_ioc_trim+0x34b/0x8f0 Code: e7 e8 59 a4 87 fe 4d 8b 24 24 4d 8d bc 24 38 04 00 00 48 8d 93 90 82 fe ff 4c 89 ff 31 f6 RSP: 0018:ffffc900055f7cd0 EFLAGS: 00010206 RAX: 0000000000000087 RBX: 00005866a9e67ff8 RCX: 000000000000000a RDX: 0000000000000001 RSI: 0000000000000004 RDI: 0000000000000001 RBP: dffffc0000000000 R08: ffff88807c180003 R09: 1ffff1100f830000 R10: dffffc0000000000 R11: ffffed100f830001 R12: 0000000000000000 R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000438 FS: 00007fe520225640(0000) GS:ffff8880b7e80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00005593c91b2c88 CR3: 000000014927c000 CR4: 00000000000006f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Kernel panic - not syncing: Fatal exception
[ Analysis ]
We believe that we have found a concurrency bug in the fs/jfs module that results in a null pointer dereference. There is a closely related issue which has been fixed:
... but, unfortunately, the accepted patch appears to still be susceptible to a null pointer dereference under some interleavings.
To trigger the bug, we think that JFS_SBI(ipbmap->i_sb)->bmap is set to NULL in dbFreeBits and then dereferenced in jfs_ioc_trim. This bug manifests quite rarely under normal circumstances, but is triggereable from a syz-program.
--- fs/jfs/jfs_discard.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/jfs/jfs_discard.c +2 -1
@@ -86,7 +86,8 @@ int jfs_ioc_trim(struct inode *ip, struct fstrim_range *range)down_read (&sb->s_umount); bmp =JFS_SBI (ip->i_sb)->bmap; -if (minlen > bmp->db_agsize || +if (bmp ==NULL || + minlen > bmp->db_agsize || start >= bmp->db_mapsize || range->len < sb->s_blocksize) {up_read (&sb->s_umount);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 13/91 exfat: fix double free in delayed_free
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit 1f3d9724e16d62c7d42c67d6613b8512f2887c22 ]
The double free could happen in the following path.
exfat_create_upcase_table()
exfat_create_upcase_table() : return error
exfat_free_upcase_table() : free ->vol_utbl
exfat_load_default_upcase_table : return error
exfat_kill_sb()
delayed_free()
exfat_free_upcase_table() <--------- double freeThis patch set ->vol_util as NULL after freeing it.
--- fs/exfat/nls.c | 1 + 1 file changed, 1 insertion(+)
fs/exfat/nls.c +1 -0
@@ -804,4 +804,5 @@ int exfat_create_upcase_table(struct super_block *sb)void exfat_free_upcase_table (struct exfat_sb_info *sbi) {kvfree (sbi->vol_utbl); + sbi->vol_utbl =NULL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 14/91 media: platform: exynos4-is: Add hardware sync wait to fimc_is_hw_change_mode()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <[email protected]>
[ Upstream commit bd9f6ce7d512fa21249415c16af801a4ed5d97b6 ]
In fimc_is_hw_change_mode(), the function changes camera modes without waiting for hardware completion, risking corrupted data or system hangs if subsequent operations proceed before the hardware is ready.
Add fimc_is_hw_wait_intmsr0_intmsd0() after mode configuration, ensuring hardware state synchronization and stable interrupt handling.
--- drivers/media/platform/samsung/exynos4-is/fimc-is-regs.c | 1 + 1 file changed, 1 insertion(+)
drivers/media/platform/samsung/exynos4-is/fimc-is-regs.c +1 -0
@@ -164,6 +164,7 @@ int fimc_is_hw_change_mode(struct fimc_is *is)if (WARN_ON (is->config_index >=ARRAY_SIZE (cmd)))return -EINVAL ; +fimc_is_hw_wait_intmsr0_intmsd0 (is);mcuctl_write (cmd[is->config_index], is,MCUCTL_REG_ISSR (0 ));mcuctl_write (is->sensor_index, is,MCUCTL_REG_ISSR (1 ));mcuctl_write (is->setfile.sub_index, is,MCUCTL_REG_ISSR (2 ));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 15/91 mISDN: hfcpci: Fix warning when deleting uninitialized timer
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vladimir Riabchun <[email protected]>
[ Upstream commit 97766512a9951b9fd6fc97f1b93211642bb0b220 ]
With CONFIG_DEBUG_OBJECTS_TIMERS unloading hfcpci module leads to the following splat:
[ 250.215892] ODEBUG: assert_init not available (active state 0) object: ffffffffc01a3dc0 object type: timer_list hint: 0x0 [ 250.217520] WARNING: CPU: 0 PID: 233 at lib/debugobjects.c:612 debug_print_object+0x1b6/0x2c0 [ 250.218775] Modules linked in: hfcpci(-) mISDN_core [ 250.219537] CPU: 0 UID: 0 PID: 233 Comm: rmmod Not tainted 6.17.0-rc2-g6f713187ac98 #2 PREEMPT(voluntary) [ 250.220940] Hardware name: QEMU Ubuntu 24.04 PC (i440FX + PIIX, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 [ 250.222377] RIP: 0010:debug_print_object+0x1b6/0x2c0 [ 250.223131] Code: fc ff df 48 89 fa 48 c1 ea 03 80 3c 02 00 75 4f 41 56 48 8b 14 dd a0 4e 01 9f 48 89 ee 48 c7 c7 20 46 01 9f e8 cb 84d [ 250.225805] RSP: 0018:ffff888015ea7c08 EFLAGS: 00010286 [ 250.226608] RAX: 0000000000000000 RBX: 0000000000000005 RCX: ffffffff9be93a95 [ 250.227708] RDX: 1ffff1100d945138 RSI: 0000000000000008 RDI: ffff88806ca289c0 [ 250.228993] RBP: ffffffff9f014a00 R08: 0000000000000001 R09: ffffed1002bd4f39 [ 250.230043] R10: ffff888015ea79cf R11: 0000000000000001 R12: 0000000000000001 [ 250.231185] R13: ffffffff9eea0520 R14: 0000000000000000 R15: ffff888015ea7cc8 [ 250.232454] FS: 00007f3208f01540(0000) GS:ffff8880caf5a000(0000) knlGS:0000000000000000 [ 250.233851] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 250.234856] CR2: 00007f32090a7421 CR3: 0000000004d63000 CR4: 00000000000006f0 [ 250.236117] Call Trace: [ 250.236599] <TASK> [ 250.236967] ? trace_irq_enable.constprop.0+0xd4/0x130 [ 250.237920] debug_object_assert_init+0x1f6/0x310 [ 250.238762] ? __pfx_debug_object_assert_init+0x10/0x10 [ 250.239658] ? __lock_acquire+0xdea/0x1c70 [ 250.240369] __try_to_del_timer_sync+0x69/0x140 [ 250.241172] ? __pfx___try_to_del_timer_sync+0x10/0x10 [ 250.242058] ? __timer_delete_sync+0xc6/0x120 [ 250.242842] ? lock_acquire+0x30/0x80 [ 250.243474] ? __timer_delete_sync+0xc6/0x120 [ 250.244262] __timer_delete_sync+0x98/0x120 [ 250.245015] HFC_cleanup+0x10/0x20 [hfcpci] [ 250.245704] __do_sys_delete_module+0x348/0x510 [ 250.246461] ? __pfx___do_sys_delete_module+0x10/0x10 [ 250.247338] do_syscall_64+0xc1/0x360 [ 250.247924] entry_SYSCALL_64_after_hwframe+0x77/0x7f
Fix this by initializing hfc_tl timer with DEFINE_TIMER macro. Also, use mod_timer instead of manual timeout update.
--- drivers/isdn/hardware/mISDN/hfcpci.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-)
drivers/isdn/hardware/mISDN/hfcpci.c +5 -7
@@ -39,12 +39,13 @@#include "hfc_pci.h" +static void hfcpci_softirq (struct timer_list *unused);static const char *hfcpci_revision ="2.0" ;static int HFC_cnt;static uint debug;static uint poll, tics; -static struct timer_list hfc_tl; +static DEFINE_TIMER(hfc_tl, hfcpci_softirq);static unsigned long hfc_jiffies;MODULE_AUTHOR ("Karsten Keil" );
@@ -2304,8 +2305,7 @@ hfcpci_softirq(struct timer_list *unused) hfc_jiffies = jiffies +1 ; else hfc_jiffies += tics; - hfc_tl.expires = hfc_jiffies; -add_timer (&hfc_tl); +mod_timer (&hfc_tl, hfc_jiffies); } static int __init
@@ -2331,10 +2331,8 @@ HFC_init(void)if (poll !=HFCPCI_BTRANS_THRESHOLD ) {printk (KERN_INFO "%s: Using alternative poll value of %d\n" , __func__, poll); -timer_setup (&hfc_tl, hfcpci_softirq,0 ); - hfc_tl.expires = jiffies + tics; - hfc_jiffies = hfc_tl.expires; -add_timer (&hfc_tl); + hfc_jiffies = jiffies + tics; +mod_timer (&hfc_tl, hfc_jiffies); }else tics =0 ;/* indicate the use of controller's timer */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 16/91 can: j1939: implement NETDEV_UNREGISTER notification handler
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tetsuo Handa <[email protected]>
[ Upstream commit 7fcbe5b2c6a4b5407bf2241fdb71e0a390f6ab9a ]
syzbot is reporting
unregister_netdevice: waiting for vcan0 to become free. Usage count = 2
problem, for j1939 protocol did not have NETDEV_UNREGISTER notification handler for undoing changes made by j1939_sk_bind().
Commit 25fe97cb7620 ("can: j1939: move j1939_priv_put() into sk_destruct callback") expects that a call to j1939_priv_put() can be unconditionally delayed until j1939_sk_sock_destruct() is called. But we need to call j1939_priv_put() against an extra ref held by j1939_sk_bind() call (as a part of undoing changes made by j1939_sk_bind()) as soon as NETDEV_UNREGISTER notification fires (i.e. before j1939_sk_sock_destruct() is called via j1939_sk_release()). Otherwise, the extra ref on "struct j1939_priv" held by j1939_sk_bind() call prevents "struct net_device" from dropping the usage count to 1; making it impossible for unregister_netdevice() to continue.
--- net/can/j1939/j1939-priv.h | 1 + net/can/j1939/main.c | 3 +++ net/can/j1939/socket.c | 49 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 53 insertions(+)
net/can/j1939/j1939-priv.h +1 -0
@@ -214,6 +214,7 @@ void j1939_priv_get(struct j1939_priv *priv);/* notify/alert all j1939 sockets bound to ifindex */ void j1939_sk_netdev_event_netdown (struct j1939_priv *priv); +void j1939_sk_netdev_event_unregister (struct j1939_priv *priv);int j1939_cancel_active_session (struct j1939_priv *priv,struct sock *sk);void j1939_tp_init (struct j1939_priv *priv);
net/can/j1939/main.c +3 -0
@@ -377,6 +377,9 @@ static int j1939_netdev_notify(struct notifier_block *nb,j1939_sk_netdev_event_netdown (priv);j1939_ecu_unmap_all (priv);break ; +case NETDEV_UNREGISTER : +j1939_sk_netdev_event_unregister (priv); +break ; }j1939_priv_put (priv);
net/can/j1939/socket.c +49 -0
55 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 17/91 can: j1939: add missing calls in NETDEV_UNREGISTER notification handler
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tetsuo Handa <[email protected]>
[ Upstream commit 93a27b5891b8194a8c083c9a80d2141d4bf47ba8 ]
Currently NETDEV_UNREGISTER event handler is not calling j1939_cancel_active_session() and j1939_sk_queue_drop_all(). This will result in these calls being skipped when j1939_sk_release() is called. And I guess that the reason syzbot is still reporting
unregister_netdevice: waiting for vcan0 to become free. Usage count = 2
is caused by lack of these calls.
Calling j1939_cancel_active_session(priv, sk) from j1939_sk_release() can be covered by calling j1939_cancel_active_session(priv, NULL) from j1939_netdev_notify().
Calling j1939_sk_queue_drop_all() from j1939_sk_release() can be covered by calling j1939_sk_netdev_event_netdown() from j1939_netdev_notify().
Therefore, we can reuse j1939_cancel_active_session(priv, NULL) and j1939_sk_netdev_event_netdown(priv) for NETDEV_UNREGISTER event handler.
--- net/can/j1939/main.c | 2 ++ 1 file changed, 2 insertions(+)
net/can/j1939/main.c +2 -0
@@ -378,6 +378,8 @@ static int j1939_netdev_notify(struct notifier_block *nb,j1939_ecu_unmap_all (priv);break ;case NETDEV_UNREGISTER : +j1939_cancel_active_session (priv,NULL ); +j1939_sk_netdev_event_netdown (priv);j1939_sk_netdev_event_unregister (priv);break ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 18/91 can: j1939: make j1939_sk_bind() fail if device is no longer registered
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tetsuo Handa <[email protected]>
[ Upstream commit 46cea215dc9444ec32a76b1b6a9cb809e17b64d5 ]
There is a theoretical race window in j1939_sk_netdev_event_unregister() where two j1939_sk_bind() calls jump in between read_unlock_bh() and lock_sock().
The assumption jsk->priv == priv can fail if the first j1939_sk_bind() call once made jsk->priv == NULL due to failed j1939_local_ecu_get() call and the second j1939_sk_bind() call again made jsk->priv != NULL due to successful j1939_local_ecu_get() call.
Since the socket lock is held by both j1939_sk_netdev_event_unregister() and j1939_sk_bind(), checking ndev->reg_state with the socket lock held can reliably make the second j1939_sk_bind() call fail (and close this race window).
--- net/can/j1939/socket.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/can/j1939/socket.c +6 -0
@@ -481,6 +481,12 @@ static int j1939_sk_bind(struct socket *sock, struct sockaddr *uaddr, int len) goto out_release_sock; } +if (ndev->reg_state !=NETREG_REGISTERED ) { +dev_put (ndev); + ret = -ENODEV ; + goto out_release_sock; + } + can_ml =can_get_ml_priv (ndev);if (!can_ml) {dev_put (ndev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 19/91 smc: Fix use-after-free in __pnet_find_base_ndev().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 3d3466878afd8d43ec0ca2facfbc7f03e40d0f79 ]
syzbot reported use-after-free of net_device in __pnet_find_base_ndev(), which was called during connect(). [0]
smc_pnet_find_ism_resource() fetches sk_dst_get(sk)->dev and passes down to pnet_find_base_ndev(), where RTNL is held. Then, UAF happened at __pnet_find_base_ndev() when the dev is first used.
This means dev had already been freed before acquiring RTNL in pnet_find_base_ndev().
While dev is going away, dst->dev could be swapped with blackhole_netdev, and the dev's refcnt by dst will be released.
We must hold dev's refcnt before calling smc_pnet_find_ism_resource().
Also, smc_pnet_find_roce_resource() has the same problem.
Let's use __sk_dst_get() and dst_dev_rcu() in the two functions.
[0]:
BUG: KASAN: use-after-free in __pnet_find_base_ndev+0x1b1/0x1c0 net/smc/smc_pnet.c:926
Read of size 1 at addr ffff888036bac33a by task syz.0.3632/18609
CPU: 1 UID: 0 PID: 18609 Comm: syz.0.3632 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/18/2025
Call Trace:
<TASK>
dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120
print_address_description mm/kasan/report.c:378 [inline]
print_report+0xca/0x240 mm/kasan/report.c:482
kasan_report+0x118/0x150 mm/kasan/report.c:595
__pnet_find_base_ndev+0x1b1/0x1c0 net/smc/smc_pnet.c:926
pnet_find_base_ndev net/smc/smc_pnet.c:946 [inline]
smc_pnet_find_ism_by_pnetid net/smc/smc_pnet.c:1103 [inline]
smc_pnet_find_ism_resource+0xef/0x390 net/smc/smc_pnet.c:1154
smc_find_ism_device net/smc/af_smc.c:1030 [inline]
smc_find_proposal_devices net/smc/af_smc.c:1115 [inline]
__smc_connect+0x372/0x1890 net/smc/af_smc.c:1545
smc_connect+0x877/0xd90 net/smc/af_smc.c:1715
__sys_connect_file net/socket.c:2086 [inline]
__sys_connect+0x313/0x440 net/socket.c:2105
__do_sys_connect net/socket.c:2111 [inline]
__se_sys_connect net/socket.c:2108 [inline]
__x64_sys_connect+0x7a/0x90 net/socket.c:2108
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f47cbf8eba9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 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 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f47ccdb1038 EFLAGS: 00000246 ORIG_RAX: 000000000000002a
RAX: ffffffffffffffda RBX: 00007f47cc1d5fa0 RCX: 00007f47cbf8eba9
RDX: 0000000000000010 RSI: 0000200000000280 RDI: 000000000000000b
RBP: 00007f47cc011e19 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f47cc1d6038 R14: 00007f47cc1d5fa0 R15: 00007ffc512f8aa8
</TASK>
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff888036bacd00 pfn:0x36bac
flags: 0xfff00000000000(node=0|zone=1|lastcpupid=0x7ff)
raw: 00fff00000000000 ffffea0001243d08 ffff8880b863fdc0 0000000000000000
raw: ffff888036bacd00 0000000000000000 00000000ffffffff 0000000000000000
page dumped because: kasan: bad access detected
page_owner tracks the page as freed
page last allocated via order 2, migratetype Unmovable, gfp_mask 0x446dc0(GFP_KERNEL_ACCOUNT|__GFP_ZERO|__GFP_NOWARN|__GFP_RETRY_MAYFAIL|__GFP_COMP), pid 16741, tgid 16741 (syz-executor), ts 343313197788, free_ts 380670750466
set_page_owner include/linux/page_owner.h:32 [inline]
post_alloc_hook+0x240/0x2a0 mm/page_alloc.c:1851
prep_new_page mm/page_alloc.c:1859 [inline]
get_page_from_freelist+0x21e4/0x22c0 mm/page_alloc.c:3858
__alloc_frozen_pages_noprof+0x181/0x370 mm/page_alloc.c:5148
alloc_pages_mpol+0x232/0x4a0 mm/mempolicy.c:2416
___kmalloc_large_node+0x5f/0x1b0 mm/slub.c:4317
__kmalloc_large_node_noprof+0x18/0x90 mm/slub.c:4348
__do_kmalloc_node mm/slub.c:4364 [inline]
__kvmalloc_node_noprof+0x6d/0x5f0 mm/slub.c:5067
alloc_netdev_mqs+0xa3/0x11b0 net/core/dev.c:11812
tun_set_iff+0x532/0xef0 drivers/net/tun.c:2775
__tun_chr_ioctl+0x788/0x1df0 drivers/net/tun.c:3085
vfs_ioctl fs/ioctl.c:51 [inline]
__do_sys_ioctl fs/ioctl.c:598 [inline]
__se_sys_ioctl+0xfc/0x170 fs/ioctl.c:584
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
page last free pid 18610 tgid 18608 stack trace:
reset_page_owner include/linux/page_owner.h:25 [inline]
free_pages_prepare mm/page_alloc.c:1395 [inline]
__free_frozen_pages+0xbc4/0xd30 mm/page_alloc.c:2895
free_large_kmalloc+0x13a/0x1f0 mm/slub.c:4820
device_release+0x99/0x1c0 drivers/base/core.c:-1
kobject_cleanup lib/kobject.c:689 [inline]
kobject_release lib/kobject.c:720 [inline]
kref_put include/linux/kref.h:65 [inline]
kobject_put+0x22b/0x480 lib/kobject.c:737
netdev_run_todo+0xd2e/0xea0 net/core/dev.c:11513
rtnl_unlock net/core/rtnetlink.c:157 [inline]
rtnl_net_unlock include/linux/rtnetlink.h:135 [inline]
rtnl_dellink+0x537/0x710 net/core/rtnetlink.c:3563
rtnetlink_rcv_msg+0x7cc/0xb70 net/core/rtnetlink.c:6946
netlink_rcv_skb+0x208/0x470 net/netlink/af_netlink.c:2552
netlink_unicast_kernel net/netlink/af_netlink.c:1320 [inline]
netlink_unicast+0x82f/0x9e0 net/netlink/af_netlink.c:1346
netlink_sendmsg+0x805/0xb30 net/netlink/af_netlink.c:1896
sock_sendmsg_nosec net/socket.c:714 [inline]
__sock_sendmsg+0x219/0x270 net/socket.c:729
____sys_sendmsg+0x505/0x830 net/socket.c:2614
___sys_sendmsg+0x21f/0x2a0 net/socket.c:2668
__sys_sendmsg net/socket.c:2700 [inline]
__do_sys_sendmsg net/socket.c:2705 [inline]
__se_sys_sendmsg net/socket.c:2703 [inline]
__x64_sys_sendmsg+0x19b/0x260 net/socket.c:2703
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Memory state around the buggy address:
ffff888036bac200: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff888036bac280: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>ffff888036bac300: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
^
ffff888036bac380: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff888036bac400: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff--- net/smc/smc_pnet.c | 43 ++++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 21 deletions(-)
net/smc/smc_pnet.c +22 -21
@@ -1131,37 +1131,38 @@ static void smc_pnet_find_ism_by_pnetid(struct net_device *ndev,*/ void smc_pnet_find_roce_resource (struct sock *sk,struct smc_init_info *ini) { -struct dst_entry *dst =sk_dst_get (sk); - -if (!dst) - goto out; -if (!dst->dev) - goto out_rel; +struct net_device *dev; +struct dst_entry *dst; -smc_pnet_find_roce_by_pnetid (dst->dev, ini); +rcu_read_lock (); + dst =__sk_dst_get (sk); + dev = dst ?dst_dev_rcu (dst) :NULL ; +dev_hold (dev); +rcu_read_unlock (); -out_rel: -dst_release (dst); -out: -return ; +if (dev) { +smc_pnet_find_roce_by_pnetid (dev, ini); +dev_put (dev); + } }void smc_pnet_find_ism_resource (struct sock *sk,struct smc_init_info *ini) { -struct dst_entry *dst =sk_dst_get (sk); +struct net_device *dev; +struct dst_entry *dst; ini->ism_dev[0 ] =NULL ; -if (!dst) - goto out; -if (!dst->dev) - goto out_rel; -smc_pnet_find_ism_by_pnetid (dst->dev, ini); +rcu_read_lock (); + dst =__sk_dst_get (sk); + dev = dst ?dst_dev_rcu (dst) :NULL ; +dev_hold (dev); +rcu_read_unlock (); -out_rel: -dst_release (dst); -out: -return ; +if (dev) { +smc_pnet_find_ism_by_pnetid (dev, ini); +dev_put (dev); + } }/* Lookup and apply a pnet table entry to the given ib device.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 20/91 KVM: arm64: Prevent access to vCPU events before init
In reply to Greg Kroah-Hartman6.6-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
@@ -1497,6 +1497,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 ;
@@ -1508,6 +1511,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 21/91 smc: Use __sk_dst_get() and dst_dev_rcu() in in smc_clc_prfx_set().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 935d783e5de9b64587f3adb25641dd8385e64ddb ]
smc_clc_prfx_set() is called during connect() and not under RCU nor RTNL.
Using sk_dst_get(sk)->dev could trigger UAF.
Let's use __sk_dst_get() and dev_dst_rcu() under rcu_read_lock() after kernel_getsockname().
Note that the returned value of smc_clc_prfx_set() is not used in the caller.
While at it, we change the 1st arg of smc_clc_prfx_set[46]_rcu() not to touch dst there.
--- net/smc/smc_clc.c | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-)
net/smc/smc_clc.c +22 -19
@@ -508,10 +508,10 @@ static bool smc_clc_msg_hdr_valid(struct smc_clc_msg_hdr *clcm, bool check_trl) }/* find ipv4 addr on device and get the prefix len, fill CLC proposal msg */ -static int smc_clc_prfx_set4_rcu (struct dst_entry *dst,__be32 ipv4, +static int smc_clc_prfx_set4_rcu (struct net_device *dev,__be32 ipv4,struct smc_clc_msg_proposal_prefix *prop) { -struct in_device *in_dev =__in_dev_get_rcu (dst->dev); +struct in_device *in_dev =__in_dev_get_rcu (dev);const struct in_ifaddr *ifa;if (!in_dev)
@@ -529,12 +529,12 @@ static int smc_clc_prfx_set4_rcu(struct dst_entry *dst, __be32 ipv4, }/* fill CLC proposal msg with ipv6 prefixes from device */ -static int smc_clc_prfx_set6_rcu (struct dst_entry *dst, +static int smc_clc_prfx_set6_rcu (struct net_device *dev,struct smc_clc_msg_proposal_prefix *prop,struct smc_clc_ipv6_prefix *ipv6_prfx) {#if IS_ENABLED (CONFIG_IPV6 ) -struct inet6_dev *in6_dev =__in6_dev_get (dst->dev); +struct inet6_dev *in6_dev =__in6_dev_get (dev);struct inet6_ifaddr *ifa;int cnt =0 ;
@@ -563,41 +563,44 @@ static int smc_clc_prfx_set(struct socket *clcsock,struct smc_clc_msg_proposal_prefix *prop, struct smc_clc_ipv6_prefix *ipv6_prfx) { - struct dst_entry *dst = sk_dst_get(clcsock->sk); struct sockaddr_storage addrs;struct sockaddr_in6 *addr6;struct sockaddr_in *addr; +struct net_device *dev; +struct dst_entry *dst;int rc = -ENOENT ; -if (!dst) { - rc = -ENOTCONN ; - goto out; - } -if (!dst->dev) { - rc = -ENODEV ; - goto out_rel; - }/* get address to which the internal TCP socket is bound */ if (kernel_getsockname (clcsock, (struct sockaddr *)&addrs) <0 ) - goto out_rel; + goto out; +/* analyze IP specific data of net_device belonging to TCP socket */ addr6 = (struct sockaddr_in6 *)&addrs; +rcu_read_lock (); + + dst =__sk_dst_get (clcsock->sk); + dev = dst ?dst_dev_rcu (dst) :NULL ; +if (!dev) { + rc = -ENODEV ; + goto out_unlock; + } +if (addrs.ss_family ==PF_INET ) {/* IPv4 */ addr = (struct sockaddr_in *)&addrs; - rc =smc_clc_prfx_set4_rcu (dst, addr->sin_addr.s_addr, prop); + rc =smc_clc_prfx_set4_rcu (dev, addr->sin_addr.s_addr, prop); }else if (ipv6_addr_v4mapped (&addr6->sin6_addr)) {/* mapped IPv4 address - peer is IPv4 only */ - rc =smc_clc_prfx_set4_rcu (dst, addr6->sin6_addr.s6_addr32[3 ], + rc =smc_clc_prfx_set4_rcu (dev, addr6->sin6_addr.s6_addr32[3 ], prop); }else {/* IPv6 */ - rc =smc_clc_prfx_set6_rcu (dst, prop, ipv6_prfx); + rc =smc_clc_prfx_set6_rcu (dev, prop, ipv6_prfx); } + +out_unlock:rcu_read_unlock (); -out_rel: -dst_release (dst); out:return rc; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 22/91 smc: Use __sk_dst_get() and dst_dev_rcu() in smc_clc_prfx_match().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 235f81045c008169cc4e1955b4a64e118eebe61b ]
smc_clc_prfx_match() is called from smc_listen_work() and not under RCU nor RTNL.
Using sk_dst_get(sk)->dev could trigger UAF.
Let's use __sk_dst_get() and dst_dev_rcu().
Note that the returned value of smc_clc_prfx_match() is not used in the caller.
--- net/smc/smc_clc.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
net/smc/smc_clc.c +13 -13
@@ -656,26 +656,26 @@ static int smc_clc_prfx_match6_rcu(struct net_device *dev,int smc_clc_prfx_match (struct socket *clcsock,struct smc_clc_msg_proposal_prefix *prop) { -struct dst_entry *dst =sk_dst_get (clcsock->sk); +struct net_device *dev; +struct dst_entry *dst;int rc; -if (!dst) { - rc = -ENOTCONN ; - goto out; - } -if (!dst->dev) { +rcu_read_lock (); + + dst =__sk_dst_get (clcsock->sk); + dev = dst ?dst_dev_rcu (dst) :NULL ; +if (!dev) { rc = -ENODEV ; - goto out_rel; + goto out; } -rcu_read_lock (); +if (!prop->ipv6_prefixes_cnt) - rc =smc_clc_prfx_match4_rcu (dst->dev, prop); + rc =smc_clc_prfx_match4_rcu (dev, prop);else - rc =smc_clc_prfx_match6_rcu (dst->dev, prop); -rcu_read_unlock (); -out_rel: -dst_release (dst); + rc =smc_clc_prfx_match6_rcu (dev, prop); out: +rcu_read_unlock (); +return rc; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 23/91 ASoC: nau8821: Cancel delayed work on component remove
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cristian Ciocaltea <[email protected]>
[ Upstream commit dbd3fd05cddfdeec1e49b0a66269881c09eebd17 ]
Attempting to unload the driver while a jack detection work is pending would likely crash the kernel when it is eventually scheduled for execution:
[ 1984.896308] BUG: unable to handle page fault for address: ffffffffc10c2a20 [...] [ 1984.896388] Hardware name: Valve Jupiter/Jupiter, BIOS F7A0131 01/30/2024 [ 1984.896396] Workqueue: events nau8821_jdet_work [snd_soc_nau8821] [ 1984.896414] RIP: 0010:__mutex_lock+0x9f/0x11d0 [...] [ 1984.896504] Call Trace: [ 1984.896511] <TASK> [ 1984.896524] ? snd_soc_dapm_disable_pin+0x26/0x60 [snd_soc_core] [ 1984.896572] ? snd_soc_dapm_disable_pin+0x26/0x60 [snd_soc_core] [ 1984.896596] snd_soc_dapm_disable_pin+0x26/0x60 [snd_soc_core] [ 1984.896622] nau8821_jdet_work+0xeb/0x1e0 [snd_soc_nau8821] [ 1984.896636] process_one_work+0x211/0x590 [ 1984.896649] ? srso_return_thunk+0x5/0x5f [ 1984.896670] worker_thread+0x1cd/0x3a0
Cancel unscheduled jdet_work or wait for its execution to finish before the component driver gets removed.
--- sound/soc/codecs/nau8821.c | 9 +++++++++ 1 file changed, 9 insertions(+)
sound/soc/codecs/nau8821.c +9 -0
@@ -1275,6 +1275,14 @@ static int nau8821_component_probe(struct snd_soc_component *component)return 0 ; } +static void nau8821_component_remove (struct snd_soc_component *component) +{ +struct nau8821 *nau8821 =snd_soc_component_get_drvdata (component); + +if (nau8821->jdet_active) +cancel_delayed_work_sync (&nau8821->jdet_work); +}; +/** * nau8821_calc_fll_param - Calculate FLL parameters. * @fll_in: external clock provided to codec.
@@ -1633,6 +1641,7 @@ static int __maybe_unused nau8821_resume(struct snd_soc_component *component)static const struct snd_soc_component_driver nau8821_component_driver = { .probe = nau8821_component_probe, + .remove = nau8821_component_remove, .set_sysclk = nau8821_set_sysclk, .set_pll = nau8821_set_fll, .set_bias_level = nau8821_set_bias_level,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 24/91 bpf: Fix use-after-free in offloaded map/prog info fill
In reply to Greg Kroah-Hartman6.6-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
@@ -437,9 +437,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 ;
@@ -645,9 +644,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 25/91 riscv: Fix register corruption from uninitialized cregs on error
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Neuling <[email protected]>
[ Upstream commit 6ebcbb53fc9bc30843054ed99fd60b8e542628f4 ]
compat_riscv_gpr_set() calls cregs_to_regs() unconditionally, even when user_regset_copyin() fails. Since cregs is an uninitialized stack variable, a copyin failure causes uninitialized stack data to be written into the target task's pt_regs, corrupting its register state and potentially leaking kernel stack contents.
compat_restore_sigcontext() has the same issue: it calls cregs_to_regs() even when __copy_from_user() fails, leading to the same corruption of the signal-returning task's register state on error.
Only call cregs_to_regs() when the user copy succeeds.
--- arch/riscv/kernel/compat_signal.c | 2 ++ arch/riscv/kernel/ptrace.c | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-)
arch/riscv/kernel/compat_signal.c +2 -0
@@ -107,6 +107,8 @@ static long compat_restore_sigcontext(struct pt_regs *regs,/* sc_regs is structured the same as the start of pt_regs */ err =__copy_from_user (&cregs, &sc->sc_regs,sizeof (sc->sc_regs)); +if (unlikely (err)) +return err;cregs_to_regs (&cregs, regs);
arch/riscv/kernel/ptrace.c +2 -2
@@ -327,8 +327,8 @@ static int compat_riscv_gpr_set(struct task_struct *target,struct compat_user_regs_struct cregs; ret =user_regset_copyin (&pos, &count, &kbuf, &ubuf, &cregs,0 ,-1 ); - -cregs_to_regs (&cregs,task_pt_regs (target)); +if (!ret) +cregs_to_regs (&cregs,task_pt_regs (target));return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 26/91 Revert "PM: sleep: Use complete() in device_pm_sleep_init()"
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
This reverts commit 59096e2aa0f66008fab21a3ebf8e097bc026c060.
--- drivers/base/power/main.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/base/power/main.c +1 -5
@@ -101,7 +101,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); }
@@ -238,10 +238,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 27/91 ASoC: nau8821: Cancel pending work before suspend
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cristian Ciocaltea <[email protected]>
[ Upstream commit 7786b10688ac0ebeaff655923cbb2c7d34a98995 ]
A jack detection work that is unscheduled or in progress while executing the suspend handler could trigger a race condition.
Ensure state consistency by cancelling any pending work or wait for its execution to complete before processing the suspend. Since driver (re)enables both insert and eject interrupts on resume, there is no risk to miss the related jack events. Therefore, flush_delayed_work() is not required here.
--- sound/soc/codecs/nau8821.c | 4 ++++ 1 file changed, 4 insertions(+)
sound/soc/codecs/nau8821.c +4 -0
@@ -1617,6 +1617,10 @@ static int __maybe_unused nau8821_suspend(struct snd_soc_component *component)if (nau8821->irq)disable_irq (nau8821->irq); + +if (nau8821->jdet_active) +cancel_delayed_work_sync (&nau8821->jdet_work); +snd_soc_component_force_bias_level (component,SND_SOC_BIAS_OFF );/* Power down codec power; don't support button wakeup */ snd_soc_component_disable_pin (component,"MICBIAS" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 28/91 smc: Use __sk_dst_get() and dst_dev_rcu() in smc_vlan_by_tcpsk().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 0b0e4d51c6554e5ecc3f8cc73c2eaf12da21249a ]
smc_vlan_by_tcpsk() fetches sk_dst_get(sk)->dev before RTNL and passes it to netdev_walk_all_lower_dev(), which is illegal.
Also, smc_vlan_by_tcpsk_walk() does not require RTNL at all.
Let's use __sk_dst_get(), dst_dev_rcu(), andnetdev_walk_all_lower_dev_rcu().
Note that the returned value of smc_vlan_by_tcpsk() is not used in the caller.
--- net/smc/smc_core.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-)
net/smc/smc_core.c +12 -15
@@ -1827,35 +1827,32 @@ static int smc_vlan_by_tcpsk_walk(struct net_device *lower_dev,/* Determine vlan of internal TCP socket. */ int smc_vlan_by_tcpsk (struct socket *clcsock,struct smc_init_info *ini) { -struct dst_entry *dst =sk_dst_get (clcsock->sk);struct netdev_nested_priv priv;struct net_device *ndev; +struct dst_entry *dst;int rc =0 ; ini->vlan_id =0 ; -if (!dst) { - rc = -ENOTCONN ; - goto out; - } -if (!dst->dev) { + +rcu_read_lock (); + + dst =__sk_dst_get (clcsock->sk); + ndev = dst ?dst_dev_rcu (dst) :NULL ; +if (!ndev) { rc = -ENODEV ; - goto out_rel; + goto out; } - ndev = dst->dev;if (is_vlan_dev (ndev)) { ini->vlan_id =vlan_dev_vlan_id (ndev); - goto out_rel; + goto out; } priv.data = (void *)&ini->vlan_id; -rtnl_lock (); -netdev_walk_all_lower_dev (ndev, smc_vlan_by_tcpsk_walk, &priv); -rtnl_unlock (); - -out_rel: -dst_release (dst); +netdev_walk_all_lower_dev_rcu (ndev, smc_vlan_by_tcpsk_walk, &priv); out: +rcu_read_unlock (); +return rc; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 29/91 selinux: switch two allocations to use kzalloc_objs()
In reply to Greg Kroah-Hartman6.6-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 30/91 net/sched: Fix mirred deadlock on device recursion
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 0f022d32c3eca477fbf79a205243a6123ed0fe11 ]
When the mirred action is used on a classful egress qdisc and a packet is mirrored or redirected to self we hit a qdisc lock deadlock. See trace below.
[..... other info removed for brevity....]
[ 82.890906]
[ 82.890906] ============================================
[ 82.890906] WARNING: possible recursive locking detected
[ 82.890906] 6.8.0-05205-g77fadd89fe2d-dirty #213 Tainted: G W
[ 82.890906] --------------------------------------------
[ 82.890906] ping/418 is trying to acquire lock:
[ 82.890906] ffff888006994110 (&sch->q.lock){+.-.}-{3:3}, at:
__dev_queue_xmit+0x1778/0x3550
[ 82.890906]
[ 82.890906] but task is already holding lock:
[ 82.890906] ffff888006994110 (&sch->q.lock){+.-.}-{3:3}, at:
__dev_queue_xmit+0x1778/0x3550
[ 82.890906]
[ 82.890906] other info that might help us debug this:
[ 82.890906] Possible unsafe locking scenario:
[ 82.890906]
[ 82.890906] CPU0
[ 82.890906] ----
[ 82.890906] lock(&sch->q.lock);
[ 82.890906] lock(&sch->q.lock);
[ 82.890906]
[ 82.890906] *** DEADLOCK ***
[ 82.890906][..... other info removed for brevity....]
Example setup (eth0->eth0) to recreate
tc qdisc add dev eth0 root handle 1: htb default 30 tc filter add dev eth0 handle 1: protocol ip prio 2 matchall \
action mirred egress redirect dev eth0
Another example(eth0->eth1->eth0) to recreate
tc qdisc add dev eth0 root handle 1: htb default 30 tc filter add dev eth0 handle 1: protocol ip prio 2 matchall \
action mirred egress redirect dev eth1
tc qdisc add dev eth1 root handle 1: htb default 30 tc filter add dev eth1 handle 1: protocol ip prio 2 matchall \
action mirred egress redirect dev eth0
We fix this by adding an owner field (CPU id) to struct Qdisc set after root qdisc is entered. When the softirq enters it a second time, if the qdisc owner is the same CPU, the packet is dropped to break the loop.
--- include/net/sch_generic.h | 1 + net/core/dev.c | 6 ++++++ net/sched/sch_generic.c | 1 + 3 files changed, 8 insertions(+)
include/net/sch_generic.h +1 -0
@@ -117,6 +117,7 @@ struct Qdisc {struct qdisc_skb_head q;struct gnet_stats_basic_sync bstats;struct gnet_stats_queue qstats; +int owner;unsigned long state;unsigned long state2;/* must be written under qdisc spinlock */ struct Qdisc *next_sched;
net/core/dev.c +6 -0
@@ -3901,6 +3901,10 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,return rc; } +if (unlikely (READ_ONCE (q->owner) ==smp_processor_id ())) { +kfree_skb_reason (skb,SKB_DROP_REASON_TC_RECLASSIFY_LOOP ); +return NET_XMIT_DROP ; + }/* * Heuristic to force contended enqueues to serialize on a * separate lock before trying to get qdisc main lock.
@@ -3940,7 +3944,9 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q,qdisc_run_end (q); rc =NET_XMIT_SUCCESS ; }else { +WRITE_ONCE (q->owner,smp_processor_id ()); rc =dev_qdisc_enqueue (skb, q, &to_free, txq); +WRITE_ONCE (q->owner,-1 );if (qdisc_run_begin (q)) {if (unlikely (contended)) {spin_unlock (&q->busylock);
net/sched/sch_generic.c +1 -0
@@ -986,6 +986,7 @@ struct Qdisc *qdisc_alloc(struct netdev_queue *dev_queue, sch->enqueue = ops->enqueue; sch->dequeue = ops->dequeue; sch->dev_queue = dev_queue; + sch->owner =-1 ;netdev_hold (dev, &sch->dev_tracker,GFP_KERNEL );refcount_set (&sch->refcnt,1 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 31/91 net/sched: initialize noop_qdisc owner
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 44180feaccf266d9b0b28cc4ceaac019817deb5c ]
When the noop_qdisc owner isn't initialized, then it will be 0, so packets will erroneously be regarded as having been subject to recursion as long as only CPU 0 queues them. For non-SMP, that's all packets, of course. This causes a change in what's reported to userspace, normally noop_qdisc would drop packets silently, but with this change the syscall returns -ENOBUFS if RECVERR is also set on the socket.
Fix this by initializing the owner field to -1, just like it would be for dynamically allocated qdiscs by qdisc_alloc().
--- net/sched/sch_generic.c | 1 + 1 file changed, 1 insertion(+)
net/sched/sch_generic.c +1 -0
@@ -684,6 +684,7 @@ struct Qdisc noop_qdisc = { .qlen = 0, .lock = __SPIN_LOCK_UNLOCKED(noop_qdisc.skb_bad_txq.lock), }, + .owner = -1, };EXPORT_SYMBOL (noop_qdisc);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 32/91 powerpc/hv-gpci: fix preempt count leak in sysfs show paths
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aboorva Devarajan <[email protected]>
[ Upstream commit dbc30a57bd8e026995e9fa8e8c31cffd18542c01 ]
Four sysfs show() callbacks in hv-gpci take get_cpu_var(hv_gpci_reqb) (which calls preempt_disable()) but only call the matching put_cpu_var() on the error path under the 'out:' label. Every successful read leaks one preempt_disable():
processor_bus_topology_show()
processor_config_show()
affinity_domain_via_virtual_processor_show()
affinity_domain_via_domain_show()
(affinity_domain_via_partition_show() was already correct.)
On a CONFIG_PREEMPT=y kernel, repeated reads raise preempt_count and eventually return to userspace with preemption still disabled. The next user-mode page fault then hits faulthandler_disabled() == 1, gets forced to SIGSEGV, and the resulting coredump trips 'BUG: scheduling while atomic' in call_usermodehelper_exec -> wait_for_completion_state -> schedule:
BUG: scheduling while atomic: <task>/<pid>/0x00000004 ... __schedule_bug+0x6c/0x90 __schedule+0x58c/0x13a0 schedule+0x48/0x1a0 schedule_timeout+0x104/0x170 wait_for_completion_state+0x16c/0x330 call_usermodehelper_exec+0x254/0x2d0 vfs_coredump+0x1050/0x2590 get_signal+0xb9c/0xc80 do_notify_resume+0xf8/0x470
Add an out_success label that calls put_cpu_var() before returning the byte count, mirroring affinity_domain_via_partition_show().
--- arch/powerpc/perf/hv-gpci.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-)
arch/powerpc/perf/hv-gpci.c +16 -8
@@ -210,7 +210,7 @@ static ssize_t processor_bus_topology_show(struct device *dev, struct device_att 0, 0, buf, &n, arg);if (!ret) -return n; + goto out_success;if (ret !=H_PARAMETER ) goto out;
@@ -244,12 +244,14 @@ static ssize_t processor_bus_topology_show(struct device *dev, struct device_att starting_index, 0, buf, &n, arg);if (!ret) -return n; + goto out_success;if (ret !=H_PARAMETER ) goto out; } +out_success: +put_cpu_var (hv_gpci_reqb);return n; out:
@@ -278,7 +280,7 @@ static ssize_t processor_config_show(struct device *dev, struct device_attribute 0, 0, buf, &n, arg);if (!ret) -return n; + goto out_success;if (ret !=H_PARAMETER ) goto out;
@@ -312,12 +314,14 @@ static ssize_t processor_config_show(struct device *dev, struct device_attribute starting_index, 0, buf, &n, arg);if (!ret) -return n; + goto out_success;if (ret !=H_PARAMETER ) goto out; } +out_success: +put_cpu_var (hv_gpci_reqb);return n; out:
@@ -346,7 +350,7 @@ static ssize_t affinity_domain_via_virtual_processor_show(struct device *dev, 0, 0, buf, &n, arg);if (!ret) -return n; + goto out_success;if (ret !=H_PARAMETER ) goto out;
@@ -382,12 +386,14 @@ static ssize_t affinity_domain_via_virtual_processor_show(struct device *dev, starting_index, secondary_index, buf, &n, arg);if (!ret) -return n; + goto out_success;if (ret !=H_PARAMETER ) goto out; } +out_success: +put_cpu_var (hv_gpci_reqb);return n; out:
@@ -416,7 +422,7 @@ static ssize_t affinity_domain_via_domain_show(struct device *dev, struct device 0, 0, buf, &n, arg);if (!ret) -return n; + goto out_success;if (ret !=H_PARAMETER ) goto out;
@@ -448,12 +454,14 @@ static ssize_t affinity_domain_via_domain_show(struct device *dev, struct device starting_index, 0, buf, &n, arg);if (!ret) -return n; + goto out_success;if (ret !=H_PARAMETER ) goto out; } +out_success: +put_cpu_var (hv_gpci_reqb);return n; out:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 33/91 crypto: starfive - Do not free stack buffer
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jia Jie Ho <[email protected]>
[ Upstream commit d7f01649f4eaf1878472d3d3f480ae1e50d98f6c ]
RSA text data uses variable length buffer allocated in software stack. Calling kfree on it causes undefined behaviour in subsequent operations.
--- drivers/crypto/starfive/jh7110-rsa.c | 1 - 1 file changed, 1 deletion(-)
drivers/crypto/starfive/jh7110-rsa.c +0 -1
@@ -303,7 +303,6 @@ static int starfive_rsa_enc_core(struct starfive_cryp_ctx *ctx, int enc) err_rsa_crypt:writel (STARFIVE_RSA_RESET , cryp->base +STARFIVE_PKA_CACR_OFFSET ); -kfree (rctx->rsa_data);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 34/91 ksmbd: harden file lifetime during session teardown
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: DaeMyung Kang <[email protected]>
commit a42896bebfcc287ed1e61d820a888e33b1eb80ce upstream.
__close_file_table_ids() is the per-session teardown that closes every fp belonging to a session (or to one tree connect on that session) by walking the session's volatile-id idr. The current loop has three related problems on busy or racing workloads:
* Sleeping under ft->lock. The session-teardown skip callback, session_fd_check(), already sleeps in ksmbd_vfs_copy_durable_owner() -> kstrdup(GFP_KERNEL) and down_write(&fp->f_ci->m_lock) (a rw_semaphore). Running the callback inside write_lock(&ft->lock) trips CONFIG_DEBUG_ATOMIC_SLEEP / CONFIG_PROVE_LOCKING on a durable-fd workload.
* Refcount accounting blind to f_state. The unconditional atomic_dec_and_test(&fp->refcount) does not distinguish FP_INITED (idr-owned reference still intact) from FP_CLOSED (an earlier ksmbd_close_fd() already consumed the idr-owned reference while leaving fp in the idr because a holder kept refcount non-zero). When the latter races with teardown the same path over-decrements into a holder reference and ksmbd_fd_put() later UAFs that holder.
* FP_NEW window. Between __open_id() publishing fp into the session idr and ksmbd_update_fstate(..., FP_INITED) committing the transition at the end of smb2_open(), an fp is in FP_NEW and an intervening teardown that takes a transient reference and unpublishes the volatile id leaves the original idr-owned reference orphaned -- the opener is unaware that fp has been unpublished, returns success to the client, and the fp leaks at refcount = 1.
Refactor __close_file_table_ids() to take a transient reference on fp and unpublish fp from the session idr *under ft->lock* before calling skip() outside the lock. A transient ref protects lifetime but not concurrent field mutation, so the idr_remove() is what keeps __ksmbd_lookup_fd() through this session's idr from granting a new ksmbd_fp_get() reference to an fp whose fp->conn / fp->tcon / fp->volatile_id / op->conn / lock_list links are about to be rewritten by session_fd_check(). Durable reconnect is unaffected because it reaches fp through the global durable table (ksmbd_lookup_durable_fd -> global_ft).
Decide n_to_drop together with any FP_INITED -> FP_CLOSED transition under ft->lock so teardown and ksmbd_close_fd() never both consume the idr-owned reference. See ksmbd_mark_fp_closed() for the per-state accounting. For the FP_NEW path to be safe, the opener has to learn that fp was unpublished: ksmbd_update_fstate() now returns -ENOENT when an FP_NEW -> FP_INITED transition finds f_state already advanced or the volatile id cleared (both committed by teardown under ft->lock); smb2_open() propagates that as STATUS_OBJECT_NAME_INVALID and drops the original reference via ksmbd_fd_put().
The list removal cannot be left for a deferred final putter because fp->volatile_id has already been cleared and __ksmbd_remove_fd() will intentionally skip both idr_remove() and list_del_init(). Move the m_fp_list unlink in __ksmbd_remove_fd() above the volatile-id check so that an FP_NEW fp that happened to be added to m_fp_list (smb2_open() adds fp->node before ksmbd_update_fstate() runs) is still cleaned up on the deferred putter path; list_del_init() on an empty node is a no-op and remains safe for fps that were never added.
Add a defensive guard in session_fd_check() that refuses non-FP_INITED fps so that even if a teardown reaches an FP_NEW fp it falls into the close branch (where the n_to_drop = 1 accounting keeps the opener's reference alive) instead of the durable-preserve branch (which mutates fp->conn / fp->tcon).
Validation on a debug kernel additionally built with CONFIG_DEBUG_LIST and CONFIG_DEBUG_OBJECTS_WORK used a same-session two-tcon workload (open/write storm on one tcon, 50 tree disconnects on the other) and reported no list-corruption, work_struct ODEBUG, sleep-in-atomic, lockdep or kmemleak reports. Reverting only the __close_file_table_ids() hunk while keeping a forced-is_reconnectable() harness produced the expected sleep-in-atomic at vfs_cache.c:1095, confirming the ft->lock-out-of-sleepable-skip discipline.
KASAN-enabled direct SMB2 coverage with durable handles enabled exercised ksmbd_close_tree_conn_fds(), ksmbd_close_session_fds(), the FP_NEW failure path, tree_conn_fd_check(), and a non-zero session_fd_check() durable-preserve return. This produced no KASAN, DEBUG_LIST, ODEBUG, or WARNING reports.
--- fs/smb/server/smb2pdu.c | 6 + fs/smb/server/vfs_cache.c | 179 ++++++++++++++++++++++++++++++++++++++++------ fs/smb/server/vfs_cache.h | 4 - 3 files changed, 164 insertions(+), 25 deletions(-)
fs/smb/server/smb2pdu.c +4 -2
@@ -3751,8 +3751,10 @@ err_out1: err_out2:if (!rc) { -ksmbd_update_fstate (&work->sess->file_table, fp,FP_INITED ); - rc =ksmbd_iov_pin_rsp (work, (void *)rsp, iov_len); + rc =ksmbd_update_fstate (&work->sess->file_table, fp, +FP_INITED ); +if (!rc) + rc =ksmbd_iov_pin_rsp (work, (void *)rsp, iov_len); }if (rc) {if (rc == -EINVAL )
fs/smb/server/vfs_cache.c +158 -21
252 lines not on this page · raw message
fs/smb/server/vfs_cache.h +2 -2
@@ -172,8 +172,8 @@ int ksmbd_close_inode_fds(struct ksmbd_wint ksmbd_init_global_file_table (void );void ksmbd_free_global_file_table (void );void ksmbd_set_fd_limit (unsigned long limit); -void ksmbd_update_fstate (struct ksmbd_file_table *ft,struct ksmbd_file *fp, -unsigned int state); +int ksmbd_update_fstate (struct ksmbd_file_table *ft,struct ksmbd_file *fp, +unsigned int state);bool ksmbd_vfs_compare_durable_owner (struct ksmbd_file *fp,struct ksmbd_user *user);
Greg Kroah-Hartman
maintainerPATCH 35/91 ext4: make state in ext4_mb_mark_bb to be bool
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kemeng Shi <[email protected]>
[ Upstream commit d2f7cf40ea89b486fb7a25f5ab9a5d3ce26fb4bb ]
As state could only be either 0 or 1, just make it bool.
Stable-dep-of: d8b8dd3530bf ("ext4: propagate errors from fast commit range replay")
--- fs/ext4/ext4.h | 2 +- fs/ext4/extents.c | 4 ++-- fs/ext4/fast_commit.c | 8 ++++---- fs/ext4/mballoc.c | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-)
fs/ext4/ext4.h +1 -1
@@ -2940,7 +2940,7 @@ extern int ext4_group_add_blocks(handle_extern int ext4_trim_fs (struct super_block *,struct fstrim_range *);extern void ext4_process_freed_data (struct super_block *sb,tid_t commit_tid);extern void ext4_mb_mark_bb (struct super_block *sb,ext4_fsblk_t block, -int len,int state); +int len,bool state);static inline bool ext4_mb_cr_expensive (enum criteria cr) {return cr >=CR_GOAL_LEN_SLOW ;
fs/ext4/extents.c +2 -2
@@ -6207,13 +6207,13 @@ int ext4_ext_clear_bb(struct inode *inodfor (j =0 ; j < path->p_depth; j++) {ext4_mb_mark_bb (inode->i_sb, - path[j].p_block,1 ,0 ); + path[j].p_block,1 , false);ext4_fc_record_regions (inode->i_sb, inode->i_ino,0 , path[j].p_block,1 ,1 ); }ext4_free_ext_path (path); } -ext4_mb_mark_bb (inode->i_sb, map.m_pblk, map.m_len,0 ); +ext4_mb_mark_bb (inode->i_sb, map.m_pblk, map.m_len, false);ext4_fc_record_regions (inode->i_sb, inode->i_ino, map.m_lblk, map.m_pblk, map.m_len,1 ); }
fs/ext4/fast_commit.c +4 -4
@@ -1838,7 +1838,7 @@ static int ext4_fc_replay_add_range(stru* at the end of the FC replay using our array of * modified inodes. */ -ext4_mb_mark_bb (inode->i_sb, map.m_pblk, map.m_len,0 ); +ext4_mb_mark_bb (inode->i_sb, map.m_pblk, map.m_len, false); goto next; }
@@ -1907,7 +1907,7 @@ ext4_fc_replay_del_range(struct super_blif (ret >0 ) { remaining -= ret; cur += ret; -ext4_mb_mark_bb (inode->i_sb, map.m_pblk, map.m_len,0 ); +ext4_mb_mark_bb (inode->i_sb, map.m_pblk, map.m_len, false); }else { remaining -= map.m_len; cur += map.m_len;
@@ -1966,12 +1966,12 @@ static void ext4_fc_set_bitmaps_and_counif (!IS_ERR (path)) {for (j =0 ; j < path->p_depth; j++)ext4_mb_mark_bb (inode->i_sb, - path[j].p_block,1 ,1 ); + path[j].p_block,1 , true);ext4_free_ext_path (path); } cur += ret;ext4_mb_mark_bb (inode->i_sb, map.m_pblk, - map.m_len,1 ); + map.m_len, true); }else { cur = cur + (map.m_len ? map.m_len :1 ); }
fs/ext4/mballoc.c +2 -2
@@ -4121,7 +4121,7 @@ out_err:* blocks in bitmaps and update counters. */ void ext4_mb_mark_bb (struct super_block *sb,ext4_fsblk_t block, -int len,int state) +int len,bool state) {struct buffer_head *bitmap_bh =NULL ;struct ext4_group_desc *gdp;
@@ -6158,7 +6158,7 @@ ext4_mb_new_blocks_simple(struct ext4_al } block =ext4_group_first_block_no (sb, group) +EXT4_C2B (sbi, i); -ext4_mb_mark_bb (sb, block,1 ,1 ); +ext4_mb_mark_bb (sb, block,1 , true); ar->len =1 ; *errp =0 ;
Greg Kroah-Hartman
maintainerPATCH 36/91 ext4: make some fast commit functions reuse extents path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
[ Upstream commit 2352e3e461926b59f01c1e39fbb0494891cff997 ]
The ext4_find_extent() can update the extent path so that it does not have to allocate and free the path repeatedly, thus reducing the consumption of memory allocation and freeing in the following functions:
ext4_ext_clear_bb
ext4_ext_replay_set_iblocks
ext4_fc_replay_add_range
ext4_fc_set_bitmaps_and_counters
No functional changes. Note that ext4_find_extent() does not support error pointers, so in this case set path to NULL first.
Stable-dep-of: d8b8dd3530bf ("ext4: propagate errors from fast commit range replay")
--- fs/ext4/extents.c | 51 +++++++++++++++++++++----------------------------- fs/ext4/fast_commit.c | 11 ++++++---- 2 files changed, 29 insertions(+), 33 deletions(-)
fs/ext4/extents.c +22 -29
@@ -6092,12 +6092,9 @@ int ext4_ext_replay_set_iblocks(struct iif (IS_ERR (path))return PTR_ERR (path); ex = path[path->p_depth].p_ext; -if (!ex) { -ext4_free_ext_path (path); +if (!ex) goto out; - } end =le32_to_cpu (ex->ee_block) +ext4_ext_get_actual_len (ex); -ext4_free_ext_path (path);/* Count the number of data blocks */ cur =0 ;
@@ -6123,32 +6120,28 @@ int ext4_ext_replay_set_iblocks(struct i ret =skip_hole (inode, &cur);if (ret <0 ) goto out; - path =ext4_find_extent (inode, cur,NULL ,0 ); + path =ext4_find_extent (inode, cur, path,0 );if (IS_ERR (path)) goto out; numblks += path->p_depth; -ext4_free_ext_path (path);while (cur < end) { - path =ext4_find_extent (inode, cur,NULL ,0 ); + path =ext4_find_extent (inode, cur, path,0 );if (IS_ERR (path))break ; ex = path[path->p_depth].p_ext; -if (!ex) { -ext4_free_ext_path (path); -return 0 ; - } +if (!ex) + goto cleanup; + cur =max (cur +1 ,le32_to_cpu (ex->ee_block) +ext4_ext_get_actual_len (ex)); ret =skip_hole (inode, &cur); -if (ret <0 ) { -ext4_free_ext_path (path); +if (ret <0 )break ; - } - path2 =ext4_find_extent (inode, cur,NULL ,0 ); -if (IS_ERR (path2)) { -ext4_free_ext_path (path); + + path2 =ext4_find_extent (inode, cur, path2,0 ); +if (IS_ERR (path2))break ; - } +for (i =0 ; i <=max (path->p_depth, path2->p_depth); i++) { cmp1 = cmp2 =0 ;if (i <= path->p_depth)
@@ -6160,13 +6153,14 @@ int ext4_ext_replay_set_iblocks(struct iif (cmp1 != cmp2 && cmp2 !=0 ) numblks++; } -ext4_free_ext_path (path); -ext4_free_ext_path (path2); } out: inode->i_blocks = numblks << (inode->i_sb->s_blocksize_bits -9 );ext4_mark_inode_dirty (NULL , inode); +cleanup: +ext4_free_ext_path (path); +ext4_free_ext_path (path2);return 0 ; }
@@ -6187,12 +6181,9 @@ int ext4_ext_clear_bb(struct inode *inodif (IS_ERR (path))return PTR_ERR (path); ex = path[path->p_depth].p_ext; -if (!ex) { -ext4_free_ext_path (path); -return 0 ; - } +if (!ex) + goto out; end =le32_to_cpu (ex->ee_block) +ext4_ext_get_actual_len (ex); -ext4_free_ext_path (path); cur =0 ;while (cur < end) {
@@ -6202,16 +6193,16 @@ int ext4_ext_clear_bb(struct inode *inodif (ret <0 )break ;if (ret >0 ) { - path =ext4_find_extent (inode, map.m_lblk,NULL ,0 ); -if (!IS_ERR_OR_NULL (path)) { + path =ext4_find_extent (inode, map.m_lblk, path,0 ); +if (!IS_ERR (path)) {for (j =0 ; j < path->p_depth; j++) { -ext4_mb_mark_bb (inode->i_sb, path[j].p_block,1 , false);ext4_fc_record_regions (inode->i_sb, inode->i_ino,0 , path[j].p_block,1 ,1 ); } -ext4_free_ext_path (path); + }else { + path =NULL ; }ext4_mb_mark_bb (inode->i_sb, map.m_pblk, map.m_len, false); ext4_fc_record_regions(inode->i_sb, inode->i_ino,
@@ -6220,5 +6211,7 @@ int ext4_ext_clear_bb(struct inode *inod cur = cur + map.m_len; } +out: +ext4_free_ext_path (path);return 0 ; }
fs/ext4/fast_commit.c +7 -4
@@ -1798,7 +1798,7 @@ static int ext4_fc_replay_add_range(struif (ret ==0 ) {/* Range is not mapped */ - path =ext4_find_extent (inode, cur,NULL ,0 ); + path =ext4_find_extent (inode, cur, path,0 );if (IS_ERR (path)) goto out;memset (&newex,0 ,sizeof (newex));
@@ -1814,7 +1814,6 @@ static int ext4_fc_replay_add_range(struup_write ((&EXT4_I (inode)->i_data_sem));if (IS_ERR (path)) goto out; -ext4_free_ext_path (path); goto next; }
@@ -1862,6 +1861,7 @@ next:ext4_ext_replay_shrink_inode (inode,i_size_read (inode) >> sb->s_blocksize_bits); out: +ext4_free_ext_path (path);iput (inode);return 0 ; }
@@ -1962,12 +1962,13 @@ static void ext4_fc_set_bitmaps_and_counbreak ;if (ret >0 ) { - path =ext4_find_extent (inode, map.m_lblk,NULL ,0 ); + path =ext4_find_extent (inode, map.m_lblk, path,0 );if (!IS_ERR (path)) {for (j =0 ; j < path->p_depth; j++)ext4_mb_mark_bb (inode->i_sb, path[j].p_block,1 , true); -ext4_free_ext_path (path); + }else { + path =NULL ; } cur += ret; ext4_mb_mark_bb(inode->i_sb, map.m_pblk,
@@ -1978,6 +1979,8 @@ static void ext4_fc_set_bitmaps_and_coun }iput (inode); } + +ext4_free_ext_path (path); }/*
Greg Kroah-Hartman
maintainerPATCH 37/91 ext4: propagate errors from fast commit range replay
In reply to Greg Kroah-Hartman6.6-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 | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-)
fs/ext4/fast_commit.c +12 -4
@@ -1799,8 +1799,11 @@ static int ext4_fc_replay_add_range(struif (ret ==0 ) {/* Range is not mapped */ path =ext4_find_extent (inode, cur, path,0 ); -if (IS_ERR (path)) +if (IS_ERR (path)) { + ret =PTR_ERR (path); + path =NULL ; goto out; + }memset (&newex,0 ,sizeof (newex)); newex.ee_block =cpu_to_le32 (cur); ext4_ext_store_pblock(
@@ -1812,8 +1815,11 @@ static int ext4_fc_replay_add_range(stru path =ext4_ext_insert_extent (NULL , inode, path, &newex,0 );up_write ((&EXT4_I (inode)->i_data_sem)); -if (IS_ERR (path)) +if (IS_ERR (path)) { + ret =PTR_ERR (path); + path =NULL ; goto out; + } goto next; }
@@ -1860,10 +1866,11 @@ next: }ext4_ext_replay_shrink_inode (inode,i_size_read (inode) >> sb->s_blocksize_bits); + ret =0 ; out:ext4_free_ext_path (path);iput (inode); -return 0 ; +return ret; }/* Replay DEL_RANGE tag */
@@ -1924,9 +1931,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 void ext4_fc_set_bitmaps_and_counters (struct super_block *sb)
Greg Kroah-Hartman
maintainerPATCH 38/91 nilfs2: correct return value kernel-doc descriptions for ioctl functions
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryusuke Konishi <[email protected]>
[ Upstream commit 17c46a45cdb94c500f4e93b176cdd61931b03020 ]
Patch series "nilfs2: fix kernel-doc comments for function return values", v2.
This series fixes the inadequacies in the return value descriptions in nilfs2's kernel-doc comments (mainly incorrect formatting), as well as the lack of return value descriptions themselves, and fixes most of the remaining warnings that are output when the kernel-doc script is run with the "-Wall" option.
This patch (of 7):
In the kernel-doc comments for functions, there are many cases where the format of the return value description is inaccurate, such as "Return
Value: ...", which causes many warnings to be output when the kernel-doc script is executed with the "-Wall" option.
This fixes such incorrectly formatted return value descriptions for ioctl functions.
Stable-dep-of: a1735eae5544 ("nilfs2: reject invalid block index in GC ioctl")
--- fs/nilfs2/ioctl.c | 231 ++++++++++++++++++++++-------------------------------- 1 file changed, 95 insertions(+), 136 deletions(-)
fs/nilfs2/ioctl.c +95 -136
@@ -32,17 +32,14 @@* @dofunc: concrete function of get/set metadata info * * Description: nilfs_ioctl_wrap_copy() gets/sets metadata info by means of -* calling dofunc() function on the basis of @argv argument. +* calling dofunc() function on the basis of @argv argument. If successful, +* the requested metadata information is copied to userspace memory. * -* Return Value: On success, 0 is returned and requested metadata info -* is copied into userspace. On error, one of the following -* negative error codes is returned. -* -* %-EINVAL - Invalid arguments from userspace. -* -* %-ENOMEM - Insufficient amount of memory available. -* -* %-EFAULT - Failure during execution of requested operation. +* Return: 0 on success, or one of the following negative error codes on +* failure: +* * %-EFAULT - Failure during execution of requested operation. +* * %-EINVAL - Invalid arguments from userspace. +* * %-ENOMEM - Insufficient memory available. */ static int nilfs_ioctl_wrap_copy(struct the_nilfs *nilfs, struct nilfs_argv *argv, int dir,
@@ -176,13 +173,10 @@ static int nilfs_ioctl_getversion(struct* given checkpoint between checkpoint and snapshot state. This ioctl * is used in chcp and mkcp utilities. * -* Return Value: On success, 0 is returned and mode of a checkpoint is -* changed. On error, one of the following negative error codes -* is returned. -* -* %-EPERM - Operation not permitted. -* -* %-EFAULT - Failure during checkpoint mode changing. +* Return: 0 on success, or one of the following negative error codes on +* failure: +* %-EFAULT - Failure during checkpoint mode changing. +* %-EPERM - Operation not permitted. */ static int nilfs_ioctl_change_cpmode (struct inode *inode,struct file *filp,unsigned int cmd,void __user *argp)
@@ -230,13 +224,10 @@ out:* checkpoint from NILFS2 file system. This ioctl is used in rmcp * utility. * -* Return Value: On success, 0 is returned and a checkpoint is -* removed. On error, one of the following negative error codes -* is returned. -* -* %-EPERM - Operation not permitted. -* -* %-EFAULT - Failure during checkpoint removing. +* Return: 0 on success, or one of the following negative error codes on +* failure: +* %-EFAULT - Failure during checkpoint removing. +* %-EPERM - Operation not permitted. */ static int nilfs_ioctl_delete_checkpoint(struct inode *inode, struct file *filp,
@@ -282,7 +273,7 @@ out:* requested checkpoints. The NILFS_IOCTL_GET_CPINFO ioctl is used in * lscp utility and by nilfs_cleanerd daemon. * -* Return value: count of nilfs_cpinfo structures in output buffer. +* Return: Count of nilfs_cpinfo structures in output buffer. */ static ssize_t nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
@@ -306,17 +297,14 @@ nilfs_ioctl_do_get_cpinfo(struct the_nil* * Description: nilfs_ioctl_get_cpstat() returns information about checkpoints. * The NILFS_IOCTL_GET_CPSTAT ioctl is used by lscp, rmcp utilities -* and by nilfs_cleanerd daemon. -* -* Return Value: On success, 0 is returned, and checkpoints information is -* copied into userspace pointer @argp. On error, one of the following -* negative error codes is returned. -* -* %-EIO - I/O error. +* and by nilfs_cleanerd daemon. The checkpoint statistics are copied to +* the userspace memory pointed to by @argp. * -* %-ENOMEM - Insufficient amount of memory available. -* -* %-EFAULT - Failure during getting checkpoints statistics. +* Return: 0 on success, or one of the following negative error codes on +* failure: +* * %-EFAULT - Failure during getting checkpoints statistics. +* * %-EIO - I/O error. +* * %-ENOMEM - Insufficient memory available. */ static int nilfs_ioctl_get_cpstat (struct inode *inode,struct file *filp,unsigned int cmd,void __user *argp)
@@ -349,7 +337,8 @@ static int nilfs_ioctl_get_cpstat(struct* info about requested segments. The NILFS_IOCTL_GET_SUINFO ioctl is used * in lssu, nilfs_resize utilities and by nilfs_cleanerd daemon. * -* Return value: count of nilfs_suinfo structures in output buffer. +* Return: Count of nilfs_suinfo structures in output buffer on success, +* or a negative error code on failure. */ static ssize_t nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
@@ -373,17 +362,14 @@ nilfs_ioctl_do_get_suinfo(struct the_nil* * Description: nilfs_ioctl_get_sustat() returns segment usage statistics. * The NILFS_IOCTL_GET_SUSTAT ioctl is used in lssu, nilfs_resize utilities -* and by nilfs_cleanerd daemon. -* -* Return Value: On success, 0 is returned, and segment usage information is -* copied into userspace pointer @argp. On error, one of the following -* negative error codes is returned. -* -* %-EIO - I/O error. +* and by nilfs_cleanerd daemon. The requested segment usage information is +* copied to the userspace memory pointed to by @argp. * -* %-ENOMEM - Insufficient amount of memory available. -* -* %-EFAULT - Failure during getting segment usage statistics. +* Return: 0 on success, or one of the following negative error codes on +* failure: +* * %-EFAULT - Failure during getting segment usage statistics. +* * %-EIO - I/O error. +* * %-ENOMEM - Insufficient memory available. */ static int nilfs_ioctl_get_sustat (struct inode *inode,struct file *filp,unsigned int cmd,void __user *argp)
@@ -416,7 +402,8 @@ static int nilfs_ioctl_get_sustat(struct* on virtual block addresses. The NILFS_IOCTL_GET_VINFO ioctl is used * by nilfs_cleanerd daemon. * -* Return value: count of nilfs_vinfo structures in output buffer. +* Return: Count of nilfs_vinfo structures in output buffer on success, or +* a negative error code on failure. */ static ssize_t nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
@@ -443,7 +430,8 @@ nilfs_ioctl_do_get_vinfo(struct the_nilf* about descriptors of disk block numbers. The NILFS_IOCTL_GET_BDESCS ioctl * is used by nilfs_cleanerd daemon. * -* Return value: count of nilfs_bdescs structures in output buffer. +* Return: Count of nilfs_bdescs structures in output buffer on success, or +* a negative error code on failure. */ static ssize_t nilfs_ioctl_do_get_bdescs(struct the_nilfs *nilfs, __u64 *posp, int flags,
@@ -480,19 +468,15 @@ nilfs_ioctl_do_get_bdescs(struct the_nil* * Description: nilfs_ioctl_do_get_bdescs() function returns information * about descriptors of disk block numbers. The NILFS_IOCTL_GET_BDESCS ioctl -* is used by nilfs_cleanerd daemon. -* -* Return Value: On success, 0 is returned, and disk block descriptors are -* copied into userspace pointer @argp. On error, one of the following -* negative error codes is returned. -* -* %-EINVAL - Invalid arguments from userspace. -* -* %-EIO - I/O error. -* -* %-ENOMEM - Insufficient amount of memory available. +* is used by nilfs_cleanerd daemon. If successful, disk block descriptors +* are copied to userspace pointer @argp. * -* %-EFAULT - Failure during getting disk block descriptors. +* Return: 0 on success, or one of the following negative error codes on +* failure: +* * %-EFAULT - Failure during getting disk block descriptors. +* * %-EINVAL - Invalid arguments from userspace. +* * %-EIO - I/O error. +* * %-ENOMEM - Insufficient memory available. */ static int nilfs_ioctl_get_bdescs (struct inode *inode,struct file *filp,unsigned int cmd,void __user *argp)
@@ -526,16 +510,12 @@ static int nilfs_ioctl_get_bdescs(struct* Description: nilfs_ioctl_move_inode_block() function registers data/node * buffer in the GC pagecache and submit read request. * -* Return Value: On success, 0 is returned. On error, one of the following -* negative error codes is returned. -* -* %-EIO - I/O error. -* -* %-ENOMEM - Insufficient amount of memory available. -* -* %-ENOENT - Requested block doesn't exist. -* -* %-EEXIST - Blocks conflict is detected. +* Return: 0 on success, or one of the following negative error codes on +* failure: +* * %-EEXIST - Block conflict detected. +* * %-EIO - I/O error. +* * %-ENOENT - Requested block doesn't exist. +* * %-ENOMEM - Insufficient memory available. */ static int nilfs_ioctl_move_inode_block(struct inode *inode, struct nilfs_vdesc *vdesc,
@@ -590,8 +570,8 @@ static int nilfs_ioctl_move_inode_block(* blocks that garbage collector specified with the array of nilfs_vdesc * structures and stores them into page caches of GC inodes. * -* Return Value: Number of processed nilfs_vdesc structures or -* error code, otherwise. +* Return: Number of processed nilfs_vdesc structures on success, or +* a negative error code on failure. */ static int nilfs_ioctl_move_blocks (struct super_block *sb,struct nilfs_argv *argv,void *buf)
@@ -668,14 +648,11 @@ static int nilfs_ioctl_move_blocks(struc* in the period from p_start to p_end, excluding p_end itself. The checkpoints * which have been already deleted are ignored. * -* Return Value: Number of processed nilfs_period structures or -* error code, otherwise. -* -* %-EIO - I/O error. -* -* %-ENOMEM - Insufficient amount of memory available. -* -* %-EINVAL - invalid checkpoints. +* Return: Number of processed nilfs_period structures on success, or one of +* the following negative error codes on failure: +* * %-EINVAL - invalid checkpoints. +* * %-EIO - I/O error. +* * %-ENOMEM - Insufficient memory available. */ static int nilfs_ioctl_delete_checkpoints (struct the_nilfs *nilfs,struct nilfs_argv *argv,void *buf)
@@ -703,14 +680,11 @@ static int nilfs_ioctl_delete_checkpoint* Description: nilfs_ioctl_free_vblocknrs() function frees * the virtual block numbers specified by @buf and @argv->v_nmembs. * -* Return Value: Number of processed virtual block numbers or -* error code, otherwise. -* -* %-EIO - I/O error. -* -* %-ENOMEM - Insufficient amount of memory available. -* -* %-ENOENT - The virtual block number have not been allocated. +* Return: Number of processed virtual block numbers on success, or one of the +* following negative error codes on failure: +* * %-EIO - I/O error. +* * %-ENOENT - Unallocated virtual block number. +* * %-ENOMEM - Insufficient memory available. */ static int nilfs_ioctl_free_vblocknrs (struct the_nilfs *nilfs,struct nilfs_argv *argv,void *buf)
@@ -732,14 +706,11 @@ static int nilfs_ioctl_free_vblocknrs(st* Description: nilfs_ioctl_mark_blocks_dirty() function marks * metadata file or data blocks as dirty. * -* Return Value: Number of processed block descriptors or -* error code, otherwise. -* -* %-ENOMEM - Insufficient memory available. -* -* %-EIO - I/O error -* -* %-ENOENT - the specified block does not exist (hole block) +* Return: Number of processed block descriptors on success, or one of the +* following negative error codes on failure: +* * %-EIO - I/O error. +* * %-ENOENT - Non-existent block (hole block). +* * %-ENOMEM - Insufficient memory available. */ static int nilfs_ioctl_mark_blocks_dirty (struct the_nilfs *nilfs,struct nilfs_argv *argv,void *buf)
@@ -844,7 +815,7 @@ int nilfs_ioctl_prepare_clean_segments(s* from userspace. The NILFS_IOCTL_CLEAN_SEGMENTS ioctl is used by * nilfs_cleanerd daemon. * -* Return Value: On success, 0 is returned or error code, otherwise. +* Return: 0 on success, or a negative error code on failure. */ static int nilfs_ioctl_clean_segments (struct inode *inode,struct file *filp,unsigned int cmd,void __user *argp)
@@ -970,20 +941,14 @@ out:* and metadata are written out to the device when it successfully * returned. * -* Return Value: On success, 0 is retured. On errors, one of the following -* negative error code is returned. -* -* %-EROFS - Read only filesystem. -* -* %-EIO - I/O error -* -* %-ENOSPC - No space left on device (only in a panic state). -* -* %-ERESTARTSYS - Interrupted. -* -* %-ENOMEM - Insufficient memory available. -* -* %-EFAULT - Failure during execution of requested operation. +* Return: 0 on success, or one of the following negative error codes on +* failure: +* * %-EFAULT - Failure during execution of requested operation. +* * %-EIO - I/O error. +* * %-ENOMEM - Insufficient memory available. +* * %-ENOSPC - No space left on device (only in a panic state). +* * %-ERESTARTSYS - Interrupted. +* * %-EROFS - Read only filesystem. */ static int nilfs_ioctl_sync (struct inode *inode,struct file *filp,unsigned int cmd,void __user *argp)
@@ -1017,7 +982,7 @@ static int nilfs_ioctl_sync(struct inode* @filp: file object * @argp: pointer on argument from userspace * -* Return Value: On success, 0 is returned or error code, otherwise. +* Return: 0 on success, or a negative error code on failure. */ static int nilfs_ioctl_resize (struct inode *inode,struct file *filp,void __user *argp)
@@ -1053,7 +1018,7 @@ out:* checks the arguments from userspace and calls nilfs_sufile_trim_fs, which * performs the actual trim operation. * -* Return Value: On success, 0 is returned or negative error code, otherwise. +* Return: 0 on success, or a negative error code on failure. */ static int nilfs_ioctl_trim_fs (struct inode *inode,void __user *argp) {
@@ -1095,7 +1060,7 @@ static int nilfs_ioctl_trim_fs(struct in* of segments in bytes and upper limit of segments in bytes. * The NILFS_IOCTL_SET_ALLOC_RANGE is used by nilfs_resize utility. * -* Return Value: On success, 0 is returned or error code, otherwise. +* Return: 0 on success, or a negative error code on failure. */ static int nilfs_ioctl_set_alloc_range (struct inode *inode,void __user *argp) {
@@ -1146,17 +1111,15 @@ out:* @dofunc: concrete function of getting metadata info * * Description: nilfs_ioctl_get_info() gets metadata info by means of -* calling dofunc() function. -* -* Return Value: On success, 0 is returned and requested metadata info -* is copied into userspace. On error, one of the following -* negative error codes is returned. -* -* %-EINVAL - Invalid arguments from userspace. -* -* %-ENOMEM - Insufficient amount of memory available. +* calling dofunc() function. The requested metadata information is copied +* to userspace memory @argp. * -* %-EFAULT - Failure during execution of requested operation. +* Return: 0 on success, or one of the following negative error codes on +* failure: +* * %-EFAULT - Failure during execution of requested operation. +* * %-EINVAL - Invalid arguments from userspace. +* * %-EIO - I/O error. +* * %-ENOMEM - Insufficient memory available. */ static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp, unsigned int cmd, void __user *argp,
@@ -1196,18 +1159,14 @@ static int nilfs_ioctl_get_info(struct i* encapsulated in nilfs_argv and updates the segment usage info * according to the flags in nilfs_suinfo_update. * -* Return Value: On success, 0 is returned. On error, one of the -* following negative error codes is returned. -* -* %-EPERM - Not enough permissions -* -* %-EFAULT - Error copying input data -* -* %-EIO - I/O error. -* -* %-ENOMEM - Insufficient amount of memory available. -* -* %-EINVAL - Invalid values in input (segment number, flags or nblocks) +* Return: 0 on success, or one of the following negative error codes on +* failure: +* * %-EEXIST - Block conflict detected. +* * %-EFAULT - Error copying input data. +* * %-EINVAL - Invalid values in input (segment number, flags or nblocks). +* * %-EIO - I/O error. +* * %-ENOMEM - Insufficient memory available. +* * %-EPERM - Not enough permissions. */ static int nilfs_ioctl_set_suinfo (struct inode *inode,struct file *filp,unsigned int cmd,void __user *argp)
Greg Kroah-Hartman
maintainerPATCH 39/91 nilfs2: reject invalid block index in GC ioctl
In reply to Greg Kroah-Hartman6.6-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 | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
fs/nilfs2/ioctl.c +18 -2
@@ -513,6 +513,7 @@ static int nilfs_ioctl_get_bdescs(struct* Return: 0 on success, or one of the following negative error codes on * failure: * * %-EEXIST - Block conflict detected. +* * %-EINVAL - Invalid virtual block descriptor. * * %-EIO - I/O error. * * %-ENOENT - Requested block doesn't exist. * * %-ENOMEM - Insufficient memory available.
@@ -522,15 +523,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 40/91 nfc: nci: add data_len bound checks to activation parameter extractors
In reply to Greg Kroah-Hartman6.6-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 | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-)
net/nfc/nci/ntf.c +22 -4
@@ -525,15 +525,19 @@ static int nci_rf_discover_ntf_packet(ststatic int nci_extract_activation_params_iso_dep (struct nci_dev *ndev,struct nci_rf_intf_activated_ntf *ntf, -const __u8 *data) +const __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,
@@ -542,8 +546,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,
@@ -562,7 +570,7 @@ static int nci_extract_activation_paramsstatic int nci_extract_activation_params_nfc_dep (struct nci_dev *ndev,struct nci_rf_intf_activated_ntf *ntf, -const __u8 *data) +const __u8 *data,__u8 data_len) {struct activation_params_poll_nfc_dep *poll;struct activation_params_listen_nfc_dep *listen;
@@ -570,9 +578,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);
@@ -580,9 +592,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);
@@ -790,12 +806,14 @@ static int nci_rf_intf_activated_ntf_pacswitch (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 41/91 HID: magicmouse: re-enable multitouch after reset-resume
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christopher Kodama <[email protected]>
[ Upstream commit 4253fe22b137c4ee68f36b707fdb1b44b191edc4 ]
When the Apple Magic Trackpad 2 (USB) is reset across a power transition (e.g. resume from hibernation) it drops out of multitouch mode: it keeps sending report ID 0x02 on its HID_TYPE_USBMOUSE interface, but the packet shrinks from 21 to 8 bytes and the trackpad2 handler drops it (size < 12). Clicks still work but pointer motion is lost until the device is re-plugged or the driver reloaded.
Re-enable multitouch from .reset_resume via the workqueue. Only .reset_resume is needed; suspend-to-idle keeps the device powered and retains multitouch.
--- drivers/hid/hid-magicmouse.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
drivers/hid/hid-magicmouse.c +19 -0
@@ -993,6 +993,22 @@ static void magicmouse_remove(struct hidhid_hw_stop (hdev); } +#ifdef CONFIG_PM +static int magicmouse_reset_resume (struct hid_device *hdev) +{ +struct magicmouse_sc *msc =hid_get_drvdata (hdev); + +/* The device drops out of multitouch mode on resume; re-send the +* enable report. Only the HID_TYPE_USBMOUSE interface accepts it, and +* it must be deferred. Sending it inline here is too early. +*/ +if (msc && hdev->type ==HID_TYPE_USBMOUSE ) +schedule_delayed_work (&msc->work,msecs_to_jiffies (500 )); + +return 0 ; +} +#endif +static __u8 *magicmouse_report_fixup (struct hid_device *hdev,__u8 *rdesc,unsigned int *rsize) {
@@ -1052,6 +1068,9 @@ static struct hid_driver magicmouse_driv .event = magicmouse_event, .input_mapping = magicmouse_input_mapping, .input_configured = magicmouse_input_configured, +#ifdef CONFIG_PM + .reset_resume = magicmouse_reset_resume, +#endif };module_hid_driver (magicmouse_driver);
Greg Kroah-Hartman
maintainerPATCH 42/91 HID: magicmouse: prevent unbounded recursion in magicmouse_raw_event()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jose Villaseñor Montfort <[email protected]>
[ Upstream commit db8d634128d2ba88d79c0b601e983ebe14bb0519 ]
magicmouse_raw_event() handles DOUBLE_REPORT_ID (0xf7) packets, which pack two touch reports into one, by splitting the packet and calling itself on each half. The only guard against runaway recursion is a "size < 1" check, which stops zero-sized calls but does not bound the recursion depth.
A malicious HID device that matches this driver can send a report starting with DOUBLE_REPORT_ID and filled with the sequence [0xf7, 0x00]. Each level consumes two bytes and recurses on the remainder, so an incoming report of up to HID_MAX_BUFFER_SIZE (16 KiB) drives roughly 8000 nested calls. That easily exhausts the 16 KiB kernel stack, leading to a stack overflow: a panic with CONFIG_VMAP_STACK, or memory corruption without it.
A double report only ever wraps two normal reports; it is never legitimately nested. Refuse to re-enter the DOUBLE_REPORT_ID case from a recursive call so the recursion depth is bounded to two, while all valid packets keep being parsed exactly as before.
--- drivers/hid/hid-magicmouse.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-)
drivers/hid/hid-magicmouse.c +20 -5
@@ -377,8 +377,8 @@ static void magicmouse_emit_touch(struct } } -static int magicmouse_raw_event (struct hid_device *hdev, -struct hid_report *report,u8 *data,int size) +static int __magicmouse_raw_event (struct hid_device *hdev, +struct hid_report *report,u8 *data,int size,bool nested) {struct magicmouse_sc *msc =hid_get_drvdata (hdev);struct input_dev *input = msc->input;
@@ -489,6 +489,15 @@ static int magicmouse_raw_event(struct h* packet. */ +/* +* A double report only ever wraps two normal reports, so it is +* never nested. Refuse to recurse a second time; otherwise a +* malicious device could chain DOUBLE_REPORT_ID packets to drive +* unbounded recursion and overflow the kernel stack. +*/ +if (nested) +return 0 ; +/* Ensure that we have at least 2 elements (report type and size) */ if (size <2 )return 0 ;
@@ -500,9 +509,9 @@ static int magicmouse_raw_event(struct hreturn 0 ; } -magicmouse_raw_event (hdev, report, data +2 , data[1 ]); -magicmouse_raw_event (hdev, report, data +2 + data[1 ], - size -2 - data[1 ]); +__magicmouse_raw_event (hdev, report, data +2 , data[1 ], true); +__magicmouse_raw_event (hdev, report, data +2 + data[1 ], + size -2 - data[1 ], true);return 0 ;default :return 0 ;
@@ -527,6 +536,12 @@ static int magicmouse_raw_event(struct hreturn 1 ; } +static int magicmouse_raw_event (struct hid_device *hdev, +struct hid_report *report,u8 *data,int size) +{ +return __magicmouse_raw_event (hdev, report, data, size, false); +} +static int magicmouse_event (struct hid_device *hdev,struct hid_field *field,struct hid_usage *usage,__s32 value) {
Greg Kroah-Hartman
maintainerPATCH 43/91 nvme: rename nvme_sc_to_pr_err to nvme_status_to_pr_err
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiwen Hu <[email protected]>
[ Upstream commit 22f19a584d7045e0509f103dbc5c0acfd6415163 ]
This should better match its semantic. "sc" is used in the NVMe spec to specifically refer to the last 8 bits in the status field. We should not reuse "sc" here.
Stable-dep-of: 4a3f00262a04 ("nvmet-tcp: bound SGL data length before allocating command buffers")
--- drivers/nvme/host/pr.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/nvme/host/pr.c +5 -5
@@ -72,12 +72,12 @@ static int nvme_send_ns_pr_command(strucreturn nvme_submit_sync_cmd (ns->queue, c, data, data_len); } -static int nvme_sc_to_pr_err (int nvme_sc) +static int nvme_status_to_pr_err (int status) { -if (nvme_is_path_error (nvme_sc)) +if (nvme_is_path_error (status))return PR_STS_PATH_FAILED ; -switch (nvme_sc &0x7ff ) { +switch (status &0x7ff ) {case NVME_SC_SUCCESS :return PR_STS_SUCCESS ;case NVME_SC_RESERVATION_CONFLICT :
@@ -122,7 +122,7 @@ static int nvme_pr_command(struct block_if (ret <0 )return ret; -return nvme_sc_to_pr_err (ret); +return nvme_status_to_pr_err (ret); } static int nvme_pr_register(struct block_device *bdev, u64 old,
@@ -197,7 +197,7 @@ retry:if (ret <0 )return ret; -return nvme_sc_to_pr_err (ret); +return nvme_status_to_pr_err (ret); } static int nvme_pr_read_keys(struct block_device *bdev,
Greg Kroah-Hartman
maintainerPATCH 44/91 nvme: fix status magic numbers
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiwen Hu <[email protected]>
[ Upstream commit d89a5c6705998ddc42b104f8eabd3c4b9e8fde08 ]
Replaced some magic numbers about SC and SCT with enum and macro.
Stable-dep-of: 4a3f00262a04 ("nvmet-tcp: bound SGL data length before allocating command buffers")
--- drivers/nvme/host/constants.c | 2 +- drivers/nvme/host/core.c | 14 +++++++------- drivers/nvme/host/multipath.c | 2 +- drivers/nvme/host/nvme.h | 4 ++-- drivers/nvme/host/pr.c | 2 +- include/linux/nvme.h | 14 ++++++++++++-- 6 files changed, 24 insertions(+), 14 deletions(-)
drivers/nvme/host/constants.c +1 -1
@@ -173,7 +173,7 @@ static const char * const nvme_statuses[const unsigned char *nvme_get_error_status_str (u16 status) { - status &=0x7ff ; + status &=NVME_SCT_SC_MASK ;if (status <ARRAY_SIZE (nvme_statuses) && nvme_statuses[status])return nvme_statuses[status &0x7ff ];return "Unknown" ;
drivers/nvme/host/core.c +7 -7
@@ -251,7 +251,7 @@ void nvme_delete_ctrl_sync(struct nvme_cstatic blk_status_t nvme_error_status (u16 status) { -switch (status &0x7ff ) { +switch (status &NVME_SCT_SC_MASK ) {case NVME_SC_SUCCESS :return BLK_STS_OK ;case NVME_SC_CAP_EXCEEDED :
@@ -319,8 +319,8 @@ static void nvme_log_error(struct reques (unsigned long long )nvme_sect_to_lba (ns,blk_rq_pos (req)), (unsigned long long )blk_rq_bytes (req) >> ns->lba_shift,nvme_get_error_status_str (nr->status), - nr->status >>8 &7 ,/* Status Code Type */ - nr->status &0xff ,/* Status Code */ +NVME_SCT (nr->status),/* Status Code Type */ + nr->status &NVME_SC_MASK ,/* Status Code */ nr->status &NVME_SC_MORE ?"MORE " :"" , nr->status & NVME_SC_DNR ? "DNR " : "");return ;
@@ -331,8 +331,8 @@ static void nvme_log_error(struct requesnvme_get_admin_opcode_str (nr->cmd->common.opcode), nr->cmd->common.opcode,nvme_get_error_status_str (nr->status), - nr->status >>8 &7 ,/* Status Code Type */ - nr->status &0xff ,/* Status Code */ +NVME_SCT (nr->status),/* Status Code Type */ + nr->status &NVME_SC_MASK ,/* Status Code */ nr->status &NVME_SC_MORE ?"MORE " :"" , nr->status & NVME_SC_DNR ? "DNR " : ""); }
@@ -349,7 +349,7 @@ static inline enum nvme_disposition nvmeif (likely (nvme_req (req)->status ==0 ))return COMPLETE ; -if ((nvme_req (req)->status &0x7ff ) ==NVME_SC_AUTH_REQUIRED ) +if ((nvme_req (req)->status &NVME_SCT_SC_MASK ) ==NVME_SC_AUTH_REQUIRED )return AUTHENTICATE ; if (blk_noretry_request(req) ||
@@ -1155,7 +1155,7 @@ EXPORT_SYMBOL_NS_GPL(nvme_passthru_end,/* * Recommended frequency for KATO commands per NVMe 1.4 section 7.12.1: -* +* * The host should send Keep Alive commands at half of the Keep Alive Timeout * accounting for transport roundtrip times [..]. */
drivers/nvme/host/multipath.c +1 -1
@@ -86,7 +86,7 @@ void nvme_mpath_start_freeze(struct nvmevoid nvme_failover_req (struct request *req) {struct nvme_ns *ns = req->q->queuedata; -u16 status =nvme_req (req)->status &0x7ff ; +u16 status =nvme_req (req)->status &NVME_SCT_SC_MASK ;unsigned long flags;struct bio *bio;
drivers/nvme/host/nvme.h +2 -2
@@ -692,7 +692,7 @@ static inline u32 nvme_bytes_to_numd(sizstatic inline bool nvme_is_ana_error (u16 status) { -switch (status &0x7ff ) { +switch (status &NVME_SCT_SC_MASK ) {case NVME_SC_ANA_TRANSITION :case NVME_SC_ANA_INACCESSIBLE :case NVME_SC_ANA_PERSISTENT_LOSS :
@@ -705,7 +705,7 @@ static inline bool nvme_is_ana_error(u16static inline bool nvme_is_path_error (u16 status) {/* check for a status code type of 'path related status' */ -return (status &0x700 ) ==0x300 ; +return (status &NVME_SCT_MASK ) ==NVME_SCT_PATH ; }/*
drivers/nvme/host/pr.c +1 -1
@@ -77,7 +77,7 @@ static int nvme_status_to_pr_err(int staif (nvme_is_path_error (status))return PR_STS_PATH_FAILED ; -switch (status &0x7ff ) { +switch (status &NVME_SCT_SC_MASK ) {case NVME_SC_SUCCESS :return PR_STS_SUCCESS ;case NVME_SC_RESERVATION_CONFLICT :
include/linux/nvme.h +12 -2
@@ -1847,6 +1847,7 @@ enum {/* * Generic Command Status: */ +NVME_SCT_GENERIC =0x0 ,NVME_SC_SUCCESS =0x0 ,NVME_SC_INVALID_OPCODE =0x1 , NVME_SC_INVALID_FIELD = 0x2,
@@ -1894,6 +1895,7 @@ enum {/* * Command Specific Status: */ +NVME_SCT_COMMAND_SPECIFIC =0x100 ,NVME_SC_CQ_INVALID =0x100 ,NVME_SC_QID_INVALID =0x101 , NVME_SC_QUEUE_SIZE = 0x102,
@@ -1967,6 +1969,7 @@ enum {/* * Media and Data Integrity Errors: */ +NVME_SCT_MEDIA_ERROR =0x200 ,NVME_SC_WRITE_FAULT =0x280 ,NVME_SC_READ_ERROR =0x281 , NVME_SC_GUARD_CHECK = 0x282,
@@ -1979,6 +1982,7 @@ enum {/* * Path-related Errors: */ +NVME_SCT_PATH =0x300 ,NVME_SC_INTERNAL_PATH_ERROR =0x300 ,NVME_SC_ANA_PERSISTENT_LOSS =0x301 , NVME_SC_ANA_INACCESSIBLE = 0x302,
@@ -1987,11 +1991,17 @@ enum {NVME_SC_HOST_PATH_ERROR =0x370 ,NVME_SC_HOST_ABORTED_CMD =0x371 , -NVME_SC_CRD =0x1800 , +NVME_SC_MASK =0x00ff ,/* Status Code */ +NVME_SCT_MASK =0x0700 ,/* Status Code Type */ +NVME_SCT_SC_MASK =NVME_SCT_MASK |NVME_SC_MASK , + +NVME_SC_CRD =0x1800 ,/* Command Retry Delayed */ NVME_SC_MORE =0x2000 , - NVME_SC_DNR = 0x4000, + NVME_SC_DNR = 0x4000, /* Do Not Retry */ }; +#define NVME_SCT (status) ((status) >> 8 & 7) + struct nvme_completion {/* * Used by Admin and Fabrics commands to return data:
Greg Kroah-Hartman
maintainerPATCH 45/91 nvme: rename CDR/MORE/DNR to NVME_STATUS_*
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiwen Hu <[email protected]>
[ Upstream commit dd0b0a4a2c5d7209457dc172997d1243ad269cfa ]
CDR/MORE/DNR fields are not belonging to SC in the NVMe spec, rename them to NVME_STATUS_* to avoid confusion.
Stable-dep-of: 4a3f00262a04 ("nvmet-tcp: bound SGL data length before allocating command buffers")
--- drivers/nvme/host/core.c | 18 ++++++------ drivers/nvme/host/fabrics.c | 8 ++--- drivers/nvme/host/fault_inject.c | 2 - drivers/nvme/host/fc.c | 8 ++--- drivers/nvme/target/admin-cmd.c | 24 ++++++++--------- drivers/nvme/target/core.c | 46 ++++++++++++++++----------------- drivers/nvme/target/discovery.c | 14 +++++----- drivers/nvme/target/fabrics-cmd-auth.c | 16 +++++------ drivers/nvme/target/fabrics-cmd.c | 36 ++++++++++++------------- drivers/nvme/target/io-cmd-bdev.c | 12 ++++---- drivers/nvme/target/passthru.c | 10 +++---- drivers/nvme/target/rdma.c | 10 +++---- drivers/nvme/target/tcp.c | 4 +- drivers/nvme/target/zns.c | 30 ++++++++++----------- include/linux/nvme.h | 6 ++-- 15 files changed, 122 insertions(+), 122 deletions(-)
drivers/nvme/host/core.c +9 -9
@@ -297,7 +297,7 @@ static void nvme_retry_req(struct requesu16 crd;/* The mask and shift result must be <= 3 */ - crd = (nvme_req (req)->status &NVME_SC_CRD ) >>11 ; + crd = (nvme_req (req)->status &NVME_STATUS_CRD ) >>11 ;if (crd) delay =nvme_req (req)->ctrl->crdt[crd -1 ] *100 ;
@@ -321,8 +321,8 @@ static void nvme_log_error(struct requesnvme_get_error_status_str (nr->status),NVME_SCT (nr->status),/* Status Code Type */ nr->status &NVME_SC_MASK ,/* Status Code */ - nr->status &NVME_SC_MORE ?"MORE " :"" , - nr->status & NVME_SC_DNR ? "DNR " : ""); + nr->status &NVME_STATUS_MORE ?"MORE " :"" , + nr->status & NVME_STATUS_DNR ? "DNR " : "");return ; }
@@ -333,8 +333,8 @@ static void nvme_log_error(struct requesnvme_get_error_status_str (nr->status),NVME_SCT (nr->status),/* Status Code Type */ nr->status &NVME_SC_MASK ,/* Status Code */ - nr->status &NVME_SC_MORE ?"MORE " :"" , - nr->status & NVME_SC_DNR ? "DNR " : ""); + nr->status &NVME_STATUS_MORE ?"MORE " :"" , + nr->status & NVME_STATUS_DNR ? "DNR " : ""); }enum nvme_disposition {
@@ -353,7 +353,7 @@ static inline enum nvme_disposition nvmereturn AUTHENTICATE ;if (blk_noretry_request (req) || - (nvme_req (req)->status &NVME_SC_DNR ) || + (nvme_req (req)->status &NVME_STATUS_DNR ) ||nvme_req (req)->retries >= nvme_max_retries)return COMPLETE ;
@@ -3764,7 +3764,7 @@ static void nvme_ns_remove_by_nsid(strucstatic void nvme_validate_ns (struct nvme_ns *ns,struct nvme_ns_info *info) { -int ret =NVME_SC_INVALID_NS |NVME_SC_DNR ; +int ret =NVME_SC_INVALID_NS |NVME_STATUS_DNR ;if (!nvme_ns_ids_equal (&ns->head->ids, &info->ids)) { dev_err(ns->ctrl->device,
@@ -3780,7 +3780,7 @@ out:* * TODO: we should probably schedule a delayed retry here. */ -if (ret >0 && (ret &NVME_SC_DNR )) +if (ret >0 && (ret &NVME_STATUS_DNR ))nvme_ns_remove (ns); }
@@ -3972,7 +3972,7 @@ static void nvme_scan_work(struct work_s* they report) but don't actually support it. */ ret =nvme_scan_ns_list (ctrl); -if (ret >0 && ret &NVME_SC_DNR ) +if (ret >0 && ret &NVME_STATUS_DNR )nvme_scan_ns_sequential (ctrl); }mutex_unlock (&ctrl->scan_lock);
drivers/nvme/host/fabrics.c +4 -4
@@ -186,7 +186,7 @@ int nvmf_reg_read32(struct nvme_ctrl *ctif (unlikely (ret !=0 ))dev_err (ctrl->device,"Property Get error: %d, offset %#x\n" , - ret >0 ? ret & ~NVME_SC_DNR : ret, off); + ret >0 ? ret & ~NVME_STATUS_DNR : ret, off);return ret; }
@@ -232,7 +232,7 @@ int nvmf_reg_read64(struct nvme_ctrl *ctif (unlikely (ret !=0 ))dev_err (ctrl->device,"Property Get error: %d, offset %#x\n" , - ret >0 ? ret & ~NVME_SC_DNR : ret, off); + ret >0 ? ret & ~NVME_STATUS_DNR : ret, off);return ret; }EXPORT_SYMBOL_GPL (nvmf_reg_read64);
@@ -274,7 +274,7 @@ int nvmf_reg_write32(struct nvme_ctrl *cif (unlikely (ret))dev_err (ctrl->device,"Property Set error: %d, offset %#x\n" , - ret >0 ? ret & ~NVME_SC_DNR : ret, off); + ret >0 ? ret & ~NVME_STATUS_DNR : ret, off);return ret; }EXPORT_SYMBOL_GPL (nvmf_reg_write32);
@@ -309,7 +309,7 @@ static void nvmf_log_connect_error(struc int errval, int offset, struct nvme_command *cmd, struct nvmf_connect_data *data) { - int err_sctype = errval & ~NVME_SC_DNR; + int err_sctype = errval & ~NVME_STATUS_DNR;if (errval <0 ) { dev_err(ctrl->device,
drivers/nvme/host/fault_inject.c +1 -1
@@ -75,7 +75,7 @@ void nvme_should_fail(struct request *re/* inject status code and DNR bit */ status = fault_inject->status;if (fault_inject->dont_retry) - status |=NVME_SC_DNR ; + status |=NVME_STATUS_DNR ;nvme_req (req)->status = status; } }
drivers/nvme/host/fc.c +4 -4
@@ -3091,7 +3091,7 @@ nvme_fc_create_association(struct nvme_fif (ctrl->ctrl.icdoff) {dev_err (ctrl->ctrl.device,"icdoff %d is not supported!\n" , ctrl->ctrl.icdoff); - ret =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + ret =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; goto out_disconnect_admin_queue; }
@@ -3099,7 +3099,7 @@ nvme_fc_create_association(struct nvme_fif (!nvme_ctrl_sgl_supported (&ctrl->ctrl)) {dev_err (ctrl->ctrl.device,"Mandatory sgls are not supported!\n" ); - ret =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + ret =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; goto out_disconnect_admin_queue; }
@@ -3275,7 +3275,7 @@ nvme_fc_reconnect_or_delete(struct nvme_dev_info (ctrl->ctrl.device,"NVME-FC{%d}: reset: Reconnect attempt failed (%d)\n" , ctrl->cnum, status); -if (status >0 && (status &NVME_SC_DNR )) +if (status >0 && (status &NVME_STATUS_DNR )) recon = false; }else if (time_after_eq (jiffies, rport->dev_loss_end)) recon = false;
@@ -3292,7 +3292,7 @@ nvme_fc_reconnect_or_delete(struct nvme_queue_delayed_work (nvme_wq, &ctrl->connect_work, recon_delay); }else {if (portptr->port_state ==FC_OBJSTATE_ONLINE ) { -if (status >0 && (status &NVME_SC_DNR )) +if (status >0 && (status &NVME_STATUS_DNR ))dev_warn (ctrl->ctrl.device,"NVME-FC{%d}: reconnect failure\n" , ctrl->cnum);
drivers/nvme/target/admin-cmd.c +12 -12
@@ -344,7 +344,7 @@ static void nvmet_execute_get_log_page(spr_debug ("unhandled lid %d on qid %d\n" , req->cmd->get_log_page.lid, req->sq->qid); req->error_loc = offsetof(struct nvme_get_log_page_command , lid); -nvmet_req_complete (req,NVME_SC_INVALID_FIELD |NVME_SC_DNR ); +nvmet_req_complete (req,NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ); }static void nvmet_execute_identify_ctrl (struct nvmet_req *req)
@@ -496,7 +496,7 @@ static void nvmet_execute_identify_ns(stif (le32_to_cpu (req->cmd->identify.nsid) ==NVME_NSID_ALL ) { req->error_loc = offsetof(struct nvme_identify , nsid); - status =NVME_SC_INVALID_NS |NVME_SC_DNR ; + status =NVME_SC_INVALID_NS |NVME_STATUS_DNR ; goto out; }
@@ -662,7 +662,7 @@ static void nvmet_execute_identify_desclif (sg_zero_buffer (req->sg, req->sg_cnt,NVME_IDENTIFY_DATA_SIZE - off, off) !=NVME_IDENTIFY_DATA_SIZE - off) - status =NVME_SC_INTERNAL |NVME_SC_DNR ; + status =NVME_SC_INTERNAL |NVME_STATUS_DNR ; out:nvmet_req_complete (req, status);
@@ -724,7 +724,7 @@ static void nvmet_execute_identify(strucpr_debug ("unhandled identify cns %d on qid %d\n" , req->cmd->identify.cns, req->sq->qid); req->error_loc = offsetof(struct nvme_identify , cns); -nvmet_req_complete (req,NVME_SC_INVALID_FIELD |NVME_SC_DNR ); +nvmet_req_complete (req,NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ); }/*
@@ -807,7 +807,7 @@ u16 nvmet_set_feat_async_event(struct nvif (val32 & ~mask) { req->error_loc = offsetof(struct nvme_common_command , cdw11); -return NVME_SC_INVALID_FIELD |NVME_SC_DNR ; +return NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; }WRITE_ONCE (req->sq->ctrl->aen_enabled, val32);
@@ -833,7 +833,7 @@ void nvmet_execute_set_features(struct n ncqr = (cdw11 >>16 ) &0xffff ; nsqr = cdw11 &0xffff ;if (ncqr ==0xffff || nsqr ==0xffff ) { - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ;break ; } nvmet_set_result(req,
@@ -846,14 +846,14 @@ void nvmet_execute_set_features(struct n status =nvmet_set_feat_async_event (req,NVMET_AEN_CFG_ALL );break ;case NVME_FEAT_HOST_ID : - status =NVME_SC_CMD_SEQ_ERROR |NVME_SC_DNR ; + status =NVME_SC_CMD_SEQ_ERROR |NVME_STATUS_DNR ;break ;case NVME_FEAT_WRITE_PROTECT : status =nvmet_set_feat_write_protect (req);break ;default : req->error_loc = offsetof(struct nvme_common_command , cdw10); - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ;break ; }
@@ -939,7 +939,7 @@ void nvmet_execute_get_features(struct nif (!(req->cmd->common.cdw11 &cpu_to_le32 (1 <<0 ))) { req->error_loc = offsetof(struct nvme_common_command , cdw11); - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ;break ; }
@@ -952,7 +952,7 @@ void nvmet_execute_get_features(struct ndefault : req->error_loc = offsetof(struct nvme_common_command , cdw10); - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ;break ; }
@@ -969,7 +969,7 @@ void nvmet_execute_async_event(struct nvmutex_lock (&ctrl->lock);if (ctrl->nr_async_event_cmds >=NVMET_ASYNC_EVENTS ) {mutex_unlock (&ctrl->lock); -nvmet_req_complete (req,NVME_SC_ASYNC_LIMIT |NVME_SC_DNR ); +nvmet_req_complete (req,NVME_SC_ASYNC_LIMIT |NVME_STATUS_DNR );return ; } ctrl->async_event_cmds[ctrl->nr_async_event_cmds++] = req;
@@ -1006,7 +1006,7 @@ u16 nvmet_parse_admin_cmd(struct nvmet_rif (nvme_is_fabrics (cmd))return nvmet_parse_fabrics_admin_cmd (req);if (unlikely (!nvmet_check_auth_status (req))) -return NVME_SC_AUTH_REQUIRED |NVME_SC_DNR ; +return NVME_SC_AUTH_REQUIRED |NVME_STATUS_DNR ;if (nvmet_is_disc_subsys (nvmet_req_subsys (req)))return nvmet_parse_discovery_cmd (req);
drivers/nvme/target/core.c +23 -23
171 lines not on this page · raw message
drivers/nvme/target/discovery.c +7 -7
@@ -179,7 +179,7 @@ static void nvmet_execute_disc_get_log_pif (req->cmd->get_log_page.lid !=NVME_LOG_DISC ) { req->error_loc = offsetof(struct nvme_get_log_page_command , lid); - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; goto out; }
@@ -187,7 +187,7 @@ static void nvmet_execute_disc_get_log_pif (offset &0x3 ) { req->error_loc = offsetof(struct nvme_get_log_page_command , lpo); - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; goto out; }
@@ -256,7 +256,7 @@ static void nvmet_execute_disc_identify(if (req->cmd->identify.cns !=NVME_ID_CNS_CTRL ) { req->error_loc = offsetof(struct nvme_identify , cns); - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; goto out; }
@@ -320,7 +320,7 @@ static void nvmet_execute_disc_set_featudefault : req->error_loc = offsetof(struct nvme_common_command , cdw10); - stat =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + stat =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ;break ; }
@@ -345,7 +345,7 @@ static void nvmet_execute_disc_get_featudefault : req->error_loc = offsetof(struct nvme_common_command , cdw10); - stat =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + stat =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ;break ; }
@@ -361,7 +361,7 @@ u16 nvmet_parse_discovery_cmd(struct nvm cmd->common.opcode); req->error_loc = offsetof(struct nvme_common_command , opcode); -return NVME_SC_INVALID_OPCODE |NVME_SC_DNR ; +return NVME_SC_INVALID_OPCODE |NVME_STATUS_DNR ; }switch (cmd->common.opcode) {
@@ -386,7 +386,7 @@ u16 nvmet_parse_discovery_cmd(struct nvmdefault :pr_debug ("unhandled cmd %d\n" , cmd->common.opcode); req->error_loc = offsetof(struct nvme_common_command , opcode); -return NVME_SC_INVALID_OPCODE |NVME_SC_DNR ; +return NVME_SC_INVALID_OPCODE |NVME_STATUS_DNR ; } }
drivers/nvme/target/fabrics-cmd-auth.c +8 -8
@@ -198,26 +198,26 @@ void nvmet_execute_auth_send(struct nvmeu8 dhchap_status;if (req->cmd->auth_send.secp !=NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER ) { - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; req->error_loc = offsetof(struct nvmf_auth_send_command , secp); goto done; }if (req->cmd->auth_send.spsp0 !=0x01 ) { - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; req->error_loc = offsetof(struct nvmf_auth_send_command , spsp0); goto done; }if (req->cmd->auth_send.spsp1 !=0x01 ) { - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; req->error_loc = offsetof(struct nvmf_auth_send_command , spsp1); goto done; } tl =le32_to_cpu (req->cmd->auth_send.tl);if (!tl) { - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; req->error_loc = offsetof(struct nvmf_auth_send_command , tl); goto done;
@@ -446,26 +446,26 @@ void nvmet_execute_auth_receive(struct nu16 status =0 ;if (req->cmd->auth_receive.secp !=NVME_AUTH_DHCHAP_PROTOCOL_IDENTIFIER ) { - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; req->error_loc = offsetof(struct nvmf_auth_receive_command , secp); goto done; }if (req->cmd->auth_receive.spsp0 !=0x01 ) { - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; req->error_loc = offsetof(struct nvmf_auth_receive_command , spsp0); goto done; }if (req->cmd->auth_receive.spsp1 !=0x01 ) { - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; req->error_loc = offsetof(struct nvmf_auth_receive_command , spsp1); goto done; } al =le32_to_cpu (req->cmd->auth_receive.al);if (!al) { - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; req->error_loc = offsetof(struct nvmf_auth_receive_command , al); goto done;
drivers/nvme/target/fabrics-cmd.c +18 -18
@@ -18,7 +18,7 @@ static void nvmet_execute_prop_set(strucif (req->cmd->prop_set.attrib &1 ) { req->error_loc = offsetof(struct nvmf_property_set_command , attrib); - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; goto out; }
@@ -29,7 +29,7 @@ static void nvmet_execute_prop_set(strucdefault : req->error_loc = offsetof(struct nvmf_property_set_command , offset); - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; } out:nvmet_req_complete (req, status);
@@ -50,7 +50,7 @@ static void nvmet_execute_prop_get(struc val = ctrl->cap;break ;default : - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ;break ; } }else {
@@ -65,7 +65,7 @@ static void nvmet_execute_prop_get(struc val = ctrl->csts;break ;default : - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ;break ; } }
@@ -105,7 +105,7 @@ u16 nvmet_parse_fabrics_admin_cmd(structpr_debug ("received unknown capsule type 0x%x\n" , cmd->fabrics.fctype); req->error_loc = offsetof(struct nvmf_common_command , fctype); -return NVME_SC_INVALID_OPCODE |NVME_SC_DNR ; +return NVME_SC_INVALID_OPCODE |NVME_STATUS_DNR ; }return 0 ;
@@ -128,7 +128,7 @@ u16 nvmet_parse_fabrics_io_cmd(struct nvpr_debug ("received unknown capsule type 0x%x\n" , cmd->fabrics.fctype); req->error_loc = offsetof(struct nvmf_common_command , fctype); -return NVME_SC_INVALID_OPCODE |NVME_SC_DNR ; +return NVME_SC_INVALID_OPCODE |NVME_STATUS_DNR ; }return 0 ;
@@ -147,14 +147,14 @@ static u16 nvmet_install_queue(struct nvpr_warn ("queue size zero!\n" ); req->error_loc = offsetof(struct nvmf_connect_command , sqsize); req->cqe->result.u32 =IPO_IATTR_CONNECT_SQE (sqsize); - ret =NVME_SC_CONNECT_INVALID_PARAM |NVME_SC_DNR ; + ret =NVME_SC_CONNECT_INVALID_PARAM |NVME_STATUS_DNR ; goto err; }if (ctrl->sqs[qid] !=NULL ) {pr_warn ("qid %u has already been created\n" , qid); req->error_loc = offsetof(struct nvmf_connect_command , qid); -return NVME_SC_CMD_SEQ_ERROR |NVME_SC_DNR ; +return NVME_SC_CMD_SEQ_ERROR |NVME_STATUS_DNR ; }if (sqsize > mqes) {
@@ -162,14 +162,14 @@ static u16 nvmet_install_queue(struct nv sqsize, mqes, ctrl->cntlid); req->error_loc = offsetof(struct nvmf_connect_command , sqsize); req->cqe->result.u32 =IPO_IATTR_CONNECT_SQE (sqsize); -return NVME_SC_CONNECT_INVALID_PARAM |NVME_SC_DNR ; +return NVME_SC_CONNECT_INVALID_PARAM |NVME_STATUS_DNR ; } old =cmpxchg (&req->sq->ctrl,NULL , ctrl);if (old) {pr_warn ("queue already connected!\n" ); req->error_loc = offsetof(struct nvmf_connect_command , opcode); -return NVME_SC_CONNECT_CTRL_BUSY |NVME_SC_DNR ; +return NVME_SC_CONNECT_CTRL_BUSY |NVME_STATUS_DNR ; }/* note: convert queue size from 0's-based value to 1's-based value */
@@ -229,14 +229,14 @@ static void nvmet_execute_admin_connect(pr_warn ("invalid connect version (%d).\n" ,le16_to_cpu (c->recfmt)); req->error_loc = offsetof(struct nvmf_connect_command , recfmt); - status =NVME_SC_CONNECT_FORMAT |NVME_SC_DNR ; + status =NVME_SC_CONNECT_FORMAT |NVME_STATUS_DNR ; goto out; }if (unlikely (d->cntlid !=cpu_to_le16 (0xffff ))) {pr_warn ("connect attempt for invalid controller ID %#x\n" , d->cntlid); - status =NVME_SC_CONNECT_INVALID_PARAM |NVME_SC_DNR ; + status =NVME_SC_CONNECT_INVALID_PARAM |NVME_STATUS_DNR ; req->cqe->result.u32 =IPO_IATTR_CONNECT_DATA (cntlid); goto out; }
@@ -258,7 +258,7 @@ static void nvmet_execute_admin_connect( dhchap_status);nvmet_ctrl_put (ctrl);if (dhchap_status ==NVME_AUTH_DHCHAP_FAILURE_FAILED ) - status = (NVME_SC_CONNECT_INVALID_HOST |NVME_SC_DNR ); + status = (NVME_SC_CONNECT_INVALID_HOST |NVME_STATUS_DNR );else status =NVME_SC_INTERNAL ; goto out;
@@ -306,7 +306,7 @@ static void nvmet_execute_io_connect(strif (c->recfmt !=0 ) {pr_warn ("invalid connect version (%d).\n" ,le16_to_cpu (c->recfmt)); - status =NVME_SC_CONNECT_FORMAT |NVME_SC_DNR ; + status =NVME_SC_CONNECT_FORMAT |NVME_STATUS_DNR ; goto out; }
@@ -315,13 +315,13 @@ static void nvmet_execute_io_connect(str ctrl =nvmet_ctrl_find_get (d->subsysnqn, d->hostnqn,le16_to_cpu (d->cntlid), req);if (!ctrl) { - status =NVME_SC_CONNECT_INVALID_PARAM |NVME_SC_DNR ; + status =NVME_SC_CONNECT_INVALID_PARAM |NVME_STATUS_DNR ; goto out; }if (unlikely (qid > ctrl->subsys->max_qid)) {pr_warn ("invalid queue id (%d)\n" , qid); - status =NVME_SC_CONNECT_INVALID_PARAM |NVME_SC_DNR ; + status =NVME_SC_CONNECT_INVALID_PARAM |NVME_STATUS_DNR ; req->cqe->result.u32 =IPO_IATTR_CONNECT_SQE (qid); goto out_ctrl_put; }
@@ -351,13 +351,13 @@ u16 nvmet_parse_connect_cmd(struct nvmetpr_debug ("invalid command 0x%x on unconnected queue.\n" , cmd->fabrics.opcode); req->error_loc = offsetof(struct nvme_common_command , opcode); -return NVME_SC_INVALID_OPCODE |NVME_SC_DNR ; +return NVME_SC_INVALID_OPCODE |NVME_STATUS_DNR ; }if (cmd->fabrics.fctype != nvme_fabrics_type_connect) {pr_debug ("invalid capsule type 0x%x on unconnected queue.\n" , cmd->fabrics.fctype); req->error_loc = offsetof(struct nvmf_common_command , fctype); -return NVME_SC_INVALID_OPCODE |NVME_SC_DNR ; +return NVME_SC_INVALID_OPCODE |NVME_STATUS_DNR ; }if (cmd->connect.qid ==0 )
drivers/nvme/target/io-cmd-bdev.c +6 -6
@@ -133,11 +133,11 @@ u16 blk_to_nvme_status(struct nvmet_req*/ switch (blk_sts) {case BLK_STS_NOSPC : - status =NVME_SC_CAP_EXCEEDED |NVME_SC_DNR ; + status =NVME_SC_CAP_EXCEEDED |NVME_STATUS_DNR ; req->error_loc = offsetof(struct nvme_rw_command , length);break ;case BLK_STS_TARGET : - status =NVME_SC_LBA_RANGE |NVME_SC_DNR ; + status =NVME_SC_LBA_RANGE |NVME_STATUS_DNR ; req->error_loc = offsetof(struct nvme_rw_command , slba);break ;case BLK_STS_NOTSUPP :
@@ -145,10 +145,10 @@ u16 blk_to_nvme_status(struct nvmet_reqswitch (req->cmd->common.opcode) {case nvme_cmd_dsm:case nvme_cmd_write_zeroes: - status =NVME_SC_ONCS_NOT_SUPPORTED |NVME_SC_DNR ; + status =NVME_SC_ONCS_NOT_SUPPORTED |NVME_STATUS_DNR ;break ;default : - status =NVME_SC_INVALID_OPCODE |NVME_SC_DNR ; + status =NVME_SC_INVALID_OPCODE |NVME_STATUS_DNR ; }break ;case BLK_STS_MEDIUM :
@@ -157,7 +157,7 @@ u16 blk_to_nvme_status(struct nvmet_reqbreak ;case BLK_STS_IOERR :default : - status =NVME_SC_INTERNAL |NVME_SC_DNR ; + status =NVME_SC_INTERNAL |NVME_STATUS_DNR ; req->error_loc = offsetof(struct nvme_common_command , opcode); }
@@ -354,7 +354,7 @@ u16 nvmet_bdev_flush(struct nvmet_req *rreturn 0 ;if (blkdev_issue_flush (req->ns->bdev)) -return NVME_SC_INTERNAL |NVME_SC_DNR ; +return NVME_SC_INTERNAL |NVME_STATUS_DNR ;return 0 ; }
drivers/nvme/target/passthru.c +5 -5
@@ -306,7 +306,7 @@ static void nvmet_passthru_execute_cmd(s ns =nvme_find_get_ns (ctrl, nsid);if (unlikely (!ns)) {pr_err ("failed to get passthru ns nsid:%u\n" , nsid); - status =NVME_SC_INVALID_NS |NVME_SC_DNR ; + status =NVME_SC_INVALID_NS |NVME_STATUS_DNR ; goto out; }
@@ -426,7 +426,7 @@ u16 nvmet_parse_passthru_io_cmd(struct n* emulated in the future if regular targets grow support for * this feature. */ -return NVME_SC_INVALID_OPCODE |NVME_SC_DNR ; +return NVME_SC_INVALID_OPCODE |NVME_STATUS_DNR ; }return nvmet_setup_passthru_command (req);
@@ -478,7 +478,7 @@ static u16 nvmet_passthru_get_set_featurcase NVME_FEAT_RESV_PERSIST :/* No reservations, see nvmet_parse_passthru_io_cmd() */ default : -return NVME_SC_INVALID_OPCODE |NVME_SC_DNR ; +return NVME_SC_INVALID_OPCODE |NVME_STATUS_DNR ; } }
@@ -546,7 +546,7 @@ u16 nvmet_parse_passthru_admin_cmd(struc req->p.use_workqueue = true;return NVME_SC_SUCCESS ; } -return NVME_SC_INVALID_OPCODE |NVME_SC_DNR ; +return NVME_SC_INVALID_OPCODE |NVME_STATUS_DNR ;case NVME_ID_CNS_NS : req->execute = nvmet_passthru_execute_cmd; req->p.use_workqueue = true;
@@ -558,7 +558,7 @@ u16 nvmet_parse_passthru_admin_cmd(struc req->p.use_workqueue = true;return NVME_SC_SUCCESS ; } -return NVME_SC_INVALID_OPCODE |NVME_SC_DNR ; +return NVME_SC_INVALID_OPCODE |NVME_STATUS_DNR ;default :return nvmet_setup_passthru_command (req); }
drivers/nvme/target/rdma.c +5 -5
@@ -853,12 +853,12 @@ static u16 nvmet_rdma_map_sgl_inline(strif (!nvme_is_write (rsp->req.cmd)) { rsp->req.error_loc = offsetof(struct nvme_common_command , opcode); -return NVME_SC_INVALID_FIELD |NVME_SC_DNR ; +return NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; }if (off + len > rsp->queue->dev->inline_data_size) {pr_err ("invalid inline data offset!\n" ); -return NVME_SC_SGL_INVALID_OFFSET |NVME_SC_DNR ; +return NVME_SC_SGL_INVALID_OFFSET |NVME_STATUS_DNR ; }/* no data command? */
@@ -922,7 +922,7 @@ static u16 nvmet_rdma_map_sgl(struct nvmpr_err ("invalid SGL subtype: %#x\n" , sgl->type); rsp->req.error_loc = offsetof(struct nvme_common_command , dptr); -return NVME_SC_INVALID_FIELD |NVME_SC_DNR ; +return NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; }case NVME_KEY_SGL_FMT_DATA_DESC :switch (sgl->type &0xf ) {
@@ -934,12 +934,12 @@ static u16 nvmet_rdma_map_sgl(struct nvmpr_err ("invalid SGL subtype: %#x\n" , sgl->type); rsp->req.error_loc = offsetof(struct nvme_common_command , dptr); -return NVME_SC_INVALID_FIELD |NVME_SC_DNR ; +return NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; }default :pr_err ("invalid SGL type: %#x\n" , sgl->type); rsp->req.error_loc = offsetof(struct nvme_common_command , dptr); -return NVME_SC_SGL_INVALID_TYPE |NVME_SC_DNR ; +return NVME_SC_SGL_INVALID_TYPE |NVME_STATUS_DNR ; } }
drivers/nvme/target/tcp.c +2 -2
@@ -420,10 +420,10 @@ static int nvmet_tcp_map_data(struct nvmif (sgl->type == ((NVME_SGL_FMT_DATA_DESC <<4 ) |NVME_SGL_FMT_OFFSET )) {if (!nvme_is_write (cmd->req.cmd)) -return NVME_SC_INVALID_FIELD |NVME_SC_DNR ; +return NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ;if (len > cmd->req.port->inline_data_size) -return NVME_SC_SGL_INVALID_OFFSET |NVME_SC_DNR ; +return NVME_SC_SGL_INVALID_OFFSET |NVME_STATUS_DNR ; cmd->pdu_len = len; } cmd->req.transfer_len += len;
drivers/nvme/target/zns.c +15 -15
@@ -104,7 +104,7 @@ void nvmet_execute_identify_ns_zns(strucif (le32_to_cpu (req->cmd->identify.nsid) ==NVME_NSID_ALL ) { req->error_loc = offsetof(struct nvme_identify , nsid); - status =NVME_SC_INVALID_NS |NVME_SC_DNR ; + status =NVME_SC_INVALID_NS |NVME_STATUS_DNR ; goto out; }
@@ -125,7 +125,7 @@ void nvmet_execute_identify_ns_zns(struc }if (!bdev_is_zoned (req->ns->bdev)) { - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; req->error_loc = offsetof(struct nvme_identify , nsid); goto out; }
@@ -162,17 +162,17 @@ static u16 nvmet_bdev_validate_zone_mgmtif (sect >=get_capacity (req->ns->bdev->bd_disk)) { req->error_loc = offsetof(struct nvme_zone_mgmt_recv_cmd , slba); -return NVME_SC_LBA_RANGE |NVME_SC_DNR ; +return NVME_SC_LBA_RANGE |NVME_STATUS_DNR ; }if (out_bufsize <sizeof (struct nvme_zone_report )) { req->error_loc = offsetof(struct nvme_zone_mgmt_recv_cmd , numd); -return NVME_SC_INVALID_FIELD |NVME_SC_DNR ; +return NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; }if (req->cmd->zmr.zra !=NVME_ZRA_ZONE_REPORT ) { req->error_loc = offsetof(struct nvme_zone_mgmt_recv_cmd , zra); -return NVME_SC_INVALID_FIELD |NVME_SC_DNR ; +return NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; }switch (req->cmd->zmr.pr) {
@@ -181,7 +181,7 @@ static u16 nvmet_bdev_validate_zone_mgmtbreak ;default : req->error_loc = offsetof(struct nvme_zone_mgmt_recv_cmd , pr); -return NVME_SC_INVALID_FIELD |NVME_SC_DNR ; +return NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; }switch (req->cmd->zmr.zrasf) {
@@ -197,7 +197,7 @@ static u16 nvmet_bdev_validate_zone_mgmtdefault : req->error_loc = offsetof(struct nvme_zone_mgmt_recv_cmd , zrasf); -return NVME_SC_INVALID_FIELD |NVME_SC_DNR ; +return NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; }return NVME_SC_SUCCESS ;
@@ -345,7 +345,7 @@ static u16 blkdev_zone_mgmt_errno_to_nvmreturn NVME_SC_SUCCESS ;case -EINVAL :case -EIO : -return NVME_SC_ZONE_INVALID_TRANSITION |NVME_SC_DNR ; +return NVME_SC_ZONE_INVALID_TRANSITION |NVME_STATUS_DNR ;default :return NVME_SC_INTERNAL ; }
@@ -468,7 +468,7 @@ static u16 nvmet_bdev_execute_zmgmt_senddefault :/* this is needed to quiet compiler warning */ req->error_loc = offsetof(struct nvme_zone_mgmt_send_cmd , zsa); -return NVME_SC_INVALID_FIELD |NVME_SC_DNR ; +return NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; }return NVME_SC_SUCCESS ;
@@ -486,7 +486,7 @@ static void nvmet_bdev_zmgmt_send_work(sif (op ==REQ_OP_LAST ) { req->error_loc = offsetof(struct nvme_zone_mgmt_send_cmd , zsa); - status =NVME_SC_ZONE_INVALID_TRANSITION |NVME_SC_DNR ; + status =NVME_SC_ZONE_INVALID_TRANSITION |NVME_STATUS_DNR ; goto out; }
@@ -498,13 +498,13 @@ static void nvmet_bdev_zmgmt_send_work(sif (sect >=get_capacity (bdev->bd_disk)) { req->error_loc = offsetof(struct nvme_zone_mgmt_send_cmd , slba); - status =NVME_SC_LBA_RANGE |NVME_SC_DNR ; + status =NVME_SC_LBA_RANGE |NVME_STATUS_DNR ; goto out; }if (sect & (zone_sectors -1 )) { req->error_loc = offsetof(struct nvme_zone_mgmt_send_cmd , slba); - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; goto out; }
@@ -556,13 +556,13 @@ void nvmet_bdev_execute_zone_append(struif (sect >=get_capacity (req->ns->bdev->bd_disk)) { req->error_loc = offsetof(struct nvme_rw_command , slba); - status =NVME_SC_LBA_RANGE |NVME_SC_DNR ; + status =NVME_SC_LBA_RANGE |NVME_STATUS_DNR ; goto out; }if (sect & (bdev_zone_sectors (req->ns->bdev) -1 )) { req->error_loc = offsetof(struct nvme_rw_command , slba); - status =NVME_SC_INVALID_FIELD |NVME_SC_DNR ; + status =NVME_SC_INVALID_FIELD |NVME_STATUS_DNR ; goto out; }
@@ -595,7 +595,7 @@ void nvmet_bdev_execute_zone_append(stru }if (total_len !=nvmet_rw_data_len (req)) { - status =NVME_SC_INTERNAL |NVME_SC_DNR ; + status =NVME_SC_INTERNAL |NVME_STATUS_DNR ; goto out_put_bio; }
include/linux/nvme.h +3 -3
@@ -1995,9 +1995,9 @@ enum {NVME_SCT_MASK =0x0700 ,/* Status Code Type */ NVME_SCT_SC_MASK =NVME_SCT_MASK |NVME_SC_MASK , -NVME_SC_CRD =0x1800 ,/* Command Retry Delayed */ -NVME_SC_MORE =0x2000 , - NVME_SC_DNR = 0x4000, /* Do Not Retry */ +NVME_STATUS_CRD =0x1800 ,/* Command Retry Delayed */ +NVME_STATUS_MORE =0x2000 , + NVME_STATUS_DNR = 0x4000, /* Do Not Retry */ };#define NVME_SCT (status) ((status) >> 8 & 7)
Greg Kroah-Hartman
maintainerPATCH 46/91 nvmet-tcp: bound SGL data length before allocating command buffers
In reply to Greg Kroah-Hartman6.6-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
@@ -417,6 +417,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_STATUS_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 47/91 HID: nintendo: stop device IO before hid_hw_stop on probe failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiangshan Yi <[email protected]>
[ Upstream commit 1f74d3bff6fe04a64e02ab3661d2e0d554565aa6 ]
nintendo_hid_probe() calls hid_device_io_start() before joycon_init() and joycon_leds_create(). If either fails, the error path jumps to err_close which calls hid_hw_close()/hid_hw_stop() without first calling hid_device_io_stop().
hid_hw_stop() does not stop device IO, so hid_input_report() may still run and access driver data that is being torn down, resulting in a use-after-free.
Add an err_io_stop label that calls hid_device_io_stop() before hid_hw_close(), and point the two post-io_start error paths at it.
--- drivers/hid/hid-nintendo.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-)
drivers/hid/hid-nintendo.c +7 -6
@@ -2350,34 +2350,34 @@ static int nintendo_hid_probe(struct hid ret =joycon_init (hdev);if (ret) {hid_err (hdev,"Failed to initialize controller; ret=%d\n" , ret); - goto err_close; + goto err_io_stop; } ret =joycon_read_info (ctlr);if (ret) {hid_err (hdev,"Failed to retrieve controller info; ret=%d\n" , ret); - goto err_close; + goto err_io_stop; }/* Initialize the leds */ ret =joycon_leds_create (ctlr);if (ret) {hid_err (hdev,"Failed to create leds; ret=%d\n" , ret); - goto err_close; + goto err_io_stop; }/* Initialize the battery power supply */ ret =joycon_power_supply_create (ctlr);if (ret) {hid_err (hdev,"Failed to create power_supply; ret=%d\n" , ret); - goto err_close; + goto err_io_stop; } ret =joycon_input_create (ctlr);if (ret) {hid_err (hdev,"Failed to create input device; ret=%d\n" , ret); - goto err_close; + goto err_io_stop; } ctlr->ctlr_state =JOYCON_CTLR_STATE_READ ;
@@ -2385,7 +2385,8 @@ static int nintendo_hid_probe(struct hidhid_dbg (hdev,"probe - success\n" );return 0 ; -err_close: +err_io_stop: +hid_device_io_stop (hdev);hid_hw_close (hdev); err_stop:hid_hw_stop (hdev);
Greg Kroah-Hartman
maintainerPATCH 48/91 HID: ft260: validate i2c input report length
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Zaidman <[email protected]>
[ Upstream commit 80c4bbb2b38513e9c3d84805fa61a0ee16d79c45 ]
Add two checks to ft260_raw_event() to prevent out-of-bounds reads from malicious or malfunctioning devices:
First, reject reports shorter than the 2-byte header (report ID + length fields). Without this, even accessing xfer->length on a 1-byte report is an OOB read.
Second, validate xfer->length against the actual data capacity of the received HID report. Each I2C data report ID (0xD0 through 0xDE) defines a different report size in the HID descriptor, so the available payload varies per report. A corrupted length field could cause memcpy to read beyond the report buffer.
Stable-dep-of: bf3e39df3a39 ("HID: ft260: fix stack-use-after-return write in I2C read race")
--- drivers/hid/hid-ft260.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-)
drivers/hid/hid-ft260.c +14 -2
@@ -1068,10 +1068,22 @@ static int ft260_raw_event(struct hid_destruct ft260_device *dev =hid_get_drvdata (hdev);struct ft260_i2c_input_report *xfer = (void *)data; +if (size < offsetof(struct ft260_i2c_input_report , data)) { +hid_err (hdev,"short report %d\n" , size); +return -1 ; + } +if (xfer->report >=FT260_I2C_REPORT_MIN && xfer->report <=FT260_I2C_REPORT_MAX ) { -ft260_dbg ("i2c resp: rep %#02x len %d\n" , xfer->report, - xfer->length); +ft260_dbg ("i2c resp: rep %#02x len %d size %d\n" , + xfer->report, xfer->length, size); + +if (xfer->length > size - + offsetof(struct ft260_i2c_input_report , data)) { +hid_err (hdev,"report %#02x: length %d exceeds HID report size\n" , + xfer->report, xfer->length); +return -1 ; + }if ((dev->read_buf ==NULL ) || (xfer->length > dev->read_len - dev->read_idx)) {
Greg Kroah-Hartman
maintainerPATCH 49/91 HID: ft260: fix stack-use-after-return write in I2C read race
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raman Varabets <[email protected]>
[ Upstream commit bf3e39df3a397fd82967a31d17c4e02c7feab221 ]
ft260_i2c_read() points dev->read_buf at a caller-supplied buffer (often an on-stack variable), arms a completion and waits up to five seconds for the device to return the data. The HID input callback ft260_raw_event() runs in the input/IRQ path, independent of the dev->lock mutex held by the read path, and copies the device-supplied payload into dev->read_buf after a plain NULL check.
These two paths share read_buf, read_idx and read_len with no serialization. If the device delays its response until the read times out, ft260_i2c_read() resets the controller, clears read_buf and returns, unwinding the stack frame the buffer lived in. A response that arrives at that moment lets ft260_raw_event() pass the NULL check and then memcpy() the device-controlled payload into the now-freed stack location, a bounded but attacker-influenced stack-use-after-return write triggerable by malicious or malfunctioning hardware.
Add a dedicated spinlock that serializes every access to read_buf, read_idx and read_len. ft260_raw_event() now holds it across the NULL check, the memcpy and the index update, while the read path takes it when arming and when clearing the buffer, so the teardown can no longer slip between the check and the copy.
--- drivers/hid/hid-ft260.c | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-)
drivers/hid/hid-ft260.c +24 -1
@@ -240,6 +240,8 @@ struct ft260_device {struct mutex lock;u8 write_buf[FT260_REPORT_MAX_LENGTH ];unsigned long need_wakeup_at; +/* Protects read_buf, read_idx and read_len against ft260_raw_event() */ +spinlock_t read_lock;u8 *read_buf;u16 read_idx;u16 read_len;
@@ -501,6 +503,7 @@ static int ft260_i2c_read(struct ft260_dint timeout, ret =0 ;struct ft260_i2c_read_request_report rep;struct hid_device *hdev = dev->hdev; +unsigned long irqflags;u8 bus_busy =0 ;if ((flag &FT260_FLAG_START_REPEATED ) ==FT260_FLAG_START_REPEATED )
@@ -526,9 +529,11 @@ static int ft260_i2c_read(struct ft260_dreinit_completion (&dev->wait); +spin_lock_irqsave (&dev->read_lock, irqflags); dev->read_idx =0 ; dev->read_buf = data; dev->read_len = rd_len; +spin_unlock_irqrestore (&dev->read_lock, irqflags); ret =ft260_hid_output_report (hdev, (u8 *)&rep,sizeof (rep));if (ret <0 ) {
@@ -543,7 +548,9 @@ static int ft260_i2c_read(struct ft260_d goto ft260_i2c_read_exit; } +spin_lock_irqsave (&dev->read_lock, irqflags); dev->read_buf =NULL ; +spin_unlock_irqrestore (&dev->read_lock, irqflags);if (flag &FT260_FLAG_STOP ) bus_busy =FT260_I2C_STATUS_BUS_BUSY ;
@@ -562,7 +569,9 @@ static int ft260_i2c_read(struct ft260_d }while (len >0 ); ft260_i2c_read_exit: +spin_lock_irqsave (&dev->read_lock, irqflags); dev->read_buf =NULL ; +spin_unlock_irqrestore (&dev->read_lock, irqflags);return ret; }
@@ -1018,6 +1027,7 @@ static int ft260_probe(struct hid_device "FT260 usb-i2c bridge");mutex_init (&dev->lock); +spin_lock_init (&dev->read_lock);init_completion (&dev->wait); ret =ft260_xfer_status (dev,FT260_I2C_STATUS_BUS_BUSY );
@@ -1067,6 +1077,7 @@ static int ft260_raw_event(struct hid_de {struct ft260_device *dev =hid_get_drvdata (hdev);struct ft260_i2c_input_report *xfer = (void *)data; +unsigned long irqflags;if (size < offsetof(struct ft260_i2c_input_report , data)) {hid_err (hdev,"short report %d\n" , size);
@@ -1075,6 +1086,8 @@ static int ft260_raw_event(struct hid_deif (xfer->report >=FT260_I2C_REPORT_MIN && xfer->report <=FT260_I2C_REPORT_MAX ) { +bool complete_read; +ft260_dbg ("i2c resp: rep %#02x len %d size %d\n" , xfer->report, xfer->length, size);
@@ -1085,8 +1098,15 @@ static int ft260_raw_event(struct hid_dereturn -1 ; } +/* +* Hold read_lock so a timed-out ft260_i2c_read() cannot +* clear read_buf between the NULL check and the memcpy. +*/ +spin_lock_irqsave (&dev->read_lock, irqflags); +if ((dev->read_buf ==NULL ) || (xfer->length > dev->read_len - dev->read_idx)) { +spin_unlock_irqrestore (&dev->read_lock, irqflags);hid_err (hdev,"unexpected report %#02x, length %d\n" , xfer->report, xfer->length);return -1 ;
@@ -1095,8 +1115,11 @@ static int ft260_raw_event(struct hid_dememcpy (&dev->read_buf[dev->read_idx], &xfer->data, xfer->length); dev->read_idx += xfer->length; + complete_read = dev->read_idx == dev->read_len; + +spin_unlock_irqrestore (&dev->read_lock, irqflags); -if (dev->read_idx == dev->read_len) +if (complete_read)complete (&dev->wait); }else {
Greg Kroah-Hartman
maintainerPATCH 50/91 HID: uclogic: fix use-after-free of inrange_timer on remove
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ibrahim Hashimov <[email protected]>
[ Upstream commit 506fd50a9027340f0e9dcc587d10ccb03312dba6 ]
uclogic_remove() cancels the pen in-range timer and then stops the device:
timer_delete_sync(&drvdata->inrange_timer); hid_hw_stop(hdev);
timer_delete_sync() only guarantees the timer is idle at that instant. uclogic_raw_event_pen() keeps delivering pen reports until hid_hw_stop() stops the transport several lines later, and every report with pen->inrange == UCLOGIC_PARAMS_PEN_INRANGE_NONE re-arms the timer:
mod_timer(&drvdata->inrange_timer, jiffies + msecs_to_jiffies(100));
A report landing between the timer_delete_sync() call and the transport teardown in hid_hw_stop() re-arms inrange_timer after it was cancelled. uclogic_remove() then returns and the devm drvdata is freed, while hid_hw_stop() has already freed the input device drvdata->pen_input points at, so when the timer fires ~100 ms later uclogic_inrange_timeout() dereferences freed memory -- a use-after-free in timer-softirq context.
Swapping the two calls is not a fix: stopping the device first frees drvdata->pen_input via hidinput_disconnect() while the timer may still be pending, so a timer already armed before removal fires on the freed input device in the window before timer_delete_sync() runs.
Use timer_shutdown_sync() before hid_hw_stop() instead. It cancels the timer, waits for a running callback while pen_input is still valid, and prevents any further re-arming -- a later mod_timer() from an in-flight report is silently ignored -- so the timer is provably dead before hid_hw_stop() frees the inputs. This is the ordering the timer core documents for this "timer re-armed from another path" teardown case.
--- drivers/hid/hid-uclogic-core.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
drivers/hid/hid-uclogic-core.c +11 -1
@@ -477,7 +477,17 @@ static void uclogic_remove(struct hid_de {struct uclogic_drvdata *drvdata =hid_get_drvdata (hdev); -del_timer_sync (&drvdata->inrange_timer); +/* +* Shut the in-range timer down before stopping the device. +* uclogic_raw_event_pen() re-arms inrange_timer on every pen report +* and keeps running until hid_hw_stop() stops the transport, so a +* plain timer_delete_sync() here can be undone by a report landing in +* the window before hid_hw_stop(). timer_shutdown_sync() cancels the +* timer and makes any later re-arm a no-op, so it is provably dead +* before hid_hw_stop() frees the input device drvdata->pen_input +* points at. +*/ +timer_shutdown_sync (&drvdata->inrange_timer);hid_hw_stop (hdev);kfree (drvdata->desc_ptr);uclogic_params_cleanup (&drvdata->params);
Greg Kroah-Hartman
maintainerPATCH 51/91 HID: pidff: Support device error response from PID_BLOCK_LOAD
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tomasz Pakuła <[email protected]>
[ Upstream commit 9d4174dc4a234408d91fd83725e1899766cd1731 ]
If an error happens on the device, the driver will no longer fall into the trap of reading this status 60 times before it decides that this reply won't change to success/memory full.
Greatly reduces communication overhead during device error situation.
Stable-dep-of: 67bb1074e3d2 ("HID: pidff: fix OOB write when hid->inputs is empty")
--- drivers/hid/usbhid/hid-pidff.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/hid/usbhid/hid-pidff.c +7 -1
@@ -131,7 +131,8 @@ static const u8 pidff_effect_types[] = {#define PID_BLOCK_LOAD_SUCCESS 0#define PID_BLOCK_LOAD_FULL 1 -static const u8 pidff_block_load_status[] = {0x8c ,0x8d }; +#define PID_BLOCK_LOAD_ERROR 2 +static const u8 pidff_block_load_status[] = {0x8c ,0x8d ,0x8e };#define PID_EFFECT_START 0#define PID_EFFECT_STOP 1
@@ -515,6 +516,11 @@ static int pidff_request_effect_upload(s pidff->block_load[PID_RAM_POOL_AVAILABLE].value[0] : -1);return -ENOSPC ; } +if (pidff->block_load_status->value[0 ] == + pidff->status_id[PID_BLOCK_LOAD_ERROR ]) { +hid_dbg (pidff->hid,"device error during effect creation\n" ); +return -EREMOTEIO ; + } }hid_err (pidff->hid,"pid_block_load failed 60 times\n" );return -EIO ;
Greg Kroah-Hartman
maintainerPATCH 52/91 HID: pidff: clang-format pass
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tomasz Pakuła <[email protected]>
[ Upstream commit ae42428fb4e3d2eed344f0d6fcfa778bc8b8f80a ]
Stable-dep-of: 67bb1074e3d2 ("HID: pidff: fix OOB write when hid->inputs is empty")
--- drivers/hid/usbhid/hid-pidff.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/hid/usbhid/hid-pidff.c +2 -2
@@ -1298,8 +1298,8 @@ static int pidff_check_autocenter(structint hid_pidff_init_with_quirks (struct hid_device *hid,__u32 initial_quirks) {struct pidff_device *pidff; -struct hid_input *hidinput =list_entry (hid->inputs.next, - struct hid_input, list); +struct hid_input *hidinput = + list_entry(hid->inputs.next, struct hid_input, list);struct input_dev *dev = hidinput->input;struct ff_device *ff;int max_effects;
Greg Kroah-Hartman
maintainerPATCH 53/91 HID: pidff: fix OOB write when hid->inputs is empty
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baul Lee <[email protected]>
[ Upstream commit 67bb1074e3d2d12fa059a9cc707e89398a4e4704 ]
hid_pidff_init_with_quirks() derives its input_dev from
list_entry(hid->inputs.next, struct hid_input, list)
without first checking that hid->inputs is non-empty. The list member of struct hid_input is at offset 0, so on an empty list list_entry() yields &hid->inputs itself and the following hidinput->input load reads an unrelated member of struct hid_device. dev is then a type-confused pointer, and force-feedback init writes through it: each set_bit(FF_*, dev->ffbit) stores 8 bytes at dev + 192, past the end of the object dev actually aliases, and input_ff_create() adds further writes of a heap pointer and two function pointers.
Until hid-universal-pidff the only caller was hid_pidff_init() from usbhid, which runs under HID_CLAIMED_INPUT and therefore always has at least one hid_input. universal_pidff_probe() starts the device with HID_CONNECT_DEFAULT & ~HID_CONNECT_FF and then calls hid_pidff_init_with_quirks() directly whenever the descriptor carries a PID usage page, bypassing that gate. A report descriptor whose only application collection is on HID_UP_PID leaves hid->inputs empty while hid_connect() still succeeds through the hidraw claim, so probe reaches the unguarded list_entry().
The write happens in the USB probe path, on the hotplug workqueue, so plugging in a malicious device is enough to trigger it; no attacker software and no logged-in user are required. KASAN reports an 8-byte out-of-bounds write in hid_pidff_init_with_quirks() reached from universal_pidff_probe().
Check for an empty list before deriving dev and return -ENODEV, as the other HID force-feedback drivers already do. universal_pidff_probe() propagates the error and unwinds.
Discovered by XBOW, triaged by Baul Lee <[email protected]>
--- drivers/hid/usbhid/hid-pidff.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
drivers/hid/usbhid/hid-pidff.c +10 -3
@@ -1298,13 +1298,20 @@ static int pidff_check_autocenter(structint hid_pidff_init_with_quirks (struct hid_device *hid,__u32 initial_quirks) {struct pidff_device *pidff; -struct hid_input *hidinput = - list_entry(hid->inputs.next, struct hid_input, list); -struct input_dev *dev = hidinput->input; +struct hid_input *hidinput; +struct input_dev *dev;struct ff_device *ff;int max_effects;int error; +if (list_empty (&hid->inputs)) { +hid_err (hid,"no inputs found\n" ); +return -ENODEV ; + } + + hidinput = list_first_entry(&hid->inputs, struct hid_input, list); + dev = hidinput->input; +hid_dbg (hid,"starting pid init\n" );if (list_empty (&hid->report_enum[HID_OUTPUT_REPORT ].report_list)) {
Greg Kroah-Hartman
maintainerPATCH 54/91 Bluetooth: hci_sync: Use bt_dev_err() to log error message in hci_update_event_filter_sync()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zijun Hu <[email protected]>
[ Upstream commit da0186f19a7433d3d5607b0f61e9a3de17d1f721 ]
Use bt_dev_err() instead of bt_dev_dbg() to log error message in hci_update_event_filter_sync().
Stable-dep-of: f57b399c4fa1 ("Bluetooth: hci_sync: Fix accept list UAF during suspend")
--- net/bluetooth/hci_sync.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/bluetooth/hci_sync.c +1 -1
@@ -6231,7 +6231,7 @@ static int hci_update_event_filter_sync( &b->bdaddr, HCI_CONN_SETUP_AUTO_ON);if (err) -bt_dev_dbg (hdev,"Failed to set event filter for %pMR" , +bt_dev_err (hdev,"Failed to set event filter for %pMR" , &b->bdaddr);else scan =SCAN_PAGE ;
Greg Kroah-Hartman
maintainerPATCH 55/91 Bluetooth: hci_sync: Fix accept list UAF during suspend
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chengfeng Ye <[email protected]>
[ Upstream commit f57b399c4fa1501b2d5451f52d861ece86bcf3db ]
hci_update_event_filter_sync() walks hdev->accept_list while sending a synchronous HCI command for each remote-wakeup device. The suspend path holds hdev->req_lock, but accept-list updates are serialized by hdev->lock. Consequently, remove_device() can free the current list entry during the controller wait.
The following interleaving causes the use-after-free:
hci_update_event_filter_sync() remove_device()
fetch accept-list entry
hci_set_event_filter_sync()
wait for controller response hci_dev_lock()
list_del()
kfree()
hci_dev_unlock()read the freed list.next
KASAN reported:
BUG: KASAN: slab-use-after-free in hci_suspend_sync+0x835/0x910 Read of size 8 at addr ffff88810bec8440 by task kworker/0:1/10 Workqueue: events vhci_suspend_work Call Trace: hci_suspend_sync+0x835/0x910 hci_suspend_dev+0x182/0x450 process_one_work+0x661/0x1090 worker_thread+0x45b/0xd10 Allocated by task 86: hci_bdaddr_list_add_with_flags+0x1a8/0x400 add_device+0x381/0x820 hci_sock_sendmsg+0x1033/0x1ea0 Freed by task 91: kfree+0x131/0x3c0 remove_device+0x429/0xb70 hci_sock_sendmsg+0x1033/0x1ea0
Snapshot the remote-wakeup addresses under hdev->lock. Release the lock before sending HCI commands. Clear the controller event filter before building the snapshot, and skip allocation and the second list traversal when there are no matching entries. This preserves the original filter and scan-state updates without retaining an accept-list node across a controller wait.
--- net/bluetooth/hci_sync.c | 50 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 39 insertions(+), 11 deletions(-)
net/bluetooth/hci_sync.c +39 -11
@@ -6204,6 +6204,8 @@ static int hci_pause_discovery_sync(strustatic int hci_update_event_filter_sync (struct hci_dev *hdev) {struct bdaddr_list_with_flags *b; +bdaddr_t *accept_list; +size_t i, num_entries =0 ;u8 scan =SCAN_DISABLED ;bool scanning =test_bit (HCI_PSCAN , &hdev->flags);int err;
@@ -6220,23 +6222,49 @@ static int hci_update_event_filter_sync(/* Always clear event filter when starting */ hci_clear_event_filter_sync (hdev); -list_for_each_entry (b, &hdev->accept_list, list) { -if (!(b->flags &HCI_CONN_FLAG_REMOTE_WAKEUP )) -continue ; - -bt_dev_dbg (hdev,"Adding event filters for %pMR" , &b->bdaddr); - - err =hci_set_event_filter_sync (hdev,HCI_FLT_CONN_SETUP , -HCI_CONN_SETUP_ALLOW_BDADDR , - &b->bdaddr, -HCI_CONN_SETUP_AUTO_ON ); +hci_dev_lock (hdev); + +list_for_each_entry (b, &hdev->accept_list, list) +if (b->flags &HCI_CONN_FLAG_REMOTE_WAKEUP ) + num_entries++; + +if (!num_entries) { +hci_dev_unlock (hdev); + goto update_scan; + } + + accept_list =kmalloc_array (num_entries,sizeof (*accept_list), +GFP_KERNEL ); +if (!accept_list) { +hci_dev_unlock (hdev); +return -ENOMEM ; + } + + i =0 ; +list_for_each_entry (b, &hdev->accept_list, list) +if (b->flags &HCI_CONN_FLAG_REMOTE_WAKEUP ) +bacpy (&accept_list[i++], &b->bdaddr); + +hci_dev_unlock (hdev); + +for (i =0 ; i < num_entries; i++) { +bt_dev_dbg (hdev,"Adding event filters for %pMR" , + &accept_list[i]); + + err =hci_set_event_filter_sync (hdev,HCI_FLT_CONN_SETUP , +HCI_CONN_SETUP_ALLOW_BDADDR , + &accept_list[i], +HCI_CONN_SETUP_AUTO_ON );if (err)bt_dev_err (hdev,"Failed to set event filter for %pMR" , - &b->bdaddr); + &accept_list[i]);else scan =SCAN_PAGE ; } +kfree (accept_list); + +update_scan:if (scan && !scanning)hci_write_scan_enable_sync (hdev, scan);else if (!scan && scanning)
Greg Kroah-Hartman
maintainerPATCH 56/91 xfs: remove file_path tracepoint data
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Darrick J. Wong <[email protected]>
commit e31c53a8060e134111ed095783fee0aa0c43b080 upstream.
The xfile/xmbuf shmem file descriptions are no longer as detailed as they were when online fsck was first merged, because moving to static strings in commit 60382993a2e180 ("xfs: get rid of the xchk_xfile_*_descr calls") removed a memory allocation and hence a source of failure.
However this makes encoding the description in the tracepoints sort of a waste of memory. David Laight also points out that file_path doesn't zero the whole buffer which causes exposure of stale trace bytes, and Steven Rostedt wonders why we're not using a dynamic array for the file path.
I don't think this is worth fixing, so let's just rip it out.
[ Karl Mehltretter: Omit the xmbuf_create hunk because that tracepoint
is not in 6.6.y. The xfile_create hunk applies unchanged. This drops dynamically generated descriptions because 60382993a2e1 is not in 6.6.y, but fixes the stale-byte exposure and matches newer stable kernels. ]
--- fs/xfs/scrub/trace.h | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-)
fs/xfs/scrub/trace.h +2 -10
@@ -784,20 +784,12 @@ TRACE_EVENT(xfile_create,TP_STRUCT__entry (__field (dev_t ,dev ) __field(unsigned long, ino) -__array (char, pathname,MAXNAMELEN ) ),TP_fast_assign ( - char *path; - __entry->ino = file_inode(xf->file)->i_ino; - path =file_path (xf->file, __entry->pathname,MAXNAMELEN ); -if (IS_ERR (path)) -strncpy (__entry->pathname,"(unknown)" , -sizeof (__entry->pathname)); ), -TP_printk ("xfino 0x%lx path '%s'" , - __entry->ino, - __entry->pathname) +TP_printk ("xfino 0x%lx" , + __entry->ino) ); TRACE_EVENT(xfile_destroy,
Greg Kroah-Hartman
maintainerPATCH 57/91 fpga: dfl: fme: add error handling
In reply to Greg Kroah-Hartman6.6-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 58/91 accessibility: speakup: unregister tty ldisc on later init failures
In reply to Greg Kroah-Hartman6.6-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
@@ -2444,6 +2444,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 59/91 usb: xhci: Handle USB3 port events when there is one roothub
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Semih Baskan <[email protected]>
commit 3e91ec3e7d80a327fb558207613c80415d3bf756 upstream.
handle_port_status() drops every USB3 port event when xhci->shared_hcd is NULL. The check dates from a time when xhci-plat always created a shared hcd, so a NULL one could only mean the hcd had been removed.
Since commit 4736ebd7fcaf ("usb: host: xhci-plat: omit shared hcd if either root hub has no ports") that is no longer true. A controller whose USB2 root hub has no ports gets a single roothub, the USB3 rhub is served by the main hcd, and shared_hcd stays NULL for the lifetime of the device. Every SuperSpeed port event is then thrown away as bogus behind a debug message, so devices never enumerate even though the port sees the device and its change bits stay set:
0x006a1203 Powered Connected Enabled Link:U0 PortSpeed:4
Change: CSC WRC PRC PLC
Broadcom Northstar is such a controller. USB3 works there up to 5.15 and stops working from 5.19 onwards.
Ask xhci_get_usb3_hcd() instead. It returns the shared hcd when there is one, the main hcd when the USB2 root hub has no ports, and NULL once the shared hcd is gone, which keeps the original meaning of the check.
Tested on an Asus RT-N18U (BCM47081), which has a single roothub. Before the change nothing enumerates on the USB3 port; after it SuperSpeed devices enumerate normally over repeated connect and disconnect cycles, the change bits shown above clear, and USB2 is unaffected on both ports.
--- drivers/usb/host/xhci-ring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/usb/host/xhci-ring.c +1 -1
@@ -2010,7 +2010,7 @@ static void handle_port_status(struct xh }/* We might get interrupts after shared_hcd is removed */ -if (port->rhub == &xhci->usb3_rhub && xhci->shared_hcd ==NULL ) { +if (port->rhub == &xhci->usb3_rhub &&xhci_get_usb3_hcd (xhci) ==NULL ) {xhci_dbg (xhci,"ignore port event for removed USB3 hcd\n" ); bogus_port_status = true; goto cleanup;
Greg Kroah-Hartman
maintainerPATCH 60/91 xhci: dbgtty: Fix unregister on tty_register_driver() failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lucas De Marchi <[email protected]>
commit a916fa66a43e10f63198b6ce978badffc678821a upstream.
If tty_register_driver() fails, it drops the reference, but fails to set the global dbc_tty_driver to NULL, causing the unregister to be called again when module exits.
On module unload dbc_tty_exit() only gates its cleanup on the driver pointer being non-NULL, so it operates on the already-freed driver:
module_init(xhci_hcd_init)
xhci_hcd_init()
xhci_dbc_init() [return value ignored]
dbc_tty_init()
tty_register_driver() fails
tty_driver_kref_put() -> driver freed
(dbc_tty_driver left dangling)
...
module_exit(xhci_hcd_fini)
xhci_hcd_fini()
xhci_dbc_exit()
dbc_tty_exit()
if (dbc_tty_driver) -> true (dangling)
tty_unregister_driver() -> use-after-free--- drivers/usb/host/xhci-dbgtty.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/host/xhci-dbgtty.c +1 -0
@@ -619,6 +619,7 @@ int dbc_tty_init(void)pr_err ("Can't register dbc tty driver\n" );tty_driver_kref_put (dbc_tty_driver);idr_destroy (&dbc_tty_minors); + dbc_tty_driver =NULL ; }return ret;
Greg Kroah-Hartman
maintainerPATCH 61/91 xhci: dbgtty: Fix unregister on tty_alloc_driver() failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lucas De Marchi <[email protected]>
commit 25b8dfc13495a6c1cf4abacc8ef20196c7f20e5c upstream.
Make sure to set dbc_tty_driver to NULL to match the check in dbc_tty_exit(). For that, make detached error handling path common to the other branch in the same function.
--- drivers/usb/host/xhci-dbgtty.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
drivers/usb/host/xhci-dbgtty.c +11 -5
@@ -596,8 +596,8 @@ int dbc_tty_init(void) dbc_tty_driver =tty_alloc_driver (64 ,TTY_DRIVER_REAL_RAW |TTY_DRIVER_DYNAMIC_DEV );if (IS_ERR (dbc_tty_driver)) { -idr_destroy (&dbc_tty_minors); -return PTR_ERR (dbc_tty_driver); + ret =PTR_ERR (dbc_tty_driver); + goto fail; } dbc_tty_driver->driver_name ="dbc_serial" ;
@@ -617,12 +617,18 @@ int dbc_tty_init(void) ret =tty_register_driver (dbc_tty_driver);if (ret) {pr_err ("Can't register dbc tty driver\n" ); -tty_driver_kref_put (dbc_tty_driver); -idr_destroy (&dbc_tty_minors); - dbc_tty_driver =NULL ; + goto fail_put; }return ret; + +fail_put: +tty_driver_kref_put (dbc_tty_driver); +fail: +idr_destroy (&dbc_tty_minors); + dbc_tty_driver =NULL ; + +return ret; }void dbc_tty_exit (void )
Greg Kroah-Hartman
maintainerPATCH 62/91 fuse: fix invalidate lock leak on setattr writeback failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
commit 9afeca0d569c9fc89d758fe7a9339d1e8afb1546 upstream.
fuse_do_setattr() takes filemap_invalidate_lock() for a DAX truncate (fault_blocked = true) and releases it at the out:/error: labels. But when a writeback flush is also needed, a write_inode_now() failure returns directly and leaks the lock, so any later fault or truncate on the file stalls on the stale rwsem.
For example, truncate(2) on a setuid file reaches fuse_do_setattr() with both ATTR_SIZE and ATTR_MODE set:
truncate(2)
└─ do_truncate()
├─ dentry_needs_remove_privs() # S_ISUID
└─ notify_change() # KILL_SUID -> ATTR_MODE
└─ fuse_setattr() # no killpriv:
│ # ia_valid |= ATTR_MODE
└─ fuse_do_setattr()
├─ filemap_invalidate_lock() # IS_DAX && is_truncate
└─ write_inode_now() # is_wb && ATTR_MODE
└─ if (err) # e.g. daemon -> -EIO
return err # <- lock leakedFix this by adding an unlock label that releases the lock before returning the error, and use it for the fuse_dax_break_layouts() failure path as well.
--- fs/fuse/dir.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
fs/fuse/dir.c +4 -5
@@ -1879,10 +1879,8 @@ int fuse_do_setattr(struct dentry *dentrfilemap_invalidate_lock (mapping); fault_blocked = true; err =fuse_dax_break_layouts (inode,0 ,-1 ); -if (err) { -filemap_invalidate_unlock (mapping); -return err; - } +if (err) + goto unlock; }if (attr->ia_valid &ATTR_OPEN ) {
@@ -1909,7 +1907,7 @@ int fuse_do_setattr(struct dentry *dentr ATTR_TIMES_SET)) { err =write_inode_now (inode, true);if (err) -return err; + goto unlock;fuse_set_nowrite (inode);fuse_release_nowrite (inode);
@@ -2017,6 +2015,7 @@ error:clear_bit (FUSE_I_SIZE_UNSTABLE , &fi->state); +unlock:if (fault_blocked)filemap_invalidate_unlock (mapping);return err;
Greg Kroah-Hartman
maintainerPATCH 63/91 fuse: fix invalidate lock leak on open O_TRUNC DAX failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
commit a927f1867e61b78f39f9da0bbba3c98c2ca151fe upstream.
fuse_open() takes filemap_invalidate_lock() for a DAX truncate (dax_truncate = true) and releases it before the out_inode_unlock label. But when fuse_dax_break_layouts() fails, the goto out_inode_unlock skips the unlock and leaks the rwsem, so any later fault or truncate on the file stalls on the stale lock.
fuse_dax_break_layouts() can fail with -ERESTARTSYS when a signal interrupts the wait for busy DAX pages to drain:
open("file", O_RDWR | O_TRUNC)
└─ fuse_open()
├─ filemap_invalidate_lock() # dax_truncate
└─ fuse_dax_break_layouts()
└─ dax_break_layout()
└─ wait_page_idle() # TASK_INTERRUPTIBLE
└─ fuse_wait_dax_page() # unlock, schedule, re-lock
└─ signal → -ERESTARTSYS
goto out_inode_unlock # <- lock leakedFix this by moving filemap_invalidate_unlock() below the label so that all error paths release the lock, and rename the label to out_unlock as it now covers more than just the inode lock.
--- fs/fuse/file.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/fuse/file.c +2 -2
@@ -260,7 +260,7 @@ int fuse_open_common(struct inode *inodefilemap_invalidate_lock (inode->i_mapping); err =fuse_dax_break_layouts (inode,0 ,-1 );if (err) - goto out_inode_unlock; + goto out_unlock; }if (is_wb_truncate || dax_truncate)
@@ -280,9 +280,9 @@ int fuse_open_common(struct inode *inodeelse if (!(ff->open_flags &FOPEN_KEEP_CACHE ))invalidate_inode_pages2 (inode->i_mapping); } +out_unlock:if (dax_truncate)filemap_invalidate_unlock (inode->i_mapping); -out_inode_unlock:if (is_wb_truncate || dax_truncate)inode_unlock (inode);
Greg Kroah-Hartman
maintainerPATCH 64/91 usb: usbtest: disable dynamic ID support
In reply to Greg Kroah-Hartman6.6-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 65/91 usb: gadget: f_tcm: keep port count until LUN teardown completes
In reply to Greg Kroah-Hartman6.6-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
@@ -690,6 +690,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
@@ -1678,7 +1678,7 @@ static const struct target_core_fabric_o .fabric_enable_tpg = usbg_enable_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
@@ -95,6 +95,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 66/91 tls: device: fix out-of-bounds write in tls_append_frag()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <[email protected]>
commit b17cf742eaad70ae29ac558cefb3aa9bbeea03d4 upstream.
Found with syzkaller and a local syzbot instance running on top of a netdevsim TLS offload emulation; tls_device.c is otherwise only reachable on a machine with a NIC that implements the offload.
tls_push_data() only checks whether the open record still has room for another frag at the bottom of its loop, and the MSG_MORE early break skips that check. The record survives to the next syscall with the frag count it already had, and tls_append_frag() does not check either, so with TLS_TX_ZEROCOPY_RO every splice(SPLICE_F_MORE) of a byte or two adds a non-coalescing pipe page and num_frags walks off the end of tls_record_info.frags[MAX_SKB_FRAGS]. Once the record is pushed, tls_push_record() runs the same index over sg_tx_data[MAX_SKB_FRAGS] and the sg_set_page() writes land on the destruct_work that follows it, which the workqueue then calls.
The byte limit is fine because copy drops to 0 and the loop falls through to the same check; the frag count has no such feedback.
Push the record rather than keep a full one open, which is what a plain TCP socket does - tcp_sendmsg_locked() uses tcp_mark_push() and new_segment in both the copy and the MSG_SPLICE_PAGES paths, and tls_sw already sets full_record when the sk_msg ring fills up, MSG_MORE or not.
BUG: KASAN: slab-out-of-bounds in tls_append_frag ( net/tls/tls_device.c:269) Write of size 8 at addr ffff8881104d1530 by task tls_oob/450 CPU: 2 UID: 0 PID: 450 Comm: tls_oob Not tainted 7.2.0-rc7+ #329 PREEMPT Call Trace: <TASK> dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120) print_report (mm/kasan/report.c:378 mm/kasan/report.c:482) kasan_report (mm/kasan/report.c:595) tls_append_frag (net/tls/tls_device.c:269) tls_push_data (net/tls/tls_device.c:518) tls_device_sendmsg (net/tls/tls_device.c:583) inet_sendmsg (net/ipv4/af_inet.c:865) sock_sendmsg (net/socket.c:775 net/socket.c:790 net/socket.c:813) splice_to_socket (fs/splice.c:884) do_splice (fs/splice.c:936 fs/splice.c:1349) __do_splice (fs/splice.c:1431) __x64_sys_splice (fs/splice.c:1634 fs/splice.c:1616) do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) </TASK>
and, once the record is pushed:
UBSAN: array-index-out-of-bounds in net/tls/tls_device.c:300:24 index 18 is out of range for type 'skb_frag_t [17]' UBSAN: array-index-out-of-bounds in net/tls/tls_device.c:301:41 index 18 is out of range for type 'scatterlist [17]' UBSAN: array-index-out-of-bounds in net/tls/tls_device.c:302:39 index 18 is out of range for type 'scatterlist [17]' UBSAN: array-index-out-of-bounds in net/tls/tls_device.c:307:38 index 26 is out of range for type 'scatterlist [17]'
kernel tried to execute NX-protected page - exploit attempt? (uid: 0)
BUG: unable to handle page fault for address: ffffea000411a680 #PF: supervisor instruction fetch in kernel mode #PF: error_code(0x0011) - permissions violation Oops: Oops: 0011 [#1] SMP KASAN PTI Workqueue: ktls_device_destruct 0xffffea000411a680 RIP: 0010:0xffffea000411a680 Call Trace: <TASK> worker_thread (kernel/workqueue.c:3405 kernel/workqueue.c:3486) 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>
--- net/tls/tls_device.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/tls/tls_device.c +2 -1
@@ -536,7 +536,8 @@ handle_error:if (!size) { last_record: tls_push_record_flags = flags; -if (flags &MSG_MORE ) { +if ((flags &MSG_MORE ) && + record->num_frags <MAX_SKB_FRAGS -1 ) { more = true;break ; }
Greg Kroah-Hartman
maintainerPATCH 67/91 x86/CPU/AMD: Add X86_FEATURE_ZEN5
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Borislav Petkov (AMD) <[email protected]>
commit 3e4147f33f8b647775357bae0248b9a2aeebfcd2 upstream.
Add a synthetic feature flag for Zen5.
--- arch/x86/include/asm/cpufeatures.h | 4 +--- arch/x86/kernel/cpu/amd.c | 25 +++++++++++++++++++++---- 2 files changed, 22 insertions(+), 7 deletions(-)
arch/x86/include/asm/cpufeatures.h +1 -3
@@ -81,10 +81,8 @@#define X86_FEATURE_K6_MTRR ( 3*32+ 1)/* AMD K6 nonstandard MTRRs */ #define X86_FEATURE_CYRIX_ARR ( 3*32+ 2)/* Cyrix ARRs (= MTRRs) */ #define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3)/* Centaur MCRs (= MTRRs) */ - -/* CPU types for specific tunings: */ #define X86_FEATURE_K8 ( 3*32+ 4)/* "" Opteron, Athlon64 */ -/* FREE, was #define X86_FEATURE_K7 ( 3*32+ 5) "" Athlon */ +#define X86_FEATURE_ZEN5 ( 3*32+ 5)/* "" CPU based on Zen5 microarchitecture */ #define X86_FEATURE_P3 ( 3*32+ 6)/* "" P3 */ #define X86_FEATURE_P4 ( 3*32+ 7)/* "" P4 */ #define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8)/* TSC ticks at a constant rate */
arch/x86/kernel/cpu/amd.c +21 -4
@@ -669,7 +669,7 @@ static void bsp_init_amd(struct cpuinfo_/* Figure out Zen generations: */ switch (c->x86) { -case 0x17 : { +case 0x17 :switch (c->x86_model) { case 0x00 ... 0x2f: case 0x50 ... 0x5f:
@@ -685,8 +685,8 @@ static void bsp_init_amd(struct cpuinfo_ goto warn; }break ; - } -case 0x19 : { + +case 0x19 :switch (c->x86_model) { case 0x00 ... 0x0f: case 0x20 ... 0x5f:
@@ -700,7 +700,17 @@ static void bsp_init_amd(struct cpuinfo_ goto warn; }break ; - } + +case 0x1a : +switch (c->x86_model) { + case 0x00 ... 0x0f: +setup_force_cpu_cap (X86_FEATURE_ZEN5 ); +break ; +default : + goto warn; + } +break ; +default :break ; }
@@ -1185,6 +1195,11 @@ static void init_amd_zen4(struct cpuinfoinit_amd_zen_common (); } +static void init_amd_zen5 (struct cpuinfo_x86 *c) +{ +init_amd_zen_common (); +} +static void init_amd (struct cpuinfo_x86 *c) {early_init_amd (c);
@@ -1228,6 +1243,8 @@ static void init_amd(struct cpuinfo_x86init_amd_zen3 (c); else if (boot_cpu_has(X86_FEATURE_ZEN4)) init_amd_zen4(c); + else if (boot_cpu_has(X86_FEATURE_ZEN5)) + init_amd_zen5(c);/* * Enable workaround for FXSAVE leak on CPUs
Greg Kroah-Hartman
maintainerPATCH 68/91 x86/CPU/AMD: Add more models to X86_FEATURE_ZEN5
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
commit b9328fd636bd50da89e792e135b234ba8e6fe59f upstream.
Add model ranges starting at 0x20, 0x40 and 0x70 to the synthetic feature flag X86_FEATURE_ZEN5.
--- arch/x86/kernel/cpu/amd.c | 3 +++ 1 file changed, 3 insertions(+)
arch/x86/kernel/cpu/amd.c +3 -0
@@ -704,6 +704,9 @@ static void bsp_init_amd(struct cpuinfo_case 0x1a :switch (c->x86_model) { case 0x00 ... 0x0f: + case 0x20 ... 0x2f: + case 0x40 ... 0x4f: + case 0x70 ... 0x7f:setup_force_cpu_cap (X86_FEATURE_ZEN5 );break ;default :
Greg Kroah-Hartman
maintainerPATCH 69/91 x86/CPU/AMD: Add models 0x10-0x1f to the Zen5 range
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wenkuan Wang <[email protected]>
commit 2718a7fdf292b2dcb49c856fa8a6a955ebbbc45f upstream.
Add some more Zen5 models.
--- arch/x86/kernel/cpu/amd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
arch/x86/kernel/cpu/amd.c +1 -2
@@ -703,8 +703,7 @@ static void bsp_init_amd(struct cpuinfo_case 0x1a :switch (c->x86_model) { - case 0x00 ... 0x0f: - case 0x20 ... 0x2f: + case 0x00 ... 0x2f: case 0x40 ... 0x4f: case 0x70 ... 0x7f:setup_force_cpu_cap (X86_FEATURE_ZEN5 );
Greg Kroah-Hartman
maintainerPATCH 70/91 x86/CPU/AMD: Add models 0x60-0x6f to the Zen5 range
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Perry Yuan <[email protected]>
commit bf5641eccf71bcd13a849930e190563c3a19815d upstream.
Add some new Zen5 models for the 0x1A family.
[ bp: Merge the 0x60 and 0x70 ranges. ]
--- arch/x86/kernel/cpu/amd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/kernel/cpu/amd.c +1 -1
@@ -705,7 +705,7 @@ static void bsp_init_amd(struct cpuinfo_switch (c->x86_model) { case 0x00 ... 0x2f: case 0x40 ... 0x4f: - case 0x70 ... 0x7f: + case 0x60 ... 0x7f:setup_force_cpu_cap (X86_FEATURE_ZEN5 );break ;default :
Greg Kroah-Hartman
maintainerPATCH 71/91 x86/CPU/AMD: Carve out a Zen5 models range
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pratik Vishwakarma <[email protected]>
commit 52075128273ace53e6254e37899a47d40d4baf45 upstream.
Family 0x1a, model 0xd0..0xd7 belongs to the Zen5 generation. Carve it out from the larger, Zen6 range where former doesn't belong.
[ bp: Rewrite commit message, add tags. ]
--- arch/x86/kernel/cpu/amd.c | 1 + 1 file changed, 1 insertion(+)
arch/x86/kernel/cpu/amd.c +1 -0
@@ -706,6 +706,7 @@ static void bsp_init_amd(struct cpuinfo_ case 0x00 ... 0x2f: case 0x40 ... 0x4f: case 0x60 ... 0x7f: + case 0xd0 ... 0xd7:setup_force_cpu_cap (X86_FEATURE_ZEN5 );break ;default :
Greg Kroah-Hartman
maintainerPATCH 72/91 xfrm: espintcp: fix UAF during close
In reply to Greg Kroah-Hartman6.6-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
@@ -516,7 +516,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);
Greg Kroah-Hartman
maintainerPATCH 73/91 xfrm: drop ESP-in-TCP packets with no ingress device
In reply to Greg Kroah-Hartman6.6-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
@@ -39,6 +39,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 )
@@ -47,6 +52,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 74/91 xfrm: ah6: validate routing header segments_left
In reply to Greg Kroah-Hartman6.6-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
@@ -232,26 +232,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 ];
@@ -261,6 +263,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)
@@ -273,6 +277,7 @@ static int ipv6_clear_mutable_options(st } exthdr = { .iph = iph };char *end = exthdr.raw + len;int nexthdr = iph->nexthdr; +int err; exthdr.iph++;
@@ -292,7 +297,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 75/91 xfrm: fix xfrm_state_construct() auth-trunc leak
In reply to Greg Kroah-Hartman6.6-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
@@ -716,7 +716,7 @@ static struct xfrm_state *xfrm_state_conif ((err =attach_auth_trunc (&x->aalg, &x->props.aalgo, attrs[XFRMA_ALG_AUTH_TRUNC ], extack))) goto error; -if (!x->props.aalgo) { +if (!x->aalg) {if ((err =attach_auth (&x->aalg, &x->props.aalgo, attrs[XFRMA_ALG_AUTH ], extack))) goto error;
Greg Kroah-Hartman
maintainerPATCH 76/91 net: bridge: mcast: fix use-after-free of a master VLANs multicast context
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Norbert Szetei <[email protected]>
commit 50e5c6605cc9c2dd57bd2d1b3459674d19738983 upstream.
br_multicast_toggle_one_vlan() clears BR_VLFLAG_MCAST_ENABLED under br->multicast_lock before stopping a VLAN's multicast context. That is the teardown handshake: lockless readers gate on the flag through br_multicast_ctx_should_use() -> br_multicast_ctx_vlan_disabled(), so once it is cleared under the lock no reader can arm the context again.
For a master VLAN the handshake never runs. __vlan_del() clears BRIDGE_VLAN_INFO_BRENTRY before calling br_vlan_put_master(), so br_multicast_toggle_one_vlan(masterv, false) returns early on !br_vlan_is_brentry(vlan): the flag stays set and br->multicast_lock is never taken. br_vlan_put_master() then drains the context in br_multicast_ctx_deinit() and frees the VLAN through call_rcu(), while a reader still inside rcu_read_lock() sees the context as enabled and re-arms it. The port and port-VLAN branch of the function has no br_vlan_is_brentry() test and flips the flag under br->multicast_lock, so it is not affected.
The reader is the bridge transmit path. For a master VLAN br_multicast_rcv() selects brmctx = &vlan->br_mcast_ctx with pmctx = NULL, so IGMP sent to the bridge device re-arms the context's timers after br_multicast_ctx_deinit() has already stopped them.
BUG: KASAN: slab-use-after-free in detach_if_pending+0x412/0x4a0 Write of size 8 at addr ffff88810ac39918 by task brmc/601 __mod_timer+0x51a/0xc50 br_multicast_host_join+0x25b/0x390 __br_multicast_add_group+0x468/0x530 br_ip4_multicast_add_group+0x1a0/0x260 br_multicast_rcv+0x2cda/0x61e0 br_dev_xmit+0x6c4/0x1540 Allocated by task 610: br_vlan_add+0x111/0xb40 br_vlan_info+0x370/0x3e0 Freed by task 0: kfree+0x1a7/0x4f0 rcu_core+0x7dc/0x10a0
Only test br_vlan_is_brentry() when enabling, like the br_multicast_ctx_vlan_global_disabled() test next to it. Disabling then always clears BR_VLFLAG_MCAST_ENABLED under br->multicast_lock before br_multicast_ctx_deinit() drains the context.
--- net/bridge/br_multicast.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/bridge/br_multicast.c +2 -2
@@ -4312,8 +4312,8 @@ void br_multicast_toggle_one_vlan(structif (br_vlan_is_master (vlan)) { br = vlan->br; -if (!br_vlan_is_brentry (vlan) || - (on && +if (on && + (!br_vlan_is_brentry (vlan) ||br_multicast_ctx_vlan_global_disabled (&vlan->br_mcast_ctx)))return ;
Greg Kroah-Hartman
maintainerPATCH 77/91 ipv6: seg6: clear IPv4 control block on IPIP decapsulation
In reply to Greg Kroah-Hartman6.6-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
@@ -256,6 +256,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 78/91 mm/swap: reject swapon() on filesystem-level encrypted files
In reply to Greg Kroah-Hartman6.6-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
@@ -1158,6 +1158,10 @@ astute users may notice some differences - DAX (Direct Access) is not supported on encrypted files. +- 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
@@ -3051,6 +3051,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 79/91 crypto: atmel-tdes - use scatterlist length before DMA mapping
In reply to Greg Kroah-Hartman6.6-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
@@ -463,14 +463,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 80/91 crypto: qce - fix CCM AAD buffer underallocation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Md Sadre Alam <[email protected]>
commit 7f2345f47dd189625f657cd72437179ab4170ee1 upstream.
The AAD buffer allocated in qce_aead_ccm_prepare_buf_assoclen() can be smaller than the length later programmed into the DMA scatterlist.
The allocation size is currently calculated as:
ALIGN(assoclen, 16) + MAX_CCM_ADATA_HEADER_LEN
while the DMA length is set to:
ALIGN(assoclen + adata_header_len, 16)
Since ALIGN() does not distribute over addition, the allocation can be smaller than the DMA length. For example, when assoclen = 32 and adata_header_len = 2:
allocation = ALIGN(32, 16) + 6 = 38
DMA length = ALIGN(32 + 2, 16) = 48
As a result, the QCE hardware can read beyond the allocated buffer while computing the CBC-MAC over the associated data. The extra bytes are folded into the authentication tag, resulting in an incorrect tag and causing CCM self-test failures such as:
alg: aead: ccm-aes-qce encryption test failed (wrong result) on test vector 8
Fix the allocation by adding the maximum possible AAD header length before alignment:
ALIGN(assoclen + MAX_CCM_ADATA_HEADER_LEN, 16)
This guarantees that the allocated buffer is large enough for the fully padded AAD data for all supported header sizes.
--- drivers/crypto/qce/aead.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/crypto/qce/aead.c +1 -1
@@ -203,7 +203,7 @@ qce_aead_ccm_prepare_buf_assoclen(struct/* Get the msg */ msg_sg =scatterwalk_ffwd (__sg, req->src, req->assoclen); - rctx->adata =kzalloc ((ALIGN (assoclen,16 ) +MAX_CCM_ADATA_HEADER_LEN ) * + rctx->adata =kzalloc (ALIGN (assoclen +MAX_CCM_ADATA_HEADER_LEN ,16 ) *sizeof (unsigned char ),GFP_ATOMIC );if (!rctx->adata)return -ENOMEM ;
Greg Kroah-Hartman
maintainerPATCH 81/91 crypto: mxs-dcp - fix source scatterlist length access
In reply to Greg Kroah-Hartman6.6-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
@@ -333,7 +333,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 82/91 crypto: qce - Remove unsafe/deprecated algorithms
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
commit 7e28b0a5c4b7d075b98ce6d8f5290a9d3deb5b92 upstream.
Remove algorithms that are either unsafe or deprecated and have no in-kernel users that cannot be served by the ARM CE implementations.
AES-ECB reveals plaintext patterns (identical plaintext blocks produce identical ciphertext blocks) and should not be exposed as a hardware- accelerated primitive. DES, Triple DES and HMAC-SHA1 have been deprecated for years.
Remove sha1, ecb(aes), ecb(des), cbc(des), ecb(des3_ede), cbc(des3_ede), hmac(sha1) and all AEAD variants built on these primitives as well as authenc(hmac(sha256),cbc(des)). Also clean up the - now dead - code, flags and constants.
--- drivers/crypto/qce/aead.c | 56 ------------------------ drivers/crypto/qce/common.c | 55 +++++------------------ drivers/crypto/qce/common.h | 16 +----- drivers/crypto/qce/regs-v5.h | 4 - drivers/crypto/qce/sha.c | 30 ------------ drivers/crypto/qce/sha.h | 1 drivers/crypto/qce/skcipher.c | 97 ------------------------------------------ 7 files changed, 20 insertions(+), 239 deletions(-)
drivers/crypto/qce/aead.c +1 -55
@@ -8,8 +8,6 @@#include <crypto/gcm.h> #include <crypto/authenc.h> #include <crypto/internal/aead.h> -#include <crypto/internal/des.h> -#include <crypto/sha1.h> #include <crypto/sha2.h> #include <crypto/scatterwalk.h> #include "aead.h"
@@ -597,7 +595,6 @@ static int qce_aead_setkey(struct cryptostruct qce_aead_ctx *ctx =crypto_aead_ctx (tfm);struct crypto_authenc_keys authenc_keys;unsigned long flags =to_aead_tmpl (tfm)->alg_flags; -u32 _key[6 ];int err; err =crypto_authenc_extractkeys (&authenc_keys, key, keylen);
@@ -608,26 +605,7 @@ static int qce_aead_setkey(struct crypto authenc_keys.authkeylen > QCE_MAX_KEY_SIZE)return -EINVAL ; -if (IS_DES (flags)) { - err =verify_aead_des_key (tfm, authenc_keys.enckey, authenc_keys.enckeylen); -if (err) -return err; - }else if (IS_3DES (flags)) { - err =verify_aead_des3_key (tfm, authenc_keys.enckey, authenc_keys.enckeylen); -if (err) -return err; -/* -* The crypto engine does not support any two keys -* being the same for triple des algorithms. The -* verify_skcipher_des3_key does not check for all the -* below conditions. Schedule fallback in this case. -*/ -memcpy (_key, authenc_keys.enckey,DES3_EDE_KEY_SIZE ); -if (!((_key[0 ] ^ _key[2 ]) | (_key[1 ] ^ _key[3 ])) || - !((_key[2 ] ^ _key[4 ]) | (_key[3 ] ^ _key[5 ])) || - !((_key[0 ] ^ _key[4 ]) | (_key[1 ] ^ _key[5 ]))) - ctx->need_fallback = true; - }else if (IS_AES (flags)) { +if (IS_AES (flags)) {/* No random key sizes */ if (authenc_keys.enckeylen != AES_KEYSIZE_128 && authenc_keys.enckeylen != AES_KEYSIZE_192 &&
@@ -699,38 +677,6 @@ struct qce_aead_def {static const struct qce_aead_def aead_def[] = { { - .flags =QCE_ALG_DES |QCE_MODE_CBC |QCE_HASH_SHA1_HMAC , - .name ="authenc(hmac(sha1),cbc(des))" , - .drv_name ="authenc-hmac-sha1-cbc-des-qce" , - .blocksize =DES_BLOCK_SIZE , - .ivsize =DES_BLOCK_SIZE , - .maxauthsize =SHA1_DIGEST_SIZE , - }, - { - .flags =QCE_ALG_3DES |QCE_MODE_CBC |QCE_HASH_SHA1_HMAC , - .name ="authenc(hmac(sha1),cbc(des3_ede))" , - .drv_name ="authenc-hmac-sha1-cbc-3des-qce" , - .blocksize =DES3_EDE_BLOCK_SIZE , - .ivsize =DES3_EDE_BLOCK_SIZE , - .maxauthsize =SHA1_DIGEST_SIZE , - }, - { - .flags =QCE_ALG_DES |QCE_MODE_CBC |QCE_HASH_SHA256_HMAC , - .name ="authenc(hmac(sha256),cbc(des))" , - .drv_name ="authenc-hmac-sha256-cbc-des-qce" , - .blocksize =DES_BLOCK_SIZE , - .ivsize =DES_BLOCK_SIZE , - .maxauthsize =SHA256_DIGEST_SIZE , - }, - { - .flags =QCE_ALG_3DES |QCE_MODE_CBC |QCE_HASH_SHA256_HMAC , - .name ="authenc(hmac(sha256),cbc(des3_ede))" , - .drv_name ="authenc-hmac-sha256-cbc-3des-qce" , - .blocksize =DES3_EDE_BLOCK_SIZE , - .ivsize =DES3_EDE_BLOCK_SIZE , - .maxauthsize =SHA256_DIGEST_SIZE , - }, - { .flags =QCE_ALG_AES |QCE_MODE_CBC |QCE_HASH_SHA256_HMAC , .name ="authenc(hmac(sha256),cbc(aes))" , .drv_name ="authenc-hmac-sha256-cbc-aes-qce" ,
drivers/crypto/qce/common.c +12 -43
113 lines not on this page · raw message
drivers/crypto/qce/common.h +3 -13
@@ -22,7 +22,7 @@/* IV length in bytes */ #define QCE_AES_IV_LENGTH AES_BLOCK_SIZE -/* max of AES_BLOCK_SIZE, DES3_EDE_BLOCK_SIZE */ +/* max of AES_BLOCK_SIZE */ #define QCE_MAX_IV_SIZE AES_BLOCK_SIZE/* maximum nonce bytes */
@@ -33,14 +33,10 @@#define QCE_MAX_ALIGN_SIZE 64/* cipher algorithms */ -#define QCE_ALG_DES BIT(0) -#define QCE_ALG_3DES BIT(1)#define QCE_ALG_AES BIT(2)/* hash and hmac algorithms */ -#define QCE_HASH_SHA1 BIT(3)#define QCE_HASH_SHA256 BIT(4) -#define QCE_HASH_SHA1_HMAC BIT(5)#define QCE_HASH_SHA256_HMAC BIT(6)#define QCE_HASH_AES_CMAC BIT(7)
@@ -58,21 +54,15 @@#define QCE_ENCRYPT BIT(30)#define QCE_DECRYPT BIT(31) -#define IS_DES (flags) (flags & QCE_ALG_DES) -#define IS_3DES (flags) (flags & QCE_ALG_3DES)#define IS_AES (flags) (flags & QCE_ALG_AES) -#define IS_SHA1 (flags) (flags & QCE_HASH_SHA1)#define IS_SHA256 (flags) (flags & QCE_HASH_SHA256) -#define IS_SHA1_HMAC (flags) (flags & QCE_HASH_SHA1_HMAC)#define IS_SHA256_HMAC (flags) (flags & QCE_HASH_SHA256_HMAC)#define IS_CMAC (flags) (flags & QCE_HASH_AES_CMAC) -#define IS_SHA (flags) (IS_SHA1(flags) || IS_SHA256(flags)) -#define IS_SHA_HMAC (flags) \ - (IS_SHA1_HMAC(flags) || IS_SHA256_HMAC(flags)) +#define IS_SHA (flags) IS_SHA256(flags) +#define IS_SHA_HMAC (flags) IS_SHA256_HMAC(flags)#define IS_CBC (mode) (mode & QCE_MODE_CBC) -#define IS_ECB (mode) (mode & QCE_MODE_ECB)#define IS_CTR (mode) (mode & QCE_MODE_CTR)#define IS_XTS (mode) (mode & QCE_MODE_XTS)#define IS_CCM (mode) (mode & QCE_MODE_CCM)
drivers/crypto/qce/regs-v5.h +0 -4
@@ -203,7 +203,6 @@#define AUTH_SIZE_SHIFT 9#define AUTH_SIZE_MASK GENMASK(13, 9) -#define AUTH_SIZE_SHA1 0#define AUTH_SIZE_SHA256 1#define AUTH_SIZE_ENUM_1_BYTES 0#define AUTH_SIZE_ENUM_2_BYTES 1
@@ -284,15 +283,12 @@#define ENCR_KEY_SZ_SHIFT 3#define ENCR_KEY_SZ_MASK GENMASK(5, 3) -#define ENCR_KEY_SZ_DES 0 -#define ENCR_KEY_SZ_3DES 1#define ENCR_KEY_SZ_AES128 0#define ENCR_KEY_SZ_AES256 2#define ENCR_ALG_SHIFT 0#define ENCR_ALG_MASK GENMASK(2, 0)#define ENCR_ALG_NONE 0 -#define ENCR_ALG_DES 1#define ENCR_ALG_AES 2#define ENCR_ALG_KASUMI 4#define ENCR_ALG_SNOW_3G 5
drivers/crypto/qce/sha.c +2 -28
@@ -24,10 +24,6 @@ struct qce_sha_saved_state {static LIST_HEAD (ahash_algs); -static const u32 std_iv_sha1[SHA256_DIGEST_SIZE /sizeof (u32)] = { -SHA1_H0 ,SHA1_H1 ,SHA1_H2 ,SHA1_H3 ,SHA1_H4 ,0 ,0 ,0 -}; -static const u32 std_iv_sha256[SHA256_DIGEST_SIZE /sizeof (u32)] = {SHA256_H0 ,SHA256_H1 ,SHA256_H2 ,SHA256_H3 ,SHA256_H4 ,SHA256_H5 ,SHA256_H6 ,SHA256_H7
@@ -348,9 +344,7 @@ static int qce_ahash_hmac_setkey(structreturn 0 ; } -if (digestsize ==SHA1_DIGEST_SIZE ) - alg_name ="sha1-qce" ; -else if (digestsize ==SHA256_DIGEST_SIZE ) +if (digestsize ==SHA256_DIGEST_SIZE ) alg_name ="sha256-qce" ;else return -EINVAL ;
@@ -412,15 +406,6 @@ struct qce_ahash_def {static const struct qce_ahash_def ahash_def[] = { { - .flags =QCE_HASH_SHA1 , - .name ="sha1" , - .drv_name ="sha1-qce" , - .digestsize =SHA1_DIGEST_SIZE , - .blocksize =SHA1_BLOCK_SIZE , - .statesize =sizeof (struct qce_sha_saved_state ), - .std_iv = std_iv_sha1, - }, - { .flags =QCE_HASH_SHA256 , .name ="sha256" , .drv_name ="sha256-qce" ,
@@ -430,15 +415,6 @@ static const struct qce_ahash_def ahash_ .std_iv = std_iv_sha256, }, { - .flags = QCE_HASH_SHA1_HMAC, - .name = "hmac(sha1)", - .drv_name = "hmac-sha1-qce", - .digestsize = SHA1_DIGEST_SIZE, - .blocksize = SHA1_BLOCK_SIZE, - .statesize = sizeof(struct qce_sha_saved_state), - .std_iv = std_iv_sha1, - }, - { .flags = QCE_HASH_SHA256_HMAC, .name = "hmac(sha256)", .drv_name = "hmac-sha256-qce",
@@ -475,9 +451,7 @@ static int qce_ahash_register_one(const alg->halg.digestsize = def->digestsize; alg->halg.statesize = def->statesize; -if (IS_SHA1 (def->flags)) - tmpl->hash_zero = sha1_zero_message_hash; -else if (IS_SHA256 (def->flags)) +if (IS_SHA256 (def->flags)) tmpl->hash_zero = sha256_zero_message_hash; base = &alg->halg.base;
drivers/crypto/qce/sha.h +0 -1
@@ -7,7 +7,6 @@#define _SHA_H_#include <crypto/scatterwalk.h> -#include <crypto/sha1.h> #include <crypto/sha2.h> #include "common.h"
drivers/crypto/qce/skcipher.c +2 -95
133 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 83/91 KVM: s390: vsie: zero stale crypto bits
In reply to Greg Kroah-Hartman6.6-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
@@ -149,6 +149,7 @@ static int setup_apcb10(struct kvm_vcpu 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 84/91 usb: core: Add lock to usb_wakeup_notification()
In reply to Greg Kroah-Hartman6.6-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
@@ -727,10 +727,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 ];
@@ -740,6 +742,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 85/91 usb: core: Strengthen error handling in hub_hub_status()
In reply to Greg Kroah-Hartman6.6-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
@@ -968,10 +968,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 86/91 ALSA: usb-audio: fix OOB write in snd_usbmidi_novation_output()
In reply to Greg Kroah-Hartman6.6-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
@@ -878,6 +878,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 87/91 ALSA: usb-audio: Complete cleanup after system-resume errors
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Will Porter <[email protected]>
commit 1739a976312e110c93a8dee66a1cdf893a1b187e upstream.
A failed system resume can leave the card unusable until reboot. usb_audio_resume() jumps to err_out when snd_usb_pcm_resume() or snd_usb_mixer_resume() fails. The error path skips the out: block, which restores D0 and decrements chip->num_suspended_intf.
The card stays in SNDRV_CTL_POWER_D3hot, so later control access blocks in snd_power_ref_and_wait(). USB core logs an interface resume callback error. It does not retry that callback, so a later callback cannot complete the skipped cleanup.
usb_audio_suspend() increments num_suspended_intf before returning success. A system-resume callback must consume the system-suspend count even if a component resume fails. Otherwise, the stranded count skews later suspend and resume cycles.
Do not apply this cleanup to runtime-resume errors. Runtime PM can retry -EAGAIN or -EBUSY without another suspend callback. The count must continue to describe that suspended interface. Other runtime-resume errors latch runtime_error in the PM core and do not cause an immediate callback retry.
Both parts of the system-resume error path are longstanding. Commit 88a8516a2128a ("ALSA: usbaudio: implement USB autosuspend") introduced err_out past the D0 restore. Commit 862b2509d157c ("ALSA: usb-audio: Fix inconsistent card PM state after resume") later moved num_suspended_intf-- into the out: block. The error path now skips both operations.
No third-party code is needed to reach the error path. snd_usb_mixer_resume() ends in snd_usb_mixer_activate(), which returns the result of usb_submit_urb() for devices that have a mixer status URB. Its mixer->private_resume hook can also fail through scarlett2_init_notify(). snd_usb_pcm_resume() issues a SET_CUR request to a UAC3 power domain. It can return -EPIPE or -EIO when the device stalls the request.
Route a component error through out: only when system_suspend is nonzero. Continue to return runtime-resume errors through err_out. Later component resume stages remain skipped. The original error still reaches USB core. A later transfer can fail if the device did not recover.
I reproduced the system-resume failure on an Audient iD14 MkI with an out-of-tree diagnostic mixer resume hook. An injected -EIO on the unpatched core left control readers in uninterruptible sleep in snd_power_ref_and_wait() until a reboot. With this patch, the same failure restored control access. A second system suspend and resume also succeeded after I disabled fault injection.
--- sound/usb/card.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
sound/usb/card.c +10 -4
@@ -1122,8 +1122,11 @@ static int usb_audio_resume(struct usb_ilist_for_each_entry (as, &chip->pcm_list, list) { err =snd_usb_pcm_resume (as); -if (err <0 ) - goto err_out; +if (err <0 ) { +if (!chip->system_suspend) + goto err_out; + goto out; + } }/*
@@ -1132,8 +1135,11 @@ static int usb_audio_resume(struct usb_i*/ list_for_each_entry (mixer, &chip->mixer_list, list) { err =snd_usb_mixer_resume (mixer); -if (err <0 ) - goto err_out; +if (err <0 ) { +if (!chip->system_suspend) + goto err_out; + goto out; + } }list_for_each (p, &chip->midi_list) {
Greg Kroah-Hartman
maintainerPATCH 88/91 USB: serial: option: fix slab OOB read in interrupt URB callback
In reply to Greg Kroah-Hartman6.6-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
@@ -2691,12 +2691,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 89/91 USB: serial: spcp8x5: drop broken carrier detect support
In reply to Greg Kroah-Hartman6.6-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
@@ -247,18 +247,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);
@@ -471,7 +459,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 90/91 USB: c67x00: fix use-after-free in c67x00_add_iso_urb()
In reply to Greg Kroah-Hartman6.6-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 91/91 usb: usbfs: fix use-after-free of usb_device in usbdev_release()
In reply to Greg Kroah-Hartman6.6-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
@@ -1110,7 +1110,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);
@@ -1119,6 +1118,7 @@ static int usbdev_release(struct inode *free_async (as); as =async_getcompleted (ps); } +usb_put_dev (dev);kfree (ps);return 0 ;
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.6.156 release. There are 91 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 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.6.156 release. There are 91 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/v6.x/stable-review/patch-6.6.156-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.6.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
Hi,
Build tested in our x86,arm64,loongarch,riscv config successfully without error.
Best Regards
Wentao Guan
Log:
Linux version 6.6.156-rc1-arm64-desktop-hwe-g658884b4c6d2 (guanwentao@uos-PC) (aarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP PREEMPT Linux version 6.6.156-rc1-arm64-desktop-hwe-g658884b4c6d2 (guanwentao@uos-PC) (aarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #2 SMP PREEMPT Tue Sep 1 01:40:37 CST 2026 Linux version 6.6.156-rc1-loong64-desktop-hwe-g658884b4c6d2 (guanwentao@uos-PC) (loongarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP PREEMPT Linux version 6.6.156-rc1-loong64-desktop-hwe-g658884b4c6d2 (guanwentao@uos-PC) (loongarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #3 SMP PREEMPT Tue Sep 1 01:56:17 CST 2026 Linux version 6.6.156-rc1-riscv64-desktop-hwe+ (guanwentao@uos-PC) (riscv64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP
Linux version 6.6.156-rc1-riscv64-desktop-hwe+ (guanwentao@uos-PC) (riscv64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #4 SMP Tue Sep 1 02:11:55 CST 2026 Linux version 6.6.156-rc1-amd64-desktop-hwe-g658884b4c6d2 (guanwentao@uos-PC) (gcc (Deepin 12.3.0-17deepin18) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP PREEMPT_DYNAMIC
Linux version 6.6.156-rc1-amd64-desktop-hwe-g658884b4c6d2 (guanwentao@uos-PC) (gcc (Deepin 12.3.0-17deepin18) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #1 SMP PREEMPT_DYNAMIC Tue Sep 1 01:25:21 CST 2026
# Librecast Test Results
020/020 [ OK ] liblcrq
010/010 [ OK ] libmld
120/120 [ OK ] liblibrecast
CPU/kernel: Linux auntie 6.6.156-rc1-g658884b4c6d2 #1 SMP PREEMPT_DYNAMIC Mon Aug 31 19:09:36 -00 2026 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux
Am 31.08.2026 um 15:33 schrieb Greg Kroah-Hartman:
Quoted 4 lines
This is the start of the stable review cycle for the 6.6.156 release. There are 91 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.
Builds, boots and works on my 2-socket Ivy Bridge Xeon E5-2697 v2 server. No dmesg oddities or regressions found.
Beste Grüße,
Peter Schneider
Signature · 8 lines
Climb the mountain not to plant your flag, but to embrace the challenge, enjoy the air and behold the view. Climb it so you can see the world, not so the world can see you. -- David McCullough Jr. OpenPGP: 0xA3828BD796CCE11A8CADE8866E3A92C92C3FF244 Download: https://www.peters-netzplatz.de/download/pschneider1968_pub.asc https://keys.mailvelope.com/pks/lookup?op=get&[email protected] https://keys.mailvelope.com/pks/lookup?op=get&[email protected]
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 6.6.156 release. There are 91 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-6.6.y
Best regards,
Pavel
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.6.156 release. There are 91 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/v6.x/stable-review/patch-6.6.156-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.6.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.6.156 release. There are 91 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/v6.x/stable-review/patch-6.6.156-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.6.y
and the diffstat can be found below.thanks,
greg k-h
Built and booted successfully on RISC-V RV64 (HiFive Unmatched).
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.6.156 release. There are 91 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/v6.x/stable-review/patch-6.6.156-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.6.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]>