6.1.191-rc1 review
Subsystems (12)
Greg Kroah-Hartman
maintainerPATCH 1755/1887 dm cache: fix issue with background work locking
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Marzinski <[email protected]>
commit bc9781c0247de107876f32929f1637db93a42b34 upstream.
dm cache used a rw_semaphore for background_work_lock. Write locks on rw_semaphores have strict owner semantics, but there was no guarantee that the process that locked background_work_lock was the same process that unlocked it. This can be easily seen using a kernel compiled with CONFIG_DEBUG_RWSEMS. Given a dm cache device <cache>, run: 'dmsetup suspend <cache> && dmsetup resume <cache>'. This will trigger a kernel warning:
DEBUG_RWSEMS_WARN_ON((rwsem_owner(sem) != current) && !rwsem_test_oflags(sem, RWSEM_NONSPINNABLE))
triggered by cache_resume(). To fix this, switch from a rw_semaphore to a spinlock and a wait queue. dm cache already has a wait queue and associated counter, migration_wait and nr_allocated_migrations, that was getting woken up when background work was getting completed, but wasn't actually used by anything. This is replaced by the background_work queue and counter.
--- drivers/md/dm-cache-target.c | 55 +++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 27 deletions(-)
drivers/md/dm-cache-target.c +28 -27
@@ -338,8 +338,6 @@ struct cache {struct list_head invalidation_requests;sector_t migration_threshold; -wait_queue_head_t migration_wait; -atomic_t nr_allocated_migrations;/* * The number of in flight migrations that are performing
@@ -395,7 +393,11 @@ struct cache { bool loaded_mappings:1; bool loaded_discards:1; -struct rw_semaphore background_work_lock; +/* background work management */ +bool background_work_allowed; +unsigned background_work_nr; +spinlock_t background_work_lock; +wait_queue_head_t background_work_wait;struct batcher committer;struct work_struct commit_ws;
@@ -486,19 +488,13 @@ static struct dm_cache_migration *alloc_memset (mg,0 ,sizeof (*mg)); mg->cache = cache; -atomic_inc (&cache->nr_allocated_migrations);return mg; }static void free_migration (struct dm_cache_migration *mg) { -struct cache *cache = mg->cache; - -if (atomic_dec_and_test (&cache->nr_allocated_migrations)) -wake_up (&cache->migration_wait); - -mempool_free (mg, &cache->migration_pool); +mempool_free (mg, &mg->cache->migration_pool); }/*----------------------------------------------------------------*/
@@ -1029,34 +1025,39 @@ static void calc_discard_block_range(strstatic void prevent_background_work (struct cache *cache) { -lockdep_off (); -down_write (&cache->background_work_lock); -lockdep_on (); +spin_lock_irq (&cache->background_work_lock); + cache->background_work_allowed = false; +wait_event_lock_irq (cache->background_work_wait, + cache->background_work_nr ==0 , + cache->background_work_lock); +spin_unlock_irq (&cache->background_work_lock); }static void allow_background_work (struct cache *cache) { -lockdep_off (); -up_write (&cache->background_work_lock); -lockdep_on (); +spin_lock_irq (&cache->background_work_lock); + cache->background_work_allowed = true; +spin_unlock_irq (&cache->background_work_lock); }static bool background_work_begin (struct cache *cache) {bool r; -lockdep_off (); - r =down_read_trylock (&cache->background_work_lock); -lockdep_on (); - +spin_lock_irq (&cache->background_work_lock); + r = cache->background_work_allowed; +if (r) + cache->background_work_nr++; +spin_unlock_irq (&cache->background_work_lock);return r; }static void background_work_end (struct cache *cache) { -lockdep_off (); -up_read (&cache->background_work_lock); -lockdep_on (); +spin_lock_irq (&cache->background_work_lock); +if (--cache->background_work_nr ==0 ) +wake_up (&cache->background_work_wait); +spin_unlock_irq (&cache->background_work_lock); }/*----------------------------------------------------------------*/
@@ -2517,9 +2518,7 @@ static int cache_create(struct cache_argspin_lock_init (&cache->lock);bio_list_init (&cache->deferred_bios); -atomic_set (&cache->nr_allocated_migrations,0 );atomic_set (&cache->nr_io_migrations,0 ); -init_waitqueue_head (&cache->migration_wait); r = -ENOMEM ;atomic_set (&cache->nr_dirty,0 );
@@ -2601,8 +2600,10 @@ static int cache_create(struct cache_arg issue_op, cache, cache->wq);dm_iot_init (&cache->tracker); -init_rwsem (&cache->background_work_lock); -prevent_background_work (cache); +init_waitqueue_head (&cache->background_work_wait); +spin_lock_init (&cache->background_work_lock); + cache->background_work_allowed = false; + cache->background_work_nr =0 ; *result = cache;return 0 ;
Greg Kroah-Hartman
maintainerPATCH 1756/1887 dm-crypt: fix a tiny race condition in crypt_dec_pending
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ben Cressey <[email protected]>
commit 148845aa1921d95ef5dc851c76e6a284f6657df6 upstream.
crypt_dec_pending reads io->error before calling atomic_dec_and_test. Another context, for example crypt_endio called from an interrupt, may set io->error and drop its reference between the read and the decrement. crypt_dec_pending then drops the last reference and completes the bio with the stale status - so a read that failed and was never decrypted, or a write that failed, is reported as successful.
The read was placed before the decrement by commit b35f8caa0890 ("dm
crypt: wait for endio to complete before destruction"), because that commit freed dm_crypt_io before calling bio_endio. This is no longer the case, dm_crypt_io lives in the per-bio data now.
Read io->error after atomic_dec_and_test instead. atomic_dec_and_test is fully ordered, so no additional barrier is needed.
--- drivers/md/dm-crypt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/md/dm-crypt.c +1 -2
@@ -1758,7 +1758,6 @@ static void crypt_dec_pending(struct dm_ {struct crypt_config *cc = io->cc;struct bio *base_bio = io->base_bio; -blk_status_t error = io->error;if (!atomic_dec_and_test (&io->io_pending))return ;
@@ -1780,7 +1779,7 @@ static void crypt_dec_pending(struct dm_else kfree (io->integrity_metadata); - base_bio->bi_status = error; + base_bio->bi_status = io->error;bio_endio (base_bio); }
Greg Kroah-Hartman
maintainerPATCH 1757/1887 dm-ebs: fix incorrect device offset check in ebs_ctr()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Genjian Zhang <[email protected]>
commit 7ac81e2d2240f2c57bd073b0733e0b2abca38e82 upstream.
<offset> is a backing-device sector offset; ti->len is the virtual target length. Comparing them rejects valid tables, e.g.:
dmsetup create ebs0 --table "0 1048576 ebs /dev/sda 2097152 1 8" -> ebs: Invalid device offset sector (-EINVAL)
Drop the check. Bounds against the backing device are already enforced later by device_area_is_invalid() via ebs_iterate_devices().
--- drivers/md/dm-ebs-target.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/md/dm-ebs-target.c +1 -2
@@ -264,8 +264,7 @@ static int ebs_ctr(struct dm_target *ti, r = -EINVAL ;if (sscanf (argv[1 ],"%llu%c" , &tmp, &dummy) !=1 || - tmp != (sector_t )tmp || - (sector_t )tmp >= ti->len) { + tmp != (sector_t )tmp) { ti->error ="Invalid device offset sector" ; goto bad; }
Greg Kroah-Hartman
maintainerPATCH 1758/1887 net/iucv: fix the recvmsg window update
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit fa5acd038ea657ad5033713d6916214cbd349151 upstream.
iucv_sock_recvmsg() sends the HiperSockets-only AF_IUCV_FLAG_WIN without testing the transport, so on a classic z/VM socket iucv_send_ctrl() sizes the skb through a NULL iucv->hs_dev. SO_MSGLIMIT accepts 1, so msglimit / 2 is zero and one recvmsg() on its own socket is enough for an unprivileged process to take a spurious disconnect.
It also calls iucv_send_ctrl() under spin_lock_bh(&message_q.lock), which allocates GFP_KERNEL inside a section the code treats as atomic. Sending outside that lock lets two recvmsg() reach afiucv_hs_send() at once, where msg_recv is sampled for the advertised window and subtracted after dev_queue_xmit() -- and sendmsg reaches that counter under lock_sock() while recvmsg holds no socket lock, so both can subtract the same value, the counter goes negative and the credit reaches the peer twice.
Test the transport, claim the credit with atomic_xchg() after the last error exit and hand it back if the transmit fails, and send once the lock is dropped.
--- net/iucv/af_iucv.c | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-)
net/iucv/af_iucv.c +25 -17
@@ -207,12 +207,6 @@ static int afiucv_hs_send(struct iucv_me phs_hdr->flags = flags;if (flags ==AF_IUCV_FLAG_SYN ) phs_hdr->window = iucv->msglimit; -else if ((flags ==AF_IUCV_FLAG_WIN ) || !flags) { - confirm_recv =atomic_read (&iucv->msg_recv); - phs_hdr->window = confirm_recv; -if (confirm_recv) - phs_hdr->flags = phs_hdr->flags |AF_IUCV_FLAG_WIN ; - }memcpy (phs_hdr->destUserID, iucv->dst_user_id,8 );memcpy (phs_hdr->destAppName, iucv->dst_name,8 );memcpy (phs_hdr->srcUserID, iucv->src_user_id,8 );
@@ -247,13 +241,22 @@ static int afiucv_hs_send(struct iucv_me } skb->protocol =cpu_to_be16 (ETH_P_AF_IUCV ); +/* Claim the receive credit here, not while building the header: every +* way this frame can be dropped has now been ruled out, so the window +* is zeroed only for as long as the transmit itself takes. +*/ +if (flags ==AF_IUCV_FLAG_WIN || !flags) { + confirm_recv =atomic_xchg (&iucv->msg_recv,0 ); + phs_hdr->window = confirm_recv; +if (confirm_recv) + phs_hdr->flags = phs_hdr->flags |AF_IUCV_FLAG_WIN ; + } +atomic_inc (&iucv->skbs_in_xmit); err =dev_queue_xmit (skb);if (net_xmit_eval (err)) {atomic_dec (&iucv->skbs_in_xmit); - }else { -atomic_sub (confirm_recv, &iucv->msg_recv); -WARN_ON (atomic_read (&iucv->msg_recv) <0 ); +atomic_add (confirm_recv, &iucv->msg_recv); }return net_xmit_eval (err);
@@ -1239,6 +1242,7 @@ static int iucv_sock_recvmsg(struct sockstruct iucv_sock *iucv =iucv_sk (sk);unsigned int copied, rlen;struct sk_buff *skb, *rskb, *cskb; +bool send_win = false;int err =0 ;u32 offset;
@@ -1329,16 +1333,20 @@ static int iucv_sock_recvmsg(struct sockif (skb_queue_empty (&iucv->backlog_skb_q)) {if (!list_empty (&iucv->message_q.list))iucv_process_message_q (sk); -if (atomic_read (&iucv->msg_recv) >= - iucv->msglimit /2 ) { - err =iucv_send_ctrl (sk,AF_IUCV_FLAG_WIN ); -if (err) { - sk->sk_state =IUCV_DISCONN ; - sk->sk_state_change (sk); - } - } +if (iucv->transport ==AF_IUCV_TRANS_HIPER && +atomic_read (&iucv->msg_recv) >= + iucv->msglimit /2 ) + send_win = true; }spin_unlock_bh (&iucv->message_q.lock); + +if (send_win) { + err =iucv_send_ctrl (sk,AF_IUCV_FLAG_WIN ); +if (err) { + sk->sk_state =IUCV_DISCONN ; + sk->sk_state_change (sk); + } + } } done:
Greg Kroah-Hartman
maintainerPATCH 1759/1887 xfs: fix capability check in xfs
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Carlos Maiolino <[email protected]>
commit e2f62a9744ebad3bcb6347a648e615026e9efeff upstream.
An user reported a bug where he managed to evade group's quota by changing a file's gid to a different group id the same user belonged to, even though quotas were enforced on both gids and the file's size was big enough to exceed the quota's hardlimit.
Commit eba0549bc7d1 replaced a capable() call by a has_capability_noaudit() to prevent unnecessary selinux audit messages. Turns out that both calls have slightly different semantics even though their documentation seems similar. Where in a nutshell:
capable() - Tests the task's effective credentials has_ns_capability_noaudit() - Tests the task's real credentials
This most of the time has no practical difference but in some cases like changing attrs (specifically group id in this case) through a NFS client this will allow the quota code to use XFS_QMOPT_FORCE_RES, effectively bypassing quota accounting checks.
Using instead ns_capable_noaudit() should fix this issue and prevent selinux audit messages.
This also fix the remaining calls to has_capability_noaudit()
--- fs/xfs/xfs_fsmap.c | 2 +- fs/xfs/xfs_ioctl.c | 2 +- fs/xfs/xfs_iops.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-)
fs/xfs/xfs_fsmap.c +1 -1
@@ -902,7 +902,7 @@ xfs_getfsmap(return -EINVAL ; use_rmap =xfs_has_rmapbt (mp) && -has_capability_noaudit (current,CAP_SYS_ADMIN ); +ns_capable_noaudit (&init_user_ns,CAP_SYS_ADMIN ); head->fmh_entries =0 ;/* Set up our device handlers. */
fs/xfs/xfs_ioctl.c +1 -1
@@ -1222,7 +1222,7 @@ xfs_ioctl_setattr_get_trans( goto out_error; error =xfs_trans_alloc_ichange (ip,NULL ,NULL , pdqp, -has_capability_noaudit (current,CAP_FOWNER ), &tp); +ns_capable_noaudit (&init_user_ns,CAP_FOWNER ), &tp);if (error) goto out_error;
fs/xfs/xfs_iops.c +1 -1
@@ -707,7 +707,7 @@ xfs_setattr_nonsize( } error =xfs_trans_alloc_ichange (ip, udqp, gdqp,NULL , -has_capability_noaudit (current,CAP_FOWNER ), &tp); +ns_capable_noaudit (&init_user_ns,CAP_FOWNER ), &tp);if (error) goto out_dqrele;
Greg Kroah-Hartman
maintainerPATCH 1760/1887 tipc: protect node reset trace dump with node lock
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chengfeng Ye <[email protected]>
commit dddf197f29ba5e47a476dde82bf542ca2e0d5e5e upstream.
The tipc_node_reset_links trace event asks tipc_node_dump() to walk the node's link entries. Unlike the other node events that request link data, this event runs without the node lock.
This permits bearer teardown to free a link while the trace callback is dumping it:
CPU 0 CPU 1
trace_tipc_node_reset_links()
tipc_node_dump()
l = n->links[0].link
tipc_node_write_lock()
kfree(l)
n->links[0].link = NULL
tipc_node_write_unlock()
tipc_link_dump(l)tipc_link_dump() then dereferences the stale pointer. KASAN reported:
BUG: KASAN: slab-use-after-free in tipc_link_dump Read of size 4 by task poc/115 Call Trace: tipc_link_dump+0x10cb/0x16b0 tipc_node_dump+0x4bb/0x740 trace_event_raw_event_tipc_node_class+0x258/0x360 tipc_node_reset_links+0x14d/0x1a0 tipc_rcv+0x13f5/0x3030 tipc_udp_recv+0x4e3/0x670 Allocated by task 0: tipc_link_create+0x1e1/0x1020 tipc_node_check_dest+0x7d2/0x11a0 tipc_disc_rcv+0xdbf/0x1430 Freed by task 89: kfree+0x131/0x3c0 tipc_node_link_down+0x267/0x4b0 tipc_node_delete_links+0xec/0x160 bearer_disable+0x107/0x260
Take the node write lock around the trace event. This serializes the dump against tipc_node_link_down(delete=true), which frees the link under the same write lock.
--- net/tipc/node.c | 2 ++ 1 file changed, 2 insertions(+)
net/tipc/node.c +2 -0
@@ -1335,7 +1335,9 @@ static void tipc_node_reset_links(structpr_warn ("Resetting all links to %x\n" , n->addr); +tipc_node_write_lock (n);trace_tipc_node_reset_links (n, true," " ); +tipc_node_write_unlock_fast (n);for (i =0 ; i <MAX_BEARERS ; i++) {tipc_node_link_down (n, i, false); }
Greg Kroah-Hartman
maintainerPATCH 1761/1887 sctp: validate chunk length in the inqueue parser
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Charles Vosburgh <[email protected]>
commit 6cfc1b90cb86f4aabc69fb8e30128e07e2cdfa3a upstream.
SCTP chunks always include a four-byte generic header, but sctp_inq_pop() currently accepts shorter declared lengths. A zero-length chunk leaves chunk_end at the current header.
When ASCONF is covered by the association's SCTP-AUTH policy, sctp_assoc_bh_rcv() can continue before the state machine performs its normal chunk-length check. sctp_inq_pop() then returns the same malformed chunk repeatedly and the receive softirq can lock up.
A remote SCTP peer can trigger this after establishing an association on a kernel built with CONFIG_IP_SCTP and configured with net.sctp.addip_enable=1 and net.sctp.auth_enable=1. The reproducer did not require application credentials, a shared SCTP AUTH key, or net.sctp.addip_noauth_enable=1.
On commit f967455fb2a5 ("seg6: reset IP6CB after IPv6 decapsulation"), one zero-length ASCONF caused repeated
watchdog soft-lockup reports in a two-vCPU KVM guest. All 3 pre-trigger health probes succeeded, while 36 of 37 post-trigger probes failed. With this change, all 37 post-trigger probes succeeded and no equivalent soft-lockup signature appeared.
Reject chunks shorter than the generic SCTP header at the shared inqueue parser boundary. Mark the packet for discard before either caller can continue processing it, while preserving the four-byte generic minimum. Declared-length 1 through 4 controls and kernel-generated ASCONF traffic remained healthy. The patched sctp_hello selftest passed for IPv4 and IPv6.
The complete private reproducer and validation evidence are available directly to maintainers on request.
--- net/sctp/inqueue.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/sctp/inqueue.c +4 -2
@@ -212,8 +212,10 @@ new_skb: chunk->chunk_end = ((__u8 *)ch) +SCTP_PAD4 (ntohs (ch->length));skb_pull (chunk->skb,sizeof (*ch)); chunk->subh.v =NULL ;/* Subheader is no longer valid. */ - -if (chunk->chunk_end +sizeof (*ch) <=skb_tail_pointer (chunk->skb)) { +if (unlikely (ntohs (ch->length) <sizeof (*ch))) { + chunk->pdiscard =1 ; + }else if (chunk->chunk_end +sizeof (*ch) <= +skb_tail_pointer (chunk->skb)) {/* This is not a singleton */ chunk->singleton =0 ; }else if (chunk->chunk_end >skb_tail_pointer (chunk->skb)) {
Greg Kroah-Hartman
maintainerPATCH 1762/1887 page_pool: keep frag_offset aligned for odd-sized requests
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Schauer <[email protected]>
commit dc0df5a0c62ccea1d0e08d39a4dc9064de81d411 upstream.
page_pool_alloc_frag_netmem() rounds the requested fragment size with
size = ALIGN(size, dma_get_cache_alignment());
dma_get_cache_alignment() returns 1 unless the architecture defines ARCH_DMA_MINALIGN, which DMA-coherent architectures such as x86 do not. There the ALIGN() is a no-op and pool->frag_offset advances by the raw, unrounded size.
A single caller asking for an odd size then leaves frag_offset misaligned for every fragment carved out of that page afterwards. The pool is shared, so the damage is not confined to the caller that caused it.
The per-cpu system_page_pool used by generic XDP hits this. skb_pp_cow_data() allocates its fragments with the raw packet length:
size = min_t(u32, len, PAGE_SIZE); truesize = size; page = page_pool_dev_alloc(pool, &page_off, &truesize);
leaving frag_offset odd for whatever is carved out of that page next. Its own head allocation is already aligned -- SKB_HEAD_ALIGN(size) plus the XDP_PACKET_HEADROOM its callers pass -- so it is a later user of the shared pool that pays: page_pool_dev_alloc_va() returns a misaligned buffer, napi_build_skb() installs it as skb->head, and skb_shinfo(skb) == skb->head + skb->end is misaligned with it.
skb_shinfo()->dataref is a 4-byte atomic_t at offset 0x20, so the atomic_inc() in __skb_clone() straddles a cache line. On x86 with split lock detection -- fatal for kernel split locks by default -- this panics the machine:
Oops: Split lock detected RIP: 0010:skb_clone+0x154/0x1e0 Call Trace: <IRQ> raw_local_deliver+0x1ed/0x2c0 ip_protocol_deliver_rcu+0x54/0x1c0 ip_local_deliver_finish+0x85/0x100 ip_local_deliver+0x67/0x100 __netif_receive_skb_one_core+0x85/0xa0 process_backlog+0x87/0x130
Reproduced by attaching any generic-mode XDP program to loopback and opening a RAW IPPROTO_UDP socket, which makes raw_local_deliver() clone every locally delivered UDP packet; ordinary DNS traffic then triggers it, roughly once per 2500 clones. Observed on 6.12.101 and 7.1.8.
Tracing page_pool_alloc_frag_netmem() over one such run shows the amplification -- two odd-sized requests, nine misaligned offsets:
requested size & 7: 0: 17035 5: 1 7: 1 frag_offset & 7: 0: 17028 3: 1 4: 1 5: 1 6: 1 7: 5
and skb_pp_cow_data() returning heads that were aligned on entry:
head 0xffff8f4c86aeac00 -> 0xffff8f4c53a9a9c4 (&7=4) head 0xffff8f4d6a8a42c0 -> 0xffff8f4c4f7b7a45 (&7=5)
Round the fragment size up to at least the alignment struct skb_shared_info requires, so fragments are always suitably aligned for the objects callers build on them. Architectures needing a larger DMA alignment keep it.
This also makes the remainder computed in page_pool_alloc_netmem(),
*size = max_size - *offset;
aligned, since max_size is a power of two -- which fixes the matching misalignment of skb->end.
Verified with a controlled A/B under QEMU/KVM: same tree, same config, same compiler, same rootfs and identical traffic, differing only by this patch. A SEC("xdp.frags") XDP_PASS program on lo plus UDP datagrams larger than max_head_size drives skb_pp_cow_data()'s fragment loop, which passes raw packet lengths to the pool. Measured at the return of skb_pp_cow_data():
unpatched patched
skb_pp_cow_data calls 40800 40800
misaligned skb->head 1120 0
dataref at line offset >60 80 0
The last row counts the accesses that actually fault:
skb_shinfo()->dataref sits at head+end+0x20 and is a 4-byte atomic, so lock incl splits a 64-byte cache line only when that address lands at offset 61..63. All 80 occurrences were at offset 61; the panic reported above was at offset 62. Eliminating the misalignment removes every one of them.
Same class of bug as commit 3bed3cc4156e ("net: Do not allocate page fragments that are not skb aligned"), which fixed the older netdev_alloc_frag()/napi_alloc_frag() allocators.
--- net/core/page_pool.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/core/page_pool.c +2 -1
@@ -727,7 +727,8 @@ struct page *page_pool_alloc_frag(struct size > max_size))return NULL ; - size =ALIGN (size,dma_get_cache_alignment ()); + size = ALIGN(size, max_t(unsigned int, dma_get_cache_alignment(), + __alignof__(struct skb_shared_info ))); *offset = pool->frag_offset;if (page && *offset + size > max_size) {
Greg Kroah-Hartman
maintainerPATCH 1763/1887 s390/ctcm: Prevent XID null dereference
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aswin Karuvally <[email protected]>
commit b264d8422779d69febce914efc47a92a85cc382c upstream.
The mpc_validate_xid() function sets grp->saved_xid2->xid2_flag2 to 0x40 to signal XID validation error. If peer XID is NULL or r/w channel pairing mismatch happens, grp->saved_xid2 is never initialized. An attempt to set the flag in such case leads to NULL dereference.
Fix this by using the always available priv->xid->xid2_flag2 instead of grp->saved_xid2->xid2_flag2 for validation errors.
--- drivers/s390/net/ctcm_mpc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/s390/net/ctcm_mpc.c +1 -2
@@ -824,7 +824,7 @@ static void mpc_action_go_ready(fsm_instfsm_deltimer (&grp->timer); -if (grp->saved_xid2->xid2_flag2 ==0x40 ) { +if (priv->xid->xid2_flag2 ==0x40 ) { priv->xid->xid2_flag2 =0x00 ;if (grp->estconnfunc) { grp->estconnfunc(grp->port_num, 1,
@@ -1633,7 +1633,6 @@ done:"The XID used in the MPC protocol is not valid, " "rc = %d\n", rc); priv->xid->xid2_flag2 =0x40 ; - grp->saved_xid2->xid2_flag2 =0x40 ; }return rc;
Greg Kroah-Hartman
maintainerPATCH 1764/1887 s390/pci: Fix leak of uninitialized kernel data in SCLP report
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Niklas Schnelle <[email protected]>
commit 8ac60ae2a307a50b599bf5d300b448d638f3ba29 upstream.
While report_error_write() checks that the provided buffer is at least as large as the header struct, but not that it is large enough to contain the report with the length claimed by report->length. If user-space provides a short buffer, meaning a larger report->length than the actually written payload, up to around 4K of kernel data from past the kmalloc(len + 1) sized buffer allocated in kernfs_fop_write_iter() will leak into the SCLP report.
However, as the entity processing the SCLP is privileged and able to access at least the page including the report, this does not leak data that entity could not access but it is still an out of bounds read and a malformed error report that should be rejected.
--- arch/s390/pci/pci_sysfs.c | 3 +++ 1 file changed, 3 insertions(+)
arch/s390/pci/pci_sysfs.c +3 -0
@@ -146,6 +146,9 @@ static ssize_t report_error_write(structif (off || (count <sizeof (*report)))return -EINVAL ; +if (count < (report->length +sizeof (*report))) +return -EINVAL ; + ret =sclp_pci_report (report, zdev->fh, zdev->fid);return ret ? ret : count;
Greg Kroah-Hartman
maintainerPATCH 1765/1887 ipv4: avoid divide by zero in fib_rebalance
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zihan Xi <[email protected]>
commit 5046d2880fec7d49ebed2fd2866747ee1d06ad71 upstream.
fib_rebalance() computes the total eligible nexthop weight in one pass and programs upper bounds in a second pass. A concurrent change to ignore_routes_with_linkdown can make the first pass return zero while the second pass sees an eligible nexthop, resulting in division by zero.
If the first pass reports a zero total, set each nexthop upper bound to -1 and skip the division. This matches the IPv6 fix in commit d2c26c2911dd ("ipv6: avoid divide by zero in rt6_multipath_rebalance") and preserves the lock-free rebalance path.
--- net/ipv4/fib_semantics.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/fib_semantics.c +1 -1
@@ -857,7 +857,7 @@ static void fib_rebalance(struct fib_infchange_nexthops (fi) {int upper_bound; -if (nexthop_nh->fib_nh_flags &RTNH_F_DEAD ) { +if (!total || nexthop_nh->fib_nh_flags &RTNH_F_DEAD ) { upper_bound =-1 ; }else if (ip_ignore_linkdown (nexthop_nh->fib_nh_dev) && nexthop_nh->fib_nh_flags &RTNH_F_LINKDOWN ) {
Greg Kroah-Hartman
maintainerPATCH 1766/1887 drm/amdgpu: Fix VCE 3 ring align_mask
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Rosca <[email protected]>
[ Upstream commit 2ee9836545e690c9e66ec203445d7705959fd7a8 ]
The largest frame is 20 dwords, so 0xf mask is too small. This was always wrong, but we were lucky with the VCE_CMD_END commands inserted after fence and vm_flush.
--- drivers/gpu/drm/amd/amdgpu/vce_v3_0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +1 -1
@@ -959,7 +959,7 @@ static const struct amdgpu_ring_funcs vce_v3_0_ring_phys_funcs = {static const struct amdgpu_ring_funcs vce_v3_0_ring_vm_funcs = { .type =AMDGPU_RING_TYPE_VCE , - .align_mask =0xf , + .align_mask =0x1f , .nop =VCE_CMD_NO_OP , .support_64bit_ptrs = false, .no_user_fence = true,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1767/1887 mm/huge_memory: initialise workingset state before folio split
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matt Fleming <[email protected]>
[ Upstream commit aca1f2d5de17e138bc6c4859126b77e516b82541 ]
xas_try_split() adds __GFP_ACCOUNT for page-cache xa_nodes, but __folio_split() leaves the xa_state's xa_lru unset. That lets a live, memcg-charged xa_node exist without being linked into the mapping's shadow_nodes list_lru; when reclaim later walks the list_lru it trips VM_WARN_ON(!css_is_dying()).
Use mapping_set_update() to install both the workingset update callback and the shadow_nodes list_lru on the xa_state.
--- mm/huge_memory.c | 2 ++ 1 file changed, 2 insertions(+)
mm/huge_memory.c +2 -0
@@ -2750,6 +2750,8 @@ int split_huge_page_to_list(struct page *page, struct list_head *list) goto out; } +mapping_set_update (&xas, mapping); +xas_split_alloc (&xas, folio,folio_order (folio), gfp);if (xas_error (&xas)) { ret =xas_error (&xas);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1768/1887 KVM: x86/mmu: Preserve nested TDP shadow page tables if they are used as roots
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hyunwoo Kim <[email protected]>
[ Upstream commit 7a2c70e777a00c32ebafd376a6fe31ebb91c5b20 ]
kvm_mmu_zap_oldest_mmu_pages() excludes a shadow page whose root_count is non-zero from top-level reclaim, because such a page cannot be freed. The path in mmu_page_zap_pte() that recursively zaps a parentless nested TDP child has no such check. As a result, a shadow page can be zapped even if the page itself can't be freed; as the comment in kvm_mmu_zap_oldest_mmu_pages() notes, zapping it will just force vCPUs to rebuild the page.
As in top-level reclaim, do not recursively prepare zapping of a nested TDP child whose root_count is non-zero.
--- arch/x86/kvm/mmu/mmu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/x86/kvm/mmu/mmu.c +3 -1
@@ -2395,7 +2395,9 @@ static int mmu_page_zap_pte(struct kvm *kvm, struct kvm_mmu_page *sp,* avoids retaining a large number of stale nested SPs. */ if (tdp_enabled && invalid_list && - child->role.guest_mode && !child->parent_ptes.val) + child->role.guest_mode && + !child->root_count && + !child->parent_ptes.val)return kvm_mmu_prepare_zap_page (kvm, child, invalid_list); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1769/1887 mm, madvise: fix potential workingset node list_lru leaks
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kairui Song <[email protected]>
[ Upstream commit 62e72d2cf702a5e2fb53d9c46ed900d9384e4a06 ]
Since commit 5abc1e37afa0 ("mm: list_lru: allocate list_lru_one only when needed"), all list_lru users need to allocate the items using the new infrastructure that provides list_lru info for slab allocation, ensuring that the corresponding memcg list_lru is allocated before use.
For workingset shadow nodes (which are xa_node), users are converted to use the new infrastructure by commit 9bbdc0f32409 ("xarray: use kmem_cache_alloc_lru to allocate xa_node"). The xas->xa_lru will be set correctly for filemap users. However, there is a missing case: xa_node allocations caused by madvise(..., MADV_COLLAPSE).
madvise(..., MADV_COLLAPSE) will also read in the absent parts of file map, and there will be xa_nodes allocated for the caller's memcg (assuming it's not rootcg). However, these allocations won't trigger memcg list_lru allocation because the proper xas info was not set.
If nothing else has allocated other xa_nodes for that memcg to trigger list_lru creation, and memory pressure starts to evict file pages, workingset_update_node will try to add these xa_nodes to their corresponding memcg list_lru, and it does not exist (NULL). So they will be added to rootcg's list_lru instead.
This shouldn't be a significant issue in practice, but it is indeed unexpected behavior, and these xa_nodes will not be reclaimed effectively. And may lead to incorrect counting of the list_lru->nr_items counter.
This problem wasn't exposed until recent commit 28e98022b31ef ("mm/list_lru: simplify reparenting and initial allocation") added a sanity check: only dying memcg could have a NULL list_lru when list_lru_{add,del} is called. This problem triggered this WARNING.
So make madvise(..., MADV_COLLAPSE) also call xas_set_lru() to pass the list_lru which we may want to insert xa_node into later. And move mapping_set_update to mm/internal.h, and turn into a macro to avoid including extra headers in mm/internal.h.
--- mm/khugepaged.c | 3 +++ 1 file changed, 3 insertions(+)
mm/khugepaged.c +3 -0
@@ -19,6 +19,7 @@#include <linux/page_table_check.h> #include <linux/swapops.h> #include <linux/shmem_fs.h> +#include <linux/dax.h> #include <asm/tlb.h> #include <asm/pgalloc.h>
@@ -1788,6 +1789,8 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,if (result !=SCAN_SUCCEED ) goto out; +mapping_set_update (&xas, mapping); +/* * Ensure we have slots for all the pages in the range. This is * almost certainly a no-op because most of the pages must be present
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1770/1887 net: bridge: mcast: dont truncate the port group walk on teardown
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jun Yang <[email protected]>
commit 5a3f7a683aee56e1f15c9d53041f3236767eaae7 upstream.
__br_multicast_disable_port_ctx() and br_multicast_del_port() walk port->mglist with hlist_for_each_entry_safe(). However, br_multicast_find_del_pg() can also delete other entries from the same list through br_multicast_fwd_src_remove() or __fwd_del_star_excl().
If such an entry is the iterator's saved next node, hlist_del_init() clears its ->next and terminates the walk early. The reproducer triggers this in both teardown walks, leaving port groups in the bridge mdb with a dangling ->key.port after del_nbp() frees the port:
BUG: KASAN: slab-use-after-free in __mdb_fill_info+0x1191/0x1320 __mdb_fill_info+0x1191/0x1320 br_mdb_dump+0x594/0xe40 rtnl_mdb_dump+0x1cf/0x5d0
Use hlist_del_init_rcu() to unlink the group while preserving ->next. br_multicast_del_pg() and the teardown walks run under br->multicast_lock. The GC worker must acquire the same lock before detaching the group for destruction, so the node remains alive while the walk uses the preserved pointer.
Preserving ->next means a walk can now reach a group that an earlier iteration already deleted as a side effect. That group is off mp->ports, so br_multicast_find_del_pg() would fall through its port scan and hit the trailing WARN_ON(1). Skip such groups at the top of that helper: a port group is put on port->mglist when it is created and only unlinked when it is deleted, so hlist_unhashed() identifies exactly this case.
--- net/bridge/br_multicast.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-)
net/bridge/br_multicast.c +12 -1
@@ -689,7 +689,11 @@ static void __br_multicast_del_pg(structstruct hlist_node *tmp;rcu_assign_pointer (*pp, pg->next); -hlist_del_init (&pg->mglist); +/* Keep ->next (held under multicast_lock, freed later by the GC work): +* a port->mglist teardown walk may have latched this node as its next, +* and deleting other groups of the same port must not truncate it. +*/ +hlist_del_init_rcu (&pg->mglist);br_multicast_eht_clean_sets (pg);hlist_for_each_entry_safe (ent, tmp, &pg->src_list, node)br_multicast_del_group_src (ent, false);
@@ -723,6 +727,13 @@ static void br_multicast_find_del_pg(strstruct net_bridge_mdb_entry *mp;struct net_bridge_port_group *p; +/* A teardown walk over port->mglist can reach a group that an earlier +* iteration already deleted as a side effect. It is off mp->ports by +* now, so skip it instead of falling through to the WARN_ON() below. +*/ +if (hlist_unhashed (&pg->mglist)) +return ; + mp =br_mdb_ip_get (br, &pg->key.addr);if (WARN_ON (!mp))return ;
Greg Kroah-Hartman
maintainerPATCH 1771/1887 ksmbd: fill in FileSysIdentifier in FS_POSIX_INFORMATION
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Khromov <[email protected]>
commit db2267b27c054a6c2151ff7fbb67927e784f31d6 upstream.
smb2_get_info_filesystem() reports 56 bytes for FS_POSIX_INFORMATION, that is the whole of FILE_SYSTEM_POSIX_INFO, but never assigns FileSysIdentifier. Those eight bytes go to the client as they are found in the response buffer.
The buffer is zeroed on allocation, so a standalone request leaks nothing. A compound request can leak: the offset of the next response is advanced by the length pinned for the previous one, so a reply that was written into the buffer and then dropped in favour of the short error response of smb2_set_err_rsp() stays there, and the next reply is laid over it with only the header cleared.
Report the file system id statfs() returned, which is what the field is for. FileSysIdentifier is __le64 and f_fsid is a pair of ints, so assemble the value first, val[0] as the low half, and convert it on the way out.
--- fs/smb/server/smb2pdu.c | 3 +++ 1 file changed, 3 insertions(+)
fs/smb/server/smb2pdu.c +3 -0
@@ -5342,6 +5342,9 @@ static int smb2_get_info_filesystem(stru info->UserBlocksAvail =cpu_to_le64 (stfs.f_bavail); info->TotalFileNodes =cpu_to_le64 (stfs.f_files); info->FreeFileNodes =cpu_to_le64 (stfs.f_ffree); + info->FileSysIdentifier = +cpu_to_le64 ((u64 )(u32 )stfs.f_fsid.val[1 ] <<32 | + (u32 )stfs.f_fsid.val[0 ]); rsp->OutputBufferLength =cpu_to_le32 (56 ); }break ;
Greg Kroah-Hartman
maintainerPATCH 1772/1887 ksmbd: initialize FileSystemControlFlags in FS_CONTROL_INFORMATION
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Khromov <[email protected]>
commit c0cd3fc6824122014da2b3b0cb7ddeaa2946ec8e upstream.
smb2_get_info_filesystem() reports 48 bytes for FS_CONTROL_INFORMATION, that is the whole of struct smb2_fs_control_info, but never assigns FileSystemControlFlags. Those four bytes go to the client as they are found in the response buffer.
The buffer is zeroed on allocation, so a standalone request leaks nothing. A compound request can leak: the offset of the next response is advanced by the length pinned for the previous one, so a reply that was written into the buffer and then dropped in favour of the short error response of smb2_set_err_rsp() stays there, and the next reply is laid over it with only the header cleared.
ksmbd does not implement quota tracking, so report no control flags.
--- fs/smb/server/smb2pdu.c | 1 + 1 file changed, 1 insertion(+)
fs/smb/server/smb2pdu.c +1 -0
@@ -5321,6 +5321,7 @@ static int smb2_get_info_filesystem(stru info->FreeSpaceStopFiltering =0 ; info->DefaultQuotaThreshold =cpu_to_le64 (SMB2_NO_FID ); info->DefaultQuotaLimit =cpu_to_le64 (SMB2_NO_FID ); + info->FileSystemControlFlags =0 ; info->Padding =0 ; rsp->OutputBufferLength =cpu_to_le32 (48 );break ;
Greg Kroah-Hartman
maintainerPATCH 1773/1887 ksmbd: zero the FS_OBJECT_ID_INFORMATION buffer before filling it in
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aleksandr Khromov <[email protected]>
commit 399aa12450a61a5c73dc77e73f069ece9687c95d upstream.
smb2_get_info_filesystem() reports 64 bytes for FS_OBJECT_ID_INFORMATION, that is the whole of struct object_id_info, but writes only 46 of them:
- objid[] is 16 bytes, and when the volume UUID is not available only sizeof(stfs.f_fsid) (8) bytes are copied into it;
- extended_info.version_string[] is STRING_LENGTH (28) bytes, and only strlen("1.1.0") (5) bytes are copied into it.
The response buffer is zeroed on allocation (kvzalloc() in smb2_allocate_rsp_buf()), so for a standalone request the remaining 31 bytes are zero. In a compound request they need not be. The offset of the next response is advanced by the length pinned for the previous one, so if a preceding command wrote its reply into the buffer and then failed, smb2_set_err_rsp() pins only the short error response and the next reply lands inside the area that has already been written. Only the header is cleared there:
memset((char *)rsp_hdr, 0, sizeof(struct smb2_hdr) + 2);
The client then receives up to 31 bytes of a response it was not meant to see, including one that failed with an access denied error.
Clear the structure before filling it in. As a side effect version_string is now NUL terminated.
--- fs/smb/server/smb2pdu.c | 1 + 1 file changed, 1 insertion(+)
fs/smb/server/smb2pdu.c +1 -0
@@ -5267,6 +5267,7 @@ static int smb2_get_info_filesystem(strustruct object_id_info *info; info = (struct object_id_info *)(rsp->Buffer); +memset (info,0 ,sizeof (*info));if (!uuid_is_null (&path.mnt->mnt_sb->s_uuid)) memcpy(info->objid, path.mnt->mnt_sb->s_uuid.b,
Greg Kroah-Hartman
maintainerPATCH 1774/1887 net/sched: cls_flower: validate mask pointer after nla_next()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aohan Mei <[email protected]>
commit fee10655709c5c597e8e9f722f3035d9ea31ff3a upstream.
fl_set_enc_opt() iterates the key's nested tunnel-option attributes with nla_for_each_attr() while advancing a single mask pointer via nla_next() at the bottom of each loop, so the mask cursor is driven by the number of key attributes rather than by the mask's own attributes. The nla_ok() added by commit c96adff956191 ("cls_flower:
call nla_ok() before nla_next()") only validates the mask pointer that was just consumed; the pointer produced by nla_next() is used by the next iteration (fl_set_geneve_opt() and siblings) without any validation.
The mask's nested attributes are validated with NL_VALIDATE_LIBERAL, which merely warns on trailing bytes that do not form a complete attribute. A mask carrying one valid attribute plus 1-3 residue bytes (or a non-aligned attribute length making msk_depth negative) therefore reaches the next iteration with msk_depth != 0, so neither the !msk_depth check in fl_set_enc_opt() nor the !depth check in the per-type helpers fires. nla_type() then reads past the mask payload and nla_parse_nested_deprecated() iterates with an nla_len taken from those bytes, reading well beyond the mask attribute (KASAN:
slab-out-of-bounds read in __nla_validate_parse from fl_change()).
Validate the advanced mask pointer as well: when the mask is not legitimately exhausted (msk_depth != 0) and the new pointer fails nla_ok(), reject the filter with -EINVAL. An exactly exhausted mask still skips the check, preserving exact-match behaviour for the remaining key attributes.
--- net/sched/cls_flower.c | 5 +++++ 1 file changed, 5 insertions(+)
net/sched/cls_flower.c +5 -0
@@ -1548,6 +1548,11 @@ static int fl_set_enc_opt(struct nlattrreturn -EINVAL ; } nla_opt_msk =nla_next (nla_opt_msk, &msk_depth); + +if (msk_depth && !nla_ok (nla_opt_msk, msk_depth)) { +NL_SET_ERR_MSG (extack,"A mask attribute is invalid" ); +return -EINVAL ; + } }return 0 ;
Greg Kroah-Hartman
maintainerPATCH 1775/1887 smb: client: fix multiuser mount with krb5
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paulo Alcantara <[email protected]>
commit 69499395867332364ed4ac8b546537eb3bab6ebb upstream.
Customer reported that they could no longer mount their SMB shares with multiuser mount option and krb5. Turned out that the client wasn't duplicating username option when creating multiuser connections, therefore failing to retrieve credentials as cifs.upcall(8) couldn't find them in keytab.
Fix this by duplicating username option (if set) from original fs context before creating multiuser connections with krb5.
Reproducer:
``` $ ktutil ktutil: add_entry -password -p testuser -k 1 -e aes256-cts Password for [email protected]: ktutil: write_kt /etc/krb5.keytab ktutil: quit $ klist -ke Keytab name: FILE:/etc/krb5.keytab KVNO Principal ---- ---------------------------------------------------------------- 1 [email protected] (aes256-cts-hmac-sha1-96) $ mount.cifs //w22-root2/scratch /mnt/1 -o \ uid=1000,sec=krb5,[email protected],multiuser mount error(13): Permission denied Refer to the mount.cifs(8) manual page (e.g. man mount.cifs) and kernel log messages (dmesg) ```
--- fs/smb/client/connect.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
fs/smb/client/connect.c +16 -5
@@ -4357,14 +4357,25 @@ cifs_setup_session(const unsigned int xireturn rc; } -static int -cifs_set_vol_auth (struct smb3_fs_context *ctx,struct cifs_ses *ses) +static int set_fs_context_auth (struct smb3_fs_context *ctx, +struct cifs_ses *ses) { ctx->sectype = ses->sectype; -/* krb5 is special, since we don't need username or pw */ -if (ctx->sectype == Kerberos) +/* +* krb5 is special as we might need to pass username (passwordless) down +* to cifs.upcall(8) for keytab. +*/ +if (ctx->sectype == Kerberos) { +if (ses->user_name && ses->user_name[0 ]) { + ctx->username =kstrndup (ses->user_name, +CIFS_MAX_USERNAME_LEN , +GFP_KERNEL ); +if (!ctx->username) +return -ENOMEM ; + }return 0 ; + }return cifs_set_cifscreds (ctx, ses); }
@@ -4401,7 +4412,7 @@ cifs_construct_tcon(struct cifs_sb_info ctx->seal = master_tcon->seal; ctx->witness = master_tcon->use_witness; - rc =cifs_set_vol_auth (ctx, master_tcon->ses); + rc =set_fs_context_auth (ctx, master_tcon->ses);if (rc) { tcon =ERR_PTR (rc); goto out;
Greg Kroah-Hartman
maintainerPATCH 1776/1887 tracing/histograms: Reject non-stacktrace fields for synthetic stacktrace fields
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lee Jones <[email protected]>
commit a244c241593b5b38a08f0df2cb43c26574efbdcb upstream.
In check_synth_field(), when a synthetic event field is a stacktrace (field->is_stack) and the histogram field is not a "long[" stacktrace array, validation falls through to the generic size and signedness comparison.
Because parse_synth_field() sets a stacktrace field's type to "__data_loc unsigned long[]", its size is sizeof(u64) and synth_field_signed() marks it as signed. Consequently, any 8-byte signed scalar histogram field passes the fallback check, and its scalar value is subsequently dereferenced as a kernel stacktrace pointer in get_field_size() and trace_stack().
Furthermore, checking strstr(hist_field->type, "long[") is insufficient because tracepoint fields defined with __bitmask() or __rel_bitmask() also have type "__data_loc unsigned long[]" or "__rel_loc unsigned long[]", whilst create_hist_field() treats them as 4-byte scalar values without HIST_FIELD_FL_STACKTRACE.
Propagate HIST_FIELD_FL_STACKTRACE to variable references and field variables (whilst excluding variable aliases from per-element stacktrace capture), and reject any mismatch between HIST_FIELD_FL_STACKTRACE and field->is_stack in check_synth_field().
[Lee: Omit create_var_field() and hist_trigger_elt_update() hunks as
288709c9f3b0 ("tracing: Allow stacktraces to be saved as histogram variables") is not present]
--- kernel/trace/trace_events_hist.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
kernel/trace/trace_events_hist.c +7 -2
@@ -2067,7 +2067,8 @@ static int init_var_ref(struct hist_fiel ref_field->size = var_field->size; ref_field->is_signed = var_field->is_signed; ref_field->flags |= var_field->flags & - (HIST_FIELD_FL_TIMESTAMP |HIST_FIELD_FL_TIMESTAMP_USECS ); + (HIST_FIELD_FL_TIMESTAMP |HIST_FIELD_FL_TIMESTAMP_USECS | +HIST_FIELD_FL_STACKTRACE );if (system) { ref_field->system =kstrdup (system,GFP_KERNEL );
@@ -3220,6 +3221,7 @@ static struct field_var *create_field_va ret = -ENOMEM ; goto err; } + var->flags |= val->flags &HIST_FIELD_FL_STACKTRACE ; field_var->var = var; field_var->val = val;
@@ -3837,7 +3839,10 @@ static int check_synth_field(struct synt && field->is_dynamic)return 0 ; -if (strstr (hist_field->type,"long[" ) && field->is_stack) +if (!!(hist_field->flags &HIST_FIELD_FL_STACKTRACE ) != field->is_stack) +return -EINVAL ; + +if (field->is_stack)return 0 ;if (strcmp (field->type, hist_field->type) !=0 ) {
Greg Kroah-Hartman
maintainerPATCH 1777/1887 scsi: st: Fix use-after-free race between st_remove() and st_open()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Laurence Oberman <[email protected]>
commit 71caf7f84bd62a4bf91cc95abd2de690afb8d15f upstream.
st_remove() drops the probe reference on the scsi_tape with kref_put() and only afterwards removes its index from st_index_idr. If that was the last reference, scsi_tape_release() frees the structure while it is still published in the idr.
scsi_tape_get(), called from st_open(), looks up the tape in st_index_idr and takes a reference under st_ref_mutex and st_index_lock. remove_cdevs() does not wait for opens that are already past chrdev_open(), so an open that is blocked on st_ref_mutex while st_remove() holds it can take the mutex as soon as st_remove() drops it, find the freed tpnt in the idr and call kref_get() on it:
BUG: KASAN: slab-use-after-free in st_open Write of size 4 ... st_open (drivers/scsi/st.c:254 drivers/scsi/st.c:1291) chrdev_open ... Freed by task ...: kfree st_remove (drivers/scsi/st.c:4512)
Remove the index from the idr before dropping the reference, all under st_ref_mutex. A concurrent scsi_tape_get() now either runs first and holds a valid reference that keeps the tape alive, or runs afterwards and finds nothing, so st_open() fails with -ENXIO.
This restores the ordering st_remove() had before the conversion to st_index_idr, where the tape was unpublished from scsi_tapes[] before the final kref_put().
--- drivers/scsi/st.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/scsi/st.c +2 -2
@@ -4440,11 +4440,11 @@ static int st_remove(struct device *dev)remove_cdevs (tpnt);mutex_lock (&st_ref_mutex); -kref_put (&tpnt->kref, scsi_tape_release); -mutex_unlock (&st_ref_mutex);spin_lock (&st_index_lock);idr_remove (&st_index_idr, index);spin_unlock (&st_index_lock); +kref_put (&tpnt->kref, scsi_tape_release); +mutex_unlock (&st_ref_mutex);return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1778/1887 perf: Track the perf mlock gift separately
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Stoakes (ARM) <[email protected]>
commit 78436f3882fb8d848c823bf8cf754988202c5ca5 upstream.
The locked_vm field in struct user_struct was originally introduced by commit 789f90fcf6b0 ("perf_counter: per user mlock gift") to provide an mlock-like budget for perf measured against mm->pinned_vm (since 2011).
perf grants each user a 'gift' of perf_event_mlock_kb * online CPUs of buffer pages which is charged to user->locked_vm without any RLIMIT_MEMLOCK check.
Only pages beyond the gift are checked against RLIMIT_MEMLOCK, per-mm, via mm->pinned_vm, which makes it different from the standard mlock() check, which is per-mm and made against RLIMIT_MEMLOCK.
However, since this was introduced, a number of other components have utilised this field where a shared resource needed to be limited against RLIMIT_MEMLOCK.
The other users are currently MSG_ZEROCOPY, io_uring, AF_XDP, iommufd, s390 KVM zPCI and most recently, secretmem in commit 97d34aa65c29 ("mm/secretmem: properly account locked pages").
This field is shared between all of these, but because the gift is not checked against RLIMIT_MEMLOCK, user->locked_vm alone can exceed it - 16 CPUs * 516 KiB is already more than the default 8 MiB - after which every other user of the field fails unconditionally.
This was reported by a user who saw secretmem failing while running a simultaneous perf record.
Resolve the issue by simply giving perf its own field separate from the rest.
BPF used user->locked_vm up until commit 80ee81e0403c ("bpf: Eliminate rlimit-based memory accounting infra for bpf maps") which landed in 5.11.
Thus also eliminate the now-defunct ifdef for CONFIG_BPF_SYSCALL for user->locked_vm.
This issue exists between all of the components which use user->locked_vm and perf, however secretmem is the first user who has caused a report over many years and has been backported, so target the fix at that.
--- include/linux/sched/user.h | 8 +++++--- kernel/events/core.c | 12 ++++++------ 2 files changed, 11 insertions(+), 9 deletions(-)
include/linux/sched/user.h +5 -3
@@ -23,11 +23,13 @@ struct user_struct {struct hlist_node uidhash_node;kuid_t uid; -#if defined(CONFIG_PERF_EVENTS ) || defined(CONFIG_BPF_SYSCALL ) || \ - defined(CONFIG_NET ) || defined(CONFIG_IO_URING ) || \ +#if defined(CONFIG_NET ) || defined(CONFIG_IO_URING ) || \ defined(CONFIG_VFIO_PCI_ZDEV_KVM ) ||IS_ENABLED (CONFIG_IOMMUFD ) || \ defined(CONFIG_SECRETMEM ) -atomic_long_t locked_vm; +atomic_long_t locked_vm;/* pinned pages charged to RLIMIT_MEMLOCK */ +#endif +#ifdef CONFIG_PERF_EVENTS +atomic_long_t perf_mlock;/* perf buffer pages within perf_event_mlock_kb */ #endif #ifdef CONFIG_WATCH_QUEUE atomic_t nr_watches;/* The number of watches this user currently has */
kernel/events/core.c +6 -6
@@ -6195,7 +6195,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)perf_pmu_output_stop (event);/* now it's safe to free the pages */ -atomic_long_sub (rb->aux_nr_pages - rb->aux_mmap_locked, &mmap_user->locked_vm); +atomic_long_sub (rb->aux_nr_pages - rb->aux_mmap_locked, &mmap_user->perf_mlock);atomic64_sub (rb->aux_mmap_locked, &vma->vm_mm->pinned_vm);/* this has to be the last one */
@@ -6270,7 +6270,7 @@ static void perf_mmap_close(struct vm_area_struct *vma)*/ atomic_long_sub ((size >>PAGE_SHIFT ) +1 - mmap_locked, - &mmap_user->locked_vm); + &mmap_user->perf_mlock);atomic64_sub (mmap_locked, &vma->vm_mm->pinned_vm);free_uid (mmap_user);
@@ -6430,11 +6430,11 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)*/ user_lock_limit *=num_online_cpus (); - user_locked =atomic_long_read (&user->locked_vm); + user_locked =atomic_long_read (&user->perf_mlock);/* * sysctl_perf_event_mlock may have changed, so that -* user->locked_vm > user_lock_limit +* user->perf_mlock > user_lock_limit */ if (user_locked > user_lock_limit) user_locked = user_lock_limit;
@@ -6442,7 +6442,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)if (user_locked > user_lock_limit) {/* -* charge locked_vm until it hits user_lock_limit; +* charge perf_mlock until it hits user_lock_limit; * charge the rest from pinned_vm */ extra = user_locked - user_lock_limit;
@@ -6494,7 +6494,7 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma) unlock:if (!ret) { -atomic_long_add (user_extra, &user->locked_vm); +atomic_long_add (user_extra, &user->perf_mlock);atomic64_add (extra, &vma->vm_mm->pinned_vm);atomic_inc (&event->mmap_count);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1779/1887 hwmon: (drivetemp) Fix driver producing garbage data when SCSI errors occur
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniil Stas <[email protected]>
commit 82163d63ae7a4c36142cd252388737205bb7e4b9 upstream.
scsi_execute_cmd() function can return both negative (linux codes) and positive (scsi_cmnd result field) error codes.
Currently the driver just passes error codes of scsi_execute_cmd() to hwmon core, which is incorrect because hwmon only checks for negative error codes. This leads to hwmon reporting uninitialized data to userspace in case of SCSI errors (for example if the disk drive was disconnected).
This patch checks scsi_execute_cmd() output and returns -EIO if it's error code is positive.
--- drivers/hwmon/drivetemp.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/hwmon/drivetemp.c +7 -3
@@ -165,6 +165,7 @@ static int drivetemp_scsi_command(struct drivetemp_data *st, {u8 scsi_cmd[MAX_COMMAND_SIZE ];int data_dir; +int err;memset (scsi_cmd,0 ,sizeof (scsi_cmd)); scsi_cmd[0 ] =ATA_16 ;
@@ -192,9 +193,12 @@ static int drivetemp_scsi_command(struct drivetemp_data *st, scsi_cmd[12 ] = lba_high; scsi_cmd[14 ] = ata_command; -return scsi_execute_req (st->sdev, scsi_cmd, data_dir, - st->smartdata,ATA_SECT_SIZE ,NULL ,HZ ,5 , -NULL ); + err =scsi_execute_req (st->sdev, scsi_cmd, data_dir, + st->smartdata,ATA_SECT_SIZE ,NULL ,HZ ,5 , +NULL ); +if (err >0 ) + err = -EIO ; +return err; } static int drivetemp_ata_command(struct drivetemp_data *st, u8 feature,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1780/1887 watch_queue: Fix note pool publication race in watch_queue_set_size()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang (Microsoft) <[email protected]>
[ Upstream commit 5e531d62f1f8834faf7a4eed0d41105cf6570a8f ]
There is a race between watch_queue_set_size() and post_one_notification(). watch_queue_set_size() publishes wqueue->notes, notes_bitmap, nr_pages and nr_notes with plain stores, and post_one_notification() reads them with plain loads under a different lock, so nothing orders the four stores against the poster's loads: depending on the build, notes can be stored last (gcc 14 on x86-64 does this). Since keyctl_watch_key() lets a watch attach to a queue before it is sized, post_one_notification() can already be running on another CPU at that moment: it reads nr_notes > 0, passes its bounds check, and then reads notes while it is still NULL, dereferencing notes[0].
An unprivileged user triggers this reliably by watching one of its own keys through a notification pipe and racing ioctl(IOC_WATCH_QUEUE_SET_SIZE) on that pipe against keyctl(KEYCTL_SETPERM) on the key from another CPU, triggering:
BUG: kernel NULL pointer dereference, address: 0000000000000000 RIP: 0010:post_one_notification.isra.0+0xa2/0x1e0 Call Trace: __post_watch_notification+0x148/0x180 keyctl_setperm_key+0x119/0x130 do_syscall_64+0x108/0x4c0 entry_SYSCALL_64_after_hwframe+0x77/0x7f Kernel panic - not syncing: Fatal exception in interrupt
Fix this by publishing nr_notes last with smp_store_release(), and by reading it once with smp_load_acquire() in post_one_notification() before the bitmap and the page array are touched. A poster that observes a non-zero nr_notes then also observes the pool behind it; one that observes zero drops the notification as before.
--- kernel/watch_queue.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
kernel/watch_queue.c +7 -4
@@ -102,7 +102,7 @@ static bool post_one_notification(struct watch_queue *wqueue,struct pipe_inode_info *pipe = wqueue->pipe;struct pipe_buffer *buf;struct page *page; -unsigned int head, tail, mask, note, offset, len; +unsigned int head, tail, mask, note, offset, len, nr_notes;bool done = false;spin_lock_irq (&pipe->rd_wait.lock);
@@ -113,8 +113,10 @@ static bool post_one_notification(struct watch_queue *wqueue,if (pipe_full (head, tail, pipe->ring_size)) goto lost; - note =find_first_bit (wqueue->notes_bitmap, wqueue->nr_notes); -if (note >= wqueue->nr_notes) +/* Pairs with the smp_store_release() in watch_queue_set_size(). */ + nr_notes =smp_load_acquire (&wqueue->nr_notes); + note =find_first_bit (wqueue->notes_bitmap, nr_notes); +if (note >= nr_notes) goto lost; page = wqueue->notes[note /WATCH_QUEUE_NOTES_PER_PAGE ];
@@ -299,7 +301,8 @@ long watch_queue_set_size(struct pipe_inode_info *pipe, unsigned int nr_notes) wqueue->notes = pages; wqueue->notes_bitmap = bitmap; wqueue->nr_pages = nr_pages; - wqueue->nr_notes = nr_notes; +/* Pairs with the smp_load_acquire() in post_one_notification(). */ +smp_store_release (&wqueue->nr_notes, nr_notes);return 0 ; error_p:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1781/1887 ext4: free the sbi after a grace period
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <[email protected]>
[ Upstream commit c17b44266a1f9fcb49b894d4611d1254bf1aa313 ]
ext4_get_link() follows a symlink that keeps its target in a data block in rcu pathwalk mode with ext4_getblk(EXT4_GET_BLOCKS_CACHED_NOWAIT). That reads s_mount_state in the ASSERT() of ext4_getblk() and again in ext4_es_lookup_extent(), and the lookup bumps the extent status hit or miss counter, all through sb->s_fs_info.
ext4_put_super() destroys those counters, clears sb->s_fs_info and frees the sbi without waiting for a grace period. A pathwalk that is still in ext4_get_link() when the last reference to the mount goes away then dereferences a NULL s_fs_info, the freed sbi or the destroyed percpu counters.
With a pathwalk held up in ext4_get_link() while the last reference goes away:
KASAN: null-ptr-deref in range [0x00000000000000a8-0x00000000000000af] RIP: 0010:ext4_getblk+0xf0/0x640 Call Trace: <TASK> ext4_get_link+0x26c/0x410 pick_link+0xf96/0x1780 step_into_slowpath+0x9b8/0x1250 path_lookupat+0x484/0xb00 filename_lookup+0x1f1/0x5b0 vfs_statx+0xd7/0x3b0 vfs_fstatat+0x4d/0x90 __do_sys_newfstatat+0xa0/0x100 do_syscall_64+0x10e/0x5e0 entry_SYSCALL_64_after_hwframe+0x77/0x7f
So far that has been hard to hit. umount(2) waits for a grace period in namespace_unlock() before it drops the mount, so only a mount whose last reference goes away elsewhere, like the close of a file or a chdir out of a lazily unmounted directory, can race a walker.
Keep sb->s_fs_info and free the sbi together with the extent status counters after a grace period. Split the counters out of ext4_es_unregister_shrinker() for that. The shrinker still gets wasted in ext4_put_super(), the counters go with the sbi.
--- fs/ext4/ext4.h | 2 ++ fs/ext4/extents_status.c | 7 ++++++- fs/ext4/extents_status.h | 1 + fs/ext4/super.c | 13 +++++++++++-- 4 files changed, 20 insertions(+), 3 deletions(-)
fs/ext4/ext4.h +2 -0
@@ -1688,6 +1688,8 @@ struct ext4_sb_info {struct list_head s_es_list;/* List of inodes with reclaimable extents */ long s_es_nr_inode;struct ext4_es_stats s_es_stats; +/* ext4_get_link() reads the sbi in rcu pathwalk */ +struct rcu_head s_rcu;struct mb_cache *s_ea_block_cache;struct mb_cache *s_ea_inode_cache;spinlock_t s_es_lock____cacheline_aligned_in_smp ;
fs/ext4/extents_status.c +6 -1
@@ -1751,12 +1751,17 @@ int ext4_es_register_shrinker(struct ext4_sb_info *sbi) }void ext4_es_unregister_shrinker (struct ext4_sb_info *sbi) +{ +unregister_shrinker (&sbi->s_es_shrinker); +} + +/* ext4_get_link() bumps the hit and miss counters in rcu pathwalk */ +void ext4_es_destroy_stats (struct ext4_sb_info *sbi) {percpu_counter_destroy (&sbi->s_es_stats.es_stats_cache_hits);percpu_counter_destroy (&sbi->s_es_stats.es_stats_cache_misses);percpu_counter_destroy (&sbi->s_es_stats.es_stats_all_cnt);percpu_counter_destroy (&sbi->s_es_stats.es_stats_shk_cnt); -unregister_shrinker (&sbi->s_es_shrinker); }/*
fs/ext4/extents_status.h +1 -0
@@ -241,6 +241,7 @@ static inline void ext4_es_store_pblock_status(struct extent_status *es,extern int ext4_es_register_shrinker (struct ext4_sb_info *sbi);extern void ext4_es_unregister_shrinker (struct ext4_sb_info *sbi); +extern void ext4_es_destroy_stats (struct ext4_sb_info *sbi);extern int ext4_seq_es_shrinker_info_show (struct seq_file *seq,void *v);
fs/ext4/super.c +11 -2
@@ -1260,6 +1260,14 @@ static void ext4_flex_groups_free(struct ext4_sb_info *sbi) } } +static void ext4_put_sbi_rcu (struct rcu_head *head) +{ + struct ext4_sb_info *sbi = container_of(head, struct ext4_sb_info, s_rcu); + +ext4_es_destroy_stats (sbi); +kfree (sbi); +} +static void ext4_put_super (struct super_block *sb) {struct ext4_sb_info *sbi =EXT4_SB (sb);
@@ -1344,7 +1352,6 @@ static void ext4_put_super(struct super_block *sb)ext4_stop_mmpd (sbi);brelse (sbi->s_sbh); - sb->s_fs_info =NULL ;/* * Now that we are completely done shutting down the * superblock, we need to actually destroy the kobject.
@@ -1359,7 +1366,8 @@ static void ext4_put_super(struct super_block *sb)#if IS_ENABLED (CONFIG_UNICODE )utf8_unload (sb->s_encoding);#endif -kfree (sbi); +/* ext4_get_link() reads the sbi and the counters in rcu pathwalk */ +call_rcu (&sbi->s_rcu, ext4_put_sbi_rcu); }static struct kmem_cache *ext4_inode_cachep;
@@ -5640,6 +5648,7 @@ failed_mount8: __maybe_unused } failed_mount3a:ext4_es_unregister_shrinker (sbi); +ext4_es_destroy_stats (sbi); failed_mount3:/* flush s_error_work before sbi destroy */ flush_work (&sbi->s_error_work);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1782/1887 exit: move core of do_wait() into helper
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jens Axboe <[email protected]>
[ Upstream commit 06a101ca45b296fe951692620b0bc49abf90c368 ]
Rather than have a maze of gotos, put the actual logic in __do_wait() and have do_wait() loop deal with waitqueue setup/teardown and whether to call __do_wait() again.
No functional changes intended in this patch.
Stable-dep-of: 81933038f5e2 ("pid_namespace: make zap_pid_ns_processes() freezable")
--- kernel/exit.c | 51 +++++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 20 deletions(-)
kernel/exit.c +31 -20
@@ -1588,16 +1588,10 @@ static int do_wait_pid(struct wait_opts *wo)return 0 ; } -static long do_wait (struct wait_opts *wo) +static long __do_wait (struct wait_opts *wo) { -int retval; - -trace_sched_process_wait (wo->wo_pid); +long retval; -init_waitqueue_func_entry (&wo->child_wait, child_wait_callback); - wo->child_wait.private = current; -add_wait_queue (¤t->signal->wait_chldexit, &wo->child_wait); -repeat:/* * If there is nothing that can match our criteria, just get out. * We will clear ->notask_error to zero if we see any child that
@@ -1609,24 +1603,23 @@ static long do_wait(struct wait_opts *wo) (!wo->wo_pid || !pid_has_task(wo->wo_pid, wo->wo_type))) goto notask; -set_current_state (TASK_INTERRUPTIBLE );read_lock (&tasklist_lock);if (wo->wo_type ==PIDTYPE_PID ) { retval =do_wait_pid (wo);if (retval) - goto end; +return retval; }else {struct task_struct *tsk = current; do { retval = do_wait_thread(wo, tsk); if (retval) - goto end; + return retval; retval = ptrace_do_wait(wo, tsk); if (retval) - goto end; + return retval; if (wo->wo_flags & __WNOTHREAD) break;
@@ -1636,14 +1629,32 @@ static long do_wait(struct wait_opts *wo) notask: retval = wo->notask_error; -if (!retval && !(wo->wo_flags &WNOHANG )) { - retval = -ERESTARTSYS ; -if (!signal_pending (current)) { -schedule (); - goto repeat; - } - } -end: +if (!retval && !(wo->wo_flags &WNOHANG )) +return -ERESTARTSYS ; + +return retval; +} + +static long do_wait (struct wait_opts *wo) +{ +int retval; + +trace_sched_process_wait (wo->wo_pid); + +init_waitqueue_func_entry (&wo->child_wait, child_wait_callback); + wo->child_wait.private = current; +add_wait_queue (¤t->signal->wait_chldexit, &wo->child_wait); + +do { +set_current_state (TASK_INTERRUPTIBLE ); + retval =__do_wait (wo); +if (retval != -ERESTARTSYS ) +break ; +if (signal_pending (current)) +break ; +schedule (); + }while (1 ); +__set_current_state (TASK_RUNNING );remove_wait_queue (¤t->signal->wait_chldexit, &wo->child_wait);return retval;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1783/1887 pid_namespace: make zap_pid_ns_processes() freezable
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aviv Vaknin <[email protected]>
[ Upstream commit 81933038f5e273d17ed22792f906889393b204c5 ]
When the init of a pid namespace exits, zap_pid_ns_processes() waits until all other pids in the namespace are freed. A tracer outside the namespace that does not reap its traced zombies keeps those pids allocated, so this wait has no upper bound, and while it lasts every suspend attempt fails:
Freezing user space processes failed after 20.006 seconds (2 tasks refusing to freeze, wq_busy=0):
Neither wait is freezable. The first loop sleeps in do_wait(), which returns -ERESTARTSYS on the freezer's fake signal; the loop then clears TIF_SIGPENDING and waits again without ever freezing. The final loop sleeps in TASK_INTERRUPTIBLE, and since nothing clears TIF_SIGPENDING there, schedule() returns immediately after the first freeze attempt and the task spins until the wait ends.
Sleep in TASK_INTERRUPTIBLE | TASK_FREEZABLE in do_wait(), so that the freezer can freeze tasks waiting there directly, and in TASK_IDLE | TASK_FREEZABLE in the final loop, like coredump_task_exit() does.
This was hit with Chromium-based browsers: crashpad ptrace-attaches the threads of a crashed renderer, which is a pid namespace init, and does not reap those killed during the dump.
--- kernel/exit.c | 2 +- kernel/pid_namespace.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
kernel/exit.c +1 -1
@@ -1646,7 +1646,7 @@ static long do_wait(struct wait_opts *wo)add_wait_queue (¤t->signal->wait_chldexit, &wo->child_wait); do { - set_current_state(TASK_INTERRUPTIBLE); + set_current_state(TASK_INTERRUPTIBLE | TASK_FREEZABLE); retval = __do_wait(wo); if (retval != -ERESTARTSYS) break;
kernel/pid_namespace.c +1 -1
@@ -242,7 +242,7 @@ void zap_pid_ns_processes(struct pid_namespace *pid_ns)* free_pid() will awaken this task. */ for (;;) { -set_current_state (TASK_INTERRUPTIBLE ); +set_current_state (TASK_IDLE |TASK_FREEZABLE );if (pid_ns->pid_allocated == init_pids)break ;/*
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1784/1887 mm/huge_memory: transfer the pmd dirty bit to the folio on zap
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Usama Arif <[email protected]>
[ Upstream commit fe6cf984939d8e12cb33a99673c8d026c5135e68 ]
zap_huge_pmd_folio() propagates the pmd young bit to the folio for the file case, but not the dirty bit. The pte path does propagate it, in zap_present_folio_ptes() and so does the pmd split path, in __split_huge_pmd_locked().
For most file mappings the omission is harmless, because writing to a shared file mapping goes through page_mkwrite(), which dirties the folio. tmpfs is different: it has no page_mkwrite(), and vma_wants_writenotify() is false for it, so a *read* fault on a MAP_SHARED tmpfs mapping installs a writable pmd via do_read_fault(). do_read_fault() does not call fault_dirty_shared_page(), so subsequent stores through that mapping set only the hardware dirty bit in the pmd and never call folio_mark_dirty(). A shmem folio allocated by a fault is marked uptodate but not dirty (see the clear: block in shmem_get_folio_gfp()), so PG_dirty is never set at all.
Unmapping such a folio - munmap(), or exit_mmap() when the process dies - then loses the only record that it was written, because zap_huge_pmd() drops the pmd without transferring the dirty bit. Reclaim afterwards sees a clean shmem folio: the whole swap-out block in shrink_folio_list() is inside "if (folio_test_dirty(folio))", so pageout() is skipped and the folio falls into __remove_mapping(). There, folio_is_file_lru() is false for a swapbacked folio, so no shadow entry is created and __filemap_remove_folio(folio, NULL) simply empties the i_pages slot. The data is freed without ever being written to swap, and the next fault on that index returns a freshly zeroed folio.
This is silent data loss for any process that keeps state in a MAP_SHARED tmpfs segment across an unmap - for example a cache handed from one process generation to the next through /dev/shm. It requires the folio to be PMD-mapped, so it only shows up once shmem THP is enabled (which is what we did in Meta fleet and started noticing crashes); with THP off the pte path transfers the dirty bit correctly. It also only becomes visible when swap is enabled, because with no swap device shmem folios (which are on the anon LRU) are not scanned by reclaim at all, so the clean folio is never dropped.
Reproduced on x86_64 with a tmpfs mounted huge=within_size: read-fault a 2MB-backed region, write a known pattern through the resulting mapping, munmap, force reclaim of the cgroup, then re-map and read back. Without this patch the region reads back as zeros and vmstat shows zswpout 0 - the data was discarded rather than swapped. With this patch the region reads back correctly and the pages are swapped out as expected. With huge=never, or when the first touch is a write, the test passes either way.
[ Ting-Han: zap_huge_pmd_folio() does not exist in this tree; the file
branch is open-coded in zap_huge_pmd(), so transfer the dirty bit there, as the 6.6.y backport does ]
--- mm/huge_memory.c | 3 +++ 1 file changed, 3 insertions(+)
mm/huge_memory.c +3 -0
@@ -1701,6 +1701,9 @@ int zap_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma,if (arch_needs_pgtable_deposit ())zap_deposited_table (tlb->mm, pmd);add_mm_counter (tlb->mm,mm_counter_file (page), -HPAGE_PMD_NR ); + +if (pmd_present (orig_pmd) &&pmd_dirty (orig_pmd)) +folio_mark_dirty (page_folio (page)); }spin_unlock (ptl);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1785/1887 dm-integrity: require stable writes for internal hash modes
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chen Cheng <[email protected]>
[ Upstream commit b2fd92f016e9d692fd3c8c08d0ee014e9212279d ]
dm-integrity direct, bitmap and inline internal-hash modes compute integrity tags from the pages carried by the write bio. The lower data write also uses those pages, so the tag and the data write depend on the same memory contents staying unchanged while writeback is in flight.
Without stable writes, a buffered writer can modify a writeback folio after dm-integrity has submitted the data bio and before the lower device has consumed the data. After a crash, this can leave data from the later contents with a tag calculated from the earlier contents, causing permanent checksum failures on read.
Set BLK_FEAT_STABLE_WRITES for internal-hash D, B and I modes so filesystems wait for writeback folios to become stable before modifying them again. Journal mode is left unchanged because it copies data into the journal before computing and persisting the tag.
Tested using dm-delay over a virtio-blk test disk, dm-integrity internal_hash:crc32c and no-journal ext4. The D and B reproducers both failed with checksum errors before this change and completed with READ_RC=0 and zero mismatches after it.
--- drivers/md/dm-integrity.c | 3 +++ drivers/md/dm-table.c | 2 +- include/linux/device-mapper.h | 5 +++++ 3 files changed, 9 insertions(+), 1 deletion(-)
drivers/md/dm-integrity.c +3 -0
@@ -3503,6 +3503,9 @@ static void dm_integrity_io_hints(struct dm_target *ti, struct queue_limits *limblk_limits_io_min (limits, ic->sectors_per_block <<SECTOR_SHIFT ); limits->dma_alignment = limits->logical_block_size -1 ; } + +if (ic->internal_hash && (ic->mode =='D' || ic->mode =='B' )) + ti->needs_stable_writes = true; }static void calculate_journal_section_size (struct dm_integrity_c *ic)
drivers/md/dm-table.c +1 -1
@@ -1941,7 +1941,7 @@ static int device_requires_stable_pages(struct dm_target *ti, struct dm_dev *dev, sector_t start, sector_t len, void *data) { - return bdev_stable_writes(dev->bdev); + return ti->needs_stable_writes || bdev_stable_writes(dev->bdev); } int dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
include/linux/device-mapper.h +5 -0
@@ -357,6 +357,11 @@ struct dm_target {*/ bool discards_supported:1; +/* +* Set if this target requires stable data during writeback. +*/ + bool needs_stable_writes:1; +/* * Set if we need to limit the number of in-flight bios when swapping. */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1786/1887 vsock/virtio: validate packet source for connected sockets
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daehyeon Ko <[email protected]>
[ Upstream commit dee44f41f206becb41c492899c1996cfd7f82a1b ]
virtio_transport_recv_pkt() looks up sockets first by the full source and destination tuple, then by destination only in the bound table. The fallback is needed for listening and connecting sockets, but sockets remain in the bound table after connect(), so it can also return a non-listening socket.
The fallback does not validate the source address. In TCP_SYN_SENT, a RESPONSE from an unrelated source can transition the victim socket to TCP_ESTABLISHED while its stored remote address remains unchanged. Subsequent RW packets from that source are delivered through the same destination-only fallback.
This was reproduced with capability-empty processes under different UIDs. The attacker discovered the target tuple through unprivileged AF_VSOCK sock_diag and caused the victim socket to read 16 attacker-chosen bytes; the intended peer-side socket read 0 of those 16 bytes.
Add vsock_check_source() to validate the transport, source port and source CID against the peer stored in a non-listening socket. The local transport is the CID exception because its packets are generated internally with VMADDR_CID_LOCAL as their source, including connections using CID aliases.
Use the helper after lock_sock() in the virtio receive path.
--- include/net/af_vsock.h | 3 +++ net/vmw_vsock/af_vsock.c | 32 +++++++++++++++++++++++++ net/vmw_vsock/virtio_transport_common.c | 3 ++- 3 files changed, 37 insertions(+), 1 deletion(-)
include/net/af_vsock.h +3 -0
@@ -207,6 +207,9 @@ void vsock_remove_connected(struct vsock_sock *vsk);struct sock *vsock_find_bound_socket (struct sockaddr_vm *addr);struct sock *vsock_find_connected_socket (struct sockaddr_vm *src,struct sockaddr_vm *dst); +bool vsock_check_source (const struct vsock_sock *vsk, +const struct vsock_transport *transport, +const struct sockaddr_vm *src);void vsock_remove_sock (struct vsock_sock *vsk);void vsock_for_each_connected_socket (struct vsock_transport *transport,void (*fn)(struct sock *sk));
net/vmw_vsock/af_vsock.c +32 -0
@@ -331,6 +331,38 @@ struct sock *vsock_find_connected_socket(struct sockaddr_vm *src, }EXPORT_SYMBOL_GPL (vsock_find_connected_socket); +/** +* vsock_check_source - validate a packet source against a socket peer +* @vsk: socket receiving the packet +* @transport: transport receiving the packet +* @src: source address from the packet +* +* Return: true if the packet arrived on the socket's assigned transport and +* its source matches the stored peer. Loopback packets are generated +* internally and always use the local CID as their source, including +* connections using a valid CID alias. +* +* The caller must hold the socket lock and must not call this for listening +* sockets, which accept packets from any source and have no assigned +* transport. +*/ +bool vsock_check_source (const struct vsock_sock *vsk, +const struct vsock_transport *transport, +const struct sockaddr_vm *src) +{ +if (vsk->transport != transport) +return false; + +if (src->svm_port != vsk->remote_addr.svm_port) +return false; + +if (src->svm_cid == vsk->remote_addr.svm_cid) +return true; + +return transport->get_local_cid () ==VMADDR_CID_LOCAL ; +} +EXPORT_SYMBOL_GPL (vsock_check_source); +void vsock_remove_sock (struct vsock_sock *vsk) {/* Transport reassignment must not remove the binding. */
net/vmw_vsock/virtio_transport_common.c +2 -1
@@ -1372,7 +1372,8 @@ void virtio_transport_recv_pkt(struct virtio_transport *t,* lock_sock (note: listener sockets are not assigned to any transport) */ if (sock_flag (sk,SOCK_DONE ) || - (sk->sk_state !=TCP_LISTEN && vsk->transport != &t->transport)) { + (sk->sk_state !=TCP_LISTEN && + !vsock_check_source (vsk, &t->transport, &src))) { (void )virtio_transport_reset_no_sock (t, skb);release_sock (sk);sock_put (sk);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1787/1887 ipv4: udp: Create exceptions before socket matching
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ido Schimmel <[email protected]>
[ Upstream commit 4c3499f79f8c7e8561266bcc220a18538cec0458 ]
Currently, when ICMP Fragmentation Needed and Redirect Message packets are locally delivered and quote a UDP packet, a FIB nexthop exception (FNHE) is only created if the kernel can match the UDP packet to an existing socket.
This behavior allows off-path attackers to conduct a side-channel attack on the FNHE cache in order to discover the ephemeral port used by a connected UDP socket.
Commit 6457378fe796 ("ipv4: use siphash instead of Jenkins in fnhe_hashfun()") and commit 67d6d681e15b ("ipv4: make exception cache less predictible") tried to mitigate such attacks by making it harder for attackers to discover hash collisions in the FNHE cache and by randomizing the number of exceptions a hash bucket can hold, respectively. Unfortunately, both of the mitigations can be bypassed.
Instead, mitigate such attacks by always creating a FNHE, even before trying to find a matching socket. Do that by calling ipv4_update_pmtu() and ipv4_redirect(), the helpers used when the quoted packet did not originate from a socket.
This means that guesses (right or wrong) from an off-path attacker will always result in a FNHE being created or updated in the cache that the attacker can observe.
Pass an oif of 0, in a similar fashion to icmp_err(). This is also the oif used by the socket path for sockets that are not bound to a device.
Note that this does not allow attackers to create FNHEs that they could not create before, as both helpers can already be reached with little to no validation. For example, by sending an ICMP error that quotes an ICMP Echo Reply or one that quotes a UDP source port that matches a wildcard socket.
Also note that in the good case (matched socket) the above scheme comes at the cost of an extra route lookup, as the no socket helpers perform their own lookup before the one performed by ipv4_sk_update_pmtu() / ipv4_sk_redirect(). When the two resolve to different nexthops, it also results in two exceptions being created for the same destination IP. One in the FNHE cache of the nexthop resolved by the no socket helpers and another in the FNHE cache of the nexthop used by the socket.
--- net/ipv4/udp.c | 9 +++++++++ 1 file changed, 9 insertions(+)
net/ipv4/udp.c +9 -0
@@ -879,6 +879,15 @@ int __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable)int udp_err (struct sk_buff *skb,u32 info) { +const int type =icmp_hdr (skb)->type; +const int code =icmp_hdr (skb)->code; +struct net *net =dev_net (skb->dev); + +if (type ==ICMP_DEST_UNREACH && code ==ICMP_FRAG_NEEDED ) +ipv4_update_pmtu (skb, net, info,0 ,IPPROTO_UDP ); +else if (type ==ICMP_REDIRECT ) +ipv4_redirect (skb, net,0 ,IPPROTO_UDP ); +return __udp4_lib_err (skb, info, &udp_table); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1788/1887 i2c: viai2c-wmt: Fix clock leak in wmt_i2c_probe()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <[email protected]>
[ Upstream commit aaabefc79b0ff0018e8e3832169bbe359d0551fc ]
In wmt_i2c_probe(), i2c->clk is acquired using of_clk_get(). If any subsequent operation fails or when the module is unloaded, the clock reference count is never decremented via clk_put(), leading to a resource leak.
Switch to devm_clk_get() so that the clock is automatically managed and released.
--- drivers/i2c/busses/i2c-wmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/busses/i2c-wmt.c +1 -1
@@ -391,7 +391,7 @@ static int wmt_i2c_probe(struct platform_device *pdev)return -EINVAL ; } - i2c_dev->clk =of_clk_get (np,0 ); + i2c_dev->clk =devm_clk_get (&pdev->dev,NULL );if (IS_ERR (i2c_dev->clk)) {dev_err (&pdev->dev,"unable to request clock\n" );return PTR_ERR (i2c_dev->clk);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1789/1887 futex: Fix mm reuse handling for FUT_OFF_MMSHARED
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jann Horn <[email protected]>
[ Upstream commit 3267512ad1c2cc0c7768c5b014dc2cceb398a801 ]
A FUT_OFF_MMSHARED futex is a shared futex that refers to an MM. It is possible for a process to wait on a shared futex with a different MM because a FUT_OFF_INODE waiter can be requeued onto a FUT_OFF_MMSHARED futex by another process.
This can cause FUT_OFF_MMSHARED waiters on a freed MM to consume wakeups intended for a newly allocated MM at the same address.
Fix it by keying FUT_OFF_MMSHARED using a unique 64-bit per-MM ID. Leave private futexes as before to avoid influencing the performance of the hotpath.
(Multi-threaded processes typically implicitly use FUT_OFF_MMSHARED by setting clear_child_tid such that it points into anonymous memory, which causes mm_release() in a multi-threaded mm to perform FUTEX_WAKE.)
--- include/linux/futex.h | 14 ++++++++---- include/linux/mm_types.h | 3 +++ kernel/fork.c | 3 +++ kernel/futex/core.c | 49 +++++++++++++++++++++------------------- 4 files changed, 41 insertions(+), 28 deletions(-)
include/linux/futex.h +9 -5
@@ -23,26 +23,30 @@ struct task_struct;* 01 : Shared futex (PTHREAD_PROCESS_SHARED) * mapped on a file (reference on the underlying inode) * 10 : Shared futex (PTHREAD_PROCESS_SHARED) -* (but private mapping on an mm, and reference taken on it) +* (but private mapping on an mm) */ -#define FUT_OFF_INODE 1/* We set bit 0 if key has a reference on inode */ -#define FUT_OFF_MMSHARED 2/* We set bit 1 if key has a reference on mm */ +#define FUT_OFF_INODE 1/* We set bit 0 if shared key identifies an inode */ +#define FUT_OFF_MMSHARED 2/* We set bit 1 if shared key identifies an mm */ union futex_key { +/* For FUT_OFF_INODE */ struct {u64 i_seq;unsigned long pgoff;unsigned int offset; } shared; + +/* For FUT_OFF_MMSHARED or private */ struct {union { -struct mm_struct *mm; -u64 __tmp; +struct mm_struct *mm;/* for private */ +u64 mm_seq;/* for FUT_OFF_MMSHARED */ };unsigned long address;unsigned int offset; } private; +struct {u64 ptr;unsigned long word;
include/linux/mm_types.h +3 -0
@@ -602,6 +602,9 @@ struct mm_struct {* by mmlist_lock */ +#ifdef CONFIG_FUTEX +atomic64_t futex_unique_id; +#endif unsigned long hiwater_rss;/* High-watermark of RSS usage */ unsigned long hiwater_vm;/* High-water virtual memory usage */
kernel/fork.c +3 -0
@@ -1159,6 +1159,9 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p,#endif mm_init_uprobes_state (mm);hugetlb_count_init (mm); +#ifdef CONFIG_FUTEX +atomic64_set (&mm->futex_unique_id,0 ); +#endif if (current->mm) { mm->flags = current->mm->flags &MMF_INIT_MASK ;
kernel/futex/core.c +26 -23
87 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1790/1887 drm/i915/dmc: Harden DMC firmware payload parsing
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dibin Moolakadan Subrahmanian <[email protected]>
[ Upstream commit 8bb1858db453cd4250e3b633f5d2d09206024ca6 ]
Validate the conversion of the DMC firmware size from dwords to bytes using check_mul_overflow() before calculating the firmware payload size.
Reject zero-length payloads and zero MMIO counts in the DMC firmware header so malformed firmware is caught early. Also set dmc_fw_size only after the payload allocation succeeds.
--- drivers/gpu/drm/i915/display/intel_dmc.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-)
drivers/gpu/drm/i915/display/intel_dmc.c +16 -5
@@ -645,7 +645,7 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc, }/* Cache the dmc header info. */ -if (mmio_count > mmio_count_max) { +if (!mmio_count || mmio_count > mmio_count_max) {drm_err (&i915->drm,"DMC firmware has wrong mmio count %u\n" , mmio_count);return 0 ; }
@@ -660,13 +660,21 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc, dmc_info->mmioaddr[i] =_MMIO (mmioaddr[i]); dmc_info->mmiodata[i] = mmiodata[i]; } - dmc_info->mmio_count = mmio_count; - dmc_info->start_mmioaddr = start_mmioaddr; rem_size -= header_len_bytes;/* fw_size is in dwords, so multiplied by 4 to convert into bytes. */ - payload_size = dmc_header->fw_size *4 ; +if (check_mul_overflow (dmc_header->fw_size,4u , &payload_size)) { +drm_err (&i915->drm,"DMC fw_size too large (%u dwords)\n" , + dmc_header->fw_size); +return 0 ; + } + +if (!payload_size) { +drm_err (&i915->drm,"DMC firmware has empty payload\n" ); +return 0 ; + } +if (rem_size < payload_size) goto error_truncated;
@@ -674,12 +682,15 @@ static u32 parse_dmc_fw_header(struct intel_dmc *dmc,drm_err (&i915->drm,"DMC FW too big (%u bytes)\n" , payload_size);return 0 ; } - dmc_info->dmc_fw_size = dmc_header->fw_size; dmc_info->payload =kmalloc (payload_size,GFP_KERNEL );if (!dmc_info->payload)return 0 ; + dmc_info->mmio_count = mmio_count; + dmc_info->start_mmioaddr = start_mmioaddr; + dmc_info->dmc_fw_size = dmc_header->fw_size; + payload = (u8 *)(dmc_header) + header_len_bytes;memcpy (dmc_info->payload, payload, payload_size);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1791/1887 dm-integrity: fix infinite loop on discard with large tag size
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ben Cressey <[email protected]>
[ Upstream commit 18d80c77b4c7dd20699e81cedfbbff4e9d198f28 ]
When integrity_metadata handles a discard, it fills a buffer with DISCARD_FILLER and writes it over the tags, max_blocks blocks at a time. If the kmalloc fails, the buffer is the on-stack array checksums_onstack and max_size is set to HASH_MAX_DIGESTSIZE. So if the tag size is larger than HASH_MAX_DIGESTSIZE, max_blocks is zero, bi_size is never decremented and the loop never terminates.
Fix this by using sizeof(checksums_onstack) as max_size. The array has MAX_TAG_SIZE bytes since commit b93b6643e9b5 ("dm integrity: fix a crash with unusually large tag size"), so max_blocks is at least 1.
--- drivers/md/dm-integrity.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/dm-integrity.c +1 -1
@@ -1830,7 +1830,7 @@ static void integrity_metadata(struct work_struct *w)if (unlikely (dio->op ==REQ_OP_DISCARD )) {unsigned int bi_size = dio->bio_details.bi_iter.bi_size; -unsigned int max_size =likely (checksums != checksums_onstack) ?PAGE_SIZE :HASH_MAX_DIGESTSIZE ; +unsigned int max_size =likely (checksums != checksums_onstack) ?PAGE_SIZE :sizeof (checksums_onstack);unsigned int max_blocks = max_size / ic->tag_size;memset (checksums,DISCARD_FILLER , max_size);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1792/1887 cifs: add revalidation on FSCTL failure in smb2_duplicate_extents()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frank Sorenson <[email protected]>
[ Upstream commit 53676a5e28231186c9f56d87b7998b640699bc15 ]
smb2_duplicate_extents() has no handling for FSCTL_DUPLICATE_EXTENTS_TO_FILE failure: when the FSCTL fails, local inode metadata may be stale from the pre-extension or from concurrent remote writes, but is never refreshed.
Force revalidation on FSCTL failure and use i_size_read() for the pre-extension check.
--- fs/smb/client/smb2ops.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
fs/smb/client/smb2ops.c +6 -1
@@ -2027,7 +2027,7 @@ smb2_duplicate_extents(const unsigned int xid, src_off, dest_off, len); inode =d_inode (trgtfile->dentry); -if (inode->i_size < dest_off + len) { +if (i_size_read (inode) < dest_off + len) { rc =smb2_set_file_size (xid, tcon, trgtfile, dest_off + len, false);if (rc) goto duplicate_extents_out;
@@ -2052,6 +2052,11 @@ smb2_duplicate_extents(const unsigned int xid,if (ret_data_len >0 )cifs_dbg (FYI ,"Non-zero response length in duplicate extents\n" ); +if (rc) { +CIFS_I (inode)->time =0 ;/* force reval */ +cifs_invalidate_cache (inode,0 ); + } + duplicate_extents_out:return rc; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1793/1887 xfs: dont hold buffer locks across sync transaction commit in xfs_sync_sb_buf
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yun Zhou <[email protected]>
[ Upstream commit 41a28c865d1d5843f8cb9e0af17a8f4d9e2961ff ]
xfs_sync_sb_buf() holds sb/rtsb buffer locks across a synchronous xfs_trans_commit(), which flushes the CIL push workqueue internally. If shutdown occurs during the CIL push, xfs_buf_item_unpin() needs to lock these buffers to fail them, causing a deadlock:
setlabel: holds buf lock -> flush_workqueue(xfs-cil)
CIL push worker: xfs_buf_item_unpin -> xfs_buf_lock(same buf)
Remove the xfs_trans_bhold() calls so that commit releases the buffer locks normally. After the sync commit, re-acquire the buffers via mp->m_sb_bp / mp->m_rtsb_bp for the on-disk writeback.
--- fs/xfs/libxfs/xfs_sb.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-)
fs/xfs/libxfs/xfs_sb.c +7 -10
@@ -1148,26 +1148,23 @@ xfs_sync_sb_buf( struct xfs_mount *mp) {struct xfs_trans *tp; -struct xfs_buf *bp;int error; error =xfs_trans_alloc (mp, &M_RES (mp)->tr_sb,0 ,0 ,0 , &tp);if (error)return error; - bp =xfs_trans_getsb (tp);xfs_log_sb (tp); -xfs_trans_bhold (tp, bp);xfs_trans_set_sync (tp); error =xfs_trans_commit (tp);if (error) - goto out; -/* -* write out the sb buffer to get the changes to disk -*/ - error =xfs_bwrite (bp); -out: -xfs_buf_relse (bp); +return error; + +/* Re-acquire and write the sb to disk. */ +xfs_buf_lock (mp->m_sb_bp); + error =xfs_bwrite (mp->m_sb_bp); +xfs_buf_unlock (mp->m_sb_bp); +return error; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1794/1887 bonding: do not set usable_slaves for broadcast mode
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hangbin Liu <[email protected]>
[ Upstream commit 45fc134bcfadde456639c1b1e206e6918d69a553 ]
After commit e0caeb24f538 ("net: bonding: update the slave array for broadcast mode"), broadcast mode will also set all_slaves and usable_slaves during bond_enslave(). But if we also set updelay, during enslave, the
slave init state will be BOND_LINK_BACK. And later bond_update_slave_arr() will alloc usable_slaves but add nothing.
This will cause bond_miimon_inspect() to have ignore_updelay
always true. So the updelay will be always ignored. e.g.
[ 6.498368] bond0: (slave veth2): link status definitely down, disabling slave [ 7.536371] bond0: (slave veth2): link status up, enabling it in 0 ms [ 7.536402] bond0: (slave veth2): link status definitely up, 10000 Mbps full duplex
To fix it, we can either always call bond_update_slave_arr() on every place when link changes. Or, let's just not set usable_slaves for broadcast mode.
--- drivers/net/bonding/bond_main.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-)
drivers/net/bonding/bond_main.c +9 -4
@@ -5173,13 +5173,18 @@ static void bond_set_slave_arr(struct bonding *bond, {struct bond_up_slave *usable, *all; - usable =rtnl_dereference (bond->usable_slaves); -rcu_assign_pointer (bond->usable_slaves, usable_slaves); -kfree_rcu (usable, rcu); - all =rtnl_dereference (bond->all_slaves);rcu_assign_pointer (bond->all_slaves, all_slaves);kfree_rcu (all, rcu); + +if (BOND_MODE (bond) ==BOND_MODE_BROADCAST ) { +kfree_rcu (usable_slaves, rcu); +return ; + } + + usable =rtnl_dereference (bond->usable_slaves); +rcu_assign_pointer (bond->usable_slaves, usable_slaves); +kfree_rcu (usable, rcu); }static void bond_reset_slave_arr (struct bonding *bond)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1795/1887 net_sched: codel: fix stale state for empty flows in fq_codel
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Köppeler <[email protected]>
[ Upstream commit 815980fe6dbb01ad4007e8b260a45617f598b76d ]
When codel_dequeue() finds an empty queue, it resets vars->dropping but does not reset vars->first_above_time. The reference CoDel algorithm (Nichols & Jacobson, ACM Queue 2012) resets both:
dodeque_result codel_queue_t::dodeque(time_t now) {
...
if (r.p == NULL) {
first_above_time = 0; // <-- Linux omits this
}
...
}Note that codel_should_drop() does reset first_above_time when called with a NULL skb, but codel_dequeue() returns early before ever calling codel_should_drop() in the empty-queue case. The post-drop code paths do reach codel_should_drop(NULL) and correctly reset the timer, so a dropped packet breaks the cycle -- but the next delivered packet re-arms first_above_time and the cycle repeats.
For sparse flows such as ICMP ping (one packet every 200ms-1s), the first packet arms first_above_time, the flow goes empty, and the second packet arrives after the interval has elapsed and gets dropped. The pattern repeats, producing sustained loss on flows that are not actually congested.
Test: veth pair, fq_codel, BQL disabled, 30000 iptables rules in the consumer namespace (NAPI-64 cycle ~14ms, well above fq_codel's 5ms target), ping at 5 pps under UDP flood:
Before fix: 26% ping packet loss
After fix: 0% ping packet loss
Fix by resetting first_above_time to zero in the empty-queue path of codel_dequeue(), matching the reference algorithm.
--- include/net/codel_impl.h | 1 + 1 file changed, 1 insertion(+)
include/net/codel_impl.h +1 -0
@@ -158,6 +158,7 @@ static struct sk_buff *codel_dequeue(void *ctx,bool drop;if (!skb) { + vars->first_above_time =0 ; vars->dropping = false;return skb; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1796/1887 mm: split critical region in remap_file_pages() and invoke LSMs in between
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kirill A. Shutemov <[email protected]>
[ Upstream commit 58a039e679fe72bd0efa8b2abe669a7914bb4429 ]
Commit ea7e2d5e49c0 ("mm: call the security_mmap_file() LSM hook in remap_file_pages()") fixed a security issue, it added an LSM check when trying to remap file pages, so that LSMs have the opportunity to evaluate such action like for other memory operations such as mmap() and mprotect().
However, that commit called security_mmap_file() inside the mmap_lock lock, while the other calls do it before taking the lock, after commit 8b3ec6814c83 ("take security_mmap_file() outside of ->mmap_sem").
This caused lock inversion issue with IMA which was taking the mmap_lock and i_mutex lock in the opposite way when the remap_file_pages() system call was called.
Solve the issue by splitting the critical region in remap_file_pages() in two regions: the first takes a read lock of mmap_lock, retrieves the VMA and the file descriptor associated, and calculates the 'prot' and 'flags' variables; the second takes a write lock on mmap_lock, checks that the VMA flags and the VMA file descriptor are the same as the ones obtained in the first critical region (otherwise the system call fails), and calls do_mmap().
In between, after releasing the read lock and before taking the write lock, call security_mmap_file(), and solve the lock inversion issue.
--- mm/mmap.c | 69 +++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 52 insertions(+), 17 deletions(-)
mm/mmap.c +52 -17
@@ -2982,6 +2982,7 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,unsigned long populate =0 ;unsigned long ret = -EINVAL ;struct file *file; +vm_flags_t vm_flags;pr_warn_once ("%s (%d) uses deprecated remap_file_pages() syscall. See Documentation/mm/remap_file_pages.rst.\n" , current->comm, current->pid);
@@ -2998,12 +2999,60 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size,if (pgoff + (size >>PAGE_SHIFT ) < pgoff)return ret; -if (mmap_write_lock_killable (mm)) +if (mmap_read_lock_killable (mm))return -EINTR ; +/* +* Look up VMA under read lock first so we can perform the security +* without holding locks (which can be problematic). We reacquire a +* write lock later and check nothing changed underneath us. +*/ vma =vma_lookup (mm, start); -if (!vma || !(vma->vm_flags &VM_SHARED )) +if (!vma || !(vma->vm_flags &VM_SHARED )) { +mmap_read_unlock (mm); +return -EINVAL ; + } + + prot |= vma->vm_flags &VM_READ ?PROT_READ :0 ; + prot |= vma->vm_flags &VM_WRITE ?PROT_WRITE :0 ; + prot |= vma->vm_flags &VM_EXEC ?PROT_EXEC :0 ; + + flags &=MAP_NONBLOCK ; + flags |=MAP_SHARED |MAP_FIXED |MAP_POPULATE ; +if (vma->vm_flags &VM_LOCKED ) + flags |=MAP_LOCKED ; + +/* Save vm_flags used to calculate prot and flags, and recheck later. */ + vm_flags = vma->vm_flags; + file =get_file (vma->vm_file); + +mmap_read_unlock (mm); + +/* Call outside mmap_lock to be consistent with other callers. */ + ret =security_mmap_file (file, prot, flags); +if (ret) { +fput (file); +return ret; + } + + ret = -EINVAL ; + +/* OK security check passed, take write lock + let it rip. */ +if (mmap_write_lock_killable (mm)) { +fput (file); +return -EINTR ; + } + + vma =vma_lookup (mm, start); + +if (!vma) + goto out; + +/* Make sure things didn't change under us. */ +if (vma->vm_flags != vm_flags) + goto out; +if (vma->vm_file != file) goto out;if (start + size > vma->vm_end) {
@@ -3031,25 +3080,11 @@ SYSCALL_DEFINE5(remap_file_pages, unsigned long, start, unsigned long, size, goto out; } - prot |= vma->vm_flags &VM_READ ?PROT_READ :0 ; - prot |= vma->vm_flags &VM_WRITE ?PROT_WRITE :0 ; - prot |= vma->vm_flags &VM_EXEC ?PROT_EXEC :0 ; - - flags &=MAP_NONBLOCK ; - flags |=MAP_SHARED |MAP_FIXED |MAP_POPULATE ; -if (vma->vm_flags &VM_LOCKED ) - flags |=MAP_LOCKED ; - - file =get_file (vma->vm_file); - ret =security_mmap_file (vma->vm_file, prot, flags); -if (ret) - goto out_fput; ret =do_mmap (vma->vm_file, start, size, prot, flags, pgoff, &populate,NULL ); -out_fput: -fput (file); out:mmap_write_unlock (mm); +fput (file);if (populate)mm_populate (ret, populate);if (!IS_ERR_VALUE (ret))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1797/1887 Bluetooth: L2CAP: access chan->conn safely in get/setsockopt
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit ca2c4c26498643f421d35ffe258fafbd3ed461c3 ]
Since commit b66774b48dd9 ("Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref") l2cap_chan::conn has held reference and remains non-NULL also after the corresponding hci_conn is deleted. In this state accessing various
fields eg. hci_conn::hdev is invalid, which leads to KASAN crash in l2cap_sock_setsockopt() access of conn->hcon->hdev.
Check l2cap_chan::conn.hcon corresponds to an alive hci_conn before trying to use it in l2cap_sock.c. Hold l2cap_chan_lock() in getsockopt/setsockopt to ensure it stays alive, and to avoid data races in l2cap_chan fields.
--- net/bluetooth/l2cap_sock.c | 57 ++++++++++++++++++++++++++++++-------- 1 file changed, 46 insertions(+), 11 deletions(-)
net/bluetooth/l2cap_sock.c +46 -11
@@ -437,11 +437,26 @@ static int l2cap_get_mode(struct l2cap_chan *chan)return -EINVAL ; } +static struct l2cap_conn *l2cap_chan_conn (struct l2cap_chan *chan) +{ +lockdep_assert_held (&chan->lock); + +/* l2cap_conn_del() sets FLAG_DEL while holding chan->lock before +* conn->hcon is deleted. If not set and conn is non-NULL, conn->hcon +* remains alive during this chan->lock critical section. +*/ +if (test_bit (FLAG_DEL , &chan->flags)) +return NULL ; + +return chan->conn; +} +static int l2cap_sock_getsockopt_old (struct socket *sock,int optname,char __user *optval,int __user *optlen) {struct sock *sk = sock->sk;struct l2cap_chan *chan =l2cap_pi (sk)->chan; +struct l2cap_conn *conn;struct l2cap_options opts;struct l2cap_conninfo cinfo;int err =0 ;
@@ -453,6 +468,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,if (get_user (len, optlen))return -EFAULT ; +l2cap_chan_lock (chan);lock_sock (sk);switch (optname) {
@@ -538,9 +554,15 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname,break ; } + conn =l2cap_chan_conn (chan); +if (!conn) { + err = -ENOTCONN ; +break ; + } +memset (&cinfo,0 ,sizeof (cinfo)); - cinfo.hci_handle = chan->conn->hcon->handle; -memcpy (cinfo.dev_class, chan->conn->hcon->dev_class,3 ); + cinfo.hci_handle = conn->hcon->handle; +memcpy (cinfo.dev_class, conn->hcon->dev_class,3 ); len =min (len,sizeof (cinfo));if (copy_to_user (optval, (char *) &cinfo, len))
@@ -554,6 +576,8 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, }release_sock (sk); +l2cap_chan_unlock (chan); +return err; }
@@ -562,6 +586,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, {struct sock *sk = sock->sk;struct l2cap_chan *chan =l2cap_pi (sk)->chan; +struct l2cap_conn *conn;struct bt_security sec;struct bt_power pwr;u32 phys;
@@ -578,6 +603,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,if (get_user (len, optlen))return -EFAULT ; +l2cap_chan_lock (chan);lock_sock (sk);switch (optname) {
@@ -589,12 +615,14 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,break ; } + conn =l2cap_chan_conn (chan); +memset (&sec,0 ,sizeof (sec)); -if (chan->conn) { - sec.level = chan->conn->hcon->sec_level; +if (conn) { + sec.level = conn->hcon->sec_level;if (sk->sk_state ==BT_CONNECTED ) - sec.key_size = chan->conn->hcon->enc_key_size; + sec.key_size = conn->hcon->enc_key_size; }else { sec.level = chan->sec_level; }
@@ -670,12 +698,14 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname,break ;case BT_PHY : -if (sk->sk_state !=BT_CONNECTED ) { + conn =l2cap_chan_conn (chan); + +if (sk->sk_state !=BT_CONNECTED || !conn) { err = -ENOTCONN ;break ; } - phys =hci_conn_get_phy (chan->conn->hcon); + phys =hci_conn_get_phy (conn->hcon);if (put_user (phys, (u32 __user *) optval)) err = -EFAULT ;
@@ -708,6 +738,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, }release_sock (sk); +l2cap_chan_unlock (chan);return err; }
@@ -738,6 +769,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,BT_DBG ("sk %p" , sk); +l2cap_chan_lock (chan);lock_sock (sk);switch (optname) {
@@ -838,6 +870,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, }release_sock (sk); +l2cap_chan_unlock (chan);return err; }
@@ -901,6 +934,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,if (level !=SOL_BLUETOOTH )return -ENOPROTOOPT ; +l2cap_chan_lock (chan);lock_sock (sk);switch (optname) {
@@ -926,11 +960,10 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, chan->sec_level = sec.level; -if (!chan->conn) + conn =l2cap_chan_conn (chan); +if (!conn)break ; - conn = chan->conn; -/* change security for LE channels */ if (chan->scid ==L2CAP_CID_ATT ) {if (smp_conn_security (conn->hcon, sec.level)) {
@@ -985,7 +1018,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, }if (opt ==BT_FLUSHABLE_OFF ) { - conn = chan->conn; + conn =l2cap_chan_conn (chan); +/* proceed further only when we have l2cap_conn and No Flush support in the LM */ if (!conn || !lmp_no_flush_capable (conn->hcon->hdev)) {
@@ -1108,6 +1142,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, }release_sock (sk); +l2cap_chan_unlock (chan);return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1798/1887 Bluetooth: L2CAP: refuse __l2cap_chan_add if chan already has conn
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit 86b55991d3cd690e73c5ef8d20b75ae4905b357a ]
l2cap_chan may be linked to l2cap_conn at most once. This is assumed in several places, eg l2cap_chan_del cleanup.
There is a TOCTOU race where the invariant is violated:
[Task 1] [Task 2]
l2cap_chan_connect l2cap_sock_bind
l2cap_chan_lock lock_sock
l2cap_state_change if (sk->sk_state != BT_OPEN)
chan->state = BT_CONNECT
l2cap_sock_state_change_cb chan->state = BT_BOUND
sk->sk_state = BT_BOUND
lock_sock <------------------ release_sock
sk->sk_state = BT_CONNECTl2cap_sock_connect() does not check sk->sk_state, so since chan->state is now BT_BOUND, subsequent connect() ends up with second __l2cap_chan_add.
Explicitly document and check the invariant in __l2cap_chan_add with WARN_ON_ONCE. The only callsite where it could be hit is l2cap_chan_connect, so add pre-check there to avoid relying on chan->state. chan->state read/write is not properly guarded currently so there can be other TOCTOUC problems.
Add l2cap_lock_chan in l2cap_sock_bind() to guard chan->state write.
--- net/bluetooth/l2cap_core.c | 7 ++++++- net/bluetooth/l2cap_sock.c | 2 ++ 2 files changed, 8 insertions(+), 1 deletion(-)
net/bluetooth/l2cap_core.c +6 -1
@@ -630,6 +630,10 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan)BT_DBG ("conn %p, psm 0x%2.2x, dcid 0x%4.4x" , conn,__le16_to_cpu (chan->psm), chan->dcid); +/* Caller must ensure l2cap_chan is linked to l2cap_conn only once */ +if (WARN_ON_ONCE (chan->conn ||test_bit (FLAG_DEL , &chan->flags))) +return ; + conn->disc_reason =HCI_ERROR_REMOTE_USER_TERM ; chan->conn =l2cap_conn_get (conn);
@@ -7428,7 +7432,8 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid,mutex_lock (&conn->chan_lock);l2cap_chan_lock (chan); -if (cid &&__l2cap_get_chan_by_dcid (conn, cid)) { +if ((cid &&__l2cap_get_chan_by_dcid (conn, cid)) || chan->conn || +test_bit (FLAG_DEL , &chan->flags)) {hci_conn_drop (hcon); err = -EBUSY ; goto chan_unlock;
net/bluetooth/l2cap_sock.c +2 -0
@@ -111,6 +111,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen)return -EINVAL ; } +l2cap_chan_lock (chan);lock_sock (sk);if (sk->sk_state !=BT_OPEN ) {
@@ -176,6 +177,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) done:release_sock (sk); +l2cap_chan_unlock (chan);return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1799/1887 Compiler Attributes: counted_by: Adjust name and identifier expansion
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kees Cook <[email protected]>
commit c8248faf3ca276ebdf60f003b3e04bf764daba91 upstream.
GCC and Clang's current RFCs name this attribute "counted_by", and have moved away from using a string for the member name. Update the kernel's macros to match. Additionally provide a UAPI no-op macro for UAPI structs that will gain annotations.
--- include/linux/compiler_attributes.h | 26 +++++++++++++------------- include/uapi/linux/stddef.h | 4 ++++ 2 files changed, 17 insertions(+), 13 deletions(-)
include/linux/compiler_attributes.h +13 -13
@@ -108,6 +108,19 @@#endif /* +* Optional: only supported since gcc >= 14 +* Optional: only supported since clang >= 18 +* +* gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896 +* clang: https://reviews.llvm.org/D148381 +*/ +#if __has_attribute (__counted_by__) +# define __counted_by (member) __attribute__((__counted_by__(member))) +#else +# define __counted_by (member) +#endif + +/* * Optional: not supported by gcc * Optional: only supported since clang >= 14.0 * Optional: not supported by icc
@@ -145,19 +158,6 @@#endif /* -* Optional: only supported since gcc >= 14 -* Optional: only supported since clang >= 17 -* -* gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=108896 -* clang: https://reviews.llvm.org/D148381 -*/ -#if __has_attribute (__element_count__) -# define __counted_by (member) __attribute__((__element_count__(#member))) -#else -# define __counted_by (member) -#endif - -/* * Optional: only supported since clang >= 14.0 * * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-error-function-attribute
include/uapi/linux/stddef.h +4 -0
@@ -52,3 +52,7 @@ TYPE NAME[]; \ }#endif + +#ifndef __counted_by +#define __counted_by (m) +#endif
Greg Kroah-Hartman
maintainerPATCH 1800/1887 tracing: Reject incomplete event filter expressions
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyle Zeng <[email protected]>
commit 1fdc4164e488916402badddbb1f51e9380dabb91 upstream.
A non-empty expression normally finishes in predicate_parse()'s inner loop, which resolves the pending logical operators before jumping to finalization. If the input ends after an operator, possibly followed by unary '!' tokens, the outer loop instead falls through with unresolved operator state.
For example, "common_pid == 1 || common_pid == 2 &&" leaves prog[0].target equal to -1. The second pass then reads prog[-1] before the forward-jump check can reject it. Depending on adjacent slab contents, it can also copy an out-of-bounds word into a branch target that passes the forward-only check. A self-targeted perf tracepoint counting event can reach this path through PERF_EVENT_IOC_SET_FILTER.
Reject the outer-loop fallthrough when a predicate has already been parsed. This ensures that non-empty expressions only reach finalization after the inner loop has resolved their operators. Keep the existing no-filter error for input that has no predicates. Add a regression test for trailing logical operators and unary negations.
--- kernel/trace/trace_events_filter.c | 6 ++ tools/testing/selftests/ftrace/test.d/filter/event-filter-incomplete.tc | 24 ++++++++++ 2 files changed, 30 insertions(+) create mode 100644 tools/testing/selftests/ftrace/test.d/filter/event-filter-incomplete.tc
kernel/trace/trace_events_filter.c +6 -0
@@ -573,6 +573,12 @@ predicate_parse(const char *str, int nr_ top--;/* #12 */ } } +/* Only the inner loop can complete a non-empty expression. */ +if (N ) { + ret = -EINVAL ; +parse_error (pe,FILT_ERR_INVALID_FILTER , ptr - str); + goto out_free; + } out:if (top != op_stack) {/* Too many '(' */
tools/testing/selftests/ftrace/test.d/filter/event-filter-incomplete.tc new file +24 -0
@@ -0,0 +1,24 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# description: event filter - reject incomplete logical expressions +# requires: events/sched/sched_switch/filter +# flags: instance + +filter=events/sched/sched_switch/filter + +for base in \ + 'common_pid == 1' \ + 'common_pid == 1 || common_pid == 2' \ + 'common_pid == 1 && common_pid == 2' \ + '!(common_pid == 1 || common_pid == 2)' +do + printf '%s' "$base" > "$filter" + for tail in '&&' '||' '&& !' '|| !' '&& !! ' '|| !! '; do + if printf '%s' "$base $tail" > "$filter" 2>/dev/null; then + echo "Accepted incomplete filter: $base $tail" + exit_fail + fi + done +done + +echo 0 > "$filter"
Greg Kroah-Hartman
maintainerPATCH 1801/1887 tracing: Save the event file instead of the compatible histogram
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Donggeun Yoo <[email protected]>
commit d5c42664fc094899af9aae5300b27fe8fdb658ef upstream.
create_field_var_hist() creates a histogram on the matched event to supply a field variable, and records it on the target so it can be torn down later:
hist_data = find_compatible_hist(target_hist_data, file); ... /* Save the compatible histogram information */ var_hist->hist_data = hist_data;
hist_data is not the histogram it creates. It is one that was already there, whose keys the new one copies. The saved pointer has a single user, unregister_field_var_hists(), which runs when the target is removed:
file = hist_data->field_var_hists[i]->hist_data->event_file;
find_compatible_hist() matches on keys alone, so it can pick one with no variables of its own. check_var_refs() then returns false and the user can remove it while the target still points at it:
BUG: KASAN: slab-use-after-free in event_hist_trigger_free+0x2b2/0x320 Read of size 8 at addr ffff8880093b90e0 by task init/1 Freed by task 1: kfree+0x154/0x420 event_hist_trigger_free+0x1d5/0x320 event_hist_trigger_parse+0x35f3/0x69e0 trigger_process_regex+0x1a6/0x250
Save the event file instead. It is all the dereference ever wanted, and it does not go away when the user removes a trigger.
--- kernel/trace/trace_events_hist.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
kernel/trace/trace_events_hist.c +4 -4
@@ -539,7 +539,7 @@ struct field_var { };struct field_var_hist { -struct hist_trigger_data *hist_data; +struct trace_event_file *file;char *cmd; };
@@ -3027,8 +3027,8 @@ create_field_var_hist(struct hist_triggereturn ERR_PTR (-ENOMEM ); } -/* Save the compatible histogram information */ - var_hist->hist_data = hist_data; +/* Needed to remove the histogram when the target goes away */ + var_hist->file = file;/* Create the new histogram with our variable */ ret = event_hist_trigger_parse(&trigger_hist_cmd, file,
@@ -5993,7 +5993,7 @@ static void unregister_field_var_hists(sint ret;for (i =0 ; i < hist_data->n_field_var_hists; i++) { - file = hist_data->field_var_hists[i]->hist_data->event_file; + file = hist_data->field_var_hists[i]->file; cmd = hist_data->field_var_hists[i]->cmd; ret =event_hist_trigger_parse (&trigger_hist_cmd, file,"!hist" ,"hist" , cmd);
Greg Kroah-Hartman
maintainerPATCH 1802/1887 tracing: Unregister field variable histograms when the command fails
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Donggeun Yoo <[email protected]>
commit 91c14d6c13096091c56304120aaa26e479130b8b upstream.
An action that names a field on another event needs that field as a variable, so create_field_var_hist() registers a second hist trigger on that event to provide it, and records it in target_hist_data->field_var_hists[].
If a later part of the same command fails, create_actions() returns an error and event_hist_trigger_parse() jumps to out_free. The write fails with -EINVAL and sched_switch gets no trigger, but:
# echo 'hist:keys=pid:ts0=common_timestamp.usecs' >> \
events/sched/sched_waking/trigger
# echo 'my_synth u64 lat; int a; int b' >> synthetic_events
# echo 'hist:keys=next_pid:wakeup_lat=common_timestamp.usecs-$ts0:\
onmatch(sched.sched_waking).my_synth($wakeup_lat,prio,nosuchfld)'\
>> events/sched/sched_switch/trigger
# cat events/sched/sched_waking/trigger
hist:keys=pid:vals=hitcount:ts0=common_timestamp.usecs:sort=hitcount:size=2048:clock=global [active]
hist:keys=pid:vals=hitcount:synthetic_prio=prio:sort=hitcount:size=2048 [active]The second histogram is the one created for 'prio'. It is still active and still counting.
out_free reaches destroy_field_var_hists(), which frees the field_var_hists[] entries, but never unregister_field_var_hists(), which is what removes the triggers and runs only from event_hist_trigger_free(). The entry is freed and the trigger is left with nothing tracking it.
Unregister the field variable histograms in out_free as well, and record each one as soon as its trigger is registered rather than after the lookup that follows it, so no exit can leave a registered trigger untracked. The entry then belongs to field_var_hists[] and is released by destroy_field_var_hists(), so freeing it on that exit would be a double free.
--- kernel/trace/trace_events_hist.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
kernel/trace/trace_events_hist.c +6 -6
@@ -3043,20 +3043,18 @@ create_field_var_hist(struct hist_triggekfree (cmd); + n = target_hist_data->n_field_var_hists; + target_hist_data->field_var_hists[n] = var_hist; + target_hist_data->n_field_var_hists++; +/* If we can't find the variable, something went wrong */ event_var =find_synthetic_field_var (target_hist_data, subsys_name, event_name, field_name);if (IS_ERR_OR_NULL (event_var)) { -kfree (var_hist->cmd); -kfree (var_hist);hist_err (tr,HIST_ERR_SYNTH_VAR_NOT_FOUND ,errpos (field_name));return ERR_PTR (-EINVAL ); } - n = target_hist_data->n_field_var_hists; - target_hist_data->field_var_hists[n] = var_hist; - target_hist_data->n_field_var_hists++; -return event_var; }
@@ -6604,6 +6602,8 @@ static int event_hist_trigger_parse(strutrigger_data_free (trigger_data); +unregister_field_var_hists (hist_data); +destroy_hist_data (hist_data); goto out; }
Greg Kroah-Hartman
maintainerPATCH 1803/1887 tracing: Fix 64-bit and signed histogram fields on 32-bit kernels
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Donggeun Yoo <[email protected]>
commit 443d23176812803d0fa182b8d05ef066a7b8271f upstream.
DEFINE_HIST_FIELD_FN() reads a trace event field and widens it to the u64 the histogram uses as a key or a value:
type *addr = (type *)(event + hist_field->field->offset); return (u64)(unsigned long)*addr;
unsigned long is 32 bits on a 32-bit kernel, so the intermediate cast discards the upper half of a 64-bit field, and widens a signed field by zero extension from 32 bits rather than sign extension from its own width. Five of the eight instantiations are wrong there: s64, u64, s32, s16 and s8.
The cast came in with commit 79e577cbce4c ("tracing: Support string type key properly"), which also added hist_field_dynstring() and hist_field_pstring(). Those convert a char * to u64 and do warn without an unsigned long in between on 32-bit. DEFINE_HIST_FIELD_FN() converts an integer and never a pointer, so it gains nothing from the cast and only loses information.
Drop the intermediate cast and let the usual arithmetic conversions widen *addr according to its own type. unsigned long is 64 bits on LP64, so the two forms are identical there and 64-bit kernels are unaffected.
--- kernel/trace/trace_events_hist.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/trace/trace_events_hist.c +1 -1
@@ -458,7 +458,7 @@ static u64 hist_field_unary_minus(struct { \type *addr = (type *)(event + hist_field->field->offset); \ \ -return (u64 )(unsigned long )*addr; \ +return (u64)*addr; \ }DEFINE_HIST_FIELD_FN (s64);
Greg Kroah-Hartman
maintainerPATCH 1804/1887 tracing/histograms: Verify event_call identity when updating synth_event refcount
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lee Jones <[email protected]>
commit 3403d9bb27ebc3572bd048620746b4414e073bf9 upstream.
In event_hist_trigger_parse() and hist_unreg_all(), the histogram registration and unregistration paths look up find_synth_event() using trace_event_name(file->event_call) and adjust se->ref if a match is found.
Because find_synth_event() only compares the event basename, registering or removing a histogram on a non-synthetic trace event whose basename matches a synthetic event erroneously modifies the synthetic event's reference count. If a histogram is registered on the non-synthetic event before the synthetic event is created and removed afterwards, se->ref is decremented without a matching increment, allowing the synthetic event to be freed while an active histogram action still holds a pointer to it.
Introduce find_synth_event_call() to verify that &se->call matches file->event_call before adjusting se->ref.
--- kernel/trace/trace_events_hist.c | 11 +++-------- kernel/trace/trace_events_synth.c | 10 ++++++++++ kernel/trace/trace_synth.h | 1 + 3 files changed, 14 insertions(+), 8 deletions(-)
kernel/trace/trace_events_hist.c +3 -8
@@ -6416,7 +6416,6 @@ static void hist_unreg_all(struct trace_struct event_trigger_data *test, *n;struct hist_trigger_data *hist_data;struct synth_event *se; -const char *se_name;lockdep_assert_held (&event_mutex);
@@ -6429,8 +6428,7 @@ static void hist_unreg_all(struct trace_list_del_rcu (&test->list);trace_event_trigger_enable_disable (file,0 ); - se_name =trace_event_name (file->event_call); - se =find_synth_event (se_name); + se =find_synth_event_call (file->event_call);if (se) se->ref--;
@@ -6454,7 +6452,6 @@ static int event_hist_trigger_parse(strustruct hist_trigger_data *hist_data;char *param, *filter, *p, *start;struct synth_event *se; -const char *se_name;bool remove;int ret =0 ;
@@ -6548,8 +6545,7 @@ static int event_hist_trigger_parse(stru }event_trigger_unregister (cmd_ops, file, glob+1 , trigger_data); - se_name =trace_event_name (file->event_call); - se =find_synth_event (se_name); + se =find_synth_event_call (file->event_call);if (se) se->ref--; ret =0 ;
@@ -6584,8 +6580,7 @@ static int event_hist_trigger_parse(struif (ret) goto out_unreg; - se_name =trace_event_name (file->event_call); - se =find_synth_event (se_name); + se =find_synth_event_call (file->event_call);if (se) se->ref++; out:
kernel/trace/trace_events_synth.c +10 -0
@@ -867,6 +867,16 @@ struct synth_event *find_synth_event(conreturn NULL ; } +struct synth_event *find_synth_event_call (struct trace_event_call *call) +{ +struct synth_event *se; +const char *name; + + name =trace_event_name (call); + se =find_synth_event (name); +return se && &se->call == call ? se :NULL ; +} +static struct trace_event_fields synth_event_fields_array[] = { { .type =TRACE_FUNCTION_TYPE , .define_fields = synth_event_define_fields },
kernel/trace/trace_synth.h +1 -0
@@ -37,5 +37,6 @@ struct synth_event { };extern struct synth_event *find_synth_event (const char *name); +extern struct synth_event *find_synth_event_call (struct trace_event_call *call);#endif /* __TRACE_SYNTH_H */
Greg Kroah-Hartman
maintainerPATCH 1805/1887 keys: Avoid the owner account dereference in named keyring lookup
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang <[email protected]>
commit 51409aaa01f8602552c336009fd22b226b0cdf1d upstream.
Named keyring lookup must keep the storage containing the owner UID alive through the namespace mapping check. find_keyring_by_name() reads keyring->user->uid under keyring_name_lock, but that lock protects the keyring's name entry and allocation, not its separate key_user.
A named session-keyring join can overlap a privileged KEYCTL_CHOWN on another CPU. If the keyring holds the last reference to its old dynamic key_user and the ownership transfer succeeds, the following ordering is possible:
Named join Chown
find_keyring_by_name() keyctl_chown_key()
read_lock(keyring_name_lock) down_write(key->sem)
load old keyring->user
replace key->user and key->uid
up_write(key->sem)
key_put(key)
key_user_put(old user): free
read old user->uid
read_unlock(keyring_name_lock)Chown neither takes keyring_name_lock nor key_session_mutex, so it can free the old account between the pointer load and the UID read. The lookup then reads freed memory even though the keyring itself is alive.
Use keyring->uid for the mapping check. key_alloc() initializes this inline owner UID and keyctl_chown_key() updates it on chown. The existing name lock keeps its containing keyring allocated throughout the check, so lookup no longer depends on the account's lifetime. This also matches the owner UID used by the permission check.
KASAN report as below:
BUG: KASAN: slab-use-after-free in find_keyring_by_name+0x577/0x5d0
Read of size 4 at addr ffff8881128ae2ec by task keycase/500--- security/keys/keyring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
security/keys/keyring.c +1 -1
@@ -1158,7 +1158,7 @@ struct key *find_keyring_by_name(const c* grants Search permission and that hasn't been revoked */ list_for_each_entry (keyring, &ns->keyring_name_list, name_link) { -if (!kuid_has_mapping (ns, keyring->user->uid)) +if (!kuid_has_mapping (ns, keyring->uid))continue ;if (test_bit (KEY_FLAG_REVOKED , &keyring->flags))
Greg Kroah-Hartman
maintainerPATCH 1806/1887 keys: Check the authorization payload in process keyring searches
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang <[email protected]>
commit 0a0ec45bf577a9b4d4960567f20d3877ef480de9 upstream.
An authorization payload and its saved credentials must remain valid while search_process_keyrings_rcu() searches the requestor's keyrings. The function validates the authorization key, then separately loads payload.data[0] and unconditionally reads rka->cred. Validation does not prevent request_key_auth_revoke() from clearing the payload.
A request-key helper can assume authority and fork a descendant that inherits the authorization key. If the descendant misses in its own keyrings, it falls back to the saved requestor credentials. Successful target instantiation invalidates the authorization key without clearing the payload. After the helper exits, UMH_WAIT_PROC returns to the requester, which calls complete_request_key() and revokes that key.
With the descendant paused after validation, the paths can interleave as follows:
1. The descendant enters search_process_keyrings_rcu() under RCU and key_validate() succeeds.
2. The helper instantiates the target, invalidates the authorization key, and exits.
3. The requester resumes from UMH_WAIT_PROC, calls complete_request_key(), and revokes the authorization key. request_key_auth_revoke() sets its payload pointer to NULL.
4. The descendant loads NULL and dereferences rka->cred.
This NULL dereference can oops the kernel. RCU delays payload disposal but does not prevent the pointer from being cleared.
Load the payload with dereference_key_rcu() and require a non-NULL result before validating the authorization key and searching its saved credentials. A non-NULL payload and its credentials remain alive for the caller's RCU read-side section; a cleared payload skips the fallback search and follows the existing error selection.
KASAN report as below:
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000005: 0000 [#1] SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000028-0x000000000000002f]
RIP: 0010:search_process_keyrings_rcu+0x32b/0x790--- security/keys/process_keys.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
security/keys/process_keys.c +2 -3
@@ -556,9 +556,8 @@ key_ref_t search_process_keyrings_rcu(st ) {const struct cred *cred = ctx->cred; -if (key_validate (cred->request_key_auth) ==0 ) { - rka = ctx->cred->request_key_auth->payload.data[0 ]; - + rka =dereference_key_rcu (cred->request_key_auth); +if (rka &&key_validate (cred->request_key_auth) ==0 ) {//// was search_process_keyrings() [ie. recursive] ctx->cred = rka->cred; key_ref =search_cred_keyrings_rcu (ctx);
Greg Kroah-Hartman
maintainerPATCH 1807/1887 keys: Protect the type name while describing a key
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang <[email protected]>
commit fced7238b7e80cf8aa688d5af976e4aa6e33c329 upstream.
keyctl_describe_key() must keep the key type's name alive until kasprintf() has consumed it. The retained key reference keeps the key and its description alive, but does not pin the module providing its type. The name is passed to kasprintf() without holding key->sem.
kvasprintf() uses the saved name pointer in two formatting passes, with a GFP_KERNEL allocation between them. With AF_RXRPC=m, a task that passes View permission before type retirement can overlap a privileged module unload in this order:
1. KEYCTL_DESCRIBE looks up the key, saves key->type->name in the kasprintf() arguments and completes the first formatting pass.
2. While the formatter is delayed before its second pass, af_rxrpc_exit() calls unregister_key_type(), which removes the type from the registry and waits for key_gc_keytype().
3. The collector takes key->sem for writing, retypes the retained key to key_type_dead and completes retirement. Unregistration and module exit return, allowing free_module() to release the type and name.
4. The formatter resumes its second pass and reads the saved name from released module storage, which can fault in string().
Hold key->sem for reading across kasprintf(). The collector then cannot retype the key or complete retirement until both formatting passes have finished. If retirement wins the lock first, formatting uses the core key_type_dead name instead. Release the semaphore immediately after kasprintf(), including on allocation failure, before copying to userspace.
Oops report as below:
BUG: unable to handle page fault for address: fffffbfff8054794
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
RIP: 0010:string+0x23f/0x470
Call Trace:
vsnprintf+0x330/0x1110--- security/keys/keyctl.c | 2 ++ 1 file changed, 2 insertions(+)
security/keys/keyctl.c +2 -0
@@ -677,12 +677,14 @@ okay:/* calculate how much information we're going to return */ ret = -ENOMEM ; +down_read (&key->sem); infobuf =kasprintf (GFP_KERNEL ,"%s;%d;%d;%08x;" , key->type->name,from_kuid_munged (current_user_ns (), key->uid),from_kgid_munged (current_user_ns (), key->gid), key->perm); +up_read (&key->sem);if (!infobuf) goto error2; infolen =strlen (infobuf);
Greg Kroah-Hartman
maintainerPATCH 1808/1887 keys: make keyring indexes independent of kernel addresses
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyle Zeng <[email protected]>
commit de891c73c1cf41ac8de12c07fa2c84d6a912ad0c upstream.
KEYCTL_READ returns the serial numbers in a keyring in associative-array traversal order. The first word of the index is a public, deterministic hash of the type pointer, domain pointer and description. An unprivileged user can therefore insert keys with known descriptions, predict their order for each possible KASLR slide, and recover the kernel image address. On an x86-64 build with 16 MiB alignment, 45 user keys suffice to distinguish the candidate slides.
Remove the addresses from the whole index, not just its first hash word. Assign each key type and domain a nonzero 64-bit ID and hash those IDs and the description with a once-initialized SipHash key. Use the full IDs in the later index chunks as well. Truncating or hashing the IDs there would lose the guarantee that distinct type/domain/description tuples have a differing index bit.
Allocate IDs lazily since private key types need not be registered. Cache them in the index key so tree walks and copies of an existing index do not need to dereference a type descriptor that may have been unregistered. Keep the 32-bit chunk layout and diff_objects() bit offsets consistent, and retain the separate root slot for keyrings used by recursive search. The key comparison, permissions and userspace data format are unchanged; only the address-dependent in-memory ordering is replaced.
--- include/linux/key-type.h | 1 include/linux/key.h | 5 + security/keys/keyring.c | 150 +++++++++++++++++++++++++---------------------- 3 files changed, 86 insertions(+), 70 deletions(-)
include/linux/key-type.h +1 -0
@@ -158,6 +158,7 @@ struct key_type { const void *in, const void *in2);/* internal fields */ +atomic64_t index_id;/* Opaque keyring index ID */ struct list_head link;/* link in types list */ struct lock_class_key lock_class;/* key->sem lock class */ } __randomize_layout;
include/linux/key.h +5 -0
@@ -107,6 +107,7 @@ struct keyring_name;struct key_tag {struct rcu_head rcu; +atomic64_t index_id;/* Opaque keyring index ID */ refcount_t usage;bool removed;/* T when subject removed */ };
@@ -129,6 +130,8 @@ struct keyring_index_key {struct key_type *type;struct key_tag *domain_tag;/* Domain of operation */ const char *description; +u64 type_id;/* Cached index IDs */ +u64 domain_id; };union key_payload {
@@ -250,6 +253,8 @@ struct key {struct key_type *type;/* type of key */ struct key_tag *domain_tag;/* Domain of operation */ char *description; +u64 type_id; +u64 domain_id; }; };
security/keys/keyring.c +80 -70
224 lines not on this page · raw message
Greg Kroah-Hartman
maintainerPATCH 1809/1887 keys: Protect the read method check against type removal
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang <[email protected]>
commit 925c84e3cc21caf09de92d9bcafab0147790debf upstream.
keyctl_read_key() checks key->type->read without holding key->sem. A reference keeps the key alive, but does not pin the module containing its type. A surviving RxRPC key can therefore be read while AF_RXRPC is being unloaded:
KEYCTL_READ task Module unload and key GC
---------------- ------------------------
lookup_user_key()
permission / possession checks
load key->type
af_rxrpc_exit()
unregister_key_type()
GC: down_write(key->sem)
GC: retype to key_type_dead
GC: up_write(key->sem)
unregister_key_type() returns
free_module()read saved type's read member
The final access can read freed module storage. The read invocation in __keyctl_read_key() is already protected by key->sem, but the earlier method check is outside that critical section.
Move the method check into __keyctl_read_key(), after key_validate() and under its existing read hold on key->sem. The check and invocation then use the same protected type for length queries and every read retry. The GC cannot retype the key until the semaphore is released, and type unregistration waits for that GC pass before the module can be freed.
Return -EOPNOTSUPP when validation succeeds and the type has no read method. A temporary buffer may now be allocated before this result; allocation and copying to userspace remain outside the semaphore.
--- security/keys/keyctl.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-)
security/keys/keyctl.c +6 -7
@@ -808,8 +808,12 @@ static long __keyctl_read_key(struct keydown_read (&key->sem); ret =key_validate (key); -if (ret ==0 ) - ret = key->type->read (key, buffer, buflen); +if (ret ==0 ) { +if (key->type->read) + ret = key->type->read (key, buffer, buflen); +else + ret = -EOPNOTSUPP ; + }up_read (&key->sem);return ret; }
@@ -863,11 +867,6 @@ long keyctl_read_key(key_serial_t keyid,/* the key is probably readable - now try to read it */ can_read_key: -if (!key->type->read) { - ret = -EOPNOTSUPP ; - goto key_put_out; - } -if (!buffer || !buflen) {/* Get the key length from the read method */ ret =__keyctl_read_key (key,NULL ,0 );
Greg Kroah-Hartman
maintainerPATCH 1810/1887 KEYS: Fix key_reject_and_link() race with keyring restriction
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Martinez <[email protected]>
commit 0b157166e612b70f98a332b6c7be7eac6f8e9593 upstream.
The restrict_link check in key_reject_and_link() is done before taking the keyring semaphore, racing with a concurrent keyring_restrict() that installs the restriction while holding the semaphore in write mode.
Move the check to after __key_link_lock(), so it is done under the semaphore, matching the pattern used in __key_create_or_update().
--- security/keys/key.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-)
security/keys/key.c +10 -3
@@ -586,11 +586,18 @@ int key_reject_and_link(struct key *key, ret = -EBUSY ;if (keyring) { -if (keyring->restrict_link) -return -EPERM ; - link_ret =__key_link_lock (keyring, &key->index_key);if (link_ret ==0 ) { +/* +* Check the restriction under the keyring semaphore. +* keyring_restrict() installs it while holding the +* semaphore, so testing it beforehand races with a +* concurrent restriction install. +*/ +if (keyring->restrict_link) { +__key_link_end (keyring, &key->index_key, edit); +return -EPERM ; + } link_ret =__key_link_begin (keyring, &key->index_key, &edit);if (link_ret <0 )__key_link_end (keyring, &key->index_key, edit);
Greg Kroah-Hartman
maintainerPATCH 1811/1887 KEYS: trusted: Fix blob allocation size in tpm2_key_decode()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stefano Garzarella <[email protected]>
commit 11077cbcc2695f71c944a84a5f08c6672ab759f1 upstream.
tpm2_key_decode() allocates 4 bytes more than needed. The ASN.1 callbacks tpm2_key_priv() and tpm2_key_pub() provide the lengths of TPM2B_PRIVATE and TPM2B_PUBLIC, so ctx.priv_len and ctx.pub_len already account for the 2-byte size field each of those structures starts with.
I noticed this while reviewing commit 114f00d738f1 ("KEYS: trusted:
Fix tpm2_load_cmd() boundary check"), which correctly reports ctx.priv_len + ctx.pub_len as the decoded blob size [1].
Let's allocate exactly that amount, matching the data copied into the blob.
[1] https://lore.kernel.org/linux-integrity/apfoKo-BdwaLXtkT@sgarzare-redhat/
--- security/keys/trusted-keys/trusted_tpm2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
security/keys/trusted-keys/trusted_tpm2.c +1 -1
@@ -124,7 +124,7 @@ static int tpm2_key_decode(struct trusteif (ctx.priv_len + ctx.pub_len >MAX_BLOB_SIZE )return -EINVAL ; - blob =kmalloc (ctx.priv_len + ctx.pub_len +4 ,GFP_KERNEL ); + blob =kmalloc (ctx.priv_len + ctx.pub_len,GFP_KERNEL );if (!blob)return -ENOMEM ;
Greg Kroah-Hartman
maintainerPATCH 1812/1887 keys/trusted_keys: return immediately after TPM unseal failure
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Srish Srinivasan <[email protected]>
commit f92d0ccb05bf9089072cb067dda0dffd5394c4ef upstream.
trusted_tpm_unseal() proceeds to pcrlock() when the TPM unseal operation fails. If pcrlock() succeeds, its return value overwrites the unseal error, causing key instantiation to succeed.
Return immediately when unseal fails to preserve the original error.
--- security/keys/trusted-keys/trusted_tpm1.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
security/keys/trusted-keys/trusted_tpm1.c +3 -1
@@ -959,8 +959,10 @@ static int trusted_tpm_unseal(struct tru ret =tpm2_unseal_trusted (chip, p, options); else ret =key_unseal (p, options); -if (ret <0 ) +if (ret <0 ) {pr_info ("key_unseal failed (%d)\n" , ret); + goto out; + }if (options->pcrlock) { ret =pcrlock (options->pcrlock);
Greg Kroah-Hartman
maintainerPATCH 1813/1887 asymmetric_keys: reject trust keys without IDs
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
commit 9695df3b1db4ac4534274d38ee16e3b9b0bf910e upstream.
The PKCS#8 parser deliberately leaves the asym_key_ids payload slot empty. key_or_keyring_common() unconditionally dereferences that slot when a PKCS#8 key is supplied to a key_or_keyring restriction. Both the plain and :chain forms reach this branch, allowing an unprivileged caller to trigger a NULL pointer dereference through KEYCTL_RESTRICT_KEYRING followed by add_key().
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000 KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007] RIP: 0010:key_or_keyring_common (crypto/asymmetric_keys/restrict.c:205 crypto/asymmetric_keys/restrict.c:279) Call Trace: <TASK> __key_create_or_update (security/keys/key.c:884) key_create_or_update (security/keys/key.c:1021) __do_sys_add_key (security/keys/keyctl.c:134) do_syscall_64 (arch/x86/entry/common.c:52 arch/x86/entry/common.c:83) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130) </TASK> Kernel panic - not syncing: Fatal exception
Reject an asymmetric restriction key without key IDs. A PKCS#8 private key cannot identify the signer of a candidate certificate and is not a valid trust anchor.
--- crypto/asymmetric_keys/restrict.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
crypto/asymmetric_keys/restrict.c +6 -2
@@ -152,10 +152,14 @@ static int key_or_keyring_common(structif (IS_ERR (key)) key =NULL ; }else if (trusted->type == &key_type_asymmetric) { +const struct asymmetric_key_ids *kids;const struct asymmetric_key_id **signer_ids; - signer_ids = (const struct asymmetric_key_id **) -asymmetric_key_ids (trusted)->id; + kids =asymmetric_key_ids (trusted); +if (!kids) +return -ENOKEY ; + + signer_ids = (const struct asymmetric_key_id **)kids->id;/* * The auth_ids come from the candidate key (the
Greg Kroah-Hartman
maintainerPATCH 1814/1887 ftrace: Initialize modname and offset in print_rec()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aaron Ahmed <[email protected]>
commit e1f339ff3b83857b93baf8b88186275a413d445e upstream.
print_rec() leaves 'modname' and 'offset' uninitialized and kallsyms_lookup() only sets them on success. When the lookup fails like when a module is being loaded or unloaded, 'modname' holds a garbage value, passes the 'if (modname)' check, and is dereferenced by seq_printf().
Oops: general protection fault RIP: 0010:string+0x48/0xe0 Call Trace: vsnprintf+0x1f5/0x650 seq_printf+0x8e/0xb0 print_rec+0x6c/0xc0 t_show+0x4c/0x440 seq_read_iter+0x119/0x480
This can be triggered by reading available_filter_functions while a module is being loaded or unloaded.
Initialize both variables so a failed lookup skips the module name.
--- kernel/trace/ftrace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
kernel/trace/ftrace.c +2 -2
@@ -3742,9 +3742,9 @@ subsys_initcall(ftrace_check_for_weak_fustatic int print_rec (struct seq_file *m,unsigned long ip) { -unsigned long offset; +unsigned long offset =0 ;char str[KSYM_SYMBOL_LEN ]; -char *modname; +char *modname =NULL ;const char *ret; ret =kallsyms_lookup (ip,NULL , &offset, &modname, str);
Greg Kroah-Hartman
maintainerPATCH 1815/1887 coredump: hold RCU while releasing parked threads
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <[email protected]>
commit 61d58591aa0188bf2463e263962256316ff8b576 upstream.
coredump_finish() releases the parked threads by clearing ->task in their core_thread entry and calling wake_up_process() on each of them. It does that without holding a reference on the task and without being inside rcu.
But calling wake_up_process(task) without rcu here isn't safe. A parked thread doesn't need that wakeup to leave. A spurious wakeup or a preemption after the store is enough for the task to go away.
So if the coredump client is preempted between the store and wake_up_process() the thread can exit and be freed in the meantime and try_to_wake_up() takes pi_lock in freed memory.
Hold rcu across the loop.
--- fs/coredump.c | 3 +++ 1 file changed, 3 insertions(+)
fs/coredump.c +3 -0
@@ -460,6 +460,8 @@ static void coredump_finish(bool core_du current->signal->core_state =NULL ;spin_unlock_irq (¤t->sighand->siglock); +/* A released thread may exit and be freed before it is woken. */ +guard (rcu)();while ((curr = next) !=NULL ) { next = curr->next; task = curr->task;
@@ -468,6 +470,7 @@ static void coredump_finish(bool core_du* ->task == NULL before we read ->next. */ smp_mb (); +/* Any wakeup now lets the thread exit, rcu keeps it alive. */ curr->task =NULL ;wake_up_process (task); }
Greg Kroah-Hartman
maintainerPATCH 1816/1887 signal: only SIGKILL and the freezers interrupt a coredumping task
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <[email protected]>
commit 563d606b93d7a1d23512832fc252d32c68860d87 upstream.
For quite a while now coredump has allowed either SIGKILL or freezing to interrupt an ongoing coredump. Since we seem to like it complicated "freezing" can mean a lot of things:
(1) Power Management induced freezing
(2) cgroup v1 freezer controller induced freezing
(3) cgroup v2 freezer controller induced freezing
So (1) and (2) are handled by checking freezing() but (3) isn't.
(3) uses cgroup_freeze_task() which sets JOBCTL_TRAP_FREEZE and calls signal_wake_up() on every task in the cgroup. The trap isn't handled by the coredump code.
Which means the current logic is inconsistent. Power and cgroup v1 freeze and abort the coredump. With cgroup v2 it depends on where the core goes. A dump to a file completes and the cgroup v2 freeze has to wait for it to finish. When dumping to a pipe or socket the dump is interrupted at the next write because of trap's TIF_SIGPENDING. Which is it? Let's be consistent and align (1)-(3): freezing interrupts an ongoing coredump and doesn't make it wait until the dump is done.
All three freezers go through signal_wake_up() and so set TIF_SIGPENDING on the dumper. And once zap_threads() has set core_state that flag can't mean anything else anymore. prepare_signal() drops every signal but SIGKILL for the group, the dying threads don't retarget shared signals to the dumper, and zap_process() cleared the pending job control traps. So the flag is the thing to check. Let dump_interrupted() test task_sigpending() and nothing else. That is also what the pipe and socket writes already fail on. TIF_NOTIFY_SIGNAL is left out on purpose, task work must not cut a dump short.
A seized tracee that gets PTRACE_INTERRUPT during the dump is cut short the same way. It already was for pipes and sockets.
The one freeze that check can miss is one requested before the dump started. zap_threads() clears TIF_SIGPENDING and the cgroup v2 freezer only wakes a task once while its JOBCTL_TRAP_FREEZE isn't part of JOBCTL_PENDING_MASK and survives zap_process(). So refuse to start the dump when freezing() is true or the trap is pending. The task then exits without dumping, which is what happens today when the freeze interrupts the dump at the first write.
--- fs/coredump.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-)
fs/coredump.c +5 -8
@@ -407,7 +407,9 @@ static int zap_threads(struct task_strucint nr = -EAGAIN ;spin_lock_irq (&tsk->sighand->siglock); -if (!(signal->flags &SIGNAL_GROUP_EXIT ) && !signal->group_exec_task) { +/* A freeze requested before the dump would be lost with TIF_SIGPENDING. */ +if (!(signal->flags &SIGNAL_GROUP_EXIT ) && !signal->group_exec_task && + !freezing (tsk) && !(tsk->jobctl &JOBCTL_TRAP_FREEZE )) { signal->core_state = core_state; nr =zap_process (tsk, exit_code);clear_tsk_thread_flag (tsk,TIF_SIGPENDING );
@@ -478,13 +480,8 @@ static void coredump_finish(bool core_dustatic bool dump_interrupted (void ) { -/* -* SIGKILL or freezing() interrupt the coredumping. Perhaps we -* can do try_to_freeze() and check __fatal_signal_pending(), -* but then we need to teach dump_write() to restart and clear -* TIF_SIGPENDING. -*/ -return fatal_signal_pending (current) ||freezing (current); +/* Only SIGKILL and the freezers set it after zap_threads(). */ +return task_sigpending (current); }static void wait_for_dump_helpers (struct file *file)
Greg Kroah-Hartman
maintainerPATCH 1817/1887 signal: dont retarget shared signals in a dying thread group
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <[email protected]>
commit c0e659511d4f49087da095a95799edb5b775a705 upstream.
If the calling thread has blocked a signal then retarget_shared_pending() slingshots a shared pending signal to a sibling thread. Today it only skips PF_EXITING threads but not a coredumping thread.
But if SIGNAL_GROUP_EXIT is set no thread in the thread-group can dequeue such signals anymore as get_signal() sends SIGKILL to every thread and prepare_signal() drops any other signal.
exit_signals() also returns early on SIGNAL_GROUP_EXIT. But neither sigprocmask() nor the mask restore in sigtimedwait() do.
Say a thread sleeps in sigtimedwait() and a sibling thread crashes. The sleeping thread gets woken by the zap call. It restores its mask on the way out and retargets a signal that was queued for the coredumping process. That means TIF_SIGPENDING is set on the coredumping task which zap_threads() had cleared. So a blocking write sees TIF_SIGPENDING and truncates the dump.
Stop retargeting signals when SIGNAL_GROUP_EXIT is set and avoid needlessly truncating coredumps.
--- kernel/signal.c | 4 ++++ 1 file changed, 4 insertions(+)
kernel/signal.c +4 -0
@@ -2942,6 +2942,10 @@ static void retarget_shared_pending(strusigset_t retarget;struct task_struct *t; +/* Nobody dequeues them in a dying group, see get_signal(). */ +if (tsk->signal->flags &SIGNAL_GROUP_EXIT ) +return ; +sigandsets (&retarget, &tsk->signal->shared_pending.signal, which);if (sigisemptyset (&retarget))return ;
Greg Kroah-Hartman
maintainerPATCH 1818/1887 pid_namespace: prevent TIF_NOTIFY_SIGNAL from interrupting the reaper
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <[email protected]>
commit 5c0985dd3c32fc2bbd0e8beaf13cf52cd97376a2 upstream.
Since commit 7fea700e04bd ("zap_pid_ns_processes: clear TIF_NOTIFY_SIGNAL along with TIF_SIGPENDING") zap_pid_ns_processes() clears TIF_NOTIFY_SIGNAL before every kernel_wait4() call. Otherwise kernel_wait4() doesn't sleep and returns -ERESTARTSYS if signal_pending() is true and the reaper busy-waits.
But clearing TIF_NOTIFY_SIGNAL doesn't fix it. It can get raised again. For example, klp_send_signals() sets it raw against any task that hasn't transitioned yet. And it keeps sending it until the livepatch finishes.
The sleep loop waiting for pid_allocated to drop has the same problem and it doesn't even clear anything. So a schedule() in TASK_INTERRUPTIBLE returns immediately.
Use a no_notify_signal guard. signal_pending() will ignore TIF_NOTIFY_SIGNAL and the pid namespace reaper sleeps until a child exits or free_pid() wakes it.
--- kernel/pid_namespace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/pid_namespace.c +2 -1
@@ -212,9 +212,10 @@ void zap_pid_ns_processes(struct pid_nam* kernel_wait4() will also block until our children traced from the * parent namespace are detached and become EXIT_DEAD. */ +/* Task work must not busy-loop the reaper, see signal_pending(). */ +guard (no_notify_signal)();do {clear_thread_flag (TIF_SIGPENDING ); -clear_thread_flag (TIF_NOTIFY_SIGNAL ); rc =kernel_wait4 (-1 ,NULL , __WALL,NULL ); }while (rc != -ECHILD );
Greg Kroah-Hartman
maintainerPATCH 1819/1887 signal: allow taks to temporarily block TIF_NOTIFY_SIGNAL
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Christian Brauner <[email protected]>
commit 22b7f491be8f93ff72de0a3fe02b8ee9e64d3f21 upstream.
TIF_NOTIFY_SIGNAL is used to kick a task in uninterruptible sleep to return to userspace and run task work and then go back to sleep. This mechanism works well but breaks e.g., coredumps. dump_interrupted() only allows fatal signals to interrupt a coredump and the whole regular write path going to actual filesystems is impervious to TIF_NOTIFY_SIGNAL as well.
Add PF_NO_NOTIFY_SIGNAL and helpers to raise and restore it. This is the same approach as memalloc_nofs_save(). signal_pending() will not report a fake pending signal via TIF_NOTIFY_SIGNAL if inside a PF_NO_NOTIFY_SIGNAL section.
No functional changes.
--- include/linux/sched.h | 2 +- include/linux/sched/signal.h | 27 +++++++++++++++++++++++++-- 2 files changed, 26 insertions(+), 3 deletions(-)
include/linux/sched.h +1 -1
@@ -1753,7 +1753,7 @@ extern struct pid *cad_pid;* I am cleaning dirty pages from some other bdi. */ #define PF_KTHREAD 0x00200000/* I am a kernel thread */ #define PF_RANDOMIZE 0x00400000/* Randomize virtual address space */ -#define PF__HOLE__00800000 0x00800000 +#define PF_NO_NOTIFY_SIGNAL 0x00800000/* see no_notify_signal_save() */ #define PF__HOLE__01000000 0x01000000#define PF__HOLE__02000000 0x02000000#define PF_NO_SETAFFINITY 0x04000000/* Userland is not allowed to meddle with cpus_mask */
include/linux/sched/signal.h +25 -2
@@ -2,6 +2,7 @@#ifndef _LINUX_SCHED_SIGNAL_H#define _LINUX_SCHED_SIGNAL_H +#include <linux/cleanup.h> #include <linux/rculist.h> #include <linux/signal.h> #include <linux/sched.h>
@@ -389,14 +390,36 @@ static inline int task_sigpending(structreturn unlikely (test_tsk_thread_flag (p,TIF_SIGPENDING )); } +/* Prevent TIF_NOTIFY_SIGNAL from interrupting this task. */ +static inline unsigned int no_notify_signal_save (void ) +{ +unsigned int flags = current->flags; + + current->flags |=PF_NO_NOTIFY_SIGNAL ; +return flags; +} + +/* Restore the previous PF_NO_NOTIFY_SIGNAL state. */ +static inline void no_notify_signal_restore (unsigned int flags) +{ +current_restore_flags (flags,PF_NO_NOTIFY_SIGNAL ); +} + +DEFINE_LOCK_GUARD_0 (no_notify_signal, + _T->flags =no_notify_signal_save (), +no_notify_signal_restore (_T->flags), + unsigned int flags) +static inline int signal_pending (struct task_struct *p) {/* * TIF_NOTIFY_SIGNAL isn't really a signal, but it requires the same * behavior in terms of ensuring that we break out of wait loops -* so that notify signal callbacks can be processed. +* so that notify signal callbacks can be processed. Not for a task +* that asked not to be interrupted by it, see no_notify_signal_save(). */ -if (unlikely (test_tsk_thread_flag (p,TIF_NOTIFY_SIGNAL ))) +if (unlikely (test_tsk_thread_flag (p,TIF_NOTIFY_SIGNAL )) && +likely (!(READ_ONCE (p->flags) &PF_NO_NOTIFY_SIGNAL )))return 1 ;return task_sigpending (p); }
Greg Kroah-Hartman
maintainerPATCH 1820/1887 riscv: use lw when reading int cpu in asm_per_cpu
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Radim Krčmář <[email protected]>
[ Upstream commit f4ea67a722e8c9e1fb8109adebb9fb881ff0793a ]
REG_L is wrong, because thread_info.cpu is 32-bit, not xlen-bit wide. The struct currently has a hole after cpu, so little endian accesses seemed fine.
--- arch/riscv/include/asm/asm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/riscv/include/asm/asm.h +1 -1
@@ -90,7 +90,7 @@#endif .macro asm_per_cpu dst sym tmp - REG_L \tmp, TASK_TI_CPU_NUM(tp) + lw \tmp, TASK_TI_CPU_NUM(tp) slli \tmp, \tmp, PER_CPU_OFFSET_SHIFT la \dst, __per_cpu_offset add \dst, \dst, \tmp
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1821/1887 riscv: Remove SHADOW_OVERFLOW_STACK_SIZE macro
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Song Shuai <[email protected]>
[ Upstream commit a7565f4d068b2e60f95c3223c3167c40b8fe83ae ]
The commit be97d0db5f44 ("riscv: VMAP_STACK overflow detection thread-safe") got rid of shadow_stack, so SHADOW_OVERFLOW_STACK_SIZE should be removed too.
--- arch/riscv/include/asm/thread_info.h | 1 - 1 file changed, 1 deletion(-)
arch/riscv/include/asm/thread_info.h +0 -1
@@ -38,7 +38,6 @@#define THREAD_SHIFT (PAGE_SHIFT + THREAD_SIZE_ORDER)#define OVERFLOW_STACK_SIZE SZ_4K -#define SHADOW_OVERFLOW_STACK_SIZE (1024)#ifndef __ASSEMBLY__
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1822/1887 interconnect: Dont access req_list while its being manipulated
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mike Tipton <[email protected]>
[ Upstream commit de1bf25b6d771abdb52d43546cf57ad775fb68a1 ]
The icc_lock mutex was split into separate icc_lock and icc_bw_lock mutexes in [1] to avoid lockdep splats. However, this didn't adequately protect access to icc_node::req_list.
The icc_set_bw() function will eventually iterate over req_list while only holding icc_bw_lock, but req_list can be modified while only holding icc_lock. This causes races between icc_set_bw(), of_icc_get(), and icc_put().
Example A:
CPU0 CPU1
---- ----
icc_set_bw(path_a)
mutex_lock(&icc_bw_lock);
icc_put(path_b)
mutex_lock(&icc_lock);
aggregate_requests()
hlist_for_each_entry(r, ...
hlist_del(...
<r = invalid pointer>Example B:
CPU0 CPU1
---- ----
icc_set_bw(path_a)
mutex_lock(&icc_bw_lock);
path_b = of_icc_get()
of_icc_get_by_index()
mutex_lock(&icc_lock);
path_find()
path_init()
aggregate_requests()
hlist_for_each_entry(r, ...
hlist_add_head(...
<r = invalid pointer>Fix this by ensuring icc_bw_lock is always held before manipulating icc_node::req_list. The additional places icc_bw_lock is held don't perform any memory allocations, so we should still be safe from the original lockdep splats that motivated the separate locks.
[1] commit af42269c3523 ("interconnect: Fix locking for runpm vs reclaim")
--- drivers/interconnect/core.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/interconnect/core.c +8 -0
@@ -162,6 +162,8 @@ static struct icc_path *path_init(struct device *dev, struct icc_node *dst, path->num_nodes = num_nodes; +mutex_lock (&icc_bw_lock); +for (i = num_nodes -1 ; i >=0 ; i--) { node->provider->users++;hlist_add_head (&path->reqs[i].req_node, &node->req_list);
@@ -172,6 +174,8 @@ static struct icc_path *path_init(struct device *dev, struct icc_node *dst, node = node->reverse; } +mutex_unlock (&icc_bw_lock); +return path; }
@@ -779,12 +783,16 @@ void icc_put(struct icc_path *path)pr_err ("%s: error (%d)\n" , __func__, ret);mutex_lock (&icc_lock); +mutex_lock (&icc_bw_lock); +for (i =0 ; i < path->num_nodes; i++) { node = path->reqs[i].node;hlist_del (&path->reqs[i].req_node);if (!WARN_ON (!node->provider->users)) node->provider->users--; } + +mutex_unlock (&icc_bw_lock);mutex_unlock (&icc_lock);kfree_const (path->name);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1823/1887 Documentation: networking: Add a caveat to nexthop_compat_mode sysctl
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Petr Machata <[email protected]>
[ Upstream commit bbe4b41259a3e255a16d795486d331c1670b4e75 ]
net.ipv4.nexthop_compat_mode was added when nexthop objects were added to provide the view of nexthop objects through the usual lens of the route UAPI. As nexthop objects evolved, the information provided through this lens became incomplete. For example, details of resilient nexthop groups are obviously omitted.
Now that 16-bit nexthop group weights are a thing, the 8-bit UAPI cannot convey the >8-bit weight accurately. Instead of inventing workarounds for an obsolete interface, just document the expectations of inaccuracy.
--- Documentation/networking/ip-sysctl.rst | 6 ++++++ 1 file changed, 6 insertions(+)
Documentation/networking/ip-sysctl.rst +6 -0
@@ -2000,6 +2000,12 @@ nexthop_compat_mode - BOOLEAN understands the new API, this sysctl can be disabled to achieve full performance benefits of the new API by disabling the nexthop expansion and extraneous notifications. + + Note that as a backward-compatible mode, dumping of modern features + might be incomplete or wrong. For example, resilient groups will not be + shown as such, but rather as just a list of next hops. Also weights that + do not fit into 8 bits will show incorrectly. + Default: true (backward compat mode) fib_notify_on_flag_change - INTEGER
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1824/1887 net/sched: initialize noop_qdisc owner
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johannes Berg <[email protected]>
[ Upstream commit 44180feaccf266d9b0b28cc4ceaac019817deb5c ]
When the noop_qdisc owner isn't initialized, then it will be 0, so packets will erroneously be regarded as having been subject to recursion as long as only CPU 0 queues them. For non-SMP, that's all packets, of course. This causes a change in what's reported to userspace, normally noop_qdisc would drop packets silently, but with this change the syscall returns -ENOBUFS if RECVERR is also set on the socket.
Fix this by initializing the owner field to -1, just like it would be for dynamically allocated qdiscs by qdisc_alloc().
--- net/sched/sch_generic.c | 1 + 1 file changed, 1 insertion(+)
net/sched/sch_generic.c +1 -0
@@ -703,6 +703,7 @@ struct Qdisc noop_qdisc = { .qlen = 0, .lock = __SPIN_LOCK_UNLOCKED(noop_qdisc.skb_bad_txq.lock), }, + .owner = -1, };EXPORT_SYMBOL (noop_qdisc);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1825/1887 btrfs: fix race between ordered extent completion and fiemap
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Filipe Manana <[email protected]>
[ Upstream commit a1a4a9ca77f143c00fce69c1239887ff8b813bec ]
For fiemap we recently stopped locking the target extent range for the whole duration of the fiemap call, in order to avoid a deadlock in a scenario where the fiemap buffer happens to be a memory mapped range of the same file. This use case is very unlikely to be useful in practice but it may be triggered by fuzz testing (syzbot, etc).
However by not locking the target extent range for the whole duration of the fiemap call we can race with an ordered extent. This happens like this:
1) The fiemap task finishes processing a file extent item that covers the file range [512K, 1M[, and that file extent item is the last item in the leaf currently being processed;
2) And ordered extent for the file range [768K, 2M[, in COW mode, completes (btrfs_finish_one_ordered()) and the file extent item covering the range [512K, 1M[ is trimmed to cover the range [512K, 768K[ and then a new file extent item for the range [768K, 2M[ is inserted in the inode's subvolume tree;
3) The fiemap task calls fiemap_next_leaf_item(), which then calls btrfs_next_leaf() to find the next leaf / item. This finds that the the next key following the one we previously processed (its type is BTRFS_EXTENT_DATA_KEY and its offset is 512K), is the key corresponding to the new file extent item inserted by the ordered extent, which has a type of BTRFS_EXTENT_DATA_KEY and an offset of 768K;
4) Later the fiemap code ends up at emit_fiemap_extent() and triggers the warning:
if (cache->offset + cache->len > offset) {
WARN_ON(1);
return -EINVAL;
} Since we get 1M > 768K, because the previously emitted entry for the old extent covering the file range [512K, 1M[ ends at an offset that is greater than the new extent's start offset (768K). This makes fiemap fail with -EINVAL besides triggering the warning that produces a stack trace like the following:
[1621.677651] ------------[ cut here ]------------
[1621.677656] WARNING: CPU: 1 PID: 204366 at fs/btrfs/extent_io.c:2492 emit_fiemap_extent+0x84/0x90 [btrfs]
[1621.677899] Modules linked in: btrfs blake2b_generic (...)
[1621.677951] CPU: 1 PID: 204366 Comm: pool Not tainted 6.8.0-rc5-btrfs-next-151+ #1
[1621.677954] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.2-0-gea1b7a073390-prebuilt.qemu.org 04/01/2014
[1621.677956] RIP: 0010:emit_fiemap_extent+0x84/0x90 [btrfs]
[1621.678033] Code: 2b 4c 89 63 (...)
[1621.678035] RSP: 0018:ffffab16089ffd20 EFLAGS: 00010206
[1621.678037] RAX: 00000000004fa000 RBX: ffffab16089ffe08 RCX: 0000000000009000
[1621.678039] RDX: 00000000004f9000 RSI: 00000000004f1000 RDI: ffffab16089ffe90
[1621.678040] RBP: 00000000004f9000 R08: 0000000000001000 R09: 0000000000000000
[1621.678041] R10: 0000000000000000 R11: 0000000000001000 R12: 0000000041d78000
[1621.678043] R13: 0000000000001000 R14: 0000000000000000 R15: ffff9434f0b17850
[1621.678044] FS: 00007fa6e20006c0(0000) GS:ffff943bdfa40000(0000) knlGS:0000000000000000
[1621.678046] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[1621.678048] CR2: 00007fa6b0801000 CR3: 000000012d404002 CR4: 0000000000370ef0
[1621.678053] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[1621.678055] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[1621.678056] Call Trace:
[1621.678074] <TASK>
[1621.678076] ? __warn+0x80/0x130
[1621.678082] ? emit_fiemap_extent+0x84/0x90 [btrfs]
[1621.678159] ? report_bug+0x1f4/0x200
[1621.678164] ? handle_bug+0x42/0x70
[1621.678167] ? exc_invalid_op+0x14/0x70
[1621.678170] ? asm_exc_invalid_op+0x16/0x20
[1621.678178] ? emit_fiemap_extent+0x84/0x90 [btrfs]
[1621.678253] extent_fiemap+0x766/0xa30 [btrfs]
[1621.678339] btrfs_fiemap+0x45/0x80 [btrfs]
[1621.678420] do_vfs_ioctl+0x1e4/0x870
[1621.678431] __x64_sys_ioctl+0x6a/0xc0
[1621.678434] do_syscall_64+0x52/0x120
[1621.678445] entry_SYSCALL_64_after_hwframe+0x6e/0x76There's also another case where before calling btrfs_next_leaf() we are processing a hole or a prealloc extent and we had several delalloc ranges within that hole or prealloc extent. In that case if the ordered extents complete before we find the next key, we may end up finding an extent item with an offset smaller than (or equals to) the offset in cache->offset.
So fix this by changing emit_fiemap_extent() to address these three scenarios like this:
1) For the first case, steps listed above, adjust the length of the previously cached extent so that it does not overlap with the current extent, emit the previous one and cache the current file extent item;
2) For the second case where he had a hole or prealloc extent with multiple delalloc ranges inside the hole or prealloc extent's range, and the current file extent item has an offset that matches the offset in the fiemap cache, just discard what we have in the fiemap cache and assign the current file extent item to the cache, since it's more up to date;
3) For the third case where he had a hole or prealloc extent with multiple delalloc ranges inside the hole or prealloc extent's range and the offset of the file extent item we just found is smaller than what we have in the cache, just skip the current file extent item if its range end at or behind the cached extent's end, because we may have emitted (to the fiemap user space buffer) delalloc ranges that overlap with the current file extent item's range. If the file extent item's range goes beyond the end offset of the cached extent, just emit the cached extent and cache a subrange of the file extent item, that goes from the end offset of the cached extent to the end offset of the file extent item.
Dealing with those cases in those ways makes everything consistent by reflecting the current state of file extent items in the btree and without emitting extents that have overlapping ranges (which would be confusing and violating expectations).
This issue could be triggered often with test case generic/561, and was also hit and reported by Wang Yugui.
--- fs/btrfs/extent_io.c | 103 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 96 insertions(+), 7 deletions(-)
fs/btrfs/extent_io.c +96 -7
@@ -3502,6 +3502,7 @@ static int emit_fiemap_extent(struct fiemap_extent_info *fieinfo,struct fiemap_cache *cache, u64 offset, u64 phys, u64 len, u32 flags) { + u64 cache_end;int ret =0 ;/* Set at the end of extent_fiemap(). */
@@ -3511,15 +3512,102 @@ static int emit_fiemap_extent(struct fiemap_extent_info *fieinfo, goto assign;/* -* Sanity check, extent_fiemap() should have ensured that new -* fiemap extent won't overlap with cached one. -* Not recoverable. +* When iterating the extents of the inode, at extent_fiemap(), we may +* find an extent that starts at an offset behind the end offset of the +* previous extent we processed. This happens if fiemap is called +* without FIEMAP_FLAG_SYNC and there are ordered extents completing +* while we call btrfs_next_leaf() (through fiemap_next_leaf_item()). * -* NOTE: Physical address can overlap, due to compression +* For example we are in leaf X processing its last item, which is the +* file extent item for file range [512K, 1M[, and after +* btrfs_next_leaf() releases the path, there's an ordered extent that +* completes for the file range [768K, 2M[, and that results in trimming +* the file extent item so that it now corresponds to the file range +* [512K, 768K[ and a new file extent item is inserted for the file +* range [768K, 2M[, which may end up as the last item of leaf X or as +* the first item of the next leaf - in either case btrfs_next_leaf() +* will leave us with a path pointing to the new extent item, for the +* file range [768K, 2M[, since that's the first key that follows the +* last one we processed. So in order not to report overlapping extents +* to user space, we trim the length of the previously cached extent and +* emit it. +* +* Upon calling btrfs_next_leaf() we may also find an extent with an +* offset smaller than or equals to cache->offset, and this happens +* when we had a hole or prealloc extent with several delalloc ranges in +* it, but after btrfs_next_leaf() released the path, delalloc was +* flushed and the resulting ordered extents were completed, so we can +* now have found a file extent item for an offset that is smaller than +* or equals to what we have in cache->offset. We deal with this as +* described below. */ -if (cache->offset + cache->len > offset) { -WARN_ON (1 ); -return -EINVAL ; + cache_end = cache->offset + cache->len; +if (cache_end > offset) { +if (offset == cache->offset) { +/* +* We cached a dealloc range (found in the io tree) for +* a hole or prealloc extent and we have now found a +* file extent item for the same offset. What we have +* now is more recent and up to date, so discard what +* we had in the cache and use what we have just found. +*/ + goto assign; + }else if (offset > cache->offset) { +/* +* The extent range we previously found ends after the +* offset of the file extent item we found and that +* offset falls somewhere in the middle of that previous +* extent range. So adjust the range we previously found +* to end at the offset of the file extent item we have +* just found, since this extent is more up to date. +* Emit that adjusted range and cache the file extent +* item we have just found. This corresponds to the case +* where a previously found file extent item was split +* due to an ordered extent completing. +*/ + cache->len = offset - cache->offset; + goto emit; + }else { +const u64 range_end = offset + len; + +/* +* The offset of the file extent item we have just found +* is behind the cached offset. This means we were +* processing a hole or prealloc extent for which we +* have found delalloc ranges (in the io tree), so what +* we have in the cache is the last delalloc range we +* found while the file extent item we found can be +* either for a whole delalloc range we previously +* emmitted or only a part of that range. +* +* We have two cases here: +* +* 1) The file extent item's range ends at or behind the +* cached extent's end. In this case just ignore the +* current file extent item because we don't want to +* overlap with previous ranges that may have been +* emmitted already; +* +* 2) The file extent item starts behind the currently +* cached extent but its end offset goes beyond the +* end offset of the cached extent. We don't want to +* overlap with a previous range that may have been +* emmitted already, so we emit the currently cached +* extent and then partially store the current file +* extent item's range in the cache, for the subrange +* going the cached extent's end to the end of the +* file extent item. +*/ +if (range_end <= cache_end) +return 0 ; + +if (!(flags & (FIEMAP_EXTENT_ENCODED |FIEMAP_EXTENT_DELALLOC ))) + phys += cache_end - offset; + + offset = cache_end; + len = range_end - cache_end; + goto emit; + } }/*
@@ -3539,6 +3627,7 @@ static int emit_fiemap_extent(struct fiemap_extent_info *fieinfo,return 0 ; } +emit:/* Not mergeable, need to submit cached one */ ret =fiemap_fill_next_extent (fieinfo, cache->offset, cache->phys, cache->len, cache->flags);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1826/1887 bpf: Fix a potential use-after-free in bpf_link_free()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cong Wang <[email protected]>
[ Upstream commit 2884dc7d08d98a89d8d65121524bb7533183a63a ]
After commit 1a80dbcb2dba, bpf_link can be freed by link->ops->dealloc_deferred, but the code still tests and uses link->ops->dealloc afterward, which leads to a use-after-free as reported by syzbot. Actually, one of them should be sufficient, so just call one of them instead of both. Also add a WARN_ON() in case of any problematic implementation.
--- kernel/bpf/syscall.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
kernel/bpf/syscall.c +6 -5
@@ -2725,6 +2725,7 @@ static int bpf_obj_get(const union bpf_attr *attr)void bpf_link_init (struct bpf_link *link,enum bpf_link_type type,const struct bpf_link_ops *ops,struct bpf_prog *prog) { +WARN_ON (ops->dealloc && ops->dealloc_deferred);atomic64_set (&link->refcnt,1 ); link->type = type; link->id =0 ;
@@ -2781,16 +2782,17 @@ static void bpf_link_defer_dealloc_mult_rcu_gp(struct rcu_head *rcu)/* bpf_link_free is guaranteed to be called from process context */ static void bpf_link_free (struct bpf_link *link) { +const struct bpf_link_ops *ops = link->ops;bool sleepable = false;bpf_link_free_id (link->id);if (link->prog) { sleepable = link->prog->aux->sleepable;/* detach BPF program, clean up used resources */ - link->ops->release (link); + ops->release (link);bpf_prog_put (link->prog); } -if (link->ops->dealloc_deferred) { +if (ops->dealloc_deferred) {/* schedule BPF link deallocation; if underlying BPF program * is sleepable, we need to first wait for RCU tasks trace * sync, then go through "classic" RCU grace period
@@ -2799,9 +2801,8 @@ static void bpf_link_free(struct bpf_link *link)call_rcu_tasks_trace (&link->rcu, bpf_link_defer_dealloc_mult_rcu_gp); else call_rcu(&link->rcu, bpf_link_defer_dealloc_rcu_gp); - } -if (link->ops->dealloc) - link->ops->dealloc (link); + }else if (ops->dealloc) + ops->dealloc (link); }static void bpf_link_put_deferred (struct work_struct *work)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1827/1887 f2fs: fix node_cnt race between extent node destroy and writeback
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yongpeng Yang <[email protected]>
[ Upstream commit ed78aeebef05212ef7dca93bd931e4eff67c113f ]
f2fs_destroy_extent_node() does not set FI_NO_EXTENT before clearing extent nodes. When called from f2fs_drop_inode() with I_SYNC set, concurrent kworker writeback can insert new extent nodes into the same extent tree, racing with the destroy and triggering f2fs_bug_on() in __destroy_extent_node(). The scenario is as follows:
drop inode writeback
- iput
- f2fs_drop_inode // I_SYNC set
- f2fs_destroy_extent_node
- __destroy_extent_node
- while (node_cnt) {
write_lock(&et->lock)
__free_extent_tree
write_unlock(&et->lock)
- __writeback_single_inode
- f2fs_outplace_write_data
- f2fs_update_read_extent_cache
- __update_extent_tree_range // FI_NO_EXTENT not set, // insert new extent node
} // node_cnt == 0, exit while
- f2fs_bug_on(node_cnt) // node_cnt > 0
Additionally, __update_extent_tree_range() only checks FI_NO_EXTENT for EX_READ type, leaving EX_BLOCK_AGE updates completely unprotected.
This patch set FI_NO_EXTENT under et->lock in __destroy_extent_node(), consistent with other callers (__update_extent_tree_range and __drop_extent_tree) and check FI_NO_EXTENT for both EX_READ and EX_BLOCK_AGE tree.
--- fs/f2fs/extent_cache.c | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-)
fs/f2fs/extent_cache.c +10 -7
@@ -76,9 +76,10 @@ static bool __may_extent_tree(struct inode *inode, enum extent_type type)if (!__init_may_extent_tree (inode, type))return false; +if (is_inode_flag_set (inode,FI_NO_EXTENT )) +return false; +if (type ==EX_READ ) { -if (is_inode_flag_set (inode,FI_NO_EXTENT )) -return false;if (is_inode_flag_set (inode,FI_COMPRESSED_FILE ) && !f2fs_sb_has_readonly (F2FS_I_SB (inode)))return false;
@@ -623,6 +624,8 @@ static unsigned int __destroy_extent_node(struct inode *inode,while (atomic_read (&et->node_cnt)) {write_lock (&et->lock); +if (!is_inode_flag_set (inode,FI_NO_EXTENT )) +set_inode_flag (inode,FI_NO_EXTENT ); node_cnt +=__free_extent_tree (sbi, et, nr_shrink);write_unlock (&et->lock); }
@@ -654,12 +657,12 @@ static void __update_extent_tree_range(struct inode *inode, tei->blk, 0);write_lock (&et->lock); -if (type ==EX_READ ) { -if (is_inode_flag_set (inode,FI_NO_EXTENT )) { -write_unlock (&et->lock); -return ; - } +if (is_inode_flag_set (inode,FI_NO_EXTENT )) { +write_unlock (&et->lock); +return ; + } +if (type ==EX_READ ) { prev = et->largest; dei.len =0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1828/1887 pinmux: fix race causing mux_owner NULL with active mux_usecount
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mukesh Ojha <[email protected]>
[ Upstream commit 0b075c011032f88d1cfde3b45d6dcf08b44140eb ]
commit 5a3e85c3c397 ("pinmux: Use sequential access to access desc->pinmux data") tried to address the issue when two client of the same gpio calls pinctrl_select_state() for the same functionality, was resulting in NULL pointer issue while accessing desc->mux_owner. However, issue was not completely fixed due to the way it was handled and it can still result in the same NULL pointer.
The issue occurs due to the following interleaving:
cpu0 (process A) cpu1 (process B)
pin_request() { pin_free() {
mutex_lock()
desc->mux_usecount--; //becomes 0
..
mutex_unlock()mutex_lock(desc->mux) desc->mux_usecount++; // becomes 1 desc->mux_owner = owner; mutex_unlock(desc->mux)
mutex_lock(desc->mux)
desc->mux_owner = NULL;
mutex_unlock(desc->mux)This sequence leads to a state where the pin appears to be in use (mux_usecount == 1) but has no owner (mux_owner == NULL), which can cause NULL pointer on next pin_request on the same pin.
Ensure that updates to mux_usecount and mux_owner are performed atomically under the same lock. Only clear mux_owner when mux_usecount reaches zero and no new owner has been assigned.
--- drivers/pinctrl/pinmux.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-)
drivers/pinctrl/pinmux.c +9 -11
@@ -235,18 +235,7 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin,if (desc->mux_usecount)return NULL ; } - } - -/* -* If there is no kind of request function for the pin we just assume -* we got it by default and proceed. -*/ -if (gpio_range && ops->gpio_disable_free) - ops->gpio_disable_free (pctldev, gpio_range, pin); -else if (ops->free) - ops->free (pctldev, pin); - scoped_guard(mutex, &desc->mux_lock) {if (gpio_range) { owner = desc->gpio_owner; desc->gpio_owner =NULL ;
@@ -257,6 +246,15 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin, } } +/* +* If there is no kind of request function for the pin we just assume +* we got it by default and proceed. +*/ +if (gpio_range && ops->gpio_disable_free) + ops->gpio_disable_free (pctldev, gpio_range, pin); +else if (ops->free) + ops->free (pctldev, pin); +module_put (pctldev->owner);return owner;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1829/1887 drm/amd/display: drop unused function set_abm_event()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hamza Mahfooz <[email protected]>
[ Upstream commit fd73c8507675f6bccc039cf319f183e41e447cb7 ]
set_abm_event() is never actually used. So, drop it.
--- drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c | 12 ------------ drivers/gpu/drm/amd/display/dc/inc/hw/abm.h | 2 -- 2 files changed, 14 deletions(-)
drivers/gpu/drm/amd/display/dc/dce/dmub_abm.c +0 -12
@@ -131,17 +131,6 @@ static bool dmub_abm_set_pipe_ex(struct abm *abm, uint32_t otg_inst, uint32_t opreturn ret; } -static bool dmub_abm_set_event_ex (struct abm *abm,unsigned int full_screen,unsigned int video_mode, -unsigned int hdr_mode,unsigned int panel_inst) -{ -bool ret = false; -unsigned int feature_support; - - feature_support =abm_feature_support (abm, panel_inst); - -return ret; -} - static bool dmub_abm_set_backlight_level_pwm_ex(struct abm *abm, unsigned int backlight_pwm_u16_16, unsigned int frame_ramp,
@@ -167,7 +156,6 @@ static const struct abm_funcs abm_funcs = { .init_abm_config = dmub_abm_init_config_ex, .set_abm_pause = dmub_abm_set_pause_ex, .set_pipe_ex = dmub_abm_set_pipe_ex, - .set_abm_event = dmub_abm_set_event_ex, .set_backlight_level_pwm = dmub_abm_set_backlight_level_pwm_ex, };
drivers/gpu/drm/amd/display/dc/inc/hw/abm.h +0 -2
@@ -59,8 +59,6 @@ struct abm_funcs {unsigned int otg_inst, unsigned int option, unsigned int panel_inst); -bool (*set_abm_event)(struct abm *abm,unsigned int full_screen,unsigned int video_mode, - unsigned int hdr_mode, unsigned int panel_inst); };#endif
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1830/1887 drm/amd/display: Fix null check for pipe_ctx->plane_state in dcn20_program_pipe
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zicheng Qu <[email protected]>
[ Upstream commit 6a057072ddd127255350357dd880903e8fa23f36 ]
This commit addresses a null pointer dereference issue in dcn20_program_pipe(). Previously, commit 8e4ed3cf1642 ("drm/amd/display:
Add null check for pipe_ctx->plane_state in dcn20_program_pipe") partially fixed the null pointer dereference issue. However, in dcn20_update_dchubp_dpp(), the variable pipe_ctx is passed in, and plane_state is accessed again through pipe_ctx. Multiple if statements directly call attributes of plane_state, leading to potential null pointer dereference issues. This patch adds necessary null checks to ensure stability.
--- drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +3 -3
@@ -1693,9 +1693,9 @@ static void dcn20_program_pipe( dc->res_pool->hubbub->funcs->program_det_size ( dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->det_buffer_size_kb); -if (pipe_ctx->update_flags.raw || - (pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.raw) || - pipe_ctx->stream->update_flags.raw) +if (pipe_ctx->plane_state && (pipe_ctx->update_flags.raw || + pipe_ctx->plane_state->update_flags.raw || + pipe_ctx->stream->update_flags.raw))dcn20_update_dchubp_dpp (dc, pipe_ctx, context); if ((pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.bits.hdr_mult) ||
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1831/1887 drm/amd/display: Remove unused-but-set variable hubp from
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gleb Markov <[email protected]>
[ Upstream commit b736792e5bd4a62f24e8d1e310bf4a75bfbeaaaa ]
The final check of hubp for NULL covers all remaining lines of code, since the value of hubp does not change until the end of the method.
This check is redundant because hubp1 is already dereferenced within the macro.
If it were NULL, the program would have already failed to proceed.
Remove the left part of the expression with the logical "&&".
Found by Linux Verification Center (linuxtesting.org) with SVACE.
--- drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_hubp.c +1 -2
@@ -749,8 +749,7 @@ bool hubp1_is_flip_pending(struct hubp *hubp)if (flip_pending)return true; -if (hubp && - earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part) +if (earliest_inuse_address.grph.addr.quad_part != hubp->request_address.grph.addr.quad_part)return true;return false;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1832/1887 firmware: arm_scmi: Move errors defs and code to common.h
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cristian Marussi <[email protected]>
[ Upstream commit 936a2b91c2e8ac9570e080e654bf53f799cbc028 ]
Move SCMI error codes definitions and helper to the common.h header together with the delayed response timeout define.
No functional change.
Stable-dep-of: a71a3d4d8a6e ("firmware: arm_scmi: Use channel ID for transport teardown")
--- drivers/firmware/arm_scmi/common.h | 40 ++++++++++++++++++++++++++++++ drivers/firmware/arm_scmi/driver.c | 40 ------------------------------ 2 files changed, 40 insertions(+), 40 deletions(-)
drivers/firmware/arm_scmi/common.h +40 -0
@@ -27,6 +27,46 @@#include "protocols.h" #include "notify.h" +#define SCMI_MAX_RESPONSE_TIMEOUT (2 * MSEC_PER_SEC) + +enum scmi_error_codes { +SCMI_SUCCESS =0 ,/* Success */ +SCMI_ERR_SUPPORT =-1 ,/* Not supported */ +SCMI_ERR_PARAMS =-2 ,/* Invalid Parameters */ +SCMI_ERR_ACCESS =-3 ,/* Invalid access/permission denied */ +SCMI_ERR_ENTRY =-4 ,/* Not found */ +SCMI_ERR_RANGE =-5 ,/* Value out of range */ +SCMI_ERR_BUSY =-6 ,/* Device busy */ +SCMI_ERR_COMMS =-7 ,/* Communication Error */ +SCMI_ERR_GENERIC =-8 ,/* Generic Error */ +SCMI_ERR_HARDWARE =-9 ,/* Hardware Error */ +SCMI_ERR_PROTOCOL =-10 ,/* Protocol Error */ +}; + +static const int scmi_linux_errmap[] = { +/* better than switch case as long as return value is continuous */ +0 ,/* SCMI_SUCCESS */ + -EOPNOTSUPP ,/* SCMI_ERR_SUPPORT */ + -EINVAL ,/* SCMI_ERR_PARAM */ + -EACCES ,/* SCMI_ERR_ACCESS */ + -ENOENT ,/* SCMI_ERR_ENTRY */ + -ERANGE ,/* SCMI_ERR_RANGE */ + -EBUSY ,/* SCMI_ERR_BUSY */ + -ECOMM ,/* SCMI_ERR_COMMS */ + -EIO ,/* SCMI_ERR_GENERIC */ + -EREMOTEIO ,/* SCMI_ERR_HARDWARE */ + -EPROTO ,/* SCMI_ERR_PROTOCOL */ +}; + +static inline int scmi_to_linux_errno (int errno) +{ +int err_idx = -errno; + +if (err_idx >=SCMI_SUCCESS && err_idx <ARRAY_SIZE (scmi_linux_errmap)) +return scmi_linux_errmap[err_idx]; +return -EIO ; +} +#define MSG_ID_MASK GENMASK(7, 0)#define MSG_XTRACT_ID (hdr) FIELD_GET(MSG_ID_MASK, (hdr))#define MSG_TYPE_MASK GENMASK(9, 8)
drivers/firmware/arm_scmi/driver.c +0 -40
@@ -37,20 +37,6 @@#define CREATE_TRACE_POINTS #include <trace/events/scmi.h> -enum scmi_error_codes { -SCMI_SUCCESS =0 ,/* Success */ -SCMI_ERR_SUPPORT =-1 ,/* Not supported */ -SCMI_ERR_PARAMS =-2 ,/* Invalid Parameters */ -SCMI_ERR_ACCESS =-3 ,/* Invalid access/permission denied */ -SCMI_ERR_ENTRY =-4 ,/* Not found */ -SCMI_ERR_RANGE =-5 ,/* Value out of range */ -SCMI_ERR_BUSY =-6 ,/* Device busy */ -SCMI_ERR_COMMS =-7 ,/* Communication Error */ -SCMI_ERR_GENERIC =-8 ,/* Generic Error */ -SCMI_ERR_HARDWARE =-9 ,/* Hardware Error */ -SCMI_ERR_PROTOCOL =-10 ,/* Protocol Error */ -}; -static DEFINE_IDR (scmi_protocols);static DEFINE_SPINLOCK (protocol_lock);
@@ -167,30 +153,6 @@ struct scmi_info {#define bus_nb_to_scmi_info (nb) container_of(nb, struct scmi_info, bus_nb)#define req_nb_to_scmi_info (nb) container_of(nb, struct scmi_info, dev_req_nb) -static const int scmi_linux_errmap[] = { -/* better than switch case as long as return value is continuous */ -0 ,/* SCMI_SUCCESS */ - -EOPNOTSUPP ,/* SCMI_ERR_SUPPORT */ - -EINVAL ,/* SCMI_ERR_PARAM */ - -EACCES ,/* SCMI_ERR_ACCESS */ - -ENOENT ,/* SCMI_ERR_ENTRY */ - -ERANGE ,/* SCMI_ERR_RANGE */ - -EBUSY ,/* SCMI_ERR_BUSY */ - -ECOMM ,/* SCMI_ERR_COMMS */ - -EIO ,/* SCMI_ERR_GENERIC */ - -EREMOTEIO ,/* SCMI_ERR_HARDWARE */ - -EPROTO ,/* SCMI_ERR_PROTOCOL */ -}; - -static inline int scmi_to_linux_errno (int errno) -{ -int err_idx = -errno; - -if (err_idx >=SCMI_SUCCESS && err_idx <ARRAY_SIZE (scmi_linux_errmap)) -return scmi_linux_errmap[err_idx]; -return -EIO ; -} -static const struct scmi_protocol *scmi_protocol_get (int protocol_id) {const struct scmi_protocol *proto;
@@ -1015,8 +977,6 @@ static void reset_rx_to_maxsz(const struct scmi_protocol_handle *ph, xfer->rx.len = info->desc->max_msg_size; } -#define SCMI_MAX_RESPONSE_TIMEOUT (2 * MSEC_PER_SEC) -/** * do_xfer_with_response() - Do one transfer and wait until the delayed * response is received
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1833/1887 firmware: arm_scmi: Add internal platform/channel identifiers
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cristian Marussi <[email protected]>
[ Upstream commit 75c86dc72dc80604e5e50fabb3c0cadee8c6087a ]
Add a couple of unique identifiers to channel and platform instance descriptors in order to emit more descriptive message dump traces.
Stable-dep-of: a71a3d4d8a6e ("firmware: arm_scmi: Use channel ID for transport teardown")
--- drivers/firmware/arm_scmi/common.h | 3 +++ drivers/firmware/arm_scmi/driver.c | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-)
drivers/firmware/arm_scmi/common.h +3 -0
@@ -159,6 +159,8 @@ void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id);/** * struct scmi_chan_info - Structure representing a SCMI channel information * +* @id: An identifier for this channel: this matches the protocol number +* used to initialize this channel * @dev: Reference to device in the SCMI hierarchy corresponding to this * channel * @rx_timeout_ms: The configured RX timeout in milliseconds.
@@ -170,6 +172,7 @@ void scmi_protocol_release(const struct scmi_handle *handle, u8 protocol_id);* @transport_info: Transport layer related information */ struct scmi_chan_info { +int id;struct device *dev;unsigned int rx_timeout_ms;struct scmi_handle *handle;
drivers/firmware/arm_scmi/driver.c +15 -2
@@ -37,6 +37,8 @@#define CREATE_TRACE_POINTS #include <trace/events/scmi.h> +static DEFINE_IDA (scmi_id); +static DEFINE_IDR (scmi_protocols);static DEFINE_SPINLOCK (protocol_lock);
@@ -96,6 +98,7 @@ struct scmi_protocol_instance {/** * struct scmi_info - Structure representing a SCMI instance * +* @id: A sequence number starting from zero identifying this instance * @dev: Device pointer * @desc: SoC description for this instance * @version: SCMI revision information containing protocol version,
@@ -128,6 +131,7 @@ struct scmi_protocol_instance {* bus */ struct scmi_info { +int id;struct device *dev;const struct scmi_desc *desc;struct scmi_revision_info version;
@@ -2102,6 +2106,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node, }of_node_get (of_node); + cinfo->id = prot_id; cinfo->dev = &tdev->dev; cinfo->handle = &info->handle; ret = info->desc->ops->chan_setup (cinfo, info->dev, tx);
@@ -2314,6 +2319,10 @@ static int scmi_probe(struct platform_device *pdev)if (!info)return -ENOMEM ; + info->id =ida_alloc_min (&scmi_id,0 ,GFP_KERNEL ); +if (info->id <0 ) +return info->id; + info->dev = dev; info->desc = desc; info->bus_nb.notifier_call = scmi_bus_notifier;
@@ -2345,13 +2354,13 @@ static int scmi_probe(struct platform_device *pdev)if (desc->ops->link_supplier) { ret = desc->ops->link_supplier (dev);if (ret) -return ret; + goto clear_ida; }/* Setup all channels described in the DT at first */ ret =scmi_channels_setup (info);if (ret) -return ret; + goto clear_ida; ret =bus_register_notifier (&scmi_bus_type, &info->bus_nb);if (ret)
@@ -2429,6 +2438,8 @@ static int scmi_probe(struct platform_device *pdev)bus_unregister_notifier (&scmi_bus_type, &info->bus_nb); clear_txrx_setup:scmi_cleanup_txrx_channels (info); +clear_ida: +ida_free (&scmi_id, info->id);return ret; }
@@ -2462,6 +2473,8 @@ static int scmi_remove(struct platform_device *pdev)/* Safe to free channels since no more users */ scmi_cleanup_txrx_channels (info); +ida_free (&scmi_id, info->id); +return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1834/1887 firmware: arm_scmi: Use channel ID for transport teardown
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit a71a3d4d8a6e9e399fd988c0e6da47a6ee21c99e ]
SCMI protocols can share the BASE transport channel when firmware does not describe a dedicated channel for the protocol. In that case multiple IDR entries can point at the same scmi_chan_info, whose owning transport device was created with cinfo->id.
scmi_chan_destroy() used the IDR iterator key when destroying the transport device. If an alias entry is visited before the owning channel entry, the lookup can miss the device because the iterator key does not match the protocol ID used when the transport device was created. The code then clears cinfo->dev, so the later owning entry skips teardown and leaks the transport device.
Destroy the transport device using cinfo->id, which is the protocol ID that owns the channel and was used when creating the transport device.
--- drivers/firmware/arm_scmi/driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/firmware/arm_scmi/driver.c +1 -1
@@ -2217,7 +2217,7 @@ static int scmi_chan_destroy(int id, void *p, void *idr)struct scmi_device *sdev =to_scmi_dev (cinfo->dev);of_node_put (cinfo->dev->of_node); -scmi_device_destroy (info->dev, id, sdev->name); +scmi_device_destroy (info->dev, cinfo->id, sdev->name); cinfo->dev =NULL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1835/1887 firmware: arm_scmi: Reject out of range DT protocol IDs
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit 59407ccb52130f2c81f4b3cbe4f14114afceb54f ]
SCMI protocol IDs carried in message headers are limited by MSG_PROTOCOL_ID_MASK. The DT parsing paths noticed protocol IDs outside that range, but only logged an error and then kept processing the invalid value.
That lets a malformed 32-bit DT reg value reach helpers which take a u8 protocol ID, where it can be truncated and/or treated as a different protocol.
For channel setup, two different out-of-range values can also be used as distinct IDR keys while aliasing the generated SCMI protocol identity.
Skip DT protocol nodes whose reg value does not fit the SCMI protocol ID field before setting up channels or creating protocol devices.
--- drivers/firmware/arm_scmi/driver.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/firmware/arm_scmi/driver.c +6 -2
@@ -2194,9 +2194,11 @@ static int scmi_channels_setup(struct scmi_info *info)if (of_property_read_u32 (child,"reg" , &prot_id))continue ; -if (!FIELD_FIT (MSG_PROTOCOL_ID_MASK , prot_id)) +if (!FIELD_FIT (MSG_PROTOCOL_ID_MASK , prot_id)) {dev_err (info->dev,"Out of range protocol %d\n" , prot_id); +continue ; + } ret =scmi_txrx_setup (info, child, prot_id);if (ret) {
@@ -2403,8 +2405,10 @@ static int scmi_probe(struct platform_device *pdev)if (of_property_read_u32 (child,"reg" , &prot_id))continue ; -if (!FIELD_FIT (MSG_PROTOCOL_ID_MASK , prot_id)) +if (!FIELD_FIT (MSG_PROTOCOL_ID_MASK , prot_id)) {dev_err (dev,"Out of range protocol %d\n" , prot_id); +continue ; + }if (!scmi_is_protocol_implemented (handle, prot_id)) { dev_err(dev, "SCMI protocol %d not implemented\n",
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1836/1887 firmware: arm_scmi: Avoid IDR updates while cleaning channels
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit c38b1e19485aaa820e52cfe162525a8af67563da ]
scmi_cleanup_channels() walks the TX/RX channel IDRs with idr_for_each() to free transport resources and destroy the dedicated transport devices before calling idr_destroy().
The destroy callback removed each entry from the same IDR being walked. That is not needed for this cleanup path, and it is unsafe because idr_for_each() has not advanced its radix-tree iterator while the callback is running. Removing the current entry from the callback can invalidate the iterator state. The callback also cannot be protected by rcu_read_lock(), because scmi_device_destroy() may sleep.
Leave IDR teardown to the following idr_destroy() call and keep the callback limited to device destruction.
--- drivers/firmware/arm_scmi/driver.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
drivers/firmware/arm_scmi/driver.c +1 -3
@@ -2210,7 +2210,7 @@ static int scmi_channels_setup(struct scmi_info *info)return 0 ; } -static int scmi_chan_destroy (int id,void *p,void *idr) +static int scmi_chan_destroy (int id,void *p,void *data) {struct scmi_chan_info *cinfo = p;
@@ -2223,8 +2223,6 @@ static int scmi_chan_destroy(int id, void *p, void *idr) cinfo->dev =NULL ; } -idr_remove (idr, id); -return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1837/1887 firmware: arm_scmi: Protect device request lookup with RCU
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit e6a0e7a49d83e4fa4e1db68d74f99282eb97aa49 ]
The SCMI device request notifier looks up protocol OF nodes from the active_protocols IDR. The IDR lookup can run concurrently with protocol activation while probe is still registering protocols and creating their SCMI devices.
Wrap the lookup in an RCU read-side critical section as required by the IDR API for lockless readers.
--- drivers/firmware/arm_scmi/driver.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/firmware/arm_scmi/driver.c +3 -0
@@ -28,6 +28,7 @@#include <linux/of_address.h> #include <linux/of_device.h> #include <linux/processor.h> +#include <linux/rcupdate.h> #include <linux/refcount.h> #include <linux/slab.h>
@@ -2282,7 +2283,9 @@ static int scmi_device_request_notifier(struct notifier_block *nb,struct scmi_device_id *id_table = data;struct scmi_info *info =req_nb_to_scmi_info (nb); +rcu_read_lock (); np =idr_find (&info->active_protocols, id_table->protocol_id); +rcu_read_unlock ();if (!np)return NOTIFY_DONE ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1838/1887 firmware: arm_scmi: Free transport channel on IDR failure
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit d72e7e5f24687c0490aabf317653caffe0447aeb ]
If transport channel setup succeeds but the following IDR insertion fails, the error path destroys the transport device and frees the channel info without invoking the transport cleanup callback.
Call chan_free() before destroying the device so transport specific resources such as IRQs, mailbox channels and mapped shared memory are released consistently with the normal teardown path.
--- drivers/firmware/arm_scmi/driver.c | 1 + 1 file changed, 1 insertion(+)
drivers/firmware/arm_scmi/driver.c +1 -0
@@ -2135,6 +2135,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node, "unable to allocate SCMI idr slot err %d\n", ret);/* Destroy channel and device only if created by this call. */ if (tdev) { + info->desc->ops->chan_free (prot_id, cinfo, idr);of_node_put (of_node);scmi_device_destroy (info->dev, prot_id, name);devm_kfree (info->dev, cinfo);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1839/1887 firmware: arm_scmi: Unregister device notifier before IDR teardown
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit 66a0bbf30cc14140fe13f63cd594a7c1ee352b75 ]
The requested-devices notifier looks up protocol fwnodes from the active_protocols IDR. During remove, unregister the notifier before releasing and destroying active_protocols so no notifier callback can race with the IDR teardown.
Keep the bus notifier registered until after the protocol state is torn down, matching the existing remove ordering for SCMI bus users.
--- drivers/firmware/arm_scmi/driver.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/firmware/arm_scmi/driver.c +3 -2
@@ -2462,6 +2462,9 @@ static int scmi_remove(struct platform_device *pdev)list_del (&info->node);mutex_unlock (&scmi_list_mutex); +blocking_notifier_chain_unregister (&scmi_requested_devices_nh, + &info->dev_req_nb); +scmi_notification_exit (&info->handle);mutex_lock (&info->protocols_mtx);
@@ -2472,8 +2475,6 @@ static int scmi_remove(struct platform_device *pdev)of_node_put (child);idr_destroy (&info->active_protocols); -blocking_notifier_chain_unregister (&scmi_requested_devices_nh, - &info->dev_req_nb);bus_unregister_notifier (&scmi_bus_type, &info->bus_nb);/* Safe to free channels since no more users */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1840/1887 firmware: arm_scmi: Add multiple protocols registration support
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cristian Marussi <[email protected]>
[ Upstream commit 2858f6e5f06440d6b9e9c3f57bc68915344830a9 ]
Add the capability for a SCMI driver to register to the core SCMI stack with multiple SCMI protocols. In such a case the SCMI driver probe function will end up being called once for each registered protocol which have been also found as implemented on the platform.
This is especially useful in testing scenarios.
Stable-dep-of: 9f7cd6a62aa7 ("firmware: arm_scmi: Unrequest devices if driver registration fails")
--- drivers/firmware/arm_scmi/bus.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-)
drivers/firmware/arm_scmi/bus.c +22 -2
@@ -134,6 +134,17 @@ static int scmi_protocol_device_request(const struct scmi_device_id *id_table)return ret; } +static int scmi_protocol_table_register (const struct scmi_device_id *id_table) +{ +int ret =0 ; +const struct scmi_device_id *entry; + +for (entry = id_table; entry->name && ret ==0 ; entry++) + ret =scmi_protocol_device_request (entry); + +return ret; +} +/** * scmi_protocol_device_unrequest - Helper to unrequest a device *
@@ -179,6 +190,15 @@ static void scmi_protocol_device_unrequest(const struct scmi_device_id *id_tablemutex_unlock (&scmi_requested_devices_mtx); } +static void +scmi_protocol_table_unregister (const struct scmi_device_id *id_table) +{ +const struct scmi_device_id *entry; + +for (entry = id_table; entry->name; entry++) +scmi_protocol_device_unrequest (entry); +} +static const struct scmi_device_id *scmi_dev_match_id (struct scmi_device *scmi_dev,struct scmi_driver *scmi_drv) {
@@ -273,7 +293,7 @@ int scmi_driver_register(struct scmi_driver *driver, struct module *owner,if (!driver->probe)return -EINVAL ; - retval =scmi_protocol_device_request (driver->id_table); + retval =scmi_protocol_table_register (driver->id_table);if (retval)return retval;
@@ -293,7 +313,7 @@ EXPORT_SYMBOL_GPL(scmi_driver_register);void scmi_driver_unregister (struct scmi_driver *driver) {driver_unregister (&driver->driver); -scmi_protocol_device_unrequest (driver->id_table); +scmi_protocol_table_unregister (driver->id_table); }EXPORT_SYMBOL_GPL (scmi_driver_unregister);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1841/1887 firmware: arm_scmi: Unrequest devices if driver registration fails
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit 9f7cd6a62aa754ed6b48cbd5d50de40add1bcc86 ]
scmi_driver_register() requests protocol devices before registering the driver. If driver_register() fails, those requests remain in the global IDR and retain pointers to the module's ID table. Once the failed module load releases that storage, later request matching or SCMI device creation can dereference the stale pointers.
Unrequest the complete protocol table before returning the registration failure. At this point table registration succeeded, so every entry is owned by the current registration attempt.
--- drivers/firmware/arm_scmi/bus.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/firmware/arm_scmi/bus.c +7 -3
@@ -303,10 +303,14 @@ int scmi_driver_register(struct scmi_driver *driver, struct module *owner, driver->driver.mod_name = mod_name; retval =driver_register (&driver->driver); -if (!retval) -pr_debug ("Registered new scmi driver %s\n" , driver->name); +if (retval) { +scmi_protocol_table_unregister (driver->id_table); +return retval; + } -return retval; +pr_debug ("Registered new scmi driver %s\n" , driver->name); + +return 0 ; }EXPORT_SYMBOL_GPL (scmi_driver_register);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1842/1887 firmware: arm_scmi: Fix requested device removal race
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit 2c4097e6c4aed276c5e9ec2ab331ab397ea780bf ]
scmi_protocol_device_unrequest() drops scmi_requested_devices_mtx while notifying listeners but continues to retain the per-protocol list head. When two SCMI drivers for the same protocol unregister concurrently, one thread can remove the final request and free the list head while the other is running its notifier. The latter then dereferences the freed list head after reacquiring the mutex and can free it a second time.
Complete the list and IDR updates, including freeing an empty list head, before dropping the mutex. Keep the blocking notifier outside the critical section and retain only the detached request across the callback.
--- drivers/firmware/arm_scmi/bus.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-)
drivers/firmware/arm_scmi/bus.c +13 -13
@@ -157,6 +157,7 @@ static int scmi_protocol_table_register(const struct scmi_device_id *id_table)*/ static void scmi_protocol_device_unrequest (const struct scmi_device_id *id_table) { +struct scmi_requested_dev *rdev, *victim =NULL ;struct list_head *phead; pr_debug("Unrequesting SCMI device (%s) for protocol %x\n",
@@ -165,29 +166,28 @@ static void scmi_protocol_device_unrequest(const struct scmi_device_id *id_tablemutex_lock (&scmi_requested_devices_mtx); phead =idr_find (&scmi_requested_devices, id_table->protocol_id);if (phead) { -struct scmi_requested_dev *victim, *tmp; - -list_for_each_entry_safe (victim, tmp, phead, node) { -if (!strcmp (victim->id_table->name, id_table->name)) { -list_del (&victim->node); - -mutex_unlock (&scmi_requested_devices_mtx); -blocking_notifier_call_chain (&scmi_requested_devices_nh, -SCMI_BUS_NOTIFY_DEVICE_UNREQUEST , - (void *)victim->id_table); -kfree (victim); -mutex_lock (&scmi_requested_devices_mtx); +list_for_each_entry (rdev, phead, node) { +if (!strcmp (rdev->id_table->name, id_table->name)) { + victim = rdev; +list_del (&rdev->node);break ; } } -if (list_empty (phead)) { +if (victim &&list_empty (phead)) {idr_remove (&scmi_requested_devices, id_table->protocol_id);kfree (phead); } }mutex_unlock (&scmi_requested_devices_mtx); + +if (victim) { +blocking_notifier_call_chain (&scmi_requested_devices_nh, +SCMI_BUS_NOTIFY_DEVICE_UNREQUEST , + (void *)victim->id_table); +kfree (victim); + } } static void
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1843/1887 firmware: arm_scmi: Drop handle on protocol bind failures
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sudeep Holla <[email protected]>
[ Upstream commit e3a5c30d233ca5d3e799a80da806554c703bda13 ]
The SCMI bus notifier acquires an SCMI handle when the driver core emits BUS_NOTIFY_BIND_DRIVER, before invoking the protocol driver probe callback. The protocol probe path only checks whether sdev->handle is set.
If device_link_add() fails after the handle has been acquired, the protocol device can still bind with a valid handle but without the dependency link to the SCMI parent. A concurrent parent unbind can then miss the child and tear down the SCMI instance while the child still holds a handle into it.
If the protocol driver probe later fails, for example with -EPROBE_DEFER, the driver core emits BUS_NOTIFY_DRIVER_NOT_BOUND rather than BUS_NOTIFY_UNBOUND_DRIVER. The SCMI notifier only released the handle on BUS_NOTIFY_UNBOUND_DRIVER, so each failed protocol-device bind leaked the SCMI instance users refcount and left sdev->handle set after the failed probe.
Make the link helper report failure and drop the acquired handle if the link cannot be created. Also handle BUS_NOTIFY_DRIVER_NOT_BOUND in the same cleanup path used for unbind so failed probes balance the earlier BUS_NOTIFY_BIND_DRIVER acquisition.
--- drivers/firmware/arm_scmi/driver.c | 31 ++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-)
drivers/firmware/arm_scmi/driver.c +23 -8
@@ -1958,21 +1958,31 @@ static int scmi_handle_put(const struct scmi_handle *handle)return 0 ; } -static void scmi_device_link_add (struct device *consumer, +static bool scmi_device_link_add (struct device *consumer,struct device *supplier) {struct device_link *link; link =device_link_add (consumer, supplier,DL_FLAG_AUTOREMOVE_CONSUMER ); -WARN_ON (!link); +return !WARN_ON (!link); +} + +static void scmi_clear_handle (struct scmi_device *scmi_dev) +{ +if (!scmi_dev->handle) +return ; + +scmi_handle_put (scmi_dev->handle); + scmi_dev->handle =NULL ; }static void scmi_set_handle (struct scmi_device *scmi_dev) { scmi_dev->handle =scmi_handle_get (&scmi_dev->dev); -if (scmi_dev->handle) -scmi_device_link_add (&scmi_dev->dev, scmi_dev->handle->dev); +if (scmi_dev->handle && + !scmi_device_link_add (&scmi_dev->dev, scmi_dev->handle->dev)) +scmi_clear_handle (scmi_dev); } static int __scmi_xfer_info_init(struct scmi_info *sinfo,
@@ -2251,6 +2261,7 @@ static int scmi_bus_notifier(struct notifier_block *nb, {struct scmi_info *info =bus_nb_to_scmi_info (nb);struct scmi_device *sdev =to_scmi_dev (data); +const char *status;/* Skip transport devices and devices of different SCMI instances */ if (!strncmp(sdev->name, "__scmi_transport_device", 23) ||
@@ -2261,18 +2272,22 @@ static int scmi_bus_notifier(struct notifier_block *nb,case BUS_NOTIFY_BIND_DRIVER :/* setup handle now as the transport is ready */ scmi_set_handle (sdev); + status ="about to be BOUND." ; +break ; +case BUS_NOTIFY_DRIVER_NOT_BOUND : +scmi_clear_handle (sdev); + status ="NOT BOUND." ;break ;case BUS_NOTIFY_UNBOUND_DRIVER : -scmi_handle_put (sdev->handle); - sdev->handle =NULL ; +scmi_clear_handle (sdev); + status ="UNBOUND." ;break ;default :return NOTIFY_DONE ; }dev_dbg (info->dev,"Device %s (%s) is now %s\n" ,dev_name (&sdev->dev), - sdev->name, action ==BUS_NOTIFY_BIND_DRIVER ? -"about to be BOUND." :"UNBOUND." ); + sdev->name, status);return NOTIFY_OK ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1844/1887 scsi: hisi_sas: Check before using pointer variables
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yihang Li <[email protected]>
[ Upstream commit 8dd10296be8562a45c6c6794dd492a2b7dccede8 ]
In commit 4b329abc9180 ("scsi: hisi_sas: Move slot variable definition in hisi_sas_abort_task()"), we move the variables slot to the function head. However, the variable slot may be NULL, we should check it in each branch.
--- drivers/scsi/hisi_sas/hisi_sas_main.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/scsi/hisi_sas/hisi_sas_main.c +5 -2
@@ -1605,7 +1605,10 @@ static int hisi_sas_abort_task(struct sas_task *task) task->task_state_flags |=SAS_TASK_STATE_ABORTED ;spin_unlock_irqrestore (&task->task_state_lock, flags); -if (slot && task->task_proto &SAS_PROTOCOL_SSP ) { +if (!slot) + goto out; + +if (task->task_proto &SAS_PROTOCOL_SSP ) {u16 tag = slot->idx;int rc2;
@@ -1652,7 +1655,7 @@ static int hisi_sas_abort_task(struct sas_task *task) rc =hisi_sas_softreset_ata_disk (device); } } - }else if (slot && task->task_proto &SAS_PROTOCOL_SMP ) { + }else if (task->task_proto &SAS_PROTOCOL_SMP ) {/* SMP */ u32 tag = slot->idx;struct hisi_sas_cq *cq = &hisi_hba->cq[slot->dlvry_queue];
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1845/1887 scsi: hisi_sas: Fix a deadlock issue related to automatic dump
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yihang Li <[email protected]>
[ Upstream commit 3c4f53b2c341ec6428b98cb51a89a09b025d0953 ]
If we issue a disabling PHY command, the device attached with it will go offline, if a 2 bit ECC error occurs at the same time, a hung task may be found:
[ 4613.652388] INFO: task kworker/u256:0:165233 blocked for more than 120 seconds. [ 4613.666297] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 4613.674809] task:kworker/u256:0 state:D stack: 0 pid:165233 ppid: 2 flags:0x00000208 [ 4613.683959] Workqueue: 0000:74:02.0_disco_q sas_revalidate_domain [libsas] [ 4613.691518] Call trace: [ 4613.694678] __switch_to+0xf8/0x17c [ 4613.698872] __schedule+0x660/0xee0 [ 4613.703063] schedule+0xac/0x240 [ 4613.706994] schedule_timeout+0x500/0x610 [ 4613.711705] __down+0x128/0x36c [ 4613.715548] down+0x240/0x2d0 [ 4613.719221] hisi_sas_internal_abort_timeout+0x1bc/0x260 [hisi_sas_main] [ 4613.726618] sas_execute_internal_abort+0x144/0x310 [libsas] [ 4613.732976] sas_execute_internal_abort_dev+0x44/0x60 [libsas] [ 4613.739504] hisi_sas_internal_task_abort_dev.isra.0+0xbc/0x1b0 [hisi_sas_main] [ 4613.747499] hisi_sas_dev_gone+0x174/0x250 [hisi_sas_main] [ 4613.753682] sas_notify_lldd_dev_gone+0xec/0x2e0 [libsas] [ 4613.759781] sas_unregister_common_dev+0x4c/0x7a0 [libsas] [ 4613.765962] sas_destruct_devices+0xb8/0x120 [libsas] [ 4613.771709] sas_do_revalidate_domain.constprop.0+0x1b8/0x31c [libsas] [ 4613.778930] sas_revalidate_domain+0x60/0xa4 [libsas] [ 4613.784716] process_one_work+0x248/0x950 [ 4613.789424] worker_thread+0x318/0x934 [ 4613.793878] kthread+0x190/0x200 [ 4613.797810] ret_from_fork+0x10/0x18 [ 4613.802121] INFO: task kworker/u256:4:316722 blocked for more than 120 seconds. [ 4613.816026] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 4613.824538] task:kworker/u256:4 state:D stack: 0 pid:316722 ppid: 2 flags:0x00000208 [ 4613.833670] Workqueue: 0000:74:02.0 hisi_sas_rst_work_handler [hisi_sas_main] [ 4613.841491] Call trace: [ 4613.844647] __switch_to+0xf8/0x17c [ 4613.848852] __schedule+0x660/0xee0 [ 4613.853052] schedule+0xac/0x240 [ 4613.856984] schedule_timeout+0x500/0x610 [ 4613.861695] __down+0x128/0x36c [ 4613.865542] down+0x240/0x2d0 [ 4613.869216] hisi_sas_controller_prereset+0x58/0x1fc [hisi_sas_main] [ 4613.876324] hisi_sas_rst_work_handler+0x40/0x8c [hisi_sas_main] [ 4613.883019] process_one_work+0x248/0x950 [ 4613.887732] worker_thread+0x318/0x934 [ 4613.892204] kthread+0x190/0x200 [ 4613.896118] ret_from_fork+0x10/0x18 [ 4613.900423] INFO: task kworker/u256:1:348985 blocked for more than 121 seconds. [ 4613.914341] "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. [ 4613.922852] task:kworker/u256:1 state:D stack: 0 pid:348985 ppid: 2 flags:0x00000208 [ 4613.931984] Workqueue: 0000:74:02.0_event_q sas_port_event_worker [libsas] [ 4613.939549] Call trace: [ 4613.942702] __switch_to+0xf8/0x17c [ 4613.946892] __schedule+0x660/0xee0 [ 4613.951083] schedule+0xac/0x240 [ 4613.955015] schedule_timeout+0x500/0x610 [ 4613.959725] wait_for_common+0x200/0x610 [ 4613.964349] wait_for_completion+0x3c/0x5c [ 4613.969146] flush_workqueue+0x198/0x790 [ 4613.973776] sas_porte_broadcast_rcvd+0x1e8/0x320 [libsas] [ 4613.979960] sas_port_event_worker+0x54/0xa0 [libsas] [ 4613.985708] process_one_work+0x248/0x950 [ 4613.990420] worker_thread+0x318/0x934 [ 4613.994868] kthread+0x190/0x200 [ 4613.998800] ret_from_fork+0x10/0x18
This is because when the device goes offline, we obtain the hisi_hba semaphore and send the ABORT_DEV command to the device. However, the internal abort timed out due to the 2 bit ECC error and triggers automatic dump. In addition, since the hisi_hba semaphore has been obtained, the dump cannot be executed and the controller cannot be reset.
Therefore, the deadlocks occur on the following circular dependencies:hisi_sas_dev_gone() -> down() -> hisi_sas_internal_task_abort_dev() -> ... -> hisi_sas_internal_abort_timeout() -> down().
The deadlock is triggered only when the timeout occurs during device goes offline. To fix this issue, use .rst_ha_timeout to distinguish the scenario where a device goes offline from other scenarios.
--- drivers/scsi/hisi_sas/hisi_sas_main.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/scsi/hisi_sas/hisi_sas_main.c +10 -2
@@ -1911,9 +1911,17 @@ static bool hisi_sas_internal_abort_timeout(struct sas_task *task,struct hisi_sas_internal_abort_data *timeout = data;if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0 ].itct) { -down (&hisi_hba->sem); +/* +* If timeout occurs in device gone scenario, to avoid +* circular dependency like: +* hisi_sas_dev_gone() -> down() -> ... -> +* hisi_sas_internal_abort_timeout() -> down(). +*/ +if (!timeout->rst_ha_timeout) +down (&hisi_hba->sem); hisi_hba->hw->debugfs_snapshot_regs (hisi_hba); -up (&hisi_hba->sem); +if (!timeout->rst_ha_timeout) +up (&hisi_hba->sem); }if (task->task_state_flags &SAS_TASK_STATE_DONE ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1846/1887 scsi: hisi_sas: Remove redundant checks for automatic debugfs dump
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yihang Li <[email protected]>
[ Upstream commit 3f030550476566b12091687c70071d05ad433e0d ]
In commit 63f0733d07ce ("scsi: hisi_sas: Allocate DFX memory during dump trigger"), the memory allocation time of the DFX is changed from device initialization to dump occurs, so .debugfs_itct is not a valid address and do not need to check.
The parameter hisi_sas_debugfs_enable is enough to check whether automatic debugfs dump is triggered, so remove redunant checks.
--- drivers/scsi/hisi_sas/hisi_sas_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/scsi/hisi_sas/hisi_sas_main.c +2 -2
@@ -1537,7 +1537,7 @@ static int hisi_sas_controller_prereset(struct hisi_hba *hisi_hba)return -EPERM ; } -if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0 ].itct) +if (hisi_sas_debugfs_enable) hisi_hba->hw->debugfs_snapshot_regs (hisi_hba);return 0 ;
@@ -1910,7 +1910,7 @@ static bool hisi_sas_internal_abort_timeout(struct sas_task *task,struct hisi_hba *hisi_hba =dev_to_hisi_hba (device);struct hisi_sas_internal_abort_data *timeout = data; -if (hisi_sas_debugfs_enable && hisi_hba->debugfs_itct[0 ].itct) { +if (hisi_sas_debugfs_enable) {/* * If timeout occurs in device gone scenario, to avoid * circular dependency like:
Signature · 1 line
2.53.0
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.1.191 release. There are 1887 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.
Build failure on amd64 with amdgpu:
CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn315.o CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn316.o CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn32.o LD [M] drivers/gpu/drm/amd/amdgpu/amdgpu.o AR drivers/gpu/built-in.a AR drivers/built-in.a
make: *** [Makefile:2040: .] Error 2
No time to bisect just now but will try to have a look tomorrow.
Signature · 1 line
Brett Sheffield (he/him)
Quoted 14 lines · Brett A C Sheffield
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.1.191 release. There are 1887 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.
Build failure on amd64 with amdgpu:
CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn315.o CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn316.o CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn32.o LD [M] drivers/gpu/drm/amd/amdgpu/amdgpu.o AR drivers/gpu/built-in.a AR drivers/built-in.a
Quoted 3 lines
make: *** [Makefile:2040: .] Error 2
No time to bisect just now but will try to have a look tomorrow.
Fortunately it was a build failure, so I just left that running:
git bisect start
# status: waiting for both 'good' and 'bad' commits
# bad: [adc8e434cf08c73b0f02dab2c15319315f07172f] Linux 6.12.115-rc1
git bisect bad adc8e434cf08c73b0f02dab2c15319315f07172f
# status: waiting for 'good' commit(s), 'bad' commit known
# good: [85d82e0d7c2dfd3e75d34f35b7ebbf41f45c9c4e] Linux 6.12.114
git bisect good 85d82e0d7c2dfd3e75d34f35b7ebbf41f45c9c4e
# good: [0e1dbd1409918dbd331cd9c382ce64736dcf3272] ksmbd: fill in FileSysIdentifier in FS_POSIX_INFORMATION git bisect good 0e1dbd1409918dbd331cd9c382ce64736dcf3272
# good: [617f27c3fa85742e9d468a2145e3676af6b2498d] Bluetooth: L2CAP: refuse __l2cap_chan_add if chan already has conn git bisect good 617f27c3fa85742e9d468a2145e3676af6b2498d
# good: [1476a3a7d286ad7763025337f20bb841b24c72ea] io_uring: don't pass restart error codes to userspace git bisect good 1476a3a7d286ad7763025337f20bb841b24c72ea
# good: [be00113e49ff42c2c007993dd05cf4bdd1c2bfeb] keys: Protect the type name while describing a key git bisect good be00113e49ff42c2c007993dd05cf4bdd1c2bfeb
# good: [6270098a65994bdf26b736b2ad6614e5b9078ad6] coredump: hold RCU while releasing parked threads git bisect good 6270098a65994bdf26b736b2ad6614e5b9078ad6
# good: [41af0a793777ede3f1839bcd8abae92a5c901fe4] fork: release the files of a failed fork after sched_cancel_fork() git bisect good 41af0a793777ede3f1839bcd8abae92a5c901fe4
# good: [6da107042aaa43b05f4c16bee65afc2e9b5f7561] signal: allow taks to temporarily block TIF_NOTIFY_SIGNAL git bisect good 6da107042aaa43b05f4c16bee65afc2e9b5f7561
# good: [da1419eb5d34caf39c1f3abad5b95a601a35114f] fanotify: Fix crash in fanotify_init(2)
git bisect good da1419eb5d34caf39c1f3abad5b95a601a35114f
# first 'bad' commit: [adc8e434cf08c73b0f02dab2c15319315f07172f] Linux 6.12.115-rc1
Signature · 4 lines
Brett Sheffield (he/him) Librecast - Decentralising the Internet with Multicast https://librecast.net/ https://blog.brettsheffield.com/
Am 28.10.2026 um 21:44 schrieb Brett A C Sheffield:
Quoted 44 lines · Brett A C Sheffield
Quoted 14 lines · Greg Kroah-Hartman
Quoted 4 lines
This is the start of the stable review cycle for the 6.1.191 release. There are 1887 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.
Build failure on amd64 with amdgpu:
CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn315.o CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn316.o CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn32.o LD [M] drivers/gpu/drm/amd/amdgpu/amdgpu.o AR drivers/gpu/built-in.a AR drivers/built-in.aQuoted 3 lines
make: *** [Makefile:2040: .] Error 2
No time to bisect just now but will try to have a look tomorrow.
Fortunately it was a build failure, so I just left that running:
git bisect start
# status: waiting for both 'good' and 'bad' commits
# bad: [adc8e434cf08c73b0f02dab2c15319315f07172f] Linux 6.12.115-rc1
git bisect badadc8e434cf08c73b0f02dab2c15319315f07172f
# status: waiting for 'good' commit(s), 'bad' commit known
# good: [85d82e0d7c2dfd3e75d34f35b7ebbf41f45c9c4e] Linux 6.12.114
git bisect good85d82e0d7c2dfd3e75d34f35b7ebbf41f45c9c4e
# good: [0e1dbd1409918dbd331cd9c382ce64736dcf3272] ksmbd: fill in FileSysIdentifier inFS_POSIX_INFORMATIONgit bisect good0e1dbd1409918dbd331cd9c382ce64736dcf3272
# good: [617f27c3fa85742e9d468a2145e3676af6b2498d] Bluetooth: L2CAP: refuse__l2cap_chan_addif chan already has conn git bisect good617f27c3fa85742e9d468a2145e3676af6b2498d
# good: [1476a3a7d286ad7763025337f20bb841b24c72ea]io_uring: don't pass restart error codes to userspace git bisect good1476a3a7d286ad7763025337f20bb841b24c72ea
# good: [be00113e49ff42c2c007993dd05cf4bdd1c2bfeb] keys: Protect the type name while describing a key git bisect goodbe00113e49ff42c2c007993dd05cf4bdd1c2bfeb
# good: [6270098a65994bdf26b736b2ad6614e5b9078ad6] coredump: hold RCU while releasing parked threads git bisect good6270098a65994bdf26b736b2ad6614e5b9078ad6
# good: [41af0a793777ede3f1839bcd8abae92a5c901fe4] fork: release the files of a failed fork aftersched_cancel_fork()git bisect good41af0a793777ede3f1839bcd8abae92a5c901fe4
# good: [6da107042aaa43b05f4c16bee65afc2e9b5f7561] signal: allow taks to temporarily blockTIF_NOTIFY_SIGNALgit bisect good6da107042aaa43b05f4c16bee65afc2e9b5f7561
# good: [da1419eb5d34caf39c1f3abad5b95a601a35114f] fanotify: Fix crash infanotify_init(2)
git bisect goodda1419eb5d34caf39c1f3abad5b95a601a35114f
Quoted 1 line
# first 'bad' commit: [adc8e434cf08c73b0f02dab2c15319315f07172f] Linux 6.12.115-rc1
Brett, you are reporting against 6.1.191-rc1. Are you on the wrong branch?
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]
Greg Kroah-Hartman
maintainerQuoted 48 lines · Peter Schneider
Am 28.10.2026 um 21:44 schrieb Brett A C Sheffield:
Quoted 44 lines · Brett A C Sheffield
Quoted 14 lines · Greg Kroah-Hartman
Quoted 4 lines
This is the start of the stable review cycle for the 6.1.191 release. There are 1887 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.
Build failure on amd64 with amdgpu:
CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn315.o CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn316.o CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn32.o LD [M] drivers/gpu/drm/amd/amdgpu/amdgpu.o AR drivers/gpu/built-in.a AR drivers/built-in.aQuoted 3 lines
make: *** [Makefile:2040: .] Error 2
No time to bisect just now but will try to have a look tomorrow.
Fortunately it was a build failure, so I just left that running:
git bisect start
# status: waiting for both 'good' and 'bad' commits
# bad: [adc8e434cf08c73b0f02dab2c15319315f07172f] Linux 6.12.115-rc1
git bisect badadc8e434cf08c73b0f02dab2c15319315f07172f
# status: waiting for 'good' commit(s), 'bad' commit known
# good: [85d82e0d7c2dfd3e75d34f35b7ebbf41f45c9c4e] Linux 6.12.114
git bisect good85d82e0d7c2dfd3e75d34f35b7ebbf41f45c9c4e
# good: [0e1dbd1409918dbd331cd9c382ce64736dcf3272] ksmbd: fill in FileSysIdentifier inFS_POSIX_INFORMATIONgit bisect good0e1dbd1409918dbd331cd9c382ce64736dcf3272
# good: [617f27c3fa85742e9d468a2145e3676af6b2498d] Bluetooth: L2CAP: refuse__l2cap_chan_addif chan already has conn git bisect good617f27c3fa85742e9d468a2145e3676af6b2498d
# good: [1476a3a7d286ad7763025337f20bb841b24c72ea]io_uring: don't pass restart error codes to userspace git bisect good1476a3a7d286ad7763025337f20bb841b24c72ea
# good: [be00113e49ff42c2c007993dd05cf4bdd1c2bfeb] keys: Protect the type name while describing a key git bisect goodbe00113e49ff42c2c007993dd05cf4bdd1c2bfeb
# good: [6270098a65994bdf26b736b2ad6614e5b9078ad6] coredump: hold RCU while releasing parked threads git bisect good6270098a65994bdf26b736b2ad6614e5b9078ad6
# good: [41af0a793777ede3f1839bcd8abae92a5c901fe4] fork: release the files of a failed fork aftersched_cancel_fork()git bisect good41af0a793777ede3f1839bcd8abae92a5c901fe4
# good: [6da107042aaa43b05f4c16bee65afc2e9b5f7561] signal: allow taks to temporarily blockTIF_NOTIFY_SIGNALgit bisect good6da107042aaa43b05f4c16bee65afc2e9b5f7561
# good: [da1419eb5d34caf39c1f3abad5b95a601a35114f] fanotify: Fix crash infanotify_init(2)
git bisect goodda1419eb5d34caf39c1f3abad5b95a601a35114fQuoted 1 line
# first 'bad' commit: [adc8e434cf08c73b0f02dab2c15319315f07172f] Linux 6.12.115-rc1
Quoted 1 line
Brett, you are reporting against 6.1.191-rc1. Are you on the wrong branch?
Yeah, somthing looks wrong here :)
Quoted 49 lines · Greg Kroah-Hartman
Quoted 48 lines · Peter Schneider
Am 28.10.2026 um 21:44 schrieb Brett A C Sheffield:
Quoted 45 lines · Brett A C Sheffield
Quoted 14 lines · Greg Kroah-Hartman
Quoted 4 lines
This is the start of the stable review cycle for the 6.1.191 release. There are 1887 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.
Build failure on amd64 with amdgpu:
CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn315.o CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn316.o CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn32.o LD [M] drivers/gpu/drm/amd/amdgpu/amdgpu.o AR drivers/gpu/built-in.a AR drivers/built-in.aQuoted 3 lines
make: *** [Makefile:2040: .] Error 2
No time to bisect just now but will try to have a look tomorrow.
Fortunately it was a build failure, so I just left that running:
git bisect start
# status: waiting for both 'good' and 'bad' commits
# bad: [adc8e434cf08c73b0f02dab2c15319315f07172f] Linux 6.12.115-rc1
git bisect badadc8e434cf08c73b0f02dab2c15319315f07172f
# status: waiting for 'good' commit(s), 'bad' commit known
# good: [85d82e0d7c2dfd3e75d34f35b7ebbf41f45c9c4e] Linux 6.12.114
git bisect good85d82e0d7c2dfd3e75d34f35b7ebbf41f45c9c4e
# good: [0e1dbd1409918dbd331cd9c382ce64736dcf3272] ksmbd: fill in FileSysIdentifier inFS_POSIX_INFORMATIONgit bisect good0e1dbd1409918dbd331cd9c382ce64736dcf3272
# good: [617f27c3fa85742e9d468a2145e3676af6b2498d] Bluetooth: L2CAP: refuse__l2cap_chan_addif chan already has conn git bisect good617f27c3fa85742e9d468a2145e3676af6b2498d
# good: [1476a3a7d286ad7763025337f20bb841b24c72ea]io_uring: don't pass restart error codes to userspace git bisect good1476a3a7d286ad7763025337f20bb841b24c72ea
# good: [be00113e49ff42c2c007993dd05cf4bdd1c2bfeb] keys: Protect the type name while describing a key git bisect goodbe00113e49ff42c2c007993dd05cf4bdd1c2bfeb
# good: [6270098a65994bdf26b736b2ad6614e5b9078ad6] coredump: hold RCU while releasing parked threads git bisect good6270098a65994bdf26b736b2ad6614e5b9078ad6
# good: [41af0a793777ede3f1839bcd8abae92a5c901fe4] fork: release the files of a failed fork aftersched_cancel_fork()git bisect good41af0a793777ede3f1839bcd8abae92a5c901fe4
# good: [6da107042aaa43b05f4c16bee65afc2e9b5f7561] signal: allow taks to temporarily blockTIF_NOTIFY_SIGNALgit bisect good6da107042aaa43b05f4c16bee65afc2e9b5f7561
# good: [da1419eb5d34caf39c1f3abad5b95a601a35114f] fanotify: Fix crash infanotify_init(2)
git bisect goodda1419eb5d34caf39c1f3abad5b95a601a35114f# first 'bad' commit: [adc8e434cf08c73b0f02dab2c15319315f07172f] Linux 6.12.115-rc1
Quoted 3 lines
Quoted 1 line
Brett, you are reporting against 6.1.191-rc1. Are you on the wrong branch?
Yeah, somthing looks wrong here :)
Yeah... lemme try that again... with coffee :-)
Signature · 1 line
Brett Sheffield (he/him)
Quoted 50 lines · Brett A C Sheffield
Quoted 49 lines · Greg Kroah-Hartman
Quoted 48 lines · Peter Schneider
Am 28.10.2026 um 21:44 schrieb Brett A C Sheffield:
Quoted 45 lines · Brett A C Sheffield
Quoted 14 lines · Greg Kroah-Hartman
Quoted 4 lines
This is the start of the stable review cycle for the 6.1.191 release. There are 1887 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.
Build failure on amd64 with amdgpu:
CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn315.o CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn316.o CC [M] drivers/gpu/drm/amd/amdgpu/../display/dmub/src/dmub_dcn32.o LD [M] drivers/gpu/drm/amd/amdgpu/amdgpu.o AR drivers/gpu/built-in.a AR drivers/built-in.aQuoted 3 lines
make: *** [Makefile:2040: .] Error 2
No time to bisect just now but will try to have a look tomorrow.
Fortunately it was a build failure, so I just left that running:
git bisect start
# status: waiting for both 'good' and 'bad' commits
# bad: [adc8e434cf08c73b0f02dab2c15319315f07172f] Linux 6.12.115-rc1
git bisect badadc8e434cf08c73b0f02dab2c15319315f07172f
# status: waiting for 'good' commit(s), 'bad' commit known
# good: [85d82e0d7c2dfd3e75d34f35b7ebbf41f45c9c4e] Linux 6.12.114
git bisect good85d82e0d7c2dfd3e75d34f35b7ebbf41f45c9c4e
# good: [0e1dbd1409918dbd331cd9c382ce64736dcf3272] ksmbd: fill in FileSysIdentifier inFS_POSIX_INFORMATIONgit bisect good0e1dbd1409918dbd331cd9c382ce64736dcf3272
# good: [617f27c3fa85742e9d468a2145e3676af6b2498d] Bluetooth: L2CAP: refuse__l2cap_chan_addif chan already has conn git bisect good617f27c3fa85742e9d468a2145e3676af6b2498d
# good: [1476a3a7d286ad7763025337f20bb841b24c72ea]io_uring: don't pass restart error codes to userspace git bisect good1476a3a7d286ad7763025337f20bb841b24c72ea
# good: [be00113e49ff42c2c007993dd05cf4bdd1c2bfeb] keys: Protect the type name while describing a key git bisect goodbe00113e49ff42c2c007993dd05cf4bdd1c2bfeb
# good: [6270098a65994bdf26b736b2ad6614e5b9078ad6] coredump: hold RCU while releasing parked threads git bisect good6270098a65994bdf26b736b2ad6614e5b9078ad6
# good: [41af0a793777ede3f1839bcd8abae92a5c901fe4] fork: release the files of a failed fork aftersched_cancel_fork()git bisect good41af0a793777ede3f1839bcd8abae92a5c901fe4
# good: [6da107042aaa43b05f4c16bee65afc2e9b5f7561] signal: allow taks to temporarily blockTIF_NOTIFY_SIGNALgit bisect good6da107042aaa43b05f4c16bee65afc2e9b5f7561
# good: [da1419eb5d34caf39c1f3abad5b95a601a35114f] fanotify: Fix crash infanotify_init(2)
git bisect goodda1419eb5d34caf39c1f3abad5b95a601a35114f# first 'bad' commit: [adc8e434cf08c73b0f02dab2c15319315f07172f] Linux 6.12.115-rc1
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Brett, you are reporting against 6.1.191-rc1. Are you on the wrong branch?
Yeah, somthing looks wrong here :)
Yeah... lemme try that again... with coffee :-)
I've reset the branch and I see we're on rc2 now, so I'll run with that.
Signature · 4 lines
Brett Sheffield (he/him) Librecast - Decentralising the Internet with Multicast https://librecast.net/ https://blog.brettsheffield.com/
Greg Kroah-Hartman
maintainerPATCH 1847/1887 rds: tcp: unregister sysctl before tearing down listen socket
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang (Microsoft) <[email protected]>
[ Upstream commit 167e54c703ccd4fa028feb568b0d1002020cff86 ]
rds_tcp_exit_net() frees the per-netns RDS TCP listen socket via rds_tcp_kill_sock() before unregistering the per-netns sysctl table. Since rds_tcp_skbuf_handler() derives the netns from rtn->rds_tcp_listen_sock->sk, a concurrent sysctl write can race with netns teardown and dereference the freed socket/sk.
KASAN reports the race as:
BUG: KASAN: slab-use-after-free in rds_tcp_skbuf_handler+0x2aa/0x2e0 rds_tcp_skbuf_handler net/rds/tcp.c:721 proc_sys_call_handler fs/proc/proc_sysctl.c vfs_write fs/read_write.c __x64_sys_pwrite64 fs/read_write.c
Fix this by unregistering the RDS TCP sysctl table before calling rds_tcp_kill_sock(). unregister_net_sysctl_table() prevents new sysctl handlers from starting and waits for in-flight handlers to finish, so the listen socket can then be released safely. The fix was tested against the linked reproducer.
--- net/rds/tcp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/rds/tcp.c +2 -2
@@ -711,13 +711,13 @@ static void __net_exit rds_tcp_exit_net(struct net *net) {struct rds_tcp_net *rtn =net_generic (net, rds_tcp_netid); -rds_tcp_kill_sock (net); -if (rtn->rds_tcp_sysctl)unregister_net_sysctl_table (rtn->rds_tcp_sysctl);if (net != &init_net)kfree (rtn->ctl_table); + +rds_tcp_kill_sock (net); }static struct pernet_operations rds_tcp_net_ops = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1848/1887 RDMA/mlx5: Fix implicit ODP hang on parent deregistration
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yishai Hadas <[email protected]>
[ Upstream commit 3d8c6f26893d55fab218ad086719de1fc9bb86ba ]
Fix the destroy_unused_implicit_child_mr() to prevent hanging during parent deregistration as of below [1].
Upon entering destroy_unused_implicit_child_mr(), the reference count for the implicit MR parent is incremented using:refcount_inc_not_zero().
A corresponding decrement must be performed iffree_implicit_child_mr_work() is not called.
The code has been updated to properly manage the reference count that was incremented.
[1]
INFO: task python3:2157 blocked for more than 120 seconds. Not tainted 6.12.0-rc7+ #1633 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message. task:python3 state:D stack:0 pid:2157 tgid:2157 ppid:1685 flags:0x00000000 Call Trace: <TASK> __schedule+0x420/0xd30 schedule+0x47/0x130 __mlx5_ib_dereg_mr+0x379/0x5d0 [mlx5_ib] ? __pfx_autoremove_wake_function+0x10/0x10 ib_dereg_mr_user+0x5f/0x120 [ib_core] ? lock_release+0xc6/0x280 destroy_hw_idr_uobject+0x1d/0x60 [ib_uverbs] uverbs_destroy_uobject+0x58/0x1d0 [ib_uverbs] uobj_destroy+0x3f/0x70 [ib_uverbs] ib_uverbs_cmd_verbs+0x3e4/0xbb0 [ib_uverbs] ? __pfx_uverbs_destroy_def_handler+0x10/0x10 [ib_uverbs] ? lock_acquire+0xc1/0x2f0 ? ib_uverbs_ioctl+0xcb/0x170 [ib_uverbs] ? ib_uverbs_ioctl+0x116/0x170 [ib_uverbs] ? lock_release+0xc6/0x280 ib_uverbs_ioctl+0xe7/0x170 [ib_uverbs] ? ib_uverbs_ioctl+0xcb/0x170 [ib_uverbs] __x64_sys_ioctl+0x1b0/0xa70 ? kmem_cache_free+0x221/0x400 do_syscall_64+0x6b/0x140 entry_SYSCALL_64_after_hwframe+0x76/0x7e RIP: 0033:0x7f20f21f017b RSP: 002b:00007ffcfc4a77c8 EFLAGS: 00000246 ORIG_RAX: 0000000000000010 RAX: ffffffffffffffda RBX: 00007ffcfc4a78d8 RCX: 00007f20f21f017b RDX: 00007ffcfc4a78c0 RSI: 00000000c0181b01 RDI: 0000000000000003 RBP: 00007ffcfc4a78a0 R08: 000056147d125190 R09: 00007f20f1f14c60 R10: 0000000000000001 R11: 0000000000000246 R12: 00007ffcfc4a7890 R13: 000000000000001c R14: 000056147d100fc0 R15: 00007f20e365c9d0 </TASK>
--- drivers/infiniband/hw/mlx5/odp.c | 1 + 1 file changed, 1 insertion(+)
drivers/infiniband/hw/mlx5/odp.c +1 -0
@@ -227,6 +227,7 @@ static void destroy_unused_implicit_child_mr(struct mlx5_ib_mr *mr)if (__xa_cmpxchg (&imr->implicit_children, idx, mr,NULL ,GFP_KERNEL ) != mr) {xa_unlock (&imr->implicit_children); +mlx5r_deref_odp_mkey (&imr->mmkey);return ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1849/1887 RDMA/mlx5: Follow rb_key.ats when creating new mkeys
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jason Gunthorpe <[email protected]>
[ Upstream commit f637040c3339a2ed8c12d65ad03f9552386e2fe7 ]
When a cache ent already exists but doesn't have any mkeys in it the cache will automatically create a new one based on the specification in the ent->rb_key.
ent->ats was missed when creating the new key and so ma_translation_mode was not being set even though the ent requires it.
--- drivers/infiniband/hw/mlx5/mr.c | 1 + 1 file changed, 1 insertion(+)
drivers/infiniband/hw/mlx5/mr.c +1 -0
@@ -295,6 +295,7 @@ static void set_cache_mkc(struct mlx5_cache_ent *ent, void *mkc)MLX5_SET (mkc, mkc, access_mode_1_0, ent->rb_key.access_mode &0x3 );MLX5_SET (mkc, mkc, access_mode_4_2, (ent->rb_key.access_mode >>2 ) &0x7 ); +MLX5_SET (mkc, mkc, ma_translation_mode, !!ent->rb_key.ats); MLX5_SET(mkc, mkc, translations_octword_size, get_mkc_octo_size(ent->rb_key.access_mode,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1850/1887 ksmbd: pin conn during async oplock break notification
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qihang <[email protected]>
[ Upstream commit aa5d8f3f96aa11a4a54ce993c11ce8af11c546f9 ]
smb2_oplock_break_noti() and smb2_lease_break_noti() store a ksmbd_conn pointer in an async ksmbd_work and then queue that work on ksmbd-io. The work only increments conn->r_count, which prevents teardown from passing the pending-request wait after the increment, but it does not pin the struct ksmbd_conn object.
If connection teardown races with an oplock break notification, the last conn reference can be dropped before the queued worker finishes. The worker then uses the freed conn in ksmbd_conn_write() and ksmbd_conn_r_count_dec().
Take a real conn reference when publishing the conn pointer to the async work item, and drop it after the notification work has decremented r_count. Apply the same lifetime rule to lease break notification, which uses the same work->conn pattern.
--- fs/smb/server/oplock.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
fs/smb/server/oplock.c +4 -2
@@ -758,6 +758,7 @@ static void __smb2_oplock_break_noti(struct work_struct *wk) out:ksmbd_free_work_struct (work);ksmbd_conn_r_count_dec (conn); +ksmbd_conn_put (conn); }/**
@@ -788,7 +789,7 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo) br_info->open_trunc = opinfo->open_trunc; work->request_buf = (char *)br_info; - work->conn = conn; + work->conn =ksmbd_conn_get (conn); work->sess = opinfo->sess;if (opinfo->op_state ==OPLOCK_ACK_WAIT ) {
@@ -862,6 +863,7 @@ static void __smb2_lease_break_noti(struct work_struct *wk) out:ksmbd_free_work_struct (work);ksmbd_conn_r_count_dec (conn); +ksmbd_conn_put (conn); }/**
@@ -897,7 +899,7 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)memcpy (br_info->lease_key, lease->lease_key,SMB2_LEASE_KEY_SIZE ); work->request_buf = (char *)br_info; - work->conn = conn; + work->conn =ksmbd_conn_get (conn); work->sess = opinfo->sess;if (opinfo->op_state ==OPLOCK_ACK_WAIT ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1851/1887 ksmbd: fix r_count dec/increment mismatch
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Namjae Jeon <[email protected]>
[ Upstream commit ddb7ea36ba7129c2ed107e2186591128618864e1 ]
r_count is only increased when there is an oplock break wait, so r_count inc/decrement are not paired. This can cause r_count to become negative, which can lead to a problem where the ksmbd thread does not terminate.
--- fs/smb/server/oplock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/smb/server/oplock.c +2 -2
@@ -792,8 +792,8 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo) work->conn =ksmbd_conn_get (conn); work->sess = opinfo->sess; +ksmbd_conn_r_count_inc (conn);if (opinfo->op_state ==OPLOCK_ACK_WAIT ) { -ksmbd_conn_r_count_inc (conn);INIT_WORK (&work->work, __smb2_oplock_break_noti);ksmbd_queue_work (work);
@@ -902,8 +902,8 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo) work->conn =ksmbd_conn_get (conn); work->sess = opinfo->sess; +ksmbd_conn_r_count_inc (conn);if (opinfo->op_state ==OPLOCK_ACK_WAIT ) { -ksmbd_conn_r_count_inc (conn);INIT_WORK (&work->work, __smb2_lease_break_noti);ksmbd_queue_work (work);wait_for_break_ack (opinfo);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1852/1887 virtio_ccw: always take irq_lock in the classic interrupt handler
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Karl Mehltretter <[email protected]>
[ Upstream commit 48a355cf5b382570975e60857450ff3d42f268e9 ]
virtio_ccw_int_handler() takes vcdev->irq_lock around its vring_interrupt() calls only when VIRTIO_HARDEN_NOTIFICATION is enabled.
The virtio shutdown path calls synchronize_cbs() even when notification hardening is disabled. virtio_reset_device() now does so after the transport reset too.
For classic interrupts, synchronize_cbs() takes vcdev->irq_lock for writing, but the interrupt handler does not take the matching read lock in that configuration. synchronize_cbs() can return while a callback is still running.
Take the read lock unconditionally so the write side can synchronize with the callbacks.
Message-ID: <[email protected]>
--- drivers/s390/virtio/virtio_ccw.c | 4 ---- 1 file changed, 4 deletions(-)
drivers/s390/virtio/virtio_ccw.c +0 -4
@@ -1141,13 +1141,11 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev, vcdev->err = -EIO ; }virtio_ccw_check_activity (vcdev, activity); -#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION /* * Paired with virtio_ccw_synchronize_cbs() and interrupts are * disabled here. */ read_lock (&vcdev->irq_lock); -#endif for_each_set_bit (i,indicators (vcdev),sizeof (*indicators (vcdev)) *BITS_PER_BYTE ) {/* The bit clear must happen before the vring kick. */
@@ -1156,9 +1154,7 @@ static void virtio_ccw_int_handler(struct ccw_device *cdev, vq =virtio_ccw_vq_by_ind (vcdev, i);vring_interrupt (0 , vq); } -#ifdef CONFIG_VIRTIO_HARDEN_NOTIFICATION read_unlock (&vcdev->irq_lock); -#endif if (test_bit (0 ,indicators2 (vcdev))) {virtio_config_changed (&vcdev->vdev);clear_bit (0 ,indicators2 (vcdev));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1853/1887 fs/ntfs3: reject index allocation if $BITMAP is empty but blocks exist
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Moon Hee Lee <[email protected]>
[ Upstream commit 0dc7117da8f92dd5fe077d712a756eccbe377d40 ]
Index allocation requires at least one bit in the $BITMAP attribute to track usage of index entries. If the bitmap is empty while index blocks are already present, this reflects on-disk corruption.
syzbot triggered this condition using a malformed NTFS image. During a rename() operation involving a long filename (which spans multiple index entries), the empty bitmap allowed the name to be added without valid tracking. Subsequent deletion of the original entry failed with -ENOENT, due to unexpected index state.
Reject such cases by verifying that the bitmap is not empty when index blocks exist.
--- fs/ntfs3/index.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
fs/ntfs3/index.c +10 -0
@@ -1552,6 +1552,16 @@ static int indx_add_allocate(struct ntfs_index *indx, struct ntfs_inode *ni, bmp_size = bmp_size_v =le32_to_cpu (bmp->res.data_size); } +/* +* Index blocks exist, but $BITMAP has zero valid bits. +* This implies an on-disk corruption and must be rejected. +*/ +if (in->name ==I30_NAME && +unlikely (bmp_size_v ==0 && indx->alloc_run.count)) { + err = -EINVAL ; + goto out1; + } + bit = bmp_size <<3 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1854/1887 highmem: fix a memory copy problem in memcpy_from_folio
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Su Hui <[email protected]>
[ Upstream commit 73424d00dc63ba681856e06cfb0a5abbdb62e2b5 ]
Clang static checker complains that value stored to 'from' is never read. And memcpy_from_folio() only copy the last chunk memory from folio to destination. Use 'to += chunk' to replace 'from += chunk' to fix this typo problem.
--- include/linux/highmem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
include/linux/highmem.h +1 -1
@@ -430,7 +430,7 @@ static inline void memcpy_from_folio(char *to, struct folio *folio,memcpy (to, from, chunk);kunmap_local (from); - from += chunk; + to += chunk; offset += chunk; len -= chunk; }while (len >0 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1855/1887 Bluetooth: MGMT: Fix dangling pointer on mgmt_add_adv_patterns_monitor_complete
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 5f5fa4cd35f707344f65ce9e225b6528691dbbaa ]
This fixes the condition checking so mgmt_pending_valid is executed whenever status != -ECANCELED otherwise calling mgmt_pending_free(cmd) would kfree(cmd) without unlinking it from the list first, leaving a dangling pointer. Any subsequent list traversal (e.g., mgmt_pending_foreach during __mgmt_power_off, or another mgmt_pending_valid call) would dereference freed memory.
--- net/bluetooth/mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/bluetooth/mgmt.c +1 -1
@@ -5409,7 +5409,7 @@ static void mgmt_add_adv_patterns_monitor_complete(struct hci_dev *hdev,* hci_adv_monitors_clear is about to be called which will take care of * freeing the adv_monitor instances. */ -if (status == -ECANCELED && !mgmt_pending_valid (hdev, cmd)) +if (status == -ECANCELED || !mgmt_pending_valid (hdev, cmd))return ; monitor = cmd->user_data;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1856/1887 Bluetooth: MGMT: Fix memory leak in set_ssp_complete
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jianpeng Chang <[email protected]>
[ Upstream commit 4db19bfd320f2124c820d3456aeae3953095ea8e ]
Fix memory leak in set_ssp_complete() where mgmt_pending_cmd structures are not freed after being removed from the pending list.
Commit 302a1f674c00 ("Bluetooth: MGMT: Fix possible UAFs") replaced mgmt_pending_foreach() calls with individual command handling but missed adding mgmt_pending_free() calls in both error and success paths of set_ssp_complete(). Other completion functions like set_le_complete() were fixed correctly in the same commit.
This causes a memory leak of the mgmt_pending_cmd structure and its associated parameter data for each SSP command that completes.
Add the missing mgmt_pending_free(cmd) calls in both code paths to fix the memory leak. Also fix the same issue in set_advertising_complete().
--- net/bluetooth/mgmt.c | 3 +++ 1 file changed, 3 insertions(+)
net/bluetooth/mgmt.c +3 -0
@@ -1928,6 +1928,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err) }mgmt_cmd_status (cmd->sk, cmd->hdev->id, cmd->opcode, mgmt_err); +mgmt_pending_free (cmd);return ; }
@@ -1946,6 +1947,7 @@ static void set_ssp_complete(struct hci_dev *hdev, void *data, int err)sock_put (match.sk);hci_update_eir_sync (hdev); +mgmt_pending_free (cmd); }static int set_ssp_sync (struct hci_dev *hdev,void *data)
@@ -6537,6 +6539,7 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err)hci_dev_clear_flag (hdev,HCI_ADVERTISING );settings_rsp (cmd, &match); +mgmt_pending_free (cmd);new_settings (hdev, match.sk);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1857/1887 Bluetooth: MGMT: fix crash in set_mesh_sync and set_mesh_complete
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pauli Virtanen <[email protected]>
[ Upstream commit e8785404de06a69d89dcdd1e9a0b6ea42dc6d327 ]
There is a BUG: KASAN: stack-out-of-bounds in set_mesh_sync due to memcpy from badly declared on-stack flexible array.
Another crash is in set_mesh_complete() due to double list_del via mgmt_pending_valid + mgmt_pending_remove.
Use DEFINE_FLEX to declare the flexible array right, and don't memcpy outside bounds.
As mgmt_pending_valid removes the cmd from list, use mgmt_pending_free, and also report status on error.
--- include/net/bluetooth/mgmt.h | 2 +- net/bluetooth/mgmt.c | 26 +++++++++++++++----------- 2 files changed, 16 insertions(+), 12 deletions(-)
include/net/bluetooth/mgmt.h +1 -1
@@ -845,7 +845,7 @@ struct mgmt_cp_set_mesh {__le16 window;__le16 period;__u8 num_ad_types; -__u8 ad_types[]; + __u8 ad_types[] __counted_by(num_ad_types); } __packed;#define MGMT_SET_MESH_RECEIVER_SIZE 6
net/bluetooth/mgmt.c +15 -11
@@ -2157,19 +2157,24 @@ static void set_mesh_complete(struct hci_dev *hdev, void *data, int err) sk = cmd->sk;if (status) { +mgmt_cmd_status (cmd->sk, hdev->id,MGMT_OP_SET_MESH_RECEIVER , + status);mgmt_pending_foreach (MGMT_OP_SET_MESH_RECEIVER , hdev, true, cmd_status_rsp, &status); -return ; + goto done; } -mgmt_pending_remove (cmd);mgmt_cmd_complete (sk, hdev->id,MGMT_OP_SET_MESH_RECEIVER ,0 ,NULL ,0 ); + +done: +mgmt_pending_free (cmd); }static int set_mesh_sync (struct hci_dev *hdev,void *data) {struct mgmt_pending_cmd *cmd = data; -struct mgmt_cp_set_mesh cp; + DEFINE_FLEX(struct mgmt_cp_set_mesh, cp, ad_types, num_ad_types, + sizeof(hdev->mesh_ad_types));size_t len;mutex_lock (&hdev->mgmt_pending_lock);
@@ -2179,27 +2184,26 @@ static int set_mesh_sync(struct hci_dev *hdev, void *data)return -ECANCELED ; } -memcpy (&cp, cmd->param,sizeof (cp)); + len = cmd->param_len; +memcpy (cp, cmd->param,min (__struct_size (cp), len));mutex_unlock (&hdev->mgmt_pending_lock); - len = cmd->param_len; -memset (hdev->mesh_ad_types,0 ,sizeof (hdev->mesh_ad_types)); -if (cp.enable) +if (cp->enable)hci_dev_set_flag (hdev,HCI_MESH );else hci_dev_clear_flag (hdev,HCI_MESH ); - hdev->le_scan_interval =__le16_to_cpu (cp.period); - hdev->le_scan_window =__le16_to_cpu (cp.window); + hdev->le_scan_interval =__le16_to_cpu (cp->period); + hdev->le_scan_window =__le16_to_cpu (cp->window); - len -=sizeof (cp); + len -=sizeof (struct mgmt_cp_set_mesh );/* If filters don't fit, forward all adv pkts */ if (len <=sizeof (hdev->mesh_ad_types)) -memcpy (hdev->mesh_ad_types, cp.ad_types, len); +memcpy (hdev->mesh_ad_types, cp->ad_types, len);hci_update_passive_scan_sync (hdev);return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1858/1887 xen/events: fix error code in xen_bind_pirq_msi_to_irq()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit 7f3da4b698bcc21a6df0e7f114af71d53a3e26ac ]
Return -ENOMEM if xen_irq_init() fails. currently the code returns an uninitialized variable or zero.
--- drivers/xen/events/events_base.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/xen/events/events_base.c +3 -1
@@ -1101,8 +1101,10 @@ int xen_bind_pirq_msi_to_irq(struct pci_dev *dev, struct msi_desc *msidesc,for (i =0 ; i < nvec; i++) { info =xen_irq_init (irq + i); -if (!info) +if (!info) { + ret = -ENOMEM ; goto error_irq; + }irq_set_chip_and_handler_name (irq + i, &xen_pirq_chip, handle_edge_irq, name);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1859/1887 drm/amdgpu: ensure no_hw_access is visible before MMIO
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Perry Yuan <[email protected]>
[ Upstream commit 31b153315b8702d0249aa44d83d9fbf42c5c7a79 ]
Add a full memory barrier after clearing no_hw_access in amdgpu_device_mode1_reset() so subsequent PCI state restore access cannot observe stale state on other CPUs.
--- drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +3 -0
@@ -4920,6 +4920,9 @@ int amdgpu_device_mode1_reset(struct amdgpu_device *adev)if (!ret) adev->no_hw_access = false; +/* ensure no_hw_access is updated before we access hw */ +smp_mb (); +amdgpu_device_load_pci_state (adev->pdev);/* wait for asic to come out of reset */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1860/1887 KVM: SEV: Drop FOLL_WRITE for encrypted region registration
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pankaj Gupta <[email protected]>
[ Upstream commit ee1a586dd1fa2f245b3b753a3e44d9263a49240b ]
When pinning SEV guest memory, drop FOLL_WRITE and rely on FOLL_LONGTERM to break CoW, as *KVM* doesn't actually to the memory using the GUP'd pages. Omitting FOLL_WRITE fixes a regression when using file-backed guest memory that was introduced when KVM (correctly) added FOLL_LONG (e.g. to ensure anonymous memory is migrated out of MIGRATE_CMA/ZONE_MOVABLE before a long term pin).
Unfortunately, as of commits:
8ac268436e6d ("mm/gup: disallow FOLL_LONGTERM GUP-nonfast writing to file-backed mappings") a6e79df92e4a ("mm/gup: disallow FOLL_LONGTERM GUP-fast writing to file-backed mappings")
GUP uses FOLL_LONGTERM as a canary of sorts to detect pins that are likely to be problematic, and disallows WRITE+LONGTERM pins for file-backed memory. As a result, backing SEV+ guests with file-backed memory, e.g. virtio-pmem, fails due to the disallowed FOLL_LONGTERM+FOLL_WRITE combination.
Note, in the past, FOLL_WRITE was required to trigger CoW unsharing, to prevent replacing the page in the (primary MMU's) page tables during a later write fault after already having pinned a (shared) page in MAP_PRIVATE mappings. FOLL_LONGTERM does that nowadays, even without FOLL_WRITE (see gup_must_unshare()).
--- arch/x86/kvm/svm/sev.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
arch/x86/kvm/svm/sev.c +5 -1
@@ -1972,8 +1972,12 @@ int sev_mem_enc_register_region(struct kvm *kvm,if (!region)return -ENOMEM ; +/* +* Do NOT specify FOLL_WRITE, as KVM isn't using the pinned pages to +* write memory, and FOLL_LONGTERM itself triggers CoW unshare. +*/ region->pages =sev_pin_memory (kvm, range->addr, range->size, ®ion->npages, -FOLL_WRITE |FOLL_LONGTERM ); +FOLL_LONGTERM );if (IS_ERR (region->pages)) { ret =PTR_ERR (region->pages); goto e_free;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1861/1887 drm/amdgpu: fix the idr allocation flags
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Prike Liang <[email protected]>
[ Upstream commit ea56aa2625708eaf96f310032391ff37746310ef ]
Fix the IDR allocation flags by using atomic GFP flags in non‑sleepable contexts to avoid the __might_sleep() complaint.
268.290239] [drm] Initialized amdgpu 3.64.0 for 0000:03:00.0 on minor 0
[ 268.294900] BUG: sleeping function called from invalid context at ./include/linux/sched/mm.h:323
[ 268.295355] in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 1744, name: modprobe
[ 268.295705] preempt_count: 1, expected: 0
[ 268.295886] RCU nest depth: 0, expected: 0
[ 268.296072] 2 locks held by modprobe/1744:
[ 268.296077] #0: ffff8c3a44abd1b8 (&dev->mutex){....}-{4:4}, at: __driver_attach+0xe4/0x210
[ 268.296100] #1: ffffffffc1a6ea78 (amdgpu_pasid_idr_lock){+.+.}-{3:3}, at: amdgpu_pasid_alloc+0x26/0xe0 [amdgpu]
[ 268.296494] CPU: 12 UID: 0 PID: 1744 Comm: modprobe Tainted: G U OE 6.19.0-custom #16 PREEMPT(voluntary)
[ 268.296498] Tainted: [U]=USER, [O]=OOT_MODULE, [E]=UNSIGNED_MODULE
[ 268.296499] Hardware name: AMD Majolica-RN/Majolica-RN, BIOS RMJ1009A 06/13/2021
[ 268.296501] Call Trace:Stable-dep-of: 3c863ff920b4 ("drm/amdgpu: replace PASID IDR with XArray")
--- drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c +4 -1
@@ -68,8 +68,11 @@ int amdgpu_pasid_alloc(unsigned int bits)return -EINVAL ;spin_lock (&amdgpu_pasid_idr_lock); +/* TODO: Need to replace the idr with an xarry, and then +* handle the internal locking with ATOMIC safe paths. +*/ pasid =idr_alloc_cyclic (&amdgpu_pasid_idr,NULL ,1 , -1U << bits,GFP_KERNEL ); +1U << bits,GFP_ATOMIC );spin_unlock (&amdgpu_pasid_idr_lock);if (pasid >=0 )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1862/1887 drm/amdgpu: replace PASID IDR with XArray
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikhail Gavrilov <[email protected]>
[ Upstream commit 3c863ff920b45fa7a9b7d4cb932f466488a87a58 ]
Replace the PASID IDR + spinlock with XArray as noted in the TODO left by commit ea56aa262570 ("drm/amdgpu: fix the idr allocation flags").
The IDR conversion still has an IRQ safety issue:amdgpu_pasid_free() can be called from hardirq context via the fence signal path, but amdgpu_pasid_idr_lock is taken with plain spin_lock() in process context, creating a potential deadlock:
CPU0
----
spin_lock(&amdgpu_pasid_idr_lock) // process context, IRQs on
<Interrupt>
spin_lock(&amdgpu_pasid_idr_lock) // deadlock
The hardirq call chain is:
sdma_v6_0_process_trap_irq
-> amdgpu_fence_process
-> dma_fence_signal
-> drm_sched_job_done
-> dma_fence_signal
-> amdgpu_pasid_free_cb
-> amdgpu_pasid_freeUse XArray with XA_FLAGS_LOCK_IRQ (all xa operations use IRQ-safe locking internally) and XA_FLAGS_ALLOC1 (zero is not a valid PASID). Both xa_alloc_cyclic() and xa_erase() then handle locking consistently, fixing the IRQ safety issue and removing the need for an explicit spinlock.
v8: squash in irq safe fix
--- drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c | 39 ++++++++++++------------- 1 file changed, 19 insertions(+), 20 deletions(-)
drivers/gpu/drm/amd/amdgpu/amdgpu_ids.c +19 -20
@@ -22,7 +22,7 @@*/ #include "amdgpu_ids.h" -#include <linux/idr.h> +#include <linux/xarray.h> #include <linux/dma-fence-array.h>
@@ -40,8 +40,8 @@* VMs are looked up from the PASID per amdgpu_device. */ -static DEFINE_IDR (amdgpu_pasid_idr); -static DEFINE_SPINLOCK (amdgpu_pasid_idr_lock); +static DEFINE_XARRAY_FLAGS(amdgpu_pasid_xa, XA_FLAGS_LOCK_IRQ | XA_FLAGS_ALLOC1); +static u32 amdgpu_pasid_xa_next;/* Helper to free pasid from a fence callback */ struct amdgpu_pasid_cb {
@@ -62,36 +62,37 @@ struct amdgpu_pasid_cb {*/ int amdgpu_pasid_alloc (unsigned int bits) { -int pasid; +u32 pasid; +int r;if (bits ==0 )return -EINVAL ; -spin_lock (&amdgpu_pasid_idr_lock); -/* TODO: Need to replace the idr with an xarry, and then -* handle the internal locking with ATOMIC safe paths. -*/ - pasid =idr_alloc_cyclic (&amdgpu_pasid_idr,NULL ,1 , -1U << bits,GFP_ATOMIC ); -spin_unlock (&amdgpu_pasid_idr_lock); - -if (pasid >=0 ) -trace_amdgpu_pasid_allocated (pasid); + r =xa_alloc_cyclic_irq (&amdgpu_pasid_xa, &pasid,xa_mk_value (0 ), +XA_LIMIT (1 , (1U << bits) -1 ), + &amdgpu_pasid_xa_next,GFP_KERNEL ); +if (r <0 ) +return r; +trace_amdgpu_pasid_allocated (pasid);return pasid; }/** * amdgpu_pasid_free - Free a PASID * @pasid: PASID to free +* +* Called in IRQ context. */ void amdgpu_pasid_free (u32 pasid) { +unsigned long flags; +trace_amdgpu_pasid_freed (pasid); -spin_lock (&amdgpu_pasid_idr_lock); -idr_remove (&amdgpu_pasid_idr, pasid); -spin_unlock (&amdgpu_pasid_idr_lock); +xa_lock_irqsave (&amdgpu_pasid_xa, flags); +__xa_erase (&amdgpu_pasid_xa, pasid); +xa_unlock_irqrestore (&amdgpu_pasid_xa, flags); } static void amdgpu_pasid_free_cb(struct dma_fence *fence,
@@ -599,7 +600,5 @@ void amdgpu_vmid_mgr_fini(struct amdgpu_device *adev)*/ void amdgpu_pasid_mgr_cleanup (void ) { -spin_lock (&amdgpu_pasid_idr_lock); -idr_destroy (&amdgpu_pasid_idr); -spin_unlock (&amdgpu_pasid_idr_lock); +xa_destroy (&amdgpu_pasid_xa); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1863/1887 smb: client: protect tc_count increment in smb2_find_smb_sess_tcon_unlocked()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Henrique Carvalho <[email protected]>
[ Upstream commit 4d8690dace005a38e6dbde9ecce2da3ad85c7c41 ]
Commit 96c4af418586 ("cifs: Fix locking usage for tcon fields") refactored cifs code to change cifs_tcp_ses_lock for tc_lock around tc_count changes.
There was missing lock around tc_count increment inside smb2_find_smb_sess_tcon_unlocked().
--- fs/smb/client/smb2transport.c | 2 ++ 1 file changed, 2 insertions(+)
fs/smb/client/smb2transport.c +2 -0
@@ -213,7 +213,9 @@ smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid)list_for_each_entry (tcon, &ses->tcon_list, tcon_list) {if (tcon->tid != tid)continue ; +spin_lock (&tcon->tc_lock); ++tcon->tc_count; +spin_unlock (&tcon->tc_lock);trace_smb3_tcon_ref (tcon->debug_id, tcon->tc_count, netfs_trace_tcon_ref_get_find_sess_tcon);return tcon;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1864/1887 alpha: do not clear remote MMU contexts in migrate_flush_tlb_page()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Magnus Lindholm <[email protected]>
[ Upstream commit 16266d50c51eb5eb98f1c345c5aa9ff359a305aa ]
After the on_each_cpu() rendezvous, migrate_flush_tlb_page() walks the other CPUs and zeroes their mm->context[cpu] when mm_users is at most one, described as mimicking flush_tlb_mm()'s mm_users<=1 optimization.
It is not one. flush_tlb_mm() tests mm_users before deciding whether to send the IPIs; here every CPU has already been visited and waited for, so nothing is saved. The callback has also just set each CPU's own slot correctly, so the loop only overwrites it, and does so while that CPU may still be running in the address space.
Remove it. The shootdown shortcuts in flush_tlb_mm(), flush_tlb_page() and flush_icache_user_page() clear remote slots too; once the next patch removes those as well, every runtime update of mm->context[cpu] is made by CPU cpu itself. That patch relies on the invariant when it reads those slots to decide whether a shootdown can be skipped, so this one is tagged for stable as its prerequisite.
--- arch/alpha/mm/tlbflush.c | 16 ---------------- 1 file changed, 16 deletions(-)
arch/alpha/mm/tlbflush.c +0 -16
@@ -90,22 +90,6 @@ void migrate_flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)*/ preempt_disable ();on_each_cpu (ipi_flush_mm_and_page, &d,1 ); - -/* -* mimic flush_tlb_mm()'s mm_users<=1 optimization. -*/ -if (atomic_read (&mm->mm_users) <=1 ) { - -int cpu, this_cpu; - this_cpu =smp_processor_id (); - -for (cpu =0 ; cpu <NR_CPUS ; cpu++) { -if (!cpu_online (cpu) || cpu == this_cpu) -continue ; -if (READ_ONCE (mm->context[cpu])) -WRITE_ONCE (mm->context[cpu],0 ); - } - }preempt_enable (); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1865/1887 media: verisilicon: Fix kernel panic due to __initconst misuse
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming Qian <[email protected]>
[ Upstream commit e8d97c270cb46a2a88739019d0f8547adc7d97da ]
Fix a kernel panic when probing the driver as a module:
Unable to handle kernel paging request at virtual address ffffd9c18eb05000 of_find_matching_node_and_match+0x5c/0x1a0 hantro_probe+0x2f4/0x7d0 [hantro_vpu]
The imx8mq_vpu_shared_resources array is referenced by variant structures through their shared_devices field. When built as a module, __initconst causes this data to be freed after module init, but it's later accessed during probe, causing a page fault.
The imx8mq_vpu_shared_resources is referenced from non-init code, so keeping __initconst or __initconst_or_module here is wrong.
Drop the __initconst annotation and let it live in the normal .rodata section.
A bug of __initconst called from regular non-init probe code leading to bugs during probe deferrals or during unbind-bind cycles.
--- drivers/media/platform/verisilicon/imx8m_vpu_hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/media/platform/verisilicon/imx8m_vpu_hw.c +1 -1
@@ -359,7 +359,7 @@ const struct hantro_variant imx8mq_vpu_variant = { .num_regs = ARRAY_SIZE(imx8mq_reg_names) }; -static const struct of_device_id imx8mq_vpu_shared_resources[]__initconst = { +static const struct of_device_id imx8mq_vpu_shared_resources[] = { { .compatible ="nxp,imx8mq-vpu-g1" , }, { .compatible ="nxp,imx8mq-vpu-g2" , }, {/* sentinel */ }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1866/1887 i3c: mipi-i3c-hci: Preserve RUN bit when aborting DMA ring
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Adrian Hunter <[email protected]>
[ Upstream commit 093eb8e73c90aa0c8cfb0421aa85bd70c23488be ]
The MIPI I3C HCI specification does not require the DMA ring RUN bit (RUN_STOP) to be cleared when issuing an ABORT. That allows the DMA ring to continue to receive IBIs, although an IBI is anyway not lost because it can be received once the ring restarts if the I3C device has not given up. Note, currently ABORT is only used on a timeout error path so the change has very little effect in practice. In the more common case of a transfer error, the ring (bundle) operation is halted by the controller anyway.
Adjust the RING_CONTROL handling to set ABORT without clearing RUN_STOP, bringing the driver into alignment with the specification.
--- drivers/i3c/master/mipi-i3c-hci/dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/i3c/master/mipi-i3c-hci/dma.c +1 -1
@@ -456,7 +456,7 @@ static bool hci_dma_dequeue_xfer(struct i3c_hci *hci,if (ring_status &RING_STATUS_RUNNING ) {/* stop the ring */ reinit_completion (&rh->op_done); -rh_reg_write (RING_CONTROL ,RING_CTRL_ENABLE |RING_CTRL_ABORT ); +rh_reg_write (RING_CONTROL ,rh_reg_read (RING_CONTROL ) |RING_CTRL_ABORT );wait_for_completion_timeout (&rh->op_done,HZ ); ring_status =rh_reg_read (RING_STATUS );if (ring_status &RING_STATUS_RUNNING ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1867/1887 ata: libata-core: fix cancellation of a port deferred qc work
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal <[email protected]>
[ Upstream commit 55db009926634b20955bd8abbee921adbc8d2cb4 ]
cancel_work_sync() is a sleeping function so it cannot be called with the spin lock of a port being held. Move the call to this function in ata_port_detach() after EH completes, with the port lock released, together with other work cancellation calls.
--- drivers/ata/libata-core.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
drivers/ata/libata-core.c +3 -5
@@ -6115,10 +6115,6 @@ static void ata_port_detach(struct ata_port *ap) } } -/* Make sure the deferred qc work finished. */ -cancel_work_sync (&ap->deferred_qc_work); -WARN_ON (ap->deferred_qc); -/* Tell EH to disable all devices */ ap->pflags |=ATA_PFLAG_UNLOADING ;ata_port_schedule_eh (ap);
@@ -6129,9 +6125,11 @@ static void ata_port_detach(struct ata_port *ap)/* wait till EH commits suicide */ ata_port_wait_eh (ap); -/* it better be dead now */ +/* It better be dead now and not have any remaining deferred qc. */ WARN_ON (!(ap->pflags &ATA_PFLAG_UNLOADED )); +WARN_ON (ap->deferred_qc); +cancel_work_sync (&ap->deferred_qc_work);cancel_delayed_work_sync (&ap->hotplug_task);cancel_delayed_work_sync (&ap->scsi_rescan_task);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1868/1887 ext4: fix error pointer dereference in ext4_mb_load_buddy_gfp()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dan Carpenter <[email protected]>
[ Upstream commit c6a6c9694aadc4c3ab8d89bdd44aed3eab1e43c6 ]
This code calls folio_put() on an error pointer which will lead to a crash. Check for both error pointers and NULL pointers before calling folio_put().
--- fs/ext4/mballoc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ext4/mballoc.c +1 -1
@@ -1625,7 +1625,7 @@ ext4_mb_load_buddy_gfp(struct super_block *sb, ext4_group_t group,return 0 ; err: -if (folio) +if (!IS_ERR_OR_NULL (folio))folio_put (folio);if (e4b->bd_bitmap_folio)folio_put (e4b->bd_bitmap_folio);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1869/1887 sched/psi: Create the psimon kthread outside of cgroup_mutex
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tejun Heo <[email protected]>
[ Upstream commit fadeedd7cfc5d73d33fa3d7ac54b9b27aabd09d2 ]
a5b98009f16d ("sched/psi: fix race between file release and pressure write") made pressure_write() hold cgroup_mutex across psi_trigger_create(), which forks the psimon kthread for the first rtpoll trigger. As kthread creation depends on the whole fork path, the commit inadvertently created a lot of unwanted locking dependencies from cgroup_mutex.
sched_ext got hit by one: its enable path blocks forks and then grabs cgroup_mutex, so a pressure write racing a scheduler enable deadlocks, with every other fork piling up behind.
Fix it by splitting trigger creation so that the worker is forked with cgroup_mutex dropped and the kernfs active reference left broken. The latter matters because rmdir and cgroup.pressure writes drain active references under cgroup_mutex. Publishing the trigger last keeps error reporting synchronous and preserves the of->priv lifetime rules.
The trigger registered in the first stage pins the group's rtpoll machinery across the unlocked window, leaving only creation races to resolve. The catch-up poll on installation covers scheduling attempts dropped while there was no worker.
v2: Retagged sched/psi (was cgroup).
--- include/linux/psi.h | 4 ++- kernel/cgroup/cgroup.c | 23 +++++++++++++- kernel/sched/psi.c | 69 ++++++++++++++++++++++++++++++++---------- 3 files changed, 78 insertions(+), 18 deletions(-)
include/linux/psi.h +3 -1
@@ -25,7 +25,9 @@ void psi_memstall_leave(unsigned long *flags);int psi_show (struct seq_file *s,struct psi_group *group,enum psi_res res);struct psi_trigger *psi_trigger_create (struct psi_group *group,char *buf,enum psi_res res,struct file *file, -struct kernfs_open_file *of); +struct kernfs_open_file *of, +bool *need_rtpoll_worker); +int psi_trigger_create_rtpoll_worker (struct psi_group *group);void psi_trigger_destroy (struct psi_trigger *t); __poll_t psi_trigger_poll(void **trigger_ptr, struct file *file,
kernel/cgroup/cgroup.c +22 -1
@@ -3790,6 +3790,7 @@ static ssize_t pressure_write(struct kernfs_open_file *of, char *buf,struct psi_trigger *new;struct cgroup *cgrp;struct psi_group *psi; +bool need_rtpoll_worker;ssize_t ret =0 ; cgrp =cgroup_kn_lock_live (of->kn, false);
@@ -3809,12 +3810,32 @@ static ssize_t pressure_write(struct kernfs_open_file *of, char *buf, } psi =cgroup_psi (cgrp); - new =psi_trigger_create (psi, buf, res, of->file, of); + new =psi_trigger_create (psi, buf, res, of->file, of, + &need_rtpoll_worker);if (IS_ERR (new)) { ret =PTR_ERR (new); goto out_unlock; } +/* +* The worker fork must run with neither cgroup_mutex nor the file's +* kernfs active reference held. The latter is broken since +* cgroup_kn_lock_live(). @of->priv may be released while unlocked, so +* recheck before publishing @new. +*/ +if (need_rtpoll_worker) { +cgroup_unlock (); + ret =psi_trigger_create_rtpoll_worker (psi); +cgroup_lock (); + +if (!ret && !of->priv) + ret = -ENODEV ; +if (ret) { +psi_trigger_destroy (new); + goto out_unlock; + } + } +smp_store_release (&ctx->psi.trigger, new); out_unlock:
kernel/sched/psi.c +53 -16
112 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1870/1887 Bluetooth: hci_core: Print number of packets in conn->data_q
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luiz Augusto von Dentz <[email protected]>
[ Upstream commit 3c34d6428740e47b29ae3afd85d6f9eb656a3ea3 ]
This attempts to print the number of packets pending to be transmitted in the conn->data_q.
Stable-dep-of: 6610c6fe4b89 ("Bluetooth: hci_core: Fix queuing tx_work after workqueue is drained")
--- net/bluetooth/hci_core.c | 8 ++++++++ 1 file changed, 8 insertions(+)
net/bluetooth/hci_core.c +8 -0
@@ -3218,6 +3218,8 @@ static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue,spin_unlock_bh (&queue->lock); } + +bt_dev_dbg (hdev,"chan %p queued %d" , chan,skb_queue_len (queue)); }void hci_send_acl (struct hci_chan *chan,struct sk_buff *skb,__u16 flags)
@@ -3249,6 +3251,10 @@ void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb)hci_skb_pkt_type (skb) =HCI_SCODATA_PKT ;skb_queue_tail (&conn->data_q, skb); + +bt_dev_dbg (hdev,"hcon %p queued %d" , conn, +skb_queue_len (&conn->data_q)); +queue_work (hdev->workqueue, &hdev->tx_work); }
@@ -3312,6 +3318,8 @@ static void hci_queue_iso(struct hci_conn *conn, struct sk_buff_head *queue,spin_unlock_bh (&queue->lock); } + +bt_dev_dbg (hdev,"hcon %p queued %d" , conn,skb_queue_len (queue)); }void hci_send_iso (struct hci_conn *conn,struct sk_buff *skb)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1871/1887 Bluetooth: hci_core: Fix queuing tx_work after workqueue is drained
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: ThangNN99 <[email protected]>
[ Upstream commit 6610c6fe4b8936c232048e6049bf77c70a6f759c ]
hci_send_acl(), hci_send_sco() and hci_send_iso() queue hdev->tx_work unconditionally. They can run from the L2CAP/SCO/ISO socket send path while hci_dev_close_sync() is draining hdev->workqueue (HCIDEVDOWN racing with a socket write). Since that queue_work() is not chained work from the tx_work worker itself, __queue_work() sees the queue marked __WQ_DRAINING, warns "cannot queue %ps on wq %s", and drops the work:
WARNING: CPU: 1 PID: 5985 at kernel/workqueue.c:2352 __queue_work Call Trace: queue_work_on l2cap_chan_send l2cap_sock_sendmsg ...
hci_dev_close_sync() already sets HCI_CMD_DRAIN_WORKQUEUE before draining, but only hci_cmd_work() and handle_cmd_cnt_and_timer() check it before queuing. Route the tx_work producers through the same guard via a shared hci_sched_tx() helper.
--- net/bluetooth/hci_core.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
net/bluetooth/hci_core.c +14 -3
@@ -3222,6 +3222,17 @@ static void hci_queue_acl(struct hci_chan *chan, struct sk_buff_head *queue,bt_dev_dbg (hdev,"chan %p queued %d" , chan,skb_queue_len (queue)); } +/* Queue hdev->tx_work, unless hdev->workqueue is being drained by +* hci_dev_close_sync(), which would otherwise WARN and drop the work. +*/ +static void hci_sched_tx (struct hci_dev *hdev) +{ +rcu_read_lock (); +if (!hci_dev_test_flag (hdev,HCI_CMD_DRAIN_WORKQUEUE )) +queue_work (hdev->workqueue, &hdev->tx_work); +rcu_read_unlock (); +} +void hci_send_acl (struct hci_chan *chan,struct sk_buff *skb,__u16 flags) {struct hci_dev *hdev = chan->conn->hdev;
@@ -3230,7 +3241,7 @@ void hci_send_acl(struct hci_chan *chan, struct sk_buff *skb, __u16 flags)hci_queue_acl (chan, &chan->data_q, skb, flags); -queue_work (hdev->workqueue, &hdev->tx_work); +hci_sched_tx (hdev); }/* Send SCO data */
@@ -3255,7 +3266,7 @@ void hci_send_sco(struct hci_conn *conn, struct sk_buff *skb)bt_dev_dbg (hdev,"hcon %p queued %d" , conn,skb_queue_len (&conn->data_q)); -queue_work (hdev->workqueue, &hdev->tx_work); +hci_sched_tx (hdev); }/* Send ISO data */
@@ -3330,7 +3341,7 @@ void hci_send_iso(struct hci_conn *conn, struct sk_buff *skb)hci_queue_iso (conn, &conn->data_q, skb); -queue_work (hdev->workqueue, &hdev->tx_work); +hci_sched_tx (hdev); }/* ---- HCI TX task (outgoing data) ---- */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1872/1887 ocfs2: use correct endian in ocfs2_dinode_has_extents
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Joseph Qi <[email protected]>
[ Upstream commit c9dff86eb78a4b6b02b1e407993c946ccaf9bfb4 ]
Fields in ocfs2_dinode is little endian, covert to host endian when checking those contents.
--- fs/ocfs2/inode.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
fs/ocfs2/inode.c +6 -4
@@ -236,13 +236,15 @@ struct inode *ocfs2_iget(struct ocfs2_super *osb, u64 blkno, unsigned flags,static int ocfs2_dinode_has_extents (struct ocfs2_dinode *di) {/* inodes flagged with other stuff in id2 */ -if (di->i_flags & (OCFS2_SUPER_BLOCK_FL |OCFS2_LOCAL_ALLOC_FL | -OCFS2_CHAIN_FL |OCFS2_DEALLOC_FL )) +if (le32_to_cpu (di->i_flags) & + (OCFS2_SUPER_BLOCK_FL |OCFS2_LOCAL_ALLOC_FL |OCFS2_CHAIN_FL | +OCFS2_DEALLOC_FL ))return 0 ;/* i_flags doesn't indicate when id2 is a fast symlink */ -if (S_ISLNK (di->i_mode) && di->i_size && di->i_clusters ==0 ) +if (S_ISLNK (le16_to_cpu (di->i_mode)) &&le64_to_cpu (di->i_size) && + !le32_to_cpu (di->i_clusters))return 0 ; -if (di->i_dyn_features &OCFS2_INLINE_DATA_FL ) +if (le16_to_cpu (di->i_dyn_features) &OCFS2_INLINE_DATA_FL )return 0 ;return 1 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1873/1887 ALSA: seq: Dont leak the extension cell pointer in the bounce payload
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: HyeongJun An <[email protected]>
[ Upstream commit 59e1592d3c270ff4642d5d6dc55c545306eb0693 ]
The bounce_error_event() embeds the failed event in the bounce payload by pointing data.ext.ptr at it. When that event is a queued variable-length event, its own data.ext.ptr holds the address of its first extension cell, put there by snd_seq_event_dup(). The payload goes out verbatim through snd_seq_expand_var_event(), so the address reaches userspace.
That is the same address commit 705dd6dcbc0e ("ALSA: seq: Clear variable event pointer on read") removed from the event header. The read path still clears it there, just above the call that expands the payload.
Embed a sanitised copy instead, treated exactly as snd_seq_read() treats the header. A stack copy is enough because delivery is synchronous and snd_seq_event_dup() copies before returning.
An unprivileged client reaches this by setting SNDRV_SEQ_FILTER_BOUNCE, queueing a variable-length event to a port that does not exist and reading the bounce back. Eight bytes on 64-bit, from its own pool.
--- sound/core/seq/seq_clientmgr.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
sound/core/seq/seq_clientmgr.c +10 -6
@@ -554,7 +554,7 @@ static int bounce_error_event(struct snd_seq_client *client,struct snd_seq_event *event, int err, int atomic, int hop) { - struct snd_seq_event bounce_ev; + struct snd_seq_event bounce_ev, quoted;int result; if (client == NULL ||
@@ -570,15 +570,19 @@ static int bounce_error_event(struct snd_seq_client *client,* For user clients, send SNDRV_SEQ_EVENT_BOUNCE with the * original event embedded as variable-length data. This * avoids exposing data.quote.event (a kernel pointer) to -* userspace. The variable-length path in snd_seq_event_dup() -* copies the event data from data.ext.ptr into chained cells, -* and snd_seq_expand_var_event() copies only the data content -* -- never the pointer -- to userspace. +* userspace. Sanitise the embedded copy too - a queued +* variable-length event carries the address of its own +* extension cell, and the payload goes out verbatim. */ + quoted = *event; +if (snd_seq_ev_is_variable ("ed)) { + quoted.data.ext.len &= ~SNDRV_SEQ_EXT_MASK ; + quoted.data.ext.ptr =NULL ; + } bounce_ev.type =SNDRV_SEQ_EVENT_BOUNCE ; bounce_ev.flags =SNDRV_SEQ_EVENT_LENGTH_VARIABLE ; bounce_ev.data.ext.len =sizeof (struct snd_seq_event ); - bounce_ev.data.ext.ptr = (char *)event; + bounce_ev.data.ext.ptr = (char *)"ed; }else {/* * For kernel clients, quote the event pointer directly.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1874/1887 seq_buf: Make DECLARE_SEQ_BUF() usable
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nathan Lynch <[email protected]>
[ Upstream commit 7a8e9cdf9405819105ae7405cd91e482bf574b01 ]
Using the address operator on the array doesn't work:
./include/linux/seq_buf.h:27:27: error: initialization of ‘char *’
from incompatible pointer type ‘char (*)[128]’ [-Werror=incompatible-pointer-types]
27 | .buffer = &__ ## NAME ## _buffer, \
| ^
Apart from fixing that, we can improve DECLARE_SEQ_BUF() by using a compound literal to define the buffer array without attaching a name to it. This makes the macro a single statement, allowing constructs such as:
static DECLARE_SEQ_BUF(my_seq_buf, MYSB_SIZE);
to work as intended.
--- include/linux/seq_buf.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
include/linux/seq_buf.h +1 -2
@@ -22,9 +22,8 @@ struct seq_buf { };#define DECLARE_SEQ_BUF (NAME ,SIZE ) \ - char __ ## NAME ## _buffer[SIZE] = ""; \ struct seq_buf NAME = { \ - .buffer = &__ ## NAME ## _buffer, \ + .buffer = (char[SIZE]) { 0 }, \ .size = SIZE, \ }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1875/1887 netfilter: ctnetlink: do not expose expectation DEAD flag
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pablo Neira Ayuso <[email protected]>
[ Upstream commit 322371b09058ad10d0282a0e7ec8eaa764e6aaac ]
Expose expectation flags included in the NF_CT_EXPECT_MASK bitmask only. The DEAD flag is internal, do not expose it.
--- net/netfilter/nf_conntrack_netlink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/nf_conntrack_netlink.c +1 -1
@@ -3043,7 +3043,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,#endif if (nla_put_be32 (skb,CTA_EXPECT_TIMEOUT ,htonl (timeout)) ||nla_put_be32 (skb,CTA_EXPECT_ID ,nf_expect_get_id (exp)) || -nla_put_be32 (skb,CTA_EXPECT_FLAGS ,htonl (exp->flags)) || +nla_put_be32 (skb,CTA_EXPECT_FLAGS ,htonl (exp->flags &NF_CT_EXPECT_MASK )) ||nla_put_be32 (skb,CTA_EXPECT_CLASS ,htonl (exp->class))) goto nla_put_failure;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1876/1887 vlan: restore HW VLAN tag insertion with reorder_hdr off
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit c2124f80be4ceb6ec566ca3b5fc87f84ea9c36e0 ]
Commit 447cbe95ebb9 ("vlan: fix skb_under_panic and races when toggling HW VLAN offload") replaced vlan_passthru_header_ops with vlan_header_ops unconditionally to avoid lockless data races when modifying hard_header_len dynamically under RTNL.
Prior to that commit, vlan devices on top of a real device capable of HW VLAN TX offload used vlan_passthru_header_ops, which never inserted the 802.1Q header in the frame.
Now, with reorder_hdr=off (as done by Home Assistant OS / NetworkManager when flags are omitted over D-Bus), vlan_dev_hard_header() always pushes an in-band 802.1Q header, and vlan_dev_hard_start_xmit() hands the frame to the real device as is, even if the real device supports HW VLAN TX offload.
This is a regression for r8169 users (Realtek RTL8168h), who report transmit queue timeouts (NETDEV WATCHDOG): this NIC stalls when asked to offload checksum and/or TSO for frames carrying an in-band tag. Users of r8152 based USB adapters were affected as well.
Reverting the blamed commit, disabling TX checksum offload (which also disables TSO), or setting reorder_hdr=on were all reported to work around the issue.
Keep vlan_dev_hard_header() as is: the in-band header keeps the frame layout seen at the vlan device egress (taps, tc, netfilter) unchanged, and is relied upon by stacked vlans (Q-in-Q) and by AF_PACKET SOCK_DGRAM users sending ETH_P_8021Q frames.
Instead, when vlan_dev_hard_start_xmit() gets a frame carrying an in-band tag with our protocol and the real device can insert tags, move that tag to skb->vlan_tci with __skb_vlan_pop(), so that the real device inserts it. Frames sent on the wire are unchanged, except that frames shorter than 64 bytes with their tag now get up to 4 bytes of extra padding, as with reorder_hdr=on and before 447cbe95ebb9.
skb_reset_mac_header() is needed first, because not all ndo_start_xmit() callers set the mac header (e.g. AF_XDP copy mode, which uses __dev_direct_xmit()).
vlan_set_encap_proto() may read the two bytes after the vlan header, so frames whose linear part is shorter than VLAN_ETH_HLEN + 2 are sent unchanged, as before. This also makes sure h_vlan_proto, read earlier in the function, was in the linear part. Shared skbs (e.g. from pktgen) are also sent unchanged, since popping the tag modifies the skb, as are skbs already carrying a hwaccel tag (e.g. from generic XDP redirect), whose tag must not be overwritten, skbs carrying XDP metadata, which the pop would have to move, and CHECKSUM_PARTIAL skbs whose csum_start lies within the first VLAN_ETH_HLEN bytes (only possible with bogus offsets, e.g. from AF_XDP tx metadata), which the pop would leave before skb->data.
If popping the header fails (memory allocation failure), the frame is dropped and counted in tx_dropped, rather than handing the real device a frame with an in-band tag.
tx_bytes is now sampled before the pop, so the vlan device statistics do not change.
This also applies to frames provided by the sender with our tag (AF_PACKET SOCK_RAW, or frames redirected from another reorder_hdr=off vlan): the real device now inserts their tag too.
--- net/8021q/vlan_dev.c | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-)
net/8021q/vlan_dev.c +32 -1
@@ -108,6 +108,8 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb,unsigned int len;int ret; + len = skb->len; +/* Handle non-VLAN frames if they are sent to us, for example by DHCP. * * NOTE: THIS ASSUMES DIX ETHERNET, SPECIFICALLY NOT SUPPORTING
@@ -119,10 +121,39 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, vlan_tci = vlan->vlan_id; vlan_tci |=vlan_dev_get_egress_qos_mask (dev, skb->priority);__vlan_hwaccel_put_tag (skb, vlan->vlan_proto, vlan_tci); + }else if (skb_headlen (skb) >=VLAN_ETH_HLEN +sizeof (__be16) && + !skb_shared (skb) && !skb_vlan_tag_present (skb) && + !skb_metadata_len (skb) && + (skb->ip_summed !=CHECKSUM_PARTIAL || +skb_checksum_start_offset (skb) >=VLAN_ETH_HLEN ) && +vlan_hw_offload_capable (READ_ONCE (vlan->real_dev->features), + vlan->vlan_proto)) { +u16 vlan_tci; + +/* The frame carries its outer tag in-band, either inserted +* by vlan_dev_hard_header() or provided by the sender. +* Let the real device insert it: some NICs can not offload +* checksum or TSO for frames carrying an in-band tag. +* Not all ndo_start_xmit() callers set the mac header. +* vlan_set_encap_proto() may read two bytes after the vlan +* header, so frames with a shorter linear part are sent +* unchanged, as are shared skbs (e.g. from pktgen), skbs +* already carrying a hwaccel tag (e.g. from generic XDP +* redirect), skbs carrying XDP metadata, and CHECKSUM_PARTIAL +* skbs whose checksum starts within the header to be popped. +* On allocation failure, drop the frame rather than handing +* it to the real device with an in-band tag. +*/ +skb_reset_mac_header (skb); +if (unlikely (__skb_vlan_pop (skb, &vlan_tci))) { +dev_kfree_skb_any (skb); +this_cpu_inc (vlan->vlan_pcpu_stats->tx_dropped); +return NETDEV_TX_OK ; + } +__vlan_hwaccel_put_tag (skb, vlan->vlan_proto, vlan_tci); } skb->dev = vlan->real_dev; - len = skb->len;if (unlikely (netpoll_tx_running (dev)))return vlan_netpoll_send_skb (vlan, skb);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1877/1887 fbdev: Use /* */ comment in initializer macro
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thomas Zimmermann <[email protected]>
[ Upstream commit cf683e8870bd4be0fd6b98639286700a35088660 ]
Use /* */ in initializer macro to avoid out-commenting the comma at the end of the line.
--- include/linux/fb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
include/linux/fb.h +2 -2
@@ -621,7 +621,7 @@ extern void cfb_imageblit(struct fb_info *info, const struct fb_image *image); .fb_imageblit = cfb_imageblit#define __FB_DEFAULT_IO_OPS_MMAP \ - .fb_mmap = NULL // default implementation + .fb_mmap = NULL/* default implementation */ #define FB_DEFAULT_IO_OPS \ __FB_DEFAULT_IO_OPS_RDWR, \
@@ -654,7 +654,7 @@ extern ssize_t fb_sys_write(struct fb_info *info, const char __user *buf, .fb_imageblit = sys_imageblit#define __FB_DEFAULT_SYS_OPS_MMAP \ - .fb_mmap = NULL // default implementation + .fb_mmap = NULL/* default implementation */ #define FB_DEFAULT_SYS_OPS \ __FB_DEFAULT_SYS_OPS_RDWR, \
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1878/1887 mm/kmemleak: use object_cache instead of kmemleak_initialized to check in set_track_prepare()
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiaolei Wang <[email protected]>
[ Upstream commit 835bc157da689f834d10296d0942aed88b310b4f ]
Patch series "mm/kmemleak: use object_cache instead of kmemleak_initialized", v3.
Use object_cache instead of kmemleak_initialized to check in set_track_prepare(), so that memory leaks after kmemleak_init() can be recorded and Rename kmemleak_initialized to kmemleak_late_initialized
unreferenced object 0xc674ca80 (size 64):
comm "swapper/0", pid 1, jiffies 4294938337 (age 204.880s) hex dump (first 32 bytes):
80 55 75 c6 80 54 75 c6 00 55 75 c6 80 52 75 c6 .Uu..Tu..Uu..Ru. 00 53 75 c6 00 00 00 00 00 00 00 00 00 00 00 00 .Su..........
This patch (of 2):
kmemleak_initialized is set in kmemleak_late_init(), which also means that there is no call trace which object's memory leak is before kmemleak_late_init(), so use object_cache instead of kmemleak_initialized to check in set_track_prepare() to avoid no call trace records when there is a memory leak in the code between kmemleak_init() and kmemleak_late_init().
unreferenced object 0xc674ca80 (size 64):
comm "swapper/0", pid 1, jiffies 4294938337 (age 204.880s) hex dump (first 32 bytes):
80 55 75 c6 80 54 75 c6 00 55 75 c6 80 52 75 c6 .Uu..Tu..Uu..Ru. 00 53 75 c6 00 00 00 00 00 00 00 00 00 00 00 00 .Su..........
--- mm/kmemleak.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
mm/kmemleak.c +6 -1
@@ -611,7 +611,12 @@ static noinline depot_stack_handle_t set_track_prepare(void)unsigned long entries[MAX_TRACE ];unsigned int nr_entries; -if (!kmemleak_initialized) +/* +* Use object_cache to determine whether kmemleak_init() has +* been invoked. stack_depot_early_init() is called before +* kmemleak_init() in mm_core_init(). +*/ +if (!object_cache)return 0 ; nr_entries =stack_trace_save (entries,ARRAY_SIZE (entries),3 ); trace_handle =stack_depot_save (entries, nr_entries,GFP_NOWAIT );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1879/1887 mm: use stack_depot_early_init for kmemleak
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhaoyang Huang <[email protected]>
[ Upstream commit 993f57e0277b78182eb9e4955d118cc8b086c83d ]
Mirsad report the below error which is caused by stack_depot_init() failure in kvcalloc. Solve this by having stackdepot use stack_depot_early_init().
On 1/4/23 17:08, Mirsad Goran Todorovac wrote:
I hate to bring bad news again, but there seems to be a problem with the output of /sys/kernel/debug/kmemleak:
[root@pc-mtodorov ~]# cat /sys/kernel/debug/kmemleak unreferenced object 0xffff951c118568b0 (size 16):
comm "kworker/u12:2", pid 56, jiffies 4294893952 (age 4356.548s) hex dump (first 16 bytes):
6d 65 6d 73 74 69 63 6b 30 00 00 00 00 00 00 00 memstick0.......
backtrace:[root@pc-mtodorov ~]#
Apparently, backtrace of called functions on the stack is no longer printed with the list of memory leaks. This appeared on Lenovo desktop 10TX000VCR, with AlmaLinux 8.7 and BIOS version M22KT49A (11/10/2022) and 6.2-rc1 and 6.2-rc2 builds. This worked on 6.1 with the same CONFIG_KMEMLEAK=y and MGLRU enabled on a vanilla mainstream kernel from Mr. Torvalds' tree. I don't know if this is deliberate feature for some reason or a bug. Please find attached the config, lshw and kmemleak output.
--- lib/Kconfig.debug | 1 + mm/kmemleak.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-)
lib/Kconfig.debug +1 -0
@@ -738,6 +738,7 @@ config DEBUG_KMEMLEAK select KALLSYMS select CRC32 select STACKDEPOT + select STACKDEPOT_ALWAYS_INIT if !DEBUG_KMEMLEAK_DEFAULT_OFF help Say Y here if you want to enable the memory leak detector. The memory allocation/freeing is traced in a way
mm/kmemleak.c +3 -2
@@ -2105,8 +2105,10 @@ static int __init kmemleak_boot_config(char *str)return -EINVAL ;if (strcmp (str,"off" ) ==0 )kmemleak_disable (); -else if (strcmp (str,"on" ) ==0 ) +else if (strcmp (str,"on" ) ==0 ) { kmemleak_skip_disable =1 ; +stack_depot_want_early_init (); + }else return -EINVAL ;return 0 ;
@@ -2128,7 +2130,6 @@ void __init kmemleak_init(void)if (kmemleak_error)return ; -stack_depot_init (); jiffies_min_age =msecs_to_jiffies (MSECS_MIN_AGE ); jiffies_scan_wait =msecs_to_jiffies (SECS_SCAN_WAIT *1000 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1880/1887 scsi: block: Introduce ioprio hints
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal <[email protected]>
[ Upstream commit 6c913257226a25879bfd6226e0ee265e98904ce6 ]
I/O priorities currently only use 6-bits of the 16-bits ioprio value: the 3-upper bits are used to define up to 8 priority classes (4 of which are valid) and the 3 lower bits of the value are used to define a priority level for the real-time and best-effort class.
The remaining 10-bits between the I/O priority class and level are unused, and in fact, cannot be used by the user as doing so would either result in the value being completely ignored, or in an error returned by ioprio_check_cap().
Use these 10-bits of an ioprio value to allow a user to specify I/O hints. An I/O hint is defined as a 10-bitsvalue, allowing up to 1023 different hints to be specified, with the value 0 being reserved as the "no hint" case. An I/O hint can apply to any I/O that specifies a valid priority class other than NONE, regardless of the I/O priority level specified.
To do so, the macros IOPRIO_PRIO_HINT() and IOPRIO_PRIO_VALUE_HINT() are introduced in include/uapi/linux/ioprio.h to respectively allow a user to get and set a hint in an ioprio value.
To support the ATA and SCSI command duration limits feature, 7 hints are
defined: IOPRIO_HINT_DEV_DURATION_LIMIT_1 to IOPRIO_HINT_DEV_DURATION_LIMIT_7, allowing a user to specify which command duration limit descriptor should be applied to the commands serving an I/O. Specifying these hints has for now no effect whatsoever if the target block devices do not support the command duration limits feature. However, in the future, block I/O schedulers can be modified to optimize I/O issuing order based on these hints, even for devices that do not support the command duration limits feature.
Given that the 7 duration limits hints defined have no effect on any block layer component, the actual definition of the duration limits implied by these hints remains at the device level.
Stable-dep-of: 01584c1e2337 ("scsi: block: Improve ioprio value validity checks")
--- include/uapi/linux/ioprio.h | 49 +++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+)
include/uapi/linux/ioprio.h +49 -0
@@ -58,4 +58,53 @@ enum {#define IOPRIO_NORM 4#define IOPRIO_BE_NORM IOPRIO_NORM +/* +* The 10 bits between the priority class and the priority level are used to +* optionally define I/O hints for any combination of I/O priority class and +* level. Depending on the kernel configuration, I/O scheduler being used and +* the target I/O device being used, hints can influence how I/Os are processed +* without affecting the I/O scheduling ordering defined by the I/O priority +* class and level. +*/ +#define IOPRIO_HINT_SHIFT IOPRIO_LEVEL_NR_BITS +#define IOPRIO_HINT_NR_BITS 10 +#define IOPRIO_NR_HINTS (1 << IOPRIO_HINT_NR_BITS) +#define IOPRIO_HINT_MASK (IOPRIO_NR_HINTS - 1) +#define IOPRIO_PRIO_HINT (ioprio) \ + (((ioprio) >> IOPRIO_HINT_SHIFT) & IOPRIO_HINT_MASK) + +/* +* Alternate macro for IOPRIO_PRIO_VALUE() to define an I/O priority with +* a class, level and hint. +*/ +#define IOPRIO_PRIO_VALUE_HINT (class, level, hint) \ + ((((class) & IOPRIO_CLASS_MASK) << IOPRIO_CLASS_SHIFT) | \ + (((hint) & IOPRIO_HINT_MASK) << IOPRIO_HINT_SHIFT) | \ + ((level) & IOPRIO_LEVEL_MASK)) + +/* +* I/O hints. +*/ +enum { +/* No hint */ +IOPRIO_HINT_NONE =0 , + +/* +* Device command duration limits: indicate to the device a desired +* duration limit for the commands that will be used to process an I/O. +* These will currently only be effective for SCSI and ATA devices that +* support the command duration limits feature. If this feature is +* enabled, then the commands issued to the device to process an I/O with +* one of these hints set will have the duration limit index (dld field) +* set to the value of the hint. +*/ +IOPRIO_HINT_DEV_DURATION_LIMIT_1 =1 , +IOPRIO_HINT_DEV_DURATION_LIMIT_2 =2 , +IOPRIO_HINT_DEV_DURATION_LIMIT_3 =3 , +IOPRIO_HINT_DEV_DURATION_LIMIT_4 =4 , +IOPRIO_HINT_DEV_DURATION_LIMIT_5 =5 , +IOPRIO_HINT_DEV_DURATION_LIMIT_6 =6 , +IOPRIO_HINT_DEV_DURATION_LIMIT_7 =7 , +}; +#endif /* _UAPI_LINUX_IOPRIO_H */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1881/1887 scsi: block: Improve ioprio value validity checks
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Damien Le Moal <[email protected]>
[ Upstream commit 01584c1e233740519d0e11aa20daa323d26bf598 ]
The introduction of the macro IOPRIO_PRIO_LEVEL() in commit eca2040972b4 ("scsi: block: ioprio: Clean up interface definition") results in an iopriority level to always be masked using the macro IOPRIO_LEVEL_MASK, and thus to the kernel always seeing an acceptable value for an I/O priority level when checked in ioprio_check_cap(). Before this patch, this function would return an error for some (but not all) invalid values for a level valid range of [0..7].
Restore and improve the detection of invalid priority levels by introducing the inline function ioprio_value() to check an ioprio class, level and hint value before combining these fields into a single value to be used with ioprio_set() or AIOs. If an invalid value for the class, level or hint of an ioprio is detected, ioprio_value() returns an ioprio using the class IOPRIO_CLASS_INVALID, indicating an invalid value and causing ioprio_check_cap() to return -EINVAL.
--- block/ioprio.c | 1 + include/uapi/linux/ioprio.h | 50 ++++++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 17 deletions(-)
block/ioprio.c +1 -0
@@ -58,6 +58,7 @@ int ioprio_check_cap(int ioprio)if (level)return -EINVAL ;break ; +case IOPRIO_CLASS_INVALID :default :return -EINVAL ; }
include/uapi/linux/ioprio.h +33 -17
81 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1882/1887 inet: control sockets should not use current thread task_frag
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 1ac88557447088ccd15eb2f2520ce46d463c8e0b ]
Because ICMP handlers run from softirq contexts, they must not use current thread task_frag.
Previously, all sockets allocated by inet_ctl_sock_create() would use the per-socket page fragment, with no chance of recursion.
--- net/ipv4/af_inet.c | 1 + 1 file changed, 1 insertion(+)
net/ipv4/af_inet.c +1 -0
@@ -1700,6 +1700,7 @@ int inet_ctl_sock_create(struct sock **sk, unsigned short family,if (rc ==0 ) { *sk = sock->sk; (*sk)->sk_allocation =GFP_ATOMIC ; + (*sk)->sk_use_task_frag = false;/* * Unhash it so that IP input processing does not even see it, * we do not wish this socket to see incoming packets.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1883/1887 Revert "esp: do not unref managed frag pages in esp_ssg_unref()"
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steffen Klassert <[email protected]>
[ Upstream commit 0fda52de8bbd4ca9a852c8a7ef6536cf82bd71fd ]
This reverts commit 21697720ff43b8dfa25b8e8d9ca7f56f4597fc80.
The patch does not fix the issue completely, so revert for now and wait for an updated version.
--- net/ipv4/esp4.c | 7 ------- net/ipv6/esp6.c | 7 ------- 2 files changed, 14 deletions(-)
net/ipv4/esp4.c +0 -7
@@ -103,13 +103,6 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)struct aead_request *req;struct scatterlist *sg; -/* Managed frags are owned by the zerocopy ubuf; the skb holds no -* per-frag page reference, so we must not drop one here. Mirrors -* the SKBFL_MANAGED_FRAG_REFS handling in skb_release_data(). -*/ -if (skb_zcopy_managed (skb)) -return ; -if (x->props.flags &XFRM_STATE_ESN ) extralen +=sizeof (struct esp_output_extra );
net/ipv6/esp6.c +0 -7
@@ -120,13 +120,6 @@ static void esp_ssg_unref(struct xfrm_state *x, void *tmp, struct sk_buff *skb)struct aead_request *req;struct scatterlist *sg; -/* Managed frags are owned by the zerocopy ubuf; the skb holds no -* per-frag page reference, so we must not drop one here. Mirrors -* the SKBFL_MANAGED_FRAG_REFS handling in skb_release_data(). -*/ -if (skb_zcopy_managed (skb)) -return ; -if (x->props.flags &XFRM_STATE_ESN ) extralen +=sizeof (struct esp_output_extra );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1884/1887 drm/amdkfd: fix dma_buf reference leak in get_dmabuf_info
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haojie Li <[email protected]>
[ Upstream commit e6895021a328594368a2a19406a53ffca1ce51c7 ]
When kzalloc fails for metadata_buffer in amdgpu_amdkfd_get_dmabuf_info(), the function returns -ENOMEM directly without calling dma_buf_put(), leaking the dma_buf reference obtained earlier via dma_buf_get().
Fix both issues by:
- Adding an error check after the first amdgpu_bo_get_metadata() call
- Replacing the direct return with r = -ENOMEM and goto out_put to ensure dma_buf_put() is called on all error paths
--- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.c +2 -0
@@ -534,6 +534,8 @@ int amdgpu_amdkfd_get_dmabuf_info(struct amdgpu_device *adev, int dma_buf_fd,/* first get metadata_size by buffer = NULL */ r =amdgpu_bo_get_metadata (bo,NULL ,0 , metadata_size,NULL ); +if (r) + goto out_put;/* user buf_size is bigger than bo metadata_size * allocate a buf at kernel space and copy */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1885/1887 gpio: mxc: map Both Edge pad wakeup to Rising Edge
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shenwei Wang <[email protected]>
[ Upstream commit c720fb57d56274213d027b3c5ab99080cf62a306 ]
Suspend may fail on i.MX8QM when Falling Edge is used as a pad wakeup trigger due to a hardware bug in the detection logic. Since the hardware does not support Both Edge wakeup, remap requests for Both Edge to Rising Edge by default to avoid hitting this issue.
A warning is emitted when Falling Edge is selected on i.MX8QM.
--- drivers/gpio/gpio-mxc.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/gpio/gpio-mxc.c +9 -1
@@ -541,12 +541,13 @@ static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable)unsigned long config;bool ret = false;int i, type; +bool is_imx8qm =of_device_is_compatible (port->dev->of_node,"fsl,imx8qm-gpio" );static const u32 pad_type_map[] = {IMX_SCU_WAKEUP_OFF ,/* 0 */ IMX_SCU_WAKEUP_RISE_EDGE ,/* IRQ_TYPE_EDGE_RISING */ IMX_SCU_WAKEUP_FALL_EDGE ,/* IRQ_TYPE_EDGE_FALLING */ -IMX_SCU_WAKEUP_FALL_EDGE ,/* IRQ_TYPE_EDGE_BOTH */ +IMX_SCU_WAKEUP_RISE_EDGE ,/* IRQ_TYPE_EDGE_BOTH */ IMX_SCU_WAKEUP_HIGH_LVL ,/* IRQ_TYPE_LEVEL_HIGH */ IMX_SCU_WAKEUP_OFF ,/* 5 */ IMX_SCU_WAKEUP_OFF ,/* 6 */
@@ -561,6 +562,13 @@ static bool mxc_gpio_set_pad_wakeup(struct mxc_gpio_port *port, bool enable) config = pad_type_map[type]; else config =IMX_SCU_WAKEUP_OFF ; + +if (is_imx8qm && config ==IMX_SCU_WAKEUP_FALL_EDGE ) { +dev_warn_once (port->dev, +"No falling-edge support for wakeup on i.MX8QM\n" ); + config =IMX_SCU_WAKEUP_OFF ; + } + ret |=mxc_gpio_generic_config (port, i, config); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1886/1887 pinctrl: freescale: Fix a memory out of bounds when num_configs is 1
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiaolei Wang <[email protected]>
[ Upstream commit 9063777ca1e2e895c5fdd493ee0c3f18fa710ed4 ]
The config passed in by pad wakeup is 1, when num_configs is 1, Configuration [1] should not be fetched, which will be detected by KASAN as a memory out of bounds condition. Modify to get configs[1] when num_configs is 2.
--- drivers/pinctrl/freescale/pinctrl-scu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/pinctrl/freescale/pinctrl-scu.c +2 -1
@@ -77,7 +77,7 @@ int imx_pinconf_set_scu(struct pinctrl_dev *pctldev, unsigned pin_id,struct imx_sc_msg_req_pad_set msg;struct imx_sc_rpc_msg *hdr = &msg.hdr;unsigned int mux = configs[0 ]; -unsigned int conf = configs[1 ]; +unsigned int conf;unsigned int val;int ret;
@@ -85,6 +85,7 @@ int imx_pinconf_set_scu(struct pinctrl_dev *pctldev, unsigned pin_id,* Set mux and conf together in one IPC call */ WARN_ON (num_configs !=2 ); + conf = configs[1 ]; val = conf |BM_PAD_CTL_IFMUX_ENABLE |BM_PAD_CTL_GP_ENABLE ; val |= mux <<BP_PAD_CTL_IFMUX ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 1887/1887 uapi: stddef.h: Fix header guard location
In reply to Greg Kroah-Hartman6.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexey Dobriyan <[email protected]>
[ Upstream commit 531108ec5b5cd45ec6272a6115e73275baef7d22 ]
The #endif for the header guard wasn't at the end of the header. This was harmless since the define that escaped was already testing for its own redefinition. Regardless, move the #endif to the correct place.
--- include/uapi/linux/stddef.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
include/uapi/linux/stddef.h +2 -1
@@ -51,8 +51,9 @@ struct { } __empty_ ## NAME; \ TYPE NAME[]; \ } -#endif #ifndef __counted_by#define __counted_by (m)#endif + +#endif /* _UAPI_LINUX_STDDEF_H */
Signature · 1 line
2.53.0
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.1.191 release. There are 1887 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 30 Oct 2026 17:02:34 +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.1.191-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.1.y
and the diffstat can be found below.thanks,
greg k-h
The ARM 32-bit kernel fails to build with:
In file included from arch/arm/probes/uprobes/core.c:9:./include/linux/highmem.h: In function 'memcpy_from_folio':./include/linux/highmem.h:427:21: error: implicit declaration of function 'folio_test_highmem'; did you mean 'folio_test_hugetlb'? [-Werror=implicit-function-declaration]
427 | if (folio_test_highmem(folio) &&
| ^~~~~~~~~~~~~~~~~~
| folio_test_hugetlbcc1: some warnings being treated as errors
host-make[6]: *** [scripts/Makefile.build:250: arch/arm/probes/uprobes/core.o] Error 1 host-make[5]: *** [scripts/Makefile.build:503: arch/arm/probes/uprobes] Error 2 host-make[5]: *** Waiting for unfinished jobs....
AS arch/arm/lib/csumpartial.o CC lib/math/lcm.o CC drivers/video/console/dummycon.o CC sound/core/control.o
host-make[4]: *** [scripts/Makefile.build:503: arch/arm/probes] Error 2 host-make[4]: *** Waiting for unfinished jobs...
this is due to 341d4e6294d9 ("highmem: add memcpy_to_folio() and memcpy_from_folio()"). We would need to also back port 00cdf76012ab ("("mm: add memcpy_from_file_folio()")
Signature · 1 line
Florian
Quoted 38 lines · Florian Fainelli
Quoted 14 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.1.191 release. There are 1887 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 30 Oct 2026 17:02:34 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/ patch-6.1.191-rc1.gz or in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable- rc.git linux-6.1.y and the diffstat can be found below.Quoted 3 lines
thanks,
greg k-h
The ARM 32-bit kernel fails to build with:
In file included from
arch/arm/probes/uprobes/core.c:9:./include/linux/highmem.h: In function 'memcpy_from_folio':./include/linux/highmem.h:427:21: error: implicit declaration of function 'folio_test_highmem'; did you mean 'folio_test_hugetlb'? [- Werror=implicit-function-declaration]
427 | if (folio_test_highmem(folio)&&
| ^~~~~~~~~~~~~~~~~~
|folio_test_hugetlb
cc1: some warnings being treated as errors
host-make[6]: *** [scripts/Makefile.build:250:arch/arm/probes/uprobes/core.o] Error 1
host-make[5]: *** [scripts/Makefile.build:503:arch/arm/probes/uprobes] Error 2
host-make[5]: *** Waiting for unfinished jobs....
ASarch/arm/lib/csumpartial.o
CClib/math/lcm.o
CCdrivers/video/console/dummycon.o
CCsound/core/control.o
host-make[4]: *** [scripts/Makefile.build:503:arch/arm/probes] Error 2
host-make[4]: *** Waiting for unfinished jobs...
Quoted 1 line
this is due to
341d4e6294d9("highmem: addmemcpy_to_folio()andmemcpy_from_folio()"). We would need to also back port00cdf76012ab("("mm: addmemcpy_from_file_folio()")
And there is this other build failure caused by 997f9c35fcad ("Bluetooth: MGMT: fix crash in set_mesh_sync and set_mesh_complete")
net/bluetooth/mgmt.c: In function 'set_mesh_sync':net/bluetooth/mgmt.c:2188:36: error: implicit declaration of function '__struct_size'; did you mean 'struct_size'? [-Werror=implicit-function-declaration]
2188 | memcpy(cp, cmd->param, min(__struct_size(cp), len));
| ^~~~~~~~~~~~~./include/linux/minmax.h:92:27: note: in definition of macro '__careful_cmp_once'
92 | __auto_type ux = (x); __auto_type uy = (y); \
| ^./include/linux/minmax.h:105:25: note: in expansion of macro '__careful_cmp'
105 | #define min(x, y) __careful_cmp(min, x, y)
| ^~~~~~~~~~~~~net/bluetooth/mgmt.c:2188:32: note: in expansion of macro 'min'
2188 | memcpy(cp, cmd->param, min(__struct_size(cp), len));
| ^~~
In file included from <command-line>:././include/linux/compiler_types.h:387:45: error: call to '__compiletime_assert_741' declared with attribute error: min(__struct_size(cp), len) signedness error
387 | _compiletime_assert(condition, msg,__compiletime_assert_, __COUNTER__)
| ^././include/linux/compiler_types.h:368:25: note: in definition of macro '__compiletime_assert'
368 | prefix ## suffix();
\
| ^~~~~~
././include/linux/compiler_types.h:387:9: note: in expansion of macro '_compiletime_assert'
387 | _compiletime_assert(condition, msg,
__compiletime_assert_, __COUNTER__)
| ^~~~~~~~~~~~~~~~~~~
./include/linux/build_bug.h:39:37: note: in expansion of macro 'compiletime_assert'
39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond),
msg)
| ^~~~~~~~~~~~~~~~~~
./include/linux/minmax.h:93:9: note: in expansion of macro 'BUILD_BUG_ON_MSG'
93 | BUILD_BUG_ON_MSG(!__types_ok(ux, uy), \
| ^~~~~~~~~~~~~~~~
./include/linux/minmax.h:98:9: note: in expansion of macro '__careful_cmp_once'
98 | __careful_cmp_once(op, x, y, __UNIQUE_ID(x_),
__UNIQUE_ID(y_))
| ^~~~~~~~~~~~~~~~~~
./include/linux/minmax.h:105:25: note: in expansion of macro '__careful_cmp'
105 | #define min(x, y) __careful_cmp(min, x, y)
| ^~~~~~~~~~~~~net/bluetooth/mgmt.c:2188:32: note: in expansion of macro 'min'
2188 | memcpy(cp, cmd->param, min(__struct_size(cp), len));
| ^~~
cc1: some warnings being treated as errors
We would need to back port 26dd68d293fd but this does not apply cleanly.
Signature · 1 line
Florian
Sasha Levin
maintainerQuoted 3 lines · Florian Fainelli
Quoted 2 lines · Florian Fainelli
this is due to
341d4e6294d9("highmem: addmemcpy_to_folio()andmemcpy_from_folio()"). We would need to also back port00cdf76012ab
That one was already addressed earlier today. Rather than adding 00cdf76012ab, I dropped the highmem/hfs set from the 6.1 queue:
- highmem: add memcpy_to_folio() and memcpy_from_folio()
- highmem: fix a memory copy problem in memcpy_from_folio
- hfs: fix general protection fault in hfs_find_init()
- pagemap: add filemap_grab_folio()
Quoted 6 lines
And there is this other build failure caused by
997f9c35fcad("Bluetooth: MGMT: fix crash inset_mesh_syncandset_mesh_complete")
net/bluetooth/mgmt.c: In function 'set_mesh_sync':net/bluetooth/mgmt.c:2188:36: error: implicit declaration of function '__struct_size'; did you mean 'struct_size'?
The 6.1 backport of that patch uses __struct_size(), which on 6.1 is only available with CONFIG_FORTIFY_SOURCE enabled, so it breaks the build without it. Fixed by dropping the five-patch Bluetooth MGMT cluster from the 6.1 queue:
- Bluetooth: MGMT: Fix possible UAFs
- Bluetooth: MGMT: Fix dangling pointer on mgmt_add_adv_patterns_monitor_complete
- Bluetooth: MGMT: Fix memory leak in set_ssp_complete
- Bluetooth: MGMT: fix crash in set_mesh_sync and set_mesh_complete
- Bluetooth: MGMT: Fix list corruption and UAF in command complete handlers
Signature · 2 lines
Thanks, Sasha
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 6.1.191 release. There are 1887 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 failure in Bluetooth (we probably see the other reported bugs, too, I did not check):
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/jobs/17550762421
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/pipelines/3000620758
Best regards,
Pavel
net/bluetooth/mgmt.c: In function 'set_mesh_sync':
3514
18:36:58net/bluetooth/mgmt.c:2188:36: error: implicit declaration of function '__struct_size'; did you mean 'struct_size'? [-Werror=implicit-function-declaration] 3515
18:36:58
2188 | memcpy(cp, cmd->param, min(__struct_size(cp), len));
3516
18:36:58
| ^~~~~~~~~~~~~
3517
18:36:58./include/linux/minmax.h:92:27: note: in definition of macro '__careful_cmp_once' 3518
18:36:58
92 | __auto_type ux = (x); __auto_type uy = (y); \
3519
18:36:58
| ^
3520
18:36:58./include/linux/minmax.h:105:25: note: in expansion of macro '__careful_cmp' 3521
18:36:58
105 | #define min(x, y) __careful_cmp(min, x, y)
3522
18:36:58
| ^~~~~~~~~~~~~
3523
18:36:58net/bluetooth/mgmt.c:2188:32: note: in expansion of macro 'min' 3524
18:36:58
2188 | memcpy(cp, cmd->param, min(__struct_size(cp), len));
3525
18:36:58
| ^~~
Am 28.10.2026 um 17:34 schrieb Greg Kroah-Hartman:
Quoted 4 lines
This is the start of the stable review cycle for the 6.1.191 release. There are 1887 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.
Strangely, I don't see the build failure in amdgpu that Brett encountered. Config attached.
Builds, boots and works on my 2-socket Ivy Bridge Xeon E5-2697v2 server. No dmesg oddities or regressions found.
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]
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.1.191 release. There are 1887 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 30 Oct 2026 17:02:34 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.1.191-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.1.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.1.191 release. There are 1887 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Responses should be made by Fri, 30 Oct 2026 17:02:34 +0000. Anything received after that time might be too late.
The whole patch series can be found in one patch at:
Quoted 9 lines
https://www.kernel.org/pub/linux/kernel/v6.x/stable-review/patch-6.1.191-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.1.y
and the diffstat can be found below.thanks,
greg k-h
Compiled and booted on my test system. No dmesg regressions.
thanks,
-- Shuah