6.12.110-rc1 review
Subsystems (7)
Greg Kroah-Hartman
maintainerPATCH 1281/1376 Bluetooth: btmtksdio: Take exclusive ownership of the SKB before TX
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Lu <[email protected]>
[ Upstream commit 155e3003d1e614f85566b636973df7118e1b4851 ]
btmtksdio_tx_packet() prepends the MediaTek SDIO header with skb_push() and writes into that space after only checking the headroom size. On a cloned SKB that headroom belongs to a buffer shared with the other owner, which the driver has no right to write to.
Cloned SKBs do reach this path: hci_send_cmd_sync() keeps a clone of every HCI command in hdev->sent_cmd before handing the SKB to the driver, and l2cap_ertm_send() clones SKBs for retransmission.
Replace the open-coded headroom check with skb_cow_head(), which both guarantees the headroom and reallocates a private buffer when the SKB is cloned. The cost is one reallocation and copy per cloned packet, the usual price of this pattern in network drivers.
This has no observable effect on its own, as the driver only writes in front of skb->data where no other owner looks. It is a prerequisite for "Bluetooth: btmtksdio: Fix out-of-bounds DMA read in the TX path", which writes padding behind skb->tail, and carries the same Fixes: tag so that both are backported together.
--- drivers/bluetooth/btmtksdio.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
drivers/bluetooth/btmtksdio.c +6 -7
@@ -274,13 +274,12 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev,struct mtkbtsdio_hdr *sdio_hdr;int err; -/* Make sure that there are enough rooms for SDIO header */ -if (unlikely (skb_headroom (skb) <sizeof (*sdio_hdr))) { - err =pskb_expand_head (skb,sizeof (*sdio_hdr),0 , -GFP_ATOMIC ); -if (err <0 ) -return err; - } +/* Make sure that the data buffer is not shared with anyone else and +* that there is enough room for the SDIO header +*/ + err =skb_cow_head (skb,sizeof (*sdio_hdr)); +if (err <0 ) +return err;/* Prepend MediaTek SDIO Specific Header */ skb_push (skb,sizeof (*sdio_hdr));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1282/1376 Bluetooth: btmtksdio: Fix out-of-bounds DMA read in the TX path
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chris Lu <[email protected]>
[ Upstream commit fa0ad2d277c7adead61d1c22411c55cea6990c2a ]
btmtksdio_tx_packet() rounds the transfer size up to the SDIO block size of 256 bytes, but hands the host controller the SKB buffer as is:
err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data, round_up(skb->len, MTK_SDIO_BLOCK_SIZE));
Only skb->len bytes hold packet data, so the controller reads up to 255 bytes of uninitialised memory and sends it to the device over the SDIO bus. Depending on how much tailroom slack the SKB allocation happens to carry, that read can also extend past the end of the buffer.
Compute the padded length up front, ensure the SKB has tailroom for it, and zero-fill the padding with skb_put_zero(). skb->len then covers the padding, so sdio_writesb() no longer needs to round up. byte_tx keeps counting the header and the payload only, and the error path restores the SKB so that the caller can requeue it.
Writing behind skb->tail is only safe because the driver owns the buffer, which "Bluetooth: btmtksdio: Take exclusive ownership of the SKB before TX" ensures.
--- drivers/bluetooth/btmtksdio.c | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-)
drivers/bluetooth/btmtksdio.c +21 -5
@@ -272,6 +272,7 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev, struct sk_buff *skb) {struct mtkbtsdio_hdr *sdio_hdr; +unsigned int len, pad_len;int err;/* Make sure that the data buffer is not shared with anyone else and
@@ -281,6 +282,18 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev,if (err <0 )return err; +/* The transfer is rounded up to the SDIO block size, so the buffer +* has to provide tailroom for the padding as well +*/ + len = skb->len +sizeof (*sdio_hdr); + pad_len =round_up (len,MTK_SDIO_BLOCK_SIZE ) - len; + +if (unlikely (skb_tailroom (skb) < pad_len)) { + err =pskb_expand_head (skb,0 , pad_len,GFP_ATOMIC ); +if (err <0 ) +return err; + } +/* Prepend MediaTek SDIO Specific Header */ skb_push (skb,sizeof (*sdio_hdr));
@@ -289,19 +302,22 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev, sdio_hdr->reserved =cpu_to_le16 (0 ); sdio_hdr->bt_type =hci_skb_pkt_type (skb); +/* Zero the padding so that no uninitialised memory is sent out */ +skb_put_zero (skb, pad_len); +clear_bit (BTMTKSDIO_HW_TX_READY , &bdev->tx_state); - err =sdio_writesb (bdev->func,MTK_REG_CTDR , skb->data, -round_up (skb->len,MTK_SDIO_BLOCK_SIZE )); + err =sdio_writesb (bdev->func,MTK_REG_CTDR , skb->data, skb->len);if (err <0 ) - goto err_skb_pull; + goto err_skb_restore; - bdev->hdev->stat.byte_tx += skb->len; + bdev->hdev->stat.byte_tx += len;kfree_skb (skb);return 0 ; -err_skb_pull: +err_skb_restore: +skb_trim (skb, len);skb_pull (skb,sizeof (*sdio_hdr));return err;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1283/1376 Bluetooth: RFCOMM: Validate MTU in rfcomm_apply_pn() to prevent infinite loop
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hyunwoo Kim <[email protected]>
[ Upstream commit 44c98fd082eafd49d55a8a4077ff488175b2fe24 ]
rfcomm_apply_pn() accepts the MTU value from a remote PN (Parameter Negotiation) frame without checking for zero. When the remote peer sends an MTU of zero, d->mtu is set to 0. This causes the sendmsg path to enter an infinite loop when fragmenting data, as each fragment has size == min_t(size_t, len, 0) == 0, so the remaining length never decreases. The infinite allocation of zero-length skbs exhausts all system memory.
Fix by clamping d->mtu to RFCOMM_DEFAULT_MTU when the negotiated value is zero, consistent with the initial value assigned in rfcomm_dlc_alloc().
--- net/bluetooth/rfcomm/core.c | 4 ++++ 1 file changed, 4 insertions(+)
net/bluetooth/rfcomm/core.c +4 -0
@@ -1458,6 +1458,10 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn) d->mtu =__le16_to_cpu (pn->mtu); +/* MTU 0 causes an infinite loop when fragmenting in sendmsg */ +if (!d->mtu) + d->mtu =RFCOMM_DEFAULT_MTU ; +if (cr && d->mtu > s->mtu) d->mtu = s->mtu;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1284/1376 gtp: add synchronize_net() in gtp_newlink() error path to prevent use-after-free
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang (Microsoft) <[email protected]>
[ Upstream commit d989e22ae9802c52c56ad4284d0caf26696cf6ae ]
gtp_newlink()'s error path frees tid_hash and addr_hash without waiting for an RCU grace period after clearing sk_user_data. A concurrent gtp_encap_recv() in softirq may still hold the gtp_dev pointer obtained via rcu_dereference_sk_user_data() and access the freed memory.
BUG: KASAN: slab-use-after-free in gtp0_pdp_find+0x1f6/0x200 (gtp.c:152) Call Trace: <IRQ> gtp0_pdp_find+0x1f6/0x200 gtp_encap_recv+0x527/0x24b0 udp_queue_rcv_one_skb+0x75f/0xc10
Add synchronize_net() before the kfree calls in out_hashtable, which covers all error paths from both gtp_encap_enable() and gtp_create_sockets().
--- drivers/net/gtp.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/gtp.c +2 -0
@@ -1544,6 +1544,8 @@ static int gtp_newlink(struct net *src_net, struct net_device *dev, out_encap:gtp_encap_disable (gtp); out_hashtable: +/* Wait for RCU readers that may still reference this gtp_dev. */ +synchronize_net ();kfree (gtp->addr_hash);kfree (gtp->tid_hash);return err;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1285/1376 octeontx2-af: fix NULL deref in NIX TM tree debugfs read path
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anshumali Gaur <[email protected]>
[ Upstream commit ec65631bd5ec251cdf67a4919fac7a3149a6e235 ]
rvu_dbg_nix_tm_tree_display() dereferences pfvf->sq_ctx without checking whether the SQ context has been allocated. Reading /sys/kernel/debug/octeontx2/nix/tm_tree for a NIX LF whose transmit queues are not set up triggers a kernel oops.
Guard the read path the same way rvu_dbg_nix_tm_tree_write() already does and return -EINVAL with a seq_file message when sq_ctx is NULL.
--- drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/net/ethernet/marvell/octeontx2/af/rvu_debugfs.c +6 -0
@@ -1659,6 +1659,12 @@ static int rvu_dbg_nix_tm_tree_display(struct seq_file *m, void *unused)return -EINVAL ; pfvf =rvu_get_pfvf (rvu, pcifunc); + +if (!pfvf->sq_ctx) { +seq_printf (m,"SQ context is not initialized for pcifunc 0x%x\n" , pcifunc); +return -EINVAL ; + } + max_id = pfvf->sq_ctx->qsize;memset (&aq_req,0 ,sizeof (struct nix_aq_enq_req ));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1286/1376 net: qualcomm: rmnet: restore skb->dev on deaggregated frames
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
[ Upstream commit a66734a1c5e36525ea07e9f4547fddc51e916de3 ]
rmnet_map_deaggregate() allocates each sub-frame with alloc_skb() and leaves skb->dev NULL. __rmnet_map_ingress_handler() assigns skb->dev = ep->egress_dev only on the data path, but a MAP command frame is dispatched to rmnet_map_command() before that, so rmnet_map_send_ack() runs netif_tx_lock(skb->dev) on a NULL device. An unprivileged user reaches this by unsharing a user+net namespace, creating an rmnet link over a tap device with INGRESS_DEAGGREGATION and INGRESS_MAP_COMMANDS, and writing an aggregated frame carrying a flow-control command to the tap fd.
Restore the assignment dropped by 378e25357ac7, so every skb leaving rmnet_map_deaggregate() has a valid device.
BUG: KASAN: null-ptr-deref in _raw_spin_lock (kernel/locking/spinlock.c:158) Write of size 4 at addr 00000000000004b4 by task exploit/144 Call Trace: _raw_spin_lock (kernel/locking/spinlock.c:158) netif_tx_lock (net/sched/sch_generic.c:497) rmnet_map_command (drivers/net/ethernet/qualcomm/rmnet/rmnet_map_command.c:67) rmnet_rx_handler (drivers/net/ethernet/qualcomm/rmnet/rmnet_handlers.c:125) __netif_receive_skb_core.constprop.0 (net/core/dev.c:6103) ... __netif_receive_skb_one_core (net/core/dev.c:6214) netif_receive_skb (net/core/dev.c:6474) tun_get_user (drivers/net/tun.c:1966) tun_chr_write_iter (drivers/net/tun.c:2012) vfs_write (fs/read_write.c:687) ksys_write (fs/read_write.c:739) do_syscall_64 (arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) Kernel panic - not syncing: Fatal exception in interrupt
--- drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/qualcomm/rmnet/rmnet_map_data.c +1 -0
@@ -394,6 +394,7 @@ struct sk_buff *rmnet_map_deaggregate(struct sk_buff *skb,if (!skbn)return NULL ; + skbn->dev = skb->dev;skb_reserve (skbn,RMNET_MAP_DEAGGR_HEADROOM );skb_put (skbn, packet_len);memcpy (skbn->data, skb->data, packet_len);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1287/1376 octeontx2-af: Fix TL3/TL2 link config ENA clearing
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Naveen Mamindlapalli <[email protected]>
[ Upstream commit 9edf8d4876e8a2471e66f54d36208eaff2858392 ]
Clear and restore the ENA bit for each TL3/TL2 link entry during SMQ flush instead of repeatedly using the same link index.
--- drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c +5 -6
@@ -2370,8 +2370,8 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,int pf =rvu_get_pf (pcifunc);u8 cgx_id =0 , lmac_id =0 ;u16 tl2_tl3_link_schq; -u8 link, link_level;u64 cfg, bmap =0 ; +u8 link_level;if (!is_rvu_otx2 (rvu)) {/* Skip SMQ flush if pkt count is zero */
@@ -2403,7 +2403,6 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr, link_level =rvu_read64 (rvu, blkaddr,NIX_AF_PSE_CHANNEL_LEVEL ) &0x01 ?NIX_TXSCH_LVL_TL3 :NIX_TXSCH_LVL_TL2 ; tl2_tl3_link_schq = smq_flush_ctx->smq_tree_ctx[link_level].schq; - link = smq_flush_ctx->smq_tree_ctx[NIX_TXSCH_LVL_TL1 ].schq;/* SMQ set enqueue xoff */ cfg =rvu_read64 (rvu, blkaddr,NIX_AF_SMQX_CFG (smq));
@@ -2413,13 +2412,13 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,/* Clear all NIX_AF_TL3_TL2_LINK_CFG[ENA] for the TL3/TL2 queue */ for (i =0 ; i < (rvu->hw->cgx_links + rvu->hw->lbk_links); i++) { cfg =rvu_read64 (rvu, blkaddr, -NIX_AF_TL3_TL2X_LINKX_CFG (tl2_tl3_link_schq, link)); +NIX_AF_TL3_TL2X_LINKX_CFG (tl2_tl3_link_schq, i));if (!(cfg &BIT_ULL (12 )))continue ; bmap |=BIT_ULL (i); cfg &= ~BIT_ULL (12 );rvu_write64 (rvu, blkaddr, -NIX_AF_TL3_TL2X_LINKX_CFG (tl2_tl3_link_schq, link), cfg); +NIX_AF_TL3_TL2X_LINKX_CFG (tl2_tl3_link_schq, i), cfg); }/* Do SMQ flush and set enqueue xoff */
@@ -2440,10 +2439,10 @@ static int nix_smq_flush(struct rvu *rvu, int blkaddr,if (!(bmap &BIT_ULL (i)))continue ; cfg =rvu_read64 (rvu, blkaddr, -NIX_AF_TL3_TL2X_LINKX_CFG (tl2_tl3_link_schq, link)); +NIX_AF_TL3_TL2X_LINKX_CFG (tl2_tl3_link_schq, i)); cfg |=BIT_ULL (12 );rvu_write64 (rvu, blkaddr, -NIX_AF_TL3_TL2X_LINKX_CFG (tl2_tl3_link_schq, link), cfg); +NIX_AF_TL3_TL2X_LINKX_CFG (tl2_tl3_link_schq, i), cfg); }/* clear XOFF on TL2s */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1288/1376 net/rds: use wq_has_sleeper() in rds_cong_map_updated()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Allison Henderson <[email protected]>
[ Upstream commit d4f484661961636eb90d287050959e613795f73a ]
rds_cong_map_updated() runs after a peer's congestion map has been rewritten (by rds_tcp_cong_recv() and rds_ib_cong_recv(), or the clear-all in the loopback and IB send-completion paths). It bumps rds_cong_generation and then checks waitqueue_active() on map->m_waitq and on rds_poll_waitq to decide whether anyone needs waking. atomic_inc() carries no ordering and waitqueue_active() is a plain load, so nothing orders the map and generation stores before the wait queue reads. The waiters do the mirror image: rds_cong_wait() adds itself to m_waitq and then tests the port bit, and rds_poll() registers on rds_poll_waitq and then reads the generation. That is the store-buffering pattern described above waitqueue_active() in include/linux/wait.h - the updater can observe an empty wait queue while the waiter still observes the port as congested, and no wake-up is issued.
rds_cong_wait() is an interruptible sleep with no timeout, so a sender blocked on a congested port stays blocked until the next congestion update from that peer arrives or a signal is delivered. A poll() waiter misses the map-updated notification the same way.
Use wq_has_sleeper(), which is waitqueue_active() preceded by the required full barrier, as rds_tcp_state_change() already does for the same pattern.
--- net/rds/cong.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/rds/cong.c +2 -2
@@ -256,9 +256,9 @@ void rds_cong_map_updated(struct rds_cong_map *map, uint64_t portmask) map, &map->m_addr);rds_stats_inc (s_cong_update_received);atomic_inc (&rds_cong_generation); -if (waitqueue_active (&map->m_waitq)) +if (wq_has_sleeper (&map->m_waitq))wake_up (&map->m_waitq); -if (waitqueue_active (&rds_poll_waitq)) +if (wq_has_sleeper (&rds_poll_waitq))wake_up_all (&rds_poll_waitq);if (portmask && !list_empty (&rds_cong_monitor)) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1289/1376 cifs: fix clearing stats for fastest execution of each smb2 command
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frank Sorenson <[email protected]>
[ Upstream commit 48cab1fd5720508148673f59d8ed52c7c7fffca2 ]
The code to clear the 'fastest_cmd' statistics has a typo that repeatedly clears the stat for cmd 0, rather than iterating through each cmd. Fix the typo (0->i).
--- fs/smb/client/cifs_debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/smb/client/cifs_debug.c +1 -1
@@ -682,7 +682,7 @@ static ssize_t cifs_stats_proc_write(struct file *file,atomic_set (&server->smb2slowcmd[i],0 ); server->time_per_cmd[i] =0 ; server->slowest_cmd[i] =0 ; - server->fastest_cmd[0] = 0; + server->fastest_cmd[i] = 0; }#endif /* CONFIG_CIFS_STATS2 */ list_for_each_entry (ses, &server->smb_ses_list, smb_ses_list) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1290/1376 selftests/mm/cow: modify the incorrect checking parameters
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hao Ge <[email protected]>
[ Upstream commit bf069012df19cf80b460a03c92bfe6320dc268b0 ]
In run_with_memfd_hugetlb(), some error handle have passed incorrect parameters. It should be "smem", but it was mistakenly written as "mem".
Let's fix it.
Stable-dep-of: 4004c130c358 ("selftests/mm: skip COW tmpfile cases when fallocate() is unsupported")
--- tools/testing/selftests/mm/cow.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
tools/testing/selftests/mm/cow.c +5 -5
@@ -1482,7 +1482,7 @@ static void run_with_zeropage(non_anon_test_fn fn, const char *desc) } smem =mmap (NULL , pagesize,PROT_READ ,MAP_PRIVATE |MAP_ANON ,-1 ,0 ); -if (mem ==MAP_FAILED ) { +if (smem ==MAP_FAILED ) {ksft_test_result_fail ("mmap() failed\n" ); goto munmap; }
@@ -1583,7 +1583,7 @@ static void run_with_memfd(non_anon_test_fn fn, const char *desc) goto close; } smem =mmap (NULL , pagesize,PROT_READ ,MAP_SHARED , fd,0 ); -if (mem ==MAP_FAILED ) { +if (smem ==MAP_FAILED ) {ksft_test_result_fail ("mmap() failed\n" ); goto munmap; }
@@ -1634,7 +1634,7 @@ static void run_with_tmpfile(non_anon_test_fn fn, const char *desc) goto close; } smem =mmap (NULL , pagesize,PROT_READ ,MAP_SHARED , fd,0 ); -if (mem ==MAP_FAILED ) { +if (smem ==MAP_FAILED ) {ksft_test_result_fail ("mmap() failed\n" ); goto munmap; }
@@ -1684,7 +1684,7 @@ static void run_with_memfd_hugetlb(non_anon_test_fn fn, const char *desc, goto close; } smem =mmap (NULL , hugetlbsize,PROT_READ ,MAP_SHARED , fd,0 ); -if (mem ==MAP_FAILED ) { +if (smem ==MAP_FAILED ) {ksft_test_result_fail ("mmap() failed\n" ); goto munmap; }
@@ -1696,7 +1696,7 @@ static void run_with_memfd_hugetlb(non_anon_test_fn fn, const char *desc,fn (mem, smem, hugetlbsize); munmap:munmap (mem, hugetlbsize); -if (mem !=MAP_FAILED ) +if (smem !=MAP_FAILED )munmap (smem, hugetlbsize); close:close (fd);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1291/1376 selftests/mm: report unique test names for each cow test
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Brown <[email protected]>
[ Upstream commit 3f2d9a9ac544694e26c8faeb1a044c2bdcd0c793 ]
The kselftest framework uses the string logged when a test result is reported as the unique identifier for a test, using it to track test results between runs. The cow test completely fails to follow this pattern, it runs test functions repeatedly with various parameters with each result report from those functions being a string logging an error message which is fixed between runs.
Since the code already logs each test uniquely before it starts refactor to also print this to a buffer, then use that name as the test result. This isn't especially pretty but is relatively straightforward and is a great help to tooling.
Stable-dep-of: 4004c130c358 ("selftests/mm: skip COW tmpfile cases when fallocate() is unsupported")
--- tools/testing/selftests/mm/cow.c | 333 ++++++++++++++++++++----------- 1 file changed, 217 insertions(+), 116 deletions(-)
tools/testing/selftests/mm/cow.c +217 -116
@@ -112,9 +112,12 @@ struct comm_pipes {static int setup_comm_pipes (struct comm_pipes *comm_pipes) { -if (pipe (comm_pipes->child_ready) <0 ) +if (pipe (comm_pipes->child_ready) <0 ) { +ksft_perror ("pipe()" );return -errno; + }if (pipe (comm_pipes->parent_ready) <0 ) { +ksft_perror ("pipe()" );close (comm_pipes->child_ready[0 ]);close (comm_pipes->child_ready[1 ]);return -errno;
@@ -207,13 +210,14 @@ static void do_test_cow_in_parent(char *mem, size_t size, bool do_mprotect, ret =setup_comm_pipes (&comm_pipes);if (ret) { -ksft_test_result_fail ("pipe() failed\n" ); +log_test_result (KSFT_FAIL );return ; } ret =fork ();if (ret <0 ) { -ksft_test_result_fail ("fork() failed\n" ); +ksft_perror ("fork() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }else if (!ret) {exit (fn (mem, size, &comm_pipes));
@@ -228,9 +232,18 @@ static void do_test_cow_in_parent(char *mem, size_t size, bool do_mprotect,* write-faults by directly mapping pages writable. */ ret =mprotect (mem, size,PROT_READ ); - ret |=mprotect (mem, size,PROT_READ |PROT_WRITE );if (ret) { -ksft_test_result_fail ("mprotect() failed\n" ); +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); +write (comm_pipes.parent_ready[1 ],"0" ,1 ); +wait (&ret); + goto close_comm_pipes; + } + + ret =mprotect (mem, size,PROT_READ |PROT_WRITE ); +if (ret) { +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL );write (comm_pipes.parent_ready[1 ],"0" ,1 );wait (&ret); goto close_comm_pipes;
@@ -248,16 +261,16 @@ static void do_test_cow_in_parent(char *mem, size_t size, bool do_mprotect, ret = -EINVAL ;if (!ret) { -ksft_test_result_pass ("No leak from parent into child\n" ); +log_test_result (KSFT_PASS ); }else if (xfail) {/* * With hugetlb, some vmsplice() tests are currently expected to * fail because (a) harder to fix and (b) nobody really cares. * Flag them as expected failure for now. */ -ksft_test_result_xfail ("Leak from parent into child\n" ); +log_test_result (KSFT_XFAIL ); }else { -ksft_test_result_fail ("Leak from parent into child\n" ); +log_test_result (KSFT_FAIL ); } close_comm_pipes:close_comm_pipes (&comm_pipes);
@@ -306,26 +319,29 @@ static void do_test_vmsplice_in_parent(char *mem, size_t size, ret =setup_comm_pipes (&comm_pipes);if (ret) { -ksft_test_result_fail ("pipe() failed\n" ); +log_test_result (KSFT_FAIL ); goto free; }if (pipe (fds) <0 ) { -ksft_test_result_fail ("pipe() failed\n" ); +ksft_perror ("pipe() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }if (before_fork) { transferred =vmsplice (fds[1 ], &iov,1 ,0 );if (transferred <=0 ) { -ksft_test_result_fail ("vmsplice() failed\n" ); +ksft_print_msg ("vmsplice() failed\n" ); +log_test_result (KSFT_FAIL ); goto close_pipe; } } ret =fork ();if (ret <0 ) { -ksft_test_result_fail ("fork() failed\n" ); +ksft_perror ("fork() failed\n" ); +log_test_result (KSFT_FAIL ); goto close_pipe; }else if (!ret) {write (comm_pipes.child_ready[1 ],"0" ,1 );
@@ -339,7 +355,8 @@ static void do_test_vmsplice_in_parent(char *mem, size_t size,if (!before_fork) { transferred =vmsplice (fds[1 ], &iov,1 ,0 );if (transferred <=0 ) { -ksft_test_result_fail ("vmsplice() failed\n" ); +ksft_perror ("vmsplice() failed" ); +log_test_result (KSFT_FAIL );wait (&ret); goto close_pipe; }
@@ -348,7 +365,8 @@ static void do_test_vmsplice_in_parent(char *mem, size_t size,while (read (comm_pipes.child_ready[0 ], &buf,1 ) !=1 ) ;if (munmap (mem, size) <0 ) { -ksft_test_result_fail ("munmap() failed\n" ); +ksft_perror ("munmap() failed" ); +log_test_result (KSFT_FAIL ); goto close_pipe; }write (comm_pipes.parent_ready[1 ],"0" ,1 );
@@ -356,7 +374,8 @@ static void do_test_vmsplice_in_parent(char *mem, size_t size,/* Wait until the child is done writing. */ wait (&ret);if (!WIFEXITED (ret)) { -ksft_test_result_fail ("wait() failed\n" ); +ksft_perror ("wait() failed" ); +log_test_result (KSFT_FAIL ); goto close_pipe; }
@@ -364,22 +383,23 @@ static void do_test_vmsplice_in_parent(char *mem, size_t size,for (total =0 ; total < transferred; total += cur) { cur =read (fds[0 ], new + total, transferred - total);if (cur <0 ) { -ksft_test_result_fail ("read() failed\n" ); +ksft_perror ("read() failed" ); +log_test_result (KSFT_FAIL ); goto close_pipe; } }if (!memcmp (old, new, transferred)) { -ksft_test_result_pass ("No leak from child into parent\n" ); +log_test_result (KSFT_PASS ); }else if (xfail) {/* * With hugetlb, some vmsplice() tests are currently expected to * fail because (a) harder to fix and (b) nobody really cares. * Flag them as expected failure for now. */ -ksft_test_result_xfail ("Leak from child into parent\n" ); +log_test_result (KSFT_XFAIL ); }else { -ksft_test_result_fail ("Leak from child into parent\n" ); +log_test_result (KSFT_FAIL ); } close_pipe:close (fds[0 ]);
@@ -416,13 +436,14 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork) ret =setup_comm_pipes (&comm_pipes);if (ret) { -ksft_test_result_fail ("pipe() failed\n" ); +log_test_result (KSFT_FAIL );return ; } file =tmpfile ();if (!file) { -ksft_test_result_fail ("tmpfile() failed\n" ); +ksft_perror ("tmpfile() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; } fd =fileno (file);
@@ -430,14 +451,16 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork) tmp =malloc (size);if (!tmp) { -ksft_test_result_fail ("malloc() failed\n" ); +ksft_print_msg ("malloc() failed\n" ); +log_test_result (KSFT_FAIL ); goto close_file; }/* Skip on errors, as we might just lack kernel support. */ ret =io_uring_queue_init (1 , &ring,0 );if (ret <0 ) { -ksft_test_result_skip ("io_uring_queue_init() failed\n" ); +ksft_print_msg ("io_uring_queue_init() failed\n" ); +log_test_result (KSFT_SKIP ); goto free_tmp; }
@@ -452,7 +475,8 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork) iov.iov_len = size; ret =io_uring_register_buffers (&ring, &iov,1 );if (ret) { -ksft_test_result_skip ("io_uring_register_buffers() failed\n" ); +ksft_print_msg ("io_uring_register_buffers() failed\n" ); +log_test_result (KSFT_SKIP ); goto queue_exit; }
@@ -463,7 +487,8 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork)*/ ret =fork ();if (ret <0 ) { -ksft_test_result_fail ("fork() failed\n" ); +ksft_perror ("fork() failed" ); +log_test_result (KSFT_FAIL ); goto unregister_buffers; }else if (!ret) {write (comm_pipes.child_ready[1 ],"0" ,1 );
@@ -483,10 +508,17 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork)* if the page is mapped R/O vs. R/W). */ ret =mprotect (mem, size,PROT_READ ); +if (ret) { +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); + goto unregister_buffers; + } +clear_softdirty (); - ret |=mprotect (mem, size,PROT_READ |PROT_WRITE ); + ret =mprotect (mem, size,PROT_READ |PROT_WRITE );if (ret) { -ksft_test_result_fail ("mprotect() failed\n" ); +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); goto unregister_buffers; } }
@@ -498,25 +530,29 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork)memset (mem,0xff , size); sqe =io_uring_get_sqe (&ring);if (!sqe) { -ksft_test_result_fail ("io_uring_get_sqe() failed\n" ); +ksft_print_msg ("io_uring_get_sqe() failed\n" ); +log_test_result (KSFT_FAIL ); goto quit_child; }io_uring_prep_write_fixed (sqe, fd, mem, size,0 ,0 ); ret =io_uring_submit (&ring);if (ret <0 ) { -ksft_test_result_fail ("io_uring_submit() failed\n" ); +ksft_print_msg ("io_uring_submit() failed\n" ); +log_test_result (KSFT_FAIL ); goto quit_child; } ret =io_uring_wait_cqe (&ring, &cqe);if (ret <0 ) { -ksft_test_result_fail ("io_uring_wait_cqe() failed\n" ); +ksft_print_msg ("io_uring_wait_cqe() failed\n" ); +log_test_result (KSFT_FAIL ); goto quit_child; }if (cqe->res != size) { -ksft_test_result_fail ("write_fixed failed\n" ); +ksft_print_msg ("write_fixed failed\n" ); +log_test_result (KSFT_FAIL ); goto quit_child; }io_uring_cqe_seen (&ring, cqe);
@@ -526,15 +562,18 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork)while (total < size) { cur =pread (fd, tmp + total, size - total, total);if (cur <0 ) { -ksft_test_result_fail ("pread() failed\n" ); +ksft_print_msg ("pread() failed\n" ); +log_test_result (KSFT_FAIL ); goto quit_child; } total += cur; }/* Finally, check if we read what we expected. */ -ksft_test_result (!memcmp (mem, tmp, size), -"Longterm R/W pin is reliable\n" ); +if (!memcmp (mem, tmp, size)) +log_test_result (KSFT_PASS ); +else +log_test_result (KSFT_FAIL ); quit_child:if (use_fork) {
@@ -582,19 +621,21 @@ static void do_test_ro_pin(char *mem, size_t size, enum ro_pin_test test,int ret;if (gup_fd <0 ) { -ksft_test_result_skip ("gup_test not available\n" ); +ksft_print_msg ("gup_test not available\n" ); +log_test_result (KSFT_SKIP );return ; } tmp =malloc (size);if (!tmp) { -ksft_test_result_fail ("malloc() failed\n" ); +ksft_print_msg ("malloc() failed\n" ); +log_test_result (KSFT_FAIL );return ; } ret =setup_comm_pipes (&comm_pipes);if (ret) { -ksft_test_result_fail ("pipe() failed\n" ); +log_test_result (KSFT_FAIL ); goto free_tmp; }
@@ -609,7 +650,8 @@ static void do_test_ro_pin(char *mem, size_t size, enum ro_pin_test test,*/ ret =fork ();if (ret <0 ) { -ksft_test_result_fail ("fork() failed\n" ); +ksft_perror ("fork() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }else if (!ret) {write (comm_pipes.child_ready[1 ],"0" ,1 );
@@ -646,7 +688,8 @@ static void do_test_ro_pin(char *mem, size_t size, enum ro_pin_test test,clear_softdirty (); ret |=mprotect (mem, size,PROT_READ |PROT_WRITE );if (ret) { -ksft_test_result_fail ("mprotect() failed\n" ); +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }break ;
@@ -661,9 +704,11 @@ static void do_test_ro_pin(char *mem, size_t size, enum ro_pin_test test, ret =ioctl (gup_fd,PIN_LONGTERM_TEST_START , &args);if (ret) {if (errno ==EINVAL ) -ksft_test_result_skip ("PIN_LONGTERM_TEST_START failed\n" ); + ret =KSFT_SKIP ;else -ksft_test_result_fail ("PIN_LONGTERM_TEST_START failed\n" ); + ret =KSFT_FAIL ; +ksft_perror ("PIN_LONGTERM_TEST_START failed" ); +log_test_result (ret); goto wait; }
@@ -676,22 +721,26 @@ static void do_test_ro_pin(char *mem, size_t size, enum ro_pin_test test,*/ tmp_val = (__u64 )(uintptr_t )tmp; ret =ioctl (gup_fd,PIN_LONGTERM_TEST_READ , &tmp_val); -if (ret) -ksft_test_result_fail ("PIN_LONGTERM_TEST_READ failed\n" ); -else -ksft_test_result (!memcmp (mem, tmp, size), -"Longterm R/O pin is reliable\n" ); +if (ret) { +ksft_perror ("PIN_LONGTERM_TEST_READ failed" ); +log_test_result (KSFT_FAIL ); + }else { +if (!memcmp (mem, tmp, size)) +log_test_result (KSFT_PASS ); +else +log_test_result (KSFT_FAIL ); + } ret =ioctl (gup_fd,PIN_LONGTERM_TEST_STOP );if (ret) -ksft_print_msg ("[INFO] PIN_LONGTERM_TEST_STOP failed\n" ); +ksft_perror ("PIN_LONGTERM_TEST_STOP failed" ); wait:switch (test) {case RO_PIN_TEST_SHARED :write (comm_pipes.parent_ready[1 ],"0" ,1 );wait (&ret);if (!WIFEXITED (ret)) -ksft_print_msg ("[INFO] wait() failed\n" ); +ksft_perror ("wait() failed" );break ;default :break ;
@@ -746,14 +795,16 @@ static void do_run_with_base_page(test_fn fn, bool swapout) mem =mmap (NULL , pagesize,PROT_READ |PROT_WRITE ,MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 );if (mem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL );return ; } ret =madvise (mem, pagesize,MADV_NOHUGEPAGE );/* Ignore if not around on a kernel. */ if (ret && errno !=EINVAL ) { -ksft_test_result_fail ("MADV_NOHUGEPAGE failed\n" ); +ksft_perror ("MADV_NOHUGEPAGE failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }
@@ -763,7 +814,8 @@ static void do_run_with_base_page(test_fn fn, bool swapout)if (swapout) {madvise (mem, pagesize,MADV_PAGEOUT );if (!pagemap_is_swapped (pagemap_fd, mem)) { -ksft_test_result_skip ("MADV_PAGEOUT did not work, is swap enabled?\n" ); +ksft_print_msg ("MADV_PAGEOUT did not work, is swap enabled?\n" ); +log_test_result (KSFT_SKIP ); goto munmap; } }
@@ -775,13 +827,13 @@ static void do_run_with_base_page(test_fn fn, bool swapout)static void run_with_base_page (test_fn fn,const char *desc) { -ksft_print_msg ("[RUN] %s ... with base page\n" , desc); +log_test_start ("%s ... with base page" , desc);do_run_with_base_page (fn, false); }static void run_with_base_page_swap (test_fn fn,const char *desc) { -ksft_print_msg ("[RUN] %s ... with swapped out base page\n" , desc); +log_test_start ("%s ... with swapped out base page" , desc);do_run_with_base_page (fn, true); }
@@ -807,7 +859,8 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize) mmap_mem =mmap (NULL , mmap_size,PROT_READ |PROT_WRITE ,MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 );if (mmap_mem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL );return ; }
@@ -816,7 +869,8 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize) ret =madvise (mem, thpsize,MADV_HUGEPAGE );if (ret) { -ksft_test_result_fail ("MADV_HUGEPAGE failed\n" ); +ksft_perror ("MADV_HUGEPAGE failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }
@@ -826,7 +880,8 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)*/ mem[0 ] =1 ;if (!pagemap_is_populated (pagemap_fd, mem + thpsize - pagesize)) { -ksft_test_result_skip ("Did not get a THP populated\n" ); +ksft_print_msg ("Did not get a THP populated\n" ); +log_test_result (KSFT_SKIP ); goto munmap; }memset (mem,1 , thpsize);
@@ -846,12 +901,14 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)*/ ret =mprotect (mem + pagesize, pagesize,PROT_READ );if (ret) { -ksft_test_result_fail ("mprotect() failed\n" ); +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; } ret =mprotect (mem + pagesize, pagesize,PROT_READ |PROT_WRITE );if (ret) { -ksft_test_result_fail ("mprotect() failed\n" ); +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }break ;
@@ -863,7 +920,8 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)*/ ret =madvise (mem + pagesize, thpsize - pagesize,MADV_DONTNEED );if (ret) { -ksft_test_result_fail ("MADV_DONTNEED failed\n" ); +ksft_perror ("MADV_DONTNEED failed" ); +log_test_result (KSFT_FAIL ); goto munmap; } size = pagesize;
@@ -877,13 +935,15 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize) mremap_mem =mmap (NULL , mremap_size,PROT_NONE ,MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 );if (mremap_mem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; } tmp =mremap (mem + mremap_size, mremap_size, mremap_size,MREMAP_MAYMOVE |MREMAP_FIXED , mremap_mem);if (tmp != mremap_mem) { -ksft_test_result_fail ("mremap() failed\n" ); +ksft_perror ("mremap() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; } size = mremap_size;
@@ -896,12 +956,14 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)*/ ret =madvise (mem + pagesize, thpsize - pagesize,MADV_DONTFORK );if (ret) { -ksft_test_result_fail ("MADV_DONTFORK failed\n" ); +ksft_perror ("MADV_DONTFORK failed" ); +log_test_result (KSFT_FAIL ); goto munmap; } ret =fork ();if (ret <0 ) { -ksft_test_result_fail ("fork() failed\n" ); +ksft_perror ("fork() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }else if (!ret) {exit (0 );
@@ -910,7 +972,8 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)/* Allow for sharing all pages again. */ ret =madvise (mem + pagesize, thpsize - pagesize,MADV_DOFORK );if (ret) { -ksft_test_result_fail ("MADV_DOFORK failed\n" ); +ksft_perror ("MADV_DOFORK failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }break ;
@@ -924,7 +987,8 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)case THP_RUN_SINGLE_PTE_SWAPOUT :madvise (mem, size,MADV_PAGEOUT );if (!range_is_swapped (mem, size)) { -ksft_test_result_skip ("MADV_PAGEOUT did not work, is swap enabled?\n" ); +ksft_print_msg ("MADV_PAGEOUT did not work, is swap enabled?\n" ); +log_test_result (KSFT_SKIP ); goto munmap; }break ;
@@ -941,56 +1005,56 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)static void run_with_thp (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with THP (%zu kB)\n" , +log_test_start ("%s ... with THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_PMD , size); }static void run_with_thp_swap (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with swapped-out THP (%zu kB)\n" , +log_test_start ("%s ... with swapped-out THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_PMD_SWAPOUT , size); }static void run_with_pte_mapped_thp (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with PTE-mapped THP (%zu kB)\n" , +log_test_start ("%s ... with PTE-mapped THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_PTE , size); }static void run_with_pte_mapped_thp_swap (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with swapped-out, PTE-mapped THP (%zu kB)\n" , +log_test_start ("%s ... with swapped-out, PTE-mapped THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_PTE_SWAPOUT , size); }static void run_with_single_pte_of_thp (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with single PTE of THP (%zu kB)\n" , +log_test_start ("%s ... with single PTE of THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_SINGLE_PTE , size); }static void run_with_single_pte_of_thp_swap (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with single PTE of swapped-out THP (%zu kB)\n" , +log_test_start ("%s ... with single PTE of swapped-out THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_SINGLE_PTE_SWAPOUT , size); }static void run_with_partial_mremap_thp (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with partially mremap()'ed THP (%zu kB)\n" , +log_test_start ("%s ... with partially mremap()'ed THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_PARTIAL_MREMAP , size); }static void run_with_partial_shared_thp (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with partially shared THP (%zu kB)\n" , +log_test_start ("%s ... with partially shared THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_PARTIAL_SHARED , size); }
@@ -1000,14 +1064,15 @@ static void run_with_hugetlb(test_fn fn, const char *desc, size_t hugetlbsize)int flags =MAP_PRIVATE |MAP_ANONYMOUS |MAP_HUGETLB ;char *mem, *dummy; -ksft_print_msg ("[RUN] %s ... with hugetlb (%zu kB)\n" , desc, +log_test_start ("%s ... with hugetlb (%zu kB)" , desc, hugetlbsize /1024 ); flags |=__builtin_ctzll (hugetlbsize) <<MAP_HUGE_SHIFT ; mem =mmap (NULL , hugetlbsize,PROT_READ |PROT_WRITE , flags,-1 ,0 );if (mem ==MAP_FAILED ) { -ksft_test_result_skip ("need more free huge pages\n" ); +ksft_perror ("need more free huge pages" ); +log_test_result (KSFT_SKIP );return ; }
@@ -1020,7 +1085,8 @@ static void run_with_hugetlb(test_fn fn, const char *desc, size_t hugetlbsize)*/ dummy =mmap (NULL , hugetlbsize,PROT_READ |PROT_WRITE , flags,-1 ,0 );if (dummy ==MAP_FAILED ) { -ksft_test_result_skip ("need more free huge pages\n" ); +ksft_perror ("need more free huge pages" ); +log_test_result (KSFT_SKIP ); goto munmap; }munmap (dummy, hugetlbsize);
@@ -1226,7 +1292,7 @@ static void do_test_anon_thp_collapse(char *mem, size_t size, ret =setup_comm_pipes (&comm_pipes);if (ret) { -ksft_test_result_fail ("pipe() failed\n" ); +log_test_result (KSFT_FAIL );return ; }
@@ -1236,12 +1302,14 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,*/ ret =mprotect (mem + pagesize, pagesize,PROT_READ );if (ret) { -ksft_test_result_fail ("mprotect() failed\n" ); +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; } ret =mprotect (mem + pagesize, pagesize,PROT_READ |PROT_WRITE );if (ret) { -ksft_test_result_fail ("mprotect() failed\n" ); +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }
@@ -1250,8 +1318,8 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,/* Collapse before actually COW-sharing the page. */ ret =madvise (mem, size,MADV_COLLAPSE );if (ret) { -ksft_test_result_skip ("MADV_COLLAPSE failed: %s\n" , -strerror (errno)); +ksft_perror ("MADV_COLLAPSE failed" ); +log_test_result (KSFT_SKIP ); goto close_comm_pipes; }break ;
@@ -1262,7 +1330,8 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,/* Don't COW-share the upper part of the THP. */ ret =madvise (mem + size /2 , size /2 ,MADV_DONTFORK );if (ret) { -ksft_test_result_fail ("MADV_DONTFORK failed\n" ); +ksft_perror ("MADV_DONTFORK failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }break ;
@@ -1270,7 +1339,8 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,/* Don't COW-share the lower part of the THP. */ ret =madvise (mem, size /2 ,MADV_DONTFORK );if (ret) { -ksft_test_result_fail ("MADV_DONTFORK failed\n" ); +ksft_perror ("MADV_DONTFORK failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }break ;
@@ -1280,7 +1350,8 @@ static void do_test_anon_thp_collapse(char *mem, size_t size, ret =fork ();if (ret <0 ) { -ksft_test_result_fail ("fork() failed\n" ); +ksft_perror ("fork() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }else if (!ret) {switch (test) {
@@ -1314,7 +1385,8 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,*/ ret =madvise (mem, size,MADV_DOFORK );if (ret) { -ksft_test_result_fail ("MADV_DOFORK failed\n" ); +ksft_perror ("MADV_DOFORK failed" ); +log_test_result (KSFT_FAIL );write (comm_pipes.parent_ready[1 ],"0" ,1 );wait (&ret); goto close_comm_pipes;
@@ -1324,8 +1396,8 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,/* Collapse before anyone modified the COW-shared page. */ ret =madvise (mem, size,MADV_COLLAPSE );if (ret) { -ksft_test_result_skip ("MADV_COLLAPSE failed: %s\n" , -strerror (errno)); +ksft_perror ("MADV_COLLAPSE failed" ); +log_test_result (KSFT_SKIP );write (comm_pipes.parent_ready[1 ],"0" ,1 );wait (&ret); goto close_comm_pipes;
@@ -1345,7 +1417,10 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,else ret = -EINVAL ; -ksft_test_result (!ret,"No leak from parent into child\n" ); +if (!ret) +log_test_result (KSFT_PASS ); +else +log_test_result (KSFT_FAIL ); close_comm_pipes:close_comm_pipes (&comm_pipes); }
@@ -1430,7 +1505,7 @@ static void run_anon_thp_test_cases(void)for (i =0 ; i <ARRAY_SIZE (anon_thp_test_cases); i++) {struct test_case const *test_case = &anon_thp_test_cases[i]; -ksft_print_msg ("[RUN] %s\n" , test_case->desc); +log_test_start ("%s" , test_case->desc);do_run_with_thp (test_case->fn,THP_RUN_PMD , pmdsize); } }
@@ -1453,8 +1528,10 @@ static void test_cow(char *mem, const char *smem, size_t size)memset (mem,0xff , size);/* See if we still read the old values via the other mapping. */ -ksft_test_result (!memcmp (smem, old, size), -"Other mapping not modified\n" ); +if (!memcmp (smem, old, size)) +log_test_result (KSFT_PASS ); +else +log_test_result (KSFT_FAIL );free (old); }
@@ -1472,18 +1549,20 @@ static void run_with_zeropage(non_anon_test_fn fn, const char *desc) {char *mem, *smem, tmp; -ksft_print_msg ("[RUN] %s ... with shared zeropage\n" , desc); +log_test_start ("%s ... with shared zeropage" , desc); mem =mmap (NULL , pagesize,PROT_READ |PROT_WRITE ,MAP_PRIVATE |MAP_ANON ,-1 ,0 );if (mem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL );return ; } smem =mmap (NULL , pagesize,PROT_READ ,MAP_PRIVATE |MAP_ANON ,-1 ,0 );if (smem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }
@@ -1504,10 +1583,11 @@ static void run_with_huge_zeropage(non_anon_test_fn fn, const char *desc)size_t mmap_size;int ret; -ksft_print_msg ("[RUN] %s ... with huge zeropage\n" , desc); +log_test_start ("%s ... with huge zeropage" , desc);if (!has_huge_zeropage) { -ksft_test_result_skip ("Huge zeropage not enabled\n" ); +ksft_print_msg ("Huge zeropage not enabled\n" ); +log_test_result (KSFT_SKIP );return ; }
@@ -1516,13 +1596,15 @@ static void run_with_huge_zeropage(non_anon_test_fn fn, const char *desc) mmap_mem =mmap (NULL , mmap_size,PROT_READ |PROT_WRITE ,MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 );if (mmap_mem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL );return ; } mmap_smem =mmap (NULL , mmap_size,PROT_READ ,MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 );if (mmap_smem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }
@@ -1531,9 +1613,15 @@ static void run_with_huge_zeropage(non_anon_test_fn fn, const char *desc) smem = (char *)(((uintptr_t )mmap_smem + pmdsize) & ~(pmdsize -1 )); ret =madvise (mem, pmdsize,MADV_HUGEPAGE ); +if (ret !=0 ) { +ksft_perror ("madvise()" ); +log_test_result (KSFT_FAIL ); + goto munmap; + } ret |=madvise (smem, pmdsize,MADV_HUGEPAGE ); -if (ret) { -ksft_test_result_fail ("MADV_HUGEPAGE failed\n" ); +if (ret !=0 ) { +ksft_perror ("madvise()" ); +log_test_result (KSFT_FAIL ); goto munmap; }
@@ -1562,29 +1650,33 @@ static void run_with_memfd(non_anon_test_fn fn, const char *desc)char *mem, *smem, tmp;int fd; -ksft_print_msg ("[RUN] %s ... with memfd\n" , desc); +log_test_start ("%s ... with memfd" , desc); fd =memfd_create ("test" ,0 );if (fd <0 ) { -ksft_test_result_fail ("memfd_create() failed\n" ); +ksft_perror ("memfd_create() failed" ); +log_test_result (KSFT_FAIL );return ; }/* File consists of a single page filled with zeroes. */ if (fallocate (fd,0 ,0 , pagesize)) { -ksft_test_result_fail ("fallocate() failed\n" ); +ksft_perror ("fallocate() failed" ); +log_test_result (KSFT_FAIL ); goto close; }/* Create a private mapping of the memfd. */ mem =mmap (NULL , pagesize,PROT_READ |PROT_WRITE ,MAP_PRIVATE , fd,0 );if (mem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto close; } smem =mmap (NULL , pagesize,PROT_READ ,MAP_SHARED , fd,0 );if (smem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }
@@ -1607,35 +1699,40 @@ static void run_with_tmpfile(non_anon_test_fn fn, const char *desc)FILE *file;int fd; -ksft_print_msg ("[RUN] %s ... with tmpfile\n" , desc); +log_test_start ("%s ... with tmpfile" , desc); file =tmpfile ();if (!file) { -ksft_test_result_fail ("tmpfile() failed\n" ); +ksft_perror ("tmpfile() failed" ); +log_test_result (KSFT_FAIL );return ; } fd =fileno (file);if (fd <0 ) { -ksft_test_result_skip ("fileno() failed\n" ); +ksft_perror ("fileno() failed" ); +log_test_result (KSFT_SKIP );return ; }/* File consists of a single page filled with zeroes. */ if (fallocate (fd,0 ,0 , pagesize)) { -ksft_test_result_fail ("fallocate() failed\n" ); +ksft_perror ("fallocate() failed" ); +log_test_result (KSFT_FAIL ); goto close; }/* Create a private mapping of the memfd. */ mem =mmap (NULL , pagesize,PROT_READ |PROT_WRITE ,MAP_PRIVATE , fd,0 );if (mem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto close; } smem =mmap (NULL , pagesize,PROT_READ ,MAP_SHARED , fd,0 );if (smem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }
@@ -1659,20 +1756,22 @@ static void run_with_memfd_hugetlb(non_anon_test_fn fn, const char *desc,char *mem, *smem, tmp;int fd; -ksft_print_msg ("[RUN] %s ... with memfd hugetlb (%zu kB)\n" , desc, +log_test_start ("%s ... with memfd hugetlb (%zu kB)" , desc, hugetlbsize /1024 ); flags |=__builtin_ctzll (hugetlbsize) <<MFD_HUGE_SHIFT ; fd =memfd_create ("test" , flags);if (fd <0 ) { -ksft_test_result_skip ("memfd_create() failed\n" ); +ksft_perror ("memfd_create() failed" ); +log_test_result (KSFT_SKIP );return ; }/* File consists of a single page filled with zeroes. */ if (fallocate (fd,0 ,0 , hugetlbsize)) { -ksft_test_result_skip ("need more free huge pages\n" ); +ksft_perror ("need more free huge pages" ); +log_test_result (KSFT_SKIP ); goto close; }
@@ -1680,12 +1779,14 @@ static void run_with_memfd_hugetlb(non_anon_test_fn fn, const char *desc, mem =mmap (NULL , hugetlbsize,PROT_READ |PROT_WRITE ,MAP_PRIVATE , fd,0 );if (mem ==MAP_FAILED ) { -ksft_test_result_skip ("need more free huge pages\n" ); +ksft_perror ("need more free huge pages" ); +log_test_result (KSFT_SKIP ); goto close; } smem =mmap (NULL , hugetlbsize,PROT_READ ,MAP_SHARED , fd,0 );if (smem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }
Signature · 1 line
2.53.0
Re: [PATCH 6.12 1291/1376] selftests/mm: report unique test names for each cow test
Quoted 54 lines · Greg Kroah-Hartman
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mark Brown <[email protected]>
[ Upstream commit
3f2d9a9ac544694e26c8faeb1a044c2bdcd0c793]The kselftest framework uses the string logged when a test result is reported as the unique identifier for a test, using it to track test results between runs. The cow test completely fails to follow this pattern, it runs test functions repeatedly with various parameters with each result report from those functions being a string logging an error message which is fixed between runs.
Since the code already logs each test uniquely before it starts refactor to also print this to a buffer, then use that name as the test result. This isn't especially pretty but is relatively straightforward and is a great help to tooling.
Signed-off-by Mark Brown <[email protected]>Cc David Hildenbrand <[email protected]>Cc Lorenzo Stoakes <[email protected]>Cc Shuah Khan <[email protected]>Signed-off-by Andrew Morton <[email protected]>Stable-dep-of:
4004c130c358("selftests/mm: skip COW tmpfile cases whenfallocate()is unsupported")Signed-off-by Sasha Levin <[email protected]>--- tools/testing/selftests/mm/cow.c | 333 ++++++++++++++++++++----------- 1 file changed, 217 insertions(+), 116 deletions(-)tools/testing/selftests/mm/cow.c +4
-1@@ -112,9 +112,12 @@ struct comm_pipes {static int setup_comm_pipes (struct comm_pipes *comm_pipes) { -if (pipe (comm_pipes->child_ready) <0 ) +if (pipe (comm_pipes->child_ready) <0 ) { +ksft_perror ("pipe()" );return -errno; + }if (pipe (comm_pipes->parent_ready) <0 ) { +ksft_perror ("pipe()" );close (comm_pipes->child_ready[0 ]);close (comm_pipes->child_ready[1 ]);return -errno;@@ -207,13 +210,14 @@ static void do_test_cow_in_parent(char *mem, size_t size, bool do_mprotect, ret =setup_comm_pipes (&comm_pipes);if (ret) {
tools/testing/selftests/mm/cow.c static void do_test_cow_in_parent(char *mem, size_t size, bool do_mprotect, · line 220
Quoted 10 lines
tools/testing/selftests/mm/cow.c +3
-2-ksft_test_result_fail ("pipe() failed\n" ); +log_test_result (KSFT_FAIL );return ; } ret =fork ();if (ret <0 ) { -ksft_test_result_fail ("fork() failed\n" ); +ksft_perror ("fork() failed" ); +log_test_result (KSFT_FAIL );
Hi Greg/Sasha,
I ran an AI-assisted backport review, and I have verified the report. It looks valid to me.
Upstream prerequisite code:
static inline void log_test_result(int result)
{
ksft_test_result_report(result, "%s\n", test_name);
}Downstream 6.12.y COW test code:
log_test_result(KSFT_FAIL);
log_test_start("%s ... with base page", desc);The converted COW test calls log_test_start() and log_test_result(), but the 6.12 vm_util.h contains neither helper. A targeted compile fails at those calls, while adding the upstream header helper makes it succeed.
I think 6.12.y misses 3f192afbede24c60e59db1272ad155a3a44f5fe7, "selftests/mm: add helper for logging test start and results". I suggest applying it before this patch and rebuilding the MM selftests. Thoughts?
Greg/Sasha: Maybe we should compile a foile list where we don't want to backport. From my earlier underatanding, we don't backport selftest fixes to stable - selftest (except for bpf are meant to be using upstream ones for even the older kernels)
thanks,
Harshit
Quoted 936 lines
tools/testing/selftests/mm/cow.c +210
-113goto close_comm_pipes; }else if (!ret) {exit (fn (mem, size, &comm_pipes));@@ -228,9 +232,18 @@ static void do_test_cow_in_parent(char *mem, size_t size, bool do_mprotect,* write-faults by directly mapping pages writable. */ ret =mprotect (mem, size,PROT_READ ); - ret |=mprotect (mem, size,PROT_READ |PROT_WRITE );if (ret) { -ksft_test_result_fail ("mprotect() failed\n" ); +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); +write (comm_pipes.parent_ready[1 ],"0" ,1 ); +wait (&ret); + goto close_comm_pipes; + } + + ret =mprotect (mem, size,PROT_READ |PROT_WRITE ); +if (ret) { +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL );write (comm_pipes.parent_ready[1 ],"0" ,1 );wait (&ret); goto close_comm_pipes;@@ -248,16 +261,16 @@ static void do_test_cow_in_parent(char *mem, size_t size, bool do_mprotect, ret = -EINVAL ;if (!ret) { -ksft_test_result_pass ("No leak from parent into child\n" ); +log_test_result (KSFT_PASS ); }else if (xfail) {/* * With hugetlb, some vmsplice() tests are currently expected to * fail because (a) harder to fix and (b) nobody really cares. * Flag them as expected failure for now. */ -ksft_test_result_xfail ("Leak from parent into child\n" ); +log_test_result (KSFT_XFAIL ); }else { -ksft_test_result_fail ("Leak from parent into child\n" ); +log_test_result (KSFT_FAIL ); } close_comm_pipes:close_comm_pipes (&comm_pipes);@@ -306,26 +319,29 @@ static void do_test_vmsplice_in_parent(char *mem, size_t size, ret =setup_comm_pipes (&comm_pipes);if (ret) { -ksft_test_result_fail ("pipe() failed\n" ); +log_test_result (KSFT_FAIL ); goto free; }if (pipe (fds) <0 ) { -ksft_test_result_fail ("pipe() failed\n" ); +ksft_perror ("pipe() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }if (before_fork) { transferred =vmsplice (fds[1 ], &iov,1 ,0 );if (transferred <=0 ) { -ksft_test_result_fail ("vmsplice() failed\n" ); +ksft_print_msg ("vmsplice() failed\n" ); +log_test_result (KSFT_FAIL ); goto close_pipe; } } ret =fork ();if (ret <0 ) { -ksft_test_result_fail ("fork() failed\n" ); +ksft_perror ("fork() failed\n" ); +log_test_result (KSFT_FAIL ); goto close_pipe; }else if (!ret) {write (comm_pipes.child_ready[1 ],"0" ,1 );@@ -339,7 +355,8 @@ static void do_test_vmsplice_in_parent(char *mem, size_t size,if (!before_fork) { transferred =vmsplice (fds[1 ], &iov,1 ,0 );if (transferred <=0 ) { -ksft_test_result_fail ("vmsplice() failed\n" ); +ksft_perror ("vmsplice() failed" ); +log_test_result (KSFT_FAIL );wait (&ret); goto close_pipe; }@@ -348,7 +365,8 @@ static void do_test_vmsplice_in_parent(char *mem, size_t size,while (read (comm_pipes.child_ready[0 ], &buf,1 ) !=1 ) ;if (munmap (mem, size) <0 ) { -ksft_test_result_fail ("munmap() failed\n" ); +ksft_perror ("munmap() failed" ); +log_test_result (KSFT_FAIL ); goto close_pipe; }write (comm_pipes.parent_ready[1 ],"0" ,1 );@@ -356,7 +374,8 @@ static void do_test_vmsplice_in_parent(char *mem, size_t size,/* Wait until the child is done writing. */ wait (&ret);if (!WIFEXITED (ret)) { -ksft_test_result_fail ("wait() failed\n" ); +ksft_perror ("wait() failed" ); +log_test_result (KSFT_FAIL ); goto close_pipe; }@@ -364,22 +383,23 @@ static void do_test_vmsplice_in_parent(char *mem, size_t size,for (total =0 ; total < transferred; total += cur) { cur =read (fds[0 ], new + total, transferred - total);if (cur <0 ) { -ksft_test_result_fail ("read() failed\n" ); +ksft_perror ("read() failed" ); +log_test_result (KSFT_FAIL ); goto close_pipe; } }if (!memcmp (old, new, transferred)) { -ksft_test_result_pass ("No leak from child into parent\n" ); +log_test_result (KSFT_PASS ); }else if (xfail) {/* * With hugetlb, some vmsplice() tests are currently expected to * fail because (a) harder to fix and (b) nobody really cares. * Flag them as expected failure for now. */ -ksft_test_result_xfail ("Leak from child into parent\n" ); +log_test_result (KSFT_XFAIL ); }else { -ksft_test_result_fail ("Leak from child into parent\n" ); +log_test_result (KSFT_FAIL ); } close_pipe:close (fds[0 ]);@@ -416,13 +436,14 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork) ret =setup_comm_pipes (&comm_pipes);if (ret) { -ksft_test_result_fail ("pipe() failed\n" ); +log_test_result (KSFT_FAIL );return ; } file =tmpfile ();if (!file) { -ksft_test_result_fail ("tmpfile() failed\n" ); +ksft_perror ("tmpfile() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; } fd =fileno (file);@@ -430,14 +451,16 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork) tmp =malloc (size);if (!tmp) { -ksft_test_result_fail ("malloc() failed\n" ); +ksft_print_msg ("malloc() failed\n" ); +log_test_result (KSFT_FAIL ); goto close_file; }/* Skip on errors, as we might just lack kernel support. */ ret =io_uring_queue_init (1 , &ring,0 );if (ret <0 ) { -ksft_test_result_skip ("io_uring_queue_init() failed\n" ); +ksft_print_msg ("io_uring_queue_init() failed\n" ); +log_test_result (KSFT_SKIP ); goto free_tmp; }@@ -452,7 +475,8 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork) iov.iov_len = size; ret =io_uring_register_buffers (&ring, &iov,1 );if (ret) { -ksft_test_result_skip ("io_uring_register_buffers() failed\n" ); +ksft_print_msg ("io_uring_register_buffers() failed\n" ); +log_test_result (KSFT_SKIP ); goto queue_exit; }@@ -463,7 +487,8 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork)*/ ret =fork ();if (ret <0 ) { -ksft_test_result_fail ("fork() failed\n" ); +ksft_perror ("fork() failed" ); +log_test_result (KSFT_FAIL ); goto unregister_buffers; }else if (!ret) {write (comm_pipes.child_ready[1 ],"0" ,1 );@@ -483,10 +508,17 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork)* if the page is mapped R/O vs. R/W). */ ret =mprotect (mem, size,PROT_READ ); +if (ret) { +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); + goto unregister_buffers; + } +clear_softdirty (); - ret |=mprotect (mem, size,PROT_READ |PROT_WRITE ); + ret =mprotect (mem, size,PROT_READ |PROT_WRITE );if (ret) { -ksft_test_result_fail ("mprotect() failed\n" ); +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); goto unregister_buffers; } }@@ -498,25 +530,29 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork)memset (mem,0xff , size); sqe =io_uring_get_sqe (&ring);if (!sqe) { -ksft_test_result_fail ("io_uring_get_sqe() failed\n" ); +ksft_print_msg ("io_uring_get_sqe() failed\n" ); +log_test_result (KSFT_FAIL ); goto quit_child; }io_uring_prep_write_fixed (sqe, fd, mem, size,0 ,0 ); ret =io_uring_submit (&ring);if (ret <0 ) { -ksft_test_result_fail ("io_uring_submit() failed\n" ); +ksft_print_msg ("io_uring_submit() failed\n" ); +log_test_result (KSFT_FAIL ); goto quit_child; } ret =io_uring_wait_cqe (&ring, &cqe);if (ret <0 ) { -ksft_test_result_fail ("io_uring_wait_cqe() failed\n" ); +ksft_print_msg ("io_uring_wait_cqe() failed\n" ); +log_test_result (KSFT_FAIL ); goto quit_child; }if (cqe->res != size) { -ksft_test_result_fail ("write_fixed failed\n" ); +ksft_print_msg ("write_fixed failed\n" ); +log_test_result (KSFT_FAIL ); goto quit_child; }io_uring_cqe_seen (&ring, cqe);@@ -526,15 +562,18 @@ static void do_test_iouring(char *mem, size_t size, bool use_fork)while (total < size) { cur =pread (fd, tmp + total, size - total, total);if (cur <0 ) { -ksft_test_result_fail ("pread() failed\n" ); +ksft_print_msg ("pread() failed\n" ); +log_test_result (KSFT_FAIL ); goto quit_child; } total += cur; }/* Finally, check if we read what we expected. */ -ksft_test_result (!memcmp (mem, tmp, size), -"Longterm R/W pin is reliable\n" ); +if (!memcmp (mem, tmp, size)) +log_test_result (KSFT_PASS ); +else +log_test_result (KSFT_FAIL ); quit_child:if (use_fork) {@@ -582,19 +621,21 @@ static void do_test_ro_pin(char *mem, size_t size, enum ro_pin_test test,int ret;if (gup_fd <0 ) { -ksft_test_result_skip ("gup_test not available\n" ); +ksft_print_msg ("gup_test not available\n" ); +log_test_result (KSFT_SKIP );return ; } tmp =malloc (size);if (!tmp) { -ksft_test_result_fail ("malloc() failed\n" ); +ksft_print_msg ("malloc() failed\n" ); +log_test_result (KSFT_FAIL );return ; } ret =setup_comm_pipes (&comm_pipes);if (ret) { -ksft_test_result_fail ("pipe() failed\n" ); +log_test_result (KSFT_FAIL ); goto free_tmp; }@@ -609,7 +650,8 @@ static void do_test_ro_pin(char *mem, size_t size, enum ro_pin_test test,*/ ret =fork ();if (ret <0 ) { -ksft_test_result_fail ("fork() failed\n" ); +ksft_perror ("fork() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }else if (!ret) {write (comm_pipes.child_ready[1 ],"0" ,1 );@@ -646,7 +688,8 @@ static void do_test_ro_pin(char *mem, size_t size, enum ro_pin_test test,clear_softdirty (); ret |=mprotect (mem, size,PROT_READ |PROT_WRITE );if (ret) { -ksft_test_result_fail ("mprotect() failed\n" ); +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }break ;@@ -661,9 +704,11 @@ static void do_test_ro_pin(char *mem, size_t size, enum ro_pin_test test, ret =ioctl (gup_fd,PIN_LONGTERM_TEST_START , &args);if (ret) {if (errno ==EINVAL ) -ksft_test_result_skip ("PIN_LONGTERM_TEST_START failed\n" ); + ret =KSFT_SKIP ;else -ksft_test_result_fail ("PIN_LONGTERM_TEST_START failed\n" ); + ret =KSFT_FAIL ; +ksft_perror ("PIN_LONGTERM_TEST_START failed" ); +log_test_result (ret); goto wait; }@@ -676,22 +721,26 @@ static void do_test_ro_pin(char *mem, size_t size, enum ro_pin_test test,*/ tmp_val = (__u64 )(uintptr_t )tmp; ret =ioctl (gup_fd,PIN_LONGTERM_TEST_READ , &tmp_val); -if (ret) -ksft_test_result_fail ("PIN_LONGTERM_TEST_READ failed\n" ); -else -ksft_test_result (!memcmp (mem, tmp, size), -"Longterm R/O pin is reliable\n" ); +if (ret) { +ksft_perror ("PIN_LONGTERM_TEST_READ failed" ); +log_test_result (KSFT_FAIL ); + }else { +if (!memcmp (mem, tmp, size)) +log_test_result (KSFT_PASS ); +else +log_test_result (KSFT_FAIL ); + } ret =ioctl (gup_fd,PIN_LONGTERM_TEST_STOP );if (ret) -ksft_print_msg ("[INFO] PIN_LONGTERM_TEST_STOP failed\n" ); +ksft_perror ("PIN_LONGTERM_TEST_STOP failed" ); wait:switch (test) {case RO_PIN_TEST_SHARED :write (comm_pipes.parent_ready[1 ],"0" ,1 );wait (&ret);if (!WIFEXITED (ret)) -ksft_print_msg ("[INFO] wait() failed\n" ); +ksft_perror ("wait() failed" );break ;default :break ;@@ -746,14 +795,16 @@ static void do_run_with_base_page(test_fn fn, bool swapout) mem =mmap (NULL , pagesize,PROT_READ |PROT_WRITE ,MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 );if (mem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL );return ; } ret =madvise (mem, pagesize,MADV_NOHUGEPAGE );/* Ignore if not around on a kernel. */ if (ret && errno !=EINVAL ) { -ksft_test_result_fail ("MADV_NOHUGEPAGE failed\n" ); +ksft_perror ("MADV_NOHUGEPAGE failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }@@ -763,7 +814,8 @@ static void do_run_with_base_page(test_fn fn, bool swapout)if (swapout) {madvise (mem, pagesize,MADV_PAGEOUT );if (!pagemap_is_swapped (pagemap_fd, mem)) { -ksft_test_result_skip ("MADV_PAGEOUT did not work, is swap enabled?\n" ); +ksft_print_msg ("MADV_PAGEOUT did not work, is swap enabled?\n" ); +log_test_result (KSFT_SKIP ); goto munmap; } }@@ -775,13 +827,13 @@ static void do_run_with_base_page(test_fn fn, bool swapout)static void run_with_base_page (test_fn fn,const char *desc) { -ksft_print_msg ("[RUN] %s ... with base page\n" , desc); +log_test_start ("%s ... with base page" , desc);do_run_with_base_page (fn, false); }static void run_with_base_page_swap (test_fn fn,const char *desc) { -ksft_print_msg ("[RUN] %s ... with swapped out base page\n" , desc); +log_test_start ("%s ... with swapped out base page" , desc);do_run_with_base_page (fn, true); }@@ -807,7 +859,8 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize) mmap_mem =mmap (NULL , mmap_size,PROT_READ |PROT_WRITE ,MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 );if (mmap_mem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL );return ; }@@ -816,7 +869,8 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize) ret =madvise (mem, thpsize,MADV_HUGEPAGE );if (ret) { -ksft_test_result_fail ("MADV_HUGEPAGE failed\n" ); +ksft_perror ("MADV_HUGEPAGE failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }@@ -826,7 +880,8 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)*/ mem[0 ] =1 ;if (!pagemap_is_populated (pagemap_fd, mem + thpsize - pagesize)) { -ksft_test_result_skip ("Did not get a THP populated\n" ); +ksft_print_msg ("Did not get a THP populated\n" ); +log_test_result (KSFT_SKIP ); goto munmap; }memset (mem,1 , thpsize);@@ -846,12 +901,14 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)*/ ret =mprotect (mem + pagesize, pagesize,PROT_READ );if (ret) { -ksft_test_result_fail ("mprotect() failed\n" ); +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; } ret =mprotect (mem + pagesize, pagesize,PROT_READ |PROT_WRITE );if (ret) { -ksft_test_result_fail ("mprotect() failed\n" ); +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }break ;@@ -863,7 +920,8 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)*/ ret =madvise (mem + pagesize, thpsize - pagesize,MADV_DONTNEED );if (ret) { -ksft_test_result_fail ("MADV_DONTNEED failed\n" ); +ksft_perror ("MADV_DONTNEED failed" ); +log_test_result (KSFT_FAIL ); goto munmap; } size = pagesize;@@ -877,13 +935,15 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize) mremap_mem =mmap (NULL , mremap_size,PROT_NONE ,MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 );if (mremap_mem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; } tmp =mremap (mem + mremap_size, mremap_size, mremap_size,MREMAP_MAYMOVE |MREMAP_FIXED , mremap_mem);if (tmp != mremap_mem) { -ksft_test_result_fail ("mremap() failed\n" ); +ksft_perror ("mremap() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; } size = mremap_size;@@ -896,12 +956,14 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)*/ ret =madvise (mem + pagesize, thpsize - pagesize,MADV_DONTFORK );if (ret) { -ksft_test_result_fail ("MADV_DONTFORK failed\n" ); +ksft_perror ("MADV_DONTFORK failed" ); +log_test_result (KSFT_FAIL ); goto munmap; } ret =fork ();if (ret <0 ) { -ksft_test_result_fail ("fork() failed\n" ); +ksft_perror ("fork() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }else if (!ret) {exit (0 );@@ -910,7 +972,8 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)/* Allow for sharing all pages again. */ ret =madvise (mem + pagesize, thpsize - pagesize,MADV_DOFORK );if (ret) { -ksft_test_result_fail ("MADV_DOFORK failed\n" ); +ksft_perror ("MADV_DOFORK failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }break ;@@ -924,7 +987,8 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)case THP_RUN_SINGLE_PTE_SWAPOUT :madvise (mem, size,MADV_PAGEOUT );if (!range_is_swapped (mem, size)) { -ksft_test_result_skip ("MADV_PAGEOUT did not work, is swap enabled?\n" ); +ksft_print_msg ("MADV_PAGEOUT did not work, is swap enabled?\n" ); +log_test_result (KSFT_SKIP ); goto munmap; }break ;@@ -941,56 +1005,56 @@ static void do_run_with_thp(test_fn fn, enum thp_run thp_run, size_t thpsize)static void run_with_thp (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with THP (%zu kB)\n" , +log_test_start ("%s ... with THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_PMD , size); }static void run_with_thp_swap (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with swapped-out THP (%zu kB)\n" , +log_test_start ("%s ... with swapped-out THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_PMD_SWAPOUT , size); }static void run_with_pte_mapped_thp (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with PTE-mapped THP (%zu kB)\n" , +log_test_start ("%s ... with PTE-mapped THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_PTE , size); }static void run_with_pte_mapped_thp_swap (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with swapped-out, PTE-mapped THP (%zu kB)\n" , +log_test_start ("%s ... with swapped-out, PTE-mapped THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_PTE_SWAPOUT , size); }static void run_with_single_pte_of_thp (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with single PTE of THP (%zu kB)\n" , +log_test_start ("%s ... with single PTE of THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_SINGLE_PTE , size); }static void run_with_single_pte_of_thp_swap (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with single PTE of swapped-out THP (%zu kB)\n" , +log_test_start ("%s ... with single PTE of swapped-out THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_SINGLE_PTE_SWAPOUT , size); }static void run_with_partial_mremap_thp (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with partially mremap()'ed THP (%zu kB)\n" , +log_test_start ("%s ... with partially mremap()'ed THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_PARTIAL_MREMAP , size); }static void run_with_partial_shared_thp (test_fn fn,const char *desc,size_t size) { -ksft_print_msg ("[RUN] %s ... with partially shared THP (%zu kB)\n" , +log_test_start ("%s ... with partially shared THP (%zu kB)" , desc, size /1024 );do_run_with_thp (fn,THP_RUN_PARTIAL_SHARED , size); }@@ -1000,14 +1064,15 @@ static void run_with_hugetlb(test_fn fn, const char *desc, size_t hugetlbsize)int flags =MAP_PRIVATE |MAP_ANONYMOUS |MAP_HUGETLB ;char *mem, *dummy; -ksft_print_msg ("[RUN] %s ... with hugetlb (%zu kB)\n" , desc, +log_test_start ("%s ... with hugetlb (%zu kB)" , desc, hugetlbsize /1024 ); flags |=__builtin_ctzll (hugetlbsize) <<MAP_HUGE_SHIFT ; mem =mmap (NULL , hugetlbsize,PROT_READ |PROT_WRITE , flags,-1 ,0 );if (mem ==MAP_FAILED ) { -ksft_test_result_skip ("need more free huge pages\n" ); +ksft_perror ("need more free huge pages" ); +log_test_result (KSFT_SKIP );return ; }@@ -1020,7 +1085,8 @@ static void run_with_hugetlb(test_fn fn, const char *desc, size_t hugetlbsize)*/ dummy =mmap (NULL , hugetlbsize,PROT_READ |PROT_WRITE , flags,-1 ,0 );if (dummy ==MAP_FAILED ) { -ksft_test_result_skip ("need more free huge pages\n" ); +ksft_perror ("need more free huge pages" ); +log_test_result (KSFT_SKIP ); goto munmap; }munmap (dummy, hugetlbsize);@@ -1226,7 +1292,7 @@ static void do_test_anon_thp_collapse(char *mem, size_t size, ret =setup_comm_pipes (&comm_pipes);if (ret) { -ksft_test_result_fail ("pipe() failed\n" ); +log_test_result (KSFT_FAIL );return ; }@@ -1236,12 +1302,14 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,*/ ret =mprotect (mem + pagesize, pagesize,PROT_READ );if (ret) { -ksft_test_result_fail ("mprotect() failed\n" ); +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; } ret =mprotect (mem + pagesize, pagesize,PROT_READ |PROT_WRITE );if (ret) { -ksft_test_result_fail ("mprotect() failed\n" ); +ksft_perror ("mprotect() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }@@ -1250,8 +1318,8 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,/* Collapse before actually COW-sharing the page. */ ret =madvise (mem, size,MADV_COLLAPSE );if (ret) { -ksft_test_result_skip ("MADV_COLLAPSE failed: %s\n" , -strerror (errno)); +ksft_perror ("MADV_COLLAPSE failed" ); +log_test_result (KSFT_SKIP ); goto close_comm_pipes; }break ;@@ -1262,7 +1330,8 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,/* Don't COW-share the upper part of the THP. */ ret =madvise (mem + size /2 , size /2 ,MADV_DONTFORK );if (ret) { -ksft_test_result_fail ("MADV_DONTFORK failed\n" ); +ksft_perror ("MADV_DONTFORK failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }break ;@@ -1270,7 +1339,8 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,/* Don't COW-share the lower part of the THP. */ ret =madvise (mem, size /2 ,MADV_DONTFORK );if (ret) { -ksft_test_result_fail ("MADV_DONTFORK failed\n" ); +ksft_perror ("MADV_DONTFORK failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }break ;@@ -1280,7 +1350,8 @@ static void do_test_anon_thp_collapse(char *mem, size_t size, ret =fork ();if (ret <0 ) { -ksft_test_result_fail ("fork() failed\n" ); +ksft_perror ("fork() failed" ); +log_test_result (KSFT_FAIL ); goto close_comm_pipes; }else if (!ret) {switch (test) {@@ -1314,7 +1385,8 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,*/ ret =madvise (mem, size,MADV_DOFORK );if (ret) { -ksft_test_result_fail ("MADV_DOFORK failed\n" ); +ksft_perror ("MADV_DOFORK failed" ); +log_test_result (KSFT_FAIL );write (comm_pipes.parent_ready[1 ],"0" ,1 );wait (&ret); goto close_comm_pipes;@@ -1324,8 +1396,8 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,/* Collapse before anyone modified the COW-shared page. */ ret =madvise (mem, size,MADV_COLLAPSE );if (ret) { -ksft_test_result_skip ("MADV_COLLAPSE failed: %s\n" , -strerror (errno)); +ksft_perror ("MADV_COLLAPSE failed" ); +log_test_result (KSFT_SKIP );write (comm_pipes.parent_ready[1 ],"0" ,1 );wait (&ret); goto close_comm_pipes;@@ -1345,7 +1417,10 @@ static void do_test_anon_thp_collapse(char *mem, size_t size,else ret = -EINVAL ; -ksft_test_result (!ret,"No leak from parent into child\n" ); +if (!ret) +log_test_result (KSFT_PASS ); +else +log_test_result (KSFT_FAIL ); close_comm_pipes:close_comm_pipes (&comm_pipes); }@@ -1430,7 +1505,7 @@ static void run_anon_thp_test_cases(void)for (i =0 ; i <ARRAY_SIZE (anon_thp_test_cases); i++) {struct test_case const *test_case = &anon_thp_test_cases[i]; -ksft_print_msg ("[RUN] %s\n" , test_case->desc); +log_test_start ("%s" , test_case->desc);do_run_with_thp (test_case->fn,THP_RUN_PMD , pmdsize); } }@@ -1453,8 +1528,10 @@ static void test_cow(char *mem, const char *smem, size_t size)memset (mem,0xff , size);/* See if we still read the old values via the other mapping. */ -ksft_test_result (!memcmp (smem, old, size), -"Other mapping not modified\n" ); +if (!memcmp (smem, old, size)) +log_test_result (KSFT_PASS ); +else +log_test_result (KSFT_FAIL );free (old); }@@ -1472,18 +1549,20 @@ static void run_with_zeropage(non_anon_test_fn fn, const char *desc) {char *mem, *smem, tmp; -ksft_print_msg ("[RUN] %s ... with shared zeropage\n" , desc); +log_test_start ("%s ... with shared zeropage" , desc); mem =mmap (NULL , pagesize,PROT_READ |PROT_WRITE ,MAP_PRIVATE |MAP_ANON ,-1 ,0 );if (mem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL );return ; } smem =mmap (NULL , pagesize,PROT_READ ,MAP_PRIVATE |MAP_ANON ,-1 ,0 );if (smem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }@@ -1504,10 +1583,11 @@ static void run_with_huge_zeropage(non_anon_test_fn fn, const char *desc)size_t mmap_size;int ret; -ksft_print_msg ("[RUN] %s ... with huge zeropage\n" , desc); +log_test_start ("%s ... with huge zeropage" , desc);if (!has_huge_zeropage) { -ksft_test_result_skip ("Huge zeropage not enabled\n" ); +ksft_print_msg ("Huge zeropage not enabled\n" ); +log_test_result (KSFT_SKIP );return ; }@@ -1516,13 +1596,15 @@ static void run_with_huge_zeropage(non_anon_test_fn fn, const char *desc) mmap_mem =mmap (NULL , mmap_size,PROT_READ |PROT_WRITE ,MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 );if (mmap_mem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL );return ; } mmap_smem =mmap (NULL , mmap_size,PROT_READ ,MAP_PRIVATE |MAP_ANONYMOUS ,-1 ,0 );if (mmap_smem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }@@ -1531,9 +1613,15 @@ static void run_with_huge_zeropage(non_anon_test_fn fn, const char *desc) smem = (char *)(((uintptr_t )mmap_smem + pmdsize) & ~(pmdsize -1 )); ret =madvise (mem, pmdsize,MADV_HUGEPAGE ); +if (ret !=0 ) { +ksft_perror ("madvise()" ); +log_test_result (KSFT_FAIL ); + goto munmap; + } ret |=madvise (smem, pmdsize,MADV_HUGEPAGE ); -if (ret) { -ksft_test_result_fail ("MADV_HUGEPAGE failed\n" ); +if (ret !=0 ) { +ksft_perror ("madvise()" ); +log_test_result (KSFT_FAIL ); goto munmap; }@@ -1562,29 +1650,33 @@ static void run_with_memfd(non_anon_test_fn fn, const char *desc)char *mem, *smem, tmp;int fd; -ksft_print_msg ("[RUN] %s ... with memfd\n" , desc); +log_test_start ("%s ... with memfd" , desc); fd =memfd_create ("test" ,0 );if (fd <0 ) { -ksft_test_result_fail ("memfd_create() failed\n" ); +ksft_perror ("memfd_create() failed" ); +log_test_result (KSFT_FAIL );return ; }/* File consists of a single page filled with zeroes. */ if (fallocate (fd,0 ,0 , pagesize)) { -ksft_test_result_fail ("fallocate() failed\n" ); +ksft_perror ("fallocate() failed" ); +log_test_result (KSFT_FAIL ); goto close; }/* Create a private mapping of the memfd. */ mem =mmap (NULL , pagesize,PROT_READ |PROT_WRITE ,MAP_PRIVATE , fd,0 );if (mem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto close; } smem =mmap (NULL , pagesize,PROT_READ ,MAP_SHARED , fd,0 );if (smem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }@@ -1607,35 +1699,40 @@ static void run_with_tmpfile(non_anon_test_fn fn, const char *desc)FILE *file;int fd; -ksft_print_msg ("[RUN] %s ... with tmpfile\n" , desc); +log_test_start ("%s ... with tmpfile" , desc); file =tmpfile ();if (!file) { -ksft_test_result_fail ("tmpfile() failed\n" ); +ksft_perror ("tmpfile() failed" ); +log_test_result (KSFT_FAIL );return ; } fd =fileno (file);if (fd <0 ) { -ksft_test_result_skip ("fileno() failed\n" ); +ksft_perror ("fileno() failed" ); +log_test_result (KSFT_SKIP );return ; }/* File consists of a single page filled with zeroes. */ if (fallocate (fd,0 ,0 , pagesize)) { -ksft_test_result_fail ("fallocate() failed\n" ); +ksft_perror ("fallocate() failed" ); +log_test_result (KSFT_FAIL ); goto close; }/* Create a private mapping of the memfd. */ mem =mmap (NULL , pagesize,PROT_READ |PROT_WRITE ,MAP_PRIVATE , fd,0 );if (mem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto close; } smem =mmap (NULL , pagesize,PROT_READ ,MAP_SHARED , fd,0 );if (smem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }@@ -1659,20 +1756,22 @@ static void run_with_memfd_hugetlb(non_anon_test_fn fn, const char *desc,char *mem, *smem, tmp;int fd; -ksft_print_msg ("[RUN] %s ... with memfd hugetlb (%zu kB)\n" , desc, +log_test_start ("%s ... with memfd hugetlb (%zu kB)" , desc, hugetlbsize /1024 ); flags |=__builtin_ctzll (hugetlbsize) <<MFD_HUGE_SHIFT ; fd =memfd_create ("test" , flags);if (fd <0 ) { -ksft_test_result_skip ("memfd_create() failed\n" ); +ksft_perror ("memfd_create() failed" ); +log_test_result (KSFT_SKIP );return ; }/* File consists of a single page filled with zeroes. */ if (fallocate (fd,0 ,0 , hugetlbsize)) { -ksft_test_result_skip ("need more free huge pages\n" ); +ksft_perror ("need more free huge pages" ); +log_test_result (KSFT_SKIP ); goto close; }@@ -1680,12 +1779,14 @@ static void run_with_memfd_hugetlb(non_anon_test_fn fn, const char *desc, mem =mmap (NULL , hugetlbsize,PROT_READ |PROT_WRITE ,MAP_PRIVATE , fd,0 );if (mem ==MAP_FAILED ) { -ksft_test_result_skip ("need more free huge pages\n" ); +ksft_perror ("need more free huge pages" ); +log_test_result (KSFT_SKIP ); goto close; } smem =mmap (NULL , hugetlbsize,PROT_READ ,MAP_SHARED , fd,0 );if (smem ==MAP_FAILED ) { -ksft_test_result_fail ("mmap() failed\n" ); +ksft_perror ("mmap() failed" ); +log_test_result (KSFT_FAIL ); goto munmap; }
Sasha Levin
maintainerRe: [PATCH 6.12 1291/1376] selftests/mm: report unique test names for each cow test
Quoted 3 lines
I think 6.12.y misses
3f192afbede24c60e59db1272ad155a3a44f5fe7, "selftests/mm: add helper for logging test start and results". I suggest applying it before this patch and rebuilding the MM selftests. Thoughts?
I compiled that route first, and it moves the break rather than closing it. With 3f192afbede2 ("selftests/mm: add helper for logging test start and results") added, hugepage-vmemmap.c and khugepaged.c start failing on 6.12, and 19 translation units fail on 6.6.
So the cow conversion is reverted on both trees instead, which restores the build.
Signature · 2 lines
Thanks, Sasha
Greg Kroah-Hartman
maintainerPATCH 1292/1376 selftests/mm: skip COW tmpfile cases when fallocate() is unsupported
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muhammad Usama Anjum <[email protected]>
[ Upstream commit 4004c130c358b1561a55323b0e747f20f5133f7b ]
Patch series "selftests/mm: Handle unsupported and transient test conditions", v3.
Several MM selftests report failures when the test environment lacks an underlying prerequisite, such as fallocate() support, MADV_REMOVE, local page-cache semantics, or swap.
This series converts those unsupported cases to SKIP while preserving failures for unexpected errors. It also allows migration tests to retry transient move_pages() failures.
This patch (of 4):
The tmpfile-backed COW cases allocate a one-page file with fallocate() before exercising private and shared mappings. When the filesystem backing tmpfile() does not implement fallocate(), setup fails with EOPNOTSUPP and no COW behavior is exercised.
This occurs when the temporary directory resides on a filesystem with limited allocation support, such as NFSv3. Reporting a failure adds noise because the test prerequisite is absent rather than the COW implementation being broken.
Report EOPNOTSUPP as a skip. Continue treating every other fallocate() error as a failure so unexpected setup regressions remain visible.
--- tools/testing/selftests/mm/cow.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
tools/testing/selftests/mm/cow.c +7 -2
@@ -1717,8 +1717,13 @@ static void run_with_tmpfile(non_anon_test_fn fn, const char *desc)/* File consists of a single page filled with zeroes. */ if (fallocate (fd,0 ,0 , pagesize)) { -ksft_perror ("fallocate() failed" ); -log_test_result (KSFT_FAIL ); +if (errno ==EOPNOTSUPP ) { +ksft_print_msg ("fallocate() not supported by filesystem\n" ); +log_test_result (KSFT_SKIP ); + }else { +ksft_perror ("fallocate() failed" ); +log_test_result (KSFT_FAIL ); + } goto close; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1293/1376 maple_tree: catch race in mas_alloc_cyclic()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Liam R. Howlett (Oracle) <[email protected]>
[ Upstream commit 35f1342e5b893a740eff2ef9ab337bfaa63ab76d ]
If mas_alloc_cyclic() is called during a low memory situation, it is possible the lock may be dropped so reclaim can occur. There is a window where some other task may allocate the same id and cause the mas_insert() to fail with -EEXIST. In this scenario the function will return -EEXIST, which is not expected.
Modifying the retry on mas_nomem() to re-search for a slot means that any race with other writes will not matter as the lock will be held between finding the index and writing the index.
Moving the flag logic avoids cases where the flag is modified on drop lock/reacquire or when the write fails after clearing the flag.
No existing users are exposed to this issue.
--- lib/maple_tree.c | 43 ++++++++++++++++++++++++------------------- 1 file changed, 24 insertions(+), 19 deletions(-)
lib/maple_tree.c +24 -19
@@ -4348,35 +4348,40 @@ int mas_alloc_cyclic(struct ma_state *mas, unsigned long *startp, void *entry, unsigned long range_lo, unsigned long range_hi, unsigned long *next, gfp_t gfp) { - unsigned long min = range_lo; -int ret =0 ; - - range_lo =max (min, *next); - ret =mas_empty_area (mas, range_lo, range_hi,1 ); -if ((mas->tree->ma_flags &MT_FLAGS_ALLOC_WRAPPED ) && ret ==0 ) { - mas->tree->ma_flags &= ~MT_FLAGS_ALLOC_WRAPPED ; - ret =1 ; - } -if (ret <0 && range_lo > min) { -mas_reset (mas); - ret =mas_empty_area (mas, min, range_hi,1 ); -if (ret ==0 ) - ret =1 ; - } -if (ret <0 ) -return ret; + int ret; +unsigned long min; + min = range_lo;do { + range_lo =max (min, *next); + ret =mas_empty_area (mas, range_lo, range_hi,1 ); +if (ret <0 && range_lo > min) { +mas_reset (mas); + ret =mas_empty_area (mas, min, range_hi,1 ); +if (ret ==0 ) + ret =1 ; + } +if (ret <0 ) + goto out; +mas_insert (mas, entry); }while (mas_nomem (mas, gfp)); -if (mas_is_err (mas)) -return xa_err (mas->node); +if (mas_is_err (mas)) { + ret =xa_err (mas->node); + goto out; + } + +if ((mas->tree->ma_flags &MT_FLAGS_ALLOC_WRAPPED ) && ret ==0 ) { + mas->tree->ma_flags &= ~MT_FLAGS_ALLOC_WRAPPED ; + ret =1 ; + } *startp = mas->index; *next = *startp +1 ;if (*next ==0 ) mas->tree->ma_flags |=MT_FLAGS_ALLOC_WRAPPED ; +out:mas_destroy (mas);return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1294/1376 maple_tree: fix argument name in header
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Liam R. Howlett (Oracle) <[email protected]>
[ Upstream commit 00f67814a14e614b749ebe54076ef1e3e6454f2b ]
The mas_prev_range() function takes a min and not a max.
--- include/linux/maple_tree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/maple_tree.h +1 -1
@@ -528,7 +528,7 @@ void mas_destroy(struct ma_state *mas);int mas_expected_entries (struct ma_state *mas,unsigned long nr_entries);void *mas_prev (struct ma_state *mas,unsigned long min); -void *mas_prev_range (struct ma_state *mas,unsigned long max); +void *mas_prev_range (struct ma_state *mas,unsigned long min);void *mas_next (struct ma_state *mas,unsigned long max);void *mas_next_range (struct ma_state *mas,unsigned long max);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1295/1376 net_sched: act_skbmod: use RCU in tcf_skbmod_dump()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 53df77e7859042a92914d664c860f65d9689f88d ]
Also storing tcf_action into struct tcf_skbmod_params makes sure there is no discrepancy in tcf_skbmod_act().
No longer block BH in tcf_skbmod_init() when acquiring tcf_lock.
Stable-dep-of: 81d0d1e64f30 ("net/sched: act_skbmod: fix length calculations and avoid invalid header warnings")
--- include/net/tc_act/tc_skbmod.h | 1 + net/sched/act_skbmod.c | 26 ++++++++++++-------------- 2 files changed, 13 insertions(+), 14 deletions(-)
include/net/tc_act/tc_skbmod.h +1 -0
@@ -12,6 +12,7 @@struct tcf_skbmod_params {struct rcu_head rcu;u64 flags;/*up to 64 types of operations; extend if needed */ +int action;u8 eth_dst[ETH_ALEN ];u16 eth_type;u8 eth_src[ETH_ALEN ];
net/sched/act_skbmod.c +12 -14
@@ -27,19 +27,18 @@ TC_INDIRECT_SCOPE int tcf_skbmod_act(struct sk_buff *skb, struct tcf_result *res) {struct tcf_skbmod *d =to_skbmod (a); -int action, max_edit_len, err;struct tcf_skbmod_params *p; +int max_edit_len, err;u64 flags;tcf_lastuse_update (&d->tcf_tm);bstats_update (this_cpu_ptr (d->common.cpu_bstats), skb); - action =READ_ONCE (d->tcf_action); -if (unlikely (action ==TC_ACT_SHOT )) + p =rcu_dereference_bh (d->skbmod_p); +if (unlikely (p->action ==TC_ACT_SHOT )) goto drop; max_edit_len =skb_mac_header_len (skb); - p =rcu_dereference_bh (d->skbmod_p); flags = p->flags;/* tcf_skbmod_init() guarantees "flags" to be one of the following:
@@ -85,7 +84,7 @@ TC_INDIRECT_SCOPE int tcf_skbmod_act(struct sk_buff *skb,INET_ECN_set_ce (skb); out: -return action; +return p->action; drop:qstats_overlimit_inc (this_cpu_ptr (d->common.cpu_qstats));
@@ -193,9 +192,9 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, } p->flags = lflags; - + p->action = parm->action;if (ovr) -spin_lock_bh (&d->tcf_lock); +spin_lock (&d->tcf_lock);/* Protected by tcf_lock if overwriting existing action. */ goto_ch =tcf_action_set_ctrlact (*a, parm->action, goto_ch); p_old =rcu_dereference_protected (d->skbmod_p,1 );
@@ -209,7 +208,7 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,rcu_assign_pointer (d->skbmod_p, p);if (ovr) -spin_unlock_bh (&d->tcf_lock); +spin_unlock (&d->tcf_lock);if (p_old)kfree_rcu (p_old, rcu);
@@ -248,10 +247,9 @@ static int tcf_skbmod_dump(struct sk_buff *skb, struct tc_action *a, opt.index = d->tcf_index; opt.refcnt =refcount_read (&d->tcf_refcnt) - ref; opt.bindcnt =atomic_read (&d->tcf_bindcnt) - bind; -spin_lock_bh (&d->tcf_lock); - opt.action = d->tcf_action; - p =rcu_dereference_protected (d->skbmod_p, -lockdep_is_held (&d->tcf_lock)); +rcu_read_lock (); + p =rcu_dereference (d->skbmod_p); + opt.action = p->action; opt.flags = p->flags;if (nla_put (skb,TCA_SKBMOD_PARMS ,sizeof (opt), &opt)) goto nla_put_failure;
@@ -269,10 +267,10 @@ static int tcf_skbmod_dump(struct sk_buff *skb, struct tc_action *a,if (nla_put_64bit (skb,TCA_SKBMOD_TM ,sizeof (t), &t,TCA_SKBMOD_PAD )) goto nla_put_failure; -spin_unlock_bh (&d->tcf_lock); +rcu_read_unlock ();return skb->len; nla_put_failure: -spin_unlock_bh (&d->tcf_lock); +rcu_read_unlock ();nlmsg_trim (skb, b);return -1 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1296/1376 net/sched: act_skbmod: fix length calculations and avoid invalid header warnings
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 81d0d1e64f30d9989c829c0953cd6e6c68d9c5fb ]
syzbot reported a warning in skb_network_header_len() triggered by tcf_skbmod_act():
!skb_transport_header_was_set(skb)
WARNING: CPU: 0 PID: 14949 at include/linux/skbuff.h:3243 skb_network_header_len include/linux/skbuff.h:3243 [inline] WARNING: CPU: 0 PID: 14949 at net/sched/act_skbmod.c:55 tcf_skbmod_act+0xfe8/0x1810 net/sched/act_skbmod.c:55
There are a few issues in tcf_skbmod_act():
1. Calling skb_network_header_len() assumes skb->transport_header is set, which is not guaranteed when tcf_skbmod_act() runs at TC ingress.
2. Unconditionally calling skb_mac_header_len() at the beginning of tcf_skbmod_act() triggers a warning on L3 devices (e.g. TUN) where the MAC header is unset, evaluating to an underflowed garbage length.
3. On TC ingress, skb->data points to the network header. Adding the MAC header length to the IP header length causes skb_ensure_writable() to request more bytes than the actual IP packet length, dropping valid short packets (e.g. 28-byte UDP/IPv4 packets).
Fix these by:
- Using skb_network_offset(skb) + sizeof(struct iphdr/ipv6hdr) for SKBMOD_F_ECN so that the required length is correctly calculated on both ingress (offset == 0) and egress (offset == mac_len).
- Setting max_edit_len to ETH_HLEN for Ethernet header modifications after validating ARPHRD_ETHER.
--- net/sched/act_skbmod.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
net/sched/act_skbmod.c +8 -4
@@ -38,7 +38,6 @@ TC_INDIRECT_SCOPE int tcf_skbmod_act(struct sk_buff *skb,if (unlikely (p->action ==TC_ACT_SHOT )) goto drop; - max_edit_len =skb_mac_header_len (skb); flags = p->flags;/* tcf_skbmod_init() guarantees "flags" to be one of the following:
@@ -51,14 +50,19 @@ TC_INDIRECT_SCOPE int tcf_skbmod_act(struct sk_buff *skb,if (flags ==SKBMOD_F_ECN ) {switch (skb_protocol (skb, true)) {case cpu_to_be16 (ETH_P_IP ): + max_edit_len =sizeof (struct iphdr ); +break ;case cpu_to_be16 (ETH_P_IPV6 ): - max_edit_len +=skb_network_header_len (skb); + max_edit_len =sizeof (struct ipv6hdr );break ;default : goto out; } - }else if (!skb->dev || skb->dev->type !=ARPHRD_ETHER ) { - goto out; + max_edit_len +=skb_network_offset (skb); + }else { +if (!skb->dev || skb->dev->type !=ARPHRD_ETHER ) + goto out; + max_edit_len =ETH_HLEN ; } err =skb_ensure_writable (skb, max_edit_len);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1297/1376 net: core: check skb_frags_readable before uncloning in skb_copy_ubufs
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mina Almasry <[email protected]>
[ Upstream commit 00e11ee9831b3439264e0ae6762a0470126515af ]
skb_copy_ubufs drops clones and modifies the SKB via pskb_expand_head() before checking for !skb_frags_readable(skb). This alters the SKB geometry prior to throwing an -EFAULT on an invalid SKB. Check readability first.
--- net/core/skbuff.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/core/skbuff.c +3 -3
@@ -1967,12 +1967,12 @@ int skb_copy_ubufs(struct sk_buff *skb, gfp_t gfp_mask)int i, order, psize, new_frags;u32 d_off; -if (skb_shared (skb) ||skb_unclone (skb, gfp_mask)) -return -EINVAL ; -if (!skb_frags_readable (skb))return -EFAULT ; +if (skb_shared (skb) ||skb_unclone (skb, gfp_mask)) +return -EINVAL ; +if (!num_frags) goto release;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1298/1376 net/sched: fq: add overflow bounds to quantum and initial quantum
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit 709f34f7c28dc4dd6c40343d101850f11e172312 ]
fq_init() computes quantum = 2 * psched_mtu() and initial_quantum = 10 * psched_mtu() with no overflow check. A device with a huge MTU (e.g. dummy with max_mtu == 0 accepting MTU 2147483634) makes psched_mtu() return 0x80000000; the 2 * and 10 * multiplications wrap to 0 in 32-bit arithmetic, so q->quantum == 0. Then in fq_dequeue() the credit-refill loop adds 0 to f->credit (which stays <= 0) and goto begin loops forever under the qdisc lock, creating a soft lockup.
Clamp psched_mtu() to [1, 1 << 20] before multiplying so the product cannot wrap, then cap the result at 1 << 20, matching the bound already enforced on TCA_FQ_QUANTUM in fq_change().
Conditions to recreate the bug: a device whose MTU (plus hard_header_len) is large enough that 2 * psched_mtu() wraps (e.g. a dummy device with max_mtu == 0 accepting MTU 2147483634). Requires CAP_NET_ADMIN in a user namespace.
--- net/sched/sch_fq.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/sched/sch_fq.c +4 -2
@@ -1141,12 +1141,14 @@ static int fq_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) {struct fq_sched_data *q =qdisc_priv (sch); +u32 mtu;int i, err; sch->limit =10000 ; q->flow_plimit =100 ; - q->quantum =2 *psched_mtu (qdisc_dev (sch)); - q->initial_quantum =10 *psched_mtu (qdisc_dev (sch)); + mtu =clamp_t (u32,psched_mtu (qdisc_dev (sch)),1 ,1 <<20 ); + q->quantum =min_t (u32,2 * mtu,1 <<20 ); + q->initial_quantum =min_t (u32,10 * mtu,1 <<20 ); q->flow_refill_delay =msecs_to_jiffies (40 ); q->flow_max_rate = ~0UL ; q->time_next_delayed_flow = ~0ULL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1299/1376 net/sched: fq_codel: clamp default quantum and mtu
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit d9ebd8f9aa8b2773235889cb903fafd61f2d8585 ]
fq_codel_init() sets q->quantum = psched_mtu(qdisc_dev(sch)) without clamping. A device with a huge MTU (e.g. dummy with max_mtu == 0 accepting MTU 2147483634) makes psched_mtu() return 0x80000000, which overflows the signed flow->deficit to INT_MIN in fq_codel_dequeue(), causing an infinite loop and soft lockup. Emulate fq_codel_change() and constrain to [256, FQ_CODEL_QUANTUM_MAX].
The same unclamped psched_mtu() is assigned to q->cparams.mtu a bit below, and fq_codel_change() never updates it. codel_should_drop() tests "*backlog <= params->mtu"; with mtu == 0x80000000 (~2 GiB) and the default 32 MiB memory_limit, the test is always true, so CoDel is silently and completely disabled (no drops, no ECN). Declare a single clamped mtu and assign both q->quantum and q->cparams.mtu from it, which also removes the double psched_mtu() call.
Conditions to recreate the bug: a device whose MTU (plus hard_header_len) wraps psched_mtu() into the sign bit (e.g. a dummy device with max_mtu == 0 accepting MTU 2147483634). Requires CAP_NET_ADMIN in a user namespace.
--- net/sched/sch_fq_codel.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/sched/sch_fq_codel.c +4 -2
@@ -504,6 +504,7 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt, struct netlink_ext_ack *extack) {struct fq_codel_sched_data *q =qdisc_priv (sch); +u32 mtu;int i;int err;
@@ -511,13 +512,14 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt, q->flows_cnt =1024 ; q->memory_limit =32 <<20 ;/* 32 MBytes */ q->drop_batch_size =64 ; - q->quantum =psched_mtu (qdisc_dev (sch)); + mtu =clamp_t (u32,psched_mtu (qdisc_dev (sch)),256 ,FQ_CODEL_QUANTUM_MAX ); + q->quantum = mtu;INIT_LIST_HEAD (&q->new_flows);INIT_LIST_HEAD (&q->old_flows);codel_params_init (&q->cparams);codel_stats_init (&q->cstats); q->cparams.ecn = true; - q->cparams.mtu =psched_mtu (qdisc_dev (sch)); + q->cparams.mtu = mtu;if (opt) { err =fq_codel_change (sch, opt, extack);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1300/1376 net/sched: sch_codel: clamp default mtu to avoid disabling CoDel
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit 6439461f1618ae176c048673ad28bdb6c68efbfc ]
codel_init() sets q->params.mtu = psched_mtu(qdisc_dev(sch)) without clamping. A device with a huge MTU (e.g. dummy with max_mtu == 0 accepting MTU 2147483634) makes psched_mtu() return 0x80000000. In codel_should_drop() the test "*backlog <= params->mtu" then compares the backlog against ~2 GiB; with the default sch->limit of DEFAULT_CODEL_LIMIT (1000) packets the backlog can never reach it, so the test is always true and CoDel is silently and completely disabled i.e no drops, no ECN marking, codel degrades to a tail-drop FIFO. codel_change() never updates params.mtu, so the init path is the only place to clamp it. Constrain to [256, 1 << 20], matching the fq_codel bound; 256 is a sane floor that only makes CoDel slightly more willing to act on very small queues, which is the safe direction.
Conditions to recreate the bug: a device whose MTU (plus hard_header_len) wraps psched_mtu() into the sign bit (e.g. a dummy device with max_mtu == 0 accepting MTU 2147483634). Requires CAP_NET_ADMIN in a user namespace.
--- net/sched/sch_codel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/sch_codel.c +1 -1
@@ -203,7 +203,7 @@ static int codel_init(struct Qdisc *sch, struct nlattr *opt,codel_params_init (&q->params);codel_vars_init (&q->vars);codel_stats_init (&q->stats); - q->params.mtu =psched_mtu (qdisc_dev (sch)); + q->params.mtu =clamp_t (u32,psched_mtu (qdisc_dev (sch)),256 ,1 <<20 );if (opt) {int err =codel_change (sch, opt, extack);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1301/1376 net/sched: fq_pie: clamp default quantum to avoid signed overflow
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit c86cd7ed0b0e44779a3d1683f03e4353baf4bdc9 ]
fq_pie_init() sets q->quantum = psched_mtu(qdisc_dev(sch)) without clamping. A device with a huge MTU (e.g. dummy with max_mtu == 0 accepting MTU 2147483634) makes psched_mtu() return 0x80000000, which overflows the signed flow->deficit to INT_MIN in fq_pie_qdisc_dequeue(), causing an infinite loop and soft lockup. Emulate fq_pie_policy which is already bounded to [1, 1 << 20]; clamp the default to [256, 1 << 20]. 256 matches fq_codel's floor and is a sane minimum for a DRR quantum.
Conditions to recreate the bug: a device whose MTU (plus hard_header_len) wraps psched_mtu() into the sign bit (e.g. a dummy device with max_mtu == 0 accepting MTU 2147483634). Requires CAP_NET_ADMIN in a user namespace.
--- net/sched/sch_fq_pie.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/sched/sch_fq_pie.c +2 -1
@@ -423,7 +423,8 @@ static int fq_pie_init(struct Qdisc *sch, struct nlattr *opt,pie_params_init (&q->p_params); sch->limit =10 *1024 ; q->p_params.limit = sch->limit; - q->quantum =psched_mtu (qdisc_dev (sch)); + q->quantum =clamp_t (u32,psched_mtu (qdisc_dev (sch)), +256 ,1 <<20 ); q->sch = sch; q->ecn_prob =10 ; q->flows_cnt =1024 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1302/1376 net/sched: hhf: clamp quantum before hhf_change() to avoid overflow
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit 2164b512b97bb053e8ce4d6e95576f11bed6a005 ]
hhf_init() sets q->quantum = psched_mtu(qdisc_dev(sch)) with no overflow check. A device with a huge MTU (e.g. dummy with max_mtu == 0 accepting MTU 2147483634) makes weight * quantum overflow the signed deficit in hhf_dequeue(), spinning forever.
Clamp q->quantum before hhf_change() so both the opt and !opt paths see a sane quantum. Without this, bare "tc qdisc add ... hhf" succeeds with a clamped quantum but "tc qdisc add ... hhf limit 1000" (any option present) fails with -EINVAL because hhf_change() re-validates the unclamped default (sch_hhf.c:559). 256 matches fq_codel's floor and is a sane minimum for a DRR quantum.
Conditions to recreate the bug: a device whose MTU (plus hard_header_len) wraps psched_mtu() into the sign bit (e.g. a dummy device with max_mtu == 0 accepting MTU 2147483634). Requires CAP_NET_ADMIN in a user namespace.
--- net/sched/sch_hhf.c | 4 ++++ 1 file changed, 4 insertions(+)
net/sched/sch_hhf.c +4 -0
@@ -621,6 +621,10 @@ static int hhf_init(struct Qdisc *sch, struct nlattr *opt, q->hhf_evict_timeout =HZ ;/* 1 sec */ q->hhf_non_hh_weight =2 ; +if ((int )q->quantum <=0 || + (u64 )q->quantum * q->hhf_non_hh_weight >INT_MAX ) + q->quantum =256 ; +if (opt) {int err =hhf_change (sch, opt, extack);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1303/1376 net/sched: sfq: clamp quantum to avoid signed overflow soft lockup
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit 816e90057ab1879562a5b7cc688e35bb9027ae97 ]
sfq_init() sets q->quantum = psched_mtu(qdisc_dev(sch)) (unsigned). A device with a huge MTU (e.g. dummy with max_mtu == 0 accepting MTU 2147483634) makes psched_mtu() return 0x80000000, so slot->allot = INT_MIN and INT_MIN + INT_MIN toggles between INT_MIN and 0 forever, spinning sfq_dequeue() under the qdisc lock.
Clamp the quantum to [256, 1 << 20] so the refill loop terminates. The lower bound also covers q->quantum == 0 (psched_mtu() returning 0), which spins sfq_dequeue() identically. sfq_change() already rejects a negative quantum, so only the init path was exposed.
Conditions to recreate the bug: a device whose MTU (plus hard_header_len) wraps psched_mtu() into the sign bit (e.g. a dummy device with max_mtu == 0 accepting MTU 2147483634). Requires CAP_NET_ADMIN in a user namespace.
--- net/sched/sch_sfq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/sched/sch_sfq.c +2 -1
@@ -796,7 +796,8 @@ static int sfq_init(struct Qdisc *sch, struct nlattr *opt, q->tail =NULL ; q->divisor =SFQ_DEFAULT_HASH_DIVISOR ; q->maxflows =SFQ_DEFAULT_FLOWS ; - q->quantum =psched_mtu (qdisc_dev (sch)); + q->quantum =clamp_t (u32,psched_mtu (qdisc_dev (sch)), +256 ,1 <<20 ); q->perturb_period =0 ;get_random_bytes (&q->perturbation,sizeof (q->perturbation));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1304/1376 net/sched: sch_teql: restore skb->dev on the slave failure path
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Victor Nogueira <[email protected]>
[ Upstream commit dc4b95b8fee95113587e93ca116356032d271371 ]
teql_master_xmit() sets skb->dev = slave before calling the slave's ndo_start_xmit(), but never restores it when that transmit fails. The skb then walks on to the next slave still pointing at the previous one.
If a later slave has no resolved neighbour, teql_resolve() hands the skb to neigh_event_send(), which queues it on that neighbour's arp_queue with the stale skb->dev. skb->dev holds no reference, so deleting the previous slave frees the net_device while the skb is still queued. Whatever runs next on that skb - arp_error_report() on timeout, or neigh_direct_output() -> dev_queue_xmit() once the neighbour resolves - causes a UAF like the one below:
BUG: KASAN: slab-use-after-free in __icmp_send (net/ipv4/icmp.c:914 (discriminator 2)) Read of size 4 at addr ffff888106e100b0 by task flood_packet/527 CPU: 0 UID: 0 PID: 527 Comm: flood_packet Not tainted 7.2.0-rc6-g594d90519502 #1 PREEMPT(lazy) Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 Call Trace: <IRQ> dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120) print_report (mm/kasan/report.c:378 mm/kasan/report.c:482) ? __pfx__raw_spin_lock_irqsave (./include/asm-generic/qrwlock.h:122 (discriminator 4)) ? __icmp_send (net/ipv4/icmp.c:914 (discriminator 2)) kasan_report (mm/kasan/report.c:595) ? __icmp_send (net/ipv4/icmp.c:914 (discriminator 2)) __icmp_send (net/ipv4/icmp.c:914 (discriminator 2))
[...]ipv4_link_failure (net/ipv4/route.c:1251 net/ipv4/route.c:1258)
? __pfx_ipv4_link_failure (./include/linux/skbuff.h:4327)
? _raw_write_lock (./include/linux/instrumented.h:55 ./include/linux/atomic/atomic-instrumented.h:1301 ./include/asm-generic/qrwlock.h:98 ./include/linux/rwlock_api_smp.h:230 kernel/locking/spinlock.c:304) ? __pfx__raw_write_lock (kernel/locking/spinlock.c:175)arp_error_report (./include/net/dst.h:438 net/ipv4/arp.c:296)neigh_invalidate (net/core/neighbour.c:1077)neigh_timer_handler (net/core/neighbour.c:1169)
[...]
Allocated by task 505: kasan_save_stack (mm/kasan/common.c:57) kasan_save_track (mm/kasan/common.c:78) __kasan_kmalloc (mm/kasan/common.c:398 mm/kasan/common.c:415) __kvmalloc_node_noprof (./include/linux/kasan.h:263 mm/slub.c:5334 mm/slub.c:6905) alloc_netdev_mqs (net/core/dev.c:12055 (discriminator 2))
rtnl_create_link (net/core/rtnetlink.c:3721)rtnl_newlink (net/core/rtnetlink.c:3903 net/core/rtnetlink.c:4044 net/core/rtnetlink.c:4159) rtnetlink_rcv_msg (net/core/rtnetlink.c:7076)
[...]
Freed by task 536: kasan_save_stack (mm/kasan/common.c:57) kasan_save_track (mm/kasan/common.c:78) kasan_save_free_info (mm/kasan/generic.c:584) __kasan_slab_free (mm/kasan/common.c:253 mm/kasan/common.c:285) kfree (./include/linux/kasan.h:235 mm/slub.c:2677 mm/slub.c:6377 mm/slub.c:6692)
device_release (drivers/base/core.c:2636)kobject_put (lib/kobject.c:689 lib/kobject.c:720 ./include/linux/kref.h:65 lib/kobject.c:737) netdev_run_todo (net/core/dev.c:11756)rtnl_dellink (net/core/rtnetlink.c:157 ./include/linux/rtnetlink.h:135 net/core/rtnetlink.c:3651) rtnetlink_rcv_msg (net/core/rtnetlink.c:7076)
[...]
Fix this by restoring skb->dev to the master at the end of each slave's iteration.
--- net/sched/sch_teql.c | 1 + 1 file changed, 1 insertion(+)
net/sched/sch_teql.c +1 -0
@@ -377,6 +377,7 @@ static netdev_tx_t teql_master_xmit(struct sk_buff *skb, struct net_device *dev) nores =1 ;break ; } + skb->dev = dev;__skb_pull (skb,skb_network_offset (skb)); }while ((q =rcu_dereference (NEXT_SLAVE (q))) != start);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1305/1376 tpm: st33zp24: Return zero on status read failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit 8b92687708f5ef980de01c2042dbd76d11f78547 ]
st33zp24_status() ignores the result of the transport read and returns data even when no byte was received. The I2C transport, for example, skips i2c_master_recv() when the register-select write is short or fails, leaving data uninitialized. The resulting stack value can be interpreted as TPM_STS flags and let status checks complete spuriously.
The status callback cannot propagate a transport error. Return zero unless recv() reports exactly one byte. With no status bits set, callers retry or take their existing timeout or error path instead of acting on an invalid status value.
This issue was found by a static analysis checker and confirmed by manual source review.
--- drivers/char/tpm/st33zp24/st33zp24.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/char/tpm/st33zp24/st33zp24.c +3 -1
@@ -93,7 +93,9 @@ static u8 st33zp24_status(struct tpm_chip *chip)struct st33zp24_dev *tpm_dev =dev_get_drvdata (&chip->dev);u8 data; - tpm_dev->ops->recv (tpm_dev->phy_id,TPM_STS , &data,1 ); +if (tpm_dev->ops->recv (tpm_dev->phy_id,TPM_STS , &data,1 ) !=1 ) +return 0 ; +return data; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1306/1376 tpm: st33zp24: Validate locality read result
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit 264216889d39df509b9c8045df53529480b0b718 ]
check_locality() treats every nonzero transport return as success. SPI errors remain negative, while the I2C path can convert a negative write error through its byte-sized status variable. Either result is nonzero even though the TPM_ACCESS byte can remain unwritten, so indeterminate ACTIVE_LOCALITY and VALID bits can falsely report an active locality.
Require recv() to return exactly the requested byte before examining TPM_ACCESS. Transport errors and short reads now report an inactive locality, while successful reads retain the existing behavior.
This issue was found by a static analysis checker and confirmed by manual source review.
--- drivers/char/tpm/st33zp24/st33zp24.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/char/tpm/st33zp24/st33zp24.c +2 -2
@@ -106,10 +106,10 @@ static bool check_locality(struct tpm_chip *chip) {struct st33zp24_dev *tpm_dev =dev_get_drvdata (&chip->dev);u8 data; -u8 status; +int status; status = tpm_dev->ops->recv (tpm_dev->phy_id,TPM_ACCESS , &data,1 ); -if (status && (data & +if (status ==1 && (data & (TPM_ACCESS_ACTIVE_LOCALITY |TPM_ACCESS_VALID )) == (TPM_ACCESS_ACTIVE_LOCALITY |TPM_ACCESS_VALID ))return true;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1307/1376 apparmor: Replace sprintf/strcpy with scnprintf/strscpy in aa_policy_init
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
[ Upstream commit b31d3f7385fbb49681d44e7104cfa033cba4b1e8 ]
strcpy() is deprecated and sprintf() does not perform bounds checking either. Although an overflow is unlikely, it's better to proactively avoid it by using the safer strscpy() and scnprintf(), respectively.
Additionally, unify memory allocation for 'hname' to simplify and improve aa_policy_init().
Stable-dep-of: 3daad923a868 ("apparmor: policy_int make sure list heads are initialized before fail path")
--- security/apparmor/lib.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-)
security/apparmor/lib.c +7 -9
@@ -448,19 +448,17 @@ bool aa_policy_init(struct aa_policy *policy, const char *prefix, const char *name, gfp_t gfp) { char *hname; +size_t hname_sz; + hname_sz = (prefix ?strlen (prefix) +2 :0 ) +strlen (name) +1 ;/* freed by policy_free */ -if (prefix) { - hname =aa_str_alloc (strlen (prefix) +strlen (name) +3 , gfp); -if (hname) -sprintf (hname,"%s//%s" , prefix, name); - }else { - hname =aa_str_alloc (strlen (name) +1 , gfp); -if (hname) -strcpy (hname, name); - } + hname =aa_str_alloc (hname_sz, gfp);if (!hname)return false; +if (prefix) +scnprintf (hname, hname_sz,"%s//%s" , prefix, name); +else +strscpy (hname, name, hname_sz); policy->hname = hname;/* base.name is a substring of fqname */ policy->name =basename (policy->hname);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1308/1376 apparmor: policy_int make sure list heads are initialized before fail path
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: John Johansen <[email protected]>
[ Upstream commit 3daad923a8685adb66087e0d819559b7eb6ba975 ]
If profile create fails before policy_init is complete the list heads are not properly initialized causing profile_free() sanity checks to trigger the following splat.
AppArmor WARN aa_policy_destroy: (((!list_empty(&policy->profiles) && (&policy->profiles)->prev != ((void *) 0x122 + (0xdead000000000000UL))))):
WARNING: security/apparmor/lib.c:509 at aa_policy_destroy+0x164/0x1b0 security/apparmor/lib.c:509, CPU#0: syz.0.17/5541 Modules linked in: CPU: 0 UID: 0 PID: 5541 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014 RIP: 0010:aa_policy_destroy+0x16b/0x1b0 security/apparmor/lib.c:509 Code: 85 ed 7e 4d e8 96 bc 37 fd 5b 41 5c 41 5e 41 5f 5d e9 19 27 4e 07 cc e8 83 bc 37 fd 48 8d 3d 0c f0 d3 0b 48 c7 c6 a4 eb 38 8e <67> 48 0f b9 3a e9 04 ff ff ff e8 66 bc 37 fd 48 8d 3d ff ef d3 0b RSP: 0018:ffffc9000345eaa0 EFLAGS: 00010293 RAX: ffffffff848f530d RBX: ffff88803f734800 RCX: ffff88801af2a580 RDX: 0000000000000000 RSI: ffffffff8e38eba4 RDI: ffffffff90634320 RBP: 0000000000000000 R08: 0000000000000cc0 R09: 00000000ffffffff R10: dffffc0000000000 R11: fffffbfff1d95913 R12: dead000000000122 R13: ffff88803f734800 R14: ffff88803f734828 R15: dffffc0000000000 FS: 00007f5f6a1836c0(0000) GS:ffff88808c519000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055d02407b048 CR3: 0000000012aa9000 CR4: 0000000000352ef0 Call Trace: <TASK> aa_free_profile+0x9d/0x9f0 security/apparmor/policy.c:334 aa_alloc_profile+0x1e4/0x3e0 security/apparmor/policy.c:416 unpack_profile security/apparmor/policy_unpack.c:1153 [inline] aa_unpack+0x17db/0x7430 security/apparmor/policy_unpack.c:1748 aa_replace_profiles+0x226/0x2a20 security/apparmor/policy.c:1183 policy_update+0x234/0x4a0 security/apparmor/apparmorfs.c:505 profile_load+0x1cb/0x320 security/apparmor/apparmorfs.c:522 vfs_write+0x296/0xba0 fs/read_write.c:685 ksys_write+0x150/0x270 fs/read_write.c:739 do_syscall_x64 arch/x86/entry/syscall_64.c:61 [inline] do_syscall_64+0x166/0x520 arch/x86/entry/syscall_64.c:84 entry_SYSCALL_64_after_hwframe+0x77/0x7f RIP: 0033:0x7f5f6939e0d9 Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007f5f6a183028 EFLAGS: 00000246 ORIG_RAX: 0000000000000001 RAX: ffffffffffffffda RBX: 00007f5f69625fa0 RCX: 00007f5f6939e0d9 RDX: 0000000000000041 RSI: 0000200000000400 RDI: 0000000000000003 RBP: 00007f5f6a183090 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001 R13: 00007f5f69626038 R14: 00007f5f69625fa0 R15: 00007ffe23725c18
--- security/apparmor/lib.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
security/apparmor/lib.c +2 -2
@@ -450,6 +450,8 @@ bool aa_policy_init(struct aa_policy *policy, const char *prefix,char *hname;size_t hname_sz; +INIT_LIST_HEAD (&policy->list); +INIT_LIST_HEAD (&policy->profiles); hname_sz = (prefix ?strlen (prefix) +2 :0 ) +strlen (name) +1 ;/* freed by policy_free */ hname =aa_str_alloc (hname_sz, gfp);
@@ -462,8 +464,6 @@ bool aa_policy_init(struct aa_policy *policy, const char *prefix, policy->hname = hname;/* base.name is a substring of fqname */ policy->name =basename (policy->hname); -INIT_LIST_HEAD (&policy->list); -INIT_LIST_HEAD (&policy->profiles);return true; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1309/1376 ASoC: dapm: Fix off-by-one check on the second enum channel
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: HyeongJun An <[email protected]>
[ Upstream commit 14511c9b54ceeeef487409d73947c89ee8563590 ]
The snd_soc_dapm_put_enum_double() rejects item[0] once it reaches e->items, but it lets item[1] be equal to it. Both go on to snd_soc_enum_item_to_val(), which indexes e->values with no bound of its own, so an enum with a value table reads one element past the end.
The indexing arrived with the MUX consolidation, which relaxed the item[1] check in the same hunk. The value MUX handler it deleted used
Quoted 1 line
= there, and the
snd_soc_put_enum_double()insoc-ops.cstill does.
Only adav80x pairs a value table with two shifts, and its second channel looks accidental, but the control does report two values. Writing three into it reads off the end of adav80x_mux_values. The core catches that only under CONFIG_SND_CTL_INPUT_VALIDATION, which defaults off.
--- sound/soc/soc-dapm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
sound/soc/soc-dapm.c +1 -1
@@ -3582,7 +3582,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol, val =snd_soc_enum_item_to_val (e, item[0 ]) << e->shift_l; mask = e->mask << e->shift_l;if (e->shift_l != e->shift_r) { -if (item[1 ] > e->items) +if (item[1 ] >= e->items)return -EINVAL ; val |=snd_soc_enum_item_to_val (e, item[1 ]) << e->shift_r; mask |= e->mask << e->shift_r;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1310/1376 ceph: revalidate ki_pos for O_APPEND writes after cap acquisition
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiubo Li <[email protected]>
[ Upstream commit d2a8d446a09c74c8ddfe108b50dd791c889983fc ]
For O_APPEND writes, ki_pos is set to the current EOF via generic_write_checks() after fetching i_size from the MDS. However, ceph_get_caps() may need to wait for Fwx exclusive caps if the write extends the file (endoff > i_max_size). While waiting for Fwx, the previous Fwx holder (another client) may have already extended the file. When the MDS grants us Fwx, the cap grant message updates the local i_size, but ki_pos remains at the old EOF, causing the append write to land at a stale offset and overwrite data from the other client.
Fix by re-reading i_size_read(inode) after ceph_get_caps() returns. At this point we hold Fwx exclusive caps, no other client can modify the file, and i_size reflects the true EOF from the MDS cap grant. No extra MDS round-trip is needed. Only adjust ki_pos when the EOF has actually changed.
After adjusting ki_pos forward, the write range [pos, pos+count) may now exceed the i_max_size that was validated by ceph_get_caps() for the old range. Re-check against i_max_size and truncate the write if necessary to stay within the MDS-granted limit.
--- fs/ceph/file.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+)
fs/ceph/file.c +48 -0
@@ -2411,6 +2411,54 @@ static ssize_t ceph_write_iter(struct kiocb *iocb, struct iov_iter *from)if (err <0 ) goto out; +/* +* For O_APPEND writes we may have waited for Fwx exclusive caps +* while the previous Fwx holder (another client) extended the +* file. i_size has been updated via the cap grant message from +* the MDS, but ki_pos is still the old EOF. Re-read i_size here +* (no extra MDS round-trip needed) and adjust ki_pos to the true +* EOF. Since we hold Fwx, no other client can change the file. +*/ +if (iocb->ki_flags &IOCB_APPEND ) { +loff_t cur_eof =i_size_read (inode); + +if (cur_eof != pos) { +doutc (cl, +"%p %llx.%llx O_APPEND: pos adjusted %lld -> %lld\n" , + inode,ceph_vinop (inode), pos, cur_eof); + iocb->ki_pos = cur_eof; + pos = cur_eof; +if (pos >= limit) { + err = -EFBIG ; + goto out_caps; + } +iov_iter_truncate (from, limit - pos); + count =iov_iter_count (from); + +/* +* ceph_get_caps() validated the old endoff +* against i_max_size; adjusting ki_pos forward +* may have shifted the write range beyond the +* granted max_size. Re-check and truncate if +* necessary. +*/ +spin_lock (&ci->i_ceph_lock); +if (pos + count > (loff_t )ci->i_max_size) { +loff_t max_size = ci->i_max_size; + +spin_unlock (&ci->i_ceph_lock); +if (pos >= max_size) { + err = -EFBIG ; + goto out_caps; + } +iov_iter_truncate (from, max_size - pos); + count =iov_iter_count (from); + }else { +spin_unlock (&ci->i_ceph_lock); + } + } + } + err =file_update_time (file);if (err) goto out_caps;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1311/1376 libceph: validate banner payload length
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Nogikh <[email protected]>
[ Upstream commit f374967fcdf04001c9b66df1c19106fa83cd91f7 ]
When parsing the Ceph messenger v2 protocol banner, the payload_len field is decoded from the banner prefix. If a client sends a banner with a payload_len of 0, the kernel sets up a 0-length socket read. This violates an invariant in the state machine, triggering a warning in populate_in_iter():
------------[ cut here ]------------ !iov_iter_count(&con->v2.in_iter) WARNING: net/ceph/messenger_v2.c:3129 at populate_in_iter net/ceph/messenger_v2.c:3129 [inline], CPU#1: kworker/1:3/5070 WARNING: net/ceph/messenger_v2.c:3129 at ceph_con_v2_try_read+0x6634/0x6810 net/ceph/messenger_v2.c:3159, CPU#1: kworker/1:3/5070 ... Call Trace: <TASK> ceph_con_workfn+0x1f5/0x14a0 net/ceph/messenger.c:1575 process_one_work kernel/workqueue.c:3322 [inline] process_scheduled_works+0xa8e/0x14e0 kernel/workqueue.c:3405 worker_thread+0xa47/0xfb0 kernel/workqueue.c:3486 kthread+0x388/0x470 kernel/kthread.c:436 ret_from_fork+0x514/0xb70 arch/x86/kernel/process.c:158 ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:245 </TASK>
According to the msgr2 protocol specification, the banner payload is expected to contain at least two 64-bit integers (server_feat and server_req_feat). Therefore, payload_len must be at least 16 bytes.
Fix this by adding a check in process_banner_prefix() to reject a payload_len smaller than 16 bytes. This prevents the 0-length read and correctly aborts the connection with a protocol error.
--- net/ceph/messenger_v2.c | 5 +++++ 1 file changed, 5 insertions(+)
net/ceph/messenger_v2.c +5 -0
@@ -2172,6 +2172,11 @@ static int process_banner_prefix(struct ceph_connection *con) payload_len =ceph_decode_16 (&p);dout ("%s con %p payload_len %d\n" , __func__, con, payload_len); +if (payload_len <sizeof (u64) +sizeof (u64)) { + con->error_msg ="protocol error, bad banner payload len" ; +return -EINVAL ; + } +return prepare_read_banner_payload (con, payload_len); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1312/1376 samples/ftrace: Fix kthread_stop() on ERR_PTR in ftrace-direct-modify
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haotian Zhang <[email protected]>
[ Upstream commit d79fb758e7e2e7a181eab630c0545a56041c473d ]
ftrace_direct_init() assigns kthread_run()'s return value to simple_tsk without an IS_ERR() check. When kthread_run() fails it returns ERR_PTR(-ENOMEM), but init still returns 0, so the module loads with simple_tsk holding an error pointer. On unload, ftrace_direct_exit() then passes that ERR_PTR to kthread_stop(), leading to a null-pointer-dereference.
Check the return value of kthread_run() with IS_ERR(); on failure, unregister the ftrace direct call and propagate the error code.
--- samples/ftrace/ftrace-direct-modify.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
samples/ftrace/ftrace-direct-modify.c +9 -3
@@ -237,9 +237,15 @@ static int __init ftrace_direct_init(void)ftrace_set_filter_ip (&direct, (unsigned long ) my_ip,0 ,0 ); ret =register_ftrace_direct (&direct, my_tramp); -if (!ret) - simple_tsk =kthread_run (simple_thread,NULL ,"event-sample-fn" ); -return ret; +if (ret) +return ret; + simple_tsk =kthread_run (simple_thread,NULL ,"event-sample-fn" ); +if (IS_ERR (simple_tsk)) { +unregister_ftrace_direct (&direct, my_tramp, true); +return PTR_ERR (simple_tsk); + } + +return 0 ; } static void __exit ftrace_direct_exit(void)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1313/1376 samples/ftrace: Fix kthread_stop() on ERR_PTR in ftrace-direct-multi-modify
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haotian Zhang <[email protected]>
[ Upstream commit 6727b7618f49401acf373fa3ec5712e2ec52e5cf ]
ftrace_direct_multi_init() assigns kthread_run()'s return value to simple_tsk without an IS_ERR() check. When kthread_run() fails it returns ERR_PTR(-ENOMEM), but init still returns 0, so the module loads with simple_tsk holding an error pointer. On unload, ftrace_direct_multi_exit() then passes that ERR_PTR to kthread_stop(), leading to a null-pointer-dereference.
Check the return value of kthread_run() with IS_ERR(); on failure, unregister the ftrace direct call and propagate the error code.
--- samples/ftrace/ftrace-direct-multi-modify.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-)
samples/ftrace/ftrace-direct-multi-modify.c +9 -3
@@ -265,9 +265,15 @@ static int __init ftrace_direct_multi_init(void) ret =register_ftrace_direct (&direct, my_tramp); -if (!ret) - simple_tsk =kthread_run (simple_thread,NULL ,"event-sample-fn" ); -return ret; +if (ret) +return ret; + simple_tsk =kthread_run (simple_thread,NULL ,"event-sample-fn" ); +if (IS_ERR (simple_tsk)) { +unregister_ftrace_direct (&direct, my_tramp, true); +return PTR_ERR (simple_tsk); + } + +return 0 ; } static void __exit ftrace_direct_multi_exit(void)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1314/1376 net: ethernet: sun4i-emac: Fix IRQ error handling
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: bui duc phuc <[email protected]>
[ Upstream commit 991c2be78257cba5bf53cf935fe70f8836964288 ]
irq_of_parse_and_map() returns 0 when parsing or mapping an IRQ fails. The current code checks for -ENXIO and therefore does not detect the failure.
Check for a zero return value and convert it to -ENXIO.
--- drivers/net/ethernet/allwinner/sun4i-emac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/allwinner/sun4i-emac.c +2 -2
@@ -996,9 +996,9 @@ static int emac_probe(struct platform_device *pdev)/* fill in parameters for net-dev structure */ ndev->base_addr = (unsigned long )db->membase; ndev->irq =irq_of_parse_and_map (np,0 ); -if (ndev->irq == -ENXIO ) { +if (!ndev->irq) {netdev_err (ndev,"No irq resource\n" ); - ret = ndev->irq; + ret = -ENXIO ; goto out_iounmap; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1315/1376 net/smc: release the internal TCP sock on IPPROTO_SMC socket creation failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yifei Chu <[email protected]>
[ Upstream commit cec261b0b4c5c0b044165303198d10ffcdf3414c ]
IPPROTO_SMC sockets create an internal TCP sock ("clcsock") from the proto->init hook. When socket creation fails after proto->init has run - e.g. a cgroup BPF program attached to BPF_CGROUP_INET_SOCK_CREATE denies the socket - sk_common_release() only invokes sk_prot->destroy if it is set, but neither smc_inet_prot nor smc_inet6_prot defines it, and smc_destruct() returns early unless sk_state is SMC_CLOSED. As a result, every failing socket(AF_INET, SOCK_STREAM, IPPROTO_SMC) call leaks one tcp_sock, so an unprivileged task able to attach a deny-all BPF_CGROUP_INET_SOCK_CREATE program to its own cgroup can grow kernel memory unboundedly.
Add a .destroy hook to both protos that releases the clcsock via smc_clcsock_release(). smc_sk_init() hashes the sock into the smc hashinfo before the clcsock is created, and smc_diag dumps walk that hash dereferencing smc->clcsock without taking clcsock_release_lock, while sk_common_release() calls .destroy before .unhash. Unhash the sock before releasing the clcsock, as __smc_release() does, so a concurrent dump cannot observe the release; the second unhash in sk_common_release() is a no-op.
--- net/smc/smc_inet.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+)
net/smc/smc_inet.c +16 -0
@@ -15,13 +15,16 @@#include "smc_inet.h" #include "smc.h" +#include "smc_close.h" static int smc_inet_init_sock (struct sock *sk); +static void smc_inet_destroy_sock (struct sock *sk);static struct proto smc_inet_prot = { .name ="INET_SMC" , .owner =THIS_MODULE , .init = smc_inet_init_sock, + .destroy = smc_inet_destroy_sock, .hash = smc_hash_sk, .unhash = smc_unhash_sk, .release_cb = smc_release_cb,
@@ -68,6 +71,7 @@ static struct proto smc_inet6_prot = { .name = "INET6_SMC", .owner = THIS_MODULE, .init = smc_inet_init_sock, + .destroy = smc_inet_destroy_sock, .hash = smc_hash_sk, .unhash = smc_unhash_sk, .release_cb = smc_release_cb,
@@ -116,6 +120,18 @@ static int smc_inet_init_sock(struct sock *sk)return smc_create_clcsk (net, sk, sk->sk_family); } +static void smc_inet_destroy_sock (struct sock *sk) +{ +/* The sock is hashed and smc_diag dumps dereference smc->clcsock +* without clcsock_release_lock, while sk_common_release() calls +* .destroy before .unhash. Unhash first, as __smc_release() does, +* so no dump can observe the clcsock being released; the second +* unhash is a no-op. +*/ + sk->sk_prot->unhash (sk); +smc_clcsock_release (smc_sk (sk)); +} +int __init smc_inet_init (void ) {int rc;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1316/1376 net: wangxun: use BIT_ULL() to prevent shift overflow on 32-bit archs
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiawen Wu <[email protected]>
[ Upstream commit 63c885688f38a757947d7050b1ee4171215269ce ]
The macros TXGBE_INTR_MISC() and WX_INTR_Q() rely on the standard BIT() macro to generate interrupt masks based on the queue vector index.
On 32-bit architectures, BIT() evaluates to a 32-bit unsigned long. Since the number of queue vectors can be up to 63 on txgbe devices, performing a left shift of 32 or more results in an integer overflow and undefined behavior. This causes incorrect interrupt masking and unmasking logic for both the queue and miscellaneous interrupts on 32-bit systems.
Fix this by replacing BIT() with BIT_ULL() in these macros. This ensures that the bitwise shift is always performed safely on a 64-bit unsigned long long type, regardless of the underlying architecture.
--- drivers/net/ethernet/wangxun/libwx/wx_type.h | 2 +- drivers/net/ethernet/wangxun/txgbe/txgbe_type.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/wangxun/libwx/wx_type.h +1 -1
@@ -1134,7 +1134,7 @@ struct wx { };#define WX_INTR_ALL (~0ULL) -#define WX_INTR_Q (i) BIT((i)) +#define WX_INTR_Q (i) BIT_ULL((i))/* register operations */ #define wr32 (a, reg, value) writel((value), ((a)->hw_addr + (reg)))
drivers/net/ethernet/wangxun/txgbe/txgbe_type.h +1 -1
@@ -264,7 +264,7 @@ struct txgbe_fdir_filter {#define TXGBE_DEFAULT_RX_WORK 128#endif -#define TXGBE_INTR_MISC (A ) BIT((A)->num_q_vectors) +#define TXGBE_INTR_MISC (A ) BIT_ULL((A)->num_q_vectors)#define TXGBE_INTR_QALL (A ) (TXGBE_INTR_MISC(A) - 1)#define TXGBE_MAX_EITR GENMASK(11, 3)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1317/1376 net: stmmac: selftests: Pass the IP proto mask in the TC selftest
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maxime Chevallier <[email protected]>
[ Upstream commit 9a56a27e6002e29a6707dc4238d469ec84c3a68e ]
The stmmac TC filtering rules have recently gained sanity checks to make sure the passed keys and their respective masks are aligned with the HW filtering abilities.
The stmmac selftests failed to pass the mask in the match data for L4 filtering tests, and are now failing consistently with -EINVAL :
$ ethtool -t eth1 [...] 23. L4 DA TCP Filtering -22 24. L4 SA TCP Filtering -22 25. L4 DA UDP Filtering -22 26. L4 SA UDP Filtering -22
Let's pass the ip_proto mask in the l4 filtering tests match data. Found on imx8mp, which now have passing L4 tests :
$ ethtool -t eth1 [...] 23. L4 DA TCP Filtering 0 24. L4 SA TCP Filtering 0 25. L4 DA UDP Filtering 0 26. L4 SA UDP Filtering 0
While at it, initialize the masks and keys to avoid re-using whatever was on the stack.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +4 -2
@@ -1452,11 +1452,11 @@ static int __stmmac_test_l4filt(struct stmmac_priv *priv, u32 dst, u32 src,struct {struct flow_dissector_key_basic bkey;struct flow_dissector_key_ports key; - }__aligned(BITS_PER_LONG / 8) keys; + }__aligned(BITS_PER_LONG / 8) keys = { };struct {struct flow_dissector_key_basic bmask;struct flow_dissector_key_ports mask; - }__aligned(BITS_PER_LONG / 8) masks; + }__aligned(BITS_PER_LONG / 8) masks = { };unsigned long dummy_cookie =0xdeadbeef ;struct stmmac_packet_attrs attr = { };struct flow_dissector *dissector;
@@ -1509,6 +1509,8 @@ static int __stmmac_test_l4filt(struct stmmac_priv *priv, u32 dst, u32 src, keys.bkey.ip_proto = udp ?IPPROTO_UDP :IPPROTO_TCP ; keys.key.src =htons (src); keys.key.dst =htons (dst); +/* Match the full IP proto field */ + masks.bmask.ip_proto =0xff ; masks.mask.src = src_mask; masks.mask.dst = dst_mask;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1318/1376 virtio-net: Ensure that TCP packets dont overflow gso_segs
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alice Mikityanska <[email protected]>
[ Upstream commit c27c449d455aafd9018a3cbab150f1c42c87923f ]
The user can specify any gso_size in a packet crafted with an AF_PACKET PACKET_VNET_HDR socket, even smaller than TCP_MIN_GSO_SIZE = 8. At the same time, GSO_MAX_SIZE = 8 * GSO_MAX_SEGS = 8 * 65535. When the user crafts a packet with gso_size < 8, there is a risk for partial GSO to overflow the 16-bit gso_segs field when dividing the SKB length by gso_size.
Adjust gso_size of TCP packets to be at least TCP_MIN_GSO_SIZE = 8. Keep gso_size of UDP GSO packets, as gso_size=1 is valid and explicitly tested at tools/testing/selftests/net/tun.c:649.
--- include/linux/virtio_net.h | 4 ++++ 1 file changed, 4 insertions(+)
include/linux/virtio_net.h +4 -0
@@ -6,6 +6,7 @@#include <linux/ip.h> #include <linux/ipv6.h> #include <linux/udp.h> +#include <net/tcp.h> #include <uapi/linux/tcp.h> #include <uapi/linux/virtio_net.h>
@@ -178,6 +179,9 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,if (skb->ip_summed ==CHECKSUM_PARTIAL && skb->csum_offset != offsetof(struct tcphdr , check))return -EINVAL ; + +BUILD_BUG_ON (TCP_MIN_GSO_SIZE *GSO_MAX_SEGS <GSO_MAX_SIZE ); + gso_size =max (gso_size,TCP_MIN_GSO_SIZE );break ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1319/1376 netfilter: nf_tables: move hardware offload step after building the chain blob
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit b1881d362e1924b66f6016c3efd28807032b41bf ]
Allocate the chain blob before the ruleset offload to reduce chances of entering an inconsistent state where the offloaded ruleset in the nic and the software ruleset differ.
--- net/netfilter/nf_tables_api.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
net/netfilter/nf_tables_api.c +10 -4
@@ -10271,10 +10271,6 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)return -EAGAIN ; } - err =nft_flow_rule_offload_commit (net); -if (err <0 ) -return err; -/* 1. Allocate space for next generation rules_gen_X[] */ list_for_each_entry_safe (trans, next, &nft_net->commit_list, list) {struct nft_table *table = trans->table;
@@ -10299,6 +10295,16 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb) } } +/* must be last, so audit and chain blob set up does not leave hardware +* in consistent state. +*/ + err =nft_flow_rule_offload_commit (net); +if (err <0 ) { +nf_tables_commit_chain_prepare_cancel (net); +nf_tables_commit_audit_free (&adl); +return err; + } +/* step 2. Make rules_gen_X visible to packet path */ list_for_each_entry (table, &nft_net->tables, list) {list_for_each_entry (chain, &table->chains, list)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1320/1376 netfilter: xt_cgroup: Make it independent from net_cls
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Koutný <[email protected]>
[ Upstream commit 3ba0032afea888d0edebf5ece3c6b36417189b63 ]
The xt_group matching supports the default hierarchy since commit c38c4597e4bf3 ("netfilter: implement xt_cgroup cgroup2 path match"). The cgroup v1 matching (based on clsid) and cgroup v2 matching (based on path) are rather independent. Downgrade the Kconfig dependency to mere CONFIG_SOCK_GROUP_DATA so that xt_group can be built even without CONFIG_NET_CLS_CGROUP for path matching.
Also add a message for users when they attempt to specify any clsid.
Stable-dep-of: 793d9eda4821 ("netfilter: x_tables: replace pr_{info,err}() by pr_info_ratelimited()")
--- net/netfilter/Kconfig | 2 +- net/netfilter/xt_cgroup.c | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-)
net/netfilter/Kconfig +1 -1
@@ -1180,7 +1180,7 @@ config NETFILTER_XT_MATCH_CGROUP tristate '"control group" match support' depends on NETFILTER_ADVANCED depends on CGROUPS - select CGROUP_NET_CLASSID + select SOCK_CGROUP_DATA help Socket/process control group matching allows you to match locally generated packets based on which net_cls control group processes
net/netfilter/xt_cgroup.c +17 -0
@@ -23,6 +23,8 @@ MODULE_DESCRIPTION("Xtables: process control group matching");MODULE_ALIAS ("ipt_cgroup" );MODULE_ALIAS ("ip6t_cgroup" ); +#define NET_CLS_CLASSID_INVALID_MSG "xt_cgroup: classid invalid without net_cls cgroups\n" +static int cgroup_mt_check_v0 (const struct xt_mtchk_param *par) {struct xt_cgroup_info_v0 *info = par->matchinfo;
@@ -30,6 +32,11 @@ static int cgroup_mt_check_v0(const struct xt_mtchk_param *par)if (info->invert & ~1 )return -EINVAL ; +if (!IS_ENABLED (CONFIG_CGROUP_NET_CLASSID )) { +pr_info (NET_CLS_CLASSID_INVALID_MSG ); +return -EINVAL ; + } +return 0 ; }
@@ -51,6 +58,11 @@ static int cgroup_mt_check_v1(const struct xt_mtchk_param *par)return -EINVAL ; } +if (info->has_classid && !IS_ENABLED (CONFIG_CGROUP_NET_CLASSID )) { +pr_info (NET_CLS_CLASSID_INVALID_MSG ); +return -EINVAL ; + } + info->priv =NULL ;if (info->has_path) {if (strnlen (info->path,sizeof (info->path)) >=sizeof (info->path))
@@ -86,6 +98,11 @@ static int cgroup_mt_check_v2(const struct xt_mtchk_param *par)return -EINVAL ; } +if (info->has_classid && !IS_ENABLED (CONFIG_CGROUP_NET_CLASSID )) { +pr_info (NET_CLS_CLASSID_INVALID_MSG ); +return -EINVAL ; + } + info->priv =NULL ;if (info->has_path) {if (strnlen (info->path,sizeof (info->path)) >=sizeof (info->path))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1321/1376 netfilter: xt_HL: add pr_fmt and checkentry validation
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marino Dzalto <[email protected]>
[ Upstream commit 24bd5c2679caf8a228d90cafa221da4b47fd6642 ]
Add pr_fmt to prefix log messages with the module name for easier debugging in dmesg.
Add checkentry functions for IPv4 (ttl_mt_check) and IPv6 (hl_mt6_check) to validate the match mode at rule registration time, rejecting invalid modes with -EINVAL.
The evaluation function returns false in case the mode is unknown, so this is a cleanup, not a bug fix.
Stable-dep-of: 793d9eda4821 ("netfilter: x_tables: replace pr_{info,err}() by pr_info_ratelimited()")
--- net/netfilter/xt_hl.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+)
net/netfilter/xt_hl.c +27 -0
@@ -6,6 +6,7 @@* Hop Limit matching module * (C) 2001-2002 Maciej Soltysiak <[email protected]> */ +#define pr_fmt (fmt) KBUILD_MODNAME ": " fmt#include <linux/ip.h> #include <linux/ipv6.h>
@@ -22,6 +23,18 @@ MODULE_LICENSE("GPL");MODULE_ALIAS ("ipt_ttl" );MODULE_ALIAS ("ip6t_hl" ); +static int ttl_mt_check (const struct xt_mtchk_param *par) +{ +const struct ipt_ttl_info *info = par->matchinfo; + +if (info->mode >IPT_TTL_GT ) { +pr_err ("Unknown TTL match mode: %d\n" , info->mode); +return -EINVAL ; + } + +return 0 ; +} +static bool ttl_mt (const struct sk_buff *skb,struct xt_action_param *par) {const struct ipt_ttl_info *info = par->matchinfo;
@@ -41,6 +54,18 @@ static bool ttl_mt(const struct sk_buff *skb, struct xt_action_param *par)return false; } +static int hl_mt6_check (const struct xt_mtchk_param *par) +{ +const struct ip6t_hl_info *info = par->matchinfo; + +if (info->mode >IP6T_HL_GT ) { +pr_err ("Unknown Hop Limit match mode: %d\n" , info->mode); +return -EINVAL ; + } + +return 0 ; +} +static bool hl_mt6 (const struct sk_buff *skb,struct xt_action_param *par) {const struct ip6t_hl_info *info = par->matchinfo;
@@ -65,6 +90,7 @@ static struct xt_match hl_mt_reg[] __read_mostly = { .name = "ttl", .revision = 0, .family = NFPROTO_IPV4, + .checkentry = ttl_mt_check, .match = ttl_mt, .matchsize = sizeof(struct ipt_ttl_info), .me = THIS_MODULE,
@@ -73,6 +99,7 @@ static struct xt_match hl_mt_reg[] __read_mostly = { .name = "hl", .revision = 0, .family = NFPROTO_IPV6, + .checkentry = hl_mt6_check, .match = hl_mt6, .matchsize = sizeof(struct ip6t_hl_info), .me = THIS_MODULE,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1322/1376 netfilter: x_tables: replace pr_{info,err}() by pr_info_ratelimited()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 793d9eda4821f75b5f7cc9e6a870b72a58b44c2b ]
Several xtables extension still use pr_err() or pr_info() without ratelimit.
For xt_cgroup, while at this, remove redundant "xt_cgroup:" prefix since pr_fmt is already set on.
--- net/netfilter/xt_cgroup.c | 12 ++++++------ net/netfilter/xt_hl.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-)
net/netfilter/xt_cgroup.c +6 -6
@@ -23,7 +23,7 @@ MODULE_DESCRIPTION("Xtables: process control group matching");MODULE_ALIAS ("ipt_cgroup" );MODULE_ALIAS ("ip6t_cgroup" ); -#define NET_CLS_CLASSID_INVALID_MSG "xt_cgroup: classid invalid without net_cls cgroups\n" +#define NET_CLS_CLASSID_INVALID_MSG "classid invalid without net_cls cgroups\n"static int cgroup_mt_check_v0 (const struct xt_mtchk_param *par) {
@@ -33,7 +33,7 @@ static int cgroup_mt_check_v0(const struct xt_mtchk_param *par)return -EINVAL ;if (!IS_ENABLED (CONFIG_CGROUP_NET_CLASSID )) { -pr_info (NET_CLS_CLASSID_INVALID_MSG ); +pr_info_ratelimited (NET_CLS_CLASSID_INVALID_MSG );return -EINVAL ; }
@@ -49,7 +49,7 @@ static int cgroup_mt_check_v1(const struct xt_mtchk_param *par)return -EINVAL ;if (!info->has_path && !info->has_classid) { -pr_info ("xt_cgroup: no path or classid specified\n" ); +pr_info_ratelimited ("no path or classid specified\n" );return -EINVAL ; }
@@ -59,7 +59,7 @@ static int cgroup_mt_check_v1(const struct xt_mtchk_param *par) }if (info->has_classid && !IS_ENABLED (CONFIG_CGROUP_NET_CLASSID )) { -pr_info (NET_CLS_CLASSID_INVALID_MSG ); +pr_info_ratelimited (NET_CLS_CLASSID_INVALID_MSG );return -EINVAL ; }
@@ -89,7 +89,7 @@ static int cgroup_mt_check_v2(const struct xt_mtchk_param *par)return -EINVAL ;if (!info->has_path && !info->has_classid) { -pr_info ("xt_cgroup: no path or classid specified\n" ); +pr_info_ratelimited ("no path or classid specified\n" );return -EINVAL ; }
@@ -99,7 +99,7 @@ static int cgroup_mt_check_v2(const struct xt_mtchk_param *par) }if (info->has_classid && !IS_ENABLED (CONFIG_CGROUP_NET_CLASSID )) { -pr_info (NET_CLS_CLASSID_INVALID_MSG ); +pr_info_ratelimited (NET_CLS_CLASSID_INVALID_MSG );return -EINVAL ; }
net/netfilter/xt_hl.c +2 -2
@@ -28,7 +28,7 @@ static int ttl_mt_check(const struct xt_mtchk_param *par)const struct ipt_ttl_info *info = par->matchinfo;if (info->mode >IPT_TTL_GT ) { -pr_err ("Unknown TTL match mode: %d\n" , info->mode); +pr_info_ratelimited ("Unknown TTL match mode: %d\n" , info->mode);return -EINVAL ; }
@@ -59,7 +59,7 @@ static int hl_mt6_check(const struct xt_mtchk_param *par)const struct ip6t_hl_info *info = par->matchinfo;if (info->mode >IP6T_HL_GT ) { -pr_err ("Unknown Hop Limit match mode: %d\n" , info->mode); +pr_info_ratelimited ("Unknown Hop Limit match mode: %d\n" , info->mode);return -EINVAL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1323/1376 ALSA: control: Dont add invalid kcontrols to LED layer
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Takashi Iwai <[email protected]>
[ Upstream commit 74e3b979ce8b78a690f8b94ccf2e2c965f7f5c11 ]
The kcontrol LED state layer tries to track the all associated kcontrol elements with naive assumptions that they are readable. But one can create a write-only element that has no get callback (even a user element can do it), and this may lead to a NULL dereference at the call chain of snd_ctl_led_notify(), as found by syzkaller.
For avoiding the Oops, add a sanity check of the kcontrol's info and get callbacks, and just skip the invalid kcontrols before assigning the kctl to the LED layer.
--- sound/core/control_led.c | 2 ++ 1 file changed, 2 insertions(+)
sound/core/control_led.c +2 -0
@@ -255,6 +255,8 @@ static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id, kctl =snd_ctl_find_id (card, id);if (!kctl)return -ENOENT ; +if (!kctl->info || !kctl->get) +return -EINVAL ; ioff =snd_ctl_get_ioff (kctl, id); vd = &kctl->vd[ioff]; access = vd->access &SNDRV_CTL_ELEM_ACCESS_LED_MASK ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1324/1376 selftests: arm64: add hugetlb mte tests
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Shi <[email protected]>
[ Upstream commit 27879e8cb6b0fdb5cdcd76685f290729309711c6 ]
The tests cover mmap, mprotect hugetlb with MTE prot and COW.
Stable-dep-of: 8d2237e9d690 ("selftests/arm64: Print missing MTE TAP headers")
--- .../arm64/mte/check_hugetlb_options.c | 285 ++++++++++++++++++ 1 file changed, 285 insertions(+) create mode 100644 tools/testing/selftests/arm64/mte/check_hugetlb_options.c
tools/testing/selftests/arm64/mte/check_hugetlb_options.c new file +285 -0
@@ -0,0 +1,285 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (C) 2024 Ampere Computing LLC + +#define _GNU_SOURCE + +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <ucontext.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include "kselftest.h" +#include "mte_common_util.h" +#include "mte_def.h" + +#define TAG_CHECK_ON 0 +#define TAG_CHECK_OFF 1 + +static unsigned long default_huge_page_size (void ) +{ +unsigned long hps =0 ; +char *line =NULL ; +size_t linelen =0 ; +FILE *f =fopen ("/proc/meminfo" ,"r" ); + +if (!f) +return 0 ; +while (getline (&line, &linelen, f) >0 ) { +if (sscanf (line,"Hugepagesize: %lu kB" , &hps) ==1 ) { + hps <<=10 ; +break ; + } + } + +free (line); +fclose (f); +return hps; +} + +static bool is_hugetlb_allocated (void ) +{ +unsigned long hps =0 ; +char *line =NULL ; +size_t linelen =0 ; +FILE *f =fopen ("/proc/meminfo" ,"r" ); + +if (!f) +return false; +while (getline (&line, &linelen, f) >0 ) { +if (sscanf (line,"Hugetlb: %lu kB" , &hps) ==1 ) { + hps <<=10 ; +break ; + } + } + +free (line); +fclose (f); + +if (hps >0 ) +return true; + +return false; +} + +static void write_sysfs (char *str,unsigned long val) +{ +FILE *f; + + f =fopen (str,"w" ); +if (!f) { +ksft_print_msg ("ERR: missing %s\n" , str); +return ; + } +fprintf (f,"%lu" , val); +fclose (f); +} + +static void allocate_hugetlb () +{ +write_sysfs ("/proc/sys/vm/nr_hugepages" ,2 ); +} + +static void free_hugetlb () +{ +write_sysfs ("/proc/sys/vm/nr_hugepages" ,0 ); +} + +static int check_child_tag_inheritance (char *ptr,int size,int mode) +{ +int i, parent_tag, child_tag, fault, child_status; +pid_t child; + + parent_tag =MT_FETCH_TAG ((uintptr_t )ptr); + fault =0 ; + + child =fork (); +if (child ==-1 ) { +ksft_print_msg ("FAIL: child process creation\n" ); +return KSFT_FAIL ; + }else if (child ==0 ) { +mte_initialize_current_context (mode, (uintptr_t )ptr, size); +/* Do copy on write */ +memset (ptr,'1' , size); +mte_wait_after_trig (); +if (cur_mte_cxt.fault_valid == true) { + fault =1 ; + goto check_child_tag_inheritance_err; + } +for (i =0 ; i < size; i +=MT_GRANULE_SIZE ) { + child_tag =MT_FETCH_TAG ((uintptr_t )(mte_get_tag_address (ptr + i))); +if (parent_tag != child_tag) { +ksft_print_msg ("FAIL: child mte tag (%d) mismatch\n" , i); + fault =1 ; + goto check_child_tag_inheritance_err; + } + } +check_child_tag_inheritance_err: +_exit (fault); + } +/* Wait for child process to terminate */ +wait (&child_status); +if (WIFEXITED (child_status)) + fault =WEXITSTATUS (child_status); +else + fault =1 ; +return (fault) ?KSFT_FAIL :KSFT_PASS ; +} + +static int check_mte_memory (char *ptr,int size,int mode,int tag_check) +{ +mte_initialize_current_context (mode, (uintptr_t )ptr, size); +memset (ptr,'1' , size); +mte_wait_after_trig (); +if (cur_mte_cxt.fault_valid == true) +return KSFT_FAIL ; + +return KSFT_PASS ; +} + +static int check_hugetlb_memory_mapping (int mem_type,int mode,int mapping,int tag_check) +{ +char *ptr, *map_ptr; +int result; +unsigned long map_size; + + map_size =default_huge_page_size (); + +mte_switch_mode (mode,MTE_ALLOW_NON_ZERO_TAG ); + map_ptr = (char *)mte_allocate_memory (map_size, mem_type, mapping, false); +if (check_allocated_memory (map_ptr, map_size, mem_type, false) !=KSFT_PASS ) +return KSFT_FAIL ; + +mte_initialize_current_context (mode, (uintptr_t )map_ptr, map_size); +/* Only mte enabled memory will allow tag insertion */ + ptr =mte_insert_tags ((void *)map_ptr, map_size); +if (!ptr || cur_mte_cxt.fault_valid == true) { +ksft_print_msg ("FAIL: Insert tags on anonymous mmap memory\n" ); +munmap ((void *)map_ptr, map_size); +return KSFT_FAIL ; + } + result =check_mte_memory (ptr, map_size, mode, tag_check); +mte_clear_tags ((void *)ptr, map_size); +mte_free_memory ((void *)map_ptr, map_size, mem_type, false); +if (result ==KSFT_FAIL ) +return KSFT_FAIL ; + +return KSFT_PASS ; +} + +static int check_clear_prot_mte_flag (int mem_type,int mode,int mapping) +{ +char *map_ptr; +int prot_flag, result; +unsigned long map_size; + + prot_flag =PROT_READ |PROT_WRITE ; +mte_switch_mode (mode,MTE_ALLOW_NON_ZERO_TAG ); + map_size =default_huge_page_size (); + map_ptr = (char *)mte_allocate_memory_tag_range (map_size, mem_type, mapping, +0 ,0 ); +if (check_allocated_memory_range (map_ptr, map_size, mem_type, +0 ,0 ) !=KSFT_PASS ) +return KSFT_FAIL ; +/* Try to clear PROT_MTE property and verify it by tag checking */ +if (mprotect (map_ptr, map_size, prot_flag)) { +mte_free_memory_tag_range ((void *)map_ptr, map_size, mem_type, +0 ,0 ); +ksft_print_msg ("FAIL: mprotect not ignoring clear PROT_MTE property\n" ); +return KSFT_FAIL ; + } + result =check_mte_memory (map_ptr, map_size, mode,TAG_CHECK_ON ); +mte_free_memory_tag_range ((void *)map_ptr, map_size, mem_type,0 ,0 ); +if (result !=KSFT_PASS ) +return KSFT_FAIL ; + +return KSFT_PASS ; +} + +static int check_child_hugetlb_memory_mapping (int mem_type,int mode,int mapping) +{ +char *ptr; +int result; +unsigned long map_size; + + map_size =default_huge_page_size (); + +mte_switch_mode (mode,MTE_ALLOW_NON_ZERO_TAG ); + ptr = (char *)mte_allocate_memory_tag_range (map_size, mem_type, mapping, +0 ,0 ); +if (check_allocated_memory_range (ptr, map_size, mem_type, +0 ,0 ) !=KSFT_PASS ) +return KSFT_FAIL ; + result =check_child_tag_inheritance (ptr, map_size, mode); +mte_free_memory_tag_range ((void *)ptr, map_size, mem_type,0 ,0 ); +if (result ==KSFT_FAIL ) +return result; + +return KSFT_PASS ; +} + +int main (int argc,char *argv[]) +{ +int err; + + err =mte_default_setup (); +if (err) +return err; + +/* Register signal handlers */ +mte_register_signal (SIGBUS , mte_default_handler); +mte_register_signal (SIGSEGV , mte_default_handler); + +allocate_hugetlb (); + +if (!is_hugetlb_allocated ()) { +ksft_print_msg ("ERR: Unable allocate hugetlb pages\n" ); +return KSFT_FAIL ; + } + +/* Set test plan */ +ksft_set_plan (12 ); + +mte_enable_pstate_tco (); + +evaluate_test (check_hugetlb_memory_mapping (USE_MMAP ,MTE_SYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ,TAG_CHECK_OFF ), +"Check hugetlb memory with private mapping, sync error mode, mmap memory and tag check off\n" ); + +mte_disable_pstate_tco (); +evaluate_test (check_hugetlb_memory_mapping (USE_MMAP ,MTE_NONE_ERR ,MAP_PRIVATE |MAP_HUGETLB ,TAG_CHECK_OFF ), +"Check hugetlb memory with private mapping, no error mode, mmap memory and tag check off\n" ); + +evaluate_test (check_hugetlb_memory_mapping (USE_MMAP ,MTE_SYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ,TAG_CHECK_ON ), +"Check hugetlb memory with private mapping, sync error mode, mmap memory and tag check on\n" ); +evaluate_test (check_hugetlb_memory_mapping (USE_MPROTECT ,MTE_SYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ,TAG_CHECK_ON ), +"Check hugetlb memory with private mapping, sync error mode, mmap/mprotect memory and tag check on\n" ); +evaluate_test (check_hugetlb_memory_mapping (USE_MMAP ,MTE_ASYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ,TAG_CHECK_ON ), +"Check hugetlb memory with private mapping, async error mode, mmap memory and tag check on\n" ); +evaluate_test (check_hugetlb_memory_mapping (USE_MPROTECT ,MTE_ASYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ,TAG_CHECK_ON ), +"Check hugetlb memory with private mapping, async error mode, mmap/mprotect memory and tag check on\n" ); + +evaluate_test (check_clear_prot_mte_flag (USE_MMAP ,MTE_SYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ), +"Check clear PROT_MTE flags with private mapping, sync error mode and mmap memory\n" ); +evaluate_test (check_clear_prot_mte_flag (USE_MPROTECT ,MTE_SYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ), +"Check clear PROT_MTE flags with private mapping and sync error mode and mmap/mprotect memory\n" ); + +evaluate_test (check_child_hugetlb_memory_mapping (USE_MMAP ,MTE_SYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ), +"Check child hugetlb memory with private mapping, precise mode and mmap memory\n" ); +evaluate_test (check_child_hugetlb_memory_mapping (USE_MMAP ,MTE_ASYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ), +"Check child hugetlb memory with private mapping, precise mode and mmap memory\n" ); +evaluate_test (check_child_hugetlb_memory_mapping (USE_MPROTECT ,MTE_SYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ), +"Check child hugetlb memory with private mapping, precise mode and mmap/mprotect memory\n" ); +evaluate_test (check_child_hugetlb_memory_mapping (USE_MPROTECT ,MTE_ASYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ), +"Check child hugetlb memory with private mapping, precise mode and mmap/mprotect memory\n" ); + +mte_restore_setup (); +free_hugetlb (); +ksft_print_cnts (); +return ksft_get_fail_cnt () ==0 ?KSFT_PASS :KSFT_FAIL ; +}
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1325/1376 selftests/arm64: Print missing MTE TAP headers
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muhammad Usama Anjum <[email protected]>
[ Upstream commit 8d2237e9d6902e234bb89aabb9cd6a9e91357223 ]
Most MTE tests set a TAP plan and emit results without first printing the TAP version header. Direct execution therefore starts with a plan such as "1..20" instead of "TAP version 13".
The problem is particularly visible in the GCR_EL1 context-switch test. It prints its plan before forking 1,024 child processes. When stdout is fully buffered, the plan remains in the stdio buffer. Each child inherits the pending "1..1" line and flushes its copy from exit(), producing repeated plan lines.
ksft_print_header() prints the TAP header and enables line buffering. Call it in every MTE test that is missing it. In the GCR_EL1 test, call it before the plan so the plan is flushed before the children are forked. In the remaining tests, call it before setup and prerequisite checks so early failures and whole-test skips also retain the header.
--- tools/testing/selftests/arm64/mte/check_buffer_fill.c | 2 ++ tools/testing/selftests/arm64/mte/check_child_memory.c | 2 ++ tools/testing/selftests/arm64/mte/check_gcr_el1_cswitch.c | 1 + tools/testing/selftests/arm64/mte/check_hugetlb_options.c | 2 ++ tools/testing/selftests/arm64/mte/check_ksm_options.c | 2 ++ tools/testing/selftests/arm64/mte/check_mmap_options.c | 2 ++ tools/testing/selftests/arm64/mte/check_tags_inclusion.c | 2 ++ tools/testing/selftests/arm64/mte/check_user_mem.c | 2 ++ 8 files changed, 15 insertions(+)
tools/testing/selftests/arm64/mte/check_buffer_fill.c +2 -0
@@ -406,6 +406,8 @@ int main(int argc, char *argv[])size_t page_size =getpagesize ();int item =ARRAY_SIZE (sizes); +ksft_print_header (); + sizes[item -3 ] = page_size -1 ; sizes[item -2 ] = page_size; sizes[item -1 ] = page_size +1 ;
tools/testing/selftests/arm64/mte/check_child_memory.c +2 -0
@@ -146,6 +146,8 @@ int main(int argc, char *argv[])int err;int item =ARRAY_SIZE (sizes); +ksft_print_header (); + page_size =getpagesize ();if (!page_size) {ksft_print_msg ("ERR: Unable to get page size\n" );
tools/testing/selftests/arm64/mte/check_gcr_el1_cswitch.c +1 -0
@@ -131,6 +131,7 @@ int main(int argc, char *argv[])if (err)return err; +ksft_print_header ();ksft_set_plan (1 ); evaluate_test(mte_gcr_fork_test(),
tools/testing/selftests/arm64/mte/check_hugetlb_options.c +2 -0
@@ -228,6 +228,8 @@ int main(int argc, char *argv[]) {int err; +ksft_print_header (); + err =mte_default_setup ();if (err)return err;
tools/testing/selftests/arm64/mte/check_ksm_options.c +2 -0
@@ -132,6 +132,8 @@ int main(int argc, char *argv[]) {int err; +ksft_print_header (); + err =mte_default_setup ();if (err)return err;
tools/testing/selftests/arm64/mte/check_mmap_options.c +2 -0
@@ -188,6 +188,8 @@ int main(int argc, char *argv[])int err;int item =ARRAY_SIZE (sizes); +ksft_print_header (); + err =mte_default_setup ();if (err)return err;
tools/testing/selftests/arm64/mte/check_tags_inclusion.c +2 -0
@@ -175,6 +175,8 @@ int main(int argc, char *argv[]) {int err; +ksft_print_header (); + err =mte_default_setup ();if (err)return err;
tools/testing/selftests/arm64/mte/check_user_mem.c +2 -0
@@ -201,6 +201,8 @@ int main(int argc, char *argv[])int tag_offsets[] = {page_sz,MT_GRANULE_SIZE };char test_name[TEST_NAME_MAX ]; +ksft_print_header (); + page_sz =getpagesize ();if (!page_sz) {ksft_print_msg ("ERR: Unable to get page size\n" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1326/1376 selftests/arm64: Treat KSM merge_across_nodes as optional
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muhammad Usama Anjum <[email protected]>
[ Upstream commit 1a0dba077f34a2f8faa98308d30d4b546d073145 ]
The MTE KSM test requires write access to KSM sysfs but does not check that it is running as root. It also unconditionally saves, enables and restores the merge_across_nodes attribute. The kernel only creates this attribute when CONFIG_NUMA=y, so a non-NUMA kernel prints the following message three times even though every KSM subtest passes:
# ERR: missing /sys/kernel/mm/ksm/merge_across_nodes
Skip the test when it is not running as root. Check that the optional attribute is readable and writable, treating ENOENT as its expected absence on non-NUMA kernels and skipping the test for other access failures. Only save, enable and restore the attribute when it is available.
Check MTE availability before the privilege and sysfs checks so systems without MTE retain the existing feature-unavailable skip result.
This preserves the existing behavior on NUMA kernels without requiring NUMA or reducing KSM coverage on single-node systems.
--- .../selftests/arm64/mte/check_ksm_options.c | 29 +++++++++++++++++-- 1 file changed, 26 insertions(+), 3 deletions(-)
tools/testing/selftests/arm64/mte/check_ksm_options.c +26 -3
@@ -6,6 +6,7 @@#include <errno.h> #include <fcntl.h> #include <signal.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h>
@@ -22,6 +23,20 @@static size_t page_sz;static unsigned long ksm_sysfs[5 ]; +static bool has_merge_across_nodes; + +static bool merge_across_nodes_available (void ) +{ +const char *path =PATH_KSM "merge_across_nodes" ; + +if (!access (path,R_OK |W_OK )) +return true; +if (errno ==ENOENT ) +return false; + +ksft_exit_skip ("Unable to read and write %s: %s\n" , path, +strerror (errno)); +}static unsigned long read_sysfs (char *str) {
@@ -56,8 +71,10 @@ static void write_sysfs(char *str, unsigned long val)static void mte_ksm_setup (void ) { - ksm_sysfs[0 ] =read_sysfs (PATH_KSM "merge_across_nodes" ); -write_sysfs (PATH_KSM "merge_across_nodes" ,1 ); +if (has_merge_across_nodes) { + ksm_sysfs[0 ] =read_sysfs (PATH_KSM "merge_across_nodes" ); +write_sysfs (PATH_KSM "merge_across_nodes" ,1 ); + } ksm_sysfs[1 ] =read_sysfs (PATH_KSM "sleep_millisecs" );write_sysfs (PATH_KSM "sleep_millisecs" ,0 ); ksm_sysfs[2 ] =read_sysfs (PATH_KSM "run" );
@@ -70,7 +87,8 @@ static void mte_ksm_setup(void)static void mte_ksm_restore (void ) { -write_sysfs (PATH_KSM "merge_across_nodes" , ksm_sysfs[0 ]); +if (has_merge_across_nodes) +write_sysfs (PATH_KSM "merge_across_nodes" , ksm_sysfs[0 ]);write_sysfs (PATH_KSM "sleep_millisecs" , ksm_sysfs[1 ]);write_sysfs (PATH_KSM "run" , ksm_sysfs[2 ]);write_sysfs (PATH_KSM "max_page_sharing" , ksm_sysfs[3 ]);
@@ -137,6 +155,11 @@ int main(int argc, char *argv[]) err =mte_default_setup ();if (err)return err; + +if (geteuid () !=0 ) +ksft_exit_skip ("Please run the test as root\n" ); + + has_merge_across_nodes =merge_across_nodes_available (); page_sz =getpagesize ();if (!page_sz) {ksft_print_msg ("ERR: Unable to get page size\n" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1327/1376 net: stmmac: selftests: Check multiple MMC counters
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maxime Chevallier <[email protected]>
[ Upstream commit d29b399150b07796dfa81d8778d4804c08c2a41d ]
The MMC counters report MAC statistics. Multiple counters can be enabled when the IP is integrated, however there's no way to know exactly which ones. Un-implemented counters seem to report 0.
It was found that on StarFive JH7110 and Amlogic SM1, the counter that's used by the selftest (mmc_tx_framecount_g) isn't implemented, triggering an MMC selftest failure.
Both the above SoCs seem to implement mmc_rx_framecount_gb, let's use this counter as well for MMC counter validation.
Note that this doesn't guarantee that we won't encounter the same issue again if another IP implements yet another set of counters that don't include that new one.
If the game of whack-a-mole with implemented counters becomes too hard to maintain, we may simply consider removing the MMC selftest entirely.
--- .../net/ethernet/stmicro/stmmac/stmmac_selftests.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +10 -4
@@ -415,11 +415,17 @@ static int stmmac_test_mmc(struct stmmac_priv *priv)stmmac_mmc_read (priv, priv->mmcaddr, &final);/* -* The number of MMC counters available depends on HW configuration -* so we just use this one to validate the feature. I hope there is -* not a version without this counter. +* The number of MMC counters available depends on HW configuration, +* and there doesn't seem to be a way to enumerate the implemented +* counters. +* +* Let's check a hand-picked set of counters, knowing that : +* - Starfive JH7110 doesn't implement mmc_tx_framecount_g +* - Amlogic SM1 doesn't implement any mmc_tx_* +* */ -if (final.mmc_tx_framecount_g <= initial.mmc_tx_framecount_g) +if (final.mmc_tx_framecount_g <= initial.mmc_tx_framecount_g && + final.mmc_rx_framecount_gb <= initial.mmc_rx_framecount_gb)return -EINVAL ;return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1328/1376 net: stmmac: dwmac1000: Account for the primary MAC address for UC filtering
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maxime Chevallier <[email protected]>
[ Upstream commit 9698b6da3714fd2ef47846cb63098d2b2d252e25 ]
The same filter slots are used to store the main MAC address as well as the address for the unicast filter. Let's account for that when deciding whether or not to use promisc when programming the UC list in hardware.
--- drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c +1 -1
@@ -185,7 +185,7 @@ static void dwmac1000_set_filter(struct mac_device_info *hw,dwmac1000_set_mchash (ioaddr, mc_filter, mcbitslog2);/* Handle multiple unicast addresses (perfect filtering) */ -if (netdev_uc_count (dev) > perfect_addr_number) +if (netdev_uc_count (dev) +1 > perfect_addr_number)/* Switch to promiscuous mode if more than unicast * addresses are requested than supported by hardware. */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1329/1376 net: stmmac: dwmac4: Account for the primary MAC address for UC filtering
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maxime Chevallier <[email protected]>
[ Upstream commit 82187f42c014d22520b9c3c4e2cfb519223fb29b ]
The same filter slots are used to store the main MAC address as well as the address for the unicast filter. Let's account for that when deciding whether or not to use promisc when programming the UC list in hardware.
--- drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c +1 -1
@@ -680,7 +680,7 @@ static void dwmac4_set_filter(struct mac_device_info *hw, value |=GMAC_PACKET_FILTER_HPF ;/* Handle multiple unicast addresses */ -if (netdev_uc_count (dev) > hw->unicast_filter_entries) { +if (netdev_uc_count (dev) +1 > hw->unicast_filter_entries) {/* Switch to promiscuous mode if more than 128 addrs * are required */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1330/1376 net: stmmac: dwxgmac: Account for the primary MAC address for UC filtering
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maxime Chevallier <[email protected]>
[ Upstream commit 2739d6f9a2b8729b0d85cbe0dc93e1d68670b6f2 ]
The same filter slots are used to store the main MAC address as well as the address for the unicast filter. Let's account for that when deciding whether or not to use promisc when programming the UC list in hardware.
--- drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +1 -1
@@ -540,7 +540,7 @@ static void dwxgmac2_set_filter(struct mac_device_info *hw,dwxgmac2_set_mchash (ioaddr, mc_filter, mcbitslog2);/* Handle multiple unicast addresses */ -if (netdev_uc_count (dev) > hw->unicast_filter_entries) { +if (netdev_uc_count (dev) +1 > hw->unicast_filter_entries) { value |=XGMAC_FILTER_PR ; }else {struct netdev_hw_addr *ha;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1331/1376 net: stmmac: selftests: Account for the UC filter list for filtering tests
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maxime Chevallier <[email protected]>
[ Upstream commit cd8c3b2752c684141eab2282e294cae2971a9759 ]
On dwmac, one of the Unicast filter entries is used to store the local HW addr. This means that we have to use promisc mode for any kind of unicast filtering if we only have one slot in our unicast filter.
The number of slots available depends on how the IP is integrated, and we can't autodiscover how many of these slots we have available, so the DT property snps,perfect-filter-entries can be used to specify how many are available.
Most IP variants default to 1 if this isn't specified, which is the case for the amlogic variants (in this case, S905X3).
The stmmac selftests for UC filtering look if we have enough slots in the filter to store the dev->uc list, but doesn't account for the device's own MAC address. The dev->uc list's size we get with netdev_uc_count() also doesn't account for the HW addr.
As the selftest only requires one available slot, in the case of single-slot platforms, that means we erroneously consider we have enough room for the test, when we actually don't, and the filtering test fails.
--- .../stmicro/stmmac/stmmac_selftests.c | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c +18 -3
@@ -499,6 +499,21 @@ static int stmmac_filter_check(struct stmmac_priv *priv)return -EOPNOTSUPP ; } +static int stmmac_uc_filter_check (struct stmmac_priv *priv) +{ +/* For tests involving the UC filter, we need at least one empty +* slot in the UC filter. The UC filters contains netdev_uc_count() + 1 +* entries: The dev->uc list + one entry for the HW address. +* +* Having an empty slot therefore means netdev_uc_count() + 2 entries +* can fit in the filter +*/ +if (netdev_uc_count (priv->dev) +2 > priv->hw->unicast_filter_entries) +return -EOPNOTSUPP ; + +return 0 ; +} +static bool stmmac_hash_check (struct stmmac_priv *priv,unsigned char *addr) {int mc_offset =32 - priv->hw->mcast_bits_log2;
@@ -590,7 +605,7 @@ static int stmmac_test_pfilt(struct stmmac_priv *priv)if (stmmac_filter_check (priv))return -EOPNOTSUPP ; -if (netdev_uc_count (priv->dev) >= priv->hw->unicast_filter_entries) +if (stmmac_uc_filter_check (priv))return -EOPNOTSUPP ;while (--tries) {
@@ -634,7 +649,7 @@ static int stmmac_test_mcfilt(struct stmmac_priv *priv)if (stmmac_filter_check (priv))return -EOPNOTSUPP ; -if (netdev_uc_count (priv->dev) >= priv->hw->unicast_filter_entries) +if (stmmac_uc_filter_check (priv))return -EOPNOTSUPP ;if (netdev_mc_count (priv->dev) >= priv->hw->multicast_filter_bins)return -EOPNOTSUPP ;
@@ -680,7 +695,7 @@ static int stmmac_test_ucfilt(struct stmmac_priv *priv)if (stmmac_filter_check (priv))return -EOPNOTSUPP ; -if (netdev_uc_count (priv->dev) >= priv->hw->unicast_filter_entries) +if (stmmac_uc_filter_check (priv))return -EOPNOTSUPP ;if (netdev_mc_count (priv->dev) >= priv->hw->multicast_filter_bins)return -EOPNOTSUPP ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1332/1376 net/sched: bound qdisc_pkt_len to prevent qdisc soft lockup
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit 8f735d64382dcf162f4276d6699d03ad2f859c0b ]
qdisc_get_stab() accepts a user-supplied size table, and __qdisc_calculate_pkt_len() amplifies qdisc_pkt_len() through the overhead, the size-table data (u16), and size_log (up to STAB_SIZE_LOG_MAX). A crafted stab can therefore set qdisc_pkt_len() to ~1 GiB for an ordinary skb. Per-flow deficit schedulers such as DRR and ETS replenish one quantum per loop iteration; with a tiny quantum (1) they spin billions of times under the qdisc lock, producing a soft lockup / RCU stall as illustrated by [email protected].
Cap the final qdisc_pkt_len() to QDISC_PKT_LEN_MAX so the size-table amplification cannot drive deficit schedulers into an unbounded loop. A legitimate size table (e.g. qfq's overhead 999999999, which is handled by dropping) is still accepted.
Introduce cap QDISC_PKT_LEN_MAX (1 << 20) = 1 MiB which is well above any legitimate single-skb wire length: the largest current skb->len is GSO_MAX_SIZE (524280), and an ATM-style size table (53/48 cell tax) amplifies that to ~578 KB, both comfortably below 1 MiB. At the same time, 1 MiB bounds the deficit refill loop to ~1M iterations per packet with quantum=1, which completes in a few milliseconds well under the demonstrated softlockup threshold (~10^9 iterations).
Conditions to recreate the bug:
- CONFIG_NET_SCHED=y, CONFIG_NET_SCH_DRR=y (or CONFIG_NET_SCH_ETS=y).
- Attach a DRR (or ETS) root qdisc with a crafted TCA_STAB that amplifies qdisc_pkt_len to ~1 GiB (e.g. size_log=15, data=[32768]).
- Add a class with a tiny quantum of 1 and send one small packet; the deficit loop spins billions of times under the qdisc lock and trips the softlockup detector (panic with kernel.softlockup_panic=1).
- Reachable as root or from an unprivileged user in a fresh user+net namespace (unshare -Urn) with namespace-local CAP_NET_ADMIN.
--- include/net/pkt_sched.h | 1 + net/sched/sch_api.c | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-)
include/net/pkt_sched.h +1 -0
@@ -12,6 +12,7 @@#define DEFAULT_TX_QUEUE_LEN 1000#define STAB_SIZE_LOG_MAX 30 +#define QDISC_PKT_LEN_MAX (1 << 20)/* 1 MiB */ struct qdisc_walker {int stop;
net/sched/sch_api.c +5 -2
@@ -608,8 +608,11 @@ void __qdisc_calculate_pkt_len(struct sk_buff *skb, pkt_len <<= stab->szopts.size_log; out: -if (unlikely (pkt_len <1 )) - pkt_len =1 ; +/* A size table can inflate qdisc_pkt_len() beyond any real packet +* (via overhead, the data table, or size_log); cap it so deficit +* schedulers such as DRR/ETS terminate their refill loops. +*/ + pkt_len =clamp_t (int, pkt_len,1 ,QDISC_PKT_LEN_MAX );qdisc_skb_cb (skb)->pkt_len = pkt_len; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1333/1376 slip: remove slip_hangup() to fix use-after-free in slip_receive_buf()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 23c53269f2baaedf2d92784290cb9ef6db2a3bce ]
Jaeyoung Chung and Eulgyu Kim reported a slab-use-after-free read in slip_receive_buf() when racing against tty hangup.
tty_ldisc_hangup() calls ld->ops->hangup() while holding only a read lock on tty->ldisc_sem (via tty_ldisc_ref()). Because slip_hangup() simply called slip_close(), it ran concurrently with reader functions such as slip_receive_buf().
slip_close() unregisters and frees the net device and its private struct slip, causing concurrent reader threads in slip_receive_buf() to dereference freed memory.
Line discipline close() is already guaranteed to be called under the write lock of tty->ldisc_sem during hangup processing (in tty_ldisc_reinit() or tty_ldisc_kill()).
Remove slip_hangup() so teardown is serialized cleanly by slip_close().
--- drivers/net/slip/slip.c | 8 -------- 1 file changed, 8 deletions(-)
drivers/net/slip/slip.c +0 -8
@@ -886,8 +886,6 @@ static int slip_open(struct tty_struct *tty)* Close down a SLIP channel. * This means flushing out any pending queues, and then returning. This * call is serialized against other ldisc functions. -* -* We also use this method fo a hangup event */ static void slip_close (struct tty_struct *tty)
@@ -915,11 +913,6 @@ static void slip_close(struct tty_struct *tty)unregister_netdev (sl->dev);/* sl_uninit() has dropped the slip_devs[] entry by now */ } - -static void slip_hangup (struct tty_struct *tty) -{ -slip_close (tty); -}/************************************************************************ * STANDARD SLIP ENCAPSULATION * ************************************************************************/
@@ -1280,7 +1273,6 @@ static struct tty_ldisc_ops sl_ldisc = { .name = "slip", .open = slip_open, .close = slip_close, - .hangup = slip_hangup, .ioctl = slip_ioctl, .receive_buf = slip_receive_buf, .write_wakeup = slip_write_wakeup,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1334/1376 net: fec: only stop PTP if it was initialized
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: bui duc phuc <[email protected]>
[ Upstream commit dd890ae29299636fb037276fc1b5238698d08b03 ]
fec_ptp_init() is only called when fep->bufdesc_ex is available. However, fec_probe() unconditionally calls fec_ptp_stop() on the failed_init path, and fec_drv_remove() unconditionally calls fec_ptp_stop() during device removal.
Check fep->bufdesc_ex before calling fec_ptp_stop() in both paths to avoid stopping PTP when it was not initialized.
--- drivers/net/ethernet/freescale/fec_main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/ethernet/freescale/fec_main.c +4 -2
@@ -4601,7 +4601,8 @@ fec_probe(struct platform_device *pdev) failed_irq:fec_enet_deinit (ndev); failed_init: -fec_ptp_stop (pdev); +if (fep->bufdesc_ex) +fec_ptp_stop (pdev); failed_reset:pm_runtime_put_noidle (&pdev->dev);pm_runtime_disable (&pdev->dev);
@@ -4643,7 +4644,8 @@ fec_drv_remove(struct platform_device *pdev) ERR_PTR(ret));cancel_work_sync (&fep->tx_timeout_work); -fec_ptp_stop (pdev); +if (fep->bufdesc_ex) +fec_ptp_stop (pdev);unregister_netdev (ndev);fec_enet_mii_remove (fep);if (fep->reg_phy)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1335/1376 usb: atm: usbatm: fix invalid ci_range initialization
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Deepanshu Kartikey <[email protected]>
[ Upstream commit a60fd8c6dbaa76da4163cf225ed2b9e982540f39 ]
syzbot reported a shift-out-of-bounds in __vcc_connect():
UBSAN: shift-out-of-bounds in net/atm/common.c:382:32 shift exponent -1 is negative CPU: 0 UID: 0 PID: 5987 Comm: syz.0.18 Not tainted syzkaller #0 PREEMPT(full) Hardware name: Google Compute Engine/Google Compute Engine, BIOS Google 08/05/2026 Call Trace: <TASK> dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120 ubsan_epilogue+0xa/0x30 lib/ubsan.c:233 __ubsan_handle_shift_out_of_bounds+0x36d/0x400 lib/ubsan.c:494 __vcc_connect+0x14b4/0x19c0 net/atm/common.c:382 vcc_connect+0x328/0x8f0 net/atm/common.c:498 pvc_bind+0x272/0x380 net/atm/pvc.c:52 __sys_bind+0x2e3/0x410 net/socket.c:1976 __x64_sys_bind+0x7a/0x90 net/socket.c:1979 ...
ATM device ci_range fields (vpi_bits and vci_bits) represent the number of bits supported for VPI and VCI addressing on the device. net/atm/common.c directly uses these fields as bit shift counts:
vpi >> dev->ci_range.vpi_bits
vci >> dev->ci_range.vci_bits
1 << vcc->dev->ci_range.vpi_bits
1 << vcc->dev->ci_range.vci_bits
usbatm_atm_init() sets ci_range.vpi_bits and ci_range.vci_bits to ATM_CI_MAX (-1), which is defined in <uapi/linux/atmdev.h> as a sentinel value for userspace ATM_SETCIRANGE requests, not a valid bit count. Shifting by -1 is undefined behavior and triggers UBSAN warnings.
ATM UNI cell headers allow up to 8 bits for VPI (0..255) and 16 bits for VCI (0..65535). Initialize vpi_bits to 8 and vci_bits to 16, as done by solos-pci.
--- drivers/usb/atm/usbatm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/usb/atm/usbatm.c +2 -2
@@ -917,8 +917,8 @@ static int usbatm_atm_init(struct usbatm_data *instance) instance->atm_dev = atm_dev; - atm_dev->ci_range.vpi_bits =ATM_CI_MAX ; - atm_dev->ci_range.vci_bits =ATM_CI_MAX ; + atm_dev->ci_range.vpi_bits =8 ; + atm_dev->ci_range.vci_bits =16 ; atm_dev->signal =ATM_PHY_SIG_UNKNOWN ;/* temp init ATM device, set to 128kbit */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1336/1376 tcp: fix corruption of urgent data on multi-segment retransmit
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jiayuan Chen <[email protected]>
[ Upstream commit ce2b807f42ed5e55567b8864ab72963f90779270 ]
On the normal xmit path, while in urgent mode we refuse to build a multi-segment TSO packet, so every segment gets its own urg_ptr:
/* tcp_write_xmit() */ limit = mss_now; if (tso_segs > 1 && !tcp_urg_mode(tp)) limit = tcp_mss_split_point(...);
The retransmit path has no such guard. __tcp_retransmit_skb() builds a segs > 1 skb and hands it to the GSO layer, which only advances th->seq per segment and copies urg_ptr verbatim:
/* __tcp_retransmit_skb() */ len = cur_mss * segs; /* segs > 1, no urg_mode check */ ... /* tcp_gso_segment(): bumps seq only, urg_ptr is copied */
urg_ptr is an offset from the segment's own seq, so a copied value points at a different place on each segment. The receiver rebuilds the absolute urgent seq as seg.seq + urg_ptr, so it walks a moving urgent point instead of the one OOB byte:
seg1 seq 1 urg_ptr 5001 -> urgent @ 5001 (ok) seg2 seq 1001 urg_ptr 5001 -> urgent @ 6001 (wrong, +MSS) seg3 seq 2001 urg_ptr 5001 -> urgent @ 7001 (wrong, +2*MSS)
The real OOB byte is never pointed at, so the receiver stops splicing it out and delivers it as normal in-band data, corrupting the stream.
Guard the retransmit length like the xmit path: keep segs = 1 while in urgent mode.
--- net/ipv4/tcp_output.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/tcp_output.c +1 -1
@@ -3381,7 +3381,7 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs) avail_wnd = cur_mss; } - len = cur_mss * segs; + len = cur_mss * (tcp_urg_mode (tp) ?1 : segs);if (len > avail_wnd) { len =rounddown (avail_wnd, cur_mss);if (!len)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1337/1376 net/sched: sch_htb: limit htb_classify inner-class filter hops
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit 729c4896ab829169f95915d65edd530325910b37 ]
htb_classify() follows each filter-selected inner class by switching to cl->filter_list, but never bounds the number of hops. A filter on an inner class can point back to itself or to another inner class that points back, creating an infinite loop in the packet classification path with the qdisc lock held and BH disabled — a soft lockup / panic from a single packet.
Bound the traversal with a hop counter and drop the packet with a rate-limited warning once the bound is exceeded. The counter is incremented at the point the inner filter chain is picked up, after the TC_ACT_* switch has consumed the classifier verdict, so a terminal TC_ACT_QUEUED/STOLEN/TRAP on the last permitted chain still sets *qerr to __NET_XMIT_STOLEN and the packet is not charged as a drop by this qdisc or its parent.
The bound is TC_HTB_MAXDEPTH, taken from HTB's own parameters rather than from the qdisc hierarchy depth limit. Class levels run from 0 to TC_HTB_MAXDEPTH - 1, so a traversal that strictly descends in level can take at most TC_HTB_MAXDEPTH hops. That descent is what a sane configuration does, but it is assumed here rather than enforced:htb_find() resolves a classid against every class in the qdisc, so a filter may equally select a sibling or an ancestor. The normal root -> inner -> leaf path takes a single hop, so the bound does not affect legitimate classification.
htb_classify() can now return NULL irrespective of CONFIG_NET_CLS_ACT, whereas previously every NULL return sat inside that ifdef. The NULL handler in htb_enqueue() therefore cannot stay conditional either, so drop the ifdef around it. This matches hfsc_enqueue(), which has always handled a NULL class unconditionally. Without it, a kernel built without actions would dereference a NULL class instead of dropping.
Conditions to recreate the bug:
- CONFIG_NET_SCHED, CONFIG_NET_SCH_HTB, CONFIG_NET_CLS_U32, CONFIG_LOCKUP_DETECTOR.
- Create an HTB qdisc on a device (e.g. lo), add an inner class 1:1 with a leaf child 1:10, install a root u32 filter selecting 1:1, and an inner-class u32 filter on 1:1 also selecting 1:1.
- Send one packet (ping). On the unfixed kernel the classify loop spins with the qdisc lock held; with softlockup_panic=1 it panics.
- Reachable from unprivileged user via unshare -Urn (CAP_NET_ADMIN).
--- net/sched/sch_htb.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
net/sched/sch_htb.c +5 -2
@@ -223,6 +223,7 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,struct htb_class *cl;struct tcf_result res;struct tcf_proto *tcf; +unsigned int hops =0 ;int result;/* allow to select class by setting skb->priority to valid classid;
@@ -265,6 +266,10 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch,if (!cl->level)return cl;/* we hit leaf; return it */ +if (++hops >TC_HTB_MAXDEPTH ) { +pr_warn_ratelimited ("htb: classify loop detected, dropping packet\n" ); +return NULL ; + }/* we have got inner class; apply inner filter chain */ tcf =rcu_dereference_bh (cl->filter_list); }
@@ -632,13 +637,11 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch, }else {return qdisc_drop (skb, sch, to_free); } -#ifdef CONFIG_NET_CLS_ACT }else if (!cl) {if (ret & __NET_XMIT_BYPASS)qdisc_qstats_drop (sch);__qdisc_drop (skb, to_free);return ret; -#endif }else if ((ret =qdisc_enqueue (skb, cl->leaf.q, to_free)) !=NET_XMIT_SUCCESS ) {if (net_xmit_drop_count (ret)) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1338/1376 platform/x86: lg-laptop: Check ACPI_COMPANION() against NULL
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit 7e169326c2263ebc4878baae536c956fa3118eff ]
Every platform driver can be forced to match a device that doesn't match its list of device IDs because of device_match_driver_override(), so platform drivers that rely on the existence of a device's ACPI companion object need to verify its presence.
Accordingly, add a requisite ACPI_COMPANION() check against NULL to the platform/x86 lg-laptop driver.
--- drivers/platform/x86/lg-laptop.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/platform/x86/lg-laptop.c +7 -2
@@ -755,12 +755,11 @@ static void lg_laptop_remove_address_space_handler(void *data)static int acpi_probe (struct platform_device *pdev) { -struct acpi_device *device =ACPI_COMPANION (&pdev->dev);struct platform_device_info pdev_info = { - .fwnode =acpi_fwnode_handle (device), .name =PLATFORM_NAME , .id =PLATFORM_DEVID_NONE , }; +struct acpi_device *device;acpi_status status;int ret;const char *product;
@@ -769,6 +768,12 @@ static int acpi_probe(struct platform_device *pdev)if (pf_device)return 0 ; + device =ACPI_COMPANION (&pdev->dev); +if (!device) +return -ENODEV ; + + pdev_info.fwnode =acpi_fwnode_handle (device), + status =acpi_install_address_space_handler (device->handle,LG_ADDRESS_SPACE_ID , &lg_laptop_address_space_handler,NULL , &pdev->dev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1339/1376 cpufreq/amd-pstate: Fix prefcore rankings
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mario Limonciello <[email protected]>
[ Upstream commit fd604ae6c261c5a56bb977ae99f875bbd7264a3f ]
commit 50a062a76200 ("cpufreq/amd-pstate: Store the boost numerator as highest perf again") updated the value stored for highest perf to no longer store the highest perf value but instead the boost numerator.
This is a fixed value for systems with preferred cores and not appropriate for use ITMT rankings. Update the value used for ITMT rankings to be the preferred core ranking.
--- drivers/cpufreq/amd-pstate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/cpufreq/amd-pstate.c +1 -1
@@ -780,7 +780,7 @@ static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata)* sched_set_itmt_support(true) has been called and it is valid to * update them at any time after it has been called. */ -sched_set_itmt_core_prio ((int )READ_ONCE (cpudata->highest_perf), cpudata->cpu); +sched_set_itmt_core_prio ((int )READ_ONCE (cpudata->prefcore_ranking), cpudata->cpu);schedule_work (&sched_prefcore_work); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1340/1376 pinctrl: mediatek: eint: Drop base from mtk_eint_chip_write_mask()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen-Yu Tsai <[email protected]>
[ Upstream commit 3ca99eed042620d12315e9272ed3ef260ca29877 ]
When support for multiple EINT base addresses was added in commit 3ef9f710efcb ("pinctrl: mediatek: Add EINT support for multiple addresses"), mtk_eint_chip_write_mask() was changed to write interrupt masks for all base addresses in one call. However the "base" parameter was left around and now causes sparse warnings:
mtk-eint.c:428:44: warning: incorrect type in argument 2 (different address spaces)
mtk-eint.c:428:44: expected void [noderef] __iomem *base
mtk-eint.c:428:44: got void [noderef] __iomem **base
mtk-eint.c:436:44: warning: incorrect type in argument 2 (different address spaces)
mtk-eint.c:436:44: expected void [noderef] __iomem *base
mtk-eint.c:436:44: got void [noderef] __iomem **baseSince the "base" parameter is no longer needed, just drop it.
--- drivers/pinctrl/mediatek/mtk-eint.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/pinctrl/mediatek/mtk-eint.c +3 -3
@@ -243,7 +243,7 @@ static int mtk_eint_irq_set_wake(struct irq_data *d, unsigned int on) }static void mtk_eint_chip_write_mask (const struct mtk_eint *eint, -void __iomem *base,unsigned int **buf) +unsigned int **buf) {int inst, port, port_num;void __iomem *reg;
@@ -422,7 +422,7 @@ static void mtk_eint_irq_handler(struct irq_desc *desc)int mtk_eint_do_suspend (struct mtk_eint *eint) { -mtk_eint_chip_write_mask (eint, eint->base, eint->wake_mask); +mtk_eint_chip_write_mask (eint, eint->wake_mask);return 0 ; }
@@ -430,7 +430,7 @@ EXPORT_SYMBOL_GPL(mtk_eint_do_suspend);int mtk_eint_do_resume (struct mtk_eint *eint) { -mtk_eint_chip_write_mask (eint, eint->base, eint->cur_mask); +mtk_eint_chip_write_mask (eint, eint->cur_mask);return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1341/1376 pinctrl: mediatek: Fix new design debounce issue
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hao Chang <[email protected]>
[ Upstream commit 34024cf69c51b11c2b608f5d578626b9b1c484f5 ]
Calculate the true offset of eint according to index.
--- drivers/pinctrl/mediatek/mtk-eint.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/pinctrl/mediatek/mtk-eint.c +1 -1
@@ -450,7 +450,7 @@ int mtk_eint_set_debounce(struct mtk_eint *eint, unsigned long eint_num,return -EOPNOTSUPP ; virq =irq_find_mapping (eint->domain, eint_num); - eint_offset = (eint_num %4 ) *8 ; + eint_offset = (idx %4 ) *8 ; d =irq_get_irq_data (virq); set_offset = (idx /4 ) *4 + eint->regs->dbnc_set;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1342/1376 pinctrl: mediatek: common-v1: Fix EINT breakage on older controllers
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen-Yu Tsai <[email protected]>
[ Upstream commit fe412e3a6c97cfe49ecf4564a278122f7d78e3f0 ]
When EINT support for multiple addresses was introduced, the driver library for the older generations (pinctrl-mtk-common) was not fixed together. This resulted in invalid pointer accesses.
Fix up the filled in |struct mtk_eint| in pinctrl-mtk-common to match what is now expected by the mtk-eint library.
--- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-)
drivers/pinctrl/mediatek/pinctrl-mtk-common.c +7 -1
@@ -1015,7 +1015,13 @@ static int mtk_eint_init(struct mtk_pinctrl *pctl, struct platform_device *pdev)if (!pctl->eint)return -ENOMEM ; - pctl->eint->base =devm_platform_ioremap_resource (pdev,0 ); + pctl->eint->nbase =1 ; +/* mtk-eint expects an array */ + pctl->eint->base =devm_kzalloc (pctl->dev,sizeof (pctl->eint->base),GFP_KERNEL ); +if (IS_ERR (pctl->eint->base)) +return -ENOMEM ; + + pctl->eint->base[0 ] =devm_platform_ioremap_resource (pdev,0 );if (IS_ERR (pctl->eint->base))return PTR_ERR (pctl->eint->base);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1343/1376 md: keep recovery_cp in mdp_superblock_s
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiao Ni <[email protected]>
[ Upstream commit c27973211ffcdf0a092eec265d5993e64b89adaf ]
commit 907a99c314a5 ("md: rename recovery_cp to resync_offset") replaces recovery_cp with resync_offset in mdp_superblock_s which is in md_p.h. md_p.h is used in userspace too. So mdadm building fails because of this. This patch revert this change.
--- drivers/md/md.c | 6 +++--- include/uapi/linux/raid/md_p.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-)
drivers/md/md.c +3 -3
@@ -1372,7 +1372,7 @@ static int super_90_validate(struct mddev *mddev, struct md_rdev *freshest, struelse {if (sb->events_hi == sb->cp_events_hi && sb->events_lo == sb->cp_events_lo) { - mddev->resync_offset = sb->resync_offset; + mddev->resync_offset = sb->recovery_cp; }else mddev->resync_offset =0 ; }
@@ -1500,13 +1500,13 @@ static void super_90_sync(struct mddev *mddev, struct md_rdev *rdev) mddev->minor_version = sb->minor_version;if (mddev->in_sync) { - sb->resync_offset = mddev->resync_offset; + sb->recovery_cp = mddev->resync_offset; sb->cp_events_hi = (mddev->events>>32 ); sb->cp_events_lo = (u32 )mddev->events;if (mddev->resync_offset == MaxSector) sb->state = (1 <<MD_SB_CLEAN ); }else - sb->resync_offset =0 ; + sb->recovery_cp =0 ; sb->layout = mddev->layout; sb->chunk_size = mddev->chunk_sectors <<9 ;
include/uapi/linux/raid/md_p.h +1 -1
@@ -173,7 +173,7 @@ typedef struct mdp_superblock_s {#else #error unspecified endianness#endif -__u32 resync_offset;/* 11 resync checkpoint sector count */ +__u32 recovery_cp;/* 11 resync checkpoint sector count */ /* There are only valid for minor_version > 90 */ __u64 reshape_position;/* 12,13 next address in array-space for reshape */ __u32 new_level;/* 14 new level we are reshaping to */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1344/1376 slub: Dont call lockdep_unregister_key() for immature kmem_cache.
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit f7dfa0f31b13ee5f2ba598cdfcab9a831ed8a6b8 ]
syzbot reported the lockdep splat below in __kmem_cache_release(). [0]
The problem is that __kmem_cache_release() could be called from do_kmem_cache_create() before init_kmem_cache_cpus() registers the lockdep key.
Let's perform lockdep_unregister_key() only when init_kmem_cache_cpus() has been done, which we can determine by checking s->cpu_slab
[0]:
WARNING: CPU: 1 PID: 6128 at kernel/locking/lockdep.c:6606 lockdep_unregister_key+0x2ca/0x310 kernel/locking/lockdep.c:6606
Modules linked in:
CPU: 1 UID: 0 PID: 6128 Comm: syz.4.21 Not tainted syzkaller #0 PREEMPT_{RT,(full)}
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 08/18/2025
RIP: 0010:lockdep_unregister_key+0x2ca/0x310 kernel/locking/lockdep.c:6606
Code: 50 e4 0f 48 3b 44 24 10 0f 84 26 fe ff ff e8 bd cd 17 09 e8 e8 ce 17 09 41 f7 c7 00 02 00 00 74 bd fb 40 84 ed 75 bc eb cd 90 <0f> 0b 90 e9 19 ff ff ff 90 0f 0b 90 e9 2a ff ff ff 48 c7 c7 d0 ac
RSP: 0018:ffffc90003e870d0 EFLAGS: 00010002
RAX: eb1525397f5bdf00 RBX: ffff88803c121148 RCX: 1ffff920007d0dfc
RDX: 0000000000000000 RSI: ffffffff8acb1500 RDI: ffffffff8b1dd0e0
RBP: 00000000ffffffea R08: ffffffff8eb5aa37 R09: 1ffffffff1d6b546
R10: dffffc0000000000 R11: fffffbfff1d6b547 R12: 0000000000000000
R13: ffff88814d1b8900 R14: 0000000000000000 R15: 0000000000000203
FS: 00007f773f75e6c0(0000) GS:ffff88812712f000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007ffdaea3af52 CR3: 000000003a5ca000 CR4: 00000000003526f0
Call Trace:
<TASK>
__kmem_cache_release+0xe3/0x1e0 mm/slub.c:7696
do_kmem_cache_create+0x74e/0x790 mm/slub.c:8575
create_cache mm/slab_common.c:242 [inline]
__kmem_cache_create_args+0x1ce/0x330 mm/slab_common.c:340
nfsd_file_cache_init+0x1d6/0x530 fs/nfsd/filecache.c:816
nfsd_startup_generic fs/nfsd/nfssvc.c:282 [inline]
nfsd_startup_net fs/nfsd/nfssvc.c:377 [inline]
nfsd_svc+0x393/0x900 fs/nfsd/nfssvc.c:786
nfsd_nl_threads_set_doit+0x84a/0x960 fs/nfsd/nfsctl.c:1639
genl_family_rcv_msg_doit+0x212/0x300 net/netlink/genetlink.c:1115
genl_family_rcv_msg net/netlink/genetlink.c:1195 [inline]
genl_rcv_msg+0x60e/0x790 net/netlink/genetlink.c:1210
netlink_rcv_skb+0x208/0x470 net/netlink/af_netlink.c:2552
genl_rcv+0x28/0x40 net/netlink/genetlink.c:1219
netlink_unicast_kernel net/netlink/af_netlink.c:1320 [inline]
netlink_unicast+0x846/0xa10 net/netlink/af_netlink.c:1346
netlink_sendmsg+0x805/0xb30 net/netlink/af_netlink.c:1896
sock_sendmsg_nosec net/socket.c:727 [inline]
__sock_sendmsg+0x219/0x270 net/socket.c:742
____sys_sendmsg+0x508/0x820 net/socket.c:2630
___sys_sendmsg+0x21f/0x2a0 net/socket.c:2684
__sys_sendmsg net/socket.c:2716 [inline]
__do_sys_sendmsg net/socket.c:2721 [inline]
__se_sys_sendmsg net/socket.c:2719 [inline]
__x64_sys_sendmsg+0x1a1/0x260 net/socket.c:2719
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xfa/0x3b0 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f77400eeec9
Code: ff ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 40 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 a8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f773f75e038 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
RAX: ffffffffffffffda RBX: 00007f7740345fa0 RCX: 00007f77400eeec9
RDX: 0000000000008004 RSI: 0000200000000180 RDI: 0000000000000006
RBP: 00007f7740171f91 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f7740346038 R14: 00007f7740345fa0 R15: 00007ffce616f8d8
</TASK>--- mm/slub.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
mm/slub.c +2 -1
@@ -5322,7 +5322,8 @@ void __kmem_cache_release(struct kmem_cache *s)cache_random_seq_destroy (s);#ifndef CONFIG_SLUB_TINY #ifdef CONFIG_PREEMPT_RT -lockdep_unregister_key (&s->lock_key); +if (s->cpu_slab) +lockdep_unregister_key (&s->lock_key);#endif free_percpu (s->cpu_slab);#endif
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1345/1376 ACPI: processor: Update cpuidle driver check in __acpi_processor_start()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael J. Wysocki <[email protected]>
[ Upstream commit 0089ce1c056aee547115bdc25c223f8f88c08498 ]
Commit 7a8c994cbb2d ("ACPI: processor: idle: Optimize ACPI idle driver registration") moved the ACPI idle driver registration to acpi_processor_driver_init() and acpi_processor_power_init() does not register an idle driver any more.
Accordingly, the cpuidle driver check in __acpi_processor_start() needs to be updated to avoid calling acpi_processor_power_init() without a cpuidle driver, in which case the registration of the cpuidle device in that function would lead to a NULL pointer dereference in __cpuidle_register_device().
--- drivers/acpi/processor_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/acpi/processor_driver.c +1 -1
@@ -166,7 +166,7 @@ static int __acpi_processor_start(struct acpi_device *device)if (result && !IS_ENABLED (CONFIG_ACPI_CPU_FREQ_PSS ))dev_dbg (&device->dev,"CPPC data invalid or not present\n" ); -if (!cpuidle_get_driver () ||cpuidle_get_driver () == &acpi_idle_driver) +if (cpuidle_get_driver () == &acpi_idle_driver)acpi_processor_power_init (pr);acpi_pss_perf_init (pr);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1346/1376 fscrypt: fix left shift underflow when inode->i_blkbits > PAGE_SHIFT
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yongpeng Yang <[email protected]>
[ Upstream commit 1e39da974ce621ed874c6d3aaf65ad14848c9f0d ]
When simulating an nvme device on qemu with both logical_block_size and physical_block_size set to 8 KiB, an error trace appears during partition table reading at boot time. The issue is caused by inode->i_blkbits being larger than PAGE_SHIFT, which leads to a left shift of -1 and triggering a UBSAN warning.
[ 2.697306] ------------[ cut here ]------------ [ 2.697309] UBSAN: shift-out-of-bounds in fs/crypto/inline_crypt.c:336:37 [ 2.697311] shift exponent -1 is negative [ 2.697315] CPU: 3 UID: 0 PID: 274 Comm: (udev-worker) Not tainted 6.18.0-rc2+ #34 PREEMPT(voluntary) [ 2.697317] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.3-0-ga6ed6b701f0a-prebuilt.qemu.org 04/01/2014 [ 2.697320] Call Trace: [ 2.697324] <TASK> [ 2.697325] dump_stack_lvl+0x76/0xa0 [ 2.697340] dump_stack+0x10/0x20 [ 2.697342] __ubsan_handle_shift_out_of_bounds+0x1e3/0x390 [ 2.697351] bh_get_inode_and_lblk_num.cold+0x12/0x94 [ 2.697359] fscrypt_set_bio_crypt_ctx_bh+0x44/0x90 [ 2.697365] submit_bh_wbc+0xb6/0x190 [ 2.697370] block_read_full_folio+0x194/0x270 [ 2.697371] ? __pfx_blkdev_get_block+0x10/0x10 [ 2.697375] ? __pfx_blkdev_read_folio+0x10/0x10 [ 2.697377] blkdev_read_folio+0x18/0x30 [ 2.697379] filemap_read_folio+0x40/0xe0 [ 2.697382] filemap_get_pages+0x5ef/0x7a0 [ 2.697385] ? mmap_region+0x63/0xd0 [ 2.697389] filemap_read+0x11d/0x520 [ 2.697392] blkdev_read_iter+0x7c/0x180 [ 2.697393] vfs_read+0x261/0x390 [ 2.697397] ksys_read+0x71/0xf0 [ 2.697398] __x64_sys_read+0x19/0x30 [ 2.697399] x64_sys_call+0x1e88/0x26a0 [ 2.697405] do_syscall_64+0x80/0x670 [ 2.697410] ? __x64_sys_newfstat+0x15/0x20 [ 2.697414] ? x64_sys_call+0x204a/0x26a0 [ 2.697415] ? do_syscall_64+0xb8/0x670 [ 2.697417] ? irqentry_exit_to_user_mode+0x2e/0x2a0 [ 2.697420] ? irqentry_exit+0x43/0x50 [ 2.697421] ? exc_page_fault+0x90/0x1b0 [ 2.697422] entry_SYSCALL_64_after_hwframe+0x76/0x7e [ 2.697425] RIP: 0033:0x75054cba4a06 [ 2.697426] Code: 5d e8 41 8b 93 08 03 00 00 59 5e 48 83 f8 fc 75 19 83 e2 39 83 fa 08 75 11 e8 26 ff ff ff 66 0f 1f 44 00 00 48 8b 45 10 0f 05 <48> 8b 5d f8 c9 c3 0f 1f 40 00 f3 0f 1e fa 55 48 89 e5 48 83 ec 08 [ 2.697427] RSP: 002b:00007fff973723a0 EFLAGS: 00000202 ORIG_RAX: 0000000000000000 [ 2.697430] RAX: ffffffffffffffda RBX: 00005ea9a2c02760 RCX: 000075054cba4a06 [ 2.697432] RDX: 0000000000002000 RSI: 000075054c190000 RDI: 000000000000001b [ 2.697433] RBP: 00007fff973723c0 R08: 0000000000000000 R09: 0000000000000000 [ 2.697434] R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000000 [ 2.697434] R13: 00005ea9a2c027c0 R14: 00005ea9a2be5608 R15: 00005ea9a2be55f0 [ 2.697436] </TASK> [ 2.697436] ---[ end trace ]---
This situation can happen for block devices because when CONFIG_TRANSPARENT_HUGEPAGE is enabled, the maximum logical_block_size is 64 KiB. set_init_blocksize() then sets the block device inode->i_blkbits to 13, which is within this limit.
File I/O does not trigger this problem because for filesystems that do not support the FS_LBS feature, sb_set_blocksize() prevents sb->s_blocksize_bits from being larger than PAGE_SHIFT. During inode allocation, alloc_inode()->inode_init_always() assigns inode->i_blkbits from sb->s_blocksize_bits. Currently, only xfs_fs_type has the FS_LBS flag, and since xfs I/O paths do not reach submit_bh_wbc(), it does not hit the left-shift underflow issue.
--- fs/crypto/inline_crypt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
fs/crypto/inline_crypt.c +1 -2
@@ -275,8 +275,7 @@ static bool bh_get_inode_and_lblk_num(const struct buffer_head *bh, inode = mapping->host; *inode_ret = inode; - *lblk_num_ret = ((u64 )folio->index << (PAGE_SHIFT - inode->i_blkbits)) + - (bh_offset (bh) >> inode->i_blkbits); + *lblk_num_ret = (folio_pos (folio) +bh_offset (bh)) >> inode->i_blkbits;return true; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1347/1376 block: reject bs > ps block devices when THP is disabled
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pankaj Raghav <[email protected]>
[ Upstream commit 4cdf1bdd45ac78a088773722f009883af30ad318 ]
If THP is disabled and when a block device with logical block size > page size is present, the following null ptr deref panic happens during boot:
[ [13.2 mK AOSAN: null-ptr-deref in range [0x0000000000000000-0x0000000000K0 0 0[07]
[ 13.017749] RIP: 0010:create_empty_buffers+0x3b/0x380 <snip> [ 13.025448] Call Trace: [ 13.025692] <TASK> [ 13.025895] block_read_full_folio+0x610/0x780 [ 13.026379] ? __pfx_blkdev_get_block+0x10/0x10 [ 13.027008] ? __folio_batch_add_and_move+0x1fa/0x2b0 [ 13.027548] ? __pfx_blkdev_read_folio+0x10/0x10 [ 13.028080] filemap_read_folio+0x9b/0x200 [ 13.028526] ? __pfx_filemap_read_folio+0x10/0x10 [ 13.029030] ? __filemap_get_folio+0x43/0x620 [ 13.029497] do_read_cache_folio+0x155/0x3b0 [ 13.029962] ? __pfx_blkdev_read_folio+0x10/0x10 [ 13.030381] read_part_sector+0xb7/0x2a0 [ 13.030805] read_lba+0x174/0x2c0 <snip> [ 13.045348] nvme_scan_ns+0x684/0x850 [nvme_core] [ 13.045858] ? __pfx_nvme_scan_ns+0x10/0x10 [nvme_core] [ 13.046414] ? _raw_spin_unlock+0x15/0x40 [ 13.046843] ? __switch_to+0x523/0x10a0 [ 13.047253] ? kvm_clock_get_cycles+0x14/0x30 [ 13.047742] ? __pfx_nvme_scan_ns_async+0x10/0x10 [nvme_core] [ 13.048353] async_run_entry_fn+0x96/0x4f0 [ 13.048787] process_one_work+0x667/0x10a0 [ 13.049219] worker_thread+0x63c/0xf60
As large folio support depends on THP, only allow bs > ps block devices if THP is enabled.
--- include/linux/blkdev.h | 5 +++++ 1 file changed, 5 insertions(+)
include/linux/blkdev.h +5 -0
@@ -268,11 +268,16 @@ static inline dev_t disk_devt(struct gendisk *disk)return MKDEV (disk->major, disk->first_minor); } +#ifdef CONFIG_TRANSPARENT_HUGEPAGE /* * We should strive for 1 << (PAGE_SHIFT + MAX_PAGECACHE_ORDER) * however we constrain this to what we can validate and test. */ #define BLK_MAX_BLOCK_SIZE SZ_64K +#else +#define BLK_MAX_BLOCK_SIZE PAGE_SIZE +#endif +/* blk_validate_limits() validates bsize, so drivers don't usually need to */ static inline int blk_validate_block_size (unsigned long bsize)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1348/1376 scsi: sd: Fix error handling in sd_probe() after large pool creation failure
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yang Xiuwei <[email protected]>
[ Upstream commit e3cc6ea1a745e7f5d326f919a428b244fa119d8f ]
After device_add(&sdkp->disk_dev) succeeds, sd_large_pool_create() failure must unregister disk_dev and let scsi_disk_release() free sdkp. Going through out_free_index kfree()s an already registered device and leaks the sysfs entry.
--- drivers/scsi/sd.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/scsi/sd.c +3 -1
@@ -4063,7 +4063,9 @@ static int sd_probe(struct scsi_device *sdp)if (sdp->sector_size >PAGE_SIZE ) {if (sd_large_pool_create ()) { error = -ENOMEM ; - goto out_free_index; +device_unregister (&sdkp->disk_dev); +put_disk (gd); + goto out; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1349/1376 selftests/bpf: add verification for BPF_PROG_QUERY attr size boundaries
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuyang Huang <[email protected]>
[ Upstream commit 5add3a4ad1a3bc15404e8bd338813ed0a636f5c9 ]
Add a new selftest to verify that the BPF syscall (specifically BPF_PROG_QUERY) correctly handles different user-declared attribute sizes.
Specifically, verify that:
- For cgroup queries, a query with a size that covers 'prog_cnt' but is smaller than 'revision' (OLD_QUERY_SIZE) succeeds, but does not write to 'revision' (verifying backward compatibility).
- A query with full size (FULL_QUERY_SIZE) succeeds and writes both 'prog_cnt' and 'revision'.
--- .../selftests/bpf/prog_tests/bpf_attr_size.c | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/bpf_attr_size.c
tools/testing/selftests/bpf/prog_tests/bpf_attr_size.c new file +69 -0
@@ -0,0 +1,69 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2026 Google LLC */ +#include <linux/bpf.h> +#include <unistd.h> +#include <sys/syscall.h> +#include <test_progs.h> +#include <cgroup_helpers.h> +#include "cgroup_skb_direct_packet_access.skel.h" + +#define OLD_QUERY_SIZE offsetofend(union bpf_attr, query.prog_cnt) +#define FULL_QUERY_SIZE offsetofend(union bpf_attr, query.revision) + +static void test_query_size_boundaries (void ) +{ +struct cgroup_skb_direct_packet_access *skel; +struct bpf_link *link =NULL ; +union bpf_attr attr; +int cg_fd =-1 ; +int err; + + skel =cgroup_skb_direct_packet_access__open_and_load (); +if (!ASSERT_OK_PTR (skel,"skel_load" )) +return ; + + cg_fd =test__join_cgroup ("/attr_size_cg" ); +if (!ASSERT_GE (cg_fd,0 ,"join_cgroup" )) + goto cleanup; + + link =bpf_program__attach_cgroup (skel->progs.direct_packet_access, + cg_fd); +if (!ASSERT_OK_PTR (link,"cg_attach" )) + goto cleanup; + +memset (&attr,0 ,sizeof (attr)); + attr.query.target_fd = cg_fd; + attr.query.attach_type =BPF_CGROUP_INET_INGRESS ; + attr.query.revision =0xdeadbeefdeadbeefULL ; + + err =syscall (__NR_bpf,BPF_PROG_QUERY , &attr,OLD_QUERY_SIZE ); +if (ASSERT_OK (err,"query_old_size" )) { +ASSERT_EQ (attr.query.prog_cnt,1 ,"prog_cnt_written_old" ); +ASSERT_EQ (attr.query.revision,0xdeadbeefdeadbeefULL , +"revision_not_written_old" ); + } + +memset (&attr,0 ,sizeof (attr)); + attr.query.target_fd = cg_fd; + attr.query.attach_type =BPF_CGROUP_INET_INGRESS ; + + err =syscall (__NR_bpf,BPF_PROG_QUERY , &attr,FULL_QUERY_SIZE ); +if (!ASSERT_OK (err,"query_full_size" )) + goto cleanup; + +ASSERT_EQ (attr.query.prog_cnt,1 ,"prog_cnt_written" ); +ASSERT_GT (attr.query.revision,0 ,"revision_written" ); + +cleanup: +if (link) +bpf_link__destroy (link); +if (cg_fd >=0 ) +close (cg_fd); +cgroup_skb_direct_packet_access__destroy (skel); +} + +void test_bpf_attr_size (void ) +{ +if (test__start_subtest ("query_size_boundaries" )) +test_query_size_boundaries (); +}
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1350/1376 bpf: fix BPF_PROG_QUERY OOB write and cgroup backward compat
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuyang Huang <[email protected]>
[ Upstream commit 21c4b99b27f3f85b89256e81b3e997dec0a460d0 ]
BPF_PROG_QUERY writes back the 'query.revision' field unconditionally to userspace. If userspace passes a smaller 'bpf_attr' structure (e.g. 40 bytes, which was the layout before the addition of 'query.revision'), the kernel performs an out-of-bounds write.
Fix this by propagating the user-provided attribute size 'uattr_size' down to the cgroup query handlers, and conditionally skipping writing the revision field to userspace when the provided buffer size is insufficient.
query.revision in bpf_mprog_query is structurally identical to the cgroup case: a late tail field, written unconditionally.
But the backward-compat hazard is not the same.
The min-historical-size test is per command, and bpf_mprog_query only serves attach types that were born with revision in the struct:
- tcx_prog_query -> BPF_TCX_INGRESS/EGRESS
- netkit_prog_query -> BPF_NETKIT_PRIMARY/PEER
tcx, netkit, the revision field, and bpf_mprog_query itself all landed in the same v6.6 merge window (053c8e1f235d added the mprog query API + revision; tcx in e420bed02507, netkit in 35dfaad7188c). There has never been a tcx/netkit BPF_PROG_QUERY userspace that doesn't know about revision. So for these commands the minimum legitimate struct already covers offset 56-64 — no old binary can be broken here.
Contrast with cgroup: BPF_PROG_QUERY on cgroup attach types shipped in 2017; revision write-back was bolted on years later (120933984460). That path has a real population of pre-revision callers.
--- include/linux/bpf-cgroup.h | 5 +++-- kernel/bpf/cgroup.c | 13 +++++++------ kernel/bpf/syscall.c | 6 +++--- 3 files changed, 13 insertions(+), 11 deletions(-)
include/linux/bpf-cgroup.h +3 -2
@@ -420,7 +420,7 @@ int cgroup_bpf_prog_detach(const union bpf_attr *attr, enum bpf_prog_type ptype);int cgroup_bpf_link_attach (const union bpf_attr *attr,struct bpf_prog *prog);int cgroup_bpf_prog_query (const union bpf_attr *attr, -union bpf_attr __user *uattr); +union bpf_attr __user *uattr,u32 uattr_size);const struct bpf_func_proto *cgroup_common_func_proto (enum bpf_func_id func_id,const struct bpf_prog *prog);
@@ -451,7 +451,8 @@ static inline int cgroup_bpf_link_attach(const union bpf_attr *attr, }static inline int cgroup_bpf_prog_query (const union bpf_attr *attr, -union bpf_attr __user *uattr) +union bpf_attr __user *uattr, +u32 uattr_size) {return -EINVAL ; }
kernel/bpf/cgroup.c +7 -6
@@ -1216,7 +1216,7 @@ static int cgroup_bpf_detach(struct cgroup *cgrp, struct bpf_prog *prog,/* Must be called with cgroup_mutex held to avoid races. */ static int __cgroup_bpf_query (struct cgroup *cgrp,const union bpf_attr *attr, -union bpf_attr __user *uattr) +union bpf_attr __user *uattr,u32 uattr_size) {__u32 __user *prog_attach_flags =u64_to_user_ptr (attr->query.prog_attach_flags);bool effective_query = attr->query.query_flags &BPF_F_QUERY_EFFECTIVE ;
@@ -1267,7 +1267,8 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr,return -EFAULT ;if (!effective_query && from_atype == to_atype) revision = cgrp->bpf.revisions[from_atype]; -if (copy_to_user (&uattr->query.revision, &revision,sizeof (revision))) + if (uattr_size >= offsetofend(union bpf_attr, query.revision) && +copy_to_user (&uattr->query.revision, &revision,sizeof (revision)))return -EFAULT ;if (attr->query.prog_cnt ==0 || !prog_ids || !total_cnt)/* return early if user requested only program count + flags */
@@ -1320,12 +1321,12 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, }static int cgroup_bpf_query (struct cgroup *cgrp,const union bpf_attr *attr, -union bpf_attr __user *uattr) +union bpf_attr __user *uattr,u32 uattr_size) {int ret;cgroup_lock (); - ret =__cgroup_bpf_query (cgrp, attr, uattr); + ret =__cgroup_bpf_query (cgrp, attr, uattr, uattr_size);cgroup_unlock ();return ret; }
@@ -1529,7 +1530,7 @@ int cgroup_bpf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog) }int cgroup_bpf_prog_query (const union bpf_attr *attr, -union bpf_attr __user *uattr) +union bpf_attr __user *uattr,u32 uattr_size) {struct cgroup *cgrp;int ret;
@@ -1538,7 +1539,7 @@ int cgroup_bpf_prog_query(const union bpf_attr *attr,if (IS_ERR (cgrp))return PTR_ERR (cgrp); - ret =cgroup_bpf_query (cgrp, attr, uattr); + ret =cgroup_bpf_query (cgrp, attr, uattr, uattr_size);cgroup_put (cgrp);return ret;
kernel/bpf/syscall.c +3 -3
@@ -4227,7 +4227,7 @@ static int bpf_prog_detach(const union bpf_attr *attr)#define BPF_PROG_QUERY_LAST_FIELD query.revisionstatic int bpf_prog_query (const union bpf_attr *attr, -union bpf_attr __user *uattr) +union bpf_attr __user *uattr,u32 uattr_size) {if (!bpf_net_capable ())return -EPERM ;
@@ -4266,7 +4266,7 @@ static int bpf_prog_query(const union bpf_attr *attr,case BPF_CGROUP_GETSOCKOPT :case BPF_CGROUP_SETSOCKOPT :case BPF_LSM_CGROUP : -return cgroup_bpf_prog_query (attr, uattr); +return cgroup_bpf_prog_query (attr, uattr, uattr_size);case BPF_LIRC_MODE2 :return lirc_prog_query (attr, uattr);case BPF_FLOW_DISSECTOR :
@@ -5720,7 +5720,7 @@ static int __sys_bpf(enum bpf_cmd cmd, bpfptr_t uattr, unsigned int size) err =bpf_prog_detach (&attr);break ;case BPF_PROG_QUERY : - err =bpf_prog_query (&attr, uattr.user); + err =bpf_prog_query (&attr, uattr.user, size);break ;case BPF_PROG_TEST_RUN : err =bpf_prog_test_run (&attr, uattr.user);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1351/1376 perf test: Dont signal all processes on system when interrupting tests
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Clark <[email protected]>
[ Upstream commit f54cd8f43f55c0274c5b51509aff39675639c2e1 ]
This signal handler loops over all tests on ctrl-C, but it's active while the test list is being constructed. process.pid is 0, then -1, then finally set to the child pid on fork. If the Ctrl-C is received during this point a kill(-1, SIGINT) can be sent which affects all processes.
Make sure the child has forked first before forwarding the signal. This can be reproduced with ctrl-C immediately after launching perf test which terminates the ssh connection.
--- tools/perf/tests/builtin-test.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
tools/perf/tests/builtin-test.c +1 -1
@@ -504,7 +504,7 @@ static int __cmd_test(struct test_suite **suites, int argc, const char *argv[],for (size_t x =0 ; x < num_tests; x++) {struct child_test *child_test = child_tests[x]; -if (!child_test) +if (!child_test || child_test->process.pid <=0 )continue ; pr_debug3("Killing %d pid %d\n",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1352/1376 phy: qcom: qmp-combo: Add missing PLL (VCO) configuration on SM8750
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Kozlowski <[email protected]>
[ Upstream commit 304c102cff7382353a28039907a7017bde795db9 ]
Add missing DP PHY status and VCO clock configuration registers to fix configuring the VCO rate on SM8750. Without proper VCO rate setting, it works on after-reset half of rate which is not enough for DP over USB to work as seen on logs:
[drm:msm_dp_ctrl_link_train_1_2] *ERROR* max v_level reached [drm:msm_dp_ctrl_link_train_1_2] *ERROR* link training #1 on phy 0 failed. ret=-11
--- drivers/phy/qualcomm/phy-qcom-qmp-combo.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/phy/qualcomm/phy-qcom-qmp-combo.c +3 -0
@@ -249,6 +249,9 @@ static const unsigned int qmp_v8_usb3phy_regs_layout[QPHY_LAYOUT_SIZE] = { [QPHY_COM_CMN_STATUS] = QSERDES_V8_COM_CMN_STATUS, [QPHY_COM_BIAS_EN_CLKBUFLR_EN] = QSERDES_V8_COM_BIAS_EN_CLKBUFLR_EN, + [QPHY_DP_PHY_STATUS] = QSERDES_V6_DP_PHY_STATUS, + [QPHY_DP_PHY_VCO_DIV] = QSERDES_V6_DP_PHY_VCO_DIV, + [QPHY_TX_TX_POL_INV] = QSERDES_V8_TX_TX_POL_INV, [QPHY_TX_TX_DRV_LVL] = QSERDES_V8_TX_TX_DRV_LVL, [QPHY_TX_TX_EMP_POST1_LVL] = QSERDES_V8_TX_TX_EMP_POST1_LVL,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1353/1376 powerpc/vdso: Remove unused clockmode asm offsets
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Weißschuh <[email protected]>
[ Upstream commit d7a82238cb8c77d4ed8cc97cd556c5f3e64bc749 ]
These offsets are not used anymore, delete them.
--- arch/powerpc/kernel/asm-offsets.c | 2 -- 1 file changed, 2 deletions(-)
arch/powerpc/kernel/asm-offsets.c +0 -2
@@ -348,8 +348,6 @@ int main(void)#else OFFSET (CFG_SYSCALL_MAP32 , vdso_arch_data, syscall_map);#endif -OFFSET (VDSO_CLOCKMODE_OFFSET , vdso_arch_data, data[0 ].clock_mode); -DEFINE (VDSO_CLOCKMODE_TIMENS ,VDSO_CLOCKMODE_TIMENS );#ifdef CONFIG_BUG DEFINE (BUG_ENTRY_SIZE ,sizeof (struct bug_entry ));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1354/1376 nvme-apple: Prevent shared tags across queues on Apple A11
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nick Chan <[email protected]>
[ Upstream commit 6fe0687245e8406bf26143bd45eb16441bbe5280 ]
On Apple A11, tags of pending commands must be unique across the admin and IO queues, else the firmware crashes with
"duplicate tag error for tag N", with N being the tag.
Apply the existing workaround for M1 of reserving two tags for the admin queue to A11.
--- drivers/nvme/host/apple.c | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-)
drivers/nvme/host/apple.c +4 -8
@@ -239,7 +239,7 @@ static unsigned int apple_nvme_queue_depth(struct apple_nvme_queue *q) {struct apple_nvme *anv =queue_to_apple_nvme (q); -if (q->is_adminq && anv->hw->has_lsq_nvmmu) +if (q->is_adminq)return APPLE_NVME_AQ_DEPTH ;return anv->hw->max_queue_depth;
@@ -317,7 +317,7 @@ static void apple_nvme_submit_cmd_t8015(struct apple_nvme_queue *q,memcpy ((void *)q->sqes + (q->sq_tail <<APPLE_NVME_IOSQES ), cmd,sizeof (*cmd)); -if (++q->sq_tail == anv->hw->max_queue_depth) +if (++q->sq_tail ==apple_nvme_queue_depth (q)) q->sq_tail =0 ;writel (q->sq_tail, q->sq_db);
@@ -1130,10 +1130,7 @@ static void apple_nvme_reset_work(struct work_struct *work) }/* Setup the admin queue */ -if (anv->hw->has_lsq_nvmmu) - aqa =APPLE_NVME_AQ_DEPTH -1 ; -else - aqa = anv->hw->max_queue_depth -1 ; + aqa =APPLE_NVME_AQ_DEPTH -1 ; aqa |= aqa <<16 ;writel (aqa, anv->mmio_nvme +NVME_REG_AQA );writeq (anv->adminq.sq_dma_addr, anv->mmio_nvme +NVME_REG_ASQ );
@@ -1316,8 +1313,7 @@ static int apple_nvme_alloc_tagsets(struct apple_nvme *anv)* both queues. The admin queue gets the first APPLE_NVME_AQ_DEPTH which * must be marked as reserved in the IO queue. */ -if (anv->hw->has_lsq_nvmmu) - anv->tagset.reserved_tags =APPLE_NVME_AQ_DEPTH ; + anv->tagset.reserved_tags =APPLE_NVME_AQ_DEPTH ; anv->tagset.queue_depth = anv->hw->max_queue_depth -1 ; anv->tagset.timeout =NVME_IO_TIMEOUT ; anv->tagset.numa_node =NUMA_NO_NODE ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1355/1376 nvme-apple: Reset q->sq_tail during queue init
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nick Chan <[email protected]>
[ Upstream commit a6ab75639e23169a741b0b2e12191fd8acb32c73 ]
Fixes a "duplicate tag error for tag 0" firmware crash during controller reset while setting up a queue on Apple A11 / T8015 caused by stale entries in the submission queue due to an invalid sq_tail offset after reset.
--- drivers/nvme/host/apple.c | 1 + 1 file changed, 1 insertion(+)
drivers/nvme/host/apple.c +1 -0
@@ -1025,6 +1025,7 @@ static void apple_nvme_init_queue(struct apple_nvme_queue *q)unsigned int depth =apple_nvme_queue_depth (q);struct apple_nvme *anv =queue_to_apple_nvme (q); + q->sq_tail =0 ; q->cq_head =0 ; q->cq_phase =1 ;if (anv->hw->has_lsq_nvmmu)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1356/1376 cpuset: fix warning when disabling remote partition
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Ridong <[email protected]>
[ Upstream commit aa7d3a56a20f07978d9f401e13637a6479b13bd0 ]
A warning was triggered as follows:
WARNING: kernel/cgroup/cpuset.c:1651 at remote_partition_disable+0xf7/0x110 RIP: 0010:remote_partition_disable+0xf7/0x110 RSP: 0018:ffffc90001947d88 EFLAGS: 00000206 RAX: 0000000000007fff RBX: ffff888103b6e000 RCX: 0000000000006f40 RDX: 0000000000006f00 RSI: ffffc90001947da8 RDI: ffff888103b6e000 RBP: ffff888103b6e000 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000001 R11: ffff88810b2e2728 R12: ffffc90001947da8 R13: 0000000000000000 R14: ffffc90001947da8 R15: ffff8881081f1c00 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00007f55c8bbe0b2 CR3: 000000010b14c000 CR4: 00000000000006f0 Call Trace: <TASK> update_prstate+0x2d3/0x580 cpuset_partition_write+0x94/0xf0 kernfs_fop_write_iter+0x147/0x200 vfs_write+0x35d/0x500 ksys_write+0x66/0xe0 do_syscall_64+0x6b/0x390 entry_SYSCALL_64_after_hwframe+0x4b/0x53 RIP: 0033:0x7f55c8cd4887
Reproduction steps (on a 16-CPU machine):
# cd /sys/fs/cgroup/
# mkdir A1
# echo +cpuset > A1/cgroup.subtree_control
# echo "0-14" > A1/cpuset.cpus.exclusive
# mkdir A1/A2
# echo "0-14" > A1/A2/cpuset.cpus.exclusive
# echo "root" > A1/A2/cpuset.cpus.partition
# echo 0 > /sys/devices/system/cpu/cpu15/online
# echo member > A1/A2/cpuset.cpus.partitionWhen CPU 15 is offlined, subpartitions_cpus gets cleared because no CPUs remain available for the top_cpuset, forcing partitions to share CPUs with the top_cpuset. In this scenario, disabling the remote partition triggers a warning stating that effective_xcpus is not a subset of subpartitions_cpus. Partitions should be invalidated in this case to inform users that the partition is now invalid(cpus are shared with top_cpuset).
To fix this issue:
1. Only emit the warning only if subpartitions_cpus is not empty and the effective_xcpus is not a subset of subpartitions_cpus.
2. During the CPU hotplug process, invalidate partitions if subpartitions_cpus is empty.
--- kernel/cgroup/cpuset.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
kernel/cgroup/cpuset.c +16 -5
@@ -1484,7 +1484,14 @@ static void remote_partition_disable(struct cpuset *cs, struct tmpmasks *tmp)bool isolcpus_updated;WARN_ON_ONCE (!is_remote_partition (cs)); -WARN_ON_ONCE (!cpumask_subset (cs->effective_xcpus, subpartitions_cpus)); +/* +* When a CPU is offlined, top_cpuset may end up with no available CPUs, +* which should clear subpartitions_cpus. We should not emit a warning for this +* scenario: the hierarchy is updated from top to bottom, so subpartitions_cpus +* may already be cleared when disabling the partition. +*/ +WARN_ON_ONCE (!cpumask_subset (cs->effective_xcpus, subpartitions_cpus) && + !cpumask_empty (subpartitions_cpus));spin_lock_irq (&callback_lock);list_del_init (&cs->remote_sibling);
@@ -3816,8 +3823,9 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp)if (remote || (is_partition_valid (cs) &&is_partition_valid (parent)))compute_partition_effective_cpumask (cs, &new_cpus); -if (remote &&cpumask_empty (&new_cpus) && -partition_is_populated (cs,NULL )) { +if (remote && (cpumask_empty (subpartitions_cpus) || + (cpumask_empty (&new_cpus) && +partition_is_populated (cs,NULL )))) { cs->prs_err =PERR_HOTPLUG ;remote_partition_disable (cs, tmp);compute_effective_cpumask (&new_cpus, cs, parent);
@@ -3830,9 +3838,12 @@ static void cpuset_hotplug_update_tasks(struct cpuset *cs, struct tmpmasks *tmp)* 1) empty effective cpus but not valid empty partition. * 2) parent is invalid or doesn't grant any cpus to child * partitions. +* 3) subpartitions_cpus is empty. */ -if (is_local_partition (cs) && (!is_partition_valid (parent) || -tasks_nocpu_error (parent, cs, &new_cpus))) +if (is_local_partition (cs) && + (!is_partition_valid (parent) || +tasks_nocpu_error (parent, cs, &new_cpus) || +cpumask_empty (subpartitions_cpus))) partcmd = partcmd_invalidate;/* * On the other hand, an invalid partition root may be transitioned
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1357/1376 erofs: fix managed cache race for unaligned extents
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gao Xiang <[email protected]>
[ Upstream commit 649932fc3815eda2f24eb4de4b3a5e94886ee0b9 ]
After unaligned compressed extents were introduced, the following race could occur:
[Thread 1] [Thread 2]
(z_erofs_fill_bio_vec)
<handle a Z_EROFS_PREALLOCATED_FOLIO folio>
...filemap_add_folio (1)
(z_erofs_bind_cache)
<the same folio is found..>
..
..folio_attach_private (2)
filemap_add_folio (3) again
Since (1) is executed but (2) hasn't been executed yet, it's possible that another thread finds the same managed folio in z_erofs_bind_cache() for a different pcluster and calls filemap_add_folio() again since folio->private is still Z_EROFS_PREALLOCATED_FOLIO.
Fix this by explicitly clearing folio->private before making the folio visible in the managed cache so that another pcluster can simply wait on the locked managed folio as what we did for other shared cases [1].
This only impacts unaligned data compression (-E48bit with zstd, for example).
[1] Commit 9e2f9d34dd12 ("erofs: handle overlapped pclusters out of crafted images properly") was originally introduced to handle crafted overlapped extents, but it addresses unaligned extents as well.
--- fs/erofs/zdata.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-)
fs/erofs/zdata.c +8 -7
@@ -1478,8 +1478,15 @@ static void z_erofs_fill_bio_vec(struct bio_vec *bvec,DBG_BUGON (z_erofs_is_shortlived_page (bvec->bv_page)); folio =page_folio (zbv.page); -/* For preallocated managed folios, add them to page cache here */ +/* +* Preallocated folios are added to the managed cache here rather than +* in z_erofs_bind_cache() in order to keep these folios locked in +* increasing (physical) address order. +* Clear folio->private before these folios become visible to others in +* the managed cache to avoid duplicate additions for unaligned extents. +*/ if (folio->private ==Z_EROFS_PREALLOCATED_FOLIO ) { + folio->private =NULL ; tocache = true; goto out_tocache; }
@@ -1515,14 +1522,8 @@ static void z_erofs_fill_bio_vec(struct bio_vec *bvec, }return ; } -/* -* Already linked with another pcluster, which only appears in -* crafted images by fuzzers for now. But handle this anyway. -*/ - tocache = false;/* use temporary short-lived pages */ }else {DBG_BUGON (1 );/* referenced managed folios can't be truncated */ - tocache = true; }folio_unlock (folio);folio_put (folio);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1358/1376 xsk: Fix offset calculation in unaligned mode
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: e.kubanski <[email protected]>
[ Upstream commit bf20af07909925ec0ae6cd4f3b7be0279dfa8768 ]
Bring back previous offset calculation behaviour
in AF_XDP unaligned umem mode.
In unaligned mode, upper 16 bits should contain
data offset, lower 48 bits should contain
only specific chunk location without offset.
Remove pool->headroom duplication into 48bit address.
--- include/net/xsk_buff_pool.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/net/xsk_buff_pool.h +1 -1
@@ -231,8 +231,8 @@ static inline u64 xp_get_handle(struct xdp_buff_xsk *xskb,return orig_addr; offset = xskb->xdp.data - xskb->xdp.data_hard_start; - orig_addr -= offset; offset += pool->headroom; + orig_addr -= offset;return orig_addr + (offset <<XSK_UNALIGNED_BUF_OFFSET_SHIFT ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1359/1376 Bluetooth: btmtk: hide unused btmtk_mt6639_devs[] array
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
[ Upstream commit 81f971c6abec59240e2bcfc38756bda8172fa788 ]
When USB support is disabled, the array is not referenced anywhere, causing a warning:
drivers/bluetooth/btmtk.c:35:3: error: 'btmtk_mt6639_devs' defined but not used [-Werror=unused-const-variable=]
35 | } btmtk_mt6639_devs[] = {
| ^~~~~~~~~~~~~~~~~Move it into the #ifdef block.
--- drivers/bluetooth/btmtk.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-)
drivers/bluetooth/btmtk.c +16 -16
@@ -25,22 +25,6 @@/* It is for mt79xx iso data transmission setting */ #define MTK_ISO_THRESHOLD 264 -/* Known MT6639 (MT7927) Bluetooth USB devices. -* Used to scope the zero-CHIPID workaround to real MT6639 hardware, -* since some boards return 0x0000 from the MMIO chip ID register. -*/ -static const struct { -u16 vendor; -u16 product; -} btmtk_mt6639_devs[] = { - {0x0489 ,0xe13a },/* ASUS ROG Crosshair X870E Hero */ - {0x0489 ,0xe0fa },/* Lenovo Legion Pro 7 16ARX9 */ - {0x0489 ,0xe10f },/* Gigabyte Z790 AORUS MASTER X */ - {0x0489 ,0xe110 },/* MSI X870E Ace Max */ - {0x0489 ,0xe116 },/* TP-Link Archer TBE550E */ - {0x13d3 ,0x3588 },/* ASUS ROG STRIX X870E-E */ -}; -struct btmtk_patch_header {u8 datetime[16 ];u8 platform[4 ];
@@ -471,6 +455,22 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)EXPORT_SYMBOL_GPL (btmtk_process_coredump);#if IS_ENABLED (CONFIG_BT_HCIBTUSB_MTK ) +/* Known MT6639 (MT7927) Bluetooth USB devices. +* Used to scope the zero-CHIPID workaround to real MT6639 hardware, +* since some boards return 0x0000 from the MMIO chip ID register. +*/ +static const struct { +u16 vendor; +u16 product; +} btmtk_mt6639_devs[] = { + {0x0489 ,0xe13a },/* ASUS ROG Crosshair X870E Hero */ + {0x0489 ,0xe0fa },/* Lenovo Legion Pro 7 16ARX9 */ + {0x0489 ,0xe10f },/* Gigabyte Z790 AORUS MASTER X */ + {0x0489 ,0xe110 },/* MSI X870E Ace Max */ + {0x0489 ,0xe116 },/* TP-Link Archer TBE550E */ + {0x13d3 ,0x3588 },/* ASUS ROG STRIX X870E-E */ +}; +static void btmtk_usb_wmt_recv (struct urb *urb) {struct hci_dev *hdev = urb->context;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1360/1376 net/sched: fq: clamp quantum and initial_quantum in change path
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit 094cc07f98dfe70a34e2a1923af17fd29b8cf622 ]
The fq change path accepts TCA_FQ_QUANTUM in [1, INT_MAX] and TCA_FQ_INITIAL_QUANTUM up to INT_MAX, while fq_init() already clamps to [1, 1<<20]. A user can override the init clamp via tc qdisc change, restoring the small-quantum deficit spin that the init clamp prevents.
Narrow iq_range.max to 1<<20 so TCA_FQ_INITIAL_QUANTUM is rejected at parse time. Clamp TCA_FQ_QUANTUM to [256, 1<<20] in fq_change() and fq_init() quantum to [256, 1<<20] for tiny-MTU devices.
Conditions to recreate the bug:
CONFIG_NET_SCH_FQ=y. Requires CAP_NET_ADMIN (namespace-local via unshare -Urn suffices).
tc qdisc add dev dummy0 root fq
tc qdisc change dev dummy0 root fq quantum 1 stab data 32768 size_log 15 cell_log 0
--- net/sched/sch_fq.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-)
net/sched/sch_fq.c +5 -9
@@ -909,7 +909,7 @@ static int fq_resize(struct Qdisc *sch, u32 log) }static const struct netlink_range_validation iq_range = { - .max =INT_MAX , + .max =1 <<20 , };static const struct nla_policy fq_policy[TCA_FQ_MAX +1 ] = {
@@ -1034,14 +1034,10 @@ static int fq_change(struct Qdisc *sch, struct nlattr *opt, nla_get_u32(tb[TCA_FQ_FLOW_PLIMIT]));if (tb[TCA_FQ_QUANTUM ]) { -u32 quantum =nla_get_u32 (tb[TCA_FQ_QUANTUM ]); +u32 quantum =clamp_t (u32,nla_get_u32 (tb[TCA_FQ_QUANTUM ]), +256 ,1 <<20 ); -if (quantum >0 && quantum <= (1 <<20 )) { -WRITE_ONCE (q->quantum, quantum); - }else { -NL_SET_ERR_MSG_MOD (extack,"invalid quantum" ); - err = -EINVAL ; - } +WRITE_ONCE (q->quantum, quantum); }if (tb[TCA_FQ_INITIAL_QUANTUM ])
@@ -1147,7 +1143,7 @@ static int fq_init(struct Qdisc *sch, struct nlattr *opt, sch->limit =10000 ; q->flow_plimit =100 ; mtu =clamp_t (u32,psched_mtu (qdisc_dev (sch)),1 ,1 <<20 ); - q->quantum =min_t (u32,2 * mtu,1 <<20 ); + q->quantum =clamp_t (u32,2 * mtu,256 ,1 <<20 ); q->initial_quantum =min_t (u32,10 * mtu,1 <<20 ); q->flow_refill_delay =msecs_to_jiffies (40 ); q->flow_max_rate = ~0UL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1361/1376 kselftest/arm64: mte: Skip the hugetlb tests if MTE not supported on such mappings
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Catalin Marinas <[email protected]>
[ Upstream commit 306219d59b72cfca4005229b2c6ad43a16479e3b ]
While the kselftest was added at the same time with the kernel support for MTE on hugetlb mappings, the tests may be run on older kernels. Skip the tests if PROT_MTE is not supported on MAP_HUGETLB mappings.
--- .../selftests/arm64/mte/check_hugetlb_options.c | 11 +++++++++++ 1 file changed, 11 insertions(+)
tools/testing/selftests/arm64/mte/check_hugetlb_options.c +11 -0
@@ -227,6 +227,8 @@ static int check_child_hugetlb_memory_mapping(int mem_type, int mode, int mappinint main (int argc,char *argv[]) {int err; +void *map_ptr; +unsigned long map_size;ksft_print_header ();
@@ -245,6 +247,15 @@ int main(int argc, char *argv[])return KSFT_FAIL ; } +/* Check if MTE supports hugetlb mappings */ + map_size =default_huge_page_size (); + map_ptr =mmap (NULL , map_size,PROT_READ |PROT_MTE , +MAP_PRIVATE |MAP_ANONYMOUS |MAP_HUGETLB ,-1 ,0 ); +if (map_ptr ==MAP_FAILED ) +ksft_exit_skip ("PROT_MTE not supported with MAP_HUGETLB mappings\n" ); +else +munmap (map_ptr, map_size); +/* Set test plan */ ksft_set_plan (12 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1362/1376 kselftest/arm64: mte: Use the correct naming for tag check modes in check_hugetlb_options.c
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Catalin Marinas <[email protected]>
[ Upstream commit 7ae95109c64d64cdcf195788cf466ec0b3019a94 ]
The architecture doesn't define precise/imprecise MTE tag check modes, only synchronous and asynchronous. Use the correct naming and also ensure they match the MTE_{ASYNC,SYNC}_ERR type.
--- tools/testing/selftests/arm64/mte/check_hugetlb_options.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
tools/testing/selftests/arm64/mte/check_hugetlb_options.c +4 -4
@@ -283,13 +283,13 @@ int main(int argc, char *argv[]) "Check clear PROT_MTE flags with private mapping and sync error mode and mmap/mprotect memory\n");evaluate_test (check_child_hugetlb_memory_mapping (USE_MMAP ,MTE_SYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ), -"Check child hugetlb memory with private mapping, precise mode and mmap memory\n" ); +"Check child hugetlb memory with private mapping, sync error mode and mmap memory\n" );evaluate_test (check_child_hugetlb_memory_mapping (USE_MMAP ,MTE_ASYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ), -"Check child hugetlb memory with private mapping, precise mode and mmap memory\n" ); +"Check child hugetlb memory with private mapping, async error mode and mmap memory\n" );evaluate_test (check_child_hugetlb_memory_mapping (USE_MPROTECT ,MTE_SYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ), -"Check child hugetlb memory with private mapping, precise mode and mmap/mprotect memory\n" ); +"Check child hugetlb memory with private mapping, sync error mode and mmap/mprotect memory\n" );evaluate_test (check_child_hugetlb_memory_mapping (USE_MPROTECT ,MTE_ASYNC_ERR ,MAP_PRIVATE |MAP_HUGETLB ), -"Check child hugetlb memory with private mapping, precise mode and mmap/mprotect memory\n" ); +"Check child hugetlb memory with private mapping, async error mode and mmap/mprotect memory\n" );mte_restore_setup ();free_hugetlb ();
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1363/1376 md: add helper rdev_needs_recovery()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zheng Qixing <[email protected]>
[ Upstream commit cb0780ad4333040a98e10f014b593ef738a3f31e ]
Add a helper for checking if an rdev needs recovery.
Stable-dep-of: b7ee30f0efd1 ("md: fix sync_action incorrect display during resync")
--- drivers/md/md.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-)
drivers/md/md.c +12 -11
@@ -4820,6 +4820,15 @@ metadata_store(struct mddev *mddev, const char *buf, size_t len)static struct md_sysfs_entry md_metadata =__ATTR_PREALLOC (metadata_version,S_IRUGO |S_IWUSR , metadata_show, metadata_store); +static bool rdev_needs_recovery (struct md_rdev *rdev,sector_t sectors) +{ +return rdev->raid_disk >=0 && + !test_bit (Journal, &rdev->flags) && + !test_bit (Faulty, &rdev->flags) && + !test_bit (In_sync, &rdev->flags) && + rdev->recovery_offset < sectors; +} +enum sync_action md_sync_action (struct mddev *mddev) {unsigned long recovery = mddev->recovery;
@@ -8989,11 +8998,7 @@ static sector_t md_sync_position(struct mddev *mddev, enum sync_action action) start = MaxSector;rcu_read_lock ();rdev_for_each_rcu (rdev, mddev) -if (rdev->raid_disk >=0 && - !test_bit (Journal, &rdev->flags) && - !test_bit (Faulty, &rdev->flags) && - !test_bit (In_sync, &rdev->flags) && - rdev->recovery_offset < start) +if (rdev_needs_recovery (rdev, start)) start = rdev->recovery_offset;rcu_read_unlock ();
@@ -9347,12 +9352,8 @@ void md_do_sync(struct md_thread *thread) test_bit(MD_RECOVERY_RECOVER, &mddev->recovery)) {rcu_read_lock ();rdev_for_each_rcu (rdev, mddev) -if (rdev->raid_disk >=0 && - mddev->delta_disks >=0 && - !test_bit (Journal, &rdev->flags) && - !test_bit (Faulty, &rdev->flags) && - !test_bit (In_sync, &rdev->flags) && - rdev->recovery_offset < mddev->curr_resync) +if (mddev->delta_disks >=0 && +rdev_needs_recovery (rdev, mddev->curr_resync)) rdev->recovery_offset = mddev->curr_resync;rcu_read_unlock (); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1364/1376 md: fix sync_action incorrect display during resync
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zheng Qixing <[email protected]>
[ Upstream commit b7ee30f0efd12f42735ae233071015389407966c ]
During raid resync, if a disk becomes faulty, the operation is briefly interrupted. The MD_RECOVERY_RECOVER flag triggered by the disk failure causes sync_action to incorrectly show "recover" instead of "resync". The same issue affects reshape operations.
Reproduction steps:
mdadm -Cv /dev/md1 -l1 -n4 -e1.2 /dev/sd{a..d} // -> resync happened
mdadm -f /dev/md1 /dev/sda // -> resync interrupted
cat sync_action
-> recover
Add progress checks in md_sync_action() for resync/recover/reshape to ensure the interface correctly reports the actual operation type.
--- drivers/md/md.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-)
drivers/md/md.c +35 -2
@@ -4829,9 +4829,33 @@ static bool rdev_needs_recovery(struct md_rdev *rdev, sector_t sectors) rdev->recovery_offset < sectors; } +static enum sync_action md_get_active_sync_action (struct mddev *mddev) +{ +struct md_rdev *rdev; +bool is_recover = false; + +if (mddev->resync_offset < MaxSector) +return ACTION_RESYNC ; + +if (mddev->reshape_position != MaxSector) +return ACTION_RESHAPE ; + +rcu_read_lock (); +rdev_for_each_rcu (rdev, mddev) { +if (rdev_needs_recovery (rdev, MaxSector)) { + is_recover = true; +break ; + } + } +rcu_read_unlock (); + +return is_recover ?ACTION_RECOVER :ACTION_IDLE ; +} +enum sync_action md_sync_action (struct mddev *mddev) {unsigned long recovery = mddev->recovery; +enum sync_action active_action;/* * frozen has the highest priority, means running sync_thread will be
@@ -4855,8 +4879,17 @@ enum sync_action md_sync_action(struct mddev *mddev) !test_bit(MD_RECOVERY_NEEDED, &recovery))return ACTION_IDLE ; -if (test_bit (MD_RECOVERY_RESHAPE , &recovery) || - mddev->reshape_position != MaxSector) +/* +* Check if any sync operation (resync/recover/reshape) is +* currently active. This ensures that only one sync operation +* can run at a time. Returns the type of active operation, or +* ACTION_IDLE if none are active. +*/ + active_action =md_get_active_sync_action (mddev); +if (active_action !=ACTION_IDLE ) +return active_action; + +if (test_bit (MD_RECOVERY_RESHAPE , &recovery))return ACTION_RESHAPE ;if (test_bit (MD_RECOVERY_RECOVER , &recovery))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1365/1376 net_sched: act_ct: use RCU in tcf_ct_dump()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 554e66bad84ce4181ad91a2ae9cc74c7c440e836 ]
Also storing tcf_action into struct tcf_ct_params makes sure there is no discrepancy in tcf_ct_act().
Stable-dep-of: 3016024d7514 ("net_sched: add back BH safety to tcf_lock")
--- include/net/tc_act/tc_ct.h | 2 +- net/sched/act_ct.c | 30 +++++++++++++++--------------- 2 files changed, 16 insertions(+), 16 deletions(-)
include/net/tc_act/tc_ct.h +1 -1
@@ -13,7 +13,7 @@ struct tcf_ct_params {struct nf_conntrack_helper *helper;struct nf_conn *tmpl;u16 zone; - +int action;u32 mark;u32 mark_mask;
net/sched/act_ct.c +15 -15
@@ -994,7 +994,7 @@ TC_INDIRECT_SCOPE int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a, p =rcu_dereference_bh (c->params); - retval =READ_ONCE (c->tcf_action); + retval = p->action; commit = p->ct_action &TCA_CT_ACT_COMMIT ; clear = p->ct_action &TCA_CT_ACT_CLEAR ; tmpl = p->tmpl;
@@ -1443,6 +1443,7 @@ static int tcf_ct_init(struct net *net, struct nlattr *nla,if (err) goto cleanup; + params->action = parm->action;spin_lock_bh (&c->tcf_lock); goto_ch =tcf_action_set_ctrlact (*a, parm->action, goto_ch); params = rcu_replace_pointer(c->params, params,
@@ -1476,8 +1477,8 @@ static void tcf_ct_cleanup(struct tc_action *a) }static int tcf_ct_dump_key_val (struct sk_buff *skb, -void *val,int val_type, -void *mask,int mask_type, +const void *val,int val_type, +const void *mask,int mask_type,int len) {int err;
@@ -1498,9 +1499,9 @@ static int tcf_ct_dump_key_val(struct sk_buff *skb,return 0 ; } -static int tcf_ct_dump_nat (struct sk_buff *skb,struct tcf_ct_params *p) +static int tcf_ct_dump_nat (struct sk_buff *skb,const struct tcf_ct_params *p) { -struct nf_nat_range2 *range = &p->range; +const struct nf_nat_range2 *range = &p->range;if (!(p->ct_action &TCA_CT_ACT_NAT ))return 0 ;
@@ -1538,7 +1539,8 @@ static int tcf_ct_dump_nat(struct sk_buff *skb, struct tcf_ct_params *p)return 0 ; } -static int tcf_ct_dump_helper (struct sk_buff *skb,struct nf_conntrack_helper *helper) +static int tcf_ct_dump_helper (struct sk_buff *skb, +const struct nf_conntrack_helper *helper) {if (!helper)return 0 ;
@@ -1555,9 +1557,8 @@ static inline int tcf_ct_dump(struct sk_buff *skb, struct tc_action *a, int bind, int ref) {unsigned char *b =skb_tail_pointer (skb); -struct tcf_ct *c =to_ct (a); -struct tcf_ct_params *p; - +const struct tcf_ct *c =to_ct (a); +const struct tcf_ct_params *p;struct tc_ct opt = { .index = c->tcf_index, .refcnt =refcount_read (&c->tcf_refcnt) - ref,
@@ -1565,10 +1566,9 @@ static inline int tcf_ct_dump(struct sk_buff *skb, struct tc_action *a, };struct tcf_t t; -spin_lock_bh (&c->tcf_lock); - p =rcu_dereference_protected (c->params, -lockdep_is_held (&c->tcf_lock)); - opt.action = c->tcf_action; +rcu_read_lock (); + p =rcu_dereference (c->params); + opt.action = p->action; if (tcf_ct_dump_key_val(skb, &p->ct_action, TCA_CT_ACTION,
@@ -1613,11 +1613,11 @@ static inline int tcf_ct_dump(struct sk_buff *skb, struct tc_action *a,tcf_tm_dump (&t, &c->tcf_tm);if (nla_put_64bit (skb,TCA_CT_TM ,sizeof (t), &t,TCA_CT_PAD )) goto nla_put_failure; -spin_unlock_bh (&c->tcf_lock); +rcu_read_unlock ();return skb->len; nla_put_failure: -spin_unlock_bh (&c->tcf_lock); +rcu_read_unlock ();nlmsg_trim (skb, b);return -1 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1366/1376 net_sched: act_ctinfo: use RCU in tcf_ctinfo_dump()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 799c94178cf9c9e80575b05b7479396de8b42b61 ]
Also storing tcf_action into struct tcf_ctinfo_params makes sure there is no discrepancy in tcf_ctinfo_act().
Stable-dep-of: 3016024d7514 ("net_sched: add back BH safety to tcf_lock")
--- include/net/tc_act/tc_ctinfo.h | 1 + net/sched/act_ctinfo.c | 23 +++++++++++------------ 2 files changed, 12 insertions(+), 12 deletions(-)
include/net/tc_act/tc_ctinfo.h +1 -0
@@ -7,6 +7,7 @@struct tcf_ctinfo_params {struct rcu_head rcu;struct net *net; +int action;u32 dscpmask;u32 dscpstatemask;u32 cpmarkmask;
net/sched/act_ctinfo.c +11 -12
@@ -88,13 +88,11 @@ TC_INDIRECT_SCOPE int tcf_ctinfo_act(struct sk_buff *skb,struct tcf_ctinfo_params *cp;struct nf_conn *ct;int proto, wlen; -int action; cp =rcu_dereference_bh (ca->params);tcf_lastuse_update (&ca->tcf_tm);tcf_action_update_bstats (&ca->common, skb); - action =READ_ONCE (ca->tcf_action); wlen =skb_network_offset (skb);switch (skb_protocol (skb, true)) {
@@ -141,7 +139,7 @@ TC_INDIRECT_SCOPE int tcf_ctinfo_act(struct sk_buff *skb,if (thash)nf_ct_put (ct); out: -return action; +return cp->action; }static const struct nla_policy ctinfo_policy[TCA_CTINFO_MAX +1 ] = {
@@ -258,6 +256,8 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla, cp_new->mode |=CTINFO_MODE_CPMARK ; } + cp_new->action = actparm->action; +spin_lock_bh (&ci->tcf_lock); goto_ch =tcf_action_set_ctrlact (*a, actparm->action, goto_ch); cp_new = rcu_replace_pointer(ci->params, cp_new,
@@ -282,25 +282,24 @@ static int tcf_ctinfo_init(struct net *net, struct nlattr *nla,static int tcf_ctinfo_dump (struct sk_buff *skb,struct tc_action *a,int bind,int ref) { -struct tcf_ctinfo *ci =to_ctinfo (a); +const struct tcf_ctinfo *ci =to_ctinfo (a); +unsigned char *b =skb_tail_pointer (skb); +const struct tcf_ctinfo_params *cp;struct tc_ctinfo opt = { .index = ci->tcf_index, .refcnt =refcount_read (&ci->tcf_refcnt) - ref, .bindcnt =atomic_read (&ci->tcf_bindcnt) - bind, }; -unsigned char *b =skb_tail_pointer (skb); -struct tcf_ctinfo_params *cp;struct tcf_t t; -spin_lock_bh (&ci->tcf_lock); - cp =rcu_dereference_protected (ci->params, -lockdep_is_held (&ci->tcf_lock)); +rcu_read_lock (); + cp =rcu_dereference (ci->params);tcf_tm_dump (&t, &ci->tcf_tm);if (nla_put_64bit (skb,TCA_CTINFO_TM ,sizeof (t), &t,TCA_CTINFO_PAD )) goto nla_put_failure; - opt.action = ci->tcf_action; + opt.action = cp->action;if (nla_put (skb,TCA_CTINFO_ACT ,sizeof (opt), &opt)) goto nla_put_failure;
@@ -337,11 +336,11 @@ static int tcf_ctinfo_dump(struct sk_buff *skb, struct tc_action *a, TCA_CTINFO_PAD)) goto nla_put_failure; -spin_unlock_bh (&ci->tcf_lock); +rcu_read_unlock ();return skb->len; nla_put_failure: -spin_unlock_bh (&ci->tcf_lock); +rcu_read_unlock ();nlmsg_trim (skb, b);return -1 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1367/1376 net_sched: act_skbedit: use RCU in tcf_skbedit_dump()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 1f376373bd225c90381b745e38fa65a9386f7f8e ]
Also storing tcf_action into struct tcf_skbedit_params makes sure there is no discrepancy in tcf_skbedit_act().
Stable-dep-of: 3016024d7514 ("net_sched: add back BH safety to tcf_lock")
--- include/net/tc_act/tc_skbedit.h | 1 + net/sched/act_skbedit.c | 20 +++++++++----------- 2 files changed, 10 insertions(+), 11 deletions(-)
include/net/tc_act/tc_skbedit.h +1 -0
@@ -12,6 +12,7 @@#include <linux/tc_act/tc_skbedit.h> struct tcf_skbedit_params { +int action;u32 flags;u32 priority;u32 mark;
net/sched/act_skbedit.c +9 -11
@@ -43,13 +43,11 @@ TC_INDIRECT_SCOPE int tcf_skbedit_act(struct sk_buff *skb, {struct tcf_skbedit *d =to_skbedit (a);struct tcf_skbedit_params *params; -int action;tcf_lastuse_update (&d->tcf_tm);bstats_update (this_cpu_ptr (d->common.cpu_bstats), skb); params =rcu_dereference_bh (d->params); - action =READ_ONCE (d->tcf_action);if (params->flags &SKBEDIT_F_PRIORITY ) skb->priority = params->priority;
@@ -85,7 +83,7 @@ TC_INDIRECT_SCOPE int tcf_skbedit_act(struct sk_buff *skb, }if (params->flags &SKBEDIT_F_PTYPE ) skb->pkt_type = params->ptype; -return action; +return params->action; err:qstats_drop_inc (this_cpu_ptr (d->common.cpu_qstats));
@@ -266,6 +264,7 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,if (flags &SKBEDIT_F_MASK ) params_new->mask = *mask; + params_new->action = parm->action;spin_lock_bh (&d->tcf_lock); goto_ch =tcf_action_set_ctrlact (*a, parm->action, goto_ch); params_new = rcu_replace_pointer(d->params, params_new,
@@ -288,9 +287,9 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla,static int tcf_skbedit_dump (struct sk_buff *skb,struct tc_action *a,int bind,int ref) { +const struct tcf_skbedit *d =to_skbedit (a);unsigned char *b =skb_tail_pointer (skb); -struct tcf_skbedit *d =to_skbedit (a); -struct tcf_skbedit_params *params; +const struct tcf_skbedit_params *params;struct tc_skbedit opt = { .index = d->tcf_index, .refcnt =refcount_read (&d->tcf_refcnt) - ref,
@@ -299,10 +298,9 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,u64 pure_flags =0 ;struct tcf_t t; -spin_lock_bh (&d->tcf_lock); - params =rcu_dereference_protected (d->params, -lockdep_is_held (&d->tcf_lock)); - opt.action = d->tcf_action; +rcu_read_lock (); + params =rcu_dereference (d->params); + opt.action = params->action;if (nla_put (skb,TCA_SKBEDIT_PARMS ,sizeof (opt), &opt)) goto nla_put_failure;
@@ -337,12 +335,12 @@ static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a,tcf_tm_dump (&t, &d->tcf_tm);if (nla_put_64bit (skb,TCA_SKBEDIT_TM ,sizeof (t), &t,TCA_SKBEDIT_PAD )) goto nla_put_failure; -spin_unlock_bh (&d->tcf_lock); +rcu_read_unlock ();return skb->len; nla_put_failure: -spin_unlock_bh (&d->tcf_lock); +rcu_read_unlock ();nlmsg_trim (skb, b);return -1 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1368/1376 net_sched: act_vlan: use RCU in tcf_vlan_dump()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 48b5e5dbdb234ffc951cacceaec7f8ee37c83b2d ]
Also storing tcf_action into struct tcf_vlan_params makes sure there is no discrepancy in tcf_vlan_act().
No longer block BH in tcf_vlan_init() when acquiring tcf_lock.
Stable-dep-of: 3016024d7514 ("net_sched: add back BH safety to tcf_lock")
--- include/net/tc_act/tc_vlan.h | 1 + net/sched/act_vlan.c | 20 +++++++++----------- 2 files changed, 10 insertions(+), 11 deletions(-)
include/net/tc_act/tc_vlan.h +1 -0
@@ -10,6 +10,7 @@#include <linux/tc_act/tc_vlan.h> struct tcf_vlan_params { +int action;int tcfv_action;unsigned char tcfv_push_dst[ETH_ALEN ];unsigned char tcfv_push_src[ETH_ALEN ];
net/sched/act_vlan.c +9 -11
@@ -25,7 +25,6 @@ TC_INDIRECT_SCOPE int tcf_vlan_act(struct sk_buff *skb, {struct tcf_vlan *v =to_vlan (a);struct tcf_vlan_params *p; -int action;int err;u16 tci;
@@ -38,8 +37,6 @@ TC_INDIRECT_SCOPE int tcf_vlan_act(struct sk_buff *skb,if (skb_at_tc_ingress (skb))skb_push_rcsum (skb, skb->mac_len); - action =READ_ONCE (v->tcf_action); - p =rcu_dereference_bh (v->vlan_p);switch (p->tcfv_action) {
@@ -97,7 +94,7 @@ TC_INDIRECT_SCOPE int tcf_vlan_act(struct sk_buff *skb,skb_pull_rcsum (skb, skb->mac_len);skb_reset_mac_len (skb); -return action; +return p->action; drop:tcf_action_inc_drop_qstats (&v->common);
@@ -255,10 +252,11 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, ETH_ALEN); } -spin_lock_bh (&v->tcf_lock); + p->action = parm->action; +spin_lock (&v->tcf_lock); goto_ch =tcf_action_set_ctrlact (*a, parm->action, goto_ch); p =rcu_replace_pointer (v->vlan_p, p,lockdep_is_held (&v->tcf_lock)); -spin_unlock_bh (&v->tcf_lock); +spin_unlock (&v->tcf_lock);if (goto_ch)tcf_chain_put_by_act (goto_ch);
@@ -297,9 +295,9 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a, };struct tcf_t t; -spin_lock_bh (&v->tcf_lock); - opt.action = v->tcf_action; - p =rcu_dereference_protected (v->vlan_p,lockdep_is_held (&v->tcf_lock)); +rcu_read_lock (); + p =rcu_dereference (v->vlan_p); + opt.action = p->action; opt.v_action = p->tcfv_action;if (nla_put (skb,TCA_VLAN_PARMS ,sizeof (opt), &opt)) goto nla_put_failure;
@@ -325,12 +323,12 @@ static int tcf_vlan_dump(struct sk_buff *skb, struct tc_action *a,tcf_tm_dump (&t, &v->tcf_tm);if (nla_put_64bit (skb,TCA_VLAN_TM ,sizeof (t), &t,TCA_VLAN_PAD )) goto nla_put_failure; -spin_unlock_bh (&v->tcf_lock); +rcu_read_unlock ();return skb->len; nla_put_failure: -spin_unlock_bh (&v->tcf_lock); +rcu_read_unlock ();nlmsg_trim (skb, b);return -1 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1369/1376 net_sched: act_tunnel_key: use RCU in tunnel_key_dump()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit e97ae742972f6cb57986a5ebb846048f80b90003 ]
Also storing tcf_action into struct tcf_tunnel_key_params makes sure there is no discrepancy in tunnel_key_act().
No longer block BH in tunnel_key_init() when acquiring tcf_lock.
Stable-dep-of: 3016024d7514 ("net_sched: add back BH safety to tcf_lock")
--- include/net/tc_act/tc_tunnel_key.h | 1 + net/sched/act_tunnel_key.c | 20 +++++++++----------- 2 files changed, 10 insertions(+), 11 deletions(-)
include/net/tc_act/tc_tunnel_key.h +1 -0
@@ -14,6 +14,7 @@struct tcf_tunnel_key_params {struct rcu_head rcu;int tcft_action; +int action;struct metadata_dst *tcft_enc_metadata; };
net/sched/act_tunnel_key.c +9 -11
@@ -29,13 +29,11 @@ TC_INDIRECT_SCOPE int tunnel_key_act(struct sk_buff *skb, {struct tcf_tunnel_key *t =to_tunnel_key (a);struct tcf_tunnel_key_params *params; -int action; params =rcu_dereference_bh (t->params);tcf_lastuse_update (&t->tcf_tm);tcf_action_update_bstats (&t->common, skb); - action =READ_ONCE (t->tcf_action);switch (params->tcft_action) {case TCA_TUNNEL_KEY_ACT_RELEASE :
@@ -51,7 +49,7 @@ TC_INDIRECT_SCOPE int tunnel_key_act(struct sk_buff *skb,break ; } -return action; +return params->action; } static const struct nla_policy
@@ -538,11 +536,12 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, params_new->tcft_action = parm->t_action; params_new->tcft_enc_metadata = metadata; -spin_lock_bh (&t->tcf_lock); + params_new->action = parm->action; +spin_lock (&t->tcf_lock); goto_ch =tcf_action_set_ctrlact (*a, parm->action, goto_ch); params_new =rcu_replace_pointer (t->params, params_new,lockdep_is_held (&t->tcf_lock)); -spin_unlock_bh (&t->tcf_lock); +spin_unlock (&t->tcf_lock);tunnel_key_release_params (params_new);if (goto_ch)tcf_chain_put_by_act (goto_ch);
@@ -732,10 +731,9 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a, };struct tcf_t tm; -spin_lock_bh (&t->tcf_lock); - params =rcu_dereference_protected (t->params, -lockdep_is_held (&t->tcf_lock)); - opt.action = t->tcf_action; +rcu_read_lock (); + params =rcu_dereference (t->params); + opt.action = params->action; opt.t_action = params->tcft_action;if (nla_put (skb,TCA_TUNNEL_KEY_PARMS ,sizeof (opt), &opt))
@@ -772,12 +770,12 @@ static int tunnel_key_dump(struct sk_buff *skb, struct tc_action *a,if (nla_put_64bit (skb,TCA_TUNNEL_KEY_TM ,sizeof (tm), &tm,TCA_TUNNEL_KEY_PAD )) goto nla_put_failure; -spin_unlock_bh (&t->tcf_lock); +rcu_read_unlock ();return skb->len; nla_put_failure: -spin_unlock_bh (&t->tcf_lock); +rcu_read_unlock ();nlmsg_trim (skb, b);return -1 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1370/1376 net_sched: add back BH safety to tcf_lock
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 3016024d7514e953cb3a6715ce29799373512eb4 ]
Jamal reported that we had to use BH safety after all, because stats can be updated from BH handler.
--- net/sched/act_skbmod.c | 4 ++-- net/sched/act_tunnel_key.c | 4 ++-- net/sched/act_vlan.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-)
net/sched/act_skbmod.c +2 -2
@@ -198,7 +198,7 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla, p->flags = lflags; p->action = parm->action;if (ovr) -spin_lock (&d->tcf_lock); +spin_lock_bh (&d->tcf_lock);/* Protected by tcf_lock if overwriting existing action. */ goto_ch =tcf_action_set_ctrlact (*a, parm->action, goto_ch); p_old =rcu_dereference_protected (d->skbmod_p,1 );
@@ -212,7 +212,7 @@ static int tcf_skbmod_init(struct net *net, struct nlattr *nla,rcu_assign_pointer (d->skbmod_p, p);if (ovr) -spin_unlock (&d->tcf_lock); +spin_unlock_bh (&d->tcf_lock);if (p_old)kfree_rcu (p_old, rcu);
net/sched/act_tunnel_key.c +2 -2
@@ -537,11 +537,11 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla, params_new->tcft_enc_metadata = metadata; params_new->action = parm->action; -spin_lock (&t->tcf_lock); +spin_lock_bh (&t->tcf_lock); goto_ch =tcf_action_set_ctrlact (*a, parm->action, goto_ch); params_new =rcu_replace_pointer (t->params, params_new,lockdep_is_held (&t->tcf_lock)); -spin_unlock (&t->tcf_lock); +spin_unlock_bh (&t->tcf_lock);tunnel_key_release_params (params_new);if (goto_ch)tcf_chain_put_by_act (goto_ch);
net/sched/act_vlan.c +2 -2
@@ -253,10 +253,10 @@ static int tcf_vlan_init(struct net *net, struct nlattr *nla, } p->action = parm->action; -spin_lock (&v->tcf_lock); +spin_lock_bh (&v->tcf_lock); goto_ch =tcf_action_set_ctrlact (*a, parm->action, goto_ch); p =rcu_replace_pointer (v->vlan_p, p,lockdep_is_held (&v->tcf_lock)); -spin_unlock (&v->tcf_lock); +spin_unlock_bh (&v->tcf_lock);if (goto_ch)tcf_chain_put_by_act (goto_ch);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1371/1376 tools/build: Use SYSTEM_BPFTOOL for system bpftool
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tomas Glozar <[email protected]>
commit 814d051ebed40b27285ab3c5e2454bd01a0f9631 upstream.
The feature test for system bpftool uses BPFTOOL as the variable to set its path, defaulting to just "bpftool" if not set by the user.
This conflicts with selftests and a few other utilities, which expect BPFTOOL to be set to the in-tree bpftool path by default. For example, bpftool selftests fail to build:
$ make -C tools/testing/selftests/bpf/ make: Entering directory '/home/tglozar/dev/linux/tools/testing/selftests/bpf'
make: *** No rule to make target 'bpftool', needed by '/home/tglozar/dev/linux/tools/testing/selftests/bpf/tools/include/vmlinux.h'. Stop.
make: Leaving directory '/home/tglozar/dev/linux/tools/testing/selftests/bpf'
Fix the problem by renaming the variable used for system bpftool from BPFTOOL to SYSTEM_BPFTOOL, so that the new usage does not conflict with the existing one of BPFTOOL.
--- tools/build/feature/Makefile | 2 +- tools/scripts/Makefile.include | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
tools/build/feature/Makefile +1 -1
@@ -427,7 +427,7 @@ $(OUTPUT)test-libpfm4.bin: $(BUILD) -lpfm $(OUTPUT)test-bpftool-skeletons.bin: - $(BPFTOOL) version | grep '^features:.*skeletons' \ + $(SYSTEM_BPFTOOL) version | grep '^features:.*skeletons' \ > $(@:.bin=.make.output) 2>&1 ###############################
tools/scripts/Makefile.include +1 -1
@@ -95,7 +95,7 @@ endif CC_NO_CLANG := $(shell $(CC) -dM -E -x c /dev/null | grep -Fq "__clang__"; echo $$?) # Some tools require bpftool -BPFTOOL ?= bpftool +SYSTEM_BPFTOOL ?= bpftool ifeq ($(CC_NO_CLANG), 1) EXTRA_WARNINGS += -Wstrict-aliasing=3
Greg Kroah-Hartman
maintainerPATCH 1372/1376 pinctrl: mediatek: common-v1: Fix error checking in mtk_eint_init()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
commit 446d28584723e5d4bcdb18cf6ef87cb2bb597dd8 upstream.
The devm_kzalloc() function doesn't return error pointers, it returns NULL on error. Then on the next line it checks the same pointer again by mistake, "->base" instead of "->base[0]".
--- drivers/pinctrl/mediatek/pinctrl-mtk-common.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/pinctrl/mediatek/pinctrl-mtk-common.c +3 -3
@@ -1018,12 +1018,12 @@ static int mtk_eint_init(struct mtk_pinc pctl->eint->nbase =1 ;/* mtk-eint expects an array */ pctl->eint->base =devm_kzalloc (pctl->dev,sizeof (pctl->eint->base),GFP_KERNEL ); -if (IS_ERR (pctl->eint->base)) +if (!pctl->eint->base)return -ENOMEM ; pctl->eint->base[0 ] =devm_platform_ioremap_resource (pdev,0 ); -if (IS_ERR (pctl->eint->base)) -return PTR_ERR (pctl->eint->base); +if (IS_ERR (pctl->eint->base[0 ])) +return PTR_ERR (pctl->eint->base[0 ]); pctl->eint->irq =irq_of_parse_and_map (np,0 );if (!pctl->eint->irq)
Greg Kroah-Hartman
maintainerPATCH 1373/1376 x86/Kconfig: Reenable PTDUMP on i386
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexander Popov <[email protected]>
commit 4f115596133fa168bac06bb34c6efd8f4d84c22e upstream.
The commit
f9aad622006bd64c ("mm: rename GENERIC_PTDUMP and PTDUMP_CORE")
has broken PTDUMP and the Kconfig options that use it on ARCH=i386, including CONFIG_DEBUG_WX.
CONFIG_GENERIC_PTDUMP was renamed into CONFIG_ARCH_HAS_PTDUMP, but it was mistakenly moved from "config X86" to "config X86_64". That made PTDUMP unavailable for i386.
Move CONFIG_ARCH_HAS_PTDUMP back to "config X86" to fix it.
[ bp: Massage commit message. ]
--- arch/x86/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/x86/Kconfig +1 -1
@@ -26,7 +26,6 @@ config X86_64 depends on 64BIT # Options that are inherently 64-bit kernel only: select ARCH_HAS_GIGANTIC_PAGE - select ARCH_HAS_PTDUMP select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 select ARCH_SUPPORTS_PER_VMA_LOCK select ARCH_SUPPORTS_HUGE_PFNMAP if TRANSPARENT_HUGEPAGE
@@ -94,6 +93,7 @@ config X86 select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS select ARCH_HAS_NON_OVERLAPPING_ADDRESS_SPACE select ARCH_HAS_PMEM_API if X86_64 + select ARCH_HAS_PTDUMP select ARCH_HAS_PTE_DEVMAP if X86_64 select ARCH_HAS_PTE_SPECIAL select ARCH_HAS_HW_PTE_YOUNG
Greg Kroah-Hartman
maintainerPATCH 1374/1376 slab: reset slab->obj_ext when freeing and it is OBJEXTS_ALLOC_FAIL
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hao Ge <[email protected]>
commit 86f54f9b6c17d6567c69e3a6fed52fdf5d7dbe93 upstream.
If obj_exts allocation failed, slab->obj_exts is set to OBJEXTS_ALLOC_FAIL, But we do not clear it when freeing the slab. Since OBJEXTS_ALLOC_FAIL and MEMCG_DATA_OBJEXTS currently share the same bit position, during the release of the associated folio, a VM_BUG_ON_FOLIO() check in folio_memcg_kmem() is triggered because the OBJEXTS_ALLOC_FAIL flag was not cleared, causing it to be interpreted as a kmem folio (non-slab) with MEMCG_OBJEXTS_DATA flag set, which is invalid because MEMCG_OBJEXTS_DATA is supposed to be set only on slabs.
Another problem that predates sharing the OBJEXTS_ALLOC_FAIL and MEMCG_DATA_OBJEXTS bits is that on configurations with is_check_pages_enabled(), the non-cleared bit in page->memcg_data will trigger a free_page_is_bad() failure "page still charged to cgroup"
When freeing a slab, we clear slab->obj_exts if the obj_ext array has been successfully allocated. So let's clear it also when the allocation has failed.
--- mm/slub.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
mm/slub.c +8 -1
@@ -2161,8 +2161,15 @@ alloc_tagging_slab_free_hook(struct kmemreturn ; obj_exts =slab_obj_exts (slab); -if (!obj_exts) +if (!obj_exts) { +/* +* If obj_exts allocation failed, slab->obj_exts is set to +* OBJEXTS_ALLOC_FAIL. In this case, we end up here and should +* clear the flag. +*/ + slab->obj_exts =0 ;return ; + }for (i =0 ; i < objects; i++) {unsigned int off =obj_to_index (s, slab, p[i]);
Re: [PATCH 6.12 1374/1376] slab: reset slab->obj_ext when freeing and it is OBJEXTS_ALLOC_FAIL
Hi Greg/Sasha,
Quoted 44 lines · Greg Kroah-Hartman
6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hao Ge <[email protected]>
commit
86f54f9b6c17d6567c69e3a6fed52fdf5d7dbe93upstream.If
obj_extsallocation failed,slab->obj_extsis set toOBJEXTS_ALLOC_FAIL, But we do not clear it when freeing the slab. SinceOBJEXTS_ALLOC_FAILandMEMCG_DATA_OBJEXTScurrently share the same bit position, during the release of the associated folio, aVM_BUG_ON_FOLIO()check infolio_memcg_kmem()is triggered because theOBJEXTS_ALLOC_FAILflag was not cleared, causing it to be interpreted as a kmem folio (non-slab) withMEMCG_OBJEXTS_DATAflag set, which is invalid becauseMEMCG_OBJEXTS_DATAis supposed to be set only on slabs.Another problem that predates sharing the
OBJEXTS_ALLOC_FAILandMEMCG_DATA_OBJEXTSbits is that on configurations withis_check_pages_enabled(), the non-cleared bit inpage->memcg_datawill trigger afree_page_is_bad()failure "page still charged to cgroup"When freeing a slab, we clear
slab->obj_extsif theobj_extarray has been successfully allocated. So let's clear it also when the allocation has failed.Fixes 09c46563ff6d ("codetag: debug: introduce OBJEXTS_ALLOC_FAIL to mark failed slab_ext allocations")Fixes 7612833192d5 ("slab: Reuse first bit for OBJEXTS_ALLOC_FAIL")Cc <[email protected]>Signed-off-by Hao Ge <[email protected]>Reviewed-by Suren Baghdasaryan <[email protected]>Reviewed-by Harry Yoo <[email protected]>Signed-off-by Vlastimil Babka <[email protected]>Signed-off-by Greg Kroah-Hartman <[email protected]>--- mm/slub.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)mm/slub.c +0
-0@@ -2161,8 +2161,15 @@ alloc_tagging_slab_free_hook(struct kmemreturn ;
mm/slub.c alloc_tagging_slab_free_hook(struct kmem · line 2171
Quoted 10 lines
mm/slub.c +7
-1obj_exts =slab_obj_exts (slab); -if (!obj_exts) +if (!obj_exts) { +/* +* If obj_exts allocation failed, slab->obj_exts is set to +* OBJEXTS_ALLOC_FAIL. In this case, we end up here and should +* clear the flag. +*/ + slab->obj_exts =0 ;return ;
Hi Greg/Sasha,
I ran an AI-assisted backport review, and I have verified the report. It looks valid to me.
Upstream canonical teardown code:
obj_exts = slab_obj_exts(slab);
if (!obj_exts) {
slab->obj_exts = 0;
return;
}Downstream reviewed ordinary-free hook:
obj_exts = slab_obj_exts(slab);
if (!obj_exts) {
slab->obj_exts = 0;
return;
}The text is similar, but downstream placed it in the wrong lifecycle
function: alloc_tagging_slab_free_hook(), not free_slab_obj_exts().
The canonical change clears OBJEXTS_ALLOC_FAIL in free_slab_obj_exts() when the slab is retired. That exact fix is already present in 6.12 as 4772e7f18ac2. The reviewed patch instead clears the marker from the ordinary object-free hook while other objects in the slab can remain live.
That premature transition prevents a later successful extension allocation from marking old slots CODETAG_EMPTY and can produce false allocation-tag warnings. I suggest reverting this.
The backport is already present in 5.15.y as:
mainline : v6.18-rc2 - 86f54f9b6c17 slab: resetslab->obj_ext when freeing and it is OBJEXTS_ALLOC_FAIL
stable-6.12 : v6.12.55 - 4772e7f18ac2 slab: resetslab->obj_ext when freeing and it is OBJEXTS_ALLOC_FAIL
stable-6.17 : v6.17.5 - 8f4c0c2fa3e3 slab: resetslab->obj_ext when freeing and it is OBJEXTS_ALLOC_FAIL
thanks,
Harshit
Quoted 7 lines
mm/slub.c +1
-0+ }for (i =0 ; i < objects; i++) {unsigned int off =obj_to_index (s, slab, p[i]);
Sasha Levin
maintainerRe: [PATCH 6.12 1374/1376] slab: reset slab->obj_ext when freeing and it is OBJEXTS_ALLOC_FAIL
Quoted 2 lines
The text is similar, but downstream placed it in the wrong lifecycle
function:alloc_tagging_slab_free_hook(), notfree_slab_obj_exts().
Confirmed. The hunk anchored there because both functions open with the same two lines, so the apply found matching context in the wrong place.
The duplicate is reverted on 6.12. The correct copy of 86f54f9b6c17 ("slab:
reset slab->obj_ext when freeing and it is OBJEXTS_ALLOC_FAIL") is already in free_slab_obj_exts() on that tree, so there is nothing to reapply.
Signature · 2 lines
Thanks, Sasha
Greg Kroah-Hartman
maintainerPATCH 1375/1376 integrity: Eliminate weak definition of arch_get_secureboot()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Chancellor <[email protected]>
commit 7caedbb5ade345df0eec0bf01035c780919a9f56 upstream.
security/integrity/secure_boot.c contains a single __weak function, which breaks recordmcount when building with clang:
$ make -skj"$(nproc)" ARCH=powerpc LLVM=1 ppc64_defconfig security/integrity/secure_boot.o Cannot find symbol for section 2: .text. security/integrity/secure_boot.o: failed
Introduce a Kconfig symbol, CONFIG_HAVE_ARCH_GET_SECUREBOOT, to indicate that an architecture provides a definition of arch_get_secureboot(). Provide a static inline stub when this symbol is not defined to achieve the same effect as the __weak function, allowing secure_boot.c to be removed altogether. Move the s390 definition of arch_get_secureboot() out of the CONFIG_KEXEC_FILE block to ensure it is always available, as it does not actually depend on KEXEC_FILE.
--- arch/Kconfig | 3 +++ arch/powerpc/Kconfig | 1 + arch/s390/Kconfig | 1 + arch/s390/kernel/ipl.c | 10 +++++----- include/linux/secure_boot.h | 4 ++++ security/integrity/Makefile | 2 +- security/integrity/secure_boot.c | 16 ---------------- 7 files changed, 15 insertions(+), 22 deletions(-) delete mode 100644 security/integrity/secure_boot.c
arch/Kconfig +3 -0
@@ -1684,4 +1684,7 @@ config CC_HAS_SANE_FUNCTION_ALIGNMENT config ARCH_NEED_CMPXCHG_1_EMU bool +config HAVE_ARCH_GET_SECUREBOOT + def_bool EFI + endmenu
arch/powerpc/Kconfig +1 -0
@@ -1044,6 +1044,7 @@ config PPC_SECURE_BOOT depends on IMA_ARCH_POLICY imply IMA_SECURE_AND_OR_TRUSTED_BOOT select PSERIES_PLPKS if PPC_PSERIES + select HAVE_ARCH_GET_SECUREBOOT help Systems with firmware secure boot enabled need to define security policies to extend secure boot to the OS. This config allows a user
arch/s390/Kconfig +1 -0
@@ -153,6 +153,7 @@ config S390 select GENERIC_IOREMAP if PCI select HAVE_ALIGNED_STRUCT_PAGE select HAVE_ARCH_AUDITSYSCALL + select HAVE_ARCH_GET_SECUREBOOT select HAVE_ARCH_JUMP_LABEL select HAVE_ARCH_JUMP_LABEL_RELATIVE select HAVE_ARCH_KASAN
arch/s390/kernel/ipl.c +5 -5
@@ -2370,6 +2370,11 @@ void s390_reset_system(void) diag_amode31_ops.diag308_reset (); } +bool arch_get_secureboot (void ) +{ +return ipl_secure_flag; +} +#ifdef CONFIG_KEXEC_FILE int ipl_report_add_component(struct ipl_report *report, struct kexec_buf *kbuf,
@@ -2487,11 +2492,6 @@ out:return buf; } -bool arch_get_secureboot (void ) -{ -return ipl_secure_flag; -} -int ipl_report_free (struct ipl_report *report) {struct ipl_report_component *comp, *ncomp;
include/linux/secure_boot.h +4 -0
@@ -10,10 +10,14 @@#include <linux/types.h> +#ifdef CONFIG_HAVE_ARCH_GET_SECUREBOOT /* * Returns true if the platform secure boot is enabled. * Returns false if disabled or not supported. */ bool arch_get_secureboot (void ); +#else +static inline bool arch_get_secureboot (void ) {return false; } +#endif #endif /* _LINUX_SECURE_BOOT_H */
security/integrity/Makefile +1 -1
@@ -5,7 +5,7 @@ obj-$(CONFIG_INTEGRITY) += integrity.o -integrity-y := iint.o secure_boot.o +integrity-y := iint.o integrity-$(CONFIG_INTEGRITY_AUDIT) += integrity_audit.o integrity-$(CONFIG_INTEGRITY_SIGNATURE) += digsig.o integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
security/integrity/secure_boot.c deleted +0 -16
@@ -1,16 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -* Copyright (C) 2026 Red Hat, Inc. All Rights Reserved. -* -* Author: Coiby Xu <[email protected]> -*/ -#include <linux/secure_boot.h> - -/* -* Default weak implementation. -* Architectures that support secure boot must override this. -*/ -__weak bool arch_get_secureboot (void ) -{ -return false; -}
Greg Kroah-Hartman
maintainerPATCH 1376/1376 ACPI: processor: Add cpuidle driver check in acpi_processor_register_idle_driver()
In reply to Greg Kroah-Hartman6.12-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tony W Wang-oc <[email protected]>
commit 66c62e6773c54ce5233eb21c6d48999c3747bd13 upstream.
Commit 7a8c994cbb2d ("ACPI: processor: idle: Optimize ACPI idle driver registration") moved the ACPI idle driver registration to acpi_processor_driver_init(), but it didn't check whether a cpuidle driver was already registered.
For example, on Intel platforms, if the intel_idle driver is already loaded, the code would still evaluate the _CST object in the ACPI table and attempt to register the acpi_idle driver. This registration would fail with -EBUSY due to the existing check in cpuidle_register_driver.
Add a check at the beginning of acpi_processor_register_idle_driver() to avoid unnecessary _CST evaluate and potential registration failures.
--- drivers/acpi/processor_idle.c | 9 +++++++++ 1 file changed, 9 insertions(+)
drivers/acpi/processor_idle.c +9 -0
@@ -1386,6 +1386,15 @@ void acpi_processor_register_idle_driverint cpu;/* +* If a cpuidle driver is already registered, there is no need to +* evaluate _CST or attempt to register the ACPI idle driver. +*/ +if (cpuidle_get_driver ()) { +pr_debug ("cpuidle driver %pS already registered.\n" ,cpuidle_get_driver ()); +return ; + } + +/* * ACPI idle driver is used by all possible CPUs. * Use the processor power info of one in them to set up idle states. * Note that the existing idle handler will be used on platforms that
Am 12.09.2026 um 08:40 schrieb Greg Kroah-Hartman:
Quoted 4 lines
This is the start of the stable review cycle for the 6.12.110 release. There are 1376 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.
Builds, boots and seems to work on my 2-socket Ivy Bridge Xeon E5-2697v2 server. However, I see the following dmesg warnings in this rc1:
[ 2.357525] Driver 'sr' needs updating - please use bus_type methods ... [ 82.818407] Driver 'ses' needs updating - please use bus_type methods
These warnings are not present when booting into 6.12.109. I don't know if they are significant or not.
Beste Grüße,
Peter Schneider
Signature · 8 lines
Climb the mountain not to plant your flag, but to embrace the challenge, enjoy the air and behold the view. Climb it so you can see the world, not so the world can see you. -- David McCullough Jr. OpenPGP: 0xA3828BD796CCE11A8CADE8866E3A92C92C3FF244 Download: https://www.peters-netzplatz.de/download/pschneider1968_pub.asc https://keys.mailvelope.com/pks/lookup?op=get&[email protected] https://keys.mailvelope.com/pks/lookup?op=get&[email protected]
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 6.12.110 release. There are 1376 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.
We get build errors in -cip testing:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/pipelines/2842911949
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/jobs/16461797877
drivers/soc/ti/knav_qmss_queue.c: In function 'knav_queue_probe':drivers/soc/ti/knav_qmss_queue.c:1874:9: error: 'knav_qdev' undeclared (first use in this function); did you mean 'knav_queue'?
Best regards,
Pavel
Quoted 7 lines · Pavel Machek
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 6.12.110 release. There are 1376 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.
Quoted 7 lines
We get build errors in -cip testing:
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/pipelines/2842911949
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/jobs/16461797877
drivers/soc/ti/knav_qmss_queue.c: In function 'knav_queue_probe':drivers/soc/ti/knav_qmss_queue.c:1874:9: error: 'knav_qdev' undeclared (first use in this function); did you mean 'knav_queue'?
I am seeing the same for 6.12 and 6.18. Appears to be this commit ...
# first bad commit: [4e91398b6ae1dde1824bcf3d19b4237773f31e68] soc: ti: knav_qmss: Remove debugfs file on teardown
Jon
Signature · 1 line
nvpublic
Greg Kroah-Hartman
maintainerQuoted 11 lines · Jon Hunter
Quoted 9 lines · Pavel Machek
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 6.12.110 release. There are 1376 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.
We get build errors in -cip testing:
Quoted 8 lines
Quoted 5 lines
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/pipelines/2842911949
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/jobs/16461797877
drivers/soc/ti/knav_qmss_queue.c: In function 'knav_queue_probe':drivers/soc/ti/knav_qmss_queue.c:1874:9: error: 'knav_qdev' undeclared (first use in this function); did you mean 'knav_queue'?I am seeing the same for 6.12 and 6.18. Appears to be this commit ...
# first bad commit: [4e91398b6ae1dde1824bcf3d19b4237773f31e68] soc: ti: knav_qmss: Remove debugfs file on teardown
Sasha fixed this up, thanks.
greg k-h
Greg Kroah-Hartman wrote on Sat, Sep 12, 2026 at 08:40:26AM +0200:
Quoted 5 lines
This is the start of the stable review cycle for the 6.12.110 release. There are 1376 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.
Quoted 8 lines
Responses should be made by Mon, 14 Sep 2026 06:54:17 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.110-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.12.y
and the diffstat can be found below.
Tested 5915db8cc000 ("Linux 6.12.110-rc1") on:
- arm i.MX6ULL (Armadillo 640)
- arm64 i.MX8MP (Armadillo G4)
- arm64 i.MX8ULP (Armadillo IoT A9E)
No obvious regression in dmesg or basic tests:
(didn't actually check patch content yet, but there are way too many commits for a sunday morning so will reply again later this week if I spot anything concerning)
Signature · 1 line
Dominique Martinet
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.110 release. There are 1376 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 Mon, 14 Sep 2026 06:54:17 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.110-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.12.y
and the diffstat can be found below.thanks,
greg k-h
Tested on an amd64 laptop (Lenovo ThinkPad T14 Gen 1).
I'm seeing the same "needs updating" warnings in dmesg that Peter Schneider reported on 6.12.110-rc1 and 6.18.52-rc1, but otherwise it's working well and I have not observed any other regressions.
Signature · 1 line
-Barry K. Nathan <[email protected]>
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.110 release. There are 1376 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 Mon, 14 Sep 2026 06:54:17 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.110-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.12.y
and the diffstat can be found below.thanks,
greg k-h
Built and booted successfully on RISC-V RV64 (HiFive Unmatched).
Quoted 8 lines · On Sat, 12 Sep 2026 08:40:26 +0200 Greg Kroah-Hartman…
This is the start of the stable review cycle for the 6.12.110 release. There are 1376 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 Mon, 14 Sep 2026 06:54:17 +0000. Anything received after that time might be too late.
Boot-tested under QEMU for Rust x86_64, arm64 and riscv64; built-tested for loongarch64:
Thanks!
Cheers,
Miguel
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.110 release. There are 1376 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.
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.12.110 release. There are 1376 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 Mon, 14 Sep 2026 06:54:17 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 8 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.12.110-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.12.y
and the diffstat can be found below.thanks,
greg k-h
perf fails to build on arm/arm64/mips:
CC
/local/users/fainelli/buildroot/output/arm/build/linux-custom/tools/perf/util/symbol.o In file included from ../include/linux/build_bug.h:5,
from ../include/linux/bits.h:22,
from ../include/linux/bitops.h:14,
from util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.c:12:
util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.c: In function 'hisi_ptt_4dw_print_dw0':
util/hisi-ptt-decoder/hisi-ptt-pkt-decoder.h:28:41: warning: implicit declaration of function 'GENMASK_U32'; did you mean 'GENMASK_ULL'? [-Wimplicit-function-declaration]
28 | #define HISI_PTT_HEAD0_4DW_FORMAT GENMASK_U32(31, 30)
| ^~~~~~~~~~~
../include/linux/compiler.h:17:23: note: in definition of macro '__compiletime_assert'
17 | if (!(condition))
\
| ^~~~~~~~~
../include/linux/compiler.h:37:9: note: in expansion of macro '_compiletime_assert'
37 | _compiletime_assert(condition, msg,
__compiletime_assert_, __COUNTER__)
| ^~~~~~~~~~~~~~~~~~~Signature · 1 line
Florian