6.6.144-rc1 review
Subsystems (6)
Greg Kroah-Hartman
maintainerPATCH 115/175 batman-adv: tvlv: avoid race of cifsnotfound handler state
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit edb557b2ba38fea2c5eb710cf366c797e187218c upstream.
TVLV handlers can have the flag BATADV_TVLV_HANDLER_OGM_CIFNOTFND set to signal that the OGM handler should be called (with NULL for data) when the specific TVLV container was not found in the OGM. This is used by:
* DAT
* GW
* Multicast (OGM + Tracker)
The state whether the handler was executed was stored in the struct batadv_tvlv_handler. But the TVLV processing is started without any lock. Multiple parallel contexts processing TVLVs would therefore overwrite each others BATADV_TVLV_HANDLER_OGM_CALLED flag in the shared batadv_tvlv_handler.
Drop the shared BATADV_TVLV_HANDLER_OGM_CALLED flag and instead determine, per TVLV buffer, whether a matching container was present by scanning the packet's buffer.
--- net/batman-adv/tvlv.c | 63 ++++++++++++++++++++++++++++++++++++++---- net/batman-adv/types.h | 7 ----- 2 files changed, 57 insertions(+), 13 deletions(-)
net/batman-adv/tvlv.c +57 -6
@@ -398,7 +398,6 @@ static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv, tvlv_handler->ogm_handler (bat_priv, orig_node,BATADV_NO_FLAGS , tvlv_value, tvlv_value_len); - tvlv_handler->flags |=BATADV_TVLV_HANDLER_OGM_CALLED ;break ;case BATADV_UNICAST_TVLV :if (!skb)
@@ -430,6 +429,48 @@ static int batadv_tvlv_call_handler(struct batadv_priv *bat_priv,return NET_RX_SUCCESS ; } +/** +* batadv_tvlv_containers_contain() - check if a tvlv buffer holds a container +* @tvlv_value: tvlv content +* @tvlv_value_len: tvlv content length +* @type: tvlv container type to look for +* @version: tvlv container version to look for +* +* Return: true if a container of the given type and version is present in the +* tvlv buffer, false otherwise. +*/ +static bool batadv_tvlv_containers_contain (void *tvlv_value, +u16 tvlv_value_len,u8 type, +u8 version) +{ +struct batadv_tvlv_hdr *tvlv_hdr; +u16 tvlv_value_cont_len; + +while (tvlv_value_len >=sizeof (*tvlv_hdr)) { + tvlv_hdr = tvlv_value; + tvlv_value_cont_len =ntohs (tvlv_hdr->len); + tvlv_value = tvlv_hdr +1 ; + tvlv_value_len -=sizeof (*tvlv_hdr); + +if (tvlv_value_cont_len > tvlv_value_len) +break ; + +/* the next tvlv header is accessed assuming (at least) 2-byte +* alignment, so it must start at an even offset. +*/ +if (tvlv_value_cont_len &1 ) +break ; + +if (tvlv_hdr->type == type && tvlv_hdr->version == version) +return true; + + tvlv_value = (u8 *)tvlv_value + tvlv_value_cont_len; + tvlv_value_len -= tvlv_value_cont_len; + } + +return false; +} +/** * batadv_tvlv_containers_process() - parse the given tvlv buffer to call the * appropriate handlers
@@ -449,7 +490,9 @@ int batadv_tvlv_containers_process(struct batadv_priv *bat_priv, struct sk_buff *skb, void *tvlv_value, u16 tvlv_value_len) { + u16 tvlv_value_start_len = tvlv_value_len;struct batadv_tvlv_handler *tvlv_handler; +void *tvlv_value_start = tvlv_value;struct batadv_tvlv_hdr *tvlv_hdr;u16 tvlv_value_cont_len;u8 cifnotfound =BATADV_TVLV_HANDLER_OGM_CIFNOTFND ;
@@ -493,12 +536,20 @@ int batadv_tvlv_containers_process(struct batadv_priv *bat_priv,if (!tvlv_handler->ogm_handler)continue ; -if ((tvlv_handler->flags &BATADV_TVLV_HANDLER_OGM_CIFNOTFND ) && - !(tvlv_handler->flags &BATADV_TVLV_HANDLER_OGM_CALLED )) - tvlv_handler->ogm_handler (bat_priv, orig_node, - cifnotfound,NULL ,0 ); +if (!(tvlv_handler->flags &BATADV_TVLV_HANDLER_OGM_CIFNOTFND )) +continue ; - tvlv_handler->flags &= ~BATADV_TVLV_HANDLER_OGM_CALLED ; +/* if the corresponding container was present then the handler +* was already called from the loop above +*/ +if (batadv_tvlv_containers_contain (tvlv_value_start, + tvlv_value_start_len, + tvlv_handler->type, + tvlv_handler->version)) +continue ; + + tvlv_handler->ogm_handler (bat_priv, orig_node, + cifnotfound,NULL ,0 ); }rcu_read_unlock ();
net/batman-adv/types.h +0 -7
@@ -2413,13 +2413,6 @@ enum batadv_tvlv_handler_flags {* will call this handler even if its type was not found (with no data) */ BATADV_TVLV_HANDLER_OGM_CIFNOTFND = BIT(1), - -/** -* @BATADV_TVLV_HANDLER_OGM_CALLED: interval tvlv handling flag - the -* API marks a handler as being called, so it won't be called if the -* BATADV_TVLV_HANDLER_OGM_CIFNOTFND flag was set -*/ - BATADV_TVLV_HANDLER_OGM_CALLED = BIT(2), };#endif /* _NET_BATMAN_ADV_TYPES_H_ */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 116/175 ipv6: account for fraggap on the paged allocation path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wongi Lee <[email protected]>
commit 736b380e28d0480c7bc3e022f1950f31fe53a7c5 upstream.
In __ip6_append_data(), when the paged-allocation branch is taken (MSG_MORE / NETIF_F_SG / large fraglen), alloclen and pagedlen are computed as
alloclen = fragheaderlen + transhdrlen; pagedlen = datalen - transhdrlen;
datalen already includes fraggap (datalen = length + fraggap). When fraggap is non-zero, this is not the first skb and transhdrlen is zero. The fraggap bytes carried over from the previous skb are copied just past the fragment headers in the new skb's linear area. The linear area is therefore undersized by fraggap bytes while pagedlen is overstated by the same amount, and the copy writes past skb->end into the trailing skb_shared_info.
An unprivileged user can trigger this via a UDPv6 socket using MSG_MORE together with MSG_SPLICE_PAGES.
The bad accounting was introduced by commit 773ba4fe9104 ("ipv6:
avoid partial copy for zc"). Before commit ce650a166335 ("udp6: Fix __ip6_append_data()'s handling of MSG_SPLICE_PAGES"), the negative copy value caused -EINVAL to be returned. That later commit allowed MSG_SPLICE_PAGES to proceed in this case, making the corruption triggerable.
The non-paged branch sets alloclen to fraglen, which already accounts for fraggap because datalen does. Bring the paged branch in line by adding fraggap to alloclen and subtracting it from pagedlen.
After this adjustment, copy no longer collapses to -fraggap on the paged path, so remove the stale comment describing that old arithmetic. Since a negative copy is no longer expected for a valid MSG_SPLICE_PAGES case, remove the MSG_SPLICE_PAGES exception from the negative copy check.
--- net/ipv6/ip6_output.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
net/ipv6/ip6_output.c +3 -6
@@ -1633,8 +1633,8 @@ alloc_new_skb: !(rt->dst.dev->features & NETIF_F_SG))) alloclen = fraglen; else { - alloclen = fragheaderlen + transhdrlen; - pagedlen = datalen - transhdrlen; + alloclen = fragheaderlen + transhdrlen + fraggap; + pagedlen = datalen - transhdrlen - fraggap; } alloclen += alloc_extra;
@@ -1649,10 +1649,7 @@ alloc_new_skb: fraglen = datalen + fragheaderlen; copy = datalen - transhdrlen - fraggap - pagedlen; -/* [!] NOTE: copy may be negative if pagedlen>0 -* because then the equation may reduces to -fraggap. -*/ -if (copy <0 && !(flags &MSG_SPLICE_PAGES )) { +if (copy <0 ) { err = -EINVAL ; goto error; }
Greg Kroah-Hartman
maintainerPATCH 117/175 inet: add indirect call wrapper for getfrag() calls
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 5204ccbfa22358f95afd031a3f337e6d9a74baea ]
UDP send path suffers from one indirect call to ip_generic_getfrag()
We can use INDIRECT_CALL_1() to avoid it.
Stable-dep-of: eca856950f7c ("ipv4: account for fraggap on the paged allocation path")
--- net/ipv4/ip_output.c | 13 +++++++++---- net/ipv6/ip6_output.c | 13 ++++++++----- 2 files changed, 17 insertions(+), 9 deletions(-)
net/ipv4/ip_output.c +9 -4
@@ -1168,7 +1168,10 @@ static int __ip_append_data(struct sock *sk,/* [!] NOTE: copy will be negative if pagedlen>0 * because then the equation reduces to -fraggap. */ -if (copy >0 &&getfrag (from, data + transhdrlen, offset, copy, fraggap, skb) <0 ) { +if (copy >0 && +INDIRECT_CALL_1 (getfrag, ip_generic_getfrag, + from, data + transhdrlen, offset, + copy, fraggap, skb) <0 ) { err = -EFAULT ;kfree_skb (skb); goto error;
@@ -1212,8 +1215,9 @@ static int __ip_append_data(struct sock *sk,unsigned int off; off = skb->len; -if (getfrag (from,skb_put (skb, copy), - offset, copy, off, skb) <0 ) { +if (INDIRECT_CALL_1 (getfrag, ip_generic_getfrag, + from,skb_put (skb, copy), + offset, copy, off, skb) <0 ) {__skb_trim (skb, off); err = -EFAULT ; goto error;
@@ -1253,7 +1257,8 @@ static int __ip_append_data(struct sock *sk,get_page (pfrag->page); } copy =min_t (int, copy, pfrag->size - pfrag->offset); -if (getfrag (from, +if (INDIRECT_CALL_1 (getfrag, ip_generic_getfrag, + from,page_address (pfrag->page) + pfrag->offset, offset, copy, skb->len, skb) <0 ) goto error_efault;
net/ipv6/ip6_output.c +8 -5
@@ -1695,8 +1695,9 @@ static int __ip6_append_data(struct sock *sk,pskb_trim_unique (skb_prev, maxfraglen); }if (copy >0 && -getfrag (from, data + transhdrlen, offset, - copy, fraggap, skb) <0 ) { +INDIRECT_CALL_1 (getfrag, ip_generic_getfrag, + from, data + transhdrlen, offset, + copy, fraggap, skb) <0 ) { err = -EFAULT ;kfree_skb (skb); goto error;
@@ -1740,8 +1741,9 @@ static int __ip6_append_data(struct sock *sk,unsigned int off; off = skb->len; -if (getfrag (from,skb_put (skb, copy), - offset, copy, off, skb) <0 ) { +if (INDIRECT_CALL_1 (getfrag, ip_generic_getfrag, + from,skb_put (skb, copy), + offset, copy, off, skb) <0 ) {__skb_trim (skb, off); err = -EFAULT ; goto error;
@@ -1781,7 +1783,8 @@ static int __ip6_append_data(struct sock *sk,get_page (pfrag->page); } copy =min_t (int, copy, pfrag->size - pfrag->offset); -if (getfrag (from, +if (INDIRECT_CALL_1 (getfrag, ip_generic_getfrag, + from,page_address (pfrag->page) + pfrag->offset, offset, copy, skb->len, skb) <0 ) goto error_efault;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 118/175 ipv4: account for fraggap on the paged allocation path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wongi Lee <[email protected]>
[ Upstream commit eca856950f7cb1a221e02b99d758409f2c5cec42 ]
In __ip_append_data(), when the paged-allocation branch is taken, alloclen and pagedlen are computed as
alloclen = fragheaderlen + transhdrlen; pagedlen = datalen - transhdrlen;
datalen already includes fraggap, but the fraggap bytes carried over from the previous skb are copied into the new skb's linear area at offset transhdrlen by the subsequent skb_copy_and_csum_bits(). The linear area is therefore undersized by fraggap bytes while pagedlen is overstated by the same amount.
The non-paged branch sets alloclen to fraglen, which already accounts for fraggap because datalen does. Bring the paged branch in line by adding fraggap to alloclen and subtracting it from pagedlen.
After this adjustment, copy no longer collapses to -fraggap on the paged path, so remove the stale comment describing that old arithmetic.
--- net/ipv4/ip_output.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-)
net/ipv4/ip_output.c +2 -5
@@ -1117,8 +1117,8 @@ static int __ip_append_data(struct sock *sk, !(rt->dst.dev->features & NETIF_F_SG))) alloclen = fraglen; else { - alloclen = fragheaderlen + transhdrlen; - pagedlen = datalen - transhdrlen; + alloclen = fragheaderlen + transhdrlen + fraggap; + pagedlen = datalen - transhdrlen - fraggap; } alloclen += alloc_extra;
@@ -1165,9 +1165,6 @@ static int __ip_append_data(struct sock *sk, } copy = datalen - transhdrlen - fraggap - pagedlen; -/* [!] NOTE: copy will be negative if pagedlen>0 -* because then the equation reduces to -fraggap. -*/ if (copy >0 && INDIRECT_CALL_1(getfrag, ip_generic_getfrag, from, data + transhdrlen, offset,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 119/175 ntfs3: reject direct userspace writes to reserved $LX* xattrs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Konstantin Komarov <[email protected]>
commit 5b08dccecf825cbf905f348bc6ccb497507e28e2 upstream.
NTFS3 uses $LXUID, $LXGID, $LXMOD and $LXDEV as internal WSL permission metadata and reloads them into i_uid, i_gid and i_mode from ntfs_get_wsl_perm().
Because the empty-prefix xattr handler also lets file owners call setxattr() on these names directly, an unprivileged writer on a writable ntfs3 mount can plant root ownership and S_ISUID on their own file and gain euid 0 after inode reload.
Reject direct userspace writes to the reserved $LX* names. Internal ntfs3 metadata updates are unchanged because ntfs_save_wsl_perm() writes them via ntfs_set_ea() directly.
--- fs/ntfs3/xattr.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
fs/ntfs3/xattr.c +12 -0
@@ -828,6 +828,12 @@ out:return err; } +static bool ntfs_is_reserved_lxattr (const char *name) +{ +return !strcmp (name,"$LXUID" ) || !strcmp (name,"$LXGID" ) || + !strcmp (name,"$LXMOD" ) || !strcmp (name,"$LXDEV" ); +} +/* * ntfs_setxattr - inode_operations::setxattr */
@@ -932,6 +938,12 @@ set_new_fa: goto out; } +/* Do not allow non privileged users to change $LXUID/$LXGID... */ +if (ntfs_is_reserved_lxattr (name) && !capable (CAP_SYS_ADMIN )) { + err = -EPERM ; + goto out; + } +/* Deal with NTFS extended attribute. */ err =ntfs_set_ea (inode, name,strlen (name), value, size, flags,0 ,NULL );
Greg Kroah-Hartman
maintainerPATCH 120/175 nvmet-tcp: fix race between ICReq handling and queue teardown
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chaitanya Kulkarni <[email protected]>
commit 5293a8882c549fab4a878bc76b0b6c951f980a61 upstream.
nvmet_tcp_handle_icreq() updates queue->state after sending an Initialization Connection Response (ICResp), but it does so without serializing against target-side queue teardown.
If an NVMe/TCP host sends an Initialization Connection Request (ICReq) and immediately closes the connection, target-side teardown may start in softirq context before io_work drains the already buffered ICReq. In that case, nvmet_tcp_schedule_release_queue() sets queue->state to NVMET_TCP_Q_DISCONNECTING and drops the queue reference under state_lock.
If io_work later processes that ICReq, nvmet_tcp_handle_icreq() can still overwrite the state back to NVMET_TCP_Q_LIVE. That defeats the DISCONNECTING-state guard in nvmet_tcp_schedule_release_queue() and allows a later socket state change to re-enter teardown and issue a second kref_put() on an already released queue.
The ICResp send failure path has the same problem. If teardown has already moved the queue to DISCONNECTING, a send error can still overwrite the state with NVMET_TCP_Q_FAILED, again reopening the window for a second teardown path to drop the queue reference.
Fix this by serializing both post-send state transitions with state_lock and bailing out if teardown has already started.
Use -ESHUTDOWN as an internal sentinel for that bail-out path rather than propagating it as a transport error like -ECONNRESET. Keep nvmet_tcp_socket_error() setting rcv_state to NVMET_TCP_RECV_ERR before honoring that sentinel so receive-side parsing stays quiesced until the existing release path completes.
[ context diff adaptation: drop queue->state = NVMET_TCP_Q_FAILED since
the enum introduced in 6.7, 675b453e0241 ("nvmet-tcp: enable TLS handshake upcall" ]
--- drivers/nvme/target/tcp.c | 29 ++++++++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-)
drivers/nvme/target/tcp.c +28 -1
@@ -380,6 +380,19 @@ static int nvmet_tcp_build_pdu_iovec(struct nvmet_tcp_cmd *cmd)static void nvmet_tcp_fatal_error (struct nvmet_tcp_queue *queue) { +/* +* Keep rcv_state at RECV_ERR even for the internal -ESHUTDOWN path. +* nvmet_tcp_handle_icreq() can return -ESHUTDOWN after the ICReq has +* already been consumed and queue teardown has started. +* +* If nvmet_tcp_data_ready() or nvmet_tcp_write_space() queues +* nvmet_tcp_io_work() again before nvmet_tcp_release_queue_work() +* cancels it, the queue must not keep that old receive state. +* Otherwise the next nvmet_tcp_io_work() run can reach +* nvmet_tcp_done_recv_pdu() and try to handle the same ICReq again. +* +* That is why queue->rcv_state needs to be updated before we return. +*/ queue->rcv_state =NVMET_TCP_RECV_ERR ;if (queue->nvme_sq.ctrl)nvmet_ctrl_fatal_error (queue->nvme_sq.ctrl);
@@ -935,10 +948,24 @@ static int nvmet_tcp_handle_icreq(struct nvmet_tcp_queue *queue) iov.iov_base = icresp; iov.iov_len =sizeof (*icresp); ret =kernel_sendmsg (queue->sock, &msg, &iov,1 , iov.iov_len); -if (ret <0 ) +if (ret <0 ) { +spin_lock_bh (&queue->state_lock); +if (queue->state ==NVMET_TCP_Q_DISCONNECTING ) { +spin_unlock_bh (&queue->state_lock); +return -ESHUTDOWN ; + } +spin_unlock_bh (&queue->state_lock);return ret;/* queue removal will cleanup */ + } +spin_lock_bh (&queue->state_lock); +if (queue->state ==NVMET_TCP_Q_DISCONNECTING ) { +spin_unlock_bh (&queue->state_lock); +/* Tell nvmet_tcp_socket_error() teardown is in progress. */ +return -ESHUTDOWN ; + } queue->state =NVMET_TCP_Q_LIVE ; +spin_unlock_bh (&queue->state_lock);nvmet_prepare_receive_pdu (queue);return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 121/175 af_unix: Set gc_in_progress to true in unix_gc().
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit d82ba05263c69fa2437fe93e4e561cc40f4c03af ]
Igor Ushakov reported that unix_gc() could run with gc_in_progress being false if the work is scheduled while running:
Thread 1 Thread 2 Thread 3
-------- -------- --------
unix_schedule_gc() unix_schedule_gc()
`- if (!gc_in_progress) `- if (!gc_in_progress)
|- gc_in_progress = true |
`- queue_work() |
unix_gc() <----------------/ |
| |- gc_in_progress = true
... `- queue_work()
| |
`- gc_in_progress = false |
| unix_gc() <---------------------------------------------' |
... /* gc_in_progress == false */
|
`- gc_in_progress = false
unix_peek_fpl() relies on gc_in_progress not to confuse GC by MSG_PEEK.
Let's set gc_in_progress to true in unix_gc().
[ Add setting gc_in_progress in __unix_gc(). Keep the existing
set in unix_gc() for wait_for_unix_gc() over-limit throttling. ]
--- net/unix/garbage.c | 2 ++ 1 file changed, 2 insertions(+)
net/unix/garbage.c +2 -0
@@ -583,6 +583,8 @@ static void __unix_gc(struct work_struct *work)struct sk_buff_head hitlist;struct sk_buff *skb; +WRITE_ONCE (gc_in_progress, true); +spin_lock (&unix_gc_lock);if (!unix_graph_maybe_cyclic) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 122/175 mac802154: llsec: add skb_cow_data() before in-place crypto
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Doruk Tan Ozturk <[email protected]>
commit 84a04eb5b210643bd67aab81ff805d32f62aa865 upstream.
llsec_do_encrypt_unauth(), llsec_do_encrypt_auth(), llsec_do_decrypt_unauth(), and llsec_do_decrypt_auth() all perform in-place cryptographic transformations on skb data. They build a scatterlist with sg_init_one() pointing into the skb's linear data area and then pass the same scatterlist as both src and dst to the crypto API (e.g. crypto_skcipher_encrypt/decrypt, crypto_aead_encrypt/decrypt).
On the RX path, __ieee802154_rx_handle_packet() clones the received skb before handing it to each subscriber via ieee802154_subif_frame(). The cloned skb shares the same underlying data buffer via reference counting. When llsec_do_decrypt() subsequently modifies this shared buffer in place, it corrupts data that other clones -- potentially belonging to other sockets or subsystems -- still reference.
On the TX path, similar data sharing can occur when an skb's head has been cloned (skb_cloned() returns true).
The fix is to call skb_cow_data() before performing any in-place crypto operation. skb_cow_data() ensures that the skb's data area is not
shared: if the skb head is cloned or the data spans multiple fragments, it copies the data into a private buffer that can be safely modified in place. This is the same pattern used by:
- ESP (net/ipv4/esp4.c, net/ipv6/esp6.c)
- MACsec (drivers/net/macsec.c)
- WireGuard (drivers/net/wireguard/receive.c)
- TIPC (net/tipc/crypto.c)
Without this guard, in-place crypto on shared skb data leads to:
- Silent data corruption of other skb clones
- Use-after-free when the crypto API scatterwalk writes through a page that has already been freed by another clone's kfree_skb()
- Kernel crashes under concurrent 802.15.4 traffic with security enabled (KASAN/KMSAN reports slab-use-after-free)
Found by 0sec (https://0sec.ai) using automated source analysis.
--- net/mac802154/llsec.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
net/mac802154/llsec.c +14 -0
@@ -710,6 +710,7 @@ int mac802154_llsec_encrypt(struct mac80 {struct ieee802154_hdr hdr;int rc, authlen, hlen; +struct sk_buff *trailer;struct mac802154_llsec_key *key;u32 frame_ctr;
@@ -769,6 +770,12 @@ int mac802154_llsec_encrypt(struct mac80 skb->mac_len =ieee802154_hdr_push (skb, &hdr);skb_reset_mac_header (skb); + rc =skb_cow_data (skb,0 , &trailer); +if (rc <0 ) { +llsec_key_put (key); +return rc; + } + rc =llsec_do_encrypt (skb, sec, &hdr, key);llsec_key_put (key);
@@ -908,6 +915,13 @@ llsec_do_decrypt(struct sk_buff *skb, coconst struct ieee802154_hdr *hdr, struct mac802154_llsec_key *key, __le64 dev_addr) { + struct sk_buff *trailer; +int err; + + err =skb_cow_data (skb,0 , &trailer); +if (err <0 ) +return err; +if (hdr->sec.level ==IEEE802154_SCF_SECLEVEL_ENC )return llsec_do_decrypt_unauth (skb, sec, hdr, key, dev_addr);else
Greg Kroah-Hartman
maintainerPATCH 123/175 net: skmsg: preserve sg.copy across SG transforms
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yiming Qian <[email protected]>
commit 406e8a651a7b854c41fecd5117bb282b3a6c2c6b upstream.
The sk_msg sg.copy bitmap is part of the scatterlist entry ownership state. A set bit tells sk_msg_compute_data_pointers() not to expose the entry through writable BPF ctx->data. This protects entries backed by pages that are not private to the sk_msg, such as splice-backed file page-cache pages.
Several sk_msg transform paths move, copy, split, or compact msg->sg.data[] entries without moving the matching sg.copy bit. This can make an externally backed entry arrive at a new slot with a clear copy bit. A later SK_MSG verdict can then expose sg_virt(sge) as writable ctx->data and BPF stores can modify the original page cache.
Keep sg.copy synchronized with sg.data[] whenever entries are transferred, shifted, split, or copied into a new sk_msg. Clear the bit when an entry is replaced by a newly allocated private page or freed. This covers the BPF pull/push/pop helpers, sk_msg_shift_left/right(), sk_msg_xfer(), and tls_split_open_record(), including the partial tail entry created during TLS open-record splitting.
--- include/linux/skmsg.h | 15 +++++++++++---- net/core/filter.c | 27 +++++++++++++++++++++++++++ net/core/skmsg.c | 2 ++ net/tls/tls_sw.c | 4 ++++ 4 files changed, 44 insertions(+), 4 deletions(-)
include/linux/skmsg.h +11 -4
@@ -4,6 +4,7 @@#ifndef _LINUX_SKMSG_H#define _LINUX_SKMSG_H +#include <linux/bitops.h> #include <linux/bpf.h> #include <linux/filter.h> #include <linux/scatterlist.h>
@@ -190,11 +191,14 @@ static inline void sk_msg_xfer(struct sk int which, u32 size) { dst->sg.data[which] = src->sg.data[which]; +__assign_bit (which, dst->sg.copy,test_bit (which, src->sg.copy)); dst->sg.data[which].length = size; dst->sg.size += size; src->sg.size -= size; src->sg.data[which].length -= size; src->sg.data[which].offset += size; +if (!src->sg.data[which].length) +__clear_bit (which, src->sg.copy); }static inline void sk_msg_xfer_full (struct sk_msg *dst,struct sk_msg *src)
@@ -264,16 +268,19 @@ static inline void sk_msg_page_add(strucstatic inline void sk_msg_sg_copy (struct sk_msg *msg,u32 i,bool copy_state) {do { -if (copy_state) -__set_bit (i, msg->sg.copy); -else -__clear_bit (i, msg->sg.copy); +__assign_bit (i, msg->sg.copy, copy_state);sk_msg_iter_var_next (i);if (i == msg->sg.end)break ; }while (1 ); } +static inline void sk_msg_sg_copy_assign (struct sk_msg *dst,u32 dst_i, +const struct sk_msg *src,u32 src_i) +{ +__assign_bit (dst_i, dst->sg.copy,test_bit (src_i, src->sg.copy)); +} +static inline void sk_msg_sg_copy_set (struct sk_msg *msg,u32 start) {sk_msg_sg_copy (msg, start, true);
net/core/filter.c +27 -0
@@ -2721,11 +2721,13 @@ BPF_CALL_4(bpf_msg_pull_data, struct sk_ poffset += len; sge->length =0 ;put_page (sg_page (sge)); +__clear_bit (i, msg->sg.copy);sk_msg_iter_var_next (i); }while (i != last_sge);sg_set_page (&msg->sg.data[first_sge], page, copy,0 ); +__clear_bit (first_sge, msg->sg.copy);/* To repair sg ring we need to shift entries. If we only * had a single entry though we can just replace it and
@@ -2751,9 +2753,11 @@ BPF_CALL_4(bpf_msg_pull_data, struct sk_break ; msg->sg.data[i] = msg->sg.data[move_from]; +sk_msg_sg_copy_assign (msg, i, msg, move_from); msg->sg.data[move_from].length =0 ; msg->sg.data[move_from].page_link =0 ; msg->sg.data[move_from].offset =0 ; +__clear_bit (move_from, msg->sg.copy);sk_msg_iter_var_next (i); }while (1 );
@@ -2782,6 +2786,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_ {struct scatterlist sge, nsge, nnsge, rsge = {0 }, *psge;u32 new, i =0 , l =0 , space, copy =0 , offset =0 ; +bool sge_copy, nsge_copy, nnsge_copy, rsge_copy = false;u8 *raw, *to, *from;struct page *page;
@@ -2854,6 +2859,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_sk_msg_iter_var_prev (i); psge =sk_msg_elem (msg, i); rsge =sk_msg_elem_cpy (msg, i); + rsge_copy =test_bit (i, msg->sg.copy); psge->length = start - offset; rsge.length -= psge->length;
@@ -2878,24 +2884,32 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_/* Shift one or two slots as needed */ sge =sk_msg_elem_cpy (msg, new); + sge_copy =test_bit (new, msg->sg.copy);sg_unmark_end (&sge); nsge =sk_msg_elem_cpy (msg, i); + nsge_copy =test_bit (i, msg->sg.copy);if (rsge.length) {sk_msg_iter_var_next (i); nnsge =sk_msg_elem_cpy (msg, i); + nnsge_copy =test_bit (i, msg->sg.copy);sk_msg_iter_next (msg, end); }while (i != msg->sg.end) { msg->sg.data[i] = sge; +__assign_bit (i, msg->sg.copy, sge_copy); sge = nsge; + sge_copy = nsge_copy;sk_msg_iter_var_next (i);if (rsge.length) { nsge = nnsge; + nsge_copy = nnsge_copy; nnsge =sk_msg_elem_cpy (msg, i); + nnsge_copy =test_bit (i, msg->sg.copy); }else { nsge =sk_msg_elem_cpy (msg, i); + nsge_copy =test_bit (i, msg->sg.copy); } }
@@ -2909,6 +2923,7 @@ place_new:get_page (sg_page (&rsge));sk_msg_iter_var_next (new); msg->sg.data[new] = rsge; +__assign_bit (new, msg->sg.copy, rsge_copy); }sk_msg_reset_curr (msg);
@@ -2936,25 +2951,33 @@ static void sk_msg_shift_left(struct sk_ prev = i;sk_msg_iter_var_next (i); msg->sg.data[prev] = msg->sg.data[i]; +sk_msg_sg_copy_assign (msg, prev, msg, i); }while (i != msg->sg.end);sk_msg_iter_prev (msg, end); +__clear_bit (msg->sg.end, msg->sg.copy); }static void sk_msg_shift_right (struct sk_msg *msg,int i) {struct scatterlist tmp, sge; +bool tmp_copy, sge_copy;sk_msg_iter_next (msg, end); sge =sk_msg_elem_cpy (msg, i); + sge_copy =test_bit (i, msg->sg.copy);sk_msg_iter_var_next (i); tmp =sk_msg_elem_cpy (msg, i); + tmp_copy =test_bit (i, msg->sg.copy);while (i != msg->sg.end) { msg->sg.data[i] = sge; +__assign_bit (i, msg->sg.copy, sge_copy);sk_msg_iter_var_next (i); sge = tmp; + sge_copy = tmp_copy; tmp =sk_msg_elem_cpy (msg, i); + tmp_copy =test_bit (i, msg->sg.copy); } }
@@ -3014,6 +3037,8 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_mstruct scatterlist *nsge, *sge =sk_msg_elem (msg, i);int a = start - offset;int b = sge->length - pop - a; +u32 sge_i = i; +bool sge_copy =test_bit (i, msg->sg.copy);sk_msg_iter_var_next (i);
@@ -3026,6 +3051,7 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg_set_page (nsge,sg_page (sge), b, sge->offset + pop + a); +__assign_bit (i, msg->sg.copy, sge_copy); }else {struct page *page, *orig;u8 *to, *from;
@@ -3042,6 +3068,7 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_mmemcpy (to, from, a);memcpy (to + a, from + a + pop, b);sg_set_page (sge, page, a + b,0 ); +__clear_bit (sge_i, msg->sg.copy);put_page (orig); } pop =0 ;
net/core/skmsg.c +2 -0
@@ -66,6 +66,7 @@ int sk_msg_alloc(struct sock *sk, struct sge = &msg->sg.data[msg->sg.end];sg_unmark_end (sge);sg_set_page (sge, pfrag->page, use, orig_offset); +__clear_bit (msg->sg.end, msg->sg.copy);get_page (pfrag->page);sk_msg_iter_next (msg, end); }
@@ -186,6 +187,7 @@ static int sk_msg_free_elem(struct socksk_mem_uncharge (sk, len);put_page (sg_page (sge)); } +__clear_bit (i, msg->sg.copy);memset (sge,0 ,sizeof (*sge));return len; }
net/tls/tls_sw.c +4 -0
@@ -623,6 +623,7 @@ static int tls_split_open_record(structstruct scatterlist *sge, *osge, *nsge;u32 orig_size = msg_opl->sg.size;struct scatterlist tmp = { }; +u32 tmp_i =0 ;struct sk_msg *msg_npl;struct tls_rec *new;int ret;
@@ -644,6 +645,7 @@ static int tls_split_open_record(structif (sge->length > apply) {u32 len = sge->length - apply; + tmp_i = i;get_page (sg_page (sge));sg_set_page (&tmp,sg_page (sge), len, sge->offset + apply);
@@ -675,6 +677,7 @@ static int tls_split_open_record(struct nsge =sk_msg_elem (msg_npl, j);if (tmp.length) {memcpy (nsge, &tmp,sizeof (*nsge)); +sk_msg_sg_copy_assign (msg_npl, j, msg_opl, tmp_i);sk_msg_iter_var_next (j); nsge =sk_msg_elem (msg_npl, j); }
@@ -682,6 +685,7 @@ static int tls_split_open_record(struct osge =sk_msg_elem (msg_opl, i);while (osge->length) {memcpy (nsge, osge,sizeof (*nsge)); +sk_msg_sg_copy_assign (msg_npl, j, msg_opl, i);sg_unmark_end (nsge);sk_msg_iter_var_next (i);sk_msg_iter_var_next (j);
Greg Kroah-Hartman
maintainerPATCH 124/175 apparmor: mediate the implicit connect of TCP fast open sendmsg
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit 4d587cd8a72155089a627130bbd4716ec0856e21 upstream.
sendmsg()/sendto() with MSG_FASTOPEN is a combination of connect(2) and write(2): it opens the connection in the SYN. apparmor_socket_sendmsg() only checks AA_MAY_SEND, so a profile that grants send but denies connect lets a confined task open an outbound TCP/MPTCP connection that connect(2) would have refused, bypassing connect mediation.
Mediate the implicit connect when MSG_FASTOPEN is set and a destination is supplied. Add it to apparmor_socket_sendmsg() (not the shared aa_sock_msg_perm() helper, which recvmsg also uses) and call aa_sk_perm() directly, mirroring the selinux and tomoyo fixes. sk_is_tcp() does not cover MPTCP fast open, so the SOCK_STREAM/IPPROTO_MPTCP arm is explicit.
--- security/apparmor/lsm.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
security/apparmor/lsm.c +15 -1
@@ -1033,7 +1033,21 @@ static int aa_sock_msg_perm(const char *static int apparmor_socket_sendmsg (struct socket *sock,struct msghdr *msg,int size) { -return aa_sock_msg_perm (OP_SENDMSG ,AA_MAY_SEND , sock, msg, size); +int error =aa_sock_msg_perm (OP_SENDMSG ,AA_MAY_SEND , sock, msg, size); + +if (error) +return error; + +/* TCP fast open carries connect() semantics in sendmsg(); mediate +* the implicit connect so it cannot bypass the connect permission. +*/ +if ((msg->msg_flags &MSG_FASTOPEN ) && msg->msg_name && + (sk_is_tcp (sock->sk) || + (sk_is_inet (sock->sk) && sock->sk->sk_type ==SOCK_STREAM && + sock->sk->sk_protocol ==IPPROTO_MPTCP ))) + error =aa_sk_perm (OP_CONNECT ,AA_MAY_CONNECT , sock->sk); + +return error; }/**
Greg Kroah-Hartman
maintainerPATCH 125/175 apparmor: fix use-after-free in rawdata dedup loop
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruslan Valiyev <[email protected]>
commit 6f060496d03e4dc560a40f73770bd08335cb7a27 upstream.
aa_replace_profiles() walks ns->rawdata_list to dedup the incoming policy blob against entries already attached to existing profiles. Per the kernel-doc on struct aa_loaddata, list membership does not hold a reference: profiles hold pcount, and when the last pcount drops, do_ploaddata_rmfs() is queued on a workqueue that takes ns->lock and removes the entry. Between dropping the last pcount and the workqueue running, an entry remains on the list with pcount == 0.
aa_get_profile_loaddata() is an unconditional kref_get() on pcount, so when the dedup loop hits such an entry, refcount hardening reports
refcount_t: addition on 0; use-after-free.
inside aa_replace_profiles(), and the poisoned counter then trips "saturated" and "underflow" warnings on the subsequent uses of the same loaddata.
Before commit a0b7091c4de4 ("apparmor: fix race on rawdata dereference") the dedup path used a get_unless_zero-style helper on a single counter, so the existing "if (tmp)" guard was meaningful. The split-refcount refactor introduced aa_get_profile_loaddata(), which has plain kref_get() semantics, and the guard quietly became a no-op.
Introduce aa_get_profile_loaddata_not0(), matching the existing _not0 convention used by aa_get_profile_not0(), and use it for the rawdata_list dedup lookup so dying entries are skipped.
Reproduced on x86_64 with v7.1-rc5 in QEMU+KVM running Ubuntu 24.04 + stress-ng 0.17.06:
stress-ng --apparmor 1 --klog-check --timeout 60s
Without this patch the three refcount_t warnings fire within a few seconds. With it the same 60 s run is clean. Coverage is a smoke-test only; a longer soak with CONFIG_KASAN, CONFIG_KCSAN and CONFIG_PROVE_LOCKING would be welcome from anyone with the cycles.
--- security/apparmor/include/policy_unpack.h | 19 +++++++++++++++++++ security/apparmor/policy.c | 8 ++++++-- 2 files changed, 25 insertions(+), 2 deletions(-)
security/apparmor/include/policy_unpack.h +19 -0
@@ -163,6 +163,25 @@ aa_get_profile_loaddata(struct aa_loaddareturn data; } +/** +* aa_get_profile_loaddata_not0 - get a profile reference count if not zero +* @data: reference to get a count on +* +* Like aa_get_profile_loaddata(), but safe to call on an entry that may +* be on a list (e.g. ns->rawdata_list) where the last pcount has already +* dropped and the deferred cleanup has not yet run. +* +* Returns: pointer to reference, or %NULL if @data is NULL or its +* profile refcount has already reached zero. +*/ +static inline struct aa_loaddata * +aa_get_profile_loaddata_not0 (struct aa_loaddata *data) +{ +if (data &&kref_get_unless_zero (&data->pcount)) +return data; +return NULL ; +} +void __aa_loaddata_update (struct aa_loaddata *data,long revision);bool aa_rawdata_eq (struct aa_loaddata *l,struct aa_loaddata *r);void aa_loaddata_kref (struct kref *kref);
security/apparmor/policy.c +6 -2
@@ -1172,8 +1172,12 @@ ssize_t aa_replace_profiles(struct aa_nsif (aa_rawdata_eq (rawdata_ent, udata)) {struct aa_loaddata *tmp; - tmp =aa_get_profile_loaddata (rawdata_ent); -/* check we didn't fail the race */ +/* +* Entries remain on rawdata_list with +* pcount == 0 until do_ploaddata_rmfs() +* runs; only take a live profile ref. +*/ + tmp =aa_get_profile_loaddata_not0 (rawdata_ent);if (tmp) {aa_put_profile_loaddata (udata); udata = tmp;
Greg Kroah-Hartman
maintainerPATCH 126/175 NTB: epf: Avoid pci_iounmap() with offset when PEER_SPAD and CONFIG share BAR
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Koichiro Den <[email protected]>
commit d876153680e3d721d385e554def919bce3d18c74 upstream.
When BAR_PEER_SPAD and BAR_CONFIG share one PCI BAR, the module teardown path ends up calling pci_iounmap() on the same iomem with some offset, which is unnecessary and triggers a kernel warning like the following:
Trying to vunmap() nonexistent vm area (0000000069a5ffe8)
WARNING: mm/vmalloc.c:3470 at vunmap+0x58/0x68, CPU#5: modprobe/2937 [...] Call trace: vunmap+0x58/0x68 (P) iounmap+0x34/0x48 pci_iounmap+0x2c/0x40 ntb_epf_pci_remove+0x44/0x80 [ntb_hw_epf] pci_device_remove+0x48/0xf8 device_remove+0x50/0x88 device_release_driver_internal+0x1c8/0x228 driver_detach+0x50/0xb0 bus_remove_driver+0x74/0x100 driver_unregister+0x34/0x68 pci_unregister_driver+0x34/0xa0 ntb_epf_pci_driver_exit+0x14/0xfe0 [ntb_hw_epf] [...]
Fix it by unmapping only when PEER_SPAD and CONFIG use difference bars.
--- drivers/ntb/hw/epf/ntb_hw_epf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/ntb/hw/epf/ntb_hw_epf.c +2 -1
@@ -646,7 +646,8 @@ static void ntb_epf_deinit_pci(struct ntstruct pci_dev *pdev = ndev->ntb.pdev;pci_iounmap (pdev, ndev->ctrl_reg); -pci_iounmap (pdev, ndev->peer_spad_reg); +if (ndev->barno_map[BAR_PEER_SPAD ] != ndev->barno_map[BAR_CONFIG ]) +pci_iounmap (pdev, ndev->peer_spad_reg);pci_iounmap (pdev, ndev->db_reg);pci_release_regions (pdev);
Greg Kroah-Hartman
maintainerPATCH 127/175 fbdev: fix use-after-free in store_modes()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Bridges <[email protected]>
commit 2c1c805c65fb7dc7524e20376d6987721e73a0b1 upstream.
store_modes() replaces a framebuffer's modelist with modes from userspace. On success it frees the old modelist with fb_destroy_modelist(). Two fields still point into that freed list.
One pointer is fb_display[i].mode, the mode a console is using. fbcon_new_modelist() moves these pointers to the new list. It only does so for consoles still mapped to the framebuffer. An unmapped console is skipped and keeps its stale pointer. Unbinding fbcon, for example, sets con2fb_map[i] to -1 but leaves fb_display[i].mode set. An FBIOPUT_VSCREENINFO ioctl with FB_ACTIVATE_INV_MODE later reaches fbcon_mode_deleted(). That function reads the stale fb_display[i].mode through fb_mode_is_equal(). The read is a use-after-free.
The other pointer is fb_info->mode, the current mode. It is set through the mode sysfs attribute. store_modes() does not update fb_info->mode, so it is left pointing into the freed list. show_mode(), the attribute's read handler, dereferences the stale fb_info->mode through mode_string(). The read is a use-after-free.
Clear both pointers before freeing the list. Commit a1f305893074 ("fbcon:
Set fb_display[i]->mode to NULL when the mode is released") added the helper fbcon_delete_modelist(). It clears every fb_display[i].mode that points into a given list. So far it is called only from the unregister path. Call it from store_modes() too, and set fb_info->mode to NULL.
--- drivers/video/fbdev/core/fbsysfs.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-)
drivers/video/fbdev/core/fbsysfs.c +9 -1
@@ -11,6 +11,7 @@#include <linux/major.h> #include "fb_internal.h" +#include "fbcon.h" #define FB_SYSFS_FLAG_ATTR 1
@@ -113,8 +114,15 @@ static ssize_t store_modes(struct deviceif (fb_new_modelist (fb_info)) {fb_destroy_modelist (&fb_info->modelist);list_splice (&old_list, &fb_info->modelist); - }else + }else { +/* +* fb_display[i].mode and fb_info->mode both point into the old +* list. Clear them before it is freed. +*/ +fbcon_delete_modelist (&old_list); + fb_info->mode =NULL ;fb_destroy_modelist (&old_list); + }unlock_fb_info (fb_info);console_unlock ();
Greg Kroah-Hartman
maintainerPATCH 128/175 err.h: use __always_inline on all error pointer helpers
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
commit 94bfc7f3b0c7c33331ba4ff6cc64ff309dfcbce8 upstream.
While testing randconfig builds on s390, I came across a link failure with CONFIG_DMA_SHARED_BUFFER disabled:
ERROR: modpost: "dma_buf_put" [drivers/iommu/iommufd/iommufd.ko] undefined!
The problem here is that IS_ERR() is not inlined and dead code elimination fails as a consequence.
The err.h helpers all turn into a trivial assignment of a bit mask and should never result in a function call, so force them to always be inline. This should generally result in better object code aside from avoiding the link failure above.
--- include/linux/err.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
include/linux/err.h +6 -6
@@ -36,7 +36,7 @@* * Return: A pointer with @error encoded within its value. */ -static inline void *__must_check ERR_PTR (long error) +static __always_inline void * __must_check ERR_PTR(long error) {return (void *) error; }
@@ -46,7 +46,7 @@ static inline void * __must_check ERR_PT* @ptr: An error pointer. * Return: The error code within @ptr. */ -static inline long __must_check PTR_ERR (__force const void *ptr) +static __always_inline long __must_check PTR_ERR (__force const void *ptr) {return (long ) ptr; }
@@ -56,7 +56,7 @@ static inline long __must_check PTR_ERR(* @ptr: The pointer to check. * Return: true if @ptr is an error pointer, false otherwise. */ -static inline bool __must_check IS_ERR (__force const void *ptr) +static __always_inline bool __must_check IS_ERR(__force const void *ptr) {return IS_ERR_VALUE ((unsigned long )ptr); }
@@ -67,7 +67,7 @@ static inline bool __must_check IS_ERR(_* * Like IS_ERR(), but also returns true for a null pointer. */ -static inline bool __must_check IS_ERR_OR_NULL (__force const void *ptr) +static __always_inline bool __must_check IS_ERR_OR_NULL(__force const void *ptr) {return unlikely (!ptr) ||IS_ERR_VALUE ((unsigned long )ptr); }
@@ -79,7 +79,7 @@ static inline bool __must_check IS_ERR_O* Explicitly cast an error-valued pointer to another pointer type in such a * way as to make it clear that's what's going on. */ -static inline void *__must_check ERR_CAST (__force const void *ptr) +static __always_inline void * __must_check ERR_CAST(__force const void *ptr) {/* cast away the const */ return (void *) ptr;
@@ -102,7 +102,7 @@ static inline void * __must_check ERR_CA* * Return: The error code within @ptr if it is an error pointer; 0 otherwise. */ -static inline int __must_check PTR_ERR_OR_ZERO (__force const void *ptr) +static __always_inline int __must_check PTR_ERR_OR_ZERO(__force const void *ptr) {if (IS_ERR (ptr))return PTR_ERR (ptr);
Greg Kroah-Hartman
maintainerPATCH 129/175 KEYS: fix overflow in keyctl_pkey_params_get_2()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jarkko Sakkinen <[email protected]>
commit cb481e59ea6cae3b7796ac1d7a22b6b24c3f3c0b upstream.
The length for the internal output buffer is calculated incorrectly, which can result overflow when a too small buffer is provided.
Fix the bug by allocating internal output with the size of the maximum length of the cryptographic primitive instead of caller provided size.
--- security/keys/keyctl_pkey.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
security/keys/keyctl_pkey.c +8 -1
@@ -138,28 +138,35 @@ static int keyctl_pkey_params_get_2(consif (uparams.in_len > info.max_dec_size || uparams.out_len > info.max_enc_size)return -EINVAL ; + + params->out_len = info.max_enc_size;break ;case KEYCTL_PKEY_DECRYPT :if (uparams.in_len > info.max_enc_size || uparams.out_len > info.max_dec_size)return -EINVAL ; + + params->out_len = info.max_dec_size;break ;case KEYCTL_PKEY_SIGN :if (uparams.in_len > info.max_data_size || uparams.out_len > info.max_sig_size)return -EINVAL ; + + params->out_len = info.max_sig_size;break ;case KEYCTL_PKEY_VERIFY :if (uparams.in_len > info.max_data_size || uparams.in2_len > info.max_sig_size)return -EINVAL ; + + params->out_len = info.max_sig_size;break ;default :BUG (); } params->in_len = uparams.in_len; - params->out_len = uparams.out_len;/* Note: same as in2_len */ return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 130/175 keys: Pin request_key_auth payload in instantiate paths
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shaomin Chen <[email protected]>
commit fd15b457a86939c38aa12116adabd8ff686c5e51 upstream.
A: request_key() B: KEYCTL_INSTANTIATE_IOV
================ =========================
create auth key
store rka in auth key
wait for helper
get auth key
load rka from auth key
copy user payload
sleep on #PF
helper completed
detach and free rka
destroy auth key
wake up
use rka->target_key
**USE-AFTER-FREE**Give request_key_auth payloads a refcount. Take a payload reference while authkey->sem stabilizes the payload and revocation state. Hold that reference across the instantiate and reject paths. Drop the auth key owning reference from revoke and destroy.
[jarkko: Replaced the first two paragraphs of text with an actual
concurrency scenario.]
--- include/keys/request_key_auth-type.h | 2 ++ security/keys/internal.h | 2 ++ security/keys/keyctl.c | 24 ++++++++++++++++++------ security/keys/request_key_auth.c | 33 +++++++++++++++++++++++++++++++-- 4 files changed, 53 insertions(+), 8 deletions(-)
include/keys/request_key_auth-type.h +2 -0
@@ -9,12 +9,14 @@#define _KEYS_REQUEST_KEY_AUTH_TYPE_H#include <linux/key.h> +#include <linux/refcount.h> /* * Authorisation record for request_key(). */ struct request_key_auth {struct rcu_head rcu; +refcount_t usage;struct key *target_key;struct key *dest_keyring;const struct cred *cred;
security/keys/internal.h +2 -0
@@ -215,6 +215,8 @@ extern struct key *request_key_auth_new(const void *callout_info, size_t callout_len, struct key *dest_keyring); +struct request_key_auth *request_key_auth_get (struct key *authkey); +void request_key_auth_put (struct request_key_auth *rka);extern struct key *key_get_instantiation_authkey (key_serial_t target_id);
security/keys/keyctl.c +18 -6
@@ -1196,9 +1196,13 @@ static long keyctl_instantiate_key_commoif (!instkey) goto error; - rka = instkey->payload.data[0 ]; -if (rka->target_key->serial != id) + rka =request_key_auth_get (instkey); +if (!rka) { + ret = -EKEYREVOKED ; goto error; + } +if (rka->target_key->serial != id) + goto error_put_rka;/* pull the payload in if one was supplied */ payload =NULL ;
@@ -1207,7 +1211,7 @@ static long keyctl_instantiate_key_commo ret = -ENOMEM ; payload =kvmalloc (plen,GFP_KERNEL );if (!payload) - goto error; + goto error_put_rka; ret = -EFAULT ;if (!copy_from_iter_full (payload, plen, from))
@@ -1233,6 +1237,8 @@ static long keyctl_instantiate_key_commo error2:kvfree_sensitive (payload, plen); +error_put_rka: +request_key_auth_put (rka); error:return ret; }
@@ -1358,15 +1364,19 @@ long keyctl_reject_key(key_serial_t id,if (!instkey) goto error; - rka = instkey->payload.data[0 ]; -if (rka->target_key->serial != id) + rka =request_key_auth_get (instkey); +if (!rka) { + ret = -EKEYREVOKED ; goto error; + } +if (rka->target_key->serial != id) + goto error_put_rka;/* find the destination keyring if present (which must also be * writable) */ ret =get_instantiation_keyring (ringid, rka, &dest_keyring);if (ret <0 ) - goto error; + goto error_put_rka;/* instantiate the key and link it into a keyring */ ret = key_reject_and_link(rka->target_key, timeout, error,
@@ -1379,6 +1389,8 @@ long keyctl_reject_key(key_serial_t id,if (ret ==0 )keyctl_change_reqkey_auth (NULL ); +error_put_rka: +request_key_auth_put (rka); error:return ret; }
security/keys/request_key_auth.c +31 -2
@@ -23,6 +23,7 @@ static void request_key_auth_describe(costatic void request_key_auth_revoke (struct key *);static void request_key_auth_destroy (struct key *);static long request_key_auth_read (const struct key *,char *,size_t ); +static void request_key_auth_rcu_disposal (struct rcu_head *);/* * The request-key authorisation key type definition.
@@ -116,6 +117,31 @@ static void free_request_key_auth(struct }/* +* Take a reference to the request-key authorisation payload so callers can +* drop authkey->sem before doing operations that may sleep. +*/ +struct request_key_auth *request_key_auth_get (struct key *authkey) +{ +struct request_key_auth *rka; + +down_read (&authkey->sem); + rka =dereference_key_locked (authkey); +if (rka && !test_bit (KEY_FLAG_REVOKED , &authkey->flags)) +refcount_inc (&rka->usage); +else + rka =NULL ; +up_read (&authkey->sem); + +return rka; +} + +void request_key_auth_put (struct request_key_auth *rka) +{ +if (rka &&refcount_dec_and_test (&rka->usage)) +call_rcu (&rka->rcu, request_key_auth_rcu_disposal); +} + +/* * Dispose of the request_key_auth record under RCU conditions */ static void request_key_auth_rcu_disposal (struct rcu_head *rcu)
@@ -136,8 +162,10 @@ static void request_key_auth_revoke(strustruct request_key_auth *rka =dereference_key_locked (key);kenter ("{%d}" , key->serial); +if (!rka) +return ;rcu_assign_keypointer (key,NULL ); -call_rcu (&rka->rcu, request_key_auth_rcu_disposal); +request_key_auth_put (rka); }/*
@@ -150,7 +178,7 @@ static void request_key_auth_destroy(strkenter ("{%d}" , key->serial);if (rka) {rcu_assign_keypointer (key,NULL ); -call_rcu (&rka->rcu, request_key_auth_rcu_disposal); +request_key_auth_put (rka); } }
@@ -174,6 +202,7 @@ struct key *request_key_auth_new(struct rka =kzalloc (sizeof (*rka),GFP_KERNEL );if (!rka) goto error; +refcount_set (&rka->usage,1 ); rka->callout_info =kmemdup (callout_info, callout_len,GFP_KERNEL );if (!rka->callout_info) goto error_free_rka;
Greg Kroah-Hartman
maintainerPATCH 131/175 wifi: mt76: mt76x2u: Add support for ELECOM WDC-867SU3S
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zenm Chen <[email protected]>
commit f4ce0664e9f0387873b181777891741c33e19465 upstream.
Add the ID 056e:400a to the table to support an additional MT7612U
adapter: ELECOM WDC-867SU3S.
Compile tested only.
--- drivers/net/wireless/mediatek/mt76/mt76x2/usb.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/mediatek/mt76/mt76x2/usb.c +1 -0
@@ -16,6 +16,7 @@ static const struct usb_device_id mt76x2 { USB_DEVICE(0x0e8d, 0x7612) }, /* Aukey USBAC1200 - Alfa AWUS036ACM */ { USB_DEVICE(0x057c, 0x8503) }, /* Avm FRITZ!WLAN AC860 */ { USB_DEVICE(0x7392, 0xb711) }, /* Edimax EW 7722 UAC */ + { USB_DEVICE(0x056e, 0x400a) }, /* ELECOM WDC-867SU3S */ { USB_DEVICE(0x0e8d, 0x7632) }, /* HC-M7662BU1 */ { USB_DEVICE(0x0471, 0x2126) }, /* LiteOn WN4516R module, nonstandard USB connector */ { USB_DEVICE(0x0471, 0x7600) }, /* LiteOn WN4519R module, nonstandard USB connector */
Greg Kroah-Hartman
maintainerPATCH 132/175 wifi: ath11k: fix warning when unbinding
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jose Ignacio Tornos Martinez <[email protected]>
commit 8b7a26b6681922a38cd5a7829ace61f8e54df9b7 upstream.
If there is an error during some initialization related to firmware, the buffers dp->tx_ring[i].tx_status are released.
However this is released again when the device is unbinded (ath11k_pci), and we get:
WARNING: CPU: 0 PID: 6231 at mm/slub.c:4368 free_large_kmalloc+0x57/0x90 Call Trace:
free_large_kmallocath11k_dp_freeath11k_core_deinitath11k_pci_remove
...
The issue is always reproducible from a VM because the MSI addressing initialization is failing.
In order to fix the issue, just set the buffers to NULL after releasing in order to avoid the double free.
--- drivers/net/wireless/ath/ath11k/dp.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/wireless/ath/ath11k/dp.c +1 -0
@@ -1039,6 +1039,7 @@ void ath11k_dp_free(struct ath11k_base *idr_destroy (&dp->tx_ring[i].txbuf_idr);spin_unlock_bh (&dp->tx_ring[i].tx_idr_lock);kfree (dp->tx_ring[i].tx_status); + dp->tx_ring[i].tx_status =NULL ; }/* Deinit any SOC level resource */
Greg Kroah-Hartman
maintainerPATCH 133/175 wifi: rtlwifi: rtl8821ae: Fix C2H bit location in RX descriptor
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bitterblue Smith <[email protected]>
commit 83d38df6929118c3f996b9e3351c2d5014073d87 upstream.
Bit 28 of double word 2 in the RX descriptor indicates if the packet is a normal 802.11 frame, or a message from the wifi firmware to the driver (Card 2 Host).
Commit f5678bfe1cdc ("rtlwifi: rtl8821ae: Replace local bit manipulation macros") mistakenly made the driver look for this bit in double word 1, causing packet loss and Bluetooth coexistence problems.
--- drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/realtek/rtlwifi/rtl8821ae/trx.h +1 -1
@@ -291,7 +291,7 @@ static inline int get_rx_desc_paggr(__lestatic inline int get_rx_status_desc_rpt_sel (__le32 *__pdesc) { -return le32_get_bits (*(__pdesc +1 ),BIT (28 )); +return le32_get_bits (*(__pdesc +2 ),BIT (28 )); }static inline int get_rx_desc_rxmcs (__le32 *__pdesc)
Greg Kroah-Hartman
maintainerPATCH 134/175 wifi: rtw88: increase TX report timeout to fix race condition
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luka Gejak <[email protected]>
commit c80788f7c5aed8d420366b821f867a8a353d83a5 upstream.
The driver expects the firmware to report TX status within 500ms. However, a timeout can be triggered when the hardware performs background scans while under TX load. During these scans, the firmware stays off-channel for periods exceeding 500ms, delaying the delivery of TX reports back to the driver.
When this occurs, the purge timer fires prematurely and drops the tracking skbs from the queue. This results in the host stack interpreting the missing status as packet loss, leading to TCP window collapse. In testing with iperf3, this causes throughput to drop from ~90 Mbps to near-zero for approximately 2 seconds until the connection recovers.
Increase RTW_TX_PROBE_TIMEOUT to 2500ms for RTL8723DU. This duration is sufficient to accommodate off-channel dwell time during full background scans, ensuring the purge timer only trips during genuine firmware lockups and preventing unnecessary TCP retransmission cycles.
--- drivers/net/wireless/realtek/rtw88/tx.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/net/wireless/realtek/rtw88/tx.c +6 -1
@@ -190,6 +190,7 @@ void rtw_tx_report_purge_timer(struct tivoid rtw_tx_report_enqueue (struct rtw_dev *rtwdev,struct sk_buff *skb,u8 sn) {struct rtw_tx_report *tx_report = &rtwdev->tx_report; +unsigned long timeout =RTW_TX_PROBE_TIMEOUT ;unsigned long flags;u8 *drv_data;
@@ -201,7 +202,11 @@ void rtw_tx_report_enqueue(struct rtw_de__skb_queue_tail (&tx_report->queue, skb);spin_unlock_irqrestore (&tx_report->q_lock, flags); -mod_timer (&tx_report->purge_timer, jiffies +RTW_TX_PROBE_TIMEOUT ); +if (rtwdev->chip->id ==RTW_CHIP_TYPE_8723D && + rtwdev->hci.type ==RTW_HCI_TYPE_USB ) + timeout =msecs_to_jiffies (2500 ); + +mod_timer (&tx_report->purge_timer, jiffies + timeout); }EXPORT_SYMBOL (rtw_tx_report_enqueue);
Greg Kroah-Hartman
maintainerPATCH 135/175 wifi: rtw88: usb: fix memory leaks on USB write failures
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luka Gejak <[email protected]>
commit 6b964941bbfe6e0f18b1a5e008486dbb62df440a upstream.
When rtw_usb_write_port() fails to submit a USB Request Block (URB) (e.g., due to device disconnect or ENOMEM), the completion callback is never executed.
Currently, the driver ignores the return value of rtw_usb_write_port() in rtw_usb_write_data() and rtw_usb_tx_agg_skb(). Because these functions rely on the completion callback to free the socket buffers (skbs) and the transaction control block (txcb), a submission failure results in:
1. A memory leak of the allocated skb in rtw_usb_write_data().
2. A memory leak of the txcb structure and all aggregated skbs in rtw_usb_tx_agg_skb().
Fix this by checking the return value of rtw_usb_write_port(). If it fails, explicitly free the skb in rtw_usb_write_data(), and properly purge the tx_ack_queue and free the txcb in rtw_usb_tx_agg_skb().
The issue was discovered in practice during device disconnect/reconnect scenarios and memory pressure conditions. Tested by verifying normal TX operation continues after the fix without regressions.
--- drivers/net/wireless/realtek/rtw88/usb.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/net/wireless/realtek/rtw88/usb.c +11 -2
@@ -339,6 +339,7 @@ static bool rtw_usb_tx_agg_skb(struct rtint agg_num =0 ;unsigned int align_next =0 ;u8 qsel; +int ret;if (skb_queue_empty (list))return false;
@@ -394,7 +395,13 @@ queue: tx_desc = (struct rtw_tx_desc *)skb_head->data; qsel =le32_get_bits (tx_desc->w1,RTW_TX_DESC_W1_QSEL ); -rtw_usb_write_port (rtwdev, qsel, skb_head, rtw_usb_write_port_tx_complete, txcb); + ret =rtw_usb_write_port (rtwdev, qsel, skb_head, + rtw_usb_write_port_tx_complete, txcb); +if (ret) { +ieee80211_purge_tx_queue (rtwdev->hw, &txcb->tx_ack_queue); +kfree (txcb); +return false; + }return true; }
@@ -458,8 +465,10 @@ static int rtw_usb_write_data(struct rtw ret =rtw_usb_write_port (rtwdev, qsel, skb, rtw_usb_write_port_complete, skb); -if (unlikely (ret)) +if (unlikely (ret)) {rtw_err (rtwdev,"failed to do USB write, ret=%d\n" , ret); +dev_kfree_skb_any (skb); + }return ret; }
Greg Kroah-Hartman
maintainerPATCH 136/175 wifi: iwlwifi: mvm: fix race condition in PTP removal
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junjie Cao <[email protected]>
commit 65150c9cc3e06ab54bc4e8134a47f6f5d095a4e3 upstream.
iwl_mvm_ptp_remove() calls cancel_delayed_work_sync() only after ptp_clock_unregister() and clearing ptp_data state (ptp_clock, ptp_clock_info, last_gp2).
This creates a race where the delayed work iwl_mvm_ptp_work() can execute between ptp_clock_unregister() and cancel_delayed_work_sync(), observing partially cleared PTP state.
Move cancel_delayed_work_sync() before ptp_clock_unregister() to ensure the delayed work is fully stopped before any PTP cleanup begins.
--- drivers/net/wireless/intel/iwlwifi/mvm/ptp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/intel/iwlwifi/mvm/ptp.c +1 -1
@@ -316,11 +316,11 @@ void iwl_mvm_ptp_remove(struct iwl_mvm * mvm->ptp_data.ptp_clock_info.name, ptp_clock_index(mvm->ptp_data.ptp_clock)); +cancel_delayed_work_sync (&mvm->ptp_data.dwork);ptp_clock_unregister (mvm->ptp_data.ptp_clock); mvm->ptp_data.ptp_clock =NULL ;memset (&mvm->ptp_data.ptp_clock_info,0 ,sizeof (mvm->ptp_data.ptp_clock_info)); mvm->ptp_data.last_gp2 =0 ; -cancel_delayed_work_sync (&mvm->ptp_data.dwork); } }
Greg Kroah-Hartman
maintainerPATCH 137/175 f2fs: validate compress cache inode only when enabled
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wenjie Qi <[email protected]>
commit 5073c66a96a9c23c0c2533ed4ed06e42f9021208 upstream.
F2FS_COMPRESS_INO() uses NM_I(sbi)->max_nid as the synthetic inode number for the compressed page cache inode. That inode only exists when the compress_cache mount option is enabled.
When compress_cache is disabled, max_nid is outside the valid inode range. A corrupted directory entry that points to ino == max_nid should therefore be rejected by f2fs_check_nid_range(). However, is_meta_ino() currently treats F2FS_COMPRESS_INO() as a meta inode unconditionally, so f2fs_iget() bypasses do_read_inode() and its nid range check, and instantiates a fake internal inode instead.
Gate the compressed cache inode case on COMPRESS_CACHE, matching f2fs_init_compress_inode(). With compress_cache disabled, ino == max_nid now follows the normal inode path and is rejected as an out-of-range nid.
--- fs/f2fs/inode.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
fs/f2fs/inode.c +7 -2
@@ -544,8 +544,13 @@ static int do_read_inode(struct inode *istatic bool is_meta_ino (struct f2fs_sb_info *sbi,unsigned int ino) { -return ino ==F2FS_NODE_INO (sbi) || ino ==F2FS_META_INO (sbi) || - ino ==F2FS_COMPRESS_INO (sbi); +if (ino ==F2FS_NODE_INO (sbi) || ino ==F2FS_META_INO (sbi)) +return true; +#ifdef CONFIG_F2FS_FS_COMPRESSION +if (test_opt (sbi,COMPRESS_CACHE ) && ino ==F2FS_COMPRESS_INO (sbi)) +return true; +#endif +return false; }struct inode *f2fs_iget (struct super_block *sb,unsigned long ino)
Greg Kroah-Hartman
maintainerPATCH 138/175 f2fs: fix to round down start offset of fallocate for pin file
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sunmin Jeong <[email protected]>
commit 4275b59673eb60b02eec3997816c83f1f4b909c4 upstream.
Currently, the length of fallocate for pin file is section-aligned to keep allocated sections from being selected as victims of GC. However, for the case that the start offset of fallocate is not aligned in section, the allocated sections can't be fully utilized. It's because a new section is allocated by f2fs_allocate_pinning_section() after using blks_per_sec blocks regardless of the start offset. As a result, several unexpected dirty segments may be created, including blocks assigned to the pinned file.
To address this issue, let's round down the start offset of fallocate to the length of section.
The reproducing scenario is as below
chunk=$(((2<<20)+4096)) # 2MB + 4KB
touch testf2fs_io pinfile set testf2fs_io fallocate 0 0 $chunk testf2fs_io fallocate 0 $chunk $chunk testf2fs_io fallocate 0 $((chunk*2)) $chunk testf2fs_io fiemap 0 $((chunk*3)) test
Fiemap: offset = 0 len = 12288
logical addr. physical addr. length flags
0 0000000000000000 000000068c600000 0000000000400000 00001088 1 0000000000400000 000000003d400000 0000000000001000 00001088 2 0000000000401000 00000003eb200000 0000000000200000 00001088 3 0000000000601000 00000005e4200000 0000000000001000 00001088 4 0000000000602000 0000000605400000 0000000000200000 00001089
--- fs/f2fs/file.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
fs/f2fs/file.c +8 -1
@@ -1826,8 +1826,15 @@ static int f2fs_expand_inode_data(structif (f2fs_is_pinned_file (inode)) {block_t sec_blks =CAP_BLKS_PER_SEC (sbi); -block_t sec_len =roundup (map.m_len, sec_blks); +block_t sec_len; +if (map.m_lblk % sec_blks) { + map.m_lblk =rounddown (map.m_lblk, sec_blks); + map.m_len = pg_end - map.m_lblk; +if (off_end) + map.m_len++; + } + sec_len =roundup (map.m_len, sec_blks); map.m_len = sec_blks; next_alloc: if (has_not_enough_free_secs(sbi, 0,
Greg Kroah-Hartman
maintainerPATCH 139/175 f2fs: validate ACL entry sizes in f2fs_acl_from_disk()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Cen <[email protected]>
commit c4810ada31e80cbe4011467c4f3b1e93f94134f3 upstream.
f2fs_acl_count() only validates the aggregate ACL xattr length. A malformed ACL can still place ACL_USER or ACL_GROUP in a slot that only contains struct f2fs_acl_entry_short bytes, and f2fs_acl_from_disk() then reads entry->e_id before verifying that a full entry fits.
Require a short entry before reading e_tag and e_perm, and require a full entry before reading e_id for ACL_USER and ACL_GROUP. Return -EFSCORRUPTED from these new truncated-entry checks, while keeping the pre-existing -EINVAL paths unchanged.
Validation reproduced this kernel report:
KASAN slab-out-of-bounds in __f2fs_get_acl+0x6fb/0x7e0
RIP: 0033:0x7f4b835ea7aa The buggy address belongs to the object at ffff888114589960 which belongs to the cache kmalloc-8 of size 8 The buggy address is located 0 bytes to the right of allocated 8-byte region [ffff888114589960, ffff888114589968) Read of size 4 Call trace: dump_stack_lvl+0x66/0xa0 (?:?) print_report+0xce/0x630 (?:?) __f2fs_get_acl+0x6fb/0x7e0 (fs/f2fs/acl.c:169) srso_alias_return_thunk+0x5/0xfbef5 (?:?) __virt_addr_valid+0x224/0x430 (?:?) kasan_report+0xe0/0x110 (?:?) __f2fs_get_acl+0x5/0x7e0 (fs/f2fs/acl.c:169) __get_acl+0x281/0x380 (?:?) vfs_get_acl+0x10b/0x190 (?:?) do_get_acl+0x2a/0x410 (?:?) do_get_acl+0x9/0x410 (?:?) do_getxattr+0xe8/0x260 (?:?) filename_getxattr+0xd1/0x140 (?:?) do_getname+0x2d/0x2d0 (?:?) path_getxattrat+0x16c/0x200 (?:?) lock_release+0xc8/0x290 (?:?) cgroup_update_frozen+0x9d/0x320 (?:?) lockdep_hardirqs_on_prepare+0xea/0x1a0 (?:?) trace_hardirqs_on+0x1a/0x170 (?:?) _raw_spin_unlock_irq+0x28/0x50 (?:?) do_syscall_64+0x115/0x6a0 (arch/x86/entry/syscall_64.c:87) entry_SYSCALL_64_after_hwframe+0x77/0x7f (?:?)
--- fs/f2fs/acl.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-)
fs/f2fs/acl.c +16 -2
@@ -46,6 +46,7 @@ static inline int f2fs_acl_count(size_tstatic struct posix_acl *f2fs_acl_from_disk (const char *value,size_t size) {int i, count; +int err = -EINVAL ;struct posix_acl *acl;struct f2fs_acl_header *hdr = (struct f2fs_acl_header *)value;struct f2fs_acl_entry *entry = (struct f2fs_acl_entry *)(hdr +1 );
@@ -69,8 +70,11 @@ static struct posix_acl *f2fs_acl_from_dfor (i =0 ; i < count; i++) { -if ((char *)entry > end) +if (unlikely ((char *)entry + +sizeof (struct f2fs_acl_entry_short ) > end)) { + err = -EFSCORRUPTED ; goto fail; + } acl->a_entries[i].e_tag =le16_to_cpu (entry->e_tag); acl->a_entries[i].e_perm =le16_to_cpu (entry->e_perm);
@@ -85,6 +89,11 @@ static struct posix_acl *f2fs_acl_from_dbreak ;case ACL_USER : +if (unlikely ((char *)entry + +sizeof (struct f2fs_acl_entry ) > end)) { + err = -EFSCORRUPTED ; + goto fail; + } acl->a_entries[i].e_uid =make_kuid (&init_user_ns,le32_to_cpu (entry->e_id));
@@ -92,6 +101,11 @@ static struct posix_acl *f2fs_acl_from_d sizeof(struct f2fs_acl_entry));break ;case ACL_GROUP : +if (unlikely ((char *)entry + +sizeof (struct f2fs_acl_entry ) > end)) { + err = -EFSCORRUPTED ; + goto fail; + } acl->a_entries[i].e_gid =make_kgid (&init_user_ns,le32_to_cpu (entry->e_id));
@@ -107,7 +121,7 @@ static struct posix_acl *f2fs_acl_from_dreturn acl; fail:posix_acl_release (acl); -return ERR_PTR (-EINVAL ); +return ERR_PTR (err); } static void *f2fs_acl_to_disk(struct f2fs_sb_info *sbi,
Greg Kroah-Hartman
maintainerPATCH 140/175 f2fs: fix incorrect FI_NO_EXTENT handling in __destroy_extent_node()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yongpeng Yang <[email protected]>
commit 1f70ddb28a3c71df124da5fa4040c808116d6bb9 upstream.
When __destroy_extent_node() sets the inode flag FI_NO_EXTENT, it does not reset the length of the largest extent to 0 and update the inode folio. Since modifications to the extent tree are disallowed afterward, the cached largest extent may become stale. This can trigger the following error in xfstests generic/388:
F2FS-fs (dm-0): sanity_check_extent_cache: inode (ino=1761) extent info [220057, 57, 6] is incorrect, run fsck to fix
In the f2fs_drop_inode path, __destroy_extent_node() does not need to guarantee that et->node_cnt is 0, because concurrency with writeback is expected in this path, and writeback may update the extent cache.
This patch reverts commit ed78aeebef05 ("f2fs: fix node_cnt race between extent node destroy and writeback"), and remove the unnecessary zero check of et->node_cnt.
--- fs/f2fs/extent_cache.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-)
fs/f2fs/extent_cache.c +7 -12
@@ -87,10 +87,9 @@ static bool __may_extent_tree(struct inoif (!__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;
@@ -603,14 +602,10 @@ static unsigned int __destroy_extent_nodwhile (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); } -f2fs_bug_on (sbi,atomic_read (&et->node_cnt)); -return node_cnt; }
@@ -640,12 +635,12 @@ static void __update_extent_tree_range(swrite_lock (&et->lock); -if (is_inode_flag_set (inode,FI_NO_EXTENT )) { -write_unlock (&et->lock); -return ; - } -if (type ==EX_READ ) { +if (is_inode_flag_set (inode,FI_NO_EXTENT )) { +write_unlock (&et->lock); +return ; + } + prev = et->largest; dei.len =0 ;
Greg Kroah-Hartman
maintainerPATCH 141/175 f2fs: keep atomic write retry from zeroing original data
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wenjie Qi <[email protected]>
commit 6d874b65aadce56ac78f76129dbcfc2599b638f8 upstream.
A partial atomic write reserves a block in the COW inode before reading the original data page for the untouched bytes in that page.
If that read fails, write_begin returns an error but leaves the COW inode entry as NEW_ADDR. A retry of the same partial write then finds the COW entry, treats it as existing COW data, and f2fs_write_begin() zeroes the whole folio because blkaddr is NEW_ADDR.
If the retry is committed, the bytes outside the retried write range are committed as zeroes instead of preserving the original file contents.
Only use the COW inode as the read source when it already has a real data block. If the COW entry is still NEW_ADDR, treat it as a reservation to
reuse: keep reading the old data from the original inode and avoid reserving or accounting the same atomic block again.
--- fs/f2fs/data.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-)
fs/f2fs/data.c +11 -5
@@ -3527,6 +3527,7 @@ static int prepare_atomic_write_begin(stpgoff_t index = page->index;int err =0 ;block_t ori_blk_addr =NULL_ADDR ; +bool cow_has_reserved_block = false;/* If pos is beyond the end of file, reserve a new block in COW inode */ if ((pos &PAGE_MASK ) >=i_size_read (inode))
@@ -3536,9 +3537,11 @@ static int prepare_atomic_write_begin(st err =__find_data_block (cow_inode, index, blk_addr);if (err) {return err; - }else if (*blk_addr !=NULL_ADDR ) { + }else if (__is_valid_data_blkaddr (*blk_addr)) { *use_cow = true;return 0 ; + }else if (*blk_addr ==NEW_ADDR ) { + cow_has_reserved_block = true; }if (is_inode_flag_set (inode,FI_ATOMIC_REPLACE ))
@@ -3551,10 +3554,13 @@ static int prepare_atomic_write_begin(st reserve_block:/* Finally, we should reserve a new block in COW inode for the update */ - err =__reserve_data_block (cow_inode, index, blk_addr, node_changed); -if (err) -return err; -inc_atomic_write_cnt (inode); +if (!cow_has_reserved_block) { + err =__reserve_data_block (cow_inode, index, blk_addr, + node_changed); +if (err) +return err; +inc_atomic_write_cnt (inode); + }if (ori_blk_addr !=NULL_ADDR ) *blk_addr = ori_blk_addr;
Greg Kroah-Hartman
maintainerPATCH 142/175 bpf: use kvfree() for replaced sysctl write buffer
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dawei Feng <[email protected]>
commit 4c21b5927d4364bfe7365f2700da5fea0ed0d004 upstream.
proc_sys_call_handler() allocates its temporary sysctl buffer with kvzalloc() and passes it to __cgroup_bpf_run_filter_sysctl(). Since kvzalloc() may fall back to vmalloc() for large allocations, freeing that buffer with kfree() is wrong and can corrupt memory.
Use kvfree() to safely handle both kmalloc and kvzalloc()/vmalloc allocations.
The bug was first flagged by an experimental analysis tool we are developing for kernel memory-management bugs while analyzing v6.13-rc1. The tool is still under development and is not yet publicly available. Manual inspection confirms that the bug is still present in v7.1-rc5.
Reproduced the bug based on v7.1-rc4 in a QEMU x86_64 guest booted with KASAN and CONFIG_FAILSLAB enabled. To exercise the replacement path, the test tree also included the accompanying fix for the stale ret == 1 check in __cgroup_bpf_run_filter_sysctl(). The reproducer confines failslab injections to the proc_sys_call_handler() range, uses stacktrace-depth=32, and injects fail-nth=1 while writing 8191 bytes to /proc/sys/kernel/domainname from a task in the target cgroup. Under that setup, fail-nth=1 triggered the fault:
BUG: unable to handle page fault for address: ffffeb0200024d48 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: Oops: 0000 SMP KASAN NOPTI CPU: 2 UID: 0 PID: 209 Comm: repro_proc_sys_ Not tainted 7.1.0-rc4-00686-g97625979a5d4 PREEMPT(lazy) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.15.0-1 04/01/2014 RIP: 0010:kfree+0x6e/0x510 ... Call Trace: <TASK> ? __cgroup_bpf_run_filter_sysctl+0x626/0xc30 __cgroup_bpf_run_filter_sysctl+0x74d/0xc30 ? __pfx___cgroup_bpf_run_filter_sysctl+0x10/0x10 ? srso_return_thunk+0x5/0x5f ? __kvmalloc_node_noprof+0x345/0x870 ? proc_sys_call_handler+0x250/0x480 ? srso_return_thunk+0x5/0x5f proc_sys_call_handler+0x3a2/0x480 ? __pfx_proc_sys_call_handler+0x10/0x10 ? srso_return_thunk+0x5/0x5f ? selinux_file_permission+0x39f/0x500 ? srso_return_thunk+0x5/0x5f ? lock_is_held_type+0x9e/0x120 vfs_write+0x98e/0x1000 ... </TASK>
With this fix applied on top of the same test setup, rerunning the reproducer with fail-nth=1 yields no corresponding Oops reports.
--- kernel/bpf/cgroup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/bpf/cgroup.c +1 -1
@@ -1776,7 +1776,7 @@ int __cgroup_bpf_run_filter_sysctl(struckfree (ctx.cur_val);if (ret ==1 && ctx.new_updated) { -kfree (*buf); +kvfree (*buf); *buf = ctx.new_val; *pcount = ctx.new_len; }else {
Greg Kroah-Hartman
maintainerPATCH 143/175 MIPS: DEC: Prevent initial console buffer from landing in XKPHYS
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej W. Rozycki <[email protected]>
commit 7fb13fd35110ebe95eb053faf79d018f51144d85 upstream.
In 64-bit configurations calling the initial console output handler from a kernel thread other than the initial one will result in a situation where the stack has been placed in the XKPHYS 64-bit memory segment and consequently so has been the buffer allocated there that is used as the argument corresponding to the `%s' output conversion specifier for the firmware's printf() entry point.
This 64-bit address will then be truncated by 32-bit firmware, resulting in an attempt to access the wrong memory location, which in turn will cause all kinds of unpredictable behaviour, such as a kernel crash:
Console: colour dummy device 160x64
Calibrating delay loop... 49.36 BogoMIPS (lpj=192512)
pid_max: default: 32768 minimum: 301
CPU 0 Unable to handle kernel paging request at virtual address 000000000203bd00, epc == ffffffffbfc08364, ra == ffffffffbfc08800 Oops[#1]:
CPU: 0 PID: 0 Comm: swapper Not tainted 5.18.0-rc2-00254-gfb649bda6f56-dirty #121
$ 0 : 0000000000000000 0000000000000001 0000000000000023 ffffffff80684ba0
$ 4 : 000000000203bd00 ffffffffbfc0f3b4 ffffffffffffffff 0000000000000073
$ 8 : 0a303d7469000000 0000000000000000 0000000000000073 ffffffffbfc0f473
$12 : 0000000000000002 0000000000000000 ffffffff80684c1c 0000000000000000
$16 : 0000000000000000 ffffffff80596dc9 0000000000000000 ffffffffbfc09240
$20 : ffffffff80684c40 ffffffffbfc0f400 000000000000002d 000000000000002b
$24 : ffffffffffffffbf 000000000203bd00
$28 : ffffffff805f0000 ffffffff80684b58 0000000000000030 ffffffffbfc08800
Hi : 0000000000000000
Lo : 0000000000000aa8
epc : ffffffffbfc08364 0xffffffffbfc08364
ra : ffffffffbfc08800 0xffffffffbfc08800
Status: 140120e2 KX SX UX KERNEL EXL
Cause : 00000008 (ExcCode 02)
BadVA : 000000000203bd00
PrId : 00000430 (R4000SC)
Modules linked in:
Process swapper (pid: 0, threadinfo=(____ptrval____), task=(____ptrval____), tls=0000000000000000)
Stack : 0000000000000000 0000000000000000 0000000000000000 0000004d0000004d
80684cc0806a2a40 80596dc80000004d 8061000000000000 bfc0850c80684c38
0000000000000000 000000000203bd00 0000000000000000 0000000000000000
0000000000000000 00000000bfc0f3b4 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
0000000000000000 0000000000000000 0000000000000000 0000000000000000
0000002500000000 0000000000000000 0000000000000000 802c1a7400000000
0203bd0080596dc8 0203bd4d69000000 6c61632000000018 5f746567646e6172
6c616320625f6d6f 5f736e5f6d6f7266 206361323778302b 303d74696e726320
806a0a38806b0000 806a0a38806b0000 00000000806b0000 80683c58806b0000
...
Call Trace:
Code: a082ffff 03e00008 00601021 <80820000> 00001821 10400005 24840001 80820000 24630001
---[ end trace 0000000000000000 ]---
Kernel panic - not syncing: Fatal exception in interrupt KN04 V2.1k (PC: 0xa0026768, SP: 0x806848e8)
Quoted 1 line
Quoted 1 line
In this case the pointer in $4 was truncated from 0x980000000203bd00 to 0x000000000203bd00.
This may happen when no final console driver has been enabled in the configuration and consequently the initial console continues being used late into bootstrap or with an upcoming change that will switch the zs driver to use a platform device, which in turn will make the console handover happen only after other kernel threads have already been started.
Fix the issue by making the buffer static and initdata, and therefore placed in the CKSEG0 32-bit compatibility segment, observing that the console output handler is called with the console lock held, implying no need for this code to be reentrant. Add an assertion to verify the buffer actually has been placed in a compatibility segment.
--- arch/mips/dec/prom/console.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
arch/mips/dec/prom/console.c +5 -2
@@ -2,8 +2,9 @@/* * DECstation PROM-based early console support. * -* Copyright (C) 2004, 2007 Maciej W. Rozycki +* Copyright (C) 2004, 2007, 2026 Maciej W. Rozycki */ +#include <linux/bug.h> #include <linux/console.h> #include <linux/init.h> #include <linux/kernel.h>
@@ -14,9 +15,11 @@static void __init prom_console_write (struct console *con,const char *s,unsigned int c) { -char buf[81 ]; +static char buf[81 ]__initdata = {0 };unsigned int chunk =sizeof (buf) -1 ; +BUG_ON ((long )buf != (int )(long )buf); +while (c >0 ) {if (chunk > c) chunk = c;
Greg Kroah-Hartman
maintainerPATCH 144/175 exfat: fix potential use-after-free in exfat_find_dir_entry()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 3f5f8ee9917cc2b9076ac533492d8a200edcabb8 upstream.
In exfat_find_dir_entry(), the buffer_head obtained from exfat_get_dentry() is released with brelse(bh) before the fall-through TYPE_EXTEND branch reads the directory entry through ep (which points into bh->b_data):
brelse(bh);
if (entry_type == TYPE_EXTEND) {
...
len = exfat_extract_uni_name(ep, entry_uniname);
...
}After brelse() drops our reference, nothing guarantees that the underlying page backing bh->b_data remains valid for the subsequent exfat_extract_uni_name() read. This is the same pattern fixed in commit fc961522ddbd ("exfat: Fix potential use after free in exfat_load_upcase_table()").
Move brelse(bh) so it runs after ep is no longer dereferenced on each branch.
Confirmed on QEMU x86_64 with CONFIG_KASAN=y + CONFIG_DEBUG_PAGEALLOC=y
+ CONFIG_PAGE_POISONING=y on linux-next, using a crafted exFAT image (long filename with same-hash collisions forcing the TYPE_EXTEND path). With a debug-only invalidate_bdev() inserted between brelse(bh) and the ep read to make the stale-deref window deterministic, the unpatched kernel faults:
BUG: KASAN: use-after-free in exfat_find_dir_entry+0x133b/0x15a0 BUG: unable to handle page fault for address: ffff88801a5fa0c2 Oops: 0000 [#1] SMP DEBUG_PAGEALLOC KASAN NOPTI RIP: 0010:exfat_find_dir_entry+0x1188/0x15a0
With this patch applied, the same instrumented harness completes cleanly under the same sanitizer stack. I have not reproduced a crash on an uninstrumented kernel under ordinary reclaim; the instrumented A/B establishes the lifetime violation and that the patch closes it, not an unaided triggerability claim.
--- fs/exfat/dir.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/exfat/dir.c +3 -1
@@ -1079,12 +1079,12 @@ rewind:continue ; } -brelse (bh);if (entry_type ==TYPE_EXTEND ) {unsigned short entry_uniname[16 ], unichar;if (step !=DIRENT_STEP_NAME || name_len >=MAX_NAME_LENGTH ) { +brelse (bh); step =DIRENT_STEP_FILE ;continue ; }
@@ -1095,6 +1095,7 @@ rewind: uniname +=EXFAT_FILE_NAME_LEN ; len =exfat_extract_uni_name (ep, entry_uniname); +brelse (bh); name_len += len; unichar = *(uniname+len);
@@ -1113,6 +1114,7 @@ rewind:continue ; } +brelse (bh);if (entry_type & (TYPE_CRITICAL_SEC |TYPE_BENIGN_SEC )) {if (step ==DIRENT_STEP_SECD ) {
Greg Kroah-Hartman
maintainerPATCH 145/175 gfs2: fix use-after-free in gfs2_qd_dealloc
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
commit f9c9ec2c319f843b70ecdf939d48b52d189bc081 upstream.
gfs2_qd_dealloc(), called as an RCU callback from gfs2_qd_dispose(), accesses the superblock object sdp through qd->qd_sbd after freeing qd. It does so to decrement sd_quota_count and wake up sd_kill_wait.
However, by the time the RCU callback runs, gfs2_put_super() may have already freed sdp via free_sbd(). This can happen when gfs2_quota_cleanup() is called during unmount: it disposes of quota objects via call_rcu() and then waits on sd_kill_wait with a 60-second timeout. If the timeout expires, or if gfs2_gl_hash_clear() triggers additional qd_put() calls that schedule more RCU callbacks after the wait completes, gfs2_put_super() will proceed to free the superblock while RCU callbacks referencing it are still pending.
Add an rcu_barrier() before free_sbd() in gfs2_put_super() to ensure all pending RCU callbacks (including gfs2_qd_dealloc) have completed before the superblock is freed.
--- fs/gfs2/super.c | 1 + 1 file changed, 1 insertion(+)
fs/gfs2/super.c +1 -0
@@ -652,6 +652,7 @@ restart:gfs2_delete_debugfs_file (sdp);gfs2_sys_fs_del (sdp); +rcu_barrier ();free_sbd (sdp); }
Greg Kroah-Hartman
maintainerPATCH 146/175 hdlc_ppp: sync per-proto timers before freeing hdlc state
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Fan Wu <[email protected]>
commit c78a4e41ab5ead6193ad8a2dd92e8906bae659fa upstream.
Each PPP control protocol (LCP/IPCP/IPV6CP) embedded in struct ppp registers a timer via timer_setup(). That struct ppp is the hdlc->state allocation, which detach_hdlc_protocol() frees with kfree() in both teardown paths: unregister_hdlc_device() and the re-attach inside attach_hdlc_protocol().
The ppp proto never registered a .detach callback, so detach_hdlc_protocol() performs no timer synchronization before the kfree(). The only cancel, timer_delete(&proto->timer) in ppp_cp_event(), is partial (it does not wait for a running callback) and only runs on the ->CLOSED transition; ppp_stop()/ppp_close() do not sync either. A ppp_timer callback already executing (blocked on ppp->lock) survives the kfree and then dereferences proto->state / ppp->lock in freed memory, leading to a use-after-free.
Fix this by adding a .detach helper that calls timer_shutdown_sync() on every per-proto timer. detach_hdlc_protocol() invokes proto->detach(dev) before kfree(hdlc->state), so timer_shutdown_sync()
now runs on both free paths.timer_shutdown_sync() is used instead of timer_delete_sync() because the keepalive path re-arms the timer through add_timer()/mod_timer() and shutdown blocks any re-activation during teardown.
Initialize the per-protocol timers in ppp_ioctl() when the protocol is attached, and remove the now-redundant timer_setup() from ppp_start(), so that the timers are initialized exactly once at attach time and ppp_timer_release() never operates on uninitialized timer_list structures. attach_hdlc_protocol() uses kmalloc() (not kzalloc), so struct ppp's protos[i].timer is uninitialized garbage until the first timer_setup(); without this init-at-attach, attaching the PPP protocol without ever bringing the device up would leave timer_shutdown_sync() operating on uninitialized memory in .detach. Moving the init out of ppp_start() (which only runs on NETDEV_UP) into the attach path makes the initialization unconditional and avoids initializing the same timer_list twice.
This bug was found by static analysis.
--- drivers/net/wan/hdlc_ppp.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/net/wan/hdlc_ppp.c +13 -2
@@ -621,7 +621,6 @@ static void ppp_start(struct net_devicestruct proto *proto = &ppp->protos[i]; proto->dev = dev; -timer_setup (&proto->timer, ppp_timer,0 ); proto->state =CLOSED ; } ppp->protos[IDX_LCP ].pid =PID_LCP ;
@@ -641,6 +640,15 @@ static void ppp_close(struct net_deviceppp_tx_flush (); } +static void ppp_timer_release (struct net_device *dev) +{ +struct ppp *ppp =get_ppp (dev); +int i; + +for (i =0 ; i <IDX_COUNT ; i++) +timer_shutdown_sync (&ppp->protos[i].timer); +} +static struct hdlc_proto proto = { .start = ppp_start, .stop = ppp_stop,
@@ -649,6 +657,7 @@ static struct hdlc_proto proto = { .ioctl = ppp_ioctl, .netif_rx = ppp_rx, .module = THIS_MODULE, + .detach = ppp_timer_release, };static const struct header_ops ppp_header_ops = {
@@ -659,7 +668,7 @@ static int ppp_ioctl(struct net_device * {hdlc_device *hdlc =dev_to_hdlc (dev);struct ppp *ppp; -int result; +int i, result;switch (ifs->type) {case IF_GET_PROTO :
@@ -687,6 +696,8 @@ static int ppp_ioctl(struct net_device *return result; ppp =get_ppp (dev); +for (i =0 ; i <IDX_COUNT ; i++) +timer_setup (&ppp->protos[i].timer, ppp_timer,0 );spin_lock_init (&ppp->lock); ppp->req_timeout =2 ; ppp->cr_retries =10 ;
Greg Kroah-Hartman
maintainerPATCH 147/175 blk-cgroup: fix UAF in __blkcg_rstat_flush()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michal Koutný <[email protected]>
commit 0ab5ee5a1badb58cbb2242617cb01a4972b1f2a2 upstream.
When multiple blkgs in the same blkcg are released concurrently, a use-after-free can occur. The race happens when one blkg's __blkcg_rstat_flush() removes another blkg's iostat entries via llist_del_all(). The second blkg sees an empty list and proceeds to free itself while the first is still iterating over its entries.
Move the flush from __blkg_release() (RCU callback) to blkg_release() (before call_rcu). This ensures the RCU grace period waits for any concurrent flush's rcu_read_lock() section to complete before freeing.
--- block/blk-cgroup.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-)
block/blk-cgroup.c +11 -10
@@ -170,20 +170,10 @@ static void blkg_free(struct blkcg_gq *bstatic void __blkg_release (struct rcu_head *rcu) { struct blkcg_gq *blkg = container_of(rcu, struct blkcg_gq, rcu_head); -struct blkcg *blkcg = blkg->blkcg; -int cpu;#ifdef CONFIG_BLK_CGROUP_PUNT_BIO WARN_ON (!bio_list_empty (&blkg->async_bios));#endif -/* -* Flush all the non-empty percpu lockless lists before releasing -* us, given these stat belongs to us. -* -* blkg_stat_lock is for serializing blkg stat update -*/ -for_each_possible_cpu (cpu) -__blkcg_rstat_flush (blkcg, cpu);/* release the blkcg and parent blkg refs this blkg has been holding */ css_put (&blkg->blkcg->css);
@@ -201,6 +191,17 @@ static void __blkg_release(struct rcu_hestatic void blkg_release (struct percpu_ref *ref) { struct blkcg_gq *blkg = container_of(ref, struct blkcg_gq, refcnt); +struct blkcg *blkcg = blkg->blkcg; +int cpu; + +/* +* Flush all the non-empty percpu lockless lists before releasing +* us, given these stat belongs to us. +* +* blkg_stat_lock is for serializing blkg stat update +*/ +for_each_possible_cpu (cpu) +__blkcg_rstat_flush (blkcg, cpu);call_rcu (&blkg->rcu_head, __blkg_release); }
Greg Kroah-Hartman
maintainerPATCH 148/175 tipc: fix slab-use-after-free Read in tipc_aead_decrypt_done
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Doruk Tan Ozturk <[email protected]>
commit bda3348872a2ef0d19f2df6aa8cb5025adce2f20 upstream.
tipc_aead_decrypt() goes straight from tipc_bearer_hold(b) to crypto_aead_decrypt(req) without taking a reference on the netns, unlike the encrypt path. When crypto_aead_decrypt() is offloaded asynchronously (e.g. the SIMD aead wrapper queuing to cryptd), the cryptd worker runs tipc_aead_decrypt_done() later. If the bearer's netns is torn down in the meantime, cleanup_net() -> tipc_exit_net() -> tipc_crypto_stop() frees the per-netns tipc_crypto, and the completion then reads it:tipc_aead_decrypt_done() dereferences aead->crypto->stats and aead->crypto->net, and tipc_crypto_rcv_complete() dereferences aead->crypto->aead[] and the node table -- reading freed memory.
Decoded KASAN splat (v7.1-rc7, CONFIG_KASAN_INLINE + TIPC + TIPC_CRYPTO):
BUG: KASAN: slab-use-after-free in tipc_aead_decrypt_done (net/tipc/crypto.c:999) Read of size 8 at addr ffff8881056258a8 by task kworker/u16:2/51 Workqueue: events_unbound Call Trace: tipc_aead_decrypt_done (net/tipc/crypto.c:999) process_one_work (kernel/workqueue.c:3314) worker_thread (kernel/workqueue.c:3397 kernel/workqueue.c:3478) kthread (kernel/kthread.c:436) ret_from_fork (arch/x86/kernel/process.c:158) ret_from_fork_asm (arch/x86/entry/entry_64.S:245) Allocated by task 169: __kasan_kmalloc (mm/kasan/common.c:398 mm/kasan/common.c:415) tipc_crypto_start (net/tipc/crypto.c:1502) tipc_init_net (net/tipc/core.c:72) ops_init (net/core/net_namespace.c:137) setup_net (net/core/net_namespace.c:446) copy_net_ns (net/core/net_namespace.c:579) create_new_namespaces (kernel/nsproxy.c:132) __x64_sys_unshare (kernel/fork.c:3316) do_syscall_64 (arch/x86/entry/syscall_64.c:63) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) Freed by task 8: kfree (mm/slub.c:6566) tipc_exit_net (net/tipc/core.c:119) cleanup_net (net/core/net_namespace.c:704) process_one_work (kernel/workqueue.c:3314) kthread (kernel/kthread.c:436)
This is the same class of bug that commit e279024617134 ("net/tipc: fix slab-use-after-free Read in tipc_aead_encrypt_done") fixed for the encrypt side. The encrypt path takes maybe_get_net(aead->crypto->net) before crypto_aead_encrypt() and drops it with put_net() on the synchronous return paths and in tipc_aead_encrypt_done(); the -EINPROGRESS/-EBUSY return keeps the reference for the async callback to release. The decrypt path was left without the equivalent guard.
Mirror the encrypt-side fix on the decrypt path: take a net reference before crypto_aead_decrypt() (failing with -ENODEV and the matching bearer put if it cannot be acquired), keep it across the -EINPROGRESS/-EBUSY async return, and drop it with put_net() on the synchronous success/error return and at the end of tipc_aead_decrypt_done().
Reproduced under KASAN on v7.1-rc7: a UDP bearer with a cluster key is flooded with crafted encrypted frames from an unknown peer (driving the cluster-key decrypt path) while the bearer's netns is repeatedly torn down. The completion must run asynchronously to outlive tipc_crypto_stop(); on x86 the stock aesni gcm(aes) now decrypts synchronously, so the async path was exercised via cryptd offload. The unguarded aead->crypto dereference in tipc_aead_decrypt_done() is the unpatched upstream path; tipc_aead_decrypt() still lacks maybe_get_net(aead->crypto->net), so the completion can outlive the free on any config where crypto_aead_decrypt() goes async.
Found by 0sec automated security-research tooling (https://0sec.ai).
--- net/tipc/crypto.c | 9 +++++++++ 1 file changed, 9 insertions(+)
net/tipc/crypto.c +9 -0
@@ -950,12 +950,20 @@ static int tipc_aead_decrypt(struct net goto exit; } +/* Get net to avoid freed tipc_crypto when delete namespace */ +if (!maybe_get_net (net)) { +tipc_bearer_put (b); + rc = -ENODEV ; + goto exit; + } +/* Now, do decrypt */ rc =crypto_aead_decrypt (req);if (rc == -EINPROGRESS || rc == -EBUSY )return rc;tipc_bearer_put (b); +put_net (net); exit:kfree (ctx);
@@ -993,6 +1001,7 @@ static void tipc_aead_decrypt_done(void }tipc_bearer_put (b); +put_net (net); }static inline int tipc_ehdr_size (struct tipc_ehdr *ehdr)
Greg Kroah-Hartman
maintainerPATCH 149/175 LoongArch: Report dying CPU to RCU in stop_this_cpu()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Huacai Chen <[email protected]>
commit f2539c56c74691e7a88af6372ba2b48c06ed2fe4 upstream.
This is a port of MIPS commit 9f3f3bdc6d9dac1 ("MIPS: smp: report dying CPU to RCU in stop_this_cpu()"). smp_send_stop() parks all secondary CPUs in stop_this_cpu(). And the function marks the CPU offline for the scheduler via set_cpu_online(false) but never informs RCU, so RCU keeps expecting a quiescent state from CPUs that are now spinning forever with interrupts disabled.
As long as nothing waits for an RCU grace period after smp_send_stop() this is harmless, which is why it went unnoticed. However, since commit 91840be8f710370 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT"), irq_work_sync() calls synchronize_rcu() on architectures without an irq_work self-IPI, i.e. where arch_irq_work_has_interrupt() returns false. Any irq_work_sync() issued in the reboot/shutdown/halt path after smp_send_stop() then blocks on a grace period that can never complete, hanging the reboot:
WARNING: CPU: 0 PID: 15 at kernel/irq_work.c:144 irq_work_queue_on ... rcu: INFO: rcu_sched detected stalls on CPUs/tasks: rcu: Offline CPU 1 blocking current GP. rcu: Offline CPU 2 blocking current GP. rcu: Offline CPU 3 blocking current GP.
This issue needs some hacks to reproduce, and it was not noticed on LoongArch because arch_irq_work_has_interrupt() usually returns true.
Call rcutree_report_cpu_dead() once interrupts are disabled, mirroring the generic CPU-hotplug offline path, so RCU stops waiting on the parked CPUs and grace periods can still complete. LoongArch shuts down all CPUs here without going through the CPU-hotplug mechanism, so this report is not otherwise issued.
--- arch/loongarch/kernel/smp.c | 1 + 1 file changed, 1 insertion(+)
arch/loongarch/kernel/smp.c +1 -0
@@ -613,6 +613,7 @@ static void stop_this_cpu(void *dummy)set_cpu_online (smp_processor_id (), false);calculate_cpu_foreign_map ();local_irq_disable (); +rcutree_report_cpu_dead ();while (true); }
Greg Kroah-Hartman
maintainerPATCH 150/175 pNFS: Fix use-after-free in pnfs_update_layout()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <[email protected]>
commit 13e198a90ca4050f4bee8a3f23680389a6563ccc upstream.
When hitting the NFS_LAYOUT_RETURN branch in pnfs_update_layout(), the code calls pnfs_prepare_to_retry_layoutget(lo). If it succeeds, pnfs_put_layout_hdr(lo) is called before trace_pnfs_update_layout(), which still references 'lo'. This results in a use-after-free when the tracepoint accesses lo's fields.
Fix this by moving the tracepoint call before pnfs_put_layout_hdr(lo).
--- fs/nfs/pnfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/nfs/pnfs.c +1 -1
@@ -2094,11 +2094,11 @@ lookup_again:dprintk ("%s wait for layoutreturn\n" , __func__); lseg =ERR_PTR (pnfs_prepare_to_retry_layoutget (lo));if (!IS_ERR (lseg)) { -pnfs_put_layout_hdr (lo);dprintk ("%s retrying\n" , __func__);trace_pnfs_update_layout (ino, pos, count, iomode, lo, lseg,PNFS_UPDATE_LAYOUT_RETRY ); +pnfs_put_layout_hdr (lo); goto lookup_again; } trace_pnfs_update_layout(ino, pos, count, iomode, lo, lseg,
Greg Kroah-Hartman
maintainerPATCH 151/175 irqchip/imgpdc: Fix resource leak, add missing chained handler cleanup on remove
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qingshuang Fu <[email protected]>
commit 37738fdf2ab1e504d1c63ce5bc0aeb6452d8f057 upstream.
The driver allocates domain generic chips using irq_alloc_domain_generic_chips() during probe and sets up chained handlers using irq_set_chained_handler_and_data(). However, on driver removal, the generic chips are not freed and the chained handlers are not removed.
The generic chips remain on the global gc_list and may later be accessed by generic interrupt chip suspend, resume, or shutdown callbacks after the driver has been removed, potentially resulting in a use-after-free and kernel crash.
The chained handlers that were installed in probe for peripheral and syswake interrupts are also left dangling, which can lead to spurious interrupts accessing freed memory.
Fix these issues by:
- Setting IRQ_DOMAIN_FLAG_DESTROY_GC flag in domain->flags, so the core code automatically removes generic chips when irq_domain_remove() is called
- Clearing all chained handlers with NULL in pdc_intc_remove()
--- drivers/irqchip/irq-imgpdc.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/irqchip/irq-imgpdc.c +6 -0
@@ -378,6 +378,7 @@ static int pdc_intc_probe(struct platfordev_err (&pdev->dev,"cannot add IRQ domain\n" );return -ENOMEM ; } + priv->domain->flags |=IRQ_DOMAIN_FLAG_DESTROY_GC ;/* * Set up 2 generic irq chips with 2 chip types.
@@ -465,6 +466,11 @@ static int pdc_intc_remove(struct platfo {struct pdc_intc_priv *priv =platform_get_drvdata (pdev); +for (unsigned int i =0 ; i < priv->nr_perips; ++i) +irq_set_chained_handler_and_data (priv->perip_irqs[i],NULL ,NULL ); + +irq_set_chained_handler_and_data (priv->syswake_irq,NULL ,NULL ); +irq_domain_remove (priv->domain);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 152/175 fpga: region: fix use-after-free in child_regions_with_firmware()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <[email protected]>
commit 54f3c5643ec523a04b6ec0e7c19eb10f5ebebdd3 upstream.
Move of_node_put(child_region) after the error print to avoid accessing freed memory when pr_err() references child_region.
--- drivers/fpga/of-fpga-region.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/fpga/of-fpga-region.c +1 -2
@@ -168,11 +168,10 @@ static int child_regions_with_firmware(s fpga_region_of_match); } -of_node_put (child_region); -if (ret)pr_err ("firmware-name not allowed in child FPGA region: %pOF" , child_region); +of_node_put (child_region);return ret; }
Greg Kroah-Hartman
maintainerPATCH 153/175 rpmsg: char: Fix use-after-free on probe error path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yuho Choi <[email protected]>
commit 1ff3f528e67d20e2b1483dcaba899dc7832b2e6b upstream.
rpmsg_chrdev_probe() stores the newly allocated eptdev in the default endpoint's priv pointer before calling rpmsg_chrdev_eptdev_add(). If rpmsg_chrdev_eptdev_add() then fails, its error path frees eptdev while the default endpoint may still dispatch callbacks with the stale priv pointer.
Avoid publishing eptdev through the default endpoint until rpmsg_chrdev_eptdev_add() succeeds. Messages received before the priv pointer is published should be ignored by rpmsg_ept_cb(). Flow-control updates can hit rpmsg_ept_flow_cb() in the same window, so make both callbacks return success when priv is NULL.
--- drivers/rpmsg/rpmsg_char.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-)
drivers/rpmsg/rpmsg_char.c +13 -2
@@ -104,6 +104,9 @@ static int rpmsg_ept_cb(struct rpmsg_devstruct rpmsg_eptdev *eptdev = priv;struct sk_buff *skb; +if (!eptdev) +return 0 ; + skb =alloc_skb (len,GFP_ATOMIC );if (!skb)return -ENOMEM ;
@@ -124,6 +127,9 @@ static int rpmsg_ept_flow_cb(struct rpms {struct rpmsg_eptdev *eptdev = priv; +if (!eptdev) +return 0 ; + eptdev->remote_flow_restricted = enable; eptdev->remote_flow_updated = true;
@@ -490,6 +496,7 @@ static int rpmsg_chrdev_probe(struct rpmstruct rpmsg_channel_info chinfo;struct rpmsg_eptdev *eptdev;struct device *dev = &rpdev->dev; +int ret;memcpy (chinfo.name, rpdev->id.name,RPMSG_NAME_SIZE ); chinfo.src = rpdev->src;
@@ -502,13 +509,17 @@ static int rpmsg_chrdev_probe(struct rpm/* Set the default_ept to the rpmsg device endpoint */ eptdev->default_ept = rpdev->ept; + ret =rpmsg_chrdev_eptdev_add (eptdev, chinfo); + +if (ret) +return ret;/* * The rpmsg_ept_cb uses *priv parameter to get its rpmsg_eptdev context. -* Storedit in default_ept *priv field. +* Stored it in default_ept *priv field. */ eptdev->default_ept->priv = eptdev; -return rpmsg_chrdev_eptdev_add (eptdev, chinfo); +return 0 ; }static void rpmsg_chrdev_remove (struct rpmsg_device *rpdev)
Greg Kroah-Hartman
maintainerPATCH 154/175 ocfs2: reject oversized group bitmap descriptors
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Cen <[email protected]>
commit 9bd541e09dffff27e5bec0f9f45b0228173a5375 upstream.
ocfs2_validate_gd_parent() only bounds bg_bits against the parent allocator's chain geometry. A malicious descriptor can still claim a bg_size/bg_bits pair that exceeds the bitmap bytes that physically fit in the group descriptor block, so later bitmap scans and bit updates can run past bg_bitmap.
Add a physical-cap check based on ocfs2_group_bitmap_size() for the parent allocator type and reject descriptors whose bg_size or bg_bits exceed that capacity. Keep the existing chain geometry check so both the on-disk bitmap layout and the allocator metadata must agree before the descriptor is used.
Validation reproduced this kernel report:
KASAN use-after-free in _find_next_bit+0x7f/0xc0
Read of size 8 Call trace: dump_stack_lvl+0x66/0xa0 (?:?) print_report+0xd0/0x630 (?:?) _find_next_bit+0x7f/0xc0 (?:?) srso_alias_return_thunk+0x5/0xfbef5 (?:?) __virt_addr_valid+0x188/0x2f0 (?:?) kasan_report+0xe4/0x120 (?:?) ocfs2_find_max_contig_free_bits+0x35/0x70 (fs/ocfs2/suballoc.c:1375) ocfs2_block_group_set_bits+0x472/0x4b0 (fs/ocfs2/suballoc.c:1457) ocfs2_cluster_group_search+0x16b/0x440 (fs/ocfs2/suballoc.c:86) ocfs2_bg_discontig_fix_result+0x1ef/0x230 (fs/ocfs2/suballoc.c:1786) ocfs2_search_chain+0x8f8/0x10a0 (fs/ocfs2/suballoc.c:1886) get_page_from_freelist+0x70e/0x2370 (?:?) lock_release+0xc6/0x290 (?:?) do_raw_spin_unlock+0x9a/0x100 (?:?) kasan_unpoison+0x27/0x60 (?:?) __bfs+0x147/0x240 (?:?) get_page_from_freelist+0x83d/0x2370 (?:?) ocfs2_claim_suballoc_bits+0x38c/0xe70 (fs/ocfs2/suballoc.c:96) sched_domains_numa_masks_clear+0x70/0xd0 (?:?) check_irq_usage+0xe8/0xb70 (?:?) __ocfs2_claim_clusters+0x18d/0x4c0 (fs/ocfs2/suballoc.c:2497) check_path+0x24/0x50 (?:?) rcu_is_watching+0x20/0x50 (?:?) check_prev_add+0xfd/0xd00 (?:?) ocfs2_add_clusters_in_btree+0x17d/0x810 (fs/ocfs2/suballoc.c:?) __folio_batch_add_and_move+0x1f5/0x3d0 (?:?) ocfs2_add_inode_data+0xd9/0x120 (fs/ocfs2/suballoc.c:?) filemap_add_folio+0x105/0x1f0 (?:?) ocfs2_write_begin_nolock+0x29f7/0x2f80 (fs/ocfs2/suballoc.c:3043) ocfs2_read_inode_block+0xb5/0x110 (fs/ocfs2/suballoc.c:?) down_write+0xf5/0x180 (?:?) ocfs2_write_begin+0x180/0x240 (fs/ocfs2/suballoc.c:?) __mark_inode_dirty+0x758/0x9a0 (?:?) inode_to_bdi+0x41/0x90 (?:?) balance_dirty_pages_ratelimited_flags+0xf8/0x1d0 (?:?) generic_perform_write+0x252/0x440 (?:?) mnt_put_write_access_file+0x16/0x70 (?:?) file_update_time_flags+0xe4/0x200 (?:?) ocfs2_file_write_iter+0x80a/0x1320 (fs/ocfs2/suballoc.c:?) lock_acquire+0x184/0x2f0 (?:?) ksys_write+0xd2/0x170 (?:?) apparmor_file_permission+0xf5/0x310 (?:?) read_zero+0x8d/0x140 (?:?) lock_is_held_type+0x8f/0x100 (?:?)
--- fs/ocfs2/suballoc.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+)
fs/ocfs2/suballoc.c +22 -0
@@ -201,8 +201,16 @@ static int ocfs2_validate_gd_parent(stru int resize) {unsigned int max_bits; +unsigned int max_bitmap_bits; +unsigned int max_bitmap_size; +int suballocator;struct ocfs2_group_desc *gd = (struct ocfs2_group_desc *)bh->b_data; + suballocator =le64_to_cpu (di->i_blkno) !=OCFS2_SB (sb)->bitmap_blkno; + max_bitmap_size =ocfs2_group_bitmap_size (sb, suballocator, +OCFS2_SB (sb)->s_feature_incompat); + max_bitmap_bits = max_bitmap_size *8 ; +if (di->i_blkno != gd->bg_parent_dinode) { do_error("Group descriptor #%llu has bad parent pointer (%llu, expected %llu)\n", (unsigned long long)bh->b_blocknr,
@@ -210,6 +218,20 @@ static int ocfs2_validate_gd_parent(stru (unsigned long long)le64_to_cpu(di->i_blkno)); } +if (le16_to_cpu (gd->bg_size) > max_bitmap_size) { +do_error ("Group descriptor #%llu has bitmap size %u but physical max of %u\n" , + (unsigned long long )bh->b_blocknr, +le16_to_cpu (gd->bg_size), + max_bitmap_size); + } + +if (le16_to_cpu (gd->bg_bits) > max_bitmap_bits) { +do_error ("Group descriptor #%llu has bit count %u but physical max of %u\n" , + (unsigned long long )bh->b_blocknr, +le16_to_cpu (gd->bg_bits), + max_bitmap_bits); + } + max_bits =le16_to_cpu (di->id2.i_chain.cl_cpg) *le16_to_cpu (di->id2.i_chain.cl_bpc);if (le16_to_cpu (gd->bg_bits) > max_bits) { do_error("Group descriptor #%llu has bit count of %u\n",
Greg Kroah-Hartman
maintainerPATCH 155/175 9p: avoid putting oldfid in p9_client_walk() error path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yizhou Zhao <[email protected]>
commit 1a3860d46e3eb47dbd60339783cdad7904486b9f upstream.
When p9_client_walk() is called with clone set to false, fid aliases oldfid. If the walk subsequently fails after the request has been sent, the error path jumps to clunk_fid, which currently calls p9_fid_put(fid) unconditionally.
This drops a reference to oldfid even though ownership of oldfid remains with the caller. If this is the last reference, oldfid can be clunked and destroyed while the caller still expects it to be valid. A later use or put of oldfid can then trigger a use-after-free or refcount underflow.
Fix this by only putting fid in the clunk_fid error path when it does not alias oldfid, matching the existing guard in the error path below.
This can be triggered when a multi-component walk is split into multiple p9_client_walk() calls and a later non-cloning walk fails. A reproducer and refcount warning logs are available on request.
Message-ID: <[email protected]>
--- net/9p/client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/9p/client.c +2 -1
@@ -1214,7 +1214,8 @@ struct p9_fid *p9_client_walk(struct p9_ clunk_fid:kfree (wqids); -p9_fid_put (fid); +if (fid != oldfid) +p9_fid_put (fid); fid =NULL ; error:
Greg Kroah-Hartman
maintainerPATCH 156/175 MIPS: smp: report dying CPU to RCU in stop_this_cpu()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jonas Jelonek <[email protected]>
commit 9f3f3bdc6d9dac1a5a8262ee7ad0f2ff1527a7e7 upstream.
smp_send_stop() parks all secondary CPUs in stop_this_cpu(). The function marks the CPU offline for the scheduler via set_cpu_online(false) but never informs RCU, so RCU keeps expecting a quiescent state from CPUs that are now spinning forever with interrupts disabled.
As long as nothing waits for an RCU grace period after smp_send_stop() this is harmless, which is why it went unnoticed. Since commit 91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT") however, irq_work_sync() calls synchronize_rcu() on architectures without an irq_work self-IPI, i.e. where arch_irq_work_has_interrupt() returns false. That is the asm-generic default used by MIPS. Any irq_work_sync() issued in the reboot/shutdown path after smp_send_stop() then blocks on a grace period that can never complete, hanging the reboot:
WARNING: CPU: 0 PID: 15 at kernel/irq_work.c:144 irq_work_queue_on ... rcu: INFO: rcu_sched detected stalls on CPUs/tasks: rcu: Offline CPU 1 blocking current GP. rcu: Offline CPU 2 blocking current GP. rcu: Offline CPU 3 blocking current GP.
This issue was noticed on several Realtek MIPS switch SoCs (MIPS interAptiv) and came up during kernel bump downstream in OpenWrt from 6.18.33 to 6.18.34, after the backport of the patch to the 6.18 stable branch. The patch also has been backported all the way back to 6.1.
Call rcutree_report_cpu_dead() once interrupts are disabled, mirroring the generic CPU-hotplug offline path, so RCU stops waiting on the parked CPUs and grace periods can still complete. MIPS shuts down all CPUs here without going through the CPU-hotplug mechanism, so this report is not otherwise issued. Reporting a dying CPU to RCU outside the regular hotplug offline path is not unprecedented: arm64 does the same in cpu_die_early(). There it is an exception for a CPU that was coming online and is aborting bringup, rather than the default shutdown action as on MIPS.
--- arch/mips/kernel/smp.c | 2 ++ 1 file changed, 2 insertions(+)
arch/mips/kernel/smp.c +2 -0
@@ -19,6 +19,7 @@#include <linux/sched/mm.h> #include <linux/cpumask.h> #include <linux/cpu.h> +#include <linux/rcupdate.h> #include <linux/err.h> #include <linux/ftrace.h> #include <linux/irqdomain.h>
@@ -410,6 +411,7 @@ static void stop_this_cpu(void *dummy)set_cpu_online (smp_processor_id (), false);calculate_cpu_foreign_map ();local_irq_disable (); +rcutree_report_cpu_dead ();while (1 ); }
Greg Kroah-Hartman
maintainerPATCH 157/175 KVM: x86: hyper-v: Bound the bank index when querying sparse banks
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hyunwoo Kim <[email protected]>
commit 4721f8160f17554b003e8928bb61e6c9b2fe92a3 upstream.
When checking if a VP ID is included in a sparse bank set, explicitly check that the ID can actually be contained in a sparse bank (the TLFS allows for a maximum of 64 banks of 64 vCPUs each). When handling a paravirtual TLB flush for L2, the VP ID is copied verbatim from the enlightened VMCS, without any bounds check, i.e. isn't guaranteed to be under the limit of 4096.
Failure to check the bounds of the VP ID leads to an out-of-bounds read when testing the sparse bank, and super strictly speaking could lead to KVM performing an unnecessary TLB flush for an L2 vCPU.
==================================================================
BUG: KASAN: use-after-free in hv_is_vp_in_sparse_set+0x85/0x100 [kvm]
Read of size 8 at addr ffff88811ba5f598 by task hyperv_evmcs/2802
CPU: 12 UID: 1000 PID: 2802 Comm: hyperv_evmcs Not tainted 7.1.0-rc2 #7 PREEMPT
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 0.0.0 02/06/2015
Call Trace:
<TASK>
dump_stack_lvl+0x51/0x60
print_report+0xcb/0x5d0
kasan_report+0xb4/0xe0
kasan_check_range+0x35/0x1b0
hv_is_vp_in_sparse_set+0x85/0x100 [kvm]
kvm_hv_flush_tlb+0xe9e/0x16c0 [kvm]
kvm_hv_hypercall+0xe6b/0x1e60 [kvm]
vmx_handle_exit+0x485/0x1b60 [kvm_intel]
kvm_arch_vcpu_ioctl_run+0x22e3/0x5070 [kvm]
kvm_vcpu_ioctl+0x5d0/0x10c0 [kvm]
__x64_sys_ioctl+0x129/0x1a0
do_syscall_64+0xb9/0xcf0
entry_SYSCALL_64_after_hwframe+0x4b/0x53
RIP: 0033:0x7f0e62d1a9bf
</TASK>
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffffffffffffffff pfn:0x11ba5f
flags: 0x4000000000000000(zone=1)
raw: 4000000000000000 0000000000000000 00000000ffffffff 0000000000000000
raw: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff88811ba5f480: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff88811ba5f500: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
>ffff88811ba5f580: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
^
ffff88811ba5f600: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
ffff88811ba5f680: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
==================================================================
Disabling lock debugging due to kernel taintOpportunistically add a compile time assertion to ensure the maximum number of sparse banks exactly matches the number of possible bits in the passed in mask.
--- arch/x86/kvm/hyperv.c | 5 +++++ 1 file changed, 5 insertions(+)
arch/x86/kvm/hyperv.c +5 -0
@@ -1787,6 +1787,11 @@ static bool hv_is_vp_in_sparse_set(u32 vint valid_bit_nr = vp_id /HV_VCPUS_PER_SPARSE_BANK ;unsigned long sbank; +BUILD_BUG_ON (BITS_PER_TYPE (valid_bank_mask) !=HV_MAX_SPARSE_VCPU_BANKS ); + +if (valid_bit_nr >=HV_MAX_SPARSE_VCPU_BANKS ) +return false; +if (!test_bit (valid_bit_nr, (unsigned long *)&valid_bank_mask))return false;
Greg Kroah-Hartman
maintainerPATCH 158/175 KVM: SVM: Fix page overflow in sev_dbg_crypt() for ENCRYPT path
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ashutosh Desai <[email protected]>
commit 78ee2d50185a037b3d2452a97f3dad69c3f7f389 upstream.
In sev_dbg_crypt(), the per-iteration transfer length is bounded by the source page offset (PAGE_SIZE - s_off) but not by the destination page offset (PAGE_SIZE - d_off). When d_off > s_off, the encrypt path (__sev_dbg_encrypt_user) performs a read-modify-write using a single-page intermediate buffer (dst_tpage):
1. __sev_dbg_decrypt() expands the size to round_up(len + (d_off & 15), 16) before issuing the PSP command. If len + (d_off & 15) > PAGE_SIZE, the PSP writes beyond the end of the 4096-byte dst_tpage allocation.
2. The subsequent memcpy()/copy_from_user() into page_address(dst_tpage) + (d_off & 15) of 'len' bytes overflows by up to 15 bytes under the same condition.
Trigger example: s_off = 0, d_off = 1, debug.len = PAGE_SIZE - the PSP is instructed to write round_up(4097, 16) = 4112 bytes to a 4096-byte buffer.
Fix by also bounding len by (PAGE_SIZE - d_off), the same check that sev_send_update_data() already performs for its single-page guest region.
==================================================================
BUG: KASAN: slab-use-after-free in sev_dbg_crypt+0x993/0xd10 [kvm_amd]
Write of size 4095 at addr ff110062293bb009 by task sev_dbg_test/228214
CPU: 96 UID: 0 PID: 228214 Comm: sev_dbg_test Tainted: G U W 7.0.0-smp--5ce9b0c48211-dbg #156 PREEMPTLAZY
Tainted: [U]=USER, [W]=WARN
Hardware name: Google Astoria/astoria, BIOS 0.20250817.1-0 08/25/2025
Call Trace:
<TASK>
dump_stack_lvl+0x54/0x70
print_report+0xbc/0x260
kasan_report+0xa2/0xd0
kasan_check_range+0x25f/0x2c0
__asan_memcpy+0x40/0x70
sev_dbg_crypt+0x993/0xd10 [kvm_amd]
sev_mem_enc_ioctl+0x33c/0x450 [kvm_amd]
kvm_vm_ioctl+0x65d/0x6d0 [kvm]
__se_sys_ioctl+0xb2/0x100
do_syscall_64+0xe8/0x870
entry_SYSCALL_64_after_hwframe+0x4b/0x53
</TASK>
The buggy address belongs to the physical page:
page: refcount:1 mapcount:0 mapping:0000000000000000 index:0x7fe72b6a0 pfn:0x62293bb
memcg:ff11000112827d82
flags: 0x1400000000000000(node=1|zone=1)
raw: 1400000000000000 0000000000000000 dead000000000122 0000000000000000
raw: 00000007fe72b6a0 0000000000000000 00000001ffffffff ff11000112827d82
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ff110062293bbf00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ff110062293bbf80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ff110062293bc000: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
^
ff110062293bc080: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
ff110062293bc100: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
==================================================================
Disabling lock debugging due to kernel taint--- arch/x86/kvm/svm/sev.c | 1 + 1 file changed, 1 insertion(+)
arch/x86/kvm/svm/sev.c +1 -0
@@ -1004,6 +1004,7 @@ static int sev_dbg_crypt(struct kvm *kvm s_off = vaddr & ~PAGE_MASK ; d_off = dst_vaddr & ~PAGE_MASK ; len =min_t (size_t, (PAGE_SIZE - s_off), size); + len =min_t (size_t, len,PAGE_SIZE - d_off);if (dec) ret = __sev_dbg_decrypt_user(kvm,
Greg Kroah-Hartman
maintainerPATCH 159/175 power: reset: linkstation-poweroff: fix use-after-free in the linkstation_poweroff_init()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <[email protected]>
commit 8eec545cde69e46e9a1d2b7d915ce4f5df85b3bd upstream.
Move of_node_put(dn) after the of_match_node() call, which still needs the node pointer. The node reference is correctly released after use.
--- drivers/power/reset/linkstation-poweroff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/power/reset/linkstation-poweroff.c +1 -1
@@ -163,10 +163,10 @@ static int __init linkstation_poweroff_i dn =of_find_matching_node (NULL , ls_poweroff_of_match);if (!dn)return -ENODEV ; -of_node_put (dn); match =of_match_node (ls_poweroff_of_match, dn); cfg = match->data; +of_node_put (dn); dn =of_find_node_by_name (NULL , cfg->mdio_node_name);if (!dn)
Greg Kroah-Hartman
maintainerPATCH 160/175 fbdev: Fix fb_new_modelist to prevent null-ptr-deref in fb_videomode_to_var
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Bridges <[email protected]>
commit 7f08fc10fa3d3366dc3af723970bd03d7d6d10e3 upstream.
info->var, a framebuffer's current mode, is expected to have a matching entry in info->modelist. var_to_display() relies on this and treats a failed fb_match_mode() as "This should not happen". fb_set_var() keeps it true by adding the mode to the list on every change, and do_register_framebuffer() does the same at registration.
store_modes() replaces the modelist from userspace. fb_new_modelist() validates the new modes but does not check that info->var still has a match. It relies on fbcon_new_modelist() to re-point consoles, but that only handles consoles mapped to the framebuffer. With fbcon unbound there are none, so info->var is left describing a mode that is no longer in the list.
A later console takeover runs var_to_display(), where fb_match_mode() returns NULL and leaves fb_display[i].mode NULL. fbcon_switch() passes it to display_to_var(), and fb_videomode_to_var() dereferences the NULL mode.
Keep the current mode in the list in fb_new_modelist(), the same way fb_set_var() does.
--- drivers/video/fbdev/core/fbmem.c | 12 ++++++++++++ 1 file changed, 12 insertions(+)
drivers/video/fbdev/core/fbmem.c +12 -0
@@ -1190,6 +1190,18 @@ int fb_new_modelist(struct fb_info *infoif (list_empty (&info->modelist))return 1 ; +/* +* The new modelist may not contain the current mode (info->var), and +* fbcon_new_modelist() below only re-points consoles mapped to this +* framebuffer. Add the current mode here so info->var keeps a match +* even when fbcon is unbound. +*/ +if (!fb_match_mode (&info->var, &info->modelist)) { +fb_var_to_videomode (&mode, &info->var); +if (fb_add_videomode (&mode, &info->modelist)) +return 1 ; + } +fbcon_new_modelist (info);return 0 ;
Greg Kroah-Hartman
maintainerPATCH 161/175 fbdev: modedb: fix a possible UAF in fb_find_mode()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tuo Li <[email protected]>
commit 85b6256469cebdac395e7447147e06b2e151014f upstream.
If mode_option is NULL, it is assigned from mode_option_buf:
if (!mode_option) {
fb_get_options(NULL, &mode_option_buf);
mode_option = mode_option_buf;
}Later, name is assigned from mode_option:
const char *name = mode_option;
However, mode_option_buf is freed before name is no longer used:
kfree(mode_option_buf);
while name is still accessed by:
if ((name_matches(db[i], name, namelen) ||
Since name aliases mode_option_buf, this may result in a use-after-free.
Fix this by extending the lifetime of mode_option_buf until the end of the function by using scope-based resource management for cleanup.
--- drivers/video/fbdev/core/modedb.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/video/fbdev/core/modedb.c +1 -2
@@ -625,7 +625,7 @@ int fb_find_mode(struct fb_var_screeninfconst struct fb_videomode *default_mode, unsigned int default_bpp) { - char *mode_option_buf = NULL; + char *mode_option_buf __free(kfree) = NULL;int i;/* Set up defaults */
@@ -723,7 +723,6 @@ int fb_find_mode(struct fb_var_screeninf res_specified =1 ; } done: -kfree (mode_option_buf);if (cvt) {struct fb_videomode cvt_mode;int ret;
Greg Kroah-Hartman
maintainerPATCH 162/175 fbdev: modedb: Fix misaligned fields in the 1920x1080-60 mode
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steffen Persvold <[email protected]>
commit d894c48a57d78206e4df9c90d4acfaf39394806a upstream.
The 1920x1080@60 modedb entry has one too many initializers before its sync field: a stray "0" occupies the sync slot, which shifts the remaining values by one field. The entry therefore decodes as sync = 0, vmode = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT (0x3, i.e. FB_VMODE_INTERLACED | FB_VMODE_DOUBLE), and flag = FB_VMODE_NONINTERLACED, instead of the intended sync = positive H/V, vmode = non-interlaced.
fb_find_mode() then returns a 1920x1080 mode flagged as interlaced + doublescan with active-low syncs. Drivers that honour var->vmode and var->sync when programming display timing enable doublescan and the wrong sync polarity, corrupting the output.
Drop the stray initializer so sync and vmode hold their intended values (positive H/V sync, non-interlaced), matching the adjacent 1920x1200 entry.
--- drivers/video/fbdev/core/modedb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/video/fbdev/core/modedb.c +1 -1
@@ -258,7 +258,7 @@ static const struct fb_videomode modedb[ FB_VMODE_DOUBLE },/* 1920x1080 @ 60 Hz, 67.3 kHz hsync */ - {NULL ,60 ,1920 ,1080 ,6734 ,148 ,88 ,36 ,4 ,44 ,5 ,0 , + {NULL ,60 ,1920 ,1080 ,6734 ,148 ,88 ,36 ,4 ,44 ,5 ,FB_SYNC_HOR_HIGH_ACT |FB_SYNC_VERT_HIGH_ACT , FB_VMODE_NONINTERLACED },
Greg Kroah-Hartman
maintainerPATCH 163/175 NFSD: Fix SECINFO_NO_NAME decode error cleanup
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guannan Wang <[email protected]>
commit 9e18e83b8846a5c3fe13fc8a464b4865d33996c6 upstream.
nfsd4_decode_secinfo_no_name() currently initializes sin_exp after decoding sin_style. If the XDR stream is truncated, the decoder returns nfserr_bad_xdr before sin_exp is initialized.
Since commit 3fdc54646234 ("NFSD: Reduce amount of struct nfsd4_compoundargs that needs clearing"), the inline iops array is not cleared between RPC calls. A failed SECINFO_NO_NAME decode can therefore leave sin_exp holding stale union contents from a previous operation.
The error response path still invokes nfsd4_secinfo_no_name_release(), which calls exp_put() on a non-NULL sin_exp.
Initialize sin_exp before the first failable decode step, matching nfsd4_decode_secinfo().
--- fs/nfsd/nfs4xdr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/nfsd/nfs4xdr.c +2 -1
@@ -1821,10 +1821,11 @@ static __be32 nfsd4_decode_secinfo_no_na union nfsd4_op_u *u) {struct nfsd4_secinfo_no_name *sin = &u->secinfo_no_name; + + sin->sin_exp =NULL ;if (xdr_stream_decode_u32 (argp->xdr, &sin->sin_style) <0 )return nfserr_bad_xdr; - sin->sin_exp =NULL ;return nfs_ok; }
Greg Kroah-Hartman
maintainerPATCH 164/175 nfsd: fix posix_acl leak on SETACL decode failure
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jeff Layton <[email protected]>
commit 0853ac544c590880d797b04daa33fcb72b6be0e1 upstream.
nfsaclsvc_decode_setaclargs() and nfs3svc_decode_setaclargs() each call nfs_stream_decode_acl() twice, first for NFS_ACL and then for NFS_DFACL. Each successful call transfers ownership of a freshly allocated posix_acl into argp->acl_access or argp->acl_default. If the first call succeeds but the second fails, the decoder returns false and argp->acl_access is left dangling.
ACLPROC2_SETACL.pc_release was wired to nfssvc_release_attrstat and ACLPROC3_SETACL.pc_release was wired to nfs3svc_release_fhandle. Both only call fh_put() and have no knowledge of the ACL fields on argp. The posix_acl_release() pairs sat at the out: labels inside nfsacld_proc_setacl() and nfsd3_proc_setacl(), but svc_process() skips pc_func when pc_decode returns false, so that cleanup is unreachable on decode failure:
svc_process_common()
pc_decode() /* decode_setaclargs: false */
/* pc_func skipped */
pc_release() /* fh_put only -- ACLs leaked */
The orphaned posix_acl is leaked for the lifetime of the server.
Fix by adding nfsaclsvc_release_setacl() and nfs3svc_release_setacl(), which release both argp->acl_access and argp->acl_default in addition to fh_put(), and wiring them as pc_release for their respective SETACL procedures. pc_release runs on every path svc_process() takes after decode, including decode failure, so the posix_acl_release() pairs are removed from the proc functions' out: labels to keep ownership in one place. This matches the existing release_getacl() pattern used by the sibling GETACL procedures.
--- fs/nfsd/nfs2acl.c | 17 ++++++++++++----- fs/nfsd/nfs3acl.c | 17 ++++++++++++----- 2 files changed, 24 insertions(+), 10 deletions(-)
fs/nfsd/nfs2acl.c +12 -5
@@ -131,10 +131,7 @@ static __be32 nfsacld_proc_setacl(struct resp->status =fh_getattr (fh, &resp->stat); out: -/* argp->acl_{access,default} may have been allocated in -nfssvc_decode_setaclargs. */ -posix_acl_release (argp->acl_access); -posix_acl_release (argp->acl_default); +/* argp->acl_{access,default} are released in nfsaclsvc_release_setacl. */ return rpc_success; out_drop_lock:
@@ -312,6 +309,16 @@ static void nfsaclsvc_release_access(strstruct nfsd3_voidargs {int dummy; }; +static void nfsaclsvc_release_setacl (struct svc_rqst *rqstp) +{ +struct nfsd3_setaclargs *argp = rqstp->rq_argp; +struct nfsd_attrstat *resp = rqstp->rq_resp; + +fh_put (&resp->fh); +posix_acl_release (argp->acl_access); +posix_acl_release (argp->acl_default); +} +#define ST 1/* status*/ #define AT 21/* attributes */ #define pAT (1+AT)/* post attributes - conditional */
@@ -345,7 +352,7 @@ static const struct svc_procedure nfsd_a .pc_func = nfsacld_proc_setacl, .pc_decode = nfsaclsvc_decode_setaclargs, .pc_encode = nfssvc_encode_attrstatres, - .pc_release = nfssvc_release_attrstat, + .pc_release = nfsaclsvc_release_setacl, .pc_argsize = sizeof(struct nfsd3_setaclargs), .pc_argzero = sizeof(struct nfsd3_setaclargs), .pc_ressize = sizeof(struct nfsd_attrstat),
fs/nfsd/nfs3acl.c +12 -5
@@ -118,10 +118,7 @@ out_drop_lock: out_errno: resp->status =nfserrno (error); out: -/* argp->acl_{access,default} may have been allocated in -nfs3svc_decode_setaclargs. */ -posix_acl_release (argp->acl_access); -posix_acl_release (argp->acl_default); +/* argp->acl_{access,default} are released in nfs3svc_release_setacl. */ return rpc_success; }
@@ -225,6 +222,16 @@ static void nfs3svc_release_getacl(strucstruct nfsd3_voidargs {int dummy; }; +static void nfs3svc_release_setacl (struct svc_rqst *rqstp) +{ +struct nfsd3_setaclargs *argp = rqstp->rq_argp; +struct nfsd3_attrstat *resp = rqstp->rq_resp; + +fh_put (&resp->fh); +posix_acl_release (argp->acl_access); +posix_acl_release (argp->acl_default); +} +#define ST 1/* status*/ #define AT 21/* attributes */ #define pAT (1+AT)/* post attributes - conditional */
@@ -258,7 +265,7 @@ static const struct svc_procedure nfsd_a .pc_func = nfsd3_proc_setacl, .pc_decode = nfs3svc_decode_setaclargs, .pc_encode = nfs3svc_encode_setaclres, - .pc_release = nfs3svc_release_fhandle, + .pc_release = nfs3svc_release_setacl, .pc_argsize = sizeof(struct nfsd3_setaclargs), .pc_argzero = sizeof(struct nfsd3_setaclargs), .pc_ressize = sizeof(struct nfsd3_attrstat),
Greg Kroah-Hartman
maintainerPATCH 165/175 nfsd: check get_user() return when reading princhashlen
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dominik Woźniak <[email protected]>
commit e186fa1c057f5eccb22afb1e83e34c0627085868 upstream.
In __cld_pipe_inprogress_downcall(), the get_user() that reads princhashlen from the userspace cld_msg_v2 buffer does not check its return value. A failing copy leaves princhashlen with uninitialised stack contents, which are then used to drive memdup_user() and stored as princhash.len on the resulting reclaim record. The other get_user() calls in this function all check the return; only this one is missed, which is most likely a copy-paste oversight from when v2 upcalls were introduced.
Mirror the existing pattern used a few lines above for namelen. namecopy is declared with __free(kfree) so the early return cleans up the already-allocated buffer automatically.
--- fs/nfsd/nfs4recover.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
fs/nfsd/nfs4recover.c +2 -1
@@ -815,7 +815,8 @@ __cld_pipe_inprogress_downcall(const strif (IS_ERR (name.data))return PTR_ERR (name.data); name.len = namelen; -get_user (princhashlen, &ci->cc_princhash.cp_len); +if (get_user (princhashlen, &ci->cc_princhash.cp_len)) +return -EFAULT ;if (princhashlen >0 ) { princhash.data = memdup_user( &ci->cc_princhash.cp_data,
Greg Kroah-Hartman
maintainerPATCH 166/175 NFSv4/pNFS: reject zero-length r_addr in nfs4_decode_mp_ds_addr
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 41fe0f7b84f0cb822ae10ab08592996a592b2a25 upstream.
nfs4_decode_mp_ds_addr() decodes the r_netid and r_addr opaques of a netaddr4 from a GETDEVICEINFO multipath-DS body, then immediately calls strrchr(buf, '.') to locate the port separator. Both decodes use xdr_stream_decode_string_dup(), and the current code checks only "nlen < 0" / "rlen < 0" before dereferencing the returned string.
When the on-wire opaque has length zero, xdr_stream_decode_opaque_inline() returns 0 and xdr_stream_decode_string_dup() falls through to its "*str = NULL; return ret" tail, leaving buf NULL with a return value of 0. The "< 0" check does not catch this, and the next line is strrchr(NULL, '.'), a kernel NULL pointer dereference reachable from any pNFS-flexfile client mounted against a malicious or compromised metadata server.
Reject the zero-length cases explicitly so the decoder fails with -EBADMSG (treated as a malformed GETDEVICEINFO body) instead of panicking the client.
--- fs/nfs/pnfs_nfs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/nfs/pnfs_nfs.c +2 -2
@@ -1102,14 +1102,14 @@ nfs4_decode_mp_ds_addr(struct net *net,/* r_netid */ nlen =xdr_stream_decode_string_dup (xdr, &netid,XDR_MAX_NETOBJ , gfp_flags); -if (unlikely (nlen <0 )) +if (unlikely (nlen <=0 )) goto out_err;/* r_addr: ip/ip6addr with port in dec octets - see RFC 5665 */ /* port is ".ABC.DEF", 8 chars max */ rlen =xdr_stream_decode_string_dup (xdr, &buf,INET6_ADDRSTRLEN +IPV6_SCOPE_ID_LEN +8 , gfp_flags); -if (unlikely (rlen <0 )) +if (unlikely (rlen <=0 )) goto out_free_netid;/* replace port '.' with '-' */
Greg Kroah-Hartman
maintainerPATCH 167/175 NFS: Prevent resource leak in nfs_alloc_server()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Markus Elfring <[email protected]>
commit d189f224308c8ac3feeea8e442c99922bd18f1b2 upstream.
It was overlooked to call ida_free() after a failed nfs_alloc_iostats() call. Thus add the missed function call in an if branch.
--- fs/nfs/client.c | 1 + 1 file changed, 1 insertion(+)
fs/nfs/client.c +1 -0
@@ -1046,6 +1046,7 @@ struct nfs_server *nfs_alloc_server(void server->io_stats =nfs_alloc_iostats ();if (!server->io_stats) { +ida_free (&s_sysfs_ids, server->s_sysfs_id);kfree (server);return NULL ; }
Greg Kroah-Hartman
maintainerPATCH 168/175 ksmbd: fix out-of-bounds read in smb_check_perm_dacl()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hem Parekh <[email protected]>
commit 1ef06004ed4bd6d3ed8c840d9d1a376b66d4935b upstream.
The permission-check ACE walk in smb_check_perm_dacl() validates the ACE header size and caps sid.num_subauth at SID_MAX_SUB_AUTHORITIES, but it never checks that ace->size is actually large enough to contain num_subauth sub-authorities before compare_sids() dereferences them.
CIFS_SID_BASE_SIZE covers the SID header up to but excluding the sub_auth[] array, and offsetof(struct smb_ace, sid) is the ACE header, so the existing guards only guarantee the 8-byte SID base, i.e. zero sub-authorities. compare_sids() then reads ace->sid.sub_auth[i] for i < min(local_sid->num_subauth, ace->sid.num_subauth). The local comparison SIDs (sid_everyone, sid_unix_NFS_mode, and the id_to_sid() result) always have at least one sub-authority, and an attacker controls the ACE revision and authority bytes (which lie within the in-bounds SID base), so they can match one of those SIDs and force the sub_auth read.
A crafted ACE with size == 16 and num_subauth >= 1 placed at the tail of the security descriptor therefore causes a heap out-of-bounds read of up to SID_MAX_SUB_AUTHORITIES * sizeof(__le32) bytes past the pntsd allocation. The security descriptor is loaded by ksmbd_vfs_get_sd_xattr() into a buffer sized exactly to the on-disk data (kzalloc(sd_size) in ndr_decode_v4_ntacl()), so the read lands past the allocation. The malformed descriptor can be stored verbatim via SMB2_SET_INFO (the DACL is not normalised before being written to the security.NTACL xattr) and the read fires on a subsequent SMB2_CREATE access check, making this reachable by an authenticated client on a share that uses ACL xattrs.
Add the missing num_subauth-versus-ace_size check, mirroring the identical guards already present in the sibling parsers parse_dacl() and smb_inherit_dacl().
--- fs/smb/server/smbacl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/smb/server/smbacl.c +3 -1
@@ -1419,7 +1419,9 @@ int smb_check_perm_dacl(struct ksmbd_conbreak ; aces_size -= ace_size; -if (ace->sid.num_subauth >SID_MAX_SUB_AUTHORITIES ) +if (ace->sid.num_subauth >SID_MAX_SUB_AUTHORITIES || + ace_size < offsetof(struct smb_ace , sid) +CIFS_SID_BASE_SIZE + +sizeof (__le32) * ace->sid.num_subauth)break ; if (!compare_sids(&sid, &ace->sid) ||
Greg Kroah-Hartman
maintainerPATCH 169/175 serial: qcom_geni: Fix RX DMA stall when SE_DMA_RX_LEN_IN is zero
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Viken Dadhaniya <[email protected]>
[ Upstream commit b93062b6d8a1b2d9bad235cac25558a909819026 ]
In qcom_geni_serial_handle_rx_dma(), geni_se_rx_dma_unprep() clears port->rx_dma_addr before SE_DMA_RX_LEN_IN is read. If the register is zero, for example when the RX stale counter fires on an idle line, the handler returns without calling geni_se_rx_dma_prep().
The next RX DMA interrupt then hits the !port->rx_dma_addr guard and returns immediately, so the RX DMA buffer is never rearmed and later input is lost.
Keep the handler on the rearm path when rx_in is zero. Warn about the unexpected zero-length DMA completion, skip received-data handling, and always call geni_se_rx_dma_prep().
--- drivers/tty/serial/qcom_geni_serial.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-)
drivers/tty/serial/qcom_geni_serial.c +3 -6
@@ -838,12 +838,9 @@ static void qcom_geni_serial_handle_rx_d port->rx_dma_addr =0 ; rx_in =readl (uport->membase +SE_DMA_RX_LEN_IN ); -if (!rx_in) { -dev_warn (uport->dev,"serial engine reports 0 RX bytes in!\n" ); -return ; - } - -if (!drop) +if (!rx_in) +dev_warn_ratelimited (uport->dev,"serial engine reports 0 RX bytes in!\n" ); +else if (!drop)handle_rx_uart (uport, rx_in, drop); ret = geni_se_rx_dma_prep(&port->se, port->rx_buf,
Greg Kroah-Hartman
maintainerPATCH 170/175 serial: 8250_dw: unregister 8250 port if clk_notifier_register() fails
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Stepan Ionichev <[email protected]>
[ Upstream commit 10fc708b4de7f86002d2d735a2dbf3b5b7f65692 ]
dw8250_probe() registers the 8250 port via serial8250_register_8250_port() and then, if the device has a clock, registers a clock notifier. If clk_notifier_register() fails, probe returns the error but leaves the 8250 port registered. The matching serial8250_unregister_port() lives in dw8250_remove(), which is not called when probe fails, so the port slot stays occupied until the device is rebound or the system is rebooted. The devm-allocated driver data is freed while the port still references it (via the saved private_data and serial_in/serial_out callbacks), so any access to that port slot before a rebind is a use-after-free hazard.
Unregister the port on the clk_notifier_register() error path.
--- drivers/tty/serial/8250/8250_dw.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/tty/serial/8250/8250_dw.c +3 -1
@@ -688,8 +688,10 @@ static int dw8250_probe(struct platform_*/ if (data->clk) { err =clk_notifier_register (data->clk, &data->clk_notifier); -if (err) +if (err) { +serial8250_unregister_port (data->data.line);return dev_err_probe (dev, err,"Failed to set the clock notifier\n" ); + }queue_work (system_unbound_wq, &data->clk_work); }
Greg Kroah-Hartman
maintainerPATCH 171/175 drivers/base/memory: set mem->altmap after successful device registration
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Georgi Djakov <[email protected]>
[ Upstream commit a2b8d7827f48ee54a686cb80e4a1d0ff954ec42a ]
If __add_memory_block() fails at xa_store() (under memory pressure for example), device_unregister() is called, which eventually triggers memory_block_release() with mem->altmap still set, causing a WARN_ON(mem->altmap). This was triggered by modifying virtio-mem driver.
Fix this by delaying the assignment of mem->altmap until after __add_memory_block() has succeeded.
--- drivers/base/memory.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/base/memory.c +2 -1
@@ -773,7 +773,6 @@ static int add_memory_block(unsigned lon mem->start_section_nr = block_id * sections_per_block; mem->state = state; mem->nid =NUMA_NO_NODE ; - mem->altmap = altmap;INIT_LIST_HEAD (&mem->group_next);#ifndef CONFIG_NUMA
@@ -791,6 +790,8 @@ static int add_memory_block(unsigned lonif (ret)return ret; + mem->altmap = altmap; +if (group) { mem->group = group;list_add (&mem->group_next, &group->memory_blocks);
Greg Kroah-Hartman
maintainerPATCH 172/175 Documentation: ioctl-number: Extend "Include File" column width
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bagas Sanjaya <[email protected]>
[ Upstream commit 15afd5def819e4df2a29cef6fcfa6ae7ba167c0f ]
Extend width of "Include File" column to fit full path to papr-physical-attestation.h in later commit.
Stable-dep-of: d237230728c5 ("crypto: qat - remove unused character device and IOCTLs")
--- Documentation/userspace-api/ioctl/ioctl-number.rst | 464 ++++++++++----------- 1 file changed, 232 insertions(+), 232 deletions(-)
Documentation/userspace-api/ioctl/ioctl-number.rst +232 -232
@@ -66,17 +66,17 @@ This table lists ioctls visible from use most drivers up to 2.6.31, but I know I am missing some. There has been no attempt to list non-X86 architectures or ioctls from drivers/staging/. -==== ===== ======================================================= ================================================================ -Code Seq# Include File Comments +==== ===== ========================================================= ================================================================ +Code Seq# Include File Comments (hex) -==== ===== ======================================================= ================================================================ -0x00 00-1F linux/fs.h conflict! -0x00 00-1F scsi/scsi_ioctl.h conflict! -0x00 00-1F linux/fb.h conflict! -0x00 00-1F linux/wavefront.h conflict! +==== ===== ========================================================= ================================================================ +0x00 00-1F linux/fs.h conflict! +0x00 00-1F scsi/scsi_ioctl.h conflict! +0x00 00-1F linux/fb.h conflict! +0x00 00-1F linux/wavefront.h conflict! 0x02 all linux/fd.h 0x03 all linux/hdreg.h -0x04 D2-DC linux/umsdos_fs.h Dead since 2.6.11, but don't reuse these. +0x04 D2-DC linux/umsdos_fs.h Dead since 2.6.11, but don't reuse these. 0x06 all linux/lp.h 0x09 all linux/raid/md_u.h 0x10 00-0F drivers/char/s390/vmcp.h
@@ -84,299 +84,299 @@ Code Seq# Include File 0x10 20-2F arch/s390/include/uapi/asm/hypfs.h 0x12 all linux/fs.h linux/blkpg.h -0x1b all InfiniBand Subsystem - <http://infiniband.sourceforge.net/> +0x1b all InfiniBand Subsystem + <http://infiniband.sourceforge.net/> 0x20 all drivers/cdrom/cm206.h 0x22 all scsi/sg.h -0x3E 00-0F linux/counter.h <mailto:[email protected]> +0x3E 00-0F linux/counter.h <mailto:[email protected]> '!' 00-1F uapi/linux/seccomp.h -'#' 00-3F IEEE 1394 Subsystem - Block for the entire subsystem +'#' 00-3F IEEE 1394 Subsystem + Block for the entire subsystem '$' 00-0F linux/perf_counter.h, linux/perf_event.h -'%' 00-0F include/uapi/linux/stm.h System Trace Module subsystem - <mailto:[email protected]> +'%' 00-0F include/uapi/linux/stm.h System Trace Module subsystem + <mailto:[email protected]> '&' 00-07 drivers/firewire/nosy-user.h -'1' 00-1F linux/timepps.h PPS kit from Ulrich Windl - <ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/> +'1' 00-1F linux/timepps.h PPS kit from Ulrich Windl + <ftp://ftp.de.kernel.org/pub/linux/daemons/ntp/PPS/> '2' 01-04 linux/i2o.h -'3' 00-0F drivers/s390/char/raw3270.h conflict! -'3' 00-1F linux/suspend_ioctls.h, conflict! +'3' 00-0F drivers/s390/char/raw3270.h conflict! +'3' 00-1F linux/suspend_ioctls.h, conflict! kernel/power/user.c -'8' all SNP8023 advanced NIC card - <mailto:[email protected]> +'8' all SNP8023 advanced NIC card + <mailto:[email protected]> ';' 64-7F linux/vfio.h ';' 80-FF linux/iommufd.h -'=' 00-3f uapi/linux/ptp_clock.h <mailto:[email protected]> -'@' 00-0F linux/radeonfb.h conflict! -'@' 00-0F drivers/video/aty/aty128fb.c conflict! -'A' 00-1F linux/apm_bios.h conflict! -'A' 00-0F linux/agpgart.h, conflict! +'=' 00-3f uapi/linux/ptp_clock.h <mailto:[email protected]> +'@' 00-0F linux/radeonfb.h conflict! +'@' 00-0F drivers/video/aty/aty128fb.c conflict! +'A' 00-1F linux/apm_bios.h conflict! +'A' 00-0F linux/agpgart.h, conflict! drivers/char/agp/compat_ioctl.h -'A' 00-7F sound/asound.h conflict! -'B' 00-1F linux/cciss_ioctl.h conflict! -'B' 00-0F include/linux/pmu.h conflict! -'B' C0-FF advanced bbus <mailto:[email protected]> -'B' 00-0F xen/xenbus_dev.h conflict! -'C' all linux/soundcard.h conflict! -'C' 01-2F linux/capi.h conflict! -'C' F0-FF drivers/net/wan/cosa.h conflict! +'A' 00-7F sound/asound.h conflict! +'B' 00-1F linux/cciss_ioctl.h conflict! +'B' 00-0F include/linux/pmu.h conflict! +'B' C0-FF advanced bbus <mailto:[email protected]> +'B' 00-0F xen/xenbus_dev.h conflict! +'C' all linux/soundcard.h conflict! +'C' 01-2F linux/capi.h conflict! +'C' F0-FF drivers/net/wan/cosa.h conflict! 'D' all arch/s390/include/asm/dasd.h -'D' 40-5F drivers/scsi/dpt/dtpi_ioctl.h Dead since 2022 +'D' 40-5F drivers/scsi/dpt/dtpi_ioctl.h Dead since 2022 'D' 05 drivers/scsi/pmcraid.h -'E' all linux/input.h conflict! -'E' 00-0F xen/evtchn.h conflict! -'F' all linux/fb.h conflict! -'F' 01-02 drivers/scsi/pmcraid.h conflict! -'F' 20 drivers/video/fsl-diu-fb.h conflict! -'F' 20 drivers/video/intelfb/intelfb.h conflict! -'F' 20 linux/ivtvfb.h conflict! -'F' 20 linux/matroxfb.h conflict! -'F' 20 drivers/video/aty/atyfb_base.c conflict! -'F' 00-0F video/da8xx-fb.h conflict! -'F' 80-8F linux/arcfb.h conflict! -'F' DD video/sstfb.h conflict! -'G' 00-3F drivers/misc/sgi-gru/grulib.h conflict! -'G' 00-0F xen/gntalloc.h, xen/gntdev.h conflict! -'H' 00-7F linux/hiddev.h conflict! -'H' 00-0F linux/hidraw.h conflict! -'H' 01 linux/mei.h conflict! -'H' 02 linux/mei.h conflict! -'H' 03 linux/mei.h conflict! -'H' 00-0F sound/asound.h conflict! -'H' 20-40 sound/asound_fm.h conflict! -'H' 80-8F sound/sfnt_info.h conflict! -'H' 10-8F sound/emu10k1.h conflict! -'H' 10-1F sound/sb16_csp.h conflict! -'H' 10-1F sound/hda_hwdep.h conflict! -'H' 40-4F sound/hdspm.h conflict! -'H' 40-4F sound/hdsp.h conflict! +'E' all linux/input.h conflict! +'E' 00-0F xen/evtchn.h conflict! +'F' all linux/fb.h conflict! +'F' 01-02 drivers/scsi/pmcraid.h conflict! +'F' 20 drivers/video/fsl-diu-fb.h conflict! +'F' 20 drivers/video/intelfb/intelfb.h conflict! +'F' 20 linux/ivtvfb.h conflict! +'F' 20 linux/matroxfb.h conflict! +'F' 20 drivers/video/aty/atyfb_base.c conflict! +'F' 00-0F video/da8xx-fb.h conflict! +'F' 80-8F linux/arcfb.h conflict! +'F' DD video/sstfb.h conflict! +'G' 00-3F drivers/misc/sgi-gru/grulib.h conflict! +'G' 00-0F xen/gntalloc.h, xen/gntdev.h conflict! +'H' 00-7F linux/hiddev.h conflict! +'H' 00-0F linux/hidraw.h conflict! +'H' 01 linux/mei.h conflict! +'H' 02 linux/mei.h conflict! +'H' 03 linux/mei.h conflict! +'H' 00-0F sound/asound.h conflict! +'H' 20-40 sound/asound_fm.h conflict! +'H' 80-8F sound/sfnt_info.h conflict! +'H' 10-8F sound/emu10k1.h conflict! +'H' 10-1F sound/sb16_csp.h conflict! +'H' 10-1F sound/hda_hwdep.h conflict! +'H' 40-4F sound/hdspm.h conflict! +'H' 40-4F sound/hdsp.h conflict! 'H' 90 sound/usb/usx2y/usb_stream.h -'H' 00-0F uapi/misc/habanalabs.h conflict! +'H' 00-0F uapi/misc/habanalabs.h conflict! 'H' A0 uapi/linux/usb/cdc-wdm.h -'H' C0-F0 net/bluetooth/hci.h conflict! -'H' C0-DF net/bluetooth/hidp/hidp.h conflict! -'H' C0-DF net/bluetooth/cmtp/cmtp.h conflict! -'H' C0-DF net/bluetooth/bnep/bnep.h conflict! -'H' F1 linux/hid-roccat.h <mailto:[email protected]> +'H' C0-F0 net/bluetooth/hci.h conflict! +'H' C0-DF net/bluetooth/hidp/hidp.h conflict! +'H' C0-DF net/bluetooth/cmtp/cmtp.h conflict! +'H' C0-DF net/bluetooth/bnep/bnep.h conflict! +'H' F1 linux/hid-roccat.h <mailto:[email protected]> 'H' F8-FA sound/firewire.h -'I' all linux/isdn.h conflict! -'I' 00-0F drivers/isdn/divert/isdn_divert.h conflict! -'I' 40-4F linux/mISDNif.h conflict! +'I' all linux/isdn.h conflict! +'I' 00-0F drivers/isdn/divert/isdn_divert.h conflict! +'I' 40-4F linux/mISDNif.h conflict! 'K' all linux/kd.h -'L' 00-1F linux/loop.h conflict! -'L' 10-1F drivers/scsi/mpt3sas/mpt3sas_ctl.h conflict! -'L' E0-FF linux/ppdd.h encrypted disk device driver - <http://linux01.gwdg.de/~alatham/ppdd.html> -'M' all linux/soundcard.h conflict! -'M' 01-16 mtd/mtd-abi.h conflict! +'L' 00-1F linux/loop.h conflict! +'L' 10-1F drivers/scsi/mpt3sas/mpt3sas_ctl.h conflict! +'L' E0-FF linux/ppdd.h encrypted disk device driver + <http://linux01.gwdg.de/~alatham/ppdd.html> +'M' all linux/soundcard.h conflict! +'M' 01-16 mtd/mtd-abi.h conflict! and drivers/mtd/mtdchar.c 'M' 01-03 drivers/scsi/megaraid/megaraid_sas.h -'M' 00-0F drivers/video/fsl-diu-fb.h conflict! +'M' 00-0F drivers/video/fsl-diu-fb.h conflict! 'N' 00-1F drivers/usb/scanner.h 'N' 40-7F drivers/block/nvme.c -'O' 00-06 mtd/ubi-user.h UBI -'P' all linux/soundcard.h conflict! -'P' 60-6F sound/sscape_ioctl.h conflict! -'P' 00-0F drivers/usb/class/usblp.c conflict! -'P' 01-09 drivers/misc/pci_endpoint_test.c conflict! -'P' 00-0F xen/privcmd.h conflict! -'P' 00-05 linux/tps6594_pfsm.h conflict! +'O' 00-06 mtd/ubi-user.h UBI +'P' all linux/soundcard.h conflict! +'P' 60-6F sound/sscape_ioctl.h conflict! +'P' 00-0F drivers/usb/class/usblp.c conflict! +'P' 01-09 drivers/misc/pci_endpoint_test.c conflict! +'P' 00-0F xen/privcmd.h conflict! +'P' 00-05 linux/tps6594_pfsm.h conflict! 'Q' all linux/soundcard.h -'R' 00-1F linux/random.h conflict! -'R' 01 linux/rfkill.h conflict! +'R' 00-1F linux/random.h conflict! +'R' 01 linux/rfkill.h conflict! 'R' C0-DF net/bluetooth/rfcomm.h 'R' E0 uapi/linux/fsl_mc.h -'S' all linux/cdrom.h conflict! -'S' 80-81 scsi/scsi_ioctl.h conflict! -'S' 82-FF scsi/scsi.h conflict! -'S' 00-7F sound/asequencer.h conflict! -'T' all linux/soundcard.h conflict! -'T' 00-AF sound/asound.h conflict! -'T' all arch/x86/include/asm/ioctls.h conflict! -'T' C0-DF linux/if_tun.h conflict! -'U' all sound/asound.h conflict! -'U' 00-CF linux/uinput.h conflict! +'S' all linux/cdrom.h conflict! +'S' 80-81 scsi/scsi_ioctl.h conflict! +'S' 82-FF scsi/scsi.h conflict! +'S' 00-7F sound/asequencer.h conflict! +'T' all linux/soundcard.h conflict! +'T' 00-AF sound/asound.h conflict! +'T' all arch/x86/include/asm/ioctls.h conflict! +'T' C0-DF linux/if_tun.h conflict! +'U' all sound/asound.h conflict! +'U' 00-CF linux/uinput.h conflict! 'U' 00-EF linux/usbdevice_fs.h 'U' C0-CF drivers/bluetooth/hci_uart.h -'V' all linux/vt.h conflict! -'V' all linux/videodev2.h conflict! -'V' C0 linux/ivtvfb.h conflict! -'V' C0 linux/ivtv.h conflict! -'V' C0 media/si4713.h conflict! -'W' 00-1F linux/watchdog.h conflict! -'W' 00-1F linux/wanrouter.h conflict! (pre 3.9) -'W' 00-3F sound/asound.h conflict! +'V' all linux/vt.h conflict! +'V' all linux/videodev2.h conflict! +'V' C0 linux/ivtvfb.h conflict! +'V' C0 linux/ivtv.h conflict! +'V' C0 media/si4713.h conflict! +'W' 00-1F linux/watchdog.h conflict! +'W' 00-1F linux/wanrouter.h conflict! (pre 3.9) +'W' 00-3F sound/asound.h conflict! 'W' 40-5F drivers/pci/switch/switchtec.c 'W' 60-61 linux/watch_queue.h -'X' all fs/xfs/xfs_fs.h, conflict! +'X' all fs/xfs/xfs_fs.h, conflict! fs/xfs/linux-2.6/xfs_ioctl32.h, include/linux/falloc.h, linux/fs.h, -'X' all fs/ocfs2/ocfs_fs.h conflict! -'X' 01 linux/pktcdvd.h conflict! +'X' all fs/ocfs2/ocfs_fs.h conflict! +'X' 01 linux/pktcdvd.h conflict! 'Z' 14-15 drivers/message/fusion/mptctl.h -'[' 00-3F linux/usb/tmc.h USB Test and Measurement Devices - <mailto:[email protected]> -'a' all linux/atm*.h, linux/sonet.h ATM on linux - <http://lrcwww.epfl.ch/> -'a' 00-0F drivers/crypto/qat/qat_common/adf_cfg_common.h conflict! qat driver -'b' 00-FF conflict! bit3 vme host bridge - <mailto:[email protected]> -'b' 00-0F linux/dma-buf.h conflict! -'c' 00-7F linux/comstats.h conflict! -'c' 00-7F linux/coda.h conflict! -'c' 00-1F linux/chio.h conflict! -'c' 80-9F arch/s390/include/asm/chsc.h conflict! +'[' 00-3F linux/usb/tmc.h USB Test and Measurement Devices + <mailto:[email protected]> +'a' all linux/atm*.h, linux/sonet.h ATM on linux + <http://lrcwww.epfl.ch/> +'a' 00-0F drivers/crypto/qat/qat_common/adf_cfg_common.h conflict! qat driver +'b' 00-FF conflict! bit3 vme host bridge + <mailto:[email protected]> +'b' 00-0F linux/dma-buf.h conflict! +'c' 00-7F linux/comstats.h conflict! +'c' 00-7F linux/coda.h conflict! +'c' 00-1F linux/chio.h conflict! +'c' 80-9F arch/s390/include/asm/chsc.h conflict! 'c' A0-AF arch/x86/include/asm/msr.h conflict! -'d' 00-FF linux/char/drm/drm.h conflict! -'d' 02-40 pcmcia/ds.h conflict! +'d' 00-FF linux/char/drm/drm.h conflict! +'d' 02-40 pcmcia/ds.h conflict! 'd' F0-FF linux/digi1.h -'e' all linux/digi1.h conflict! -'f' 00-1F linux/ext2_fs.h conflict! -'f' 00-1F linux/ext3_fs.h conflict! -'f' 00-0F fs/jfs/jfs_dinode.h conflict! -'f' 00-0F fs/ext4/ext4.h conflict! -'f' 00-0F linux/fs.h conflict! -'f' 00-0F fs/ocfs2/ocfs2_fs.h conflict! +'e' all linux/digi1.h conflict! +'f' 00-1F linux/ext2_fs.h conflict! +'f' 00-1F linux/ext3_fs.h conflict! +'f' 00-0F fs/jfs/jfs_dinode.h conflict! +'f' 00-0F fs/ext4/ext4.h conflict! +'f' 00-0F linux/fs.h conflict! +'f' 00-0F fs/ocfs2/ocfs2_fs.h conflict! 'f' 13-27 linux/fscrypt.h 'f' 81-8F linux/fsverity.h 'g' 00-0F linux/usb/gadgetfs.h 'g' 20-2F linux/usb/g_printer.h -'h' 00-7F conflict! Charon filesystem - <mailto:[email protected]> -'h' 00-1F linux/hpet.h conflict! +'h' 00-7F conflict! Charon filesystem + <mailto:[email protected]> +'h' 00-1F linux/hpet.h conflict! 'h' 80-8F fs/hfsplus/ioctl.c -'i' 00-3F linux/i2o-dev.h conflict! -'i' 0B-1F linux/ipmi.h conflict! +'i' 00-3F linux/i2o-dev.h conflict! +'i' 0B-1F linux/ipmi.h conflict! 'i' 80-8F linux/i8k.h -'i' 90-9F `linux/iio/*.h` IIO +'i' 90-9F `linux/iio/*.h` IIO 'j' 00-3F linux/joystick.h -'k' 00-0F linux/spi/spidev.h conflict! -'k' 00-05 video/kyro.h conflict! -'k' 10-17 linux/hsi/hsi_char.h HSI character device -'l' 00-3F linux/tcfs_fs.h transparent cryptographic file system - <http://web.archive.org/web/%2A/http://mikonos.dia.unisa.it/tcfs> -'l' 40-7F linux/udf_fs_i.h in development: - <https://github.com/pali/udftools> -'m' 00-09 linux/mmtimer.h conflict! -'m' all linux/mtio.h conflict! -'m' all linux/soundcard.h conflict! -'m' all linux/synclink.h conflict! -'m' 00-19 drivers/message/fusion/mptctl.h conflict! -'m' 00 drivers/scsi/megaraid/megaraid_ioctl.h conflict! +'k' 00-0F linux/spi/spidev.h conflict! +'k' 00-05 video/kyro.h conflict! +'k' 10-17 linux/hsi/hsi_char.h HSI character device +'l' 00-3F linux/tcfs_fs.h transparent cryptographic file system + <http://web.archive.org/web/%2A/http://mikonos.dia.unisa.it/tcfs> +'l' 40-7F linux/udf_fs_i.h in development: + <https://github.com/pali/udftools> +'m' 00-09 linux/mmtimer.h conflict! +'m' all linux/mtio.h conflict! +'m' all linux/soundcard.h conflict! +'m' all linux/synclink.h conflict! +'m' 00-19 drivers/message/fusion/mptctl.h conflict! +'m' 00 drivers/scsi/megaraid/megaraid_ioctl.h conflict! 'n' 00-7F linux/ncp_fs.h and fs/ncpfs/ioctl.c -'n' 80-8F uapi/linux/nilfs2_api.h NILFS2 -'n' E0-FF linux/matroxfb.h matroxfb -'o' 00-1F fs/ocfs2/ocfs2_fs.h OCFS2 -'o' 00-03 mtd/ubi-user.h conflict! (OCFS2 and UBI overlaps) -'o' 40-41 mtd/ubi-user.h UBI -'o' 01-A1 `linux/dvb/*.h` DVB -'p' 00-0F linux/phantom.h conflict! (OpenHaptics needs this) -'p' 00-1F linux/rtc.h conflict! +'n' 80-8F uapi/linux/nilfs2_api.h NILFS2 +'n' E0-FF linux/matroxfb.h matroxfb +'o' 00-1F fs/ocfs2/ocfs2_fs.h OCFS2 +'o' 00-03 mtd/ubi-user.h conflict! (OCFS2 and UBI overlaps) +'o' 40-41 mtd/ubi-user.h UBI +'o' 01-A1 `linux/dvb/*.h` DVB +'p' 00-0F linux/phantom.h conflict! (OpenHaptics needs this) +'p' 00-1F linux/rtc.h conflict! 'p' 40-7F linux/nvram.h -'p' 80-9F linux/ppdev.h user-space parport - <mailto:[email protected]> -'p' A1-A5 linux/pps.h LinuxPPS - <mailto:[email protected]> +'p' 80-9F linux/ppdev.h user-space parport + <mailto:[email protected]> +'p' A1-A5 linux/pps.h LinuxPPS + <mailto:[email protected]> 'q' 00-1F linux/serio.h -'q' 80-FF linux/telephony.h Internet PhoneJACK, Internet LineJACK - linux/ixjuser.h <http://web.archive.org/web/%2A/http://www.quicknet.net> +'q' 80-FF linux/telephony.h Internet PhoneJACK, Internet LineJACK + linux/ixjuser.h <http://web.archive.org/web/%2A/http://www.quicknet.net> 'r' 00-1F linux/msdos_fs.h and fs/fat/dir.c 's' all linux/cdk.h 't' 00-7F linux/ppp-ioctl.h 't' 80-8F linux/isdn_ppp.h -'t' 90-91 linux/toshiba.h toshiba and toshiba_acpi SMM -'u' 00-1F linux/smb_fs.h gone -'u' 20-3F linux/uvcvideo.h USB video class host driver -'u' 40-4f linux/udmabuf.h userspace dma-buf misc device -'v' 00-1F linux/ext2_fs.h conflict! -'v' 00-1F linux/fs.h conflict! -'v' 00-0F linux/sonypi.h conflict! -'v' 00-0F media/v4l2-subdev.h conflict! -'v' 20-27 arch/powerpc/include/uapi/asm/vas-api.h VAS API -'v' C0-FF linux/meye.h conflict! -'w' all CERN SCI driver -'y' 00-1F packet based user level communications - <mailto:[email protected]> -'z' 00-3F CAN bus card conflict! - <mailto:[email protected]> -'z' 40-7F CAN bus card conflict! - <mailto:[email protected]> -'z' 10-4F drivers/s390/crypto/zcrypt_api.h conflict! +'t' 90-91 linux/toshiba.h toshiba and toshiba_acpi SMM +'u' 00-1F linux/smb_fs.h gone +'u' 20-3F linux/uvcvideo.h USB video class host driver +'u' 40-4f linux/udmabuf.h userspace dma-buf misc device +'v' 00-1F linux/ext2_fs.h conflict! +'v' 00-1F linux/fs.h conflict! +'v' 00-0F linux/sonypi.h conflict! +'v' 00-0F media/v4l2-subdev.h conflict! +'v' 20-27 arch/powerpc/include/uapi/asm/vas-api.h VAS API +'v' C0-FF linux/meye.h conflict! +'w' all CERN SCI driver +'y' 00-1F packet based user level communications + <mailto:[email protected]> +'z' 00-3F CAN bus card conflict! + <mailto:[email protected]> +'z' 40-7F CAN bus card conflict! + <mailto:[email protected]> +'z' 10-4F drivers/s390/crypto/zcrypt_api.h conflict! '|' 00-7F linux/media.h 0x80 00-1F linux/fb.h 0x81 00-1F linux/vduse.h 0x89 00-06 arch/x86/include/asm/sockios.h 0x89 0B-DF linux/sockios.h -0x89 E0-EF linux/sockios.h SIOCPROTOPRIVATE range -0x89 F0-FF linux/sockios.h SIOCDEVPRIVATE range +0x89 E0-EF linux/sockios.h SIOCPROTOPRIVATE range +0x89 F0-FF linux/sockios.h SIOCDEVPRIVATE range 0x8B all linux/wireless.h -0x8C 00-3F WiNRADiO driver - <http://www.winradio.com.au/> +0x8C 00-3F WiNRADiO driver + <http://www.winradio.com.au/> 0x90 00 drivers/cdrom/sbpcd.h 0x92 00-0F drivers/usb/mon/mon_bin.c 0x93 60-7F linux/auto_fs.h -0x94 all fs/btrfs/ioctl.h Btrfs filesystem - and linux/fs.h some lifted to vfs/generic -0x97 00-7F fs/ceph/ioctl.h Ceph file system -0x99 00-0F 537-Addinboard driver - <mailto:[email protected]> -0xA0 all linux/sdp/sdp.h Industrial Device Project - <mailto:[email protected]> -0xA1 0 linux/vtpm_proxy.h TPM Emulator Proxy Driver -0xA2 all uapi/linux/acrn.h ACRN hypervisor -0xA3 80-8F Port ACL in development: - <mailto:[email protected]> +0x94 all fs/btrfs/ioctl.h Btrfs filesystem + and linux/fs.h some lifted to vfs/generic +0x97 00-7F fs/ceph/ioctl.h Ceph file system +0x99 00-0F 537-Addinboard driver + <mailto:[email protected]> +0xA0 all linux/sdp/sdp.h Industrial Device Project + <mailto:[email protected]> +0xA1 0 linux/vtpm_proxy.h TPM Emulator Proxy Driver +0xA2 all uapi/linux/acrn.h ACRN hypervisor +0xA3 80-8F Port ACL in development: + <mailto:[email protected]> 0xA3 90-9F linux/dtlk.h -0xA4 00-1F uapi/linux/tee.h Generic TEE subsystem -0xA4 00-1F uapi/asm/sgx.h <mailto:[email protected]> -0xA5 01-05 linux/surface_aggregator/cdev.h Microsoft Surface Platform System Aggregator - <mailto:[email protected]> -0xA5 20-2F linux/surface_aggregator/dtx.h Microsoft Surface DTX driver - <mailto:[email protected]> +0xA4 00-1F uapi/linux/tee.h Generic TEE subsystem +0xA4 00-1F uapi/asm/sgx.h <mailto:[email protected]> +0xA5 01-05 linux/surface_aggregator/cdev.h Microsoft Surface Platform System Aggregator + <mailto:[email protected]> +0xA5 20-2F linux/surface_aggregator/dtx.h Microsoft Surface DTX driver + <mailto:[email protected]> 0xAA 00-3F linux/uapi/linux/userfaultfd.h 0xAB 00-1F linux/nbd.h 0xAC 00-1F linux/raw.h -0xAD 00 Netfilter device in development: - <mailto:[email protected]> -0xAE 00-1F linux/kvm.h Kernel-based Virtual Machine - <mailto:[email protected]> -0xAE 40-FF linux/kvm.h Kernel-based Virtual Machine - <mailto:[email protected]> -0xAE 20-3F linux/nitro_enclaves.h Nitro Enclaves -0xAF 00-1F linux/fsl_hypervisor.h Freescale hypervisor -0xB0 all RATIO devices in development: - <mailto:[email protected]> -0xB1 00-1F PPPoX - <mailto:[email protected]> +0xAD 00 Netfilter device in development: + <mailto:[email protected]> +0xAE 00-1F linux/kvm.h Kernel-based Virtual Machine + <mailto:[email protected]> +0xAE 40-FF linux/kvm.h Kernel-based Virtual Machine + <mailto:[email protected]> +0xAE 20-3F linux/nitro_enclaves.h Nitro Enclaves +0xAF 00-1F linux/fsl_hypervisor.h Freescale hypervisor +0xB0 all RATIO devices in development: + <mailto:[email protected]> +0xB1 00-1F PPPoX + <mailto:[email protected]> 0xB3 00 linux/mmc/ioctl.h -0xB4 00-0F linux/gpio.h <mailto:[email protected]> -0xB5 00-0F uapi/linux/rpmsg.h <mailto:[email protected]> +0xB4 00-0F linux/gpio.h <mailto:[email protected]> +0xB5 00-0F uapi/linux/rpmsg.h <mailto:[email protected]> 0xB6 all linux/fpga-dfl.h -0xB7 all uapi/linux/remoteproc_cdev.h <mailto:[email protected]> -0xB7 all uapi/linux/nsfs.h <mailto:Andrei Vagin <[email protected]>> +0xB7 all uapi/linux/remoteproc_cdev.h <mailto:[email protected]> +0xB7 all uapi/linux/nsfs.h <mailto:Andrei Vagin <[email protected]>> 0xC0 00-0F linux/usb/iowarrior.h 0xCA 00-0F uapi/misc/cxl.h 0xCA 10-2F uapi/misc/ocxl.h 0xCA 80-BF uapi/scsi/cxlflash_ioctl.h -0xCB 00-1F CBM serial IEC bus in development: - <mailto:[email protected]> -0xCC 00-0F drivers/misc/ibmvmc.h pseries VMC driver +0xCB 00-1F CBM serial IEC bus in development: + <mailto:[email protected]> +0xCC 00-0F drivers/misc/ibmvmc.h pseries VMC driver 0xCD 01 linux/reiserfs_fs.h -0xCE 01-02 uapi/linux/cxl_mem.h Compute Express Link Memory Devices +0xCE 01-02 uapi/linux/cxl_mem.h Compute Express Link Memory Devices 0xCF 02 fs/smb/client/cifs_ioctl.h 0xDB 00-0F drivers/char/mwave/mwavepub.h -0xDD 00-3F ZFCP device driver see drivers/s390/scsi/ - <mailto:[email protected]> +0xDD 00-3F ZFCP device driver see drivers/s390/scsi/ + <mailto:[email protected]> 0xE5 00-3F linux/fuse.h -0xEC 00-01 drivers/platform/chrome/cros_ec_dev.h ChromeOS EC driver -0xEE 00-09 uapi/linux/pfrut.h Platform Firmware Runtime Update and Telemetry -0xF3 00-3F drivers/usb/misc/sisusbvga/sisusb.h sisfb (in development) - <mailto:[email protected]> -0xF6 all LTTng Linux Trace Toolkit Next Generation - <mailto:[email protected]> -0xF8 all arch/x86/include/uapi/asm/amd_hsmp.h AMD HSMP EPYC system management interface driver - <mailto:[email protected]> +0xEC 00-01 drivers/platform/chrome/cros_ec_dev.h ChromeOS EC driver +0xEE 00-09 uapi/linux/pfrut.h Platform Firmware Runtime Update and Telemetry +0xF3 00-3F drivers/usb/misc/sisusbvga/sisusb.h sisfb (in development) + <mailto:[email protected]> +0xF6 all LTTng Linux Trace Toolkit Next Generation + <mailto:[email protected]> +0xF8 all arch/x86/include/uapi/asm/amd_hsmp.h AMD HSMP EPYC system management interface driver + <mailto:[email protected]> 0xFD all linux/dm-ioctl.h 0xFE all linux/isst_if.h -==== ===== ======================================================= ================================================================ +==== ===== ========================================================= ================================================================
Greg Kroah-Hartman
maintainerPATCH 173/175 crypto: qat - Replace kzalloc() + copy_from_user() with memdup_user()
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
[ Upstream commit 1e26339703e2afd397037defa798682b2b93dcc0 ]
Replace kzalloc() followed by copy_from_user() with memdup_user() to improve and simplify adf_ctl_alloc_resources(). memdup_user() returns either -ENOMEM or -EFAULT (instead of -EIO) if an error occurs.
Remove the unnecessary device id initialization, since memdup_user() (like copy_from_user()) immediately overwrites it.
No functional changes intended other than returning the more idiomatic error code -EFAULT.
Stable-dep-of: d237230728c5 ("crypto: qat - remove unused character device and IOCTLs")
--- drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-)
drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c +3 -10
@@ -91,17 +91,10 @@ static int adf_ctl_alloc_resources(struc {struct adf_user_cfg_ctl_data *cfg_data; - cfg_data =kzalloc (sizeof (*cfg_data),GFP_KERNEL ); -if (!cfg_data) -return -ENOMEM ; - -/* Initialize device id to NO DEVICE as 0 is a valid device id */ - cfg_data->device_id =ADF_CFG_NO_DEVICE ; - -if (copy_from_user (cfg_data, (void __user *)arg,sizeof (*cfg_data))) { + cfg_data =memdup_user ((void __user *)arg,sizeof (*cfg_data)); +if (IS_ERR (cfg_data)) {pr_err ("QAT: failed to copy from user cfg_data.\n" ); -kfree (cfg_data); -return -EIO ; +return PTR_ERR (cfg_data); } *ctl_data = cfg_data;
Greg Kroah-Hartman
maintainerPATCH 174/175 crypto: qat - Return pointer directly in adf_ctl_alloc_resources
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu <[email protected]>
[ Upstream commit 5ce9891ea928208a915411ce8227f8c3e37e5ad9 ]
Returning values through arguments is confusing and that has upset the compiler with the recent change to memdup_user:
../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c: In function ‘adf_ctl_ioctl’:../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:308:26: warning: ‘ctl_data’ may be used uninitialized [-Wmaybe-uninitialized]
308 | ctl_data->device_id);
| ^~../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:294:39: note: ‘ctl_data’ was declared here
294 | struct adf_user_cfg_ctl_data *ctl_data;
| ^~~~~~~~
In function ‘adf_ctl_ioctl_dev_stop’,
inlined from ‘adf_ctl_ioctl’ at ../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:386:9:../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:273:48: warning: ‘ctl_data’ may be used uninitialized [-Wmaybe-uninitialized]
273 | ret = adf_ctl_is_device_in_use(ctl_data->device_id);
| ~~~~~~~~^~~~~~~~~~~../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c: In function ‘adf_ctl_ioctl’:../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:261:39: note: ‘ctl_data’ was declared here
261 | struct adf_user_cfg_ctl_data *ctl_data;
| ^~~~~~~~
In function ‘adf_ctl_ioctl_dev_config’,
inlined from ‘adf_ctl_ioctl’ at ../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:382:9:../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:192:54: warning: ‘ctl_data’ may be used uninitialized [-Wmaybe-uninitialized]
192 | accel_dev = adf_devmgr_get_dev_by_id(ctl_data->device_id);
| ~~~~~~~~^~~~~~~~~~~../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c: In function ‘adf_ctl_ioctl’:../drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c:185:39: note: ‘ctl_data’ was declared here
185 | struct adf_user_cfg_ctl_data *ctl_data;
| ^~~~~~~~
Fix this by returning the pointer directly.
Stable-dep-of: d237230728c5 ("crypto: qat - remove unused character device and IOCTLs")
--- drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c | 31 +++++++++------------- 1 file changed, 13 insertions(+), 18 deletions(-)
drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c +13 -18
@@ -86,19 +86,14 @@ err_chrdev_unreg:return -EFAULT ; } -static int adf_ctl_alloc_resources (struct adf_user_cfg_ctl_data **ctl_data, -unsigned long arg) +static struct adf_user_cfg_ctl_data *adf_ctl_alloc_resources (unsigned long arg) {struct adf_user_cfg_ctl_data *cfg_data; cfg_data =memdup_user ((void __user *)arg,sizeof (*cfg_data)); -if (IS_ERR (cfg_data)) { +if (IS_ERR (cfg_data))pr_err ("QAT: failed to copy from user cfg_data.\n" ); -return PTR_ERR (cfg_data); - } - - *ctl_data = cfg_data; -return 0 ; +return cfg_data; } static int adf_add_key_value_data(struct adf_accel_dev *accel_dev,
@@ -178,13 +173,13 @@ out_err:static int adf_ctl_ioctl_dev_config (struct file *fp,unsigned int cmd,unsigned long arg) { -int ret;struct adf_user_cfg_ctl_data *ctl_data;struct adf_accel_dev *accel_dev; +int ret =0 ; - ret =adf_ctl_alloc_resources (&ctl_data, arg); -if (ret) -return ret; + ctl_data =adf_ctl_alloc_resources (arg); +if (IS_ERR (ctl_data)) +return PTR_ERR (ctl_data); accel_dev =adf_devmgr_get_dev_by_id (ctl_data->device_id);if (!accel_dev) {
@@ -257,9 +252,9 @@ static int adf_ctl_ioctl_dev_stop(structint ret;struct adf_user_cfg_ctl_data *ctl_data; - ret =adf_ctl_alloc_resources (&ctl_data, arg); -if (ret) -return ret; + ctl_data =adf_ctl_alloc_resources (arg); +if (IS_ERR (ctl_data)) +return PTR_ERR (ctl_data);if (adf_devmgr_verify_id (ctl_data->device_id)) {pr_err ("QAT: Device %d not found\n" , ctl_data->device_id);
@@ -291,9 +286,9 @@ static int adf_ctl_ioctl_dev_start(strucstruct adf_user_cfg_ctl_data *ctl_data;struct adf_accel_dev *accel_dev; - ret =adf_ctl_alloc_resources (&ctl_data, arg); -if (ret) -return ret; + ctl_data =adf_ctl_alloc_resources (arg); +if (IS_ERR (ctl_data)) +return PTR_ERR (ctl_data); ret = -ENODEV ; accel_dev =adf_devmgr_get_dev_by_id (ctl_data->device_id);
Greg Kroah-Hartman
maintainerPATCH 175/175 crypto: qat - remove unused character device and IOCTLs
In reply to Greg Kroah-Hartman6.6-stable review patch. If anyone has any objections, please let me know.
------------------
From: Giovanni Cabiddu <[email protected]>
[ Upstream commit d237230728c567297f2f98b425d63156ab2ed17f ]
The QAT driver exposes a character device (qat_adf_ctl) with IOCTLs for device configuration, start, stop, status query and enumeration. These IOCTLs are not part of any public uAPI header and have no known in-tree or out-of-tree users. Device lifecycle is already managed via sysfs.
The ioctl interface also increases the attack surface and is the subject of a number of bug reports.
Remove the character device, the IOCTL definitions, and the related data structures (adf_dev_status_info, adf_user_cfg_key_val, adf_user_cfg_section, adf_user_cfg_ctl_data). Drop the now-unused adf_cfg_user.h header and strip adf_ctl_drv.c down to the minimal module_init/module_exit hooks for workqueue, AER, and crypto/compression algorithm registration.
Clean up leftover dead code that was only reachable from the removed IOCTL paths: adf_cfg_del_all(), adf_devmgr_verify_id(), adf_devmgr_get_num_dev(), adf_devmgr_get_dev_by_id(), adf_get_vf_real_id() and the unused ADF_CFG macros.
Additionally, drop the entry associated to QAT IOCTLs in ioctl-number.rst.
--- Documentation/userspace-api/ioctl/ioctl-number.rst | 1 drivers/crypto/intel/qat/qat_common/adf_cfg_common.h | 32 - drivers/crypto/intel/qat/qat_common/adf_cfg_user.h | 38 - drivers/crypto/intel/qat/qat_common/adf_common_drv.h | 3 drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c | 401 ------------------- drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c | 70 --- 6 files changed, 1 insertion(+), 544 deletions(-) delete mode 100644 drivers/crypto/intel/qat/qat_common/adf_cfg_user.h
Documentation/userspace-api/ioctl/ioctl-number.rst +0 -1
@@ -219,7 +219,6 @@ Code Seq# Include File <mailto:[email protected]> 'a' all linux/atm*.h, linux/sonet.h ATM on linux <http://lrcwww.epfl.ch/> -'a' 00-0F drivers/crypto/qat/qat_common/adf_cfg_common.h conflict! qat driver 'b' 00-FF conflict! bit3 vme host bridge <mailto:[email protected]> 'b' 00-0F linux/dma-buf.h conflict!
drivers/crypto/intel/qat/qat_common/adf_cfg_common.h +0 -32
@@ -4,18 +4,11 @@#define ADF_CFG_COMMON_H_ #include <linux/types.h> -#include <linux/ioctl.h> #define ADF_CFG_MAX_STR_LEN 64#define ADF_CFG_MAX_KEY_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN#define ADF_CFG_MAX_VAL_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN#define ADF_CFG_MAX_SECTION_LEN_IN_BYTES ADF_CFG_MAX_STR_LEN -#define ADF_CFG_BASE_DEC 10 -#define ADF_CFG_BASE_HEX 16 -#define ADF_CFG_ALL_DEVICES 0xFE -#define ADF_CFG_NO_DEVICE 0xFF -#define ADF_CFG_AFFINITY_WHATEVER 0xFF -#define MAX_DEVICE_NAME_SIZE 32#define ADF_MAX_DEVICES (32 * 32)#define ADF_DEVS_ARRAY_SIZE BITS_TO_LONGS(ADF_MAX_DEVICES)
@@ -48,29 +41,4 @@ enum adf_device_type {DEV_C3XXXVF , DEV_4XXX, }; - -struct adf_dev_status_info { -enum adf_device_type type; -__u32 accel_id; -__u32 instance_id; -__u8 num_ae; -__u8 num_accel; -__u8 num_logical_accel; -__u8 banks_per_accel; -__u8 state; -__u8 bus; -__u8 dev; -__u8 fun; -char name[MAX_DEVICE_NAME_SIZE ]; -}; - -#define ADF_CTL_IOC_MAGIC 'a' -#define IOCTL_CONFIG_SYS_RESOURCE_PARAMETERS _IOW(ADF_CTL_IOC_MAGIC, 0, \ - struct adf_user_cfg_ctl_data) -#define IOCTL_STOP_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 1, \ - struct adf_user_cfg_ctl_data) -#define IOCTL_START_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 2, \ - struct adf_user_cfg_ctl_data) -#define IOCTL_STATUS_ACCEL_DEV _IOW(ADF_CTL_IOC_MAGIC, 3, __u32) -#define IOCTL_GET_NUM_DEVICES _IOW(ADF_CTL_IOC_MAGIC, 4, __s32)#endif
drivers/crypto/intel/qat/qat_common/adf_cfg_user.h deleted +0 -38
@@ -1,38 +0,0 @@ -/* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0-only) */ -/* Copyright(c) 2014 - 2020 Intel Corporation */ -#ifndef ADF_CFG_USER_H_ -#define ADF_CFG_USER_H_ - -#include "adf_cfg_common.h" -#include "adf_cfg_strings.h" - -struct adf_user_cfg_key_val { -char key[ADF_CFG_MAX_KEY_LEN_IN_BYTES ]; -char val[ADF_CFG_MAX_VAL_LEN_IN_BYTES ]; -union { -struct adf_user_cfg_key_val *next; -__u64 padding3; - }; -enum adf_cfg_val_type type; -} __packed; - -struct adf_user_cfg_section { -char name[ADF_CFG_MAX_SECTION_LEN_IN_BYTES ]; -union { -struct adf_user_cfg_key_val *params; -__u64 padding1; - }; -union { -struct adf_user_cfg_section *next; -__u64 padding3; - }; -} __packed; - -struct adf_user_cfg_ctl_data { -union { -struct adf_user_cfg_section *config_section; -__u64 padding; - }; -__u8 device_id; -} __packed; -#endif
drivers/crypto/intel/qat/qat_common/adf_common_drv.h +0 -3
@@ -65,11 +65,8 @@ int adf_devmgr_add_dev(struct adf_accel_void adf_devmgr_rm_dev (struct adf_accel_dev *accel_dev,struct adf_accel_dev *pf);struct list_head *adf_devmgr_get_head (void ); -struct adf_accel_dev *adf_devmgr_get_dev_by_id (u32 id);struct adf_accel_dev *adf_devmgr_get_first (void );struct adf_accel_dev *adf_devmgr_pci_to_accel_dev (struct pci_dev *pci_dev); -int adf_devmgr_verify_id (u32 id); -void adf_devmgr_get_num_dev (u32 *num);int adf_devmgr_in_reset (struct adf_accel_dev *accel_dev);int adf_dev_started (struct adf_accel_dev *accel_dev);int adf_dev_restarting_notify (struct adf_accel_dev *accel_dev);
drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c +1 -400
430 lines not on this page · raw message
drivers/crypto/intel/qat/qat_common/adf_dev_mgr.c +0 -70
82 lines not on this page · raw message
# Librecast Test Results
020/020 [ OK ] liblcrq
010/010 [ OK ] libmld
120/120 [ OK ] liblibrecast
CPU/kernel: Linux auntie 6.6.144-rc1-g383d9611bec7 #1 SMP PREEMPT_DYNAMIC Thu Jul 2 19:35:43 -00 2026 x86_64 AMD Ryzen 9 9950X 16-Core Processor AuthenticAMD GNU/Linux
Am 02.07.2026 um 18:18 schrieb Greg Kroah-Hartman:
Quoted 4 lines
This is the start of the stable review cycle for the 6.6.144 release. There are 175 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Builds, boots and works on my 2-socket Ivy Bridge Xeon E5-2697 v2 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 8 lines · On Thu, 02 Jul 2026 18:18:21 +0200 Greg Kroah-Hartman…
This is the start of the stable review cycle for the 6.6.144 release. There are 175 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 Sat, 04 Jul 2026 15:50:58 +0000. Anything received after that time might be too late.
Boot-tested under QEMU for Rust x86_64:
Thanks!
Cheers,
Miguel
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.6.144 release. There are 175 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 Sat, 04 Jul 2026 15:50:58 +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.6.144-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.6.y
and the diffstat can be found below.thanks,
greg k-h
Built and booted successfully on RISC-V RV64 (HiFive Unmatched).
Quoted 7 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.6.144 release. There are 175 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 Sat, 04 Jul 2026 15:50:58 +0000. Anything received after that time might be too late.
test_progs, test_progs-no_alu32, test_progs-cpuv4, test_maps, test_verifier in BPF selftests all passes[1] on both x86_64 and aarch64.
1: https://github.com/kernel-patches/linux-stable/actions/runs/28642644980
[...]
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.6.144 release. There are 175 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.
Hi,
Build failed in loongarch arch, which resolve in link:
https://lore.kernel.org/stable/[email protected]/
https://lore.kernel.org/stable/2026070318-monotone-mug-74d6@gregkh/
arch/loongarch/kernel/smp.c: In function ‘stop_this_cpu’:arch/loongarch/kernel/smp.c:616:9: error: implicit declaration of function ‘rcutree_report_cpu_dead’; did you mean ‘rcutree_prepare_cpu’? [-Werror=implicit-function-declaration]
616 | rcutree_report_cpu_dead();
| ^~~~~~~~~~~~~~~~~~~~~~~
| rcutree_prepare_cpuBuild tested in our x86,arm64,riscv config successfully without error.
BRs
Wentao Guan
Log:
Linux version 6.6.144-rc1-arm64-desktop-hwe-g383d9611bec7 (guanwentao@uos-PC) (aarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP PREEMPT Linux version 6.6.144-rc1-arm64-desktop-hwe-g383d9611bec7 (guanwentao@uos-PC) (aarch64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #2 SMP PREEMPT Fri Jul 3 12:05:13 CST 2026 Linux version 6.6.144-rc1-riscv64-desktop-hwe+ (guanwentao@uos-PC) (riscv64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP
Linux version 6.6.144-rc1-riscv64-desktop-hwe+ (guanwentao@uos-PC) (riscv64-linux-gnu-gcc-12 (Deepin 12.3.0-17deepin8) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #4 SMP Fri Jul 3 15:53:55 CST 2026 Linux version 6.6.144-rc1-amd64-desktop-hwe-g383d9611bec7 (guanwentao@uos-PC) (gcc (Deepin 12.3.0-17deepin15) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) # SMP PREEMPT_DYNAMIC
Linux version 6.6.144-rc1-amd64-desktop-hwe-g383d9611bec7 (guanwentao@uos-PC) (gcc (Deepin 12.3.0-17deepin15) 12.3.0, GNU ld (GNU Binutils for Deepin) 2.41) #1 SMP PREEMPT_DYNAMIC Fri Jul 3 11:47:09 CST 2026
Greg KH
maintainerQuoted 6 lines · Wentao Guan
Hi,
Build failed in loongarch arch, which resolve in link:
https://lore.kernel.org/stable/[email protected]/
https://lore.kernel.org/stable/2026070318-monotone-mug-74d6@gregkh/
Quoted 7 lines
arch/loongarch/kernel/smp.c: In function ‘stop_this_cpu’:arch/loongarch/kernel/smp.c:616:9: error: implicit declaration of function ‘rcutree_report_cpu_dead’; did you mean ‘rcutree_prepare_cpu’? [-Werror=implicit-function-declaration]616 | rcutree_report_cpu_dead(); | ^~~~~~~~~~~~~~~~~~~~~~~ | rcutree_prepare_cpuBuild tested in our x86,arm64,riscv config successfully without error.
Offending commit already dropped.
thans,
greg k-h
Hi!
Quoted 4 lines
This is the start of the stable review cycle for the 6.6.144 release. There are 175 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.
https://gitlab.com/cip-project/cip-testing/linux-stable-rc-ci/-/tree/linux-6.6.y
Best regards,
Pavel
Quoted 4 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.6.144 release. There are 175 patches in this series, all will be posted as a response to this one. If anyone has any issues with these being applied, please let me know.
Quoted 9 lines · Greg Kroah-Hartman
This is the start of the stable review cycle for the 6.6.144 release. There are 175 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 Sat, 04 Jul 2026 15:50:58 +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.6.144-rc1.gzor in the git tree and branch at:
git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable-rc.gitlinux-6.6.y
and the diffstat can be found below.thanks,
greg k-h
On ARCH_BRCMSTB using 32-bit and 64-bit ARM kernels, same build failure as 6.1 for MIPS:
arch/mips/kernel/smp.c: In function 'stop_this_cpu':arch/mips/kernel/smp.c:396:2: error: implicit declaration of function 'rcutree_report_cpu_dead'; did you mean 'rcutree_prepare_cpu'? [-Werror=implicit-function-declaration]
rcutree_report_cpu_dead();
^~~~~~~~~~~~~~~~~~~~~~~
rcutree_prepare_cpu
Signature · 1 line
Florian
Sasha Levin
maintainerQuoted 10 lines · Florian Fainelli
On
ARCH_BRCMSTBusing 32-bit and 64-bit ARM kernels, same build failure as 6.1 for MIPS:
arch/mips/kernel/smp.c: In function 'stop_this_cpu':arch/mips/kernel/smp.c:396:2: error: implicit declaration of function 'rcutree_report_cpu_dead'; did you mean 'rcutree_prepare_cpu'? [-Werror=implicit-function-declaration]rcutree_report_cpu_dead(); ^~~~~~~~~~~~~~~~~~~~~~~ rcutree_prepare_cpu
The offending backport was dropped before 6.6.144 was released, so the build failure itself is gone.
That still leaves 6.6.y and 6.1.y without 9f3f3bdc6d9d ("MIPS: smp:
report dying CPU to RCU in stop_this_cpu()") while both trees already ship 91840be8f710 ("irq_work: Fix use-after-free in irq_work_single() on PREEMPT_RT"), which is what exposes the MIPS reboot hang that 9f3f3bdc6d9d fixes.
Jonas, could you send backports of 9f3f3bdc6d9d for 6.6.y and 6.1.y with that adaptation? I'd rather take the author's version than adapt it here.
Signature · 2 lines
Thanks, Sasha
Hi Sasha,
Quoted 20 lines · Sasha Levin
Quoted 10 lines · Florian Fainelli
On
ARCH_BRCMSTBusing 32-bit and 64-bit ARM kernels, same build failure as 6.1 for MIPS:
arch/mips/kernel/smp.c: In function 'stop_this_cpu':arch/mips/kernel/smp.c:396:2: error: implicit declaration of function 'rcutree_report_cpu_dead'; did you mean 'rcutree_prepare_cpu'? [-Werror=implicit-function-declaration]rcutree_report_cpu_dead(); ^~~~~~~~~~~~~~~~~~~~~~~ rcutree_prepare_cpuThe offending backport was dropped before 6.6.144 was released, so the build failure itself is gone.
That still leaves 6.6.y and 6.1.y without
9f3f3bdc6d9d("MIPS: smp:
report dying CPU to RCU instop_this_cpu()") while both trees already ship91840be8f710("irq_work: Fix use-after-free inirq_work_single()onPREEMPT_RT"), which is what exposes the MIPS reboot hang that9f3f3bdc6d9dfixes.
Quoted 4 lines
Jonas, could you send backports of
9f3f3bdc6d9dfor 6.6.y and 6.1.y with that adaptation? I'd rather take the author's version than adapt it here.
Sure, I adopted it accordingly and sent patches for 6.6.y and 6.1.y.
Best regards,
Jonas