6.1.107-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainercover 6.1.107-rc1 review
This is the start of the stable review cycle for the 6.1.107 release. There are 321 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Thu, 29 Aug 2024 14:37:36 +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.1.107-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.1.y
and the diffstat can be found below.
thanks,
greg k-h
-------------
Pseudo-Shortlog of commits:
Greg Kroah-Hartman <[email protected]>
Linux 6.1.107-rc1
Tetsuo Handa <[email protected]>
Input: MT - limit max slots
Paolo Abeni <[email protected]>
selftests: net: more strict check in net_helper
Yuri Benditovich <[email protected]>
net: change maximum number of UDP segments to 128
Dave Kleikamp <[email protected]>
Revert "jfs: fix shift-out-of-bounds in dbJoin"
Jesse Brandeburg <[email protected]>
ice: fix W=1 headers mismatch
Felix Fietkau <[email protected]>
udp: fix receiving fraglist GSO packets
Andreas Gruenbacher <[email protected]>
gfs2: Remove freeze_go_demote_ok
Andreas Gruenbacher <[email protected]>
gfs2: Remove LM_FLAG_PRIORITY flag
Andreas Gruenbacher <[email protected]>
gfs2: don't withdraw if init_threads() got interrupted
Andreas Gruenbacher <[email protected]>
gfs2: Fix another freeze/thaw hang
Felix Fietkau <[email protected]>
wifi: cfg80211: fix receiving mesh packets without RFC1042 header
Felix Fietkau <[email protected]>
wifi: mac80211: fix potential null pointer dereference
Felix Fietkau <[email protected]>
wifi: mac80211: drop bogus static keywords in A-MSDU rx
Felix Fietkau <[email protected]>
wifi: mac80211: fix receiving mesh packets in forwarding=0 networks
Felix Fietkau <[email protected]>
wifi: mac80211: fix flow dissection for forwarded packets
Felix Fietkau <[email protected]>
wifi: mac80211: fix mesh forwarding
Felix Fietkau <[email protected]>
wifi: mac80211: fix mesh path discovery based on unicast packets
Johannes Berg <[email protected]>
wifi: mac80211: add documentation for amsdu_mesh_control
Willem de Bruijn <[email protected]>
net: drop bad gso csum_start and offset in virtio_net_hdr
Willem de Bruijn <[email protected]>
net: more strict VIRTIO_NET_HDR_GSO_UDP_L4 validation
Yan Zhai <[email protected]>
gso: fix dodgy bit handling for GSO_UDP_L4
Andrew Melnychenko <[email protected]>
udp: allow header check for dodgy GSO_UDP_L4 packets.
Jan Höppner <[email protected]>
Revert "s390/dasd: Establish DMA alignment"
Li RongQing <[email protected]>
KVM: x86: fire timer when it is migrated and expired, and in oneshot mode
Boyuan Zhang <[email protected]>
drm/amdgpu/vcn: not pause dpg for unified queue
Boyuan Zhang <[email protected]>
drm/amdgpu/vcn: identify unified queue in sw init
Lee, Chun-Yi <[email protected]>
Bluetooth: hci_ldisc: check HCI_UART_PROTO_READY flag in HCIUARTGETPROTO
Trond Myklebust <[email protected]>
nfsd: Fix a regression in nfsd_setattr()
NeilBrown <[email protected]>
nfsd: don't call locks_release_private() twice concurrently
Jeff Layton <[email protected]>
nfsd: drop the nfsd_put helper
NeilBrown <[email protected]>
nfsd: call nfsd_last_thread() before final nfsd_put()
NeilBrown <[email protected]>
NFSD: simplify error paths in nfsd_svc()
NeilBrown <[email protected]>
nfsd: separate nfsd_last_thread() from nfsd_put()
NeilBrown <[email protected]>
nfsd: Simplify code around svc_exit_thread() call in nfsd()
Zi Yan <[email protected]>
mm/numa: no task_numa_fault() call if PTE is changed
Zi Yan <[email protected]>
mm/numa: no task_numa_fault() call if PMD is changed
Hailong Liu <[email protected]>
mm/vmalloc: fix page mapping if vm_area_alloc_pages() with high order fallback to order 0
Takashi Iwai <[email protected]>
ALSA: timer: Relax start tick time check for slave timer elements
Javier Carrasco <[email protected]>
hwmon: (ltc2992) Fix memory leak in ltc2992_parse_dt()
Eric Dumazet <[email protected]>
tcp: do not export tcp_twsk_purge()
Alex Hung <[email protected]>
Revert "drm/amd/display: Validate hw_points_num before using it"
Greg Kroah-Hartman <[email protected]>
Revert "usb: gadget: uvc: cleanup request when not in correct state"
Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: only decrement add_addr_accepted for MPJ req
Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: re-using ID of unused flushed subflows
Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: re-using ID of unused removed subflows
Matthieu Baerts (NGI0) <[email protected]>
mptcp: pm: re-using ID of unused removed ADD_ADDR
Peng Fan <[email protected]>
pmdomain: imx: wait SSAR when i.MX93 power domain on
Ben Whitten <[email protected]>
mmc: dw_mmc: allow biu and ciu clocks to defer
Marc Zyngier <[email protected]>
KVM: arm64: Make ICC_*SGI*_EL1 undef in the absence of a vGICv3
Nikolay Kuratov <[email protected]>
cxgb4: add forgotten u64 ivlan cast before shift
Werner Sembach <[email protected]>
Input: i8042 - use new forcenorestore quirk to replace old buggy quirk combination
Werner Sembach <[email protected]>
Input: i8042 - add forcenorestore quirk to leave controller untouched even on s3
Siarhei Vishniakou <[email protected]>
HID: microsoft: Add rumble support to latest xbox controllers
Jason Gerecke <[email protected]>
HID: wacom: Defer calculation of resolution until resolution_code is known
Jiaxun Yang <[email protected]>
MIPS: Loongson64: Set timer mode in cpu-probe
Candice Li <[email protected]>
drm/amdgpu: Validate TA binary size
Namjae Jeon <[email protected]>
ksmbd: the buffer of smb2 query dir response has at least 1 byte
Chaotian Jing <[email protected]>
scsi: core: Fix the return value of scsi_logical_block_count()
Griffin Kroah-Hartman <[email protected]>
Bluetooth: MGMT: Add error handling to pair_device()
Dan Carpenter <[email protected]>
mmc: mmc_test: Fix NULL dereference on allocation failure
Dmitry Baryshkov <[email protected]>
drm/msm/dpu: cleanup FB if dpu_format_populate_layout fails
Abhinav Kumar <[email protected]>
drm/msm/dp: reset the link phy params before link training
Abhinav Kumar <[email protected]>
drm/msm/dp: fix the max supported bpp logic
Dmitry Baryshkov <[email protected]>
drm/msm/dpu: don't play tricks with debug macros
Sean Anderson <[email protected]>
net: xilinx: axienet: Fix dangling multicast addresses
Sean Anderson <[email protected]>
net: xilinx: axienet: Always disable promiscuous mode
Bharat Bhushan <[email protected]>
octeontx2-af: Fix CPT AF register offset calculation
Pablo Neira Ayuso <[email protected]>
netfilter: flowtable: validate vlan header
Eric Dumazet <[email protected]>
ipv6: prevent possible UAF in ip6_xmit()
Eric Dumazet <[email protected]>
ipv6: fix possible UAF in ip6_finish_output2()
Eric Dumazet <[email protected]>
ipv6: prevent UAF in ip6_send_skb()
Stephen Hemminger <[email protected]>
netem: fix return value if duplicate enqueue fails
Joseph Huang <[email protected]>
net: dsa: mv88e6xxx: Fix out-of-bound access
Dan Carpenter <[email protected]>
dpaa2-switch: Fix error checking in dpaa2_switch_seed_bp()
Maciej Fijalkowski <[email protected]>
ice: fix ICE_LAST_OFFSET formula
Maciej Fijalkowski <[email protected]>
ice: fix page reuse when PAGE_SIZE is over 8k
Maciej Fijalkowski <[email protected]>
ice: Pull out next_to_clean bump out of ice_put_rx_buf()
Maciej Fijalkowski <[email protected]>
ice: Store page count inside ice_rx_buf
Maciej Fijalkowski <[email protected]>
ice: Add xdp_buff to ice_rx_ring struct
Maciej Fijalkowski <[email protected]>
ice: Prepare legacy-rx for upcoming XDP multi-buffer support
Nikolay Aleksandrov <[email protected]>
bonding: fix xfrm state handling when clearing active slave
Nikolay Aleksandrov <[email protected]>
bonding: fix xfrm real_dev null pointer dereference
Nikolay Aleksandrov <[email protected]>
bonding: fix null pointer deref in bond_ipsec_offload_ok
Nikolay Aleksandrov <[email protected]>
bonding: fix bond_ipsec_offload_ok return type
Thomas Bogendoerfer <[email protected]>
ip6_tunnel: Fix broken GRO
Sebastian Andrzej Siewior <[email protected]>
netfilter: nft_counter: Synchronize nft_counter_reset() against reader.
Sebastian Andrzej Siewior <[email protected]>
netfilter: nft_counter: Disable BH in nft_counter_offload_stats().
Kuniyuki Iwashima <[email protected]>
kcm: Serialise kcm_sendmsg() for the same socket.
Jeremy Kerr <[email protected]>
net: mctp: test: Use correct skb for route input check
Florian Westphal <[email protected]>
tcp: prevent concurrent execution of tcp_sk_exit_batch
Eric Dumazet <[email protected]>
tcp/dccp: do not care about families in inet_twsk_purge()
Eric Dumazet <[email protected]>
tcp/dccp: bypass empty buckets in inet_twsk_purge()
Hangbin Liu <[email protected]>
selftests: udpgro: report error when receive failed
Lucas Karpinski <[email protected]>
selftests/net: synchronize udpgro tests' tx and rx connection
Simon Horman <[email protected]>
tc-testing: don't access non-existent variable on exception
Vladimir Oltean <[email protected]>
net: mscc: ocelot: serialize access to the injection/extraction groups
Vladimir Oltean <[email protected]>
net: mscc: ocelot: fix QoS class for injected packets with "ocelot-8021q"
Vladimir Oltean <[email protected]>
net: mscc: ocelot: use ocelot_xmit_get_vlan_info() also for FDMA and register injection
Vladimir Oltean <[email protected]>
net: dsa: tag_ocelot: call only the relevant portion of __skb_vlan_pop() on TX
Vladimir Oltean <[email protected]>
net: dsa: tag_ocelot: do not rely on skb_mac_header() for VLAN xmit
Luiz Augusto von Dentz <[email protected]>
Bluetooth: SMP: Fix assumption of Central always being Initiator
Luiz Augusto von Dentz <[email protected]>
Bluetooth: hci_core: Fix LE quote calculation
Lang Yu <[email protected]>
drm/amdkfd: reserve the BO before validating it
Maximilian Luz <[email protected]>
platform/surface: aggregator: Fix warning when controller is destroyed in probe
Rodrigo Siqueira <[email protected]>
drm/amd/display: Adjust cursor position
Filipe Manana <[email protected]>
btrfs: send: allow cloning non-aligned extent if it ends at i_size
David Sterba <[email protected]>
btrfs: replace sb::s_blocksize by fs_info::sectorsize
Long Li <[email protected]>
net: mana: Fix doorbell out of order violation and avoid unnecessary doorbell rings
Mikulas Patocka <[email protected]>
dm suspend: return -ERESTARTSYS instead of -EINTR
Breno Leitao <[email protected]>
i2c: tegra: Do not mark ACPI devices as irq safe
Michał Mirosław <[email protected]>
i2c: tegra: allow VI support to be compiled out
Michał Mirosław <[email protected]>
i2c: tegra: allow DVC support to be compiled out
Aurelien Jarno <[email protected]>
media: solo6x10: replace max(a, min(b, c)) by clamp(b, a, c)
Eric Dumazet <[email protected]>
gtp: pull network headers in gtp_dev_xmit()
Phil Chang <[email protected]>
hrtimer: Prevent queuing of hrtimer without a function callback
Jesse Zhang <[email protected]>
drm/amdgpu: fix dereference null return value for the function amdgpu_vm_pt_parent
Sagi Grimberg <[email protected]>
nvmet-rdma: fix possible bad dereference when freeing rsps
Baokun Li <[email protected]>
ext4: set the type of max_zeroout to unsigned int to avoid overflow
Guanrui Huang <[email protected]>
irqchip/gic-v3-its: Remove BUG_ON in its_vpe_irq_domain_alloc
Abdulrasaq Lawani <[email protected]>
fbdev: offb: replace of_node_put with __free(device_node)
Krishna Kurapati <[email protected]>
usb: dwc3: core: Skip setting event buffers for host only controllers
Gergo Koteles <[email protected]>
platform/x86: lg-laptop: fix %s null argument warning
Adrian Hunter <[email protected]>
clocksource: Make watchdog and suspend-timing multiplication overflow safe
Biju Das <[email protected]>
irqchip/renesas-rzg2l: Do not set TIEN and TINT source at the same time
Alexander Gordeev <[email protected]>
s390/iucv: fix receive buffer virtual vs physical address confusion
Oreoluwa Babatunde <[email protected]>
openrisc: Call setup_memory() earlier in the init sequence
NeilBrown <[email protected]>
NFS: avoid infinite loop in pnfs_update_layout.
Hannes Reinecke <[email protected]>
nvmet-tcp: do not continue for invalid icreq
Jian Shen <[email protected]>
net: hns3: add checking for vf id of mailbox
Alexandre Belloni <[email protected]>
rtc: nct3018y: fix possible NULL dereference
Richard Fitzgerald <[email protected]>
firmware: cirrus: cs_dsp: Initialize debugfs_root to invalid
Luiz Augusto von Dentz <[email protected]>
Bluetooth: bnep: Fix out-of-bound access
Keith Busch <[email protected]>
nvme: clear caller pointer on identify failure
Uwe Kleine-König <[email protected]>
usb: gadget: fsl: Increase size of name buffer for endpoints
Zhiguo Niu <[email protected]>
f2fs: fix to do sanity check in update_sit_entry
David Sterba <[email protected]>
btrfs: delete pointless BUG_ON check on quota root in btrfs_qgroup_account_extent()
David Sterba <[email protected]>
btrfs: change BUG_ON to assertion in tree_move_down()
David Sterba <[email protected]>
btrfs: send: handle unexpected data in header buffer in begin_cmd()
David Sterba <[email protected]>
btrfs: handle invalid root reference found in may_destroy_subvol()
David Sterba <[email protected]>
btrfs: tests: allocate dummy fs_info and root in test_find_delalloc()
David Sterba <[email protected]>
btrfs: change BUG_ON to assertion when checking for delayed_node root
David Sterba <[email protected]>
btrfs: delayed-inode: drop pointless BUG_ON in __btrfs_remove_delayed_item()
Michael Ellerman <[email protected]>
powerpc/boot: Only free if realloc() succeeds
Li zeming <[email protected]>
powerpc/boot: Handle allocation failure in simple_realloc()
Helge Deller <[email protected]>
parisc: Use irq_enter_rcu() to fix warning at kernel/context_tracking.c:367
Christophe Kerello <[email protected]>
memory: stm32-fmc2-ebi: check regmap_read return value
Kees Cook <[email protected]>
x86: Increase brk randomness entropy for 64-bit systems
Li Nan <[email protected]>
md: clean up invalid BUG_ON in md_ioctl
Eric Dumazet <[email protected]>
netlink: hold nlk->cb_mutex longer in __netlink_dump_start()
Martin Blumenstingl <[email protected]>
clocksource/drivers/arm_global_timer: Guard against division by zero
Stefan Hajnoczi <[email protected]>
virtiofs: forbid newlines in tags
Costa Shulyupin <[email protected]>
hrtimer: Select housekeeping CPU during migration
Erico Nunes <[email protected]>
drm/lima: set gp bus_stop bit before hard reset
Kees Cook <[email protected]>
net/sun3_82586: Avoid reading past buffer in debug output
Philipp Stanner <[email protected]>
media: drivers/media/dvb-core: copy user arrays safely
Justin Tee <[email protected]>
scsi: lpfc: Initialize status local variable in lpfc_sli4_repost_sgl_list()
Max Filippov <[email protected]>
fs: binfmt_elf_efpic: don't use missing interpreter's properties
Hans Verkuil <[email protected]>
media: pci: cx23885: check cx23885_vdev_init() return
Neel Natu <[email protected]>
kernfs: fix false-positive WARN(nr_mmapped) in kernfs_drain_open_files
Jan Kara <[email protected]>
quota: Remove BUG_ON from dqget()
Al Viro <[email protected]>
fuse: fix UAF in rcu pathwalks
Al Viro <[email protected]>
afs: fix __afs_break_callback() / afs_drop_open_mmap() race
Baokun Li <[email protected]>
ext4: do not trim the group with corrupted block bitmap
Daniel Wagner <[email protected]>
nvmet-trace: avoid dereferencing pointer too early
Andreas Gruenbacher <[email protected]>
gfs2: Refcounting fix in gfs2_thaw_super
Zijun Hu <[email protected]>
Bluetooth: hci_conn: Check non NULL function before calling for HFP offload
Andy Yan <[email protected]>
drm/rockchip: vop2: clear afbc en and transform bit for cluster window at linear mode
Kees Cook <[email protected]>
hwmon: (pc87360) Bounds check data->innr usage
Bard Liao <[email protected]>
ASoC: SOF: ipc4: check return value of snd_sof_ipc_msg_data
Kunwu Chan <[email protected]>
powerpc/xics: Check return value of kasprintf in icp_native_map_one_cpu
Ashish Mhetre <[email protected]>
memory: tegra: Skip SID programming if SID registers aren't set
Rob Clark <[email protected]>
drm/msm: Reduce fallout of fence signaling vs reclaim hangs
Li Lingfeng <[email protected]>
block: Fix lockdep warning in blk_mq_mark_tag_wait
Samuel Holland <[email protected]>
arm64: Fix KASAN random tag seed initialization
Masahiro Yamada <[email protected]>
rust: fix the default format for CONFIG_{RUSTC,BINDGEN}_VERSION_TEXT
Masahiro Yamada <[email protected]>
rust: suppress error messages from CONFIG_{RUSTC,BINDGEN}_VERSION_TEXT
Miguel Ojeda <[email protected]>
rust: work around bindgen 0.69.0 issue
Miguel Ojeda <[email protected]>
kbuild: rust_is_available: handle failures calling $RUSTC/$BINDGEN
Miguel Ojeda <[email protected]>
kbuild: rust_is_available: normalize version matching
Antoniu Miclaus <[email protected]>
hwmon: (ltc2992) Avoid division by zero
Chengfeng Ye <[email protected]>
IB/hfi1: Fix potential deadlock on &irq_src_lock and &dd->uctxt_lock
Gustavo A. R. Silva <[email protected]>
clk: visconti: Add bounds-checking coverage for struct visconti_pll_provider
Mukesh Sisodiya <[email protected]>
wifi: iwlwifi: fw: Fix debugfs command sending
Miri Korenblit <[email protected]>
wifi: iwlwifi: abort scan when rfkill on but device enabled
Andreas Gruenbacher <[email protected]>
gfs2: setattr_chown: Add missing initialization
Mike Christie <[email protected]>
scsi: spi: Fix sshdr use
Hans Verkuil <[email protected]>
media: qcom: venus: fix incorrect return value
Mikko Perttunen <[email protected]>
drm/tegra: Zero-initialize iosys_map
Christian Brauner <[email protected]>
binfmt_misc: cleanup on filesystem umount
Yu Kuai <[email protected]>
md/raid5-cache: use READ_ONCE/WRITE_ONCE for 'conf->log'
Chengfeng Ye <[email protected]>
media: s5p-mfc: Fix potential deadlock on condlock
Chengfeng Ye <[email protected]>
staging: ks7010: disable bh on tx_dev_lock
Alex Hung <[email protected]>
drm/amd/display: Validate hw_points_num before using it
Michael Grzeschik <[email protected]>
usb: gadget: uvc: cleanup request when not in correct state
David Lechner <[email protected]>
staging: iio: resolver: ad2s1210: fix use before initialization
Hans Verkuil <[email protected]>
media: radio-isa: use dev_name to fill in bus_info
Philip Yang <[email protected]>
drm/amdkfd: Move dma unmapping after TLB flush
Jarkko Nikula <[email protected]>
i3c: mipi-i3c-hci: Do not unmap region not mapped for transfer
Jarkko Nikula <[email protected]>
i3c: mipi-i3c-hci: Remove BUG() when Ring Abort request times out
Tomi Valkeinen <[email protected]>
drm/bridge: tc358768: Attempt to fix DSI horizontal timings
Heiko Carstens <[email protected]>
s390/smp,mcck: fix early IPI handling
Zhu Yanjun <[email protected]>
RDMA/rtrs: Fix the problem of variable not initialized fully
Wolfram Sang <[email protected]>
i2c: riic: avoid potential division by zero
Kamalesh Babulal <[email protected]>
cgroup: Avoid extra dereference in css_populate_dir()
Jeff Johnson <[email protected]>
wifi: cw1200: Avoid processing an invalid TIM IE
Paul E. McKenney <[email protected]>
rcu: Eliminate rcu_gp_slow_unregister() false positive
Zhen Lei <[email protected]>
rcu: Dump memory object info if callback function is invalid
Johannes Berg <[email protected]>
wifi: mac80211: fix BA session teardown race
Johannes Berg <[email protected]>
wifi: cfg80211: check wiphy mutex is held for wdev mutex
Rand Deeb <[email protected]>
ssb: Fix division by zero issue in ssb_calc_clock_rate
Lee Jones <[email protected]>
drm/amd/amdgpu/imu_v11_0: Increase buffer size to ensure all possible values can be stored
Parsa Poorshikhian <[email protected]>
ALSA: hda/realtek: Fix noise from speakers on Lenovo IdeaPad 3 15IAU7
Jie Wang <[email protected]>
net: hns3: fix a deadlock problem when config TC during resetting
Peiyang Wang <[email protected]>
net: hns3: use the user's cfg after reset
Jie Wang <[email protected]>
net: hns3: fix wrong use of semaphore up
Phil Sutter <[email protected]>
netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests
Phil Sutter <[email protected]>
netfilter: nf_tables: Introduce nf_tables_getobj_single
Phil Sutter <[email protected]>
netfilter: nf_tables: Carry reset boolean in nft_obj_dump_ctx
Phil Sutter <[email protected]>
netfilter: nf_tables: nft_obj_filter fits into cb->ctx
Phil Sutter <[email protected]>
netfilter: nf_tables: Carry s_idx in nft_obj_dump_ctx
Phil Sutter <[email protected]>
netfilter: nf_tables: A better name for nft_obj_filter
Phil Sutter <[email protected]>
netfilter: nf_tables: Unconditionally allocate nft_obj_filter
Phil Sutter <[email protected]>
netfilter: nf_tables: Drop pointless memset in nf_tables_dump_obj
Phil Sutter <[email protected]>
netfilter: nf_tables: Audit log dump reset after the fact
Florian Westphal <[email protected]>
netfilter: nf_queue: drop packets with cloned unconfirmed conntracks
Donald Hunter <[email protected]>
netfilter: flowtable: initialise extack before use
Tom Hughes <[email protected]>
netfilter: allow ipv6 fragments to arrive on different devices
Eugene Syromiatnikov <[email protected]>
mptcp: correct MPTCP_SUBFLOW_ATTR_SSN_OFFSET reserved size
David Thompson <[email protected]>
mlxbf_gige: disable RX filters until RX path initialized
Yue Haibing <[email protected]>
mlxbf_gige: Remove two unused function declarations
Pawel Dembicki <[email protected]>
net: dsa: vsc73xx: check busy flag in MDIO operations
Pawel Dembicki <[email protected]>
net: dsa: vsc73xx: use read_poll_timeout instead delay loop
Pawel Dembicki <[email protected]>
net: dsa: vsc73xx: pass value in phy_write operation
Radhey Shyam Pandey <[email protected]>
net: axienet: Fix register defines comment description
Dan Carpenter <[email protected]>
atm: idt77252: prevent use after free in dequeue_rx()
Cosmin Ratiu <[email protected]>
net/mlx5e: Correctly report errors for ethtool rx flows
Dragos Tatulea <[email protected]>
net/mlx5e: Take state lock during tx timeout reporter
Faizal Rahim <[email protected]>
igc: Fix packet still tx after gate close by reducing i226 MAC retry buffer
Muhammad Husaini Zulkifli <[email protected]>
igc: Correct the launchtime offset
Takashi Iwai <[email protected]>
ALSA: usb: Fix UBSAN warning in parse_audio_unit()
Konstantin Komarov <[email protected]>
fs/ntfs3: Do copy_to_user out of run_lock
Pei Li <[email protected]>
jfs: Fix shift-out-of-bounds in dbDiscardAG
Edward Adam Davis <[email protected]>
jfs: fix null ptr deref in dtInsertEntry
Willem de Bruijn <[email protected]>
fou: remove warn in gue_gro_receive on unsupported protocol
yunshui <[email protected]>
bpf, net: Use DEV_STAT_INC()
Jan Kara <[email protected]>
udf: Fix bogus checksum computation in udf_rename()
Jan Kara <[email protected]>
ext4: do not create EA inode under buffer lock
Jan Kara <[email protected]>
ext4: fold quota accounting into ext4_xattr_inode_lookup_create()
Li Zhong <[email protected]>
ext4: check the return value of ext4_xattr_inode_dec_ref()
Luiz Augusto von Dentz <[email protected]>
Bluetooth: RFCOMM: Fix not validating setsockopt user input
Alexei Starovoitov <[email protected]>
bpf: Avoid kfree_rcu() under lock in bpf_lpm_trie.
Kees Cook <[email protected]>
bpf: Replace bpf_lpm_trie_key 0-length array with flexible array
Donald Hunter <[email protected]>
docs/bpf: Document BPF_MAP_TYPE_LPM_TRIE map
Johannes Berg <[email protected]>
wifi: cfg80211: check A-MSDU format more carefully
Felix Fietkau <[email protected]>
wifi: mac80211: add a workaround for receiving non-standard mesh A-MSDU
Felix Fietkau <[email protected]>
wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces
Felix Fietkau <[email protected]>
wifi: mac80211: remove mesh forwarding congestion check
Felix Fietkau <[email protected]>
wifi: cfg80211: factor out bridge tunnel / RFC1042 header check
Felix Fietkau <[email protected]>
wifi: cfg80211: move A-MSDU check in ieee80211_data_to_8023_exthdr
Felix Fietkau <[email protected]>
wifi: mac80211: fix and simplify unencrypted drop check for mesh
Gavrilov Ilia <[email protected]>
pppoe: Fix memory leak in pppoe_sendmsg()
Dmitry Antipov <[email protected]>
net: sctp: fix skb leak in sctp_inq_free()
Allison Henderson <[email protected]>
net:rds: Fix possible deadlock in rds_message_put
Jan Kara <[email protected]>
quota: Detect loops in quota tree
Gao Xiang <[email protected]>
erofs: avoid debugging output for (de)compressed data
Edward Adam Davis <[email protected]>
reiserfs: fix uninit-value in comp_keys
Phillip Lougher <[email protected]>
Squashfs: fix variable overflow triggered by sysbot
Lizhi Xu <[email protected]>
squashfs: squashfs_read_data need to check if the length is 0
Manas Ghandat <[email protected]>
jfs: fix shift-out-of-bounds in dbJoin
Jakub Kicinski <[email protected]>
net: don't dump stack on queue timeout
Yajun Deng <[email protected]>
net: sched: Print msecs when transmit queue time out
Johannes Berg <[email protected]>
wifi: mac80211: fix change_address deadlock during unregister
Johannes Berg <[email protected]>
wifi: mac80211: take wiphy lock for MAC addr change
Ying Hsu <[email protected]>
Bluetooth: Fix hci_link_tx_to RCU lock usage
Andreas Gruenbacher <[email protected]>
gfs2: Stop using gfs2_make_fs_ro for withdraw
Andreas Gruenbacher <[email protected]>
gfs2: Rework freeze / thaw logic
Andreas Gruenbacher <[email protected]>
gfs2: Rename SDF_{FS_FROZEN => FREEZE_INITIATOR}Andreas Gruenbacher <[email protected]>
gfs2: Rename gfs2_freeze_lock{ => _shared }Andreas Gruenbacher <[email protected]>
gfs2: Rename the {freeze,thaw}_super callbacks
Andreas Gruenbacher <[email protected]>
gfs2: Rename remaining "transaction" glock references
Kees Cook <[email protected]>
pid: Replace struct pid 1-element array with flex-array
Thomas Gleixner <[email protected]>
posix-timers: Ensure timer ID search-loop limit is valid
Andrii Nakryiko <[email protected]>
bpf: drop unnecessary user-triggerable WARN_ONCE in verifierl log
Andrii Nakryiko <[email protected]>
bpf: Split off basic BPF verifier log into separate file
Ivan Orlov <[email protected]>
mm: khugepaged: fix kernel BUG in hpage_collapse_scan_file()
Tetsuo Handa <[email protected]>
nilfs2: initialize "struct nilfs_binfo_dat"->bi_pad field
Ivan Orlov <[email protected]>
9P FS: Fix wild-memory-access write in v9fs_get_acl
Theodore Ts'o <[email protected]>
ext4, jbd2: add an optimized bmap for the journal inode
Ryusuke Konishi <[email protected]>
nilfs2: prevent WARNING in nilfs_dat_commit_end()
Leon Hwang <[email protected]>
bpf: Fix updating attached freplace prog in prog_array map
Claudio Imbrenda <[email protected]>
s390/uv: Panic for set and remove shared access UVC errors
Alex Deucher <[email protected]>
drm/amdgpu/jpeg2: properly set atomics vmid field
Al Viro <[email protected]>
memcg_write_event_control(): fix a user-triggerable oops
Bas Nieuwenhuizen <[email protected]>
drm/amdgpu: Actually check flags for all context ops.
Qu Wenruo <[email protected]>
btrfs: tree-checker: add dev extent item checks
Naohiro Aota <[email protected]>
btrfs: zoned: properly take lock to read/update block group's zoned variables
Waiman Long <[email protected]>
mm/memory-failure: use raw_spinlock_t in struct memory_failure_cpu
Zhen Lei <[email protected]>
selinux: fix potential counting error in avc_add_xperms_decision()
Max Kellermann <[email protected]>
fs/netfs/fscache_cookie: add missing "n_accesses" check
Dan Carpenter <[email protected]>
rtla/osnoise: Prevent NULL dereference in error handling
Andi Shyti <[email protected]>
i2c: qcom-geni: Add missing geni_icc_disable in geni_i2c_runtime_resume
Al Viro <[email protected]>
fix bitmap corruption on close_range() with CLOSE_RANGE_UNSHARE
Alexander Lobakin <[email protected]>
bitmap: introduce generic optimized bitmap_size()
Alexander Lobakin <[email protected]>
btrfs: rename bitmap_set_bits() -> btrfs_bitmap_set_bits()
Alexander Lobakin <[email protected]>
s390/cio: rename bitmap_size() -> idset_bitmap_size()
Alexander Lobakin <[email protected]>
fs/ntfs3: add prefix to bitmap_size() and use BITS_TO_U64()
Zhihao Cheng <[email protected]>
vfs: Don't evict inode under the inode lru traversing context
Mikulas Patocka <[email protected]>
dm persistent data: fix memory allocation failure
Khazhismel Kumykov <[email protected]>
dm resume: don't return EINVAL when signalled
Haibo Xu <[email protected]>
arm64: ACPI: NUMA: initialize all values of acpi_early_node_map to NUMA_NO_NODE
Nam Cao <[email protected]>
riscv: change XIP's kernel_map.size to be size of the entire kernel
Stefan Haberland <[email protected]>
s390/dasd: fix error recovery leading to data corruption on ESE devices
Mika Westerberg <[email protected]>
thunderbolt: Mark XDomain as unplugged when router is removed
Mathias Nyman <[email protected]>
xhci: Fix Panther point NULL pointer deref at full-speed re-enumeration
Juan José Arboleda <[email protected]>
ALSA: usb-audio: Support Yamaha P-125 quirk entry
Lianqin Hu <[email protected]>
ALSA: usb-audio: Add delay quirk for VIVO USB-C-XE710 HEADSET
Eli Billauer <[email protected]>
char: xillybus: Check USB endpoints when probing device
Eli Billauer <[email protected]>
char: xillybus: Refine workqueue handling
Eli Billauer <[email protected]>
char: xillybus: Don't destroy workqueue from work item running on it
Jann Horn <[email protected]>
fuse: Initialize beyond-EOF page contents before setting uptodate
Mathieu Othacehe <[email protected]>
tty: atmel_serial: use the correct RTS flag.
-------------
Diffstat:
Documentation/bpf/map_lpm_trie.rst | 181 ++++++++++ Documentation/filesystems/gfs2-glocks.rst | 3 +- Makefile | 4 +- arch/arm64/kernel/acpi_numa.c | 2 +- arch/arm64/kernel/setup.c | 3 - arch/arm64/kernel/smp.c | 2 + arch/arm64/kvm/sys_regs.c | 6 + arch/arm64/kvm/vgic/vgic.h | 7 + arch/mips/kernel/cpu-probe.c | 4 + arch/openrisc/kernel/setup.c | 6 +- arch/parisc/kernel/irq.c | 4 +- arch/powerpc/boot/simple_alloc.c | 7 +- arch/powerpc/sysdev/xics/icp-native.c | 2 + arch/riscv/mm/init.c | 4 +- arch/s390/include/asm/uv.h | 5 +- arch/s390/kernel/early.c | 12 +- arch/s390/kernel/smp.c | 4 +- arch/x86/kernel/process.c | 5 +- arch/x86/kvm/lapic.c | 8 +- block/blk-mq-tag.c | 5 +- drivers/atm/idt77252.c | 9 +- drivers/bluetooth/hci_ldisc.c | 3 +- drivers/char/xillybus/xillyusb.c | 42 ++- drivers/clk/visconti/pll.c | 6 +- drivers/clocksource/arm_global_timer.c | 11 +- drivers/firmware/cirrus/cs_dsp.c | 7 +- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 40 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 8 + drivers/gpu/drm/amd/amdgpu/amdgpu_psp_ta.c | 3 + drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 53 ++- drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 1 + drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c | 6 +- drivers/gpu/drm/amd/amdgpu/imu_v11_0.c | 2 +- drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c | 4 +- drivers/gpu/drm/amd/amdkfd/kfd_chardev.c | 24 +- .../drm/amd/display/dc/dcn10/dcn10_hw_sequencer.c | 2 +- drivers/gpu/drm/bridge/tc358768.c | 215 ++++++++++-- drivers/gpu/drm/lima/lima_gp.c | 12 + drivers/gpu/drm/msm/disp/dpu1/dpu_kms.h | 14 +- drivers/gpu/drm/msm/disp/dpu1/dpu_plane.c | 3 + drivers/gpu/drm/msm/dp/dp_ctrl.c | 2 + drivers/gpu/drm/msm/dp/dp_panel.c | 19 +- drivers/gpu/drm/msm/msm_gem_shrinker.c | 2 +- drivers/gpu/drm/rockchip/rockchip_drm_vop2.c | 5 + drivers/gpu/drm/tegra/gem.c | 2 +- drivers/hid/hid-ids.h | 10 +- drivers/hid/hid-microsoft.c | 11 +- drivers/hid/wacom_wac.c | 4 +- drivers/hwmon/ltc2992.c | 8 +- drivers/hwmon/pc87360.c | 6 +- drivers/i2c/busses/i2c-qcom-geni.c | 4 +- drivers/i2c/busses/i2c-riic.c | 2 +- drivers/i2c/busses/i2c-tegra.c | 41 ++- drivers/i3c/master/mipi-i3c-hci/dma.c | 5 +- drivers/infiniband/hw/hfi1/chip.c | 5 +- drivers/infiniband/ulp/rtrs/rtrs.c | 2 +- drivers/input/input-mt.c | 3 + drivers/input/serio/i8042-acpipnpio.h | 20 +- drivers/input/serio/i8042.c | 10 +- drivers/irqchip/irq-gic-v3-its.c | 2 - drivers/irqchip/irq-renesas-rzg2l.c | 5 +- drivers/md/dm-clone-metadata.c | 5 - drivers/md/dm-ioctl.c | 22 +- drivers/md/dm.c | 4 +- drivers/md/md.c | 5 - drivers/md/persistent-data/dm-space-map-metadata.c | 4 +- drivers/md/raid5-cache.c | 47 +-- drivers/media/dvb-core/dvb_frontend.c | 12 +- drivers/media/pci/cx23885/cx23885-video.c | 8 + drivers/media/pci/solo6x10/solo6x10-offsets.h | 10 +- drivers/media/platform/qcom/venus/pm_helpers.c | 2 +- .../media/platform/samsung/s5p-mfc/s5p_mfc_enc.c | 2 +- drivers/media/radio/radio-isa.c | 2 +- drivers/memory/stm32-fmc2-ebi.c | 122 +++++-- drivers/memory/tegra/tegra186.c | 3 + drivers/mmc/core/mmc_test.c | 9 +- drivers/mmc/host/dw_mmc.c | 8 + drivers/net/bonding/bond_main.c | 21 +- drivers/net/bonding/bond_options.c | 2 +- drivers/net/dsa/mv88e6xxx/global1_atu.c | 3 +- drivers/net/dsa/ocelot/felix.c | 11 + drivers/net/dsa/vitesse-vsc73xx-core.c | 69 +++- drivers/net/ethernet/chelsio/cxgb4/cxgb4_filter.c | 3 +- .../net/ethernet/freescale/dpaa2/dpaa2-switch.c | 7 +- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 3 + .../ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 28 +- .../net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c | 7 +- .../ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c | 3 + .../ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 +- drivers/net/ethernet/i825xx/sun3_82586.c | 2 +- drivers/net/ethernet/intel/ice/ice_base.c | 4 +- drivers/net/ethernet/intel/ice/ice_lib.c | 8 +- drivers/net/ethernet/intel/ice/ice_main.c | 10 +- drivers/net/ethernet/intel/ice/ice_txrx.c | 117 +++---- drivers/net/ethernet/intel/ice/ice_txrx.h | 6 +- drivers/net/ethernet/intel/ice/ice_txrx_lib.c | 1 + drivers/net/ethernet/intel/igc/igc_defines.h | 15 + drivers/net/ethernet/intel/igc/igc_main.c | 7 + drivers/net/ethernet/intel/igc/igc_regs.h | 1 + drivers/net/ethernet/intel/igc/igc_tsn.c | 64 ++++ drivers/net/ethernet/intel/igc/igc_tsn.h | 1 + .../net/ethernet/marvell/octeontx2/af/rvu_cpt.c | 23 +- .../ethernet/mellanox/mlx5/core/en/reporter_tx.c | 2 + .../ethernet/mellanox/mlx5/core/en_fs_ethtool.c | 2 +- .../net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h | 9 +- .../ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c | 10 + .../ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h | 2 + .../ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c | 50 ++- drivers/net/ethernet/microsoft/mana/mana.h | 1 + drivers/net/ethernet/microsoft/mana/mana_en.c | 22 +- drivers/net/ethernet/mscc/ocelot.c | 91 ++++- drivers/net/ethernet/mscc/ocelot_fdma.c | 3 +- drivers/net/ethernet/mscc/ocelot_vsc7514.c | 4 + drivers/net/ethernet/xilinx/xilinx_axienet.h | 17 +- drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 25 +- drivers/net/gtp.c | 3 + drivers/net/ppp/pppoe.c | 23 +- drivers/net/wireless/intel/iwlwifi/fw/debugfs.c | 6 +- drivers/net/wireless/intel/iwlwifi/mvm/scan.c | 2 +- .../net/wireless/marvell/mwifiex/11n_rxreorder.c | 2 +- drivers/net/wireless/st/cw1200/txrx.c | 2 +- drivers/nvme/host/core.c | 5 +- drivers/nvme/target/rdma.c | 16 +- drivers/nvme/target/tcp.c | 1 + drivers/nvme/target/trace.c | 6 +- drivers/nvme/target/trace.h | 28 +- drivers/platform/surface/aggregator/controller.c | 3 +- drivers/platform/x86/lg-laptop.c | 2 +- drivers/rtc/rtc-nct3018y.c | 6 +- drivers/s390/block/dasd.c | 36 +- drivers/s390/block/dasd_3990_erp.c | 10 +- drivers/s390/block/dasd_diag.c | 1 - drivers/s390/block/dasd_eckd.c | 58 ++- drivers/s390/block/dasd_int.h | 2 +- drivers/s390/cio/idset.c | 12 +- drivers/scsi/lpfc/lpfc_sli.c | 2 +- drivers/scsi/scsi_transport_spi.c | 4 +- drivers/soc/imx/imx93-pd.c | 5 +- drivers/ssb/main.c | 2 +- drivers/staging/iio/resolver/ad2s1210.c | 7 +- drivers/staging/ks7010/ks7010_sdio.c | 4 +- drivers/thunderbolt/switch.c | 1 + drivers/tty/serial/atmel_serial.c | 2 +- drivers/usb/dwc3/core.c | 13 + drivers/usb/gadget/udc/fsl_udc_core.c | 2 +- drivers/usb/host/xhci.c | 8 +- drivers/video/fbdev/offb.c | 3 +- fs/9p/xattr.c | 8 +- fs/afs/file.c | 8 +- fs/binfmt_elf_fdpic.c | 2 +- fs/binfmt_misc.c | 216 +++++++++--- fs/btrfs/delayed-inode.c | 4 +- fs/btrfs/disk-io.c | 2 + fs/btrfs/extent_io.c | 4 +- fs/btrfs/free-space-cache.c | 22 +- fs/btrfs/inode.c | 11 +- fs/btrfs/ioctl.c | 2 +- fs/btrfs/qgroup.c | 2 - fs/btrfs/reflink.c | 6 +- fs/btrfs/send.c | 63 +++- fs/btrfs/super.c | 2 +- fs/btrfs/tests/extent-io-tests.c | 28 +- fs/btrfs/tree-checker.c | 69 ++++ fs/erofs/decompressor.c | 8 +- fs/ext4/extents.c | 3 +- fs/ext4/mballoc.c | 3 + fs/ext4/super.c | 23 ++ fs/ext4/xattr.c | 158 ++++----- fs/f2fs/segment.c | 5 +- fs/file.c | 28 +- fs/fscache/cookie.c | 4 + fs/fuse/cuse.c | 3 +- fs/fuse/dev.c | 6 +- fs/fuse/fuse_i.h | 1 + fs/fuse/inode.c | 15 +- fs/fuse/virtio_fs.c | 10 + fs/gfs2/glock.c | 27 +- fs/gfs2/glock.h | 9 - fs/gfs2/glops.c | 66 ++-- fs/gfs2/incore.h | 2 +- fs/gfs2/inode.c | 2 +- fs/gfs2/lock_dlm.c | 5 - fs/gfs2/log.c | 2 - fs/gfs2/ops_fstype.c | 13 +- fs/gfs2/recovery.c | 28 +- fs/gfs2/super.c | 197 ++++++++--- fs/gfs2/super.h | 1 + fs/gfs2/sys.c | 2 +- fs/gfs2/util.c | 53 +-- fs/gfs2/util.h | 5 +- fs/inode.c | 39 ++- fs/jbd2/journal.c | 9 +- fs/jfs/jfs_dmap.c | 2 + fs/jfs/jfs_dtree.c | 2 + fs/kernfs/file.c | 8 +- fs/nfs/pnfs.c | 8 + fs/nfsd/nfs4proc.c | 4 + fs/nfsd/nfs4state.c | 2 +- fs/nfsd/nfsctl.c | 32 +- fs/nfsd/nfsd.h | 3 +- fs/nfsd/nfssvc.c | 85 ++--- fs/nfsd/vfs.c | 6 +- fs/nilfs2/btree.c | 1 + fs/nilfs2/dat.c | 11 + fs/nilfs2/direct.c | 1 + fs/ntfs3/bitmap.c | 4 +- fs/ntfs3/frecord.c | 75 +++- fs/ntfs3/fsntfs.c | 2 +- fs/ntfs3/index.c | 11 +- fs/ntfs3/ntfs_fs.h | 4 +- fs/ntfs3/super.c | 2 +- fs/quota/dquot.c | 5 +- fs/quota/quota_tree.c | 128 +++++-- fs/quota/quota_v2.c | 15 +- fs/reiserfs/stree.c | 2 +- fs/smb/server/smb2pdu.c | 3 +- fs/squashfs/block.c | 2 +- fs/squashfs/file.c | 3 +- fs/squashfs/file_direct.c | 6 +- fs/udf/namei.c | 1 - include/linux/bitmap.h | 20 +- include/linux/bpf_verifier.h | 23 +- include/linux/cpumask.h | 2 +- include/linux/dsa/ocelot.h | 47 +++ include/linux/fs.h | 5 + include/linux/if_vlan.h | 21 ++ include/linux/jbd2.h | 8 + include/linux/pid.h | 2 +- include/linux/sched/signal.h | 2 +- include/linux/sunrpc/svc.h | 13 - include/linux/udp.h | 2 +- include/linux/virtio_net.h | 35 +- include/net/cfg80211.h | 40 ++- include/net/inet_timewait_sock.h | 2 +- include/net/kcm.h | 1 + include/net/tcp.h | 2 +- include/scsi/scsi_cmnd.h | 2 +- include/soc/mscc/ocelot.h | 12 +- include/trace/events/huge_memory.h | 3 +- include/uapi/linux/bpf.h | 19 +- init/Kconfig | 7 +- kernel/bpf/Makefile | 3 +- kernel/bpf/log.c | 82 +++++ kernel/bpf/lpm_trie.c | 33 +- kernel/bpf/verifier.c | 69 ---- kernel/cgroup/cgroup.c | 4 +- kernel/pid.c | 7 +- kernel/pid_namespace.c | 2 +- kernel/rcu/rcu.h | 7 + kernel/rcu/srcutiny.c | 1 + kernel/rcu/srcutree.c | 1 + kernel/rcu/tasks.h | 1 + kernel/rcu/tiny.c | 1 + kernel/rcu/tree.c | 3 +- kernel/time/clocksource.c | 42 ++- kernel/time/hrtimer.c | 5 +- kernel/time/posix-timers.c | 31 +- lib/math/prime_numbers.c | 2 - mm/huge_memory.c | 30 +- mm/khugepaged.c | 20 ++ mm/memcontrol.c | 7 +- mm/memory-failure.c | 20 +- mm/memory.c | 29 +- mm/vmalloc.c | 11 +- net/bluetooth/bnep/core.c | 3 +- net/bluetooth/hci_conn.c | 11 +- net/bluetooth/hci_core.c | 24 +- net/bluetooth/mgmt.c | 4 + net/bluetooth/rfcomm/sock.c | 14 +- net/bluetooth/smp.c | 146 ++++---- net/bridge/br_netfilter_hooks.c | 6 +- net/core/filter.c | 8 +- net/core/skbuff.c | 8 +- net/dccp/ipv4.c | 2 +- net/dccp/ipv6.c | 6 - net/dsa/tag_ocelot.c | 37 +- net/ipv4/fou.c | 2 +- net/ipv4/inet_timewait_sock.c | 16 +- net/ipv4/tcp_ipv4.c | 16 +- net/ipv4/tcp_minisocks.c | 7 +- net/ipv4/tcp_offload.c | 3 + net/ipv4/udp_offload.c | 18 +- net/ipv6/ip6_output.c | 10 + net/ipv6/ip6_tunnel.c | 12 +- net/ipv6/netfilter/nf_conntrack_reasm.c | 4 + net/ipv6/tcp_ipv6.c | 6 - net/iucv/iucv.c | 3 +- net/kcm/kcmsock.c | 4 + net/mac80211/agg-tx.c | 6 +- net/mac80211/debugfs_netdev.c | 3 - net/mac80211/driver-ops.c | 3 - net/mac80211/ieee80211_i.h | 1 - net/mac80211/iface.c | 27 +- net/mac80211/rx.c | 387 +++++++++++---------- net/mac80211/sta_info.c | 17 + net/mac80211/sta_info.h | 3 + net/mctp/test/route-test.c | 2 +- net/mptcp/diag.c | 2 +- net/mptcp/pm_netlink.c | 31 +- net/netfilter/nf_flow_table_inet.c | 3 + net/netfilter/nf_flow_table_ip.c | 3 + net/netfilter/nf_flow_table_offload.c | 2 +- net/netfilter/nf_tables_api.c | 225 +++++++----- net/netfilter/nfnetlink_queue.c | 35 +- net/netfilter/nft_counter.c | 9 +- net/netlink/af_netlink.c | 13 +- net/rds/recv.c | 13 +- net/sched/sch_generic.c | 11 +- net/sched/sch_netem.c | 47 ++- net/sctp/inqueue.c | 14 +- net/wireless/core.h | 8 +- net/wireless/util.c | 195 +++++++---- samples/bpf/map_perf_test_user.c | 2 +- samples/bpf/xdp_router_ipv4_user.c | 2 +- scripts/rust_is_available.sh | 41 ++- security/selinux/avc.c | 2 +- sound/core/timer.c | 2 +- sound/pci/hda/patch_realtek.c | 1 - sound/soc/sof/ipc4.c | 9 +- sound/usb/mixer.c | 7 + sound/usb/quirks-table.h | 1 + sound/usb/quirks.c | 2 + tools/include/linux/bitmap.h | 7 +- tools/include/uapi/linux/bpf.h | 19 +- tools/testing/selftests/bpf/progs/map_ptr_kern.c | 2 +- tools/testing/selftests/bpf/test_lpm_map.c | 18 +- tools/testing/selftests/core/close_range_test.c | 35 ++ tools/testing/selftests/net/net_helper.sh | 25 ++ tools/testing/selftests/net/udpgro.sh | 57 +-- tools/testing/selftests/net/udpgro_bench.sh | 5 +- tools/testing/selftests/net/udpgro_frglist.sh | 5 +- tools/testing/selftests/net/udpgso.c | 2 +- tools/testing/selftests/tc-testing/tdc.py | 1 - tools/tracing/rtla/src/osnoise_top.c | 11 +- 335 files changed, 4050 insertions(+), 2027 deletions(-)
Greg Kroah-Hartman
maintainerPATCH 1/321 tty: atmel_serial: use the correct RTS flag.
6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mathieu Othacehe <[email protected]>
commit c9f6613b16123989f2c3bd04b1d9b2365d6914e7 upstream.
In RS485 mode, the RTS pin is driven high by hardware when the transmitter is operating. This behaviour cannot be changed. This means that the driver should claim that it supports SER_RS485_RTS_ON_SEND and not SER_RS485_RTS_AFTER_SEND.
Otherwise, when configuring the port with the SER_RS485_RTS_ON_SEND, one get the following warning:
kern.warning kernel: atmel_usart_serial atmel_usart_serial.2.auto:
ttyS1 (1): invalid RTS setting, using RTS_AFTER_SEND instead
which is contradictory with what's really happening.
--- drivers/tty/serial/atmel_serial.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/tty/serial/atmel_serial.c +1 -1
@@ -2539,7 +2539,7 @@ static const struct uart_ops atmel_pops };static const struct serial_rs485 atmel_rs485_supported = { - .flags =SER_RS485_ENABLED |SER_RS485_RTS_AFTER_SEND |SER_RS485_RX_DURING_TX , + .flags =SER_RS485_ENABLED |SER_RS485_RTS_ON_SEND |SER_RS485_RX_DURING_TX , .delay_rts_before_send =1 , .delay_rts_after_send =1 , };
Greg Kroah-Hartman
maintainerPATCH 2/321 fuse: Initialize beyond-EOF page contents before setting uptodate
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jann Horn <[email protected]>
commit 3c0da3d163eb32f1f91891efaade027fa9b245b9 upstream.
fuse_notify_store(), unlike fuse_do_readpage(), does not enable page zeroing (because it can be used to change partial page contents).
So fuse_notify_store() must be more careful to fully initialize page contents (including parts of the page that are beyond end-of-file) before marking the page uptodate.
The current code can leave beyond-EOF page contents uninitialized, which makes these uninitialized page contents visible to userspace via mmap().
This is an information leak, but only affects systems which do not enable init-on-alloc (via CONFIG_INIT_ON_ALLOC_DEFAULT_ON=y or the corresponding kernel command line parameter).
--- fs/fuse/dev.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
fs/fuse/dev.c +4 -2
@@ -1615,9 +1615,11 @@ static int fuse_notify_store(struct fuse this_num =min_t (unsigned, num,PAGE_SIZE - offset); err =fuse_copy_page (cs, &page, offset, this_num,0 ); -if (!err && offset ==0 && - (this_num ==PAGE_SIZE || file_size == end)) +if (!PageUptodate (page) && !err && offset ==0 && + (this_num ==PAGE_SIZE || file_size == end)) { +zero_user_segment (page, this_num,PAGE_SIZE );SetPageUptodate (page); + }unlock_page (page);put_page (page);
Greg Kroah-Hartman
maintainerPATCH 3/321 char: xillybus: Dont destroy workqueue from work item running on it
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eli Billauer <[email protected]>
commit ccbde4b128ef9c73d14d0d7817d68ef795f6d131 upstream.
Triggered by a kref decrement, destroy_workqueue() may be called from within a work item for destroying its own workqueue. This illegal situation is averted by adding a module-global workqueue for exclusive use of the offending work item. Other work items continue to be queued on per-device workqueues to ensure performance.
--- drivers/char/xillybus/xillyusb.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
drivers/char/xillybus/xillyusb.c +11 -5
@@ -50,6 +50,7 @@ MODULE_LICENSE("GPL v2");static const char xillyname[] ="xillyusb" ;static unsigned int fifo_buf_order; +static struct workqueue_struct *wakeup_wq;#define USB_VENDOR_ID_XILINX 0x03fd#define USB_VENDOR_ID_ALTERA 0x09fb
@@ -561,10 +562,6 @@ static void cleanup_dev(struct kref *kre* errors if executed. The mechanism relies on that xdev->error is assigned * a non-zero value by report_io_error() prior to queueing wakeup_all(), * which prevents bulk_in_work() from calling process_bulk_in(). -* -* The fact that wakeup_all() and bulk_in_work() are queued on the same -* workqueue makes their concurrent execution very unlikely, however the -* kernel's API doesn't seem to ensure this strictly. */ static void wakeup_all (struct work_struct *work)
@@ -619,7 +616,7 @@ static void report_io_error(struct xillyif (do_once) {kref_get (&xdev->kref);/* xdev is used by work item */ -queue_work (xdev->workq, &xdev->wakeup_workitem); +queue_work (wakeup_wq, &xdev->wakeup_workitem); } }
@@ -2242,6 +2239,10 @@ static int __init xillyusb_init(void) {int rc =0 ; + wakeup_wq =alloc_workqueue (xillyname,0 ,0 ); +if (!wakeup_wq) +return -ENOMEM ; +if (LOG2_INITIAL_FIFO_BUF_SIZE >PAGE_SHIFT ) fifo_buf_order =LOG2_INITIAL_FIFO_BUF_SIZE -PAGE_SHIFT ;else
@@ -2249,11 +2250,16 @@ static int __init xillyusb_init(void) rc =usb_register (&xillyusb_driver); +if (rc) +destroy_workqueue (wakeup_wq); +return rc; } static void __exit xillyusb_exit(void) { +destroy_workqueue (wakeup_wq); +usb_deregister (&xillyusb_driver); }
Greg Kroah-Hartman
maintainerPATCH 4/321 char: xillybus: Refine workqueue handling
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eli Billauer <[email protected]>
commit ad899c301c880766cc709aad277991b3ab671b66 upstream.
As the wakeup work item now runs on a separate workqueue, it needs to be flushed separately along with flushing the device's workqueue.
Also, move the destroy_workqueue() call to the end of the exit method, so that deinitialization is done in the opposite order of initialization.
--- drivers/char/xillybus/xillyusb.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/char/xillybus/xillyusb.c +5 -3
@@ -2079,9 +2079,11 @@ static int xillyusb_discovery(struct usb* just after responding with the IDT, there is no reason for any * work item to be running now. To be sure that xdev->channels * is updated on anything that might run in parallel, flush the -* workqueue, which rarely does anything. +* device's workqueue and the wakeup work item. This rarely +* does anything. */ flush_workqueue (xdev->workq); +flush_work (&xdev->wakeup_workitem); xdev->num_channels = num_channels;
@@ -2258,9 +2260,9 @@ static int __init xillyusb_init(void) static void __exit xillyusb_exit(void) { -destroy_workqueue (wakeup_wq); -usb_deregister (&xillyusb_driver); + +destroy_workqueue (wakeup_wq); }module_init (xillyusb_init);
Greg Kroah-Hartman
maintainerPATCH 5/321 char: xillybus: Check USB endpoints when probing device
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eli Billauer <[email protected]>
commit 2374bf7558de915edc6ec8cb10ec3291dfab9594 upstream.
Ensure, as the driver probes the device, that all endpoints that the driver may attempt to access exist and are of the correct type.
All XillyUSB devices must have a Bulk IN and Bulk OUT endpoint at address 1. This is verified in xillyusb_setup_base_eps().
On top of that, a XillyUSB device may have additional Bulk OUT endpoints. The information about these endpoints' addresses is deduced from a data structure (the IDT) that the driver fetches from the device while probing it. These endpoints are checked in setup_channels().
A XillyUSB device never has more than one IN endpoint, as all data towards the host is multiplexed in this single Bulk IN endpoint. This is why setup_channels() only checks OUT endpoints.
--- drivers/char/xillybus/xillyusb.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-)
drivers/char/xillybus/xillyusb.c +20 -2
@@ -1889,6 +1889,13 @@ static const struct file_operations xillstatic int xillyusb_setup_base_eps (struct xillyusb_dev *xdev) { +struct usb_device *udev = xdev->udev; + +/* Verify that device has the two fundamental bulk in/out endpoints */ +if (usb_pipe_type_check (udev,usb_sndbulkpipe (udev,MSG_EP_NUM )) || +usb_pipe_type_check (udev,usb_rcvbulkpipe (udev,IN_EP_NUM ))) +return -ENODEV ; + xdev->msg_ep =endpoint_alloc (xdev,MSG_EP_NUM |USB_DIR_OUT , bulk_out_work,1 ,2 );if (!xdev->msg_ep)
@@ -1918,14 +1925,15 @@ static int setup_channels(struct xillyus __le16 *chandesc, int num_channels) { -struct xillyusb_channel *chan; +struct usb_device *udev = xdev->udev; +struct xillyusb_channel *chan, *new_channels;int i; chan =kcalloc (num_channels,sizeof (*chan),GFP_KERNEL );if (!chan)return -ENOMEM ; - xdev->channels = chan; + new_channels = chan;for (i =0 ; i < num_channels; i++, chan++) {unsigned int in_desc =le16_to_cpu (*chandesc++);
@@ -1954,6 +1962,15 @@ static int setup_channels(struct xillyus*/ if ((out_desc &0x80 ) && i <14 ) {/* Entry is valid */ +if (usb_pipe_type_check (udev, +usb_sndbulkpipe (udev, i +2 ))) { +dev_err (xdev->dev, +"Missing BULK OUT endpoint %d\n" , + i +2 ); +kfree (new_channels); +return -ENODEV ; + } + chan->writable =1 ; chan->out_synchronous = !!(out_desc &0x40 ); chan->out_seekable = !!(out_desc &0x20 );
@@ -1963,6 +1980,7 @@ static int setup_channels(struct xillyus } } + xdev->channels = new_channels;return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 6/321 ALSA: usb-audio: Add delay quirk for VIVO USB-C-XE710 HEADSET
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lianqin Hu <[email protected]>
commit 004eb8ba776ccd3e296ea6f78f7ae7985b12824e upstream.
Audio control requests that sets sampling frequency sometimes fail on this card. Adding delay between control messages eliminates that problem.
--- sound/usb/quirks.c | 2 ++ 1 file changed, 2 insertions(+)
sound/usb/quirks.c +2 -0
@@ -2179,6 +2179,8 @@ static const struct usb_audio_quirk_flag QUIRK_FLAG_GENERIC_IMPLICIT_FB),DEVICE_FLG (0x2b53 ,0x0031 ,/* Fiero SC-01 (firmware v1.1.0) */ QUIRK_FLAG_GENERIC_IMPLICIT_FB ), +DEVICE_FLG (0x2d95 ,0x8021 ,/* VIVO USB-C-XE710 HEADSET */ +QUIRK_FLAG_CTL_MSG_DELAY_1M ),DEVICE_FLG (0x30be ,0x0101 ,/* Schiit Hel */ QUIRK_FLAG_IGNORE_CTL_ERROR ), DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */
Greg Kroah-Hartman
maintainerPATCH 7/321 ALSA: usb-audio: Support Yamaha P-125 quirk entry
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Juan José Arboleda <[email protected]>
commit c286f204ce6ba7b48e3dcba53eda7df8eaa64dd9 upstream.
This patch adds a USB quirk for the Yamaha P-125 digital piano.
--- sound/usb/quirks-table.h | 1 + 1 file changed, 1 insertion(+)
sound/usb/quirks-table.h +1 -0
@@ -273,6 +273,7 @@ YAMAHA_DEVICE(0x105a, NULL), YAMAHA_DEVICE(0x105b, NULL), YAMAHA_DEVICE(0x105c, NULL), YAMAHA_DEVICE(0x105d, NULL), +YAMAHA_DEVICE(0x1718, "P-125"), { USB_DEVICE(0x0499, 0x1503), .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
Greg Kroah-Hartman
maintainerPATCH 8/321 xhci: Fix Panther point NULL pointer deref at full-speed re-enumeration
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mathias Nyman <[email protected]>
commit af8e119f52e9c13e556be9e03f27957554a84656 upstream.
re-enumerating full-speed devices after a failed address device command can trigger a NULL pointer dereference.
Full-speed devices may need to reconfigure the endpoint 0 Max Packet Size value during enumeration. Usb core calls usb_ep0_reinit() in this case, which ends up calling xhci_configure_endpoint().
On Panther point xHC the xhci_configure_endpoint() function will additionally check and reserve bandwidth in software. Other hosts do this in hardware
If xHC address device command fails then a new xhci_virt_device structure is allocated as part of re-enabling the slot, but the bandwidth table pointers are not set up properly here.
This triggers the NULL pointer dereference the next time usb_ep0_reinit() is called and xhci_configure_endpoint() tries to check and reserve bandwidth
[46710.713538] usb 3-1: new full-speed USB device number 5 using xhci_hcd [46710.713699] usb 3-1: Device not responding to setup address. [46710.917684] usb 3-1: Device not responding to setup address. [46711.125536] usb 3-1: device not accepting address 5, error -71 [46711.125594] BUG: kernel NULL pointer dereference, address: 0000000000000008 [46711.125600] #PF: supervisor read access in kernel mode [46711.125603] #PF: error_code(0x0000) - not-present page [46711.125606] PGD 0 P4D 0 [46711.125610] Oops: Oops: 0000 [#1] PREEMPT SMP PTI [46711.125615] CPU: 1 PID: 25760 Comm: kworker/1:2 Not tainted 6.10.3_2 #1 [46711.125620] Hardware name: Gigabyte Technology Co., Ltd. [46711.125623] Workqueue: usb_hub_wq hub_event [usbcore] [46711.125668] RIP: 0010:xhci_reserve_bandwidth (drivers/usb/host/xhci.c
Fix this by making sure bandwidth table pointers are set up correctly after a failed address device command, and additionally by avoiding checking for bandwidth in cases like this where no actual endpoints are added or removed, i.e. only context for default control endpoint 0 is evaluated.
--- drivers/usb/host/xhci.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/usb/host/xhci.c +5 -3
@@ -2971,7 +2971,7 @@ static int xhci_configure_endpoint(struc xhci->num_active_eps);return -ENOMEM ; } -if ((xhci->quirks &XHCI_SW_BW_CHECKING ) && +if ((xhci->quirks &XHCI_SW_BW_CHECKING ) && !ctx_change &&xhci_reserve_bandwidth (xhci, virt_dev, command->in_ctx)) {if ((xhci->quirks &XHCI_EP_LIMIT_QUIRK ))xhci_free_host_resources (xhci, ctrl_ctx);
@@ -4313,8 +4313,10 @@ static int xhci_setup_device(struct usb_mutex_unlock (&xhci->mutex); ret =xhci_disable_slot (xhci, udev->slot_id);xhci_free_virt_device (xhci, udev->slot_id); -if (!ret) -xhci_alloc_dev (hcd, udev); +if (!ret) { +if (xhci_alloc_dev (hcd, udev) ==1 ) +xhci_setup_addressable_virt_dev (xhci, udev); + }kfree (command->completion);kfree (command);return -EPROTO ;
Greg Kroah-Hartman
maintainerPATCH 9/321 thunderbolt: Mark XDomain as unplugged when router is removed
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mika Westerberg <[email protected]>
commit e2006140ad2e01a02ed0aff49cc2ae3ceeb11f8d upstream.
I noticed that when we do discrete host router NVM upgrade and it gets hot-removed from the PCIe side as a result of NVM firmware authentication, if there is another host connected with enabled paths we hang in tearing them down. This is due to fact that the Thunderbolt networking driver also tries to cleanup the paths and ends up blocking in tb_disconnect_xdomain_paths() waiting for the domain lock.
However, at this point we already cleaned the paths in tb_stop() so there is really no need for tb_disconnect_xdomain_paths() to do that anymore. Furthermore it already checks if the XDomain is unplugged and bails out early so take advantage of that and mark the XDomain as unplugged when we remove the parent router.
--- drivers/thunderbolt/switch.c | 1 + 1 file changed, 1 insertion(+)
drivers/thunderbolt/switch.c +1 -0
@@ -3086,6 +3086,7 @@ void tb_switch_remove(struct tb_switch *tb_switch_remove (port->remote->sw); port->remote =NULL ; }else if (port->xdomain) { + port->xdomain->is_unplugged = true;tb_xdomain_remove (port->xdomain); port->xdomain =NULL ; }
Greg Kroah-Hartman
maintainerPATCH 10/321 s390/dasd: fix error recovery leading to data corruption on ESE devices
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefan Haberland <[email protected]>
commit 7db4042336580dfd75cb5faa82c12cd51098c90b upstream.
Extent Space Efficient (ESE) or thin provisioned volumes need to be formatted on demand during usual IO processing.
The dasd_ese_needs_format function checks for error codes that signal the non existence of a proper track format.
The check for incorrect length is to imprecise since other error cases leading to transport of insufficient data also have this flag set. This might lead to data corruption in certain error cases for example during a storage server warmstart.
Fix by removing the check for incorrect length and replacing by explicitly checking for invalid track format in transport mode.
Also remove the check for file protected since this is not a valid ESE handling case.
--- drivers/s390/block/dasd.c | 36 +++++++++++++++--------- drivers/s390/block/dasd_3990_erp.c | 10 +----- drivers/s390/block/dasd_eckd.c | 55 ++++++++++++++++--------------------- drivers/s390/block/dasd_int.h | 2 - 4 files changed, 50 insertions(+), 53 deletions(-)
drivers/s390/block/dasd.c +23 -13
@@ -1597,9 +1597,15 @@ static int dasd_ese_needs_format(structif (!sense)return 0 ; -return !!(sense[1 ] &SNS1_NO_REC_FOUND ) || - !!(sense[1 ] &SNS1_FILE_PROTECTED ) || -scsw_cstat (&irb->scsw) ==SCHN_STAT_INCORR_LEN ; +if (sense[1 ] &SNS1_NO_REC_FOUND ) +return 1 ; + +if ((sense[1 ] &SNS1_INV_TRACK_FORMAT ) && +scsw_is_tm (&irb->scsw) && + !(sense[2 ] &SNS2_ENV_DATA_PRESENT )) +return 1 ; + +return 0 ; }static int dasd_ese_oos_cond (u8 *sense)
@@ -1620,7 +1626,7 @@ void dasd_int_handler(struct ccw_devicestruct dasd_device *device;unsigned long now;int nrf_suppressed =0 ; -int fp_suppressed =0 ; +int it_suppressed =0 ;struct request *req;u8 *sense =NULL ;int expires;
@@ -1675,8 +1681,9 @@ void dasd_int_handler(struct ccw_device*/ sense =dasd_get_sense (irb);if (sense) { - fp_suppressed = (sense[1 ] &SNS1_FILE_PROTECTED ) && -test_bit (DASD_CQR_SUPPRESS_FP , &cqr->flags); + it_suppressed = (sense[1 ] &SNS1_INV_TRACK_FORMAT ) && + !(sense[2 ] &SNS2_ENV_DATA_PRESENT ) && +test_bit (DASD_CQR_SUPPRESS_IT , &cqr->flags); nrf_suppressed = (sense[1 ] &SNS1_NO_REC_FOUND ) &&test_bit (DASD_CQR_SUPPRESS_NRF , &cqr->flags);
@@ -1691,7 +1698,7 @@ void dasd_int_handler(struct ccw_devicereturn ; } } -if (!(fp_suppressed || nrf_suppressed)) +if (!(it_suppressed || nrf_suppressed)) device->discipline->dump_sense_dbf (device, irb,"int" );if (device->features &DASD_FEATURE_ERPLOG )
@@ -2452,14 +2459,17 @@ retry: rc =0 ;list_for_each_entry_safe (cqr, n, ccw_queue, blocklist) {/* -* In some cases the 'File Protected' or 'Incorrect Length' -* error might be expected and error recovery would be -* unnecessary in these cases. Check if the according suppress -* bit is set. +* In some cases certain errors might be expected and +* error recovery would be unnecessary in these cases. +* Check if the according suppress bit is set. */ sense =dasd_get_sense (&cqr->irb); -if (sense && sense[1 ] &SNS1_FILE_PROTECTED && -test_bit (DASD_CQR_SUPPRESS_FP , &cqr->flags)) +if (sense && (sense[1 ] &SNS1_INV_TRACK_FORMAT ) && + !(sense[2 ] &SNS2_ENV_DATA_PRESENT ) && +test_bit (DASD_CQR_SUPPRESS_IT , &cqr->flags)) +continue ; +if (sense && (sense[1 ] &SNS1_NO_REC_FOUND ) && +test_bit (DASD_CQR_SUPPRESS_NRF , &cqr->flags))continue ;if (scsw_cstat (&cqr->irb.scsw) ==0x40 &&test_bit (DASD_CQR_SUPPRESS_IL , &cqr->flags))
drivers/s390/block/dasd_3990_erp.c +2 -8
@@ -1406,14 +1406,8 @@ dasd_3990_erp_file_prot(struct dasd_ccw_struct dasd_device *device = erp->startdev; -/* -* In some cases the 'File Protected' error might be expected and -* log messages shouldn't be written then. -* Check if the according suppress bit is set. -*/ -if (!test_bit (DASD_CQR_SUPPRESS_FP , &erp->flags)) -dev_err (&device->cdev->dev, -"Accessing the DASD failed because of a hardware error\n" ); +dev_err (&device->cdev->dev, +"Accessing the DASD failed because of a hardware error\n" );return dasd_3990_erp_cleanup (erp,DASD_CQR_FAILED );
drivers/s390/block/dasd_eckd.c +24 -31
90 lines not on this page · raw message
drivers/s390/block/dasd_int.h +1 -1
@@ -225,7 +225,7 @@ struct dasd_ccw_req {* The following flags are used to suppress output of certain errors. */ #define DASD_CQR_SUPPRESS_NRF 4/* Suppress 'No Record Found' error */ -#define DASD_CQR_SUPPRESS_FP 5/* Suppress 'File Protected' error*/ +#define DASD_CQR_SUPPRESS_IT 5/* Suppress 'Invalid Track' error*/ #define DASD_CQR_SUPPRESS_IL 6/* Suppress 'Incorrect Length' error */ #define DASD_CQR_SUPPRESS_CR 7/* Suppress 'Command Reject' error */
Greg Kroah-Hartman
maintainerPATCH 11/321 riscv: change XIPs kernel_map.size to be size of the entire kernel
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nam Cao <[email protected]>
commit 57d76bc51fd80824bcc0c84a5b5ec944f1b51edd upstream.
With XIP kernel, kernel_map.size is set to be only the size of data part of the kernel. This is inconsistent with "normal" kernel, who sets it to be the size of the entire kernel.
More importantly, XIP kernel fails to boot if CONFIG_DEBUG_VIRTUAL is enabled, because there are checks on virtual addresses with the assumption that kernel_map.size is the size of the entire kernel (these checks are in arch/riscv/mm/physaddr.c).
Change XIP's kernel_map.size to be the size of the entire kernel.
--- arch/riscv/mm/init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
arch/riscv/mm/init.c +2 -2
@@ -816,7 +816,7 @@ static void __init create_kernel_page_ta PMD_SIZE, PAGE_KERNEL_EXEC);/* Map the data in RAM */ - end_va = kernel_map.virt_addr +XIP_OFFSET + kernel_map.size; + end_va = kernel_map.virt_addr + kernel_map.size;for (va = kernel_map.virt_addr +XIP_OFFSET ; va < end_va; va +=PMD_SIZE ) create_pgd_mapping(pgdir, va, kernel_map.phys_addr + (va - (kernel_map.virt_addr + XIP_OFFSET)),
@@ -947,7 +947,7 @@ asmlinkage void __init setup_vm(uintptr_ phys_ram_base =CONFIG_PHYS_RAM_BASE ; kernel_map.phys_addr = (uintptr_t )CONFIG_PHYS_RAM_BASE ; - kernel_map.size = (uintptr_t )(&_end) - (uintptr_t )(&_sdata); + kernel_map.size = (uintptr_t )(&_end) - (uintptr_t )(&_start); kernel_map.va_kernel_xip_pa_offset = kernel_map.virt_addr - kernel_map.xiprom;#else
Greg Kroah-Hartman
maintainerPATCH 12/321 arm64: ACPI: NUMA: initialize all values of acpi_early_node_map to NUMA_NO_NODE
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haibo Xu <[email protected]>
commit a21dcf0ea8566ebbe011c79d6ed08cdfea771de3 upstream.
Currently, only acpi_early_node_map[0] was initialized to NUMA_NO_NODE. To ensure all the values were properly initialized, switch to initialize all of them to NUMA_NO_NODE.
--- arch/arm64/kernel/acpi_numa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/kernel/acpi_numa.c +1 -1
@@ -27,7 +27,7 @@#include <asm/numa.h> -static int acpi_early_node_map[NR_CPUS ]__initdata = {NUMA_NO_NODE }; +static int acpi_early_node_map[NR_CPUS ]__initdata = { [0 ...NR_CPUS -1 ] =NUMA_NO_NODE };int __init acpi_numa_get_nid (unsigned int cpu) {
Greg Kroah-Hartman
maintainerPATCH 13/321 dm resume: dont return EINVAL when signalled
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Khazhismel Kumykov <[email protected]>
commit 7a636b4f03af9d541205f69e373672e7b2b60a8a upstream.
If the dm_resume method is called on a device that is not suspended, the method will suspend the device briefly, before resuming it (so that the table will be swapped).
However, there was a bug that the return value of dm_suspended_md was not checked. dm_suspended_md may return an error when it is interrupted by a signal. In this case, do_resume would call dm_swap_table, which would return -EINVAL.
This commit fixes the logic, so that error returned by dm_suspend is checked and the resume operation is undone.
--- drivers/md/dm-ioctl.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-)
drivers/md/dm-ioctl.c +20 -2
@@ -1156,8 +1156,26 @@ static int do_resume(struct dm_ioctl *pa suspend_flags &= ~DM_SUSPEND_LOCKFS_FLAG ;if (param->flags &DM_NOFLUSH_FLAG ) suspend_flags |=DM_SUSPEND_NOFLUSH_FLAG ; -if (!dm_suspended_md (md)) -dm_suspend (md, suspend_flags); +if (!dm_suspended_md (md)) { + r =dm_suspend (md, suspend_flags); +if (r) { +down_write (&_hash_lock); + hc =dm_get_mdptr (md); +if (hc && !hc->new_map) { + hc->new_map = new_map; + new_map =NULL ; + }else { + r = -ENXIO ; + } +up_write (&_hash_lock); +if (new_map) { +dm_sync_table (md); +dm_table_destroy (new_map); + } +dm_put (md); +return r; + } + } old_size =dm_get_size (md); old_map =dm_swap_table (md, new_map);
Greg Kroah-Hartman
maintainerPATCH 14/321 dm persistent data: fix memory allocation failure
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <[email protected]>
commit faada2174c08662ae98b439c69efe3e79382c538 upstream.
kmalloc is unreliable when allocating more than 8 pages of memory. It may fail when there is plenty of free memory but the memory is fragmented. Zdenek Kabelac observed such failure in his tests.
This commit changes kmalloc to kvmalloc - kvmalloc will fall back to vmalloc if the large allocation fails.
--- drivers/md/persistent-data/dm-space-map-metadata.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/md/persistent-data/dm-space-map-metadata.c +2 -2
@@ -274,7 +274,7 @@ static void sm_metadata_destroy(struct d { struct sm_metadata *smm = container_of(sm, struct sm_metadata, sm); -kfree (smm); +kvfree (smm); }static int sm_metadata_get_nr_blocks (struct dm_space_map *sm,dm_block_t *count)
@@ -768,7 +768,7 @@ struct dm_space_map *dm_sm_metadata_init {struct sm_metadata *smm; - smm =kmalloc (sizeof (*smm),GFP_KERNEL ); + smm =kvmalloc (sizeof (*smm),GFP_KERNEL );if (!smm)return ERR_PTR (-ENOMEM );
Greg Kroah-Hartman
maintainerPATCH 15/321 vfs: Dont evict inode under the inode lru traversing context
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhihao Cheng <[email protected]>
commit 2a0629834cd82f05d424bbc193374f9a43d1f87d upstream.
The inode reclaiming process(See function prune_icache_sb) collects all reclaimable inodes and mark them with I_FREEING flag at first, at that time, other processes will be stuck if they try getting these inodes (See function find_inode_fast), then the reclaiming process destroy the inodes by function dispose_list(). Some filesystems(eg. ext4 with ea_inode feature, ubifs with xattr) may do inode lookup in the inode evicting callback function, if the inode lookup is operated under the inode lru traversing context, deadlock problems may happen.
Case 1: In function ext4_evict_inode(), the ea inode lookup could happen
if ea_inode feature is enabled, the lookup process will be stuck under the evicting context like this:
1. File A has inode i_reg and an ea inode i_ea
2. getfattr(A, xattr_buf) // i_ea is added into lru // lru->i_ea
3. Then, following three processes running like this:
PA PB
echo 2 > /proc/sys/vm/drop_caches
shrink_slab
prune_dcache_sb
// i_reg is added into lru, lru->i_ea->i_reg
prune_icache_sb
list_lru_walk_one
inode_lru_isolate
i_ea->i_state |= I_FREEING // set inode state
inode_lru_isolate
__iget(i_reg)
spin_unlock(&i_reg->i_lock)
spin_unlock(lru_lock)
rm file A
i_reg->nlink = 0
iput(i_reg) // i_reg->nlink is 0, do evict
ext4_evict_inode
ext4_xattr_delete_inode
ext4_xattr_inode_dec_ref_all
ext4_xattr_inode_iget
ext4_iget(i_ea->i_ino)
iget_locked
find_inode_fast
__wait_on_freeing_inode(i_ea) ----→ AA deadlock
dispose_list // cannot be executed by prune_icache_sb
wake_up_bit(&i_ea->i_state)Case 2: In deleted inode writing function ubifs_jnl_write_inode(), file
deleting process holds BASEHD's wbuf->io_mutex while getting the xattr inode, which could race with inode reclaiming process(The reclaiming process could try locking BASEHD's wbuf->io_mutex in inode evicting function), then an ABBA deadlock problem would happen as following:
1. File A has inode ia and a xattr(with inode ixa), regular file B has inode ib and a xattr.
2. getfattr(A, xattr_buf) // ixa is added into lru // lru->ixa
3. Then, following three processes running like this:
PA PB PC
echo 2 > /proc/sys/vm/drop_caches
shrink_slab
prune_dcache_sb
// ib and ia are added into lru, lru->ixa->ib->ia
prune_icache_sb
list_lru_walk_one
inode_lru_isolate
ixa->i_state |= I_FREEING // set inode state
inode_lru_isolate
__iget(ib)
spin_unlock(&ib->i_lock)
spin_unlock(lru_lock)
rm file B
ib->nlink = 0
rm file A
iput(ia)
ubifs_evict_inode(ia)
ubifs_jnl_delete_inode(ia)
ubifs_jnl_write_inode(ia)
make_reservation(BASEHD) // Lock wbuf->io_mutex
ubifs_iget(ixa->i_ino)
iget_locked
find_inode_fast
__wait_on_freeing_inode(ixa)
| iput(ib) // ib->nlink is 0, do evict
| ubifs_evict_inode
| ubifs_jnl_delete_inode(ib)
↓ ubifs_jnl_write_inode
ABBA deadlock ←-----make_reservation(BASEHD)
dispose_list // cannot be executed by prune_icache_sb
wake_up_bit(&ixa->i_state)Fix the possible deadlock by using new inode state flag I_LRU_ISOLATING to pin the inode in memory while inode_lru_isolate() reclaims its pages instead of using ordinary inode reference. This way inode deletion cannot be triggered from inode_lru_isolate() thus avoiding the deadlock. evict() is made to wait for I_LRU_ISOLATING to be cleared before proceeding with inode cleanup.
--- fs/inode.c | 39 +++++++++++++++++++++++++++++++++++++-- include/linux/fs.h | 5 +++++ 2 files changed, 42 insertions(+), 2 deletions(-)
fs/inode.c +37 -2
@@ -486,6 +486,39 @@ static void inode_lru_list_del(struct inthis_cpu_dec (nr_unused); } +static void inode_pin_lru_isolating (struct inode *inode) +{ +lockdep_assert_held (&inode->i_lock); +WARN_ON (inode->i_state & (I_LRU_ISOLATING |I_FREEING |I_WILL_FREE )); + inode->i_state |=I_LRU_ISOLATING ; +} + +static void inode_unpin_lru_isolating (struct inode *inode) +{ +spin_lock (&inode->i_lock); +WARN_ON (!(inode->i_state &I_LRU_ISOLATING )); + inode->i_state &= ~I_LRU_ISOLATING ; +smp_mb (); +wake_up_bit (&inode->i_state, __I_LRU_ISOLATING); +spin_unlock (&inode->i_lock); +} + +static void inode_wait_for_lru_isolating (struct inode *inode) +{ +spin_lock (&inode->i_lock); +if (inode->i_state &I_LRU_ISOLATING ) { +DEFINE_WAIT_BIT (wq, &inode->i_state, __I_LRU_ISOLATING); +wait_queue_head_t *wqh; + + wqh =bit_waitqueue (&inode->i_state, __I_LRU_ISOLATING); +spin_unlock (&inode->i_lock); +__wait_on_bit (wqh, &wq, bit_wait,TASK_UNINTERRUPTIBLE ); +spin_lock (&inode->i_lock); +WARN_ON (inode->i_state &I_LRU_ISOLATING ); + } +spin_unlock (&inode->i_lock); +} +/** * inode_sb_list_add - add inode to the superblock list of inodes * @inode: inode to add
@@ -654,6 +687,8 @@ static void evict(struct inode *inode)inode_sb_list_del (inode); +inode_wait_for_lru_isolating (inode); +/* * Wait for flusher thread to be done with the inode so that filesystem * does not start destroying it while writeback is still running. Since
@@ -855,7 +890,7 @@ static enum lru_status inode_lru_isolate* be under pressure before the cache inside the highmem zone. */ if (inode_has_buffers (inode) || !mapping_empty (&inode->i_data)) { -__iget (inode); +inode_pin_lru_isolating (inode);spin_unlock (&inode->i_lock);spin_unlock (lru_lock);if (remove_inode_buffers (inode)) {
@@ -868,7 +903,7 @@ static enum lru_status inode_lru_isolateif (current->reclaim_state) current->reclaim_state->reclaimed_slab += reap; } -iput (inode); +inode_unpin_lru_isolating (inode);spin_lock (lru_lock);return LRU_RETRY ; }
include/linux/fs.h +5 -0
@@ -2507,6 +2507,9 @@ static inline void kiocb_clone(struct ki* * I_PINNING_FSCACHE_WB Inode is pinning an fscache object for writeback. * +* I_LRU_ISOLATING Inode is pinned being isolated from LRU without holding +* i_count. +* * Q: What is the difference between I_WILL_FREE and I_FREEING? */ #define I_DIRTY_SYNC (1 << 0)
@@ -2530,6 +2533,8 @@ static inline void kiocb_clone(struct ki#define I_DONTCACHE (1 << 16)#define I_SYNC_QUEUED (1 << 17)#define I_PINNING_FSCACHE_WB (1 << 18) +#define __I_LRU_ISOLATING 19 +#define I_LRU_ISOLATING (1 << __I_LRU_ISOLATING)#define I_DIRTY_INODE (I_DIRTY_SYNC | I_DIRTY_DATASYNC)#define I_DIRTY (I_DIRTY_INODE | I_DIRTY_PAGES)
Greg Kroah-Hartman
maintainerPATCH 16/321 fs/ntfs3: add prefix to bitmap_size() and use BITS_TO_U64()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Lobakin <[email protected]>
commit 3f5ef5109f6a054ce58b3bec7214ed76c9cc269f upstream.
bitmap_size() is a pretty generic name and one may want to use it for a generic bitmap API function. At the same time, its logic is NTFS-specific, as it aligns to the sizeof(u64), not the sizeof(long) (although it uses ideologically right ALIGN() instead of division). Add the prefix 'ntfs3_' used for that FS (not just 'ntfs_' to not mix it with the legacy module) and use generic BITS_TO_U64() while at it.
--- fs/ntfs3/bitmap.c | 4 ++-- fs/ntfs3/fsntfs.c | 2 +- fs/ntfs3/index.c | 11 ++++++----- fs/ntfs3/ntfs_fs.h | 4 ++-- fs/ntfs3/super.c | 2 +- 5 files changed, 12 insertions(+), 11 deletions(-)
fs/ntfs3/bitmap.c +2 -2
@@ -656,7 +656,7 @@ int wnd_init(struct wnd_bitmap *wnd, str wnd->total_zeroes = nbits; wnd->extent_max =MINUS_ONE_T ; wnd->zone_bit = wnd->zone_end =0 ; - wnd->nwnd =bytes_to_block (sb,bitmap_size (nbits)); + wnd->nwnd =bytes_to_block (sb,ntfs3_bitmap_size (nbits)); wnd->bits_last = nbits & (wbits -1 );if (!wnd->bits_last) wnd->bits_last = wbits;
@@ -1320,7 +1320,7 @@ int wnd_extend(struct wnd_bitmap *wnd, sreturn -EINVAL ;/* Align to 8 byte boundary. */ - new_wnd =bytes_to_block (sb,bitmap_size (new_bits)); + new_wnd =bytes_to_block (sb,ntfs3_bitmap_size (new_bits)); new_last = new_bits & (wbits -1 );if (!new_last) new_last = wbits;
fs/ntfs3/fsntfs.c +1 -1
@@ -493,7 +493,7 @@ static int ntfs_extend_mft(struct ntfs_s ni->mi.dirty = true;/* Step 2: Resize $MFT::BITMAP. */ - new_bitmap_bytes =bitmap_size (new_mft_total); + new_bitmap_bytes =ntfs3_bitmap_size (new_mft_total); err =attr_set_size (ni,ATTR_BITMAP ,NULL ,0 , &sbi->mft.bitmap.run, new_bitmap_bytes, &new_bitmap_bytes, true,NULL );
fs/ntfs3/index.c +6 -5
@@ -1454,8 +1454,8 @@ static int indx_create_allocate(struct n alloc->nres.valid_size = alloc->nres.data_size =cpu_to_le64 (data_size); - err =ni_insert_resident (ni,bitmap_size (1 ),ATTR_BITMAP , in->name, - in->name_len, &bitmap,NULL ,NULL ); + err =ni_insert_resident (ni,ntfs3_bitmap_size (1 ),ATTR_BITMAP , + in->name, in->name_len, &bitmap,NULL ,NULL );if (err) goto out2;
@@ -1516,8 +1516,9 @@ static int indx_add_allocate(struct ntfsif (bmp) {/* Increase bitmap. */ err =attr_set_size (ni,ATTR_BITMAP , in->name, in->name_len, - &indx->bitmap_run,bitmap_size (bit +1 ), -NULL , true,NULL ); + &indx->bitmap_run, +ntfs3_bitmap_size (bit +1 ),NULL , true, +NULL );if (err) goto out1; }
@@ -2080,7 +2081,7 @@ static int indx_shrink(struct ntfs_indexif (err)return err; - bpb =bitmap_size (bit); + bpb =ntfs3_bitmap_size (bit);if (bpb *8 == nbits)return 0 ;
fs/ntfs3/ntfs_fs.h +2 -2
@@ -951,9 +951,9 @@ static inline bool run_is_empty(struct r }/* NTFS uses quad aligned bitmaps. */ -static inline size_t bitmap_size (size_t bits) +static inline size_t ntfs3_bitmap_size (size_t bits) { -return ALIGN ((bits +7 ) >>3 ,8 ); +return BITS_TO_U64 (bits) *sizeof (u64); }#define _100ns2seconds 10000000
fs/ntfs3/super.c +1 -1
@@ -1108,7 +1108,7 @@ static int ntfs_fill_super(struct super_/* Check bitmap boundary. */ tt = sbi->used.bitmap.nbits; -if (inode->i_size <bitmap_size (tt)) { +if (inode->i_size <ntfs3_bitmap_size (tt)) { err = -EINVAL ; goto put_inode_out; }
Greg Kroah-Hartman
maintainerPATCH 17/321 s390/cio: rename bitmap_size() -> idset_bitmap_size()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Lobakin <[email protected]>
commit c1023f5634b9bfcbfff0dc200245309e3cde9b54 upstream.
bitmap_size() is a pretty generic name and one may want to use it for a generic bitmap API function. At the same time, its logic is not "generic", i.e. it's not just nbits -> size of bitmap in bytes converter as it would be expected from its name.
Add the prefix 'idset_' used throughout the file where the function resides.
--- drivers/s390/cio/idset.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
drivers/s390/cio/idset.c +6 -4
@@ -16,7 +16,7 @@ struct idset {unsigned long bitmap[]; }; -static inline unsigned long bitmap_size (int num_ssid,int num_id) +static inline unsigned long idset_bitmap_size (int num_ssid,int num_id) {return BITS_TO_LONGS (num_ssid * num_id) *sizeof (unsigned long ); }
@@ -25,11 +25,12 @@ static struct idset *idset_new(int num_s {struct idset *set; - set =vmalloc (sizeof (struct idset ) +bitmap_size (num_ssid, num_id)); + set =vmalloc (sizeof (struct idset ) + +idset_bitmap_size (num_ssid, num_id));if (set) { set->num_ssid = num_ssid; set->num_id = num_id; -memset (set->bitmap,0 ,bitmap_size (num_ssid, num_id)); +memset (set->bitmap,0 ,idset_bitmap_size (num_ssid, num_id)); }return set; }
@@ -41,7 +42,8 @@ void idset_free(struct idset *set)void idset_fill (struct idset *set) { -memset (set->bitmap,0xff ,bitmap_size (set->num_ssid, set->num_id)); +memset (set->bitmap,0xff , +idset_bitmap_size (set->num_ssid, set->num_id)); }static inline void idset_add (struct idset *set,int ssid,int id)
Greg Kroah-Hartman
maintainerPATCH 18/321 btrfs: rename bitmap_set_bits() -> btrfs_bitmap_set_bits()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Lobakin <[email protected]>
commit 4ca532d64648d4776d15512caed3efea05ca7195 upstream.
bitmap_set_bits() does not start with the FS' prefix and may collide with a new generic helper one day. It operates with the FS-specific types, so there's no change those two could do the same thing. Just add the prefix to exclude such possible conflict.
--- fs/btrfs/free-space-cache.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
fs/btrfs/free-space-cache.c +4 -4
@@ -1894,9 +1894,9 @@ static inline void bitmap_clear_bits(str ctl->free_space -= bytes; } -static void bitmap_set_bits (struct btrfs_free_space_ctl *ctl, -struct btrfs_free_space *info,u64 offset, -u64 bytes) +static void btrfs_bitmap_set_bits (struct btrfs_free_space_ctl *ctl, +struct btrfs_free_space *info,u64 offset, +u64 bytes) {unsigned long start, count, end;int extent_delta =1 ;
@@ -2232,7 +2232,7 @@ static u64 add_bytes_to_bitmap(struct bt bytes_to_set =min (end - offset, bytes); -bitmap_set_bits (ctl, info, offset, bytes_to_set); +btrfs_bitmap_set_bits (ctl, info, offset, bytes_to_set);return bytes_to_set;
Greg Kroah-Hartman
maintainerPATCH 19/321 bitmap: introduce generic optimized bitmap_size()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Lobakin <[email protected]>
commit a37fbe666c016fd89e4460d0ebfcea05baba46dc upstream.
The number of times yet another open coded BITS_TO_LONGS(nbits) * sizeof(long) can be spotted is huge. Some generic helper is long overdue.
Add one, bitmap_size(), but with one detail. BITS_TO_LONGS() uses DIV_ROUND_UP(). The latter works well when both divident and divisor are compile-time constants or when the divisor is not a pow-of-2. When it is however, the compilers sometimes tend to generate suboptimal code (GCC 13):
48 83 c0 3f add $0x3f,%rax 48 c1 e8 06 shr $0x6,%rax
48 8d 14 c5 00 00 00 00 lea 0x0(,%rax,8),%rdx
%BITS_PER_LONG is always a pow-2 (either 32 or 64), but GCC still does full division of nbits + 63 by it and then multiplication by 8. Instead of BITS_TO_LONGS(), use ALIGN() and then divide by 8. GCC:
8d 50 3f lea 0x3f(%rax),%edx c1 ea 03 shr $0x3,%edx 81 e2 f8 ff ff 1f and $0x1ffffff8,%edx
Now it shifts nbits + 63 by 3 positions (IOW performs fast division by 8) and then masks bits[2:0]. bloat-o-meter:
add/remove: 0/0 grow/shrink: 20/133 up/down: 156/-773 (-617)
Clang does it better and generates the same code before/after starting from -O1, except that with the ALIGN() approach it uses %edx and thus still saves some bytes:
add/remove: 0/0 grow/shrink: 9/133 up/down: 18/-538 (-520)
Note that we can't expand DIV_ROUND_UP() by adding a check and using this approach there, as it's used in array declarations where expressions are not allowed.
Add this helper to tools/ as well.
--- drivers/md/dm-clone-metadata.c | 5 ----- drivers/s390/cio/idset.c | 2 +- include/linux/bitmap.h | 8 +++++--- include/linux/cpumask.h | 2 +- lib/math/prime_numbers.c | 2 -- tools/include/linux/bitmap.h | 7 ++++--- 6 files changed, 11 insertions(+), 15 deletions(-)
drivers/md/dm-clone-metadata.c +0 -5
@@ -465,11 +465,6 @@ static void __destroy_persistent_data_st/*---------------------------------------------------------------------------*/ -static size_t bitmap_size (unsigned long nr_bits) -{ -return BITS_TO_LONGS (nr_bits) *sizeof (long ); -} -static int __dirty_map_init (struct dirty_map *dmap,unsigned long nr_words,unsigned long nr_regions) {
drivers/s390/cio/idset.c +1 -1
@@ -18,7 +18,7 @@ struct idset {static inline unsigned long idset_bitmap_size (int num_ssid,int num_id) { -return BITS_TO_LONGS (num_ssid * num_id) *sizeof (unsigned long ); +return bitmap_size (size_mul (num_ssid, num_id)); }static struct idset *idset_new (int num_ssid,int num_id)
include/linux/bitmap.h +5 -3
@@ -237,9 +237,11 @@ extern int bitmap_print_list_to_buf(char#define BITMAP_FIRST_WORD_MASK (start) (~0UL << ((start) & (BITS_PER_LONG - 1)))#define BITMAP_LAST_WORD_MASK (nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1))) +#define bitmap_size (nbits) (ALIGN(nbits, BITS_PER_LONG) / BITS_PER_BYTE) +static inline void bitmap_zero (unsigned long *dst,unsigned int nbits) { -unsigned int len =BITS_TO_LONGS (nbits) *sizeof (unsigned long ); +unsigned int len =bitmap_size (nbits);if (small_const_nbits (nbits)) *dst =0 ;
@@ -249,7 +251,7 @@ static inline void bitmap_zero(unsignedstatic inline void bitmap_fill (unsigned long *dst,unsigned int nbits) { -unsigned int len =BITS_TO_LONGS (nbits) *sizeof (unsigned long ); +unsigned int len =bitmap_size (nbits);if (small_const_nbits (nbits)) *dst = ~0UL ;
@@ -260,7 +262,7 @@ static inline void bitmap_fill(unsignedstatic inline void bitmap_copy (unsigned long *dst,const unsigned long *src,unsigned int nbits) { -unsigned int len =BITS_TO_LONGS (nbits) *sizeof (unsigned long ); +unsigned int len =bitmap_size (nbits);if (small_const_nbits (nbits)) *dst = *src;
include/linux/cpumask.h +1 -1
@@ -769,7 +769,7 @@ static inline int cpulist_parse(const ch*/ static inline unsigned int cpumask_size (void ) { -return BITS_TO_LONGS (nr_cpumask_bits) *sizeof (long ); +return bitmap_size (nr_cpumask_bits); }/*
lib/math/prime_numbers.c +0 -2
@@ -6,8 +6,6 @@#include <linux/prime_numbers.h> #include <linux/slab.h> -#define bitmap_size (nbits) (BITS_TO_LONGS(nbits) * sizeof(unsigned long)) -struct primes {struct rcu_head rcu;unsigned long last, sz;
tools/include/linux/bitmap.h +4 -3
@@ -25,13 +25,14 @@ bool __bitmap_intersects(const unsigned#define BITMAP_FIRST_WORD_MASK (start) (~0UL << ((start) & (BITS_PER_LONG - 1)))#define BITMAP_LAST_WORD_MASK (nbits) (~0UL >> (-(nbits) & (BITS_PER_LONG - 1))) +#define bitmap_size (nbits) (ALIGN(nbits, BITS_PER_LONG) / BITS_PER_BYTE) +static inline void bitmap_zero (unsigned long *dst,unsigned int nbits) {if (small_const_nbits (nbits)) *dst =0UL ;else { -int len =BITS_TO_LONGS (nbits) *sizeof (unsigned long ); -memset (dst,0 , len); +memset (dst,0 ,bitmap_size (nbits)); } }
@@ -117,7 +118,7 @@ static inline int test_and_clear_bit(int*/ static inline unsigned long *bitmap_zalloc (int nbits) { -return calloc (1 ,BITS_TO_LONGS (nbits) *sizeof (unsigned long )); +return calloc (1 ,bitmap_size (nbits)); }/*
Greg Kroah-Hartman
maintainerPATCH 20/321 fix bitmap corruption on close_range() with CLOSE_RANGE_UNSHARE
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
commit 9a2fa1472083580b6c66bdaf291f591e1170123a upstream.
copy_fd_bitmaps(new, old, count) is expected to copy the first count/BITS_PER_LONG bits from old->full_fds_bits[] and fill the rest with zeroes. What it does is copying enough words (BITS_TO_LONGS(count/BITS_PER_LONG)), then memsets the rest. That works fine, *if* all bits past the cutoff point are clear. Otherwise we are risking garbage from the last word we'd copied.
For most of the callers that is true - expand_fdtable() has count equal to old->max_fds, so there's no open descriptors past count, let alone fully occupied words in ->open_fds[], which is what bits in ->full_fds_bits[] correspond to.
The other caller (dup_fd()) passes sane_fdtable_size(old_fdt, max_fds), which is the smallest multiple of BITS_PER_LONG that covers all opened descriptors below max_fds. In the common case (copying on fork()) max_fds is ~0U, so all opened descriptors will be below it and we are fine, by the same reasons why the call in expand_fdtable() is safe.
Unfortunately, there is a case where max_fds is less than that and where we might, indeed, end up with junk in ->full_fds_bits[] - close_range(from, to, CLOSE_RANGE_UNSHARE) with
* descriptor table being currently shared
* 'to' being above the current capacity of descriptor table
* 'from' being just under some chunk of opened descriptors.
In that case we end up with observably wrong behaviour - e.g. spawn a child with CLONE_FILES, get all descriptors in range 0..127 open, then close_range(64, ~0U, CLOSE_RANGE_UNSHARE) and watch dup(0) ending up with descriptor #128, despite #64 being observably not open.
The minimally invasive fix would be to deal with that in dup_fd(). If this proves to add measurable overhead, we can go that way, but let's try to fix copy_fd_bitmaps() first.
* new helper: bitmap_copy_and_expand(to, from, bits_to_copy, size).
* make copy_fd_bitmaps() take the bitmap size in words, rather than bits; it's 'count' argument is always a multiple of BITS_PER_LONG, so we are not losing any information, and that way we can use the same helper for all three bitmaps - compiler will see that count is a multiple of BITS_PER_LONG for the large ones, so it'll generate plain memcpy()+memset().
Reproducer added to tools/testing/selftests/core/close_range_test.c
--- fs/file.c | 28 ++++++++----------- include/linux/bitmap.h | 12 ++++++++ tools/testing/selftests/core/close_range_test.c | 35 ++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 16 deletions(-)
fs/file.c +12 -16
@@ -46,27 +46,23 @@ static void free_fdtable_rcu(struct rcu_#define BITBIT_NR (nr) BITS_TO_LONGS(BITS_TO_LONGS(nr))#define BITBIT_SIZE (nr) (BITBIT_NR(nr) * sizeof(long)) +#define fdt_words (fdt) ((fdt)->max_fds / BITS_PER_LONG) // words in ->open_fds/* * Copy 'count' fd bits from the old table to the new table and clear the extra * space if any. This does not copy the file pointers. Called with the files * spinlock held for write. */ -static void copy_fd_bitmaps (struct fdtable *nfdt,struct fdtable *ofdt, -unsigned int count) +static inline void copy_fd_bitmaps (struct fdtable *nfdt,struct fdtable *ofdt, +unsigned int copy_words) { -unsigned int cpy, set; +unsigned int nwords =fdt_words (nfdt); - cpy = count /BITS_PER_BYTE ; - set = (nfdt->max_fds - count) /BITS_PER_BYTE ; -memcpy (nfdt->open_fds, ofdt->open_fds, cpy); -memset ((char *)nfdt->open_fds + cpy,0 , set); -memcpy (nfdt->close_on_exec, ofdt->close_on_exec, cpy); -memset ((char *)nfdt->close_on_exec + cpy,0 , set); - - cpy =BITBIT_SIZE (count); - set =BITBIT_SIZE (nfdt->max_fds) - cpy; -memcpy (nfdt->full_fds_bits, ofdt->full_fds_bits, cpy); -memset ((char *)nfdt->full_fds_bits + cpy,0 , set); +bitmap_copy_and_extend (nfdt->open_fds, ofdt->open_fds, + copy_words *BITS_PER_LONG , nwords *BITS_PER_LONG ); +bitmap_copy_and_extend (nfdt->close_on_exec, ofdt->close_on_exec, + copy_words *BITS_PER_LONG , nwords *BITS_PER_LONG ); +bitmap_copy_and_extend (nfdt->full_fds_bits, ofdt->full_fds_bits, + copy_words, nwords); }/*
@@ -84,7 +80,7 @@ static void copy_fdtable(struct fdtablememcpy (nfdt->fd, ofdt->fd, cpy);memset ((char *)nfdt->fd + cpy,0 , set); -copy_fd_bitmaps (nfdt, ofdt, ofdt->max_fds); +copy_fd_bitmaps (nfdt, ofdt,fdt_words (ofdt)); }/*
@@ -374,7 +370,7 @@ struct files_struct *dup_fd(struct files open_files =sane_fdtable_size (old_fdt, max_fds); } -copy_fd_bitmaps (new_fdt, old_fdt, open_files); +copy_fd_bitmaps (new_fdt, old_fdt, open_files /BITS_PER_LONG ); old_fds = old_fdt->fd; new_fds = new_fdt->fd;
include/linux/bitmap.h +12 -0
@@ -281,6 +281,18 @@ static inline void bitmap_copy_clear_tai dst[nbits /BITS_PER_LONG ] &=BITMAP_LAST_WORD_MASK (nbits); } +static inline void bitmap_copy_and_extend (unsigned long *to, +const unsigned long *from, +unsigned int count,unsigned int size) +{ +unsigned int copy =BITS_TO_LONGS (count); + +memcpy (to, from, copy *sizeof (long )); +if (count %BITS_PER_LONG ) + to[copy -1 ] &=BITMAP_LAST_WORD_MASK (count); +memset (to + copy,0 ,bitmap_size (size) - copy *sizeof (long )); +} +/* * On 32-bit systems bitmaps are represented as u32 arrays internally. On LE64 * machines the order of hi and lo parts of numbers match the bitmap structure.
tools/testing/selftests/core/close_range_test.c +35 -0
@@ -563,4 +563,39 @@ TEST(close_range_cloexec_unshare_syzbot)EXPECT_EQ (close (fd3),0 ); } +TEST (close_range_bitmap_corruption) +{ +pid_t pid; +int status; +struct __clone_args args = { + .flags =CLONE_FILES , + .exit_signal =SIGCHLD , + }; + +/* get the first 128 descriptors open */ +for (int i =2 ; i <128 ; i++) +EXPECT_GE (dup2 (0 , i),0 ); + +/* get descriptor table shared */ + pid =sys_clone3 (&args,sizeof (args)); +ASSERT_GE (pid,0 ); + +if (pid ==0 ) { +/* unshare and truncate descriptor table down to 64 */ +if (sys_close_range (64 , ~0U ,CLOSE_RANGE_UNSHARE )) +exit (EXIT_FAILURE ); + +ASSERT_EQ (fcntl (64 ,F_GETFD ),-1 ); +/* ... and verify that the range 64..127 is not +stuck "fully used" according to secondary bitmap */ + EXPECT_EQ(dup(0), 64) +exit (EXIT_FAILURE ); +exit (EXIT_SUCCESS ); + } + +EXPECT_EQ (waitpid (pid, &status,0 ), pid); +EXPECT_EQ (true,WIFEXITED (status)); +EXPECT_EQ (0 ,WEXITSTATUS (status)); +} +TEST_HARNESS_MAIN
Greg Kroah-Hartman
maintainerPATCH 21/321 i2c: qcom-geni: Add missing geni_icc_disable in geni_i2c_runtime_resume
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andi Shyti <[email protected]>
commit 4e91fa1ef3ce6290b4c598e54b5eb6cf134fbec8 upstream.
Add the missing geni_icc_disable() call before returning in the geni_i2c_runtime_resume() function.
Commit 9ba48db9f77c ("i2c: qcom-geni: Add missing geni_icc_disable in geni_i2c_runtime_resume") by Gaosheng missed disabling the interconnect in one case.
--- drivers/i2c/busses/i2c-qcom-geni.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/i2c/busses/i2c-qcom-geni.c +3 -1
@@ -990,8 +990,10 @@ static int __maybe_unused geni_i2c_runtireturn ret; ret =clk_prepare_enable (gi2c->core_clk); -if (ret) +if (ret) { +geni_icc_disable (&gi2c->se);return ret; + } ret =geni_se_resources_on (&gi2c->se);if (ret) {
Greg Kroah-Hartman
maintainerPATCH 22/321 rtla/osnoise: Prevent NULL dereference in error handling
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
commit 90574d2a675947858b47008df8d07f75ea50d0d0 upstream.
If the "tool->data" allocation fails then there is no need to call osnoise_free_top() and, in fact, doing so will lead to a NULL dereference.
--- tools/tracing/rtla/src/osnoise_top.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-)
tools/tracing/rtla/src/osnoise_top.c +4 -7
@@ -520,8 +520,10 @@ struct osnoise_tool *osnoise_init_top(streturn NULL ; tool->data =osnoise_alloc_top (nr_cpus); -if (!tool->data) - goto out_err; +if (!tool->data) { +osnoise_destroy_tool (tool); +return NULL ; + } tool->params = params;
@@ -529,11 +531,6 @@ struct osnoise_tool *osnoise_init_top(st osnoise_top_handler, NULL);return tool; - -out_err: -osnoise_free_top (tool->data); -osnoise_destroy_tool (tool); -return NULL ; }static int stop_tracing;
Greg Kroah-Hartman
maintainerPATCH 23/321 fs/netfs/fscache_cookie: add missing "n_accesses" check
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Max Kellermann <[email protected]>
commit f71aa06398aabc2e3eaac25acdf3d62e0094ba70 upstream.
This fixes a NULL pointer dereference bug due to a data race which looks like this:
BUG: kernel NULL pointer dereference, address: 0000000000000008 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] SMP PTI CPU: 33 PID: 16573 Comm: kworker/u97:799 Not tainted 6.8.7-cm4all1-hp+ #43 Hardware name: HP ProLiant DL380 Gen9/ProLiant DL380 Gen9, BIOS P89 10/17/2018 Workqueue: events_unbound netfs_rreq_write_to_cache_work RIP: 0010:cachefiles_prepare_write+0x30/0xa0 Code: 57 41 56 45 89 ce 41 55 49 89 cd 41 54 49 89 d4 55 53 48 89 fb 48 83 ec 08 48 8b 47 08 48 83 7f 10 00 48 89 34 24 48 8b 68 20 <48> 8b 45 08 4c 8b 38 74 45 49 8b 7f 50 e8 4e a9 b0 ff 48 8b 73 10 RSP: 0018:ffffb4e78113bde0 EFLAGS: 00010286 RAX: ffff976126be6d10 RBX: ffff97615cdb8438 RCX: 0000000000020000 RDX: ffff97605e6c4c68 RSI: ffff97605e6c4c60 RDI: ffff97615cdb8438 RBP: 0000000000000000 R08: 0000000000278333 R09: 0000000000000001 R10: ffff97605e6c4600 R11: 0000000000000001 R12: ffff97605e6c4c68 R13: 0000000000020000 R14: 0000000000000001 R15: ffff976064fe2c00 FS: 0000000000000000(0000) GS:ffff9776dfd40000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000008 CR3: 000000005942c002 CR4: 00000000001706f0 Call Trace: <TASK> ? __die+0x1f/0x70 ? page_fault_oops+0x15d/0x440 ? search_module_extables+0xe/0x40 ? fixup_exception+0x22/0x2f0 ? exc_page_fault+0x5f/0x100 ? asm_exc_page_fault+0x22/0x30 ? cachefiles_prepare_write+0x30/0xa0 netfs_rreq_write_to_cache_work+0x135/0x2e0 process_one_work+0x137/0x2c0 worker_thread+0x2e9/0x400 ? __pfx_worker_thread+0x10/0x10 kthread+0xcc/0x100 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x30/0x50 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1b/0x30 </TASK> Modules linked in: CR2: 0000000000000008 ---[ end trace 0000000000000000 ]---
This happened because fscache_cookie_state_machine() was slow and was still running while another process invoked fscache_unuse_cookie(); this led to a fscache_cookie_lru_do_one() call, setting the FSCACHE_COOKIE_DO_LRU_DISCARD flag, which was picked up by fscache_cookie_state_machine(), withdrawing the cookie via cachefiles_withdraw_cookie(), clearing cookie->cache_priv.
At the same time, yet another process invoked cachefiles_prepare_write(), which found a NULL pointer in this code line:
struct cachefiles_object *object = cachefiles_cres_object(cres);
The next line crashes, obviously:
struct cachefiles_cache *cache = object->volume->cache;
During cachefiles_prepare_write(), the "n_accesses" counter is non-zero (via fscache_begin_operation()). The cookie must not be withdrawn until it drops to zero.
The counter is checked by fscache_cookie_state_machine() before switching to FSCACHE_COOKIE_STATE_RELINQUISHING and FSCACHE_COOKIE_STATE_WITHDRAWING (in "case FSCACHE_COOKIE_STATE_FAILED"), but not for FSCACHE_COOKIE_STATE_LRU_DISCARDING ("case FSCACHE_COOKIE_STATE_ACTIVE").
This patch adds the missing check. With a non-zero access counter, the function returns and the next fscache_end_cookie_access() call will queue another fscache_cookie_state_machine() call to handle the still-pending FSCACHE_COOKIE_DO_LRU_DISCARD.
--- fs/fscache/cookie.c | 4 ++++ 1 file changed, 4 insertions(+)
fs/fscache/cookie.c +4 -0
@@ -741,6 +741,10 @@ again_locked:spin_lock (&cookie->lock); }if (test_bit (FSCACHE_COOKIE_DO_LRU_DISCARD , &cookie->flags)) { +if (atomic_read (&cookie->n_accesses) !=0 ) +/* still being accessed: postpone it */ +break ; +__fscache_set_cookie_state (cookie,FSCACHE_COOKIE_STATE_LRU_DISCARDING ); wake = true;
Greg Kroah-Hartman
maintainerPATCH 24/321 selinux: fix potential counting error in avc_add_xperms_decision()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhen Lei <[email protected]>
commit 379d9af3f3da2da1bbfa67baf1820c72a080d1f1 upstream.
The count increases only when a node is successfully added to the linked list.
--- security/selinux/avc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
security/selinux/avc.c +1 -1
@@ -332,12 +332,12 @@ static int avc_add_xperms_decision(struc {struct avc_xperms_decision_node *dest_xpd; - node->ae.xp_node->xp.len++; dest_xpd =avc_xperms_decision_alloc (src->used);if (!dest_xpd)return -ENOMEM ;avc_copy_xperms_decision (&dest_xpd->xpd, src);list_add (&dest_xpd->xpd_list, &node->ae.xp_node->xpd_head); + node->ae.xp_node->xp.len++;return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 25/321 mm/memory-failure: use raw_spinlock_t in struct memory_failure_cpu
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Waiman Long <[email protected]>
commit d75abd0d0bc29e6ebfebbf76d11b4067b35844af upstream.
The memory_failure_cpu structure is a per-cpu structure. Access to its content requires the use of get_cpu_var() to lock in the current CPU and disable preemption. The use of a regular spinlock_t for locking purpose is fine for a non-RT kernel.
Since the integration of RT spinlock support into the v5.15 kernel, a spinlock_t in a RT kernel becomes a sleeping lock and taking a sleeping lock in a preemption disabled context is illegal resulting in the following kind of warning.
[12135.732244] BUG: sleeping function called from invalid context at kernel/locking/spinlock_rt.c:48
[12135.732248] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 270076, name: kworker/0:0
[12135.732252] preempt_count: 1, expected: 0
[12135.732255] RCU nest depth: 2, expected: 2
:
[12135.732420] Hardware name: Dell Inc. PowerEdge R640/0HG0J8, BIOS 2.10.2 02/24/2021
[12135.732423] Workqueue: kacpi_notify acpi_os_execute_deferred
[12135.732433] Call Trace:
[12135.732436] <TASK>
[12135.732450] dump_stack_lvl+0x57/0x81
[12135.732461] __might_resched.cold+0xf4/0x12f
[12135.732479] rt_spin_lock+0x4c/0x100
[12135.732491] memory_failure_queue+0x40/0xe0
[12135.732503] ghes_do_memory_failure+0x53/0x390
[12135.732516] ghes_do_proc.constprop.0+0x229/0x3e0
[12135.732575] ghes_proc+0xf9/0x1a0
[12135.732591] ghes_notify_hed+0x6a/0x150
[12135.732602] notifier_call_chain+0x43/0xb0
[12135.732626] blocking_notifier_call_chain+0x43/0x60
[12135.732637] acpi_ev_notify_dispatch+0x47/0x70
[12135.732648] acpi_os_execute_deferred+0x13/0x20
[12135.732654] process_one_work+0x41f/0x500
[12135.732695] worker_thread+0x192/0x360
[12135.732715] kthread+0x111/0x140
[12135.732733] ret_from_fork+0x29/0x50
[12135.732779] </TASK>Fix it by using a raw_spinlock_t for locking instead.
Also move the pr_err() out of the lock critical section and after put_cpu_ptr() to avoid indeterminate latency and the possibility of sleep with this call.
--- mm/memory-failure.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-)
mm/memory-failure.c +11 -9
@@ -2208,7 +2208,7 @@ struct memory_failure_entry {struct memory_failure_cpu { DECLARE_KFIFO(fifo, struct memory_failure_entry, MEMORY_FAILURE_FIFO_SIZE); -spinlock_t lock; +raw_spinlock_t lock;struct work_struct work; };
@@ -2234,20 +2234,22 @@ void memory_failure_queue(unsigned long {struct memory_failure_cpu *mf_cpu;unsigned long proc_flags; +bool buffer_overflow;struct memory_failure_entry entry = { .pfn = pfn, .flags = flags, }; mf_cpu = &get_cpu_var (memory_failure_cpu); -spin_lock_irqsave (&mf_cpu->lock, proc_flags); -if (kfifo_put (&mf_cpu->fifo, entry)) +raw_spin_lock_irqsave (&mf_cpu->lock, proc_flags); + buffer_overflow = !kfifo_put (&mf_cpu->fifo, entry); +if (!buffer_overflow)schedule_work_on (smp_processor_id (), &mf_cpu->work); -else +raw_spin_unlock_irqrestore (&mf_cpu->lock, proc_flags); +put_cpu_var (memory_failure_cpu); +if (buffer_overflow)pr_err ("buffer overflow when queuing memory failure at %#lx\n" , pfn); -spin_unlock_irqrestore (&mf_cpu->lock, proc_flags); -put_cpu_var (memory_failure_cpu); }EXPORT_SYMBOL_GPL (memory_failure_queue);
@@ -2260,9 +2262,9 @@ static void memory_failure_work_func(str mf_cpu = container_of(work, struct memory_failure_cpu, work);for (;;) { -spin_lock_irqsave (&mf_cpu->lock, proc_flags); +raw_spin_lock_irqsave (&mf_cpu->lock, proc_flags); gotten =kfifo_get (&mf_cpu->fifo, &entry); -spin_unlock_irqrestore (&mf_cpu->lock, proc_flags); +raw_spin_unlock_irqrestore (&mf_cpu->lock, proc_flags);if (!gotten)break ;if (entry.flags &MF_SOFT_OFFLINE )
@@ -2292,7 +2294,7 @@ static int __init memory_failure_init(vofor_each_possible_cpu (cpu) { mf_cpu = &per_cpu (memory_failure_cpu, cpu); -spin_lock_init (&mf_cpu->lock); +raw_spin_lock_init (&mf_cpu->lock);INIT_KFIFO (mf_cpu->fifo);INIT_WORK (&mf_cpu->work, memory_failure_work_func); }
Greg Kroah-Hartman
maintainerPATCH 26/321 btrfs: zoned: properly take lock to read/update block groups zoned variables
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Naohiro Aota <[email protected]>
commit e30729d4bd4001881be4d1ad4332a5d4985398f8 upstream.
__btrfs_add_free_space_zoned() references and modifies bg's alloc_offset, ro, and zone_unusable, but without taking the lock. It is mostly safe because they monotonically increase (at least for now) and this function is mostly called by a transaction commit, which is serialized by itself.
Still, taking the lock is a safer and correct option and I'm going to add a change to reset zone_unusable while a block group is still alive. So, add locking around the operations.
--- fs/btrfs/free-space-cache.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-)
fs/btrfs/free-space-cache.c +8 -6
@@ -2677,15 +2677,16 @@ static int __btrfs_add_free_space_zoned(u64 offset = bytenr - block_group->start;u64 to_free, to_unusable;int bg_reclaim_threshold =0 ; -bool initial = ((size == block_group->length) && (block_group->alloc_offset ==0 )); +bool initial;u64 reclaimable_unusable; -WARN_ON (!initial && offset + size > block_group->zone_capacity); +spin_lock (&block_group->lock); + initial = ((size == block_group->length) && (block_group->alloc_offset ==0 )); +WARN_ON (!initial && offset + size > block_group->zone_capacity);if (!initial) bg_reclaim_threshold =READ_ONCE (sinfo->bg_reclaim_threshold); -spin_lock (&ctl->tree_lock);if (!used) to_free = size;else if (initial)
@@ -2698,7 +2699,9 @@ static int __btrfs_add_free_space_zoned( to_free = offset + size - block_group->alloc_offset; to_unusable = size - to_free; +spin_lock (&ctl->tree_lock); ctl->free_space += to_free; +spin_unlock (&ctl->tree_lock);/* * If the block group is read-only, we should account freed space into * bytes_readonly.
@@ -2707,11 +2710,8 @@ static int __btrfs_add_free_space_zoned( block_group->zone_unusable += to_unusable;WARN_ON (block_group->zone_unusable > block_group->length); } -spin_unlock (&ctl->tree_lock);if (!used) { -spin_lock (&block_group->lock); block_group->alloc_offset -= size; -spin_unlock (&block_group->lock); } reclaimable_unusable = block_group->zone_unusable -
@@ -2726,6 +2726,8 @@ static int __btrfs_add_free_space_zoned(btrfs_mark_bg_to_reclaim (block_group); } +spin_unlock (&block_group->lock); +return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 27/321 btrfs: tree-checker: add dev extent item checks
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qu Wenruo <[email protected]>
commit 008e2512dc5696ab2dc5bf264e98a9fe9ceb830e upstream.
[REPORT]
There is a corruption report that btrfs refused to mount a fs that has overlapping dev extents:
BTRFS error (device sdc): dev extent devid 4 physical offset 14263979671552 overlap with previous dev extent end 14263980982272 BTRFS error (device sdc): failed to verify dev extents against chunks: -117
BTRFS error (device sdc): open_ctree failed
[CAUSE]
The direct cause is very obvious, there is a bad dev extent item with incorrect length.
With btrfs check reporting two overlapping extents, the second one shows some clue on the cause:
ERROR: dev extent devid 4 offset 14263979671552 len 6488064 overlap with previous dev extent end 14263980982272
ERROR: dev extent devid 13 offset 2257707008000 len 6488064 overlap with previous dev extent end 2257707270144
ERROR: errors found in extent allocation tree or chunk allocation
The second one looks like a bitflip happened during new chunk allocation:
hex(2257707008000) = 0x20da9d30000 hex(2257707270144) = 0x20da9d70000
diff = 0x00000040000
So it looks like a bitflip happened during new dev extent allocation, resulting the second overlap.
Currently we only do the dev-extent verification at mount time, but if the corruption is caused by memory bitflip, we really want to catch it before writing the corruption to the storage.
Furthermore the dev extent items has the following key definition:
(<device id> DEV_EXTENT <physical offset>)
Thus we can not just rely on the generic key order check to make sure there is no overlapping.
[ENHANCEMENT]
Introduce dedicated dev extent checks, including:
- Fixed member checks
* chunk_tree should always be BTRFS_CHUNK_TREE_OBJECTID (3)
* chunk_objectid should always be BTRFS_FIRST_CHUNK_CHUNK_TREE_OBJECTID (256)
- Alignment checks
* chunk_offset should be aligned to sectorsize
* length should be aligned to sectorsize
* key.offset should be aligned to sectorsize
- Overlap checks
If the previous key is also a dev-extent item, with the same device id, make sure we do not overlap with the previous dev extent.
Reported: Stefan N <[email protected]>
--- fs/btrfs/tree-checker.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+)
fs/btrfs/tree-checker.c +69 -0
@@ -1613,6 +1613,72 @@ static int check_inode_ref(struct extentreturn 0 ; } +static int check_dev_extent_item (const struct extent_buffer *leaf, +const struct btrfs_key *key, +int slot, +struct btrfs_key *prev_key) +{ +struct btrfs_dev_extent *de; +const u32 sectorsize = leaf->fs_info->sectorsize; + + de = btrfs_item_ptr(leaf, slot, struct btrfs_dev_extent); +/* Basic fixed member checks. */ +if (unlikely (btrfs_dev_extent_chunk_tree (leaf, de) != +BTRFS_CHUNK_TREE_OBJECTID )) { +generic_err (leaf, slot, +"invalid dev extent chunk tree id, has %llu expect %llu" , +btrfs_dev_extent_chunk_tree (leaf, de), +BTRFS_CHUNK_TREE_OBJECTID ); +return -EUCLEAN ; + } +if (unlikely (btrfs_dev_extent_chunk_objectid (leaf, de) != +BTRFS_FIRST_CHUNK_TREE_OBJECTID )) { +generic_err (leaf, slot, +"invalid dev extent chunk objectid, has %llu expect %llu" , +btrfs_dev_extent_chunk_objectid (leaf, de), +BTRFS_FIRST_CHUNK_TREE_OBJECTID ); +return -EUCLEAN ; + } +/* Alignment check. */ +if (unlikely (!IS_ALIGNED (key->offset, sectorsize))) { +generic_err (leaf, slot, +"invalid dev extent key.offset, has %llu not aligned to %u" , + key->offset, sectorsize); +return -EUCLEAN ; + } +if (unlikely (!IS_ALIGNED (btrfs_dev_extent_chunk_offset (leaf, de), + sectorsize))) { +generic_err (leaf, slot, +"invalid dev extent chunk offset, has %llu not aligned to %u" , +btrfs_dev_extent_chunk_objectid (leaf, de), + sectorsize); +return -EUCLEAN ; + } +if (unlikely (!IS_ALIGNED (btrfs_dev_extent_length (leaf, de), + sectorsize))) { +generic_err (leaf, slot, +"invalid dev extent length, has %llu not aligned to %u" , +btrfs_dev_extent_length (leaf, de), sectorsize); +return -EUCLEAN ; + } +/* Overlap check with previous dev extent. */ +if (slot && prev_key->objectid == key->objectid && + prev_key->type == key->type) { +struct btrfs_dev_extent *prev_de; +u64 prev_len; + + prev_de = btrfs_item_ptr(leaf, slot - 1, struct btrfs_dev_extent); + prev_len =btrfs_dev_extent_length (leaf, prev_de); +if (unlikely (prev_key->offset + prev_len > key->offset)) { +generic_err (leaf, slot, +"dev extent overlap, prev offset %llu len %llu current offset %llu" , + prev_key->objectid, prev_len, key->offset); +return -EUCLEAN ; + } + } +return 0 ; +} +/* * Common point to switch the item-specific validation. */
@@ -1648,6 +1714,9 @@ static int check_leaf_item(struct extentcase BTRFS_DEV_ITEM_KEY : ret =check_dev_item (leaf, key, slot);break ; +case BTRFS_DEV_EXTENT_KEY : + ret =check_dev_extent_item (leaf, key, slot, prev_key); +break ;case BTRFS_INODE_ITEM_KEY : ret =check_inode_item (leaf, key, slot);break ;
Greg Kroah-Hartman
maintainerPATCH 28/321 drm/amdgpu: Actually check flags for all context ops.
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bas Nieuwenhuizen <[email protected]>
commit 0573a1e2ea7e35bff08944a40f1adf2bb35cea61 upstream.
Missing validation ...
Checked libdrm and it clears all the structs, so we should be safe to just check everything.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +8 -0
@@ -656,16 +656,24 @@ int amdgpu_ctx_ioctl(struct drm_device *switch (args->in.op) {case AMDGPU_CTX_OP_ALLOC_CTX : +if (args->in.flags) +return -EINVAL ; r =amdgpu_ctx_alloc (adev, fpriv, filp, priority, &id); args->out.alloc.ctx_id = id;break ;case AMDGPU_CTX_OP_FREE_CTX : +if (args->in.flags) +return -EINVAL ; r =amdgpu_ctx_free (fpriv, id);break ;case AMDGPU_CTX_OP_QUERY_STATE : +if (args->in.flags) +return -EINVAL ; r =amdgpu_ctx_query (adev, fpriv, id, &args->out);break ;case AMDGPU_CTX_OP_QUERY_STATE2 : +if (args->in.flags) +return -EINVAL ; r =amdgpu_ctx_query2 (adev, fpriv, id, &args->out);break ;case AMDGPU_CTX_OP_GET_STABLE_PSTATE :
Greg Kroah-Hartman
maintainerPATCH 29/321 memcg_write_event_control(): fix a user-triggerable oops
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Al Viro <[email protected]>
commit 046667c4d3196938e992fba0dfcde570aa85cd0e upstream.
we are *not* guaranteed that anything past the terminating NUL is mapped (let alone initialized with anything sane).
--- mm/memcontrol.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
mm/memcontrol.c +5 -2
@@ -4857,9 +4857,12 @@ static ssize_t memcg_write_event_control buf = endp +1 ; cfd =simple_strtoul (buf, &endp,10 ); -if ((*endp !=' ' ) && (*endp !='\0' )) +if (*endp =='\0' ) + buf = endp; +else if (*endp ==' ' ) + buf = endp +1 ; +else return -EINVAL ; - buf = endp +1 ; event =kzalloc (sizeof (*event),GFP_KERNEL );if (!event)
Greg Kroah-Hartman
maintainerPATCH 30/321 drm/amdgpu/jpeg2: properly set atomics vmid field
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alex Deucher <[email protected]>
commit e414a304f2c5368a84f03ad34d29b89f965a33c9 upstream.
This needs to be set as well if the IB uses atomics.
--- drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c +2 -2
@@ -541,11 +541,11 @@ void jpeg_v2_0_dec_ring_emit_ib(struct aamdgpu_ring_write (ring,PACKETJ (mmUVD_LMI_JRBC_IB_VMID_INTERNAL_OFFSET,0 ,0 ,PACKETJ_TYPE0 )); -amdgpu_ring_write (ring, (vmid | (vmid <<4 ))); +amdgpu_ring_write (ring, (vmid | (vmid <<4 ) | (vmid <<8 )));amdgpu_ring_write (ring,PACKETJ (mmUVD_LMI_JPEG_VMID_INTERNAL_OFFSET,0 ,0 ,PACKETJ_TYPE0 )); -amdgpu_ring_write (ring, (vmid | (vmid <<4 ))); +amdgpu_ring_write (ring, (vmid | (vmid <<4 ) | (vmid <<8 )));amdgpu_ring_write (ring,PACKETJ (mmUVD_LMI_JRBC_IB_64BIT_BAR_LOW_INTERNAL_OFFSET,0 ,0 ,PACKETJ_TYPE0 ));
Greg Kroah-Hartman
maintainerPATCH 31/321 s390/uv: Panic for set and remove shared access UVC errors
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Claudio Imbrenda <[email protected]>
[ Upstream commit cff59d8631e1409ffdd22d9d717e15810181b32c ]
The return value uv_set_shared() and uv_remove_shared() (which are wrappers around the share() function) is not always checked. The system integrity of a protected guest depends on the Share and Unshare UVCs being successful. This means that any caller that fails to check the return value will compromise the security of the protected guest.
No code path that would lead to such violation of the security guarantees is currently exercised, since all the areas that are shared never get unshared during the lifetime of the system. This might change and become an issue in the future.
The Share and Unshare UVCs can only fail in case of hypervisor misbehaviour (either a bug or malicious behaviour). In such cases there is no reasonable way forward, and the system needs to panic.
This patch replaces the return at the end of the share() function with a panic, to guarantee system integrity.
Message-ID: <[email protected]>
--- arch/s390/include/asm/uv.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
arch/s390/include/asm/uv.h +4 -1
@@ -387,7 +387,10 @@ static inline int share(unsigned long addr, u16 cmd)if (!uv_call (0 , (u64)&uvcb))return 0 ; -return -EINVAL ; +pr_err ("%s UVC failed (rc: 0x%x, rrc: 0x%x), possible hypervisor bug.\n" , + uvcb.header.cmd ==UVC_CMD_SET_SHARED_ACCESS ?"Share" :"Unshare" , + uvcb.header.rc, uvcb.header.rrc); +panic ("System security cannot be guaranteed unless the system panics now.\n" ); }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 32/321 bpf: Fix updating attached freplace prog in prog_array map
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Leon Hwang <[email protected]>
[ Upstream commit fdad456cbcca739bae1849549c7a999857c56f88 ]
The commit f7866c358733 ("bpf: Fix null pointer dereference in resolve_prog_type() for BPF_PROG_TYPE_EXT") fixed a NULL pointer dereference panic, but didn't fix the issue that
fails to update attached freplace prog to prog_array map.
Since commit 1c123c567fb1 ("bpf: Resolve fext program type when checking map compatibility"), freplace prog and its target prog are able to tail call each other.
And the commit 3aac1ead5eb6 ("bpf: Move prog->aux->linked_prog and trampoline into bpf_link on attach") sets prog->aux->dst_prog as NULL after attaching freplace prog to its
target prog.
After loading freplace the prog_array's owner type is BPF_PROG_TYPE_SCHED_CLS. Then, after attaching freplace its prog->aux->dst_prog is NULL. Then, while updating freplace in prog_array the bpf_prog_map_compatible() incorrectly returns false because resolve_prog_type() returns BPF_PROG_TYPE_EXT instead of BPF_PROG_TYPE_SCHED_CLS.
After this patch the resolve_prog_type() returns BPF_PROG_TYPE_SCHED_CLS and update to prog_array can succeed.
--- include/linux/bpf_verifier.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/linux/bpf_verifier.h +2 -2
@@ -645,8 +645,8 @@ static inline u32 type_flag(u32 type)/* only use after check_attach_btf_id() */ static inline enum bpf_prog_type resolve_prog_type (const struct bpf_prog *prog) { -return (prog->type ==BPF_PROG_TYPE_EXT && prog->aux->dst_prog) ? - prog->aux->dst_prog->type : prog->type; +return (prog->type ==BPF_PROG_TYPE_EXT && prog->aux->saved_dst_prog_type) ? + prog->aux->saved_dst_prog_type : prog->type; }static inline bool bpf_prog_check_recur (const struct bpf_prog *prog)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 33/321 nilfs2: prevent WARNING in nilfs_dat_commit_end()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ryusuke Konishi <[email protected]>
[ Upstream commit 602ce7b8e1343b19c0cf93a3dd1926838ac5a1cc ]
If nilfs2 reads a corrupted disk image and its DAT metadata file contains invalid lifetime data for a virtual block number, a kernel warning can be generated by the WARN_ON check in nilfs_dat_commit_end() and can panic if the kernel is booted with panic_on_warn.
This patch avoids the issue with a sanity check that treats it as an error.
Since error return is not allowed in the execution phase of nilfs_dat_commit_end(), this inserts that sanity check in nilfs_dat_prepare_end(), which prepares for nilfs_dat_commit_end().
As the error code, -EINVAL is returned to notify bmap layer of the metadata corruption. When the bmap layer sees this code, it handles the abnormal situation and replaces the return code with -EIO as it should.
--- fs/nilfs2/dat.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
fs/nilfs2/dat.c +11 -0
@@ -158,6 +158,7 @@ void nilfs_dat_commit_start(struct inode *dat, struct nilfs_palloc_req *req,int nilfs_dat_prepare_end (struct inode *dat,struct nilfs_palloc_req *req) {struct nilfs_dat_entry *entry; +__u64 start;sector_t blocknr;void *kaddr;int ret;
@@ -169,6 +170,7 @@ int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req) kaddr =kmap_atomic (req->pr_entry_bh->b_page); entry =nilfs_palloc_block_get_entry (dat, req->pr_entry_nr, req->pr_entry_bh, kaddr); + start =le64_to_cpu (entry->de_start); blocknr =le64_to_cpu (entry->de_blocknr);kunmap_atomic (kaddr);
@@ -179,6 +181,15 @@ int nilfs_dat_prepare_end(struct inode *dat, struct nilfs_palloc_req *req)return ret; } } +if (unlikely (start >nilfs_mdt_cno (dat))) { +nilfs_err (dat->i_sb, +"vblocknr = %llu has abnormal lifetime: start cno (= %llu) > current cno (= %llu)" , + (unsigned long long )req->pr_entry_nr, + (unsigned long long )start, + (unsigned long long )nilfs_mdt_cno (dat)); +nilfs_dat_abort_entry (dat, req); +return -EINVAL ; + }return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 34/321 ext4, jbd2: add an optimized bmap for the journal inode
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Theodore Ts'o <[email protected]>
[ Upstream commit 62913ae96de747091c4dacd06d158e7729c1a76d ]
The generic bmap() function exported by the VFS takes locks and does checks that are not necessary for the journal inode. So allow the file system to set a journal-optimized bmap function in journal->j_bmap.
--- fs/ext4/super.c | 23 +++++++++++++++++++++++ fs/jbd2/journal.c | 9 ++++++--- include/linux/jbd2.h | 8 ++++++++ 3 files changed, 37 insertions(+), 3 deletions(-)
fs/ext4/super.c +23 -0
@@ -5752,6 +5752,28 @@ static struct inode *ext4_get_journal_inode(struct super_block *sb,return journal_inode; } +static int ext4_journal_bmap (journal_t *journal,sector_t *block) +{ +struct ext4_map_blocks map; +int ret; + +if (journal->j_inode ==NULL ) +return 0 ; + + map.m_lblk = *block; + map.m_len =1 ; + ret =ext4_map_blocks (NULL , journal->j_inode, &map,0 ); +if (ret <=0 ) { +ext4_msg (journal->j_inode->i_sb,KERN_CRIT , +"journal bmap failed: block %llu ret %d\n" , + *block, ret); +jbd2_journal_abort (journal, ret ? ret : -EIO ); +return ret; + } + *block = map.m_pblk; +return 0 ; +} +static journal_t *ext4_get_journal (struct super_block *sb,unsigned int journal_inum) {
@@ -5772,6 +5794,7 @@ static journal_t *ext4_get_journal(struct super_block *sb,return NULL ; } journal->j_private = sb; + journal->j_bmap = ext4_journal_bmap;ext4_init_journal_params (sb, journal);return journal; }
fs/jbd2/journal.c +6 -3
@@ -971,10 +971,13 @@ int jbd2_journal_bmap(journal_t *journal, unsigned long blocknr, {int err =0 ;unsigned long long ret; -sector_t block =0 ; +sector_t block = blocknr; -if (journal->j_inode) { - block = blocknr; +if (journal->j_bmap) { + err = journal->j_bmap (journal, &block); +if (err ==0 ) + *retp = block; + }else if (journal->j_inode) { ret =bmap (journal->j_inode, &block);if (ret || !block) {
include/linux/jbd2.h +8 -0
@@ -1302,6 +1302,14 @@ struct journal_sstruct buffer_head *bh, enum passtype pass, int off, tid_t expected_commit_id); + +/** +* @j_bmap: +* +* Bmap function that should be used instead of the generic +* VFS bmap function. +*/ +int (*j_bmap)(struct journal_s *journal,sector_t *block); };#define jbd2_might_wait_for_commit (j) \
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 35/321 9P FS: Fix wild-memory-access write in v9fs_get_acl
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ivan Orlov <[email protected]>
[ Upstream commit 707823e7f22f3864ddc7d85e8e9b614afe4f1b16 ]
KASAN reported the following issue:
[ 36.825817][ T5923] BUG: KASAN: wild-memory-access in v9fs_get_acl+0x1a4/0x390 [ 36.827479][ T5923] Write of size 4 at addr 9fffeb37f97f1c00 by task syz-executor798/5923 [ 36.829303][ T5923] [ 36.829846][ T5923] CPU: 0 PID: 5923 Comm: syz-executor798 Not tainted 6.2.0-syzkaller-18302-g596b6b709632 #0 [ 36.832110][ T5923] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/21/2023 [ 36.834464][ T5923] Call trace: [ 36.835196][ T5923] dump_backtrace+0x1c8/0x1f4 [ 36.836229][ T5923] show_stack+0x2c/0x3c [ 36.837100][ T5923] dump_stack_lvl+0xd0/0x124 [ 36.838103][ T5923] print_report+0xe4/0x4c0 [ 36.839068][ T5923] kasan_report+0xd4/0x130 [ 36.840052][ T5923] kasan_check_range+0x264/0x2a4 [ 36.841199][ T5923] __kasan_check_write+0x2c/0x3c [ 36.842216][ T5923] v9fs_get_acl+0x1a4/0x390 [ 36.843232][ T5923] v9fs_mount+0x77c/0xa5c [ 36.844163][ T5923] legacy_get_tree+0xd4/0x16c [ 36.845173][ T5923] vfs_get_tree+0x90/0x274 [ 36.846137][ T5923] do_new_mount+0x25c/0x8c8 [ 36.847066][ T5923] path_mount+0x590/0xe58 [ 36.848147][ T5923] __arm64_sys_mount+0x45c/0x594 [ 36.849273][ T5923] invoke_syscall+0x98/0x2c0 [ 36.850421][ T5923] el0_svc_common+0x138/0x258 [ 36.851397][ T5923] do_el0_svc+0x64/0x198 [ 36.852398][ T5923] el0_svc+0x58/0x168 [ 36.853224][ T5923] el0t_64_sync_handler+0x84/0xf0 [ 36.854293][ T5923] el0t_64_sync+0x190/0x194
Calling '__v9fs_get_acl' method in 'v9fs_get_acl' creates the following chain of function calls:
__v9fs_get_acl
v9fs_fid_get_acl
v9fs_fid_xattr_get
p9_client_xattrwalk
Function p9_client_xattrwalk accepts a pointer to u64-typed variable attr_size and puts some u64 value into it. However, after the executing the p9_client_xattrwalk, in some circumstances we assign the value of u64-typed variable 'attr_size' to the variable 'retval', which we will return. However, the type of 'retval' is ssize_t, and if the value of attr_size is larger than SSIZE_MAX, we will face the signed type overflow. If the overflow occurs, the result of v9fs_fid_xattr_get may be negative, but not classified as an error. When we try to allocate an acl with 'broken' size we receive an error, but don't process it. When we try to free this acl, we face the 'wild-memory-access' error (because it wasn't allocated).
This patch will add new condition to the 'v9fs_fid_xattr_get' function, so it will return an EOVERFLOW error if the 'attr_size' is larger than SSIZE_MAX.
In this version of the patch I simplified the condition.
In previous (v2) version of the patch I removed explicit type conversion and added separate condition to check the possible overflow and return an error (in v1 version I've just modified the existing condition).
Tested via syzkaller.
--- fs/9p/xattr.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
fs/9p/xattr.c +5 -3
@@ -34,10 +34,12 @@ ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name,return retval; }if (attr_size > buffer_size) { -if (!buffer_size)/* request to get the attr_size */ - retval = attr_size; -else +if (buffer_size) retval = -ERANGE ; +else if (attr_size >SSIZE_MAX ) + retval = -EOVERFLOW ; +else /* request to get the attr_size */ + retval = attr_size; }else {iov_iter_truncate (&to, attr_size); retval =p9_client_read (attr_fid,0 , &to, &err);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 36/321 nilfs2: initialize "struct nilfs_binfo_dat"->bi_pad field
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tetsuo Handa <[email protected]>
[ Upstream commit 7397031622e05ca206e2d674ec199d6bb66fc9ba ]
nilfs_btree_assign_p() and nilfs_direct_assign_p() are not initializing "struct nilfs_binfo_dat"->bi_pad field, causing uninit-value reports when being passed to CRC function.
--- fs/nilfs2/btree.c | 1 + fs/nilfs2/direct.c | 1 + 2 files changed, 2 insertions(+)
fs/nilfs2/btree.c +1 -0
@@ -2224,6 +2224,7 @@ static int nilfs_btree_assign_p(struct nilfs_bmap *btree,/* on-disk format */ binfo->bi_dat.bi_blkoff =cpu_to_le64 (key); binfo->bi_dat.bi_level = level; +memset (binfo->bi_dat.bi_pad,0 ,sizeof (binfo->bi_dat.bi_pad));return 0 ; }
fs/nilfs2/direct.c +1 -0
@@ -319,6 +319,7 @@ static int nilfs_direct_assign_p(struct nilfs_bmap *direct, binfo->bi_dat.bi_blkoff =cpu_to_le64 (key); binfo->bi_dat.bi_level =0 ; +memset (binfo->bi_dat.bi_pad,0 ,sizeof (binfo->bi_dat.bi_pad));return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 37/321 mm: khugepaged: fix kernel BUG in hpage_collapse_scan_file()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ivan Orlov <[email protected]>
[ Upstream commit 2ce0bdfebc74f6cbd4e97a4e767d505a81c38cf2 ]
Syzkaller reported the following issue:
kernel BUG at mm/khugepaged.c:1823!
invalid opcode: 0000 [#1] PREEMPT SMP KASAN
CPU: 1 PID: 5097 Comm: syz-executor220 Not tainted 6.2.0-syzkaller-13154-g857f1268a591 #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/16/2023 RIP: 0010:collapse_file mm/khugepaged.c:1823 [inline] RIP: 0010:hpage_collapse_scan_file+0x67c8/0x7580 mm/khugepaged.c:2233 Code: 00 00 89 de e8 c9 66 a3 ff 31 ff 89 de e8 c0 66 a3 ff 45 84 f6 0f 85 28 0d 00 00 e8 22 64 a3 ff e9 dc f7 ff ff e8 18 64 a3 ff <0f> 0b f3 0f 1e fa e8 0d 64 a3 ff e9 93 f6 ff ff f3 0f 1e fa 4c 89 RSP: 0018:ffffc90003dff4e0 EFLAGS: 00010093 RAX: ffffffff81e95988 RBX: 00000000000001c1 RCX: ffff8880205b3a80 RDX: 0000000000000000 RSI: 00000000000001c0 RDI: 00000000000001c1 RBP: ffffc90003dff830 R08: ffffffff81e90e67 R09: fffffbfff1a433c3 R10: 0000000000000000 R11: dffffc0000000001 R12: 0000000000000000 R13: ffffc90003dff6c0 R14: 00000000000001c0 R15: 0000000000000000 FS: 00007fdbae5ee700(0000) GS:ffff8880b9900000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007fdbae6901e0 CR3: 000000007b2dd000 CR4: 00000000003506e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: <TASK> madvise_collapse+0x721/0xf50 mm/khugepaged.c:2693 madvise_vma_behavior mm/madvise.c:1086 [inline] madvise_walk_vmas mm/madvise.c:1260 [inline] do_madvise+0x9e5/0x4680 mm/madvise.c:1439 __do_sys_madvise mm/madvise.c:1452 [inline] __se_sys_madvise mm/madvise.c:1450 [inline] __x64_sys_madvise+0xa5/0xb0 mm/madvise.c:1450 do_syscall_x64 arch/x86/entry/common.c:50 [inline] do_syscall_64+0x41/0xc0 arch/x86/entry/common.c:80 entry_SYSCALL_64_after_hwframe+0x63/0xcd
The xas_store() call during page cache scanning can potentially translate 'xas' into the error state (with the reproducer provided by the syzkaller the error code is -ENOMEM). However, there are no further checks after the 'xas_store', and the next call of 'xas_next' at the start of the scanning cycle doesn't increase the xa_index, and the issue occurs.
This patch will add the xarray state error checking after the xas_store() and the corresponding result error code.
Tested via syzbot.
--- include/trace/events/huge_memory.h | 3 ++- mm/khugepaged.c | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-)
include/trace/events/huge_memory.h +2 -1
@@ -36,7 +36,8 @@ EM( SCAN_ALLOC_HUGE_PAGE_FAIL, "alloc_huge_page_failed") \ EM( SCAN_CGROUP_CHARGE_FAIL, "ccgroup_charge_failed") \ EM( SCAN_TRUNCATED, "truncated") \ - EMe(SCAN_PAGE_HAS_PRIVATE, "page_has_private") \ + EM( SCAN_PAGE_HAS_PRIVATE, "page_has_private") \ + EMe(SCAN_STORE_FAILED, "store_failed")#undef EM#undef EMe
mm/khugepaged.c +20 -0
@@ -55,6 +55,7 @@ enum scan_result {SCAN_CGROUP_CHARGE_FAIL ,SCAN_TRUNCATED ,SCAN_PAGE_HAS_PRIVATE , + SCAN_STORE_FAILED, };#define CREATE_TRACE_POINTS
@@ -1840,6 +1841,15 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr, goto xa_locked; }xas_store (&xas, hpage); +if (xas_error (&xas)) { +/* revert shmem_charge performed +* in the previous condition +*/ + mapping->nrpages--; +shmem_uncharge (mapping->host,1 ); + result =SCAN_STORE_FAILED ; + goto xa_locked; + } nr_none++;continue ; }
@@ -1991,6 +2001,11 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,/* Finally, replace with the new page. */ xas_store (&xas, hpage); +/* We can't get an ENOMEM here (because the allocation happened before) +* but let's check for errors (XArray implementation can be +* changed in the future) +*/ +WARN_ON_ONCE (xas_error (&xas));continue ; out_unlock:unlock_page (page);
@@ -2028,6 +2043,11 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,/* Join all the small entries into a single multi-index entry */ xas_set_order (&xas, start,HPAGE_PMD_ORDER );xas_store (&xas, hpage); +/* Here we can't get an ENOMEM (because entries were +* previously allocated) But let's check for errors +* (XArray implementation can be changed in the future) +*/ +WARN_ON_ONCE (xas_error (&xas)); xa_locked:xas_unlock_irq (&xas); xa_unlocked:
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 38/321 bpf: Split off basic BPF verifier log into separate file
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrii Nakryiko <[email protected]>
[ Upstream commit 4294a0a7ab6282c3d92f03de84e762dda993c93d ]
kernel/bpf/verifier.c file is large and growing larger all the time. So it's good to start splitting off more or less self-contained parts into separate files to keep source code size (somewhat) somewhat under control.
This patch is a one step in this direction, moving some of BPF verifier log routines into a separate kernel/bpf/log.c. Right now it's most low-level and isolated routines to append data to log, reset log to previous position, etc. Eventually we could probably move verifier state printing logic here as well, but this patch doesn't attempt to do that yet.
Subsequent patches will add more logic to verifier log management, so having basics in a separate file will make sure verifier.c doesn't grow more with new changes.
Stable-dep-of: cff36398bd4c ("bpf: drop unnecessary user-triggerable WARN_ONCE in verifierl log")
--- include/linux/bpf_verifier.h | 19 +++----- kernel/bpf/Makefile | 3 +- kernel/bpf/log.c | 85 ++++++++++++++++++++++++++++++++++++ kernel/bpf/verifier.c | 69 ----------------------------- 4 files changed, 94 insertions(+), 82 deletions(-) create mode 100644 kernel/bpf/log.c
include/linux/bpf_verifier.h +7 -12
@@ -445,11 +445,6 @@ struct bpf_verifier_log {u32 len_total; }; -static inline bool bpf_verifier_log_full (const struct bpf_verifier_log *log) -{ -return log->len_used >= log->len_total -1 ; -} -#define BPF_LOG_LEVEL1 1#define BPF_LOG_LEVEL2 2#define BPF_LOG_STATS 4
@@ -459,6 +454,11 @@ static inline bool bpf_verifier_log_full(const struct bpf_verifier_log *log)#define BPF_LOG_MIN_ALIGNMENT 8U#define BPF_LOG_ALIGNMENT 40U +static inline bool bpf_verifier_log_full (const struct bpf_verifier_log *log) +{ +return log->len_used >= log->len_total -1 ; +} +static inline bool bpf_verifier_log_needed (const struct bpf_verifier_log *log) { return log &&
@@ -466,13 +466,6 @@ static inline bool bpf_verifier_log_needed(const struct bpf_verifier_log *log) log->level == BPF_LOG_KERNEL); } -static inline bool -bpf_verifier_log_attr_valid (const struct bpf_verifier_log *log) -{ -return log->len_total >=128 && log->len_total <=UINT_MAX >>2 && - log->level && log->ubuf && !(log->level & ~BPF_LOG_MASK ); -} -#define BPF_MAX_SUBPROGS 256struct bpf_subprog_info {
@@ -556,12 +549,14 @@ struct bpf_verifier_env {char type_str_buf[TYPE_STR_BUF_LEN ]; }; +bool bpf_verifier_log_attr_valid (const struct bpf_verifier_log *log); __printf(2, 0) void bpf_verifier_vlog(struct bpf_verifier_log *log,const char *fmt,va_list args); __printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env,const char *fmt, ...); __printf(2, 3) void bpf_log(struct bpf_verifier_log *log,const char *fmt, ...); +void bpf_vlog_reset (struct bpf_verifier_log *log,u32 new_pos);static inline struct bpf_func_state *cur_func (struct bpf_verifier_env *env) {
kernel/bpf/Makefile +2 -1
@@ -6,7 +6,8 @@ cflags-nogcse-$(CONFIG_X86)$(CONFIG_CC_IS_GCC) := -fno-gcse endif CFLAGS_core.o += $(call cc-disable-warning, override-init) $(cflags-nogcse-yy) -obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o bpf_iter.o map_iter.o task_iter.o prog_iter.o link_iter.o +obj-$(CONFIG_BPF_SYSCALL) += syscall.o verifier.o inode.o helpers.o tnum.o log.o +obj-$(CONFIG_BPF_SYSCALL) += bpf_iter.o map_iter.o task_iter.o prog_iter.o link_iter.o obj-$(CONFIG_BPF_SYSCALL) += hashtab.o arraymap.o percpu_freelist.o bpf_lru_list.o lpm_trie.o map_in_map.o bloom_filter.o obj-$(CONFIG_BPF_SYSCALL) += local_storage.o queue_stack_maps.o ringbuf.o obj-$(CONFIG_BPF_SYSCALL) += bpf_local_storage.o bpf_task_storage.o
kernel/bpf/log.c new file +85 -0
85 lines not on this page · raw message
kernel/bpf/verifier.c +0 -69
81 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 39/321 bpf: drop unnecessary user-triggerable WARN_ONCE in verifierl log
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrii Nakryiko <[email protected]>
[ Upstream commit cff36398bd4c7d322d424433db437f3c3391c491 ]
It's trivial for user to trigger "verifier log line truncated" warning, as verifier has a fixed-sized buffer of 1024 bytes (as of now), and there are at least two pieces of user-provided information that can be output through this buffer, and both can be arbitrarily sized by user:
- BTF names;
- BTF.ext source code lines strings.
Verifier log buffer should be properly sized for typical verifier state output. But it's sort-of expected that this buffer won't be long enough in some circumstances. So let's drop the check. In any case code will work correctly, at worst truncating a part of a single line output.
--- kernel/bpf/log.c | 3 --- 1 file changed, 3 deletions(-)
kernel/bpf/log.c +0 -3
@@ -22,9 +22,6 @@ void bpf_verifier_vlog(struct bpf_verifier_log *log, const char *fmt, n =vscnprintf (log->kbuf,BPF_VERIFIER_TMP_LOG_SIZE , fmt, args); -WARN_ONCE (n >=BPF_VERIFIER_TMP_LOG_SIZE -1 , -"verifier log line truncated - local buffer too short\n" ); -if (log->level ==BPF_LOG_KERNEL ) {bool newline = n >0 && log->kbuf[n -1 ] =='\n' ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 40/321 posix-timers: Ensure timer ID search-loop limit is valid
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Gleixner <[email protected]>
[ Upstream commit 8ce8849dd1e78dadcee0ec9acbd259d239b7069f ]
posix_timer_add() tries to allocate a posix timer ID by starting from the cached ID which was stored by the last successful allocation.
This is done in a loop searching the ID space for a free slot one by one. The loop has to terminate when the search wrapped around to the starting point.
But that's racy vs. establishing the starting point. That is read out lockless, which leads to the following problem:
CPU0 CPU1posix_timer_add()
start = sig->posix_timer_id;
lock(hash_lock);
... posix_timer_add()
if (++sig->posix_timer_id < 0)
start = sig->posix_timer_id;
sig->posix_timer_id = 0;So CPU1 can observe a negative start value, i.e. -1, and the loop break never happens because the condition can never be true:
if (sig->posix_timer_id == start)
break;
While this is unlikely to ever turn into an endless loop as the ID space is huge (INT_MAX), the racy read of the start value caught the attention of KCSAN and Dmitry unearthed that incorrectness.
Rewrite it so that all id operations are under the hash lock.
--- include/linux/sched/signal.h | 2 +- kernel/time/posix-timers.c | 31 ++++++++++++++++++------------- 2 files changed, 19 insertions(+), 14 deletions(-)
include/linux/sched/signal.h +1 -1
@@ -135,7 +135,7 @@ struct signal_struct {#ifdef CONFIG_POSIX_TIMERS /* POSIX.1b Interval Timers */ -int posix_timer_id; +unsigned int next_posix_timer_id;struct list_head posix_timers;/* ITIMER_REAL timer for the process */
kernel/time/posix-timers.c +18 -13
@@ -140,25 +140,30 @@ static struct k_itimer *posix_timer_by_id(timer_t id)static int posix_timer_add (struct k_itimer *timer) {struct signal_struct *sig = current->signal; -int first_free_id = sig->posix_timer_id;struct hlist_head *head; -int ret = -ENOENT ; +unsigned int cnt, id; -do { +/* +* FIXME: Replace this by a per signal struct xarray once there is +* a plan to handle the resulting CRIU regression gracefully. +*/ +for (cnt =0 ; cnt <=INT_MAX ; cnt++) {spin_lock (&hash_lock); - head = &posix_timers_hashtable[hash (sig, sig->posix_timer_id)]; -if (!__posix_timers_find (head, sig, sig->posix_timer_id)) { + id = sig->next_posix_timer_id; + +/* Write the next ID back. Clamp it to the positive space */ + sig->next_posix_timer_id = (id +1 ) &INT_MAX ; + + head = &posix_timers_hashtable[hash (sig, id)]; +if (!__posix_timers_find (head, sig, id)) {hlist_add_head_rcu (&timer->t_hash, head); - ret = sig->posix_timer_id; +spin_unlock (&hash_lock); +return id; } -if (++sig->posix_timer_id <0 ) - sig->posix_timer_id =0 ; -if ((sig->posix_timer_id == first_free_id) && (ret == -ENOENT )) -/* Loop over all possible ids completed */ - ret = -EAGAIN ;spin_unlock (&hash_lock); - }while (ret == -ENOENT ); -return ret; + } +/* POSIX return code when no timer ID could be allocated */ +return -EAGAIN ; }static inline void unlock_timer (struct k_itimer *timr,unsigned long flags)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 41/321 pid: Replace struct pid 1-element array with flex-array
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kees Cook <[email protected]>
[ Upstream commit b69f0aeb068980af983d399deafc7477cec8bc04 ]
For pid namespaces, struct pid uses a dynamically sized array member, "numbers". This was implemented using the ancient 1-element fake flexible array, which has been deprecated for decades.
Replace it with a C99 flexible array, refactor the array size calculations to use struct_size(), and address elements via indexes. Note that the static initializer (which defines a single element) works as-is, and requires no special handling.
Without this, CONFIG_UBSAN_BOUNDS (and potentially CONFIG_FORTIFY_SOURCE) will trigger bounds checks:
https://lore.kernel.org/lkml/20230517-bushaltestelle-super-e223978c1ba6@brauner
--- include/linux/pid.h | 2 +- kernel/pid.c | 7 +++++-- kernel/pid_namespace.c | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-)
include/linux/pid.h +1 -1
@@ -67,7 +67,7 @@ struct pid/* wait queue for pidfd notifications */ wait_queue_head_t wait_pidfd;struct rcu_head rcu; -struct upid numbers[1 ]; +struct upid numbers[]; };extern struct pid init_struct_pid;
kernel/pid.c +5 -2
@@ -661,8 +661,11 @@ void __init pid_idr_init(void)idr_init (&init_pid_ns.idr); - init_pid_ns.pid_cachep =KMEM_CACHE (pid, -SLAB_HWCACHE_ALIGN |SLAB_PANIC |SLAB_ACCOUNT ); + init_pid_ns.pid_cachep =kmem_cache_create ("pid" , +struct_size ((struct pid *)NULL , numbers,1 ), + __alignof__(struct pid ), +SLAB_HWCACHE_ALIGN |SLAB_PANIC |SLAB_ACCOUNT , +NULL ); }static struct file *__pidfd_fget (struct task_struct *task,int fd)
kernel/pid_namespace.c +1 -1
@@ -47,7 +47,7 @@ static struct kmem_cache *create_pid_cachep(unsigned int level)return kc;snprintf (name,sizeof (name),"pid_%u" , level +1 ); - len =sizeof (struct pid ) + level *sizeof (struct upid ); + len =struct_size ((struct pid *)NULL , numbers, level +1 );mutex_lock (&pid_caches_mutex);/* Name collision forces to do allocation under mutex. */ if (!*pkc)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 42/321 gfs2: Rename remaining "transaction" glock references
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andreas Gruenbacher <[email protected]>
[ Upstream commit af1abe11466f1a6cb6ba22ee0d815c21c3559947 ]
The transaction glock was repurposed to serve as the new freeze glock years ago. Don't refer to it as the transaction glock anymore.
Also, to be more precise, call it the "freeze glock" instead of the "freeze lock". Ditto for the journal glock.
Stable-dep-of: f66af88e3321 ("gfs2: Stop using gfs2_make_fs_ro for withdraw")
--- fs/gfs2/glock.c | 4 ++-- fs/gfs2/ops_fstype.c | 2 +- fs/gfs2/recovery.c | 8 ++++---- fs/gfs2/super.c | 2 +- fs/gfs2/util.c | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-)
fs/gfs2/glock.c +2 -2
@@ -146,8 +146,8 @@ static void gfs2_glock_dealloc(struct rcu_head *rcu)* * We need to allow some glocks to be enqueued, dequeued, promoted, and demoted * when we're withdrawn. For example, to maintain metadata integrity, we should -* disallow the use of inode and rgrp glocks when withdrawn. Other glocks, like -* iopen or the transaction glocks may be safely used because none of their +* disallow the use of inode and rgrp glocks when withdrawn. Other glocks like +* the iopen or freeze glock may be safely used because none of their * metadata goes through the journal. So in general, we should disallow all * glocks that are journaled, and allow all the others. One exception is: * we need to allow our active journal to be promoted and demoted so others
fs/gfs2/ops_fstype.c +1 -1
@@ -434,7 +434,7 @@ static int init_locking(struct gfs2_sbd *sdp, struct gfs2_holder *mount_gh, error =gfs2_glock_get (sdp,GFS2_FREEZE_LOCK , &gfs2_freeze_glops,CREATE , &sdp->sd_freeze_gl);if (error) { -fs_err (sdp,"can't create transaction glock: %d\n" , error); +fs_err (sdp,"can't create freeze glock: %d\n" , error); goto fail_rename; }
fs/gfs2/recovery.c +4 -4
@@ -420,10 +420,10 @@ void gfs2_recover_func(struct work_struct *work)if (sdp->sd_args.ar_spectator) goto fail;if (jd->jd_jid != sdp->sd_lockstruct.ls_jid) { -fs_info (sdp,"jid=%u: Trying to acquire journal lock...\n" , +fs_info (sdp,"jid=%u: Trying to acquire journal glock...\n" , jd->jd_jid); jlocked =1 ; -/* Acquire the journal lock so we can do recovery */ +/* Acquire the journal glock so we can do recovery */ error = gfs2_glock_nq_num(sdp, jd->jd_jid, &gfs2_journal_glops, LM_ST_EXCLUSIVE,
@@ -465,10 +465,10 @@ void gfs2_recover_func(struct work_struct *work) ktime_ms_delta(t_jhd, t_jlck));if (!(head.lh_flags &GFS2_LOG_HEAD_UNMOUNT )) { -fs_info (sdp,"jid=%u: Acquiring the transaction lock...\n" , +fs_info (sdp,"jid=%u: Acquiring the freeze glock...\n" , jd->jd_jid); -/* Acquire a shared hold on the freeze lock */ +/* Acquire a shared hold on the freeze glock */ error =gfs2_freeze_lock (sdp, &thaw_gh,LM_FLAG_PRIORITY );if (error)
fs/gfs2/super.c +1 -1
@@ -463,7 +463,7 @@ static int gfs2_write_inode(struct inode *inode, struct writeback_control *wbc)* @flags: The type of dirty * * Unfortunately it can be called under any combination of inode -* glock and transaction lock, so we have to check carefully. +* glock and freeze glock, so we have to check carefully. * * At the moment this deals only with atime - it should be possible * to expand that role in future, once a review of the locking has
fs/gfs2/util.c +1 -1
@@ -107,7 +107,7 @@ int gfs2_freeze_lock(struct gfs2_sbd *sdp, struct gfs2_holder *freeze_gh, error =gfs2_glock_nq_init (sdp->sd_freeze_gl,LM_ST_SHARED , flags, freeze_gh);if (error && error !=GLR_TRYFAILED ) -fs_err (sdp,"can't lock the freeze lock: %d\n" , error); +fs_err (sdp,"can't lock the freeze glock: %d\n" , error);return error; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 43/321 gfs2: Rename the {freeze,thaw}_super callbacks
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andreas Gruenbacher <[email protected]>
[ Upstream commit 097cca525adf10f35c9dac037155564f1b1a688b ]
Rename gfs2_freeze to gfs2_freeze_super and gfs2_unfreeze to gfs2_thaw_super to match the names of the corresponding super operations.
Stable-dep-of: f66af88e3321 ("gfs2: Stop using gfs2_make_fs_ro for withdraw")
--- fs/gfs2/super.c | 12 ++++++------ fs/gfs2/util.c | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-)
fs/gfs2/super.c +6 -6
@@ -682,12 +682,12 @@ void gfs2_freeze_func(struct work_struct *work) }/** -* gfs2_freeze - prevent further writes to the filesystem +* gfs2_freeze_super - prevent further writes to the filesystem * @sb: the VFS structure for the filesystem * */ -static int gfs2_freeze (struct super_block *sb) +static int gfs2_freeze_super (struct super_block *sb) {struct gfs2_sbd *sdp = sb->s_fs_info;int error;
@@ -727,12 +727,12 @@ static int gfs2_freeze(struct super_block *sb) }/** -* gfs2_unfreeze - reallow writes to the filesystem +* gfs2_thaw_super - reallow writes to the filesystem * @sb: the VFS structure for the filesystem * */ -static int gfs2_unfreeze (struct super_block *sb) +static int gfs2_thaw_super (struct super_block *sb) {struct gfs2_sbd *sdp = sb->s_fs_info;
@@ -1499,8 +1499,8 @@ const struct super_operations gfs2_super_ops = { .evict_inode = gfs2_evict_inode, .put_super = gfs2_put_super, .sync_fs = gfs2_sync_fs, - .freeze_super = gfs2_freeze, - .thaw_super = gfs2_unfreeze, + .freeze_super = gfs2_freeze_super, + .thaw_super = gfs2_thaw_super, .statfs = gfs2_statfs, .drop_inode = gfs2_drop_inode, .show_options = gfs2_show_options,
fs/gfs2/util.c +1 -1
@@ -188,7 +188,7 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp) sdp->sd_jinode_gh.gh_flags |=GL_NOCACHE ;gfs2_glock_dq (&sdp->sd_jinode_gh);if (test_bit (SDF_FS_FROZEN , &sdp->sd_flags)) { -/* Make sure gfs2_unfreeze works if partially-frozen */ +/* Make sure gfs2_thaw_super works if partially-frozen */ flush_work (&sdp->sd_freeze_work);atomic_set (&sdp->sd_freeze_state,SFS_FROZEN );thaw_super (sdp->sd_vfs);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 44/321 gfs2: Rename gfs2_freeze_lock{ => _shared }
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andreas Gruenbacher <[email protected]>
[ Upstream commit e392edd5d52a6742595ecaf8270c1af3e96b9a38 ]
Rename gfs2_freeze_lock to gfs2_freeze_lock_shared to make it a bit more obvious that this function establishes the "thawed" state of the freeze glock.
Stable-dep-of: f66af88e3321 ("gfs2: Stop using gfs2_make_fs_ro for withdraw")
--- fs/gfs2/ops_fstype.c | 4 ++-- fs/gfs2/recovery.c | 2 +- fs/gfs2/super.c | 2 +- fs/gfs2/util.c | 10 +++++----- fs/gfs2/util.h | 5 +++-- 5 files changed, 12 insertions(+), 11 deletions(-)
fs/gfs2/ops_fstype.c +2 -2
@@ -1266,7 +1266,7 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) } } - error =gfs2_freeze_lock (sdp, &freeze_gh,0 ); + error =gfs2_freeze_lock_shared (sdp, &freeze_gh,0 );if (error) goto fail_per_node;
@@ -1587,7 +1587,7 @@ static int gfs2_reconfigure(struct fs_context *fc)if ((sb->s_flags ^ fc->sb_flags) &SB_RDONLY ) {struct gfs2_holder freeze_gh; - error =gfs2_freeze_lock (sdp, &freeze_gh,0 ); + error =gfs2_freeze_lock_shared (sdp, &freeze_gh,0 );if (error)return -EINVAL ;
fs/gfs2/recovery.c +1 -1
@@ -470,7 +470,7 @@ void gfs2_recover_func(struct work_struct *work)/* Acquire a shared hold on the freeze glock */ - error =gfs2_freeze_lock (sdp, &thaw_gh,LM_FLAG_PRIORITY ); + error =gfs2_freeze_lock_shared (sdp, &thaw_gh,LM_FLAG_PRIORITY );if (error) goto fail_gunlock_ji;
fs/gfs2/super.c +1 -1
@@ -662,7 +662,7 @@ void gfs2_freeze_func(struct work_struct *work)struct super_block *sb = sdp->sd_vfs;atomic_inc (&sb->s_active); - error =gfs2_freeze_lock (sdp, &freeze_gh,0 ); + error =gfs2_freeze_lock_shared (sdp, &freeze_gh,0 );if (error) {gfs2_assert_withdraw (sdp,0 ); }else {
fs/gfs2/util.c +5 -5
@@ -93,13 +93,13 @@ int check_journal_clean(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd, }/** -* gfs2_freeze_lock - hold the freeze glock +* gfs2_freeze_lock_shared - hold the freeze glock * @sdp: the superblock * @freeze_gh: pointer to the requested holder * @caller_flags: any additional flags needed by the caller */ -int gfs2_freeze_lock (struct gfs2_sbd *sdp,struct gfs2_holder *freeze_gh, -int caller_flags) +int gfs2_freeze_lock_shared (struct gfs2_sbd *sdp,struct gfs2_holder *freeze_gh, +int caller_flags) {int flags =LM_FLAG_NOEXP |GL_EXACT | caller_flags;int error;
@@ -157,8 +157,8 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp)gfs2_holder_mark_uninitialized (&freeze_gh);if (sdp->sd_freeze_gl && !gfs2_glock_is_locked_by_me (sdp->sd_freeze_gl)) { - ret =gfs2_freeze_lock (sdp, &freeze_gh, - log_write_allowed ?0 :LM_FLAG_TRY ); + ret =gfs2_freeze_lock_shared (sdp, &freeze_gh, + log_write_allowed ?0 :LM_FLAG_TRY );if (ret ==GLR_TRYFAILED ) ret =0 ; }
fs/gfs2/util.h +3 -2
@@ -149,8 +149,9 @@ int gfs2_io_error_i(struct gfs2_sbd *sdp, const char *function,extern int check_journal_clean (struct gfs2_sbd *sdp,struct gfs2_jdesc *jd,bool verbose); -extern int gfs2_freeze_lock (struct gfs2_sbd *sdp, -struct gfs2_holder *freeze_gh,int caller_flags); +extern int gfs2_freeze_lock_shared (struct gfs2_sbd *sdp, +struct gfs2_holder *freeze_gh, +int caller_flags);extern void gfs2_freeze_unlock (struct gfs2_holder *freeze_gh);#define gfs2_io_error (sdp) \
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 45/321 gfs2: Rename SDF_{FS_FROZEN => FREEZE_INITIATOR}
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andreas Gruenbacher <[email protected]>
[ Upstream commit cad1e15804a83afd9a5c1d95a428d60d1f9c0340 ]
Rename the SDF_FS_FROZEN flag to SDF_FREEZE_INITIATOR to indicate more clearly that the node that has this flag set is the initiator of the freeze.
Stable-dep-of: f66af88e3321 ("gfs2: Stop using gfs2_make_fs_ro for withdraw")
--- fs/gfs2/incore.h | 2 +- fs/gfs2/super.c | 8 ++++---- fs/gfs2/sys.c | 2 +- fs/gfs2/util.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-)
fs/gfs2/incore.h +1 -1
@@ -600,7 +600,7 @@ enum {SDF_RORECOVERY =7 ,/* read only recovery */ SDF_SKIP_DLM_UNLOCK =8 ,SDF_FORCE_AIL_FLUSH =9 , -SDF_FS_FROZEN =10 , +SDF_FREEZE_INITIATOR =10 ,SDF_WITHDRAWING =11 ,/* Will withdraw eventually */ SDF_WITHDRAW_IN_PROG =12 ,/* Withdraw is in progress */ SDF_REMOTE_WITHDRAW = 13, /* Performing remote recovery */
fs/gfs2/super.c +4 -4
@@ -676,8 +676,8 @@ void gfs2_freeze_func(struct work_struct *work)gfs2_freeze_unlock (&freeze_gh); }deactivate_super (sb); -clear_bit_unlock (SDF_FS_FROZEN , &sdp->sd_flags); -wake_up_bit (&sdp->sd_flags,SDF_FS_FROZEN ); +clear_bit_unlock (SDF_FREEZE_INITIATOR , &sdp->sd_flags); +wake_up_bit (&sdp->sd_flags,SDF_FREEZE_INITIATOR );return ; }
@@ -720,7 +720,7 @@ static int gfs2_freeze_super(struct super_block *sb)fs_err (sdp,"retrying...\n" );msleep (1000 ); } -set_bit (SDF_FS_FROZEN , &sdp->sd_flags); +set_bit (SDF_FREEZE_INITIATOR , &sdp->sd_flags); out:mutex_unlock (&sdp->sd_freeze_mutex);return error;
@@ -745,7 +745,7 @@ static int gfs2_thaw_super(struct super_block *sb)gfs2_freeze_unlock (&sdp->sd_freeze_gh);mutex_unlock (&sdp->sd_freeze_mutex); -return wait_on_bit (&sdp->sd_flags,SDF_FS_FROZEN ,TASK_INTERRUPTIBLE ); +return wait_on_bit (&sdp->sd_flags,SDF_FREEZE_INITIATOR ,TASK_INTERRUPTIBLE ); }/**
fs/gfs2/sys.c +1 -1
@@ -110,7 +110,7 @@ static ssize_t status_show(struct gfs2_sbd *sdp, char *buf)test_bit (SDF_RORECOVERY , &f),test_bit (SDF_SKIP_DLM_UNLOCK , &f),test_bit (SDF_FORCE_AIL_FLUSH , &f), -test_bit (SDF_FS_FROZEN , &f), +test_bit (SDF_FREEZE_INITIATOR , &f),test_bit (SDF_WITHDRAWING , &f),test_bit (SDF_WITHDRAW_IN_PROG , &f), test_bit(SDF_REMOTE_WITHDRAW, &f),
fs/gfs2/util.c +1 -1
@@ -187,7 +187,7 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp) } sdp->sd_jinode_gh.gh_flags |=GL_NOCACHE ;gfs2_glock_dq (&sdp->sd_jinode_gh); -if (test_bit (SDF_FS_FROZEN , &sdp->sd_flags)) { +if (test_bit (SDF_FREEZE_INITIATOR , &sdp->sd_flags)) {/* Make sure gfs2_thaw_super works if partially-frozen */ flush_work (&sdp->sd_freeze_work);atomic_set (&sdp->sd_freeze_state,SFS_FROZEN );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 46/321 gfs2: Rework freeze / thaw logic
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andreas Gruenbacher <[email protected]>
[ Upstream commit b77b4a4815a9651d1d6e07b8e6548eee9531a5eb ]
So far, at mount time, gfs2 would take the freeze glock in shared mode and then immediately drop it again, turning it into a cached glock that can be reclaimed at any time. To freeze the filesystem cluster-wide, the node initiating the freeze would take the freeze glock in exclusive mode, which would cause the freeze glock's freeze_go_sync() callback to run on each node. There, gfs2 would freeze the filesystem and schedule gfs2_freeze_func() to run. gfs2_freeze_func() would re-acquire the freeze glock in shared mode, thaw the filesystem, and drop the freeze glock again. The initiating node would keep the freeze glock held in exclusive mode. To thaw the filesystem, the initiating node would drop the freeze glock again, which would allow gfs2_freeze_func() to resume on all nodes, leaving the filesystem in the thawed state.
It turns out that in freeze_go_sync(), we cannot reliably and safely freeze the filesystem. This is primarily because the final unmount of a filesystem takes a write lock on the s_umount rw semaphore before calling into gfs2_put_super(), and freeze_go_sync() needs to call freeze_super() which also takes a write lock on the same semaphore, causing a deadlock. We could work around this by trying to take an active reference on the super block first, which would prevent unmount from running at the same time. But that can fail, and freeze_go_sync() isn't actually allowed to fail.
To get around this, this patch changes the freeze glock locking scheme as follows:
At mount time, each node takes the freeze glock in shared mode. To freeze a filesystem, the initiating node first freezes the filesystem locally and then drops and re-acquires the freeze glock in exclusive mode. All other nodes notice that there is contention on the freeze glock in their go_callback callbacks, and they schedule gfs2_freeze_func() to run. There, they freeze the filesystem locally and drop and re-acquire the freeze glock before re-thawing the filesystem. This is happening outside of the glock state engine, so there, we are allowed to fail.
Quoted 1 line
From a cluster point of view, taking and immediately dropping a glock is
indistinguishable from taking the glock and only dropping it upon contention, so this new scheme is compatible with the old one.
Thanks to Li Dong <[email protected]> for reporting a locking bug in gfs2_freeze_func() in a previous version of this commit.
Stable-dep-of: f66af88e3321 ("gfs2: Stop using gfs2_make_fs_ro for withdraw")
--- fs/gfs2/glops.c | 52 +++++-------- fs/gfs2/log.c | 2 - fs/gfs2/ops_fstype.c | 5 +- fs/gfs2/recovery.c | 24 +++--- fs/gfs2/super.c | 172 +++++++++++++++++++++++++++++++++---------- fs/gfs2/super.h | 1 + fs/gfs2/util.c | 32 +++----- 7 files changed, 178 insertions(+), 110 deletions(-)
fs/gfs2/glops.c +19 -33
@@ -555,47 +555,33 @@ static void inode_go_dump(struct seq_file *seq, struct gfs2_glock *gl, }/** -* freeze_go_sync - promote/demote the freeze glock +* freeze_go_callback - A cluster node is requesting a freeze * @gl: the glock +* @remote: true if this came from a different cluster node */ -static int freeze_go_sync (struct gfs2_glock *gl) +static void freeze_go_callback (struct gfs2_glock *gl,bool remote) { -int error =0 ;struct gfs2_sbd *sdp = gl->gl_name.ln_sbd; +struct super_block *sb = sdp->sd_vfs; + +if (!remote || + gl->gl_state !=LM_ST_SHARED || + gl->gl_demote_state !=LM_ST_UNLOCKED ) +return ;/* -* We need to check gl_state == LM_ST_SHARED here and not gl_req == -* LM_ST_EXCLUSIVE. That's because when any node does a freeze, -* all the nodes should have the freeze glock in SH mode and they all -* call do_xmote: One for EX and the others for UN. They ALL must -* freeze locally, and they ALL must queue freeze work. The freeze_work -* calls freeze_func, which tries to reacquire the freeze glock in SH, -* effectively waiting for the thaw on the node who holds it in EX. -* Once thawed, the work func acquires the freeze glock in -* SH and everybody goes back to thawed. +* Try to get an active super block reference to prevent racing with +* unmount (see trylock_super()). But note that unmount isn't the only +* place where a write lock on s_umount is taken, and we can fail here +* because of things like remount as well. */ -if (gl->gl_state ==LM_ST_SHARED && !gfs2_withdrawn (sdp) && - !test_bit (SDF_NORECOVERY , &sdp->sd_flags)) { -atomic_set (&sdp->sd_freeze_state,SFS_STARTING_FREEZE ); - error =freeze_super (sdp->sd_vfs); -if (error) { -fs_info (sdp,"GFS2: couldn't freeze filesystem: %d\n" , - error); -if (gfs2_withdrawn (sdp)) { -atomic_set (&sdp->sd_freeze_state,SFS_UNFROZEN ); -return 0 ; - } -gfs2_assert_withdraw (sdp,0 ); - } -queue_work (gfs2_freeze_wq, &sdp->sd_freeze_work); -if (test_bit (SDF_JOURNAL_LIVE , &sdp->sd_flags)) -gfs2_log_flush (sdp,NULL ,GFS2_LOG_HEAD_FLUSH_FREEZE | -GFS2_LFC_FREEZE_GO_SYNC ); -else /* read-only mounts */ -atomic_set (&sdp->sd_freeze_state,SFS_FROZEN ); +if (down_read_trylock (&sb->s_umount)) { +atomic_inc (&sb->s_active); +up_read (&sb->s_umount); +if (!queue_work (gfs2_freeze_wq, &sdp->sd_freeze_work)) +deactivate_super (sb); } -return 0 ; }/**
@@ -760,9 +746,9 @@ const struct gfs2_glock_operations gfs2_rgrp_glops = { };const struct gfs2_glock_operations gfs2_freeze_glops = { - .go_sync = freeze_go_sync, .go_xmote_bh = freeze_go_xmote_bh, .go_demote_ok = freeze_go_demote_ok, + .go_callback = freeze_go_callback, .go_type =LM_TYPE_NONDISK , .go_flags =GLOF_NONDISK , };
fs/gfs2/log.c +0 -2
@@ -1136,8 +1136,6 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)if (flags & (GFS2_LOG_HEAD_FLUSH_SHUTDOWN |GFS2_LOG_HEAD_FLUSH_FREEZE ))gfs2_log_shutdown (sdp); -if (flags &GFS2_LOG_HEAD_FLUSH_FREEZE ) -atomic_set (&sdp->sd_freeze_state,SFS_FROZEN ); } out_end:
fs/gfs2/ops_fstype.c +2 -3
@@ -1143,7 +1143,6 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc)int silent = fc->sb_flags &SB_SILENT ;struct gfs2_sbd *sdp;struct gfs2_holder mount_gh; -struct gfs2_holder freeze_gh;int error; sdp =init_sbd (sb);
@@ -1266,15 +1265,15 @@ static int gfs2_fill_super(struct super_block *sb, struct fs_context *fc) } } - error =gfs2_freeze_lock_shared (sdp, &freeze_gh,0 ); + error =gfs2_freeze_lock_shared (sdp, &sdp->sd_freeze_gh,0 );if (error) goto fail_per_node;if (!sb_rdonly (sb)) error =gfs2_make_fs_rw (sdp); -gfs2_freeze_unlock (&freeze_gh);if (error) { +gfs2_freeze_unlock (&sdp->sd_freeze_gh);if (sdp->sd_quotad_process)kthread_stop (sdp->sd_quotad_process); sdp->sd_quotad_process =NULL ;
fs/gfs2/recovery.c +12 -12
@@ -404,7 +404,7 @@ void gfs2_recover_func(struct work_struct *work)struct gfs2_inode *ip =GFS2_I (jd->jd_inode);struct gfs2_sbd *sdp =GFS2_SB (jd->jd_inode);struct gfs2_log_header_host head; -struct gfs2_holder j_gh, ji_gh, thaw_gh; +struct gfs2_holder j_gh, ji_gh;ktime_t t_start, t_jlck, t_jhd, t_tlck, t_rep;int ro =0 ;unsigned int pass;
@@ -465,14 +465,14 @@ void gfs2_recover_func(struct work_struct *work) ktime_ms_delta(t_jhd, t_jlck));if (!(head.lh_flags &GFS2_LOG_HEAD_UNMOUNT )) { -fs_info (sdp,"jid=%u: Acquiring the freeze glock...\n" , - jd->jd_jid); - -/* Acquire a shared hold on the freeze glock */ +mutex_lock (&sdp->sd_freeze_mutex); - error =gfs2_freeze_lock_shared (sdp, &thaw_gh,LM_FLAG_PRIORITY ); -if (error) +if (atomic_read (&sdp->sd_freeze_state) !=SFS_UNFROZEN ) { +mutex_unlock (&sdp->sd_freeze_mutex); +fs_warn (sdp,"jid=%u: Can't replay: filesystem " +"is frozen\n" , jd->jd_jid); goto fail_gunlock_ji; + }if (test_bit (SDF_RORECOVERY , &sdp->sd_flags)) { ro =1 ;
@@ -496,7 +496,7 @@ void gfs2_recover_func(struct work_struct *work)fs_warn (sdp,"jid=%u: Can't replay: read-only block " "device\n" , jd->jd_jid); error = -EROFS ; - goto fail_gunlock_thaw; + goto fail_gunlock_nofreeze; } t_tlck =ktime_get ();
@@ -514,7 +514,7 @@ void gfs2_recover_func(struct work_struct *work)lops_after_scan (jd, error, pass);if (error) {up_read (&sdp->sd_log_flush_lock); - goto fail_gunlock_thaw; + goto fail_gunlock_nofreeze; } }
@@ -522,7 +522,7 @@ void gfs2_recover_func(struct work_struct *work)clean_journal (jd, &head);up_read (&sdp->sd_log_flush_lock); -gfs2_freeze_unlock (&thaw_gh); +mutex_unlock (&sdp->sd_freeze_mutex); t_rep =ktime_get (); fs_info(sdp, "jid=%u: Journal replayed in %lldms [jlck:%lldms, " "jhead:%lldms, tlck:%lldms, replay:%lldms]\n",
@@ -543,8 +543,8 @@ void gfs2_recover_func(struct work_struct *work)fs_info (sdp,"jid=%u: Done\n" , jd->jd_jid); goto done; -fail_gunlock_thaw: -gfs2_freeze_unlock (&thaw_gh); +fail_gunlock_nofreeze: +mutex_unlock (&sdp->sd_freeze_mutex); fail_gunlock_ji:if (jlocked) {gfs2_glock_dq_uninit (&ji_gh);
fs/gfs2/super.c +135 -37
244 lines not on this page · raw message
fs/gfs2/super.h +1 -0
@@ -46,6 +46,7 @@ extern void gfs2_statfs_change_out(const struct gfs2_statfs_change_host *sc,extern void update_statfs (struct gfs2_sbd *sdp,struct buffer_head *m_bh);extern int gfs2_statfs_sync (struct super_block *sb,int type);extern void gfs2_freeze_func (struct work_struct *work); +extern void gfs2_thaw_freeze_initiator (struct super_block *sb);extern void free_local_statfs_inodes (struct gfs2_sbd *sdp); extern struct inode *find_local_statfs_inode(struct gfs2_sbd *sdp,
fs/gfs2/util.c +9 -23
@@ -124,7 +124,6 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp)struct gfs2_inode *ip;struct gfs2_glock *i_gl;u64 no_formal_ino; -int log_write_allowed =test_bit (SDF_JOURNAL_LIVE , &sdp->sd_flags);int ret =0 ;int tries;
@@ -152,24 +151,18 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp)*/ clear_bit (SDF_JOURNAL_LIVE , &sdp->sd_flags);if (!sb_rdonly (sdp->sd_vfs)) { -struct gfs2_holder freeze_gh; - -gfs2_holder_mark_uninitialized (&freeze_gh); -if (sdp->sd_freeze_gl && - !gfs2_glock_is_locked_by_me (sdp->sd_freeze_gl)) { - ret =gfs2_freeze_lock_shared (sdp, &freeze_gh, - log_write_allowed ?0 :LM_FLAG_TRY ); -if (ret ==GLR_TRYFAILED ) - ret =0 ; - } -if (!ret) -gfs2_make_fs_ro (sdp); +bool locked =mutex_trylock (&sdp->sd_freeze_mutex); + +gfs2_make_fs_ro (sdp); + +if (locked) +mutex_unlock (&sdp->sd_freeze_mutex); +/* * Dequeue any pending non-system glock holders that can no * longer be granted because the file system is withdrawn. */ gfs2_gl_dq_holders (sdp); -gfs2_freeze_unlock (&freeze_gh); }if (sdp->sd_lockstruct.ls_ops->lm_lock ==NULL ) {/* lock_nolock */
@@ -187,15 +180,8 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp) } sdp->sd_jinode_gh.gh_flags |=GL_NOCACHE ;gfs2_glock_dq (&sdp->sd_jinode_gh); -if (test_bit (SDF_FREEZE_INITIATOR , &sdp->sd_flags)) { -/* Make sure gfs2_thaw_super works if partially-frozen */ -flush_work (&sdp->sd_freeze_work); -atomic_set (&sdp->sd_freeze_state,SFS_FROZEN ); -thaw_super (sdp->sd_vfs); - }else { -wait_on_bit (&i_gl->gl_flags,GLF_DEMOTE , -TASK_UNINTERRUPTIBLE ); - } +gfs2_thaw_freeze_initiator (sdp->sd_vfs); +wait_on_bit (&i_gl->gl_flags,GLF_DEMOTE ,TASK_UNINTERRUPTIBLE );/* * holder_uninit to force glock_put, to force dlm to let go
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 47/321 gfs2: Stop using gfs2_make_fs_ro for withdraw
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andreas Gruenbacher <[email protected]>
[ Upstream commit f66af88e33212b57ea86da2c5d66c0d9d5c46344 ]
[ 81.372851][ T5532] CPU: 1 PID: 5532 Comm: syz-executor.0 Not tainted 6.2.0-rc1-syzkaller-dirty #0 [ 81.382080][ T5532] Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/12/2023 [ 81.392343][ T5532] Call Trace: [ 81.395654][ T5532] <TASK> [ 81.398603][ T5532] dump_stack_lvl+0x1b1/0x290 [ 81.418421][ T5532] gfs2_assert_warn_i+0x19a/0x2e0 [ 81.423480][ T5532] gfs2_quota_cleanup+0x4c6/0x6b0 [ 81.428611][ T5532] gfs2_make_fs_ro+0x517/0x610 [ 81.457802][ T5532] gfs2_withdraw+0x609/0x1540 [ 81.481452][ T5532] gfs2_inode_refresh+0xb2d/0xf60 [ 81.506658][ T5532] gfs2_instantiate+0x15e/0x220 [ 81.511504][ T5532] gfs2_glock_wait+0x1d9/0x2a0 [ 81.516352][ T5532] do_sync+0x485/0xc80 [ 81.554943][ T5532] gfs2_quota_sync+0x3da/0x8b0 [ 81.559738][ T5532] gfs2_sync_fs+0x49/0xb0 [ 81.564063][ T5532] sync_filesystem+0xe8/0x220 [ 81.568740][ T5532] generic_shutdown_super+0x6b/0x310 [ 81.574112][ T5532] kill_block_super+0x79/0xd0 [ 81.578779][ T5532] deactivate_locked_super+0xa7/0xf0 [ 81.584064][ T5532] cleanup_mnt+0x494/0x520 [ 81.593753][ T5532] task_work_run+0x243/0x300 [ 81.608837][ T5532] exit_to_user_mode_loop+0x124/0x150 [ 81.614232][ T5532] exit_to_user_mode_prepare+0xb2/0x140 [ 81.619820][ T5532] syscall_exit_to_user_mode+0x26/0x60 [ 81.625287][ T5532] do_syscall_64+0x49/0xb0 [ 81.629710][ T5532] entry_SYSCALL_64_after_hwframe+0x63/0xcd
In this backtrace, gfs2_quota_sync() takes quota data references and then calls do_sync(). Function do_sync() encounters filesystem corruption and withdraws the filesystem, which (among other things) calls gfs2_quota_cleanup(). Function gfs2_quota_cleanup() wrongly assumes that nobody is holding any quota data references anymore, and destroys all quota data objects. When gfs2_quota_sync() then resumes and dereferences the quota data objects it is holding, those objects are no longer there.
Function gfs2_quota_cleanup() deals with resource deallocation and can easily be delayed until gfs2_put_super() in the case of a filesystem withdraw. In fact, most of the other work gfs2_make_fs_ro() does is unnecessary during a withdraw as well, so change signal_our_withdraw() to skip gfs2_make_fs_ro() and perform the necessary steps directly instead.
Thanks to Edward Adam Davis <[email protected]> for the initial patches.
--- fs/gfs2/super.c | 9 ++------- fs/gfs2/util.c | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 8 deletions(-)
fs/gfs2/super.c +2 -7
@@ -563,15 +563,8 @@ void gfs2_make_fs_ro(struct gfs2_sbd *sdp)gfs2_log_is_empty (sdp), HZ * 5);gfs2_assert_warn (sdp,gfs2_log_is_empty (sdp)); - }else { -wait_event_timeout (sdp->sd_log_waitq, -gfs2_log_is_empty (sdp), -HZ *5 ); }gfs2_quota_cleanup (sdp); - -if (!log_write_allowed) - sdp->sd_vfs->s_flags |=SB_RDONLY ; }/**
@@ -607,6 +600,8 @@ static void gfs2_put_super(struct super_block *sb) }else {gfs2_quota_cleanup (sdp); } +if (gfs2_withdrawn (sdp)) +gfs2_quota_cleanup (sdp);WARN_ON (gfs2_withdrawing (sdp));/* At this point, we're through modifying the disk */
fs/gfs2/util.c +18 -1
@@ -9,6 +9,7 @@#include <linux/spinlock.h> #include <linux/completion.h> #include <linux/buffer_head.h> +#include <linux/kthread.h> #include <linux/crc32.h> #include <linux/gfs2_ondisk.h> #include <linux/delay.h>
@@ -153,7 +154,23 @@ static void signal_our_withdraw(struct gfs2_sbd *sdp)if (!sb_rdonly (sdp->sd_vfs)) {bool locked =mutex_trylock (&sdp->sd_freeze_mutex); -gfs2_make_fs_ro (sdp); +if (sdp->sd_quotad_process && + current != sdp->sd_quotad_process) { +kthread_stop (sdp->sd_quotad_process); + sdp->sd_quotad_process =NULL ; + } + +if (sdp->sd_logd_process && + current != sdp->sd_logd_process) { +kthread_stop (sdp->sd_logd_process); + sdp->sd_logd_process =NULL ; + } + +wait_event_timeout (sdp->sd_log_waitq, +gfs2_log_is_empty (sdp), +HZ *5 ); + + sdp->sd_vfs->s_flags |=SB_RDONLY ;if (locked)mutex_unlock (&sdp->sd_freeze_mutex);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 48/321 Bluetooth: Fix hci_link_tx_to RCU lock usage
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ying Hsu <[email protected]>
[ Upstream commit c7eaf80bfb0c8cef852cce9501b95dd5a6bddcb9 ]
Syzbot found a bug "BUG: sleeping function called from invalid context at kernel/locking/mutex.c:580". It is because hci_link_tx_to holds an RCU read lock and calls hci_disconnect which would hold a mutex lock since the commit a13f316e90fd ("Bluetooth: hci_conn: Consolidate code for aborting connections"). Here's an example call trace:
__dump_stack lib/dump_stack.c:88 [inline] dump_stack_lvl+0xfc/0x174 lib/dump_stack.c:106 ___might_sleep+0x4a9/0x4d3 kernel/sched/core.c:9663 __mutex_lock_common kernel/locking/mutex.c:576 [inline] __mutex_lock+0xc7/0x6e7 kernel/locking/mutex.c:732 hci_cmd_sync_queue+0x3a/0x287 net/bluetooth/hci_sync.c:388 hci_abort_conn+0x2cd/0x2e4 net/bluetooth/hci_conn.c:1812 hci_disconnect+0x207/0x237 net/bluetooth/hci_conn.c:244 hci_link_tx_to net/bluetooth/hci_core.c:3254 [inline] __check_timeout net/bluetooth/hci_core.c:3419 [inline] __check_timeout+0x310/0x361 net/bluetooth/hci_core.c:3399 hci_sched_le net/bluetooth/hci_core.c:3602 [inline] hci_tx_work+0xe8f/0x12d0 net/bluetooth/hci_core.c:3652 process_one_work+0x75c/0xba1 kernel/workqueue.c:2310 worker_thread+0x5b2/0x73a kernel/workqueue.c:2457 kthread+0x2f7/0x30b kernel/kthread.c:319 ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:298
This patch releases RCU read lock before calling hci_disconnect and reacquires it afterward to fix the bug.
--- net/bluetooth/hci_core.c | 5 +++++ 1 file changed, 5 insertions(+)
net/bluetooth/hci_core.c +5 -0
@@ -3419,7 +3419,12 @@ static void hci_link_tx_to(struct hci_dev *hdev, __u8 type)if (c->type == type && c->sent) {bt_dev_err (hdev,"killing stalled connection %pMR" , &c->dst); +/* hci_disconnect might sleep, so, we have to release +* the RCU read lock before calling it. +*/ +rcu_read_unlock ();hci_disconnect (c,HCI_ERROR_REMOTE_USER_TERM ); +rcu_read_lock (); } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 49/321 wifi: mac80211: take wiphy lock for MAC addr change
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit a26787aa13974fb0b3fb42bfeb4256c1b686e305 ]
We want to ensure everything holds the wiphy lock, so also extend that to the MAC change callback.
Stable-dep-of: 74a7c93f45ab ("wifi: mac80211: fix change_address deadlock during unregister")
--- net/mac80211/iface.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
net/mac80211/iface.c +16 -3
@@ -251,9 +251,9 @@ static int ieee80211_can_powered_addr_change(struct ieee80211_sub_if_data *sdatareturn ret; } -static int ieee80211_change_mac (struct net_device *dev,void *addr) +static int _ieee80211_change_mac (struct ieee80211_sub_if_data *sdata, +void *addr) { -struct ieee80211_sub_if_data *sdata =IEEE80211_DEV_TO_SUB_IF (dev);struct ieee80211_local *local = sdata->local;struct sockaddr *sa = addr;bool check_dup = true;
@@ -278,7 +278,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)if (live)drv_remove_interface (local, sdata); - ret =eth_mac_addr (dev, sa); + ret =eth_mac_addr (sdata->dev, sa);if (ret ==0 ) {memcpy (sdata->vif.addr, sa->sa_data,ETH_ALEN );
@@ -294,6 +294,19 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)return ret; } +static int ieee80211_change_mac (struct net_device *dev,void *addr) +{ +struct ieee80211_sub_if_data *sdata =IEEE80211_DEV_TO_SUB_IF (dev); +struct ieee80211_local *local = sdata->local; +int ret; + +wiphy_lock (local->hw.wiphy); + ret =_ieee80211_change_mac (sdata, addr); +wiphy_unlock (local->hw.wiphy); + +return ret; +} +static inline int identical_mac_addr_allowed (int type1,int type2) { return type1 == NL80211_IFTYPE_MONITOR ||
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 50/321 wifi: mac80211: fix change_address deadlock during unregister
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 74a7c93f45abba538914a65dd2ef2ea7cf7150e2 ]
When using e.g. bonding, and doing a sequence such as
# iw wlan0 set type __ap # ip link add name bond1 type bond # ip link set wlan0 master bond1 # iw wlan0 interface del
we deadlock, since the wlan0 interface removal will cause bonding to reset the MAC address of wlan0.
The locking would be somewhat difficult to fix, but since this only happens during removal, we can simply ignore the MAC address change at this time.
--- net/mac80211/iface.c | 8 ++++++++ 1 file changed, 8 insertions(+)
net/mac80211/iface.c +8 -0
@@ -300,6 +300,14 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)struct ieee80211_local *local = sdata->local;int ret; +/* +* This happens during unregistration if there's a bond device +* active (maybe other cases?) and we must get removed from it. +* But we really don't care anymore if it's not registered now. +*/ +if (!dev->ieee80211_ptr->registered) +return 0 ; +wiphy_lock (local->hw.wiphy); ret =_ieee80211_change_mac (sdata, addr);wiphy_unlock (local->hw.wiphy);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 51/321 net: sched: Print msecs when transmit queue time out
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yajun Deng <[email protected]>
[ Upstream commit 2f0f9465ad9fa9c93f30009184c10da0f504f313 ]
The kernel will print several warnings in a short period of time when it stalls. Like this:
First warning:
[ 7100.097547] ------------[ cut here ]------------
[ 7100.097550] NETDEV WATCHDOG: eno2 (xxx): transmit queue 8 timed out
[ 7100.097571] WARNING: CPU: 8 PID: 0 at net/sched/sch_generic.c:467
dev_watchdog+0x260/0x270...
Second warning:
[ 7147.756952] rcu: INFO: rcu_preempt self-detected stall on CPU
[ 7147.756958] rcu: 24-....: (59999 ticks this GP) idle=546/1/0x400000000000000
softirq=367 3137/3673146 fqs=13844
[ 7147.756960] (t=60001 jiffies g=4322709 q=133381)
[ 7147.756962] NMI backtrace for cpu 24...
We calculate that the transmit queue start stall should occur before 7095s according to watchdog_timeo, the rcu start stall at 7087s. These two times are close together, it is difficult to confirm which happened first.
To let users know the exact time the stall started, print msecs when the transmit queue time out.
Stable-dep-of: e316dd1cf135 ("net: don't dump stack on queue timeout")
--- net/sched/sch_generic.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
net/sched/sch_generic.c +5 -5
@@ -502,7 +502,7 @@ static void dev_watchdog(struct timer_list *t)if (netif_device_present (dev) &&netif_running (dev) &&netif_carrier_ok (dev)) { -int some_queue_timedout =0 ; +unsigned int timedout_ms =0 ;unsigned int i;unsigned long trans_start;
@@ -514,16 +514,16 @@ static void dev_watchdog(struct timer_list *t)if (netif_xmit_stopped (txq) &&time_after (jiffies, (trans_start + dev->watchdog_timeo))) { - some_queue_timedout =1 ; + timedout_ms =jiffies_to_msecs (jiffies - trans_start);atomic_long_inc (&txq->trans_timeout);break ; } } -if (unlikely (some_queue_timedout)) { +if (unlikely (timedout_ms)) {trace_net_dev_xmit_timeout (dev, i); -WARN_ONCE (1 ,KERN_INFO "NETDEV WATCHDOG: %s (%s): transmit queue %u timed out\n" , - dev->name,netdev_drivername (dev), i); +WARN_ONCE (1 ,"NETDEV WATCHDOG: %s (%s): transmit queue %u timed out %u ms\n" , + dev->name,netdev_drivername (dev), i, timedout_ms);netif_freeze_queues (dev); dev->netdev_ops->ndo_tx_timeout (dev, i);netif_unfreeze_queues (dev);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 52/321 net: dont dump stack on queue timeout
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jakub Kicinski <[email protected]>
[ Upstream commit e316dd1cf1358ff9c44b37c7be273a7dc4349986 ]
The top syzbot report for networking (#14 for the entire kernel) is the queue timeout splat. We kept it around for a long time, because in real life it provides pretty strong signal that something is wrong with the driver or the device.
Removing it is also likely to break monitoring for those who track it as a kernel warning.
Nevertheless, WARN()ings are best suited for catching kernel programming bugs. If a Tx queue gets starved due to a pause storm, priority configuration, or other weirdness - that's obviously a problem, but not a problem we can fix at the kernel level.
Bite the bullet and convert the WARN() to a print.
Before:
NETDEV WATCHDOG: eni1np1 (netdevsim): transmit queue 0 timed out 1975 ms
WARNING: CPU: 0 PID: 0 at net/sched/sch_generic.c:525 dev_watchdog+0x39e/0x3b0 [... completely pointless stack trace of a timer follows ...]
Now:
netdevsim netdevsim1 eni1np1: NETDEV WATCHDOG: CPU: 0: transmit queue 0 timed out 1769 ms
Alternatively we could mark the drivers which syzbot has learned to abuse as "print-instead-of-WARN" selectively.
--- net/sched/sch_generic.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
net/sched/sch_generic.c +3 -2
@@ -522,8 +522,9 @@ static void dev_watchdog(struct timer_list *t)if (unlikely (timedout_ms)) {trace_net_dev_xmit_timeout (dev, i); -WARN_ONCE (1 ,"NETDEV WATCHDOG: %s (%s): transmit queue %u timed out %u ms\n" , - dev->name,netdev_drivername (dev), i, timedout_ms); +netdev_crit (dev,"NETDEV WATCHDOG: CPU: %d: transmit queue %u timed out %u ms\n" , +raw_smp_processor_id (), + i, timedout_ms);netif_freeze_queues (dev); dev->netdev_ops->ndo_tx_timeout (dev, i);netif_unfreeze_queues (dev);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 53/321 jfs: fix shift-out-of-bounds in dbJoin
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Manas Ghandat <[email protected]>
[ Upstream commit cca974daeb6c43ea971f8ceff5a7080d7d49ee30 ]
Currently while joining the leaf in a buddy system there is shift out of bound error in calculation of BUDSIZE. Added the required check to the BUDSIZE and fixed the documentation as well.
--- fs/jfs/jfs_dmap.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
fs/jfs/jfs_dmap.c +7 -1
@@ -2763,7 +2763,9 @@ static int dbBackSplit(dmtree_t *tp, int leafno, bool is_ctl)* leafno - the number of the leaf to be updated. * newval - the new value for the leaf. * -* RETURN VALUES: none +* RETURN VALUES: +* 0 - success +* -EIO - i/o error */ static int dbJoin (dmtree_t *tp,int leafno,int newval,bool is_ctl) {
@@ -2790,6 +2792,10 @@ static int dbJoin(dmtree_t *tp, int leafno, int newval, bool is_ctl)* get the buddy size (number of words covered) of * the new value. */ + +if ((newval - tp->dmt_budmin) >BUDMIN ) +return -EIO ; + budsz =BUDSIZE (newval, tp->dmt_budmin);/* try to join.
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 54/321 squashfs: squashfs_read_data need to check if the length is 0
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lizhi Xu <[email protected]>
[ Upstream commit eb66b8abae98f869c224f7c852b685ae02144564 ]
When the length passed in is 0, the pagemap_scan_test_walk() caller should bail. This error causes at least a WARN_ON().
--- fs/squashfs/block.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/squashfs/block.c +1 -1
@@ -198,7 +198,7 @@ int squashfs_read_data(struct super_block *sb, u64 index, int length,TRACE ("Block @ 0x%llx, %scompressed size %d\n" , index -2 , compressed ?"" :"un" , length); } -if (length <0 || length > output->length || +if (length <=0 || length > output->length || (index + length) > msblk->bytes_used) { res = -EIO ; goto out;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 55/321 Squashfs: fix variable overflow triggered by sysbot
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phillip Lougher <[email protected]>
[ Upstream commit 12427de9439d68b8e96ba6f50b601ef15f437612 ]
Sysbot reports a slab out of bounds write in squashfs_readahead().
This is ultimately caused by a file reporting an (infeasibly) large file size (1407374883553280 bytes) with the minimum block size of 4K.
This causes variable overflow.
--- fs/squashfs/file.c | 3 ++- fs/squashfs/file_direct.c | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-)
fs/squashfs/file.c +2 -1
@@ -544,7 +544,8 @@ static void squashfs_readahead(struct readahead_control *ractl)struct squashfs_page_actor *actor;unsigned int nr_pages =0 ;struct page **pages; -int i, file_end =i_size_read (inode) >> msblk->block_log; +int i; +loff_t file_end =i_size_read (inode) >> msblk->block_log;unsigned int max_pages =1UL << shift;readahead_expand (ractl, start, (len | mask) +1 );
fs/squashfs/file_direct.c +3 -3
@@ -26,10 +26,10 @@ int squashfs_readpage_block(struct page *target_page, u64 block, int bsize,struct inode *inode = target_page->mapping->host;struct squashfs_sb_info *msblk = inode->i_sb->s_fs_info; -int file_end = (i_size_read (inode) -1 ) >>PAGE_SHIFT ; +loff_t file_end = (i_size_read (inode) -1 ) >>PAGE_SHIFT ;int mask = (1 << (msblk->block_log -PAGE_SHIFT )) -1 ; -int start_index = target_page->index & ~mask; -int end_index = start_index | mask; +loff_t start_index = target_page->index & ~mask; +loff_t end_index = start_index | mask;int i, n, pages, bytes, res = -ENOMEM ;struct page **page;struct squashfs_page_actor *actor;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 56/321 reiserfs: fix uninit-value in comp_keys
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Edward Adam Davis <[email protected]>
[ Upstream commit dd8f87f21dc3da2eaf46e7401173f935b90b13a8 ]
The cpu_key was not initialized in reiserfs_delete_solid_item(), which triggered this issue.
--- fs/reiserfs/stree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/reiserfs/stree.c +1 -1
@@ -1409,7 +1409,7 @@ void reiserfs_delete_solid_item(struct reiserfs_transaction_handle *th,INITIALIZE_PATH (path);int item_len =0 ;int tb_init =0 ; -struct cpu_key cpu_key; +struct cpu_key cpu_key = {};int retval;int quota_cut_bytes =0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 57/321 erofs: avoid debugging output for (de)compressed data
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gao Xiang <[email protected]>
[ Upstream commit 496530c7c1dfc159d59a75ae00b572f570710c53 ]
Syzbot reported a KMSAN warning,
erofs: (device loop0): z_erofs_lz4_decompress_mem: failed to decompress -12 in[46, 4050] out[917]
=====================================================
BUG: KMSAN: uninit-value in hex_dump_to_buffer+0xae9/0x10f0 lib/hexdump.c:194 .. print_hex_dump+0x13d/0x3e0 lib/hexdump.c:276 z_erofs_lz4_decompress_mem fs/erofs/decompressor.c:252 [inline] z_erofs_lz4_decompress+0x257e/0x2a70 fs/erofs/decompressor.c:311 z_erofs_decompress_pcluster fs/erofs/zdata.c:1290 [inline] z_erofs_decompress_queue+0x338c/0x6460 fs/erofs/zdata.c:1372 z_erofs_runqueue+0x36cd/0x3830 z_erofs_read_folio+0x435/0x810 fs/erofs/zdata.c:1843
The root cause is that the printed decompressed buffer may be filled incompletely due to decompression failure. Since they were once only used for debugging, get rid of them now.
--- fs/erofs/decompressor.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
fs/erofs/decompressor.c +1 -7
@@ -248,15 +248,9 @@ static int z_erofs_lz4_decompress_mem(struct z_erofs_lz4_decompress_ctx *ctx,if (ret != rq->outputsize) {erofs_err (rq->sb,"failed to decompress %d in[%u, %u] out[%u]" , ret, rq->inputsize, inputmargin, rq->outputsize); - -print_hex_dump (KERN_DEBUG ,"[ in]: " ,DUMP_PREFIX_OFFSET , -16 ,1 , src + inputmargin, rq->inputsize, true); -print_hex_dump (KERN_DEBUG ,"[out]: " ,DUMP_PREFIX_OFFSET , -16 ,1 , out, rq->outputsize, true); -if (ret >=0 )memset (out + ret,0 , rq->outputsize - ret); - ret = -EIO ; + ret = -EFSCORRUPTED ; }else { ret =0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 58/321 quota: Detect loops in quota tree
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
[ Upstream commit a898cb621ac589b0b9e959309689a027e765aa12 ]
Syzbot has found that when it creates corrupted quota files where the quota tree contains a loop, we will deadlock when tryling to insert a dquot. Add loop detection into functions traversing the quota tree.
--- fs/quota/quota_tree.c | 128 +++++++++++++++++++++++++++++++----------- fs/quota/quota_v2.c | 15 +++-- 2 files changed, 105 insertions(+), 38 deletions(-)
fs/quota/quota_tree.c +96 -32
@@ -21,6 +21,12 @@ MODULE_AUTHOR("Jan Kara");MODULE_DESCRIPTION ("Quota trie support" );MODULE_LICENSE ("GPL" ); +/* +* Maximum quota tree depth we support. Only to limit recursion when working +* with the tree. +*/ +#define MAX_QTREE_DEPTH 6 +#define __QUOTA_QT_PARANOIAstatic int __get_index (struct qtree_mem_dqinfo *info,qid_t id,int depth)
@@ -327,27 +333,36 @@ static uint find_free_dqentry(struct qtree_mem_dqinfo *info,/* Insert reference to structure into the trie */ static int do_insert_tree (struct qtree_mem_dqinfo *info,struct dquot *dquot, -uint *treeblk,int depth) +uint *blks,int depth) {char *buf =kmalloc (info->dqi_usable_bs,GFP_NOFS );int ret =0 , newson =0 , newact =0 ;__le32 *ref;uint newblk; +int i;if (!buf)return -ENOMEM ; -if (!*treeblk) { +if (!blks[depth]) { ret =get_free_dqblk (info);if (ret <0 ) goto out_buf; - *treeblk = ret; +for (i =0 ; i < depth; i++) +if (ret == blks[i]) { +quota_error (dquot->dq_sb, +"Free block already used in tree: block %u" , + ret); + ret = -EIO ; + goto out_buf; + } + blks[depth] = ret;memset (buf,0 , info->dqi_usable_bs); newact =1 ; }else { - ret =read_blk (info, *treeblk, buf); + ret =read_blk (info, blks[depth], buf);if (ret <0 ) {quota_error (dquot->dq_sb,"Can't read tree quota " -"block %u" , *treeblk); +"block %u" , blks[depth]); goto out_buf; } }
@@ -357,8 +372,20 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, info->dqi_blocks - 1);if (ret) goto out_buf; -if (!newblk) +if (!newblk) { newson =1 ; + }else { +for (i =0 ; i <= depth; i++) +if (newblk == blks[i]) { +quota_error (dquot->dq_sb, +"Cycle in quota tree detected: block %u index %u" , + blks[depth], +get_index (info, dquot->dq_id, depth)); + ret = -EIO ; + goto out_buf; + } + } + blks[depth +1 ] = newblk;if (depth == info->dqi_qtree_depth -1 ) {#ifdef __QUOTA_QT_PARANOIAif (newblk) {
@@ -370,16 +397,16 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot, goto out_buf; }#endif - newblk =find_free_dqentry (info, dquot, &ret); + blks[depth +1 ] =find_free_dqentry (info, dquot, &ret); }else { - ret =do_insert_tree (info, dquot, &newblk, depth+1 ); + ret =do_insert_tree (info, dquot, blks, depth +1 ); }if (newson && ret >=0 ) { ref[get_index (info, dquot->dq_id, depth)] = -cpu_to_le32 (newblk); - ret =write_blk (info, *treeblk, buf); +cpu_to_le32 (blks[depth +1 ]); + ret =write_blk (info, blks[depth], buf); }else if (newact && ret <0 ) { -put_free_dqblk (info, buf, *treeblk); +put_free_dqblk (info, buf, blks[depth]); } out_buf:kfree (buf);
@@ -390,7 +417,7 @@ static int do_insert_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,static inline int dq_insert_tree (struct qtree_mem_dqinfo *info,struct dquot *dquot) { -int tmp =QT_TREEOFF ; +uint blks[MAX_QTREE_DEPTH ] = {QT_TREEOFF };#ifdef __QUOTA_QT_PARANOIAif (info->dqi_blocks <=QT_TREEOFF ) {
@@ -398,7 +425,11 @@ static inline int dq_insert_tree(struct qtree_mem_dqinfo *info, return -EIO; }#endif -return do_insert_tree (info, dquot, &tmp,0 ); +if (info->dqi_qtree_depth >=MAX_QTREE_DEPTH ) { +quota_error (dquot->dq_sb,"Quota tree depth too big!" ); +return -EIO ; + } +return do_insert_tree (info, dquot, blks,0 ); }/*
@@ -511,19 +542,20 @@ static int free_dqentry(struct qtree_mem_dqinfo *info, struct dquot *dquot,/* Remove reference to dquot from tree */ static int remove_tree (struct qtree_mem_dqinfo *info,struct dquot *dquot, -uint *blk,int depth) +uint *blks,int depth) {char *buf =kmalloc (info->dqi_usable_bs,GFP_NOFS );int ret =0 ;uint newblk;__le32 *ref = (__le32 *)buf; +int i;if (!buf)return -ENOMEM ; - ret =read_blk (info, *blk, buf); + ret =read_blk (info, blks[depth], buf);if (ret <0 ) {quota_error (dquot->dq_sb,"Can't read quota data block %u" , - *blk); + blks[depth]); goto out_buf; } newblk =le32_to_cpu (ref[get_index (info, dquot->dq_id, depth)]);
@@ -532,29 +564,38 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,if (ret) goto out_buf; +for (i =0 ; i <= depth; i++) +if (newblk == blks[i]) { +quota_error (dquot->dq_sb, +"Cycle in quota tree detected: block %u index %u" , + blks[depth], +get_index (info, dquot->dq_id, depth)); + ret = -EIO ; + goto out_buf; + }if (depth == info->dqi_qtree_depth -1 ) { ret =free_dqentry (info, dquot, newblk); - newblk =0 ; + blks[depth +1 ] =0 ; }else { - ret =remove_tree (info, dquot, &newblk, depth+1 ); + blks[depth +1 ] = newblk; + ret =remove_tree (info, dquot, blks, depth +1 ); } -if (ret >=0 && !newblk) { -int i; +if (ret >=0 && !blks[depth +1 ]) { ref[get_index (info, dquot->dq_id, depth)] =cpu_to_le32 (0 );/* Block got empty? */ for (i =0 ; i < (info->dqi_usable_bs >>2 ) && !ref[i]; i++) ;/* Don't put the root block into the free block list */ if (i == (info->dqi_usable_bs >>2 ) - && *blk !=QT_TREEOFF ) { -put_free_dqblk (info, buf, *blk); - *blk =0 ; + && blks[depth] !=QT_TREEOFF ) { +put_free_dqblk (info, buf, blks[depth]); + blks[depth] =0 ; }else { - ret =write_blk (info, *blk, buf); + ret =write_blk (info, blks[depth], buf);if (ret <0 )quota_error (dquot->dq_sb,"Can't write quota tree block %u" , - *blk); + blks[depth]); } } out_buf:
@@ -565,11 +606,15 @@ static int remove_tree(struct qtree_mem_dqinfo *info, struct dquot *dquot,/* Delete dquot from tree */ int qtree_delete_dquot (struct qtree_mem_dqinfo *info,struct dquot *dquot) { -uint tmp =QT_TREEOFF ; +uint blks[MAX_QTREE_DEPTH ] = {QT_TREEOFF };if (!dquot->dq_off)/* Even not allocated? */ return 0 ; -return remove_tree (info, dquot, &tmp,0 ); +if (info->dqi_qtree_depth >=MAX_QTREE_DEPTH ) { +quota_error (dquot->dq_sb,"Quota tree depth too big!" ); +return -EIO ; + } +return remove_tree (info, dquot, blks,0 ); }EXPORT_SYMBOL (qtree_delete_dquot);
@@ -613,18 +658,20 @@ static loff_t find_block_dqentry(struct qtree_mem_dqinfo *info,/* Find entry for given id in the tree */ static loff_t find_tree_dqentry (struct qtree_mem_dqinfo *info, -struct dquot *dquot,uint blk,int depth) +struct dquot *dquot,uint *blks,int depth) {char *buf =kmalloc (info->dqi_usable_bs,GFP_NOFS );loff_t ret =0 ;__le32 *ref = (__le32 *)buf; +uint blk; +int i;if (!buf)return -ENOMEM ; - ret =read_blk (info, blk, buf); + ret =read_blk (info, blks[depth], buf);if (ret <0 ) {quota_error (dquot->dq_sb,"Can't read quota tree block %u" , - blk); + blks[depth]); goto out_buf; } ret =0 ;
@@ -636,8 +683,19 @@ static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info,if (ret) goto out_buf; +/* Check for cycles in the tree */ +for (i =0 ; i <= depth; i++) +if (blk == blks[i]) { +quota_error (dquot->dq_sb, +"Cycle in quota tree detected: block %u index %u" , + blks[depth], +get_index (info, dquot->dq_id, depth)); + ret = -EIO ; + goto out_buf; + } + blks[depth +1 ] = blk;if (depth < info->dqi_qtree_depth -1 ) - ret =find_tree_dqentry (info, dquot, blk, depth+1 ); + ret =find_tree_dqentry (info, dquot, blks, depth +1 );else ret =find_block_dqentry (info, dquot, blk); out_buf:
@@ -649,7 +707,13 @@ static loff_t find_tree_dqentry(struct qtree_mem_dqinfo *info,static inline loff_t find_dqentry (struct qtree_mem_dqinfo *info,struct dquot *dquot) { -return find_tree_dqentry (info, dquot,QT_TREEOFF ,0 ); +uint blks[MAX_QTREE_DEPTH ] = {QT_TREEOFF }; + +if (info->dqi_qtree_depth >=MAX_QTREE_DEPTH ) { +quota_error (dquot->dq_sb,"Quota tree depth too big!" ); +return -EIO ; + } +return find_tree_dqentry (info, dquot, blks,0 ); }int qtree_read_dquot (struct qtree_mem_dqinfo *info,struct dquot *dquot)
fs/quota/quota_v2.c +9 -6
@@ -166,14 +166,17 @@ static int v2_read_file_info(struct super_block *sb, int type) i_size_read(sb_dqopt(sb)->files[type])); goto out_free; } -if (qinfo->dqi_free_blk >= qinfo->dqi_blocks) { -quota_error (sb,"Free block number too big (%u >= %u)." , - qinfo->dqi_free_blk, qinfo->dqi_blocks); +if (qinfo->dqi_free_blk && (qinfo->dqi_free_blk <=QT_TREEOFF || + qinfo->dqi_free_blk >= qinfo->dqi_blocks)) { +quota_error (sb,"Free block number %u out of range (%u, %u)." , + qinfo->dqi_free_blk,QT_TREEOFF , qinfo->dqi_blocks); goto out_free; } -if (qinfo->dqi_free_entry >= qinfo->dqi_blocks) { -quota_error (sb,"Block with free entry too big (%u >= %u)." , - qinfo->dqi_free_entry, qinfo->dqi_blocks); +if (qinfo->dqi_free_entry && (qinfo->dqi_free_entry <=QT_TREEOFF || + qinfo->dqi_free_entry >= qinfo->dqi_blocks)) { +quota_error (sb,"Block with free entry %u out of range (%u, %u)." , + qinfo->dqi_free_entry,QT_TREEOFF , + qinfo->dqi_blocks); goto out_free; } ret =0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 59/321 net:rds: Fix possible deadlock in rds_message_put
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Allison Henderson <[email protected]>
[ Upstream commit f1acf1ac84d2ae97b7889b87223c1064df850069 ]
Functions rds_still_queued and rds_clear_recv_queue lock a given socket in order to safely iterate over the incoming rds messages. However calling rds_inc_put while under this lock creates a potential deadlock. rds_inc_put may eventually call rds_message_purge, which will lock m_rs_lock. This is the incorrect locking order since m_rs_lock is meant to be locked before the socket. To fix this, we move the message item to a local list or variable that wont need rs_recv_lock protection. Then we can safely call rds_inc_put on any item stored locally after rs_recv_lock is released.
--- net/rds/recv.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
net/rds/recv.c +11 -2
@@ -424,6 +424,7 @@ static int rds_still_queued(struct rds_sock *rs, struct rds_incoming *inc,struct sock *sk =rds_rs_to_sk (rs);int ret =0 ;unsigned long flags; +struct rds_incoming *to_drop =NULL ;write_lock_irqsave (&rs->rs_recv_lock, flags);if (!list_empty (&inc->i_item)) {
@@ -434,11 +435,14 @@ static int rds_still_queued(struct rds_sock *rs, struct rds_incoming *inc, -be32_to_cpu (inc->i_hdr.h_len), inc->i_hdr.h_dport);list_del_init (&inc->i_item); -rds_inc_put (inc); + to_drop = inc; } }write_unlock_irqrestore (&rs->rs_recv_lock, flags); +if (to_drop) +rds_inc_put (to_drop); +rdsdebug ("inc %p rs %p still %d dropped %d\n" , inc, rs, ret, drop);return ret; }
@@ -757,16 +761,21 @@ void rds_clear_recv_queue(struct rds_sock *rs)struct sock *sk =rds_rs_to_sk (rs);struct rds_incoming *inc, *tmp;unsigned long flags; +LIST_HEAD (to_drop);write_lock_irqsave (&rs->rs_recv_lock, flags);list_for_each_entry_safe (inc, tmp, &rs->rs_recv_queue, i_item) {rds_recv_rcvbuf_delta (rs, sk, inc->i_conn->c_lcong, -be32_to_cpu (inc->i_hdr.h_len), inc->i_hdr.h_dport); +list_move (&inc->i_item, &to_drop); + } +write_unlock_irqrestore (&rs->rs_recv_lock, flags); + +list_for_each_entry_safe (inc, tmp, &to_drop, i_item) {list_del_init (&inc->i_item);rds_inc_put (inc); } -write_unlock_irqrestore (&rs->rs_recv_lock, flags); }/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 60/321 net: sctp: fix skb leak in sctp_inq_free()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Antipov <[email protected]>
[ Upstream commit 4e45170d9acc2d5ae8f545bf3f2f67504a361338 ]
In case of GSO, 'chunk->skb' pointer may point to an entry from fraglist created in 'sctp_packet_gso_append()'. To avoid freeing random fraglist entry (and so undefined behavior and/or memory leak), introduce 'sctp_inq_chunk_free()' helper to ensure that 'chunk->skb' is set to 'chunk->head_skb' (i.e. fraglist head) before calling 'sctp_chunk_free()', and use the aforementioned helper in 'sctp_inq_pop()' as well.
--- net/sctp/inqueue.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
net/sctp/inqueue.c +10 -4
@@ -38,6 +38,14 @@ void sctp_inq_init(struct sctp_inq *queue)INIT_WORK (&queue->immediate,NULL ); } +/* Properly release the chunk which is being worked on. */ +static inline void sctp_inq_chunk_free (struct sctp_chunk *chunk) +{ +if (chunk->head_skb) + chunk->skb = chunk->head_skb; +sctp_chunk_free (chunk); +} +/* Release the memory associated with an SCTP inqueue. */ void sctp_inq_free (struct sctp_inq *queue) {
@@ -53,7 +61,7 @@ void sctp_inq_free(struct sctp_inq *queue)* free it as well. */ if (queue->in_progress) { -sctp_chunk_free (queue->in_progress); +sctp_inq_chunk_free (queue->in_progress); queue->in_progress =NULL ; } }
@@ -130,9 +138,7 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) goto new_skb; } -if (chunk->head_skb) - chunk->skb = chunk->head_skb; -sctp_chunk_free (chunk); +sctp_inq_chunk_free (chunk); chunk = queue->in_progress =NULL ; }else {/* Nothing to do. Next chunk in the packet, please. */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 61/321 pppoe: Fix memory leak in pppoe_sendmsg()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gavrilov Ilia <[email protected]>
[ Upstream commit dc34ebd5c018b0edf47f39d11083ad8312733034 ]
syzbot reports a memory leak in pppoe_sendmsg [1].
The problem is in the pppoe_recvmsg() function that handles errors in the wrong order. For the skb_recv_datagram() function, check the pointer to skb for NULL first, and then check the 'error' variable, because the skb_recv_datagram() function can set 'error'
to -EAGAIN in a loop but return a correct pointer to socket buffer after a number of attempts, though 'error' remains set to -EAGAIN.
skb_recv_datagram
__skb_recv_datagram // Loop. if (err == -EAGAIN) then
// go to the next loop iteration
__skb_try_recv_datagram // if (skb != NULL) then return 'skb'
// else if a signal is received then
// return -EAGAINFound by InfoTeCS on behalf of Linux Verification Center (linuxtesting.org) with Syzkaller.
--- drivers/net/ppp/pppoe.c | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-)
drivers/net/ppp/pppoe.c +9 -14
@@ -1007,26 +1007,21 @@ static int pppoe_recvmsg(struct socket *sock, struct msghdr *m,struct sk_buff *skb;int error =0 ; -if (sk->sk_state &PPPOX_BOUND ) { - error = -EIO ; - goto end; - } +if (sk->sk_state &PPPOX_BOUND ) +return -EIO ; skb =skb_recv_datagram (sk, flags, &error); -if (error <0 ) - goto end; +if (!skb) +return error; -if (skb) { - total_len =min_t (size_t, total_len, skb->len); - error =skb_copy_datagram_msg (skb,0 , m, total_len); -if (error ==0 ) { -consume_skb (skb); -return total_len; - } + total_len =min_t (size_t, total_len, skb->len); + error =skb_copy_datagram_msg (skb,0 , m, total_len); +if (error ==0 ) { +consume_skb (skb); +return total_len; }kfree_skb (skb); -end:return error; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 62/321 wifi: mac80211: fix and simplify unencrypted drop check for mesh
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit 94b9b9de05b62ac54d8766caa9865fb4d82cc47e ]
ieee80211_drop_unencrypted is called from ieee80211_rx_h_mesh_fwding and ieee80211_frame_allowed.
Since ieee80211_rx_h_mesh_fwding can forward packets for other mesh nodes and is called earlier, it needs to check the decryptions status and if the packet is using the control protocol on its own, instead of deferring to the later call from ieee80211_frame_allowed.
Because of that, ieee80211_drop_unencrypted has a mesh specific check that skips over the mesh header in order to check the payload protocol. This code is invalid when called from ieee80211_frame_allowed, since that happens after the 802.11->802.3 conversion.
Fix this by moving the mesh specific check directly into ieee80211_rx_h_mesh_fwding.
Stable-dep-of: 9ad797485692 ("wifi: cfg80211: check A-MSDU format more carefully")
--- net/mac80211/rx.c | 38 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 28 deletions(-)
net/mac80211/rx.c +10 -28
@@ -2408,7 +2408,6 @@ static int ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)static int ieee80211_drop_unencrypted (struct ieee80211_rx_data *rx,__le16 fc) { -struct ieee80211_hdr *hdr = (void *)rx->skb->data;struct sk_buff *skb = rx->skb;struct ieee80211_rx_status *status =IEEE80211_SKB_RXCB (skb);
@@ -2419,31 +2418,6 @@ static int ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)if (status->flag &RX_FLAG_DECRYPTED )return 0 ; -/* check mesh EAPOL frames first */ -if (unlikely (rx->sta &&ieee80211_vif_is_mesh (&rx->sdata->vif) && -ieee80211_is_data (fc))) { -struct ieee80211s_hdr *mesh_hdr; -u16 hdr_len =ieee80211_hdrlen (fc); -u16 ethertype_offset; -__be16 ethertype; - -if (!ether_addr_equal (hdr->addr1, rx->sdata->vif.addr)) - goto drop_check; - -/* make sure fixed part of mesh header is there, also checks skb len */ -if (!pskb_may_pull (rx->skb, hdr_len +6 )) - goto drop_check; - - mesh_hdr = (struct ieee80211s_hdr *)(skb->data + hdr_len); - ethertype_offset = hdr_len +ieee80211_get_mesh_hdrlen (mesh_hdr) + -sizeof (rfc1042_header); - -if (skb_copy_bits (rx->skb, ethertype_offset, ðertype,2 ) ==0 && - ethertype == rx->sdata->control_port_protocol) -return 0 ; - } - -drop_check:/* Drop unencrypted frames if key is set. */ if (unlikely(!ieee80211_has_protected(fc) && !ieee80211_is_any_nullfunc(fc) &&
@@ -2897,8 +2871,16 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx) hdr = (struct ieee80211_hdr *) skb->data; mesh_hdr = (struct ieee80211s_hdr *) (skb->data + hdrlen); -if (ieee80211_drop_unencrypted (rx, hdr->frame_control)) -return RX_DROP_MONITOR ; +if (ieee80211_drop_unencrypted (rx, hdr->frame_control)) { +int offset = hdrlen +ieee80211_get_mesh_hdrlen (mesh_hdr) + +sizeof (rfc1042_header); +__be16 ethertype; + +if (!ether_addr_equal (hdr->addr1, rx->sdata->vif.addr) || +skb_copy_bits (rx->skb, offset, ðertype,2 ) !=0 || + ethertype != rx->sdata->control_port_protocol) +return RX_DROP_MONITOR ; + }/* frame is in RMC, don't forward */ if (ieee80211_is_data(hdr->frame_control) &&
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 63/321 wifi: cfg80211: move A-MSDU check in ieee80211_data_to_8023_exthdr
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit 0f690e6b4dcd7243e2805a76981b252c2d4bdce6 ]
When parsing the outer A-MSDU header, don't check for inner bridge tunnel or RFC1042 headers. This is handled by ieee80211_amsdu_to_8023s already.
Stable-dep-of: 9ad797485692 ("wifi: cfg80211: check A-MSDU format more carefully")
--- net/wireless/util.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
net/wireless/util.c +3 -2
@@ -631,8 +631,9 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,break ; } -if (likely (skb_copy_bits (skb, hdrlen, &payload,sizeof (payload)) ==0 && - ((!is_amsdu &ðer_addr_equal (payload.hdr, rfc1042_header) && +if (likely (!is_amsdu && +skb_copy_bits (skb, hdrlen, &payload,sizeof (payload)) ==0 && + ((ether_addr_equal (payload.hdr, rfc1042_header) && payload.proto !=htons (ETH_P_AARP ) && payload.proto !=htons (ETH_P_IPX )) ||ether_addr_equal (payload.hdr, bridge_tunnel_header)))) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 64/321 wifi: cfg80211: factor out bridge tunnel / RFC1042 header check
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit 9f718554e7eacea62d3f972cae24d969755bf3b6 ]
The same check is done in multiple places, unify it.
Stable-dep-of: 9ad797485692 ("wifi: cfg80211: check A-MSDU format more carefully")
--- net/wireless/util.c | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-)
net/wireless/util.c +18 -16
@@ -542,6 +542,21 @@ unsigned int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr) }EXPORT_SYMBOL (ieee80211_get_mesh_hdrlen); +static bool ieee80211_get_8023_tunnel_proto (const void *hdr,__be16 *proto) +{ +const __be16 *hdr_proto = hdr +ETH_ALEN ; + +if (!(ether_addr_equal (hdr, rfc1042_header) && + *hdr_proto !=htons (ETH_P_AARP ) && + *hdr_proto !=htons (ETH_P_IPX )) && + !ether_addr_equal (hdr, bridge_tunnel_header)) +return false; + + *proto = *hdr_proto; + +return true; +} +int ieee80211_data_to_8023_exthdr (struct sk_buff *skb,struct ethhdr *ehdr,const u8 *addr,enum nl80211_iftype iftype,u8 data_offset,bool is_amsdu)
@@ -633,14 +648,9 @@ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,if (likely (!is_amsdu &&skb_copy_bits (skb, hdrlen, &payload,sizeof (payload)) ==0 && - ((ether_addr_equal (payload.hdr, rfc1042_header) && - payload.proto !=htons (ETH_P_AARP ) && - payload.proto !=htons (ETH_P_IPX )) || -ether_addr_equal (payload.hdr, bridge_tunnel_header)))) { -/* remove RFC1042 or Bridge-Tunnel encapsulation and -* replace EtherType */ +ieee80211_get_8023_tunnel_proto (&payload, &tmp.h_proto))) { +/* remove RFC1042 or Bridge-Tunnel encapsulation */ hdrlen +=ETH_ALEN +2 ; - tmp.h_proto = payload.proto;skb_postpull_rcsum (skb, &payload,ETH_ALEN +2 ); }else { tmp.h_proto =htons (skb->len - hdrlen);
@@ -756,8 +766,6 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, {unsigned int hlen =ALIGN (extra_headroom,4 );struct sk_buff *frame =NULL ; -u16 ethertype; -u8 *payload;int offset =0 , remaining;struct ethhdr eth;bool reuse_frag = skb->head_frag && !skb_has_frag_list (skb);
@@ -811,14 +819,8 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, frame->dev = skb->dev; frame->priority = skb->priority; - payload = frame->data; - ethertype = (payload[6 ] <<8 ) | payload[7 ]; -if (likely ((ether_addr_equal (payload, rfc1042_header) && - ethertype !=ETH_P_AARP && ethertype !=ETH_P_IPX ) || -ether_addr_equal (payload, bridge_tunnel_header))) { - eth.h_proto =htons (ethertype); +if (likely (ieee80211_get_8023_tunnel_proto (frame->data, ð.h_proto)))skb_pull (frame,ETH_ALEN +2 ); - }memcpy (skb_push (frame,sizeof (eth)), ð,sizeof (eth));__skb_queue_tail (list, frame);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 65/321 wifi: mac80211: remove mesh forwarding congestion check
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit 5c1e269aa5ebafeec69b68ff560522faa5bcb6c1 ]
Now that all drivers use iTXQ, it does not make sense to check to drop tx forwarding packets when the driver has stopped the queues. fq_codel will take care of dropping packets when the queues fill up
Stable-dep-of: 9ad797485692 ("wifi: cfg80211: check A-MSDU format more carefully")
--- net/mac80211/debugfs_netdev.c | 3 --- net/mac80211/ieee80211_i.h | 1 - net/mac80211/rx.c | 5 ----- 3 files changed, 9 deletions(-)
net/mac80211/debugfs_netdev.c +0 -3
@@ -603,8 +603,6 @@ IEEE80211_IF_FILE(fwded_mcast, u.mesh.mshstats.fwded_mcast, DEC);IEEE80211_IF_FILE (fwded_unicast, u.mesh.mshstats.fwded_unicast,DEC );IEEE80211_IF_FILE (fwded_frames, u.mesh.mshstats.fwded_frames,DEC );IEEE80211_IF_FILE (dropped_frames_ttl, u.mesh.mshstats.dropped_frames_ttl,DEC ); -IEEE80211_IF_FILE (dropped_frames_congestion, - u.mesh.mshstats.dropped_frames_congestion,DEC );IEEE80211_IF_FILE (dropped_frames_no_route, u.mesh.mshstats.dropped_frames_no_route,DEC );
@@ -741,7 +739,6 @@ static void add_mesh_stats(struct ieee80211_sub_if_data *sdata)MESHSTATS_ADD (fwded_frames);MESHSTATS_ADD (dropped_frames_ttl);MESHSTATS_ADD (dropped_frames_no_route); -MESHSTATS_ADD (dropped_frames_congestion);#undef MESHSTATS_ADD }
net/mac80211/ieee80211_i.h +0 -1
@@ -327,7 +327,6 @@ struct mesh_stats {__u32 fwded_frames;/* Mesh total forwarded frames */ __u32 dropped_frames_ttl;/* Not transmitted since mesh_ttl == 0*/ __u32 dropped_frames_no_route;/* Not transmitted, no route found */ -__u32 dropped_frames_congestion;/* Not forwarded due to congestion */ };#define PREQ_Q_F_START 0x1
net/mac80211/rx.c +0 -5
@@ -2931,11 +2931,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)return RX_CONTINUE ; ac = ieee802_1d_to_ac[skb->priority]; - q = sdata->vif.hw_queue[ac]; -if (ieee80211_queue_stopped (&local->hw, q)) { -IEEE80211_IFSTA_MESH_CTR_INC (ifmsh, dropped_frames_congestion); -return RX_DROP_MONITOR ; - }skb_set_queue_mapping (skb, ac);if (!--mesh_hdr->ttl) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 66/321 wifi: mac80211: fix receiving A-MSDU frames on mesh interfaces
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit 986e43b19ae9176093da35e0a844e65c8bf9ede7 ]
The current mac80211 mesh A-MSDU receive path fails to parse A-MSDU packets on mesh interfaces, because it assumes that the Mesh Control field is always directly after the 802.11 header.
802.11-2020 9.3.2.2.2 Figure 9-70 shows that the Mesh Control field is actually part of the A-MSDU subframe header.
This makes more sense, since it allows packets for multiple different destinations to be included in the same A-MSDU, as long as RA and TID are still the same.
Another issue is the fact that the A-MSDU subframe length field was apparently accidentally defined as little-endian in the standard.
In order to fix this, the mesh forwarding path needs happen at a different point in the receive path.
ieee80211_data_to_8023_exthdr is changed to ignore the mesh control field and leave it in after the ethernet header. This also affects the source/dest MAC address fields, which now in the case of mesh point to the mesh SA/DA.
ieee80211_amsdu_to_8023s is changed to deal with the endian difference and to add the Mesh Control length to the subframe length, since it's not covered by the MSDU length field.
With these changes, the mac80211 will get the same packet structure for converted regular data packets and unpacked A-MSDU subframes.
The mesh forwarding checks are now only performed after the A-MSDU decap. For locally received packets, the Mesh Control header is stripped away. For forwarded packets, a new 802.11 header gets added.
Stable-dep-of: 9ad797485692 ("wifi: cfg80211: check A-MSDU format more carefully")
--- .../wireless/marvell/mwifiex/11n_rxreorder.c | 2 +- include/net/cfg80211.h | 27 +- net/mac80211/rx.c | 350 ++++++++++-------- net/wireless/util.c | 120 +++--- 4 files changed, 297 insertions(+), 202 deletions(-)
drivers/net/wireless/marvell/mwifiex/11n_rxreorder.c +1 -1
@@ -33,7 +33,7 @@ static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv,skb_trim (skb,le16_to_cpu (local_rx_pd->rx_pkt_length));ieee80211_amsdu_to_8023s (skb, &list, priv->curr_addr, - priv->wdev.iftype,0 ,NULL ,NULL ); + priv->wdev.iftype,0 ,NULL ,NULL , false);while (!skb_queue_empty (&list)) {struct rx_packet_hdr *rx_hdr;
include/net/cfg80211.h +26 -1
@@ -6316,11 +6316,36 @@ static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,* @extra_headroom: The hardware extra headroom for SKBs in the @list. * @check_da: DA to check in the inner ethernet header, or NULL * @check_sa: SA to check in the inner ethernet header, or NULL +* @mesh_control: A-MSDU subframe header includes the mesh control field */ void ieee80211_amsdu_to_8023s (struct sk_buff *skb,struct sk_buff_head *list,const u8 *addr,enum nl80211_iftype iftype,const unsigned int extra_headroom, -const u8 *check_da,const u8 *check_sa); +const u8 *check_da,const u8 *check_sa, +bool mesh_control); + +/** +* ieee80211_get_8023_tunnel_proto - get RFC1042 or bridge tunnel encap protocol +* +* Check for RFC1042 or bridge tunnel header and fetch the encapsulated +* protocol. +* +* @hdr: pointer to the MSDU payload +* @proto: destination pointer to store the protocol +* Return: true if encapsulation was found +*/ +bool ieee80211_get_8023_tunnel_proto (const void *hdr,__be16 *proto); + +/** +* ieee80211_strip_8023_mesh_hdr - strip mesh header from converted 802.3 frames +* +* Strip the mesh header, which was left in by ieee80211_data_to_8023 as part +* of the MSDU data. Also move any source/destination addresses from the mesh +* header to the ethernet header (if present). +* +* @skb: The 802.3 frame with embedded mesh header +*/ +int ieee80211_strip_8023_mesh_hdr (struct sk_buff *skb);/** * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
net/mac80211/rx.c +194 -156
414 lines not on this page · raw message
net/wireless/util.c +76 -44
224 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 67/321 wifi: mac80211: add a workaround for receiving non-standard mesh A-MSDU
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Felix Fietkau <[email protected]>
[ Upstream commit 6e4c0d0460bd32ca9244dff3ba2d2da27235de11 ]
At least ath10k and ath11k supported hardware (maybe more) does not implement mesh A-MSDU aggregation in a standard compliant way.
802.11-2020 9.3.2.2.2 declares that the Mesh Control field is part of the A-MSDU header (and little-endian).
As such, its length must not be included in the subframe length field. Hardware affected by this bug treats the mesh control field as part of the MSDU data and sets the length accordingly.
In order to avoid packet loss, keep track of which stations are affected by this and take it into account when converting A-MSDU to 802.3 + mesh control packets.
Stable-dep-of: 9ad797485692 ("wifi: cfg80211: check A-MSDU format more carefully")
--- include/net/cfg80211.h | 13 +++++++++++++ net/mac80211/rx.c | 15 ++++++++++++--- net/mac80211/sta_info.c | 3 +++ net/mac80211/sta_info.h | 1 + net/wireless/util.c | 32 ++++++++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 3 deletions(-)
include/net/cfg80211.h +13 -0
@@ -6301,6 +6301,19 @@ static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,return ieee80211_data_to_8023_exthdr (skb,NULL , addr, iftype,0 , false); } +/** +* ieee80211_is_valid_amsdu - check if subframe lengths of an A-MSDU are valid +* +* This is used to detect non-standard A-MSDU frames, e.g. the ones generated +* by ath10k and ath11k, where the subframe length includes the length of the +* mesh control field. +* +* @skb: The input A-MSDU frame without any headers. +* @mesh_hdr: use standard compliant mesh A-MSDU subframe header +* Returns: true if subframe header lengths are valid for the @mesh_hdr mode +*/ +bool ieee80211_is_valid_amsdu (struct sk_buff *skb,bool mesh_hdr); +/** * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame *
net/mac80211/rx.c +12 -3
@@ -2904,7 +2904,6 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)static ieee80211_rx_result res;struct ethhdr ethhdr;const u8 *check_da = ethhdr.h_dest, *check_sa = ethhdr.h_source; -bool mesh = false;if (unlikely (ieee80211_has_a4 (hdr->frame_control))) { check_da =NULL ;
@@ -2922,7 +2921,6 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset)case NL80211_IFTYPE_MESH_POINT : check_sa =NULL ; check_da =NULL ; - mesh = true;break ;default :break ;
@@ -2937,10 +2935,21 @@ __ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx, u8 data_offset) data_offset, true))return RX_DROP_UNUSABLE ; +if (rx->sta && rx->sta->amsdu_mesh_control <0 ) { +bool valid_std =ieee80211_is_valid_amsdu (skb, true); +bool valid_nonstd =ieee80211_is_valid_amsdu (skb, false); + +if (valid_std && !valid_nonstd) + rx->sta->amsdu_mesh_control =1 ; +else if (valid_nonstd && !valid_std) + rx->sta->amsdu_mesh_control =0 ; + } +ieee80211_amsdu_to_8023s (skb, &frame_list, dev->dev_addr, rx->sdata->vif.type, rx->local->hw.extra_tx_headroom, - check_da, check_sa, mesh); + check_da, check_sa, + rx->sta->amsdu_mesh_control);while (!skb_queue_empty (&frame_list)) { rx->skb =__skb_dequeue (&frame_list);
net/mac80211/sta_info.c +3 -0
@@ -594,6 +594,9 @@ __sta_info_alloc(struct ieee80211_sub_if_data *sdata, sta->sta_state =IEEE80211_STA_NONE ; +if (sdata->vif.type ==NL80211_IFTYPE_MESH_POINT ) + sta->amsdu_mesh_control =-1 ; +/* Mark TID as unreserved */ sta->reserved_tid =IEEE80211_TID_UNRESERVED ;
net/mac80211/sta_info.h +1 -0
@@ -706,6 +706,7 @@ struct sta_info {struct codel_params cparams;u8 reserved_tid; +s8 amsdu_mesh_control;struct cfg80211_chan_def tdls_chandef;
net/wireless/util.c +32 -0
@@ -776,6 +776,38 @@ __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,return frame; } +bool ieee80211_is_valid_amsdu (struct sk_buff *skb,bool mesh_hdr) +{ +int offset =0 , remaining, subframe_len, padding; + +for (offset =0 ; offset < skb->len; offset += subframe_len + padding) { +struct { +__be16 len; +u8 mesh_flags; + } hdr; +u16 len; + +if (skb_copy_bits (skb, offset +2 *ETH_ALEN , &hdr,sizeof (hdr)) <0 ) +return false; + +if (mesh_hdr) + len =le16_to_cpu (*(__le16 *)&hdr.len) + +__ieee80211_get_mesh_hdrlen (hdr.mesh_flags); +else + len =ntohs (hdr.len); + + subframe_len =sizeof (struct ethhdr ) + len; + padding = (4 - subframe_len) &0x3 ; + remaining = skb->len - offset; + +if (subframe_len > remaining) +return false; + } + +return true; +} +EXPORT_SYMBOL (ieee80211_is_valid_amsdu); + void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, const u8 *addr, enum nl80211_iftype iftype, const unsigned int extra_headroom,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 68/321 wifi: cfg80211: check A-MSDU format more carefully
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 9ad7974856926129f190ffbe3beea78460b3b7cc ]
If it looks like there's another subframe in the A-MSDU but the header isn't fully there, we can end up reading data out of bounds, only to discard later. Make this a bit more careful and check if the subframe header can even be present.
--- net/wireless/util.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
net/wireless/util.c +10 -4
@@ -778,15 +778,19 @@ __ieee80211_amsdu_copy(struct sk_buff *skb, unsigned int hlen,bool ieee80211_is_valid_amsdu (struct sk_buff *skb,bool mesh_hdr) { -int offset =0 , remaining, subframe_len, padding; +int offset =0 , subframe_len, padding;for (offset =0 ; offset < skb->len; offset += subframe_len + padding) { +int remaining = skb->len - offset;struct {__be16 len;u8 mesh_flags; } hdr;u16 len; +if (sizeof (hdr) > remaining) +return false; +if (skb_copy_bits (skb, offset +2 *ETH_ALEN , &hdr,sizeof (hdr)) <0 )return false;
@@ -798,7 +802,6 @@ bool ieee80211_is_valid_amsdu(struct sk_buff *skb, bool mesh_hdr) subframe_len =sizeof (struct ethhdr ) + len; padding = (4 - subframe_len) &0x3 ; - remaining = skb->len - offset;if (subframe_len > remaining)return false;
@@ -816,7 +819,7 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, {unsigned int hlen =ALIGN (extra_headroom,4 );struct sk_buff *frame =NULL ; -int offset =0 , remaining; +int offset =0 ;struct {struct ethhdr eth;uint8_t flags;
@@ -830,10 +833,14 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, copy_len =sizeof (hdr);while (!last) { +int remaining = skb->len - offset;unsigned int subframe_len;int len, mesh_len =0 ;u8 padding; +if (copy_len > remaining) + goto purge; +skb_copy_bits (skb, offset, &hdr, copy_len);if (iftype ==NL80211_IFTYPE_MESH_POINT ) mesh_len =__ieee80211_get_mesh_hdrlen (hdr.flags);
@@ -846,7 +853,6 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list, padding = (4 - subframe_len) &0x3 ;/* the last MSDU has no padding */ - remaining = skb->len - offset;if (subframe_len > remaining) goto purge;/* mitigate A-MSDU aggregation injection attacks */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 69/321 docs/bpf: Document BPF_MAP_TYPE_LPM_TRIE map
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Donald Hunter <[email protected]>
[ Upstream commit 83177c0dca3811faa051124731a692609caee7c7 ]
Add documentation for BPF_MAP_TYPE_LPM_TRIE including kernel BPF helper usage, userspace usage and examples.
Stable-dep-of: 59f2f841179a ("bpf: Avoid kfree_rcu() under lock in bpf_lpm_trie.")
--- Documentation/bpf/map_lpm_trie.rst | 181 +++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 Documentation/bpf/map_lpm_trie.rst
Documentation/bpf/map_lpm_trie.rst new file +181 -0
@@ -0,0 +1,181 @@ +.. SPDX-License-Identifier: GPL-2.0-only +.. Copyright (C) 2022 Red Hat, Inc. + +===================== +BPF_MAP_TYPE_LPM_TRIE +===================== + +.. note:: + - ``BPF_MAP_TYPE_LPM_TRIE`` was introduced in kernel version 4.11 + +``BPF_MAP_TYPE_LPM_TRIE`` provides a longest prefix match algorithm that +can be used to match IP addresses to a stored set of prefixes. +Internally, data is stored in an unbalanced trie of nodes that uses +``prefixlen,data`` pairs as its keys. The ``data`` is interpreted in +network byte order, i.e. big endian, so ``data[0]`` stores the most +significant byte. + +LPM tries may be created with a maximum prefix length that is a multiple +of 8, in the range from 8 to 2048. The key used for lookup and update +operations is a ``struct bpf_lpm_trie_key``, extended by +``max_prefixlen/8`` bytes. + +- For IPv4 addresses the data length is 4 bytes +- For IPv6 addresses the data length is 16 bytes + +The value type stored in the LPM trie can be any user defined type. + +.. note:: + When creating a map of type ``BPF_MAP_TYPE_LPM_TRIE`` you must set the + ``BPF_F_NO_PREALLOC`` flag. + +Usage +===== + +Kernel BPF +---------- + +.. c:function:: + void *bpf_map_lookup_elem(struct bpf_map *map, const void *key) + +The longest prefix entry for a given data value can be found using the +``bpf_map_lookup_elem()`` helper. This helper returns a pointer to the +value associated with the longest matching ``key``, or ``NULL`` if no +entry was found. + +The ``key`` should have ``prefixlen`` set to ``max_prefixlen`` when +performing longest prefix lookups. For example, when searching for the +longest prefix match for an IPv4 address, ``prefixlen`` should be set to +``32``. + +.. c:function:: + long bpf_map_update_elem(struct bpf_map *map, const void *key, const void *value, u64 flags) + +Prefix entries can be added or updated using the ``bpf_map_update_elem()`` +helper. This helper replaces existing elements atomically. + +``bpf_map_update_elem()`` returns ``0`` on success, or negative error in +case of failure. + + .. note:: + The flags parameter must be one of BPF_ANY, BPF_NOEXIST or BPF_EXIST, + but the value is ignored, giving BPF_ANY semantics. + +.. c:function:: + long bpf_map_delete_elem(struct bpf_map *map, const void *key) + +Prefix entries can be deleted using the ``bpf_map_delete_elem()`` +helper. This helper will return 0 on success, or negative error in case +of failure. + +Userspace +--------- + +Access from userspace uses libbpf APIs with the same names as above, with +the map identified by ``fd``. + +.. c:function:: + int bpf_map_get_next_key (int fd, const void *cur_key, void *next_key) + +A userspace program can iterate through the entries in an LPM trie using +libbpf's ``bpf_map_get_next_key()`` function. The first key can be +fetched by calling ``bpf_map_get_next_key()`` with ``cur_key`` set to +``NULL``. Subsequent calls will fetch the next key that follows the +current key. ``bpf_map_get_next_key()`` returns ``0`` on success, +``-ENOENT`` if ``cur_key`` is the last key in the trie, or negative +error in case of failure. + +``bpf_map_get_next_key()`` will iterate through the LPM trie elements +from leftmost leaf first. This means that iteration will return more +specific keys before less specific ones. + +Examples +======== + +Please see ``tools/testing/selftests/bpf/test_lpm_map.c`` for examples +of LPM trie usage from userspace. The code snippets below demonstrate +API usage. + +Kernel BPF +---------- + +The following BPF code snippet shows how to declare a new LPM trie for IPv4 +address prefixes: + +.. code-block:: c + + #include <linux/bpf.h> + #include <bpf/bpf_helpers.h> + + struct ipv4_lpm_key { + __u32 prefixlen; + __u32 data; + }; + + struct { + __uint(type, BPF_MAP_TYPE_LPM_TRIE); + __type(key, struct ipv4_lpm_key); + __type(value, __u32); + __uint(map_flags, BPF_F_NO_PREALLOC); + __uint(max_entries, 255); + } ipv4_lpm_map SEC(".maps"); + +The following BPF code snippet shows how to lookup by IPv4 address: + +.. code-block:: c + + void *lookup(__u32 ipaddr) + { + struct ipv4_lpm_key key = { + .prefixlen = 32, + .data = ipaddr + }; + + return bpf_map_lookup_elem(&ipv4_lpm_map, &key); + } + +Userspace +--------- + +The following snippet shows how to insert an IPv4 prefix entry into an +LPM trie: + +.. code-block:: c + + int add_prefix_entry(int lpm_fd, __u32 addr, __u32 prefixlen, struct value *value) + { + struct ipv4_lpm_key ipv4_key = { + .prefixlen = prefixlen, + .data = addr + }; + return bpf_map_update_elem(lpm_fd, &ipv4_key, value, BPF_ANY); + } + +The following snippet shows a userspace program walking through the entries +of an LPM trie: + + +.. code-block:: c + + #include <bpf/libbpf.h> + #include <bpf/bpf.h> + + void iterate_lpm_trie(int map_fd) + { + struct ipv4_lpm_key *cur_key = NULL; + struct ipv4_lpm_key next_key; + struct value value; + int err; + + for (;;) { + err = bpf_map_get_next_key(map_fd, cur_key, &next_key); + if (err) + break; + + bpf_map_lookup_elem(map_fd, &next_key, &value); + + /* Use key and value here */ + + cur_key = &next_key; + } + }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 70/321 bpf: Replace bpf_lpm_trie_key 0-length array with flexible array
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kees Cook <[email protected]>
[ Upstream commit 896880ff30866f386ebed14ab81ce1ad3710cfc4 ]
Replace deprecated 0-length array in struct bpf_lpm_trie_key with flexible array. Found with GCC 13:
../kernel/bpf/lpm_trie.c:207:51: warning: array subscript i is outside array bounds of 'const __u8[0]' {aka 'const unsigned char[]'} [-Warray-bounds=]
207 | *(__be16 *)&key->data[i]);
| ^~~~~~~~~~~~~../include/uapi/linux/swab.h:102:54: note: in definition of macro '__swab16'
102 | #define __swab16(x) (__u16)__builtin_bswap16((__u16)(x))
| ^../include/linux/byteorder/generic.h:97:21: note: in expansion of macro '__be16_to_cpu'
97 | #define be16_to_cpu __be16_to_cpu
| ^~~~~~~~~~~~~
../kernel/bpf/lpm_trie.c:206:28: note: in expansion of macro 'be16_to_cpu'
206 | u16 diff = be16_to_cpu(*(__be16 *)&node->data[i]
^
| ^~~~~~~~~~~
In file included from ../include/linux/bpf.h:7:
../include/uapi/linux/bpf.h:82:17: note: while referencing 'data'
82 | __u8 data[0]; /* Arbitrary size */
| ^~~~And found at run-time under CONFIG_FORTIFY_SOURCE:
UBSAN: array-index-out-of-bounds in kernel/bpf/lpm_trie.c:218:49 index 0 is out of range for type '__u8 [*]'
Changing struct bpf_lpm_trie_key is difficult since has been used by userspace. For example, in Cilium:
struct egress_gw_policy_key {
struct bpf_lpm_trie_key lpm_key;
__u32 saddr;
__u32 daddr;
};While direct references to the "data" member haven't been found, there are static initializers what include the final member. For example, the "{}" here:
struct egress_gw_policy_key in_key = {
.lpm_key = { 32 + 24, {} },
.saddr = CLIENT_IP,
.daddr = EXTERNAL_SVC_IP & 0Xffffff,
};To avoid the build time and run time warnings seen with a 0-sized trailing array for struct bpf_lpm_trie_key, introduce a new struct that correctly uses a flexible array for the trailing bytes, struct bpf_lpm_trie_key_u8. As part of this, include the "header" portion (which is just the "prefixlen" member), so it can be used by anything building a bpf_lpr_trie_key that has trailing members that aren't a u8 flexible array (like the self-test[1]), which is named struct bpf_lpm_trie_key_hdr.
Unfortunately, C++ refuses to parse the __struct_group() helper, so it is not possible to define struct bpf_lpm_trie_key_hdr directly in struct bpf_lpm_trie_key_u8, so we must open-code the union directly.
Adjust the kernel code to use struct bpf_lpm_trie_key_u8 through-out, and for the selftest to use struct bpf_lpm_trie_key_hdr. Add a comment to the UAPI header directing folks to the two new options.
Stable-dep-of: 59f2f841179a ("bpf: Avoid kfree_rcu() under lock in bpf_lpm_trie.")
--- Documentation/bpf/map_lpm_trie.rst | 2 +- include/uapi/linux/bpf.h | 19 +++++++++++++++++- kernel/bpf/lpm_trie.c | 20 +++++++++---------- samples/bpf/map_perf_test_user.c | 2 +- samples/bpf/xdp_router_ipv4_user.c | 2 +- tools/include/uapi/linux/bpf.h | 19 +++++++++++++++++- .../selftests/bpf/progs/map_ptr_kern.c | 2 +- tools/testing/selftests/bpf/test_lpm_map.c | 18 ++++++++--------- 8 files changed, 59 insertions(+), 25 deletions(-)
Documentation/bpf/map_lpm_trie.rst +1 -1
@@ -17,7 +17,7 @@ significant byte. LPM tries may be created with a maximum prefix length that is a multiple of 8, in the range from 8 to 2048. The key used for lookup and update -operations is a ``struct bpf_lpm_trie_key``, extended by +operations is a ``struct bpf_lpm_trie_key_u8``, extended by ``max_prefixlen/8`` bytes. - For IPv4 addresses the data length is 4 bytes
include/uapi/linux/bpf.h +18 -1
@@ -76,12 +76,29 @@ struct bpf_insn {__s32 imm;/* signed immediate constant */ }; -/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */ +/* Deprecated: use struct bpf_lpm_trie_key_u8 (when the "data" member is needed for +* byte access) or struct bpf_lpm_trie_key_hdr (when using an alternative type for +* the trailing flexible array member) instead. +*/ struct bpf_lpm_trie_key {__u32 prefixlen;/* up to 32 for AF_INET, 128 for AF_INET6 */ __u8 data[0 ];/* Arbitrary size */ }; +/* Header for bpf_lpm_trie_key structs */ +struct bpf_lpm_trie_key_hdr { +__u32 prefixlen; +}; + +/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry, with trailing byte array. */ +struct bpf_lpm_trie_key_u8 { +union { +struct bpf_lpm_trie_key_hdr hdr; +__u32 prefixlen; + }; +__u8 data[];/* Arbitrary size */ +}; +struct bpf_cgroup_storage_key {__u64 cgroup_inode_id;/* cgroup inode id */ __u32 attach_type;/* program attach type (enum bpf_attach_type) */
kernel/bpf/lpm_trie.c +10 -10
@@ -164,13 +164,13 @@ static inline int extract_bit(const u8 *data, size_t index)*/ static size_t longest_prefix_match (const struct lpm_trie *trie,const struct lpm_trie_node *node, -const struct bpf_lpm_trie_key *key) +const struct bpf_lpm_trie_key_u8 *key) {u32 limit =min (node->prefixlen, key->prefixlen);u32 prefixlen =0 , i =0 ;BUILD_BUG_ON (offsetof(struct lpm_trie_node , data) %sizeof (u32)); -BUILD_BUG_ON (offsetof(struct bpf_lpm_trie_key , data) %sizeof (u32)); +BUILD_BUG_ON (offsetof(struct bpf_lpm_trie_key_u8 , data) %sizeof (u32));#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS ) && defined(CONFIG_64BIT )
@@ -229,7 +229,7 @@ static void *trie_lookup_elem(struct bpf_map *map, void *_key) { struct lpm_trie *trie = container_of(map, struct lpm_trie, map);struct lpm_trie_node *node, *found =NULL ; -struct bpf_lpm_trie_key *key = _key; +struct bpf_lpm_trie_key_u8 *key = _key;if (key->prefixlen > trie->max_prefixlen)return NULL ;
@@ -309,7 +309,7 @@ static int trie_update_elem(struct bpf_map *map, struct lpm_trie *trie = container_of(map, struct lpm_trie, map);struct lpm_trie_node *node, *im_node =NULL , *new_node =NULL ;struct lpm_trie_node __rcu **slot; -struct bpf_lpm_trie_key *key = _key; +struct bpf_lpm_trie_key_u8 *key = _key;unsigned long irq_flags;unsigned int next_bit;size_t matchlen =0 ;
@@ -437,7 +437,7 @@ static int trie_update_elem(struct bpf_map *map,static int trie_delete_elem (struct bpf_map *map,void *_key) { struct lpm_trie *trie = container_of(map, struct lpm_trie, map); -struct bpf_lpm_trie_key *key = _key; +struct bpf_lpm_trie_key_u8 *key = _key;struct lpm_trie_node __rcu **trim, **trim2;struct lpm_trie_node *node, *parent;unsigned long irq_flags;
@@ -536,7 +536,7 @@ static int trie_delete_elem(struct bpf_map *map, void *_key) sizeof(struct lpm_trie_node))#define LPM_VAL_SIZE_MIN 1 -#define LPM_KEY_SIZE (X ) (sizeof(struct bpf_lpm_trie_key) + (X)) +#define LPM_KEY_SIZE (X ) (sizeof(struct bpf_lpm_trie_key_u8) + (X))#define LPM_KEY_SIZE_MAX LPM_KEY_SIZE(LPM_DATA_SIZE_MAX)#define LPM_KEY_SIZE_MIN LPM_KEY_SIZE(LPM_DATA_SIZE_MIN)
@@ -568,7 +568,7 @@ static struct bpf_map *trie_alloc(union bpf_attr *attr)/* copy mandatory map attributes */ bpf_map_init_from_attr (&trie->map, attr); trie->data_size = attr->key_size - - offsetof(struct bpf_lpm_trie_key , data); + offsetof(struct bpf_lpm_trie_key_u8 , data); trie->max_prefixlen = trie->data_size *8 ;spin_lock_init (&trie->lock);
@@ -619,7 +619,7 @@ static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key) {struct lpm_trie_node *node, *next_node =NULL , *parent, *search_root; struct lpm_trie *trie = container_of(map, struct lpm_trie, map); -struct bpf_lpm_trie_key *key = _key, *next_key = _next_key; +struct bpf_lpm_trie_key_u8 *key = _key, *next_key = _next_key;struct lpm_trie_node **node_stack =NULL ;int err =0 , stack_ptr =-1 ;unsigned int next_bit;
@@ -706,7 +706,7 @@ static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key) } do_copy: next_key->prefixlen = next_node->prefixlen; -memcpy ((void *)next_key + offsetof(struct bpf_lpm_trie_key , data), +memcpy ((void *)next_key + offsetof(struct bpf_lpm_trie_key_u8 , data), next_node->data, trie->data_size); free_stack:kfree (node_stack);
@@ -718,7 +718,7 @@ static int trie_check_btf(const struct bpf_map *map, const struct btf_type *key_type, const struct btf_type *value_type) { - /* Keys must have struct bpf_lpm_trie_key embedded. */ + /* Keys must have struct bpf_lpm_trie_key_u8 embedded. */ return BTF_INFO_KIND(key_type->info) != BTF_KIND_STRUCT ? -EINVAL : 0; }
samples/bpf/map_perf_test_user.c +1 -1
@@ -370,7 +370,7 @@ static void run_perf_test(int tasks)static void fill_lpm_trie (void ) { -struct bpf_lpm_trie_key *key; +struct bpf_lpm_trie_key_u8 *key;unsigned long value =0 ;unsigned int i;int r;
samples/bpf/xdp_router_ipv4_user.c +1 -1
@@ -91,7 +91,7 @@ static int recv_msg(struct sockaddr_nl sock_addr, int sock)static void read_route (struct nlmsghdr *nh,int nll) {char dsts[24 ], gws[24 ], ifs[16 ], dsts_len[24 ], metrics[24 ]; -struct bpf_lpm_trie_key *prefix_key; +struct bpf_lpm_trie_key_u8 *prefix_key;struct rtattr *rt_attr;struct rtmsg *rt_msg;int rtm_family;
tools/include/uapi/linux/bpf.h +18 -1
@@ -76,12 +76,29 @@ struct bpf_insn {__s32 imm;/* signed immediate constant */ }; -/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry */ +/* Deprecated: use struct bpf_lpm_trie_key_u8 (when the "data" member is needed for +* byte access) or struct bpf_lpm_trie_key_hdr (when using an alternative type for +* the trailing flexible array member) instead. +*/ struct bpf_lpm_trie_key {__u32 prefixlen;/* up to 32 for AF_INET, 128 for AF_INET6 */ __u8 data[0 ];/* Arbitrary size */ }; +/* Header for bpf_lpm_trie_key structs */ +struct bpf_lpm_trie_key_hdr { +__u32 prefixlen; +}; + +/* Key of an a BPF_MAP_TYPE_LPM_TRIE entry, with trailing byte array. */ +struct bpf_lpm_trie_key_u8 { +union { +struct bpf_lpm_trie_key_hdr hdr; +__u32 prefixlen; + }; +__u8 data[];/* Arbitrary size */ +}; +struct bpf_cgroup_storage_key {__u64 cgroup_inode_id;/* cgroup inode id */ __u32 attach_type;/* program attach type (enum bpf_attach_type) */
tools/testing/selftests/bpf/progs/map_ptr_kern.c +1 -1
@@ -311,7 +311,7 @@ struct lpm_trie { } __attribute__((preserve_access_index));struct lpm_key { -struct bpf_lpm_trie_key trie_key; +struct bpf_lpm_trie_key_hdr trie_key;__u32 data; };
tools/testing/selftests/bpf/test_lpm_map.c +9 -9
@@ -211,7 +211,7 @@ static void test_lpm_map(int keysize)volatile size_t n_matches, n_matches_after_delete;size_t i, j, n_nodes, n_lookups;struct tlpm_node *t, *list =NULL ; -struct bpf_lpm_trie_key *key; +struct bpf_lpm_trie_key_u8 *key;uint8_t *data, *value;int r, map;
@@ -331,8 +331,8 @@ static void test_lpm_map(int keysize)static void test_lpm_ipaddr (void ) { LIBBPF_OPTS(bpf_map_create_opts, opts, .map_flags = BPF_F_NO_PREALLOC); -struct bpf_lpm_trie_key *key_ipv4; -struct bpf_lpm_trie_key *key_ipv6; +struct bpf_lpm_trie_key_u8 *key_ipv4; +struct bpf_lpm_trie_key_u8 *key_ipv6;size_t key_size_ipv4;size_t key_size_ipv6;int map_fd_ipv4;
@@ -423,7 +423,7 @@ static void test_lpm_ipaddr(void)static void test_lpm_delete (void ) { LIBBPF_OPTS(bpf_map_create_opts, opts, .map_flags = BPF_F_NO_PREALLOC); -struct bpf_lpm_trie_key *key; +struct bpf_lpm_trie_key_u8 *key;size_t key_size;int map_fd;__u64 value;
@@ -532,7 +532,7 @@ static void test_lpm_delete(void)static void test_lpm_get_next_key (void ) { LIBBPF_OPTS(bpf_map_create_opts, opts, .map_flags = BPF_F_NO_PREALLOC); -struct bpf_lpm_trie_key *key_p, *next_key_p; +struct bpf_lpm_trie_key_u8 *key_p, *next_key_p;size_t key_size;__u32 value =0 ;int map_fd;
@@ -693,9 +693,9 @@ static void *lpm_test_command(void *arg) {int i, j, ret, iter, key_size;struct lpm_mt_test_info *info = arg; -struct bpf_lpm_trie_key *key_p; +struct bpf_lpm_trie_key_u8 *key_p; - key_size =sizeof (struct bpf_lpm_trie_key ) +sizeof (__u32); + key_size =sizeof (*key_p) +sizeof (__u32); key_p =alloca (key_size);for (iter =0 ; iter < info->iter; iter++)for (i =0 ; i <MAX_TEST_KEYS ; i++) {
@@ -717,7 +717,7 @@ static void *lpm_test_command(void *arg) ret =bpf_map_lookup_elem (info->map_fd, key_p, &value);assert (ret ==0 || errno ==ENOENT ); }else { -struct bpf_lpm_trie_key *next_key_p =alloca (key_size); +struct bpf_lpm_trie_key_u8 *next_key_p =alloca (key_size); ret =bpf_map_get_next_key (info->map_fd, key_p, next_key_p);assert (ret ==0 || errno ==ENOENT || errno ==ENOMEM ); }
@@ -752,7 +752,7 @@ static void test_lpm_multi_thread(void)/* create a trie */ value_size =sizeof (__u32); - key_size =sizeof (struct bpf_lpm_trie_key ) + value_size; + key_size =sizeof (struct bpf_lpm_trie_key_hdr ) + value_size; map_fd =bpf_map_create (BPF_MAP_TYPE_LPM_TRIE ,NULL , key_size, value_size,100 , &opts);/* create 4 threads to test update, delete, lookup and get_next_key */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 71/321 bpf: Avoid kfree_rcu() under lock in bpf_lpm_trie.
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexei Starovoitov <[email protected]>
[ Upstream commit 59f2f841179aa6a0899cb9cf53659149a35749b7 ]
syzbot reported the following lock sequence:
cpu 2:
grabs timer_base lock
spins on bpf_lpm lock
cpu 1:
grab rcu krcp lock
spins on timer_base lock
cpu 0:
grab bpf_lpm lock
spins on rcu krcp lock
bpf_lpm lock can be the same.timer_base lock can also be the same due to timer migration. but rcu krcp lock is always per-cpu, so it cannot be the same lock. Hence it's a false positive.
To avoid lockdep complaining move kfree_rcu() after spin_unlock.
--- kernel/bpf/lpm_trie.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
kernel/bpf/lpm_trie.c +9 -4
@@ -308,6 +308,7 @@ static int trie_update_elem(struct bpf_map *map, { struct lpm_trie *trie = container_of(map, struct lpm_trie, map);struct lpm_trie_node *node, *im_node =NULL , *new_node =NULL ; +struct lpm_trie_node *free_node =NULL ;struct lpm_trie_node __rcu **slot;struct bpf_lpm_trie_key_u8 *key = _key;unsigned long irq_flags;
@@ -382,7 +383,7 @@ static int trie_update_elem(struct bpf_map *map, trie->n_entries--;rcu_assign_pointer (*slot, new_node); -kfree_rcu (node, rcu); + free_node = node; goto out; }
@@ -429,6 +430,7 @@ static int trie_update_elem(struct bpf_map *map, }spin_unlock_irqrestore (&trie->lock, irq_flags); +kfree_rcu (free_node, rcu);return ret; }
@@ -437,6 +439,7 @@ static int trie_update_elem(struct bpf_map *map,static int trie_delete_elem (struct bpf_map *map,void *_key) { struct lpm_trie *trie = container_of(map, struct lpm_trie, map); +struct lpm_trie_node *free_node =NULL , *free_parent =NULL ;struct bpf_lpm_trie_key_u8 *key = _key;struct lpm_trie_node __rcu **trim, **trim2;struct lpm_trie_node *node, *parent;
@@ -506,8 +509,8 @@ static int trie_delete_elem(struct bpf_map *map, void *_key)else rcu_assign_pointer ( *trim2,rcu_access_pointer (parent->child[0 ])); -kfree_rcu (parent, rcu); -kfree_rcu (node, rcu); + free_parent = parent; + free_node = node; goto out; }
@@ -521,10 +524,12 @@ static int trie_delete_elem(struct bpf_map *map, void *_key)rcu_assign_pointer (*trim,rcu_access_pointer (node->child[1 ])); else RCU_INIT_POINTER(*trim, NULL); -kfree_rcu (node, rcu); + free_node = node; out:spin_unlock_irqrestore (&trie->lock, irq_flags); +kfree_rcu (free_parent, rcu); +kfree_rcu (free_node, rcu);return ret; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 72/321 Bluetooth: RFCOMM: Fix not validating setsockopt user input
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit a97de7bff13b1cc825c1b1344eaed8d6c2d3e695 ]
syzbot reported rfcomm_sock_setsockopt_old() is copying data without checking user input length.
BUG: KASAN: slab-out-of-bounds in copy_from_sockptr_offset include/linux/sockptr.h:49 [inline] BUG: KASAN: slab-out-of-bounds in copy_from_sockptr include/linux/sockptr.h:55 [inline] BUG: KASAN: slab-out-of-bounds in rfcomm_sock_setsockopt_old net/bluetooth/rfcomm/sock.c:632 [inline] BUG: KASAN: slab-out-of-bounds in rfcomm_sock_setsockopt+0x893/0xa70 net/bluetooth/rfcomm/sock.c:673 Read of size 4 at addr ffff8880209a8bc3 by task syz-executor632/5064
--- net/bluetooth/rfcomm/sock.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-)
net/bluetooth/rfcomm/sock.c +5 -9
@@ -629,7 +629,7 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname,switch (optname) {case RFCOMM_LM : -if (copy_from_sockptr (&opt, optval,sizeof (u32))) { +if (bt_copy_from_sockptr (&opt,sizeof (opt), optval, optlen)) { err = -EFAULT ;break ; }
@@ -664,7 +664,6 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,struct sock *sk = sock->sk;struct bt_security sec;int err =0 ; -size_t len;u32 opt;BT_DBG ("sk %p" , sk);
@@ -686,11 +685,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, sec.level =BT_SECURITY_LOW ; - len = min_t(unsigned int, sizeof(sec), optlen); -if (copy_from_sockptr (&sec, optval, len)) { - err = -EFAULT ; + err =bt_copy_from_sockptr (&sec,sizeof (sec), optval, optlen); +if (err)break ; - }if (sec.level >BT_SECURITY_HIGH ) { err = -EINVAL ;
@@ -706,10 +703,9 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,break ; } -if (copy_from_sockptr (&opt, optval,sizeof (u32))) { - err = -EFAULT ; + err =bt_copy_from_sockptr (&opt,sizeof (opt), optval, optlen); +if (err)break ; - }if (opt)set_bit (BT_SK_DEFER_SETUP , &bt_sk (sk)->flags);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 73/321 ext4: check the return value of ext4_xattr_inode_dec_ref()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li Zhong <[email protected]>
[ Upstream commit 56d0d0b9289dae041becc7ee6bd966a00dd610e0 ]
Check the return value of ext4_xattr_inode_dec_ref(), which could return error code and need to be warned.
Stable-dep-of: 0a46ef234756 ("ext4: do not create EA inode under buffer lock")
--- fs/ext4/xattr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/ext4/xattr.c +2 -1
@@ -1550,7 +1550,8 @@ static int ext4_xattr_inode_lookup_create(handle_t *handle, struct inode *inode, err =ext4_xattr_inode_write (handle, ea_inode, value, value_len);if (err) { -ext4_xattr_inode_dec_ref (handle, ea_inode); +if (ext4_xattr_inode_dec_ref (handle, ea_inode)) +ext4_warning_inode (ea_inode,"cleanup dec ref error %d" , err);iput (ea_inode);return err; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 74/321 ext4: fold quota accounting into ext4_xattr_inode_lookup_create()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
[ Upstream commit 8208c41c43ad5e9b63dce6c45a73e326109ca658 ]
When allocating EA inode, quota accounting is done just before ext4_xattr_inode_lookup_create(). Logically these two operations belong together so just fold quota accounting into ext4_xattr_inode_lookup_create(). We also make ext4_xattr_inode_lookup_create() return the looked up / created inode to convert the function to a more standard calling convention.
Stable-dep-of: 0a46ef234756 ("ext4: do not create EA inode under buffer lock")
--- fs/ext4/xattr.c | 50 ++++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 26 deletions(-)
fs/ext4/xattr.c +24 -26
@@ -1522,46 +1522,49 @@ ext4_xattr_inode_cache_find(struct inode *inode, const void *value,/* * Add value of the EA in an inode. */ -static int ext4_xattr_inode_lookup_create (handle_t *handle,struct inode *inode, -const void *value,size_t value_len, -struct inode **ret_inode) +static struct inode *ext4_xattr_inode_lookup_create (handle_t *handle, +struct inode *inode,const void *value,size_t value_len) {struct inode *ea_inode;u32 hash;int err; +/* Account inode & space to quota even if sharing... */ + err =ext4_xattr_inode_alloc_quota (inode, value_len); +if (err) +return ERR_PTR (err); + hash =ext4_xattr_inode_hash (EXT4_SB (inode->i_sb), value, value_len); ea_inode =ext4_xattr_inode_cache_find (inode, value, value_len, hash);if (ea_inode) { err =ext4_xattr_inode_inc_ref (handle, ea_inode); -if (err) { -iput (ea_inode); -return err; - } - - *ret_inode = ea_inode; -return 0 ; +if (err) + goto out_err; +return ea_inode; }/* Create an inode for the EA value */ ea_inode =ext4_xattr_inode_create (handle, inode, hash); -if (IS_ERR (ea_inode)) -return PTR_ERR (ea_inode); +if (IS_ERR (ea_inode)) { +ext4_xattr_inode_free_quota (inode,NULL , value_len); +return ea_inode; + } err =ext4_xattr_inode_write (handle, ea_inode, value, value_len);if (err) {if (ext4_xattr_inode_dec_ref (handle, ea_inode))ext4_warning_inode (ea_inode,"cleanup dec ref error %d" , err); -iput (ea_inode); -return err; + goto out_err; }if (EA_INODE_CACHE (inode))mb_cache_entry_create (EA_INODE_CACHE (inode),GFP_NOFS , hash, ea_inode->i_ino, true/* reusable */ ); - - *ret_inode = ea_inode; -return 0 ; +return ea_inode; +out_err: +iput (ea_inode); +ext4_xattr_inode_free_quota (inode,NULL , value_len); +return ERR_PTR (err); }/*
@@ -1669,16 +1672,11 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i,if (i->value && in_inode) {WARN_ON_ONCE (!i->value_len); - ret =ext4_xattr_inode_alloc_quota (inode, i->value_len); -if (ret) - goto out; - - ret =ext4_xattr_inode_lookup_create (handle, inode, i->value, - i->value_len, - &new_ea_inode); -if (ret) { + new_ea_inode =ext4_xattr_inode_lookup_create (handle, inode, + i->value, i->value_len); +if (IS_ERR (new_ea_inode)) { + ret =PTR_ERR (new_ea_inode); new_ea_inode =NULL ; -ext4_xattr_inode_free_quota (inode,NULL , i->value_len); goto out; } }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 75/321 ext4: do not create EA inode under buffer lock
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
[ Upstream commit 0a46ef234756dca04623b7591e8ebb3440622f0b ]
ext4_xattr_set_entry() creates new EA inodes while holding buffer lock on the external xattr block. This is problematic as it nests all the allocation locking (which acquires locks on other buffers) under the buffer lock. This can even deadlock when the filesystem is corrupted and e.g. quota file is setup to contain xattr block as data block. Move the allocation of EA inode out of ext4_xattr_set_entry() into the callers.
--- fs/ext4/xattr.c | 113 +++++++++++++++++++++++------------------------- 1 file changed, 53 insertions(+), 60 deletions(-)
fs/ext4/xattr.c +53 -60
@@ -1576,6 +1576,7 @@ static struct inode *ext4_xattr_inode_lookup_create(handle_t *handle,static int ext4_xattr_set_entry (struct ext4_xattr_info *i,struct ext4_xattr_search *s,handle_t *handle,struct inode *inode, +struct inode *new_ea_inode,bool is_block) {struct ext4_xattr_entry *last, *next;
@@ -1583,7 +1584,6 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i,size_t min_offs = s->end - s->base, name_len =strlen (i->name);int in_inode = i->in_inode;struct inode *old_ea_inode =NULL ; -struct inode *new_ea_inode =NULL ;size_t old_size, new_size;int ret;
@@ -1668,38 +1668,11 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i, old_ea_inode =NULL ; goto out; } - } -if (i->value && in_inode) { -WARN_ON_ONCE (!i->value_len); - - new_ea_inode =ext4_xattr_inode_lookup_create (handle, inode, - i->value, i->value_len); -if (IS_ERR (new_ea_inode)) { - ret =PTR_ERR (new_ea_inode); - new_ea_inode =NULL ; - goto out; - } - } -if (old_ea_inode) {/* We are ready to release ref count on the old_ea_inode. */ ret =ext4_xattr_inode_dec_ref (handle, old_ea_inode); -if (ret) { -/* Release newly required ref count on new_ea_inode. */ -if (new_ea_inode) { -int err; - - err =ext4_xattr_inode_dec_ref (handle, - new_ea_inode); -if (err) -ext4_warning_inode (new_ea_inode, -"dec ref new_ea_inode err=%d" , - err); -ext4_xattr_inode_free_quota (inode, new_ea_inode, - i->value_len); - } +if (ret) goto out; - }ext4_xattr_inode_free_quota (inode, old_ea_inode,le32_to_cpu (here->e_value_size));
@@ -1823,7 +1796,6 @@ static int ext4_xattr_set_entry(struct ext4_xattr_info *i, ret =0 ; out:iput (old_ea_inode); -iput (new_ea_inode);return ret; }
@@ -1886,9 +1858,21 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode,size_t old_ea_inode_quota =0 ;unsigned int ea_ino; -#define header (x) ((struct ext4_xattr_header *)(x)) +/* If we need EA inode, prepare it before locking the buffer */ +if (i->value && i->in_inode) { +WARN_ON_ONCE (!i->value_len); + + ea_inode =ext4_xattr_inode_lookup_create (handle, inode, + i->value, i->value_len); +if (IS_ERR (ea_inode)) { + error =PTR_ERR (ea_inode); + ea_inode =NULL ; + goto cleanup; + } + } +if (s->base) {int offset = (char *)s->here - bs->bh->b_data;
@@ -1897,6 +1881,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, EXT4_JTR_NONE);if (error) goto cleanup; +lock_buffer (bs->bh);if (header (s->base)->h_refcount ==cpu_to_le32 (1 )) {
@@ -1923,7 +1908,7 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, }ea_bdebug (bs->bh,"modifying in-place" ); error =ext4_xattr_set_entry (i, s, handle, inode, - true/* is_block */ ); + ea_inode, true/* is_block */ );ext4_xattr_block_csum_set (inode, bs->bh);unlock_buffer (bs->bh);if (error == -EFSCORRUPTED )
@@ -1991,29 +1976,13 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, s->end = s->base + sb->s_blocksize; } - error =ext4_xattr_set_entry (i, s, handle, inode, true/* is_block */ ); + error =ext4_xattr_set_entry (i, s, handle, inode, ea_inode, + true/* is_block */ );if (error == -EFSCORRUPTED ) goto bad_block;if (error) goto cleanup; -if (i->value && s->here->e_value_inum) { -/* -* A ref count on ea_inode has been taken as part of the call to -* ext4_xattr_set_entry() above. We would like to drop this -* extra ref but we have to wait until the xattr block is -* initialized and has its own ref count on the ea_inode. -*/ - ea_ino =le32_to_cpu (s->here->e_value_inum); - error =ext4_xattr_inode_iget (inode, ea_ino, -le32_to_cpu (s->here->e_hash), - &ea_inode); -if (error) { - ea_inode =NULL ; - goto cleanup; - } - } - inserted:if (!IS_LAST_ENTRY (s->first)) { new_bh = ext4_xattr_block_cache_find(inode, header(s->base),
@@ -2166,17 +2135,16 @@ ext4_xattr_block_set(handle_t *handle, struct inode *inode, cleanup:if (ea_inode) { -int error2; - - error2 =ext4_xattr_inode_dec_ref (handle, ea_inode); -if (error2) -ext4_warning_inode (ea_inode,"dec ref error=%d" , - error2); +if (error) { +int error2; -/* If there was an error, revert the quota charge. */ -if (error) + error2 =ext4_xattr_inode_dec_ref (handle, ea_inode); +if (error2) +ext4_warning_inode (ea_inode,"dec ref error=%d" , + error2);ext4_xattr_inode_free_quota (inode, ea_inode,i_size_read (ea_inode)); + }iput (ea_inode); }if (ce)
@@ -2234,14 +2202,38 @@ int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode, {struct ext4_xattr_ibody_header *header;struct ext4_xattr_search *s = &is->s; +struct inode *ea_inode =NULL ;int error;if (!EXT4_INODE_HAS_XATTR_SPACE (inode))return -ENOSPC ; - error =ext4_xattr_set_entry (i, s, handle, inode, false/* is_block */ ); -if (error) +/* If we need EA inode, prepare it before locking the buffer */ +if (i->value && i->in_inode) { +WARN_ON_ONCE (!i->value_len); + + ea_inode =ext4_xattr_inode_lookup_create (handle, inode, + i->value, i->value_len); +if (IS_ERR (ea_inode)) +return PTR_ERR (ea_inode); + } + error =ext4_xattr_set_entry (i, s, handle, inode, ea_inode, + false/* is_block */ ); +if (error) { +if (ea_inode) { +int error2; + + error2 =ext4_xattr_inode_dec_ref (handle, ea_inode); +if (error2) +ext4_warning_inode (ea_inode,"dec ref error=%d" , + error2); + +ext4_xattr_inode_free_quota (inode, ea_inode, +i_size_read (ea_inode)); +iput (ea_inode); + }return error; + } header =IHDR (inode,ext4_raw_inode (&is->iloc));if (!IS_LAST_ENTRY (s->first)) { header->h_magic =cpu_to_le32 (EXT4_XATTR_MAGIC );
@@ -2250,6 +2242,7 @@ int ext4_xattr_ibody_set(handle_t *handle, struct inode *inode, header->h_magic =cpu_to_le32 (0 );ext4_clear_inode_state (inode,EXT4_STATE_XATTR ); } +iput (ea_inode);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 76/321 udf: Fix bogus checksum computation in udf_rename()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jan Kara <[email protected]>
[ Upstream commit 27ab33854873e6fb958cb074681a0107cc2ecc4c ]
Syzbot reports uninitialized memory access in udf_rename() when updating checksum of '..' directory entry of a moved directory. This is indeed true as we pass on-stack diriter.fi to the udf_update_tag() and because that has only struct fileIdentDesc included in it and not the impUse or name fields, the checksumming function is going to checksum random stack contents beyond the end of the structure. This is actually harmless because the following udf_fiiter_write_fi() will recompute the checksum from on-disk buffers where everything is properly included. So all that is needed is just removing the bogus calculation.
--- fs/udf/namei.c | 1 - 1 file changed, 1 deletion(-)
fs/udf/namei.c +0 -1
@@ -1183,7 +1183,6 @@ static int udf_rename(struct user_namespace *mnt_userns, struct inode *old_dir,if (dir_fi) { dir_fi->icb.extLocation =cpu_to_lelb (UDF_I (new_dir)->i_location); -udf_update_tag ((char *)dir_fi,udf_dir_entry_len (dir_fi));if (old_iinfo->i_alloc_type ==ICBTAG_FLAG_AD_IN_ICB )mark_inode_dirty (old_inode);else
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 77/321 bpf, net: Use DEV_STAT_INC()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: yunshui <[email protected]>
[ Upstream commit d9cbd8343b010016fcaabc361c37720dcafddcbe ]
syzbot/KCSAN reported that races happen when multiple CPUs updating dev->stats.tx_error concurrently. Adopt SMP safe DEV_STATS_INC() to update the dev->stats fields.
--- net/core/filter.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
net/core/filter.c +4 -4
@@ -2264,12 +2264,12 @@ static int __bpf_redirect_neigh_v6(struct sk_buff *skb, struct net_device *dev, err =bpf_out_neigh_v6 (net, skb, dev, nh);if (unlikely (net_xmit_eval (err))) - dev->stats.tx_errors++; +DEV_STATS_INC (dev, tx_errors);else ret =NET_XMIT_SUCCESS ; goto out_xmit; out_drop: - dev->stats.tx_errors++; +DEV_STATS_INC (dev, tx_errors);kfree_skb (skb); out_xmit:return ret;
@@ -2371,12 +2371,12 @@ static int __bpf_redirect_neigh_v4(struct sk_buff *skb, struct net_device *dev, err =bpf_out_neigh_v4 (net, skb, dev, nh);if (unlikely (net_xmit_eval (err))) - dev->stats.tx_errors++; +DEV_STATS_INC (dev, tx_errors);else ret =NET_XMIT_SUCCESS ; goto out_xmit; out_drop: - dev->stats.tx_errors++; +DEV_STATS_INC (dev, tx_errors);kfree_skb (skb); out_xmit:return ret;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 78/321 fou: remove warn in gue_gro_receive on unsupported protocol
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Willem de Bruijn <[email protected]>
[ Upstream commit dd89a81d850fa9a65f67b4527c0e420d15bf836c ]
Drop the WARN_ON_ONCE inn gue_gro_receive if the encapsulated type is not known or does not have a GRO handler.
Such a packet is easily constructed. Syzbot generates them and sets off this warning.
Remove the warning as it is expected and not actionable.
The warning was previously reduced from WARN_ON to WARN_ON_ONCE in commit 270136613bf7 ("fou: Do WARN_ON_ONCE in gue_gro_receive for bad proto callbacks").
--- net/ipv4/fou.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/fou.c +1 -1
@@ -431,7 +431,7 @@ static struct sk_buff *gue_gro_receive(struct sock *sk, offloads =NAPI_GRO_CB (skb)->is_ipv6 ? inet6_offloads : inet_offloads; ops =rcu_dereference (offloads[proto]); -if (WARN_ON_ONCE (!ops || !ops->callbacks.gro_receive)) +if (!ops || !ops->callbacks.gro_receive) goto out; pp =call_gro_receive (ops->callbacks.gro_receive, head, skb);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 79/321 jfs: fix null ptr deref in dtInsertEntry
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Edward Adam Davis <[email protected]>
[ Upstream commit ce6dede912f064a855acf6f04a04cbb2c25b8c8c ]
[syzbot reported]
general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] PREEMPT SMP KASAN PTI KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] CPU: 0 PID: 5061 Comm: syz-executor404 Not tainted 6.8.0-syzkaller-08951-gfe46a7dd189e #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/27/2024 RIP: 0010:dtInsertEntry+0xd0c/0x1780 fs/jfs/jfs_dtree.c:3713
...
[Analyze]
In dtInsertEntry(), when the pointer h has the same value as p, after writing name in UniStrncpy_to_le(), p->header.flag will be cleared. This will cause the previously true judgment "p->header.flag & BT-LEAF" to change to no after writing the name operation, this leads to entering an incorrect branch and accessing the uninitialized object ih when judging this condition for the second time.
[Fix]
After got the page, check freelist first, if freelist == 0 then exit dtInsert() and return -EINVAL.
--- fs/jfs/jfs_dtree.c | 2 ++ 1 file changed, 2 insertions(+)
fs/jfs/jfs_dtree.c +2 -0
@@ -834,6 +834,8 @@ int dtInsert(tid_t tid, struct inode *ip,* the full page. */ DT_GETSEARCH (ip, btstack->top, bn, mp, p, index); +if (p->header.freelist ==0 ) +return -EINVAL ;/* * insert entry for new key
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 80/321 jfs: Fix shift-out-of-bounds in dbDiscardAG
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pei Li <[email protected]>
[ Upstream commit 7063b80268e2593e58bee8a8d709c2f3ff93e2f2 ]
When searching for the next smaller log2 block, BLKSTOL2() returned 0, causing shift exponent -1 to be negative.
This patch fixes the issue by exiting the loop directly when negative shift is found.
--- fs/jfs/jfs_dmap.c | 2 ++ 1 file changed, 2 insertions(+)
fs/jfs/jfs_dmap.c +2 -0
@@ -1626,6 +1626,8 @@ s64 dbDiscardAG(struct inode *ip, int agno, s64 minlen) }else if (rc == -ENOSPC ) {/* search for next smaller log2 block */ l2nb =BLKSTOL2 (nblocks) -1 ; +if (unlikely (l2nb <0 )) +break ; nblocks =1LL << l2nb; }else {/* Trim any already allocated blocks */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 81/321 fs/ntfs3: Do copy_to_user out of run_lock
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konstantin Komarov <[email protected]>
[ Upstream commit d57431c6f511bf020e474026d9f3123d7bfbea8c ]
In order not to call copy_to_user (from fiemap_fill_next_extent) we allocate memory in the kernel, fill it and copy it to user memory after up_read(run_lock).
--- fs/ntfs3/frecord.c | 75 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 3 deletions(-)
fs/ntfs3/frecord.c +72 -3
@@ -1897,6 +1897,47 @@ enum REPARSE_SIGN ni_parse_reparse(struct ntfs_inode *ni, struct ATTRIB *attr,return REPARSE_LINK ; } +/* +* fiemap_fill_next_extent_k - a copy of fiemap_fill_next_extent +* but it accepts kernel address for fi_extents_start +*/ +static int fiemap_fill_next_extent_k (struct fiemap_extent_info *fieinfo, +u64 logical,u64 phys,u64 len,u32 flags) +{ +struct fiemap_extent extent; +struct fiemap_extent __user *dest = fieinfo->fi_extents_start; + +/* only count the extents */ +if (fieinfo->fi_extents_max ==0 ) { + fieinfo->fi_extents_mapped++; +return (flags &FIEMAP_EXTENT_LAST ) ?1 :0 ; + } + +if (fieinfo->fi_extents_mapped >= fieinfo->fi_extents_max) +return 1 ; + +if (flags &FIEMAP_EXTENT_DELALLOC ) + flags |=FIEMAP_EXTENT_UNKNOWN ; +if (flags &FIEMAP_EXTENT_DATA_ENCRYPTED ) + flags |=FIEMAP_EXTENT_ENCODED ; +if (flags & (FIEMAP_EXTENT_DATA_TAIL |FIEMAP_EXTENT_DATA_INLINE )) + flags |=FIEMAP_EXTENT_NOT_ALIGNED ; + +memset (&extent,0 ,sizeof (extent)); + extent.fe_logical = logical; + extent.fe_physical = phys; + extent.fe_length = len; + extent.fe_flags = flags; + + dest += fieinfo->fi_extents_mapped; +memcpy (dest, &extent,sizeof (extent)); + + fieinfo->fi_extents_mapped++; +if (fieinfo->fi_extents_mapped == fieinfo->fi_extents_max) +return 1 ; +return (flags &FIEMAP_EXTENT_LAST ) ?1 :0 ; +} +/* * ni_fiemap - Helper for file_fiemap(). *
@@ -1907,6 +1948,8 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, __u64 vbo, __u64 len) { int err = 0; +struct fiemap_extent __user *fe_u = fieinfo->fi_extents_start; +struct fiemap_extent *fe_k =NULL ;struct ntfs_sb_info *sbi = ni->mi.sbi;u8 cluster_bits = sbi->cluster_bits;struct runs_tree *run;
@@ -1954,6 +1997,18 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo, goto out; } +/* +* To avoid lock problems replace pointer to user memory by pointer to kernel memory. +*/ + fe_k =kmalloc_array (fieinfo->fi_extents_max, +sizeof (struct fiemap_extent ), +GFP_NOFS | __GFP_ZERO); +if (!fe_k) { + err = -ENOMEM ; + goto out; + } + fieinfo->fi_extents_start = fe_k; + end = vbo + len; alloc_size =le64_to_cpu (attr->nres.alloc_size);if (end > alloc_size)
@@ -2042,8 +2097,9 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,if (vbo + dlen >= end) flags |=FIEMAP_EXTENT_LAST ; - err =fiemap_fill_next_extent (fieinfo, vbo, lbo, dlen, - flags); + err =fiemap_fill_next_extent_k (fieinfo, vbo, lbo, dlen, + flags); +if (err <0 )break ;if (err ==1 ) {
@@ -2063,7 +2119,8 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,if (vbo + bytes >= end) flags |=FIEMAP_EXTENT_LAST ; - err =fiemap_fill_next_extent (fieinfo, vbo, lbo, bytes, flags); + err =fiemap_fill_next_extent_k (fieinfo, vbo, lbo, bytes, + flags);if (err <0 )break ;if (err ==1 ) {
@@ -2076,7 +2133,19 @@ int ni_fiemap(struct ntfs_inode *ni, struct fiemap_extent_info *fieinfo,up_read (run_lock); +/* +* Copy to user memory out of lock +*/ +if (copy_to_user (fe_u, fe_k, + fieinfo->fi_extents_max * +sizeof (struct fiemap_extent ))) { + err = -EFAULT ; + } + out: +/* Restore original pointer. */ + fieinfo->fi_extents_start = fe_u; +kfree (fe_k);return err; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 82/321 ALSA: usb: Fix UBSAN warning in parse_audio_unit()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ Upstream commit 2f38cf730caedaeacdefb7ff35b0a3c1168117f9 ]
A malformed USB descriptor may pass the lengthy mixer description with a lot of channels, and this may overflow the 32bit integer shift size, as caught by syzbot UBSAN test. Although this won't cause any real trouble, it's better to address.
This patch introduces a sanity check of the number of channels to bail out the parsing when too many channels are found.
--- sound/usb/mixer.c | 7 +++++++ 1 file changed, 7 insertions(+)
sound/usb/mixer.c +7 -0
@@ -2023,6 +2023,13 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, bmaControls = ftr->bmaControls; } +if (channels >32 ) { +usb_audio_info (state->chip, +"usbmixer: too many channels (%d) in unit %d\n" , + channels, unitid); +return -EINVAL ; + } +/* parse the source unit */ err =parse_audio_unit (state, hdr->bSourceID);if (err <0 )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 83/321 igc: Correct the launchtime offset
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muhammad Husaini Zulkifli <[email protected]>
[ Upstream commit 790835fcc0cb9992349ae3c9010dbc7321aaa24d ]
The launchtime offset should be corrected according to sections 7.5.2.6 Transmit Scheduling Latency of the Intel Ethernet I225/I226 Software User Manual.
Software can compensate the latency between the transmission scheduling and the time that packet is transmitted to the network by setting this GTxOffset register. Without setting this register, there may be a significant delay between the packet scheduling and the network point.
This patch helps to reduce the latency for each of the link speed.
Before:
10Mbps : 11000 - 13800 nanosecond
100Mbps : 1300 - 1700 nanosecond
1000Mbps : 190 - 600 nanosecond
2500Mbps : 1400 - 1700 nanosecond
After:
10Mbps : less than 750 nanosecond
100Mbps : less than 192 nanosecond
1000Mbps : less than 128 nanosecond
2500Mbps : less than 128 nanosecond
Test Setup:
Talker : Use l2_tai.c to generate the launchtime into packet payload.
Listener: Use timedump.c to compute the delta between packet arrival and LaunchTime packet payload.
Stable-dep-of: e037a26ead18 ("igc: Fix packet still tx after gate close by reducing i226 MAC retry buffer")
--- drivers/net/ethernet/intel/igc/igc_defines.h | 9 ++++++ drivers/net/ethernet/intel/igc/igc_main.c | 7 +++++ drivers/net/ethernet/intel/igc/igc_regs.h | 1 + drivers/net/ethernet/intel/igc/igc_tsn.c | 30 ++++++++++++++++++++ drivers/net/ethernet/intel/igc/igc_tsn.h | 1 + 5 files changed, 48 insertions(+)
drivers/net/ethernet/intel/igc/igc_defines.h +9 -0
@@ -402,6 +402,15 @@#define IGC_DTXMXPKTSZ_TSN 0x19/* 1600 bytes of max TX DMA packet size */ #define IGC_DTXMXPKTSZ_DEFAULT 0x98/* 9728-byte Jumbo frames */ +/* Transmit Scheduling Latency */ +/* Latency between transmission scheduling (LaunchTime) and the time +* the packet is transmitted to the network in nanosecond. +*/ +#define IGC_TXOFFSET_SPEED_10 0x000034BC +#define IGC_TXOFFSET_SPEED_100 0x00000578 +#define IGC_TXOFFSET_SPEED_1000 0x0000012C +#define IGC_TXOFFSET_SPEED_2500 0x00000578 +/* Time Sync Interrupt Causes */ #define IGC_TSICR_SYS_WRAP BIT(0)/* SYSTIM Wrap around. */ #define IGC_TSICR_TXTS BIT(1)/* Transmit Timestamp. */
drivers/net/ethernet/intel/igc/igc_main.c +7 -0
@@ -5586,6 +5586,13 @@ static void igc_watchdog_task(struct work_struct *work)break ; } +/* Once the launch time has been set on the wire, there +* is a delay before the link speed can be determined +* based on link-up activity. Write into the register +* as soon as we know the correct link speed. +*/ +igc_tsn_adjust_txtime_offset (adapter); +if (adapter->link_speed !=SPEED_1000 ) goto no_wait;
drivers/net/ethernet/intel/igc/igc_regs.h +1 -0
@@ -224,6 +224,7 @@/* Transmit Scheduling Registers */ #define IGC_TQAVCTRL 0x3570#define IGC_TXQCTL (_n) (0x3344 + 0x4 * (_n)) +#define IGC_GTXOFFSET 0x3310#define IGC_BASET_L 0x3314#define IGC_BASET_H 0x3318#define IGC_QBVCYCLET 0x331C
drivers/net/ethernet/intel/igc/igc_tsn.c +30 -0
@@ -49,6 +49,35 @@ static unsigned int igc_tsn_new_flags(struct igc_adapter *adapter)return new_flags; } +void igc_tsn_adjust_txtime_offset (struct igc_adapter *adapter) +{ +struct igc_hw *hw = &adapter->hw; +u16 txoffset; + +if (!is_any_launchtime (adapter)) +return ; + +switch (adapter->link_speed) { +case SPEED_10 : + txoffset =IGC_TXOFFSET_SPEED_10 ; +break ; +case SPEED_100 : + txoffset =IGC_TXOFFSET_SPEED_100 ; +break ; +case SPEED_1000 : + txoffset =IGC_TXOFFSET_SPEED_1000 ; +break ; +case SPEED_2500 : + txoffset =IGC_TXOFFSET_SPEED_2500 ; +break ; +default : + txoffset =0 ; +break ; + } + +wr32 (IGC_GTXOFFSET , txoffset); +} +/* Returns the TSN specific registers to their default values after * the adapter is reset. */
@@ -58,6 +87,7 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)u32 tqavctrl;int i; +wr32 (IGC_GTXOFFSET ,0 );wr32 (IGC_TXPBS ,I225_TXPBSIZE_DEFAULT );wr32 (IGC_DTXMXPKTSZ ,IGC_DTXMXPKTSZ_DEFAULT );
drivers/net/ethernet/intel/igc/igc_tsn.h +1 -0
@@ -6,5 +6,6 @@int igc_tsn_offload_apply (struct igc_adapter *adapter);int igc_tsn_reset (struct igc_adapter *adapter); +void igc_tsn_adjust_txtime_offset (struct igc_adapter *adapter);#endif /* _IGC_BASE_H */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 84/321 igc: Fix packet still tx after gate close by reducing i226 MAC retry buffer
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Faizal Rahim <[email protected]>
[ Upstream commit e037a26ead187901f83cad9c503ccece5ff6817a ]
Testing uncovered that even when the taprio gate is closed, some packets still transmit.
According to i225/6 hardware errata [1], traffic might overflow the planned QBV window. This happens because MAC maintains an internal buffer, primarily for supporting half duplex retries. Therefore, even when the gate closes, residual MAC data in the buffer may still transmit.
To mitigate this for i226, reduce the MAC's internal buffer from 192 bytes to the recommended 88 bytes by modifying the RETX_CTL register value.
This follows guidelines from:
[1] Ethernet Controller I225/I22 Spec Update Rev 2.1 Errata Item 9:
TSN: Packet Transmission Might Cross Qbv Window
[2] I225/6 SW User Manual Rev 1.2.4: Section 8.11.5 Retry Buffer Control
Note that the RETX_CTL register can't be used in TSN mode because half duplex feature cannot coexist with TSN.
Test Steps:
1. Send taprio cmd to board A:
tc qdisc replace dev enp1s0 parent root handle 100 taprio \
num_tc 4 \
map 3 2 1 0 3 3 3 3 3 3 3 3 3 3 3 3 \
queues 1@0 1@1 1@2 1@3 \
base-time 0 \
sched-entry S 0x07 500000 \
sched-entry S 0x0f 500000 \
flags 0x2 \
txtime-delay 0
Note that for TC3, gate should open for 500us and close for another
500us.3. Take tcpdump log on Board B.
4. Send udp packets via UDP tai app from Board A to Board B.
5. Analyze tcpdump log via wireshark log on Board B. Ensure that the total time from the first to the last packet received during one cycle for TC3 does not exceed 500us.
--- drivers/net/ethernet/intel/igc/igc_defines.h | 6 ++++ drivers/net/ethernet/intel/igc/igc_tsn.c | 34 ++++++++++++++++++++ 2 files changed, 40 insertions(+)
drivers/net/ethernet/intel/igc/igc_defines.h +6 -0
@@ -402,6 +402,12 @@#define IGC_DTXMXPKTSZ_TSN 0x19/* 1600 bytes of max TX DMA packet size */ #define IGC_DTXMXPKTSZ_DEFAULT 0x98/* 9728-byte Jumbo frames */ +/* Retry Buffer Control */ +#define IGC_RETX_CTL 0x041C +#define IGC_RETX_CTL_WATERMARK_MASK 0xF +#define IGC_RETX_CTL_QBVFULLTH_SHIFT 8/* QBV Retry Buffer Full Threshold */ +#define IGC_RETX_CTL_QBVFULLEN 0x1000/* Enable QBV Retry Buffer Full Threshold */ +/* Transmit Scheduling Latency */ /* Latency between transmission scheduling (LaunchTime) and the time * the packet is transmitted to the network in nanosecond.
drivers/net/ethernet/intel/igc/igc_tsn.c +34 -0
@@ -78,6 +78,15 @@ void igc_tsn_adjust_txtime_offset(struct igc_adapter *adapter)wr32 (IGC_GTXOFFSET , txoffset); } +static void igc_tsn_restore_retx_default (struct igc_adapter *adapter) +{ +struct igc_hw *hw = &adapter->hw; +u32 retxctl; + + retxctl =rd32 (IGC_RETX_CTL ) &IGC_RETX_CTL_WATERMARK_MASK ; +wr32 (IGC_RETX_CTL , retxctl); +} +/* Returns the TSN specific registers to their default values after * the adapter is reset. */
@@ -91,6 +100,9 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)wr32 (IGC_TXPBS ,I225_TXPBSIZE_DEFAULT );wr32 (IGC_DTXMXPKTSZ ,IGC_DTXMXPKTSZ_DEFAULT ); +if (igc_is_device_id_i226 (hw)) +igc_tsn_restore_retx_default (adapter); + tqavctrl =rd32 (IGC_TQAVCTRL ); tqavctrl &= ~(IGC_TQAVCTRL_TRANSMIT_MODE_TSN |IGC_TQAVCTRL_ENHANCED_QAV |IGC_TQAVCTRL_FUTSCDDIS );
@@ -111,6 +123,25 @@ static int igc_tsn_disable_offload(struct igc_adapter *adapter)return 0 ; } +/* To partially fix i226 HW errata, reduce MAC internal buffering from 192 Bytes +* to 88 Bytes by setting RETX_CTL register using the recommendation from: +* a) Ethernet Controller I225/I226 Specification Update Rev 2.1 +* Item 9: TSN: Packet Transmission Might Cross the Qbv Window +* b) I225/6 SW User Manual Rev 1.2.4: Section 8.11.5 Retry Buffer Control +*/ +static void igc_tsn_set_retx_qbvfullthreshold (struct igc_adapter *adapter) +{ +struct igc_hw *hw = &adapter->hw; +u32 retxctl, watermark; + + retxctl =rd32 (IGC_RETX_CTL ); + watermark = retxctl &IGC_RETX_CTL_WATERMARK_MASK ; +/* Set QBVFULLTH value using watermark and set QBVFULLEN */ + retxctl |= (watermark <<IGC_RETX_CTL_QBVFULLTH_SHIFT ) | +IGC_RETX_CTL_QBVFULLEN ; +wr32 (IGC_RETX_CTL , retxctl); +} +static int igc_tsn_enable_offload (struct igc_adapter *adapter) {struct igc_hw *hw = &adapter->hw;
@@ -124,6 +155,9 @@ static int igc_tsn_enable_offload(struct igc_adapter *adapter)wr32 (IGC_DTXMXPKTSZ ,IGC_DTXMXPKTSZ_TSN );wr32 (IGC_TXPBS ,IGC_TXPBSIZE_TSN ); +if (igc_is_device_id_i226 (hw)) +igc_tsn_set_retx_qbvfullthreshold (adapter); +for (i =0 ; i < adapter->num_tx_queues; i++) {struct igc_ring *ring = adapter->tx_ring[i];u32 txqctl =0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 85/321 net/mlx5e: Take state lock during tx timeout reporter
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dragos Tatulea <[email protected]>
[ Upstream commit e6b5afd30b99b43682a7764e1a74a42fe4d5f4b3 ]
mlx5e_safe_reopen_channels() requires the state lock taken. The referenced changed in the Fixes tag removed the lock to fix another issue. This patch adds it back but at a later point (when calling mlx5e_safe_reopen_channels()) to avoid the deadlock referenced in the Fixes tag.
--- drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/ethernet/mellanox/mlx5/core/en/reporter_tx.c +2 -0
@@ -111,7 +111,9 @@ static int mlx5e_tx_reporter_timeout_recover(void *ctx)return err; } +mutex_lock (&priv->state_lock); err =mlx5e_safe_reopen_channels (priv); +mutex_unlock (&priv->state_lock);if (!err) { to_ctx->status =1 ;/* all channels recovered */ return err;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 86/321 net/mlx5e: Correctly report errors for ethtool rx flows
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cosmin Ratiu <[email protected]>
[ Upstream commit cbc796be1779c4dbc9a482c7233995e2a8b6bfb3 ]
Previously, an ethtool rx flow with no attrs would not be added to the NIC as it has no rules to configure the hw with, but it would be reported as successful to the caller (return code 0). This is confusing for the user as ethtool then reports "Added rule $num", but no rule was actually added.
This change corrects that by instead reporting these wrong rules as -EINVAL.
--- drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/en_fs_ethtool.c +1 -1
@@ -738,7 +738,7 @@ mlx5e_ethtool_flow_replace(struct mlx5e_priv *priv,if (num_tuples <=0 ) {netdev_warn (priv->netdev,"%s: flow is not valid %d\n" , __func__, num_tuples); -return num_tuples; +return num_tuples <0 ? num_tuples : -EINVAL ; } eth_ft =get_flow_table (priv, fs, num_tuples);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 87/321 atm: idt77252: prevent use after free in dequeue_rx()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit a9a18e8f770c9b0703dab93580d0b02e199a4c79 ]
We can't dereference "skb" after calling vcc->push() because the skb is released.
--- drivers/atm/idt77252.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/atm/idt77252.c +5 -4
@@ -1118,8 +1118,8 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe) rpp->len += skb->len;if (stat &SAR_RSQE_EPDU ) { +unsigned int len, truesize;unsigned char *l1l2; -unsigned int len; l1l2 = (unsigned char *) ((unsigned long ) skb->data + skb->len -6 );
@@ -1189,14 +1189,15 @@ dequeue_rx(struct idt77252_dev *card, struct rsq_entry *rsqe)ATM_SKB (skb)->vcc = vcc;__net_timestamp (skb); + truesize = skb->truesize; vcc->push (vcc, skb);atomic_inc (&vcc->stats->rx); -if (skb->truesize >SAR_FB_SIZE_3 ) +if (truesize >SAR_FB_SIZE_3 )add_rx_skb (card,3 ,SAR_FB_SIZE_3 ,1 ); -else if (skb->truesize >SAR_FB_SIZE_2 ) +else if (truesize >SAR_FB_SIZE_2 )add_rx_skb (card,2 ,SAR_FB_SIZE_2 ,1 ); -else if (skb->truesize >SAR_FB_SIZE_1 ) +else if (truesize >SAR_FB_SIZE_1 )add_rx_skb (card,1 ,SAR_FB_SIZE_1 ,1 );else add_rx_skb (card,0 ,SAR_FB_SIZE_0 ,1 );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 88/321 net: axienet: Fix register defines comment description
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Radhey Shyam Pandey <[email protected]>
[ Upstream commit 9ff2f816e2aa65ca9a1cdf0954842f8173c0f48d ]
In axiethernet header fix register defines comment description to be inline with IP documentation. It updates MAC configuration register, MDIO configuration register and frame filter control description.
--- drivers/net/ethernet/xilinx/xilinx_axienet.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
drivers/net/ethernet/xilinx/xilinx_axienet.h +8 -8
@@ -159,16 +159,16 @@#define XAE_RCW1_OFFSET 0x00000404/* Rx Configuration Word 1 */ #define XAE_TC_OFFSET 0x00000408/* Tx Configuration */ #define XAE_FCC_OFFSET 0x0000040C/* Flow Control Configuration */ -#define XAE_EMMC_OFFSET 0x00000410/* EMAC mode configuration */ -#define XAE_PHYC_OFFSET 0x00000414/* RGMII/SGMII configuration */ +#define XAE_EMMC_OFFSET 0x00000410/* MAC speed configuration */ +#define XAE_PHYC_OFFSET 0x00000414/* RX Max Frame Configuration */ #define XAE_ID_OFFSET 0x000004F8/* Identification register */ -#define XAE_MDIO_MC_OFFSET 0x00000500/* MII Management Config */ -#define XAE_MDIO_MCR_OFFSET 0x00000504/* MII Management Control */ -#define XAE_MDIO_MWD_OFFSET 0x00000508/* MII Management Write Data */ -#define XAE_MDIO_MRD_OFFSET 0x0000050C/* MII Management Read Data */ +#define XAE_MDIO_MC_OFFSET 0x00000500/* MDIO Setup */ +#define XAE_MDIO_MCR_OFFSET 0x00000504/* MDIO Control */ +#define XAE_MDIO_MWD_OFFSET 0x00000508/* MDIO Write Data */ +#define XAE_MDIO_MRD_OFFSET 0x0000050C/* MDIO Read Data */ #define XAE_UAW0_OFFSET 0x00000700/* Unicast address word 0 */ #define XAE_UAW1_OFFSET 0x00000704/* Unicast address word 1 */ -#define XAE_FMI_OFFSET 0x00000708/* Filter Mask Index */ +#define XAE_FMI_OFFSET 0x00000708/* Frame Filter Control */ #define XAE_AF0_OFFSET 0x00000710/* Address Filter 0 */ #define XAE_AF1_OFFSET 0x00000714/* Address Filter 1 */
@@ -307,7 +307,7 @@*/ #define XAE_UAW1_UNICASTADDR_MASK 0x0000FFFF -/* Bit masks for Axi Ethernet FMI register */ +/* Bit masks for Axi Ethernet FMC register */ #define XAE_FMI_PM_MASK 0x80000000/* Promis. mode enable */ #define XAE_FMI_IND_MASK 0x00000003/* Index Mask */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 89/321 net: dsa: vsc73xx: pass value in phy_write operation
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pawel Dembicki <[email protected]>
[ Upstream commit 5b9eebc2c7a5f0cc7950d918c1e8a4ad4bed5010 ]
In the 'vsc73xx_phy_write' function, the register value is missing, and the phy write operation always sends zeros.
This commit passes the value variable into the proper register.
--- drivers/net/dsa/vitesse-vsc73xx-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/dsa/vitesse-vsc73xx-core.c +1 -1
@@ -531,7 +531,7 @@ static int vsc73xx_phy_write(struct dsa_switch *ds, int phy, int regnum,return 0 ; } - cmd = (phy <<21 ) | (regnum <<16 ); + cmd = (phy <<21 ) | (regnum <<16 ) | val; ret =vsc73xx_write (vsc,VSC73XX_BLOCK_MII ,0 ,1 , cmd);if (ret)return ret;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 90/321 net: dsa: vsc73xx: use read_poll_timeout instead delay loop
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pawel Dembicki <[email protected]>
[ Upstream commit eb7e33d01db3aec128590391b2397384bab406b6 ]
Switch the delay loop during the Arbiter empty check from vsc73xx_adjust_link() to use read_poll_timeout(). Functionally, one msleep() call is eliminated at the end of the loop in the timeout case.
As Russell King suggested:
"This [change] avoids the issue that on the last iteration, the code reads the register, tests it, finds the condition that's being waiting for is false, _then_ waits and end up printing the error message - that last wait is rather useless, and as the arbiter state isn't checked after waiting, it could be that we had success during the last wait."
Stable-dep-of: fa63c6434b6f ("net: dsa: vsc73xx: check busy flag in MDIO operations")
--- drivers/net/dsa/vitesse-vsc73xx-core.c | 30 ++++++++++++++------------ 1 file changed, 16 insertions(+), 14 deletions(-)
drivers/net/dsa/vitesse-vsc73xx-core.c +16 -14
@@ -17,6 +17,7 @@#include <linux/kernel.h> #include <linux/module.h> #include <linux/device.h> +#include <linux/iopoll.h> #include <linux/of.h> #include <linux/of_device.h> #include <linux/of_mdio.h>
@@ -269,6 +270,9 @@#define IS_7398 (a) ((a)->chipid == VSC73XX_CHIPID_ID_7398)#define IS_739X (a) (IS_7395(a) || IS_7398(a)) +#define VSC73XX_POLL_SLEEP_US 1000 +#define VSC73XX_POLL_TIMEOUT_US 10000 +struct vsc73xx_counter {u8 counter;const char *name;
@@ -780,7 +784,7 @@ static void vsc73xx_adjust_link(struct dsa_switch *ds, int port,* after a PHY or the CPU port comes up or down. */ if (!phydev->link) { -int maxloop =10 ; +int ret, err;dev_dbg (vsc->dev,"port %d: went down\n" , port);
@@ -795,19 +799,17 @@ static void vsc73xx_adjust_link(struct dsa_switch *ds, int port, VSC73XX_ARBDISC, BIT(port), BIT(port));/* Wait until queue is empty */ -vsc73xx_read (vsc,VSC73XX_BLOCK_ARBITER ,0 , -VSC73XX_ARBEMPTY , &val); -while (!(val &BIT (port))) { -msleep (1 ); -vsc73xx_read (vsc,VSC73XX_BLOCK_ARBITER ,0 , -VSC73XX_ARBEMPTY , &val); -if (--maxloop ==0 ) { -dev_err (vsc->dev, -"timeout waiting for block arbiter\n" ); -/* Continue anyway */ -break ; - } - } + ret =read_poll_timeout (vsc73xx_read, err, + err <0 || (val &BIT (port)), +VSC73XX_POLL_SLEEP_US , +VSC73XX_POLL_TIMEOUT_US , false, + vsc,VSC73XX_BLOCK_ARBITER ,0 , +VSC73XX_ARBEMPTY , &val); +if (ret) +dev_err (vsc->dev, +"timeout waiting for block arbiter\n" ); +else if (err <0 ) +dev_err (vsc->dev,"error reading arbiter\n" );/* Put this port into reset */ vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port, VSC73XX_MAC_CFG,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 91/321 net: dsa: vsc73xx: check busy flag in MDIO operations
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pawel Dembicki <[email protected]>
[ Upstream commit fa63c6434b6f6aaf9d8d599dc899bc0a074cc0ad ]
The VSC73xx has a busy flag used during MDIO operations. It is raised when MDIO read/write operations are in progress. Without it, PHYs are misconfigured and bus operations do not work as expected.
--- drivers/net/dsa/vitesse-vsc73xx-core.c | 37 +++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-)
drivers/net/dsa/vitesse-vsc73xx-core.c +36 -1
@@ -39,6 +39,10 @@#define VSC73XX_BLOCK_ARBITER 0x5/* Only subblock 0 */ #define VSC73XX_BLOCK_SYSTEM 0x7/* Only subblock 0 */ +/* MII Block subblock */ +#define VSC73XX_BLOCK_MII_INTERNAL 0x0/* Internal MDIO subblock */ +#define VSC73XX_BLOCK_MII_EXTERNAL 0x1/* External MDIO subblock */ +#define CPU_PORT 6/* CPU port */ /* MAC Block registers */
@@ -197,6 +201,8 @@#define VSC73XX_MII_CMD 0x1#define VSC73XX_MII_DATA 0x2 +#define VSC73XX_MII_STAT_BUSY BIT(3) +/* Arbiter block 5 registers */ #define VSC73XX_ARBEMPTY 0x0c#define VSC73XX_ARBDISC 0x0e
@@ -271,6 +277,7 @@#define IS_739X (a) (IS_7395(a) || IS_7398(a))#define VSC73XX_POLL_SLEEP_US 1000 +#define VSC73XX_MDIO_POLL_SLEEP_US 5#define VSC73XX_POLL_TIMEOUT_US 10000struct vsc73xx_counter {
@@ -488,6 +495,22 @@ static int vsc73xx_detect(struct vsc73xx *vsc)return 0 ; } +static int vsc73xx_mdio_busy_check (struct vsc73xx *vsc) +{ +int ret, err; +u32 val; + + ret =read_poll_timeout (vsc73xx_read, err, + err <0 || !(val &VSC73XX_MII_STAT_BUSY ), +VSC73XX_MDIO_POLL_SLEEP_US , +VSC73XX_POLL_TIMEOUT_US , false, vsc, +VSC73XX_BLOCK_MII ,VSC73XX_BLOCK_MII_INTERNAL , +VSC73XX_MII_STAT , &val); +if (ret) +return ret; +return err; +} +static int vsc73xx_phy_read (struct dsa_switch *ds,int phy,int regnum) {struct vsc73xx *vsc = ds->priv;
@@ -495,12 +518,20 @@ static int vsc73xx_phy_read(struct dsa_switch *ds, int phy, int regnum)u32 val;int ret; + ret =vsc73xx_mdio_busy_check (vsc); +if (ret) +return ret; +/* Setting bit 26 means "read" */ cmd =BIT (26 ) | (phy <<21 ) | (regnum <<16 ); ret =vsc73xx_write (vsc,VSC73XX_BLOCK_MII ,0 ,1 , cmd);if (ret)return ret; -msleep (2 ); + + ret =vsc73xx_mdio_busy_check (vsc); +if (ret) +return ret; + ret =vsc73xx_read (vsc,VSC73XX_BLOCK_MII ,0 ,2 , &val);if (ret)return ret;
@@ -524,6 +555,10 @@ static int vsc73xx_phy_write(struct dsa_switch *ds, int phy, int regnum,u32 cmd;int ret; + ret =vsc73xx_mdio_busy_check (vsc); +if (ret) +return ret; +/* It was found through tedious experiments that this router * chip really hates to have it's PHYs reset. They * never recover if that happens: autonegotiation stops
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 92/321 mlxbf_gige: Remove two unused function declarations
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yue Haibing <[email protected]>
[ Upstream commit 98261be155f8de38f11b6542d4a8935e5532687b ]
Commit f92e1869d74e ("Add Mellanox BlueField Gigabit Ethernet driver") declared but never implemented these.
Stable-dep-of: df934abb185c ("mlxbf_gige: disable RX filters until RX path initialized")
--- drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h | 3 --- 1 file changed, 3 deletions(-)
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +0 -3
@@ -148,9 +148,6 @@ enum mlxbf_gige_res {int mlxbf_gige_mdio_probe (struct platform_device *pdev,struct mlxbf_gige *priv);void mlxbf_gige_mdio_remove (struct mlxbf_gige *priv); -irqreturn_t mlxbf_gige_mdio_handle_phy_interrupt (int irq,void *dev_id); -void mlxbf_gige_mdio_enable_phy_int (struct mlxbf_gige *priv); -void mlxbf_gige_set_mac_rx_filter (struct mlxbf_gige *priv,unsigned int index,u64 dmac); void mlxbf_gige_get_mac_rx_filter(struct mlxbf_gige *priv,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 93/321 mlxbf_gige: disable RX filters until RX path initialized
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Thompson <[email protected]>
[ Upstream commit df934abb185c71c9f2fa07a5013672d0cbd36560 ]
A recent change to the driver exposed a bug where the MAC RX filters (unicast MAC, broadcast MAC, and multicast MAC) are configured and enabled before the RX path is fully initialized. The result of this bug is that after the PHY is started packets that match these MAC RX filters start to flow into the RX FIFO. And then, after rx_init() is completed, these packets will go into the driver RX ring as well. If enough packets are received to fill the RX ring (default size is 128 packets) before the call to request_irq() completes, the driver RX function becomes stuck.
This bug is intermittent but is most likely to be seen where the oob_net0 interface is connected to a busy network with lots of broadcast and multicast traffic.
All the MAC RX filters must be disabled until the RX path is ready, i.e. all initialization is done and all the IRQs are installed.
--- .../ethernet/mellanox/mlxbf_gige/mlxbf_gige.h | 8 +++ .../mellanox/mlxbf_gige/mlxbf_gige_main.c | 10 ++++ .../mellanox/mlxbf_gige/mlxbf_gige_regs.h | 2 + .../mellanox/mlxbf_gige/mlxbf_gige_rx.c | 50 ++++++++++++++++--- 4 files changed, 64 insertions(+), 6 deletions(-)
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige.h +8 -0
@@ -39,6 +39,7 @@*/ #define MLXBF_GIGE_BCAST_MAC_FILTER_IDX 0#define MLXBF_GIGE_LOCAL_MAC_FILTER_IDX 1 +#define MLXBF_GIGE_MAX_FILTER_IDX 3/* Define for broadcast MAC literal */ #define BCAST_MAC_ADDR 0xFFFFFFFFFFFF
@@ -148,6 +149,13 @@ enum mlxbf_gige_res {int mlxbf_gige_mdio_probe (struct platform_device *pdev,struct mlxbf_gige *priv);void mlxbf_gige_mdio_remove (struct mlxbf_gige *priv); + +void mlxbf_gige_enable_multicast_rx (struct mlxbf_gige *priv); +void mlxbf_gige_disable_multicast_rx (struct mlxbf_gige *priv); +void mlxbf_gige_enable_mac_rx_filter (struct mlxbf_gige *priv, +unsigned int index); +void mlxbf_gige_disable_mac_rx_filter (struct mlxbf_gige *priv, +unsigned int index);void mlxbf_gige_set_mac_rx_filter (struct mlxbf_gige *priv,unsigned int index,u64 dmac); void mlxbf_gige_get_mac_rx_filter(struct mlxbf_gige *priv,
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_main.c +10 -0
@@ -168,6 +168,10 @@ static int mlxbf_gige_open(struct net_device *netdev)if (err) goto napi_deinit; +mlxbf_gige_enable_mac_rx_filter (priv,MLXBF_GIGE_BCAST_MAC_FILTER_IDX ); +mlxbf_gige_enable_mac_rx_filter (priv,MLXBF_GIGE_LOCAL_MAC_FILTER_IDX ); +mlxbf_gige_enable_multicast_rx (priv); +/* Set bits in INT_EN that we care about */ int_en =MLXBF_GIGE_INT_EN_HW_ACCESS_ERROR | MLXBF_GIGE_INT_EN_TX_CHECKSUM_INPUTS |
@@ -293,6 +297,7 @@ static int mlxbf_gige_probe(struct platform_device *pdev)void __iomem *plu_base;void __iomem *base;int addr, phy_irq; +unsigned int i;int err; base =devm_platform_ioremap_resource (pdev,MLXBF_GIGE_RES_MAC );
@@ -335,6 +340,11 @@ static int mlxbf_gige_probe(struct platform_device *pdev) priv->rx_q_entries =MLXBF_GIGE_DEFAULT_RXQ_SZ ; priv->tx_q_entries =MLXBF_GIGE_DEFAULT_TXQ_SZ ; +for (i =0 ; i <=MLXBF_GIGE_MAX_FILTER_IDX ; i++) +mlxbf_gige_disable_mac_rx_filter (priv, i); +mlxbf_gige_disable_multicast_rx (priv); +mlxbf_gige_disable_promisc (priv); +/* Write initial MAC address to hardware */ mlxbf_gige_initial_mac (priv);
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_regs.h +2 -0
@@ -59,6 +59,8 @@#define MLXBF_GIGE_TX_STATUS_DATA_FIFO_FULL BIT(1)#define MLXBF_GIGE_RX_MAC_FILTER_DMAC_RANGE_START 0x0520#define MLXBF_GIGE_RX_MAC_FILTER_DMAC_RANGE_END 0x0528 +#define MLXBF_GIGE_RX_MAC_FILTER_GENERAL 0x0530 +#define MLXBF_GIGE_RX_MAC_FILTER_EN_MULTICAST BIT(1)#define MLXBF_GIGE_RX_MAC_FILTER_COUNT_DISC 0x0540#define MLXBF_GIGE_RX_MAC_FILTER_COUNT_DISC_EN BIT(0)#define MLXBF_GIGE_RX_MAC_FILTER_COUNT_PASS 0x0548
drivers/net/ethernet/mellanox/mlxbf_gige/mlxbf_gige_rx.c +44 -6
65 lines not on this page · raw message
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 94/321 mptcp: correct MPTCP_SUBFLOW_ATTR_SSN_OFFSET reserved size
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eugene Syromiatnikov <[email protected]>
[ Upstream commit 655111b838cdabdb604f3625a9ff08c5eedb11da ]
ssn_offset field is u32 and is placed into the netlink response with nla_put_u32(), but only 2 bytes are reserved for the attribute payload in subflow_get_info_size() (even though it makes no difference in the end, as it is aligned up to 4 bytes). Supply the correct argument to the relevant nla_total_size() call to make it less confusing.
--- net/mptcp/diag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/mptcp/diag.c +1 -1
@@ -95,7 +95,7 @@ static size_t subflow_get_info_size(const struct sock *sk)nla_total_size (4 ) +/* MPTCP_SUBFLOW_ATTR_RELWRITE_SEQ */ nla_total_size_64bit (8 ) +/* MPTCP_SUBFLOW_ATTR_MAP_SEQ */ nla_total_size (4 ) +/* MPTCP_SUBFLOW_ATTR_MAP_SFSEQ */ -nla_total_size (2 ) +/* MPTCP_SUBFLOW_ATTR_SSN_OFFSET */ +nla_total_size (4 ) +/* MPTCP_SUBFLOW_ATTR_SSN_OFFSET */ nla_total_size (2 ) +/* MPTCP_SUBFLOW_ATTR_MAP_DATALEN */ nla_total_size (4 ) +/* MPTCP_SUBFLOW_ATTR_FLAGS */ nla_total_size(1) + /* MPTCP_SUBFLOW_ATTR_ID_REM */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 95/321 netfilter: allow ipv6 fragments to arrive on different devices
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tom Hughes <[email protected]>
[ Upstream commit 3cd740b985963f874a1a094f1969e998b9d05554 ]
Commit 264640fc2c5f4 ("ipv6: distinguish frag queues by device for multicast and link-local packets") modified the ipv6 fragment reassembly logic to distinguish frag queues by device for multicast and link-local packets but in fact only the main reassembly code limits the use of the device to those address types and the netfilter reassembly code uses the device for all packets.
This means that if fragments of a packet arrive on different interfaces then netfilter will fail to reassemble them and the fragments will be expired without going any further through the filters.
--- net/ipv6/netfilter/nf_conntrack_reasm.c | 4 ++++ 1 file changed, 4 insertions(+)
net/ipv6/netfilter/nf_conntrack_reasm.c +4 -0
@@ -154,6 +154,10 @@ static struct frag_queue *fq_find(struct net *net, __be32 id, u32 user, };struct inet_frag_queue *q; +if (!(ipv6_addr_type (&hdr->daddr) & (IPV6_ADDR_MULTICAST | +IPV6_ADDR_LINKLOCAL ))) + key.iif =0 ; + q =inet_frag_find (nf_frag->fqdir, &key);if (!q)return NULL ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 96/321 netfilter: flowtable: initialise extack before use
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Donald Hunter <[email protected]>
[ Upstream commit e9767137308daf906496613fd879808a07f006a2 ]
Fix missing initialisation of extack in flow offload.
--- net/netfilter/nf_flow_table_offload.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/nf_flow_table_offload.c +1 -1
@@ -841,8 +841,8 @@ static int nf_flow_offload_tuple(struct nf_flowtable *flowtable, struct list_head *block_cb_list) {struct flow_cls_offload cls_flow = {}; +struct netlink_ext_ack extack = {};struct flow_block_cb *block_cb; -struct netlink_ext_ack extack;__be16 proto =ETH_P_ALL ;int err, i =0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 97/321 netfilter: nf_queue: drop packets with cloned unconfirmed conntracks
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
[ Upstream commit 7d8dc1c7be8d3509e8f5164dd5df64c8e34d7eeb ]
Conntrack assumes an unconfirmed entry (not yet committed to global hash table) has a refcount of 1 and is not visible to other cores.
With multicast forwarding this assumption breaks down because such skbs get cloned after being picked up, i.e. ct->use refcount is > 1.
Likewise, bridge netfilter will clone broad/mutlicast frames and all frames in case they need to be flood-forwarded during learning phase.
For ip multicast forwarding or plain bridge flood-forward this will "work" because packets don't leave softirq and are implicitly serialized.
With nfqueue this no longer holds true, the packets get queued and can be reinjected in arbitrary ways.
Disable this feature, I see no other solution.
After this patch, nfqueue cannot queue packets except the last multicast/broadcast packet.
--- net/bridge/br_netfilter_hooks.c | 6 +++++- net/netfilter/nfnetlink_queue.c | 35 +++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 3 deletions(-)
net/bridge/br_netfilter_hooks.c +5 -1
@@ -618,8 +618,12 @@ static unsigned int br_nf_local_in(void *priv,if (likely (nf_ct_is_confirmed (ct)))return NF_ACCEPT ; +if (WARN_ON_ONCE (refcount_read (&nfct->use) !=1 )) { +nf_reset_ct (skb); +return NF_ACCEPT ; + } +WARN_ON_ONCE (skb_shared (skb)); -WARN_ON_ONCE (refcount_read (&nfct->use) !=1 );/* We can't call nf_confirm here, it would create a dependency * on nf_conntrack module.
net/netfilter/nfnetlink_queue.c +33 -2
@@ -647,10 +647,41 @@ static bool nf_ct_drop_unconfirmed(const struct nf_queue_entry *entry) {#if IS_ENABLED (CONFIG_NF_CONNTRACK )static const unsigned long flags =IPS_CONFIRMED |IPS_DYING ; -const struct nf_conn *ct = (void *)skb_nfct (entry->skb); +struct nf_conn *ct = (void *)skb_nfct (entry->skb); +unsigned long status; +unsigned int use; -if (ct && ((ct->status & flags) ==IPS_DYING )) +if (!ct) +return false; + + status =READ_ONCE (ct->status); +if ((status & flags) ==IPS_DYING )return true; + +if (status &IPS_CONFIRMED ) +return false; + +/* in some cases skb_clone() can occur after initial conntrack +* pickup, but conntrack assumes exclusive skb->_nfct ownership for +* unconfirmed entries. +* +* This happens for br_netfilter and with ip multicast routing. +* We can't be solved with serialization here because one clone could +* have been queued for local delivery. +*/ + use =refcount_read (&ct->ct_general.use); +if (likely (use ==1 )) +return false; + +/* Can't decrement further? Exclusive ownership. */ +if (!refcount_dec_not_one (&ct->ct_general.use)) +return false; + +skb_set_nfct (entry->skb,0 ); +/* No nf_ct_put(): we already decremented .use and it cannot +* drop down to 0. +*/ +return true;#endif return false; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 98/321 netfilter: nf_tables: Audit log dump reset after the fact
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phil Sutter <[email protected]>
[ Upstream commit e0b6648b0446e59522819c75ba1dcb09e68d3e94 ]
In theory, dumpreset may fail and invalidate the preceeding log message. Fix this and use the occasion to prepare for object reset locking, which benefits from a few unrelated changes:
* Add an early call to nfnetlink_unicast if not resetting which effectively skips the audit logging but also unindents it.
* Extract the table's name from the netlink attribute (which is verified via earlier table lookup) to not rely upon validity of the looked up table pointer.
* Do not use local variable family, it will vanish.
--- net/netfilter/nf_tables_api.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-)
net/netfilter/nf_tables_api.c +13 -15
@@ -7531,6 +7531,7 @@ static int nf_tables_dump_obj_done(struct netlink_callback *cb)static int nf_tables_getobj (struct sk_buff *skb,const struct nfnl_info *info,const struct nlattr *const nla[]) { +const struct nftables_pernet *nft_net =nft_pernet (info->net);struct netlink_ext_ack *extack = info->extack;u8 genmask =nft_genmask_cur (info->net);u8 family = info->nfmsg->nfgen_family;
@@ -7540,6 +7541,7 @@ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,struct sk_buff *skb2;bool reset = false;u32 objtype; +char *buf;int err;if (info->nlh->nlmsg_flags &NLM_F_DUMP ) {
@@ -7578,27 +7580,23 @@ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,if (NFNL_MSG_TYPE (info->nlh->nlmsg_type) ==NFT_MSG_GETOBJ_RESET ) reset = true; -if (reset) { -const struct nftables_pernet *nft_net; -char *buf; - - nft_net =nft_pernet (net); - buf =kasprintf (GFP_ATOMIC ,"%s:%u" , table->name, nft_net->base_seq); - -audit_log_nfcfg (buf, - family, -1 , -AUDIT_NFT_OP_OBJ_RESET , -GFP_ATOMIC ); -kfree (buf); - } - err =nf_tables_fill_obj_info (skb2, net,NETLINK_CB (skb).portid, info->nlh->nlmsg_seq,NFT_MSG_NEWOBJ ,0 , family, table, obj, reset);if (err <0 ) goto err_fill_obj_info; +if (!reset) +return nfnetlink_unicast (skb2, net,NETLINK_CB (skb).portid); + + buf =kasprintf (GFP_ATOMIC ,"%.*s:%u" , +nla_len (nla[NFTA_OBJ_TABLE ]), + (char *)nla_data (nla[NFTA_OBJ_TABLE ]), + nft_net->base_seq); +audit_log_nfcfg (buf, info->nfmsg->nfgen_family,1 , +AUDIT_NFT_OP_OBJ_RESET ,GFP_ATOMIC ); +kfree (buf); +return nfnetlink_unicast (skb2, net,NETLINK_CB (skb).portid); err_fill_obj_info:
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 99/321 netfilter: nf_tables: Drop pointless memset in nf_tables_dump_obj
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phil Sutter <[email protected]>
[ Upstream commit ff16111cc10c82ee065ffbd9fa8d6210394ff8c6 ]
The code does not make use of cb->args fields past the first one, no need to zero them.
Stable-dep-of: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
--- net/netfilter/nf_tables_api.c | 3 --- 1 file changed, 3 deletions(-)
net/netfilter/nf_tables_api.c +0 -3
@@ -7452,9 +7452,6 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) goto cont;if (idx < s_idx) goto cont; -if (idx > s_idx) -memset (&cb->args[1 ],0 , -sizeof (cb->args) -sizeof (cb->args[0 ]));if (filter && filter->table &&strcmp (filter->table, table->name)) goto cont;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 100/321 netfilter: nf_tables: Unconditionally allocate nft_obj_filter
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phil Sutter <[email protected]>
[ Upstream commit 4279cc60b354d2d2b970655a70a151cbfa1d958b ]
Prep work for moving the filter into struct netlink_callback's scratch area.
Stable-dep-of: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
--- net/netfilter/nf_tables_api.c | 36 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 21 deletions(-)
net/netfilter/nf_tables_api.c +15 -21
@@ -7452,11 +7452,9 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) goto cont;if (idx < s_idx) goto cont; -if (filter && filter->table && -strcmp (filter->table, table->name)) +if (filter->table &&strcmp (filter->table, table->name)) goto cont; -if (filter && - filter->type !=NFT_OBJECT_UNSPEC && +if (filter->type !=NFT_OBJECT_UNSPEC && obj->ops->type->type != filter->type) goto cont;
@@ -7491,23 +7489,21 @@ static int nf_tables_dump_obj_start(struct netlink_callback *cb)const struct nlattr *const *nla = cb->data;struct nft_obj_filter *filter =NULL ; -if (nla[NFTA_OBJ_TABLE ] || nla[NFTA_OBJ_TYPE ]) { - filter =kzalloc (sizeof (*filter),GFP_ATOMIC ); -if (!filter) -return -ENOMEM ; + filter =kzalloc (sizeof (*filter),GFP_ATOMIC ); +if (!filter) +return -ENOMEM ; -if (nla[NFTA_OBJ_TABLE ]) { - filter->table =nla_strdup (nla[NFTA_OBJ_TABLE ],GFP_ATOMIC ); -if (!filter->table) { -kfree (filter); -return -ENOMEM ; - } +if (nla[NFTA_OBJ_TABLE ]) { + filter->table =nla_strdup (nla[NFTA_OBJ_TABLE ],GFP_ATOMIC ); +if (!filter->table) { +kfree (filter); +return -ENOMEM ; } - -if (nla[NFTA_OBJ_TYPE ]) - filter->type =ntohl (nla_get_be32 (nla[NFTA_OBJ_TYPE ])); } +if (nla[NFTA_OBJ_TYPE ]) + filter->type =ntohl (nla_get_be32 (nla[NFTA_OBJ_TYPE ])); + cb->data = filter;return 0 ; }
@@ -7516,10 +7512,8 @@ static int nf_tables_dump_obj_done(struct netlink_callback *cb) {struct nft_obj_filter *filter = cb->data; -if (filter) { -kfree (filter->table); -kfree (filter); - } +kfree (filter->table); +kfree (filter);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 101/321 netfilter: nf_tables: A better name for nft_obj_filter
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phil Sutter <[email protected]>
[ Upstream commit ecf49cad807061d880bea27a5da8e0114ddc7690 ]
Name it for what it is supposed to become, a real nft_obj_dump_ctx. No functional change intended.
Stable-dep-of: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
--- net/netfilter/nf_tables_api.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-)
net/netfilter/nf_tables_api.c +16 -16
@@ -7416,7 +7416,7 @@ static void audit_log_obj_reset(const struct nft_table *table,kfree (buf); } -struct nft_obj_filter { +struct nft_obj_dump_ctx {char *table;u32 type; };
@@ -7426,7 +7426,7 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)const struct nfgenmsg *nfmsg =nlmsg_data (cb->nlh);const struct nft_table *table;unsigned int idx =0 , s_idx = cb->args[0 ]; -struct nft_obj_filter *filter = cb->data; +struct nft_obj_dump_ctx *ctx = cb->data;struct net *net =sock_net (skb->sk);int family = nfmsg->nfgen_family;struct nftables_pernet *nft_net;
@@ -7452,10 +7452,10 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) goto cont;if (idx < s_idx) goto cont; -if (filter->table &&strcmp (filter->table, table->name)) +if (ctx->table &&strcmp (ctx->table, table->name)) goto cont; -if (filter->type !=NFT_OBJECT_UNSPEC && - obj->ops->type->type != filter->type) +if (ctx->type !=NFT_OBJECT_UNSPEC && + obj->ops->type->type != ctx->type) goto cont; rc = nf_tables_fill_obj_info(skb, net,
@@ -7487,33 +7487,33 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)static int nf_tables_dump_obj_start (struct netlink_callback *cb) {const struct nlattr *const *nla = cb->data; -struct nft_obj_filter *filter =NULL ; +struct nft_obj_dump_ctx *ctx =NULL ; - filter =kzalloc (sizeof (*filter),GFP_ATOMIC ); -if (!filter) + ctx =kzalloc (sizeof (*ctx),GFP_ATOMIC ); +if (!ctx)return -ENOMEM ;if (nla[NFTA_OBJ_TABLE ]) { - filter->table =nla_strdup (nla[NFTA_OBJ_TABLE ],GFP_ATOMIC ); -if (!filter->table) { -kfree (filter); + ctx->table =nla_strdup (nla[NFTA_OBJ_TABLE ],GFP_ATOMIC ); +if (!ctx->table) { +kfree (ctx);return -ENOMEM ; } }if (nla[NFTA_OBJ_TYPE ]) - filter->type =ntohl (nla_get_be32 (nla[NFTA_OBJ_TYPE ])); + ctx->type =ntohl (nla_get_be32 (nla[NFTA_OBJ_TYPE ])); - cb->data = filter; + cb->data = ctx;return 0 ; }static int nf_tables_dump_obj_done (struct netlink_callback *cb) { -struct nft_obj_filter *filter = cb->data; +struct nft_obj_dump_ctx *ctx = cb->data; -kfree (filter->table); -kfree (filter); +kfree (ctx->table); +kfree (ctx);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 102/321 netfilter: nf_tables: Carry s_idx in nft_obj_dump_ctx
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phil Sutter <[email protected]>
[ Upstream commit 2eda95cfa2fc43bcb21a801dc1d16a0b7cc73860 ]
Prep work for moving the context into struct netlink_callback scratch area.
Stable-dep-of: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
--- net/netfilter/nf_tables_api.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
net/netfilter/nf_tables_api.c +5 -4
@@ -7417,6 +7417,7 @@ static void audit_log_obj_reset(const struct nft_table *table, }struct nft_obj_dump_ctx { +unsigned int s_idx;char *table;u32 type; };
@@ -7424,14 +7425,14 @@ struct nft_obj_dump_ctx {static int nf_tables_dump_obj (struct sk_buff *skb,struct netlink_callback *cb) {const struct nfgenmsg *nfmsg =nlmsg_data (cb->nlh); -const struct nft_table *table; -unsigned int idx =0 , s_idx = cb->args[0 ];struct nft_obj_dump_ctx *ctx = cb->data;struct net *net =sock_net (skb->sk);int family = nfmsg->nfgen_family;struct nftables_pernet *nft_net; +const struct nft_table *table;unsigned int entries =0 ;struct nft_object *obj; +unsigned int idx =0 ;bool reset = false;int rc =0 ;
@@ -7450,7 +7451,7 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)list_for_each_entry_rcu (obj, &table->objects, list) {if (!nft_is_active (net, obj)) goto cont; -if (idx < s_idx) +if (idx < ctx->s_idx) goto cont;if (ctx->table &&strcmp (ctx->table, table->name)) goto cont;
@@ -7480,7 +7481,7 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) }rcu_read_unlock (); - cb->args[0 ] = idx; + ctx->s_idx = idx;return skb->len; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 103/321 netfilter: nf_tables: nft_obj_filter fits into cb->ctx
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phil Sutter <[email protected]>
[ Upstream commit 5a893b9cdf6fa5758f43d323a1d7fa6d1bf489ff ]
No need to allocate it if one may just use struct netlink_callback's scratch area for it.
Stable-dep-of: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
--- net/netfilter/nf_tables_api.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-)
net/netfilter/nf_tables_api.c +5 -11
@@ -7425,7 +7425,7 @@ struct nft_obj_dump_ctx {static int nf_tables_dump_obj (struct sk_buff *skb,struct netlink_callback *cb) {const struct nfgenmsg *nfmsg =nlmsg_data (cb->nlh); -struct nft_obj_dump_ctx *ctx = cb->data; +struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;struct net *net =sock_net (skb->sk);int family = nfmsg->nfgen_family;struct nftables_pernet *nft_net;
@@ -7487,34 +7487,28 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)static int nf_tables_dump_obj_start (struct netlink_callback *cb) { +struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;const struct nlattr *const *nla = cb->data; -struct nft_obj_dump_ctx *ctx =NULL ; - ctx =kzalloc (sizeof (*ctx),GFP_ATOMIC ); -if (!ctx) -return -ENOMEM ; +BUILD_BUG_ON (sizeof (*ctx) >sizeof (cb->ctx));if (nla[NFTA_OBJ_TABLE ]) { ctx->table =nla_strdup (nla[NFTA_OBJ_TABLE ],GFP_ATOMIC ); -if (!ctx->table) { -kfree (ctx); +if (!ctx->table)return -ENOMEM ; - } }if (nla[NFTA_OBJ_TYPE ]) ctx->type =ntohl (nla_get_be32 (nla[NFTA_OBJ_TYPE ])); - cb->data = ctx;return 0 ; }static int nf_tables_dump_obj_done (struct netlink_callback *cb) { -struct nft_obj_dump_ctx *ctx = cb->data; +struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;kfree (ctx->table); -kfree (ctx);return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 104/321 netfilter: nf_tables: Carry reset boolean in nft_obj_dump_ctx
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phil Sutter <[email protected]>
[ Upstream commit a552339063d37b3b1133d9dfc31f851edafb27bb ]
Relieve the dump callback from having to inspect nlmsg_type upon each call, just do it once at start of the dump.
Stable-dep-of: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
--- net/netfilter/nf_tables_api.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
net/netfilter/nf_tables_api.c +6 -6
@@ -7420,6 +7420,7 @@ struct nft_obj_dump_ctx {unsigned int s_idx;char *table;u32 type; +bool reset; };static int nf_tables_dump_obj (struct sk_buff *skb,struct netlink_callback *cb)
@@ -7433,12 +7434,8 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)unsigned int entries =0 ;struct nft_object *obj;unsigned int idx =0 ; -bool reset = false;int rc =0 ; -if (NFNL_MSG_TYPE (cb->nlh->nlmsg_type) ==NFT_MSG_GETOBJ_RESET ) - reset = true; -rcu_read_lock (); nft_net =nft_pernet (net); cb->seq =READ_ONCE (nft_net->base_seq);
@@ -7465,7 +7462,7 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)NFT_MSG_NEWOBJ ,NLM_F_MULTI |NLM_F_APPEND , table->family, table, - obj, reset); + obj, ctx->reset);if (rc <0 )break ;
@@ -7474,7 +7471,7 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb) cont: idx++; } -if (reset && entries) +if (ctx->reset && entries)audit_log_obj_reset (table, nft_net->base_seq, entries);if (rc <0 )break ;
@@ -7501,6 +7498,9 @@ static int nf_tables_dump_obj_start(struct netlink_callback *cb)if (nla[NFTA_OBJ_TYPE ]) ctx->type =ntohl (nla_get_be32 (nla[NFTA_OBJ_TYPE ])); +if (NFNL_MSG_TYPE (cb->nlh->nlmsg_type) ==NFT_MSG_GETOBJ_RESET ) + ctx->reset = true; +return 0 ; }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 105/321 netfilter: nf_tables: Introduce nf_tables_getobj_single
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phil Sutter <[email protected]>
[ Upstream commit 69fc3e9e90f1afc11f4015e6b75d18ab9acee348 ]
Outsource the reply skb preparation for non-dump getrule requests into a distinct function. Prep work for object reset locking.
Stable-dep-of: bd662c4218f9 ("netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests")
--- net/netfilter/nf_tables_api.c | 75 ++++++++++++++++++++--------------- 1 file changed, 44 insertions(+), 31 deletions(-)
net/netfilter/nf_tables_api.c +44 -31
@@ -7514,10 +7514,10 @@ static int nf_tables_dump_obj_done(struct netlink_callback *cb) }/* called with rcu_read_lock held */ -static int nf_tables_getobj (struct sk_buff *skb,const struct nfnl_info *info, -const struct nlattr *const nla[]) +static struct sk_buff * +nf_tables_getobj_single (u32 portid,const struct nfnl_info *info, +const struct nlattr *const nla[],bool reset) { -const struct nftables_pernet *nft_net =nft_pernet (info->net);struct netlink_ext_ack *extack = info->extack;u8 genmask =nft_genmask_cur (info->net);u8 family = info->nfmsg->nfgen_family;
@@ -7525,52 +7525,69 @@ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,struct net *net = info->net;struct nft_object *obj;struct sk_buff *skb2; -bool reset = false;u32 objtype; -char *buf;int err; -if (info->nlh->nlmsg_flags &NLM_F_DUMP ) { -struct netlink_dump_control c = { - .start = nf_tables_dump_obj_start, - .dump = nf_tables_dump_obj, - .done = nf_tables_dump_obj_done, - .module =THIS_MODULE , - .data = (void *)nla, - }; - -return nft_netlink_dump_start_rcu (info->sk, skb, info->nlh, &c); - } -if (!nla[NFTA_OBJ_NAME ] || !nla[NFTA_OBJ_TYPE ]) -return -EINVAL ; +return ERR_PTR (-EINVAL ); table =nft_table_lookup (net, nla[NFTA_OBJ_TABLE ], family, genmask,0 );if (IS_ERR (table)) {NL_SET_BAD_ATTR (extack, nla[NFTA_OBJ_TABLE ]); -return PTR_ERR (table); +return ERR_CAST (table); } objtype =ntohl (nla_get_be32 (nla[NFTA_OBJ_TYPE ])); obj =nft_obj_lookup (net, table, nla[NFTA_OBJ_NAME ], objtype, genmask);if (IS_ERR (obj)) {NL_SET_BAD_ATTR (extack, nla[NFTA_OBJ_NAME ]); -return PTR_ERR (obj); +return ERR_CAST (obj); } skb2 =alloc_skb (NLMSG_GOODSIZE ,GFP_ATOMIC );if (!skb2) -return -ENOMEM ; +return ERR_PTR (-ENOMEM ); + + err =nf_tables_fill_obj_info (skb2, net, portid, + info->nlh->nlmsg_seq,NFT_MSG_NEWOBJ ,0 , + family, table, obj, reset); +if (err <0 ) { +kfree_skb (skb2); +return ERR_PTR (err); + } + +return skb2; +} + +static int nf_tables_getobj (struct sk_buff *skb,const struct nfnl_info *info, +const struct nlattr *const nla[]) +{ +struct nftables_pernet *nft_net =nft_pernet (info->net); +u32 portid =NETLINK_CB (skb).portid; +struct net *net = info->net; +struct sk_buff *skb2; +bool reset = false; +char *buf; + +if (info->nlh->nlmsg_flags &NLM_F_DUMP ) { +struct netlink_dump_control c = { + .start = nf_tables_dump_obj_start, + .dump = nf_tables_dump_obj, + .done = nf_tables_dump_obj_done, + .module =THIS_MODULE , + .data = (void *)nla, + }; + +return nft_netlink_dump_start_rcu (info->sk, skb, info->nlh, &c); + }if (NFNL_MSG_TYPE (info->nlh->nlmsg_type) ==NFT_MSG_GETOBJ_RESET ) reset = true; - err =nf_tables_fill_obj_info (skb2, net,NETLINK_CB (skb).portid, - info->nlh->nlmsg_seq,NFT_MSG_NEWOBJ ,0 , - family, table, obj, reset); -if (err <0 ) - goto err_fill_obj_info; + skb2 =nf_tables_getobj_single (portid, info, nla, reset); +if (IS_ERR (skb2)) +return PTR_ERR (skb2);if (!reset)return nfnetlink_unicast (skb2, net,NETLINK_CB (skb).portid);
@@ -7583,11 +7600,7 @@ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info, AUDIT_NFT_OP_OBJ_RESET, GFP_ATOMIC);kfree (buf); -return nfnetlink_unicast (skb2, net,NETLINK_CB (skb).portid); - -err_fill_obj_info: -kfree_skb (skb2); -return err; +return nfnetlink_unicast (skb2, net, portid); }static void nft_obj_destroy (const struct nft_ctx *ctx,struct nft_object *obj)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 106/321 netfilter: nf_tables: Add locking for NFT_MSG_GETOBJ_RESET requests
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Phil Sutter <[email protected]>
[ Upstream commit bd662c4218f9648e888bebde9468146965f3f8a0 ]
Objects' dump callbacks are not concurrency-safe per-se with reset bit set. If two CPUs perform a reset at the same time, at least counter and quota objects suffer from value underrun.
Prevent this by introducing dedicated locking callbacks for nfnetlink and the asynchronous dump handling to serialize access.
--- net/netfilter/nf_tables_api.c | 72 ++++++++++++++++++++++++++++------- 1 file changed, 59 insertions(+), 13 deletions(-)
net/netfilter/nf_tables_api.c +59 -13
@@ -7482,6 +7482,19 @@ static int nf_tables_dump_obj(struct sk_buff *skb, struct netlink_callback *cb)return skb->len; } +static int nf_tables_dumpreset_obj (struct sk_buff *skb, +struct netlink_callback *cb) +{ +struct nftables_pernet *nft_net =nft_pernet (sock_net (skb->sk)); +int ret; + +mutex_lock (&nft_net->commit_mutex); + ret =nf_tables_dump_obj (skb, cb); +mutex_unlock (&nft_net->commit_mutex); + +return ret; +} +static int nf_tables_dump_obj_start (struct netlink_callback *cb) {struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;
@@ -7498,12 +7511,18 @@ static int nf_tables_dump_obj_start(struct netlink_callback *cb)if (nla[NFTA_OBJ_TYPE ]) ctx->type =ntohl (nla_get_be32 (nla[NFTA_OBJ_TYPE ])); -if (NFNL_MSG_TYPE (cb->nlh->nlmsg_type) ==NFT_MSG_GETOBJ_RESET ) - ctx->reset = true; -return 0 ; } +static int nf_tables_dumpreset_obj_start (struct netlink_callback *cb) +{ +struct nft_obj_dump_ctx *ctx = (void *)cb->ctx; + + ctx->reset = true; + +return nf_tables_dump_obj_start (cb); +} +static int nf_tables_dump_obj_done (struct netlink_callback *cb) {struct nft_obj_dump_ctx *ctx = (void *)cb->ctx;
@@ -7562,18 +7581,43 @@ nf_tables_getobj_single(u32 portid, const struct nfnl_info *info,static int nf_tables_getobj (struct sk_buff *skb,const struct nfnl_info *info,const struct nlattr *const nla[]) +{ +u32 portid =NETLINK_CB (skb).portid; +struct sk_buff *skb2; + +if (info->nlh->nlmsg_flags &NLM_F_DUMP ) { +struct netlink_dump_control c = { + .start = nf_tables_dump_obj_start, + .dump = nf_tables_dump_obj, + .done = nf_tables_dump_obj_done, + .module =THIS_MODULE , + .data = (void *)nla, + }; + +return nft_netlink_dump_start_rcu (info->sk, skb, info->nlh, &c); + } + + skb2 =nf_tables_getobj_single (portid, info, nla, false); +if (IS_ERR (skb2)) +return PTR_ERR (skb2); + +return nfnetlink_unicast (skb2, info->net, portid); +} + +static int nf_tables_getobj_reset (struct sk_buff *skb, +const struct nfnl_info *info, +const struct nlattr *const nla[]) {struct nftables_pernet *nft_net =nft_pernet (info->net);u32 portid =NETLINK_CB (skb).portid;struct net *net = info->net;struct sk_buff *skb2; -bool reset = false;char *buf;if (info->nlh->nlmsg_flags &NLM_F_DUMP ) {struct netlink_dump_control c = { - .start = nf_tables_dump_obj_start, - .dump = nf_tables_dump_obj, + .start = nf_tables_dumpreset_obj_start, + .dump = nf_tables_dumpreset_obj, .done = nf_tables_dump_obj_done, .module =THIS_MODULE , .data = (void *)nla,
@@ -7582,16 +7626,18 @@ static int nf_tables_getobj(struct sk_buff *skb, const struct nfnl_info *info,return nft_netlink_dump_start_rcu (info->sk, skb, info->nlh, &c); } -if (NFNL_MSG_TYPE (info->nlh->nlmsg_type) ==NFT_MSG_GETOBJ_RESET ) - reset = true; +if (!try_module_get (THIS_MODULE )) +return -EINVAL ; +rcu_read_unlock (); +mutex_lock (&nft_net->commit_mutex); + skb2 =nf_tables_getobj_single (portid, info, nla, true); +mutex_unlock (&nft_net->commit_mutex); +rcu_read_lock (); +module_put (THIS_MODULE ); - skb2 =nf_tables_getobj_single (portid, info, nla, reset);if (IS_ERR (skb2))return PTR_ERR (skb2); -if (!reset) -return nfnetlink_unicast (skb2, net,NETLINK_CB (skb).portid); - buf = kasprintf(GFP_ATOMIC, "%.*s:%u", nla_len(nla[NFTA_OBJ_TABLE]), (char *)nla_data(nla[NFTA_OBJ_TABLE]),
@@ -8807,7 +8853,7 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { .policy = nft_obj_policy, }, [NFT_MSG_GETOBJ_RESET] = { - .call = nf_tables_getobj, + .call = nf_tables_getobj_reset, .type = NFNL_CB_RCU, .attr_count = NFTA_OBJ_MAX, .policy = nft_obj_policy,
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 107/321 net: hns3: fix wrong use of semaphore up
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jie Wang <[email protected]>
[ Upstream commit 8445d9d3c03101859663d34fda747f6a50947556 ]
Currently, if hns3 PF or VF FLR reset failed after five times retry, the reset done process will directly release the semaphore which has already released in hclge_reset_prepare_general. This will cause down operation fail.
So this patch fixes it by adding reset state judgement. The up operation is only called after successful PF FLR reset.
--- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 4 ++-- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +2 -2
@@ -11538,8 +11538,8 @@ static void hclge_reset_done(struct hnae3_ae_dev *ae_dev)dev_err (&hdev->pdev->dev,"fail to rebuild, ret=%d\n" , ret); hdev->reset_type =HNAE3_NONE_RESET ; -clear_bit (HCLGE_STATE_RST_HANDLING , &hdev->state); -up (&hdev->reset_sem); +if (test_and_clear_bit (HCLGE_STATE_RST_HANDLING , &hdev->state)) +up (&hdev->reset_sem); }static void hclge_clear_resetting_state (struct hclge_dev *hdev)
drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +2 -2
@@ -1764,8 +1764,8 @@ static void hclgevf_reset_done(struct hnae3_ae_dev *ae_dev) ret); hdev->reset_type =HNAE3_NONE_RESET ; -clear_bit (HCLGEVF_STATE_RST_HANDLING , &hdev->state); -up (&hdev->reset_sem); +if (test_and_clear_bit (HCLGEVF_STATE_RST_HANDLING , &hdev->state)) +up (&hdev->reset_sem); }static u32 hclgevf_get_fw_version (struct hnae3_handle *handle)
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 108/321 net: hns3: use the users cfg after reset
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Peiyang Wang <[email protected]>
[ Upstream commit 30545e17eac1f50c5ef49644daf6af205100a965 ]
Consider the followed case that the user change speed and reset the net interface. Before the hw change speed successfully, the driver get old old speed from hw by timer task. After reset, the previous speed is config to hw. As a result, the new speed is configed successfully but lost after PF reset. The followed pictured shows more dirrectly.
+------+ +----+ +----+
| USER | | PF | | HW |
+---+--+ +-+--+ +-+--+
| ethtool -s 100G | |
+------------------>| set speed 100G |
| +--------------------->|
| | set successfully |
| |<---------------------+---+
| |query cfg (timer task)| |
| +--------------------->| | handle speed
| | return 200G | | changing event
| ethtool --reset |<---------------------+ | (100G)
+------------------>| cfg previous speed |<--+
| | after reset (200G) |
| +--------------------->|
| | +---+
| |query cfg (timer task)| |
| +--------------------->| | handle speed
| | return 100G | | changing event
| |<---------------------+ | (200G)
| | |<--+
| |query cfg (timer task)|
| +--------------------->|
| | return 200G |
| |<---------------------+
| | |
v v vThis patch save new speed if hw change speed successfully, which will be used after reset successfully.
--- .../hisilicon/hns3/hns3pf/hclge_main.c | 24 ++++++++++++++----- .../hisilicon/hns3/hns3pf/hclge_mdio.c | 3 +++ 2 files changed, 21 insertions(+), 6 deletions(-)
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +18 -6
@@ -2696,8 +2696,17 @@ static int hclge_cfg_mac_speed_dup_h(struct hnae3_handle *handle, int speed, {struct hclge_vport *vport =hclge_get_vport (handle);struct hclge_dev *hdev = vport->back; +int ret; + + ret =hclge_cfg_mac_speed_dup (hdev, speed, duplex, lane_num); -return hclge_cfg_mac_speed_dup (hdev, speed, duplex, lane_num); +if (ret) +return ret; + + hdev->hw.mac.req_speed = speed; + hdev->hw.mac.req_duplex = duplex; + +return 0 ; }static int hclge_set_autoneg_en (struct hclge_dev *hdev,bool enable)
@@ -2999,17 +3008,20 @@ static int hclge_mac_init(struct hclge_dev *hdev)if (!test_bit (HCLGE_STATE_RST_HANDLING , &hdev->state)) hdev->hw.mac.duplex =HCLGE_MAC_FULL ; - ret =hclge_cfg_mac_speed_dup_hw (hdev, hdev->hw.mac.speed, - hdev->hw.mac.duplex, hdev->hw.mac.lane_num); -if (ret) -return ret; -if (hdev->hw.mac.support_autoneg) { ret =hclge_set_autoneg_en (hdev, hdev->hw.mac.autoneg);if (ret)return ret; } +if (!hdev->hw.mac.autoneg) { + ret =hclge_cfg_mac_speed_dup_hw (hdev, hdev->hw.mac.req_speed, + hdev->hw.mac.req_duplex, + hdev->hw.mac.lane_num); +if (ret) +return ret; + } + mac->link =0 ;if (mac->user_fec_mode &BIT (HNAE3_FEC_USER_DEF )) {
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c +3 -0
@@ -191,6 +191,9 @@ static void hclge_mac_adjust_link(struct net_device *netdev)if (ret)netdev_err (netdev,"failed to adjust link.\n" ); + hdev->hw.mac.req_speed = (u32 )speed; + hdev->hw.mac.req_duplex = (u8 )duplex; + ret =hclge_cfg_flowctrl (hdev);if (ret)netdev_err (netdev,"failed to configure flow control.\n" );
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 109/321 net: hns3: fix a deadlock problem when config TC during resetting
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jie Wang <[email protected]>
[ Upstream commit be5e816d00a506719e9dbb1a9c861c5ced30a109 ]
When config TC during the reset process, may cause a deadlock, the flow is as below:
pf reset start
│
▼
......
setup tc │
│ ▼
▼ DOWN: napi_disable()
napi_disable()(skip) │
│ │
▼ ▼
...... ......
│ │
▼ │
napi_enable() │
▼
UINIT: netif_napi_del()
│
▼
......
│
▼
INIT: netif_napi_add()
│
▼
...... global reset start
│ │
▼ ▼
UP: napi_enable()(skip) ......
│ │
▼ ▼
...... napi_disable()In reset process, the driver will DOWN the port and then UINIT, in this case, the setup tc process will UP the port before UINIT, so cause the problem. Adds a DOWN process in UINIT to fix it.
--- drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +3 -0
@@ -5728,6 +5728,9 @@ static int hns3_reset_notify_uninit_enet(struct hnae3_handle *handle)struct net_device *netdev = handle->kinfo.netdev;struct hns3_nic_priv *priv =netdev_priv (netdev); +if (!test_bit (HNS3_NIC_STATE_DOWN , &priv->state)) +hns3_nic_net_stop (netdev); +if (!test_and_clear_bit (HNS3_NIC_STATE_INITED , &priv->state)) {netdev_warn (netdev,"already uninitialized\n" );return 0 ;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 110/321 ALSA: hda/realtek: Fix noise from speakers on Lenovo IdeaPad 3 15IAU7
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Parsa Poorshikhian <[email protected]>
[ Upstream commit ef9718b3d54e822de294351251f3a574f8a082ce ]
Fix noise from speakers connected to AUX port when no sound is playing. The problem occurs because the alc_shutup_pins function includes a 0x10ec0257 vendor ID, which causes noise on Lenovo IdeaPad 3 15IAU7 with Realtek ALC257 codec when no sound is playing.
Removing this vendor ID from the function fixes the bug.
--- sound/pci/hda/patch_realtek.c | 1 - 1 file changed, 1 deletion(-)
sound/pci/hda/patch_realtek.c +0 -1
@@ -583,7 +583,6 @@ static void alc_shutup_pins(struct hda_codec *codec)switch (codec->core.vendor_id) {case 0x10ec0236 :case 0x10ec0256 : -case 0x10ec0257 :case 0x19e58326 :case 0x10ec0283 :case 0x10ec0285 :
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 111/321 drm/amd/amdgpu/imu_v11_0: Increase buffer size to ensure all possible values can be stored
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lee Jones <[email protected]>
[ Upstream commit a728342ae4ec2a7fdab0038b11427579424f133e ]
Fixes the following W=1 kernel build warning(s):
drivers/gpu/drm/amd/amdgpu/imu_v11_0.c: In function ‘imu_v11_0_init_microcode’:
drivers/gpu/drm/amd/amdgpu/imu_v11_0.c:52:54: warning: ‘_imu.bin’ directive output may be truncated writing 8 bytes into a region of size between 4 and 33 [-Wformat-truncation=] drivers/gpu/drm/amd/amdgpu/imu_v11_0.c:52:9: note: ‘snprintf’ output between 16 and 45 bytes into a destination of size 40
--- drivers/gpu/drm/amd/amdgpu/imu_v11_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/imu_v11_0.c +1 -1
@@ -38,7 +38,7 @@ MODULE_FIRMWARE("amdgpu/gc_11_0_3_imu.bin");static int imu_v11_0_init_microcode (struct amdgpu_device *adev) { -char fw_name[40 ]; +char fw_name[45 ];char ucode_prefix[30 ];int err;const struct imu_firmware_header_v1_0 *imu_hdr;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 112/321 ssb: Fix division by zero issue in ssb_calc_clock_rate
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rand Deeb <[email protected]>
[ Upstream commit e0b5127fa134fe0284d58877b6b3133939c8b3ce ]
In ssb_calc_clock_rate(), there is a potential issue where the value of m1 could be zero due to initialization using clkfactor_f6_resolv(). This situation raised concerns about the possibility of a division by zero error.
We fixed it by following the suggestions provided by Larry Finger <[email protected]> and Michael Büsch <[email protected]>. The fix involves returning a value of 1 instead of 0 in clkfactor_f6_resolv(). This modification ensures the proper functioning of the code and eliminates the risk of division by zero errors.
--- drivers/ssb/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/ssb/main.c +1 -1
@@ -837,7 +837,7 @@ static u32 clkfactor_f6_resolve(u32 v)case SSB_CHIPCO_CLK_F6_7 :return 7 ; } -return 0 ; +return 1 ; }/* Calculate the speed the backplane would run at a given set of clockcontrol values */
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 113/321 wifi: cfg80211: check wiphy mutex is held for wdev mutex
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 1474bc87fe57deac726cc10203f73daa6c3212f7 ]
This might seem pretty pointless rather than changing the locking immediately, but it seems safer to run for a while with checks and the old locking scheme, and then remove the wdev lock later.
--- net/wireless/core.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
net/wireless/core.h +7 -1
@@ -228,6 +228,7 @@ void cfg80211_register_wdev(struct cfg80211_registered_device *rdev,static inline void wdev_lock (struct wireless_dev *wdev)__acquires (wdev) { +lockdep_assert_held (&wdev->wiphy->mtx);mutex_lock (&wdev->mtx);__acquire (wdev->mtx); }
@@ -235,11 +236,16 @@ static inline void wdev_lock(struct wireless_dev *wdev)static inline void wdev_unlock (struct wireless_dev *wdev)__releases (wdev) { +lockdep_assert_held (&wdev->wiphy->mtx);__release (wdev->mtx);mutex_unlock (&wdev->mtx); } -#define ASSERT_WDEV_LOCK (wdev) lockdep_assert_held(&(wdev)->mtx) +static inline void ASSERT_WDEV_LOCK (struct wireless_dev *wdev) +{ +lockdep_assert_held (&wdev->wiphy->mtx); +lockdep_assert_held (&wdev->mtx); +}static inline bool cfg80211_has_monitors_only (struct cfg80211_registered_device *rdev) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 114/321 wifi: mac80211: fix BA session teardown race
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 05f136220d17839eb7c155f015ace9152f603225 ]
As previously reported by Alexander, whose commit 69403bad97aa ("wifi: mac80211: sdata can be NULL during AMPDU start") I'm reverting as part of this commit, there's a race between station destruction and aggregation setup, where the aggregation setup can happen while the station is being removed and queue the work after ieee80211_sta_tear_down_BA_sessions() has already run in __sta_info_destroy_part1(), and thus the worker will run with a now freed station. In his case, this manifested in a NULL sdata pointer, but really there's no guarantee whatsoever.
The real issue seems to be that it's possible at all to have a situation where this occurs - we want to stop the BA sessions when doing _part1, but we cannot be sure, and WLAN_STA_BLOCK_BA isn't necessarily effective since we don't know that the setup isn't concurrently running and already got past the check.
Simply call ieee80211_sta_tear_down_BA_sessions() again in the second part of station destruction, since at that point really nothing else can hold a reference to the station any more.
Also revert the sdata checks since those are just misleading at this point.
--- net/mac80211/agg-tx.c | 6 +----- net/mac80211/driver-ops.c | 3 --- net/mac80211/sta_info.c | 14 ++++++++++++++ 3 files changed, 15 insertions(+), 8 deletions(-)
net/mac80211/agg-tx.c +1 -5
@@ -491,7 +491,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) {struct tid_ampdu_tx *tid_tx;struct ieee80211_local *local = sta->local; -struct ieee80211_sub_if_data *sdata; +struct ieee80211_sub_if_data *sdata = sta->sdata;struct ieee80211_ampdu_params params = { .sta = &sta->sta, .action =IEEE80211_AMPDU_TX_START ,
@@ -519,7 +519,6 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)*/ synchronize_net (); - sdata = sta->sdata; params.ssn = sta->tid_seq[tid] >>4 ; ret =drv_ampdu_action (local, sdata, ¶ms); tid_tx->ssn = params.ssn;
@@ -533,9 +532,6 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)*/ set_bit (HT_AGG_STATE_DRV_READY , &tid_tx->state); }else if (ret) { -if (!sdata) -return ; -ht_dbg (sdata,"BA request denied - HW unavailable for %pM tid %d\n" , sta->sta.addr, tid);
net/mac80211/driver-ops.c +0 -3
@@ -391,9 +391,6 @@ int drv_ampdu_action(struct ieee80211_local *local,might_sleep (); -if (!sdata) -return -EIO ; - sdata =get_bss_sdata (sdata);if (!check_sdata_in_driver (sdata))return -EIO ;
net/mac80211/sta_info.c +14 -0
@@ -1272,6 +1272,20 @@ static void __sta_info_destroy_part2(struct sta_info *sta)* after _part1 and before _part2! */ +/* +* There's a potential race in _part1 where we set WLAN_STA_BLOCK_BA +* but someone might have just gotten past a check, and not yet into +* queuing the work/creating the data/etc. +* +* Do another round of destruction so that the worker is certainly +* canceled before we later free the station. +* +* Since this is after synchronize_rcu()/synchronize_net() we're now +* certain that nobody can actually hold a reference to the STA and +* be calling e.g. ieee80211_start_tx_ba_session(). +*/ +ieee80211_sta_tear_down_BA_sessions (sta,AGG_STOP_DESTROY_STA ); +might_sleep ();lockdep_assert_held (&local->sta_mtx);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 115/321 rcu: Dump memory object info if callback function is invalid
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhen Lei <[email protected]>
[ Upstream commit 2cbc482d325ee58001472c4359b311958c4efdd1 ]
When a structure containing an RCU callback rhp is (incorrectly) freed and reallocated after rhp is passed to call_rcu(), it is not unusual for rhp->func to be set to NULL. This defeats the debugging prints used by __call_rcu_common() in kernels built with CONFIG_DEBUG_OBJECTS_RCU_HEAD=y, which expect to identify the offending code using the identity of this function.
And in kernels build without CONFIG_DEBUG_OBJECTS_RCU_HEAD=y, things are even worse, as can be seen from this splat:
Unable to handle kernel NULL pointer dereference at virtual address 0
... ...
PC is at 0x0
LR is at rcu_do_batch+0x1c0/0x3b8
... ...
(rcu_do_batch) from (rcu_core+0x1d4/0x284) (rcu_core) from (__do_softirq+0x24c/0x344) (__do_softirq) from (__irq_exit_rcu+0x64/0x108) (__irq_exit_rcu) from (irq_exit+0x8/0x10) (irq_exit) from (__handle_domain_irq+0x74/0x9c) (__handle_domain_irq) from (gic_handle_irq+0x8c/0x98) (gic_handle_irq) from (__irq_svc+0x5c/0x94) (__irq_svc) from (arch_cpu_idle+0x20/0x3c) (arch_cpu_idle) from (default_idle_call+0x4c/0x78) (default_idle_call) from (do_idle+0xf8/0x150) (do_idle) from (cpu_startup_entry+0x18/0x20) (cpu_startup_entry) from (0xc01530)
This commit therefore adds calls to mem_dump_obj(rhp) to output some information, for example:
slab kmalloc-256 start ffff410c45019900 pointer offset 0 size 256
This provides the rough size of the memory block and the offset of the rcu_head structure, which as least provides at least a few clues to help locate the problem. If the problem is reproducible, additional slab debugging can be enabled, for example, CONFIG_DEBUG_SLAB=y, which can provide significantly more information.
--- kernel/rcu/rcu.h | 7 +++++++ kernel/rcu/srcutiny.c | 1 + kernel/rcu/srcutree.c | 1 + kernel/rcu/tasks.h | 1 + kernel/rcu/tiny.c | 1 + kernel/rcu/tree.c | 1 + 6 files changed, 12 insertions(+)
kernel/rcu/rcu.h +7 -0
@@ -10,6 +10,7 @@#ifndef __LINUX_RCU_H#define __LINUX_RCU_H +#include <linux/slab.h> #include <trace/events/rcu.h> /*
@@ -211,6 +212,12 @@ static inline void debug_rcu_head_unqueue(struct rcu_head *head) }#endif /* #else !CONFIG_DEBUG_OBJECTS_RCU_HEAD */ +static inline void debug_rcu_head_callback (struct rcu_head *rhp) +{ +if (unlikely (!rhp->func)) +kmem_dump_obj (rhp); +} +extern int rcu_cpu_stall_suppress_at_boot;static inline bool rcu_stall_is_suppressed_at_boot (void )
kernel/rcu/srcutiny.c +1 -0
@@ -138,6 +138,7 @@ void srcu_drive_gp(struct work_struct *wp)while (lh) { rhp = lh; lh = lh->next; +debug_rcu_head_callback (rhp);local_bh_disable (); rhp->func (rhp);local_bh_enable ();
kernel/rcu/srcutree.c +1 -0
@@ -1591,6 +1591,7 @@ static void srcu_invoke_callbacks(struct work_struct *work) rhp =rcu_cblist_dequeue (&ready_cbs);for (; rhp !=NULL ; rhp =rcu_cblist_dequeue (&ready_cbs)) {debug_rcu_head_unqueue (rhp); +debug_rcu_head_callback (rhp);local_bh_disable (); rhp->func (rhp);local_bh_enable ();
kernel/rcu/tasks.h +1 -0
@@ -487,6 +487,7 @@ static void rcu_tasks_invoke_cbs(struct rcu_tasks *rtp, struct rcu_tasks_percpuraw_spin_unlock_irqrestore_rcu_node (rtpcp, flags); len = rcl.len;for (rhp =rcu_cblist_dequeue (&rcl); rhp; rhp =rcu_cblist_dequeue (&rcl)) { +debug_rcu_head_callback (rhp);local_bh_disable (); rhp->func (rhp);local_bh_enable ();
kernel/rcu/tiny.c +1 -0
@@ -97,6 +97,7 @@ static inline bool rcu_reclaim_tiny(struct rcu_head *head)trace_rcu_invoke_callback ("" , head); f = head->func; +debug_rcu_head_callback (head);WRITE_ONCE (head->func, (rcu_callback_t )0L );f (head);rcu_lock_release (&rcu_callback_map);
kernel/rcu/tree.c +1 -0
@@ -2292,6 +2292,7 @@ static void rcu_do_batch(struct rcu_data *rdp)trace_rcu_invoke_callback (rcu_state.name, rhp); f = rhp->func; +debug_rcu_head_callback (rhp);WRITE_ONCE (rhp->func, (rcu_callback_t )0L );f (rhp);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 116/321 rcu: Eliminate rcu_gp_slow_unregister() false positive
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul E. McKenney <[email protected]>
[ Upstream commit 0ae9942f03d0d034fdb0a4f44fc99f62a3107987 ]
When using rcutorture as a module, there are a number of conditions that can abort the modprobe operation, for example, when attempting to run both RCU CPU stall warning tests and forward-progress tests. This can cause rcu_torture_cleanup() to be invoked on the unwind path out of rcu_rcu_torture_init(), which will mean that rcu_gp_slow_unregister() is invoked without a matching rcu_gp_slow_register(). This will cause a splat because rcu_gp_slow_unregister() is passed rcu_fwd_cb_nodelay, which does not match a NULL pointer.
This commit therefore forgives a mismatch involving a NULL pointer, thus avoiding this false-positive splat.
--- kernel/rcu/tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/rcu/tree.c +1 -1
@@ -1336,7 +1336,7 @@ EXPORT_SYMBOL_GPL(rcu_gp_slow_register);/* Unregister a counter, with NULL for not caring which. */ void rcu_gp_slow_unregister (atomic_t *rgssp) { -WARN_ON_ONCE (rgssp && rgssp != rcu_gp_slow_suppress); +WARN_ON_ONCE (rgssp && rgssp != rcu_gp_slow_suppress && rcu_gp_slow_suppress !=NULL );WRITE_ONCE (rcu_gp_slow_suppress,NULL ); }
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 117/321 wifi: cw1200: Avoid processing an invalid TIM IE
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Johnson <[email protected]>
[ Upstream commit b7bcea9c27b3d87b54075735c870500123582145 ]
While converting struct ieee80211_tim_ie::virtual_map to be a flexible array it was observed that the TIM IE processing in cw1200_rx_cb() could potentially process a malformed IE in a manner that could result in a buffer over-read. Add logic to verify that the TIM IE length is large enough to hold a valid TIM payload before processing it.
--- drivers/net/wireless/st/cw1200/txrx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/st/cw1200/txrx.c +1 -1
@@ -1166,7 +1166,7 @@ void cw1200_rx_cb(struct cw1200_common *priv,size_t ies_len = skb->len - (ies - (u8 *)(skb->data)); tim_ie =cfg80211_find_ie (WLAN_EID_TIM , ies, ies_len); -if (tim_ie) { +if (tim_ie && tim_ie[1 ] >=sizeof (struct ieee80211_tim_ie )) {struct ieee80211_tim_ie *tim = (struct ieee80211_tim_ie *)&tim_ie[2 ];
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 118/321 cgroup: Avoid extra dereference in css_populate_dir()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kamalesh Babulal <[email protected]>
[ Upstream commit d24f05987ce8bf61e62d86fedbe47523dc5c3393 ]
Use css directly instead of dereferencing it from &cgroup->self, while adding the cgroup v2 cft base and psi files in css_populate_dir(). Both points to the same css, when css->ss is NULL, this avoids extra deferences and makes code consistent in usage across the function.
--- kernel/cgroup/cgroup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/cgroup/cgroup.c +2 -2
@@ -1751,13 +1751,13 @@ static int css_populate_dir(struct cgroup_subsys_state *css)if (!css->ss) {if (cgroup_on_dfl (cgrp)) { - ret =cgroup_addrm_files (&cgrp->self, cgrp, + ret =cgroup_addrm_files (css, cgrp, cgroup_base_files, true);if (ret <0 )return ret;if (cgroup_psi_enabled ()) { - ret =cgroup_addrm_files (&cgrp->self, cgrp, + ret =cgroup_addrm_files (css, cgrp, cgroup_psi_files, true);if (ret <0 )return ret;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 119/321 i2c: riic: avoid potential division by zero
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wolfram Sang <[email protected]>
[ Upstream commit 7890fce6201aed46d3576e3d641f9ee5c1f0e16f ]
Value comes from DT, so it could be 0. Unlikely, but could be.
--- drivers/i2c/busses/i2c-riic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/busses/i2c-riic.c +1 -1
@@ -314,7 +314,7 @@ static int riic_init_hw(struct riic_dev *riic, struct i2c_timings *t)* frequency with only 62 clock ticks max (31 high, 31 low). * Aim for a duty of 60% LOW, 40% HIGH. */ - total_ticks =DIV_ROUND_UP (rate, t->bus_freq_hz); + total_ticks =DIV_ROUND_UP (rate, t->bus_freq_hz ?:1 );for (cks =0 ; cks <7 ; cks++) {/*
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 120/321 RDMA/rtrs: Fix the problem of variable not initialized fully
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhu Yanjun <[email protected]>
[ Upstream commit c5930a1aa08aafe6ffe15b5d28fe875f88f6ac86 ]
No functionality change. The variable which is not initialized fully will introduce potential risks.
--- drivers/infiniband/ulp/rtrs/rtrs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/infiniband/ulp/rtrs/rtrs.c +1 -1
@@ -255,7 +255,7 @@ static int create_cq(struct rtrs_con *con, int cq_vector, int nr_cqe,static int create_qp (struct rtrs_con *con,struct ib_pd *pd,u32 max_send_wr,u32 max_recv_wr,u32 max_sge) { -struct ib_qp_init_attr init_attr = {NULL }; +struct ib_qp_init_attr init_attr = {};struct rdma_cm_id *cm_id = con->cm_id;int ret;
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 121/321 s390/smp,mcck: fix early IPI handling
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Heiko Carstens <[email protected]>
[ Upstream commit 4a1725281fc5b0009944b1c0e1d2c1dc311a09ec ]
Both the external call as well as the emergency signal submask bits in control register 0 are set before any interrupt handler is registered.
Change the order and first register the interrupt handler and only then enable the interrupts by setting the corresponding bits in control register 0.
This prevents that the second part of the machine check handler for early machine check handling is not executed: the machine check handler sends an IPI to the CPU it runs on. If the corresponding interrupts are enabled, but no interrupt handler is present, the interrupt is ignored.
--- arch/s390/kernel/early.c | 12 +++--------- arch/s390/kernel/smp.c | 4 ++-- 2 files changed, 5 insertions(+), 11 deletions(-)
arch/s390/kernel/early.c +3 -9
@@ -237,15 +237,9 @@ static inline void save_vector_registers(void)#endif } -static inline void setup_control_registers (void ) +static inline void setup_low_address_protection (void ) { -unsigned long reg; - -__ctl_store (reg,0 ,0 ); - reg |=CR0_LOW_ADDRESS_PROTECTION ; - reg |=CR0_EMERGENCY_SIGNAL_SUBMASK ; - reg |=CR0_EXTERNAL_CALL_SUBMASK ; -__ctl_load (reg,0 ,0 ); +__ctl_set_bit (0 ,28 ); }static inline void setup_access_registers (void )
@@ -304,7 +298,7 @@ void __init startup_init(void)save_vector_registers ();setup_topology ();sclp_early_detect (); -setup_control_registers (); +setup_low_address_protection ();setup_access_registers ();lockdep_on (); }
arch/s390/kernel/smp.c +2 -2
@@ -1007,12 +1007,12 @@ void __init smp_fill_possible_mask(void)void __init smp_prepare_cpus (unsigned int max_cpus) { -/* request the 0x1201 emergency signal external interrupt */ if (register_external_irq (EXT_IRQ_EMERGENCY_SIG , do_ext_call_interrupt))panic ("Couldn't request external interrupt 0x1201" ); -/* request the 0x1202 external call external interrupt */ +ctl_set_bit (0 ,14 );if (register_external_irq (EXT_IRQ_EXTERNAL_CALL , do_ext_call_interrupt))panic ("Couldn't request external interrupt 0x1202" ); +ctl_set_bit (0 ,13 ); }void __init smp_prepare_boot_cpu (void )
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 122/321 drm/bridge: tc358768: Attempt to fix DSI horizontal timings
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tomi Valkeinen <[email protected]>
[ Upstream commit 9fc75c40faa29df14ba16066be6bdfaea9f39ce4 ]
The DSI horizontal timing calculations done by the driver seem to often lead to underflows or overflows, depending on the videomode.
There are two main things the current driver doesn't seem to get right:
DSI HSW and HFP, and VSDly. However, even following Toshiba's documentation it seems we don't always get a working display.
This patch attempts to fix the horizontal timings for DSI event mode, and on a system with a DSI->HDMI encoder, a lot of standard HDMI modes now seem to work. The work relies on Toshiba's documentation, but also quite a bit on empirical testing.
This also adds timing related debug prints to make it easier to improve on this later.
The DSI pulse mode has only been tested with a fixed-resolution panel, which limits the testing of different modes on DSI pulse mode. However, as the VSDly calculation also affects pulse mode, so this might cause a regression.
--- drivers/gpu/drm/bridge/tc358768.c | 213 ++++++++++++++++++++++++++---- 1 file changed, 185 insertions(+), 28 deletions(-)
drivers/gpu/drm/bridge/tc358768.c +185 -28
@@ -9,6 +9,7 @@#include <linux/gpio/consumer.h> #include <linux/i2c.h> #include <linux/kernel.h> +#include <linux/math64.h> #include <linux/media-bus-format.h> #include <linux/minmax.h> #include <linux/module.h>
@@ -158,6 +159,7 @@ struct tc358768_priv {u32 frs;/* PLL Freqency range for HSCK (post divider) */ u32 dsiclk;/* pll_clk / 2 */ +u32 pclk;/* incoming pclk rate */ }; static inline struct tc358768_priv *dsi_host_to_tc358768(struct mipi_dsi_host
@@ -381,6 +383,7 @@ static int tc358768_calc_pll(struct tc358768_priv *priv, priv->prd = best_prd; priv->frs = frs; priv->dsiclk = best_pll /2 ; + priv->pclk = mode->clock *1000 ;return 0 ; }
@@ -639,6 +642,28 @@ static u32 tc358768_ps_to_ns(u32 ps)return ps /1000 ; } +static u32 tc358768_dpi_to_ns (u32 val,u32 pclk) +{ +return (u32 )div_u64 ((u64 )val *NANO , pclk); +} + +/* Convert value in DPI pixel clock units to DSI byte count */ +static u32 tc358768_dpi_to_dsi_bytes (struct tc358768_priv *priv,u32 val) +{ +u64 m = (u64 )val * priv->dsiclk /4 * priv->dsi_lanes; +u64 n = priv->pclk; + +return (u32 )div_u64 (m + n -1 , n); +} + +static u32 tc358768_dsi_bytes_to_ns (struct tc358768_priv *priv,u32 val) +{ +u64 m = (u64 )val *NANO ; +u64 n = priv->dsiclk /4 * priv->dsi_lanes; + +return (u32 )div_u64 (m, n); +} +static void tc358768_bridge_pre_enable (struct drm_bridge *bridge) {struct tc358768_priv *priv =bridge_to_tc358768 (bridge);
@@ -648,11 +673,19 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)s32 raw_val;const struct drm_display_mode *mode;u32 hsbyteclk_ps, dsiclk_ps, ui_ps; -u32 dsiclk, hsbyteclk, video_start; -const u32 internal_delay =40 ; +u32 dsiclk, hsbyteclk;int ret, i;struct videomode vm;struct device *dev = priv->dev; +/* In pixelclock units */ +u32 dpi_htot, dpi_data_start; +/* In byte units */ +u32 dsi_dpi_htot, dsi_dpi_data_start; +u32 dsi_hsw, dsi_hbp, dsi_hact, dsi_hfp; +const u32 dsi_hss =4 ;/* HSS is a short packet (4 bytes) */ +/* In hsbyteclk units */ +u32 dsi_vsdly; +const u32 internal_dly =40 ;if (mode_flags &MIPI_DSI_CLOCK_NON_CONTINUOUS ) {dev_warn_once (dev,"Non-continuous mode unimplemented, falling back to continuous\n" );
@@ -687,27 +720,23 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)case MIPI_DSI_FMT_RGB888 : val |= (0x3 <<4 ); hact = vm.hactive *3 ; - video_start = (vm.hsync_len + vm.hback_porch) *3 ; data_type =MIPI_DSI_PACKED_PIXEL_STREAM_24 ;break ;case MIPI_DSI_FMT_RGB666 : val |= (0x4 <<4 ); hact = vm.hactive *3 ; - video_start = (vm.hsync_len + vm.hback_porch) *3 ; data_type =MIPI_DSI_PACKED_PIXEL_STREAM_18 ;break ;case MIPI_DSI_FMT_RGB666_PACKED : val |= (0x4 <<4 ) |BIT (3 ); hact = vm.hactive *18 /8 ; - video_start = (vm.hsync_len + vm.hback_porch) *18 /8 ; data_type =MIPI_DSI_PIXEL_STREAM_3BYTE_18 ;break ;case MIPI_DSI_FMT_RGB565 : val |= (0x5 <<4 ); hact = vm.hactive *2 ; - video_start = (vm.hsync_len + vm.hback_porch) *2 ; data_type =MIPI_DSI_PACKED_PIXEL_STREAM_16 ;break ;default :
@@ -717,9 +746,152 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)return ; } +/* +* There are three important things to make TC358768 work correctly, +* which are not trivial to manage: +* +* 1. Keep the DPI line-time and the DSI line-time as close to each +* other as possible. +* 2. TC358768 goes to LP mode after each line's active area. The DSI +* HFP period has to be long enough for entering and exiting LP mode. +* But it is not clear how to calculate this. +* 3. VSDly (video start delay) has to be long enough to ensure that the +* DSI TX does not start transmitting until we have started receiving +* pixel data from the DPI input. It is not clear how to calculate +* this either. +*/ + + dpi_htot = vm.hactive + vm.hfront_porch + vm.hsync_len + vm.hback_porch; + dpi_data_start = vm.hsync_len + vm.hback_porch; + +dev_dbg (dev,"dpi horiz timing (pclk): %u + %u + %u + %u = %u\n" , + vm.hsync_len, vm.hback_porch, vm.hactive, vm.hfront_porch, + dpi_htot); + +dev_dbg (dev,"dpi horiz timing (ns): %u + %u + %u + %u = %u\n" , +tc358768_dpi_to_ns (vm.hsync_len, vm.pixelclock), +tc358768_dpi_to_ns (vm.hback_porch, vm.pixelclock), +tc358768_dpi_to_ns (vm.hactive, vm.pixelclock), +tc358768_dpi_to_ns (vm.hfront_porch, vm.pixelclock), +tc358768_dpi_to_ns (dpi_htot, vm.pixelclock)); + +dev_dbg (dev,"dpi data start (ns): %u + %u = %u\n" , +tc358768_dpi_to_ns (vm.hsync_len, vm.pixelclock), +tc358768_dpi_to_ns (vm.hback_porch, vm.pixelclock), +tc358768_dpi_to_ns (dpi_data_start, vm.pixelclock)); + + dsi_dpi_htot =tc358768_dpi_to_dsi_bytes (priv, dpi_htot); + dsi_dpi_data_start =tc358768_dpi_to_dsi_bytes (priv, dpi_data_start); + +if (dsi_dev->mode_flags &MIPI_DSI_MODE_VIDEO_SYNC_PULSE ) { + dsi_hsw =tc358768_dpi_to_dsi_bytes (priv, vm.hsync_len); + dsi_hbp =tc358768_dpi_to_dsi_bytes (priv, vm.hback_porch); + }else { +/* HBP is included in HSW in event mode */ + dsi_hbp =0 ; + dsi_hsw =tc358768_dpi_to_dsi_bytes (priv, + vm.hsync_len + + vm.hback_porch); + +/* +* The pixel packet includes the actual pixel data, and: +* DSI packet header = 4 bytes +* DCS code = 1 byte +* DSI packet footer = 2 bytes +*/ + dsi_hact = hact +4 +1 +2 ; + + dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss; + +/* +* Here we should check if HFP is long enough for entering LP +* and exiting LP, but it's not clear how to calculate that. +* Instead, this is a naive algorithm that just adjusts the HFP +* and HSW so that HFP is (at least) roughly 2/3 of the total +* blanking time. +*/ +if (dsi_hfp < (dsi_hfp + dsi_hsw + dsi_hss) *2 /3 ) { +u32 old_hfp = dsi_hfp; +u32 old_hsw = dsi_hsw; +u32 tot = dsi_hfp + dsi_hsw + dsi_hss; + + dsi_hsw = tot /3 ; + +/* +* Seems like sometimes HSW has to be divisible by num-lanes, but +* not always... +*/ + dsi_hsw =roundup (dsi_hsw, priv->dsi_lanes); + + dsi_hfp = dsi_dpi_htot - dsi_hact - dsi_hsw - dsi_hss; + +dev_dbg (dev, +"hfp too short, adjusting dsi hfp and dsi hsw from %u, %u to %u, %u\n" , + old_hfp, old_hsw, dsi_hfp, dsi_hsw); + } + +dev_dbg (dev, +"dsi horiz timing (bytes): %u, %u + %u + %u + %u = %u\n" , + dsi_hss, dsi_hsw, dsi_hbp, dsi_hact, dsi_hfp, + dsi_hss + dsi_hsw + dsi_hbp + dsi_hact + dsi_hfp); + +dev_dbg (dev,"dsi horiz timing (ns): %u + %u + %u + %u + %u = %u\n" , +tc358768_dsi_bytes_to_ns (priv, dsi_hss), +tc358768_dsi_bytes_to_ns (priv, dsi_hsw), +tc358768_dsi_bytes_to_ns (priv, dsi_hbp), +tc358768_dsi_bytes_to_ns (priv, dsi_hact), +tc358768_dsi_bytes_to_ns (priv, dsi_hfp), +tc358768_dsi_bytes_to_ns (priv, dsi_hss + dsi_hsw + + dsi_hbp + dsi_hact + dsi_hfp)); + } + +/* VSDly calculation */ + +/* Start with the HW internal delay */ + dsi_vsdly = internal_dly; + +/* Convert to byte units as the other variables are in byte units */ + dsi_vsdly *= priv->dsi_lanes; + +/* Do we need more delay, in addition to the internal? */ +if (dsi_dpi_data_start > dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp) { + dsi_vsdly = dsi_dpi_data_start - dsi_hss - dsi_hsw - dsi_hbp; + dsi_vsdly =roundup (dsi_vsdly, priv->dsi_lanes); + } + +dev_dbg (dev,"dsi data start (bytes) %u + %u + %u + %u = %u\n" , + dsi_vsdly, dsi_hss, dsi_hsw, dsi_hbp, + dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp); + +dev_dbg (dev,"dsi data start (ns) %u + %u + %u + %u = %u\n" , +tc358768_dsi_bytes_to_ns (priv, dsi_vsdly), +tc358768_dsi_bytes_to_ns (priv, dsi_hss), +tc358768_dsi_bytes_to_ns (priv, dsi_hsw), +tc358768_dsi_bytes_to_ns (priv, dsi_hbp), +tc358768_dsi_bytes_to_ns (priv, dsi_vsdly + dsi_hss + dsi_hsw + dsi_hbp)); + +/* Convert back to hsbyteclk */ + dsi_vsdly /= priv->dsi_lanes; + +/* +* The docs say that there is an internal delay of 40 cycles. +* However, we get underflows if we follow that rule. If we +* instead ignore the internal delay, things work. So either +* the docs are wrong or the calculations are wrong. +* +* As a temporary fix, add the internal delay here, to counter +* the subtraction when writing the register. +*/ + dsi_vsdly += internal_dly; + +/* Clamp to the register max */ +if (dsi_vsdly - internal_dly >0x3ff ) { +dev_warn (dev,"VSDly too high, underflows likely\n" ); + dsi_vsdly =0x3ff + internal_dly; + } +/* VSDly[9:0] */ - video_start =max (video_start, internal_delay +1 ) - internal_delay; -tc358768_write (priv,TC358768_VSDLY , video_start); +tc358768_write (priv,TC358768_VSDLY , dsi_vsdly - internal_dly);tc358768_write (priv,TC358768_DATAFMT , val);tc358768_write (priv,TC358768_DSITX_DT , data_type);
@@ -827,18 +999,6 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)/* vbp */ tc358768_write (priv,TC358768_DSI_VBPR , vm.vback_porch); - -/* hsw * byteclk * ndl / pclk */ - val = (u32 )div_u64 (vm.hsync_len * - (u64 )hsbyteclk * priv->dsi_lanes, - vm.pixelclock); -tc358768_write (priv,TC358768_DSI_HSW , val); - -/* hbp * byteclk * ndl / pclk */ - val = (u32 )div_u64 (vm.hback_porch * - (u64 )hsbyteclk * priv->dsi_lanes, - vm.pixelclock); -tc358768_write (priv,TC358768_DSI_HBPR , val); }else {/* Set event mode */ tc358768_write (priv,TC358768_DSI_EVENT ,1 );
@@ -852,16 +1012,13 @@ static void tc358768_bridge_pre_enable(struct drm_bridge *bridge)/* vbp (not used in event mode) */ tc358768_write (priv,TC358768_DSI_VBPR ,0 ); + } -/* (hsw + hbp) * byteclk * ndl / pclk */ - val = (u32 )div_u64 ((vm.hsync_len + vm.hback_porch) * - (u64 )hsbyteclk * priv->dsi_lanes, - vm.pixelclock); -tc358768_write (priv,TC358768_DSI_HSW , val); +/* hsw (bytes) */ +tc358768_write (priv,TC358768_DSI_HSW , dsi_hsw); -/* hbp (not used in event mode) */ -tc358768_write (priv,TC358768_DSI_HBPR ,0 ); - } +/* hbp (bytes) */ +tc358768_write (priv,TC358768_DSI_HBPR , dsi_hbp);/* hact (bytes) */ tc358768_write (priv,TC358768_DSI_HACT , hact);
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 123/321 i3c: mipi-i3c-hci: Remove BUG() when Ring Abort request times out
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jarkko Nikula <[email protected]>
[ Upstream commit 361acacaf7c706223968c8186f0d3b6e214e7403 ]
Ring Abort request will timeout in case there is an error in the Host Controller interrupt delivery or Ring Header configuration. Using BUG() makes hard to debug those cases.
Make it less severe and turn BUG() to WARN_ON().
--- drivers/i3c/master/mipi-i3c-hci/dma.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/i3c/master/mipi-i3c-hci/dma.c +1 -2
@@ -450,10 +450,9 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,/* * We're deep in it if ever this condition is ever met. * Hardware might still be writing to memory, etc. -* Better suspend the world than risking silent corruption. */ dev_crit (&hci->master.dev,"unable to abort the ring\n" ); -BUG (); +WARN_ON (1 ); }for (i =0 ; i < n; i++) {
Signature · 1 line
2.43.0
Greg Kroah-Hartman
maintainerPATCH 124/321 i3c: mipi-i3c-hci: Do not unmap region not mapped for transfer
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jarkko Nikula <[email protected]>
[ Upstream commit b8806e0c939f168237593af0056c309bf31022b0 ]
Fix following warning (with CONFIG_DMA_API_DEBUG) which happens with a transfer without a data buffer.
DMA-API: i3c mipi-i3c-hci.0: device driver tries to free DMA memory it has not allocated [device address=0x0000000000000000] [size=0 bytes]
For those transfers the hci_dma_queue_xfer() doesn't create a mapping and the DMA address pointer xfer->data_dma is not set.
--- drivers/i3c/master/mipi-i3c-hci/dma.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/i3c/master/mipi-i3c-hci/dma.c +2 -0
@@ -345,6 +345,8 @@ static void hci_dma_unmap_xfer(struct i3c_hci *hci,for (i =0 ; i < n; i++) { xfer = xfer_list + i; +if (!xfer->data) +continue ;dma_unmap_single (&hci->master.dev, xfer->data_dma, xfer->data_len, xfer->rnw ?DMA_FROM_DEVICE :DMA_TO_DEVICE );
Signature · 1 line
2.43.0