6.12.103-rc1 review
Subsystems (2)
Greg Kroah-Hartman
maintainercover 6.12.103-rc1 review
This is the start of the stable review cycle for the 6.12.103 release. There are 337 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.12.103-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.12.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 6.12.103-rc1
Thomas Zimmermann <[email protected]>
drm/tegra: fbdev: Do not assign to struct drm_fb_helper.info
Bart Van Assche <[email protected]>
drm/fb-helper: Fix a locking bug in an error path
Andrei Kuchynski <[email protected]>
usb: typec: ucsi: Correct teardown ordering in ucsi_init() error path
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
David Howells <[email protected]>
rxrpc: Fix irq-disabled in local_bh_enable()
David Howells <[email protected]>
rxrpc: Manage RTT per-call rather than per-peer
David Howells <[email protected]>
rxrpc: Fix the calculation and use of RTO
David Howells <[email protected]>
rxrpc: Adjust the rxrpc_rtt_rx tracepoint
David Howells <[email protected]>
rxrpc: Generate rtt_min
Zongyao Bai <[email protected]>
drm/xe/pt: Reset current_op in xe_pt_update_ops_init()
Matthew Brost <[email protected]>
drm/xe: Stub out new pagefault layer
Jani Nikula <[email protected]>
drm/i915/hdcp: check streams[] bounds before overflow
Suraj Kandpal <[email protected]>
drm/i915/hdcp: Skip inactive MST connectors when building stream list
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
Nitin Gote <[email protected]>
drm/xe: Hold a dma-buf reference for imported BOs
Thomas Hellström <[email protected]>
drm/xe: Rename ___xe_bo_create_locked()
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()
Matthew Brost <[email protected]>
drm/xe: Wait on external BO kernel fences in exec IOCTL
Thomas Hellström <[email protected]>
drm/exec: Remove the index parameter from drm_exec_for_each_locked_obj[_reverse]
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
Asad Kamal <[email protected]>
drm/amdgpu/gfx: fix cleaner shader IB buffer overflow
Pierre-Eric Pelloux-Prayer <[email protected]>
drm/amdgpu: give each kernel job a unique id
Pierre-Eric Pelloux-Prayer <[email protected]>
drm/sched: Store the drm client_id in drm_sched_fence
Tvrtko Ursulin <[email protected]>
drm/amdgpu: Fix context pstate override handling
Timur Kristóf <[email protected]>
drm/amdgpu: Respect placement requirements in amdgpu_gtt_mgr functions
Breno Leitao <[email protected]>
mm/kmemleak: fix checksum computation for per-cpu objects
Catalin Marinas <[email protected]>
kmemleak: iommu/iova: fix transient kmemleak false positive
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
Kai Vehmanen <[email protected]>
ALSA: hda: codecs: hdmi: disable keep-alive before audio format change
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()
Fan Wu <[email protected]>
wifi: brcmfmac: drain bus_reset work on device removal
Niklas Söderlund <[email protected]>
media: uapi: rkisp: Correct name version enum
Jackson Lee <[email protected]>
media: chips-media: wave5: Support CBP profile
Sakari Ailus <[email protected]>
media: imx219: Fix maximum frame length in lines
Jai Luthra <[email protected]>
media: i2c: imx219: Rename VTS to FRM_LENGTH
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
Cen Zhang <[email protected]>
usb: gadget: f_tcm: synchronize delayed set_alt with teardown
Junjie Cao <[email protected]>
gpio: pch: use raw_spinlock_t for the register lock
Harry Yoo (Oracle) <[email protected]>
mm/slab: prevent unbounded recursion in free path with new kmalloc type
Harry Yoo (Oracle) <[email protected]>
lib/alloc_tag: introduce mem_alloc_profiling_permanently_disabled()
Kiryl Shutsemau (Meta) <[email protected]>
mm/huge_memory: unlock i_mmap_rwsem before releasing after-split folios
Kiryl Shutsemau (Meta) <[email protected]>
fs/proc/task_mmu: fix PAGEMAP_SCAN written state for unpopulated ptes
Kiryl Shutsemau (Meta) <[email protected]>
mm/hugetlb: fix swap entry corruption when clearing uffd-wp at fork()
Ashutosh Dixit <[email protected]>
drm/xe/rtp: Ensure locking/ref counting for OA whitelists
Ashutosh Dixit <[email protected]>
drm/xe/oa: (De-)whitelist OA registers on OA stream open/release
Ashutosh Dixit <[email protected]>
drm/xe/rtp: (De-)whitelist OA registers for all hwe's for a gt
Ashutosh Dixit <[email protected]>
drm/xe/rtp: Toggle 'deny' bit to (de-)whitelist OA regs
Ashutosh Dixit <[email protected]>
drm/xe/rtp: Save OA nonpriv registers to register save/restore lists
Ashutosh Dixit <[email protected]>
drm/xe/rtp: Generalize whitelist_apply_to_hwe
Ashutosh Dixit <[email protected]>
drm/xe/rtp: Keep track of non-OA nonpriv slots
Ashutosh Dixit <[email protected]>
drm/xe/rtp: Maintain OA whitelists separately
Ashutosh Dixit <[email protected]>
drm/xe/rtp: Add RING_FORCE_TO_NONPRIV_DENY to OA whitelists
Lucas De Marchi <[email protected]>
drm/xe: Apply whitelist to engine save-restore
Michal Wajdeczko <[email protected]>
drm/xe: Introduce xe_gt_dbg_printer()
Ashutosh Dixit <[email protected]>
drm/xe/rtp: Refactor OAG MMIO trigger register whitelisting
Pauli Virtanen <[email protected]>
Bluetooth: ISO: fix CONNECTED -> CLOSED transition on shutdown/release
Wandun Chen <[email protected]>
of: reserved_mem: avoid post-init UAF when alloc_reserved_mem_array() fails
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: avoid destroy_workqueue(NULL) on vkms init failure
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
William Palacek <[email protected]>
drm/amdkfd: fix uint32_t overflow in EOP ring buffer size alignment
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
Jiri Slaby (SUSE) <[email protected]>
drm/amd/display: use proper context for logging
Ray Wu <[email protected]>
drm/amd/display: Increase HDMI AV mute wait from 2 to 3 frames
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
Osama Abdelkader <[email protected]>
drm/panthor: validate firmware interface structure sizes
Osama Abdelkader <[email protected]>
drm/panthor: reject firmware sections with oversized data
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
Jonas Gorski <[email protected]>
i2c: iproc: reset bus after timeout if START_BUSY is stuck
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
Niklas Schnelle <[email protected]>
s390/pci: Fix s390_pci_mmio_write syscall error return without MIO
Jianing Li <[email protected]>
power: supply: max17040: handle missing status supplier
Xu Rao <[email protected]>
power: supply: bq25890: fix the -10 C NTC lookup entry
Zhongqiu Han <[email protected]>
cpufreq: schedutil: Publish util hooks only after all sg_cpu are initialized
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()
Matt Fleming <[email protected]>
veth: convert frag_list skbs before running XDP
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
Breno Leitao <[email protected]>
mm: memcg: initialize *locked in memcg1_oom_prepare() stub
Link Lin <[email protected]>
mm/page_reporting: use system_freezable_wq to fix UAF during suspend
Christian Brauner <[email protected]>
binfmt_misc: don't let an 'F' entry pin its own instance
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 stack info leak in RME Digiface status
Baul Lee <[email protected]>
ALSA: usb-audio: fix use-after-free in ump_to_endpoint()
Niklas Cassel <[email protected]>
ata: libata-sata: fix ata_scsi_lpm_supported() iteration
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: timer: Clear SNDRV_TIMER_IFLG_DEAD once the close completes
Norbert Szetei <[email protected]>
ALSA: seq: Fix division by zero in initialize_timer()
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
Chengfeng Ye <[email protected]>
Bluetooth: hci_sync: Fix advertising data UAFs
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()
Greg Kroah-Hartman <[email protected]>
Bluetooth: btusb: Fix short read errors in btusb_qca_send_vendor_req()
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()
Kiryl Shutsemau (Meta) <[email protected]>
fs/proc/task_mmu: fix PAGEMAP_SCAN written state for PMD holes
Kefeng Wang <[email protected]>
mm: migrate_device: fix pte_pfn/pte_dirty called on non-present PTE
Nathan Chancellor <[email protected]>
fortify: Disable -Wstringop-overread in tests
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
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
Gabriele Monaco <[email protected]>
sched/deadline: Use revised wakeup rule only for running dl_server
Suman Ghosh <[email protected]>
octeontx2-pf: Set correct sequence for carrier off and tx queue stop
Jiawen Wu <[email protected]>
net: libwx: fix FDIR ATR queue mismatch for software VLAN packets
Daniel Golle <[email protected]>
net: dsa: mt7530: error out on failed reads in MT7531 PHY polling
Daniel Golle <[email protected]>
net: dsa: mt7530: check bus->read() errors in the MDIO regmap backend
Karl Mehltretter <[email protected]>
riscv: mm: Fix out-of-bounds page-table walk during memory hot-remove
Muhammad Bilal <[email protected]>
accel/qaic: use sizeof(*trans_hdr) for transaction length check
Masami Hiramatsu (Google) <[email protected]>
tracing/mmiotrace: Add NULL check for mmio_trace_array in logging functions
Zheng Yejian <[email protected]>
tracing: Remove TRACE_EVENT_FL_FILTERED logic
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: avoid deadlocks in iso_sock_timeout
Pauli Virtanen <[email protected]>
Bluetooth: ISO: fix leaking sk after socket release
Pauli Virtanen <[email protected]>
Bluetooth: ISO: validate sockaddr_iso first in iso_sock_rebind_bis()
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
Yuho Choi <[email protected]>
idpf: Fix mailbox IRQ name leak on request failure
Joshua Hay <[email protected]>
idpf: adjust TxQ ring count minimum
Guenter Roeck <[email protected]>
hwmon: (pmbus) Fix return value from pmbus_update_byte_data()
Chenguang Zhao <[email protected]>
net: ethernet: mtk_eth_soc: pass eth to mtk_handle_irq_rx in poll_controller
Frank Wunderlich <[email protected]>
net: ethernet: mtk_eth_soc: add consts for irq index
Frank Wunderlich <[email protected]>
net: ethernet: mtk_eth_soc: support named IRQs
Zhao Li <[email protected]>
wifi: mac80211: validate individual TWT params before driver setup
Eric Dumazet <[email protected]>
net: udp_tunnel: fix memory leak in udp_tunnel_nic_unregister()
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
Yun Lu <[email protected]>
rtase: fix double free of multi-frag skb on DMA map failure
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: (sht3x) Fix unaligned accesses
Guenter Roeck <[email protected]>
hwmon: (ltc4282) Fix reading the minimum alarm voltage
Guenter Roeck <[email protected]>
hwmon: (ina2xx) Fix various overflow issues
Jonas Rebmann <[email protected]>
hwmon: (ina2xx) Shift INA234 shunt and current registers
Ian Ray <[email protected]>
hwmon: (ina2xx) Add support for INA234
Ian Ray <[email protected]>
hwmon: (ina2xx) Make it easier to add more devices
Wenliang Yan <[email protected]>
hwmon: (ina226) Add support for SY24655
Guenter Roeck <[email protected]>
hwmon: (ina2xx) Add support for INA260
Guenter Roeck <[email protected]>
hwmon: (ina2xx) Add support for has_alerts configuration flag
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
Pablo Neira Ayuso <[email protected]>
netfilter: xt_hashlimit: validate hashtable supports XT_HASHLIMIT_RATE_MATCH
Pablo Neira Ayuso <[email protected]>
netfilter: nf_tables: make nft_object rhltable per table
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()
Fabrice Derepas <[email protected]>
KEYS: trusted: dcp: fix key_len validation and calc_blob_len() return type
Sebastian Andrzej Siewior <[email protected]>
Drivers: hv: vmbus: Replace lockdep_hardirq_threaded() with lockdep annotation
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
Qu Wenruo <[email protected]>
btrfs: fix leaking BTRFS_FS_STATE_REMOUNTING flag
Sang-Heon Jeon <[email protected]>
of: reserved_mem: prevent OOB when too many dynamic regions are defined
Oreoluwa Babatunde <[email protected]>
of: reserved_mem: Add code to dynamically allocate reserved_mem array
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
Abdun Nihaal <[email protected]>
gpio: sloppy-logic-analyzer: Fix memory leak in gpio_la_poll_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
Sneh Mankad <[email protected]>
pinctrl: qcom: Unconditionally mark gpio as wakeup enable
Michael Bommarito <[email protected]>
thunderbolt: Prevent XDomain delayed work use-after-free on disconnect
Jakub Kicinski <[email protected]>
netconsole: avoid OOB reads, msg is not nul-terminated
Tristan Madani <[email protected]>
bpf: Reset register bounds before narrowing retval range in check_mem_access()
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
Yehyeong Lee <[email protected]>
net: mpls: initialize rtm_tos in mpls_getroute()
Wayen.Yan <[email protected]>
net: airoha: Fix register index for Tx-fwd counter configuration
Lorenzo Bianconi <[email protected]>
netfilter: br_netfilter: Reallocate headroom if necessary in neigh_hh_bridge()
Tiwei Bie <[email protected]>
um: Preserve errno within signal handler
Shuvam Pandey <[email protected]>
kunit: tool: skip stty when stdin is not a tty
David Gow <[email protected]>
kunit: tool: Terminate kernel under test on SIGINT
Benjamin Berg <[email protected]>
um: Set parent death signal for userspace process
Tiwei Bie <[email protected]>
um: Set parent-death signal for write_sigio thread/process
Tiwei Bie <[email protected]>
um: Set parent-death signal for ubd io thread/process
Tiwei Bie <[email protected]>
um: Use os_set_pdeathsig helper in winch thread/process
Benjamin Berg <[email protected]>
um: Set parent death signal for winch thread/process
Tiwei Bie <[email protected]>
um: Add os_set_pdeathsig helper function
Pablo Neira Ayuso <[email protected]>
netfilter: nf_conntrack_expect: restore helper propagation via expectation
-------------
Diffstat:
Documentation/dev-tools/kmemleak.rst | 1 + Documentation/hwmon/ina2xx.rst | 67 +- 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/riscv/mm/init.c | 4 +- arch/s390/kvm/pci.c | 28 +- arch/s390/pci/pci_mmio.c | 1 + arch/um/drivers/chan_user.c | 2 + arch/um/drivers/ubd_kern.c | 1 + arch/um/drivers/vector_kern.c | 3 + arch/um/include/shared/os.h | 2 + arch/um/os-Linux/process.c | 6 + arch/um/os-Linux/sigio.c | 1 + arch/um/os-Linux/signal.c | 3 + arch/um/os-Linux/skas/process.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/libata-sata.c | 2 +- drivers/ata/sata_mv.c | 2 +- drivers/block/ublk_drv.c | 9 + drivers/bluetooth/btintel.c | 3 + drivers/bluetooth/btmtk.c | 50 +- drivers/bluetooth/btusb.c | 30 +- drivers/cpufreq/powernow-k8.c | 1 + drivers/dma/idxd/cdev.c | 4 +- drivers/dma/sun6i-dma.c | 11 +- drivers/gpio/gpio-pca953x.c | 15 +- drivers/gpio/gpio-pch.c | 28 +- drivers/gpio/gpio-sloppy-logic-analyzer.c | 10 + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c | 12 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 73 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 15 + drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c | 11 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 30 +- drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 11 +- drivers/gpu/drm/amd/amdgpu/amdgpu_job.h | 22 +- drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_object.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 40 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c | 5 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 8 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 6 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 2 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm_cpu.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c | 4 +- drivers/gpu/drm/amd/amdgpu/amdgpu_vm_sdma.c | 12 +- drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c | 6 +- drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c | 6 +- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 10 +- drivers/gpu/drm/amd/amdkfd/kfd_events.c | 23 +- drivers/gpu/drm/amd/amdkfd/kfd_migrate.c | 3 +- .../gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_queue.c | 2 +- .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 20 +- .../drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c | 16 +- drivers/gpu/drm/armada/armada_fbdev.c | 12 +- drivers/gpu/drm/display/drm_dp_helper.c | 12 + drivers/gpu/drm/drm_exec.c | 6 +- drivers/gpu/drm/drm_fb_helper.c | 41 +- drivers/gpu/drm/drm_fbdev_dma.c | 12 +- drivers/gpu/drm/drm_fbdev_shmem.c | 12 +- drivers/gpu/drm/drm_fbdev_ttm.c | 12 +- drivers/gpu/drm/drm_gpuvm.c | 3 +- drivers/gpu/drm/etnaviv/etnaviv_gem_submit.c | 2 +- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 9 +- drivers/gpu/drm/gma500/fbdev.c | 13 +- drivers/gpu/drm/i915/display/intel_fbdev.c | 9 +- drivers/gpu/drm/i915/display/intel_hdcp.c | 699 +++++++++++---------- drivers/gpu/drm/i915/display/intel_hdcp_gsc.c | 9 +- drivers/gpu/drm/i915/display/intel_hdcp_gsc.h | 5 +- .../gpu/drm/i915/display/intel_hdcp_gsc_message.h | 3 +- drivers/gpu/drm/i915/display/intel_vrr.c | 10 +- drivers/gpu/drm/imagination/pvr_job.c | 2 +- drivers/gpu/drm/imagination/pvr_queue.c | 5 +- drivers/gpu/drm/imagination/pvr_queue.h | 2 +- drivers/gpu/drm/lima/lima_gem.c | 2 +- drivers/gpu/drm/lima/lima_sched.c | 6 +- drivers/gpu/drm/lima/lima_sched.h | 3 +- drivers/gpu/drm/mediatek/mtk_crtc.c | 6 +- drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c | 7 +- drivers/gpu/drm/msm/msm_fbdev.c | 9 +- drivers/gpu/drm/msm/msm_gem_submit.c | 8 +- drivers/gpu/drm/nouveau/nouveau_sched.c | 3 +- drivers/gpu/drm/omapdrm/omap_fbdev.c | 9 +- drivers/gpu/drm/panfrost/panfrost_drv.c | 2 +- drivers/gpu/drm/panthor/panthor_drv.c | 3 +- drivers/gpu/drm/panthor/panthor_fw.c | 47 +- drivers/gpu/drm/panthor/panthor_mmu.c | 2 +- drivers/gpu/drm/panthor/panthor_sched.c | 5 +- drivers/gpu/drm/panthor/panthor_sched.h | 3 +- drivers/gpu/drm/radeon/radeon_fbdev.c | 13 +- drivers/gpu/drm/scheduler/sched_fence.c | 4 +- drivers/gpu/drm/scheduler/sched_main.c | 7 +- drivers/gpu/drm/tegra/fbdev.c | 18 +- drivers/gpu/drm/v3d/v3d_submit.c | 2 +- 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/gpu/drm/vmwgfx/vmwgfx_vkms.c | 17 +- drivers/gpu/drm/xe/Makefile | 1 + drivers/gpu/drm/xe/display/xe_hdcp_gsc.c | 7 +- drivers/gpu/drm/xe/xe_bo.c | 33 +- drivers/gpu/drm/xe/xe_bo.h | 10 +- drivers/gpu/drm/xe/xe_bo_types.h | 2 + drivers/gpu/drm/xe/xe_dma_buf.c | 6 +- drivers/gpu/drm/xe/xe_exec.c | 22 +- drivers/gpu/drm/xe/xe_gt.c | 4 +- drivers/gpu/drm/xe/xe_gt_debugfs.c | 4 +- drivers/gpu/drm/xe/xe_gt_printk.h | 31 + drivers/gpu/drm/xe/xe_hw_engine.c | 3 +- drivers/gpu/drm/xe/xe_hw_engine_types.h | 8 + drivers/gpu/drm/xe/xe_oa.c | 7 + drivers/gpu/drm/xe/xe_oa_types.h | 3 + drivers/gpu/drm/xe/xe_pagefault.c | 65 ++ drivers/gpu/drm/xe/xe_pagefault.h | 19 + drivers/gpu/drm/xe/xe_pagefault_types.h | 136 ++++ drivers/gpu/drm/xe/xe_pt.c | 3 + drivers/gpu/drm/xe/xe_reg_sr.c | 53 -- drivers/gpu/drm/xe/xe_reg_whitelist.c | 147 ++++- drivers/gpu/drm/xe/xe_reg_whitelist.h | 4 + drivers/gpu/drm/xe/xe_sched_job.c | 3 +- drivers/gpu/drm/xe/xe_vm.c | 3 +- drivers/hid/hid-logitech-dj.c | 28 +- drivers/hv/vmbus_drv.c | 13 +- drivers/hwmon/Kconfig | 5 +- drivers/hwmon/adt7470.c | 131 ++-- drivers/hwmon/ina2xx.c | 251 ++++++-- drivers/hwmon/lm90.c | 4 +- drivers/hwmon/ltc4282.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/hwmon/sht3x.c | 9 +- drivers/i2c/busses/i2c-amd-mp2-plat.c | 4 +- drivers/i2c/busses/i2c-bcm-iproc.c | 11 + drivers/i2c/busses/i2c-imx.c | 9 +- drivers/i2c/busses/i2c-jz4780.c | 5 +- drivers/iommu/iova.c | 6 + drivers/media/i2c/imx219.c | 31 +- .../media/platform/chips-media/wave5/wave5-hw.c | 3 + .../platform/chips-media/wave5/wave5-vpu-enc.c | 5 +- .../platform/chips-media/wave5/wave5-vpuapi.h | 1 + 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-mdio.c | 11 +- drivers/net/dsa/mt7530.c | 58 +- drivers/net/ethernet/airoha/airoha_eth.c | 2 +- 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/idpf/idpf_lib.c | 2 +- drivers/net/ethernet/intel/idpf/idpf_txrx.c | 5 +- drivers/net/ethernet/intel/idpf/idpf_txrx.h | 2 +- drivers/net/ethernet/intel/igbvf/netdev.c | 2 - .../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 2 +- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 58 +- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 7 +- drivers/net/ethernet/nvidia/forcedeth.c | 4 +- drivers/net/ethernet/qlogic/qede/qede_main.c | 44 +- drivers/net/ethernet/realtek/rtase/rtase_main.c | 3 + drivers/net/ethernet/samsung/sxgbe/sxgbe_main.c | 14 +- drivers/net/ethernet/wangxun/libwx/wx_lib.c | 2 + drivers/net/netconsole.c | 3 +- drivers/net/phy/phylink.c | 29 +- drivers/net/veth.c | 4 +- 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/of/of_reserved_mem.c | 87 ++- 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-msm.c | 8 +- drivers/pinctrl/qcom/pinctrl-sc8280xp.c | 21 +- drivers/power/supply/bq25890_charger.c | 2 +- drivers/power/supply/max17040_battery.c | 6 +- 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/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/typec/ucsi/ucsi.c | 88 +-- drivers/usb/typec/ucsi/ucsi.h | 1 + fs/binfmt_misc.c | 8 + fs/btrfs/super.c | 8 +- fs/btrfs/zoned.c | 6 +- fs/erofs/Kconfig | 14 + fs/erofs/decompressor_lzma.c | 3 +- fs/proc/task_mmu.c | 33 +- fs/smb/client/cifssmb.c | 12 +- fs/smb/server/vfs_cache.c | 6 +- include/drm/drm_exec.h | 20 +- include/drm/drm_fb_helper.h | 12 - include/drm/gpu_scheduler.h | 12 +- include/linux/alloc_tag.h | 3 + include/linux/can/core.h | 1 + include/linux/can/skb.h | 2 - include/linux/dma/qcom_bam_dma.h | 21 +- include/linux/kmemleak.h | 4 + include/linux/libata.h | 2 +- include/linux/mmc/sdio_ids.h | 2 +- include/linux/netfilter/nf_conntrack_sip.h | 2 +- include/linux/slab.h | 8 +- include/linux/thunderbolt.h | 3 + include/linux/trace_events.h | 4 - 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 | 4 +- include/scsi/libsas.h | 1 - include/trace/events/rxrpc.h | 14 +- include/uapi/linux/rkisp1-config.h | 6 +- kernel/audit.c | 11 +- kernel/auditfilter.c | 6 +- kernel/bpf/verifier.c | 1 + kernel/sched/cpufreq_schedutil.c | 11 + kernel/sched/deadline.c | 3 +- kernel/trace/trace.c | 44 +- kernel/trace/trace.h | 4 - kernel/trace/trace_branch.c | 4 +- kernel/trace/trace_events.c | 6 +- kernel/trace/trace_events_filter.c | 3 + kernel/trace/trace_functions_graph.c | 8 +- kernel/trace/trace_hwlat.c | 4 +- kernel/trace/trace_mmiotrace.c | 21 +- kernel/trace/trace_osnoise.c | 12 +- kernel/trace/trace_probe.c | 6 +- kernel/trace/trace_sched_wakeup.c | 8 +- lib/alloc_tag.c | 9 + lib/assoc_array.c | 3 +- lib/rhashtable.c | 1 + lib/test_fortify/Makefile | 1 + lib/win_minmax.c | 1 + mm/huge_memory.c | 16 +- mm/hugetlb.c | 12 +- mm/kmemleak.c | 44 +- mm/memcontrol-v1.h | 6 +- mm/migrate_device.c | 5 +- mm/mm_init.c | 15 +- mm/page_reporting.c | 6 +- mm/percpu-km.c | 2 +- mm/slab.h | 28 +- mm/slab_common.c | 13 + mm/slub.c | 34 +- net/bluetooth/hci_conn.c | 14 +- net/bluetooth/hci_sync.c | 154 +++-- net/bluetooth/hidp/core.c | 30 +- net/bluetooth/iso.c | 113 ++-- 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 | 6 +- 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/skbuff.c | 18 +- net/ipv4/route.c | 2 - net/ipv4/udp_tunnel_nic.c | 32 +- net/ipv6/fib6_rules.c | 1 + net/ipv6/ip6_output.c | 2 +- net/ipv6/ndisc.c | 2 + net/mac80211/s1g.c | 4 + net/mpls/af_mpls.c | 1 + 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_nat_sip.c | 2 +- net/netfilter/nf_tables_api.c | 34 +- net/netfilter/nft_payload.c | 12 +- 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 | 38 +- net/rxrpc/call_accept.c | 1 + net/rxrpc/call_event.c | 19 +- net/rxrpc/call_object.c | 2 + net/rxrpc/input.c | 12 +- net/rxrpc/output.c | 14 +- net/rxrpc/peer_object.c | 20 +- net/rxrpc/proc.c | 6 +- net/rxrpc/rtt.c | 103 +-- net/rxrpc/sendmsg.c | 2 +- net/sctp/associola.c | 3 + net/sctp/sm_make_chunk.c | 17 +- net/smc/smc_core.c | 2 +- net/tipc/socket.c | 2 +- security/keys/keyring.c | 14 +- security/keys/trusted-keys/trusted_dcp.c | 15 +- sound/core/pcm_native.c | 7 + sound/core/seq/seq_timer.c | 9 +- sound/core/timer.c | 2 + 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 +- sound/usb/mixer_quirks.c | 2 +- tools/testing/kunit/kunit_kernel.py | 39 +- tools/testing/kunit/kunit_tool_test.py | 42 ++ tools/testing/selftests/clone3/clone3_set_tid.c | 2 +- tools/testing/selftests/mm/mlock-random-test.c | 2 +- 387 files changed, 4750 insertions(+), 2372 deletions(-)
From [email protected] Fri Aug 7 16:34:18 2026
Message-ID: <[email protected]>
User-Agent: quilt/0.69
Date: Fri, 07 Aug 2026 16:34:19 +0200
From: Greg Kroah-Hartman <[email protected]>
To: [email protected]
Cc: [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected],
Ilya Maximets <[email protected]>,
Pablo Neira Ayuso <[email protected]>,
Sasha Levin <[email protected]>
X-stable: review
X-Patchwork-Hint: ignore
Subject: [PATCH 6.12 001/337] netfilter: nf_conntrack_expect: restore helper propagation via
expectation
MIME-Version: 1.0
6.12-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
@@ -1773,14 +1773,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
@@ -419,6 +419,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
@@ -2630,6 +2630,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);
@@ -2856,6 +2857,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;
@@ -2871,8 +2873,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);
@@ -3511,6 +3523,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) {
@@ -3564,6 +3577,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;
@@ -3619,7 +3633,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/337 um: Add os_set_pdeathsig helper function
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tiwei Bie <[email protected]>
commit 4e5adbe447db382cc76e05613581f96aef4f91d2 upstream.
This helper can be used to set the parent-death signal of the calling process to SIGKILL to ensure that the process will be killed if the UML kernel dies unexpectedly without proper cleanup. This helper will be used in the follow-up patches.
--- arch/um/include/shared/os.h | 2 ++ arch/um/os-Linux/process.c | 6 ++++++ 2 files changed, 8 insertions(+)
arch/um/include/shared/os.h +2 -0
@@ -219,6 +219,8 @@ extern int os_unmap_memory(void *addr, int len);extern int os_drop_memory (void *addr,int length);extern int can_drop_memory (void ); +void os_set_pdeathsig (void ); +/* execvp.c */ extern int execvp_noalloc (char *buf,const char *file,char *const argv[]);/* helper.c */
arch/um/os-Linux/process.c +6 -0
@@ -12,6 +12,7 @@#include <fcntl.h> #include <sys/mman.h> #include <sys/ptrace.h> +#include <sys/prctl.h> #include <sys/wait.h> #include <asm/unistd.h> #include <init.h>
@@ -234,3 +235,8 @@ void init_new_thread_signals(void)set_handler (SIGIO );signal (SIGWINCH ,SIG_IGN ); } + +void os_set_pdeathsig (void ) +{ +prctl (PR_SET_PDEATHSIG ,SIGKILL ); +}
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 3/337 um: Set parent death signal for winch thread/process
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Berg <[email protected]>
commit fdb2ecd35d327a1fc6bba69b97f85b494e1f4b6b upstream.
The winch "thread" is really a separate process. Using prctl to set PR_SET_PDEATHSIG ensures that this separate thread will be killed if the UML kernel itself dies unexpectedly and does not perform proper cleanup.
--- arch/um/drivers/chan_user.c | 3 +++ 1 file changed, 3 insertions(+)
arch/um/drivers/chan_user.c +3 -0
@@ -10,6 +10,7 @@#include <signal.h> #include <termios.h> #include <sys/ioctl.h> +#include <sys/prctl.h> #include "chan_user.h" #include <os.h> #include <um_malloc.h>
@@ -161,6 +162,8 @@ static __noreturn int winch_thread(void *arg)int count;char c =1 ; +prctl (PR_SET_PDEATHSIG ,SIGKILL ); + pty_fd = data->pty_fd; pipe_fd = data->pipe_fd; count =write (pipe_fd, &c,sizeof (c));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 4/337 um: Use os_set_pdeathsig helper in winch thread/process
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tiwei Bie <[email protected]>
commit 42b8b00c8ab1ac18fccde3f29ee589626a561ea7 upstream.
Since we have a helper now, let's switch to using it. It will make the code slightly more consistent.
--- arch/um/drivers/chan_user.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
arch/um/drivers/chan_user.c +1 -2
@@ -10,7 +10,6 @@#include <signal.h> #include <termios.h> #include <sys/ioctl.h> -#include <sys/prctl.h> #include "chan_user.h" #include <os.h> #include <um_malloc.h>
@@ -162,7 +161,7 @@ static __noreturn int winch_thread(void *arg)int count;char c =1 ; -prctl (PR_SET_PDEATHSIG ,SIGKILL ); +os_set_pdeathsig (); pty_fd = data->pty_fd; pipe_fd = data->pipe_fd;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 5/337 um: Set parent-death signal for ubd io thread/process
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tiwei Bie <[email protected]>
commit 9b5e6c0f5a9199c69af81ac5bedc512ee7dc20b3 upstream.
The ubd io thread is not really a traditional thread. Set the parent-death signal for it to ensure that it will be killed if the UML kernel dies unexpectedly without proper cleanup.
--- arch/um/drivers/ubd_kern.c | 1 + 1 file changed, 1 insertion(+)
arch/um/drivers/ubd_kern.c +1 -0
@@ -1501,6 +1501,7 @@ int io_thread(void *arg) {int n, count, written, res; +os_set_pdeathsig ();os_fix_helper_signals ();while (1 ){
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 6/337 um: Set parent-death signal for write_sigio thread/process
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tiwei Bie <[email protected]>
commit c6c4adee65969218b0b7b13f568fd2c6f2333373 upstream.
The write_sigio thread is not really a traditional thread. Set the parent-death signal for it to ensure that it will be killed if the UML kernel dies unexpectedly without proper cleanup.
--- arch/um/os-Linux/sigio.c | 1 + 1 file changed, 1 insertion(+)
arch/um/os-Linux/sigio.c +1 -0
@@ -55,6 +55,7 @@ static int write_sigio_thread(void *unused)int i, n, respond_fd;char c; +os_set_pdeathsig ();os_fix_helper_signals (); fds = ¤t_poll;while (1 ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 7/337 um: Set parent death signal for userspace process
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Berg <[email protected]>
commit 801e00d3a1b78b7f71675fae79946ff4aa3ee070 upstream.
Enable PR_SET_PDEATHSIG so that the UML userspace process will be killed when the kernel exits unexpectedly.
[florian: upstream applies os_set_pdeathsig() in stub_exe.c, a file introduced in v6.13 that does not exist in 6.12; applied instead to userspace_tramp() in arch/um/os-Linux/skas/process.c, which is the equivalent entry-point for the userspace process in 6.12]
--- arch/um/os-Linux/skas/process.c | 3 +++ 1 file changed, 3 insertions(+)
arch/um/os-Linux/skas/process.c +3 -0
@@ -214,6 +214,9 @@ static int userspace_tramp(void *stack) (unsigned long ) stub_segv_handler - (unsigned long ) __syscall_stub_start; +/* Make sure this process dies if the kernel dies */ +os_set_pdeathsig (); +ptrace (PTRACE_TRACEME ,0 ,0 ,0 );signal (SIGTERM ,SIG_DFL );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 8/337 kunit: tool: Terminate kernel under test on SIGINT
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Gow <[email protected]>
commit 8f260b02eeeffbf2263c2b82b6e3e32fd73cde2b upstream.
kunit.py will attempt to catch SIGINT / ^C in order to ensure the TTY isn't messed up, but never actually attempts to terminate the running kernel (be it UML or QEMU). This can lead to a bit of frustration if the kernel has crashed or hung.
Terminate the kernel process in the signal handler, if it's running. This requires plumbing through the process handle in a few more places (and having some checks to see if the kernel is still running in places where it may have already been killed).
[florian: resolved conflict in signal_handler(): upstream references _restore_terminal_if_tty() which is introduced by the following commit; retained subprocess.call(['stty', 'sane']) until that helper is available]
--- tools/testing/kunit/kunit_kernel.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-)
tools/testing/kunit/kunit_kernel.py +19 -9
@@ -15,7 +15,7 @@ import shlex import shutil import signal import threading -from typing import Iterator, List, Optional, Tuple +from typing import Iterator, List, Optional, Tuple, Any from types import FrameType import kunit_config
@@ -252,6 +252,7 @@ class LinuxSourceTree: if kconfig_add: kconfig = kunit_config.parse_from_string('\n'.join(kconfig_add)) self._kconfig.merge_in_entries(kconfig) + self._process : Optional[subprocess.Popen[Any]] = None def arch(self) -> str: return self._arch
@@ -345,36 +346,45 @@ class LinuxSourceTree: args.append('kunit.filter_action=' + filter_action) args.append('kunit.enable=1') - process = self._ops.start(args, build_dir) - assert process.stdout is not None # tell mypy it's set + self._process = self._ops.start(args, build_dir) + assert self._process is not None # tell mypy it's set + assert self._process.stdout is not None # tell mypy it's set # Enforce the timeout in a background thread. def _wait_proc() -> None: try: - process.wait(timeout=timeout) + if self._process: + self._process.wait(timeout=timeout) except Exception as e: print(e) - process.terminate() - process.wait() + if self._process: + self._process.terminate() + self._process.wait() waiter = threading.Thread(target=_wait_proc) waiter.start() output = open(get_outfile_path(build_dir), 'w') try: # Tee the output to the file and to our caller in real time. - for line in process.stdout: + for line in self._process.stdout: output.write(line) yield line # This runs even if our caller doesn't consume every line. finally: # Flush any leftover output to the file - output.write(process.stdout.read()) + if self._process: + if self._process.stdout: + output.write(self._process.stdout.read()) + self._process.stdout.close() + self._process = None output.close() - process.stdout.close() waiter.join() subprocess.call(['stty', 'sane']) def signal_handler(self, unused_sig: int, unused_frame: Optional[FrameType]) -> None: logging.error('Build interruption occurred. Cleaning console.') + if self._process: + self._process.terminate() + self._process.wait() subprocess.call(['stty', 'sane'])
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 9/337 kunit: tool: skip stty when stdin is not a tty
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuvam Pandey <[email protected]>
commit e42c349f4cdfa43cb39a68c8f764f8cafc23a9a9 upstream.
run_kernel() cleanup and signal_handler() invoke stty unconditionally. When stdin is not a tty (for example in CI or unit tests), this writes noise to stderr.
Call stty only when stdin is a tty.
Add regression tests for these paths:
- run_kernel() with non-tty stdin
- signal_handler() with non-tty stdin
- signal_handler() with tty stdin
[florian: add missing 'import sys' required by sys.stdin.isatty(); the module was already present in the mainline tree before this commit but was absent from the 6.12 base of kunit_kernel.py]
--- tools/testing/kunit/kunit_kernel.py | 11 +++++-- tools/testing/kunit/kunit_tool_test.py | 42 ++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 2 deletions(-)
tools/testing/kunit/kunit_kernel.py +9 -2
@@ -14,6 +14,7 @@ import os import shlex import shutil import signal +import sys import threading from typing import Iterator, List, Optional, Tuple, Any from types import FrameType
@@ -333,6 +334,12 @@ class LinuxSourceTree: return False return self.validate_config(build_dir) + def _restore_terminal_if_tty(self) -> None: + # stty requires a controlling terminal; skip headless runs. + if sys.stdin is None or not sys.stdin.isatty(): + return + subprocess.call(['stty', 'sane']) + def run_kernel(self, args: Optional[List[str]]=None, build_dir: str='', filter_glob: str='', filter: str='', filter_action: Optional[str]=None, timeout: Optional[int]=None) -> Iterator[str]: # Copy to avoid mutating the caller-supplied list. exec_tests() reuses # the same args across repeated run_kernel() calls (e.g. --run_isolated),
@@ -380,11 +387,11 @@ class LinuxSourceTree: output.close() waiter.join() - subprocess.call(['stty', 'sane']) + self._restore_terminal_if_tty() def signal_handler(self, unused_sig: int, unused_frame: Optional[FrameType]) -> None: logging.error('Build interruption occurred. Cleaning console.') if self._process: self._process.terminate() self._process.wait() - subprocess.call(['stty', 'sane']) + self._restore_terminal_if_tty()
tools/testing/kunit/kunit_tool_test.py +42 -0
48 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 10/337 um: Preserve errno within signal handler
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tiwei Bie <[email protected]>
commit f68b2d5a907b53eed99cf2efcaaae116df73c298 upstream.
We rely on errno to determine whether a syscall has failed, so we need to ensure that accessing errno is async-signal-safe. Currently, we preserve the errno in sig_handler_common(), but it doesn't cover every possible case. Let's do it in hard_handler() instead, which is the signal handler we actually register.
[florian: hard_handler() in 6.12 retains the to_irq_stack/from_irq_stack loop from before the upstream SMP refactoring; errno save/restore is wrapped around that loop rather than replacing sig_handler_common's existing save/restore]
--- arch/um/os-Linux/signal.c | 3 +++ 1 file changed, 3 insertions(+)
arch/um/os-Linux/signal.c +3 -0
@@ -190,6 +190,7 @@ static void hard_handler(int sig, siginfo_t *si, void *p) {ucontext_t *uc = p;mcontext_t *mc = &uc->uc_mcontext; +int save_errno = errno;unsigned long pending =1UL << sig; do {
@@ -227,6 +228,8 @@ static void hard_handler(int sig, siginfo_t *si, void *p)if (!nested) pending =from_irq_stack (nested); }while (pending); + + errno = save_errno; }void set_handler (int sig)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 11/337 netfilter: br_netfilter: Reallocate headroom if necessary in neigh_hh_bridge()
In reply to Greg Kroah-Hartman6.12-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
@@ -296,7 +296,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 12/337 net: airoha: Fix register index for Tx-fwd counter configuration
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wayen.Yan <[email protected]>
[ Upstream commit 1402ecccf5630a0b7fa4749d7d2e72abc3f3d73d ]
In airoha_qdma_init_qos_stats(), the Tx-fwd counter configuration register uses the same index (i << 1) as the Tx-cpu counter, which overwrites the Tx-cpu configuration. The Tx-fwd counter value register correctly uses (i << 1) + 1, so the configuration register should use the same index.
Fix the REG_CNTR_CFG index from (i << 1) to ((i << 1) + 1) so that the Tx-fwd counter is properly configured instead of clobbering the Tx-cpu counter config.
--- drivers/net/ethernet/airoha/airoha_eth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/airoha/airoha_eth.c +1 -1
@@ -2022,7 +2022,7 @@ static void airoha_qdma_init_qos_stats(struct airoha_qdma *qdma) FIELD_PREP(CNTR_CHAN_MASK, i));/* Tx-fwd transferred count */ airoha_qdma_wr (qdma,REG_CNTR_VAL ((i <<1 ) +1 ),0 ); - airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1), + airoha_qdma_wr(qdma, REG_CNTR_CFG((i << 1) + 1), CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK | CNTR_ALL_DSCP_RING_EN_MASK | FIELD_PREP(CNTR_SRC_MASK, 1) |
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 13/337 net: mpls: initialize rtm_tos in mpls_getroute()
In reply to Greg Kroah-Hartman6.12-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
@@ -2468,6 +2468,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 14/337 HID: logitech-dj: Standardise hid_report_enum variable nomenclature
In reply to Greg Kroah-Hartman6.12-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 15/337 HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated OOB write
In reply to Greg Kroah-Hartman6.12-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 16/337 HID: logitech-dj: fix wrong detection of bad DJ_SHORT output report
In reply to Greg Kroah-Hartman6.12-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 17/337 bpf: Reset register bounds before narrowing retval range in check_mem_access()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
[ Upstream commit 5e0b273e0a62cc04ec338c7b502797c66c2ed42a ]
When the BPF verifier processes a context load of an LSM hook return value, it calls __mark_reg_s32_range() to narrow the register to the hook's valid range. However, __mark_reg_s32_range() intersects the new range with the register's existing bounds using max_t()/min_t() rather than replacing them.
If the destination register carries stale bounds from a prior instruction (e.g. BPF_MOV64_IMM), the intersection can produce a range narrower than reality. The verifier then believes it knows the register's exact value, while at runtime the actual hook return value is loaded, creating a verifier/runtime mismatch that can be used to bypass BPF memory safety checks.
The else branch already calls mark_reg_unknown() to reset register state before any narrowing. Apply the same reset in the is_retval path so stale bounds are cleared before __mark_reg_s32_range() intersects.
--- kernel/bpf/verifier.c | 1 + 1 file changed, 1 insertion(+)
kernel/bpf/verifier.c +1 -0
@@ -7234,6 +7234,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn*/ if (reg_type ==SCALAR_VALUE ) {if (is_retval &&get_func_retval_range (env->prog, &range)) { +mark_reg_unknown (env, regs, value_regno); err =__mark_reg_s32_range (env, regs, value_regno, range.minval, range.maxval);if (err)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 18/337 netconsole: avoid OOB reads, msg is not nul-terminated
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Kicinski <[email protected]>
[ Upstream commit 82aec772fca2223bc5774bd9af486fd95766e578 ]
msg passed to netconsole from the console subsystem is not guaranteed to be nul-terminated. Before recent
commit 7eab73b18630 ("netconsole: convert to NBCON console infrastructure") the message would be placed in printk_shared_pbufs, a static global buffer, so KASAN had harder time catching OOB accesses. Now we see:
printk: console [netcon_ext0] enabled
BUG: KASAN: slab-out-of-bounds in string+0x1f7/0x240
Read of size 1 at addr ffff88813b6d4c00 by task pr/netcon_ext0/594
CPU: 65 UID: 0 PID: 594 Comm: pr/netcon_ext0 Not tainted 6.19.0-11754-g4246fd6547c9
Call Trace:
kasan_report+0xe4/0x120
string+0x1f7/0x240
vsnprintf+0x655/0xba0
scnprintf+0xba/0x120
netconsole_write+0x3fe/0xa10
nbcon_emit_next_record+0x46e/0x860
nbcon_kthread_func+0x623/0x750
Allocated by task 1:
nbcon_alloc+0x1ea/0x450
register_console+0x26b/0xe10
init_netconsole+0xbb0/0xda0
The buggy address belongs to the object at ffff88813b6d4000
which belongs to the cache kmalloc-4k of size 4096
The buggy address is located 0 bytes to the right of
allocated 3072-byte region [ffff88813b6d4000, ffff88813b6d4c00)[ mb: adjusted context; in 6.12 the affected code lives in
send_ext_msg_udp() and writes to a static buffer instead of nt->buf ]
--- drivers/net/netconsole.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/netconsole.c +2 -1
@@ -1103,7 +1103,8 @@ static void send_ext_msg_udp(struct netconsole_target *nt, const char *msg,if (msg_len + release_len + userdata_len <=MAX_PRINT_CHUNK ) {/* No fragmentation needed */ if (nt->release) { -scnprintf (buf,MAX_PRINT_CHUNK ,"%s,%s" , release, msg); +scnprintf (buf,MAX_PRINT_CHUNK ,"%s,%.*s" , release, + msg_len, msg); msg_len += release_len; }else {memcpy (buf, msg, msg_len);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 19/337 thunderbolt: Prevent XDomain delayed work use-after-free on disconnect
In reply to Greg Kroah-Hartman6.12-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 );
@@ -2068,6 +2080,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);
@@ -2464,8 +2480,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
@@ -202,6 +202,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
@@ -250,6 +252,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 20/337 pinctrl: qcom: Unconditionally mark gpio as wakeup enable
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sneh Mankad <[email protected]>
[ Upstream commit 859e02a369ab328a77dfcabf59562100e55f9c5c ]
GPIO interrupts that are wakeup capable need to be forwarded to wakeup capable parent irqchip. This is done via writing to it's wakeup_enable bit.
Currently the bit is set only for PDC irqchip by checking skip_wake_irqs. skip_wake_irqs is set to differentiate between parent irqchips MPM and PDC. It is set when the parent irqchip is PDC to inform pinctrl about skipping the IRQ setting up at TLMM.
However, the functionality to forward GPIO interrupts during SoC low power mode is needed regardless of which parent irqchip it is. Without the functionality it is impossible for MPM irqchip to detect the GPIO interrupt during SoC low power mode since for MPM irqchip the skip_wake_irqs is always false.
Remove skip_wake_irqs condition when setting wakeup enable bit to allow forwarding GPIO interrupts for SoCs using MPM irqchip too.
--- drivers/pinctrl/qcom/pinctrl-msm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/pinctrl/qcom/pinctrl-msm.c +4 -4
@@ -1247,12 +1247,12 @@ static int msm_gpio_irq_reqres(struct irq_data *d)/* * If the wakeup_enable bit is present and marked as available for the * requested GPIO, it should be enabled when the GPIO is marked as -* wake irq in order to allow the interrupt event to be transfered to -* the PDC HW. +* wake irq in order to allow the interrupt event to be transferred to +* the PDC/MPM HW. * While the name implies only the wakeup event, it's also required for * the interrupt event. */ -if (test_bit (d->hwirq, pctrl->skip_wake_irqs) && g->intr_wakeup_present_bit) { +if (g->intr_wakeup_present_bit) {u32 intr_cfg;raw_spin_lock_irqsave (&pctrl->lock, flags);
@@ -1280,7 +1280,7 @@ static void msm_gpio_irq_relres(struct irq_data *d)unsigned long flags;/* Disable the wakeup_enable bit if it has been set in msm_gpio_irq_reqres() */ -if (test_bit (d->hwirq, pctrl->skip_wake_irqs) && g->intr_wakeup_present_bit) { +if (g->intr_wakeup_present_bit) {u32 intr_cfg;raw_spin_lock_irqsave (&pctrl->lock, flags);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 21/337 pinctrl: qcom: sc8280xp: Add missing wakeup entries for GPIO143/151
In reply to Greg Kroah-Hartman6.12-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 22/337 dmaengine: sun6i-dma: Fix reclaim descriptors while terminating DMA
In reply to Greg Kroah-Hartman6.12-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 23/337 dmaengine: idxd: fix fdev setup failure cleanup in idxd_cdev_open()
In reply to Greg Kroah-Hartman6.12-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 24/337 gpio: sloppy-logic-analyzer: Fix memory leak in gpio_la_poll_probe()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
[ Upstream commit 7a7baebd9f23ba4f24796775472b2fd00dcd95d9 ]
The memory allocated for priv->blob.data is not freed in the error paths that follow the fops_buf_size_set() call in gpio_la_poll_probe(), as well as in the remove function. Fix that by using device managed action to free the memory on remove.
--- drivers/gpio/gpio-sloppy-logic-analyzer.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
drivers/gpio/gpio-sloppy-logic-analyzer.c +10 -0
@@ -161,6 +161,13 @@ static int fops_buf_size_get(void *data, u64 *val)return 0 ; } +static void fops_buf_release (void *data) +{ +struct gpio_la_poll_priv *priv = data; + +vfree (priv->blob.data); +} +static int fops_buf_size_set (void *data,u64 val) {struct gpio_la_poll_priv *priv = data;
@@ -239,6 +246,9 @@ static int gpio_la_poll_probe(struct platform_device *pdev)return ret;fops_buf_size_set (priv,GPIO_LA_DEFAULT_BUF_SIZE ); + ret =devm_add_action_or_reset (dev, fops_buf_release, priv); +if (ret) +return ret; priv->descs =devm_gpiod_get_array (dev,"probe" ,GPIOD_IN );if (IS_ERR (priv->descs))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 25/337 ata: sata_mv: accept 1 or 2 resources in platform probe
In reply to Greg Kroah-Hartman6.12-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 26/337 ata: libahci_platform: support non-consecutive port numbers
In reply to Greg Kroah-Hartman6.12-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]); }
@@ -432,6 +441,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
@@ -458,6 +481,7 @@ struct ahci_host_priv *ahci_platform_get_resources(struct platform_device *pdev,struct device *dev = &pdev->dev;struct ahci_host_priv *hpriv;u32 mask_port_map =0 ; +u32 max_port;if (!devres_open_group (dev,NULL ,GFP_KERNEL ))return ERR_PTR (-ENOMEM );
@@ -549,15 +573,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) {
@@ -625,6 +651,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 27/337 ahci: Introduce ahci_ignore_port() helper
In reply to Greg Kroah-Hartman6.12-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
@@ -329,7 +329,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 */
@@ -380,6 +380,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 28/337 ata: ahci_ceva: fix error paths in ceva_ahci_platform_enable_resources()
In reply to Greg Kroah-Hartman6.12-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 29/337 ASoC: max98095: fix missing IS_ERR() before PTR_ERR() on mclk lookup
In reply to Greg Kroah-Hartman6.12-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 30/337 ASoC: max98090: fix missing IS_ERR() before PTR_ERR() on mclk lookup
In reply to Greg Kroah-Hartman6.12-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 31/337 of: reserved_mem: Add code to dynamically allocate reserved_mem array
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oreoluwa Babatunde <[email protected]>
[ Upstream commit 00c9a452a235c61f099504783badd9a7675ff5a5 ]
The reserved_mem array is statically allocated with a size of MAX_RESERVED_REGIONS(64). Therefore, if the number of reserved_mem regions exceeds this size, there will not be enough space to store all the data.
Hence, extend the use of the static array by introducing a dynamically allocated array based on the number of reserved memory regions specified in the DT.
On architectures such as arm64, memblock allocated memory is not writable until after the page tables have been setup. Hence, the dynamic allocation of the reserved_mem array will need to be done only after the page tables have been setup.
As a result, a temporary static array is still needed in the initial stages to store the information of the dynamically-placed reserved memory regions because the start address is selected only at run-time and is not stored anywhere else.
It is not possible to wait until the reserved_mem array is allocated because this is done after the page tables are setup and the reserved memory regions need to be initialized before then.
After the reserved_mem array is allocated, all entries from the static array is copied over to the new array, and the rest of the information for the statically-placed reserved memory regions are read in from the DT and stored in the new array as well.
Once the init process is completed, the temporary static array is released back to the system because it is no longer needed. This is achieved by marking it as __initdata.
Stable-dep-of: db3dbdfea1b8 ("of: reserved_mem: prevent OOB when too many dynamic regions are defined")
--- drivers/of/of_reserved_mem.c | 63 +++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 4 deletions(-)
drivers/of/of_reserved_mem.c +59 -4
@@ -28,7 +28,9 @@#include "of_private.h" -static struct reserved_mem reserved_mem[MAX_RESERVED_REGIONS ]; +static struct reserved_mem reserved_mem_array[MAX_RESERVED_REGIONS ]__initdata ; +static struct reserved_mem *reserved_mem__refdata = reserved_mem_array; +static int total_reserved_mem_cnt =MAX_RESERVED_REGIONS ;static int reserved_mem_count; static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,
@@ -57,6 +59,50 @@ static int __init early_init_dt_alloc_reserved_memory_arch(phys_addr_t size,return err; } +/* +* alloc_reserved_mem_array() - allocate memory for the reserved_mem +* array using memblock +* +* This function is used to allocate memory for the reserved_mem +* array according to the total number of reserved memory regions +* defined in the DT. +* After the new array is allocated, the information stored in +* the initial static array is copied over to this new array and +* the new array is used from this point on. +*/ +static void __init alloc_reserved_mem_array (void ) +{ +struct reserved_mem *new_array; +size_t alloc_size, copy_size, memset_size; + + alloc_size =array_size (total_reserved_mem_cnt,sizeof (*new_array)); +if (alloc_size ==SIZE_MAX ) { +pr_err ("Failed to allocate memory for reserved_mem array with err: %d" , -EOVERFLOW ); +return ; + } + + new_array =memblock_alloc (alloc_size,SMP_CACHE_BYTES ); +if (!new_array) { +pr_err ("Failed to allocate memory for reserved_mem array with err: %d" , -ENOMEM ); +return ; + } + + copy_size =array_size (reserved_mem_count,sizeof (*new_array)); +if (copy_size ==SIZE_MAX ) { +memblock_free (new_array, alloc_size); + total_reserved_mem_cnt =MAX_RESERVED_REGIONS ; +pr_err ("Failed to allocate memory for reserved_mem array with err: %d" , -EOVERFLOW ); +return ; + } + + memset_size = alloc_size - copy_size; + +memcpy (new_array, reserved_mem, copy_size); +memset (new_array + reserved_mem_count,0 , memset_size); + + reserved_mem = new_array; +} +static void __init fdt_init_reserved_mem_node (struct reserved_mem *rmem);/* * fdt_reserved_mem_save_node() - save fdt node for second pass initialization
@@ -66,7 +112,7 @@ static void __init fdt_reserved_mem_save_node(unsigned long node, const char *un {struct reserved_mem *rmem = &reserved_mem[reserved_mem_count]; -if (reserved_mem_count ==ARRAY_SIZE (reserved_mem)) { +if (reserved_mem_count == total_reserved_mem_cnt) {pr_err ("not enough space for all defined regions.\n" );return ; }
@@ -199,6 +245,9 @@ void __init fdt_scan_reserved_mem_reg_nodes(void)return ; } +/* Attempt dynamic allocation of a new reserved_mem array */ +alloc_reserved_mem_array (); +if (__reserved_mem_check_root (node)) {pr_err ("Reserved memory: unsupported node format, ignoring\n" );return ;
@@ -243,7 +292,7 @@ static int __init __reserved_mem_alloc_size(unsigned long node, const char *unamint __init fdt_scan_reserved_mem (void ) {int node, child; -int dynamic_nodes_cnt =0 ; +int dynamic_nodes_cnt =0 , count =0 ;int dynamic_nodes[MAX_RESERVED_REGIONS ];const void *fdt = initial_boot_params;
@@ -266,6 +315,8 @@ int __init fdt_scan_reserved_mem(void) uname =fdt_get_name (fdt, child,NULL ); err =__reserved_mem_reserve_reg (child, uname); +if (!err) + count++;/* * Save the nodes for the dynamically-placed regions * into an array which will be used for allocation right
@@ -280,11 +331,15 @@ int __init fdt_scan_reserved_mem(void) }for (int i =0 ; i < dynamic_nodes_cnt; i++) {const char *uname; +int err; child = dynamic_nodes[i]; uname =fdt_get_name (fdt, child,NULL ); -__reserved_mem_alloc_size (child, uname); + err =__reserved_mem_alloc_size (child, uname); +if (!err) + count++; } + total_reserved_mem_cnt = count;return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 32/337 of: reserved_mem: prevent OOB when too many dynamic regions are defined
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sang-Heon Jeon <[email protected]>
[ Upstream commit db3dbdfea1b8f38774419c5c2c14e4b81c48708d ]
On boot, fdt_scan_reserved_mem() saves each dynamically-placed /reserved-memory subnode into a local array of size MAX_RESERVED_REGIONS.
If the device tree defines more than MAX_RESERVED_REGIONS dynamically-placed regions, fdt_scan_reserved_mem() writes past the end of the local array.
Add a bounds check that logs an error and skips the excess regions, restoring the original behavior.
--- drivers/of/of_reserved_mem.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-)
drivers/of/of_reserved_mem.c +11 -3
@@ -317,6 +317,7 @@ int __init fdt_scan_reserved_mem(void) err =__reserved_mem_reserve_reg (child, uname);if (!err) count++; +/* * Save the nodes for the dynamically-placed regions * into an array which will be used for allocation right
@@ -324,10 +325,17 @@ int __init fdt_scan_reserved_mem(void)* or marked as no-map. This is done to avoid dynamically * allocating from one of the statically-placed regions. */ -if (err == -ENOENT &&of_get_flat_dt_prop (child,"size" ,NULL )) { - dynamic_nodes[dynamic_nodes_cnt] = child; - dynamic_nodes_cnt++; +if (err != -ENOENT || !of_get_flat_dt_prop (child,"size" ,NULL )) +continue ; + +if (dynamic_nodes_cnt ==MAX_RESERVED_REGIONS ) { +pr_err ("too many defined dynamic regions, skip '%s'\n" , + uname); +continue ; } + + dynamic_nodes[dynamic_nodes_cnt] = child; + dynamic_nodes_cnt++; }for (int i =0 ; i < dynamic_nodes_cnt; i++) {const char *uname;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 33/337 btrfs: fix leaking BTRFS_FS_STATE_REMOUNTING flag
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
[ Upstream commit 6881f45d0eb541f2cee8c37c84b3860a23823bb3 ]
[BUG]
The following script can lead to unexpected qgroup rescan failure:
# mkfs.btrfs -f -O quota $dev
# mount $dev $mnt
# mount -o remount,rescue=ibadroots $mnt
^^^^^ This above command is expected to fail # btrfs quota rescan -w $mnt
^^^^^ The above qgroup rescan is not expected to fail# btrfs qgroup show $mnt WARNING: qgroup data inconsistent, rescan recommended Qgroupid Referenced Exclusive Path -------- ---------- --------- ---- 0/5 16.00KiB 16.00KiB <toplevel>
The above short script will be converted to a proper fstests case.
[CAUSE]
Inside btrfs_reconfigure(), if either btrfs_check_options() or btrfs_check_features() failed, we will always have BTRFS_FS_STATE_REMOUNTING set for the fs until the next successful remount.
That BTRFS_FS_STATE_REMOUNTING flag will interrupt several operations, including:
- Qgroup rescan
- Auto defrag
- Space reclaim
[FIX]
Change the error handling of btrfs_check_options() and btrfs_check_features() to goto restore label.
--- fs/btrfs/super.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
fs/btrfs/super.c +5 -3
@@ -1509,12 +1509,14 @@ static int btrfs_reconfigure(struct fs_context *fc)sync_filesystem (sb);set_bit (BTRFS_FS_STATE_REMOUNTING , &fs_info->fs_state); -if (!btrfs_check_options (fs_info, &ctx->mount_opt, fc->sb_flags)) -return -EINVAL ; +if (!btrfs_check_options (fs_info, &ctx->mount_opt, fc->sb_flags)) { + ret = -EINVAL ; + goto restore; + } ret =btrfs_check_features (fs_info, !(fc->sb_flags &SB_RDONLY ));if (ret <0 ) -return ret; + goto restore;btrfs_ctx_to_info (fs_info, ctx);btrfs_remount_begin (fs_info, old_ctx.mount_opt, fc->sb_flags);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 34/337 btrfs: zoned: fix deadlock between metadata writeback and transaction commit
In reply to Greg Kroah-Hartman6.12-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
@@ -2122,7 +2122,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 35/337 phy-zynqmp: Postpone getting clock rate until actually needed
In reply to Greg Kroah-Hartman6.12-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
@@ -222,7 +222,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
@@ -235,7 +234,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;
@@ -398,13 +396,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),
@@ -446,6 +471,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. */
@@ -658,7 +685,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) {
@@ -823,8 +853,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 ); }
@@ -928,9 +957,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 ];
@@ -946,29 +973,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 36/337 phy: zynqmp: fix clock error handling in xpsgtr_phy_init()
In reply to Greg Kroah-Hartman6.12-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
@@ -658,12 +658,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. */
@@ -673,7 +674,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; }
@@ -687,7 +688,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);
@@ -705,6 +706,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 37/337 phy: zynqmp: fix runtime PM leak on probe allocation failure
In reply to Greg Kroah-Hartman6.12-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
@@ -1044,6 +1044,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);
@@ -1053,12 +1059,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 38/337 netfilter: nf_conntrack_sip: widen NAT rewrite delta to s32 in sip_help_tcp()
In reply to Greg Kroah-Hartman6.12-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 39/337 drm/mediatek: Check CRTC state before freeing
In reply to Greg Kroah-Hartman6.12-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_crtc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/gpu/drm/mediatek/mtk_crtc.c +3 -3
@@ -153,10 +153,10 @@ static void mtk_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 40/337 Drivers: hv: vmbus: Replace lockdep_hardirq_threaded() with lockdep annotation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sebastian Andrzej Siewior <[email protected]>
[ Upstream commit 8c7ab779c8850f4dab8473463cca9a7d52fdaecc ]
lockdep_hardirq_threaded() is supposed to be used within IRQ core code and not within drivers. It is not obvious from within the driver, that this is the only interrupt service routing and that it is not shared handler.
Replace lockdep_hardirq_threaded() with a lockdep annotation limiting threaded context on PREEMPT_RT to __vmbus_isr().
--- drivers/hv/vmbus_drv.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
drivers/hv/vmbus_drv.c +12 -1
@@ -1320,8 +1320,19 @@ static void vmbus_isr(void)if (IS_ENABLED (CONFIG_PREEMPT_RT )) {vmbus_irqd_wake (); }else { -lockdep_hardirq_threaded (); + static DEFINE_WAIT_OVERRIDE_MAP(vmbus_map, LD_WAIT_CONFIG); + +/* +* vmbus_isr is never force-threaded and always invoked at hard +* IRQ level. __vmbus_isr() below can acquire a spinlock_t +* which becomes a sleeping lock and must not be acquired in +* this context. Therefore on PREEMPT_RT this will be threaded +* via vmbus_irqd_wake(). On non-PREEMPT the annotation lets +* lockdep know that acquiring a spinlock_t is not an issue. +*/ +lock_map_acquire_try (&vmbus_map);__vmbus_isr (); +lock_map_release (&vmbus_map); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 41/337 KEYS: trusted: dcp: fix key_len validation and calc_blob_len() return type
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fabrice Derepas <[email protected]>
[ Upstream commit 35d661c98fe4733490f20b4311616a3c2c30abc0 ]
Two correctness and type-hygiene issues exist in the DCP trusted keys implementation.
First, trusted_dcp_unseal() reads p->key_len from a user-supplied blob without checking if it exceeds MAX_KEY_SIZE. If a crafted blob provides a payload_len larger than 128, the subsequent do_aead_crypto() call writes past the end of the p->key array into the adjacent p->blob buffer within the same struct trusted_key_payload -- the caller's own input, not unrelated kernel memory. While not exploitable, this violates strict array bounds and triggers static analyzers. Fix this by adding a validation check against MIN_KEY_SIZE and MAX_KEY_SIZE immediately after reading the length, matching the checks already done in trusted_core.c.
Second, calc_blob_len() calculates a sum in size_t that truncates to unsigned int on 64-bit platforms. Because the DCP hardware is only present on 32-bit i.MX SoC platforms, size_t and unsigned int are functionally equivalent in production, making this truncation harmless in practice. Nevertheless, updating the return type to size_t (and subsequently updating 'blen' in the seal/unseal paths) resolves type-narrowing warnings and improves overall code hygiene.
--- security/keys/trusted-keys/trusted_dcp.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-)
security/keys/trusted-keys/trusted_dcp.c +11 -4
@@ -69,7 +69,7 @@ static bool skip_zk_test;module_param_named (dcp_skip_zk_test, skip_zk_test, bool,0 );MODULE_PARM_DESC (dcp_skip_zk_test,"Don't test whether device keys are zero'ed" ); -static unsigned int calc_blob_len (unsigned int payload_len) +static size_t calc_blob_len (unsigned int payload_len) {return sizeof (struct dcp_blob_fmt ) + payload_len +DCP_BLOB_AUTHLEN ; }
@@ -200,7 +200,8 @@ static int encrypt_blob_key(u8 *plain_key, u8 *encrypted_key)static int trusted_dcp_seal (struct trusted_key_payload *p,char *datablob) {struct dcp_blob_fmt *b = (struct dcp_blob_fmt *)p->blob; -int blen, ret; +size_t blen; +int ret;u8 *plain_blob_key; blen =calc_blob_len (p->key_len);
@@ -242,7 +243,8 @@ static int trusted_dcp_seal(struct trusted_key_payload *p, char *datablob)static int trusted_dcp_unseal (struct trusted_key_payload *p,char *datablob) {struct dcp_blob_fmt *b = (struct dcp_blob_fmt *)p->blob; -int blen, ret; +size_t blen; +int ret;u8 *plain_blob_key =NULL ;if (b->fmt_version !=DCP_BLOB_VERSION ) {
@@ -253,9 +255,14 @@ static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob) } p->key_len =le32_to_cpu (b->payload_len); +if (p->key_len <MIN_KEY_SIZE || p->key_len >MAX_KEY_SIZE ) { + ret = -EINVAL ; + goto out; + } + blen =calc_blob_len (p->key_len);if (blen != p->blob_len) { -pr_err ("DCP blob has bad length: %i != %i\n" , blen, +pr_err ("DCP blob has bad length: %zu != %u\n" , blen, p->blob_len); ret = -EINVAL ; goto out;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 42/337 keys: fix out-of-bounds read in keyring_get_key_chunk()
In reply to Greg Kroah-Hartman6.12-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 43/337 keys: make keyring key-chunk byte order agree with keyring_diff_objects()
In reply to Greg Kroah-Hartman6.12-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 44/337 assoc_array: trim the final shortcut word using the current chunk end
In reply to Greg Kroah-Hartman6.12-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 45/337 netfilter: nf_tables: make nft_object rhltable per table
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit f4f699790590bd0896c48a71e9232a65198f92f0 ]
The nft_object rhltable is global, this allows for accessing objects that are being dismangled from lookup path by other existing netns. Given the nft_obj_destroy() releases the object inmediately, this might lead to use-after-free of these objects that are being released. Make the existing rhltable per table to address this issue to deal with with the nft_rcv_nl_event() path too.
Update nft_obj_lookup() to take the table as non-const, otherwise, compiler complains when passing the objname_ht to rhltable_lookup().
--- include/net/netfilter/nf_tables.h | 4 +++- net/netfilter/nf_tables_api.c | 34 +++++++++++++++---------------- 2 files changed, 19 insertions(+), 19 deletions(-)
include/net/netfilter/nf_tables.h +3 -1
@@ -1274,6 +1274,7 @@ static inline void nft_use_inc_restore(u32 *use)* @sets: sets in the table * @objects: stateful objects in the table * @flowtables: flow tables in the table +* @objname_ht: hashtable for objects lookup by name * @hgenerator: handle generator state * @handle: table handle * @use: number of chain references to this table
@@ -1293,6 +1294,7 @@ struct nft_table {struct list_head sets;struct list_head objects;struct list_head flowtables; +struct rhltable objname_ht;u64 hgenerator;u64 handle;u32 use;
@@ -1380,7 +1382,7 @@ static inline void *nft_obj_data(const struct nft_object *obj)#define nft_expr_obj (expr) *((struct nft_object **)nft_expr_priv(expr))struct nft_object *nft_obj_lookup (const struct net *net, -const struct nft_table *table, +struct nft_table *table,const struct nlattr *nla,u32 objtype,u8 genmask);
net/netfilter/nf_tables_api.c +16 -18
@@ -41,8 +41,6 @@ enum { NFT_VALIDATE_DO, }; -static struct rhltable nft_objname_ht; -static u32 nft_chain_hash (const void *data,u32 len,u32 seed);static u32 nft_chain_hash_obj (const void *data,u32 len,u32 seed);static int nft_chain_hash_cmp (struct rhashtable_compare_arg *,const void *);
@@ -1457,6 +1455,10 @@ static int nf_tables_newtable(struct sk_buff *skb, const struct nfnl_info *info,if (err) goto err_chain_ht; + err =rhltable_init (&table->objname_ht, &nft_objname_ht_params); +if (err <0 ) + goto err_obj_ht; +INIT_LIST_HEAD (&table->chains);INIT_LIST_HEAD (&table->sets);INIT_LIST_HEAD (&table->objects);
@@ -1475,6 +1477,8 @@ static int nf_tables_newtable(struct sk_buff *skb, const struct nfnl_info *info,list_add_tail_rcu (&table->list, &nft_net->tables);return 0 ; err_trans: +rhltable_destroy (&table->objname_ht); +err_obj_ht:rhltable_destroy (&table->chains_ht); err_chain_ht:kfree (table->udata);
@@ -1641,6 +1645,7 @@ static void nf_tables_table_destroy(struct nft_table *table)return ;rhltable_destroy (&table->chains_ht); +rhltable_destroy (&table->objname_ht);kfree (table->name);kfree (table->udata);kfree (table);
@@ -7578,7 +7583,7 @@ void nft_unregister_obj(struct nft_object_type *obj_type)EXPORT_SYMBOL_GPL (nft_unregister_obj);struct nft_object *nft_obj_lookup (const struct net *net, -const struct nft_table *table, +struct nft_table *table,const struct nlattr *nla,u32 objtype,u8 genmask) {
@@ -7594,7 +7599,7 @@ struct nft_object *nft_obj_lookup(const struct net *net, !lockdep_commit_lock_is_held(net));rcu_read_lock (); - list =rhltable_lookup (&nft_objname_ht, &k, nft_objname_ht_params); + list =rhltable_lookup (&table->objname_ht, &k, nft_objname_ht_params);if (!list) goto out;
@@ -7873,7 +7878,7 @@ static int nf_tables_newobj(struct sk_buff *skb, const struct nfnl_info *info,if (err <0 ) goto err_trans; - err =rhltable_insert (&nft_objname_ht, &obj->rhlhead, + err =rhltable_insert (&table->objname_ht, &obj->rhlhead, nft_objname_ht_params);if (err <0 ) goto err_obj_ht;
@@ -8052,8 +8057,8 @@ nf_tables_getobj_single(u32 portid, const struct nfnl_info *info,struct netlink_ext_ack *extack = info->extack;u8 genmask =nft_genmask_cur (info->net);u8 family = info->nfmsg->nfgen_family; -const struct nft_table *table;struct net *net = info->net; +struct nft_table *table;struct nft_object *obj;struct sk_buff *skb2;u32 objtype;
@@ -9782,9 +9787,9 @@ static void nf_tables_commit_chain(struct net *net, struct nft_chain *chain)nf_tables_commit_chain_free_rules_old (g0); } -static void nft_obj_del (struct nft_object *obj) +static void nft_obj_del (struct nft_table *table,struct nft_object *obj) { -rhltable_remove (&nft_objname_ht, &obj->rhlhead, nft_objname_ht_params); +rhltable_remove (&table->objname_ht, &obj->rhlhead, nft_objname_ht_params);list_del_rcu (&obj->list); }
@@ -10480,7 +10485,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)break ;case NFT_MSG_DELOBJ :case NFT_MSG_DESTROYOBJ : -nft_obj_del (nft_trans_obj (trans)); +nft_obj_del (table,nft_trans_obj (trans));nf_tables_obj_notify (&ctx,nft_trans_obj (trans), trans->msg_type);break ;
@@ -10780,7 +10785,7 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)nft_trans_destroy (trans); }else {nft_use_dec_restore (&table->use); -nft_obj_del (nft_trans_obj (trans)); +nft_obj_del (table,nft_trans_obj (trans)); }break ;case NFT_MSG_DELOBJ :
@@ -11447,7 +11452,7 @@ static void __nft_release_table(struct net *net, struct nft_table *table)nft_set_destroy (&ctx, set); }list_for_each_entry_safe (obj, ne, &table->objects, list) { -nft_obj_del (obj); +nft_obj_del (table, obj);nft_use_dec (&table->use);nft_obj_destroy (&ctx, obj); }
@@ -11629,10 +11634,6 @@ static int __init nf_tables_module_init(void)if (err <0 ) goto err_netdev_notifier; - err =rhltable_init (&nft_objname_ht, &nft_objname_ht_params); -if (err <0 ) - goto err_rht_objname; - err =nft_offload_init ();if (err <0 ) goto err_offload;
@@ -11655,8 +11656,6 @@ static int __init nf_tables_module_init(void) err_netlink_notifier:nft_offload_exit (); err_offload: -rhltable_destroy (&nft_objname_ht); -err_rht_objname:unregister_netdevice_notifier (&nf_tables_flowtable_notifier); err_netdev_notifier:nf_tables_core_module_exit ();
@@ -11678,7 +11677,6 @@ static void __exit nf_tables_module_exit(void)unregister_pernet_subsys (&nf_tables_net_ops);cancel_work_sync (&trans_gc_work);rcu_barrier (); -rhltable_destroy (&nft_objname_ht);nf_tables_core_module_exit (); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 46/337 netfilter: xt_hashlimit: validate hashtable supports XT_HASHLIMIT_RATE_MATCH
In reply to Greg Kroah-Hartman6.12-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 47/337 ipvs: fix the checksum validations
In reply to Greg Kroah-Hartman6.12-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));
@@ -1720,7 +1721,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);
@@ -1886,6 +1888,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 48/337 ipvs: fix places with wrong packet offsets
In reply to Greg Kroah-Hartman6.12-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
@@ -1499,8 +1499,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;
@@ -1512,7 +1513,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 */
@@ -1530,7 +1531,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);
@@ -1562,13 +1563,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 ;
@@ -1584,8 +1585,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;
@@ -1597,7 +1599,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 */
@@ -1614,7 +1616,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));
@@ -1646,13 +1648,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 49/337 ipvs: do not mangle ICMP replies for non-first fragments
In reply to Greg Kroah-Hartman6.12-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
@@ -1500,13 +1500,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
@@ -1562,6 +1563,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;
@@ -1569,7 +1577,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 ;
@@ -1586,10 +1594,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;
@@ -1647,6 +1656,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;
@@ -1654,7 +1670,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 50/337 netfilter: nft_payload: fix mask build for partial field offload
In reply to Greg Kroah-Hartman6.12-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 51/337 rds: Fix inet6_addr_lst NULL dereference when IPv6 is disabled
In reply to Greg Kroah-Hartman6.12-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
@@ -342,9 +342,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 52/337 rds: tcp: hold the RCU lock across ipv6_chk_addr() in rds_tcp_laddr_check()
In reply to Greg Kroah-Hartman6.12-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
@@ -331,23 +331,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 53/337 pinctrl-amd: Dont clear S4 wake bits at probe
In reply to Greg Kroah-Hartman6.12-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 54/337 scsi: libiscsi: Fix stale-data leak into the SCSI sense buffer
In reply to Greg Kroah-Hartman6.12-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 55/337 scsi: libiscsi_tcp: Bound SCSI Response data segment to the connection buffer
In reply to Greg Kroah-Hartman6.12-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 56/337 scsi: libsas: Fix HA resume deadlock and hisi_sas disk-wake race
In reply to Greg Kroah-Hartman6.12-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
@@ -5219,15 +5219,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
@@ -676,7 +676,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_phy_reset (struct sas_phy *phy,int hard_reset);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 57/337 smb: client: fix buffer leaks in SMB1 read and write
In reply to Greg Kroah-Hartman6.12-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
@@ -1436,8 +1436,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;
@@ -1549,8 +1551,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;
@@ -1816,8 +1820,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 58/337 spi: spi-cadence: supports transmission with bits_per_word of 16 and 32
In reply to Greg Kroah-Hartman6.12-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
@@ -109,6 +109,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
@@ -120,16 +121,24 @@ 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;struct reset_control *rstc; }; +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) {
@@ -305,6 +314,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
@@ -321,23 +402,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--; } - } }
@@ -454,6 +526,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 );
@@ -654,6 +730,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;
@@ -809,6 +888,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 59/337 spi: spi-cadence: Move TX FIFO full busy-wait into FIFO
In reply to Greg Kroah-Hartman6.12-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
@@ -388,11 +388,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);
@@ -407,6 +409,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--; }
@@ -460,14 +472,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);
@@ -520,17 +532,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 60/337 hwmon: (nct6775-core) Fix number of temperature registers for NCT6116
In reply to Greg Kroah-Hartman6.12-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 61/337 hwmon: (ina2xx) Add support for has_alerts configuration flag
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit de0da6ae1908b43b23782d64b4564b5ca3119f7f ]
Add configuration flag indicating if the chip supports alerts and limits to prepare for adding INA260 support.
Stable-dep-of: e6c80061ca23 ("hwmon: (ina2xx) Fix various overflow issues")
--- drivers/hwmon/ina2xx.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
drivers/hwmon/ina2xx.c +11 -7
@@ -129,6 +129,7 @@ enum ina2xx_ids { ina219, ina226 };struct ina2xx_config {u16 config_default; +bool has_alerts;/* chip supports alerts and limits */ int calibration_value;int shunt_div;int bus_voltage_shift;
@@ -155,6 +156,7 @@ static const struct ina2xx_config ina2xx_config[] = { .bus_voltage_shift = 3, .bus_voltage_lsb = 4000, .power_lsb_factor = 20, + .has_alerts = false, }, [ina226] = { .config_default = INA226_CONFIG_DEFAULT,
@@ -163,6 +165,7 @@ static const struct ina2xx_config ina2xx_config[] = { .bus_voltage_shift = 0, .bus_voltage_lsb = 1250, .power_lsb_factor = 25, + .has_alerts = true, }, };
@@ -624,6 +627,7 @@ static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types type u32 attr, int channel) {const struct ina2xx_data *data = _data; +bool has_alerts = data->config->has_alerts;enum ina2xx_ids chip = data->chip;switch (type) {
@@ -633,12 +637,12 @@ static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types typereturn 0444 ;case hwmon_in_lcrit:case hwmon_in_crit: -if (chip == ina226) +if (has_alerts)return 0644 ;break ;case hwmon_in_lcrit_alarm:case hwmon_in_crit_alarm: -if (chip == ina226) +if (has_alerts)return 0444 ;break ;default :
@@ -651,12 +655,12 @@ static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types typereturn 0444 ;case hwmon_curr_lcrit:case hwmon_curr_crit: -if (chip == ina226) +if (has_alerts)return 0644 ;break ;case hwmon_curr_lcrit_alarm:case hwmon_curr_crit_alarm: -if (chip == ina226) +if (has_alerts)return 0444 ;break ;default :
@@ -668,11 +672,11 @@ static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types typecase hwmon_power_input:return 0444 ;case hwmon_power_crit: -if (chip == ina226) +if (has_alerts)return 0644 ;break ;case hwmon_power_crit_alarm: -if (chip == ina226) +if (has_alerts)return 0444 ;break ;default :
@@ -802,7 +806,7 @@ static int ina2xx_init(struct device *dev, struct ina2xx_data *data)if (ret <0 )return ret; -if (data->chip == ina226) { +if (data->config->has_alerts) {bool active_high =device_property_read_bool (dev,"ti,alert-polarity-active-high" ); regmap_update_bits(regmap, INA226_MASK_ENABLE,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 62/337 hwmon: (ina2xx) Add support for INA260
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit 70fb84a109c639637f0636281dbdb21ed8ffb000 ]
INA260 is similar to other chips of the series, except it has an internal shunt resistor. The calibration register is therefore not present. Also, the current register address was changed, though that does not matter for the driver since the shunt voltage register (which is now the current register) value is already used to read the current.
Stable-dep-of: e6c80061ca23 ("hwmon: (ina2xx) Fix various overflow issues")
--- Documentation/hwmon/ina2xx.rst | 23 +++++++++++++++---- drivers/hwmon/Kconfig | 5 ++-- drivers/hwmon/ina2xx.c | 42 ++++++++++++++++++++++++++++++---- 3 files changed, 59 insertions(+), 11 deletions(-)
Documentation/hwmon/ina2xx.rst +18 -5
@@ -53,6 +53,16 @@ Supported chips: https://www.ti.com/ + * Texas Instruments INA260 + + Prefix: 'ina260' + + Addresses: I2C 0x40 - 0x4f + + Datasheet: Publicly available at the Texas Instruments website + + https://www.ti.com/ + Author: Lothar Felten <[email protected]> Description
@@ -72,6 +82,9 @@ INA230 and INA231 are high or low side current shunt and power monitors with an I2C interface. The chips monitor both a shunt voltage drop and bus supply voltage. +INA260 is a high or low side current and power monitor with integrated shunt +resistor. + The shunt value in micro-ohms can be set via platform data or device tree at compile-time or via the shunt_resistor attribute in sysfs at run-time. Please refer to the Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml for bindings
@@ -87,16 +100,16 @@ The actual programmed interval may vary from the desired value. General sysfs entries --------------------- -======================= =============================== +======================= =============================================== in0_input Shunt voltage(mV) channel in1_input Bus voltage(mV) channel curr1_input Current(mA) measurement channel power1_input Power(uW) measurement channel -shunt_resistor Shunt resistance(uOhm) channel -======================= =============================== +shunt_resistor Shunt resistance(uOhm) channel (not for ina260) +======================= =============================================== -Sysfs entries for ina226, ina230 and ina231 only ------------------------------------------------- +Additional sysfs entries for ina226, ina230, ina231, and ina260 +--------------------------------------------------------------- ======================= ==================================================== curr1_lcrit Critical low current
drivers/hwmon/Kconfig +3 -2
@@ -2170,11 +2170,12 @@ config SENSORS_INA2XX select REGMAP_I2C help If you say yes here you get support for INA219, INA220, INA226, - INA230, and INA231 power monitor chips. + INA230, INA231, and INA260 power monitor chips. The INA2xx driver is configured for the default configuration of the part as described in the datasheet. - Default value for Rshunt is 10 mOhms. + Default value for Rshunt is 10 mOhms except for INA260 which has an + internal 2 mOhm shunt resistor. This driver can also be built as a module. If so, the module will be called ina2xx.
drivers/hwmon/ina2xx.c +38 -4
118 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 63/337 hwmon: (ina226) Add support for SY24655
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wenliang Yan <[email protected]>
[ Upstream commit 52172ad87a22ed6e687ca678da21d3c949bc89a1 ]
SY24655: Support for current and voltage detection as well as power calculation.
Message-ID: <[email protected]> [groeck: Changed order of compatible entries;
dropped spurious extra return statement in is_visible(); fixed code problems]
Stable-dep-of: e6c80061ca23 ("hwmon: (ina2xx) Fix various overflow issues")
--- Documentation/hwmon/ina2xx.rst | 27 +++++++++- drivers/hwmon/Kconfig | 2 +- drivers/hwmon/ina2xx.c | 94 ++++++++++++++++++++++++++++++++-- 3 files changed, 116 insertions(+), 7 deletions(-)
Documentation/hwmon/ina2xx.rst +25 -2
@@ -63,6 +63,17 @@ Supported chips: https://www.ti.com/ + * Silergy SY24655 + + Prefix: 'sy24655' + + Addresses: I2C 0x40 - 0x4f + + Datasheet: Publicly available at the Silergy website + + https://us1.silergy.com/ + + Author: Lothar Felten <[email protected]> Description
@@ -85,6 +96,11 @@ bus supply voltage. INA260 is a high or low side current and power monitor with integrated shunt resistor. +The SY24655 is a high- and low-side current shunt and power monitor with an I2C +interface. The SY24655 supports both shunt drop and supply voltage, with +programmable calibration value and conversion times. The SY24655 can also +calculate average power for use in energy conversion. + The shunt value in micro-ohms can be set via platform data or device tree at compile-time or via the shunt_resistor attribute in sysfs at run-time. Please refer to the Documentation/devicetree/bindings/hwmon/ti,ina2xx.yaml for bindings
@@ -108,8 +124,8 @@ power1_input Power(uW) measurement channel shunt_resistor Shunt resistance(uOhm) channel (not for ina260) ======================= =============================================== -Additional sysfs entries for ina226, ina230, ina231, and ina260 ---------------------------------------------------------------- +Additional sysfs entries for ina226, ina230, ina231, ina260, and sy24655 +------------------------------------------------------------------------ ======================= ==================================================== curr1_lcrit Critical low current
@@ -130,6 +146,13 @@ update_interval data conversion time; affects number of samples used to average results for shunt and bus voltages. ======================= ==================================================== +Sysfs entries for sy24655 only +------------------------------ + +======================= ==================================================== +power1_average average power from last reading to the present. +======================= ==================================================== + .. note:: - Configure `shunt_resistor` before configure `power1_crit`, because power
drivers/hwmon/Kconfig +1 -1
@@ -2170,7 +2170,7 @@ config SENSORS_INA2XX select REGMAP_I2C help If you say yes here you get support for INA219, INA220, INA226, - INA230, INA231, and INA260 power monitor chips. + INA230, INA231, INA260, and SY24655 power monitor chips. The INA2xx driver is configured for the default configuration of the part as described in the datasheet.
drivers/hwmon/ina2xx.c +90 -4
205 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 64/337 hwmon: (ina2xx) Make it easier to add more devices
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Ray <[email protected]>
[ Upstream commit f6e14b5bcabf4ee97a2d535c3c2d7e72c8da4c15 ]
* Make sysfs entries documentation easier to maintain.
* Use multi-line enum.
* Correct "has_power_average" comment.
Create a new "has_update_interval" member for chips which support averaging.
Stable-dep-of: e6c80061ca23 ("hwmon: (ina2xx) Fix various overflow issues")
--- Documentation/hwmon/ina2xx.rst | 12 ++++++++++-- drivers/hwmon/ina2xx.c | 18 ++++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-)
Documentation/hwmon/ina2xx.rst +10 -2
@@ -124,8 +124,16 @@ power1_input Power(uW) measurement channel shunt_resistor Shunt resistance(uOhm) channel (not for ina260) ======================= =============================================== -Additional sysfs entries for ina226, ina230, ina231, ina260, and sy24655 ------------------------------------------------------------------------- +Additional sysfs entries +------------------------ + +Additional entries are available for the following chips: + + * ina226 + * ina230 + * ina231 + * ina260 + * sy24655 ======================= ==================================================== curr1_lcrit Critical low current
drivers/hwmon/ina2xx.c +14 -4
@@ -135,13 +135,19 @@ static const struct regmap_config ina2xx_regmap_config = { .writeable_reg = ina2xx_writeable_reg, }; -enum ina2xx_ids { ina219, ina226, ina260, sy24655 }; +enum ina2xx_ids { + ina219, + ina226, + ina260, + sy24655 +};struct ina2xx_config {u16 config_default;bool has_alerts;/* chip supports alerts and limits */ bool has_ishunt;/* chip has internal shunt resistor */ -bool has_power_average;/* chip has internal shunt resistor */ +bool has_power_average;/* chip supports average power */ +bool has_update_interval;int calibration_value;int shunt_div;int bus_voltage_shift;
@@ -172,6 +178,7 @@ static const struct ina2xx_config ina2xx_config[] = { .has_alerts = false, .has_ishunt = false, .has_power_average = false, + .has_update_interval = false, }, [ina226] = { .config_default = INA226_CONFIG_DEFAULT,
@@ -183,6 +190,7 @@ static const struct ina2xx_config ina2xx_config[] = { .has_alerts = true, .has_ishunt = false, .has_power_average = false, + .has_update_interval = true, }, [ina260] = { .config_default = INA260_CONFIG_DEFAULT,
@@ -193,6 +201,7 @@ static const struct ina2xx_config ina2xx_config[] = { .has_alerts = true, .has_ishunt = true, .has_power_average = false, + .has_update_interval = true, }, [sy24655] = { .config_default = SY24655_CONFIG_DEFAULT,
@@ -204,6 +213,7 @@ static const struct ina2xx_config ina2xx_config[] = { .has_alerts = true, .has_ishunt = false, .has_power_average = true, + .has_update_interval = false, }, };
@@ -713,7 +723,7 @@ static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types typeconst struct ina2xx_data *data = _data;bool has_alerts = data->config->has_alerts;bool has_power_average = data->config->has_power_average; -enum ina2xx_ids chip = data->chip; +bool has_update_interval = data->config->has_update_interval;switch (type) {case hwmon_in:
@@ -775,7 +785,7 @@ static umode_t ina2xx_is_visible(const void *_data, enum hwmon_sensor_types typecase hwmon_chip:switch (attr) {case hwmon_chip_update_interval: -if (chip == ina226 || chip == ina260) +if (has_update_interval)return 0644 ;break ;default :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 65/337 hwmon: (ina2xx) Add support for INA234
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Ray <[email protected]>
[ Upstream commit 88a928eebccdc5445d874ddcbf1683b76c9f1431 ]
INA234 is register compatible to INA226 (excepting manufacturer and die or device id registers) but has different scaling.
Stable-dep-of: e6c80061ca23 ("hwmon: (ina2xx) Fix various overflow issues")
--- Documentation/hwmon/ina2xx.rst | 13 ++++++++++++- drivers/hwmon/Kconfig | 2 +- drivers/hwmon/ina2xx.c | 18 ++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-)
Documentation/hwmon/ina2xx.rst +12 -1
@@ -74,6 +74,16 @@ Supported chips: https://us1.silergy.com/ + * Texas Instruments INA234 + + Prefix: 'ina234' + + Addresses: I2C 0x40 - 0x43 + + Datasheet: Publicly available at the Texas Instruments website + + https://www.ti.com/ + Author: Lothar Felten <[email protected]> Description
@@ -89,7 +99,7 @@ interface. The INA220 monitors both shunt drop and supply voltage. The INA226 is a current shunt and power monitor with an I2C interface. The INA226 monitors both a shunt voltage drop and bus supply voltage. -INA230 and INA231 are high or low side current shunt and power monitors +INA230, INA231, and INA234 are high or low side current shunt and power monitors with an I2C interface. The chips monitor both a shunt voltage drop and bus supply voltage.
@@ -132,6 +142,7 @@ Additional entries are available for the following chips: * ina226 * ina230 * ina231 + * ina234 * ina260 * sy24655
drivers/hwmon/Kconfig +1 -1
@@ -2170,7 +2170,7 @@ config SENSORS_INA2XX select REGMAP_I2C help If you say yes here you get support for INA219, INA220, INA226, - INA230, INA231, INA260, and SY24655 power monitor chips. + INA230, INA231, INA234, INA260, and SY24655 power monitor chips. The INA2xx driver is configured for the default configuration of the part as described in the datasheet.
drivers/hwmon/ina2xx.c +18 -0
@@ -138,6 +138,7 @@ static const struct regmap_config ina2xx_regmap_config = {enum ina2xx_ids { ina219, ina226, + ina234, ina260, sy24655 };
@@ -192,6 +193,18 @@ static const struct ina2xx_config ina2xx_config[] = { .has_power_average = false, .has_update_interval = true, }, + [ina234] = { + .config_default = INA226_CONFIG_DEFAULT, + .calibration_value = 2048, + .shunt_div = 400, /* 2.5 µV/LSB raw ADC reading from INA2XX_SHUNT_VOLTAGE */ + .bus_voltage_shift = 4, + .bus_voltage_lsb = 25600, + .power_lsb_factor = 32, + .has_alerts = true, + .has_ishunt = false, + .has_power_average = false, + .has_update_interval = true, + }, [ina260] = { .config_default = INA260_CONFIG_DEFAULT, .shunt_div = 400,
@@ -996,6 +1009,7 @@ static const struct i2c_device_id ina2xx_id[] = { { "ina226", ina226 }, { "ina230", ina226 }, { "ina231", ina226 }, + { "ina234", ina234 }, { "ina260", ina260 }, { "sy24655", sy24655 }, { }
@@ -1027,6 +1041,10 @@ static const struct of_device_id __maybe_unused ina2xx_of_match[] = { .compatible = "ti,ina231", .data = (void *)ina226 }, + { + .compatible = "ti,ina234", + .data = (void *)ina234 + }, { .compatible ="ti,ina260" , .data = (void *)ina260
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 66/337 hwmon: (ina2xx) Shift INA234 shunt and current registers
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Rebmann <[email protected]>
[ Upstream commit eeca1114d1e2cc0eacaebb80f3f2afbaebfc60be ]
The INA219 has the lowest three bits of the bus voltage register zero-reserved, the bus_voltage_shift ina2xx_config field was introduced to accommodate for that.
The INA234 has four bits of the bus voltage, of the shunt voltage, and of the current registers zero-reserved but the latter two were implemented by choosing a 16x higher shunt_div instead of a separate field specifying a bit shift.
This is possible because shunt voltage and current are divided by shunt_div, hence a 16x higher shunt_div results in a 16x smaller LSB for both the shunt voltage and the current register, perfectly accounting for the missing bit shift.
For consistency and correctness, account for the reserved bits via shunt_voltage_shift and current_shift configuration fields as already done for voltage registers and use the conversion constants given in the INA234 datasheet.
Stable-dep-of: e6c80061ca23 ("hwmon: (ina2xx) Fix various overflow issues")
--- drivers/hwmon/ina2xx.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-)
drivers/hwmon/ina2xx.c +19 -3
@@ -151,9 +151,11 @@ struct ina2xx_config {bool has_update_interval;int calibration_value;int shunt_div; +int shunt_voltage_shift;int bus_voltage_shift;int bus_voltage_lsb;/* uV */ int power_lsb_factor; +int current_shift; };struct ina2xx_data {
@@ -173,59 +175,69 @@ static const struct ina2xx_config ina2xx_config[] = { .config_default = INA219_CONFIG_DEFAULT, .calibration_value = 4096, .shunt_div = 100, + .shunt_voltage_shift = 0, .bus_voltage_shift = 3, .bus_voltage_lsb = 4000, .power_lsb_factor = 20, .has_alerts = false, .has_ishunt = false, .has_power_average = false, + .current_shift = 0, .has_update_interval = false, }, [ina226] = { .config_default = INA226_CONFIG_DEFAULT, .calibration_value = 2048, .shunt_div = 400, + .shunt_voltage_shift = 0, .bus_voltage_shift = 0, .bus_voltage_lsb = 1250, .power_lsb_factor = 25, .has_alerts = true, .has_ishunt = false, .has_power_average = false, + .current_shift = 0, .has_update_interval = true, }, [ina234] = { .config_default = INA226_CONFIG_DEFAULT, .calibration_value = 2048, - .shunt_div = 400, /* 2.5 µV/LSB raw ADC reading from INA2XX_SHUNT_VOLTAGE */ + .shunt_div = 25, /* 2.5 µV/LSB raw ADC reading from INA2XX_SHUNT_VOLTAGE */ + .shunt_voltage_shift = 4, .bus_voltage_shift = 4, .bus_voltage_lsb = 25600, .power_lsb_factor = 32, .has_alerts = true, .has_ishunt = false, .has_power_average = false, + .current_shift = 4, .has_update_interval = true, }, [ina260] = { .config_default = INA260_CONFIG_DEFAULT, .shunt_div = 400, + .shunt_voltage_shift = 0, .bus_voltage_shift = 0, .bus_voltage_lsb = 1250, .power_lsb_factor = 8, .has_alerts = true, .has_ishunt = true, .has_power_average = false, + .current_shift = 0, .has_update_interval = true, }, [sy24655] = { .config_default = SY24655_CONFIG_DEFAULT, .calibration_value = 4096, .shunt_div = 400, + .shunt_voltage_shift = 0, .bus_voltage_shift = 0, .bus_voltage_lsb = 1250, .power_lsb_factor = 25, .has_alerts = true, .has_ishunt = false, .has_power_average = true, + .current_shift = 0, .has_update_interval = false, }, };
@@ -279,7 +291,8 @@ static int ina2xx_get_value(struct ina2xx_data *data, u8 reg,switch (reg) {case INA2XX_SHUNT_VOLTAGE :/* signed register */ - val =DIV_ROUND_CLOSEST ((s16 )regval, data->config->shunt_div); + val = (s16 )regval >> data->config->shunt_voltage_shift; + val =DIV_ROUND_CLOSEST (val, data->config->shunt_div);break ;case INA2XX_BUS_VOLTAGE : val = (regval >> data->config->bus_voltage_shift) *
@@ -291,7 +304,8 @@ static int ina2xx_get_value(struct ina2xx_data *data, u8 reg,break ;case INA2XX_CURRENT :/* signed register, result in mA */ - val = (s16 )regval * data->current_lsb_uA; + val = ((s16 )regval >> data->config->current_shift) * + data->current_lsb_uA; val =DIV_ROUND_CLOSEST (val,1000 );break ;case INA2XX_CALIBRATION :
@@ -385,6 +399,7 @@ static u16 ina226_alert_to_reg(struct ina2xx_data *data, int reg, long val)case INA2XX_SHUNT_VOLTAGE : val =clamp_val (val,0 ,SHRT_MAX * data->config->shunt_div); val *= data->config->shunt_div; + val <<= data->config->shunt_voltage_shift;return clamp_val (val,0 ,SHRT_MAX );case INA2XX_BUS_VOLTAGE : val =clamp_val (val,0 ,200000 );
@@ -399,6 +414,7 @@ static u16 ina226_alert_to_reg(struct ina2xx_data *data, int reg, long val) val =clamp_val (val,INT_MIN /1000 ,INT_MAX /1000 );/* signed register, result in mA */ val =DIV_ROUND_CLOSEST (val *1000 , data->current_lsb_uA); + val <<= data->config->current_shift;return clamp_val (val,SHRT_MIN ,SHRT_MAX );default :/* programmer goofed */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 67/337 hwmon: (ina2xx) Fix various overflow issues
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit e6c80061ca239f45c0eaf7e47a91d6d6df9bd636 ]
Sashiko reports several integer overflow problems in the ina2xx driver caused by unbounded multiplications and inadequate types for intermediate calculations.
Specifically:
- In ina2xx_get_value(), the return type is changed from int to long. Intermediate calculations for current are now performed using 64-bit types to prevent 32-bit integer overflow before the division by 1000.
- When calculating power in ina2xx_get_value() and sy24655_average_power_read(), interim values are cast to u64 and clamped to LONG_MAX. This prevents overflow when regval or accumulator_24 is multiplied by power_lsb_uW.
- In ina226_alert_to_reg(), the clamping logic is rewritten using min_t(). This safely avoids integer overflows when scaling user-provided values for shunt voltage, bus voltage, power, and current limits.
--- drivers/hwmon/ina2xx.c | 61 ++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 26 deletions(-)
drivers/hwmon/ina2xx.c +35 -26
@@ -31,6 +31,7 @@#include <linux/i2c.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/limits.h> #include <linux/module.h> #include <linux/property.h> #include <linux/regmap.h>
@@ -283,30 +284,34 @@ static u16 ina226_interval_to_reg(long interval)return FIELD_PREP (INA226_AVG_RD_MASK , avg_bits); } -static int ina2xx_get_value (struct ina2xx_data *data,u8 reg, -unsigned int regval) +static long ina2xx_get_value (struct ina2xx_data *data,u8 reg, +unsigned int regval) { -int val; +s64 val64; +long val;switch (reg) {case INA2XX_SHUNT_VOLTAGE :/* signed register */ - val = (s16 )regval >> data->config->shunt_voltage_shift; - val =DIV_ROUND_CLOSEST (val, data->config->shunt_div); + val =DIV_ROUND_CLOSEST ((s16 )regval >> data->config->shunt_voltage_shift, + data->config->shunt_div);break ;case INA2XX_BUS_VOLTAGE : - val = (regval >> data->config->bus_voltage_shift) * - data->config->bus_voltage_lsb; - val =DIV_ROUND_CLOSEST (val,1000 ); + val =DIV_ROUND_CLOSEST ((regval >> data->config->bus_voltage_shift) * + data->config->bus_voltage_lsb,1000 );break ;case INA2XX_POWER : - val = regval * data->power_lsb_uW; + val =min_t (u64, (u64 )regval * data->power_lsb_uW,LONG_MAX );break ;case INA2XX_CURRENT :/* signed register, result in mA */ - val = ((s16 )regval >> data->config->current_shift) * + val64 = (s64)((s16 )regval >> data->config->current_shift) * data->current_lsb_uA; - val =DIV_ROUND_CLOSEST (val,1000 ); +if (val64 <0 ) + val64 = -DIV_ROUND_CLOSEST_ULL (-val64,1000 ); +else + val64 =DIV_ROUND_CLOSEST_ULL (val64,1000 ); + val =clamp_val (val64,LONG_MIN ,LONG_MAX );break ;case INA2XX_CALIBRATION : val = regval;
@@ -395,27 +400,29 @@ static int ina2xx_read_init(struct device *dev, int reg, long *val)*/ static u16 ina226_alert_to_reg (struct ina2xx_data *data,int reg,long val) { +long limit; +switch (reg) {case INA2XX_SHUNT_VOLTAGE : - val =clamp_val (val,0 ,SHRT_MAX * data->config->shunt_div); - val *= data->config->shunt_div; - val <<= data->config->shunt_voltage_shift; -return clamp_val (val,0 ,SHRT_MAX ); + val =min_t (long, val,DIV_ROUND_CLOSEST (SHRT_MAX , data->config->shunt_div)); +return min_t (long, (val * data->config->shunt_div) << data->config->shunt_voltage_shift, +SHRT_MAX );case INA2XX_BUS_VOLTAGE : - val =clamp_val (val,0 ,200000 ); - val = (val *1000 ) << data->config->bus_voltage_shift; - val =DIV_ROUND_CLOSEST (val, data->config->bus_voltage_lsb); -return clamp_val (val,0 ,USHRT_MAX ); + val =min_t (long, val,130000 ); +return min_t (long, +DIV_ROUND_CLOSEST ((val *1000 ) << data->config->bus_voltage_shift, + data->config->bus_voltage_lsb), +USHRT_MAX );case INA2XX_POWER : - val =clamp_val (val,0 ,UINT_MAX - data->power_lsb_uW); - val =DIV_ROUND_CLOSEST (val, data->power_lsb_uW); -return clamp_val (val,0 ,USHRT_MAX ); + val =min_t (long, val,LONG_MAX - data->power_lsb_uW); +return min_t (long,DIV_ROUND_CLOSEST (val, data->power_lsb_uW),USHRT_MAX );case INA2XX_CURRENT : - val =clamp_val (val,INT_MIN /1000 ,INT_MAX /1000 ); + limit = (LONG_MAX - (data->current_lsb_uA /2 )) /1000 ; + val =min_t (long, val, limit);/* signed register, result in mA */ val =DIV_ROUND_CLOSEST (val *1000 , data->current_lsb_uA); - val <<= data->config->current_shift; -return clamp_val (val,SHRT_MIN ,SHRT_MAX ); + limit =SHRT_MAX >> data->config->current_shift; +return (u16)(min_t (long, val, limit) << data->config->current_shift);default :/* programmer goofed */ WARN_ON_ONCE (1 );
@@ -560,6 +567,7 @@ static int sy24655_average_power_read(struct ina2xx_data *data, u8 reg, long *vau8 template[6 ];int ret;long accumulator_24, sample_count; +u64 val64;/* 48-bit register read */ ret =i2c_smbus_read_i2c_block_data (data->client, reg,6 , template);
@@ -578,7 +586,8 @@ static int sy24655_average_power_read(struct ina2xx_data *data, u8 reg, long *vareturn 0 ; } - *val =DIV_ROUND_CLOSEST (accumulator_24, sample_count) * data->power_lsb_uW; + val64 = (u64 )DIV_ROUND_CLOSEST (accumulator_24, sample_count) * data->power_lsb_uW; + *val =min_t (u64, val64,LONG_MAX );return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 68/337 hwmon: (ltc4282) Fix reading the minimum alarm voltage
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit 00feb1cce93dab948a299b69753d99c681d45a0b ]
Coverity reports an out-of-bounds access when reading the minimum alarm voltage for the VGPIO channel. Add the missing return statement to fix the problem.
--- drivers/hwmon/ltc4282.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/hwmon/ltc4282.c +2 -2
@@ -382,8 +382,8 @@ static int ltc4282_read_in(struct ltc4282_state *st, u32 attr, long *val, channel, val);case hwmon_in_min_alarm:if (channel ==LTC4282_CHAN_VGPIO ) -ltc4282_read_alarm (st,LTC4282_ADC_ALERT_LOG , -LTC4282_GPIO_ALARM_L_MASK , val); +return ltc4282_read_alarm (st,LTC4282_ADC_ALERT_LOG , +LTC4282_GPIO_ALARM_L_MASK , val); return ltc4282_vdd_source_read_alm(st, LTC4282_VSOURCE_ALARM_L_MASK,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 69/337 hwmon: (sht3x) Fix unaligned accesses
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guenter Roeck <[email protected]>
[ Upstream commit f46d5ab43a572b84773015a76966f5da56fc1748 ]
Sashiko reports:
In sht3x_update_client(), the 16-bit temperature and humidity values are extracted from a stack-allocated byte array using be16_to_cpup(). The pointers passed to this function are calculated as buf and buf + 3. Since the difference between the two pointers is an odd number of bytes, at least one of them is guaranteed to be at an unaligned offset.
This will trigger an alignment fault on strict-alignment architectures such as ARMv5 or SPARC, resulting in a kernel panic.
Fix the problem by using get_unaligned_be16() instead of be16_to_cpup(), and put_unaligned_be16() instead of cpu_to_be16().
--- drivers/hwmon/sht3x.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/hwmon/sht3x.c +5 -4
@@ -21,6 +21,7 @@#include <linux/module.h> #include <linux/slab.h> #include <linux/jiffies.h> +#include <linux/unaligned.h> /* commands (high repeatability mode) */ static const unsigned char sht3x_cmd_measure_single_hpm[] = {0x24 ,0x00 };
@@ -279,9 +280,9 @@ static struct sht3x_data *sht3x_update_client(struct device *dev)if (ret) goto out; - val =be16_to_cpup ((__be16 *)buf); + val =get_unaligned_be16 (buf); data->temperature =sht3x_extract_temperature (val); - val =be16_to_cpup ((__be16 *)(buf +3 )); + val =get_unaligned_be16 (buf +3 ); data->humidity =sht3x_extract_humidity (val); data->last_update = jiffies; }
@@ -339,7 +340,7 @@ static int limits_update(struct sht3x_data *data)if (ret)return ret; - raw =be16_to_cpup ((__be16 *)buffer); + raw =get_unaligned_be16 (buffer); temperature =sht3x_extract_temperature ((raw &0x01ff ) <<7 ); humidity =sht3x_extract_humidity (raw &0xfe00 ); data->temperature_limits[index] = temperature;
@@ -392,7 +393,7 @@ static size_t limit_write(struct device *dev, raw = ((u32)(temperature +45000 ) *24543 ) >> (16 +7 ); raw |= ((humidity *42950 ) >>16 ) &0xfe00 ; - *((__be16 *)position) =cpu_to_be16 (raw); +put_unaligned_be16 (raw, position); position +=SHT3X_WORD_LEN ; *position = crc8(sht3x_crc8_table, position - SHT3X_WORD_LEN,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 70/337 hwmon: (lm90) Only report alarms if driver is ready
In reply to Greg Kroah-Hartman6.12-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 71/337 hwmon: (nzxt-smart2) DMA-align output buffer
In reply to Greg Kroah-Hartman6.12-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 72/337 net: do not send ICMP/NDISC Redirects when peer allocation fails
In reply to Greg Kroah-Hartman6.12-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
@@ -890,8 +890,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
@@ -627,7 +627,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
@@ -1739,6 +1739,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 73/337 hwmon: (nct6775-core) Prevent access to unsupported weight registers
In reply to Greg Kroah-Hartman6.12-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 74/337 net: bridge: mrp: fix Option TLV length in MRP_Test frames
In reply to Greg Kroah-Hartman6.12-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 75/337 forcedeth: fix UAF of txrx_stats in nv_remove
In reply to Greg Kroah-Hartman6.12-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 76/337 hwmon: (adt7470) Fix fans stuck in manual mode on I2C errors
In reply to Greg Kroah-Hartman6.12-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 77/337 hwmon: (adt7470) Fix cache updated before hardware write on I2C error
In reply to Greg Kroah-Hartman6.12-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 :
@@ -831,9 +833,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:
@@ -847,10 +850,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 78/337 hwmon: (adt7470) Fix busy-loop and I2C flooding in update thread
In reply to Greg Kroah-Hartman6.12-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 79/337 hwmon: (adt7470) Fix temperature alarm logic in hwmon_temp_read()
In reply to Greg Kroah-Hartman6.12-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 80/337 hwmon: (adt7470) Fix swapped PWM3 and PWM4 auto mode masks
In reply to Greg Kroah-Hartman6.12-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 81/337 hwmon: (adt7470) Use cached PWM frequency value
In reply to Greg Kroah-Hartman6.12-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 };
@@ -796,7 +797,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 ;
@@ -809,12 +810,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 ;
@@ -832,6 +835,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);
@@ -1285,6 +1292,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 );
@@ -1309,6 +1317,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 82/337 hwmon: (adt7470) Fix divide-by-zero TOCTOU crash in fan speed read
In reply to Greg Kroah-Hartman6.12-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 83/337 hwmon: (adt7470) Fix PWM auto temp state array and bounds check
In reply to Greg Kroah-Hartman6.12-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
@@ -1049,8 +1049,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 ;
@@ -1061,6 +1063,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 84/337 rtase: fix double free of multi-frag skb on DMA map failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yun Lu <[email protected]>
[ Upstream commit 6fb7b769d6ed6d1d2e02af4a80e57a2477f35086 ]
In rtase_start_xmit(), when the head buffer DMA mapping fails after rtase_xmit_frags() has mapped all fragments, the error path clears the fragment descriptors with rtase_tx_clear_range(), which frees the skb through the last-frag slot and accounts tx_dropped. Control then falls through to the common error label, which frees the same skb a second time and counts it again.
Return right after clearing the fragments when the skb owns frags; the no-frag case still drops through and frees the head skb once.
--- drivers/net/ethernet/realtek/rtase/rtase_main.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ethernet/realtek/rtase/rtase_main.c +3 -0
@@ -1609,6 +1609,9 @@ static netdev_tx_t rtase_start_xmit(struct sk_buff *skb, err_dma_1: ring->skbuff[entry] =NULL ;rtase_tx_clear_range (ring, ring->cur_idx +1 , frags); +if (frags) +/* the frags were cleared above, along with the skb */ +return NETDEV_TX_OK ; err_dma_0: tp->stats.tx_dropped++;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 85/337 powerpc/boot: Fix simpleboot CPU node lookup check
In reply to Greg Kroah-Hartman6.12-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 86/337 powerpc/boot: Fix treeboot-currituck CPU node lookup check
In reply to Greg Kroah-Hartman6.12-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 87/337 powerpc/boot: Fix treeboot-akebono CPU node lookup check
In reply to Greg Kroah-Hartman6.12-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 88/337 net: udp_tunnel: fix memory leak in udp_tunnel_nic_unregister()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 080695e6f005e2396f1207fd69d24c442cb230c6 ]
syzbot reported a memory leak [1] in the UDP tunnel NIC offload code.
When device registration fails (e.g. in register_netdevice()), netdev core unwinds by sending a single NETDEV_UNREGISTER notification. If work was queued during NETDEV_REGISTER (utn->work_pending is set), udp_tunnel_nic_unregister() returns early:
if (utn->work_pending) return;
Because failed registrations do not enter netdev_wait_allrefs_any(), no subsequent NETDEV_UNREGISTER rebroadcast will ever occur. As a result, the struct udp_tunnel_nic allocated in udp_tunnel_nic_alloc() is leaked permanently.
Fix this by removing the early return. Instead, synchronously cancel any pending work with cancel_delayed_work_sync() before freeing @utn.
To be able to call cancel_delayed_work_sync() while holding RTNL (the work also needs RTNL), switch udp_tunnel_nic_device_sync_work() to rtnl_trylock(). If RTNL is contended, requeue the work with a 1 jiffy delay (via queue_delayed_work()) to prevent high CPU contention while waiting for RTNL lock.
The utn->work_pending bookkeeping is no longer needed and is removed, as the workqueue core already tracks the pending/running state of the work.
[1]
BUG: memory leak
unreferenced object 0xffff888127d5f840 (size 96):
comm "syz-executor", pid 5806, jiffies 4294942188
backtrace (crc 99fdb6c8):
__kmalloc_noprof+0x3bf/0x550
udp_tunnel_nic_alloc net/ipv4/udp_tunnel_nic.c:756 [inline]
udp_tunnel_nic_register net/ipv4/udp_tunnel_nic.c:833 [inline]
udp_tunnel_nic_netdevice_event+0x804/0xab0 net/ipv4/udp_tunnel_nic.c:931
notifier_call_chain+0x59/0x160 kernel/notifier.c:85
call_netdevice_notifiers_info+0x7d/0xb0 net/core/dev.c:2250
register_netdevice+0xc10/0xeb0 net/core/dev.c:11478--- net/ipv4/udp_tunnel_nic.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-)
net/ipv4/udp_tunnel_nic.c +17 -15
@@ -32,13 +32,12 @@ struct udp_tunnel_nic_table_entry {* @lock: protects all fields * @need_sync: at least one port start changed * @need_replay: space was freed, we need a replay of all ports -* @work_pending: @work is currently scheduled * @n_tables: number of tables under @entries * @missed: bitmap of tables which overflown * @entries: table of tables of ports currently offloaded */ struct udp_tunnel_nic { -struct work_struct work; +struct delayed_work work;struct net_device *dev;
@@ -46,7 +45,6 @@ struct udp_tunnel_nic { u8 need_sync:1; u8 need_replay:1; - u8 work_pending:1;unsigned int n_tables;unsigned long missed;
@@ -301,11 +299,10 @@ __udp_tunnel_nic_device_sync(struct net_device *dev, struct udp_tunnel_nic *utn)static void udp_tunnel_nic_device_sync (struct net_device *dev,struct udp_tunnel_nic *utn) { -if (!utn->need_sync || utn->work_pending) +if (!utn->need_sync)return ; -queue_work (udp_tunnel_nic_workqueue, &utn->work); - utn->work_pending =1 ; +queue_delayed_work (udp_tunnel_nic_workqueue, &utn->work,0 ); } static bool
@@ -731,12 +728,17 @@ udp_tunnel_nic_replay(struct net_device *dev, struct udp_tunnel_nic *utn)static void udp_tunnel_nic_device_sync_work (struct work_struct *work) {struct udp_tunnel_nic *utn = - container_of(work, struct udp_tunnel_nic, work); + container_of(work, struct udp_tunnel_nic, work.work); -rtnl_lock (); +/* We cannot block on RTNL here, otherwise we would deadlock with +* udp_tunnel_nic_unregister() calling cancel_delayed_work_sync() +* while holding RTNL. Requeue with 1 jiffy delay if RTNL is contended. +*/ +if (!rtnl_trylock ()) { +queue_delayed_work (udp_tunnel_nic_workqueue, &utn->work,1 ); +return ; + }mutex_lock (&utn->lock); - - utn->work_pending =0 ;__udp_tunnel_nic_device_sync (utn->dev, utn);if (utn->need_replay)
@@ -757,7 +759,7 @@ udp_tunnel_nic_alloc(const struct udp_tunnel_nic_info *info,if (!utn)return NULL ; utn->n_tables = n_tables; -INIT_WORK (&utn->work, udp_tunnel_nic_device_sync_work); +INIT_DELAYED_WORK (&utn->work, udp_tunnel_nic_device_sync_work);mutex_init (&utn->lock);for (i =0 ; i < n_tables; i++) {
@@ -901,11 +903,11 @@ udp_tunnel_nic_unregister(struct net_device *dev, struct udp_tunnel_nic *utn)udp_tunnel_nic_flush (dev, utn);udp_tunnel_nic_unlock (dev); -/* Wait for the work to be done using the state, netdev core will -* retry unregister until we give up our reference on this device. +/* Make sure no work is running or queued before freeing @utn. +* The work handler uses rtnl_trylock(), so it will not deadlock +* against the RTNL we are holding here. */ -if (utn->work_pending) -return ; +cancel_delayed_work_sync (&utn->work);udp_tunnel_nic_free (utn); release_dev:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 89/337 wifi: mac80211: validate individual TWT params before driver setup
In reply to Greg Kroah-Hartman6.12-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
@@ -101,6 +101,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 90/337 net: ethernet: mtk_eth_soc: support named IRQs
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frank Wunderlich <[email protected]>
[ Upstream commit ee85b483fefbbebe1e6e61c53169f864bbdd8f13 ]
Add named interrupts and keep index based fallback for existing devicetrees.
Currently only rx and tx IRQs are defined to be used with mt7988, but later extended with RSS/LRO support.
Stable-dep-of: e095f249e220 ("net: ethernet: mtk_eth_soc: pass eth to mtk_handle_irq_rx in poll_controller")
--- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 46 ++++++++++++++++----- 1 file changed, 35 insertions(+), 11 deletions(-)
drivers/net/ethernet/mediatek/mtk_eth_soc.c +35 -11
@@ -3210,6 +3210,37 @@ static void mtk_tx_timeout(struct net_device *dev, unsigned int txqueue)schedule_work (ð->pending_work); } +static int mtk_get_irqs (struct platform_device *pdev,struct mtk_eth *eth) +{ +int i; + +/* future SoCs beginning with MT7988 should use named IRQs in dts */ + eth->irq[1 ] =platform_get_irq_byname (pdev,"fe1" ); + eth->irq[2 ] =platform_get_irq_byname (pdev,"fe2" ); +if (eth->irq[1 ] >=0 && eth->irq[2 ] >=0 ) +return 0 ; + +/* legacy way: +* On MTK_SHARED_INT SoCs (MT7621 + MT7628) the first IRQ is taken +* from devicetree and used for both RX and TX - it is shared. +* On SoCs with non-shared IRQs the first entry is not used, +* the second is for TX, and the third is for RX. +*/ +for (i =0 ; i <3 ; i++) { +if (MTK_HAS_CAPS (eth->soc->caps,MTK_SHARED_INT ) && i >0 ) + eth->irq[i] = eth->irq[0 ]; +else + eth->irq[i] =platform_get_irq (pdev, i); + +if (eth->irq[i] <0 ) { +dev_err (&pdev->dev,"no IRQ%d resource found\n" , i); +return -ENXIO ; + } + } + +return 0 ; +} +static irqreturn_t mtk_handle_irq_rx (int irq,void *_eth) {struct mtk_eth *eth = _eth;
@@ -4986,17 +5017,10 @@ static int mtk_probe(struct platform_device *pdev) } } -for (i =0 ; i <3 ; i++) { -if (MTK_HAS_CAPS (eth->soc->caps,MTK_SHARED_INT ) && i >0 ) - eth->irq[i] = eth->irq[0 ]; -else - eth->irq[i] =platform_get_irq (pdev, i); -if (eth->irq[i] <0 ) { -dev_err (&pdev->dev,"no IRQ%d resource found\n" , i); - err = -ENXIO ; - goto err_wed_exit; - } - } + err =mtk_get_irqs (pdev, eth); +if (err) + goto err_wed_exit; +for (i =0 ; i <ARRAY_SIZE (eth->clks); i++) { eth->clks[i] =devm_clk_get (eth->dev, mtk_clks_source_name[i]);
Signature · 1 line
2.53.0
Re: [PATCH 6.12 090/337] net: ethernet: mtk_eth_soc: support named IRQs
Hi, this patch caused the following errors on non MT7988 SoCs:
[ 7.071127] mtk_soc_eth 1e100000.ethernet: error -ENXIO: IRQ fe1 not found [ 7.078022] mtk_soc_eth 1e100000.ethernet: error -ENXIO: IRQ fe2 not found
Please backport these patches to fix it:070e98dd4e26279280e15db8f37077a001ca1b4c ("net: ethernet: mtk_eth_soc: only use legacy mode on missing IRQ name") e81d36d48880ab3f2b351ce3df799acaa8b11c4f ("net: ethernet: mtk_eth_soc: improve support for named interrupts")
Regards,
Shiji Yang
Greg KH
maintainerRe: [PATCH 6.12 090/337] net: ethernet: mtk_eth_soc: support named IRQs
Quoted 7 lines · Shiji Yang
Hi, this patch caused the following errors on non MT7988 SoCs:
[ 7.071127] mtk_soc_eth 1e100000.ethernet: error -ENXIO: IRQ fe1 not found [ 7.078022] mtk_soc_eth 1e100000.ethernet: error -ENXIO: IRQ fe2 not foundPlease backport these patches to fix it:
070e98dd4e26279280e15db8f37077a001ca1b4c("net: ethernet:mtk_eth_soc: only use legacy mode on missing IRQ name")e81d36d48880ab3f2b351ce3df799acaa8b11c4f("net: ethernet:mtk_eth_soc: improve support for named interrupts")
Why did neither of these have Fixes: tags?
Anyway, I'll go queue both of these up now, thanks.
greg k-h
Greg Kroah-Hartman
maintainerPATCH 91/337 net: ethernet: mtk_eth_soc: add consts for irq index
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frank Wunderlich <[email protected]>
[ Upstream commit 4981901009923c8889a635a928d55b8f7f8b31ec ]
Use consts instead of fixed integers for accessing IRQ array.
Stable-dep-of: e095f249e220 ("net: ethernet: mtk_eth_soc: pass eth to mtk_handle_irq_rx in poll_controller")
--- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 22 ++++++++++----------- drivers/net/ethernet/mediatek/mtk_eth_soc.h | 7 ++++++- 2 files changed, 17 insertions(+), 12 deletions(-)
drivers/net/ethernet/mediatek/mtk_eth_soc.c +11 -11
@@ -3215,9 +3215,9 @@ static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth)int i;/* future SoCs beginning with MT7988 should use named IRQs in dts */ - eth->irq[1 ] =platform_get_irq_byname (pdev,"fe1" ); - eth->irq[2 ] =platform_get_irq_byname (pdev,"fe2" ); -if (eth->irq[1 ] >=0 && eth->irq[2 ] >=0 ) + eth->irq[MTK_FE_IRQ_TX ] =platform_get_irq_byname (pdev,"fe1" ); + eth->irq[MTK_FE_IRQ_RX ] =platform_get_irq_byname (pdev,"fe2" ); +if (eth->irq[MTK_FE_IRQ_TX ] >=0 && eth->irq[MTK_FE_IRQ_RX ] >=0 )return 0 ;/* legacy way:
@@ -3226,9 +3226,9 @@ static int mtk_get_irqs(struct platform_device *pdev, struct mtk_eth *eth)* On SoCs with non-shared IRQs the first entry is not used, * the second is for TX, and the third is for RX. */ -for (i =0 ; i <3 ; i++) { +for (i =0 ; i <MTK_FE_IRQ_NUM ; i++) {if (MTK_HAS_CAPS (eth->soc->caps,MTK_SHARED_INT ) && i >0 ) - eth->irq[i] = eth->irq[0 ]; + eth->irq[i] = eth->irq[MTK_FE_IRQ_SHARED ];else eth->irq[i] =platform_get_irq (pdev, i);
@@ -3294,7 +3294,7 @@ static void mtk_poll_controller(struct net_device *dev)mtk_tx_irq_disable (eth,MTK_TX_DONE_INT );mtk_rx_irq_disable (eth, eth->soc->rx.irq_done_mask); -mtk_handle_irq_rx (eth->irq[2 ], dev); +mtk_handle_irq_rx (eth->irq[MTK_FE_IRQ_RX ], dev);mtk_tx_irq_enable (eth,MTK_TX_DONE_INT );mtk_rx_irq_enable (eth, eth->soc->rx.irq_done_mask); }
@@ -4787,7 +4787,7 @@ static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np) eth->netdev[id]->features |= eth->soc->hw_features; eth->netdev[id]->ethtool_ops = &mtk_ethtool_ops; - eth->netdev[id]->irq = eth->irq[0 ]; + eth->netdev[id]->irq = eth->irq[MTK_FE_IRQ_SHARED ]; eth->netdev[id]->dev.of_node = np;if (MTK_HAS_CAPS (eth->soc->caps,MTK_SOC_MT7628 ))
@@ -5064,17 +5064,17 @@ static int mtk_probe(struct platform_device *pdev) }if (MTK_HAS_CAPS (eth->soc->caps,MTK_SHARED_INT )) { - err =devm_request_irq (eth->dev, eth->irq[0 ], + err =devm_request_irq (eth->dev, eth->irq[MTK_FE_IRQ_SHARED ], mtk_handle_irq,0 ,dev_name (eth->dev), eth); }else { - err =devm_request_irq (eth->dev, eth->irq[1 ], + err =devm_request_irq (eth->dev, eth->irq[MTK_FE_IRQ_TX ], mtk_handle_irq_tx,0 ,dev_name (eth->dev), eth);if (err) goto err_free_dev; - err =devm_request_irq (eth->dev, eth->irq[2 ], + err =devm_request_irq (eth->dev, eth->irq[MTK_FE_IRQ_RX ], mtk_handle_irq_rx,0 ,dev_name (eth->dev), eth); }
@@ -5120,7 +5120,7 @@ static int mtk_probe(struct platform_device *pdev) }else netif_info (eth, probe, eth->netdev[i],"mediatek frame engine at 0x%08lx, irq %d\n" , - eth->netdev[i]->base_addr, eth->irq[0 ]); + eth->netdev[i]->base_addr, eth->irq[MTK_FE_IRQ_SHARED ]); }/* we run 2 devices on the same DMA ring so we need a dummy device
drivers/net/ethernet/mediatek/mtk_eth_soc.h +6 -1
@@ -611,6 +611,11 @@#define MTK_MAC_FSM (x) (0x1010C + ((x) * 0x100)) +#define MTK_FE_IRQ_SHARED 0 +#define MTK_FE_IRQ_TX 1 +#define MTK_FE_IRQ_RX 2 +#define MTK_FE_IRQ_NUM (MTK_FE_IRQ_RX + 1) +struct mtk_rx_dma {unsigned int rxd1;unsigned int rxd2;
@@ -1248,7 +1253,7 @@ struct mtk_eth {struct net_device *dummy_dev;struct net_device *netdev[MTK_MAX_DEVS ];struct mtk_mac *mac[MTK_MAX_DEVS ]; -int irq[3 ]; +int irq[MTK_FE_IRQ_NUM ];u32 msg_enable;unsigned long sysclk;struct regmap *ethsys;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 92/337 net: ethernet: mtk_eth_soc: pass eth to mtk_handle_irq_rx in poll_controller
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenguang Zhao <[email protected]>
[ Upstream commit e095f249e2209674f6366f6db0383a2b96e19239 ]
mtk_handle_irq_rx expects a struct mtk_eth * (matching the request_irq cookie), but mtk_poll_controller incorrectly passed the net_device *. Calling ndo_poll_controller with CONFIG_NET_POLL_CONTROLLER enabled would then crash.
--- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/mediatek/mtk_eth_soc.c +1 -1
@@ -3294,7 +3294,7 @@ static void mtk_poll_controller(struct net_device *dev)mtk_tx_irq_disable (eth,MTK_TX_DONE_INT );mtk_rx_irq_disable (eth, eth->soc->rx.irq_done_mask); -mtk_handle_irq_rx (eth->irq[MTK_FE_IRQ_RX ], dev); +mtk_handle_irq_rx (eth->irq[MTK_FE_IRQ_RX ], eth);mtk_tx_irq_enable (eth,MTK_TX_DONE_INT );mtk_rx_irq_enable (eth, eth->soc->rx.irq_done_mask); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 93/337 hwmon: (pmbus) Fix return value from pmbus_update_byte_data()
In reply to Greg Kroah-Hartman6.12-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
@@ -508,7 +508,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 94/337 idpf: adjust TxQ ring count minimum
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joshua Hay <[email protected]>
[ Upstream commit bef152db47debcd14cbacefc5767f6f026c4bc89 ]
Set the TxQ ring count minimum to 128 descriptors. Any lower than this, and the queue will stall and trigger Tx timeouts in flow based scheduling mode. This is because next_to_clean might never be updated.
In flow based scheduling mode, next_to_clean is only updated after a descriptor completion is processed, i.e. after the RE bit is set in the last descriptor of a Tx packet. This will never happen with a ring size of 64 and an IDPF_TX_SPLITQ_RE_MIN_GAP of 64. No matter what the value of last_re is initialized/set to, the calculated gap will be at most 63 and never trigger the RE bit.
Even a ring size of 96 does not solve this. Because of how infrequent next_to_clean is updated and how small the ring is, IDPF_DESC_UNUSED will be much smaller on average. This increases the chance the queue will be stopped because a multi-descriptor packet, e.g. a large LSO packet, does not see enough resources on the ring. In this case, the queue will trigger the stop logic. The queue permanently stalls because there is no chance for a descriptor completion to update next_to_clean since it is dependent on a packet being sent.
--- drivers/net/ethernet/intel/idpf/idpf_txrx.c | 5 +---- drivers/net/ethernet/intel/idpf/idpf_txrx.h | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-)
drivers/net/ethernet/intel/idpf/idpf_txrx.c +1 -4
@@ -2507,10 +2507,7 @@ static netdev_tx_t idpf_tx_splitq_frame(struct sk_buff *skb, tx_params.dtype =IDPF_TX_DESC_DTYPE_FLEX_FLOW_SCHE ; tx_params.eop_cmd =IDPF_TXD_FLEX_FLOW_CMD_EOP ; -/* Set the RE bit to periodically "clean" the descriptor ring. -* MIN_GAP is set to MIN_RING size to ensure it will be set at -* least once each time around the ring. -*/ +/* Set the RE bit periodically to "clean" the descriptor ring */ if (idpf_tx_splitq_need_re (tx_q)) { tx_params.eop_cmd |=IDPF_TXD_FLEX_FLOW_CMD_RE ; tx_q->txq_grp->num_completions_pending++;
drivers/net/ethernet/intel/idpf/idpf_txrx.h +1 -1
@@ -19,7 +19,7 @@/* Mailbox Queue */ #define IDPF_MAX_MBXQ 1 -#define IDPF_MIN_TXQ_DESC 64 +#define IDPF_MIN_TXQ_DESC 128#define IDPF_MIN_RXQ_DESC 64#define IDPF_MIN_TXQ_COMPLQ_DESC 256#define IDPF_MAX_QIDS 256
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 95/337 idpf: Fix mailbox IRQ name leak on request failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
[ Upstream commit 9bff30482c10f70d9e56c0633a6616e07140e217 ]
idpf_mb_intr_req_irq() allocates the mailbox IRQ name before calling request_irq(). On success, the name is released later through kfree(free_irq()), but request_irq() failure returns without freeing it.
Free the allocated name on the request_irq() failure path.
--- drivers/net/ethernet/intel/idpf/idpf_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/intel/idpf/idpf_lib.c +1 -1
@@ -134,7 +134,7 @@ static int idpf_mb_intr_req_irq(struct idpf_adapter *adapter)if (err) {dev_err (&adapter->pdev->dev,"IRQ request for mailbox failed, error: %d\n" , err); - +kfree (name);return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 96/337 Bluetooth: ISO: clear iso_data always when detaching conn from hcon
In reply to Greg Kroah-Hartman6.12-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
@@ -811,6 +811,7 @@ static void iso_sock_disconn(struct sock *sk) sk->sk_state =BT_DISCONN ;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 97/337 Bluetooth: L2CAP: fix UAF in l2cap_le_connect_rsp
In reply to Greg Kroah-Hartman6.12-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
@@ -4796,6 +4796,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);
@@ -4841,6 +4845,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 98/337 Bluetooth: ISO: fix timeout vs sync_timeout typo in check_bcast_qos
In reply to Greg Kroah-Hartman6.12-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
@@ -1636,7 +1636,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 99/337 Bluetooth: ISO: validate sockaddr_iso first in iso_sock_rebind_bis()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit 4e20192d46a685d73e590a60a4a2419a0a8afcbf ]
iso_sock_rebind_bis() updates socket iso_pi(sk)->bc_num_bis before validating the BIS values, so it's possible to end up with bc_num_bis inconsistent.
Assign to iso_pi(sk)->bc_num_bis only after validation.
--- net/bluetooth/iso.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/bluetooth/iso.c +3 -3
@@ -1014,15 +1014,15 @@ static int iso_sock_bind_pa_sk(struct sock *sk, struct sockaddr_iso *sa, goto done; } -iso_pi (sk)->bc_num_bis = sa->iso_bc->bc_num_bis; - -for (int i =0 ; i <iso_pi (sk)->bc_num_bis; i++) +for (int i =0 ; i < sa->iso_bc->bc_num_bis; i++)if (sa->iso_bc->bc_bis[i] <0x01 || sa->iso_bc->bc_bis[i] >0x1f ) { err = -EINVAL ; goto done; } +iso_pi (sk)->bc_num_bis = sa->iso_bc->bc_num_bis; +memcpy (iso_pi (sk)->bc_bis, sa->iso_bc->bc_bis,iso_pi (sk)->bc_num_bis);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 100/337 Bluetooth: ISO: fix leaking sk after socket release
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit ce57442a379212fe3fda59c9437ee8217eceb5b1 ]
iso_sock_kill() tests !sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket || sock_flag(sk, SOCK_DEAD) for early return, but this is always true since sock_orphan(sk) sets SOCK_DEAD, so the sk reference released by socket always leaks, iso_sock_destruct is never called.
The socket reference also leaks when __iso_sock_close() does not set SOCK_ZAPPED, since iso_conn_del() does not call iso_sock_kill() after zapping.
Fix by replacing SOCK_DEAD by BT_SK_KILLED flag that is not used for something else, and lock_sock to ensure iso_sock_kill() puts sk only after socket release only once. Release and iso_conn_del may run concurrently. Call iso_sock_kill() from iso_conn_del() to clean sk up after zapping.
Remove call to iso_sock_kill() from iso_sock_close(), as it's generally no-op there.
--- net/bluetooth/iso.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
net/bluetooth/iso.c +18 -2
@@ -55,6 +55,7 @@ static void iso_sock_kill(struct sock *sk);enum {BT_SK_BIG_SYNC ,BT_SK_PA_SYNC , +BT_SK_KILLED , };struct iso_pinfo {
@@ -286,6 +287,7 @@ static void iso_conn_del(struct hci_conn *hcon, int err)iso_sock_clear_timer (sk);iso_chan_del (sk, err);release_sock (sk); +iso_sock_kill (sk);sock_put (sk); }
@@ -764,9 +766,13 @@ static void iso_sock_cleanup_listen(struct sock *parent)*/ static void iso_sock_kill (struct sock *sk) { +lock_sock (sk); +if (!sock_flag (sk,SOCK_ZAPPED ) || sk->sk_socket || -sock_flag (sk,SOCK_DEAD )) +test_bit (BT_SK_KILLED , &iso_pi (sk)->flags)) { +release_sock (sk);return ; + }BT_DBG ("sk %p state %d" , sk, sk->sk_state);
@@ -780,6 +786,9 @@ static void iso_sock_kill(struct sock *sk)/* Kill poor orphan */ bt_sock_unlink (&iso_sk_list, sk);sock_set_flag (sk,SOCK_DEAD ); +set_bit (BT_SK_KILLED , &iso_pi (sk)->flags); + +release_sock (sk);sock_put (sk); }
@@ -859,7 +868,6 @@ static void iso_sock_close(struct sock *sk)iso_sock_clear_timer (sk);__iso_sock_close (sk);release_sock (sk); -iso_sock_kill (sk); }static void iso_sock_init (struct sock *sk,struct sock *parent)
@@ -1867,8 +1875,16 @@ static int iso_sock_release(struct socket *sock)release_sock (sk); } +/* Make sure sk is valid even if iso_conn_del() is concurrent */ +sock_hold (sk); + +lock_sock (sk);sock_orphan (sk); +release_sock (sk); +iso_sock_kill (sk); + +sock_put (sk);return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 101/337 Bluetooth: ISO: avoid deadlocks in iso_sock_timeout
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit 200fa1629c57a3ca2b03d3ca63fd3a9bfd910c43 ]
iso_sock_timeout() takes lock_sock, so sync disabling the timer while holding that lock may deadlock.
iso_sock_timeout() may also run concurrently with iso_conn_del(), which leads to UAF
[Task 1] [Task hdev->workqueue]
iso_sock_timeout iso_conn_del
iso_conn_hold_unless_zero iso_chan_del
`------------> iso_conn_put
caller frees hcon
iso_conn_put
iso_conn_free
conn->hcon->iso_data = NULL; /* UAF */Fix the deadlock by removing the disable from the lock_sock sections. Move the timer from iso_conn to iso_pinfo to decouple it from iso_conn which may need to be freed in lock_sock section. Convert some of the clear_timer to disable_timer.
--- net/bluetooth/iso.c | 60 ++++++++++++++++++++++----------------------- 1 file changed, 29 insertions(+), 31 deletions(-)
net/bluetooth/iso.c +29 -31
@@ -30,8 +30,6 @@ struct iso_conn {spinlock_t lock;struct sock *sk; -struct delayed_work timeout_work; -struct sk_buff *rx_skb;__u32 rx_len;__u16 tx_sn;
@@ -74,6 +72,7 @@ struct iso_pinfo {__u8 base_len;__u8 base[BASE_MAX_LENGTH ];struct iso_conn *conn; +struct delayed_work timeout_work; };static struct bt_iso_qos default_qos;
@@ -109,9 +108,6 @@ static void iso_conn_free(struct kref *ref)hci_conn_drop (conn->hcon); } -/* Ensure no more work items will run since hci_conn has been dropped */ -disable_delayed_work_sync (&conn->timeout_work); -kfree_skb (conn->rx_skb);kfree (conn);
@@ -152,48 +148,45 @@ static struct sock *iso_sock_hold(struct iso_conn *conn)static void iso_sock_timeout (struct work_struct *work) { - struct iso_conn *conn = container_of(work, struct iso_conn, - timeout_work.work); -struct sock *sk; - - conn =iso_conn_hold_unless_zero (conn); -if (!conn) -return ; - -iso_conn_lock (conn); - sk =iso_sock_hold (conn); -iso_conn_unlock (conn); -iso_conn_put (conn); - -if (!sk) -return ; + struct iso_pinfo *pi = container_of(work, struct iso_pinfo, + timeout_work.work); +struct sock *sk = &pi->bt.sk;BT_DBG ("sock %p state %d" , sk, sk->sk_state);lock_sock (sk); - sk->sk_err =ETIMEDOUT ; - sk->sk_state_change (sk); +if (!sock_flag (sk,SOCK_ZAPPED )) { + sk->sk_err =ETIMEDOUT ; + sk->sk_state_change (sk); + }release_sock (sk); -sock_put (sk); }static void iso_sock_set_timer (struct sock *sk,long timeout) { +lockdep_assert (lockdep_sock_is_held (sk)); + +cancel_delayed_work (&iso_pi (sk)->timeout_work); +if (!iso_pi (sk)->conn)return ;BT_DBG ("sock %p state %d timeout %ld" , sk, sk->sk_state, timeout); -cancel_delayed_work (&iso_pi (sk)->conn->timeout_work); -schedule_delayed_work (&iso_pi (sk)->conn->timeout_work, timeout); +schedule_delayed_work (&iso_pi (sk)->timeout_work, timeout); }static void iso_sock_clear_timer (struct sock *sk) { -if (!iso_pi (sk)->conn) -return ; +BT_DBG ("sock %p state %d" , sk, sk->sk_state); +cancel_delayed_work (&iso_pi (sk)->timeout_work); +} + +static void iso_sock_disable_timer (struct sock *sk) +{ +lockdep_assert (!lockdep_sock_is_held (sk));BT_DBG ("sock %p state %d" , sk, sk->sk_state); -cancel_delayed_work (&iso_pi (sk)->conn->timeout_work); +disable_delayed_work_sync (&iso_pi (sk)->timeout_work); }/* ---- ISO connections ---- */
@@ -218,7 +211,6 @@ static struct iso_conn *iso_conn_add(struct hci_conn *hcon)kref_init (&conn->ref);spin_lock_init (&conn->lock); -INIT_DELAYED_WORK (&conn->timeout_work, iso_sock_timeout); hcon->iso_data = conn; conn->hcon = hcon;
@@ -283,8 +275,9 @@ static void iso_conn_del(struct hci_conn *hcon, int err)return ; } +iso_sock_disable_timer (sk); +lock_sock (sk); -iso_sock_clear_timer (sk);iso_chan_del (sk, err);release_sock (sk);iso_sock_kill (sk);
@@ -766,6 +759,8 @@ static void iso_sock_cleanup_listen(struct sock *parent)*/ static void iso_sock_kill (struct sock *sk) { +iso_sock_disable_timer (sk); +lock_sock (sk); if (!sock_flag(sk, SOCK_ZAPPED) || sk->sk_socket ||
@@ -864,8 +859,9 @@ static void __iso_sock_close(struct sock *sk)/* Must be called on unlocked socket. */ static void iso_sock_close (struct sock *sk) { +iso_sock_disable_timer (sk); +lock_sock (sk); -iso_sock_clear_timer (sk);__iso_sock_close (sk);release_sock (sk); }
@@ -934,6 +930,8 @@ static struct sock *iso_sock_alloc(struct net *net, struct socket *sock,iso_pi (sk)->qos = default_qos;iso_pi (sk)->sync_handle =-1 ; +INIT_DELAYED_WORK (&iso_pi (sk)->timeout_work, iso_sock_timeout); +bt_sock_link (&iso_sk_list, sk);return sk; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 102/337 Bluetooth: btintel: Validate length before parsing diagnostics TLV
In reply to Greg Kroah-Hartman6.12-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
@@ -3335,6 +3335,9 @@ 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 103/337 Bluetooth: hci_sync: make hci_cmd_sync_run_once return -EEXIST if exists
In reply to Greg Kroah-Hartman6.12-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
@@ -2928,6 +2928,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.
@@ -2949,5 +2950,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
@@ -825,7 +825,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 104/337 Bluetooth: hci_conn: hold conn reference in abort_conn_sync()
In reply to Greg Kroah-Hartman6.12-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
@@ -2925,6 +2925,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;
@@ -2950,6 +2957,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 105/337 Bluetooth: hci_sync: fix hci_conn_del() use in hci_le_create_conn_sync
In reply to Greg Kroah-Hartman6.12-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
@@ -6593,7 +6593,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 106/337 Bluetooth: hci_sync: remove unnecessary hci_conn_get in create_conn_sync
In reply to Greg Kroah-Hartman6.12-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
@@ -6577,11 +6577,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 ;
@@ -6596,7 +6591,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 ; }
@@ -6690,7 +6684,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; }
@@ -6965,11 +6958,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. */
@@ -6981,7 +6969,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
Re: [PATCH 6.12 106/337] Bluetooth: hci_sync: remove unnecessary hci_conn_get in create_conn_sync
Hi Greg/Sasha
Quoted 6 lines · Greg Kroah-Hartman
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
Quoted 9 lines
[ 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_synctask, so remove these extraget()+put()as they are not needed.
I have run an AI assisted backport review and it spotted an issue; I checked 6.12.y tree and the prerequisite change is missing.
Upstream first changed the callers to queue a held reference:
err = hci_cmd_sync_queue_once(hdev, hci_acl_create_conn_sync,
hci_conn_get(conn), hci_acl_create_conn_sync_complete); if (err) hci_conn_put(conn);
The posted 6.12.y state still queues the raw pointer:
return hci_cmd_sync_queue_once(hdev, hci_acl_create_conn_sync, conn,
NULL);
This backport nevertheless removes the worker-side get/put pairs. That leaves the queued work without a reference if connection deletion races it. I think 6.12.y misses commit: 2f5d635ad5906 ("Bluetooth:hci_sync: hold conn in hci_connect_acl/le_sync() callbacks"); I think we have to either queue this prerequisite or drop this, thoughts ?
Also this is part of the series: https://lore.kernel.org/all/178517880663.1372023.9123649060094265539.git-patchwork-notify@kernel.org/
thanks,
Harshit
Quoted 27 lines
Fixes 12917f591cea ("Bluetooth: hci_conn: Fix null ptr deref in hci_abort_conn()")Signed-off-by Pauli Virtanen <[email protected]>Signed-off-by Luiz Augusto von Dentz <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- net/bluetooth/hci_sync.c | 13 ------------- 1 file changed, 13 deletions(-)net/bluetooth/hci_sync.c +0
-5@@ -6577,11 +6577,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 ;@@ -6596,7 +6591,6 @@ static int hci_le_create_conn_sync(struct hci_dev *hdev, void *data) conn->state =BT_OPEN ; hci_abort_conn_sync(hdev, conn,
Sasha Levin
maintainerRe: [PATCH 6.12 106/337] Bluetooth: hci_sync: remove unnecessary hci_conn_get in create_conn_sync
Quoted 5 lines · Harshit Mogalapalli
This backport nevertheless removes the worker-side get/put pairs. That leaves the queued work without a reference if connection deletion races it. I think 6.12.y misses commit:
2f5d635ad5906("Bluetooth:hci_sync: hold conn in hci_connect_acl/le_sync() callbacks"); I think we have to either queue this prerequisite or drop this, thoughts ?
Good catch, thank you. The same problem is in 6.18.y and 6.6.y, not just 6.12.y. I've dropped it from the 6.18, 6.12 and 6.6 queues.
Signature · 2 lines
Thanks, Sasha
Greg Kroah-Hartman
maintainerPATCH 107/337 net: phylink: put link_gpio if phylink_create fails
In reply to Greg Kroah-Hartman6.12-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
@@ -1728,8 +1728,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;
@@ -1753,28 +1753,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 108/337 scsi: target: iblock: Fix wrong PR ops NULL check for PREEMPT/RELEASE
In reply to Greg Kroah-Hartman6.12-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
@@ -891,7 +891,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 ; }
@@ -901,8 +901,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 109/337 scsi: ufs: core: Cancel RTC work in active-active suspend
In reply to Greg Kroah-Hartman6.12-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
@@ -9761,6 +9761,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; }
@@ -9970,10 +9971,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 110/337 scsi: zfcp: Fix memory leak during adapter release by destroying gid_pn_req
In reply to Greg Kroah-Hartman6.12-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 111/337 scsi: target: Clear cmd_cnt when initial counter enrollment fails
In reply to Greg Kroah-Hartman6.12-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
@@ -1691,6 +1691,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);
@@ -1720,7 +1721,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);
@@ -1996,8 +2001,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;
@@ -2005,6 +2012,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 112/337 net: sxgbe: free TX rings on RX allocation failure
In reply to Greg Kroah-Hartman6.12-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
@@ -598,14 +598,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 113/337 net: sxgbe: check descriptor ring allocation failures
In reply to Greg Kroah-Hartman6.12-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
@@ -1079,7 +1079,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);
@@ -1188,6 +1190,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 114/337 can: isotp: check register_netdevice_notifier() error in module init
In reply to Greg Kroah-Hartman6.12-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
@@ -1885,13 +1885,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 115/337 tracing/mmiotrace: Reset dropped_count in mmio_reset_data()
In reply to Greg Kroah-Hartman6.12-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 116/337 tracing: Remove TRACE_EVENT_FL_FILTERED logic
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zheng Yejian <[email protected]>
[ Upstream commit 49e4154f4b16345da5e219b23ed9737a6e735bc1 ]
After commit dcb0b5575d24 ("tracing: Remove TRACE_EVENT_FL_USE_CALL_FILTER
logic"), no one's going to set the TRACE_EVENT_FL_FILTERED or change thecall->filter, so remove related logic.
Stable-dep-of: 12b80cdbc54c ("tracing/mmiotrace: Add NULL check for mmio_trace_array in logging functions")
--- include/linux/trace_events.h | 4 --- kernel/trace/trace.c | 44 ++++++---------------------- kernel/trace/trace.h | 4 --- kernel/trace/trace_branch.c | 4 +-- kernel/trace/trace_events.c | 2 -- kernel/trace/trace_functions_graph.c | 8 ++--- kernel/trace/trace_hwlat.c | 4 +-- kernel/trace/trace_mmiotrace.c | 8 ++--- kernel/trace/trace_osnoise.c | 12 ++------ kernel/trace/trace_sched_wakeup.c | 8 ++--- 10 files changed, 20 insertions(+), 78 deletions(-)
include/linux/trace_events.h +0 -4
@@ -327,7 +327,6 @@ void *trace_event_buffer_reserve(struct trace_event_buffer *fbuffer,void trace_event_buffer_commit (struct trace_event_buffer *fbuffer);enum { -TRACE_EVENT_FL_FILTERED_BIT ,TRACE_EVENT_FL_CAP_ANY_BIT ,TRACE_EVENT_FL_NO_SET_FILTER_BIT ,TRACE_EVENT_FL_IGNORE_ENABLE_BIT ,
@@ -343,7 +342,6 @@ enum {/* * Event flags: -* FILTERED - The event has a filter attached * CAP_ANY - Any user can enable for perf * NO_SET_FILTER - Set when filter has error and is to be ignored * IGNORE_ENABLE - For trace internal events, do not enable with debugfs file
@@ -359,7 +357,6 @@ enum {* TEST_STR - The event has a "%s" that points to a string outside the event */ enum { -TRACE_EVENT_FL_FILTERED = (1 <<TRACE_EVENT_FL_FILTERED_BIT ),TRACE_EVENT_FL_CAP_ANY = (1 <<TRACE_EVENT_FL_CAP_ANY_BIT ),TRACE_EVENT_FL_NO_SET_FILTER = (1 <<TRACE_EVENT_FL_NO_SET_FILTER_BIT ),TRACE_EVENT_FL_IGNORE_ENABLE = (1 <<TRACE_EVENT_FL_IGNORE_ENABLE_BIT ),
@@ -385,7 +382,6 @@ struct trace_event_call { };struct trace_event event;char *print_fmt; -struct event_filter *filter;/* * Static events can disappear with modules, * where as dynamic ones need their own ref count.
kernel/trace/trace.c +9 -35
110 lines not on this page · raw message
kernel/trace/trace.h +0 -4
@@ -1440,10 +1440,6 @@ struct trace_subsystem_dir {int nr_events; }; -extern int call_filter_check_discard (struct trace_event_call *call,void *rec, -struct trace_buffer *buffer, -struct ring_buffer_event *event); - void trace_buffer_unlock_commit_regs(struct trace_array *tr, struct trace_buffer *buffer, struct ring_buffer_event *event,
kernel/trace/trace_branch.c +1 -3
@@ -30,7 +30,6 @@ static struct trace_array *branch_tracer;static void probe_likely_condition (struct ftrace_likely_data *f,int val,int expect) { -struct trace_event_call *call = &event_branch;struct trace_array *tr = branch_tracer;struct trace_buffer *buffer;struct trace_array_cpu *data;
@@ -82,8 +81,7 @@ probe_likely_condition(struct ftrace_likely_data *f, int val, int expect) entry->line = f->data.line; entry->correct = val == expect; -if (!call_filter_check_discard (call, entry, buffer, event)) -trace_buffer_unlock_commit_nostack (buffer, event); +trace_buffer_unlock_commit_nostack (buffer, event); out: current->trace_recursion &= ~TRACE_BRANCH_BIT ;
kernel/trace/trace_events.c +0 -2
@@ -3319,8 +3319,6 @@ static void __trace_remove_event_call(struct trace_event_call *call) {event_remove (call);trace_destroy_fields (call); -free_event_filter (call->filter); - call->filter =NULL ; }static int probe_remove_event_call (struct trace_event_call *call)
kernel/trace/trace_functions_graph.c +2 -6
@@ -102,7 +102,6 @@ int __trace_graph_entry(struct trace_array *tr,struct ftrace_graph_ent *trace, unsigned int trace_ctx) { - struct trace_event_call *call = &event_funcgraph_entry; struct ring_buffer_event *event;struct trace_buffer *buffer = tr->array_buffer.buffer;struct ftrace_graph_ent_entry *entry;
@@ -113,8 +112,7 @@ int __trace_graph_entry(struct trace_array *tr,return 0 ; entry =ring_buffer_event_data (event); entry->graph_ent = *trace; -if (!call_filter_check_discard (call, entry, buffer, event)) -trace_buffer_unlock_commit_nostack (buffer, event); +trace_buffer_unlock_commit_nostack (buffer, event);return 1 ; }
@@ -223,7 +221,6 @@ void __trace_graph_return(struct trace_array *tr,struct ftrace_graph_ret *trace, unsigned int trace_ctx) { - struct trace_event_call *call = &event_funcgraph_exit; struct ring_buffer_event *event;struct trace_buffer *buffer = tr->array_buffer.buffer;struct ftrace_graph_ret_entry *entry;
@@ -234,8 +231,7 @@ void __trace_graph_return(struct trace_array *tr,return ; entry =ring_buffer_event_data (event); entry->ret = *trace; -if (!call_filter_check_discard (call, entry, buffer, event)) -trace_buffer_unlock_commit_nostack (buffer, event); +trace_buffer_unlock_commit_nostack (buffer, event); } void trace_graph_return(struct ftrace_graph_ret *trace,
kernel/trace/trace_hwlat.c +1 -3
@@ -130,7 +130,6 @@ static bool hwlat_busy;static void trace_hwlat_sample (struct hwlat_sample *sample) {struct trace_array *tr = hwlat_trace; -struct trace_event_call *call = &event_hwlat;struct trace_buffer *buffer = tr->array_buffer.buffer;struct ring_buffer_event *event;struct hwlat_entry *entry;
@@ -148,8 +147,7 @@ static void trace_hwlat_sample(struct hwlat_sample *sample) entry->nmi_count = sample->nmi_count; entry->count = sample->count; -if (!call_filter_check_discard (call, entry, buffer, event)) -trace_buffer_unlock_commit_nostack (buffer, event); +trace_buffer_unlock_commit_nostack (buffer, event); }/* Macros to encapsulate the time capturing infrastructure */
kernel/trace/trace_mmiotrace.c +2 -6
@@ -295,7 +295,6 @@ static void __trace_mmiotrace_rw(struct trace_array *tr,struct trace_array_cpu *data, struct mmiotrace_rw *rw) { - struct trace_event_call *call = &event_mmiotrace_rw; struct trace_buffer *buffer = tr->array_buffer.buffer;struct ring_buffer_event *event;struct trace_mmiotrace_rw *entry;
@@ -311,8 +310,7 @@ static void __trace_mmiotrace_rw(struct trace_array *tr, entry =ring_buffer_event_data (event); entry->rw = *rw; -if (!call_filter_check_discard (call, entry, buffer, event)) -trace_buffer_unlock_commit (tr, buffer, event, trace_ctx); +trace_buffer_unlock_commit (tr, buffer, event, trace_ctx); }void mmio_trace_rw (struct mmiotrace_rw *rw)
@@ -326,7 +324,6 @@ static void __trace_mmiotrace_map(struct trace_array *tr,struct trace_array_cpu *data, struct mmiotrace_map *map) { - struct trace_event_call *call = &event_mmiotrace_map; struct trace_buffer *buffer = tr->array_buffer.buffer;struct ring_buffer_event *event;struct trace_mmiotrace_map *entry;
@@ -342,8 +339,7 @@ static void __trace_mmiotrace_map(struct trace_array *tr, entry =ring_buffer_event_data (event); entry->map = *map; -if (!call_filter_check_discard (call, entry, buffer, event)) -trace_buffer_unlock_commit (tr, buffer, event, trace_ctx); +trace_buffer_unlock_commit (tr, buffer, event, trace_ctx); }void mmio_trace_mapping (struct mmiotrace_map *map)
kernel/trace/trace_osnoise.c +3 -9
@@ -501,7 +501,6 @@ static void print_osnoise_headers(struct seq_file *s)static void __trace_osnoise_sample (struct osnoise_sample *sample,struct trace_buffer *buffer) { -struct trace_event_call *call = &event_osnoise;struct ring_buffer_event *event;struct osnoise_entry *entry;
@@ -519,8 +518,7 @@ __trace_osnoise_sample(struct osnoise_sample *sample, struct trace_buffer *buffe entry->softirq_count = sample->softirq_count; entry->thread_count = sample->thread_count; -if (!call_filter_check_discard (call, entry, buffer, event)) -trace_buffer_unlock_commit_nostack (buffer, event); +trace_buffer_unlock_commit_nostack (buffer, event); }/*
@@ -580,7 +578,6 @@ static void print_timerlat_headers(struct seq_file *s)static void __trace_timerlat_sample (struct timerlat_sample *sample,struct trace_buffer *buffer) { -struct trace_event_call *call = &event_osnoise;struct ring_buffer_event *event;struct timerlat_entry *entry;
@@ -593,8 +590,7 @@ __trace_timerlat_sample(struct timerlat_sample *sample, struct trace_buffer *buf entry->context = sample->context; entry->timer_latency = sample->timer_latency; -if (!call_filter_check_discard (call, entry, buffer, event)) -trace_buffer_unlock_commit_nostack (buffer, event); +trace_buffer_unlock_commit_nostack (buffer, event); }/*
@@ -656,7 +652,6 @@ static void timerlat_save_stack(int skip)static void __timerlat_dump_stack (struct trace_buffer *buffer,struct trace_stack *fstack,unsigned int size) { -struct trace_event_call *call = &event_osnoise;struct ring_buffer_event *event;struct stack_entry *entry;
@@ -670,8 +665,7 @@ __timerlat_dump_stack(struct trace_buffer *buffer, struct trace_stack *fstack, u entry->size = fstack->nr_entries;memcpy (&entry->caller, fstack->calls, size); -if (!call_filter_check_discard (call, entry, buffer, event)) -trace_buffer_unlock_commit_nostack (buffer, event); +trace_buffer_unlock_commit_nostack (buffer, event); }/*
kernel/trace/trace_sched_wakeup.c +2 -6
@@ -376,7 +376,6 @@ tracing_sched_switch_trace(struct trace_array *tr,struct task_struct *next, unsigned int trace_ctx) { - struct trace_event_call *call = &event_context_switch; struct trace_buffer *buffer = tr->array_buffer.buffer;struct ring_buffer_event *event;struct ctx_switch_entry *entry;
@@ -394,8 +393,7 @@ tracing_sched_switch_trace(struct trace_array *tr, entry->next_state =task_state_index (next); entry->next_cpu =task_cpu (next); -if (!call_filter_check_discard (call, entry, buffer, event)) -trace_buffer_unlock_commit (tr, buffer, event, trace_ctx); +trace_buffer_unlock_commit (tr, buffer, event, trace_ctx); } static void
@@ -404,7 +402,6 @@ tracing_sched_wakeup_trace(struct trace_array *tr,struct task_struct *curr, unsigned int trace_ctx) { - struct trace_event_call *call = &event_wakeup; struct ring_buffer_event *event;struct ctx_switch_entry *entry;struct trace_buffer *buffer = tr->array_buffer.buffer;
@@ -422,8 +419,7 @@ tracing_sched_wakeup_trace(struct trace_array *tr, entry->next_state =task_state_index (wakee); entry->next_cpu =task_cpu (wakee); -if (!call_filter_check_discard (call, entry, buffer, event)) -trace_buffer_unlock_commit (tr, buffer, event, trace_ctx); +trace_buffer_unlock_commit (tr, buffer, event, trace_ctx); }static void notrace
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 117/337 tracing/mmiotrace: Add NULL check for mmio_trace_array in logging functions
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <[email protected]>
[ Upstream commit 12b80cdbc54cf615b4717a4e8180063408091ea2 ]
mmio_trace_rw() and mmio_trace_mapping() retrieve mmio_trace_array into tr and pass it to __trace_mmiotrace_rw() and __trace_mmiotrace_map(). If these functions are invoked while mmio_trace_array is NULL (e.g. before initialization or after disabled), accessing tr->array_buffer.buffer will result in a NULL pointer dereference crash.
Fix this by adding an explicit NULL check for tr at the beginning of __trace_mmiotrace_rw() and __trace_mmiotrace_map().
--- kernel/trace/trace_mmiotrace.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
kernel/trace/trace_mmiotrace.c +10 -2
@@ -295,11 +295,15 @@ static void __trace_mmiotrace_rw(struct trace_array *tr,struct trace_array_cpu *data, struct mmiotrace_rw *rw) { - struct trace_buffer *buffer = tr->array_buffer.buffer; + struct trace_buffer *buffer;struct ring_buffer_event *event;struct trace_mmiotrace_rw *entry;unsigned int trace_ctx; +if (!tr) +return ; + + buffer = tr->array_buffer.buffer; trace_ctx =tracing_gen_ctx_flags (0 ); event =trace_buffer_lock_reserve (buffer,TRACE_MMIO_RW ,sizeof (*entry), trace_ctx);
@@ -324,11 +328,15 @@ static void __trace_mmiotrace_map(struct trace_array *tr,struct trace_array_cpu *data, struct mmiotrace_map *map) { - struct trace_buffer *buffer = tr->array_buffer.buffer; + struct trace_buffer *buffer;struct ring_buffer_event *event;struct trace_mmiotrace_map *entry;unsigned int trace_ctx; +if (!tr) +return ; + + buffer = tr->array_buffer.buffer; trace_ctx =tracing_gen_ctx_flags (0 ); event =trace_buffer_lock_reserve (buffer,TRACE_MMIO_MAP ,sizeof (*entry), trace_ctx);
Signature · 1 line
2.53.0
Re: [PATCH 6.12 117/337] tracing/mmiotrace: Add NULL check for mmio_trace_array in logging functions
Hi Greg/Sasha,
Quoted 32 lines · Greg Kroah-Hartman
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <[email protected]>
[ Upstream commit
12b80cdbc54cf615b4717a4e8180063408091ea2]
mmio_trace_rw()andmmio_trace_mapping()retrievemmio_trace_arrayinto tr and pass it to__trace_mmiotrace_rw()and__trace_mmiotrace_map(). If these functions are invoked whilemmio_trace_arrayis NULL (e.g. before initialization or after disabled), accessingtr->array_buffer.bufferwill result in a NULL pointer dereference crash.Fix this by adding an explicit NULL check for tr at the beginning of
__trace_mmiotrace_rw()and__trace_mmiotrace_map().Fixes f984b51e0779 ("ftrace: add mmiotrace plugin")Assisted-by Antigravity:gemini-3.6-flashSigned-off-by Masami Hiramatsu (Google) <[email protected]>Signed-off-by Steven Rostedt <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- kernel/trace/trace_mmiotrace.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)kernel/trace/trace_mmiotrace.c +0
-0
kernel/trace/trace_mmiotrace.c static void __trace_mmiotrace_rw(struct trace_array *tr, · line 295
Quoted 1 line
kernel/trace/trace_mmiotrace.c +0
-0@@ -295,11 +295,15 @@ static void __trace_mmiotrace_rw(struct trace_array *tr, struct trace_array_cpu *data,
^^^ lets keep this in mind
kernel/trace/trace_mmiotrace.c static void __trace_mmiotrace_rw(struct trace_array *tr, · line 306
Quoted 12 lines
kernel/trace/trace_mmiotrace.c +5
-1struct mmiotrace_rw *rw) { -struct trace_buffer *buffer = tr->array_buffer.buffer; +struct trace_buffer *buffer;struct ring_buffer_event *event;struct trace_mmiotrace_rw *entry;unsigned int trace_ctx; +if (!tr) +return ; + + buffer = tr->array_buffer.buffer;
I ran an AI-assisted backport review and then checked the 6.12.y code. I think this backport is missing a small prerequisite.
Upstream's wrappers pass tr directly to __trace_mmiotrace_rw() and __trace_mmiotrace_map().Each function checks tr before dereferencing it:
if (!tr)
return;
buffer = tr->array_buffer.buffer;
The upstream fix follows commit: 6936298393d8 ("tracing/mmiotrace: Remove reference to unused per CPU data pointer"), which removes the unused data argument.
6.12.y does not have that commit, so both functions still have that argument and their wrappers compute it first:
struct trace_array *tr = mmio_trace_array;
struct trace_array_cpu *data =
per_cpu_ptr(tr->array_buffer.data, smp_processor_id());
__trace_mmiotrace_rw(tr, data, rw);
Consequently, if mmio_trace_array is NULL, the dereference in per_cpu_ptr(tr->array_buffer.data, ...) occurs before either function's new NULL check.
I think 6.12.y needs commit: 6936298393d8 ("tracing/mmiotrace: Remove reference to unused per CPU data pointer") before this fix.
Thoughts?
thanks,
Harshit
Quoted 20 lines
kernel/trace/trace_mmiotrace.c +5
-1trace_ctx =tracing_gen_ctx_flags (0 ); event =trace_buffer_lock_reserve (buffer,TRACE_MMIO_RW ,sizeof (*entry), trace_ctx);@@ -324,11 +328,15 @@ static void __trace_mmiotrace_map(struct trace_array *tr,struct trace_array_cpu *data, struct mmiotrace_map *map) { - struct trace_buffer *buffer = tr->array_buffer.buffer; + struct trace_buffer *buffer;struct ring_buffer_event *event;struct trace_mmiotrace_map *entry;unsigned int trace_ctx; +if (!tr) +return ; + + buffer = tr->array_buffer.buffer; trace_ctx =tracing_gen_ctx_flags (0 ); event =trace_buffer_lock_reserve (buffer,TRACE_MMIO_MAP ,sizeof (*entry), trace_ctx);
Re: [PATCH 6.12 117/337] tracing/mmiotrace: Add NULL check for mmio_trace_array in logging functions
Quoted 24 lines · On Sat, 8 Aug 2026 22:53:31 +0530 Harshit Mogalapalli…
I ran an AI-assisted backport review and then checked the 6.12.y code. I think this backport is missing a small prerequisite.
Upstream's wrappers pass tr directly to
__trace_mmiotrace_rw()and __trace_mmiotrace_map().Each function checks tr before dereferencing it:if (!tr)
return;buffer =
tr->array_buffer.buffer;The upstream fix follows commit:
6936298393d8("tracing/mmiotrace:
Remove reference to unused per CPU data pointer"), which removes the unused data argument.6.12.y does not have that commit, so both functions still have that argument and their wrappers compute it first:
struct
trace_array*tr =mmio_trace_array;
structtrace_array_cpu*data =per_cpu_ptr(tr->array_buffer.data, smp_processor_id());
__trace_mmiotrace_rw(tr, data, rw);
Quoted 9 lines
Consequently, if
mmio_trace_arrayis NULL, the dereference inper_cpu_ptr(tr->array_buffer.data, ...)occurs before either function's new NULL check.I think 6.12.y needs commit:
6936298393d8("tracing/mmiotrace: Remove reference to unused per CPU data pointer") before this fix.Thoughts?
Yeah, it looks like the kernel could crash for the same reasons without commit 6936298393d8.
Greg, care to backport that one too?
Thanks,
-- Steve
Greg Kroah-Hartman
maintainerPATCH 118/337 accel/qaic: use sizeof(*trans_hdr) for transaction length check
In reply to Greg Kroah-Hartman6.12-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 119/337 riscv: mm: Fix out-of-bounds page-table walk during memory hot-remove
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karl Mehltretter <[email protected]>
[ Upstream commit a0188cc133696627857d16054e43f9ebc7efc821 ]
remove_pud_mapping() and remove_p4d_mapping() obtain a child table base with pud_offset(p4dp, 0) and p4d_offset(pgd, 0), then add the index for addr.
RISC-V folds page-table levels at runtime. When a level is folded, its offset helper returns the parent entry itself, but the index can still be nonzero. Adding it walks past the parent table. Sv48 folds P4D, while Sv39 folds both P4D and PUD, so memory hot-remove can descend into unrelated memory and pass an invalid page to __free_pages(). This can trigger:
kernel BUG at include/linux/mm.h:1810!
VM_BUG_ON_PAGE(page_ref_count(page) == 0)
arch_remove_memory+0x1e/0x5c try_remove_memory+0x15e/0x200 remove_memory+0x24/0x3c
Only add the index when the corresponding page-table level is enabled, matching p4d_offset() and pud_offset().
--- arch/riscv/mm/init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/riscv/mm/init.c +2 -2
@@ -1726,7 +1726,7 @@ static void __meminit remove_pud_mapping(pud_t *pud_base, unsigned long addr, unfor (; addr < end; addr = next) { next =pud_addr_end (addr, end); - pudp = pud_base +pud_index (addr); + pudp = pgtable_l4_enabled ? pud_base +pud_index (addr) : pud_base; pud =pudp_get (pudp);if (!pud_present (pud))continue ;
@@ -1757,7 +1757,7 @@ static void __meminit remove_p4d_mapping(p4d_t *p4d_base, unsigned long addr, unfor (; addr < end; addr = next) { next =p4d_addr_end (addr, end); - p4dp = p4d_base +p4d_index (addr); + p4dp = pgtable_l5_enabled ? p4d_base +p4d_index (addr) : p4d_base; p4d =p4dp_get (p4dp);if (!p4d_present (p4d))continue ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 120/337 net: dsa: mt7530: check bus->read() errors in the MDIO regmap backend
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Golle <[email protected]>
[ Upstream commit b4ce102b2cd88424c5860fbbb20b9eb343a93bf4 ]
bus->read() returns a negative errno on failure, but mt7530_regmap_read() assigns it to a u16, truncating e.g. -ETIMEDOUT into 0xff92, and returns success. The garbage word is then consumed as register data, and read-modify-write cycles write it back to the switch. Check both reads and propagate their errors.
The same defect existed in mt7530_mii_read() since the driver was introduced and moved into the regmap backend unchanged.
--- drivers/net/dsa/mt7530-mdio.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-)
drivers/net/dsa/mt7530-mdio.c +9 -2
@@ -55,8 +55,15 @@ mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val)if (ret <0 )return ret; - lo = bus->read (bus, priv->mdiodev->addr, r); - hi = bus->read (bus, priv->mdiodev->addr,0x10 ); + ret = bus->read (bus, priv->mdiodev->addr, r); +if (ret <0 ) +return ret; + lo = ret; + + ret = bus->read (bus, priv->mdiodev->addr,0x10 ); +if (ret <0 ) +return ret; + hi = ret; *val = (hi <<16 ) | (lo &0xffff );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 121/337 net: dsa: mt7530: error out on failed reads in MT7531 PHY polling
In reply to Greg Kroah-Hartman6.12-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
@@ -219,12 +219,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) {
@@ -577,16 +571,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;
@@ -596,8 +587,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;
@@ -607,8 +598,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;
@@ -625,16 +616,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;
@@ -644,8 +632,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;
@@ -655,8 +643,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;
@@ -671,16 +659,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;
@@ -691,8 +676,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;
@@ -709,16 +694,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;
@@ -729,8 +711,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 122/337 net: libwx: fix FDIR ATR queue mismatch for software VLAN packets
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiawen Wu <[email protected]>
[ Upstream commit 732ed8f75ce583d115716f668dc80d730f3ad610 ]
When TX VLAN hardware offload is disabled, VLAN tags are embedded in the packet payload (software VLAN). Previously, the driver failed to set the WX_TX_FLAGS_SW_VLAN flag for these packets during transmission.
This missing flag caused the txgbe FDIR ATR logic to fall through to the default hash calculation path. This resulted in asymmetric hash values for Tx and Rx flows, preventing return packets from being steered to the same queue as the transmit packets.
Fix this by detecting software VLANs via eth_type_vlan(skb->protocol) and setting WX_TX_FLAGS_SW_VLAN. This ensures the ATR feature selects the correct hashing algorithm to maintain Tx/Rx queue symmetry.
--- drivers/net/ethernet/wangxun/libwx/wx_lib.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/ethernet/wangxun/libwx/wx_lib.c +2 -0
@@ -1481,6 +1481,8 @@ static netdev_tx_t wx_xmit_frame_ring(struct sk_buff *skb,if (skb_vlan_tag_present (skb)) { tx_flags |=skb_vlan_tag_get (skb) <<WX_TX_FLAGS_VLAN_SHIFT ; tx_flags |=WX_TX_FLAGS_HW_VLAN ; + }else if (eth_type_vlan (skb->protocol)) { + tx_flags |=WX_TX_FLAGS_SW_VLAN ; }/* record initial flags and protocol */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 123/337 octeontx2-pf: Set correct sequence for carrier off and tx queue stop
In reply to Greg Kroah-Hartman6.12-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
@@ -838,8 +838,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 124/337 sched/deadline: Use revised wakeup rule only for running dl_server
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabriele Monaco <[email protected]>
[ Upstream commit 1842bf97af109f5ebf830175c9725bf81ebb78b1 ]
Commit 14a857056466 ("sched/deadline: Use revised wakeup rule for dl_server") applies the revised wakeup rule to any server, as a result servers that are not running (dl_defer_running == 0) and start with a deadline overflow get enqueued and can boost tasks as if they were running, invalidating the defer rule and the documented state model.
Apply the revised wakeup rule only for deferrable servers that are marked as running.
--- kernel/sched/deadline.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/sched/deadline.c +2 -1
@@ -1079,7 +1079,8 @@ static void update_dl_entity(struct sched_dl_entity *dl_se)if (dl_time_before (dl_se->deadline,rq_clock (rq)) ||dl_entity_overflow (dl_se,rq_clock (rq))) { -if (unlikely ((!dl_is_implicit (dl_se) || dl_se->dl_defer) && +if (unlikely ((!dl_is_implicit (dl_se) || + (dl_se->dl_defer && dl_se->dl_defer_running)) && !dl_time_before (dl_se->deadline,rq_clock (rq)) && !is_dl_boosted (dl_se))) {update_dl_revised_wakeup (dl_se, rq);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 125/337 qede: sync udp_tunnel ports outside qede_lock in the recovery path
In reply to Greg Kroah-Hartman6.12-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 126/337 ksmbd: return success for deferred final close
In reply to Greg Kroah-Hartman6.12-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