Skip to contentSkip to conversation

6.6.143-rc1 review

PATCH In review Greg Kroah-Hartman 16 participants 482 messages Jun 16 – Sep 17 Page 1 of 4

Subsystems (4)
lore
Share & tools
lore

Greg Kroah-Hartman

author maintainer
#0 lore raw

cover 6.6.143-rc1 review

This is the start of the stable review cycle for the 6.6.143 release. There are 452 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/v6.x/stable-review/patch-6.6.143-rc1.gz

or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.6.y
and the diffstat can be found below.

thanks,

greg k-h

-------------
Pseudo-Shortlog of commits:

Greg Kroah-Hartman <[email protected]>

    Linux 6.6.143-rc1

Borislav Petkov (AMD) <[email protected]>
x86/CPU/AMD: Rename init_amd_zn() to init_amd_zen_common()

Borislav Petkov (AMD) <[email protected]>
x86/CPU/AMD: Call the spectral chicken in the Zen2 init function

Borislav Petkov (AMD) <[email protected]>
x86/CPU/AMD: Move the Zen3 BTC_NO detection to the Zen3 init function

Petr Machata <[email protected]>
Revert "selftest/ptp: update ptp selftest to exercise the gettimex options"

Paolo Abeni <[email protected]>
mptcp: fix missing wakeups in edge scenarios

Matthieu Baerts (NGI0) <[email protected]>
mptcp: add-addr: always drop other suboptions

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

Aaron Erhardt <[email protected]>
ALSA: hda/hdmi: Add quirk for TUXEDO IBS14G6

Julian Anastasov <[email protected]>
ipvs: skip ipv6 extension headers for csum checks

Xiang Mei <[email protected]>
net: bonding: fix use-after-free in bond_xmit_broadcast()

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

Jason Gunthorpe <[email protected]>
RDMA: During rereg_mr ensure that REREG_ACCESS is compatible

Anton Leontev <[email protected]>
hv_netvsc: use kmap_local_page in netvsc_copy_to_send_buf

Wupeng Ma <[email protected]>
mm/memory-failure: fix hugetlb_lock AA deadlock in get_huge_page_for_hwpoison

Jane Chu <[email protected]>

    mm/memory-failure: fix missing ->mf_stats count in hugetlb poison

David Hildenbrand <[email protected]>
mm/hugetlb: rename folio_putback_active_hugetlb() to folio_putback_hugetlb()

David Hildenbrand <[email protected]>
mm/migrate: don't call folio_putback_active_hugetlb() on dst hugetlb folio

David Hildenbrand <[email protected]>
mm/hugetlb: rename isolate_hugetlb() to folio_isolate_hugetlb()

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

Viken Dadhaniya <[email protected]>
serial: qcom_geni: fix kfifo underflow when flush precedes DMA completion IRQ

Michael Bommarito <[email protected]>
scsi: target: iscsi: Fix CRC overread and double-free in iscsit_handle_text_cmd()

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

Kai Aizen <[email protected]>

    usb: gadget: uvc: hold opts->lock across XU walks in uvc_function_bind

Radhey Shyam Pandey <[email protected]>
usb: dwc3: xilinx: fix error handling in zynqmp init error paths

Wentao Liang <[email protected]>

    usb: musb: omap2430: Fix use-after-free in omap2430_probe()

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

Cássio Gabriel <[email protected]>
ALSA: firewire-motu: Protect register DSP event queue positions

Pratyush Yadav (Google) <[email protected]>
memfd: deny writeable mappings when implying SEAL_WRITE

Rodrigo Alencar <[email protected]>
iio: dac: ad5686: fix ref bit initialization for single-channel parts

Peter Chen <[email protected]>
usb: cdns3: plat: fix leaked usb2_phy initialization on usb3_phy acquisition failure

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

Antoniu Miclaus <[email protected]>
iio: gyro: adis16260: fix division by zero in write_raw

Paolo Abeni <[email protected]>
mptcp: handle first subflow closing consistently

Shuai Zhang <[email protected]>
Bluetooth: hci_qca: Convert timeout from jiffies to ms

Uwe Kleine-König <[email protected]>
Bluetooth: hci_qca: Migrate to serdev specific shutdown function

Uwe Kleine-König <[email protected]>
serdev: Provide a bustype shutdown function

Ricardo B. Marliere <[email protected]>
serdev: make serdev_bus_type const

SeongJae Park <[email protected]>
mm/damon/sysfs-schemes: delete tried region in regions_rmdirs()

Alistair Popple <[email protected]>
mm/memory: fix spurious warning when unmapping device-private/exclusive pages

Shardul Bankar <[email protected]>
mptcp: do not drop partial packets

Paolo Abeni <[email protected]>
mptcp: introduce the mptcp_init_skb helper

David Carlier <[email protected]>
iio: adc: npcm: fix unbalanced clk_disable_unprepare()

Uwe Kleine-König <[email protected]>
iio: adc: npcm: Convert to platform remove callback returning void

Zeng Heng <[email protected]>
arm64: tlb: Flush walk cache when unsharing PMD tables

Dawei Feng <[email protected]>

    octeontx2-pf: avoid double free of pool->stack on AQ init failure

Jann Horn <[email protected]>

    af_unix: Fix UAF read of tail->len in unix_stream_data_wait()

Kuniyuki Iwashima <[email protected]>

    af_unix: Cache state->msg in unix_stream_read_generic().

David Howells <[email protected]>
rxrpc: Fix RESPONSE packet verification to extract skb to a linear buffer

David Howells <[email protected]>
rxrpc: Fix DATA decrypt vs splice() by copying data to buffer in recvmsg

Michael Bommarito <[email protected]>
net: hsr: defer node table free until after RCU readers

Justin Iurman <[email protected]>
ipv6: ioam: add NULL check for idev in ipv6_hop_ioam()

Eric Dumazet <[email protected]>
ipv6/addrconf: annotate data-races around devconf fields (II)

Li Xiasong <[email protected]>
mptcp: pm: fix ADD_ADDR timer infinite retry on option space insufficient

Jose Ignacio Tornos Martinez <[email protected]>
ice: fix VF queue configuration with low MTU values

Matthieu Baerts (NGI0) <[email protected]>
selftests: mptcp: drop nanoseconds width specifier

Paolo Abeni <[email protected]>
mptcp: reset rcv wnd on disconnect

Paolo Abeni <[email protected]>
mptcp: cleanup fallback dummy mapping generation

Paolo Abeni <[email protected]>
mptcp: use plain bool instead of custom binary enum

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

Lukas Wunner <[email protected]>
platform/x86/intel/vsec: Fix enable_cnt imbalance on PCIe error recovery

Michael Bommarito <[email protected]>
smb: client: require net admin for CIFS SWN netlink

Ido Schimmel <[email protected]>
genetlink: Use internal flags for multicast groups

Guopeng Zhang <[email protected]>
cgroup/cpuset: Reset DL migration state on can_attach() failure

Asim Viladi Oglu Manizada <[email protected]>
ksmbd: fix OOB write in QUERY_INFO for compound requests

Thomas Zimmermann <[email protected]>
fbdev/vt8500lcdfb: Initialize fb_ops with fbdev macros

Corey Minyard <[email protected]>
ipmi:ssif: NULL thread on error

Corey Minyard <[email protected]>
ipmi:ssif: Remove unnecessary indention

Yin Tirui <[email protected]>
mm/huge_memory: update file PMD counter before folio_put()

Manivannan Sadhasivam <[email protected]>
soc: qcom: ice: Fix race between qcom_ice_probe() and of_qcom_ice_get()

Lorenzo Stoakes <[email protected]>
mm/hugetlb: avoid false positive lockdep assertion

Johan Hovold <[email protected]>
driver core: reject devices with unregistered buses

Mingyu Wang <[email protected]>
fs/fcntl: fix SOFTIRQ-unsafe lock order in fasync signaling

Harry Wentland <[email protected]>
drm/amd/display: Use krealloc_array() in dal_vector_reserve()

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 VBIOS HDMI retimer register count to array size

Harry Wentland <[email protected]>
drm/amd/display: Clamp HDMI HDCP2 rx_id_list read to buffer size

Christian König <[email protected]>
drm/amdgpu: restart the CS if some parts of the VM are still invalidated

Andrew Martin <[email protected]>
drm/amdkfd: Fix buffer overflow in SDMA queue checkpoint/restore on GFX11

Muhammad Bilal <[email protected]>
drm/amdkfd: fix NULL dereference in get_queue_ids()

Bjorn Andersson <[email protected]>

    slimbus: qcom-ngd-ctrl: Avoid ABBA on tx_lock/ctrl->lock

Bartosz Golaszewski <[email protected]>
slimbus: qcom-ngd-ctrl: fix OF node refcount

Michael Bommarito <[email protected]>
thunderbolt: Limit XDomain response copy to actual frame size

Michael Bommarito <[email protected]>
thunderbolt: Validate XDomain request packet size before type cast

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

Lad Prabhakar <[email protected]>
mmc: renesas_sdhi: Add OF entry for RZ/G2H SoC

Inochi Amaoto <[email protected]>
mmc: litex_mmc: Set mandatory idle clocks before CMD0

Kamal Dasu <[email protected]>
mmc: core: Fix host controller programming for fixed driver type

David Carlier <[email protected]>
mm/hugetlb: restore reservation on error in hugetlb folio copy paths

Eduard Zingerman <[email protected]>

    selftests/bpf: Update comments find_equal_scalars->sync_linked_regs

Eduard Zingerman <[email protected]>
selftests/bpf: Tests for per-insn sync_linked_regs() precision tracking

Eduard Zingerman <[email protected]>
bpf: Remove mark_precise_scalar_ids()

Eduard Zingerman <[email protected]>
bpf: Track equal scalars history on per-instruction level

Dawei Feng <[email protected]>
octeontx2-af: fix memory leak in rvu_setup_hw_resources()

Andre Heider <[email protected]>
nvmem: layouts: onie-tlv: fix hang on unknown types

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()

Nikolay Kuratov <[email protected]>
net/mlx5: Reorder completion before putting command entry in cmd_work_handler

Mukesh Ojha <[email protected]>
misc: fastrpc: Fix NULL pointer dereference in rpmsg callback

Junrui Luo <[email protected]>
misc: fastrpc: fix DMA address corruption due to find_vma misuse

Zhenghang Xiao <[email protected]>
misc: fastrpc: fix use-after-free race in fastrpc_map_create

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

Guillermo Rodríguez <[email protected]>
i2c: stm32f7: fix timing computation ignoring i2c-analog-filter

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

Hyunwoo Kim <[email protected]>
inet: frags: fix use-after-free caused by the fqdir_pre_exit() flush

Michael Bommarito <[email protected]>
IB/isert: Reject login PDUs shorter than ISER_HEADERS_LEN

Kyle Meyer <[email protected]>
bnxt_en: Fix NULL pointer dereference

Chancel Liu <[email protected]>
ASoC: fsl_sai: Fix 32 slots TDM broken by integer shift UB in xMR write

Raf Dickson <[email protected]>
vsock/vmci: fix sk_ack_backlog leak on failed handshake

Yuqi Xu <[email protected]>
wifi: nl80211: reject oversized EMA RNR lists

Tao Cui <[email protected]>
selftests: mptcp: add test for extra_subflows underflow on userspace PM

Matthieu Baerts (NGI0) <[email protected]>
mptcp: sockopt: check timestamping ret value

Paolo Abeni <[email protected]>
mptcp: allow subflow rcv wnd to shrink

Paolo Abeni <[email protected]>
mptcp: close TOCTOU race while computing rcv_wnd

Paolo Abeni <[email protected]>
mptcp: fix retransmission loop when csum is enabled

Karl Mehltretter <[email protected]>
ARM: 9475/1: entry: use byte load for KASAN VMAP stack shadow

Karl Mehltretter <[email protected]>
ARM: 9474/1: io: avoid KASAN instrumentation of raw halfword I/O

Yuho Choi <[email protected]>
ARM: socfpga: Fix OF node refcount leak in SMP setup

Sechang Lim <[email protected]>

    udp: clear skb->dev before running a sockmap verdict

Cunlong Li <[email protected]>
zram: fix use-after-free in zram_bvec_write_partial()

Michael Bommarito <[email protected]>
RDMA/srp: bound SRP_RSP sense copy by the received length

SeongJae Park <[email protected]>
mm/damon/ops-common: call folio_test_lru() after folio_get()

Harry Wentland <[email protected]>
drm/amd/display: Reject gpio_bitshift >= 32 in bios_parser_get_gpio_pin_info()

Wentao Liang <[email protected]>
drm/virtio: fix dma_fence refcount leak on error in virtio_gpu_dma_fence_wait()

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

Gil Portnoy <[email protected]>
ksmbd: fix use-after-free of a deferred file_lock on double SMB2_CANCEL

Joonas Lahtinen <[email protected]>
drm/i915/gem: Fix phys BO pread/pwrite with offset

Sean Christopherson <[email protected]>
KVM: Don't WARN if memory is dirtied without a vCPU when the VM is dying

Inochi Amaoto <[email protected]>
mmc: litex_mmc: Use DIV_ROUND_UP for more accurate clock calculation

Masami Hiramatsu (Google) <[email protected]>
tracing/probes: Point the error offset correctly for eprobe argument error

Michael Bommarito <[email protected]>
Bluetooth: L2CAP: reject BR/EDR signaling packets over MTUsig

Yuqi Xu <[email protected]>
Bluetooth: hci_sync: reject oversized Broadcast Announcement prepend

Tristan Madani <[email protected]>
netfilter: nft_tunnel: fix use-after-free on object destroy

Alexander A. Klimov <[email protected]>
drm/vc4: fix krealloc() memory leak

Dmitry Osipenko <[email protected]>
drm/virtio: Fix driver removal with disabled KMS

Pengyu Luo <[email protected]>

    clk: qcom: dispcc-sc8280xp: Don't park mdp_clk_src at registration time

Pablo Neira Ayuso <[email protected]>
netfilter: ctnetlink: ensure safe access to master conntrack

Ido Schimmel <[email protected]>
ipv6: Fix a potential NPD in cleanup_prefix_route()

Til Kaiser <[email protected]>
net: mvpp2: build skb from XDP-adjusted data on XDP_PASS

Til Kaiser <[email protected]>
net: mvpp2: refill RX buffers before XDP or skb use

Lorenzo Bianconi <[email protected]>
net: mvpp2: Add metadata support for xdp mode

Til Kaiser <[email protected]>
net: mvpp2: limit XDP frame size to the RX buffer

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

Xiang Mei <[email protected]>
netfilter: nf_log: validate MAC header was set before dumping it

Kyle Zeng <[email protected]>
netfilter: x_tables: avoid leaking percpu counter pointers

Weiming Shi <[email protected]>
netfilter: nf_conntrack: destroy stale expectfn expectations on unregister

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()

Chih Kai Hsu <[email protected]>
r8152: handle the return value of usb_reset_device()

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

Dragos Tatulea <[email protected]>
net/mlx5: Fix slab-out-of-bounds in mlx5_query_nic_vport_mac_list

Mingyu Wang <[email protected]>
net: qrtr: fix refcount saturation and potential UAF in qrtr_port_remove

Maxime Chevallier <[email protected]>
net: phy: clean the sfp upstream if phy probing fails

Yao Sang <[email protected]>
net/mlx4: avoid GCC 10 __bad_copy_from() false positive

Eric Dumazet <[email protected]>
tcp: restrict SO_ATTACH_FILTER to priv users

Richard Fitzgerald <[email protected]>
ASoC: wm_adsp: Fix NULL dereference when removing firmware controls

Yun Zhou <[email protected]>
gpio: mvebu: fix NULL pointer dereference in suspend/resume

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()

Brian Foster <[email protected]>
iomap: don't revert iov_iter on partially completed buffered writes

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]>
tap: free page on error paths in tap_get_user_xdp()

Minh Nguyen <[email protected]>
net: skbuff: fix missing zerocopy reference in pskb_carve helpers

Gabriele Monaco <[email protected]>
tools/rv: Fix cleanup after failed trace setup

Kuen-Han Tsai <[email protected]>
usb: gadget: u_ether: Fix NULL pointer deref in eth_get_drvinfo

Kuen-Han Tsai <[email protected]>
usb: gadget: f_ncm: Fix net_device lifecycle with device_move

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()

Rui Qi <[email protected]>
ipmi: Fix rcu_read_unlock to srcu_read_unlock in handle_read_event_rsp

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()

Andy Roulin <[email protected]>
vxlan: vnifilter: fix spurious notification on VNI update

Andy Roulin <[email protected]>
vxlan: vnifilter: send notification on VNI add

Nithin Dabilpuram <[email protected]>
octeontx2-af: npc: Fix CPT channel mask in npc_install_flow

Lorenzo Bianconi <[email protected]>
net: ethernet: mtk_eth_soc: Fix use-after-free in metadata dst teardown

Kurt Kanzenbach <[email protected]>
ptp: vclock: Switch from RCU to SRCU

Eric Dumazet <[email protected]>
ipv4: restrict IPOPT_SSRR and IPOPT_LSRR options

Luiz Augusto von Dentz <[email protected]>
Bluetooth: MGMT: Fix backward compatibility with userspace

Bharath Reddy <[email protected]>
Bluetooth: fix memory leak in error path of hci_alloc_dev()

Zhang Cen <[email protected]>
Bluetooth: bnep: reject short frames before parsing

Dudu Lu <[email protected]>
Bluetooth: bnep: fix incorrect length parsing in bnep_rx_frame() extension handling

SeungJu Cheon <[email protected]>
Bluetooth: RFCOMM: validate skb length in MCC handlers

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()

Tapio Reijonen <[email protected]>
net: fec: fix pinctrl default state restore order on resume

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

Kuniyuki Iwashima <[email protected]>
hsr: Remove WARN_ONCE() in hsr_addr_is_self().

Kuniyuki Iwashima <[email protected]>

    net: Annotate sk->sk_write_space() for UDP SOCKMAP.

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

Jiayuan Chen <[email protected]>
netfilter: nft_ct: bail out on template ct in get eval

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

Gil Portnoy <[email protected]>

    ksmbd: fix NULL-deref of opinfo->conn in oplock/lease break notifiers

Amirreza Zarrabi <[email protected]>
tee: optee: prevent use-after-free when the client exits before the supplicant

Nicolò Coccia <[email protected]>
net/smc: fix sleep-inside-lock in __smc_setsockopt() causing local DoS

Ido Schimmel <[email protected]>
ipv6: mcast: Fix use-after-free when processing MLD queries

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

Guenter Roeck <[email protected]>
hwmon: (pmbus/core) Protect regulator operations with mutex

Zhu Yanjun <[email protected]>
RDMA/rxe: Fix "trying to register non-static key in rxe_qp_do_cleanup" bug

Pauli Virtanen <[email protected]>
Bluetooth: hci_conn: fix potential UAF in set_cig_params_sync

Johan Hovold <[email protected]>
USB: serial: mct_u232: fix memory corruption with small endpoint

Kuniyuki Iwashima <[email protected]>
bpf: Free reuseport cBPF prog after RCU grace period.

Michal Pecio <[email protected]>
usb: core: Fix SuperSpeed root hub wMaxPacketSize

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

Maciej W. Rozycki <[email protected]>
serial: zs: Convert to use a platform device

Maciej W. Rozycki <[email protected]>
serial: dz: Convert to use a platform device

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

Mickaël Salaün <[email protected]>
landlock: Fix handling of disconnected directories

Aleksandr Nogikh <[email protected]>
x86/kexec: Disable KCOV instrumentation after load_segments()

Doruk Tan Ozturk <[email protected]>
Bluetooth: hci_sync: fix UAF in hci_le_create_cis_sync

Johan Hovold <[email protected]>
USB: serial: cypress_m8: fix memory corruption with small endpoint

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

David Francis <[email protected]>
drm/amdkfd: Check for pdd drm file first in CRIU restore path

Eric Huang <[email protected]>
drm/amdkfd: fix a vulnerability of integer overflow in kfd debugger

Eric Huang <[email protected]>
drm/amdkfd: fix NULL pointer bug in svm_range_set_attr

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

Prasanna S <[email protected]>
serial: qcom-geni: fix UART_RX_PAR_EN bit position

Myeonghun Pak <[email protected]>
serial: altera_jtaguart: handle uart_add_one_port() failures

Timur Kristóf <[email protected]>
drm/amd/pm/si: Disregard vblank time when no displays are connected

Janusz Krzysztofik <[email protected]>
drm/i915: Fix potential UAF in TTM object purge

Berkant Koc <[email protected]>
drm/hyperv: validate VMBus packet size in receive callback

Berkant Koc <[email protected]>
drm/hyperv: validate resolution_count and fix WIN8 fallback

Alexandru Hossu <[email protected]>
scsi: target: iscsi: Validate CHAP_R length before base64 decode

Michael Bommarito <[email protected]>
scsi: target: iscsi: Bound iscsi_encode_text_output() appends to rsp_buf

Michael Bommarito <[email protected]>
scsi: scsi_transport_fc: Widen FPIN pname walker counter to u32

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()

Michael Bommarito <[email protected]>
usb: gadget: f_fs: copy only received bytes on short ep0 read

Seungjin Bae <[email protected]>
usb: gadget: dummy_hcd: Reject hub port requests for non-existent ports

Jeremy Erazo <[email protected]>
usb: gadget: composite: fix integer underflow in WebUSB GET_URL handling

Guangshuo Li <[email protected]>
usb: gadget: f_hid: fix device reference leak in hidg_alloc()

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()

Guangshuo Li <[email protected]>
counter: Fix refcount leak in counter_alloc() error path

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

Ali Ganiyev <[email protected]>
ksmbd: OOB read regression in smb_check_perm_dacl() ACE-walk loops

Dmitriy Zharov <[email protected]>
Input: xpad - add support for ASUS ROG RAIKIRI II

Qbeliw Tanaka <[email protected]>
Input: xpad - add "Nova 2 Lite" from GameSir

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().

Zhengchuan Liang <[email protected]>
xfrm: input: hold netns during deferred transport reinjection

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().

Zhengchuan Liang <[email protected]>
ipv6: exthdrs: refresh nh after handling HAO option

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

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

Peter Chen <[email protected]>
usb: cdns3: plat: fix unbalanced pm_runtime_forbid() call permanently leaks the runtime PM usage counter across bind/unbind cycles

Yongchao Wu <[email protected]>
usb: cdns3: gadget: fix request skipping after clearing halt

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

Advait Dhamorikar <[email protected]>
iio: magnetometer: st_magn: fix default DRDY pin selection for LIS2MDL

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: acquire lock when doing powerdown control

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

Jason A. Donenfeld <[email protected]>
wireguard: send: append trailer after expanding head

Sean Christopherson <[email protected]>
KVM: SVM: Flush the current TLB when transitioning from xAVIC => x2AVIC

Qiang Ma <[email protected]>
KVM: arm64: PMU: Preserve AArch32 counter low bits

Wentao Guan <[email protected]>
USB: cdc-acm: Fix bit overlap and move quirk definitions to header

Ben Hutchings <[email protected]>
parport: Fix race between port and client registration

Dmitry Torokhov <[email protected]>
Input: xpad - fix out-of-bounds access for Share button

Muhammad Bilal <[email protected]>
Bluetooth: ISO: serialize iso_sock_clear_timer with socket lock

Muhammad Bilal <[email protected]>
Bluetooth: ISO: fix UAF in iso_recv_frame

Muhammad Bilal <[email protected]>
Bluetooth: HIDP: fix missing length checks in hidp_input_report()

Siwei Zhang <[email protected]>
Bluetooth: L2CAP: fix chan ref leak in l2cap_chan_timeout() on !conn

Siwei Zhang <[email protected]>
Bluetooth: L2CAP: use chan timer to close channels in cleanup_listen()

Stepan Ionichev <[email protected]>
auxdisplay: line-display: fix OOB read on zero-length message_store()

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

hlleng <[email protected]>
HID: quirks: Add ALWAYS_POLL quirk for SIGMACHIP USB mouse

Thomas Fourier <[email protected]>
Input: ims-pcu - fix usb_free_coherent() size in ims_pcu_buffers_free()

Henri A <[email protected]>
media: rc: igorplugusb: fix control request setup packet

Johan Hovold <[email protected]>
USB: serial: safe_serial: fix memory corruption with small endpoint

Greg Kroah-Hartman <[email protected]>
usb: typec: ucsi: validate connector number in ucsi_connector_change()

Greg Kroah-Hartman <[email protected]>
usb: typec: tcpm/tcpci_maxim: validate header NDO against RX_BYTE_CNT

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

Prathamesh Shete <[email protected]>
soc/tegra: pmc: Fix unsafe generic_handle_irq() call

Abdurrahman Hussain <[email protected]>
hwmon: (pmbus/adm1266) serialize NVMEM blackbox read with pmbus_lock

Abdurrahman Hussain <[email protected]>
hwmon: (pmbus/adm1266) serialize GPIO PMBus accesses with pmbus_lock

Harshit Mogalapalli <[email protected]>
x86/kexec: add a sanity check on previous kernel's ima kexec buffer

Harshit Mogalapalli <[email protected]>
of/kexec: refactor ima_get_kexec_buffer() to use ima_validate_range()

Harshit Mogalapalli <[email protected]>
ima: verify the previous kernel's IMA buffer lies in addressable RAM

Horatiu Vultur <[email protected]>

    phy: mscc: Use PHY_ID_MATCH_EXACT for VSC8584, VSC8582, VSC8575, VSC856X

Will Deacon <[email protected]>
arm64: io: Extract user memory type in ioremap_prot()

Will Deacon <[email protected]>
arm64: io: Rename ioremap_prot() to __ioremap_prot()

Jouni Högander <[email protected]>
drm/i915/psr: Apply Intel DPCD workaround when SDP on prior line used

Suraj Kandpal <[email protected]>
drm/dp: Add eDP 1.5 bit definition

Jouni Högander <[email protected]>
drm/i915/psr: Read Intel DPCD workaround register

Jouni Högander <[email protected]>
drm/i915/psr: Add defininitions for INTEL_WA_REGISTER_CAPS DPCD register

Jakub Kicinski <[email protected]>
inet: frags: flush pending skbs in fqdir_pre_exit()

Jakub Kicinski <[email protected]>
inet: frags: add inet_frag_queue_flush()

Thomas Zimmermann <[email protected]>
drm, fbcon, vga_switcheroo: Avoid race condition in fbcon setup

Thomas Zimmermann <[email protected]>
drm/fbdev-helper: Set and clear VGA switcheroo client from fb_info

Oliver Neukum <[email protected]>
media: rc: ttusbir: fix inverted error logic

Sean Young <[email protected]>
media: rc: fix race between unregister and urb/irq callbacks

Mikhail Gavrilov <[email protected]>

    mm/page_alloc: clear page->private in free_pages_prepare()

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

Sven Eckelmann <[email protected]>
batman-adv: tp_meter: directly shut down timer on cleanup

Zhengchuan Liang <[email protected]>
net: af_key: zero aligned sockaddr tail in PF_KEY exports

Sven Eckelmann <[email protected]>
batman-adv: tp_meter: avoid role confusion in tp_list

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: tt: reject oversized local TVLV buffers

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

Yeoreum Yun <[email protected]>
perf: Fix dangling cgroup pointer in cpuctx

Pavel Begunkov <[email protected]>
net: skbuff: fix pskb_carve leaking zcopy pages

Jiayuan Chen <[email protected]>
ipv6: fix possible infinite loop in fib6_select_path()

Jiayuan Chen <[email protected]>
ipv6: fix possible infinite loop in rt6_fill_node()

Zhenghang Xiao <[email protected]>
sctp: fix race between sctp_wait_for_connect and peeloff

Dipayaan Roy <[email protected]>
net: mana: Add NULL guards in teardown path to prevent panic on attach failure

Marco Scardovi <[email protected]>

    gpio: rockchip: convert bank->clk to devm_clk_get_enabled()

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()

Jakub Kicinski <[email protected]>
ethtool: eeprom: add more safeties to EEPROM Netlink fallback

Jakub Kicinski <[email protected]>
ethtool: eeprom: add missing ethnl_ops_begin() / _complete() during fallback

Oliver Hartkopp <[email protected]>
bonding: refuse to enslave CAN devices

Zhao Dongdong <[email protected]>
Bluetooth: 6lowpan: check skb_clone() return value in send_mcast_pkt()

Cássio Gabriel <[email protected]>
ASoC: codecs: simple-mux: Fix enum control bounds check

Sean Shen <[email protected]>
ksmbd: fix FSCTL permission bypass by adding a permission check for FSCTL_SET_SPARSE

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]()

Alexander Stein <[email protected]>
gpio: mxc: fix irq_high handling

Luka Gejak <[email protected]>
net: hsr: fix potential OOB access in supervision frame handling

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()

David Jeffery <[email protected]>
scsi: core: Run queues for all non-SDEV_DEL devices from scsi_run_host_queues

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

Ziyu Zhang <[email protected]>
vsock: keep poll shutdown state consistent

Weiming Shi <[email protected]>
tun: free page on build_skb failure in tun_xdp_one()

Weiming Shi <[email protected]>
tun: free page on short-frame rejection in tun_xdp_one()

Fernando Fernandez Mancera <[email protected]>
netfilter: nf_tables: fix dst corruption in same register operation

Jeremy Sowden <[email protected]>
netfilter: bitwise: add support for doing AND, OR and XOR directly

Jeremy Sowden <[email protected]>
netfilter: bitwise: rename some boolean operation functions

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()

Kevin Hao <[email protected]>
net: cpsw_new: Fix potential unregister of netdev that has not been registered yet

Mingzhe Zou <[email protected]>
bcache: fix uninitialized closure object

Carlos Eduardo Gallo Filho <[email protected]>
drm: Remove plane hsub/vsub alignment requirement for core helpers

Victor Nogueria <[email protected]>
net/sched: sch_sfb: Replace direct dequeue call with peek and qdisc_dequeue_peeked

Jeremy Kerr <[email protected]>
net: mctp: ensure our nlmsg responses are initialised

Davide Caratti <[email protected]>
net/sched: cls_fw: fix NULL dereference of "old" filters before change()

Greg Kroah-Hartman <[email protected]>
Input: usbtouchscreen - clamp NEXIO data_len/x_len to URB buffer size

-------------

Diffstat:

 Documentation/arch/arm64/silicon-errata.rst        |  48 +++
 Makefile                                           |   4 +-
 arch/arm/include/asm/io.h                          |  15 +-
 arch/arm/kernel/entry-armv.S                       |   2 +-
 arch/arm/mach-socfpga/platsmp.c                    |   1 +
 arch/arm64/Kconfig                                 |  50 +++
 arch/arm64/include/asm/cputype.h                   |   6 +
 arch/arm64/include/asm/io.h                        |  25 +-
 arch/arm64/include/asm/kvm_mmu.h                   |   5 +-
 arch/arm64/include/asm/tlb.h                       |   2 +-
 arch/arm64/include/asm/tlbflush.h                  |  64 ++--
 arch/arm64/kernel/acpi.c                           |   2 +-
 arch/arm64/kernel/cpu_errata.c                     |  34 +-
 arch/arm64/kernel/sys_compat.c                     |   2 +-
 arch/arm64/kvm/hyp/nvhe/mm.c                       |   2 +-
 arch/arm64/kvm/hyp/nvhe/pkvm.c                     |   2 +-
 arch/arm64/kvm/hyp/nvhe/tlb.c                      |  69 +---
 arch/arm64/kvm/hyp/pgtable.c                       |   2 +-
 arch/arm64/kvm/hyp/vhe/tlb.c                       |  21 +-
 arch/arm64/kvm/pmu-emul.c                          |   4 +-
 arch/arm64/mm/ioremap.c                            |   8 +-
 arch/mips/dec/platform.c                           | 109 +++++-
 arch/x86/kernel/Makefile                           |  14 +
 arch/x86/kernel/cpu/amd.c                          |  33 +-
 arch/x86/kernel/setup.c                            |   6 +
 arch/x86/kvm/svm/avic.c                            |  35 +-
 arch/x86/mm/Makefile                               |   2 +
 drivers/auxdisplay/line-display.c                  |   2 +-
 drivers/base/bus.c                                 |  11 +-
 drivers/block/zram/zram_drv.c                      |   2 +-
 drivers/bluetooth/btusb.c                          |   8 +-
 drivers/bluetooth/hci_qca.c                        |  38 +--
 drivers/char/ipmi/ipmi_msghandler.c                |   2 +-
 drivers/char/ipmi/ipmi_ssif.c                      |  29 +-
 drivers/clk/qcom/dispcc-sc8280xp.c                 |   4 +-
 drivers/comedi/drivers/comedi_test.c               |   5 +-
 drivers/counter/counter-core.c                     |   3 +-
 drivers/gpio/gpio-mvebu.c                          |   4 +-
 drivers/gpio/gpio-mxc.c                            |   2 +-
 drivers/gpio/gpio-rockchip.c                       |   6 +-
 drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c             |   4 +-
 drivers/gpu/drm/amd/amdkfd/kfd_chardev.c           |  10 +-
 .../gpu/drm/amd/amdkfd/kfd_device_queue_manager.c  |  10 +-
 drivers/gpu/drm/amd/amdkfd/kfd_mqd_manager_v11.c   |  49 ++-
 drivers/gpu/drm/amd/amdkfd/kfd_svm.c               |   3 +
 .../drm/amd/display/amdgpu_dm/amdgpu_dm_debugfs.c  |   5 +
 drivers/gpu/drm/amd/display/dc/basics/vector.c     |   4 +-
 drivers/gpu/drm/amd/display/dc/bios/bios_parser2.c |  54 ++-
 .../gpu/drm/amd/display/modules/hdcp/hdcp_ddc.c    |   3 +-
 drivers/gpu/drm/amd/pm/legacy-dpm/si_dpm.c         |   4 +
 drivers/gpu/drm/bridge/sil-sii8620.c               |   1 +
 drivers/gpu/drm/drm_fb_helper.c                    |  12 +-
 drivers/gpu/drm/hyperv/hyperv_drm_proto.c          | 113 ++++++-
 drivers/gpu/drm/i915/display/intel_display_types.h |   1 +
 drivers/gpu/drm/i915/display/intel_dpcd.h          |  15 +
 drivers/gpu/drm/i915/display/intel_psr.c           |  34 +-
 drivers/gpu/drm/i915/gem/i915_gem_phys.c           |  19 +-
 drivers/gpu/drm/i915/gem/i915_gem_ttm.c            |  28 +-
 drivers/gpu/drm/imx/dcss/dcss-scaler.c             |   3 +
 drivers/gpu/drm/vc4/vc4_validate_shaders.c         |  13 +-
 drivers/gpu/drm/virtio/virtgpu_drv.c               |   5 +-
 drivers/gpu/drm/virtio/virtgpu_submit.c            |   4 +-
 drivers/hid/bpf/hid_bpf_dispatch.c                 |   3 +-
 drivers/hid/hid-core.c                             |  35 +-
 drivers/hid/hid-gfrm.c                             |   4 +-
 drivers/hid/hid-ids.h                              |   1 +
 drivers/hid/hid-logitech-hidpp.c                   |   2 +-
 drivers/hid/hid-multitouch.c                       |   2 +-
 drivers/hid/hid-picolcd_cir.c                      |   1 +
 drivers/hid/hid-primax.c                           |   2 +-
 drivers/hid/hid-quirks.c                           |   1 +
 drivers/hid/hid-vivaldi-common.c                   |   2 +-
 drivers/hid/wacom_sys.c                            |  19 +-
 drivers/hid/wacom_wac.h                            |   1 +
 drivers/hwmon/pmbus/adm1266.c                      |  49 ++-
 drivers/hwmon/pmbus/pmbus_core.c                   | 117 +++++--
 drivers/i2c/busses/i2c-qcom-cci.c                  |   2 +-
 drivers/i2c/busses/i2c-stm32f7.c                   |   6 +-
 drivers/i2c/busses/i2c-tegra.c                     |  53 +--
 drivers/i2c/i2c-dev.c                              |   9 +-
 drivers/iio/adc/npcm_adc.c                         |  31 +-
 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                           |  16 +-
 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/magnetometer/st_magn_core.c            |  13 +-
 drivers/iio/temperature/tsys01.c                   |   2 +-
 drivers/infiniband/core/Makefile                   |   2 +-
 drivers/infiniband/core/iter.c                     |  43 +++
 drivers/infiniband/core/umem.c                     |  16 +
 drivers/infiniband/core/verbs.c                    |  38 ---
 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/erdma/erdma_verbs.c          |   2 +-
 drivers/infiniband/hw/hns/hns_roce_alloc.c         |   2 +-
 drivers/infiniband/hw/hns/hns_roce_mr.c            |   4 +
 drivers/infiniband/hw/irdma/main.h                 |   2 +-
 drivers/infiniband/hw/irdma/verbs.c                |   4 +
 drivers/infiniband/hw/mana/mana_ib.h               |   2 +-
 drivers/infiniband/hw/mlx4/mr.c                    |   5 +
 drivers/infiniband/hw/mlx5/mem.c                   |   1 +
 drivers/infiniband/hw/mlx5/mr.c                    |   4 +
 drivers/infiniband/hw/mlx5/umr.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_qp.c                 |   7 +-
 drivers/infiniband/sw/rxe/rxe_verbs.c              |   5 +
 drivers/infiniband/ulp/isert/ib_isert.c            |   6 +
 drivers/infiniband/ulp/srp/ib_srp.c                |  30 +-
 drivers/input/joystick/xpad.c                      |  14 +-
 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/md/bcache/super.c                          |   3 +-
 drivers/md/dm-cache-policy-smq.c                   |  12 +-
 drivers/media/cec/core/cec-core.c                  |   2 +-
 drivers/media/common/siano/smsir.c                 |   1 +
 drivers/media/i2c/ir-kbd-i2c.c                     |   2 +
 drivers/media/pci/bt8xx/bttv-input.c               |   3 +-
 drivers/media/pci/cx23885/cx23885-input.c          |   1 +
 drivers/media/pci/cx88/cx88-input.c                |   3 +-
 drivers/media/pci/dm1105/dm1105.c                  |   1 +
 drivers/media/pci/mantis/mantis_input.c            |   1 +
 drivers/media/pci/saa7134/saa7134-input.c          |   1 +
 drivers/media/pci/smipcie/smipcie-ir.c             |   1 +
 drivers/media/pci/ttpci/budget-ci.c                |   1 +
 drivers/media/rc/ati_remote.c                      |   6 +-
 drivers/media/rc/ene_ir.c                          |   2 +-
 drivers/media/rc/fintek-cir.c                      |   3 +-
 drivers/media/rc/igorplugusb.c                     |   3 +-
 drivers/media/rc/iguanair.c                        |   1 +
 drivers/media/rc/img-ir/img-ir-hw.c                |   3 +-
 drivers/media/rc/img-ir/img-ir-raw.c               |   3 +-
 drivers/media/rc/imon.c                            |   3 +-
 drivers/media/rc/ir-hix5hd2.c                      |   2 +-
 drivers/media/rc/ir_toy.c                          |   1 +
 drivers/media/rc/ite-cir.c                         |   2 +-
 drivers/media/rc/mceusb.c                          |   1 +
 drivers/media/rc/rc-ir-raw.c                       |   5 -
 drivers/media/rc/rc-loopback.c                     |   1 +
 drivers/media/rc/rc-main.c                         |   6 +-
 drivers/media/rc/redrat3.c                         |   4 +-
 drivers/media/rc/st_rc.c                           |   2 +-
 drivers/media/rc/streamzap.c                       |   7 +-
 drivers/media/rc/sunxi-cir.c                       |   1 +
 drivers/media/rc/ttusbir.c                         |   4 +-
 drivers/media/rc/winbond-cir.c                     |   2 +-
 drivers/media/rc/xbox_remote.c                     |   5 +-
 drivers/media/usb/au0828/au0828-input.c            |   1 +
 drivers/media/usb/dvb-usb-v2/dvb_usb_core.c        |   1 +
 drivers/media/usb/dvb-usb/dvb-usb-remote.c         |   6 +-
 drivers/media/usb/em28xx/em28xx-input.c            |   1 +
 drivers/misc/fastrpc.c                             | 107 +++---
 drivers/mmc/core/mmc.c                             |   4 +-
 drivers/mmc/host/litex_mmc.c                       |  20 +-
 drivers/mmc/host/renesas_sdhi_internal_dmac.c      |   1 +
 drivers/mmc/host/sdhci.c                           |   1 +
 drivers/net/bonding/bond_main.c                    |  12 +-
 drivers/net/ethernet/amd/pcnet32.c                 |   4 +-
 drivers/net/ethernet/broadcom/bnxt/bnxt.c          |   2 +-
 drivers/net/ethernet/freescale/fec_main.c          |   3 +-
 drivers/net/ethernet/intel/ice/ice_virtchnl.c      |   2 +-
 drivers/net/ethernet/marvell/mv643xx_eth.c         |   2 +-
 drivers/net/ethernet/marvell/mvpp2/mvpp2_main.c    |  75 +++--
 drivers/net/ethernet/marvell/octeontx2/af/cgx.c    |  13 +-
 drivers/net/ethernet/marvell/octeontx2/af/rvu.c    |   2 +-
 drivers/net/ethernet/marvell/octeontx2/af/rvu.h    |   1 +
 .../net/ethernet/marvell/octeontx2/af/rvu_npc.c    |  32 +-
 .../net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c |   2 +-
 .../ethernet/marvell/octeontx2/nic/otx2_common.c   |   2 +
 drivers/net/ethernet/mediatek/mtk_eth_soc.c        |   2 +-
 drivers/net/ethernet/mellanox/mlx4/cq.c            |   9 +-
 drivers/net/ethernet/mellanox/mlx5/core/cmd.c      |   6 +-
 drivers/net/ethernet/mellanox/mlx5/core/eswitch.c  |  13 +-
 drivers/net/ethernet/mellanox/mlx5/core/vport.c    |  72 +++-
 drivers/net/ethernet/microchip/lan743x_main.c      |  32 ++
 drivers/net/ethernet/microchip/lan743x_main.h      |   1 +
 drivers/net/ethernet/microsoft/mana/mana_en.c      |  72 ++--
 drivers/net/ethernet/ti/cpsw_new.c                 |   4 +-
 drivers/net/hyperv/netvsc.c                        |  19 +-
 drivers/net/macsec.c                               |   3 +-
 drivers/net/phy/mscc/mscc.h                        |   8 +-
 drivers/net/phy/mscc/mscc_main.c                   |  23 +-
 drivers/net/phy/phy_device.c                       |   6 +
 drivers/net/tap.c                                  |   2 +
 drivers/net/tun.c                                  |   5 +-
 drivers/net/usb/r8152.c                            |   7 +-
 drivers/net/vxlan/vxlan_core.c                     |   4 +-
 drivers/net/vxlan/vxlan_vnifilter.c                |   5 +-
 drivers/net/wireguard/send.c                       |  20 +-
 drivers/nfc/nxp-nci/i2c.c                          |  21 +-
 drivers/nvmem/layouts/onie-tlv.c                   |   3 +-
 drivers/of/kexec.c                                 |  15 +-
 drivers/parport/share.c                            |  11 +-
 drivers/platform/x86/intel/vsec.c                  |  34 +-
 drivers/ptp/ptp_vclock.c                           |  14 +-
 drivers/scsi/fcoe/fcoe_ctlr.c                      |   2 +-
 drivers/scsi/scsi_lib.c                            |  27 +-
 drivers/scsi/scsi_transport_fc.c                   |  77 +++--
 drivers/slimbus/qcom-ngd-ctrl.c                    |   5 +-
 drivers/soc/qcom/ice.c                             |  36 +-
 drivers/soc/tegra/pmc.c                            | 104 ++++--
 drivers/staging/greybus/hid.c                      |   2 +-
 drivers/staging/media/av7110/av7110_ir.c           |   1 +
 drivers/target/iscsi/iscsi_target.c                |   6 +-
 drivers/target/iscsi/iscsi_target_auth.c           |  19 +-
 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/tee/optee/supp.c                           | 107 ++++--
 drivers/thunderbolt/property.c                     |  38 ++-
 drivers/thunderbolt/xdomain.c                      |  14 +-
 drivers/tty/serdev/core.c                          |  23 +-
 drivers/tty/serial/altera_jtaguart.c               |   7 +-
 drivers/tty/serial/dz.c                            | 171 +++++-----
 drivers/tty/serial/fsl_lpuart.c                    |  15 +-
 drivers/tty/serial/pch_uart.c                      |  19 +-
 drivers/tty/serial/qcom_geni_serial.c              |  17 +-
 drivers/tty/serial/samsung_tty.c                   | 129 ++++---
 drivers/tty/serial/sh-sci.c                        |   2 +-
 drivers/tty/serial/zs.c                            | 218 +++++-------
 drivers/tty/serial/zs.h                            |   1 -
 drivers/usb/cdns3/cdns3-gadget.c                   |  12 +-
 drivers/usb/cdns3/cdns3-plat.c                     |  11 +-
 drivers/usb/chipidea/core.c                        |  16 +-
 drivers/usb/class/cdc-acm.c                        |   2 -
 drivers/usb/class/cdc-acm.h                        |   2 +
 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/dwc3-xilinx.c                     |  26 +-
 drivers/usb/gadget/composite.c                     |   5 +-
 drivers/usb/gadget/function/f_fs.c                 |   2 +-
 drivers/usb/gadget/function/f_hid.c                |   3 +-
 drivers/usb/gadget/function/f_ncm.c                |  33 +-
 drivers/usb/gadget/function/f_uvc.c                |  26 +-
 drivers/usb/gadget/function/u_ether.c              |  28 +-
 drivers/usb/gadget/function/u_ether.h              |  26 ++
 drivers/usb/gadget/function/u_ncm.h                |   2 +-
 drivers/usb/gadget/udc/dummy_hcd.c                 |   4 +
 drivers/usb/gadget/udc/net2280.c                   |   4 +-
 drivers/usb/host/xhci-tegra.c                      |  77 +++--
 drivers/usb/musb/omap2430.c                        |   3 +-
 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/tcpci_maxim_core.c          |   9 +
 drivers/usb/typec/tcpm/wcove.c                     |  13 +-
 drivers/usb/typec/ucsi/displayport.c               |   4 +
 drivers/usb/typec/ucsi/ucsi.c                      |  24 +-
 drivers/usb/typec/ucsi/ucsi_ccg.c                  |   5 +
 drivers/usb/usbip/vudc_dev.c                       |   1 +
 drivers/usb/usbip/vudc_transfer.c                  |   3 +-
 drivers/video/fbdev/Kconfig                        |   1 +
 drivers/video/fbdev/core/fbcon.c                   |   9 +
 drivers/video/fbdev/vt8500lcdfb.c                  |   4 +-
 fs/fcntl.c                                         |   8 +-
 fs/fuse/dev.c                                      |   9 +-
 fs/hpfs/alloc.c                                    |   2 +-
 fs/iomap/buffered-io.c                             |   4 -
 fs/smb/client/netlink.c                            |   6 +-
 fs/smb/server/oplock.c                             |  15 +-
 fs/smb/server/smb2pdu.c                            | 143 ++++++--
 fs/smb/server/smbacl.c                             |  51 ++-
 fs/smb/server/smbacl.h                             |   2 +
 include/drm/display/drm_dp.h                       |   1 +
 include/drm/drm_fourcc.h                           |   5 +-
 include/linux/bpf_verifier.h                       |   4 +
 include/linux/compat.h                             |   4 +
 include/linux/compiler-clang.h                     |   6 +
 include/linux/compiler_attributes.h                |  11 +
 include/linux/compiler_types.h                     |   4 +
 include/linux/hid.h                                |  15 +-
 include/linux/hid_bpf.h                            |   4 +-
 include/linux/hugetlb.h                            |  16 +-
 include/linux/ima.h                                |   1 +
 include/linux/mlx5/vport.h                         |   4 +-
 include/linux/mm.h                                 |   8 -
 include/linux/parport.h                            |   1 +
 include/linux/serdev.h                             |   1 +
 include/linux/syscalls.h                           |   4 +
 include/media/rc-core.h                            |   2 -
 include/net/act_api.h                              |   1 +
 include/net/bluetooth/l2cap.h                      |   1 +
 include/net/genetlink.h                            |   9 +-
 include/net/inet_frag.h                            |  18 +-
 include/net/ip_vs.h                                |   3 +-
 include/net/ipv6_frag.h                            |   9 +-
 include/net/netfilter/nf_conntrack_core.h          |   5 +
 include/net/netfilter/nf_conntrack_helper.h        |   1 +
 include/net/netfilter/nf_tables.h                  |   7 +
 include/net/sock.h                                 |   1 +
 include/net/xfrm.h                                 |   3 +-
 include/rdma/ib_umem.h                             |  44 +--
 include/rdma/ib_verbs.h                            |  48 ---
 include/rdma/iter.h                                |  88 +++++
 include/uapi/linux/netfilter/nf_tables.h           |  18 +-
 ipc/shm.c                                          |  10 +-
 ipc/util.c                                         |   2 +-
 kernel/bpf/verifier.c                              | 369 +++++++++++++--------
 kernel/cgroup/cpuset.c                             |   8 +-
 kernel/events/core.c                               |  16 +-
 kernel/pid.c                                       |   8 +-
 kernel/signal.c                                    |   1 +
 kernel/time/time.c                                 |   2 +-
 kernel/trace/trace_probe.c                         |   2 -
 lib/debugobjects.c                                 |   2 +-
 mm/damon/ops-common.c                              |   4 +-
 mm/damon/sysfs-schemes.c                           |   8 +-
 mm/gup.c                                           |   2 +-
 mm/huge_memory.c                                   |   2 +
 mm/hugetlb.c                                       | 118 ++++---
 mm/memfd.c                                         |  12 +-
 mm/memory-failure.c                                |  94 +++---
 mm/memory.c                                        |   2 +-
 mm/memory_hotplug.c                                |   2 +-
 mm/mempolicy.c                                     |   2 +-
 mm/migrate.c                                       |  18 +-
 mm/page_alloc.c                                    |   1 +
 net/6lowpan/iphc.c                                 |   4 +-
 net/802/garp.c                                     |   2 +-
 net/802/mrp.c                                      |   9 +
 net/batman-adv/bat_iv_ogm.c                        |  82 ++++-
 net/batman-adv/bat_v_ogm.c                         |  59 ++--
 net/batman-adv/bridge_loop_avoidance.c             |  57 +++-
 net/batman-adv/soft-interface.c                    |   1 +
 net/batman-adv/tp_meter.c                          |  67 ++--
 net/batman-adv/translation-table.c                 |  43 ++-
 net/batman-adv/tvlv.c                              |  28 +-
 net/batman-adv/tvlv.h                              |   2 +-
 net/batman-adv/types.h                             |  42 ++-
 net/bluetooth/6lowpan.c                            |   2 +
 net/bluetooth/bnep/core.c                          |  50 ++-
 net/bluetooth/hci_conn.c                           |   8 +-
 net/bluetooth/hci_sync.c                           |   9 +-
 net/bluetooth/hci_sysfs.c                          |   6 +-
 net/bluetooth/hidp/core.c                          |  23 +-
 net/bluetooth/iso.c                                |  12 +-
 net/bluetooth/l2cap_core.c                         |  87 ++++-
 net/bluetooth/l2cap_sock.c                         |  16 +-
 net/bluetooth/mgmt.c                               |  17 +-
 net/bluetooth/rfcomm/core.c                        |  69 ++--
 net/bluetooth/rfcomm/sock.c                        |  26 +-
 net/bridge/netfilter/ebt_snat.c                    |   3 +
 net/bridge/netfilter/ebtables.c                    |  30 ++
 net/core/drop_monitor.c                            |   2 +-
 net/core/filter.c                                  |  17 +-
 net/core/skbuff.c                                  |  20 +-
 net/core/sock.c                                    |  13 +-
 net/ethtool/eeprom.c                               |  10 +-
 net/hsr/hsr_forward.c                              |   4 +-
 net/hsr/hsr_framereg.c                             |  10 +-
 net/ieee802154/6lowpan/tx.c                        |   5 +
 net/ipv4/ah4.c                                     |   2 +-
 net/ipv4/esp4.c                                    |   4 +-
 net/ipv4/inet_fragment.c                           |  54 ++-
 net/ipv4/ip_fragment.c                             |  21 +-
 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/nf_nat_h323.c                   |   2 +
 net/ipv4/netfilter/nft_fib_ipv4.c                  |   2 +-
 net/ipv4/sysctl_net_ipv4.c                         |   2 +-
 net/ipv4/udp.c                                     |   8 +
 net/ipv6/addrconf.c                                |  53 +--
 net/ipv6/ah6.c                                     |   2 +-
 net/ipv6/datagram.c                                |  54 ++-
 net/ipv6/esp6.c                                    |   4 +-
 net/ipv6/exthdrs.c                                 |  35 +-
 net/ipv6/ioam6.c                                   |   8 +-
 net/ipv6/ip6_input.c                               |   2 +-
 net/ipv6/ip6_vti.c                                 |  25 +-
 net/ipv6/mcast.c                                   |  22 +-
 net/ipv6/ndisc.c                                   |  18 +-
 net/ipv6/netfilter/ip6_tables.c                    |  15 +-
 net/ipv6/netfilter/nft_fib_ipv6.c                  |   2 +-
 net/ipv6/route.c                                   |   5 +
 net/ipv6/seg6_hmac.c                               |   8 +-
 net/ipv6/sit.c                                     |   1 +
 net/iucv/af_iucv.c                                 |  20 +-
 net/key/af_key.c                                   |  58 ++--
 net/mctp/device.c                                  |   1 +
 net/mctp/neigh.c                                   |   1 +
 net/mctp/route.c                                   |   1 +
 net/mptcp/options.c                                |  73 ++--
 net/mptcp/pm.c                                     |  49 ++-
 net/mptcp/pm_netlink.c                             |  18 +-
 net/mptcp/protocol.c                               | 102 ++++--
 net/mptcp/protocol.h                               |  17 +-
 net/mptcp/sockopt.c                                |   8 +-
 net/mptcp/subflow.c                                |  20 +-
 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/nf_conntrack_ecache.c                |   2 +
 net/netfilter/nf_conntrack_expect.c                |  10 +-
 net/netfilter/nf_conntrack_helper.c                |  19 ++
 net/netfilter/nf_conntrack_irc.c                   |   4 +-
 net/netfilter/nf_conntrack_netlink.c               |  28 +-
 net/netfilter/nf_conntrack_proto_tcp.c             |   3 +-
 net/netfilter/nf_log_syslog.c                      |   4 +-
 net/netfilter/nf_nat_core.c                        |   2 +
 net/netfilter/nf_nat_sip.c                         |   1 +
 net/netfilter/nf_synproxy_core.c                   |  26 +-
 net/netfilter/nft_bitwise.c                        | 184 ++++++++--
 net/netfilter/nft_byteorder.c                      |  13 +-
 net/netfilter/nft_ct.c                             |   8 +-
 net/netfilter/nft_ct_fast.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                  |  30 +-
 net/netlink/af_netlink.c                           |  11 +-
 net/netlink/genetlink.c                            |   4 +-
 net/nfc/hci/core.c                                 |  10 +
 net/nfc/llcp_core.c                                |  11 +
 net/nfc/llcp_sock.c                                |   2 +
 net/nfc/nci/hci.c                                  |  10 +
 net/openvswitch/datapath.c                         |   1 +
 net/psample/psample.c                              |   2 +-
 net/qrtr/af_qrtr.c                                 |   4 +-
 net/rds/ib_cm.c                                    |   1 +
 net/rds/ib_send.c                                  |   2 +
 net/rds/info.c                                     |   2 +-
 net/rxrpc/ar-internal.h                            |  12 +-
 net/rxrpc/call_event.c                             |  27 +-
 net/rxrpc/call_object.c                            |   2 +
 net/rxrpc/conn_event.c                             |  30 +-
 net/rxrpc/insecure.c                               |   8 +-
 net/rxrpc/recvmsg.c                                |  68 +++-
 net/rxrpc/rxkad.c                                  | 115 +++----
 net/sched/act_api.c                                |   7 +-
 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                                   |  21 +-
 net/socket.c                                       |  11 +-
 net/unix/af_unix.c                                 |  38 +--
 net/vmw_vsock/af_vsock.c                           |  49 ++-
 net/vmw_vsock/hyperv_transport.c                   |   9 +-
 net/vmw_vsock/virtio_transport_common.c            |  14 +-
 net/vmw_vsock/vmci_transport.c                     |  12 +-
 net/wireless/nl80211.c                             |   3 +
 net/xfrm/espintcp.c                                |   4 +
 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/integrity/ima/ima_kexec.c                 |  35 ++
 security/landlock/errata/abi-1.h                   |  16 +
 security/landlock/fs.c                             |  40 ++-
 sound/core/pcm_native.c                            |   7 +-
 sound/core/timer.c                                 |   1 +
 .../motu/motu-register-dsp-message-parser.c        |  14 +-
 sound/pci/hda/patch_hdmi.c                         |   1 +
 sound/soc/codecs/simple-mux.c                      |   2 +-
 sound/soc/codecs/wm_adsp.c                         |   3 +
 sound/soc/fsl/fsl_sai.c                            |   2 +-
 sound/soc/intel/boards/bytcht_es8316.c             |  29 +-
 sound/soc/qcom/qdsp6/q6asm-dai.c                   |  43 +--
 .../selftests/bpf/progs/verifier_scalar_ids.c      | 333 ++++++++++++-------
 .../selftests/bpf/progs/verifier_spill_fill.c      |   4 +-
 .../bpf/progs/verifier_subprog_precision.c         |   2 +-
 tools/testing/selftests/bpf/verifier/precise.c     |   2 +-
 .../test.d/dynevent/eprobes_syntax_errors.tc       |   2 +-
 tools/testing/selftests/mm/hmm-tests.c             |  50 +++
 tools/testing/selftests/net/mptcp/mptcp_connect.sh |   6 +-
 tools/testing/selftests/net/mptcp/mptcp_join.sh    |   4 +
 tools/testing/selftests/ptp/testptp.c              |  62 +---
 tools/verification/rv/src/in_kernel.c              |   2 +-
 virt/kvm/kvm_main.c                                |   3 +-
 508 files changed, 5864 insertions(+), 3002 deletions(-)
author maintainer
#1 lore raw

PATCH 1/452 Input: usbtouchscreen - clamp NEXIO data_len/x_len to URB buffer size

6.6-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.

Cc Dmitry Torokhov <[email protected]>
Fixes 5197424cdccc ("Input: usbtouchscreen - add NEXIO (or iNexio) support")
Cc stable <[email protected]>
Assisted-by gkh_clanker_t1000
---
 drivers/input/touchscreen/usbtouchscreen.c |    5 +++++
 1 file changed, 5 insertions(+)
drivers/input/touchscreen/usbtouchscreen.c +5 -0
@@ -1061,6 +1061,11 @@ static int nexio_read_data(struct usbtou
 	if (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);
 	if (ret)
author maintainer
#2 lore raw

PATCH 2/452 net/sched: cls_fw: fix NULL dereference of "old" filters before change()

In reply to Greg Kroah-Hartman

6.6-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

Fixes faeea8bbf6e9 ("net/sched: cls_fw: fix NULL pointer dereference on shared blocks")
Fixes ed76f5edccc9 ("net: sched: protect filter_chain list with filter_chain_lock mutex")
---
 net/sched/cls_fw.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)
net/sched/cls_fw.c +5 -1
index 2e5e8df5ca55c4..bc007bb47432cd 100644
@@ -74,9 +74,13 @@ TC_INDIRECT_SCOPE int fw_classify(struct sk_buff *skb,
 			}
 		}
 	} 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
author maintainer
#3 lore raw

PATCH 3/452 net: mctp: ensure our nlmsg responses are initialised

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jeremy Kerr <[email protected]>

[ Upstream commit a6a9bc544b675d8b5180f2718ec985ad267b5cbf ]

Syed Faraz Abrar (@farazsth98) from Zellic, and Pumpkin (@u1f383) from DEVCORE Research Team working with Trend Micro Zero Day Initiative report that a RTM_GETNEIGH will return uninitalised data in the pad bytes of the ndmsg data.

Ensure we're initialising the netlink data to zero, in the link, addr and neigh response messages.

Fixes 831119f88781 ("mctp: Add neighbour netlink interface")
Fixes 06d2f4c583a7 ("mctp: Add netlink route management")
Fixes 583be982d934 ("mctp: Add device handling and netlink interface")
---
 net/mctp/device.c | 1 +
 net/mctp/neigh.c  | 1 +
 net/mctp/route.c  | 1 +
 3 files changed, 3 insertions(+)
net/mctp/device.c +1 -0
index 8d1386601bbe06..67576cb2728ece 100644
@@ -70,6 +70,7 @@ static int mctp_fill_addrinfo(struct sk_buff *skb,
 		return -EMSGSIZE;
 
 	hdr = nlmsg_data(nlh);
+	memset(hdr, 0, sizeof(*hdr));
 	hdr->ifa_family = AF_MCTP;
 	hdr->ifa_prefixlen = 0;
 	hdr->ifa_flags = 0;
net/mctp/neigh.c +1 -0
index 590f642413e4ef..c0151a69d2b7c2 100644
@@ -218,6 +218,7 @@ static int mctp_fill_neigh(struct sk_buff *skb, u32 portid, u32 seq, int event,
 		return -EMSGSIZE;
 
 	hdr = nlmsg_data(nlh);
+	memset(hdr, 0, sizeof(*hdr));
 	hdr->ndm_family = AF_MCTP;
 	hdr->ndm_ifindex = dev->ifindex;
 	hdr->ndm_state = 0; // TODO other state bits?
net/mctp/route.c +1 -0
index a565cf2bc7330d..6d6e19c049396f 100644
@@ -1332,6 +1332,7 @@ static int mctp_fill_rtinfo(struct sk_buff *skb, struct mctp_route *rt,
 		return -EMSGSIZE;
 
 	hdr = nlmsg_data(nlh);
+	memset(hdr, 0, sizeof(*hdr));
 	hdr->rtm_family = AF_MCTP;
 
 	/* we use the _len fields as a number of EIDs, rather than
Signature · 1 line
2.53.0
author maintainer
#4 lore raw

PATCH 4/452 net/sched: sch_sfb: Replace direct dequeue call with peek and qdisc_dequeue_peeked

In reply to Greg Kroah-Hartman

6.6-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
index ce67826fdf9b6d..58bf4c803f7fee 100644
@@ -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
author maintainer
#5 lore raw

PATCH 5/452 drm: Remove plane hsub/vsub alignment requirement for core helpers

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Carlos Eduardo Gallo Filho <[email protected]>

[ Upstream commit f2f455981a34ce8ca88a41458c09494b387d344f ]

The drm_format_info_plane_{height,width} functions was implemented using regular division for the plane size calculation, which cause issues [1][2] when used on contexts where the dimensions are misaligned with relation to the subsampling factors. So, replace the regular division by the DIV_ROUND_UP macro.

This allows these functions to be used in more drivers, making further work to bring more core presence on them possible.

[1] http://patchwork.freedesktop.org/patch/msgid/[email protected]
[2] https://patchwork.freedesktop.org/patch/msgid/[email protected]

---
 include/drm/drm_fourcc.h | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)
include/drm/drm_fourcc.h +3 -2
index 532ae78ca747e6..ccf91daa430702 100644
@@ -22,6 +22,7 @@
 #ifndef __DRM_FOURCC_H__
 #define __DRM_FOURCC_H__
 
+#include <linux/math.h>
 #include <linux/types.h>
 #include <uapi/drm/drm_fourcc.h>
 
@@ -279,7 +280,7 @@ int drm_format_info_plane_width(const struct drm_format_info *info, int width,
 	if (plane == 0)
 		return width;
 
-	return width / info->hsub;
+	return DIV_ROUND_UP(width, info->hsub);
 }
 
 /**
@@ -301,7 +302,7 @@ int drm_format_info_plane_height(const struct drm_format_info *info, int height,
 	if (plane == 0)
 		return height;
 
-	return height / info->vsub;
+	return DIV_ROUND_UP(height, info->vsub);
 }
 
 const struct drm_format_info *__drm_format_info(u32 format);
Signature · 1 line
2.53.0
author maintainer
#6 lore raw

PATCH 6/452 bcache: fix uninitialized closure object

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Mingzhe Zou <[email protected]>

[ Upstream commit 20a8e451ec1c7e99060b1bbaaad03ce88c39ddb8 ]

In the previous patch ("bcache: fix cached_dev.sb_bio use-after-free and crash"), we adopted a simple modification suggestion from AI to fix the use-after-free.

But in actual testing, we found an extreme case where the device is stopped before calling bch_write_bdev_super().

At this point, struct closure sb_write has not been initialized yet. For this patch, we ensure that sb_bio has been completed via sb_write_mutex.

Fixes fec114a98b87 ("bcache: fix cached_dev.sb_bio use-after-free and crash")
---
 drivers/md/bcache/super.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/md/bcache/super.c +2 -1
index a66423cf12d0a7..6d9349f6f8fd75 100644
@@ -1372,7 +1372,8 @@ static void cached_dev_free(struct closure *cl)
 	 * The sb_bio is embedded in struct cached_dev, so we must
 	 * ensure no I/O is in progress.
 	 */
-	closure_sync(&dc->sb_write);
+	down(&dc->sb_write_mutex);
+	up(&dc->sb_write_mutex);
 
 	if (dc->sb_disk)
 		put_page(virt_to_page(dc->sb_disk));
Signature · 1 line
2.53.0
author maintainer
#7 lore raw

PATCH 7/452 net: cpsw_new: Fix potential unregister of netdev that has not been registered yet

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Kevin Hao <[email protected]>

[ Upstream commit 9d724b34fbe13b71865ad0906a4be97571f19cf5 ]

If an error occurs during register_netdev() for the first MAC in cpsw_register_ports(), even though cpsw->slaves[0].ndev is set to NULL, cpsw->slaves[1].ndev would remain unchanged. This could later cause cpsw_unregister_ports() to attempt unregistering the second MAC. To address this, add a check for ndev->reg_state before calling unregister_netdev(). With this change, setting cpsw->slaves[i].ndev to NULL becomes unnecessary and can be removed accordingly.

Fixes ed3525eda4c4 ("net: ethernet: ti: introduce cpsw switchdev based driver part 1 - dual-emac")
---
 drivers/net/ethernet/ti/cpsw_new.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/ti/cpsw_new.c +2 -2
index 1f98044b3666ff..64f527ba9a4746 100644
@@ -1442,7 +1442,8 @@ static void cpsw_unregister_ports(struct cpsw_common *cpsw)
 	int i = 0;
 
 	for (i = 0; i < cpsw->data.slaves; i++) {
-		if (!cpsw->slaves[i].ndev)
+		if (!cpsw->slaves[i].ndev ||
+		    cpsw->slaves[i].ndev->reg_state != NETREG_REGISTERED)
 			continue;
 
 		unregister_netdev(cpsw->slaves[i].ndev);
@@ -1462,7 +1463,6 @@ static int cpsw_register_ports(struct cpsw_common *cpsw)
 		if (ret) {
 			dev_err(cpsw->dev,
 				"cpsw: err registering net device%d\n", i);
-			cpsw->slaves[i].ndev = NULL;
 			break;
 		}
 	}
Signature · 1 line
2.53.0
author maintainer
#8 lore raw

PATCH 8/452 nfc: llcp: Fix use-after-free in llcp_sock_release()

In reply to Greg Kroah-Hartman

6.6-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.

Fixes b4011239a08e ("NFC: llcp: Fix non blocking sockets connections")
---
 net/nfc/llcp_sock.c | 2 ++
 1 file changed, 2 insertions(+)
net/nfc/llcp_sock.c +2 -0
index d5344563e525c9..cd1fdf0beefb6b 100644
@@ -633,6 +633,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
author maintainer
#9 lore raw

PATCH 9/452 nfc: llcp: Fix use-after-free race in nfc_llcp_recv_cc()

In reply to Greg Kroah-Hartman

6.6-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
index d9562840fa180b..62b0f2d6686eb8 100644
@@ -1216,6 +1216,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);
@@ -1227,6 +1236,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
author maintainer
#10 lore raw

PATCH 10/452 xfrm: Check for underflow in xfrm_state_mtu

In reply to Greg Kroah-Hartman

6.6-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.

Fixes c5c252389374 ("[XFRM]: Optimize MTU calculation")
Assisted-by Codex:26.506.31004
---
 net/xfrm/xfrm_state.c | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)
net/xfrm/xfrm_state.c +16 -3
index 8ba31cf9b31993..6e8860779e2154 100644
@@ -2860,10 +2860,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);
@@ -2883,8 +2887,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
author maintainer
#11 lore raw

PATCH 11/452 nfc: nxp-nci: i2c: use rising-edge IRQ on ACPI systems

In reply to Greg Kroah-Hartman

6.6-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
index 5ecbf3366a1de4..e80ce1b97bccc9 100644
@@ -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>
@@ -267,6 +268,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)) {
@@ -303,9 +305,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
author maintainer
#12 lore raw

PATCH 12/452 netfilter: synproxy: refresh tcphdr after skb_ensure_writable

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 48b1de4c110a ("netfilter: add SYNPROXY core/target")
Assisted-by kres (claude-opus-4-7)
---
 net/netfilter/nf_synproxy_core.c | 2 ++
 1 file changed, 2 insertions(+)
net/netfilter/nf_synproxy_core.c +2 -0
index 16915f8eef2b16..f5a52075691faa 100644
@@ -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
author maintainer
#13 lore raw

PATCH 13/452 netfilter: xt_cpu: prefer raw_smp_processor_id

In reply to Greg Kroah-Hartman

6.6-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()").

Fixes 0ca743a55991 ("netfilter: nf_tables: add compatibility layer for x_tables")
Reported-by [email protected]
---
 net/netfilter/xt_cpu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/xt_cpu.c +1 -1
index 3bdc302a0f9137..9cb259902a586b 100644
@@ -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
author maintainer
#14 lore raw

PATCH 14/452 netfilter: ebtables: fix OOB read in compat_mtw_from_user

In reply to Greg Kroah-Hartman

6.6-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
index f99e348c8f37fa..bc69406d103df6 100644
@@ -1952,6 +1952,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,
@@ -1977,6 +1996,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)
@@ -1996,6 +2020,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
author maintainer
#15 lore raw

PATCH 15/452 netfilter: bitwise: rename some boolean operation functions

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jeremy Sowden <[email protected]>

[ Upstream commit a12143e6084c502fc3cfaa8b717bffc8c14cf806 ]

In the next patch we add support for doing AND, OR and XOR operations directly in the kernel, so rename some functions and an enum constant related to mask-and-xor boolean operations.

Stable-dep-of: 18014147d3ee ("netfilter: nf_tables: fix dst corruption in same register operation")

---
 include/uapi/linux/netfilter/nf_tables.h | 10 ++++---
 net/netfilter/nft_bitwise.c              | 34 ++++++++++++------------
 2 files changed, 24 insertions(+), 20 deletions(-)
include/uapi/linux/netfilter/nf_tables.h +7 -3
index 9c29015d09c10f..cbb1b58e181fca 100644
@@ -560,16 +560,20 @@ enum nft_immediate_attributes {
 /**
  * enum nft_bitwise_ops - nf_tables bitwise operations
  *
- * @NFT_BITWISE_BOOL: mask-and-xor operation used to implement NOT, AND, OR and
- *                    XOR boolean operations
+ * @NFT_BITWISE_MASK_XOR: mask-and-xor operation used to implement NOT, AND, OR
+ *                        and XOR boolean operations
  * @NFT_BITWISE_LSHIFT: left-shift operation
  * @NFT_BITWISE_RSHIFT: right-shift operation
  */
 enum nft_bitwise_ops {
-	NFT_BITWISE_BOOL,
+	NFT_BITWISE_MASK_XOR,
 	NFT_BITWISE_LSHIFT,
 	NFT_BITWISE_RSHIFT,
 };
+/*
+ * Old name for NFT_BITWISE_MASK_XOR.  Retained for backwards-compatibility.
+ */
+#define NFT_BITWISE_BOOL NFT_BITWISE_MASK_XOR
 
 /**
  * enum nft_bitwise_attributes - nf_tables bitwise expression netlink attributes
net/netfilter/nft_bitwise.c +17 -17
index 2cfb0104680c62..86abbe4c1308b3 100644
@@ -25,8 +25,8 @@ struct nft_bitwise {
 	struct nft_data		data;
 };
 
-static void nft_bitwise_eval_bool(u32 *dst, const u32 *src,
-				  const struct nft_bitwise *priv)
+static void nft_bitwise_eval_mask_xor(u32 *dst, const u32 *src,
+				      const struct nft_bitwise *priv)
 {
 	unsigned int i;
 
@@ -68,8 +68,8 @@ void nft_bitwise_eval(const struct nft_expr *expr,
 	u32 *dst = &regs->data[priv->dreg];
 
 	switch (priv->op) {
-	case NFT_BITWISE_BOOL:
-		nft_bitwise_eval_bool(dst, src, priv);
+	case NFT_BITWISE_MASK_XOR:
+		nft_bitwise_eval_mask_xor(dst, src, priv);
 		break;
 	case NFT_BITWISE_LSHIFT:
 		nft_bitwise_eval_lshift(dst, src, priv);
@@ -90,8 +90,8 @@ static const struct nla_policy nft_bitwise_policy[NFTA_BITWISE_MAX + 1] = {
 	[NFTA_BITWISE_DATA]	= { .type = NLA_NESTED },
 };
 
-static int nft_bitwise_init_bool(struct nft_bitwise *priv,
-				 const struct nlattr *const tb[])
+static int nft_bitwise_init_mask_xor(struct nft_bitwise *priv,
+				     const struct nlattr *const tb[])
 {
 	struct nft_data_desc mask = {
 		.type	= NFT_DATA_VALUE,
@@ -186,7 +186,7 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
 	if (tb[NFTA_BITWISE_OP]) {
 		priv->op = ntohl(nla_get_be32(tb[NFTA_BITWISE_OP]));
 		switch (priv->op) {
-		case NFT_BITWISE_BOOL:
+		case NFT_BITWISE_MASK_XOR:
 		case NFT_BITWISE_LSHIFT:
 		case NFT_BITWISE_RSHIFT:
 			break;
@@ -194,12 +194,12 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
 			return -EOPNOTSUPP;
 		}
 	} else {
-		priv->op = NFT_BITWISE_BOOL;
+		priv->op = NFT_BITWISE_MASK_XOR;
 	}
 
 	switch(priv->op) {
-	case NFT_BITWISE_BOOL:
-		err = nft_bitwise_init_bool(priv, tb);
+	case NFT_BITWISE_MASK_XOR:
+		err = nft_bitwise_init_mask_xor(priv, tb);
 		break;
 	case NFT_BITWISE_LSHIFT:
 	case NFT_BITWISE_RSHIFT:
@@ -210,8 +210,8 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
 	return err;
 }
 
-static int nft_bitwise_dump_bool(struct sk_buff *skb,
-				 const struct nft_bitwise *priv)
+static int nft_bitwise_dump_mask_xor(struct sk_buff *skb,
+				     const struct nft_bitwise *priv)
 {
 	if (nft_data_dump(skb, NFTA_BITWISE_MASK, &priv->mask,
 			  NFT_DATA_VALUE, priv->len) < 0)
@@ -249,8 +249,8 @@ static int nft_bitwise_dump(struct sk_buff *skb,
 		return -1;
 
 	switch (priv->op) {
-	case NFT_BITWISE_BOOL:
-		err = nft_bitwise_dump_bool(skb, priv);
+	case NFT_BITWISE_MASK_XOR:
+		err = nft_bitwise_dump_mask_xor(skb, priv);
 		break;
 	case NFT_BITWISE_LSHIFT:
 	case NFT_BITWISE_RSHIFT:
@@ -270,7 +270,7 @@ static int nft_bitwise_offload(struct nft_offload_ctx *ctx,
 	const struct nft_bitwise *priv = nft_expr_priv(expr);
 	struct nft_offload_reg *reg = &ctx->regs[priv->dreg];
 
-	if (priv->op != NFT_BITWISE_BOOL)
+	if (priv->op != NFT_BITWISE_MASK_XOR)
 		return -EOPNOTSUPP;
 
 	if (memcmp(&priv->xor, &zero, sizeof(priv->xor)) ||
@@ -407,7 +407,7 @@ nft_bitwise_fast_dump(struct sk_buff *skb,
 		return -1;
 	if (nla_put_be32(skb, NFTA_BITWISE_LEN, htonl(sizeof(u32))))
 		return -1;
-	if (nla_put_be32(skb, NFTA_BITWISE_OP, htonl(NFT_BITWISE_BOOL)))
+	if (nla_put_be32(skb, NFTA_BITWISE_OP, htonl(NFT_BITWISE_MASK_XOR)))
 		return -1;
 
 	data.data[0] = priv->mask;
@@ -502,7 +502,7 @@ nft_bitwise_select_ops(const struct nft_ctx *ctx,
 		return &nft_bitwise_ops;
 
 	if (tb[NFTA_BITWISE_OP] &&
-	    ntohl(nla_get_be32(tb[NFTA_BITWISE_OP])) != NFT_BITWISE_BOOL)
+	    ntohl(nla_get_be32(tb[NFTA_BITWISE_OP])) != NFT_BITWISE_MASK_XOR)
 		return &nft_bitwise_ops;
 
 	return &nft_bitwise_fast_ops;
Signature · 1 line
2.53.0
author maintainer
#16 lore raw

PATCH 16/452 netfilter: bitwise: add support for doing AND, OR and XOR directly

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jeremy Sowden <[email protected]>

[ Upstream commit b0ccf4f53d968e794a4ea579d5135cc1aaf1a53f ]

Hitherto, these operations have been converted in user space to mask-and-xor operations on one register and two immediate values, and it is the latter which have been evaluated by the kernel. We add support for evaluating these operations directly in kernel space on one register and either an immediate value or a second register.

Pablo made a few changes to the original patch:

- EINVAL if NFTA_BITWISE_SREG2 is used with fast version.
- Allow _AND,_OR,_XOR with _DATA != sizeof(u32)
- Dump _SREG2 or _DATA with _AND,_OR,_XOR

Stable-dep-of: 18014147d3ee ("netfilter: nf_tables: fix dst corruption in same register operation")

---
 include/uapi/linux/netfilter/nf_tables.h |   8 ++
 net/netfilter/nft_bitwise.c              | 134 +++++++++++++++++++++--
 2 files changed, 131 insertions(+), 11 deletions(-)
include/uapi/linux/netfilter/nf_tables.h +8 -0
index cbb1b58e181fca..f8867f198f3104 100644
@@ -564,11 +564,17 @@ enum nft_immediate_attributes {
  *                        and XOR boolean operations
  * @NFT_BITWISE_LSHIFT: left-shift operation
  * @NFT_BITWISE_RSHIFT: right-shift operation
+ * @NFT_BITWISE_AND: and operation
+ * @NFT_BITWISE_OR: or operation
+ * @NFT_BITWISE_XOR: xor operation
  */
 enum nft_bitwise_ops {
 	NFT_BITWISE_MASK_XOR,
 	NFT_BITWISE_LSHIFT,
 	NFT_BITWISE_RSHIFT,
+	NFT_BITWISE_AND,
+	NFT_BITWISE_OR,
+	NFT_BITWISE_XOR,
 };
 /*
  * Old name for NFT_BITWISE_MASK_XOR.  Retained for backwards-compatibility.
@@ -586,6 +592,7 @@ enum nft_bitwise_ops {
  * @NFTA_BITWISE_OP: type of operation (NLA_U32: nft_bitwise_ops)
  * @NFTA_BITWISE_DATA: argument for non-boolean operations
  *                     (NLA_NESTED: nft_data_attributes)
+ * @NFTA_BITWISE_SREG2: second source register (NLA_U32: nft_registers)
  *
  * The bitwise expression supports boolean and shift operations.  It implements
  * the boolean operations by performing the following operation:
@@ -609,6 +616,7 @@ enum nft_bitwise_attributes {
 	NFTA_BITWISE_XOR,
 	NFTA_BITWISE_OP,
 	NFTA_BITWISE_DATA,
+	NFTA_BITWISE_SREG2,
 	__NFTA_BITWISE_MAX
 };
 #define NFTA_BITWISE_MAX	(__NFTA_BITWISE_MAX - 1)
net/netfilter/nft_bitwise.c +123 -11

214 lines not on this page · raw message

Signature · 1 line
2.53.0
author maintainer
#17 lore raw

PATCH 17/452 netfilter: nf_tables: fix dst corruption in same register operation

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Fernando Fernandez Mancera <[email protected]>

[ Upstream commit 18014147d3ee7831dce53fe65d7fc8d428b02552 ]

For lshift and rshift, the shift operations are performed in a loop over 32-bit words. The loop calculates the shifted value and write it to dst, and then immediately reads from src to calculate the carry for the next iteration. Because src and dst could point to the same memory location, the carry is incorrectly calculated using the newly modified dst value instead of the original src value.

Adding a temporary local variable to cache the original value before writing to dst and using it for the carry calculation solves the problem. In addition, partial overlap is rejected from control plane for all kind of operations including byteorder. This was tested with the following bytecode:

table test_table ip flags 0 use 1 handle 1
ip test_table test_chain use 3 type filter hook input prio 0 policy accept packets 0 bytes 0 flags 1 ip test_table test_chain 2
[ immediate reg 1 0x44332211 0x88776655 ]
[ bitwise reg 1 = ( reg 1 << 0x08000000 ) ]
[ cmp eq reg 1 0x66443322 0x00887766 ]
[ counter pkts 0 bytes 0 ]
ip test_table test_chain 4 3
[ immediate reg 1 0x44332211 0x88776655 ]
[ bitwise reg 1 = ( reg 1 << 0x08000000 ) ]
[ cmp eq reg 1 0x55443322 0x00887766 ]
[ counter pkts 21794 bytes 1917798 ]

Fixes 567d746b55bc ("netfilter: bitwise: add support for shifts.")
---
 include/net/netfilter/nf_tables.h |  7 +++++++
 net/netfilter/nft_bitwise.c       | 18 ++++++++++++++----
 net/netfilter/nft_byteorder.c     | 13 ++++++++++---
 3 files changed, 31 insertions(+), 7 deletions(-)
include/net/netfilter/nf_tables.h +7 -0
index ab0567951e3105..a1f828efc9e3de 100644
@@ -188,6 +188,13 @@ static inline u64 nft_reg_load64(const u32 *sreg)
 	return get_unaligned((u64 *)sreg);
 }
 
+static inline bool nft_reg_overlap(u8 src, u8 dst, u32 len)
+{
+	unsigned int n = DIV_ROUND_UP(len, sizeof(u32));
+
+	return src != dst && src < dst + n && dst < src + n;
+}
+
 static inline void nft_data_copy(u32 *dst, const struct nft_data *src,
 				 unsigned int len)
 {
net/netfilter/nft_bitwise.c +14 -4
index af990c600745be..1afb36fb5994db 100644
@@ -43,8 +43,10 @@ static void nft_bitwise_eval_lshift(u32 *dst, const u32 *src,
 	u32 carry = 0;
 
 	for (i = DIV_ROUND_UP(priv->len, sizeof(u32)); i > 0; i--) {
-		dst[i - 1] = (src[i - 1] << shift) | carry;
-		carry = src[i - 1] >> (BITS_PER_TYPE(u32) - shift);
+		u32 tmp_src = src[i - 1];
+
+		dst[i - 1] = (tmp_src << shift) | carry;
+		carry = tmp_src >> (BITS_PER_TYPE(u32) - shift);
 	}
 }
 
@@ -56,8 +58,10 @@ static void nft_bitwise_eval_rshift(u32 *dst, const u32 *src,
 	u32 carry = 0;
 
 	for (i = 0; i < DIV_ROUND_UP(priv->len, sizeof(u32)); i++) {
-		dst[i] = carry | (src[i] >> shift);
-		carry = src[i] << (BITS_PER_TYPE(u32) - shift);
+		u32 tmp_src = src[i];
+
+		dst[i] = carry | (tmp_src >> shift);
+		carry = tmp_src << (BITS_PER_TYPE(u32) - shift);
 	}
 }
 
@@ -235,6 +239,9 @@ static int nft_bitwise_init_bool(const struct nft_ctx *ctx,
 					      &priv->sreg2, priv->len);
 		if (err < 0)
 			return err;
+
+		if (nft_reg_overlap(priv->sreg2, priv->dreg, priv->len))
+			return -EINVAL;
 	}
 
 	return 0;
@@ -265,6 +272,9 @@ static int nft_bitwise_init(const struct nft_ctx *ctx,
 	if (err < 0)
 		return err;
 
+	if (nft_reg_overlap(priv->sreg, priv->dreg, priv->len))
+		return -EINVAL;
+
 	if (tb[NFTA_BITWISE_OP]) {
 		priv->op = ntohl(nla_get_be32(tb[NFTA_BITWISE_OP]));
 		switch (priv->op) {
net/netfilter/nft_byteorder.c +10 -3
index 2f82a444d21bf3..51f5de5c4ca363 100644
@@ -144,9 +144,16 @@ static int nft_byteorder_init(const struct nft_ctx *ctx,
 	if (err < 0)
 		return err;
 
-	return nft_parse_register_store(ctx, tb[NFTA_BYTEORDER_DREG],
-					&priv->dreg, NULL, NFT_DATA_VALUE,
-					priv->len);
+	err = nft_parse_register_store(ctx, tb[NFTA_BYTEORDER_DREG],
+				       &priv->dreg, NULL, NFT_DATA_VALUE,
+				       priv->len);
+	if (err < 0)
+		return err;
+
+	if (nft_reg_overlap(priv->sreg, priv->dreg, priv->len))
+		return -EINVAL;
+
+	return 0;
 }
 
 static int nft_byteorder_dump(struct sk_buff *skb,
Signature · 1 line
2.53.0
author maintainer
#18 lore raw

PATCH 18/452 tun: free page on short-frame rejection in tun_xdp_one()

In reply to Greg Kroah-Hartman

6.6-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
index 97dbec8d78077d..88b704b5d0b26e 100644
@@ -2459,8 +2459,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
author maintainer
#19 lore raw

PATCH 19/452 tun: free page on build_skb failure in tun_xdp_one()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Weiming Shi <[email protected]>

[ Upstream commit aa8963fdce667a42fb7f0bdd2909fadcab02f9a8 ]

When build_skb() fails in tun_xdp_one(), the function sets ret to -ENOMEM and jumps to the out label, which returns without freeing the page that vhost_net_build_xdp() allocated for the frame. As with the short-frame rejection path, tun_sendmsg() discards the per-buffer error and still returns total_len, so vhost_tx_batch() takes the success path and never frees the page. Each build_skb() failure in a batch leaks one page-frag chunk.

Free the page before taking the error path, matching the put_page() the other error exits of tun_xdp_one() already perform.

---
 drivers/net/tun.c | 1 +
 1 file changed, 1 insertion(+)
drivers/net/tun.c +1 -0
index 88b704b5d0b26e..9a4192d6a4cabf 100644
@@ -2505,6 +2505,7 @@ static int tun_xdp_one(struct tun_struct *tun,
 build:
 	skb = build_skb(xdp->data_hard_start, buflen);
 	if (!skb) {
+		put_page(virt_to_head_page(xdp->data));
 		ret = -ENOMEM;
 		goto out;
 	}
Signature · 1 line
2.53.0
author maintainer
#20 lore raw

PATCH 20/452 vsock: keep poll shutdown state consistent

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Ziyu Zhang <[email protected]>

[ Upstream commit aae9d8a5528b8ee9ff8dc5d3558b8a9f852a724a ]

vsock_poll() reads vsk->peer_shutdown before taking the socket lock to set EPOLLHUP and EPOLLRDHUP, then reads it again after taking the lock to report EOF readability. A shutdown packet can update peer_shutdown while poll is waiting for the lock, so one poll invocation can report EOF readability without the corresponding HUP/RDHUP bits.

For connectible sockets, take one peer_shutdown snapshot after lock_sock() and use it for all peer-shutdown-derived poll bits. For datagram sockets, which do not take lock_sock() in poll(), take one lockless READ_ONCE() snapshot and pair it with WRITE_ONCE() on the writer side.

This keeps the peer-shutdown-derived bits internally consistent for each poll pass.

---
 net/vmw_vsock/af_vsock.c                | 49 ++++++++++++++++---------
 net/vmw_vsock/hyperv_transport.c        |  9 +++--
 net/vmw_vsock/virtio_transport_common.c | 14 ++++---
 net/vmw_vsock/vmci_transport.c          |  8 ++--
 4 files changed, 52 insertions(+), 28 deletions(-)
net/vmw_vsock/af_vsock.c +32 -17
index 187cc259f820b5..a06f708f300c4a 100644
@@ -522,7 +522,7 @@ int vsock_assign_transport(struct vsock_sock *vsk, struct vsock_sock *psk)
 		 */
 		sock_reset_flag(sk, SOCK_DONE);
 		sk->sk_state = TCP_CLOSE;
-		vsk->peer_shutdown = 0;
+		WRITE_ONCE(vsk->peer_shutdown, 0);
 	}
 
 	if (sk->sk_type == SOCK_SEQPACKET) {
@@ -813,7 +813,7 @@ static struct sock *__vsock_create(struct net *net,
 	vsk->rejected = false;
 	vsk->sent_request = false;
 	vsk->ignore_connecting_rst = false;
-	vsk->peer_shutdown = 0;
+	WRITE_ONCE(vsk->peer_shutdown, 0);
 	INIT_DELAYED_WORK(&vsk->connect_work, vsock_connect_timeout);
 	INIT_DELAYED_WORK(&vsk->pending_work, vsock_pending_work);
 
@@ -1095,6 +1095,25 @@ static int vsock_shutdown(struct socket *sock, int mode)
 	return err;
 }
 
+static __poll_t vsock_poll_shutdown(struct sock *sk, u32 peer_shutdown)
+{
+	__poll_t mask = 0;
+
+	/* INET sockets treat local write shutdown and peer write shutdown as a
+	 * case of EPOLLHUP set.
+	 */
+	if (sk->sk_shutdown == SHUTDOWN_MASK ||
+	    ((sk->sk_shutdown & SEND_SHUTDOWN) &&
+	     (peer_shutdown & SEND_SHUTDOWN)))
+		mask |= EPOLLHUP;
+
+	if (sk->sk_shutdown & RCV_SHUTDOWN ||
+	    peer_shutdown & SEND_SHUTDOWN)
+		mask |= EPOLLRDHUP;
+
+	return mask;
+}
+
 static __poll_t vsock_poll(struct file *file, struct socket *sock,
 			       poll_table *wait)
 {
@@ -1112,24 +1131,17 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
 		/* Signify that there has been an error on this socket. */
 		mask |= EPOLLERR;
 
-	/* INET sockets treat local write shutdown and peer write shutdown as a
-	 * case of EPOLLHUP set.
-	 */
-	if ((sk->sk_shutdown == SHUTDOWN_MASK) ||
-	    ((sk->sk_shutdown & SEND_SHUTDOWN) &&
-	     (vsk->peer_shutdown & SEND_SHUTDOWN))) {
-		mask |= EPOLLHUP;
-	}
-
-	if (sk->sk_shutdown & RCV_SHUTDOWN ||
-	    vsk->peer_shutdown & SEND_SHUTDOWN) {
-		mask |= EPOLLRDHUP;
-	}
-
 	if (sk_is_readable(sk))
 		mask |= EPOLLIN | EPOLLRDNORM;
 
 	if (sock->type == SOCK_DGRAM) {
+		u32 peer_shutdown = READ_ONCE(vsk->peer_shutdown);
+
+		/* DGRAM sockets do not take lock_sock() in poll(), so use one
+		 * lockless snapshot for all shutdown-derived mask bits.
+		 */
+		mask |= vsock_poll_shutdown(sk, peer_shutdown);
+
 		/* For datagram sockets we can read if there is something in
 		 * the queue and write as long as the socket isn't shutdown for
 		 * sending.
@@ -1144,6 +1156,7 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
 
 	} else if (sock_type_connectible(sk->sk_type)) {
 		const struct vsock_transport *transport;
+		u32 peer_shutdown;
 
 		lock_sock(sk);
 
@@ -1176,8 +1189,10 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
 		 * terminated should also be considered read, and we check the
 		 * shutdown flag for that.
 		 */
+		peer_shutdown = READ_ONCE(vsk->peer_shutdown);
+		mask |= vsock_poll_shutdown(sk, peer_shutdown);
 		if (sk->sk_shutdown & RCV_SHUTDOWN ||
-		    vsk->peer_shutdown & SEND_SHUTDOWN) {
+		    peer_shutdown & SEND_SHUTDOWN) {
 			mask |= EPOLLIN | EPOLLRDNORM;
 		}
 
net/vmw_vsock/hyperv_transport.c +6 -3
index 34871ed1a099c6..865e004ee286f2 100644
@@ -264,7 +264,7 @@ static void hvs_do_close_lock_held(struct vsock_sock *vsk,
 	struct sock *sk = sk_vsock(vsk);
 
 	sock_set_flag(sk, SOCK_DONE);
-	vsk->peer_shutdown = SHUTDOWN_MASK;
+	WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
 	if (vsock_stream_has_data(vsk) <= 0)
 		sk->sk_state = TCP_CLOSING;
 	sk->sk_state_change(sk);
@@ -593,7 +593,9 @@ static int hvs_update_recv_data(struct hvsock *hvs)
 		return -EIO;
 
 	if (payload_len == 0)
-		hvs->vsk->peer_shutdown |= SEND_SHUTDOWN;
+		WRITE_ONCE(hvs->vsk->peer_shutdown,
+			   READ_ONCE(hvs->vsk->peer_shutdown) |
+			   SEND_SHUTDOWN);
 
 	hvs->recv_data_len = payload_len;
 	hvs->recv_data_off = 0;
@@ -704,7 +706,8 @@ static s64 hvs_stream_has_data(struct vsock_sock *vsk)
 		ret = 1;
 		break;
 	case 0:
-		vsk->peer_shutdown |= SEND_SHUTDOWN;
+		WRITE_ONCE(vsk->peer_shutdown,
+			   READ_ONCE(vsk->peer_shutdown) | SEND_SHUTDOWN);
 		ret = 0;
 		break;
 	default: /* -1 */
net/vmw_vsock/virtio_transport_common.c +9 -5
index d4ff9506eaf6d5..16431ef52799db 100644
@@ -1043,7 +1043,7 @@ static void virtio_transport_do_close(struct vsock_sock *vsk,
 	struct sock *sk = sk_vsock(vsk);
 
 	sock_set_flag(sk, SOCK_DONE);
-	vsk->peer_shutdown = SHUTDOWN_MASK;
+	WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
 	if (vsock_stream_has_data(vsk) <= 0)
 		sk->sk_state = TCP_CLOSING;
 	sk->sk_state_change(sk);
@@ -1244,12 +1244,15 @@ virtio_transport_recv_connected(struct sock *sk,
 	case VIRTIO_VSOCK_OP_CREDIT_UPDATE:
 		sk->sk_write_space(sk);
 		break;
-	case VIRTIO_VSOCK_OP_SHUTDOWN:
+	case VIRTIO_VSOCK_OP_SHUTDOWN: {
+		u32 peer_shutdown = READ_ONCE(vsk->peer_shutdown);
+
 		if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SHUTDOWN_RCV)
-			vsk->peer_shutdown |= RCV_SHUTDOWN;
+			peer_shutdown |= RCV_SHUTDOWN;
 		if (le32_to_cpu(hdr->flags) & VIRTIO_VSOCK_SHUTDOWN_SEND)
-			vsk->peer_shutdown |= SEND_SHUTDOWN;
-		if (vsk->peer_shutdown == SHUTDOWN_MASK) {
+			peer_shutdown |= SEND_SHUTDOWN;
+		WRITE_ONCE(vsk->peer_shutdown, peer_shutdown);
+		if (peer_shutdown == SHUTDOWN_MASK) {
 			if (vsock_stream_has_data(vsk) <= 0 && !sock_flag(sk, SOCK_DONE)) {
 				(void)virtio_transport_reset(vsk, NULL);
 				virtio_transport_do_close(vsk, true);
@@ -1264,6 +1267,7 @@ virtio_transport_recv_connected(struct sock *sk,
 		if (le32_to_cpu(virtio_vsock_hdr(skb)->flags))
 			sk->sk_state_change(sk);
 		break;
+	}
 	case VIRTIO_VSOCK_OP_RST:
 		virtio_transport_do_close(vsk, true);
 		break;
net/vmw_vsock/vmci_transport.c +5 -3
index 4cd11f355e9d6b..443125e48f2481 100644
@@ -811,7 +811,7 @@ static void vmci_transport_handle_detach(struct sock *sk)
 		/* On a detach the peer will not be sending or receiving
 		 * anymore.
 		 */
-		vsk->peer_shutdown = SHUTDOWN_MASK;
+		WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
 
 		/* We should not be sending anymore since the peer won't be
 		 * there to receive, but we can still receive if there is data
@@ -1534,7 +1534,9 @@ static int vmci_transport_recv_connected(struct sock *sk,
 		if (pkt->u.mode) {
 			vsk = vsock_sk(sk);
 
-			vsk->peer_shutdown |= pkt->u.mode;
+			WRITE_ONCE(vsk->peer_shutdown,
+				   READ_ONCE(vsk->peer_shutdown) |
+				   pkt->u.mode);
 			sk->sk_state_change(sk);
 		}
 		break;
@@ -1551,7 +1553,7 @@ static int vmci_transport_recv_connected(struct sock *sk,
 		 * a clean shutdown.
 		 */
 		sock_set_flag(sk, SOCK_DONE);
-		vsk->peer_shutdown = SHUTDOWN_MASK;
+		WRITE_ONCE(vsk->peer_shutdown, SHUTDOWN_MASK);
 		if (vsock_stream_has_data(vsk) <= 0)
 			sk->sk_state = TCP_CLOSING;
 
Signature · 1 line
2.53.0
author maintainer
#21 lore raw

PATCH 21/452 net: netlink: fix sending unassigned nsid after assigned one

In reply to Greg Kroah-Hartman

6.6-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
index a5ffda87daf63b..f8d9a04d5d8b11 100644
@@ -1484,6 +1484,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
author maintainer
#22 lore raw

PATCH 22/452 net: netlink: dont set nsid on local notifications

In reply to Greg Kroah-Hartman

6.6-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
index f8d9a04d5d8b11..f3a8c8338d203f 100644
@@ -1484,10 +1484,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
author maintainer
#23 lore raw

PATCH 23/452 net/smc: Do not re-initialize smc hashtables

In reply to Greg Kroah-Hartman

6.6-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
index 6629fd61be06a6..7a82e1a8a83f4b 100644
@@ -181,10 +181,12 @@ static bool smc_hs_congested(const struct sock *sk)
 
 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)
@@ -3579,8 +3581,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
author maintainer
#24 lore raw

PATCH 24/452 net/iucv: fix locking in .getsockopt

In reply to Greg Kroah-Hartman

6.6-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
index 0f660b1d3bd51c..e9a9bb0dee065a 100644
@@ -1539,7 +1539,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;
@@ -1552,26 +1552,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
author maintainer
#25 lore raw

PATCH 25/452 scsi: core: Run queues for all non-SDEV_DEL devices from scsi_run_host_queues

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: David Jeffery <[email protected]>

[ Upstream commit 7205b58702273baf21d6ba7992e6ba15852325f7 ]

While a SCSI host is in a recovery state, scsi_mq_requeue_cmd() will not set the requeue list for a requeued command to be kicked in the future. The expectation is a call to scsi_run_host_queues() will kick all SCSI devices once the recovery state is cleared.

However, scsi_run_host_queues() uses shost_for_each_device() which uses scsi_device_get() and so will ignore devices in a partially removed state like SDEV_CANCEL. But these devices may also have requeued requests, leaving their requests stuck from not being kicked and causing the removal process of the device to hang.

scsi_run_host_queues() needs to run against more devices than the macro shost_for_each_device() allows. Instead of using the too limiting scsi_device_get() state checks, only ignore devices in SDEV_DEL state or when unable to acquire a reference. Attempt to run the queues for all other devices when scsi_run_host_queues() is called.

Fixes 8b566edbdbfb ("scsi: core: Only kick the requeue list if necessary")
---
 drivers/scsi/scsi_lib.c | 27 +++++++++++++++++++++++++--
 1 file changed, 25 insertions(+), 2 deletions(-)
drivers/scsi/scsi_lib.c +25 -2
index efd1f1d6e4e9b0..2268e540f28ae6 100644
@@ -474,10 +474,33 @@ void scsi_requeue_run_queue(struct work_struct *work)
 
 void scsi_run_host_queues(struct Scsi_Host *shost)
 {
-	struct scsi_device *sdev;
+	struct scsi_device *sdev, *prev = NULL;
+	unsigned long flags;
 
-	shost_for_each_device(sdev, shost)
+	spin_lock_irqsave(shost->host_lock, flags);
+	__shost_for_each_device(sdev, shost) {
+		/*
+		 * Only skip devices so deep into removal they will never need
+		 * another kick to their queues. Thus scsi_device_get() cannot
+		 * be used as it would skip devices in SDEV_CANCEL state which
+		 * may need a queue kick.
+		 */
+		if (sdev->sdev_state == SDEV_DEL ||
+		    !get_device(&sdev->sdev_gendev))
+			continue;
+		spin_unlock_irqrestore(shost->host_lock, flags);
+
+		if (prev)
+			put_device(&prev->sdev_gendev);
 		scsi_run_queue(sdev->request_queue);
+
+		prev = sdev;
+
+		spin_lock_irqsave(shost->host_lock, flags);
+	}
+	spin_unlock_irqrestore(shost->host_lock, flags);
+	if (prev)
+		put_device(&prev->sdev_gendev);
 }
 
 static void scsi_uninit_cmd(struct scsi_cmnd *cmd)
Signature · 1 line
2.53.0
author maintainer
#26 lore raw

PATCH 26/452 ipv4: free net->ipv4.sysctl_local_reserved_ports after unregister_net_sysctl_table()

In reply to Greg Kroah-Hartman

6.6-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
index 96f1b8d39fac11..9c827751dad6a7 100644
@@ -1560,10 +1560,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
author maintainer
#27 lore raw

PATCH 27/452 ASoC: Intel: bytcht_es8316: Fix MCLK leak on init errors

In reply to Greg Kroah-Hartman

6.6-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
index fbd7e1f0783fd9..d334d748f76fb0 100644
@@ -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_pins(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,
@@ -355,6 +379,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
author maintainer
#28 lore raw

PATCH 28/452 net: hsr: fix potential OOB access in supervision frame handling

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Luka Gejak <[email protected]>

[ Upstream commit f229426072fc865654a60978bb7fda790a051ff3 ]

Ensure the entire TLV header is linearized before access by adding sizeof(struct hsr_sup_tlv) to the pskb_may_pull() calls. Without this, a truncated frame could cause an out-of-bounds access.

Fixes eafaa88b3eb7 ("net: hsr: Add support for redbox supervision frames")
---
 net/hsr/hsr_forward.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
net/hsr/hsr_forward.c +2 -2
index 3852fd99509f04..7a596c4f603e2d 100644
@@ -84,7 +84,7 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
 
 	/* Get next tlv */
 	total_length += hsr_sup_tag->tlv.HSR_TLV_length;
-	if (!pskb_may_pull(skb, total_length))
+	if (!pskb_may_pull(skb, total_length + sizeof(struct hsr_sup_tlv)))
 		return false;
 	skb_pull(skb, total_length);
 	hsr_sup_tlv = (struct hsr_sup_tlv *)skb->data;
@@ -100,7 +100,7 @@ static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb)
 
 		/* make sure another tlv follows */
 		total_length += sizeof(struct hsr_sup_tlv) + hsr_sup_tlv->HSR_TLV_length;
-		if (!pskb_may_pull(skb, total_length))
+		if (!pskb_may_pull(skb, total_length + sizeof(struct hsr_sup_tlv)))
 			return false;
 
 		/* get next tlv */
Signature · 1 line
2.53.0
author maintainer
#29 lore raw

PATCH 29/452 gpio: mxc: fix irq_high handling

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Alexander Stein <[email protected]>

[ Upstream commit dac917ed5aead741004db8d0d5151dd577802df8 ]

If port->irq_high is -1 (fsl,imx21-gpio compatible) and gpio_idx is >= 16 enable_irq_wake() is called with -1 which is wrong.

Fixes 5f6d1998adeb ("gpio: mxc: release the parent IRQ in runtime suspend")
---
 drivers/gpio/gpio-mxc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpio/gpio-mxc.c +1 -1
index 3cdc2b218a86af..a8ab78ae7fa30c 100644
@@ -473,7 +473,7 @@ static int mxc_gpio_probe(struct platform_device *pdev)
 		 * the handler is needed only once, but doing it for every port
 		 * is more robust and easier.
 		 */
-		port->irq_high = -1;
+		port->irq_high = 0;
 		port->mx_irq_handler = mx2_gpio_irq_handler;
 	} else
 		port->mx_irq_handler = mx3_gpio_irq_handler;
Signature · 1 line
2.53.0
author maintainer
#30 lore raw

PATCH 30/452 tunnels: load network headers after skb_cow() in iptunnel_pmtud_build_icmp[v6]()

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
---
 net/ipv4/ip_tunnel_core.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)
net/ipv4/ip_tunnel_core.c +4 -5
index 75e3d7501752df..5fb437f040ace7 100644
@@ -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
author maintainer
#31 lore raw

PATCH 31/452 vxlan: do not reuse cached ip_hdr() value after skb_tunnel_check_pmtu()

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
---
 drivers/net/vxlan/vxlan_core.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/vxlan/vxlan_core.c +2 -2
index 1a973dcf256127..958d3be4f99086 100644
@@ -2607,7 +2607,7 @@ 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);
@@ -2670,7 +2670,7 @@ 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
author maintainer
#32 lore raw

PATCH 32/452 tunnels: do not assume transport header in iptunnel_pmtud_check_icmp()

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 4cb47a8644cc ("tunnels: PMTU discovery support for directly bridged IP packets")
---
 net/ipv4/ip_tunnel_core.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)
net/ipv4/ip_tunnel_core.c +10 -3
index 5fb437f040ace7..9f6f1b435d8d72 100644
@@ -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
author maintainer
#33 lore raw

PATCH 33/452 ksmbd: fix FSCTL permission bypass by adding a permission check for FSCTL_SET_SPARSE

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sean Shen <[email protected]>

[ Upstream commit cc57232cae23c0df91b4a59d0f519141ce9b5b02 ]

FSCTL_SET_SPARSE in fsctl_set_sparse() modifies the file's sparse attribute and saves it through xattr without any permission checks.

This exposes two issues:

1) A client on a read-only share can change the sparse attribute on files it opened, even though the share is read-only. Other FSCTL write operations already check test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE), but FSCTL_SET_SPARSE does not.

2) Even on writable shares, clients without FILE_WRITE_DATA or FILE_WRITE_ATTRIBUTES access should not modify the sparse attribute. Similar handle-level checks exist in other functions but are missing here.

Add both share-level writable check and per-handle access check. Use goto out on error to avoid leaking file references.

Fixes e2f34481b24d ("cifsd: add server-side procedures for SMB3")
Cc Namjae Jeon <[email protected]>
Cc Sergey Senozhatsky <[email protected]>
Cc Steve French <[email protected]>
---
 fs/smb/server/smb2pdu.c | 11 +++++++++++
 1 file changed, 11 insertions(+)
fs/smb/server/smb2pdu.c +11 -0
index 04d4a784deaf98..97b03f76741ef2 100644
@@ -8067,9 +8067,20 @@ static inline int fsctl_set_sparse(struct ksmbd_work *work, u64 id,
 	int ret = 0;
 	__le32 old_fattr;
 
+	if (!test_tree_conn_flag(work->tcon, KSMBD_TREE_CONN_FLAG_WRITABLE)) {
+		ksmbd_debug(SMB, "User does not have write permission\n");
+		return -EACCES;
+	}
+
 	fp = ksmbd_lookup_fd_fast(work, id);
 	if (!fp)
 		return -ENOENT;
+
+	if (!(fp->daccess & (FILE_WRITE_DATA_LE | FILE_WRITE_ATTRIBUTES_LE))) {
+		ret = -EACCES;
+		goto out;
+	}
+
 	idmap = file_mnt_idmap(fp->filp);
 
 	old_fattr = fp->f_ci->m_fattr;
Signature · 1 line
2.53.0
author maintainer
#34 lore raw

PATCH 34/452 ASoC: codecs: simple-mux: Fix enum control bounds check

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Cássio Gabriel <[email protected]>

[ Upstream commit f63ad68e18d774a5d15cd7e405ead63f6b322679 ]

simple_mux_control_put() rejects values greater than e->items, but enum control values are zero based. For the two-entry mux used by this driver, valid values are 0 and 1, so value 2 must be rejected as well.

Accepting e->items can store an invalid mux state, pass it to the GPIO setter, and pass it on to the DAPM mux update path where it is used as an index into the enum text array.

Use the same >= e->items check used by the ASoC enum helpers.

---
 sound/soc/codecs/simple-mux.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/codecs/simple-mux.c +1 -1
index bf67de12d20b7f..02ccaa4c9a0804 100644
@@ -40,7 +40,7 @@ static int simple_mux_control_put(struct snd_kcontrol *kcontrol,
 	struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
 	struct simple_mux *priv = snd_soc_component_get_drvdata(c);
 
-	if (ucontrol->value.enumerated.item[0] > e->items)
+	if (ucontrol->value.enumerated.item[0] >= e->items)
 		return -EINVAL;
 
 	if (priv->mux == ucontrol->value.enumerated.item[0])
Signature · 1 line
2.53.0
author maintainer
#35 lore raw

PATCH 35/452 Bluetooth: 6lowpan: check skb_clone() return value in send_mcast_pkt()

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 18722c247023 ("Bluetooth: Enable 6LoWPAN support for BT LE devices")
---
 net/bluetooth/6lowpan.c | 2 ++
 1 file changed, 2 insertions(+)
net/bluetooth/6lowpan.c +2 -0
index e65d4754c94f4c..b3132079573d4d 100644
@@ -485,6 +485,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 %u IP %pI6c chan %p",
 			       netdev->name,
Signature · 1 line
2.53.0
author maintainer
#36 lore raw

PATCH 36/452 bonding: refuse to enslave CAN devices

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Oliver Hartkopp <[email protected]>

[ Upstream commit 8ba68464e4787b6a7ec938826e16124df20fd23d ]

syzbot reported a kernel paging request crash in can_rx_unregister() inside net/can/af_can.c. The crash occurs because a virtual CAN device (vxcan) is being enslaved to a bonding master.

During the enslavement process, the bonding driver mutates and modifies the network device states to fit an Ethernet-like aggregation model. However, CAN devices operate on a completely different Layer 2 architecture, relying on the CAN mid-layer private data structure (can_ml_priv) instead of standard Ethernet structures. Since bonding does not initialize or maintain these CAN structures, subsequent operations on the half-enslaved interface (such as closing associated sockets via isotp_release) lead to a null-pointer dereference when accessing the CAN receiver lists.

Bonding CAN interfaces is architecturally invalid as CAN lacks MAC addresses, ARP capabilities, and standard Ethernet link-layer mechanisms. While generic loopback devices are blocked globally in net/core/dev.c, virtual CAN devices bypass this check because they do not carry the IFF_LOOPBACK flag, despite acting as local software-loopbacks.

Fix this by explicitly blocking network devices of type ARPHRD_CAN from being enslaved at the very beginning of bond_enslave(). This prevents illegal state mutations, eliminates the resulting KASAN crashes, and avoids potential memory leaks from incomplete socket cleanups.

As the CAN support has been added a long time after bonding the Fixes-tag points to the introduction of ARPHRD_CAN that would have needed a specific handling in bonding_main.c.

---
 drivers/net/bonding/bond_main.c | 6 ++++++
 1 file changed, 6 insertions(+)
drivers/net/bonding/bond_main.c +6 -0
index 029a7f001dd8a0..7732f7023033ed 100644
@@ -1889,6 +1889,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev,
 	int link_reporting;
 	int res = 0, i;
 
+	if (slave_dev->type == ARPHRD_CAN) {
+		BOND_NL_ERR(bond_dev, extack,
+			    "CAN devices cannot be enslaved");
+		return -EPERM;
+	}
+
 	if (slave_dev->flags & IFF_MASTER &&
 	    !netif_is_bond_master(slave_dev)) {
 		BOND_NL_ERR(bond_dev, extack,
Signature · 1 line
2.53.0
author maintainer
#37 lore raw

PATCH 37/452 ethtool: eeprom: add missing ethnl_ops_begin() / _complete() during fallback

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jakub Kicinski <[email protected]>

[ Upstream commit 2376586f85f972fefe701f095bb37dcfe7405d21 ]

All ethtool driver op calls should be sandwiched between ethnl_ops_begin() / ethnl_ops_complete(). In Netlink eeprom code, if the paged access failed we fall back to old API, but we first call _complete() and the fallback never does its own ethnl_ops_begin(). Move the fallback into the _begin() / _complete() section.

Fixes 96d971e307cc ("ethtool: Add fallback to get_module_eeprom from netlink command")
---
 net/ethtool/eeprom.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
net/ethtool/eeprom.c +2 -3
index 6209c3a9c8f723..15546f2a5e4583 100644
@@ -134,12 +134,11 @@ static int eeprom_prepare_data(const struct ethnl_req_info *req_base,
 	return 0;
 
 err_ops:
+	if (ret == -EOPNOTSUPP)
+		ret = eeprom_fallback(request, reply);
 	ethnl_ops_complete(dev);
 err_free:
 	kfree(page_data.data);
-
-	if (ret == -EOPNOTSUPP)
-		return eeprom_fallback(request, reply);
 	return ret;
 }
 
Signature · 1 line
2.53.0
author maintainer
#38 lore raw

PATCH 38/452 ethtool: eeprom: add more safeties to EEPROM Netlink fallback

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jakub Kicinski <[email protected]>

[ Upstream commit 67cfdd9210b99f260b3e0afeb9525e0acc7be31e ]

The Netlink fallback path for reading module EEPROM (fallback_set_params()) validates that offset < eeprom_len, but does not check that offset + length stays within eeprom_len. The ioctl equivalent (ethtool_get_any_eeprom() in ioctl.c) has always enforced both bounds:

if (eeprom.offset + eeprom.len > total_len)

      return -EINVAL;

This could lead to surprises in both drivers and device FW. Add the missing offset + length validation to fallback_set_params(), mirroring the ioctl.

Similarly - ethtool core in general, and ethtool_get_any_eeprom() in particular tries to zero-init all buffers passed to the drivers to avoid any extra work of zeroing things out. eeprom_fallback() uses a plain kmalloc(), change it to zalloc.

Fixes 96d971e307cc ("ethtool: Add fallback to get_module_eeprom from netlink command")
---
 net/ethtool/eeprom.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)
net/ethtool/eeprom.c +4 -1
index 15546f2a5e4583..4e864824b64d28 100644
@@ -43,6 +43,9 @@ static int fallback_set_params(struct eeprom_req_info *request,
 	if (offset >= modinfo->eeprom_len)
 		return -EINVAL;
 
+	if (length > modinfo->eeprom_len - offset)
+		return -EINVAL;
+
 	eeprom->cmd = ETHTOOL_GMODULEEEPROM;
 	eeprom->len = length;
 	eeprom->offset = offset;
@@ -68,7 +71,7 @@ static int eeprom_fallback(struct eeprom_req_info *request,
 	if (err < 0)
 		return err;
 
-	data = kmalloc(eeprom.len, GFP_KERNEL);
+	data = kzalloc(eeprom.len, GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 	err = ethtool_get_module_eeprom_call(dev, &eeprom, data);
Signature · 1 line
2.53.0
author maintainer
#39 lore raw

PATCH 39/452 ipv6: rpl: fix hdrlen overflow in ipv6_rpl_srh_decompress()

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 8610c7c6e3bd ("net: ipv6: add support for rpl sr exthdr")
---
 net/ipv6/exthdrs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/exthdrs.c +1 -1
index 54e71623aac9cc..e1d632c12cc46a 100644
@@ -546,7 +546,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
author maintainer
#40 lore raw

PATCH 40/452 net/sched: Revert "net/sched: Restrict conditions for adding duplicating netems to qdisc tree"

In reply to Greg Kroah-Hartman

6.6-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
index f8c5c506180858..827489b31626bb 100644
@@ -1005,41 +1005,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)
@@ -1116,11 +1081,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
author maintainer
#41 lore raw

PATCH 41/452 Bluetooth: l2cap: clear chan->ident on ECRED reconfiguration success

In reply to Greg Kroah-Hartman

6.6-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).

Fixes 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
---
 net/bluetooth/l2cap_core.c | 10 ++++++++--
 1 file changed, 8 insertions(+), 2 deletions(-)
net/bluetooth/l2cap_core.c +8 -2
index bbaf0070ca6176..0295a18a1cb3d7 100644
@@ -5393,14 +5393,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
author maintainer
#42 lore raw

PATCH 42/452 Bluetooth: L2CAP: Fix possible crash on l2cap_ecred_conn_rsp

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 15f02b910562 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
---
 net/bluetooth/l2cap_core.c | 27 ++++++++++++++++++++++-----
 1 file changed, 22 insertions(+), 5 deletions(-)
net/bluetooth/l2cap_core.c +22 -5
index 0295a18a1cb3d7..1f5d5343d380e4 100644
@@ -5195,6 +5195,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 ||
@@ -5216,8 +5217,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
@@ -5226,10 +5229,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
author maintainer
#43 lore raw

PATCH 43/452 gpio: rockchip: convert bank->clk to devm_clk_get_enabled()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Marco Scardovi <[email protected]>

[ Upstream commit 3e46c18d5d87f063a93ae0fe7662fbf6660459d5 ]

The bank->clk was previously obtained via of_clk_get() and manually prepared/enabled. However, it was missing a corresponding clk_put() in both the error paths and the remove function, leading to a reference leak.

Convert the allocation to devm_clk_get_enabled(), which also properly propagates failures from clk_prepare_enable() that were previously ignored.

The GPIO bank device uses the same OF node as the previous of_clk_get() call, so devm_clk_get_enabled(dev, NULL) correctly resolves the same clock provider entry.

Fix the reference leak and simplify the code by removing the manual clk_disable_unprepare() calls in the probe error paths and in the remove function.

Fixes 936ee2675eee ("gpio/rockchip: add driver for rockchip gpio")
Assisted-by Antigravity:gemini-3.5-flash
---
 drivers/gpio/gpio-rockchip.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)
drivers/gpio/gpio-rockchip.c +1 -5
index 752bbc0c3d9db1..ff9a4b8611d7f4 100644
@@ -647,11 +647,10 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
 	if (!bank->irq)
 		return -EINVAL;
 
-	bank->clk = of_clk_get(bank->of_node, 0);
+	bank->clk = devm_clk_get_enabled(bank->dev, NULL);
 	if (IS_ERR(bank->clk))
 		return PTR_ERR(bank->clk);
 
-	clk_prepare_enable(bank->clk);
 	id = readl(bank->reg_base + gpio_regs_v2.version_id);
 
 	/* If not gpio v2, that is default to v1. */
@@ -661,7 +660,6 @@ static int rockchip_get_bank_data(struct rockchip_pin_bank *bank)
 		bank->db_clk = of_clk_get(bank->of_node, 1);
 		if (IS_ERR(bank->db_clk)) {
 			dev_err(bank->dev, "cannot find debounce clk\n");
-			clk_disable_unprepare(bank->clk);
 			return -EINVAL;
 		}
 	} else {
@@ -735,7 +733,6 @@ static int rockchip_gpio_probe(struct platform_device *pdev)
 
 	ret = rockchip_gpiolib_register(bank);
 	if (ret) {
-		clk_disable_unprepare(bank->clk);
 		mutex_unlock(&bank->deferred_lock);
 		return ret;
 	}
@@ -776,7 +773,6 @@ static int rockchip_gpio_remove(struct platform_device *pdev)
 {
 	struct rockchip_pin_bank *bank = platform_get_drvdata(pdev);
 
-	clk_disable_unprepare(bank->clk);
 	gpiochip_remove(&bank->gpio_chip);
 
 	return 0;
Signature · 1 line
2.53.0
author maintainer
#44 lore raw

PATCH 44/452 net: mana: Add NULL guards in teardown path to prevent panic on attach failure

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dipayaan Roy <[email protected]>

[ Upstream commit 17bfe0a8c014ee1d542ad352cd6a0a505361664a ]

When queue allocation fails partway through, the error cleanup frees and NULLs apc->tx_qp and apc->rxqs. Multiple teardown paths such as mana_remove(), mana_change_mtu() recovery, and internal error handling in mana_alloc_queues() can subsequently call into functions that dereference these pointers without NULL checks:

- mana_chn_setxdp() dereferences apc->rxqs[0], causing a NULL pointer dereference panic (CR2: 0000000000000000 at mana_chn_setxdp+0x26).
- mana_destroy_vport() iterates apc->rxqs without a NULL check.
- mana_fence_rqs() iterates apc->rxqs without a NULL check.
- mana_dealloc_queues() iterates apc->tx_qp without a NULL check.

Add NULL guards for apc->rxqs in mana_fence_rqs(), mana_destroy_vport(), and before the mana_chn_setxdp() call. Add a NULL guard for apc->tx_qp in mana_dealloc_queues() to skip TX queue draining when TX queues were never allocated or already freed.

Fixes ca9c54d2d6a5 ("net: mana: Add a driver for Microsoft Azure Network Adapter (MANA)")
---
 drivers/net/ethernet/microsoft/mana/mana_en.c | 70 +++++++++++--------
 1 file changed, 41 insertions(+), 29 deletions(-)
drivers/net/ethernet/microsoft/mana/mana_en.c +41 -29
index 343f6e879af39e..3cf4ad1d91f67e 100644
@@ -1304,6 +1304,9 @@ static void mana_fence_rqs(struct mana_port_context *apc)
 	struct mana_rxq *rxq;
 	int err;
 
+	if (!apc->rxqs)
+		return;
+
 	for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
 		rxq = apc->rxqs[rxq_idx];
 		err = mana_fence_rq(apc, rxq);
@@ -2334,13 +2337,16 @@ static void mana_destroy_vport(struct mana_port_context *apc)
 	struct mana_rxq *rxq;
 	u32 rxq_idx;
 
-	for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
-		rxq = apc->rxqs[rxq_idx];
-		if (!rxq)
-			continue;
+	if (apc->rxqs) {
 
-		mana_destroy_rxq(apc, rxq, true);
-		apc->rxqs[rxq_idx] = NULL;
+		for (rxq_idx = 0; rxq_idx < apc->num_queues; rxq_idx++) {
+			rxq = apc->rxqs[rxq_idx];
+			if (!rxq)
+				continue;
+
+			mana_destroy_rxq(apc, rxq, true);
+			apc->rxqs[rxq_idx] = NULL;
+		}
 	}
 
 	mana_destroy_txq(apc);
@@ -2577,7 +2583,8 @@ static int mana_dealloc_queues(struct net_device *ndev)
 	if (apc->port_is_up)
 		return -EINVAL;
 
-	mana_chn_setxdp(apc, NULL);
+	if (apc->rxqs)
+		mana_chn_setxdp(apc, NULL);
 
 	if (gd->gdma_context->is_pf)
 		mana_pf_deregister_filter(apc);
@@ -2595,33 +2602,38 @@ static int mana_dealloc_queues(struct net_device *ndev)
 	 * number of queues.
 	 */
 
-	for (i = 0; i < apc->num_queues; i++) {
-		txq = &apc->tx_qp[i].txq;
-		tsleep = 1000;
-		while (atomic_read(&txq->pending_sends) > 0 &&
-		       time_before(jiffies, timeout)) {
-			usleep_range(tsleep, tsleep + 1000);
-			tsleep <<= 1;
-		}
-		if (atomic_read(&txq->pending_sends)) {
-			err = pcie_flr(to_pci_dev(gd->gdma_context->dev));
-			if (err) {
-				netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
-					   err, atomic_read(&txq->pending_sends),
-					   txq->gdma_txq_id);
+	if (apc->tx_qp) {
+		for (i = 0; i < apc->num_queues; i++) {
+			txq = &apc->tx_qp[i].txq;
+			tsleep = 1000;
+			while (atomic_read(&txq->pending_sends) > 0 &&
+			       time_before(jiffies, timeout)) {
+				usleep_range(tsleep, tsleep + 1000);
+				tsleep <<= 1;
+			}
+			if (atomic_read(&txq->pending_sends)) {
+				err =
+				    pcie_flr(to_pci_dev(gd->gdma_context->dev));
+				if (err) {
+					netdev_err(ndev, "flr failed %d with %d pkts pending in txq %u\n",
+						   err,
+					    atomic_read(&txq->pending_sends),
+					    txq->gdma_txq_id);
+				}
+				break;
 			}
-			break;
 		}
-	}
 
-	for (i = 0; i < apc->num_queues; i++) {
-		txq = &apc->tx_qp[i].txq;
-		while ((skb = skb_dequeue(&txq->pending_skbs))) {
-			mana_unmap_skb(skb, apc);
-			dev_kfree_skb_any(skb);
+		for (i = 0; i < apc->num_queues; i++) {
+			txq = &apc->tx_qp[i].txq;
+			while ((skb = skb_dequeue(&txq->pending_skbs))) {
+				mana_unmap_skb(skb, apc);
+				dev_kfree_skb_any(skb);
+			}
+			atomic_set(&txq->pending_sends, 0);
 		}
-		atomic_set(&txq->pending_sends, 0);
 	}
+
 	/* We're 100% sure the queues can no longer be woken up, because
 	 * we're sure now mana_poll_tx_cq() can't be running.
 	 */
Signature · 1 line
2.53.0
author maintainer
#45 lore raw

PATCH 45/452 sctp: fix race between sctp_wait_for_connect and peeloff

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 668c9beb9020 ("sctp: implement assign_number for sctp_stream_interleave")
---
 net/sctp/socket.c | 2 ++
 1 file changed, 2 insertions(+)
net/sctp/socket.c +2 -0
index 98586bcf83cebe..a6a53b0c4ea324 100644
@@ -9371,6 +9371,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
author maintainer
#46 lore raw

PATCH 46/452 ipv6: fix possible infinite loop in rt6_fill_node()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jiayuan Chen <[email protected]>

[ Upstream commit 9f72412bcf60144f252b0d6205106abf14344abc ]

Sashiko reported this issue [1]. Apply the same fix as
commit f8d8ce1b515a ("ipv6: fix possible infinite loop in fib6_info_uses_dev()").

Writers holding tb6_lock can list_del_rcu(&rt->fib6_siblings) without waiting for RCU readers; rt->fib6_siblings.next then still points into the old ring and this softirq-side walker never reaches &rt->fib6_siblings, causing a CPU stall. fib6_del_route() always WRITE_ONCE()s rt->fib6_nsiblings to 0 before list_del_rcu(), so an inside-loop check is a reliable detach signal.

[1] https://sashiko.dev/#/patchset/20260526020227.4857-1-jiayuan.chen%40linux.dev

Fixes d9ccb18f83ea ("ipv6: Fix soft lockups in fib6_select_path under high next hop churn")
---
 net/ipv6/route.c | 2 ++
 1 file changed, 2 insertions(+)
net/ipv6/route.c +2 -0
index c5b71baf95e7b3..69659f2a6aea96 100644
@@ -5797,6 +5797,8 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
 
 				goto nla_put_failure;
 			}
+			if (!READ_ONCE(rt->fib6_nsiblings))
+				break;
 		}
 
 		rcu_read_unlock();
Signature · 1 line
2.53.0
author maintainer
#47 lore raw

PATCH 47/452 ipv6: fix possible infinite loop in fib6_select_path()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jiayuan Chen <[email protected]>

[ Upstream commit 9c7da87c2dc860bb17ca1ece942495d28b1ce3b9 ]

Found while auditing the same pattern Sashiko reported in rt6_fill_node() [1]. Apply the same fix as
commit f8d8ce1b515a ("ipv6: fix possible infinite loop in fib6_info_uses_dev()").

Writers holding tb6_lock can list_del_rcu(&first->fib6_siblings) without waiting for RCU readers; first->fib6_siblings.next then still points into the old ring and this softirq-side walker never reaches &first->fib6_siblings as its terminator. fib6_purge_rt() always WRITE_ONCE()s first->fib6_nsiblings to 0 before list_del_rcu(), so an inside-loop check is a reliable detach signal.

[1] https://sashiko.dev/#/patchset/20260526020227.4857-1-jiayuan.chen%40linux.dev

Fixes d9ccb18f83ea ("ipv6: Fix soft lockups in fib6_select_path under high next hop churn")
---
 net/ipv6/route.c | 3 +++
 1 file changed, 3 insertions(+)
net/ipv6/route.c +3 -0
index 69659f2a6aea96..6d80e17c04c0d8 100644
@@ -484,6 +484,9 @@ void fib6_select_path(const struct net *net, struct fib6_result *res,
 		const struct fib6_nh *nh = sibling->fib6_nh;
 		int nh_upper_bound;
 
+		if (!READ_ONCE(first->fib6_nsiblings))
+			break;
+
 		nh_upper_bound = atomic_read(&nh->fib_nh_upper_bound);
 		if (hash > nh_upper_bound)
 			continue;
Signature · 1 line
2.53.0
author maintainer
#48 lore raw

PATCH 48/452 net: skbuff: fix pskb_carve leaking zcopy pages

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Pavel Begunkov <[email protected]>

[ Upstream commit ff6e798c2eac3ebd0501ad7e796f583fab928de8 ]

When SKBFL_MANAGED_FRAG_REFS is set, frag pages are not refcounted but their lifetime is controlled by the attached ubuf_info. To make a copy of the skb_shared_info, we either should clear the flag and reference the frags, or keep the flag and have frags unreferenced.

pskb_carve_inside_header() and pskb_carve_inside_nonlinear() don't follow the rule and thus can leak page references. Let's clear SKBFL_MANAGED_FRAG_REFS from the original skb to fix it. It's the simplest way to address it, but there are more performant ways to do that if it ever becomes a problem.

---
 net/core/skbuff.c | 10 ++++++++++
 1 file changed, 10 insertions(+)
net/core/skbuff.c +10 -0
index 8b05866e93b195..2282b6ad4be21a 100644
@@ -6397,6 +6397,11 @@ static int pskb_carve_inside_header(struct sk_buff *skb, const u32 off,
 	skb_copy_from_linear_data_offset(skb, off, data, new_hlen);
 	skb->len -= off;
 
+	/* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
+	 * while refcounting frags below.
+	 */
+	skb_zcopy_downgrade_managed(skb);
+
 	memcpy((struct skb_shared_info *)(data + size),
 	       skb_shinfo(skb),
 	       offsetof(struct skb_shared_info,
@@ -6509,6 +6514,11 @@ static int pskb_carve_inside_nonlinear(struct sk_buff *skb, const u32 off,
 		return -ENOMEM;
 	size = SKB_WITH_OVERHEAD(size);
 
+	/* Remove SKBFL_MANAGED_FRAG_REFS instead of trying to honour it
+	 * while refcounting frags below.
+	 */
+	skb_zcopy_downgrade_managed(skb);
+
 	memcpy((struct skb_shared_info *)(data + size),
 	       skb_shinfo(skb), offsetof(struct skb_shared_info, frags[0]));
 	if (skb_orphan_frags(skb, gfp_mask)) {
Signature · 1 line
2.53.0
author maintainer
#49 lore raw

PATCH 49/452 perf: Fix dangling cgroup pointer in cpuctx

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Yeoreum Yun <[email protected]>

[ Upstream commit 3b7a34aebbdf2a4b7295205bf0c654294283ec82 ]

Commit a3c3c6667("perf/core: Fix child_total_time_enabled accounting bug at task exit") moves the event->state update to before list_del_event(). This makes the event->state test in list_del_event() always false; never calling perf_cgroup_event_disable().

As a result, cpuctx->cgrp won't be cleared properly; causing havoc.

Fixes a3c3c6667("perf/core: Fix child_total_time_enabled accounting bug at task exit")
---
 kernel/events/core.c | 16 ++++------------
 1 file changed, 4 insertions(+), 12 deletions(-)
kernel/events/core.c +4 -12
index eba5eb6fcb8762..a4187dea6402a7 100644
@@ -2056,18 +2056,6 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)
 	if (event->group_leader == event)
 		del_event_from_groups(event, ctx);
 
-	/*
-	 * If event was in error state, then keep it
-	 * that way, otherwise bogus counts will be
-	 * returned on read(). The only way to get out
-	 * of error state is by explicit re-enabling
-	 * of the event
-	 */
-	if (event->state > PERF_EVENT_STATE_OFF) {
-		perf_cgroup_event_disable(event, ctx);
-		perf_event_set_state(event, PERF_EVENT_STATE_OFF);
-	}
-
 	ctx->generation++;
 	event->pmu_ctx->nr_events--;
 }
@@ -2401,6 +2389,10 @@ __perf_remove_from_context(struct perf_event *event,
 		state = PERF_EVENT_STATE_DEAD;
 	}
 	event_sched_out(event, ctx);
+
+	if (event->state > PERF_EVENT_STATE_OFF)
+		perf_cgroup_event_disable(event, ctx);
+
 	perf_event_set_state(event, min(event->state, state));
 	if (flags & DETACH_GROUP)
 		perf_group_detach(event);
Signature · 1 line
2.53.0
#50 lore raw

Re: perf: Fix dangling cgroup pointer in cpuctx

Hello,

I noticed your backport missed - 'event->pending_disable = 1;', which different than upstream version, is that true?

BRs
Wentao Guan

author maintainer
#51 lore raw

Re: perf: Fix dangling cgroup pointer in cpuctx

Quoted 4 lines · Wentao Guan

Hello,

I noticed your backport missed - 'event->pending_disable = 1;', which different than upstream version, is that true?

I have no context here at all :(

#52 lore raw

Re: perf: Fix dangling cgroup pointer in cpuctx

Hello,

orginal patch commit 3b7a34aebbdf2a4b7295205bf0c654294283ec82,
perf: Fix dangling cgroup pointer in cpuctx delete 'event->pending_disable = 1;' in __perf_remove_from_context(), but the backport commit ae1ada0af16249a3ed15e33fa6719a6a2f96f537 did not.

[context different]
25,26c19,20
< kernel/events/core.c | 16 ++++------------ < 1 file changed, 4 insertions(+), 12 deletions(-)
---

Quoted 2 lines
 kernel/events/core.c | 21 ++++++---------------
 1 file changed, 6 insertions(+), 15 deletions(-)

29c23
< index 0ac83fc1cb5e3..132524d0297cb 100644
---

Quoted 1 line

index 1cc98b9b3c0b4..d78608323916f 100644

32c26
< @@ -2056,18 +2056,6 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)
---

Review list_del_event(struct perf_event *event, struct perf_event_context *ctx)

Quoted 1 line
(quoted diff) +0 -0
@@ -2120,18 +2120,6 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)

51c45,51
< @@ -2401,6 +2389,10 @@ __perf_remove_from_context(struct perf_event *event,
---

Review __perf_remove_from_context(struct perf_event *event, · line 2479

Quoted 7 lines
(quoted diff) +1 -2
@@ -2488,11 +2476,14 @@ __perf_remove_from_context(struct perf_event *event,
              state = PERF_EVENT_STATE_EXIT;
      if (flags & DETACH_REVOKE)
              state = PERF_EVENT_STATE_REVOKED;
-     if (flags & DETACH_DEAD) {
-             event->pending_disable = 1;
+     if (flags & DETACH_DEAD)

53c53,54
< }
---

kernel/events/core.c list_del_event(struct perf_event *event, struct perf_event_context *ctx) · line 2069

Quoted 1 line
kernel/events/core.c +0 -1
-     }

BRs
Wentao Guan

author maintainer
#53 lore raw

Re: perf: Fix dangling cgroup pointer in cpuctx

Quoted 25 lines · Wentao Guan

Hello,

orginal patch commit 3b7a34aebbdf2a4b7295205bf0c654294283ec82,
perf: Fix dangling cgroup pointer in cpuctx delete 'event->pending_disable = 1;' in __perf_remove_from_context(), but the backport commit ae1ada0af16249a3ed15e33fa6719a6a2f96f537 did not.

[context different]
25,26c19,20
< kernel/events/core.c | 16 ++++------------ < 1 file changed, 4 insertions(+), 12 deletions(-)
---

Quoted 2 lines
 kernel/events/core.c | 21 ++++++---------------
 1 file changed, 6 insertions(+), 15 deletions(-)

29c23
< index 0ac83fc1cb5e3..132524d0297cb 100644
---

Quoted 1 line

index 1cc98b9b3c0b4..d78608323916f 100644

32c26
< @@ -2056,18 +2056,6 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)
---

Review list_del_event(struct perf_event *event, struct perf_event_context *ctx)

Quoted 1 line
(quoted diff) +0 -0
@@ -2120,18 +2120,6 @@ list_del_event(struct perf_event *event, struct perf_event_context *ctx)

51c45,51
< @@ -2401,6 +2389,10 @@ __perf_remove_from_context(struct perf_event *event,
---

Quoted 11 lines

Review __perf_remove_from_context(struct perf_event *event, · line 2479

Quoted 7 lines
(quoted diff) +1 -2
@@ -2488,11 +2476,14 @@ __perf_remove_from_context(struct perf_event *event,
              state = PERF_EVENT_STATE_EXIT;
      if (flags & DETACH_REVOKE)
              state = PERF_EVENT_STATE_REVOKED;
-     if (flags & DETACH_DEAD) {
-             event->pending_disable = 1;
+     if (flags & DETACH_DEAD)

53c53,54
< }
---

Quoted 1 line
kernel/events/core.c +0 -1
-     }

I'm sorry, but I can't understand un-unified diffs, and diffs of diffs are a whole other level of toughness.... If you feel something was backported incorrectly, can you provide a patch to fix it up?

thanks,

greg k-h

#54 lore raw

PATCH 1/1 perf: Fix dangling cgroup pointer in cpuctx backport

In reply to Greg KH

recently backport of ("perf: Fix dangling cgroup pointer in cpuctx") use a middle version, so aligned with the upstream commit:
3b7a34aebbdf2a4b7295205bf0c654294283ec82

---
 kernel/events/core.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/events/core.c +2 -3
index a4187dea6402a..73a86db06cc9b 100644
@@ -2384,10 +2384,9 @@ __perf_remove_from_context(struct perf_event *event,
 	 */
 	if (flags & DETACH_EXIT)
 		state = PERF_EVENT_STATE_EXIT;
-	if (flags & DETACH_DEAD) {
-		event->pending_disable = 1;
+	if (flags & DETACH_DEAD)
 		state = PERF_EVENT_STATE_DEAD;
-	}
+
 	event_sched_out(event, ctx);
 
 	if (event->state > PERF_EVENT_STATE_OFF)
Signature · 1 line
2.30.2
author maintainer
#55 lore raw

Re: [PATCH] perf: Fix dangling cgroup pointer in cpuctx backport

Quoted 29 lines · Wentao Guan

recently backport of ("perf: Fix dangling cgroup pointer in cpuctx") use a middle version, so aligned with the upstream commit:
3b7a34aebbdf2a4b7295205bf0c654294283ec82

---
 kernel/events/core.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/events/core.c +2 -3
index a4187dea6402a..73a86db06cc9b 100644
@@ -2384,10 +2384,9 @@ __perf_remove_from_context(struct perf_event *event,
 	 */
 	if (flags & DETACH_EXIT)
 		state = PERF_EVENT_STATE_EXIT;
-	if (flags & DETACH_DEAD) {
-		event->pending_disable = 1;
+	if (flags & DETACH_DEAD)
 		state = PERF_EVENT_STATE_DEAD;
-	}
+
 	event_sched_out(event, ctx);
 
 	if (event->state > PERF_EVENT_STATE_OFF)
Signature · 1 line
2.30.2

What kernel tree(s) is this for? What git id does this fix?

thanks,

greg k-h

#56 lore raw

Re: [PATCH] perf: Fix dangling cgroup pointer in cpuctx backport

Quoted 26 lines · Wentao Guan
Quoted 25 lines

recently backport of ("perf: Fix dangling cgroup pointer in cpuctx") use a middle version, so aligned with the upstream commit:
3b7a34aebbdf2a4b7295205bf0c654294283ec82

Quoted 1 line
---
 kernel/events/core.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/events/core.c +2 -3
index a4187dea6402a..73a86db06cc9b 100644
@@ -2384,10 +2384,9 @@ __perf_remove_from_context(struct perf_event *event,
 */
 if (flags & DETACH_EXIT)
 state = PERF_EVENT_STATE_EXIT;
- if (flags & DETACH_DEAD) {
- event->pending_disable = 1;
+ if (flags & DETACH_DEAD)
 state = PERF_EVENT_STATE_DEAD;
- }
+
 event_sched_out(event, ctx);
 
Quoted 6 lines
Quoted 4 lines
kernel/events/core.c +0 -1
 if (event->state > PERF_EVENT_STATE_OFF)
--

2.30.2

What kernel tree(s) is this for? What git id does this fix?

1. v6.6.143 and v6.12.94
2.
ae1ada0af16249a3ed15e33fa6719a6a2f96f537 in v6.6.143 46f5623f9b0ef66127e1de16fb857850cdb14e68 in v6.12.94

BRs
Wentao Guan

author maintainer
#57 lore raw

Re: [PATCH] perf: Fix dangling cgroup pointer in cpuctx backport

Quoted 32 lines · Wentao Guan
Quoted 26 lines · Wentao Guan
Quoted 25 lines

recently backport of ("perf: Fix dangling cgroup pointer in cpuctx") use a middle version, so aligned with the upstream commit:
3b7a34aebbdf2a4b7295205bf0c654294283ec82

Quoted 1 line
---
 kernel/events/core.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/events/core.c +2 -3
index a4187dea6402a..73a86db06cc9b 100644
@@ -2384,10 +2384,9 @@ __perf_remove_from_context(struct perf_event *event,
 */
 if (flags & DETACH_EXIT)
 state = PERF_EVENT_STATE_EXIT;
- if (flags & DETACH_DEAD) {
- event->pending_disable = 1;
+ if (flags & DETACH_DEAD)
 state = PERF_EVENT_STATE_DEAD;
- }
+
 event_sched_out(event, ctx);
 
Quoted 6 lines
Quoted 4 lines
kernel/events/core.c +0 -1
 if (event->state > PERF_EVENT_STATE_OFF)
--

2.30.2

What kernel tree(s) is this for? What git id does this fix?

Quoted 4 lines

1. v6.6.143 and v6.12.94
2.
ae1ada0af16249a3ed15e33fa6719a6a2f96f537 in v6.6.143 46f5623f9b0ef66127e1de16fb857850cdb14e68 in v6.12.94

Please put all of this information in the changelog and provide versions for all of the branches you want it for.

thanks,

greg k-h

#58 lore raw

Re: [PATCH] perf: Fix dangling cgroup pointer in cpuctx backport

Hi,

Quoted 33 lines · Wentao Guan
Quoted 32 lines
Quoted 32 lines · Wentao Guan
Quoted 27 lines

recently backport of ("perf: Fix dangling cgroup pointer in cpuctx") use a middle version, so aligned with the upstream commit:
3b7a34aebbdf2a4b7295205bf0c654294283ec82

Quoted 1 line
---
 kernel/events/core.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/events/core.c +2 -4
index a4187dea6402a..73a86db06cc9b 100644
@@ -2384,10 +2384,9 @@ __perf_remove_from_context(struct perf_event *event,
 */
 if (flags & DETACH_EXIT)
 state = PERF_EVENT_STATE_EXIT;
- if (flags & DETACH_DEAD) {
- event->pending_disable = 1;
+ if (flags & DETACH_DEAD)
 state = PERF_EVENT_STATE_DEAD;
- }
+
 event_sched_out(event, ctx);
 
 if (event->state > PERF_EVENT_STATE_OFF)
--
Quoted 2 lines

2.30.2

What kernel tree(s) is this for? What git id does this fix?

Quoted 7 lines
Quoted 4 lines

1. v6.6.143 and v6.12.94
2.
ae1ada0af16249a3ed15e33fa6719a6a2f96f537 in v6.6.143 46f5623f9b0ef66127e1de16fb857850cdb14e68 in v6.12.94

Please put all of this information in the changelog and provide versions for all of the branches you want it for.

Thanks for your reply, I will sumbit later.

Out of thread, people says https://cdn.kernel.org/pub/linux/kernel/v7.x/linux-7.1.2.tar.xz
from kernel.org public archive return 404, what happen?

BRs
Wentao Guan

#59 lore raw

PATCH 1/1 perf: Fix dangling cgroup pointer in cpuctx backport

In reply to Greg KH

recently backport of ("perf: Fix dangling cgroup pointer in cpuctx") use a middle version, so aligned with the upstream commit:
commit 3b7a34aebbdf ("perf: Fix dangling cgroup pointer in cpuctx")

This is a fix for stable v6.6.143 backport commit, so no upstream commit.

Fixes ae1ada0af162 ("perf: Fix dangling cgroup pointer in cpuctx")
---
 kernel/events/core.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/events/core.c +2 -3
index a4187dea6402a..73a86db06cc9b 100644
@@ -2384,10 +2384,9 @@ __perf_remove_from_context(struct perf_event *event,
 	 */
 	if (flags & DETACH_EXIT)
 		state = PERF_EVENT_STATE_EXIT;
-	if (flags & DETACH_DEAD) {
-		event->pending_disable = 1;
+	if (flags & DETACH_DEAD)
 		state = PERF_EVENT_STATE_DEAD;
-	}
+
 	event_sched_out(event, ctx);
 
 	if (event->state > PERF_EVENT_STATE_OFF)
Signature · 1 line
2.30.2
maintainer Applied
#60 lore raw

Re: [PATCH 6.6.y] perf: Fix dangling cgroup pointer in cpuctx backport

Quoted 5 lines · Wentao Guan

recently backport of ("perf: Fix dangling cgroup pointer in cpuctx") use a middle version, so aligned with the upstream commit:
commit 3b7a34aebbdf ("perf: Fix dangling cgroup pointer in cpuctx")

This is a fix for stable v6.6.143 backport commit, so no upstream commit.

Queued for 6.6.y, thanks!

Signature · 2 lines
Thanks,
Sasha
#61 lore raw

PATCH 1/1 perf: Fix dangling cgroup pointer in cpuctx backport

In reply to Greg KH

recently backport of ("perf: Fix dangling cgroup pointer in cpuctx") use a middle version, so aligned with the upstream commit:
commit 3b7a34aebbdf ("perf: Fix dangling cgroup pointer in cpuctx")

This is a fix for stable v6.12.94 backport commit, so no upstream commit.

Fixes 46f5623f9b0e ("perf: Fix dangling cgroup pointer in cpuctx")
---
 kernel/events/core.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)
kernel/events/core.c +2 -3
index 9099c0cc933be..8fa3ee209a5be 100644
@@ -2440,10 +2440,9 @@ __perf_remove_from_context(struct perf_event *event,
 	 */
 	if (flags & DETACH_EXIT)
 		state = PERF_EVENT_STATE_EXIT;
-	if (flags & DETACH_DEAD) {
-		event->pending_disable = 1;
+	if (flags & DETACH_DEAD)
 		state = PERF_EVENT_STATE_DEAD;
-	}
+
 	event_sched_out(event, ctx);
 
 	if (event->state > PERF_EVENT_STATE_OFF)
Signature · 1 line
2.30.2
maintainer Applied
#62 lore raw

Re: [PATCH 6.12.y] perf: Fix dangling cgroup pointer in cpuctx backport

Quoted 3 lines · Wentao Guan

recently backport of ("perf: Fix dangling cgroup pointer in cpuctx") use a middle version, so aligned with the upstream commit:
commit 3b7a34aebbdf ("perf: Fix dangling cgroup pointer in cpuctx")

Queued for 6.12.y, thanks!

Signature · 2 lines
Thanks,
Sasha
#63 lore raw

Re: perf: Fix dangling cgroup pointer in cpuctx

In reply to Wentao Guan

Hi,

Quoted 5 lines

Hello,

I noticed your backport missed - 'event->pending_disable = 1;', which different than upstream version, is that true?

Yes. I think it was missed otherwise for the DEAD event, it would have the middle OFF state.

Signature · 2 lines
Sincerely,
Yeoreum Yun
author maintainer
#64 lore raw

PATCH 50/452 batman-adv: v: stop OGMv2 on disabled interface

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 0da0035942d4 ("batman-adv: OGMv2 - add basic infrastructure")
[ switch to old "mesh_iface" name "soft_iface" ]
---
 net/batman-adv/bat_v_ogm.c | 33 +++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)
net/batman-adv/bat_v_ogm.c +21 -12
index 8f89ffe6020ced..310248a5812c49 100644
@@ -115,14 +115,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;
@@ -189,6 +189,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
@@ -198,7 +199,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;
@@ -228,27 +230,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);
@@ -347,7 +354,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();
@@ -387,12 +394,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);
@@ -582,7 +591,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:
 	batadv_orig_ifinfo_put(orig_ifinfo);
Signature · 1 line
2.53.0
author maintainer
#65 lore raw

PATCH 51/452 batman-adv: tvlv: abort OGM send on tvlv append failure

In reply to Greg Kroah-Hartman

6.6-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.

Fixes ef26157747d4 ("batman-adv: tvlv - basic infrastructure")
[ Context ]
---
 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
index 748188d3b878b2..42b687c1a76807 100644
@@ -781,6 +781,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);
 
@@ -804,9 +805,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
index 310248a5812c49..8cfc3944dcfd52 100644
@@ -271,9 +271,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);
@@ -281,25 +281,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
index 2a583215d439bd..76c6e0599694c7 100644
@@ -8,6 +8,7 @@
 
 #include <linux/byteorder/generic.h>
 #include <linux/container_of.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
index e5697230d99173..f96f6b3f44a001 100644
@@ -16,7 +16,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
author maintainer
#66 lore raw

PATCH 52/452 batman-adv: tt: reject oversized local TVLV buffers

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sven Eckelmann <[email protected]>

commit 1e9fab756f8395096d5bba7be0c373c4c8f5d165 upstream.

The commit 3a359bf5c61d ("batman-adv: reject oversized global TT response buffers") added a check to ensure that a global return buffer size can be stored in an u16. The same buffer handling also exists for the local data buffer but was not touched.

A similar check should be also be in place for the local TVLV buffer. It doesn't have the similar attack surface because it is only generated from locally discovered MAC addresses but the dynamic nature could still cause temporarily to large buffers.

Fixes 7ea7b4a14275 ("batman-adv: make the TT CRC logic VLAN specific")
[ Context ]
---
 net/batman-adv/translation-table.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)
net/batman-adv/translation-table.c +5 -3
index d830ccf016697b..8ffebece03c529 100644
@@ -924,12 +924,12 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
 {
 	struct batadv_tvlv_tt_vlan_data *tt_vlan;
 	struct batadv_softif_vlan *vlan;
+	size_t change_offset;
 	u16 num_vlan = 0;
 	u16 vlan_entries = 0;
 	u16 total_entries = 0;
 	u16 tvlv_len;
 	u8 *tt_change_ptr;
-	int change_offset;
 
 	spin_lock_bh(&bat_priv->softif_vlan_list_lock);
 	hlist_for_each_entry(vlan, &bat_priv->softif_vlan_list, list) {
@@ -948,8 +948,10 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
 	if (*tt_len < 0)
 		*tt_len = batadv_tt_len(total_entries);
 
-	tvlv_len = *tt_len;
-	tvlv_len += change_offset;
+	if (check_add_overflow(*tt_len, change_offset, &tvlv_len)) {
+		tvlv_len = 0;
+		goto out;
+	}
 
 	*tt_data = kmalloc(tvlv_len, GFP_ATOMIC);
 	if (!*tt_data) {
Signature · 1 line
2.53.0
author maintainer
#67 lore raw

PATCH 53/452 batman-adv: bla: avoid NULL-ptr deref for claim via dropped interface

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 23721387c409 ("batman-adv: add basic bridge loop avoidance code")
Reported-by [email protected]
[ switch to old "mesh_iface" name "soft_iface" ]
---
 net/batman-adv/bridge_loop_avoidance.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)
net/batman-adv/bridge_loop_avoidance.c +4 -2
index f614709e6cda74..76d8c91c156a3b 100644
@@ -356,12 +356,14 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, const 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
author maintainer
#68 lore raw

PATCH 54/452 batman-adv: tvlv: reject oversized TVLV packets

In reply to Greg Kroah-Hartman

6.6-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
index 76c6e0599694c7..8d6b017c433cc9 100644
@@ -13,6 +13,7 @@
 #include <linux/gfp.h>
 #include <linux/if_ether.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
author maintainer
#69 lore raw

PATCH 55/452 batman-adv: iv: recover OGM scheduling after forward packet error

In reply to Greg Kroah-Hartman

6.6-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.

Fixes c6c8fea29769 ("net: Add batman-adv meshing protocol")
---
 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
index 42b687c1a76807..b37c9fb178ae50 100644
@@ -223,6 +223,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)
@@ -527,8 +529,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,
@@ -552,13 +556,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;
@@ -580,6 +584,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 */
@@ -609,8 +615,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,
@@ -662,14 +670,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;
 	}
 }
 
@@ -781,6 +791,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);
@@ -809,11 +821,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;
@@ -835,8 +844,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;
 	}
 
@@ -851,15 +863,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)));
+	}
+
 	batadv_hardif_put(primary_if);
 }
 
@@ -874,6 +899,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
@@ -2277,6 +2313,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
index 957a70854157dc..d333f9dfec55d0 100644
@@ -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
author maintainer
#70 lore raw

PATCH 56/452 batman-adv: tp_meter: avoid role confusion in tp_list

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 33a3bb4a3345 ("batman-adv: throughput meter implementation")
---
 net/batman-adv/tp_meter.c | 59 ++++++++++++++++++++++++---------------
 1 file changed, 36 insertions(+), 23 deletions(-)
net/batman-adv/tp_meter.c +36 -23
index 04a83d6be45bc0..bc3dc377f0bfd0 100644
@@ -255,6 +255,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
@@ -262,7 +263,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;
 
@@ -271,6 +273,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
@@ -286,12 +291,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
@@ -301,7 +327,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;
 
@@ -313,6 +339,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
@@ -671,13 +700,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;
 
@@ -986,10 +1012,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,
@@ -1110,18 +1134,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);
@@ -1377,7 +1397,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;
 
@@ -1448,7 +1468,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",
@@ -1457,13 +1477,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
author maintainer
#71 lore raw

PATCH 57/452 net: af_key: zero aligned sockaddr tail in PF_KEY exports

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Zhengchuan Liang <[email protected]>

[ Upstream commit 426c355742f02cf743b347d9d7dbdc1bfbfa31ef ]

PF_KEY export paths use pfkey_sockaddr_size() when reserving sockaddr payload space, so IPv6 addresses occupy 32 bytes on the wire. However, pfkey_sockaddr_fill() initializes only the first 28 bytes of struct sockaddr_in6, leaving the final 4 aligned bytes uninitialized.

Not every PF_KEY message is affected. The state and policy dump builders already zero the whole message buffer before filling the sockaddr payloads. Keep the fix to the export paths that still append aligned sockaddr payloads with plain skb_put():

- SADB_ACQUIRE
- SADB_X_NAT_T_NEW_MAPPING
- SADB_X_MIGRATE

Fix those paths by clearing only the aligned sockaddr tail after pfkey_sockaddr_fill().

Fixes 1da177e4c3f4 ("Linux-2.6.12-rc2")
Fixes 08de61beab8a ("[PFKEYV2]: Extension for dynamic update of endpoint address(es)")
---
 net/key/af_key.c | 52 +++++++++++++++++++++++++++++++-----------------
 1 file changed, 34 insertions(+), 18 deletions(-)
net/key/af_key.c +34 -18
index 4849407da86d6e..486c9a2e1f52f3 100644
@@ -757,6 +757,22 @@ static unsigned int pfkey_sockaddr_fill(const xfrm_address_t *xaddr, __be16 port
 	return 0;
 }
 
+static unsigned int pfkey_sockaddr_fill_zero_tail(const xfrm_address_t *xaddr,
+						  __be16 port,
+						  struct sockaddr *sa,
+						  unsigned short family)
+{
+	unsigned int prefixlen;
+	int sockaddr_len = pfkey_sockaddr_len(family);
+	int sockaddr_size = pfkey_sockaddr_size(family);
+
+	prefixlen = pfkey_sockaddr_fill(xaddr, port, sa, family);
+	if (sockaddr_size > sockaddr_len)
+		memset((u8 *)sa + sockaddr_len, 0, sockaddr_size - sockaddr_len);
+
+	return prefixlen;
+}
+
 static struct sk_buff *__pfkey_xfrm_state2msg(const struct xfrm_state *x,
 					      int add_keys, int hsc)
 {
@@ -3205,9 +3221,9 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
 	addr->sadb_address_proto = 0;
 	addr->sadb_address_reserved = 0;
 	addr->sadb_address_prefixlen =
-		pfkey_sockaddr_fill(&x->props.saddr, 0,
-				    (struct sockaddr *) (addr + 1),
-				    x->props.family);
+		pfkey_sockaddr_fill_zero_tail(&x->props.saddr, 0,
+					      (struct sockaddr *)(addr + 1),
+					      x->props.family);
 	if (!addr->sadb_address_prefixlen)
 		BUG();
 
@@ -3220,9 +3236,9 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
 	addr->sadb_address_proto = 0;
 	addr->sadb_address_reserved = 0;
 	addr->sadb_address_prefixlen =
-		pfkey_sockaddr_fill(&x->id.daddr, 0,
-				    (struct sockaddr *) (addr + 1),
-				    x->props.family);
+		pfkey_sockaddr_fill_zero_tail(&x->id.daddr, 0,
+					      (struct sockaddr *)(addr + 1),
+					      x->props.family);
 	if (!addr->sadb_address_prefixlen)
 		BUG();
 
@@ -3420,9 +3436,9 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
 	addr->sadb_address_proto = 0;
 	addr->sadb_address_reserved = 0;
 	addr->sadb_address_prefixlen =
-		pfkey_sockaddr_fill(&x->props.saddr, 0,
-				    (struct sockaddr *) (addr + 1),
-				    x->props.family);
+		pfkey_sockaddr_fill_zero_tail(&x->props.saddr, 0,
+					      (struct sockaddr *)(addr + 1),
+					      x->props.family);
 	if (!addr->sadb_address_prefixlen)
 		BUG();
 
@@ -3442,9 +3458,9 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
 	addr->sadb_address_proto = 0;
 	addr->sadb_address_reserved = 0;
 	addr->sadb_address_prefixlen =
-		pfkey_sockaddr_fill(ipaddr, 0,
-				    (struct sockaddr *) (addr + 1),
-				    x->props.family);
+		pfkey_sockaddr_fill_zero_tail(ipaddr, 0,
+					      (struct sockaddr *)(addr + 1),
+					      x->props.family);
 	if (!addr->sadb_address_prefixlen)
 		BUG();
 
@@ -3473,15 +3489,15 @@ static int set_sadb_address(struct sk_buff *skb, int sasize, int type,
 	switch (type) {
 	case SADB_EXT_ADDRESS_SRC:
 		addr->sadb_address_prefixlen = sel->prefixlen_s;
-		pfkey_sockaddr_fill(&sel->saddr, 0,
-				    (struct sockaddr *)(addr + 1),
-				    sel->family);
+		pfkey_sockaddr_fill_zero_tail(&sel->saddr, 0,
+					      (struct sockaddr *)(addr + 1),
+					      sel->family);
 		break;
 	case SADB_EXT_ADDRESS_DST:
 		addr->sadb_address_prefixlen = sel->prefixlen_d;
-		pfkey_sockaddr_fill(&sel->daddr, 0,
-				    (struct sockaddr *)(addr + 1),
-				    sel->family);
+		pfkey_sockaddr_fill_zero_tail(&sel->daddr, 0,
+					      (struct sockaddr *)(addr + 1),
+					      sel->family);
 		break;
 	default:
 		return -EINVAL;
Signature · 1 line
2.53.0
author maintainer
#72 lore raw

PATCH 58/452 batman-adv: tp_meter: directly shut down timer on cleanup

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sven Eckelmann <[email protected]>

commit d5487249a81ea658717614009c8f46acc5b7101a upstream.

batadv_tp_sender_cleanup() was calling timer_delete_sync() followed by timer_delete() to guard against the timer handler re-arming itself between the two calls. This double-deletion hack relied on the sending status being set to 0 to suppress re-arming.

Replace both calls with a single timer_shutdown_sync(). This function both waits for any running timer callback to complete (like timer_delete_sync()) and permanently disarms the timer so it cannot be re-armed afterwards, making re-arming prevention unconditional and self-documenting.

The re-arming property is also required because otherwise:

1. context 0 (batadv_tp_recv_ack()) checks in batadv_tp_reset_sender_timer() if sending is still 1 -> it is
2. context 1 changes in batadv_tp_sender_shutdown() sending to 0 and in this process forces the kthread to stop timer in batadv_tp_sender_cleanup()
3. context 0 continues in batadv_tp_reset_sender_timer() and rearms the timer -> but the reference for it is already gone

Fixes 33a3bb4a3345 ("batman-adv: throughput meter implementation")
[ adapt pre-hunk to old del_timer* names ]
---
 net/batman-adv/tp_meter.c | 8 +-------
 1 file changed, 1 insertion(+), 7 deletions(-)
net/batman-adv/tp_meter.c +1 -7
index bc3dc377f0bfd0..dfc3374549921f 100644
@@ -430,13 +430,7 @@ static void batadv_tp_sender_cleanup(struct batadv_tp_vars *tp_vars)
 	batadv_tp_list_detach(tp_vars);
 
 	/* kill the timer and remove its reference */
-	del_timer_sync(&tp_vars->timer);
-	/* the worker might have rearmed itself therefore we kill it again. Note
-	 * that if the worker should run again before invoking the following
-	 * del_timer(), it would not re-arm itself once again because the status
-	 * is OFF now
-	 */
-	del_timer(&tp_vars->timer);
+	timer_shutdown_sync(&tp_vars->timer);
 	batadv_tp_vars_put(tp_vars);
 }
 
Signature · 1 line
2.53.0
author maintainer
#73 lore raw

PATCH 59/452 batman-adv: tt: fix TOCTOU race for reported vlans

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 16116dac2339 ("batman-adv: prevent TT request storms by not sending inconsistent TT TLVLs")
[ Context, drop flex array dependency ]
---
 net/batman-adv/translation-table.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)
net/batman-adv/translation-table.c +10 -4
index 8ffebece03c529..d4cebe122e528a 100644
@@ -934,11 +934,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);
@@ -964,6 +961,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)
@@ -974,8 +972,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
author maintainer
#74 lore raw

PATCH 60/452 batman-adv: tt: avoid empty VLAN responses

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 7ea7b4a14275 ("batman-adv: make the TT CRC logic VLAN specific")
[ Context, drop flex array dependency ]
---
 net/batman-adv/translation-table.c | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)
net/batman-adv/translation-table.c +18 -3
index d4cebe122e528a..4045ddefc29b47 100644
@@ -843,17 +843,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);
@@ -861,7 +863,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;
@@ -882,14 +884,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
author maintainer
#75 lore raw

PATCH 61/452 batman-adv: bla: avoid double decrement of bla.num_requests

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 23721387c409 ("batman-adv: add basic bridge loop avoidance code")
---
 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
index 76d8c91c156a3b..cfb1eb25c6ac4d 100644
@@ -516,8 +516,8 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, const 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);
@@ -546,9 +546,13 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, const 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;
@@ -651,10 +655,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);
 }
 
 /**
@@ -875,10 +881,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);
@@ -1257,9 +1265,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);
@@ -1510,7 +1522,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.
 			 *
@@ -1519,14 +1531,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
index 1bf1232a4f7595..680f729b3b0228 100644
@@ -783,6 +783,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
index d333f9dfec55d0..2dfdc78d4ded99 100644
@@ -1027,6 +1027,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
 	 */
@@ -1755,6 +1761,27 @@ struct batadv_priv {
 
 #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
  */
@@ -1780,16 +1807,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
author maintainer
#76 lore raw

PATCH 62/452 mm/page_alloc: clear page->private in free_pages_prepare()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Mikhail Gavrilov <[email protected]>

[ Upstream commit ac1ea219590c09572ed5992dc233bbf7bb70fef9 ]

Several subsystems (slub, shmem, ttm, etc.) use page->private but don't clear it before freeing pages. When these pages are later allocated as high-order pages and split via split_page(), tail pages retain stale page->private values.

This causes a use-after-free in the swap subsystem. The swap code uses page->private to track swap count continuations, assuming freshly allocated pages have page->private == 0. When stale values are present, swap_count_continued() incorrectly assumes the continuation list is valid and iterates over uninitialized page->lru containing LIST_POISON values, causing a crash:

  KASAN: maybe wild-memory-access in range [0xdead000000000100-0xdead000000000107]
  RIP: 0010:__do_sys_swapoff+0x1151/0x1860

Fix this by clearing page->private in free_pages_prepare(), ensuring all freed pages have clean state regardless of previous use.

Fixes 3b8000ae185c ("mm/vmalloc: huge vmalloc backing pages should be split rather than compound")
Cc Brendan Jackman <[email protected]>
Cc Chris Li <[email protected]>
Cc Hugh Dickins <[email protected]>
Cc Johannes Weiner <[email protected]>
Cc Kairui Song <[email protected]>
Cc Matthew Wilcox (Oracle) <[email protected]>
Cc Michal Hocko <[email protected]>
Cc Nicholas Piggin <[email protected]>
Cc Suren Baghdasaryan <[email protected]>
[backport: context only]
---
 mm/page_alloc.c | 1 +
 1 file changed, 1 insertion(+)
mm/page_alloc.c +1 -0
index b617fb364b15d1..ffdc71103c2ad2 100644
@@ -1178,6 +1178,7 @@ static __always_inline bool free_pages_prepare(struct page *page,
 
 	page_cpupid_reset_last(page);
 	page->flags &= ~PAGE_FLAGS_CHECK_AT_PREP;
+	page->private = 0;
 	reset_page_owner(page, order);
 	page_table_check_free(page, order);
 
Signature · 1 line
2.53.0
author maintainer
#77 lore raw

PATCH 63/452 media: rc: fix race between unregister and urb/irq callbacks

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sean Young <[email protected]>

[ Upstream commit dccc0c3ddf8f16071736f98a7d6dd46a2d43e037 ]

Some rc device drivers have a race condition between rc_unregister_device() and irq or urb callbacks. This is because rc_unregister_device() does two things, it marks the device as unregistered so no new commands can be issued and then it calls rc_free_device(). This means the driver has no chance to cancel any pending urb callbacks or interrupts after the device has been marked as unregistered. Those callbacks may access struct rc_dev or its members (e.g. struct ir_raw_event_ctrl), which have been freed by rc_free_device().

This change removes the implicit call to rc_free_device() from rc_unregister_device(). This means that device drivers can call rc_unregister_device() in their remove or disconnect function, then cancel all the urbs and interrupts before explicitly calling rc_free_device().

Note this is an alternative fix for an issue found by Haotian Zhang, see the Closes: tags.

Stable-dep-of: 646ebdd31058 ("media: rc: ttusbir: fix inverted error logic")

---
 drivers/gpu/drm/bridge/sil-sii8620.c        | 1 +
 drivers/hid/hid-picolcd_cir.c               | 1 +
 drivers/media/cec/core/cec-core.c           | 2 +-
 drivers/media/common/siano/smsir.c          | 1 +
 drivers/media/i2c/ir-kbd-i2c.c              | 2 ++
 drivers/media/pci/bt8xx/bttv-input.c        | 3 ++-
 drivers/media/pci/cx23885/cx23885-input.c   | 1 +
 drivers/media/pci/cx88/cx88-input.c         | 3 ++-
 drivers/media/pci/dm1105/dm1105.c           | 1 +
 drivers/media/pci/mantis/mantis_input.c     | 1 +
 drivers/media/pci/saa7134/saa7134-input.c   | 1 +
 drivers/media/pci/smipcie/smipcie-ir.c      | 1 +
 drivers/media/pci/ttpci/budget-ci.c         | 1 +
 drivers/media/rc/ati_remote.c               | 6 +++---
 drivers/media/rc/ene_ir.c                   | 2 +-
 drivers/media/rc/fintek-cir.c               | 3 ++-
 drivers/media/rc/igorplugusb.c              | 1 +
 drivers/media/rc/iguanair.c                 | 1 +
 drivers/media/rc/img-ir/img-ir-hw.c         | 3 ++-
 drivers/media/rc/img-ir/img-ir-raw.c        | 3 ++-
 drivers/media/rc/imon.c                     | 3 ++-
 drivers/media/rc/ir-hix5hd2.c               | 2 +-
 drivers/media/rc/ir_toy.c                   | 1 +
 drivers/media/rc/ite-cir.c                  | 2 +-
 drivers/media/rc/mceusb.c                   | 1 +
 drivers/media/rc/rc-ir-raw.c                | 5 -----
 drivers/media/rc/rc-loopback.c              | 1 +
 drivers/media/rc/rc-main.c                  | 6 +-----
 drivers/media/rc/redrat3.c                  | 4 +++-
 drivers/media/rc/st_rc.c                    | 2 +-
 drivers/media/rc/streamzap.c                | 7 ++++---
 drivers/media/rc/sunxi-cir.c                | 1 +
 drivers/media/rc/ttusbir.c                  | 2 +-
 drivers/media/rc/winbond-cir.c              | 2 +-
 drivers/media/rc/xbox_remote.c              | 5 +++--
 drivers/media/usb/au0828/au0828-input.c     | 1 +
 drivers/media/usb/dvb-usb-v2/dvb_usb_core.c | 1 +
 drivers/media/usb/dvb-usb/dvb-usb-remote.c  | 6 ++++--
 drivers/media/usb/em28xx/em28xx-input.c     | 1 +
 drivers/staging/media/av7110/av7110_ir.c    | 1 +
 include/media/rc-core.h                     | 2 --
 41 files changed, 58 insertions(+), 36 deletions(-)
drivers/gpu/drm/bridge/sil-sii8620.c +1 -0
index 599164e3877dbd..93c41c8dedff84 100644
@@ -2220,6 +2220,7 @@ static void sii8620_detach(struct drm_bridge *bridge)
 		return;
 
 	rc_unregister_device(ctx->rc_dev);
+	rc_free_device(ctx->rc_dev);
 }
 
 static int sii8620_is_packing_required(struct sii8620 *ctx,
drivers/hid/hid-picolcd_cir.c +1 -0
index d6faa0e00f95ac..6d4c636e1c9f7e 100644
@@ -134,5 +134,6 @@ void picolcd_exit_cir(struct picolcd_data *data)
 
 	data->rc_dev = NULL;
 	rc_unregister_device(rdev);
+	rc_free_device(rdev);
 }
 
drivers/media/cec/core/cec-core.c +1 -1
index b4dcc352a3c6f1..74dff5f8d33658 100644
@@ -366,8 +366,8 @@ int cec_register_adapter(struct cec_adapter *adap,
 	res = cec_devnode_register(&adap->devnode, adap->owner);
 	if (res) {
 #ifdef CONFIG_MEDIA_CEC_RC
-		/* Note: rc_unregister also calls rc_free */
 		rc_unregister_device(adap->rc);
+		rc_free_device(adap->rc);
 		adap->rc = NULL;
 #endif
 		return res;
drivers/media/common/siano/smsir.c +1 -0
index d85c78c104b990..5f4c0aa7a0d72a 100644
@@ -92,6 +92,7 @@ int sms_ir_init(struct smscore_device_t *coredev)
 void sms_ir_exit(struct smscore_device_t *coredev)
 {
 	rc_unregister_device(coredev->ir.dev);
+	rc_free_device(coredev->ir.dev);
 
 	pr_debug("\n");
 }
drivers/media/i2c/ir-kbd-i2c.c +2 -0
index a8026f0f980f98..943e761c149643 100644
@@ -355,6 +355,7 @@ static void ir_work(struct work_struct *work)
 		mutex_unlock(&ir->lock);
 		if (rc == -ENODEV) {
 			rc_unregister_device(ir->rc);
+			rc_free_device(ir->rc);
 			ir->rc = NULL;
 			return;
 		}
@@ -972,6 +973,7 @@ static void ir_remove(struct i2c_client *client)
 	i2c_unregister_device(ir->tx_c);
 
 	rc_unregister_device(ir->rc);
+	rc_free_device(ir->rc);
 }
 
 static const struct i2c_device_id ir_kbd_id[] = {
drivers/media/pci/bt8xx/bttv-input.c +2 -1
index 41226f1d0e5b64..d70e6282c48b2e 100644
@@ -572,8 +572,9 @@ void bttv_input_fini(struct bttv *btv)
 	if (btv->remote == NULL)
 		return;
 
-	bttv_ir_stop(btv);
 	rc_unregister_device(btv->remote->dev);
+	bttv_ir_stop(btv);
+	rc_free_device(btv->remote->dev);
 	kfree(btv->remote);
 	btv->remote = NULL;
 }
drivers/media/pci/cx23885/cx23885-input.c +1 -0
index d2e84c6457e0ab..722329ef3fd2cc 100644
@@ -402,6 +402,7 @@ void cx23885_input_fini(struct cx23885_dev *dev)
 	if (dev->kernel_ir == NULL)
 		return;
 	rc_unregister_device(dev->kernel_ir->rc);
+	rc_free_device(dev->kernel_ir->rc);
 	kfree(dev->kernel_ir->phys);
 	kfree(dev->kernel_ir->name);
 	kfree(dev->kernel_ir);
drivers/media/pci/cx88/cx88-input.c +2 -1
index a04a1d33fadb1b..74a8769dd6c79c 100644
@@ -510,8 +510,9 @@ int cx88_ir_fini(struct cx88_core *core)
 	if (!ir)
 		return 0;
 
-	cx88_ir_stop(core);
 	rc_unregister_device(ir->dev);
+	cx88_ir_stop(core);
+	rc_free_device(ir->dev);
 	kfree(ir);
 
 	/* done */
drivers/media/pci/dm1105/dm1105.c +1 -0
index 9e9c7c071accce..e1185aa669f480 100644
@@ -763,6 +763,7 @@ static int dm1105_ir_init(struct dm1105_dev *dm1105)
 static void dm1105_ir_exit(struct dm1105_dev *dm1105)
 {
 	rc_unregister_device(dm1105->ir.dev);
+	rc_free_device(dm1105->ir.dev);
 }
 
 static int dm1105_hw_init(struct dm1105_dev *dev)
drivers/media/pci/mantis/mantis_input.c +1 -0
index 34c0d979240fda..edb4cacf55d229 100644
@@ -72,5 +72,6 @@ EXPORT_SYMBOL_GPL(mantis_input_init);
 void mantis_input_exit(struct mantis_pci *mantis)
 {
 	rc_unregister_device(mantis->rc);
+	rc_free_device(mantis->rc);
 }
 EXPORT_SYMBOL_GPL(mantis_input_exit);
drivers/media/pci/saa7134/saa7134-input.c +1 -0
index 8610eb473b39e1..8a0f26d94d1de8 100644
@@ -834,6 +834,7 @@ void saa7134_input_fini(struct saa7134_dev *dev)
 		return;
 
 	rc_unregister_device(dev->remote->dev);
+	rc_free_device(dev->remote->dev);
 	kfree(dev->remote);
 	dev->remote = NULL;
 }
drivers/media/pci/smipcie/smipcie-ir.c +1 -0
index c0604d9c70119a..0bbe4fa2d5a84e 100644
@@ -181,5 +181,6 @@ void smi_ir_exit(struct smi_dev *dev)
 
 	rc_unregister_device(rc_dev);
 	smi_ir_stop(ir);
+	rc_free_device(rc_dev);
 	ir->rc_dev = NULL;
 }
drivers/media/pci/ttpci/budget-ci.c +1 -0
index 66e1a004ee431c..2ad30f91bcd9ee 100644
@@ -247,6 +247,7 @@ static void msp430_ir_deinit(struct budget_ci *budget_ci)
 	tasklet_kill(&budget_ci->ir.msp430_irq_tasklet);
 
 	rc_unregister_device(budget_ci->ir.dev);
+	rc_free_device(budget_ci->ir.dev);
 }
 
 static int ciintf_read_attribute_mem(struct dvb_ca_en50221 *ca, int slot, int address)
drivers/media/rc/ati_remote.c +3 -3
index fff4dd48eacad2..1d68834ecd0b15 100644
@@ -921,7 +921,6 @@ static int ati_remote_probe(struct usb_interface *interface,
 	input_free_device(input_dev);
  exit_unregister_device:
 	rc_unregister_device(rc_dev);
-	rc_dev = NULL;
  exit_kill_urbs:
 	usb_kill_urb(ati_remote->irq_urb);
 	usb_kill_urb(ati_remote->out_urb);
@@ -941,18 +940,19 @@ static void ati_remote_disconnect(struct usb_interface *interface)
 	struct ati_remote *ati_remote;
 
 	ati_remote = usb_get_intfdata(interface);
-	usb_set_intfdata(interface, NULL);
 	if (!ati_remote) {
 		dev_warn(&interface->dev, "%s - null device?\n", __func__);
 		return;
 	}
 
+	rc_unregister_device(ati_remote->rdev);
+	usb_set_intfdata(interface, NULL);
 	usb_kill_urb(ati_remote->irq_urb);
 	usb_kill_urb(ati_remote->out_urb);
 	if (ati_remote->idev)
 		input_unregister_device(ati_remote->idev);
-	rc_unregister_device(ati_remote->rdev);
 	ati_remote_free_buffers(ati_remote);
+	rc_free_device(ati_remote->rdev);
 	kfree(ati_remote);
 }
 
drivers/media/rc/ene_ir.c +1 -1
index 11ee21a7db8f00..9140e4f28c9955 100644
@@ -1093,7 +1093,6 @@ static int ene_probe(struct pnp_dev *pnp_dev, const struct pnp_device_id *id)
 	release_region(dev->hw_io, ENE_IO_SIZE);
 exit_unregister_device:
 	rc_unregister_device(rdev);
-	rdev = NULL;
 exit_free_dev_rdev:
 	rc_free_device(rdev);
 	kfree(dev);
@@ -1113,6 +1112,7 @@ static void ene_remove(struct pnp_dev *pnp_dev)
 	ene_rx_restore_hw_buffer(dev);
 	spin_unlock_irqrestore(&dev->hw_lock, flags);
 
+	rc_free_device(dev->rdev);
 	free_irq(dev->irq, dev);
 	release_region(dev->hw_io, ENE_IO_SIZE);
 	kfree(dev);
drivers/media/rc/fintek-cir.c +2 -1
index 3fb0968efd57d3..9b789097cdd4c3 100644
@@ -568,6 +568,7 @@ static void fintek_remove(struct pnp_dev *pdev)
 	struct fintek_dev *fintek = pnp_get_drvdata(pdev);
 	unsigned long flags;
 
+	rc_unregister_device(fintek->rdev);
 	spin_lock_irqsave(&fintek->fintek_lock, flags);
 	/* disable CIR */
 	fintek_disable_cir(fintek);
@@ -580,7 +581,7 @@ static void fintek_remove(struct pnp_dev *pdev)
 	free_irq(fintek->cir_irq, fintek);
 	release_region(fintek->cir_addr, fintek->cir_port_len);
 
-	rc_unregister_device(fintek->rdev);
+	rc_free_device(fintek->rdev);
 
 	kfree(fintek);
 }
drivers/media/rc/igorplugusb.c +1 -0
index f3616607d4f52b..8bf059b9a31b45 100644
@@ -247,6 +247,7 @@ static void igorplugusb_disconnect(struct usb_interface *intf)
 	usb_set_intfdata(intf, NULL);
 	usb_unpoison_urb(ir->urb);
 	usb_free_urb(ir->urb);
+	rc_free_device(ir->rc);
 	kfree(ir->buf_in);
 	kfree(ir->request);
 }
drivers/media/rc/iguanair.c +1 -0
index 8af94246e5916e..7bd6dd7254157a 100644
@@ -500,6 +500,7 @@ static void iguanair_disconnect(struct usb_interface *intf)
 	usb_set_intfdata(intf, NULL);
 	usb_kill_urb(ir->urb_in);
 	usb_kill_urb(ir->urb_out);
+	rc_free_device(ir->rc);
 	usb_free_urb(ir->urb_in);
 	usb_free_urb(ir->urb_out);
 	usb_free_coherent(ir->udev, MAX_IN_PACKET, ir->buf_in, ir->dma_in);
drivers/media/rc/img-ir/img-ir-hw.c +2 -1
index 5da7479c1793b1..07f41372976eaf 100644
@@ -1117,9 +1117,10 @@ void img_ir_remove_hw(struct img_ir_priv *priv)
 	struct rc_dev *rdev = hw->rdev;
 	if (!rdev)
 		return;
+	rc_unregister_device(rdev);
 	img_ir_set_decoder(priv, NULL, 0);
 	hw->rdev = NULL;
-	rc_unregister_device(rdev);
+	rc_free_device(rdev);
 #ifdef CONFIG_COMMON_CLK
 	if (!IS_ERR(priv->clk))
 		clk_notifier_unregister(priv->clk, &hw->clk_nb);
drivers/media/rc/img-ir/img-ir-raw.c +2 -1
index 8b0bdd9603b3c5..533d40dae54224 100644
@@ -136,6 +136,7 @@ void img_ir_remove_raw(struct img_ir_priv *priv)
 	if (!rdev)
 		return;
 
+	rc_unregister_device(rdev);
 	/* switch off and disable raw (edge) interrupts */
 	spin_lock_irq(&priv->lock);
 	raw->rdev = NULL;
@@ -145,7 +146,7 @@ void img_ir_remove_raw(struct img_ir_priv *priv)
 	img_ir_write(priv, IMG_IR_IRQ_CLEAR, IMG_IR_IRQ_EDGE);
 	spin_unlock_irq(&priv->lock);
 
-	rc_unregister_device(rdev);
+	rc_free_device(rdev);
 
 	del_timer_sync(&raw->timer);
 }
drivers/media/rc/imon.c +2 -1
index bb4aabb08c06ef..69e118863aa67c 100644
@@ -2546,9 +2546,10 @@ static void imon_disconnect(struct usb_interface *interface)
 
 	if (ifnum == 0) {
 		ictx->dev_present_intf0 = false;
+		rc_unregister_device(ictx->rdev);
 		usb_kill_urb(ictx->rx_urb_intf0);
 		input_unregister_device(ictx->idev);
-		rc_unregister_device(ictx->rdev);
+		rc_free_device(ictx->rdev);
 		if (ictx->display_supported) {
 			if (ictx->display_type == IMON_DISPLAY_TYPE_LCD)
 				usb_deregister_dev(interface, &imon_lcd_class);
drivers/media/rc/ir-hix5hd2.c +1 -1
index 0034f615b4660e..df347d2fb0ead3 100644
@@ -331,7 +331,6 @@ static int hix5hd2_ir_probe(struct platform_device *pdev)
 
 regerr:
 	rc_unregister_device(rdev);
-	rdev = NULL;
 clkerr:
 	clk_disable_unprepare(priv->clock);
 err:
@@ -346,6 +345,7 @@ static void hix5hd2_ir_remove(struct platform_device *pdev)
 
 	clk_disable_unprepare(priv->clock);
 	rc_unregister_device(priv->rdev);
+	rc_free_device(priv->rdev);
 }
 
 #ifdef CONFIG_PM_SLEEP
drivers/media/rc/ir_toy.c +1 -0
index 69e630d85262f6..490de29b7ffbef 100644
@@ -536,6 +536,7 @@ static void irtoy_disconnect(struct usb_interface *intf)
 	usb_free_urb(ir->urb_out);
 	usb_kill_urb(ir->urb_in);
 	usb_free_urb(ir->urb_in);
+	rc_free_device(ir->rc);
 	kfree(ir->in);
 	kfree(ir->out);
 	kfree(ir);
drivers/media/rc/ite-cir.c +1 -1
index fcfadd7ea31cf3..c584dc6bfd7b48 100644
@@ -1415,7 +1415,6 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
 	release_region(itdev->cir_addr, itdev->params->io_region_size);
 exit_unregister_device:
 	rc_unregister_device(rdev);
-	rdev = NULL;
 exit_free_dev_rdev:
 	rc_free_device(rdev);
 	kfree(itdev);
@@ -1440,6 +1439,7 @@ static void ite_remove(struct pnp_dev *pdev)
 	release_region(dev->cir_addr, dev->params->io_region_size);
 
 	rc_unregister_device(dev->rdev);
+	rc_free_device(dev->rdev);
 
 	kfree(dev);
 }
drivers/media/rc/mceusb.c +1 -0
index c76ba24c1f5595..4115a46929c473 100644
@@ -1858,6 +1858,7 @@ static void mceusb_dev_disconnect(struct usb_interface *intf)
 	usb_free_urb(ir->urb_in);
 	usb_free_coherent(dev, ir->len_in, ir->buf_in, ir->dma_in);
 	usb_put_dev(dev);
+	rc_free_device(ir->rc);
 
 	kfree(ir);
 }
drivers/media/rc/rc-ir-raw.c +0 -5
index 16e33d7eaaa2d8..dd70f8ad526642 100644
@@ -647,9 +647,6 @@ int ir_raw_event_register(struct rc_dev *dev)
 
 void ir_raw_event_free(struct rc_dev *dev)
 {
-	if (!dev)
-		return;
-
 	kfree(dev->raw);
 	dev->raw = NULL;
 }
@@ -673,8 +670,6 @@ void ir_raw_event_unregister(struct rc_dev *dev)
 
 	lirc_bpf_free(dev);
 
-	ir_raw_event_free(dev);
-
 	/*
 	 * A user can be calling bpf(BPF_PROG_{QUERY|ATTACH|DETACH}), so
 	 * ensure that the raw member is null on unlock; this is how
drivers/media/rc/rc-loopback.c +1 -0
index b356041c5c00e7..79073aaabd9175 100644
@@ -264,6 +264,7 @@ static int __init loop_init(void)
 static void __exit loop_exit(void)
 {
 	rc_unregister_device(loopdev.dev);
+	rc_free_device(loopdev.dev);
 }
 
 module_init(loop_init);
drivers/media/rc/rc-main.c +1 -5
index 6bdad6341844f5..10464f7942304e 100644
@@ -1611,6 +1611,7 @@ static void rc_dev_release(struct device *device)
 {
 	struct rc_dev *dev = to_rc_dev(device);
 
+	ir_raw_event_free(dev);
 	kfree(dev);
 }
 
@@ -1773,7 +1774,6 @@ struct rc_dev *devm_rc_allocate_device(struct device *dev,
 	}
 
 	rc->dev.parent = dev;
-	rc->managed_alloc = true;
 	*dr = rc;
 	devres_add(dev, dr);
 
@@ -2042,11 +2042,7 @@ void rc_unregister_device(struct rc_dev *dev)
 	device_del(&dev->dev);
 
 	ida_free(&rc_ida, dev->minor);
-
-	if (!dev->managed_alloc)
-		rc_free_device(dev);
 }
-
 EXPORT_SYMBOL_GPL(rc_unregister_device);
 
 /*
drivers/media/rc/redrat3.c +3 -1
index 880981e1c507e1..d47f6e983ec67d 100644
@@ -1133,11 +1133,13 @@ static void redrat3_dev_disconnect(struct usb_interface *intf)
 {
 	struct usb_device *udev = interface_to_usbdev(intf);
 	struct redrat3_dev *rr3 = usb_get_intfdata(intf);
+	struct rc_dev *rc = rr3->rc;
 
 	usb_set_intfdata(intf, NULL);
-	rc_unregister_device(rr3->rc);
+	rc_unregister_device(rc);
 	led_classdev_unregister(&rr3->led);
 	redrat3_delete(rr3, udev);
+	rc_free_device(rc);
 }
 
 static int redrat3_dev_suspend(struct usb_interface *intf, pm_message_t message)
drivers/media/rc/st_rc.c +1 -1
index 8a9f31e15b0c01..bac1ac4e0f3a22 100644
@@ -202,6 +202,7 @@ static void st_rc_remove(struct platform_device *pdev)
 	device_init_wakeup(&pdev->dev, false);
 	clk_disable_unprepare(rc_dev->sys_clock);
 	rc_unregister_device(rc_dev->rdev);
+	rc_free_device(rc_dev->rdev);
 }
 
 static int st_rc_open(struct rc_dev *rdev)
@@ -333,7 +334,6 @@ static int st_rc_probe(struct platform_device *pdev)
 	return ret;
 rcerr:
 	rc_unregister_device(rdev);
-	rdev = NULL;
 clkerr:
 	clk_disable_unprepare(rc_dev->sys_clock);
 err:
drivers/media/rc/streamzap.c +4 -3
index 8e9b156e430022..8c85b9f30a3a96 100644
@@ -392,15 +392,16 @@ static void streamzap_disconnect(struct usb_interface *interface)
 	struct streamzap_ir *sz = usb_get_intfdata(interface);
 	struct usb_device *usbdev = interface_to_usbdev(interface);
 
-	usb_set_intfdata(interface, NULL);
-
 	if (!sz)
 		return;
 
-	usb_kill_urb(sz->urb_in);
 	rc_unregister_device(sz->rdev);
+	usb_set_intfdata(interface, NULL);
+
+	usb_kill_urb(sz->urb_in);
 	usb_free_urb(sz->urb_in);
 	usb_free_coherent(usbdev, sz->buf_in_len, sz->buf_in, sz->dma_in);
+	rc_free_device(sz->rdev);
 
 	kfree(sz);
 }
drivers/media/rc/sunxi-cir.c +1 -0
index bf58c965ead8cf..e2477e724637fa 100644
@@ -370,6 +370,7 @@ static void sunxi_ir_remove(struct platform_device *pdev)
 	struct sunxi_ir *ir = platform_get_drvdata(pdev);
 
 	rc_unregister_device(ir->rc);
+	rc_free_device(ir->rc);
 	sunxi_ir_hw_exit(&pdev->dev);
 }
 
drivers/media/rc/ttusbir.c +1 -1
index dde446a95eaa93..a670d4b008cb0d 100644
@@ -336,7 +336,6 @@ static int ttusbir_probe(struct usb_interface *intf,
 	return 0;
 out3:
 	rc_unregister_device(rc);
-	rc = NULL;
 out2:
 	led_classdev_unregister(&tt->led);
 out:
@@ -378,6 +377,7 @@ static void ttusbir_disconnect(struct usb_interface *intf)
 	usb_kill_urb(tt->bulk_urb);
 	usb_free_urb(tt->bulk_urb);
 	kfree(tt->bulk_buffer);
+	rc_free_device(tt->rc);
 	usb_set_intfdata(intf, NULL);
 	kfree(tt);
 }
drivers/media/rc/winbond-cir.c +1 -1
index 25884a79985c8a..14d8b58e283980 100644
@@ -1132,7 +1132,6 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
 	release_region(data->wbase, WAKEUP_IOMEM_LEN);
 exit_unregister_device:
 	rc_unregister_device(data->dev);
-	data->dev = NULL;
 exit_free_rc:
 	rc_free_device(data->dev);
 exit_unregister_led:
@@ -1163,6 +1162,7 @@ wbcir_remove(struct pnp_dev *device)
 	wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x00, 0x07);
 
 	rc_unregister_device(data->dev);
+	rc_free_device(data->dev);
 
 	led_classdev_unregister(&data->led);
 
drivers/media/rc/xbox_remote.c +3 -2
index 0c9c855ced729c..80b7c247932a8f 100644
@@ -283,14 +283,15 @@ static void xbox_remote_disconnect(struct usb_interface *interface)
 	struct xbox_remote *xbox_remote;
 
 	xbox_remote = usb_get_intfdata(interface);
-	usb_set_intfdata(interface, NULL);
 	if (!xbox_remote) {
 		dev_warn(&interface->dev, "%s - null device?\n", __func__);
 		return;
 	}
 
-	usb_kill_urb(xbox_remote->irq_urb);
 	rc_unregister_device(xbox_remote->rdev);
+	usb_set_intfdata(interface, NULL);
+	usb_kill_urb(xbox_remote->irq_urb);
+	rc_free_device(xbox_remote->rdev);
 	usb_free_urb(xbox_remote->irq_urb);
 	kfree(xbox_remote->inbuf);
 	kfree(xbox_remote);
drivers/media/usb/au0828/au0828-input.c +1 -0
index 3d3368202cd018..283ad2c6288cd5 100644
@@ -357,6 +357,7 @@ void au0828_rc_unregister(struct au0828_dev *dev)
 		return;
 
 	rc_unregister_device(ir->rc);
+	rc_free_device(ir->rc);
 
 	/* done */
 	kfree(ir);
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c +1 -0
index f1c79f351ec8de..17e8961179d14b 100644
@@ -187,6 +187,7 @@ static int dvb_usbv2_remote_exit(struct dvb_usb_device *d)
 	if (d->rc_dev) {
 		cancel_delayed_work_sync(&d->rc_query_work);
 		rc_unregister_device(d->rc_dev);
+		rc_free_device(d->rc_dev);
 		d->rc_dev = NULL;
 	}
 
drivers/media/usb/dvb-usb/dvb-usb-remote.c +4 -2
index 65e2c9e2cdc99f..6dc11718dfb985 100644
@@ -347,10 +347,12 @@ int dvb_usb_remote_exit(struct dvb_usb_device *d)
 {
 	if (d->state & DVB_USB_STATE_REMOTE) {
 		cancel_delayed_work_sync(&d->rc_query_work);
-		if (d->props.rc.mode == DVB_RC_LEGACY)
+		if (d->props.rc.mode == DVB_RC_LEGACY) {
 			input_unregister_device(d->input_dev);
-		else
+		} else {
 			rc_unregister_device(d->rc_dev);
+			rc_free_device(d->rc_dev);
+		}
 	}
 	d->state &= ~DVB_USB_STATE_REMOTE;
 	return 0;
drivers/media/usb/em28xx/em28xx-input.c +1 -0
index 5f3b00869bdbc9..26f333b5be7325 100644
@@ -853,6 +853,7 @@ static int em28xx_ir_fini(struct em28xx *dev)
 		goto ref_put;
 
 	rc_unregister_device(ir->rc);
+	rc_free_device(ir->rc);
 
 	kfree(ir->i2c_client);
 
drivers/staging/media/av7110/av7110_ir.c +1 -0
index a851ba328e4a3e..c0a32325e2cc98 100644
@@ -152,6 +152,7 @@ int av7110_ir_init(struct av7110 *av7110)
 void av7110_ir_exit(struct av7110 *av7110)
 {
 	rc_unregister_device(av7110->ir.rcdev);
+	rc_free_device(av7110->ir.rcdev);
 }
 
 //MODULE_AUTHOR("Holger Waechtler <[email protected]>, Oliver Endriss <[email protected]>");
include/media/rc-core.h +0 -2
index 803349599c272b..b487b0d5ffd1d0 100644
@@ -81,7 +81,6 @@ struct lirc_fh {
 /**
  * struct rc_dev - represents a remote control device
  * @dev: driver model's view of this device
- * @managed_alloc: devm_rc_allocate_device was used to create rc_dev
  * @sysfs_groups: sysfs attribute groups
  * @device_name: name of the rc child device
  * @input_phys: physical path to the input child device
@@ -157,7 +156,6 @@ struct lirc_fh {
  */
 struct rc_dev {
 	struct device			dev;
-	bool				managed_alloc;
 	const struct attribute_group	*sysfs_groups[5];
 	const char			*device_name;
 	const char			*input_phys;
Signature · 1 line
2.53.0
author maintainer
#78 lore raw

PATCH 64/452 media: rc: ttusbir: fix inverted error logic

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Oliver Neukum <[email protected]>

[ Upstream commit 646ebdd3105809d84ed04aa9e92e47e89cc44502 ]

We have to report ENOMEM if no buffer is allocated. Typo dropped a "!". Restore it.

Fixes 50acaad3d202 ("media: rc: ttusbir: respect DMA coherency rules")
---
 drivers/media/rc/ttusbir.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/rc/ttusbir.c +1 -1
index a670d4b008cb0d..3452b5aefd2848 100644
@@ -191,7 +191,7 @@ static int ttusbir_probe(struct usb_interface *intf,
 	tt = kzalloc(sizeof(*tt), GFP_KERNEL);
 	buffer = kzalloc(5, GFP_KERNEL);
 	rc = rc_allocate_device(RC_DRIVER_IR_RAW);
-	if (!tt || !rc || buffer) {
+	if (!tt || !rc || !buffer) {
 		ret = -ENOMEM;
 		goto out;
 	}
Signature · 1 line
2.53.0
author maintainer
#79 lore raw

PATCH 65/452 drm/fbdev-helper: Set and clear VGA switcheroo client from fb_info

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Thomas Zimmermann <[email protected]>

[ Upstream commit 02257549daf7ff839e2be6d4f3cac975e522fd7a ]

Call vga_switcheroo_client_fb_set() with the PCI device from the instance of struct fb_info. All fbdev clients now run these calls. For non-PCI devices or drivers without vga-switcheroo, this does nothing. For i915 and radeon, it allows these drivers to use a common fbdev client.

The device is the same as the one stored in struct drm_client and struct drm_fb_helper, so there is no difference in behavior. Some NULL-pointer checks are being removed, where those pointers cannot be NULL.

v4:
- clarify call semantics for drm_fb_helper_unregister_info() (Javier)

[ The variable 'dev' in the function drm_fb_helper_single_fb_probe() is unused; remove it in v6.6. ]

---
 drivers/gpu/drm/drm_fb_helper.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)
drivers/gpu/drm/drm_fb_helper.c +12 -6
index b507c1c008a3e9..eee7b56d441f71 100644
@@ -567,7 +567,7 @@ EXPORT_SYMBOL(drm_fb_helper_release_info);
 
 /**
  * drm_fb_helper_unregister_info - unregister fb_info framebuffer device
- * @fb_helper: driver-allocated fbdev helper, can be NULL
+ * @fb_helper: driver-allocated fbdev helper, must not be NULL
  *
  * A wrapper around unregister_framebuffer, to release the fb_info
  * framebuffer device. This must be called before releasing all resources for
@@ -575,8 +575,12 @@ EXPORT_SYMBOL(drm_fb_helper_release_info);
  */
 void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper)
 {
-	if (fb_helper && fb_helper->info)
-		unregister_framebuffer(fb_helper->info);
+	struct fb_info *info = fb_helper->info;
+	struct device *dev = info->device;
+
+	if (dev_is_pci(dev))
+		vga_switcheroo_client_fb_set(to_pci_dev(dev), NULL);
+	unregister_framebuffer(fb_helper->info);
 }
 EXPORT_SYMBOL(drm_fb_helper_unregister_info);
 
@@ -1668,8 +1672,8 @@ static int drm_fb_helper_find_sizes(struct drm_fb_helper *fb_helper,
 static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper)
 {
 	struct drm_client_dev *client = &fb_helper->client;
-	struct drm_device *dev = fb_helper->dev;
 	struct drm_fb_helper_surface_size sizes;
+	struct fb_info *info;
 	int ret;
 
 	ret = drm_fb_helper_find_sizes(fb_helper, &sizes);
@@ -1687,9 +1691,11 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper)
 
 	strcpy(fb_helper->fb->comm, "[fbcon]");
 
+	info = fb_helper->info;
+
 	/* Set the fb info for vgaswitcheroo clients. Does nothing otherwise. */
-	if (dev_is_pci(dev->dev))
-		vga_switcheroo_client_fb_set(to_pci_dev(dev->dev), fb_helper->info);
+	if (dev_is_pci(info->device))
+		vga_switcheroo_client_fb_set(to_pci_dev(info->device), info);
 
 	return 0;
 }
Signature · 1 line
2.53.0
author maintainer
#80 lore raw

PATCH 66/452 drm, fbcon, vga_switcheroo: Avoid race condition in fbcon setup

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Thomas Zimmermann <[email protected]>

[ Upstream commit eb76d0f5553575599561010f24c277cc5b31d003 ]

Protect vga_switcheroo_client_fb_set() with console lock. Avoids OOB access in fbcon_remap_all(). Without holding the console lock the call races with switching outputs.

VGA switcheroo calls fbcon_remap_all() when switching clients. The fbcon function uses struct fb_info.node, which is set by register_framebuffer(). As the fb-helper code currently sets up VGA switcheroo before registering the framebuffer, the value of node is -1 and therefore not a legal value. For example, fbcon uses the value within set_con2fb_map() [1] as an index into an array.

Moving vga_switcheroo_client_fb_set() after register_framebuffer() can result in VGA switching that does not switch fbcon correctly.

Therefore move vga_switcheroo_client_fb_set() under fbcon_fb_registered(), which already holds the console lock. Fbdev calls fbcon_fb_registered() from within register_framebuffer(). Serializes the helper with VGA switcheroo's call to fbcon_remap_all().

Although vga_switcheroo_client_fb_set() takes an instance of struct fb_info as parameter, it really only needs the contained fbcon state. Moving the call to fbcon initialization is therefore cleaner than before. Only amdgpu, i915, nouveau and radeon support vga_switcheroo. For all other drivers, this change does nothing.

---
 drivers/gpu/drm/drm_fb_helper.c  | 14 --------------
 drivers/video/fbdev/core/fbcon.c |  9 +++++++++
 2 files changed, 9 insertions(+), 14 deletions(-)
drivers/gpu/drm/drm_fb_helper.c +0 -14
index eee7b56d441f71..9691c93f19a0dd 100644
@@ -30,9 +30,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/console.h>
-#include <linux/pci.h>
 #include <linux/sysrq.h>
-#include <linux/vga_switcheroo.h>
 
 #include <drm/drm_atomic.h>
 #include <drm/drm_drv.h>
@@ -575,11 +573,6 @@ EXPORT_SYMBOL(drm_fb_helper_release_info);
  */
 void drm_fb_helper_unregister_info(struct drm_fb_helper *fb_helper)
 {
-	struct fb_info *info = fb_helper->info;
-	struct device *dev = info->device;
-
-	if (dev_is_pci(dev))
-		vga_switcheroo_client_fb_set(to_pci_dev(dev), NULL);
 	unregister_framebuffer(fb_helper->info);
 }
 EXPORT_SYMBOL(drm_fb_helper_unregister_info);
@@ -1673,7 +1666,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper)
 {
 	struct drm_client_dev *client = &fb_helper->client;
 	struct drm_fb_helper_surface_size sizes;
-	struct fb_info *info;
 	int ret;
 
 	ret = drm_fb_helper_find_sizes(fb_helper, &sizes);
@@ -1691,12 +1683,6 @@ static int drm_fb_helper_single_fb_probe(struct drm_fb_helper *fb_helper)
 
 	strcpy(fb_helper->fb->comm, "[fbcon]");
 
-	info = fb_helper->info;
-
-	/* Set the fb info for vgaswitcheroo clients. Does nothing otherwise. */
-	if (dev_is_pci(info->device))
-		vga_switcheroo_client_fb_set(to_pci_dev(info->device), info);
-
 	return 0;
 }
 
drivers/video/fbdev/core/fbcon.c +9 -0
index 703c4e851612c8..d1ac4e45eea68e 100644
@@ -64,6 +64,7 @@
 #include <linux/console.h>
 #include <linux/string.h>
 #include <linux/kd.h>
+#include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/fb.h>
 #include <linux/fbcon.h>
@@ -75,6 +76,7 @@
 #include <linux/interrupt.h>
 #include <linux/crc32.h> /* For counting font checksums */
 #include <linux/uaccess.h>
+#include <linux/vga_switcheroo.h>
 #include <asm/irq.h>
 
 #include "fbcon.h"
@@ -2914,6 +2916,9 @@ void fbcon_fb_unregistered(struct fb_info *info)
 
 	console_lock();
 
+	if (info->device && dev_is_pci(info->device))
+		vga_switcheroo_client_fb_set(to_pci_dev(info->device), NULL);
+
 	fbcon_registered_fb[info->node] = NULL;
 	fbcon_num_registered_fb--;
 
@@ -3047,6 +3052,10 @@ static int do_fb_registered(struct fb_info *info)
 		}
 	}
 
+	/* Set the fb info for vga_switcheroo clients. Does nothing otherwise. */
+	if (info->device && dev_is_pci(info->device))
+		vga_switcheroo_client_fb_set(to_pci_dev(info->device), info);
+
 	return ret;
 }
 
Signature · 1 line
2.53.0
author maintainer
#81 lore raw

PATCH 67/452 inet: frags: add inet_frag_queue_flush()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jakub Kicinski <[email protected]>

[ Upstream commit 1231eec6994be29d6bb5c303dfa54731ed9fc0e6 ]

Instead of exporting inet_frag_rbtree_purge() which requires that caller takes care of memory accounting, add a new helper. We will need to call it from a few places in the next patch.

---
 include/net/inet_frag.h  |  5 ++---
 net/ipv4/inet_fragment.c | 15 ++++++++++++---
 net/ipv4/ip_fragment.c   |  6 +-----
 3 files changed, 15 insertions(+), 11 deletions(-)
include/net/inet_frag.h +2 -3
index 5af6eb14c5db15..94edc0e130d2c4 100644
@@ -141,9 +141,8 @@ void inet_frag_kill(struct inet_frag_queue *q);
 void inet_frag_destroy(struct inet_frag_queue *q);
 struct inet_frag_queue *inet_frag_find(struct fqdir *fqdir, void *key);
 
-/* Free all skbs in the queue; return the sum of their truesizes. */
-unsigned int inet_frag_rbtree_purge(struct rb_root *root,
-				    enum skb_drop_reason reason);
+void inet_frag_queue_flush(struct inet_frag_queue *q,
+			   enum skb_drop_reason reason);
 
 static inline void inet_frag_put(struct inet_frag_queue *q)
 {
net/ipv4/inet_fragment.c +12 -3
index 496308c0238485..1e390d24f11440 100644
@@ -264,8 +264,8 @@ static void inet_frag_destroy_rcu(struct rcu_head *head)
 	kmem_cache_free(f->frags_cachep, q);
 }
 
-unsigned int inet_frag_rbtree_purge(struct rb_root *root,
-				    enum skb_drop_reason reason)
+static unsigned int
+inet_frag_rbtree_purge(struct rb_root *root, enum skb_drop_reason reason)
 {
 	struct rb_node *p = rb_first(root);
 	unsigned int sum = 0;
@@ -285,7 +285,16 @@ unsigned int inet_frag_rbtree_purge(struct rb_root *root,
 	}
 	return sum;
 }
-EXPORT_SYMBOL(inet_frag_rbtree_purge);
+
+void inet_frag_queue_flush(struct inet_frag_queue *q,
+			   enum skb_drop_reason reason)
+{
+	unsigned int sum;
+
+	sum = inet_frag_rbtree_purge(&q->rb_fragments, reason);
+	sub_frag_mem_limit(q->fqdir, sum);
+}
+EXPORT_SYMBOL(inet_frag_queue_flush);
 
 void inet_frag_destroy(struct inet_frag_queue *q)
 {
net/ipv4/ip_fragment.c +1 -5
index 484edc8513e4b7..7214d5bcc647e5 100644
@@ -253,16 +253,12 @@ static int ip_frag_too_far(struct ipq *qp)
 
 static int ip_frag_reinit(struct ipq *qp)
 {
-	unsigned int sum_truesize = 0;
-
 	if (!mod_timer(&qp->q.timer, jiffies + qp->q.fqdir->timeout)) {
 		refcount_inc(&qp->q.refcnt);
 		return -ETIMEDOUT;
 	}
 
-	sum_truesize = inet_frag_rbtree_purge(&qp->q.rb_fragments,
-					      SKB_DROP_REASON_FRAG_TOO_FAR);
-	sub_frag_mem_limit(qp->q.fqdir, sum_truesize);
+	inet_frag_queue_flush(&qp->q, SKB_DROP_REASON_FRAG_TOO_FAR);
 
 	qp->q.flags = 0;
 	qp->q.len = 0;
Signature · 1 line
2.53.0
author maintainer
#82 lore raw

PATCH 68/452 inet: frags: flush pending skbs in fqdir_pre_exit()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jakub Kicinski <[email protected]>

[ Upstream commit 006a5035b495dec008805df249f92c22c89c3d2e ]

We have been seeing occasional deadlocks on pernet_ops_rwsem since September in NIPA. The stuck task was usually modprobe (often loading a driver like ipvlan), trying to take the lock as a Writer. lockdep does not track readers for rwsems so the read wasn't obvious from the reports.

On closer inspection the Reader holding the lock was conntrack looping forever in nf_conntrack_cleanup_net_list(). Based on past experience with occasional NIPA crashes I looked thru the tests which run before the crash and noticed that the crash follows ip_defrag.sh. An immediate red flag. Scouring thru (de)fragmentation queues reveals skbs sitting around, holding conntrack references.

The problem is that since conntrack depends on nf_defrag_ipv6, nf_defrag_ipv6 will load first. Since nf_defrag_ipv6 loads first its netns exit hooks run _after_ conntrack's netns exit hook.

Flush all fragment queue SKBs during fqdir_pre_exit() to release conntrack references before conntrack cleanup runs. Also flush the queues in timer expiry handlers when they discover fqdir->dead is set, in case packet sneaks in while we're running the pre_exit flush.

The commit under Fixes is not exactly the culprit, but I think previously the timer firing would eventually unblock the spinning conntrack.

Fixes d5dd88794a13 ("inet: fix various use-after-free in defrags units")
---
 include/net/inet_frag.h  | 13 +------------
 include/net/ipv6_frag.h  |  9 ++++++---
 net/ipv4/inet_fragment.c | 36 ++++++++++++++++++++++++++++++++++++
 net/ipv4/ip_fragment.c   | 12 +++++++-----
 4 files changed, 50 insertions(+), 20 deletions(-)
include/net/inet_frag.h +1 -12
index 94edc0e130d2c4..fcabb34fff35de 100644
@@ -123,18 +123,7 @@ void inet_frags_fini(struct inet_frags *);
 
 int fqdir_init(struct fqdir **fqdirp, struct inet_frags *f, struct net *net);
 
-static inline void fqdir_pre_exit(struct fqdir *fqdir)
-{
-	/* Prevent creation of new frags.
-	 * Pairs with READ_ONCE() in inet_frag_find().
-	 */
-	WRITE_ONCE(fqdir->high_thresh, 0);
-
-	/* Pairs with READ_ONCE() in inet_frag_kill(), ip_expire()
-	 * and ip6frag_expire_frag_queue().
-	 */
-	WRITE_ONCE(fqdir->dead, true);
-}
+void fqdir_pre_exit(struct fqdir *fqdir);
 void fqdir_exit(struct fqdir *fqdir);
 
 void inet_frag_kill(struct inet_frag_queue *q);
include/net/ipv6_frag.h +6 -3
index 7321ffe3a108c1..df61b98b521531 100644
@@ -68,9 +68,6 @@ ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq)
 	struct sk_buff *head;
 
 	rcu_read_lock();
-	/* Paired with the WRITE_ONCE() in fqdir_pre_exit(). */
-	if (READ_ONCE(fq->q.fqdir->dead))
-		goto out_rcu_unlock;
 	spin_lock(&fq->q.lock);
 
 	if (fq->q.flags & INET_FRAG_COMPLETE)
@@ -79,6 +76,12 @@ ip6frag_expire_frag_queue(struct net *net, struct frag_queue *fq)
 	fq->q.flags |= INET_FRAG_DROP;
 	inet_frag_kill(&fq->q);
 
+	/* Paired with the WRITE_ONCE() in fqdir_pre_exit(). */
+	if (READ_ONCE(fq->q.fqdir->dead)) {
+		inet_frag_queue_flush(&fq->q, 0);
+		goto out;
+	}
+
 	dev = dev_get_by_index_rcu(net, fq->iif);
 	if (!dev)
 		goto out;
net/ipv4/inet_fragment.c +36 -0
index 1e390d24f11440..8cf88882d65e3e 100644
@@ -219,6 +219,41 @@ static int __init inet_frag_wq_init(void)
 
 pure_initcall(inet_frag_wq_init);
 
+void fqdir_pre_exit(struct fqdir *fqdir)
+{
+	struct inet_frag_queue *fq;
+	struct rhashtable_iter hti;
+
+	/* Prevent creation of new frags.
+	 * Pairs with READ_ONCE() in inet_frag_find().
+	 */
+	WRITE_ONCE(fqdir->high_thresh, 0);
+
+	/* Pairs with READ_ONCE() in inet_frag_kill(), ip_expire()
+	 * and ip6frag_expire_frag_queue().
+	 */
+	WRITE_ONCE(fqdir->dead, true);
+
+	rhashtable_walk_enter(&fqdir->rhashtable, &hti);
+	rhashtable_walk_start(&hti);
+
+	while ((fq = rhashtable_walk_next(&hti))) {
+		if (IS_ERR(fq)) {
+			if (PTR_ERR(fq) != -EAGAIN)
+				break;
+			continue;
+		}
+		spin_lock_bh(&fq->lock);
+		if (!(fq->flags & INET_FRAG_COMPLETE))
+			inet_frag_queue_flush(fq, 0);
+		spin_unlock_bh(&fq->lock);
+	}
+
+	rhashtable_walk_stop(&hti);
+	rhashtable_walk_exit(&hti);
+}
+EXPORT_SYMBOL(fqdir_pre_exit);
+
 void fqdir_exit(struct fqdir *fqdir)
 {
 	INIT_WORK(&fqdir->destroy_work, fqdir_work_fn);
@@ -291,6 +326,7 @@ void inet_frag_queue_flush(struct inet_frag_queue *q,
 {
 	unsigned int sum;
 
+	reason = reason ?: SKB_DROP_REASON_FRAG_REASM_TIMEOUT;
 	sum = inet_frag_rbtree_purge(&q->rb_fragments, reason);
 	sub_frag_mem_limit(q->fqdir, sum);
 }
net/ipv4/ip_fragment.c +7 -5
index 7214d5bcc647e5..f5b5aa036cc668 100644
@@ -148,11 +148,6 @@ static void ip_expire(struct timer_list *t)
 	net = qp->q.fqdir->net;
 
 	rcu_read_lock();
-
-	/* Paired with WRITE_ONCE() in fqdir_pre_exit(). */
-	if (READ_ONCE(qp->q.fqdir->dead))
-		goto out_rcu_unlock;
-
 	spin_lock(&qp->q.lock);
 
 	if (qp->q.flags & INET_FRAG_COMPLETE)
@@ -160,6 +155,13 @@ static void ip_expire(struct timer_list *t)
 
 	qp->q.flags |= INET_FRAG_DROP;
 	ipq_kill(qp);
+
+	/* Paired with WRITE_ONCE() in fqdir_pre_exit(). */
+	if (READ_ONCE(qp->q.fqdir->dead)) {
+		inet_frag_queue_flush(&qp->q, 0);
+		goto out;
+	}
+
 	__IP_INC_STATS(net, IPSTATS_MIB_REASMFAILS);
 	__IP_INC_STATS(net, IPSTATS_MIB_REASMTIMEOUT);
 
Signature · 1 line
2.53.0
author maintainer
#83 lore raw

PATCH 69/452 drm/i915/psr: Add defininitions for INTEL_WA_REGISTER_CAPS DPCD register

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jouni Högander <[email protected]>

commit fbceb39b536e40c2f7cc47ab42037bb7c2b7ced9 upstream.

EDP specification says:

"If either VSC SDP is unable to be transmitted 100 ns before the SU region, the Source device may optionally transmit the VSC SDP during the prior video scan line’s HBlank period There is a Intel specific drm dp register currently containing bits related how TCON can support PSR2 with SDP on prior line."

Unfortunately many panels are having problems in implementing this. So there is a custom Intel specific DPCD register (INTEL_WA_REGISTER_CAPS) to figure out if this is properly implemented on a panel or if panel doesn't require that 100 ns delay before the SU region. Here are the definitions in this custom DPCD address:

0 = Panel doesn't support SDP on prior line
1 = Panel supports SDP on prior line
2 = Panel doesn't have 100ns requirement
3 = Reserved

Add definitions for this new register and it's values into new header intel_dpcd.h.

v2: add INTEL_DPCD_ prefix to definitions

Bspec: 74741

(cherry picked from commit 1da1c9294825f08f622c473480d185680c2a3b75)
---
 drivers/gpu/drm/i915/display/intel_dpcd.h | 15 +++++++++++++++
 1 file changed, 15 insertions(+)
 create mode 100644 drivers/gpu/drm/i915/display/intel_dpcd.h
drivers/gpu/drm/i915/display/intel_dpcd.h new file +15 -0
new file mode 100644
index 00000000000000..4aea5326f2ed48
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * Copyright © 2026 Intel Corporation
+ */
+
+#ifndef __INTEL_DPCD_H__
+#define __INTEL_DPCD_H__
+
+#define INTEL_DPCD_INTEL_WA_REGISTER_CAPS					0x3f0
+# define INTEL_DPCD_INTEL_WA_REGISTER_CAPS_PSR2_EARLYSCANLINE_SDP_SUPPORT_MASK	REG_GENMASK(1, 0)
+# define INTEL_DPCD_INTEL_WA_REGISTER_CAPS_FALL_BACK_TO_PSR1			0
+# define INTEL_DPCD_INTEL_WA_REGISTER_CAPS_PSR2_WITH_EARLY_SCANLINE		1
+# define INTEL_DPCD_INTEL_WA_REGISTER_CAPS_PSR2_WITHOUT_EARLY_SCANLINE		2
+
+#endif /* __INTEL_DPCD_H__ */
Signature · 1 line
2.53.0
author maintainer
#84 lore raw

PATCH 70/452 drm/i915/psr: Read Intel DPCD workaround register

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jouni Högander <[email protected]>

commit f30bece421a4ae34359254e1dc2a187a42b6af9b upstream.

Read Intel DPCD workaround register and store it into intel_connector->dp.psr_caps. psr_caps was chosen as currently it contains only PSR workaround for PSR2 SDP on prior scanline implementation.

(cherry picked from commit c48ff24d0f4ab7ad696b2d35ad64ce7e049c668c)
---
 drivers/gpu/drm/i915/display/intel_display_types.h | 1 +
 drivers/gpu/drm/i915/display/intel_psr.c           | 7 +++++++
 2 files changed, 8 insertions(+)
drivers/gpu/drm/i915/display/intel_display_types.h +1 -0
index 1c23b186aff20c..3a228cfb1550f2 100644
@@ -1719,6 +1719,7 @@ struct intel_dp {
 	u8 lttpr_phy_caps[DP_MAX_LTTPR_COUNT][DP_LTTPR_PHY_CAP_SIZE];
 	u8 fec_capable;
 	u8 pcon_dsc_dpcd[DP_PCON_DSC_ENCODER_CAP_SIZE];
+	u8 intel_wa_dpcd;
 	/* source rates */
 	int num_source_rates;
 	const int *source_rates;
drivers/gpu/drm/i915/display/intel_psr.c +7 -0
index b0818dc8480edb..49842f7877f435 100644
@@ -31,6 +31,7 @@
 #include "intel_de.h"
 #include "intel_display_types.h"
 #include "intel_dp.h"
+#include "intel_dpcd.h"
 #include "intel_dp_aux.h"
 #include "intel_hdmi.h"
 #include "intel_psr.h"
@@ -528,6 +529,12 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
 			intel_dp_get_su_granularity(intel_dp);
 		}
 	}
+
+	if (intel_dp->psr.sink_psr2_support)
+		drm_dp_dpcd_read(&intel_dp->aux,
+				 INTEL_DPCD_INTEL_WA_REGISTER_CAPS,
+				 &intel_dp->intel_wa_dpcd,
+				 sizeof(intel_dp->intel_wa_dpcd));
 }
 
 static void hsw_psr_setup_aux(struct intel_dp *intel_dp)
Signature · 1 line
2.53.0
author maintainer
#85 lore raw

PATCH 71/452 drm/dp: Add eDP 1.5 bit definition

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Suraj Kandpal <[email protected]>

commit 5dfc37a6b77bf6beedbd30d70184b54e1a08ccac upstream.

Add the eDP revision bit value for 1.5.

Spec: eDPv1.5 Table 16-5

---
 include/drm/display/drm_dp.h | 1 +
 1 file changed, 1 insertion(+)
include/drm/display/drm_dp.h +1 -0
index e69cece404b3cf..861527bf9ccb7f 100644
@@ -959,6 +959,7 @@
 # define DP_EDP_14			    0x03
 # define DP_EDP_14a                         0x04    /* eDP 1.4a */
 # define DP_EDP_14b                         0x05    /* eDP 1.4b */
+# define DP_EDP_15			    0x06    /* eDP 1.5 */
 
 #define DP_EDP_GENERAL_CAP_1		    0x701
 # define DP_EDP_TCON_BACKLIGHT_ADJUSTMENT_CAP		(1 << 0)
Signature · 1 line
2.53.0
author maintainer
#86 lore raw

PATCH 72/452 drm/i915/psr: Apply Intel DPCD workaround when SDP on prior line used

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Jouni Högander <[email protected]>

commit 4703049f768fc1c1caac754134118bee1a3af189 upstream.

There is Intel specific workaround DPCD address containing workaround for case where SDP is on prior line. Apply this workaround according to values in the offset.

Fixes 61e887329e33 ("drm/i915/xelpd: Handle PSR2 SDP indication in the prior scanline")
Cc <[email protected]> # v5.15+
(cherry picked from commit c3fe899fbeac86ea4a5ca9dd845b2cbc0da46249)
---
 drivers/gpu/drm/i915/display/intel_psr.c | 27 +++++++++++++++++++++++-
 1 file changed, 26 insertions(+), 1 deletion(-)
drivers/gpu/drm/i915/display/intel_psr.c +26 -1
index 49842f7877f435..416686a6566bab 100644
@@ -1007,6 +1007,30 @@ static bool psr2_granularity_check(struct intel_dp *intel_dp,
 	return true;
 }
 
+static bool apply_scanline_indication_wa(struct intel_dp *intel_dp,
+					 struct intel_crtc_state *crtc_state)
+{
+	u8 early_scanline_support = intel_dp->intel_wa_dpcd &
+		INTEL_DPCD_INTEL_WA_REGISTER_CAPS_PSR2_EARLYSCANLINE_SDP_SUPPORT_MASK;
+
+	if (intel_dp->edp_dpcd[0] >= DP_EDP_15)
+		return true;
+
+	switch (early_scanline_support)	{
+	case INTEL_DPCD_INTEL_WA_REGISTER_CAPS_FALL_BACK_TO_PSR1:
+		crtc_state->req_psr2_sdp_prior_scanline = false;
+		return false;
+	case INTEL_DPCD_INTEL_WA_REGISTER_CAPS_PSR2_WITH_EARLY_SCANLINE:
+		return true;
+	case INTEL_DPCD_INTEL_WA_REGISTER_CAPS_PSR2_WITHOUT_EARLY_SCANLINE:
+		crtc_state->req_psr2_sdp_prior_scanline = false;
+		return true;
+	default:
+		MISSING_CASE(early_scanline_support);
+		return false;
+	}
+}
+
 static bool _compute_psr2_sdp_prior_scanline_indication(struct intel_dp *intel_dp,
 							struct intel_crtc_state *crtc_state)
 {
@@ -1028,7 +1052,8 @@ static bool _compute_psr2_sdp_prior_scanline_indication(struct intel_dp *intel_d
 		return false;
 
 	crtc_state->req_psr2_sdp_prior_scanline = true;
-	return true;
+
+	return apply_scanline_indication_wa(intel_dp, crtc_state);
 }
 
 static bool _compute_psr2_wake_times(struct intel_dp *intel_dp,
Signature · 1 line
2.53.0
author maintainer
#87 lore raw

PATCH 73/452 arm64: io: Rename ioremap_prot() to __ioremap_prot()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Will Deacon <[email protected]>

commit f6bf47ab32e0863df50f5501d207dcdddb7fc507 upstream.

Rename our ioremap_prot() implementation to __ioremap_prot() and convert all arch-internal callers over to the new function.

ioremap_prot() remains as a #define to __ioremap_prot() for generic_access_phys() and will be subsequently extended to handle user permissions in 'prot'.

---
 arch/arm64/include/asm/io.h | 8 +++++---
 arch/arm64/kernel/acpi.c    | 2 +-
 arch/arm64/mm/ioremap.c     | 8 ++++----
 3 files changed, 10 insertions(+), 8 deletions(-)
arch/arm64/include/asm/io.h +5 -3
index 3b694511b98f83..46d9f3f8290828 100644
@@ -139,14 +139,16 @@ extern void __memset_io(volatile void __iomem *, int, size_t);
  * I/O memory mapping functions.
  */
 
+void __iomem *__ioremap_prot(phys_addr_t phys, size_t size, pgprot_t prot);
+
 #define ioremap_prot ioremap_prot
 
 #define _PAGE_IOREMAP PROT_DEVICE_nGnRE
 
 #define ioremap_wc(addr, size)	\
-	ioremap_prot((addr), (size), PROT_NORMAL_NC)
+	__ioremap_prot((addr), (size), __pgprot(PROT_NORMAL_NC))
 #define ioremap_np(addr, size)	\
-	ioremap_prot((addr), (size), PROT_DEVICE_nGnRnE)
+	__ioremap_prot((addr), (size), __pgprot(PROT_DEVICE_nGnRnE))
 
 /*
  * io{read,write}{16,32,64}be() macros
@@ -167,7 +169,7 @@ static inline void __iomem *ioremap_cache(phys_addr_t addr, size_t size)
 	if (pfn_is_map_memory(__phys_to_pfn(addr)))
 		return (void __iomem *)__phys_to_virt(addr);
 
-	return ioremap_prot(addr, size, PROT_NORMAL);
+	return __ioremap_prot(addr, size, __pgprot(PROT_NORMAL));
 }
 
 /*
arch/arm64/kernel/acpi.c +1 -1
index dba8fcec7f33d6..0b06e6c2ebc4de 100644
@@ -352,7 +352,7 @@ void __iomem *acpi_os_ioremap(acpi_physical_address phys, acpi_size size)
 				prot = __acpi_get_writethrough_mem_attribute();
 		}
 	}
-	return ioremap_prot(phys, size, pgprot_val(prot));
+	return __ioremap_prot(phys, size, prot);
 }
 
 /*
arch/arm64/mm/ioremap.c +4 -4
index 269f2f63ab7dc4..49fd31e33c3146 100644
@@ -3,8 +3,8 @@
 #include <linux/mm.h>
 #include <linux/io.h>
 
-void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
-			   unsigned long prot)
+void __iomem *__ioremap_prot(phys_addr_t phys_addr, size_t size,
+			     pgprot_t pgprot)
 {
 	unsigned long last_addr = phys_addr + size - 1;
 
@@ -16,9 +16,9 @@ void __iomem *ioremap_prot(phys_addr_t phys_addr, size_t size,
 	if (WARN_ON(pfn_is_map_memory(__phys_to_pfn(phys_addr))))
 		return NULL;
 
-	return generic_ioremap_prot(phys_addr, size, __pgprot(prot));
+	return generic_ioremap_prot(phys_addr, size, pgprot);
 }
-EXPORT_SYMBOL(ioremap_prot);
+EXPORT_SYMBOL(__ioremap_prot);
 
 /*
  * Must be called after early_fixmap_init
Signature · 1 line
2.53.0
author maintainer
#88 lore raw

PATCH 74/452 arm64: io: Extract user memory type in ioremap_prot()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Will Deacon <[email protected]>

[ Upstream commit 8f098037139b294050053123ab2bc0f819d08932 ]

The only caller of ioremap_prot() outside of the generic ioremap() implementation is generic_access_phys(), which passes a 'pgprot_t' value determined from the user mapping of the target 'pfn' being accessed by the kernel. On arm64, the 'pgprot_t' contains all of the non-address bits from the pte, including the permission controls, and so we end up returning a new user mapping from ioremap_prot() which faults when accessed from the kernel on systems with PAN:

  | Unable to handle kernel read from unreadable memory at virtual address ffff80008ea89000
  | ...
  | Call trace:
  |   __memcpy_fromio+0x80/0xf8
  |   generic_access_phys+0x20c/0x2b8
  |   __access_remote_vm+0x46c/0x5b8
  |   access_remote_vm+0x18/0x30
  |   environ_read+0x238/0x3e8
  |   vfs_read+0xe4/0x2b0
  |   ksys_read+0xcc/0x178
  |   __arm64_sys_read+0x4c/0x68

Extract only the memory type from the user 'pgprot_t' in ioremap_prot() and assert that we're being passed a user mapping, to protect us against any changes in future that may require additional handling. To avoid falsely flagging users of ioremap(), provide our own ioremap() macro which simply wraps __ioremap_prot().

Cc Zeng Heng <[email protected]>
Cc Jinjiang Tu <[email protected]>
Cc Catalin Marinas <[email protected]>
Fixes 893dea9ccd08 ("arm64: Add HAVE_IOREMAP_PROT support")

[ Modified ioremap_prot() parameter, using "unsigned long user_prot" instead of "pgprot_t user_prot" to fix conflict with generic header. ]

---
 arch/arm64/include/asm/io.h | 17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)
arch/arm64/include/asm/io.h +15 -2
index 46d9f3f8290828..8fae8746eb98da 100644
@@ -141,10 +141,23 @@ extern void __memset_io(volatile void __iomem *, int, size_t);
 
 void __iomem *__ioremap_prot(phys_addr_t phys, size_t size, pgprot_t prot);
 
-#define ioremap_prot ioremap_prot
+static inline void __iomem *ioremap_prot(phys_addr_t phys, size_t size,
+					 unsigned long user_prot)
+{
+	pgprot_t prot;
+	pteval_t user_prot_val = pgprot_val(__pgprot(user_prot));
+
+	if (WARN_ON_ONCE(!(user_prot_val & PTE_USER)))
+		return NULL;
 
-#define _PAGE_IOREMAP PROT_DEVICE_nGnRE
+	prot = __pgprot_modify(PAGE_KERNEL, PTE_ATTRINDX_MASK,
+			       user_prot_val & PTE_ATTRINDX_MASK);
+	return __ioremap_prot(phys, size, prot);
+}
+#define ioremap_prot ioremap_prot
 
+#define ioremap(addr, size)	\
+	__ioremap_prot((addr), (size), __pgprot(PROT_DEVICE_nGnRE))
 #define ioremap_wc(addr, size)	\
 	__ioremap_prot((addr), (size), __pgprot(PROT_NORMAL_NC))
 #define ioremap_np(addr, size)	\
Signature · 1 line
2.53.0
author maintainer
#89 lore raw

PATCH 75/452 phy: mscc: Use PHY_ID_MATCH_EXACT for VSC8584, VSC8582, VSC8575, VSC856X

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Horatiu Vultur <[email protected]>

[ Upstream commit 1bc80d673087e5704adbb3ee8e4b785c14899cce ]

As the PHYs VSC8584, VSC8582, VSC8575 and VSC856X exists only as rev B, we can use PHY_ID_MATCH_EXACT to match exactly on revision B of the PHY. Because of this change then there is not need the check if it is a different revision than rev B in the function vsc8584_probe() as we already know that this will never happen.
These changes are a preparation for the next patch because in that patch we will make the PHYs VSC8574 and VSC8572 to use vsc8584_probe() and these PHYs have multiple revision.

---
 drivers/net/phy/mscc/mscc.h      |  8 ++++----
 drivers/net/phy/mscc/mscc_main.c | 23 ++++-------------------
 2 files changed, 8 insertions(+), 23 deletions(-)
drivers/net/phy/mscc/mscc.h +4 -4
index 4ba6e32cf6d8d1..c7aaf2c1ee52f1 100644
@@ -286,12 +286,12 @@ enum rgmii_clock_delay {
 #define PHY_ID_VSC8540			  0x00070760
 #define PHY_ID_VSC8541			  0x00070770
 #define PHY_ID_VSC8552			  0x000704e0
-#define PHY_ID_VSC856X			  0x000707e0
+#define PHY_ID_VSC856X			  0x000707e1
 #define PHY_ID_VSC8572			  0x000704d0
 #define PHY_ID_VSC8574			  0x000704a0
-#define PHY_ID_VSC8575			  0x000707d0
-#define PHY_ID_VSC8582			  0x000707b0
-#define PHY_ID_VSC8584			  0x000707c0
+#define PHY_ID_VSC8575			  0x000707d1
+#define PHY_ID_VSC8582			  0x000707b1
+#define PHY_ID_VSC8584			  0x000707c1
 #define PHY_VENDOR_MSCC			0x00070400
 
 #define MSCC_VDDMAC_1500		  1500
drivers/net/phy/mscc/mscc_main.c +4 -19
index 0a4aa8e08827aa..bce7ff8555c2e9 100644
@@ -1724,12 +1724,6 @@ static int vsc8584_config_init(struct phy_device *phydev)
 	 * in this pre-init function.
 	 */
 	if (phy_package_init_once(phydev)) {
-		/* The following switch statement assumes that the lowest
-		 * nibble of the phy_id_mask is always 0. This works because
-		 * the lowest nibble of the PHY_ID's below are also 0.
-		 */
-		WARN_ON(phydev->drv->phy_id_mask & 0xf);
-
 		switch (phydev->phy_id & phydev->drv->phy_id_mask) {
 		case PHY_ID_VSC8504:
 		case PHY_ID_VSC8552:
@@ -2268,11 +2262,6 @@ static int vsc8584_probe(struct phy_device *phydev)
 	   VSC8531_DUPLEX_COLLISION};
 	int ret;
 
-	if ((phydev->phy_id & MSCC_DEV_REV_MASK) != VSC8584_REVB) {
-		dev_err(&phydev->mdio.dev, "Only VSC8584 revB is supported.\n");
-		return -ENOTSUPP;
-	}
-
 	vsc8531 = devm_kzalloc(&phydev->mdio.dev, sizeof(*vsc8531), GFP_KERNEL);
 	if (!vsc8531)
 		return -ENOMEM;
@@ -2559,9 +2548,8 @@ static struct phy_driver vsc85xx_driver[] = {
 	.get_stats      = &vsc85xx_get_stats,
 },
 {
-	.phy_id		= PHY_ID_VSC856X,
+	PHY_ID_MATCH_EXACT(PHY_ID_VSC856X),
 	.name		= "Microsemi GE VSC856X SyncE",
-	.phy_id_mask	= 0xfffffff0,
 	/* PHY_GBIT_FEATURES */
 	.soft_reset	= &genphy_soft_reset,
 	.config_init    = &vsc8584_config_init,
@@ -2633,9 +2621,8 @@ static struct phy_driver vsc85xx_driver[] = {
 	.get_stats      = &vsc85xx_get_stats,
 },
 {
-	.phy_id		= PHY_ID_VSC8575,
+	PHY_ID_MATCH_EXACT(PHY_ID_VSC8575),
 	.name		= "Microsemi GE VSC8575 SyncE",
-	.phy_id_mask	= 0xfffffff0,
 	/* PHY_GBIT_FEATURES */
 	.soft_reset	= &genphy_soft_reset,
 	.config_init    = &vsc8584_config_init,
@@ -2657,9 +2644,8 @@ static struct phy_driver vsc85xx_driver[] = {
 	.get_stats      = &vsc85xx_get_stats,
 },
 {
-	.phy_id		= PHY_ID_VSC8582,
+	PHY_ID_MATCH_EXACT(PHY_ID_VSC8582),
 	.name		= "Microsemi GE VSC8582 SyncE",
-	.phy_id_mask	= 0xfffffff0,
 	/* PHY_GBIT_FEATURES */
 	.soft_reset	= &genphy_soft_reset,
 	.config_init    = &vsc8584_config_init,
@@ -2681,9 +2667,8 @@ static struct phy_driver vsc85xx_driver[] = {
 	.get_stats      = &vsc85xx_get_stats,
 },
 {
-	.phy_id		= PHY_ID_VSC8584,
+	PHY_ID_MATCH_EXACT(PHY_ID_VSC8584),
 	.name		= "Microsemi GE VSC8584 SyncE",
-	.phy_id_mask	= 0xfffffff0,
 	/* PHY_GBIT_FEATURES */
 	.soft_reset	= &genphy_soft_reset,
 	.config_init    = &vsc8584_config_init,
Signature · 1 line
2.53.0
author maintainer
#90 lore raw

PATCH 76/452 ima: verify the previous kernels IMA buffer lies in addressable RAM

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Harshit Mogalapalli <[email protected]>

[ Upstream commit 10d1c75ed4382a8e79874379caa2ead8952734f9 ]

Patch series "Address page fault in ima_restore_measurement_list()", v3.

When the second-stage kernel is booted via kexec with a limiting command line such as "mem=<size>" we observe a pafe fault that happens.

    BUG: unable to handle page fault for address: ffff97793ff47000
    RIP: ima_restore_measurement_list+0xdc/0x45a
    #PF: error_code(0x0000)  not-present page

This happens on x86_64 only, as this is already fixed in aarch64 in
commit: cbf9c4b9617b ("of: check previous kernel's ima-kexec-buffer against memory bounds")

This patch (of 3):

When the second-stage kernel is booted with a limiting command line (e.g. "mem=<size>"), the IMA measurement buffer handed over from the previous kernel may fall outside the addressable RAM of the new kernel. Accessing such a buffer can fault during early restore.

Introduce a small generic helper, ima_validate_range(), which verifies that a physical [start, end] range for the previous-kernel IMA buffer lies within addressable memory:
- On x86, use pfn_range_is_mapped().
- On OF based architectures, use page_is_ram().

---
 include/linux/ima.h                |  1 +
 security/integrity/ima/ima_kexec.c | 35 ++++++++++++++++++++++++++++++
 2 files changed, 36 insertions(+)
include/linux/ima.h +1 -0
index 86b57757c7b100..1ae8647576ff53 100644
@@ -145,6 +145,7 @@ static inline int ima_measure_critical_data(const char *event_label,
 #ifdef CONFIG_HAVE_IMA_KEXEC
 int __init ima_free_kexec_buffer(void);
 int __init ima_get_kexec_buffer(void **addr, size_t *size);
+int ima_validate_range(phys_addr_t phys, size_t size);
 #endif
 
 #ifdef CONFIG_IMA_SECURE_AND_OR_TRUSTED_BOOT
security/integrity/ima/ima_kexec.c +35 -0
index ad133fe120db29..d7c18d8a31035e 100644
@@ -12,6 +12,8 @@
 #include <linux/kexec.h>
 #include <linux/of.h>
 #include <linux/ima.h>
+#include <linux/mm.h>
+#include <linux/overflow.h>
 #include "ima.h"
 
 #ifdef CONFIG_IMA_KEXEC
@@ -164,3 +166,36 @@ void __init ima_load_kexec_buffer(void)
 		pr_debug("Error restoring the measurement list: %d\n", rc);
 	}
 }
+
+/*
+ * ima_validate_range - verify a physical buffer lies in addressable RAM
+ * @phys: physical start address of the buffer from previous kernel
+ * @size: size of the buffer
+ *
+ * On success return 0. On failure returns -EINVAL so callers can skip
+ * restoring.
+ */
+int ima_validate_range(phys_addr_t phys, size_t size)
+{
+	unsigned long start_pfn, end_pfn;
+	phys_addr_t end_phys;
+
+	if (check_add_overflow(phys, (phys_addr_t)size - 1, &end_phys))
+		return -EINVAL;
+
+	start_pfn = PHYS_PFN(phys);
+	end_pfn = PHYS_PFN(end_phys);
+
+#ifdef CONFIG_X86
+	if (!pfn_range_is_mapped(start_pfn, end_pfn))
+#else
+	if (!page_is_ram(start_pfn) || !page_is_ram(end_pfn))
+#endif
+	{
+		pr_warn("IMA: previous kernel measurement buffer %pa (size 0x%zx) lies outside available memory\n",
+			&phys, size);
+		return -EINVAL;
+	}
+
+	return 0;
+}
Signature · 1 line
2.53.0
author maintainer
#91 lore raw

PATCH 77/452 of/kexec: refactor ima_get_kexec_buffer() to use ima_validate_range()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Harshit Mogalapalli <[email protected]>

[ Upstream commit 4d02233235ed0450de9c10fcdcf3484e3c9401ce ]

Refactor the OF/DT ima_get_kexec_buffer() to use a generic helper to validate the address range. No functional change intended.

Cc Alexander Graf <[email protected]>
Cc Ard Biesheuvel <[email protected]>
Cc Baoquan He <[email protected]>
Cc Borislav Betkov <[email protected]>
Cc guoweikang <[email protected]>
Cc Henry Willard <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Jiri Bohac <[email protected]>
Cc Joel Granados <[email protected]>
Cc Jonathan McDowell <[email protected]>
Cc Mike Rapoport <[email protected]>
Cc Paul Webb <[email protected]>
Cc Sohil Mehta <[email protected]>
Cc Sourabh Jain <[email protected]>
Cc Thomas Gleinxer <[email protected]>
Cc Yifei Liu <[email protected]>
---
 drivers/of/kexec.c | 15 +++------------
 1 file changed, 3 insertions(+), 12 deletions(-)
drivers/of/kexec.c +3 -12
index 3b98a57f1f0743..23fde2d032e6d9 100644
@@ -128,7 +128,6 @@ int __init ima_get_kexec_buffer(void **addr, size_t *size)
 {
 	int ret, len;
 	unsigned long tmp_addr;
-	unsigned long start_pfn, end_pfn;
 	size_t tmp_size;
 	const void *prop;
 
@@ -144,17 +143,9 @@ int __init ima_get_kexec_buffer(void **addr, size_t *size)
 	if (!tmp_size)
 		return -ENOENT;
 
-	/*
-	 * Calculate the PFNs for the buffer and ensure
-	 * they are with in addressable memory.
-	 */
-	start_pfn = PHYS_PFN(tmp_addr);
-	end_pfn = PHYS_PFN(tmp_addr + tmp_size - 1);
-	if (!page_is_ram(start_pfn) || !page_is_ram(end_pfn)) {
-		pr_warn("IMA buffer at 0x%lx, size = 0x%zx beyond memory\n",
-			tmp_addr, tmp_size);
-		return -EINVAL;
-	}
+	ret = ima_validate_range(tmp_addr, tmp_size);
+	if (ret)
+		return ret;
 
 	*addr = __va(tmp_addr);
 	*size = tmp_size;
Signature · 1 line
2.53.0
author maintainer
#92 lore raw

PATCH 78/452 x86/kexec: add a sanity check on previous kernels ima kexec buffer

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Harshit Mogalapalli <[email protected]>

[ Upstream commit c5489d04337b47e93c0623e8145fcba3f5739efd ]

When the second-stage kernel is booted via kexec with a limiting command line such as "mem=<size>", the physical range that contains the carried over IMA measurement list may fall outside the truncated RAM leading to a kernel panic.

    BUG: unable to handle page fault for address: ffff97793ff47000
    RIP: ima_restore_measurement_list+0xdc/0x45a
    #PF: error_code(0x0000) – not-present page

Other architectures already validate the range with page_is_ram(), as done in commit cbf9c4b9617b ("of: check previous kernel's ima-kexec-buffer against memory bounds") do a similar check on x86.

Without carrying the measurement list across kexec, the attestation would fail.

Fixes b69a2afd5afc ("x86/kexec: Carry forward IMA measurement log on kexec")
Cc Alexander Graf <[email protected]>
Cc Ard Biesheuvel <[email protected]>
Cc Baoquan He <[email protected]>
Cc Borislav Betkov <[email protected]>
Cc guoweikang <[email protected]>
Cc Henry Willard <[email protected]>
Cc "H. Peter Anvin" <[email protected]>
Cc Ingo Molnar <[email protected]>
Cc Jiri Bohac <[email protected]>
Cc Joel Granados <[email protected]>
Cc Jonathan McDowell <[email protected]>
Cc Mike Rapoport <[email protected]>
Cc Sohil Mehta <[email protected]>
Cc Sourabh Jain <[email protected]>
Cc Thomas Gleinxer <[email protected]>
Cc Yifei Liu <[email protected]>
---
 arch/x86/kernel/setup.c | 6 ++++++
 1 file changed, 6 insertions(+)
arch/x86/kernel/setup.c +6 -0
index eb129277dcdd64..df74f865c9f121 100644
@@ -372,9 +372,15 @@ int __init ima_free_kexec_buffer(void)
 
 int __init ima_get_kexec_buffer(void **addr, size_t *size)
 {
+	int ret;
+
 	if (!ima_kexec_buffer_size)
 		return -ENOENT;
 
+	ret = ima_validate_range(ima_kexec_buffer_phys, ima_kexec_buffer_size);
+	if (ret)
+		return ret;
+
 	*addr = __va(ima_kexec_buffer_phys);
 	*size = ima_kexec_buffer_size;
 
Signature · 1 line
2.53.0
author maintainer
#93 lore raw

PATCH 79/452 hwmon: (pmbus/adm1266) serialize GPIO PMBus accesses with pmbus_lock

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Abdurrahman Hussain <[email protected]>

[ Upstream commit bab8c6fb5af8df7e753d196c1262cb78e92ca872 ]

adm1266_gpio_get(), adm1266_gpio_get_multiple(), and adm1266_gpio_dbg_show() all issue PMBus reads against the device but none of them take pmbus_lock. The pmbus_core framework holds pmbus_lock around its own multi-transaction sequences (notably the "set PAGE, then read paged register" pattern used by hwmon attributes), so an unlocked GPIO accessor can land between a PAGE write and the subsequent paged read in another thread and corrupt either side's view of the device state machine.

Take pmbus_lock at the top of each of the three accessors via the scope-based guard(). The lock is uncontended in the common case and adds only a single mutex round-trip per call.

Fixes d98dfad35c38 ("hwmon: (pmbus/adm1266) Add support for GPIOs")
[ open-coded `guard(pmbus_lock)()` as explicit `pmbus_lock_interruptible()`/`pmbus_unlock()` ]
---
 drivers/hwmon/pmbus/adm1266.c | 40 +++++++++++++++++++++++++++++------
 1 file changed, 34 insertions(+), 6 deletions(-)
drivers/hwmon/pmbus/adm1266.c +34 -6
index a8690d6c9b9cb0..518eaf07a123de 100644
@@ -173,7 +173,12 @@ static int adm1266_gpio_get(struct gpio_chip *chip, unsigned int offset)
 	else
 		pmbus_cmd = ADM1266_PDIO_STATUS;
 
+	ret = pmbus_lock_interruptible(data->client);
+	if (ret)
+		return ret;
+
 	ret = i2c_smbus_read_block_data(data->client, pmbus_cmd, read_buf);
+	pmbus_unlock(data->client);
 	if (ret < 0)
 		return ret;
 	if (ret < 2)
@@ -195,11 +200,19 @@ static int adm1266_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask
 	unsigned int gpio_nr;
 	int ret;
 
+	ret = pmbus_lock_interruptible(data->client);
+	if (ret)
+		return ret;
+
 	ret = i2c_smbus_read_block_data(data->client, ADM1266_GPIO_STATUS, read_buf);
-	if (ret < 0)
+	if (ret < 0) {
+		pmbus_unlock(data->client);
 		return ret;
-	if (ret < 2)
+	}
+	if (ret < 2) {
+		pmbus_unlock(data->client);
 		return -EIO;
+	}
 
 	status = read_buf[0] + (read_buf[1] << 8);
 
@@ -210,10 +223,14 @@ static int adm1266_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask
 	}
 
 	ret = i2c_smbus_read_block_data(data->client, ADM1266_PDIO_STATUS, read_buf);
-	if (ret < 0)
+	if (ret < 0) {
+		pmbus_unlock(data->client);
 		return ret;
-	if (ret < 2)
+	}
+	if (ret < 2) {
+		pmbus_unlock(data->client);
 		return -EIO;
+	}
 
 	status = read_buf[0] + (read_buf[1] << 8);
 
@@ -222,6 +239,8 @@ static int adm1266_gpio_get_multiple(struct gpio_chip *chip, unsigned long *mask
 			set_bit(gpio_nr, bits);
 	}
 
+	pmbus_unlock(data->client);
+
 	return 0;
 }
 
@@ -236,11 +255,16 @@ static void adm1266_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 	int ret;
 	int i;
 
+	if (pmbus_lock_interruptible(data->client))
+		return;
+
 	for (i = 0; i < ADM1266_GPIO_NR; i++) {
 		write_cmd = adm1266_gpio_mapping[i][1];
 		ret = adm1266_pmbus_block_xfer(data, ADM1266_GPIO_CONFIG, 1, &write_cmd, read_buf);
-		if (ret != 2)
+		if (ret != 2) {
+			pmbus_unlock(data->client);
 			return;
+		}
 
 		gpio_config = read_buf[0];
 		seq_puts(s, adm1266_names[i]);
@@ -262,8 +286,10 @@ static void adm1266_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 
 	write_cmd = 0xFF;
 	ret = adm1266_pmbus_block_xfer(data, ADM1266_PDIO_CONFIG, 1, &write_cmd, read_buf);
-	if (ret != 32)
+	if (ret != 32) {
+		pmbus_unlock(data->client);
 		return;
+	}
 
 	for (i = 0; i < ADM1266_PDIO_NR; i++) {
 		seq_puts(s, adm1266_names[ADM1266_GPIO_NR + i]);
@@ -286,6 +312,8 @@ static void adm1266_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 
 		seq_puts(s, ")\n");
 	}
+
+	pmbus_unlock(data->client);
 }
 
 static int adm1266_config_gpio(struct adm1266_data *data)
Signature · 1 line
2.53.0
author maintainer
#94 lore raw

PATCH 80/452 hwmon: (pmbus/adm1266) serialize NVMEM blackbox read with pmbus_lock

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Abdurrahman Hussain <[email protected]>

[ Upstream commit 9f1dd8f9491eb840cbea7ffdf4cad031e25f8ae0 ]

adm1266_nvmem_read() is the reg_read callback the NVMEM core invokes when userspace reads /sys/bus/nvmem/devices/.../nvmem on this chip. On the first byte of every read it does a memset of data->dev_mem, walks the device blackbox through adm1266_nvmem_read_blackbox() (which issues a chain of PMBus block transactions), and then memcpys the refreshed buffer out to userspace. None of that runs under pmbus_lock today.

Two consequences:

- The PMBus traffic the refresh issues is not serialised against pmbus_core's own multi-step PAGE+register sequences. A paged hwmon attribute read from another thread can land between a PAGE write and the paged read in either direction and corrupt one side's view of the device state machine.

- The NVMEM core does not serialise concurrent reg_read calls, so two userspace readers racing at offset 0 can interleave the memset of data->dev_mem with another reader's adm1266_nvmem_read_blackbox() refill or memcpy out, returning torn data to userspace.

Take pmbus_lock at the top of adm1266_nvmem_read() via the scope-based guard(). Patch 5 of this series moves adm1266_config_nvmem() past pmbus_do_probe() so the lock is guaranteed to be live before the callback is reachable from userspace.

Fixes 15609d189302 ("hwmon: (pmbus/adm1266) read blackbox")
[ adapted `guard(pmbus_lock)(data->client)` to manual `pmbus_lock_interruptible()`/`pmbus_unlock()` ]
---
 drivers/hwmon/pmbus/adm1266.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/hwmon/pmbus/adm1266.c +7 -0
index 518eaf07a123de..432846ef0cf45d 100644
@@ -421,18 +421,25 @@ static int adm1266_nvmem_read(void *priv, unsigned int offset, void *val, size_t
 	if (offset + bytes > data->nvmem_config.size)
 		return -EINVAL;
 
+	ret = pmbus_lock_interruptible(data->client);
+	if (ret)
+		return ret;
+
 	if (offset == 0) {
 		memset(data->dev_mem, 0, data->nvmem_config.size);
 
 		ret = adm1266_nvmem_read_blackbox(data, data->dev_mem);
 		if (ret) {
 			dev_err(&data->client->dev, "Could not read blackbox!");
+			pmbus_unlock(data->client);
 			return ret;
 		}
 	}
 
 	memcpy(val, data->dev_mem + offset, bytes);
 
+	pmbus_unlock(data->client);
+
 	return 0;
 }
 
Signature · 1 line
2.53.0
author maintainer
#95 lore raw

PATCH 81/452 soc/tegra: pmc: Fix unsafe generic_handle_irq() call

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Prathamesh Shete <[email protected]>

[ Upstream commit e6d96073af681780820c94079b978474a8a44413 ]

Currently, when resuming from system suspend on Tegra platforms, the following warning is observed:

WARNING: CPU: 0 PID: 14459 at kernel/irq/irqdesc.c:666
Call trace:
 handle_irq_desc+0x20/0x58 (P)
 tegra186_pmc_wake_syscore_resume+0xe4/0x15c
 syscore_resume+0x3c/0xb8
 suspend_devices_and_enter+0x510/0x540
 pm_suspend+0x16c/0x1d8

The warning occurs because generic_handle_irq() is being called from a non-interrupt context which is considered as unsafe.

Fix this warning by deferring generic_handle_irq() call to an IRQ work which gets executed in hard IRQ context where generic_handle_irq() can be called safely.

When PREEMPT_RT kernels are used, regular IRQ work (initialized with init_irq_work) is deferred to run in per-CPU kthreads in preemptible context rather than hard IRQ context. Hence, use the IRQ_WORK_INIT_HARD variant so that with PREEMPT_RT kernels, the IRQ work is processed in hardirq context instead of being deferred to a thread which is required for calling generic_handle_irq().

On non-PREEMPT_RT kernels, both init_irq_work() and IRQ_WORK_INIT_HARD() execute in IRQ context, so this change has no functional impact for standard kernel configurations.

---
 drivers/soc/tegra/pmc.c | 104 ++++++++++++++++++++++++++++------------
 1 file changed, 74 insertions(+), 30 deletions(-)
drivers/soc/tegra/pmc.c +74 -30
index 1306e3b8b5c04b..4cb47c29dc6b95 100644
@@ -28,6 +28,7 @@
 #include <linux/iopoll.h>
 #include <linux/irqdomain.h>
 #include <linux/irq.h>
+#include <linux/irq_work.h>
 #include <linux/kernel.h>
 #include <linux/of_address.h>
 #include <linux/of_clk.h>
@@ -467,6 +468,10 @@ struct tegra_pmc {
 	unsigned long *wake_sw_status_map;
 	unsigned long *wake_cntrl_level_map;
 	struct syscore_ops syscore;
+
+	/* Pending wake IRQ processing */
+	struct irq_work wake_work;
+	u32 *wake_status;
 };
 
 static struct tegra_pmc *pmc = &(struct tegra_pmc) {
@@ -1940,6 +1945,50 @@ static int tegra_pmc_parse_dt(struct tegra_pmc *pmc, struct device_node *np)
 	return 0;
 }
 
+/* translate sc7 wake sources back into IRQs to catch edge triggered wakeups */
+static void tegra186_pmc_wake_handler(struct irq_work *work)
+{
+	struct tegra_pmc *pmc = container_of(work, struct tegra_pmc, wake_work);
+	unsigned int i, wake;
+
+	for (i = 0; i < pmc->soc->max_wake_vectors; i++) {
+		unsigned long status = pmc->wake_status[i];
+
+		for_each_set_bit(wake, &status, 32) {
+			irq_hw_number_t hwirq = wake + (i * 32);
+			struct irq_desc *desc;
+			unsigned int irq;
+
+			irq = irq_find_mapping(pmc->domain, hwirq);
+			if (!irq) {
+				dev_warn(pmc->dev,
+					 "No IRQ found for WAKE#%lu!\n",
+					 hwirq);
+				continue;
+			}
+
+			dev_dbg(pmc->dev,
+				"Resume caused by WAKE#%lu mapped to IRQ#%u\n",
+				hwirq, irq);
+
+			desc = irq_to_desc(irq);
+			if (!desc) {
+				dev_warn(pmc->dev,
+					 "No descriptor found for IRQ#%u\n",
+					 irq);
+				continue;
+			}
+
+			if (!desc->action || !desc->action->name)
+				continue;
+
+			generic_handle_irq(irq);
+		}
+
+		pmc->wake_status[i] = 0;
+	}
+}
+
 static int tegra_pmc_init(struct tegra_pmc *pmc)
 {
 	if (pmc->soc->max_wake_events > 0) {
@@ -1958,6 +2007,18 @@ static int tegra_pmc_init(struct tegra_pmc *pmc)
 		pmc->wake_cntrl_level_map = bitmap_zalloc(pmc->soc->max_wake_events, GFP_KERNEL);
 		if (!pmc->wake_cntrl_level_map)
 			return -ENOMEM;
+
+		pmc->wake_status = kcalloc(pmc->soc->max_wake_vectors, sizeof(u32), GFP_KERNEL);
+		if (!pmc->wake_status)
+			return -ENOMEM;
+
+		/*
+		 * Initialize IRQ work for processing wake IRQs. Must use
+		 * HARD_IRQ variant to run in hard IRQ context on PREEMPT_RT
+		 * because we call generic_handle_irq() which requires hard
+		 * IRQ context.
+		 */
+		pmc->wake_work = IRQ_WORK_INIT_HARD(tegra186_pmc_wake_handler);
 	}
 
 	if (pmc->soc->init)
@@ -3156,47 +3217,30 @@ static void wke_clear_wake_status(struct tegra_pmc *pmc)
 	}
 }
 
-/* translate sc7 wake sources back into IRQs to catch edge triggered wakeups */
-static void tegra186_pmc_process_wake_events(struct tegra_pmc *pmc, unsigned int index,
-					     unsigned long status)
-{
-	unsigned int wake;
-
-	dev_dbg(pmc->dev, "Wake[%d:%d]  status=%#lx\n", (index * 32) + 31, index * 32, status);
-
-	for_each_set_bit(wake, &status, 32) {
-		irq_hw_number_t hwirq = wake + 32 * index;
-		struct irq_desc *desc;
-		unsigned int irq;
-
-		irq = irq_find_mapping(pmc->domain, hwirq);
-
-		desc = irq_to_desc(irq);
-		if (!desc || !desc->action || !desc->action->name) {
-			dev_dbg(pmc->dev, "Resume caused by WAKE%ld, IRQ %d\n", hwirq, irq);
-			continue;
-		}
-
-		dev_dbg(pmc->dev, "Resume caused by WAKE%ld, %s\n", hwirq, desc->action->name);
-		generic_handle_irq(irq);
-	}
-}
-
 static void tegra186_pmc_wake_syscore_resume(void)
 {
-	u32 status, mask;
 	unsigned int i;
+	u32 mask;
 
 	for (i = 0; i < pmc->soc->max_wake_vectors; i++) {
 		mask = readl(pmc->wake + WAKE_AOWAKE_TIER2_ROUTING(i));
-		status = readl(pmc->wake + WAKE_AOWAKE_STATUS_R(i)) & mask;
-
-		tegra186_pmc_process_wake_events(pmc, i, status);
+		pmc->wake_status[i] = readl(pmc->wake + WAKE_AOWAKE_STATUS_R(i)) & mask;
 	}
+
+	/* Schedule IRQ work to process wake IRQs (if any) */
+	irq_work_queue(&pmc->wake_work);
 }
 
 static int tegra186_pmc_wake_syscore_suspend(void)
 {
+	unsigned int i;
+
+	/* Check if there are unhandled wake IRQs */
+	for (i = 0; i < pmc->soc->max_wake_vectors; i++)
+		if (pmc->wake_status[i])
+			dev_warn(pmc->dev,
+				 "Unhandled wake IRQs pending vector[%u]: 0x%x\n",
+				 i, pmc->wake_status[i]);
 	wke_read_sw_wake_status(pmc);
 
 	/* flip the wakeup trigger for dual-edge triggered pads
Signature · 1 line
2.53.0
author maintainer
#96 lore raw

PATCH 82/452 iio: imu: st_lsm6dsx: fix stack leak in tagged FIFO buffer

In reply to Greg Kroah-Hartman

6.6-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.

Cc Lorenzo Bianconi <[email protected]>
Cc Jonathan Cameron <[email protected]>
Cc David Lechner <[email protected]>
Cc "Nuno Sá" <[email protected]>
Cc Andy Shevchenko <[email protected]>
Fixes c14edb4d0bdc ("iio:imu:st_lsm6dsx Fix alignment and data leak issues")
Cc stable <[email protected]>
Assisted-by gregkh_clanker_t1000
---
 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
@@ -586,7 +586,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;
author maintainer
#97 lore raw

PATCH 83/452 usb: typec: ucsi: ccg: reject firmware images without a : record header

In reply to Greg Kroah-Hartman

6.6-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
@@ -1178,6 +1178,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, ':');
 
author maintainer
#98 lore raw

PATCH 84/452 usb: typec: ucsi: displayport: NAK DP_CMD_CONFIGURE without a payload VDO

In reply to Greg Kroah-Hartman

6.6-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
@@ -240,6 +240,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);
author maintainer
#99 lore raw

PATCH 85/452 usb: typec: altmodes/displayport: validate count before reading Status Update VDO

In reply to Greg Kroah-Hartman

6.6-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
@@ -311,6 +311,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;
author maintainer
#100 lore raw

PATCH 86/452 usb: typec: wcove: dont write past struct pd_message in wcove_read_rx_buffer()

In reply to Greg Kroah-Hartman

6.6-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
@@ -444,9 +444,11 @@ static int wcove_start_toggling(struct t
 	return 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;
 
@@ -454,12 +456,13 @@ static int wcove_read_rx_buffer(struct w
 	if (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,
author maintainer
#101 lore raw

PATCH 87/452 usb: typec: tcpm/tcpci_maxim: validate header NDO against RX_BYTE_CNT

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Greg Kroah-Hartman <[email protected]>

commit aa2f716327be1818e1cb156da8a2844804aaec2f upstream.

A broken/malicious port can transmit a CRC-valid frame whose header advertises up to seven data objects but whose body carries fewer than that. Check for this, and rightfully reject the message, instead of reading from uninitialized stack memory.

Assisted-by gkh_clanker_t1000
Cc Heikki Krogerus <[email protected]>
Cc "André Draszik" <[email protected]>
Cc Badhri Jagan Sridharan <[email protected]>
Cc Amit Sunil Dhamne <[email protected]>
Cc stable <[email protected]>
---
 drivers/usb/typec/tcpm/tcpci_maxim_core.c |    9 +++++++++
 1 file changed, 9 insertions(+)
drivers/usb/typec/tcpm/tcpci_maxim_core.c +9 -0
@@ -165,6 +165,15 @@ static void process_rx(struct max_tcpci_
 	rx_buf_ptr = rx_buf + TCPC_RECEIVE_BUFFER_RX_BYTE_BUF_OFFSET;
 	msg.header = cpu_to_le16(*(u16 *)rx_buf_ptr);
 	rx_buf_ptr = rx_buf_ptr + sizeof(msg.header);
+
+	if (count < TCPC_RECEIVE_BUFFER_RX_BYTE_BUF_OFFSET + sizeof(msg.header) +
+		    pd_header_cnt_le(msg.header) * sizeof(msg.payload[0])) {
+		max_tcpci_write16(chip, TCPC_ALERT, TCPC_ALERT_RX_STATUS);
+		dev_err(chip->dev, "Invalid TCPC_RX_BYTE_CNT %d for header cnt %d\n",
+			count, pd_header_cnt_le(msg.header));
+		return;
+	}
+
 	for (payload_index = 0; payload_index < pd_header_cnt_le(msg.header); payload_index++,
 	     rx_buf_ptr += sizeof(msg.payload[0]))
 		msg.payload[payload_index] = cpu_to_le32(*(u32 *)rx_buf_ptr);
author maintainer
#102 lore raw

PATCH 88/452 usb: typec: ucsi: validate connector number in ucsi_connector_change()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Greg Kroah-Hartman <[email protected]>

commit 288a81a8507052bcfbf884d39a463c44c42c5fd9 upstream.

The connector number in a UCSI CCI notification is a 7-bit field supplied by the PPM. ucsi_connector_change() uses it to index the ucsi->connector[] array without checking it against the number of connectors the PPM reported at init time, so a buggy or malicious PPM (EC firmware, or an I2C-attached UCSI controller on the ccg / stm32g0 / glink transports) can drive schedule_work() on memory past the end of the array.

Reject connector numbers that are zero or exceed cap.num_connectors before dereferencing the array.

---
 drivers/usb/typec/ucsi/ucsi.c |   11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/usb/typec/ucsi/ucsi.c +10 -1
@@ -960,13 +960,22 @@ out_unlock:
  */
 void ucsi_connector_change(struct ucsi *ucsi, u8 num)
 {
-	struct ucsi_connector *con = &ucsi->connector[num - 1];
+	struct ucsi_connector *con;
 
 	if (!(ucsi->ntfy & UCSI_ENABLE_NTFY_CONNECTOR_CHANGE)) {
 		dev_dbg(ucsi->dev, "Early connector change event\n");
 		return;
 	}
 
+	if (!num || num > ucsi->cap.num_connectors) {
+		dev_warn_ratelimited(ucsi->dev,
+				     "Bogus connector change on %u (max %u)\n",
+				     num, ucsi->cap.num_connectors);
+		return;
+	}
+
+	con = &ucsi->connector[num - 1];
+
 	if (!test_and_set_bit(EVENT_PENDING, &ucsi->flags))
 		schedule_work(&con->work);
 }
author maintainer
#103 lore raw

PATCH 89/452 USB: serial: safe_serial: fix memory corruption with small endpoint

In reply to Greg Kroah-Hartman

6.6-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(str
 static 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_seria
 	default:
 		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;
 }
 
author maintainer
#104 lore raw

PATCH 90/452 media: rc: igorplugusb: fix control request setup packet

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Henri A <[email protected]>

commit 171022c7d594c133a45f92357a2a91475edabe20 upstream.

Commit eac69475b01f ("media: rc: igorplugusb: heed coherency rules") changed the control request storage from an embedded struct to an allocated pointer so it can obey DMA coherency rules.

However, the driver still passes &ir->request to usb_fill_control_urb(). That points the URB setup packet at the pointer field itself rather than at the allocated struct usb_ctrlrequest.

USB core then interprets pointer bytes as the setup packet. This can produce an invalid bRequestType and trigger the control direction warning reported by syzbot:

usb 2-1: BOGUS control dir, pipe 80003580 doesn't match bRequestType 0

Pass ir->request itself as the setup packet.

Fixes eac69475b01f ("media: rc: igorplugusb: heed coherency rules")
Reported-by [email protected]
Assisted-by Codex:GPT-5.5
---
 drivers/media/rc/igorplugusb.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/rc/igorplugusb.c +1 -1
@@ -184,7 +184,7 @@ static int igorplugusb_probe(struct usb_
 	if (!ir->buf_in)
 		goto fail;
 	usb_fill_control_urb(ir->urb, udev,
-		usb_rcvctrlpipe(udev, 0), (uint8_t *)&ir->request,
+		usb_rcvctrlpipe(udev, 0), (uint8_t *)ir->request,
 		ir->buf_in, MAX_PACKET, igorplugusb_callback, ir);
 
 	usb_make_path(udev, ir->phys, sizeof(ir->phys));
author maintainer
#105 lore raw

PATCH 91/452 Input: ims-pcu - fix usb_free_coherent() size in ims_pcu_buffers_free()

In reply to Greg Kroah-Hartman

6.6-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(struct
 	usb_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);
author maintainer
#106 lore raw

PATCH 92/452 HID: quirks: Add ALWAYS_POLL quirk for SIGMACHIP USB mouse

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: hlleng <[email protected]>

commit 07466fc91c55532edcfb5c6a7ccd2ea52728d6bd upstream.

The SIGMACHIP USB mouse with VID/PID 1c4f:0034 can disconnect and re-enumerate repeatedly after it has been enumerated if its interrupt endpoint is not continuously polled.

This was observed with the device reporting itself as "SIGMACHIP Usb Mouse". Keeping the input event device open avoids the disconnects.

Add HID_QUIRK_ALWAYS_POLL for this device so the HID core keeps polling it even when there is no userspace input consumer.

---
 drivers/hid/hid-ids.h    |    1 +
 drivers/hid/hid-quirks.c |    1 +
 2 files changed, 2 insertions(+)
drivers/hid/hid-ids.h +1 -0
@@ -1212,6 +1212,7 @@
 
 #define USB_VENDOR_ID_SIGMA_MICRO	0x1c4f
 #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD	0x0002
+#define USB_DEVICE_ID_SIGMA_MICRO_USB_MOUSE	0x0034
 #define USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD2	0x0059
 
 #define USB_VENDOR_ID_SIGMATEL		0x066F
drivers/hid/hid-quirks.c +1 -0
@@ -186,6 +186,7 @@ static const struct hid_device_id hid_qu
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_KEYBOARD), HID_QUIRK_NO_INIT_REPORTS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SIGMA_MICRO, USB_DEVICE_ID_SIGMA_MICRO_USB_MOUSE), HID_QUIRK_ALWAYS_POLL },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780), HID_QUIRK_NOGET },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS1030_TOUCH), HID_QUIRK_NOGET },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SIS_TOUCH, USB_DEVICE_ID_SIS817_TOUCH), HID_QUIRK_NOGET },
author maintainer
#107 lore raw

PATCH 93/452 Bluetooth: btusb: Allow firmware re-download when version matches

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 3267c884cefa ("Bluetooth: btusb: Add support for QCA ROME chipset family")
---
 drivers/bluetooth/btusb.c |    8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/bluetooth/btusb.c +7 -1
@@ -3667,7 +3667,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;
author maintainer
#108 lore raw

PATCH 94/452 hpfs: fix a crash if hpfs_map_dnode_bitmap fails

In reply to Greg Kroah-Hartman

6.6-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");
author maintainer
#109 lore raw

PATCH 95/452 ipc: limit next_id allocation to the valid ID range

In reply to Greg Kroah-Hartman

6.6-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
@@ -253,7 +253,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;
author maintainer
#110 lore raw

PATCH 96/452 auxdisplay: line-display: fix OOB read on zero-length message_store()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Stepan Ionichev <[email protected]>

commit a7511dcd9dd4bc55d123f9b800c8a4ed2662e5c6 upstream.

linedisp_display() unconditionally reads msg[count - 1] before checking whether count is zero, so a write of zero bytes to the message sysfs attribute hits msg[-1]:

	write(fd, "", 0);

	-> message_store(..., buf, count=0)
	   -> linedisp_display(linedisp, buf, count=0)
	      -> msg[count - 1] == '\n'  ; OOB read

The kernfs write buffer for that store is a 1-byte allocation (kernfs_fop_write_iter() does kmalloc(len + 1) with len == 0), so msg[-1] is a 1-byte read before the slab object. On a KASAN-enabled kernel this trips an out-of-bounds report and panics; on stock kernels it silently reads adjacent slab data and, if that byte happens to be '\n', the following count-- wraps ssize_t 0 to -1 and is then passed to kmemdup_nul().

linedisp_display() is reached from the message_store() sysfs callback (drivers/auxdisplay/line-display.c message attribute, mode 0644) and from the in-tree initial-message setup with count == -1, so the OOB path is only userspace-triggerable via zero-byte writes; vfs_write() does not short-circuit on count == 0 and kernfs_fop_write_iter() dispatches the store callback regardless.

Guard the trailing-newline trim with a count check. The existing if (!count) block then takes the clear-display path unchanged.

Affects every auxdisplay driver that registers via linedisp_register() / linedisp_attach(): ht16k33, max6959, img-ascii-lcd, seg-led-gpio.

Fixes 7e76aece6f03 ("auxdisplay: Extract character line display core support")
---
 drivers/auxdisplay/line-display.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/auxdisplay/line-display.c +1 -1
@@ -80,7 +80,7 @@ static int linedisp_display(struct lined
 		count = strlen(msg);
 
 	/* if the string ends with a newline, trim it */
-	if (msg[count - 1] == '\n')
+	if (count && msg[count - 1] == '\n')
 		count--;
 
 	if (!count) {
author maintainer
#111 lore raw

PATCH 97/452 Bluetooth: L2CAP: use chan timer to close channels in cleanup_listen()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Siwei Zhang <[email protected]>

commit 8c8e620467a7b51562dbcefbd1f09f288d7d710d upstream.

l2cap_chan_close() removes the channel from conn->chan_l, which must be done under conn->lock. cleanup_listen() runs under the parent sk_lock, so acquiring conn->lock would invert the established conn->lock -> chan->lock -> sk_lock order.

Instead of calling l2cap_chan_close() directly, schedule l2cap_chan_timeout with delay 0 to close the channel asynchronously. The timeout handler already acquires conn->lock and chan->lock in the correct order.

The timer is only armed when chan->conn is still set: if it is already NULL, l2cap_conn_del() has already processed this channel (l2cap_chan_del + l2cap_sock_teardown_cb + l2cap_sock_close_cb), so there is nothing left to do. If l2cap_conn_del() races in after the timer is armed, __clear_chan_timer() inside l2cap_chan_del() cancels it; if the timer has already fired, the handler returns harmlessly because chan->conn was cleared.

Fixes 3df91ea20e74 ("Bluetooth: Revert to mutexes from RCU list")
Cc <[email protected]> # 0b58004: Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del()
---
 net/bluetooth/l2cap_sock.c |   16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)
net/bluetooth/l2cap_sock.c +9 -7
@@ -1465,6 +1465,10 @@ static void l2cap_sock_cleanup_listen(st
 	 * pin it (hold_unless_zero() additionally skips a chan already past
 	 * its last reference).  We then drop the sk lock before taking
 	 * chan->lock, so sk and chan locks are never held together.
+	 *
+	 * Since we cannot call l2cap_chan_close() without conn->lock,
+	 * schedule l2cap_chan_timeout to close the channel; it already
+	 * acquires conn->lock -> chan->lock in the correct order.
 	 */
 	while ((sk = bt_accept_dequeue(parent, NULL))) {
 		struct l2cap_chan *chan;
@@ -1482,14 +1486,12 @@ static void l2cap_sock_cleanup_listen(st
 		       state_to_string(chan->state));
 
 		l2cap_chan_lock(chan);
-		__clear_chan_timer(chan);
-		l2cap_chan_close(chan, ECONNRESET);
-		/* l2cap_conn_del() may already have killed this socket
-		 * (it sets SOCK_DEAD); skip the duplicate to avoid a
-		 * double sock_put()/l2cap_chan_put().
+		/* Since we cannot call l2cap_chan_close() without
+		 * conn->lock, schedule its timer to trigger the close
+		 * and cleanup of this channel.
 		 */
-		if (!sock_flag(sk, SOCK_DEAD))
-			l2cap_sock_kill(sk);
+		if (chan->conn)
+			__set_chan_timer(chan, 0);
 		l2cap_chan_unlock(chan);
 
 		l2cap_chan_put(chan);
author maintainer
#112 lore raw

PATCH 98/452 Bluetooth: L2CAP: fix chan ref leak in l2cap_chan_timeout() on !conn

In reply to Greg Kroah-Hartman

6.6-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.

Fixes adf0398cee86 ("Bluetooth: l2cap: fix null-ptr-deref in l2cap_chan_timeout")
---
 net/bluetooth/l2cap_core.c |    4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
net/bluetooth/l2cap_core.c +3 -1
@@ -411,8 +411,10 @@ static void l2cap_chan_timeout(struct wo
 
 	BT_DBG("chan %p state %s", chan, state_to_string(chan->state));
 
-	if (!conn)
+	if (!conn) {
+		l2cap_chan_put(chan);
 		return;
+	}
 
 	mutex_lock(&conn->lock);
 	/* __set_chan_timer() calls l2cap_chan_hold(chan) while scheduling
author maintainer
#113 lore raw

PATCH 99/452 Bluetooth: HIDP: fix missing length checks in hidp_input_report()

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Muhammad Bilal <[email protected]>

commit 2a3ac9ee11dbb9845f3947cef4a79dba658cf6f6 upstream.

hidp_input_report() reads keyboard and mouse payload data from an skb without first verifying that skb->len contains enough data.

hidp_recv_intr_frame() pulls the 1-byte HIDP header before dispatching to hidp_input_report(). If a paired device sends a truncated packet, the handler reads beyond the valid skb data, resulting in an out-of-bounds read of skb data. The OOB bytes may be interpreted as phantom key presses or spurious mouse movement.

Replace the open-coded length tracking and pointer arithmetic with skb_pull_data() calls. skb_pull_data() returns NULL if the requested bytes are not present, eliminating the need for a manual size variable and the separate skb->len guard.

---
 net/bluetooth/hidp/core.c |   23 ++++++++++++++++++-----
 1 file changed, 18 insertions(+), 5 deletions(-)
net/bluetooth/hidp/core.c +18 -5
@@ -179,12 +179,21 @@ static void hidp_input_report(struct hid
 {
 	struct input_dev *dev = session->input;
 	unsigned char *keys = session->keys;
-	unsigned char *udata = skb->data + 1;
-	signed char *sdata = skb->data + 1;
-	int i, size = skb->len - 1;
+	unsigned char *udata;
+	signed char *sdata;
+	u8 *hdr;
+	int i;
+
+	hdr = skb_pull_data(skb, 1);
+	if (!hdr)
+		return;
 
-	switch (skb->data[0]) {
+	switch (*hdr) {
 	case 0x01:	/* Keyboard report */
+		udata = skb_pull_data(skb, 8);
+		if (!udata)
+			break;
+
 		for (i = 0; i < 8; i++)
 			input_report_key(dev, hidp_keycode[i + 224], (udata[0] >> i) & 1);
 
@@ -213,6 +222,10 @@ static void hidp_input_report(struct hid
 		break;
 
 	case 0x02:	/* Mouse report */
+		sdata = skb_pull_data(skb, 3);
+		if (!sdata)
+			break;
+
 		input_report_key(dev, BTN_LEFT,   sdata[0] & 0x01);
 		input_report_key(dev, BTN_RIGHT,  sdata[0] & 0x02);
 		input_report_key(dev, BTN_MIDDLE, sdata[0] & 0x04);
@@ -222,7 +235,7 @@ static void hidp_input_report(struct hid
 		input_report_rel(dev, REL_X, sdata[1]);
 		input_report_rel(dev, REL_Y, sdata[2]);
 
-		if (size > 3)
+		if (skb->len > 0)
 			input_report_rel(dev, REL_WHEEL, sdata[3]);
 		break;
 	}
author maintainer
#114 lore raw

PATCH 100/452 Bluetooth: ISO: fix UAF in iso_recv_frame

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Muhammad Bilal <[email protected]>

commit 47f23a259517abbdb8032c057a1e8a6bf3734878 upstream.

iso_recv_frame reads conn->sk under iso_conn_lock but releases the lock before using sk, with no reference held. A concurrent iso_sock_kill() can free sk in that window, causing use-after-free on sk->sk_state and sock_queue_rcv_skb().

Fix by replacing the bare pointer read with iso_sock_hold(conn), which calls sock_hold() while the spinlock is held, atomically elevating the refcount before the lock drops. Add a drop_put label so sock_put() is called on all exit paths where the hold succeeded.

Fixes ccf74f2390d60a2f9a75ef496d2564abb478f46a ("Bluetooth: Add BTPROTO_ISO socket type")
---
 net/bluetooth/iso.c |   10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)
net/bluetooth/iso.c +7 -3
@@ -526,7 +526,7 @@ static void iso_recv_frame(struct iso_co
 	struct sock *sk;
 
 	iso_conn_lock(conn);
-	sk = conn->sk;
+	sk = iso_sock_hold(conn);
 	iso_conn_unlock(conn);
 
 	if (!sk)
@@ -535,11 +535,15 @@ static void iso_recv_frame(struct iso_co
 	BT_DBG("sk %p len %d", sk, skb->len);
 
 	if (sk->sk_state != BT_CONNECTED)
-		goto drop;
+		goto drop_put;
 
-	if (!sock_queue_rcv_skb(sk, skb))
+	if (!sock_queue_rcv_skb(sk, skb)) {
+		sock_put(sk);
 		return;
+	}
 
+drop_put:
+	sock_put(sk);
 drop:
 	kfree_skb(skb);
 }
author maintainer
#115 lore raw

PATCH 101/452 Bluetooth: ISO: serialize iso_sock_clear_timer with socket lock

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Muhammad Bilal <[email protected]>

commit 4b5f8e608749b7e8fa386c6e4301cf9272595859 upstream.

iso_sock_close() calls iso_sock_clear_timer() before acquiring lock_sock(sk).

iso_sock_clear_timer() reads iso_pi(sk)->conn twice without the socket lock held:

    if (!iso_pi(sk)->conn)
        return;
    cancel_delayed_work(&iso_pi(sk)->conn->timeout_work);

Concurrently, iso_conn_del() executes under lock_sock(sk) and calls iso_chan_del(), which sets iso_pi(sk)->conn to NULL and may result in the final reference to the connection being dropped:

    CPU0                         CPU1
    ----                         ----
    iso_sock_clear_timer()
      if (conn != NULL) ...      lock_sock(sk)
                                   iso_chan_del()
                                   iso_pi(sk)->conn = NULL
      cancel_delayed_work(conn)  /* NULL deref or UAF */

iso_pi(sk)->conn is not stable across the unlock window, causing a NULL pointer dereference or use-after-free.

Serialize iso_sock_clear_timer() with the socket lock by moving it inside lock_sock()/release_sock(), matching the pattern used in iso_conn_del() and all other call sites.

Fixes ccf74f2390d60a2f9a75ef496d2564abb478f46a ("Bluetooth: Add BTPROTO_ISO socket type")
---
 net/bluetooth/iso.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
net/bluetooth/iso.c +1 -1
@@ -808,8 +808,8 @@ static void __iso_sock_close(struct sock
 /* Must be called on unlocked socket. */
 static void iso_sock_close(struct sock *sk)
 {
-	iso_sock_clear_timer(sk);
 	lock_sock(sk);
+	iso_sock_clear_timer(sk);
 	__iso_sock_close(sk);
 	release_sock(sk);
 	iso_sock_kill(sk);
author maintainer
#116 lore raw

PATCH 102/452 Input: xpad - fix out-of-bounds access for Share button

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Dmitry Torokhov <[email protected]>

commit 6cdc46b38cf146ce81d4831b6472dbf7731849a2 upstream.

xpadone_process_packet() receives len directly from urb->actual_length and uses it to index the share-button byte at data[len - 18] or data[len - 26]. Since both len and data[0] are under the device's control, a broken controller can send a GIP_CMD_INPUT packet with actual_length < 18 (e.g. 5 bytes) and reach this code path, causing accesses beyond the actual array.

Fix this by calculating the offset and checking bounds against the packet length.

Fixes 4ef46367073b ("Input: xpad - fix Share button on Xbox One controllers")
---
 drivers/input/joystick/xpad.c |    8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/input/joystick/xpad.c +4 -4
@@ -1079,10 +1079,10 @@ static void xpadone_process_packet(struc
 		input_report_key(dev, BTN_START,  data[4] & BIT(2));
 		input_report_key(dev, BTN_SELECT, data[4] & BIT(3));
 		if (xpad->mapping & MAP_SHARE_BUTTON) {
-			if (xpad->mapping & MAP_SHARE_OFFSET)
-				input_report_key(dev, KEY_RECORD, data[len - 26] & BIT(0));
-			else
-				input_report_key(dev, KEY_RECORD, data[len - 18] & BIT(0));
+			u32 offset = (xpad->mapping & MAP_SHARE_OFFSET) ? 26 : 18;
+
+			if (len >= offset)
+				input_report_key(dev, KEY_RECORD, data[len - offset] & BIT(0));
 		}
 
 		/* buttons A,B,X,Y */
author maintainer
#117 lore raw

PATCH 103/452 parport: Fix race between port and client registration

In reply to Greg Kroah-Hartman

6.6-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 parpor
 		if (slave)
 			attach_driver_chain(slave);
 	}
+	set_bit(PARPORT_ANNOUNCED, &port->devflags);
 	mutex_unlock(&registration_lock);
 }
 EXPORT_SYMBOL(parport_announce_port);
@@ -582,6 +587,8 @@ void parport_remove_port(struct parport
 
 	mutex_lock(&registration_lock);
 
+	clear_bit(PARPORT_ANNOUNCED, &port->devflags);
+
 	/* Spread the word. */
 	detach_driver_chain(port);
 
include/linux/parport.h +1 -0
@@ -242,6 +242,7 @@ struct parport {
 
 	unsigned long devflags;
 #define PARPORT_DEVPROC_REGISTERED	0
+#define PARPORT_ANNOUNCED		1
 	struct pardevice *proc_device;	/* Currently register proc device */
 
 	struct list_head full_list;
author maintainer
#118 lore raw

PATCH 104/452 USB: cdc-acm: Fix bit overlap and move quirk definitions to header

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Wentao Guan <[email protected]>

commit 5eb070769ea5e18405535609d1d3f6886f3755bd upstream.

The VENDOR_CLASS_DATA_IFACE and ALWAYS_POLL_CTRL quirk flags added in commit f58752ebcb35 ("USB: cdc-acm: Add quirks for Yoga Book 9 14IAH10 INGENIC touchscreen") were placed inside the acm_ctrl_msg() function rather than in the header with the other quirk flags. Then, their values (BIT(9) and BIT(10)) collided with NO_UNION_12 which is already BIT(9).

Move the definitions to drivers/usb/class/cdc-acm.h where they belong and shift them to BIT(10) and BIT(11) to avoid the overlap.

Fixes f58752ebcb35 ("USB: cdc-acm: Add quirks for Yoga Book 9 14IAH10 INGENIC touchscreen")
Cc stable <[email protected]>
---
 drivers/usb/class/cdc-acm.c |    2 --
 drivers/usb/class/cdc-acm.h |    2 ++
 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/usb/class/cdc-acm.c +0 -2
@@ -114,8 +114,6 @@ static int acm_ctrl_msg(struct acm *acm,
 	int retval;
 
 	retval = usb_autopm_get_interface(acm->control);
-#define VENDOR_CLASS_DATA_IFACE		BIT(9)  /* data interface uses vendor-specific class */
-#define ALWAYS_POLL_CTRL		BIT(10) /* keep ctrl URB active even without an open TTY */
 	if (retval)
 		return retval;
 
drivers/usb/class/cdc-acm.h +2 -0
@@ -115,3 +115,5 @@ struct acm {
 #define DISABLE_ECHO			BIT(7)
 #define MISSING_CAP_BRK			BIT(8)
 #define NO_UNION_12			BIT(9)
+#define VENDOR_CLASS_DATA_IFACE		BIT(10)  /* data interface uses vendor-specific class */
+#define ALWAYS_POLL_CTRL		BIT(11) /* keep ctrl URB active even without an open TTY */
author maintainer
#119 lore raw

PATCH 105/452 KVM: arm64: PMU: Preserve AArch32 counter low bits

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Qiang Ma <[email protected]>

commit 1750ad1388e03fb27068cd1f22c9c8b4590fe936 upstream.

AArch32 writes to PMU event counters cannot update the top 32 bits, even when PMUv3p5 makes the counters 64-bit. KVM therefore needs to preserve the existing high half and only update the low half written by the guest, unless the caller explicitly forces a full reset through PMCR.P.

The current code masks @val down to the old high half before taking lower_32_bits(val), which means the low half is always zero. As a result, AArch32 writes to event counters discard the guest-provided low 32 bits instead of storing them.

Build the new value from the old high 32 bits and the low 32 bits of the value supplied by the guest.

Fixes 26d2d0594d70 ("KVM: arm64: PMU: Do not let AArch32 change the counters' top 32 bits")
---
 arch/arm64/kvm/pmu-emul.c |    4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)
arch/arm64/kvm/pmu-emul.c +2 -2
@@ -146,8 +146,8 @@ static void kvm_pmu_set_pmc_value(struct
 		 * action is to use PMCR.P, which will reset them to
 		 * 0 (the only use of the 'force' parameter).
 		 */
-		val  = __vcpu_sys_reg(vcpu, reg) & GENMASK(63, 32);
-		val |= lower_32_bits(val);
+		val = (__vcpu_sys_reg(vcpu, reg) & GENMASK(63, 32)) |
+		      lower_32_bits(val);
 	}
 
 	__vcpu_sys_reg(vcpu, reg) = val;
author maintainer
#120 lore raw

PATCH 106/452 KVM: SVM: Flush the current TLB when transitioning from xAVIC => x2AVIC

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Sean Christopherson <[email protected]>

commit a9e18aa3263f356edae305e29830e5fe63d8597a upstream.

Flush the current TLB when xAVIC *or* x2AVIC is activated, as KVM is (apparently) responsible for purging TLB entries when transitioning from xAVIC to x2AVIC. The APM says a whole lot of nothing about TLB flushing with respect to (x2)AVIC, but empirical data strongly suggests hardware also does a whole lot of nothing.

Failure to flush the TLB when enabling x2AVIC can lead to guest accesses to the APIC base address getting incorrectly redirected to the virtual APIC page. The flaw most visibly manifests as failures in KVM-Unit-Test's verify_disabled_apic_mmio() testcase when x2APIC is enabled (though for reasons unknown, the test only reliably fails with EFI builds).

Fixes 0ccf3e7cb95a ("KVM: SVM: Flush the "current" TLB when activating AVIC")
Fixes 4d1d7942e36a ("KVM: SVM: Introduce logic to (de)activate x2AVIC mode")
Cc Naveen N Rao (AMD) <[email protected]>
---
 arch/x86/kvm/svm/avic.c |   35 +++++++++++++++++++++++++++++------
 1 file changed, 29 insertions(+), 6 deletions(-)
arch/x86/kvm/svm/avic.c +29 -6
@@ -111,6 +111,35 @@ static void avic_activate_vmcb(struct vc
 	svm_clr_intercept(svm, INTERCEPT_CR8_WRITE);
 
 	/*
+	 * Flush the TLB when enabling (x2)AVIC and when transitioning between
+	 * xAVIC and x2AVIC, as the CPU may have inserted a TLB entry for the
+	 * "wrong" mapping.
+	 *
+	 * KVM uses a per-VM "scratch" page to back the APIC memslot, because
+	 * KVM also uses per-VM page tables *and* maintains the page table (NPT
+	 * or shadow page) mappings for said memslot even if one or more vCPUs
+	 * have their local APIC hardware-disabled or are in x2APIC mode, i.e.
+	 * even if one or more vCPUs' APIC MMIO BAR is effectively disabled.
+	 *
+	 * If xAVIC is fully enabled, hardware ignores the physical address in
+	 * KVM's page tables, i.e. in the leaf SPTE for the APIC memslot, and
+	 * instead redirects the access to the AVIC backing page, i.e. to the
+	 * vCPU's virtual APIC page.  If xAVIC is not enabled (APIC is either
+	 * hardware-disabled or in x2APIC mode), then guest accesses will use
+	 * the page table mapping verbatim, i.e. will access the per-VM scratch
+	 * page, as normal memory.
+	 *
+	 * In both cases, the CPU is allowed to cache TLB entries for the APIC
+	 * base GPA.  So, KVM needs to flush the TLB when enabling xAVIC, as
+	 * accesses need to be redirected to the virtual APIC page, but the TLB
+	 * may contain entries pointing at the scratch page.  KVM also needs to
+	 * flush the TLB when enabling x2AVIC, as accesses need to go to the
+	 * scratch page, but the TLB may contain entries tagged as xAVIC, i.e.
+	 * entries pointing to the vCPU's virtual APIC page.
+	 */
+	kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, &svm->vcpu);
+
+	/*
 	 * Note: KVM supports hybrid-AVIC mode, where KVM emulates x2APIC MSR
 	 * accesses, while interrupt injection to a running vCPU can be
 	 * achieved using AVIC doorbell.  KVM disables the APIC access page
@@ -123,12 +152,6 @@ static void avic_activate_vmcb(struct vc
 		/* Disabling MSR intercept for x2APIC registers */
 		svm_set_x2apic_msr_interception(svm, false);
 	} else {
-		/*
-		 * Flush the TLB, the guest may have inserted a non-APIC
-		 * mapping into the TLB while AVIC was disabled.
-		 */
-		kvm_make_request(KVM_REQ_TLB_FLUSH_CURRENT, &svm->vcpu);
-
 		/* Enabling MSR intercept for x2APIC registers */
 		svm_set_x2apic_msr_interception(svm, true);
 	}
author maintainer
#121 lore raw

PATCH 107/452 wireguard: send: append trailer after expanding head

In reply to Greg Kroah-Hartman

6.6-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.
 	 */
author maintainer
#122 lore raw

PATCH 108/452 iio: adc: xilinx-xadc: Fix sequencer mode in postdisable for dual mux

In reply to Greg Kroah-Hartman

6.6-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
@@ -818,6 +818,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;
 
@@ -825,6 +826,12 @@ static int xadc_postdisable(struct iio_d
 	for (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)
@@ -835,11 +842,11 @@ static int xadc_postdisable(struct iio_d
 		return 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)
author maintainer
#123 lore raw

PATCH 109/452 iio: dac: max5821: fix return value check in powerdown sync

In reply to Greg Kroah-Hartman

6.6-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).

Fixes 472988972737 ("iio: add support of the max5821")
---
 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(s
 	else
 		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,
author maintainer
#124 lore raw

PATCH 110/452 iio: dac: ad5686: fix input raw value check

In reply to Greg Kroah-Hartman

6.6-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.

Fixes c2f37c8dcadc ("iio: dac: New driver for AD5686R, AD5685R, AD5684R Digital to analog converters")
---
 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_d
 
 	switch (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);
author maintainer
#125 lore raw

PATCH 111/452 iio: dac: ad5686: acquire lock when doing powerdown control

In reply to Greg Kroah-Hartman

6.6-stable review patch. If anyone has any objections, please let me know.

------------------

From: Rodrigo Alencar <[email protected]>

commit 5237c3175cae5ab05f18878cec3301a04403859e upstream.

Protect access of pwr_down_mode and pwr_down_mask fields with existing mutex lock. Each channel exposes their own attributes for controlling powerdown modes and powerdown state. This fixes potential race conditions as those the write functions perform non-atomic read-modify-write operations to those pwr_down_* fields. This issue exists since the ad5686 driver was first introduced.

Fixes c2f37c8dcadc ("iio: dac: New driver for AD5686R, AD5685R, AD5684R Digital to analog converters")
---
 drivers/iio/dac/ad5686.c |    8 ++++++++
 1 file changed, 8 insertions(+)
drivers/iio/dac/ad5686.c +8 -0
@@ -30,6 +30,8 @@ static int ad5686_get_powerdown_mode(str
 {
 	struct ad5686_state *st = iio_priv(indio_dev);
 
+	guard(mutex)(&st->lock);
+
 	return ((st->pwr_down_mode >> (chan->channel * 2)) & 0x3) - 1;
 }
 
@@ -39,6 +41,8 @@ static int ad5686_set_powerdown_mode(str
 {
 	struct ad5686_state *st = iio_priv(indio_dev);
 
+	guard(mutex)(&st->lock);
+
 	st->pwr_down_mode &= ~(0x3 << (chan->channel * 2));
 	st->pwr_down_mode |= ((mode + 1) << (chan->channel * 2));
 
@@ -57,6 +61,8 @@ static ssize_t ad5686_read_dac_powerdown
 {
 	struct ad5686_state *st = iio_priv(indio_dev);
 
+	guard(mutex)(&st->lock);
+
 	return sysfs_emit(buf, "%d\n", !!(st->pwr_down_mask &
 				       (0x3 << (chan->channel * 2))));
 }
@@ -77,6 +83,8 @@ static ssize_t ad5686_write_dac_powerdow
 	if (ret)
 		return ret;
 
+	guard(mutex)(&st->lock);
+
 	if (readin)
 		st->pwr_down_mask |= (0x3 << (chan->channel * 2));
 	else
author maintainer
#126 lore raw

PATCH 112/452 iio: adc: viperboard: Fix error handling in vprbrd_iio_read_raw

In reply to Greg Kroah-Hartman

6.6-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 ii
 			VPRBRD_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,
author maintainer
#127 lore raw

PATCH 113/452 iio: gyro: itg3200: fix i2c read into the wrong stack location

In reply to Greg Kroah-Hartman

6.6-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,
 		},
 	};
 
author maintainer
#128 lore raw

PATCH 114/452 iio: ssp_sensors: cancel delayed work_refresh on remove

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 50dd64d57eee ("iio: common: ssp_sensors: Add sensorhub driver")
---
 drivers/iio/common/ssp_sensors/ssp_dev.c |    1 +
 1 file changed, 1 insertion(+)
drivers/iio/common/ssp_sensors/ssp_dev.c +1 -0
@@ -590,6 +590,7 @@ static void ssp_remove(struct spi_device
 	ssp_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);
author maintainer
#129 lore raw

PATCH 115/452 iio: temperature: tsys01: fix broken PROM checksum validation

In reply to Greg Kroah-Hartman

6.6-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.

Fixes 43e53407f680 ("Add tsys01 meas-spec driver support")
---
 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_prom
 	u8 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);
 }