6.18.44-rc1 review
Subsystems (4)
Greg Kroah-Hartman
maintainercover 6.18.44-rc1 review
This is the start of the stable review cycle for the 6.18.44 release. There are 396 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.18.44-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.18.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 6.18.44-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
Zongyao Bai <[email protected]>
drm/xe/pt: Reset current_op in xe_pt_update_ops_init()
Oak Zeng <[email protected]>
drm/xe: Add page reclamation info to device info
Matthew Brost <[email protected]>
drm/xe: Stub out new pagefault layer
Matthew Brost <[email protected]>
drm/xe: Use SVM range helpers in PT layer
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]
Himal Prasad Ghimiray <[email protected]>
drm/xe/vm: Fix BO prefetch with CONSULT_MEM_ADVISE_PREF_LOC
Arvind Yadav <[email protected]>
drm/xe/vm: Prevent binding of purged buffer objects
Arvind Yadav <[email protected]>
drm/xe/bo: Add purgeable bo state tracking and field madv to xe_bo
Nitin Gote <[email protected]>
drm/xe: add xe_migrate_resolve wrapper and is_vram_resolve support
Xin Wang <[email protected]>
drm/xe/pat: Add helper to query compression enable status
Leo Li <[email protected]>
drm/amd/display: Exit idle optimizations before programming
Leo Li <[email protected]>
drm/amd/display: check GRPH_FLIP status before sending event
Tejas Upadhyay <[email protected]>
drm/xe/guc: Fix buffer overflow in steered register list allocation
Timur Kristóf <[email protected]>
drm/amdgpu: Respect placement requirements in amdgpu_gtt_mgr functions
Tvrtko Ursulin <[email protected]>
drm/amdgpu: Fix context pstate override handling
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
Mike Rapoport (Microsoft) <[email protected]>
userfaultfd: prevent registration of special VMAs
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
Bryan O'Donoghue <[email protected]>
media: qcom: camss: Fix RDI streaming for CSID 340
Loic Poulain <[email protected]>
media: qcom: camss: csid-340: Fix unused variables
Jackson Lee <[email protected]>
media: chips-media: wave5: Support CBP profile
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
Chuck Lever <[email protected]>
net/handshake: Drain pending requests at net namespace exit
Chuck Lever <[email protected]>
net/handshake: Close the submit-side sock_hold race
Chuck Lever <[email protected]>
net/handshake: hand off the pinned file reference to accept_doit
Chuck Lever <[email protected]>
net/handshake: Take a long-lived file reference at submit
Wang Liang <[email protected]>
net/handshake: Fix null-ptr-deref in handshake_complete()
Christian Brauner <[email protected]>
net/handshake: convert handshake_nl_accept_doit() to FD_PREPARE()
Christian Brauner <[email protected]>
file: ensure cleanup
Christian Brauner <[email protected]>
file: add FD_{ADD,PREPARE}()
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
Ashutosh Dixit <[email protected]>
drm/xe/rtp: Refactor OAG MMIO trigger register whitelisting
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: enforce cursor size limits for MOB cursors
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: take fman->lock around fence list mutation in fifo_down
Zack Rusin <[email protected]>
drm/vmwgfx: clamp dirty-page range with min, not max
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
Yang Wang <[email protected]>
drm/amd/pm: fix torn gpu metrics reads
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
Pierre-Eric Pelloux-Prayer <[email protected]>
drm/amdgpu: move debug_vm handling to amdgpu_cs_parser_fini
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
Laurent Pinchart <[email protected]>
drm/bridge: display-connector: Fix I2C adapter resource leak
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
Carlos Song <[email protected]>
i2c: imx: mark I2C adapter when hardware is powered down
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
Wenmeng Liu <[email protected]>
i2c: qcom-cci: drop custom suspend/resume and rely on runtime PM helpers
Linmao Li <[email protected]>
i2c: spacemit: request IRQ after controller initialization
Dawei Feng <[email protected]>
ice: fix memory leak in ice_lbtest_prepare_rings()
Dawid Osuchowski <[email protected]>
ice: fix VF interrupts cleanup
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 missing mem scrub at clear key import in cca_clr2cipherkey()
Harald Freudenberger <[email protected]>
s390/zcrypt: Fix buffer over-read in cca_cipher2protkey
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()
Frank Sorenson <[email protected]>
cifs: add fscache_resize_cookie() to cifs_setsize()
Junjie Cao <[email protected]>
gpio: pch: use raw_spinlock_t for the register lock
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
Stanislaw Pal <[email protected]>
spi: spi-qpic-snand: write the feature value before executing SET_FEATURE
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 pskb_network_may_pull() for transmit path header pulls
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
Breno Leitao <[email protected]>
uprobes: Fix NULL pointer dereference in hprobe_expire()
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()
Chengfeng Ye <[email protected]>
net: pktgen: fix proc entry use-after-free
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
Jens Axboe <[email protected]>
io_uring/net: initialize mshot_len for send
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
Christian Brauner <[email protected]>
binfmt_misc: use exe_file_deny_write_access() for the interpreter clone
Christian Brauner <[email protected]>
binfmt_misc: restore write access when removing an entry
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
Carlo Caione <[email protected]>
of/address: Fix NULL bus dereference in of_pci_range_parser_one()
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
Wei Liu <[email protected]>
mshv: fix hv_input_get_system_property struct
Namjae Jeon <[email protected]>
ksmbd: reject repeated SMB2 NEGOTIATE requests
Zhiling Zou <[email protected]>
ipvs: do not propagate one-packet flag to synced conns
David Carlier <[email protected]>
igc: remove napi_synchronize() in igc_down()
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
Shengjiu Wang <[email protected]>
ASoC: fsl_easrc: fix m2m_init error path to use goto instead of bare return
Shengjiu Wang <[email protected]>
ASoC: fsl_asrc: fix m2m_init error path to use goto instead of bare return
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
Eckhart Mohr <[email protected]>
ALSA: hda/realtek: Add quirk for TongFang X6SP45xU
Takashi Iwai <[email protected]>
ALSA: 6fire: Fix UAF at error handling during probe
David Howells <[email protected]>
afs: Fix UAF when sending a message
David Howells <[email protected]>
afs: Fix afs_fs_fetch_data() to subtract transferred from len
David Howells <[email protected]>
afs: Fix afs_fs_fetch_data() to set call->async
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
Aldo Ariel Panzardo <[email protected]>
Bluetooth: SCO: give the socket its own sco_conn reference
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
Hidayath Khan <[email protected]>
dibs: fix use-after-free of dmb_node in loopback attach/detach/unregister
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: Fix missing error codes and memory unaccounting
Farhan Ali <[email protected]>
KVM: s390: pci: Fix memory accounting for pinned/unpinned pages
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
Paolo Bonzini <[email protected]>
KVM: VMX: add memory clobber to asm for VMX instructions
Raushan Patel <[email protected]>
tracing/fprobe: Roll back on enable_trace_fprobe() failure
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
Jori Koolstra <[email protected]>
selftest: fix headers in fclog.c
Aboorva Devarajan <[email protected]>
mm/util: don't read __page_2 for order-1 folios in snapshot_page()
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
Peiyang He <[email protected]>
iommu/iommufd: Fix IOPF group ownership UAF
Peiyang He <[email protected]>
iommufd: Fix wrong hwpt passed to iommufd_auto_response_faults on replace
Nicolin Chen <[email protected]>
iommufd/viommu: Publish a vDEVICE only after vdevice_init() succeeds
Nicolin Chen <[email protected]>
iommufd/viommu: Release the igroup lock on the vdevice_size error path
Stanislav Kinsburskii <[email protected]>
mshv: Order pt_vp_array publish against irqfd assertion path
Stanislav Kinsburskii <[email protected]>
mshv: Fix level-triggered check on uninitialized data
Jinank Jain <[email protected]>
mshv: adjust interrupt control structure for ARM64
Stanislav Kinsburskii <[email protected]>
mshv: Fix race in mshv_irqfd_deassign
Christoph Hellwig <[email protected]>
iomap: add a separate bio_set for iomap_split_ioend
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
Jerome Tollet <[email protected]>
drm/i915/hdmi: Poll for 200 msec for TMDS_Scrambler_Status
Denis V. Lunev <[email protected]>
qede: sync udp_tunnel ports outside qede_lock in the recovery path
Haibo Chen <[email protected]>
spi: spi-nxp-fspi: add per-SoC SDR/DTR clock rate limits for all supported SoCs
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
Wei Fang <[email protected]>
ptp: netc: fix potential interrupt storm caused by incorrect unbind order
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
Anirudh Srinivasan <[email protected]>
riscv: drop __init from vec_check_unaligned_access_speed_all_cpus
Masami Hiramatsu (Google) <[email protected]>
tracing/mmiotrace: Add NULL check for mmio_trace_array in logging functions
Masami Hiramatsu (Google) <[email protected]>
tracing/mmiotrace: Reset dropped_count in mmio_reset_data()
Masami Hiramatsu (Google) <[email protected]>
fprobe: Fix module reference count leak on error in register_fprobe()
Alexander Kaplan <[email protected]>
drm/i915/dp: Ignore the sink's DSC max FRL rate without a PCON DSC encoder
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
Bart Van Assche <[email protected]>
scsi: ufs: core: Revert "Delegate the interrupt service routine to a threaded IRQ handler"
Peter Wang <[email protected]>
scsi: ufs: core: Avoid IRQ thread wakeup during active UIC command
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
Mauricio Faria de Oliveira <[email protected]>
x86/boot: Add volatile, clobbers and zero-length test in memcmp()
Pauli Virtanen <[email protected]>
Bluetooth: hci_sync: remove unnecessary hci_conn_get in create_conn_sync
Pauli Virtanen <[email protected]>
Bluetooth: hci_sync: fix hci_conn_del() use in hci_le_create_conn_sync
Pauli Virtanen <[email protected]>
Bluetooth: hci_conn: hold conn reference in abort_conn_sync()
Pauli Virtanen <[email protected]>
Bluetooth: hci_sync: make hci_cmd_sync_run_once return -EEXIST if exists
Zijun Hu <[email protected]>
Bluetooth: btintel: Validate length before parsing diagnostics TLV
Pauli Virtanen <[email protected]>
Bluetooth: ISO: fix refcounting of iso_conn
Pauli Virtanen <[email protected]>
Bluetooth: ISO: ensure no dangling hcon references in iso_conn
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: hold sk properly in iso_conn_ready
Pauli Virtanen <[email protected]>
Bluetooth: ISO: fix CONNECTED -> CLOSED transition on shutdown/release
Luiz Augusto von Dentz <[email protected]>
Bluetooth: ISO: Fix not updating BIS sender source address
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
Pauli Virtanen <[email protected]>
Bluetooth: ISO: lock sk in iso_connect_ind
SeungJu Cheon <[email protected]>
Bluetooth: ISO: Fix data-race on iso_pi(sk) in socket and HCI event paths
Luiz Augusto von Dentz <[email protected]>
Bluetooth: HCI: Add initial support for PAST
Pauli Virtanen <[email protected]>
Bluetooth: ISO: lock sk in iso_sock_getname
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
Przemyslaw Korba <[email protected]>
ice: suppress DPLL errors during reset recovery
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
Yichong Chen <[email protected]>
netfs: release readahead folios on iterator preparation failure
Yichong Chen <[email protected]>
netfs: handle single writeback rolling buffer allocation failure
Yichong Chen <[email protected]>
netfs: clear PG_private_2 on copy-to-cache append failure
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
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
wangdicheng <[email protected]>
ASoC: tas2781: Use correct calibration data for SINEGAIN2 register
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
Jason Xing <[email protected]>
xsk: drain continuation descs after overflow in xsk_build_skb()
Jason Xing <[email protected]>
xsk: use a smaller new lock for shared pool case
Jason Xing <[email protected]>
xsk: fix buffer leak in xsk_drop_skb() for AF_XDP multi-buffer Tx
John Ericson <[email protected]>
selftests/net/af_unix: test listen() rejects wrong socket states
Kuniyuki Iwashima <[email protected]>
selftest: af_unix: Create its own .gitignore.
Sunday Adelodun <[email protected]>
selftests: af_unix: Add tests for ECONNRESET and EOF semantics
John Ericson <[email protected]>
af_unix: fix listen() succeeding on sockets in the wrong state
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
Charles Keepax <[email protected]>
ASoC: SDCA: Ensure that Control Range is large enough for header
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
Alexandru Elisei <[email protected]>
KVM: arm64: Reject guest_memfd memslots when the VM has MTE
Stanislav Kinsburskii <[email protected]>
mshv: Fix sleeping under spinlock in mshv_portid_alloc
Stanislav Kinsburskii <[email protected]>
mshv: Fix duplicate GSI detection for GSI 0
Sebastian Andrzej Siewior <[email protected]>
Drivers: hv: vmbus: Replace lockdep_hardirq_threaded() with lockdep annotation
Roman Kisel <[email protected]>
Drivers: hv: Allocate the paravisor SynIC pages when required
Roman Kisel <[email protected]>
Drivers: hv: Rename fields for SynIC message and event pages
Roman Kisel <[email protected]>
arch/x86: mshyperv: Discover Confidential VMBus availability
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()
Qu Wenruo <[email protected]>
btrfs: raid56: fix an incorrect csum skip during scrub
Johannes Thumshirn <[email protected]>
btrfs: zoned: reset meta_write_pointer on zone reset
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
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
Krishna Kurapati <[email protected]>
phy: qcom: m31-eusb2: Fix return value of init call
Radhey Shyam Pandey <[email protected]>
ata: ahci_ceva: fix error paths in ceva_ahci_platform_enable_resources()
Rosen Penev <[email protected]>
ata: sata_mv: accept 1 or 2 resources in platform probe
Kuan-Ying Lee <[email protected]>
selftests/seccomp: Fix pointer type mismatch build error
Haofeng Li <[email protected]>
selftests/lkdtm: rename STACKLEAK_ERASING to KSTACK_ERASE
Abdun Nihaal <[email protected]>
gpio: sloppy-logic-analyzer: Fix memory leak in gpio_la_poll_probe()
Nicolin Chen <[email protected]>
iommu/arm-smmu-v3-iommufd: Require exactly one Stream ID for a vDEVICE
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
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()
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
Fabian Lippold <[email protected]>
ALSA: hda/realtek: add quirk for HP Dragonfly Folio G3 2-in-1
Honglei Huang <[email protected]>
drm/gpusvm: publish dpagemap early to avoid device mapping leak on error
Yehyeong Lee <[email protected]>
net: mpls: initialize rtm_tos in mpls_getroute()
Lorenzo Bianconi <[email protected]>
netfilter: br_netfilter: Reallocate headroom if necessary in neigh_hh_bridge()
David Gow <[email protected]>
kunit: tool: Terminate kernel under test on SIGINT
Shuvam Pandey <[email protected]>
kunit: tool: skip stty when stdin is not a tty
Pablo Neira Ayuso <[email protected]>
netfilter: nf_conntrack_expect: restore helper propagation via expectation
-------------
Diffstat:
Documentation/hwmon/ina2xx.rst | 25 +- Documentation/virt/kvm/api.rst | 6 + Makefile | 4 +- arch/arm64/kvm/arm.c | 25 +- arch/arm64/kvm/mmu.c | 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/kernel/unaligned_access_speed.c | 4 +- arch/riscv/mm/init.c | 4 +- arch/s390/kvm/pci.c | 78 ++++- arch/s390/kvm/pci.h | 2 + arch/s390/pci/pci_mmio.c | 1 + arch/um/drivers/vector_kern.c | 3 + arch/x86/boot/string.c | 11 +- arch/x86/kernel/cpu/mshyperv.c | 28 +- arch/x86/kvm/svm/avic.c | 8 - arch/x86/kvm/vmx/vmx_ops.h | 8 +- drivers/accel/qaic/qaic_control.c | 2 +- drivers/ata/ahci_ceva.c | 18 +- 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/dibs/dibs_loopback.c | 47 +-- 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_cs.c | 39 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 73 +++-- drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 15 + drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c | 3 +- drivers/gpu/drm/amd/amdgpu/amdgpu_gtt_mgr.c | 30 +- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 12 + drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 10 +- drivers/gpu/drm/amd/amdkfd/kfd_events.c | 23 +- .../gpu/drm/amd/amdkfd/kfd_process_queue_manager.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_queue.c | 2 +- drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 243 +++++++++++---- drivers/gpu/drm/amd/display/dc/core/dc.c | 45 +++ drivers/gpu/drm/amd/display/dc/dc.h | 1 + .../gpu/drm/amd/display/dc/dce/dce_clock_source.c | 20 +- .../drm/amd/display/dc/hwss/dcn30/dcn30_hwseq.c | 16 +- drivers/gpu/drm/amd/pm/amdgpu_dpm.c | 12 +- drivers/gpu/drm/amd/pm/amdgpu_pm.c | 8 +- drivers/gpu/drm/amd/pm/inc/amdgpu_dpm.h | 3 +- drivers/gpu/drm/armada/armada_fbdev.c | 12 +- drivers/gpu/drm/bridge/display-connector.c | 11 +- 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_gpusvm.c | 12 +- drivers/gpu/drm/drm_gpuvm.c | 3 +- drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 9 +- drivers/gpu/drm/gma500/fbdev.c | 12 +- drivers/gpu/drm/i915/display/intel_ddi.c | 2 + drivers/gpu/drm/i915/display/intel_dp.c | 9 +- drivers/gpu/drm/i915/display/intel_fbdev.c | 9 +- drivers/gpu/drm/i915/display/intel_hdmi.c | 26 ++ drivers/gpu/drm/i915/display/intel_hdmi.h | 2 + drivers/gpu/drm/i915/display/intel_vrr.c | 10 +- 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/omapdrm/omap_fbdev.c | 9 +- drivers/gpu/drm/panthor/panthor_fw.c | 47 ++- drivers/gpu/drm/radeon/radeon_fbdev.c | 13 +- drivers/gpu/drm/tegra/fbdev.c | 18 +- drivers/gpu/drm/vc4/vc4_irq.c | 2 +- drivers/gpu/drm/vc4/vc4_validate.c | 29 +- drivers/gpu/drm/vmwgfx/ttm_object.c | 7 +- drivers/gpu/drm/vmwgfx/vmwgfx_blit.c | 39 ++- drivers/gpu/drm/vmwgfx/vmwgfx_cursor_plane.c | 49 ++- drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | 20 +- drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 13 +- drivers/gpu/drm/vmwgfx/vmwgfx_page_dirty.c | 4 +- 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/xe_bo.h | 56 ++++ drivers/gpu/drm/xe/xe_bo_types.h | 6 + drivers/gpu/drm/xe/xe_device_types.h | 2 + drivers/gpu/drm/xe/xe_exec.c | 22 +- drivers/gpu/drm/xe/xe_gt_debugfs.c | 4 +- drivers/gpu/drm/xe/xe_guc_capture.c | 11 +- drivers/gpu/drm/xe/xe_hw_engine.c | 2 + drivers/gpu/drm/xe/xe_hw_engine_types.h | 8 + drivers/gpu/drm/xe/xe_migrate.c | 90 ++++-- drivers/gpu/drm/xe/xe_migrate.h | 4 + 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_pat.c | 6 + drivers/gpu/drm/xe/xe_pat.h | 10 + drivers/gpu/drm/xe/xe_pci.c | 1 + drivers/gpu/drm/xe/xe_pci_types.h | 1 + drivers/gpu/drm/xe/xe_pt.c | 31 +- drivers/gpu/drm/xe/xe_reg_whitelist.c | 119 ++++++-- drivers/gpu/drm/xe/xe_reg_whitelist.h | 4 + drivers/gpu/drm/xe/xe_vm.c | 107 +++++-- drivers/hid/hid-logitech-dj.c | 28 +- drivers/hv/channel_mgmt.c | 6 +- drivers/hv/hv.c | 206 +++++++------ drivers/hv/hyperv_vmbus.h | 22 +- drivers/hv/mshv_eventfd.c | 43 ++- drivers/hv/mshv_irq.c | 6 +- drivers/hv/mshv_portid_table.c | 6 +- drivers/hv/mshv_root.h | 2 +- drivers/hv/mshv_root_hv_call.c | 6 + drivers/hv/mshv_root_main.c | 8 +- drivers/hv/mshv_synic.c | 6 +- drivers/hv/vmbus_drv.c | 19 +- drivers/hwmon/Kconfig | 2 +- drivers/hwmon/adt7470.c | 131 +++++--- drivers/hwmon/ina2xx.c | 107 +++++-- 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 | 54 +++- drivers/i2c/busses/i2c-jz4780.c | 5 +- drivers/i2c/busses/i2c-k1.c | 10 +- drivers/i2c/busses/i2c-qcom-cci.c | 18 +- .../iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 15 + drivers/iommu/io-pgfault.c | 24 +- drivers/iommu/iommufd/device.c | 2 +- drivers/iommu/iommufd/eventq.c | 2 + drivers/iommu/iommufd/viommu.c | 22 +- .../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/media/platform/qcom/camss/camss-csid-340.c | 28 +- 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/intel/e1000/e1000_main.c | 2 +- drivers/net/ethernet/intel/ice/ice_dpll.c | 19 +- drivers/net/ethernet/intel/ice/ice_ethtool.c | 10 +- drivers/net/ethernet/intel/ice/ice_main.c | 10 + drivers/net/ethernet/intel/ice/ice_vf_lib.c | 27 ++ .../net/ethernet/intel/ice/ice_vf_lib_private.h | 1 + drivers/net/ethernet/intel/ice/virt/queues.c | 21 ++ 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 - drivers/net/ethernet/intel/igc/igc_main.c | 3 +- .../net/ethernet/marvell/octeontx2/nic/otx2_pf.c | 2 +- drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +- 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/phy/phylink.c | 29 +- drivers/net/veth.c | 4 +- drivers/net/vxlan/vxlan_core.c | 21 +- drivers/net/vxlan/vxlan_mdb.c | 4 +- .../wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 13 + .../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 6 + .../wireless/broadcom/brcm80211/brcmfmac/core.c | 46 ++- .../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 6 + .../wireless/broadcom/brcm80211/brcmfmac/sdio.c | 6 + .../wireless/broadcom/brcm80211/brcmfmac/sdio.h | 1 + .../net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 3 + .../net/wireless/marvell/mwifiex/11n_rxreorder.c | 2 +- drivers/of/address.c | 22 +- drivers/of/of_reserved_mem.c | 14 +- drivers/phy/qualcomm/phy-qcom-m31-eusb2.c | 2 +- drivers/phy/xilinx/phy-zynqmp.c | 62 ++-- 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/ptp/ptp_netc.c | 15 +- drivers/s390/block/dasd_eckd.c | 11 +- drivers/s390/block/dasd_ioctl.c | 2 +- drivers/s390/crypto/pkey_cca.c | 15 +- drivers/s390/crypto/zcrypt_api.c | 2 +- drivers/s390/crypto/zcrypt_ccamisc.c | 89 +++++- drivers/s390/crypto/zcrypt_ccamisc.h | 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-nxp-fspi.c | 83 ++++- drivers/spi/spi-qcom-qspi.c | 3 +- drivers/spi/spi-qpic-snand.c | 22 +- drivers/target/target_core_iblock.c | 6 +- drivers/target/target_core_transport.c | 12 +- drivers/thunderbolt/xdomain.c | 40 ++- drivers/ufs/core/ufshcd.c | 41 +-- drivers/usb/typec/ucsi/ucsi.c | 88 +++--- drivers/usb/typec/ucsi/ucsi.h | 1 + fs/afs/fsclient.c | 5 +- fs/afs/internal.h | 3 +- fs/binfmt_misc.c | 22 +- fs/btrfs/raid56.c | 4 +- fs/btrfs/super.c | 8 +- fs/btrfs/zoned.c | 17 +- fs/erofs/Kconfig | 14 + fs/erofs/decompressor_lzma.c | 3 +- fs/iomap/ioend.c | 21 +- fs/netfs/buffered_read.c | 4 +- fs/netfs/read_pgpriv2.c | 1 + fs/netfs/write_issue.c | 7 +- fs/proc/task_mmu.c | 33 +- fs/smb/client/cifssmb.c | 12 +- fs/smb/client/inode.c | 1 + fs/smb/server/connection.h | 5 + fs/smb/server/smb2pdu.c | 10 +- fs/smb/server/smb_common.c | 37 ++- fs/smb/server/vfs_cache.c | 6 +- include/asm-generic/mshyperv.h | 2 + include/drm/drm_exec.h | 20 +- include/drm/drm_fb_helper.h | 12 - include/hyperv/hvhdk.h | 6 + include/hyperv/hvhdk_mini.h | 3 +- include/linux/alloc_tag.h | 3 + include/linux/can/core.h | 1 + include/linux/can/skb.h | 2 - include/linux/cleanup.h | 7 + include/linux/dma/qcom_bam_dma.h | 21 +- include/linux/file.h | 125 ++++++++ include/linux/iommu.h | 5 + include/linux/libata.h | 2 +- include/linux/netfilter/nf_conntrack_sip.h | 2 +- include/linux/slab.h | 8 +- include/linux/thunderbolt.h | 3 + include/linux/userfaultfd_k.h | 5 +- include/net/bluetooth/hci.h | 54 ++++ include/net/bluetooth/hci_core.h | 12 + include/net/bluetooth/mgmt.h | 2 + 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/net/xdp_sock.h | 1 + include/net/xsk_buff_pool.h | 13 +- include/scsi/libsas.h | 1 - include/uapi/linux/rkisp1-config.h | 6 +- io_uring/net.c | 1 + kernel/audit.c | 11 +- kernel/auditfilter.c | 6 +- kernel/events/uprobes.c | 2 +- kernel/sched/cpufreq_schedutil.c | 11 + kernel/sched/deadline.c | 3 +- kernel/trace/fprobe.c | 6 +- kernel/trace/trace_events.c | 4 +- kernel/trace/trace_events_filter.c | 3 + kernel/trace/trace_fprobe.c | 12 +- kernel/trace/trace_mmiotrace.c | 13 +- kernel/trace/trace_probe.c | 6 +- lib/alloc_tag.c | 9 + lib/assoc_array.c | 3 +- lib/test_fortify/Makefile | 1 + mm/huge_memory.c | 12 + mm/hugetlb.c | 12 +- 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 | 76 ++--- mm/util.c | 2 +- net/bluetooth/hci_conn.c | 14 +- net/bluetooth/hci_event.c | 79 ++++- net/bluetooth/hci_sync.c | 157 ++++++---- net/bluetooth/hidp/core.c | 30 +- net/bluetooth/iso.c | 301 ++++++++++++------ net/bluetooth/l2cap_core.c | 5 + net/bluetooth/mgmt.c | 96 ++++-- net/bluetooth/sco.c | 22 +- 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/pktgen.c | 4 +- net/core/skbuff.c | 18 +- net/handshake/handshake-test.c | 8 + net/handshake/handshake.h | 2 + net/handshake/netlink.c | 54 ++-- net/handshake/request.c | 65 +++- 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/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/sctp/associola.c | 3 + net/sctp/sm_make_chunk.c | 17 +- net/smc/smc_core.c | 2 +- net/tipc/socket.c | 2 +- net/unix/af_unix.c | 1 + net/xdp/xsk.c | 73 +++-- net/xdp/xsk_buff_pool.c | 3 +- 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/hda/codecs/realtek/alc269.c | 4 +- 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/soc/codecs/tas2781-i2c.c | 4 +- sound/soc/fsl/fsl_asrc.c | 2 +- sound/soc/fsl/fsl_easrc.c | 2 +- sound/soc/sdca/sdca_functions.c | 2 + 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 | 38 ++- tools/testing/kunit/kunit_tool_test.py | 42 +++ tools/testing/selftests/clone3/clone3_set_tid.c | 2 +- tools/testing/selftests/filesystems/fclog.c | 4 +- tools/testing/selftests/lkdtm/tests.txt | 2 +- tools/testing/selftests/mm/mlock-random-test.c | 2 +- tools/testing/selftests/net/.gitignore | 7 - tools/testing/selftests/net/af_unix/.gitignore | 9 + tools/testing/selftests/net/af_unix/Makefile | 2 + .../testing/selftests/net/af_unix/unix_connreset.c | 177 +++++++++++ tools/testing/selftests/net/af_unix/unix_listen.c | 187 ++++++++++++ tools/testing/selftests/seccomp/seccomp_bpf.c | 3 +- 402 files changed, 5655 insertions(+), 2209 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/396 netfilter: nf_conntrack_expect: restore helper propagation via expectation
6.18-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
@@ -1771,14 +1771,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
@@ -2635,6 +2635,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);
@@ -2861,6 +2862,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;
@@ -2876,8 +2878,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);
@@ -3516,6 +3528,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) {
@@ -3569,6 +3582,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;
@@ -3624,7 +3638,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/396 kunit: tool: skip stty when stdin is not a tty
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuvam Pandey <[email protected]>
[ Upstream commit e42c349f4cdfa43cb39a68c8f764f8cafc23a9a9 ]
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
--- tools/testing/kunit/kunit_kernel.py | 10 ++++-- tools/testing/kunit/kunit_tool_test.py | 42 ++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 2 deletions(-)
tools/testing/kunit/kunit_kernel.py +8 -2
@@ -345,6 +345,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),
@@ -386,8 +392,8 @@ class LinuxSourceTree: process.stdout.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.') - 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 3/396 kunit: tool: Terminate kernel under test on SIGINT
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Gow <[email protected]>
[ Upstream commit 8f260b02eeeffbf2263c2b82b6e3e32fd73cde2b ]
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).
--- tools/testing/kunit/kunit_kernel.py | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-)
tools/testing/kunit/kunit_kernel.py +19 -9
@@ -16,7 +16,7 @@ import shutil import signal import sys import threading -from typing import Iterator, List, Optional, Tuple +from typing import Iterator, List, Optional, Tuple, Any from types import FrameType import kunit_config
@@ -265,6 +265,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
@@ -364,36 +365,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() 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() self._restore_terminal_if_tty()
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 4/396 netfilter: br_netfilter: Reallocate headroom if necessary in neigh_hh_bridge()
In reply to Greg Kroah-Hartman6.18-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
@@ -480,11 +480,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 5/396 net: mpls: initialize rtm_tos in mpls_getroute()
In reply to Greg Kroah-Hartman6.18-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 6/396 drm/gpusvm: publish dpagemap early to avoid device mapping leak on error
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Honglei Huang <[email protected]>
commit 7f708f51e3955bda0d77a0b67ab9bea6c97fea99 upstream.
drm_gpusvm_get_pages() only stored the local dpagemap into svm_pages->dpagemap on the success path. If a later page failed (e.g. -EOPNOTSUPP when ctx->allow_mixed is false) and jumped to err_unmap, svm_pages->dpagemap was still NULL, so __drm_gpusvm_unmap_pages() skipped device_unmap() and leaked the device mappings already created.
Assign svm_pages->dpagemap when the first device page is mapped so the err_unmap path can device_unmap() those mappings.
This issue was found by Sashiko AI review.
[ Adjusted for 6.18.y: drop drm_pagemap_get()/drm_pagemap_put() around the
svm_pages->dpagemap assignment; that reference counting is not present in 6.18 where the field is not refcounted (unmap path only clears it). ]
--- drivers/gpu/drm/drm_gpusvm.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
drivers/gpu/drm/drm_gpusvm.c +9 -3
@@ -1390,6 +1390,14 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm, err = -EAGAIN ; goto err_unmap; } + +/* +* Set the dpagemap as soon as the first +* device page is mapped so the err_unmap path +* can device_unmap() the device mappings that +* have already been created. +*/ + svm_pages->dpagemap = dpagemap; } svm_pages->dma_addr[j] = dpagemap->ops->device_map(dpagemap,
@@ -1432,10 +1440,8 @@ int drm_gpusvm_get_pages(struct drm_gpusvm *gpusvm, flags.has_dma_mapping = true; } -if (pagemap) { +if (pagemap) flags.has_devmem_pages = true; - svm_pages->dpagemap = dpagemap; - }/* WRITE_ONCE pairs with READ_ONCE for opportunistic checks */ WRITE_ONCE (svm_pages->flags.__flags, flags.__flags);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 7/396 ALSA: hda/realtek: add quirk for HP Dragonfly Folio G3 2-in-1
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fabian Lippold <[email protected]>
[ Upstream commit 0a10faad5ca58332ad70f7663ba82611f4daf736 ]
Add PCI quirk for HP Dragonfly Folio G3 (PCI ID 103c:8a06) to select the CS35L41 SPI4 & GPIO LED fixup variant.
--- sound/hda/codecs/realtek/alc269.c | 1 + 1 file changed, 1 insertion(+)
sound/hda/codecs/realtek/alc269.c +1 -0
@@ -6839,6 +6839,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {SND_PCI_QUIRK (0x103c ,0x89d3 ,"HP EliteBook 645 G9 (MB 89D2)" ,ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF ),SND_PCI_QUIRK (0x103c ,0x89da ,"HP Spectre x360 14t-ea100" ,ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX ),SND_PCI_QUIRK (0x103c ,0x89e7 ,"HP Elite x2 G9" ,ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED ), +SND_PCI_QUIRK (0x103c ,0x8a06 ,"HP Dragonfly Folio G3 2-in-1" ,ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED ),SND_PCI_QUIRK (0x103c ,0x8a0f ,"HP Pavilion 14-ec1xxx" ,ALC287_FIXUP_HP_GPIO_LED ),SND_PCI_QUIRK (0x103c ,0x8a1f ,"HP Laptop 14s-dr5xxx" ,ALC236_FIXUP_HP_MUTE_LED_COEFBIT2 ), SND_PCI_QUIRK(0x103c, 0x8a20, "HP Laptop 15s-fq5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 8/396 HID: logitech-dj: Standardise hid_report_enum variable nomenclature
In reply to Greg Kroah-Hartman6.18-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 9/396 HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated OOB write
In reply to Greg Kroah-Hartman6.18-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 10/396 HID: logitech-dj: fix wrong detection of bad DJ_SHORT output report
In reply to Greg Kroah-Hartman6.18-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 11/396 lib/alloc_tag: introduce mem_alloc_profiling_permanently_disabled()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harry Yoo (Oracle) <[email protected]>
commit a37b0066a10aabf3c968b4566706fb866eaf9a85 upstream.
mem_alloc_profiling_enabled() tells whether memalloc profiling is currently enabled. However, even when this function returns false, it can be enabled later.
However, this is not enough. Some optimizations can be applied only when memalloc profiling is permanently disabled. For example, to skip the creation of KMALLOC_NO_OBJ_EXT caches at boot time, mem_profiling must be set to "never", "0" w/ debugging on, or have been shutdown so that it can no longer be enabled.
Introduce mem_alloc_profiling_permanently_disabled() for this purpose.
--- include/linux/alloc_tag.h | 3 +++ lib/alloc_tag.c | 9 +++++++++ 2 files changed, 12 insertions(+)
include/linux/alloc_tag.h +3 -0
@@ -134,6 +134,8 @@ static inline bool mem_alloc_profiling_enabled(void) &mem_alloc_profiling_key); } +bool mem_alloc_profiling_permanently_disabled (void ); +static inline struct alloc_tag_counters alloc_tag_read (struct alloc_tag *tag) {struct alloc_tag_counters v = {0 ,0 };
@@ -239,6 +241,7 @@ static inline bool alloc_tag_is_inaccurate(struct alloc_tag *tag)#define DEFINE_ALLOC_TAG (_alloc_tag)static inline bool mem_alloc_profiling_enabled (void ) {return false; } +static inline bool mem_alloc_profiling_permanently_disabled (void ) {return true; }static inline void alloc_tag_add (union codetag_ref *ref,struct alloc_tag *tag,size_t bytes) {}static inline void alloc_tag_sub (union codetag_ref *ref,size_t bytes) {}
lib/alloc_tag.c +9 -0
@@ -26,6 +26,15 @@ static bool mem_profiling_support = true;static bool mem_profiling_support;#endif +/* +* Memory allocation profiling is permanently disabled and cannot be enabled. +* Must be called after setup_early_mem_profiling(). +*/ +bool mem_alloc_profiling_permanently_disabled (void ) +{ +return !mem_profiling_support; +} +static struct codetag_type *alloc_tag_cttype;#ifdef CONFIG_ARCH_MODULE_NEEDS_WEAK_PER_CPU
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 12/396 mm/slab: prevent unbounded recursion in free path with new kmalloc type
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harry Yoo (Oracle) <[email protected]>
commit d9e6a7623938968e3752b67e37eaff097e559a54 upstream.
Commit 280ea9c3154b ("mm/slab: avoid allocating slabobj_ext array from its own slab") avoided recursive allocation of obj_exts from kmalloc caches of the same size, by bumping the obj_exts array's allocation size whenever the array size equals the size of the object being allocated.
However, as reported by Danielle Costantino and Shakeel Butt, even slabs from kmalloc caches of different sizes can form a cycle by allocating obj_exts arrays from each other [1]:
What happened: a KMALLOC_NORMAL slab's obj_exts array (used by allocation profiling / memcg accounting) is itself kmalloc()'d from a KMALLOC_NORMAL cache, so the "slab holds another slab's obj_exts array" relation can form cycles. With sizeof(struct slabobj_ext) == 16 and the host's geometry:
- kmalloc-512 has 64 objects/slab -> array is 64*16 == 1024 bytes,
served from kmalloc-1k;
- kmalloc-1k has 32 objects/slab -> array is 32*16 == 512 bytes, served from kmalloc-512.
A kmalloc-512 slab and a kmalloc-1k slab therefore hold each other's obj_exts array. Discarding one frees the other's array, which empties and discards that slab, which frees the first's array, and so on:
__free_slab() -> free_slab_obj_exts() -> kfree() -> discard_slab() -> __free_slab() recurses along the cycle until the stack is exhausted.
With memory allocation profiling, this allows unbounded recursion in the free path and led to a stack overflow on a production host in the Meta fleet [1]:
BUG: TASK stack guard page was hit Oops: stack guard page RIP: 0010:kfree+0x8/0x5d0 Call Trace: __free_slab+0x66/0xc0 kfree+0x3f0/0x5d0 ... ( ~125x __free_slab <-> kfree ) ... <kernel driver freeing a resource> do_syscall_64
It is proposed [1] to resolve this issue by always serving the obj_exts array allocation from kmalloc caches (or large kmalloc) of sizes larger than the object size. However, as pointed out by Vlastimil Babka [2], this can waste an excessive amount of memory as slabs from large kmalloc sizes (e.g. kmalloc-8k) generally need obj_exts arrays much smaller than the object size.
Therefore, rather than bumping the size, let us take a different approach; disallow formation of cycles between kmalloc types when allocating obj_exts arrays. Currently, all obj_exts arrays are served from normal kmalloc caches. Cycles cannot be created if obj_exts arrays of normal kmalloc caches are served from a special kmalloc type that can never have obj_exts arrays.
To achieve this, create a new kmalloc type called KMALLOC_NO_OBJ_EXT. KMALLOC_NO_OBJ_EXT caches are created with SLAB_NO_OBJ_EXT flag when either 1) memory allocation profiling is not permanently disabled, or 2) kmalloc types with a priority higher than KMALLOC_CGROUP are aliased with KMALLOC_NORMAL.
Sheaf bootstrapping for KMALLOC_NO_OBJ_EXT caches now must be deferred because allocation of a barn can trigger obj_exts array allocation of normal kmalloc caches when the KMALLOC_NO_OBJ_EXT cache for that size is not ready yet. For simplicity, perform bootstrapping of sheaves for all kmalloc caches later.
Introduce a new slab alloc flag, SLAB_ALLOC_NO_OBJ_EXT, to prevent allocation of obj_exts arrays, and let kmalloc_slab() override the type to KMALLOC_NO_OBJ_EXT when specified. Note that kmalloc_type() remains unchanged because kmalloc_flags() bypasses the kmalloc fastpath.
Do not pass SLAB_ALLOC_NO_RECURSE to kmalloc_flags() in alloc_slab_obj_exts() and instead use SLAB_ALLOC_NO_OBJ_EXT only when the objects are allocated from normal kmalloc caches. While this prevents unbounded recursive allocation of obj_exts, it allows KMALLOC_NO_OBJ_EXT caches to have sheaves.
Since sheaf allocations specify SLAB_ALLOC_NO_RECURSE that prevents allocation of both sheaves and obj_exts arrays, the recursion depth is bounded.
obj_exts arrays for non-kmalloc-normal caches can now have a valid tag. Do not call mark_obj_codetag_empty() when freeing an obj_exts array to avoid false warnings. KMALLOC_NO_OBJ_EXT don't need this as they never allocate those arrays.
[[email protected]: Backport notes:
- Fix a minor conflict due to missing partitioned kmalloc caches in 6.18.
- Use __GFP_NO_OBJ_EXT instead of SLAB_ALLOC_NO_OBJ_EXT since slab's internal alloc_flags do not exist in 6.18.
- Deferring sheaf bootstrapping for kmalloc caches is not applied as they don't have sheaves in 6.18.
- Adjust the comment for SLAB_NO_OBJ_EXT, like in the commit 982e31382d9a ("mm/slab: decouple SLAB_NO_SHEAVES from SLAB_NO_OBJ_EXT"). The rest of that commit is a no-op in 6.18 as kmalloc caches don't have sheaves and thus only adjust the comment.
- Apply the __GFP_NO_OBJ_EXT flag to the !allow_spin path in alloc_slab_obj_exts(). ]
--- include/linux/slab.h | 8 ++++- mm/slab.h | 28 ++++++++++++++-- mm/slab_common.c | 13 ++++++++ mm/slub.c | 76 ++++++++++++++------------------------------ 4 files changed, 70 insertions(+), 55 deletions(-)
include/linux/slab.h +7 -1
@@ -238,7 +238,7 @@ enum _slab_flag_bits {#endif #define SLAB_TEMPORARY SLAB_RECLAIM_ACCOUNT/* Objects are short-lived */ -/* Slab created using create_boot_cache */ +/* Slab caches without obj_exts array */ #ifdef CONFIG_SLAB_OBJ_EXT #define SLAB_NO_OBJ_EXT __SLAB_FLAG_BIT(_SLAB_NO_OBJ_EXT)#else
@@ -641,6 +641,9 @@ enum kmalloc_cache_type {#endif #ifndef CONFIG_MEMCG KMALLOC_CGROUP = KMALLOC_NORMAL, +#endif +#ifndef CONFIG_SLAB_OBJ_EXT +KMALLOC_NO_OBJ_EXT =KMALLOC_NORMAL , #endifKMALLOC_RANDOM_START =KMALLOC_NORMAL , KMALLOC_RANDOM_END = KMALLOC_RANDOM_START + RANDOM_KMALLOC_CACHES_NR,
@@ -654,6 +657,9 @@ enum kmalloc_cache_type {#endif #ifdef CONFIG_MEMCG KMALLOC_CGROUP, +#endif +#ifdef CONFIG_SLAB_OBJ_EXT +KMALLOC_NO_OBJ_EXT , #endifNR_KMALLOC_TYPES };
mm/slab.h +26 -2
@@ -394,9 +394,13 @@ static inline struct kmem_cache * kmalloc_slab(size_t size, kmem_buckets *b, gfp_t flags, unsigned long caller) { unsigned int index; +enum kmalloc_cache_type type =kmalloc_type (flags, caller); + +if (flags & __GFP_NO_OBJ_EXT) + type =KMALLOC_NO_OBJ_EXT ;if (!b) - b = &kmalloc_caches[kmalloc_type (flags, caller)]; + b = &kmalloc_caches[type];if (size <=192 ) index = kmalloc_size_index[size_index_elem (size)];else
@@ -435,7 +439,8 @@ static inline bool is_kmalloc_normal(struct kmem_cache *s) {if (!is_kmalloc_cache (s))return false; -return !(s->flags & (SLAB_CACHE_DMA |SLAB_ACCOUNT |SLAB_RECLAIM_ACCOUNT )); + +return !(s->flags & (SLAB_CACHE_DMA |SLAB_ACCOUNT |SLAB_RECLAIM_ACCOUNT |SLAB_NO_OBJ_EXT )); }bool __kfree_rcu_sheaf (struct kmem_cache *s,void *obj);
@@ -520,6 +525,25 @@ bool slab_in_kunit_test(void);static inline bool slab_in_kunit_test (void ) {return false; }#endif +/* +* Return true if KMALLOC_NORMAL caches may need obj_exts arrays. +* +* Memory allocation profiling requires obj_exts for all caches. +* Memcg usually doesn't need them for normal kmalloc caches, but kmalloc types +* with a priority higher than KMALLOC_CGROUP can be aliased with KMALLOC_NORMAL. +*/ +static inline bool need_kmalloc_no_objext (void ) +{ +if (!mem_alloc_profiling_permanently_disabled ()) +return true; + +if (!mem_cgroup_kmem_disabled () && + (KMALLOC_NORMAL ==KMALLOC_RECLAIM )) +return true; + +return false; +} +#ifdef CONFIG_SLAB_OBJ_EXT /*
mm/slab_common.c +13 -0
@@ -803,6 +803,12 @@ EXPORT_SYMBOL(kmalloc_size_roundup);#define KMALLOC_RANDOM_NAME (N , sz)#endif +#ifdef CONFIG_SLAB_OBJ_EXT +#define KMALLOC_NO_OBJ_EXT_NAME (sz) .name[KMALLOC_NO_OBJ_EXT] = "kmalloc-no-objext-" #sz, +#else +#define KMALLOC_NO_OBJ_EXT_NAME (sz) +#endif +#define INIT_KMALLOC_INFO (__size, __short_size) \ { \ .name[KMALLOC_NORMAL] = "kmalloc-" #__short_size, \
@@ -810,6 +816,7 @@ EXPORT_SYMBOL(kmalloc_size_roundup);KMALLOC_CGROUP_NAME (__short_size) \KMALLOC_DMA_NAME (__short_size ) \KMALLOC_RANDOM_NAME (RANDOM_KMALLOC_CACHES_NR , __short_size) \ +KMALLOC_NO_OBJ_EXT_NAME (__short_size) \ .size = __size, \ }
@@ -917,6 +924,12 @@ new_kmalloc_cache(int idx, enum kmalloc_cache_type type)return ; } flags |=SLAB_ACCOUNT ; + }else if (IS_ENABLED (CONFIG_SLAB_OBJ_EXT ) && type ==KMALLOC_NO_OBJ_EXT ) { +if (!need_kmalloc_no_objext ()) { + kmalloc_caches[type][idx] = kmalloc_caches[KMALLOC_NORMAL ][idx]; +return ; + } + flags |=SLAB_NO_OBJ_EXT |SLAB_NO_MERGE ; }else if (IS_ENABLED (CONFIG_ZONE_DMA ) && (type ==KMALLOC_DMA )) { flags |=SLAB_CACHE_DMA ; }
mm/slub.c +24 -52
115 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 13/396 thunderbolt: Prevent XDomain delayed work use-after-free on disconnect
In reply to Greg Kroah-Hartman6.18-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
@@ -785,9 +785,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 :
@@ -800,8 +804,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 ;
@@ -829,9 +837,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 );
@@ -2074,6 +2086,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);
@@ -2484,8 +2500,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
@@ -209,6 +209,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
@@ -257,6 +259,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 14/396 pinctrl: qcom: Unconditionally mark gpio as wakeup enable
In reply to Greg Kroah-Hartman6.18-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
@@ -1226,12 +1226,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);
@@ -1259,7 +1259,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 15/396 pinctrl: qcom: sc8280xp: Add missing wakeup entries for GPIO143/151
In reply to Greg Kroah-Hartman6.18-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 16/396 dmaengine: sun6i-dma: Fix reclaim descriptors while terminating DMA
In reply to Greg Kroah-Hartman6.18-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
@@ -935,16 +935,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 17/396 dmaengine: idxd: fix fdev setup failure cleanup in idxd_cdev_open()
In reply to Greg Kroah-Hartman6.18-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
@@ -288,6 +288,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 ) {
@@ -301,13 +302,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 18/396 iommu/arm-smmu-v3-iommufd: Require exactly one Stream ID for a vDEVICE
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolin Chen <[email protected]>
[ Upstream commit c3b8ee84a965058b41275069d4696f37a8b14bf6 ]
arm_vsmmu_vsid_to_sid() maps a guest's vSID to a single physical Stream ID taken from master->streams[0], assuming a device has exactly one stream. A device with several streams gets only its first one mapped, so a guest vSID invalidation cannot reach the others' ATC and IOTLB entries; a device with none makes master->streams a ZERO_SIZE_PTR, read out of bounds.
Add an arm_vsmmu_vdevice_init() op to reject the vDEVICE with -EOPNOTSUPP when master->num_streams is not one, rather than mapping it silently.
--- .../iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c +15 -0
@@ -285,6 +285,20 @@ static int arm_vsmmu_vsid_to_sid(struct arm_vsmmu *vsmmu, u32 vsid, u32 *sid)return ret; } +static int arm_vsmmu_vdevice_init (struct iommufd_vdevice *vdev) +{ +struct device *dev =iommufd_vdevice_to_device (vdev); +struct arm_smmu_master *master =dev_iommu_priv_get (dev); + +/* +* arm_vsmmu_vsid_to_sid() maps a vSID to master->streams[0] alone, so +* more streams would leave the rest stale and none reads out of bounds. +*/ +if (master->num_streams !=1 ) +return -EOPNOTSUPP ; +return 0 ; +} +/* This is basically iommu_viommu_arm_smmuv3_invalidate in u64 for conversion */ struct arm_vsmmu_invalidation_cmd { union {
@@ -391,6 +405,7 @@ int arm_vsmmu_cache_invalidate(struct iommufd_viommu *viommu,static const struct iommufd_viommu_ops arm_vsmmu_ops = { .alloc_domain_nested = arm_vsmmu_alloc_domain_nested, .cache_invalidate = arm_vsmmu_cache_invalidate, + .vdevice_init = arm_vsmmu_vdevice_init, }; size_t arm_smmu_get_viommu_size(struct device *dev,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 19/396 gpio: sloppy-logic-analyzer: Fix memory leak in gpio_la_poll_probe()
In reply to Greg Kroah-Hartman6.18-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 20/396 selftests/lkdtm: rename STACKLEAK_ERASING to KSTACK_ERASE
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haofeng Li <[email protected]>
[ Upstream commit b3a7aa9c0020ae549a0d4964867ff66d2bd61709 ]
Commit 57fbad15c2ee ("stackleak: Rename STACKLEAK to KSTACK_ERASE") renamed the LKDTM crash type and selftest configuration but missed the entry in tests.txt.
As a result, the selftest generates STACKLEAK_ERASING.sh, which run.sh skips because the LKDTM DIRECT trigger only exposes KSTACK_ERASE. Rename the test entry so the generated runner uses the registered crash type.
--- tools/testing/selftests/lkdtm/tests.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/lkdtm/tests.txt +1 -1
@@ -74,7 +74,7 @@ USERCOPY_STACK_FRAME_TO USERCOPY_STACK_FRAME_FROM USERCOPY_STACK_BEYOND USERCOPY_KERNEL -STACKLEAK_ERASING OK: the rest of the thread stack is properly erased +KSTACK_ERASE OK: the rest of the thread stack is properly erased CFI_FORWARD_PROTO CFI_BACKWARD call trace:|ok: control flow unchanged FORTIFY_STRSCPY detected buffer overflow
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 21/396 selftests/seccomp: Fix pointer type mismatch build error
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuan-Ying Lee <[email protected]>
[ Upstream commit 3421b9b056a6576d0ebac1030eafb48ad0544092 ]
We hit the following build error while running the seccomp selftests in our testing.
CC seccomp_bpfseccomp_bpf.c: In function ‘UPROBE_setup’:
seccomp_bpf.c:5175:74: error: pointer type mismatch in conditional expression [-Wincompatible-pointer-types] 5175 | offset = get_uprobe_offset(variant->uretprobe ? probed_uretprobe : probed_uprobe); | ^
seccomp_bpf.c:5175:57: note: first expression has type ‘int (*)(void)’
5175 | offset = get_uprobe_offset(variant->uretprobe ? probed_uretprobe : probed_uprobe); | ^~~~~~~~~~~~~~~~
seccomp_bpf.c:5175:76: note: second expression has type ‘int (__attribute__((nocf_check)) *)(void)’ 5175 | offset = get_uprobe_offset(variant->uretprobe ? probed_uretprobe : probed_uprobe); | ^~~~~~~~~~~~~
get_uprobe_offset() takes a 'const void *' argument, so cast both operands to 'void *'.
--- tools/testing/selftests/seccomp/seccomp_bpf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
tools/testing/selftests/seccomp/seccomp_bpf.c +2 -1
@@ -5172,7 +5172,8 @@ FIXTURE_SETUP(UPROBE)ASSERT_GE (bit,0 ); } - offset =get_uprobe_offset (variant->uretprobe ? probed_uretprobe : probed_uprobe); + offset =get_uprobe_offset (variant->uretprobe ? (void *)probed_uretprobe + : (void *)probed_uprobe);ASSERT_GE (offset,0 );if (variant->uretprobe)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 22/396 ata: sata_mv: accept 1 or 2 resources in platform probe
In reply to Greg Kroah-Hartman6.18-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 23/396 ata: ahci_ceva: fix error paths in ceva_ahci_platform_enable_resources()
In reply to Greg Kroah-Hartman6.18-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 24/396 phy: qcom: m31-eusb2: Fix return value of init call
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krishna Kurapati <[email protected]>
[ Upstream commit 361f533a2dce2c2841fe4dc0c9d85a67117edf95 ]
The init call currently returns success irrespective of any failures during repeater init or clock enablement. Return appropriate error value in the init call failure path.
--- drivers/phy/qualcomm/phy-qcom-m31-eusb2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/phy/qualcomm/phy-qcom-m31-eusb2.c +1 -1
@@ -221,7 +221,7 @@ static int m31eusb2_phy_init(struct phy *uphy) disable_vreg:regulator_bulk_disable (M31_EUSB_NUM_VREGS , phy->vregs); -return 0 ; +return ret; }static int m31eusb2_phy_exit (struct phy *uphy)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 25/396 ASoC: max98095: fix missing IS_ERR() before PTR_ERR() on mclk lookup
In reply to Greg Kroah-Hartman6.18-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 26/396 ASoC: max98090: fix missing IS_ERR() before PTR_ERR() on mclk lookup
In reply to Greg Kroah-Hartman6.18-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
@@ -2390,8 +2390,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 27/396 of: reserved_mem: prevent OOB when too many dynamic regions are defined
In reply to Greg Kroah-Hartman6.18-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
@@ -326,6 +326,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
@@ -333,10 +334,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 28/396 btrfs: fix leaking BTRFS_FS_STATE_REMOUNTING flag
In reply to Greg Kroah-Hartman6.18-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
@@ -1518,12 +1518,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 29/396 btrfs: zoned: fix deadlock between metadata writeback and transaction commit
In reply to Greg Kroah-Hartman6.18-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
@@ -2167,7 +2167,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 30/396 btrfs: zoned: reset meta_write_pointer on zone reset
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Thumshirn <[email protected]>
[ Upstream commit 5fabb1cf25d723274009d7b759545fd59f230c9d ]
btrfs_reset_unused_block_groups() resets a block group's zone and sets alloc_offset back to 0 so the space can be reused, but it leaves meta_write_pointer pointing at the previous end of the zone.
Once the block group is reactivated and reused for metadata, newly allocated tree blocks live before that stale write pointer. btrfs_check_meta_write_pointer() then sees them behind the write pointer, so they can never be written out in sequential order: the dirty extent buffers are stranded and pin their btree_inode folios until unmount.
Reset meta_write_pointer back to the start of the block group for metadata and system block groups.
--- fs/btrfs/zoned.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
fs/btrfs/zoned.c +11 -0
@@ -3171,6 +3171,17 @@ int btrfs_reset_unused_block_groups(struct btrfs_space_info *space_info, u64 num reclaimed = bg->alloc_offset; bg->zone_unusable = bg->length - bg->zone_capacity; bg->alloc_offset =0 ; +/* +* The zone was just reset to empty, so alloc_offset went back to +* the start of the zone. For metadata/system block groups the +* write pointer must follow it back to the start of the zone; +* otherwise it stays stale at the previous (finished) zone end, +* and metadata written into the reused zone would sit behind the +* write pointer, could never be written out in sequential order, +* and would be stranded (pinning its folio) until unmount. +*/ +if (bg->flags & (BTRFS_BLOCK_GROUP_METADATA |BTRFS_BLOCK_GROUP_SYSTEM )) + bg->meta_write_pointer = bg->start;/* * This holds because we currently reset fully used then freed * block group.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 31/396 btrfs: raid56: fix an incorrect csum skip during scrub
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
[ Upstream commit 330dcc553f282e8dc0b88c9495b4c296465364e1 ]
Commit 7425a2894019 ("btrfs: introduce btrfs_bio_for_each_block_all() helper") uses the new helper to replace the nested loop inside verify_bio_data_sectors(), which simplifies the code.
However that also changed the behavior of "continue" when a block has no data checksum.
Previously the "continue" would skip the old for() loop, which would also increase @total_sector_nr.
Now the "continue" will skip the new btrfs_bio_for_each_block_all() loop, which doesn't update @total_sector_nr.
This means if we hit a block that has no data checksum, we will skip all the remaining blocks no matter if they have data checksum. As @total_sector_nr will never be updated, and that test_bit() will always return false.
Fix it by increasing @total_sector_nr before calling "continue".
--- fs/btrfs/raid56.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/btrfs/raid56.c +3 -1
@@ -1583,8 +1583,10 @@ static void verify_bio_data_sectors(struct btrfs_raid_bio *rbio,int ret;/* No csum for this sector, skip to the next sector. */ -if (!test_bit (total_sector_nr, rbio->csum_bitmap)) +if (!test_bit (total_sector_nr, rbio->csum_bitmap)) { + total_sector_nr++;continue ; + } ret =btrfs_check_block_csum (fs_info, paddr, csum_buf, expected_csum);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 32/396 phy: zynqmp: fix clock error handling in xpsgtr_phy_init()
In reply to Greg Kroah-Hartman6.18-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 33/396 phy: zynqmp: fix runtime PM leak on probe allocation failure
In reply to Greg Kroah-Hartman6.18-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 34/396 netfilter: nf_conntrack_sip: widen NAT rewrite delta to s32 in sip_help_tcp()
In reply to Greg Kroah-Hartman6.18-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 35/396 drm/mediatek: Check CRTC state before freeing
In reply to Greg Kroah-Hartman6.18-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 36/396 arch/x86: mshyperv: Discover Confidential VMBus availability
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Roman Kisel <[email protected]>
[ Upstream commit 7c8b6c326d830ca5c6b95f390c703966e14167e6 ]
Confidential VMBus requires enabling paravisor SynIC, and the x86_64 guest has to inspect the Virtualization Stack (VS) CPUID leaf to see if Confidential VMBus is available. If it is, the guest shall enable the paravisor SynIC.
Read the relevant data from the VS CPUID leaf. Refactor the code to avoid repeating CPUID and add flags to the struct ms_hyperv_info. For ARM64, the flag for Confidential VMBus is not set which provides the desired behaviour for now as it is not available on ARM64 just yet. Once ARM64 CCA guests are supported, this flag will be set unconditionally when running such a guest.
Stable-dep-of: 8c7ab779c885 ("Drivers: hv: vmbus: Replace lockdep_hardirq_threaded() with lockdep annotation")
--- arch/x86/kernel/cpu/mshyperv.c | 28 +++++++++++++++------------- include/asm-generic/mshyperv.h | 2 ++ 2 files changed, 17 insertions(+), 13 deletions(-)
arch/x86/kernel/cpu/mshyperv.c +15 -13
@@ -440,7 +440,7 @@ EXPORT_SYMBOL_GPL(hv_get_hypervisor_version);static void __init ms_hyperv_init_platform (void ) { -int hv_max_functions_eax; +int hv_max_functions_eax, eax;#ifdef CONFIG_PARAVIRT pv_info.name ="Hyper-V" ;
@@ -475,6 +475,19 @@ static void __init ms_hyperv_init_platform(void)pr_info ("Hyper-V: running on a nested hypervisor\n" ); } +/* +* There is no check against the max function for HYPERV_CPUID_VIRT_STACK_* CPUID +* leaves as the hypervisor doesn't handle them. Even a nested root partition (L2 +* root) will not get them because the nested (L1) hypervisor filters them out. +* These are handled through intercept processing by the Windows Hyper-V stack +* or the paravisor. +*/ + eax =cpuid_eax (HYPERV_CPUID_VIRT_STACK_PROPERTIES ); + ms_hyperv.confidential_vmbus_available = + eax &HYPERV_VS_PROPERTIES_EAX_CONFIDENTIAL_VMBUS_AVAILABLE ; + ms_hyperv.msi_ext_dest_id = + eax &HYPERV_VS_PROPERTIES_EAX_EXTENDED_IOAPIC_RTE ; +if (ms_hyperv.features &HV_ACCESS_FREQUENCY_MSRS && ms_hyperv.misc_features &HV_FEATURE_FREQUENCY_MSRS_AVAILABLE ) { x86_platform.calibrate_tsc = hv_get_tsc_khz;
@@ -675,21 +688,10 @@ static bool __init ms_hyperv_x2apic_available(void)* pci-hyperv host bridge. * * Note: for a Hyper-V root partition, this will always return false. -* The hypervisor doesn't expose these HYPERV_CPUID_VIRT_STACK_* cpuids by -* default, they are implemented as intercepts by the Windows Hyper-V stack. -* Even a nested root partition (L2 root) will not get them because the -* nested (L1) hypervisor filters them out. */ static bool __init ms_hyperv_msi_ext_dest_id (void ) { -u32 eax; - - eax =cpuid_eax (HYPERV_CPUID_VIRT_STACK_INTERFACE ); -if (eax !=HYPERV_VS_INTERFACE_EAX_SIGNATURE ) -return false; - - eax =cpuid_eax (HYPERV_CPUID_VIRT_STACK_PROPERTIES ); -return eax &HYPERV_VS_PROPERTIES_EAX_EXTENDED_IOAPIC_RTE ; +return ms_hyperv.msi_ext_dest_id; }#ifdef CONFIG_AMD_MEM_ENCRYPT
include/asm-generic/mshyperv.h +2 -0
@@ -62,6 +62,8 @@ struct ms_hyperv_info { }; };u64 shared_gpa_boundary; +bool msi_ext_dest_id; +bool confidential_vmbus_available; };extern struct ms_hyperv_info ms_hyperv;extern bool hv_nested;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 37/396 Drivers: hv: Rename fields for SynIC message and event pages
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Roman Kisel <[email protected]>
[ Upstream commit 163224c189e8b679ce919aa64ccabb7a992ca2d1 ]
Confidential VMBus requires interacting with two SynICs -- one provided by the host hypervisor, and one provided by the paravisor. Each SynIC requires its own message and event pages.
Rename the existing host-accessible SynIC message and event pages with the "hyp_" prefix to clearly distinguish them from the paravisor ones. The field name is also changed in mshv_root.* for consistency.
No functional changes.
Stable-dep-of: 8c7ab779c885 ("Drivers: hv: vmbus: Replace lockdep_hardirq_threaded() with lockdep annotation")
--- drivers/hv/channel_mgmt.c | 6 ++-- drivers/hv/hv.c | 66 +++++++++++++++++++-------------------- drivers/hv/hyperv_vmbus.h | 4 +-- drivers/hv/mshv_root.h | 2 +- drivers/hv/mshv_synic.c | 6 ++-- drivers/hv/vmbus_drv.c | 6 ++-- 6 files changed, 45 insertions(+), 45 deletions(-)
drivers/hv/channel_mgmt.c +3 -3
@@ -844,14 +844,14 @@ static void vmbus_wait_for_unload(void) = per_cpu_ptr(hv_context.cpu_context, cpu);/* -* In a CoCo VM the synic_message_page is not allocated +* In a CoCo VM the hyp_synic_message_page is not allocated * in hv_synic_alloc(). Instead it is set/cleared in * hv_synic_enable_regs() and hv_synic_disable_regs() * such that it is set only when the CPU is online. If * not all present CPUs are online, the message page * might be NULL, so skip such CPUs. */ - page_addr = hv_cpu->synic_message_page; + page_addr = hv_cpu->hyp_synic_message_page;if (!page_addr)continue ;
@@ -892,7 +892,7 @@ static void vmbus_wait_for_unload(void)struct hv_per_cpu_context *hv_cpu =per_cpu_ptr (hv_context.cpu_context, cpu); - page_addr = hv_cpu->synic_message_page; + page_addr = hv_cpu->hyp_synic_message_page;if (!page_addr)continue ;
drivers/hv/hv.c +33 -33
158 lines not on this page · raw message
drivers/hv/hyperv_vmbus.h +2 -2
@@ -120,8 +120,8 @@ enum {* Per cpu state for channel handling */ struct hv_per_cpu_context { -void *synic_message_page; -void *synic_event_page; +void *hyp_synic_message_page; +void *hyp_synic_event_page;/* * The page is only used in hv_post_message() for a TDX VM (with the
drivers/hv/mshv_root.h +1 -1
@@ -169,7 +169,7 @@ struct mshv_girq_routing_table { };struct hv_synic_pages { -struct hv_message_page *synic_message_page; +struct hv_message_page *hyp_synic_message_page;struct hv_synic_event_flags_page *synic_event_flags_page;struct hv_synic_event_ring_page *synic_event_ring_page; };
drivers/hv/mshv_synic.c +3 -3
@@ -399,7 +399,7 @@ mshv_intercept_isr(struct hv_message *msg)void mshv_isr (void ) {struct hv_synic_pages *spages =this_cpu_ptr (mshv_root.synic_pages); -struct hv_message_page **msg_page = &spages->synic_message_page; +struct hv_message_page **msg_page = &spages->hyp_synic_message_page;struct hv_message *msg;bool handled;
@@ -461,7 +461,7 @@ int mshv_synic_init(unsigned int cpu)#endif union hv_synic_scontrol sctrl;struct hv_synic_pages *spages =this_cpu_ptr (mshv_root.synic_pages); -struct hv_message_page **msg_page = &spages->synic_message_page; +struct hv_message_page **msg_page = &spages->hyp_synic_message_page;struct hv_synic_event_flags_page **event_flags_page = &spages->synic_event_flags_page; struct hv_synic_event_ring_page **event_ring_page =
@@ -555,7 +555,7 @@ int mshv_synic_cleanup(unsigned int cpu)union hv_synic_sirbp sirbp;union hv_synic_scontrol sctrl;struct hv_synic_pages *spages =this_cpu_ptr (mshv_root.synic_pages); -struct hv_message_page **msg_page = &spages->synic_message_page; +struct hv_message_page **msg_page = &spages->hyp_synic_message_page;struct hv_synic_event_flags_page **event_flags_page = &spages->synic_event_flags_page; struct hv_synic_event_ring_page **event_ring_page =
drivers/hv/vmbus_drv.c +3 -3
@@ -1048,7 +1048,7 @@ static void vmbus_onmessage_work(struct work_struct *work)void vmbus_on_msg_dpc (unsigned long data) {struct hv_per_cpu_context *hv_cpu = (void *)data; -void *page_addr = hv_cpu->synic_message_page; +void *page_addr = hv_cpu->hyp_synic_message_page;struct hv_message msg_copy, *msg = (struct hv_message *)page_addr +VMBUS_MESSAGE_SINT ;struct vmbus_channel_message_header *hdr;
@@ -1232,7 +1232,7 @@ static void vmbus_chan_sched(struct hv_per_cpu_context *hv_cpu)* The event page can be directly checked to get the id of * the channel that has the interrupt pending. */ -void *page_addr = hv_cpu->synic_event_page; +void *page_addr = hv_cpu->hyp_synic_event_page;union hv_synic_event_flags *event = (union hv_synic_event_flags *)page_addr +VMBUS_MESSAGE_SINT ;
@@ -1315,7 +1315,7 @@ static void __vmbus_isr(void)vmbus_chan_sched (hv_cpu); - page_addr = hv_cpu->synic_message_page; + page_addr = hv_cpu->hyp_synic_message_page; msg = (struct hv_message *)page_addr +VMBUS_MESSAGE_SINT ;/* Check if there are actual msgs to be processed */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 38/396 Drivers: hv: Allocate the paravisor SynIC pages when required
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Roman Kisel <[email protected]>
[ Upstream commit 226494e5ee4eb0bae4fc7b525505828271d5047e ]
Confidential VMBus requires interacting with two SynICs -- one provided by the host hypervisor, and one provided by the paravisor. Each SynIC requires its own message and event pages.
Refactor and extend the existing code to add allocating and freeing the message and event pages for the paravisor SynIC when it is present.
Stable-dep-of: 8c7ab779c885 ("Drivers: hv: vmbus: Replace lockdep_hardirq_threaded() with lockdep annotation")
--- drivers/hv/hv.c | 184 +++++++++++++++++++------------------- drivers/hv/hyperv_vmbus.h | 18 ++++ 2 files changed, 112 insertions(+), 90 deletions(-)
drivers/hv/hv.c +94 -90
@@ -96,10 +96,70 @@ int hv_post_message(union hv_connection_id connection_id,return hv_result (status); } +static int hv_alloc_page (void **page,bool decrypt,const char *note) +{ +int ret =0 ; + +/* +* After the page changes its encryption status, its contents might +* appear scrambled on some hardware. Thus `get_zeroed_page` would +* zero the page out in vain, so do that explicitly exactly once. +* +* By default, the page is allocated encrypted in a CoCo VM. +*/ + *page = (void *)__get_free_page (GFP_KERNEL ); +if (!*page) +return -ENOMEM ; + +if (decrypt) + ret =set_memory_decrypted ((unsigned long )*page,1 ); +if (ret) + goto failed; + +memset (*page,0 ,PAGE_SIZE ); +return 0 ; + +failed: +/* +* Report the failure but don't put the page back on the free list as +* its encryption status is unknown. +*/ +pr_err ("allocation failed for %s page, error %d, decrypted %d\n" , + note, ret, decrypt); + *page =NULL ; +return ret; +} + +static int hv_free_page (void **page,bool encrypt,const char *note) +{ +int ret =0 ; + +if (!*page) +return 0 ; + +if (encrypt) + ret =set_memory_encrypted ((unsigned long )*page,1 ); + +/* +* In the case of the failure, the page is leaked. Something is wrong, +* prefer to lose the page with the unknown encryption status and stay afloat. +*/ +if (ret) +pr_err ("deallocation failed for %s page, error %d, encrypt %d\n" , + note, ret, encrypt); +else +free_page ((unsigned long )*page); + + *page =NULL ; + +return ret; +} +int hv_synic_alloc (void ) {int cpu, ret = -ENOMEM ;struct hv_per_cpu_context *hv_cpu; +const bool decrypt = !vmbus_is_confidential ();/* * First, zero all per-cpu memory areas so hv_synic_free() can
@@ -125,73 +185,37 @@ int hv_synic_alloc(void) vmbus_on_msg_dpc, (unsigned long)hv_cpu);if (ms_hyperv.paravisor_present &&hv_isolation_type_tdx ()) { - hv_cpu->post_msg_page = (void *)get_zeroed_page (GFP_ATOMIC ); -if (!hv_cpu->post_msg_page) { -pr_err ("Unable to allocate post msg page\n" ); + ret =hv_alloc_page (&hv_cpu->post_msg_page, + decrypt,"post msg" ); +if (ret) goto err; - } - - ret =set_memory_decrypted ((unsigned long )hv_cpu->post_msg_page,1 ); -if (ret) { -pr_err ("Failed to decrypt post msg page: %d\n" , ret); -/* Just leak the page, as it's unsafe to free the page. */ - hv_cpu->post_msg_page =NULL ; - goto err; - } - -memset (hv_cpu->post_msg_page,0 ,PAGE_SIZE ); }/* -* Synic message and event pages are allocated by paravisor. -* Skip these pages allocation here. +* If these SynIC pages are not allocated, SIEF and SIM pages +* are configured using what the root partition or the paravisor +* provides upon reading the SIEFP and SIMP registers. */ if (!ms_hyperv.paravisor_present && !hv_root_partition ()) { - hv_cpu->hyp_synic_message_page = - (void *)get_zeroed_page (GFP_ATOMIC ); -if (!hv_cpu->hyp_synic_message_page) { -pr_err ("Unable to allocate SYNIC message page\n" ); + ret =hv_alloc_page (&hv_cpu->hyp_synic_message_page, + decrypt,"hypervisor SynIC msg" ); +if (ret) goto err; - } - - hv_cpu->hyp_synic_event_page = - (void *)get_zeroed_page (GFP_ATOMIC ); -if (!hv_cpu->hyp_synic_event_page) { -pr_err ("Unable to allocate SYNIC event page\n" ); - -free_page ((unsigned long )hv_cpu->hyp_synic_message_page); - hv_cpu->hyp_synic_message_page =NULL ; + ret =hv_alloc_page (&hv_cpu->hyp_synic_event_page, + decrypt,"hypervisor SynIC event" ); +if (ret) goto err; - } } -if (!ms_hyperv.paravisor_present && - (hv_isolation_type_snp () ||hv_isolation_type_tdx ())) { - ret =set_memory_decrypted ((unsigned long ) - hv_cpu->hyp_synic_message_page,1 ); -if (ret) { -pr_err ("Failed to decrypt SYNIC msg page: %d\n" , ret); - hv_cpu->hyp_synic_message_page =NULL ; - -/* -* Free the event page here so that hv_synic_free() -* won't later try to re-encrypt it. -*/ -free_page ((unsigned long )hv_cpu->hyp_synic_event_page); - hv_cpu->hyp_synic_event_page =NULL ; +if (vmbus_is_confidential ()) { + ret =hv_alloc_page (&hv_cpu->para_synic_message_page, + false,"paravisor SynIC msg" ); +if (ret) goto err; - } - - ret =set_memory_decrypted ((unsigned long ) - hv_cpu->hyp_synic_event_page,1 ); -if (ret) { -pr_err ("Failed to decrypt SYNIC event page: %d\n" , ret); - hv_cpu->hyp_synic_event_page =NULL ; + ret =hv_alloc_page (&hv_cpu->para_synic_event_page, + false,"paravisor SynIC event" ); +if (ret) goto err; - } - -memset (hv_cpu->hyp_synic_message_page,0 ,PAGE_SIZE ); -memset (hv_cpu->hyp_synic_event_page,0 ,PAGE_SIZE ); } }
@@ -207,48 +231,28 @@ int hv_synic_alloc(void)void hv_synic_free (void ) { -int cpu, ret; +int cpu; +const bool encrypt = !vmbus_is_confidential ();for_each_present_cpu (cpu) {struct hv_per_cpu_context *hv_cpu =per_cpu_ptr (hv_context.cpu_context, cpu); -/* It's better to leak the page if the encryption fails. */ -if (ms_hyperv.paravisor_present &&hv_isolation_type_tdx ()) { -if (hv_cpu->post_msg_page) { - ret =set_memory_encrypted ((unsigned long ) - hv_cpu->post_msg_page,1 ); -if (ret) { -pr_err ("Failed to encrypt post msg page: %d\n" , ret); - hv_cpu->post_msg_page =NULL ; - } - } +if (ms_hyperv.paravisor_present &&hv_isolation_type_tdx ()) +hv_free_page (&hv_cpu->post_msg_page, + encrypt,"post msg" ); +if (!ms_hyperv.paravisor_present && !hv_root_partition ()) { +hv_free_page (&hv_cpu->hyp_synic_event_page, + encrypt,"hypervisor SynIC event" ); +hv_free_page (&hv_cpu->hyp_synic_message_page, + encrypt,"hypervisor SynIC msg" ); } - -if (!ms_hyperv.paravisor_present && - (hv_isolation_type_snp () ||hv_isolation_type_tdx ())) { -if (hv_cpu->hyp_synic_message_page) { - ret =set_memory_encrypted ((unsigned long ) - hv_cpu->hyp_synic_message_page,1 ); -if (ret) { -pr_err ("Failed to encrypt SYNIC msg page: %d\n" , ret); - hv_cpu->hyp_synic_message_page =NULL ; - } - } - -if (hv_cpu->hyp_synic_event_page) { - ret =set_memory_encrypted ((unsigned long ) - hv_cpu->hyp_synic_event_page,1 ); -if (ret) { -pr_err ("Failed to encrypt SYNIC event page: %d\n" , ret); - hv_cpu->hyp_synic_event_page =NULL ; - } - } +if (vmbus_is_confidential ()) { +hv_free_page (&hv_cpu->para_synic_event_page, + false,"paravisor SynIC event" ); +hv_free_page (&hv_cpu->para_synic_message_page, + false,"paravisor SynIC msg" ); } - -free_page ((unsigned long )hv_cpu->post_msg_page); -free_page ((unsigned long )hv_cpu->hyp_synic_event_page); -free_page ((unsigned long )hv_cpu->hyp_synic_message_page); }kfree (hv_context.hv_numa_map);
drivers/hv/hyperv_vmbus.h +18 -0
@@ -120,8 +120,26 @@ enum {* Per cpu state for channel handling */ struct hv_per_cpu_context { +/* +* SynIC pages for communicating with the host. +* +* These pages are accessible to the host partition and the hypervisor. +* They may be used for exchanging data with the host partition and the +* hypervisor even when they aren't trusted yet the guest partition +* must be prepared to handle the malicious behavior. +*/ void *hyp_synic_message_page;void *hyp_synic_event_page; +/* +* SynIC pages for communicating with the paravisor. +* +* These pages may be accessed from within the guest partition only in +* CoCo VMs. Neither the host partition nor the hypervisor can access +* these pages in that case; they are used for exchanging data with the +* paravisor. +*/ +void *para_synic_message_page; +void *para_synic_event_page;/* * The page is only used in hv_post_message() for a TDX VM (with the
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 39/396 Drivers: hv: vmbus: Replace lockdep_hardirq_threaded() with lockdep annotation
In reply to Greg Kroah-Hartman6.18-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
@@ -1372,8 +1372,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 40/396 mshv: Fix duplicate GSI detection for GSI 0
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stanislav Kinsburskii <[email protected]>
[ Upstream commit 649dd135491945afa544351e3e6d4a727de87020 ]
The duplicate routing entry check in mshv_update_routing_table() uses guest_irq_num != 0 to detect whether a GSI slot is already occupied. This fails for GSI 0 because its guest_irq_num is 0 both when the slot is unused (zero-initialized) and when legitimately assigned. As a result, duplicate entries for GSI 0 are silently accepted, with the second entry overwriting the first — corrupting the routing table without any error reported to userspace.
While GSI 0 (legacy timer) is unlikely to appear in MSI-based routing in practice, the check is semantically wrong — it conflates "uninitialized" with "GSI number 0." Use girq_entry_valid instead, which is explicitly set to true when an entry is populated and remains zero for unused slots regardless of the GSI number.
--- drivers/hv/mshv_irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/hv/mshv_irq.c +1 -1
@@ -51,7 +51,7 @@ int mshv_update_routing_table(struct mshv_partition *partition,/* * Allow only one to one mapping between GSI and MSI routing. */ -if (girq->guest_irq_num !=0 ) { +if (girq->girq_entry_valid) { r = -EINVAL ; goto out; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 41/396 mshv: Fix sleeping under spinlock in mshv_portid_alloc
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stanislav Kinsburskii <[email protected]>
[ Upstream commit a9708e550d11a53b22d932cdbfaa10c26346a2d0 ]
idr_alloc() is called with GFP_KERNEL inside idr_lock(), which holds a spinlock. GFP_KERNEL allows the allocator to sleep, triggering a sleeping-while-atomic bug.
Fix by using idr_preload(GFP_KERNEL) before taking the lock to pre-allocate memory in a sleepable context, then idr_alloc() with GFP_NOWAIT inside the spinlock-protected section.
--- drivers/hv/mshv_portid_table.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/hv/mshv_portid_table.c +4 -2
@@ -40,12 +40,14 @@ mshv_port_table_fini(void)int mshv_portid_alloc (struct port_table_info *info) { -int ret =0 ; +int ret; +idr_preload (GFP_KERNEL );idr_lock (&port_table_idr); ret =idr_alloc (&port_table_idr, info,PORTID_MIN , -PORTID_MAX ,GFP_KERNEL ); +PORTID_MAX ,GFP_NOWAIT );idr_unlock (&port_table_idr); +idr_preload_end ();return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 42/396 KVM: arm64: Reject guest_memfd memslots when the VM has MTE
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexandru Elisei <[email protected]>
[ Upstream commit 679d7201c1f09e37fa1c12ce28d84079c17fc87f ]
The user cannot use MTE on VMAs created by mapping a guest_memfd file, as arch_calc_vm_flag_bits() does not set VM_MTE_ALLOWED.
When creating a guest_memfd backed memslot, kvm_arch_prepare_memory_region() rejects the memslot if MTE is enabled for the VM and if guest_memfd has been mapped in a VMA that intersects the memslot.
However, the documentation for KVM_SET_USER_MEMORY_REGION2 explicitly states that the only condition for userspace_addr is for it to be a legal userspace address, but the mapping is not required to be valid nor populated at memslot creation.
If userspace sets userspace_addr to an address that hasn't been mapped, or if userspace_addr belongs to a VMA that isn't backed by the guest_memfd file, or if the VMA doesn't intersect the memslot, memslot creation is successful and KVM ends up with a VM with MTE and guest_memfd-backed memslots.
The same happens if the order is reversed: when userspace enables MTE, KVM does not check if memslots backed by guest_memfd are already present.
Fix both issues by rejecting guest_memfd-backed memslots when MTE is enabled, and by rejecting MTE when guest_memfd-backed memslots are already present.
--- Documentation/virt/kvm/api.rst | 6 ++++++ arch/arm64/kvm/arm.c | 25 +++++++++++++++++++------ arch/arm64/kvm/mmu.c | 4 ++++ 3 files changed, 29 insertions(+), 6 deletions(-)
Documentation/virt/kvm/api.rst +6 -0
@@ -8259,6 +8259,12 @@ When this capability is enabled all memory in memslots must be mapped as attempts to create a memslot with an invalid mmap will result in an -EINVAL return. +``guest_memfd``, even though it is an anonymous file, is not supported with MTE. +Attempting to create a memslot backed by ``guest_memfd`` when the MTE capability +is enabled, or attempting to enable the MTE capability after +``guest_memfd``-backed memslots have been created, will result in an -EINVAL +return. + When enabled the VMM may make use of the ``KVM_ARM_MTE_COPY_TAGS`` ioctl to perform a bulk copy of tags to/from the guest.
arch/arm64/kvm/arm.c +19 -6
@@ -96,14 +96,27 @@ int kvm_vm_ioctl_enable_cap(struct kvm *kvm,set_bit (KVM_ARCH_FLAG_RETURN_NISV_IO_ABORT_TO_USER , &kvm->arch.flags);break ; -case KVM_CAP_ARM_MTE : -mutex_lock (&kvm->lock); -if (system_supports_mte () && !kvm->created_vcpus) { - r =0 ; -set_bit (KVM_ARCH_FLAG_MTE_ENABLED , &kvm->arch.flags); +case KVM_CAP_ARM_MTE : { +struct kvm_memory_slot *memslot; +int bkt; + +guard (mutex)(&kvm->lock); +if (!system_supports_mte () || kvm->created_vcpus) +break ; + + r =0 ; +guard (mutex)(&kvm->slots_lock); +kvm_for_each_memslot (memslot, bkt,kvm_memslots (kvm)) { +if (kvm_slot_has_gmem (memslot)) { + r = -EINVAL ; +break ; + } } -mutex_unlock (&kvm->lock); +if (r ==0 ) +set_bit (KVM_ARCH_FLAG_MTE_ENABLED , &kvm->arch.flags);break ; + + }case KVM_CAP_ARM_SYSTEM_SUSPEND : r =0 ;set_bit (KVM_ARCH_FLAG_SYSTEM_SUSPEND_ENABLED , &kvm->arch.flags);
arch/arm64/kvm/mmu.c +4 -0
@@ -2323,6 +2323,10 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,if (kvm_slot_has_gmem (new) && !kvm_memslot_is_gmem_only (new))return -EINVAL ; +/* guest_memfd is incompatible with MTE. */ +if (kvm_slot_has_gmem (new) &&kvm_has_mte (kvm)) +return -EINVAL ; + hva = new->userspace_addr; reg_end = hva + (new->npages <<PAGE_SHIFT );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 43/396 KEYS: trusted: dcp: fix key_len validation and calc_blob_len() return type
In reply to Greg Kroah-Hartman6.18-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 44/396 keys: fix out-of-bounds read in keyring_get_key_chunk()
In reply to Greg Kroah-Hartman6.18-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 45/396 keys: make keyring key-chunk byte order agree with keyring_diff_objects()
In reply to Greg Kroah-Hartman6.18-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 46/396 assoc_array: trim the final shortcut word using the current chunk end
In reply to Greg Kroah-Hartman6.18-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 47/396 netfilter: nf_tables: make nft_object rhltable per table
In reply to Greg Kroah-Hartman6.18-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
@@ -1288,6 +1288,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
@@ -1307,6 +1308,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;
@@ -1394,7 +1396,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
@@ -44,8 +44,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 *);
@@ -1600,6 +1598,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);
@@ -1618,6 +1620,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);
@@ -1784,6 +1788,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);
@@ -7957,7 +7962,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) {
@@ -7973,7 +7978,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;
@@ -8252,7 +8257,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;
@@ -8437,8 +8442,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;
@@ -10270,9 +10275,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); }
@@ -10960,7 +10965,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 ;
@@ -11251,7 +11256,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 :
@@ -11877,7 +11882,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); }
@@ -12059,10 +12064,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;
@@ -12085,8 +12086,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 ();
@@ -12108,7 +12107,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 48/396 netfilter: xt_hashlimit: validate hashtable supports XT_HASHLIMIT_RATE_MATCH
In reply to Greg Kroah-Hartman6.18-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
@@ -117,6 +117,7 @@ struct xt_hashlimit_htable {refcount_t use;u_int8_t family;bool rnd_initialized; +bool ratematch;struct hashlimit_cfg3 cfg;/* config */
@@ -323,6 +324,7 @@ static int htable_create(struct net *net, struct hashlimit_cfg3 *cfg,kvfree (hinfo);return -ENOMEM ; } + hinfo->ratematch = !!(cfg->mode &XT_HASHLIMIT_RATE_MATCH );spin_lock_init (&hinfo->lock);switch (revision) {
@@ -870,7 +872,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 ;
@@ -903,6 +908,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 49/396 ipvs: fix the checksum validations
In reply to Greg Kroah-Hartman6.18-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
@@ -1724,8 +1726,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 };
@@ -1751,6 +1751,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 50/396 ipvs: fix places with wrong packet offsets
In reply to Greg Kroah-Hartman6.18-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
@@ -1639,8 +1639,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
@@ -1653,8 +1654,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
@@ -1719,11 +1721,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 51/396 ipvs: do not mangle ICMP replies for non-first fragments
In reply to Greg Kroah-Hartman6.18-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
@@ -1640,8 +1640,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
@@ -1655,8 +1654,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
@@ -1721,12 +1719,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 52/396 netfilter: nft_payload: fix mask build for partial field offload
In reply to Greg Kroah-Hartman6.18-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
@@ -259,9 +259,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);
@@ -270,15 +268,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 53/396 ASoC: SDCA: Ensure that Control Range is large enough for header
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Charles Keepax <[email protected]>
[ Upstream commit 951e921b039b793bef7050eaf5c5fb1a4a5341d1 ]
When reading the Ranges structure from an SDCA Control, ensure that the read data is large enough to encompass the required header before accessing it.
--- sound/soc/sdca/sdca_functions.c | 2 ++ 1 file changed, 2 insertions(+)
sound/soc/sdca/sdca_functions.c +2 -0
@@ -849,6 +849,8 @@ static int find_sdca_control_range(struct device *dev,return 0 ; else if (num_range < 0) return num_range; + else if (num_range < 2 * sizeof(*limits)) + return -EINVAL; range_list =devm_kcalloc (dev, num_range,sizeof (*range_list),GFP_KERNEL );if (!range_list)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 54/396 rds: Fix inet6_addr_lst NULL dereference when IPv6 is disabled
In reply to Greg Kroah-Hartman6.18-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 55/396 rds: tcp: hold the RCU lock across ipv6_chk_addr() in rds_tcp_laddr_check()
In reply to Greg Kroah-Hartman6.18-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 56/396 af_unix: fix listen() succeeding on sockets in the wrong state
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Ericson <[email protected]>
[ Upstream commit f0d9c3ffc2b5fc2ffacb56b3036155ce7a940a12 ]
Commit fd0a109a0f6b ("net, pidfs: prepare for handing out pidfds for reaped sk->sk_peer_pid") inserted a prepare_peercred() call between err = -EINVAL and the socket-state check in unix_listen(). Since prepare_peercred() leaves err at 0 on success, listen() on an AF_UNIX socket that is not in TCP_CLOSE or TCP_LISTEN state (e.g. one that is already connected) now silently returns success without doing anything, instead of failing with EINVAL as it did before.
--- net/unix/af_unix.c | 1 + 1 file changed, 1 insertion(+)
net/unix/af_unix.c +1 -0
@@ -835,6 +835,7 @@ static int unix_listen(struct socket *sock, int backlog)if (err) goto out;unix_state_lock (sk); + err = -EINVAL ;if (sk->sk_state !=TCP_CLOSE && sk->sk_state !=TCP_LISTEN ) goto out_unlock;if (backlog > sk->sk_max_ack_backlog)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 57/396 selftests: af_unix: Add tests for ECONNRESET and EOF semantics
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sunday Adelodun <[email protected]>
[ Upstream commit 45a1cd8346ca245a1ca475b26eb6ceb9d8b7c6f0 ]
Add selftests to verify and document Linux’s intended behaviour for UNIX domain sockets (SOCK_STREAM and SOCK_DGRAM) when a peer closes. The tests verify that:
1. SOCK_STREAM returns EOF when the peer closes normally.
2. SOCK_STREAM returns ECONNRESET if the peer closes with unread data.
3. SOCK_SEQPACKET returns EOF when the peer closes normally.
4. SOCK_SEQPACKET returns ECONNRESET if the peer closes with unread data.
5. SOCK_DGRAM does not return ECONNRESET when the peer closes.
This follows up on review feedback suggesting a selftest to clarify Linux’s semantics.
Stable-dep-of: 7f57c650d08b ("selftests/net/af_unix: test listen() rejects wrong socket states")
--- tools/testing/selftests/net/.gitignore | 1 + tools/testing/selftests/net/af_unix/Makefile | 1 + .../selftests/net/af_unix/unix_connreset.c | 177 ++++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 tools/testing/selftests/net/af_unix/unix_connreset.c
tools/testing/selftests/net/.gitignore +1 -0
@@ -66,3 +66,4 @@ udpgso udpgso_bench_rx udpgso_bench_tx unix_connect +unix_connreset
tools/testing/selftests/net/af_unix/Makefile +1 -0
@@ -13,6 +13,7 @@ TEST_GEN_PROGS := \ scm_rights \ so_peek_off \ unix_connect \ + unix_connreset \ # end of TEST_GEN_PROGS include ../../lib.mk
tools/testing/selftests/net/af_unix/unix_connreset.c new file +177 -0
177 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 58/396 selftest: af_unix: Create its own .gitignore.
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit adb6b68c50604f3113d62758e839cc0186b94ce8 ]
Somehow AF_UNIX tests have reused ../.gitignore,
but now NIPA warns about it.
Let's create .gitignore under af_unix/.
Stable-dep-of: 7f57c650d08b ("selftests/net/af_unix: test listen() rejects wrong socket states")
--- tools/testing/selftests/net/.gitignore | 8 -------- tools/testing/selftests/net/af_unix/.gitignore | 8 ++++++++ 2 files changed, 8 insertions(+), 8 deletions(-) create mode 100644 tools/testing/selftests/net/af_unix/.gitignore
tools/testing/selftests/net/.gitignore +0 -8
@@ -4,7 +4,6 @@ bind_timewait bind_wildcard busy_poller cmsg_sender -diag_uid epoll_busy_poll fin_ack_lat gro
@@ -18,7 +17,6 @@ ipv6_flowlabel ipv6_flowlabel_mgr ipv6_fragmentation log.txt -msg_oob msg_zerocopy netlink-dumps nettest
@@ -35,9 +33,6 @@ reuseport_bpf_numa reuseport_dualstack rxtimestamp sctp_hello -scm_inq -scm_pidfd -scm_rights sk_bind_sendto_listen sk_connect_zero_addr sk_so_peek_off
@@ -45,7 +40,6 @@ skf_net_off socket so_incoming_cpu so_netns_cookie -so_peek_off so_txtime so_rcv_listener stress_reuseport_listen
@@ -65,5 +59,3 @@ txtimestamp udpgso udpgso_bench_rx udpgso_bench_tx -unix_connect -unix_connreset
tools/testing/selftests/net/af_unix/.gitignore new file +8 -0
@@ -0,0 +1,8 @@ +diag_uid +msg_oob +scm_inq +scm_pidfd +scm_rights +so_peek_off +unix_connect +unix_connreset
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 59/396 selftests/net/af_unix: test listen() rejects wrong socket states
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Ericson <[email protected]>
[ Upstream commit 7f57c650d08b8793bb551bdb33ad876535ef9fe8 ]
Add a regression test for the unix_listen() state check. The key case is listen() on a bound socket that has already been connected: it is no longer in TCP_CLOSE or TCP_LISTEN, so it must fail with EINVAL. A prepare_peercred() call slipped in ahead of that check once left err at 0 and made listen() silently succeed there instead; this guards against a repeat.
The neighbouring outcomes are covered too so they cannot regress the same
way: a bound socket in TCP_CLOSE listens fine, calling listen() again on a socket already in TCP_LISTEN is allowed, and an unbound socket fails with EINVAL.
Each case runs for both listenable socket types (SOCK_STREAM and SOCK_SEQPACKET) and both pathname and abstract addresses.
--- .../testing/selftests/net/af_unix/.gitignore | 1 + tools/testing/selftests/net/af_unix/Makefile | 1 + .../selftests/net/af_unix/unix_listen.c | 187 ++++++++++++++++++ 3 files changed, 189 insertions(+) create mode 100644 tools/testing/selftests/net/af_unix/unix_listen.c
tools/testing/selftests/net/af_unix/.gitignore +1 -0
@@ -6,3 +6,4 @@ scm_rights so_peek_off unix_connect unix_connreset +unix_listen
tools/testing/selftests/net/af_unix/Makefile +1 -0
@@ -14,6 +14,7 @@ TEST_GEN_PROGS := \ so_peek_off \ unix_connect \ unix_connreset \ + unix_listen \ # end of TEST_GEN_PROGS include ../../lib.mk
tools/testing/selftests/net/af_unix/unix_listen.c new file +187 -0
187 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 60/396 xsk: fix buffer leak in xsk_drop_skb() for AF_XDP multi-buffer Tx
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Xing <[email protected]>
[ Upstream commit a3c8382ebce4780c6b3ace2c09bc342313ac0186 ]
This patch is inspired by the check[1] from sashiko. It says when overflow happens, the address of cq to be published is invalid. Actually the severer thing is the whole process of publishing the address of cq in this particular case is not right: it should truely publish the address and advance the cached_prod in cq as long as it reads descriptors from txq.
The following is the full analysis.xsk_drop_skb() is called in three places, which all discard a partially built multi-buffer skb:
1) xsk_build_skb() -EOVERFLOW error path: packet exceeds MAX_SKB_FRAGS
2) __xsk_generic_xmit() post-loop cleanup: an invalid descriptor in the TX ring prevents the partial packet from completing
3) xsk_release(): socket close while xs->skb holds an incomplete packet
In all three cases, the TX descriptors for the already-processed frags have been consumed from the TX ring (xskq_cons_release), and CQ slots have been reserved. However, xsk_drop_skb() calls xsk_consume_skb() which cancels the CQ reservations via xsk_cq_cancel_locked(). Since the buffer addresses never appear in the completion queue, userspace permanently loses track of these buffers.
Fix this by letting consume_skb() trigger the existing xsk_destruct_skb destructor, which already submits buffer addresses to the CQ via xsk_cq_submit_addr_locked().
Note that cancelling the descriptors back to the TX ring (via xskq_cons_cancel_n) is not a appropriate option because an oversized packet that always exceeds MAX_SKB_FRAGS would be retried indefinitely, which is an obviously deadlock bug in the TX path.
Also move the desc->addr assignment in xsk_build_skb() above the overflow check so that the current descriptor's address is recorded before a potential -EOVERFLOW jump to free_err, consistent with the zerocopy path in xsk_build_skb_zerocopy().
[1]: https://lore.kernel.org/all/[email protected]/
--- net/xdp/xsk.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-)
net/xdp/xsk.c +8 -5
@@ -676,8 +676,11 @@ static void xsk_consume_skb(struct sk_buff *skb)static void xsk_drop_skb (struct sk_buff *skb) { -xdp_sk (skb->sk)->tx->invalid_descs +=xsk_get_num_desc (skb); -xsk_consume_skb (skb); +struct xdp_sock *xs =xdp_sk (skb->sk); + + xs->tx->invalid_descs +=xsk_get_num_desc (skb); +consume_skb (skb); + xs->skb =NULL ; } static int xsk_skb_metadata(struct sk_buff *skb, void *buffer,
@@ -768,7 +771,7 @@ static struct sk_buff *xsk_build_skb_zerocopy(struct xdp_sock *xs, }/* in case of -EOVERFLOW that could happen below, -* xsk_consume_skb() will release this node as whole skb +* xsk_drop_skb() will release this node as whole skb * would be dropped, which implies freeing all list elements */ xsk_addr->addrs[xsk_addr->num_descs] = desc->addr;
@@ -867,6 +870,8 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs, xsk_addr = (struct xsk_addrs *)skb_shinfo (skb)->destructor_arg; } + xsk_addr->addrs[xsk_addr->num_descs] = desc->addr; +if (unlikely (nr_frags == (MAX_SKB_FRAGS -1 ) &&xp_mb_desc (desc))) { err = -EOVERFLOW ; goto free_err;
@@ -884,8 +889,6 @@ static struct sk_buff *xsk_build_skb(struct xdp_sock *xs,skb_add_rx_frag (skb, nr_frags, page,0 , len,PAGE_SIZE );refcount_add (PAGE_SIZE , &xs->sk.sk_wmem_alloc); - - xsk_addr->addrs[xsk_addr->num_descs] = desc->addr; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 61/396 xsk: use a smaller new lock for shared pool case
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Xing <[email protected]>
[ Upstream commit 30ed05adca4a05c50594384cff18910858dd1d35 ]
- Split cq_lock into two smaller locks: cq_prod_lock and cq_cached_prod_lock
- Avoid disabling/enabling interrupts in the hot xmit path
In either xsk_cq_cancel_locked() or xsk_cq_reserve_locked() function, the race condition is only between multiple xsks sharing the same pool. They are all in the process context rather than interrupt context, so now the small lock named cq_cached_prod_lock can be used without handling interrupts.
While cq_cached_prod_lock ensures the exclusive modification of @cached_prod, cq_prod_lock in xsk_cq_submit_addr_locked() only cares about @producer and corresponding @desc. Both of them don't necessarily be consistent with @cached_prod protected by cq_cached_prod_lock. That's the reason why the previous big lock can be split into two smaller ones. Please note that SPSC rule is all about the global state of producer and consumer that can affect both layers instead of local or cached ones.
Frequently disabling and enabling interrupt are very time consuming in some cases, especially in a per-descriptor granularity, which now can be avoided after this optimization, even when the pool is shared by multiple xsks.
With this patch, the performance number[1] could go from 1,872,565 pps to 1,961,009 pps. It's a minor rise of around 5%.
[1]: taskset -c 1 ./xdpsock -i enp2s0f1 -q 0 -t -S -s 64
Stable-dep-of: bd44a6dcd424 ("xsk: drain continuation descs after overflow in xsk_build_skb()")
--- include/net/xsk_buff_pool.h | 13 +++++++++---- net/xdp/xsk.c | 15 ++++++--------- net/xdp/xsk_buff_pool.c | 3 ++- 3 files changed, 17 insertions(+), 14 deletions(-)
include/net/xsk_buff_pool.h +9 -4
@@ -85,11 +85,16 @@ struct xsk_buff_pool {bool unaligned;bool tx_sw_csum;void *addrs; -/* Mutual exclusion of the completion ring in the SKB mode. Two cases to protect: -* NAPI TX thread and sendmsg error paths in the SKB destructor callback and when -* sockets share a single cq when the same netdev and queue id is shared. +/* Mutual exclusion of the completion ring in the SKB mode. +* Protect: NAPI TX thread and sendmsg error paths in the SKB +* destructor callback. */ -spinlock_t cq_lock; +spinlock_t cq_prod_lock; +/* Mutual exclusion of the completion ring in the SKB mode. +* Protect: when sockets share a single cq when the same netdev +* and queue id is shared. +*/ +spinlock_t cq_cached_prod_lock;struct xdp_buff_xsk *free_heads[]; };
net/xdp/xsk.c +6 -9
@@ -547,12 +547,11 @@ static int xsk_wakeup(struct xdp_sock *xs, u8 flags)static int xsk_cq_reserve_locked (struct xsk_buff_pool *pool) { -unsigned long flags;int ret; -spin_lock_irqsave (&pool->cq_lock, flags); +spin_lock (&pool->cq_cached_prod_lock); ret =xskq_prod_reserve (pool->cq); -spin_unlock_irqrestore (&pool->cq_lock, flags); +spin_unlock (&pool->cq_cached_prod_lock);return ret; }
@@ -603,7 +602,7 @@ static void xsk_cq_submit_addr_locked(struct xsk_buff_pool *pool,unsigned long flags;u32 idx, i; -spin_lock_irqsave (&pool->cq_lock, flags); +spin_lock_irqsave (&pool->cq_prod_lock, flags); idx =xskq_get_prod (pool->cq);if (unlikely (num_descs >1 )) {
@@ -621,16 +620,14 @@ static void xsk_cq_submit_addr_locked(struct xsk_buff_pool *pool, descs_processed++; }xskq_prod_submit_n (pool->cq, descs_processed); -spin_unlock_irqrestore (&pool->cq_lock, flags); +spin_unlock_irqrestore (&pool->cq_prod_lock, flags); }static void xsk_cq_cancel_locked (struct xsk_buff_pool *pool,u32 n) { -unsigned long flags; - -spin_lock_irqsave (&pool->cq_lock, flags); +spin_lock (&pool->cq_cached_prod_lock);xskq_prod_cancel_n (pool->cq, n); -spin_unlock_irqrestore (&pool->cq_lock, flags); +spin_unlock (&pool->cq_cached_prod_lock); }static void xsk_destruct_skb (struct sk_buff *skb)
net/xdp/xsk_buff_pool.c +2 -1
@@ -96,7 +96,8 @@ struct xsk_buff_pool *xp_create_and_assign_umem(struct xdp_sock *xs,INIT_LIST_HEAD (&pool->xskb_list);INIT_LIST_HEAD (&pool->xsk_tx_list);spin_lock_init (&pool->xsk_tx_list_lock); -spin_lock_init (&pool->cq_lock); +spin_lock_init (&pool->cq_prod_lock); +spin_lock_init (&pool->cq_cached_prod_lock);refcount_set (&pool->users,1 ); pool->fq = xs->fq_tmp;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 62/396 xsk: drain continuation descs after overflow in xsk_build_skb()
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Xing <[email protected]>
[ Upstream commit bd44a6dcd4248883de90f5dad53ae80066e27096 ]
Fix generic xmit path multi-buffer logic when packets are either too big (count of descriptors exceed MAX_SKB_FRAGS) or an invalid descriptor is included in fragmented packet. Introduce xdp_sock::drain_cont and act upon this flag - when it is set, keep on consuming descriptors from AF_XDP Tx ring and put them directly onto Cq. Previously these descriptors were silently lost and could never be reached again.
--- include/net/xdp_sock.h | 1 + net/xdp/xsk.c | 45 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 3 deletions(-)
include/net/xdp_sock.h +1 -0
@@ -80,6 +80,7 @@ struct xdp_sock {* call of __xsk_generic_xmit(). */ struct sk_buff *skb; +bool drain_cont;struct list_head map_list;/* Protects map_list */
net/xdp/xsk.c +42 -3
90 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 63/396 pinctrl-amd: Dont clear S4 wake bits at probe
In reply to Greg Kroah-Hartman6.18-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
@@ -886,8 +886,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 64/396 scsi: libiscsi: Fix stale-data leak into the SCSI sense buffer
In reply to Greg Kroah-Hartman6.18-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 65/396 scsi: libiscsi_tcp: Bound SCSI Response data segment to the connection buffer
In reply to Greg Kroah-Hartman6.18-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
@@ -752,13 +752,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 ;
@@ -766,6 +759,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 66/396 scsi: libsas: Fix HA resume deadlock and hisi_sas disk-wake race
In reply to Greg Kroah-Hartman6.18-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
@@ -5261,15 +5261,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
@@ -684,7 +684,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 67/396 smb: client: fix buffer leaks in SMB1 read and write
In reply to Greg Kroah-Hartman6.18-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
@@ -1515,8 +1515,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;
@@ -1628,8 +1630,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;
@@ -1908,8 +1912,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 68/396 ASoC: tas2781: Use correct calibration data for SINEGAIN2 register
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: wangdicheng <[email protected]>
[ Upstream commit dd88cf6273de61f2f7206c2066af97798dbb38b0 ]
The SINEGAIN2_REG case in cali_reg_update() references t->sin_gn[] rather than t->sin_gn2[], causing the second pilot tone gain calibration to be programmed with the wrong register address.
These are distinct fields in struct fct_param_address and are populated from separate firmware parameters by the parser in tas2781-fmwlib.c.
--- sound/soc/codecs/tas2781-i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
sound/soc/codecs/tas2781-i2c.c +2 -2
@@ -1303,8 +1303,8 @@ static void cali_reg_update(struct bulk_reg_val *p, t->sin_gn[2]);break ;case TAS2781_PRM_SINEGAIN2_REG : - reg =TASDEVICE_REG (t->sin_gn[0 ], t->sin_gn[1 ], - t->sin_gn[2 ]); + reg =TASDEVICE_REG (t->sin_gn2[0 ], t->sin_gn2[1 ], + t->sin_gn2[2 ]);break ;default : reg =0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 69/396 spi: spi-cadence: supports transmission with bits_per_word of 16 and 32
In reply to Greg Kroah-Hartman6.18-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;
@@ -812,6 +891,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 70/396 spi: spi-cadence: Move TX FIFO full busy-wait into FIFO
In reply to Greg Kroah-Hartman6.18-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 71/396 hwmon: (nct6775-core) Fix number of temperature registers for NCT6116
In reply to Greg Kroah-Hartman6.18-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 72/396 hwmon: (ina2xx) Make it easier to add more devices
In reply to Greg Kroah-Hartman6.18-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 73/396 hwmon: (ina2xx) Add support for INA234
In reply to Greg Kroah-Hartman6.18-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
@@ -2275,7 +2275,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,
@@ -1000,6 +1013,7 @@ static const struct i2c_device_id ina2xx_id[] = { { "ina226", ina226 }, { "ina230", ina226 }, { "ina231", ina226 }, + { "ina234", ina234 }, { "ina260", ina260 }, { "sy24655", sy24655 }, { }
@@ -1031,6 +1045,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 74/396 hwmon: (ina2xx) Shift INA234 shunt and current registers
In reply to Greg Kroah-Hartman6.18-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 75/396 hwmon: (ina2xx) Fix various overflow issues
In reply to Greg Kroah-Hartman6.18-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 76/396 hwmon: (ltc4282) Fix reading the minimum alarm voltage
In reply to Greg Kroah-Hartman6.18-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
@@ -384,8 +384,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 77/396 hwmon: (sht3x) Fix unaligned accesses
In reply to Greg Kroah-Hartman6.18-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 };
@@ -276,9 +277,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; }
@@ -336,7 +337,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;
@@ -389,7 +390,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 78/396 hwmon: (lm90) Only report alarms if driver is ready
In reply to Greg Kroah-Hartman6.18-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
@@ -1196,7 +1196,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);/*
@@ -1204,7 +1204,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 79/396 hwmon: (nzxt-smart2) DMA-align output buffer
In reply to Greg Kroah-Hartman6.18-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 80/396 net: do not send ICMP/NDISC Redirects when peer allocation fails
In reply to Greg Kroah-Hartman6.18-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
@@ -892,8 +892,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
@@ -630,7 +630,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
@@ -1706,6 +1706,8 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target) } peer =inet_getpeer_v6 (net->ipv6.peers, &ipv6_hdr (skb)->saddr); +if (!peer) + goto release; ret =inet_peer_xrlim_allow (peer,1 *HZ );if (!ret)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 81/396 hwmon: (nct6775-core) Prevent access to unsupported weight registers
In reply to Greg Kroah-Hartman6.18-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 82/396 net: bridge: mrp: fix Option TLV length in MRP_Test frames
In reply to Greg Kroah-Hartman6.18-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 83/396 forcedeth: fix UAF of txrx_stats in nv_remove
In reply to Greg Kroah-Hartman6.18-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
@@ -6187,10 +6187,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 84/396 hwmon: (adt7470) Fix fans stuck in manual mode on I2C errors
In reply to Greg Kroah-Hartman6.18-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 85/396 hwmon: (adt7470) Fix cache updated before hardware write on I2C error
In reply to Greg Kroah-Hartman6.18-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 86/396 hwmon: (adt7470) Fix busy-loop and I2C flooding in update thread
In reply to Greg Kroah-Hartman6.18-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 87/396 hwmon: (adt7470) Fix temperature alarm logic in hwmon_temp_read()
In reply to Greg Kroah-Hartman6.18-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 88/396 hwmon: (adt7470) Fix swapped PWM3 and PWM4 auto mode masks
In reply to Greg Kroah-Hartman6.18-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 89/396 hwmon: (adt7470) Use cached PWM frequency value
In reply to Greg Kroah-Hartman6.18-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 90/396 hwmon: (adt7470) Fix divide-by-zero TOCTOU crash in fan speed read
In reply to Greg Kroah-Hartman6.18-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 91/396 hwmon: (adt7470) Fix PWM auto temp state array and bounds check
In reply to Greg Kroah-Hartman6.18-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 92/396 rtase: fix double free of multi-frag skb on DMA map failure
In reply to Greg Kroah-Hartman6.18-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
@@ -1620,6 +1620,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 93/396 powerpc/boot: Fix simpleboot CPU node lookup check
In reply to Greg Kroah-Hartman6.18-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 94/396 powerpc/boot: Fix treeboot-currituck CPU node lookup check
In reply to Greg Kroah-Hartman6.18-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 95/396 powerpc/boot: Fix treeboot-akebono CPU node lookup check
In reply to Greg Kroah-Hartman6.18-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 96/396 net: udp_tunnel: fix memory leak in udp_tunnel_nic_unregister()
In reply to Greg Kroah-Hartman6.18-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 97/396 wifi: mac80211: validate individual TWT params before driver setup
In reply to Greg Kroah-Hartman6.18-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 98/396 netfs: clear PG_private_2 on copy-to-cache append failure
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yichong Chen <[email protected]>
[ Upstream commit a81fc9266e1c5fef9ccf675a9b44b2f4ab464923 ]
netfs_pgpriv2_copy_to_cache() marks the folio with PG_private_2 before netfs_pgpriv2_copy_folio() appends it to the copy-to-cache rolling buffer.
If the append fails, the folio is not queued for cache writeback, so the PG_private_2 state and its reference must be released immediately.
--- fs/netfs/read_pgpriv2.c | 1 + 1 file changed, 1 insertion(+)
fs/netfs/read_pgpriv2.c +1 -0
@@ -54,6 +54,7 @@ static void netfs_pgpriv2_copy_folio(struct netfs_io_request *creq, struct folio/* Attach the folio to the rolling buffer. */ if (rolling_buffer_append (&creq->buffer, folio,0 ) <0 ) { +folio_end_private_2 (folio);clear_bit (NETFS_RREQ_FOLIO_COPY_TO_CACHE , &creq->flags);return ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 99/396 netfs: handle single writeback rolling buffer allocation failure
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yichong Chen <[email protected]>
[ Upstream commit 37a1c535c80c67d98668d190c7432f9ebda43310 ]
netfs_write_folio_single() takes an extra folio reference before appending the folio to the rolling buffer.
rolling_buffer_append() can fail if it cannot allocate another folio_queue. Check the return value and drop the extra folio reference before returning the error.
--- fs/netfs/write_issue.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
fs/netfs/write_issue.c +6 -1
@@ -730,6 +730,7 @@ static int netfs_write_folio_single(struct netfs_io_request *wreq,size_t iter_off =0 ;size_t fsize =folio_size (folio), flen;loff_t fpos =folio_pos (folio); +ssize_t ret;bool to_eof = false;bool no_debug = false;
@@ -758,7 +759,11 @@ static int netfs_write_folio_single(struct netfs_io_request *wreq,/* Attach the folio to the rolling buffer. */ folio_get (folio); -rolling_buffer_append (&wreq->buffer, folio,NETFS_ROLLBUF_PUT_MARK ); + ret =rolling_buffer_append (&wreq->buffer, folio,NETFS_ROLLBUF_PUT_MARK ); +if (ret <0 ) { +folio_put (folio); +return ret; + }/* Move the submission point forward to allow for write-streaming data * not starting at the front of the page. We don't do write-streaming
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 100/396 netfs: release readahead folios on iterator preparation failure
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yichong Chen <[email protected]>
[ Upstream commit 87eb3d272dcbcbbfe5c1576c10e5dc72810cf1f6 ]
netfs_prepare_read_iterator() batches readahead folios in put_batch so that the folio references can be dropped after the I/O iterator has been prepared.
If rolling_buffer_load_from_ra() fails after earlier folios have been batched, the function returns immediately and leaves those references held. Release the batch before returning the error.
--- fs/netfs/buffered_read.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/netfs/buffered_read.c +3 -1
@@ -102,8 +102,10 @@ static ssize_t netfs_prepare_read_iterator(struct netfs_io_subrequest *subreq, added =rolling_buffer_load_from_ra (&rreq->buffer, ractl, &put_batch); -if (added <0 ) +if (added <0 ) { +folio_batch_release (&put_batch);return added; + } rreq->submitted += added; }folio_batch_release (&put_batch);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 101/396 net: ethernet: mtk_eth_soc: pass eth to mtk_handle_irq_rx in poll_controller
In reply to Greg Kroah-Hartman6.18-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
@@ -3446,7 +3446,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 102/396 hwmon: (pmbus) Fix return value from pmbus_update_byte_data()
In reply to Greg Kroah-Hartman6.18-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
@@ -512,7 +512,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 103/396 idpf: adjust TxQ ring count minimum
In reply to Greg Kroah-Hartman6.18-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
@@ -3075,10 +3075,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
@@ -21,7 +21,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 104/396 idpf: Fix mailbox IRQ name leak on request failure
In reply to Greg Kroah-Hartman6.18-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
@@ -139,7 +139,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 105/396 ice: suppress DPLL errors during reset recovery
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Przemyslaw Korba <[email protected]>
[ Upstream commit b00be7c6b4bd7da3d510753b27ff6cb7ec647d07 ]
During reset recovery, the admin queue returns EBUSY which is expected behavior. However, the DPLL subsystem was logging these as errors and incrementing the error counter, potentially leading to unnecessary warnings and even disabling the DPLL periodic worker if the threshold was reached.
Suppress error logging and error counter increments when the admin queue returns EBUSY, as this is expected during reset recovery and not a real failure condition.
test case:
- ethtool --reset eth3 irq-shared dma-shared filter-shared offload-shared mac-shared phy-shared ram-shared
- observe if dmesg EBUSY errors are gone
--- drivers/net/ethernet/intel/ice/ice_dpll.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-)
drivers/net/ethernet/intel/ice/ice_dpll.c +12 -7
@@ -703,7 +703,7 @@ ice_dpll_pin_state_update(struct ice_pf *pf, struct ice_dpll_pin *pin, ret,libie_aq_str (pf->hw.adminq.sq_last_status), pin_type_name[pin_type], pin->idx); - else + else if (pf->hw.adminq.sq_last_status != LIBIE_AQ_RC_EBUSY) dev_err_ratelimited(ice_pf_to_dev(pf),"err:%d %s failed to update %s pin:%u\n" , ret,
@@ -2669,7 +2669,8 @@ static int ice_dpll_pps_update_phase_offsets(struct ice_pf *pf, *phase_offset_pins_updated =0 ; ret =ice_aq_get_cgu_input_pin_measure (&pf->hw,DPLL_TYPE_PPS , meas,ARRAY_SIZE (meas)); -if (ret && pf->hw.adminq.sq_last_status ==LIBIE_AQ_RC_EAGAIN ) { +if (ret && (pf->hw.adminq.sq_last_status ==LIBIE_AQ_RC_EAGAIN || + pf->hw.adminq.sq_last_status ==LIBIE_AQ_RC_EBUSY )) {return 0 ; }else if (ret) { dev_err(ice_pf_to_dev(pf),
@@ -2731,10 +2732,12 @@ ice_dpll_update_state(struct ice_pf *pf, struct ice_dpll *d, bool init) d->dpll_idx, d->prev_input_idx, d->input_idx, d->dpll_state, d->prev_dpll_state, d->mode);if (ret) { -dev_err (ice_pf_to_dev (pf), -"update dpll=%d state failed, ret=%d %s\n" , - d->dpll_idx, ret, -libie_aq_str (pf->hw.adminq.sq_last_status)); +/* EBUSY is expected during reset recovery, don't log error */ +if (pf->hw.adminq.sq_last_status !=LIBIE_AQ_RC_EBUSY ) +dev_err (ice_pf_to_dev (pf), +"update dpll=%d state failed, ret=%d %s\n" , + d->dpll_idx, ret, +libie_aq_str (pf->hw.adminq.sq_last_status));return ret; }if (init) {
@@ -2803,7 +2806,9 @@ static void ice_dpll_periodic_work(struct kthread_work *work) d->periodic_counter % dp->phase_offset_monitor_period == 0) ret =ice_dpll_pps_update_phase_offsets (pf, &phase_offset_ntf);if (ret) { - d->cgu_state_acq_err_num++; +/* EBUSY is expected during reset recovery */ +if (pf->hw.adminq.sq_last_status !=LIBIE_AQ_RC_EBUSY ) + d->cgu_state_acq_err_num++;/* stop rescheduling this worker */ if (d->cgu_state_acq_err_num >ICE_CGU_STATE_ACQ_ERR_THRESHOLD ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 106/396 Bluetooth: ISO: clear iso_data always when detaching conn from hcon
In reply to Greg Kroah-Hartman6.18-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
@@ -826,6 +826,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 107/396 Bluetooth: L2CAP: fix UAF in l2cap_le_connect_rsp
In reply to Greg Kroah-Hartman6.18-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
@@ -4831,6 +4831,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);
@@ -4876,6 +4880,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 108/396 Bluetooth: ISO: lock sk in iso_sock_getname
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit 89cf154d7c18e6e94a3da83051f3cf2bac317ae2 ]
Accessing iso_pi(sk)->conn requires lock_sock, which is not held here.
Fix by adding the lock/release.
--- net/bluetooth/iso.c | 4 ++++ 1 file changed, 4 insertions(+)
net/bluetooth/iso.c +4 -0
@@ -1392,6 +1392,8 @@ static int iso_sock_getname(struct socket *sock, struct sockaddr *addr,BT_DBG ("sock %p, sk %p" , sock, sk); +lock_sock (sk); + addr->sa_family =AF_BLUETOOTH ;if (peer) {
@@ -1413,6 +1415,8 @@ static int iso_sock_getname(struct socket *sock, struct sockaddr *addr, sa->iso_bdaddr_type =iso_pi (sk)->src_type; } +release_sock (sk); +return len; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 109/396 Bluetooth: HCI: Add initial support for PAST
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 33b2835f0b7e2a458473b0e3a23b54b92108b6b0 ]
This adds PAST related commands (HCI_OP_LE_PAST, HCI_OP_LE_PAST_SET_INFO and HCI_OP_LE_PAST_PARAMS) and events (HCI_EV_LE_PAST_RECEIVED) along with handling of PAST sender and receiver features bits including new MGMG settings ( HCI_EV_LE_PAST_RECEIVED and MGMT_SETTING_PAST_RECEIVER) which userspace can use to determine if PAST is supported by the controller.
Stable-dep-of: 4311fd6f4290 ("Bluetooth: ISO: lock sk in iso_connect_ind")
--- include/net/bluetooth/hci.h | 54 ++++++++++++++++++++++ include/net/bluetooth/hci_core.h | 12 +++++ include/net/bluetooth/mgmt.h | 2 + net/bluetooth/hci_event.c | 79 ++++++++++++++++++++++++++++---- net/bluetooth/hci_sync.c | 3 ++ net/bluetooth/iso.c | 25 ++++++++++ net/bluetooth/mgmt.c | 12 +++++ 7 files changed, 177 insertions(+), 10 deletions(-)
include/net/bluetooth/hci.h +54 -0
@@ -647,6 +647,8 @@ enum {#define HCI_LE_EXT_ADV 0x10#define HCI_LE_PERIODIC_ADV 0x20#define HCI_LE_CHAN_SEL_ALG2 0x40 +#define HCI_LE_PAST_SENDER 0x01 +#define HCI_LE_PAST_RECEIVER 0x02#define HCI_LE_CIS_CENTRAL 0x10#define HCI_LE_CIS_PERIPHERAL 0x20#define HCI_LE_ISO_BROADCASTER 0x40
@@ -2068,6 +2070,44 @@ struct hci_cp_le_set_privacy_mode {__u8 mode; } __packed; +#define HCI_OP_LE_PAST 0x205a +struct hci_cp_le_past { +__le16 handle; +__le16 service_data; +__le16 sync_handle; +} __packed; + +struct hci_rp_le_past { +__u8 status; +__le16 handle; +} __packed; + +#define HCI_OP_LE_PAST_SET_INFO 0x205b +struct hci_cp_le_past_set_info { +__le16 handle; +__le16 service_data; +__u8 adv_handle; +} __packed; + +struct hci_rp_le_past_set_info { +__u8 status; +__le16 handle; +} __packed; + +#define HCI_OP_LE_PAST_PARAMS 0x205c +struct hci_cp_le_past_params { +__le16 handle; +__u8 mode; +__le16 skip; +__le16 sync_timeout; +__u8 cte_type; +} __packed; + +struct hci_rp_le_past_params { +__u8 status; +__le16 handle; +} __packed; +#define HCI_OP_LE_READ_BUFFER_SIZE_V2 0x2060struct hci_rp_le_read_buffer_size_v2 {__u8 status;
@@ -2800,6 +2840,20 @@ struct hci_evt_le_ext_adv_set_term {__u8 num_evts; } __packed; +#define HCI_EV_LE_PAST_RECEIVED 0x18 +struct hci_ev_le_past_received { +__u8 status; +__le16 handle; +__le16 service_data; +__le16 sync_handle; +__u8 sid; +__u8 bdaddr_type; +bdaddr_t bdaddr; +__u8 phy; +__le16 interval; +__u8 clock_accuracy; +} __packed; +#define HCI_EVT_LE_CIS_ESTABLISHED 0x19struct hci_evt_le_cis_established {__u8 status;
include/net/bluetooth/hci_core.h +12 -0
@@ -2054,6 +2054,18 @@ void hci_conn_del_sysfs(struct hci_conn *conn);#define sync_recv_capable (dev) \ ((dev)->le_features[3] & HCI_LE_ISO_SYNC_RECEIVER)#define sync_recv_enabled (dev) (le_enabled(dev) && sync_recv_capable(dev)) +#define past_sender_capable (dev) \ + ((dev)->le_features[3] & HCI_LE_PAST_SENDER) +#define past_receiver_capable (dev) \ + ((dev)->le_features[3] & HCI_LE_PAST_RECEIVER) +#define past_capable (dev) \ + (past_sender_capable(dev) || past_receiver_capable(dev)) +#define past_sender_enabled (dev) \ + (le_enabled(dev) && past_sender_capable(dev)) +#define past_receiver_enabled (dev) \ + (le_enabled(dev) && past_receiver_capable(dev)) +#define past_enabled (dev) \ + (past_sender_enabled(dev) || past_receiver_enabled(dev))#define mws_transport_config_capable (dev) (((dev)->commands[30] & 0x08) && \ (!hci_test_quirk((dev), HCI_QUIRK_BROKEN_MWS_TRANSPORT_CONFIG)))
include/net/bluetooth/mgmt.h +2 -0
@@ -119,6 +119,8 @@ struct mgmt_rp_read_index_list {#define MGMT_SETTING_ISO_BROADCASTER BIT(20)#define MGMT_SETTING_ISO_SYNC_RECEIVER BIT(21)#define MGMT_SETTING_LL_PRIVACY BIT(22) +#define MGMT_SETTING_PAST_SENDER BIT(23) +#define MGMT_SETTING_PAST_RECEIVER BIT(24)#define MGMT_OP_READ_INFO 0x0004#define MGMT_READ_INFO_SIZE 0
net/bluetooth/hci_event.c +69 -10
97 lines not on this page · raw message
net/bluetooth/hci_sync.c +3 -0
@@ -4450,6 +4450,9 @@ static int hci_le_set_event_mask_sync(struct hci_dev *hdev)if (ext_adv_capable (hdev)) events[2 ] |=0x02 ;/* LE Advertising Set Terminated */ +if (past_receiver_capable (hdev)) + events[2 ] |=0x80 ;/* LE PAST Received */ +if (cis_capable (hdev)) { events[3 ] |=0x01 ;/* LE CIS Established */ if (cis_peripheral_capable (hdev))
net/bluetooth/iso.c +25 -0
@@ -80,6 +80,7 @@ static struct bt_iso_qos default_qos;static bool check_ucast_qos (struct bt_iso_qos *qos);static bool check_bcast_qos (struct bt_iso_qos *qos);static bool iso_match_sid (struct sock *sk,void *data); +static bool iso_match_sid_past (struct sock *sk,void *data);static bool iso_match_sync_handle (struct sock *sk,void *data);static bool iso_match_sync_handle_pa_report (struct sock *sk,void *data);static void iso_sock_disconn (struct sock *sk);
@@ -2147,6 +2148,16 @@ static bool iso_match_sid(struct sock *sk, void *data)return ev->sid ==iso_pi (sk)->bc_sid; } +static bool iso_match_sid_past (struct sock *sk,void *data) +{ +struct hci_ev_le_past_received *ev = data; + +if (iso_pi (sk)->bc_sid ==HCI_SID_INVALID ) +return true; + +return ev->sid ==iso_pi (sk)->bc_sid; +} +static bool iso_match_sync_handle (struct sock *sk,void *data) {struct hci_evt_le_big_info_adv_report *ev = data;
@@ -2166,6 +2177,7 @@ static bool iso_match_sync_handle_pa_report(struct sock *sk, void *data)int iso_connect_ind (struct hci_dev *hdev,bdaddr_t *bdaddr,__u8 *flags) {struct hci_ev_le_pa_sync_established *ev1; +struct hci_ev_le_past_received *ev1a;struct hci_evt_le_big_info_adv_report *ev2;struct hci_ev_le_per_adv_report *ev3;struct sock *sk;
@@ -2179,6 +2191,7 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)* SID to listen to and once sync is established its handle needs to * be stored in iso_pi(sk)->sync_handle so it can be matched once * receiving the BIG Info. +* 1a. HCI_EV_LE_PAST_RECEIVED: alternative to 1. * 2. HCI_EVT_LE_BIG_INFO_ADV_REPORT: When connect_ind is triggered by a * a BIG Info it attempts to check if there any listening socket with * the same sync_handle and if it does then attempt to create a sync.
@@ -2198,6 +2211,18 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) goto done; } + ev1a =hci_recv_event_data (hdev,HCI_EV_LE_PAST_RECEIVED ); +if (ev1a) { + sk =iso_get_sock (&hdev->bdaddr, bdaddr,BT_LISTEN , + iso_match_sid_past, ev1a); +if (sk && !ev1a->status) { +iso_pi (sk)->sync_handle =le16_to_cpu (ev1a->sync_handle); +iso_pi (sk)->bc_sid = ev1a->sid; + } + + goto done; + } + ev2 =hci_recv_event_data (hdev,HCI_EVT_LE_BIG_INFO_ADV_REPORT );if (ev2) {/* Check if BIGInfo report has already been handled */
net/bluetooth/mgmt.c +12 -0
@@ -858,6 +858,12 @@ static u32 get_supported_settings(struct hci_dev *hdev)if (ll_privacy_capable (hdev)) settings |=MGMT_SETTING_LL_PRIVACY ; +if (past_sender_capable (hdev)) + settings |=MGMT_SETTING_PAST_SENDER ; + +if (past_receiver_capable (hdev)) + settings |=MGMT_SETTING_PAST_RECEIVER ; + settings |=MGMT_SETTING_PHY_CONFIGURATION ;return settings;
@@ -943,6 +949,12 @@ static u32 get_current_settings(struct hci_dev *hdev)if (ll_privacy_enabled (hdev)) settings |=MGMT_SETTING_LL_PRIVACY ; +if (past_sender_enabled (hdev)) + settings |=MGMT_SETTING_PAST_SENDER ; + +if (past_receiver_enabled (hdev)) + settings |=MGMT_SETTING_PAST_RECEIVER ; +return settings; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 110/396 Bluetooth: ISO: Fix data-race on iso_pi(sk) in socket and HCI event paths
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: SeungJu Cheon <[email protected]>
[ Upstream commit f958c7805b18e9d69f6b322b231ecee46ec6f331 ]
Several iso_pi(sk) fields (qos, qos_user_set, bc_sid, base, base_len, sync_handle, bc_num_bis) are written under lock_sock in iso_sock_setsockopt() and iso_sock_bind(), but read and written under hci_dev_lock only in two other paths:
- iso_connect_bis() / iso_connect_cis(), invoked from connect(2), read qos/base/bc_sid and reset qos to default_qos on the qos_user_set validation failure -- all without lock_sock.
- iso_connect_ind(), invoked from hci_rx_work, writes sync_handle, bc_sid, qos.bcast.encryption, bc_num_bis, base and base_len on PA_SYNC_ESTABLISHED / PAST_RECEIVED / BIG_INFO_ADV_REPORT / PER_ADV_REPORT events. The BIG_INFO handler additionally passes &iso_pi(sk)->qos together with sync_handle / bc_num_bis / bc_bis to hci_conn_big_create_sync() while setsockopt may be mutating them.
Acquire lock_sock around the affected accesses in both paths.
The locking order hci_dev_lock -> lock_sock matches the existing iso_conn_big_sync() precedent, whose comment documents the same requirement for hci_conn_big_create_sync(). The HCI connect/bind helpers do not wait for command completion -- they enqueue work via hci_cmd_sync_queue{,_once}() / hci_le_create_cis_pending() and return -- so the added hold time is comparable to iso_conn_big_sync().
KCSAN report:
BUG: KCSAN: data-race in iso_connect_cis / iso_sock_setsockopt
read to 0xffffa3ae8ce3cdc8 of 1 bytes by task 335 on cpu 0:
iso_connect_cis+0x49f/0xa20 iso_sock_connect+0x60e/0xb40 __sys_connect_file+0xbd/0xe0 __sys_connect+0xe0/0x110 __x64_sys_connect+0x40/0x50 x64_sys_call+0xcad/0x1c60 do_syscall_64+0x133/0x590 entry_SYSCALL_64_after_hwframe+0x77/0x7f
write to 0xffffa3ae8ce3cdc8 of 60 bytes by task 334 on cpu 1:
iso_sock_setsockopt+0x69a/0x930 do_sock_setsockopt+0xc3/0x170 __sys_setsockopt+0xd1/0x130 __x64_sys_setsockopt+0x64/0x80 x64_sys_call+0x1547/0x1c60 do_syscall_64+0x133/0x590 entry_SYSCALL_64_after_hwframe+0x77/0x7f
Reported by Kernel Concurrency Sanitizer on:
CPU: 1 UID: 0 PID: 334 Comm: iso_setup_race Not tainted 7.0.0-10949-g8541d8f725c6 #44 PREEMPT(lazy)
The iso_connect_ind() races were found by inspection.
Stable-dep-of: 4311fd6f4290 ("Bluetooth: ISO: lock sk in iso_connect_ind")
--- net/bluetooth/iso.c | 54 +++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 24 deletions(-)
net/bluetooth/iso.c +30 -24
@@ -355,6 +355,7 @@ static int iso_connect_bis(struct sock *sk)return -EHOSTUNREACH ;hci_dev_lock (hdev); +lock_sock (sk);if (!bis_capable (hdev)) { err = -EOPNOTSUPP ;
@@ -407,13 +408,9 @@ static int iso_connect_bis(struct sock *sk) goto unlock; } -lock_sock (sk); - err =iso_chan_add (conn, sk,NULL ); -if (err) { -release_sock (sk); +if (err) goto unlock; - }/* Update source addr of the socket */ bacpy (&iso_pi (sk)->src, &hcon->src);
@@ -429,9 +426,8 @@ static int iso_connect_bis(struct sock *sk)iso_sock_set_timer (sk,READ_ONCE (sk->sk_sndtimeo)); } -release_sock (sk); - unlock: +release_sock (sk);hci_dev_unlock (hdev);hci_dev_put (hdev);return err;
@@ -459,6 +455,7 @@ static int iso_connect_cis(struct sock *sk)return -EHOSTUNREACH ;hci_dev_lock (hdev); +lock_sock (sk);if (!cis_central_capable (hdev)) { err = -EOPNOTSUPP ;
@@ -513,13 +510,9 @@ static int iso_connect_cis(struct sock *sk) goto unlock; } -lock_sock (sk); - err =iso_chan_add (conn, sk,NULL ); -if (err) { -release_sock (sk); +if (err) goto unlock; - }/* Update source addr of the socket */ bacpy (&iso_pi (sk)->src, &hcon->src);
@@ -535,9 +528,8 @@ static int iso_connect_cis(struct sock *sk)iso_sock_set_timer (sk,READ_ONCE (sk->sk_sndtimeo)); } -release_sock (sk); - unlock: +release_sock (sk);hci_dev_unlock (hdev);hci_dev_put (hdev);return err;
@@ -2204,8 +2196,10 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) sk =iso_get_sock (&hdev->bdaddr, bdaddr,BT_LISTEN , iso_match_sid, ev1);if (sk && !ev1->status) { +lock_sock (sk);iso_pi (sk)->sync_handle =le16_to_cpu (ev1->handle);iso_pi (sk)->bc_sid = ev1->sid; +release_sock (sk); } goto done;
@@ -2216,8 +2210,10 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) sk =iso_get_sock (&hdev->bdaddr, bdaddr,BT_LISTEN , iso_match_sid_past, ev1a);if (sk && !ev1a->status) { +lock_sock (sk);iso_pi (sk)->sync_handle =le16_to_cpu (ev1a->sync_handle);iso_pi (sk)->bc_sid = ev1a->sid; +release_sock (sk); } goto done;
@@ -2244,27 +2240,35 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) ev2);if (sk) { -int err; -struct hci_conn *hcon =iso_pi (sk)->conn->hcon; +int err =0 ; +bool big_sync; +struct hci_conn *hcon; +lock_sock (sk); + + hcon =iso_pi (sk)->conn->hcon;iso_pi (sk)->qos.bcast.encryption = ev2->encryption;if (ev2->num_bis <iso_pi (sk)->bc_num_bis)iso_pi (sk)->bc_num_bis = ev2->num_bis; -if (!test_bit (BT_SK_DEFER_SETUP , &bt_sk (sk)->flags) && - !test_and_set_bit (BT_SK_BIG_SYNC , &iso_pi (sk)->flags)) { + big_sync = !test_bit (BT_SK_DEFER_SETUP , &bt_sk (sk)->flags) && + !test_and_set_bit (BT_SK_BIG_SYNC , &iso_pi (sk)->flags); + +if (big_sync) err =hci_conn_big_create_sync (hdev, hcon, &iso_pi (sk)->qos,iso_pi (sk)->sync_handle,iso_pi (sk)->bc_num_bis,iso_pi (sk)->bc_bis); -if (err) { -bt_dev_err (hdev,"hci_le_big_create_sync: %d" , - err); -sock_put (sk); - sk =NULL ; - } + +release_sock (sk); + +if (big_sync && err) { +bt_dev_err (hdev,"hci_le_big_create_sync: %d" , + err); +sock_put (sk); + sk =NULL ; } }
@@ -2318,8 +2322,10 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)if (!base || base_len >BASE_MAX_LENGTH ) goto done; +lock_sock (sk);memcpy (iso_pi (sk)->base, base, base_len);iso_pi (sk)->base_len = base_len; +release_sock (sk); }else {/* This is a PA data fragment. Keep pa_data_len set to 0 * until all data has been reassembled.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 111/396 Bluetooth: ISO: lock sk in iso_connect_ind
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit 4311fd6f429065a8ba208660360a895627a00cf3 ]
Accessing iso_pi(sk)->conn requires lock_sock, which is not taken in the "ev3" part of iso_connect_ind. It may also be NULL if socket has transitioned away from the LISTEN/CONNECT states before locking.
Fix by adding lock/release. Recheck hcon is valid after lock acquire where needed.
--- net/bluetooth/iso.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-)
net/bluetooth/iso.c +11 -8
@@ -2246,7 +2246,7 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)lock_sock (sk); - hcon =iso_pi (sk)->conn->hcon; + hcon =iso_pi (sk)->conn ?iso_pi (sk)->conn->hcon :NULL ;iso_pi (sk)->qos.bcast.encryption = ev2->encryption;if (ev2->num_bis <iso_pi (sk)->bc_num_bis)
@@ -2286,9 +2286,11 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)if (!sk) goto done; - hcon =iso_pi (sk)->conn->hcon; +lock_sock (sk); + + hcon =iso_pi (sk)->conn ?iso_pi (sk)->conn->hcon :NULL ;if (!hcon) - goto done; + goto release3;if (ev3->data_status ==LE_PA_DATA_TRUNCATED ) {/* The controller was unable to retrieve PA data. */
@@ -2296,12 +2298,12 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) HCI_MAX_PER_AD_TOT_LEN); hcon->le_per_adv_data_len =0 ; hcon->le_per_adv_data_offset =0 ; - goto done; + goto release3; }if (hcon->le_per_adv_data_offset + ev3->length >HCI_MAX_PER_AD_TOT_LEN ) - goto done; + goto release3;memcpy (hcon->le_per_adv_data + hcon->le_per_adv_data_offset, ev3->data, ev3->length);
@@ -2320,18 +2322,19 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) &base_len);if (!base || base_len >BASE_MAX_LENGTH ) - goto done; + goto release3; -lock_sock (sk);memcpy (iso_pi (sk)->base, base, base_len);iso_pi (sk)->base_len = base_len; -release_sock (sk); }else {/* This is a PA data fragment. Keep pa_data_len set to 0 * until all data has been reassembled. */ hcon->le_per_adv_data_len =0 ; } + +release3: +release_sock (sk); }else { sk =iso_get_sock (&hdev->bdaddr,BDADDR_ANY ,BT_LISTEN ,NULL ,NULL );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 112/396 Bluetooth: ISO: fix timeout vs sync_timeout typo in check_bcast_qos
In reply to Greg Kroah-Hartman6.18-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
@@ -1709,7 +1709,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 113/396 Bluetooth: ISO: validate sockaddr_iso first in iso_sock_rebind_bis()
In reply to Greg Kroah-Hartman6.18-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
@@ -1022,15 +1022,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 114/396 Bluetooth: ISO: Fix not updating BIS sender source address
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 577cf4c0a1e8471a0d6c0f36bb3716285e27ad5e ]
The source address for a BIS sender/Broadcast Source shall be updated with the advertisement address since in case privacy is enabled it may use an RPA rather than an identity address.
Stable-dep-of: 0d255e63fcf3 ("Bluetooth: ISO: hold sk properly in iso_conn_ready")
--- net/bluetooth/iso.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
net/bluetooth/iso.c +19 -0
@@ -2001,6 +2001,25 @@ static void iso_conn_ready(struct iso_conn *conn)BT_DBG ("conn %p" , conn);if (sk) { +/* Attempt to update source address in case of BIS Sender if +* the advertisement is using a random address. +*/ +if (conn->hcon->type ==BIS_LINK && + conn->hcon->role ==HCI_ROLE_MASTER && + !bacmp (&conn->hcon->dst,BDADDR_ANY )) { +struct hci_conn *bis = conn->hcon; +struct adv_info *adv; + + adv =hci_find_adv_instance (bis->hdev, + bis->iso_qos.bcast.bis); +if (adv &&bacmp (&adv->random_addr,BDADDR_ANY )) { +lock_sock (sk); +iso_pi (sk)->src_type =BDADDR_LE_RANDOM ; +bacpy (&iso_pi (sk)->src, &adv->random_addr); +release_sock (sk); + } + } +iso_sock_ready (conn->sk); }else { hcon = conn->hcon;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 115/396 Bluetooth: ISO: fix CONNECTED -> CLOSED transition on shutdown/release
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit 0786469ee242952008628ed0e2d386098e2065ab ]
Commit d57e506f6a1e ("Bluetooth: ISO: clear iso_data always when detaching conn from hcon") merged a version of the UAF fix that breaks releasing connected
ISO sockets. Since hci_conn::iso_data is set to NULL, iso_chan_del() won't be called when the hci_conn disconnects, and the ISO socket does not emit POLLHUP correctly.
Fix by retaining full hci_conn <-> iso_conn association while in BT_DISCONNECT state, so that local disconnect via shutdown() follows similar ISO socket code path as remote disconnect. Use a separate flag to track whether hci_conn_drop() is needed, instead of setting iso_conn::hcon = NULL
In iso_sock_ready(), disallow disconnecting socket going BT_CONNECTED, in case hcon connects while its drop is pending.
Stable-dep-of: 0d255e63fcf3 ("Bluetooth: ISO: hold sk properly in iso_conn_ready")
--- net/bluetooth/iso.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-)
net/bluetooth/iso.c +20 -6
@@ -23,8 +23,14 @@ static struct bt_sock_list iso_sk_list = { };/* ---- ISO connections ---- */ +enum { +ISO_CONN_DROPPED , + __ISO_CONN_NUM_FLAGS +}; +struct iso_conn {struct hci_conn *hcon; + DECLARE_BITMAP(flags, __ISO_CONN_NUM_FLAGS);/* @lock: spinlock protecting changes to iso_conn fields */ spinlock_t lock;
@@ -106,7 +112,8 @@ static void iso_conn_free(struct kref *ref)if (conn->hcon) { conn->hcon->iso_data =NULL ; -hci_conn_drop (conn->hcon); +if (!test_and_set_bit (ISO_CONN_DROPPED , conn->flags)) +hci_conn_drop (conn->hcon); }/* Ensure no more work items will run since hci_conn has been dropped */
@@ -305,6 +312,7 @@ static int __iso_chan_add(struct iso_conn *conn, struct sock *sk,iso_pi (sk)->conn = conn; conn->sk = sk; +clear_bit (ISO_CONN_DROPPED , conn->flags);if (parent)bt_accept_enqueue (parent, sk, true);
@@ -817,11 +825,8 @@ 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); +if (!test_and_set_bit (ISO_CONN_DROPPED ,iso_pi (sk)->conn->flags)) +hci_conn_drop (iso_pi (sk)->conn->hcon); }static void __iso_sock_close (struct sock *sk)
@@ -1964,9 +1969,18 @@ static void iso_sock_ready(struct sock *sk)return ;lock_sock (sk); + +switch (sk->sk_state) { +case BT_DISCONN : +case BT_CLOSED : +release_sock (sk); +return ; + } +iso_sock_clear_timer (sk); sk->sk_state =BT_CONNECTED ; sk->sk_state_change (sk); +release_sock (sk); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 116/396 Bluetooth: ISO: hold sk properly in iso_conn_ready
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit 0d255e63fcf3f13a570d7ac11678fa1164ac015c ]
sk deref in iso_conn_ready must be done either under conn->lock, or holding a refcount, to avoid concurrent close. conn->sk is currently accessed without either:
[Task 1] [Task 2]
iso_sock_release
iso_conn_ready
sk = conn->sk
lock_sock(sk)
conn->sk = NULL
lock_sock(sk)
release_sock(sk)
iso_sock_kill(sk)
UAF on sk deref
Fix possible UAF by holding sk refcount in iso_conn_ready(). Also recheck after lock_sock that the socket is still valid. Adjust locking so conn->sk is cleared only under lock_sock.
--- net/bluetooth/iso.c | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-)
net/bluetooth/iso.c +23 -11
@@ -787,11 +787,13 @@ static void iso_sock_kill(struct sock *sk)BT_DBG ("sk %p state %d" , sk, sk->sk_state);/* Sock is dead, so set conn->sk to NULL to avoid possible UAF */ +lock_sock (sk);if (iso_pi (sk)->conn) {iso_conn_lock (iso_pi (sk)->conn);iso_pi (sk)->conn->sk =NULL ;iso_conn_unlock (iso_pi (sk)->conn); } +release_sock (sk);/* Kill poor orphan */ bt_sock_unlink (&iso_sk_list, sk);
@@ -1965,23 +1967,17 @@ static void iso_sock_ready(struct sock *sk) {BT_DBG ("sk %p" , sk); -if (!sk) -return ; - -lock_sock (sk); +lockdep_assert (lockdep_sock_is_held (sk));switch (sk->sk_state) {case BT_DISCONN :case BT_CLOSED : -release_sock (sk);return ; }iso_sock_clear_timer (sk); sk->sk_state =BT_CONNECTED ; sk->sk_state_change (sk); - -release_sock (sk); }static bool iso_match_big (struct sock *sk,void *data)
@@ -2006,7 +2002,7 @@ static bool iso_match_pa_sync_flag(struct sock *sk, void *data)static void iso_conn_ready (struct iso_conn *conn) {struct sock *parent =NULL ; -struct sock *sk = conn->sk; +struct sock *sk;struct hci_ev_le_big_sync_established *ev =NULL ;struct hci_ev_le_pa_sync_established *ev2 =NULL ;struct hci_ev_le_per_adv_report *ev3 =NULL ;
@@ -2014,7 +2010,22 @@ static void iso_conn_ready(struct iso_conn *conn)BT_DBG ("conn %p" , conn); +iso_conn_lock (conn); + sk =iso_sock_hold (conn); +iso_conn_unlock (conn); +if (sk) { +lock_sock (sk); + +/* conn->sk may have become NULL if racing with sk close, but +* due to held hdev->lock, it can't become different sk. +*/ +if (!conn->sk) { +release_sock (sk); +sock_put (sk); +return ; + } +/* Attempt to update source address in case of BIS Sender if * the advertisement is using a random address. */
@@ -2027,14 +2038,15 @@ static void iso_conn_ready(struct iso_conn *conn) adv =hci_find_adv_instance (bis->hdev, bis->iso_qos.bcast.bis);if (adv &&bacmp (&adv->random_addr,BDADDR_ANY )) { -lock_sock (sk);iso_pi (sk)->src_type =BDADDR_LE_RANDOM ;bacpy (&iso_pi (sk)->src, &adv->random_addr); -release_sock (sk); } } -iso_sock_ready (conn->sk); +iso_sock_ready (sk); + +release_sock (sk); +sock_put (sk); }else { hcon = conn->hcon;if (!hcon)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 117/396 Bluetooth: ISO: fix leaking sk after socket release
In reply to Greg Kroah-Hartman6.18-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 | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-)
net/bluetooth/iso.c +18 -4
@@ -61,6 +61,7 @@ static void iso_sock_kill(struct sock *sk);enum {BT_SK_BIG_SYNC ,BT_SK_PA_SYNC , +BT_SK_KILLED , };struct iso_pinfo {
@@ -294,6 +295,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); }
@@ -780,24 +782,29 @@ 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);/* Sock is dead, so set conn->sk to NULL to avoid possible UAF */ -lock_sock (sk);if (iso_pi (sk)->conn) {iso_conn_lock (iso_pi (sk)->conn);iso_pi (sk)->conn->sk =NULL ;iso_conn_unlock (iso_pi (sk)->conn); } -release_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); }
@@ -874,7 +881,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)
@@ -1958,8 +1964,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 118/396 Bluetooth: ISO: avoid deadlocks in iso_sock_timeout
In reply to Greg Kroah-Hartman6.18-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
@@ -36,8 +36,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;
@@ -80,6 +78,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;
@@ -117,9 +116,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);
@@ -160,48 +156,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 ---- */
@@ -226,7 +219,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;
@@ -291,8 +283,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);
@@ -782,6 +775,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 ||
@@ -877,8 +872,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); }
@@ -947,6 +943,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 119/396 Bluetooth: ISO: ensure no dangling hcon references in iso_conn
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit aa9f7cb2bd3a2be998ceb739fc9a2f986eba43eb ]
After iso_conn_del(), ISO sockets should not dereference the hcon any more. Currently, clearing iso_conn::hcon relies on iso_conn_del() releasing the last reference to the iso_conn.
Simplify this by explicitly clearing conn->hcon in iso_conn_del(), to avoid more complex reasoning on races about who holds the last reference.
Stable-dep-of: fdfde532ab1c ("Bluetooth: ISO: fix refcounting of iso_conn")
--- net/bluetooth/iso.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-)
net/bluetooth/iso.c +21 -3
@@ -262,6 +262,7 @@ static void iso_chan_del(struct sock *sk, int err) }static void iso_conn_del (struct hci_conn *hcon,int err) + __must_hold(&hcon->hdev->lock) {struct iso_conn *conn = hcon->iso_data;struct sock *sk;
@@ -276,11 +277,10 @@ static void iso_conn_del(struct hci_conn *hcon, int err)iso_conn_lock (conn); sk =iso_sock_hold (conn);iso_conn_unlock (conn); -iso_conn_put (conn);if (!sk) {iso_conn_put (conn); -return ; + goto done; }iso_sock_disable_timer (sk);
@@ -290,6 +290,15 @@ static void iso_conn_del(struct hci_conn *hcon, int err)release_sock (sk);iso_sock_kill (sk);sock_put (sk); + +done: +/* No sk access to conn->hcon any more (lock_sock + hdev->lock) */ +iso_conn_lock (conn); + conn->hcon =NULL ; + hcon->iso_data =NULL ; +iso_conn_unlock (conn); + +iso_conn_put (conn); } static int __iso_chan_add(struct iso_conn *conn, struct sock *sk,
@@ -305,6 +314,11 @@ static int __iso_chan_add(struct iso_conn *conn, struct sock *sk,return -EBUSY ; } +if (!conn->hcon) { +BT_ERR ("conn->hcon missing" ); +return -EIO ; + } +iso_pi (sk)->conn = conn; conn->sk = sk;clear_bit (ISO_CONN_DROPPED , conn->flags);
@@ -2410,6 +2424,7 @@ int iso_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags) }static void iso_connect_cfm (struct hci_conn *hcon,__u8 status) + __must_hold(&hcon->hdev->lock) {if (hcon->type !=CIS_LINK && hcon->type !=BIS_LINK && hcon->type !=PA_LINK ) {
@@ -2421,8 +2436,10 @@ static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)struct hci_link *link, *t;list_for_each_entry_safe (link, t, &hcon->link_list, - list) + list) { +lockdep_assert_held (&link->conn->hdev->lock);iso_conn_del (link->conn,bt_to_errno (status)); + }return ; }
@@ -2452,6 +2469,7 @@ static void iso_connect_cfm(struct hci_conn *hcon, __u8 status) }static void iso_disconn_cfm (struct hci_conn *hcon,__u8 reason) + __must_hold(&hcon->hdev->lock) {if (hcon->type !=CIS_LINK && hcon->type !=BIS_LINK && hcon->type !=PA_LINK )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 120/396 Bluetooth: ISO: fix refcounting of iso_conn
In reply to Greg Kroah-Hartman6.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit fdfde532ab1caa165fcd8985001157ac8b4db365 ]
iso_conn_del() and iso_chan_del() have a race that results to double-put of iso_conn:
[Task hdev->workqueue] [Task 2]
iso_conn_del iso_chan_del
iso_conn_hold_unless_zero iso_conn_lock
iso_conn_lock conn->sk = NULL
iso_conn_unlock
sk = iso_sock_hold(conn) <---------´
if (!sk) iso_conn_put iso_conn_put
iso_conn_put /* UAF */The extra put for !sk in iso_conn_del() is currently required since failing iso_chan_add() may leave iso_conn not associated with any sk.
Fix by having iso_pi(sk)->conn own refcount when non-NULL, so iso_conn_del does not need to put it. Adjust the iso_conn_add() refcounting so that conn is put if it does not get associated with an sk.
--- net/bluetooth/iso.c | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-)
net/bluetooth/iso.c +17 -12
@@ -107,9 +107,6 @@ static void iso_conn_free(struct kref *ref)BT_DBG ("conn %p" , conn); -if (conn->sk) -iso_pi (conn->sk)->conn =NULL ; -if (conn->hcon) { conn->hcon->iso_data =NULL ;if (!test_and_set_bit (ISO_CONN_DROPPED , conn->flags))
@@ -144,6 +141,14 @@ static struct iso_conn *iso_conn_hold_unless_zero(struct iso_conn *conn)return conn; } +static struct iso_conn *iso_conn_hold (struct iso_conn *conn) +{ +BT_DBG ("conn %p refcnt %u" , conn,kref_read (&conn->ref)); + +kref_get (&conn->ref); +return conn; +} +static struct sock *iso_sock_hold (struct iso_conn *conn) {if (!conn || !bt_sock_linked (&iso_sk_list, conn->sk))
@@ -209,7 +214,6 @@ static struct iso_conn *iso_conn_add(struct hci_conn *hcon) conn->hcon = hcon;iso_conn_unlock (conn); } -iso_conn_put (conn);return conn; }
@@ -278,10 +282,8 @@ static void iso_conn_del(struct hci_conn *hcon, int err) sk =iso_sock_hold (conn);iso_conn_unlock (conn); -if (!sk) { -iso_conn_put (conn); +if (!sk) goto done; - }iso_sock_disable_timer (sk);
@@ -319,7 +321,7 @@ static int __iso_chan_add(struct iso_conn *conn, struct sock *sk,return -EIO ; } -iso_pi (sk)->conn = conn; +iso_pi (sk)->conn =iso_conn_hold (conn); conn->sk = sk;clear_bit (ISO_CONN_DROPPED , conn->flags);
@@ -426,6 +428,7 @@ static int iso_connect_bis(struct sock *sk) } err =iso_chan_add (conn, sk,NULL ); +iso_conn_put (conn);if (err) goto unlock;
@@ -528,6 +531,7 @@ static int iso_connect_cis(struct sock *sk) } err =iso_chan_add (conn, sk,NULL ); +iso_conn_put (conn);if (err) goto unlock;
@@ -1228,10 +1232,9 @@ static int iso_listen_bis(struct sock *sk) } err =iso_chan_add (conn, sk,NULL ); -if (err) { -hci_conn_drop (hcon); +iso_conn_put (conn); +if (err) goto unlock; - } unlock:release_sock (sk);
@@ -2461,8 +2464,10 @@ static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)struct iso_conn *conn; conn =iso_conn_add (hcon); -if (conn) +if (conn) {iso_conn_ready (conn); +iso_conn_put (conn); + } }else {iso_conn_del (hcon,bt_to_errno (status)); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 121/396 Bluetooth: btintel: Validate length before parsing diagnostics TLV
In reply to Greg Kroah-Hartman6.18-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
@@ -3694,6 +3694,9 @@ static int btintel_diagnostics(struct hci_dev *hdev, struct sk_buff *skb) {struct intel_tlv *tlv = (void *)&skb->data[5 ]; +if (skb->len <5 +sizeof (*tlv) +sizeof (tlv->val[0 ])) + goto recv_frame; +/* The first event is always an event type TLV */ if (tlv->type !=INTEL_TLV_TYPE_ID ) goto recv_frame;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 122/396 Bluetooth: hci_sync: make hci_cmd_sync_run_once return -EEXIST if exists
In reply to Greg Kroah-Hartman6.18-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
@@ -2968,6 +2968,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.
@@ -2989,7 +2990,8 @@ 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; } void hci_setup_tx_timestamp(struct sk_buff *skb, size_t key_offset,
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 123/396 Bluetooth: hci_conn: hold conn reference in abort_conn_sync()
In reply to Greg Kroah-Hartman6.18-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
@@ -2965,6 +2965,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;
@@ -2990,7 +2997,10 @@ 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 124/396 Bluetooth: hci_sync: fix hci_conn_del() use in hci_le_create_conn_sync
In reply to Greg Kroah-Hartman6.18-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
@@ -6620,7 +6620,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 125/396 Bluetooth: hci_sync: remove unnecessary hci_conn_get in create_conn_sync
In reply to Greg Kroah-Hartman6.18-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
@@ -6604,11 +6604,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 ;
@@ -6623,7 +6618,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 ; }
@@ -6717,7 +6711,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; }
@@ -6992,11 +6985,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. */
@@ -7008,7 +6996,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