6.6.35-rc1 review
Subsystems (5)
Greg Kroah-Hartman
maintainercover 6.6.35-rc1 review
This is the start of the stable review cycle for the 6.6.35 release. There are 267 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 Fri, 21 Jun 2024 12:55:11 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.6.35-rc1.gz
or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.git linux-6.6.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 6.6.35-rc1
Oleg Nesterov <[email protected]>
zap_pid_ns_processes: clear TIF_NOTIFY_SIGNAL along with TIF_SIGPENDING
Jean Delvare <[email protected]>
i2c: designware: Fix the functionality flags of the slave-only interface
Jean Delvare <[email protected]>
i2c: at91: Fix the functionality flags of the slave-only interface
Yongzhi Liu <[email protected]>
misc: microchip: pci1xxxx: Fix a memory leak in the error handling of gp_aux_bus_probe()
Shichao Lai <[email protected]>
usb-storage: alauda: Check whether the media is initialized
Andy Shevchenko <[email protected]>
serial: 8250_dw: Don't use struct dw8250_data outside of 8250_dw
Andy Shevchenko <[email protected]>
serial: 8250_dw: Replace ACPI device check by a quirk
Andy Shevchenko <[email protected]>
serial: 8250_dw: Switch to use uart_read_port_properties()
Andy Shevchenko <[email protected]>
serial: port: Introduce a common helper to read properties
Andy Shevchenko <[email protected]>
serial: core: Add UPIO_UNKNOWN constant for unknown port type
Andy Shevchenko <[email protected]>
device property: Implement device_is_big_endian()
Stefan Berger <[email protected]>
ima: Fix use-after-free on a dentry's dname.name
Sicong Huang <[email protected]>
greybus: Fix use-after-free bug in gb_interface_release due to race condition.
Matthieu Baerts (NGI0) <[email protected]>
selftests: net: lib: avoid error removing empty netns name
Matthieu Baerts (NGI0) <[email protected]>
selftests: net: lib: support errexit with busywait
Hangbin Liu <[email protected]>
selftests/net/lib: no need to record ns name if it already exist
Hangbin Liu <[email protected]>
selftests/net/lib: update busywait timeout value
David Howells <[email protected]>
cachefiles, erofs: Fix NULL deref in when cachefiles is not doing ondemand-mode
Beleswar Padhi <[email protected]>
remoteproc: k3-r5: Jump to error handling labels in start/stop errors
Benjamin Poirier <[email protected]>
selftests: forwarding: Avoid failures to source net/lib.sh
Hangbin Liu <[email protected]>
selftests/net: add variable NS_LIST for lib.sh
Hangbin Liu <[email protected]>
selftests/net: add lib.sh
Sam James <[email protected]>
Revert "fork: defer linking file vma until vma is fully initialized"
Doug Brown <[email protected]>
serial: 8250_pxa: Configure tx_loadsz to match FIFO IRQ level
Miaohe Lin <[email protected]>
mm/huge_memory: don't unpoison huge_zero_folio
Oleg Nesterov <[email protected]>
tick/nohz_full: Don't abuse smp_call_function_single() in tick_setup_device()
Ryusuke Konishi <[email protected]>
nilfs2: fix potential kernel bug due to lack of writeback flag waiting
Petr Tesarik <[email protected]>
swiotlb: extend buffer pre-padding to alloc_align_mask if necessary
Will Deacon <[email protected]>
swiotlb: Reinstate page-alignment for mappings >= PAGE_SIZE
Will Deacon <[email protected]>
swiotlb: Enforce page alignment in swiotlb_alloc()
Andrey Albershteyn <[email protected]>
xfs: allow cross-linking special files without project quota
Dave Chinner <[email protected]>
xfs: don't use current->journal_info
Dave Chinner <[email protected]>
xfs: allow sunit mount option to repair bad primary sb stripe values
Long Li <[email protected]>
xfs: ensure submit buffers on LSN boundaries in error handlers
Dave Chinner <[email protected]>
xfs: shrink failure needs to hold AGI buffer
Dave Chinner <[email protected]>
xfs: fix SEEK_HOLE/DATA for regions with active COW extents
Darrick J. Wong <[email protected]>
xfs: fix scrub stats file permissions
Darrick J. Wong <[email protected]>
xfs: fix imprecise logic in xchk_btree_check_block_owner
Filipe Manana <[email protected]>
btrfs: zoned: fix use-after-free due to race with dev replace
Christoph Hellwig <[email protected]>
btrfs: zoned: factor out DUP bg handling from btrfs_load_block_group_zone_info
Christoph Hellwig <[email protected]>
btrfs: zoned: factor out single bg handling from btrfs_load_block_group_zone_info
Christoph Hellwig <[email protected]>
btrfs: zoned: factor out per-zone logic from btrfs_load_block_group_zone_info
Christoph Hellwig <[email protected]>
btrfs: zoned: introduce a zone_info struct in btrfs_load_block_group_zone_info
Tomi Valkeinen <[email protected]>
pmdomain: ti-sci: Fix duplicate PD referrals
Alexander Shishkin <[email protected]>
intel_th: pci: Add Lunar Lake support
Alexander Shishkin <[email protected]>
intel_th: pci: Add Meteor Lake-S support
Alexander Shishkin <[email protected]>
intel_th: pci: Add Sapphire Rapids SOC support
Alexander Shishkin <[email protected]>
intel_th: pci: Add Granite Rapids SOC support
Alexander Shishkin <[email protected]>
intel_th: pci: Add Granite Rapids support
Imre Deak <[email protected]>
drm/i915: Fix audio component initialization
Vidya Srinivas <[email protected]>
drm/i915/dpt: Make DPT object unshrinkable
Wachowski, Karol <[email protected]>
drm/shmem-helper: Fix BUG_ON() on mmap(PROT_WRITE, MAP_PRIVATE)
Chris Wilson <[email protected]>
drm/i915/gt: Disarm breadcrumbs if engines are already idle
Daniel Bristot de Oliveira <[email protected]>
rtla/auto-analysis: Replace \t with spaces
Daniel Bristot de Oliveira <[email protected]>
rtla/timerlat: Simplify "no value" printing on top
Nam Cao <[email protected]>
riscv: rewrite __kernel_map_pages() to fix sleeping in invalid context
Jean-Baptiste Maneyrol <[email protected]>
iio: invensense: fix interrupt timestamp alignment
Nuno Sa <[email protected]>
iio: adc: axi-adc: make sure AXI clock is enabled
Beleswar Padhi <[email protected]>
remoteproc: k3-r5: Do not allow core1 to power up before core0 via sysfs
Apurva Nandan <[email protected]>
remoteproc: k3-r5: Wait for core0 power-up before powering up core1
Nuno Sa <[email protected]>
dmaengine: axi-dmac: fix possible race in remove()
Rick Wertenbroek <[email protected]>
PCI: rockchip-ep: Remove wrong mask on subsys_vendor_id
Su Yue <[email protected]>
ocfs2: fix races between hole punching and AIO+DIO
Su Yue <[email protected]>
ocfs2: use coarse time for new created files
Rik van Riel <[email protected]>
fs/proc: fix softlockup in __read_vmcore
Trond Myklebust <[email protected]>
knfsd: LOOKUP can return an illegal error value
Vamshi Gajjela <[email protected]>
spmi: hisi-spmi-controller: Do not override device identifier
Hagar Gamal Halim Hemdan <[email protected]>
vmci: prevent speculation leaks by sanitizing event in event_deliver()
Fedor Pchelkin <[email protected]>
dma-buf: handle testing kthreads creation failure
Thadeu Lima de Souza Cascardo <[email protected]>
sock_map: avoid race between sock_map_close and sk_psock_put
Damien Le Moal <[email protected]>
null_blk: Print correct max open zones limit in null_init_zoned_dev()
Matthias Maennich <[email protected]>
kheaders: explicitly define file modes for archived headers
Steven Rostedt (Google) <[email protected]>
tracing/selftests: Fix kprobe event name test for .isra. functions
Nam Cao <[email protected]>
riscv: fix overlap of allocated page and PTR_ERR
Adrian Hunter <[email protected]>
perf auxtrace: Fix multiple use of --itrace option
Haifeng Xu <[email protected]>
perf/core: Fix missing wakeup when waiting for context reference
Yazen Ghannam <[email protected]>
x86/amd_nb: Check for invalid SMN reads
David Kaplan <[email protected]>
x86/kexec: Fix bug with call depth tracking
Hagar Hemdan <[email protected]>
irqchip/gic-v3-its: Fix potential race condition in its_vlpi_prop_update()
Michael J. Ruhl <[email protected]>
clkdev: Update clkdev id usage to allow for longer names
YonglongLi <[email protected]>
mptcp: pm: update add_addr counters after connect
YonglongLi <[email protected]>
mptcp: pm: inc RmAddr MIB counter once per RM_ADDR ID
Paolo Abeni <[email protected]>
mptcp: ensure snd_una is properly initialized on connect
Marek Szyprowski <[email protected]>
drm/exynos: hdmi: report safe 640x480 mode as a fallback when no EDID found
Jani Nikula <[email protected]>
drm/exynos/vidi: fix memory leak in .get_modes()
Mario Limonciello <[email protected]>
ACPI: x86: Force StorageD3Enable on more products
John David Anglin <[email protected]>
parisc: Try to fix random segmentation faults in package builds
Dirk Behme <[email protected]>
drivers: core: synchronize really_probe() and dev_uevent()
Jean-Baptiste Maneyrol <[email protected]>
iio: imu: inv_icm42600: delete unneeded update watermark call
Jean-Baptiste Maneyrol <[email protected]>
iio: invensense: fix odr switching to same value
Marc Ferland <[email protected]>
iio: dac: ad5592r: fix temperature channel scaling value
David Lechner <[email protected]>
iio: adc: ad9467: fix scan type sign
Benjamin Segall <[email protected]>
x86/boot: Don't add the EFI stub to targets, again
Namjae Jeon <[email protected]>
ksmbd: fix missing use of get_write in in smb2_set_ea()
Namjae Jeon <[email protected]>
ksmbd: move leading slash check to smb2_get_name()
Yongzhi Liu <[email protected]>
misc: microchip: pci1xxxx: fix double free in the error handling of gp_aux_bus_probe()
Aleksandr Mishin <[email protected]>
bnxt_en: Adjust logging of firmware messages in case of released token in __hwrm_send()
Rao Shoaib <[email protected]>
af_unix: Read with MSG_PEEK loops if the first unread byte is OOB
Taehee Yoo <[email protected]>
ionic: fix use after netif_napi_del()
Nikolay Aleksandrov <[email protected]>
net: bridge: mst: fix suspicious rcu usage in br_mst_set_state
Nikolay Aleksandrov <[email protected]>
net: bridge: mst: pass vlan group directly to br_mst_vlan_set_state
Petr Pavlu <[email protected]>
net/ipv6: Fix the RT cache flush via sysctl using a previous delay
Daniel Wagner <[email protected]>
nvmet-passthru: propagate status from id override functions
Chengming Zhou <[email protected]>
block: fix request.queuelist usage in flush
Su Hui <[email protected]>
block: sed-opal: avoid possible wrong address reference in read_sed_opal_key()
Xiaolei Wang <[email protected]>
net: stmmac: replace priv->speed with the portTransmitRate from the tc-cbs parameters
Joshua Washington <[email protected]>
gve: ignore nonrelevant GSO type bits when processing TSO headers
Kory Maincent <[email protected]>
net: pse-pd: Use EOPNOTSUPP error code instead of ENOTSUPP
Ziqi Chen <[email protected]>
scsi: ufs: core: Quiesce request queues before checking pending cmds
Kees Cook <[email protected]>
x86/uaccess: Fix missed zeroing of ia32 u64 get_user() range checking
Uros Bizjak <[email protected]>
x86/asm: Use %c/%n instead of %P operand modifier in asm templates
Jozsef Kadlecsik <[email protected]>
netfilter: ipset: Fix race between namespace cleanup and gc in the list:set type
Davide Ornaghi <[email protected]>
netfilter: nft_inner: validate mandatory meta and payload
Pauli Virtanen <[email protected]>
Bluetooth: fix connection setup in l2cap_connect
Luiz Augusto von Dentz <[email protected]>
Bluetooth: L2CAP: Fix rejecting L2CAP_CONN_PARAM_UPDATE_REQ
Gal Pressman <[email protected]>
net/mlx5e: Fix features validation check for tunneled UDP (non-VXLAN) packets
Gal Pressman <[email protected]>
geneve: Fix incorrect inner network header offset when innerprotoinherit is set
Andy Shevchenko <[email protected]>
net dsa: qca8k: fix usages of device_get_named_child_node()
Eric Dumazet <[email protected]>
tcp: fix race in tcp_v6_syn_recv_sock()
Adam Miotk <[email protected]>
drm/bridge/panel: Fix runtime warning on panel bridge release
Amjad Ouled-Ameur <[email protected]>
drm/komeda: check for error-valued pointer
Sagar Cheluvegowda <[email protected]>
net: stmmac: dwmac-qcom-ethqos: Configure host DMA width
Aleksandr Mishin <[email protected]>
liquidio: Adjust a NULL pointer handling path in lio_vf_rep_copy_packet
Jie Wang <[email protected]>
net: hns3: add cond_resched() to hns3 ring buffer init process
Yonglong Liu <[email protected]>
net: hns3: fix kernel crash problem in concurrent scenario
Csókás, Bence <[email protected]>
net: sfp: Always call sfp_sm_mod_remove() on remove
Masahiro Yamada <[email protected]>
modpost: do not warn about missing MODULE_DESCRIPTION() for vmlinux.o
Kuniyuki Iwashima <[email protected]>
af_unix: Annotate data-race of sk->sk_state in unix_accept().
Ian Forbes <[email protected]>
drm/vmwgfx: Don't memcmp equivalent pointers
Ian Forbes <[email protected]>
drm/vmwgfx: Remove STDU logic from generic mode_valid function
Ian Forbes <[email protected]>
drm/vmwgfx: 3D disabled should not effect STDU memory limits
Ian Forbes <[email protected]>
drm/vmwgfx: Filter modes which exceed graphics memory
Martin Krastev <[email protected]>
drm/vmwgfx: Refactor drm connector probing for display modes
José Expósito <[email protected]>
HID: logitech-dj: Fix memory leak in logi_dj_recv_switch_to_dj_mode()
Su Hui <[email protected]>
io_uring/io-wq: avoid garbage value of 'match' in io_wq_enqueue()
Breno Leitao <[email protected]>
io_uring/io-wq: Use set_bit() and test_bit() at worker->flags
Lu Baolu <[email protected]>
iommu: Return right value in iommu_sva_bind_device()
Kun(llfl) <[email protected]>
iommu/amd: Fix sysfs leak in iommu init
Nikita Zhandarovich <[email protected]>
HID: core: remove unnecessary WARN_ON() in implement()
Matthias Schiffer <[email protected]>
gpio: tqmx86: fix broken IRQ_TYPE_EDGE_BOTH interrupt type
Matthias Schiffer <[email protected]>
gpio: tqmx86: store IRQ trigger type and unmask status separately
Matthias Schiffer <[email protected]>
gpio: tqmx86: introduce shadow register for GPIO output value
Gregor Herburger <[email protected]>
gpio: tqmx86: fix typo in Kconfig label
Armin Wolf <[email protected]>
platform/x86: dell-smbios: Fix wrong token data in sysfs
Chen Ni <[email protected]>
drm/panel: sitronix-st7789v: Add check for of_drm_get_panel_orientation
Weiwen Hu <[email protected]>
nvme: fix nvme_pr_* status code parsing
Masami Hiramatsu (Google) <[email protected]>
selftests/tracing: Fix event filter test to retry up to 10 times
NeilBrown <[email protected]>
NFS: add barriers when testing for NFS_FSDATA_BLOCKED
Chen Hanxiao <[email protected]>
SUNRPC: return proper error from gss_wrap_req_priv
Olga Kornievskaia <[email protected]>
NFSv4.1 enforce rootpath check in fs_location query
Samuel Holland <[email protected]>
clk: sifive: Do not register clkdevs for PRCI clocks
Masami Hiramatsu (Google) <[email protected]>
selftests/ftrace: Fix to check required event file
Baokun Li <[email protected]>
cachefiles: flush all requests after setting CACHEFILES_DEAD
Baokun Li <[email protected]>
cachefiles: defer exposing anon_fd until after copy_to_user() succeeds
Baokun Li <[email protected]>
cachefiles: never get a new anonymous fd if ondemand_id is valid
Baokun Li <[email protected]>
cachefiles: remove err_put_fd label in cachefiles_ondemand_daemon_read()
Baokun Li <[email protected]>
cachefiles: fix slab-use-after-free in cachefiles_ondemand_daemon_read()
Baokun Li <[email protected]>
cachefiles: fix slab-use-after-free in cachefiles_ondemand_get_fd()
Jia Zhu <[email protected]>
cachefiles: add restore command to recover inflight ondemand read requests
Baokun Li <[email protected]>
cachefiles: add spin_lock for cachefiles_ondemand_info
Jia Zhu <[email protected]>
cachefiles: resend an open request if the read request's object is closed
Jia Zhu <[email protected]>
cachefiles: extract ondemand info field from cachefiles_object
Jia Zhu <[email protected]>
cachefiles: introduce object ondemand state
Baokun Li <[email protected]>
cachefiles: remove requests from xarray during flushing requests
Baokun Li <[email protected]>
cachefiles: add output string to cachefiles_obj_[get|put]_ondemand_fd
Li Zhijian <[email protected]>
cxl/region: Fix memregion leaks in devm_cxl_add_region()
Dave Jiang <[email protected]>
cxl/test: Add missing vmalloc.h for tools/testing/cxl/test/mem.c
Chen Ni <[email protected]>
HID: nvidia-shield: Add missing check for input_ff_create_memless
Michael Ellerman <[email protected]>
powerpc/uaccess: Fix build errors seen with GCC 13/14
Ziwei Xiao <[email protected]>
gve: Clear napi->skb before dev_kfree_skb_any()
Martin K. Petersen <[email protected]>
scsi: sd: Use READ(16) when reading block zero on large capacity disks
Breno Leitao <[email protected]>
scsi: mpt3sas: Avoid test/set_bit() operating in non-allocated memory
Damien Le Moal <[email protected]>
scsi: mpi3mr: Fix ATA NCQ priority support
Damien Le Moal <[email protected]>
scsi: core: Disable CDL by default
Aapo Vienamo <[email protected]>
thunderbolt: debugfs: Fix margin debugfs node creation condition
Kuangyi Chiang <[email protected]>
xhci: Apply broken streams quirk to Etron EJ188 xHCI host
Hector Martin <[email protected]>
xhci: Handle TD clearing for multiple streams case
Kuangyi Chiang <[email protected]>
xhci: Apply reset resume quirk to Etron EJ188 xHCI host
Mathias Nyman <[email protected]>
xhci: Set correct transferred length for cancelled bulk transfers
Greg Kroah-Hartman <[email protected]>
jfs: xattr: fix buffer overflow for invalid xattr
Mickaël Salaün <[email protected]>
landlock: Fix d_parent walk
Douglas Anderson <[email protected]>
serial: port: Don't block system suspend even if bytes are left to xmit
Ilpo Järvinen <[email protected]>
tty: n_tty: Fix buffer offsets when lookahead is used
Tomas Winkler <[email protected]>
mei: me: release irq in mei_me_pci_resume error path
Kyle Tso <[email protected]>
usb: typec: tcpm: Ignore received Hard Reset in TOGGLING state
Amit Sunil Dhamne <[email protected]>
usb: typec: tcpm: fix use-after-free case in tcpm_register_source_caps
John Ernberg <[email protected]>
USB: xen-hcd: Traverse host/ when CONFIG_USB_XEN_HCD is selected
Alan Stern <[email protected]>
USB: class: cdc-wdm: Fix CPU lockup caused by excessive log messages
Jens Axboe <[email protected]>
io_uring: check for non-NULL file pointer in io_file_can_poll()
Pavel Begunkov <[email protected]>
io_uring/rsrc: don't lock while !TASK_RUNNING
Ryusuke Konishi <[email protected]>
nilfs2: fix nilfs_empty_dir() misjudgment and long loop on I/O errors
Matthew Wilcox (Oracle) <[email protected]>
nilfs2: return the mapped address from nilfs_get_page()
Andrii Nakryiko <[email protected]>
bpf: fix multi-uprobe PID filtering logic
Steven Rostedt (Google) <[email protected]>
eventfs: Update all the eventfs_inodes from the events descriptor
Sunil V L <[email protected]>
irqchip/riscv-intc: Prevent memory leak when riscv_intc_init_common() fails
Yu Chien Peter Lin <[email protected]>
irqchip/riscv-intc: Introduce Andes hart-level interrupt controller
Yu Chien Peter Lin <[email protected]>
irqchip/riscv-intc: Allow large non-standard interrupt number
Dev Jain <[email protected]>
selftests/mm: compaction_test: fix bogus test success on Aarch64
Mark Brown <[email protected]>
selftests/mm: log a consistent test name for check_compaction
Muhammad Usama Anjum <[email protected]>
selftests/mm: conform test to TAP format output
Miaohe Lin <[email protected]>
mm/memory-failure: fix handling of dissolved but not taken off from buddy pages
Matthew Wilcox (Oracle) <[email protected]>
memory-failure: use a folio in me_huge_page()
Gabor Juhos <[email protected]>
firmware: qcom_scm: disable clocks if qcom_scm_bw_enable() fails
Namjae Jeon <[email protected]>
ksmbd: use rwsem instead of rwlock for lease break
Su Hui <[email protected]>
net: ethtool: fix the error condition in ethtool_get_phy_stats_ethtool()
Eric Dumazet <[email protected]>
ipv6: fix possible race in __fib6_drop_pcpu_from()
Kuniyuki Iwashima <[email protected]>
af_unix: Annotate data-race of sk->sk_shutdown in sk_diag_fill().
Kuniyuki Iwashima <[email protected]>
af_unix: Use skb_queue_len_lockless() in sk_diag_show_rqlen().
Kuniyuki Iwashima <[email protected]>
af_unix: Use skb_queue_empty_lockless() in unix_release_sock().
Kuniyuki Iwashima <[email protected]>
af_unix: Use unix_recvq_full_lockless() in unix_stream_connect().
Kuniyuki Iwashima <[email protected]>
af_unix: Annotate data-race of net->unx.sysctl_max_dgram_qlen.
Kuniyuki Iwashima <[email protected]>
af_unix: Annotate data-races around sk->sk_sndbuf.
Kuniyuki Iwashima <[email protected]>
af_unix: Annotate data-races around sk->sk_state in UNIX_DIAG.
Kuniyuki Iwashima <[email protected]>
af_unix: Annotate data-race of sk->sk_state in unix_stream_read_skb().
Kuniyuki Iwashima <[email protected]>
af_unix: Annotate data-races around sk->sk_state in sendmsg() and recvmsg().
Kuniyuki Iwashima <[email protected]>
af_unix: Annotate data-race of sk->sk_state in unix_stream_connect().
Kuniyuki Iwashima <[email protected]>
af_unix: Annotate data-races around sk->sk_state in unix_write_space() and poll().
Kuniyuki Iwashima <[email protected]>
af_unix: Annotate data-race of sk->sk_state in unix_inq_len().
Kuniyuki Iwashima <[email protected]>
af_unix: Annodate data-races around sk->sk_state for writers.
Kuniyuki Iwashima <[email protected]>
af_unix: Set sk->sk_state under unix_state_lock() for truly disconencted peer.
Aleksandr Mishin <[email protected]>
net: wwan: iosm: Fix tainted pointer delete is case of region creation fail
Larysa Zaremba <[email protected]>
ice: add flag to distinguish reset from .ndo_bpf in XDP rings config
Larysa Zaremba <[email protected]>
ice: remove af_xdp_zc_qps bitmap
Jacob Keller <[email protected]>
ice: fix iteration of TLVs in Preserved Fields Area
Karol Kolacinski <[email protected]>
ptp: Fix error message on failed pin verification
Eric Dumazet <[email protected]>
net/sched: taprio: always validate TCA_TAPRIO_ATTR_PRIOMAP
Aleksandr Mishin <[email protected]>
net/mlx5: Fix tainted pointer delete is case of flow rules creation fail
Shay Drory <[email protected]>
net/mlx5: Always stop health timer during driver removal
Moshe Shemesh <[email protected]>
net/mlx5: Stop waiting for PCI if pci channel is offline
Jason Xing <[email protected]>
mptcp: count CLOSE-WAIT sockets for MPTCP_MIB_CURRESTAB
Jason Xing <[email protected]>
tcp: count CLOSE-WAIT sockets for TCP_MIB_CURRESTAB
Daniel Borkmann <[email protected]>
vxlan: Fix regression when dropping packets due to invalid src addresses
Hangyu Hua <[email protected]>
net: sched: sch_multiq: fix possible OOB write in multiq_tune()
Tristram Ha <[email protected]>
net: phy: Micrel KSZ8061: fix errata solution not taking effect problem
Wen Gu <[email protected]>
net/smc: avoid overwriting when adjusting sock bufsizes
Subbaraya Sundeep <[email protected]>
octeontx2-af: Always allocate PF entries from low prioriy zone
Jiri Olsa <[email protected]>
bpf: Set run context for rawtp test_run callback
Jakub Kicinski <[email protected]>
net: tls: fix marking packets as decrypted
Eric Dumazet <[email protected]>
ipv6: sr: block BH in seg6_output_core() and seg6_input_core()
Eric Dumazet <[email protected]>
ipv6: ioam: block BH from ioam6_output()
Matthias Stocker <[email protected]>
vmxnet3: disable rx data ring on dma allocation failure
Ravi Bangoria <[email protected]>
KVM: SEV-ES: Delegate LBR virtualization to the processor
Michael Roth <[email protected]>
KVM: SEV: Do not intercept accesses to MSR_IA32_XSS for SEV-ES guests
Ravi Bangoria <[email protected]>
KVM: SEV-ES: Disallow SEV-ES guests when X86_FEATURE_LBRV is absent
Cong Wang <[email protected]>
bpf: Fix a potential use-after-free in bpf_link_free()
Hou Tao <[email protected]>
bpf: Optimize the free of inner map
Jiri Olsa <[email protected]>
bpf: Store ref_ctr_offsets values in bpf_uprobe array
Tristram Ha <[email protected]>
net: phy: micrel: fix KSZ9477 PHY issues after suspend/resume
DelphineCCChiu <[email protected]>
net/ncsi: Fix the multi thread manner of NCSI driver
Peter Delevoryas <[email protected]>
net/ncsi: Simplify Kconfig/dts control flow
Duoming Zhou <[email protected]>
ax25: Replace kfree() in ax25_dev_free() with ax25_dev_put()
Lars Kellogg-Stedman <[email protected]>
ax25: Fix refcount imbalance on inbound connections
Quan Zhou <[email protected]>
RISC-V: KVM: Fix incorrect reg_subtype labels in kvm_riscv_vcpu_set_reg_isa_ext function
Yong-Xuan Wang <[email protected]>
RISC-V: KVM: No need to use mask when hart-index-bit is 0
Chanwoo Lee <[email protected]>
scsi: ufs: mcq: Fix error output and clean up ufshcd_mcq_abort()
Lingbo Kong <[email protected]>
wifi: mac80211: correctly parse Spatial Reuse Parameter Set element
Emmanuel Grumbach <[email protected]>
wifi: iwlwifi: mvm: don't read past the mfuart notifcation
Miri Korenblit <[email protected]>
wifi: iwlwifi: mvm: check n_ssids before accessing the ssids
Shahar S Matityahu <[email protected]>
wifi: iwlwifi: dbg_ini: move iwl_dbg_tlv_free outside of debugfs ifdef
Mordechay Goodstein <[email protected]>
wifi: iwlwifi: mvm: set properly mac header
Johannes Berg <[email protected]>
wifi: iwlwifi: mvm: revert gen2 TX A-MPDU size to 64
Miri Korenblit <[email protected]>
wifi: iwlwifi: mvm: don't initialize csa_work twice
Lin Ma <[email protected]>
wifi: cfg80211: pmsr: use correct nla_get_uX functions
Remi Pommarel <[email protected]>
wifi: cfg80211: Lock wiphy in cfg80211_get_station
Johannes Berg <[email protected]>
wifi: cfg80211: fully move wiphy work to unbound workqueue
Remi Pommarel <[email protected]>
wifi: mac80211: Fix deadlock in ieee80211_sta_ps_deliver_wakeup()
Nicolas Escande <[email protected]>
wifi: mac80211: mesh: Fix leak of mesh_preq_queue objects
-------------
Diffstat:
Makefile | 4 +- arch/parisc/include/asm/cacheflush.h | 15 +- arch/parisc/include/asm/pgtable.h | 27 +- arch/parisc/kernel/cache.c | 421 +++++++++++++-------- arch/powerpc/include/asm/uaccess.h | 16 + arch/riscv/kvm/aia_device.c | 7 +- arch/riscv/kvm/vcpu_onereg.c | 4 +- arch/riscv/mm/init.c | 21 +- arch/riscv/mm/pageattr.c | 28 +- arch/x86/boot/compressed/Makefile | 4 +- arch/x86/boot/main.c | 4 +- arch/x86/include/asm/alternative.h | 22 +- arch/x86/include/asm/atomic64_32.h | 2 +- arch/x86/include/asm/cpufeature.h | 2 +- arch/x86/include/asm/irq_stack.h | 2 +- arch/x86/include/asm/uaccess.h | 6 +- arch/x86/kernel/amd_nb.c | 9 +- arch/x86/kernel/machine_kexec_64.c | 11 +- arch/x86/kvm/svm/sev.c | 38 +- arch/x86/kvm/svm/svm.c | 25 +- arch/x86/kvm/svm/svm.h | 4 +- arch/x86/lib/getuser.S | 6 +- block/blk-flush.c | 3 +- block/sed-opal.c | 2 +- drivers/acpi/x86/utils.c | 24 +- drivers/base/core.c | 3 + drivers/block/null_blk/zoned.c | 2 +- drivers/clk/clkdev.c | 2 +- drivers/clk/sifive/sifive-prci.c | 8 - drivers/cxl/core/region.c | 18 +- drivers/dma-buf/st-dma-fence.c | 6 + drivers/dma/dma-axi-dmac.c | 2 +- drivers/firmware/qcom_scm.c | 18 +- drivers/gpio/Kconfig | 2 +- drivers/gpio/gpio-tqmx86.c | 110 ++++-- .../drm/arm/display/komeda/komeda_pipeline_state.c | 2 +- drivers/gpu/drm/bridge/panel.c | 7 +- drivers/gpu/drm/drm_gem_shmem_helper.c | 3 + drivers/gpu/drm/exynos/exynos_drm_vidi.c | 7 +- drivers/gpu/drm/exynos/exynos_hdmi.c | 7 +- drivers/gpu/drm/i915/display/intel_audio.c | 32 +- drivers/gpu/drm/i915/display/intel_audio.h | 1 + .../gpu/drm/i915/display/intel_display_driver.c | 2 + drivers/gpu/drm/i915/gem/i915_gem_object.h | 4 +- drivers/gpu/drm/i915/gt/intel_breadcrumbs.c | 15 +- drivers/gpu/drm/panel/panel-sitronix-st7789v.c | 4 +- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 7 - drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 3 - drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 276 +++++--------- drivers/gpu/drm/vmwgfx/vmwgfx_kms.h | 6 +- drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c | 5 +- drivers/gpu/drm/vmwgfx/vmwgfx_scrn.c | 5 +- drivers/gpu/drm/vmwgfx/vmwgfx_stdu.c | 47 ++- drivers/greybus/interface.c | 1 + drivers/hid/hid-core.c | 1 - drivers/hid/hid-logitech-dj.c | 4 +- drivers/hid/hid-nvidia-shield.c | 4 +- drivers/hwtracing/intel_th/pci.c | 25 ++ drivers/i2c/busses/i2c-at91-slave.c | 3 +- drivers/i2c/busses/i2c-designware-slave.c | 2 +- drivers/iio/adc/ad9467.c | 4 +- drivers/iio/adc/adi-axi-adc.c | 5 + .../iio/common/inv_sensors/inv_sensors_timestamp.c | 15 +- drivers/iio/dac/ad5592r-base.c | 2 +- drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c | 4 - drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c | 4 - drivers/iommu/amd/init.c | 9 + drivers/irqchip/irq-gic-v3-its.c | 44 +-- drivers/irqchip/irq-riscv-intc.c | 89 ++++- drivers/misc/mchp_pci1xxxx/mchp_pci1xxxx_gp.c | 9 +- drivers/misc/mei/pci-me.c | 4 +- drivers/misc/vmw_vmci/vmci_event.c | 6 +- drivers/net/dsa/qca/qca8k-leds.c | 12 +- drivers/net/ethernet/broadcom/bnxt/bnxt_hwrm.c | 2 +- drivers/net/ethernet/cavium/liquidio/lio_vf_rep.c | 11 +- drivers/net/ethernet/google/gve/gve_rx_dqo.c | 8 +- drivers/net/ethernet/google/gve/gve_tx_dqo.c | 20 +- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 4 + drivers/net/ethernet/hisilicon/hns3/hns3_enet.h | 2 + .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 21 +- drivers/net/ethernet/intel/ice/ice.h | 43 ++- drivers/net/ethernet/intel/ice/ice_lib.c | 13 +- drivers/net/ethernet/intel/ice/ice_main.c | 22 +- drivers/net/ethernet/intel/ice/ice_nvm.c | 28 +- drivers/net/ethernet/intel/ice/ice_xsk.c | 13 +- .../net/ethernet/marvell/octeontx2/af/rvu_npc.c | 33 +- drivers/net/ethernet/mellanox/mlx5/core/en_main.c | 3 +- drivers/net/ethernet/mellanox/mlx5/core/fw.c | 4 + drivers/net/ethernet/mellanox/mlx5/core/health.c | 8 + .../net/ethernet/mellanox/mlx5/core/lag/port_sel.c | 8 +- .../net/ethernet/mellanox/mlx5/core/lib/pci_vsc.c | 4 + drivers/net/ethernet/mellanox/mlx5/core/main.c | 3 + drivers/net/ethernet/pensando/ionic/ionic_lif.c | 4 +- .../ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 4 + drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 25 +- drivers/net/geneve.c | 10 +- drivers/net/phy/micrel.c | 104 ++++- drivers/net/phy/sfp.c | 3 +- drivers/net/vmxnet3/vmxnet3_drv.c | 2 +- drivers/net/vxlan/vxlan_core.c | 4 + drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 2 +- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 10 - .../net/wireless/intel/iwlwifi/mvm/mld-mac80211.c | 2 - drivers/net/wireless/intel/iwlwifi/mvm/rs.h | 9 +- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 5 +- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 4 +- drivers/net/wwan/iosm/iosm_ipc_devlink.c | 2 +- drivers/nvme/host/pr.c | 2 +- drivers/nvme/target/passthru.c | 6 +- drivers/pci/controller/pcie-rockchip-ep.c | 6 +- drivers/platform/x86/dell/dell-smbios-base.c | 92 ++--- drivers/pmdomain/ti/ti_sci_pm_domains.c | 20 +- drivers/ptp/ptp_chardev.c | 3 +- drivers/remoteproc/ti_k3_r5_remoteproc.c | 58 ++- drivers/scsi/mpi3mr/mpi3mr_app.c | 62 +++ drivers/scsi/mpt3sas/mpt3sas_base.c | 19 + drivers/scsi/mpt3sas/mpt3sas_base.h | 3 - drivers/scsi/mpt3sas/mpt3sas_ctl.c | 4 +- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 23 -- drivers/scsi/scsi.c | 7 + drivers/scsi/scsi_transport_sas.c | 23 ++ drivers/scsi/sd.c | 17 +- drivers/spmi/hisi-spmi-controller.c | 1 - drivers/thunderbolt/debugfs.c | 5 +- drivers/tty/n_tty.c | 22 +- drivers/tty/serial/8250/8250_dw.c | 125 +++--- drivers/tty/serial/8250/8250_dwlib.c | 3 +- drivers/tty/serial/8250/8250_dwlib.h | 3 +- drivers/tty/serial/8250/8250_pxa.c | 1 + drivers/tty/serial/serial_port.c | 152 ++++++++ drivers/ufs/core/ufs-mcq.c | 17 +- drivers/ufs/core/ufshcd.c | 6 +- drivers/usb/Makefile | 1 + drivers/usb/class/cdc-wdm.c | 4 +- drivers/usb/host/xhci-pci.c | 7 + drivers/usb/host/xhci-ring.c | 59 ++- drivers/usb/host/xhci.h | 1 + drivers/usb/storage/alauda.c | 9 +- drivers/usb/typec/tcpm/tcpm.c | 5 +- fs/btrfs/zoned.c | 330 ++++++++-------- fs/cachefiles/daemon.c | 4 +- fs/cachefiles/interface.c | 7 +- fs/cachefiles/internal.h | 52 ++- fs/cachefiles/ondemand.c | 324 ++++++++++++---- fs/jfs/xattr.c | 4 +- fs/nfs/dir.c | 47 ++- fs/nfs/nfs4proc.c | 23 +- fs/nfsd/nfsfh.c | 4 +- fs/nilfs2/dir.c | 59 ++- fs/nilfs2/segment.c | 3 + fs/ocfs2/file.c | 2 + fs/ocfs2/namei.c | 2 +- fs/proc/vmcore.c | 2 + fs/smb/server/oplock.c | 30 +- fs/smb/server/smb2pdu.c | 26 +- fs/smb/server/smb_common.c | 4 +- fs/smb/server/vfs.c | 17 +- fs/smb/server/vfs.h | 3 +- fs/smb/server/vfs_cache.c | 31 +- fs/smb/server/vfs_cache.h | 2 +- fs/tracefs/event_inode.c | 59 ++- fs/xfs/libxfs/xfs_ag.c | 11 +- fs/xfs/libxfs/xfs_sb.c | 40 +- fs/xfs/libxfs/xfs_sb.h | 5 +- fs/xfs/scrub/btree.c | 7 +- fs/xfs/scrub/common.c | 4 +- fs/xfs/scrub/stats.c | 4 +- fs/xfs/xfs_aops.c | 7 - fs/xfs/xfs_icache.c | 8 +- fs/xfs/xfs_inode.c | 15 +- fs/xfs/xfs_iomap.c | 4 +- fs/xfs/xfs_log_recover.c | 23 +- fs/xfs/xfs_trans.h | 9 +- include/linux/bpf.h | 2 + include/linux/iommu.h | 2 +- include/linux/property.h | 26 ++ include/linux/pse-pd/pse.h | 4 +- include/linux/serial_core.h | 3 + include/linux/soc/andes/irq.h | 18 + include/net/bluetooth/hci_core.h | 36 +- include/net/ip_tunnels.h | 5 +- include/scsi/scsi_transport_sas.h | 2 + include/trace/events/cachefiles.h | 8 +- io_uring/io-wq.c | 57 +-- io_uring/kbuf.c | 3 +- io_uring/rsrc.c | 1 + kernel/bpf/core.c | 4 + kernel/bpf/map_in_map.c | 14 +- kernel/bpf/syscall.c | 19 +- kernel/bpf/verifier.c | 4 +- kernel/dma/swiotlb.c | 83 +++- kernel/events/core.c | 13 + kernel/fork.c | 18 +- kernel/gen_kheaders.sh | 2 +- kernel/pid_namespace.c | 1 + kernel/time/tick-common.c | 42 +- kernel/trace/bpf_trace.c | 22 +- mm/memory-failure.c | 23 +- net/ax25/af_ax25.c | 6 + net/ax25/ax25_dev.c | 2 +- net/bluetooth/l2cap_core.c | 12 +- net/bpf/test_run.c | 6 + net/bridge/br_mst.c | 13 +- net/core/sock_map.c | 16 +- net/ethtool/ioctl.c | 2 +- net/ipv4/tcp.c | 9 +- net/ipv6/ioam6_iptunnel.c | 8 +- net/ipv6/ip6_fib.c | 6 +- net/ipv6/route.c | 5 +- net/ipv6/seg6_iptunnel.c | 14 +- net/ipv6/tcp_ipv6.c | 3 +- net/mac80211/he.c | 10 +- net/mac80211/mesh_pathtbl.c | 13 + net/mac80211/sta_info.c | 4 +- net/mptcp/pm_netlink.c | 21 +- net/mptcp/protocol.c | 10 +- net/ncsi/internal.h | 2 + net/ncsi/ncsi-manage.c | 95 ++--- net/ncsi/ncsi-rsp.c | 4 +- net/netfilter/ipset/ip_set_core.c | 93 +++-- net/netfilter/ipset/ip_set_list_set.c | 30 +- net/netfilter/nft_meta.c | 3 + net/netfilter/nft_payload.c | 4 + net/sched/sch_multiq.c | 2 +- net/sched/sch_taprio.c | 15 +- net/smc/af_smc.c | 22 +- net/sunrpc/auth_gss/auth_gss.c | 4 +- net/unix/af_unix.c | 108 +++--- net/unix/diag.c | 12 +- net/wireless/core.c | 2 +- net/wireless/pmsr.c | 8 +- net/wireless/sysfs.c | 4 +- net/wireless/util.c | 7 +- scripts/mod/modpost.c | 5 +- security/integrity/ima/ima_api.c | 16 +- security/integrity/ima/ima_template_lib.c | 17 +- security/landlock/fs.c | 13 +- tools/perf/util/auxtrace.c | 4 +- tools/testing/cxl/test/mem.c | 1 + .../ftrace/test.d/dynevent/test_duplicates.tc | 2 +- .../ftrace/test.d/filter/event-filter-function.tc | 20 +- .../ftrace/test.d/kprobe/kprobe_eventname.tc | 3 +- tools/testing/selftests/mm/compaction_test.c | 106 +++--- tools/testing/selftests/net/Makefile | 2 +- tools/testing/selftests/net/forwarding/lib.sh | 52 +-- tools/testing/selftests/net/lib.sh | 97 +++++ tools/testing/selftests/net/mptcp/mptcp_join.sh | 5 +- tools/tracing/rtla/src/timerlat_aa.c | 109 +++--- tools/tracing/rtla/src/timerlat_top.c | 17 +- 249 files changed, 3442 insertions(+), 1950 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/267 wifi: mac80211: mesh: Fix leak of mesh_preq_queue objects
6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicolas Escande <[email protected]>
[ Upstream commit b7d7f11a291830fdf69d3301075dd0fb347ced84 ]
The hwmp code use objects of type mesh_preq_queue, added to a list in ieee80211_if_mesh, to keep track of mpath we need to resolve. If the mpath gets deleted, ex mesh interface is removed, the entries in that list will never get cleaned. Fix this by flushing all corresponding items of the preq_queue in mesh_path_flush_pending().
This should take care of KASAN reports like this:
unreferenced object 0xffff00000668d800 (size 128):
comm "kworker/u8:4", pid 67, jiffies 4295419552 (age 1836.444s) hex dump (first 32 bytes):
00 1f 05 09 00 00 ff ff 00 d5 68 06 00 00 ff ff ..........h.....
8e 97 ea eb 3e b8 01 00 00 00 00 00 00 00 00 00 ....>...........
backtrace:
[<000000007302a0b6>] __kmem_cache_alloc_node+0x1e0/0x35c
[<00000000049bd418>] kmalloc_trace+0x34/0x80
[<0000000000d792bb>] mesh_queue_preq+0x44/0x2a8
[<00000000c99c3696>] mesh_nexthop_resolve+0x198/0x19c
[<00000000926bf598>] ieee80211_xmit+0x1d0/0x1f4
[<00000000fc8c2284>] __ieee80211_subif_start_xmit+0x30c/0x764
[<000000005926ee38>] ieee80211_subif_start_xmit+0x9c/0x7a4
[<000000004c86e916>] dev_hard_start_xmit+0x174/0x440
[<0000000023495647>] __dev_queue_xmit+0xe24/0x111c
[<00000000cfe9ca78>] batadv_send_skb_packet+0x180/0x1e4
[<000000007bacc5d5>] batadv_v_elp_periodic_work+0x2f4/0x508
[<00000000adc3cd94>] process_one_work+0x4b8/0xa1c
[<00000000b36425d1>] worker_thread+0x9c/0x634
[<0000000005852dd5>] kthread+0x1bc/0x1c4
[<000000005fccd770>] ret_from_fork+0x10/0x20
unreferenced object 0xffff000009051f00 (size 128):
comm "kworker/u8:4", pid 67, jiffies 4295419553 (age 1836.440s)
hex dump (first 32 bytes):
90 d6 92 0d 00 00 ff ff 00 d8 68 06 00 00 ff ff ..........h.....
36 27 92 e4 02 e0 01 00 00 58 79 06 00 00 ff ff 6'.......Xy.....
backtrace:
[<000000007302a0b6>] __kmem_cache_alloc_node+0x1e0/0x35c
[<00000000049bd418>] kmalloc_trace+0x34/0x80
[<0000000000d792bb>] mesh_queue_preq+0x44/0x2a8
[<00000000c99c3696>] mesh_nexthop_resolve+0x198/0x19c
[<00000000926bf598>] ieee80211_xmit+0x1d0/0x1f4
[<00000000fc8c2284>] __ieee80211_subif_start_xmit+0x30c/0x764
[<000000005926ee38>] ieee80211_subif_start_xmit+0x9c/0x7a4
[<000000004c86e916>] dev_hard_start_xmit+0x174/0x440
[<0000000023495647>] __dev_queue_xmit+0xe24/0x111c
[<00000000cfe9ca78>] batadv_send_skb_packet+0x180/0x1e4
[<000000007bacc5d5>] batadv_v_elp_periodic_work+0x2f4/0x508
[<00000000adc3cd94>] process_one_work+0x4b8/0xa1c
[<00000000b36425d1>] worker_thread+0x9c/0x634
[<0000000005852dd5>] kthread+0x1bc/0x1c4
[<000000005fccd770>] ret_from_fork+0x10/0x20--- net/mac80211/mesh_pathtbl.c | 13 +++++++++++++ 1 file changed, 13 insertions(+)
net/mac80211/mesh_pathtbl.c +13 -0
@@ -1011,10 +1011,23 @@ void mesh_path_discard_frame(struct ieee80211_sub_if_data *sdata,*/ void mesh_path_flush_pending (struct mesh_path *mpath) { +struct ieee80211_sub_if_data *sdata = mpath->sdata; +struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; +struct mesh_preq_queue *preq, *tmp;struct sk_buff *skb;while ((skb =skb_dequeue (&mpath->frame_queue)) !=NULL )mesh_path_discard_frame (mpath->sdata, skb); + +spin_lock_bh (&ifmsh->mesh_preq_queue_lock); +list_for_each_entry_safe (preq, tmp, &ifmsh->preq_queue.list, list) { +if (ether_addr_equal (mpath->dst, preq->dst)) { +list_del (&preq->list); +kfree (preq); + --ifmsh->preq_queue_len; + } + } +spin_unlock_bh (&ifmsh->mesh_preq_queue_lock); }/**
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 2/267 wifi: mac80211: Fix deadlock in ieee80211_sta_ps_deliver_wakeup()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Remi Pommarel <[email protected]>
[ Upstream commit 44c06bbde6443de206b30f513100b5670b23fc5e ]
The ieee80211_sta_ps_deliver_wakeup() function takes sta->ps_lock to synchronizes with ieee80211_tx_h_unicast_ps_buf() which is called from softirq context. However using only spin_lock() to get sta->ps_lock in ieee80211_sta_ps_deliver_wakeup() does not prevent softirq to execute on this same CPU, to run ieee80211_tx_h_unicast_ps_buf() and try to take this same lock ending in deadlock. Below is an example of rcu stall that arises in such situation.
rcu: INFO: rcu_sched self-detected stall on CPU rcu: 2-....: (42413413 ticks this GP) idle=b154/1/0x4000000000000000 softirq=1763/1765 fqs=21206996 rcu: (t=42586894 jiffies g=2057 q=362405 ncpus=4) CPU: 2 PID: 719 Comm: wpa_supplicant Tainted: G W 6.4.0-02158-g1b062f552873 #742 Hardware name: RPT (r1) (DT) pstate: 00000005 (nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : queued_spin_lock_slowpath+0x58/0x2d0 lr : invoke_tx_handlers_early+0x5b4/0x5c0 sp : ffff00001ef64660 x29: ffff00001ef64660 x28: ffff000009bc1070 x27: ffff000009bc0ad8 x26: ffff000009bc0900 x25: ffff00001ef647a8 x24: 0000000000000000 x23: ffff000009bc0900 x22: ffff000009bc0900 x21: ffff00000ac0e000 x20: ffff00000a279e00 x19: ffff00001ef646e8 x18: 0000000000000000 x17: ffff800016468000 x16: ffff00001ef608c0 x15: 0010533c93f64f80 x14: 0010395c9faa3946 x13: 0000000000000000 x12: 00000000fa83b2da x11: 000000012edeceea x10: ffff0000010fbe00 x9 : 0000000000895440 x8 : 000000000010533c x7 : ffff00000ad8b740 x6 : ffff00000c350880 x5 : 0000000000000007 x4 : 0000000000000001 x3 : 0000000000000000 x2 : 0000000000000000 x1 : 0000000000000001 x0 : ffff00000ac0e0e8 Call trace: queued_spin_lock_slowpath+0x58/0x2d0 ieee80211_tx+0x80/0x12c ieee80211_tx_pending+0x110/0x278 tasklet_action_common.constprop.0+0x10c/0x144 tasklet_action+0x20/0x28 _stext+0x11c/0x284 ____do_softirq+0xc/0x14 call_on_irq_stack+0x24/0x34 do_softirq_own_stack+0x18/0x20 do_softirq+0x74/0x7c __local_bh_enable_ip+0xa0/0xa4 _ieee80211_wake_txqs+0x3b0/0x4b8 __ieee80211_wake_queue+0x12c/0x168 ieee80211_add_pending_skbs+0xec/0x138 ieee80211_sta_ps_deliver_wakeup+0x2a4/0x480 ieee80211_mps_sta_status_update.part.0+0xd8/0x11c ieee80211_mps_sta_status_update+0x18/0x24 sta_apply_parameters+0x3bc/0x4c0 ieee80211_change_station+0x1b8/0x2dc nl80211_set_station+0x444/0x49c genl_family_rcv_msg_doit.isra.0+0xa4/0xfc genl_rcv_msg+0x1b0/0x244 netlink_rcv_skb+0x38/0x10c genl_rcv+0x34/0x48 netlink_unicast+0x254/0x2bc netlink_sendmsg+0x190/0x3b4 ____sys_sendmsg+0x1e8/0x218 ___sys_sendmsg+0x68/0x8c __sys_sendmsg+0x44/0x84 __arm64_sys_sendmsg+0x20/0x28 do_el0_svc+0x6c/0xe8 el0_svc+0x14/0x48 el0t_64_sync_handler+0xb0/0xb4 el0t_64_sync+0x14c/0x150
Using spin_lock_bh()/spin_unlock_bh() instead prevents softirq to raise on the same CPU that is holding the lock.
--- net/mac80211/sta_info.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/mac80211/sta_info.c +2 -2
@@ -1709,7 +1709,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)skb_queue_head_init (&pending);/* sync with ieee80211_tx_h_unicast_ps_buf */ -spin_lock (&sta->ps_lock); +spin_lock_bh (&sta->ps_lock);/* Send all buffered frames to the station */ for (ac =0 ; ac <IEEE80211_NUM_ACS ; ac++) {int count =skb_queue_len (&pending), tmp;
@@ -1738,7 +1738,7 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta)*/ clear_sta_flag (sta,WLAN_STA_PSPOLL );clear_sta_flag (sta,WLAN_STA_UAPSD ); -spin_unlock (&sta->ps_lock); +spin_unlock_bh (&sta->ps_lock);atomic_dec (&ps->num_sta_ps);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 3/267 wifi: cfg80211: fully move wiphy work to unbound workqueue
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit e296c95eac655008d5a709b8cf54d0018da1c916 ]
Previously I had moved the wiphy work to the unbound system workqueue, but missed that when it restarts and during resume it was still using the normal system workqueue. Fix that.
--- net/wireless/core.c | 2 +- net/wireless/sysfs.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-)
net/wireless/core.c +1 -1
@@ -431,7 +431,7 @@ static void cfg80211_wiphy_work(struct work_struct *work)if (wk) {list_del_init (&wk->entry);if (!list_empty (&rdev->wiphy_work_list)) -schedule_work (work); +queue_work (system_unbound_wq, work);spin_unlock_irq (&rdev->wiphy_work_lock); wk->func (&rdev->wiphy, wk);
net/wireless/sysfs.c +2 -2
@@ -5,7 +5,7 @@* * Copyright 2005-2006 Jiri Benc <[email protected]> * Copyright 2006 Johannes Berg <[email protected]> -* Copyright (C) 2020-2021, 2023 Intel Corporation +* Copyright (C) 2020-2021, 2023-2024 Intel Corporation */ #include <linux/device.h>
@@ -137,7 +137,7 @@ static int wiphy_resume(struct device *dev)if (rdev->wiphy.registered && rdev->ops->resume) ret =rdev_resume (rdev); rdev->suspended = false; -schedule_work (&rdev->wiphy_work); +queue_work (system_unbound_wq, &rdev->wiphy_work);wiphy_unlock (&rdev->wiphy);if (ret)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 4/267 wifi: cfg80211: Lock wiphy in cfg80211_get_station
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Remi Pommarel <[email protected]>
[ Upstream commit 642f89daa34567d02f312d03e41523a894906dae ]
Wiphy should be locked before calling rdev_get_station() (see lockdep assert in ieee80211_get_station()).
This fixes the following kernel NULL dereference:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000050 Mem abort info: ESR = 0x0000000096000006 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x06: level 2 translation fault Data abort info: ISV = 0, ISS = 0x00000006 CM = 0, WnR = 0 user pgtable: 4k pages, 48-bit VAs, pgdp=0000000003001000 [0000000000000050] pgd=0800000002dca003, p4d=0800000002dca003, pud=08000000028e9003, pmd=0000000000000000 Internal error: Oops: 0000000096000006 [#1] SMP Modules linked in: netconsole dwc3_meson_g12a dwc3_of_simple dwc3 ip_gre gre ath10k_pci ath10k_core ath9k ath9k_common ath9k_hw ath CPU: 0 PID: 1091 Comm: kworker/u8:0 Not tainted 6.4.0-02144-g565f9a3a7911-dirty #705 Hardware name: RPT (r1) (DT) Workqueue: bat_events batadv_v_elp_throughput_metric_update pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : ath10k_sta_statistics+0x10/0x2dc [ath10k_core] lr : sta_set_sinfo+0xcc/0xbd4 sp : ffff000007b43ad0 x29: ffff000007b43ad0 x28: ffff0000071fa900 x27: ffff00000294ca98 x26: ffff000006830880 x25: ffff000006830880 x24: ffff00000294c000 x23: 0000000000000001 x22: ffff000007b43c90 x21: ffff800008898acc x20: ffff00000294c6e8 x19: ffff000007b43c90 x18: 0000000000000000 x17: 445946354d552d78 x16: 62661f7200000000 x15: 57464f445946354d x14: 0000000000000000 x13: 00000000000000e3 x12: d5f0acbcebea978e x11: 00000000000000e3 x10: 000000010048fe41 x9 : 0000000000000000 x8 : ffff000007b43d90 x7 : 000000007a1e2125 x6 : 0000000000000000 x5 : ffff0000024e0900 x4 : ffff800000a0250c x3 : ffff000007b43c90 x2 : ffff00000294ca98 x1 : ffff000006831920 x0 : 0000000000000000 Call trace: ath10k_sta_statistics+0x10/0x2dc [ath10k_core] sta_set_sinfo+0xcc/0xbd4 ieee80211_get_station+0x2c/0x44 cfg80211_get_station+0x80/0x154 batadv_v_elp_get_throughput+0x138/0x1fc batadv_v_elp_throughput_metric_update+0x1c/0xa4 process_one_work+0x1ec/0x414 worker_thread+0x70/0x46c kthread+0xdc/0xe0 ret_from_fork+0x10/0x20 Code: a9bb7bfd 910003fd a90153f3 f9411c40 (f9402814)
This happens because STA has time to disconnect and reconnect before batadv_v_elp_throughput_metric_update() delayed work gets scheduled. In this situation, ath10k_sta_state() can be in the middle of resetting arsta data when the work queue get chance to be scheduled and ends up accessing it. Locking wiphy prevents that.
--- net/wireless/util.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
net/wireless/util.c +6 -1
@@ -2399,6 +2399,7 @@ int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr, {struct cfg80211_registered_device *rdev;struct wireless_dev *wdev; +int ret; wdev = dev->ieee80211_ptr;if (!wdev)
@@ -2410,7 +2411,11 @@ int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr,memset (sinfo,0 ,sizeof (*sinfo)); -return rdev_get_station (rdev, dev, mac_addr, sinfo); +wiphy_lock (&rdev->wiphy); + ret =rdev_get_station (rdev, dev, mac_addr, sinfo); +wiphy_unlock (&rdev->wiphy); + +return ret; }EXPORT_SYMBOL (cfg80211_get_station);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 5/267 wifi: cfg80211: pmsr: use correct nla_get_uX functions
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lin Ma <[email protected]>
[ Upstream commit ab904521f4de52fef4f179d2dfc1877645ef5f5c ]
The commit 9bb7e0f24e7e ("cfg80211: add peer measurement with FTM initiator API") defines four attributes NL80211_PMSR_FTM_REQ_ATTR_ {NUM_BURSTS_EXP}/{BURST_PERIOD}/{BURST_DURATION}/{FTMS_PER_BURST} in following ways.
static const struct nla_policy
nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
...
[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP] =
NLA_POLICY_MAX(NLA_U8, 15),
[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD] = { .type = NLA_U16 },
[NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION] =
NLA_POLICY_MAX(NLA_U8, 15),
[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST] =
NLA_POLICY_MAX(NLA_U8, 31),
...
};That is, those attributes are expected to be NLA_U8 and NLA_U16 types. However, the consumers of these attributes in pmsr_parse_ftm blindly all use nla_get_u32, which is incorrect and causes functionality issues on little-endian platforms. Hence, fix them with the correct nla_get_u8 and nla_get_u16 functions.
--- net/wireless/pmsr.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/wireless/pmsr.c +4 -4
@@ -56,7 +56,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, out->ftm.burst_period =0 ;if (tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD ]) out->ftm.burst_period = -nla_get_u32 (tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD ]); +nla_get_u16 (tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_PERIOD ]); out->ftm.asap = !!tb[NL80211_PMSR_FTM_REQ_ATTR_ASAP ];if (out->ftm.asap && !capa->ftm.asap) {
@@ -75,7 +75,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, out->ftm.num_bursts_exp =0 ;if (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP ]) out->ftm.num_bursts_exp = -nla_get_u32 (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP ]); +nla_get_u8 (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_BURSTS_EXP ]);if (capa->ftm.max_bursts_exponent >=0 && out->ftm.num_bursts_exp > capa->ftm.max_bursts_exponent) {
@@ -88,7 +88,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, out->ftm.burst_duration =15 ;if (tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION ]) out->ftm.burst_duration = -nla_get_u32 (tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION ]); +nla_get_u8 (tb[NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION ]); out->ftm.ftms_per_burst =0 ;if (tb[NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST ])
@@ -107,7 +107,7 @@ static int pmsr_parse_ftm(struct cfg80211_registered_device *rdev, out->ftm.ftmr_retries =3 ;if (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES ]) out->ftm.ftmr_retries = -nla_get_u32 (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES ]); +nla_get_u8 (tb[NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES ]); out->ftm.request_lci = !!tb[NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI ];if (out->ftm.request_lci && !capa->ftm.request_lci) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 6/267 wifi: iwlwifi: mvm: dont initialize csa_work twice
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miri Korenblit <[email protected]>
[ Upstream commit 92158790ce4391ce4c35d8dfbce759195e4724cb ]
The initialization of this worker moved to iwl_mvm_mac_init_mvmvif but we removed only from the pre-MLD version of the add_interface callback. Remove it also from the MLD version.
--- drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c | 2 -- 1 file changed, 2 deletions(-)
drivers/net/wireless/intel/iwlwifi/mvm/mld-mac80211.c +0 -2
@@ -73,8 +73,6 @@ static int iwl_mvm_mld_mac_add_interface(struct ieee80211_hw *hw, goto out_free_bf;iwl_mvm_tcm_add_vif (mvm, vif); -INIT_DELAYED_WORK (&mvmvif->csa_work, - iwl_mvm_channel_switch_disconnect_wk);if (vif->type ==NL80211_IFTYPE_MONITOR ) { mvm->monitor_on = true;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 7/267 wifi: iwlwifi: mvm: revert gen2 TX A-MPDU size to 64
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 4a7aace2899711592327463c1a29ffee44fcc66e ]
We don't actually support >64 even for HE devices, so revert back to 64. This fixes an issue where the session is refused because the queue is configured differently from the actual session later.
--- drivers/net/wireless/intel/iwlwifi/mvm/rs.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-)
drivers/net/wireless/intel/iwlwifi/mvm/rs.h +2 -7
@@ -122,13 +122,8 @@ enum {#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (63)#define LINK_QUAL_AGG_FRAME_LIMIT_MAX (63) -/* -* FIXME - various places in firmware API still use u8, -* e.g. LQ command and SCD config command. -* This should be 256 instead. -*/ -#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF (255) -#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_MAX (255) +#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_DEF (64) +#define LINK_QUAL_AGG_FRAME_LIMIT_GEN2_MAX (64)#define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0)#define LQ_SIZE 2/* 2 mode tables: "Active" and "Search" */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 8/267 wifi: iwlwifi: mvm: set properly mac header
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mordechay Goodstein <[email protected]>
[ Upstream commit 0f2e9f6f21d1ff292363cdfb5bc4d492eeaff76e ]
In the driver we only use skb_put* for adding data to the skb, hence data never moves and skb_reset_mac_haeder would set mac_header to the first time data was added and not to mac80211 header, fix this my using the actual len of bytes added for setting the mac header.
--- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +4 -1
@@ -2730,8 +2730,11 @@ void iwl_mvm_rx_monitor_no_data(struct iwl_mvm *mvm, struct napi_struct *napi,* * We mark it as mac header, for upper layers to know where * all radio tap header ends. +* +* Since data doesn't move data while putting data on skb and that is +* the only way we use, data + len is the next place that hdr would be put */ -skb_reset_mac_header (skb); +skb_set_mac_header (skb, skb->len);/* * Override the nss from the rx_vec since the rate_n_flags has
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 9/267 wifi: iwlwifi: dbg_ini: move iwl_dbg_tlv_free outside of debugfs ifdef
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shahar S Matityahu <[email protected]>
[ Upstream commit 87821b67dea87addbc4ab093ba752753b002176a ]
The driver should call iwl_dbg_tlv_free even if debugfs is not defined since ini mode does not depend on debugfs ifdef.
--- drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/intel/iwlwifi/iwl-drv.c +1 -1
@@ -1824,8 +1824,8 @@ struct iwl_drv *iwl_drv_start(struct iwl_trans *trans) err_fw:#ifdef CONFIG_IWLWIFI_DEBUGFS debugfs_remove_recursive (drv->dbgfs_drv); -iwl_dbg_tlv_free (drv->trans);#endif +iwl_dbg_tlv_free (drv->trans);kfree (drv); err:return ERR_PTR (ret);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 10/267 wifi: iwlwifi: mvm: check n_ssids before accessing the ssids
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miri Korenblit <[email protected]>
[ Upstream commit 60d62757df30b74bf397a2847a6db7385c6ee281 ]
In some versions of cfg80211, the ssids poinet might be a valid one even though n_ssids is 0. Accessing the pointer in this case will cuase an out-of-bound access. Fix this by checking n_ssids first.
--- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/wireless/intel/iwlwifi/mvm/scan.c +2 -2
@@ -1304,7 +1304,7 @@ static void iwl_mvm_scan_umac_dwell(struct iwl_mvm *mvm,if (IWL_MVM_ADWELL_MAX_BUDGET ) cmd->v7.adwell_max_budget =cpu_to_le16 (IWL_MVM_ADWELL_MAX_BUDGET ); -else if (params->ssids && params->ssids[0 ].ssid_len) +else if (params->n_ssids && params->ssids[0 ].ssid_len) cmd->v7.adwell_max_budget =cpu_to_le16 (IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN );else
@@ -1406,7 +1406,7 @@ iwl_mvm_scan_umac_dwell_v11(struct iwl_mvm *mvm,if (IWL_MVM_ADWELL_MAX_BUDGET ) general_params->adwell_max_budget =cpu_to_le16 (IWL_MVM_ADWELL_MAX_BUDGET ); -else if (params->ssids && params->ssids[0 ].ssid_len) +else if (params->n_ssids && params->ssids[0 ].ssid_len) general_params->adwell_max_budget =cpu_to_le16 (IWL_SCAN_ADWELL_MAX_BUDGET_DIRECTED_SCAN );else
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 11/267 wifi: iwlwifi: mvm: dont read past the mfuart notifcation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Emmanuel Grumbach <[email protected]>
[ Upstream commit 4bb95f4535489ed830cf9b34b0a891e384d1aee4 ]
In case the firmware sends a notification that claims it has more data than it has, we will read past that was allocated for the notification. Remove the print of the buffer, we won't see it by default. If needed, we can see the content with tracing.
This was reported by KFENCE.
--- drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 10 ---------- 1 file changed, 10 deletions(-)
drivers/net/wireless/intel/iwlwifi/mvm/fw.c +0 -10
@@ -92,20 +92,10 @@ void iwl_mvm_mfu_assert_dump_notif(struct iwl_mvm *mvm, {struct iwl_rx_packet *pkt =rxb_addr (rxb);struct iwl_mfu_assert_dump_notif *mfu_dump_notif = (void *)pkt->data; -__le32 *dump_data = mfu_dump_notif->data; -int n_words =le32_to_cpu (mfu_dump_notif->data_size) /sizeof (__le32); -int i;if (mfu_dump_notif->index_num ==0 )IWL_INFO (mvm,"MFUART assert id 0x%x occurred\n" ,le32_to_cpu (mfu_dump_notif->assert_id)); - -for (i =0 ; i < n_words; i++) -IWL_DEBUG_INFO (mvm, -"MFUART assert dump, dword %u: 0x%08x\n" , -le16_to_cpu (mfu_dump_notif->index_num) * - n_words + i, -le32_to_cpu (dump_data[i])); } static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 12/267 wifi: mac80211: correctly parse Spatial Reuse Parameter Set element
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lingbo Kong <[email protected]>
[ Upstream commit a26d8dc5227f449a54518a8b40733a54c6600a8b ]
Currently, the way of parsing Spatial Reuse Parameter Set element is incorrect and some members of struct ieee80211_he_obss_pd are not assigned.
To address this issue, it must be parsed in the order of the elements of Spatial Reuse Parameter Set defined in the IEEE Std 802.11ax specification.
The diagram of the Spatial Reuse Parameter Set element (IEEE Std 802.11ax -2021-9.4.2.252).
-------------------------------------------------------------------------
| | | | |Non-SRG| SRG | SRG | SRG | SRG | |Element|Length| Element | SR |OBSS PD|OBSS PD|OBSS PD| BSS |Partial| | ID | | ID |Control| Max | Min | Max |Color | BSSID | | | |Extension| | Offset| Offset|Offset |Bitmap|Bitmap |
-------------------------------------------------------------------------
--- net/mac80211/he.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
net/mac80211/he.c +8 -2
@@ -230,15 +230,21 @@ ieee80211_he_spr_ie_to_bss_conf(struct ieee80211_vif *vif,if (!he_spr_ie_elem)return ; + + he_obss_pd->sr_ctrl = he_spr_ie_elem->he_sr_control; data = he_spr_ie_elem->optional;if (he_spr_ie_elem->he_sr_control &IEEE80211_HE_SPR_NON_SRG_OFFSET_PRESENT ) - data++; + he_obss_pd->non_srg_max_offset = *data++; +if (he_spr_ie_elem->he_sr_control &IEEE80211_HE_SPR_SRG_INFORMATION_PRESENT ) { - he_obss_pd->max_offset = *data++; he_obss_pd->min_offset = *data++; + he_obss_pd->max_offset = *data++; +memcpy (he_obss_pd->bss_color_bitmap, data,8 ); + data +=8 ; +memcpy (he_obss_pd->partial_bssid_bitmap, data,8 ); he_obss_pd->enable = true; } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 13/267 scsi: ufs: mcq: Fix error output and clean up ufshcd_mcq_abort()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chanwoo Lee <[email protected]>
[ Upstream commit d53b681ce9ca7db5ef4ecb8d2cf465ae4a031264 ]
An error unrelated to ufshcd_try_to_abort_task is being logged and can cause confusion. Modify ufshcd_mcq_abort() to print the result of the abort failure. For readability, return immediately instead of 'goto'.
--- drivers/ufs/core/ufs-mcq.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
drivers/ufs/core/ufs-mcq.c +8 -9
@@ -630,20 +630,20 @@ int ufshcd_mcq_abort(struct scsi_cmnd *cmd)struct ufshcd_lrb *lrbp = &hba->lrb[tag];struct ufs_hw_queue *hwq;unsigned long flags; -int err =FAILED ; +int err;if (!ufshcd_cmd_inflight (lrbp->cmd)) {dev_err (hba->dev,"%s: skip abort. cmd at tag %d already completed.\n" , __func__, tag); - goto out; +return FAILED ; }/* Skip task abort in case previous aborts failed and report failure */ if (lrbp->req_abort_skip) {dev_err (hba->dev,"%s: skip abort. tag %d failed earlier\n" , __func__, tag); - goto out; +return FAILED ; } hwq =ufshcd_mcq_req_to_hwq (hba,scsi_cmd_to_rq (cmd));
@@ -655,7 +655,7 @@ int ufshcd_mcq_abort(struct scsi_cmnd *cmd)*/ dev_err (hba->dev,"%s: cmd found in sq. hwq=%d, tag=%d\n" , __func__, hwq->id, tag); - goto out; +return FAILED ; }/*
@@ -663,18 +663,17 @@ int ufshcd_mcq_abort(struct scsi_cmnd *cmd)* in the completion queue either. Query the device to see if * the command is being processed in the device. */ -if (ufshcd_try_to_abort_task (hba, tag)) { + err =ufshcd_try_to_abort_task (hba, tag); +if (err) {dev_err (hba->dev,"%s: device abort failed %d\n" , __func__, err); lrbp->req_abort_skip = true; - goto out; +return FAILED ; } - err =SUCCESS ;spin_lock_irqsave (&hwq->cq_lock, flags);if (ufshcd_cmd_inflight (lrbp->cmd))ufshcd_release_scsi_cmd (hba, lrbp);spin_unlock_irqrestore (&hwq->cq_lock, flags); -out: -return err; +return SUCCESS ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 14/267 RISC-V: KVM: No need to use mask when hart-index-bit is 0
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yong-Xuan Wang <[email protected]>
[ Upstream commit 2d707b4e37f9b0c37b8b2392f91b04c5b63ea538 ]
When the maximum hart number within groups is 1, hart-index-bit is set to
0. Consequently, there is no need to restore the hart ID from IMSIC addresses and hart-index-bit settings. Currently, QEMU and kvmtool do not pass correct hart-index-bit values when the maximum hart number is a power of 2, thereby avoiding this issue. Corresponding patches for QEMU and kvmtool will also be dispatched.
--- arch/riscv/kvm/aia_device.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
arch/riscv/kvm/aia_device.c +4 -3
@@ -237,10 +237,11 @@ static gpa_t aia_imsic_ppn(struct kvm_aia *aia, gpa_t addr)static u32 aia_imsic_hart_index (struct kvm_aia *aia,gpa_t addr) { -u32 hart, group =0 ; +u32 hart =0 , group =0 ; - hart = (addr >> (aia->nr_guest_bits +IMSIC_MMIO_PAGE_SHIFT )) & -GENMASK_ULL (aia->nr_hart_bits -1 ,0 ); +if (aia->nr_hart_bits) + hart = (addr >> (aia->nr_guest_bits +IMSIC_MMIO_PAGE_SHIFT )) & +GENMASK_ULL (aia->nr_hart_bits -1 ,0 );if (aia->nr_group_bits) group = (addr >> aia->nr_group_shift) &GENMASK_ULL (aia->nr_group_bits -1 ,0 );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 15/267 RISC-V: KVM: Fix incorrect reg_subtype labels in kvm_riscv_vcpu_set_reg_isa_ext function
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Quan Zhou <[email protected]>
[ Upstream commit c66f3b40b17d3dfc4b6abb5efde8e71c46971821 ]
In the function kvm_riscv_vcpu_set_reg_isa_ext, the original code used incorrect reg_subtype labels KVM_REG_RISCV_SBI_MULTI_EN/DIS. These have been corrected to KVM_REG_RISCV_ISA_MULTI_EN/DIS respectively. Although they are numerically equivalent, the actual processing will not result in errors, but it may lead to ambiguous code semantics.
--- arch/riscv/kvm/vcpu_onereg.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/riscv/kvm/vcpu_onereg.c +2 -2
@@ -614,9 +614,9 @@ static int kvm_riscv_vcpu_set_reg_isa_ext(struct kvm_vcpu *vcpu,switch (reg_subtype) {case KVM_REG_RISCV_ISA_SINGLE :return riscv_vcpu_set_isa_ext_single (vcpu, reg_num, reg_val); -case KVM_REG_RISCV_SBI_MULTI_EN : +case KVM_REG_RISCV_ISA_MULTI_EN :return riscv_vcpu_set_isa_ext_multi (vcpu, reg_num, reg_val, true); -case KVM_REG_RISCV_SBI_MULTI_DIS : +case KVM_REG_RISCV_ISA_MULTI_DIS :return riscv_vcpu_set_isa_ext_multi (vcpu, reg_num, reg_val, false);default :return -ENOENT ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 16/267 ax25: Fix refcount imbalance on inbound connections
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lars Kellogg-Stedman <[email protected]>
[ Upstream commit 3c34fb0bd4a4237592c5ecb5b2e2531900c55774 ]
When releasing a socket in ax25_release(), we call netdev_put() to decrease the refcount on the associated ax.25 device. However, the execution path for accepting an incoming connection never calls netdev_hold(). This imbalance leads to refcount errors, and ultimately to kernel crashes.
A typical call trace for the above situation will start with one of the following errors:
refcount_t: decrement hit 0; leaking memory.
refcount_t: underflow; use-after-free.
And will then have a trace like:
Call Trace:
<TASK>
? show_regs+0x64/0x70
? __warn+0x83/0x120
? refcount_warn_saturate+0xb2/0x100
? report_bug+0x158/0x190
? prb_read_valid+0x20/0x30
? handle_bug+0x3e/0x70
? exc_invalid_op+0x1c/0x70
? asm_exc_invalid_op+0x1f/0x30
? refcount_warn_saturate+0xb2/0x100
? refcount_warn_saturate+0xb2/0x100
ax25_release+0x2ad/0x360
__sock_release+0x35/0xa0
sock_close+0x19/0x20
[...]On reboot (or any attempt to remove the interface), the kernel gets stuck in an infinite loop:
unregister_netdevice: waiting for ax0 to become free. Usage count = 0
This patch corrects these issues by ensuring that we call netdev_hold() and ax25_dev_hold() for new connections in ax25_accept(). This makes the logic leading to ax25_accept() match the logic for ax25_bind(): in both cases we increment the refcount, which is ultimately decremented in ax25_release().
--- net/ax25/af_ax25.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/ax25/af_ax25.c +6 -0
@@ -1378,8 +1378,10 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags, {struct sk_buff *skb;struct sock *newsk; +ax25_dev *ax25_dev;DEFINE_WAIT (wait);struct sock *sk; +ax25_cb *ax25;int err =0 ;if (sock->state !=SS_UNCONNECTED )
@@ -1434,6 +1436,10 @@ static int ax25_accept(struct socket *sock, struct socket *newsock, int flags,kfree_skb (skb);sk_acceptq_removed (sk); newsock->state =SS_CONNECTED ; + ax25 =sk_to_ax25 (newsk); + ax25_dev = ax25->ax25_dev; +netdev_hold (ax25_dev->dev, &ax25->dev_tracker,GFP_ATOMIC ); +ax25_dev_hold (ax25_dev); out:release_sock (sk);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 17/267 ax25: Replace kfree() in ax25_dev_free() with ax25_dev_put()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Duoming Zhou <[email protected]>
[ Upstream commit 166fcf86cd34e15c7f383eda4642d7a212393008 ]
The object "ax25_dev" is managed by reference counting. Thus it should not be directly released by kfree(), replace with ax25_dev_put().
--- net/ax25/ax25_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ax25/ax25_dev.c +1 -1
@@ -193,7 +193,7 @@ void __exit ax25_dev_free(void)list_for_each_entry_safe (s, n, &ax25_dev_list, list) {netdev_put (s->dev, &s->dev_tracker);list_del (&s->list); -kfree (s); +ax25_dev_put (s); }spin_unlock_bh (&ax25_dev_lock); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 18/267 net/ncsi: Simplify Kconfig/dts control flow
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peter Delevoryas <[email protected]>
[ Upstream commit c797ce168930ce3d62a9b7fc4d7040963ee6a01e ]
Background:
1. CONFIG_NCSI_OEM_CMD_KEEP_PHY
If this is enabled, we send an extra OEM Intel command in the probe sequence immediately after discovering a channel (e.g. after "Clear Initial State").
2. CONFIG_NCSI_OEM_CMD_GET_MAC
If this is enabled, we send one of 3 OEM "Get MAC Address" commands from Broadcom, Mellanox (Nvidida), and Intel in the *configuration* sequence for a channel.
3. mellanox,multi-host (or mlx,multi-host)
Introduced by this patch:
https://lore.kernel.org/all/[email protected]/
Which was actually originally from [email protected]:
https://github.com/facebook/openbmc-linux/commit/9f132a10ec48db84613519258cd8a317fb9c8f1b
Cosmo claimed that the Nvidia ConnectX-4 and ConnectX-6 NIC's don't respond to Get Version ID, et. al in the probe sequence unless you send the Set MC Affinity command first.
Problem Statement:
We've been using a combination of #ifdef code blocks and IS_ENABLED() conditions to conditionally send these OEM commands.
It makes adding any new code around these commands hard to understand.
Solution:
In this patch, I just want to remove the conditionally compiled blocks of code, and always use IS_ENABLED(...) to do dynamic control flow.
I don't think the small amount of code this adds to non-users of the OEM Kconfigs is a big deal.
Stable-dep-of: e85e271dec02 ("net/ncsi: Fix the multi thread manner of NCSI driver")
--- net/ncsi/ncsi-manage.c | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-)
net/ncsi/ncsi-manage.c +3 -17
@@ -689,8 +689,6 @@ static int set_one_vid(struct ncsi_dev_priv *ndp, struct ncsi_channel *nc,return 0 ; } -#if IS_ENABLED (CONFIG_NCSI_OEM_CMD_KEEP_PHY ) -static int ncsi_oem_keep_phy_intel (struct ncsi_cmd_arg *nca) {unsigned char data[NCSI_OEM_INTEL_CMD_KEEP_PHY_LEN ];
@@ -716,10 +714,6 @@ static int ncsi_oem_keep_phy_intel(struct ncsi_cmd_arg *nca)return ret; } -#endif - -#if IS_ENABLED (CONFIG_NCSI_OEM_CMD_GET_MAC ) -/* NCSI OEM Command APIs */ static int ncsi_oem_gma_handler_bcm (struct ncsi_cmd_arg *nca) {
@@ -856,8 +850,6 @@ static int ncsi_gma_handler(struct ncsi_cmd_arg *nca, unsigned int mf_id)return nch->handler (nca); } -#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */ -/* Determine if a given channel from the channel_queue should be used for Tx */ static bool ncsi_channel_is_tx (struct ncsi_dev_priv *ndp,struct ncsi_channel *nc)
@@ -1039,20 +1031,18 @@ static void ncsi_configure_channel(struct ncsi_dev_priv *ndp) goto error; } - nd->state = ncsi_dev_state_config_oem_gma; + nd->state =IS_ENABLED (CONFIG_NCSI_OEM_CMD_GET_MAC ) + ? ncsi_dev_state_config_oem_gma + : ncsi_dev_state_config_clear_vids;break ;case ncsi_dev_state_config_oem_gma: nd->state = ncsi_dev_state_config_clear_vids; - ret =-1 ; -#if IS_ENABLED (CONFIG_NCSI_OEM_CMD_GET_MAC ) nca.type =NCSI_PKT_CMD_OEM ; nca.package = np->id; nca.channel = nc->id; ndp->pending_req_num =1 ; ret =ncsi_gma_handler (&nca, nc->version.mf_id); -#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */ -if (ret <0 )schedule_work (&ndp->work);
@@ -1404,7 +1394,6 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)schedule_work (&ndp->work);break ; -#if IS_ENABLED (CONFIG_NCSI_OEM_CMD_GET_MAC )case ncsi_dev_state_probe_mlx_gma: ndp->pending_req_num =1 ;
@@ -1429,7 +1418,6 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp) nd->state = ncsi_dev_state_probe_cis;break ; -#endif /* CONFIG_NCSI_OEM_CMD_GET_MAC */ case ncsi_dev_state_probe_cis: ndp->pending_req_num =NCSI_RESERVED_CHANNEL ;
@@ -1447,7 +1435,6 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp)if (IS_ENABLED (CONFIG_NCSI_OEM_CMD_KEEP_PHY )) nd->state = ncsi_dev_state_probe_keep_phy;break ; -#if IS_ENABLED (CONFIG_NCSI_OEM_CMD_KEEP_PHY )case ncsi_dev_state_probe_keep_phy: ndp->pending_req_num =1 ;
@@ -1460,7 +1447,6 @@ static void ncsi_probe_channel(struct ncsi_dev_priv *ndp) nd->state = ncsi_dev_state_probe_gvi;break ; -#endif /* CONFIG_NCSI_OEM_CMD_KEEP_PHY */ case ncsi_dev_state_probe_gvi:case ncsi_dev_state_probe_gc:case ncsi_dev_state_probe_gls:
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 19/267 net/ncsi: Fix the multi thread manner of NCSI driver
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: DelphineCCChiu <[email protected]>
[ Upstream commit e85e271dec0270982afed84f70dc37703fcc1d52 ]
Currently NCSI driver will send several NCSI commands back to back without waiting the response of previous NCSI command or timeout in some state when NIC have multi channel. This operation against the single thread manner defined by NCSI SPEC(section 6.3.2.3 in DSP0222_1.1.1)
According to NCSI SPEC(section 6.2.13.1 in DSP0222_1.1.1), we should probe one channel at a time by sending NCSI commands (Clear initial state, Get version ID, Get capabilities...), than repeat this steps until the max number of channels which we got from NCSI command (Get capabilities) has been probed.
--- net/ncsi/internal.h | 2 ++ net/ncsi/ncsi-manage.c | 73 +++++++++++++++++++++--------------------- net/ncsi/ncsi-rsp.c | 4 ++- 3 files changed, 41 insertions(+), 38 deletions(-)
net/ncsi/internal.h +2 -0
@@ -325,6 +325,7 @@ struct ncsi_dev_priv {spinlock_t lock;/* Protect the NCSI device */ unsigned int package_probe_id;/* Current ID during probe */ unsigned int package_num;/* Number of packages */ +unsigned int channel_probe_id;/* Current cahnnel ID during probe */ struct list_head packages;/* List of packages */ struct ncsi_channel *hot_channel;/* Channel was ever active */ struct ncsi_request requests[256 ];/* Request table */
@@ -343,6 +344,7 @@ struct ncsi_dev_priv {bool multi_package;/* Enable multiple packages */ bool mlx_multi_host;/* Enable multi host Mellanox */ u32 package_whitelist;/* Packages to configure */ +unsigned char channel_count;/* Num of channels to probe */ };struct ncsi_cmd_arg {
net/ncsi/ncsi-manage.c +36 -37
128 lines not on this page · raw message
net/ncsi/ncsi-rsp.c +3 -1
@@ -795,12 +795,13 @@ static int ncsi_rsp_handler_gc(struct ncsi_request *nr)struct ncsi_rsp_gc_pkt *rsp;struct ncsi_dev_priv *ndp = nr->ndp;struct ncsi_channel *nc; +struct ncsi_package *np;size_t size;/* Find the channel */ rsp = (struct ncsi_rsp_gc_pkt *)skb_network_header (nr->rsp);ncsi_find_package_and_channel (ndp, rsp->rsp.common.channel, -NULL , &nc); + &np, &nc);if (!nc)return -ENODEV ;
@@ -835,6 +836,7 @@ static int ncsi_rsp_handler_gc(struct ncsi_request *nr)*/ nc->vlan_filter.bitmap =U64_MAX ; nc->vlan_filter.n_vids = rsp->vlan_cnt; + np->ndp->channel_count = rsp->channel_cnt;return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 20/267 net: phy: micrel: fix KSZ9477 PHY issues after suspend/resume
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristram Ha <[email protected]>
[ Upstream commit 6149db4997f582e958da675092f21c666e3b67b7 ]
When the PHY is powered up after powered down most of the registers are reset, so the PHY setup code needs to be done again. In addition the interrupt register will need to be setup again so that link status indication works again.
--- drivers/net/phy/micrel.c | 62 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 56 insertions(+), 6 deletions(-)
drivers/net/phy/micrel.c +56 -6
@@ -1821,7 +1821,7 @@ static const struct ksz9477_errata_write ksz9477_errata_writes[] = { {0x1c, 0x20, 0xeeee}, }; -static int ksz9477_config_init (struct phy_device *phydev) +static int ksz9477_phy_errata (struct phy_device *phydev) {int err;int i;
@@ -1849,16 +1849,30 @@ static int ksz9477_config_init(struct phy_device *phydev)return err; } + err =genphy_restart_aneg (phydev); +if (err) +return err; + +return err; +} + +static int ksz9477_config_init (struct phy_device *phydev) +{ +int err; + +/* Only KSZ9897 family of switches needs this fix. */ +if ((phydev->phy_id &0xf ) ==1 ) { + err =ksz9477_phy_errata (phydev); +if (err) +return err; + } +/* According to KSZ9477 Errata DS80000754C (Module 4) all EEE modes * in this switch shall be regarded as broken. */ if (phydev->dev_flags &MICREL_NO_EEE ) phydev->eee_broken_modes =-1 ; - err =genphy_restart_aneg (phydev); -if (err) -return err; -return kszphy_config_init (phydev); }
@@ -1967,6 +1981,42 @@ static int kszphy_resume(struct phy_device *phydev)return 0 ; } +static int ksz9477_resume (struct phy_device *phydev) +{ +int ret; + +/* No need to initialize registers if not powered down. */ + ret =phy_read (phydev,MII_BMCR ); +if (ret <0 ) +return ret; +if (!(ret &BMCR_PDOWN )) +return 0 ; + +genphy_resume (phydev); + +/* After switching from power-down to normal mode, an internal global +* reset is automatically generated. Wait a minimum of 1 ms before +* read/write access to the PHY registers. +*/ +usleep_range (1000 ,2000 ); + +/* Only KSZ9897 family of switches needs this fix. */ +if ((phydev->phy_id &0xf ) ==1 ) { + ret =ksz9477_phy_errata (phydev); +if (ret) +return ret; + } + +/* Enable PHY Interrupts */ +if (phy_interrupt_is_valid (phydev)) { + phydev->interrupts =PHY_INTERRUPT_ENABLED ; +if (phydev->drv->config_intr) + phydev->drv->config_intr (phydev); + } + +return 0 ; +} +static int kszphy_probe (struct phy_device *phydev) {const struct kszphy_type *type = phydev->drv->driver_data;
@@ -4916,7 +4966,7 @@ static struct phy_driver ksphy_driver[] = { .config_intr = kszphy_config_intr, .handle_interrupt = kszphy_handle_interrupt, .suspend = genphy_suspend, - .resume = genphy_resume, + .resume = ksz9477_resume, .get_features = ksz9477_get_features, } };
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 21/267 bpf: Store ref_ctr_offsets values in bpf_uprobe array
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Olsa <[email protected]>
[ Upstream commit 4930b7f53a298533bc31d7540b6ea8b79a000331 ]
We will need to return ref_ctr_offsets values through link_info interface in following change, so we need to keep them around.
Storing ref_ctr_offsets values directly into bpf_uprobe array.
Stable-dep-of: 2884dc7d08d9 ("bpf: Fix a potential use-after-free in bpf_link_free()")
--- kernel/trace/bpf_trace.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-)
kernel/trace/bpf_trace.c +3 -11
@@ -3030,6 +3030,7 @@ struct bpf_uprobe_multi_link;struct bpf_uprobe {struct bpf_uprobe_multi_link *link;loff_t offset; +unsigned long ref_ctr_offset;u64 cookie;struct uprobe_consumer consumer; };
@@ -3169,7 +3170,6 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr {struct bpf_uprobe_multi_link *link =NULL ;unsigned long __user *uref_ctr_offsets; -unsigned long *ref_ctr_offsets =NULL ;struct bpf_link_primer link_primer;struct bpf_uprobe *uprobes =NULL ;struct task_struct *task =NULL ;
@@ -3244,18 +3244,12 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prif (!uprobes || !link) goto error_free; -if (uref_ctr_offsets) { - ref_ctr_offsets =kvcalloc (cnt,sizeof (*ref_ctr_offsets),GFP_KERNEL ); -if (!ref_ctr_offsets) - goto error_free; - } -for (i =0 ; i < cnt; i++) {if (ucookies &&__get_user (uprobes[i].cookie, ucookies + i)) { err = -EFAULT ; goto error_free; } -if (uref_ctr_offsets &&__get_user (ref_ctr_offsets[i], uref_ctr_offsets + i)) { +if (uref_ctr_offsets &&__get_user (uprobes[i].ref_ctr_offset, uref_ctr_offsets + i)) { err = -EFAULT ; goto error_free; }
@@ -3286,7 +3280,7 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prfor (i =0 ; i < cnt; i++) { err =uprobe_register_refctr (d_real_inode (link->path.dentry), uprobes[i].offset, - ref_ctr_offsets ? ref_ctr_offsets[i] :0 , + uprobes[i].ref_ctr_offset, &uprobes[i].consumer);if (err) {bpf_uprobe_unregister (&path, uprobes, i);
@@ -3298,11 +3292,9 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prif (err) goto error_free; -kvfree (ref_ctr_offsets);return bpf_link_settle (&link_primer); error_free: -kvfree (ref_ctr_offsets);kvfree (uprobes);kfree (link);if (task)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 22/267 bpf: Optimize the free of inner map
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hou Tao <[email protected]>
[ Upstream commit af66bfd3c8538ed21cf72af18426fc4a408665cf ]
When removing the inner map from the outer map, the inner map will be freed after one RCU grace period and one RCU tasks trace grace period, so it is certain that the bpf program, which may access the inner map, has exited before the inner map is freed.
However there is no need to wait for one RCU tasks trace grace period if the outer map is only accessed by non-sleepable program. So adding sleepable_refcnt in bpf_map and increasing sleepable_refcnt when adding the outer map into env->used_maps for sleepable program. Although the max number of bpf program is INT_MAX - 1, the number of bpf programs which are being loaded may be greater than INT_MAX, so using atomic64_t instead of atomic_t for sleepable_refcnt. When removing the inner map from the outer map, using sleepable_refcnt to decide whether or not a RCU tasks trace grace period is needed before freeing the inner map.
Stable-dep-of: 2884dc7d08d9 ("bpf: Fix a potential use-after-free in bpf_link_free()")
--- include/linux/bpf.h | 2 ++ kernel/bpf/core.c | 4 ++++ kernel/bpf/map_in_map.c | 14 +++++++++----- kernel/bpf/syscall.c | 8 ++++++++ kernel/bpf/verifier.c | 4 +++- 5 files changed, 26 insertions(+), 6 deletions(-)
include/linux/bpf.h +2 -0
@@ -296,6 +296,8 @@ struct bpf_map {bool bypass_spec_v1;bool frozen;/* write-once; write-protected by freeze_mutex */ bool free_after_mult_rcu_gp; +bool free_after_rcu_gp; +atomic64_t sleepable_refcnt;s64 __percpu *elem_count; };
kernel/bpf/core.c +4 -0
@@ -2673,12 +2673,16 @@ void __bpf_free_used_maps(struct bpf_prog_aux *aux, struct bpf_map **used_maps, u32 len) {struct bpf_map *map; +bool sleepable;u32 i; + sleepable = aux->sleepable;for (i =0 ; i < len; i++) { map = used_maps[i];if (map->ops->map_poke_untrack) map->ops->map_poke_untrack (map, aux); +if (sleepable) +atomic64_dec (&map->sleepable_refcnt);bpf_map_put (map); } }
kernel/bpf/map_in_map.c +9 -5
@@ -131,12 +131,16 @@ void bpf_map_fd_put_ptr(struct bpf_map *map, void *ptr, bool need_defer) {struct bpf_map *inner_map = ptr; -/* The inner map may still be used by both non-sleepable and sleepable -* bpf program, so free it after one RCU grace period and one tasks -* trace RCU grace period. +/* Defer the freeing of inner map according to the sleepable attribute +* of bpf program which owns the outer map, so unnecessary waiting for +* RCU tasks trace grace period can be avoided. */ -if (need_defer) -WRITE_ONCE (inner_map->free_after_mult_rcu_gp, true); +if (need_defer) { +if (atomic64_read (&map->sleepable_refcnt)) +WRITE_ONCE (inner_map->free_after_mult_rcu_gp, true); +else +WRITE_ONCE (inner_map->free_after_rcu_gp, true); + }bpf_map_put (inner_map); }
kernel/bpf/syscall.c +8 -0
@@ -753,8 +753,11 @@ void bpf_map_put(struct bpf_map *map)/* bpf_map_free_id() must be called first */ bpf_map_free_id (map); +WARN_ON_ONCE (atomic64_read (&map->sleepable_refcnt));if (READ_ONCE (map->free_after_mult_rcu_gp))call_rcu_tasks_trace (&map->rcu, bpf_map_free_mult_rcu_gp); +else if (READ_ONCE (map->free_after_rcu_gp)) +call_rcu (&map->rcu, bpf_map_free_rcu_gp);else bpf_map_free_in_work (map); }
@@ -5358,6 +5361,11 @@ static int bpf_prog_bind_map(union bpf_attr *attr) goto out_unlock; } +/* The bpf program will not access the bpf map, but for the sake of +* simplicity, increase sleepable_refcnt for sleepable program as well. +*/ +if (prog->aux->sleepable) +atomic64_inc (&map->sleepable_refcnt);memcpy (used_maps_new, used_maps_old,sizeof (used_maps_old[0 ]) * prog->aux->used_map_cnt); used_maps_new[prog->aux->used_map_cnt] = map;
kernel/bpf/verifier.c +3 -1
@@ -17732,10 +17732,12 @@ static int resolve_pseudo_ldimm64(struct bpf_verifier_env *env)return -E2BIG ; } +if (env->prog->aux->sleepable) +atomic64_inc (&map->sleepable_refcnt);/* hold the map. If the program is rejected by verifier, * the map will be released by release_maps() or it * will be used by the valid program until it's unloaded -* and all maps are released in free_used_maps() +* and all maps are released in bpf_free_used_maps() */ bpf_map_inc (map);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 23/267 bpf: Fix a potential use-after-free in bpf_link_free()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cong Wang <[email protected]>
[ Upstream commit 2884dc7d08d98a89d8d65121524bb7533183a63a ]
After commit 1a80dbcb2dba, bpf_link can be freed by link->ops->dealloc_deferred, but the code still tests and uses link->ops->dealloc afterward, which leads to a use-after-free as reported by syzbot. Actually, one of them should be sufficient, so just call one of them instead of both. Also add a WARN_ON() in case of any problematic implementation.
--- kernel/bpf/syscall.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
kernel/bpf/syscall.c +6 -5
@@ -2830,6 +2830,7 @@ static int bpf_obj_get(const union bpf_attr *attr)void bpf_link_init (struct bpf_link *link,enum bpf_link_type type,const struct bpf_link_ops *ops,struct bpf_prog *prog) { +WARN_ON (ops->dealloc && ops->dealloc_deferred);atomic64_set (&link->refcnt,1 ); link->type = type; link->id =0 ;
@@ -2888,16 +2889,17 @@ static void bpf_link_defer_dealloc_mult_rcu_gp(struct rcu_head *rcu)/* bpf_link_free is guaranteed to be called from process context */ static void bpf_link_free (struct bpf_link *link) { +const struct bpf_link_ops *ops = link->ops;bool sleepable = false;bpf_link_free_id (link->id);if (link->prog) { sleepable = link->prog->aux->sleepable;/* detach BPF program, clean up used resources */ - link->ops->release (link); + ops->release (link);bpf_prog_put (link->prog); } -if (link->ops->dealloc_deferred) { +if (ops->dealloc_deferred) {/* schedule BPF link deallocation; if underlying BPF program * is sleepable, we need to first wait for RCU tasks trace * sync, then go through "classic" RCU grace period
@@ -2906,9 +2908,8 @@ static void bpf_link_free(struct bpf_link *link)call_rcu_tasks_trace (&link->rcu, bpf_link_defer_dealloc_mult_rcu_gp); else call_rcu(&link->rcu, bpf_link_defer_dealloc_rcu_gp); - } -if (link->ops->dealloc) - link->ops->dealloc (link); + }else if (ops->dealloc) + ops->dealloc (link); }static void bpf_link_put_deferred (struct work_struct *work)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 24/267 KVM: SEV-ES: Disallow SEV-ES guests when X86_FEATURE_LBRV is absent
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ravi Bangoria <[email protected]>
[ Upstream commit d922056215617eedfbdbc29fe49953423686fe5e ]
As documented in APM[1], LBR Virtualization must be enabled for SEV-ES guests. So, prevent SEV-ES guests when LBRV support is missing.
[1]: AMD64 Architecture Programmer's Manual Pub. 40332, Rev. 4.07 - June
2023, Vol 2, 15.35.2 Enabling SEV-ES.
https://bugzilla.kernel.org/attachment.cgi?id=304653Message-ID: <[email protected]>
--- arch/x86/kvm/svm/sev.c | 6 ++++++ arch/x86/kvm/svm/svm.c | 16 +++++++--------- arch/x86/kvm/svm/svm.h | 1 + 3 files changed, 14 insertions(+), 9 deletions(-)
arch/x86/kvm/svm/sev.c +6 -0
@@ -2264,6 +2264,12 @@ void __init sev_hardware_setup(void)if (!boot_cpu_has (X86_FEATURE_SEV_ES )) goto out; +if (!lbrv) { +WARN_ONCE (!boot_cpu_has (X86_FEATURE_LBRV ), +"LBRV must be present for SEV-ES support" ); + goto out; + } +/* Has the system been allocated ASIDs for SEV-ES? */ if (min_sev_asid ==1 ) goto out;
arch/x86/kvm/svm/svm.c +7 -9
@@ -214,7 +214,7 @@ int vgif = true;module_param (vgif, int,0444 );/* enable/disable LBR virtualization */ -static int lbrv = true; +int lbrv = true;module_param (lbrv, int,0444 );static int tsc_scaling = true;
@@ -5248,6 +5248,12 @@ static __init int svm_hardware_setup(void) nrips = nrips &&boot_cpu_has (X86_FEATURE_NRIPS ); +if (lbrv) { +if (!boot_cpu_has (X86_FEATURE_LBRV )) + lbrv = false; +else +pr_info ("LBR virtualization supported\n" ); + }/* * Note, SEV setup consumes npt_enabled and enable_mmio_caching (which * may be modified by svm_adjust_mmio_mask()), as well as nrips.
@@ -5301,14 +5307,6 @@ static __init int svm_hardware_setup(void) svm_x86_ops.set_vnmi_pending =NULL ; } - -if (lbrv) { -if (!boot_cpu_has (X86_FEATURE_LBRV )) - lbrv = false; -else -pr_info ("LBR virtualization supported\n" ); - } -if (!enable_pmu)pr_info ("PMU virtualization is disabled\n" );
arch/x86/kvm/svm/svm.h +1 -0
@@ -39,6 +39,7 @@ extern int vgif;extern bool intercept_smi;extern bool x2avic_enabled;extern bool vnmi; +extern int lbrv;/* * Clean bits in VMCB.
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 25/267 KVM: SEV: Do not intercept accesses to MSR_IA32_XSS for SEV-ES guests
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Roth <[email protected]>
[ Upstream commit a26b7cd2254695f8258cc370f33280db0a9a3813 ]
When intercepts are enabled for MSR_IA32_XSS, the host will swap in/out the guest-defined values while context-switching to/from guest mode. However, in the case of SEV-ES, vcpu->arch.guest_state_protected is set, so the guest-defined value is effectively ignored when switching to guest mode with the understanding that the VMSA will handle swapping in/out this register state.
However, SVM is still configured to intercept these accesses for SEV-ES guests, so the values in the initial MSR_IA32_XSS are effectively read-only, and a guest will experience undefined behavior if it actually tries to write to this MSR. Fortunately, only CET/shadowstack makes use of this register on SEV-ES-capable systems currently, which isn't yet widely used, but this may become more of an issue in the future.
Additionally, enabling intercepts of MSR_IA32_XSS results in #VC exceptions in the guest in certain paths that can lead to unexpected #VC nesting levels. One example is SEV-SNP guests when handling #VC exceptions for CPUID instructions involving leaf 0xD, subleaf 0x1, since they will access MSR_IA32_XSS as part of servicing the CPUID #VC, then generate another #VC when accessing MSR_IA32_XSS, which can lead to guest crashes if an NMI occurs at that point in time. Running perf on a guest while it is issuing such a sequence is one example where these can be problematic.
Address this by disabling intercepts of MSR_IA32_XSS for SEV-ES guests if the host/guest configuration allows it. If the host/guest configuration doesn't allow for MSR_IA32_XSS, leave it intercepted so that it can be caught by the existing checks in kvm_{set,get}_msr_common() if the guest still attempts to access it.
Message-Id: <[email protected]>
Stable-dep-of: b7e4be0a224f ("KVM: SEV-ES: Delegate LBR virtualization to the processor")
--- arch/x86/kvm/svm/sev.c | 19 +++++++++++++++++++ arch/x86/kvm/svm/svm.c | 1 + arch/x86/kvm/svm/svm.h | 2 +- 3 files changed, 21 insertions(+), 1 deletion(-)
arch/x86/kvm/svm/sev.c +19 -0
@@ -2994,6 +2994,25 @@ static void sev_es_vcpu_after_set_cpuid(struct vcpu_svm *svm)set_msr_interception (vcpu, svm->msrpm,MSR_TSC_AUX , v_tsc_aux, v_tsc_aux); } + +/* +* For SEV-ES, accesses to MSR_IA32_XSS should not be intercepted if +* the host/guest supports its use. +* +* guest_can_use() checks a number of requirements on the host/guest to +* ensure that MSR_IA32_XSS is available, but it might report true even +* if X86_FEATURE_XSAVES isn't configured in the guest to ensure host +* MSR_IA32_XSS is always properly restored. For SEV-ES, it is better +* to further check that the guest CPUID actually supports +* X86_FEATURE_XSAVES so that accesses to MSR_IA32_XSS by misbehaved +* guests will still get intercepted and caught in the normal +* kvm_emulate_rdmsr()/kvm_emulated_wrmsr() paths. +*/ +if (guest_can_use (vcpu,X86_FEATURE_XSAVES ) && +guest_cpuid_has (vcpu,X86_FEATURE_XSAVES )) +set_msr_interception (vcpu, svm->msrpm,MSR_IA32_XSS ,1 ,1 ); +else +set_msr_interception (vcpu, svm->msrpm,MSR_IA32_XSS ,0 ,0 ); }void sev_vcpu_after_set_cpuid (struct vcpu_svm *svm)
arch/x86/kvm/svm/svm.c +1 -0
@@ -103,6 +103,7 @@ static const struct svm_direct_access_msrs { { .index = MSR_IA32_LASTBRANCHTOIP, .always = false }, { .index = MSR_IA32_LASTINTFROMIP, .always = false }, { .index = MSR_IA32_LASTINTTOIP, .always = false }, + { .index = MSR_IA32_XSS, .always = false }, { .index = MSR_EFER, .always = false }, { .index = MSR_IA32_CR_PAT, .always = false }, { .index = MSR_AMD64_SEV_ES_GHCB, .always = true },
arch/x86/kvm/svm/svm.h +1 -1
@@ -30,7 +30,7 @@#define IOPM_SIZE PAGE_SIZE * 3#define MSRPM_SIZE PAGE_SIZE * 2 -#define MAX_DIRECT_ACCESS_MSRS 46 +#define MAX_DIRECT_ACCESS_MSRS 47#define MSRPM_OFFSETS 32extern u32 msrpm_offsets[MSRPM_OFFSETS ]__read_mostly ;extern bool npt_enabled;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 26/267 KVM: SEV-ES: Delegate LBR virtualization to the processor
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ravi Bangoria <[email protected]>
[ Upstream commit b7e4be0a224fe5c6be30c1c8bdda8d2317ad6ba4 ]
As documented in APM[1], LBR Virtualization must be enabled for SEV-ES guests. Although KVM currently enforces LBRV for SEV-ES guests, there are multiple issues with it:
o MSR_IA32_DEBUGCTLMSR is still intercepted. Since MSR_IA32_DEBUGCTLMSR interception is used to dynamically toggle LBRV for performance reasons, this can be fatal for SEV-ES guests. For ex SEV-ES guest on Zen3:
[guest ~]# wrmsr 0x1d9 0x4
KVM: entry failed, hardware error 0xffffffff EAX=00000004 EBX=00000000 ECX=000001d9 EDX=00000000
Fix this by never intercepting MSR_IA32_DEBUGCTLMSR for SEV-ES guests. No additional save/restore logic is required since MSR_IA32_DEBUGCTLMSR is of swap type A.
o KVM will disable LBRV if userspace sets MSR_IA32_DEBUGCTLMSR before the VMSA is encrypted. Fix this by moving LBRV enablement code post VMSA encryption.
[1]: AMD64 Architecture Programmer's Manual Pub. 40332, Rev. 4.07 - June
2023, Vol 2, 15.35.2 Enabling SEV-ES.
https://bugzilla.kernel.org/attachment.cgi?id=304653Message-ID: <[email protected]>
--- arch/x86/kvm/svm/sev.c | 13 ++++++++----- arch/x86/kvm/svm/svm.c | 8 +++++++- arch/x86/kvm/svm/svm.h | 3 ++- 3 files changed, 17 insertions(+), 7 deletions(-)
arch/x86/kvm/svm/sev.c +8 -5
@@ -664,6 +664,14 @@ static int __sev_launch_update_vmsa(struct kvm *kvm, struct kvm_vcpu *vcpu,return ret; vcpu->arch.guest_state_protected = true; + +/* +* SEV-ES guest mandates LBR Virtualization to be _always_ ON. Enable it +* only after setting guest_state_protected because KVM_SET_MSRS allows +* dynamic toggling of LBRV (for performance reason) on write access to +* MSR_IA32_DEBUGCTLMSR when guest_state_protected is not set. +*/ +svm_enable_lbrv (vcpu);return 0 ; }
@@ -3035,7 +3043,6 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm)struct kvm_vcpu *vcpu = &svm->vcpu; svm->vmcb->control.nested_ctl |=SVM_NESTED_CTL_SEV_ES_ENABLE ; - svm->vmcb->control.virt_ext |=LBR_CTL_ENABLE_MASK ;/* * An SEV-ES guest requires a VMSA area that is a separate from the
@@ -3087,10 +3094,6 @@ static void sev_es_init_vmcb(struct vcpu_svm *svm)/* Clear intercepts on selected MSRs */ set_msr_interception (vcpu, svm->msrpm,MSR_EFER ,1 ,1 );set_msr_interception (vcpu, svm->msrpm,MSR_IA32_CR_PAT ,1 ,1 ); -set_msr_interception (vcpu, svm->msrpm,MSR_IA32_LASTBRANCHFROMIP ,1 ,1 ); -set_msr_interception (vcpu, svm->msrpm,MSR_IA32_LASTBRANCHTOIP ,1 ,1 ); -set_msr_interception (vcpu, svm->msrpm,MSR_IA32_LASTINTFROMIP ,1 ,1 ); -set_msr_interception (vcpu, svm->msrpm,MSR_IA32_LASTINTTOIP ,1 ,1 ); }void sev_init_vmcb (struct vcpu_svm *svm)
arch/x86/kvm/svm/svm.c +7 -1
@@ -99,6 +99,7 @@ static const struct svm_direct_access_msrs { { .index = MSR_IA32_SPEC_CTRL, .always = false }, { .index = MSR_IA32_PRED_CMD, .always = false }, { .index = MSR_IA32_FLUSH_CMD, .always = false }, + { .index = MSR_IA32_DEBUGCTLMSR, .always = false }, { .index = MSR_IA32_LASTBRANCHFROMIP, .always = false }, { .index = MSR_IA32_LASTBRANCHTOIP, .always = false }, { .index = MSR_IA32_LASTINTFROMIP, .always = false },
@@ -1008,7 +1009,7 @@ void svm_copy_lbrs(struct vmcb *to_vmcb, struct vmcb *from_vmcb)vmcb_mark_dirty (to_vmcb,VMCB_LBR ); } -static void svm_enable_lbrv (struct kvm_vcpu *vcpu) +void svm_enable_lbrv (struct kvm_vcpu *vcpu) {struct vcpu_svm *svm =to_svm (vcpu);
@@ -1018,6 +1019,9 @@ static void svm_enable_lbrv(struct kvm_vcpu *vcpu)set_msr_interception (vcpu, svm->msrpm,MSR_IA32_LASTINTFROMIP ,1 ,1 );set_msr_interception (vcpu, svm->msrpm,MSR_IA32_LASTINTTOIP ,1 ,1 ); +if (sev_es_guest (vcpu->kvm)) +set_msr_interception (vcpu, svm->msrpm,MSR_IA32_DEBUGCTLMSR ,1 ,1 ); +/* Move the LBR msrs to the vmcb02 so that the guest can see them. */ if (is_guest_mode (vcpu))svm_copy_lbrs (svm->vmcb, svm->vmcb01.ptr);
@@ -1027,6 +1031,8 @@ static void svm_disable_lbrv(struct kvm_vcpu *vcpu) {struct vcpu_svm *svm =to_svm (vcpu); +KVM_BUG_ON (sev_es_guest (vcpu->kvm), vcpu->kvm); + svm->vmcb->control.virt_ext &= ~LBR_CTL_ENABLE_MASK ;set_msr_interception (vcpu, svm->msrpm,MSR_IA32_LASTBRANCHFROMIP ,0 ,0 );set_msr_interception (vcpu, svm->msrpm,MSR_IA32_LASTBRANCHTOIP ,0 ,0 );
arch/x86/kvm/svm/svm.h +2 -1
@@ -30,7 +30,7 @@#define IOPM_SIZE PAGE_SIZE * 3#define MSRPM_SIZE PAGE_SIZE * 2 -#define MAX_DIRECT_ACCESS_MSRS 47 +#define MAX_DIRECT_ACCESS_MSRS 48#define MSRPM_OFFSETS 32extern u32 msrpm_offsets[MSRPM_OFFSETS ]__read_mostly ;extern bool npt_enabled;
@@ -542,6 +542,7 @@ u32 *svm_vcpu_alloc_msrpm(void);void svm_vcpu_init_msrpm (struct kvm_vcpu *vcpu,u32 *msrpm);void svm_vcpu_free_msrpm (u32 *msrpm);void svm_copy_lbrs (struct vmcb *to_vmcb,struct vmcb *from_vmcb); +void svm_enable_lbrv (struct kvm_vcpu *vcpu);void svm_update_lbrv (struct kvm_vcpu *vcpu);int svm_set_efer (struct kvm_vcpu *vcpu,u64 efer);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 27/267 vmxnet3: disable rx data ring on dma allocation failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthias Stocker <[email protected]>
[ Upstream commit ffbe335b8d471f79b259e950cb20999700670456 ]
When vmxnet3_rq_create() fails to allocate memory for rq->data_ring.base, the subsequent call to vmxnet3_rq_destroy_all_rxdataring does not reset rq->data_ring.desc_size for the data ring that failed, which presumably causes the hypervisor to reference it on packet reception.
To fix this bug, rq->data_ring.desc_size needs to be set to 0 to tell the hypervisor to disable this feature.
[ 95.436876] kernel BUG at net/core/skbuff.c:207! [ 95.439074] invalid opcode: 0000 [#1] PREEMPT SMP NOPTI [ 95.440411] CPU: 7 PID: 0 Comm: swapper/7 Not tainted 6.9.3-dirty #1 [ 95.441558] Hardware name: VMware, Inc. VMware Virtual Platform/440BX Desktop Reference Platform, BIOS 6.00 12/12/2018 [ 95.443481] RIP: 0010:skb_panic+0x4d/0x4f [ 95.444404] Code: 4f 70 50 8b 87 c0 00 00 00 50 8b 87 bc 00 00 00 50 ff b7 d0 00 00 00 4c 8b 8f c8 00 00 00 48 c7 c7 68 e8 be 9f e8 63 58 f9 ff <0f> 0b 48 8b 14 24 48 c7 c1 d0 73 65 9f e8 a1 ff ff ff 48 8b 14 24 [ 95.447684] RSP: 0018:ffffa13340274dd0 EFLAGS: 00010246 [ 95.448762] RAX: 0000000000000089 RBX: ffff8fbbc72b02d0 RCX: 000000000000083f [ 95.450148] RDX: 0000000000000000 RSI: 00000000000000f6 RDI: 000000000000083f [ 95.451520] RBP: 000000000000002d R08: 0000000000000000 R09: ffffa13340274c60 [ 95.452886] R10: ffffffffa04ed468 R11: 0000000000000002 R12: 0000000000000000 [ 95.454293] R13: ffff8fbbdab3c2d0 R14: ffff8fbbdbd829e0 R15: ffff8fbbdbd809e0 [ 95.455682] FS: 0000000000000000(0000) GS:ffff8fbeefd80000(0000) knlGS:0000000000000000 [ 95.457178] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 95.458340] CR2: 00007fd0d1f650c8 CR3: 0000000115f28000 CR4: 00000000000406f0 [ 95.459791] Call Trace: [ 95.460515] <IRQ> [ 95.461180] ? __die_body.cold+0x19/0x27 [ 95.462150] ? die+0x2e/0x50 [ 95.462976] ? do_trap+0xca/0x110 [ 95.463973] ? do_error_trap+0x6a/0x90 [ 95.464966] ? skb_panic+0x4d/0x4f [ 95.465901] ? exc_invalid_op+0x50/0x70 [ 95.466849] ? skb_panic+0x4d/0x4f [ 95.467718] ? asm_exc_invalid_op+0x1a/0x20 [ 95.468758] ? skb_panic+0x4d/0x4f [ 95.469655] skb_put.cold+0x10/0x10 [ 95.470573] vmxnet3_rq_rx_complete+0x862/0x11e0 [vmxnet3] [ 95.471853] vmxnet3_poll_rx_only+0x36/0xb0 [vmxnet3] [ 95.473185] __napi_poll+0x2b/0x160 [ 95.474145] net_rx_action+0x2c6/0x3b0 [ 95.475115] handle_softirqs+0xe7/0x2a0 [ 95.476122] __irq_exit_rcu+0x97/0xb0 [ 95.477109] common_interrupt+0x85/0xa0 [ 95.478102] </IRQ> [ 95.478846] <TASK> [ 95.479603] asm_common_interrupt+0x26/0x40 [ 95.480657] RIP: 0010:pv_native_safe_halt+0xf/0x20 [ 95.481801] Code: 22 d7 e9 54 87 01 00 0f 1f 40 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 f3 0f 1e fa eb 07 0f 00 2d 93 ba 3b 00 fb f4 <e9> 2c 87 01 00 66 66 2e 0f 1f 84 00 00 00 00 00 90 90 90 90 90 90 [ 95.485563] RSP: 0018:ffffa133400ffe58 EFLAGS: 00000246 [ 95.486882] RAX: 0000000000004000 RBX: ffff8fbbc1d14064 RCX: 0000000000000000 [ 95.488477] RDX: ffff8fbeefd80000 RSI: ffff8fbbc1d14000 RDI: 0000000000000001 [ 95.490067] RBP: ffff8fbbc1d14064 R08: ffffffffa0652260 R09: 00000000000010d3 [ 95.491683] R10: 0000000000000018 R11: ffff8fbeefdb4764 R12: ffffffffa0652260 [ 95.493389] R13: ffffffffa06522e0 R14: 0000000000000001 R15: 0000000000000000 [ 95.495035] acpi_safe_halt+0x14/0x20 [ 95.496127] acpi_idle_do_entry+0x2f/0x50 [ 95.497221] acpi_idle_enter+0x7f/0xd0 [ 95.498272] cpuidle_enter_state+0x81/0x420 [ 95.499375] cpuidle_enter+0x2d/0x40 [ 95.500400] do_idle+0x1e5/0x240 [ 95.501385] cpu_startup_entry+0x29/0x30 [ 95.502422] start_secondary+0x11c/0x140 [ 95.503454] common_startup_64+0x13e/0x141 [ 95.504466] </TASK> [ 95.505197] Modules linked in: nft_fib_inet nft_fib_ipv4
nft_fib_ipv6 nft_fib nft_reject_inet nf_reject_ipv4 nf_reject_ipv6 nft_reject nft_ct nft_chain_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 rfkill ip_set nf_tables vsock_loopback vmw_vsock_virtio_transport_common qrtr vmw_vsock_vmci_transport vsock sunrpc binfmt_misc pktcdvd vmw_balloon pcspkr vmw_vmci i2c_piix4 joydev loop dm_multipath nfnetlink zram crct10dif_pclmul crc32_pclmul vmwgfx crc32c_intel polyval_clmulni polyval_generic ghash_clmulni_intel sha512_ssse3 sha256_ssse3 vmxnet3 sha1_ssse3 drm_ttm_helper vmw_pvscsi ttm ata_generic pata_acpi serio_raw scsi_dh_rdac scsi_dh_emc scsi_dh_alua ip6_tables ip_tables fuse
[ 95.516536] ---[ end trace 0000000000000000 ]---
--- drivers/net/vmxnet3/vmxnet3_drv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/vmxnet3/vmxnet3_drv.c +1 -1
@@ -2034,8 +2034,8 @@ vmxnet3_rq_destroy_all_rxdataring(struct vmxnet3_adapter *adapter) rq->data_ring.base, rq->data_ring.basePA); rq->data_ring.base =NULL ; - rq->data_ring.desc_size =0 ; } + rq->data_ring.desc_size =0 ; } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 28/267 ipv6: ioam: block BH from ioam6_output()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 2fe40483ec257de2a0d819ef88e3e76c7e261319 ]
As explained in commit 1378817486d6 ("tipc: block BH before using dst_cache"), net/core/dst_cache.c helpers need to be called with BH disabled.
Disabling preemption in ioam6_output() is not good enough, because ioam6_output() is called from process context, lwtunnel_output() only uses rcu_read_lock().
We might be interrupted by a softirq, re-enter ioam6_output() and corrupt dst_cache data structures.
Fix the race by using local_bh_disable() instead of preempt_disable().
--- net/ipv6/ioam6_iptunnel.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/ipv6/ioam6_iptunnel.c +4 -4
@@ -351,9 +351,9 @@ static int ioam6_output(struct net *net, struct sock *sk, struct sk_buff *skb) goto drop;if (!ipv6_addr_equal (&orig_daddr, &ipv6_hdr (skb)->daddr)) { -preempt_disable (); +local_bh_disable (); dst =dst_cache_get (&ilwt->cache); -preempt_enable (); +local_bh_enable ();if (unlikely (!dst)) {struct ipv6hdr *hdr =ipv6_hdr (skb);
@@ -373,9 +373,9 @@ static int ioam6_output(struct net *net, struct sock *sk, struct sk_buff *skb) goto drop; } -preempt_disable (); +local_bh_disable ();dst_cache_set_ip6 (&ilwt->cache, dst, &fl6.saddr); -preempt_enable (); +local_bh_enable (); }skb_dst_drop (skb);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 29/267 ipv6: sr: block BH in seg6_output_core() and seg6_input_core()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit c0b98ac1cc104f48763cdb27b1e9ac25fd81fc90 ]
As explained in commit 1378817486d6 ("tipc: block BH before using dst_cache"), net/core/dst_cache.c helpers need to be called with BH disabled.
Disabling preemption in seg6_output_core() is not good enough, because seg6_output_core() is called from process context, lwtunnel_output() only uses rcu_read_lock().
We might be interrupted by a softirq, re-enter seg6_output_core() and corrupt dst_cache data structures.
Fix the race by using local_bh_disable() instead of preempt_disable().
Apply a similar change in seg6_input_core().
--- net/ipv6/seg6_iptunnel.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-)
net/ipv6/seg6_iptunnel.c +6 -8
@@ -464,23 +464,21 @@ static int seg6_input_core(struct net *net, struct sock *sk, slwt =seg6_lwt_lwtunnel (orig_dst->lwtstate); -preempt_disable (); +local_bh_disable (); dst =dst_cache_get (&slwt->cache); -preempt_enable ();if (!dst) {ip6_route_input (skb); dst =skb_dst (skb);if (!dst->error) { -preempt_disable ();dst_cache_set_ip6 (&slwt->cache, dst, &ipv6_hdr (skb)->saddr); -preempt_enable (); } }else {skb_dst_drop (skb);skb_dst_set (skb, dst); } +local_bh_enable (); err =skb_cow_head (skb,LL_RESERVED_SPACE (dst->dev));if (unlikely (err))
@@ -536,9 +534,9 @@ static int seg6_output_core(struct net *net, struct sock *sk, slwt =seg6_lwt_lwtunnel (orig_dst->lwtstate); -preempt_disable (); +local_bh_disable (); dst =dst_cache_get (&slwt->cache); -preempt_enable (); +local_bh_enable ();if (unlikely (!dst)) {struct ipv6hdr *hdr =ipv6_hdr (skb);
@@ -558,9 +556,9 @@ static int seg6_output_core(struct net *net, struct sock *sk, goto drop; } -preempt_disable (); +local_bh_disable ();dst_cache_set_ip6 (&slwt->cache, dst, &fl6.saddr); -preempt_enable (); +local_bh_enable (); }skb_dst_drop (skb);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 30/267 net: tls: fix marking packets as decrypted
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Kicinski <[email protected]>
[ Upstream commit a535d59432370343058755100ee75ab03c0e3f91 ]
For TLS offload we mark packets with skb->decrypted to make sure they don't escape the host without getting encrypted first. The crypto state lives in the socket, so it may get detached by a call to skb_orphan(). As a safety check - the egress path drops all packets with skb->decrypted and no "crypto-safe" socket.
The skb marking was added to sendpage only (and not sendmsg), because tls_device injected data into the TCP stack using sendpage. This special case was missed when sendpage got folded into sendmsg.
--- net/ipv4/tcp.c | 3 +++ 1 file changed, 3 insertions(+)
net/ipv4/tcp.c +3 -0
@@ -1158,6 +1158,9 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size) process_backlog++; +#ifdef CONFIG_SKB_DECRYPTED + skb->decrypted = !!(flags &MSG_SENDPAGE_DECRYPTED ); +#endif tcp_skb_entail (sk, skb); copy = size_goal;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 31/267 bpf: Set run context for rawtp test_run callback
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiri Olsa <[email protected]>
[ Upstream commit d0d1df8ba18abc57f28fb3bc053b2bf319367f2c ]
syzbot reported crash when rawtp program executed through the test_run interface calls bpf_get_attach_cookie helper or any other helper that touches task->bpf_ctx pointer.
Setting the run context (task->bpf_ctx pointer) for test_run callback.
--- net/bpf/test_run.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/bpf/test_run.c +6 -0
@@ -707,10 +707,16 @@ static void __bpf_prog_test_run_raw_tp(void *data) {struct bpf_raw_tp_test_run_info *info = data; +struct bpf_trace_run_ctx run_ctx = {}; +struct bpf_run_ctx *old_run_ctx; + + old_run_ctx =bpf_set_run_ctx (&run_ctx.run_ctx);rcu_read_lock (); info->retval =bpf_prog_run (info->prog, info->ctx);rcu_read_unlock (); + +bpf_reset_run_ctx (old_run_ctx); } int bpf_prog_test_run_raw_tp(struct bpf_prog *prog,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 32/267 octeontx2-af: Always allocate PF entries from low prioriy zone
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Subbaraya Sundeep <[email protected]>
[ Upstream commit 8b0f7410942cdc420c4557eda02bfcdf60ccec17 ]
PF mcam entries has to be at low priority always so that VF can install longest prefix match rules at higher priority. This was taken care currently but when priority allocation wrt reference entry is requested then entries are allocated from mid-zone instead of low priority zone. Fix this and always allocate entries from low priority zone for PFs.
--- .../ethernet/marvell/octeontx2/af/rvu_npc.c | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-)
drivers/net/ethernet/marvell/octeontx2/af/rvu_npc.c +22 -11
@@ -2506,7 +2506,17 @@ static int npc_mcam_alloc_entries(struct npc_mcam *mcam, u16 pcifunc,* - when available free entries are less. * Lower priority ones out of avaialble free entries are always * chosen when 'high vs low' question arises. +* +* For a VF base MCAM match rule is set by its PF. And all the +* further MCAM rules installed by VF on its own are +* concatenated with the base rule set by its PF. Hence PF entries +* should be at lower priority compared to VF entries. Otherwise +* base rule is hit always and rules installed by VF will be of +* no use. Hence if the request is from PF then allocate low +* priority entries. */ +if (!(pcifunc &RVU_PFVF_FUNC_MASK )) + goto lprio_alloc;/* Get the search range for priority allocation request */ if (req->priority) {
@@ -2515,17 +2525,6 @@ static int npc_mcam_alloc_entries(struct npc_mcam *mcam, u16 pcifunc, goto alloc; } -/* For a VF base MCAM match rule is set by its PF. And all the -* further MCAM rules installed by VF on its own are -* concatenated with the base rule set by its PF. Hence PF entries -* should be at lower priority compared to VF entries. Otherwise -* base rule is hit always and rules installed by VF will be of -* no use. Hence if the request is from PF and NOT a priority -* allocation request then allocate low priority entries. -*/ -if (!(pcifunc &RVU_PFVF_FUNC_MASK )) - goto lprio_alloc; -/* Find out the search range for non-priority allocation request * * Get MCAM free entry count in middle zone.
@@ -2555,6 +2554,18 @@ static int npc_mcam_alloc_entries(struct npc_mcam *mcam, u16 pcifunc, reverse = true; start =0 ; end = mcam->bmap_entries; +/* Ensure PF requests are always at bottom and if PF requests +* for higher/lower priority entry wrt reference entry then +* honour that criteria and start search for entries from bottom +* and not in mid zone. +*/ +if (!(pcifunc &RVU_PFVF_FUNC_MASK ) && + req->priority ==NPC_MCAM_HIGHER_PRIO ) + end = req->ref_entry; + +if (!(pcifunc &RVU_PFVF_FUNC_MASK ) && + req->priority ==NPC_MCAM_LOWER_PRIO ) + start = req->ref_entry; } alloc:
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 33/267 net/smc: avoid overwriting when adjusting sock bufsizes
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wen Gu <[email protected]>
[ Upstream commit fb0aa0781a5f457e3864da68af52c3b1f4f7fd8f ]
When copying smc settings to clcsock, avoid setting clcsock's sk_sndbuf to sysctl_tcp_wmem[1], since this may overwrite the value set by tcp_sndbuf_expand() in TCP connection establishment.
And the other setting sk_{snd|rcv}buf to sysctl value in smc_adjust_sock_bufsizes() can also be omitted since the initialization of smc sock and clcsock has set sk_{snd|rcv}buf to smc.sysctl_{w|r}mem or ipv4_sysctl_tcp_{w|r}mem[1].
--- net/smc/af_smc.c | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-)
net/smc/af_smc.c +2 -20
@@ -460,29 +460,11 @@ static int smc_bind(struct socket *sock, struct sockaddr *uaddr,static void smc_adjust_sock_bufsizes (struct sock *nsk,struct sock *osk,unsigned long mask) { -struct net *nnet =sock_net (nsk); - nsk->sk_userlocks = osk->sk_userlocks; -if (osk->sk_userlocks &SOCK_SNDBUF_LOCK ) { +if (osk->sk_userlocks &SOCK_SNDBUF_LOCK ) nsk->sk_sndbuf = osk->sk_sndbuf; - }else { -if (mask ==SK_FLAGS_SMC_TO_CLC ) -WRITE_ONCE (nsk->sk_sndbuf, -READ_ONCE (nnet->ipv4.sysctl_tcp_wmem[1 ])); -else -WRITE_ONCE (nsk->sk_sndbuf, -2 *READ_ONCE (nnet->smc.sysctl_wmem)); - } -if (osk->sk_userlocks &SOCK_RCVBUF_LOCK ) { +if (osk->sk_userlocks &SOCK_RCVBUF_LOCK ) nsk->sk_rcvbuf = osk->sk_rcvbuf; - }else { -if (mask ==SK_FLAGS_SMC_TO_CLC ) -WRITE_ONCE (nsk->sk_rcvbuf, -READ_ONCE (nnet->ipv4.sysctl_tcp_rmem[1 ])); -else -WRITE_ONCE (nsk->sk_rcvbuf, -2 *READ_ONCE (nnet->smc.sysctl_rmem)); - } } static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 34/267 net: phy: Micrel KSZ8061: fix errata solution not taking effect problem
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristram Ha <[email protected]>
[ Upstream commit 0a8d3f2e3e8d8aea8af017e14227b91d5989b696 ]
KSZ8061 needs to write to a MMD register at driver initialization to fix an errata. This worked in 5.0 kernel but not in newer kernels. The issue is the main phylib code no longer resets PHY at the very beginning. Calling phy resuming code later will reset the chip if it is already powered down at the beginning. This wipes out the MMD register write. Solution is to implement a phy resume function for KSZ8061 to take care of this problem.
--- drivers/net/phy/micrel.c | 42 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 41 insertions(+), 1 deletion(-)
drivers/net/phy/micrel.c +41 -1
@@ -770,6 +770,17 @@ static int ksz8061_config_init(struct phy_device *phydev) {int ret; +/* Chip can be powered down by the bootstrap code. */ + ret =phy_read (phydev,MII_BMCR ); +if (ret <0 ) +return ret; +if (ret &BMCR_PDOWN ) { + ret =phy_write (phydev,MII_BMCR , ret & ~BMCR_PDOWN ); +if (ret <0 ) +return ret; +usleep_range (1000 ,2000 ); + } + ret =phy_write_mmd (phydev,MDIO_MMD_PMAPMD ,MDIO_DEVID1 ,0xB61A );if (ret)return ret;
@@ -2017,6 +2028,35 @@ static int ksz9477_resume(struct phy_device *phydev)return 0 ; } +static int ksz8061_resume (struct phy_device *phydev) +{ +int ret; + +/* This function can be called twice when the Ethernet device is on. */ + ret =phy_read (phydev,MII_BMCR ); +if (ret <0 ) +return ret; +if (!(ret &BMCR_PDOWN )) +return 0 ; + +genphy_resume (phydev); +usleep_range (1000 ,2000 ); + +/* Re-program the value after chip is reset. */ + ret =phy_write_mmd (phydev,MDIO_MMD_PMAPMD ,MDIO_DEVID1 ,0xB61A ); +if (ret) +return ret; + +/* Enable PHY Interrupts */ +if (phy_interrupt_is_valid (phydev)) { + phydev->interrupts =PHY_INTERRUPT_ENABLED ; +if (phydev->drv->config_intr) + phydev->drv->config_intr (phydev); + } + +return 0 ; +} +static int kszphy_probe (struct phy_device *phydev) {const struct kszphy_type *type = phydev->drv->driver_data;
@@ -4812,7 +4852,7 @@ static struct phy_driver ksphy_driver[] = { .config_intr = kszphy_config_intr, .handle_interrupt = kszphy_handle_interrupt, .suspend = kszphy_suspend, - .resume = kszphy_resume, + .resume = ksz8061_resume, }, { .phy_id = PHY_ID_KSZ9021, .phy_id_mask = 0x000ffffe,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 35/267 net: sched: sch_multiq: fix possible OOB write in multiq_tune()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangyu Hua <[email protected]>
[ Upstream commit affc18fdc694190ca7575b9a86632a73b9fe043d ]
q->bands will be assigned to qopt->bands to execute subsequent code logic after kmalloc. So the old q->bands should not be used in kmalloc. Otherwise, an out-of-bounds write will occur.
--- net/sched/sch_multiq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/sch_multiq.c +1 -1
@@ -185,7 +185,7 @@ static int multiq_tune(struct Qdisc *sch, struct nlattr *opt, qopt->bands =qdisc_dev (sch)->real_num_tx_queues; - removed =kmalloc (sizeof (*removed) * (q->max_bands - q->bands), + removed =kmalloc (sizeof (*removed) * (q->max_bands - qopt->bands),GFP_KERNEL );if (!removed)return -ENOMEM ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 36/267 vxlan: Fix regression when dropping packets due to invalid src addresses
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 1cd4bc987abb2823836cbb8f887026011ccddc8a ]
Commit f58f45c1e5b9 ("vxlan: drop packets from invalid src-address") has recently been added to vxlan mainly in the context of source address snooping/learning so that when it is enabled, an entry in the FDB is not being created for an invalid address for the corresponding tunnel endpoint.
Before commit f58f45c1e5b9 vxlan was similarly behaving as geneve in that it passed through whichever macs were set in the L2 header. It turns out that this change in behavior breaks setups, for example, Cilium with netkit in L3 mode for Pods as well as tunnel mode has been passing before the change in f58f45c1e5b9 for both vxlan and geneve. After mentioned change it is only passing for geneve as in case of vxlan packets are dropped due to vxlan_set_mac() returning false as source and destination macs are zero which for E/W traffic via tunnel is totally fine.
Fix it by only opting into the is_valid_ether_addr() check in vxlan_set_mac() when in fact source address snooping/learning is actually enabled in vxlan. This is done by moving the check into vxlan_snoop(). With this change, the Cilium connectivity test suite passes again for both tunnel flavors.
--- drivers/net/vxlan/vxlan_core.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/net/vxlan/vxlan_core.c +4 -0
@@ -1446,6 +1446,10 @@ static bool vxlan_snoop(struct net_device *dev,struct vxlan_fdb *f;u32 ifindex =0 ; +/* Ignore packets from invalid src-address */ +if (!is_valid_ether_addr (src_mac)) +return true; +#if IS_ENABLED (CONFIG_IPV6 )if (src_ip->sa.sa_family ==AF_INET6 && (ipv6_addr_type (&src_ip->sin6.sin6_addr) &IPV6_ADDR_LINKLOCAL ))
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 37/267 tcp: count CLOSE-WAIT sockets for TCP_MIB_CURRESTAB
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Xing <[email protected]>
[ Upstream commit a46d0ea5c94205f40ecf912d1bb7806a8a64704f ]
According to RFC 1213, we should also take CLOSE-WAIT sockets into consideration:
"tcpCurrEstab OBJECT-TYPE
...
The number of TCP connections for which the current state is either ESTABLISHED or CLOSE- WAIT."
After this, CurrEstab counter will display the total number of ESTABLISHED and CLOSE-WAIT sockets.
The logic of counting
When we increment the counter?
a) if we change the state to ESTABLISHED.
b) if we change the state from SYN-RECEIVED to CLOSE-WAIT.
When we decrement the counter?
a) if the socket leaves ESTABLISHED and will never go into CLOSE-WAIT, say, on the client side, changing from ESTABLISHED to FIN-WAIT-1.
b) if the socket leaves CLOSE-WAIT, say, on the server side, changing from CLOSE-WAIT to LAST-ACK.
Please note: there are two chances that old state of socket can be changed to CLOSE-WAIT in tcp_fin(). One is SYN-RECV, the other is ESTABLISHED. So we have to take care of the former case.
--- net/ipv4/tcp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/ipv4/tcp.c +5 -1
@@ -2640,6 +2640,10 @@ void tcp_set_state(struct sock *sk, int state)if (oldstate !=TCP_ESTABLISHED )TCP_INC_STATS (sock_net (sk),TCP_MIB_CURRESTAB );break ; +case TCP_CLOSE_WAIT : +if (oldstate ==TCP_SYN_RECV ) +TCP_INC_STATS (sock_net (sk),TCP_MIB_CURRESTAB ); +break ;case TCP_CLOSE :if (oldstate ==TCP_CLOSE_WAIT || oldstate ==TCP_ESTABLISHED )
@@ -2651,7 +2655,7 @@ void tcp_set_state(struct sock *sk, int state)inet_put_port (sk); fallthrough;default : -if (oldstate ==TCP_ESTABLISHED ) +if (oldstate ==TCP_ESTABLISHED || oldstate ==TCP_CLOSE_WAIT )TCP_DEC_STATS (sock_net (sk),TCP_MIB_CURRESTAB ); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 38/267 mptcp: count CLOSE-WAIT sockets for MPTCP_MIB_CURRESTAB
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Xing <[email protected]>
[ Upstream commit 9633e9377e6af0244f7381e86b9aac5276f5be97 ]
Like previous patch does in TCP, we need to adhere to RFC 1213:
"tcpCurrEstab OBJECT-TYPE
...
The number of TCP connections for which the current state is either ESTABLISHED or CLOSE- WAIT."
So let's consider CLOSE-WAIT sockets.
The logic of counting
When we increment the counter?
a) Only if we change the state to ESTABLISHED.
When we decrement the counter?
a) if the socket leaves ESTABLISHED and will never go into CLOSE-WAIT, say, on the client side, changing from ESTABLISHED to FIN-WAIT-1.
b) if the socket leaves CLOSE-WAIT, say, on the server side, changing from CLOSE-WAIT to LAST-ACK.
--- net/mptcp/protocol.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
net/mptcp/protocol.c +7 -2
@@ -2873,9 +2873,14 @@ void mptcp_set_state(struct sock *sk, int state)if (oldstate !=TCP_ESTABLISHED )MPTCP_INC_STATS (sock_net (sk),MPTCP_MIB_CURRESTAB );break ; - +case TCP_CLOSE_WAIT : +/* Unlike TCP, MPTCP sk would not have the TCP_SYN_RECV state: +* MPTCP "accepted" sockets will be created later on. So no +* transition from TCP_SYN_RECV to TCP_CLOSE_WAIT. +*/ +break ;default : -if (oldstate ==TCP_ESTABLISHED ) +if (oldstate ==TCP_ESTABLISHED || oldstate ==TCP_CLOSE_WAIT )MPTCP_DEC_STATS (sock_net (sk),MPTCP_MIB_CURRESTAB ); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 39/267 net/mlx5: Stop waiting for PCI if pci channel is offline
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Moshe Shemesh <[email protected]>
[ Upstream commit 33afbfcc105a572159750f2ebee834a8a70fdd96 ]
In case pci channel becomes offline the driver should not wait for PCI reads during health dump and recovery flow. The driver has timeout for each of these loops trying to read PCI, so it would fail anyway. However, in case of recovery waiting till timeout may cause the pci error_detected() callback fail to meet pci_dpc_recovered() wait timeout.
--- drivers/net/ethernet/mellanox/mlx5/core/fw.c | 4 ++++ drivers/net/ethernet/mellanox/mlx5/core/health.c | 8 ++++++++ drivers/net/ethernet/mellanox/mlx5/core/lib/pci_vsc.c | 4 ++++ 3 files changed, 16 insertions(+)
drivers/net/ethernet/mellanox/mlx5/core/fw.c +4 -0
@@ -373,6 +373,10 @@ int mlx5_cmd_fast_teardown_hca(struct mlx5_core_dev *dev)do {if (mlx5_get_nic_state (dev) ==MLX5_NIC_IFC_DISABLED )break ; +if (pci_channel_offline (dev->pdev)) { +mlx5_core_err (dev,"PCI channel offline, stop waiting for NIC IFC\n" ); +return -EACCES ; + }cond_resched (); }while (!time_after (jiffies, end));
drivers/net/ethernet/mellanox/mlx5/core/health.c +8 -0
@@ -248,6 +248,10 @@ void mlx5_error_sw_reset(struct mlx5_core_dev *dev)do {if (mlx5_get_nic_state (dev) ==MLX5_NIC_IFC_DISABLED )break ; +if (pci_channel_offline (dev->pdev)) { +mlx5_core_err (dev,"PCI channel offline, stop waiting for NIC IFC\n" ); + goto unlock; + }msleep (20 ); }while (!time_after (jiffies, end));
@@ -317,6 +321,10 @@ int mlx5_health_wait_pci_up(struct mlx5_core_dev *dev)mlx5_core_warn (dev,"device is being removed, stop waiting for PCI\n" );return -ENODEV ; } +if (pci_channel_offline (dev->pdev)) { +mlx5_core_err (dev,"PCI channel offline, stop waiting for PCI\n" ); +return -EACCES ; + }msleep (100 ); }return 0 ;
drivers/net/ethernet/mellanox/mlx5/core/lib/pci_vsc.c +4 -0
@@ -74,6 +74,10 @@ int mlx5_vsc_gw_lock(struct mlx5_core_dev *dev) ret = -EBUSY ; goto pci_unlock; } +if (pci_channel_offline (dev->pdev)) { + ret = -EACCES ; + goto pci_unlock; + }/* Check if semaphore is already locked */ ret =vsc_read (dev,VSC_SEMAPHORE_OFFSET , &lock_val);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 40/267 net/mlx5: Always stop health timer during driver removal
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shay Drory <[email protected]>
[ Upstream commit c8b3f38d2dae0397944814d691a419c451f9906f ]
Currently, if teardown_hca fails to execute during driver removal, mlx5 does not stop the health timer. Afterwards, mlx5 continue with driver teardown. This may lead to a UAF bug, which results in page fault Oops[1], since the health timer invokes after resources were freed.
Hence, stop the health monitor even if teardown_hca fails.
[1]mlx5_core 0000:18:00.0: E-Switch: Unload vfs: mode(LEGACY), nvfs(0), necvfs(0), active vports(0) mlx5_core 0000:18:00.0: E-Switch: Disable: mode(LEGACY), nvfs(0), necvfs(0), active vports(0) mlx5_core 0000:18:00.0: E-Switch: Disable: mode(LEGACY), nvfs(0), necvfs(0), active vports(0) mlx5_core 0000:18:00.0: E-Switch: cleanupmlx5_core 0000:18:00.0: wait_func:1155:(pid 1967079): TEARDOWN_HCA(0x103) timeout. Will cause a leak of a command resource mlx5_core 0000:18:00.0: mlx5_function_close:1288:(pid 1967079): tear_down_hca failed, skip cleanup
BUG: unable to handle page fault for address: ffffa26487064230 PGD 100c00067 P4D 100c00067 PUD 100e5a067 PMD 105ed7067 PTE 0 Oops: 0000 [#1] PREEMPT SMP PTI CPU: 0 PID: 0 Comm: swapper/0 Tainted: G OE ------- --- 6.7.0-68.fc38.x86_64 #1 Hardware name: Intel Corporation S2600WFT/S2600WFT, BIOS SE5C620.86B.02.01.0013.121520200651 12/15/2020 RIP: 0010:ioread32be+0x34/0x60 RSP: 0018:ffffa26480003e58 EFLAGS: 00010292 RAX: ffffa26487064200 RBX: ffff9042d08161a0 RCX: ffff904c108222c0 RDX: 000000010bbf1b80 RSI: ffffffffc055ddb0 RDI: ffffa26487064230 RBP: ffff9042d08161a0 R08: 0000000000000022 R09: ffff904c108222e8 R10: 0000000000000004 R11: 0000000000000441 R12: ffffffffc055ddb0 R13: ffffa26487064200 R14: ffffa26480003f00 R15: ffff904c108222c0 FS: 0000000000000000(0000) GS:ffff904c10800000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffa26487064230 CR3: 00000002c4420006 CR4: 00000000007706f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 PKRU: 55555554 Call Trace: <IRQ> ? __die+0x23/0x70 ? page_fault_oops+0x171/0x4e0 ? exc_page_fault+0x175/0x180 ? asm_exc_page_fault+0x26/0x30 ? __pfx_poll_health+0x10/0x10 [mlx5_core] ? __pfx_poll_health+0x10/0x10 [mlx5_core] ? ioread32be+0x34/0x60 mlx5_health_check_fatal_sensors+0x20/0x100 [mlx5_core] ? __pfx_poll_health+0x10/0x10 [mlx5_core] poll_health+0x42/0x230 [mlx5_core] ? __next_timer_interrupt+0xbc/0x110 ? __pfx_poll_health+0x10/0x10 [mlx5_core] call_timer_fn+0x21/0x130 ? __pfx_poll_health+0x10/0x10 [mlx5_core] __run_timers+0x222/0x2c0 run_timer_softirq+0x1d/0x40 __do_softirq+0xc9/0x2c8 __irq_exit_rcu+0xa6/0xc0 sysvec_apic_timer_interrupt+0x72/0x90 </IRQ> <TASK> asm_sysvec_apic_timer_interrupt+0x1a/0x20 RIP: 0010:cpuidle_enter_state+0xcc/0x440 ? cpuidle_enter_state+0xbd/0x440 cpuidle_enter+0x2d/0x40 do_idle+0x20d/0x270 cpu_startup_entry+0x2a/0x30 rest_init+0xd0/0xd0 arch_call_rest_init+0xe/0x30 start_kernel+0x709/0xa90 x86_64_start_reservations+0x18/0x30 x86_64_start_kernel+0x96/0xa0 secondary_startup_64_no_verify+0x18f/0x19b ---[ end trace 0000000000000000 ]---
--- drivers/net/ethernet/mellanox/mlx5/core/main.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ethernet/mellanox/mlx5/core/main.c +3 -0
@@ -1287,6 +1287,9 @@ static int mlx5_function_teardown(struct mlx5_core_dev *dev, bool boot)if (!err)mlx5_function_disable (dev, boot); +else +mlx5_stop_health_poll (dev, boot); +return err; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 41/267 net/mlx5: Fix tainted pointer delete is case of flow rules creation fail
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Mishin <[email protected]>
[ Upstream commit 229bedbf62b13af5aba6525ad10b62ad38d9ccb5 ]
In case of flow rule creation fail in mlx5_lag_create_port_sel_table(), instead of previously created rules, the tainted pointer is deleted deveral times.
Fix this bug by using correct flow rules pointers.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c +6 -2
@@ -88,9 +88,13 @@ static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev, &dest, 1);if (IS_ERR (lag_definer->rules[idx])) { err =PTR_ERR (lag_definer->rules[idx]); -while (i--) -while (j--) +do { +while (j--) { + idx = i * ldev->buckets + j;mlx5_del_flow_rules (lag_definer->rules[idx]); + } + j = ldev->buckets; + }while (i--); goto destroy_fg; } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 42/267 net/sched: taprio: always validate TCA_TAPRIO_ATTR_PRIOMAP
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit f921a58ae20852d188f70842431ce6519c4fdc36 ]
If one TCA_TAPRIO_ATTR_PRIOMAP attribute has been provided, taprio_parse_mqprio_opt() must validate it, or userspace can inject arbitrary data to the kernel, the second time taprio_change() is called.
First call (with valid attributes) sets dev->num_tc to a non zero value.
Second call (with arbitrary mqprio attributes)
returns early from taprio_parse_mqprio_opt()
and bad things can happen.
--- net/sched/sch_taprio.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-)
net/sched/sch_taprio.c +6 -9
@@ -1186,16 +1186,13 @@ static int taprio_parse_mqprio_opt(struct net_device *dev, {bool allow_overlapping_txqs =TXTIME_ASSIST_IS_ENABLED (taprio_flags); -if (!qopt && !dev->num_tc) { -NL_SET_ERR_MSG (extack,"'mqprio' configuration is necessary" ); -return -EINVAL ; - } - -/* If num_tc is already set, it means that the user already -* configured the mqprio part -*/ -if (dev->num_tc) +if (!qopt) { +if (!dev->num_tc) { +NL_SET_ERR_MSG (extack,"'mqprio' configuration is necessary" ); +return -EINVAL ; + }return 0 ; + }/* taprio imposes that traffic classes map 1:n to tx queues */ if (qopt->num_tc > dev->num_tx_queues) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 43/267 ptp: Fix error message on failed pin verification
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karol Kolacinski <[email protected]>
[ Upstream commit 323a359f9b077f382f4483023d096a4d316fd135 ]
On failed verification of PTP clock pin, error message prints channel number instead of pin index after "pin", which is incorrect.
Fix error message by adding channel number to the message and printing pin number instead of channel number.
--- drivers/ptp/ptp_chardev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/ptp/ptp_chardev.c +2 -1
@@ -84,7 +84,8 @@ int ptp_set_pinfunc(struct ptp_clock *ptp, unsigned int pin, }if (info->verify (info, pin, func, chan)) { -pr_err ("driver cannot use function %u on pin %u\n" , func, chan); +pr_err ("driver cannot use function %u and channel %u on pin %u\n" , + func, chan, pin);return -EOPNOTSUPP ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 44/267 ice: fix iteration of TLVs in Preserved Fields Area
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jacob Keller <[email protected]>
[ Upstream commit 03e4a092be8ce3de7c1baa7ae14e68b64e3ea644 ]
The ice_get_pfa_module_tlv() function iterates over the Type-Length-Value structures in the Preserved Fields Area (PFA) of the NVM. This is used by the driver to access data such as the Part Board Assembly identifier.
The function uses simple logic to iterate over the PFA. First, the pointer to the PFA in the NVM is read. Then the total length of the PFA is read from the first word.
A pointer to the first TLV is initialized, and a simple loop iterates over each TLV. The pointer is moved forward through the NVM until it exceeds the PFA area.
The logic seems sound, but it is missing a key detail. The Preserved Fields Area length includes one additional final word. This is documented in the device data sheet as a dummy word which contains 0xFFFF. All NVMs have this extra word.
If the driver tries to scan for a TLV that is not in the PFA, it will read past the size of the PFA. It reads and interprets the last dummy word of the PFA as a TLV with type 0xFFFF. It then reads the word following the PFA as a length.
The PFA resides within the Shadow RAM portion of the NVM, which is relatively small. All of its offsets are within a 16-bit size. The PFA pointer and TLV pointer are stored by the driver as 16-bit values.
In almost all cases, the word following the PFA will be such that interpreting it as a length will result in 16-bit arithmetic overflow. Once overflowed, the new next_tlv value is now below the maximum offset of the PFA. Thus, the driver will continue to iterate the data as TLVs. In the worst case, the driver hits on a sequence of reads which loop back to reading the same offsets in an endless loop.
To fix this, we need to correct the loop iteration check to account for this extra word at the end of the PFA. This alone is sufficient to resolve the known cases of this issue in the field. However, it is plausible that an NVM could be misconfigured or have corrupt data which results in the same kind of overflow. Protect against this by using check_add_overflow when calculating both the maximum offset of the TLVs, and when calculating the next_tlv offset at the end of each loop iteration. This ensures that the driver will not get stuck in an infinite loop when scanning the PFA.
--- drivers/net/ethernet/intel/ice/ice_nvm.c | 28 ++++++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-)
drivers/net/ethernet/intel/ice/ice_nvm.c +21 -7
@@ -441,8 +441,7 @@ int ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len, u16 module_type) { - u16 pfa_len, pfa_ptr; -u16 next_tlv; + u16 pfa_len, pfa_ptr, next_tlv, max_tlv;int status; status =ice_read_sr_word (hw,ICE_SR_PFA_PTR , &pfa_ptr);
@@ -455,11 +454,23 @@ ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len,ice_debug (hw,ICE_DBG_INIT ,"Failed to read PFA length.\n" );return status; } + +/* The Preserved Fields Area contains a sequence of Type-Length-Value +* structures which define its contents. The PFA length includes all +* of the TLVs, plus the initial length word itself, *and* one final +* word at the end after all of the TLVs. +*/ +if (check_add_overflow (pfa_ptr, pfa_len -1 , &max_tlv)) { +dev_warn (ice_hw_to_dev (hw),"PFA starts at offset %u. PFA length of %u caused 16-bit arithmetic overflow.\n" , + pfa_ptr, pfa_len); +return -EINVAL ; + } +/* Starting with first TLV after PFA length, iterate through the list * of TLVs to find the requested one. */ next_tlv = pfa_ptr +1 ; -while (next_tlv < pfa_ptr + pfa_len) { +while (next_tlv < max_tlv) {u16 tlv_sub_module_type;u16 tlv_len;
@@ -483,10 +494,13 @@ ice_get_pfa_module_tlv(struct ice_hw *hw, u16 *module_tlv, u16 *module_tlv_len, }return -EINVAL ; } -/* Check next TLV, i.e. current TLV pointer + length + 2 words -* (for current TLV's type and length) -*/ - next_tlv = next_tlv + tlv_len +2 ; + +if (check_add_overflow (next_tlv,2 , &next_tlv) || +check_add_overflow (next_tlv, tlv_len, &next_tlv)) { +dev_warn (ice_hw_to_dev (hw),"TLV of type %u and length 0x%04x caused 16-bit arithmetic overflow. The PFA starts at 0x%04x and has length of 0x%04x\n" , + tlv_sub_module_type, tlv_len, pfa_ptr, pfa_len); +return -EINVAL ; + } }/* Module does not exist */ return -ENOENT ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 45/267 ice: remove af_xdp_zc_qps bitmap
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Larysa Zaremba <[email protected]>
[ Upstream commit adbf5a42341f6ea038d3626cd4437d9f0ad0b2dd ]
Referenced commit has introduced a bitmap to distinguish between ZC and copy-mode AF_XDP queues, because xsk_get_pool_from_qid() does not do this for us.
The bitmap would be especially useful when restoring previous state after rebuild, if only it was not reallocated in the process. This leads to e.g. xdpsock dying after changing number of queues.
Instead of preserving the bitmap during the rebuild, remove it completely and distinguish between ZC and copy-mode queues based on the presence of a device associated with the pool.
--- drivers/net/ethernet/intel/ice/ice.h | 32 ++++++++++++++++-------- drivers/net/ethernet/intel/ice/ice_lib.c | 8 ------ drivers/net/ethernet/intel/ice/ice_xsk.c | 13 +++++----- 3 files changed, 27 insertions(+), 26 deletions(-)
drivers/net/ethernet/intel/ice/ice.h +21 -11
@@ -407,7 +407,6 @@ struct ice_vsi {struct ice_tc_cfg tc_cfg;struct bpf_prog *xdp_prog;struct ice_tx_ring **xdp_rings;/* XDP ring array */ -unsigned long *af_xdp_zc_qps;/* tracks AF_XDP ZC enabled qps */ u16 num_xdp_txq;/* Used XDP queues */ u8 xdp_mapping_mode;/* ICE_MAP_MODE_[CONTIG|SCATTER] */
@@ -714,6 +713,25 @@ static inline void ice_set_ring_xdp(struct ice_tx_ring *ring) ring->flags |=ICE_TX_FLAGS_RING_XDP ; } +/** +* ice_get_xp_from_qid - get ZC XSK buffer pool bound to a queue ID +* @vsi: pointer to VSI +* @qid: index of a queue to look at XSK buff pool presence +* +* Return: A pointer to xsk_buff_pool structure if there is a buffer pool +* attached and configured as zero-copy, NULL otherwise. +*/ +static inline struct xsk_buff_pool *ice_get_xp_from_qid (struct ice_vsi *vsi, +u16 qid) +{ +struct xsk_buff_pool *pool =xsk_get_pool_from_qid (vsi->netdev, qid); + +if (!ice_is_xdp_ena_vsi (vsi)) +return NULL ; + +return (pool && pool->dev) ? pool :NULL ; +} +/** * ice_xsk_pool - get XSK buffer pool bound to a ring * @ring: Rx ring to use
@@ -726,10 +744,7 @@ static inline struct xsk_buff_pool *ice_xsk_pool(struct ice_rx_ring *ring)struct ice_vsi *vsi = ring->vsi;u16 qid = ring->q_index; -if (!ice_is_xdp_ena_vsi (vsi) || !test_bit (qid, vsi->af_xdp_zc_qps)) -return NULL ; - -return xsk_get_pool_from_qid (vsi->netdev, qid); +return ice_get_xp_from_qid (vsi, qid); }/**
@@ -754,12 +769,7 @@ static inline void ice_tx_xsk_pool(struct ice_vsi *vsi, u16 qid)if (!ring)return ; -if (!ice_is_xdp_ena_vsi (vsi) || !test_bit (qid, vsi->af_xdp_zc_qps)) { - ring->xsk_pool =NULL ; -return ; - } - - ring->xsk_pool =xsk_get_pool_from_qid (vsi->netdev, qid); + ring->xsk_pool =ice_get_xp_from_qid (vsi, qid); }/**
drivers/net/ethernet/intel/ice/ice_lib.c +0 -8
@@ -117,14 +117,8 @@ static int ice_vsi_alloc_arrays(struct ice_vsi *vsi)if (!vsi->q_vectors) goto err_vectors; - vsi->af_xdp_zc_qps =bitmap_zalloc (max_t (int, vsi->alloc_txq, vsi->alloc_rxq),GFP_KERNEL ); -if (!vsi->af_xdp_zc_qps) - goto err_zc_qps; -return 0 ; -err_zc_qps: -devm_kfree (dev, vsi->q_vectors); err_vectors:devm_kfree (dev, vsi->rxq_map); err_rxq_map:
@@ -321,8 +315,6 @@ static void ice_vsi_free_arrays(struct ice_vsi *vsi) dev =ice_pf_to_dev (pf); -bitmap_free (vsi->af_xdp_zc_qps); - vsi->af_xdp_zc_qps =NULL ;/* free the ring and vector containers */ devm_kfree (dev, vsi->q_vectors); vsi->q_vectors =NULL ;
drivers/net/ethernet/intel/ice/ice_xsk.c +6 -7
@@ -289,7 +289,6 @@ static int ice_xsk_pool_disable(struct ice_vsi *vsi, u16 qid)if (!pool)return -EINVAL ; -clear_bit (qid, vsi->af_xdp_zc_qps);xsk_pool_dma_unmap (pool,ICE_RX_DMA_ATTR );return 0 ;
@@ -320,8 +319,6 @@ ice_xsk_pool_enable(struct ice_vsi *vsi, struct xsk_buff_pool *pool, u16 qid)if (err)return err; -set_bit (qid, vsi->af_xdp_zc_qps); -return 0 ; }
@@ -369,11 +366,13 @@ ice_realloc_rx_xdp_bufs(struct ice_rx_ring *rx_ring, bool pool_present)int ice_realloc_zc_buf (struct ice_vsi *vsi,bool zc) {struct ice_rx_ring *rx_ring; -unsigned long q; +uint i; + +ice_for_each_rxq (vsi, i) { + rx_ring = vsi->rx_rings[i]; +if (!rx_ring->xsk_pool) +continue ; -for_each_set_bit (q, vsi->af_xdp_zc_qps, -max_t (int, vsi->alloc_txq, vsi->alloc_rxq)) { - rx_ring = vsi->rx_rings[q];if (ice_realloc_rx_xdp_bufs (rx_ring, zc))return -ENOMEM ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 46/267 ice: add flag to distinguish reset from .ndo_bpf in XDP rings config
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Larysa Zaremba <[email protected]>
[ Upstream commit 744d197162c2070a6045a71e2666ed93a57cc65d ]
Commit 6624e780a577 ("ice: split ice_vsi_setup into smaller functions") has placed ice_vsi_free_q_vectors() after ice_destroy_xdp_rings() in the rebuild process. The behaviour of the XDP rings config functions is context-dependent, so the change of order has led to ice_destroy_xdp_rings() doing additional work and removing XDP prog, when it was supposed to be preserved.
Also, dependency on the PF state reset flags creates an additional, fortunately less common problem:
* PFR is requested e.g. by tx_timeout handler
* .ndo_bpf() is asked to delete the program, calls ice_destroy_xdp_rings(), but reset flag is set, so rings are destroyed without deleting the program
* ice_vsi_rebuild tries to delete non-existent XDP rings, because the program is still on the VSI
* system crashes
With a similar race, when requested to attach a program, ice_prepare_xdp_rings() can actually skip setting the program in the VSI and nevertheless report success.
Instead of reverting to the old order of function calls, add an enum argument to both ice_prepare_xdp_rings() and ice_destroy_xdp_rings() in order to distinguish between calls from rebuild and .ndo_bpf().
--- drivers/net/ethernet/intel/ice/ice.h | 11 +++++++++-- drivers/net/ethernet/intel/ice/ice_lib.c | 5 +++-- drivers/net/ethernet/intel/ice/ice_main.c | 22 ++++++++++++---------- 3 files changed, 24 insertions(+), 14 deletions(-)
drivers/net/ethernet/intel/ice/ice.h +9 -2
@@ -892,9 +892,16 @@ int ice_down(struct ice_vsi *vsi);int ice_down_up (struct ice_vsi *vsi);int ice_vsi_cfg_lan (struct ice_vsi *vsi);struct ice_vsi *ice_lb_vsi_setup (struct ice_pf *pf,struct ice_port_info *pi); + +enum ice_xdp_cfg { +ICE_XDP_CFG_FULL ,/* Fully apply new config in .ndo_bpf() */ +ICE_XDP_CFG_PART ,/* Save/use part of config in VSI rebuild */ +}; +int ice_vsi_determine_xdp_res (struct ice_vsi *vsi); -int ice_prepare_xdp_rings (struct ice_vsi *vsi,struct bpf_prog *prog); -int ice_destroy_xdp_rings (struct ice_vsi *vsi); +int ice_prepare_xdp_rings (struct ice_vsi *vsi,struct bpf_prog *prog, +enum ice_xdp_cfg cfg_type); +int ice_destroy_xdp_rings (struct ice_vsi *vsi,enum ice_xdp_cfg cfg_type);int ice_xdp_xmit (struct net_device *dev,int n,struct xdp_frame **frames,u32 flags);
drivers/net/ethernet/intel/ice/ice_lib.c +3 -2
@@ -2462,7 +2462,8 @@ ice_vsi_cfg_def(struct ice_vsi *vsi, struct ice_vsi_cfg_params *params) ret =ice_vsi_determine_xdp_res (vsi);if (ret) goto unroll_vector_base; - ret =ice_prepare_xdp_rings (vsi, vsi->xdp_prog); + ret =ice_prepare_xdp_rings (vsi, vsi->xdp_prog, +ICE_XDP_CFG_PART );if (ret) goto unroll_vector_base; }
@@ -2613,7 +2614,7 @@ void ice_vsi_decfg(struct ice_vsi *vsi)/* return value check can be skipped here, it always returns * 0 if reset is in progress */ -ice_destroy_xdp_rings (vsi); +ice_destroy_xdp_rings (vsi,ICE_XDP_CFG_PART );ice_vsi_clear_rings (vsi);ice_vsi_free_q_vectors (vsi);
drivers/net/ethernet/intel/ice/ice_main.c +12 -10
@@ -2657,10 +2657,12 @@ static void ice_vsi_assign_bpf_prog(struct ice_vsi *vsi, struct bpf_prog *prog)* ice_prepare_xdp_rings - Allocate, configure and setup Tx rings for XDP * @vsi: VSI to bring up Tx rings used by XDP * @prog: bpf program that will be assigned to VSI +* @cfg_type: create from scratch or restore the existing configuration * * Return 0 on success and negative value on error */ -int ice_prepare_xdp_rings (struct ice_vsi *vsi,struct bpf_prog *prog) +int ice_prepare_xdp_rings (struct ice_vsi *vsi,struct bpf_prog *prog, +enum ice_xdp_cfg cfg_type) {u16 max_txqs[ICE_MAX_TRAFFIC_CLASS ] = {0 };int xdp_rings_rem = vsi->num_xdp_txq;
@@ -2736,7 +2738,7 @@ int ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog)* taken into account at the end of ice_vsi_rebuild, where * ice_cfg_vsi_lan is being called */ -if (ice_is_reset_in_progress (pf->state)) +if (cfg_type ==ICE_XDP_CFG_PART )return 0 ;/* tell the Tx scheduler that right now we have
@@ -2788,22 +2790,21 @@ int ice_prepare_xdp_rings(struct ice_vsi *vsi, struct bpf_prog *prog)/** * ice_destroy_xdp_rings - undo the configuration made by ice_prepare_xdp_rings * @vsi: VSI to remove XDP rings +* @cfg_type: disable XDP permanently or allow it to be restored later * * Detach XDP rings from irq vectors, clean up the PF bitmap and free * resources */ -int ice_destroy_xdp_rings (struct ice_vsi *vsi) +int ice_destroy_xdp_rings (struct ice_vsi *vsi,enum ice_xdp_cfg cfg_type) {u16 max_txqs[ICE_MAX_TRAFFIC_CLASS ] = {0 };struct ice_pf *pf = vsi->back;int i, v_idx;/* q_vectors are freed in reset path so there's no point in detaching -* rings; in case of rebuild being triggered not from reset bits -* in pf->state won't be set, so additionally check first q_vector -* against NULL +* rings */ -if (ice_is_reset_in_progress (pf->state) || !vsi->q_vectors[0 ]) +if (cfg_type ==ICE_XDP_CFG_PART ) goto free_qmap;ice_for_each_q_vector (vsi, v_idx) {
@@ -2844,7 +2845,7 @@ int ice_destroy_xdp_rings(struct ice_vsi *vsi)if (static_key_enabled (&ice_xdp_locking_key))static_branch_dec (&ice_xdp_locking_key); -if (ice_is_reset_in_progress (pf->state) || !vsi->q_vectors[0 ]) +if (cfg_type ==ICE_XDP_CFG_PART )return 0 ;ice_vsi_assign_bpf_prog (vsi,NULL );
@@ -2955,7 +2956,8 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,if (xdp_ring_err) {NL_SET_ERR_MSG_MOD (extack,"Not enough Tx resources for XDP" ); }else { - xdp_ring_err =ice_prepare_xdp_rings (vsi, prog); + xdp_ring_err =ice_prepare_xdp_rings (vsi, prog, +ICE_XDP_CFG_FULL );if (xdp_ring_err)NL_SET_ERR_MSG_MOD (extack,"Setting up XDP Tx resources failed" ); }
@@ -2966,7 +2968,7 @@ ice_xdp_setup_prog(struct ice_vsi *vsi, struct bpf_prog *prog,NL_SET_ERR_MSG_MOD (extack,"Setting up XDP Rx resources failed" ); }else if (ice_is_xdp_ena_vsi (vsi) && !prog) {xdp_features_clear_redirect_target (vsi->netdev); - xdp_ring_err =ice_destroy_xdp_rings (vsi); + xdp_ring_err =ice_destroy_xdp_rings (vsi,ICE_XDP_CFG_FULL );if (xdp_ring_err)NL_SET_ERR_MSG_MOD (extack,"Freeing XDP Tx resources failed" );/* reallocate Rx queues that were used for zero-copy */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 47/267 net: wwan: iosm: Fix tainted pointer delete is case of region creation fail
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Mishin <[email protected]>
[ Upstream commit b0c9a26435413b81799047a7be53255640432547 ]
In case of region creation fail in ipc_devlink_create_region(), previously created regions delete process starts from tainted pointer which actually holds error code value.
Fix this bug by decreasing region index before delete.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/net/wwan/iosm/iosm_ipc_devlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wwan/iosm/iosm_ipc_devlink.c +1 -1
@@ -210,7 +210,7 @@ static int ipc_devlink_create_region(struct iosm_devlink *devlink) rc =PTR_ERR (devlink->cd_regions[i]);dev_err (devlink->dev,"Devlink region fail,err %d" , rc);/* Delete previously created regions */ -for ( ; i >=0 ; i--) +for (i--; i >=0 ; i--)devlink_region_destroy (devlink->cd_regions[i]); goto region_create_fail; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 48/267 af_unix: Set sk->sk_state under unix_state_lock() for truly disconencted peer.
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 26bfb8b57063f52b867f9b6c8d1742fcb5bd656c ]
When a SOCK_DGRAM socket connect()s to another socket, the both sockets' sk->sk_state are changed to TCP_ESTABLISHED so that we can register them to BPF SOCKMAP.
When the socket disconnects from the peer by connect(AF_UNSPEC), the state is set back to TCP_CLOSE.
Then, the peer's state is also set to TCP_CLOSE, but the update is done locklessly and unconditionally.
Let's say socket A connect()ed to B, B connect()ed to C, and A disconnects from B.
After the first two connect()s, all three sockets' sk->sk_state are TCP_ESTABLISHED:
$ ss -xa Netid State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess u_dgr ESTAB 0 0 @A 641 * 642 u_dgr ESTAB 0 0 @B 642 * 643 u_dgr ESTAB 0 0 @C 643 * 0
And after the disconnect, B's state is TCP_CLOSE even though it's still connected to C and C's state is TCP_ESTABLISHED.
$ ss -xa Netid State Recv-Q Send-Q Local Address:Port Peer Address:PortProcess u_dgr UNCONN 0 0 @A 641 * 0 u_dgr UNCONN 0 0 @B 642 * 643 u_dgr ESTAB 0 0 @C 643 * 0
In this case, we cannot register B to SOCKMAP.
So, when a socket disconnects from the peer, we should not set TCP_CLOSE to the peer if the peer is connected to yet another socket, and this must be done under unix_state_lock().
Note that we use WRITE_ONCE() for sk->sk_state as there are many lockless readers. These data-races will be fixed in the following patches.
--- net/unix/af_unix.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-)
net/unix/af_unix.c +8 -2
@@ -571,7 +571,6 @@ static void unix_dgram_disconnected(struct sock *sk, struct sock *other)sk_error_report (other); } } - other->sk_state =TCP_CLOSE ; }static void unix_sock_destructor (struct sock *sk)
@@ -1434,8 +1433,15 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,unix_state_double_unlock (sk, other); -if (other != old_peer) +if (other != old_peer) {unix_dgram_disconnected (sk, old_peer); + +unix_state_lock (old_peer); +if (!unix_peer (old_peer)) +WRITE_ONCE (old_peer->sk_state,TCP_CLOSE ); +unix_state_unlock (old_peer); + } +sock_put (old_peer); }else {unix_peer (sk) = other;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 49/267 af_unix: Annodate data-races around sk->sk_state for writers.
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 942238f9735a4a4ebf8274b218d9a910158941d1 ]
sk->sk_state is changed under unix_state_lock(), but it's read locklessly in many places.
This patch adds WRITE_ONCE() on the writer side.
We will add READ_ONCE() to the lockless readers in the following patches.
--- net/unix/af_unix.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
net/unix/af_unix.c +8 -6
@@ -617,7 +617,7 @@ static void unix_release_sock(struct sock *sk, int embrion) u->path.dentry =NULL ; u->path.mnt =NULL ; state = sk->sk_state; - sk->sk_state =TCP_CLOSE ; +WRITE_ONCE (sk->sk_state,TCP_CLOSE ); skpair =unix_peer (sk);unix_peer (sk) =NULL ;
@@ -739,7 +739,8 @@ static int unix_listen(struct socket *sock, int backlog)if (backlog > sk->sk_max_ack_backlog)wake_up_interruptible_all (&u->peer_wait); sk->sk_max_ack_backlog = backlog; - sk->sk_state =TCP_LISTEN ; +WRITE_ONCE (sk->sk_state,TCP_LISTEN ); +/* set credentials so connect can copy them */ init_peercred (sk); err =0 ;
@@ -1411,7 +1412,8 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,if (err) goto out_unlock; - sk->sk_state = other->sk_state =TCP_ESTABLISHED ; +WRITE_ONCE (sk->sk_state,TCP_ESTABLISHED ); +WRITE_ONCE (other->sk_state,TCP_ESTABLISHED ); }else {/* * 1003.1g breaking connected state with AF_UNSPEC
@@ -1428,7 +1430,7 @@ static int unix_dgram_connect(struct socket *sock, struct sockaddr *addr,unix_peer (sk) = other;if (!other) - sk->sk_state =TCP_CLOSE ; +WRITE_ONCE (sk->sk_state,TCP_CLOSE );unix_dgram_peer_wake_disconnect_wakeup (sk, old_peer);unix_state_double_unlock (sk, other);
@@ -1644,7 +1646,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,copy_peercred (sk, other); sock->state =SS_CONNECTED ; - sk->sk_state =TCP_ESTABLISHED ; +WRITE_ONCE (sk->sk_state,TCP_ESTABLISHED );sock_hold (newsk);smp_mb__after_atomic ();/* sock_hold() does an atomic_inc() */
@@ -2027,7 +2029,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,unix_peer (sk) =NULL ;unix_dgram_peer_wake_disconnect_wakeup (sk, other); - sk->sk_state =TCP_CLOSE ; +WRITE_ONCE (sk->sk_state,TCP_CLOSE );unix_state_unlock (sk);unix_dgram_disconnected (sk, other);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 50/267 af_unix: Annotate data-race of sk->sk_state in unix_inq_len().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 3a0f38eb285c8c2eead4b3230c7ac2983707599d ]
ioctl(SIOCINQ) calls unix_inq_len() that checks sk->sk_state first and returns -EINVAL if it's TCP_LISTEN.
Then, for SOCK_STREAM sockets, unix_inq_len() returns the number of bytes in recvq.
However, unix_inq_len() does not hold unix_state_lock(), and the concurrent listen() might change the state after checking sk->sk_state.
If the race occurs, 0 is returned for the listener, instead of -EINVAL, because the length of skb with embryo is 0.
We could hold unix_state_lock() in unix_inq_len(), but it's overkill given the result is true for pre-listen() TCP_CLOSE state.
So, let's use READ_ONCE() for sk->sk_state in unix_inq_len().
--- net/unix/af_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/unix/af_unix.c +1 -1
@@ -2983,7 +2983,7 @@ long unix_inq_len(struct sock *sk)struct sk_buff *skb;long amount =0 ; -if (sk->sk_state ==TCP_LISTEN ) +if (READ_ONCE (sk->sk_state) ==TCP_LISTEN )return -EINVAL ;spin_lock (&sk->sk_receive_queue.lock);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 51/267 af_unix: Annotate data-races around sk->sk_state in unix_write_space() and poll().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit eb0718fb3e97ad0d6f4529b810103451c90adf94 ]
unix_poll() and unix_dgram_poll() read sk->sk_state locklessly and calls unix_writable() which also reads sk->sk_state without holding unix_state_lock().
Let's use READ_ONCE() in unix_poll() and unix_dgram_poll() and pass it to unix_writable().
While at it, we remove TCP_SYN_SENT check in unix_dgram_poll() as that state does not exist for AF_UNIX socket since the code was added.
--- net/unix/af_unix.c | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-)
net/unix/af_unix.c +12 -13
@@ -531,9 +531,9 @@ static int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other)return 0 ; } -static int unix_writable (const struct sock *sk) +static int unix_writable (const struct sock *sk,unsigned char state) { -return sk->sk_state !=TCP_LISTEN && +return state !=TCP_LISTEN && (refcount_read (&sk->sk_wmem_alloc) <<2 ) <= sk->sk_sndbuf; }
@@ -542,7 +542,7 @@ static void unix_write_space(struct sock *sk)struct socket_wq *wq;rcu_read_lock (); -if (unix_writable (sk)) { +if (unix_writable (sk,READ_ONCE (sk->sk_state))) { wq =rcu_dereference (sk->sk_wq);if (skwq_has_sleeper (wq)) wake_up_interruptible_sync_poll(&wq->wait,
@@ -3095,12 +3095,14 @@ static int unix_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned lonstatic __poll_t unix_poll (struct file *file,struct socket *sock,poll_table *wait) {struct sock *sk = sock->sk; +unsigned char state;__poll_t mask;u8 shutdown;sock_poll_wait (file, sock, wait); mask =0 ; shutdown =READ_ONCE (sk->sk_shutdown); + state =READ_ONCE (sk->sk_state);/* exceptional events? */ if (READ_ONCE (sk->sk_err))
@@ -3122,14 +3124,14 @@ static __poll_t unix_poll(struct file *file, struct socket *sock, poll_table *wa/* Connection-based need to check for termination and startup */ if ((sk->sk_type ==SOCK_STREAM || sk->sk_type ==SOCK_SEQPACKET ) && - sk->sk_state ==TCP_CLOSE ) + state ==TCP_CLOSE ) mask |=EPOLLHUP ;/* * we set writable also when the other side has shut down the * connection. This prevents stuck sockets. */ -if (unix_writable (sk)) +if (unix_writable (sk, state)) mask |=EPOLLOUT |EPOLLWRNORM |EPOLLWRBAND ;return mask;
@@ -3140,12 +3142,14 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock, {struct sock *sk = sock->sk, *other;unsigned int writable; +unsigned char state;__poll_t mask;u8 shutdown;sock_poll_wait (file, sock, wait); mask =0 ; shutdown =READ_ONCE (sk->sk_shutdown); + state =READ_ONCE (sk->sk_state);/* exceptional events? */ if (READ_ONCE(sk->sk_err) ||
@@ -3165,19 +3169,14 @@ static __poll_t unix_dgram_poll(struct file *file, struct socket *sock, mask |=EPOLLIN |EPOLLRDNORM ;/* Connection-based need to check for termination and startup */ -if (sk->sk_type ==SOCK_SEQPACKET ) { -if (sk->sk_state ==TCP_CLOSE ) - mask |=EPOLLHUP ; -/* connection hasn't started yet? */ -if (sk->sk_state ==TCP_SYN_SENT ) -return mask; - } +if (sk->sk_type ==SOCK_SEQPACKET && state ==TCP_CLOSE ) + mask |=EPOLLHUP ;/* No write status requested, avoid expensive OUT tests. */ if (!(poll_requested_events (wait) & (EPOLLWRBAND |EPOLLWRNORM |EPOLLOUT )))return mask; - writable =unix_writable (sk); + writable =unix_writable (sk, state);if (writable) {unix_state_lock (sk);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 52/267 af_unix: Annotate data-race of sk->sk_state in unix_stream_connect().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit a9bf9c7dc6a5899c01cb8f6e773a66315a5cd4b7 ]
As small optimisation, unix_stream_connect() prefetches the client's sk->sk_state without unix_state_lock() and checks if it's TCP_CLOSE.
Later, sk->sk_state is checked again under unix_state_lock().
Let's use READ_ONCE() for the first check and TCP_CLOSE directly for the second check.
--- net/unix/af_unix.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
net/unix/af_unix.c +2 -5
@@ -1491,7 +1491,6 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,struct sk_buff *skb =NULL ;long timeo;int err; -int st; err =unix_validate_addr (sunaddr, addr_len);if (err)
@@ -1577,9 +1576,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,Well, and we have to recheck the state after socket locked. */ - st = sk->sk_state; - -switch (st) { +switch (READ_ONCE (sk->sk_state)) {case TCP_CLOSE :/* This is ok... continue with connect */ break ;
@@ -1594,7 +1591,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,unix_state_lock_nested (sk,U_LOCK_SECOND ); -if (sk->sk_state != st) { +if (sk->sk_state !=TCP_CLOSE ) {unix_state_unlock (sk);unix_state_unlock (other);sock_put (other);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 53/267 af_unix: Annotate data-races around sk->sk_state in sendmsg() and recvmsg().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 8a34d4e8d9742a24f74998f45a6a98edd923319b ]
The following functions read sk->sk_state locklessly and proceed only if the state is TCP_ESTABLISHED.
* unix_stream_sendmsg
* unix_stream_read_generic
* unix_seqpacket_sendmsg
* unix_seqpacket_recvmsg
Let's use READ_ONCE() there.
--- net/unix/af_unix.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/unix/af_unix.c +4 -4
@@ -2202,7 +2202,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, }if (msg->msg_namelen) { - err = sk->sk_state ==TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP ; + err =READ_ONCE (sk->sk_state) ==TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP ; goto out_err; }else { err = -ENOTCONN ;
@@ -2316,7 +2316,7 @@ static int unix_seqpacket_sendmsg(struct socket *sock, struct msghdr *msg,if (err)return err; -if (sk->sk_state !=TCP_ESTABLISHED ) +if (READ_ONCE (sk->sk_state) !=TCP_ESTABLISHED )return -ENOTCONN ;if (msg->msg_namelen)
@@ -2330,7 +2330,7 @@ static int unix_seqpacket_recvmsg(struct socket *sock, struct msghdr *msg, {struct sock *sk = sock->sk; -if (sk->sk_state !=TCP_ESTABLISHED ) +if (READ_ONCE (sk->sk_state) !=TCP_ESTABLISHED )return -ENOTCONN ;return unix_dgram_recvmsg (sock, msg, size, flags);
@@ -2654,7 +2654,7 @@ static int unix_stream_read_generic(struct unix_stream_read_state *state,size_t size = state->size;unsigned int last_len; -if (unlikely (sk->sk_state !=TCP_ESTABLISHED )) { +if (unlikely (READ_ONCE (sk->sk_state) !=TCP_ESTABLISHED )) { err = -EINVAL ; goto out; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 54/267 af_unix: Annotate data-race of sk->sk_state in unix_stream_read_skb().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit af4c733b6b1aded4dc808fafece7dfe6e9d2ebb3 ]
unix_stream_read_skb() is called from sk->sk_data_ready() context where unix_state_lock() is not held.
Let's use READ_ONCE() there.
--- net/unix/af_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/unix/af_unix.c +1 -1
@@ -2630,7 +2630,7 @@ static struct sk_buff *manage_oob(struct sk_buff *skb, struct sock *sk,static int unix_stream_read_skb (struct sock *sk,skb_read_actor_t recv_actor) { -if (unlikely (sk->sk_state !=TCP_ESTABLISHED )) +if (unlikely (READ_ONCE (sk->sk_state) !=TCP_ESTABLISHED ))return -ENOTCONN ;return unix_read_skb (sk, recv_actor);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 55/267 af_unix: Annotate data-races around sk->sk_state in UNIX_DIAG.
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 0aa3be7b3e1f8f997312cc4705f8165e02806f8f ]
While dumping AF_UNIX sockets via UNIX_DIAG, sk->sk_state is read locklessly.
Let's use READ_ONCE() there.
Note that the result could be inconsistent if the socket is dumped during the state change. This is common for other SOCK_DIAG and similar interfaces.
--- net/unix/diag.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/unix/diag.c +4 -4
@@ -65,7 +65,7 @@ static int sk_diag_dump_icons(struct sock *sk, struct sk_buff *nlskb)u32 *buf;int i; -if (sk->sk_state ==TCP_LISTEN ) { +if (READ_ONCE (sk->sk_state) ==TCP_LISTEN ) {spin_lock (&sk->sk_receive_queue.lock); attr = nla_reserve(nlskb, UNIX_DIAG_ICONS,
@@ -103,7 +103,7 @@ static int sk_diag_show_rqlen(struct sock *sk, struct sk_buff *nlskb) {struct unix_diag_rqlen rql; -if (sk->sk_state ==TCP_LISTEN ) { +if (READ_ONCE (sk->sk_state) ==TCP_LISTEN ) { rql.udiag_rqueue = sk->sk_receive_queue.qlen; rql.udiag_wqueue = sk->sk_max_ack_backlog; }else {
@@ -136,7 +136,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r rep =nlmsg_data (nlh); rep->udiag_family =AF_UNIX ; rep->udiag_type = sk->sk_type; - rep->udiag_state = sk->sk_state; + rep->udiag_state =READ_ONCE (sk->sk_state); rep->pad =0 ; rep->udiag_ino = sk_ino;sock_diag_save_cookie (sk, rep->udiag_cookie);
@@ -215,7 +215,7 @@ static int unix_diag_dump(struct sk_buff *skb, struct netlink_callback *cb)sk_for_each (sk, &net->unx.table.buckets[slot]) {if (num < s_num) goto next; -if (!(req->udiag_states & (1 << sk->sk_state))) +if (!(req->udiag_states & (1 <<READ_ONCE (sk->sk_state)))) goto next; if (sk_diag_dump(sk, skb, req, sk_user_ns(skb->sk), NETLINK_CB(cb->skb).portid,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 56/267 af_unix: Annotate data-races around sk->sk_sndbuf.
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit b0632e53e0da8054e36bc973f0eec69d30f1b7c6 ]
sk_setsockopt() changes sk->sk_sndbuf under lock_sock(), but it's not used in af_unix.c.
Let's use READ_ONCE() to read sk->sk_sndbuf in unix_writable(), unix_dgram_sendmsg(), and unix_stream_sendmsg().
--- net/unix/af_unix.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/unix/af_unix.c +3 -3
@@ -534,7 +534,7 @@ static int unix_dgram_peer_wake_me(struct sock *sk, struct sock *other)static int unix_writable (const struct sock *sk,unsigned char state) {return state !=TCP_LISTEN && - (refcount_read (&sk->sk_wmem_alloc) <<2 ) <= sk->sk_sndbuf; + (refcount_read (&sk->sk_wmem_alloc) <<2 ) <=READ_ONCE (sk->sk_sndbuf); }static void unix_write_space (struct sock *sk)
@@ -1944,7 +1944,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg, } err = -EMSGSIZE ; -if (len > sk->sk_sndbuf -32 ) +if (len >READ_ONCE (sk->sk_sndbuf) -32 ) goto out;if (len >SKB_MAX_ALLOC ) {
@@ -2223,7 +2223,7 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg, &err, 0); }else {/* Keep two messages in the pipe so it schedules better */ - size =min_t (int, size, (sk->sk_sndbuf >>1 ) -64 ); + size =min_t (int, size, (READ_ONCE (sk->sk_sndbuf) >>1 ) -64 );/* allow fallback to order-0 allocations */ size =min_t (int, size,SKB_MAX_HEAD (0 ) +UNIX_SKB_FRAGS_SZ );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 57/267 af_unix: Annotate data-race of net->unx.sysctl_max_dgram_qlen.
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit bd9f2d05731f6a112d0c7391a0d537bfc588dbe6 ]
net->unx.sysctl_max_dgram_qlen is exposed as a sysctl knob and can be changed concurrently.
Let's use READ_ONCE() in unix_create1().
--- net/unix/af_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/unix/af_unix.c +1 -1
@@ -990,7 +990,7 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern, sk->sk_hash =unix_unbound_hash (sk); sk->sk_allocation =GFP_KERNEL_ACCOUNT ; sk->sk_write_space = unix_write_space; - sk->sk_max_ack_backlog = net->unx.sysctl_max_dgram_qlen; + sk->sk_max_ack_backlog =READ_ONCE (net->unx.sysctl_max_dgram_qlen); sk->sk_destruct = unix_sock_destructor; u =unix_sk (sk); u->inflight =0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 58/267 af_unix: Use unix_recvq_full_lockless() in unix_stream_connect().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 45d872f0e65593176d880ec148f41ad7c02e40a7 ]
Once sk->sk_state is changed to TCP_LISTEN, it never changes.
unix_accept() takes advantage of this characteristics; it does not hold the listener's unix_state_lock() and only acquires recvq lock to pop one skb.
It means unix_state_lock() does not prevent the queue length from changing in unix_stream_connect().
Thus, we need to use unix_recvq_full_lockless() to avoid data-race.
Now we remove unix_recvq_full() as no one uses it.
Note that we can remove READ_ONCE() for sk->sk_max_ack_backlog in unix_recvq_full_lockless() because of the following reasons:
(1) For SOCK_DGRAM, it is a written-once field in unix_create1()
(2) For SOCK_STREAM and SOCK_SEQPACKET, it is changed under the listener's unix_state_lock() in unix_listen(), and we hold the lock in unix_stream_connect()
--- net/unix/af_unix.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-)
net/unix/af_unix.c +2 -8
@@ -222,15 +222,9 @@ static inline int unix_may_send(struct sock *sk, struct sock *osk)return unix_peer (osk) ==NULL ||unix_our_peer (sk, osk); } -static inline int unix_recvq_full (const struct sock *sk) -{ -return skb_queue_len (&sk->sk_receive_queue) > sk->sk_max_ack_backlog; -} -static inline int unix_recvq_full_lockless (const struct sock *sk) { -return skb_queue_len_lockless (&sk->sk_receive_queue) > -READ_ONCE (sk->sk_max_ack_backlog); +return skb_queue_len_lockless (&sk->sk_receive_queue) > sk->sk_max_ack_backlog; }struct sock *unix_peer_get (struct sock *s)
@@ -1551,7 +1545,7 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,if (other->sk_shutdown &RCV_SHUTDOWN ) goto out_unlock; -if (unix_recvq_full (other)) { +if (unix_recvq_full_lockless (other)) { err = -EAGAIN ;if (!timeo) goto out_unlock;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 59/267 af_unix: Use skb_queue_empty_lockless() in unix_release_sock().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 83690b82d228b3570565ebd0b41873933238b97f ]
If the socket type is SOCK_STREAM or SOCK_SEQPACKET, unix_release_sock() checks the length of the peer socket's recvq under unix_state_lock().
However, unix_stream_read_generic() calls skb_unlink() after releasing the lock. Also, for SOCK_SEQPACKET, __skb_try_recv_datagram() unlinks skb without unix_state_lock().
Thues, unix_state_lock() does not protect qlen.
Let's use skb_queue_empty_lockless() in unix_release_sock().
--- net/unix/af_unix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/unix/af_unix.c +1 -1
@@ -632,7 +632,7 @@ static void unix_release_sock(struct sock *sk, int embrion)unix_state_lock (skpair);/* No more writes */ WRITE_ONCE (skpair->sk_shutdown,SHUTDOWN_MASK ); -if (!skb_queue_empty (&sk->sk_receive_queue) || embrion) +if (!skb_queue_empty_lockless (&sk->sk_receive_queue) || embrion)WRITE_ONCE (skpair->sk_err,ECONNRESET );unix_state_unlock (skpair); skpair->sk_state_change (skpair);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 60/267 af_unix: Use skb_queue_len_lockless() in sk_diag_show_rqlen().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 5d915e584d8408211d4567c22685aae8820bfc55 ]
We can dump the socket queue length via UNIX_DIAG by specifying UDIAG_SHOW_RQLEN.
If sk->sk_state is TCP_LISTEN, we return the recv queue length, but here we do not hold recvq lock.
Let's use skb_queue_len_lockless() in sk_diag_show_rqlen().
--- net/unix/diag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/unix/diag.c +1 -1
@@ -104,7 +104,7 @@ static int sk_diag_show_rqlen(struct sock *sk, struct sk_buff *nlskb)struct unix_diag_rqlen rql;if (READ_ONCE (sk->sk_state) ==TCP_LISTEN ) { - rql.udiag_rqueue = sk->sk_receive_queue.qlen; + rql.udiag_rqueue =skb_queue_len_lockless (&sk->sk_receive_queue); rql.udiag_wqueue = sk->sk_max_ack_backlog; }else { rql.udiag_rqueue = (u32 )unix_inq_len (sk);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 61/267 af_unix: Annotate data-race of sk->sk_shutdown in sk_diag_fill().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit efaf24e30ec39ebbea9112227485805a48b0ceb1 ]
While dumping sockets via UNIX_DIAG, we do not hold unix_state_lock().
Let's use READ_ONCE() to read sk->sk_shutdown.
--- net/unix/diag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/unix/diag.c +1 -1
@@ -165,7 +165,7 @@ static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct unix_diag_r sock_diag_put_meminfo(sk, skb, UNIX_DIAG_MEMINFO)) goto out_nlmsg_trim; -if (nla_put_u8 (skb,UNIX_DIAG_SHUTDOWN , sk->sk_shutdown)) +if (nla_put_u8 (skb,UNIX_DIAG_SHUTDOWN ,READ_ONCE (sk->sk_shutdown))) goto out_nlmsg_trim; if ((req->udiag_show & UDIAG_SHOW_UID) &&
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 62/267 ipv6: fix possible race in __fib6_drop_pcpu_from()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit b01e1c030770ff3b4fe37fc7cc6bca03f594133f ]
syzbot found a race in __fib6_drop_pcpu_from() [1]
If compiler reads more than once (*ppcpu_rt), second read could read NULL, if another cpu clears the value in rt6_get_pcpu_route().
Add a READ_ONCE() to prevent this race.
Also add rcu_read_lock()/rcu_read_unlock() because we rely on RCU protection while dereferencing pcpu_rt.
[1]
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000012: 0000 [#1] PREEMPT SMP KASAN PTI KASAN: null-ptr-deref in range [0x0000000000000090-0x0000000000000097] CPU: 0 PID: 7543 Comm: kworker/u8:17 Not tainted 6.10.0-rc1-syzkaller-00013-g2bfcfd584ff5 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/02/2024 Workqueue: netns cleanup_net RIP: 0010:__fib6_drop_pcpu_from.part.0+0x10a/0x370 net/ipv6/ip6_fib.c:984 Code: f8 48 c1 e8 03 80 3c 28 00 0f 85 16 02 00 00 4d 8b 3f 4d 85 ff 74 31 e8 74 a7 fa f7 49 8d bf 90 00 00 00 48 89 f8 48 c1 e8 03 <80> 3c 28 00 0f 85 1e 02 00 00 49 8b 87 90 00 00 00 48 8b 0c 24 48 RSP: 0018:ffffc900040df070 EFLAGS: 00010206 RAX: 0000000000000012 RBX: 0000000000000001 RCX: ffffffff89932e16 RDX: ffff888049dd1e00 RSI: ffffffff89932d7c RDI: 0000000000000091 RBP: dffffc0000000000 R08: 0000000000000005 R09: 0000000000000007 R10: 0000000000000001 R11: 0000000000000006 R12: ffff88807fa080b8 R13: fffffbfff1a9a07d R14: ffffed100ff41022 R15: 0000000000000001 FS: 0000000000000000(0000) GS:ffff8880b9200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000001b32c26000 CR3: 000000005d56e000 CR4: 00000000003526f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> __fib6_drop_pcpu_from net/ipv6/ip6_fib.c:966 [inline] fib6_drop_pcpu_from net/ipv6/ip6_fib.c:1027 [inline] fib6_purge_rt+0x7f2/0x9f0 net/ipv6/ip6_fib.c:1038 fib6_del_route net/ipv6/ip6_fib.c:1998 [inline] fib6_del+0xa70/0x17b0 net/ipv6/ip6_fib.c:2043 fib6_clean_node+0x426/0x5b0 net/ipv6/ip6_fib.c:2205 fib6_walk_continue+0x44f/0x8d0 net/ipv6/ip6_fib.c:2127 fib6_walk+0x182/0x370 net/ipv6/ip6_fib.c:2175 fib6_clean_tree+0xd7/0x120 net/ipv6/ip6_fib.c:2255 __fib6_clean_all+0x100/0x2d0 net/ipv6/ip6_fib.c:2271 rt6_sync_down_dev net/ipv6/route.c:4906 [inline] rt6_disable_ip+0x7ed/0xa00 net/ipv6/route.c:4911 addrconf_ifdown.isra.0+0x117/0x1b40 net/ipv6/addrconf.c:3855 addrconf_notify+0x223/0x19e0 net/ipv6/addrconf.c:3778 notifier_call_chain+0xb9/0x410 kernel/notifier.c:93 call_netdevice_notifiers_info+0xbe/0x140 net/core/dev.c:1992 call_netdevice_notifiers_extack net/core/dev.c:2030 [inline] call_netdevice_notifiers net/core/dev.c:2044 [inline] dev_close_many+0x333/0x6a0 net/core/dev.c:1585 unregister_netdevice_many_notify+0x46d/0x19f0 net/core/dev.c:11193 unregister_netdevice_many net/core/dev.c:11276 [inline] default_device_exit_batch+0x85b/0xae0 net/core/dev.c:11759 ops_exit_list+0x128/0x180 net/core/net_namespace.c:178 cleanup_net+0x5b7/0xbf0 net/core/net_namespace.c:640 process_one_work+0x9fb/0x1b60 kernel/workqueue.c:3231 process_scheduled_works kernel/workqueue.c:3312 [inline] worker_thread+0x6c8/0xf70 kernel/workqueue.c:3393 kthread+0x2c1/0x3a0 kernel/kthread.c:389 ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:147 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
--- net/ipv6/ip6_fib.c | 6 +++++- net/ipv6/route.c | 1 + 2 files changed, 6 insertions(+), 1 deletion(-)
net/ipv6/ip6_fib.c +5 -1
@@ -961,6 +961,7 @@ static void __fib6_drop_pcpu_from(struct fib6_nh *fib6_nh,if (!fib6_nh->rt6i_pcpu)return ; +rcu_read_lock ();/* release the reference to this fib entry from * all of its cached pcpu routes */
@@ -969,7 +970,9 @@ static void __fib6_drop_pcpu_from(struct fib6_nh *fib6_nh,struct rt6_info *pcpu_rt; ppcpu_rt =per_cpu_ptr (fib6_nh->rt6i_pcpu, cpu); - pcpu_rt = *ppcpu_rt; + +/* Paired with xchg() in rt6_get_pcpu_route() */ + pcpu_rt =READ_ONCE (*ppcpu_rt);/* only dropping the 'from' reference if the cached route * is using 'match'. The cached pcpu_rt->from only changes
@@ -983,6 +986,7 @@ static void __fib6_drop_pcpu_from(struct fib6_nh *fib6_nh,fib6_info_release (from); } } +rcu_read_unlock (); }struct fib6_nh_pcpu_arg {
net/ipv6/route.c +1 -0
@@ -1399,6 +1399,7 @@ static struct rt6_info *rt6_get_pcpu_route(const struct fib6_result *res)struct rt6_info *prev, **p; p =this_cpu_ptr (res->nh->rt6i_pcpu); +/* Paired with READ_ONCE() in __fib6_drop_pcpu_from() */ prev =xchg (p,NULL );if (prev) {dst_dev_put (&prev->dst);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 63/267 net: ethtool: fix the error condition in ethtool_get_phy_stats_ethtool()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Su Hui <[email protected]>
[ Upstream commit 0dcc53abf58d572d34c5313de85f607cd33fc691 ]
Clang static checker (scan-build) warning:
net/ethtool/ioctl.c:line 2233, column 2 Called function pointer is null (null dereference).
Return '-EOPNOTSUPP' when 'ops->get_ethtool_phy_stats' is NULL to fix this typo error.
--- net/ethtool/ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ethtool/ioctl.c +1 -1
@@ -2134,7 +2134,7 @@ static int ethtool_get_phy_stats_ethtool(struct net_device *dev,const struct ethtool_ops *ops = dev->ethtool_ops;int n_stats, ret; -if (!ops || !ops->get_sset_count || ops->get_ethtool_phy_stats) +if (!ops || !ops->get_sset_count || !ops->get_ethtool_phy_stats)return -EOPNOTSUPP ; n_stats = ops->get_sset_count (dev,ETH_SS_PHY_STATS );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 64/267 ksmbd: use rwsem instead of rwlock for lease break
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit d1c189c6cb8b0fb7b5ee549237d27889c40c2f8b ]
lease break wait for lease break acknowledgment.
rwsem is more suitable than unlock while traversing the list for parent lease break in ->m_op_list.
--- fs/smb/server/oplock.c | 30 +++++++++++------------------- fs/smb/server/smb2pdu.c | 4 ++-- fs/smb/server/smb_common.c | 4 ++-- fs/smb/server/vfs_cache.c | 28 ++++++++++++++-------------- fs/smb/server/vfs_cache.h | 2 +- 5 files changed, 30 insertions(+), 38 deletions(-)
fs/smb/server/oplock.c +11 -19
@@ -207,9 +207,9 @@ static void opinfo_add(struct oplock_info *opinfo) {struct ksmbd_inode *ci = opinfo->o_fp->f_ci; -write_lock (&ci->m_lock); +down_write (&ci->m_lock);list_add_rcu (&opinfo->op_entry, &ci->m_op_list); -write_unlock (&ci->m_lock); +up_write (&ci->m_lock); }static void opinfo_del (struct oplock_info *opinfo)
@@ -221,9 +221,9 @@ static void opinfo_del(struct oplock_info *opinfo)lease_del_list (opinfo);write_unlock (&lease_list_lock); } -write_lock (&ci->m_lock); +down_write (&ci->m_lock);list_del_rcu (&opinfo->op_entry); -write_unlock (&ci->m_lock); +up_write (&ci->m_lock); }static unsigned long opinfo_count (struct ksmbd_file *fp)
@@ -526,21 +526,18 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,* Compare lease key and client_guid to know request from same owner * of same client */ -read_lock (&ci->m_lock); +down_read (&ci->m_lock);list_for_each_entry (opinfo, &ci->m_op_list, op_entry) {if (!opinfo->is_lease || !opinfo->conn)continue ; -read_unlock (&ci->m_lock); lease = opinfo->o_lease; ret =compare_guid_key (opinfo, client_guid, lctx->lease_key);if (ret) { m_opinfo = opinfo;/* skip upgrading lease about breaking lease */ -if (atomic_read (&opinfo->breaking_cnt)) { -read_lock (&ci->m_lock); +if (atomic_read (&opinfo->breaking_cnt))continue ; - }/* upgrading lease */ if ((atomic_read(&ci->op_count) +
@@ -570,9 +567,8 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci,lease_none_upgrade (opinfo, lctx->req_state); } } -read_lock (&ci->m_lock); } -read_unlock (&ci->m_lock); +up_read (&ci->m_lock);return m_opinfo; }
@@ -1119,7 +1115,7 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,if (!p_ci)return ; -read_lock (&p_ci->m_lock); +down_read (&p_ci->m_lock);list_for_each_entry (opinfo, &p_ci->m_op_list, op_entry) {if (opinfo->conn ==NULL || !opinfo->is_lease)continue ;
@@ -1137,13 +1133,11 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,continue ; } -read_unlock (&p_ci->m_lock);oplock_break (opinfo,SMB2_OPLOCK_LEVEL_NONE );opinfo_conn_put (opinfo); -read_lock (&p_ci->m_lock); } } -read_unlock (&p_ci->m_lock); +up_read (&p_ci->m_lock);ksmbd_inode_put (p_ci); }
@@ -1164,7 +1158,7 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)if (!p_ci)return ; -read_lock (&p_ci->m_lock); +down_read (&p_ci->m_lock);list_for_each_entry (opinfo, &p_ci->m_op_list, op_entry) {if (opinfo->conn ==NULL || !opinfo->is_lease)continue ;
@@ -1178,13 +1172,11 @@ void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp)atomic_dec (&opinfo->conn->r_count);continue ; } -read_unlock (&p_ci->m_lock);oplock_break (opinfo,SMB2_OPLOCK_LEVEL_NONE );opinfo_conn_put (opinfo); -read_lock (&p_ci->m_lock); } } -read_unlock (&p_ci->m_lock); +up_read (&p_ci->m_lock);ksmbd_inode_put (p_ci); }
fs/smb/server/smb2pdu.c +2 -2
@@ -3376,9 +3376,9 @@ int smb2_open(struct ksmbd_work *work)* after daccess, saccess, attrib_only, and stream are * initialized. */ -write_lock (&fp->f_ci->m_lock); +down_write (&fp->f_ci->m_lock);list_add (&fp->node, &fp->f_ci->m_fp_list); -write_unlock (&fp->f_ci->m_lock); +up_write (&fp->f_ci->m_lock);/* Check delete pending among previous fp before oplock break */ if (ksmbd_inode_pending_delete (fp)) {
fs/smb/server/smb_common.c +2 -2
@@ -646,7 +646,7 @@ int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp)* Lookup fp in master fp list, and check desired access and * shared mode between previous open and current open. */ -read_lock (&curr_fp->f_ci->m_lock); +down_read (&curr_fp->f_ci->m_lock);list_for_each_entry (prev_fp, &curr_fp->f_ci->m_fp_list, node) {if (file_inode (filp) !=file_inode (prev_fp->filp))continue ;
@@ -722,7 +722,7 @@ int ksmbd_smb_check_shared_mode(struct file *filp, struct ksmbd_file *curr_fp)break ; } } -read_unlock (&curr_fp->f_ci->m_lock); +up_read (&curr_fp->f_ci->m_lock);return rc; }
fs/smb/server/vfs_cache.c +14 -14
@@ -165,7 +165,7 @@ static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp) ci->m_fattr =0 ;INIT_LIST_HEAD (&ci->m_fp_list);INIT_LIST_HEAD (&ci->m_op_list); -rwlock_init (&ci->m_lock); +init_rwsem (&ci->m_lock); ci->m_de = fp->filp->f_path.dentry;return 0 ; }
@@ -261,14 +261,14 @@ static void __ksmbd_inode_close(struct ksmbd_file *fp) }if (atomic_dec_and_test (&ci->m_count)) { -write_lock (&ci->m_lock); +down_write (&ci->m_lock);if (ci->m_flags & (S_DEL_ON_CLS |S_DEL_PENDING )) { ci->m_flags &= ~(S_DEL_ON_CLS |S_DEL_PENDING ); -write_unlock (&ci->m_lock); +up_write (&ci->m_lock);ksmbd_vfs_unlink (filp); -write_lock (&ci->m_lock); +down_write (&ci->m_lock); } -write_unlock (&ci->m_lock); +up_write (&ci->m_lock);ksmbd_inode_free (ci); }
@@ -289,9 +289,9 @@ static void __ksmbd_remove_fd(struct ksmbd_file_table *ft, struct ksmbd_file *fpif (!has_file_id (fp->volatile_id))return ; -write_lock (&fp->f_ci->m_lock); +down_write (&fp->f_ci->m_lock);list_del_init (&fp->node); -write_unlock (&fp->f_ci->m_lock); +up_write (&fp->f_ci->m_lock);write_lock (&ft->lock);idr_remove (ft->idr, fp->volatile_id);
@@ -523,17 +523,17 @@ struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry)if (!ci)return NULL ; -read_lock (&ci->m_lock); +down_read (&ci->m_lock);list_for_each_entry (lfp, &ci->m_fp_list, node) {if (inode ==file_inode (lfp->filp)) {atomic_dec (&ci->m_count); lfp =ksmbd_fp_get (lfp); -read_unlock (&ci->m_lock); +up_read (&ci->m_lock);return lfp; } }atomic_dec (&ci->m_count); -read_unlock (&ci->m_lock); +up_read (&ci->m_lock);return NULL ; }
@@ -705,13 +705,13 @@ static bool session_fd_check(struct ksmbd_tree_connect *tcon, conn = fp->conn; ci = fp->f_ci; -write_lock (&ci->m_lock); +down_write (&ci->m_lock);list_for_each_entry_rcu (op, &ci->m_op_list, op_entry) {if (op->conn != conn)continue ; op->conn =NULL ; } -write_unlock (&ci->m_lock); +up_write (&ci->m_lock); fp->conn =NULL ; fp->tcon =NULL ;
@@ -801,13 +801,13 @@ int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp) fp->tcon = work->tcon; ci = fp->f_ci; -write_lock (&ci->m_lock); +down_write (&ci->m_lock);list_for_each_entry_rcu (op, &ci->m_op_list, op_entry) {if (op->conn)continue ; op->conn = fp->conn; } -write_unlock (&ci->m_lock); +up_write (&ci->m_lock);__open_id (&work->sess->file_table, fp,OPEN_ID_TYPE_VOLATILE_ID );if (!has_file_id (fp->volatile_id)) {
fs/smb/server/vfs_cache.h +1 -1
@@ -47,7 +47,7 @@ struct stream { };struct ksmbd_inode { -rwlock_t m_lock; +struct rw_semaphore m_lock;atomic_t m_count;atomic_t op_count;/* opinfo count for streams */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 65/267 firmware: qcom_scm: disable clocks if qcom_scm_bw_enable() fails
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gabor Juhos <[email protected]>
[ Upstream commit 0c50b7fcf2773b4853e83fc15aba1a196ba95966 ]
There are several functions which are calling qcom_scm_bw_enable() then returns immediately if the call fails and leaves the clocks enabled.
Change the code of these functions to disable clocks when the qcom_scm_bw_enable() call fails. This also fixes a possible dma buffer leak in the qcom_scm_pas_init_image() function.
Compile tested only due to lack of hardware with interconnect support.
--- drivers/firmware/qcom_scm.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-)
drivers/firmware/qcom_scm.c +12 -6
@@ -498,13 +498,14 @@ int qcom_scm_pas_init_image(u32 peripheral, const void *metadata, size_t size, ret =qcom_scm_bw_enable ();if (ret) -return ret; + goto disable_clk; desc.args[1 ] = mdata_phys; ret =qcom_scm_call (__scm->dev, &desc, &res); -qcom_scm_bw_disable (); + +disable_clk:qcom_scm_clk_disable (); out:
@@ -566,10 +567,12 @@ int qcom_scm_pas_mem_setup(u32 peripheral, phys_addr_t addr, phys_addr_t size) ret =qcom_scm_bw_enable ();if (ret) -return ret; + goto disable_clk; ret =qcom_scm_call (__scm->dev, &desc, &res);qcom_scm_bw_disable (); + +disable_clk:qcom_scm_clk_disable ();return ret ? : res.result[0 ];
@@ -601,10 +604,12 @@ int qcom_scm_pas_auth_and_reset(u32 peripheral) ret =qcom_scm_bw_enable ();if (ret) -return ret; + goto disable_clk; ret =qcom_scm_call (__scm->dev, &desc, &res);qcom_scm_bw_disable (); + +disable_clk:qcom_scm_clk_disable ();return ret ? : res.result[0 ];
@@ -635,11 +640,12 @@ int qcom_scm_pas_shutdown(u32 peripheral) ret =qcom_scm_bw_enable ();if (ret) -return ret; + goto disable_clk; ret =qcom_scm_call (__scm->dev, &desc, &res); -qcom_scm_bw_disable (); + +disable_clk:qcom_scm_clk_disable ();return ret ? : res.result[0 ];
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 66/267 memory-failure: use a folio in me_huge_page()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Wilcox (Oracle) <[email protected]>
[ Upstream commit b6fd410c32f1a66a52a42d6aae1ab7b011b74547 ]
This function was already explicitly calling compound_head(); unfortunately the compiler can't know that and elide the redundant calls to compound_head() buried in page_mapping(), unlock_page(), etc. Switch to using a folio, which does let us elide these calls.
Stable-dep-of: 8cf360b9d6a8 ("mm/memory-failure: fix handling of dissolved but not taken off from buddy pages")
--- mm/memory-failure.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
mm/memory-failure.c +6 -6
@@ -1193,25 +1193,25 @@ static int me_swapcache_clean(struct page_state *ps, struct page *p)*/ static int me_huge_page (struct page_state *ps,struct page *p) { +struct folio *folio =page_folio (p);int res; -struct page *hpage =compound_head (p);struct address_space *mapping;bool extra_pins = false; - mapping =page_mapping (hpage); + mapping =folio_mapping (folio);if (mapping) { - res =truncate_error_page (hpage,page_to_pfn (p), mapping); + res =truncate_error_page (&folio->page,page_to_pfn (p), mapping);/* The page is kept in page cache. */ extra_pins = true; -unlock_page (hpage); +folio_unlock (folio); }else { -unlock_page (hpage); +folio_unlock (folio);/* * migration entry prevents later access on error hugepage, * so we can free and dissolve it into buddy to save healthy * subpages. */ -put_page (hpage); +folio_put (folio);if (__page_handle_poison (p) >=0 ) {page_ref_inc (p); res =MF_RECOVERED ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 67/267 mm/memory-failure: fix handling of dissolved but not taken off from buddy pages
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Miaohe Lin <[email protected]>
[ Upstream commit 8cf360b9d6a840700e06864236a01a883b34bbad ]
When I did memory failure tests recently, below panic occurs:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x8cee00 flags: 0x6fffe0000000000(node=1|zone=2|lastcpupid=0x7fff) raw: 06fffe0000000000 dead000000000100 dead000000000122 0000000000000000 raw: 0000000000000000 0000000000000009 00000000ffffffff 0000000000000000 page dumped because: VM_BUG_ON_PAGE(!PageBuddy(page)) ------------[ cut here ]------------ kernel BUG at include/linux/page-flags.h:1009! invalid opcode: 0000 [#1] PREEMPT SMP NOPTI RIP: 0010:__del_page_from_free_list+0x151/0x180 RSP: 0018:ffffa49c90437998 EFLAGS: 00000046 RAX: 0000000000000035 RBX: 0000000000000009 RCX: ffff8dd8dfd1c9c8 RDX: 0000000000000000 RSI: 0000000000000027 RDI: ffff8dd8dfd1c9c0 RBP: ffffd901233b8000 R08: ffffffffab5511f8 R09: 0000000000008c69 R10: 0000000000003c15 R11: ffffffffab5511f8 R12: ffff8dd8fffc0c80 R13: 0000000000000001 R14: ffff8dd8fffc0c80 R15: 0000000000000009 FS: 00007ff916304740(0000) GS:ffff8dd8dfd00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055eae50124c8 CR3: 00000008479e0000 CR4: 00000000000006f0 Call Trace: <TASK> __rmqueue_pcplist+0x23b/0x520 get_page_from_freelist+0x26b/0xe40 __alloc_pages_noprof+0x113/0x1120 __folio_alloc_noprof+0x11/0xb0 alloc_buddy_hugetlb_folio.isra.0+0x5a/0x130 __alloc_fresh_hugetlb_folio+0xe7/0x140 alloc_pool_huge_folio+0x68/0x100 set_max_huge_pages+0x13d/0x340 hugetlb_sysctl_handler_common+0xe8/0x110 proc_sys_call_handler+0x194/0x280 vfs_write+0x387/0x550 ksys_write+0x64/0xe0 do_syscall_64+0xc2/0x1d0 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7ff916114887 RSP: 002b:00007ffec8a2fd78 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 000055eae500e350 RCX: 00007ff916114887 RDX: 0000000000000004 RSI: 000055eae500e390 RDI: 0000000000000003 RBP: 000055eae50104c0 R08: 0000000000000000 R09: 000055eae50104c0 R10: 0000000000000077 R11: 0000000000000246 R12: 0000000000000004 R13: 0000000000000004 R14: 00007ff916216b80 R15: 00007ff916216a00 </TASK> Modules linked in: mce_inject hwpoison_inject ---[ end trace 0000000000000000 ]---
And before the panic, there had an warning about bad page state:
BUG: Bad page state in process page-types pfn:8cee00 page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x8cee00 flags: 0x6fffe0000000000(node=1|zone=2|lastcpupid=0x7fff) page_type: 0xffffff7f(buddy) raw: 06fffe0000000000 ffffd901241c0008 ffffd901240f8008 0000000000000000 raw: 0000000000000000 0000000000000009 00000000ffffff7f 0000000000000000 page dumped because: nonzero mapcount Modules linked in: mce_inject hwpoison_inject CPU: 8 PID: 154211 Comm: page-types Not tainted 6.9.0-rc4-00499-g5544ec3178e2-dirty #22 Call Trace: <TASK> dump_stack_lvl+0x83/0xa0 bad_page+0x63/0xf0 free_unref_page+0x36e/0x5c0 unpoison_memory+0x50b/0x630 simple_attr_write_xsigned.constprop.0.isra.0+0xb3/0x110 debugfs_attr_write+0x42/0x60 full_proxy_write+0x5b/0x80 vfs_write+0xcd/0x550 ksys_write+0x64/0xe0 do_syscall_64+0xc2/0x1d0 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f189a514887 RSP: 002b:00007ffdcd899718 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f189a514887 RDX: 0000000000000009 RSI: 00007ffdcd899730 RDI: 0000000000000003 RBP: 00007ffdcd8997a0 R08: 0000000000000000 R09: 00007ffdcd8994b2 R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffdcda199a8 R13: 0000000000404af1 R14: 000000000040ad78 R15: 00007f189a7a5040 </TASK>
The root cause should be the below race:
memory_failure
try_memory_failure_hugetlb
me_huge_page
__page_handle_poison
dissolve_free_hugetlb_folio
drain_all_pages -- Buddy page can be isolated e.g. for compaction. take_page_off_buddy -- Failed as page is not in the buddy list.
-- Page can be putback into buddy after compaction.
page_ref_inc -- Leads to buddy page with refcnt = 1.
Then unpoison_memory() can unpoison the page and send the buddy page back into buddy list again leading to the above bad page state warning. And bad_page() will call page_mapcount_reset() to remove PageBuddy from buddy page leading to later VM_BUG_ON_PAGE(!PageBuddy(page)) when trying to allocate this page.
Fix this issue by only treating __page_handle_poison() as successful when it returns 1.
--- mm/memory-failure.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
mm/memory-failure.c +2 -2
@@ -1212,7 +1212,7 @@ static int me_huge_page(struct page_state *ps, struct page *p)* subpages. */ folio_put (folio); -if (__page_handle_poison (p) >=0 ) { +if (__page_handle_poison (p) >0 ) {page_ref_inc (p); res =MF_RECOVERED ; }else {
@@ -2082,7 +2082,7 @@ static int try_memory_failure_hugetlb(unsigned long pfn, int flags, int *hugetlb*/ if (res ==0 ) {folio_unlock (folio); -if (__page_handle_poison (p) >=0 ) { +if (__page_handle_poison (p) >0 ) {page_ref_inc (p); res =MF_RECOVERED ; }else {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 68/267 selftests/mm: conform test to TAP format output
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muhammad Usama Anjum <[email protected]>
[ Upstream commit 9a21701edc41465de56f97914741bfb7bfc2517d ]
Conform the layout, informational and status messages to TAP. No functional change is intended other than the layout of output messages.
Stable-dep-of: d4202e66a4b1 ("selftests/mm: compaction_test: fix bogus test success on Aarch64")
--- tools/testing/selftests/mm/compaction_test.c | 91 ++++++++++---------- 1 file changed, 44 insertions(+), 47 deletions(-)
tools/testing/selftests/mm/compaction_test.c +44 -47
@@ -33,7 +33,7 @@ int read_memory_info(unsigned long *memfree, unsigned long *hugepagesize)FILE *cmdfile =popen (cmd,"r" );if (!(fgets (buffer,sizeof (buffer), cmdfile))) { -perror ("Failed to read meminfo\n" ); +ksft_print_msg ("Failed to read meminfo: %s\n" ,strerror (errno));return -1 ; }
@@ -44,7 +44,7 @@ int read_memory_info(unsigned long *memfree, unsigned long *hugepagesize) cmdfile =popen (cmd,"r" );if (!(fgets (buffer,sizeof (buffer), cmdfile))) { -perror ("Failed to read meminfo\n" ); +ksft_print_msg ("Failed to read meminfo: %s\n" ,strerror (errno));return -1 ; }
@@ -62,14 +62,14 @@ int prereq(void) fd =open ("/proc/sys/vm/compact_unevictable_allowed" ,O_RDONLY |O_NONBLOCK );if (fd <0 ) { -perror ("Failed to open\n" -"/proc/sys/vm/compact_unevictable_allowed\n" ); +ksft_print_msg ("Failed to open /proc/sys/vm/compact_unevictable_allowed: %s\n" , +strerror (errno));return -1 ; }if (read (fd, &allowed,sizeof (char )) !=sizeof (char )) { -perror ("Failed to read from\n" -"/proc/sys/vm/compact_unevictable_allowed\n" ); +ksft_print_msg ("Failed to read from /proc/sys/vm/compact_unevictable_allowed: %s\n" , +strerror (errno));close (fd);return -1 ; }
@@ -78,12 +78,13 @@ int prereq(void)if (allowed =='1' )return 0 ; +ksft_print_msg ("Compaction isn't allowed\n" );return -1 ; }int check_compaction (unsigned long mem_free,unsigned int hugepage_size) { -int fd; +int fd, ret =-1 ;int compaction_index =0 ;char initial_nr_hugepages[10 ] = {0 };char nr_hugepages[10 ] = {0 };
@@ -94,12 +95,14 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size) fd =open ("/proc/sys/vm/nr_hugepages" ,O_RDWR |O_NONBLOCK );if (fd <0 ) { -perror ("Failed to open /proc/sys/vm/nr_hugepages" ); +ksft_test_result_fail ("Failed to open /proc/sys/vm/nr_hugepages: %s\n" , +strerror (errno));return -1 ; }if (read (fd, initial_nr_hugepages,sizeof (initial_nr_hugepages)) <=0 ) { -perror ("Failed to read from /proc/sys/vm/nr_hugepages" ); +ksft_test_result_fail ("Failed to read from /proc/sys/vm/nr_hugepages: %s\n" , +strerror (errno)); goto close_fd; }
@@ -107,7 +110,8 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)/* Start with the initial condition of 0 huge pages*/ if (write (fd,"0" ,sizeof (char )) !=sizeof (char )) { -perror ("Failed to write 0 to /proc/sys/vm/nr_hugepages\n" ); +ksft_test_result_fail ("Failed to write 0 to /proc/sys/vm/nr_hugepages: %s\n" , +strerror (errno)); goto close_fd; }
@@ -116,14 +120,16 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)/* Request a large number of huge pages. The Kernel will allocate as much as it can */ if (write (fd,"100000" , (6 *sizeof (char ))) != (6 *sizeof (char ))) { -perror ("Failed to write 100000 to /proc/sys/vm/nr_hugepages\n" ); +ksft_test_result_fail ("Failed to write 100000 to /proc/sys/vm/nr_hugepages: %s\n" , +strerror (errno)); goto close_fd; }lseek (fd,0 ,SEEK_SET );if (read (fd, nr_hugepages,sizeof (nr_hugepages)) <=0 ) { -perror ("Failed to re-read from /proc/sys/vm/nr_hugepages\n" ); +ksft_test_result_fail ("Failed to re-read from /proc/sys/vm/nr_hugepages: %s\n" , +strerror (errno)); goto close_fd; }
@@ -131,67 +137,58 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)huge pages */ compaction_index = mem_free/(atoi (nr_hugepages) * hugepage_size); -if (compaction_index >3 ) { -printf ("No of huge pages allocated = %d\n" , - (atoi (nr_hugepages))); -fprintf (stderr,"ERROR: Less that 1/%d of memory is available\n" -"as huge pages\n" , compaction_index); - goto close_fd; - } - -printf ("No of huge pages allocated = %d\n" , - (atoi (nr_hugepages))); -lseek (fd,0 ,SEEK_SET );if (write (fd, initial_nr_hugepages,strlen (initial_nr_hugepages)) !=strlen (initial_nr_hugepages)) { -perror ("Failed to write value to /proc/sys/vm/nr_hugepages\n" ); +ksft_test_result_fail ("Failed to write value to /proc/sys/vm/nr_hugepages: %s\n" , +strerror (errno)); goto close_fd; } -close (fd); -return 0 ; +if (compaction_index >3 ) { +ksft_print_msg ("ERROR: Less that 1/%d of memory is available\n" +"as huge pages\n" , compaction_index); +ksft_test_result_fail ("No of huge pages allocated = %d\n" , (atoi (nr_hugepages))); + goto close_fd; + } + +ksft_test_result_pass ("Memory compaction succeeded. No of huge pages allocated = %d\n" , + (atoi (nr_hugepages))); + ret =0 ; close_fd:close (fd); -printf ("Not OK. Compaction test failed." ); -return -1 ; +return ret; }int main (int argc,char **argv) {struct rlimit lim; -struct map_list *list, *entry; +struct map_list *list =NULL , *entry;size_t page_size, i;void *map =NULL ;unsigned long mem_free =0 ;unsigned long hugepage_size =0 ;long mem_fragmentable_MB =0 ; -if (prereq () !=0 ) { -printf ("Either the sysctl compact_unevictable_allowed is not\n" -"set to 1 or couldn't read the proc file.\n" -"Skipping the test\n" ); -return KSFT_SKIP ; - } +ksft_print_header (); + +if (prereq () !=0 ) +return ksft_exit_pass (); + +ksft_set_plan (1 ); lim.rlim_cur =RLIM_INFINITY ; lim.rlim_max =RLIM_INFINITY ; -if (setrlimit (RLIMIT_MEMLOCK , &lim)) { -perror ("Failed to set rlimit:\n" ); -return -1 ; - } +if (setrlimit (RLIMIT_MEMLOCK , &lim)) +ksft_exit_fail_msg ("Failed to set rlimit: %s\n" ,strerror (errno)); page_size =getpagesize (); - list =NULL ; - -if (read_memory_info (&mem_free, &hugepage_size) !=0 ) { -printf ("ERROR: Cannot read meminfo\n" ); -return -1 ; - } +if (read_memory_info (&mem_free, &hugepage_size) !=0 ) +ksft_exit_fail_msg ("Failed to get meminfo\n" ); mem_fragmentable_MB = mem_free *0.8 /1024 ;
@@ -227,7 +224,7 @@ int main(int argc, char **argv) }if (check_compaction (mem_free, hugepage_size) ==0 ) -return 0 ; +return ksft_exit_pass (); -return -1 ; +return ksft_exit_fail (); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 69/267 selftests/mm: log a consistent test name for check_compaction
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Brown <[email protected]>
[ Upstream commit f3b7568c49420d2dcd251032c9ca1e069ec8a6c9 ]
Every test result report in the compaction test prints a distinct log messae, and some of the reports print a name that varies at runtime. This causes problems for automation since a lot of automation software uses the printed string as the name of the test, if the name varies from run to run and from pass to fail then the automation software can't identify that a test changed result or that the same tests are being run.
Refactor the logging to use a consistent name when printing the result of the test, printing the existing messages as diagnostic information instead so they are still available for people trying to interpret the results.
Stable-dep-of: d4202e66a4b1 ("selftests/mm: compaction_test: fix bogus test success on Aarch64")
--- tools/testing/selftests/mm/compaction_test.c | 35 +++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-)
tools/testing/selftests/mm/compaction_test.c +19 -16
@@ -95,14 +95,15 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size) fd =open ("/proc/sys/vm/nr_hugepages" ,O_RDWR |O_NONBLOCK );if (fd <0 ) { -ksft_test_result_fail ("Failed to open /proc/sys/vm/nr_hugepages: %s\n" , -strerror (errno)); -return -1 ; +ksft_print_msg ("Failed to open /proc/sys/vm/nr_hugepages: %s\n" , +strerror (errno)); + ret =-1 ; + goto out; }if (read (fd, initial_nr_hugepages,sizeof (initial_nr_hugepages)) <=0 ) { -ksft_test_result_fail ("Failed to read from /proc/sys/vm/nr_hugepages: %s\n" , -strerror (errno)); +ksft_print_msg ("Failed to read from /proc/sys/vm/nr_hugepages: %s\n" , +strerror (errno)); goto close_fd; }
@@ -110,8 +111,8 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)/* Start with the initial condition of 0 huge pages*/ if (write (fd,"0" ,sizeof (char )) !=sizeof (char )) { -ksft_test_result_fail ("Failed to write 0 to /proc/sys/vm/nr_hugepages: %s\n" , -strerror (errno)); +ksft_print_msg ("Failed to write 0 to /proc/sys/vm/nr_hugepages: %s\n" , +strerror (errno)); goto close_fd; }
@@ -120,16 +121,16 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)/* Request a large number of huge pages. The Kernel will allocate as much as it can */ if (write (fd,"100000" , (6 *sizeof (char ))) != (6 *sizeof (char ))) { -ksft_test_result_fail ("Failed to write 100000 to /proc/sys/vm/nr_hugepages: %s\n" , -strerror (errno)); +ksft_print_msg ("Failed to write 100000 to /proc/sys/vm/nr_hugepages: %s\n" , +strerror (errno)); goto close_fd; }lseek (fd,0 ,SEEK_SET );if (read (fd, nr_hugepages,sizeof (nr_hugepages)) <=0 ) { -ksft_test_result_fail ("Failed to re-read from /proc/sys/vm/nr_hugepages: %s\n" , -strerror (errno)); +ksft_print_msg ("Failed to re-read from /proc/sys/vm/nr_hugepages: %s\n" , +strerror (errno)); goto close_fd; }
@@ -141,24 +142,26 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)if (write (fd, initial_nr_hugepages,strlen (initial_nr_hugepages)) !=strlen (initial_nr_hugepages)) { -ksft_test_result_fail ("Failed to write value to /proc/sys/vm/nr_hugepages: %s\n" , -strerror (errno)); +ksft_print_msg ("Failed to write value to /proc/sys/vm/nr_hugepages: %s\n" , +strerror (errno)); goto close_fd; } +ksft_print_msg ("Number of huge pages allocated = %d\n" , +atoi (nr_hugepages)); +if (compaction_index >3 ) {ksft_print_msg ("ERROR: Less that 1/%d of memory is available\n" "as huge pages\n" , compaction_index); -ksft_test_result_fail ("No of huge pages allocated = %d\n" , (atoi (nr_hugepages))); goto close_fd; } -ksft_test_result_pass ("Memory compaction succeeded. No of huge pages allocated = %d\n" , - (atoi (nr_hugepages))); ret =0 ; close_fd:close (fd); + out: +ksft_test_result (ret ==0 ,"check_compaction\n" );return ret; }
Signature · 1 line
2.43.0
Re: [PATCH 6.6 069/267] selftests/mm: log a consistent test name for check_compaction
Quoted 15 lines · Greg Kroah-Hartman
6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Brown <[email protected]>
[ Upstream commit
f3b7568c49420d2dcd251032c9ca1e069ec8a6c9]Every test result report in the compaction test prints a distinct log messae, and some of the reports print a name that varies at runtime. This causes problems for automation since a lot of automation software uses the printed string as the name of the test, if the name varies from run to run and from pass to fail then the automation software can't identify that a test changed result or that the same tests are being run.
Quoted 3 lines
Refactor the logging to use a consistent name when printing the result of the test, printing the existing messages as diagnostic information instead so they are still available for people trying to interpret the results.
This will change the test names for these tests which might disrupt people's CI.
Greg Kroah-Hartman
maintainerPATCH 70/267 selftests/mm: compaction_test: fix bogus test success on Aarch64
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dev Jain <[email protected]>
[ Upstream commit d4202e66a4b1fe6968f17f9f09bbc30d08f028a1 ]
Patch series "Fixes for compaction_test", v2.
The compaction_test memory selftest introduces fragmentation in memory and then tries to allocate as many hugepages as possible. This series addresses some problems.
On Aarch64, if nr_hugepages == 0, then the test trivially succeeds since compaction_index becomes 0, which is less than 3, due to no division by zero exception being raised. We fix that by checking for division by zero.
Secondly, correctly set the number of hugepages to zero before trying to set a large number of them.
Now, consider a situation in which, at the start of the test, a non-zero number of hugepages have been already set (while running the entire selftests/mm suite, or manually by the admin). The test operates on 80% of memory to avoid OOM-killer invocation, and because some memory is already blocked by hugepages, it would increase the chance of OOM-killing. Also, since mem_free used in check_compaction() is the value before we set nr_hugepages to zero, the chance that the compaction_index will be small is very high if the preset nr_hugepages was high, leading to a bogus test success.
This patch (of 3):
Currently, if at runtime we are not able to allocate a huge page, the test will trivially pass on Aarch64 due to no exception being raised on division by zero while computing compaction_index. Fix that by checking for nr_hugepages == 0. Anyways, in general, avoid a division by zero by exiting the program beforehand. While at it, fix a typo, and handle the case where the number of hugepages may overflow an integer.
--- tools/testing/selftests/mm/compaction_test.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-)
tools/testing/selftests/mm/compaction_test.c +13 -7
@@ -82,12 +82,13 @@ int prereq(void)return -1 ; } -int check_compaction (unsigned long mem_free,unsigned int hugepage_size) +int check_compaction (unsigned long mem_free,unsigned long hugepage_size) { +unsigned long nr_hugepages_ul;int fd, ret =-1 ;int compaction_index =0 ; -char initial_nr_hugepages[10 ] = {0 }; -char nr_hugepages[10 ] = {0 }; +char initial_nr_hugepages[20 ] = {0 }; +char nr_hugepages[20 ] = {0 };/* We want to test with 80% of available memory. Else, OOM killer comes in to play */
@@ -136,7 +137,12 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)/* We should have been able to request at least 1/3 rd of the memory in huge pages */ - compaction_index = mem_free/(atoi (nr_hugepages) * hugepage_size); + nr_hugepages_ul =strtoul (nr_hugepages,NULL ,10 ); +if (!nr_hugepages_ul) { +ksft_print_msg ("ERROR: No memory is available as huge pages\n" ); + goto close_fd; + } + compaction_index = mem_free/(nr_hugepages_ul * hugepage_size);lseek (fd,0 ,SEEK_SET );
@@ -147,11 +153,11 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size) goto close_fd; } -ksft_print_msg ("Number of huge pages allocated = %d\n" , -atoi (nr_hugepages)); +ksft_print_msg ("Number of huge pages allocated = %lu\n" , + nr_hugepages_ul);if (compaction_index >3 ) { -ksft_print_msg ("ERROR: Less that 1/%d of memory is available\n" +ksft_print_msg ("ERROR: Less than 1/%d of memory is available\n" "as huge pages\n" , compaction_index); goto close_fd; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 71/267 irqchip/riscv-intc: Allow large non-standard interrupt number
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yu Chien Peter Lin <[email protected]>
[ Upstream commit 96303bcb401c21dc1426d8d9bb1fc74aae5c02a9 ]
Currently, the implementation of the RISC-V INTC driver uses the interrupt cause as the hardware interrupt number, with a maximum of 64 interrupts. However, the platform can expand the interrupt number further for custom local interrupts.
To fully utilize the available local interrupt sources, switch to using irq_domain_create_tree() that creates the radix tree map, add global variables (riscv_intc_nr_irqs, riscv_intc_custom_base and riscv_intc_custom_nr_irqs) to determine the valid range of local interrupt number (hwirq).
Stable-dep-of: 0110c4b11047 ("irqchip/riscv-intc: Prevent memory leak when riscv_intc_init_common() fails")
--- drivers/irqchip/irq-riscv-intc.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-)
drivers/irqchip/irq-riscv-intc.c +19 -7
@@ -19,15 +19,16 @@#include <linux/smp.h> static struct irq_domain *intc_domain; +static unsigned int riscv_intc_nr_irqs__ro_after_init =BITS_PER_LONG ; +static unsigned int riscv_intc_custom_base__ro_after_init =BITS_PER_LONG ; +static unsigned int riscv_intc_custom_nr_irqs__ro_after_init ; static asmlinkage void riscv_intc_irq(struct pt_regs *regs) {unsigned long cause = regs->cause & ~CAUSE_IRQ_FLAG ; -if (unlikely (cause >=BITS_PER_LONG )) -panic ("unexpected interrupt cause" ); - -generic_handle_domain_irq (intc_domain, cause); +if (generic_handle_domain_irq (intc_domain, cause)) +pr_warn_ratelimited ("Failed to handle interrupt (cause: %ld)\n" , cause); }/*
@@ -93,6 +94,14 @@ static int riscv_intc_domain_alloc(struct irq_domain *domain,if (ret)return ret; +/* +* Only allow hwirq for which we have corresponding standard or +* custom interrupt enable register. +*/ +if ((hwirq >= riscv_intc_nr_irqs && hwirq < riscv_intc_custom_base) || + (hwirq >= riscv_intc_custom_base + riscv_intc_custom_nr_irqs)) +return -EINVAL ; +for (i =0 ; i < nr_irqs; i++) { ret =riscv_intc_domain_map (domain, virq + i, hwirq + i);if (ret)
@@ -117,8 +126,7 @@ static int __init riscv_intc_init_common(struct fwnode_handle *fn) {int rc; - intc_domain =irq_domain_create_linear (fn,BITS_PER_LONG , - &riscv_intc_domain_ops,NULL ); + intc_domain =irq_domain_create_tree (fn, &riscv_intc_domain_ops,NULL );if (!intc_domain) {pr_err ("unable to add IRQ domain\n" );return -ENXIO ;
@@ -132,7 +140,11 @@ static int __init riscv_intc_init_common(struct fwnode_handle *fn)riscv_set_intc_hwnode_fn (riscv_intc_hwnode); -pr_info ("%d local interrupts mapped\n" ,BITS_PER_LONG ); +pr_info ("%d local interrupts mapped\n" , riscv_intc_nr_irqs); +if (riscv_intc_custom_nr_irqs) { +pr_info ("%d custom local interrupts mapped\n" , + riscv_intc_custom_nr_irqs); + }return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 72/267 irqchip/riscv-intc: Introduce Andes hart-level interrupt controller
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yu Chien Peter Lin <[email protected]>
[ Upstream commit f4cc33e78ba8624a79ba8dea98ce5c85aa9ca33c ]
Add support for the Andes hart-level interrupt controller. This controller provides interrupt mask/unmask functions to access the custom register (SLIE) where the non-standard S-mode local interrupt enable bits are located. The base of custom interrupt number is set to 256.
To share the riscv_intc_domain_map() with the generic RISC-V INTC and ACPI, add a chip parameter to riscv_intc_init_common(), so it can be passed to the irq_domain_set_info() as a private data.
Andes hart-level interrupt controller requires the "andestech,cpu-intc" compatible string to be present in interrupt-controller of cpu node to enable the use of custom local interrupt source.
e.g.,
cpu0: cpu@0 {
compatible = "andestech,ax45mp", "riscv";
...
cpu0-intc: interrupt-controller {
#interrupt-cells = <0x01>;
compatible = "andestech,cpu-intc", "riscv,cpu-intc";
interrupt-controller;
};
};Stable-dep-of: 0110c4b11047 ("irqchip/riscv-intc: Prevent memory leak when riscv_intc_init_common() fails")
--- drivers/irqchip/irq-riscv-intc.c | 58 ++++++++++++++++++++++++++++---- include/linux/soc/andes/irq.h | 18 ++++++++++ 2 files changed, 69 insertions(+), 7 deletions(-) create mode 100644 include/linux/soc/andes/irq.h
drivers/irqchip/irq-riscv-intc.c +51 -7
@@ -17,6 +17,7 @@#include <linux/module.h> #include <linux/of.h> #include <linux/smp.h> +#include <linux/soc/andes/irq.h> static struct irq_domain *intc_domain;static unsigned int riscv_intc_nr_irqs__ro_after_init =BITS_PER_LONG ;
@@ -48,6 +49,31 @@ static void riscv_intc_irq_unmask(struct irq_data *d)csr_set (CSR_IE ,BIT (d->hwirq)); } +static void andes_intc_irq_mask (struct irq_data *d) +{ +/* +* Andes specific S-mode local interrupt causes (hwirq) +* are defined as (256 + n) and controlled by n-th bit +* of SLIE. +*/ +unsigned int mask =BIT (d->hwirq %BITS_PER_LONG ); + +if (d->hwirq <ANDES_SLI_CAUSE_BASE ) +csr_clear (CSR_IE , mask); +else +csr_clear (ANDES_CSR_SLIE , mask); +} + +static void andes_intc_irq_unmask (struct irq_data *d) +{ +unsigned int mask =BIT (d->hwirq %BITS_PER_LONG ); + +if (d->hwirq <ANDES_SLI_CAUSE_BASE ) +csr_set (CSR_IE , mask); +else +csr_set (ANDES_CSR_SLIE , mask); +} +static void riscv_intc_irq_eoi (struct irq_data *d) {/*
@@ -71,12 +97,21 @@ static struct irq_chip riscv_intc_chip = { .irq_eoi = riscv_intc_irq_eoi, }; +static struct irq_chip andes_intc_chip = { + .name ="RISC-V INTC" , + .irq_mask = andes_intc_irq_mask, + .irq_unmask = andes_intc_irq_unmask, + .irq_eoi = riscv_intc_irq_eoi, +}; +static int riscv_intc_domain_map (struct irq_domain *d,unsigned int irq,irq_hw_number_t hwirq) { +struct irq_chip *chip = d->host_data; +irq_set_percpu_devid (irq); -irq_domain_set_info (d, irq, hwirq, &riscv_intc_chip, d->host_data, - handle_percpu_devid_irq,NULL ,NULL ); +irq_domain_set_info (d, irq, hwirq, chip,NULL , handle_percpu_devid_irq, +NULL ,NULL );return 0 ; }
@@ -122,11 +157,12 @@ static struct fwnode_handle *riscv_intc_hwnode(void)return intc_domain->fwnode; } -static int __init riscv_intc_init_common (struct fwnode_handle *fn) +static int __init riscv_intc_init_common (struct fwnode_handle *fn, +struct irq_chip *chip) {int rc; - intc_domain =irq_domain_create_tree (fn, &riscv_intc_domain_ops,NULL ); + intc_domain =irq_domain_create_tree (fn, &riscv_intc_domain_ops, chip);if (!intc_domain) {pr_err ("unable to add IRQ domain\n" );return -ENXIO ;
@@ -152,8 +188,9 @@ static int __init riscv_intc_init_common(struct fwnode_handle *fn)static int __init riscv_intc_init (struct device_node *node,struct device_node *parent) { -int rc; +struct irq_chip *chip = &riscv_intc_chip;unsigned long hartid; +int rc; rc =riscv_of_parent_hartid (node, &hartid);if (rc <0 ) {
@@ -178,10 +215,17 @@ static int __init riscv_intc_init(struct device_node *node,return 0 ; } -return riscv_intc_init_common (of_node_to_fwnode (node)); +if (of_device_is_compatible (node,"andestech,cpu-intc" )) { + riscv_intc_custom_base =ANDES_SLI_CAUSE_BASE ; + riscv_intc_custom_nr_irqs =ANDES_RV_IRQ_LAST ; + chip = &andes_intc_chip; + } + +return riscv_intc_init_common (of_node_to_fwnode (node), chip); }IRQCHIP_DECLARE (riscv,"riscv,cpu-intc" , riscv_intc_init); +IRQCHIP_DECLARE (andes,"andestech,cpu-intc" , riscv_intc_init);#ifdef CONFIG_ACPI
@@ -208,7 +252,7 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,return -ENOMEM ; } -return riscv_intc_init_common (fn); +return riscv_intc_init_common (fn, &riscv_intc_chip); } IRQCHIP_ACPI_DECLARE(riscv_intc, ACPI_MADT_TYPE_RINTC, NULL,
include/linux/soc/andes/irq.h new file +18 -0
@@ -0,0 +1,18 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* +* Copyright (C) 2023 Andes Technology Corporation +*/ +#ifndef __ANDES_IRQ_H +#define __ANDES_IRQ_H + +/* Andes PMU irq number */ +#define ANDES_RV_IRQ_PMOVI 18 +#define ANDES_RV_IRQ_LAST ANDES_RV_IRQ_PMOVI +#define ANDES_SLI_CAUSE_BASE 256 + +/* Andes PMU related registers */ +#define ANDES_CSR_SLIE 0x9c4 +#define ANDES_CSR_SLIP 0x9c5 +#define ANDES_CSR_SCOUNTEROF 0x9d4 + +#endif /* __ANDES_IRQ_H */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 73/267 irqchip/riscv-intc: Prevent memory leak when riscv_intc_init_common() fails
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sunil V L <[email protected]>
[ Upstream commit 0110c4b110477bb1f19b0d02361846be7ab08300 ]
When riscv_intc_init_common() fails, the firmware node allocated is not freed. Add the missing free().
--- drivers/irqchip/irq-riscv-intc.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/irqchip/irq-riscv-intc.c +7 -2
@@ -232,8 +232,9 @@ IRQCHIP_DECLARE(andes, "andestech,cpu-intc", riscv_intc_init);static int __init riscv_intc_acpi_init (union acpi_subtable_headers *header,const unsigned long end) { -struct fwnode_handle *fn;struct acpi_madt_rintc *rintc; +struct fwnode_handle *fn; +int rc; rintc = (struct acpi_madt_rintc *)header;
@@ -252,7 +253,11 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,return -ENOMEM ; } -return riscv_intc_init_common (fn, &riscv_intc_chip); + rc =riscv_intc_init_common (fn, &riscv_intc_chip); +if (rc) +irq_domain_free_fwnode (fn); + +return rc; } IRQCHIP_ACPI_DECLARE(riscv_intc, ACPI_MADT_TYPE_RINTC, NULL,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 74/267 eventfs: Update all the eventfs_inodes from the events descriptor
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Rostedt (Google) <[email protected]>
[ Upstream commit 340f0c7067a95281ad13734f8225f49c6cf52067 ]
The change to update the permissions of the eventfs_inode had the misconception that using the tracefs_inode would find all the eventfs_inodes that have been updated and reset them on remount. The problem with this approach is that the eventfs_inodes are freed when they are no longer used (basically the reason the eventfs system exists). When they are freed, the updated eventfs_inodes are not reset on a remount because their tracefs_inodes have been freed.
Instead, since the events directory eventfs_inode always has a tracefs_inode pointing to it (it is not freed when finished), and the events directory has a link to all its children, have the eventfs_remount() function only operate on the events eventfs_inode and have it descend into its children updating their uid and gids.
--- fs/tracefs/event_inode.c | 51 ++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 12 deletions(-)
fs/tracefs/event_inode.c +39 -12
@@ -305,33 +305,60 @@ static const struct file_operations eventfs_file_operations = { .llseek = generic_file_llseek, }; -/* -* On a remount of tracefs, if UID or GID options are set, then -* the mount point inode permissions should be used. -* Reset the saved permission flags appropriately. -*/ -void eventfs_remount (struct tracefs_inode *ti,bool update_uid,bool update_gid) +static void eventfs_set_attrs (struct eventfs_inode *ei,bool update_uid,kuid_t uid, +bool update_gid,kgid_t gid,int level) { -struct eventfs_inode *ei = ti->private; +struct eventfs_inode *ei_child; -if (!ei) +/* Update events/<system>/<event> */ +if (WARN_ON_ONCE (level >3 ))return ; -if (update_uid) +if (update_uid) { ei->attr.mode &= ~EVENTFS_SAVE_UID ; + ei->attr.uid = uid; + } -if (update_gid) +if (update_gid) { ei->attr.mode &= ~EVENTFS_SAVE_GID ; + ei->attr.gid = gid; + } + +list_for_each_entry (ei_child, &ei->children, list) { +eventfs_set_attrs (ei_child, update_uid, uid, update_gid, gid, level +1 ); + }if (!ei->entry_attrs)return ;for (int i =0 ; i < ei->nr_entries; i++) { -if (update_uid) +if (update_uid) { ei->entry_attrs[i].mode &= ~EVENTFS_SAVE_UID ; -if (update_gid) + ei->entry_attrs[i].uid = uid; + } +if (update_gid) { ei->entry_attrs[i].mode &= ~EVENTFS_SAVE_GID ; + ei->entry_attrs[i].gid = gid; + } } + +} + +/* +* On a remount of tracefs, if UID or GID options are set, then +* the mount point inode permissions should be used. +* Reset the saved permission flags appropriately. +*/ +void eventfs_remount (struct tracefs_inode *ti,bool update_uid,bool update_gid) +{ +struct eventfs_inode *ei = ti->private; + +/* Only the events directory does the updates */ +if (!ei || !ei->is_events || ei->is_freed) +return ; + +eventfs_set_attrs (ei, update_uid, ti->vfs_inode.i_uid, + update_gid, ti->vfs_inode.i_gid,0 ); }/* Return the evenfs_inode of the "events" directory */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 75/267 bpf: fix multi-uprobe PID filtering logic
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrii Nakryiko <[email protected]>
[ Upstream commit 46ba0e49b64232adac35a2bc892f1710c5b0fb7f ]
Current implementation of PID filtering logic for multi-uprobes in uprobe_prog_run() is filtering down to exact *thread*, while the intent for PID filtering it to filter by *process* instead. The check in uprobe_prog_run() also differs from the analogous one in uprobe_multi_link_filter() for some reason. The latter is correct, checking task->mm, not the task itself.
Fix the check in uprobe_prog_run() to perform the same task->mm check.
While doing this, we also update get_pid_task() use to use PIDTYPE_TGID type of lookup, given the intent is to get a representative task of an entire process. This doesn't change behavior, but seems more logical. It would hold task group leader task now, not any random thread task.
Last but not least, given multi-uprobe support is half-broken due to this PID filtering logic (depending on whether PID filtering is important or not), we need to make it easy for user space consumers (including libbpf) to easily detect whether PID filtering logic was already fixed.
We do it here by adding an early check on passed pid parameter. If it's negative (and so has no chance of being a valid PID), we return -EINVAL. Previous behavior would eventually return -ESRCH ("No process found"), given there can't be any process with negative PID. This subtle change won't make any practical change in behavior, but will allow applications to detect PID filtering fixes easily. Libbpf fixes take advantage of this in the next patch.
--- kernel/trace/bpf_trace.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
kernel/trace/bpf_trace.c +4 -4
@@ -3099,7 +3099,7 @@ static int uprobe_prog_run(struct bpf_uprobe *uprobe,struct bpf_run_ctx *old_run_ctx;int err =0 ; -if (link->task && current != link->task) +if (link->task && current->mm != link->task->mm)return 0 ;if (sleepable)
@@ -3200,8 +3200,9 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr upath =u64_to_user_ptr (attr->link_create.uprobe_multi.path); uoffsets =u64_to_user_ptr (attr->link_create.uprobe_multi.offsets); cnt = attr->link_create.uprobe_multi.cnt; + pid = attr->link_create.uprobe_multi.pid; -if (!upath || !uoffsets || !cnt) +if (!upath || !uoffsets || !cnt || pid <0 )return -EINVAL ;if (cnt >MAX_UPROBE_MULTI_CNT )return -E2BIG ;
@@ -3225,10 +3226,9 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr goto error_path_put; } - pid = attr->link_create.uprobe_multi.pid;if (pid) {rcu_read_lock (); - task =get_pid_task (find_vpid (pid),PIDTYPE_PID ); + task =get_pid_task (find_vpid (pid),PIDTYPE_TGID );rcu_read_unlock ();if (!task) { err = -ESRCH ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 76/267 nilfs2: return the mapped address from nilfs_get_page()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthew Wilcox (Oracle) <[email protected]>
[ Upstream commit 09a46acb3697e50548bb265afa1d79163659dd85 ]
In prepartion for switching from kmap() to kmap_local(), return the kmap address from nilfs_get_page() instead of having the caller look up page_address().
Stable-dep-of: 7373a51e7998 ("nilfs2: fix nilfs_empty_dir() misjudgment and long loop on I/O errors")
--- fs/nilfs2/dir.c | 57 +++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 30 deletions(-)
fs/nilfs2/dir.c +27 -30
@@ -186,19 +186,24 @@ static bool nilfs_check_page(struct page *page)return false; } -static struct page *nilfs_get_page (struct inode *dir,unsigned long n) +static void *nilfs_get_page (struct inode *dir,unsigned long n, +struct page **pagep) {struct address_space *mapping = dir->i_mapping;struct page *page =read_mapping_page (mapping, n,NULL ); +void *kaddr; -if (!IS_ERR (page)) { -kmap (page); -if (unlikely (!PageChecked (page))) { -if (!nilfs_check_page (page)) - goto fail; - } +if (IS_ERR (page)) +return page; + + kaddr =kmap (page); +if (unlikely (!PageChecked (page))) { +if (!nilfs_check_page (page)) + goto fail; } -return page; + + *pagep = page; +return kaddr; fail:nilfs_put_page (page);
@@ -275,14 +280,14 @@ static int nilfs_readdir(struct file *file, struct dir_context *ctx)for ( ; n < npages; n++, offset =0 ) {char *kaddr, *limit;struct nilfs_dir_entry *de; -struct page *page =nilfs_get_page (inode, n); +struct page *page; -if (IS_ERR (page)) { + kaddr =nilfs_get_page (inode, n, &page); +if (IS_ERR (kaddr)) {nilfs_error (sb,"bad page in #%lu" , inode->i_ino); ctx->pos +=PAGE_SIZE - offset;return -EIO ; } - kaddr =page_address (page); de = (struct nilfs_dir_entry *)(kaddr + offset); limit = kaddr +nilfs_last_byte (inode, n) -NILFS_DIR_REC_LEN (1 );
@@ -345,11 +350,9 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr, start =0 ; n = start; do { - char *kaddr; + char *kaddr = nilfs_get_page(dir, n, &page); - page = nilfs_get_page(dir, n); - if (!IS_ERR(page)) { - kaddr = page_address(page); + if (!IS_ERR(kaddr)) { de = (struct nilfs_dir_entry *)kaddr; kaddr += nilfs_last_byte(dir, n) - reclen; while ((char *) de <= kaddr) {
@@ -387,15 +390,11 @@ nilfs_find_entry(struct inode *dir, const struct qstr *qstr,struct nilfs_dir_entry *nilfs_dotdot (struct inode *dir,struct page **p) { -struct page *page =nilfs_get_page (dir,0 ); -struct nilfs_dir_entry *de =NULL ; +struct nilfs_dir_entry *de =nilfs_get_page (dir,0 , p); -if (!IS_ERR (page)) { - de =nilfs_next_entry ( - (struct nilfs_dir_entry *)page_address (page)); - *p = page; - } -return de; +if (IS_ERR (de)) +return NULL ; +return nilfs_next_entry (de); }ino_t nilfs_inode_by_name (struct inode *dir,const struct qstr *qstr)
@@ -459,12 +458,11 @@ int nilfs_add_link(struct dentry *dentry, struct inode *inode)for (n =0 ; n <= npages; n++) {char *dir_end; - page =nilfs_get_page (dir, n); - err =PTR_ERR (page); -if (IS_ERR (page)) + kaddr =nilfs_get_page (dir, n, &page); + err =PTR_ERR (kaddr); +if (IS_ERR (kaddr)) goto out;lock_page (page); - kaddr =page_address (page); dir_end = kaddr +nilfs_last_byte (dir, n); de = (struct nilfs_dir_entry *)kaddr; kaddr +=PAGE_SIZE - reclen;
@@ -627,11 +625,10 @@ int nilfs_empty_dir(struct inode *inode)char *kaddr;struct nilfs_dir_entry *de; - page =nilfs_get_page (inode, i); -if (IS_ERR (page)) + kaddr =nilfs_get_page (inode, i, &page); +if (IS_ERR (kaddr))continue ; - kaddr =page_address (page); de = (struct nilfs_dir_entry *)kaddr; kaddr +=nilfs_last_byte (inode, i) -NILFS_DIR_REC_LEN (1 );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 77/267 nilfs2: fix nilfs_empty_dir() misjudgment and long loop on I/O errors
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryusuke Konishi <[email protected]>
[ Upstream commit 7373a51e7998b508af7136530f3a997b286ce81c ]
The error handling in nilfs_empty_dir() when a directory folio/page read fails is incorrect, as in the old ext2 implementation, and if the folio/page cannot be read or nilfs_check_folio() fails, it will falsely determine the directory as empty and corrupt the file system.
In addition, since nilfs_empty_dir() does not immediately return on a failed folio/page read, but continues to loop, this can cause a long loop with I/O if i_size of the directory's inode is also corrupted, causing the log writer thread to wait and hang, as reported by syzbot.
Fix these issues by making nilfs_empty_dir() immediately return a false value (0) if it fails to get a directory folio/page.
--- fs/nilfs2/dir.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nilfs2/dir.c +1 -1
@@ -627,7 +627,7 @@ int nilfs_empty_dir(struct inode *inode) kaddr =nilfs_get_page (inode, i, &page);if (IS_ERR (kaddr)) -continue ; +return 0 ; de = (struct nilfs_dir_entry *)kaddr; kaddr +=nilfs_last_byte (inode, i) -NILFS_DIR_REC_LEN (1 );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 78/267 io_uring/rsrc: dont lock while !TASK_RUNNING
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pavel Begunkov <[email protected]>
commit 54559642b96116b45e4b5ca7fd9f7835b8561272 upstream.
There is a report of io_rsrc_ref_quiesce() locking a mutex while not TASK_RUNNING, which is due to forgetting restoring the state back after io_run_task_work_sig() and attempts to break out of the waiting loop.
do not call blocking ops when !TASK_RUNNING; state=1 set at [<ffffffff815d2494>] prepare_to_wait+0xa4/0x380 kernel/sched/wait.c:237
WARNING: CPU: 2 PID: 397056 at kernel/sched/core.c:10099 __might_sleep+0x114/0x160 kernel/sched/core.c:10099 RIP: 0010:__might_sleep+0x114/0x160 kernel/sched/core.c:10099 Call Trace: <TASK> __mutex_lock_common kernel/locking/mutex.c:585 [inline] __mutex_lock+0xb4/0x940 kernel/locking/mutex.c:752 io_rsrc_ref_quiesce+0x590/0x940 io_uring/rsrc.c:253 io_sqe_buffers_unregister+0xa2/0x340 io_uring/rsrc.c:799 __io_uring_register io_uring/register.c:424 [inline] __do_sys_io_uring_register+0x5b9/0x2400 io_uring/register.c:613 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xd8/0x270 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x6f/0x77
--- io_uring/rsrc.c | 1 + 1 file changed, 1 insertion(+)
io_uring/rsrc.c +1 -0
@@ -250,6 +250,7 @@ __cold static int io_rsrc_ref_quiesce(st ret =io_run_task_work_sig (ctx);if (ret <0 ) { +__set_current_state (TASK_RUNNING );mutex_lock (&ctx->uring_lock);if (list_empty (&ctx->rsrc_ref_list)) ret =0 ;
Greg Kroah-Hartman
maintainerPATCH 79/267 io_uring: check for non-NULL file pointer in io_file_can_poll()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jens Axboe <[email protected]>
commit 5fc16fa5f13b3c06fdb959ef262050bd810416a2 upstream.
In earlier kernels, it was possible to trigger a NULL pointer dereference off the forced async preparation path, if no file had been assigned. The trace leading to that looks as follows:
BUG: kernel NULL pointer dereference, address: 00000000000000b0 PGD 0 P4D 0 Oops: 0000 [#1] PREEMPT SMP CPU: 67 PID: 1633 Comm: buf-ring-invali Not tainted 6.8.0-rc3+ #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS unknown 2/2/2022 RIP: 0010:io_buffer_select+0xc3/0x210 Code: 00 00 48 39 d1 0f 82 ae 00 00 00 48 81 4b 48 00 00 01 00 48 89 73 70 0f b7 50 0c 66 89 53 42 85 ed 0f 85 d2 00 00 00 48 8b 13 <48> 8b 92 b0 00 00 00 48 83 7a 40 00 0f 84 21 01 00 00 4c 8b 20 5b RSP: 0018:ffffb7bec38c7d88 EFLAGS: 00010246 RAX: ffff97af2be61000 RBX: ffff97af234f1700 RCX: 0000000000000040 RDX: 0000000000000000 RSI: ffff97aecfb04820 RDI: ffff97af234f1700 RBP: 0000000000000000 R08: 0000000000200030 R09: 0000000000000020 R10: ffffb7bec38c7dc8 R11: 000000000000c000 R12: ffffb7bec38c7db8 R13: ffff97aecfb05800 R14: ffff97aecfb05800 R15: ffff97af2be5e000 FS: 00007f852f74b740(0000) GS:ffff97b1eeec0000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000000b0 CR3: 000000016deab005 CR4: 0000000000370ef0 Call Trace: <TASK> ? __die+0x1f/0x60 ? page_fault_oops+0x14d/0x420 ? do_user_addr_fault+0x61/0x6a0 ? exc_page_fault+0x6c/0x150 ? asm_exc_page_fault+0x22/0x30 ? io_buffer_select+0xc3/0x210 __io_import_iovec+0xb5/0x120 io_readv_prep_async+0x36/0x70 io_queue_sqe_fallback+0x20/0x260 io_submit_sqes+0x314/0x630 __do_sys_io_uring_enter+0x339/0xbc0 ? __do_sys_io_uring_register+0x11b/0xc50 ? vm_mmap_pgoff+0xce/0x160 do_syscall_64+0x5f/0x180 entry_SYSCALL_64_after_hwframe+0x46/0x4e RIP: 0033:0x55e0a110a67e Code: ba cc 00 00 00 45 31 c0 44 0f b6 92 d0 00 00 00 31 d2 41 b9 08 00 00 00 41 83 e2 01 41 c1 e2 04 41 09 c2 b8 aa 01 00 00 0f 05 <c3> 90 89 30 eb a9 0f 1f 40 00 48 8b 42 20 8b 00 a8 06 75 af 85 f6
because the request is marked forced ASYNC and has a bad file fd, and hence takes the forced async prep path.
Current kernels with the request async prep cleaned up can no longer hit this issue, but for ease of backporting, let's add this safety check in here too as it really doesn't hurt. For both cases, this will inevitably end with a CQE posted with -EBADF.
--- io_uring/kbuf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
io_uring/kbuf.c +2 -1
@@ -168,7 +168,8 @@ static void __user *io_ring_buffer_selec req->buf_list = bl; req->buf_index = buf->bid; -if (issue_flags &IO_URING_F_UNLOCKED || !file_can_poll (req->file)) { +if (issue_flags &IO_URING_F_UNLOCKED || + (req->file && !file_can_poll (req->file))) {/* * If we came in unlocked, we have no choice but to consume the * buffer here, otherwise nothing ensures that the buffer won't
Greg Kroah-Hartman
maintainerPATCH 80/267 USB: class: cdc-wdm: Fix CPU lockup caused by excessive log messages
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alan Stern <[email protected]>
commit 22f00812862564b314784167a89f27b444f82a46 upstream.
The syzbot fuzzer found that the interrupt-URB completion callback in the cdc-wdm driver was taking too long, and the driver's immediate resubmission of interrupt URBs with -EPROTO status combined with the dummy-hcd emulation to cause a CPU lockup:
cdc_wdm 1-1:1.0: nonzero urb status received: -71cdc_wdm 1-1:1.0: wdm_int_callback - 0 bytes
watchdog: BUG: soft lockup - CPU#0 stuck for 26s! [syz-executor782:6625] CPU#0 Utilization every 4s during lockup: #1: 98% system, 0% softirq, 3% hardirq, 0% idle #2: 98% system, 0% softirq, 3% hardirq, 0% idle #3: 98% system, 0% softirq, 3% hardirq, 0% idle #4: 98% system, 0% softirq, 3% hardirq, 0% idle #5: 98% system, 1% softirq, 3% hardirq, 0% idle Modules linked in: irq event stamp: 73096 hardirqs last enabled at (73095): [<ffff80008037bc00>] console_emit_next_record kernel/printk/printk.c:2935 [inline] hardirqs last enabled at (73095): [<ffff80008037bc00>] console_flush_all+0x650/0xb74 kernel/printk/printk.c:2994 hardirqs last disabled at (73096): [<ffff80008af10b00>] __el1_irq arch/arm64/kernel/entry-common.c:533 [inline] hardirqs last disabled at (73096): [<ffff80008af10b00>] el1_interrupt+0x24/0x68 arch/arm64/kernel/entry-common.c:551 softirqs last enabled at (73048): [<ffff8000801ea530>] softirq_handle_end kernel/softirq.c:400 [inline] softirqs last enabled at (73048): [<ffff8000801ea530>] handle_softirqs+0xa60/0xc34 kernel/softirq.c:582 softirqs last disabled at (73043): [<ffff800080020de8>] __do_softirq+0x14/0x20 kernel/softirq.c:588 CPU: 0 PID: 6625 Comm: syz-executor782 Tainted: G W 6.10.0-rc2-syzkaller-g8867bbd4a056 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/02/2024
Testing showed that the problem did not occur if the two error messages -- the first two lines above -- were removed; apparently adding material to the kernel log takes a surprisingly large amount of time.
In any case, the best approach for preventing these lockups and to avoid spamming the log with thousands of error messages per second is to ratelimit the two dev_err() calls. Therefore we replace them with dev_err_ratelimited().
--- drivers/usb/class/cdc-wdm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/class/cdc-wdm.c +2 -2
@@ -266,14 +266,14 @@ static void wdm_int_callback(struct urbdev_err (&desc->intf->dev,"Stall on int endpoint\n" ); goto sw;/* halt is cleared in work */ default : -dev_err (&desc->intf->dev, +dev_err_ratelimited (&desc->intf->dev,"nonzero urb status received: %d\n" , status);break ; } }if (urb->actual_length <sizeof (struct usb_cdc_notification )) { -dev_err (&desc->intf->dev,"wdm_int_callback - %d bytes\n" , +dev_err_ratelimited (&desc->intf->dev,"wdm_int_callback - %d bytes\n" , urb->actual_length); goto exit; }
Greg Kroah-Hartman
maintainerPATCH 81/267 USB: xen-hcd: Traverse host/ when CONFIG_USB_XEN_HCD is selected
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Ernberg <[email protected]>
commit 8475ffcfb381a77075562207ce08552414a80326 upstream.
If no other USB HCDs are selected when compiling a small pure virutal machine, the Xen HCD driver cannot be built.
Fix it by traversing down host/ if CONFIG_USB_XEN_HCD is selected.
--- drivers/usb/Makefile | 1 + 1 file changed, 1 insertion(+)
drivers/usb/Makefile +1 -0
@@ -35,6 +35,7 @@ obj-$(CONFIG_USB_R8A66597_HCD) += host/ obj-$(CONFIG_USB_FSL_USB2) += host/ obj-$(CONFIG_USB_FOTG210_HCD) += host/ obj-$(CONFIG_USB_MAX3421_HCD) += host/ +obj-$(CONFIG_USB_XEN_HCD) += host/ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/
Greg Kroah-Hartman
maintainerPATCH 82/267 usb: typec: tcpm: fix use-after-free case in tcpm_register_source_caps
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amit Sunil Dhamne <[email protected]>
commit e7e921918d905544500ca7a95889f898121ba886 upstream.
There could be a potential use-after-free case in tcpm_register_source_caps(). This could happen when:
* new (say invalid) source caps are advertised
* the existing source caps are unregistered
* tcpm_register_source_caps() returns with an error as usb_power_delivery_register_capabilities() fails
This causes port->partner_source_caps to hold on to the now freed source caps.
Reset port->partner_source_caps value to NULL after unregistering existing source caps.
--- drivers/usb/typec/tcpm/tcpm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/usb/typec/tcpm/tcpm.c +3 -1
@@ -2436,8 +2436,10 @@ static int tcpm_register_sink_caps(strucmemcpy (caps.pdo, port->sink_caps,sizeof (u32) * port->nr_sink_caps); caps.role =TYPEC_SINK ; -if (cap) +if (cap) {usb_power_delivery_unregister_capabilities (cap); + port->partner_source_caps =NULL ; + } cap =usb_power_delivery_register_capabilities (port->partner_pd, &caps);if (IS_ERR (cap))
Greg Kroah-Hartman
maintainerPATCH 83/267 usb: typec: tcpm: Ignore received Hard Reset in TOGGLING state
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyle Tso <[email protected]>
commit fc8fb9eea94d8f476e15f3a4a7addeb16b3b99d6 upstream.
Similar to what fixed in Commit a6fe37f428c1 ("usb: typec: tcpm: Skip hard reset when in error recovery"), the handling of the received Hard Reset has to be skipped during TOGGLING state.
[ 4086.021288] VBUS off [ 4086.021295] pending state change SNK_READY -> SNK_UNATTACHED @ 650 ms [rev2 NONE_AMS] [ 4086.022113] VBUS VSAFE0V [ 4086.022117] state change SNK_READY -> SNK_UNATTACHED [rev2 NONE_AMS] [ 4086.022447] VBUS off [ 4086.022450] state change SNK_UNATTACHED -> SNK_UNATTACHED [rev2 NONE_AMS] [ 4086.023060] VBUS VSAFE0V [ 4086.023064] state change SNK_UNATTACHED -> SNK_UNATTACHED [rev2 NONE_AMS] [ 4086.023070] disable BIST MODE TESTDATA [ 4086.023766] disable vbus discharge ret:0 [ 4086.023911] Setting usb_comm capable false [ 4086.028874] Setting voltage/current limit 0 mV 0 mA [ 4086.028888] polarity 0 [ 4086.030305] Requesting mux state 0, usb-role 0, orientation 0 [ 4086.033539] Start toggling [ 4086.038496] state change SNK_UNATTACHED -> TOGGLING [rev2 NONE_AMS]
// This Hard Reset is unexpected
[ 4086.038499] Received hard reset [ 4086.038501] state change TOGGLING -> HARD_RESET_START [rev2 HARD_RESET]
--- drivers/usb/typec/tcpm/tcpm.c | 1 + 1 file changed, 1 insertion(+)
drivers/usb/typec/tcpm/tcpm.c +1 -0
@@ -5415,6 +5415,7 @@ static void _tcpm_pd_hard_reset(struct t port->tcpc->set_bist_data (port->tcpc, false);switch (port->state) { +case TOGGLING :case ERROR_RECOVERY :case PORT_RESET :case PORT_RESET_WAIT_OFF :
Greg Kroah-Hartman
maintainerPATCH 84/267 mei: me: release irq in mei_me_pci_resume error path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tomas Winkler <[email protected]>
commit 283cb234ef95d94c61f59e1cd070cd9499b51292 upstream.
The mei_me_pci_resume doesn't release irq on the error path, in case mei_start() fails.
--- drivers/misc/mei/pci-me.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/misc/mei/pci-me.c +3 -1
@@ -400,8 +400,10 @@ static int mei_me_pci_resume(struct devi } err =mei_restart (dev); -if (err) +if (err) { +free_irq (pdev->irq, dev);return err; + }/* Start timer if stopped in suspend */ schedule_delayed_work (&dev->timer_work,HZ );
Greg Kroah-Hartman
maintainerPATCH 85/267 tty: n_tty: Fix buffer offsets when lookahead is used
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ilpo Järvinen <[email protected]>
commit b19ab7ee2c4c1ec5f27c18413c3ab63907f7d55c upstream.
When lookahead has "consumed" some characters (la_count > 0), n_tty_receive_buf_standard() and n_tty_receive_buf_closing() for characters beyond the la_count are given wrong cp/fp offsets which leads to duplicating and losing some characters.
If la_count > 0, correct buffer pointers and make count consistent too (the latter is not strictly necessary to fix the issue but seems more logical to adjust all variables immediately to keep state consistent).
--- drivers/tty/n_tty.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-)
drivers/tty/n_tty.c +16 -6
@@ -1624,15 +1624,25 @@ static void __receive_buf(struct tty_strelse if (ldata->raw || (L_EXTPROC (tty) && !preops))n_tty_receive_buf_raw (tty, cp, fp, count);else if (tty->closing && !L_EXTPROC (tty)) { -if (la_count >0 ) +if (la_count >0 ) {n_tty_receive_buf_closing (tty, cp, fp, la_count, true); -if (count > la_count) -n_tty_receive_buf_closing (tty, cp, fp, count - la_count, false); + cp += la_count; +if (fp) + fp += la_count; + count -= la_count; + } +if (count >0 ) +n_tty_receive_buf_closing (tty, cp, fp, count, false); }else { -if (la_count >0 ) +if (la_count >0 ) {n_tty_receive_buf_standard (tty, cp, fp, la_count, true); -if (count > la_count) -n_tty_receive_buf_standard (tty, cp, fp, count - la_count, false); + cp += la_count; +if (fp) + fp += la_count; + count -= la_count; + } +if (count >0 ) +n_tty_receive_buf_standard (tty, cp, fp, count, false);flush_echoes (tty);if (tty->ops->flush_chars)
Greg Kroah-Hartman
maintainerPATCH 86/267 serial: port: Dont block system suspend even if bytes are left to xmit
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Douglas Anderson <[email protected]>
commit ca84cd379b45e9b1775b9e026f069a3a886b409d upstream.
Recently, suspend testing on sc7180-trogdor based devices has started to sometimes fail with messages like this:
port a88000.serial:0.0: PM: calling pm_runtime_force_suspend+0x0/0xf8 @ 28934, parent: a88000.serial:0 port a88000.serial:0.0: PM: dpm_run_callback(): pm_runtime_force_suspend+0x0/0xf8 returns -16 port a88000.serial:0.0: PM: pm_runtime_force_suspend+0x0/0xf8 returned -16 after 33 usecs port a88000.serial:0.0: PM: failed to suspend: error -16
I could reproduce these problems by logging in via an agetty on the debug serial port (which was _not_ used for kernel console) and running:
cat /var/log/messages
...and then (via an SSH session) forcing a few suspend/resume cycles.
Tracing through the code and doing some printf()-based debugging shows that the -16 (-EBUSY) comes from the recently added serial_port_runtime_suspend().
The idea of the serial_port_runtime_suspend() function is to prevent the port from being _runtime_ suspended if it still has bytes left to transmit. Having bytes left to transmit isn't a reason to block _system_ suspend, though. If a serdev device in the kernel needs to block system suspend it should block its own suspend and it can use serdev_device_wait_until_sent() to ensure bytes are sent.
The DEFINE_RUNTIME_DEV_PM_OPS() used by the serial_port code means that the system suspend function will be pm_runtime_force_suspend(). In pm_runtime_force_suspend() we can see that before calling the runtime suspend function we'll call pm_runtime_disable(). This should be a reliable way to detect that we're called from system suspend and that we shouldn't look for busyness.
--- drivers/tty/serial/serial_port.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/tty/serial/serial_port.c +7 -0
@@ -60,6 +60,13 @@ static int serial_port_runtime_suspend(sif (port->flags &UPF_DEAD )return 0 ; +/* +* Nothing to do on pm_runtime_force_suspend(), see +* DEFINE_RUNTIME_DEV_PM_OPS. +*/ +if (!pm_runtime_enabled (dev)) +return 0 ; +uart_port_lock_irqsave (port, &flags);if (!port_dev->tx_enabled) {uart_port_unlock_irqrestore (port, flags);
Greg Kroah-Hartman
maintainerPATCH 87/267 landlock: Fix d_parent walk
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mickaël Salaün <[email protected]>
commit 88da52ccd66e65f2e63a6c35c9dff55d448ef4dc upstream.
The WARN_ON_ONCE() in collect_domain_accesses() can be triggered when trying to link a root mount point. This cannot work in practice because this directory is mounted, but the VFS check is done after the call to security_path_link().
Do not use source directory's d_parent when the source directory is the mount point.
--- security/landlock/fs.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
security/landlock/fs.c +11 -2
@@ -820,6 +820,7 @@ static int current_check_refer_path(strubool allow_parent1, allow_parent2;access_mask_t access_request_parent1, access_request_parent2;struct path mnt_dir; +struct dentry *old_parent;layer_mask_t layer_masks_parent1[LANDLOCK_NUM_ACCESS_FS ] = {}, layer_masks_parent2[LANDLOCK_NUM_ACCESS_FS ] = {};
@@ -867,9 +868,17 @@ static int current_check_refer_path(stru mnt_dir.mnt = new_dir->mnt; mnt_dir.dentry = new_dir->mnt->mnt_root; +/* +* old_dentry may be the root of the common mount point and +* !IS_ROOT(old_dentry) at the same time (e.g. with open_tree() and +* OPEN_TREE_CLONE). We do not need to call dget(old_parent) because +* we keep a reference to old_dentry. +*/ + old_parent = (old_dentry == mnt_dir.dentry) ? old_dentry : + old_dentry->d_parent; +/* new_dir->dentry is equal to new_dentry->d_parent */ - allow_parent1 =collect_domain_accesses (dom, mnt_dir.dentry, - old_dentry->d_parent, + allow_parent1 =collect_domain_accesses (dom, mnt_dir.dentry, old_parent, &layer_masks_parent1); allow_parent2 =collect_domain_accesses ( dom, mnt_dir.dentry, new_dir->dentry, &layer_masks_parent2);
PATCH 1/1 selftests/landlock: Add layout1.refer_mount_root
[ Upstream commit 0055f53aac80fd938bf7cdfad7ad414ca6c0e198 ]
Add tests to check error codes when linking or renaming a mount root directory. This previously triggered a kernel warning, but it is fixed with the previous commit.
--- tools/testing/selftests/landlock/fs_test.c | 45 ++++++++++++++++++++++ 1 file changed, 45 insertions(+)
tools/testing/selftests/landlock/fs_test.c +45 -0
@@ -11,6 +11,7 @@#include <fcntl.h> #include <linux/landlock.h> #include <linux/magic.h> +#include <linux/mount.h> #include <sched.h> #include <stdio.h> #include <string.h>
@@ -34,6 +35,13 @@ int renameat2(int olddirfd, const char *oldpath, int newdirfd, }#endif +#ifndef open_tree +int open_tree (int dfd,const char *filename,unsigned int flags) +{ +return syscall (__NR_open_tree, dfd, filename, flags); +} +#endif +#ifndef RENAME_EXCHANGE #define RENAME_EXCHANGE (1 << 1)#endif
@@ -2264,6 +2272,43 @@ TEST_F_FORK(layout1, refer_denied_by_default4) layer_dir_s1d1_refer); } +/* +* Tests walking through a denied root mount. +*/ +TEST_F_FORK(layout1, refer_mount_root_deny) +{ +const struct landlock_ruleset_attr ruleset_attr = { + .handled_access_fs =LANDLOCK_ACCESS_FS_MAKE_DIR , + }; +int root_fd, ruleset_fd; + +/* Creates a mount object from a non-mount point. */ +set_cap (_metadata,CAP_SYS_ADMIN ); + root_fd = +open_tree (AT_FDCWD , dir_s1d1, +AT_EMPTY_PATH |OPEN_TREE_CLONE |OPEN_TREE_CLOEXEC ); +clear_cap (_metadata,CAP_SYS_ADMIN ); +ASSERT_LE (0 , root_fd); + + ruleset_fd = +landlock_create_ruleset (&ruleset_attr,sizeof (ruleset_attr),0 ); +ASSERT_LE (0 , ruleset_fd); + +ASSERT_EQ (0 ,prctl (PR_SET_NO_NEW_PRIVS ,1 ,0 ,0 ,0 )); +ASSERT_EQ (0 ,landlock_restrict_self (ruleset_fd,0 )); +EXPECT_EQ (0 ,close (ruleset_fd)); + +/* Link denied by Landlock: EACCES. */ +EXPECT_EQ (-1 ,linkat (root_fd,"." , root_fd,"does_not_exist" ,0 )); +EXPECT_EQ (EACCES , errno); + +/* renameat2() always returns EBUSY. */ +EXPECT_EQ (-1 ,renameat2 (root_fd,"." , root_fd,"does_not_exist" ,0 )); +EXPECT_EQ (EBUSY , errno); + +EXPECT_EQ (0 ,close (root_fd)); +} + TEST_F_FORK(layout1, reparent_link) {const struct rule layer1[] = {
Greg Kroah-Hartman
maintainerPATCH 88/267 jfs: xattr: fix buffer overflow for invalid xattr
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Greg Kroah-Hartman <[email protected]>
commit 7c55b78818cfb732680c4a72ab270cc2d2ee3d0f upstream.
When an xattr size is not what is expected, it is printed out to the kernel log in hex format as a form of debugging. But when that xattr size is bigger than the expected size, printing it out can cause an access off the end of the buffer.
Fix this all up by properly restricting the size of the debug hex dump in the kernel log.
--- fs/jfs/xattr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/jfs/xattr.c +3 -1
@@ -557,9 +557,11 @@ static int ea_get(struct inode *inode, s size_check:if (EALIST_SIZE (ea_buf->xattr) != ea_size) { +int size =min_t (int,EALIST_SIZE (ea_buf->xattr), ea_size); +printk (KERN_ERR "ea_get: invalid extended attribute\n" );print_hex_dump (KERN_ERR ,"" ,DUMP_PREFIX_ADDRESS ,16 ,1 , - ea_buf->xattr, ea_size,1 ); + ea_buf->xattr, size,1 );ea_release (inode, ea_buf); rc = -EIO ; goto clean_up;
Greg Kroah-Hartman
maintainerPATCH 89/267 xhci: Set correct transferred length for cancelled bulk transfers
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mathias Nyman <[email protected]>
commit f0260589b439e2637ad54a2b25f00a516ef28a57 upstream.
The transferred length is set incorrectly for cancelled bulk transfer TDs in case the bulk transfer ring stops on the last transfer block with a 'Stop - Length Invalid' completion code.
length essentially ends up being set to the requested length:urb->actual_length = urb->transfer_buffer_length
Length for 'Stop - Length Invalid' cases should be the sum of all TRB transfer block lengths up to the one the ring stopped on, _excluding_ the one stopped on.
Fix this by always summing up TRB lengths for 'Stop - Length Invalid' bulk cases.
This issue was discovered by Alan Stern while debugging
https://bugzilla.kernel.org/show_bug.cgi?id=218890, but does not solve that bug. Issue is older than 4.10 kernel but fix won't apply to those due to major reworks in that area.
--- drivers/usb/host/xhci-ring.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
drivers/usb/host/xhci-ring.c +2 -3
@@ -2525,9 +2525,8 @@ static int process_bulk_intr_td(struct x goto finish_td;case COMP_STOPPED_LENGTH_INVALID :/* stopped on ep trb with invalid length, exclude it */ - ep_trb_len =0 ; - remaining =0 ; -break ; + td->urb->actual_length =sum_trb_lengths (xhci, ep_ring, ep_trb); + goto finish_td;case COMP_USB_TRANSACTION_ERROR : if (xhci->quirks & XHCI_NO_SOFT_RETRY || (ep->err_count++ > MAX_SOFT_RETRY) ||
Greg Kroah-Hartman
maintainerPATCH 90/267 xhci: Apply reset resume quirk to Etron EJ188 xHCI host
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuangyi Chiang <[email protected]>
commit 17bd54555c2aaecfdb38e2734149f684a73fa584 upstream.
As described in commit c877b3b2ad5c ("xhci: Add reset on resume quirk for asrock p67 host"), EJ188 have the same issue as EJ168, where completely dies on resume. So apply XHCI_RESET_ON_RESUME quirk to EJ188 as well.
--- drivers/usb/host/xhci-pci.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/usb/host/xhci-pci.c +5 -0
@@ -36,6 +36,7 @@#define PCI_VENDOR_ID_ETRON 0x1b6f#define PCI_DEVICE_ID_EJ168 0x7023 +#define PCI_DEVICE_ID_EJ188 0x7052#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
@@ -461,6 +462,10 @@ static void xhci_pci_quirks(struct devic xhci->quirks |=XHCI_TRUST_TX_LENGTH ; xhci->quirks |=XHCI_BROKEN_STREAMS ; } +if (pdev->vendor ==PCI_VENDOR_ID_ETRON && + pdev->device ==PCI_DEVICE_ID_EJ188 ) + xhci->quirks |=XHCI_RESET_ON_RESUME ; +if (pdev->vendor ==PCI_VENDOR_ID_RENESAS && pdev->device ==0x0014 ) { xhci->quirks |=XHCI_TRUST_TX_LENGTH ;
Greg Kroah-Hartman
maintainerPATCH 91/267 xhci: Handle TD clearing for multiple streams case
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hector Martin <[email protected]>
commit 5ceac4402f5d975e5a01c806438eb4e554771577 upstream.
When multiple streams are in use, multiple TDs might be in flight when an endpoint is stopped. We need to issue a Set TR Dequeue Pointer for each, to ensure everything is reset properly and the caches cleared. Change the logic so that any N>1 TDs found active for different streams are deferred until after the first one is processed, calling xhci_invalidate_cancelled_tds() again from xhci_handle_cmd_set_deq() to queue another command until we are done with all of them. Also change the error/"should never happen" paths to ensure we at least clear any affected TDs, even if we can't issue a command to clear the hardware cache, and complain loudly with an xhci_warn() if this ever happens.
This problem case dates back to commit e9df17eb1408 ("USB: xhci: Correct assumptions about number of rings per endpoint.") early on in the XHCI driver's life, when stream support was first added.
It was then identified but not fixed nor made into a warning in commit 674f8438c121 ("xhci: split handling halted endpoints into two steps"), which added a FIXME comment for the problem case (without materially changing the behavior as far as I can tell, though the new logic made the problem more obvious).
Then later, in commit 94f339147fc3 ("xhci: Fix failure to give back some cached cancelled URBs."), it was acknowledged again.
[Mathias: commit 94f339147fc3 ("xhci: Fix failure to give back some cached cancelled URBs.") was a targeted regression fix to the previously mentioned patch. Users reported issues with usb stuck after unmounting/disconnecting UAS devices. This rolled back the TD clearing of multiple streams to its original state.]
Apparently the commit author was aware of the problem (yet still chose to submit it): It was still mentioned as a FIXME, an xhci_dbg() was added to log the problem condition, and the remaining issue was mentioned in the commit description. The choice of making the log type xhci_dbg() for what is, at this point, a completely unhandled and known broken condition is puzzling and unfortunate, as it guarantees that no actual users would see the log in production, thereby making it nigh undebuggable (indeed, even if you turn on DEBUG, the message doesn't really hint at there being a problem at all).
It took me *months* of random xHC crashes to finally find a reliable repro and be able to do a deep dive debug session, which could all have been avoided had this unhandled, broken condition been actually reported with a warning, as it should have been as a bug intentionally left in unfixed (never mind that it shouldn't have been left in at all).
Quoted 2 lines
Another fix to solve clearing the caches of all stream rings with cancelled TDs is needed, but not as urgent.
3 years after that statement and 14 years after the original bug was introduced, I think it's finally time to fix it. And maybe next time let's not leave bugs unfixed (that are actually worse than the original bug), and let's actually get people to review kernel commits please.
Fixes xHC crashes and IOMMU faults with UAS devices when handling errors/faults. Easiest repro is to use hdparm to mark an early sector (e.g. 1024) on a disk as bad, then cat /dev/sdX > /dev/null in a loop. At least in the case of JMicron controllers, the read errors end up having to cancel two TDs (for two queued requests to different streams) and the one that didn't get cleared properly ends up faulting the xHC entirely when it tries to access DMA pages that have since been unmapped, referred to by the stale TDs. This normally happens quickly (after two or three loops). After this fix, I left the cat in a loop running overnight and experienced no xHC failures, with all read errors recovered properly. Repro'd and tested on an Apple M1 Mac Mini (dwc3 host).
On systems without an IOMMU, this bug would instead silently corrupt freed memory, making this a security bug (even on systems with IOMMUs this could silently corrupt memory belonging to other USB devices on the same controller, so it's still a security bug). Given that the kernel autoprobes partition tables, I'm pretty sure a malicious USB device pretending to be a UAS device and reporting an error with the right timing could deliberately trigger a UAF and write to freed memory, with no user action.
[Mathias: Commit message and code comment edit, original at:]
https://lore.kernel.org/linux-usb/[email protected]/
--- drivers/usb/host/xhci-ring.c | 54 ++++++++++++++++++++++++++++++++++--------- drivers/usb/host/xhci.h | 1 2 files changed, 44 insertions(+), 11 deletions(-)
drivers/usb/host/xhci-ring.c +43 -11
@@ -1027,13 +1027,27 @@ static int xhci_invalidate_cancelled_tdsbreak ;case TD_DIRTY :/* TD is cached, clear it */ case TD_HALTED : +case TD_CLEARING_CACHE_DEFERRED : +if (cached_td) { +if (cached_td->urb->stream_id != td->urb->stream_id) { +/* Multiple streams case, defer move dq */ +xhci_dbg (xhci, +"Move dq deferred: stream %u URB %p\n" , + td->urb->stream_id, td->urb); + td->cancel_status =TD_CLEARING_CACHE_DEFERRED ; +break ; + } + +/* Should never happen, but clear the TD if it does */ +xhci_warn (xhci, +"Found multiple active URBs %p and %p in stream %u?\n" , + td->urb, cached_td->urb, + td->urb->stream_id); +td_to_noop (xhci, ring, cached_td, false); + cached_td->cancel_status =TD_CLEARED ; + } + td->cancel_status =TD_CLEARING_CACHE ; -if (cached_td) -/* FIXME stream case, several stopped rings */ -xhci_dbg (xhci, -"Move dq past stream %u URB %p instead of stream %u URB %p\n" , - td->urb->stream_id, td->urb, - cached_td->urb->stream_id, cached_td->urb); cached_td = td;break ; }
@@ -1053,10 +1067,16 @@ static int xhci_invalidate_cancelled_tdsif (err) {/* Failed to move past cached td, just set cached TDs to no-op */ list_for_each_entry_safe (td, tmp_td, &ep->cancelled_td_list, cancelled_td_list) { -if (td->cancel_status !=TD_CLEARING_CACHE ) +/* +* Deferred TDs need to have the deq pointer set after the above command +* completes, so if that failed we just give up on all of them (and +* complain loudly since this could cause issues due to caching). +*/ +if (td->cancel_status !=TD_CLEARING_CACHE && + td->cancel_status !=TD_CLEARING_CACHE_DEFERRED )continue ; -xhci_dbg (xhci,"Failed to clear cancelled cached URB %p, mark clear anyway\n" , - td->urb); +xhci_warn (xhci,"Failed to clear cancelled cached URB %p, mark clear anyway\n" , + td->urb);td_to_noop (xhci, ring, td, false); td->cancel_status =TD_CLEARED ; }
@@ -1334,6 +1354,7 @@ static void xhci_handle_cmd_set_deq(strustruct xhci_ep_ctx *ep_ctx;struct xhci_slot_ctx *slot_ctx;struct xhci_td *td, *tmp_td; +bool deferred = false; ep_index =TRB_TO_EP_INDEX (le32_to_cpu (trb->generic.field[3 ])); stream_id =TRB_TO_STREAM_ID (le32_to_cpu (trb->generic.field[2 ]));
@@ -1420,6 +1441,8 @@ static void xhci_handle_cmd_set_deq(struxhci_dbg (ep->xhci,"%s: Giveback cancelled URB %p TD\n" , __func__, td->urb);xhci_td_cleanup (ep->xhci, td, ep_ring, td->status); + }else if (td->cancel_status ==TD_CLEARING_CACHE_DEFERRED ) { + deferred = true; }else {xhci_dbg (ep->xhci,"%s: Keep cancelled URB %p TD as cancel_status is %d\n" , __func__, td->urb, td->cancel_status);
@@ -1429,8 +1452,17 @@ cleanup: ep->ep_state &= ~SET_DEQ_PENDING ; ep->queued_deq_seg =NULL ; ep->queued_deq_ptr =NULL ; -/* Restart any rings with pending URBs */ -ring_doorbell_for_active_rings (xhci, slot_id, ep_index); + +if (deferred) { +/* We have more streams to clear */ +xhci_dbg (ep->xhci,"%s: Pending TDs to clear, continuing with invalidation\n" , + __func__); +xhci_invalidate_cancelled_tds (ep); + }else { +/* Restart any rings with pending URBs */ +xhci_dbg (ep->xhci,"%s: All TDs cleared, ring doorbell\n" , __func__); +ring_doorbell_for_active_rings (xhci, slot_id, ep_index); + } } static void xhci_handle_cmd_reset_ep(struct xhci_hcd *xhci, int slot_id,
drivers/usb/host/xhci.h +1 -0
@@ -1559,6 +1559,7 @@ enum xhci_cancelled_td_status {TD_DIRTY =0 ,TD_HALTED ,TD_CLEARING_CACHE , +TD_CLEARING_CACHE_DEFERRED , TD_CLEARED, };
Greg Kroah-Hartman
maintainerPATCH 92/267 xhci: Apply broken streams quirk to Etron EJ188 xHCI host
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuangyi Chiang <[email protected]>
commit 91f7a1524a92c70ffe264db8bdfa075f15bbbeb9 upstream.
As described in commit 8f873c1ff4ca ("xhci: Blacklist using streams on the Etron EJ168 controller"), EJ188 have the same issue as EJ168, where Streams do not work reliable on EJ188. So apply XHCI_BROKEN_STREAMS quirk to EJ188 as well.
--- drivers/usb/host/xhci-pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/usb/host/xhci-pci.c +3 -1
@@ -463,8 +463,10 @@ static void xhci_pci_quirks(struct devic xhci->quirks |=XHCI_BROKEN_STREAMS ; }if (pdev->vendor ==PCI_VENDOR_ID_ETRON && - pdev->device ==PCI_DEVICE_ID_EJ188 ) + pdev->device ==PCI_DEVICE_ID_EJ188 ) { xhci->quirks |=XHCI_RESET_ON_RESUME ; + xhci->quirks |=XHCI_BROKEN_STREAMS ; + }if (pdev->vendor ==PCI_VENDOR_ID_RENESAS && pdev->device ==0x0014 ) {
Greg Kroah-Hartman
maintainerPATCH 93/267 thunderbolt: debugfs: Fix margin debugfs node creation condition
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aapo Vienamo <[email protected]>
commit 985cfe501b74f214905ab4817acee0df24627268 upstream.
The margin debugfs node controls the "Enable Margin Test" field of the lane margining operations. This field selects between either low or high voltage margin values for voltage margin test or left or right timing margin values for timing margin test.
According to the USB4 specification, whether or not the "Enable Margin Test" control applies, depends on the values of the "Independent High/Low Voltage Margin" or "Independent Left/Right Timing Margin" capability fields for voltage and timing margin tests respectively. The pre-existing condition enabled the debugfs node also in the case where both low/high or left/right margins are returned, which is incorrect. This change only enables the debugfs node in question, if the specific required capability values are met.
--- drivers/thunderbolt/debugfs.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/thunderbolt/debugfs.c +3 -2
@@ -943,8 +943,9 @@ static void margining_port_init(struct tdebugfs_create_file ("run" ,0600 , dir, port, &margining_run_fops);debugfs_create_file ("results" ,0600 , dir, port, &margining_results_fops);debugfs_create_file ("test" ,0600 , dir, port, &margining_test_fops); -if (independent_voltage_margins (usb4) || - (supports_time (usb4) &&independent_time_margins (usb4))) +if (independent_voltage_margins (usb4) ==USB4_MARGIN_CAP_0_VOLTAGE_HL || + (supports_time (usb4) && +independent_time_margins (usb4) ==USB4_MARGIN_CAP_1_TIME_LR ))debugfs_create_file ("margin" ,0600 , dir, port, &margining_margin_fops); }
Greg Kroah-Hartman
maintainerPATCH 94/267 scsi: core: Disable CDL by default
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal <[email protected]>
commit 52912ca87e2b810e5acdcdc452593d30c9187d8f upstream.
For SCSI devices supporting the Command Duration Limits feature set, the user can enable/disable this feature use through the sysfs device attribute "cdl_enable". This attribute modification triggers a call to scsi_cdl_enable() to enable and disable the feature for ATA devices and set the scsi device cdl_enable field to the user provided bool value. For SCSI devices supporting CDL, the feature set is always enabled and scsi_cdl_enable() is reduced to setting the cdl_enable field.
However, for ATA devices, a drive may spin-up with the CDL feature enabled by default. But the SCSI device cdl_enable field is always initialized to false (CDL disabled), regardless of the actual device CDL feature state. For ATA devices managed by libata (or libsas), libata-core always disables the CDL feature set when the device is attached, thus syncing the state of the CDL feature on the device and of the SCSI device cdl_enable field. However, for ATA devices connected to a SAS HBA, the CDL feature is not disabled on scan for ATA devices that have this feature enabled by default, leading to an inconsistent state of the feature on the device with the SCSI device cdl_enable field.
Avoid this inconsistency by adding a call to scsi_cdl_enable() in scsi_cdl_check() to make sure that the device-side state of the CDL feature set always matches the scsi device cdl_enable field state. This implies that CDL will always be disabled for ATA devices connected to SAS HBAs, which is consistent with libata/libsas initialization of the device.
--- drivers/scsi/scsi.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/scsi/scsi.c +7 -0
@@ -671,6 +671,13 @@ void scsi_cdl_check(struct scsi_device * sdev->use_10_for_rw =0 ; sdev->cdl_supported =1 ; + +/* +* If the device supports CDL, make sure that the current drive +* feature status is consistent with the user controlled +* cdl_enable state. +*/ +scsi_cdl_enable (sdev, sdev->cdl_enable); }else { sdev->cdl_supported =0 ; }
Greg Kroah-Hartman
maintainerPATCH 95/267 scsi: mpi3mr: Fix ATA NCQ priority support
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal <[email protected]>
commit 90e6f08915ec6efe46570420412a65050ec826b2 upstream.
The function mpi3mr_qcmd() of the mpi3mr driver is able to indicate to the HBA if a read or write command directed at an ATA device should be translated to an NCQ read/write command with the high prioiryt bit set when the request uses the RT priority class and the user has enabled NCQ priority through sysfs.
However, unlike the mpt3sas driver, the mpi3mr driver does not define the sas_ncq_prio_supported and sas_ncq_prio_enable sysfs attributes, so the ncq_prio_enable field of struct mpi3mr_sdev_priv_data is never actually set and NCQ Priority cannot ever be used.
Fix this by defining these missing atributes to allow a user to check if an ATA device supports NCQ priority and to enable/disable the use of NCQ priority. To do this, lift the function scsih_ncq_prio_supp() out of the mpt3sas driver and make it the generic SCSI SAS transport function sas_ata_ncq_prio_supported(). Nothing in that function is hardware specific, so this function can be used in both the mpt3sas driver and the mpi3mr driver.
--- drivers/scsi/mpi3mr/mpi3mr_app.c | 62 +++++++++++++++++++++++++++++++++++ drivers/scsi/mpt3sas/mpt3sas_base.h | 3 - drivers/scsi/mpt3sas/mpt3sas_ctl.c | 4 +- drivers/scsi/mpt3sas/mpt3sas_scsih.c | 23 ------------ drivers/scsi/scsi_transport_sas.c | 23 ++++++++++++ include/scsi/scsi_transport_sas.h | 2 + 6 files changed, 89 insertions(+), 28 deletions(-)
drivers/scsi/mpi3mr/mpi3mr_app.c +62 -0
@@ -1854,10 +1854,72 @@ persistent_id_show(struct device *dev, s }static DEVICE_ATTR_RO (persistent_id); +/** +* sas_ncq_prio_supported_show - Indicate if device supports NCQ priority +* @dev: pointer to embedded device +* @attr: sas_ncq_prio_supported attribute descriptor +* @buf: the buffer returned +* +* A sysfs 'read-only' sdev attribute, only works with SATA devices +*/ +static ssize_t +sas_ncq_prio_supported_show (struct device *dev, +struct device_attribute *attr,char *buf) +{ +struct scsi_device *sdev =to_scsi_device (dev); + +return sysfs_emit (buf,"%d\n" ,sas_ata_ncq_prio_supported (sdev)); +} +static DEVICE_ATTR_RO (sas_ncq_prio_supported); + +/** +* sas_ncq_prio_enable_show - send prioritized io commands to device +* @dev: pointer to embedded device +* @attr: sas_ncq_prio_enable attribute descriptor +* @buf: the buffer returned +* +* A sysfs 'read/write' sdev attribute, only works with SATA devices +*/ +static ssize_t +sas_ncq_prio_enable_show (struct device *dev, +struct device_attribute *attr,char *buf) +{ +struct scsi_device *sdev =to_scsi_device (dev); +struct mpi3mr_sdev_priv_data *sdev_priv_data = sdev->hostdata; + +if (!sdev_priv_data) +return 0 ; + +return sysfs_emit (buf,"%d\n" , sdev_priv_data->ncq_prio_enable); +} + +static ssize_t +sas_ncq_prio_enable_store (struct device *dev, +struct device_attribute *attr, +const char *buf,size_t count) +{ +struct scsi_device *sdev =to_scsi_device (dev); +struct mpi3mr_sdev_priv_data *sdev_priv_data = sdev->hostdata; +bool ncq_prio_enable =0 ; + +if (kstrtobool (buf, &ncq_prio_enable)) +return -EINVAL ; + +if (!sas_ata_ncq_prio_supported (sdev)) +return -EINVAL ; + + sdev_priv_data->ncq_prio_enable = ncq_prio_enable; + +return strlen (buf); +} +static DEVICE_ATTR_RW (sas_ncq_prio_enable); +static struct attribute *mpi3mr_dev_attrs[] = { &dev_attr_sas_address.attr, &dev_attr_device_handle.attr, &dev_attr_persistent_id.attr, + &dev_attr_sas_ncq_prio_supported.attr, + &dev_attr_sas_ncq_prio_enable.attr,NULL , };
drivers/scsi/mpt3sas/mpt3sas_base.h +0 -3
@@ -2045,9 +2045,6 @@ void mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, struct _raid_device *raid_device, Mpi25SCSIIORequest_t *mpi_request); -/* NCQ Prio Handling Check */ -bool scsih_ncq_prio_supp (struct scsi_device *sdev); -void mpt3sas_setup_debugfs (struct MPT3SAS_ADAPTER *ioc);void mpt3sas_destroy_debugfs (struct MPT3SAS_ADAPTER *ioc);void mpt3sas_init_debugfs (void );
drivers/scsi/mpt3sas/mpt3sas_ctl.c +2 -2
@@ -4034,7 +4034,7 @@ sas_ncq_prio_supported_show(struct devic {struct scsi_device *sdev =to_scsi_device (dev); -return sysfs_emit (buf,"%d\n" ,scsih_ncq_prio_supp (sdev)); +return sysfs_emit (buf,"%d\n" ,sas_ata_ncq_prio_supported (sdev)); }static DEVICE_ATTR_RO (sas_ncq_prio_supported);
@@ -4069,7 +4069,7 @@ sas_ncq_prio_enable_store(struct deviceif (kstrtobool (buf, &ncq_prio_enable))return -EINVAL ; -if (!scsih_ncq_prio_supp (sdev)) +if (!sas_ata_ncq_prio_supported (sdev))return -EINVAL ; sas_device_priv_data->ncq_prio_enable = ncq_prio_enable;
drivers/scsi/mpt3sas/mpt3sas_scsih.c +0 -23
@@ -12590,29 +12590,6 @@ scsih_pci_mmio_enabled(struct pci_dev *preturn PCI_ERS_RESULT_RECOVERED ; } -/** -* scsih_ncq_prio_supp - Check for NCQ command priority support -* @sdev: scsi device struct -* -* This is called when a user indicates they would like to enable -* ncq command priorities. This works only on SATA devices. -*/ -bool scsih_ncq_prio_supp (struct scsi_device *sdev) -{ -struct scsi_vpd *vpd; -bool ncq_prio_supp = false; - -rcu_read_lock (); - vpd =rcu_dereference (sdev->vpd_pg89); -if (!vpd || vpd->len <214 ) - goto out; - - ncq_prio_supp = (vpd->data[213 ] >>4 ) &1 ; -out: -rcu_read_unlock (); - -return ncq_prio_supp; -}/* * The pci device ids are defined in mpi/mpi2_cnfg.h. */
drivers/scsi/scsi_transport_sas.c +23 -0
@@ -416,6 +416,29 @@ unsigned int sas_is_tlr_enabled(struct s }EXPORT_SYMBOL_GPL (sas_is_tlr_enabled); +/** +* sas_ata_ncq_prio_supported - Check for ATA NCQ command priority support +* @sdev: SCSI device +* +* Check if an ATA device supports NCQ priority using VPD page 89h (ATA +* Information). Since this VPD page is implemented only for ATA devices, +* this function always returns false for SCSI devices. +*/ +bool sas_ata_ncq_prio_supported (struct scsi_device *sdev) +{ +struct scsi_vpd *vpd; +bool ncq_prio_supported = false; + +rcu_read_lock (); + vpd =rcu_dereference (sdev->vpd_pg89); +if (vpd && vpd->len >=214 ) + ncq_prio_supported = (vpd->data[213 ] >>4 ) &1 ; +rcu_read_unlock (); + +return ncq_prio_supported; +} +EXPORT_SYMBOL_GPL (sas_ata_ncq_prio_supported); +/* * SAS Phy attributes */
include/scsi/scsi_transport_sas.h +2 -0
@@ -200,6 +200,8 @@ unsigned int sas_is_tlr_enabled(struct svoid sas_disable_tlr (struct scsi_device *);void sas_enable_tlr (struct scsi_device *); +bool sas_ata_ncq_prio_supported (struct scsi_device *sdev); +extern struct sas_rphy *sas_end_device_alloc (struct sas_port *);extern struct sas_rphy *sas_expander_alloc (struct sas_port *,enum sas_device_type );void sas_rphy_free (struct sas_rphy *);
Greg Kroah-Hartman
maintainerPATCH 96/267 scsi: mpt3sas: Avoid test/set_bit() operating in non-allocated memory
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Breno Leitao <[email protected]>
commit 4254dfeda82f20844299dca6c38cbffcfd499f41 upstream.
There is a potential out-of-bounds access when using test_bit() on a single word. The test_bit() and set_bit() functions operate on long values, and when testing or setting a single word, they can exceed the word boundary. KASAN detects this issue and produces a dump:
BUG: KASAN: slab-out-of-bounds in _scsih_add_device.constprop.0 (./arch/x86/include/asm/bitops.h:60 ./include/asm-generic/bitops/instrumented-atomic.h:29 drivers/scsi/mpt3sas/mpt3sas_scsih.c:7331) mpt3sas Write of size 8 at addr ffff8881d26e3c60 by task kworker/u1536:2/2965
For full log, please look at [1].
Make the allocation at least the size of sizeof(unsigned long) so that set_bit() and test_bit() have sufficient room for read/write operations without overwriting unallocated memory.
[1] Link: https://lore.kernel.org/all/[email protected]/
--- drivers/scsi/mpt3sas/mpt3sas_base.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
drivers/scsi/mpt3sas/mpt3sas_base.c +19 -0
@@ -8486,6 +8486,12 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPT ioc->pd_handles_sz = (ioc->facts.MaxDevHandle /8 );if (ioc->facts.MaxDevHandle %8 ) ioc->pd_handles_sz++; +/* +* pd_handles_sz should have, at least, the minimal room for +* set_bit()/test_bit(), otherwise out-of-memory touch may occur. +*/ + ioc->pd_handles_sz =ALIGN (ioc->pd_handles_sz,sizeof (unsigned long )); + ioc->pd_handles =kzalloc (ioc->pd_handles_sz,GFP_KERNEL );if (!ioc->pd_handles) {
@@ -8503,6 +8509,13 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPT ioc->pend_os_device_add_sz = (ioc->facts.MaxDevHandle /8 );if (ioc->facts.MaxDevHandle %8 ) ioc->pend_os_device_add_sz++; + +/* +* pend_os_device_add_sz should have, at least, the minimal room for +* set_bit()/test_bit(), otherwise out-of-memory may occur. +*/ + ioc->pend_os_device_add_sz =ALIGN (ioc->pend_os_device_add_sz, +sizeof (unsigned long )); ioc->pend_os_device_add =kzalloc (ioc->pend_os_device_add_sz,GFP_KERNEL );if (!ioc->pend_os_device_add) {
@@ -8794,6 +8807,12 @@ _base_check_ioc_facts_changes(struct MPTif (ioc->facts.MaxDevHandle %8 ) pd_handles_sz++; +/* +* pd_handles should have, at least, the minimal room for +* set_bit()/test_bit(), otherwise out-of-memory touch may +* occur. +*/ + pd_handles_sz =ALIGN (pd_handles_sz,sizeof (unsigned long )); pd_handles =krealloc (ioc->pd_handles, pd_handles_sz,GFP_KERNEL );if (!pd_handles) {
Greg Kroah-Hartman
maintainerPATCH 97/267 scsi: sd: Use READ(16) when reading block zero on large capacity disks
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Martin K. Petersen <[email protected]>
commit 7926d51f73e0434a6250c2fd1a0555f98d9a62da upstream.
Commit 321da3dc1f3c ("scsi: sd: usb_storage: uas: Access media prior to querying device properties") triggered a read to LBA 0 before attempting to inquire about device characteristics. This was done because some protocol bridge devices will return generic values until an attached storage device's media has been accessed.
Pierre Tomon reported that this change caused problems on a large capacity external drive connected via a bridge device. The bridge in question does not appear to implement the READ(10) command.
Issue a READ(16) instead of READ(10) when a device has been identified as preferring 16-byte commands (use_16_for_rw heuristic).
--- drivers/scsi/sd.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/scsi/sd.c +12 -5
@@ -3406,16 +3406,23 @@ static bool sd_validate_opt_xfer_size(ststatic void sd_read_block_zero (struct scsi_disk *sdkp) { -unsigned int buf_len = sdkp->device->sector_size; -char *buffer, cmd[10 ] = { }; +struct scsi_device *sdev = sdkp->device; +unsigned int buf_len = sdev->sector_size; +u8 *buffer, cmd[16 ] = { }; buffer =kmalloc (buf_len,GFP_KERNEL );if (!buffer)return ; - cmd[0 ] =READ_10 ; -put_unaligned_be32 (0 , &cmd[2 ]);/* Logical block address 0 */ -put_unaligned_be16 (1 , &cmd[7 ]);/* Transfer 1 logical block */ +if (sdev->use_16_for_rw) { + cmd[0 ] =READ_16 ; +put_unaligned_be64 (0 , &cmd[2 ]);/* Logical block address 0 */ +put_unaligned_be32 (1 , &cmd[10 ]);/* Transfer 1 logical block */ + }else { + cmd[0 ] =READ_10 ; +put_unaligned_be32 (0 , &cmd[2 ]);/* Logical block address 0 */ +put_unaligned_be16 (1 , &cmd[7 ]);/* Transfer 1 logical block */ + }scsi_execute_cmd (sdkp->device, cmd,REQ_OP_DRV_IN , buffer, buf_len,SD_TIMEOUT , sdkp->max_retries,NULL );
Greg Kroah-Hartman
maintainerPATCH 98/267 gve: Clear napi->skb before dev_kfree_skb_any()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ziwei Xiao <[email protected]>
commit 6f4d93b78ade0a4c2cafd587f7b429ce95abb02e upstream.
gve_rx_free_skb incorrectly leaves napi->skb referencing an skb after it is freed with dev_kfree_skb_any(). This can result in a subsequent call to napi_get_frags returning a dangling pointer.
Fix this by clearing napi->skb before the skb is freed.
--- drivers/net/ethernet/google/gve/gve_rx_dqo.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/net/ethernet/google/gve/gve_rx_dqo.c +5 -3
@@ -506,11 +506,13 @@ static void gve_rx_skb_hash(struct sk_buskb_set_hash (skb,le32_to_cpu (compl_desc->hash), hash_type); } -static void gve_rx_free_skb (struct gve_rx_ring *rx) +static void gve_rx_free_skb (struct napi_struct *napi,struct gve_rx_ring *rx) {if (!rx->ctx.skb_head)return ; +if (rx->ctx.skb_head == napi->skb) + napi->skb =NULL ;dev_kfree_skb_any (rx->ctx.skb_head); rx->ctx.skb_head =NULL ; rx->ctx.skb_tail =NULL ;
@@ -783,7 +785,7 @@ int gve_rx_poll_dqo(struct gve_notify_bl err =gve_rx_dqo (napi, rx, compl_desc, rx->q_num);if (err <0 ) { -gve_rx_free_skb (rx); +gve_rx_free_skb (napi, rx);u64_stats_update_begin (&rx->statss);if (err == -ENOMEM ) rx->rx_skb_alloc_fail++;
@@ -826,7 +828,7 @@ int gve_rx_poll_dqo(struct gve_notify_bl/* gve_rx_complete_skb() will consume skb if successful */ if (gve_rx_complete_skb (rx, napi, compl_desc, feat) !=0 ) { -gve_rx_free_skb (rx); +gve_rx_free_skb (napi, rx);u64_stats_update_begin (&rx->statss); rx->rx_desc_err_dropped_pkt++;u64_stats_update_end (&rx->statss);
Greg Kroah-Hartman
maintainerPATCH 99/267 powerpc/uaccess: Fix build errors seen with GCC 13/14
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Ellerman <[email protected]>
commit 2d43cc701b96f910f50915ac4c2a0cae5deb734c upstream.
Building ppc64le_defconfig with GCC 14 fails with assembler errors:
CC fs/readdir.o
/tmp/ccdQn0mD.s: Assembler messages:
/tmp/ccdQn0mD.s:212: Error: operand out of domain (18 is not a multiple of 4) /tmp/ccdQn0mD.s:226: Error: operand out of domain (18 is not a multiple of 4) ... [6 lines]
/tmp/ccdQn0mD.s:1699: Error: operand out of domain (18 is not a multiple of 4)
A snippet of the asm shows:
# ../fs/readdir.c:210: unsafe_copy_dirent_name(dirent->d_name, name, namlen, efault_end);
ld 9,0(29) # MEM[(u64 *)name_38(D) + _88 * 1], MEM[(u64 *)name_38(D) + _88 * 1]
# 210 "../fs/readdir.c" 1
1: std 9,18(8) # put_user # *__pus_addr_52, MEM[(u64 *)name_38(D) + _88 * 1]The 'std' instruction requires a 4-byte aligned displacement because it is a DS-form instruction, and as the assembler says, 18 is not a multiple of 4.
A similar error is seen with GCC 13 and CONFIG_UBSAN_SIGNED_WRAP=y.
The fix is to change the constraint on the memory operand to put_user(), from "m" which is a general memory reference to "YZ".
The "Z" constraint is documented in the GCC manual PowerPC machine constraints, and specifies a "memory operand accessed with indexed or indirect addressing". "Y" is not documented in the manual but specifies a "memory operand for a DS-form instruction". Using both allows the compiler to generate a DS-form "std" or X-form "stdx" as appropriate.
The change has to be conditional on CONFIG_PPC_KERNEL_PREFIXED because the "Y" constraint does not guarantee 4-byte alignment when prefixed instructions are enabled.
Unfortunately clang doesn't support the "Y" constraint so that has to be behind an ifdef.
Although the build error is only seen with GCC 13/14, that appears to just be luck. The constraint has been incorrect since it was first added.
--- arch/powerpc/include/asm/uaccess.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
arch/powerpc/include/asm/uaccess.h +16 -0
@@ -92,9 +92,25 @@ __pu_failed: \ : label)#endif +#ifdef CONFIG_CC_IS_CLANG +#define DS_FORM_CONSTRAINT "Z<>" +#else +#define DS_FORM_CONSTRAINT "YZ<>" +#endif +#ifdef __powerpc64__ +#ifdef CONFIG_PPC_KERNEL_PREFIXED #define __put_user_asm2_goto (x, ptr, label) \ __put_user_asm_goto(x, ptr, label, "std") +#else +#define __put_user_asm2_goto (x, addr, label) \ + asm goto ("1: std%U1%X1 %0,%1 # put_user\n" \ + EX_TABLE(1b, %l2) \ + : \ + : "r" (x), DS_FORM_CONSTRAINT (*addr) \ + : \ + : label) +#endif // CONFIG_PPC_KERNEL_PREFIXED #else /* __powerpc64__ */ #define __put_user_asm2_goto (x, addr, label) \ asm goto( \
Greg Kroah-Hartman
maintainerPATCH 100/267 HID: nvidia-shield: Add missing check for input_ff_create_memless
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Ni <[email protected]>
[ Upstream commit 0a3f9f7fc59feb8a91a2793b8b60977895c72365 ]
Add check for the return value of input_ff_create_memless() and return the error if it fails in order to catch the error.
--- drivers/hid/hid-nvidia-shield.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/hid/hid-nvidia-shield.c +3 -1
@@ -283,7 +283,9 @@ static struct input_dev *shield_haptics_create(return haptics;input_set_capability (haptics,EV_FF ,FF_RUMBLE ); -input_ff_create_memless (haptics,NULL , play_effect); + ret =input_ff_create_memless (haptics,NULL , play_effect); +if (ret) + goto err; ret =input_register_device (haptics);if (ret)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 101/267 cxl/test: Add missing vmalloc.h for tools/testing/cxl/test/mem.c
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dave Jiang <[email protected]>
[ Upstream commit d55510527153d17a3af8cc2df69c04f95ae1350d ]
tools/testing/cxl/test/mem.c uses vmalloc() and vfree() but does not include linux/vmalloc.h. Kernel v6.10 made changes that causes the currently included headers not depend on vmalloc.h and therefore mem.c can no longer compile. Add linux/vmalloc.h to fix compile issue.
CC [M] tools/testing/cxl/test/mem.otools/testing/cxl/test/mem.c: In function ‘label_area_release’:tools/testing/cxl/test/mem.c:1428:9: error: implicit declaration of function ‘vfree’; did you mean ‘kvfree’? [-Werror=implicit-function-declaration]
1428 | vfree(lsa);
| ^~~~~
| kvfree
tools/testing/cxl/test/mem.c: In function ‘cxl_mock_mem_probe’:
tools/testing/cxl/test/mem.c:1466:22: error: implicit declaration of function ‘vmalloc’; did you mean ‘kmalloc’? [-Werror=implicit-function-declaration]
1466 | mdata->lsa = vmalloc(LSA_SIZE);
| ^~~~~~~
| kmalloc--- tools/testing/cxl/test/mem.c | 1 + 1 file changed, 1 insertion(+)
tools/testing/cxl/test/mem.c +1 -0
@@ -3,6 +3,7 @@#include <linux/platform_device.h> #include <linux/mod_devicetable.h> +#include <linux/vmalloc.h> #include <linux/module.h> #include <linux/delay.h> #include <linux/sizes.h>
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 102/267 cxl/region: Fix memregion leaks in devm_cxl_add_region()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Zhijian <[email protected]>
[ Upstream commit 49ba7b515c4c0719b866d16f068e62d16a8a3dd1 ]
Move the mode verification to __create_region() before allocating the memregion to avoid the memregion leaks.
--- drivers/cxl/core/region.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-)
drivers/cxl/core/region.c +9 -9
@@ -2186,15 +2186,6 @@ static struct cxl_region *devm_cxl_add_region(struct cxl_root_decoder *cxlrd,struct device *dev;int rc; -switch (mode) { -case CXL_DECODER_RAM : -case CXL_DECODER_PMEM : -break ; -default : -dev_err (&cxlrd->cxlsd.cxld.dev,"unsupported mode %d\n" , mode); -return ERR_PTR (-EINVAL ); - } - cxlr =cxl_region_alloc (cxlrd, id);if (IS_ERR (cxlr))return cxlr;
@@ -2245,6 +2236,15 @@ static struct cxl_region *__create_region(struct cxl_root_decoder *cxlrd, {int rc; +switch (mode) { +case CXL_DECODER_RAM : +case CXL_DECODER_PMEM : +break ; +default : +dev_err (&cxlrd->cxlsd.cxld.dev,"unsupported mode %d\n" , mode); +return ERR_PTR (-EINVAL ); + } + rc =memregion_alloc (GFP_KERNEL );if (rc <0 )return ERR_PTR (rc);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 103/267 cachefiles: add output string to cachefiles_obj_[get|put]_ondemand_fd
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
[ Upstream commit cc5ac966f26193ab185cc43d64d9f1ae998ccb6e ]
This lets us see the correct trace output.
--- include/trace/events/cachefiles.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
include/trace/events/cachefiles.h +3 -1
@@ -127,7 +127,9 @@ enum cachefiles_error_trace { EM(cachefiles_obj_see_lookup_cookie, "SEE lookup_cookie") \ EM(cachefiles_obj_see_lookup_failed, "SEE lookup_failed") \ EM(cachefiles_obj_see_withdraw_cookie, "SEE withdraw_cookie") \ - E_(cachefiles_obj_see_withdrawal, "SEE withdrawal") + EM(cachefiles_obj_see_withdrawal, "SEE withdrawal") \ + EM(cachefiles_obj_get_ondemand_fd, "GET ondemand_fd") \ + E_(cachefiles_obj_put_ondemand_fd, "PUT ondemand_fd")#define cachefiles_coherency_traces \ EM(cachefiles_coherency_check_aux, "BAD aux ") \
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 104/267 cachefiles: remove requests from xarray during flushing requests
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
[ Upstream commit 0fc75c5940fa634d84e64c93bfc388e1274ed013 ]
Even with CACHEFILES_DEAD set, we can still read the requests, so in the following concurrency the request may be used after it has been freed:
mount | daemon_thread1 | daemon_thread2
------------------------------------------------------------
cachefiles_ondemand_init_object
cachefiles_ondemand_send_req
REQ_A = kzalloc(sizeof(*req) + data_len)
wait_for_completion(&REQ_A->done)
cachefiles_daemon_read
cachefiles_ondemand_daemon_read
// close dev fd
cachefiles_flush_reqs
complete(&REQ_A->done)
kfree(REQ_A)
xa_lock(&cache->reqs);
cachefiles_ondemand_select_req
req->msg.opcode != CACHEFILES_OP_READ
// req use-after-free !!!
xa_unlock(&cache->reqs);
xa_destroy(&cache->reqs)Hence remove requests from cache->reqs when flushing them to avoid accessing freed requests.
--- fs/cachefiles/daemon.c | 1 + 1 file changed, 1 insertion(+)
fs/cachefiles/daemon.c +1 -0
@@ -158,6 +158,7 @@ static void cachefiles_flush_reqs(struct cachefiles_cache *cache)xa_for_each (xa, index, req) { req->error = -EIO ;complete (&req->done); +__xa_erase (xa, index); }xa_unlock (xa);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 105/267 cachefiles: introduce object ondemand state
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jia Zhu <[email protected]>
[ Upstream commit 357a18d033143617e9c7d420c8f0dd4cbab5f34d ]
Previously, @ondemand_id field was used not only to identify ondemand state of the object, but also to represent the index of the xarray. This commit introduces @state field to decouple the role of @ondemand_id and adds helpers to access it.
Stable-dep-of: 0a790040838c ("cachefiles: add spin_lock for cachefiles_ondemand_info")
--- fs/cachefiles/internal.h | 21 +++++++++++++++++++++ fs/cachefiles/ondemand.c | 21 +++++++++------------ 2 files changed, 30 insertions(+), 12 deletions(-)
fs/cachefiles/internal.h +21 -0
@@ -44,6 +44,11 @@ struct cachefiles_volume {struct dentry *fanout[256 ];/* Fanout subdirs */ }; +enum cachefiles_object_state { +CACHEFILES_ONDEMAND_OBJSTATE_CLOSE ,/* Anonymous fd closed by daemon or initial state */ +CACHEFILES_ONDEMAND_OBJSTATE_OPEN ,/* Anonymous fd associated with object is available */ +}; +/* * Backing file state. */
@@ -62,6 +67,7 @@ struct cachefiles_object {#define CACHEFILES_OBJECT_USING_TMPFILE 0/* Have an unlinked tmpfile */ #ifdef CONFIG_CACHEFILES_ONDEMAND int ondemand_id; +enum cachefiles_object_state state;#endif };
@@ -296,6 +302,21 @@ extern void cachefiles_ondemand_clean_object(struct cachefiles_object *object);extern int cachefiles_ondemand_read (struct cachefiles_object *object,loff_t pos,size_t len); +#define CACHEFILES_OBJECT_STATE_FUNCS (_state, _STATE) \ +static inline bool \ +cachefiles_ondemand_object_is_##_state(const struct cachefiles_object *object) \ +{ \ + return object->state == CACHEFILES_ONDEMAND_OBJSTATE_##_STATE; \ +} \ + \ +static inline void \ +cachefiles_ondemand_set_object_##_state(struct cachefiles_object *object) \ +{ \ + object->state = CACHEFILES_ONDEMAND_OBJSTATE_##_STATE; \ +} + +CACHEFILES_OBJECT_STATE_FUNCS (open,OPEN ); +CACHEFILES_OBJECT_STATE_FUNCS (close,CLOSE );#else static inline ssize_t cachefiles_ondemand_daemon_read (struct cachefiles_cache *cache,char __user *_buffer,size_t buflen)
fs/cachefiles/ondemand.c +9 -12
@@ -15,6 +15,7 @@ static int cachefiles_ondemand_fd_release(struct inode *inode,xa_lock (&cache->reqs); object->ondemand_id =CACHEFILES_ONDEMAND_ID_CLOSED ; +cachefiles_ondemand_set_object_close (object);/* * Flush all pending READ requests since their completion depends on
@@ -176,6 +177,8 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args)set_bit (FSCACHE_COOKIE_NO_DATA_TO_READ , &cookie->flags);trace_cachefiles_ondemand_copen (req->object, id, size); +cachefiles_ondemand_set_object_open (req->object); + out:complete (&req->done);return ret;
@@ -363,7 +366,8 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object,/* coupled with the barrier in cachefiles_flush_reqs() */ smp_mb (); -if (opcode !=CACHEFILES_OP_OPEN && object->ondemand_id <=0 ) { +if (opcode !=CACHEFILES_OP_OPEN && + !cachefiles_ondemand_object_is_open (object)) {WARN_ON_ONCE (object->ondemand_id ==0 );xas_unlock (&xas); ret = -EIO ;
@@ -430,18 +434,11 @@ static int cachefiles_ondemand_init_close_req(struct cachefiles_req *req, void *private) {struct cachefiles_object *object = req->object; -int object_id = object->ondemand_id; -/* -* It's possible that object id is still 0 if the cookie looking up -* phase failed before OPEN request has ever been sent. Also avoid -* sending CLOSE request for CACHEFILES_ONDEMAND_ID_CLOSED, which means -* anon_fd has already been closed. -*/ -if (object_id <=0 ) +if (!cachefiles_ondemand_object_is_open (object))return -ENOENT ; - req->msg.object_id = object_id; + req->msg.object_id = object->ondemand_id;trace_cachefiles_ondemand_close (object, &req->msg);return 0 ; }
@@ -460,7 +457,7 @@ static int cachefiles_ondemand_init_read_req(struct cachefiles_req *req,int object_id = object->ondemand_id;/* Stop enqueuing requests when daemon has closed anon_fd. */ -if (object_id <=0 ) { +if (!cachefiles_ondemand_object_is_open (object)) {WARN_ON_ONCE (object_id ==0 );pr_info_once ("READ: anonymous fd closed prematurely.\n" );return -EIO ;
@@ -485,7 +482,7 @@ int cachefiles_ondemand_init_object(struct cachefiles_object *object)* creating a new tmpfile as the cache file. Reuse the previously * allocated object ID if any. */ -if (object->ondemand_id >0 ) +if (cachefiles_ondemand_object_is_open (object))return 0 ; volume_key_size = volume->key[0 ] +1 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 106/267 cachefiles: extract ondemand info field from cachefiles_object
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jia Zhu <[email protected]>
[ Upstream commit 3c5ecfe16e7699011c12c2d44e55437415331fa3 ]
We'll introduce a @work_struct field for @object in subsequent patches, it will enlarge the size of @object.
As the result of that, this commit extracts ondemand info field from @object.
Stable-dep-of: 0a790040838c ("cachefiles: add spin_lock for cachefiles_ondemand_info")
--- fs/cachefiles/interface.c | 7 ++++++- fs/cachefiles/internal.h | 26 ++++++++++++++++++++++---- fs/cachefiles/ondemand.c | 34 ++++++++++++++++++++++++++++------ 3 files changed, 56 insertions(+), 11 deletions(-)
fs/cachefiles/interface.c +6 -1
@@ -31,6 +31,11 @@ struct cachefiles_object *cachefiles_alloc_object(struct fscache_cookie *cookie)if (!object)return NULL ; +if (cachefiles_ondemand_init_obj_info (object, volume)) { +kmem_cache_free (cachefiles_object_jar, object); +return NULL ; + } +refcount_set (&object->ref,1 );spin_lock_init (&object->lock);
@@ -88,7 +93,7 @@ void cachefiles_put_object(struct cachefiles_object *object, ASSERTCMP(object->file, ==, NULL);kfree (object->d_name); - +cachefiles_ondemand_deinit_obj_info (object); cache = object->volume->cache->cache;fscache_put_cookie (object->cookie, fscache_cookie_put_object); object->cookie =NULL ;
fs/cachefiles/internal.h +22 -4
@@ -49,6 +49,12 @@ enum cachefiles_object_state { CACHEFILES_ONDEMAND_OBJSTATE_OPEN, /* Anonymous fd associated with object is available */ }; +struct cachefiles_ondemand_info { +int ondemand_id; +enum cachefiles_object_state state; +struct cachefiles_object *object; +}; +/* * Backing file state. */
@@ -66,8 +72,7 @@ struct cachefiles_object {unsigned long flags;#define CACHEFILES_OBJECT_USING_TMPFILE 0/* Have an unlinked tmpfile */ #ifdef CONFIG_CACHEFILES_ONDEMAND -int ondemand_id; -enum cachefiles_object_state state; +struct cachefiles_ondemand_info *ondemand;#endif };
@@ -302,17 +307,21 @@ extern void cachefiles_ondemand_clean_object(struct cachefiles_object *object);extern int cachefiles_ondemand_read (struct cachefiles_object *object,loff_t pos,size_t len); +extern int cachefiles_ondemand_init_obj_info (struct cachefiles_object *obj, +struct cachefiles_volume *volume); +extern void cachefiles_ondemand_deinit_obj_info (struct cachefiles_object *obj); +#define CACHEFILES_OBJECT_STATE_FUNCS (_state, _STATE) \ static inline bool \ cachefiles_ondemand_object_is_##_state(const struct cachefiles_object *object) \ { \ - return object->state == CACHEFILES_ONDEMAND_OBJSTATE_##_STATE; \ + return object->ondemand->state == CACHEFILES_ONDEMAND_OBJSTATE_##_STATE; \ } \ \ static inline void \ cachefiles_ondemand_set_object_##_state(struct cachefiles_object *object) \ { \ - object->state = CACHEFILES_ONDEMAND_OBJSTATE_##_STATE; \ + object->ondemand->state = CACHEFILES_ONDEMAND_OBJSTATE_##_STATE; \ }CACHEFILES_OBJECT_STATE_FUNCS (open,OPEN );
@@ -338,6 +347,15 @@ static inline int cachefiles_ondemand_read(struct cachefiles_object *object, {return -EOPNOTSUPP ; } + +static inline int cachefiles_ondemand_init_obj_info (struct cachefiles_object *obj, +struct cachefiles_volume *volume) +{ +return 0 ; +} +static inline void cachefiles_ondemand_deinit_obj_info (struct cachefiles_object *obj) +{ +}#endif /*
fs/cachefiles/ondemand.c +28 -6
@@ -9,12 +9,13 @@ static int cachefiles_ondemand_fd_release(struct inode *inode, {struct cachefiles_object *object = file->private_data;struct cachefiles_cache *cache = object->volume->cache; -int object_id = object->ondemand_id; +struct cachefiles_ondemand_info *info = object->ondemand; +int object_id = info->ondemand_id;struct cachefiles_req *req;XA_STATE (xas, &cache->reqs,0 );xa_lock (&cache->reqs); - object->ondemand_id =CACHEFILES_ONDEMAND_ID_CLOSED ; + info->ondemand_id =CACHEFILES_ONDEMAND_ID_CLOSED ;cachefiles_ondemand_set_object_close (object);/*
@@ -222,7 +223,7 @@ static int cachefiles_ondemand_get_fd(struct cachefiles_req *req) load = (void *)req->msg.data; load->fd = fd; req->msg.object_id = object_id; - object->ondemand_id = object_id; + object->ondemand->ondemand_id = object_id;cachefiles_get_unbind_pincount (cache);trace_cachefiles_ondemand_open (object, &req->msg, load);
@@ -368,7 +369,7 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object,if (opcode !=CACHEFILES_OP_OPEN && !cachefiles_ondemand_object_is_open (object)) { -WARN_ON_ONCE (object->ondemand_id ==0 ); +WARN_ON_ONCE (object->ondemand->ondemand_id ==0 );xas_unlock (&xas); ret = -EIO ; goto out;
@@ -438,7 +439,7 @@ static int cachefiles_ondemand_init_close_req(struct cachefiles_req *req,if (!cachefiles_ondemand_object_is_open (object))return -ENOENT ; - req->msg.object_id = object->ondemand_id; + req->msg.object_id = object->ondemand->ondemand_id;trace_cachefiles_ondemand_close (object, &req->msg);return 0 ; }
@@ -454,7 +455,7 @@ static int cachefiles_ondemand_init_read_req(struct cachefiles_req *req,struct cachefiles_object *object = req->object;struct cachefiles_read *load = (void *)req->msg.data;struct cachefiles_read_ctx *read_ctx = private; -int object_id = object->ondemand_id; +int object_id = object->ondemand->ondemand_id;/* Stop enqueuing requests when daemon has closed anon_fd. */ if (!cachefiles_ondemand_object_is_open (object)) {
@@ -500,6 +501,27 @@ void cachefiles_ondemand_clean_object(struct cachefiles_object *object) cachefiles_ondemand_init_close_req, NULL); } +int cachefiles_ondemand_init_obj_info (struct cachefiles_object *object, +struct cachefiles_volume *volume) +{ +if (!cachefiles_in_ondemand_mode (volume->cache)) +return 0 ; + + object->ondemand =kzalloc (sizeof (struct cachefiles_ondemand_info ), +GFP_KERNEL ); +if (!object->ondemand) +return -ENOMEM ; + + object->ondemand->object = object; +return 0 ; +} + +void cachefiles_ondemand_deinit_obj_info (struct cachefiles_object *object) +{ +kfree (object->ondemand); + object->ondemand =NULL ; +} +int cachefiles_ondemand_read (struct cachefiles_object *object,loff_t pos,size_t len) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 107/267 cachefiles: resend an open request if the read requests object is closed
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jia Zhu <[email protected]>
[ Upstream commit 0a7e54c1959c0feb2de23397ec09c7692364313e ]
When an anonymous fd is closed by user daemon, if there is a new read request for this file comes up, the anonymous fd should be re-opened to handle that read request rather than fail it directly.
1. Introduce reopening state for objects that are closed but have inflight/subsequent read requests.
2. No longer flush READ requests but only CLOSE requests when anonymous fd is closed.
3. Enqueue the reopen work to workqueue, thus user daemon could get rid of daemon_read context and handle that request smoothly. Otherwise, the user daemon will send a reopen request and wait for itself to process the request.
Stable-dep-of: 0a790040838c ("cachefiles: add spin_lock for cachefiles_ondemand_info")
--- fs/cachefiles/internal.h | 3 ++ fs/cachefiles/ondemand.c | 98 ++++++++++++++++++++++++++++------------ 2 files changed, 72 insertions(+), 29 deletions(-)
fs/cachefiles/internal.h +3 -0
@@ -47,9 +47,11 @@ struct cachefiles_volume {enum cachefiles_object_state {CACHEFILES_ONDEMAND_OBJSTATE_CLOSE ,/* Anonymous fd closed by daemon or initial state */ CACHEFILES_ONDEMAND_OBJSTATE_OPEN ,/* Anonymous fd associated with object is available */ +CACHEFILES_ONDEMAND_OBJSTATE_REOPENING ,/* Object that was closed and is being reopened. */ };struct cachefiles_ondemand_info { +struct work_struct ondemand_work;int ondemand_id;enum cachefiles_object_state state;struct cachefiles_object *object;
@@ -326,6 +328,7 @@ cachefiles_ondemand_set_object_##_state(struct cachefiles_object *object) \CACHEFILES_OBJECT_STATE_FUNCS (open,OPEN );CACHEFILES_OBJECT_STATE_FUNCS (close,CLOSE ); +CACHEFILES_OBJECT_STATE_FUNCS (reopening,REOPENING );#else static inline ssize_t cachefiles_ondemand_daemon_read (struct cachefiles_cache *cache,char __user *_buffer,size_t buflen)
fs/cachefiles/ondemand.c +69 -29
194 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 108/267 cachefiles: add spin_lock for cachefiles_ondemand_info
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
[ Upstream commit 0a790040838c736495d5afd6b2d636f159f817f1 ]
The following concurrency may cause a read request to fail to be completed and result in a hung:
t1 | t2
---------------------------------------------------------
cachefiles_ondemand_copen
req = xa_erase(&cache->reqs, id)// Anon fd is maliciously closed.cachefiles_ondemand_fd_release
xa_lock(&cache->reqs)
cachefiles_ondemand_set_object_close(object)
xa_unlock(&cache->reqs)
cachefiles_ondemand_set_object_open
// No one will ever close it again.cachefiles_ondemand_daemon_read
cachefiles_ondemand_select_req
// Get a read req but its fd is already closed.
// The daemon can't issue a cread ioctl with an closed fd, then hung.
So add spin_lock for cachefiles_ondemand_info to protect ondemand_id and state, thus we can avoid the above problem in cachefiles_ondemand_copen() by using ondemand_id to determine if fd has been closed.
--- fs/cachefiles/internal.h | 1 + fs/cachefiles/ondemand.c | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-)
fs/cachefiles/internal.h +1 -0
@@ -55,6 +55,7 @@ struct cachefiles_ondemand_info {int ondemand_id;enum cachefiles_object_state state;struct cachefiles_object *object; +spinlock_t lock; };/*
fs/cachefiles/ondemand.c +34 -1
@@ -10,13 +10,16 @@ static int cachefiles_ondemand_fd_release(struct inode *inode,struct cachefiles_object *object = file->private_data;struct cachefiles_cache *cache = object->volume->cache;struct cachefiles_ondemand_info *info = object->ondemand; -int object_id = info->ondemand_id; +int object_id;struct cachefiles_req *req;XA_STATE (xas, &cache->reqs,0 );xa_lock (&cache->reqs); +spin_lock (&info->lock); + object_id = info->ondemand_id; info->ondemand_id =CACHEFILES_ONDEMAND_ID_CLOSED ;cachefiles_ondemand_set_object_close (object); +spin_unlock (&info->lock);/* Only flush CACHEFILES_REQ_NEW marked req to avoid race with daemon_read */ xas_for_each_marked (&xas, req,ULONG_MAX ,CACHEFILES_REQ_NEW ) {
@@ -116,6 +119,7 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args) {struct cachefiles_req *req;struct fscache_cookie *cookie; +struct cachefiles_ondemand_info *info;char *pid, *psize;unsigned long id;long size;
@@ -166,6 +170,33 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args) goto out; } + info = req->object->ondemand; +spin_lock (&info->lock); +/* +* The anonymous fd was closed before copen ? Fail the request. +* +* t1 | t2 +* --------------------------------------------------------- +* cachefiles_ondemand_copen +* req = xa_erase(&cache->reqs, id) +* // Anon fd is maliciously closed. +* cachefiles_ondemand_fd_release +* xa_lock(&cache->reqs) +* cachefiles_ondemand_set_object_close(object) +* xa_unlock(&cache->reqs) +* cachefiles_ondemand_set_object_open +* // No one will ever close it again. +* cachefiles_ondemand_daemon_read +* cachefiles_ondemand_select_req +* +* Get a read req but its fd is already closed. The daemon can't +* issue a cread ioctl with an closed fd, then hung. +*/ +if (info->ondemand_id ==CACHEFILES_ONDEMAND_ID_CLOSED ) { +spin_unlock (&info->lock); + req->error = -EBADFD ; + goto out; + } cookie = req->object->cookie; cookie->object_size = size;if (size)
@@ -175,6 +206,7 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args)trace_cachefiles_ondemand_copen (req->object, id, size);cachefiles_ondemand_set_object_open (req->object); +spin_unlock (&info->lock);wake_up_all (&cache->daemon_pollwq); out:
@@ -552,6 +584,7 @@ int cachefiles_ondemand_init_obj_info(struct cachefiles_object *object,return -ENOMEM ; object->ondemand->object = object; +spin_lock_init (&object->ondemand->lock);INIT_WORK (&object->ondemand->ondemand_work, ondemand_object_worker);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 109/267 cachefiles: add restore command to recover inflight ondemand read requests
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jia Zhu <[email protected]>
[ Upstream commit e73fa11a356ca0905c3cc648eaacc6f0f2d2c8b3 ]
Previously, in ondemand read scenario, if the anonymous fd was closed by user daemon, inflight and subsequent read requests would return EIO. As long as the device connection is not released, user daemon can hold and restore inflight requests by setting the request flag to CACHEFILES_REQ_NEW.
Stable-dep-of: 4b4391e77a6b ("cachefiles: defer exposing anon_fd until after copy_to_user() succeeds")
--- fs/cachefiles/daemon.c | 1 + fs/cachefiles/internal.h | 3 +++ fs/cachefiles/ondemand.c | 23 +++++++++++++++++++++++ 3 files changed, 27 insertions(+)
fs/cachefiles/daemon.c +1 -0
@@ -77,6 +77,7 @@ static const struct cachefiles_daemon_cmd cachefiles_daemon_cmds[] = { { "tag", cachefiles_daemon_tag }, #ifdef CONFIG_CACHEFILES_ONDEMAND { "copen", cachefiles_ondemand_copen }, + { "restore", cachefiles_ondemand_restore }, #endif { "", NULL } };
fs/cachefiles/internal.h +3 -0
@@ -304,6 +304,9 @@ extern ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,extern int cachefiles_ondemand_copen (struct cachefiles_cache *cache,char *args); +extern int cachefiles_ondemand_restore (struct cachefiles_cache *cache, +char *args); +extern int cachefiles_ondemand_init_object (struct cachefiles_object *object);extern void cachefiles_ondemand_clean_object (struct cachefiles_object *object);
fs/cachefiles/ondemand.c +23 -0
@@ -214,6 +214,29 @@ int cachefiles_ondemand_copen(struct cachefiles_cache *cache, char *args)return ret; } +int cachefiles_ondemand_restore (struct cachefiles_cache *cache,char *args) +{ +struct cachefiles_req *req; + +XA_STATE (xas, &cache->reqs,0 ); + +if (!test_bit (CACHEFILES_ONDEMAND_MODE , &cache->flags)) +return -EOPNOTSUPP ; + +/* +* Reset the requests to CACHEFILES_REQ_NEW state, so that the +* requests have been processed halfway before the crash of the +* user daemon could be reprocessed after the recovery. +*/ +xas_lock (&xas); +xas_for_each (&xas, req,ULONG_MAX ) +xas_set_mark (&xas,CACHEFILES_REQ_NEW ); +xas_unlock (&xas); + +wake_up_all (&cache->daemon_pollwq); +return 0 ; +} +static int cachefiles_ondemand_get_fd (struct cachefiles_req *req) {struct cachefiles_object *object;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 110/267 cachefiles: fix slab-use-after-free in cachefiles_ondemand_get_fd()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
[ Upstream commit de3e26f9e5b76fc628077578c001c4a51bf54d06 ]
We got the following issue in a fuzz test of randomly issuing the restore command:
==================================================================
BUG: KASAN: slab-use-after-free in cachefiles_ondemand_daemon_read+0x609/0xab0 Write of size 4 at addr ffff888109164a80 by task ondemand-04-dae/4962 CPU: 11 PID: 4962 Comm: ondemand-04-dae Not tainted 6.8.0-rc7-dirty #542 Call Trace: kasan_report+0x94/0xc0 cachefiles_ondemand_daemon_read+0x609/0xab0 vfs_read+0x169/0xb50 ksys_read+0xf5/0x1e0 Allocated by task 626: __kmalloc+0x1df/0x4b0 cachefiles_ondemand_send_req+0x24d/0x690 cachefiles_create_tmpfile+0x249/0xb30 cachefiles_create_file+0x6f/0x140 cachefiles_look_up_object+0x29c/0xa60 cachefiles_lookup_cookie+0x37d/0xca0 fscache_cookie_state_machine+0x43c/0x1230 [...] Freed by task 626: kfree+0xf1/0x2c0 cachefiles_ondemand_send_req+0x568/0x690 cachefiles_create_tmpfile+0x249/0xb30 cachefiles_create_file+0x6f/0x140 cachefiles_look_up_object+0x29c/0xa60 cachefiles_lookup_cookie+0x37d/0xca0 fscache_cookie_state_machine+0x43c/0x1230 [...] ==================================================================
Following is the process that triggers the issue:
mount | daemon_thread1 | daemon_thread2
------------------------------------------------------------
cachefiles_ondemand_init_object
cachefiles_ondemand_send_req
REQ_A = kzalloc(sizeof(*req) + data_len)
wait_for_completion(&REQ_A->done)
cachefiles_daemon_read
cachefiles_ondemand_daemon_read
REQ_A = cachefiles_ondemand_select_req
cachefiles_ondemand_get_fd
copy_to_user(_buffer, msg, n)
process_open_req(REQ_A)
------ restore ------
cachefiles_ondemand_restore
xas_for_each(&xas, req, ULONG_MAX)
xas_set_mark(&xas, CACHEFILES_REQ_NEW);
cachefiles_daemon_read
cachefiles_ondemand_daemon_read
REQ_A = cachefiles_ondemand_select_req
write(devfd, ("copen %u,%llu", msg->msg_id, size));
cachefiles_ondemand_copen
xa_erase(&cache->reqs, id)
complete(&REQ_A->done)
kfree(REQ_A)
cachefiles_ondemand_get_fd(REQ_A)
fd = get_unused_fd_flags
file = anon_inode_getfile
fd_install(fd, file)
load = (void *)REQ_A->msg.data;
load->fd = fd;
// load UAF !!!This issue is caused by issuing a restore command when the daemon is still alive, which results in a request being processed multiple times thus triggering a UAF. So to avoid this problem, add an additional reference count to cachefiles_req, which is held while waiting and reading, and then released when the waiting and reading is over.
Note that since there is only one reference count for waiting, we need to avoid the same request being completed multiple times, so we can only complete the request if it is successfully removed from the xarray.
Stable-dep-of: 4b4391e77a6b ("cachefiles: defer exposing anon_fd until after copy_to_user() succeeds")
--- fs/cachefiles/internal.h | 1 + fs/cachefiles/ondemand.c | 23 +++++++++++++++++++---- 2 files changed, 20 insertions(+), 4 deletions(-)
fs/cachefiles/internal.h +1 -0
@@ -139,6 +139,7 @@ static inline bool cachefiles_in_ondemand_mode(struct cachefiles_cache *cache)struct cachefiles_req {struct cachefiles_object *object;struct completion done; +refcount_t ref;int error;struct cachefiles_msg msg; };
fs/cachefiles/ondemand.c +19 -4
@@ -4,6 +4,12 @@#include <linux/uio.h> #include "internal.h" +static inline void cachefiles_req_put (struct cachefiles_req *req) +{ +if (refcount_dec_and_test (&req->ref)) +kfree (req); +} +static int cachefiles_ondemand_fd_release (struct inode *inode,struct file *file) {
@@ -362,6 +368,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,xas_clear_mark (&xas,CACHEFILES_REQ_NEW ); cache->req_id_next = xas.xa_index +1 ; +refcount_inc (&req->ref);xa_unlock (&cache->reqs); id = xas.xa_index;
@@ -388,15 +395,22 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,complete (&req->done); } +cachefiles_req_put (req);return n; err_put_fd:if (msg->opcode ==CACHEFILES_OP_OPEN )close_fd (((struct cachefiles_open *)msg->data)->fd); error: -xa_erase (&cache->reqs, id); - req->error = ret; -complete (&req->done); +xas_reset (&xas); +xas_lock (&xas); +if (xas_load (&xas) == req) { + req->error = ret; +complete (&req->done); +xas_store (&xas,NULL ); + } +xas_unlock (&xas); +cachefiles_req_put (req);return ret; }
@@ -427,6 +441,7 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object, goto out; } +refcount_set (&req->ref,1 ); req->object = object;init_completion (&req->done); req->msg.opcode = opcode;
@@ -488,7 +503,7 @@ static int cachefiles_ondemand_send_req(struct cachefiles_object *object,wake_up_all (&cache->daemon_pollwq);wait_for_completion (&req->done); ret = req->error; -kfree (req); +cachefiles_req_put (req);return ret; out:/* Reset the object to close state in error handling path.
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 111/267 cachefiles: fix slab-use-after-free in cachefiles_ondemand_daemon_read()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
[ Upstream commit da4a827416066191aafeeccee50a8836a826ba10 ]
We got the following issue in a fuzz test of randomly issuing the restore command:
==================================================================
BUG: KASAN: slab-use-after-free in cachefiles_ondemand_daemon_read+0xb41/0xb60 Read of size 8 at addr ffff888122e84088 by task ondemand-04-dae/963 CPU: 13 PID: 963 Comm: ondemand-04-dae Not tainted 6.8.0-dirty #564 Call Trace: kasan_report+0x93/0xc0 cachefiles_ondemand_daemon_read+0xb41/0xb60 vfs_read+0x169/0xb50 ksys_read+0xf5/0x1e0 Allocated by task 116: kmem_cache_alloc+0x140/0x3a0 cachefiles_lookup_cookie+0x140/0xcd0 fscache_cookie_state_machine+0x43c/0x1230 [...] Freed by task 792: kmem_cache_free+0xfe/0x390 cachefiles_put_object+0x241/0x480 fscache_cookie_state_machine+0x5c8/0x1230 [...] ==================================================================
Following is the process that triggers the issue:
mount | daemon_thread1 | daemon_thread2
------------------------------------------------------------cachefiles_withdraw_cookie
cachefiles_ondemand_clean_object(object)
cachefiles_ondemand_send_req
REQ_A = kzalloc(sizeof(*req) + data_len)
wait_for_completion(&REQ_A->done)
cachefiles_daemon_read
cachefiles_ondemand_daemon_read
REQ_A = cachefiles_ondemand_select_req
msg->object_id = req->object->ondemand->ondemand_id
------ restore ------
cachefiles_ondemand_restore
xas_for_each(&xas, req, ULONG_MAX)
xas_set_mark(&xas, CACHEFILES_REQ_NEW)
cachefiles_daemon_read
cachefiles_ondemand_daemon_read
REQ_A = cachefiles_ondemand_select_req
copy_to_user(_buffer, msg, n)
xa_erase(&cache->reqs, id)
complete(&REQ_A->done)
------ close(fd) ------
cachefiles_ondemand_fd_release
cachefiles_put_object
cachefiles_put_object
kmem_cache_free(cachefiles_object_jar, object)
REQ_A->object->ondemand->ondemand_id
// object UAF !!!When we see the request within xa_lock, req->object must not have been freed yet, so grab the reference count of object before xa_unlock to avoid the above issue.
Stable-dep-of: 4b4391e77a6b ("cachefiles: defer exposing anon_fd until after copy_to_user() succeeds")
--- fs/cachefiles/ondemand.c | 3 +++ include/trace/events/cachefiles.h | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-)
fs/cachefiles/ondemand.c +3 -0
@@ -369,6 +369,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,xas_clear_mark (&xas,CACHEFILES_REQ_NEW ); cache->req_id_next = xas.xa_index +1 ;refcount_inc (&req->ref); +cachefiles_grab_object (req->object, cachefiles_obj_get_read_req);xa_unlock (&cache->reqs); id = xas.xa_index;
@@ -389,6 +390,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, goto err_put_fd; } +cachefiles_put_object (req->object, cachefiles_obj_put_read_req);/* CLOSE request has no reply */ if (msg->opcode ==CACHEFILES_OP_CLOSE ) {xa_erase (&cache->reqs, id);
@@ -402,6 +404,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,if (msg->opcode ==CACHEFILES_OP_OPEN )close_fd (((struct cachefiles_open *)msg->data)->fd); error: +cachefiles_put_object (req->object, cachefiles_obj_put_read_req);xas_reset (&xas);xas_lock (&xas);if (xas_load (&xas) == req) {
include/trace/events/cachefiles.h +5 -1
@@ -33,6 +33,8 @@ enum cachefiles_obj_ref_trace { cachefiles_obj_see_withdrawal, cachefiles_obj_get_ondemand_fd, cachefiles_obj_put_ondemand_fd, + cachefiles_obj_get_read_req, + cachefiles_obj_put_read_req, }; enum fscache_why_object_killed {
@@ -129,7 +131,9 @@ enum cachefiles_error_trace { EM(cachefiles_obj_see_withdraw_cookie, "SEE withdraw_cookie") \ EM(cachefiles_obj_see_withdrawal, "SEE withdrawal") \ EM(cachefiles_obj_get_ondemand_fd, "GET ondemand_fd") \ - E_(cachefiles_obj_put_ondemand_fd, "PUT ondemand_fd") + EM(cachefiles_obj_put_ondemand_fd, "PUT ondemand_fd") \ + EM(cachefiles_obj_get_read_req, "GET read_req") \ + E_(cachefiles_obj_put_read_req, "PUT read_req")#define cachefiles_coherency_traces \ EM(cachefiles_coherency_check_aux, "BAD aux ") \
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 112/267 cachefiles: remove err_put_fd label in cachefiles_ondemand_daemon_read()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
[ Upstream commit 3e6d704f02aa4c50c7bc5fe91a4401df249a137b ]
The err_put_fd label is only used once, so remove it to make the code more readable. In addition, the logic for deleting error request and CLOSE request is merged to simplify the code.
Stable-dep-of: 4b4391e77a6b ("cachefiles: defer exposing anon_fd until after copy_to_user() succeeds")
--- fs/cachefiles/ondemand.c | 45 ++++++++++++++-------------------------- 1 file changed, 16 insertions(+), 29 deletions(-)
fs/cachefiles/ondemand.c +16 -29
@@ -337,7 +337,6 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, {struct cachefiles_req *req;struct cachefiles_msg *msg; -unsigned long id =0 ;size_t n;int ret =0 ;XA_STATE (xas, &cache->reqs, cache->req_id_next);
@@ -372,49 +371,37 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,cachefiles_grab_object (req->object, cachefiles_obj_get_read_req);xa_unlock (&cache->reqs); - id = xas.xa_index; -if (msg->opcode ==CACHEFILES_OP_OPEN ) { ret =cachefiles_ondemand_get_fd (req);if (ret) {cachefiles_ondemand_set_object_close (req->object); - goto error; + goto out; } } - msg->msg_id = id; + msg->msg_id = xas.xa_index; msg->object_id = req->object->ondemand->ondemand_id;if (copy_to_user (_buffer, msg, n) !=0 ) { ret = -EFAULT ; - goto err_put_fd; - } - -cachefiles_put_object (req->object, cachefiles_obj_put_read_req); -/* CLOSE request has no reply */ -if (msg->opcode ==CACHEFILES_OP_CLOSE ) { -xa_erase (&cache->reqs, id); -complete (&req->done); +if (msg->opcode ==CACHEFILES_OP_OPEN ) +close_fd (((struct cachefiles_open *)msg->data)->fd); } - -cachefiles_req_put (req); -return n; - -err_put_fd: -if (msg->opcode ==CACHEFILES_OP_OPEN ) -close_fd (((struct cachefiles_open *)msg->data)->fd); -error: +out:cachefiles_put_object (req->object, cachefiles_obj_put_read_req); -xas_reset (&xas); -xas_lock (&xas); -if (xas_load (&xas) == req) { - req->error = ret; -complete (&req->done); -xas_store (&xas,NULL ); +/* Remove error request and CLOSE request has no reply */ +if (ret || msg->opcode ==CACHEFILES_OP_CLOSE ) { +xas_reset (&xas); +xas_lock (&xas); +if (xas_load (&xas) == req) { + req->error = ret; +complete (&req->done); +xas_store (&xas,NULL ); + } +xas_unlock (&xas); } -xas_unlock (&xas);cachefiles_req_put (req); -return ret; +return ret ? ret : n; }typedef int (*init_req_fn )(struct cachefiles_req *req,void *private);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 113/267 cachefiles: never get a new anonymous fd if ondemand_id is valid
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
[ Upstream commit 4988e35e95fc938bdde0e15880fe72042fc86acf ]
Now every time the daemon reads an open request, it gets a new anonymous fd and ondemand_id. With the introduction of "restore", it is possible to read the same open request more than once, and therefore an object can have more than one anonymous fd.
If the anonymous fd is not unique, the following concurrencies will result in an fd leak:
t1 | t2 | t3
------------------------------------------------------------
cachefiles_ondemand_init_object
cachefiles_ondemand_send_req
REQ_A = kzalloc(sizeof(*req) + data_len)
wait_for_completion(&REQ_A->done)
cachefiles_daemon_read
cachefiles_ondemand_daemon_read
REQ_A = cachefiles_ondemand_select_req
cachefiles_ondemand_get_fd
load->fd = fd0
ondemand_id = object_id0
------ restore ------
cachefiles_ondemand_restore
// restore REQ_A
cachefiles_daemon_read
cachefiles_ondemand_daemon_read
REQ_A = cachefiles_ondemand_select_req
cachefiles_ondemand_get_fd
load->fd = fd1
ondemand_id = object_id1
process_open_req(REQ_A)
write(devfd, ("copen %u,%llu", msg->msg_id, size))
cachefiles_ondemand_copen
xa_erase(&cache->reqs, id)
complete(&REQ_A->done)
kfree(REQ_A)
process_open_req(REQ_A)
// copen fails due to no req
// daemon close(fd1)
cachefiles_ondemand_fd_release
// set object closed
-- umount --
cachefiles_withdraw_cookie
cachefiles_ondemand_clean_object
cachefiles_ondemand_init_close_req
if (!cachefiles_ondemand_object_is_open(object))
return -ENOENT;
// The fd0 is not closed until the daemon exits.However, the anonymous fd holds the reference count of the object and the object holds the reference count of the cookie. So even though the cookie has been relinquished, it will not be unhashed and freed until the daemon exits.
In fscache_hash_cookie(), when the same cookie is found in the hash list, if the cookie is set with the FSCACHE_COOKIE_RELINQUISHED bit, then the new cookie waits for the old cookie to be unhashed, while the old cookie is waiting for the leaked fd to be closed, if the daemon does not exit in time it will trigger a hung task.
To avoid this, allocate a new anonymous fd only if no anonymous fd has been allocated (ondemand_id == 0) or if the previously allocated anonymous fd has been closed (ondemand_id == -1). Moreover, returns an error if ondemand_id is valid, letting the daemon know that the current userland restore logic is abnormal and needs to be checked.
Stable-dep-of: 4b4391e77a6b ("cachefiles: defer exposing anon_fd until after copy_to_user() succeeds")
--- fs/cachefiles/ondemand.c | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-)
fs/cachefiles/ondemand.c +28 -6
@@ -14,11 +14,18 @@ static int cachefiles_ondemand_fd_release(struct inode *inode, struct file *file) {struct cachefiles_object *object = file->private_data; -struct cachefiles_cache *cache = object->volume->cache; -struct cachefiles_ondemand_info *info = object->ondemand; +struct cachefiles_cache *cache; +struct cachefiles_ondemand_info *info;int object_id;struct cachefiles_req *req; -XA_STATE (xas, &cache->reqs,0 ); +XA_STATE (xas,NULL ,0 ); + +if (!object) +return 0 ; + + info = object->ondemand; + cache = object->volume->cache; + xas.xa = &cache->reqs;xa_lock (&cache->reqs);spin_lock (&info->lock);
@@ -275,22 +282,39 @@ static int cachefiles_ondemand_get_fd(struct cachefiles_req *req) goto err_put_fd; } +spin_lock (&object->ondemand->lock); +if (object->ondemand->ondemand_id >0 ) { +spin_unlock (&object->ondemand->lock); +/* Pair with check in cachefiles_ondemand_fd_release(). */ + file->private_data =NULL ; + ret = -EEXIST ; + goto err_put_file; + } + file->f_mode |=FMODE_PWRITE |FMODE_LSEEK ;fd_install (fd, file); load = (void *)req->msg.data; load->fd = fd; object->ondemand->ondemand_id = object_id; +spin_unlock (&object->ondemand->lock);cachefiles_get_unbind_pincount (cache);trace_cachefiles_ondemand_open (object, &req->msg, load);return 0 ; +err_put_file: +fput (file); err_put_fd:put_unused_fd (fd); err_free_id:xa_erase (&cache->ondemand_ids, object_id); err: +spin_lock (&object->ondemand->lock); +/* Avoid marking an opened object as closed. */ +if (object->ondemand->ondemand_id <=0 ) +cachefiles_ondemand_set_object_close (object); +spin_unlock (&object->ondemand->lock);cachefiles_put_object (object, cachefiles_obj_put_ondemand_fd);return ret; }
@@ -373,10 +397,8 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,if (msg->opcode ==CACHEFILES_OP_OPEN ) { ret =cachefiles_ondemand_get_fd (req); -if (ret) { -cachefiles_ondemand_set_object_close (req->object); +if (ret) goto out; - } } msg->msg_id = xas.xa_index;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 114/267 cachefiles: defer exposing anon_fd until after copy_to_user() succeeds
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
[ Upstream commit 4b4391e77a6bf24cba2ef1590e113d9b73b11039 ]
After installing the anonymous fd, we can now see it in userland and close it. However, at this point we may not have gotten the reference count of the cache, but we will put it during colse fd, so this may cause a cache UAF.
So grab the cache reference count before fd_install(). In addition, by kernel convention, fd is taken over by the user land after fd_install(), and the kernel should not call close_fd() after that, i.e., it should call fd_install() after everything is ready, thus fd_install() is called after copy_to_user() succeeds.
--- fs/cachefiles/ondemand.c | 53 +++++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 20 deletions(-)
fs/cachefiles/ondemand.c +33 -20
@@ -4,6 +4,11 @@#include <linux/uio.h> #include "internal.h" +struct ondemand_anon_file { +struct file *file; +int fd; +}; +static inline void cachefiles_req_put (struct cachefiles_req *req) {if (refcount_dec_and_test (&req->ref))
@@ -250,14 +255,14 @@ int cachefiles_ondemand_restore(struct cachefiles_cache *cache, char *args)return 0 ; } -static int cachefiles_ondemand_get_fd (struct cachefiles_req *req) +static int cachefiles_ondemand_get_fd (struct cachefiles_req *req, +struct ondemand_anon_file *anon_file) {struct cachefiles_object *object;struct cachefiles_cache *cache;struct cachefiles_open *load; -struct file *file;u32 object_id; -int ret, fd; +int ret; object =cachefiles_grab_object (req->object, cachefiles_obj_get_ondemand_fd);
@@ -269,16 +274,16 @@ static int cachefiles_ondemand_get_fd(struct cachefiles_req *req)if (ret <0 ) goto err; - fd =get_unused_fd_flags (O_WRONLY ); -if (fd <0 ) { - ret = fd; + anon_file->fd =get_unused_fd_flags (O_WRONLY ); +if (anon_file->fd <0 ) { + ret = anon_file->fd; goto err_free_id; } - file =anon_inode_getfile ("[cachefiles]" , &cachefiles_ondemand_fd_fops, - object,O_WRONLY ); -if (IS_ERR (file)) { - ret =PTR_ERR (file); + anon_file->file =anon_inode_getfile ("[cachefiles]" , + &cachefiles_ondemand_fd_fops, object,O_WRONLY ); +if (IS_ERR (anon_file->file)) { + ret =PTR_ERR (anon_file->file); goto err_put_fd; }
@@ -286,16 +291,15 @@ static int cachefiles_ondemand_get_fd(struct cachefiles_req *req)if (object->ondemand->ondemand_id >0 ) {spin_unlock (&object->ondemand->lock);/* Pair with check in cachefiles_ondemand_fd_release(). */ - file->private_data =NULL ; + anon_file->file->private_data =NULL ; ret = -EEXIST ; goto err_put_file; } - file->f_mode |=FMODE_PWRITE |FMODE_LSEEK ; -fd_install (fd, file); + anon_file->file->f_mode |=FMODE_PWRITE |FMODE_LSEEK ; load = (void *)req->msg.data; - load->fd = fd; + load->fd = anon_file->fd; object->ondemand->ondemand_id = object_id;spin_unlock (&object->ondemand->lock);
@@ -304,9 +308,11 @@ static int cachefiles_ondemand_get_fd(struct cachefiles_req *req)return 0 ; err_put_file: -fput (file); +fput (anon_file->file); + anon_file->file =NULL ; err_put_fd: -put_unused_fd (fd); +put_unused_fd (anon_file->fd); + anon_file->fd = ret; err_free_id:xa_erase (&cache->ondemand_ids, object_id); err:
@@ -363,6 +369,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,struct cachefiles_msg *msg;size_t n;int ret =0 ; +struct ondemand_anon_file anon_file;XA_STATE (xas, &cache->reqs, cache->req_id_next);xa_lock (&cache->reqs);
@@ -396,7 +403,7 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache,xa_unlock (&cache->reqs);if (msg->opcode ==CACHEFILES_OP_OPEN ) { - ret =cachefiles_ondemand_get_fd (req); + ret =cachefiles_ondemand_get_fd (req, &anon_file);if (ret) goto out; }
@@ -404,10 +411,16 @@ ssize_t cachefiles_ondemand_daemon_read(struct cachefiles_cache *cache, msg->msg_id = xas.xa_index; msg->object_id = req->object->ondemand->ondemand_id; -if (copy_to_user (_buffer, msg, n) !=0 ) { +if (copy_to_user (_buffer, msg, n) !=0 ) ret = -EFAULT ; -if (msg->opcode ==CACHEFILES_OP_OPEN ) -close_fd (((struct cachefiles_open *)msg->data)->fd); + +if (msg->opcode ==CACHEFILES_OP_OPEN ) { +if (ret <0 ) { +fput (anon_file.file); +put_unused_fd (anon_file.fd); + goto out; + } +fd_install (anon_file.fd, anon_file.file); } out:cachefiles_put_object (req->object, cachefiles_obj_put_read_req);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 115/267 cachefiles: flush all requests after setting CACHEFILES_DEAD
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Baokun Li <[email protected]>
[ Upstream commit 85e833cd7243bda7285492b0653c3abb1e2e757b ]
In ondemand mode, when the daemon is processing an open request, if the kernel flags the cache as CACHEFILES_DEAD, the cachefiles_daemon_write() will always return -EIO, so the daemon can't pass the copen to the kernel. Then the kernel process that is waiting for the copen triggers a hung_task.
Since the DEAD state is irreversible, it can only be exited by closing /dev/cachefiles. Therefore, after calling cachefiles_io_error() to mark the cache as CACHEFILES_DEAD, if in ondemand mode, flush all requests to avoid the above hungtask. We may still be able to read some of the cached data before closing the fd of /dev/cachefiles.
Note that this relies on the patch that adds reference counting to the req, otherwise it may UAF.
--- fs/cachefiles/daemon.c | 2 +- fs/cachefiles/internal.h | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-)
fs/cachefiles/daemon.c +1 -1
@@ -133,7 +133,7 @@ static int cachefiles_daemon_open(struct inode *inode, struct file *file)return 0 ; } -static void cachefiles_flush_reqs (struct cachefiles_cache *cache) +void cachefiles_flush_reqs (struct cachefiles_cache *cache) {struct xarray *xa = &cache->reqs;struct cachefiles_req *req;
fs/cachefiles/internal.h +3 -0
@@ -188,6 +188,7 @@ extern int cachefiles_has_space(struct cachefiles_cache *cache,* daemon.c */ extern const struct file_operations cachefiles_daemon_fops; +extern void cachefiles_flush_reqs (struct cachefiles_cache *cache);extern void cachefiles_get_unbind_pincount (struct cachefiles_cache *cache);extern void cachefiles_put_unbind_pincount (struct cachefiles_cache *cache);
@@ -414,6 +415,8 @@ do { \ pr_err("I/O Error: " FMT"\n", ##__VA_ARGS__); \fscache_io_error ((___cache)->cache); \set_bit (CACHEFILES_DEAD , &(___cache)->flags); \ +if (cachefiles_in_ondemand_mode (___cache)) \ +cachefiles_flush_reqs (___cache); \ } while (0)#define cachefiles_io_error_obj (object,FMT , ...) \
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 116/267 selftests/ftrace: Fix to check required event file
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <[email protected]>
[ Upstream commit f6c3c83db1d939ebdb8c8922748ae647d8126d91 ]
The dynevent/test_duplicates.tc test case uses syscalls/sys_enter_openat event for defining eprobe on it. Since this syscalls events depend on CONFIG_FTRACE_SYSCALLS=y, if it is not set, the test will fail.
Add the event file to required line so that the test will return unsupported result.
--- .../testing/selftests/ftrace/test.d/dynevent/test_duplicates.tc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/ftrace/test.d/dynevent/test_duplicates.tc +1 -1
@@ -1,7 +1,7 @@ #!/bin/sh # SPDX-License-Identifier: GPL-2.0 # description: Generic dynamic event - check if duplicate events are caught -# requires: dynamic_events "e[:[<group>/][<event>]] <attached-group>.<attached-event> [<args>]":README +# requires: dynamic_events "e[:[<group>/][<event>]] <attached-group>.<attached-event> [<args>]":README events/syscalls/sys_enter_openat echo 0 > events/enable
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 117/267 clk: sifive: Do not register clkdevs for PRCI clocks
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Samuel Holland <[email protected]>
[ Upstream commit 2607133196c35f31892ee199ce7ffa717bea4ad1 ]
These clkdevs were unnecessary, because systems using this driver always look up clocks using the devicetree. And as Russell King points out[1], since the provided device name was truncated, lookups via clkdev would never match.
Recently, commit 8d532528ff6a ("clkdev: report over-sized strings when creating clkdev entries") caused clkdev registration to fail due to the truncation, and this now prevents the driver from probing. Fix the driver by removing the clkdev registration.
--- drivers/clk/sifive/sifive-prci.c | 8 -------- 1 file changed, 8 deletions(-)
drivers/clk/sifive/sifive-prci.c +0 -8
@@ -4,7 +4,6 @@* Copyright (C) 2020 Zong Li */ -#include <linux/clkdev.h> #include <linux/delay.h> #include <linux/io.h> #include <linux/of.h>
@@ -536,13 +535,6 @@ static int __prci_register_clocks(struct device *dev, struct __prci_data *pd,return r; } - r =clk_hw_register_clkdev (&pic->hw, pic->name,dev_name (dev)); -if (r) { -dev_warn (dev,"Failed to register clkdev for %s: %d\n" , - init.name, r); -return r; - } - pd->hw_clks.hws[i] = &pic->hw; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 118/267 NFSv4.1 enforce rootpath check in fs_location query
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Olga Kornievskaia <[email protected]>
[ Upstream commit 28568c906c1bb5f7560e18082ed7d6295860f1c2 ]
In commit 4ca9f31a2be66 ("NFSv4.1 test and add 4.1 trunking transport"), we introduce the ability to query the NFS server for possible trunking locations of the existing filesystem. However, we never checked the returned file system path for these alternative locations. According to the RFC, the server can say that the filesystem currently known under "fs_root" of fs_location also resides under these server locations under the following "rootpath" pathname. The client cannot handle trunking a filesystem that reside under different location under different paths other than what the main path is. This patch enforces the check that fs_root path and rootpath path in fs_location reply is the same.
--- fs/nfs/nfs4proc.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-)
fs/nfs/nfs4proc.c +22 -1
@@ -4003,6 +4003,23 @@ static void test_fs_location_for_trunking(struct nfs4_fs_location *location, } } +static bool _is_same_nfs4_pathname (struct nfs4_pathname *path1, +struct nfs4_pathname *path2) +{ +int i; + +if (path1->ncomponents != path2->ncomponents) +return false; +for (i =0 ; i < path1->ncomponents; i++) { +if (path1->components[i].len != path2->components[i].len) +return false; +if (memcmp (path1->components[i].data, path2->components[i].data, + path1->components[i].len)) +return false; + } +return true; +} +static int _nfs4_discover_trunking (struct nfs_server *server,struct nfs_fh *fhandle) {
@@ -4036,9 +4053,13 @@ static int _nfs4_discover_trunking(struct nfs_server *server,if (status) goto out_free_3; -for (i =0 ; i < locations->nlocations; i++) +for (i =0 ; i < locations->nlocations; i++) { +if (!_is_same_nfs4_pathname (&locations->fs_path, + &locations->locations[i].rootpath)) +continue ;test_fs_location_for_trunking (&locations->locations[i], clp, server); + } out_free_3:kfree (locations->fattr); out_free_2:
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 119/267 SUNRPC: return proper error from gss_wrap_req_priv
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Hanxiao <[email protected]>
[ Upstream commit 33c94d7e3cb84f6d130678d6d59ba475a6c489cf ]
don't return 0 if snd_buf->len really greater than snd_buf->buflen
--- net/sunrpc/auth_gss/auth_gss.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/sunrpc/auth_gss/auth_gss.c +3 -1
@@ -1875,8 +1875,10 @@ gss_wrap_req_priv(struct rpc_cred *cred, struct gss_cl_ctx *ctx, offset = (u8 *)p - (u8 *)snd_buf->head[0 ].iov_base; maj_stat =gss_wrap (ctx->gc_gss_ctx, offset, snd_buf, inpages);/* slack space should prevent this ever happening: */ -if (unlikely (snd_buf->len > snd_buf->buflen)) +if (unlikely (snd_buf->len > snd_buf->buflen)) { + status = -EIO ; goto wrap_failed; + }/* We're assuming that when GSS_S_CONTEXT_EXPIRED, the encryption was * done anyway, so it's safe to put the request on the wire: */ if (maj_stat ==GSS_S_CONTEXT_EXPIRED )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 120/267 NFS: add barriers when testing for NFS_FSDATA_BLOCKED
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: NeilBrown <[email protected]>
[ Upstream commit 99bc9f2eb3f79a2b4296d9bf43153e1d10ca50d3 ]
dentry->d_fsdata is set to NFS_FSDATA_BLOCKED while unlinking or renaming-over a file to ensure that no open succeeds while the NFS operation progressed on the server.
Setting dentry->d_fsdata to NFS_FSDATA_BLOCKED is done under ->d_lock after checking the refcount is not elevated. Any attempt to open the file (through that name) will go through lookp_open() which will take ->d_lock while incrementing the refcount, we can be sure that once the new value is set, __nfs_lookup_revalidate() *will* see the new value and will block.
We don't have any locking guarantee that when we set ->d_fsdata to NULL, the wait_var_event() in __nfs_lookup_revalidate() will notice. wait/wake primitives do NOT provide barriers to guarantee order. We must use smp_load_acquire() in wait_var_event() to ensure we look at an up-to-date value, and must use smp_store_release() before wake_up_var().
This patch adds those barrier functions and factors out block_revalidate() and unblock_revalidate() far clarity.
There is also a hypothetical bug in that if memory allocation fails (which never happens in practice) we might leave ->d_fsdata locked. This patch adds the missing call to unblock_revalidate().
--- fs/nfs/dir.c | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-)
fs/nfs/dir.c +32 -15
@@ -1802,9 +1802,10 @@ __nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags,if (parent !=READ_ONCE (dentry->d_parent))return -ECHILD ; }else { -/* Wait for unlink to complete */ +/* Wait for unlink to complete - see unblock_revalidate() */ wait_var_event (&dentry->d_fsdata, - dentry->d_fsdata !=NFS_FSDATA_BLOCKED ); +smp_load_acquire (&dentry->d_fsdata) + !=NFS_FSDATA_BLOCKED ); parent =dget_parent (dentry); ret =reval (d_inode (parent), dentry, flags);dput (parent);
@@ -1817,6 +1818,29 @@ static int nfs_lookup_revalidate(struct dentry *dentry, unsigned int flags)return __nfs_lookup_revalidate (dentry, flags, nfs_do_lookup_revalidate); } +static void block_revalidate (struct dentry *dentry) +{ +/* old devname - just in case */ +kfree (dentry->d_fsdata); + +/* Any new reference that could lead to an open +* will take ->d_lock in lookup_open() -> d_lookup(). +* Holding this lock ensures we cannot race with +* __nfs_lookup_revalidate() and removes and need +* for further barriers. +*/ +lockdep_assert_held (&dentry->d_lock); + + dentry->d_fsdata =NFS_FSDATA_BLOCKED ; +} + +static void unblock_revalidate (struct dentry *dentry) +{ +/* store_release ensures wait_var_event() sees the update */ +smp_store_release (&dentry->d_fsdata,NULL ); +wake_up_var (&dentry->d_fsdata); +} +/* * A weaker form of d_revalidate for revalidating just the d_inode(dentry) * when we don't really care about the dentry name. This is called when a
@@ -2499,15 +2523,12 @@ int nfs_unlink(struct inode *dir, struct dentry *dentry)spin_unlock (&dentry->d_lock); goto out; } -/* old devname */ -kfree (dentry->d_fsdata); - dentry->d_fsdata =NFS_FSDATA_BLOCKED ; +block_revalidate (dentry);spin_unlock (&dentry->d_lock); error =nfs_safe_remove (dentry);nfs_dentry_remove_handle_error (dir, dentry, error); - dentry->d_fsdata =NULL ; -wake_up_var (&dentry->d_fsdata); +unblock_revalidate (dentry); out:trace_nfs_unlink_exit (dir, dentry, error);return error;
@@ -2619,8 +2640,7 @@ nfs_unblock_rename(struct rpc_task *task, struct nfs_renamedata *data) {struct dentry *new_dentry = data->new_dentry; - new_dentry->d_fsdata =NULL ; -wake_up_var (&new_dentry->d_fsdata); +unblock_revalidate (new_dentry); }/*
@@ -2682,11 +2702,6 @@ int nfs_rename(struct mnt_idmap *idmap, struct inode *old_dir,if (WARN_ON (new_dentry->d_flags &DCACHE_NFSFS_RENAMED ) ||WARN_ON (new_dentry->d_fsdata ==NFS_FSDATA_BLOCKED )) goto out; -if (new_dentry->d_fsdata) { -/* old devname */ -kfree (new_dentry->d_fsdata); - new_dentry->d_fsdata =NULL ; - }spin_lock (&new_dentry->d_lock);if (d_count (new_dentry) >2 ) {
@@ -2708,7 +2723,7 @@ int nfs_rename(struct mnt_idmap *idmap, struct inode *old_dir, new_dentry = dentry; new_inode =NULL ; }else { - new_dentry->d_fsdata =NFS_FSDATA_BLOCKED ; +block_revalidate (new_dentry); must_unblock = true;spin_unlock (&new_dentry->d_lock); }
@@ -2720,6 +2735,8 @@ int nfs_rename(struct mnt_idmap *idmap, struct inode *old_dir, task =nfs_async_rename (old_dir, new_dir, old_dentry, new_dentry, must_unblock ? nfs_unblock_rename :NULL );if (IS_ERR (task)) { +if (must_unblock) +unblock_revalidate (new_dentry); error =PTR_ERR (task); goto out; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 121/267 selftests/tracing: Fix event filter test to retry up to 10 times
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <[email protected]>
[ Upstream commit 0f42bdf59b4e428485aa922bef871bfa6cc505e0 ]
Commit eb50d0f250e9 ("selftests/ftrace: Choose target function for filter test from samples") choose the target function from samples, but sometimes this test failes randomly because the target function does not hit at the next time. So retry getting samples up to 10 times.
--- .../test.d/filter/event-filter-function.tc | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-)
tools/testing/selftests/ftrace/test.d/filter/event-filter-function.tc +19 -1
@@ -10,7 +10,6 @@ fail() { #msg } sample_events() { - echo > trace echo 1 > events/kmem/kmem_cache_free/enable echo 1 > tracing_on ls > /dev/null
@@ -22,6 +21,7 @@ echo 0 > tracing_on echo 0 > events/enable echo "Get the most frequently calling function" +echo > trace sample_events target_func=`cat trace | grep -o 'call_site=\([^+]*\)' | sed 's/call_site=//' | sort | uniq -c | sort | tail -n 1 | sed 's/^[ 0-9]*//'`
@@ -32,7 +32,16 @@ echo > trace echo "Test event filter function name" echo "call_site.function == $target_func" > events/kmem/kmem_cache_free/filter + +sample_events +max_retry=10 +while [ `grep kmem_cache_free trace| wc -l` -eq 0 ]; do sample_events +max_retry=$((max_retry - 1)) +if [ $max_retry -eq 0 ]; then + exit_fail +fi +done hitcnt=`grep kmem_cache_free trace| grep $target_func | wc -l` misscnt=`grep kmem_cache_free trace| grep -v $target_func | wc -l`
@@ -49,7 +58,16 @@ address=`grep " ${target_func}\$" /proc/kallsyms | cut -d' ' -f1` echo "Test event filter function address" echo "call_site.function == 0x$address" > events/kmem/kmem_cache_free/filter +echo > trace +sample_events +max_retry=10 +while [ `grep kmem_cache_free trace| wc -l` -eq 0 ]; do sample_events +max_retry=$((max_retry - 1)) +if [ $max_retry -eq 0 ]; then + exit_fail +fi +done hitcnt=`grep kmem_cache_free trace| grep $target_func | wc -l` misscnt=`grep kmem_cache_free trace| grep -v $target_func | wc -l`
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 122/267 nvme: fix nvme_pr_* status code parsing
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiwen Hu <[email protected]>
[ Upstream commit b1a1fdd7096dd2d67911b07f8118ff113d815db4 ]
Fix the parsing if extra status bits (e.g. MORE) is present.
--- drivers/nvme/host/pr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/nvme/host/pr.c +1 -1
@@ -77,7 +77,7 @@ static int nvme_sc_to_pr_err(int nvme_sc)if (nvme_is_path_error (nvme_sc))return PR_STS_PATH_FAILED ; -switch (nvme_sc) { +switch (nvme_sc &0x7ff ) {case NVME_SC_SUCCESS :return PR_STS_SUCCESS ;case NVME_SC_RESERVATION_CONFLICT :
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 123/267 drm/panel: sitronix-st7789v: Add check for of_drm_get_panel_orientation
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Ni <[email protected]>
[ Upstream commit 629f2b4e05225e53125aaf7ff0b87d5d53897128 ]
Add check for the return value of of_drm_get_panel_orientation() and return the error if it fails in order to catch the error.
--- drivers/gpu/drm/panel/panel-sitronix-st7789v.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/gpu/drm/panel/panel-sitronix-st7789v.c +3 -1
@@ -643,7 +643,9 @@ static int st7789v_probe(struct spi_device *spi)if (ret)return dev_err_probe (dev, ret,"Failed to get backlight\n" ); -of_drm_get_panel_orientation (spi->dev.of_node, &ctx->orientation); + ret =of_drm_get_panel_orientation (spi->dev.of_node, &ctx->orientation); +if (ret) +return dev_err_probe (&spi->dev, ret,"Failed to get orientation\n" );drm_panel_add (&ctx->panel);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 124/267 platform/x86: dell-smbios: Fix wrong token data in sysfs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Armin Wolf <[email protected]>
[ Upstream commit 1981b296f858010eae409548fd297659b2cc570e ]
When reading token data from sysfs on my Inspiron 3505, the token locations and values are wrong. This happens because match_attribute() blindly assumes that all entries in da_tokens have an associated entry in token_attrs.
This however is not true as soon as da_tokens[] contains zeroed token entries. Those entries are being skipped when initialising token_attrs, breaking the core assumption of match_attribute().
Fix this by defining an extra struct for each pair of token attributes and use container_of() to retrieve token information.
Tested on a Dell Inspiron 3050.
--- drivers/platform/x86/dell/dell-smbios-base.c | 92 ++++++++------------ 1 file changed, 36 insertions(+), 56 deletions(-)
drivers/platform/x86/dell/dell-smbios-base.c +36 -56
@@ -11,6 +11,7 @@*/ #define pr_fmt (fmt) KBUILD_MODNAME ": " fmt +#include <linux/container_of.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/capability.h>
@@ -25,11 +26,16 @@ static u32 da_supported_commands;static int da_num_tokens;static struct platform_device *platform_device;static struct calling_interface_token *da_tokens; -static struct device_attribute *token_location_attrs; -static struct device_attribute *token_value_attrs; +static struct token_sysfs_data *token_entries;static struct attribute **token_attrs;static DEFINE_MUTEX (smbios_mutex); +struct token_sysfs_data { +struct device_attribute location_attr; +struct device_attribute value_attr; +struct calling_interface_token *token; +}; +struct smbios_device {struct list_head list;struct device *device;
@@ -416,47 +422,26 @@ static void __init find_tokens(const struct dmi_header *dm, void *dummy) } } -static int match_attribute (struct device *dev, -struct device_attribute *attr) -{ -int i; - -for (i =0 ; i < da_num_tokens *2 ; i++) { -if (!token_attrs[i]) -continue ; -if (strcmp (token_attrs[i]->name, attr->attr.name) ==0 ) -return i/2 ; - } -dev_dbg (dev,"couldn't match: %s\n" , attr->attr.name); -return -EINVAL ; -} -static ssize_t location_show (struct device *dev,struct device_attribute *attr,char *buf) { -int i; + struct token_sysfs_data *data = container_of(attr, struct token_sysfs_data, location_attr);if (!capable (CAP_SYS_ADMIN ))return -EPERM ; - i =match_attribute (dev, attr); -if (i >0 ) -return sysfs_emit (buf,"%08x" , da_tokens[i].location); -return 0 ; +return sysfs_emit (buf,"%08x" , data->token->location); }static ssize_t value_show (struct device *dev,struct device_attribute *attr,char *buf) { -int i; + struct token_sysfs_data *data = container_of(attr, struct token_sysfs_data, value_attr);if (!capable (CAP_SYS_ADMIN ))return -EPERM ; - i =match_attribute (dev, attr); -if (i >0 ) -return sysfs_emit (buf,"%08x" , da_tokens[i].value); -return 0 ; +return sysfs_emit (buf,"%08x" , data->token->value); }static struct attribute_group smbios_attribute_group = {
@@ -473,22 +458,15 @@ static int build_tokens_sysfs(struct platform_device *dev) {char *location_name;char *value_name; -size_t size;int ret;int i, j; -/* (number of tokens + 1 for null terminated */ - size =sizeof (struct device_attribute ) * (da_num_tokens +1 ); - token_location_attrs =kzalloc (size,GFP_KERNEL ); -if (!token_location_attrs) + token_entries =kcalloc (da_num_tokens,sizeof (*token_entries),GFP_KERNEL ); +if (!token_entries)return -ENOMEM ; - token_value_attrs =kzalloc (size,GFP_KERNEL ); -if (!token_value_attrs) - goto out_allocate_value;/* need to store both location and value + terminator*/ - size =sizeof (struct attribute *) * ((2 * da_num_tokens) +1 ); - token_attrs =kzalloc (size,GFP_KERNEL ); + token_attrs =kcalloc ((2 * da_num_tokens) +1 ,sizeof (*token_attrs),GFP_KERNEL );if (!token_attrs) goto out_allocate_attrs;
@@ -496,27 +474,32 @@ static int build_tokens_sysfs(struct platform_device *dev)/* skip empty */ if (da_tokens[i].tokenID ==0 )continue ; + + token_entries[i].token = &da_tokens[i]; +/* add location */ location_name =kasprintf (GFP_KERNEL ,"%04x_location" , da_tokens[i].tokenID);if (location_name ==NULL ) goto out_unwind_strings; -sysfs_attr_init (&token_location_attrs[i].attr); - token_location_attrs[i].attr.name = location_name; - token_location_attrs[i].attr.mode =0444 ; - token_location_attrs[i].show = location_show; - token_attrs[j++] = &token_location_attrs[i].attr; + +sysfs_attr_init (&token_entries[i].location_attr.attr); + token_entries[i].location_attr.attr.name = location_name; + token_entries[i].location_attr.attr.mode =0444 ; + token_entries[i].location_attr.show = location_show; + token_attrs[j++] = &token_entries[i].location_attr.attr;/* add value */ value_name =kasprintf (GFP_KERNEL ,"%04x_value" , da_tokens[i].tokenID);if (value_name ==NULL ) goto loop_fail_create_value; -sysfs_attr_init (&token_value_attrs[i].attr); - token_value_attrs[i].attr.name = value_name; - token_value_attrs[i].attr.mode =0444 ; - token_value_attrs[i].show = value_show; - token_attrs[j++] = &token_value_attrs[i].attr; + +sysfs_attr_init (&token_entries[i].value_attr.attr); + token_entries[i].value_attr.attr.name = value_name; + token_entries[i].value_attr.attr.mode =0444 ; + token_entries[i].value_attr.show = value_show; + token_attrs[j++] = &token_entries[i].value_attr.attr;continue ; loop_fail_create_value:
@@ -532,14 +515,12 @@ static int build_tokens_sysfs(struct platform_device *dev) out_unwind_strings:while (i--) { -kfree (token_location_attrs[i].attr.name); -kfree (token_value_attrs[i].attr.name); +kfree (token_entries[i].location_attr.attr.name); +kfree (token_entries[i].value_attr.attr.name); }kfree (token_attrs); out_allocate_attrs: -kfree (token_value_attrs); -out_allocate_value: -kfree (token_location_attrs); +kfree (token_entries);return -ENOMEM ; }
@@ -551,12 +532,11 @@ static void free_group(struct platform_device *pdev)sysfs_remove_group (&pdev->dev.kobj, &smbios_attribute_group);for (i =0 ; i < da_num_tokens; i++) { -kfree (token_location_attrs[i].attr.name); -kfree (token_value_attrs[i].attr.name); +kfree (token_entries[i].location_attr.attr.name); +kfree (token_entries[i].value_attr.attr.name); }kfree (token_attrs); -kfree (token_value_attrs); -kfree (token_location_attrs); +kfree (token_entries); }static int __init dell_smbios_init (void )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 125/267 gpio: tqmx86: fix typo in Kconfig label
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gregor Herburger <[email protected]>
[ Upstream commit 8c219e52ca4d9a67cd6a7074e91bf29b55edc075 ]
Fix description for GPIO_TQMX86 from QTMX86 to TQMx86.
--- drivers/gpio/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpio/Kconfig +1 -1
@@ -1507,7 +1507,7 @@ config GPIO_TPS68470 are "output only" GPIOs. config GPIO_TQMX86 - tristate "TQ-Systems QTMX86 GPIO" + tristate "TQ-Systems TQMx86 GPIO" depends on MFD_TQMX86 || COMPILE_TEST depends on HAS_IOPORT_MAP select GPIOLIB_IRQCHIP
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 126/267 gpio: tqmx86: introduce shadow register for GPIO output value
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthias Schiffer <[email protected]>
[ Upstream commit 9d6a811b522ba558bcb4ec01d12e72a0af8e9f6e ]
The TQMx86 GPIO controller uses the same register address for input and output data. Reading the register will always return current inputs rather than the previously set outputs (regardless of the current direction setting). Therefore, using a RMW pattern does not make sense when setting output values. Instead, the previously set output register value needs to be stored as a shadow register.
As there is no reliable way to get the current output values from the hardware, also initialize all channels to 0, to ensure that stored and actual output values match. This should usually not have any effect in practise, as the TQMx86 UEFI sets all outputs to 0 during boot.
Also prepare for extension of the driver to more than 8 GPIOs by using DECLARE_BITMAP.
--- drivers/gpio/gpio-tqmx86.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-)
drivers/gpio/gpio-tqmx86.c +11 -7
@@ -6,6 +6,7 @@* Vadim V.Vlasov <[email protected]> */ +#include <linux/bitmap.h> #include <linux/bitops.h> #include <linux/errno.h> #include <linux/gpio/driver.h>
@@ -38,6 +39,7 @@ struct tqmx86_gpio_data {void __iomem *io_base;int irq;raw_spinlock_t spinlock; +DECLARE_BITMAP (output,TQMX86_NGPIO );u8 irq_type[TQMX86_NGPI ]; };
@@ -64,15 +66,10 @@ static void tqmx86_gpio_set(struct gpio_chip *chip, unsigned int offset, {struct tqmx86_gpio_data *gpio =gpiochip_get_data (chip);unsigned long flags; -u8 val;raw_spin_lock_irqsave (&gpio->spinlock, flags); - val =tqmx86_gpio_read (gpio,TQMX86_GPIOD ); -if (value) - val |=BIT (offset); -else - val &= ~BIT (offset); -tqmx86_gpio_write (gpio, val,TQMX86_GPIOD ); +__assign_bit (offset, gpio->output, value); +tqmx86_gpio_write (gpio,bitmap_get_value8 (gpio->output,0 ),TQMX86_GPIOD );raw_spin_unlock_irqrestore (&gpio->spinlock, flags); }
@@ -277,6 +274,13 @@ static int tqmx86_gpio_probe(struct platform_device *pdev)tqmx86_gpio_write (gpio, (u8 )~TQMX86_DIR_INPUT_MASK ,TQMX86_GPIODD ); +/* +* Reading the previous output state is not possible with TQMx86 hardware. +* Initialize all outputs to 0 to have a defined state that matches the +* shadow register. +*/ +tqmx86_gpio_write (gpio,0 ,TQMX86_GPIOD ); + chip = &gpio->chip; chip->label ="gpio-tqmx86" ; chip->owner =THIS_MODULE ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 127/267 gpio: tqmx86: store IRQ trigger type and unmask status separately
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthias Schiffer <[email protected]>
[ Upstream commit 08af509efdf8dad08e972b48de0e2c2a7919ea8b ]
irq_set_type() should not implicitly unmask the IRQ.
All accesses to the interrupt configuration register are moved to a new helper tqmx86_gpio_irq_config(). We also introduce the new rule that accessing irq_type must happen while locked, which will become significant for fixing EDGE_BOTH handling.
--- drivers/gpio/gpio-tqmx86.c | 48 ++++++++++++++++++++++---------------- 1 file changed, 28 insertions(+), 20 deletions(-)
drivers/gpio/gpio-tqmx86.c +28 -20
@@ -29,15 +29,19 @@#define TQMX86_GPIIC 3/* GPI Interrupt Configuration Register */ #define TQMX86_GPIIS 4/* GPI Interrupt Status Register */ +#define TQMX86_GPII_NONE 0#define TQMX86_GPII_FALLING BIT(0)#define TQMX86_GPII_RISING BIT(1)#define TQMX86_GPII_MASK (BIT(0) | BIT(1))#define TQMX86_GPII_BITS 2 +/* Stored in irq_type with GPII bits */ +#define TQMX86_INT_UNMASKED BIT(2)struct tqmx86_gpio_data {struct gpio_chip chip;void __iomem *io_base;int irq; +/* Lock must be held for accessing output and irq_type fields */ raw_spinlock_t spinlock; DECLARE_BITMAP(output, TQMX86_NGPIO);u8 irq_type[TQMX86_NGPI ];
@@ -104,21 +108,32 @@ static int tqmx86_gpio_get_direction(struct gpio_chip *chip,return GPIO_LINE_DIRECTION_OUT ; } +static void tqmx86_gpio_irq_config (struct tqmx86_gpio_data *gpio,int offset) + __must_hold(&gpio->spinlock) +{ +u8 type =TQMX86_GPII_NONE , gpiic; + +if (gpio->irq_type[offset] &TQMX86_INT_UNMASKED ) + type = gpio->irq_type[offset] &TQMX86_GPII_MASK ; + + gpiic =tqmx86_gpio_read (gpio,TQMX86_GPIIC ); + gpiic &= ~(TQMX86_GPII_MASK << (offset *TQMX86_GPII_BITS )); + gpiic |= type << (offset *TQMX86_GPII_BITS ); +tqmx86_gpio_write (gpio, gpiic,TQMX86_GPIIC ); +} +static void tqmx86_gpio_irq_mask (struct irq_data *data) {unsigned int offset = (data->hwirq -TQMX86_NGPO );struct tqmx86_gpio_data *gpio =gpiochip_get_data (irq_data_get_irq_chip_data (data));unsigned long flags; -u8 gpiic, mask; - - mask =TQMX86_GPII_MASK << (offset *TQMX86_GPII_BITS );raw_spin_lock_irqsave (&gpio->spinlock, flags); - gpiic =tqmx86_gpio_read (gpio,TQMX86_GPIIC ); - gpiic &= ~mask; -tqmx86_gpio_write (gpio, gpiic,TQMX86_GPIIC ); + gpio->irq_type[offset] &= ~TQMX86_INT_UNMASKED ; +tqmx86_gpio_irq_config (gpio, offset);raw_spin_unlock_irqrestore (&gpio->spinlock, flags); +gpiochip_disable_irq (&gpio->chip,irqd_to_hwirq (data)); }
@@ -128,16 +143,12 @@ static void tqmx86_gpio_irq_unmask(struct irq_data *data)struct tqmx86_gpio_data *gpio =gpiochip_get_data (irq_data_get_irq_chip_data (data));unsigned long flags; -u8 gpiic, mask; - - mask =TQMX86_GPII_MASK << (offset *TQMX86_GPII_BITS );gpiochip_enable_irq (&gpio->chip,irqd_to_hwirq (data)); +raw_spin_lock_irqsave (&gpio->spinlock, flags); - gpiic =tqmx86_gpio_read (gpio,TQMX86_GPIIC ); - gpiic &= ~mask; - gpiic |= gpio->irq_type[offset] << (offset *TQMX86_GPII_BITS ); -tqmx86_gpio_write (gpio, gpiic,TQMX86_GPIIC ); + gpio->irq_type[offset] |=TQMX86_INT_UNMASKED ; +tqmx86_gpio_irq_config (gpio, offset);raw_spin_unlock_irqrestore (&gpio->spinlock, flags); }
@@ -148,7 +159,7 @@ static int tqmx86_gpio_irq_set_type(struct irq_data *data, unsigned int type)unsigned int offset = (data->hwirq -TQMX86_NGPO );unsigned int edge_type = type &IRQF_TRIGGER_MASK ;unsigned long flags; -u8 new_type, gpiic; +u8 new_type;switch (edge_type) {case IRQ_TYPE_EDGE_RISING :
@@ -164,13 +175,10 @@ static int tqmx86_gpio_irq_set_type(struct irq_data *data, unsigned int type)return -EINVAL ;/* not supported */ } - gpio->irq_type[offset] = new_type; -raw_spin_lock_irqsave (&gpio->spinlock, flags); - gpiic =tqmx86_gpio_read (gpio,TQMX86_GPIIC ); - gpiic &= ~((TQMX86_GPII_MASK ) << (offset *TQMX86_GPII_BITS )); - gpiic |= new_type << (offset *TQMX86_GPII_BITS ); -tqmx86_gpio_write (gpio, gpiic,TQMX86_GPIIC ); + gpio->irq_type[offset] &= ~TQMX86_GPII_MASK ; + gpio->irq_type[offset] |= new_type; +tqmx86_gpio_irq_config (gpio, offset);raw_spin_unlock_irqrestore (&gpio->spinlock, flags);return 0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 128/267 gpio: tqmx86: fix broken IRQ_TYPE_EDGE_BOTH interrupt type
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthias Schiffer <[email protected]>
[ Upstream commit 90dd7de4ef7ba584823dfbeba834c2919a4bb55b ]
The TQMx86 GPIO controller only supports falling and rising edge triggers, but not both. Fix this by implementing a software both-edge mode that toggles the edge type after every interrupt.
--- drivers/gpio/gpio-tqmx86.c | 46 ++++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-)
drivers/gpio/gpio-tqmx86.c +42 -4
@@ -32,6 +32,10 @@#define TQMX86_GPII_NONE 0#define TQMX86_GPII_FALLING BIT(0)#define TQMX86_GPII_RISING BIT(1) +/* Stored in irq_type as a trigger type, but not actually valid as a register +* value, so the name doesn't use "GPII" +*/ +#define TQMX86_INT_BOTH (BIT(0) | BIT(1))#define TQMX86_GPII_MASK (BIT(0) | BIT(1))#define TQMX86_GPII_BITS 2/* Stored in irq_type with GPII bits */
@@ -113,9 +117,15 @@ static void tqmx86_gpio_irq_config(struct tqmx86_gpio_data *gpio, int offset) {u8 type =TQMX86_GPII_NONE , gpiic; -if (gpio->irq_type[offset] &TQMX86_INT_UNMASKED ) +if (gpio->irq_type[offset] &TQMX86_INT_UNMASKED ) { type = gpio->irq_type[offset] &TQMX86_GPII_MASK ; +if (type ==TQMX86_INT_BOTH ) + type =tqmx86_gpio_get (&gpio->chip, offset +TQMX86_NGPO ) + ?TQMX86_GPII_FALLING + :TQMX86_GPII_RISING ; + } + gpiic =tqmx86_gpio_read (gpio,TQMX86_GPIIC ); gpiic &= ~(TQMX86_GPII_MASK << (offset *TQMX86_GPII_BITS )); gpiic |= type << (offset *TQMX86_GPII_BITS );
@@ -169,7 +179,7 @@ static int tqmx86_gpio_irq_set_type(struct irq_data *data, unsigned int type) new_type =TQMX86_GPII_FALLING ;break ;case IRQ_TYPE_EDGE_BOTH : - new_type =TQMX86_GPII_FALLING |TQMX86_GPII_RISING ; + new_type =TQMX86_INT_BOTH ;break ;default :return -EINVAL ;/* not supported */
@@ -189,8 +199,8 @@ static void tqmx86_gpio_irq_handler(struct irq_desc *desc)struct gpio_chip *chip =irq_desc_get_handler_data (desc);struct tqmx86_gpio_data *gpio =gpiochip_get_data (chip);struct irq_chip *irq_chip =irq_desc_get_chip (desc); -unsigned long irq_bits; -int i =0 ; +unsigned long irq_bits, flags; +int i;u8 irq_status;chained_irq_enter (irq_chip, desc);
@@ -199,6 +209,34 @@ static void tqmx86_gpio_irq_handler(struct irq_desc *desc)tqmx86_gpio_write (gpio, irq_status,TQMX86_GPIIS ); irq_bits = irq_status; + +raw_spin_lock_irqsave (&gpio->spinlock, flags); +for_each_set_bit (i, &irq_bits,TQMX86_NGPI ) { +/* +* Edge-both triggers are implemented by flipping the edge +* trigger after each interrupt, as the controller only supports +* either rising or falling edge triggers, but not both. +* +* Internally, the TQMx86 GPIO controller has separate status +* registers for rising and falling edge interrupts. GPIIC +* configures which bits from which register are visible in the +* interrupt status register GPIIS and defines what triggers the +* parent IRQ line. Writing to GPIIS always clears both rising +* and falling interrupt flags internally, regardless of the +* currently configured trigger. +* +* In consequence, we can cleanly implement the edge-both +* trigger in software by first clearing the interrupt and then +* setting the new trigger based on the current GPIO input in +* tqmx86_gpio_irq_config() - even if an edge arrives between +* reading the input and setting the trigger, we will have a new +* interrupt pending. +*/ +if ((gpio->irq_type[i] &TQMX86_GPII_MASK ) ==TQMX86_INT_BOTH ) +tqmx86_gpio_irq_config (gpio, i); + } +raw_spin_unlock_irqrestore (&gpio->spinlock, flags); +for_each_set_bit (i, &irq_bits,TQMX86_NGPI )generic_handle_domain_irq (gpio->chip.irq.domain, i +TQMX86_NGPO );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 129/267 HID: core: remove unnecessary WARN_ON() in implement()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikita Zhandarovich <[email protected]>
[ Upstream commit 4aa2dcfbad538adf7becd0034a3754e1bd01b2b5 ]
Syzkaller hit a warning [1] in a call to implement() when trying to write a value into a field of smaller size in an output report.
Since implement() already has a warn message printed out with the help of hid_warn() and value in question gets trimmed with:
... value &= m; ...
WARN_ON may be considered superfluous. Remove it to suppress future syzkaller triggers.
[1]
WARNING: CPU: 0 PID: 5084 at drivers/hid/hid-core.c:1451 implement drivers/hid/hid-core.c:1451 [inline] WARNING: CPU: 0 PID: 5084 at drivers/hid/hid-core.c:1451 hid_output_report+0x548/0x760 drivers/hid/hid-core.c:1863 Modules linked in: CPU: 0 PID: 5084 Comm: syz-executor424 Not tainted 6.9.0-rc7-syzkaller-00183-gcf87f46fd34d #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 04/02/2024 RIP: 0010:implement drivers/hid/hid-core.c:1451 [inline] RIP: 0010:hid_output_report+0x548/0x760 drivers/hid/hid-core.c:1863 ... Call Trace: <TASK> __usbhid_submit_report drivers/hid/usbhid/hid-core.c:591 [inline] usbhid_submit_report+0x43d/0x9e0 drivers/hid/usbhid/hid-core.c:636 hiddev_ioctl+0x138b/0x1f00 drivers/hid/usbhid/hiddev.c:726 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:904 [inline] __se_sys_ioctl+0xfc/0x170 fs/ioctl.c:890 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xf5/0x240 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f
...
--- drivers/hid/hid-core.c | 1 - 1 file changed, 1 deletion(-)
drivers/hid/hid-core.c +0 -1
@@ -1448,7 +1448,6 @@ static void implement(const struct hid_device *hid, u8 *report,hid_warn (hid,"%s() called with too large value %d (n: %d)! (%s)\n" , __func__, value, n, current->comm); -WARN_ON (1 ); value &= m; } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 130/267 iommu/amd: Fix sysfs leak in iommu init
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kun(llfl) <[email protected]>
[ Upstream commit a295ec52c8624883885396fde7b4df1a179627c3 ]
During the iommu initialization, iommu_init_pci() adds sysfs nodes. However, these nodes aren't remove in free_iommu_resources() subsequently.
--- drivers/iommu/amd/init.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/iommu/amd/init.c +9 -0
@@ -1692,8 +1692,17 @@ static void __init free_pci_segments(void) } } +static void __init free_sysfs (struct amd_iommu *iommu) +{ +if (iommu->iommu.dev) { +iommu_device_unregister (&iommu->iommu); +iommu_device_sysfs_remove (&iommu->iommu); + } +} +static void __init free_iommu_one (struct amd_iommu *iommu) { +free_sysfs (iommu);free_cwwb_sem (iommu);free_command_buffer (iommu);free_event_buffer (iommu);
Signature · 1 line
2.43.0