5.10.259-rc1 review
Subsystems (4)
Greg Kroah-Hartman
maintainercover 5.10.259-rc1 review
This is the start of the stable review cycle for the 5.10.259 release. There are 342 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 Thu, 18 Jun 2026 14:49:57 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/patch-5.10.259-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-5.10.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 5.10.259-rc1
Borislav Petkov (AMD) <[email protected]>
x86/CPU/AMD: Move the Zen3 BTC_NO detection to the Zen3 init function
Ben Hutchings <[email protected]>
apparmor: validate default DFA states are in bounds
Ben Hutchings <[email protected]>
fbdev: vt8500lcdfb: Fix dma_free_coherent() cpu_addr parameter
Will Deacon <[email protected]>
arm64: errata: Mitigate TLBI errata on Microsoft Azure Cobalt 100 CPU
Shanker Donthineni <[email protected]>
arm64: errata: Mitigate TLBI errata on NVIDIA Olympus CPU
Mark Rutland <[email protected]>
arm64: errata: Mitigate TLBI errata on various Arm CPUs
Mark Rutland <[email protected]>
arm64: cputype: Add C1-Premium definitions
Mark Rutland <[email protected]>
arm64: cputype: Add C1-Ultra definitions
Shanker Donthineni <[email protected]>
arm64: cputype: Add NVIDIA Olympus definitions
Easwar Hariharan <[email protected]>
arm64: Subscribe Microsoft Azure Cobalt 100 to ARM Neoverse N2 errata
Lukas Wunner <[email protected]>
lib/crypto: mpi: Fix integer underflow in mpi_read_raw_from_sgl()
Guangshuo Li <[email protected]>
usb: gadget: f_hid: fix device reference leak in hidg_alloc()
John Keeping <[email protected]>
usb: gadget: f_hid: tidy error handling in hidg_alloc
Tudor Ambarus <[email protected]>
tty: serial: samsung: Remove redundant port lock acquisition in rx helpers
Tudor Ambarus <[email protected]>
tty: serial: samsung: use u32 for register interactions
Thomas Gleixner <[email protected]>
serial: samsung_tty: Use port lock wrappers
Minh Nguyen <[email protected]>
net: skbuff: fix missing zerocopy reference in pskb_carve helpers
Zhengchuan Liang <[email protected]>
xfrm: input: hold netns during deferred transport reinjection
Rodrigo Alencar <[email protected]>
iio: dac: ad5686: fix ref bit initialization for single-channel parts
Antoniu Miclaus <[email protected]>
iio: gyro: adis16260: fix division by zero in write_raw
Antoniu Miclaus <[email protected]>
iio: chemical: scd30: fix division by zero in write_raw
Jonathan Cameron <[email protected]>
iio: chemical: scd30: Use guard(mutex) to allow early returns
Yongchao Wu <[email protected]>
usb: cdns3: gadget: fix request skipping after clearing halt
David Carlier <[email protected]>
iio: adc: npcm: fix unbalanced clk_disable_unprepare()
Aaron Erhardt <[email protected]>
ALSA: hda/hdmi: Add quirk for TUXEDO IBS14G6
Siwei Zhang <[email protected]>
Bluetooth: L2CAP: use chan timer to close channels in cleanup_listen()
Jason Gunthorpe <[email protected]>
RDMA/umem: Fix truncation for block sizes >= 4G
Leon Romanovsky <[email protected]>
RDMA: Move DMA block iterator logic into dedicated files
Randy Dunlap <[email protected]>
RDMA/umem: fix kernel-doc warnings
Yin Tirui <[email protected]>
mm/huge_memory: update file PMD counter before folio_put()
Anton Leontev <[email protected]>
hv_netvsc: use kmap_local_page in netvsc_copy_to_send_buf
Davide Ornaghi <[email protected]>
netfilter: nft_fib: fix stale stack leak via the OIFNAME register
Myrrh Periwinkle <[email protected]>
usb: typec: ucsi: Don't update power_supply on power role change if not connected
Michael Bommarito <[email protected]>
scsi: target: iscsi: Fix CRC overread and double-free in iscsit_handle_text_cmd()
Myeonghun Pak <[email protected]>
serial: altera_jtaguart: handle uart_add_one_port() failures
Lad Prabhakar <[email protected]>
serial: altera_jtaguart: Use platform_get_irq_optional() to get the interrupt
Prasanna S <[email protected]>
serial: qcom-geni: fix UART_RX_PAR_EN bit position
Bartosz Golaszewski <[email protected]>
tty: serial: qcom-geni-serial: align #define values
Bartosz Golaszewski <[email protected]>
tty: serial: qcom-geni-serial: remove unused symbols
Michael Bommarito <[email protected]>
thunderbolt: property: Cap recursion depth in __tb_property_parse_dir()
Myrrh Periwinkle <[email protected]>
usb: typec: ucsi: Check if power role change actually happened before handling
Michael Bommarito <[email protected]>
scsi: target: iscsi: Bound iscsi_encode_text_output() appends to rsp_buf
Wayne Chang <[email protected]>
phy: tegra: xusb: Fix per-pad high-speed termination calibration
Wayne Chang <[email protected]>
phy: tegra: xusb: Disable trk clk when not in use
Zeng Heng <[email protected]>
arm64: tlb: Flush walk cache when unsharing PMD tables
Johan Hovold <[email protected]>
spi: qup: fix error pointer deref after DMA setup failure
Yang Yingliang <[email protected]>
spi: qup: switch to use modern name
Sam Daly <[email protected]>
octeontx2-af: CGX: add bounds check to cgx_speed_mbps index
Justin Stitt <[email protected]>
octeontx2-af: replace deprecated strncpy with strscpy
Hariprasad Kelam <[email protected]>
octeontx2-af: Add validation for lmac type
Dawei Feng <[email protected]>
octeontx2-pf: avoid double free of pool->stack on AQ init failure
Shardul Bankar <[email protected]>
mptcp: do not drop partial packets
Matthieu Baerts (NGI0) <[email protected]>
selftests: mptcp: drop nanoseconds width specifier
Al Viro <[email protected]>
use less confusing names for iov_iter direction initializers
Jose Ignacio Tornos Martinez <[email protected]>
ice: fix VF queue configuration with low MTU values
Michael Bommarito <[email protected]>
net: hsr: defer node table free until after RCU readers
Jiexun Wang <[email protected]>
Bluetooth: serialize accept_q access
Luiz Augusto von Dentz <[email protected]>
Bluetooth: Init sk_peer_* on bt_sock_alloc
Luiz Augusto von Dentz <[email protected]>
Bluetooth: Consolidate code around sk_alloc into a helper function
Haoze Xie <[email protected]>
netfilter: nf_queue: hold bridge skb->dev while queued
Yajun Deng <[email protected]>
net: Remove redundant if statements
Dawei Feng <[email protected]>
qed: fix double free in qed_cxt_tables_alloc()
Christophe JAILLET <[email protected]>
qed: Use the bitmap API to simplify some functions
Shuai Zhang <[email protected]>
Bluetooth: hci_qca: Convert timeout from jiffies to ms
Safa Karakuş <[email protected]>
Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del()
Johan Hovold <[email protected]>
spi: lantiq-ssc: fix controller deregistration
Johan Hovold <[email protected]>
spi: st-ssc4: fix controller deregistration
Yongpeng Yang <[email protected]>
f2fs: fix incorrect file address mapping when inline inode is unwritten
Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: ADD_ADDR rtx: fix potential data-race
Piyush Sachdeva <[email protected]>
smb: client: Use FullSessionKey for AES-256 encryption key derivation
Filipe Manana <[email protected]>
btrfs: fix missing last_unlink_trans update when removing a directory
Mikulas Patocka <[email protected]>
dm-thin: fix metadata refcount underflow
Joe Thornber <[email protected]>
dm btree: improve btree residency
Ulf Hansson <[email protected]>
pmdomain: core: Fix detach procedure for virtual devices in genpd
Steven Rostedt <[email protected]>
tracing/probes: Limit size of event probe to 3K
Yochai Eisenrich <[email protected]>
btrfs: fix btrfs_ioctl_space_info() slot_count TOCTOU which can lead to info-leak
Johan Hovold <[email protected]>
spi: topcliff-pch: fix controller deregistration
Thomas Zimmermann <[email protected]>
fbcon: Avoid OOB font access if console rotation fails
Sang-Heon Jeon <[email protected]>
mm/hugetlb_cma: round up per_node before logging it
Johan Hovold <[email protected]>
spi: uniphier: fix controller deregistration
Johan Hovold <[email protected]>
spi: tegra114: fix controller deregistration
Johan Hovold <[email protected]>
spi: tegra20-sflash: fix controller deregistration
Johan Hovold <[email protected]>
spi: sun6i: fix controller deregistration
Johan Hovold <[email protected]>
spi: zynq-qspi: fix controller deregistration
Johan Hovold <[email protected]>
spi: ti-qspi: fix controller deregistration
Johan Hovold <[email protected]>
spi: sun4i: fix controller deregistration
Johan Hovold <[email protected]>
spi: syncuacer: fix controller deregistration
Selvarasu Ganesan <[email protected]>
usb: dwc3: Move GUID programming after PHY initialization
Marek Szyprowski <[email protected]>
wifi: brcmfmac: Fix potential use-after-free issue when stopping watchdog task
David Carlier <[email protected]>
tracepoint: balance regfunc() on func_add() failure in tracepoint_add_func()
Guangshuo Li <[email protected]>
ACPI: scan: Use acpi_dev_put() in object add error paths
Thorsten Blum <[email protected]>
crypto: caam - guard HMAC key hex dumps in hash_digest_key
Thorsten Blum <[email protected]>
printk: add print_hex_dump_devel()
Cássio Gabriel <[email protected]>
ALSA: aloop: Fix peer runtime UAF during format-change stop
Max Kellermann <[email protected]>
ceph: only d_add() negative dentries when they are unhashed
Steven Rostedt <[email protected]>
ktest: Fix the month in the name of the failure directory
John 'Warthog9' Hawley (VMware) <[email protected]>
ktest: Fixing indentation to match expected pattern
Johan Hovold <[email protected]>
can: ucan: fix devres lifetime
Julia Lawall <[email protected]>
can: ucan: fix typos in comments
Shuvam Pandey <[email protected]>
Bluetooth: hci_event: fix potential UAF in SSP passkey handlers
Zilin Guan <[email protected]>
hfsplus: fix held lock freed on hfsplus_fill_super()
Deepanshu Kartikey <[email protected]>
hfsplus: fix uninit-value by validating catalog record size
Seohyeon Maeng <[email protected]>
udf: fix partition descriptor append bookkeeping
Sanjaikumar V S <[email protected]>
mtd: spi-nor: sst: Fix write enable before AAI sequence
Zhengchuan Liang <[email protected]>
net: bridge: use a stable FDB dst snapshot in RCU readers
Manivannan Sadhasivam <[email protected]>
net: qrtr: ns: Limit the total number of nodes
Manivannan Sadhasivam <[email protected]>
net: qrtr: ns: Free the node during ctrl_cmd_bye()
Vignesh Viswanathan <[email protected]>
net: qrtr: ns: Change servers radix tree to xarray
Manivannan Sadhasivam <[email protected]>
net: qrtr: ns: Limit the maximum number of lookups
Takashi Iwai <[email protected]>
ALSA: core: Fix potential data race at fasync handling
Joseph Salisbury <[email protected]>
sched: Use u64 for bandwidth ratio calculations
Oliver Neukum <[email protected]>
media: rc: igorplugusb: heed coherency rules
Gao Xiang <[email protected]>
erofs: fix the out-of-bounds nameoff handling for trailing dirents
Thorsten Blum <[email protected]>
ALSA: aoa: Skip devices with no codecs in i2sbus_resume()
Oliver Neukum <[email protected]>
media: rc: ttusbir: respect DMA coherency rules
Cássio Gabriel <[email protected]>
ALSA: aoa: i2sbus: clear stale prepared state
Takashi Iwai <[email protected]>
ALSA: aoa: Use guard() for mutex locks
Daniel Hodges <[email protected]>
wifi: mwifiex: fix use-after-free in mwifiex_adapter_cleanup()
Rafael J. Wysocki <[email protected]>
thermal: core: Fix thermal zone governor cleanup issues
Anshuman Khandual <[email protected]>
arm64/mm: Enable batched TLB flush in unmap_hotplug_range()
Greg Kroah-Hartman <[email protected]>
drm/nouveau: fix u32 overflow in pushbuf reloc bounds check
Bingquan Chen <[email protected]>
net/packet: fix TOCTOU race on mmap'd vnet_hdr in tpacket_snd()
Michael Bommarito <[email protected]>
smb: client: fix OOB read in smb2_ioctl_query_info QUERY_INFO path
Michael Bommarito <[email protected]>
smb: client: require a full NFS mode SID before reading mode bits
Yongpeng Yang <[email protected]>
f2fs: fix UAF caused by decrementing sbi->nr_pages[] in f2fs_write_end_io()
Sven Eckelmann <[email protected]>
batman-adv: tp_meter: fix tp_num leak on kmalloc failure
Jiexun Wang <[email protected]>
batman-adv: stop tp_meter sessions during mesh teardown
Julian Anastasov <[email protected]>
ipvs: skip ipv6 extension headers for csum checks
Longxuan Yu <[email protected]>
io_uring/poll: fix signed comparison in io_poll_get_ownership()
Mingyu Wang <[email protected]>
fs/fcntl: fix SOFTIRQ-unsafe lock order in fasync signaling
Harry Wentland <[email protected]>
drm/amd/display: Fix NULL deref and buffer over-read in SDP debugfs
Harry Wentland <[email protected]>
drm/amd/display: Clamp HDMI HDCP2 rx_id_list read to buffer size
Michael Bommarito <[email protected]>
thunderbolt: Limit XDomain response copy to actual frame size
Michael Bommarito <[email protected]>
thunderbolt: Clamp XDomain response data copy to allocation size
Michael Bommarito <[email protected]>
thunderbolt: Bound root directory content to block size
Michael Bommarito <[email protected]>
thunderbolt: Reject zero-length property entries in validator
Wyatt Feng <[email protected]>
sctp: stream: fully roll back denied add-stream state
Zhao Zhang <[email protected]>
sctp: diag: reject stale associations in dump_one path
Jisheng Zhang <[email protected]>
mmc: sdhci: add signal voltage switch in sdhci_resume_host
Kamal Dasu <[email protected]>
mmc: core: Fix host controller programming for fixed driver type
Yuqi Xu <[email protected]>
net: rds: clear i_sends on setup unwind
Bartosz Golaszewski <[email protected]>
net: mv643xx: fix OF node refcount
ZhaoJinming <[email protected]>
net: bonding: fix NULL pointer dereference in bond_do_ioctl()
Anandu Krishnan E <[email protected]>
misc: fastrpc: fix use-after-free of fastrpc_user in workqueue context
Yilin Zhu <[email protected]>
ipc/shm: serialize orphan cleanup with shm_nattch updates
Cryolitia PukNgae <[email protected]>
Input: atkbd - skip deactivate for HONOR BCC-N's internal keyboard
Zeyu WANG <[email protected]>
Input: atkbd - add DMI quirk for Lenovo Yoga Air 14 (83QK)
Akhil R <[email protected]>
i2c: tegra: Fix NOIRQ suspend/resume
Vladimir Zapolskiy <[email protected]>
i2c: qcom-cci: Fix NULL pointer dereference in cci_remove()
Jann Horn <[email protected]>
fuse: reject fuse_notify() pagecache ops on directories
Christian Brauner <[email protected]>
pidfd: refuse access to tasks that have started exiting harder
Michael Bommarito <[email protected]>
IB/isert: Reject login PDUs shorter than ISER_HEADERS_LEN
Raf Dickson <[email protected]>
vsock/vmci: fix sk_ack_backlog leak on failed handshake
Yuho Choi <[email protected]>
ARM: socfpga: Fix OF node refcount leak in SMP setup
Michael Bommarito <[email protected]>
RDMA/srp: bound SRP_RSP sense copy by the received length
Harry Wentland <[email protected]>
drm/amd/display: Reject gpio_bitshift >= 32 in bios_parser_get_gpio_pin_info()
Takashi Iwai <[email protected]>
ALSA: timer: Fix UAF at snd_timer_user_params()
HyeongJun An <[email protected]>
USB: serial: kl5kusb105: fix bulk-out buffer overflow
Jack Wu <[email protected]>
USB: serial: option: add usb-id for Dell Wireless DW5826e-m
Adrian Korwel <[email protected]>
USB: serial: io_ti: fix heap overflow in build_i2c_fw_hdr()
Adrian Korwel <[email protected]>
USB: serial: io_ti: fix heap overflow in get_manuf_info()
Wyatt Feng <[email protected]>
xfrm: espintcp: do not reuse an in-progress partial send
Joonas Lahtinen <[email protected]>
drm/i915/gem: Fix phys BO pread/pwrite with offset
Michael Bommarito <[email protected]>
Bluetooth: L2CAP: reject BR/EDR signaling packets over MTUsig
Tristan Madani <[email protected]>
netfilter: nft_tunnel: fix use-after-free on object destroy
Til Kaiser <[email protected]>
net: mvpp2: sync RX data at the hardware packet offset
Florian Westphal <[email protected]>
netfilter: nft_exthdr: fix register tracking for F_PRESENT flag
Kyle Zeng <[email protected]>
netfilter: x_tables: avoid leaking percpu counter pointers
Breno Leitao <[email protected]>
rds: mark snapshot pages dirty in rds_info_getsockopt()
Eric Dumazet <[email protected]>
ip6_vti: fix incorrect tunnel matching in vti6_tnl_lookup()
Weiming Shi <[email protected]>
net/rds: fix NULL deref in rds_ib_send_cqe_handler() on masked atomic completion
Kyle Zeng <[email protected]>
net: guard timestamp cmsgs to real error queue skbs
Michael Bommarito <[email protected]>
sctp: fix uninit-value in __sctp_rcv_asconf_lookup()
Adrian Moreno <[email protected]>
net: openvswitch: fix possible kfree_skb of ERR_PTR
Kyle Zeng <[email protected]>
ipv6: sit: reload inner IPv6 header after GSO offloads
Mingyu Wang <[email protected]>
net: qrtr: fix refcount saturation and potential UAF in qrtr_port_remove
Chenguang Zhao <[email protected]>
netlabel: validate unlabeled address and mask attribute lengths
Sanghyun Park <[email protected]>
xfrm: policy: fix use-after-free on inexact bin in xfrm_policy_bysel_ctx()
Mark Rutland <[email protected]>
arm64: tlb: Optimize ARM64_WORKAROUND_REPEAT_TLBI
Mark Rutland <[email protected]>
arm64: tlb: Allow XZR argument to TLBI ops
Marc Zyngier <[email protected]>
KVM: arm64: Remove VPIPT I-cache handling
Weiming Shi <[email protected]>
tun: free page on build_skb failure in tun_xdp_one()
Weiming Shi <[email protected]>
tap: free page on error paths in tap_get_user_xdp()
Pavel Begunkov <[email protected]>
io_uring: prevent opcode speculation
Felix Gu <[email protected]>
spi: meson-spicc: Fix double-put in remove path
Deepanshu Kartikey <[email protected]>
wifi: mac80211: check tdls flag in ieee80211_tdls_oper
Jeff Layton <[email protected]>
nfsd: don't ignore the return code of svc_proc_register()
Zqiang <[email protected]>
usbnet: Fix using smp_processor_id() in preemptible code warnings
Eric Dumazet <[email protected]>
bonding: limit BOND_MODE_8023AD to Ethernet devices
Tejas Bharambe <[email protected]>
ext4: validate p_idx bounds in ext4_ext_correct_indexes
Ji'an Zhou <[email protected]>
ALSA: PCM: Fix wait queue list corruption in snd_pcm_drain() on linked streams
Naveen Kumar Chaudhary <[email protected]>
time: Fix off-by-one in settimeofday() usec validation
Aleksandr Nogikh <[email protected]>
signal: clear JOBCTL_PENDING_MASK for caller in zap_other_threads()
Xin Long <[email protected]>
sctp: purge outqueue on stale COOKIE-ECHO handling
Yizhou Zhao <[email protected]>
net/802/mrp: fix vector attribute parsing in mrp_pdu_parse_vecattr
Eric Dumazet <[email protected]>
ieee802154: 6lowpan: only accept IPv6 packets in lowpan_xmit()
Eric Dumazet <[email protected]>
ipv4: restrict IPOPT_SSRR and IPOPT_LSRR options
Zhang Cen <[email protected]>
Bluetooth: MGMT: validate advertising TLV before type checks
Zhang Cen <[email protected]>
Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind()
David Thompson <[email protected]>
net: lan743x: permit VLAN-tagged packets up to configured MTU
Yizhou Zhao <[email protected]>
net: garp: fix unsigned integer underflow in garp_pdu_parse_attr
Oscar Maes <[email protected]>
pcnet32: stop holding device spin lock during napi_complete_done
Yicong Hui <[email protected]>
drm/imx: Fix three kernel-doc warnings in dcss-scaler.c
Yizhou Zhao <[email protected]>
6lowpan: fix off-by-one in multicast context address compression
Jamal Hadi Salim <[email protected]>
net/sched: act_api: use RCU with deferred freeing for action lifecycle
Guangshuo Li <[email protected]>
dm cache policy smq: check allocation under invalidate lock
Yiming Qian <[email protected]>
netfilter: bridge: make ebt_snat ARP rewrite writable
Florian Westphal <[email protected]>
netfilter: conntrack_irc: fix possible out-of-bounds read
Fernando Fernandez Mancera <[email protected]>
netfilter: synproxy: add mutex to guard hook reference counting
Julian Anastasov <[email protected]>
ipvs: clear the svc scheduler ptr early on edit
Fernando Fernandez Mancera <[email protected]>
netfilter: xt_NFQUEUE: prefer raw_smp_processor_id
Amirreza Zarrabi <[email protected]>
tee: optee: prevent use-after-free when the client exits before the supplicant
Mingyu Wang <[email protected]>
i2c: dev: prevent integer overflow in I2C_TIMEOUT ioctl
Nathan Chancellor <[email protected]>
Disable -Wattribute-alias for clang-23 and newer
Nathan Chancellor <[email protected]>
compiler-clang.h: Add __diag infrastructure for clang
Johan Hovold <[email protected]>
USB: serial: mct_u232: fix memory corruption with small endpoint
Nathan Chancellor <[email protected]>
HID: core: Fix size_t specifier in hid_report_raw_event()
Benjamin Tissoires <[email protected]>
HID: pass the buffer size to hid_report_raw_event
Vicki Pfau <[email protected]>
HID: core: Add printk_ratelimited variants to hid_warn() etc
Kuniyuki Iwashima <[email protected]>
bpf: Free reuseport cBPF prog after RCU grace period.
Michal Pecio <[email protected]>
usb: core: Fix SuperSpeed root hub wMaxPacketSize
Nikola Z. Ivanov <[email protected]>
team: Move team device type change at the end of team_port_add
Dong Chenchen <[email protected]>
page_pool: Fix use-after-free in page_pool_recycle_in_ring
Maciej W. Rozycki <[email protected]>
serial: dz: Fix bootconsole handover lockup
Wei-Cheng Chen <[email protected]>
xhci: tegra: Fix ghost USB device on dual-role port unplug
Johan Hovold <[email protected]>
USB: serial: digi_acceleport: fix memory corruption with small endpoints
Johan Hovold <[email protected]>
USB: serial: cypress_m8: fix memory corruption with small endpoint
Kuniyuki Iwashima <[email protected]>
Bluetooth: hci_core: Fix use-after-free in vhci_flush()
Maciej W. Rozycki <[email protected]>
serial: zs: Switch to using channel reset
Maciej W. Rozycki <[email protected]>
serial: zs: Fix bootconsole handover lockup
Maciej W. Rozycki <[email protected]>
serial: dz: Fix bootconsole message clobbering at chip reset
Shitalkumar Gandhi <[email protected]>
serial: fsl_lpuart: fix rx buffer and DMA map leaks in start_rx_dma
Maciej W. Rozycki <[email protected]>
serial: zs: Fix swapped RI/DSR modem line transition counting
Hongling Zeng <[email protected]>
serial: sh-sci: fix memory region release in error path
Michael Bommarito <[email protected]>
scsi: fcoe: Reject FIP descriptors with zero fip_dlen in CVL walker
Michael Bommarito <[email protected]>
thunderbolt: property: Reject dir_len < 4 to prevent size_t underflow
Michael Bommarito <[email protected]>
thunderbolt: property: Reject u32 wrap in tb_property_entry_valid()
Seungjin Bae <[email protected]>
usb: gadget: dummy_hcd: Reject hub port requests for non-existent ports
Guangshuo Li <[email protected]>
usb: gadget: net2280: Fix double free in probe error path
Johan Hovold <[email protected]>
USB: serial: mct_u232: fix missing interrupt-in transfer sanity check
Johan Hovold <[email protected]>
USB: serial: mxuport: fix memory corruption with small endpoint
Johan Hovold <[email protected]>
USB: serial: keyspan: fix missing indat transfer sanity check
Zhang Cen <[email protected]>
USB: serial: cypress_m8: validate interrupt packet headers
Zhang Cen <[email protected]>
USB: serial: belkin_sa: validate interrupt status length
Wanquan Zhong <[email protected]>
USB: serial: option: add missing RSVD(5) flag for Rolling RW135R-GL
Jan Volckaert <[email protected]>
USB: serial: option: add MeiG SRM813Q
Heitor Alves de Siqueira <[email protected]>
usb: usbtmc: reject interrupt endpoints with small wMaxPacketSize
Heitor Alves de Siqueira <[email protected]>
usb: usbtmc: check URB actual_length for interrupt-IN notifications
Michael Bommarito <[email protected]>
usbip: vudc: Fix use after free bug in vudc_remove due to race condition
Sam Burkels <[email protected]>
usb: storage: Add quirks for PNY Elite Portable SSD
Stephen J. Fuhry <[email protected]>
USB: quirks: add NO_LPM for Lenovo ThinkPad USB-C Dock Gen2 hub controllers
Michal Pecio <[email protected]>
usb: core: Fix up Interrupt IN endpoints with bogus wBytesPerInterval
Xu Yang <[email protected]>
usb: chipidea: core: convert ci_role_switch to local variable
Zhaoyang Yu <[email protected]>
tty: serial: pch_uart: add check for dma_alloc_coherent()
Ian Abbott <[email protected]>
comedi: comedi_test: Fix limiting of convert_arg in waveform_ai_cmdtest()
Ian Abbott <[email protected]>
comedi: comedi_test: fix check for valid scan_begin_src in waveform_ai_cmdtest()
Nicolás Bazaes <[email protected]>
Input: synaptics - add LEN2058 to SMBus passlist for ThinkPad E490
Dmitry Torokhov <[email protected]>
Input: atmel_mxt_ts - fix boundary check in mxt_prepare_cfg_mem
Jingguo Tan <[email protected]>
xfrm: esp: restore combined single-frag length gate
Srinivas Kandagatla <[email protected]>
ASoC: qcom: q6asm-dai: do not set stream state in event and trigger callbacks
Srinivas Kandagatla <[email protected]>
ASoC: qcom: q6asm-dai: close stream only when running
Hamza Mahfooz <[email protected]>
netfilter: conntrack: tcp: do not force CLOSE on invalid-seq RST without direction check
Michael Bommarito <[email protected]>
xfrm: ah: use skb_to_full_sk in async output callbacks
Maoyi Xie <[email protected]>
xfrm: route MIGRATE notifications to caller's netns
Ashutosh Desai <[email protected]>
nfc: hci: fix out-of-bounds read in HCP header parsing
Arnd Bergmann <[email protected]>
iommu, debugobjects: avoid gcc-16.1 section mismatch warnings
Lee Jones <[email protected]>
HID: wacom: Fix OOB write in wacom_hid_set_device_mode()
Kuniyuki Iwashima <[email protected]>
ip6: vti: Use ip6_tnl.net in vti6_changelink().
Qi Tang <[email protected]>
ipv6: validate extension header length before copying to cmsg
Maoyi Xie <[email protected]>
ip6: vti: Use ip6_tnl.net in vti6_siocdevprivate().
Srinivas Kandagatla <[email protected]>
ASoC: qcom: q6asm-dai: fix error handling in prepare and set_params
Justin Iurman <[email protected]>
ipv6: exthdrs: refresh nh pointer after ipv6_hop_jumbo()
Junrui Luo <[email protected]>
macsec: fix replay protection at XPN lower-PN wrap
Yuqi Xu <[email protected]>
bpf: sockmap: fix tail fragment offset in bpf_msg_push_data
Jason A. Donenfeld <[email protected]>
wireguard: send: append trailer after expanding head
Dmitry Torokhov <[email protected]>
Input: elan_i2c - validate firmware size before use
Dan Carpenter <[email protected]>
usb: dwc2: Fix use after free in debug code
Johan Hovold <[email protected]>
USB: serial: omninet: fix memory corruption with small endpoint
Felix Gu <[email protected]>
iio: buffer: hw-consumer: fix use-after-free in error path
Aldo Conte <[email protected]>
iio: light: cm3323: fix reg_conf not being initialized correctly
Salah Triki <[email protected]>
iio: temperature: tsys01: fix broken PROM checksum validation
Sanjay Chitroda <[email protected]>
iio: ssp_sensors: cancel delayed work_refresh on remove
David Carlier <[email protected]>
iio: gyro: itg3200: fix i2c read into the wrong stack location
Salah Triki <[email protected]>
iio: adc: viperboard: Fix error handling in vprbrd_iio_read_raw
Rodrigo Alencar <[email protected]>
iio: dac: ad5686: fix input raw value check
Salah Triki <[email protected]>
iio: dac: max5821: fix return value check in powerdown sync
Christofer Jonason <[email protected]>
iio: adc: xilinx-xadc: Fix sequencer mode in postdisable for dual mux
Ben Hutchings <[email protected]>
parport: Fix race between port and client registration
Siwei Zhang <[email protected]>
Bluetooth: L2CAP: fix chan ref leak in l2cap_chan_timeout() on !conn
Linpu Yu <[email protected]>
ipc: limit next_id allocation to the valid ID range
Mikulas Patocka <[email protected]>
hpfs: fix a crash if hpfs_map_dnode_bitmap fails
Shuai Zhang <[email protected]>
Bluetooth: btusb: Allow firmware re-download when version matches
Thomas Fourier <[email protected]>
Input: ims-pcu - fix usb_free_coherent() size in ims_pcu_buffers_free()
Johan Hovold <[email protected]>
USB: serial: safe_serial: fix memory corruption with small endpoint
Greg Kroah-Hartman <[email protected]>
usb: typec: wcove: don't write past struct pd_message in wcove_read_rx_buffer()
Greg Kroah-Hartman <[email protected]>
usb: typec: altmodes/displayport: validate count before reading Status Update VDO
Greg Kroah-Hartman <[email protected]>
usb: typec: ucsi: displayport: NAK DP_CMD_CONFIGURE without a payload VDO
Greg Kroah-Hartman <[email protected]>
usb: typec: ucsi: ccg: reject firmware images without a ':' record header
Greg Kroah-Hartman <[email protected]>
iio: imu: st_lsm6dsx: fix stack leak in tagged FIFO buffer
Stefan Metzmacher <[email protected]>
smb: client: fix smbdirect_recv_io leak in smbd_negotiate() error path
Jiasheng Jiang <[email protected]>
RDMA/rxe: Fix double free in rxe_srq_from_init
Ben Hutchings <[email protected]>
Revert "RDMA/rxe: Fix double free in rxe_srq_from_init"
Sven Eckelmann <[email protected]>
batman-adv: bla: avoid double decrement of bla.num_requests
Sven Eckelmann <[email protected]>
batman-adv: tt: avoid empty VLAN responses
Sven Eckelmann <[email protected]>
batman-adv: tt: fix TOCTOU race for reported vlans
Petr Machata <[email protected]>
selftests: forwarding: lib: Add helpers for checksum handling
Sven Eckelmann <[email protected]>
batman-adv: tp_meter: avoid role confusion in tp_list
Sven Eckelmann <[email protected]>
batman-adv: tp_meter: fix race condition in send error reporting
Sven Eckelmann <[email protected]>
batman-adv: iv: recover OGM scheduling after forward packet error
Sven Eckelmann <[email protected]>
batman-adv: tvlv: reject oversized TVLV packets
Sven Eckelmann <[email protected]>
batman-adv: bla: avoid NULL-ptr deref for claim via dropped interface
Sven Eckelmann <[email protected]>
batman-adv: tvlv: abort OGM send on tvlv append failure
Sven Eckelmann <[email protected]>
batman-adv: v: stop OGMv2 on disabled interface
Zhenghang Xiao <[email protected]>
sctp: fix race between sctp_wait_for_connect and peeloff
Luiz Augusto von Dentz <[email protected]>
Bluetooth: L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
Zhenghang Xiao <[email protected]>
Bluetooth: l2cap: clear chan->ident on ECRED reconfiguration success
Jamal Hadi Salim <[email protected]>
net/sched: Revert "net/sched: Restrict conditions for adding duplicating netems to qdisc tree"
Rahul Chandelkar <[email protected]>
ipv6: rpl: fix hdrlen overflow in ipv6_rpl_srh_decompress()
Zhao Dongdong <[email protected]>
Bluetooth: 6lowpan: check skb_clone() return value in send_mcast_pkt()
Eric Dumazet <[email protected]>
tunnels: do not assume transport header in iptunnel_pmtud_check_icmp()
Eric Dumazet <[email protected]>
vxlan: do not reuse cached ip_hdr() value after skb_tunnel_check_pmtu()
Eric Dumazet <[email protected]>
tunnels: load network headers after skb_cow() in iptunnel_pmtud_build_icmp[v6]()
Cássio Gabriel <[email protected]>
ASoC: Intel: bytcht_es8316: Fix MCLK leak on init errors
Eric Dumazet <[email protected]>
ipv4: free net->ipv4.sysctl_local_reserved_ports after unregister_net_sysctl_table()
Breno Leitao <[email protected]>
net/iucv: fix locking in .getsockopt
Alexandra Winter <[email protected]>
net/smc: Do not re-initialize smc hashtables
Ilya Maximets <[email protected]>
net: netlink: don't set nsid on local notifications
Ilya Maximets <[email protected]>
net: netlink: fix sending unassigned nsid after assigned one
Weiming Shi <[email protected]>
tun: free page on short-frame rejection in tun_xdp_one()
Florian Westphal <[email protected]>
netfilter: ebtables: fix OOB read in compat_mtw_from_user
Florian Westphal <[email protected]>
netfilter: xt_cpu: prefer raw_smp_processor_id
Chris Mason <[email protected]>
netfilter: synproxy: refresh tcphdr after skb_ensure_writable
Carl Lee <[email protected]>
nfc: nxp-nci: i2c: use rising-edge IRQ on ACPI systems
David Ahern <[email protected]>
xfrm: Check for underflow in xfrm_state_mtu
Lee Jones <[email protected]>
nfc: llcp: Fix use-after-free race in nfc_llcp_recv_cc()
Lee Jones <[email protected]>
nfc: llcp: Fix use-after-free in llcp_sock_release()
Krzysztof Kozlowski <[email protected]>
nfc: llcp: protect nfc_llcp_sock_unlink() calls
Victor Nogueria <[email protected]>
net/sched: sch_sfb: Replace direct dequeue call with peek and qdisc_dequeue_peeked
Nobuhiro Iwamatsu <[email protected]>
phy: renesas: rcar-gen3-usb2: Fix the use of msleep during spinlock
Davide Caratti <[email protected]>
net/sched: cls_fw: fix NULL dereference of "old" filters before change()
Chengfeng Ye <[email protected]>
ALSA: usb-audio: fix null pointer dereference on pointer cs_desc
Greg Kroah-Hartman <[email protected]>
Input: usbtouchscreen - clamp NEXIO data_len/x_len to URB buffer size
-------------
Diffstat:
Documentation/arm64/silicon-errata.rst | 48 +++ Makefile | 4 +- arch/arm/mach-socfpga/platsmp.c | 1 + arch/arm64/Kconfig | 50 +++ arch/arm64/include/asm/cputype.h | 10 + arch/arm64/include/asm/kvm_mmu.h | 4 +- arch/arm64/include/asm/tlb.h | 2 +- arch/arm64/include/asm/tlbflush.h | 55 ++- arch/arm64/kernel/cpu_errata.c | 34 +- arch/arm64/kernel/sys_compat.c | 2 +- arch/arm64/kvm/hyp/nvhe/tlb.c | 41 +- arch/arm64/kvm/hyp/vhe/tlb.c | 19 +- arch/arm64/mm/mmu.c | 36 +- arch/x86/kernel/cpu/amd.c | 18 +- arch/x86/kernel/cpu/microcode/intel.c | 2 +- crypto/testmgr.c | 4 +- drivers/acpi/power.c | 2 +- drivers/acpi/scan.c | 2 +- drivers/base/power/domain.c | 10 +- drivers/block/drbd/drbd_main.c | 2 +- drivers/block/drbd/drbd_receiver.c | 2 +- drivers/block/loop.c | 14 +- drivers/block/nbd.c | 10 +- drivers/bluetooth/btusb.c | 8 +- drivers/bluetooth/hci_qca.c | 33 +- drivers/char/random.c | 4 +- drivers/crypto/caam/caamalg_qi2.c | 4 +- drivers/crypto/caam/caamhash.c | 4 +- drivers/fsi/fsi-sbefifo.c | 6 +- .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c | 5 + drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c | 6 +- .../gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c | 3 +- drivers/gpu/drm/i915/gem/i915_gem_phys.c | 19 +- drivers/gpu/drm/imx/dcss/dcss-scaler.c | 3 + drivers/gpu/drm/nouveau/nouveau_gem.c | 2 +- drivers/hid/hid-core.c | 29 +- drivers/hid/hid-gfrm.c | 4 +- drivers/hid/hid-logitech-hidpp.c | 2 +- drivers/hid/hid-multitouch.c | 2 +- drivers/hid/hid-primax.c | 2 +- drivers/hid/hid-vivaldi.c | 2 +- drivers/hid/wacom_sys.c | 19 +- drivers/hid/wacom_wac.h | 1 + drivers/i2c/busses/i2c-qcom-cci.c | 2 +- drivers/i2c/busses/i2c-tegra.c | 53 +-- drivers/i2c/i2c-dev.c | 9 +- drivers/iio/adc/npcm_adc.c | 26 +- drivers/iio/adc/viperboard_adc.c | 4 +- drivers/iio/adc/xilinx-xadc-core.c | 11 +- drivers/iio/buffer/industrialio-hw-consumer.c | 4 +- drivers/iio/chemical/scd30_core.c | 65 ++- drivers/iio/common/ssp_sensors/ssp_dev.c | 1 + drivers/iio/dac/ad5686.c | 8 +- drivers/iio/dac/ad5686.h | 1 + drivers/iio/dac/max5821.c | 9 +- drivers/iio/gyro/adis16260.c | 3 + drivers/iio/gyro/itg3200_buffer.c | 2 +- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 2 +- drivers/iio/light/cm3323.c | 5 +- drivers/iio/temperature/tsys01.c | 2 +- drivers/infiniband/core/Makefile | 2 +- drivers/infiniband/core/iter.c | 43 ++ drivers/infiniband/core/verbs.c | 37 -- drivers/infiniband/hw/bnxt_re/qplib_res.c | 2 +- drivers/infiniband/hw/cxgb4/mem.c | 2 +- drivers/infiniband/hw/efa/efa_verbs.c | 2 +- drivers/infiniband/hw/hns/hns_roce_alloc.c | 2 +- drivers/infiniband/hw/i40iw/i40iw_verbs.c | 1 + drivers/infiniband/hw/mlx4/mr.c | 1 + drivers/infiniband/hw/mlx5/mem.c | 1 + drivers/infiniband/hw/mthca/mthca_provider.c | 2 +- drivers/infiniband/hw/ocrdma/ocrdma_verbs.c | 2 +- drivers/infiniband/hw/qedr/verbs.c | 2 +- drivers/infiniband/hw/vmw_pvrdma/pvrdma.h | 2 +- drivers/infiniband/sw/rxe/rxe_srq.c | 3 - drivers/infiniband/ulp/isert/ib_isert.c | 6 + drivers/infiniband/ulp/rtrs/rtrs-clt.c | 2 +- drivers/infiniband/ulp/srp/ib_srp.c | 30 +- drivers/input/keyboard/atkbd.c | 15 + drivers/input/misc/ims-pcu.c | 2 +- drivers/input/mouse/elan_i2c_core.c | 5 + drivers/input/mouse/synaptics.c | 1 + drivers/input/touchscreen/atmel_mxt_ts.c | 2 +- drivers/input/touchscreen/usbtouchscreen.c | 5 + drivers/iommu/io-pgtable-arm-v7s.c | 18 +- drivers/isdn/mISDN/l1oip_core.c | 2 +- drivers/md/dm-cache-policy-smq.c | 12 +- drivers/md/persistent-data/dm-btree-remove.c | 8 + drivers/md/persistent-data/dm-btree.c | 451 +++++++++++++++++++-- .../md/persistent-data/dm-transaction-manager.c | 9 + .../md/persistent-data/dm-transaction-manager.h | 10 +- drivers/media/rc/igorplugusb.c | 17 +- drivers/media/rc/ttusbir.c | 13 +- drivers/misc/fastrpc.c | 75 ++-- drivers/misc/vmw_vmci/vmci_queue_pair.c | 6 +- drivers/mmc/core/mmc.c | 4 +- drivers/mmc/host/sdhci.c | 1 + drivers/mtd/spi-nor/sst.c | 13 + drivers/net/bonding/bond_main.c | 11 +- drivers/net/can/usb/ucan.c | 6 +- drivers/net/ethernet/amd/pcnet32.c | 4 +- drivers/net/ethernet/intel/ice/ice_virtchnl_pf.c | 2 +- drivers/net/ethernet/marvell/mv643xx_eth.c | 2 +- drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c | 7 +- drivers/net/ethernet/marvell/octeontx2/af/cgx.c | 20 +- drivers/net/ethernet/marvell/octeontx2/af/mbox.h | 1 + .../ethernet/marvell/octeontx2/nic/otx2_common.c | 2 + drivers/net/ethernet/microchip/lan743x_main.c | 32 ++ drivers/net/ethernet/microchip/lan743x_main.h | 1 + drivers/net/ethernet/qlogic/qed/qed_cxt.c | 26 +- drivers/net/hyperv/netvsc.c | 19 +- drivers/net/macsec.c | 3 +- drivers/net/ppp/ppp_generic.c | 2 +- drivers/net/tap.c | 2 + drivers/net/team/team.c | 23 +- drivers/net/tun.c | 5 +- drivers/net/usb/usbnet.c | 2 + drivers/net/vxlan/vxlan_core.c | 4 +- drivers/net/wireguard/send.c | 20 +- .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 4 + drivers/net/wireless/marvell/mwifiex/init.c | 2 +- drivers/nfc/nxp-nci/i2c.c | 21 +- drivers/nvme/host/tcp.c | 4 +- drivers/nvme/target/io-cmd-file.c | 4 +- drivers/nvme/target/tcp.c | 2 +- drivers/parport/share.c | 11 +- drivers/phy/renesas/phy-rcar-gen3-usb2.c | 2 +- drivers/phy/tegra/xusb-tegra186.c | 38 +- drivers/phy/tegra/xusb.h | 1 + drivers/scsi/fcoe/fcoe_ctlr.c | 2 +- drivers/scsi/sg.c | 2 +- drivers/spi/spi-lantiq-ssc.c | 8 +- drivers/spi/spi-meson-spicc.c | 2 - drivers/spi/spi-qup.c | 165 ++++---- drivers/spi/spi-st-ssc4.c | 8 +- drivers/spi/spi-sun4i.c | 10 +- drivers/spi/spi-sun6i.c | 10 +- drivers/spi/spi-synquacer.c | 8 +- drivers/spi/spi-tegra114.c | 8 +- drivers/spi/spi-tegra20-sflash.c | 8 +- drivers/spi/spi-ti-qspi.c | 11 +- drivers/spi/spi-topcliff-pch.c | 7 +- drivers/spi/spi-uniphier.c | 8 +- drivers/spi/spi-zynq-qspi.c | 15 +- drivers/staging/comedi/drivers/comedi_test.c | 5 +- drivers/staging/greybus/hid.c | 2 +- drivers/target/iscsi/iscsi_target.c | 6 +- drivers/target/iscsi/iscsi_target_nego.c | 7 +- drivers/target/iscsi/iscsi_target_parameters.c | 62 ++- drivers/target/iscsi/iscsi_target_parameters.h | 2 +- drivers/target/iscsi/iscsi_target_util.c | 4 +- drivers/target/target_core_file.c | 2 +- drivers/tee/optee/supp.c | 107 +++-- drivers/thermal/thermal_core.c | 7 +- drivers/thunderbolt/property.c | 38 +- drivers/thunderbolt/xdomain.c | 6 +- drivers/tty/serial/altera_jtaguart.c | 18 +- drivers/tty/serial/dz.c | 58 +-- drivers/tty/serial/fsl_lpuart.c | 15 +- drivers/tty/serial/pch_uart.c | 19 +- drivers/tty/serial/qcom_geni_serial.c | 75 ++-- drivers/tty/serial/samsung_tty.c | 103 +++-- drivers/tty/serial/sh-sci.c | 2 +- drivers/tty/serial/zs.c | 40 +- drivers/tty/serial/zs.h | 2 +- drivers/usb/cdns3/gadget.c | 12 +- drivers/usb/chipidea/core.c | 16 +- drivers/usb/class/usbtmc.c | 14 + drivers/usb/core/config.c | 9 +- drivers/usb/core/hcd.c | 4 +- drivers/usb/core/quirks.c | 4 + drivers/usb/dwc2/hcd.c | 4 +- drivers/usb/dwc3/core.c | 12 +- drivers/usb/gadget/function/f_hid.c | 20 +- drivers/usb/gadget/udc/dummy_hcd.c | 4 + drivers/usb/gadget/udc/net2280.c | 4 +- drivers/usb/host/xhci-tegra.c | 76 ++-- drivers/usb/serial/belkin_sa.c | 3 + drivers/usb/serial/cypress_m8.c | 20 +- drivers/usb/serial/digi_acceleport.c | 23 +- drivers/usb/serial/io_ti.c | 11 + drivers/usb/serial/keyspan.c | 4 + drivers/usb/serial/kl5kusb105.c | 4 +- drivers/usb/serial/mct_u232.c | 26 +- drivers/usb/serial/mxuport.c | 8 + drivers/usb/serial/omninet.c | 9 +- drivers/usb/serial/option.c | 12 +- drivers/usb/serial/safe_serial.c | 11 + drivers/usb/storage/unusual_uas.h | 7 + drivers/usb/typec/altmodes/displayport.c | 2 + drivers/usb/typec/tcpm/wcove.c | 13 +- drivers/usb/typec/ucsi/displayport.c | 4 + drivers/usb/typec/ucsi/ucsi.c | 13 +- drivers/usb/typec/ucsi/ucsi_ccg.c | 5 + drivers/usb/usbip/usbip_common.c | 2 +- drivers/usb/usbip/vudc_dev.c | 1 + drivers/usb/usbip/vudc_transfer.c | 3 +- drivers/vhost/net.c | 6 +- drivers/vhost/scsi.c | 10 +- drivers/vhost/vhost.c | 6 +- drivers/vhost/vringh.c | 4 +- drivers/vhost/vsock.c | 4 +- drivers/video/fbdev/core/fbcon_rotate.c | 5 +- drivers/video/fbdev/vt8500lcdfb.c | 2 +- drivers/xen/pvcalls-back.c | 8 +- fs/9p/vfs_addr.c | 4 +- fs/9p/vfs_dir.c | 2 +- fs/9p/xattr.c | 4 +- fs/afs/cmservice.c | 2 +- fs/afs/internal.h | 4 +- fs/afs/rxrpc.c | 12 +- fs/aio.c | 4 +- fs/btrfs/inode.c | 2 + fs/btrfs/ioctl.c | 5 +- fs/ceph/dir.c | 6 +- fs/ceph/file.c | 4 +- fs/cifs/cifsacl.c | 1 + fs/cifs/connect.c | 6 +- fs/cifs/file.c | 4 +- fs/cifs/smb2ops.c | 10 +- fs/cifs/smb2transport.c | 36 +- fs/cifs/smbdirect.c | 4 +- fs/cifs/transport.c | 6 +- fs/erofs/dir.c | 30 +- fs/ext4/extents.c | 15 + fs/f2fs/data.c | 4 +- fs/f2fs/inline.c | 13 +- fs/fcntl.c | 8 +- fs/fuse/dev.c | 9 +- fs/hfsplus/bfind.c | 51 +++ fs/hfsplus/catalog.c | 4 +- fs/hfsplus/dir.c | 2 +- fs/hfsplus/hfsplus_fs.h | 9 + fs/hfsplus/super.c | 6 +- fs/hpfs/alloc.c | 2 +- fs/nfsd/nfsctl.c | 9 +- fs/nfsd/stats.c | 4 +- fs/nfsd/stats.h | 2 +- fs/nfsd/vfs.c | 4 +- fs/ocfs2/cluster/tcp.c | 2 +- fs/orangefs/inode.c | 6 +- fs/read_write.c | 12 +- fs/seq_file.c | 2 +- fs/splice.c | 10 +- fs/udf/super.c | 4 +- include/linux/compat.h | 4 + include/linux/compiler-clang.h | 28 ++ include/linux/compiler_attributes.h | 11 + include/linux/compiler_types.h | 4 + include/linux/hid.h | 15 +- include/linux/parport.h | 1 + include/linux/printk.h | 13 + include/linux/syscalls.h | 4 + include/linux/uio.h | 3 + include/net/act_api.h | 1 + include/net/bluetooth/bluetooth.h | 3 + include/net/bluetooth/hci_core.h | 2 + include/net/bluetooth/l2cap.h | 1 + include/net/ip_vs.h | 3 +- include/net/netfilter/nf_queue.h | 1 + include/net/sock.h | 1 + include/net/xfrm.h | 3 +- include/rdma/ib_umem.h | 23 -- include/rdma/ib_verbs.h | 47 --- include/rdma/iter.h | 80 ++++ io_uring/io_uring.c | 4 +- ipc/shm.c | 10 +- ipc/util.c | 2 +- kernel/pid.c | 8 +- kernel/sched/core.c | 2 +- kernel/sched/rt.c | 2 +- kernel/sched/sched.h | 2 +- kernel/signal.c | 1 + kernel/time/time.c | 2 +- kernel/trace/trace_probe.c | 5 + kernel/trace/trace_probe.h | 4 +- kernel/tracepoint.c | 2 + lib/debugobjects.c | 2 +- lib/mpi/mpicoder.c | 2 +- mm/huge_memory.c | 2 + mm/hugetlb.c | 1 + mm/madvise.c | 2 +- mm/page_io.c | 2 +- mm/process_vm_access.c | 2 +- net/6lowpan/iphc.c | 4 +- net/802/garp.c | 2 +- net/802/mrp.c | 9 + net/9p/client.c | 2 +- net/batman-adv/bat_iv_ogm.c | 82 +++- net/batman-adv/bat_v_ogm.c | 59 +-- net/batman-adv/bridge_loop_avoidance.c | 63 ++- net/batman-adv/distributed-arp-table.c | 3 +- net/batman-adv/gateway_client.c | 3 +- net/batman-adv/main.c | 1 + net/batman-adv/multicast.c | 9 +- net/batman-adv/originator.c | 12 +- net/batman-adv/soft-interface.c | 1 + net/batman-adv/tp_meter.c | 198 ++++++--- net/batman-adv/tp_meter.h | 1 + net/batman-adv/translation-table.c | 44 +- net/batman-adv/tvlv.c | 28 +- net/batman-adv/tvlv.h | 2 +- net/batman-adv/types.h | 56 ++- net/bluetooth/6lowpan.c | 4 +- net/bluetooth/a2mp.c | 2 +- net/bluetooth/af_bluetooth.c | 144 +++++-- net/bluetooth/bnep/sock.c | 10 +- net/bluetooth/hci_core.c | 34 +- net/bluetooth/hci_event.c | 18 +- net/bluetooth/hci_sock.c | 10 +- net/bluetooth/hidp/sock.c | 10 +- net/bluetooth/l2cap_core.c | 87 +++- net/bluetooth/l2cap_sock.c | 86 ++-- net/bluetooth/mgmt.c | 12 +- net/bluetooth/rfcomm/sock.c | 48 ++- net/bluetooth/sco.c | 19 +- net/bluetooth/smp.c | 2 +- net/bridge/br_arp_nd_proxy.c | 8 +- net/bridge/br_fdb.c | 28 +- net/bridge/netfilter/ebt_snat.c | 3 + net/bridge/netfilter/ebtables.c | 30 ++ net/can/raw.c | 8 +- net/core/dev.c | 6 +- net/core/drop_monitor.c | 6 +- net/core/dst.c | 6 +- net/core/filter.c | 17 +- net/core/neighbour.c | 15 +- net/core/page_pool.c | 41 +- net/core/skbuff.c | 10 +- net/ethtool/netlink.c | 6 +- net/hsr/hsr_framereg.c | 6 +- net/ieee802154/6lowpan/tx.c | 5 + net/ieee802154/nl-phy.c | 3 +- net/ieee802154/nl802154.c | 3 +- net/ieee802154/socket.c | 3 +- net/ipv4/ah4.c | 2 +- net/ipv4/esp4.c | 4 +- net/ipv4/fib_semantics.c | 4 +- net/ipv4/ip_options.c | 4 + net/ipv4/ip_tunnel_core.c | 22 +- net/ipv4/netfilter/arp_tables.c | 15 +- net/ipv4/netfilter/ip_tables.c | 15 +- net/ipv4/netfilter/nft_fib_ipv4.c | 2 +- net/ipv4/route.c | 3 +- net/ipv4/sysctl_net_ipv4.c | 2 +- net/ipv4/tcp.c | 2 +- net/ipv6/addrconf.c | 6 +- net/ipv6/ah6.c | 2 +- net/ipv6/datagram.c | 54 ++- net/ipv6/esp6.c | 4 +- net/ipv6/exthdrs.c | 4 +- net/ipv6/ip6_vti.c | 25 +- net/ipv6/ip6mr.c | 3 +- net/ipv6/netfilter/ip6_tables.c | 15 +- net/ipv6/netfilter/nft_fib_ipv6.c | 2 +- net/ipv6/route.c | 3 +- net/ipv6/sit.c | 1 + net/iucv/af_iucv.c | 20 +- net/key/af_key.c | 6 +- net/mac80211/tdls.c | 2 +- net/mptcp/pm_netlink.c | 8 + net/mptcp/protocol.c | 22 +- net/netfilter/ipvs/ip_vs_ctl.c | 13 +- net/netfilter/ipvs/ip_vs_proto_sctp.c | 18 +- net/netfilter/ipvs/ip_vs_proto_tcp.c | 21 +- net/netfilter/ipvs/ip_vs_proto_udp.c | 20 +- net/netfilter/ipvs/ip_vs_sched.c | 14 +- net/netfilter/ipvs/ip_vs_sync.c | 2 +- net/netfilter/nf_conntrack_irc.c | 4 +- net/netfilter/nf_conntrack_proto_tcp.c | 3 +- net/netfilter/nf_queue.c | 28 +- net/netfilter/nf_synproxy_core.c | 26 +- net/netfilter/nfnetlink_queue.c | 2 + net/netfilter/nft_exthdr.c | 3 + net/netfilter/nft_fib.c | 6 + net/netfilter/nft_tunnel.c | 2 +- net/netfilter/xt_NFQUEUE.c | 2 +- net/netfilter/xt_cpu.c | 2 +- net/netlabel/netlabel_unlabeled.c | 36 +- net/netlink/af_netlink.c | 11 +- net/netrom/nr_loopback.c | 3 +- net/netrom/nr_route.c | 3 +- net/nfc/hci/core.c | 10 + net/nfc/llcp_core.c | 11 + net/nfc/llcp_sock.c | 12 +- net/nfc/nci/hci.c | 10 + net/openvswitch/datapath.c | 1 + net/packet/af_packet.c | 40 +- net/phonet/af_phonet.c | 3 +- net/phonet/pn_dev.c | 6 +- net/phonet/socket.c | 3 +- net/qrtr/af_qrtr.c | 4 +- net/qrtr/ns.c | 180 ++++---- net/rds/ib_cm.c | 1 + net/rds/ib_send.c | 2 + net/rds/info.c | 2 +- net/sched/act_api.c | 7 +- net/sched/act_mirred.c | 6 +- net/sched/cls_fw.c | 6 +- net/sched/sch_netem.c | 40 -- net/sched/sch_sfb.c | 2 +- net/sctp/diag.c | 17 +- net/sctp/input.c | 8 + net/sctp/sm_statefuns.c | 6 +- net/sctp/socket.c | 2 + net/sctp/stream.c | 6 +- net/smc/af_smc.c | 4 +- net/smc/smc_clc.c | 6 +- net/smc/smc_pnet.c | 3 +- net/socket.c | 23 +- net/sunrpc/socklib.c | 6 +- net/sunrpc/svcsock.c | 4 +- net/sunrpc/xprtsock.c | 6 +- net/tipc/topsrv.c | 2 +- net/tls/tls_device.c | 4 +- net/vmw_vsock/vmci_transport.c | 4 +- net/wireless/nl80211.c | 16 +- net/wireless/scan.c | 3 +- net/xfrm/espintcp.c | 6 +- net/xfrm/xfrm_input.c | 16 +- net/xfrm/xfrm_policy.c | 15 +- net/xfrm/xfrm_state.c | 23 +- net/xfrm/xfrm_user.c | 5 +- security/apparmor/policy_unpack.c | 27 +- security/keys/keyctl.c | 4 +- sound/aoa/codecs/onyx.c | 104 ++--- sound/aoa/codecs/tas.c | 113 ++---- sound/aoa/core/gpio-feature.c | 20 +- sound/aoa/core/gpio-pmf.c | 26 +- sound/aoa/soundbus/i2sbus/core.c | 3 + sound/aoa/soundbus/i2sbus/pcm.c | 143 +++---- sound/core/misc.c | 14 +- sound/core/pcm_native.c | 7 +- sound/core/timer.c | 1 + sound/drivers/aloop.c | 40 +- sound/pci/hda/patch_hdmi.c | 1 + sound/soc/intel/boards/bytcht_es8316.c | 29 +- sound/soc/qcom/qdsp6/q6asm-dai.c | 43 +- sound/usb/clock.c | 6 + tools/testing/ktest/ktest.pl | 196 +++++---- tools/testing/selftests/net/forwarding/lib.sh | 56 +++ tools/testing/selftests/net/mptcp/mptcp_connect.sh | 6 +- 442 files changed, 4423 insertions(+), 2404 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/342 Input: usbtouchscreen - clamp NEXIO data_len/x_len to URB buffer size
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
commit 2905281cbda52ec9df540113b35b835feb5fafd3 upstream.
nexio_read_data() pulls data_len and x_len from a packed __be16 header in the device's interrupt packet and then walks packet->data[0..x_len) and packet->data[x_len..data_len) comparing each byte against a threshold.
Both fields are 16-bit on the wire (max 65535). The existing adjustments shave at most 0x100 / 0x80 off, so the loop bound can still reach roughly 0xfeff. The URB transfer buffer for NEXIO is rept_size (1024) bytes from usb_alloc_coherent(), with the first 7 occupied by the packed header — so packet->data[] has 1017 valid bytes. read_data() callbacks are not given urb->actual_length, and nothing else bounds the walk.
A device that lies about its length can get a ~64 KiB out-of-bounds read past the coherent DMA allocation. The first index whose byte exceeds NEXIO_THRESHOLD lands in begin_x / begin_y and from there into the reported touch coordinates, so adjacent kernel memory contents leak to userspace as ABS_X / ABS_Y events. Far enough out, the read can also hit an unmapped page and fault.
Fix this all by clamping data_len to the buffer's data[] capacity and x_len to data_len.
--- drivers/input/touchscreen/usbtouchscreen.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/input/touchscreen/usbtouchscreen.c +5 -0
@@ -1060,6 +1060,11 @@ static int nexio_read_data(struct usbtouif (x_len >0xff ) x_len -=0x80 ; +if (data_len > usbtouch->data_size -sizeof (*packet)) + data_len = usbtouch->data_size -sizeof (*packet); +if (x_len > data_len) + x_len = data_len; +/* send ACK */ ret =usb_submit_urb (priv->ack,GFP_ATOMIC );
Greg Kroah-Hartman
maintainerPATCH 2/342 ALSA: usb-audio: fix null pointer dereference on pointer cs_desc
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chengfeng Ye <[email protected]>
commit b97053df0f04747c3c1e021ecbe99db675342954 upstream.
The pointer cs_desc return from snd_usb_find_clock_source could be null, so there is a potential null pointer dereference issue. Fix this by adding a null check before dereference.
[ kovalev: bp to fix CVE-2021-47211; added Fixes tag; the null
check was added into both UAC2 and UAC3 branches since the older kernel still has the clock source lookup split between snd_usb_find_clock_source() and snd_usb_find_clock_source_v3() (see upstream commit 9ec730052fa2); return -ENXIO instead of 0 to match upstream behavior, where the caller reaches the clock validation path and returns -ENXIO ]
--- sound/usb/clock.c | 6 ++++++ 1 file changed, 6 insertions(+)
sound/usb/clock.c +6 -0
@@ -646,11 +646,17 @@ static int set_sample_rate_v2v3(struct snd_usb_audio *chip, int iface,struct uac3_clock_source_descriptor *cs_desc; cs_desc =snd_usb_find_clock_source_v3 (chip->ctrl_intf, clock); + +if (!cs_desc) +return -ENXIO ; bmControls =le32_to_cpu (cs_desc->bmControls); }else {struct uac_clock_source_descriptor *cs_desc; cs_desc =snd_usb_find_clock_source (chip->ctrl_intf, clock); + +if (!cs_desc) +return -ENXIO ; bmControls = cs_desc->bmControls; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 3/342 net/sched: cls_fw: fix NULL dereference of "old" filters before change()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Davide Caratti <[email protected]>
[ Upstream commit 65782b2db7321d5f97c16718c4c7f6c7205a56be ]
Like pointed out by Sashiko [1], since commit ed76f5edccc9 ("net: sched:
protect filter_chain list with filter_chain_lock mutex") TC filters are added to a shared block and published to datapath before their ->change() function is called. This is a problem for cls_fw: an invalid filter created with the "old" method can still classify some packets before it is destroyed by the validation logic added by Xiang. Therefore, insisting with repeated runs of the following script:
# ip link add dev crash0 type dummy # ip link set dev crash0 up # mausezahn crash0 -c 100000 -P 10 \
Quoted 1 line
-A 4.3.2.1 -B 1.2.3.4 -t udp "dp=1234" -q &
# sleep 1 # tc qdisc add dev crash0 egress_block 1 clsact # tc filter add block 1 protocol ip prio 1 matchall \
Quoted 1 line
action skbedit mark 65536 continue
# tc filter add block 1 protocol ip prio 2 fw # ip link del dev crash0
can still make fw_classify() hit the WARN_ON() in [2]:
WARNING: ./include/net/pkt_cls.h:88 at fw_classify+0x244/0x250 [cls_fw], CPU#18: mausezahn/1399 Modules linked in: cls_fw(E) act_skbedit(E) CPU: 18 UID: 0 PID: 1399 Comm: mausezahn Tainted: G E 7.0.0-rc6-virtme #17 PREEMPT(full) Tainted: [E]=UNSIGNED_MODULE Hardware name: Red Hat KVM, BIOS 1.16.3-2.el9 04/01/2014 RIP: 0010:fw_classify+0x244/0x250 [cls_fw] Code: 5c 49 c7 45 00 00 00 00 00 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 5b b8 ff ff ff ff 41 5c 41 5d 41 5e 41 5f 5d c3 cc cc cc cc 90 <0f> 0b 90 eb a0 0f 1f 80 00 00 00 00 90 90 90 90 90 90 90 90 90 90 RSP: 0018:ffffd1b7026bf8a8 EFLAGS: 00010202 RAX: ffff8c5ac9c60800 RBX: ffff8c5ac99322c0 RCX: 0000000000000004 RDX: 0000000000000001 RSI: ffff8c5b74d7a000 RDI: ffff8c5ac8284f40 RBP: ffffd1b7026bf8d0 R08: 0000000000000000 R09: ffffd1b7026bf9b0 R10: 00000000ffffffff R11: 0000000000000000 R12: 0000000000010000 R13: ffffd1b7026bf930 R14: ffff8c5ac8284f40 R15: 0000000000000000 FS: 00007fca40c37740(0000) GS:ffff8c5b74d7a000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fca40e822a0 CR3: 0000000005ca0001 CR4: 0000000000172ef0 Call Trace: <TASK> tcf_classify+0x17d/0x5c0 tc_run+0x9d/0x150 __dev_queue_xmit+0x2ab/0x14d0 ip_finish_output2+0x340/0x8f0 ip_output+0xa4/0x250 raw_sendmsg+0x147d/0x14b0 __sys_sendto+0x1cc/0x1f0 __x64_sys_sendto+0x24/0x30 do_syscall_64+0x126/0xf80 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7fca40e822ba Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb b8 0f 1f 00 f3 0f 1e fa 41 89 ca 64 8b 04 25 18 00 00 00 85 c0 75 15 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 7e c3 0f 1f 44 00 00 41 54 48 83 ec 30 44 89 RSP: 002b:00007ffc248a42c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c RAX: ffffffffffffffda RBX: 000055ef233289d0 RCX: 00007fca40e822ba RDX: 000000000000001e RSI: 000055ef23328c30 RDI: 0000000000000003 RBP: 000055ef233289d0 R08: 00007ffc248a42d0 R09: 0000000000000010 R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000001e R13: 00000000000186a0 R14: 0000000000000000 R15: 00007fca41043000 </TASK> irq event stamp: 1045778 hardirqs last enabled at (1045784): [<ffffffff864ec042>] __up_console_sem+0x52/0x60 hardirqs last disabled at (1045789): [<ffffffff864ec027>] __up_console_sem+0x37/0x60 softirqs last enabled at (1045426): [<ffffffff874d48c7>] __alloc_skb+0x207/0x260 softirqs last disabled at (1045434): [<ffffffff874fe8f8>] __dev_queue_xmit+0x78/0x14d0
Then, because of the value in the packet's mark, dereference on 'q->handle' with NULL 'q' occurs:
BUG: kernel NULL pointer dereference, address: 0000000000000038 [...] RIP: 0010:fw_classify+0x1fe/0x250 [cls_fw] [...]
Skip "old-style" classification on shared blocks, so that the NULL dereference is fixed and WARN_ON() is not hit anymore in the short lifetime of invalid cls_fw "old-style" filters.
[1] https://sashiko.dev/#/patchset/20260331050217.504278-1-xmei5%40asu.edu
[2] https://elixir.bootlin.com/linux/v7.0-rc6/source/include/net/pkt_cls.h#L86
--- net/sched/cls_fw.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/sched/cls_fw.c +5 -1
@@ -72,9 +72,13 @@ static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp, } } }else { -struct Qdisc *q =tcf_block_q (tp->chain->block); +struct Qdisc *q;/* Old method: classify the packet using its skb mark. */ +if (tcf_block_shared (tp->chain->block)) +return -1 ; + + q =tcf_block_q (tp->chain->block);if (id && (TC_H_MAJ (id) ==0 || !(TC_H_MAJ (id ^ q->handle)))) { res->classid = id;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 4/342 phy: renesas: rcar-gen3-usb2: Fix the use of msleep during spinlock
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nobuhiro Iwamatsu <[email protected]>
This fixes an issue caused by the use of msleep during spinlock. In the original commit, msleep was changed to mdelay, but this fix was not carried over during the backport to 5.10.y tree.
This is a backporting error, so no fix is needed in the upstream.
``` [ 62.677594] BUG: scheduling while atomic: kworker/1:2/126/0x00000002 [ 62.683957] Modules linked in: [ 62.687014] CPU: 1 PID: 126 Comm: kworker/1:2 Not tainted 5.10.253 #1 [ 62.693447] Hardware name: HopeRun HiHope RZ/G2M with sub board (DT) [ 62.699812] Workqueue: events deferred_probe_work_func [ 62.704948] Call trace: [ 62.707397] dump_backtrace+0x0/0x1c0 [ 62.711058] show_stack+0x18/0x40 [ 62.714375] dump_stack+0xe8/0x124 [ 62.717776] __schedule_bug+0x54/0x70 [ 62.721436] __schedule+0x6b4/0x710 [ 62.724920] schedule+0x70/0x104 [ 62.728145] schedule_timeout+0x80/0xf0 [ 62.728153] msleep+0x30/0x44 [ 62.728165] rcar_gen3_phy_usb2_init+0x180/0x1e0 [ 62.736946] phy_init+0x64/0x100 [ 62.736955] usb_phy_roothub_init+0x48/0xa0 [ 62.736962] usb_add_hcd+0x54/0x6c0 [ 62.736974] ehci_platform_probe+0x1ec/0x4b0 [ 62.744541] platform_drv_probe+0x54/0xac [ 62.744548] really_probe+0xec/0x4f0 [ 62.744552] driver_probe_device+0x58/0xec [ 62.744556] __device_attach_driver+0xb8/0x120 [ 62.744562] bus_for_each_drv+0x78/0xd0 [ 62.744568] __device_attach+0xa8/0x1c0 [ 62.744575] device_initial_probe+0x14/0x20 [ 62.752315] bus_probe_device+0x9c/0xa4 [ 62.752319] deferred_probe_work_func+0x88/0xc0 [ 62.752327] process_one_work+0x1cc/0x370 [ 62.759977] worker_thread+0x218/0x480 [ 62.759984] kthread+0x154/0x160 [ 62.759990] ret_from_fork+0x10/0x18 [ 62.760115] ehci-platform ee080100.usb: EHCI Host Controller [ 62.839982] ehci-platform ee080100.usb: new USB bus registered, assigned bus number 3 ```
--- drivers/phy/renesas/phy-rcar-gen3-usb2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/phy/renesas/phy-rcar-gen3-usb2.c +1 -1
@@ -386,7 +386,7 @@ static void rcar_gen3_init_otg(struct rcar_gen3_chan *ch) val =readl (usb2_base +USB2_ADPCTRL );writel (val |USB2_ADPCTRL_IDPULLUP , usb2_base +USB2_ADPCTRL ); -msleep (20 ); +mdelay (20 );writel (0xffffffff , usb2_base +USB2_OBINTSTA );writel (USB2_OBINT_BITS , usb2_base +USB2_OBINTEN );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 5/342 net/sched: sch_sfb: Replace direct dequeue call with peek and qdisc_dequeue_peeked
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Victor Nogueria <[email protected]>
[ Upstream commit 1b9bc71153b01dbde8045b9edede4240f4f5520e ]
When sfb has children (eg qfq qdisc) whose peek() callback is qdisc_peek_dequeued(), we could get a kernel panic. When the parent of such qdiscs (eg illustrated in patch #3 as tbf) wants to retrieve an skb from its child (sfb in this case), it will do the following:
1a. do a peek() - and when sensing there's an skb the child can offer, then
- the child in this case(sfb) calls its child's (qfq) peek. qfq does the right thing and will return the gso_skb queue packet.
Note: if there wasnt a gso_skb entry then qfq will store it there.
1b. invoke a dequeue() on the child (sfb). And herein lies the problem.
- sfb will call the child's dequeue() which will essentially just try to grab something of qfq's queue.
[ 127.594489][ T453] KASAN: null-ptr-deref in range [0x0000000000000048-0x000000000000004f] [ 127.594741][ T453] CPU: 2 UID: 0 PID: 453 Comm: ping Not tainted 7.1.0-rc1-00035-gac961974495b-dirty #793 PREEMPT(full) [ 127.595059][ T453] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011 [ 127.595254][ T453] RIP: 0010:qfq_dequeue+0x35c/0x1650 [sch_qfq] [ 127.595461][ T453] Code: 00 fc ff df 80 3c 02 00 0f 85 17 0e 00 00 4c 8d 73 48 48 89 9d b8 02 00 00 48 b8 00 00 00 00 00 fc ff df 4c 89 f2 48 c1 ea 03 <80> 3c 02 00 0f 85 76 0c 00 00 48 b8 00 00 00 00 00 fc ff df 4c 8b [ 127.596081][ T453] RSP: 0018:ffff88810e5af440 EFLAGS: 00010216 [ 127.596337][ T453] RAX: dffffc0000000000 RBX: 0000000000000000 RCX: dffffc0000000000 [ 127.596623][ T453] RDX: 0000000000000009 RSI: 0000001880000000 RDI: ffff888104fd82b0 [ 127.596917][ T453] RBP: ffff888104fd8000 R08: ffff888104fd8280 R09: 1ffff110211893a3 [ 127.597165][ T453] R10: 1ffff110211893a6 R11: 1ffff110211893a7 R12: 0000001880000000 [ 127.597404][ T453] R13: ffff888104fd82b8 R14: 0000000000000048 R15: 0000000040000000 [ 127.597644][ T453] FS: 00007fc380cbfc40(0000) GS:ffff88816f2a8000(0000) knlGS:0000000000000000 [ 127.597956][ T453] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 127.598160][ T453] CR2: 00005610aa9890a8 CR3: 000000010369e000 CR4: 0000000000750ef0 [ 127.598390][ T453] PKRU: 55555554 [ 127.598509][ T453] Call Trace: [ 127.598629][ T453] <TASK> [ 127.598718][ T453] ? mark_held_locks+0x40/0x70 [ 127.598890][ T453] ? srso_alias_return_thunk+0x5/0xfbef5 [ 127.599053][ T453] sfb_dequeue+0x88/0x4d0 [ 127.599174][ T453] ? ktime_get+0x137/0x230 [ 127.599328][ T453] ? srso_alias_return_thunk+0x5/0xfbef5 [ 127.599480][ T453] ? qdisc_peek_dequeued+0x7b/0x350 [sch_qfq] [ 127.599670][ T453] ? srso_alias_return_thunk+0x5/0xfbef5 [ 127.599831][ T453] tbf_dequeue+0x6b1/0x1098 [sch_tbf] [ 127.599988][ T453] __qdisc_run+0x169/0x1900
The right thing to do in #1b is to grab the skb off gso_skb queue. This patchset fixes that issue by changing #1b to use qdisc_dequeue_peeked() method instead.
--- net/sched/sch_sfb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/sch_sfb.c +1 -1
@@ -439,7 +439,7 @@ static struct sk_buff *sfb_dequeue(struct Qdisc *sch)struct Qdisc *child = q->qdisc;struct sk_buff *skb; - skb = child->dequeue (q->qdisc); + skb =qdisc_dequeue_peeked (child);if (skb) {qdisc_bstats_update (sch, skb);
Signature · 1 line
2.53.0
# Librecast Test Results
020/020 [ OK ] liblcrq
010/010 [ OK ] libmld
120/120 [ OK ] liblibrecast
CPU/kernel: Linux auntie 5.10.259-rc1-00934-gb93100fe2cc0 #1 SMP Tue Jun 16 15:41:40 -00 2026 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux
Greg Kroah-Hartman
maintainerPATCH 6/342 nfc: llcp: protect nfc_llcp_sock_unlink() calls
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
[ Upstream commit a06b8044169f6d5c3eb34772c13d2c0c1b205352 ]
nfc_llcp_sock_link() is called in all paths (bind/connect) as a last action, still protected with lock_sock(). When cleaning up in llcp_sock_release(), call nfc_llcp_sock_unlink() in a mirrored way:
earlier and still under the lock_sock().
Stable-dep-of: f4268b466190 ("nfc: llcp: Fix use-after-free in llcp_sock_release()")
--- net/nfc/llcp_sock.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
net/nfc/llcp_sock.c +5 -5
@@ -626,6 +626,11 @@ static int llcp_sock_release(struct socket *sock) } } +if (sock->type ==SOCK_RAW ) +nfc_llcp_sock_unlink (&local->raw_sockets, sk); +else +nfc_llcp_sock_unlink (&local->sockets, sk); +if (llcp_sock->reserved_ssap <LLCP_SAP_MAX )nfc_llcp_put_ssap (llcp_sock->local, llcp_sock->ssap);
@@ -638,11 +643,6 @@ static int llcp_sock_release(struct socket *sock)if (sk->sk_state ==LLCP_DISCONNECTING )return err; -if (sock->type ==SOCK_RAW ) -nfc_llcp_sock_unlink (&local->raw_sockets, sk); -else -nfc_llcp_sock_unlink (&local->sockets, sk); - out:sock_orphan (sk);sock_put (sk);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 7/342 nfc: llcp: Fix use-after-free in llcp_sock_release()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lee Jones <[email protected]>
[ Upstream commit f4268b466190dae95a7585f69b4f1f8ad097632c ]
llcp_sock_release() unconditionally unlinks the socket from the local sockets list. However, if the socket is still in connecting state, it is on the connecting list.
Fix this by checking the socket state and unlinking from the correct list.
--- net/nfc/llcp_sock.c | 2 ++ 1 file changed, 2 insertions(+)
net/nfc/llcp_sock.c +2 -0
@@ -628,6 +628,8 @@ static int llcp_sock_release(struct socket *sock)if (sock->type ==SOCK_RAW )nfc_llcp_sock_unlink (&local->raw_sockets, sk); +else if (sk->sk_state ==LLCP_CONNECTING ) +nfc_llcp_sock_unlink (&local->connecting_sockets, sk);else nfc_llcp_sock_unlink (&local->sockets, sk);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 8/342 nfc: llcp: Fix use-after-free race in nfc_llcp_recv_cc()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lee Jones <[email protected]>
[ Upstream commit b493ea2765cc17cb8aa7e7544a4b6dcb05b6ed77 ]
A race condition exists in the NFC LLCP connection state machine where the connection acceptance packet (CC) can be processed concurrently with socket release. This can lead to a use-after-free of the socket object.
When nfc_llcp_recv_cc() moves the socket from the connecting_sockets list to the sockets list, it does so without holding the socket lock. If llcp_sock_release() is executing concurrently, it might have already unlinked the socket and dropped its references, which can result in nfc_llcp_recv_cc() linking a freed socket into the live list.
Fix this by holding lock_sock() during the state transition and list movement in nfc_llcp_recv_cc(). After acquiring the lock, check if the socket is still hashed to ensure it hasn't already been unlinked and marked for destruction by the release path. This aligns the locking pattern with recv_hdlc() and recv_disc().
--- net/nfc/llcp_core.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
net/nfc/llcp_core.c +11 -0
@@ -1225,6 +1225,15 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, sk = &llcp_sock->sk; +lock_sock (sk); + +/* Check if socket was destroyed whilst waiting for the lock */ +if (!sk_hashed (sk)) { +release_sock (sk); +nfc_llcp_sock_put (llcp_sock); +return ; + } +/* Unlink from connecting and link to the client array */ nfc_llcp_sock_unlink (&local->connecting_sockets, sk);nfc_llcp_sock_link (&local->sockets, sk);
@@ -1236,6 +1245,8 @@ static void nfc_llcp_recv_cc(struct nfc_llcp_local *local, sk->sk_state =LLCP_CONNECTED ; sk->sk_state_change (sk); +release_sock (sk); +nfc_llcp_sock_put (llcp_sock); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 9/342 xfrm: Check for underflow in xfrm_state_mtu
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Ahern <[email protected]>
[ Upstream commit 742b04d0550b0ec89dcbc99537ec88653bd1ad90 ]
Leo Lin reported OOB write issue in esp component:
xfrm_state_mtu() returns u32 but performs its arithmetic in unsigned modulo-2^32 space using an attacker-influenced "header_len + authsize + net_adj" subtracted from a small "mtu" argument. A nobody user can install an IPv4 ESP tunnel SA with a large authentication key (XFRMA_ALG_AUTH_TRUNC, e.g. hmac(sha512), 64-byte key, 64-byte trunc), configure a small interface MTU (68 bytes), and set XFRMA_TFCPAD to a large value. When a single UDP datagram is then sent through the tunnel, xfrm_state_mtu() underflows to a near-2^32 value, and esp_output() consumes it as a signed int via:
padto = min(x->tfcpad, xfrm_state_mtu(x, mtu_cached))
esp.tfclen = padto - skb->len (assigned to int) esp.tfclen ends up negative (e.g. -207). It is sign-extended to size_t when passed to memset() inside esp_output_fill_trailer(), producing a ~16 EB write of zeroes at skb_tail_pointer(skb). KASAN logs it as "Write of size 18446744073709551537 at addr ffff888...".
Check for underflow and return 1. This causes the sendmsg attempt to fail with ENETUNREACH.
--- net/xfrm/xfrm_state.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
net/xfrm/xfrm_state.c +16 -3
@@ -2549,10 +2549,14 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)const struct xfrm_type *type =READ_ONCE (x->type);struct crypto_aead *aead;u32 blksize, net_adj =0 ; +u32 overhead, payload_mtu;if (x->km.state !=XFRM_STATE_VALID || - !type || type->proto !=IPPROTO_ESP ) + !type || type->proto !=IPPROTO_ESP ) { +if (mtu <= x->props.header_len) +return 1 ;return mtu - x->props.header_len; + } aead = x->data; blksize =ALIGN (crypto_aead_blocksize (aead),4 );
@@ -2572,8 +2576,17 @@ u32 xfrm_state_mtu(struct xfrm_state *x, int mtu)break ; } -return ((mtu - x->props.header_len -crypto_aead_authsize (aead) - - net_adj) & ~(blksize -1 )) + net_adj -2 ; + overhead = x->props.header_len +crypto_aead_authsize (aead) + net_adj; +if (mtu <= overhead) +return 1 ; + + payload_mtu = mtu - overhead; + payload_mtu &= ~(blksize -1 ); +if (payload_mtu <=2 ) +return 1 ; + +return payload_mtu + net_adj -2 ; + }EXPORT_SYMBOL_GPL (xfrm_state_mtu);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 10/342 nfc: nxp-nci: i2c: use rising-edge IRQ on ACPI systems
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Carl Lee <[email protected]>
[ Upstream commit f23bf992d65a42007c517b060ca35cebdea3525a ]
Some ACPI-based platforms report incorrect IRQ trigger types (e.g. IRQF_TRIGGER_HIGH), which can lead to interrupt storms.
Use the historically working rising-edge trigger on ACPI systems to avoid this regression.
Device Tree-based systems continue to use the firmware-provided trigger type.
--- drivers/nfc/nxp-nci/i2c.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-)
drivers/nfc/nxp-nci/i2c.c +20 -1
@@ -16,6 +16,7 @@#include <linux/delay.h> #include <linux/i2c.h> #include <linux/interrupt.h> +#include <linux/irq.h> #include <linux/module.h> #include <linux/nfc.h> #include <linux/gpio/consumer.h>
@@ -268,6 +269,7 @@ static int nxp_nci_i2c_probe(struct i2c_client *client, {struct device *dev = &client->dev;struct nxp_nci_i2c_phy *phy; +unsigned long irqflags;int r;if (!i2c_check_functionality (client->adapter,I2C_FUNC_I2C )) {
@@ -304,9 +306,26 @@ static int nxp_nci_i2c_probe(struct i2c_client *client,if (r <0 )return r; +/* +* ACPI platforms may report incorrect IRQ trigger types +* (e.g. level-high), which can lead to interrupt storms. +* +* Use the historically stable rising-edge trigger for ACPI devices. +* +* On non-ACPI systems (e.g. Device Tree), prefer the firmware- +* provided trigger type, falling back to rising-edge if not set. +*/ +if (ACPI_COMPANION (dev)) { + irqflags =IRQF_TRIGGER_RISING ; + }else { + irqflags =irq_get_trigger_type (client->irq); +if (!irqflags) + irqflags =IRQF_TRIGGER_RISING ; + } + r =request_threaded_irq (client->irq,NULL , nxp_nci_i2c_irq_thread_fn, -IRQF_ONESHOT , + irqflags |IRQF_ONESHOT ,NXP_NCI_I2C_DRIVER_NAME , phy);if (r <0 )nfc_err (&client->dev,"Unable to register IRQ handler\n" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 11/342 netfilter: synproxy: refresh tcphdr after skb_ensure_writable
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Mason <[email protected]>
[ Upstream commit 92170e6afe927ab2792a3f71902845789c8e31b1 ]
synproxy_tstamp_adjust() rewrites the TCP timestamp option in place and then patches the TCP checksum via inet_proto_csum_replace4() on the caller-supplied tcphdr pointer. Both ipv4_synproxy_hook() and ipv6_synproxy_hook() obtain that pointer with skb_header_pointer() before calling in, so it may either alias skb->head directly or point at the caller's on-stack _tcph buffer.
Between obtaining the pointer and using it, the function calls skb_ensure_writable(skb, optend), which on a cloned or non-linear skb invokes pskb_expand_head() and frees the old skb->head. After that point the cached th is stale:
caller (ipv[46]_synproxy_hook)
th = skb_header_pointer(skb, ..., &_tcph)
synproxy_tstamp_adjust(skb, protoff, th, ...)
skb_ensure_writable(skb, optend)
pskb_expand_head() /* kfree(old skb->head) */
...
inet_proto_csum_replace4(&th->check, ...)
/* writes into freed head, or
into the caller's stack copy
leaving the on-wire checksum
stale */The option bytes are written through skb->data and are fine; only the checksum update goes through th and so lands in the wrong place. The result is either a write into freed slab memory or a packet leaving with a checksum that does not match its payload.
Fix by re-deriving th from skb->data + protoff immediately after skb_ensure_writable() succeeds, so the subsequent checksum update targets the linear, writable header.
--- net/netfilter/nf_synproxy_core.c | 2 ++ 1 file changed, 2 insertions(+)
net/netfilter/nf_synproxy_core.c +2 -0
@@ -199,6 +199,8 @@ synproxy_tstamp_adjust(struct sk_buff *skb, unsigned int protoff,if (skb_ensure_writable (skb, optend))return 0 ; + th = (struct tcphdr *)(skb->data + protoff); +while (optoff < optend) {unsigned char *op = skb->data + optoff;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 12/342 netfilter: xt_cpu: prefer raw_smp_processor_id
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit c376f07e16c02239ed44cabb97145d03f65b4d15 ]
With PREEMPT_RCU we get splat:
BUG: using smp_processor_id() in preemptible [..] caller is cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37 CPU: 1 .. Comm: syz.3.1377 #0 PREEMPT(full) Call Trace: <TASK> dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120 check_preemption_disabled+0xd3/0xe0 lib/smp_processor_id.c:47 cpu_mt+0x53/0xd0 net/netfilter/xt_cpu.c:37 [..]
Just use raw version instead.
This is similar to 14d14a5d2957 ("netfilter: nft_meta: use raw_smp_processor_id()").
--- net/netfilter/xt_cpu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/xt_cpu.c +1 -1
@@ -34,7 +34,7 @@ static bool cpu_mt(const struct sk_buff *skb, struct xt_action_param *par) {const struct xt_cpu_info *info = par->matchinfo; -return (info->cpu ==smp_processor_id ()) ^ info->invert; +return (info->cpu ==raw_smp_processor_id ()) ^ info->invert; }static struct xt_match cpu_mt_reg__read_mostly = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 13/342 netfilter: ebtables: fix OOB read in compat_mtw_from_user
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit f438d1786d657d57790c5d138d6db3fc9fdac392 ]
Luxiao Xu says:
The function compat_mtw_from_user() converts ebtables extensions from 32-bit user structures to kernel native structures. However, it lacks proper validation of the user-supplied match_size/target_size.
When certain extensions are processed, the kernel-side translation logic may perform memory accesses based on the extension's expected size. If the user provides a size smaller than what the extension requires, it results in an out-of-bounds read as reported by KASAN.
This fix introduces a check to ensure match_size is at least as large as the extension's required compatsize. This covers matches, watchers, and targets, while maintaining compatibility with standard targets.
AFAIU this is relevant for matches that need to go though match->compat_from_user() call. Those that use plain memcpy with the user-provided size are ok because the caller checks that size vs the start of the next rule entry offset (which itself is checked vs. total size copied from userspace).
The ->compat_from_user() callbacks assume they can read compatsize bytes, so they need this extra check.
Based on an earlier patch from Luxiao Xu.
--- net/bridge/netfilter/ebtables.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+)
net/bridge/netfilter/ebtables.c +30 -0
@@ -1838,6 +1838,25 @@ enum compat_mwt { EBT_COMPAT_TARGET, }; +static bool match_size_ok (const struct xt_match *match,unsigned int match_size) +{ +u16 csize; + +if (match->matchsize ==-1 )/* cannot validate ebt_among */ +return true; + + csize = match->compatsize ? : match->matchsize; + +return match_size >= csize; +} + +static bool tgt_size_ok (const struct xt_target *tgt,unsigned int tgt_size) +{ +u16 csize = tgt->compatsize ? : tgt->targetsize; + +return tgt_size >= csize; +} + static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt, enum compat_mwt compat_mwt, struct ebt_entries_buf_state *state,
@@ -1863,6 +1882,11 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt,if (IS_ERR (match))return PTR_ERR (match); +if (!match_size_ok (match, match_size)) { +module_put (match->me); +return -EINVAL ; + } + off =ebt_compat_match_offset (match, match_size);if (dst) {if (match->compat_from_user)
@@ -1882,6 +1906,12 @@ static int compat_mtw_from_user(const struct compat_ebt_entry_mwt *mwt, mwt->u.revision);if (IS_ERR (wt))return PTR_ERR (wt); + +if (!tgt_size_ok (wt, match_size)) { +module_put (wt->me); +return -EINVAL ; + } + off =xt_compat_target_offset (wt);if (dst) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 14/342 tun: free page on short-frame rejection in tun_xdp_one()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
[ Upstream commit f4feb1e20058e407cb00f45aff47f5b7e19a6bbf ]
tun_xdp_one() returns -EINVAL on a frame shorter than ETH_HLEN without freeing the page that vhost_net_build_xdp() allocated for it. tun_sendmsg() discards that -EINVAL and still returns total_len, so vhost_tx_batch() takes the success path and never frees the page; each short frame in a batch leaks one page-frag chunk.
A local process that can open /dev/net/tun and /dev/vhost-net can hit this path: it attaches a tun/tap device as the vhost-net backend and feeds TX descriptors whose length minus the virtio-net header is below ETH_HLEN. Each kick leaks the page-frag chunks for that batch, and a tight submission loop exhausts host memory and triggers an OOM panic. Free the page before returning -EINVAL, matching the XDP-program error path in the same function.
--- drivers/net/tun.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/tun.c +3 -1
@@ -2472,8 +2472,10 @@ static int tun_xdp_one(struct tun_struct *tun,bool skb_xdp = false;struct page *page; -if (unlikely (datasize <ETH_HLEN )) +if (unlikely (datasize <ETH_HLEN )) { +put_page (virt_to_head_page (xdp->data));return -EINVAL ; + } xdp_prog =rcu_dereference (tun->xdp_prog);if (xdp_prog) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 15/342 net: netlink: fix sending unassigned nsid after assigned one
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ilya Maximets <[email protected]>
[ Upstream commit 70f8592ee90585272018a725054b6eb2ab7e99ca ]
If the current skb is not shared, it is re-used directly for all the sockets subscribed to the notification. If we have remote all-nsid socket receiving a message first, then the 'nsid_is_set' will be set to 'true'. If the nsid is NOT_ASSIGNED for the next socket in the list, the 'nsid_is_set' will remain 'true' and the negative value is be delivered to the user space. All subsequent nsid values will be delivered as well, since there is no code path that sets the flag back to 'false'.
Fix that by always dropping the flag to 'false' first.
--- net/netlink/af_netlink.c | 1 + 1 file changed, 1 insertion(+)
net/netlink/af_netlink.c +1 -0
@@ -1478,6 +1478,7 @@ static void do_one_broadcast(struct sock *sk, p->skb2 =NULL ; goto out; } +NETLINK_CB (p->skb2).nsid_is_set = false;NETLINK_CB (p->skb2).nsid =peernet2id (sock_net (sk), p->net);if (NETLINK_CB (p->skb2).nsid !=NETNSA_NSID_NOT_ASSIGNED )NETLINK_CB (p->skb2).nsid_is_set = true;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 16/342 net: netlink: dont set nsid on local notifications
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ilya Maximets <[email protected]>
[ Upstream commit 88b126b39f9757e9debc322d4679239e9af089c7 ]
In most cases, notifications on sockets with NETLINK_LISTEN_ALL_NSID do not contain NSID in their ancillary data in case the event is local to the listener.
However, when a self-referential NSID is allocated for a namespace, every local notification starts sending this ID to the user space.
This is problematic, because the listener cannot tell if those notifications are local or not anymore without making extra requests to figure out if the provided NSID is local or not. The listener can also not figure out the local NSID beforehand as it can be allocated at any point in time by other processes, changing the structure of the future notifications for everyone.
The value is practically not useful, since it's the namespace's own ID that the application has to obtain from other sources in order to figure out if it's the same or not. So, for the application it's just an extra busy work with no benefits. Moreover, applications that do not know about this quirk may be mishandling notifications with NSID set as notifications from remote namespaces. This is the case for ovs-vswitchd and the iproute2's 'ip monitor' that stops printing 'current' and starts printing the nsid number mid-session.
Lack of clear documentation for this behavior is also not helping.
A search though open-source projects doesn't reveal any projects that use NETNSA_NSID_NOT_ASSIGNED and rely on metadata to contain self-referential NSIDs (expected, since the value is not useful). Quite the opposite, as already mentioned, there are few applications that rely on NSID to not be present in local events.
Since the value is not useful and actively harmful in some cases, let's not report it for local events, making the notifications more consistent.
Also adding some blank lines for readability.
--- net/netlink/af_netlink.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
net/netlink/af_netlink.c +7 -3
@@ -1478,10 +1478,14 @@ static void do_one_broadcast(struct sock *sk, p->skb2 =NULL ; goto out; } +NETLINK_CB (p->skb2).nsid_is_set = false; -NETLINK_CB (p->skb2).nsid =peernet2id (sock_net (sk), p->net); -if (NETLINK_CB (p->skb2).nsid !=NETNSA_NSID_NOT_ASSIGNED ) -NETLINK_CB (p->skb2).nsid_is_set = true; +if (!net_eq (sock_net (sk), p->net)) { +NETLINK_CB (p->skb2).nsid =peernet2id (sock_net (sk), p->net); +if (NETLINK_CB (p->skb2).nsid !=NETNSA_NSID_NOT_ASSIGNED ) +NETLINK_CB (p->skb2).nsid_is_set = true; + } + val =netlink_broadcast_deliver (sk, p->skb2);if (val <0 ) {netlink_overrun (sk);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 17/342 net/smc: Do not re-initialize smc hashtables
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexandra Winter <[email protected]>
[ Upstream commit 9e4389b0038781f19f97895186ed941ff8ac1678 ]
INIT_HLIST_HEAD(&smc_v*_hashinfo.ht) are called after smc_nl_init(), proto_register() and sock_register(). This can lead to smc_v*_hashinfo.ht being reset even though hash entries already exist and are being used, possibly resulting in a corrupted list.
Remove unnecessary and dangerous re-initialisation of smc_v*_hashinfo.ht in smc_init(); it is implicitly initialised to zero anyhow. Add HLIST_HEAD_INIT to the definitions for clarity.
--- net/smc/af_smc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/smc/af_smc.c +2 -2
@@ -71,10 +71,12 @@ static void smc_set_keepalive(struct sock *sk, int val)static struct smc_hashinfo smc_v4_hashinfo = { .lock =__RW_LOCK_UNLOCKED (smc_v4_hashinfo.lock), + .ht =HLIST_HEAD_INIT , };static struct smc_hashinfo smc_v6_hashinfo = { .lock =__RW_LOCK_UNLOCKED (smc_v6_hashinfo.lock), + .ht =HLIST_HEAD_INIT , };int smc_hash_sk (struct sock *sk)
@@ -2586,8 +2588,6 @@ static int __init smc_init(void)pr_err ("%s: sock_register fails with %d\n" , __func__, rc); goto out_proto6; } -INIT_HLIST_HEAD (&smc_v4_hashinfo.ht); -INIT_HLIST_HEAD (&smc_v6_hashinfo.ht); rc =smc_ib_register_client ();if (rc) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 18/342 net/iucv: fix locking in .getsockopt
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
[ Upstream commit 3589d20a666caf30ad100c960a2de7de390fce88 ]
Mirror iucv_sock_setsockopt() and wrap the whole switch in lock_sock()/release_sock(). The pre-existing SO_MSGLIMIT-only lock becomes redundant and is removed.
Any AF_IUCV HIPER user can potentially crash the kernel by racing recvmsg() with getsockopt(SO_MSGSIZE): the SO_MSGSIZE arm dereferences iucv->hs_dev->mtu after iucv_sock_close() (called from the racing recvmsg()) has set hs_dev to NULL, producing a NULL pointer dereference oops.
--- net/iucv/af_iucv.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-)
net/iucv/af_iucv.c +14 -6
@@ -1550,7 +1550,7 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname,struct sock *sk = sock->sk;struct iucv_sock *iucv =iucv_sk (sk);unsigned int val; -int len; +int len, rc;if (level !=SOL_IUCV )return -ENOPROTOOPT ;
@@ -1563,26 +1563,34 @@ static int iucv_sock_getsockopt(struct socket *sock, int level, int optname, len = min_t(unsigned int, len, sizeof(int)); + rc =0 ; + +lock_sock (sk);switch (optname) {case SO_IPRMDATA_MSG : val = (iucv->flags &IUCV_IPRMDATA ) ?1 :0 ;break ;case SO_MSGLIMIT : -lock_sock (sk); val = (iucv->path !=NULL ) ? iucv->path->msglim/* connected */ : iucv->msglimit;/* default */ -release_sock (sk);break ;case SO_MSGSIZE : -if (sk->sk_state ==IUCV_OPEN ) -return -EBADFD ; +if (sk->sk_state ==IUCV_OPEN ) { + rc = -EBADFD ; +break ; + } val = (iucv->hs_dev) ? iucv->hs_dev->mtu -sizeof (struct af_iucv_trans_hdr ) -ETH_HLEN :0x7fffffff ;break ;default : -return -ENOPROTOOPT ; + rc = -ENOPROTOOPT ; +break ; } +release_sock (sk); + +if (rc) +return rc;if (put_user (len, optlen))return -EFAULT ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 19/342 ipv4: free net->ipv4.sysctl_local_reserved_ports after unregister_net_sysctl_table()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 87a1e0fe7776da7ab411be332b4be58ac8840d10 ]
ipv4_sysctl_exit_net() is currently freeing net->ipv4.sysctl_local_reserved_ports too soon.
Only after unregister_net_sysctl_table() we can be sure no threads can possibly use the sysctls, including /proc/sys/net/ipv4/ip_local_reserved_ports.
--- net/ipv4/sysctl_net_ipv4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/sysctl_net_ipv4.c +1 -1
@@ -1362,10 +1362,10 @@ static __net_exit void ipv4_sysctl_exit_net(struct net *net) {struct ctl_table *table; -kfree (net->ipv4.sysctl_local_reserved_ports); table = net->ipv4.ipv4_hdr->ctl_table_arg;unregister_net_sysctl_table (net->ipv4.ipv4_hdr);kfree (table); +kfree (net->ipv4.sysctl_local_reserved_ports); }static __net_initdata struct pernet_operations ipv4_sysctl_ops = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 20/342 ASoC: Intel: bytcht_es8316: Fix MCLK leak on init errors
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cássio Gabriel <[email protected]>
[ Upstream commit afb2a3a9d8369d18122a0d7cd294eba9a98259c6 ]
byt_cht_es8316_init() enables MCLK before configuring the codec sysclk and creating the headset jack. If either of those later steps fails, the function returns without disabling MCLK, leaving the clock enabled after card registration fails.
Track whether this driver enabled MCLK and disable it on the init error paths. Add the matching DAI link exit callback so the same clock enable is also balanced when ASoC cleans up a successfully initialized link.
--- sound/soc/intel/boards/bytcht_es8316.c | 29 ++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-)
sound/soc/intel/boards/bytcht_es8316.c +27 -2
@@ -39,6 +39,7 @@ struct byt_cht_es8316_private {struct gpio_desc *speaker_en_gpio;struct device *codec_dev;bool speaker_en; +bool mclk_enabled; };enum {
@@ -169,6 +170,15 @@ static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = { }, }; +static void byt_cht_es8316_disable_mclk (struct byt_cht_es8316_private *priv) +{ +if (!priv->mclk_enabled) +return ; + +clk_disable_unprepare (priv->mclk); + priv->mclk_enabled = false; +} +static int byt_cht_es8316_init (struct snd_soc_pcm_runtime *runtime) {struct snd_soc_component *codec =asoc_rtd_to_codec (runtime,0 )->component;
@@ -225,12 +235,14 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime) ret =clk_prepare_enable (priv->mclk);if (ret)dev_err (card->dev,"unable to enable MCLK\n" ); +else + priv->mclk_enabled = true; ret =snd_soc_dai_set_sysclk (asoc_rtd_to_codec (runtime,0 ),0 ,19200000 ,SND_SOC_CLOCK_IN );if (ret <0 ) {dev_err (card->dev,"can't set codec clock %d\n" , ret); -return ret; + goto err_disable_mclk; } ret = snd_soc_card_jack_new(card, "Headset",
@@ -239,13 +251,25 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime) ARRAY_SIZE(byt_cht_es8316_jack_pins));if (ret) {dev_err (card->dev,"jack creation failed %d\n" , ret); -return ret; + goto err_disable_mclk; }snd_jack_set_key (priv->jack.jack,SND_JACK_BTN_0 ,KEY_PLAYPAUSE );snd_soc_component_set_jack (codec, &priv->jack,NULL );return 0 ; + +err_disable_mclk: +byt_cht_es8316_disable_mclk (priv); +return ret; +} + +static void byt_cht_es8316_exit (struct snd_soc_pcm_runtime *runtime) +{ +struct snd_soc_card *card = runtime->card; +struct byt_cht_es8316_private *priv =snd_soc_card_get_drvdata (card); + +byt_cht_es8316_disable_mclk (priv); } static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
@@ -359,6 +383,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = { .dpcm_playback = 1, .dpcm_capture = 1, .init = byt_cht_es8316_init, + .exit = byt_cht_es8316_exit, SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform), }, };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 21/342 tunnels: load network headers after skb_cow() in iptunnel_pmtud_build_icmp[v6]()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit b4bc94353050b1fa7b702bd4c6600710dd926cff ]
Sashiko found that iptunnel_pmtud_build_icmp() and iptunnel_pmtud_build_icmpv6() were caching ip_hdr() and ipv6_hdr() before an skb_cow() call which can reallocate skb->head.
Fix this possible UAF by initializing the local variables after the skb_cow() call.
Remove skb_reset_network_header() calls which were not needed.
--- net/ipv4/ip_tunnel_core.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
net/ipv4/ip_tunnel_core.c +4 -5
@@ -194,7 +194,7 @@ EXPORT_SYMBOL_GPL(iptunnel_handle_offloads);*/ static int iptunnel_pmtud_build_icmp (struct sk_buff *skb,int mtu) { -const struct iphdr *iph =ip_hdr (skb); +const struct iphdr *iph;struct icmphdr *icmph;struct iphdr *niph;struct ethhdr eh;
@@ -208,7 +208,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)skb_copy_bits (skb,skb_mac_offset (skb), &eh,ETH_HLEN );pskb_pull (skb,ETH_HLEN ); -skb_reset_network_header (skb); err =pskb_trim (skb,576 -sizeof (*niph) -sizeof (*icmph));if (err)
@@ -218,7 +217,7 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu) err =skb_cow (skb,sizeof (*niph) +sizeof (*icmph) +ETH_HLEN );if (err)return err; - + iph =ip_hdr (skb); icmph =skb_push (skb,sizeof (*icmph)); *icmph = (struct icmphdr ) { .type =ICMP_DEST_UNREACH ,
@@ -290,7 +289,7 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu)*/ static int iptunnel_pmtud_build_icmpv6 (struct sk_buff *skb,int mtu) { -const struct ipv6hdr *ip6h =ipv6_hdr (skb); +const struct ipv6hdr *ip6h;struct icmp6hdr *icmp6h;struct ipv6hdr *nip6h;struct ethhdr eh;
@@ -305,7 +304,6 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)skb_copy_bits (skb,skb_mac_offset (skb), &eh,ETH_HLEN );pskb_pull (skb,ETH_HLEN ); -skb_reset_network_header (skb); err =pskb_trim (skb,IPV6_MIN_MTU -sizeof (*nip6h) -sizeof (*icmp6h));if (err)
@@ -316,6 +314,7 @@ static int iptunnel_pmtud_build_icmpv6(struct sk_buff *skb, int mtu)if (err)return err; + ip6h =ipv6_hdr (skb); icmp6h =skb_push (skb,sizeof (*icmp6h)); *icmp6h = (struct icmp6hdr ) { .icmp6_type =ICMPV6_PKT_TOOBIG ,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 22/342 vxlan: do not reuse cached ip_hdr() value after skb_tunnel_check_pmtu()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 7d9ef0cb271555d8cf39fefe6c981e1493b25ecf ]
skb_tunnel_check_pmtu() can change skb->head.
Reusing old_iph afer skb_tunnel_check_pmtu() can cause an UAF.
Use instead ip_hdr(skb) as done in drivers/net/bareudp.c and drivers/net/geneve.c.
Found by Sashiko.
--- drivers/net/vxlan/vxlan_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/vxlan/vxlan_core.c +2 -2
@@ -2752,7 +2752,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, goto out_unlock; } - tos =ip_tunnel_ecn_encap (tos, old_iph, skb); + tos =ip_tunnel_ecn_encap (tos,ip_hdr (skb), skb); ttl = ttl ? :ip4_dst_hoplimit (&rt->dst); err =vxlan_build_skb (skb, ndst,sizeof (struct iphdr ), vni, md, flags, udp_sum);
@@ -2815,7 +2815,7 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, goto out_unlock; } - tos =ip_tunnel_ecn_encap (tos, old_iph, skb); + tos =ip_tunnel_ecn_encap (tos,ip_hdr (skb), skb); ttl = ttl ? :ip6_dst_hoplimit (ndst);skb_scrub_packet (skb, xnet); err = vxlan_build_skb(skb, ndst, sizeof(struct ipv6hdr),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 23/342 tunnels: do not assume transport header in iptunnel_pmtud_check_icmp()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 509323077ef79a26ba0c60bb556e45c12c398b2d ]
In some cases, iptunnel_pmtud_check_icmp() can be called while skb transport header is not set.
This triggers an out-of-bound access, because
(typeof(skb->transport_header))~0U is 65535.
Access the icmp header based on IPv4 network header, after making sure icmp->type is present in skb linear part.
Note that iptunnel_pmtud_check_icmpv6()) is fine.
--- net/ipv4/ip_tunnel_core.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
net/ipv4/ip_tunnel_core.c +10 -3
@@ -262,7 +262,6 @@ static int iptunnel_pmtud_build_icmp(struct sk_buff *skb, int mtu)*/ static int iptunnel_pmtud_check_icmp (struct sk_buff *skb,int mtu) { -const struct icmphdr *icmph =icmp_hdr (skb);const struct iphdr *iph =ip_hdr (skb);if (mtu <576 || iph->frag_off !=htons (IP_DF ))
@@ -273,9 +272,17 @@ static int iptunnel_pmtud_check_icmp(struct sk_buff *skb, int mtu) ipv4_is_lbcast(iph->saddr) || ipv4_is_multicast(iph->saddr))return 0 ; -if (iph->protocol ==IPPROTO_ICMP &&icmp_is_err (icmph->type)) -return 0 ; +if (iph->protocol ==IPPROTO_ICMP ) { +const struct icmphdr *icmph; +if (!pskb_network_may_pull (skb, iph->ihl *4 + + offsetofend(struct icmphdr, type))) +return 0 ; + iph =ip_hdr (skb); + icmph = (void *)iph + iph->ihl *4 ; +if (icmp_is_err (icmph->type)) +return 0 ; + }return iptunnel_pmtud_build_icmp (skb, mtu); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 24/342 Bluetooth: 6lowpan: check skb_clone() return value in send_mcast_pkt()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhao Dongdong <[email protected]>
[ Upstream commit 3c40d381ce04f9575a5d8b542898183c3b4b38dc ]
The skb_clone() function can return NULL if memory allocation fails. send_mcast_pkt() calls skb_clone() without checking the return value, which can lead to a NULL pointer dereference in send_pkt() when it dereferences skb->data.
Add a NULL check after skb_clone() and skip the peer if the clone fails.
--- net/bluetooth/6lowpan.c | 2 ++ 1 file changed, 2 insertions(+)
net/bluetooth/6lowpan.c +2 -0
@@ -514,6 +514,8 @@ static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)int ret; local_skb =skb_clone (skb,GFP_ATOMIC ); +if (!local_skb) +continue ; BT_DBG("xmit %s to %pMR type %d IP %pI6c chan %p", netdev->name,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 25/342 ipv6: rpl: fix hdrlen overflow in ipv6_rpl_srh_decompress()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rahul Chandelkar <[email protected]>
[ Upstream commit 9d5e7a46a9f6d8f503b41bfefef70659845f1679 ]
ipv6_rpl_srh_decompress() computes:
outhdr->hdrlen = (((n + 1) * sizeof(struct in6_addr)) >> 3);
hdrlen is __u8. For n >= 127 the result exceeds 255 and silently truncates. With n=127 (cmpri=15, cmpre=15, pad=0, hdrlen=16):
(128 * 16) >> 3 = 256, truncated to 0 as __u8
The caller in ipv6_rpl_srh_rcv() then places the compressed header at buf + ((ohdr->hdrlen + 1) << 3). With hdrlen=0 this is buf + 8, but the decompressed region occupies buf[0..2055] (8-byte header plus 128 full addresses). The compressed header overlaps the decompressed data, and ipv6_rpl_srh_compress() writes into this overlap, corrupting the routing header of the forwarded packet.
The existing guard at exthdrs.c:546 checks (n + 1) > 255, which prevents n+1 from overflowing unsigned char (the segments_left field), but does not prevent the computed hdrlen from overflowing __u8. n=127 passes because 128 <= 255, yet hdrlen=256 does not fit.
Tighten the bound to (n + 1) > 127. This caps n at 126, giving hdrlen = (127 * 16) >> 3 = 254, which fits in __u8. The compressed header then lands at buf + ((254 + 1) << 3) = buf + 2040, exactly past the decompressed region (buf[0..2039]). No overlap. 127 segments is well beyond any realistic RPL deployment.
--- net/ipv6/exthdrs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/exthdrs.c +1 -1
@@ -544,7 +544,7 @@ static int ipv6_rpl_srh_rcv(struct sk_buff *skb)* unsigned char which is segments_left field. Should not be * higher than that. */ -if (r || (n +1 ) >255 ) { +if (r || (n +1 ) >127 ) {kfree_skb (skb);return -1 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 26/342 net/sched: Revert "net/sched: Restrict conditions for adding duplicating netems to qdisc tree"
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit eda0b7f203bb166c98d1418b204135bd566ac83b ]
This reverts commit ec8e0e3d7adef940cdf9475e2352c0680189d14e.
The original patch rejects any tree containing two netems when either has duplication set, even when they sit on unrelated classes of the same classful parent. That broke configurations that have worked since netem was introduced.
The re-entrancy problem the original commit was trying to solve is handled by later patch using tc_depth flag.
Doing this revert will (re)expose the original bug with multiple netem duplication. When this patch is backported make sure and get the full series.
--- net/sched/sch_netem.c | 40 ---------------------------------------- 1 file changed, 40 deletions(-)
net/sched/sch_netem.c +0 -40
@@ -985,41 +985,6 @@ static int parse_attr(struct nlattr *tb[], int maxtype, struct nlattr *nla,return 0 ; } -static const struct Qdisc_class_ops netem_class_ops; - -static int check_netem_in_tree (struct Qdisc *sch,bool duplicates, -struct netlink_ext_ack *extack) -{ -struct Qdisc *root, *q; -unsigned int i; - - root =qdisc_root_sleeping (sch); - -if (sch != root && root->ops->cl_ops == &netem_class_ops) { -if (duplicates || - ((struct netem_sched_data *)qdisc_priv (root))->duplicate) - goto err; - } - -if (!qdisc_dev (root)) -return 0 ; - -hash_for_each (qdisc_dev (root)->qdisc_hash, i, q, hash) { -if (sch != q && q->ops->cl_ops == &netem_class_ops) { -if (duplicates || - ((struct netem_sched_data *)qdisc_priv (q))->duplicate) - goto err; - } - } - -return 0 ; - -err: -NL_SET_ERR_MSG (extack, -"netem: cannot mix duplicating netems with other netems in tree" ); -return -EINVAL ; -} -/* Parse netlink message to set options */ static int netem_change (struct Qdisc *sch,struct nlattr *opt,struct netlink_ext_ack *extack)
@@ -1087,11 +1052,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt, q->gap = qopt->gap; q->counter =0 ; q->loss = qopt->loss; - - ret =check_netem_in_tree (sch, qopt->duplicate, extack); -if (ret) - goto unlock; - q->duplicate = qopt->duplicate;/* for compatibility with earlier versions.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 27/342 Bluetooth: l2cap: clear chan->ident on ECRED reconfiguration success
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhenghang Xiao <[email protected]>
[ Upstream commit 00e1950716c6ed67d74777b2db286b0fa23b4be9 ]
l2cap_ecred_reconf_rsp() returns early on success without clearing chan->ident. Every other L2CAP response handler (l2cap_ecred_conn_rsp, l2cap_le_connect_rsp, l2cap_config_rsp) clears chan->ident after a successful transaction to prevent the channel from matching subsequent responses with the recycled ident value.
A remote attacker that completed a reconfiguration as the peer can replay a failure response with the stale ident, causing the kernel to match and destroy the already-established channel via l2cap_chan_del(chan, ECONNRESET).
Clear chan->ident for all matching channels on success, and harden the failure path by using l2cap_chan_hold_unless_zero() consistent with other L2CAP handlers (l2cap_le_command_rej, __l2cap_get_chan_by_ident).
--- net/bluetooth/l2cap_core.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
net/bluetooth/l2cap_core.c +8 -2
@@ -6432,14 +6432,20 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn,BT_DBG ("result 0x%4.4x" , result); -if (!result) +if (!result) { +list_for_each_entry (chan, &conn->chan_l, list) { +if (chan->ident == cmd->ident) + chan->ident =0 ; + }return 0 ; + }list_for_each_entry_safe (chan, tmp, &conn->chan_l, list) {if (chan->ident != cmd->ident)continue ; -l2cap_chan_hold (chan); +if (!l2cap_chan_hold_unless_zero (chan)) +continue ;l2cap_chan_lock (chan);l2cap_chan_del (chan,ECONNRESET );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 28/342 Bluetooth: L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 41c2713b204e6cb6a94587bc6bf6935107df5479 ]
If dcid is received for an already-assigned destination CID the spec requires that both channels to be discarded, but calling l2cap_chan_del may invalidate the tmp cursor created by list_for_each_entry_safe and in fact it is the wrong procedure as the chan->dcid may be assigned previously it really needs to be disconnected.
Calling l2cap_chan_clone directly may still lead to l2cap_chan_del so instead schedule l2cap_chan_timeout with delay 0 to close the channel asynchronously.
--- net/bluetooth/l2cap_core.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-)
net/bluetooth/l2cap_core.c +22 -5
@@ -6232,6 +6232,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn, cmd_len -=sizeof (*rsp);list_for_each_entry_safe (chan, tmp, &conn->chan_l, list) { +struct l2cap_chan *orig;u16 dcid; if (chan->ident != cmd->ident ||
@@ -6253,8 +6254,10 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,BT_DBG ("dcid[%d] 0x%4.4x" , i, dcid); + orig =__l2cap_get_chan_by_dcid (conn, dcid); +/* Check if dcid is already in use */ -if (dcid &&__l2cap_get_chan_by_dcid (conn, dcid)) { +if (dcid && orig) {/* If a device receives a * L2CAP_CREDIT_BASED_CONNECTION_RSP packet with an * already-assigned Destination CID, then both the
@@ -6263,10 +6266,24 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn,*/ l2cap_chan_del (chan,ECONNREFUSED );l2cap_chan_unlock (chan); - chan =__l2cap_get_chan_by_dcid (conn, dcid); -l2cap_chan_lock (chan); -l2cap_chan_del (chan,ECONNRESET ); -l2cap_chan_unlock (chan); + +/* Check that the dcid channel mode is +* L2CAP_MODE_EXT_FLOWCTL since this procedure is only +* valid for that mode and shouldn't disconnect a dcid +* in other modes. +*/ +if (orig->mode ==L2CAP_MODE_EXT_FLOWCTL ) { +l2cap_chan_lock (orig); +/* Disconnect the original channel as it may be +* considered connected since dcid has already +* been assigned; don't call l2cap_chan_close +* directly since that could lead to +* l2cap_chan_del and then removing the channel +* from the list while we're iterating over it. +*/ +__set_chan_timer (orig,0 ); +l2cap_chan_unlock (orig); + }continue ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 29/342 sctp: fix race between sctp_wait_for_connect and peeloff
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhenghang Xiao <[email protected]>
[ Upstream commit f14fe6395a8b3d961a61e138ad7b36ba3626dd4e ]
sctp_wait_for_connect() drops and re-acquires the socket lock while waiting for the association to reach ESTABLISHED state. During this window, another thread can peeloff the association to a new socket via getsockopt(SCTP_SOCKOPT_PEELOFF), changing asoc->base.sk. After re-acquiring the old socket lock, sctp_wait_for_connect() returns success without noticing the migration — the caller then accesses the association under the wrong lock in sctp_datamsg_from_user().
Add the same sk != asoc->base.sk check that sctp_wait_for_sndbuf() already has, returning an error if the association was migrated while we slept.
--- net/sctp/socket.c | 2 ++ 1 file changed, 2 insertions(+)
net/sctp/socket.c +2 -0
@@ -9133,6 +9133,8 @@ static int sctp_wait_for_connect(struct sctp_association *asoc, long *timeo_p)release_sock (sk); current_timeo =schedule_timeout (current_timeo);lock_sock (sk); +if (sk != asoc->base.sk) + goto do_error; *timeo_p = current_timeo; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 30/342 batman-adv: v: stop OGMv2 on disabled interface
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit f8ce8b8331a1bc44ad4905886a482214d428b253 upstream.
When a batadv_hard_iface is disabled, its mesh_iface pointer is set to NULL. However, batadv_v_ogm_send_meshif() may still dispatch OGMs via batadv_v_ogm_queue_on_if() for interfaces that have since lost their mesh_iface association. This results in a NULL pointer dereference when batadv_v_ogm_queue_on_if() unconditionally calls netdev_priv() on the now NULL hard_iface->mesh_iface to retrieve the batadv_priv.
It is necessary to ensure that the batadv_v_ogm_queue_on_if() checks that it is using the same mesh_iface for which batadv_v_ogm_send_meshif() was called.
--- net/batman-adv/bat_v_ogm.c | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-)
net/batman-adv/bat_v_ogm.c +21 -12
@@ -116,14 +116,14 @@ static void batadv_v_ogm_start_timer(struct batadv_priv *bat_priv)/** * batadv_v_ogm_send_to_if() - send a batman ogm using a given interface +* @bat_priv: the bat priv with all the mesh interface information * @skb: the OGM to send * @hard_iface: the interface to use to send the OGM */ -static void batadv_v_ogm_send_to_if (struct sk_buff *skb, +static void batadv_v_ogm_send_to_if (struct batadv_priv *bat_priv, +struct sk_buff *skb,struct batadv_hard_iface *hard_iface) { -struct batadv_priv *bat_priv =netdev_priv (hard_iface->soft_iface); -if (hard_iface->if_status !=BATADV_IF_ACTIVE ) {kfree_skb (skb);return ;
@@ -190,6 +190,7 @@ static void batadv_v_ogm_aggr_list_free(struct batadv_hard_iface *hard_iface)/** * batadv_v_ogm_aggr_send() - flush & send aggregation queue +* @bat_priv: the bat priv with all the mesh interface information * @hard_iface: the interface with the aggregation queue to flush * * Aggregates all OGMv2 packets currently in the aggregation queue into a
@@ -199,7 +200,8 @@ static void batadv_v_ogm_aggr_list_free(struct batadv_hard_iface *hard_iface)* * Caller needs to hold the hard_iface->bat_v.aggr_list.lock. */ -static void batadv_v_ogm_aggr_send (struct batadv_hard_iface *hard_iface) +static void batadv_v_ogm_aggr_send (struct batadv_priv *bat_priv, +struct batadv_hard_iface *hard_iface) {unsigned int aggr_len = hard_iface->bat_v.aggr_len;struct sk_buff *skb_aggr;
@@ -229,27 +231,32 @@ static void batadv_v_ogm_aggr_send(struct batadv_hard_iface *hard_iface)consume_skb (skb); } -batadv_v_ogm_send_to_if (skb_aggr, hard_iface); +batadv_v_ogm_send_to_if (bat_priv, skb_aggr, hard_iface); }/** * batadv_v_ogm_queue_on_if() - queue a batman ogm on a given interface +* @bat_priv: the bat priv with all the mesh interface information * @skb: the OGM to queue * @hard_iface: the interface to queue the OGM on */ -static void batadv_v_ogm_queue_on_if (struct sk_buff *skb, +static void batadv_v_ogm_queue_on_if (struct batadv_priv *bat_priv, +struct sk_buff *skb,struct batadv_hard_iface *hard_iface) { -struct batadv_priv *bat_priv =netdev_priv (hard_iface->soft_iface); +if (hard_iface->soft_iface != bat_priv->soft_iface) { +kfree_skb (skb); +return ; + }if (!atomic_read (&bat_priv->aggregated_ogms)) { -batadv_v_ogm_send_to_if (skb, hard_iface); +batadv_v_ogm_send_to_if (bat_priv, skb, hard_iface);return ; }spin_lock_bh (&hard_iface->bat_v.aggr_list.lock);if (!batadv_v_ogm_queue_left (skb, hard_iface)) -batadv_v_ogm_aggr_send (hard_iface); +batadv_v_ogm_aggr_send (bat_priv, hard_iface); hard_iface->bat_v.aggr_len +=batadv_v_ogm_len (skb);__skb_queue_tail (&hard_iface->bat_v.aggr_list, skb);
@@ -348,7 +355,7 @@ static void batadv_v_ogm_send_softif(struct batadv_priv *bat_priv)break ; } -batadv_v_ogm_queue_on_if (skb_tmp, hard_iface); +batadv_v_ogm_queue_on_if (bat_priv, skb_tmp, hard_iface);batadv_hardif_put (hard_iface); }rcu_read_unlock ();
@@ -388,12 +395,14 @@ void batadv_v_ogm_aggr_work(struct work_struct *work) {struct batadv_hard_iface_bat_v *batv;struct batadv_hard_iface *hard_iface; +struct batadv_priv *bat_priv; batv = container_of(work, struct batadv_hard_iface_bat_v, aggr_wq.work); hard_iface = container_of(batv, struct batadv_hard_iface, bat_v); + bat_priv =netdev_priv (hard_iface->soft_iface);spin_lock_bh (&hard_iface->bat_v.aggr_list.lock); -batadv_v_ogm_aggr_send (hard_iface); +batadv_v_ogm_aggr_send (bat_priv, hard_iface);spin_unlock_bh (&hard_iface->bat_v.aggr_list.lock);batadv_v_ogm_start_queue_timer (hard_iface);
@@ -583,7 +592,7 @@ static void batadv_v_ogm_forward(struct batadv_priv *bat_priv, if_outgoing->net_dev->name,ntohl (ogm_forward->throughput), ogm_forward->ttl, if_incoming->net_dev->name); -batadv_v_ogm_queue_on_if (skb, if_outgoing); +batadv_v_ogm_queue_on_if (bat_priv, skb, if_outgoing); out:if (orig_ifinfo)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 31/342 batman-adv: tvlv: abort OGM send on tvlv append failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 501368506563e151b322c8c3f228b796e615b90d upstream.
batadv_tvlv_container_ogm_append() could fail in two ways: a memory allocation failure when resizing the packet buffer, or the tvlv data exceeding U16_MAX bytes. In both cases the function previously returned the old (now stale) tvlv_value_len rather than signalling an error, causing the OGM/OGM2 send path to transmit a packet whose TVLV length field no longer matched the actual buffer contents. And because it also didn't fill in the new TVLV data, sending either uninitialized or corrupted data on the wire.
All errors in batadv_tvlv_container_ogm_append() must be forwarded to the caller. And the caller must abort the send of the OGM2. For B.A.T.M.A.N. IV, it is currently not allowed to abort the send. The non-TVLV part of the OGM must be queued up instead.
--- net/batman-adv/bat_iv_ogm.c | 16 +++++++++++++--- net/batman-adv/bat_v_ogm.c | 26 ++++++++++++++------------ net/batman-adv/tvlv.c | 17 ++++++++++++----- net/batman-adv/tvlv.h | 2 +- 4 files changed, 40 insertions(+), 21 deletions(-)
net/batman-adv/bat_iv_ogm.c +13 -3
@@ -784,6 +784,7 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)u32 seqno;u16 tvlv_len =0 ;unsigned long send_time; +int ret;lockdep_assert_held (&hard_iface->bat_iv.ogm_buff_mutex);
@@ -807,9 +808,18 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)* appended as it may alter the tt tvlv container */ batadv_tt_local_commit_changes (bat_priv); - tvlv_len =batadv_tvlv_container_ogm_append (bat_priv, ogm_buff, - ogm_buff_len, -BATADV_OGM_HLEN ); + ret =batadv_tvlv_container_ogm_append (bat_priv, ogm_buff, + ogm_buff_len, +BATADV_OGM_HLEN ); +if (ret <0 ) { +/* OGMs must be queued even when the buffer allocation for +* TVLVs failed. just fall back to the non-TVLV version +*/ + ret =0 ; + *ogm_buff_len =BATADV_OGM_HLEN ; + } + + tvlv_len = ret; } batadv_ogm_packet = (struct batadv_ogm_packet *)(*ogm_buff);
net/batman-adv/bat_v_ogm.c +14 -12
@@ -272,9 +272,9 @@ static void batadv_v_ogm_send_softif(struct batadv_priv *bat_priv)struct batadv_hard_iface *hard_iface;struct batadv_ogm2_packet *ogm_packet;struct sk_buff *skb, *skb_tmp; -unsigned char *ogm_buff; -int ogm_buff_len; -u16 tvlv_len =0 ; +unsigned char **ogm_buff; +int *ogm_buff_len; +u16 tvlv_len;int ret;lockdep_assert_held (&bat_priv->bat_v.ogm_buff_mutex);
@@ -282,25 +282,27 @@ static void batadv_v_ogm_send_softif(struct batadv_priv *bat_priv)if (atomic_read (&bat_priv->mesh_state) ==BATADV_MESH_DEACTIVATING ) goto out; - ogm_buff = bat_priv->bat_v.ogm_buff; - ogm_buff_len = bat_priv->bat_v.ogm_buff_len; + ogm_buff = &bat_priv->bat_v.ogm_buff; + ogm_buff_len = &bat_priv->bat_v.ogm_buff_len; +/* tt changes have to be committed before the tvlv data is * appended as it may alter the tt tvlv container */ batadv_tt_local_commit_changes (bat_priv); - tvlv_len =batadv_tvlv_container_ogm_append (bat_priv, &ogm_buff, - &ogm_buff_len, -BATADV_OGM2_HLEN ); + ret =batadv_tvlv_container_ogm_append (bat_priv, ogm_buff, + ogm_buff_len, +BATADV_OGM2_HLEN ); +if (ret <0 ) + goto reschedule; - bat_priv->bat_v.ogm_buff = ogm_buff; - bat_priv->bat_v.ogm_buff_len = ogm_buff_len; + tvlv_len = ret; - skb =netdev_alloc_skb_ip_align (NULL ,ETH_HLEN + ogm_buff_len); + skb =netdev_alloc_skb_ip_align (NULL ,ETH_HLEN + *ogm_buff_len);if (!skb) goto reschedule;skb_reserve (skb,ETH_HLEN ); -skb_put_data (skb, ogm_buff, ogm_buff_len); +skb_put_data (skb, *ogm_buff, *ogm_buff_len); ogm_packet = (struct batadv_ogm2_packet *)skb->data; ogm_packet->seqno =htonl (atomic_read (&bat_priv->bat_v.ogm_seqno));
net/batman-adv/tvlv.c +12 -5
@@ -7,6 +7,7 @@#include "main.h" #include <linux/byteorder/generic.h> +#include <linux/errno.h> #include <linux/etherdevice.h> #include <linux/gfp.h> #include <linux/if_ether.h>
@@ -306,9 +307,10 @@ static bool batadv_tvlv_realloc_packet_buff(unsigned char **packet_buff,* The ogm packet might be enlarged or shrunk depending on the current size * and the size of the to-be-appended tvlv containers. * -* Return: size of all appended tvlv containers in bytes. +* Return: size of all appended tvlv containers in bytes (max U16_MAX), negative +* if operation failed */ -u16 batadv_tvlv_container_ogm_append (struct batadv_priv *bat_priv, +int batadv_tvlv_container_ogm_append (struct batadv_priv *bat_priv,unsigned char **packet_buff,int *packet_buff_len,int packet_min_len) {
@@ -316,6 +318,7 @@ u16 batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv,struct batadv_tvlv_hdr *tvlv_hdr;u16 tvlv_value_len;void *tvlv_value; +int tvlv_len_ret;bool ret;spin_lock_bh (&bat_priv->tvlv.container_list_lock);
@@ -323,9 +326,12 @@ u16 batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv, ret =batadv_tvlv_realloc_packet_buff (packet_buff, packet_buff_len, packet_min_len, tvlv_value_len); - -if (!ret) +if (!ret) { + tvlv_len_ret = -ENOMEM ; goto end; + } + + tvlv_len_ret = tvlv_value_len;if (!tvlv_value_len) goto end;
@@ -344,7 +350,8 @@ u16 batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv, end:spin_unlock_bh (&bat_priv->tvlv.container_list_lock); -return tvlv_value_len; + +return tvlv_len_ret; }/**
net/batman-adv/tvlv.h +1 -1
@@ -15,7 +15,7 @@void batadv_tvlv_container_register (struct batadv_priv *bat_priv,u8 type,u8 version,void *tvlv_value,u16 tvlv_value_len); -u16 batadv_tvlv_container_ogm_append (struct batadv_priv *bat_priv, +int batadv_tvlv_container_ogm_append (struct batadv_priv *bat_priv,unsigned char **packet_buff,int *packet_buff_len,int packet_min_len); void batadv_tvlv_ogm_receive(struct batadv_priv *bat_priv,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 32/342 batman-adv: bla: avoid NULL-ptr deref for claim via dropped interface
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit f80d3d98d2ff78d9e2fe5d68b1f45948c4f7bd24 upstream.
Without rtnl_lock held, a hardif might be retrieved as primary interface of a meshif, but then (while operating on this interface) getting decoupled from the mesh interface. In this case, the meshif still exists but the pointer from the primary hardif to the meshif is set to NULL.
The mesh_iface must be checked first to be non-NULL before continuing to send an ARP request using meshif.
--- net/batman-adv/bridge_loop_avoidance.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/batman-adv/bridge_loop_avoidance.c +4 -2
@@ -357,12 +357,14 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, u8 *mac, sizeof(local_claim_dest)); local_claim_dest.type = claimtype; - soft_iface = primary_if->soft_iface; + soft_iface =READ_ONCE (primary_if->soft_iface); +if (!soft_iface) + goto out; skb = arp_create(ARPOP_REPLY, ETH_P_ARP, /* IP DST: 0.0.0.0 */ zeroip, - primary_if->soft_iface, + soft_iface, /* IP SRC: 0.0.0.0 */ zeroip,/* Ethernet DST: Broadcast */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 33/342 batman-adv: tvlv: reject oversized TVLV packets
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit f50487e3566358b2b982b7801945e858c78ad9ab upstream.
batadv_tvlv_container_ogm_append() builds a TVLV packet section from the tvlv.container_list. The total size of this section is computed by batadv_tvlv_container_list_size(), which sums the sizes of all registered containers.
The return type and accumulator in batadv_tvlv_container_list_size() were u16. If the accumulated size exceeds U16_MAX, the value wraps around, causing the subsequent allocation in batadv_tvlv_container_ogm_append() to be undersized. The memcpy-style copy that follows would then write beyond the end of the allocated buffer, corrupting kernel memory.
Fix this by widening the return type of batadv_tvlv_container_list_size() to size_t. In batadv_tvlv_container_ogm_append(), check the computed length against U16_MAX before proceeding, and bail out as if the allocation had failed when the limit is exceeded.
--- net/batman-adv/tvlv.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
net/batman-adv/tvlv.c +8 -3
@@ -13,6 +13,7 @@#include <linux/if_ether.h> #include <linux/kernel.h> #include <linux/kref.h> +#include <linux/limits.h> #include <linux/list.h> #include <linux/lockdep.h> #include <linux/netdevice.h>
@@ -160,10 +161,10 @@ batadv_tvlv_container_get(struct batadv_priv *bat_priv, u8 type, u8 version)* * Return: size of all currently registered tvlv containers in bytes. */ -static u16 batadv_tvlv_container_list_size (struct batadv_priv *bat_priv) +static size_t batadv_tvlv_container_list_size (struct batadv_priv *bat_priv) {struct batadv_tvlv_container *tvlv; -u16 tvlv_len =0 ; +size_t tvlv_len =0 ;lockdep_assert_held (&bat_priv->tvlv.container_list_lock);
@@ -316,13 +317,17 @@ int batadv_tvlv_container_ogm_append(struct batadv_priv *bat_priv, {struct batadv_tvlv_container *tvlv;struct batadv_tvlv_hdr *tvlv_hdr; -u16 tvlv_value_len; +size_t tvlv_value_len;void *tvlv_value;int tvlv_len_ret;bool ret;spin_lock_bh (&bat_priv->tvlv.container_list_lock); tvlv_value_len =batadv_tvlv_container_list_size (bat_priv); +if (tvlv_value_len >U16_MAX ) { + tvlv_len_ret = -E2BIG ; + goto end; + } ret =batadv_tvlv_realloc_packet_buff (packet_buff, packet_buff_len, packet_min_len, tvlv_value_len);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 34/342 batman-adv: iv: recover OGM scheduling after forward packet error
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit aa3153bd139a6c48667dcd02608d3b2c80bff02c upstream.
When batadv_iv_ogm_schedule_buff() fails to allocate and queue a forward packet for OGM transmission, the work item that drives periodic OGM scheduling is never re-armed. This silently halts transmission of the node's own OGMs on the affected interface — only OGMs from other peers continue to be aggregated and forwarded.
Fix this by tracking whether batadv_iv_ogm_queue_add() (and transitively batadv_iv_ogm_aggregate_new()) successfully scheduled a forward packet. When scheduling fails, batadv_iv_ogm_schedule_buff() falls back to queuing a dedicated recovery work item (reschedule_work) that fires after one originator interval and calls batadv_iv_ogm_schedule() again.
--- net/batman-adv/bat_iv_ogm.c | 76 +++++++++++++++++++++++++++---------- net/batman-adv/types.h | 3 ++ 2 files changed, 60 insertions(+), 19 deletions(-)
net/batman-adv/bat_iv_ogm.c +57 -19
@@ -225,6 +225,8 @@ static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface) hard_iface->bat_iv.ogm_buff =NULL ;mutex_unlock (&hard_iface->bat_iv.ogm_buff_mutex); + +cancel_delayed_work_sync (&hard_iface->bat_iv.reschedule_work); }static void batadv_iv_ogm_iface_update_mac (struct batadv_hard_iface *hard_iface)
@@ -530,8 +532,10 @@ batadv_iv_ogm_can_aggregate(const struct batadv_ogm_packet *new_bat_ogm_packet,* @if_incoming: interface where the packet was received * @if_outgoing: interface for which the retransmission should be considered * @own_packet: true if it is a self-generated ogm +* +* Return: whether forward packet was scheduled */ -static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, +static bool batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, int packet_len, unsigned long send_time, bool direct_link, struct batadv_hard_iface *if_incoming,
@@ -555,13 +559,13 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, skb =netdev_alloc_skb_ip_align (NULL , skb_size);if (!skb) -return ; +return false; forw_packet_aggr =batadv_forw_packet_alloc (if_incoming, if_outgoing, queue_left, bat_priv, skb);if (!forw_packet_aggr) {kfree_skb (skb); -return ; +return false; } forw_packet_aggr->skb->priority =TC_PRIO_CONTROL ;
@@ -583,6 +587,8 @@ static void batadv_iv_ogm_aggregate_new(const unsigned char *packet_buff, batadv_iv_send_outstanding_bat_ogm_packet);batadv_forw_packet_ogmv1_queue (bat_priv, forw_packet_aggr, send_time); + +return true; }/* aggregate a new packet into the existing ogm packet */
@@ -612,8 +618,10 @@ static void batadv_iv_ogm_aggregate(struct batadv_forw_packet *forw_packet_aggr,* @if_outgoing: interface for which the retransmission should be considered * @own_packet: true if it is a self-generated ogm * @send_time: timestamp (jiffies) when the packet is to be sent +* +* Return: whether forward packet was scheduled */ -static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv, +static bool batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv, unsigned char *packet_buff, int packet_len, struct batadv_hard_iface *if_incoming,
@@ -665,14 +673,16 @@ static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv,if (!own_packet &&atomic_read (&bat_priv->aggregated_ogms)) send_time += max_aggregation_jiffies; -batadv_iv_ogm_aggregate_new (packet_buff, packet_len, - send_time, direct_link, - if_incoming, if_outgoing, - own_packet); +return batadv_iv_ogm_aggregate_new (packet_buff, packet_len, + send_time, direct_link, + if_incoming, if_outgoing, + own_packet); }else {batadv_iv_ogm_aggregate (forw_packet_aggr, packet_buff, packet_len, direct_link);spin_unlock_bh (&bat_priv->forw_bat_list_lock); + +return true; } }
@@ -784,6 +794,8 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)u32 seqno;u16 tvlv_len =0 ;unsigned long send_time; +bool reschedule = false; +bool scheduled;int ret;lockdep_assert_held (&hard_iface->bat_iv.ogm_buff_mutex);
@@ -812,11 +824,8 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface) ogm_buff_len, BATADV_OGM_HLEN);if (ret <0 ) { -/* OGMs must be queued even when the buffer allocation for -* TVLVs failed. just fall back to the non-TVLV version -*/ - ret =0 ; - *ogm_buff_len =BATADV_OGM_HLEN ; + reschedule = true; + goto out; } tvlv_len = ret;
@@ -838,8 +847,11 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)/* OGMs from secondary interfaces are only scheduled on their * respective interfaces. */ -batadv_iv_ogm_queue_add (bat_priv, *ogm_buff, *ogm_buff_len, - hard_iface, hard_iface,1 , send_time); + scheduled =batadv_iv_ogm_queue_add (bat_priv, *ogm_buff, *ogm_buff_len, + hard_iface, hard_iface,1 , send_time); +if (!scheduled) + reschedule = true; + goto out; }
@@ -854,15 +866,28 @@ static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)if (!kref_get_unless_zero (&tmp_hard_iface->refcount))continue ; -batadv_iv_ogm_queue_add (bat_priv, *ogm_buff, - *ogm_buff_len, hard_iface, - tmp_hard_iface,1 , send_time); - + scheduled =batadv_iv_ogm_queue_add (bat_priv, *ogm_buff, + *ogm_buff_len, hard_iface, + tmp_hard_iface,1 , send_time);batadv_hardif_put (tmp_hard_iface); + +if (!scheduled && tmp_hard_iface == hard_iface) + reschedule = true; }rcu_read_unlock (); out: +if (reschedule) { +/* there was a failure scheduling the own forward packet. +* as result, the batadv_iv_send_outstanding_bat_ogm_packet() +* work item is no longer scheduled. it is therefore necessary +* to reschedule it manually +*/ +queue_delayed_work (batadv_event_workqueue, + &hard_iface->bat_iv.reschedule_work, +msecs_to_jiffies (atomic_read (&bat_priv->orig_interval))); + } +if (primary_if)batadv_hardif_put (primary_if); }
@@ -878,6 +903,17 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)mutex_unlock (&hard_iface->bat_iv.ogm_buff_mutex); } +static void batadv_iv_ogm_reschedule (struct work_struct *work) +{ +struct delayed_work *delayed_work =to_delayed_work (work); +struct batadv_hard_iface *hard_iface; + + hard_iface =container_of (delayed_work, + struct batadv_hard_iface, + bat_iv.reschedule_work); +batadv_iv_ogm_schedule (hard_iface); +} +/** * batadv_iv_orig_ifinfo_sum() - Get bcast_own sum for originator over interface * @orig_node: originator which reproadcasted the OGMs directly
@@ -2443,6 +2479,8 @@ batadv_iv_ogm_neigh_is_sob(struct batadv_neigh_node *neigh1,static void batadv_iv_iface_enabled (struct batadv_hard_iface *hard_iface) { +INIT_DELAYED_WORK (&hard_iface->bat_iv.reschedule_work, batadv_iv_ogm_reschedule); +/* begin scheduling originator messages on that interface */ batadv_iv_ogm_schedule (hard_iface); }
net/batman-adv/types.h +3 -0
@@ -83,6 +83,9 @@ struct batadv_hard_iface_bat_iv {/** @ogm_seqno: OGM sequence number - used to identify each OGM */ atomic_t ogm_seqno; +/** @reschedule_work: recover OGM schedule after schedule error */ +struct delayed_work reschedule_work; +/** @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len */ struct mutex ogm_buff_mutex; };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 35/342 batman-adv: tp_meter: fix race condition in send error reporting
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 71dce47f0758537fff78fddb5fb0d4632d29b29f upstream.
batadv_tp_sender_shutdown() previously used two separate variables to track session state: sending (an atomic flag indicating whether the session was active) and reason (a plain enum storing the stop reason). This introduced a race window between the two writes: after sending was cleared to 0, batadv_tp_send() could observe the stopped state and call batadv_tp_sender_end() before reason was written, causing the wrong stop reason to be reported to the caller.
Fix this by consolidating both variables into a single atomic send_result, which holds 0 while the session is running and the stop reason once it ends.
--- net/batman-adv/tp_meter.c | 40 ++++++++++++++++++++++++--------------- net/batman-adv/types.h | 10 +++++----- 2 files changed, 30 insertions(+), 20 deletions(-)
net/batman-adv/tp_meter.c +25 -15
@@ -402,11 +402,14 @@ static void batadv_tp_sender_cleanup(struct batadv_priv *bat_priv,static void batadv_tp_sender_end (struct batadv_priv *bat_priv,struct batadv_tp_vars *tp_vars) { +enum batadv_tp_meter_reason reason;u32 session_cookie; + reason =atomic_read (&tp_vars->send_result); +batadv_dbg (BATADV_DBG_TP_METER , bat_priv,"Test towards %pM finished..shutting down (reason=%d)\n" , - tp_vars->other_end, tp_vars->reason); + tp_vars->other_end, reason); batadv_dbg(BATADV_DBG_TP_METER, bat_priv, "Last timing stats: SRTT=%ums RTTVAR=%ums RTO=%ums\n",
@@ -419,7 +422,7 @@ static void batadv_tp_sender_end(struct batadv_priv *bat_priv, session_cookie =batadv_tp_session_cookie (tp_vars->session, tp_vars->icmp_uid); - batadv_tp_batctl_notify(tp_vars->reason, + batadv_tp_batctl_notify(reason, tp_vars->other_end, bat_priv, tp_vars->start_time,
@@ -435,10 +438,18 @@ static void batadv_tp_sender_end(struct batadv_priv *bat_priv,static void batadv_tp_sender_shutdown (struct batadv_tp_vars *tp_vars,enum batadv_tp_meter_reason reason) { -if (atomic_xchg (&tp_vars->sending,0 ) !=1 ) -return ; +atomic_cmpxchg (&tp_vars->send_result,0 , reason); +} - tp_vars->reason = reason; +/** +* batadv_tp_sender_stopped() - check if tp session was stopped with reason +* @tp_vars: the private data of the current TP meter session +* +* Return: whether stop reason was found +*/ +static bool batadv_tp_sender_stopped (struct batadv_tp_vars *tp_vars) +{ +return atomic_read (&tp_vars->send_result) !=0 ; }/**
@@ -468,7 +479,7 @@ static void batadv_tp_reset_sender_timer(struct batadv_tp_vars *tp_vars)/* most of the time this function is invoked while normal packet * reception... */ -if (unlikely (atomic_read (&tp_vars->sending) ==0 )) +if (unlikely (batadv_tp_sender_stopped (tp_vars)))/* timer ref will be dropped in batadv_tp_sender_cleanup */ return ;
@@ -488,7 +499,7 @@ static void batadv_tp_sender_timeout(struct timer_list *t)struct batadv_tp_vars *tp_vars =from_timer (tp_vars, t, timer);struct batadv_priv *bat_priv = tp_vars->bat_priv; -if (atomic_read (&tp_vars->sending) ==0 ) +if (batadv_tp_sender_stopped (tp_vars))return ;/* if the user waited long enough...shutdown the test */
@@ -650,7 +661,7 @@ static void batadv_tp_recv_ack(struct batadv_priv *bat_priv,if (unlikely (tp_vars->role !=BATADV_TP_SENDER )) goto out; -if (unlikely (atomic_read (&tp_vars->sending) ==0 )) +if (unlikely (batadv_tp_sender_stopped (tp_vars))) goto out;/* old ACK? silently drop it.. */
@@ -819,21 +830,21 @@ static int batadv_tp_send(void *arg)if (unlikely (tp_vars->role !=BATADV_TP_SENDER )) { err =BATADV_TP_REASON_DST_UNREACHABLE ; - tp_vars->reason = err; +batadv_tp_sender_shutdown (tp_vars, err); goto out; } orig_node =batadv_orig_hash_find (bat_priv, tp_vars->other_end);if (unlikely (!orig_node)) { err =BATADV_TP_REASON_DST_UNREACHABLE ; - tp_vars->reason = err; +batadv_tp_sender_shutdown (tp_vars, err); goto out; } primary_if =batadv_primary_if_get_selected (bat_priv);if (unlikely (!primary_if)) { err =BATADV_TP_REASON_DST_UNREACHABLE ; - tp_vars->reason = err; +batadv_tp_sender_shutdown (tp_vars, err); goto out; }
@@ -852,7 +863,7 @@ static int batadv_tp_send(void *arg)queue_delayed_work (batadv_event_workqueue, &tp_vars->finish_work,msecs_to_jiffies (tp_vars->test_length)); -while (atomic_read (&tp_vars->sending) !=0 ) { +while (!batadv_tp_sender_stopped (tp_vars)) {if (unlikely (!batadv_tp_avail (tp_vars, payload_len))) {batadv_tp_wait_available (tp_vars, payload_len);continue ;
@@ -875,8 +886,7 @@ static int batadv_tp_send(void *arg)"Meter: %s() cannot send packets (%d)\n" , __func__, err);/* ensure nobody else tries to stop the thread now */ -if (atomic_xchg (&tp_vars->sending,0 ) ==1 ) - tp_vars->reason = err; +batadv_tp_sender_shutdown (tp_vars, err);break ; }
@@ -997,7 +1007,7 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,ether_addr_copy (tp_vars->other_end, dst);kref_init (&tp_vars->refcount); tp_vars->role =BATADV_TP_SENDER ; -atomic_set (&tp_vars->sending,1 ); +atomic_set (&tp_vars->send_result,0 );memcpy (tp_vars->session, session_id,sizeof (session_id)); tp_vars->icmp_uid = icmp_uid;
net/batman-adv/types.h +5 -5
@@ -1407,11 +1407,11 @@ struct batadv_tp_vars {/** @role: receiver/sender modi */ enum batadv_tp_meter_role role; -/** @sending: sending binary semaphore: 1 if sending, 0 is not */ -atomic_t sending; - -/** @reason: reason for a stopped session */ -enum batadv_tp_meter_reason reason; +/** +* @send_result: 0 when sending is ongoing and otherwise +* enum batadv_tp_meter_reason +*/ +atomic_t send_result;/** @finish_work: work item for the finishing procedure */ struct delayed_work finish_work;
Signature · 1 line
2.53.0
Re: [PATCH 5.10 035/342] batman-adv: tp_meter: fix race condition in send error reporting
Quoted 7 lines · Greg Kroah-Hartman
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit
71dce47f0758537fff78fddb5fb0d4632d29b29fupstream.
[...]
No objection, but this is missing from the 5.15 and 6.1 queues. (It was already applied to 6.6 and later.)
Ben.
Signature · 2 lines
Ben Hutchings Humour is the best antidote to reality.
Greg Kroah-Hartman
maintainerRe: [PATCH 5.10 035/342] batman-adv: tp_meter: fix race condition in send error reporting
Quoted 5 lines · Ben Hutchings
Quoted 4 lines · Greg Kroah-Hartman
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
Quoted 7 lines
Quoted 3 lines
From: Sven Eckelmann <[email protected]>
commit
71dce47f0758537fff78fddb5fb0d4632d29b29fupstream.[...]
No objection, but this is missing from the 5.15 and 6.1 queues. (It was already applied to 6.6 and later.)
Good catch, I've queued both of these up now.
greg k-h
Greg Kroah-Hartman
maintainerPATCH 36/342 batman-adv: tp_meter: avoid role confusion in tp_list
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit ff24f2ecfd94c07a2b89bac497433e3b23271cac upstream.
Session lookups in tp_list matched only on destination address (and optionally session ID), leaving role validation to the caller. If two sessions with the same other_end coexisted (one as sender, one as receiver) a lookup could silently return the wrong one, causing the caller's role to bail out early, potentially skipping necessary cleanup.
Move the role check into the lookup functions themselves so the correct entry is always returned, or none at all. Since batadv_tp_start() legitimately needs to detect any active session to a destination regardless of role, introduce a dedicated helper for that case rather than bending the existing lookup semantics.
--- net/batman-adv/tp_meter.c | 59 ++++++++++++++++++++++++--------------- 1 file changed, 36 insertions(+), 23 deletions(-)
net/batman-adv/tp_meter.c +36 -23
@@ -253,6 +253,7 @@ static void batadv_tp_batctl_error_notify(enum batadv_tp_meter_reason reason,* batadv_tp_list_find() - find a tp_vars object in the global list * @bat_priv: the bat priv with all the soft interface information * @dst: the other endpoint MAC address to look for +* @role: role of the session * * Look for a tp_vars object matching dst as end_point and return it after * having increment the refcounter. Return NULL is not found
@@ -260,7 +261,8 @@ static void batadv_tp_batctl_error_notify(enum batadv_tp_meter_reason reason,* Return: matching tp_vars or NULL when no tp_vars with @dst was found */ static struct batadv_tp_vars *batadv_tp_list_find (struct batadv_priv *bat_priv, -const u8 *dst) +const u8 *dst, +enum batadv_tp_meter_role role) {struct batadv_tp_vars *pos, *tp_vars =NULL ;
@@ -269,6 +271,9 @@ static struct batadv_tp_vars *batadv_tp_list_find(struct batadv_priv *bat_priv,if (!batadv_compare_eth (pos->other_end, dst))continue ; +if (pos->role != role) +continue ; +/* most of the time this function is invoked during the normal * process..it makes sens to pay more when the session is * finished and to speed the process up during the measurement
@@ -284,12 +289,33 @@ static struct batadv_tp_vars *batadv_tp_list_find(struct batadv_priv *bat_priv,return tp_vars; } +/** +* batadv_tp_list_active() - check if session from/to destination is ongoing +* @bat_priv: the bat priv with all the mesh interface information +* @dst: the other endpoint MAC address to look for +* +* Return: if matching session with @dst was found +*/ +static bool batadv_tp_list_active (struct batadv_priv *bat_priv,const u8 *dst) + __must_hold(&bat_priv->tp_list_lock) +{ +struct batadv_tp_vars *tp_vars; + +hlist_for_each_entry_rcu (tp_vars, &bat_priv->tp_list, list) { +if (batadv_compare_eth (tp_vars->other_end, dst)) +return true; + } + +return false; +} +/** * batadv_tp_list_find_session() - find tp_vars session object in the global * list * @bat_priv: the bat priv with all the soft interface information * @dst: the other endpoint MAC address to look for * @session: session identifier +* @role: role of the session * * Look for a tp_vars object matching dst as end_point, session as tp meter * session and return it after having increment the refcounter. Return NULL
@@ -299,7 +325,7 @@ static struct batadv_tp_vars *batadv_tp_list_find(struct batadv_priv *bat_priv,*/ static struct batadv_tp_vars *batadv_tp_list_find_session (struct batadv_priv *bat_priv,const u8 *dst, -const u8 *session) +const u8 *session,enum batadv_tp_meter_role role) {struct batadv_tp_vars *pos, *tp_vars =NULL ;
@@ -311,6 +337,9 @@ batadv_tp_list_find_session(struct batadv_priv *bat_priv, const u8 *dst,if (memcmp (pos->session, session,sizeof (pos->session)) !=0 )continue ; +if (pos->role != role) +continue ; +/* most of the time this function is invoked during the normal * process..it makes sense to pay more when the session is * finished and to speed the process up during the measurement
@@ -654,13 +683,10 @@ static void batadv_tp_recv_ack(struct batadv_priv *bat_priv,/* find the tp_vars */ tp_vars =batadv_tp_list_find_session (bat_priv, icmp->orig, - icmp->session); + icmp->session,BATADV_TP_SENDER );if (unlikely (!tp_vars))return ; -if (unlikely (tp_vars->role !=BATADV_TP_SENDER )) - goto out; -if (unlikely (batadv_tp_sender_stopped (tp_vars))) goto out;
@@ -972,10 +998,8 @@ void batadv_tp_start(struct batadv_priv *bat_priv, const u8 *dst,return ; } - tp_vars =batadv_tp_list_find (bat_priv, dst); -if (tp_vars) { +if (batadv_tp_list_active (bat_priv, dst)) {spin_unlock_bh (&bat_priv->tp_list_lock); -batadv_tp_vars_put (tp_vars);batadv_dbg (BATADV_DBG_TP_METER , bat_priv,"Meter: test to or from the same node already ongoing, aborting\n" ); batadv_tp_batctl_error_notify(BATADV_TP_REASON_ALREADY_ONGOING,
@@ -1094,18 +1118,14 @@ void batadv_tp_stop(struct batadv_priv *bat_priv, const u8 *dst,if (!orig_node)return ; - tp_vars =batadv_tp_list_find (bat_priv, orig_node->orig); + tp_vars =batadv_tp_list_find (bat_priv, orig_node->orig,BATADV_TP_SENDER );if (!tp_vars) {batadv_dbg (BATADV_DBG_TP_METER , bat_priv,"Meter: trying to interrupt an already over connection\n" ); goto out_put_orig_node; } -if (unlikely (tp_vars->role !=BATADV_TP_SENDER )) - goto out_put_tp_vars; -batadv_tp_sender_shutdown (tp_vars, return_value); -out_put_tp_vars:batadv_tp_vars_put (tp_vars); out_put_orig_node:batadv_orig_node_put (orig_node);
@@ -1367,7 +1387,7 @@ batadv_tp_init_recv(struct batadv_priv *bat_priv, goto out_unlock; tp_vars =batadv_tp_list_find_session (bat_priv, icmp->orig, - icmp->session); + icmp->session,BATADV_TP_RECEIVER );if (tp_vars) goto out_unlock;
@@ -1435,7 +1455,7 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv, } }else { tp_vars =batadv_tp_list_find_session (bat_priv, icmp->orig, - icmp->session); + icmp->session,BATADV_TP_RECEIVER );if (!tp_vars) { batadv_dbg(BATADV_DBG_TP_METER, bat_priv, "Unexpected packet from %pM!\n",
@@ -1444,13 +1464,6 @@ static void batadv_tp_recv_msg(struct batadv_priv *bat_priv, } } -if (unlikely (tp_vars->role !=BATADV_TP_RECEIVER )) { -batadv_dbg (BATADV_DBG_TP_METER , bat_priv, -"Meter: dropping packet: not expected (role=%u)\n" , - tp_vars->role); - goto out; - } - tp_vars->last_recv_time = jiffies;/* if the packet is a duplicate, it may be the case that an ACK has been
Signature · 1 line
2.53.0
Re: [PATCH 5.10 036/342] batman-adv: tp_meter: avoid role confusion in tp_list
Quoted 7 lines · Greg Kroah-Hartman
5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit
ff24f2ecfd94c07a2b89bac497433e3b23271cacupstream.
[...]
No objection, but this is missing from the 5.15 and 6.1 queues. (It was already applied to 6.12 and later, and is queued for 6.6.)
Ben.
Signature · 2 lines
Ben Hutchings Humour is the best antidote to reality.
Greg Kroah-Hartman
maintainerPATCH 37/342 selftests: forwarding: lib: Add helpers for checksum handling
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Petr Machata <[email protected]>
commit 952e0ee38c7215c45192d8c899acd1830873f28b upstream.
In order to generate IGMPv3 and MLDv2 packets on the fly, we will need helpers to calculate the packet checksum.
The approach presented in this patch revolves around payload templates for mausezahn. These are mausezahn-like payload strings (01:23:45:...) with possibly one 2-byte sequence replaced with the word PAYLOAD. The main function is payload_template_calc_checksum(), which calculates RFC 1071 checksum of the message. There are further helpers to then convert the checksum to the payload format, and to expand it.
For IPv6, MLDv2 message checksum is computed using a pseudoheader that differs from the header used in the payload itself. The fact that the two messages are different means that the checksum needs to be returned as a separate quantity, instead of being expanded in-place in the payload itself. Furthermore, the pseudoheader includes a length of the message. Much like the checksum, this needs to be expanded in mausezahn format. And likewise for number of addresses for (S,G) entries. Thus we have several places where a computed quantity needs to be presented in the payload format. Add a helper u16_to_bytes(), which will be used in all these cases.
Stable-dep-of: 02cb2e6bacbb ("selftests: forwarding: vxlan_bridge_1d: fix test failure with br_netfilter enabled")
--- tools/testing/selftests/net/forwarding/lib.sh | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+)
tools/testing/selftests/net/forwarding/lib.sh +56 -0
@@ -1298,3 +1298,59 @@ tcpdump_show() { tcpdump -e -n -r $capfile 2>&1 } + +u16_to_bytes() +{ + local u16=$1; shift + + printf "%04x" $u16 | sed 's/^/000/;s/^.*\(..\)\(..\)$/\1:\2/' +} + +# Given a mausezahn-formatted payload (colon-separated bytes given as %02x), +# possibly with a keyword CHECKSUM stashed where a 16-bit checksum should be, +# calculate checksum as per RFC 1071, assuming the CHECKSUM field (if any) +# stands for 00:00. +payload_template_calc_checksum() +{ + local payload=$1; shift + + ( + # Set input radix. + echo "16i" + # Push zero for the initial checksum. + echo 0 + + # Pad the payload with a terminating 00: in case we get an odd + # number of bytes. + echo "${payload%:}:00:" | + sed 's/CHECKSUM/00:00/g' | + tr '[:lower:]' '[:upper:]' | + # Add the word to the checksum. + sed 's/\(..\):\(..\):/\1\2+\n/g' | + # Strip the extra odd byte we pushed if left unconverted. + sed 's/\(..\):$//' + + echo "10000 ~ +" # Calculate and add carry. + echo "FFFF r - p" # Bit-flip and print. + ) | + dc | + tr '[:upper:]' '[:lower:]' +} + +payload_template_expand_checksum() +{ + local payload=$1; shift + local checksum=$1; shift + + local ckbytes=$(u16_to_bytes $checksum) + + echo "$payload" | sed "s/CHECKSUM/$ckbytes/g" +} + +payload_template_nbytes() +{ + local payload=$1; shift + + payload_template_expand_checksum "${payload%:}" 0 | + sed 's/:/\n/g' | wc -l +}
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 38/342 batman-adv: tt: fix TOCTOU race for reported vlans
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 94d27005016be15ffc638b2ecbc4d58805ad7b48 upstream.
The local TT based TVLV is generated by first checking the number of VLANs which have at least one TT entry. A new buffer with the correct size for the VLANs is then allocated. Only then, the list of VLANs s used to fill the VLAN entries in the buffer. During this time, the meshif_vlan_list_lock is held. But the actual number of TT entries of each VLAN can still increase during this time - just not the number of VLANs in the list.
But the prefilter used in the buffer size calculation might still cause an increase of the number of VLANs which need to be stored. Simply because a VLAN might now suddenly have at least one entry when it had none in the pre-alloc check - and then needs to occupy space which was not allocated.
It is better to overestimate the buffer size at the beginning and then fill the buffer only with the VLANs which are not empty.
--- net/batman-adv/translation-table.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
net/batman-adv/translation-table.c +10 -4
@@ -939,11 +939,8 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,spin_lock_bh (&bat_priv->softif_vlan_list_lock);hlist_for_each_entry (vlan, &bat_priv->softif_vlan_list, list) { vlan_entries =atomic_read (&vlan->tt.num_entries); -if (vlan_entries <1 ) -continue ; - - num_vlan++; total_entries += vlan_entries; + num_vlan++; } change_offset =sizeof (**tt_data);
@@ -967,6 +964,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv, (*tt_data)->num_vlan =htons (num_vlan); tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data +1 ); + num_vlan =0 ;hlist_for_each_entry (vlan, &bat_priv->softif_vlan_list, list) { vlan_entries =atomic_read (&vlan->tt.num_entries);if (vlan_entries <1 )
@@ -977,8 +975,16 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv, tt_vlan->reserved =0 ; tt_vlan++; + num_vlan++; } +/* recalculate in case number of VLANs reduced */ + change_offset =sizeof (**tt_data); + change_offset += num_vlan *sizeof (*tt_vlan); + tvlv_len = *tt_len + change_offset; + + (*tt_data)->num_vlan =htons (num_vlan); + tt_change_ptr = (u8 *)*tt_data + change_offset; *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 39/342 batman-adv: tt: avoid empty VLAN responses
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit fa1bd704940b5bcbc32c0b28db9167405c8ee5e0 upstream.
The commit 16116dac2339 ("batman-adv: prevent TT request storms by not sending inconsistent TT TLVLs") added checks to the local (direct) TT response code. But the response can also be done indirectly by another node using the global TT state. To avoid such inconsistency states reported in the original fix, also avoid sending empty VLANs for replies from the global TT state.
--- net/batman-adv/translation-table.c | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
net/batman-adv/translation-table.c +18 -3
@@ -848,17 +848,19 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node, s32 *tt_len) {u16 num_vlan =0 ; -u16 num_entries =0 ;u16 tvlv_len =0 ;unsigned int change_offset;struct batadv_tvlv_tt_vlan_data *tt_vlan;struct batadv_orig_node_vlan *vlan; +u16 total_entries =0 ;u8 *tt_change_ptr; +int vlan_entries;spin_lock_bh (&orig_node->vlan_list_lock);hlist_for_each_entry (vlan, &orig_node->vlan_list, list) { + vlan_entries =atomic_read (&vlan->tt.num_entries); + total_entries += vlan_entries; num_vlan++; - num_entries +=atomic_read (&vlan->tt.num_entries); } change_offset =sizeof (**tt_data);
@@ -866,7 +868,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,/* if tt_len is negative, allocate the space needed by the full table */ if (*tt_len <0 ) - *tt_len =batadv_tt_len (num_entries); + *tt_len =batadv_tt_len (total_entries);if (change_offset >U16_MAX || *tt_len >U16_MAX - change_offset) { *tt_len =0 ;
@@ -887,14 +889,27 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node, (*tt_data)->num_vlan =htons (num_vlan); tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data +1 ); + num_vlan =0 ;hlist_for_each_entry (vlan, &orig_node->vlan_list, list) { + vlan_entries =atomic_read (&vlan->tt.num_entries); +if (vlan_entries <1 ) +continue ; + tt_vlan->vid =htons (vlan->vid); tt_vlan->crc =htonl (vlan->tt.crc); tt_vlan->reserved =0 ; tt_vlan++; + num_vlan++; } +/* recalculate in case number of VLANs reduced */ + change_offset =sizeof (**tt_data); + change_offset += num_vlan *sizeof (*tt_vlan); + tvlv_len = *tt_len + change_offset; + + (*tt_data)->num_vlan =htons (num_vlan); + tt_change_ptr = (u8 *)*tt_data + change_offset; *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 40/342 batman-adv: bla: avoid double decrement of bla.num_requests
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 83ab69bd12b80f6ea169c8bea6977701b53a043d upstream.
The bla.num_requests is increased when no request_sent was in progress. And it is decremented in various places (announcement was received, backbone is purged, periodic work). But the check if the request_sent is actually set to a specific state and the atomic_dec/_inc are not safe because they are not atomic (TOCTOU) and multiple such code portions can run concurrently.
At the same time, it is necessary to modify request_sent (state) and bla.num_requests atomically. Otherwise batadv_bla_send_request() might set request_sent to 1 and is interrupted. batadv_handle_announce() can then set request_sent back to 0 and decrement num_requests before batadv_bla_send_request() incremented it.
The two operations must therefore be locked. And since state (request_sent) and wait_periods are only accessed inside this lock, they can be converted to simpler datatypes. And to avoid that the bla.num_requests is touched by a parallel running context with a valid backbone_gw reference after batadv_bla_purge_backbone_gw() ran, a third state "stopped" is required to correctly signal that a backbone_gw is in the state of being cleaned up.
--- net/batman-adv/bridge_loop_avoidance.c | 51 ++++++++++++++++++-------- net/batman-adv/soft-interface.c | 1 + net/batman-adv/types.h | 39 ++++++++++++++++---- 3 files changed, 67 insertions(+), 24 deletions(-)
net/batman-adv/bridge_loop_avoidance.c +35 -16
@@ -521,8 +521,8 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, u8 *orig, entry->crc =BATADV_BLA_CRC_INIT ; entry->bat_priv = bat_priv;spin_lock_init (&entry->crc_lock); -atomic_set (&entry->request_sent,0 ); -atomic_set (&entry->wait_periods,0 ); + entry->state =BATADV_BLA_BACKBONE_GW_SYNCED ; + entry->wait_periods =0 ;ether_addr_copy (entry->orig, orig);INIT_WORK (&entry->report_work, batadv_bla_loopdetect_report);kref_init (&entry->refcount);
@@ -551,9 +551,13 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, u8 *orig,batadv_bla_send_announce (bat_priv, entry);/* this will be decreased in the worker thread */ -atomic_inc (&entry->request_sent); -atomic_set (&entry->wait_periods,BATADV_BLA_WAIT_PERIODS ); -atomic_inc (&bat_priv->bla.num_requests); +spin_lock_bh (&bat_priv->bla.num_requests_lock); +if (entry->state ==BATADV_BLA_BACKBONE_GW_SYNCED ) { + entry->state =BATADV_BLA_BACKBONE_GW_UNSYNCED ; + entry->wait_periods =BATADV_BLA_WAIT_PERIODS ; +atomic_inc (&bat_priv->bla.num_requests); + } +spin_unlock_bh (&bat_priv->bla.num_requests_lock); }return entry;
@@ -656,10 +660,12 @@ static void batadv_bla_send_request(struct batadv_bla_backbone_gw *backbone_gw) backbone_gw->vid, BATADV_CLAIM_TYPE_REQUEST);/* no local broadcasts should be sent or received, for now. */ -if (!atomic_read (&backbone_gw->request_sent)) { +spin_lock_bh (&backbone_gw->bat_priv->bla.num_requests_lock); +if (backbone_gw->state ==BATADV_BLA_BACKBONE_GW_SYNCED ) { + backbone_gw->state =BATADV_BLA_BACKBONE_GW_UNSYNCED ;atomic_inc (&backbone_gw->bat_priv->bla.num_requests); -atomic_set (&backbone_gw->request_sent,1 ); } +spin_unlock_bh (&backbone_gw->bat_priv->bla.num_requests_lock); }/**
@@ -880,10 +886,12 @@ static bool batadv_handle_announce(struct batadv_priv *bat_priv, u8 *an_addr,/* if we have sent a request and the crc was OK, * we can allow traffic again. */ -if (atomic_read (&backbone_gw->request_sent)) { +spin_lock_bh (&bat_priv->bla.num_requests_lock); +if (backbone_gw->state ==BATADV_BLA_BACKBONE_GW_UNSYNCED ) { + backbone_gw->state =BATADV_BLA_BACKBONE_GW_SYNCED ;atomic_dec (&backbone_gw->bat_priv->bla.num_requests); -atomic_set (&backbone_gw->request_sent,0 ); } +spin_unlock_bh (&bat_priv->bla.num_requests_lock); }batadv_backbone_gw_put (backbone_gw);
@@ -1262,9 +1270,13 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now) purged = true;/* don't wait for the pending request anymore */ -if (atomic_read (&backbone_gw->request_sent)) +spin_lock_bh (&bat_priv->bla.num_requests_lock); +if (backbone_gw->state ==BATADV_BLA_BACKBONE_GW_UNSYNCED )atomic_dec (&bat_priv->bla.num_requests); + backbone_gw->state =BATADV_BLA_BACKBONE_GW_STOPPED ; +spin_unlock_bh (&bat_priv->bla.num_requests_lock); +batadv_bla_del_backbone_claims (backbone_gw);hlist_del_rcu (&backbone_gw->hash_entry);
@@ -1515,7 +1527,7 @@ static void batadv_bla_periodic_work(struct work_struct *work)batadv_bla_send_loopdetect (bat_priv, backbone_gw); -/* request_sent is only set after creation to avoid +/* state is only set to unsynced after creation to avoid * problems when we are not yet known as backbone gw * in the backbone. *
@@ -1524,14 +1536,21 @@ static void batadv_bla_periodic_work(struct work_struct *work)* some grace time. */ -if (atomic_read (&backbone_gw->request_sent) ==0 ) -continue ; +spin_lock_bh (&bat_priv->bla.num_requests_lock); +if (backbone_gw->state !=BATADV_BLA_BACKBONE_GW_UNSYNCED ) + goto unlock_next; -if (!atomic_dec_and_test (&backbone_gw->wait_periods)) -continue ; +if (backbone_gw->wait_periods >0 ) + backbone_gw->wait_periods--; + +if (backbone_gw->wait_periods >0 ) + goto unlock_next; + backbone_gw->state =BATADV_BLA_BACKBONE_GW_SYNCED ;atomic_dec (&backbone_gw->bat_priv->bla.num_requests); -atomic_set (&backbone_gw->request_sent,0 ); + +unlock_next: +spin_unlock_bh (&bat_priv->bla.num_requests_lock); }rcu_read_unlock (); }
net/batman-adv/soft-interface.c +1 -0
@@ -822,6 +822,7 @@ static int batadv_softif_init_late(struct net_device *dev)atomic_set (&bat_priv->tt.ogm_append_cnt,0 );#ifdef CONFIG_BATMAN_ADV_BLA atomic_set (&bat_priv->bla.num_requests,0 ); +spin_lock_init (&bat_priv->bla.num_requests_lock);#endif atomic_set (&bat_priv->tp_num,0 );
net/batman-adv/types.h +31 -8
@@ -1036,6 +1036,12 @@ struct batadv_priv_bla {/** @num_requests: number of bla requests in flight */ atomic_t num_requests; +/** +* @num_requests_lock: locks update num_requests + +* batadv_backbone_gw::state + batadv_backbone_gw::wait_periods update +*/ +spinlock_t num_requests_lock; +/** * @claim_hash: hash table containing mesh nodes this host has claimed */
@@ -1815,6 +1821,27 @@ struct batadv_socket_packet {#ifdef CONFIG_BATMAN_ADV_BLA +enum batadv_bla_backbone_gw_state { +/** +* @BATADV_BLA_BACKBONE_GW_STOPPED: backbone gw is being removed +* and it must not longer work on requests +*/ +BATADV_BLA_BACKBONE_GW_STOPPED , + +/** +* @BATADV_BLA_BACKBONE_GW_UNSYNCED: backbone was detected out +* of sync and a request was send. No traffic is forwarded until the +* situation is resolved +*/ +BATADV_BLA_BACKBONE_GW_UNSYNCED , + +/** +* @BATADV_BLA_BACKBONE_GW_SYNCED: backbone is consider to be in +* sync. traffic can be forwarded +*/ +BATADV_BLA_BACKBONE_GW_SYNCED , +}; +/** * struct batadv_bla_backbone_gw - batman-adv gateway bridged into the LAN */
@@ -1840,16 +1867,12 @@ struct batadv_bla_backbone_gw {/** * @wait_periods: grace time for bridge forward delays and bla group * forming at bootup phase - no bcast traffic is formwared until it has -* elapsed +* elapsed. Must only be access with num_requests_lock. */ -atomic_t wait_periods; +u8 wait_periods; -/** -* @request_sent: if this bool is set to true we are out of sync with -* this backbone gateway - no bcast traffic is formwared until the -* situation was resolved -*/ -atomic_t request_sent; +/** @state: sync state. Must only be access with num_requests_lock. */ +enum batadv_bla_backbone_gw_state state;/** @crc: crc16 checksum over all claims */ u16 crc;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 41/342 Revert "RDMA/rxe: Fix double free in rxe_srq_from_init"
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ben Hutchings <[email protected]>
This reverts commit 22b8c23a3b92d023614bb00896fe364b2c1a31d3, which was commit 0beefd0e15d962f497aad750b2d5e9c3570b66d1 upstream. The backported version did not move but duplicated the problematic assignment, so it did not fix the bug. A proper backport will follow.
--- drivers/infiniband/sw/rxe/rxe_srq.c | 3 --- 1 file changed, 3 deletions(-)
drivers/infiniband/sw/rxe/rxe_srq.c +0 -3
@@ -116,9 +116,6 @@ int rxe_srq_from_init(struct rxe_dev *rxe, struct rxe_srq *srq, } } - srq->rq.queue = q; - init->attr.max_wr = srq->rq.max_wr; -return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 42/342 RDMA/rxe: Fix double free in rxe_srq_from_init
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiasheng Jiang <[email protected]>
commit 0beefd0e15d962f497aad750b2d5e9c3570b66d1 upstream.
In rxe_srq_from_init(), the queue pointer 'q' is assigned to 'srq->rq.queue' before copying the SRQ number to user space. If copy_to_user() fails, the function calls rxe_queue_cleanup() to free the queue, but leaves the now-invalid pointer in 'srq->rq.queue'.
The caller of rxe_srq_from_init() (rxe_create_srq) eventually calls rxe_srq_cleanup() upon receiving the error, which triggers a second rxe_queue_cleanup() on the same memory, leading to a double free.
The call trace looks like this:
kmem_cache_free+0x.../0x... rxe_queue_cleanup+0x1a/0x30 [rdma_rxe] rxe_srq_cleanup+0x42/0x60 [rdma_rxe] rxe_elem_release+0x31/0x70 [rdma_rxe] rxe_create_srq+0x12b/0x1a0 [rdma_rxe] ib_create_srq_user+0x9a/0x150 [ib_core]
Fix this by moving 'srq->rq.queue = q' after copy_to_user.
[bwh: Backported to 5.10: There was no assignment to init->attr.max_wr
here; don't add it]
--- drivers/infiniband/sw/rxe/rxe_srq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/infiniband/sw/rxe/rxe_srq.c +2 -2
@@ -98,8 +98,6 @@ int rxe_srq_from_init(struct rxe_dev *rxe, struct rxe_srq *srq,return -ENOMEM ; } - srq->rq.queue = q; - err =do_mmap_info (rxe, uresp ? &uresp->mi :NULL , udata, q->buf, q->buf_size, &q->ip);if (err) {
@@ -116,6 +114,8 @@ int rxe_srq_from_init(struct rxe_dev *rxe, struct rxe_srq *srq, } } + srq->rq.queue = q; +return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 43/342 smb: client: fix smbdirect_recv_io leak in smbd_negotiate() error path
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Metzmacher <[email protected]>
[ Upstream commit daac51c7032036a0ca5f1aa419ad1b0471d1c6e0 ]
During tests of another unrelated patch I was able to trigger this
error: Objects remaining on __kmem_cache_shutdown()
--- fs/cifs/smbdirect.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/cifs/smbdirect.c +3 -1
@@ -1083,8 +1083,10 @@ static int smbd_negotiate(struct smbd_connection *info)log_rdma_event (INFO ,"smbd_post_recv rc=%d iov.addr=%llx iov.length=%x iov.lkey=%x\n" , rc, response->sge.addr, response->sge.length, response->sge.lkey); -if (rc) +if (rc) { +put_receive_buffer (info, response);return rc; + }init_completion (&info->negotiate_completion); info->negotiate_done = false;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 44/342 iio: imu: st_lsm6dsx: fix stack leak in tagged FIFO buffer
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
commit c9d8e9adaa63150ef7e833480b799d0bab83a276 upstream.
The tagged FIFO path declares iio_buff on the stack with __aligned(8) but no initializer, but there is a hole in the structure, which will then leak to userspace as ST_LSM6DSX_SAMPLE_SIZE bytes (6) will be copied, but the space between that and the timestamp are not initialized.
Commit c14edb4d0bdc ("iio:imu:st_lsm6dsx Fix alignment and data leak issues") moved the untagged FIFO path to a kzalloc'd buffer in hw->scan, but for the tagged path it only added the alignment qualifier and not the initializer :(
Fix this by just zero-initializing the structure on the stack.
--- drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_buffer.c +1 -1
@@ -585,7 +585,7 @@ int st_lsm6dsx_read_tagged_fifo(struct s* must be passed a buffer that is aligned to 8 bytes so * as to allow insertion of a naturally aligned timestamp. */ -u8 iio_buff[ST_LSM6DSX_IIO_BUFF_SIZE ]__aligned(8) ; +u8 iio_buff[ST_LSM6DSX_IIO_BUFF_SIZE ]__aligned(8) = { };u8 tag;bool reset_ts = false;int i, err, read_len;
Greg Kroah-Hartman
maintainerPATCH 45/342 usb: typec: ucsi: ccg: reject firmware images without a : record header
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
commit d7486952bf74e546ee3748fb14b2d07881fa6273 upstream.
do_flash() locates the first .cyacd record with
p = strnchr(fw->data, fw->size, ':');
while (p < eof) {
s = strnchr(p + 1, eof - p - 1, ':');
...
}If the firmware image contains no ':' byte, strnchr() returns NULL. NULL compares less than the valid kernel pointer eof, so the loop body runs and strnchr() is called with p + 1 == (void *)1 and a length of roughly (unsigned long)eof, causing a wonderful crash.
The not_signed_fw fallthrough earlier in do_flash() and the chip-state branches in ccg_fw_update_needed() allow an unsigned blob to reach this loop, so a root user who can place a crafted file under /lib/firmware and write the do_flash sysfs attribute can trigger the oops.
Bail out with -EINVAL when the initial strnchr() returns NULL.
--- drivers/usb/typec/ucsi/ucsi_ccg.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/usb/typec/ucsi/ucsi_ccg.c +5 -0
@@ -1156,6 +1156,11 @@ not_signed_fw:*****************************************************************/ p =strnchr (fw->data, fw->size,':' ); +if (!p) { +dev_err (dev,"Bad FW format: no ':' record header found\n" ); + err = -EINVAL ; + goto release_mem; + }while (p < eof) { s =strnchr (p +1 , eof - p -1 ,':' );
Greg Kroah-Hartman
maintainerPATCH 46/342 usb: typec: ucsi: displayport: NAK DP_CMD_CONFIGURE without a payload VDO
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
commit 167dd8d12226587ee554f520aed0256b7769cd5d upstream.
ucsi_displayport_vdm() handles a DP_CMD_CONFIGURE by copying the first payload VDO from data[], but unlike the equivalent handler in altmodes/displayport.c it does not check that count covers a VDO beyond the header. A header-only Configure VDM (count == 1) would read one u32 past the caller's array.
In the normal UCSI path the caller controls count, so this is hardening for non-standard delivery paths. NAK and bail when no configuration VDO is present, matching the generic DP altmode driver's existing guard.
--- drivers/usb/typec/ucsi/displayport.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/usb/typec/ucsi/displayport.c +4 -0
@@ -211,6 +211,10 @@ static int ucsi_displayport_vdm(struct t dp->header |=VDO_CMDT (CMDT_RSP_ACK );break ;case DP_CMD_CONFIGURE : +if (count <2 ) { + dp->header |=VDO_CMDT (CMDT_RSP_NAK ); +break ; + } dp->data.conf = *data;if (ucsi_displayport_configure (dp)) { dp->header |=VDO_CMDT (CMDT_RSP_NAK );
Greg Kroah-Hartman
maintainerPATCH 47/342 usb: typec: altmodes/displayport: validate count before reading Status Update VDO
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
commit 8a18f896e667df491331371b55d4ad644dc51d60 upstream.
A broken/malicious device can send the incorrect count for a status update VDO, which will cause the kernel to read uninitialized stack data and send it off elsewhere.
Fix this up by correctly verifying the count for the update object.
--- drivers/usb/typec/altmodes/displayport.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/usb/typec/altmodes/displayport.c +2 -0
@@ -292,6 +292,8 @@ static int dp_altmode_vdm(struct typec_a }break ;case DP_CMD_STATUS_UPDATE : +if (count <2 ) +break ; dp->data.status = *vdo; ret =dp_altmode_status_update (dp);break ;
Greg Kroah-Hartman
maintainerPATCH 48/342 usb: typec: wcove: dont write past struct pd_message in wcove_read_rx_buffer()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
commit 4af7ad0e6d7aa4403dbb1dac7b9659b0421efcaa upstream.
wcove_read_rx_buffer() copies the PD RX FIFO into the caller's struct pd_message with
for (i = 0; i < USBC_RXINFO_RXBYTES(info); i++) regmap_read(wcove->regmap, USBC_RX_DATA + i, msg + i);
which has two problems:
USBC_RXINFO_RXBYTES() is a 5-bit field (max 31) while struct pd_message is 30 bytes (__le16 header + __le32 payload[PD_MAX_PAYLOAD], packed). The byte count latched in RXINFO is the number of bytes the port partner put on the wire, so a malicious partner that transmits a 31-byte frame can drive the loop one byte past the destination if the WCOVE BMC receiver does not enforce the PD object-count limit in hardware. The existing FIXME flagged this as unverified.
Independently, regmap_read() takes an unsigned int * and stores a full unsigned int at the destination. Passing the byte pointer msg + i means each iteration writes four bytes; the high three are zero (val_bits is
8) and are normally overwritten by the next iteration, but the final iteration's high bytes are not. With RXBYTES == 30 the i == 29 iteration already writes three zero bytes past msg, which sits on the IRQ thread's stack in wcove_typec_irq().
Clamp the loop to sizeof(struct pd_message) and read each register into a local before storing only its low byte, so the copy can never exceed the destination regardless of what RXINFO reports.
--- drivers/usb/typec/tcpm/wcove.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
drivers/usb/typec/tcpm/wcove.c +8 -5
@@ -443,9 +443,11 @@ static int wcove_start_toggling(struct treturn regmap_write (wcove->regmap,USBC_CONTROL1 , usbc_ctrl); } -static int wcove_read_rx_buffer (struct wcove_typec *wcove,void *msg) +static int wcove_read_rx_buffer (struct wcove_typec *wcove, +struct pd_message *msg) { -unsigned int info; +unsigned int info, val, len; +u8 *buf = (u8 *)msg;int ret;int i;
@@ -453,12 +455,13 @@ static int wcove_read_rx_buffer(struct wif (ret)return ret; -/* FIXME: Check that USBC_RXINFO_RXBYTES(info) matches the header */ + len =min (USBC_RXINFO_RXBYTES (info),sizeof (*msg)); -for (i =0 ; i <USBC_RXINFO_RXBYTES (info); i++) { - ret =regmap_read (wcove->regmap,USBC_RX_DATA + i, msg + i); +for (i =0 ; i < len; i++) { + ret =regmap_read (wcove->regmap,USBC_RX_DATA + i, &val);if (ret)return ret; + buf[i] = val; } return regmap_write(wcove->regmap, USBC_RXSTATUS,
Greg Kroah-Hartman
maintainerPATCH 49/342 USB: serial: safe_serial: fix memory corruption with small endpoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 438061ed1ad85e6743e2dce826671772d81089ec upstream.
Make sure that the bulk-out buffer size is at least eight bytes to avoid user-controlled slab corruption in "safe" mode should a malicious device report a smaller size.
--- drivers/usb/serial/safe_serial.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
drivers/usb/serial/safe_serial.c +11 -0
@@ -259,6 +259,7 @@ static int safe_prepare_write_buffer(strstatic int safe_startup (struct usb_serial *serial) {struct usb_interface_descriptor *desc; +int bulk_out_size;if (serial->dev->descriptor.bDeviceClass !=CDC_DEVICE_CLASS )return -ENODEV ;
@@ -279,6 +280,16 @@ static int safe_startup(struct usb_seriadefault :return -EINVAL ; } + +/* +* The bulk-out buffer needs to be large enough for the two-byte +* trailer in safe mode, but assume anything smaller than eight bytes +* is broken. +*/ + bulk_out_size = serial->port[0 ]->bulk_out_size; +if (bulk_out_size >0 && bulk_out_size <8 ) +return -EINVAL ; +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 50/342 Input: ims-pcu - fix usb_free_coherent() size in ims_pcu_buffers_free()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Fourier <[email protected]>
commit dab48a7e74e6a394f3aa0461a2b1fb0c7b38fcb8 upstream.
The input buffer size is pcu->max_in_size, but pcu->max_out_size is passed to usb_free_coherent().
Change size to match the allocation size.
--- drivers/input/misc/ims-pcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/misc/ims-pcu.c +1 -1
@@ -1598,7 +1598,7 @@ static void ims_pcu_buffers_free(structusb_kill_urb (pcu->urb_in);usb_free_urb (pcu->urb_in); -usb_free_coherent (pcu->udev, pcu->max_out_size, +usb_free_coherent (pcu->udev, pcu->max_in_size, pcu->urb_in_buf, pcu->read_dma);kfree (pcu->urb_out_buf);
Greg Kroah-Hartman
maintainerPATCH 51/342 Bluetooth: btusb: Allow firmware re-download when version matches
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuai Zhang <[email protected]>
commit 82855073c1081732656734b74d7d1d5e4cfd0da7 upstream.
The Bluetooth host decides whether to download firmware by reading the controller firmware download completion flag and firmware version information.
If a USB error occurs during the firmware download process (for example due to a USB disconnect), the download is aborted immediately. An incomplete firmware transfer does not cause the controller to set the download completion flag, but the firmware version information may be updated at an early stage of the download process.
In this case, after USB reconnection, the host attempts to re-download the firmware because the download completion flag is not set. However, since the controller reports the same firmware version as the target firmware, the download is skipped. This ultimately results in the firmware not being properly updated on the controller.
This change removes the restriction that skips firmware download when the versions are equal. It covers scenarios where the USB connection can be disconnected at any time and ensures that firmware download can be retriggered after USB reconnection, allowing the Bluetooth firmware to be correctly and completely updated.
--- drivers/bluetooth/btusb.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/bluetooth/btusb.c +7 -1
@@ -3744,7 +3744,13 @@ static int btusb_setup_qca_load_rampatch"firmware rome 0x%x build 0x%x" , rver_rom, rver_patch, ver_rom, ver_patch); -if (rver_rom != ver_rom || rver_patch <= ver_patch) { +/* Allow rampatch when the patch version equals the firmware version. +* A firmware download may be aborted by a transient USB error (e.g. +* disconnect) after the controller updates version info but before +* completion. +* Allowing equal versions enables re-flashing during recovery. +*/ +if (rver_rom != ver_rom || rver_patch < ver_patch) {bt_dev_err (hdev,"rampatch file version did not match with firmware" ); err = -EINVAL ; goto done;
Greg Kroah-Hartman
maintainerPATCH 52/342 hpfs: fix a crash if hpfs_map_dnode_bitmap fails
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <[email protected]>
commit 974820a59efde7c1a7e1260bcfe9bb81f833cc9f upstream.
If hpfs_map_dnode_bitmap fails, the code would call hpfs_brelse4 on uninitialized quad buffer head, causing a crash.
--- fs/hpfs/alloc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/hpfs/alloc.c +1 -1
@@ -372,8 +372,8 @@ int hpfs_check_free_dnodes(struct super_return 0 ; } } +hpfs_brelse4 (&qbh); } -hpfs_brelse4 (&qbh); i =0 ;if (hpfs_sb (s)->sb_c_bitmap !=-1 ) { bmp =hpfs_map_bitmap (s, b, &qbh,"chkdn1" );
Greg Kroah-Hartman
maintainerPATCH 53/342 ipc: limit next_id allocation to the valid ID range
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Linpu Yu <[email protected]>
commit fa0b9b2b7ae3539908d69c2b9ac0d144d9bc5139 upstream.
The checkpoint/restore sysctl path can request the next SysV IPC id through ids->next_id. ipc_idr_alloc() currently forwards that request to idr_alloc() with an open-ended upper bound.
If the valid tail of the SysV IPC id space is full, the allocation can spill beyond ipc_mni. The returned SysV IPC id still uses the normal index encoding, so later lookup and removal can target the wrong slot. This leaves the real IDR entry behind and breaks the IDR state for the object.
The bug is in ipc_idr_alloc() in the checkpoint/restore path.
1. ids->next_id is passed to:
idr_alloc(&ids->ipcs_idr, new, ipcid_to_idx(next_id), 0, ...)
2. The zero upper bound makes the allocation effectively open-ended. Once the valid SysV IPC tail is occupied, idr_alloc() can spill past ipc_mni and allocate an entry beyond the valid IPC id range.
3. The new object id is still encoded with the narrower SysV IPC index width:
new->id = (new->seq << ipcmni_seq_shift()) + idx
4. Later removal goes through ipc_rmid(), which uses:
ipcid_to_idx(ipcp->id)
That truncates the real IDR index. An object actually stored at a high index can then be removed as if it lived at a low in-range index.
5. For shared memory, shm_destroy() frees the current object anyway, but the real high IDR slot is left behind as a dangling pointer.
6. A subsequent walk of /proc/sysvipc/shm reaches the stale IDR entry and dereferences freed memory.
Prevent this by bounding the requested allocation to ipc_mni so the checkpoint/restore path fails once the valid range is exhausted.
--- ipc/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
ipc/util.c +1 -1
@@ -252,7 +252,7 @@ static inline int ipc_idr_alloc(struct i }else { new->seq =ipcid_to_seqx (next_id); idx =idr_alloc (&ids->ipcs_idr, new,ipcid_to_idx (next_id), -0 ,GFP_NOWAIT ); + ipc_mni,GFP_NOWAIT ); }if (idx >=0 ) new->id = (new->seq <<ipcmni_seq_shift ()) + idx;
Greg Kroah-Hartman
maintainerPATCH 54/342 Bluetooth: L2CAP: fix chan ref leak in l2cap_chan_timeout() on !conn
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Siwei Zhang <[email protected]>
commit 9dbd84990394c51f5cee1e8871bb5ff8af5ed939 upstream.
__set_chan_timer() takes a l2cap_chan reference via l2cap_chan_hold() before scheduling the delayed work. The normal path in l2cap_chan_timeout() drops this reference with l2cap_chan_put() at the end, but the early return when chan->conn is NULL skips the put, leaking the reference.
Add the missing l2cap_chan_put() before the early return.
--- net/bluetooth/l2cap_core.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/bluetooth/l2cap_core.c +3 -1
@@ -435,8 +435,10 @@ static void l2cap_chan_timeout(struct woBT_DBG ("chan %p state %s" , chan,state_to_string (chan->state)); -if (!conn) +if (!conn) { +l2cap_chan_put (chan);return ; + }mutex_lock (&conn->chan_lock);/* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling
Greg Kroah-Hartman
maintainerPATCH 55/342 parport: Fix race between port and client registration
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ben Hutchings <[email protected]>
commit ef15ccbb3e8640a723c42ad90eaf81d66ae02017 upstream.
The parport subsystem registers port devices before they are fully initialised, resulting in a race condition where client drivers such as lp can attach to ports that are not completely initialised or even being torn down.
When the port and client drivers are built as modules and loaded around the same time during boot, this occasionally results in a crash. I was able to make this happen reliably in a VM with a PC-style parallel port by patching parport_pc to fail probing:
drivers/parport/parport_pc.c static struct parport *__parport_pc_probe_port(unsigned long int base, · line 2075
Quoted 11 lines
drivers/parport/parport_pc.c +1
-1@@ -2069,7 +2069,7 @@ static struct parport *__parport_pc_probe_port(unsigned long int base,if (!p) goto out3; - base_res =request_region (base,3 , p->name); + base_res =NULL ;if (!base_res) goto out4;
and then running:
while true; do
modprobe lp & modprobe parport_pc
wait
rmmod lp parport_pc
done
for a few seconds.
In the long term I think port registration should be changed to put the call to device_add() inside parport_announce_port(), but since the latter currently cannot fail this will require changing all port drivers.
For now, add a flag to indicate whether a port has been "announced" and only try to attach client drivers to ports when the flag is set.
--- drivers/parport/share.c | 11 +++++++++-- include/linux/parport.h | 1 + 2 files changed, 10 insertions(+), 2 deletions(-)
drivers/parport/share.c +9 -2
@@ -223,10 +223,14 @@ static void get_lowlevel_driver(void)static int port_check (struct device *dev,void *dev_drv) {struct parport_driver *drv = dev_drv; +struct parport *port;/* only send ports, do not send other devices connected to bus */ -if (is_parport (dev)) - drv->match_port (to_parport_dev (dev)); +if (is_parport (dev)) { + port =to_parport_dev (dev); +if (test_bit (PARPORT_ANNOUNCED , &port->devflags)) + drv->match_port (port); + }return 0 ; }
@@ -553,6 +557,7 @@ void parport_announce_port(struct parporif (slave)attach_driver_chain (slave); } +set_bit (PARPORT_ANNOUNCED , &port->devflags);mutex_unlock (®istration_lock); }EXPORT_SYMBOL (parport_announce_port);
@@ -582,6 +587,8 @@ void parport_remove_port(struct parportmutex_lock (®istration_lock); +clear_bit (PARPORT_ANNOUNCED , &port->devflags); +/* Spread the word. */ detach_driver_chain (port);
include/linux/parport.h +1 -0
@@ -245,6 +245,7 @@ struct parport {unsigned long devflags;#define PARPORT_DEVPROC_REGISTERED 0 +#define PARPORT_ANNOUNCED 1struct pardevice *proc_device;/* Currently register proc device */ struct list_head full_list;
Greg Kroah-Hartman
maintainerPATCH 56/342 iio: adc: xilinx-xadc: Fix sequencer mode in postdisable for dual mux
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christofer Jonason <[email protected]>
commit 852534744c2d35626a604f128ff0b8ec12805591 upstream.
xadc_postdisable() unconditionally sets the sequencer to continuous mode. For dual external multiplexer configurations this is incorrect:
simultaneous sampling mode is required so that ADC-A samples through the mux on VAUX[0-7] while ADC-B simultaneously samples through the mux on VAUX[8-15]. In continuous mode only ADC-A is active, so VAUX[8-15] channels return incorrect data.
Since postdisable is also called from xadc_probe() to set the initial idle state, the wrong sequencer mode is active from the moment the driver loads.
The preenable path already uses xadc_get_seq_mode() which returns SIMULTANEOUS for dual mux. Fix postdisable to do the same.
--- drivers/iio/adc/xilinx-xadc-core.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/iio/adc/xilinx-xadc-core.c +9 -2
@@ -770,6 +770,7 @@ static int xadc_postdisable(struct iio_d {struct xadc *xadc =iio_priv (indio_dev);unsigned long scan_mask; +int seq_mode;int ret;int i;
@@ -777,6 +778,12 @@ static int xadc_postdisable(struct iio_dfor (i =0 ; i < indio_dev->num_channels; i++) scan_mask |=BIT (indio_dev->channels[i].scan_index); +/* +* Use the correct sequencer mode for the idle state: simultaneous +* mode for dual external mux configurations, continuous otherwise. +*/ + seq_mode =xadc_get_seq_mode (xadc, scan_mask); +/* Enable all channels and calibration */ ret =xadc_write_adc_reg (xadc,XADC_REG_SEQ (0 ), scan_mask &0xffff );if (ret)
@@ -787,11 +794,11 @@ static int xadc_postdisable(struct iio_dreturn ret; ret =xadc_update_adc_reg (xadc,XADC_REG_CONF1 ,XADC_CONF1_SEQ_MASK , -XADC_CONF1_SEQ_CONTINUOUS ); + seq_mode);if (ret)return ret; -return xadc_power_adc_b (xadc,XADC_CONF1_SEQ_CONTINUOUS ); +return xadc_power_adc_b (xadc, seq_mode); }static int xadc_preenable (struct iio_dev *indio_dev)
Greg Kroah-Hartman
maintainerPATCH 57/342 iio: dac: max5821: fix return value check in powerdown sync
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Salah Triki <[email protected]>
commit d0a228d903425e653f18a4341e60c0538afb6d41 upstream.
The function max5821_sync_powerdown_mode() returned the result of i2c_master_send() directly. If a partial transfer occurred, it would be incorrectly treated as a success by the caller.
While the caller currently handles the positive return value of 2 as success, this patch refactors the function to return 0 on full success and -EIO on short writes. This ensures robust error handling for incomplete transfers and improves code maintainability by using sizeof(outbuf).
--- drivers/iio/dac/max5821.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/iio/dac/max5821.c +8 -1
@@ -91,6 +91,7 @@ static int max5821_sync_powerdown_mode(s const struct iio_chan_spec *chan) {u8 outbuf[2 ]; +int ret; outbuf[0 ] =MAX5821_EXTENDED_COMMAND_MODE ;
@@ -104,7 +105,13 @@ static int max5821_sync_powerdown_mode(selse outbuf[1 ] |=MAX5821_EXTENDED_POWER_UP ; -return i2c_master_send (data->client, outbuf,2 ); + ret =i2c_master_send (data->client, outbuf,sizeof (outbuf)); +if (ret <0 ) +return ret; +if (ret !=sizeof (outbuf)) +return -EIO ; + +return 0 ; } static ssize_t max5821_write_dac_powerdown(struct iio_dev *indio_dev,
Greg Kroah-Hartman
maintainerPATCH 58/342 iio: dac: ad5686: fix input raw value check
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rodrigo Alencar <[email protected]>
commit d01220ee5e43c65a206df827b39bf5cf5f7b9dce upstream.
Fix range check for input raw value, which is off by one, i.e., for a 10-bit DAC the max valid value is 1023, but 1 << 10 equals 1024, which passes the previous check, allowing an out-of-range write. The issue exists since the ad5686 driver was first introduced.
--- drivers/iio/dac/ad5686.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/dac/ad5686.c +1 -1
@@ -154,7 +154,7 @@ static int ad5686_write_raw(struct iio_dswitch (mask) {case IIO_CHAN_INFO_RAW : -if (val > (1 << chan->scan_type.realbits) || val <0 ) +if (val >= (1 << chan->scan_type.realbits) || val <0 )return -EINVAL ;mutex_lock (&st->lock);
Greg Kroah-Hartman
maintainerPATCH 59/342 iio: adc: viperboard: Fix error handling in vprbrd_iio_read_raw
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Salah Triki <[email protected]>
commit 422b5bbf333f75fb486855ad0eedc23cf21f3277 upstream.
The driver proceeds to the reception phase even if the preceding transmission fails.
This uses a goto error label for an early bail out and ensures the mutex is properly unlocked in case of failure.
--- drivers/iio/adc/viperboard_adc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/iio/adc/viperboard_adc.c +3 -1
@@ -70,8 +70,10 @@ static int vprbrd_iio_read_raw(struct iiVPRBRD_USB_TYPE_OUT ,0x0000 ,0x0000 , admsg, sizeof(struct vprbrd_adc_msg), VPRBRD_USB_TIMEOUT_MS);if (ret !=sizeof (struct vprbrd_adc_msg )) { -dev_err (&iio_dev->dev,"usb send error on adc read\n" ); +mutex_unlock (&vb->lock); error = -EREMOTEIO ; +dev_err (&iio_dev->dev,"usb send error on adc read\n" ); + goto error; } ret = usb_control_msg(vb->usb_dev,
Greg Kroah-Hartman
maintainerPATCH 60/342 iio: gyro: itg3200: fix i2c read into the wrong stack location
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Carlier <[email protected]>
commit 6bdc3023d62ed5c7d591f0eb27a5adb37fb892ae upstream.
itg3200_read_all_channels() takes __be16 *buf' as a parameter and fills the i2c_msg destination as (char *)&buf'. Since buf' is the parameter (a pointer), &buf' is the address of the local pointer slot on the stack of itg3200_read_all_channels(), not the address of the caller's scan buffer. The (char *) cast hides the type mismatch.
i2c_transfer() therefore writes ITG3200_SCAN_ELEMENTS * sizeof(s16) = 8 bytes into the parameter's stack slot, which is discarded when the function returns. The caller's scan buffer in itg3200_trigger_handler() is never written to, so iio_push_to_buffers_with_timestamp() pushes uninitialised stack contents to userspace via /dev/iio:deviceX every scan -- both a functional bug (no actual gyroscope or temperature data is delivered through the triggered buffer) and an information leak.
The non-buffered read_raw() path is unaffected: it goes through itg3200_read_reg_s16() which uses `&out' on a local s16 value, where that is correct.
Drop the spurious `&' so the i2c read writes into the caller's buffer.
--- drivers/iio/gyro/itg3200_buffer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/gyro/itg3200_buffer.c +1 -1
@@ -34,7 +34,7 @@ static int itg3200_read_all_channels(str .addr = i2c->addr, .flags = i2c->flags | I2C_M_RD, .len = ITG3200_SCAN_ELEMENTS * sizeof(s16), - .buf = (char *)&buf, + .buf = (char *)buf, }, };
Greg Kroah-Hartman
maintainerPATCH 61/342 iio: ssp_sensors: cancel delayed work_refresh on remove
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sanjay Chitroda <[email protected]>
commit eedf7602fbd929e97e0c480da501dc7a34beb2a8 upstream.
The work_refresh may still be pending or running when the device is removed, cancel the delayed work_refresh in remove path.
--- drivers/iio/common/ssp_sensors/ssp_dev.c | 1 + 1 file changed, 1 insertion(+)
drivers/iio/common/ssp_sensors/ssp_dev.c +1 -0
@@ -602,6 +602,7 @@ static int ssp_remove(struct spi_devicessp_clean_pending_list (data);free_irq (data->spi->irq, data); +cancel_delayed_work_sync (&data->work_refresh);del_timer_sync (&data->wdt_timer);cancel_work_sync (&data->work_wdt);
Greg Kroah-Hartman
maintainerPATCH 62/342 iio: temperature: tsys01: fix broken PROM checksum validation
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Salah Triki <[email protected]>
commit 4701e471c16866e7aa8f5e6a3a6b0d31e097e2c9 upstream.
The current implementation of tsys01_crc_valid() incorrectly sums the first word (n_prom[0]) repeatedly instead of iterating over the 8 words retrieved from the PROM. This leads to a checksum mismatch and probe failure on hardware.
According to the TSYS01 datasheet, the PROM consists of 8 words. A valid check must iterate through all 8 words to verify the integrity of the calibration data. The current driver only checks the first word 8 times.
Note: This fix was identified during a code audit and is based on datasheet specifications. It has not been tested on real hardware.
--- drivers/iio/temperature/tsys01.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iio/temperature/tsys01.c +1 -1
@@ -119,7 +119,7 @@ static bool tsys01_crc_valid(u16 *n_promu8 sum =0 ;for (cnt =0 ; cnt <TSYS01_PROM_WORDS_NB ; cnt++) - sum += ((n_prom[0 ] >>8 ) + (n_prom[0 ] &0xFF )); + sum += ((n_prom[cnt] >>8 ) + (n_prom[cnt] &0xFF ));return (sum ==0 ); }
Greg Kroah-Hartman
maintainerPATCH 63/342 iio: light: cm3323: fix reg_conf not being initialized correctly
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aldo Conte <[email protected]>
commit 1f4f0bcc5255dec5c4c3a1551bf49d8c33b69b20 upstream.
The code stores the return value of i2c_smbus_write_word_data() in data->reg_conf; however, this value represents the result of the write operation and not the value actually written to the configuration register. This meant that the contents of data->reg_conf did not truly reflect the contents
of the hardware register.
Instead, save the value of the register before the write and use this value in the I2C write.
The bug was found by code inspection: i2c_smbus_write_word_data() returns 0 on success, not the value written to the register.
Tested using i2c-stub on a Raspberry Pi 3B running a custom 6.19.10 kernel. Before loading the driver, the configuration register 0x00 CM3323_CMD_CONF was populated with 0x0030 usingi2cset -y 11 0x10 0x00 0x0030 w, encoding an integration time of 320ms in bits[6:4].
Due to incorrect initialization of data->reg_conf in cm3323_init(), the print of integration_time returns 0.040000 instead of the expected 0.320000. This happens because the read of the integration_time depends on cm3323_get_it_bits() that is based on the value of data->reg_conf, which is erroneously set to 0.
With this fix applied, data->reg_conf correctly saves 0x0030 after init and the successive integration_time reports 0.320000 as expected.
--- drivers/iio/light/cm3323.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/iio/light/cm3323.c +2 -3
@@ -89,15 +89,14 @@ static int cm3323_init(struct iio_dev *i/* enable sensor and set auto force mode */ ret &= ~(CM3323_CONF_SD_BIT |CM3323_CONF_AF_BIT ); + data->reg_conf = ret; - ret =i2c_smbus_write_word_data (data->client,CM3323_CMD_CONF , ret); + ret =i2c_smbus_write_word_data (data->client,CM3323_CMD_CONF , data->reg_conf);if (ret <0 ) {dev_err (&data->client->dev,"Error writing reg_conf\n" );return ret; } - data->reg_conf = ret; -return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 64/342 iio: buffer: hw-consumer: fix use-after-free in error path
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Gu <[email protected]>
commit 6f5ed4f2c7c83f33344e0ba179f72a12e5dad4a4 upstream.
In the err_put_buffers cleanup path of iio_hw_consumer_alloc(), the code was using list_for_each_entry() to iterate through buffers while calling iio_buffer_put() which can free the current buffer if refcount drops to 0. The list_for_each_entry() loop macro then evaluates buf->head.next to continue iteration, accessing the freed buffer.
Fix this by using list_for_each_entry_safe().
--- drivers/iio/buffer/industrialio-hw-consumer.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/iio/buffer/industrialio-hw-consumer.c +2 -2
@@ -82,7 +82,7 @@ static struct hw_consumer_buffer *iio_hw*/ struct iio_hw_consumer *iio_hw_consumer_alloc (struct device *dev) { -struct hw_consumer_buffer *buf; +struct hw_consumer_buffer *buf, *tmp;struct iio_hw_consumer *hwc;struct iio_channel *chan;int ret;
@@ -113,7 +113,7 @@ struct iio_hw_consumer *iio_hw_consumer_return hwc; err_put_buffers: -list_for_each_entry (buf, &hwc->buffers, head) +list_for_each_entry_safe (buf, tmp, &hwc->buffers, head)iio_buffer_put (&buf->buffer);iio_channel_release_all (hwc->channels); err_free_hwc:
Greg Kroah-Hartman
maintainerPATCH 65/342 USB: serial: omninet: fix memory corruption with small endpoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 60df93d30f9bdd27db17c4d80ed80ef718d7226b upstream.
Make sure that the bulk-out buffers are at least as large as the hardcoded transfer size to avoid user-controlled slab corruption should a malicious device report a smaller endpoint max packet size than expected.
--- drivers/usb/serial/omninet.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/usb/serial/omninet.c +5 -4
@@ -30,6 +30,10 @@/* This one seems to be a re-branded ZyXEL device */ #define BT_IGNITIONPRO_ID 0x2000 +#define OMNINET_HEADERLEN 4 +#define OMNINET_BULKOUTSIZE 64 +#define OMNINET_PAYLOADSIZE (OMNINET_BULKOUTSIZE - OMNINET_HEADERLEN) +/* function prototypes */ static void omninet_process_read_urb (struct urb *urb); static int omninet_prepare_write_buffer(struct usb_serial_port *port,
@@ -55,6 +59,7 @@ static struct usb_serial_driver zyxel_om .description = "ZyXEL - omni.net lcd plus usb", .id_table = id_table, .num_bulk_out = 2, + .bulk_out_size = OMNINET_BULKOUTSIZE, .calc_num_ports = omninet_calc_num_ports, .port_probe = omninet_port_probe, .port_remove = omninet_port_remove,
@@ -133,10 +138,6 @@ static int omninet_port_remove(struct usreturn 0 ; } -#define OMNINET_HEADERLEN 4 -#define OMNINET_BULKOUTSIZE 64 -#define OMNINET_PAYLOADSIZE (OMNINET_BULKOUTSIZE - OMNINET_HEADERLEN) -static void omninet_process_read_urb (struct urb *urb) {struct usb_serial_port *port = urb->context;
Greg Kroah-Hartman
maintainerPATCH 66/342 usb: dwc2: Fix use after free in debug code
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
commit 9ea06a3fbf9f16e0d98c52cb3b99642be15ec281 upstream.
We're not allowed to dereference "urb" after calling usb_hcd_giveback_urb() so save the urb->status ahead of time.
--- drivers/usb/dwc2/hcd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/usb/dwc2/hcd.c +3 -1
@@ -4718,6 +4718,7 @@ static int _dwc2_hcd_urb_dequeue(structstruct dwc2_hsotg *hsotg =dwc2_hcd_to_hsotg (hcd);int rc;unsigned long flags; +int urb_status;dev_dbg (hsotg->dev,"DWC OTG HCD URB Dequeue\n" );dwc2_dump_urb_info (hcd, urb,"urb_dequeue" );
@@ -4742,11 +4743,12 @@ static int _dwc2_hcd_urb_dequeue(struct/* Higher layer software sets URB status */ spin_unlock (&hsotg->lock); + urb_status = urb->status;usb_hcd_giveback_urb (hcd, urb, status);spin_lock (&hsotg->lock);dev_dbg (hsotg->dev,"Called usb_hcd_giveback_urb()\n" ); -dev_dbg (hsotg->dev," urb->status = %d\n" , urb->status); +dev_dbg (hsotg->dev," urb->status = %d\n" , urb_status); out:spin_unlock_irqrestore (&hsotg->lock, flags);
Greg Kroah-Hartman
maintainerPATCH 67/342 Input: elan_i2c - validate firmware size before use
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit 76b0d0baa9ae9c60e726bbe1b6ff0bec2c993634 upstream.
Ensure that the firmware file is large enough to contain the expected number of pages and the signature (which resides at the end of the firmware blob) before accessing them to prevent potential out-of-bounds reads.
--- drivers/input/mouse/elan_i2c_core.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/input/mouse/elan_i2c_core.c +5 -0
@@ -608,6 +608,11 @@ static ssize_t elan_sysfs_update_fw(strureturn error; } +if (fw->size < data->fw_signature_address +sizeof (signature)) { +dev_err (dev,"firmware file too small\n" ); +return -EBADF ; + } +/* Firmware file must match signature data */ fw_signature = &fw->data[data->fw_signature_address];if (memcmp (fw_signature, signature,sizeof (signature)) !=0 ) {
Greg Kroah-Hartman
maintainerPATCH 68/342 wireguard: send: append trailer after expanding head
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason A. Donenfeld <[email protected]>
commit f75e3eb08fe31d30a9af6ed80cdd22e6772837e2 upstream.
With how this is currently written, we add the trailer, zero it out, and then add the header space on. If that header space requires a reallocation + copy, the zeros in the trailer aren't copied, because the skb len hasn't actually been yet expanded to cover that. Instead add the padding at the end of the process rather than at the beginning.
--- drivers/net/wireguard/send.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-)
drivers/net/wireguard/send.c +10 -10
@@ -177,16 +177,6 @@ static bool encrypt_packet(struct sk_buf trailer_len = padding_len +noise_encrypted_len (0 ); plaintext_len = skb->len + padding_len; -/* Expand data section to have room for padding and auth tag. */ - num_frags =skb_cow_data (skb, trailer_len, &trailer); -if (unlikely (num_frags <0 || num_frags >ARRAY_SIZE (sg))) -return false; - -/* Set the padding to zeros, and make sure it and the auth tag are part -* of the skb. -*/ -memset (skb_tail_pointer (trailer),0 , padding_len); -/* Expand head section to have room for our header and the network * stack's headers. */
@@ -198,6 +188,16 @@ static bool encrypt_packet(struct sk_buf skb_checksum_help(skb)))return false; +/* Expand data section to have room for padding and auth tag. */ + num_frags =skb_cow_data (skb, trailer_len, &trailer); +if (unlikely (num_frags <0 || num_frags >ARRAY_SIZE (sg))) +return false; + +/* Set the padding to zeros, and make sure it and the auth tag are part +* of the skb. +*/ +memset (skb_tail_pointer (trailer),0 , padding_len); +/* Only after checksumming can we safely add on the padding at the end * and the header. */
Greg Kroah-Hartman
maintainerPATCH 69/342 bpf: sockmap: fix tail fragment offset in bpf_msg_push_data
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuqi Xu <[email protected]>
commit f72eed9b84fb771019a955908132410a9ba9ea3f upstream.
When bpf_msg_push_data() inserts data in the middle of a scatterlist entry, it splits the original entry into a left fragment and a right fragment.
The right fragment offset is page-local, but the code advances it with start, which is the message-global insertion point. For inserts into a non-first SG entry, this over-advances the offset and leaves the split layout inconsistent.
Advance the right fragment offset by the fragment-local delta, start - offset, which matches the length removed from the front of the original entry.
--- net/core/filter.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/core/filter.c +1 -1
@@ -2845,7 +2845,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_ psge->length = start - offset; rsge.length -= psge->length; - rsge.offset += start; + rsge.offset += start - offset;sk_msg_iter_var_next (i);sg_unmark_end (psge);
Greg Kroah-Hartman
maintainerPATCH 70/342 macsec: fix replay protection at XPN lower-PN wrap
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junrui Luo <[email protected]>
commit e68842b3356471ba56c882209f324613dac47f64 upstream.
In macsec_post_decrypt(), when pn is U32_MAX, pn + 1 overflows u32 to 0 and the first branch never fires. If next_pn_halves.lower is also in the upper half, pn_same_half(pn, lower) is true and the XPN else-if does not fire either, leaving next_pn_halves unchanged. An attacker that captures the legitimate frame carrying pn == 0xFFFFFFFF on an XPN association can then replay it indefinitely, since lowest_pn never rises above the captured pn and macsec_decrypt() reconstructs the same IV.
Extend the XPN else-if to also fire when pn + 1 wraps to 0, so receipt of pn == U32_MAX advances next_pn_halves to (upper + 1, 0).
--- drivers/net/macsec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/macsec.c +2 -1
@@ -828,7 +828,8 @@ static bool macsec_post_decrypt(struct sif (pn +1 > rx_sa->next_pn_halves.lower) { rx_sa->next_pn_halves.lower = pn +1 ; }else if (secy->xpn && - !pn_same_half (pn, rx_sa->next_pn_halves.lower)) { + (pn +1 ==0 || + !pn_same_half (pn, rx_sa->next_pn_halves.lower))) { rx_sa->next_pn_halves.upper++; rx_sa->next_pn_halves.lower = pn +1 ; }
Greg Kroah-Hartman
maintainerPATCH 71/342 ipv6: exthdrs: refresh nh pointer after ipv6_hop_jumbo()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Justin Iurman <[email protected]>
commit d47548a36639095939f4747d4c43f2271366f565 upstream.
ipv6_hop_jumbo() calls pskb_trim_rcsum(), which can change skb pointers. Let's recompute nh pointer to make sure any change won't mess things up.
--- net/ipv6/exthdrs.c | 2 ++ 1 file changed, 2 insertions(+)
net/ipv6/exthdrs.c +2 -0
@@ -180,6 +180,8 @@ static bool ip6_parse_tlv(const struct tfunc(). */ if (curr->func (skb, off) == false)return false; + + nh =skb_network_header (skb);break ; } }
Greg Kroah-Hartman
maintainerPATCH 72/342 ASoC: qcom: q6asm-dai: fix error handling in prepare and set_params
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivas Kandagatla <[email protected]>
commit 4b4db09f283df65d780bc7cee66cb4a7e9bf4770 upstream.
Fix error handling in q6asm_dai_compr_set_params() and q6asm_dai_prepare() for both CMD_CLOSE and q6asm_unmap_memory_regions().
In both the functions, we are doing q6asm_audio_client_free in failure cases, which means if prepare or set_params fail, we can never recover. Now open and close are done in respective dai_open/close functions.
--- sound/soc/qcom/qdsp6/q6asm-dai.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-)
sound/soc/qcom/qdsp6/q6asm-dai.c +16 -8
@@ -239,9 +239,19 @@ static int q6asm_dai_prepare(struct snd_/* rate and channels are sent to audio driver */ if (prtd->state ==Q6ASM_STREAM_RUNNING ) {/* clear the previous setup if any */ -q6asm_cmd (prtd->audio_client, prtd->stream_id,CMD_CLOSE ); -q6asm_unmap_memory_regions (substream->stream, - prtd->audio_client); + ret =q6asm_cmd (prtd->audio_client, prtd->stream_id,CMD_CLOSE ); +if (ret <0 ) { +dev_err (dev,"Failed to close q6asm stream %d\n" , prtd->stream_id); +return ret; + } + + ret =q6asm_unmap_memory_regions (substream->stream, prtd->audio_client); +if (ret <0 ) { +dev_err (dev,"Failed to unmap memory regions for q6asm stream %d\n" , + prtd->stream_id); +return ret; + } +q6routing_stream_close (soc_prtd->dai_link->id, substream->stream); prtd->state =Q6ASM_STREAM_STOPPED ;
@@ -309,8 +319,6 @@ routing_err:q6asm_cmd (prtd->audio_client, prtd->stream_id,CMD_CLOSE ); open_err:q6asm_unmap_memory_regions (substream->stream, prtd->audio_client); -q6asm_audio_client_free (prtd->audio_client); - prtd->audio_client =NULL ;return ret; }
@@ -926,7 +934,7 @@ static int q6asm_dai_compr_set_params(st prtd->session_id, dir);if (ret) {dev_err (dev,"Stream reg failed ret:%d\n" , ret); - goto q6_err; + goto routing_err; } ret = __q6asm_dai_compr_set_codec_params(component, stream,
@@ -952,11 +960,11 @@ static int q6asm_dai_compr_set_params(streturn 0 ; q6_err: +q6routing_stream_close (rtd->dai_link->id, dir); +routing_err:q6asm_cmd (prtd->audio_client, prtd->stream_id,CMD_CLOSE ); open_err: -q6asm_audio_client_free (prtd->audio_client); - prtd->audio_client =NULL ;return ret; }
Greg Kroah-Hartman
maintainerPATCH 73/342 ip6: vti: Use ip6_tnl.net in vti6_siocdevprivate().
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maoyi Xie <[email protected]>
commit 8b484efd5cb4eeef9021a661e198edc5349dacf6 upstream.
After patch 1/2 in this series, vti6_update() unlinks and relinks the tunnel through t->net. vti6_siocdevprivate() still uses dev_net(dev) for the collision lookup. For a tunnel moved through IFLA_NET_NS_FD, dev_net(dev) is the new netns, not t->net.
SIOCCHGTUNNEL on a migrated tunnel then runs:
net = dev_net(dev) /* migrated netns */
t = vti6_locate(net, &p1, false) /* misses target in t->net */
...
t = netdev_priv(dev)
vti6_update(t, &p1, false) /* mutates t->net's hash */
A caller in the migrated netns picks params that match a tunnel in the creation netns. The lookup in dev_net(dev) finds nothing. vti6_update() prepends the migrated tunnel at the head of the creation netns hash bucket for those params. Later lookups in the creation netns resolve to the migrated device. xfrm receive delivers the matched packets through a device the caller controls.
Reachable from an unprivileged user namespace (unshare --user --map-root-user --net). Cross tenant scope on container hosts.
Switch the SIOCCHGTUNNEL path on a non fallback device to use t->net for the lookup. The lookup now matches the netns vti6_update() operates on.
Also add ns_capable(self->net->user_ns, CAP_NET_ADMIN) before the lookup. The check at the top of the case is against dev_net(dev)->user_ns, which after migration is the attacker's netns. A caller there can pick params absent from self->net, the lookup returns NULL, t becomes self, and vti6_update() inserts the device into the creation netns hash. The new check requires CAP_NET_ADMIN in the creation netns user_ns too.
SIOCADDTUNNEL and SIOCCHGTUNNEL on the fallback device keep dev_net(dev), which equals init_net there.
--- net/ipv6/ip6_vti.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
net/ipv6/ip6_vti.c +9 -2
@@ -836,17 +836,24 @@ vti6_ioctl(struct net_device *dev, strucif (p.proto !=IPPROTO_IPV6 && p.proto !=0 )break ;vti6_parm_from_user (&p1, &p); - t =vti6_locate (net, &p1, cmd ==SIOCADDTUNNEL );if (dev != ip6n->fb_tnl_dev && cmd ==SIOCCHGTUNNEL ) { +struct ip6_tnl *self =netdev_priv (dev); + + err = -EPERM ; +if (!ns_capable (self->net->user_ns,CAP_NET_ADMIN )) +break ; + t =vti6_locate (self->net, &p1, false);if (t) {if (t->dev != dev) { err = -EEXIST ;break ; } }else - t =netdev_priv (dev); + t = self; err =vti6_update (t, &p1, false); + }else { + t =vti6_locate (net, &p1, cmd ==SIOCADDTUNNEL ); }if (t) { err =0 ;
Greg Kroah-Hartman
maintainerPATCH 74/342 ipv6: validate extension header length before copying to cmsg
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qi Tang <[email protected]>
commit dd433671fef381fdaf7b530c631e6b782d66e224 upstream.
ip6_datagram_recv_specific_ctl() builds IPV6_{HOPOPTS,DSTOPTS,RTHDR} cmsgs (and their IPV6_2292* legacy counterparts) by trusting the on-wire hdrlen byte (ptr[1]) when computing the put_cmsg() length. The length was validated only at parse time (ipv6_parse_hopopts(), etc.). An nftables payload-write expression can rewrite hdrlen after parsing and before the skb reaches recvmsg; the write itself is in-bounds but put_cmsg() then reads up to ((hdrlen+1) << 3) = 2040 bytes from an 8-byte header. nftables is reachable from an unprivileged user namespace, so this is an unprivileged slab-out-of-bounds read:
BUG: KASAN: slab-out-of-bounds in put_cmsg+0x3ac/0x540 put_cmsg+0x3ac/0x540 udpv6_recvmsg+0xca0/0x1250 sock_recvmsg+0xdf/0x190 ____sys_recvmsg+0x1b1/0x620
Add ipv6_get_exthdr_len() which validates that at least two bytes are accessible before reading the hdrlen field, then checks the computed length against skb_tail_pointer(skb), returning 0 on failure. Extension headers are kept in the linear skb area by pskb_may_pull() during input, so skb_tail_pointer() is the correct bound.
Use ipv6_get_exthdr_len() at all non-AH call sites: the five standalone cmsg blocks (HbH, 2292HbH, 2292DSTOPTS x2, 2292RTHDR) and the three standard cases in the extension-header walk loop (DSTOPTS, ROUTING, default). AH retains an inline bounds check because its length formula differs ((ptr[1]+2)<<2).
The walk loop also gets a pre-read bounds check at the top to validate ptr before any case accesses ptr[0] or ptr[1].
When the walk loop detects a corrupted header, return from the function instead of continuing to process later socket options.
--- net/ipv6/datagram.c | 54 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 8 deletions(-)
net/ipv6/datagram.c +46 -8
@@ -611,6 +611,18 @@ void ip6_datagram_recv_common_ctl(struct } } +static u16 ipv6_get_exthdr_len (const struct sk_buff *skb,const u8 *ptr) +{ +u16 len; + +if (ptr +2 >skb_tail_pointer (skb)) +return 0 ; + + len = (ptr[1 ] +1 ) <<3 ; + +return (len <=skb_tail_pointer (skb) - ptr) ? len :0 ; +} +void ip6_datagram_recv_specific_ctl (struct sock *sk,struct msghdr *msg,struct sk_buff *skb) {
@@ -637,7 +649,10 @@ void ip6_datagram_recv_specific_ctl(stru/* HbH is allowed only once */ if (np->rxopt.bits.hopopts && (opt->flags &IP6SKB_HOPBYHOP )) {u8 *ptr = nh +sizeof (struct ipv6hdr ); -put_cmsg (msg,SOL_IPV6 ,IPV6_HOPOPTS , (ptr[1 ]+1 )<<3 , ptr); +u16 len =ipv6_get_exthdr_len (skb, ptr); + +if (len) +put_cmsg (msg,SOL_IPV6 ,IPV6_HOPOPTS , len, ptr); } if (opt->lastopt &&
@@ -658,26 +673,37 @@ void ip6_datagram_recv_specific_ctl(struunsigned int len;u8 *ptr = nh + off; +if (ptr +2 >skb_tail_pointer (skb)) +return ; +switch (nexthdr) {case IPPROTO_DSTOPTS : nexthdr = ptr[0 ]; - len = (ptr[1 ] +1 ) <<3 ; + len =ipv6_get_exthdr_len (skb, ptr); +if (!len) +return ;if (np->rxopt.bits.dstopts)put_cmsg (msg,SOL_IPV6 ,IPV6_DSTOPTS , len, ptr);break ;case IPPROTO_ROUTING : nexthdr = ptr[0 ]; - len = (ptr[1 ] +1 ) <<3 ; + len =ipv6_get_exthdr_len (skb, ptr); +if (!len) +return ;if (np->rxopt.bits.srcrt)put_cmsg (msg,SOL_IPV6 ,IPV6_RTHDR , len, ptr);break ;case IPPROTO_AH : nexthdr = ptr[0 ]; len = (ptr[1 ] +2 ) <<2 ; +if (ptr + len >skb_tail_pointer (skb)) +return ;break ;default : nexthdr = ptr[0 ]; - len = (ptr[1 ] +1 ) <<3 ; + len =ipv6_get_exthdr_len (skb, ptr); +if (!len) +return ;break ; }
@@ -699,19 +725,31 @@ void ip6_datagram_recv_specific_ctl(stru }if (np->rxopt.bits.ohopopts && (opt->flags &IP6SKB_HOPBYHOP )) {u8 *ptr = nh +sizeof (struct ipv6hdr ); -put_cmsg (msg,SOL_IPV6 ,IPV6_2292HOPOPTS , (ptr[1 ]+1 )<<3 , ptr); +u16 len =ipv6_get_exthdr_len (skb, ptr); + +if (len) +put_cmsg (msg,SOL_IPV6 ,IPV6_2292HOPOPTS , len, ptr); }if (np->rxopt.bits.odstopts && opt->dst0) {u8 *ptr = nh + opt->dst0; -put_cmsg (msg,SOL_IPV6 ,IPV6_2292DSTOPTS , (ptr[1 ]+1 )<<3 , ptr); +u16 len =ipv6_get_exthdr_len (skb, ptr); + +if (len) +put_cmsg (msg,SOL_IPV6 ,IPV6_2292DSTOPTS , len, ptr); }if (np->rxopt.bits.osrcrt && opt->srcrt) {struct ipv6_rt_hdr *rthdr = (struct ipv6_rt_hdr *)(nh + opt->srcrt); -put_cmsg (msg,SOL_IPV6 ,IPV6_2292RTHDR , (rthdr->hdrlen+1 ) <<3 , rthdr); +u16 len =ipv6_get_exthdr_len (skb, (u8 *)rthdr); + +if (len) +put_cmsg (msg,SOL_IPV6 ,IPV6_2292RTHDR , len, rthdr); }if (np->rxopt.bits.odstopts && opt->dst1) {u8 *ptr = nh + opt->dst1; -put_cmsg (msg,SOL_IPV6 ,IPV6_2292DSTOPTS , (ptr[1 ]+1 )<<3 , ptr); +u16 len =ipv6_get_exthdr_len (skb, ptr); + +if (len) +put_cmsg (msg,SOL_IPV6 ,IPV6_2292DSTOPTS , len, ptr); }if (np->rxopt.bits.rxorigdstaddr) {struct sockaddr_in6 sin6;
Greg Kroah-Hartman
maintainerPATCH 75/342 ip6: vti: Use ip6_tnl.net in vti6_changelink().
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
commit 11b326fb0a374f4654f9be22d0f0f7abd9f7d3fe upstream.
ip netns add ns1
ip netns add ns2
ip -n ns1 link add vti6_test type vti6 remote ::1 local ::2 key 7 ip -n ns1 link set vti6_test netns ns2
ip -n ns2 link set vti6_test type vti6 remote ::3 local ::4 key 9 ip netns del ns2
ip netns del ns1
[ 132.495484] ------------[ cut here ]------------ [ 132.497609] kernel BUG at net/core/dev.c:12376!
Commit 61220ab34948 ("vti6: Enable namespace changing") dropped NETIF_F_NETNS_LOCAL from vti6 devices. A vti6 tunnel can then move through IFLA_NET_NS_FD. After the move dev_net(dev) points at the new netns while t->net stays at the creation netns.
vti6_changelink() and vti6_update() still use dev_net(dev) and dev_net(t->dev). They unlink from one per netns hash and relink into another. The creation netns is left with a stale entry. cleanup_net() of that netns later walks freed memory.
Reachable from an unprivileged user namespace (unshare --user --map-root-user --net). Cross tenant scope on container hosts.
--- net/ipv6/ip6_vti.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-)
net/ipv6/ip6_vti.c +7 -5
@@ -725,10 +725,11 @@ vti6_tnl_change(struct ip6_tnl *t, conststatic int vti6_update (struct ip6_tnl *t,struct __ip6_tnl_parm *p,bool keep_mtu) { -struct net *net =dev_net (t->dev); -struct vti6_net *ip6n =net_generic (net, vti6_net_id); +struct net *net = t->net; +struct vti6_net *ip6n;int err; + ip6n =net_generic (net, vti6_net_id);vti6_tnl_unlink (ip6n, t);synchronize_net (); err =vti6_tnl_change (t, p, keep_mtu);
@@ -1040,11 +1041,12 @@ static int vti6_changelink(struct net_destruct nlattr *data[], struct netlink_ext_ack *extack) { - struct ip6_tnl *t; + struct ip6_tnl *t = netdev_priv(dev); +struct net *net = t->net;struct __ip6_tnl_parm p; -struct net *net =dev_net (dev); -struct vti6_net *ip6n =net_generic (net, vti6_net_id); +struct vti6_net *ip6n; + ip6n =net_generic (net, vti6_net_id);if (dev == ip6n->fb_tnl_dev)return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 76/342 HID: wacom: Fix OOB write in wacom_hid_set_device_mode()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lee Jones <[email protected]>
commit c0a8899e02ddebd51e2589835182c239c2e224ae upstream.
wacom_hid_set_device_mode() currently assumes that the HID_DG_INPUTMODE usage is always located in the first field (field[0]) of the feature report. However, a device can specify HID_DG_INPUTMODE in a different field.
If HID_DG_INPUTMODE is in a field other than the first one and the first field has a report_count smaller than the usage_index of HID_DG_INPUTMODE, this leads to an out-of-bounds write to r->field[0]->value.
Fix this by storing the field index of HID_DG_INPUTMODE in 'struct hid_data' during feature mapping. In wacom_hid_set_device_mode(), use this stored field index to access the correct field and add bounds checks to ensure both the field index and the value index are within valid ranges before writing.
--- drivers/hid/wacom_sys.c | 13 ++++++++++--- drivers/hid/wacom_wac.h | 1 + 2 files changed, 11 insertions(+), 3 deletions(-)
drivers/hid/wacom_sys.c +10 -3
@@ -346,6 +346,7 @@ static void wacom_feature_mapping(struct hid_data->inputmode = field->report->id; hid_data->inputmode_index = usage->usage_index; + hid_data->inputmode_field_index = field->index;break ;case HID_UP_DIGITIZER :
@@ -561,9 +562,14 @@ static int wacom_hid_set_device_mode(str re = &(hdev->report_enum[HID_FEATURE_REPORT ]); r = re->report_id_hash[hid_data->inputmode]; -if (r) { - r->field[0 ]->value[hid_data->inputmode_index] =2 ; -hid_hw_request (hdev, r,HID_REQ_SET_REPORT ); +if (r && hid_data->inputmode_field_index >=0 && + hid_data->inputmode_field_index < r->maxfield) { +struct hid_field *field = r->field[hid_data->inputmode_field_index]; + +if (field && hid_data->inputmode_index < field->report_count) { + field->value[hid_data->inputmode_index] =2 ; +hid_hw_request (hdev, r,HID_REQ_SET_REPORT ); + } }return 0 ; }
@@ -2815,6 +2821,7 @@ static int wacom_probe(struct hid_devicereturn error; wacom_wac->hid_data.inputmode =-1 ; + wacom_wac->hid_data.inputmode_field_index =-1 ; wacom_wac->mode_report =-1 ;if (hid_is_usb (hdev)) {
drivers/hid/wacom_wac.h +1 -0
@@ -296,6 +296,7 @@ struct wacom_shared {struct hid_data {__s16 inputmode;/* InputMode HID feature, -1 if non-existent */ __s16 inputmode_index;/* InputMode HID feature index in the report */ +__s16 inputmode_field_index;/* InputMode HID feature field index in the report */ bool sense_state;bool inrange_state;bool invert_state;
Greg Kroah-Hartman
maintainerPATCH 77/342 iommu, debugobjects: avoid gcc-16.1 section mismatch warnings
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
commit 4c9ad387aa2d6785299722e54224d34764edaeb3 upstream.
gcc-16 has gained some more advanced inter-procedual optimization techniques that enable it to inline the dummy_tlb_add_page() and dummy_tlb_flush() function pointers into a specialized version of __arm_v7s_unmap:
WARNING: modpost: vmlinux: section mismatch in reference: __arm_v7s_unmap+0x2cc (section: .text) -> dummy_tlb_add_page (section: .init.text)
ERROR: modpost: Section mismatches detected.
Quoted 1 line
From what I can tell, the transformation is correct, as this is only
called when __arm_v7s_unmap() is called from arm_v7s_do_selftests(), which is also __init. Since __arm_v7s_unmap() however is not __init, gcc cannot inline the inner function calls directly.
In debug_objects_selftest(), the same thing happens. Both the caller and the leaf function are __init, but the IPA pulls it into a non-init one:
WARNING: modpost: vmlinux: section mismatch in reference: lookup_object_or_alloc+0x7c (section: .text.lookup_object_or_alloc) -> is_static_object (section: .init.text)
Marking the affected functions as not "__init" would reliably avoid this issue but is not a good solution because it removes an otherwise correct annotation. I tried marking the functions as 'noinline', but that ended up not covering all the affected configurations.
With some more experimenting, I found that marking these functions as __attribute__((noipa)) is both logical and reliable.
In order to keep the syntax readable, add a custom macro for this in include/linux/compiler_attributes.h next to other related macros and use it to annotate both files.
--- drivers/iommu/io-pgtable-arm-v7s.c | 18 ++++++++++++------ include/linux/compiler_attributes.h | 11 +++++++++++ lib/debugobjects.c | 2 +- 3 files changed, 24 insertions(+), 7 deletions(-)
drivers/iommu/io-pgtable-arm-v7s.c +12 -6
@@ -848,21 +848,27 @@ struct io_pgtable_init_fns io_pgtable_arstatic struct io_pgtable_cfg *cfg_cookie__initdata ; -static void __init dummy_tlb_flush_all (void *cookie) +/* +* __noipa prevents gcc from turning indirect iommu_flush_ops calls +* into direct calls from a specialized __arm_v7s_unmap() that triggers +* a build time section mismatch assertion. +*/ +static __noipa void __init dummy_tlb_flush_all(void *cookie) {WARN_ON (cookie != cfg_cookie); } -static void __init dummy_tlb_flush (unsigned long iova,size_t size, -size_t granule,void *cookie) +static __noipa void __init dummy_tlb_flush(unsigned long iova, size_t size, +size_t granule,void *cookie) {WARN_ON (cookie != cfg_cookie);WARN_ON (!(size & cfg_cookie->pgsize_bitmap)); } -static void __init dummy_tlb_add_page (struct iommu_iotlb_gather *gather, -unsigned long iova,size_t granule, -void *cookie) +static __noipa void __init dummy_tlb_add_page(struct iommu_iotlb_gather *gather, +unsigned long iova, +size_t granule, +void *cookie) {dummy_tlb_flush (iova, granule, granule, cookie); }
include/linux/compiler_attributes.h +11 -0
@@ -316,6 +316,17 @@#endif /* +* Optional: not supported by clang +* +* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Attributes.html#index-noipa +*/ +#if __has_attribute (noipa) +# define __noipa __attribute__((noipa)) +#else +# define __noipa +#endif + +/* * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-weak-function-attribute * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-weak-variable-attribute */
lib/debugobjects.c +1 -1
@@ -1068,7 +1068,7 @@ struct self_test {static __initconst const struct debug_obj_descr descr_type_test; -static bool __init is_static_object (void *addr) +static __noipa bool __init is_static_object(void *addr) {struct self_test *obj = addr;
Greg Kroah-Hartman
maintainerPATCH 78/342 nfc: hci: fix out-of-bounds read in HCP header parsing
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ashutosh Desai <[email protected]>
commit f040e590c035bfd9553fe79ee9585caf1b14d67b upstream.
Both nfc_hci_recv_from_llc() and nci_hci_data_received_cb() read packet->header from skb->data at function entry without first checking that the buffer holds at least one byte. A malicious NFC peer can send a 0-byte HCP frame that passes through the SHDLC layer and reaches these functions, causing an out-of-bounds heap read of packet->header. The same 0-byte frame, if queued as a non-final fragment, also causes the reassembly loop to underflow msg_len to UINT_MAX, triggering skb_over_panic() when the reassembled skb is written.
Fix this by adding a pskb_may_pull() check at the entry of each function before packet->header is first accessed. The existing pskb_may_pull() checks before the reassembled hcp_skb is cast to struct hcp_packet remain in place to guard the 2-byte HCP message header.
--- net/nfc/hci/core.c | 10 ++++++++++ net/nfc/nci/hci.c | 10 ++++++++++ 2 files changed, 20 insertions(+)
net/nfc/hci/core.c +10 -0
@@ -861,6 +861,11 @@ static void nfc_hci_recv_from_llc(structstruct sk_buff *frag_skb;int msg_len; +if (!pskb_may_pull (skb,NFC_HCI_HCP_PACKET_HEADER_LEN )) { +kfree_skb (skb); +return ; + } + packet = (struct hcp_packet *)skb->data;if ((packet->header & ~NFC_HCI_FRAGMENT ) ==0 ) {skb_queue_tail (&hdev->rx_hcp_frags, skb);
@@ -904,6 +909,11 @@ static void nfc_hci_recv_from_llc(struct* unblock waiting cmd context. Otherwise, enqueue to dispatch * in separate context where handler can also execute command. */ +if (!pskb_may_pull (hcp_skb,NFC_HCI_HCP_HEADER_LEN )) { +kfree_skb (hcp_skb); +return ; + } + packet = (struct hcp_packet *)hcp_skb->data; type =HCP_MSG_GET_TYPE (packet->message.header);if (type ==NFC_HCI_HCP_RESPONSE ) {
net/nfc/nci/hci.c +10 -0
@@ -444,6 +444,11 @@ void nci_hci_data_received_cb(void *contreturn ; } +if (!pskb_may_pull (skb,NCI_HCI_HCP_PACKET_HEADER_LEN )) { +kfree_skb (skb); +return ; + } + packet = (struct nci_hcp_packet *)skb->data;if ((packet->header & ~NCI_HCI_FRAGMENT ) ==0 ) {skb_queue_tail (&ndev->hci_dev->rx_hcp_frags, skb);
@@ -487,6 +492,11 @@ void nci_hci_data_received_cb(void *cont* unblock waiting cmd context. Otherwise, enqueue to dispatch * in separate context where handler can also execute command. */ +if (!pskb_may_pull (hcp_skb,NCI_HCI_HCP_HEADER_LEN )) { +kfree_skb (hcp_skb); +return ; + } + packet = (struct nci_hcp_packet *)hcp_skb->data; type =NCI_HCP_MSG_GET_TYPE (packet->message.header);if (type ==NCI_HCI_HCP_RESPONSE ) {
Greg Kroah-Hartman
maintainerPATCH 79/342 xfrm: route MIGRATE notifications to callers netns
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maoyi Xie <[email protected]>
commit 7e2a4f7ca0952820731ef7bdadfc9a9e9d3571b4 upstream.
xfrm_send_migrate() in net/xfrm/xfrm_user.c and pfkey_send_migrate() in net/key/af_key.c both hardcode &init_net for the multicast that announces a successful XFRM_MSG_MIGRATE / SADB_X_MIGRATE.
XFRM_MSG_MIGRATE arrives on a per-netns NETLINK_XFRM socket, and the rest of the xfrm/af_key netlink path was made netns-aware in 2008. The other 14 multicast paths in xfrm_user.c route their event using xs_net(x), xp_net(xp) or sock_net(skb->sk); only the migrate path was missed.
Two consequences of the init_net hardcoding:
1. The notification (selector, old/new endpoint addresses, and the km_address) is delivered to listeners on init_net's XFRMNLGRP_MIGRATE / pfkey BROADCAST_ALL groups rather than on the issuing netns. An IKE daemon running in init_net therefore receives migration notifications originating from any other netns on the host.
2. An IKE daemon running inside a non-init netns and subscribed to its own XFRMNLGRP_MIGRATE / pfkey groups never receives the notification of its own migration. IKEv2 MOBIKE / address-update handling inside a netns is silently broken.
Thread struct net through km_migrate() and the xfrm_mgr.migrate function pointer, drop the &init_net override in xfrm_send_migrate() and pfkey_send_migrate(), and pass the caller's net (already in scope in xfrm_migrate() via sock_net(skb->sk)) all the way down. struct xfrm_mgr is in-tree only and not exported as a stable API, so the function-pointer signature change is internal.
pfkey_broadcast() is already netns-aware via net_generic(net, pfkey_net_id) since the pernet conversion. The five other pfkey_broadcast() callers in af_key.c already pass xs_net(x), sock_net(sk) or a per-netns net, so this only removes the &init_net outlier.
--- include/net/xfrm.h | 3 ++- net/key/af_key.c | 6 +++--- net/xfrm/xfrm_policy.c | 2 +- net/xfrm/xfrm_state.c | 4 ++-- net/xfrm/xfrm_user.c | 5 ++--- 5 files changed, 10 insertions(+), 10 deletions(-)
include/net/xfrm.h +2 -1
@@ -593,6 +593,7 @@ struct xfrm_mgr {const struct xfrm_migrate *m, int num_bundles, const struct xfrm_kmaddress *k, + struct net *net, const struct xfrm_encap_tmpl *encap);bool (*is_alive)(const struct km_event *c); };
@@ -1697,7 +1698,7 @@ int xfrm_sk_policy_insert(struct sock *s#ifdef CONFIG_XFRM_MIGRATE int km_migrate (const struct xfrm_selector *sel,u8 dir,u8 type,const struct xfrm_migrate *m,int num_bundles, -const struct xfrm_kmaddress *k, +const struct xfrm_kmaddress *k,struct net *net,const struct xfrm_encap_tmpl *encap);struct xfrm_state *xfrm_migrate_state_find (struct xfrm_migrate *m,struct net *net,u32 if_id);
net/key/af_key.c +3 -3
@@ -3552,7 +3552,7 @@ static int set_ipsecrequest(struct sk_bu#ifdef CONFIG_NET_KEY_MIGRATE static int pfkey_send_migrate (const struct xfrm_selector *sel,u8 dir,u8 type,const struct xfrm_migrate *m,int num_bundles, -const struct xfrm_kmaddress *k, +const struct xfrm_kmaddress *k,struct net *net,const struct xfrm_encap_tmpl *encap) {int i;
@@ -3657,7 +3657,7 @@ static int pfkey_send_migrate(const stru }/* broadcast migrate message to sockets */ -pfkey_broadcast (skb,GFP_ATOMIC ,BROADCAST_ALL ,NULL , &init_net); +pfkey_broadcast (skb,GFP_ATOMIC ,BROADCAST_ALL ,NULL , net);return 0 ;
@@ -3668,7 +3668,7 @@ err:#else static int pfkey_send_migrate (const struct xfrm_selector *sel,u8 dir,u8 type,const struct xfrm_migrate *m,int num_bundles, -const struct xfrm_kmaddress *k, +const struct xfrm_kmaddress *k,struct net *net,const struct xfrm_encap_tmpl *encap) {return -ENOPROTOOPT ;
net/xfrm/xfrm_policy.c +1 -1
@@ -4532,7 +4532,7 @@ int xfrm_migrate(const struct xfrm_selec }/* Stage 5 - announce */ -km_migrate (sel, dir, type, m, num_migrate, k, encap); +km_migrate (sel, dir, type, m, num_migrate, k, net, encap);xfrm_pol_put (pol);
net/xfrm/xfrm_state.c +2 -2
@@ -2270,7 +2270,7 @@ EXPORT_SYMBOL(km_policy_expired);#ifdef CONFIG_XFRM_MIGRATE int km_migrate (const struct xfrm_selector *sel,u8 dir,u8 type,const struct xfrm_migrate *m,int num_migrate, -const struct xfrm_kmaddress *k, +const struct xfrm_kmaddress *k,struct net *net,const struct xfrm_encap_tmpl *encap) {int err = -EINVAL ;
@@ -2281,7 +2281,7 @@ int km_migrate(const struct xfrm_selectolist_for_each_entry_rcu (km, &xfrm_km_list, list) {if (km->migrate) { ret = km->migrate (sel, dir, type, m, num_migrate, k, - encap); + net, encap);if (!ret) err = ret; }
net/xfrm/xfrm_user.c +2 -3
@@ -2675,10 +2675,9 @@ out_cancel:static int xfrm_send_migrate (const struct xfrm_selector *sel,u8 dir,u8 type,const struct xfrm_migrate *m,int num_migrate, -const struct xfrm_kmaddress *k, +const struct xfrm_kmaddress *k,struct net *net,const struct xfrm_encap_tmpl *encap) { -struct net *net = &init_net;struct sk_buff *skb;int err;
@@ -2696,7 +2695,7 @@ static int xfrm_send_migrate(const struc#else static int xfrm_send_migrate (const struct xfrm_selector *sel,u8 dir,u8 type,const struct xfrm_migrate *m,int num_migrate, -const struct xfrm_kmaddress *k, +const struct xfrm_kmaddress *k,struct net *net,const struct xfrm_encap_tmpl *encap) {return -ENOPROTOOPT ;
Greg Kroah-Hartman
maintainerPATCH 80/342 xfrm: ah: use skb_to_full_sk in async output callbacks
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 79d8be262377f7112cfa3088dfc4142d5a2533f3 upstream.
When AH output is offloaded to an asynchronous crypto provider (hardware accelerators such as AMD CCP, or a forced-async software shim used for testing), the digest completion fires ah_output_done() / ah6_output_done() on a workqueue. The egress skb at that point may have been originated by a TCP listener sending a SYN-ACK, which sets skb->sk to a request_sock via skb_set_owner_edemux(); it may also have been originated by an inet_timewait_sock retransmit. Neither is a full struct sock, and passing the raw skb->sk to xfrm_output_resume() then forwards a non-full socket through the rest of the xfrm output chain.
xfrm_output_resume() and its downstream consumers expect a full sk where they dereference at all. The natural egress path through ah_output_done() does not crash today because the consumers that read past sock_common are either gated by sk_fullsock() or short-circuit on flags that are clear on a fresh request_sock; an exhaustive walk of the 50 most plausible consumers under sch_fq, dev_queue_xmit, netfilter, tc-egress and cgroup-egress BPF found no current unguarded deref. The bug is still a real type confusion that future consumer changes could turn into a memory-corruption primitive.
This is the same bug class fixed for ESP in commit 1620c88887b1 ("xfrm: Fix the usage of skb->sk"). Apply the analogous fix to
AH: convert skb->sk to a full socket pointer (or NULL) via skb_to_full_sk() before handing it to xfrm_output_resume().
The same async AH callbacks were touched recently for an independent ESN-related ICV layout bug in commit ec54093e6a8f ("xfrm: ah: account for ESN high bits in async callbacks"); the sk type-confusion addressed here is orthogonal. This patch is part of an ongoing audit of the AH callback paths; an ah_output ihl-validation hardening series is also currently under review on netdev.
Reproduced under UML + KASAN + lockdep with a forced-async hmac(sha1) shim that registers at priority 9999 and wraps the sync in-tree hmac-sha1-lib. With the shim loaded, ah_output_done runs on every SYN-ACK egress through a transport-mode AH SA and skb->sk arrives as a request_sock (TCP_NEW_SYN_RECV); after this patch, xfrm_output_resume() receives the listener (the result of sk_to_full_sk()) and consumer derefs land on full-sock fields as intended.
--- net/ipv4/ah4.c | 2 +- net/ipv6/ah6.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
net/ipv4/ah4.c +1 -1
@@ -141,7 +141,7 @@ static void ah_output_done(struct crypto }kfree (AH_SKB_CB (skb)->tmp); -xfrm_output_resume (skb->sk, skb, err); +xfrm_output_resume (skb_to_full_sk (skb), skb, err); }static int ah_output (struct xfrm_state *x,struct sk_buff *skb)
net/ipv6/ah6.c +1 -1
@@ -338,7 +338,7 @@ static void ah6_output_done(struct cryptah6_restore_hdrs (top_iph, iph_ext, extlen);kfree (AH_SKB_CB (skb)->tmp); -xfrm_output_resume (skb->sk, skb, err); +xfrm_output_resume (skb_to_full_sk (skb), skb, err); }static int ah6_output (struct xfrm_state *x,struct sk_buff *skb)
Greg Kroah-Hartman
maintainerPATCH 81/342 netfilter: conntrack: tcp: do not force CLOSE on invalid-seq RST without direction check
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hamza Mahfooz <[email protected]>
commit bed6e04be8e6b9133d8b16d5a42d0e0ce674fa9a upstream.
An unintended behavior in the TCP conntrack state machine allows a connection to be forced into the CLOSE state using an RST packet with an invalid sequence number.
Specifically, after a SYN packet is observed, an RST with an invalid SEQ can transition the conntrack entry to TCP_CONNTRACK_CLOSE, regardless of whether the RST corresponds to the expected reply direction. The relevant code path assumes the RST is a response to an outgoing SYN, but does not validate packet direction or ensure that a matching SYN was actually sent in the opposite direction.
As a result, a crafted packet sequence consisting of a SYN followed by an invalid-sequence RST can prematurely terminate an active NAT entry. This makes connection teardown easier than intended.
So, tighten the state transition logic to ensure that RST-triggered CLOSE transitions only occur when the RST is a valid response to a previously observed SYN in the correct direction.
--- net/netfilter/nf_conntrack_proto_tcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/netfilter/nf_conntrack_proto_tcp.c +2 -1
@@ -1083,7 +1083,8 @@ int nf_conntrack_tcp_packet(struct nf_co new_state = old_state; }if (((test_bit (IPS_SEEN_REPLY_BIT , &ct->status) - && ct->proto.tcp.last_index ==TCP_SYN_SET ) + && ct->proto.tcp.last_index ==TCP_SYN_SET + && ct->proto.tcp.last_dir != dir) || (!test_bit (IPS_ASSURED_BIT , &ct->status) && ct->proto.tcp.last_index ==TCP_ACK_SET )) &&ntohl (th->ack_seq) == ct->proto.tcp.last_end) {
Greg Kroah-Hartman
maintainerPATCH 82/342 ASoC: qcom: q6asm-dai: close stream only when running
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivas Kandagatla <[email protected]>
commit 048c540ee76ded666bda74f9dae1ca3254e0633c upstream.
q6asm_dai_close() and q6asm_dai_compr_free() currently issue CMD_CLOSE whenever prtd->state is non-zero.
After prepare() closes an existing stream, the state is updated to Q6ASM_STREAM_STOPPED. Since this state is also non-zero, the close and free paths can send CMD_CLOSE again for a stream that has already been closed.
Restrict CMD_CLOSE to the Q6ASM_STREAM_RUNNING state so the command is sent only when the ASM stream is still active.
--- sound/soc/qcom/qdsp6/q6asm-dai.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
sound/soc/qcom/qdsp6/q6asm-dai.c +7 -7
@@ -458,12 +458,12 @@ static int q6asm_dai_close(struct snd_sostruct q6asm_dai_rtd *prtd = runtime->private_data;if (prtd->audio_client) { -if (prtd->state) +if (prtd->state ==Q6ASM_STREAM_RUNNING ) {q6asm_cmd (prtd->audio_client, prtd->stream_id,CMD_CLOSE ); - -q6asm_unmap_memory_regions (substream->stream, +q6asm_unmap_memory_regions (substream->stream, prtd->audio_client); + }q6asm_audio_client_free (prtd->audio_client); prtd->audio_client =NULL ; }
@@ -692,7 +692,7 @@ static int q6asm_dai_compr_free(struct sstruct snd_soc_pcm_runtime *rtd = stream->private_data;if (prtd->audio_client) { -if (prtd->state) { +if (prtd->state ==Q6ASM_STREAM_RUNNING ) {q6asm_cmd (prtd->audio_client, prtd->stream_id,CMD_CLOSE );if (prtd->next_track_stream_id) {
@@ -700,11 +700,11 @@ static int q6asm_dai_compr_free(struct s prtd->next_track_stream_id, CMD_CLOSE); } - } -snd_dma_free_pages (&prtd->dma_buffer); -q6asm_unmap_memory_regions (stream->direction, +q6asm_unmap_memory_regions (stream->direction, prtd->audio_client); + } +snd_dma_free_pages (&prtd->dma_buffer);q6asm_audio_client_free (prtd->audio_client); prtd->audio_client =NULL ; }
Greg Kroah-Hartman
maintainerPATCH 83/342 ASoC: qcom: q6asm-dai: do not set stream state in event and trigger callbacks
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srinivas Kandagatla <[email protected]>
commit cee3e63e7106c3c81b2053371fdf14240bfba2fc upstream.
The q6asm-dai stream state is used by prepare() to decide whether an existing stream setup needs to be closed before opening/configuring a new one. Updating the state from trigger or asynchronous DSP callbacks can make that state stale or incorrect relative to the actual setup lifetime.
In particular, setting Q6ASM_STREAM_STOPPED on STOP or EOS completion can make prepare() believe there is no active setup to close, which can result in opening/configuring the same stream more than once.
Keep stream state updates tied to prepare(), where the stream is actually closed and reopened, and stop changing it from trigger and EOS callbacks.
--- sound/soc/qcom/qdsp6/q6asm-dai.c | 5 ----- 1 file changed, 5 deletions(-)
sound/soc/qcom/qdsp6/q6asm-dai.c +0 -5
@@ -191,7 +191,6 @@ static void event_handler(uint32_t opcod prtd->pcm_count, 0, 0, 0);break ;case ASM_CLIENT_EVENT_CMD_EOS_DONE : - prtd->state =Q6ASM_STREAM_STOPPED ;break ;case ASM_CLIENT_EVENT_DATA_WRITE_DONE : { prtd->pcm_irq_pos += prtd->pcm_count;
@@ -338,7 +337,6 @@ static int q6asm_dai_trigger(struct snd_ 0, 0, 0);break ;case SNDRV_PCM_TRIGGER_STOP : - prtd->state =Q6ASM_STREAM_STOPPED ; ret =q6asm_cmd_nowait (prtd->audio_client, prtd->stream_id,CMD_EOS );break ;
@@ -568,8 +566,6 @@ static void compress_event_handler(uint3snd_compr_drain_notify (prtd->cstream); prtd->notify_on_drain = false; - }else { - prtd->state =Q6ASM_STREAM_STOPPED ; }spin_unlock_irqrestore (&prtd->lock, flags);break ;
@@ -1032,7 +1028,6 @@ static int q6asm_dai_compr_trigger(struc 0, 0, 0);break ;case SNDRV_PCM_TRIGGER_STOP : - prtd->state =Q6ASM_STREAM_STOPPED ; ret =q6asm_cmd_nowait (prtd->audio_client, prtd->stream_id,CMD_EOS );break ;
Greg Kroah-Hartman
maintainerPATCH 84/342 xfrm: esp: restore combined single-frag length gate
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jingguo Tan <[email protected]>
commit dfa0d7b0ff1eb6b2c416b8fdb9b4f2cefba57a40 upstream.
The ESP out-of-place fast path appends the trailer in esp_output_head() before esp_output_tail() allocates the destination page frag. The head-side gate currently checks skb->data_len and tailen separately, but the tail code allocates a single destination frag from the combined post-trailer skb->data_len.
Reject the page-frag fast path when the combined aligned length exceeds a page. Otherwise skb_page_frag_refill() may fall back to a single page while the destination sg still spans the combined skb->data_len.
Restore this combined-length page gate for both IPv4 and IPv6.
--- net/ipv4/esp4.c | 4 ++-- net/ipv6/esp6.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
net/ipv4/esp4.c +2 -2
@@ -459,8 +459,8 @@ int esp_output_head(struct xfrm_state *xreturn err; } -if (ALIGN (tailen,L1_CACHE_BYTES ) >PAGE_SIZE || -ALIGN (skb->data_len,L1_CACHE_BYTES ) >PAGE_SIZE ) +if (ALIGN (skb->data_len + tailen,L1_CACHE_BYTES ) > +PAGE_SIZE ) goto cow;if (!skb_cloned (skb)) {
net/ipv6/esp6.c +2 -2
@@ -493,8 +493,8 @@ int esp6_output_head(struct xfrm_state *return err; } -if (ALIGN (tailen,L1_CACHE_BYTES ) >PAGE_SIZE || -ALIGN (skb->data_len,L1_CACHE_BYTES ) >PAGE_SIZE ) +if (ALIGN (skb->data_len + tailen,L1_CACHE_BYTES ) > +PAGE_SIZE ) goto cow;if (!skb_cloned (skb)) {
Greg Kroah-Hartman
maintainerPATCH 85/342 Input: atmel_mxt_ts - fix boundary check in mxt_prepare_cfg_mem
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit baa0210fb6a9dc3882509a9411b6d284d88fe30e upstream.
When a configuration file provides an object size that is larger than the driver's known mxt_obj_size(object), the driver intends to discard the extra bytes.
The loop iterates using for (i = 0; i < size; i++). Inside the loop, the condition to skip processing extra bytes is:
if (i > mxt_obj_size(object))
continue;
Since i is a 0-based index, the valid indices for the object are 0 through mxt_obj_size(object) - 1.
When i == mxt_obj_size(object), the condition evaluates to false, and the code processes the byte instead of discarding it.
This causes the code to calculate byte_offset = reg + i - cfg->start_ofs and writes the byte there, overwriting exactly one byte of the adjacent instance or object.
Update the boundary check to skip extra bytes correctly by using >=.
--- drivers/input/touchscreen/atmel_mxt_ts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/touchscreen/atmel_mxt_ts.c +1 -1
@@ -1400,7 +1400,7 @@ static int mxt_prepare_cfg_mem(struct mx } cfg->raw_pos += offset; -if (i >mxt_obj_size (object)) +if (i >=mxt_obj_size (object))continue ; byte_offset = reg + i - cfg->start_ofs;
Greg Kroah-Hartman
maintainerPATCH 86/342 Input: synaptics - add LEN2058 to SMBus passlist for ThinkPad E490
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolás Bazaes <[email protected]>
commit 16ca52bc209fa4bf9239cd9e5643e95533476b58 upstream.
The Lenovo ThinkPad E490 (PNP ID: LEN2058) has a Synaptics TM3471-020 touchpad that supports SMBus/RMI4 mode but is not listed in smbus_pnp_ids[]. Without this entry, RMI4 over SMBus is not enabled by default, and the touchpad falls back to PS/2 mode.
Adding LEN2058 to the passlist enables automatic RMI4 detection without requiring the psmouse.synaptics_intertouch parameter, and matches the behavior of similar ThinkPad models already in the list (E480/LEN2054, E580/LEN2055).
Tested on ThinkPad E490 with kernel 7.0.5-zen1 and Arch Linux. RMI4 over SMBus is confirmed working without any kernel parameters.
--- drivers/input/mouse/synaptics.c | 1 + 1 file changed, 1 insertion(+)
drivers/input/mouse/synaptics.c +1 -0
@@ -187,6 +187,7 @@ static const char * const smbus_pnp_ids["LEN2044" ,/* L470 */ "LEN2054" ,/* E480 */ "LEN2055" ,/* E580 */ +"LEN2058" ,/* E490 */ "LEN2068" ,/* T14 Gen 1 */ "SYN1221" ,/* TUXEDO InfinityBook Pro 14 v5 */ "SYN3003", /* HP EliteBook 850 G1 */
Greg Kroah-Hartman
maintainerPATCH 87/342 comedi: comedi_test: fix check for valid scan_begin_src in waveform_ai_cmdtest()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Abbott <[email protected]>
commit 542f5248cb481073203e0dadab5bcbd28aeae308 upstream.
Commit 783ddaebd397 ("staging: comedi: comedi_test: support scan_begin_src == TRIG_FOLLOW") neglected to add a test that scan_begin_src has only one bit set. The allowed values are TRIG_FOLLOW and TRIG_TIMER, but the code incorrectly also allows TRIG_FOLLOW | TRIG_TIMER. Add a call to comedi_check_trigger_is_unique() to check that only one trigger source bit is set.
--- drivers/staging/comedi/drivers/comedi_test.c | 1 + 1 file changed, 1 insertion(+)
drivers/staging/comedi/drivers/comedi_test.c +1 -0
@@ -273,6 +273,7 @@ static int waveform_ai_cmdtest(struct co/* Step 2a : make sure trigger sources are unique */ err |=comedi_check_trigger_is_unique (cmd->convert_src); + err |=comedi_check_trigger_is_unique (cmd->scan_begin_src); err |=comedi_check_trigger_is_unique (cmd->stop_src);/* Step 2b : and mutually compatible */
Greg Kroah-Hartman
maintainerPATCH 88/342 comedi: comedi_test: Fix limiting of convert_arg in waveform_ai_cmdtest()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Abbott <[email protected]>
commit 8a3bee801d420be8a7a0bae4a26547b353b8fe22 upstream.
The function checks and possibly modifies the description of an asynchronous command to be run on the analog input subdevice of a comedi device attached to the "comedi_test" driver, returning 0 if no modifications were required, or a positive value that indicates which step of the checking process it failed on. Step 4 fixes up various argument values for various trigger sources.
There are two bugs in the fixing up of the convert_arg value to keep the scan_begin_arg value within the range of unsigned int when scan_begin_src and convert_src both have the value TRIG_TIMER, which indicates that the corresponding _arg values hold a time period in nanoseconds. The code also uses scan_end_arg which hold the number of "conversions" within each "scan". The goal is to end up with the scan period being less than or equal to the convert period multiplied by the number of conversions per scan. It intends to do that by clamping the convert_arg value to a maximum value of UINT_MAX / scan_end_arg rounded down to a multiple of 1000 (NSEC_PER_USEC).
(The rounding from nanoseconds to microseconds is because the driver is modelling a device that uses a 1 MHz clock for timing. This is partly because that is a more typical timing base for real hardware devices driven by comedi, and partly because the driver used to use struct timeval internally.)
The first bug is that the code checks if scan_begin_arg == TRIG_TIMER when it should be checking if scan_begin_src == TRIG_TIMER. The bugged check will always fail because if scan_begin_src == TRIG_TIMER, then scan_begin_arg will be at least 1000 (NSEC_PER_USEC), otherwise scan_begin_src == TRIG_FOLLOW and scan_begin_arg will be 0. (N.B TRIG_TIMER is defined as 0x10.) The second bug is that is rounding the maximum value down to a multiple of 1000000000 (NSEC_PER_SEC) instead of 1000 (NSEC_PER_USEC), however this bug is not reached due to the first bug. This patch fixes both bugs.
--- drivers/staging/comedi/drivers/comedi_test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/staging/comedi/drivers/comedi_test.c +2 -2
@@ -324,10 +324,10 @@ static int waveform_ai_cmdtest(struct co arg =min (arg,rounddown (UINT_MAX , (unsigned int )NSEC_PER_USEC )); arg =NSEC_PER_USEC *DIV_ROUND_CLOSEST (arg,NSEC_PER_USEC ); -if (cmd->scan_begin_arg ==TRIG_TIMER ) { +if (cmd->scan_begin_src ==TRIG_TIMER ) {/* limit convert_arg to keep scan_begin_arg in range */ limit =UINT_MAX / cmd->scan_end_arg; - limit =rounddown (limit, (unsigned int )NSEC_PER_SEC ); + limit =rounddown (limit, (unsigned int )NSEC_PER_USEC ); arg =min (arg, limit); } err |=comedi_check_trigger_arg_is (&cmd->convert_arg, arg);
Greg Kroah-Hartman
maintainerPATCH 89/342 tty: serial: pch_uart: add check for dma_alloc_coherent()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhaoyang Yu <[email protected]>
commit 6fe472c1bbbe238e91141f7cabc1226e96a60d43 upstream.
Add a check for dma_alloc_coherent() failure to prevent a potential NULL pointer dereference in dma_handle_rx(). Properly release DMA channels and the PCI device reference using a goto ladder if the allocation fails.
--- drivers/tty/serial/pch_uart.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-)
drivers/tty/serial/pch_uart.c +13 -6
@@ -711,8 +711,7 @@ static void pch_request_dma(struct uart_if (!chan) {dev_err (priv->port.dev,"%s:dma_request_channel FAILS(Tx)\n" , __func__); -pci_dev_put (dma_dev); -return ; + goto err_pci_get; } priv->chan_tx = chan;
@@ -726,18 +725,26 @@ static void pch_request_dma(struct uart_if (!chan) {dev_err (priv->port.dev,"%s:dma_request_channel FAILS(Rx)\n" , __func__); -dma_release_channel (priv->chan_tx); - priv->chan_tx =NULL ; -pci_dev_put (dma_dev); -return ; + goto err_req_tx; }/* Get Consistent memory for DMA */ priv->rx_buf_virt =dma_alloc_coherent (port->dev, port->fifosize, &priv->rx_buf_dma,GFP_KERNEL ); +if (!priv->rx_buf_virt) + goto err_req_rx; priv->chan_rx = chan;pci_dev_put (dma_dev); +return ; + +err_req_rx: +dma_release_channel (chan); +err_req_tx: +dma_release_channel (priv->chan_tx); + priv->chan_tx =NULL ; +err_pci_get: +pci_dev_put (dma_dev); }static void pch_dma_rx_complete (void *arg)
Greg Kroah-Hartman
maintainerPATCH 90/342 usb: chipidea: core: convert ci_role_switch to local variable
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Yang <[email protected]>
commit 8f6aa392653e52a45858cff5c063df550028836b upstream.
When a system contains multiple USB controllers, the global ci_role_switch variable may be overwritten by subsequent driver initialization code.
This can cause issues in the following cases:
- The 2nd ci_hdrc_probe() sees ci_role_switch.fwnode as non-NULL even though the "usb-role-switch" property is not present for the controller.
- When the ci_hdrc device is unbound and bound again, ci_role_switch fwnode will not be reassigned, and the old value will be used instead.
Convert ci_role_switch to a local variable to fix these issues.
--- drivers/usb/chipidea/core.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-)
drivers/usb/chipidea/core.c +6 -10
@@ -654,12 +654,6 @@ static int ci_usb_role_switch_set(structreturn 0 ; } -static struct usb_role_switch_desc ci_role_switch = { - .set = ci_usb_role_switch_set, - .get = ci_usb_role_switch_get, - .allow_userspace_control = true, -}; -static int ci_get_platdata (struct device *dev,struct ci_hdrc_platform_data *platdata) {
@@ -786,9 +780,6 @@ static int ci_get_platdata(struct device cable->connected = false; } -if (device_property_read_bool (dev,"usb-role-switch" )) - ci_role_switch.fwnode = dev->fwnode; - platdata->pctl =devm_pinctrl_get (dev);if (!IS_ERR (platdata->pctl)) {struct pinctrl_state *p;
@@ -1005,6 +996,7 @@ ATTRIBUTE_GROUPS(ci);static int ci_hdrc_probe (struct platform_device *pdev) { +struct usb_role_switch_desc ci_role_switch = {};struct device *dev = &pdev->dev;struct ci_hdrc *ci;struct resource *res;
@@ -1146,7 +1138,11 @@ static int ci_hdrc_probe(struct platform } } -if (ci_role_switch.fwnode) { +if (device_property_read_bool (dev,"usb-role-switch" )) { + ci_role_switch.set = ci_usb_role_switch_set; + ci_role_switch.get = ci_usb_role_switch_get; + ci_role_switch.allow_userspace_control = true; + ci_role_switch.fwnode =dev_fwnode (dev); ci_role_switch.driver_data = ci; ci->role_switch =usb_role_switch_register (dev, &ci_role_switch);
Greg Kroah-Hartman
maintainerPATCH 91/342 usb: core: Fix up Interrupt IN endpoints with bogus wBytesPerInterval
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Pecio <[email protected]>
commit 727d045d064b7c9a24db3bce9c0485a382cb768b upstream.
Tao Xue found that some common devices violate USB 3.x section 9.6.7 by reporting wBytesPerInterval lower than the size of packets they actually send. I confirmed that AX88179 may set it to 0 and RTL8153 CDC configuration sets it to 8 but sends both 8 and 16 byte packets:
S Ii:11:007:3 -115:128 16 <
C Ii:11:007:3 0:128 8 = a1000000 01000000
S Ii:11:007:3 -115:128 16 <
C Ii:11:007:3 0:128 16 = a12a0000 01000800 00000000 00000000
Most xHCI host controllers neglect interrupt bandwidth reservations and let such devices exceed theirs, some fail the URB with EOVERFLOW.
Assume that wBytesPerInterval lower than wMaxPacketSize is bogus and increase it to the worst case maximum on interrupt IN endpoints. This solves xHCI problems and appears to have no other effect. Interrupt transfers are not limited to one interval and drivers submit URBs of class defined size without looking at wBytesPerInterval. Any multi- interval transfer is considered terminated by a packet shorter than wMaxPacketSize regardless of wBytesPerInterval - see USB3 8.10.3.
Stay in spec on OUT endpoints and isochronous. No buggy devices are known and we don't want to risk sending more data than the device is prepared to handle or confusing isoc drivers regarding altsetting capacities guaranteed by the device itself. And don't complain when wMaxPacketSize <= wBytesPerInterval < wMaxPacketSize * (bMaxBurst+1) because enabling this seems to be the exact goal of the spec.
--- drivers/usb/core/config.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/usb/core/config.c +8 -1
@@ -165,7 +165,14 @@ static void usb_parse_ss_endpoint_compan (desc->bMaxBurst +1 ); else max_tx =999999 ; -if (le16_to_cpu (desc->wBytesPerInterval) > max_tx) { +/* +* wBytesPerInterval > max_tx is bogus, but USB3 spec doesn't forbid the opposite. +* Experience shows that wBytesPerInterval < wMaxPacketSize on common interrupt IN +* endpoints is usually bogus too, and recent HCs enforce interrupt BW limits. +*/ +if (le16_to_cpu (desc->wBytesPerInterval) > max_tx || + (le16_to_cpu (desc->wBytesPerInterval) <usb_endpoint_maxp (&ep->desc) && +usb_endpoint_is_int_in (&ep->desc))) { dev_notice(ddev, "%s endpoint with wBytesPerInterval of %d in " "config %d interface %d altsetting %d ep %d: " "setting to %d\n",
Greg Kroah-Hartman
maintainerPATCH 92/342 USB: quirks: add NO_LPM for Lenovo ThinkPad USB-C Dock Gen2 hub controllers
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stephen J. Fuhry <[email protected]>
commit 9ddb9c0deca48d2c2a22ebf4d2f35c925a520328 upstream.
The Lenovo ThinkPad USB-C Dock Gen2 (17ef:a391, 17ef:a392) hub controllers exhibit link instability when USB Link Power Management is enabled, similar to the dock's Ethernet adapter (17ef:a387) which already carries USB_QUIRK_NO_LPM.
When the dock reconnects after a transient disconnect, the hub controllers enter LPM states between re-enumeration retries, causing repeated disconnect/reconnect cycles lasting up to two minutes. Disabling LPM for these devices restores stable enumeration.
--- drivers/usb/core/quirks.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/usb/core/quirks.c +4 -0
@@ -498,6 +498,10 @@ static const struct usb_device_id usb_qu/* Lenovo ThinkPad USB-C Dock Gen2 Ethernet (RTL8153 GigE) */ { USB_DEVICE(0x17ef, 0xa387), .driver_info = USB_QUIRK_NO_LPM }, + /* Lenovo ThinkPad USB-C Dock Gen2 USB 3.1 and USB 2.0 hub controllers */ + { USB_DEVICE(0x17ef, 0xa391), .driver_info = USB_QUIRK_NO_LPM }, + { USB_DEVICE(0x17ef, 0xa392), .driver_info = USB_QUIRK_NO_LPM }, + /* BUILDWIN Photo Frame */ { USB_DEVICE(0x1908, 0x1315), .driver_info = USB_QUIRK_HONOR_BNUMINTERFACES },
Greg Kroah-Hartman
maintainerPATCH 93/342 usb: storage: Add quirks for PNY Elite Portable SSD
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sam Burkels <[email protected]>
commit b53ebb811e00be50a779ce4e7aee604178b4a825 upstream.
The PNY Elite Portable SSD (USB ID 154b:f009) is a sibling of the already-quirked PNY Pro Elite SSDs (154b:f00b and 154b:f00d). Like its siblings, it uses a Phison-based USB-SATA bridge that exhibits firmware bugs when bound to the uas driver.
Without quirks, the device fails to complete READ CAPACITY commands when accessed over UAS on a SuperSpeed (USB 3) port. The device enumerates and reports as a SCSI direct-access device, but reports zero logical blocks and never finishes spin-up:
usb 2-3: new SuperSpeed USB device number 8 using xhci_hcd usb 2-3: New USB device found, idVendor=154b, idProduct=f009 usb 2-3: Product: PNY ELITE PSSD
usb 2-3: Manufacturer: PNY
scsi host0: uas
scsi 0:0:0:0: Direct-Access PNY PNY ELITE PSSD 0
sd 0:0:0:0: [sda] Spinning up disk...
[...10+ seconds of polling, no progress...]
sd 0:0:0:0: [sda] Read Capacity(16) failed: hostbyte=DID_ERROR sd 0:0:0:0: [sda] Read Capacity(10) failed: hostbyte=DID_ERROR sd 0:0:0:0: [sda] 0 512-byte logical blocks: (0 B/0 B)
Tested each individual quirk to find the minimum that fixes this:
- US_FL_NO_ATA_1X alone: device hangs on spin-up
- US_FL_NO_REPORT_OPCODES alone: works on USB 2.0, hangs on USB 3.0
- US_FL_NO_ATA_1X | US_FL_NO_REPORT_OPCODES: works on both
With both quirks the device enumerates correctly while still using the uas driver, and delivers full UAS throughput (~281 MB/s sequential read on a USB 3.0 Gen 1 port).
The existing PNY Pro Elite entries (f00b, f00d) only set NO_ATA_1X, but this device additionally chokes on REPORT OPCODES under SuperSpeed.
--- drivers/usb/storage/unusual_uas.h | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/usb/storage/unusual_uas.h +7 -0
@@ -132,6 +132,13 @@ UNUSUAL_DEV(0x152d, 0x0583, 0x0000, 0x99 USB_SC_DEVICE, USB_PR_DEVICE, NULL, US_FL_NO_REPORT_OPCODES), +/* Reported-by: Sam Burkels <[email protected]> */ +UNUSUAL_DEV (0x154b ,0xf009 ,0x0000 ,0x9999 , +"PNY" , +"PNY ELITE PSSD" , +USB_SC_DEVICE ,USB_PR_DEVICE ,NULL , +US_FL_NO_ATA_1X |US_FL_NO_REPORT_OPCODES ), +/* Reported-by: Thinh Nguyen <[email protected]> */ UNUSUAL_DEV(0x154b, 0xf00b, 0x0000, 0x9999, "PNY",
Greg Kroah-Hartman
maintainerPATCH 94/342 usbip: vudc: Fix use after free bug in vudc_remove due to race condition
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit d96209626a29ea64666be98c30b30ac82e5f1be6 upstream.
This patch follows up Zheng Wang's 2023 report of a use-after-free in vudc_remove(). The original thread stalled on Shuah Khan's request for runtime testing of the unplug/unbind path. This patch supplies that testing and keeps Zheng's original fix shape.
In vudc_probe(), v_init_timer() binds udc->tr_timer.timer to v_timer(). usbip_sockfd_store() starts the timer via v_start_timer()/v_kick_timer(). vudc_remove() can then free the containing struct vudc while the timer is still pending or executing.
KASAN confirms the race on an unpatched x86_64 QEMU guest with CONFIG_KASAN=y, CONFIG_USBIP_VUDC=y, CONFIG_USB_ZERO=y, and a tight loop that repeatedly writes a socket fd to usbip_sockfd, closes the socket pair, and unbinds/rebinds usbip-vudc.0:
BUG: KASAN: slab-use-after-free in __run_timer_base.part.0+0x8ba/0x8e0
Write of size 8 at addr ffff888001b80740 by task trigger_and_unb/239
Allocated by task 239:
vudc_probe+0x4d/0xaa0
Freed by task 239:
kfree+0x18f/0x520
device_release_driver_internal+0x388/0x540
unbind_store+0xd9/0x100This lands in the timer core rather than v_timer() itself because the embedded timer_list is being walked after its containing struct vudc has already been freed. The underlying lifetime bug is the same one Zheng reported.
With v_stop_timer() called from vudc_remove() and the timer deleted synchronously, the same harness completed 5000 bind/unbind iterations with no KASAN report.
--- drivers/usb/usbip/vudc_dev.c | 1 + drivers/usb/usbip/vudc_transfer.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-)
drivers/usb/usbip/vudc_dev.c +1 -0
@@ -633,6 +633,7 @@ int vudc_remove(struct platform_device * {struct vudc *udc =platform_get_drvdata (pdev); +v_stop_timer (udc);usb_del_gadget_udc (&udc->gadget);cleanup_vudc_hw (udc);kfree (udc);
drivers/usb/usbip/vudc_transfer.c +2 -1
@@ -490,7 +490,8 @@ void v_stop_timer(struct vudc *udc) {struct transfer_timer *t = &udc->tr_timer; -/* timer itself will take care of stopping */ +/* Delete the timer synchronously before teardown frees udc. */ dev_dbg (&udc->pdev->dev,"timer stop" ); +timer_delete_sync (&t->timer); t->state =VUDC_TR_STOPPED ; }
Greg Kroah-Hartman
maintainerPATCH 95/342 usb: usbtmc: check URB actual_length for interrupt-IN notifications
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heitor Alves de Siqueira <[email protected]>
commit 52f2ad3f7e5eb3b5908e1d685d4342519dc9cfcd upstream.
USBTMC devices can use an optional interrupt endpoint for notification messages. These typically contain two-byte headers indicating the payload format, but the driver does not check if these headers are present before accessing the data buffers. In cases where the URB actual_length is not enough to fit these headers, the driver will either cause an out-of-bounds read, or consume stale leftover data from a previous notification.
Fix by checking if actual_data contains enough bytes for the headers, otherwise resubmit URB to the interrupt endpoint.
--- drivers/usb/class/usbtmc.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/usb/class/usbtmc.c +8 -0
@@ -2268,6 +2268,14 @@ static void usbtmc_interrupt(struct urbswitch (status) {case 0 :/* SUCCESS */ +/* ensure at least two bytes of headers were transferred */ +if (urb->actual_length <2 ) { +dev_warn (dev, +"actual length %d not sufficient for interrupt headers\n" , + urb->actual_length); + goto exit; + } +/* check for valid STB notification */ if (data->iin_buffer[0 ] >0x81 ) { data->bNotify1 = data->iin_buffer[0 ];
Greg Kroah-Hartman
maintainerPATCH 96/342 usb: usbtmc: reject interrupt endpoints with small wMaxPacketSize
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heitor Alves de Siqueira <[email protected]>
commit 121d2f682ba912b1427cddca7cf84840f41cc620 upstream.
The USB488 subclass specification requires interrupt wMaxPacketSize to be 0x02, unless the device sends vendor-specific notifications. Endpoints that advertise less than 2 bytes for wMaxPacketSize are unlikely to work with the current driver, as URBs will not have enough space for interrupt headers. Considering that any notification URBs will be ignored by the driver, reject these endpoints early during probe.
--- drivers/usb/class/usbtmc.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/usb/class/usbtmc.c +6 -0
@@ -2402,6 +2402,12 @@ static int usbtmc_probe(struct usb_inter data->iin_ep = int_in->bEndpointAddress; data->iin_wMaxPacketSize =usb_endpoint_maxp (int_in); data->iin_interval = int_in->bInterval; +/* wMaxPacketSize should be 0x02 or more as per USB488 Table 22 */ +if (iface_desc->desc.bInterfaceProtocol ==1 && + data->iin_wMaxPacketSize <2 ) { + retcode = -EINVAL ; + goto err_put; + }dev_dbg (&intf->dev,"Found Int in endpoint at %u\n" , data->iin_ep); }
Greg Kroah-Hartman
maintainerPATCH 97/342 USB: serial: option: add MeiG SRM813Q
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Volckaert <[email protected]>
commit 7d2b37d3e42d19071b62f4ddbee6e16e905efbf1 upstream.
Add support for the Qualcomm Technology Snapdragon X35-based MeiG SRM813Q module.
The module can be put in different modes via AT commands to enable/disable GPS functionality:
MODEM - PPP mode(2dee:4d63): AT+SER=1,1
If#= 0: RMNET
If#= 1: DIAG/ADB
If#= 2: MODEM
If#= 3: AT
P: Vendor=2dee ProdID=4d63 Rev=05.15 S: Manufacturer=MEIG S: Product=LTE-A Module S: SerialNumber=1bd51f0e C: #Ifs= 4 Cfg#= 1 Atr=80 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
NMEA mode(2dee:4d64): AT+SER=51,1
If#= 0: RMNET
If#= 1: DIAG/ADB
If#= 2: NMEA
If#= 3: AT
P: Vendor=2dee ProdID=4d64 Rev=05.15 S: Manufacturer=MEIG S: Product=LTE-A Module S: SerialNumber=1bd51f0e C: #Ifs= 4 Cfg#= 1 Atr=80 MxPwr=500mA I: If#= 0 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=50 Driver=qmi_wwan E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=82(I) Atr=03(Int.) MxPS= 8 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I: If#= 2 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=60 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=85(I) Atr=03(Int.) MxPS= 10 Ivl=32ms I: If#= 3 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=86(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=03(Int.) MxPS= 10 Ivl=32ms
--- drivers/usb/serial/option.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/usb/serial/option.c +6 -0
@@ -2450,6 +2450,12 @@ static const struct usb_device_id option { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d38, 0xff, 0xff, 0x30) }, /* MeiG Smart SRM825WN (Diag) */ { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d38, 0xff, 0xff, 0x40) }, /* MeiG Smart SRM825WN (AT) */ { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d38, 0xff, 0xff, 0x60) }, /* MeiG Smart SRM825WN (NMEA) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d63, 0xff, 0xff, 0x30) }, /* MeiG SRM813Q (Diag) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d63, 0xff, 0xff, 0x40) }, /* MeiG SRM813Q (AT) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d64, 0xff, 0xff, 0x30) }, /* MeiG SRM813Q (Diag) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d64, 0xff, 0xff, 0x40) }, /* MeiG SRM813Q (AT) */ + { USB_DEVICE_AND_INTERFACE_INFO(0x2dee, 0x4d64, 0xff, 0xff, 0x60) }, /* MeiG SRM813Q (NMEA) */ + { USB_DEVICE_INTERFACE_CLASS(0x2df3, 0x9d03, 0xff) }, /* LongSung M5710 */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1404, 0xff) }, /* GosunCn GM500 RNDIS */ { USB_DEVICE_INTERFACE_CLASS(0x305a, 0x1405, 0xff) }, /* GosunCn GM500 MBIM */
Greg Kroah-Hartman
maintainerPATCH 98/342 USB: serial: option: add missing RSVD(5) flag for Rolling RW135R-GL
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wanquan Zhong <[email protected]>
commit 689f2facc689c8add11d7ff69fbbad17d65ee596 upstream.
The RW135R-GL entry added in commit 01e8d0f74222 ("USB: serial: option:
add support for Rolling Wireless RW135R-GL") was missing the .driver_info = RSVD(5) flag used by other Rolling Wireless MBIM laptop modules (e.g. RW135-GL and RW350-GL).
Without this flag, the option driver incorrectly binds to the reserved ADB interface (If#5) in multi-interface USB modes, causing AT/MBIM communication failures after mode switching. This matches the handling of other Rolling Wireless MBIM devices.
- VID:PID 33f8:1003, RW135R-GL for laptop debug M.2 cards (with MBIM interface for Linux/Chrome OS)
0x1003: mbim, diag, AT, pipe
Here are the outputs of usb-devices:
T: Bus=03 Lev=01 Prnt=01 Port=04 Cnt=02 Dev#= 8 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=33f8 ProdID=1003 Rev= 5.15 S: Manufacturer=Rolling Wireless S.a.r.l. S: Product=Rolling RW135R-GL Module S: SerialNumber=12345678 C:* #Ifs= 5 Cfg#= 1 Atr=a0 MxPwr=500mA A: FirstIf#= 0 IfCount= 2 Cls=02(comm.) Sub=0e Prot=00 I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=0e Prot=00 Driver=cdc_mbim E: Ad=82(I) Atr=03(Int.) MxPS= 64 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim I:* If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- VID:PID 33f8:1003, RW135R-GL for laptop debug M.2 cards (with MBIM interface for Linux/Chrome OS)
0x1003: mbim, diag, AT, ADB, pipe
Here are the outputs of usb-devices:
T: Bus=03 Lev=01 Prnt=01 Port=04 Cnt=02 Dev#= 7 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=33f8 ProdID=1003 Rev= 5.15 S: Manufacturer=Rolling Wireless S.a.r.l. S: Product=Rolling RW135R-GL Module S: SerialNumber=12345678 C:* #Ifs= 6 Cfg#= 1 Atr=a0 MxPwr=500mA A: FirstIf#= 0 IfCount= 2 Cls=02(comm.) Sub=0e Prot=00 I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=0e Prot=00 Driver=cdc_mbim E: Ad=82(I) Atr=03(Int.) MxPS= 64 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim I:* If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 3 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=30 Driver=option E: Ad=03(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=84(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 4 Alt= 0 #EPs= 3 Cls=ff(vend.) Sub=ff Prot=40 Driver=option E: Ad=86(I) Atr=03(Int.) MxPS= 10 Ivl=32ms E: Ad=85(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=04(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 5 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=42 Prot=01 Driver=(none) E: Ad=05(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=87(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms
- VID:PID 33f8:1003, RW135R-GL for laptop debug M.2 cards (with MBIM interface for Linux/Chrome OS)
0x1003: mbim, pipe
Here are the outputs of usb-devices:
T: Bus=03 Lev=01 Prnt=01 Port=04 Cnt=02 Dev#= 9 Spd=480 MxCh= 0 D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS=64 #Cfgs= 1 P: Vendor=33f8 ProdID=1003 Rev= 5.15 S: Manufacturer=Rolling Wireless S.a.r.l. S: Product=Rolling RW135R-GL Module S: SerialNumber=12345678 C:* #Ifs= 3 Cfg#= 1 Atr=a0 MxPwr=500mA A: FirstIf#= 0 IfCount= 2 Cls=02(comm.) Sub=0e Prot=00 I:* If#= 0 Alt= 0 #EPs= 1 Cls=02(comm.) Sub=0e Prot=00 Driver=cdc_mbim E: Ad=82(I) Atr=03(Int.) MxPS= 64 Ivl=32ms I: If#= 1 Alt= 0 #EPs= 0 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim I:* If#= 1 Alt= 1 #EPs= 2 Cls=0a(data ) Sub=00 Prot=02 Driver=cdc_mbim E: Ad=81(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=01(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms I:* If#= 2 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=00 Prot=00 Driver=option E: Ad=83(I) Atr=02(Bulk) MxPS= 512 Ivl=0ms E: Ad=02(O) Atr=02(Bulk) MxPS= 512 Ivl=0ms
--- drivers/usb/serial/option.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/usb/serial/option.c +2 -1
@@ -2476,7 +2476,8 @@ static const struct usb_device_id option { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0302, 0xff) }, /* Rolling RW101R-GL (laptop MBIM) */ { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x0802, 0xff), /* Rolling RW350-GL (laptop MBIM) */ .driver_info = RSVD(5) }, - { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x1003, 0xff) }, /* Rolling RW135R-GL (laptop MBIM) */ + { USB_DEVICE_INTERFACE_CLASS(0x33f8, 0x1003, 0xff), /* Rolling RW135R-GL (laptop MBIM) */ + .driver_info = RSVD(5) }, { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for Global */ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0x00, 0x40) }, { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0100, 0xff, 0xff, 0x40) },
Greg Kroah-Hartman
maintainerPATCH 99/342 USB: serial: belkin_sa: validate interrupt status length
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Cen <[email protected]>
commit 4ce058df2ee02cc2a0f0fd5cd64ce6f1482a0b65 upstream.
The Belkin interrupt callback treats interrupt data as a four-byte status report and reads LSR/MSR fields at offsets 2 and 3. The interrupt-in buffer length is derived from endpoint wMaxPacketSize, and short interrupt transfers may complete successfully with a smaller actual_length.
Check the completed interrupt packet length before parsing status fields so short interrupt endpoints and short successful packets are ignored instead of causing out-of-bounds or stale status-byte reads.
KASAN report as below:
BUG: KASAN: slab-out-of-bounds in belkin_sa_read_int_callback() Read of size 1 Call trace: belkin_sa_read_int_callback() (drivers/usb/serial/belkin_sa.c:202) __usb_hcd_giveback_urb() (drivers/usb/core/hcd.c:1630) dummy_timer() (?:?)
--- drivers/usb/serial/belkin_sa.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/usb/serial/belkin_sa.c +3 -0
@@ -196,6 +196,9 @@ static void belkin_sa_read_int_callback(usb_serial_debug_data (&port->dev, __func__, urb->actual_length, data); +if (urb->actual_length <BELKIN_SA_MSR_INDEX +1 ) + goto exit; +/* Handle known interrupt data */ /* ignore data[0] and data[1] */
Greg Kroah-Hartman
maintainerPATCH 100/342 USB: serial: cypress_m8: validate interrupt packet headers
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Cen <[email protected]>
commit 9f9bfc80c67f35a275820da7e83a35dface08281 upstream.
cypress_read_int_callback() parses the interrupt-in buffer according to the selected Cypress packet format. Format 1 has a two-byte status/count header and format 2 has a one-byte combined status/count header. The usb-serial core sizes the interrupt-in buffer from the endpoint descriptor's wMaxPacketSize, and successful interrupt transfers can complete short when URB_SHORT_NOT_OK is not set.
Check that the completed packet contains the selected header before reading it. Malformed short reports are ignored and the interrupt URB is resubmitted through the existing retry path, preventing out-of-bounds header-byte reads.
KASAN report as below:
KASAN slab-out-of-bounds in cypress_read_int_callback+0x240/0x7f0
Read of size 1 Call trace: cypress_read_int_callback() (drivers/usb/serial/cypress_m8.c:1009) __usb_hcd_giveback_urb() dummy_timer()
--- drivers/usb/serial/cypress_m8.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
drivers/usb/serial/cypress_m8.c +11 -1
@@ -1035,8 +1035,8 @@ static void cypress_read_int_callback(stchar tty_flag =TTY_NORMAL ;int bytes =0 ;int result; -int i =0 ;int status = urb->status; +int i;switch (status) {case 0 :/* success */
@@ -1074,22 +1074,32 @@ static void cypress_read_int_callback(stspin_lock_irqsave (&priv->lock, flags); result = urb->actual_length; + i =0 ;switch (priv->pkt_fmt) {default :case packet_format_1:/* This is for the CY7C64013... */ +if (result <2 ) +break ; priv->current_status = data[0 ] &0xF8 ; bytes = data[1 ] +2 ; i =2 ;break ;case packet_format_2:/* This is for the CY7C63743... */ +if (result <1 ) +break ; priv->current_status = data[0 ] &0xF8 ; bytes = (data[0 ] &0x07 ) +1 ; i =1 ;break ; }spin_unlock_irqrestore (&priv->lock, flags); +if (i ==0 ) { +dev_dbg (dev,"%s - short packet received: %d bytes\n" , + __func__, result); + goto continue_read; + }if (result < bytes) { dev_dbg(dev, "%s - wrong packet size - received %d bytes but packet said %d bytes\n",
Greg Kroah-Hartman
maintainerPATCH 101/342 USB: serial: keyspan: fix missing indat transfer sanity check
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit ab8336a7e414f018430aa1af3a46944032f7ff96 upstream.
Add the missing sanity check on the size of usa49wg indat transfers to avoid parsing stale or uninitialised slab data.
--- drivers/usb/serial/keyspan.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/usb/serial/keyspan.c +4 -0
@@ -1204,6 +1204,10 @@ static void usa49wg_indat_callback(struc len =0 ;while (i < urb->actual_length) { +if (urb->actual_length - i <3 ) { +dev_warn_ratelimited (&urb->dev->dev,"malformed indat packet\n" ); +break ; + }/* Check port number from message */ if (data[i] >= serial->num_ports) {
Greg Kroah-Hartman
maintainerPATCH 102/342 USB: serial: mxuport: fix memory corruption with small endpoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 4085f0dbb1ce2251c9a5938d693de6593f0ab2bd upstream.
Make sure that the bulk-out endpoint max packet size is at least eight bytes to avoid user-controlled slab corruption should a malicious device report a smaller size.
--- drivers/usb/serial/mxuport.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/usb/serial/mxuport.c +8 -0
@@ -969,6 +969,14 @@ static int mxuport_calc_num_ports(struct*/ BUILD_BUG_ON (ARRAY_SIZE (epds->bulk_out) <16 ); +/* +* The bulk-out buffers must be large enough for the four-byte header +* (and following data), but assume anything smaller than eight bytes +* is broken. +*/ +if (usb_endpoint_maxp (epds->bulk_out[0 ]) <8 ) +return -EINVAL ; +for (i =1 ; i < num_ports; ++i) epds->bulk_out[i] = epds->bulk_out[0 ];
Greg Kroah-Hartman
maintainerPATCH 103/342 USB: serial: mct_u232: fix missing interrupt-in transfer sanity check
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 245aba83e3c288e176ed037a1f6b618b09e92ed8 upstream.
Add the missing sanity check on the size of interrupt-in transfers to avoid parsing stale or uninitialised slab data (and leaking it to user space).
--- drivers/usb/serial/mct_u232.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/usb/serial/mct_u232.c +5 -0
@@ -545,6 +545,11 @@ static void mct_u232_read_int_callback(s goto exit; } +if (urb->actual_length <2 ) { +dev_warn_ratelimited (&port->dev,"short interrupt-in packet\n" ); + goto exit; + } +/* * The interrupt-in pipe signals exceptional conditions (modem line * signal changes and errors). data[0] holds MSR, data[1] holds LSR.
Greg Kroah-Hartman
maintainerPATCH 104/342 usb: gadget: net2280: Fix double free in probe error path
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
commit c8547c74988e0b5f4cbb1b895e2a57aae084f070 upstream.
usb_initialize_gadget() installs gadget_release() as the release callback for the embedded gadget device. The struct net2280 instance is therefore released through gadget_release() when the gadget device's last reference is dropped.
The probe error path calls net2280_remove(), which tears down the partially initialized device and drops the gadget reference with usb_put_gadget(). Calling kfree(dev) afterwards can free the same object again.
Drop the explicit kfree() and let the gadget device release callback handle the final free. This issue was found by a static analysis tool I am developing.
--- drivers/usb/gadget/udc/net2280.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/usb/gadget/udc/net2280.c +1 -3
@@ -3783,10 +3783,8 @@ static int net2280_probe(struct pci_devreturn 0 ; done: -if (dev) { +if (dev)net2280_remove (pdev); -kfree (dev); - }return retval; }
Greg Kroah-Hartman
maintainerPATCH 105/342 usb: gadget: dummy_hcd: Reject hub port requests for non-existent ports
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Seungjin Bae <[email protected]>
commit 7d9633528dd40e33964d2dc74a5abbf5c4d116ce upstream.
The dummy_hub_control() function handles USB hub class requests to the virtual root hub. The GetPortStatus case returns -EPIPE for requests with wIndex != 1, since the virtual root hub has only a single port. However, the ClearPortFeature and SetPortFeature cases lack the same check.
Fix this by extending the wIndex != 1 rejection to both cases, matching the existing behavior of GetPortStatus.
--- drivers/usb/gadget/udc/dummy_hcd.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/usb/gadget/udc/dummy_hcd.c +4 -0
@@ -2110,6 +2110,8 @@ static int dummy_hub_control(case ClearHubFeature:break ;case ClearPortFeature: +if (wIndex !=1 ) + goto error;switch (wValue) {case USB_PORT_FEAT_SUSPEND :if (hcd->speed ==HCD_USB3 ) {
@@ -2224,6 +2226,8 @@ static int dummy_hub_control( retval = -EPIPE ;break ;case SetPortFeature: +if (wIndex !=1 ) + goto error;switch (wValue) {case USB_PORT_FEAT_LINK_STATE :if (hcd->speed !=HCD_USB3 ) {
Greg Kroah-Hartman
maintainerPATCH 106/342 thunderbolt: property: Reject u32 wrap in tb_property_entry_valid()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 01deda0152066c6c955f0619114ea6afa070aaec upstream.
entry->value is u32 and entry->length is u16; the sum is performed in u32 and wraps. A malicious XDomain peer can pick
value = 0xffffff00, length = 0x100 so the sum 0x100000000 wraps to 0 and passes the > block_len check. tb_property_parse() then passes entry->value to parse_dwdata() as a dword offset into the property block, reading attacker-directed memory far past the allocation.
For TEXT-typed entries with the "deviceid" or "vendorid" keys this lands in xd->device_name / xd->vendor_name and is readable back via the per-XDomain device_name / vendor_name sysfs attributes; the leak is NUL-bounded (kstrdup() stops at the first zero byte) and untargeted (the attacker picks a delta, not an absolute address). DATA-typed entries are parsed into property->value.data but not generically surfaced to userspace.
Use check_add_overflow() so a wrapped sum is rejected.
--- drivers/thunderbolt/property.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/thunderbolt/property.c +5 -1
@@ -8,6 +8,7 @@*/ #include <linux/err.h> +#include <linux/overflow.h> #include <linux/slab.h> #include <linux/string.h> #include <linux/uuid.h>
@@ -52,13 +53,16 @@ static inline void format_dwdata(void *dstatic bool tb_property_entry_valid (const struct tb_property_entry *entry,size_t block_len) { +u32 end; +switch (entry->type) {case TB_PROPERTY_TYPE_DIRECTORY :case TB_PROPERTY_TYPE_DATA :case TB_PROPERTY_TYPE_TEXT :if (entry->length > block_len)return false; -if (entry->value + entry->length > block_len) +if (check_add_overflow (entry->value, entry->length, &end) || + end > block_len)return false;break ;
Greg Kroah-Hartman
maintainerPATCH 107/342 thunderbolt: property: Reject dir_len < 4 to prevent size_t underflow
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit de21b59c29e31c5108ddc04210631bbfab81b997 upstream.
On the non-root path, __tb_property_parse_dir() takes dir_len from entry->length (u16 widened to size_t). Two distinct OOB conditions follow when entry->length < 4:
1. The non-root path begins with kmemdup(&block[dir_offset], sizeof(*dir->uuid), ...) which always reads 4 dwords from dir_offset. tb_property_entry_valid() only enforces dir_offset + entry->length <= block_len, so a crafted entry with dir_offset close to the end of the property block and entry->length in 0..3 passes that gate but lets the UUID copy run off the block (e.g. dir_offset = 497, dir_len = 3 in a 500-dword block reads block[497..501]).
2. After the kmemdup, content_len = dir_len - 4 underflows size_t to ~SIZE_MAX, nentries becomes SIZE_MAX / 4, and the entry walk runs OOB on each iteration until an entry fails validation or the kernel oopses on an unmapped page.
Reject dir_len < 4 on the non-root path *before* the UUID kmemdup, which closes both holes.
Also move INIT_LIST_HEAD(&dir->properties) up to immediately after the dir allocation so the new error-return path (and the existing uuid-alloc failure path) calling tb_property_free_dir() sees a walkable list rather than the zero-initialized NULL next/prev that list_for_each_entry_safe() would oops on.
--- drivers/thunderbolt/property.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/thunderbolt/property.c +6 -2
@@ -174,10 +174,16 @@ static struct tb_property_dir *__tb_propif (!dir)return NULL ; +INIT_LIST_HEAD (&dir->properties); +if (is_root) { content_offset = dir_offset +2 ; content_len = dir_len; }else { +if (dir_len <4 ) { +tb_property_free_dir (dir); +return NULL ; + } dir->uuid =kmemdup (&block[dir_offset],sizeof (*dir->uuid),GFP_KERNEL );if (!dir->uuid) {
@@ -191,8 +197,6 @@ static struct tb_property_dir *__tb_prop entries = (const struct tb_property_entry *)&block[content_offset]; nentries = content_len / (sizeof (*entries) /4 ); -INIT_LIST_HEAD (&dir->properties); -for (i =0 ; i < nentries; i++) {struct tb_property *property;
Greg Kroah-Hartman
maintainerPATCH 108/342 scsi: fcoe: Reject FIP descriptors with zero fip_dlen in CVL walker
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 9eed1bd59937e6828b00d2f2dfef631d964f3636 upstream.
drivers/scsi/fcoe/fcoe_ctlr.c::fcoe_ctlr_recv_clr_vlink() advanced the descriptor cursor by an attacker-supplied fip_dlen without ever requiring dlen >= sizeof(struct fip_desc) in the default branch. The named descriptor cases (FIP_DT_MAC, FIP_DT_NAME, FIP_DT_VN_ID) checked their per-type minimum lengths, but a FIP_DT_NON_CRITICAL descriptor (fip_dtype >= 128, which the standard requires receivers to silently ignore) skipped that check entirely.
An unauthenticated L2 peer on the FCoE control VLAN could hang fcoe_ctlr_recv_work on an fcoe, qedf, or bnx2fc initiator indefinitely by emitting one FIP CVL frame whose single descriptor had fip_dtype == FIP_DT_NON_CRITICAL and fip_dlen == 0: the cursor advanced zero bytes per iteration and the loop condition rlen >= sizeof(*desc) stayed true forever, blocking every subsequent FIP frame on that controller.
Tighten the outer dlen guard to also reject dlen < sizeof(struct fip_desc), so a malformed descriptor whose length cannot even cover the descriptor header is rejected before the switch. This is the same lower-bound the named cases already apply and is the minimum scope that closes the loop.
--- drivers/scsi/fcoe/fcoe_ctlr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/fcoe/fcoe_ctlr.c +1 -1
@@ -1391,7 +1391,7 @@ static void fcoe_ctlr_recv_clr_vlink(strwhile (rlen >=sizeof (*desc)) { dlen = desc->fip_dlen *FIP_BPW ; -if (dlen > rlen) +if (dlen <sizeof (*desc) || dlen > rlen) goto err;/* Drop CVL if there are duplicate critical descriptors */ if ((desc->fip_dtype < 32) &&
Greg Kroah-Hartman
maintainerPATCH 109/342 serial: sh-sci: fix memory region release in error path
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hongling Zeng <[email protected]>
commit 92b1ea22454b08a39baef3a7290fb3ec50366616 upstream.
The sci_request_port() function uses request_mem_region() to reserve I/O memory, but in the error path when sci_remap_port() fails, it incorrectly calls release_resource() instead of release_mem_region().
This mismatch can cause resource accounting issues. Fix it by using the correct release function, consistent with sci_release_port().
--- drivers/tty/serial/sh-sci.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/tty/serial/sh-sci.c +1 -1
@@ -2781,7 +2781,7 @@ static int sci_request_port(struct uart_ ret =sci_remap_port (port);if (unlikely (ret !=0 )) { -release_resource (res); +release_mem_region (port->mapbase, sport->reg_size);return ret; }
Greg Kroah-Hartman
maintainerPATCH 110/342 serial: zs: Fix swapped RI/DSR modem line transition counting
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej W. Rozycki <[email protected]>
commit d15cd40cb1858f75846eaafa9a6bca841b790a92 upstream.
Fix a thinko in the status interrupt handler that has caused counters for the RI and DSR modem line transitions to be used for the other line each.
--- drivers/tty/serial/zs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/tty/serial/zs.c +2 -2
@@ -679,9 +679,9 @@ static void zs_status_handle(struct zs_puart_handle_dcd_change (uport, zport->mctrl &TIOCM_CAR );if (delta &TIOCM_RNG ) - uport->icount.dsr++; -if (delta &TIOCM_DSR ) uport->icount.rng++; +if (delta &TIOCM_DSR ) + uport->icount.dsr++;if (delta)wake_up_interruptible (&uport->state->port.delta_msr_wait);
Greg Kroah-Hartman
maintainerPATCH 111/342 serial: fsl_lpuart: fix rx buffer and DMA map leaks in start_rx_dma
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shitalkumar Gandhi <[email protected]>
commit 9a9254c4a2a3ca2b3da16d173f3b0dd01f397ff6 upstream.
lpuart_start_rx_dma() allocates sport->rx_ring.buf with kzalloc() and then maps a scatterlist via dma_map_sg(). On three subsequent error paths the function returns directly without releasing those resources:
- when dma_map_sg() returns 0 (-EINVAL):
ring->buf is leaked.
- when dmaengine_slave_config() fails:
ring->buf and the DMA mapping are leaked.
- when dmaengine_prep_dma_cyclic() returns NULL:
ring->buf and the DMA mapping are leaked.The sole cleanup path, lpuart_dma_rx_free(), is only reached when lpuart_dma_rx_use is set, and the caller lpuart_rx_dma_startup() clears that flag on failure of lpuart_start_rx_dma(). So these resources are permanently leaked on every failure in this function. Repeated port open/close or termios changes under error conditions will slowly consume memory and leave stale streaming DMA mappings behind.
Fix it by introducing two error labels that unmap the scatterlist and free the ring buffer as appropriate. While here, replace the misleading -EFAULT (bad userspace pointer) returned when dmaengine_prep_dma_cyclic() fails with the more accurate -ENOMEM, matching how other dmaengine users in the tree treat this failure.
No functional change on the success path.
--- drivers/tty/serial/fsl_lpuart.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
drivers/tty/serial/fsl_lpuart.c +12 -3
@@ -1234,7 +1234,8 @@ static inline int lpuart_start_rx_dma(stif (!nent) {dev_err (sport->port.dev,"DMA Rx mapping error\n" ); -return -EINVAL ; + ret = -EINVAL ; + goto err_free_buf; } dma_rx_sconfig.src_addr =lpuart_dma_datareg_addr (sport);
@@ -1246,7 +1247,7 @@ static inline int lpuart_start_rx_dma(stif (ret <0 ) {dev_err (sport->port.dev,"DMA Rx slave config failed, err = %d\n" , ret); -return ret; + goto err_unmap_sg; } sport->dma_rx_desc = dmaengine_prep_dma_cyclic(chan,
@@ -1257,7 +1258,8 @@ static inline int lpuart_start_rx_dma(st DMA_PREP_INTERRUPT);if (!sport->dma_rx_desc) {dev_err (sport->port.dev,"Cannot prepare cyclic DMA\n" ); -return -EFAULT ; + ret = -ENOMEM ; + goto err_unmap_sg; } sport->dma_rx_desc->callback = lpuart_dma_rx_complete;
@@ -1275,6 +1277,13 @@ static inline int lpuart_start_rx_dma(st }return 0 ; + +err_unmap_sg: +dma_unmap_sg (chan->device->dev, &sport->rx_sgl,1 ,DMA_FROM_DEVICE ); +err_free_buf: +kfree (ring->buf); + ring->buf =NULL ; +return ret; }static void lpuart_dma_rx_free (struct uart_port *port)
Greg Kroah-Hartman
maintainerPATCH 112/342 serial: dz: Fix bootconsole message clobbering at chip reset
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej W. Rozycki <[email protected]>
commit ca904f4b42355287bc5ce8b7550ebe909cda4c2c upstream.
In the DZ interface as implemented by the DC7085 gate array the serial transmitters are double buffered, meaning that at the time a transmitter is ready to accept the next character there is one in the transmit shift register still being sent to the line. Issuing a master clear at this time causes this character to be lost, so wait an extra amount of time sufficient for the transmit shift register to drain at 9600bps, which is the baud rate setting used by the firmware console.
Mind the specified 1.4us TRDY recovery time in the course and continue using iob() as the completion barrier, since the platforms involved use a write buffer that can delay and combine writes, and reorder them with respect to reads regardless of the MMIO locations accessed and we still lack a platform-independent handler for that.
When called from dz_serial_console_init() this is too early for fsleep() to work and even before lpj has been calculated and therefore the delay is actually not sufficient for the transmitter to drain and is merely a placeholder now. This will be addressed in a follow-up change.
--- drivers/tty/serial/dz.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
drivers/tty/serial/dz.c +21 -0
@@ -544,10 +544,31 @@ static int dz_encode_baud_rate(unsignedstatic void dz_reset (struct dz_port *dport) {struct dz_mux *mux = dport->mux; +unsigned short tcr; +int loops =10000 ;if (mux->initialised)return ; + tcr =dz_in (dport,DZ_TCR ); + +/* Do not disturb any ongoing transmissions. */ +if (dz_in (dport,DZ_CSR ) &DZ_MSE ) { +unsigned short csr, mask; + + mask = tcr; +while ((mask &DZ_LNENB ) && loops--) { + csr =dz_in (dport,DZ_CSR ); +if (!(csr &DZ_TRDY )) +continue ; + mask &= ~(1 << ((csr &DZ_TLINE ) >>8 )); +dz_out (dport,DZ_TCR , mask); +iob (); +udelay (2 );/* 1.4us TRDY recovery. */ + } +udelay (1200 );/* Transmitter drain. */ + } +dz_out (dport,DZ_CSR ,DZ_CLR );while (dz_in (dport,DZ_CSR ) &DZ_CLR );iob ();
Greg Kroah-Hartman
maintainerPATCH 113/342 serial: zs: Fix bootconsole handover lockup
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej W. Rozycki <[email protected]>
commit 6c05cf72e13314ce9b770b5951695dc5a2152920 upstream.
Calling zs_reset() in the course of setting up the serial device causes line parameters to be reset and the transmitter disabled. We've been lucky in that no message is usually produced to the kernel log between this call and the later call to uart_set_options() in the course of console setup done by zs_serial_console_init(), or the system would hang as the console output handler in the firmware tried to access a port the transmitter of which has been disabled and line parameters messed up.
This will change with the next change to the driver, so fix zs_reset() such that line parameters are set for 9600n8 console operation as with the system firmware and the transmitter re-enabled after reset. This also means zs_pm() serves no purpose anymore, so drop it.
--- drivers/tty/serial/zs.c | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-)
drivers/tty/serial/zs.c +8 -21
@@ -105,18 +105,24 @@ struct zs_parms {static struct zs_scc zs_sccs[ZS_NUM_SCCS ]; +/* +* Set parameters in WR5, WR12, WR13 such as not to interfere +* with the initial PROM-based console. Otherwise any output +* produced before the console handover would cause the system +* firmware to hang (TxENAB) or produce rubbish (Tx8, B9600). +*/ static u8 zs_init_regs[ZS_NUM_REGS ]__initdata = {0 ,/* write 0 */ PAR_SPEC ,/* write 1 */ 0 ,/* write 2 */ 0 ,/* write 3 */ X16CLK |SB1 ,/* write 4 */ -0 ,/* write 5 */ + Tx8 | TxENAB,/* write 5 */ 0 ,0 ,0 ,/* write 6, 7, 8 */ MIE |DLC |NV ,/* write 9 */ NRZ ,/* write 10 */ TCBR |RCBR ,/* write 11 */ -0 ,0 ,/* BRG time constant, write 12 + 13 */ +0x16 ,0x00 ,/* BRG time constant, write 12 + 13 */ BRSRC |BRENABL ,/* write 14 */ 0 ,/* write 15 */ };
@@ -955,23 +961,6 @@ static void zs_set_termios(struct uart_pspin_unlock_irqrestore (&scc->zlock, flags); } -/* -* Hack alert! -* Required solely so that the initial PROM-based console -* works undisturbed in parallel with this one. -*/ -static void zs_pm (struct uart_port *uport,unsigned int state, -unsigned int oldstate) -{ -struct zs_port *zport =to_zport (uport); - -if (state <3 ) - zport->regs[5 ] |= TxENAB; -else - zport->regs[5 ] &= ~TxENAB; -write_zsreg (zport,R5 , zport->regs[5 ]); -} -static const char *zs_type (struct uart_port *uport) {
@@ -1054,7 +1043,6 @@ static const struct uart_ops zs_ops = { .startup = zs_startup, .shutdown = zs_shutdown, .set_termios = zs_set_termios, - .pm = zs_pm, .type = zs_type, .release_port = zs_release_port, .request_port = zs_request_port,
@@ -1209,7 +1197,6 @@ static int __init zs_console_setup(strucreturn ret;zs_reset (zport); -zs_pm (uport,0 ,-1 );if (options)uart_parse_options (options, &baud, &parity, &bits, &flow);
Greg Kroah-Hartman
maintainerPATCH 114/342 serial: zs: Switch to using channel reset
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej W. Rozycki <[email protected]>
commit 8572955630f30948837088aa98bcbe0532d1ceac upstream.
Switch the driver to using the channel reset rather than hardware reset, simplifying handling by removing an interference between channels that causes the other channel to become uninitialised afterwards.
There is little difference between the two kinds of reset in terms of register settings that result, and we initialise the whole register set right away anyway. However this prevents a hang from happening should the console output handler in the firmware try to access the other port whose transmitter has been disabled and line parameters messed up.
For example this will happen if the keyboard port (port A) is chosen for the system console, unusually but not insanely for a headless system, as the port is wired to a standard DA-15 connector and an adapter can be easily made. Or with the next change in place this would happen for the regular console port (port B), since the keyboard port (port A) will be initialised first.
Just remove the unnecessary complication then, a channel reset is good enough. We still need the initialisation marker, now per channel rather than per SCC, as for the console port zs_reset() will be called twice:
once early on via zs_serial_console_init() for the console setup only, and then again via zs_config_port() as the port is associated with a TTY device.
--- drivers/tty/serial/zs.c | 7 ++++--- drivers/tty/serial/zs.h | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-)
drivers/tty/serial/zs.c +4 -3
@@ -831,21 +831,22 @@ static void zs_shutdown(struct uart_portstatic void zs_reset (struct zs_port *zport) { +struct zs_port *zport_a = &zport->scc->zport[ZS_CHAN_A ];struct zs_scc *scc = zport->scc;int irq;unsigned long flags;spin_lock_irqsave (&scc->zlock, flags); irq = !irqs_disabled_flags (flags); -if (!scc->initialised) { +if (!zport->initialised) {/* Reset the pointer first, just in case... */ read_zsreg (zport,R0 );/* And let the current transmission finish. */ zs_line_drain (zport, irq); -write_zsreg (zport,R9 ,FHWRES ); +write_zsreg (zport,R9 , zport == zport_a ?CHRA :CHRB );udelay (10 );write_zsreg (zport,R9 ,0 ); - scc->initialised =1 ; + zport->initialised =1 ; }load_zsregs (zport, zport->regs, irq);spin_unlock_irqrestore (&scc->zlock, flags);
drivers/tty/serial/zs.h +1 -1
@@ -22,6 +22,7 @@struct zs_port {struct zs_scc *scc;/* Containing SCC. */ struct uart_port port;/* Underlying UART. */ +int initialised;/* For the console port. */ int clk_mode;/* May be 1, 16, 32, or 64. */
@@ -41,7 +42,6 @@ struct zs_scc {struct zs_port zport[2 ];spinlock_t zlock; atomic_t irq_guard; - int initialised; };#endif /* __KERNEL__ */
Greg Kroah-Hartman
maintainerPATCH 115/342 Bluetooth: hci_core: Fix use-after-free in vhci_flush()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
commit 1d6123102e9fbedc8d25bf4731da6d513173e49e upstream.
syzbot reported use-after-free in vhci_flush() without repro. [0]
Quoted 1 line
From the splat, a thread close()d a vhci file descriptor while
its device was being used by iotcl() on another thread.
Once the last fd refcnt is released, vhci_release() calls hci_unregister_dev(), hci_free_dev(), and kfree() for struct vhci_data, which is set to hci_dev->dev->driver_data.
The problem is that there is no synchronisation after unlinking hdev from hci_dev_list in hci_unregister_dev(). There might be another thread still accessing the hdev which was fetched before the unlink operation.
We can use SRCU for such synchronisation.
Let's run hci_dev_reset() under SRCU and wait for its completion in hci_unregister_dev().
Another option would be to restore hci_dev->destruct(), which was removed in commit 587ae086f6e4 ("Bluetooth: Remove unused hci-destruct cb"). However, this would not be a good solution, as we should not run hci_unregister_dev() while there are in-flight ioctl() requests, which could lead to another data-race KCSAN splat.
Note that other drivers seem to have the same problem, for exmaple, virtbt_remove().
[0]:
BUG: KASAN: slab-use-after-free in skb_queue_empty_lockless include/linux/skbuff.h:1891 [inline] BUG: KASAN: slab-use-after-free in skb_queue_purge_reason+0x99/0x360 net/core/skbuff.c:3937 Read of size 8 at addr ffff88807cb8d858 by task syz.1.219/6718 CPU: 1 UID: 0 PID: 6718 Comm: syz.1.219 Not tainted 6.16.0-rc1-syzkaller-00196-g08207f42d3ff #0 PREEMPT(full) Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 05/07/2025 Call Trace: <TASK> dump_stack_lvl+0x189/0x250 lib/dump_stack.c:120 print_address_description mm/kasan/report.c:408 [inline] print_report+0xd2/0x2b0 mm/kasan/report.c:521 kasan_report+0x118/0x150 mm/kasan/report.c:634 skb_queue_empty_lockless include/linux/skbuff.h:1891 [inline] skb_queue_purge_reason+0x99/0x360 net/core/skbuff.c:3937 skb_queue_purge include/linux/skbuff.h:3368 [inline] vhci_flush+0x44/0x50 drivers/bluetooth/hci_vhci.c:69 hci_dev_do_reset net/bluetooth/hci_core.c:552 [inline] hci_dev_reset+0x420/0x5c0 net/bluetooth/hci_core.c:592 sock_do_ioctl+0xd9/0x300 net/socket.c:1190 sock_ioctl+0x576/0x790 net/socket.c:1311 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:907 [inline] __se_sys_ioctl+0xf9/0x170 fs/ioctl.c:893 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:0x7fcf5b98e929 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:00007fcf5c7b9038 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00007fcf5bbb6160 RCX: 00007fcf5b98e929 RDX: 0000000000000000 RSI: 00000000400448cb RDI: 0000000000000009 RBP: 00007fcf5ba10b39 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000000000 R14: 00007fcf5bbb6160 R15: 00007ffd6353d528 </TASK> Allocated by task 6535: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 poison_kmalloc_redzone mm/kasan/common.c:377 [inline] __kasan_kmalloc+0x93/0xb0 mm/kasan/common.c:394 kasan_kmalloc include/linux/kasan.h:260 [inline] __kmalloc_cache_noprof+0x230/0x3d0 mm/slub.c:4359 kmalloc_noprof include/linux/slab.h:905 [inline] kzalloc_noprof include/linux/slab.h:1039 [inline] vhci_open+0x57/0x360 drivers/bluetooth/hci_vhci.c:635 misc_open+0x2bc/0x330 drivers/char/misc.c:161 chrdev_open+0x4c9/0x5e0 fs/char_dev.c:414 do_dentry_open+0xdf0/0x1970 fs/open.c:964 vfs_open+0x3b/0x340 fs/open.c:1094 do_open fs/namei.c:3887 [inline] path_openat+0x2ee5/0x3830 fs/namei.c:4046 do_filp_open+0x1fa/0x410 fs/namei.c:4073 do_sys_openat2+0x121/0x1c0 fs/open.c:1437 do_sys_open fs/open.c:1452 [inline] __do_sys_openat fs/open.c:1468 [inline] __se_sys_openat fs/open.c:1463 [inline] __x64_sys_openat+0x138/0x170 fs/open.c:1463 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 Freed by task 6535: kasan_save_stack mm/kasan/common.c:47 [inline] kasan_save_track+0x3e/0x80 mm/kasan/common.c:68 kasan_save_free_info+0x46/0x50 mm/kasan/generic.c:576 poison_slab_object mm/kasan/common.c:247 [inline] __kasan_slab_free+0x62/0x70 mm/kasan/common.c:264 kasan_slab_free include/linux/kasan.h:233 [inline] slab_free_hook mm/slub.c:2381 [inline] slab_free mm/slub.c:4643 [inline] kfree+0x18e/0x440 mm/slub.c:4842 vhci_release+0xbc/0xd0 drivers/bluetooth/hci_vhci.c:671 __fput+0x44c/0xa70 fs/file_table.c:465 task_work_run+0x1d1/0x260 kernel/task_work.c:227 exit_task_work include/linux/task_work.h:40 [inline] do_exit+0x6ad/0x22e0 kernel/exit.c:955 do_group_exit+0x21c/0x2d0 kernel/exit.c:1104 __do_sys_exit_group kernel/exit.c:1115 [inline] __se_sys_exit_group kernel/exit.c:1113 [inline] __x64_sys_exit_group+0x3f/0x40 kernel/exit.c:1113 x64_sys_call+0x21ba/0x21c0 arch/x86/include/generated/asm/syscalls_64.h:232 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 The buggy address belongs to the object at ffff88807cb8d800 which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 88 bytes inside of
freed 1024-byte region [ffff88807cb8d800, ffff88807cb8dc00)
--- include/net/bluetooth/hci_core.h | 2 ++ net/bluetooth/hci_core.c | 34 ++++++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 4 deletions(-)
include/net/bluetooth/hci_core.h +2 -0
@@ -28,6 +28,7 @@#include <linux/idr.h> #include <linux/leds.h> #include <linux/rculist.h> +#include <linux/srcu.h> #include <net/bluetooth/hci.h> #include <net/bluetooth/hci_sock.h>
@@ -285,6 +286,7 @@ struct amp_assoc {struct hci_dev {struct list_head list; +struct srcu_struct srcu;struct mutex lock;const char *name;
net/bluetooth/hci_core.c +30 -4
@@ -1040,7 +1040,7 @@ static int hci_linkpol_req(struct hci_request *req, unsigned long opt)/* Get HCI device by index. * Device is held on return. */ -struct hci_dev *hci_dev_get (int index) +static struct hci_dev *__hci_dev_get (int index,int *srcu_index) {struct hci_dev *hdev =NULL , *d;
@@ -1053,6 +1053,8 @@ struct hci_dev *hci_dev_get(int index)list_for_each_entry (d, &hci_dev_list, list) {if (d->id == index) { hdev =hci_dev_hold (d); +if (srcu_index) + *srcu_index =srcu_read_lock (&d->srcu);break ; } }
@@ -1060,6 +1062,22 @@ struct hci_dev *hci_dev_get(int index)return hdev; } +struct hci_dev *hci_dev_get (int index) +{ +return __hci_dev_get (index,NULL ); +} + +static struct hci_dev *hci_dev_get_srcu (int index,int *srcu_index) +{ +return __hci_dev_get (index, srcu_index); +} + +static void hci_dev_put_srcu (struct hci_dev *hdev,int srcu_index) +{ +srcu_read_unlock (&hdev->srcu, srcu_index); +hci_dev_put (hdev); +} +/* ---- Inquiry support ---- */ bool hci_discovery_active (struct hci_dev *hdev)
@@ -1906,9 +1924,9 @@ static int hci_dev_do_reset(struct hci_dev *hdev)int hci_dev_reset (__u16 dev) {struct hci_dev *hdev; -int err; +int err, srcu_index; - hdev =hci_dev_get (dev); + hdev =hci_dev_get_srcu (dev, &srcu_index);if (!hdev)return -ENODEV ;
@@ -1930,7 +1948,7 @@ int hci_dev_reset(__u16 dev) err =hci_dev_do_reset (hdev); done: -hci_dev_put (hdev); +hci_dev_put_srcu (hdev, srcu_index);return err; }
@@ -3596,6 +3614,11 @@ struct hci_dev *hci_alloc_dev(void)if (!hdev)return NULL ; +if (init_srcu_struct (&hdev->srcu)) { +kfree (hdev); +return NULL ; + } + hdev->pkt_type = (HCI_DM1 |HCI_DH1 |HCI_HV1 ); hdev->esco_type = (ESCO_HV1 ); hdev->link_mode = (HCI_LM_ACCEPT );
@@ -3839,6 +3862,9 @@ void hci_unregister_dev(struct hci_dev *hdev)list_del (&hdev->list);write_unlock (&hci_dev_list_lock); +synchronize_srcu (&hdev->srcu); +cleanup_srcu_struct (&hdev->srcu); +cancel_work_sync (&hdev->rx_work);cancel_work_sync (&hdev->cmd_work);cancel_work_sync (&hdev->tx_work);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 116/342 USB: serial: cypress_m8: fix memory corruption with small endpoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit e1a9d791fd66ab2431b9e6f6f835823809869047 upstream.
Make sure that the interrupt-out endpoint max packet size is at least eight bytes to avoid user-controlled slab corruption or NULL-pointer dereference should a malicious device report a smaller size.
--- drivers/usb/serial/cypress_m8.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/usb/serial/cypress_m8.c +8 -0
@@ -447,6 +447,14 @@ static int cypress_generic_port_probe(struct usb_serial_port *port)return -ENODEV ; } +/* +* The buffer must be large enough for the one or two-byte header (and +* following data), but assume anything smaller than eight bytes is +* broken. +*/ +if (port->interrupt_out_size <8 ) +return -EINVAL ; + priv =kzalloc (sizeof (struct cypress_private ),GFP_KERNEL );if (!priv)return -ENOMEM ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 117/342 USB: serial: digi_acceleport: fix memory corruption with small endpoints
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit cb3560e8eab1dfa1cac1ed52631adf8ec6ff2cd5 upstream.
Add the missing bulk-out buffer size sanity checks to avoid out-of-bounds memory accesses or slab corruption should a malicious device report smaller buffers than expected.
--- drivers/usb/serial/digi_acceleport.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
drivers/usb/serial/digi_acceleport.c +21 -2
@@ -1229,15 +1229,34 @@ static int digi_port_init(struct usb_serial_port *port, unsigned port_num)static int digi_startup (struct usb_serial *serial) {struct digi_serial *serial_priv; +int oob_port_num;int ret; +int i; + +/* +* The port bulk-out buffers must be large enough for header and +* buffered data. +*/ +for (i =0 ; i < serial->type->num_ports; i++) { +if (serial->port[i]->bulk_out_size <DIGI_OUT_BUF_SIZE +2 ) +return -EINVAL ; + } + +/* +* The OOB port bulk-out buffer must be large enough for the two +* commands in digi_set_modem_signals(). +*/ + oob_port_num = serial->type->num_ports; +if (serial->port[oob_port_num]->bulk_out_size <8 ) +return -EINVAL ; serial_priv =kzalloc (sizeof (*serial_priv),GFP_KERNEL );if (!serial_priv)return -ENOMEM ;spin_lock_init (&serial_priv->ds_serial_lock); - serial_priv->ds_oob_port_num = serial->type->num_ports; - serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num]; + serial_priv->ds_oob_port_num = oob_port_num; + serial_priv->ds_oob_port = serial->port[oob_port_num]; ret =digi_port_init (serial_priv->ds_oob_port, serial_priv->ds_oob_port_num);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 118/342 xhci: tegra: Fix ghost USB device on dual-role port unplug
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wei-Cheng Chen <[email protected]>
[ Upstream commit 5a4c828b8b29b47534814ade26d9aee09d5101fc ]
When a USB device is unplugged from the dual-role port, the device-mode path in tegra_xhci_id_work() explicitly clears both SS and HS port power via direct hub_control ClearPortFeature(POWER) calls. This preempts the xHCI controller's normal disconnect processing -- PORT_CSC is never generated, the USB core never sees the disconnect, and the device remains in its internal tree as a ghost visible in lsusb.
Add an otg_set_port_power flag to control whether the dual-role switch path performs explicit port power management. SoCs that need it (Tegra124 / Tegra210 / Tegra186) set the flag; later SoCs (Tegra194 and beyond) rely on the PHY mode change to handle disconnect naturally and skip all port power calls.
Within the port power path, otg_reset_sspi additionally gates the SSPI reset sequence on host-mode entry for SoCs that require it.
Flags set per SoC:
Tegra124, Tegra186 -> otg_set_port_power Tegra210 -> otg_set_port_power, otg_reset_sspi Tegra194 and later -> (none)
[ Backport to 5.10.y: keep the host-mode snapshot in the existing
tegra->lock section, retain pm_runtime_mark_last_busy() in the host port-power path, and omit the newer Tegra234 entry. ]
--- drivers/usb/host/xhci-tegra.c | 78 ++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 34 deletions(-)
drivers/usb/host/xhci-tegra.c +44 -34
@@ -208,6 +208,7 @@ struct tegra_xusb_soc {bool has_ipfs;bool lpm_support;bool otg_reset_sspi; +bool otg_set_port_power; };struct tegra_xusb_context {
@@ -1161,14 +1162,17 @@ static void tegra_xhci_id_work(struct work_struct *work)struct tegra_xusb_mbox_msg msg;struct phy *phy =tegra_xusb_get_phy (tegra,"usb2" , tegra->otg_usb2_port); +bool host_mode;u32 status;int ret; -dev_dbg (tegra->dev,"host mode %s\n" , tegra->host_mode ?"on" :"off" ); -mutex_lock (&tegra->lock); -if (tegra->host_mode) + host_mode = tegra->host_mode; + +dev_dbg (tegra->dev,"host mode %s\n" , host_mode ?"on" :"off" ); + +if (host_mode)phy_set_mode_ext (phy,PHY_MODE_USB_OTG ,USB_ROLE_HOST );else phy_set_mode_ext (phy,PHY_MODE_USB_OTG ,USB_ROLE_NONE );
@@ -1179,42 +1183,44 @@ static void tegra_xhci_id_work(struct work_struct *work) tegra->otg_usb2_port);pm_runtime_get_sync (tegra->dev); -if (tegra->host_mode) { -/* switch to host mode */ -if (tegra->otg_usb3_port >=0 ) { -if (tegra->soc->otg_reset_sspi) { -/* set PP=0 */ - tegra_xhci_hc_driver.hub_control ( - xhci->shared_hcd, GetPortStatus, -0 , tegra->otg_usb3_port+1 , - (char *) &status,sizeof (status)); -if (status &USB_SS_PORT_STAT_POWER ) -tegra_xhci_set_port_power (tegra, false, - false); - -/* reset OTG port SSPI */ - msg.cmd =MBOX_CMD_RESET_SSPI ; - msg.data = tegra->otg_usb3_port+1 ; - - ret =tegra_xusb_mbox_send (tegra, &msg); -if (ret <0 ) { -dev_info (tegra->dev, -"failed to RESET_SSPI %d\n" , - ret); +if (tegra->soc->otg_set_port_power) { +if (host_mode) { +/* switch to host mode */ +if (tegra->otg_usb3_port >=0 ) { +if (tegra->soc->otg_reset_sspi) { +/* set PP=0 */ + tegra_xhci_hc_driver.hub_control ( + xhci->shared_hcd, GetPortStatus, +0 , tegra->otg_usb3_port+1 , + (char *) &status,sizeof (status)); +if (status &USB_SS_PORT_STAT_POWER ) +tegra_xhci_set_port_power (tegra, false, + false); + +/* reset OTG port SSPI */ + msg.cmd =MBOX_CMD_RESET_SSPI ; + msg.data = tegra->otg_usb3_port+1 ; + + ret =tegra_xusb_mbox_send (tegra, &msg); +if (ret <0 ) { +dev_info (tegra->dev, +"failed to RESET_SSPI %d\n" , + ret); + } } - } -tegra_xhci_set_port_power (tegra, false, true); - } +tegra_xhci_set_port_power (tegra, false, true); + } -tegra_xhci_set_port_power (tegra, true, true); -pm_runtime_mark_last_busy (tegra->dev); +tegra_xhci_set_port_power (tegra, true, true); +pm_runtime_mark_last_busy (tegra->dev); - }else { -if (tegra->otg_usb3_port >=0 ) -tegra_xhci_set_port_power (tegra, false, false); + }else { +if (tegra->otg_usb3_port >=0 ) +tegra_xhci_set_port_power (tegra, false, false); -tegra_xhci_set_port_power (tegra, true, false); +tegra_xhci_set_port_power (tegra, true, false); + } }pm_runtime_put_autosuspend (tegra->dev); }
@@ -1925,6 +1931,7 @@ static const struct tegra_xusb_soc tegra124_soc = { .scale_ss_clock = true, .has_ipfs = true, .otg_reset_sspi = false, + .otg_set_port_power = true, .mbox = { .cmd = 0xe4, .data_in = 0xe8,
@@ -1961,6 +1968,7 @@ static const struct tegra_xusb_soc tegra210_soc = { .scale_ss_clock = false, .has_ipfs = true, .otg_reset_sspi = true, + .otg_set_port_power = true, .mbox = { .cmd = 0xe4, .data_in = 0xe8,
@@ -2002,6 +2010,7 @@ static const struct tegra_xusb_soc tegra186_soc = { .scale_ss_clock = false, .has_ipfs = false, .otg_reset_sspi = false, + .otg_set_port_power = true, .mbox = { .cmd = 0xe4, .data_in = 0xe8,
@@ -2033,6 +2042,7 @@ static const struct tegra_xusb_soc tegra194_soc = { .scale_ss_clock = false, .has_ipfs = false, .otg_reset_sspi = false, + .otg_set_port_power = false, .mbox = { .cmd = 0x68, .data_in = 0x6c,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 119/342 serial: dz: Fix bootconsole handover lockup
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej W. Rozycki <[email protected]>
commit 7f127b2208e5e2b817243cad41fe4211a6d5a7a3 upstream.
Calling dz_reset() in the course of setting up the serial device causes line parameters to be reset and the transmitter disabled. We've been lucky in that no message is usually produced to the kernel log between this call and the later call to uart_set_options() in the course of console setup done by dz_serial_console_init(), or the system would hang as the console output handler in the firmware tried to access a port the transmitter of which has been disabled and line parameters messed up.
This will change with the next change to the driver, so fix dz_reset() such that line parameters are set for 9600n8 console operation as with the system firmware and the transmitter re-enabled after reset. This also means dz_pm() serves no purpose anymore, so drop it.
--- drivers/tty/serial/dz.c | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-)
drivers/tty/serial/dz.c +13 -24
@@ -546,6 +546,7 @@ static void dz_reset(struct dz_port *dport)struct dz_mux *mux = dport->mux;unsigned short tcr;int loops =10000 ; +int line;if (mux->initialised)return ;
@@ -573,6 +574,18 @@ static void dz_reset(struct dz_port *dport)while (dz_in (dport,DZ_CSR ) &DZ_CLR );iob (); +/* +* Set parameters across all lines such as not to interfere +* with the initial PROM-based console. Otherwise any output +* produced before the console handover would cause the system +* firmware to produce rubbish. +*/ +for (line =0 ; line <DZ_NB_PORT ; line++) +dz_out (dport,DZ_LPR ,DZ_B9600 |DZ_CS8 | line); + +/* Re-enable transmission for the initial PROM-based console. */ +dz_out (dport,DZ_TCR , tcr); +/* Enable scanning. */ dz_out (dport,DZ_CSR ,DZ_MSE );
@@ -653,26 +666,6 @@ static void dz_set_termios(struct uart_port *uport, struct ktermios *termios,spin_unlock_irqrestore (&dport->port.lock, flags); } -/* -* Hack alert! -* Required solely so that the initial PROM-based console -* works undisturbed in parallel with this one. -*/ -static void dz_pm (struct uart_port *uport,unsigned int state, -unsigned int oldstate) -{ -struct dz_port *dport =to_dport (uport); -unsigned long flags; - -spin_lock_irqsave (&dport->port.lock, flags); -if (state <3 ) -dz_start_tx (&dport->port); -else -dz_stop_tx (&dport->port); -spin_unlock_irqrestore (&dport->port.lock, flags); -} - -static const char *dz_type (struct uart_port *uport) {return "DZ" ;
@@ -768,7 +761,6 @@ static const struct uart_ops dz_ops = { .startup = dz_startup, .shutdown = dz_shutdown, .set_termios = dz_set_termios, - .pm = dz_pm, .type = dz_type, .release_port = dz_release_port, .request_port = dz_request_port,
@@ -893,10 +885,7 @@ static int __init dz_console_setup(struct console *co, char *options)if (ret)return ret; -spin_lock_init (&dport->port.lock);/* For dz_pm(). */ -dz_reset (dport); -dz_pm (uport,0 ,-1 );if (options)uart_parse_options (options, &baud, &parity, &bits, &flow);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 120/342 page_pool: Fix use-after-free in page_pool_recycle_in_ring
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dong Chenchen <[email protected]>
[ Upstream commit 271683bb2cf32e5126c592b5d5e6a756fa374fd9 ]
syzbot reported a uaf in page_pool_recycle_in_ring:
BUG: KASAN: slab-use-after-free in lock_release+0x151/0xa30 kernel/locking/lockdep.c:5862 Read of size 8 at addr ffff8880286045a0 by task syz.0.284/6943
root cause is:
page_pool_recycle_in_ring
ptr_ring_produce
spin_lock(&r->producer_lock);
WRITE_ONCE(r->queue[r->producer++], ptr)
//recycle last page to pool
page_pool_release
page_pool_scrub
page_pool_empty_ring
ptr_ring_consume
page_pool_return_page //release all page
__page_pool_destroy
free_percpu(pool->recycle_stats);
free(pool) //free
spin_unlock(&r->producer_lock); //pool->ring uaf read recycle_stat_inc(pool, ring);
page_pool can be free while page pool recycle the last page in ring. Add producer-lock barrier to page_pool_release to prevent the page pool from being free before all pages have been recycled.
[v5.10: introduced page_pool_producer_lock/unlock helpers inline since
prerequisite commit 368d3cb406cd ("page_pool: fix inconsistency for page_pool_ring_[un]lock()") depends on page_pool_put_page_bulk which does not exist in 5.10; used in_serving_softirq() per 5.10 convention; kept struct page * API (no netmem_ref); dropped recycle_stat_inc change as page pool stats do not exist in this tree]
--- net/core/page_pool.c | 39 +++++++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 6 deletions(-)
net/core/page_pool.c +33 -6
@@ -318,16 +318,39 @@ static void page_pool_return_page(struct page_pool *pool, struct page *page)*/ } +static bool page_pool_producer_lock (struct page_pool *pool) + __acquires(&pool->ring.producer_lock) +{ +bool in_softirq =in_serving_softirq (); + +if (in_softirq) +spin_lock (&pool->ring.producer_lock); +else +spin_lock_bh (&pool->ring.producer_lock); + +return in_softirq; +} + +static void page_pool_producer_unlock (struct page_pool *pool, +bool in_softirq) + __releases(&pool->ring.producer_lock) +{ +if (in_softirq) +spin_unlock (&pool->ring.producer_lock); +else +spin_unlock_bh (&pool->ring.producer_lock); +} +static bool page_pool_recycle_in_ring (struct page_pool *pool,struct page *page) { -int ret; +bool in_softirq, ret; +/* BH protection not needed if current is serving softirq */ -if (in_serving_softirq ()) - ret =ptr_ring_produce (&pool->ring, page); -else - ret =ptr_ring_produce_bh (&pool->ring, page); + in_softirq =page_pool_producer_lock (pool); + ret = !__ptr_ring_produce (&pool->ring, page); +page_pool_producer_unlock (pool, in_softirq); -return (ret ==0 ) ? true : false; +return ret; }/* Only allow direct recycling in special circumstances, into the
@@ -464,10 +487,14 @@ static void page_pool_scrub(struct page_pool *pool)static int page_pool_release (struct page_pool *pool) { +bool in_softirq;int inflight;page_pool_scrub (pool); inflight =page_pool_inflight (pool); +/* Acquire producer lock to make sure producers have exited. */ + in_softirq =page_pool_producer_lock (pool); +page_pool_producer_unlock (pool, in_softirq);if (!inflight)page_pool_free (pool);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 121/342 team: Move team device type change at the end of team_port_add
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikola Z. Ivanov <[email protected]>
commit 0ae9cfc454ea5ead5f3ddbdfe2e70270d8e2c8ef upstream.
Attempting to add a port device that is already up will expectedly fail, but not before modifying the team device header_ops.
In the case of the syzbot reproducer the gre0 device is already in state UP when it attempts to add it as a
port device of team0, this fails but before that header_ops->create of team0 is changed from eth_header to ipgre_header in the call to team_dev_type_check_change.
Later when we end up in ipgre_header() struct ip_tunnel* points to nonsense as the private data of the device still holds a struct team.
Example sequence of iproute2 commands to reproduce the hang/BUG():
ip link add dev team0 type team
ip link add dev gre0 type gre
ip link set dev gre0 up
ip link set dev gre0 master team0
ip link set dev team0 up
ping -I team0 1.1.1.1
Move team_dev_type_check_change down where all other checks have passed as it changes the dev type with no way to restore it in case one of the checks that follow it fail.
Also make sure to preserve the origial mtu assignment:
- If port_dev is not the same type as dev, dev takes mtu from port_dev
- If port_dev is the same type as dev, port_dev takes mtu from dev
This is done by adding a conditional before the call to dev_set_mtu to prevent it from assigning port_dev->mtu = dev->mtu and instead letting team_dev_type_check_change assign dev->mtu = port_dev->mtu. The conditional is needed because the patch moves the call to team_dev_type_check_change past dev_set_mtu.
Testing:
- team device driver in-tree selftests
- Add/remove various devices as slaves of team device
- syzbot
[ Alexey: backport to 5.10: adjust path from drivers/net/team/team_core.c to drivers/net/team/team.c ]
--- drivers/net/team/team.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-)
drivers/net/team/team.c +15 -8
@@ -1180,10 +1180,6 @@ static int team_port_add(struct team *team, struct net_device *port_dev,return -EPERM ; } - err =team_dev_type_check_change (dev, port_dev); -if (err) -return err; -if (port_dev->flags &IFF_UP ) {NL_SET_ERR_MSG (extack,"Device is up. Set it down before adding it as a team port" ); netdev_err(dev, "Device %s is up. Set it down before adding it as a team port\n",
@@ -1201,10 +1197,16 @@ static int team_port_add(struct team *team, struct net_device *port_dev,INIT_LIST_HEAD (&port->qom_list); port->orig.mtu = port_dev->mtu; - err =dev_set_mtu (port_dev, dev->mtu); -if (err) { -netdev_dbg (dev,"Error %d calling dev_set_mtu\n" , err); - goto err_set_mtu; +/* +* MTU assignment will be handled in team_dev_type_check_change +* if dev and port_dev are of different types +*/ +if (dev->type == port_dev->type) { + err =dev_set_mtu (port_dev, dev->mtu); +if (err) { +netdev_dbg (dev,"Error %d calling dev_set_mtu\n" , err); + goto err_set_mtu; + } }memcpy (port->orig.dev_addr, port_dev->dev_addr, port_dev->addr_len);
@@ -1279,6 +1281,10 @@ static int team_port_add(struct team *team, struct net_device *port_dev, } } + err =team_dev_type_check_change (dev, port_dev); +if (err) + goto err_set_dev_type; +if (dev->flags &IFF_UP ) {netif_addr_lock_bh (dev);dev_uc_sync_multiple (port_dev, dev);
@@ -1297,6 +1303,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev,return 0 ; +err_set_dev_type: err_set_slave_promisc:__team_option_inst_del_port (team, port);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 122/342 usb: core: Fix SuperSpeed root hub wMaxPacketSize
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Pecio <[email protected]>
commit d1e280334b7f0a1df441e08bd1f6a1bcc36b3bbb upstream.
There is no good reason to have wBytesPerInterval < wMaxPacketSize - either one is too low or the other too high, and we may want to warn about such descriptors. Start with cleaning up our own root hubs.
USB 3.2 section 10.15.1 sets wMaxPacketSize and wBytesPerInterval of SuperSpeed hub status endpoints at 2 bytes, so reduce wMaxPacketSize from its former value of 4, which was derived from USB 2.0 spec and the kernel's USB_MAXCHILDREN limit. They don't apply because USB 3.2 10.15.2.1 specifies SuperSpeed hubs to have up to 15 ports.
--- drivers/usb/core/hcd.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/usb/core/hcd.c +1 -3
@@ -353,9 +353,7 @@ static const u8 ss_rh_config_descriptor[USB_DT_ENDPOINT ,/* __u8 ep_bDescriptorType; Endpoint */ 0x81 ,/* __u8 ep_bEndpointAddress; IN Endpoint 1 */ 0x03 ,/* __u8 ep_bmAttributes; Interrupt */ -/* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) -* see hub.c:hub_configure() for details. */ - (USB_MAXCHILDREN +1 +7 ) /8 ,0x00 , +0x02 ,0x00 ,/* __le16 ep_wMaxPacketSize; 2 bytes per USB3 10.15.1 */ 0x0c ,/* __u8 ep_bInterval; (256ms -- usb 2.0 spec) */ /* one SuperSpeed endpoint companion descriptor */
Greg Kroah-Hartman
maintainerPATCH 123/342 bpf: Free reuseport cBPF prog after RCU grace period.
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 18fc650ccd7fe3376eca89203668cfb8268f60df ]
Eulgyu Kim reported the splat below with a repro. [0]
The repro sets up a UDP reuseport group with a cBPF prog and replaces it with a new one while another thread is sending a UDP packet to the group.
The reuseport prog is freed by sk_reuseport_prog_free(). bpf_prog_put() is called for "e"BPF prog to destruct through multiple stages while cBPF prog is freed immediately by bpf_release_orig_filter() and bpf_prog_free().
If a reuseport prog is detached from the setsockopt() path (reuseport_attach_prog() or reuseport_detach_prog()), sk_reuseport_prog_free() is called without waiting for RCU readers to complete, resulting in various bugs.
Let's defer freeing the reuseport cBPF prog after one RCU grace period.
Note "e"BPF prog is safe as is unless the fast path starts to touch fields destroyed in bpf_prog_put_deferred() and __bpf_prog_put_noref().
[0]:
BUG: KASAN: vmalloc-out-of-bounds in reuseport_select_sock+0xedc/0x1220 net/core/sock_reuseport.c:596 Read of size 4 at addr ffffc9000051e004 by task slowme/10208 CPU: 6 UID: 1000 PID: 10208 Comm: slowme Not tainted 7.0.0-geb7ac95ff75e #32 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: <IRQ> dump_stack_lvl+0xe8/0x150 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 reuseport_select_sock+0xedc/0x1220 net/core/sock_reuseport.c:596 udp4_lib_lookup2+0x3bc/0x950 net/ipv4/udp.c:495 __udp4_lib_lookup+0x768/0xe20 net/ipv4/udp.c:723 __udp4_lib_lookup_skb+0x297/0x390 net/ipv4/udp.c:752 __udp4_lib_rcv+0x1312/0x2620 net/ipv4/udp.c:2752 ip_protocol_deliver_rcu+0x282/0x440 net/ipv4/ip_input.c:207 ip_local_deliver_finish+0x3bb/0x6f0 net/ipv4/ip_input.c:241 NF_HOOK+0x30c/0x3a0 include/linux/netfilter.h:318 NF_HOOK+0x30c/0x3a0 include/linux/netfilter.h:318 __netif_receive_skb_one_core net/core/dev.c:6181 [inline] __netif_receive_skb net/core/dev.c:6294 [inline] process_backlog+0xaa4/0x1960 net/core/dev.c:6645 __napi_poll+0xae/0x340 net/core/dev.c:7709 napi_poll net/core/dev.c:7772 [inline] net_rx_action+0x5d7/0xf50 net/core/dev.c:7929 handle_softirqs+0x22b/0x870 kernel/softirq.c:622 do_softirq+0x76/0xd0 kernel/softirq.c:523 </IRQ> <TASK> __local_bh_enable_ip+0xf8/0x130 kernel/softirq.c:450 local_bh_enable include/linux/bottom_half.h:33 [inline] rcu_read_unlock_bh include/linux/rcupdate.h:924 [inline] __dev_queue_xmit+0x1dd7/0x3710 net/core/dev.c:4890 neigh_output include/net/neighbour.h:556 [inline] ip_finish_output2+0xca9/0x1070 net/ipv4/ip_output.c:237 NF_HOOK_COND include/linux/netfilter.h:307 [inline] ip_output+0x29f/0x450 net/ipv4/ip_output.c:438 ip_send_skb+0x45/0xc0 net/ipv4/ip_output.c:1508 udp_send_skb+0xb04/0x1510 net/ipv4/udp.c:1195 udp_sendmsg+0x1a71/0x2350 net/ipv4/udp.c:1485 sock_sendmsg_nosec net/socket.c:727 [inline] __sock_sendmsg net/socket.c:742 [inline] __sys_sendto+0x554/0x680 net/socket.c:2206 __do_sys_sendto net/socket.c:2213 [inline] __se_sys_sendto net/socket.c:2209 [inline] __x64_sys_sendto+0xde/0x100 net/socket.c:2209 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline] do_syscall_64+0x160/0xf80 arch/x86/entry/syscall_64.c:94 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x415a2d Code: b3 66 2e 0f 1f 84 00 00 00 00 00 66 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 b8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f6bc31e41e8 EFLAGS: 00000212 ORIG_RAX: 000000000000002c RAX: ffffffffffffffda RBX: 00007f6bc31e4cdc RCX: 0000000000415a2d RDX: 0000000000000001 RSI: 00007f6bc31e421f RDI: 0000000000000003 RBP: 00007f6bc31e4240 R08: 00007f6bc31e4220 R09: 0000000000000010 R10: 0000000000000000 R11: 0000000000000212 R12: 00007f6bc31e46c0 R13: ffffffffffffffb8 R14: 0000000000000000 R15: 00007ffc9b0d70b0 </TASK>
--- net/core/filter.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-)
net/core/filter.c +12 -3
@@ -1640,15 +1640,24 @@ int sk_reuseport_attach_bpf(u32 ufd, struct sock *sk)return err; } +static void sk_reuseport_prog_free_rcu (struct rcu_head *rcu) +{ + struct bpf_prog_aux *aux = container_of(rcu, struct bpf_prog_aux, rcu); +struct bpf_prog *prog = aux->prog; + +bpf_release_orig_filter (prog); +bpf_prog_free (prog); +} +void sk_reuseport_prog_free (struct bpf_prog *prog) {if (!prog)return ; -if (prog->type ==BPF_PROG_TYPE_SK_REUSEPORT ) -bpf_prog_put (prog); +if (bpf_prog_was_classic (prog)) +call_rcu (&prog->aux->rcu, sk_reuseport_prog_free_rcu);else -bpf_prog_destroy (prog); +bpf_prog_put (prog); }struct bpf_scratchpad {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 124/342 HID: core: Add printk_ratelimited variants to hid_warn() etc
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vicki Pfau <[email protected]>
[ Upstream commit 1d64624243af8329b4b219d8c39e28ea448f9929 ]
hid_warn_ratelimited() is needed. Add the others as part of the block.
--- include/linux/hid.h | 11 +++++++++++ 1 file changed, 11 insertions(+)
include/linux/hid.h +11 -0
@@ -1217,4 +1217,15 @@ do { \#define hid_dbg_once (hid, fmt, ...) \ dev_dbg_once(&(hid)->dev, fmt, ##__VA_ARGS__) +#define hid_err_ratelimited (hid, fmt, ...) \ + dev_err_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) +#define hid_notice_ratelimited (hid, fmt, ...) \ + dev_notice_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) +#define hid_warn_ratelimited (hid, fmt, ...) \ + dev_warn_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) +#define hid_info_ratelimited (hid, fmt, ...) \ + dev_info_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) +#define hid_dbg_ratelimited (hid, fmt, ...) \ + dev_dbg_ratelimited(&(hid)->dev, fmt, ##__VA_ARGS__) +#endif
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 125/342 HID: pass the buffer size to hid_report_raw_event
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Tissoires <[email protected]>
[ Upstream commit 2c85c61d1332e1e16f020d76951baf167dcb6f7a ]
commit 0a3fe972a7cb ("HID: core: Mitigate potential OOB by removing bogus memset()") enforced the provided data to be at least the size of the declared buffer in the report descriptor to prevent a buffer overflow. However, we can try to be smarter by providing both the buffer size and the data size, meaning that hid_report_raw_event() can make better decision whether we should plaining reject the buffer (buffer overflow attempt) or if we can safely memset it to 0 and pass it to the rest of the stack.
Stable-dep-of: 206342541fc8 ("HID: core: introduce hid_safe_input_report()")
--- drivers/hid/hid-core.c | 29 ++++++++++++++++++++++------- drivers/hid/hid-gfrm.c | 4 ++-- drivers/hid/hid-logitech-hidpp.c | 2 +- drivers/hid/hid-multitouch.c | 2 +- drivers/hid/hid-primax.c | 2 +- drivers/hid/hid-vivaldi.c | 2 +- drivers/hid/wacom_sys.c | 6 +++--- drivers/staging/greybus/hid.c | 2 +- include/linux/hid.h | 4 ++-- 9 files changed, 34 insertions(+), 19 deletions(-)
drivers/hid/hid-core.c +22 -7
@@ -1775,8 +1775,8 @@ int __hid_request(struct hid_device *hid, struct hid_report *report, }EXPORT_SYMBOL_GPL (__hid_request); -int hid_report_raw_event (struct hid_device *hid,int type,u8 *data,u32 size, -int interrupt) +int hid_report_raw_event (struct hid_device *hid,int type,u8 *data, +size_t bufsize,u32 size,int interrupt) {struct hid_report_enum *report_enum = hid->report_enum + type;struct hid_report *report;
@@ -1784,16 +1784,24 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,int max_buffer_size =HID_MAX_BUFFER_SIZE ;unsigned int a;u32 rsize, csize = size; +size_t bsize = bufsize;u8 *cdata = data;int ret =0 ; report =hid_get_report (report_enum, data);if (!report) - goto out; +return 0 ; + +if (unlikely (bsize < csize)) { +hid_warn_ratelimited (hid,"Event data for report %d is incorrect (%d vs %ld)\n" , + report->id, csize, bsize); +return -EINVAL ; + }if (report_enum->numbered) { cdata++; csize--; + bsize--; } rsize =hid_compute_report_size (report);
@@ -1806,9 +1814,15 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,else if (rsize > max_buffer_size) rsize = max_buffer_size; +if (bsize < rsize) { +hid_warn_ratelimited (hid,"Event data for report %d was too short (%d vs %ld)\n" , + report->id, rsize, bsize); +return -EINVAL ; + } +if (csize < rsize) {dbg_hid ("report %d is too short, (%d < %d)\n" , report->id, - csize, rsize); + csize, rsize);memset (cdata + csize,0 , rsize - csize); }
@@ -1817,7 +1831,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,if (hid->claimed &HID_CLAIMED_HIDRAW ) { ret =hidraw_report_event (hid, data, size);if (ret) - goto out; +return ret; }if (hid->claimed !=HID_CLAIMED_HIDRAW && report->maxfield) {
@@ -1830,7 +1844,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,if (hid->claimed &HID_CLAIMED_INPUT )hidinput_report_event (hid, report); -out: +return ret; }EXPORT_SYMBOL_GPL (hid_report_raw_event);
@@ -1851,6 +1865,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, u32 size, int istruct hid_report_enum *report_enum;struct hid_driver *hdrv;struct hid_report *report; +size_t bufsize = size;int ret =0 ;if (!hid)
@@ -1889,7 +1904,7 @@ int hid_input_report(struct hid_device *hid, int type, u8 *data, u32 size, int i goto unlock; } - ret =hid_report_raw_event (hid, type, data, size, interrupt); + ret =hid_report_raw_event (hid, type, data, bufsize, size, interrupt); unlock:up (&hid->driver_input_lock);
drivers/hid/hid-gfrm.c +2 -2
@@ -66,7 +66,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,switch (data[1 ]) {case GFRM100_SEARCH_KEY_DOWN : ret =hid_report_raw_event (hdev,HID_INPUT_REPORT , search_key_dn, -sizeof (search_key_dn),1 ); +sizeof (search_key_dn),sizeof (search_key_dn),1 );break ;case GFRM100_SEARCH_KEY_AUDIO_DATA :
@@ -74,7 +74,7 @@ static int gfrm_raw_event(struct hid_device *hdev, struct hid_report *report,case GFRM100_SEARCH_KEY_UP : ret =hid_report_raw_event (hdev,HID_INPUT_REPORT , search_key_up, -sizeof (search_key_up),1 ); +sizeof (search_key_up),sizeof (search_key_up),1 );break ;default :
drivers/hid/hid-logitech-hidpp.c +1 -1
@@ -3176,7 +3176,7 @@ static int hidpp10_consumer_keys_raw_event(struct hidpp_device *hidpp,memcpy (&consumer_report[1 ], &data[3 ],4 );/* We are called from atomic context */ hid_report_raw_event (hidpp->hid_dev,HID_INPUT_REPORT , - consumer_report,5 ,1 ); + consumer_report,sizeof (consumer_report),5 ,1 );return 1 ; }
drivers/hid/hid-multitouch.c +1 -1
@@ -449,7 +449,7 @@ static void mt_get_feature(struct hid_device *hdev, struct hid_report *report) } ret =hid_report_raw_event (hdev,HID_FEATURE_REPORT , buf, - size,0 ); + size, size,0 );if (ret)dev_warn (&hdev->dev,"failed to report feature\n" ); }
drivers/hid/hid-primax.c +1 -1
@@ -44,7 +44,7 @@ static int px_raw_event(struct hid_device *hid, struct hid_report *report, data[0 ] |= (1 << (data[idx] -0xE0 )); data[idx] =0 ; } -hid_report_raw_event (hid,HID_INPUT_REPORT , data, size,0 ); +hid_report_raw_event (hid,HID_INPUT_REPORT , data, size, size,0 );return 1 ;default :/* unknown report */
drivers/hid/hid-vivaldi.c +1 -1
@@ -126,7 +126,7 @@ static void vivaldi_feature_mapping(struct hid_device *hdev, } ret =hid_report_raw_event (hdev,HID_FEATURE_REPORT , report_data, - report_len,0 ); + report_len, report_len,0 );if (ret) {dev_warn (&hdev->dev,"failed to report feature %d\n" , field->report->id);
drivers/hid/wacom_sys.c +3 -3
@@ -79,7 +79,7 @@ static void wacom_wac_queue_flush(struct hid_device *hdev,int err; size =kfifo_out (fifo, buf,sizeof (buf)); - err =hid_report_raw_event (hdev,HID_INPUT_REPORT , buf, size, false); + err =hid_report_raw_event (hdev,HID_INPUT_REPORT , buf, size, size, false);if (err) {hid_warn (hdev,"%s: unable to flush event due to error %d\n" , __func__, err);
@@ -324,7 +324,7 @@ static void wacom_feature_mapping(struct hid_device *hdev, data, n, WAC_CMD_RETRIES);if (ret == n && features->type ==HID_GENERIC ) { ret =hid_report_raw_event (hdev, -HID_FEATURE_REPORT , data, n,0 ); +HID_FEATURE_REPORT , data, n, n,0 ); }else if (ret ==2 && features->type !=HID_GENERIC ) { features->touch_max = data[1 ]; }else {
@@ -386,7 +386,7 @@ static void wacom_feature_mapping(struct hid_device *hdev, data, n, WAC_CMD_RETRIES);if (ret == n) { ret =hid_report_raw_event (hdev,HID_FEATURE_REPORT , - data, n,0 ); + data, n, n,0 ); }else {hid_warn (hdev,"%s: could not retrieve sensor offsets\n" , __func__);
drivers/staging/greybus/hid.c +1 -1
@@ -201,7 +201,7 @@ static void gb_hid_init_report(struct gb_hid *ghid, struct hid_report *report)* we just need to setup the input fields, so using * hid_report_raw_event is safe. */ -hid_report_raw_event (ghid->hid, report->type, ghid->inbuf, size,1 ); +hid_report_raw_event (ghid->hid, report->type, ghid->inbuf, ghid->bufsize, size,1 ); }static void gb_hid_init_reports (struct gb_hid *ghid)
include/linux/hid.h +2 -2
@@ -1175,8 +1175,8 @@ static inline u32 hid_report_len(struct hid_report *report)return DIV_ROUND_UP (report->size,8 ) + (report->id >0 ); } -int hid_report_raw_event (struct hid_device *hid,int type,u8 *data,u32 size, -int interrupt); +int hid_report_raw_event (struct hid_device *hid,int type,u8 *data, +size_t bufsize,u32 size,int interrupt);/* HID quirks API */ unsigned long hid_lookup_quirk (const struct hid_device *hdev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 126/342 HID: core: Fix size_t specifier in hid_report_raw_event()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Chancellor <[email protected]>
[ Upstream commit 4d3a2a466b8d68d852a1f3bbf11204b718428dc4 ]
When building for 32-bit platforms, for which 'size_t' is 'unsigned int', there are warnings around using the incorrect format specifier to print bsize in hid_report_raw_event():
drivers/hid/hid-core.c:2054:29: error: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Werror,-Wformat]
2053 | hid_warn_ratelimited(hid, "Event data for report %d is incorrect (%d vs %ld)\n",
| ~~~
| %zu
2054 | report->id, csize, bsize);
| ^~~~~
drivers/hid/hid-core.c:2076:29: error: format specifies type 'long' but the argument has type 'size_t' (aka 'unsigned int') [-Werror,-Wformat]
2075 | hid_warn_ratelimited(hid, "Event data for report %d was too short (%d vs %ld)\n",
| ~~~
| %zu
2076 | report->id, rsize, bsize);
| ^~~~~Use the proper 'size_t' format specifier, '%zu', to clear up the warnings.
--- drivers/hid/hid-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/hid/hid-core.c +2 -2
@@ -1793,7 +1793,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data,return 0 ;if (unlikely (bsize < csize)) { -hid_warn_ratelimited (hid,"Event data for report %d is incorrect (%d vs %ld)\n" , +hid_warn_ratelimited (hid,"Event data for report %d is incorrect (%d vs %zu)\n" , report->id, csize, bsize);return -EINVAL ; }
@@ -1815,7 +1815,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, rsize = max_buffer_size;if (bsize < rsize) { -hid_warn_ratelimited (hid,"Event data for report %d was too short (%d vs %ld)\n" , +hid_warn_ratelimited (hid,"Event data for report %d was too short (%d vs %zu)\n" , report->id, rsize, bsize);return -EINVAL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 127/342 USB: serial: mct_u232: fix memory corruption with small endpoint
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 915b36d701950503c4ea0f6e314b10868e59fce3 upstream.
The driver overrides the maximum transfer size for a specific device which only accepts 16 byte packets for its 32 byte bulk-out endpoint.
Make sure to never increase the maximum transfer size to prevent slab corruption should a malicious device report a smaller endpoint max packet size than expected.
--- drivers/usb/serial/mct_u232.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
drivers/usb/serial/mct_u232.c +11 -10
@@ -378,6 +378,7 @@ static int mct_u232_port_probe(struct usb_serial_port *port) {struct usb_serial *serial = port->serial;struct mct_u232_private *priv; +u16 pid;/* check first to simplify error handling */ if (!serial->port[1 ] || !serial->port[1 ]->interrupt_in_urb) {
@@ -385,6 +386,16 @@ static int mct_u232_port_probe(struct usb_serial_port *port)return -ENODEV ; } +/* +* Compensate for a hardware bug: although the Sitecom U232-P25 +* device reports a maximum output packet size of 32 bytes, +* it seems to be able to accept only 16 bytes (and that's what +* SniffUSB says too...) +*/ + pid =le16_to_cpu (serial->dev->descriptor.idProduct); +if (pid ==MCT_U232_SITECOM_PID ) + port->bulk_out_size =min (16 , port->bulk_out_size); + priv =kzalloc (sizeof (*priv),GFP_KERNEL );if (!priv)return -ENOMEM ;
@@ -412,7 +423,6 @@ static int mct_u232_port_remove(struct usb_serial_port *port)static int mct_u232_open (struct tty_struct *tty,struct usb_serial_port *port) { -struct usb_serial *serial = port->serial;struct mct_u232_private *priv =usb_get_serial_port_data (port);int retval =0 ;unsigned int control_state;
@@ -420,15 +430,6 @@ static int mct_u232_open(struct tty_struct *tty, struct usb_serial_port *port)unsigned char last_lcr;unsigned char last_msr; -/* Compensate for a hardware bug: although the Sitecom U232-P25 -* device reports a maximum output packet size of 32 bytes, -* it seems to be able to accept only 16 bytes (and that's what -* SniffUSB says too...) -*/ -if (le16_to_cpu (serial->dev->descriptor.idProduct) - ==MCT_U232_SITECOM_PID ) - port->bulk_out_size =16 ; -/* Do a defined restart: the normal serial device seems to * always turn on DTR and RTS here, so do the same. I'm not * sure if this is really necessary. But it should not harm
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 128/342 compiler-clang.h: Add __diag infrastructure for clang
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Chancellor <[email protected]>
commit f014a00bbeb09cea16017b82448d32a468a6b96f upstream.
Add __diag macros similar to those in compiler-gcc.h, so that warnings that need to be adjusted for specific cases but not globally can be ignored when building with clang.
[ Kartikeya: wrote commit message ]
--- include/linux/compiler-clang.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
include/linux/compiler-clang.h +22 -0
@@ -126,3 +126,25 @@#if __has_feature (shadow_call_stack)# define __noscs __attribute__((__no_sanitize__("shadow-call-stack")))#endif + +/* +* Turn individual warnings and errors on and off locally, depending +* on version. +*/ +#define __diag_clang (version, severity, s) \ + __diag_clang_ ## version(__diag_clang_ ## severity s) + +/* Severity used in pragma directives */ +#define __diag_clang_ignore ignored +#define __diag_clang_warn warning +#define __diag_clang_error error + +#define __diag_str1 (s) #s +#define __diag_str (s) __diag_str1(s) +#define __diag (s) _Pragma(__diag_str(clang diagnostic s)) + +#if CONFIG_CLANG_VERSION >=110000 +#define __diag_clang_11 (s) __diag(s) +#else +#define __diag_clang_11 (s) +#endif
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 129/342 Disable -Wattribute-alias for clang-23 and newer
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Chancellor <[email protected]>
commit 175db11786bde9061db526bf1ac5107d915f5163 upstream.
Clang recently added support for -Wattribute-alias [1], which results in the same warnings that necessitated commit bee20031772a ("disable -Wattribute-alias warning for SYSCALL_DEFINEx()") for GCC.
kernel/time/itimer.c:325:1: error: alias and aliasee have different types 'long (unsigned int)' and 'long (typeof (__builtin_choose_expr((__builtin_types_compatible_p(typeof ((unsigned int)0), typeof (0LL)) || __builtin_types_compatible_p(typeof ((unsigned int)0), typeof (0ULL))), 0LL, 0L)))' (aka 'long (long)') [-Werror,-Wattribute-alias]
325 | SYSCALL_DEFINE1(alarm, unsigned int, seconds)
| ^
include/linux/syscalls.h:225:36: note: expanded from macro 'SYSCALL_DEFINE1'
225 | #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
| ^
include/linux/syscalls.h:236:2: note: expanded from macro 'SYSCALL_DEFINEx'
236 | __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
| ^
include/linux/syscalls.h:251:18: note: expanded from macro '__SYSCALL_DEFINEx'
251 | __attribute__((alias(__stringify(__se_sys##name)))); \
| ^
kernel/time/itimer.c:325:1: note: aliasee is declared here
include/linux/syscalls.h:225:36: note: expanded from macro 'SYSCALL_DEFINE1'
225 | #define SYSCALL_DEFINE1(name, ...) SYSCALL_DEFINEx(1, _##name, __VA_ARGS__)
| ^
include/linux/syscalls.h:236:2: note: expanded from macro 'SYSCALL_DEFINEx'
236 | __SYSCALL_DEFINEx(x, sname, __VA_ARGS__)
| ^
include/linux/syscalls.h:255:18: note: expanded from macro '__SYSCALL_DEFINEx'
255 | asmlinkage long __se_sys##name(__MAP(x,__SC_LONG,__VA_ARGS__)) \
| ^
<scratch space>:16:1: note: expanded from here
16 | __se_sys_alarm
| ^Disable the warnings in the same way for clang-23 and newer. Disable the warning about unknown warning options to avoid breaking the build for versions of clang-23 that do not have -Wattribute-alias, such as ones deployed by vendors like Android or CI systems or when bisecting LLVM between llvmorg-23-init and release/23.x.
--- include/linux/compat.h | 4 ++++ include/linux/compiler-clang.h | 6 ++++++ include/linux/compiler_types.h | 4 ++++ include/linux/syscalls.h | 4 ++++ 4 files changed, 18 insertions(+)
include/linux/compat.h +4 -0
@@ -75,6 +75,10 @@__diag_push (); \__diag_ignore (GCC ,8 ,"-Wattribute-alias" , \"Type aliasing is used to sanitize syscall arguments" );\ +__diag_ignore (clang,23 ,"-Wunknown-warning-option" , \ +"Avoid breaking versions without -Wattribute-alias" ); \ +__diag_ignore (clang,23 ,"-Wattribute-alias" , \ +"Type aliasing is used to sanitize syscall arguments" ); \ asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)); \ asmlinkage long compat_sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ __attribute__((alias(__stringify(__se_compat_sys##name)))); \
include/linux/compiler-clang.h +6 -0
@@ -148,3 +148,9 @@#else #define __diag_clang_11 (s)#endif + +#if CONFIG_CLANG_VERSION >=230000 +#define __diag_clang_23 (s) __diag(s) +#else +#define __diag_clang_23 (s) +#endif
include/linux/compiler_types.h +4 -0
@@ -320,6 +320,10 @@ struct ftrace_likely_data {#define __diag_GCC (version, severity, string)#endif +#ifndef __diag_clang +#define __diag_clang (version, severity, string) +#endif +#define __diag_push () __diag(push)#define __diag_pop () __diag(pop)
include/linux/syscalls.h +4 -0
@@ -236,6 +236,10 @@ static inline int is_syscall_trace_event(struct trace_event_call *tp_event)__diag_push (); \__diag_ignore (GCC ,8 ,"-Wattribute-alias" , \"Type aliasing is used to sanitize syscall arguments" );\ +__diag_ignore (clang,23 ,"-Wunknown-warning-option" , \ +"Avoid breaking versions without -Wattribute-alias" );\ +__diag_ignore (clang,23 ,"-Wattribute-alias" , \ +"Type aliasing is used to sanitize syscall arguments" );\ asmlinkage long sys##name(__MAP(x,__SC_DECL,__VA_ARGS__)) \ __attribute__((alias(__stringify(__se_sys##name)))); \ ALLOW_ERROR_INJECTION(sys##name, ERRNO); \
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 130/342 i2c: dev: prevent integer overflow in I2C_TIMEOUT ioctl
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mingyu Wang <[email protected]>
commit 617eb7c0961a8dfcfc811844a6396e406b2923ea upstream.
While fuzzing with Syzkaller, a persistent schedule_timeout: wrong timeout value warning was observed, accompanied by SMBus controller state machine corruption.
The I2C_TIMEOUT ioctl accepts a user-provided timeout in multiples of 10 ms. The user argument is checked against INT_MAX, but it is subsequently multiplied by 10 before being passed to msecs_to_jiffies().
A malicious user can pass a large value (e.g., 429496729) that passes the arg > INT_MAX check but overflows when multiplied by 10. This results in a truncated 32-bit unsigned value that bypasses the internal (int)m < 0 check in msecs_to_jiffies().
The truncated value is then assigned to client->adapter->timeout (a signed 32-bit int), which is reinterpreted as a negative number. When passed to wait_for_completion_timeout(), this negative value undergoes sign extension to a 64-bit unsigned long, triggering the schedule_timeout warning and causing premature returns. This leaves the SMBus state machine in an unrecoverable state, constituting a local Denial of Service (DoS).
Fix this by bounding the user argument to INT_MAX / 10.
--- drivers/i2c/i2c-dev.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/i2c/i2c-dev.c +5 -4
@@ -477,12 +477,13 @@ static long i2cdev_ioctl(struct file *fi client->adapter->retries = arg;break ;case I2C_TIMEOUT : -if (arg >INT_MAX ) +/* +* For historical reasons, user-space sets the timeout value in +* units of 10 ms. +*/ +if (arg >INT_MAX /10 )return -EINVAL ; -/* For historical reasons, user-space sets the timeout -* value in units of 10 ms. -*/ client->adapter->timeout =msecs_to_jiffies (arg *10 );break ;default :
Greg Kroah-Hartman
maintainerPATCH 131/342 tee: optee: prevent use-after-free when the client exits before the supplicant
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amirreza Zarrabi <[email protected]>
[ Upstream commit 387a926ee166814611acecb960207fe2f3c4fd3e ]
Commit 70b0d6b0a199 ("tee: optee: Fix supplicant wait loop") made the client wait as killable so it can be interrupted during shutdown or after a supplicant crash. This changes the original lifetime expectations:
the client task can now terminate while the supplicant is still processing its request.
If the client exits first it removes the request from its queue and kfree()s it, while the request ID remains in supp->idr. A subsequent lookup on the supplicant path then dereferences freed memory, leading to a use-after-free.
Serialise access to the request with supp->mutex:
* Hold supp->mutex in optee_supp_recv() and optee_supp_send() while looking up and touching the request.
* Let optee_supp_thrd_req() notice that the client has terminated and signal optee_supp_send() accordingly.
With these changes the request cannot be freed while the supplicant still has a reference, eliminating the race.
--- drivers/tee/optee/supp.c | 107 +++++++++++++++++++++++++++------------ 1 file changed, 74 insertions(+), 33 deletions(-)
drivers/tee/optee/supp.c +74 -33
@@ -10,7 +10,11 @@struct optee_supp_req {struct list_head link; +int id; +bool in_queue; +bool processed; +u32 func;u32 ret;size_t num_params;
@@ -19,6 +23,9 @@ struct optee_supp_req {struct completion c; }; +/* It is temporary request used for revoked pending request in supp->idr. */ +#define INVALID_REQ_PTR ((struct optee_supp_req *)ERR_PTR(-EBADF)) +void optee_supp_init (struct optee_supp *supp) {memset (supp,0 ,sizeof (*supp));
@@ -39,21 +46,23 @@ void optee_supp_release(struct optee_supp *supp) {int id;struct optee_supp_req *req; -struct optee_supp_req *req_tmp;mutex_lock (&supp->mutex); -/* Abort all request retrieved by supplicant */ +/* Abort all request */ idr_for_each_entry (&supp->idr, req, id) {idr_remove (&supp->idr, id); - req->ret =TEEC_ERROR_COMMUNICATION ; -complete (&req->c); - } +/* Skip if request was already marked invalid */ +if (IS_ERR (req)) +continue ; -/* Abort all queued requests */ -list_for_each_entry_safe (req, req_tmp, &supp->reqs, link) { -list_del (&req->link); - req->in_queue = false; +/* For queued requests where supplicant has not seen it */ +if (req->in_queue) { +list_del (&req->link); + req->in_queue = false; + } + + req->processed = true; req->ret =TEEC_ERROR_COMMUNICATION ;complete (&req->c); }
@@ -100,8 +109,16 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,/* Insert the request in the request list */ mutex_lock (&supp->mutex); + req->id =idr_alloc (&supp->idr, req,1 ,0 ,GFP_KERNEL ); +if (req->id <0 ) { +mutex_unlock (&supp->mutex); +kfree (req); +return TEEC_ERROR_OUT_OF_MEMORY ; + } +list_add_tail (&req->link, &supp->reqs); req->in_queue = true; + req->processed = false;mutex_unlock (&supp->mutex);/* Tell an eventual waiter there's a new request */
@@ -117,21 +134,43 @@ u32 optee_supp_thrd_req(struct tee_context *ctx, u32 func, size_t num_params,if (wait_for_completion_killable (&req->c)) {mutex_lock (&supp->mutex);if (req->in_queue) { +/* Supplicant has not seen this request yet. */ +idr_remove (&supp->idr, req->id);list_del (&req->link); req->in_queue = false; + + ret =TEEC_ERROR_COMMUNICATION ; + }else if (req->processed) { +/* +* Supplicant has processed this request. Ignore the +* kill signal for now and submit the result. req is not +* in supp->reqs (removed by supp_pop_entry()) nor in +* supp->idr (removed by supp_pop_req()). +*/ + ret = req->ret; + }else { +/* +* Supplicant is in the middle of processing this +* request. Replace req with INVALID_REQ_PTR so that +* the ID remains busy, causing optee_supp_send() to +* fail on the next call to supp_pop_req() with this ID. +*/ +idr_replace (&supp->idr,INVALID_REQ_PTR , req->id); + ret =TEEC_ERROR_COMMUNICATION ; } +mutex_unlock (&supp->mutex); - req->ret =TEEC_ERROR_COMMUNICATION ; + }else { + ret = req->ret; } - ret = req->ret;kfree (req);return ret; }static struct optee_supp_req *supp_pop_entry (struct optee_supp *supp, -int num_params,int *id) +int num_params) {struct optee_supp_req *req;
@@ -153,10 +192,6 @@ static struct optee_supp_req *supp_pop_entry(struct optee_supp *supp,return ERR_PTR (-EINVAL ); } - *id =idr_alloc (&supp->idr, req,1 ,0 ,GFP_KERNEL ); -if (*id <0 ) -return ERR_PTR (-ENOMEM ); -list_del (&req->link); req->in_queue = false;
@@ -214,7 +249,6 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,struct optee *optee =tee_get_drvdata (teedev);struct optee_supp *supp = &optee->supp;struct optee_supp_req *req =NULL ; -int id;size_t num_meta;int rc;
@@ -224,15 +258,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,while (true) {mutex_lock (&supp->mutex); - req =supp_pop_entry (supp, *num_params - num_meta, &id); + req =supp_pop_entry (supp, *num_params - num_meta); +if (req) +break ;/* Keep mutex held. */ mutex_unlock (&supp->mutex); -if (req) { -if (IS_ERR (req)) -return PTR_ERR (req); -break ; - } -/* * If we didn't get a request we'll block in * wait_for_completion() to avoid needless spinning.
@@ -245,6 +275,13 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,return -ERESTARTSYS ; } +/* supp->mutex held and req != NULL. */ + +if (IS_ERR (req)) { +mutex_unlock (&supp->mutex); +return PTR_ERR (req); + } +if (num_meta) {/* * tee-supplicant support meta parameters -> requsts can be
@@ -252,13 +289,11 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,*/ param->attr =TEE_IOCTL_PARAM_ATTR_TYPE_VALUE_INOUT |TEE_IOCTL_PARAM_ATTR_META ; - param->u.value.a = id; + param->u.value.a = req->id; param->u.value.b =0 ; param->u.value.c =0 ; }else { -mutex_lock (&supp->mutex); - supp->req_id = id; -mutex_unlock (&supp->mutex); + supp->req_id = req->id; } *func = req->func;
@@ -266,6 +301,7 @@ int optee_supp_recv(struct tee_context *ctx, u32 *func, u32 *num_params,memcpy (param + num_meta, req->param,sizeof (struct tee_param ) * req->num_params); +mutex_unlock (&supp->mutex);return 0 ; }
@@ -297,12 +333,17 @@ static struct optee_supp_req *supp_pop_req(struct optee_supp *supp,if (!req)return ERR_PTR (-ENOENT ); +/* optee_supp_thrd_req() already returned to optee. */ +if (IS_ERR (req)) + goto failed_req; +if ((num_params - nm) != req->num_params)return ERR_PTR (-EINVAL ); + *num_meta = nm; +failed_req:idr_remove (&supp->idr, id); supp->req_id =-1 ; - *num_meta = nm;return req; }
@@ -328,10 +369,9 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params,mutex_lock (&supp->mutex); req =supp_pop_req (supp, num_params, param, &num_meta); -mutex_unlock (&supp->mutex); -if (IS_ERR (req)) { -/* Something is wrong, let supplicant restart. */ +mutex_unlock (&supp->mutex); +/* Something is wrong, let supplicant handel it. */ return PTR_ERR (req); }
@@ -355,9 +395,10 @@ int optee_supp_send(struct tee_context *ctx, u32 ret, u32 num_params, } } req->ret = ret; - + req->processed = true;/* Let the requesting thread continue */ complete (&req->c); +mutex_unlock (&supp->mutex);return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 132/342 netfilter: xt_NFQUEUE: prefer raw_smp_processor_id
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fernando Fernandez Mancera <[email protected]>
[ Upstream commit c6c5327dd18bec1e1bbf139b2cf5ae53608a9d30 ]
With PREEMPT_RCU this triggers a splat because smp_processor_id() can be preempted while inside a RCU critical section. If xt_NFQUEUE target is invoked via nft_compat_eval() path, we are inside a RCU critical section.
Just use the raw version instead.
--- net/netfilter/xt_NFQUEUE.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/xt_NFQUEUE.c +1 -1
@@ -91,7 +91,7 @@ nfqueue_tg_v3(struct sk_buff *skb, const struct xt_action_param *par)if (info->queues_total >1 ) {if (info->flags &NFQ_FLAG_CPU_FANOUT ) { -int cpu =smp_processor_id (); +int cpu =raw_smp_processor_id (); queue = info->queuenum + cpu % info->queues_total; }else {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 133/342 ipvs: clear the svc scheduler ptr early on edit
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Anastasov <[email protected]>
[ Upstream commit 193989cc6d80dd8e0460fb3992e69fa03bf0ff9b ]
ip_vs_edit_service() while unbinding the old scheduler clears the svc->scheduler ptr after the scheduler module initiates RCU callbacks. This can cause packets to use the old scheduler at the time when svc->sched_data is already freed after RCU grace period.
Fix it by clearing the ptr early in ip_vs_unbind_scheduler(), before the done_service method schedules any RCU callbacks.
Also, if the new scheduler fails to initialize when replacing the old scheduler, try to restore the old scheduler while still returning the error code.
--- include/net/ip_vs.h | 3 +-- net/netfilter/ipvs/ip_vs_ctl.c | 13 ++++++++----- net/netfilter/ipvs/ip_vs_sched.c | 14 +++++++------- 3 files changed, 16 insertions(+), 14 deletions(-)
include/net/ip_vs.h +1 -2
@@ -1396,8 +1396,7 @@ int register_ip_vs_scheduler(struct ip_vs_scheduler *scheduler);int unregister_ip_vs_scheduler (struct ip_vs_scheduler *scheduler);int ip_vs_bind_scheduler (struct ip_vs_service *svc,struct ip_vs_scheduler *scheduler); -void ip_vs_unbind_scheduler (struct ip_vs_service *svc, -struct ip_vs_scheduler *sched); +void ip_vs_unbind_scheduler (struct ip_vs_service *svc);struct ip_vs_scheduler *ip_vs_scheduler_get (const char *sched_name);void ip_vs_scheduler_put (struct ip_vs_scheduler *scheduler); struct ip_vs_conn *
net/netfilter/ipvs/ip_vs_ctl.c +8 -5
@@ -1417,7 +1417,7 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,if (ret_hooks >=0 )ip_vs_unregister_hooks (ipvs, u->af);if (svc !=NULL ) { -ip_vs_unbind_scheduler (svc, sched); +ip_vs_unbind_scheduler (svc);ip_vs_service_free (svc); }ip_vs_scheduler_put (sched);
@@ -1479,9 +1479,8 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u) old_sched =rcu_dereference_protected (svc->scheduler,1 );if (sched != old_sched) {if (old_sched) { -ip_vs_unbind_scheduler (svc, old_sched); -RCU_INIT_POINTER (svc->scheduler,NULL ); -/* Wait all svc->sched_data users */ +ip_vs_unbind_scheduler (svc); +/* Wait all svc->scheduler/sched_data users */ synchronize_rcu (); }/* Bind the new scheduler */
@@ -1489,6 +1488,10 @@ ip_vs_edit_service(struct ip_vs_service *svc, struct ip_vs_service_user_kern *u) ret =ip_vs_bind_scheduler (svc, sched);if (ret) {ip_vs_scheduler_put (sched); +/* Try to restore the old_sched */ +if (old_sched && + !ip_vs_bind_scheduler (svc, old_sched)) + old_sched =NULL ; goto out; } }
@@ -1545,7 +1548,7 @@ static void __ip_vs_del_service(struct ip_vs_service *svc, bool cleanup)/* Unbind scheduler */ old_sched =rcu_dereference_protected (svc->scheduler,1 ); -ip_vs_unbind_scheduler (svc, old_sched); +ip_vs_unbind_scheduler (svc);ip_vs_scheduler_put (old_sched);/* Unbind persistence engine, keep svc->pe */
net/netfilter/ipvs/ip_vs_sched.c +7 -7
@@ -57,19 +57,19 @@ int ip_vs_bind_scheduler(struct ip_vs_service *svc,/* * Unbind a service with its scheduler */ -void ip_vs_unbind_scheduler (struct ip_vs_service *svc, -struct ip_vs_scheduler *sched) +void ip_vs_unbind_scheduler (struct ip_vs_service *svc) { -struct ip_vs_scheduler *cur_sched; +struct ip_vs_scheduler *sched; - cur_sched =rcu_dereference_protected (svc->scheduler,1 ); -/* This check proves that old 'sched' was installed */ -if (!cur_sched) + sched =rcu_dereference_protected (svc->scheduler,1 ); +if (!sched)return ; +/* Reset the scheduler before initiating any RCU callbacks */ +rcu_assign_pointer (svc->scheduler,NULL ); +smp_wmb ();/* paired with smp_rmb() in ip_vs_schedule() */ if (sched->done_service) sched->done_service (svc); -/* svc->scheduler can be set to NULL only by caller */ }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 134/342 netfilter: synproxy: add mutex to guard hook reference counting
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fernando Fernandez Mancera <[email protected]>
[ Upstream commit 2fcba19caaeb2a33017459d3430f057967bb91b6 ]
As the synproxy infrastructure register netfilter hooks on-demand when a user adds the first iptables target or nftables expression, if done concurrently they can race each other.
Introduce a mutex to serialize the refcount control blocks access from both frontends. While a per namespace mutex might be more efficient, it is not needed for target/expression like SYNPROXY.
--- net/netfilter/nf_synproxy_core.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-)
net/netfilter/nf_synproxy_core.c +18 -6
@@ -21,6 +21,8 @@#include <net/netfilter/nf_conntrack_zones.h> #include <net/netfilter/nf_synproxy.h> +static DEFINE_MUTEX (synproxy_mutex); +unsigned int synproxy_net_id;EXPORT_SYMBOL_GPL (synproxy_net_id);
@@ -790,26 +792,31 @@ static const struct nf_hook_ops ipv4_synproxy_ops[] = {int nf_synproxy_ipv4_init (struct synproxy_net *snet,struct net *net) { -int err; +int err =0 ; +mutex_lock (&synproxy_mutex);if (snet->hook_ref4 ==0 ) { err =nf_register_net_hooks (net, ipv4_synproxy_ops,ARRAY_SIZE (ipv4_synproxy_ops));if (err) -return err; + goto out; } snet->hook_ref4++; -return 0 ; +out: +mutex_unlock (&synproxy_mutex); +return err; }EXPORT_SYMBOL_GPL (nf_synproxy_ipv4_init);void nf_synproxy_ipv4_fini (struct synproxy_net *snet,struct net *net) { +mutex_lock (&synproxy_mutex); snet->hook_ref4--;if (snet->hook_ref4 ==0 )nf_unregister_net_hooks (net, ipv4_synproxy_ops,ARRAY_SIZE (ipv4_synproxy_ops)); +mutex_unlock (&synproxy_mutex); }EXPORT_SYMBOL_GPL (nf_synproxy_ipv4_fini);
@@ -1214,27 +1221,32 @@ static const struct nf_hook_ops ipv6_synproxy_ops[] = {int nf_synproxy_ipv6_init (struct synproxy_net *snet,struct net *net) { -int err; +int err =0 ; +mutex_lock (&synproxy_mutex);if (snet->hook_ref6 ==0 ) { err =nf_register_net_hooks (net, ipv6_synproxy_ops,ARRAY_SIZE (ipv6_synproxy_ops));if (err) -return err; + goto out; } snet->hook_ref6++; -return 0 ; +out: +mutex_unlock (&synproxy_mutex); +return err; }EXPORT_SYMBOL_GPL (nf_synproxy_ipv6_init);void nf_synproxy_ipv6_fini (struct synproxy_net *snet,struct net *net) { +mutex_lock (&synproxy_mutex); snet->hook_ref6--;if (snet->hook_ref6 ==0 )nf_unregister_net_hooks (net, ipv6_synproxy_ops,ARRAY_SIZE (ipv6_synproxy_ops)); +mutex_unlock (&synproxy_mutex); }EXPORT_SYMBOL_GPL (nf_synproxy_ipv6_fini);#endif /* CONFIG_IPV6 */
Signature · 1 line
2.53.0