6.6.151-rc1 review
Subsystems (3)
Greg Kroah-Hartman
maintainercover 6.6.151-rc1 review
This is the start of the stable review cycle for the 6.6.151 release. There are 261 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 Sun, 09 Aug 2026 14:33:46 +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.151-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.151-rc1
Andrei Kuchynski <[email protected]>
usb: typec: ucsi: Correct teardown ordering in ucsi_init() error path
Thomas Zimmermann <[email protected]>
drm/tegra: fbdev: Do not assign to struct drm_fb_helper.info
Kai Vehmanen <[email protected]>
ALSA: hda: codecs: hdmi: disable keep-alive before audio format change
Jani Nikula <[email protected]>
drm/i915/hdcp: check streams[] bounds before overflow
Jani Nikula <[email protected]>
drm/i915/hdcp: require monotonically increasing seq_num_v
Suraj Kandpal <[email protected]>
drm/i915/hdcp: Move to using intel_display in intel_hdcp
Jani Nikula <[email protected]>
drm/i915/hdcp: migrate away from kdev_to_i915() in bind/unbind
Ville Syrjälä <[email protected]>
drm/i915/fbc: Extract intel_fbc_has_fences()
Zhiling Zou <[email protected]>
sctp: close UDP tunnel sockets during netns teardown
Geliang Tang <[email protected]>
mptcp: pm: userspace: fix use-after-free in get_local_id
Geliang Tang <[email protected]>
mptcp: pm: use addr entry for get_local_id
Geliang Tang <[email protected]>
mptcp: add mptcp_userspace_pm_lookup_addr helper
Geliang Tang <[email protected]>
mptcp: pm: avoid code duplication to lookup endp
WenTao Liang <[email protected]>
ceph: fix refcount leak in ceph_readdir()
Xiubo Li <[email protected]>
ceph: print cluster fsid and client global_id in all debug logs
Xiubo Li <[email protected]>
libceph: add doutc and *_client debug macros support
Oliver Hartkopp <[email protected]>
can: isotp: fix timer drain order, wakeup handling and tx_gen ordering
Oliver Hartkopp <[email protected]>
can: use skb hash instead of private variable in headroom
Zhiling Zou <[email protected]>
sctp: avoid auth_enable sysctl UAF during netns teardown
Thomas Weißschuh <[email protected]>
sysctl: treewide: constify ctl_table_header::ctl_table_arg
Fan Wu <[email protected]>
wifi: brcmfmac: drain bus_reset work on device removal
LiangCheng Wang <[email protected]>
wifi: brcmfmac: set F2 blocksize to 256 for BCM43752
Gokul Sivakumar <[email protected]>
wifi: brcmfmac: fix 43752 SDIO FWVID incorrectly labelled as Cypress (CYW)
Daniel Hodges <[email protected]>
wifi: ath6kl: fix use-after-free in aggr_reset_state()
Mirela Rabulea <[email protected]>
media: v4l2-fwnode: Fix subdev owner overwritten in v4l2_async_register_subdev_sensor()
Sakari Ailus <[email protected]>
media: v4l: async: Set owner for async sub-devices
Pablo Neira Ayuso <[email protected]>
netfilter: nf_tables: clone set on flush only
David Howells <[email protected]>
rxrpc: Fix irq-disabled in local_bh_enable()
Sakari Ailus <[email protected]>
media: imx219: Fix maximum frame length in lines
Jai Luthra <[email protected]>
media: i2c: imx219: Rename VTS to FRM_LENGTH
Laurent Pinchart <[email protected]>
media: i2c: imx219: Calculate crop rectangle dynamically
Laurent Pinchart <[email protected]>
media: i2c: imx219: Group functions by purpose
Laurent Pinchart <[email protected]>
media: i2c: imx219: Drop IMX219_VTS_* macros
Laurent Pinchart <[email protected]>
media: i2c: imx219: Don't store the current mode in the imx219 structure
Laurent Pinchart <[email protected]>
media: i2c: imx219: Access height from active format in imx219_set_ctrl
Jani Nikula <[email protected]>
drm/i915/vrr: require valid min/max vfreq for VRR
Ville Syrjälä <[email protected]>
drm/i915/vrr: Check HAS_VRR() first in intel_vrr_is_capable()
Timur Kristóf <[email protected]>
drm/amdgpu: Respect placement requirements in amdgpu_gtt_mgr functions
Thomas Zimmermann <[email protected]>
drm/tegra: fbdev: Remove offset into framebuffer memory
Thomas Zimmermann <[email protected]>
drm/fb-helper: Allocate and release fb_info in single place
Andrei Kuchynski <[email protected]>
usb: typec: ucsi: Fix race condition and ordering in port unregistration
Sergey Senozhatsky <[email protected]>
usb: typec: ucsi: split connector lock classes
Diogo Ivo <[email protected]>
usb: typec: ucsi: Only enable supported notifications
Cen Zhang <[email protected]>
usb: gadget: f_tcm: synchronize delayed set_alt with teardown
Biju Das <[email protected]>
drm: renesas: rzg2l_mipi_dsi: Increase reset deassertion delay
Lad Prabhakar <[email protected]>
drm: renesas: Move RZ/G2L MIPI DSI driver to rz-du
Guangshuo Li <[email protected]>
usb: musb: omap2430: Do not put borrowed of_node in probe
Johan Hovold <[email protected]>
usb: musb: omap2430: clean up probe error handling
Frank Scheiner <[email protected]>
Revert "ia64: Make acpi_cpufreq_cpu_exit return void"
Junjie Cao <[email protected]>
gpio: pch: use raw_spinlock_t for the register lock
Tze Yee Ng <[email protected]>
firmware: stratix10-svc: fix memory leaks and list corruption bugs
Kiryl Shutsemau (Meta) <[email protected]>
mm/huge_memory: unlock i_mmap_rwsem before releasing after-split folios
Kiryl Shutsemau (Meta) <[email protected]>
mm/hugetlb: fix swap entry corruption when clearing uffd-wp at fork()
Wei Yang <[email protected]>
iommu/sva: move x86 disable check before allocation
Niklas Cassel <[email protected]>
ata: ahci: Make ahci_ignore_port() handle empty mask_port_map
Damien Le Moal <[email protected]>
ata: libahci_platform: Do not set mask_port_map when not needed
HyeongJun An <[email protected]>
HID: logitech-dj: Fix maxfield check in DJ short report validation
Jun Guo <[email protected]>
spi: spi-cadence: enable SPI_CONTROLLER_MUST_TX
Zack Rusin <[email protected]>
drm/vmwgfx: validate external BO copy bounds for both stride paths
Zack Rusin <[email protected]>
drm/vmwgfx: use check_add_overflow for shader size+offset bound
Zack Rusin <[email protected]>
drm/vmwgfx: bound DMA command body size against suffix pointer
Zack Rusin <[email protected]>
drm/vmwgfx: validate DRAW_PRIMITIVES header size before division
Zack Rusin <[email protected]>
drm/vmwgfx: drop dma_buf reference on foreign-fd prime import
Zack Rusin <[email protected]>
drm/vmwgfx: reject DX_BIND_QUERY without a DX context
Zack Rusin <[email protected]>
drm/vmwgfx: fix guest_memory_dirty bitfield clobbered as size
William Palacek <[email protected]>
drm/amdkfd: hold event_mutex while checkpointing CRIU events
David Francis <[email protected]>
drm/amdkfd: Handle invalid event type in CRIU event restore
Vladimir Marioukhine <[email protected]>
drm/amdkfd: fix QID bit leak in pqm_create_queue()
Gang Ba <[email protected]>
drm/amdkfd: Fix missing authorization check in KFD_IOC_DBG_TRAP_DISABLE
Harkirat Gill <[email protected]>
drm/amdgpu: cap GTT size to physical RAM on APUs
Candice Li <[email protected]>
drm/amdgpu: restore UMD profile pstate after runtime resume
Myeonghun Pak <[email protected]>
drm/mediatek: ovl_adaptor: balance component registrations
Maíra Canal <[email protected]>
drm/vc4: Zero the tile state data array before each BIN job
Jose Maria Casanova Crespo <[email protected]>
drm/vc4: Supply the overflow slot size in BPOS, not the whole bin BO size
Alexander Kaplan <[email protected]>
drm/dp: Read the PCON max FRL bandwidth only for HDMI DFPs
Avi Weiss <[email protected]>
can: ctucanfd: mark error-active controller status valid
Avi Weiss <[email protected]>
can: ctucanfd: handle bus error interrupts
Avi Weiss <[email protected]>
can: ctucanfd: unmap BAR0 using base address
Avi Weiss <[email protected]>
can: ctucanfd: use self-test mode for PRESUME_ACK
Pengpeng Hou <[email protected]>
can: ctucanfd: add missing MODULE_DEVICE_TABLE()
Pengpeng Hou <[email protected]>
can: peak_usb: validate uCAN receive record lengths
Maoyi Xie <[email protected]>
can: peak_usb: peak_usb_start(): fix double free of transfer buffer on URB submit error
James Gao <[email protected]>
can: peak_usb: add bounds check for USB channel index
Pengpeng Hou <[email protected]>
can: softing: fw_parse(): validate firmware record spans
Pengpeng Hou <[email protected]>
can: kvaser_usb_leaf: kvaser_usb_leaf_wait_cmd(): validate received command extents
Abdun Nihaal <[email protected]>
can: kvaser_usb: kvaser_usb_hydra_get_busparams(): fix memory leak in kvaser_usb_hydra_get_busparams()
Tetsuo Handa <[email protected]>
can: j1939: use netdevice_tracker for j1939_{priv,session,ecu} tracking
Oleksij Rempel <[email protected]>
can: j1939: transport: j1939_session_fresh_new(): initialize receive buffer
Marc Kleine-Budde <[email protected]>
can: gs_usb: gs_usb_receive_bulk_callback(): resubmit URB on skb allocation failure
Guangshuo Li <[email protected]>
can: etas_es58x: es58x_read_bulk_callback(): fix RX buffer leak on URB resubmit failure
Pengpeng Hou <[email protected]>
can: ems_usb: validate CPC message lengths
Lucas Martins Alves <[email protected]>
can: c_can: c_can_chip_config(): keep controller in init mode until bittiming is configured
Liem <[email protected]>
i2c: imx: Cancel hrtimer before clearing slave pointer
Liem <[email protected]>
i2c: imx: Fix slave registration race and error handling
H. Nikolaus Schaller <[email protected]>
i2c: jz4780: Cache host clock rate at probe to prevent CCF prepare_lock deadlock
Dawei Feng <[email protected]>
ice: fix memory leak in ice_lbtest_prepare_rings()
Aaron Ma <[email protected]>
ice: wait for reset completion in ice_resume()
Ilya Maximets <[email protected]>
net: openvswitch: fix skb leak on flow key update failure during ct
Ilya Maximets <[email protected]>
net: openvswitch: fix skb leak on flow key update failure during recirculation
Ilya Maximets <[email protected]>
net: openvswitch: fix potential UAF on meter attach failure
Nava kishore Manne <[email protected]>
phy: zynqmp: keep SERDES scrambler and 8b/10b enabled for USB
Nava kishore Manne <[email protected]>
phy: zynqmp: use read-modify-write for SERDES scrambler bypass
Nava kishore Manne <[email protected]>
phy: zynqmp: fix L0_TM_DISABLE_SCRAMBLE_ENCODER mask
Holger Dengler <[email protected]>
s390/zcrypt: Validate length for CCA ECC private key requests
Holger Dengler <[email protected]>
s390/zcrypt: Validate length for CCA AES cipher key requests
Harald Freudenberger <[email protected]>
s390/zcrypt: Fix wrong domain value verification with EP11 CPRBs
Stefan Haberland <[email protected]>
s390/dasd: Fix undersized format-check buffer
Jan Höppner <[email protected]>
s390/dasd: Fix potential NULL pointer dereference
Aswin Karuvally <[email protected]>
s390/qeth: Check CAP_NET_ADMIN for private ioctls
Xu Rao <[email protected]>
power: supply: bq25890: fix the -10 C NTC lookup entry
Abdun Nihaal <[email protected]>
cpufreq: powernow-k8: Fix possible memory leak in powernowk8_cpu_init()
bui duc phuc <[email protected]>
gpio: pca953x: fix cache_only and IRQ state on restore_context() failure
Myeonghun Pak <[email protected]>
i2c: amd-mp2: Unregister callback on adapter add failure
Vincent Jardin <[email protected]>
hwmon: (pmbus/core) notify on the hwmon device, not the i2c client
Hongyan Xu <[email protected]>
hwmon: (npcm750-pwm-fan): stop fan timer on device detach
Asim Viladi Oglu Manizada <[email protected]>
sctp: prevent peer transport count overflow
Yuxiang Yang <[email protected]>
sctp: reject stale cookies with mismatched verification tags
Ibrahim Hashimov <[email protected]>
scsi: scsi_debug: Fix REPORT ZONES alloc_len underflow OOB write
Chris Gellermann <[email protected]>
selftests/clone3: fix wild pointer access of getline due to missing init
Chris Gellermann <[email protected]>
selftests/mm: fix potential wild pointer access of getline due to missing init
Vijaya Krishna Nivarthi <[email protected]>
spi: qcom-qspi: Correct max DMA length to avoid 64K boundary failure
Masami Hiramatsu (Google) <[email protected]>
tracing/filters: Fix false positive match in regex_match_full()
Masami Hiramatsu (Google) <[email protected]>
tracing: Check return value of __register_event() in trace_module_add_events()
Ming Lei <[email protected]>
ublk: reset kernel-owned dev_info fields in ublk_ctrl_add_dev()
Eric Dumazet <[email protected]>
vxlan: use pskb_network_may_pull() in route_shortcircuit()
Eric Dumazet <[email protected]>
vxlan: use neigh_ha_snapshot() in route_shortcircuit()
Eric Dumazet <[email protected]>
vxlan: unclone skb head before modifying eth header in route_shortcircuit()
Eric Dumazet <[email protected]>
vxlan: re-fetch eth header after route_shortcircuit()
Michael Bommarito <[email protected]>
um: vector: fix use-after-free in vector_mmsg_rx()
Thorsten Blum <[email protected]>
powerpc/ps3: Fix map failure path in dma_ioc0_map_pages()
Zhiling Zou <[email protected]>
net: ipv6: clear suppressed fib6 rule result
Zhiling Zou <[email protected]>
net: bridge: stop fast-leave after deleting a port group
Link Lin <[email protected]>
mm/page_reporting: use system_freezable_wq to fix UAF during suspend
Christian Brauner <[email protected]>
binfmt_misc: reject a flag character as the field delimiter
Zhao Li <[email protected]>
wifi: mwifiex: use the subframe length when parsing A-MSDU TDLS frames
Zihan Xi <[email protected]>
tipc: avoid use-after-free in poll trace queue dumps
David Lee <[email protected]>
netfilter: ipset: do not update comments from kernel-side hash adds
Xuanqiang Luo <[email protected]>
net/smc: fix socket use-after-free during link group termination
Zhiling Zou <[email protected]>
ipvs: do not propagate one-packet flag to synced conns
Matt Vollrath <[email protected]>
igbvf: Fix leak in TX DMA error cleanup
Dawei Feng <[email protected]>
e1000: fix memory leak in e1000_probe()
Md Sadre Alam <[email protected]>
dmaengine: qcom: bam_dma: Fix command element mask field for BAM v1.6.0+
Sonali Pradhan <[email protected]>
ALSA: usb-audio: Clamp frame size in implicit-feedback mode
Sonali Pradhan <[email protected]>
ALSA: usb-audio: Fix DMA buffer out-of-bounds write when fill_max is set
Baul Lee <[email protected]>
ALSA: usb-audio: fix OOB write in snd_usbmidi_akai_output()
Baul Lee <[email protected]>
ALSA: usb-audio: fix use-after-free in ump_to_endpoint()
Matt Vollrath <[email protected]>
ata: libata-eh: Increase STANDBY IMMEDIATE timeout
Haidar Lee <[email protected]>
ASoC: tas2562: fix broken entries in the volume lookup table
Haidar Lee <[email protected]>
ASoC: tas2562: fix DVC coefficient write order
Baul Lee <[email protected]>
ALSA: ump: fix double free of out_cvts on rawmidi error
Norbert Szetei <[email protected]>
ALSA: pcm: wake linked drain waiters on unlink
Xu Rao <[email protected]>
ALSA: lx6464es: fix period byte count for 16-bit streams
Takashi Iwai <[email protected]>
ALSA: 6fire: Fix UAF at error handling during probe
Xuanqiang Luo <[email protected]>
bpf: lwt: Fix dst reference leak on reroute failure
Sangho Lee <[email protected]>
Bluetooth: HIDP: validate numbered report payloads
Sangho Lee <[email protected]>
Bluetooth: HIDP: reject frames without a transaction header
Zihan Xi <[email protected]>
Bluetooth: mgmt: fix UAF in pair command cancellation
Zihan Xi <[email protected]>
Bluetooth: mgmt: fix pending command UAF in EIR updates
Greg Kroah-Hartman <[email protected]>
Bluetooth: btmtk: Fix short read errors in btmtk_usb_uhw_reg_read()
Luxiao Xu <[email protected]>
audit: fix potential use-after-free in audit_del_rule()
Zhan Xusheng <[email protected]>
audit: fix potential integer overflow in audit_log_n_string()
Charles Vosburgh <[email protected]>
sctp: validate Adaptation Indication parameter length
Farhan Ali <[email protected]>
KVM: s390: pci: Validate AIBV and AISB before pinning guest pages
Farhan Ali <[email protected]>
KVM: s390: pci: Fix NULL dereference on AIBV allocation failure
Farhan Ali <[email protected]>
KVM: s390: pci: Reject adapter interrupt forwarding if already enabled
Sean Christopherson <[email protected]>
KVM: SVM: Update x2APIC MSR intercepts if AVIC is inhibited while L2 is active
Raushan Patel <[email protected]>
tracing/probes: Reject $arg0 in meta argument expansion
Gregory Price <[email protected]>
mm/vmstat: fold stranded per-cpu node stats when a node comes online
Xiangfeng Cai <[email protected]>
mm/hugetlb: fix list corruption in allocate_file_region_entries()
Zi Yan <[email protected]>
mm/percpu-km: fix bitmap overflow and accounting in pcpu_create_chunk()
Benjamin Boortz <[email protected]>
pinctrl: bm1880: add missing select GENERIC_PINCONF
Michael Bommarito <[email protected]>
erofs: cap LZMA stream pool size
Karl Mehltretter <[email protected]>
pinctrl: devicetree: don't free uninitialized dev_name on error path
Benjamin Boortz <[email protected]>
pinctrl: microchip-sgpio: add missing select REGMAP_MMIO
Cen Zhang (Microsoft) <[email protected]>
rhashtable: clear stale iter->p on table restart
Pengfei Zhang <[email protected]>
ipv6: fib6: fix NULL deref in fib6_walk_continue() on multi-batch dump
Namjae Jeon <[email protected]>
ksmbd: fix use-after-free in __close_file_table_ids()
Namjae Jeon <[email protected]>
ksmbd: return success for deferred final close
Denis V. Lunev <[email protected]>
qede: sync udp_tunnel ports outside qede_lock in the recovery path
Suman Ghosh <[email protected]>
octeontx2-pf: Set correct sequence for carrier off and tx queue stop
Daniel Golle <[email protected]>
net: dsa: mt7530: error out on failed reads in MT7531 PHY polling
Muhammad Bilal <[email protected]>
accel/qaic: use sizeof(*trans_hdr) for transaction length check
Masami Hiramatsu (Google) <[email protected]>
tracing/mmiotrace: Reset dropped_count in mmio_reset_data()
Minhong He <[email protected]>
can: isotp: check register_netdevice_notifier() error in module init
Chenguang Zhao <[email protected]>
net: sxgbe: check descriptor ring allocation failures
Chenguang Zhao <[email protected]>
net: sxgbe: free TX rings on RX allocation failure
Leon Romanovsky <[email protected]>
scsi: target: Clear cmd_cnt when initial counter enrollment fails
Benjamin Block <[email protected]>
scsi: zfcp: Fix memory leak during adapter release by destroying gid_pn_req
Guangshuo Li <[email protected]>
scsi: ufs: core: Cancel RTC work in active-active suspend
TanZheng <[email protected]>
scsi: target: iblock: Fix wrong PR ops NULL check for PREEMPT/RELEASE
Christian Marangi <[email protected]>
net: phylink: put link_gpio if phylink_create fails
Pauli Virtanen <[email protected]>
Bluetooth: hci_sync: remove unnecessary hci_conn_get in create_conn_sync
Pauli Virtanen <[email protected]>
Bluetooth: hci_sync: fix hci_conn_del() use in hci_le_create_conn_sync
Pauli Virtanen <[email protected]>
Bluetooth: hci_conn: hold conn reference in abort_conn_sync()
Pauli Virtanen <[email protected]>
Bluetooth: hci_sync: make hci_cmd_sync_run_once return -EEXIST if exists
Zijun Hu <[email protected]>
Bluetooth: btintel: Validate length before parsing diagnostics TLV
Pauli Virtanen <[email protected]>
Bluetooth: ISO: fix timeout vs sync_timeout typo in check_bcast_qos
Jiale Yao <[email protected]>
Bluetooth: L2CAP: fix UAF in l2cap_le_connect_rsp
Pauli Virtanen <[email protected]>
Bluetooth: ISO: clear iso_data always when detaching conn from hcon
Guenter Roeck <[email protected]>
hwmon: (pmbus) Fix return value from pmbus_update_byte_data()
Zhao Li <[email protected]>
wifi: mac80211: validate individual TWT params before driver setup
Thorsten Blum <[email protected]>
powerpc/boot: Fix treeboot-akebono CPU node lookup check
Thorsten Blum <[email protected]>
powerpc/boot: Fix treeboot-currituck CPU node lookup check
Thorsten Blum <[email protected]>
powerpc/boot: Fix simpleboot CPU node lookup check
Luiz Angelo Daros de Luca <[email protected]>
hwmon: (adt7470) Fix PWM auto temp state array and bounds check
Luiz Angelo Daros de Luca <[email protected]>
hwmon: (adt7470) Fix divide-by-zero TOCTOU crash in fan speed read
Luiz Angelo Daros de Luca <[email protected]>
hwmon: (adt7470) Use cached PWM frequency value
Luiz Angelo Daros de Luca <[email protected]>
hwmon: (adt7470) Fix swapped PWM3 and PWM4 auto mode masks
Luiz Angelo Daros de Luca <[email protected]>
hwmon: (adt7470) Fix temperature alarm logic in hwmon_temp_read()
Luiz Angelo Daros de Luca <[email protected]>
hwmon: (adt7470) Fix busy-loop and I2C flooding in update thread
Luiz Angelo Daros de Luca <[email protected]>
hwmon: (adt7470) Fix cache updated before hardware write on I2C error
Luiz Angelo Daros de Luca <[email protected]>
hwmon: (adt7470) Fix fans stuck in manual mode on I2C errors
Chenguang Zhao <[email protected]>
forcedeth: fix UAF of txrx_stats in nv_remove
David Corvaglia <[email protected]>
net: bridge: mrp: fix Option TLV length in MRP_Test frames
Guenter Roeck <[email protected]>
hwmon: (nct6775-core) Prevent access to unsupported weight registers
Eric Dumazet <[email protected]>
net: do not send ICMP/NDISC Redirects when peer allocation fails
Guenter Roeck <[email protected]>
hwmon: (nzxt-smart2) DMA-align output buffer
Guenter Roeck <[email protected]>
hwmon: (lm90) Only report alarms if driver is ready
Guenter Roeck <[email protected]>
hwmon: (nct6775-core) Fix number of temperature registers for NCT6116
Srikanth Boyapally <[email protected]>
spi: spi-cadence: Move TX FIFO full busy-wait into FIFO
Jun Guo <[email protected]>
spi: spi-cadence: supports transmission with bits_per_word of 16 and 32
Dawei Feng <[email protected]>
smb: client: fix buffer leaks in SMB1 read and write
Xingui Yang <[email protected]>
scsi: libsas: Fix HA resume deadlock and hisi_sas disk-wake race
HyeongJun An <[email protected]>
scsi: libiscsi_tcp: Bound SCSI Response data segment to the connection buffer
HyeongJun An <[email protected]>
scsi: libiscsi: Fix stale-data leak into the SCSI sense buffer
Mario Limonciello <[email protected]>
pinctrl-amd: Don't clear S4 wake bits at probe
Xiang Mei <[email protected]>
rds: tcp: hold the RCU lock across ipv6_chk_addr() in rds_tcp_laddr_check()
Ilia Gavrilov <[email protected]>
rds: Fix inet6_addr_lst NULL dereference when IPv6 is disabled
Xiang Mei (Microsoft) <[email protected]>
netfilter: nft_payload: fix mask build for partial field offload
Julian Anastasov <[email protected]>
ipvs: do not mangle ICMP replies for non-first fragments
Julian Anastasov <[email protected]>
ipvs: fix places with wrong packet offsets
Julian Anastasov <[email protected]>
ipvs: fix the checksum validations
Kent Overstreet <[email protected]>
sched: Add task_struct->faults_disabled_mapping
Pablo Neira Ayuso <[email protected]>
netfilter: xt_hashlimit: validate hashtable supports XT_HASHLIMIT_RATE_MATCH
Michael Bommarito <[email protected]>
assoc_array: trim the final shortcut word using the current chunk end
Michael Bommarito <[email protected]>
keys: make keyring key-chunk byte order agree with keyring_diff_objects()
Michael Bommarito <[email protected]>
keys: fix out-of-bounds read in keyring_get_key_chunk()
Ruoyu Wang <[email protected]>
drm/mediatek: Check CRTC state before freeing
Xiang Mei <[email protected]>
netfilter: nf_conntrack_sip: widen NAT rewrite delta to s32 in sip_help_tcp()
Radhey Shyam Pandey <[email protected]>
phy: zynqmp: fix runtime PM leak on probe allocation failure
Radhey Shyam Pandey <[email protected]>
phy: zynqmp: fix clock error handling in xpsgtr_phy_init()
Mike Looijmans <[email protected]>
phy-zynqmp: Postpone getting clock rate until actually needed
Johannes Thumshirn <[email protected]>
btrfs: zoned: fix deadlock between metadata writeback and transaction commit
Uday Khare <[email protected]>
ASoC: max98090: fix missing IS_ERR() before PTR_ERR() on mclk lookup
Uday Khare <[email protected]>
ASoC: max98095: fix missing IS_ERR() before PTR_ERR() on mclk lookup
Radhey Shyam Pandey <[email protected]>
ata: ahci_ceva: fix error paths in ceva_ahci_platform_enable_resources()
Damien Le Moal <[email protected]>
ahci: Introduce ahci_ignore_port() helper
Josua Mayer <[email protected]>
ata: libahci_platform: support non-consecutive port numbers
Rosen Penev <[email protected]>
ata: sata_mv: accept 1 or 2 resources in platform probe
Yuho Choi <[email protected]>
dmaengine: idxd: fix fdev setup failure cleanup in idxd_cdev_open()
Hongling Zeng <[email protected]>
dmaengine: sun6i-dma: Fix reclaim descriptors while terminating DMA
Konrad Dybcio <[email protected]>
pinctrl: qcom: sc8280xp: Add missing wakeup entries for GPIO143/151
Michael Bommarito <[email protected]>
thunderbolt: Prevent XDomain delayed work use-after-free on disconnect
Harshal Dev <[email protected]>
soc: qcom: ice: Allow explicit votes on 'iface' clock for ICE
Benjamin Tissoires <[email protected]>
HID: logitech-dj: fix wrong detection of bad DJ_SHORT output report
Lee Jones <[email protected]>
HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated OOB write
Lee Jones <[email protected]>
HID: logitech-dj: Standardise hid_report_enum variable nomenclature
Eddie Phillips <[email protected]>
gve: fix Rx queue stall on alloc failure
Yehyeong Lee <[email protected]>
net: mpls: initialize rtm_tos in mpls_getroute()
Lorenzo Bianconi <[email protected]>
netfilter: br_netfilter: Reallocate headroom if necessary in neigh_hh_bridge()
Pablo Neira Ayuso <[email protected]>
netfilter: nf_conntrack_expect: restore helper propagation via expectation
-------------
Diffstat:
Makefile | 4 +-
arch/powerpc/boot/simpleboot.c | 2 +-
arch/powerpc/boot/treeboot-akebono.c | 2 +-
arch/powerpc/boot/treeboot-currituck.c | 2 +-
arch/powerpc/platforms/ps3/mm.c | 1 +
arch/s390/kvm/pci.c | 28 +-
arch/um/drivers/vector_kern.c | 3 +
arch/x86/kvm/svm/avic.c | 8 -
drivers/accel/qaic/qaic_control.c | 2 +-
drivers/ata/ahci.h | 17 +-
drivers/ata/ahci_brcm.c | 3 +
drivers/ata/ahci_ceva.c | 24 +-
drivers/ata/libahci.c | 1 +
drivers/ata/libahci_platform.c | 38 +-
drivers/ata/libata-eh.c | 8 +
drivers/ata/sata_mv.c | 2 +-
drivers/block/ublk_drv.c | 9 +
drivers/bluetooth/btintel.c | 3 +
drivers/bluetooth/btmtk.c | 50 +-
drivers/cpufreq/ia64-acpi-cpufreq.c | 4 +-
drivers/cpufreq/powernow-k8.c | 1 +
drivers/dma/idxd/cdev.c | 4 +-
drivers/dma/sun6i-dma.c | 11 +-
drivers/firmware/stratix10-svc.c | 10 +-
drivers/gpio/gpio-pca953x.c | 15 +-
drivers/gpio/gpio-pch.c | 28 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 15 +
drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 30 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 12 +
drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 10 +-
drivers/gpu/drm/amd/amdkfd/kfd_events.c | 23 +-
.../gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 2 +-
drivers/gpu/drm/armada/armada_fbdev.c | 12 +-
drivers/gpu/drm/display/drm_dp_helper.c | 12 +
drivers/gpu/drm/drm_fb_helper.c | 41 +-
drivers/gpu/drm/drm_fbdev_dma.c | 12 +-
drivers/gpu/drm/drm_fbdev_generic.c | 12 +-
drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 9 +-
drivers/gpu/drm/gma500/fbdev.c | 13 +-
drivers/gpu/drm/i915/display/intel_display_core.h | 3 +
.../gpu/drm/i915/display/intel_display_device.c | 3 +
drivers/gpu/drm/i915/display/intel_display_types.h | 40 ++
drivers/gpu/drm/i915/display/intel_fbc.c | 9 +-
drivers/gpu/drm/i915/display/intel_fbdev.c | 9 +-
drivers/gpu/drm/i915/display/intel_hdcp.c | 266 ++++----
drivers/gpu/drm/i915/display/intel_vrr.c | 10 +-
drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 +-
drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 6 +-
drivers/gpu/drm/msm/msm_fbdev.c | 9 +-
drivers/gpu/drm/omapdrm/omap_fbdev.c | 9 +-
drivers/gpu/drm/radeon/radeon_fbdev.c | 13 +-
drivers/gpu/drm/renesas/Kconfig | 1 +
drivers/gpu/drm/renesas/Makefile | 1 +
drivers/gpu/drm/renesas/rcar-du/Kconfig | 8 -
drivers/gpu/drm/renesas/rcar-du/Makefile | 2 -
drivers/gpu/drm/renesas/rz-du/Kconfig | 8 +
drivers/gpu/drm/renesas/rz-du/Makefile | 3 +
.../renesas/{rcar-du => rz-du}/rzg2l_mipi_dsi.c | 2 +-
.../{rcar-du => rz-du}/rzg2l_mipi_dsi_regs.h | 0
drivers/gpu/drm/tegra/fbdev.c | 18 +-
drivers/gpu/drm/vc4/vc4_irq.c | 2 +-
drivers/gpu/drm/vc4/vc4_validate.c | 29 +-
drivers/gpu/drm/vmwgfx/ttm_object.c | 7 +-
drivers/gpu/drm/vmwgfx/vmwgfx_blit.c | 39 +-
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 20 +-
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 4 +-
drivers/gpu/drm/vmwgfx/vmwgfx_shader.c | 13 +-
drivers/hid/hid-logitech-dj.c | 28 +-
drivers/hwmon/adt7470.c | 131 ++--
drivers/hwmon/lm90.c | 4 +-
drivers/hwmon/nct6775-core.c | 20 +-
drivers/hwmon/npcm750-pwm-fan.c | 11 +
drivers/hwmon/nzxt-smart2.c | 2 +-
drivers/hwmon/pmbus/pmbus_core.c | 7 +-
drivers/i2c/busses/i2c-amd-mp2-plat.c | 4 +-
drivers/i2c/busses/i2c-imx.c | 9 +-
drivers/i2c/busses/i2c-jz4780.c | 5 +-
drivers/iommu/iommu-sva.c | 6 +-
drivers/media/i2c/imx219.c | 670 ++++++++++---------
drivers/media/v4l2-core/v4l2-async.c | 8 +-
drivers/media/v4l2-core/v4l2-fwnode.c | 6 +-
drivers/net/can/c_can/c_can_main.c | 8 +-
drivers/net/can/ctucanfd/ctucanfd_base.c | 14 +-
drivers/net/can/ctucanfd/ctucanfd_pci.c | 3 +-
drivers/net/can/dev/skb.c | 2 -
drivers/net/can/softing/softing_fw.c | 46 +-
drivers/net/can/usb/ems_usb.c | 43 ++
drivers/net/can/usb/etas_es58x/es58x_core.c | 1 -
drivers/net/can/usb/gs_usb.c | 4 +-
drivers/net/can/usb/kvaser_usb/kvaser_usb_hydra.c | 1 +
drivers/net/can/usb/kvaser_usb/kvaser_usb_leaf.c | 13 +-
drivers/net/can/usb/peak_usb/pcan_usb_core.c | 1 -
drivers/net/can/usb/peak_usb/pcan_usb_fd.c | 40 +-
drivers/net/can/usb/peak_usb/pcan_usb_pro.c | 20 +-
drivers/net/dsa/mt7530.c | 58 +-
drivers/net/ethernet/google/gve/gve.h | 3 +
drivers/net/ethernet/google/gve/gve_main.c | 3 +
drivers/net/ethernet/google/gve/gve_rx_dqo.c | 33 +
drivers/net/ethernet/intel/e1000/e1000_main.c | 2 +-
drivers/net/ethernet/intel/ice/ice_ethtool.c | 10 +-
drivers/net/ethernet/intel/ice/ice_main.c | 10 +
drivers/net/ethernet/intel/igbvf/netdev.c | 2 -
.../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 2 +-
drivers/net/ethernet/nvidia/forcedeth.c | 4 +-
drivers/net/ethernet/qlogic/qede/qede_main.c | 44 +-
drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | 14 +-
drivers/net/phy/phylink.c | 29 +-
drivers/net/vrf.c | 2 +-
drivers/net/vxlan/vxlan_core.c | 15 +-
drivers/net/wireless/ath/ath6kl/txrx.c | 2 +-
.../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 16 +-
.../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 6 +
.../wireless/broadcom/brcm80211/brcmfmac/chip.c | 4 +-
.../wireless/broadcom/brcm80211/brcmfmac/core.c | 46 +-
.../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 6 +
.../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 14 +-
.../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 1 +
.../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 3 +
.../broadcom/brcm80211/include/brcm_hw_ids.h | 2 +-
.../net/wireless/marvell/mwifiex/11n_rxreorder.c | 2 +-
drivers/phy/xilinx/phy-zynqmp.c | 130 ++--
drivers/pinctrl/Kconfig | 2 +
drivers/pinctrl/devicetree.c | 4 +
drivers/pinctrl/pinctrl-amd.c | 3 +-
drivers/pinctrl/qcom/pinctrl-sc8280xp.c | 21 +-
drivers/power/supply/bq25890_charger.c | 2 +-
drivers/s390/block/dasd_eckd.c | 11 +-
drivers/s390/block/dasd_ioctl.c | 2 +-
drivers/s390/crypto/zcrypt_api.c | 2 +-
drivers/s390/crypto/zcrypt_ccamisc.c | 6 +
drivers/s390/net/qeth_core_main.c | 3 +
drivers/s390/scsi/zfcp_aux.c | 1 +
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 10 +-
drivers/scsi/libiscsi.c | 2 +-
drivers/scsi/libiscsi_tcp.c | 8 +-
drivers/scsi/libsas/sas_init.c | 37 +-
drivers/scsi/scsi_debug.c | 8 +-
drivers/soc/qcom/ice.c | 17 +-
drivers/spi/spi-cadence.c | 129 +++-
drivers/spi/spi-qcom-qspi.c | 3 +-
drivers/target/target_core_iblock.c | 6 +-
drivers/target/target_core_transport.c | 12 +-
drivers/thunderbolt/xdomain.c | 40 +-
drivers/ufs/core/ufshcd.c | 6 +-
drivers/usb/gadget/function/f_tcm.c | 192 +++++-
drivers/usb/gadget/function/tcm.h | 13 +
drivers/usb/musb/omap2430.c | 25 +-
drivers/usb/typec/ucsi/ucsi.c | 113 ++--
drivers/usb/typec/ucsi/ucsi.h | 1 +
fs/binfmt_misc.c | 4 +
fs/btrfs/zoned.c | 6 +-
fs/ceph/acl.c | 6 +-
fs/ceph/addr.c | 279 ++++----
fs/ceph/caps.c | 708 ++++++++++++---------
fs/ceph/crypto.c | 39 +-
fs/ceph/debugfs.c | 6 +-
fs/ceph/dir.c | 225 ++++---
fs/ceph/export.c | 39 +-
fs/ceph/file.c | 245 ++++---
fs/ceph/inode.c | 485 +++++++-------
fs/ceph/ioctl.c | 13 +-
fs/ceph/locks.c | 57 +-
fs/ceph/mds_client.c | 554 +++++++++-------
fs/ceph/mdsmap.c | 24 +-
fs/ceph/metric.c | 5 +-
fs/ceph/quota.c | 29 +-
fs/ceph/snap.c | 174 ++---
fs/ceph/super.c | 70 +-
fs/ceph/super.h | 6 +
fs/ceph/xattr.c | 96 +--
fs/erofs/Kconfig | 14 +
fs/erofs/decompressor_lzma.c | 3 +-
fs/smb/client/cifssmb.c | 12 +-
fs/smb/server/vfs_cache.c | 6 +-
include/drm/drm_fb_helper.h | 12 -
include/linux/can/core.h | 1 +
include/linux/can/skb.h | 2 -
include/linux/ceph/ceph_debug.h | 38 ++
include/linux/dma/qcom_bam_dma.h | 21 +-
include/linux/libata.h | 2 +-
include/linux/mmc/sdio_ids.h | 2 +-
include/linux/netfilter/nf_conntrack_sip.h | 2 +-
include/linux/sched.h | 1 +
include/linux/sysctl.h | 2 +-
include/linux/thunderbolt.h | 3 +
include/media/v4l2-async.h | 8 +-
include/net/ip_vs.h | 45 +-
include/net/neighbour.h | 8 +-
include/net/netfilter/nf_conntrack_expect.h | 5 +-
include/net/netfilter/nf_tables.h | 2 +
include/scsi/libsas.h | 1 -
init/init_task.c | 1 +
ipc/ipc_sysctl.c | 2 +-
ipc/mq_sysctl.c | 2 +-
kernel/audit.c | 11 +-
kernel/auditfilter.c | 6 +-
kernel/trace/trace_events.c | 4 +-
kernel/trace/trace_events_filter.c | 3 +
kernel/trace/trace_mmiotrace.c | 1 +
kernel/trace/trace_probe.c | 6 +-
kernel/ucount.c | 2 +-
lib/assoc_array.c | 3 +-
lib/rhashtable.c | 1 +
mm/huge_memory.c | 16 +-
mm/hugetlb.c | 12 +-
mm/mm_init.c | 15 +-
mm/page_reporting.c | 6 +-
mm/percpu-km.c | 2 +-
net/ax25/sysctl_net_ax25.c | 2 +-
net/bluetooth/hci_conn.c | 14 +-
net/bluetooth/hci_sync.c | 19 +-
net/bluetooth/hidp/core.c | 30 +-
net/bluetooth/iso.c | 3 +-
net/bluetooth/l2cap_core.c | 5 +
net/bluetooth/mgmt.c | 84 ++-
net/bridge/br_mrp.c | 2 +-
net/bridge/br_multicast.c | 1 +
net/bridge/br_netfilter_hooks.c | 8 +-
net/can/af_can.c | 14 +-
net/can/bcm.c | 2 -
net/can/isotp.c | 337 +++++++---
net/can/j1939/bus.c | 2 +
net/can/j1939/j1939-priv.h | 3 +
net/can/j1939/main.c | 8 +-
net/can/j1939/socket.c | 1 -
net/can/j1939/transport.c | 6 +-
net/can/raw.c | 7 +-
net/core/lwt_bpf.c | 4 +-
net/core/sysctl_net_core.c | 2 +-
net/ieee802154/6lowpan/reassembly.c | 2 +-
net/ipv4/devinet.c | 2 +-
net/ipv4/ip_fragment.c | 2 +-
net/ipv4/route.c | 4 +-
net/ipv4/sysctl_net_ipv4.c | 2 +-
net/ipv4/xfrm4_policy.c | 2 +-
net/ipv6/addrconf.c | 2 +-
net/ipv6/fib6_rules.c | 1 +
net/ipv6/ip6_fib.c | 17 +-
net/ipv6/ip6_output.c | 2 +-
net/ipv6/ndisc.c | 2 +
net/ipv6/netfilter/nf_conntrack_reasm.c | 2 +-
net/ipv6/reassembly.c | 2 +-
net/ipv6/sysctl_net_ipv6.c | 6 +-
net/ipv6/xfrm6_policy.c | 2 +-
net/mac80211/s1g.c | 4 +
net/mpls/af_mpls.c | 5 +-
net/mptcp/ctrl.c | 2 +-
net/mptcp/pm.c | 9 +-
net/mptcp/pm_netlink.c | 29 +-
net/mptcp/pm_userspace.c | 87 ++-
net/mptcp/protocol.h | 6 +-
net/netfilter/ipset/ip_set_hash_gen.h | 2 +-
net/netfilter/ipvs/ip_vs_app.c | 4 +-
net/netfilter/ipvs/ip_vs_conn.c | 3 +
net/netfilter/ipvs/ip_vs_core.c | 180 +++---
net/netfilter/ipvs/ip_vs_proto_sctp.c | 19 +-
net/netfilter/ipvs/ip_vs_proto_tcp.c | 48 +-
net/netfilter/ipvs/ip_vs_proto_udp.c | 54 +-
net/netfilter/ipvs/ip_vs_xmit.c | 42 +-
net/netfilter/nf_conntrack_broadcast.c | 1 +
net/netfilter/nf_conntrack_core.c | 7 +-
net/netfilter/nf_conntrack_expect.c | 1 +
net/netfilter/nf_conntrack_h323_main.c | 12 +-
net/netfilter/nf_conntrack_helper.c | 5 +
net/netfilter/nf_conntrack_netlink.c | 18 +-
net/netfilter/nf_conntrack_sip.c | 4 +-
net/netfilter/nf_conntrack_standalone.c | 2 +-
net/netfilter/nf_log.c | 2 +-
net/netfilter/nf_nat_sip.c | 2 +-
net/netfilter/nf_tables_api.c | 10 +-
net/netfilter/nft_payload.c | 12 +-
net/netfilter/nft_set_pipapo.c | 11 +-
net/netfilter/xt_hashlimit.c | 16 +-
net/openvswitch/actions.c | 12 +-
net/openvswitch/meter.c | 33 +-
net/rds/ib.c | 4 +
net/rds/ib_cm.c | 4 +
net/rds/tcp.c | 14 +-
net/rxrpc/ar-internal.h | 1 +
net/rxrpc/call_accept.c | 1 +
net/rxrpc/peer_object.c | 12 +-
net/sctp/associola.c | 3 +
net/sctp/protocol.c | 21 +-
net/sctp/sm_make_chunk.c | 17 +-
net/sctp/sysctl.c | 11 +-
net/smc/smc_core.c | 2 +-
net/smc/smc_sysctl.c | 2 +-
net/tipc/socket.c | 2 +-
net/unix/sysctl_net_unix.c | 2 +-
net/xfrm/xfrm_sysctl.c | 2 +-
security/keys/keyring.c | 14 +-
sound/core/pcm_native.c | 7 +
sound/core/ump.c | 1 +
sound/pci/hda/patch_hdmi.c | 48 +-
sound/pci/lx6464es/lx6464es.c | 5 +-
sound/pci/lx6464es/lx_core.c | 5 +-
sound/soc/codecs/max98090.c | 5 +-
sound/soc/codecs/max98095.c | 5 +-
sound/soc/codecs/tas2562.c | 30 +-
sound/usb/6fire/chip.c | 4 +
sound/usb/endpoint.c | 14 +-
sound/usb/midi.c | 2 +
sound/usb/midi2.c | 4 +-
tools/testing/selftests/clone3/clone3_set_tid.c | 2 +-
tools/testing/selftests/mm/mlock-random-test.c | 2 +-
305 files changed, 4972 insertions(+), 3146 deletions(-)Greg Kroah-Hartman
maintainerPATCH 1/261 netfilter: nf_conntrack_expect: restore helper propagation via expectation
6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit dcb0f9aefdd604d36710fda53c25bd7cf4a3e37a ]
A recent series to fix expectations broke helper propagation via expectation, this mechanism is used by the sip and h323 helper. This also propagates the conntrack helper to expected connections. I changed semantics of exp->helper which now tells us the actual helper that created the expectation.
Add an explicit assign_helper field to expectations for this purpose and update helpers to use it.
Restore this feature for userspace conntrack helper via ctnetlink nfqueue integration so it is again possible to attach a helper to an expectation, where it makes sense. This is not restored via ctnetlink expectation creation as there is no client for such feature. Use the expectation layer 4 protocol number for the helper lookup for consistency.
Make sure the expectation using this helper propagation mechanism also go away when the helper is unregistered.
--- include/net/netfilter/nf_conntrack_expect.h | 5 ++++- net/netfilter/nf_conntrack_broadcast.c | 1 + net/netfilter/nf_conntrack_core.c | 7 +++++-- net/netfilter/nf_conntrack_expect.c | 1 + net/netfilter/nf_conntrack_h323_main.c | 12 ++++++------ net/netfilter/nf_conntrack_helper.c | 5 +++++ net/netfilter/nf_conntrack_netlink.c | 18 ++++++++++++++++-- net/netfilter/nf_conntrack_sip.c | 2 +- 8 files changed, 39 insertions(+), 12 deletions(-)
include/net/netfilter/nf_conntrack_expect.h +4 -1
@@ -45,9 +45,12 @@ struct nf_conntrack_expect {void (*expectfn)(struct nf_conn *new,struct nf_conntrack_expect *this); -/* Helper to assign to new connection */ +/* Helper that created this expectation */ struct nf_conntrack_helper __rcu *helper; +/* Helper to assign to new connection */ +struct nf_conntrack_helper __rcu *assign_helper; +/* The conntrack of the master connection */ struct nf_conn *master;
net/netfilter/nf_conntrack_broadcast.c +1 -0
@@ -72,6 +72,7 @@ int nf_conntrack_broadcast_help(struct sk_buff *skb, exp->flags =NF_CT_EXPECT_PERMANENT ; exp->class =NF_CT_EXPECT_CLASS_DEFAULT ;rcu_assign_pointer (exp->helper, helper); +rcu_assign_pointer (exp->assign_helper,NULL );write_pnet (&exp->net, net);#ifdef CONFIG_NF_CONNTRACK_ZONES exp->zone = ct->zone;
net/netfilter/nf_conntrack_core.c +5 -2
@@ -1729,14 +1729,17 @@ init_conntrack(struct net *net, struct nf_conn *tmpl,spin_lock_bh (&nf_conntrack_expect_lock); exp =nf_ct_find_expectation (net, zone, tuple, !tmpl ||nf_ct_is_confirmed (tmpl));if (exp) { +struct nf_conntrack_helper *assign_helper; +/* Welcome, Mr. Bond. We've been expecting you... */ __set_bit (IPS_EXPECTED_BIT , &ct->status);/* exp->master safe, refcnt bumped in nf_ct_find_expectation */ ct->master = exp->master; -if (exp->helper) { + assign_helper =rcu_dereference (exp->assign_helper); +if (assign_helper) { help =nf_ct_helper_ext_add (ct,GFP_ATOMIC );if (help) -rcu_assign_pointer (help->helper, exp->helper); +rcu_assign_pointer (help->helper, assign_helper); }#ifdef CONFIG_NF_CONNTRACK_MARK
net/netfilter/nf_conntrack_expect.c +1 -0
@@ -344,6 +344,7 @@ void nf_ct_expect_init(struct nf_conntrack_expect *exp, unsigned int class, helper =rcu_dereference (help->helper);rcu_assign_pointer (exp->helper, helper); +rcu_assign_pointer (exp->assign_helper,NULL );write_pnet (&exp->net, net);#ifdef CONFIG_NF_CONNTRACK_ZONES exp->zone = ct->zone;
net/netfilter/nf_conntrack_h323_main.c +6 -6
@@ -642,7 +642,7 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct, &ct->tuplehash[!dir].tuple.src.u3, &ct->tuplehash[!dir].tuple.dst.u3, IPPROTO_TCP, NULL, &port); -rcu_assign_pointer (exp->helper, &nf_conntrack_helper_h245); +rcu_assign_pointer (exp->assign_helper, &nf_conntrack_helper_h245); nathook =rcu_dereference (nfct_h323_nat_hook); if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
@@ -766,7 +766,7 @@ static int expect_callforwarding(struct sk_buff *skb,nf_ct_expect_init (exp,NF_CT_EXPECT_CLASS_DEFAULT ,nf_ct_l3num (ct), &ct->tuplehash[!dir].tuple.src.u3, &addr,IPPROTO_TCP ,NULL , &port); -rcu_assign_pointer (exp->helper, nf_conntrack_helper_q931); +rcu_assign_pointer (exp->assign_helper, nf_conntrack_helper_q931); nathook =rcu_dereference (nfct_h323_nat_hook); if (memcmp(&ct->tuplehash[dir].tuple.src.u3,
@@ -1233,7 +1233,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct, &ct->tuplehash[!dir].tuple.src.u3 : NULL, &ct->tuplehash[!dir].tuple.dst.u3, IPPROTO_TCP, NULL, &port); -rcu_assign_pointer (exp->helper, nf_conntrack_helper_q931); +rcu_assign_pointer (exp->assign_helper, nf_conntrack_helper_q931); exp->flags =NF_CT_EXPECT_PERMANENT ;/* Accept multiple calls */ nathook =rcu_dereference (nfct_h323_nat_hook);
@@ -1305,7 +1305,7 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,nf_ct_expect_init (exp,NF_CT_EXPECT_CLASS_DEFAULT ,nf_ct_l3num (ct), &ct->tuplehash[!dir].tuple.src.u3, &addr,IPPROTO_UDP ,NULL , &port); -rcu_assign_pointer (exp->helper, nf_conntrack_helper_ras); +rcu_assign_pointer (exp->assign_helper, nf_conntrack_helper_ras);if (nf_ct_expect_related (exp,0 ) ==0 ) {pr_debug ("nf_ct_ras: expect RAS " );
@@ -1522,7 +1522,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct, &ct->tuplehash[!dir].tuple.src.u3, &addr, IPPROTO_TCP, NULL, &port); exp->flags =NF_CT_EXPECT_PERMANENT ; -rcu_assign_pointer (exp->helper, nf_conntrack_helper_q931); +rcu_assign_pointer (exp->assign_helper, nf_conntrack_helper_q931);if (nf_ct_expect_related (exp,0 ) ==0 ) {pr_debug ("nf_ct_ras: expect Q.931 " );
@@ -1576,7 +1576,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct, &ct->tuplehash[!dir].tuple.src.u3, &addr, IPPROTO_TCP, NULL, &port); exp->flags =NF_CT_EXPECT_PERMANENT ; -rcu_assign_pointer (exp->helper, nf_conntrack_helper_q931); +rcu_assign_pointer (exp->assign_helper, nf_conntrack_helper_q931);if (nf_ct_expect_related (exp,0 ) ==0 ) {pr_debug ("nf_ct_ras: expect Q.931 " );
net/netfilter/nf_conntrack_helper.c +5 -0
@@ -424,6 +424,11 @@ static bool expect_iter_me(struct nf_conntrack_expect *exp, void *data) this =rcu_dereference_protected (exp->helper,lockdep_is_held (&nf_conntrack_expect_lock)); +if (this == me) +return true; + + this =rcu_dereference_protected (exp->assign_helper, +lockdep_is_held (&nf_conntrack_expect_lock));return this == me; }
net/netfilter/nf_conntrack_netlink.c +16 -2
@@ -2624,6 +2624,7 @@ static const struct nla_policy exp_nla_policy[CTA_EXPECT_MAX+1] = {static struct nf_conntrack_expect *ctnetlink_alloc_expect (const struct nlattr *const cda[],struct nf_conn *ct, +const struct nf_conntrack_helper *assign_helper,struct nf_conntrack_tuple *tuple,struct nf_conntrack_tuple *mask);
@@ -2850,6 +2851,7 @@ static int ctnetlink_glue_attach_expect(const struct nlattr *attr, struct nf_conn *ct, u32 portid, u32 report) { + struct nf_conntrack_helper *assign_helper = NULL;struct nlattr *cda[CTA_EXPECT_MAX +1 ];struct nf_conntrack_tuple tuple, mask;struct nf_conntrack_expect *exp;
@@ -2865,8 +2867,18 @@ ctnetlink_glue_attach_expect(const struct nlattr *attr, struct nf_conn *ct,if (err <0 )return err; +if (cda[CTA_EXPECT_HELP_NAME ]) { +const char *helpname =nla_data (cda[CTA_EXPECT_HELP_NAME ]); + + assign_helper =__nf_conntrack_helper_find (helpname, +nf_ct_l3num (ct), + tuple.dst.protonum); +if (!assign_helper) +return -EOPNOTSUPP ; + } + exp =ctnetlink_alloc_expect ((const struct nlattr *const *)cda, ct, - &tuple, &mask); + assign_helper, &tuple, &mask);if (IS_ERR (exp))return PTR_ERR (exp);
@@ -3505,6 +3517,7 @@ ctnetlink_parse_expect_nat(const struct nlattr *attr,static struct nf_conntrack_expect *ctnetlink_alloc_expect (const struct nlattr *const cda[],struct nf_conn *ct, +const struct nf_conntrack_helper *assign_helper,struct nf_conntrack_tuple *tuple,struct nf_conntrack_tuple *mask) {
@@ -3558,6 +3571,7 @@ ctnetlink_alloc_expect(const struct nlattr * const cda[], struct nf_conn *ct, exp->zone = ct->zone;#endif rcu_assign_pointer (exp->helper, helper); +rcu_assign_pointer (exp->assign_helper, assign_helper); exp->tuple = *tuple; exp->mask.src.u3 = mask->src.u3; exp->mask.src.u.all = mask->src.u.all;
@@ -3613,7 +3627,7 @@ ctnetlink_create_expect(struct net *net, ct =nf_ct_tuplehash_to_ctrack (h);rcu_read_lock (); - exp =ctnetlink_alloc_expect (cda, ct, &tuple, &mask); + exp =ctnetlink_alloc_expect (cda, ct,NULL , &tuple, &mask);if (IS_ERR (exp)) { err =PTR_ERR (exp); goto err_rcu;
net/netfilter/nf_conntrack_sip.c +1 -1
@@ -1386,7 +1386,7 @@ static int process_register_request(struct sk_buff *skb, unsigned int protoff,nf_ct_expect_init (exp,SIP_EXPECT_SIGNALLING ,nf_ct_l3num (ct), saddr, &daddr, proto,NULL , &port); exp->timeout.expires = sip_timeout *HZ ; -rcu_assign_pointer (exp->helper, helper); +rcu_assign_pointer (exp->assign_helper, helper); exp->flags =NF_CT_EXPECT_PERMANENT |NF_CT_EXPECT_INACTIVE ; hooks =rcu_dereference (nf_nat_sip_hooks);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 2/261 netfilter: br_netfilter: Reallocate headroom if necessary in neigh_hh_bridge()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit b2870fc21601db9133bc70c48c603b487614fa3b ]
neigh_hh_bridge() assumes the skb always has sufficient headroom to copy the aligned L2 header. This assumption can trigger the crash reported below using the following netfilter setup:
$modprobe br_netfilter
$sysctl -w net.bridge.bridge-nf-call-iptables=1
$root@OpenWrt:~# nft list ruleset
table ip nat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
ip daddr 192.168.83.123 dnat to 192.168.83.120
}
}- iperf3 client (192.168.83.119) --> bridge (192.168.83.118) --> iperf3 server (192.168.83.120)
the iperf3 client is sending packet for 192.168.83.123 to the bridge device.
[ 1579.036575] Unable to handle kernel write to read-only memory at virtual address ffffff8004d76ffe [ 1579.045482] Mem abort info: [ 1579.048273] ESR = 0x000000009600004f [ 1579.052024] EC = 0x25: DABT (current EL), IL = 32 bits [ 1579.057363] SET = 0, FnV = 0 [ 1579.060417] EA = 0, S1PTW = 0 [ 1579.063550] FSC = 0x0f: level 3 permission fault [ 1579.068345] Data abort info: [ 1579.071224] ISV = 0, ISS = 0x0000004f, ISS2 = 0x00000000 [ 1579.076720] CM = 0, WnR = 1, TnD = 0, TagAccess = 0 [ 1579.081770] GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0 [ 1579.087092] swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000080dc4000 [ 1579.093794] [ffffff8004d76ffe] pgd=180000009ffff003, p4d=180000009ffff003, pud=180000009ffff003, pmd=180000009ffe3003, pte=0060000084d76787 [ 1579.106343] Internal error: Oops: 000000009600004f [#1] SMP [ 1579.193824] CPU: 0 UID: 0 PID: 235 Comm: napi/qdma_eth-3 Tainted: G O 6.12.57 #0 [ 1579.202614] Tainted: [O]=OOT_MODULE [ 1579.206102] Hardware name: Airoha AN7581 Evaluation Board (DT) [ 1579.211929] pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) [ 1579.218889] pc : br_nf_pre_routing_finish_bridge+0x1ac/0xcc8 [br_netfilter] [ 1579.225859] lr : br_nf_pre_routing_finish_bridge+0x18c/0xcc8 [br_netfilter] [ 1579.232822] sp : ffffffc0817cba20 [ 1579.236128] x29: ffffffc0817cba20 x28: 0000000000000000 x27: ffffff8002b89000 [ 1579.243273] x26: ffffff8004d7700e x25: 0000000000000008 x24: 0000000000000000 [ 1579.250416] x23: ffffffc08179d4c0 x22: 0000000000000000 x21: ffffffc08179d4c0 [ 1579.257561] x20: ffffff8004d9b800 x19: ffffff8015010000 x18: 0000000000000014 [ 1579.264704] x17: ffffffbf9e930000 x16: ffffffc0817c8000 x15: 0000000000000070 [ 1579.271848] x14: 0000000000000080 x13: 0000000000000001 x12: 0000000000000000 [ 1579.278993] x11: ffffffc0798caae0 x10: ffffff8014db6fd8 x9 : 0000000000000000 [ 1579.286136] x8 : 0000000000000003 x7 : ffffffc08171f628 x6 : 000000001a3b83d3 [ 1579.293281] x5 : 0000000000000000 x4 : 1beb76f22fee0000 x3 : ffffff8004d7700e [ 1579.300425] x2 : 0000000000000000 x1 : ffffff8004d9b8bc x0 : ffffff80026ed000 [ 1579.307570] Call trace: [ 1579.310018] br_nf_pre_routing_finish_bridge+0x1ac/0xcc8 [br_netfilter] [ 1579.316632] br_nf_hook_thresh+0xd4/0x14bc [br_netfilter] [ 1579.322032] br_nf_hook_thresh+0x250/0x14bc [br_netfilter] [ 1579.327517] br_nf_hook_thresh+0x76c/0x14bc [br_netfilter] [ 1579.333003] br_handle_frame+0x180/0x480 [ 1579.336935] __netif_receive_skb_core.constprop.0+0x540/0xf40 [ 1579.342682] __netif_receive_skb_one_core+0x28/0x50 [ 1579.347561] process_backlog+0x98/0x1e0 [ 1579.351398] __napi_poll+0x34/0x1c4 [ 1579.354887] net_rx_action+0x178/0x330 [ 1579.358638] handle_softirqs+0x108/0x2d4 [ 1579.362560] __do_softirq+0x10/0x18 [ 1579.366051] ____do_softirq+0xc/0x20 [ 1579.369627] call_on_irq_stack+0x30/0x4c [ 1579.373550] do_softirq_own_stack+0x18/0x20 [ 1579.377734] do_softirq+0x4c/0x60 [ 1579.381050] __local_bh_enable_ip+0x88/0x98 [ 1579.385234] napi_threaded_poll_loop+0x188/0x21c [ 1579.389853] napi_threaded_poll+0x70/0x80 [ 1579.393863] kthread+0xd8/0xdc [ 1579.396918] ret_from_fork+0x10/0x20 [ 1579.400499] Code: 88dffc22 3707ffc2 f9406663 f9406684 (f81f0064) [ 1579.406589] ---[ end trace 0000000000000000 ]--- [ 1579.411209] Kernel panic - not syncing: Oops: Fatal exception in interrupt [ 1579.418083] SMP: stopping secondary CPUs [ 1579.422012] Kernel Offset: disabled
Fix the issue reallocating the skb headroom if necessary in neigh_hh_bridge routine.
--- include/net/neighbour.h | 8 ++++++-- net/bridge/br_netfilter_hooks.c | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-)
include/net/neighbour.h +6 -2
@@ -476,11 +476,15 @@ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)#if IS_ENABLED (CONFIG_BRIDGE_NETFILTER )static inline int neigh_hh_bridge (struct hh_cache *hh,struct sk_buff *skb) { -unsigned int seq, hh_alen; +unsigned int seq, hh_alen =HH_DATA_ALIGN (ETH_HLEN ); +int err; + + err =skb_cow_head (skb, hh_alen); +if (err) +return err;do { seq =read_seqbegin (&hh->hh_lock); - hh_alen =HH_DATA_ALIGN (ETH_HLEN );memcpy (skb->data - hh_alen, hh->hh_data,ETH_ALEN + hh_alen -ETH_HLEN ); }while (read_seqretry (&hh->hh_lock, seq));return 0 ;
net/bridge/br_netfilter_hooks.c +5 -1
@@ -292,7 +292,11 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_ goto free_skb; } -neigh_hh_bridge (&neigh->hh, skb); +if (neigh_hh_bridge (&neigh->hh, skb)) { +neigh_release (neigh); + goto free_skb; + } + skb->dev = br_indev; ret =br_handle_frame_finish (net, sk, skb);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 3/261 net: mpls: initialize rtm_tos in mpls_getroute()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yehyeong Lee <[email protected]>
[ Upstream commit 295dd295e2137e10e9a5b1891d97e0f08de76f03 ]
mpls_getroute() builds the RTM_NEWROUTE reply to an RTM_GETROUTE request by filling a struct rtmsg allocated from an skb whose data area is not zeroed (alloc_skb(NLMSG_GOODSIZE, ...)). It sets every field of the header except rtm_tos:
r = nlmsg_data(nlh); r->rtm_family = AF_MPLS; r->rtm_dst_len = 20; r->rtm_src_len = 0; r->rtm_table = RT_TABLE_MAIN; r->rtm_type = RTN_UNICAST; r->rtm_scope = RT_SCOPE_UNIVERSE; r->rtm_protocol = rt->rt_protocol; r->rtm_flags = 0;
struct rtmsg has no padding, so the one uninitialised byte rtm_tos (offset 3) is copied straight to user space on recvmsg(), leaking a byte of uninitialised heap memory. This is in contrast to mpls_dump_route(), which fills the very same header and does set rtm_tos = 0.
Initialize rtm_tos to 0, matching mpls_dump_route().
Reproduced with KMSAN by adding an MPLS route and issuing a non-RTM_F_FIB_MATCH RTM_GETROUTE for its label:
BUG: KMSAN: kernel-infoleak in _copy_to_iter+0x36c/0x33f0 _copy_to_iter+0x36c/0x33f0 __skb_datagram_iter+0x196/0x12c0 skb_copy_datagram_iter+0x5b/0x210 netlink_recvmsg+0x37b/0xef0 ... Uninit was created at: __alloc_skb+0x8ca/0x10e0 mpls_getroute+0x1280/0x3a40 rtnetlink_rcv_msg+0x1138/0x15a0 ... Byte 19 of 64 is uninitialized
(byte 19 = nlmsghdr(16) + rtmsg offset 3 = rtm_tos)
--- net/mpls/af_mpls.c | 1 + 1 file changed, 1 insertion(+)
net/mpls/af_mpls.c +1 -0
@@ -2469,6 +2469,7 @@ static int mpls_getroute(struct sk_buff *in_skb, struct nlmsghdr *in_nlh, r->rtm_family =AF_MPLS ; r->rtm_dst_len =20 ; r->rtm_src_len =0 ; + r->rtm_tos =0 ; r->rtm_table =RT_TABLE_MAIN ; r->rtm_type =RTN_UNICAST ; r->rtm_scope =RT_SCOPE_UNIVERSE ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 4/261 gve: fix Rx queue stall on alloc failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eddie Phillips <[email protected]>
commit b65352a1bac64442ad95e64f385b40ccb9f1b0db upstream.
When the system is under extreme memory pressure, page allocations can fail during the Rx buffer refill loop. If the number of buffers posted to hardware falls below a critical low threshold and the refill loop exits due to allocation failures, the queue can stall:
1. The device drops incoming packets because there are no descriptors.
2. Since no packets are processed, no Rx completions are generated.
3. Because no completions occur, NAPI is never scheduled, preventing the refill loop from running again even after memory is freed.
This results in a permanent queue stall.
Resolve this by introducing a starvation recovery timer for each Rx queue. If the number of buffers posted to hardware falls below a critical low threshold, start a timer to periodically reschedule NAPI. Once NAPI runs and successfully refills the queue above the threshold, the timer is not rescheduled.
The threshold is set to 32 because a single maximum-sized Receive Segment Coalescing (RSC) packet can consume up to 19 descriptors in the Rx path. Lower thresholds (such as 8 or 16) would be insufficient to process a complete maximum-sized RSC packet, risking packet drops or unexpected hardware behavior under memory pressure. Setting the threshold to 32 guarantees a safe margin to handle at least one full RSC packet.
--- drivers/net/ethernet/google/gve/gve.h | 3 ++ drivers/net/ethernet/google/gve/gve_main.c | 3 ++ drivers/net/ethernet/google/gve/gve_rx_dqo.c | 33 ++++++++++++++++++++ 3 files changed, 39 insertions(+)
drivers/net/ethernet/google/gve/gve.h +3 -0
@@ -10,6 +10,7 @@#include <linux/dma-mapping.h> #include <linux/netdevice.h> #include <linux/pci.h> +#include <linux/timer.h> #include <linux/u64_stats_sync.h> #include <net/xdp.h>
@@ -36,6 +37,7 @@/* Interval to schedule a stats report update, 20000ms. */ #define GVE_STATS_REPORT_TIMER_PERIOD 20000 +#define GVE_RX_NAPI_RESCHED_MS 20/* msecs */ /* Numbers of NIC tx/rx stats in stats report. */ #define NIC_TX_STATS_REPORT_NUM 0
@@ -281,6 +283,7 @@ struct gve_rx_ring {struct xdp_rxq_info xsk_rxq;struct xsk_buff_pool *xsk_pool;struct page_frag_cache page_cache;/* Page cache to allocate XDP frames */ +struct timer_list starvation_timer;/* for queue starvation recovery */ };/* A TX desc ring entry */
drivers/net/ethernet/google/gve/gve_main.c +3 -0
@@ -583,6 +583,9 @@ static void gve_remove_napi(struct gve_priv *priv, int ntfy_idx) {struct gve_notify_block *block = &priv->ntfy_blocks[ntfy_idx]; +if (block->rx && !gve_is_gqi (priv)) +timer_shutdown_sync (&block->rx->starvation_timer); +netif_napi_del (&block->napi);disable_irq (block->irq); }
drivers/net/ethernet/google/gve/gve_rx_dqo.c +33 -0
@@ -16,6 +16,16 @@#include <net/ipv6.h> #include <net/tcp.h> +static void gve_rx_starvation_timer (struct timer_list *t) +{ +struct gve_rx_ring *rx =from_timer (rx, t, starvation_timer); +struct gve_priv *priv = rx->gve; +struct gve_notify_block *block; + + block = &priv->ntfy_blocks[rx->ntfy_id]; +napi_schedule (&block->napi); +} +static int gve_buf_ref_cnt (struct gve_rx_buf_state_dqo *bs) {return page_count (bs->page_info.page) - bs->page_info.pagecnt_bias;
@@ -211,6 +221,7 @@ static void gve_rx_free_ring_dqo(struct gve_priv *priv, int idx) completion_queue_slots = rx->dqo.complq.mask +1 ; buffer_queue_slots = rx->dqo.bufq.mask +1 ; +timer_shutdown_sync (&rx->starvation_timer);gve_rx_remove_from_block (priv, idx);if (rx->q_resources) {
@@ -268,6 +279,7 @@ static int gve_rx_alloc_ring_dqo(struct gve_priv *priv, int idx)memset (rx,0 ,sizeof (*rx)); rx->gve = priv; rx->q_num = idx; +timer_setup (&rx->starvation_timer, gve_rx_starvation_timer,0 ); rx->dqo.bufq.mask = buffer_queue_slots -1 ; rx->dqo.complq.num_free_slots = completion_queue_slots; rx->dqo.complq.mask = completion_queue_slots -1 ;
@@ -374,6 +386,7 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx)struct gve_rx_compl_queue_dqo *complq = &rx->dqo.complq;struct gve_rx_buf_queue_dqo *bufq = &rx->dqo.bufq;struct gve_priv *priv = rx->gve; +u32 num_bufs_avail_to_hw;u32 num_avail_slots;u32 num_full_slots;u32 num_posted =0 ;
@@ -414,6 +427,26 @@ void gve_rx_post_buffers_dqo(struct gve_rx_ring *rx) } rx->fill_cnt += num_posted; + +/* If the queue has fewer than GVE_RX_BUF_THRESH_DQO descriptors +* visible to the hardware, the hardware is in danger of starving +* and cannot trigger interrupts. +* +* We use a threshold of 32 because a single maximum-sized RSC +* packet can consume up to 19 descriptors in the Rx path. Lower +* thresholds (e.g., 8 or 16) would be unsafe as they could cause +* the device to drop/stall on a maximum-sized RSC packet. +* +* Start the timer to periodically reschedule NAPI and recover. +*/ + num_bufs_avail_to_hw = + ((bufq->tail & ~(GVE_RX_BUF_THRESH_DQO -1 )) - + bufq->head) & bufq->mask; + +if (num_bufs_avail_to_hw <GVE_RX_BUF_THRESH_DQO ) { +mod_timer (&rx->starvation_timer, + jiffies +msecs_to_jiffies (GVE_RX_NAPI_RESCHED_MS )); + } } static void gve_try_recycle_buf(struct gve_priv *priv, struct gve_rx_ring *rx,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 5/261 HID: logitech-dj: Standardise hid_report_enum variable nomenclature
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lee Jones <[email protected]>
[ Upstream commit a940aee176437046598dfc786b719bd96db3c74c ]
Since we will need to differentiate between the two report_enum types soon, let's unify the naming conventions now to save confusion and/or unnecessary/unrelated changes in upcoming commits.
{input,output}_report_enum is used in other places to let's conform.
--- drivers/hid/hid-logitech-dj.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/hid/hid-logitech-dj.c +6 -6
@@ -1749,7 +1749,7 @@ static int logi_dj_raw_event(struct hid_device *hdev,static int logi_dj_probe (struct hid_device *hdev,const struct hid_device_id *id) { -struct hid_report_enum *rep_enum; +struct hid_report_enum *input_report_enum;struct hid_report *rep;struct dj_receiver_dev *djrcv_dev;struct usb_interface *intf;
@@ -1793,10 +1793,10 @@ static int logi_dj_probe(struct hid_device *hdev, } } - rep_enum = &hdev->report_enum[HID_INPUT_REPORT ]; + input_report_enum = &hdev->report_enum[HID_INPUT_REPORT ];/* no input reports, bail out */ -if (list_empty (&rep_enum->report_list)) +if (list_empty (&input_report_enum->report_list))return -ENODEV ;/*
@@ -1804,7 +1804,7 @@ static int logi_dj_probe(struct hid_device *hdev,* Note: we should theoretically check for HID++ and DJ * collections, but this will do. */ -list_for_each_entry (rep, &rep_enum->report_list, list) { +list_for_each_entry (rep, &input_report_enum->report_list, list) {if (rep->application ==0xff000001 ) has_hidpp = true; }
@@ -1817,7 +1817,7 @@ static int logi_dj_probe(struct hid_device *hdev,return -ENODEV ;/* get the current application attached to the node */ - rep = list_first_entry(&rep_enum->report_list, struct hid_report, list); + rep = list_first_entry(&input_report_enum->report_list, struct hid_report, list); djrcv_dev =dj_get_receiver_dev (hdev, id->driver_data, rep->application, has_hidpp);if (!djrcv_dev) {
@@ -1825,7 +1825,7 @@ static int logi_dj_probe(struct hid_device *hdev,return -ENOMEM ; } -if (!rep_enum->numbered) +if (!input_report_enum->numbered) djrcv_dev->unnumbered_application = rep->application;/* Starts the usb device and connects to upper interfaces hiddev and
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 6/261 HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated OOB write
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lee Jones <[email protected]>
[ Upstream commit b6a57912854e7ea36f3b270032661140cc4209cd ]
logi_dj_recv_send_report() assumes that all incoming REPORT_ID_DJ_SHORT reports are 14 Bytes (DJREPORT_SHORT_LENGTH - 1) long. It uses that assumption to load the associated field's 'value' array with 14 Bytes of data. However, if a malicious user only sends say 1 Byte of data, 'report_count' will be 1 and only 1 Byte of memory will be allocated to the 'value' Byte array. When we come to populate 'value[1-13]' we will experience an OOB write.
--- drivers/hid/hid-logitech-dj.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/hid/hid-logitech-dj.c +10 -0
@@ -1750,6 +1750,7 @@ static int logi_dj_probe(struct hid_device *hdev, const struct hid_device_id *id) {struct hid_report_enum *input_report_enum; +struct hid_report_enum *output_report_enum;struct hid_report *rep;struct dj_receiver_dev *djrcv_dev;struct usb_interface *intf;
@@ -1793,6 +1794,15 @@ static int logi_dj_probe(struct hid_device *hdev, } } + output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT ]; + rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT ]; + +if (rep->maxfield <1 || rep->field[0 ]->report_count !=DJREPORT_SHORT_LENGTH -1 ) { +hid_err (hdev,"Expected size of DJ short report is %d, but got %d" , +DJREPORT_SHORT_LENGTH -1 , rep->field[0 ]->report_count); +return -EINVAL ; + } + input_report_enum = &hdev->report_enum[HID_INPUT_REPORT ];/* no input reports, bail out */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 7/261 HID: logitech-dj: fix wrong detection of bad DJ_SHORT output report
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Tissoires <[email protected]>
[ Upstream commit 8b9a097eb2fc37b486afd81388c693bf3ab44466 ]
commit b6a57912854e ("HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated OOB write") assumed that all HID devices attached to the logitech-dj driver was having an output report of DJ_SHORT.
However, on the receiver itself, we have 2 other HID device we attach
here: the mouse emulation and the keyboard emulation. For those devices the value of rep is NULL and we are triggered a segfault here.
This is doubly required because logitech-dj also handles non DJ devices that might not have the DJ collection.
--- drivers/hid/hid-logitech-dj.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/hid/hid-logitech-dj.c +2 -1
@@ -1797,7 +1797,8 @@ static int logi_dj_probe(struct hid_device *hdev, output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT ]; rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT ]; -if (rep->maxfield <1 || rep->field[0 ]->report_count !=DJREPORT_SHORT_LENGTH -1 ) { +if (rep && (rep->maxfield <1 || + rep->field[0 ]->report_count !=DJREPORT_SHORT_LENGTH -1 )) {hid_err (hdev,"Expected size of DJ short report is %d, but got %d" ,DJREPORT_SHORT_LENGTH -1 , rep->field[0 ]->report_count);return -EINVAL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 8/261 soc: qcom: ice: Allow explicit votes on iface clock for ICE
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harshal Dev <[email protected]>
[ Upstream commit 0d5dc5818191b55e4364d04b1b898a14a2ccac38 ]
Since Qualcomm inline-crypto engine (ICE) is now a dedicated driver de-coupled from the QCOM UFS driver, it explicitly votes for its required clocks during probe. For scenarios where the 'clk_ignore_unused' flag is not passed on the kernel command line, to avoid potential unclocked ICE hardware register access during probe the ICE driver should additionally vote on the 'iface' clock.
Also update the suspend and resume callbacks to handle un-voting and voting on the 'iface' clock.
--- drivers/soc/qcom/ice.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
drivers/soc/qcom/ice.c +15 -2
@@ -48,6 +48,7 @@ struct qcom_ice {struct device_link *link;struct clk *core_clk; +struct clk *iface_clk; };static DEFINE_XARRAY (ice_handles);
@@ -149,8 +150,13 @@ int qcom_ice_resume(struct qcom_ice *ice) err =clk_prepare_enable (ice->core_clk);if (err) { -dev_err (dev,"failed to enable core clock (%d)\n" , - err); +dev_err (dev,"Failed to enable core clock: %d\n" , err); +return err; + } + + err =clk_prepare_enable (ice->iface_clk); +if (err) { +dev_err (dev,"Failed to enable iface clock: %d\n" , err);return err; }
@@ -160,6 +166,7 @@ EXPORT_SYMBOL_GPL(qcom_ice_resume);int qcom_ice_suspend (struct qcom_ice *ice) { +clk_disable_unprepare (ice->iface_clk);clk_disable_unprepare (ice->core_clk);return 0 ;
@@ -240,11 +247,17 @@ static struct qcom_ice *qcom_ice_create(struct device *dev, engine->core_clk =devm_clk_get_optional_enabled (dev,"ice_core_clk" );if (!engine->core_clk) engine->core_clk =devm_clk_get_optional_enabled (dev,"ice" ); +if (!engine->core_clk) + engine->core_clk =devm_clk_get_optional_enabled (dev,"core" );if (!engine->core_clk) engine->core_clk =devm_clk_get_enabled (dev,NULL );if (IS_ERR (engine->core_clk))return ERR_CAST (engine->core_clk); + engine->iface_clk =devm_clk_get_optional_enabled (dev,"iface" ); +if (IS_ERR (engine->iface_clk)) +return ERR_CAST (engine->iface_clk); +if (!qcom_ice_check_supported (engine))return ERR_PTR (-EOPNOTSUPP );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 9/261 thunderbolt: Prevent XDomain delayed work use-after-free on disconnect
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
[ Upstream commit 2c5d2d3c3f70cde2565d7b279b544893a2035842 ]
tb_xdp_handle_request() runs on system_wq and queues xd->state_work via queue_delayed_work() in three request handlers:PROPERTIES_CHANGED_REQUEST, UUID_REQUEST (via start_handshake), and LINK_STATE_CHANGE_REQUEST. Similarly, update_xdomain() queues xd->properties_changed_work when local properties change.
Concurrently, tb_xdomain_remove() calls stop_handshake() which does cancel_delayed_work_sync() on both delayed works. Later, tb_xdomain_unregister() calls device_unregister() which eventually frees the xdomain. Since commit 559c1e1e0134 ("thunderbolt: Run tb_xdp_handle_request() in system workqueue") moved the request handler off tb->wq, the handler and the remove path are no longer serialized. If queue_delayed_work() executes after cancel_delayed_work_sync() but before the xdomain is freed, the delayed work fires on a freed object.
Add xd->removing that tb_xdomain_remove() sets under xd->lock before calling stop_handshake(). Each external queue site holds the same lock and checks removing before calling queue_delayed_work(). This provides the mutual exclusion needed:
either the queue site acquires the lock first and queues work that the subsequent cancel will see, or the remove path acquires the lock first and the queue site observes removing == true and skips the queue.
--- drivers/thunderbolt/xdomain.c | 40 ++++++++++++++++++++++++++--------- include/linux/thunderbolt.h | 3 +++ 2 files changed, 33 insertions(+), 10 deletions(-)
drivers/thunderbolt/xdomain.c +30 -10
@@ -783,9 +783,13 @@ static void tb_xdp_handle_request(struct work_struct *work)* the xdomain related to this connection as well in * case there is a change in services it offers. */ -if (xd &&device_is_registered (&xd->dev)) -queue_delayed_work (tb->wq, &xd->state_work, -msecs_to_jiffies (XDOMAIN_SHORT_TIMEOUT )); +if (xd) { +mutex_lock (&xd->lock); +if (!xd->removing &&device_is_registered (&xd->dev)) +queue_delayed_work (tb->wq, &xd->state_work, +msecs_to_jiffies (XDOMAIN_SHORT_TIMEOUT )); +mutex_unlock (&xd->lock); + }break ;case UUID_REQUEST_OLD :
@@ -798,8 +802,12 @@ static void tb_xdp_handle_request(struct work_struct *work)* received UUID request from the remote host. */ if (!ret && xd && xd->state ==XDOMAIN_STATE_ERROR ) { -dev_dbg (&xd->dev,"restarting handshake\n" ); -start_handshake (xd); +mutex_lock (&xd->lock); +if (!xd->removing) { +dev_dbg (&xd->dev,"restarting handshake\n" ); +start_handshake (xd); + } +mutex_unlock (&xd->lock); }break ;
@@ -827,9 +835,13 @@ static void tb_xdp_handle_request(struct work_struct *work) ret =tb_xdp_link_state_change_response (ctl, route, sequence,0 ); - xd->target_link_width = lsc->tlw; -queue_delayed_work (tb->wq, &xd->state_work, -msecs_to_jiffies (XDOMAIN_SHORT_TIMEOUT )); +mutex_lock (&xd->lock); +if (!xd->removing) { + xd->target_link_width = lsc->tlw; +queue_delayed_work (tb->wq, &xd->state_work, +msecs_to_jiffies (XDOMAIN_SHORT_TIMEOUT )); + } +mutex_unlock (&xd->lock); }else {tb_xdp_error_response (ctl, route, sequence,ERROR_NOT_READY );
@@ -2018,6 +2030,10 @@ void tb_xdomain_remove(struct tb_xdomain *xd) {tb_xdomain_debugfs_remove (xd); +mutex_lock (&xd->lock); + xd->removing = true; +mutex_unlock (&xd->lock); +stop_handshake (xd);device_for_each_child_reverse (&xd->dev, xd, unregister_service);
@@ -2412,8 +2428,12 @@ static int update_xdomain(struct device *dev, void *data) xd =tb_to_xdomain (dev);if (xd) { -queue_delayed_work (xd->tb->wq, &xd->properties_changed_work, -msecs_to_jiffies (50 )); +mutex_lock (&xd->lock); +if (!xd->removing) +queue_delayed_work (xd->tb->wq, + &xd->properties_changed_work, +msecs_to_jiffies (50 )); +mutex_unlock (&xd->lock); }return 0 ;
include/linux/thunderbolt.h +3 -0
@@ -203,6 +203,8 @@ enum tb_link_width {* @link_width: Width of the downstream facing link * @link_usb4: Downstream link is USB4 * @is_unplugged: The XDomain is unplugged +* @removing: Set by tb_xdomain_remove() under @lock to prevent +* concurrent delayed work queueing * @needs_uuid: If the XDomain does not have @remote_uuid it will be * queried first * @service_ids: Used to generate IDs for the services
@@ -251,6 +253,7 @@ struct tb_xdomain {enum tb_link_width link_width;bool link_usb4;bool is_unplugged; +bool removing;bool needs_uuid;struct ida service_ids;struct ida in_hopids;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 10/261 pinctrl: qcom: sc8280xp: Add missing wakeup entries for GPIO143/151
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konrad Dybcio <[email protected]>
[ Upstream commit 437a8d2aa1aa442c4a176fdf4700a9b3bb0c8794 ]
Pins 143 and 151 were not included in the PDC wakeup map. They are normally used for PCIe2A and PCIe3a PERST# respectively, so they're unlikely to be excercised in practice, but still add them for the sake of completeness.
--- drivers/pinctrl/qcom/pinctrl-sc8280xp.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
drivers/pinctrl/qcom/pinctrl-sc8280xp.c +11 -10
@@ -1884,16 +1884,17 @@ static const struct msm_gpio_wakeirq_map sc8280xp_pdc_map[] = { { 126, 200 }, { 127, 225 }, { 128, 262 }, { 129, 201 }, { 130, 209 }, { 131, 173 }, { 132, 202 }, { 136, 210 }, { 138, 171 }, { 139, 226 }, { 140, 227 }, { 142, 228 }, - { 144, 229 }, { 145, 230 }, { 146, 231 }, { 148, 232 }, - { 149, 233 }, { 150, 234 }, { 152, 235 }, { 154, 212 }, - { 157, 213 }, { 161, 219 }, { 170, 236 }, { 171, 221 }, - { 174, 222 }, { 175, 237 }, { 176, 223 }, { 177, 170 }, - { 180, 238 }, { 181, 239 }, { 182, 240 }, { 183, 241 }, - { 184, 242 }, { 185, 243 }, { 190, 178 }, { 193, 184 }, - { 196, 185 }, { 198, 186 }, { 200, 174 }, { 201, 175 }, - { 205, 176 }, { 206, 177 }, { 208, 187 }, { 210, 198 }, - { 211, 199 }, { 212, 204 }, { 215, 205 }, { 220, 188 }, - { 221, 194 }, { 223, 195 }, { 225, 196 }, { 227, 197 }, + { 143, 261 }, { 144, 229 }, { 145, 230 }, { 146, 231 }, + { 148, 232 }, { 149, 233 }, { 150, 234 }, { 151, 264 }, + { 152, 235 }, { 154, 212 }, { 157, 213 }, { 161, 219 }, + { 170, 236 }, { 171, 221 }, { 174, 222 }, { 175, 237 }, + { 176, 223 }, { 177, 170 }, { 180, 238 }, { 181, 239 }, + { 182, 240 }, { 183, 241 }, { 184, 242 }, { 185, 243 }, + { 190, 178 }, { 193, 184 }, { 196, 185 }, { 198, 186 }, + { 200, 174 }, { 201, 175 }, { 205, 176 }, { 206, 177 }, + { 208, 187 }, { 210, 198 }, { 211, 199 }, { 212, 204 }, + { 215, 205 }, { 220, 188 }, { 221, 194 }, { 223, 195 }, + { 225, 196 }, { 227, 197 }, }; static struct msm_pinctrl_soc_data sc8280xp_pinctrl = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 11/261 dmaengine: sun6i-dma: Fix reclaim descriptors while terminating DMA
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hongling Zeng <[email protected]>
[ Upstream commit ab1150115e68a46b687eb38c1ab92782018c9f2c ]
When terminating DMA transfers, active descriptors are not properly reclaimed. Only cyclic descriptors were handled, leaving non-cyclic descriptors and their LLI chains to be permanently leaked.
Fix by using vchan_terminate_vdesc() which handles both cyclic and non-cyclic descriptors by adding them to desc_terminated queue for proper cleanup.
Add pchan->desc != pchan->done check to prevent double-adding completed descriptors, which would corrupt the list.
--- drivers/dma/sun6i-dma.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
drivers/dma/sun6i-dma.c +4 -7
@@ -934,16 +934,13 @@ static int sun6i_dma_terminate_all(struct dma_chan *chan)spin_lock_irqsave (&vchan->vc.lock, flags); -if (vchan->cyclic) { - vchan->cyclic = false; -if (pchan && pchan->desc) { -struct virt_dma_desc *vd = &pchan->desc->vd; -struct virt_dma_chan *vc = &vchan->vc; +if (pchan && pchan->desc && pchan->desc != pchan->done) { +struct virt_dma_desc *vd = &pchan->desc->vd; -list_add_tail (&vd->node, &vc->desc_completed); - } +vchan_terminate_vdesc (vd); } + vchan->cyclic = false;vchan_get_all_descriptors (&vchan->vc, &head);if (pchan) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 12/261 dmaengine: idxd: fix fdev setup failure cleanup in idxd_cdev_open()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit ee1d7274102285d78a53161fc705a8d8cd40b066 ]
The failed_dev_add and failed_dev_name paths drop the file-device reference while wq->wq_lock is still held. If put_device(fdev) drops the last reference, idxd_file_dev_release() runs synchronously and tries to take wq->wq_lock again, deadlocking.
Those paths also fall through into the later ctx cleanup labels even though idxd_file_dev_release() owns that cleanup and frees ctx. This can make idxd_xa_pasid_remove(ctx) and kfree(ctx) operate on a freed context.
Move idxd_wq_get() before file-device setup can fail, since the release callback always calls idxd_wq_put(). Then unlock wq->wq_lock before put_device(fdev) and return directly from the file-device setup failure path, leaving ctx cleanup to the release callback.
--- drivers/dma/idxd/cdev.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/dma/idxd/cdev.c +3 -1
@@ -293,6 +293,7 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp) fdev->parent =cdev_dev (idxd_cdev); fdev->bus = &dsa_bus_type; fdev->type = &idxd_cdev_file_type; +idxd_wq_get (wq); rc =dev_set_name (fdev,"file%d" , ctx->id);if (rc <0 ) {
@@ -306,13 +307,14 @@ static int idxd_cdev_open(struct inode *inode, struct file *filp) goto failed_dev_add; } -idxd_wq_get (wq);mutex_unlock (&wq->wq_lock);return 0 ; failed_dev_add: failed_dev_name: +mutex_unlock (&wq->wq_lock);put_device (fdev); +return rc; failed_ida: failed_set_pasid:if (device_user_pasid_enabled (idxd))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 13/261 ata: sata_mv: accept 1 or 2 resources in platform probe
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rosen Penev <[email protected]>
[ Upstream commit ef19a9cf037957fe3a35df8355c76ff0a63a0436 ]
Board files in arch/arm/plat-orion, arch/arm/mach-dove, arch/arm/mach-mv78xx0 and arch/arm/mach-orion5x still register the "sata_mv" device with two resources (IORESOURCE_MEM plus IORESOURCE_IRQ). Those devices are rejected with -EINVAL, so SATA no longer probes on legacy Marvell Orion/Kirkwood-style boards.
Accept both 1 resource (DT, IRQ fetched via platform_get_irq()) and 2 resources (legacy, IRQ supplied as a second resource) so both probing paths work.
--- drivers/ata/sata_mv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/ata/sata_mv.c +1 -1
@@ -4026,7 +4026,7 @@ static int mv_platform_probe(struct platform_device *pdev)/* * Simple resource validation .. */ -if (unlikely (pdev->num_resources !=1 )) { +if (unlikely (pdev->num_resources !=1 && pdev->num_resources !=2 )) {dev_err (&pdev->dev,"invalid number of resources\n" );return -EINVAL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 14/261 ata: libahci_platform: support non-consecutive port numbers
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Josua Mayer <[email protected]>
[ Upstream commit 8c87215dd3a2c814dcffc0bafe8c80c8f98f2574 ]
So far ahci_platform relied on number of child nodes in firmware to allocate arrays and expected port numbers to start from 0 without holes. This number of ports is then set in private structure for use when configuring phys and regulators.
Some platforms may not use every port of an ahci controller. E.g. SolidRUN CN9130 Clearfog uses only port 1 but not port 0, leading to the following errors during boot:
[ 1.719476] ahci f2540000.sata: invalid port number 1 [ 1.724562] ahci f2540000.sata: No port enabled
Update all accessesors of ahci_host_priv phys and target_pwrs arrays to support holes. Access is gated by hpriv->mask_port_map which has a bit set for each enabled port.
Update ahci_platform_get_resources to ignore holes in the port numbers and enable ports defined in firmware by their reg property only.
When firmware does not define children it is assumed that there is exactly one port, using index 0.
Stable-dep-of: 4d99a91574c4 ("ata: ahci_ceva: fix error paths in ceva_ahci_platform_enable_resources()")
--- drivers/ata/ahci_brcm.c | 3 +++ drivers/ata/ahci_ceva.c | 6 +++++ drivers/ata/libahci_platform.c | 40 +++++++++++++++++++++++++++++----- 3 files changed, 43 insertions(+), 6 deletions(-)
drivers/ata/ahci_brcm.c +3 -0
@@ -288,6 +288,9 @@ static unsigned int brcm_ahci_read_id(struct ata_device *dev,/* Re-initialize and calibrate the PHY */ for (i =0 ; i < hpriv->nports; i++) { +if (!(hpriv->mask_port_map & (1 << i))) +continue ; + rc =phy_init (hpriv->phys[i]);if (rc) goto disable_phys;
drivers/ata/ahci_ceva.c +6 -0
@@ -206,6 +206,9 @@ static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv) goto disable_clks;for (i =0 ; i < hpriv->nports; i++) { +if (!(hpriv->mask_port_map & (1 << i))) +continue ; + rc =phy_init (hpriv->phys[i]);if (rc) goto disable_rsts;
@@ -215,6 +218,9 @@ static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv)ahci_platform_deassert_rsts (hpriv);for (i =0 ; i < hpriv->nports; i++) { +if (!(hpriv->mask_port_map & (1 << i))) +continue ; + rc =phy_power_on (hpriv->phys[i]);if (rc) {phy_exit (hpriv->phys[i]);
drivers/ata/libahci_platform.c +34 -6
@@ -49,6 +49,9 @@ int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)int rc, i;for (i =0 ; i < hpriv->nports; i++) { +if (!(hpriv->mask_port_map & (1 << i))) +continue ; + rc =phy_init (hpriv->phys[i]);if (rc) goto disable_phys;
@@ -70,6 +73,9 @@ int ahci_platform_enable_phys(struct ahci_host_priv *hpriv) disable_phys:while (--i >=0 ) { +if (!(hpriv->mask_port_map & (1 << i))) +continue ; +phy_power_off (hpriv->phys[i]);phy_exit (hpriv->phys[i]); }
@@ -88,6 +94,9 @@ void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)int i;for (i =0 ; i < hpriv->nports; i++) { +if (!(hpriv->mask_port_map & (1 << i))) +continue ; +phy_power_off (hpriv->phys[i]);phy_exit (hpriv->phys[i]); }
@@ -435,6 +444,20 @@ static int ahci_platform_get_firmware(struct ahci_host_priv *hpriv,return 0 ; } +static u32 ahci_platform_find_max_port_id (struct device *dev) +{ +u32 max_port =0 ; + +for_each_child_of_node_scoped (dev->of_node, child) { +u32 port; + +if (!of_property_read_u32 (child,"reg" , &port)) + max_port =max (max_port, port); + } + +return max_port; +} +/** * ahci_platform_get_resources - Get platform resources * @pdev: platform device to get resources for
@@ -462,6 +485,7 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,struct ahci_host_priv *hpriv;struct device_node *child;u32 mask_port_map =0 ; +u32 max_port;if (!devres_open_group (dev,NULL ,GFP_KERNEL ))return ERR_PTR (-ENOMEM );
@@ -553,15 +577,17 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev, goto err_out; } +/* find maximum port id for allocating structures */ + max_port =ahci_platform_find_max_port_id (dev);/* -* If no sub-node was found, we still need to set nports to -* one in order to be able to use the +* Set nports according to maximum port id. Clamp at +* AHCI_MAX_PORTS, warning message for invalid port id +* is generated later. +* When DT has no sub-nodes max_port is 0, nports is 1, +* in order to be able to use the * ahci_platform_[en|dis]able_[phys|regulators] functions. */ -if (child_nodes) - hpriv->nports = child_nodes; -else - hpriv->nports =1 ; + hpriv->nports =min (AHCI_MAX_PORTS , max_port +1 ); hpriv->phys =devm_kcalloc (dev, hpriv->nports,sizeof (*hpriv->phys),GFP_KERNEL );if (!hpriv->phys) {
@@ -634,6 +660,8 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,* If no sub-node was found, keep this for device tree * compatibility */ + hpriv->mask_port_map |=BIT (0 ); + rc =ahci_platform_get_phy (hpriv,0 , dev, dev->of_node);if (rc) goto err_out;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 15/261 ahci: Introduce ahci_ignore_port() helper
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal <[email protected]>
[ Upstream commit c9b5be909e6595547ed5d45aef39fd65948aa342 ]
libahci and AHCI drivers may ignore some ports if the port is invalid (its ID does not correspond to a valid physical port) or if the user explicitly requested the port to be ignored with the mask_port_map ahci module parameter. Such port that shall be ignored can be identified by checking that the bit corresponding to the port ID is not set in the mask_port_map field of struct ahci_host_priv. E.g. code such as:
"if (!(hpriv->mask_port_map & (1 << portid)))".
Replace all direct use of the mask_port_map field to detect such port with the new helper inline function ahci_ignore_port() to make the code more readable/easier to understand.
The comment describing the mask_port_map field of struct ahci_host_priv is also updated to be more accurate.
Stable-dep-of: 4d99a91574c4 ("ata: ahci_ceva: fix error paths in ceva_ahci_platform_enable_resources()")
--- drivers/ata/ahci.h | 13 ++++++++++++- drivers/ata/ahci_brcm.c | 2 +- drivers/ata/ahci_ceva.c | 4 ++-- drivers/ata/libahci_platform.c | 6 +++--- 4 files changed, 18 insertions(+), 7 deletions(-)
drivers/ata/ahci.h +12 -1
@@ -330,7 +330,7 @@ struct ahci_port_priv {struct ahci_host_priv {/* Input fields */ unsigned int flags;/* AHCI_HFLAG_* */ -u32 mask_port_map;/* mask out particular bits */ +u32 mask_port_map;/* Mask of valid ports */ void __iomem * mmio;/* bus-independent mem map */ u32 cap;/* cap to use */
@@ -381,6 +381,17 @@ struct ahci_host_priv { int port); }; +/* +* Return true if a port should be ignored because it is excluded from +* the host port map. +*/ +static inline bool ahci_ignore_port (struct ahci_host_priv *hpriv, +unsigned int portid) +{ +return portid >= hpriv->nports || + !(hpriv->mask_port_map & (1 << portid)); +} +extern int ahci_ignore_sss;extern const struct attribute_group *ahci_shost_groups[];
drivers/ata/ahci_brcm.c +1 -1
@@ -288,7 +288,7 @@ static unsigned int brcm_ahci_read_id(struct ata_device *dev,/* Re-initialize and calibrate the PHY */ for (i =0 ; i < hpriv->nports; i++) { -if (!(hpriv->mask_port_map & (1 << i))) +if (ahci_ignore_port (hpriv, i))continue ; rc =phy_init (hpriv->phys[i]);
drivers/ata/ahci_ceva.c +2 -2
@@ -206,7 +206,7 @@ static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv) goto disable_clks;for (i =0 ; i < hpriv->nports; i++) { -if (!(hpriv->mask_port_map & (1 << i))) +if (ahci_ignore_port (hpriv, i))continue ; rc =phy_init (hpriv->phys[i]);
@@ -218,7 +218,7 @@ static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv)ahci_platform_deassert_rsts (hpriv);for (i =0 ; i < hpriv->nports; i++) { -if (!(hpriv->mask_port_map & (1 << i))) +if (ahci_ignore_port (hpriv, i))continue ; rc =phy_power_on (hpriv->phys[i]);
drivers/ata/libahci_platform.c +3 -3
@@ -49,7 +49,7 @@ int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)int rc, i;for (i =0 ; i < hpriv->nports; i++) { -if (!(hpriv->mask_port_map & (1 << i))) +if (ahci_ignore_port (hpriv, i))continue ; rc =phy_init (hpriv->phys[i]);
@@ -73,7 +73,7 @@ int ahci_platform_enable_phys(struct ahci_host_priv *hpriv) disable_phys:while (--i >=0 ) { -if (!(hpriv->mask_port_map & (1 << i))) +if (ahci_ignore_port (hpriv, i))continue ;phy_power_off (hpriv->phys[i]);
@@ -94,7 +94,7 @@ void ahci_platform_disable_phys(struct ahci_host_priv *hpriv)int i;for (i =0 ; i < hpriv->nports; i++) { -if (!(hpriv->mask_port_map & (1 << i))) +if (ahci_ignore_port (hpriv, i))continue ;phy_power_off (hpriv->phys[i]);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 16/261 ata: ahci_ceva: fix error paths in ceva_ahci_platform_enable_resources()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Radhey Shyam Pandey <[email protected]>
[ Upstream commit 4d99a91574c420decab56cc880fad0dc15b8a7a3 ]
On phy_init() failure the error path fallsthrough to disable_rsts, which deasserts the controller reset and then enters disable_phys calling phy_power_off() on PHYs that were never powered on. That corrupts the PHY power_count and triggers an extra runtime PM put.
Use a separate exit_phys path that unwinds with phy_exit() only and falls through to disable_clks while the controller remains in reset. Reserve phy_power_off() for the phy_power_on() failure path only, and skip masked-out ports in both unwind loops.
On phy_power_on() failure re-assert the controller reset before disabling clocks and regulators, matching the teardown order used by ahci_platform_enable_resources() and ahci_platform_disable_resources().
--- drivers/ata/ahci_ceva.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-)
drivers/ata/ahci_ceva.c +14 -4
@@ -211,7 +211,7 @@ static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv) rc =phy_init (hpriv->phys[i]);if (rc) - goto disable_rsts; + goto exit_phys; }/* De-assert the controller reset */
@@ -230,14 +230,24 @@ static int ceva_ahci_platform_enable_resources(struct ahci_host_priv *hpriv)return 0 ; -disable_rsts: -ahci_platform_deassert_rsts (hpriv); - disable_phys:while (--i >=0 ) { +if (ahci_ignore_port (hpriv, i)) +continue ; +phy_power_off (hpriv->phys[i]);phy_exit (hpriv->phys[i]); } +ahci_platform_assert_rsts (hpriv); + goto disable_clks; + +exit_phys: +while (--i >=0 ) { +if (ahci_ignore_port (hpriv, i)) +continue ; + +phy_exit (hpriv->phys[i]); + } disable_clks:ahci_platform_disable_clks (hpriv);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 17/261 ASoC: max98095: fix missing IS_ERR() before PTR_ERR() on mclk lookup
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uday Khare <[email protected]>
[ Upstream commit 317e21532e6ffa1de026bdbce5ba98e1b70ca5c6 ]
In max98095_probe(), the -EPROBE_DEFER check after devm_clk_get() is broken due to a missing IS_ERR() guard.
The code intends to return -EPROBE_DEFER only when the clock lookup fails with that specific error. However, without IS_ERR() the check:
if (PTR_ERR(max98095->mclk) == -EPROBE_DEFER)
is called unconditionally, including when devm_clk_get() succeeds and returns a valid pointer. Calling PTR_ERR() on a valid pointer reinterprets its address as a signed long; the result is arbitrary and is almost never equal to -EPROBE_DEFER, so the check silently does nothing in the success case. When devm_clk_get() fails with any error other than -EPROBE_DEFER the check is also skipped, leaving max98095->mclk holding an error pointer with no indication to the caller.
This means a deferred probe will never actually be triggered for this device, and any non-EPROBE_DEFER clock error is silently swallowed with the error pointer left in the mclk field.
Fix this by adding the missing IS_ERR() guard around the PTR_ERR() call, matching the pattern already used in the sibling max98088 and wm8960 drivers.
--- sound/soc/codecs/max98095.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
sound/soc/codecs/max98095.c +3 -2
@@ -1984,8 +1984,9 @@ static int max98095_probe(struct snd_soc_component *component)int ret =0 ; max98095->mclk =devm_clk_get (component->dev,"mclk" ); -if (PTR_ERR (max98095->mclk) == -EPROBE_DEFER ) -return -EPROBE_DEFER ; +if (IS_ERR (max98095->mclk)) +if (PTR_ERR (max98095->mclk) == -EPROBE_DEFER ) +return -EPROBE_DEFER ;/* reset the codec, the DSP core, and disable all interrupts */ max98095_reset (component);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 18/261 ASoC: max98090: fix missing IS_ERR() before PTR_ERR() on mclk lookup
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Uday Khare <[email protected]>
[ Upstream commit a792ce0fad61a70793ec565743f11d6ca534de59 ]
In max98090_probe(), the -EPROBE_DEFER check after devm_clk_get() is broken due to a missing IS_ERR() guard.
The code intends to return -EPROBE_DEFER only when the clock lookup fails with that specific error. However, without IS_ERR() the check:
if (PTR_ERR(max98090->mclk) == -EPROBE_DEFER)
is called unconditionally, including when devm_clk_get() succeeds and returns a valid pointer. Calling PTR_ERR() on a valid pointer reinterprets its address as a signed long; the result is arbitrary and is almost never equal to -EPROBE_DEFER, so the check silently does nothing in the success case. When devm_clk_get() fails with any error other than -EPROBE_DEFER the check is also skipped, leaving max98090->mclk holding an error pointer with no indication to the caller.
This means a deferred probe will never actually be triggered for this device, and any non-EPROBE_DEFER clock error is silently swallowed with the error pointer left in the mclk field.
Fix this by adding the missing IS_ERR() guard around the PTR_ERR() call, matching the pattern already used in the sibling max98088 and wm8960 drivers.
--- sound/soc/codecs/max98090.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
sound/soc/codecs/max98090.c +3 -2
@@ -2388,8 +2388,9 @@ static int max98090_probe(struct snd_soc_component *component)dev_dbg (component->dev,"max98090_probe\n" ); max98090->mclk =devm_clk_get (component->dev,"mclk" ); -if (PTR_ERR (max98090->mclk) == -EPROBE_DEFER ) -return -EPROBE_DEFER ; +if (IS_ERR (max98090->mclk)) +if (PTR_ERR (max98090->mclk) == -EPROBE_DEFER ) +return -EPROBE_DEFER ; max98090->component = component;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 19/261 btrfs: zoned: fix deadlock between metadata writeback and transaction commit
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Thumshirn <[email protected]>
[ Upstream commit 1ebe51c29fa9755d5b2fea28727c051117907cf8 ]
When writing out metadata extent buffers in a zoned filesystem, btree_writepages() holds fs_info->zoned_meta_io_lock across the whole writeback loop, including the call to btrfs_check_meta_write_pointer() -> check_bg_is_active().
For the tree-log block group, check_bg_is_active() may fail to activate the zone and fall back to btrfs_zone_finish_one_bg() to free an active zone. That path waits for the running transaction to commit while still holding zoned_meta_io_lock, but the committer needs that same lock to write out the tree extents, so the two tasks deadlock:
Task A (kworker, metadata writeback) Task B (fsstress, transaction commit) ------------------------------------ ------------------------------------- wb_workfn() btrfs_commit_transaction(T)
btree_writepages() btrfs_write_and_wait_transaction()
btrfs_zoned_meta_io_lock() btrfs_write_marked_extents()
btrfs_check_meta_write_pointer() btree_writepages()
check_bg_is_active() [treelog_bg] btrfs_zoned_meta_io_lock()
btrfs_zone_finish_one_bg() <blocks on zoned_meta_io_lock,
btrfs_zone_finish() held by Task A>
do_zone_finish()
btrfs_inc_block_group_ro()
btrfs_wait_for_commit()
<blocks waiting for commit
of transaction T, done by
Task B>
The sibling branch in check_bg_is_active() already drops zoned_meta_io_lock around do_zone_finish() for this exact reason. Do the same in the tree-log
branch: release the lock around btrfs_zone_finish_one_bg() and re-acquire it afterwards. The lock only protects fs_info->active_{meta,system}_bg, which this branch does not touch, and ctx->zoned_bg keeps a reference to the block group across the unlock, so nothing is lost while the lock is dropped.
This hang occasionally reproduces with fstests generic/475 on a zoned btrfs filesystem.
--- fs/btrfs/zoned.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
fs/btrfs/zoned.c +5 -1
@@ -1775,7 +1775,11 @@ static bool check_bg_is_active(struct btrfs_eb_write_context *ctx,if (fs_info->treelog_bg == block_group->start) {if (!btrfs_zone_activate (block_group)) { -int ret_fin =btrfs_zone_finish_one_bg (fs_info); +int ret_fin; + +btrfs_zoned_meta_io_unlock (fs_info); + ret_fin =btrfs_zone_finish_one_bg (fs_info); +btrfs_zoned_meta_io_lock (fs_info);if (ret_fin !=1 || !btrfs_zone_activate (block_group))return false;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 20/261 phy-zynqmp: Postpone getting clock rate until actually needed
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Looijmans <[email protected]>
[ Upstream commit 065d5885f6180c534b7b176847b3e008f4e11850 ]
At probe time the driver would display the following error and abort:
xilinx-psgtr fd400000.phy: Invalid rate 0 for reference clock 0
At probe time, the associated GTR driver (e.g. SATA or PCIe) hasn't initialized the clock yet, so clk_get_rate() likely returns 0 if the clock is programmable. So this driver only works if the clock is fixed.
The PHY driver doesn't need to know the clock frequency at probe yet, so wait until the associated driver initializes the lane before requesting the clock rate setting.
In addition to allowing the driver to be used with programmable clocks, this also reduces the driver's runtime memory footprint by removing an array of pointers from struct xpsgtr_phy.
Stable-dep-of: e4779e2a16d6 ("phy: zynqmp: fix clock error handling in xpsgtr_phy_init()")
--- drivers/phy/xilinx/phy-zynqmp.c | 70 +++++++++++++++++---------------- 1 file changed, 37 insertions(+), 33 deletions(-)
drivers/phy/xilinx/phy-zynqmp.c +37 -33
@@ -227,7 +227,6 @@ struct xpsgtr_phy {* @siou: siou base address * @gtr_mutex: mutex for locking * @phys: PHY lanes -* @refclk_sscs: spread spectrum settings for the reference clocks * @clk: reference clocks * @tx_term_fix: fix for GT issue * @saved_icm_cfg0: stored value of ICM CFG0 register
@@ -240,7 +239,6 @@ struct xpsgtr_dev {void __iomem *siou;struct mutex gtr_mutex;/* mutex for locking */ struct xpsgtr_phy phys[NUM_LANES ]; -const struct xpsgtr_ssc *refclk_sscs[NUM_LANES ];struct clk *clk[NUM_LANES ];bool tx_term_fix;unsigned int saved_icm_cfg0;
@@ -383,13 +381,40 @@ static int xpsgtr_wait_pll_lock(struct phy *phy)return ret; } +/* Get the spread spectrum (SSC) settings for the reference clock rate */ +static const struct xpsgtr_ssc *xpsgtr_find_sscs (struct xpsgtr_phy *gtr_phy) +{ +unsigned long rate; +struct clk *clk; +unsigned int i; + + clk = gtr_phy->dev->clk[gtr_phy->refclk]; + rate =clk_get_rate (clk); + +for (i =0 ; i <ARRAY_SIZE (ssc_lookup); i++) { +/* Allow an error of 100 ppm */ +unsigned long error = ssc_lookup[i].refclk_rate /10000 ; + +if (abs (rate - ssc_lookup[i].refclk_rate) < error) +return &ssc_lookup[i]; + } + +dev_err (gtr_phy->dev->dev,"Invalid rate %lu for reference clock %u\n" , + rate, gtr_phy->refclk); + +return NULL ; +} +/* Configure PLL and spread-sprectrum clock. */ -static void xpsgtr_configure_pll (struct xpsgtr_phy *gtr_phy) +static int xpsgtr_configure_pll (struct xpsgtr_phy *gtr_phy) {const struct xpsgtr_ssc *ssc;u32 step_size; - ssc = gtr_phy->dev->refclk_sscs[gtr_phy->refclk]; + ssc =xpsgtr_find_sscs (gtr_phy); +if (!ssc) +return -EINVAL ; + step_size = ssc->step_size; xpsgtr_clr_set(gtr_phy->dev, PLL_REF_SEL(gtr_phy->lane),
@@ -431,6 +456,8 @@ static void xpsgtr_configure_pll(struct xpsgtr_phy *gtr_phy)xpsgtr_clr_set_phy (gtr_phy,L0_PLL_SS_STEP_SIZE_3_MSB ,STEP_SIZE_3_MASK , (step_size &STEP_SIZE_3_MASK ) |FORCE_STEP_SIZE |FORCE_STEPS ); + +return 0 ; }/* Configure the lane protocol. */
@@ -643,7 +670,10 @@ static int xpsgtr_phy_init(struct phy *phy)* Configure the PLL, the lane protocol, and perform protocol-specific * initialization. */ -xpsgtr_configure_pll (gtr_phy); + ret =xpsgtr_configure_pll (gtr_phy); +if (ret) + goto out; +xpsgtr_lane_set_protocol (gtr_phy);switch (gtr_phy->protocol) {
@@ -854,8 +884,7 @@ static struct phy *xpsgtr_xlate(struct device *dev, } refclk = args->args[3 ]; -if (refclk >=ARRAY_SIZE (gtr_dev->refclk_sscs) || - !gtr_dev->refclk_sscs[refclk]) { +if (refclk >=ARRAY_SIZE (gtr_dev->clk)) {dev_err (dev,"Invalid reference clock number %u\n" , refclk);return ERR_PTR (-EINVAL ); }
@@ -931,9 +960,7 @@ static int xpsgtr_get_ref_clocks(struct xpsgtr_dev *gtr_dev) {unsigned int refclk; -for (refclk =0 ; refclk <ARRAY_SIZE (gtr_dev->refclk_sscs); ++refclk) { -unsigned long rate; -unsigned int i; +for (refclk =0 ; refclk <ARRAY_SIZE (gtr_dev->clk); ++refclk) {struct clk *clk;char name[8 ];
@@ -949,29 +976,6 @@ static int xpsgtr_get_ref_clocks(struct xpsgtr_dev *gtr_dev)continue ; gtr_dev->clk[refclk] = clk; - -/* -* Get the spread spectrum (SSC) settings for the reference -* clock rate. -*/ - rate =clk_get_rate (clk); - -for (i =0 ; i <ARRAY_SIZE (ssc_lookup); i++) { -/* Allow an error of 100 ppm */ -unsigned long error = ssc_lookup[i].refclk_rate /10000 ; - -if (abs (rate - ssc_lookup[i].refclk_rate) < error) { - gtr_dev->refclk_sscs[refclk] = &ssc_lookup[i]; -break ; - } - } - -if (i ==ARRAY_SIZE (ssc_lookup)) { -dev_err (gtr_dev->dev, -"Invalid rate %lu for reference clock %u\n" , - rate, refclk); -return -EINVAL ; - } }return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 21/261 phy: zynqmp: fix clock error handling in xpsgtr_phy_init()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Radhey Shyam Pandey <[email protected]>
[ Upstream commit e4779e2a16d600892aaf743438f6ce8cc4eb3c4c ]
Propagate clk_prepare_enable() failures to the caller instead of returning success, and disable the reference clock on initialization error paths to avoid leaking clock references when phy_exit() is not called.
--- drivers/phy/xilinx/phy-zynqmp.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/phy/xilinx/phy-zynqmp.c +9 -4
@@ -643,12 +643,13 @@ static int xpsgtr_phy_init(struct phy *phy) {struct xpsgtr_phy *gtr_phy =phy_get_drvdata (phy);struct xpsgtr_dev *gtr_dev = gtr_phy->dev; -int ret =0 ; +int ret;mutex_lock (>r_dev->gtr_mutex);/* Configure and enable the clock when peripheral phy_init call */ -if (clk_prepare_enable (gtr_dev->clk[gtr_phy->refclk])) + ret =clk_prepare_enable (gtr_dev->clk[gtr_phy->refclk]); +if (ret) goto out;/* Skip initialization if not required. */
@@ -658,7 +659,7 @@ static int xpsgtr_phy_init(struct phy *phy)if (gtr_dev->tx_term_fix) { ret =xpsgtr_phy_tx_term_fix (gtr_phy);if (ret <0 ) - goto out; + goto out_disable_clk; gtr_dev->tx_term_fix = false; }
@@ -672,7 +673,7 @@ static int xpsgtr_phy_init(struct phy *phy)*/ ret =xpsgtr_configure_pll (gtr_phy);if (ret) - goto out; + goto out_disable_clk;xpsgtr_lane_set_protocol (gtr_phy);
@@ -690,6 +691,10 @@ static int xpsgtr_phy_init(struct phy *phy)break ; } + goto out; + +out_disable_clk: +clk_disable_unprepare (gtr_dev->clk[gtr_phy->refclk]); out:mutex_unlock (>r_dev->gtr_mutex);return ret;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 22/261 phy: zynqmp: fix runtime PM leak on probe allocation failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Radhey Shyam Pandey <[email protected]>
[ Upstream commit f3506e15cf72e94f62d5f2d173e5b7008f644cde ]
Allocate saved_regs before pm_runtime_resume_and_get() so a devm_kmalloc() failure does not leave an unreleased runtime PM usage counter.
--- drivers/phy/xilinx/phy-zynqmp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/phy/xilinx/phy-zynqmp.c +6 -6
@@ -1045,6 +1045,12 @@ static int xpsgtr_probe(struct platform_device *pdev)return PTR_ERR (provider); } + gtr_dev->saved_regs =devm_kmalloc (gtr_dev->dev, +sizeof (save_reg_address), +GFP_KERNEL ); +if (!gtr_dev->saved_regs) +return -ENOMEM ; +pm_runtime_set_active (gtr_dev->dev);pm_runtime_enable (gtr_dev->dev);
@@ -1054,12 +1060,6 @@ static int xpsgtr_probe(struct platform_device *pdev)return ret; } - gtr_dev->saved_regs =devm_kmalloc (gtr_dev->dev, -sizeof (save_reg_address), -GFP_KERNEL ); -if (!gtr_dev->saved_regs) -return -ENOMEM ; -return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 23/261 netfilter: nf_conntrack_sip: widen NAT rewrite delta to s32 in sip_help_tcp()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
[ Upstream commit db3d0e0e5d4bc5ab4fe445b9f413d1b486508ca5 ]
sip_help_tcp() stores the size change of each NAT-rewritten SIP message in s16 diff and accumulates it in s16 tdiff, but a single message can grow by more than S16_MAX while the packet stays under the 65535 enlarge_skb() limit: nf_nat_sip() rewrites every matching URI, and a long Contact list expands the message by tens of kilobytes. diff then wraps, and "datalen = datalen + diff - msglen" yields a huge unsigned datalen, so the next iteration's ct_sip_get_header() reads past the linearized skb tail.
Widen diff, tdiff and the seq_adjust hook to s32. Both are bounded by the 65535 byte packet limit, and the seqadj core is already s32 (nf_ct_seqadj_set() takes s32), so no previously accepted input is rejected.
BUG: KASAN: use-after-free in ct_sip_get_header (net/netfilter/nf_conntrack_sip.c:464) Read of size 1 at addr ffff888010800000 by task ksoftirqd/1/25 ct_sip_get_header (net/netfilter/nf_conntrack_sip.c:464) sip_help_tcp (net/netfilter/nf_conntrack_sip.c:1694) nf_confirm (net/netfilter/nf_conntrack_proto.c:183) nf_hook_slow (net/netfilter/core.c:619) ip6_output (net/ipv6/ip6_output.c:246) ip6_forward (net/ipv6/ip6_output.c:690) ipv6_rcv (net/ipv6/ip6_input.c:351) __netif_receive_skb_one_core (net/core/dev.c:6212) process_backlog (net/core/dev.c:6676) __napi_poll (net/core/dev.c:7735) net_rx_action (net/core/dev.c:7955) handle_softirqs (kernel/softirq.c:622) run_ksoftirqd (kernel/softirq.c:1076) ...
--- include/linux/netfilter/nf_conntrack_sip.h | 2 +- net/netfilter/nf_conntrack_sip.c | 2 +- net/netfilter/nf_nat_sip.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
include/linux/netfilter/nf_conntrack_sip.h +1 -1
@@ -115,7 +115,7 @@ struct nf_nat_sip_hooks { unsigned int *datalen);void (*seq_adjust)(struct sk_buff *skb, -unsigned int protoff,s16 off); +unsigned int protoff,s32 off); unsigned int (*expect)(struct sk_buff *skb, unsigned int protoff,
net/netfilter/nf_conntrack_sip.c +1 -1
@@ -1629,7 +1629,7 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff,unsigned int matchoff, matchlen;unsigned int msglen, origlen;const char *dptr, *end; -s16 diff, tdiff =0 ; +s32 diff, tdiff =0 ;int ret =NF_ACCEPT ;unsigned long clen;bool term;
net/netfilter/nf_nat_sip.c +1 -1
@@ -315,7 +315,7 @@ static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, }static void nf_nat_sip_seq_adjust (struct sk_buff *skb,unsigned int protoff, -s16 off) +s32 off) {enum ip_conntrack_info ctinfo;struct nf_conn *ct =nf_ct_get (skb, &ctinfo);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 24/261 drm/mediatek: Check CRTC state before freeing
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit 233a4d3a39fc1585f5e271b2adab43c6af025ae0 ]
mtk_crtc_reset() destroys the current CRTC state only when crtc->state is non-NULL, but it always converts crtc->state to struct mtk_crtc_state and passes the result to kfree().
When reset is called without an existing state, container_of(NULL, ...) does not produce NULL. Keep the mtk state free in the same crtc->state guard as the helper state destruction.
This issue was found by a static analysis checker and confirmed by manual source review.
--- drivers/gpu/drm/mediatek/mtk_drm_crtc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/gpu/drm/mediatek/mtk_drm_crtc.c +3 -3
@@ -185,10 +185,10 @@ static void mtk_drm_crtc_reset(struct drm_crtc *crtc) {struct mtk_crtc_state *state; -if (crtc->state) +if (crtc->state) {__drm_atomic_helper_crtc_destroy_state (crtc->state); - -kfree (to_mtk_crtc_state (crtc->state)); +kfree (to_mtk_crtc_state (crtc->state)); + } crtc->state =NULL ; state =kzalloc (sizeof (*state),GFP_KERNEL );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 25/261 keys: fix out-of-bounds read in keyring_get_key_chunk()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
[ Upstream commit 63918731f9ae25b5deb022f118e941e6dddfcef4 ]
For description-level chunks keyring_get_key_chunk() advances the read pointer by level * sizeof(long) past the inline prefix but only bounds-checks the prefix, so a long enough key description is read past its kmemdup(desc, desc_len + 1) allocation. Compute the full byte offset and bounds-check the description against it before reading.
The walk only reaches a description-level chunk when two keys collide through the hash, x, type and domain_tag chunks, so this is reached from an unprivileged add_key(2) with a crafted pair of same-type keys whose index hashes collide; KASAN reports a slab-out-of-bounds read.
--- security/keys/keyring.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
security/keys/keyring.c +5 -4
@@ -271,6 +271,7 @@ static unsigned long keyring_get_key_chunk(const void *data, int level)unsigned long chunk =0 ;const u8 *d;int desc_len = index_key->desc_len, n =sizeof (chunk); +unsigned int offset; level /=ASSOC_ARRAY_KEY_CHUNK_SIZE ;switch (level) {
@@ -284,12 +285,12 @@ static unsigned long keyring_get_key_chunk(const void *data, int level)return (unsigned long )index_key->domain_tag;default : level -=4 ; -if (desc_len <=sizeof (index_key->desc)) + offset =sizeof (index_key->desc) + level *sizeof (long ); +if (desc_len <= offset)return 0 ; - d = index_key->description +sizeof (index_key->desc); - d += level *sizeof (long ); - desc_len -=sizeof (index_key->desc); + d = index_key->description + offset; + desc_len -= offset;if (desc_len > n) desc_len = n; do {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 26/261 keys: make keyring key-chunk byte order agree with keyring_diff_objects()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
[ Upstream commit 58565eef0f8d861aae92abfb7658458d661cee17 ]
keyring_get_key_chunk() loads description bytes into the index chunk low address first, while keyring_diff_objects() numbers the first differing bit from the low end and folds the absolute byte index into the level without removing the inline-prefix offset the level already carries. The two disagree on byte order and bit position, so the array can be told two keys first differ at a bit that does not differ in the chunk the walker uses, letting crafted descriptions collide into one node.
Load the chunk in the order keyring_diff_objects() assumes and drop the inline-prefix length when folding the byte index into the level. This only changes the in-memory ordering used to place keys within a keyring; add, search and read of non-colliding keys are unaffected.
--- security/keys/keyring.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
security/keys/keyring.c +3 -2
@@ -293,9 +293,10 @@ static unsigned long keyring_get_key_chunk(const void *data, int level) desc_len -= offset;if (desc_len > n) desc_len = n; + d += desc_len;do { chunk <<=8 ; - chunk |= *d++; + chunk |= *--d; }while (--desc_len >0 );return chunk; }
@@ -376,7 +377,7 @@ static int keyring_diff_objects(const void *object, const void *data)return -1 ; differ_plus_i: - level += i; + level += i - (int )sizeof (a->desc); differ: i = level *8 +__ffs (seg_a ^ seg_b);return i;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 27/261 assoc_array: trim the final shortcut word using the current chunk end
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
[ Upstream commit a82c8a05e86f3f84e09698f65b4515b5d04633f6 ]
assoc_array_walk() masks off the bits past shortcut->skip_to_level in the word that contains skip_to_level, gated onround_up(sc_level, ASSOC_ARRAY_KEY_CHUNK_SIZE) > skip_to_level.
That guard is wrong in two opposite ways:
- When sc_level is word-aligned (every word after the first) round_up() is a no-op, so the guard is sc_level > skip_to_level and never fires for the word that holds skip_to_level. A shortcut that spans more than one word and ends in the middle of its last word leaves that word untrimmed, and its stale high bits leak into the dissimilarity word and can steer the walk down the wrong descendant.
- When sc_level is unaligned (the first word) and skip_to_level sits on the next chunk boundary, sc_level + CHUNK would exceed skip_to_level and fire the trim with shift = skip_to_level & CHUNK_MASK == 0, which clears the whole dissimilarity word and makes a differing shortcut compare equal.
Use the end of the chunk that contains sc_level instead:
skip_to_level < round_down(sc_level, CHUNK) + CHUNK
For an aligned sc_level whose word holds skip_to_level this now fires (the first bug); for an unaligned sc_level with skip_to_level on the following boundary it does not, so shift is never 0 when the branch runs and the trim never clears the whole word.
--- lib/assoc_array.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
lib/assoc_array.c +2 -1
@@ -255,7 +255,8 @@ assoc_array_walk(const struct assoc_array *array, sc_segments = shortcut->index_key[sc_level >>ASSOC_ARRAY_KEY_CHUNK_SHIFT ]; dissimilarity = segments ^ sc_segments; -if (round_up (sc_level,ASSOC_ARRAY_KEY_CHUNK_SIZE ) > shortcut->skip_to_level) { +if (shortcut->skip_to_level <round_down (sc_level, +ASSOC_ARRAY_KEY_CHUNK_SIZE ) +ASSOC_ARRAY_KEY_CHUNK_SIZE ) {/* Trim segments that are beyond the shortcut */ int shift = shortcut->skip_to_level &ASSOC_ARRAY_KEY_CHUNK_MASK ; dissimilarity &= ~(ULONG_MAX << shift);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 28/261 netfilter: xt_hashlimit: validate hashtable supports XT_HASHLIMIT_RATE_MATCH
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 305b63e1402267459fdabb183af4527f6799eebf ]
The XT_HASHLIMIT_RATE_MATCH flag mode changes the semantics of the dsthash_ent structure which represents an entry in the hashtable. There is a union area which uses a different layout to express the rate match mode.
Update .checkentry path to validate the XT_HASHLIMIT_RATE_MATCH mode flag is requested by two or more different rules that refer to the same hashtable. Otherwise, uninitialized access to the burst field in the union is possible.
Reject the use of the XT_HASHLIMIT_RATE_MATCH mode flag if set on by revision less than 3 too.
--- net/netfilter/xt_hashlimit.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
net/netfilter/xt_hashlimit.c +15 -1
@@ -118,6 +118,7 @@ struct xt_hashlimit_htable {refcount_t use;u_int8_t family;bool rnd_initialized; +bool ratematch;struct hashlimit_cfg3 cfg;/* config */
@@ -325,6 +326,7 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg,vfree (hinfo);return -ENOMEM ; } + hinfo->ratematch = !!(cfg->mode &XT_HASHLIMIT_RATE_MATCH );spin_lock_init (&hinfo->lock);switch (revision) {
@@ -868,7 +870,10 @@ static int hashlimit_mt_check_common(const struct xt_mtchk_param *par, }/* Check for overflow. */ -if (revision >=3 && cfg->mode &XT_HASHLIMIT_RATE_MATCH ) { +if (cfg->mode &XT_HASHLIMIT_RATE_MATCH ) { +if (revision <3 ) +return -EINVAL ; +if (cfg->avg ==0 || cfg->avg >U32_MAX ) {pr_info_ratelimited ("invalid rate\n" );return -ERANGE ;
@@ -901,6 +906,15 @@ static int hashlimit_mt_check_common(const struct xt_mtchk_param *par,mutex_unlock (&hashlimit_mutex);return ret; } + }else { +if ((cfg->mode &XT_HASHLIMIT_RATE_MATCH && + !(*hinfo)->ratematch) || + (!(cfg->mode &XT_HASHLIMIT_RATE_MATCH ) && + (*hinfo)->ratematch)) { +mutex_unlock (&hashlimit_mutex); +htable_put (*hinfo); +return -EINVAL ; + } }mutex_unlock (&hashlimit_mutex);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 29/261 sched: Add task_struct->faults_disabled_mapping
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kent Overstreet <[email protected]>
[ Upstream commit 2b69987be575b92adb6c177679f3c559134f0d8f ]
There has been a long standing page cache coherence bug with direct IO. This provides part of a mechanism to fix it, currently just used by bcachefs but potentially worth promoting to the VFS.
Direct IO evicts the range of the pagecache being read or written to.
For reads, we need dirty pages to be written to disk, so that the read doesn't return stale data. For writes, we need to evict that range of the pagecache so that it's not stale after the write completes.
However, without a locking mechanism to prevent those pages from being re-added to the pagecache - by a buffered read or page fault - page cache inconsistency is still possible.
This isn't necessarily just an issue for userspace when they're playing games; filesystems may hang arbitrary state off the pagecache, and so page cache inconsistency may cause real filesystem bugs, depending on the filesystem. This is less of an issue for iomap based filesystems, but e.g. buffer heads caches disk block mappings (!) and attaches them to the pagecache, and bcachefs attaches disk reservations to pagecache pages.
This issue has been hard to fix, because
- we need to add a lock (henceforth called pagecache_add_lock), which would be held for the duration of the direct IO
- page faults add pages to the page cache, thus need to take the same lock
- dio -> gup -> page fault thus can deadlock
And we cannot enforce a lock ordering with this lock, since userspace will be controlling the lock ordering (via the fd and buffer arguments to direct IOs), so we need a different method of deadlock avoidance.
We need to tell the page fault handler that we're already holding a pagecache_add_lock, and since plumbing it through the entire gup() path would be highly impractical this adds a field to task_struct.
Then the full method is:
- in the dio path, when we first take the pagecache_add_lock, note the mapping in the current task_struct
- in the page fault handler, if faults_disabled_mapping is set, we check if it's the same mapping as the one we're taking a page fault for, and if so return an error.
Then we check lock ordering: if there's a lock ordering violation and trylock fails, we'll have to cycle the locks and return an error that tells the DIO path to retry: faults_disabled_mapping is also used for signalling "locks were dropped, please retry".
Also relevant to this patch: mapping->invalidate_lock. mapping->invalidate_lock provides most of the required semantics - it's used by truncate/fallocate to block pages being added to the pagecache. However, since it's a rwsem, direct IOs would need to take the write side in order to block page cache adds, and would then be exclusive with each other - we'll need a new type of lock to pair with this approach.
Stable-dep-of: e876b75b9020 ("ipvs: fix the checksum validations")
--- include/linux/sched.h | 1 + init/init_task.c | 1 + 2 files changed, 2 insertions(+)
include/linux/sched.h +1 -0
@@ -878,6 +878,7 @@ struct task_struct {struct mm_struct *mm;struct mm_struct *active_mm; +struct address_space *faults_disabled_mapping;int exit_state;int exit_code;
init/init_task.c +1 -0
@@ -85,6 +85,7 @@ struct task_struct init_task .nr_cpus_allowed= NR_CPUS, .mm = NULL, .active_mm = &init_mm, + .faults_disabled_mapping = NULL, .restart_block = { .fn = do_no_restart_syscall, },
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 30/261 ipvs: fix the checksum validations
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Anastasov <[email protected]>
[ Upstream commit e876b75b9020a97bbdc79721e7fc749024891c65 ]
ip_vs_in_icmp_v6() is missing checksum validation for ICMPv6 packets from clients. In fact, as for TCP/UDP we should validate the checksum for ICMP packets only when we mangle the packets on MASQ or on reply for tunnel.
Also, Sashiko points out that handle_response_icmp() being common for IPv4 and IPv6 is missing the pseudo-header calculation while validating ICMPv6 messages from real servers which is a problem if checksum is not validated by the hardware.
Fix the problems by creating ip_vs_checksum_common_check() helper and use it for TCP/UDP/ICMP both for IPv4 and IPv6. Rely on the nf_checksum() for validating the ICMP messages but use it also for TCP and UDP.
Use correct IP offset for IP_VS_DBG_RL_PKT for TCP/UDP/SCTP.
IPVS packets (TCP/UDP/SCTP/ICMP) do not need checksum validation on LOCAL_OUT (local clients or local real servers) and on FORWARD (traffic from servers on LAN). Do it only on LOCAL_IN, in case nf_checksum() is not called on PRE_ROUTING.
Also, ip_vs_checksum_complete() can be marked static.
--- include/net/ip_vs.h | 31 +++++++++++++++-- net/netfilter/ipvs/ip_vs_core.c | 20 +++++++++-- net/netfilter/ipvs/ip_vs_proto_sctp.c | 15 ++++---- net/netfilter/ipvs/ip_vs_proto_tcp.c | 44 +++++------------------ net/netfilter/ipvs/ip_vs_proto_udp.c | 50 ++++++--------------------- 5 files changed, 74 insertions(+), 86 deletions(-)
include/net/ip_vs.h +29 -2
@@ -24,7 +24,9 @@#include <linux/netfilter.h> /* for union nf_inet_addr */ #include <linux/ip.h> #include <linux/ipv6.h> /* for struct ipv6hdr */ +#include <net/route.h> #include <net/ipv6.h> +#include <net/ip6_fib.h> #if IS_ENABLED (CONFIG_NF_CONNTRACK )#include <net/netfilter/nf_conntrack.h> #endif
@@ -1711,8 +1713,6 @@ void ip_vs_nat_icmp_v6(struct sk_buff *skb, struct ip_vs_protocol *pp, struct ip_vs_conn *cp, int dir);#endif -__sum16 ip_vs_checksum_complete (struct sk_buff *skb,int offset); -static inline __wsum ip_vs_check_diff4 (__be32 old,__be32 new,__wsum oldsum) {__be32 diff[2 ] = { ~old, new };
@@ -1738,6 +1738,33 @@ static inline __wsum ip_vs_check_diff2(__be16 old, __be16 new, __wsum oldsum)return csum_partial (diff,sizeof (diff), oldsum); } +static inline bool ip_vs_checksum_needed (struct sk_buff *skb,int af) +{ +/* Checksum unnecessary or already validated? */ +if (skb_csum_unnecessary (skb)) +return false; +/* LOCAL_OUT ? */ +if (!skb->dev || skb->dev->flags &IFF_LOOPBACK ) +return false; +/* !LOCAL_IN (FORWARD) ? */ +if (af ==AF_INET6 ) { +if (!(dst_rt6_info (skb_dst (skb))->rt6i_flags &RTF_LOCAL )) +return false; + }else { +if (!(skb_rtable (skb)->rt_flags &RTCF_LOCAL )) +return false; + } +return true; +} + +static inline bool ip_vs_checksum_common_check (struct sk_buff *skb, +int offset,int proto,int af) +{ +if (!ip_vs_checksum_needed (skb, af)) +return true; +return !nf_checksum (skb,NF_INET_LOCAL_IN , offset, proto, af); +} +/* Forget current conntrack (unconfirmed) and attach notrack entry */ static inline void ip_vs_notrack (struct sk_buff *skb) {
net/netfilter/ipvs/ip_vs_core.c +17 -3
@@ -689,7 +689,7 @@ static int sysctl_nat_icmp_send(struct netns_ipvs *ipvs) { return 0; }#endif -__sum16 ip_vs_checksum_complete (struct sk_buff *skb,int offset) +static __sum16 ip_vs_checksum_complete (struct sk_buff *skb,int offset) {return csum_fold (skb_checksum (skb, offset, skb->len - offset,0 )); }
@@ -860,13 +860,14 @@ static int handle_response_icmp(int af, struct sk_buff *skb, unsigned int offset, unsigned int ihl, unsigned int hooknum) { + int iproto = af == AF_INET6 ? IPPROTO_ICMPV6 : IPPROTO_ICMP;unsigned int verdict =NF_DROP ;if (IP_VS_FWD_METHOD (cp) !=IP_VS_CONN_F_MASQ ) goto after_nat;/* Ensure the checksum is correct */ -if (!skb_csum_unnecessary (skb) &&ip_vs_checksum_complete (skb, ihl)) { +if (!ip_vs_checksum_common_check (skb, ihl, iproto, af)) {/* Failed checksum! */ IP_VS_DBG_BUF (1 ,"Forward ICMP: failed checksum from %s!\n" ,IP_VS_DBG_ADDR (af, snet));
@@ -1716,7 +1717,8 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related, verdict =NF_DROP ;/* Ensure the checksum is correct */ -if (!skb_csum_unnecessary (skb) &&ip_vs_checksum_complete (skb, ihl)) { +if ((IP_VS_FWD_METHOD (cp) ==IP_VS_CONN_F_MASQ || tunnel) && + !ip_vs_checksum_common_check (skb, ihl,IPPROTO_ICMP ,AF_INET )) {/* Failed checksum! */ IP_VS_DBG (1 ,"Incoming ICMP: failed checksum from %pI4!\n" , &iph->saddr);
@@ -1882,6 +1884,18 @@ static int ip_vs_in_icmp_v6(struct netns_ipvs *ipvs, struct sk_buff *skb, goto out; } + verdict =NF_DROP ; + +/* Ensure the checksum is correct */ +if (IP_VS_FWD_METHOD (cp) ==IP_VS_CONN_F_MASQ && + !ip_vs_checksum_common_check (skb, iph->len,IPPROTO_ICMPV6 , +AF_INET6 )) { +/* Failed checksum! */ +IP_VS_DBG (1 ,"Incoming ICMPv6: failed checksum from %pI6c!\n" , + &iph->saddr); + goto out; + } +/* do the statistics and put it back */ ip_vs_in_stats (cp, skb);
net/netfilter/ipvs/ip_vs_proto_sctp.c +9 -6
@@ -11,7 +11,7 @@static int sctp_csum_check (int af,struct sk_buff *skb,struct ip_vs_protocol *pp, -unsigned int sctphoff); +struct ip_vs_iphdr *iph); static int sctp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
@@ -109,7 +109,7 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,int ret;/* Some checks before mangling */ -if (!sctp_csum_check (cp->af, skb, pp, sctphoff)) +if (!sctp_csum_check (cp->af, skb, pp, iph))return 0 ;/* Call application helper if needed */
@@ -157,7 +157,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,int ret;/* Some checks before mangling */ -if (!sctp_csum_check (cp->af, skb, pp, sctphoff)) +if (!sctp_csum_check (cp->af, skb, pp, iph))return 0 ;/* Call application helper if needed */
@@ -187,19 +187,22 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp,static int sctp_csum_check (int af,struct sk_buff *skb,struct ip_vs_protocol *pp, -unsigned int sctphoff) +struct ip_vs_iphdr *iph) { +unsigned int sctphoff = iph->len;struct sctphdr *sh;__le32 cmp, val; +if (!ip_vs_checksum_needed (skb, af)) +return 1 ; sh = (struct sctphdr *)(skb->data + sctphoff); cmp = sh->checksum; val =sctp_compute_cksum (skb, sctphoff);if (val != cmp) {/* CRC failure, dump it. */ -IP_VS_DBG_RL_PKT (0 , af, pp, skb,0 , -"Failed checksum for" ); +IP_VS_DBG_RL_PKT (0 , af, pp, skb, iph->off, +"Failed checksum for" );return 0 ; }return 1 ;
net/netfilter/ipvs/ip_vs_proto_tcp.c +8 -36
70 lines not on this page · raw message
net/netfilter/ipvs/ip_vs_proto_udp.c +11 -39
80 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 31/261 ipvs: fix places with wrong packet offsets
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Anastasov <[email protected]>
[ Upstream commit 15cab31a3730e05f0767b922a7450e5d784b2607 ]
The offsets we use to packet headers and payloads should be based on skb->data. We even already respect non-zero network offset in ip_vs_fill_iph_skb() but some places do it wrongly and support only zero offset which is expected for the IP layer where IPVS has hooks.
Change all places that instead of skb->data use offsets based on the network header (skb_network_header, ip_hdr, etc) because this doubles the network offset as noted by Sashiko.
For ip_vs_nat_icmp_v6() we can even rely on the IPv6 header parsing done by the caller.
--- include/net/ip_vs.h | 15 +-- net/netfilter/ipvs/ip_vs_app.c | 4 +- net/netfilter/ipvs/ip_vs_core.c | 133 +++++++++++++------------- net/netfilter/ipvs/ip_vs_proto_sctp.c | 4 +- net/netfilter/ipvs/ip_vs_proto_tcp.c | 4 +- net/netfilter/ipvs/ip_vs_proto_udp.c | 4 +- net/netfilter/ipvs/ip_vs_xmit.c | 26 ++--- 7 files changed, 97 insertions(+), 93 deletions(-)
include/net/ip_vs.h +9 -6
@@ -1626,8 +1626,9 @@ int ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,int ip_vs_dr_xmit (struct sk_buff *skb,struct ip_vs_conn *cp,struct ip_vs_protocol *pp,struct ip_vs_iphdr *iph);int ip_vs_icmp_xmit (struct sk_buff *skb,struct ip_vs_conn *cp, -struct ip_vs_protocol *pp,int offset, -unsigned int hooknum,struct ip_vs_iphdr *iph); +struct ip_vs_protocol *pp,unsigned int toff, +unsigned int wlen,unsigned int hooknum, +struct ip_vs_iphdr *ciph);void ip_vs_dest_dst_rcu_free (struct rcu_head *head);#ifdef CONFIG_IP_VS_IPV6
@@ -1640,8 +1641,9 @@ int ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,int ip_vs_dr_xmit_v6 (struct sk_buff *skb,struct ip_vs_conn *cp,struct ip_vs_protocol *pp,struct ip_vs_iphdr *iph);int ip_vs_icmp_xmit_v6 (struct sk_buff *skb,struct ip_vs_conn *cp, -struct ip_vs_protocol *pp,int offset, -unsigned int hooknum,struct ip_vs_iphdr *iph); +struct ip_vs_protocol *pp,unsigned int toff, +unsigned int wlen,unsigned int hooknum, +struct ip_vs_iphdr *ciph);#endif #ifdef CONFIG_SYSCTL
@@ -1706,11 +1708,12 @@ static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp) }void ip_vs_nat_icmp (struct sk_buff *skb,struct ip_vs_protocol *pp, -struct ip_vs_conn *cp,int dir); +struct ip_vs_conn *cp,int dir,unsigned int toff);#ifdef CONFIG_IP_VS_IPV6 void ip_vs_nat_icmp_v6 (struct sk_buff *skb,struct ip_vs_protocol *pp, -struct ip_vs_conn *cp,int dir); +struct ip_vs_conn *cp,int dir,unsigned int toff, +struct ip_vs_iphdr *ciph);#endif static inline __wsum ip_vs_check_diff4 (__be32 old,__be32 new,__wsum oldsum)
net/netfilter/ipvs/ip_vs_app.c +2 -2
@@ -368,7 +368,7 @@ static inline int app_tcp_pkt_out(struct ip_vs_conn *cp, struct sk_buff *skb,if (skb_ensure_writable (skb, ipvsh->len +sizeof (*th)))return 0 ; - th = (struct tcphdr *)(skb_network_header (skb) + ipvsh->len); + th = (struct tcphdr *)(skb->data + ipvsh->len);/* * Remember seq number in case this pkt gets resized
@@ -444,7 +444,7 @@ static inline int app_tcp_pkt_in(struct ip_vs_conn *cp, struct sk_buff *skb,if (skb_ensure_writable (skb, ipvsh->len +sizeof (*th)))return 0 ; - th = (struct tcphdr *)(skb_network_header (skb) + ipvsh->len); + th = (struct tcphdr *)(skb->data + ipvsh->len);/* * Remember seq number in case this pkt gets resized
net/netfilter/ipvs/ip_vs_core.c +66 -67
332 lines not on this page · raw message
net/netfilter/ipvs/ip_vs_proto_sctp.c +2 -2
@@ -121,7 +121,7 @@ sctp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, payload_csum = true; } - sctph = (void *)skb_network_header (skb) + sctphoff; + sctph = (void *)skb->data + sctphoff;/* Only update csum if we really have to */ if (sctph->source != cp->vport || payload_csum ||
@@ -169,7 +169,7 @@ sctp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, payload_csum = true; } - sctph = (void *)skb_network_header (skb) + sctphoff; + sctph = (void *)skb->data + sctphoff;/* Only update csum if we really have to */ if (sctph->dest != cp->dport || payload_csum ||
net/netfilter/ipvs/ip_vs_proto_tcp.c +2 -2
@@ -180,7 +180,7 @@ tcp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, payload_csum = true; } - tcph = (void *)skb_network_header (skb) + tcphoff; + tcph = (void *)skb->data + tcphoff; tcph->source = cp->vport;/* Adjust TCP checksums */
@@ -261,7 +261,7 @@ tcp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, payload_csum = true; } - tcph = (void *)skb_network_header (skb) + tcphoff; + tcph = (void *)skb->data + tcphoff; tcph->dest = cp->dport;/*
net/netfilter/ipvs/ip_vs_proto_udp.c +2 -2
@@ -171,7 +171,7 @@ udp_snat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, payload_csum = true; } - udph = (void *)skb_network_header (skb) + udphoff; + udph = (void *)skb->data + udphoff; udph->source = cp->vport;/*
@@ -255,7 +255,7 @@ udp_dnat_handler(struct sk_buff *skb, struct ip_vs_protocol *pp, payload_csum = true; } - udph = (void *)skb_network_header (skb) + udphoff; + udph = (void *)skb->data + udphoff; udph->dest = cp->dport;/*
net/netfilter/ipvs/ip_vs_xmit.c +14 -12
@@ -1473,8 +1473,9 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,*/ int ip_vs_icmp_xmit (struct sk_buff *skb,struct ip_vs_conn *cp, -struct ip_vs_protocol *pp,int offset,unsigned int hooknum, -struct ip_vs_iphdr *iph) +struct ip_vs_protocol *pp,unsigned int toff, +unsigned int wlen,unsigned int hooknum, +struct ip_vs_iphdr *ciph) {struct rtable *rt;/* Route to the other host */ int rc;
@@ -1486,7 +1487,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,translate address/port back */ if (IP_VS_FWD_METHOD (cp) !=IP_VS_CONN_F_MASQ ) {if (cp->packet_xmit) - rc = cp->packet_xmit (skb, cp, pp, iph); + rc = cp->packet_xmit (skb, cp, pp, ciph);else rc =NF_ACCEPT ;/* do not touch skb anymore */
@@ -1504,7 +1505,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,IP_VS_RT_MODE_LOCAL |IP_VS_RT_MODE_NON_LOCAL | IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; local =__ip_vs_get_out_rt (cp->ipvs, cp->af, skb, cp->dest, cp->daddr.ip, rt_mode, -NULL , iph); +NULL , ciph);if (local <0 ) goto tx_error; rt =skb_rtable (skb);
@@ -1536,13 +1537,13 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, }/* copy-on-write the packet before mangling it */ -if (skb_ensure_writable (skb, offset)) +if (skb_ensure_writable (skb, wlen)) goto tx_error;if (skb_cow (skb, rt->dst.dev->hard_header_len)) goto tx_error; -ip_vs_nat_icmp (skb, pp, cp,0 ); +ip_vs_nat_icmp (skb, pp, cp,0 , toff);/* Another hack: avoid icmp_send in ip_fragment */ skb->ignore_df =1 ;
@@ -1558,8 +1559,9 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,#ifdef CONFIG_IP_VS_IPV6 int ip_vs_icmp_xmit_v6 (struct sk_buff *skb,struct ip_vs_conn *cp, -struct ip_vs_protocol *pp,int offset,unsigned int hooknum, -struct ip_vs_iphdr *ipvsh) +struct ip_vs_protocol *pp,unsigned int toff, +unsigned int wlen,unsigned int hooknum, +struct ip_vs_iphdr *ciph) {struct rt6_info *rt;/* Route to the other host */ int rc;
@@ -1571,7 +1573,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,translate address/port back */ if (IP_VS_FWD_METHOD (cp) !=IP_VS_CONN_F_MASQ ) {if (cp->packet_xmit) - rc = cp->packet_xmit (skb, cp, pp, ipvsh); + rc = cp->packet_xmit (skb, cp, pp, ciph);else rc =NF_ACCEPT ;/* do not touch skb anymore */
@@ -1588,7 +1590,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,IP_VS_RT_MODE_LOCAL |IP_VS_RT_MODE_NON_LOCAL | IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; local =__ip_vs_get_out_rt_v6 (cp->ipvs, cp->af, skb, cp->dest, - &cp->daddr.in6,NULL , ipvsh,0 , rt_mode); + &cp->daddr.in6,NULL , ciph,0 , rt_mode);if (local <0 ) goto tx_error; rt =dst_rt6_info (skb_dst (skb));
@@ -1620,13 +1622,13 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, }/* copy-on-write the packet before mangling it */ -if (skb_ensure_writable (skb, offset)) +if (skb_ensure_writable (skb, wlen)) goto tx_error;if (skb_cow (skb, rt->dst.dev->hard_header_len)) goto tx_error; -ip_vs_nat_icmp_v6 (skb, pp, cp,0 ); +ip_vs_nat_icmp_v6 (skb, pp, cp,0 , toff, ciph);/* Another hack: avoid icmp_send in ip_fragment */ skb->ignore_df =1 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 32/261 ipvs: do not mangle ICMP replies for non-first fragments
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Anastasov <[email protected]>
[ Upstream commit 342e24a339b90e8e339a0f8c151ca479b8565661 ]
Sashiko warns that ip_vs_nat_icmp() unconditionally mangles the payload for embedded non-first IPv4 fragments. The problem is in the very old inverted pp->dont_defrag check which should not continue when embedded is a non-first TCP/UDP/SCTP fragment.
Check for embedded non-first fragment is also missing from ip_vs_out_icmp_v6(), it is needed before any connection lookups that expect ports after the network headers.
Drop the blocking code from ip_vs_in_icmp_v6() which prevents ICMPv6 from local clients to use non-MASQ forwarding.
--- include/net/ip_vs.h | 11 +++--- net/netfilter/ipvs/ip_vs_core.c | 61 ++++++++++++--------------------- net/netfilter/ipvs/ip_vs_xmit.c | 28 +++++++++++---- 3 files changed, 48 insertions(+), 52 deletions(-)
include/net/ip_vs.h +5 -6
@@ -1627,8 +1627,7 @@ int ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);int ip_vs_icmp_xmit (struct sk_buff *skb,struct ip_vs_conn *cp,struct ip_vs_protocol *pp,unsigned int toff, -unsigned int wlen,unsigned int hooknum, -struct ip_vs_iphdr *ciph); +unsigned int hooknum,struct ip_vs_iphdr *ciph);void ip_vs_dest_dst_rcu_free (struct rcu_head *head);#ifdef CONFIG_IP_VS_IPV6
@@ -1642,8 +1641,7 @@ int ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, struct ip_vs_protocol *pp, struct ip_vs_iphdr *iph);int ip_vs_icmp_xmit_v6 (struct sk_buff *skb,struct ip_vs_conn *cp,struct ip_vs_protocol *pp,unsigned int toff, -unsigned int wlen,unsigned int hooknum, -struct ip_vs_iphdr *ciph); +unsigned int hooknum,struct ip_vs_iphdr *ciph);#endif #ifdef CONFIG_SYSCTL
@@ -1708,12 +1706,13 @@ static inline char ip_vs_fwd_tag(struct ip_vs_conn *cp) }void ip_vs_nat_icmp (struct sk_buff *skb,struct ip_vs_protocol *pp, -struct ip_vs_conn *cp,int dir,unsigned int toff); +struct ip_vs_conn *cp,int dir,unsigned int toff, +bool has_ports);#ifdef CONFIG_IP_VS_IPV6 void ip_vs_nat_icmp_v6 (struct sk_buff *skb,struct ip_vs_protocol *pp,struct ip_vs_conn *cp,int dir,unsigned int toff, -struct ip_vs_iphdr *ciph); +bool has_ports,struct ip_vs_iphdr *ciph);#endif static inline __wsum ip_vs_check_diff4 (__be32 old,__be32 new,__wsum oldsum)
net/netfilter/ipvs/ip_vs_core.c +21 -40
161 lines not on this page · raw message
net/netfilter/ipvs/ip_vs_xmit.c +22 -6
@@ -1474,13 +1474,14 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,int ip_vs_icmp_xmit (struct sk_buff *skb,struct ip_vs_conn *cp,struct ip_vs_protocol *pp,unsigned int toff, -unsigned int wlen,unsigned int hooknum, -struct ip_vs_iphdr *ciph) +unsigned int hooknum,struct ip_vs_iphdr *ciph) {struct rtable *rt;/* Route to the other host */ int rc;int local;int rt_mode, was_input; +bool has_ports = false; +unsigned int wlen;/* The ICMP packet for VS/TUN, VS/DR and LOCALNODE will be forwarded directly here, because there is no need to
@@ -1536,6 +1537,13 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, goto tx_error; } + wlen = ciph->len; +if (ciph->protocol ==IPPROTO_TCP || ciph->protocol ==IPPROTO_UDP || + ciph->protocol ==IPPROTO_SCTP ) { + wlen +=2 *sizeof (__u16);/* Also mangle ports */ + has_ports = true; + } +/* copy-on-write the packet before mangling it */ if (skb_ensure_writable (skb, wlen)) goto tx_error;
@@ -1543,7 +1551,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,if (skb_cow (skb, rt->dst.dev->hard_header_len)) goto tx_error; -ip_vs_nat_icmp (skb, pp, cp,0 , toff); +ip_vs_nat_icmp (skb, pp, cp,0 , toff, has_ports);/* Another hack: avoid icmp_send in ip_fragment */ skb->ignore_df =1 ;
@@ -1560,10 +1568,11 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,int ip_vs_icmp_xmit_v6 (struct sk_buff *skb,struct ip_vs_conn *cp,struct ip_vs_protocol *pp,unsigned int toff, -unsigned int wlen,unsigned int hooknum, -struct ip_vs_iphdr *ciph) +unsigned int hooknum,struct ip_vs_iphdr *ciph) { +bool has_ports = false;struct rt6_info *rt;/* Route to the other host */ +unsigned int wlen;int rc;int local;int rt_mode;
@@ -1621,6 +1630,13 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, goto tx_error; } + wlen = ciph->len; +if (ciph->protocol ==IPPROTO_TCP || ciph->protocol ==IPPROTO_UDP || + ciph->protocol ==IPPROTO_SCTP ) { + wlen +=2 *sizeof (__u16);/* Also mangle ports */ + has_ports = true; + } +/* copy-on-write the packet before mangling it */ if (skb_ensure_writable (skb, wlen)) goto tx_error;
@@ -1628,7 +1644,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,if (skb_cow (skb, rt->dst.dev->hard_header_len)) goto tx_error; -ip_vs_nat_icmp_v6 (skb, pp, cp,0 , toff, ciph); +ip_vs_nat_icmp_v6 (skb, pp, cp,0 , toff, has_ports, ciph);/* Another hack: avoid icmp_send in ip_fragment */ skb->ignore_df =1 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 33/261 netfilter: nft_payload: fix mask build for partial field offload
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei (Microsoft) <[email protected]>
[ Upstream commit 39e88f28fb32bf02bd4b525c24c842c9cff5663d ]
nft_payload_offload_mask() builds the offload match mask for a payload expression that covers only part of a header field. For a partial IPv6 address match (field_len = 16, priv_len = 1) that shift is 1 << 120, which is undefined on the 32-bit int operand. It also trims only one word, so the remaining words stay 0xffffffff (and when priv_len is a multiple of 4 the trim is skipped entirely), leaving the mask covering more bytes than the rule matches.
UBSAN: shift-out-of-bounds in net/netfilter/nft_payload.c:278:20 shift exponent 120 is too large for 32-bit type 'int' ...
The match is byte-granular and struct nft_data is zero-initialised, so the correct mask is simply the first priv_len bytes set to 0xff. Set those bytes directly and drop the word/shift trimming; this removes the undefined shift and no longer over-masks the trailing bytes.
--- net/netfilter/nft_payload.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-)
net/netfilter/nft_payload.c +1 -11
@@ -253,9 +253,7 @@ static int nft_payload_dump(struct sk_buff *skb,static bool nft_payload_offload_mask (struct nft_offload_reg *reg,u32 priv_len,u32 field_len) { -unsigned int remainder, delta, k;struct nft_data mask = {}; -__be32 remainder_mask;if (priv_len == field_len) {memset (®->mask,0xff , priv_len);
@@ -264,15 +262,7 @@ static bool nft_payload_offload_mask(struct nft_offload_reg *reg,return false; } -memset (&mask,0xff , field_len); - remainder = priv_len %sizeof (u32); -if (remainder) { - k = priv_len /sizeof (u32); - delta = field_len - priv_len; - remainder_mask =htonl (~((1 << (delta *BITS_PER_BYTE )) -1 )); - mask.data[k] = (__force u32 )remainder_mask; - } - +memset (&mask,0xff , priv_len);memcpy (®->mask, &mask, field_len);return true;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 34/261 rds: Fix inet6_addr_lst NULL dereference when IPv6 is disabled
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ilia Gavrilov <[email protected]>
[ Upstream commit 9c805e592a29be9e4e61ff1bd567da04aa8fd6f9 ]
When booting with the 'ipv6.disable=1' parameter, inet6_addr_lst is never initialized because inet6_init() exits before addrconf_init() is called to initialize it. An attempt to bind an RDS socket to an ipv6 address results in a crash in __ipv6_chk_addr_and_flags()
KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] RIP: 0010:__ipv6_chk_addr_and_flags+0x1df/0x7e0 Call Trace: <TASK> ipv6_chk_addr+0x3b/0x50 rds_tcp_laddr_check+0x155/0x3b0 [rds_tcp] rds_trans_get_preferred+0x15d/0x2d0 [rds] ? trace_hardirqs_on+0x2d/0x110 rds_bind+0x1433/0x1d60 [rds] ? rds_remove_bound+0xd50/0xd50 [rds] ? aa_af_perm+0x250/0x250 ? __might_fault+0xde/0x190 ? __sys_bind+0x1dc/0x210 __sys_bind+0x1dc/0x210 ? __ia32_sys_socketpair+0x100/0x100 ? restore_fpregs_from_fpstate+0x53/0x100 __x64_sys_bind+0x73/0xb0 ? syscall_enter_from_user_mode+0x1c/0x50 do_syscall_64+0x34/0x80 entry_SYSCALL_64_after_hwframe+0x6e/0xd8 RIP: 0033:0x7f47f8269ea9 </TASK>
The following code reproduces the issue:
struct sockaddr_in6 addr;
s = socket(PF_RDS, SOCK_SEQPACKET, 0);
memset(&addr, 0, sizeof(addr));inet_pton(AF_INET6, ADDRESS, &addr.sin6_addr);
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(PORT);
bind(s, &addr, sizeof(addr));
Found by InfoTeCS on behalf of Linux Verification Center (linuxtesting.org) with Syzkaller.
Stable-dep-of: 78f75d632f74 ("rds: tcp: hold the RCU lock across ipv6_chk_addr() in rds_tcp_laddr_check()")
--- net/rds/ib.c | 4 ++++ net/rds/ib_cm.c | 4 ++++ net/rds/tcp.c | 8 +++++--- 3 files changed, 13 insertions(+), 3 deletions(-)
net/rds/ib.c +4 -0
@@ -431,6 +431,10 @@ static int rds_ib_laddr_check_cm(struct net *net, const struct in6_addr *addr, sa = (struct sockaddr *)&sin; }else {#if IS_ENABLED (CONFIG_IPV6 ) +if (!ipv6_mod_enabled ()) { + ret = -EADDRNOTAVAIL ; + goto out; + }memset (&sin6,0 ,sizeof (sin6)); sin6.sin6_family =AF_INET6 ; sin6.sin6_addr = *addr;
net/rds/ib_cm.c +4 -0
@@ -810,6 +810,10 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id, dp = event->param.conn.private_data;if (isv6) {#if IS_ENABLED (CONFIG_IPV6 ) +if (!ipv6_mod_enabled ()) { + err = -EOPNOTSUPP ; + goto out; + } dp_cmn = &dp->ricp_v6.dp_cmn; saddr6 = &dp->ricp_v6.dp_saddr; daddr6 = &dp->ricp_v6.dp_daddr;
net/rds/tcp.c +5 -3
@@ -341,9 +341,11 @@ int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr,rcu_read_unlock (); }#if IS_ENABLED (CONFIG_IPV6 ) - ret =ipv6_chk_addr (net, addr, dev,0 ); -if (ret) -return 0 ; +if (ipv6_mod_enabled ()) { + ret =ipv6_chk_addr (net, addr, dev,0 ); +if (ret) +return 0 ; + }#endif return -EADDRNOTAVAIL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 35/261 rds: tcp: hold the RCU lock across ipv6_chk_addr() in rds_tcp_laddr_check()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
[ Upstream commit 78f75d632f74b8de0f081a128588f7c37d0d1164 ]
rds_tcp_laddr_check() looks up a scoped IPv6 interface with dev_get_by_index_rcu(), drops the RCU read-side lock, and only then passes the bare struct net_device * into ipv6_chk_addr().
dev_get_by_index_rcu() only keeps the device alive within the same RCU read-side section. After rcu_read_unlock(), a concurrent RTM_DELLINK can free the net_device; ipv6_chk_addr() then dereferences the stale pointer in __ipv6_chk_addr_and_flags() (e.g. l3mdev_master_dev_rcu(dev)), reading freed memory.
Keep the RCU read-side lock held across the ipv6_chk_addr() call instead of dropping it right after the lookup, so the device cannot be freed while it is in use.
BUG: KASAN: slab-use-after-free in __ipv6_chk_addr_and_flags (... net/ipv6/addrconf.c:1998) Read of size 8 at addr ffff8880106ec000 by task exploit/153 Call Trace: ... kasan_report (mm/kasan/report.c:595) __ipv6_chk_addr_and_flags (... net/ipv6/addrconf.c:1998) ipv6_chk_addr (net/ipv6/addrconf.c:2031 net/ipv6/addrconf.c:1972) rds_tcp_laddr_check (net/rds/tcp.c:370) rds_bind (net/rds/bind.c:248) __sys_bind (net/socket.c:1920) __x64_sys_bind (net/socket.c:1956) do_syscall_64 (arch/x86/entry/syscall_64.c:63) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
--- net/rds/tcp.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
net/rds/tcp.c +5 -3
@@ -330,23 +330,25 @@ int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr,/* If the scope_id is specified, check only those addresses * hosted on the specified interface. */ +rcu_read_lock ();if (scope_id !=0 ) { -rcu_read_lock (); dev =dev_get_by_index_rcu (net, scope_id);/* scope_id is not valid... */ if (!dev) {rcu_read_unlock ();return -EADDRNOTAVAIL ; } -rcu_read_unlock (); }#if IS_ENABLED (CONFIG_IPV6 )if (ipv6_mod_enabled ()) { ret =ipv6_chk_addr (net, addr, dev,0 ); -if (ret) +if (ret) { +rcu_read_unlock ();return 0 ; + } }#endif +rcu_read_unlock ();return -EADDRNOTAVAIL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 36/261 pinctrl-amd: Dont clear S4 wake bits at probe
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
[ Upstream commit ffe8a0c6b55285ceaf2f42fc20c3a0594d14f1e9 ]
commit 6bc3462a0f5e ("pinctrl: amd: Mask wake bits on probe again") introduced a regression where Wake-on-LAN no longer works after suspend or shutdown on some AMD platforms.
Firmware-programmed S4 wake bits for devices like PCIe NICs using PCI PME are cleared at probe, but nothing restores them. Unlike S0i3/S3 wake sources that use enable_irq_wake() -> amd_gpio_irq_set_wake(), PCIe PME does not use GPIO IRQ infrastructure and relies on firmware configuration.
The original intent of commit 6bc3462a0f5e ("pinctrl: amd: Mask wake bits on probe again") was to clear spurious wake bits left by firmware to prevent unwanted wakeups. However, S4 wake bits are used for hardware-level wake sources like WoL that bypass the kernel's IRQ wake API.
Fix by preserving S4 wake bits at probe and only clearing S0i3/S3 bits:
- Firmware-configured S4 wake sources (WoL) continue working
- Kernel maintains control of S3/S0i3 wake policy via set_wake()
- S3-only wake sources work correctly per commit f31f33dbb3ba ("pinctrl:
amd: Take suspend type into consideration which pins are non-wake")
The trade-off is that firmware-programmed spurious S4 wake bits remain set, but this is less problematic than breaking WoL.
--- drivers/pinctrl/pinctrl-amd.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/pinctrl/pinctrl-amd.c +1 -2
@@ -869,8 +869,7 @@ static void amd_gpio_irq_init(struct amd_gpio *gpio_dev)u32 pin_reg, mask;int i; - mask =BIT (WAKE_CNTRL_OFF_S0I3 ) |BIT (WAKE_CNTRL_OFF_S3 ) | -BIT (WAKE_CNTRL_OFF_S4 ); + mask =BIT (WAKE_CNTRL_OFF_S0I3 ) |BIT (WAKE_CNTRL_OFF_S3 );for (i =0 ; i < desc->npins; i++) {int pin = desc->pins[i].number;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 37/261 scsi: libiscsi: Fix stale-data leak into the SCSI sense buffer
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: HyeongJun An <[email protected]>
[ Upstream commit 98b87885de4b7f605533a2860685f5689fce8e82 ]
iscsi_scsi_cmd_rsp() copies the sense data of a SCSI Response from the target-supplied data segment. The segment carries a 2-byte sense length followed by the sense bytes, so it must hold 2 + senselen bytes, but the bounds check only requires datalen >= senselen:
senselen = get_unaligned_be16(data); if (datalen < senselen) goto invalid_datalen; memcpy(sc->sense_buffer, data + 2, min_t(uint16_t, senselen, SCSI_SENSE_BUFFERSIZE));
A target that returns a SCSI Response whose datalen equals senselen (with senselen <= SCSI_SENSE_BUFFERSIZE) makes the memcpy() from data + 2 read up to two bytes past the received data. Those bytes are stale conn->data contents and end up in the command's sense buffer, which is returned to userspace.
Account for the 2-byte sense length prefix in the check.
--- drivers/scsi/libiscsi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/libiscsi.c +1 -1
@@ -918,7 +918,7 @@ static void iscsi_scsi_cmd_rsp(struct iscsi_conn *conn, struct iscsi_hdr *hdr, } senselen =get_unaligned_be16 (data); -if (datalen < senselen) +if (datalen < senselen +2 ) goto invalid_datalen; memcpy(sc->sense_buffer, data + 2,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 38/261 scsi: libiscsi_tcp: Bound SCSI Response data segment to the connection buffer
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: HyeongJun An <[email protected]>
[ Upstream commit c1dea15f819cded9b3faf58f8bec72323568b6e6 ]
iscsi_tcp_hdr_dissect() receives the data segment of several PDU types into the fixed-size conn->data buffer, which is allocated for ISCSI_DEF_MAX_RECV_SEG_LEN (8192) bytes. For the LOGIN_RSP, TEXT_RSP, REJECT and ASYNC_EVENT opcodes the dissect path already rejects a PDU whose DataSegmentLength exceeds that buffer.
The SCSI Command Response (ISCSI_OP_SCSI_CMD_RSP) path also copies its data segment (sense/response data) into conn->data via iscsi_tcp_data_recv_prep(), but it does so without the same check. The only upstream bound on in.datalen is conn->max_recv_dlength, the initiator's advertised MaxRecvDataSegmentLength, which is commonly negotiated well above 8192 (open-iscsi defaults to 262144). A target that returns a SCSI Response with a DataSegmentLength between 8193 and max_recv_dlength therefore overflows the 8192-byte conn->data buffer.
Once the same bound applies, ISCSI_OP_SCSI_CMD_RSP is handled exactly like those responses: bound the data segment, receive it into conn->data when present, and otherwise complete the PDU with no data. Fold the opcode into that case group rather than duplicating the check.
--- drivers/scsi/libiscsi_tcp.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
drivers/scsi/libiscsi_tcp.c +1 -7
@@ -763,13 +763,6 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) rc =__iscsi_complete_pdu (conn, hdr,NULL ,0 );spin_unlock (&conn->session->back_lock);break ; -case ISCSI_OP_SCSI_CMD_RSP : -if (tcp_conn->in.datalen) { -iscsi_tcp_data_recv_prep (tcp_conn); -return 0 ; - } - rc =iscsi_complete_pdu (conn, hdr,NULL ,0 ); -break ;case ISCSI_OP_R2T :if (ahslen) { rc =ISCSI_ERR_AHSLEN ;
@@ -777,6 +770,7 @@ iscsi_tcp_hdr_dissect(struct iscsi_conn *conn, struct iscsi_hdr *hdr) } rc =iscsi_tcp_r2t_rsp (conn, hdr);break ; +case ISCSI_OP_SCSI_CMD_RSP :case ISCSI_OP_LOGIN_RSP :case ISCSI_OP_TEXT_RSP :case ISCSI_OP_REJECT :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 39/261 scsi: libsas: Fix HA resume deadlock and hisi_sas disk-wake race
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xingui Yang <[email protected]>
[ Upstream commit 3dbbbf656b850c9c8de05df6ad4a1dfc6ff02845 ]
Commit fbefe22811c3 ("scsi: libsas: Don't always drain event workqueue for HA resume") introduced sas_resume_ha_no_sync() to avoid a deadlock:
the PHYE_RESUME_TIMEOUT handler, running on the HA event workqueue, calls sas_deform_port() -> sas_destruct_devices(), which removes SCSI devices and waits for the host to become runtime-active. But the host cannot resume until sas_resume_ha() -> sas_drain_work() returns, and the drain is blocked on that very handler.
However skipping the drain reintroduces a race: hisi_sas returns from resume before all PHY UP work and libsas discovery work finish. The controller may then autosuspend while disks are still waking up. The disks issue IO to a suspended controller, the IO fails, and the disks get disabled.
Fix the deadlock at its source by moving the PHYE_RESUME_TIMEOUT notification to after sas_drain_work(). By then the host resume is about to complete, so device removal through device_link no longer blocks on the resume and the cycle is broken.
With the deadlock gone, restore sas_resume_ha() (the draining variant) in hisi_sas and remove sas_resume_ha_no_sync().
The reorder is safe for the other libsas consumers (isci, pm8001, aic94xx, mvsas). During suspend, sas_suspend_devices() calls sas_notify_lldd_dev_gone() for each device, which sets dev->lldd_dev to NULL. When scsi_unblock_requests re-enables I/O in resume, any I/O to a timed-out phy's disk is immediately rejected by the LLDD before reaching
hardware: isci returns SAS_DEVICE_UNKNOWN (mapped to DID_BAD_TARGET), and pm8001 returns SAS_PHY_DOWN (mapped to DID_NO_CONNECT). Both complete directly via scsi_done() without entering SCSI EH. This is identical in both the old and new ordering since lldd_dev_gone runs during suspend, before resume. The reorder only affects when the PHYE_RESUME_TIMEOUT handler runs (synchronized by sas_drain_work() vs. asynchronous after resume returns), not whether I/O can reach the device. aic94xx and mvsas do not register any PM ops and never reach this code path.
--- drivers/scsi/hisi_sas/hisi_sas_v3_hw.c | 10 +------ drivers/scsi/libsas/sas_init.c | 37 +++++++++++++------------- include/scsi/libsas.h | 1 - 3 files changed, 19 insertions(+), 29 deletions(-)
drivers/scsi/hisi_sas/hisi_sas_v3_hw.c +1 -9
@@ -5345,15 +5345,7 @@ static int _resume_v3_hw(struct device *device)return rc; }phys_init_v3_hw (hisi_hba); - -/* -* If a directly-attached disk is removed during suspend, a deadlock -* may occur, as the PHYE_RESUME_TIMEOUT processing will require the -* hisi_hba->device to be active, which can only happen when resume -* completes. So don't wait for the HA event workqueue to drain upon -* resume. -*/ -sas_resume_ha_no_sync (sha); +sas_resume_ha (sha);clear_bit (HISI_SAS_RESETTING_BIT , &hisi_hba->flags);dev_warn (dev,"end of resuming controller\n" );
drivers/scsi/libsas/sas_init.c +18 -19
@@ -409,7 +409,7 @@ static void sas_resume_insert_broadcast_ha(struct sas_ha_struct *ha) } } -static void _sas_resume_ha (struct sas_ha_struct *ha,bool drain) +void sas_resume_ha (struct sas_ha_struct *ha) {const unsigned long tmo =msecs_to_jiffies (25000 );int i;
@@ -425,6 +425,23 @@ static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain)dev_info (ha->dev,"waiting up to 25 seconds for %d phy%s to resume\n" , i, i >1 ?"s" :"" );wait_event_timeout (ha->eh_wait_q,phys_suspended (ha) ==0 , tmo); + +/* +* All phys are back up or timed out. Turn on I/O and drain +* pending work. +*/ +scsi_unblock_requests (ha->shost); +sas_drain_work (ha); + +/* +* Send PHYE_RESUME_TIMEOUT after sas_drain_work(). The handler +* calls sas_deform_port() -> sas_destruct_devices(), which removes +* SCSI devices and, for LLDDs using device_link() PM sync, waits +* for the host to be runtime-active. Sending it before the drain +* would deadlock: the drain waits for the handler, the handler +* waits for host resume, and host resume waits for the drain to +* finish. +*/ for (i =0 ; i < ha->num_phys; i++) {struct asd_sas_phy *phy = ha->sas_phy[i];
@@ -435,12 +452,6 @@ static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain) } } -/* all phys are back up or timed out, turn on i/o so we can -* flush out disks that did not return -*/ -scsi_unblock_requests (ha->shost); -if (drain) -sas_drain_work (ha);clear_bit (SAS_HA_RESUMING , &ha->state);sas_queue_deferred_work (ha);
@@ -449,20 +460,8 @@ static void _sas_resume_ha(struct sas_ha_struct *ha, bool drain)*/ sas_resume_insert_broadcast_ha (ha); } - -void sas_resume_ha (struct sas_ha_struct *ha) -{ -_sas_resume_ha (ha, true); -}EXPORT_SYMBOL (sas_resume_ha); -/* A no-sync variant, which does not call sas_drain_ha(). */ -void sas_resume_ha_no_sync (struct sas_ha_struct *ha) -{ -_sas_resume_ha (ha, false); -} -EXPORT_SYMBOL (sas_resume_ha_no_sync); -void sas_suspend_ha (struct sas_ha_struct *ha) {int i;
include/scsi/libsas.h +0 -1
@@ -678,7 +678,6 @@ extern int sas_register_ha(struct sas_ha_struct *);extern int sas_unregister_ha (struct sas_ha_struct *);extern void sas_prep_resume_ha (struct sas_ha_struct *sas_ha);extern void sas_resume_ha (struct sas_ha_struct *sas_ha); -extern void sas_resume_ha_no_sync (struct sas_ha_struct *sas_ha);extern void sas_suspend_ha (struct sas_ha_struct *sas_ha);int sas_set_phy_speed (struct sas_phy *phy,struct sas_phy_linkrates *rates);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 40/261 smb: client: fix buffer leaks in SMB1 read and write
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dawei Feng <[email protected]>
[ Upstream commit 6a3e16d60e81a4aa3056ab15617036cfbea2e07d ]
CIFSSMBRead(), CIFSSMBWrite() and CIFSSMBWrite2() allocate a request buffer before checking whether tcon->ses->server is NULL. If that defensive check ever fails, the helper returns -ECONNABORTED without releasing the request buffer.
Fix these leaks by releasing the allocated request buffer before returning from these error paths. Use cifs_small_buf_release() for the buffers allocated by small_smb_init() and cifs_buf_release() for the buffer allocated by smb_init().
The bug was first flagged by an experimental analysis tool we are developing for kernel memory-management bugs while analyzing v6.13-rc1. The tool is still under development and is not yet publicly available. Manual inspection confirms that the bug is still present in v7.1.1.
An x86_64 allyesconfig build showed no new warnings.
Runtime validation used a temporary fault-injection hook to force tcon->ses->server to NULL after request-buffer initialization. On the unfixed kernel, the harness observed two leaked small request buffers and one leaked large request buffer, with directed kmemleak dumps confirming the CIFS buffer allocation stacks. After the fix, no CIFS request-buffer deltas remained.
--- fs/smb/client/cifssmb.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
fs/smb/client/cifssmb.c +9 -3
@@ -1416,8 +1416,10 @@ CIFSSMBRead(const unsigned int xid, struct cifs_io_parms *io_parms, pSMB->hdr.PidHigh =cpu_to_le16 ((__u16)(pid >>16 ));/* tcon and ses pointer are checked in smb_init */ -if (tcon->ses->server ==NULL ) +if (!tcon->ses->server) { +cifs_small_buf_release (pSMB);return -ECONNABORTED ; + } pSMB->AndXCommand =0xFF ;/* none */ pSMB->Fid = netfid;
@@ -1529,8 +1531,10 @@ CIFSSMBWrite(const unsigned int xid, struct cifs_io_parms *io_parms, pSMB->hdr.PidHigh =cpu_to_le16 ((__u16)(pid >>16 ));/* tcon and ses pointer are checked in smb_init */ -if (tcon->ses->server ==NULL ) +if (!tcon->ses->server) { +cifs_buf_release (pSMB);return -ECONNABORTED ; + } pSMB->AndXCommand =0xFF ;/* none */ pSMB->Fid = netfid;
@@ -1780,8 +1784,10 @@ CIFSSMBWrite2(const unsigned int xid, struct cifs_io_parms *io_parms, pSMB->hdr.PidHigh =cpu_to_le16 ((__u16)(pid >>16 ));/* tcon and ses pointer are checked in smb_init */ -if (tcon->ses->server ==NULL ) +if (!tcon->ses->server) { +cifs_small_buf_release (pSMB);return -ECONNABORTED ; + } pSMB->AndXCommand =0xFF ;/* none */ pSMB->Fid = netfid;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 41/261 spi: spi-cadence: supports transmission with bits_per_word of 16 and 32
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jun Guo <[email protected]>
[ Upstream commit 4e00135b2dd1d7924a58bffa551b6ceb3bd836f2 ]
The default FIFO data width of the Cadence SPI IP is 8 bits, but the hardware supports configurations of 16 bits and 32 bits. This patch enhances the driver to support communication with both 16-bits and 32-bits FIFO data widths.
Stable-dep-of: d9eadfce2fac ("spi: spi-cadence: Move TX FIFO full busy-wait into FIFO")
--- drivers/spi/spi-cadence.c | 106 +++++++++++++++++++++++++++++++++----- 1 file changed, 93 insertions(+), 13 deletions(-)
drivers/spi/spi-cadence.c +93 -13
@@ -108,6 +108,7 @@* @rxbuf: Pointer to the RX buffer * @tx_bytes: Number of bytes left to transfer * @rx_bytes: Number of bytes requested +* @n_bytes: Number of bytes per word * @dev_busy: Device busy flag * @is_decoded_cs: Flag for decoder property set or not * @tx_fifo_depth: Depth of the TX FIFO
@@ -118,15 +119,23 @@ struct cdns_spi {struct clk *pclk;unsigned int clk_rate;u32 speed_hz; -const u8 *txbuf; -u8 *rxbuf; +const void *txbuf; +void *rxbuf;int tx_bytes;int rx_bytes; +u8 n_bytes;u8 dev_busy;u32 is_decoded_cs;unsigned int tx_fifo_depth; }; +enum cdns_spi_frame_n_bytes { +CDNS_SPI_N_BYTES_NULL =0 , +CDNS_SPI_N_BYTES_U8 =1 , +CDNS_SPI_N_BYTES_U16 =2 , +CDNS_SPI_N_BYTES_U32 =4 +}; +/* Macros for the SPI controller read/write */ static inline u32 cdns_spi_read (struct cdns_spi *xspi,u32 offset) {
@@ -302,6 +311,78 @@ static int cdns_spi_setup_transfer(struct spi_device *spi,return 0 ; } +static u8 cdns_spi_n_bytes (struct spi_transfer *transfer) +{ +if (transfer->bits_per_word <=8 ) +return CDNS_SPI_N_BYTES_U8 ; +else if (transfer->bits_per_word <=16 ) +return CDNS_SPI_N_BYTES_U16 ; +else +return CDNS_SPI_N_BYTES_U32 ; +} + +static inline void cdns_spi_reader (struct cdns_spi *xspi) +{ +u32 rxw =0 ; + +if (xspi->rxbuf && !IS_ALIGNED ((uintptr_t )xspi->rxbuf, xspi->n_bytes)) { +pr_err ("%s: rxbuf address is not aligned for %d bytes\n" , + __func__, xspi->n_bytes); +return ; + } + + rxw =cdns_spi_read (xspi,CDNS_SPI_RXD ); +if (xspi->rxbuf) { +switch (xspi->n_bytes) { +case CDNS_SPI_N_BYTES_U8 : + *(u8 *)xspi->rxbuf = rxw; +break ; +case CDNS_SPI_N_BYTES_U16 : + *(u16 *)xspi->rxbuf = rxw; +break ; +case CDNS_SPI_N_BYTES_U32 : + *(u32 *)xspi->rxbuf = rxw; +break ; +default : +pr_err ("%s invalid n_bytes %d\n" , __func__, + xspi->n_bytes); +return ; + } + xspi->rxbuf = (u8 *)xspi->rxbuf + xspi->n_bytes; + } +} + +static inline void cdns_spi_writer (struct cdns_spi *xspi) +{ +u32 txw =0 ; + +if (xspi->txbuf && !IS_ALIGNED ((uintptr_t )xspi->txbuf, xspi->n_bytes)) { +pr_err ("%s: txbuf address is not aligned for %d bytes\n" , + __func__, xspi->n_bytes); +return ; + } + +if (xspi->txbuf) { +switch (xspi->n_bytes) { +case CDNS_SPI_N_BYTES_U8 : + txw = *(u8 *)xspi->txbuf; +break ; +case CDNS_SPI_N_BYTES_U16 : + txw = *(u16 *)xspi->txbuf; +break ; +case CDNS_SPI_N_BYTES_U32 : + txw = *(u32 *)xspi->txbuf; +break ; +default : +pr_err ("%s invalid n_bytes %d\n" , __func__, + xspi->n_bytes); +return ; + } +cdns_spi_write (xspi,CDNS_SPI_TXD , txw); + xspi->txbuf = (u8 *)xspi->txbuf + xspi->n_bytes; + } +} +/** * cdns_spi_process_fifo - Fills the TX FIFO, and drain the RX FIFO * @xspi: Pointer to the cdns_spi structure
@@ -318,23 +399,14 @@ static void cdns_spi_process_fifo(struct cdns_spi *xspi, int ntx, int nrx)while (ntx || nrx) {if (nrx) { -u8 data =cdns_spi_read (xspi,CDNS_SPI_RXD ); - -if (xspi->rxbuf) - *xspi->rxbuf++ = data; - +cdns_spi_reader (xspi); nrx--; }if (ntx) { -if (xspi->txbuf) -cdns_spi_write (xspi,CDNS_SPI_TXD , *xspi->txbuf++); -else -cdns_spi_write (xspi,CDNS_SPI_TXD ,0 ); - +cdns_spi_writer (xspi); ntx--; } - } }
@@ -451,6 +523,10 @@ static int cdns_transfer_one(struct spi_controller *ctlr,if (cdns_spi_read (xspi,CDNS_SPI_ISR ) &CDNS_SPI_IXR_TXFULL )udelay (10 ); + xspi->n_bytes =cdns_spi_n_bytes (transfer); + xspi->tx_bytes =DIV_ROUND_UP (xspi->tx_bytes, xspi->n_bytes); + xspi->rx_bytes =DIV_ROUND_UP (xspi->rx_bytes, xspi->n_bytes); +cdns_spi_process_fifo (xspi, xspi->tx_fifo_depth,0 );cdns_spi_write (xspi,CDNS_SPI_IER ,CDNS_SPI_IXR_DEFAULT );
@@ -641,6 +717,9 @@ static int cdns_spi_probe(struct platform_device *pdev) ctlr->mode_bits =SPI_CPOL |SPI_CPHA ; ctlr->bits_per_word_mask =SPI_BPW_MASK (8 ); +if (of_device_is_compatible (pdev->dev.of_node,"cix,sky1-spi-r1p6" )) + ctlr->bits_per_word_mask |=SPI_BPW_MASK (16 ) |SPI_BPW_MASK (32 ); +if (!spi_controller_is_target (ctlr)) { ctlr->mode_bits |=SPI_CS_HIGH ; ctlr->set_cs = cdns_spi_chipselect;
@@ -796,6 +875,7 @@ static const struct dev_pm_ops cdns_spi_dev_pm_ops = {static const struct of_device_id cdns_spi_of_match[] = { { .compatible ="xlnx,zynq-spi-r1p6" }, + { .compatible ="cix,sky1-spi-r1p6" }, { .compatible ="cdns,spi-r1p6" }, {/* end of table */ } };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 42/261 spi: spi-cadence: Move TX FIFO full busy-wait into FIFO
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srikanth Boyapally <[email protected]>
[ Upstream commit d9eadfce2fac49445db40808fe4d8259f20a9d2b ]
SPI host transfers could intermittently stall with spi_transfer timeouts. The TXFULL condition was checked only once in cdns_transfer_one() before cdns_spi_process_fifo(), so if the FIFO became full again during refill, writes could be dropped and the transfer would never complete.
Move the TXFULL busy-wait into the TX path of cdns_spi_process_fifo() so the 10µs back-off is applied per FIFO entry during filling, ensuring forward progress and eliminating spurious timeouts.
Restrict the delay to host mode using spi_controller_is_target(), the controller is passed into cdns_spi_process_fifo() so the check is made at the point of use. In target mode this delay must not run as it causes the target to miss its transfer window and corrupt data.
--- drivers/spi/spi-cadence.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-)
drivers/spi/spi-cadence.c +16 -10
@@ -385,11 +385,13 @@ static inline void cdns_spi_writer(struct cdns_spi *xspi)/** * cdns_spi_process_fifo - Fills the TX FIFO, and drain the RX FIFO +* @ctlr: Pointer to the spi_controller structure * @xspi: Pointer to the cdns_spi structure * @ntx: Number of bytes to pack into the TX FIFO * @nrx: Number of bytes to drain from the RX FIFO */ -static void cdns_spi_process_fifo (struct cdns_spi *xspi,int ntx,int nrx) +static void cdns_spi_process_fifo (struct spi_controller *ctlr, +struct cdns_spi *xspi,int ntx,int nrx) { ntx =clamp (ntx,0 , xspi->tx_bytes); nrx =clamp (nrx,0 , xspi->rx_bytes);
@@ -404,6 +406,16 @@ static void cdns_spi_process_fifo(struct cdns_spi *xspi, int ntx, int nrx) }if (ntx) { +/* When xspi in busy condition, bytes may send failed, +* then spi control didn't work thoroughly, add one byte +* delay. Only in host mode; in target mode this delay +* causes data corruption as the target fails to prepare +* data in time. +*/ +if (!spi_controller_is_target (ctlr) && + (cdns_spi_read (xspi,CDNS_SPI_ISR ) &CDNS_SPI_IXR_TXFULL )) +udelay (10 ); +cdns_spi_writer (xspi); ntx--; }
@@ -457,14 +469,14 @@ static irqreturn_t cdns_spi_irq(int irq, void *dev_id)cdns_spi_write (xspi,CDNS_SPI_THLD ,1 );if (xspi->tx_bytes) { -cdns_spi_process_fifo (xspi, trans_cnt, trans_cnt); +cdns_spi_process_fifo (ctlr, xspi, trans_cnt, trans_cnt); }else {/* Fixed delay due to controller limitation with * RX_NEMPTY incorrect status * Xilinx AR:65885 contains more details */ udelay (10 ); -cdns_spi_process_fifo (xspi,0 , trans_cnt); +cdns_spi_process_fifo (ctlr, xspi,0 , trans_cnt);cdns_spi_write (xspi,CDNS_SPI_IDR ,CDNS_SPI_IXR_DEFAULT );spi_finalize_current_transfer (ctlr);
@@ -517,17 +529,11 @@ static int cdns_transfer_one(struct spi_controller *ctlr,cdns_spi_write (xspi,CDNS_SPI_THLD , xspi->tx_fifo_depth >>1 ); } -/* When xspi in busy condition, bytes may send failed, -* then spi control didn't work thoroughly, add one byte delay -*/ -if (cdns_spi_read (xspi,CDNS_SPI_ISR ) &CDNS_SPI_IXR_TXFULL ) -udelay (10 ); - xspi->n_bytes =cdns_spi_n_bytes (transfer); xspi->tx_bytes =DIV_ROUND_UP (xspi->tx_bytes, xspi->n_bytes); xspi->rx_bytes =DIV_ROUND_UP (xspi->rx_bytes, xspi->n_bytes); -cdns_spi_process_fifo (xspi, xspi->tx_fifo_depth,0 ); +cdns_spi_process_fifo (ctlr, xspi, xspi->tx_fifo_depth,0 );cdns_spi_write (xspi,CDNS_SPI_IER ,CDNS_SPI_IXR_DEFAULT );return transfer->len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 43/261 hwmon: (nct6775-core) Fix number of temperature registers for NCT6116
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit b0e8adb2ccb43009796897ced09f91636685c9d3 ]
Unlike NCT6106, NCT6116 only has three temperature registers, and with it only three temperature source and temperature source configuration registers. The register addresses match those of NCT6106 and can be re-used.
The code used a separate array to list the temperature source registers for NCT6116, but used the size of the NCT6106 register array to set the number of registers. The NCT6106 register array provides six addresses, while the temperature source register array for NCT6116 only provides three addresses. This causes a KASAN report.
BUG: KASAN: global-out-of-bounds in nct6775_probe+0x936/0x46f0 [nct6775] Read of size 2 at addr ffffffffc19561a6 by task modprobe/954 ... Call Trace: dump_stack+0x7d/0xa7 print_address_description.constprop.0+0x1c/0x220 ? __kasan_kmalloc.constprop.0+0xc9/0xd0 ? __kmalloc_node_track_caller+0x194/0x5b0 ? nct6775_probe+0x936/0x46f0 [nct6775] ? nct6775_probe+0x936/0x46f0 [nct6775]
...
Fix the problem by hard-coding the number of temperature and temperature configuration registers to three for NCT6116. Drop the unnecessary NCT6116_REG_TEMP_SOURCE array and re-use NCT6106_REG_TEMP_SOURCE.
--- drivers/hwmon/nct6775-core.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
drivers/hwmon/nct6775-core.c +3 -5
@@ -846,8 +846,6 @@ static const u16 NCT6116_FAN_PULSE_SHIFT[] = { 0, 2, 4, 6, 6 };static const u16 NCT6116_REG_PWM [] = {0x119 ,0x129 ,0x139 ,0x199 ,0x1a9 };static const u16 NCT6116_REG_FAN_MODE [] = {0x113 ,0x123 ,0x133 ,0x193 ,0x1a3 };static const u16 NCT6116_REG_TEMP_SEL [] = {0x110 ,0x120 ,0x130 ,0x190 ,0x1a0 }; -static const u16 NCT6116_REG_TEMP_SOURCE [] = { -0xb0 ,0xb1 ,0xb2 };static const u16 NCT6116_REG_CRITICAL_TEMP [] = {0x11a ,0x12a ,0x13a ,0x19a ,0x1aa };
@@ -3650,7 +3648,7 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, = NCT6106_CRITICAL_PWM_ENABLE_MASK; data->REG_CRITICAL_PWM =NCT6116_REG_CRITICAL_PWM ; data->REG_TEMP_OFFSET =NCT6106_REG_TEMP_OFFSET ; - data->REG_TEMP_SOURCE =NCT6116_REG_TEMP_SOURCE ; + data->REG_TEMP_SOURCE =NCT6106_REG_TEMP_SOURCE ; data->REG_TEMP_SEL =NCT6116_REG_TEMP_SEL ; data->REG_WEIGHT_TEMP_SEL =NCT6106_REG_WEIGHT_TEMP_SEL ; data->REG_WEIGHT_TEMP[0 ] =NCT6106_REG_WEIGHT_TEMP_STEP ;
@@ -3664,13 +3662,13 @@ int nct6775_probe(struct device *dev, struct nct6775_data *data, reg_temp =NCT6106_REG_TEMP ; reg_temp_mon =NCT6106_REG_TEMP_MON ; - num_reg_temp =ARRAY_SIZE (NCT6106_REG_TEMP ); + num_reg_temp =3 ; num_reg_temp_mon =ARRAY_SIZE (NCT6106_REG_TEMP_MON ); num_reg_tsi_temp =ARRAY_SIZE (NCT6116_REG_TSI_TEMP ); reg_temp_over =NCT6106_REG_TEMP_OVER ; reg_temp_hyst =NCT6106_REG_TEMP_HYST ; reg_temp_config =NCT6106_REG_TEMP_CONFIG ; - num_reg_temp_config =ARRAY_SIZE (NCT6106_REG_TEMP_CONFIG ); + num_reg_temp_config =3 ; reg_temp_alternate =NCT6106_REG_TEMP_ALTERNATE ; reg_temp_crit =NCT6106_REG_TEMP_CRIT ; reg_temp_crit_l =NCT6106_REG_TEMP_CRIT_L ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 44/261 hwmon: (lm90) Only report alarms if driver is ready
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit aa9429edf9fc0e90d6f4da19ea4b5495a54ab117 ]
Userspace can read sysfs attributes before driver registration is complete, immediately after devm_hwmon_device_register_with_info() has been called. At that time, data->hwmon_dev is not yet initialized. This can trigger a NULL pointer access since lm90_update_device() and with it lm90_update_alarms_locked() will be called. This call schedules report_work and lm90_report_alarms(), which passes the still-NULL data->hwmon_dev to hwmon_notify_event() and triggers a NULL pointer dereference.
Fix the problem by only scheduling the report and alert workers data->hwmon_dev is set.
--- drivers/hwmon/lm90.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/hwmon/lm90.c +2 -2
@@ -1149,7 +1149,7 @@ static int lm90_update_alarms_locked(struct lm90_data *data, bool force) check_enable = (client->irq || !(data->config_orig &0x80 )) && (data->config &0x80 ); -if (force || check_enable) +if (data->hwmon_dev && (force || check_enable))schedule_work (&data->report_work);/*
@@ -1157,7 +1157,7 @@ static int lm90_update_alarms_locked(struct lm90_data *data, bool force)* alarms are all clear, and alerts are currently disabled. * Otherwise (re)schedule worker if needed. */ -if (check_enable) { +if (check_enable && data->hwmon_dev) {if (!(data->current_alarms & data->alert_alarms)) {dev_dbg (&client->dev,"Re-enabling ALERT#\n" );lm90_update_confreg (data, data->config & ~0x80 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 45/261 hwmon: (nzxt-smart2) DMA-align output buffer
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit 080bbf42faf77e6489ab30d5114c5f8f6ccbb1b8 ]
Sashiko reports:
When send_output_report() calls hid_hw_output_report(), the underlying USB HID core calls usb_interrupt_msg() which maps this buffer directly for DMA.
When the DMA mapping flushes or invalidates the cacheline, it will corrupt the adjacent variables (mutex, update_interval) that were modified concurrently by the CPU. This causes memory corruption due to cacheline sharing on non-coherent CPU architectures (such as ARM or MIPS). The DMA API debugging tool (CONFIG_DMA_API_DEBUG) will trigger runtime warnings for this violation.
Any operation that triggers send_output_report() (like setting a fan speed or updating the interval) causes the USB DMA mapping. On systems with non-coherent caches, this structural bug causes immediate and deterministic memory corruption.
Align the output buffer to ARCH_DMA_MINALIGN to fix the problem.
--- drivers/hwmon/nzxt-smart2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hwmon/nzxt-smart2.c +1 -1
@@ -203,7 +203,7 @@ struct drvdata {*/ struct mutex mutex;long update_interval; -u8 output_buffer[OUTPUT_REPORT_SIZE ]; +u8 output_buffer[OUTPUT_REPORT_SIZE ]__aligned(ARCH_DMA_MINALIGN) ; };static long scale_pwm_value (long val,long orig_max,long new_max)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 46/261 net: do not send ICMP/NDISC Redirects when peer allocation fails
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit dbc3791e3b2472e1ccc08947e0f83b443470ff4f ]
When inet_getpeer_v4() or inet_getpeer_v6() fails to allocate a peer entry under memory pressure or tree size caps, redirect handlers previously fell back to sending un-rate-limited ICMP/NDISC Redirect messages.
In IPv4, ip_rt_send_redirect() called icmp_send() directly when peer == NULL. In IPv6, ip6_forward() and ndisc_send_redirect() passed a NULL peer into inet_peer_xrlim_allow(), which returned true when peer == NULL.
Because ICMP/NDISC Redirects are not part of the default global rate limit mask (sysctl_icmp_ratemask), sending redirects when peer == NULL creates an un-rate-limited ICMP packet storm.
Fix this by failing closed in ip_rt_send_redirect(), ip6_forward(), and ndisc_send_redirect() when peer is NULL.
--- net/ipv4/route.c | 2 -- net/ipv6/ip6_output.c | 2 +- net/ipv6/ndisc.c | 2 ++ 3 files changed, 3 insertions(+), 3 deletions(-)
net/ipv4/route.c +0 -2
@@ -902,8 +902,6 @@ void ip_rt_send_redirect(struct sk_buff *skb) peer =inet_getpeer_v4 (net->ipv4.peers,ip_hdr (skb)->saddr, vif);if (!peer) {rcu_read_unlock (); -icmp_send (skb,ICMP_REDIRECT ,ICMP_REDIR_HOST , -rt_nexthop (rt,ip_hdr (skb)->daddr));return ; }
net/ipv6/ip6_output.c +1 -1
@@ -625,7 +625,7 @@ int ip6_forward(struct sk_buff *skb)/* Limit redirects both by destination (here) and by source (inside ndisc_send_redirect) */ -if (inet_peer_xrlim_allow (peer,1 *HZ )) +if (peer &&inet_peer_xrlim_allow (peer,1 *HZ ))ndisc_send_redirect (skb, target);rcu_read_unlock (); }else {
net/ipv6/ndisc.c +2 -0
@@ -1731,6 +1731,8 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)rcu_read_lock (); peer =inet_getpeer_v6 (net->ipv6.peers, &ipv6_hdr (skb)->saddr); +if (!peer) + goto release; ret =inet_peer_xrlim_allow (peer,1 *HZ );rcu_read_unlock ();
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 47/261 hwmon: (nct6775-core) Prevent access to unsupported weight registers
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit d0b704e569ac3b8416d8e02270cdc9bf830ed395 ]
Sashiko reports:
During initialization of the nct6116 chip, the driver sets data->pwm_num to 5. However, it assigns several NCT6106 register arrays (such as NCT6106_REG_WEIGHT_DUTY_STEP, NCT6106_REG_WEIGHT_TEMP_SEL, and NCT6106_REG_WEIGHT_TEMP_*) to data->REG_PWM and data->REG_WEIGHT_TEMP. These arrays only contain 3 elements.
In nct6775_update_pwm(), the driver iterates up to data->pwm_num. If data->has_pwm has bits 3 or 4 set (which is structurally possible for nct6116), the loop attempts to read elements at index 3 and 4 from these 3-element arrays. This results in a global out-of-bounds read, which can be caught by KASAN.
Furthermore, the driver uses these garbage out-of-bounds values as hardware register addresses for subsequent read and write operations. This leads to invalid hardware register access, potentially causing hardware misconfiguration or system crashes.
The underlying problem is that the chip does support up to five fan control channels, but only the first three support weight control. Fix the problem by extending the affected weight register arrays with zeroed fields. The driver uses zeroed register addresses to determine if a register is supported or not, and skips accesses for unsupported registers.
--- drivers/hwmon/nct6775-core.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/hwmon/nct6775-core.c +6 -6
@@ -791,12 +791,12 @@ static const u16 NCT6106_REG_TOLERANCE_H[] = { 0x112, 0x122, 0x132 };static const u16 NCT6106_REG_TARGET [] = {0x111 ,0x121 ,0x131 }; -static const u16 NCT6106_REG_WEIGHT_TEMP_SEL [] = {0x168 ,0x178 ,0x188 }; -static const u16 NCT6106_REG_WEIGHT_TEMP_STEP [] = {0x169 ,0x179 ,0x189 }; -static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL [] = {0x16a ,0x17a ,0x18a }; -static const u16 NCT6106_REG_WEIGHT_DUTY_STEP [] = {0x16b ,0x17b ,0x18b }; -static const u16 NCT6106_REG_WEIGHT_TEMP_BASE [] = {0x16c ,0x17c ,0x18c }; -static const u16 NCT6106_REG_WEIGHT_DUTY_BASE [] = {0x16d ,0x17d ,0x18d }; +static const u16 NCT6106_REG_WEIGHT_TEMP_SEL [] = {0x168 ,0x178 ,0x188 ,0 ,0 }; +static const u16 NCT6106_REG_WEIGHT_TEMP_STEP [] = {0x169 ,0x179 ,0x189 ,0 ,0 }; +static const u16 NCT6106_REG_WEIGHT_TEMP_STEP_TOL [] = {0x16a ,0x17a ,0x18a ,0 ,0 }; +static const u16 NCT6106_REG_WEIGHT_DUTY_STEP [] = {0x16b ,0x17b ,0x18b ,0 ,0 }; +static const u16 NCT6106_REG_WEIGHT_TEMP_BASE [] = {0x16c ,0x17c ,0x18c ,0 ,0 }; +static const u16 NCT6106_REG_WEIGHT_DUTY_BASE [] = {0x16d ,0x17d ,0x18d ,0 ,0 };static const u16 NCT6106_REG_AUTO_TEMP [] = {0x160 ,0x170 ,0x180 };static const u16 NCT6106_REG_AUTO_PWM [] = {0x164 ,0x174 ,0x184 };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 48/261 net: bridge: mrp: fix Option TLV length in MRP_Test frames
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Corvaglia <[email protected]>
[ Upstream commit 5546da86894d5906f131b05890705a7abf949d84 ]
oui is a pointer, so sizeof(oui) is the pointer size. The MRA Option TLV thus advertises a wrong length (15 vs 10 on x86_64), causing misparsing of the frame on peers. Fix is to replace with sizeof(*oui).
--- net/bridge/br_mrp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/bridge/br_mrp.c +1 -1
@@ -215,7 +215,7 @@ static struct sk_buff *br_mrp_alloc_test_skb(struct br_mrp *mrp,struct br_mrp_oui_hdr *oui =NULL ;u8 length; - length =sizeof (*sub_opt) +sizeof (*sub_tlv) +sizeof (oui) + + length =sizeof (*sub_opt) +sizeof (*sub_tlv) +sizeof (*oui) +MRP_OPT_PADDING ;br_mrp_skb_tlv (skb,BR_MRP_TLV_HEADER_OPTION , length);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 49/261 forcedeth: fix UAF of txrx_stats in nv_remove
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenguang Zhao <[email protected]>
[ Upstream commit 22666ba1420164753d7b0f5a841986b25ace5435 ]
nv_remove() frees the per-CPU txrx_stats before unregister_netdev(). Until unregister completes, ndo_get_stats64, the NAPI/xmit data path, and nv_close()/drain may still access txrx_stats, leading to a use-after-free.
Free the stats only after unregister_netdev().
--- drivers/net/ethernet/nvidia/forcedeth.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/nvidia/forcedeth.c +2 -2
@@ -6199,10 +6199,10 @@ static void nv_remove(struct pci_dev *pci_dev)struct net_device *dev =pci_get_drvdata (pci_dev);struct fe_priv *np =netdev_priv (dev); -free_percpu (np->txrx_stats); -unregister_netdev (dev); +free_percpu (np->txrx_stats); +nv_restore_mac_addr (pci_dev);/* restore any phy related changes */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 50/261 hwmon: (adt7470) Fix fans stuck in manual mode on I2C errors
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Angelo Daros de Luca <[email protected]>
[ Upstream commit 625a2c02a1c04571232a746fe188b4d9a8d63edd ]
During adt7470_read_temperatures(), the driver temporarily switches the PWM channels to manual mode, performs the temperature collection, and then restores the original configuration registers.
However, if an I2C transaction fails at any point after entering manual mode, the function aborts and returns immediately. This leaves the configuration registers un-restored, permanently trapping the fans in manual mode.
Introduce a recovery path to ensure that the original PWM configuration registers are always restored, even when intermediate I2C operations fail.
--- drivers/hwmon/adt7470.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-)
drivers/hwmon/adt7470.c +29 -11
@@ -205,11 +205,12 @@ static inline int adt7470_write_word_data(struct adt7470_data *data, unsigned in/* Probe for temperature sensors. Assumes lock is held */ static int adt7470_read_temperatures (struct adt7470_data *data) { -unsigned long res; +struct device *dev =regmap_get_device (data->regmap); +u8 pwm[ADT7470_FAN_COUNT ];unsigned int pwm_cfg[2 ]; -int err; +unsigned long res; +int err, err2;int i; -u8 pwm[ADT7470_FAN_COUNT ];/* save pwm[1-4] config register */ err =regmap_read (data->regmap,ADT7470_REG_PWM_CFG (0 ), &pwm_cfg[0 ]);
@@ -233,19 +234,19 @@ static int adt7470_read_temperatures(struct adt7470_data *data) err =regmap_update_bits (data->regmap,ADT7470_REG_PWM_CFG (2 ),ADT7470_PWM_AUTO_MASK ,0 );if (err <0 ) -return err; + goto out_restore;/* write pwm control to whatever it was */ err =regmap_bulk_write (data->regmap,ADT7470_REG_PWM (0 ), &pwm[0 ],ADT7470_PWM_COUNT );if (err <0 ) -return err; + goto out_restore;/* start reading temperature sensors */ err =regmap_update_bits (data->regmap,ADT7470_REG_CFG ,ADT7470_T05_STB_MASK ,ADT7470_T05_STB_MASK );if (err <0 ) -return err; + goto out_restore;/* Delay is 200ms * number of temp sensors. */ res = msleep_interruptible((data->num_temp_sensors >= 0 ?
@@ -256,13 +257,30 @@ static int adt7470_read_temperatures(struct adt7470_data *data) err =regmap_update_bits (data->regmap,ADT7470_REG_CFG ,ADT7470_T05_STB_MASK ,0 );if (err <0 ) -return err; + goto out_restore; +out_restore:/* restore pwm[1-4] config registers */ - err =regmap_write (data->regmap,ADT7470_REG_PWM_CFG (0 ), pwm_cfg[0 ]); -if (err <0 ) -return err; - err =regmap_write (data->regmap,ADT7470_REG_PWM_CFG (2 ), pwm_cfg[1 ]); + err2 =regmap_write (data->regmap,ADT7470_REG_PWM_CFG (0 ), pwm_cfg[0 ]); +if (err2 <0 ) { +dev_warn_ratelimited (dev, +"failed to restore PWM{1,2} config (%d)\n" , + err2); + +if (!err) + err = err2; + } + + err2 =regmap_write (data->regmap,ADT7470_REG_PWM_CFG (2 ), pwm_cfg[1 ]); +if (err2 <0 ) { +dev_warn_ratelimited (dev, +"failed to restore PWM{3,4} config (%d)\n" , + err2); + +if (!err) + err = err2; + } +if (err <0 )return err;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 51/261 hwmon: (adt7470) Fix cache updated before hardware write on I2C error
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Angelo Daros de Luca <[email protected]>
[ Upstream commit 05270bd38d9bf88a2f4c212246a8fa29f4032078 ]
adt7470_temp_write() and adt7470_pwm_write() update the driver's cached values (temp_min, temp_max, pwm_input, pwm_enable) before issuing the corresponding regmap_write(), and never check whether the write succeeded before committing that update. If the I2C transaction fails, the function correctly propagates the error to the caller, but the cache silently keeps the new value, which was never actually applied to the hardware. Subsequent reads then report a value that does not match the device state.
Reorder both write paths to update the cache only after a successful regmap_write(), so the cache always reflects what was actually written to the hardware.
--- drivers/hwmon/adt7470.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-)
drivers/hwmon/adt7470.c +9 -5
@@ -589,14 +589,16 @@ static int adt7470_temp_write(struct device *dev, u32 attr, int channel, long vaswitch (attr) {case hwmon_temp_min:mutex_lock (&data->lock); - data->temp_min[channel] = val; err =regmap_write (data->regmap,ADT7470_TEMP_MIN_REG (channel), val); +if (!err) + data->temp_min[channel] = val;mutex_unlock (&data->lock);break ;case hwmon_temp_max:mutex_lock (&data->lock); - data->temp_max[channel] = val; err =regmap_write (data->regmap,ADT7470_TEMP_MAX_REG (channel), val); +if (!err) + data->temp_max[channel] = val;mutex_unlock (&data->lock);break ;default :
@@ -839,9 +841,10 @@ static int adt7470_pwm_write(struct device *dev, u32 attr, int channel, long valcase hwmon_pwm_input: val =clamp_val (val,0 ,255 );mutex_lock (&data->lock); - data->pwm[channel] = val; err =regmap_write (data->regmap,ADT7470_REG_PWM (channel), - data->pwm[channel]); + val); +if (!err) + data->pwm[channel] = val;mutex_unlock (&data->lock);break ;case hwmon_pwm_enable:
@@ -855,10 +858,11 @@ static int adt7470_pwm_write(struct device *dev, u32 attr, int channel, long val val--;mutex_lock (&data->lock); - data->pwm_automatic[channel] = val; err =regmap_update_bits (data->regmap,ADT7470_REG_PWM_CFG (channel), pwm_auto_reg_mask, val ? pwm_auto_reg_mask :0 ); +if (!err) + data->pwm_automatic[channel] = val;mutex_unlock (&data->lock);break ;case hwmon_pwm_freq:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 52/261 hwmon: (adt7470) Fix busy-loop and I2C flooding in update thread
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Angelo Daros de Luca <[email protected]>
[ Upstream commit cb0b7f9c43b0abbd422a7e4c2c85e91db429207c ]
When userspace configures 'auto_update_interval' to 0 via sysfs, the background kthread executes schedule_timeout_interruptible(0), which returns immediately.
If 'num_temp_sensors' is concurrently or previously set to 0, the msleep_interruptible() delay inside adt7470_read_temperatures() also becomes 0. This combination forces the background thread into a tight, unbounded busy-loop, hogging the CPU and flooding the I2C bus with a continuous stream of transactions.
Fix this vulnerability by raising the lower limit of the clamp_val in auto_update_interval_store() from 0 to 500 milliseconds. This guarantees a reasonable minimum sleep window between sensor updates, protecting the system from intentional or accidental I2C bus denial of service.
--- drivers/hwmon/adt7470.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hwmon/adt7470.c +1 -1
@@ -509,7 +509,7 @@ static ssize_t auto_update_interval_store(struct device *dev,if (kstrtol (buf,10 , &temp))return -EINVAL ; - temp =clamp_val (temp,0 ,60000 ); + temp =clamp_val (temp,500 ,60000 );mutex_lock (&data->lock); data->auto_update_interval = temp;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 53/261 hwmon: (adt7470) Fix temperature alarm logic in hwmon_temp_read()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Angelo Daros de Luca <[email protected]>
[ Upstream commit 1a18c79c4bc44cc5349c60e16b0b744dc6ec5f77 ]
During the conversion the alarm callback started interpreting the channel index as an alarm bitmask, resulting in incorrect alarm reporting. Compute the proper alarm bit instead.
--- drivers/hwmon/adt7470.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
drivers/hwmon/adt7470.c +17 -2
@@ -110,6 +110,21 @@ static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END };#define ALARM2 (x) ((x) << 8) +/* TEMP1..TEMP7 (ch 0..6) are, respectively BIT(0)..BIT(6) of reg 0x41 and +* 0x72, or BIT(0)..BIT(6) of data->alarm. +* TEMP8..TEMP9 (ch 7..9) are, respectively BIT(0)..BIT(2) of reg 0x42 and +* 0x73, or BIT(8)..BIT(10) of data->alarm. +*/ +#define TEMP_ALARM_BIT (ch) ({ \ + typeof(ch) _ch = (ch); \ + (1 << (_ch < 7 ? _ch : _ch + 1)); \ +}) + +/* FAN1..FAN4 (ch 0..3) are respectively BIT(4)..BIT(7) in +* reg 0x42 and 0x73 or BIT(12)..BIT(15) in data->alarm. +*/ +#define FAN_ALARM_BIT (ch) (1 << (12 + (ch))) +#define ADT7470_VENDOR 0x41#define ADT7470_DEVICE 0x70/* datasheet only mentions a revision 2 */
@@ -569,7 +584,7 @@ static int adt7470_temp_read(struct device *dev, u32 attr, int channel, long *va *val =1000 * data->temp_max[channel];break ;case hwmon_temp_alarm: - *val = !!(data->alarm & channel); + *val = !!(data->alarm &TEMP_ALARM_BIT (channel));break ;default :return -EOPNOTSUPP ;
@@ -668,7 +683,7 @@ static int adt7470_fan_read(struct device *dev, u32 attr, int channel, long *val *val =0 ;break ;case hwmon_fan_alarm: - *val = !!(data->alarm & (1 << (12 + channel))); + *val = !!(data->alarm &FAN_ALARM_BIT (channel));break ;default :return -EOPNOTSUPP ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 54/261 hwmon: (adt7470) Fix swapped PWM3 and PWM4 auto mode masks
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Angelo Daros de Luca <[email protected]>
[ Upstream commit a3850231521b06bbbb18c8ebea100320c14a08be ]
The ADT7470_PWM3_AUTO_MASK and ADT7470_PWM4_AUTO_MASK macros are currently defined with swapped bit values.
According to Table 22 of the ADT7470 datasheet, the Fan Control Mode Configuration for register 0x69 follows the exact same bit position layout as register 0x68:
- 0x68 Bit[7] corresponds to BHVR1 (PWM1) -> 0x80
- 0x68 Bit[6] corresponds to BHVR2 (PWM2) -> 0x40
- 0x69 Bit[7] corresponds to BHVR3 (PWM3) -> 0x80
- 0x69 Bit[6] corresponds to BHVR4 (PWM4) -> 0x40
Consequently, PWM3 should use mask 0x80 and PWM4 should use 0x40.
This typo did not cause any functional bugs because these specific macros are never referenced in the driver code. Instead, the driver correctly applies the configuration by relying on the modulo parity of the channel index (e.g., channel % 2) to selectively apply either ADT7470_PWM1_AUTO_MASK (0x80) or ADT7470_PWM2_AUTO_MASK (0x40). Since the bit layout is identical between the two configuration registers, the hardware is currently configured correctly.
Fix the macro definitions to reflect the datasheet accurately and prevent future bugs or confusion during code review and refactoring. As this is a purely cosmetic fix with no functional impact, a backport to stable kernels is not necessary.
--- drivers/hwmon/adt7470.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/hwmon/adt7470.c +2 -2
@@ -70,8 +70,8 @@ static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END };#define ADT7470_PWM1_AUTO_MASK 0x80#define ADT7470_PWM_AUTO_MASK 0xC0#define ADT7470_REG_PWM34_CFG 0x69 -#define ADT7470_PWM3_AUTO_MASK 0x40 -#define ADT7470_PWM4_AUTO_MASK 0x80 +#define ADT7470_PWM4_AUTO_MASK 0x40 +#define ADT7470_PWM3_AUTO_MASK 0x80#define ADT7470_REG_PWM_MIN_BASE_ADDR 0x6A#define ADT7470_REG_PWM_MIN_MAX_ADDR 0x6D#define ADT7470_REG_PWM_TEMP_MIN_BASE_ADDR 0x6E
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 55/261 hwmon: (adt7470) Use cached PWM frequency value
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Angelo Daros de Luca <[email protected]>
[ Upstream commit 60677cd4c28f44d5b307d3029dccece38fcce90f ]
adt7470_pwm_read() currently ignores failures returned by pwm1_freq_get(). If the register read fails, the negative error code is returned through *val while the function itself reports success, potentially exposing a negative PWM frequency through sysfs.
Fix this by using the cached PWM frequency maintained by the driver, eliminating the register access from the read path.
Apart from the corrected error propagation and using the cached value, no functional change is intended.
--- drivers/hwmon/adt7470.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
drivers/hwmon/adt7470.c +18 -2
@@ -182,6 +182,7 @@ struct adt7470_data {u8 pwm_min[ADT7470_PWM_COUNT ];s8 pwm_tmin[ADT7470_PWM_COUNT ];u8 pwm_auto_temp[ADT7470_PWM_COUNT ]; +u32 pwm_freq;struct task_struct *auto_update;unsigned int auto_update_interval;
@@ -756,7 +757,7 @@ static ssize_t force_pwm_max_store(struct device *dev, }/* These are the valid PWM frequencies to the nearest Hz */ -static const int adt7470_freq_map[] = { +static const u32 adt7470_freq_map[] = {11 ,15 ,22 ,29 ,35 ,44 ,59 ,88 ,1400 ,22500 };
@@ -804,7 +805,7 @@ static int adt7470_pwm_read(struct device *dev, u32 attr, int channel, long *val *val =1 + data->pwm_automatic[channel];break ;case hwmon_pwm_freq: - *val =pwm1_freq_get (dev); + *val = data->pwm_freq;break ;default :return -EOPNOTSUPP ;
@@ -817,12 +818,14 @@ static int pwm1_freq_set(struct device *dev, long freq) {struct adt7470_data *data =dev_get_drvdata (dev);unsigned int low_freq =ADT7470_CFG_LF ; +u32 closest_freq;int index;int err;/* Round the user value given to the closest available frequency */ index =find_closest (freq, adt7470_freq_map,ARRAY_SIZE (adt7470_freq_map)); + closest_freq = adt7470_freq_map[index];if (index >=8 ) { index -=8 ;
@@ -840,6 +843,10 @@ static int pwm1_freq_set(struct device *dev, long freq) err =regmap_update_bits (data->regmap,ADT7470_REG_CFG_2 ,ADT7470_FREQ_MASK , index <<ADT7470_FREQ_SHIFT ); +if (err <0 ) + goto out; + + data->pwm_freq = closest_freq; out:mutex_unlock (&data->lock);
@@ -1293,6 +1300,7 @@ static int adt7470_probe(struct i2c_client *client)struct device *dev = &client->dev;struct adt7470_data *data;struct device *hwmon_dev; +int freq_val;int err; data =devm_kzalloc (dev,sizeof (struct adt7470_data ),GFP_KERNEL );
@@ -1317,6 +1325,14 @@ static int adt7470_probe(struct i2c_client *client)if (err <0 )return err; + freq_val =pwm1_freq_get (dev); +if (freq_val <=0 ) { + err = freq_val <0 ? freq_val : -EINVAL ; +return err; + } + + data->pwm_freq = (u32 )freq_val; +/* Register sysfs hooks */ hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name, data, &adt7470_chip_info,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 56/261 hwmon: (adt7470) Fix divide-by-zero TOCTOU crash in fan speed read
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Angelo Daros de Luca <[email protected]>
[ Upstream commit 1b46fe9dc8f8de59310f37e6c5e5c0e05ded46c3 ]
If the fan data becomes 0 between the FAN_DATA_VALID() check and the FAN_PERIOD_TO_RPM() conversion, it will result in a divide-by-zero crash due to a race with a concurrent update of the cached fan value.
Fix a TOCTOU issue by reading fan data once.
--- drivers/hwmon/adt7470.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-)
drivers/hwmon/adt7470.c +10 -13
@@ -660,36 +660,33 @@ static ssize_t alarm_mask_store(struct device *dev,static int adt7470_fan_read (struct device *dev,u32 attr,int channel,long *val) {struct adt7470_data *data =adt7470_update_device (dev); +u16 fan_data;if (IS_ERR (data))return PTR_ERR (data);switch (attr) {case hwmon_fan_input: -if (FAN_DATA_VALID (data->fan[channel])) - *val =FAN_PERIOD_TO_RPM (data->fan[channel]); -else - *val =0 ; + fan_data =READ_ONCE (data->fan[channel]);break ;case hwmon_fan_min: -if (FAN_DATA_VALID (data->fan_min[channel])) - *val =FAN_PERIOD_TO_RPM (data->fan_min[channel]); -else - *val =0 ; + fan_data =READ_ONCE (data->fan_min[channel]);break ;case hwmon_fan_max: -if (FAN_DATA_VALID (data->fan_max[channel])) - *val =FAN_PERIOD_TO_RPM (data->fan_max[channel]); -else - *val =0 ; + fan_data =READ_ONCE (data->fan_max[channel]);break ;case hwmon_fan_alarm: *val = !!(data->alarm &FAN_ALARM_BIT (channel)); -break ; +return 0 ;default :return -EOPNOTSUPP ; } +if (FAN_DATA_VALID (fan_data)) + *val =FAN_PERIOD_TO_RPM (fan_data); +else + *val =0 ; +return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 57/261 hwmon: (adt7470) Fix PWM auto temp state array and bounds check
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Angelo Daros de Luca <[email protected]>
[ Upstream commit 92413f439d1ec5e55b73ede8d66a7b971cbd1ced ]
In pwm_auto_temp_store(), the parsed user input was missing bounds checks, allowing values > 0xF to overflow into the adjacent channel's bits. Furthermore, the value was being incorrectly written to the pwm_automatic state array instead of pwm_auto_temp.
Fix this by rejecting values > 0xF with -EINVAL, and assigning the value to the correct array only after a successful I2C write.
--- drivers/hwmon/adt7470.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/hwmon/adt7470.c +6 -1
@@ -1057,8 +1057,10 @@ static ssize_t pwm_auto_temp_store(struct device *dev,if (temp <0 )return temp; +if (temp >0xF ) +return -EINVAL ; +mutex_lock (&data->lock); - data->pwm_automatic[attr->index] = temp;if (!(attr->index %2 )) { mask =0xF0 ;
@@ -1069,6 +1071,9 @@ static ssize_t pwm_auto_temp_store(struct device *dev, } err =regmap_update_bits (data->regmap, pwm_auto_reg, mask, val); +if (!err) + data->pwm_auto_temp[attr->index] = temp; +mutex_unlock (&data->lock);return err <0 ? err : count;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 58/261 powerpc/boot: Fix simpleboot CPU node lookup check
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
[ Upstream commit c824ab65685bb119c6c6a3a200b3428c72862d5a ]
fdt_node_offset_by_prop_value() returns a negative error code on failure - fix the check accordingly.
--- arch/powerpc/boot/simpleboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/boot/simpleboot.c +1 -1
@@ -68,7 +68,7 @@ void platform_init(unsigned long r3, unsigned long r4, unsigned long r5,/* finally, setup the timebase */ node =fdt_node_offset_by_prop_value (_dtb_start,-1 ,"device_type" ,"cpu" ,sizeof ("cpu" )); -if (!node) +if (node <0 )fatal ("Cannot find cpu node\n" ); timebase =fdt_getprop (_dtb_start, node,"timebase-frequency" , &size);if (timebase && (size ==4 ))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 59/261 powerpc/boot: Fix treeboot-currituck CPU node lookup check
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
[ Upstream commit 43863f6575d2211e8c5157fefb83ad0ad046aab4 ]
fdt_node_offset_by_prop_value() returns a negative error code on failure - fix the check accordingly.
--- arch/powerpc/boot/treeboot-currituck.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/boot/treeboot-currituck.c +1 -1
@@ -102,7 +102,7 @@ void platform_init(void) node =fdt_node_offset_by_prop_value (_dtb_start,-1 ,"device_type" ,"cpu" ,sizeof ("cpu" )); -if (!node) +if (node <0 )fatal ("Cannot find cpu node\n" ); timebase =fdt_getprop (_dtb_start, node,"timebase-frequency" , &size);if (timebase && (size ==4 ))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 60/261 powerpc/boot: Fix treeboot-akebono CPU node lookup check
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
[ Upstream commit b24fc8278b70a9d27ec801a427ab4de9b769d69a ]
fdt_node_offset_by_prop_value() returns a negative error code on failure - fix the check accordingly.
--- arch/powerpc/boot/treeboot-akebono.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/powerpc/boot/treeboot-akebono.c +1 -1
@@ -146,7 +146,7 @@ void platform_init(char *userdata) node =fdt_node_offset_by_prop_value (_dtb_start,-1 ,"device_type" ,"cpu" ,sizeof ("cpu" )); -if (!node) +if (node <0 )fatal ("Cannot find cpu node\n" ); timebase =fdt_getprop (_dtb_start, node,"timebase-frequency" , &size);if (timebase && (size ==4 ))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 61/261 wifi: mac80211: validate individual TWT params before driver setup
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhao Li <[email protected]>
[ Upstream commit 0502d5077e419427d80f4d46ba95d0067f5fb916 ]
ieee80211_process_rx_twt_action() only partially validates a received S1G TWT setup frame before queueing it.
An individual agreement can therefore reach ieee80211_s1g_rx_twt_setup() with twt->length too short for the full struct ieee80211_twt_params.
The individual path passes twt to drv_add_twt_setup(). Both the tracepoint and the driver callback consume the complete parameters block, not merely req_type. Do not pass a short individual agreement to the driver. Broadcast agreements remain unchanged because they are rejected locally after accessing only req_type.
[edit commit message to not overclaim lack of validation nor
understate driver impact]
--- net/mac80211/s1g.c | 4 ++++ 1 file changed, 4 insertions(+)
net/mac80211/s1g.c +4 -0
@@ -100,6 +100,10 @@ ieee80211_s1g_rx_twt_setup(struct ieee80211_sub_if_data *sdata,struct ieee80211_twt_setup *twt = (void *)mgmt->u.action.u.s1g.variable;struct ieee80211_twt_params *twt_agrt = (void *)twt->params; +if (!(twt->control &IEEE80211_TWT_CONTROL_NEG_TYPE_BROADCAST ) && + twt->length <sizeof (twt->control) +sizeof (*twt_agrt)) +return ; + twt_agrt->req_type &=cpu_to_le16 (~IEEE80211_TWT_REQTYPE_REQUEST );/* broadcast TWT not supported yet */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 62/261 hwmon: (pmbus) Fix return value from pmbus_update_byte_data()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit a19038a200f18d9e74ac30081797917d0886e16b ]
pmbus_update_byte_data() is supposed to return a negative error code or 0. However, if no change is made to the register, it actually returns the register value. This can result in problems if the calling code explicitly expects to see an error code or 0.
Fix it to return 0 on success or the error code as expected.
--- drivers/hwmon/pmbus/pmbus_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hwmon/pmbus/pmbus_core.c +1 -1
@@ -449,7 +449,7 @@ int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg,if (tmp != rv) rv =_pmbus_write_byte_data (client, page, reg, tmp); -return rv; +return rv <0 ? rv :0 ; }EXPORT_SYMBOL_NS_GPL (pmbus_update_byte_data,PMBUS );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 63/261 Bluetooth: ISO: clear iso_data always when detaching conn from hcon
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit d57e506f6a1e3929611340fae87c1e4823f4d85c ]
When setting conn->hcon = NULL, also conn->hcon->iso_data = NULL is necessary, otherwise later iso_conn_free() will UAF.
Fix clearing of iso_data in iso_sock_disconn()
Fixes KASAN: slab-use-after-free in iso_conn_hold_unless_zero on iso_sock_release() followed by hci_abort_conn_sync().
--- net/bluetooth/iso.c | 1 + 1 file changed, 1 insertion(+)
net/bluetooth/iso.c +1 -0
@@ -767,6 +767,7 @@ static void iso_sock_disconn(struct sock *sk)iso_sock_set_timer (sk,ISO_DISCONN_TIMEOUT );iso_conn_lock (iso_pi (sk)->conn);hci_conn_drop (iso_pi (sk)->conn->hcon); +iso_pi (sk)->conn->hcon->iso_data =NULL ;iso_pi (sk)->conn->hcon =NULL ;iso_conn_unlock (iso_pi (sk)->conn); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 64/261 Bluetooth: L2CAP: fix UAF in l2cap_le_connect_rsp
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiale Yao <[email protected]>
[ Upstream commit c4740e7f23ff9a8210198d8b4703259e21b9f69d ]
l2cap_le_connect_rsp() obtains a channel via __l2cap_get_chan_by_ident() but neither holds a reference nor uses l2cap_chan_hold_unless_zero() before locking and operating on it. A concurrent l2cap_chan_del() triggered by a remote disconnect can free the channel between the lookup and l2cap_chan_lock(), causing a use-after-free.
The BR/EDR counterpart l2cap_connect_rsp() and the sibling handler l2cap_le_command_rej() already use l2cap_chan_hold_unless_zero() to safely hold a reference, but l2cap_le_connect_rsp() was left unprotected.
Fix by adding l2cap_chan_hold_unless_zero() after the ident lookup and l2cap_chan_put() on the exit path, consistent with other L2CAP response handlers.
--- net/bluetooth/l2cap_core.c | 5 +++++ 1 file changed, 5 insertions(+)
net/bluetooth/l2cap_core.c +5 -0
@@ -4779,6 +4779,10 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn,if (!chan)return -EBADSLT ; + chan =l2cap_chan_hold_unless_zero (chan); +if (!chan) +return -EBADSLT ; + err =0 ;l2cap_chan_lock (chan);
@@ -4824,6 +4828,7 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn, }l2cap_chan_unlock (chan); +l2cap_chan_put (chan);return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 65/261 Bluetooth: ISO: fix timeout vs sync_timeout typo in check_bcast_qos
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit e9cb51813d79fc9aae4a2098aab3ab6ebd7fb6c8 ]
In iso.c check_bcast_qos(), missing bcast.timeout is not set to its default value, and appears typoed as bcast.sync_timeout.
Fix the typo.
--- net/bluetooth/iso.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/bluetooth/iso.c +1 -1
@@ -1439,7 +1439,7 @@ static bool check_bcast_qos(struct bt_iso_qos *qos)return false;if (!qos->bcast.timeout) - qos->bcast.sync_timeout =BT_ISO_SYNC_TIMEOUT ; + qos->bcast.timeout =BT_ISO_SYNC_TIMEOUT ;if (qos->bcast.timeout <0x000a || qos->bcast.timeout >0x4000 )return false;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 66/261 Bluetooth: btintel: Validate length before parsing diagnostics TLV
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zijun Hu <[email protected]>
[ Upstream commit b640ff9af3c809ff5ea2077fbba17df1594ec1e4 ]
btintel_diagnostics() accesses tlv->val[0] without first validating that the diagnostics VSE is long enough to contain that field, so may cause reading data beyond the received frame.
Fix by validating the length before access.
--- drivers/bluetooth/btintel.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/bluetooth/btintel.c +3 -0
@@ -2922,6 +2922,9 @@ static int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb) {struct intel_tlv *tlv = (void *)&skb->data[5 ]; +if (skb->len <5 +sizeof (*tlv) +sizeof (tlv->val[0 ])) + goto recv_frame; +/* The first event is always an event type TLV */ if (tlv->type !=INTEL_TLV_TYPE_ID ) goto recv_frame;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 67/261 Bluetooth: hci_sync: make hci_cmd_sync_run_once return -EEXIST if exists
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit d288f4db0909c22342eb50cd1632b4d850517281 ]
hci_cmd_sync_run_once() needs to indicate whether a queue item was added, so caller can know if callbacks are called, so it can avoid leaking resources.
Change the function to return -EEXIST if queue item already exists.
Modify all callsites vs. the changes. The only callsite is hci_abort_conn().
Stable-dep-of: 5761d003daa9 ("Bluetooth: hci_conn: hold conn reference in abort_conn_sync()")
--- net/bluetooth/hci_conn.c | 4 +++- net/bluetooth/hci_sync.c | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-)
net/bluetooth/hci_conn.c +3 -1
@@ -2899,6 +2899,7 @@ static int abort_conn_sync(struct hci_dev *hdev, void *data)int hci_abort_conn (struct hci_conn *conn,u8 reason) {struct hci_dev *hdev = conn->hdev; +int err;/* If abort_reason has already been set it means the connection is * already being aborted so don't attempt to overwrite it.
@@ -2920,5 +2921,6 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)* as a result to MGMT_OP_DISCONNECT/MGMT_OP_UNPAIR which does * already queue its callback on cmd_sync_work. */ -return hci_cmd_sync_run_once (hdev, abort_conn_sync, conn,NULL ); + err =hci_cmd_sync_run_once (hdev, abort_conn_sync, conn,NULL ); +return (err == -EEXIST ) ?0 : err; }
net/bluetooth/hci_sync.c +1 -1
@@ -849,7 +849,7 @@ int hci_cmd_sync_run_once(struct hci_dev *hdev, hci_cmd_sync_work_func_t func, void *data, hci_cmd_sync_work_destroy_t destroy) { if (hci_cmd_sync_lookup_entry(hdev, func, data, destroy)) - return 0; + return -EEXIST;return hci_cmd_sync_run (hdev, func, data, destroy); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 68/261 Bluetooth: hci_conn: hold conn reference in abort_conn_sync()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit 5761d003daa987ac81463f570713ce9c9dd204e5 ]
There is theoretical UAF if the conn is freed while the hci_sync task is running.
Hold refcount to avoid that.
--- net/bluetooth/hci_conn.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
net/bluetooth/hci_conn.c +11 -1
@@ -2896,6 +2896,13 @@ static int abort_conn_sync(struct hci_dev *hdev, void *data)return hci_abort_conn_sync (hdev, conn, conn->abort_reason); } +static void abort_conn_destroy (struct hci_dev *hdev,void *data,int err) +{ +struct hci_conn *conn = data; + +hci_conn_put (conn); +} +int hci_abort_conn (struct hci_conn *conn,u8 reason) {struct hci_dev *hdev = conn->hdev;
@@ -2921,6 +2928,9 @@ int hci_abort_conn(struct hci_conn *conn, u8 reason)* as a result to MGMT_OP_DISCONNECT/MGMT_OP_UNPAIR which does * already queue its callback on cmd_sync_work. */ - err =hci_cmd_sync_run_once (hdev, abort_conn_sync, conn,NULL ); + err =hci_cmd_sync_run_once (hdev, abort_conn_sync,hci_conn_get (conn), + abort_conn_destroy); +if (err) +hci_conn_put (conn);return (err == -EEXIST ) ?0 : err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 69/261 Bluetooth: hci_sync: fix hci_conn_del() use in hci_le_create_conn_sync
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit 2c1e4e00613dfd105f978be2276e5e265801ec9f ]
hci_conn_del() caller must hold hdev->lock, check the conn was not concurrently deleted, and usually inform socket the conn is going to be deleted.
Use hci_abort_conn_sync() instead of calling hci_conn_del() without locks etc.
--- net/bluetooth/hci_sync.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/bluetooth/hci_sync.c +3 -1
@@ -6582,7 +6582,9 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data)if (hci_dev_test_flag (hdev,HCI_LE_SCAN ) && hdev->le_scan_type ==LE_SCAN_ACTIVE && !hci_dev_test_flag (hdev,HCI_LE_SIMULTANEOUS_ROLES )) { -hci_conn_del (conn); + conn->state =BT_OPEN ; +hci_abort_conn_sync (hdev, conn, +HCI_ERROR_REJ_LIMITED_RESOURCES );hci_conn_put (conn);return -EBUSY ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 70/261 Bluetooth: hci_sync: remove unnecessary hci_conn_get in create_conn_sync
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit c0a9dcd2be398eee505d4b254ec3a845aa8ab189 ]
hci_conn_get() without already held reference is data race against concurrent deletion.
In previous patches, the refcount has been changed to be taken before starting the hci_sync task, so remove these extra get() + put() as they are not needed.
--- net/bluetooth/hci_sync.c | 13 ------------- 1 file changed, 13 deletions(-)
net/bluetooth/hci_sync.c +0 -13
@@ -6566,11 +6566,6 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data)bt_dev_dbg (hdev,"conn %p" , conn); -/* Hold a reference so conn stays valid for the HCI_CONN_CREATE -* clear_bit() at done. -*/ -hci_conn_get (conn); -clear_bit (HCI_CONN_SCANNING , &conn->flags); conn->state =BT_CONNECT ;
@@ -6585,7 +6580,6 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data) conn->state =BT_OPEN ;hci_abort_conn_sync (hdev, conn,HCI_ERROR_REJ_LIMITED_RESOURCES ); -hci_conn_put (conn);return -EBUSY ; }
@@ -6679,7 +6673,6 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data)/* Re-enable advertising after the connection attempt is finished. */ hci_resume_advertising_sync (hdev); -hci_conn_put (conn);return err; }
@@ -6958,11 +6951,6 @@ static int hci_acl_create_conn_sync(struct hci_dev *hdev, void *data)else cp.role_switch =0x00 ; -/* Hold a reference so conn stays valid for the HCI_CONN_CREATE -* clear_bit() below. -*/ -hci_conn_get (conn); -/* Mark create connection in flight so hci_cancel_connect_sync() can * cancel it while blocking on the connection complete event. */
@@ -6974,7 +6962,6 @@ static int hci_acl_create_conn_sync(struct hci_dev *hdev, void *data) conn->conn_timeout, NULL);clear_bit (HCI_CONN_CREATE , &conn->flags); -hci_conn_put (conn);return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 71/261 net: phylink: put link_gpio if phylink_create fails
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Marangi <[email protected]>
[ Upstream commit 0fe1e3e8f3380d7862296a73b528d164e96c76b8 ]
In phylink_create() if phylink_register_sfp() returns an error, link_gpio obtained by phylink_parse_fixedlink() is never released. While this is a very unlikely scenario, it's worth to fix/handle this.
This was present from the very first implementation of phylink but got relevant only with the introduction of ce0aa27ff3f6 ("sfp: add sfp-bus to bridge between network devices and sfp cages") where additional function were added after phylink_parse_fixedlink() making the release of link_gpio needed if such additional function errored out.
While at it, restructure the exit condition of phylink_create() with the goto pattern to reduce code duplication on handling error conditions.
--- drivers/net/phy/phylink.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-)
drivers/net/phy/phylink.c +15 -14
@@ -1635,8 +1635,8 @@ struct phylink *phylink_create(struct phylink_config *config, }else if (config->type ==PHYLINK_DEV ) { pl->dev = config->dev; }else { -kfree (pl); -return ERR_PTR (-EINVAL ); + ret = -EINVAL ; + goto free_pl; } pl->using_mac_select_pcs = using_mac_select_pcs;
@@ -1660,28 +1660,29 @@ struct phylink *phylink_create(struct phylink_config *config,phylink_validate (pl, pl->supported, &pl->link_config); ret =phylink_parse_mode (pl, fwnode); -if (ret <0 ) { -kfree (pl); -return ERR_PTR (ret); - } +if (ret <0 ) + goto free_pl;if (pl->cfg_link_an_mode ==MLO_AN_FIXED ) { ret =phylink_parse_fixedlink (pl, fwnode); -if (ret <0 ) { -kfree (pl); -return ERR_PTR (ret); - } +if (ret <0 ) + goto release_link_gpio; } pl->cur_link_an_mode = pl->cfg_link_an_mode; ret =phylink_register_sfp (pl, fwnode); -if (ret <0 ) { -kfree (pl); -return ERR_PTR (ret); - } +if (ret <0 ) + goto release_link_gpio;return pl; + +release_link_gpio: +if (pl->link_gpio) +gpiod_put (pl->link_gpio); +free_pl: +kfree (pl); +return ERR_PTR (ret); }EXPORT_SYMBOL_GPL (phylink_create);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 72/261 scsi: target: iblock: Fix wrong PR ops NULL check for PREEMPT/RELEASE
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: TanZheng <[email protected]>
[ Upstream commit 9c33222bd387312874fbe36ca8002e5c945b9653 ]
In the iblock_execute_pr_out() function, PRO_PREEMPT, PRO_PREEMPT_AND_ABORT, and PRO_RELEASE all perform callback capability checks through ops->pr_clear. The error check allows unimplemented hooks to pass through the gate, resulting dereferencing a NULL function pointer.
Check whether the hooks that need to be called are supported.
--- drivers/target/target_core_iblock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/target/target_core_iblock.c +3 -3
@@ -885,7 +885,7 @@ static sense_reason_t iblock_execute_pr_out(struct se_cmd *cmd, u8 sa, u64 key,break ;case PRO_PREEMPT :case PRO_PREEMPT_AND_ABORT : -if (!ops->pr_clear) { +if (!ops->pr_preempt) {pr_err ("block_device does not support pr_preempt.\n" );return TCM_UNSUPPORTED_SCSI_OPCODE ; }
@@ -895,8 +895,8 @@ static sense_reason_t iblock_execute_pr_out(struct se_cmd *cmd, u8 sa, u64 key, sa == PRO_PREEMPT_AND_ABORT);break ;case PRO_RELEASE : -if (!ops->pr_clear) { -pr_err ("block_device does not support pr_pclear.\n" ); +if (!ops->pr_release) { +pr_err ("block_device does not support pr_release.\n" );return TCM_UNSUPPORTED_SCSI_OPCODE ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 73/261 scsi: ufs: core: Cancel RTC work in active-active suspend
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit f71b4a30983b846b4075bf544e835121e70e6a43 ]
UFS RTC support schedules ufs_rtc_update_work to periodically update the device RTC. The work can issue query commands and access the UFS host controller.
A previous change moved the RTC work cancellation before the PRE_CHANGE vendor suspend callback to close a race in the common suspend path. However, the active-active path jumps directly to vops_suspend after flushing exception handling work and therefore bypasses the cancellation.
If the RTC work runs while the vendor suspend callback is gating or otherwise changing hardware state, it can access the controller during suspend and trigger an SError.
Cancel the RTC work before entering the vendor suspend callback in the active-active path. Since this path now cancels the work, move the RTC work scheduling outside the device and link state restoration block in the resume path. This restarts RTC updates after an active-active suspend and resume cycle.
--- drivers/ufs/core/ufshcd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/ufs/core/ufshcd.c +4 -2
@@ -9830,6 +9830,7 @@ static int __ufshcd_wl_suspend(struct ufs_hba *hba, enum ufs_pm_op pm_op) req_link_state == UIC_LINK_ACTIVE_STATE) {ufshcd_disable_auto_bkops (hba);flush_work (&hba->eeh_work); +cancel_delayed_work_sync (&hba->ufs_rtc_update_work); goto vops_suspend; }
@@ -10039,10 +10040,11 @@ static int __ufshcd_wl_resume(struct ufs_hba *hba, enum ufs_pm_op pm_op)if (ret) goto set_old_link_state;ufshcd_set_timestamp_attr (hba); -schedule_delayed_work (&hba->ufs_rtc_update_work, -msecs_to_jiffies (UFS_RTC_UPDATE_INTERVAL_MS )); } +schedule_delayed_work (&hba->ufs_rtc_update_work, +msecs_to_jiffies (UFS_RTC_UPDATE_INTERVAL_MS )); +if (ufshcd_keep_autobkops_enabled_except_suspend (hba))ufshcd_enable_auto_bkops (hba);else
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 74/261 scsi: zfcp: Fix memory leak during adapter release by destroying gid_pn_req
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Block <[email protected]>
[ Upstream commit b601fa590e667bd9643feed8c869b6b3e418480d ]
When releasing an adapter we don't free the mempool 'gid_pn_req' that is allocated during the enqueue. This leaks memory:
unreferenced object 0xd8d29297de700 (size 256):
comm "(udev-worker)", pid 2105, jiffies 4294945794
hex dump (first 32 bytes):
00 00 00 00 de ad 4e ad ff ff ff ff 00 00 00 00 ......N.........
ff ff ff ff ff ff ff ff 00 0d c4 5f 67 9d 99 e0 ..........._g...
backtrace (crc 4a5b5da2):
[<000dc45f64da418c>] kmemleak_alloc+0x6c/0xa0
[<000dc45f62b430aa>] __kmalloc_cache_node_noprof+0x36a/0x4d0
[<000dc45f629a535a>] mempool_create_node_noprof+0xaa/0x150
[<000dc45ee2c065e6>] zfcp_allocate_low_mem_buffers+0x96/0x370 [zfcp]
[<000dc45ee2c070f8>] zfcp_adapter_enqueue+0x598/0xd40 [zfcp]
[<000dc45ee2c08eb0>] zfcp_ccw_set_online+0x160/0x210 [zfcp]
[<000dc45f643d4762>] ccw_device_set_online+0x232/0xd80
[<000dc45f643d53d4>] online_store_recog_and_online+0x124/0x390
[<000dc45f643d8238>] online_store+0x298/0x5b0
[<000dc45f62eb0a04>] kernfs_fop_write_iter+0x2c4/0x480
[<000dc45f62c81150>] new_sync_write+0x370/0x4b0
[<000dc45f62c87abe>] vfs_write+0x43e/0x5b0
[<000dc45f62c87ff4>] ksys_write+0x114/0x1f0
[<000dc45f621c4a16>] do_syscall+0x2f6/0x430
[<000dc45f64d9d5d8>] __do_syscall+0xc8/0x1c0
[<000dc45f64dc2224>] system_call+0x74/0xa0Fix this by destroying the mempool during the adapter's release.
--- drivers/s390/scsi/zfcp_aux.c | 1 + 1 file changed, 1 insertion(+)
drivers/s390/scsi/zfcp_aux.c +1 -0
@@ -254,6 +254,7 @@ static int zfcp_allocate_low_mem_buffers(struct zfcp_adapter *adapter)static void zfcp_free_low_mem_buffers (struct zfcp_adapter *adapter) {mempool_destroy (adapter->pool.erp_req); +mempool_destroy (adapter->pool.gid_pn_req);mempool_destroy (adapter->pool.scsi_req);mempool_destroy (adapter->pool.scsi_abort);mempool_destroy (adapter->pool.qtcb_pool);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 75/261 scsi: target: Clear cmd_cnt when initial counter enrollment fails
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Romanovsky <[email protected]>
[ Upstream commit a8ddfd2425bbbafadae8700d63ed8a61a4109878 ]
When target_get_sess_cmd() fails during session shutdown because percpu_ref_tryget_live() returns false, the command keeps the se_cmd->cmd_cnt pointer that __target_init_cmd() assigned earlier without owning a reference. Final release through target_release_cmd_kref() then issues an unmatched percpu_ref_put().
Commit 8e288be8606a ("scsi: target: Pass in cmd counter to use during cmd setup") moved the cmd_cnt assignment ahead of the reference acquisition. Clear se_cmd->cmd_cnt whenever the initial target_get_sess_cmd() fails in target_init_cmd() and target_submit_tmr(), so release performs exactly one matching put per acquired reference.
--- drivers/target/target_core_transport.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/target/target_core_transport.c +10 -2
@@ -1670,6 +1670,7 @@ int target_init_cmd(struct se_cmd *se_cmd, struct se_session *se_sess, u32 data_length, int task_attr, int data_dir, int flags) { struct se_portal_group *se_tpg; +int ret; se_tpg = se_sess->se_tpg;BUG_ON (!se_tpg);
@@ -1699,7 +1700,11 @@ int target_init_cmd(struct se_cmd *se_cmd, struct se_session *se_sess,* necessary for fabrics using TARGET_SCF_ACK_KREF that expect a second * kref_put() to happen during fabric packet acknowledgement. */ -return target_get_sess_cmd (se_cmd, flags &TARGET_SCF_ACK_KREF ); + ret =target_get_sess_cmd (se_cmd, flags &TARGET_SCF_ACK_KREF ); +if (ret) + se_cmd->cmd_cnt =NULL ; + +return ret; }EXPORT_SYMBOL_GPL (target_init_cmd);
@@ -1994,8 +1999,10 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,* allocation failure. */ ret =core_tmr_alloc_req (se_cmd, fabric_tmr_ptr, tm_type, gfp); -if (ret <0 ) +if (ret <0 ) { + se_cmd->cmd_cnt =NULL ;return -ENOMEM ; + }if (tm_type ==TMR_ABORT_TASK ) se_cmd->se_tmr_req->ref_task_tag = tag;
@@ -2003,6 +2010,7 @@ int target_submit_tmr(struct se_cmd *se_cmd, struct se_session *se_sess,/* See target_submit_cmd for commentary */ ret =target_get_sess_cmd (se_cmd, flags &TARGET_SCF_ACK_KREF );if (ret) { + se_cmd->cmd_cnt =NULL ;core_tmr_release_req (se_cmd->se_tmr_req);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 76/261 net: sxgbe: free TX rings on RX allocation failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenguang Zhao <[email protected]>
[ Upstream commit c870f7e2890b9f78ac84515a9809cc5c183c975e ]
When RX descriptor ring allocation fails, init_dma_desc_rings() only frees the partially allocated RX rings and returns. The TX rings that were allocated earlier in the same function are leaked.
Rearrange error labels to clean up TX rings upon RX failures.
--- drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +4 -5
@@ -599,14 +599,13 @@ static int init_dma_desc_rings(struct net_device *netd)return 0 ; -txalloc_err: -while (queue_num--) -free_tx_ring (priv->device, priv->txq[queue_num], tx_rsize); -return ret; - rxalloc_err:while (queue_num--)free_rx_ring (priv->device, priv->rxq[queue_num], rx_rsize); + queue_num =SXGBE_TX_QUEUES ; +txalloc_err: +while (queue_num--) +free_tx_ring (priv->device, priv->txq[queue_num], tx_rsize);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 77/261 net: sxgbe: check descriptor ring allocation failures
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenguang Zhao <[email protected]>
[ Upstream commit 51b093a7ba27476e1f639455f005e8d2e75390e4 ]
sxgbe_open() ignores the return value of init_dma_desc_rings() and continues to program DMA with invalid ring addresses when allocation fails. Check the return value and disconnect the PHY on failure.
--- drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c +4 -1
@@ -1080,7 +1080,9 @@ static int sxgbe_open(struct net_device *dev) priv->dma_buf_sz =SXGBE_ALIGN (DMA_BUFFER_SIZE ); priv->tx_tc =TC_DEFAULT ; priv->rx_tc =TC_DEFAULT ; -init_dma_desc_rings (dev); + ret =init_dma_desc_rings (dev); +if (ret) + goto init_phy_error;/* DMA initialization and SW reset */ ret =sxgbe_init_dma_engine (priv);
@@ -1189,6 +1191,7 @@ static int sxgbe_open(struct net_device *dev) init_error:free_dma_desc_resources (priv); +init_phy_error:if (dev->phydev)phy_disconnect (dev->phydev); phy_error:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 78/261 can: isotp: check register_netdevice_notifier() error in module init
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Minhong He <[email protected]>
[ Upstream commit ef09a13c5afac41a3c4b5f22b8572820d9e7518c ]
Register the netdevice notifier before can_proto_register() and check the return value. If protocol registration fails, unregister the notifier before returning the error.
Align isotp_module_init() with the reordering already done for raw.c (commit c28b3bffe49e ("can: raw: process optimization in raw_init()")) and bcm.c (commit edd1a7e42f1d ("can: bcm: registration process optimization in bcm_module_init()")).
--- net/can/isotp.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
net/can/isotp.c +9 -4
@@ -1883,13 +1883,18 @@ static __init int isotp_module_init(void)pr_info ("can: isotp protocol (max_pdu_size %d)\n" , max_pdu_size); + err =register_netdevice_notifier (&canisotp_notifier); +if (err) +return err; + err =can_proto_register (&isotp_can_proto); -if (err <0 ) +if (err <0 ) {pr_err ("can: registration of isotp protocol failed %pe\n" ,ERR_PTR (err)); -else -register_netdevice_notifier (&canisotp_notifier); +unregister_netdevice_notifier (&canisotp_notifier); +return err; + } -return err; +return 0 ; } static __exit void isotp_module_exit(void)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 79/261 tracing/mmiotrace: Reset dropped_count in mmio_reset_data()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <[email protected]>
[ Upstream commit c786d2bdf1f3964deee192ad942dee2a741c1e2c ]
mmio_reset_data() is called during tracer initialization, reset, and start. While it resets overrun_detected and prev_overruns, it neglects to reset dropped_count. Consequently, dropped event counts from prior tracing sessions persist in dropped_count and corrupt overrun reports in subsequent runs.
Fix this by explicitly calling atomic_set(&dropped_count, 0) in mmio_reset_data().
--- kernel/trace/trace_mmiotrace.c | 1 + 1 file changed, 1 insertion(+)
kernel/trace/trace_mmiotrace.c +1 -0
@@ -29,6 +29,7 @@ static void mmio_reset_data(struct trace_array *tr) { overrun_detected = false; prev_overruns =0 ; +atomic_set (&dropped_count,0 );tracing_reset_online_cpus (&tr->array_buffer); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 80/261 accel/qaic: use sizeof(*trans_hdr) for transaction length check
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muhammad Bilal <[email protected]>
[ Upstream commit d6c075f797a672a6e3bd2fd44aee713801698ec2 ]
In encode_message() the per-transaction lower-bound check compares trans_hdr->len against sizeof(trans_hdr), i.e. the size of the pointer, instead of sizeof(*trans_hdr), the size of struct qaic_manage_trans_hdr.
Every other length check in this file (encode_message() at the loop guard, decode_message(), etc.) correctly uses sizeof(*trans_hdr), so this is an inconsistency. On 64-bit builds the pointer and the struct are both 8 bytes, so the check is correct by coincidence and there is no behavioural change. On 32-bit builds the pointer is 4 bytes, which weakens the minimum-length check below the 8-byte header size.
Use sizeof(*trans_hdr) so the check validates against the actual transaction header size on all builds.
--- drivers/accel/qaic/qaic_control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/accel/qaic/qaic_control.c +1 -1
@@ -782,7 +782,7 @@ static int encode_message(struct qaic_device *qdev, struct manage_msg *user_msg,break ; } trans_hdr = (struct qaic_manage_trans_hdr *)(user_msg->data + user_len); -if (trans_hdr->len <sizeof (trans_hdr) || +if (trans_hdr->len <sizeof (*trans_hdr) ||size_add (user_len, trans_hdr->len) > user_msg->len) { ret = -EINVAL ;break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 81/261 net: dsa: mt7530: error out on failed reads in MT7531 PHY polling
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Golle <[email protected]>
[ Upstream commit 77a9ebe8818cf6dd1699bd6728cb5d66307801d7 ]
The MT7531 indirect PHY access functions poll MT7531_PHY_IAC through a helper which returns 0 when the underlying read fails, so a failed bus transaction clears MT7531_PHY_ACS_ST and the access carries on, returning garbage PHY register data to phylib.
Poll using regmap_read_poll_timeout(), which stops on read errors and propagates them. These functions hold the MDIO bus lock across the whole sequence, so the unlocked regmap accesses remain correct. Remove the now-unused _mt7530_unlocked_read().
--- drivers/net/dsa/mt7530.c | 58 ++++++++++++++-------------------------- 1 file changed, 20 insertions(+), 38 deletions(-)
drivers/net/dsa/mt7530.c +20 -38
@@ -233,12 +233,6 @@ mt7530_write(struct mt7530_priv *priv, u32 reg, u32 val)mt7530_mutex_unlock (priv); } -static u32 -_mt7530_unlocked_read (struct mt7530_dummy_poll *p) -{ -return mt7530_mii_read (p->priv, p->reg); -} -static u32 _mt7530_read (struct mt7530_dummy_poll *p) {
@@ -628,16 +622,13 @@ static int mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad, int regnum) { - struct mt7530_dummy_poll p; u32 reg, val;int ret; -INIT_MT7530_DUMMY_POLL (&p, priv,MT7531_PHY_IAC ); -mt7530_mutex_lock (priv); - ret =readx_poll_timeout (_mt7530_unlocked_read, &p, val, - !(val &MT7531_PHY_ACS_ST ),20 ,100000 ); + ret =regmap_read_poll_timeout (priv->regmap,MT7531_PHY_IAC , val, + !(val &MT7531_PHY_ACS_ST ),20 ,100000 );if (ret <0 ) {dev_err (priv->dev,"poll timeout\n" ); goto out;
@@ -647,8 +638,8 @@ mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,MT7531_MDIO_DEV_ADDR (devad) | regnum;mt7530_mii_write (priv,MT7531_PHY_IAC , reg |MT7531_PHY_ACS_ST ); - ret =readx_poll_timeout (_mt7530_unlocked_read, &p, val, - !(val &MT7531_PHY_ACS_ST ),20 ,100000 ); + ret =regmap_read_poll_timeout (priv->regmap,MT7531_PHY_IAC , val, + !(val &MT7531_PHY_ACS_ST ),20 ,100000 );if (ret <0 ) {dev_err (priv->dev,"poll timeout\n" ); goto out;
@@ -658,8 +649,8 @@ mt7531_ind_c45_phy_read(struct mt7530_priv *priv, int port, int devad,MT7531_MDIO_DEV_ADDR (devad);mt7530_mii_write (priv,MT7531_PHY_IAC , reg |MT7531_PHY_ACS_ST ); - ret =readx_poll_timeout (_mt7530_unlocked_read, &p, val, - !(val &MT7531_PHY_ACS_ST ),20 ,100000 ); + ret =regmap_read_poll_timeout (priv->regmap,MT7531_PHY_IAC , val, + !(val &MT7531_PHY_ACS_ST ),20 ,100000 );if (ret <0 ) {dev_err (priv->dev,"poll timeout\n" ); goto out;
@@ -676,16 +667,13 @@ static int mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad, int regnum, u16 data) { - struct mt7530_dummy_poll p; u32 val, reg;int ret; -INIT_MT7530_DUMMY_POLL (&p, priv,MT7531_PHY_IAC ); -mt7530_mutex_lock (priv); - ret =readx_poll_timeout (_mt7530_unlocked_read, &p, val, - !(val &MT7531_PHY_ACS_ST ),20 ,100000 ); + ret =regmap_read_poll_timeout (priv->regmap,MT7531_PHY_IAC , val, + !(val &MT7531_PHY_ACS_ST ),20 ,100000 );if (ret <0 ) {dev_err (priv->dev,"poll timeout\n" ); goto out;
@@ -695,8 +683,8 @@ mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,MT7531_MDIO_DEV_ADDR (devad) | regnum;mt7530_mii_write (priv,MT7531_PHY_IAC , reg |MT7531_PHY_ACS_ST ); - ret =readx_poll_timeout (_mt7530_unlocked_read, &p, val, - !(val &MT7531_PHY_ACS_ST ),20 ,100000 ); + ret =regmap_read_poll_timeout (priv->regmap,MT7531_PHY_IAC , val, + !(val &MT7531_PHY_ACS_ST ),20 ,100000 );if (ret <0 ) {dev_err (priv->dev,"poll timeout\n" ); goto out;
@@ -706,8 +694,8 @@ mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,MT7531_MDIO_DEV_ADDR (devad) | data;mt7530_mii_write (priv,MT7531_PHY_IAC , reg |MT7531_PHY_ACS_ST ); - ret =readx_poll_timeout (_mt7530_unlocked_read, &p, val, - !(val &MT7531_PHY_ACS_ST ),20 ,100000 ); + ret =regmap_read_poll_timeout (priv->regmap,MT7531_PHY_IAC , val, + !(val &MT7531_PHY_ACS_ST ),20 ,100000 );if (ret <0 ) {dev_err (priv->dev,"poll timeout\n" ); goto out;
@@ -722,16 +710,13 @@ mt7531_ind_c45_phy_write(struct mt7530_priv *priv, int port, int devad,static int mt7531_ind_c22_phy_read (struct mt7530_priv *priv,int port,int regnum) { -struct mt7530_dummy_poll p;int ret;u32 val; -INIT_MT7530_DUMMY_POLL (&p, priv,MT7531_PHY_IAC ); -mt7530_mutex_lock (priv); - ret =readx_poll_timeout (_mt7530_unlocked_read, &p, val, - !(val &MT7531_PHY_ACS_ST ),20 ,100000 ); + ret =regmap_read_poll_timeout (priv->regmap,MT7531_PHY_IAC , val, + !(val &MT7531_PHY_ACS_ST ),20 ,100000 );if (ret <0 ) {dev_err (priv->dev,"poll timeout\n" ); goto out;
@@ -742,8 +727,8 @@ mt7531_ind_c22_phy_read(struct mt7530_priv *priv, int port, int regnum)mt7530_mii_write (priv,MT7531_PHY_IAC , val |MT7531_PHY_ACS_ST ); - ret =readx_poll_timeout (_mt7530_unlocked_read, &p, val, - !(val &MT7531_PHY_ACS_ST ),20 ,100000 ); + ret =regmap_read_poll_timeout (priv->regmap,MT7531_PHY_IAC , val, + !(val &MT7531_PHY_ACS_ST ),20 ,100000 );if (ret <0 ) {dev_err (priv->dev,"poll timeout\n" ); goto out;
@@ -760,16 +745,13 @@ static int mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum, u16 data) { - struct mt7530_dummy_poll p; int ret;u32 reg; -INIT_MT7530_DUMMY_POLL (&p, priv,MT7531_PHY_IAC ); -mt7530_mutex_lock (priv); - ret =readx_poll_timeout (_mt7530_unlocked_read, &p, reg, - !(reg &MT7531_PHY_ACS_ST ),20 ,100000 ); + ret =regmap_read_poll_timeout (priv->regmap,MT7531_PHY_IAC , reg, + !(reg &MT7531_PHY_ACS_ST ),20 ,100000 );if (ret <0 ) {dev_err (priv->dev,"poll timeout\n" ); goto out;
@@ -780,8 +762,8 @@ mt7531_ind_c22_phy_write(struct mt7530_priv *priv, int port, int regnum,mt7530_mii_write (priv,MT7531_PHY_IAC , reg |MT7531_PHY_ACS_ST ); - ret =readx_poll_timeout (_mt7530_unlocked_read, &p, reg, - !(reg &MT7531_PHY_ACS_ST ),20 ,100000 ); + ret =regmap_read_poll_timeout (priv->regmap,MT7531_PHY_IAC , reg, + !(reg &MT7531_PHY_ACS_ST ),20 ,100000 );if (ret <0 ) {dev_err (priv->dev,"poll timeout\n" ); goto out;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 82/261 octeontx2-pf: Set correct sequence for carrier off and tx queue stop
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Suman Ghosh <[email protected]>
[ Upstream commit 16809472409d998afcda402e32b8229b389337c4 ]
During link down event, we were doing netif_tx_stop_all_queues() first and then netif_carrier_off(). This can cause a potential race since carrier is still on during down event. This patch reverse the calling order to fix the issue.
--- drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c +1 -1
@@ -842,8 +842,8 @@ static void otx2_handle_link_event(struct otx2_nic *pf)netif_carrier_on (netdev);netif_tx_start_all_queues (netdev); }else { -netif_tx_stop_all_queues (netdev);netif_carrier_off (netdev); +netif_tx_stop_all_queues (netdev); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 83/261 qede: sync udp_tunnel ports outside qede_lock in the recovery path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Denis V. Lunev <[email protected]>
[ Upstream commit 451c9075d6c53f2438d110addbeeeea6fac18567 ]
A TX timeout on a qede NIC that has VXLAN/GENEVE tunnel ports configured wedges the rtnetlink control plane of the whole machine:
NETDEV WATCHDOG: ens6f1 (qede): transmit queue 2 timed out 10226 ms [qede_tx_timeout:586(ens6f1)]TX timeout on queue 2! [qede_recovery_handler:2665(ens6f0)]Starting a recovery process
The recovery path deadlocks on the driver's own mutex:
qede_sp_task
rtnl_lock()
mutex_lock(&edev->qede_lock) <- taken
qede_recovery_handler
qede_load
udp_tunnel_nic_reset_ntf
__udp_tunnel_nic_device_sync
info->sync_table == qede_udp_tunnel_sync
mutex_lock(&edev->qede_lock) <- same task: deadlockThe mutex is not recursive, so the kworker blocks on itself with rtnl_lock held, and neither lock is ever released. Every task that calls rtnl_lock() afterwards (ip, ovs-vswitchd, lldpad, IPv6 addrconf, sshd) blocks forever while the node still answers ping. In a vmcore from an affected production node rtnl_mutex.owner decodes to the very kworker blocked at the innermost mutex_lock() above.
Re-sync the tunnel ports from qede_sp_task() after the internal lock is dropped, still under rtnl_lock as the udp_tunnel API requires. This mirrors qede_open(), which calls udp_tunnel_nic_reset_ntf() under rtnl without the internal lock.
qede_recovery_handler() now returns whether it has successfully reloaded an open device, and the caller re-syncs the ports only in that case. This keeps the old gating exactly: a device that was down or a failed recovery returns false, as those paths never reached the udp_tunnel_nic_reset_ntf() call before either.
This was the only user of the qede_lock()/qede_unlock() helpers, so remove them.
--- drivers/net/ethernet/qlogic/qede/qede_main.c | 44 ++++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-)
drivers/net/ethernet/qlogic/qede/qede_main.c +22 -22
@@ -107,7 +107,7 @@ static void qede_remove(struct pci_dev *pdev);static void qede_shutdown (struct pci_dev *pdev);static void qede_link_update (void *dev,struct qed_link_output *link);static void qede_schedule_recovery_handler (void *dev); -static void qede_recovery_handler (struct qede_dev *edev); +static bool qede_recovery_handler (struct qede_dev *edev);static void qede_schedule_hw_err_handler (void *dev,enum qed_hw_err_type err_type);static void qede_get_eth_tlv_data (void *edev,void *data);
@@ -1065,21 +1065,6 @@ void __qede_unlock(struct qede_dev *edev)mutex_unlock (&edev->qede_lock); } -/* This version of the lock should be used when acquiring the RTNL lock is also -* needed in addition to the internal qede lock. -*/ -static void qede_lock (struct qede_dev *edev) -{ -rtnl_lock (); -__qede_lock (edev); -} - -static void qede_unlock (struct qede_dev *edev) -{ -__qede_unlock (edev); -rtnl_unlock (); -} -static void qede_periodic_task (struct work_struct *work) { struct qede_dev *edev = container_of(work, struct qede_dev,
@@ -1116,6 +1101,8 @@ static void qede_sp_task(struct work_struct *work)*/ if (test_and_clear_bit (QEDE_SP_RECOVERY , &edev->sp_flags)) { +bool reloaded; +cancel_delayed_work_sync (&edev->periodic_task);#ifdef CONFIG_QED_SRIOV /* SRIOV must be disabled outside the lock to avoid a deadlock.
@@ -1124,9 +1111,17 @@ static void qede_sp_task(struct work_struct *work)if (pci_num_vf (edev->pdev))qede_sriov_configure (edev->pdev,0 );#endif -qede_lock (edev); -qede_recovery_handler (edev); -qede_unlock (edev); +rtnl_lock (); +__qede_lock (edev); + reloaded =qede_recovery_handler (edev); +__qede_unlock (edev); + +/* The udp_tunnel core synchronously calls back into +* qede_udp_tunnel_sync(), which takes the qede lock. +*/ +if (reloaded) +udp_tunnel_nic_reset_ntf (edev->ndev); +rtnl_unlock (); }__qede_lock (edev);
@@ -2667,9 +2662,13 @@ static void qede_recovery_failed(struct qede_dev *edev) edev->ops->common->set_power_state (edev->cdev, PCI_D3hot); } -static void qede_recovery_handler (struct qede_dev *edev) +/* Returns true if an open device was successfully reloaded and its +* udp_tunnel ports need to be re-synced by the caller. +*/ +static bool qede_recovery_handler (struct qede_dev *edev) {u32 curr_state = edev->state; +bool reloaded = false;int rc;DP_NOTICE (edev,"Starting a recovery process\n" );
@@ -2699,17 +2698,18 @@ static void qede_recovery_handler(struct qede_dev *edev) goto err;qede_config_rx_mode (edev->ndev); -udp_tunnel_nic_reset_ntf (edev->ndev); + reloaded = true; } edev->state = curr_state;DP_NOTICE (edev,"Recovery handling is done\n" ); -return ; +return reloaded; err:qede_recovery_failed (edev); +return false; }static void qede_atomic_hw_err_handler (struct qede_dev *edev)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 84/261 ksmbd: return success for deferred final close
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit c5db4de8988f1a621556ca5c4537f77b766ca07d ]
ksmbd_close_fd() marks an open file as FP_CLOSED and drops the file table reference. If another in-flight request still holds a reference, the final close is deferred until that request drops its reference.
The function currently returns -EINVAL in that deferred-final-close case because fp is cleared when the reference count does not reach zero. That turns a valid close into STATUS_FILE_CLOSED.
smb2.compound_find.compound_find_close sends QUERY_DIRECTORY and then closes the same directory handle before receiving the find response. The query holds a reference while it builds the response, so close must mark the handle closed and return success even though final teardown is delayed. Track whether the handle was successfully transitioned to FP_CLOSED and return success when only the final close is deferred.
Stable-dep-of: e7188199eff4 ("ksmbd: fix use-after-free in __close_file_table_ids()")
--- fs/smb/server/vfs_cache.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/smb/server/vfs_cache.c +3 -1
@@ -487,6 +487,7 @@ int ksmbd_close_fd(struct ksmbd_work *work, u64 id) {struct ksmbd_file *fp;struct ksmbd_file_table *ft; +bool closed = false;if (!has_file_id (id))return 0 ;
@@ -501,6 +502,7 @@ int ksmbd_close_fd(struct ksmbd_work *work, u64 id) fp =NULL ; else { fp->f_state =FP_CLOSED ; + closed = true;if (!atomic_dec_and_test (&fp->refcount)) fp =NULL ; }
@@ -508,7 +510,7 @@ int ksmbd_close_fd(struct ksmbd_work *work, u64 id)write_unlock (&ft->lock);if (!fp) -return -EINVAL ; +return closed ?0 : -EINVAL ;__put_fd_final (work, fp);return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 85/261 ksmbd: fix use-after-free in __close_file_table_ids()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit e7188199eff46a636f3436356f0aae039be6dd66 ]
A ksmbd_file can remain alive after logical close while another session holds a temporary reference obtained through ksmbd_lookup_fd_inode(). ksmbd_close_fd() currently marks the file closed and drops the idr-owned reference, but leaves the pointer published in the closing session's idr until the final reference is dropped.
If the foreign holder performs the final ksmbd_fd_put(), __put_fd_final() supplies the foreign session's file table to __ksmbd_close_fd(). The object is then freed without being removed from its owner's idr, and the owner session later dereferences the stale pointer during file-table teardown.
Remove the volatile id from the owner's idr while ksmbd_close_fd() still holds that table's lock, and clear volatile_id before dropping the idr-owned reference. A later foreign final put then only performs physical destruction and cannot remove the object from the wrong table.
--- fs/smb/server/vfs_cache.c | 2 ++ 1 file changed, 2 insertions(+)
fs/smb/server/vfs_cache.c +2 -0
@@ -502,6 +502,8 @@ int ksmbd_close_fd(struct ksmbd_work *work, u64 id) fp =NULL ; else { fp->f_state =FP_CLOSED ; +idr_remove (ft->idr, id); + fp->volatile_id =KSMBD_NO_FID ; closed = true;if (!atomic_dec_and_test (&fp->refcount)) fp =NULL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 86/261 ipv6: fib6: fix NULL deref in fib6_walk_continue() on multi-batch dump
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengfei Zhang <[email protected]>
commit 9facb861dc6b9b9ea9793ef5032a9a826f7a4229 upstream.
inet6_dump_fib() saves its progress in cb->args[1] as a positional index within the current hash chain. Between batches, a concurrent fib6_new_table() can insert a new table at the chain head, shifting all existing entries. The saved index then lands on a different table, causing fib6_dump_table() to set w->root to the wrong table while w->node still points into the previous one. fib6_walk_continue() dereferences w->node->parent (NULL) and panics:
BUG: kernel NULL pointer dereference, address: 0000000000000008 RIP: 0010:fib6_walk_continue+0x6e/0x170 Call Trace: <TASK> fib6_dump_table.isra.0+0xc5/0x240 inet6_dump_fib+0xf6/0x420 rtnl_dumpit+0x30/0xa0 netlink_dump+0x15b/0x460 netlink_recvmsg+0x1d6/0x2a0 ____sys_recvmsg+0x17a/0x190
Fix by storing tb->tb6_id in cb->args[1] instead of a positional index. On resume, skip entries until the id matches; a concurrent head-insert can never match the saved id, so the walker always resumes on the correct table.
[Adapted to 5.10/6.1/6.6: inet6_dump_fib() there predates 22e36ea9f5d7
and 5fc68320c1fb, so the return variable is "res" not "err" and the RCU-protected hash walk exits via "out_unlock" instead of "unlock". Context-only change; the fix itself is identical.]
--- net/ipv6/ip6_fib.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
net/ipv6/ip6_fib.c +8 -9
@@ -627,11 +627,11 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb)const struct nlmsghdr *nlh = cb->nlh;struct net *net =sock_net (skb->sk);unsigned int h, s_h; -unsigned int e =0 , s_e;struct fib6_walker *w;struct fib6_table *tb;struct hlist_head *head;int res =0 ; +u32 s_id;if (cb->strict_check) {int err;
@@ -689,25 +689,24 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) } s_h = cb->args[0 ]; - s_e = cb->args[1 ]; + s_id = cb->args[1 ];rcu_read_lock (); -for (h = s_h; h <FIB6_TABLE_HASHSZ ; h++, s_e =0 ) { - e =0 ; +for (h = s_h; h <FIB6_TABLE_HASHSZ ; h++, s_id =0 ) { head = &net->ipv6.fib_table_hash[h];hlist_for_each_entry_rcu (tb, head, tb6_hlist) { -if (e < s_e) - goto next; +if (s_id && tb->tb6_id != s_id) +continue ; + + s_id =0 ; + cb->args[1 ] = tb->tb6_id; res =fib6_dump_table (tb, skb, cb);if (res !=0 ) goto out_unlock; -next: - e++; } } out_unlock:rcu_read_unlock (); - cb->args[1 ] = e; cb->args[0 ] = h; out: res = res <0 ? res : skb->len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 87/261 rhashtable: clear stale iter->p on table restart
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang (Microsoft) <[email protected]>
[ Upstream commit 8173f7e2ce67e6ca1d4763f3da14e5b01ce77456 ]
rhashtable_walk_start_check() has two restart paths when resuming a walk. When iter->walker.tbl is valid, it re-validates iter->p against the table and sets iter->p = NULL if the object is gone. When iter->walker.tbl is NULL (table was freed during resize), it resets slot and skip but forgets to clear iter->p.
rhashtable_walk_next() then dereferences the stale iter->p, reading freed memory. This is a use-after-free.
Any caller that does multi-fragment rhashtable walks across walk_stop/walk_start boundaries is affected. Concrete cases include netlink_diag (__netlink_diag_dump in net/netlink/diag.c) and TIPC (tipc_nl_sk_walk in net/tipc/socket.c).
Crash stack (netlink_diag):
BUG: KASAN: slab-use-after-free in rhashtable_walk_next+0x365/0x3c0 Read of size 8 at addr ffff88801a9d2438 (freed kmalloc-2k, offset 1080) Call Trace: rhashtable_walk_next+0x365/0x3c0 (lib/rhashtable.c:1016) __netlink_diag_dump+0x160/0x760 (net/netlink/diag.c:122) netlink_diag_dump+0xc2/0x240 netlink_dump+0x5bc/0x1270 netlink_recvmsg+0x7a3/0x980 sock_recvmsg+0x1bc/0x200 __sys_recvfrom+0x1d4/0x2c0
--- lib/rhashtable.c | 1 + 1 file changed, 1 insertion(+)
lib/rhashtable.c +1 -0
@@ -734,6 +734,7 @@ int rhashtable_walk_start_check(struct rhashtable_iter *iter) iter->walker.tbl =rht_dereference_rcu (ht->tbl, ht); iter->slot =0 ; iter->skip =0 ; + iter->p =NULL ;return -EAGAIN ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 88/261 pinctrl: microchip-sgpio: add missing select REGMAP_MMIO
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Boortz <[email protected]>
commit 25cb6e9a13123d1039cdc75b446ac52e1ebdc26d upstream.
The driver calls ocelot_regmap_from_resource() via <linux/mfd/ocelot.h>, which internally uses devm_regmap_init_mmio() and requires REGMAP_MMIO. The Kconfig entry does not select REGMAP_MMIO, causing a build failure when no other driver in the config happens to pull in REGMAP_MMIO:
include/linux/mfd/ocelot.h:34:24: error: implicit declaration of function 'devm_regmap_init_mmio'
Found by randconfig testing on arm64; tinyconfig reproducer below.
--- drivers/pinctrl/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/pinctrl/Kconfig +1 -0
@@ -188,6 +188,7 @@ config PINCTRL_EQUILIBRIUM select GENERIC_PINCONF select GENERIC_PINCTRL_GROUPS select GENERIC_PINMUX_FUNCTIONS + select REGMAP_MMIO help Equilibrium driver is a pinctrl and GPIO driver for Intel Lightning Mountain network processor SoC that supports both the GPIO and pin
Greg Kroah-Hartman
maintainerPATCH 89/261 pinctrl: devicetree: dont free uninitialized dev_name on error path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karl Mehltretter <[email protected]>
commit 015b5bcbcb622b32317642be91a7f79aa5413649 upstream.
dt_remember_or_free_map() duplicates dev_name for each map entry. If kstrdup_const() fails, dt_free_map() frees dev_name in all num_maps entries, including entries that have not been initialized.
Some pinctrl drivers, including pinctrl-imx, allocate the map with kmalloc() and leave dev_name for the core to initialize. The untouched entries therefore contain uninitialized data which is passed to kfree_const().
Reproduced on qemu's mcimx6ul-evk (pinctrl-imx) with failslab injection while binding the pinctrl-consuming device, under KASAN:
BUG: KASAN: double-free in dt_free_map+0x34/0xa4 Free of addr c425a900 by task init/1 kfree from dt_free_map+0x34/0xa4 dt_free_map from dt_remember_or_free_map+0x184/0x198 dt_remember_or_free_map from pinctrl_dt_to_map+0x33c/0x4c8 pinctrl_dt_to_map from create_pinctrl+0x9c/0x5c0
Initialize all dev_name fields to NULL before duplicating the device name, making the full-map cleanup safe after a partial failure.
--- drivers/pinctrl/devicetree.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/pinctrl/devicetree.c +4 -0
@@ -69,6 +69,10 @@ static int dt_remember_or_free_map(strucint i;struct pinctrl_dt_map *dt_map; +/* Initialize dev_name before any allocation can fail */ +for (i =0 ; i < num_maps; i++) + map[i].dev_name =NULL ; +/* Initialize common mapping table entry fields */ for (i =0 ; i < num_maps; i++) {const char *devname;
Greg Kroah-Hartman
maintainerPATCH 90/261 erofs: cap LZMA stream pool size
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit c9b47e6b23114e939b17f818471c7a46e59006e7 upstream.
fs/erofs/decompressor_lzma.c sizes the module-global MicroLZMA stream pool from num_possible_cpus() when the lzma_streams module parameter is unset, then z_erofs_load_lzma_config() preallocates one image-supplied dictionary per stream, accepting dictionaries up to 8 MiB. On high-CPU systems, a small EROFS image can pin hundreds of MiB of vmalloc-backed decoder state until the erofs module is unloaded.
Impact: An EROFS image mounted by the system can pin up to 8 MiB of vmalloc memory per LZMA stream, either as intended or unexpectedly.
Bound the default stream count by a new CONFIG_EROFS_FS_ZIP_LZMA_DEFAULT_MAX_STREAMS option, default 16, so the worst-case default preallocation is 128 MiB if the number of CPUs is no less than 16 while preserving the existing per-image dictionary limit. An explicit lzma_streams module parameter is still honoured as-is, so administrators who deliberately size the pool are not affected.
--- fs/erofs/Kconfig | 14 ++++++++++++++ fs/erofs/decompressor_lzma.c | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-)
fs/erofs/Kconfig +14 -0
@@ -100,6 +100,20 @@ config EROFS_FS_ZIP_LZMA If unsure, say N. +config EROFS_FS_ZIP_LZMA_DEFAULT_MAX_STREAMS + int "EROFS LZMA default maximum decompression streams" + depends on EROFS_FS_ZIP_LZMA + range 1 NR_CPUS + default 16 + help + By default EROFS allocates one LZMA decompression stream per CPU. + Each stream can hold a dictionary of up to 8 MiB taken from the + mounted image, so on systems with many CPUs this can reserve a lot + of memory. This caps the default; the lzma_streams module parameter + still overrides it. + + If unsure, keep the default of 16. + config EROFS_FS_ZIP_DEFLATE bool "EROFS DEFLATE compressed data support" depends on EROFS_FS_ZIP
fs/erofs/decompressor_lzma.c +2 -1
@@ -53,7 +53,8 @@ int __init z_erofs_lzma_init(void)/* by default, use # of possible CPUs instead */ if (!z_erofs_lzma_nstrms) - z_erofs_lzma_nstrms =num_possible_cpus (); + z_erofs_lzma_nstrms = min_t(unsigned int, num_possible_cpus(), +CONFIG_EROFS_FS_ZIP_LZMA_DEFAULT_MAX_STREAMS );for (i =0 ; i < z_erofs_lzma_nstrms; ++i) {struct z_erofs_lzma *strm =kzalloc (sizeof (*strm),GFP_KERNEL );
Greg Kroah-Hartman
maintainerPATCH 91/261 pinctrl: bm1880: add missing select GENERIC_PINCONF
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Boortz <[email protected]>
commit dad6e107b3cd9d20514e7799b7ad8674f81e3f30 upstream.
drivers/pinctrl/pinctrl-bm1880.c initialises its pinconf_ops with .is_generic = true, but that field is only present when CONFIG_GENERIC_PINCONF is enabled (guarded by #ifdef in pinconf.h). The Kconfig entry for PINCTRL_BM1880 never selects GENERIC_PINCONF, so any config that enables CONFIG_PINCTRL_BM1880=y without CONFIG_GENERIC_PINCONF=y fails to compile:
drivers/pinctrl/pinctrl-bm1880.c:1288:10: error: 'const struct pinconf_ops' has no member named 'is_generic'
Found by randconfig testing on arm64; tinyconfig reproducer below. Add the missing select to fix the build.
--- drivers/pinctrl/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/pinctrl/Kconfig +1 -0
@@ -132,6 +132,7 @@ config PINCTRL_BM1880 depends on OF && (ARCH_BITMAIN || COMPILE_TEST) default ARCH_BITMAIN select PINMUX + select GENERIC_PINCONF help Pinctrl driver for Bitmain BM1880 SoC.
Greg Kroah-Hartman
maintainerPATCH 92/261 mm/percpu-km: fix bitmap overflow and accounting in pcpu_create_chunk()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zi Yan <[email protected]>
commit 89b1b79c308818a715e75f28744b70d8940a07c9 upstream.
In pcpu_create_chunk(), nr_pages is the total contiguous backing allocation, i.e., nr_units * pcpu_unit_pages, but pcpu_chunk_populated() uses it to set chunk->populated, whose size is pcpu_unit_pages, bitmap. Since bit N in chunk->populated means page offset N inside every unit is backed. When nr_units > 1, the function writes beyond chunk->populated. Fix it by using chunk->nr_pages.
It also fixes the global pcpu_nr_empty_pop_pages accounting, since pcpu_balance_free() only iterates up to chunk->nr_pages.
Commit a63d4ac4ab609 ("percpu: make percpu-km set chunk->populated bitmap properly") introduced the bitmap overflow issue. Later, commit b539b87fed37f ("percpu: implmeent pcpu_nr_empty_pop_pages and chunk->nr_populated") added pcpu_nr_empty_pop_pages and caused the accounting issue.
--- mm/percpu-km.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/percpu-km.c +1 -1
@@ -75,7 +75,7 @@ static struct pcpu_chunk *pcpu_create_ch chunk->base_addr =page_address (pages);spin_lock_irqsave (&pcpu_lock, flags); -pcpu_chunk_populated (chunk,0 , nr_pages); +pcpu_chunk_populated (chunk,0 , chunk->nr_pages);spin_unlock_irqrestore (&pcpu_lock, flags);pcpu_stats_chunk_alloc ();
Greg Kroah-Hartman
maintainerPATCH 93/261 mm/hugetlb: fix list corruption in allocate_file_region_entries()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiangfeng Cai <[email protected]>
commit dd9623f58ec702a07b2d67179d6fcea79c52231a upstream.
allocate_file_region_entries() tops up resv->region_cache with freshly allocated file_region descriptors. The allocation uses GFP_KERNEL, so resv->lock is dropped around it: the new entries are gathered on a stack-local list head, allocated_regions, and spliced into resv->region_cache once the lock is re-acquired.
The splice used list_splice(), which moves the entries but does not re-initialize the source head, so allocated_regions is left pointing at an entry that now lives on resv->region_cache. The top-up runs in a while loop that re-checks the cache deficit after re-acquiring the lock. For a shared mapping the resv_map is shared by every mapper of the hugetlbfs inode, so a concurrent region_chg()/region_add()/region_del() on the same resv_map can consume cache entries during the unlocked window and force a second iteration. That iteration calls list_add() on the stale head and corrupts the list; with CONFIG_DEBUG_LIST the __list_add_valid() check trips:
list_add corruption. next->prev should be prev (ffffc900011ff7f8), but was ffff88814c281460. (next=ffff88814c545640). kernel BUG at lib/list_debug.c:31!
allocate_file_region_entries+0x191/0x420 region_chg+0x267/0x300 hugetlb_reserve_pages+0x387/0xc80 hugetlbfs_file_mmap+0x2ce/0x3f0 mmap_region+0x1348/0x1a80 do_mmap+0x85e/0xb90 vm_mmap_pgoff+0x18c/0x330 ksys_mmap_pgoff+0x2a1/0x3e0 do_syscall_64+0xd7/0x420
Without CONFIG_DEBUG_LIST the bad list_add() silently links a kernel-stack address into resv->region_cache, leading to later use-after-free.
This was observed as a real host panic on a dense KVM host where a QEMU guest-RAM hugetlbfs file was mapped MAP_SHARED by both QEMU and a separate SPDK/DPDK vhost-user target, generating concurrent region_* traffic on one shared resv_map.
Use list_splice_init() so the source head is re-initialized empty after each splice, making the retry loop safe.
--- mm/hugetlb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
mm/hugetlb.c +1 -1
@@ -674,7 +674,7 @@ static int allocate_file_region_entries(spin_lock (&resv->lock); -list_splice (&allocated_regions, &resv->region_cache); +list_splice_init (&allocated_regions, &resv->region_cache); resv->region_cache_count += to_allocate; }
Greg Kroah-Hartman
maintainerPATCH 94/261 mm/vmstat: fold stranded per-cpu node stats when a node comes online
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gregory Price <[email protected]>
commit ea3034b2b00fa50c8d2518d0804c9d427bbafa86 upstream.
A per-node vmstat counter is pgdat->vm_stat[] plus per-cpu deltas. A balanced counter can sit split as global=+N / per-cpu=-N.
The folds reconciling the split only walk online nodes, so when try_offline_node() marks a node offline the per-cpu deltas are stranded.
A subsequent online resets the per-cpu area but not pgdat->vm_stat[], orphaning the +N permanently. All NR_VM_NODE_STAT_ITEMS are affected.
The existing code zeroes the per-cpu counters and causes a permanent skew. Fold the stranded deltas instead, before the node rejoins the online set. The node is not online yet and the hotplug lock is held, so the remote access to per-cpu values is safe.
Discovered when node compaction hung for a nearly empty node, as the math to determine throttling broke. Reproduced by repeated memory hotplug/unplug cycles on a node under pressure: NR_ISOLATED_ANON ratchets up and never returns to zero.
--- mm/mm_init.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
mm/mm_init.c +11 -4
@@ -1514,7 +1514,7 @@ void __ref free_area_init_core_hotplug(s {int nid = pgdat->node_id;enum zone_type z; -int cpu; +int cpu, i;pgdat_init_internals (pgdat);
@@ -1532,10 +1532,17 @@ void __ref free_area_init_core_hotplug(s pgdat->node_start_pfn =0 ; pgdat->node_present_pages =0 ; -for_each_online_cpu (cpu) { -struct per_cpu_nodestat *p; +/* +* Hot-unplug can leave per-cpu vmstat deltas unfolded (folders skip +* offline nodes) - reconcile this at online. Foreign access to counters +* is safe: the node is not online yet and we hold the hotplug lock. +*/ +for_each_possible_cpu (cpu) { +struct per_cpu_nodestat *p =per_cpu_ptr (pgdat->per_cpu_nodestats, cpu); - p =per_cpu_ptr (pgdat->per_cpu_nodestats, cpu); +for (i =0 ; i <NR_VM_NODE_STAT_ITEMS ; i++) +if (p->vm_node_stat_diff[i]) +node_page_state_add (p->vm_node_stat_diff[i], pgdat, i);memset (p,0 ,sizeof (*p)); }
Greg Kroah-Hartman
maintainerPATCH 95/261 tracing/probes: Reject $arg0 in meta argument expansion
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raushan Patel <[email protected]>
commit 00a8ce2a2a9fa17674e1feec4d9105c1a5d6a419 upstream.
traceprobe_expand_meta_args() parses $argN with simple_strtoul() and calls sprint_nth_btf_arg(n - 1, ...). For $arg0, n is 0 so the index is -1. Because ctx->nr_params is signed, the "idx >= nr_params" guard in sprint_nth_btf_arg() does not catch the negative index, and ctx->params[-1].name_off is read out of bounds.
The normal per-argument path (parse_probe_vars()) already rejects $arg0 via its argument-number check, but meta-argument expansion runs before per-argument parsing and substitutes the value first, bypassing that check.
Reject $arg0 explicitly during expansion.
--- kernel/trace/trace_probe.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
kernel/trace/trace_probe.c +5 -1
@@ -1721,7 +1721,11 @@ const char **traceprobe_expand_meta_args ret = -ENOENT ; goto error; } -/* Note: $argN starts from $arg1 */ +/* Note: $argN starts from $arg1, so $arg0 is invalid. */ +if (n ==0 ) { +trace_probe_log_err (0 ,BAD_ARG_NUM ); +return ERR_PTR (-EINVAL ); + } ret =sprint_nth_btf_arg (n -1 , type, buf + used, bufsize - used, ctx);if (ret <0 )
Re: [PATCH 6.6 095/261] tracing/probes: Reject $arg0 in meta argument expansion
Hi Greg,
Quoted 35 lines · Greg Kroah-Hartman
6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raushan Patel <[email protected]>
commit
00a8ce2a2a9fa17674e1feec4d9105c1a5d6a419upstream.
traceprobe_expand_meta_args()parses $argN withsimple_strtoul()and callssprint_nth_btf_arg(n - 1, ...). For $arg0, n is 0 so the index is -1. Becausectx->nr_paramsis signed, the "idx >=nr_params" guard insprint_nth_btf_arg()does not catch the negative index, and ctx->params[-1].name_off is read out of bounds.The normal per-argument path (
parse_probe_vars()) already rejects $arg0 via its argument-number check, but meta-argument expansion runs before per-argument parsing and substitutes the value first, bypassing that check.Reject $arg0 explicitly during expansion.
Fixes 18b1e870a496 ("tracing/probes: Add $arg* meta argument for all function args")Signed-off-by Raushan Patel <[email protected]>Signed-off-by Masami Hiramatsu (Google) <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- kernel/trace/trace_probe.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
kernel/trace/trace_probe.c const char **traceprobe_expand_meta_args · line 1727
Quoted 8 lines
kernel/trace/trace_probe.c +4
-1@@ -1721,7 +1721,11 @@ const char **traceprobe_expand_meta_args ret = -ENOENT ; goto error; } -/* Note: $argN starts from $arg1 */ +/* Note: $argN starts from $arg1, so $arg0 is invalid. */ +if (n ==0 ) { +trace_probe_log_err (0 ,BAD_ARG_NUM ); +return ERR_PTR (-EINVAL );
The control flow here is not quite right.
Returning directly within this branch fails to free the new_argv memory, resulting in a memory leak.
The mainline does not have this issue because the preceding patch 4af0532a0f47 ("tracing: Use __free() in trace_probe for cleanup") introduced __free to manage the release of new_argv memory. However, due to the extensive changes involved, directly cherry-picking that patch does not seem to be that straightforward.
Therefore, it might be more appropriate to simply change it to goto here:
kernel/trace/trace_probe.c +2 -1
@@ -1724,7 +1724,8 @@ const char **traceprobe_expand_meta_args(int argc, const char *argv[],/* Note: $argN starts from $arg1, so $arg0 is invalid. */ if (n ==0 ) {trace_probe_log_err (0 ,BAD_ARG_NUM ); -return ERR_PTR (-EINVAL ); + ret = -EINVAL ; + goto error; } ret =sprint_nth_btf_arg (n -1 , type, buf + used, bufsize - used, ctx);
Thanks,
Tengda
Quoted 6 lines
kernel/trace/trace_probe.c +1
-0+ } ret =sprint_nth_btf_arg (n -1 , type, buf + used, bufsize - used, ctx);if (ret <0 )
Greg Kroah-Hartman
maintainerRe: [PATCH 6.6 095/261] tracing/probes: Reject $arg0 in meta argument expansion
Quoted 52 lines · Tengda Wu
Hi Greg,
Quoted 35 lines · Greg Kroah-Hartman
6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raushan Patel <[email protected]>
commit
00a8ce2a2a9fa17674e1feec4d9105c1a5d6a419upstream.
traceprobe_expand_meta_args()parses $argN withsimple_strtoul()and callssprint_nth_btf_arg(n - 1, ...). For $arg0, n is 0 so the index is -1. Becausectx->nr_paramsis signed, the "idx >=nr_params" guard insprint_nth_btf_arg()does not catch the negative index, and ctx->params[-1].name_off is read out of bounds.The normal per-argument path (
parse_probe_vars()) already rejects $arg0 via its argument-number check, but meta-argument expansion runs before per-argument parsing and substitutes the value first, bypassing that check.Reject $arg0 explicitly during expansion.
Fixes 18b1e870a496 ("tracing/probes: Add $arg* meta argument for all function args")Signed-off-by Raushan Patel <[email protected]>Signed-off-by Masami Hiramatsu (Google) <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- kernel/trace/trace_probe.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)kernel/trace/trace_probe.c const char **traceprobe_expand_meta_args · line 1727
Quoted 8 lines
kernel/trace/trace_probe.c +4
-1@@ -1721,7 +1721,11 @@ const char **traceprobe_expand_meta_args ret = -ENOENT ; goto error; } -/* Note: $argN starts from $arg1 */ +/* Note: $argN starts from $arg1, so $arg0 is invalid. */ +if (n ==0 ) { +trace_probe_log_err (0 ,BAD_ARG_NUM ); +return ERR_PTR (-EINVAL );The control flow here is not quite right.
Returning directly within this branch fails to free the
new_argvmemory, resulting in a memory leak.
Quoted 7 lines
The mainline does not have this issue because the preceding patch
4af0532a0f47("tracing: Use__free()intrace_probefor cleanup") introduced__freeto manage the release ofnew_argvmemory. However, due to the extensive changes involved, directly cherry-picking that patch does not seem to be that straightforward.Therefore, it might be more appropriate to simply change it to goto here:
Thanks for the review, can you send a fix-up patch for this as it is already in a release?
greg k-h
Re: [PATCH 6.6 095/261] tracing/probes: Reject $arg0 in meta argument expansion
Quoted 59 lines · Greg Kroah-Hartman
Quoted 58 lines · Tengda Wu
Hi Greg,
Quoted 35 lines · Greg Kroah-Hartman
6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raushan Patel <[email protected]>
commit
00a8ce2a2a9fa17674e1feec4d9105c1a5d6a419upstream.
traceprobe_expand_meta_args()parses $argN withsimple_strtoul()and callssprint_nth_btf_arg(n - 1, ...). For $arg0, n is 0 so the index is -1. Becausectx->nr_paramsis signed, the "idx >=nr_params" guard insprint_nth_btf_arg()does not catch the negative index, and ctx->params[-1].name_off is read out of bounds.The normal per-argument path (
parse_probe_vars()) already rejects $arg0 via its argument-number check, but meta-argument expansion runs before per-argument parsing and substitutes the value first, bypassing that check.Reject $arg0 explicitly during expansion.
Fixes 18b1e870a496 ("tracing/probes: Add $arg* meta argument for all function args")Signed-off-by Raushan Patel <[email protected]>Signed-off-by Masami Hiramatsu (Google) <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- kernel/trace/trace_probe.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)kernel/trace/trace_probe.c const char **traceprobe_expand_meta_args · line 1727
Quoted 8 lines
kernel/trace/trace_probe.c +4
-1@@ -1721,7 +1721,11 @@ const char **traceprobe_expand_meta_args ret = -ENOENT ; goto error; } -/* Note: $argN starts from $arg1 */ +/* Note: $argN starts from $arg1, so $arg0 is invalid. */ +if (n ==0 ) { +trace_probe_log_err (0 ,BAD_ARG_NUM ); +return ERR_PTR (-EINVAL );The control flow here is not quite right.
Returning directly within this branch fails to free the
new_argvmemory, resulting in a memory leak.The mainline does not have this issue because the preceding patch
4af0532a0f47("tracing: Use__free()intrace_probefor cleanup") introduced__freeto manage the release ofnew_argvmemory. However, due to the extensive changes involved, directly cherry-picking that patch does not seem to be that straightforward.
Quoted 6 lines
Quoted 1 line
Therefore, it might be more appropriate to simply change it to goto here:
Thanks for the review, can you send a fix-up patch for this as it is already in a release?
greg k-h
Sure.
Tengda
Greg Kroah-Hartman
maintainerPATCH 96/261 KVM: SVM: Update x2APIC MSR intercepts if AVIC is inhibited while L2 is active
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Christopherson <[email protected]>
commit 7d3aae206663c4e006b25a1c7a20a4029e67da76 upstream.
Always update x2APIC MSR intercepts for L1 when AVIC is deactivated, even if L2 is active and KVM is using a separate MSR bitmap to run L2. If AVIC is fully enabled prior to running L2, and is then inhibited while L2 is active (for a VM-scoped inhibit), then KVM will run L1 with AVIC disabled, but with x2APIC MSR intercepts disabled, i.e. will allow L1 to read most of the host's APIC state, send arbitrary interrupts, change task priority, and ultimately trivially DoS the host.
E.g. sending a self-IPI in L1 on HYPERV_REENLIGHTENMENT_VECTOR, 0xee, with CONFIG_HYPERV=n in the host kernel as a "safe" PoC, yields:
Spurious interrupt (vector 0xee) on CPU#425. Acked
And hacking KVM to abuse kvm_set_posted_intr_wakeup_handler() to register a handler and WARN on POSTED_INTR_WAKEUP_VECTOR yields:
------------[ cut here ]------------ WARNING: arch/x86/kvm/svm/svm.c:5594 at pi_wakeup_handler+0x9/0x10 [kvm_amd], CPU#156: nested_x2apic_t/316940 CPU: 156 UID: 0 PID: 316940 Comm: nested_x2apic_t Tainted: G S U Tainted: [S]=CPU_OUT_OF_SPEC, [U]=USER Hardware name: Google Astoria-Turin/astoria, BIOS 0.20260209.0-0 02/09/2026 RIP: 0010:pi_wakeup_handler+0x9/0x10 [kvm_amd] Call Trace: <IRQ> sysvec_kvm_posted_intr_wakeup_ipi+0x64/0x80 </IRQ> <TASK> asm_sysvec_kvm_posted_intr_wakeup_ipi+0x1a/0x20 RIP: 0010:vcpu_run+0x1430/0x1e40 [kvm] kvm_arch_vcpu_ioctl_run+0x2c1/0x600 [kvm] kvm_vcpu_ioctl+0x580/0x6b0 [kvm] __se_sys_ioctl+0x6d/0xb0 do_syscall_64+0x10a/0x480 entry_SYSCALL_64_after_hwframe+0x4b/0x53 RIP: 0033:0x46ff4b </TASK> ---[ end trace 0000000000000000 ]---
--- arch/x86/kvm/svm/avic.c | 8 -------- 1 file changed, 8 deletions(-)
arch/x86/kvm/svm/avic.c +0 -8
@@ -167,14 +167,6 @@ static void avic_deactivate_vmcb(structif (!sev_es_guest (svm->vcpu.kvm))svm_set_intercept (svm,INTERCEPT_CR8_WRITE ); -/* -* If running nested and the guest uses its own MSR bitmap, there -* is no need to update L0's msr bitmap -*/ -if (is_guest_mode (&svm->vcpu) && -vmcb12_is_intercept (&svm->nested.ctl,INTERCEPT_MSR_PROT )) -return ; -/* Enabling MSR intercept for x2APIC registers */ svm_set_x2apic_msr_interception (svm, true); }
Greg Kroah-Hartman
maintainerPATCH 97/261 KVM: s390: pci: Reject adapter interrupt forwarding if already enabled
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Farhan Ali <[email protected]>
commit 8fa01be5a6149404adb82c0979a78f6347edd3ef upstream.
The MPCIFC instruction doesn't allow registering adapter interrupts without first unregistering. So reject any request to enable interrupt forwarding if its already enabled for the zPCI device. This also fixes overwriting and thus leaking resources when the ioctl is called multiple times for the same device.
--- arch/s390/kvm/pci.c | 4 ++++ 1 file changed, 4 insertions(+)
arch/s390/kvm/pci.c +4 -0
@@ -239,6 +239,10 @@ static int kvm_s390_pci_aif_enable(strucif (zdev->gisa ==0 )return -EINVAL ; +/* AIF already enabled for the device */ +if (zdev->kzdev->fib.fmt0.aibv !=0 ) +return -EINVAL ; + kvm = zdev->kzdev->kvm; msi_vecs = min_t(unsigned int, fib->fmt0.noi, zdev->max_msi);
Greg Kroah-Hartman
maintainerPATCH 98/261 KVM: s390: pci: Fix NULL dereference on AIBV allocation failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Farhan Ali <[email protected]>
commit 8bf09b9b7d3232806df95f409581f8a9fd99a3fa upstream.
The airq_iv_create() can return NULL on failure, but the return value was never checked. If it fails, zdev->aibv will be NULL and fail when dereferenced in kvm_zpci_set_airq(). Add a NULL check and free the previously allocated AISB bit and zdev->aisb on failure.
--- arch/s390/kvm/pci.c | 8 ++++++++ 1 file changed, 8 insertions(+)
arch/s390/kvm/pci.c +8 -0
@@ -295,6 +295,11 @@ static int kvm_s390_pci_aif_enable(strucAIRQ_IV_GUESTVEC , phys_to_virt(fib->fmt0.aibv)); +if (!zdev->aibv) { + rc = -ENOMEM ; + goto free_aisb; + } +spin_lock_irq (&aift->gait_lock); gaite = aift->gait + zdev->aisb;
@@ -331,6 +336,9 @@ static int kvm_s390_pci_aif_enable(struc rc =kvm_zpci_set_airq (zdev);return rc; +free_aisb: +airq_iv_free_bit (aift->sbv, zdev->aisb); + zdev->aisb =0 ; unlock:mutex_unlock (&aift->aift_lock); unpin2:
Greg Kroah-Hartman
maintainerPATCH 99/261 KVM: s390: pci: Validate AIBV and AISB before pinning guest pages
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Farhan Ali <[email protected]>
commit 868d32ac72cba21c5c6d8a66a814b7c25a3a5c01 upstream.
The AIBV holds one bit per MSI-X vector for a given function. The size of the bit vector is derived from the NOI and the AIBVO. If the size of the AIBV exceeds a single page boundary, then reject the request as we cannot safely pin the guest AIBV.
Similarly reject the request if the AISB address is not 8-byte aligned as the architecture requires doubleword alignment for the summary bit address. Since the AISBO can address up to 64 bits, the size of the AISB can only be 8 bytes for the function. This also ensures the AISB doesn't exceed a single page boundary.
--- arch/s390/kvm/pci.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
arch/s390/kvm/pci.c +15 -1
@@ -225,7 +225,7 @@ static int kvm_s390_pci_aif_enable(struc bool assist) {struct page *pages[1 ], *aibv_page, *aisb_page =NULL ; -unsigned int msi_vecs, idx; +unsigned int msi_vecs, idx, size;struct zpci_gaite *gaite;unsigned long hva, bit;struct kvm *kvm;
@@ -252,6 +252,14 @@ static int kvm_s390_pci_aif_enable(strucreturn gisc;/* Replace AIBV address */ + size =BITS_TO_LONGS (msi_vecs + fib->fmt0.aibvo) *sizeof (unsigned long ); + npages =DIV_ROUND_UP ((fib->fmt0.aibv & ~PAGE_MASK ) + size,PAGE_SIZE ); +/* AIBV cannot span more than 1 page */ +if (npages >1 ) { + rc = -EINVAL ; + goto out; + } + idx =srcu_read_lock (&kvm->srcu); hva =gfn_to_hva (kvm,gpa_to_gfn ((gpa_t )fib->fmt0.aibv)); npages =pin_user_pages_fast (hva,1 ,FOLL_WRITE |FOLL_LONGTERM , pages);
@@ -267,6 +275,12 @@ static int kvm_s390_pci_aif_enable(struc/* Pin the guest AISB if one was specified */ if (fib->fmt0.sum ==1 ) { +/* AISB must be dword aligned */ +if (fib->fmt0.aisb &0x7 ) { + rc = -EINVAL ; + goto unpin1; + } + idx =srcu_read_lock (&kvm->srcu); hva =gfn_to_hva (kvm,gpa_to_gfn ((gpa_t )fib->fmt0.aisb)); npages = pin_user_pages_fast(hva, 1, FOLL_WRITE | FOLL_LONGTERM,
Greg Kroah-Hartman
maintainerPATCH 100/261 sctp: validate Adaptation Indication parameter length
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Charles Vosburgh <[email protected]>
commit 74b21f52c5c5a71a05c0ff70e513f4f04ff28b17 upstream.
The Adaptation Layer Indication parameter contains a fixed 32-bit Adaptation Code Point after its parameter header. However, sctp_verify_param() accepts a header-only parameter because the generic parameter walker only requires the header to be present.
sctp_process_param() then reads adaptation_ind beyond the declared parameter. When the malformed parameter is last in an INIT, the read starts at the receive skb tail, and the value is copied into the state cookie returned in the INIT ACK. This may disclose four receive-buffer tail bytes.
Require the declared parameter length to match the fixed structure size and abort the association through the existing invalid parameter length path otherwise.
--- net/sctp/sm_make_chunk.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/sctp/sm_make_chunk.c +6 -0
@@ -2187,7 +2187,13 @@ static enum sctp_ierror sctp_verify_paracase SCTP_PARAM_HEARTBEAT_INFO :case SCTP_PARAM_UNRECOGNIZED_PARAMETERS :case SCTP_PARAM_ECN_CAPABLE : +break ;case SCTP_PARAM_ADAPTATION_LAYER_IND : +if (ntohs (param.p->length) !=sizeof (*param.aind)) { +sctp_process_inv_paramlength (asoc, param.p, + chunk, err_chunk); + retval =SCTP_IERROR_ABORT ; + }break ;case SCTP_PARAM_SUPPORTED_EXT :
Greg Kroah-Hartman
maintainerPATCH 101/261 audit: fix potential integer overflow in audit_log_n_string()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhan Xusheng <[email protected]>
commit f865c143629d4094866a811dba5f329250bad486 upstream.
audit_log_n_string() computes new_len as "slen + 3" (enclosing quotes plus the NUL terminator) and stores it into an int, while slen is a size_t. For a sufficiently large slen the addition can overflow and/or the result be truncated when assigned to the int new_len, so the "new_len > avail" check can be bypassed and the subsequent memcpy(ptr, string, slen) can write past the skb tail.
This is the same class of bug that was fixed for the hex sibling in commit 65dfde57d1e2 ("audit: fix potential integer overflow in audit_log_n_hex()"); both helpers are reached through audit_log_n_untrustedstring() with the same length source.
Make new_len a size_t and use check_add_overflow() to catch the overflow, mirroring the audit_log_n_hex() fix. No functional change for the in-tree callers, which all pass bounded lengths.
--- kernel/audit.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
kernel/audit.c +9 -2
@@ -2074,7 +2074,8 @@ void audit_log_n_hex(struct audit_buffervoid audit_log_n_string (struct audit_buffer *ab,const char *string,size_t slen) { -int avail, new_len; +int avail; +size_t new_len;unsigned char *ptr;struct sk_buff *skb;
@@ -2084,7 +2085,13 @@ void audit_log_n_string(struct audit_bufBUG_ON (!ab->skb); skb = ab->skb; avail =skb_tailroom (skb); - new_len = slen +3 ;/* enclosing quotes + null terminator */ + +/* enclosing quotes + null terminator */ +if (check_add_overflow (slen,3 , &new_len)) { +audit_log_format (ab,"?" ); +return ; + } +if (new_len > avail) { avail =audit_expand (ab, new_len);if (!avail)
Greg Kroah-Hartman
maintainerPATCH 102/261 audit: fix potential use-after-free in audit_del_rule()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luxiao Xu <[email protected]>
commit 246df90b5f1a8a6e6abbd2f058b029558720adec upstream.
audit_del_rule() destroys e->rule.exe via audit_remove_mark_rule() before unlinking the rule from RCU-visible filter lists and waiting for a grace period. Concurrent readers in audit_filter() and audit_filter_rules() still dereference e->rule.exe, while the fsnotify mark can be freed on an independent lifetime path. This creates a use-after-free window during rule deletion.
Fix this by unlinking the rule from the RCU-visible lists and invoking synchronize_rcu() before calling audit_remove_mark_rule() (and other rule removal helpers). This ensures that all existing RCU readers have exited the critical section before any underlying resources are destroyed.
--- kernel/auditfilter.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
kernel/auditfilter.c +4 -2
@@ -1047,6 +1047,10 @@ int audit_del_rule(struct audit_entry *e goto out; } +list_del_rcu (&e->list); +list_del (&e->rule.list); +synchronize_rcu (); +if (e->rule.watch)audit_remove_watch_rule (&e->rule);
@@ -1064,8 +1068,6 @@ int audit_del_rule(struct audit_entry *e audit_signals--;#endif -list_del_rcu (&e->list); -list_del (&e->rule.list);call_rcu (&e->rcu, audit_free_rule_rcu); out:
Greg Kroah-Hartman
maintainerPATCH 103/261 Bluetooth: btmtk: Fix short read errors in btmtk_usb_uhw_reg_read()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
commit b186c18c4843dd58adc29443369bddc71cb626a3 upstream.
If btmtk_usb_uhw_reg_read() gets a "short" read from a device, it will accidentally treat that as a "real" read and populate the returned value with some unknown and probably totally invalid data.
Fix this logic error up by calling usb_control_msg_recv() which guarantees a "full" read happens, and then simplify the error checking for when btmtk_usb_uhw_reg_read() is called.
Note, one caller of btmtk_usb_uhw_reg_read() does not check the return value, but as we pre-initialize the return value as 0, an incorrect read will not do anything wrong.
--- drivers/bluetooth/btmtk.c | 50 ++++++++++++++++++++-------------------------- 1 file changed, 22 insertions(+), 28 deletions(-)
drivers/bluetooth/btmtk.c +22 -28
@@ -760,30 +760,24 @@ static int btmtk_usb_uhw_reg_write(strucstatic int btmtk_usb_uhw_reg_read (struct hci_dev *hdev,u32 reg,u32 *val) {struct btmtk_data *data =hci_get_priv (hdev); -int pipe, err; -void *buf; - - buf =kzalloc (4 ,GFP_KERNEL ); -if (!buf) -return -ENOMEM ; +u8 buf[sizeof (u32)]; +int err; - pipe =usb_rcvctrlpipe (data->udev,0 ); - err =usb_control_msg (data->udev, pipe,0x01 , -0xDE , - reg >>16 , reg &0xffff , - buf,4 ,USB_CTRL_GET_TIMEOUT ); -if (err <0 ) { + *val =0 ; + err =usb_control_msg_recv (data->udev,0 ,0x01 , +0xDE , + reg >>16 , reg &0xffff , + buf,sizeof (buf),USB_CTRL_GET_TIMEOUT , +GFP_KERNEL ); +if (err) {bt_dev_err (hdev,"Failed to read uhw reg(%d)" , err); - goto err_free_buf; +return err; } *val =get_unaligned_le32 (buf);bt_dev_dbg (hdev,"reg=%x, value=0x%08x" , reg, *val); -err_free_buf: -kfree (buf); - -return err; +return 0 ; }static int btmtk_usb_reg_read (struct hci_dev *hdev,u32 reg,u32 *val)
@@ -833,7 +827,7 @@ int btmtk_usb_subsys_reset(struct hci_deif (dev_id ==0x7922 ) { err =btmtk_usb_uhw_reg_read (hdev,MTK_BT_SUBSYS_RST , &val); -if (err <0 ) +if (err)return err; val |=0x00002020 ; err =btmtk_usb_uhw_reg_write (hdev,MTK_BT_SUBSYS_RST , val);
@@ -843,7 +837,7 @@ int btmtk_usb_subsys_reset(struct hci_deif (err <0 )return err; err =btmtk_usb_uhw_reg_read (hdev,MTK_BT_SUBSYS_RST , &val); -if (err <0 ) +if (err)return err; val |=BIT (0 ); err =btmtk_usb_uhw_reg_write (hdev,MTK_BT_SUBSYS_RST , val);
@@ -852,14 +846,14 @@ int btmtk_usb_subsys_reset(struct hci_demsleep (100 ); }else if (dev_id ==0x7925 ) { err =btmtk_usb_uhw_reg_read (hdev,MTK_BT_RESET_REG_CONNV3 , &val); -if (err <0 ) +if (err)return err; val |= (1 <<5 ); err =btmtk_usb_uhw_reg_write (hdev,MTK_BT_RESET_REG_CONNV3 , val);if (err <0 )return err; err =btmtk_usb_uhw_reg_read (hdev,MTK_BT_RESET_REG_CONNV3 , &val); -if (err <0 ) +if (err)return err; val &=0xFFFF00FF ; val |= (1 <<13 );
@@ -870,7 +864,7 @@ int btmtk_usb_subsys_reset(struct hci_deif (err <0 )return err; err =btmtk_usb_uhw_reg_read (hdev,MTK_BT_RESET_REG_CONNV3 , &val); -if (err <0 ) +if (err)return err; val |= (1 <<0 ); err =btmtk_usb_uhw_reg_write (hdev,MTK_BT_RESET_REG_CONNV3 , val);
@@ -880,13 +874,13 @@ int btmtk_usb_subsys_reset(struct hci_deif (err <0 )return err; err =btmtk_usb_uhw_reg_read (hdev,MTK_UDMA_INT_STA_BT , &val); -if (err <0 ) +if (err)return err; err =btmtk_usb_uhw_reg_write (hdev,MTK_UDMA_INT_STA_BT1 ,0x000000FF );if (err <0 )return err; err =btmtk_usb_uhw_reg_read (hdev,MTK_UDMA_INT_STA_BT1 , &val); -if (err <0 ) +if (err)return err;msleep (100 ); }else {
@@ -896,7 +890,7 @@ int btmtk_usb_subsys_reset(struct hci_deif (err <0 )return err; err =btmtk_usb_uhw_reg_read (hdev,MTK_BT_WDT_STATUS , &val); -if (err <0 ) +if (err)return err;/* Reset the bluetooth chip via USB interface. */ err =btmtk_usb_uhw_reg_write (hdev,MTK_BT_SUBSYS_RST ,1 );
@@ -906,13 +900,13 @@ int btmtk_usb_subsys_reset(struct hci_deif (err <0 )return err; err =btmtk_usb_uhw_reg_read (hdev,MTK_UDMA_INT_STA_BT , &val); -if (err <0 ) +if (err)return err; err =btmtk_usb_uhw_reg_write (hdev,MTK_UDMA_INT_STA_BT1 ,0x000000FF );if (err <0 )return err; err =btmtk_usb_uhw_reg_read (hdev,MTK_UDMA_INT_STA_BT1 , &val); -if (err <0 ) +if (err)return err;/* MT7921 need to delay 20ms between toggle reset bit */ msleep (20 );
@@ -920,7 +914,7 @@ int btmtk_usb_subsys_reset(struct hci_deif (err <0 )return err; err =btmtk_usb_uhw_reg_read (hdev,MTK_BT_SUBSYS_RST , &val); -if (err <0 ) +if (err)return err; }
Greg Kroah-Hartman
maintainerPATCH 104/261 Bluetooth: mgmt: fix pending command UAF in EIR updates
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zihan Xi <[email protected]>
commit 8f2f62855a41d1730fb9e8122912bd2c8d6bed5d upstream.
MGMT_OP_SET_LOCAL_NAME is handled asynchronously on powered controllers and can run set_name_sync(). When the controller is BR/EDR capable, set_name_sync() updates the local name and then rebuilds EIR data through eir_create(). The EIR builder walks hdev->uuids, but the UUID list can be changed and entries can be freed by MGMT_OP_ADD_UUID and MGMT_OP_REMOVE_UUID.
pending_eir_or_class() is meant to serialize management commands that can change EIR or the class of device, but it did not include MGMT_OP_SET_LOCAL_NAME. In addition, it walked hdev->mgmt_pending without hdev->mgmt_pending_lock even though pending commands are added and removed under that mutex. A racing command completion can therefore remove and free a pending command while pending_eir_or_class() is still inspecting it, leading to a use-after-free in the pending-command list or allowing a local name update to rebuild EIR while UUID entries are being removed.
Take hdev->mgmt_pending_lock while scanning hdev->mgmt_pending and treat MGMT_OP_SET_LOCAL_NAME as an EIR/class-affecting pending command on the powered asynchronous path. Check for a conflicting pending command before copying the new short name so a rejected SET_LOCAL_NAME request does not modify hdev->short_name.
--- net/bluetooth/mgmt.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
net/bluetooth/mgmt.c +18 -2
@@ -2610,18 +2610,28 @@ unlock:static bool pending_eir_or_class (struct hci_dev *hdev) {struct mgmt_pending_cmd *cmd; +bool pending = false; + +mutex_lock (&hdev->mgmt_pending_lock);list_for_each_entry (cmd, &hdev->mgmt_pending, list) {switch (cmd->opcode) {case MGMT_OP_ADD_UUID :case MGMT_OP_REMOVE_UUID :case MGMT_OP_SET_DEV_CLASS : +case MGMT_OP_SET_LOCAL_NAME :case MGMT_OP_SET_POWERED : -return true; + pending = true; +break ; } + +if (pending) +break ; } -return false; +mutex_unlock (&hdev->mgmt_pending_lock); + +return pending; }static const u8 bluetooth_base_uuid[] = {
@@ -3955,6 +3965,12 @@ static int set_local_name(struct sock *s goto failed; } +if (hdev_is_powered (hdev) &&pending_eir_or_class (hdev)) { + err =mgmt_cmd_status (sk, hdev->id,MGMT_OP_SET_LOCAL_NAME , +MGMT_STATUS_BUSY ); + goto failed; + } +memcpy (hdev->short_name, cp->short_name,sizeof (hdev->short_name));if (!hdev_is_powered (hdev)) {
Greg Kroah-Hartman
maintainerPATCH 105/261 Bluetooth: mgmt: fix UAF in pair command cancellation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zihan Xi <[email protected]>
commit d0a7b48ad0921bd88effaee10bf970ab1d5d0ddd upstream.
The pairing completion and authentication failure callbacks look up the pending MGMT_OP_PAIR_DEVICE command by walking hdev->mgmt_pending. The lookup returned a command that was still linked on the shared pending list, without keeping mgmt_pending_lock held for the later dereference and removal.
A concurrent MGMT_OP_CANCEL_PAIR_DEVICE request can remove and free the same pending command before the callback uses it. The reverse race is also possible when cancel_pair_device() gets a command from pending_find() and a callback removes it before the cancel path dereferences it. This can lead to a use-after-free and a second list_del().
Make the pairing lookup helpers transfer ownership of the pending command by removing it from hdev->mgmt_pending while holding mgmt_pending_lock. The callbacks and cancel path then complete the command and free it directly, so racing paths cannot find or free the same command again. Take a temporary hci_conn reference in cancel_pair_device() because the command completion drops the reference stored in the pending command.
--- net/bluetooth/mgmt.c | 64 ++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 18 deletions(-)
net/bluetooth/mgmt.c +46 -18
@@ -3437,11 +3437,13 @@ static int set_io_capability(struct sock NULL, 0); } -static struct mgmt_pending_cmd *find_pairing (struct hci_conn *conn) +static struct mgmt_pending_cmd *remove_pairing (struct hci_conn *conn) {struct hci_dev *hdev = conn->hdev;struct mgmt_pending_cmd *cmd; +mutex_lock (&hdev->mgmt_pending_lock); +list_for_each_entry (cmd, &hdev->mgmt_pending, list) {if (cmd->opcode !=MGMT_OP_PAIR_DEVICE )continue ;
@@ -3449,9 +3451,39 @@ static struct mgmt_pending_cmd *find_paiif (cmd->user_data != conn)continue ; +list_del (&cmd->list); +mutex_unlock (&hdev->mgmt_pending_lock);return cmd; } +mutex_unlock (&hdev->mgmt_pending_lock); + +return NULL ; +} + +static struct mgmt_pending_cmd *remove_pairing_by_addr (struct hci_dev *hdev, +bdaddr_t *bdaddr) +{ +struct mgmt_pending_cmd *cmd; +struct hci_conn *conn; + +mutex_lock (&hdev->mgmt_pending_lock); + +list_for_each_entry (cmd, &hdev->mgmt_pending, list) { +if (cmd->opcode !=MGMT_OP_PAIR_DEVICE ) +continue ; + + conn = cmd->user_data; +if (bacmp (bdaddr, &conn->dst) !=0 ) +continue ; + +list_del (&cmd->list); +mutex_unlock (&hdev->mgmt_pending_lock); +return cmd; + } + +mutex_unlock (&hdev->mgmt_pending_lock); +return NULL ; }
@@ -3489,10 +3521,10 @@ void mgmt_smp_complete(struct hci_conn *u8 status = complete ?MGMT_STATUS_SUCCESS :MGMT_STATUS_FAILED ;struct mgmt_pending_cmd *cmd; - cmd =find_pairing (conn); + cmd =remove_pairing (conn);if (cmd) { cmd->cmd_complete (cmd, status); -mgmt_pending_remove (cmd); +mgmt_pending_free (cmd); } }
@@ -3502,14 +3534,14 @@ static void pairing_complete_cb(struct hBT_DBG ("status %u" , status); - cmd =find_pairing (conn); + cmd =remove_pairing (conn);if (!cmd) {BT_DBG ("Unable to find a pending command" );return ; } cmd->cmd_complete (cmd,mgmt_status (status)); -mgmt_pending_remove (cmd); +mgmt_pending_free (cmd); }static void le_pairing_complete_cb (struct hci_conn *conn,u8 status)
@@ -3521,14 +3553,14 @@ static void le_pairing_complete_cb(strucif (!status)return ; - cmd =find_pairing (conn); + cmd =remove_pairing (conn);if (!cmd) {BT_DBG ("Unable to find a pending command" );return ; } cmd->cmd_complete (cmd,mgmt_status (status)); -mgmt_pending_remove (cmd); +mgmt_pending_free (cmd); } static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data,
@@ -3684,23 +3716,17 @@ static int cancel_pair_device(struct soc goto unlock; } - cmd =pending_find (MGMT_OP_PAIR_DEVICE , hdev); + cmd =remove_pairing_by_addr (hdev, &addr->bdaddr);if (!cmd) { err =mgmt_cmd_status (sk, hdev->id,MGMT_OP_CANCEL_PAIR_DEVICE ,MGMT_STATUS_INVALID_PARAMS ); goto unlock; } - conn = cmd->user_data; - -if (bacmp (&addr->bdaddr, &conn->dst) !=0 ) { - err =mgmt_cmd_status (sk, hdev->id,MGMT_OP_CANCEL_PAIR_DEVICE , -MGMT_STATUS_INVALID_PARAMS ); - goto unlock; - } + conn =hci_conn_get (cmd->user_data); cmd->cmd_complete (cmd,MGMT_STATUS_CANCELLED ); -mgmt_pending_remove (cmd); +mgmt_pending_free (cmd); err =mgmt_cmd_complete (sk, hdev->id,MGMT_OP_CANCEL_PAIR_DEVICE ,0 , addr,sizeof (*addr));
@@ -3718,6 +3744,8 @@ static int cancel_pair_device(struct socif (conn->conn_reason ==CONN_REASON_PAIR_DEVICE )hci_abort_conn (conn,HCI_ERROR_REMOTE_USER_TERM ); +hci_conn_put (conn); + unlock:hci_dev_unlock (hdev);return err;
@@ -10138,14 +10166,14 @@ void mgmt_auth_failed(struct hci_conn *c ev.addr.type =link_to_bdaddr (conn->type, conn->dst_type); ev.status = status; - cmd =find_pairing (conn); + cmd =remove_pairing (conn);mgmt_event (MGMT_EV_AUTH_FAILED , conn->hdev, &ev,sizeof (ev), cmd ? cmd->sk :NULL );if (cmd) { cmd->cmd_complete (cmd, status); -mgmt_pending_remove (cmd); +mgmt_pending_free (cmd); } }
Greg Kroah-Hartman
maintainerPATCH 106/261 Bluetooth: HIDP: reject frames without a transaction header
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sangho Lee <[email protected]>
commit 47778d2c2087b5d192398f6fddf692d16a5431cf upstream.
hidp_recv_ctrl_frame() and hidp_recv_intr_frame() read skb->data[0] before checking that the L2CAP SDU contains a transaction header. A connected HIDP peer can send an empty basic-mode SDU and make both paths use an uninitialized byte from skb tailroom.
KMSAN reports the use in hidp_session_run(), with the uninitialized value originating in __alloc_skb() through vhci_write(). The control path produces two reports and the interrupt path produces one.
The byte can also be controlled by a malformed lower-layer packet. If an HCI ACL packet contains an L2CAP PDU with a declared zero-length payload followed by an extra 0x15 byte, l2cap_recv_acldata() reduces skb->len to the declared PDU length before dispatch. The current HIDP path nevertheless consumes the extra byte as HIDP_TRANS_HID_CONTROL | HIDP_CTRL_VIRTUAL_CABLE_UNPLUG and terminates the HIDP session. With this change, the same packet is discarded and a subsequent feature report request succeeds.
Pull the transaction header with skb_pull_data() and discard frames that do not contain it.
--- net/bluetooth/hidp/core.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-)
net/bluetooth/hidp/core.c +15 -10
@@ -563,16 +563,18 @@ static int hidp_process_data(struct hidpstatic void hidp_recv_ctrl_frame (struct hidp_session *session,struct sk_buff *skb) { -unsigned char hdr, type, param; +unsigned char type, param; +u8 *hdr;int free_skb =1 ;BT_DBG ("session %p skb %p len %u" , session, skb, skb->len); - hdr = skb->data[0 ]; -skb_pull (skb,1 ); + hdr =skb_pull_data (skb,1 ); +if (!hdr) + goto free; - type = hdr &HIDP_HEADER_TRANS_MASK ; - param = hdr &HIDP_HEADER_PARAM_MASK ; + type = *hdr &HIDP_HEADER_TRANS_MASK ; + param = *hdr &HIDP_HEADER_PARAM_MASK ;switch (type) {case HIDP_TRANS_HANDSHAKE :
@@ -593,6 +595,7 @@ static void hidp_recv_ctrl_frame(structbreak ; } +free:if (free_skb)kfree_skb (skb); }
@@ -600,14 +603,15 @@ static void hidp_recv_ctrl_frame(structstatic void hidp_recv_intr_frame (struct hidp_session *session,struct sk_buff *skb) { -unsigned char hdr; +u8 *hdr;BT_DBG ("session %p skb %p len %u" , session, skb, skb->len); - hdr = skb->data[0 ]; -skb_pull (skb,1 ); + hdr =skb_pull_data (skb,1 ); +if (!hdr) + goto free; -if (hdr == (HIDP_TRANS_DATA |HIDP_DATA_RTYPE_INPUT )) { +if (*hdr == (HIDP_TRANS_DATA |HIDP_DATA_RTYPE_INPUT )) {hidp_set_timer (session);if (session->input)
@@ -619,9 +623,10 @@ static void hidp_recv_intr_frame(structBT_DBG ("report len %d" , skb->len); } }else { -BT_DBG ("Unsupported protocol header 0x%02x" , hdr); +BT_DBG ("Unsupported protocol header 0x%02x" , *hdr); } +free:kfree_skb (skb); }
Greg Kroah-Hartman
maintainerPATCH 107/261 Bluetooth: HIDP: validate numbered report payloads
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sangho Lee <[email protected]>
commit 34f53d27b81a16a02828c8fdfa4e02badc326f17 upstream.
When hidp_get_raw_report() waits for a numbered report, hidp_process_data() compares the expected report number with skb->data[0]. A connected HIDP peer can reply with only a DATA transaction header, leaving the skb empty after the header is removed.
KMSAN reports an uninitialized-value use in hidp_session_run(), with the value originating in __alloc_skb() through vhci_write(). The transaction header checks remove the empty-frame reports, but this report remains until the payload check is added.
The comparison can also consume a peer-controlled byte beyond the declared L2CAP PDU. A DATA | FEATURE response followed by an extra 0x01 byte made the current code accept that byte as report ID 1 and complete HIDIOCGFEATURE with a zero-byte result. With this change the malformed response is rejected with -EIO, while a subsequent valid response still succeeds.
Require a payload byte before comparing a numbered report ID. Unnumbered reports continue to accept an empty payload.
--- net/bluetooth/hidp/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
net/bluetooth/hidp/core.c +3 -2
@@ -546,9 +546,10 @@ static int hidp_process_data(struct hidp }if (test_bit (HIDP_WAITING_FOR_RETURN , &session->flags) && - param == session->waiting_report_type) { + param == session->waiting_report_type) {if (session->waiting_report_number <0 || - session->waiting_report_number == skb->data[0 ]) { + (skb->len && + session->waiting_report_number == skb->data[0 ])) {/* hidp_get_raw_report() is waiting on this report. */ session->report_return = skb; done_with_skb =0 ;
Greg Kroah-Hartman
maintainerPATCH 108/261 bpf: lwt: Fix dst reference leak on reroute failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xuanqiang Luo <[email protected]>
commit 88c17de85ddb459c3fe1e3c65d61fa366b1cf0a8 upstream.
bpf_lwt_xmit_reroute() obtains a referenced dst from the route lookup. When skb_cow_head() fails before that dst is installed on the skb, the error path only frees the skb. The skb still owns its previous dst, so the newly looked up dst reference is leaked.
Release the new dst reference before freeing the skb on this error path.
--- net/core/lwt_bpf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/core/lwt_bpf.c +3 -1
@@ -246,8 +246,10 @@ static int bpf_lwt_xmit_reroute(struct s* if there is enough header space in skb. */ err =skb_cow_head (skb,LL_RESERVED_SPACE (dst->dev)); -if (unlikely (err)) +if (unlikely (err)) { +dst_release (dst); goto err; + }skb_dst_drop (skb);skb_dst_set (skb, dst);
Greg Kroah-Hartman
maintainerPATCH 109/261 ALSA: 6fire: Fix UAF at error handling during probe
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
commit a54bf16965f896415c3337bc4fbb40fb11941d99 upstream.
Although 6fire driver had a few fixes for dealing with the early error handling during the probe phase, it forgot a pending URB before freeing the resources, which may lead to a UAF.
This patch addresses it by doing the almost same cleanup procedure like the normal disconnect phase at the error path.
--- sound/usb/6fire/chip.c | 4 ++++ 1 file changed, 4 insertions(+)
sound/usb/6fire/chip.c +4 -0
@@ -158,6 +158,10 @@ static int usb6fire_chip_probe(struct usreturn 0 ; destroy_chip: + chip->shutdown = true; +if (card) +snd_card_disconnect (card); +usb6fire_chip_abort (chip);snd_card_free (card);return ret; }
Greg Kroah-Hartman
maintainerPATCH 110/261 ALSA: lx6464es: fix period byte count for 16-bit streams
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Rao <[email protected]>
commit 6437033bffe8bd2af174d139af552d90d40c7ac6 upstream.
The lx6464es driver advertises both 16-bit and packed 24-bit PCM formats, but lx_trigger_start() and lx_interrupt_request_new_buffer() calculate the DMA period size as runtime->period_size * runtime->channels * 3. That is only correct for the packed 24-bit formats.
For 16-bit streams the driver submits buffers that are 50% larger than the actual ALSA period and advances the DMA address by the same wrong amount. For example, with 2 channels, 256 frames and 4 periods, the third buffer already extends beyond the ALSA buffer and the fourth buffer starts outside it.
Use snd_pcm_lib_period_bytes() so the byte count matches the runtime format, channel count and period size.
--- sound/pci/lx6464es/lx6464es.c | 5 +---- sound/pci/lx6464es/lx_core.c | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-)
sound/pci/lx6464es/lx6464es.c +1 -4
@@ -410,11 +410,8 @@ static void lx_trigger_start(struct lx64int err; -const u32 channels = substream->runtime->channels; -const u32 bytes_per_frame = channels *3 ; -const u32 period_size = substream->runtime->period_size;const u32 periods = substream->runtime->periods; -const u32 period_bytes = period_size * bytes_per_frame; +const u32 period_bytes =snd_pcm_lib_period_bytes (substream);dma_addr_t buf = substream->dma_buffer.addr;int i;
sound/pci/lx6464es/lx_core.c +1 -4
@@ -1015,10 +1015,7 @@ static int lx_interrupt_request_new_buffconst unsigned int is_capture = lx_stream->is_capture;int err; -const u32 channels = substream->runtime->channels; -const u32 bytes_per_frame = channels *3 ; -const u32 period_size = substream->runtime->period_size; -const u32 period_bytes = period_size * bytes_per_frame; +const u32 period_bytes =snd_pcm_lib_period_bytes (substream);const u32 pos = lx_stream->frame_pos;const u32 next_pos = ((pos+1 ) == substream->runtime->periods) ?0 : pos +1 ;
Greg Kroah-Hartman
maintainerPATCH 111/261 ALSA: pcm: wake linked drain waiters on unlink
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Norbert Szetei <[email protected]>
commit f495b6c4c8594122918552c9be2b51eb71647cd9 upstream.
snd_pcm_drain() on a linked stream parks an on-stack wait entry on the drained peer's runtime->sleep, and after schedule_timeout() removes it only if that peer is still found in the caller's group. If group membership changes during the wait and the sleep ends by signal or timeout (so autoremove_wake_function() does not run), finish_wait() is skipped and snd_pcm_drain() returns with the entry still queued on that stream's sleep list; a later wake_up() then walks a freed stack frame. This is reachable by unlinking either the drained or the draining stream.
Unlike the close path (snd_pcm_drop() -> snd_pcm_post_stop()), snd_pcm_unlink() never wakes the sleep queues. Wake every group member under the group lock before the membership change, so a linked drainer is released and drops its entry while the streams are still grouped.
The window was opened when snd_pcm_link_rwsem stopped being held across the wait and the removal became conditional on group membership (see Fixes). The later switch to finish_wait() kept that conditional removal, so the signal/timeout case remained.
--- sound/core/pcm_native.c | 7 +++++++ 1 file changed, 7 insertions(+)
sound/core/pcm_native.c +7 -0
@@ -2354,6 +2354,7 @@ static void relink_to_local(struct snd_pstatic int snd_pcm_unlink (struct snd_pcm_substream *substream) { +struct snd_pcm_substream *s;struct snd_pcm_group *group;bool nonatomic = substream->pcm->nonatomic;bool do_free = false;
@@ -2369,6 +2370,12 @@ static int snd_pcm_unlink(struct snd_pcm group = substream->group;snd_pcm_group_lock_irq (group, nonatomic); +/* release drain waiters before changing membership, else snd_pcm_drain() +* leaves its on-stack wait entry queued on a member's sleep list +*/ +snd_pcm_group_for_each_entry (s, substream) +wake_up (&s->runtime->sleep); +relink_to_local (substream);refcount_dec (&group->refs);
Greg Kroah-Hartman
maintainerPATCH 112/261 ALSA: ump: fix double free of out_cvts on rawmidi error
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baul Lee <[email protected]>
commit 70c977815af0d997feb2d0c5d284d55689bf7051 upstream.
snd_ump_attach_legacy_rawmidi() allocates the legacy conversion array ump->out_cvts and, on the snd_rawmidi_new() error path, frees it with kfree() but leaves ump->out_cvts pointing at the freed memory. When the endpoint is later torn down, snd_ump_endpoint_free() frees ump->out_cvts a second time, resulting in a double free.
The host snd-usb-audio driver attaches the legacy rawmidi for any USB MIDI 2.0 (UMP) device, so a device that makes snd_rawmidi_new() fail reaches this path on enumeration.
Clear ump->out_cvts after freeing it on the error path so it is not freed again during teardown.
Discovered by XBOW, triaged by Baul Lee <[email protected]>
--- sound/core/ump.c | 1 + 1 file changed, 1 insertion(+)
sound/core/ump.c +1 -0
@@ -1286,6 +1286,7 @@ int snd_ump_attach_legacy_rawmidi(struct &rmidi);if (err <0 ) {kfree (ump->out_cvts); + ump->out_cvts =NULL ;return err; }
Greg Kroah-Hartman
maintainerPATCH 113/261 ASoC: tas2562: fix DVC coefficient write order
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haidar Lee <[email protected]>
commit 8e957e4907c58e9ca944f98799524f2bbb9cf68a upstream.
The TAS2562 applies the 32-bit digital volume coefficient to the playback path when the last byte, DVC_CFG4 (book 0 page 2 reg 0x0F), is written. tas2562_volume_control_put() wrote DVC_CFG4 first and DVC_CFG1 (the MSB) last, so every volume change latched a value made of the previous coefficient's upper three bytes combined with the new LSB; the remaining bytes only took effect on the next volume change.
In practice the control was unusable: the first setting after power-on always played at roughly 0 dB no matter what value was requested (the chip's default upper bytes were still latched), and most subsequent changes muted the output entirely or produced a distorted, over-unity gain.
Verified on a TAS2562 (ADLINK OSM-520 / MT8189 board) by tracing the I2C writes with ftrace and by writing the same coefficients manually in both byte orders: written MSB-first the register block behaves exactly as the driver expects, LSB-first reproduces the broken behaviour.
Write the bytes MSB first with DVC_CFG4 last so the complete new coefficient is latched atomically.
--- sound/soc/codecs/tas2562.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-)
sound/soc/codecs/tas2562.c +15 -8
@@ -476,20 +476,27 @@ static int tas2562_volume_control_put(stu32 reg_val; reg_val = float_vol_db_lookup[ucontrol->value.integer.value[0 ]/2 ]; - ret =snd_soc_component_write (component,TAS2562_DVC_CFG4 , - (reg_val &0xff )); -if (ret) -return ret; - ret =snd_soc_component_write (component,TAS2562_DVC_CFG3 , - ((reg_val >>8 ) &0xff )); +/* +* The device applies the 32-bit coefficient to the playback path on +* the write to DVC_CFG4 (the LSB, book 0 page 2 reg 0x0F), so the +* bytes must be written MSB first and DVC_CFG4 last. Writing CFG4 +* first latches a mix of the previous coefficient's upper bytes and +* the new LSB instead of the requested value. +*/ + ret =snd_soc_component_write (component,TAS2562_DVC_CFG1 , + ((reg_val >>24 ) &0xff ));if (ret)return ret; ret =snd_soc_component_write (component,TAS2562_DVC_CFG2 , ((reg_val >>16 ) &0xff ));if (ret)return ret; - ret =snd_soc_component_write (component,TAS2562_DVC_CFG1 , - ((reg_val >>24 ) &0xff )); + ret =snd_soc_component_write (component,TAS2562_DVC_CFG3 , + ((reg_val >>8 ) &0xff )); +if (ret) +return ret; + ret =snd_soc_component_write (component,TAS2562_DVC_CFG4 , + (reg_val &0xff ));if (ret)return ret;
Greg Kroah-Hartman
maintainerPATCH 114/261 ASoC: tas2562: fix broken entries in the volume lookup table
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haidar Lee <[email protected]>
commit bdb0fd6de403fcea7b85dc9d38f0a571583ebe80 upstream.
The float_vol_db_lookup table is supposed to hold round(10^(dB/20) * 2^30) for every 2 dB step from -110 dB to 0 dB, which is 56 entries, but it only has 55: the -90 dB entry duplicates the -92 dB value (0x0000695b) and the -20 dB entry (0x06666666) is missing altogether. As a result every step between -90 dB and -22 dB is off by 2 dB, and the control's maximum raw value of 110 indexes one element past the end of the array.
Replace the duplicated -90 dB entry with the correct value 0x000084a3 and add the missing -20 dB entry, bringing the table to the full 56 entries so index 55 (raw value 110, 0 dB) is in range again.
--- sound/soc/codecs/tas2562.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
sound/soc/codecs/tas2562.c +4 -3
@@ -32,15 +32,16 @@static const unsigned int float_vol_db_lookup[] = {0x00000d43 ,0x000010b2 ,0x00001505 ,0x00001a67 ,0x00002151 ,0x000029f1 ,0x000034cd ,0x00004279 ,0x000053af ,0x0000695b , -0x0000695b ,0x0000a6fa ,0x0000d236 ,0x000108a4 ,0x00014d2a , +0x000084a3 ,0x0000a6fa ,0x0000d236 ,0x000108a4 ,0x00014d2a ,0x0001a36e ,0x00021008 ,0x000298c0 ,0x000344df ,0x00041d8f ,0x00052e5a ,0x000685c8 ,0x00083621 ,0x000a566d ,0x000d03a7 ,0x0010624d ,0x0014a050 ,0x0019f786 ,0x0020b0bc ,0x0029279d ,0x0033cf8d ,0x004139d3 ,0x00521d50 ,0x00676044 ,0x0082248a ,0x00a3d70a ,0x00ce4328 ,0x0103ab3d ,0x0146e75d ,0x019b8c27 ,0x02061b89 ,0x028c423f ,0x03352529 ,0x0409c2b0 ,0x05156d68 , -0x080e9f96 ,0x0a24b062 ,0x0cc509ab ,0x10137987 ,0x143d1362 , -0x197a967f ,0x2013739e ,0x28619ae9 ,0x32d64617 ,0x40000000 +0x06666666 ,0x080e9f96 ,0x0a24b062 ,0x0cc509ab ,0x10137987 , +0x143d1362 ,0x197a967f ,0x2013739e ,0x28619ae9 ,0x32d64617 , +0x40000000 };struct tas2562_data {
Greg Kroah-Hartman
maintainerPATCH 115/261 ata: libata-eh: Increase STANDBY IMMEDIATE timeout
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matt Vollrath <[email protected]>
commit 1e024d2b41ee32bc06818f7f09a3562c58842cf9 upstream.
Correct a previous change (see Fixes) which reduced the standby timeout from 30 to 5 seconds. Increase it to 15 seconds.
I was troubleshooting an error spotted during system suspend:
[ 1217.152867] ata1.00: Entering standby power mode
[ 1222.322948] ata1.00: qc timeout after 5000 msecs (cmd 0xe0)
[ 1222.324010] ata1.00: STANDBY IMMEDIATE failed (err_mask=0x4)This drive is a Samsung 870 EVO SSD in good SMART standing, and I wasn't aware of any reason it should be taking so long to standby. The issue is intermittent, but I observed it sometimes taking 7 seconds to manually standby. I assume this was interruption of background maintenance after a power outage.
As a desktop user, I would prefer to wait the extra 2 seconds at suspend to let the drive finish its business rather than drop the rails from under it.
The change from 30 to 5 seconds was implicit when switching suspend from START STOP UNIT to an internal command with no timeout table entry. No reason was stated for the change.
--- drivers/ata/libata-eh.c | 8 ++++++++ include/linux/libata.h | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-)
drivers/ata/libata-eh.c +8 -0
@@ -106,6 +106,12 @@ static const unsigned int ata_eh_flush_t UINT_MAX, }; +static const unsigned int ata_eh_standby_timeouts[] = { +15000 ,/* Some drives may be slow to standby */ +/* but don't hold up a suspend too long waiting for them */ +UINT_MAX , +}; +static const unsigned int ata_eh_other_timeouts[] = {5000 ,/* same rationale as identify timeout */ 10000 ,/* ditto */
@@ -147,6 +153,8 @@ ata_eh_cmd_timeout_table[ATA_EH_CMD_TIME .timeouts = ata_eh_other_timeouts, }, { .commands = CMDS(ATA_CMD_FLUSH, ATA_CMD_FLUSH_EXT), .timeouts = ata_eh_flush_timeouts }, + { .commands = CMDS(ATA_CMD_STANDBYNOW1), + .timeouts = ata_eh_standby_timeouts }, { .commands = CMDS(ATA_CMD_VERIFY), .timeouts = ata_eh_reset_timeouts }, };
include/linux/libata.h +1 -1
@@ -360,7 +360,7 @@ enum {/* This should match the actual table size of * ata_eh_cmd_timeout_table in libata-eh.c. */ - ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 8, + ATA_EH_CMD_TIMEOUT_TABLE_SIZE = 9,/* Horkage types. May be set by libata or controller on drives (some horkage may be drive/controller pair dependent */
Greg Kroah-Hartman
maintainerPATCH 116/261 ALSA: usb-audio: fix use-after-free in ump_to_endpoint()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baul Lee <[email protected]>
commit 4a05b2d1b4642df74f30b6f54843e825c4a2bfd3 upstream.
create_midi2_ump() registers a card-owned snd_ump_endpoint and stores a back-pointer to its per-interface snd_usb_midi2_ump object in ump->private_data, but it never installs an ump->private_free hook and never clears that pointer.
If a later step of snd_usb_midi_v2_create() fails, its error path calls free_all_midi2_umps(), which kfree()s the snd_usb_midi2_ump object while the already-registered endpoint keeps pointing at it. The created /dev/snd/umpC*D* node stays exposed, so the first operation of any UMP open, ump_to_endpoint(), dereferences the dangling ump->private_data and reads rmidi->eps[dir] out of freed memory.
A malicious USB MIDI 2.0 device that makes creation fail after the endpoint is registered can thus trigger a slab use-after-free read on a subsequent open of the UMP node.
Clear the endpoint's back-pointer before freeing the object, and let ump_to_endpoint() tolerate a NULL private_data so the open/close/trigger callbacks fail cleanly (their callers already handle a NULL endpoint) instead of dereferencing a stale pointer.
Discovered by XBOW, triaged by Baul Lee <[email protected]>
--- sound/usb/midi2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
sound/usb/midi2.c +3 -1
@@ -337,7 +337,7 @@ ump_to_endpoint(struct snd_ump_endpoint {struct snd_usb_midi2_ump *rmidi = ump->private_data; -return rmidi->eps[dir]; +return rmidi ? rmidi->eps[dir] :NULL ; }/* ump open callback */
@@ -703,6 +703,8 @@ static void free_all_midi2_umps(struct s rmidi =list_first_entry (&umidi->rawmidi_list, struct snd_usb_midi2_ump, list);list_del (&rmidi->list); +if (rmidi->ump) + rmidi->ump->private_data =NULL ;kfree (rmidi); } }
Greg Kroah-Hartman
maintainerPATCH 117/261 ALSA: usb-audio: fix OOB write in snd_usbmidi_akai_output()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baul Lee <[email protected]>
commit 0970274613fb463d376211450cab066d34ebfe6a upstream.
snd_usbmidi_akai_output() computes its fill-loop bound
buf_end = ep->max_transfer - MAX_AKAI_SYSEX_LEN - 1;
as a signed int, so a small device-advertised bulk-OUT max_transfer makes buf_end negative. The loop guard then compares the u32 urb->transfer_buffer_length against that negative int: the usual arithmetic conversion turns buf_end into a large unsigned value, so the guard stays true and each iteration keeps appending SysEx framing and payload bytes past the end of the URB transfer buffer, which is only max_transfer bytes long.
A USB device that advertises a tiny bulk-OUT endpoint can therefore trigger an attacker-length- and content-controlled heap out-of-bounds write when a process writes to the created /dev/snd/midiC*D* node.
Return early when there is no room for even one SysEx, so the loop is never entered with a bound that would wrap. The loop is the last statement of the function, so bailing out is equivalent to it not running.
Discovered by XBOW, triaged by Baul Lee <[email protected]>
--- sound/usb/midi.c | 2 ++ 1 file changed, 2 insertions(+)
sound/usb/midi.c +2 -0
@@ -800,6 +800,8 @@ static void snd_usbmidi_akai_output(stru msg = urb->transfer_buffer + urb->transfer_buffer_length; buf_end = ep->max_transfer -MAX_AKAI_SYSEX_LEN -1 ; +if (buf_end <=0 ) +return ;/* only try adding more data when there's space for at least 1 SysEx */ while (urb->transfer_buffer_length < buf_end) {
Greg Kroah-Hartman
maintainerPATCH 118/261 ALSA: usb-audio: Fix DMA buffer out-of-bounds write when fill_max is set
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sonali Pradhan <[email protected]>
commit d0199ae1666ff9ae2d1d568d64c3430d4c47f0e5 upstream.
When a USB audio endpoint requests full packet transfers via the fill_max descriptor flag, data_ep_set_params() promotes ep->curpacksize to ep->maxpacksize. However, maxsize is left at the original sample-rate derived value.
Since u->buffer_size is allocated as maxsize * packets, the resulting DMA buffer is far too small for the requested transfer length. When the USB host controller streams up to curpacksize bytes per packet, it writes past the end of the buffer via DMA, corrupting kernel heap memory.
Update maxsize to curpacksize when fill_max is set so that the allocated DMA buffer size matches the actual transfer request size.
[ changed to reassign maxsize only when ep->fill_max is set -- tiwai ]
--- sound/usb/endpoint.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
sound/usb/endpoint.c +4 -2
@@ -1185,10 +1185,12 @@ static int data_ep_set_params(struct snd << (16 - ep->datainterval); } -if (ep->fill_max) +if (ep->fill_max) { ep->curpacksize = ep->maxpacksize; -else + maxsize = ep->curpacksize; + }else { ep->curpacksize = maxsize; + }if (snd_usb_get_speed (chip->dev) !=USB_SPEED_FULL ) { packs_per_ms =8 >> ep->datainterval;
Greg Kroah-Hartman
maintainerPATCH 119/261 ALSA: usb-audio: Clamp frame size in implicit-feedback mode
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sonali Pradhan <[email protected]>
commit 8d7a30c50c2e58a6839634ed0acde14466d1dc61 upstream.
snd_usb_handle_sync_urb() scales received sync packet sizes by the sender's stride and stores the result directly in out_packet->packet_size[i]. If a connected USB device sends an oversized sync packet, this frame count can exceed ep->maxframesize.
The un-clamped frame count then propagates to the playback endpoint queue, potentially driving packet transfers beyond the endpoint's hardware frame limits.
Cap the calculated frame count against ep->maxframesize in snd_usb_handle_sync_urb() to prevent oversized packets from entering the playback queue.
--- sound/usb/endpoint.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
sound/usb/endpoint.c +5 -3
@@ -1834,11 +1834,13 @@ static void snd_usb_handle_sync_urb(stru out_packet->packets = in_ctx->packets;for (i =0 ; i < in_ctx->packets; i++) { -if (urb->iso_frame_desc[i].status ==0 ) - out_packet->packet_size[i] = +if (urb->iso_frame_desc[i].status ==0 ) { +unsigned int frames = urb->iso_frame_desc[i].actual_length / sender->stride; -else + out_packet->packet_size[i] =min (frames, ep->maxframesize); + }else { out_packet->packet_size[i] =0 ; + } }spin_unlock_irqrestore (&ep->lock, flags);
Greg Kroah-Hartman
maintainerPATCH 120/261 dmaengine: qcom: bam_dma: Fix command element mask field for BAM v1.6.0+
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Md Sadre Alam <[email protected]>
commit 867621ba203027338b525af6729719c544135336 upstream.
BAM version 1.6.0 and later changed the behavior of the mask field in command elements for read operations.
In older BAM versions, or prior implementation assumptions, the mask field was effectively ignored for read commands. However, starting from BAM v1.6.0, the mask field for read commands is repurposed to carry the upper 4 bits of the destination address, enabling support for 36-bit addressing. For write commands, the mask field continues to function as a traditional write mask.
The current driver sets mask = 0xffffffff for all command elements. While this works for write operations, it breaks read operations on BAM v1.6.0+ hardware. In such cases, the hardware interprets the upper address bits as 0xf, resulting in an invalid destination address (0xf_xxxxxxxx instead of 0x0_xxxxxxxx).
This leads to failures such as NAND enumeration issues observed on platforms like IPQ5424.
Fix this by assigning the mask field based on command type:
- For read commands: set mask = 0 (upper address bits = 0)
- For write commands: retain mask = 0xffffffff
Also update the bam_cmd_element structure documentation to reflect the dual purpose of the mask field across BAM versions.
This ensures correct behavior on BAM v1.6.0+ while maintaining backward compatibility with older hardware.
--- include/linux/dma/qcom_bam_dma.h | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
include/linux/dma/qcom_bam_dma.h +16 -5
@@ -13,9 +13,12 @@* supported by BAM DMA Engine. * * @cmd_and_addr - upper 8 bits command and lower 24 bits register address. -* @data - for write command: content to be written into peripheral register. -* for read command: dest addr to write peripheral register value. -* @mask - register mask. +* @data - For write command: content to be written into peripheral register. +* For read command: lower 32 bits of destination address. +* @mask - For write command: register write mask. +* For read command on BAM v1.6.0+: upper 4 bits of destination address. +* For read command on BAM < v1.6.0: ignored by hardware. +* Setting to 0 ensures 32-bit addressing compatibility. * @reserved - for future usage. * */
@@ -42,6 +45,10 @@ enum bam_command_type {* @addr: target address * @cmd: BAM command * @data: actual data for write and dest addr for read in le32 +* +* For BAM v1.6.0+, the mask field behavior depends on command type: +* - Write commands: mask = write mask (typically 0xffffffff) +* - Read commands: mask = upper 4 bits of destination address (0 for 32-bit) */ static inline void bam_prep_ce_le32(struct bam_cmd_element *bam_ce, u32 addr,
@@ -50,7 +57,11 @@ bam_prep_ce_le32(struct bam_cmd_element bam_ce->cmd_and_addr =cpu_to_le32 ((addr &0xffffff ) | ((cmd &0xff ) <<24 )); bam_ce->data = data; - bam_ce->mask =cpu_to_le32 (0xffffffff ); +if (cmd ==BAM_READ_COMMAND ) + bam_ce->mask =cpu_to_le32 (0x0 );/* 32-bit addressing */ +else + bam_ce->mask =cpu_to_le32 (0xffffffff );/* Write mask */ + bam_ce->reserved =0 ; }/*
@@ -60,7 +71,7 @@ bam_prep_ce_le32(struct bam_cmd_element* @bam_ce: BAM command element * @addr: target address * @cmd: BAM command -* @data: actual data for write and dest addr for read +* @data: actual data for write and destination address for read */ static inline void bam_prep_ce(struct bam_cmd_element *bam_ce, u32 addr,
Greg Kroah-Hartman
maintainerPATCH 121/261 e1000: fix memory leak in e1000_probe()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dawei Feng <[email protected]>
commit 816419dfea5c88126f35eb7a1b429a1bf546665e upstream.
In the e1000_probe() path, e1000_sw_init() allocates adapter->tx_ring and adapter->rx_ring. If the subsequent CE4100-specific MDIO BAR mapping fails, the error handling jumps past the ring cleanup code, leaking both allocations.
Fix this leak by moving the err_mdio_ioremap label above the ring deallocation logic. This guarantees the proper release of these resources and prevents the memory leak.
The bug was first flagged by an experimental analysis tool we are developing for kernel memory-management bugs while analyzing v6.13-rc1. The tool is still under development and is not yet publicly available. Manual inspection confirms that the bug is still present in v7.1-rc6.
An x86_64 allyesconfig build showed no new warnings. As we do not have a CE4100 reference platform to test with, no runtime testing was able to be performed.
--- drivers/net/ethernet/intel/e1000/e1000_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/intel/e1000/e1000_main.c +1 -1
@@ -1228,11 +1228,11 @@ err_eeprom:if (hw->flash_address)iounmap (hw->flash_address); +err_mdio_ioremap:kfree (adapter->tx_ring);kfree (adapter->rx_ring); err_dma: err_sw_init: -err_mdio_ioremap:iounmap (hw->ce4100_gbe_mdio_base_virt);iounmap (hw->hw_addr); err_ioremap:
Greg Kroah-Hartman
maintainerPATCH 122/261 igbvf: Fix leak in TX DMA error cleanup
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matt Vollrath <[email protected]>
commit 0565052b7e2f436b7f1541f4849da96dc0aa7a0e upstream.
If an error is encountered while mapping TX buffers, the driver should unmap any buffers already mapped for that skb.
Because count is incremented before each frag mapping, it will always match the correct number of unmappings needed when dma_error is reached. Decrementing count before the while loop in dma_error causes an off-by-one error. If any mapping was successful before an unsuccessful mapping, exactly one DMA mapping (the head) would leak.
This bug was introduced by a 2010 fix for an endless loop in dma_error. All other affected drivers have already been fixed.
--- drivers/net/ethernet/intel/igbvf/netdev.c | 2 -- 1 file changed, 2 deletions(-)
drivers/net/ethernet/intel/igbvf/netdev.c +0 -2
@@ -2201,8 +2201,6 @@ dma_error: buffer_info->time_stamp =0 ; buffer_info->length =0 ; buffer_info->mapped_as_page = false; -if (count) - count--;/* clear timestamp and dma mappings for remaining portion of packet */ while (count--) {
Greg Kroah-Hartman
maintainerPATCH 123/261 ipvs: do not propagate one-packet flag to synced conns
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhiling Zou <[email protected]>
commit a63d2dbaeb50a85d4c976b15a36e6b0c7113db5b upstream.
Synced connections can be created before their destination exists. When the destination is later added, ip_vs_bind_dest() copies connection flags from the destination into cp->flags.
IP_VS_CONN_F_ONE_PACKET connections are not synced. If a synced connection inherits IP_VS_CONN_F_ONE_PACKET while it is already hashed, expiry can treat it as a one-packet connection and skip unlinking the existing conn_tab node, leaving stale hash nodes pointing at a freed struct ip_vs_conn.
Drop IP_VS_CONN_F_ONE_PACKET from destination flags when binding synced connections.
--- net/netfilter/ipvs/ip_vs_conn.c | 3 +++ 1 file changed, 3 insertions(+)
net/netfilter/ipvs/ip_vs_conn.c +3 -0
@@ -598,6 +598,9 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, s flags = cp->flags;/* Bind with the destination and its corresponding transmitter */ if (flags &IP_VS_CONN_F_SYNC ) { +/* Synced conns are hashed, so they can not get this flag */ + conn_flags &= ~IP_VS_CONN_F_ONE_PACKET ; +/* if the connection is not template and is created * by sync, preserve the activity flag. */
Greg Kroah-Hartman
maintainerPATCH 124/261 net/smc: fix socket use-after-free during link group termination
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xuanqiang Luo <[email protected]>
commit f621d6ebeebb6374342571e4ddf45fdbc420f6cd upstream.
__smc_lgr_terminate() drops conns_lock after finding a connection in lgr->conns_all, but before taking a reference on its socket. The connection is embedded in the socket, and its registration reference protects it only while the connection remains in the tree.
A concurrent close can unregister the connection and drop that reference, freeing the socket before the termination worker reaches sock_hold().
The race is reachable when close overlaps link group termination. Local stress testing reproduced the use-after-free and KASAN reported:
BUG: KASAN: slab-use-after-free in __smc_lgr_terminate.part.0 [smc] Write of size 4 by task kworker/3:3 Workqueue: events smc_lgr_terminate_work [smc] __smc_lgr_terminate.part.0 [smc]
The socket was allocated by smc_create(), freed through slab_free_after_rcu_debug(), and was followed by:
refcount_t: addition on 0; use-after-free.
__smc_lgr_terminate.part.0 [smc]
Take the socket reference while conns_lock still protects the tree entry. The unregister path then cannot drop the last reference until termination has finished using the socket.
--- net/smc/smc_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/smc/smc_core.c +1 -1
@@ -1502,10 +1502,10 @@ static void __smc_lgr_terminate(struct sread_lock_bh (&lgr->conns_lock); node =rb_first (&lgr->conns_all);while (node) { -read_unlock_bh (&lgr->conns_lock); conn = rb_entry(node, struct smc_connection, alert_node); smc = container_of(conn, struct smc_sock, conn);sock_hold (&smc->sk);/* sock_put below */ +read_unlock_bh (&lgr->conns_lock);lock_sock (&smc->sk);smc_conn_kill (conn, soft);release_sock (&smc->sk);
Greg Kroah-Hartman
maintainerPATCH 125/261 netfilter: ipset: do not update comments from kernel-side hash adds
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lee <[email protected]>
commit f30415929be8aeb002d557c8d3f7ab2d2188003a upstream.
mtype_resize() copies comment pointers with memcpy(), not the comment objects themselves. During the window after an entry has been copied but before the table swap and backlog replay, the old table is still published for packet-side updates while the replacement-table entry already holds the same ip_set_comment_rcu pointer.
If xt_SET --add-set ... --exist hits that old entry in this window, mtype_add() calls ip_set_init_comment() even though packet-side adds carry no comment payload. That call frees the shared comment through the old entry, so the replacement-table entry now holds a stale pointer. When the queued add is replayed on the new table, mtype_add() calls ip_set_init_comment() again and strlen() dereferences the stale pointer.
Fix this in mtype_add() by skipping ip_set_init_comment() when ext->target marks a packet-side add. Userspace adds still update comments, while packet-side adds can no longer free comment storage shared with a resize copy.
--- net/netfilter/ipset/ip_set_hash_gen.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/ipset/ip_set_hash_gen.h +1 -1
@@ -983,7 +983,7 @@ overwrite_extensions:#endif if (SET_WITH_COUNTER (set))ip_set_init_counter (ext_counter (data, set), ext); -if (SET_WITH_COMMENT (set)) +if (SET_WITH_COMMENT (set) && !ext->target)ip_set_init_comment (set,ext_comment (data, set), ext);if (SET_WITH_SKBINFO (set))ip_set_init_skbinfo (ext_skbinfo (data, set), ext);
Greg Kroah-Hartman
maintainerPATCH 126/261 tipc: avoid use-after-free in poll trace queue dumps
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zihan Xi <[email protected]>
commit b4f1719dfea023220e0e6bd892b087d76b2a6a49 upstream.
TIPC socket tracepoints dump queue state through tipc_sk_dump(). Most queue-dump callsites already serialize that walk under the socket lock or sk->sk_lock.slock, but tipc_poll() calls trace_tipc_sk_poll(..., TIPC_DUMP_ALL, ...) without holding either lock.
That lets the poll trace path reach tipc_list_dump() and backlog head/tail dumping while another context dequeues and frees an skb, leaving the trace helper dereferencing a stale queue entry.
Stop the unlocked poll trace site from requesting queue dumps. Other queue dump trace callsites keep their existing output under the locking they already provide, while poll still emits the event itself without walking live queue members from an unlocked context.
--- net/tipc/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/tipc/socket.c +1 -1
@@ -798,7 +798,7 @@ static __poll_t tipc_poll(struct file *f__poll_t revents =0 ;sock_poll_wait (file, sock, wait); -trace_tipc_sk_poll (sk,NULL ,TIPC_DUMP_ALL ," " ); +trace_tipc_sk_poll (sk,NULL ,TIPC_DUMP_NONE ," " );if (sk->sk_shutdown &RCV_SHUTDOWN ) revents |=EPOLLRDHUP |EPOLLIN |EPOLLRDNORM ;
Greg Kroah-Hartman
maintainerPATCH 127/261 wifi: mwifiex: use the subframe length when parsing A-MSDU TDLS frames
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhao Li <[email protected]>
commit 99a948382af8a225e2d5e54a7052158cd6281cc6 upstream.
mwifiex_11n_dispatch_amsdu_pkt() splits an A-MSDU with ieee80211_amsdu_to_8023s() and walks the resulting subframes. For each subframe it passes the subframe data pointer to mwifiex_process_tdls_action_frame(), but pairs it with skb->len, the length of the A-MSDU parent, instead of rx_skb->len:
rx_skb = __skb_dequeue(&list);
rx_hdr = (struct rx_packet_hdr *)rx_skb->data;
if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) &&
ntohs(rx_hdr->eth803_hdr.h_proto) == ETH_P_TDLS) {
mwifiex_process_tdls_action_frame(priv, (u8 *)rx_hdr,
skb->len);
}The parent is not a valid description of that buffer, and may not be valid memory at all. ieee80211_amsdu_to_8023s() ends with
if (!reuse_skb) dev_kfree_skb(skb);
and it only sets reuse_skb when the parent is linear, is not a head_frag, and is being consumed as the *last* subframe. So when the parent does not qualify for reuse it has already been freed, and the read of skb->len is a use-after-free. When it is reused, skb->len is the length of the last subframe, applied to every earlier subframe, which over-states the buffer whenever an earlier subframe is shorter.
The callee cannot absorb a wrong length, because it derives its own ceiling from the value it is given. Each frame type computes
ies_len = len - sizeof(struct ethhdr) - TDLS_*_FIX_LEN;
and the element walk is then bounded entirely against that ceiling,
for (end = pos + ies_len; pos + 1 < end; pos += 2 + pos[1]) {
u8 ie_len = pos[1];
if (pos + 2 + ie_len > end)
break;so a too-large len moves end past the end of the subframe and the walk reads and copies beyond it. The A-MSDU layout is chosen by the sender, which makes the difference between the last subframe and a shorter earlier one remotely selectable. Reaching this requires TDLS support in firmware and the TDLS ethertype on the subframe.
The other caller, mwifiex_process_rx_packet(), is correct: it passes a pointer and a length that describe the same region of the RX buffer.
Pass rx_skb->len, the length of the subframe actually being parsed.
--- drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +1 -1
@@ -44,7 +44,7 @@ static int mwifiex_11n_dispatch_amsdu_pk ntohs(rx_hdr->eth803_hdr.h_proto) == ETH_P_TDLS) {mwifiex_process_tdls_action_frame (priv, (u8 *)rx_hdr, - skb->len); + rx_skb->len); }if (priv->bss_role ==MWIFIEX_BSS_ROLE_UAP )
Greg Kroah-Hartman
maintainerPATCH 128/261 binfmt_misc: reject a flag character as the field delimiter
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <[email protected]>
commit 8e85d50ba1117fd446bf9a250bd8a97d48384bdc upstream.
The registration string starts with a user chosen delimiter that separates the individual fields. So that the field parsers terminate even on a truncated string create_entry() pads the buffer with that same delimiter:
memset(buf + count, del, 8);
Most fields are scanned for the delimiter with strchr()/scanarg() and happily stop on the padding. The flags field is different: instead of scanning for the delimiter check_special_flags() consumes the flag characters 'P', 'O', 'C' and 'F' and stops at the first byte that is none of them, relying on the trailing delimiter to end the scan.
If the delimiter is itself a flag character the padding no longer acts as a terminator. The scan swallows all eight padding bytes and keeps reading past the end of the allocation until it hits a byte that is not a flag character. For example registering
PaPEPPxPPiP
with 'P' as the delimiter (name "a", type extension, magic "x", interpreter "i", empty flags) leaves the flag scan running off the end of the buffer. The registration is rejected in the end because the parser does not stop exactly at buf + count, but only after the out of bounds read has already happened. With an unlucky allocation layout the scan can walk into an unmapped page; under KASAN it is reported as a slab out of bounds read. binfmt_misc mounts are available to unprivileged users in a user namespace so the read is reachable without privileges.
Reject a delimiter that is one of the flag characters up front. Such a registration was always rejected anyway, only after the out of bounds read, so no valid registration string changes meaning.
--- fs/binfmt_misc.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/binfmt_misc.c +4 -0
@@ -347,6 +347,10 @@ static Node *create_entry(const char __upr_debug ("register: delim: %#x {%c}\n" , del, del); +/* A flag-char delimiter runs the flag scan off the buffer. */ +if (del =='P' || del =='O' || del =='C' || del =='F' ) + goto einval; +/* Pad the buffer with the delim to simplify parsing below. */ memset (buf + count, del,8 );
Greg Kroah-Hartman
maintainerPATCH 129/261 mm/page_reporting: use system_freezable_wq to fix UAF during suspend
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Link Lin <[email protected]>
commit 0b45f6927a14914ff685fe0e6f9d11232a1e03df upstream.
During PM freeze (e.g. S3 suspend or S4 hibernation), device drivers like virtio_balloon reset their underlying virtio devices and delete their virtqueues via vdev->config->del_vqs().
However, page reporting work (page_reporting_process) was scheduled on the global system_wq. Because system_wq lacks the WQ_FREEZABLE flag, the PM freezer skips it, leaving page_reporting_process active during suspend.
If pages are freed into the buddy allocator while suspending (for example, when core MM invokes the balloon shrinker during S4 hibernation image saving), page reporting triggers virtballoon_free_page_report() on deleted virtqueues, resulting in a Use-After-Free / General Protection Fault:
[ 196.795226] general protection fault, probably for non-canonical address 0xaa1436fe70dae6df: 0000 [#1] SMP NOPTI
[ 196.825967] Workqueue: events page_reporting_process
[ 196.831038] RIP: 0010:virtqueue_add_split+0x233/0x4c0 [virtio_ring]
[ 196.927073] virtballoon_free_page_report+0x3a/0xe0 [virtio_balloon]
[ 196.946943] page_reporting_process+0x370/0x4f0Fix this by switching page reporting work to system_freezable_wq. This ensures that the PM freezer pauses page_reporting_process before device drivers destroy their reporting virtqueues. Because the reporting worker is frozen, memory reclamation/freeing (e.g. via shrinker execution) can safely return pages to MM during freeze without triggering unfrozen reporting work on deleted virtqueues.
This aligns with the driver's existing design. The comment in virtballoon_freeze() states:
/*
* The workqueue is already frozen by the PM core before this
* function is called.
*/
Testing:
I have verified these fixes using Google’s virtualization infrastructure by running continuous suspend/resume iterations (40+ cycles) while churning memory using stress-ng (stress-ng --vm 4 --vm-bytes 60% --timeout 1) to constantly create free pages for the buddy allocator. We also set the page_reporting_order parameter to 0 to make the page reporting worker highly sensitive, forcing it to pick up any 4K free pages. This confirmed that the UAF crashes are no longer reproducible.
--- mm/page_reporting.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
mm/page_reporting.c +4 -2
@@ -80,7 +80,8 @@ __page_reporting_request(struct page_rep* now we are limiting this to running no more than once every * couple of seconds. */ -schedule_delayed_work (&prdev->work,PAGE_REPORTING_DELAY ); +queue_delayed_work (system_freezable_wq, &prdev->work, +PAGE_REPORTING_DELAY ); }/* notify prdev of free page reporting request */
@@ -343,7 +344,8 @@ err_out:*/ state =atomic_cmpxchg (&prdev->state, state,PAGE_REPORTING_IDLE );if (state ==PAGE_REPORTING_REQUESTED ) -schedule_delayed_work (&prdev->work,PAGE_REPORTING_DELAY ); +queue_delayed_work (system_freezable_wq, &prdev->work, +PAGE_REPORTING_DELAY ); }static DEFINE_MUTEX (page_reporting_mutex);
Greg Kroah-Hartman
maintainerPATCH 130/261 net: bridge: stop fast-leave after deleting a port group
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhiling Zou <[email protected]>
commit a39789f211b8a4125f0c70e05b30cf715f4f187d upstream.
br_multicast_leave_group() iterates mp->ports with pp = &p->next in its fast-leave path. After br_multicast_del_pg() removes p, continuing the loop advances pp through the deleted entry.
If multicast-to-unicast was enabled, the bridge can hold multiple port groups for the same port and group with different source MAC addresses. Once multicast-to-unicast is disabled, br_port_group_equal() matches those entries by port only. A fast leave can then delete one entry and continue from its stale next pointer, leaving mp->ports pointing at a deleted port group.
Fast leave only needs to remove one matching port group. Break after br_multicast_del_pg() so the loop stops before dereferencing the removed entry.
--- net/bridge/br_multicast.c | 1 + 1 file changed, 1 insertion(+)
net/bridge/br_multicast.c +1 -0
@@ -3684,6 +3684,7 @@ br_multicast_leave_group(struct net_brid p->flags |=MDB_PG_FLAGS_FAST_LEAVE ;br_multicast_del_pg (mp, p, pp); +break ; } goto out; }
Greg Kroah-Hartman
maintainerPATCH 131/261 net: ipv6: clear suppressed fib6 rule result
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhiling Zou <[email protected]>
commit 6aea62e433fe1b586202a5fee8b5807ce635e1d7 upstream.
fib6_rule_suppress() drops a suppressed route with ip6_rt_put_flags(), but leaves res->rt6 pointing at the released rt6_info.
If no later rule supplies a replacement, fib6_rule_lookup() still sees res.rt6 and returns that stale dst to its caller. A suppressing rule can therefore leak a released route back to rt6_lookup(), and the next put hits rcuref_put_slowpath() from dst_release().
Clear res->rt6 when suppressing the route so suppressed lookups fall through to the null dst instead of reusing the released one.
--- net/ipv6/fib6_rules.c | 1 + 1 file changed, 1 insertion(+)
net/ipv6/fib6_rules.c +1 -0
@@ -301,6 +301,7 @@ INDIRECT_CALLABLE_SCOPE bool fib6_rule_s suppress_route:ip6_rt_put_flags (rt, flags); + res->rt6 =NULL ;return true; }
Greg Kroah-Hartman
maintainerPATCH 132/261 powerpc/ps3: Fix map failure path in dma_ioc0_map_pages()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
commit 0bb024f11d120abff3e8db9144a585b9d7fb8459 upstream.
If lv1_put_iopte() fails in dma_ioc0_map_pages(), the error path decrements iopage but keeps using the failed mapping's offset. As a result, it repeatedly tries to invalidate the failed IOPTE slot and leaves the already installed IOPTEs valid.
Recompute offset and invalidate the installed IOPTEs instead.
--- arch/powerpc/platforms/ps3/mm.c | 1 + 1 file changed, 1 insertion(+)
arch/powerpc/platforms/ps3/mm.c +1 -0
@@ -615,6 +615,7 @@ static int dma_ioc0_map_pages(struct ps3 fail_map:for (iopage--;0 <= iopage; iopage--) { + offset = (1 << r->page_size) * iopage; lv1_put_iopte(0, c->bus_addr + offset, c->lpar_addr + offset,
Greg Kroah-Hartman
maintainerPATCH 133/261 um: vector: fix use-after-free in vector_mmsg_rx()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit af421e9aed3920c7ac88c24daa48606c7112feca upstream.
When vector_mmsg_rx() discards a packet whose overlay header fails verify_header(), it frees the skb and continues the loop:
if (header_check < 0) {
dev_kfree_skb_irq(skb);
vp->estats.rx_encaps_errors++;
continue;
}The normal and short-packet paths fall through to the bottom of the loop body, which clears the consumed slot and advances the cursors:
(*skbuff_vector) = NULL; mmsg_vector++; skbuff_vector++;
The verify_header() < 0 path skips that via continue, so the freed skb is left in skbuff_vector[] and the cursors do not advance. The next iteration reads the same slot, gets the freed skb, and frees it again, producing a refcount underflow / use-after-free in the RX path.
Discard the slot the same way the other paths do before continuing.
Only transports whose verify_header() can return negative are affected:
GRE and L2TPv3 do so on a cookie/session-id mismatch (raw/tap do not), so any peer on such a transport can trigger it without authentication.
--- arch/um/drivers/vector_kern.c | 3 +++ 1 file changed, 3 insertions(+)
arch/um/drivers/vector_kern.c +3 -0
@@ -1007,6 +1007,9 @@ static int vector_mmsg_rx(struct vector_*/ dev_kfree_skb_irq (skb); vp->estats.rx_encaps_errors++; + (*skbuff_vector) =NULL ; + mmsg_vector++; + skbuff_vector++;continue ; }if (header_check >0 ) {
Greg Kroah-Hartman
maintainerPATCH 134/261 vxlan: re-fetch eth header after route_shortcircuit()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 1395a676ec15a0a02a2a6d86602324f2d5fd41d5 upstream.
Before route_shortcircuit(), the eth header pointer is cached from eth_hdr(skb).
Inside route_shortcircuit(), pskb_may_pull() can be called, which may reallocate skb->head.
In this case, returning to vxlan_xmit() leaves the cached eth pointer pointing to freed memory, leading to a use-after-free when dereferencing eth->h_dest.
Fix this by updating eth = eth_hdr(skb) after calling route_shortcircuit().
--- drivers/net/vxlan/vxlan_core.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/vxlan/vxlan_core.c +1 -0
@@ -2863,6 +2863,7 @@ static netdev_tx_t vxlan_xmit(struct sk_ (ntohs(eth->h_proto) == ETH_P_IP || ntohs(eth->h_proto) == ETH_P_IPV6)) { did_rsc =route_shortcircuit (dev, skb); + eth =eth_hdr (skb);if (did_rsc) f =vxlan_find_mac (vxlan, eth->h_dest, vni); }
Greg Kroah-Hartman
maintainerPATCH 135/261 vxlan: unclone skb head before modifying eth header in route_shortcircuit()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 760d36e737f2b3867762f42af36c663f55babcc4 upstream.
When route_shortcircuit() performs L3 short-circuit routing, it modifies the Ethernet header of the skb in-place:
memcpy(eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, dev->addr_len);
memcpy(eth_hdr(skb)->h_dest, n->ha, dev->addr_len);If the incoming skb is cloned (for example by packet sockets, tcpdump, or dev_queue_xmit), modifying the Ethernet header without uncloning can corrupt the packet header for other readers holding a reference to the cloned skb.
Ensure the skb header is writable and unshared by calling skb_cow_head(skb, 0) prior to updating the Ethernet header. If skb_cow_head() fails, abort short-circuiting and return false to allow standard packet processing fallback.
--- drivers/net/vxlan/vxlan_core.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/vxlan/vxlan_core.c +4 -0
@@ -2163,6 +2163,10 @@ static bool route_shortcircuit(struct ne diff = !ether_addr_equal (eth_hdr (skb)->h_dest, n->ha);if (diff) { +if (skb_cow_head (skb,0 )) { +neigh_release (n); +return false; + }memcpy (eth_hdr (skb)->h_source,eth_hdr (skb)->h_dest, dev->addr_len);memcpy (eth_hdr (skb)->h_dest, n->ha, dev->addr_len);
Greg Kroah-Hartman
maintainerPATCH 136/261 vxlan: use neigh_ha_snapshot() in route_shortcircuit()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 8eca411347e1d38964f9ed2c8d3b6ab0e7e4473d upstream.
The neighbour hardware address n->ha can be updated asynchronously by the neighbour subsystem, protected by n->ha_lock seqlock. Reading n->ha without holding the seqlock loop can lead to torn reads or reading a partially updated MAC address.
Use neigh_ha_snapshot() in route_shortcircuit() to safely copy n->ha under read_seqbegin()/read_seqretry() lock protection before using it.
Note that arp_reduce() and neigh_reduce() seem to have the same issue left for future patches.
--- drivers/net/vxlan/vxlan_core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/vxlan/vxlan_core.c +4 -2
@@ -2159,9 +2159,11 @@ static bool route_shortcircuit(struct ne }if (n) { +u8 haddr[ETH_ALEN ];bool diff; - diff = !ether_addr_equal (eth_hdr (skb)->h_dest, n->ha); +neigh_ha_snapshot (haddr, n, dev); + diff = !ether_addr_equal_unaligned (eth_hdr (skb)->h_dest, haddr);if (diff) {if (skb_cow_head (skb,0 )) {neigh_release (n);
@@ -2169,7 +2171,7 @@ static bool route_shortcircuit(struct ne }memcpy (eth_hdr (skb)->h_source,eth_hdr (skb)->h_dest, dev->addr_len); -memcpy (eth_hdr (skb)->h_dest, n->ha, dev->addr_len); +memcpy (eth_hdr (skb)->h_dest, haddr, dev->addr_len); }neigh_release (n);return diff;
Greg Kroah-Hartman
maintainerPATCH 137/261 vxlan: use pskb_network_may_pull() in route_shortcircuit()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
commit 26bb2dd0a8839617e2c79ffbbe1923f8e4bab9fb upstream.
route_shortcircuit() currently calls pskb_may_pull(skb, sizeof(struct iphdr)) (or ipv6hdr), which checks if bytes are available starting from skb->data.
However, in vxlan_xmit(), skb->data points to the MAC header, so skb_network_offset(skb) is ETH_HLEN (14 bytes). Using pskb_may_pull(skb, 20) only checks 20 bytes from skb->data (which is 14 bytes MAC header + 6 bytes of IP header), leaving the rest of the IP header potentially un-pulled in non-linear frags. Subsequent dereferences of ip_hdr(skb)->daddr can read beyond the pulled linear buffer length.
Fix this by using pskb_network_may_pull(), which adds skb_network_offset(skb) to the length check to ensure the full network header is present in the linear buffer.
--- drivers/net/vxlan/vxlan_core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/vxlan/vxlan_core.c +2 -2
@@ -2111,7 +2111,7 @@ static bool route_shortcircuit(struct ne {struct iphdr *pip; -if (!pskb_may_pull (skb,sizeof (struct iphdr ))) +if (!pskb_network_may_pull (skb,sizeof (struct iphdr )))return false; pip =ip_hdr (skb); n =neigh_lookup (&arp_tbl, &pip->daddr, dev);
@@ -2137,7 +2137,7 @@ static bool route_shortcircuit(struct ne*/ if (!ipv6_stub->nd_tbl)return false; -if (!pskb_may_pull (skb,sizeof (struct ipv6hdr ))) +if (!pskb_network_may_pull (skb,sizeof (struct ipv6hdr )))return false; pip6 =ipv6_hdr (skb); n =neigh_lookup (ipv6_stub->nd_tbl, &pip6->daddr, dev);
Greg Kroah-Hartman
maintainerPATCH 138/261 ublk: reset kernel-owned dev_info fields in ublk_ctrl_add_dev()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Lei <[email protected]>
commit e65848e4ce352bac9e3465099354c8b8f845391f upstream.
ublk_ctrl_add_dev() memcpy()s the userspace ublksrv_ctrl_dev_info into ub->dev_info and then fixes up the fields the driver owns, but misses ->state and ->ublksrv_pid.
A device added with ->state = UBLK_S_DEV_LIVE passes the "->state != UBLK_S_DEV_DEAD" test that ublk_stop_dev_unlocked() uses as its proxy for "a disk is attached", while ->ub_disk is still NULL, so DEL_DEV right after ADD_DEV oopses in del_gendisk(). UBLK_S_DEV_QUIESCED plus UBLK_F_USER_RECOVERY dies one step earlier, in ublk_force_abort_dev(). A poisoned ->state also gets START_USER_RECOVERY and the char device read/write path onto a device that was never started, and wedges START_DEV at -EEXIST. A poisoned ->ublksrv_pid just makes GET_DEV_INFO report an unrelated task as the ublk server.
Reset both after the memcpy(), as ublk_detach_disk() does. Userspace only ever reads these back, so correcting them silently breaks nothing.
ADD_DEV has copied ->state in unsanitized since ublk was merged, but back then it was harmless: the gendisk was allocated during ADD_DEV, and both teardown and the START_DEV -EEXIST check keyed off disk_live() rather than ->state. The oops became reachable once the disk allocation moved to START_DEV and those checks switched to ->state.
--- drivers/block/ublk_drv.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/block/ublk_drv.c +9 -0
@@ -2438,6 +2438,15 @@ static int ublk_ctrl_add_dev(struct io_u ub->dev_info.dev_id = ub->ub_number;/* +* ->state and ->ublksrv_pid are owned by the driver and only read back +* by userspace, but they come from the copied-in dev_info, so reset +* them. Otherwise a device added with ->state != DEAD looks live while +* ->ub_disk is still NULL. +*/ + ub->dev_info.state =UBLK_S_DEV_DEAD ; + ub->dev_info.ublksrv_pid =-1 ; + +/* * 64bit flags will be copied back to userspace as feature * negotiation result, so have to clear flags which driver * doesn't support yet, then userspace can get correct flags
Greg Kroah-Hartman
maintainerPATCH 139/261 tracing: Check return value of __register_event() in trace_module_add_events()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <[email protected]>
commit ac8719969e6c3c54e939834df812bc41f25453cf upstream.
trace_module_add_events() ignores the return value of __register_event() and unconditionally calls __add_event_to_tracers() for each event.
If __register_event() fails (for example, if event_init() fails), the trace_event_call is not added to ftrace_events list, but __add_event_to_tracers() still creates a trace_event_file pointing to it. If module loading subsequently fails and module memory is freed, tracing state retains a stale trace_event_call pointer in trace_event_file, leading to a use-after-free when tracefs or tracing subsystem operations are later executed.
Fix this by checking the return value of __register_event() and only calling __add_event_to_tracers() if event registration succeeded.
--- kernel/trace/trace_events.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/trace/trace_events.c +2 -2
@@ -3373,8 +3373,8 @@ static void trace_module_add_events(stru end = mod->trace_events + mod->num_trace_events;for_each_event (call, start, end) { -__register_event (*call, mod); -__add_event_to_tracers (*call); +if (!__register_event (*call, mod)) +__add_event_to_tracers (*call); } }
Greg Kroah-Hartman
maintainerPATCH 140/261 tracing/filters: Fix false positive match in regex_match_full()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <[email protected]>
commit c22c7b735f9810ad276014f788f9aa5c879ec238 upstream.
regex_match_full() calls strncmp(str, r->pattern, len) where len is the target field buffer size. When len is smaller than r->len (the filter pattern length), strncmp() checks only len bytes of r->pattern against str. If those len bytes match, strncmp() returns 0, resulting in a false-positive match where a shorter string in a fixed-size field matches a longer filter pattern.
For example, a 4-byte static string field containing "abcd" matched the filter pattern "abcdefgh" because strncmp("abcd", "abcdefgh", 4) returned 0. In this case, @len does NOT include '\0' because it is fixed-size array.
Fix this by returning 0 (no match) early when len < r->len.
--- kernel/trace/trace_events_filter.c | 3 +++ 1 file changed, 3 insertions(+)
kernel/trace/trace_events_filter.c +3 -0
@@ -1027,6 +1027,9 @@ static int regex_match_full(char *str, sif (!len)return strcmp (str, r->pattern) ==0 ; +if (len < r->len) +return 0 ; +return strncmp (str, r->pattern, len) ==0 ; }
Greg Kroah-Hartman
maintainerPATCH 141/261 spi: qcom-qspi: Correct max DMA length to avoid 64K boundary failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vijaya Krishna Nivarthi <[email protected]>
commit 90ef2f2961c2dc55957dafe2f53b3efdb4675efc upstream.
The maximum size for a DMA data descriptor is 64KB-1 because the size field in HW is 16 bits wide. For this reason, transfers fail at 64KB and beyond.
Lower max_dma_len to 60KB so larger transfers are split into multiple DMA blocks and do not hit the failing 64KB boundary. 60KB is chosen as a safe round number below the 64KB-1 hardware limit while satisfying alignment requirements.
Tested on x1e80100 (Hamoa) with SPI-NOR flash (/dev/mtd0):
Without patch:
dd if=/dev/mtd0 of=/tmp/spi_dump.bin bs=32768 count=2 # works dd if=/dev/mtd0 of=/tmp/spi_dump.bin bs=65536 count=1 # fails
With patch:
dd if=/dev/mtd0 of=/tmp/spi_dump.bin bs=65536 count=1 # works
--- drivers/spi/spi-qcom-qspi.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/spi/spi-qcom-qspi.c +2 -1
@@ -759,7 +759,8 @@ static int qcom_qspi_probe(struct platforeturn dev_err_probe (dev, ret,"could not set DMA mask\n" ); host->max_speed_hz =300000000 ; - host->max_dma_len =65536 ;/* as per HPG */ +/* as per HPG, it is 64KB, limit to 60KB to avoid boundary condition failures */ + host->max_dma_len =0xf000 ; host->dma_alignment =QSPI_ALIGN_REQ ; host->num_chipselect =QSPI_NUM_CS ; host->bus_num =-1 ;