5.10.261-rc1 review
Subsystems (4)
Greg Kroah-Hartman
maintainerPATCH 420/699 ipvs: pass parsed transport offset to state handlers
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yizhou Zhao <[email protected]>
[ Upstream commit bae7ce7bafb59e42dc0e0e2999fdd9d1cffe3866 ]
IPVS callers already parse the packet into struct ip_vs_iphdr before updating connection state. For IPv6 this records the real transport-header offset after extension headers in iph.len.
Pass this parsed transport offset through ip_vs_set_state() and the protocol state_transition() callback so protocol handlers can use the same packet context as scheduling and NAT handling. This patch only changes the common callback plumbing and adapts the protocol callback signatures; TCP and SCTP start using the value in follow-up patches.
Stable-dep-of: 2500fa3958b1 ("ipvs: use parsed transport offset in TCP state lookup")
--- include/net/ip_vs.h | 3 ++- net/netfilter/ipvs/ip_vs_core.c | 10 +++++----- net/netfilter/ipvs/ip_vs_proto_sctp.c | 3 ++- net/netfilter/ipvs/ip_vs_proto_tcp.c | 3 ++- net/netfilter/ipvs/ip_vs_proto_udp.c | 3 ++- 5 files changed, 13 insertions(+), 9 deletions(-)
include/net/ip_vs.h +2 -1
@@ -455,7 +455,8 @@ struct ip_vs_protocol {void (*state_transition)(struct ip_vs_conn *cp,int direction,const struct sk_buff *skb, -struct ip_vs_proto_data *pd); +struct ip_vs_proto_data *pd, +unsigned int iph_len);int (*register_app)(struct netns_ipvs *ipvs,struct ip_vs_app *inc);
net/netfilter/ipvs/ip_vs_core.c +5 -5
@@ -232,10 +232,10 @@ ip_vs_conn_stats(struct ip_vs_conn *cp, struct ip_vs_service *svc)static inline void ip_vs_set_state (struct ip_vs_conn *cp,int direction,const struct sk_buff *skb, -struct ip_vs_proto_data *pd) +struct ip_vs_proto_data *pd,unsigned int iph_len) {if (likely (pd->pp->state_transition)) - pd->pp->state_transition (cp, direction, skb, pd); + pd->pp->state_transition (cp, direction, skb, pd, iph_len); } static inline int
@@ -637,7 +637,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,ip_vs_in_stats (cp, skb);/* set state */ -ip_vs_set_state (cp,IP_VS_DIR_INPUT , skb, pd); +ip_vs_set_state (cp,IP_VS_DIR_INPUT , skb, pd, iph->len);/* transmit the first SYN packet */ ret = cp->packet_xmit (skb, cp, pd->pp, iph);
@@ -1320,7 +1320,7 @@ handle_response(int af, struct sk_buff *skb, struct ip_vs_proto_data *pd, after_nat:ip_vs_out_stats (cp, skb); -ip_vs_set_state (cp,IP_VS_DIR_OUTPUT , skb, pd); +ip_vs_set_state (cp,IP_VS_DIR_OUTPUT , skb, pd, iph->len); skb->ipvs_property =1 ;if (!(cp->flags &IP_VS_CONN_F_NFCT ))ip_vs_notrack (skb);
@@ -2116,7 +2116,7 @@ ip_vs_in(struct netns_ipvs *ipvs, unsigned int hooknum, struct sk_buff *skb, intIP_VS_DBG_PKT (11 , af, pp, skb, iph.off,"Incoming packet" );ip_vs_in_stats (cp, skb); -ip_vs_set_state (cp,IP_VS_DIR_INPUT , skb, pd); +ip_vs_set_state (cp,IP_VS_DIR_INPUT , skb, pd, iph.len);if (cp->packet_xmit) ret = cp->packet_xmit (skb, cp, pp, &iph);/* do not touch skb anymore */
net/netfilter/ipvs/ip_vs_proto_sctp.c +2 -1
@@ -468,7 +468,8 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,static void sctp_state_transition (struct ip_vs_conn *cp,int direction, -const struct sk_buff *skb,struct ip_vs_proto_data *pd) +const struct sk_buff *skb,struct ip_vs_proto_data *pd, +unsigned int iph_len) {spin_lock_bh (&cp->lock);set_sctp_state (pd, cp, direction, skb);
net/netfilter/ipvs/ip_vs_proto_tcp.c +2 -1
@@ -580,7 +580,8 @@ set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,static void tcp_state_transition (struct ip_vs_conn *cp,int direction,const struct sk_buff *skb, -struct ip_vs_proto_data *pd) +struct ip_vs_proto_data *pd, +unsigned int iph_len) {struct tcphdr _tcph, *th;
net/netfilter/ipvs/ip_vs_proto_udp.c +2 -1
@@ -445,7 +445,8 @@ static const char * udp_state_name(int state)static void udp_state_transition (struct ip_vs_conn *cp,int direction,const struct sk_buff *skb, -struct ip_vs_proto_data *pd) +struct ip_vs_proto_data *pd, +unsigned int iph_len) {if (unlikely (!pd)) {pr_err ("UDP no ns data\n" );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 421/699 ipvs: use parsed transport offset in TCP state lookup
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yizhou Zhao <[email protected]>
[ Upstream commit 2500fa3958b1ba51c2b065e39db1b04dfa7e23a2 ]
TCP state handling reparses the skb to find the TCP header. For IPv6 it uses sizeof(struct ipv6hdr), while the surrounding IPVS code already parsed the packet with ip_vs_fill_iph_skb() and has the real transport-header offset in iph.len.
This makes TCP state handling look at the wrong bytes when an IPv6 packet carries extension headers. Use the parsed transport offset passed down from ip_vs_set_state() when reading the TCP header.
For IPv4 and for IPv6 packets without extension headers, the passed offset matches the previous value.
--- net/netfilter/ipvs/ip_vs_proto_tcp.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
net/netfilter/ipvs/ip_vs_proto_tcp.c +1 -7
@@ -585,13 +585,7 @@ tcp_state_transition(struct ip_vs_conn *cp, int direction, {struct tcphdr _tcph, *th; -#ifdef CONFIG_IP_VS_IPV6 -int ihl = cp->af ==AF_INET ?ip_hdrlen (skb) :sizeof (struct ipv6hdr ); -#else -int ihl =ip_hdrlen (skb); -#endif - - th =skb_header_pointer (skb, ihl,sizeof (_tcph), &_tcph); + th =skb_header_pointer (skb, iph_len,sizeof (_tcph), &_tcph);if (th ==NULL )return ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 422/699 ipvs: fix PMTU for GUE/GRE tunnel ICMP errors
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yizhou Zhao <[email protected]>
[ Upstream commit 6b335af0d0d1ff44ac579d106953bf19299e5233 ]
When an ICMP Fragmentation Needed error is received for a tunneled IPVS connection, ip_vs_in_icmp() recomputes the MTU that the original packet can use by subtracting the tunnel overhead from the reported next-hop MTU.
The current code always subtracts sizeof(struct iphdr), which is only the IPIP overhead. For GUE and GRE tunnels, ipvs_udp_decap() and ipvs_gre_decap() already compute the additional tunnel header length, but that value is scoped to the decapsulation block and is lost before the ICMP_FRAG_NEEDED handling. As a result, the ICMP error sent back to the client advertises an MTU that is too large, so PMTUD can fail to converge for GUE/GRE-tunneled real servers.
With a reported next-hop MTU of 1400, a GUE tunnel currently returns 1380 to the client. The correct value is 1368:
1400 - sizeof(struct iphdr) - sizeof(struct udphdr) - sizeof(struct guehdr)
Hoist the tunnel header length into the main ip_vs_in_icmp() scope and subtract sizeof(struct iphdr) + ulen in the Fragmentation Needed path. The IPIP path keeps ulen as 0, so its existing 1400 - 20 = 1380 result is unchanged.
Stable-dep-of: 3f7a535ff0fa ("ipvs: ensure inner headers in ICMP errors are in headroom")
--- net/netfilter/ipvs/ip_vs_core.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/netfilter/ipvs/ip_vs_core.c +3 -3
@@ -1653,6 +1653,7 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,bool tunnel, new_cp = false;union nf_inet_addr *raddr;char *outer_proto ="IPIP" ; +int ulen =0 ; *related =1 ;
@@ -1717,7 +1718,6 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,/* Error for our tunnel must arrive at LOCAL_IN */ (skb_rtable(skb)->rt_flags & RTCF_LOCAL)) {__u8 iproto; -int ulen;/* Non-first fragment has no UDP/GRE header */ if (unlikely (cih->frag_off &htons (IP_OFFSET )))
@@ -1822,8 +1822,8 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,if (dest_dst) mtu =dst_mtu (dest_dst->dst_cache); } -if (mtu >68 +sizeof (struct iphdr )) - mtu -=sizeof (struct iphdr ); +if (mtu >68 +sizeof (struct iphdr ) + ulen) + mtu -=sizeof (struct iphdr ) + ulen; info =htonl (mtu); }/* Strip outer IP, ICMP and IPIP/UDP/GRE, go to IP header of
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 423/699 ipvs: ensure inner headers in ICMP errors are in headroom
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Anastasov <[email protected]>
[ Upstream commit 3f7a535ff0fa627a0132803e4c2f903ceffcbc1c ]
Sashiko points out that after stripping the outer headers with pskb_pull() we should ensure the inner IP headers in ICMP errors from tunnels are present in the skb headroom for functions like ipv4_update_pmtu(), icmp_send() and IP_VS_DBG().
Also, add more checks for the length of the inner headers.
--- net/netfilter/ipvs/ip_vs_core.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-)
net/netfilter/ipvs/ip_vs_core.c +15 -6
@@ -1653,6 +1653,7 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,bool tunnel, new_cp = false;union nf_inet_addr *raddr;char *outer_proto ="IPIP" ; +unsigned int hlen_ipip;int ulen =0 ; *related =1 ;
@@ -1690,9 +1691,10 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,/* Now find the contained IP header */ offset +=sizeof (_icmph); cih =skb_header_pointer (skb, offset,sizeof (_ciph), &_ciph); -if (cih ==NULL ) +if (!(cih && cih->version ==4 && cih->ihl >=5 ))return NF_ACCEPT ;/* The packet looks wrong, ignore */ raddr = (union nf_inet_addr *)&cih->daddr; + hlen_ipip = cih->ihl *4 ;/* Special case for errors for IPIP/UDP/GRE tunnel packets */ tunnel = false;
@@ -1708,9 +1710,9 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,/* Only for known tunnel */ if (!dest || dest->tun_type !=IP_VS_CONN_F_TUNNEL_TYPE_IPIP )return NF_ACCEPT ; - offset += cih->ihl *4 ; + offset += hlen_ipip; cih =skb_header_pointer (skb, offset,sizeof (_ciph), &_ciph); -if (cih ==NULL ) +if (!(cih && cih->version ==4 && cih->ihl >=5 ))return NF_ACCEPT ;/* The packet looks wrong, ignore */ tunnel = true; } else if ((cih->protocol == IPPROTO_UDP || /* Can be UDP encap */
@@ -1722,7 +1724,7 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,/* Non-first fragment has no UDP/GRE header */ if (unlikely (cih->frag_off &htons (IP_OFFSET )))return NF_ACCEPT ; - offset2 = offset + cih->ihl *4 ; + offset2 = offset + hlen_ipip;if (cih->protocol ==IPPROTO_UDP ) { ulen =ipvs_udp_decap (ipvs, skb, offset2,AF_INET , raddr, &iproto);
@@ -1791,6 +1793,7 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related, }if (tunnel) { +unsigned int hlen_orig = cih->ihl *4 ;__be32 info = ic->un.gateway;__u8 type = ic->type;__u8 code = ic->code;
@@ -1807,6 +1810,9 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related, goto ignore_tunnel; offset2 -= ihl +sizeof (_icmph);skb_reset_network_header (skb); +/* Ensure the IP header is present in headroom */ +if (!pskb_may_pull (skb, hlen_ipip)) + goto ignore_tunnel;IP_VS_DBG (12 ,"ICMP for %s %pI4->%pI4: mtu=%u\n" , outer_proto, &ip_hdr (skb)->saddr, &ip_hdr (skb)->daddr, mtu);
@@ -1822,8 +1828,8 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,if (dest_dst) mtu =dst_mtu (dest_dst->dst_cache); } -if (mtu >68 +sizeof (struct iphdr ) + ulen) - mtu -=sizeof (struct iphdr ) + ulen; +if (mtu >68 + hlen_ipip + ulen) + mtu -= hlen_ipip + ulen; info =htonl (mtu); }/* Strip outer IP, ICMP and IPIP/UDP/GRE, go to IP header of
@@ -1832,6 +1838,9 @@ ip_vs_in_icmp(struct netns_ipvs *ipvs, struct sk_buff *skb, int *related,if (pskb_pull (skb, offset2) ==NULL ) goto ignore_tunnel;skb_reset_network_header (skb); +/* Ensure the IP header is present in headroom */ +if (!pskb_may_pull (skb, hlen_orig)) + goto ignore_tunnel;IP_VS_DBG (12 ,"Sending ICMP for %pI4->%pI4: t=%u, c=%u, i=%u\n" , &ip_hdr (skb)->saddr, &ip_hdr (skb)->daddr, type, code,ntohl (info));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 424/699 dm era: fix NULL pointer dereference in metadata_open()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cao Guanghui <[email protected]>
[ Upstream commit 9ae672606c17891d90b282e3490b817620549599 ]
metadata_open() returns NULL when kzalloc_obj() fails, but the caller era_ctr() only checks IS_ERR(md). Since IS_ERR(NULL) returns false, the NULL pointer is treated as a valid result and later assigned to era->md, leading to a NULL pointer dereference when the metadata is accessed.
Fix this by returning ERR_PTR(-ENOMEM) on allocation failure, consistent with dm-cache-metadata.c, dm-thin-metadata.c, and dm-clone-metadata.c which all use ERR_PTR(-ENOMEM) for the same pattern.
--- drivers/md/dm-era-target.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/md/dm-era-target.c +4 -2
@@ -791,8 +791,10 @@ static struct era_metadata *metadata_open(struct block_device *bdev,int r;struct era_metadata *md =kzalloc (sizeof (*md),GFP_KERNEL ); -if (!md) -return NULL ; +if (!md) { +DMERR ("could not allocate metadata struct" ); +return ERR_PTR (-ENOMEM ); + } md->bdev = bdev; md->block_size = block_size;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 425/699 regulator: core: Make regulator_lock_two() logic easier to follow
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Douglas Anderson <[email protected]>
[ Upstream commit 37473397b852f556d8b9428ccbfd51886037842d ]
The regulator_lock_two() function could be made clearer in the case of lock contention by having a local variable for each of the held and contended locks. Let's do that. At the same time, let's use the swap() function instead of open coding it.
This change is expected to be a no-op and simply improves code clarity.
Stable-dep-of: d38f8bd771c4 ("regulator: core: regulator_lock_two() should test for EDEADLK not EDEADLOCK")
--- drivers/regulator/core.c | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-)
drivers/regulator/core.c +12 -19
@@ -228,7 +228,7 @@ static void regulator_lock_two(struct regulator_dev *rdev1,struct regulator_dev *rdev2, struct ww_acquire_ctx *ww_ctx) { - struct regulator_dev *tmp; + struct regulator_dev *held, *contended;int ret;ww_acquire_init (ww_ctx, ®ulator_ww_class);
@@ -242,25 +242,18 @@ static void regulator_lock_two(struct regulator_dev *rdev1, goto exit; } + held = rdev1; + contended = rdev2;while (true) { -/* -* Start of loop: rdev1 was locked and rdev2 was contended. -* Need to unlock rdev1, slowly lock rdev2, then try rdev1 -* again. -*/ -regulator_unlock (rdev1); - -ww_mutex_lock_slow (&rdev2->mutex, ww_ctx); - rdev2->ref_cnt++; - rdev2->mutex_owner = current; - ret =regulator_lock_nested (rdev1, ww_ctx); - -if (ret == -EDEADLOCK ) { -/* More contention; swap which needs to be slow */ - tmp = rdev1; - rdev1 = rdev2; - rdev2 = tmp; - }else { +regulator_unlock (held); + +ww_mutex_lock_slow (&contended->mutex, ww_ctx); + contended->ref_cnt++; + contended->mutex_owner = current; +swap (held, contended); + ret =regulator_lock_nested (contended, ww_ctx); + +if (ret != -EDEADLOCK ) {WARN_ON (ret);break ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 426/699 regulator: core: regulator_lock_two() should test for EDEADLK not EDEADLOCK
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Timur Tabi <[email protected]>
[ Upstream commit d38f8bd771c4999b797d7074b348cf201414bd34 ]
Compare against -EDEADLK, which is what ww_mutex_lock() actually returns and what every other deadlock check in this file already uses.
Function regulator_lock_two() acquires two regulators via regulator_lock_nested() -> ww_mutex_lock(). On contention, ww_mutex_lock() returns -EDEADLK, which is the caller's signal to drop the lock it holds and retry the acquisition in the canonical order.
However, regulator_lock_two() tests the return value against -EDEADLOCK rather than -EDEADLK. On most architectures, EDEADLK and EDEADLOCK are the same value, so the comparison happens to be correct and the bug is invisible. But on MIPS, SPARC, and PowerPC, those two errors have different values. The test is wrong: a genuine -EDEADLK backoff no longer matches -EDEADLOCK, so instead of unlocking and retrying, the code falls into WARN_ON(ret) and returns with only one of the two regulators locked.
In practice, this is a bug only on MIPS, because the regulator core is not built or used on the other two platforms.
In general, EDEADLK is preferred over EDEADLOCK for new code.
--- drivers/regulator/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/regulator/core.c +2 -2
@@ -237,7 +237,7 @@ static void regulator_lock_two(struct regulator_dev *rdev1, ret =regulator_lock_nested (rdev1, ww_ctx);WARN_ON (ret); ret =regulator_lock_nested (rdev2, ww_ctx); -if (ret != -EDEADLOCK ) { +if (ret != -EDEADLK ) {WARN_ON (ret); goto exit; }
@@ -253,7 +253,7 @@ static void regulator_lock_two(struct regulator_dev *rdev1,swap (held, contended); ret =regulator_lock_nested (contended, ww_ctx); -if (ret != -EDEADLOCK ) { +if (ret != -EDEADLK ) {WARN_ON (ret);break ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 427/699 net/mlx5: Fix L3 tunnel entropy refcount leak
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li RongQing <[email protected]>
[ Upstream commit c914307e1d41c2cb7bcdcbfde4cd2f214f6aa027 ]
mlx5_tun_entropy_refcount_inc() counts both VXLAN and L2-to-L3 tunnel reformat entries as entropy-enabling users. The matching decrement path only handled VXLAN, leaving L2-to-L3 tunnel entries counted after release.
Handle MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL in mlx5_tun_entropy_refcount_dec() as well so the enabling entry refcount remains balanced.
--- drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/lib/port_tun.c +2 -1
@@ -177,7 +177,8 @@ void mlx5_tun_entropy_refcount_dec(struct mlx5_tun_entropy *tun_entropy, int reformat_type) {mutex_lock (&tun_entropy->lock); -if (reformat_type ==MLX5_REFORMAT_TYPE_L2_TO_VXLAN ) +if (reformat_type ==MLX5_REFORMAT_TYPE_L2_TO_VXLAN || + reformat_type ==MLX5_REFORMAT_TYPE_L2_TO_L3_TUNNEL ) tun_entropy->num_enabling_entries--;else if (reformat_type ==MLX5_REFORMAT_TYPE_L2_TO_NVGRE && --tun_entropy->num_disabling_entries ==0 )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 428/699 smb: client: fix overflow in passthrough ioctl bounds check
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit a4f27ad055392fa164f5649e89a3637b033c5fcc ]
smb2_ioctl_query_info() validates the PASSTHRU_FSCTL response payload before copying it to userspace.
The payload offset and length both come from 32-bit fields. The bounds check currently adds OutputOffset and qi.input_buffer_length directly, so the addition can wrap in 32-bit arithmetic before the result is compared against the response buffer length.
A malicious server can use a large OutputOffset and a small OutputCount to make the wrapped sum pass the bounds check. The later copy_to_user() then reads from io_rsp + OutputOffset, outside the response buffer.
Use size_add() for the offset plus length check so overflow is treated as out of bounds.
--- fs/cifs/smb2ops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
fs/cifs/smb2ops.c +2 -2
@@ -1698,8 +1698,8 @@ smb2_ioctl_query_info(const unsigned int xid,if (le32_to_cpu (io_rsp->OutputCount) < qi.input_buffer_length) qi.input_buffer_length =le32_to_cpu (io_rsp->OutputCount);if (qi.input_buffer_length >0 && -le32_to_cpu (io_rsp->OutputOffset) + qi.input_buffer_length - > rsp_iov[1 ].iov_len) { +size_add (le32_to_cpu (io_rsp->OutputOffset), + qi.input_buffer_length) > rsp_iov[1 ].iov_len) { rc = -EFAULT ; goto out; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 429/699 mlxsw: fix refcount leak in mlxsw_sp_vrs_lpm_tree_replace()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <[email protected]>
commit 21cf8dc478a49e8de039c2739b1646a774cb1944 upstream.
When mlxsw_sp_vrs_lpm_tree_replace() fails after replacing some VRs, the error rollback loop does not correctly revert the preceding replacements. The loop decrements the index but fails to update the vr pointer, which still points to the VR that caused the failure. As a result, the condition and the rollback call always operate on the same VR, potentially calling mlxsw_sp_vr_lpm_tree_replace() multiple times on it while never rolling back the earlier VRs. Those VRs continue to hold a reference to new_tree acquired via mlxsw_sp_lpm_tree_hold(), leaking the reference count of new_tree.
Fix by reinitializing vr inside the error loop with the updated index:
vr = &mlxsw_sp->router->vrs[i];
so that the loop correctly iterates over all VRs that were actually replaced.
--- drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/mellanox/mlxsw/spectrum_router.c +1 -0
@@ -910,6 +910,7 @@ static int mlxsw_sp_vrs_lpm_tree_replace err_tree_replace:for (i--; i >=0 ; i--) { + vr = &mlxsw_sp->router->vrs[i];if (!mlxsw_sp_vr_lpm_tree_should_replace (vr, proto, new_id))continue ; mlxsw_sp_vr_lpm_tree_replace(mlxsw_sp,
Greg Kroah-Hartman
maintainerPATCH 430/699 net: qrtr: fix 32-bit integer overflow in qrtr_endpoint_post()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 20054869770c7df060c5ecee3e8bbf9029c47191 upstream.
qrtr_endpoint_post() validates an incoming packet with
if (!size || len != ALIGN(size, 4) + hdrlen) goto err;
where size comes from the wire. On 32-bit, size_t is 32 bits and ALIGN(size, 4) wraps to 0 for size >= 0xfffffffd, so the check passes and skb_put_data(skb, data + hdrlen, size) writes past the hdrlen-sized skb and oopses the kernel. 64-bit is unaffected.
This is the 32-bit residual of ad9d24c9429e2 ("net: qrtr: fix OOB Read in qrtr_endpoint_post"), which fixed only the 64-bit case.
Reject any size that cannot fit the buffer before the ALIGN.
--- net/qrtr/af_qrtr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/qrtr/af_qrtr.c +1 -1
@@ -490,7 +490,7 @@ int qrtr_endpoint_post(struct qrtr_endpo goto err; } -if (!size || len !=ALIGN (size,4 ) + hdrlen) +if (!size || size > len || len !=ALIGN (size,4 ) + hdrlen) goto err; if ((cb->type == QRTR_TYPE_NEW_SERVER ||
Greg Kroah-Hartman
maintainerPATCH 431/699 net: atm: reject out-of-range traffic classes in QoS validation
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhengchuan Liang <[email protected]>
commit cdf19f380e46192e7084be559638aab1f6ed86a2 upstream.
Reject ATM traffic classes above ATM_ANYCLASS in check_tp(). SO_ATMQOS stores the supplied QoS after check_qos() succeeds, so accepting larger values leaves invalid traffic_class values in vcc->qos.
That bad state later reaches pvc_info(), which indexes class_name[] with vcc->qos.{rx,tp}.traffic_class. Values above ATM_ANYCLASS cause an out-of-bounds read when /proc/net/atm/pvc is read.
Tighten the existing QoS validation so invalid traffic_class values are rejected at the point where user supplied QoS is accepted.
--- net/atm/common.c | 2 ++ 1 file changed, 2 insertions(+)
net/atm/common.c +2 -0
@@ -720,6 +720,8 @@ static int atm_change_qos(struct atm_vccstatic int check_tp (const struct atm_trafprm *tp) {/* @@@ Should be merged with adjust_tp */ +if (tp->traffic_class >ATM_ANYCLASS ) +return -EINVAL ;if (!tp->traffic_class || tp->traffic_class ==ATM_ANYCLASS )return 0 ; if (tp->traffic_class != ATM_UBR && !tp->min_pcr && !tp->pcr &&
Greg Kroah-Hartman
maintainerPATCH 432/699 net: ife: require ETH_HLEN to be pullable in ife_decode()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yong Wang <[email protected]>
commit 9406f6012b7343661efb516a11c62d4db2b62f75 upstream.
ife decode may return after making only the outer IFE header and metadata pullable. The caller then passes the decapsulated packet to eth_type_trans(), which expects the inner Ethernet header to be accessible from the linear data area.
With a malformed IFE frame, the inner Ethernet header may still be shorter than ETH_HLEN in the linear area, which can lead to a crash in the original code.
Fix this by extending the pull check in ife_decode() so that the inner Ethernet header is also guaranteed to be pullable before returning.
--- net/ife/ife.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ife/ife.c +1 -1
@@ -79,7 +79,7 @@ void *ife_decode(struct sk_buff *skb, u1if (unlikely (ifehdrln <2 ))return NULL ; -if (unlikely (!pskb_may_pull (skb, total_pull))) +if (unlikely (!pskb_may_pull (skb, total_pull +ETH_HLEN )))return NULL ; ifehdr = (struct ifeheadr *)(skb->data + skb->dev->hard_header_len);
Greg Kroah-Hartman
maintainerPATCH 433/699 arm64: dts: qcom: sdm630: describe adsp_mem region properly
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nickolay Goppen <[email protected]>
commit ce414263e9ebe5080381a50cbdf9065c29816202 upstream.
Downstream [1] this region is marked as shared, reusable and dynamic so describe it that way.
--- arch/arm64/boot/dts/qcom/sdm630.dtsi | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
arch/arm64/boot/dts/qcom/sdm630.dtsi +6 -3
@@ -391,9 +391,12 @@ no-map; }; - adsp_mem: adsp-region@f6000000 { - reg = <0x0 0xf6000000 0x0 0x800000>; - no-map; + adsp_mem: adsp-region { + compatible = "shared-dma-pool"; + alloc-ranges = <0x0 0x80000000 0x0 0x80000000>; + alignment = <0x0 0x400000>; + size = <0x0 0x800000>; + reusable; }; qseecom_mem: qseecom-region@f6800000 {
Greg Kroah-Hartman
maintainerPATCH 434/699 KVM: arm64: vgic: Check the interrupt is still ours before migrating it
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hyunwoo Kim <[email protected]>
commit 0074b82cdfcb5fd13710a0ac308ade68ac6f6fbe upstream.
vgic_prune_ap_list() drops both ap_list_lock and irq_lock while migrating an interrupt to another vCPU. After reacquiring the locks it only checks that the affinity is unchanged (target_vcpu == vgic_target_oracle(irq)) before moving the interrupt, which assumes that an interrupt whose affinity is preserved is still queued on this vCPU's ap_list.
That assumption no longer holds if the interrupt is taken off the ap_list while the locks are dropped. vgic_flush_pending_lpis() removes the interrupt from the list and sets irq->vcpu to NULL, but leaves enabled/pending/target_vcpu untouched. As the interrupt is still enabled and pending, vgic_target_oracle() returns the same target_vcpu, so the affinity check passes and list_del() is run a second time on an entry that has already been removed.
Also check that the interrupt is still assigned to this vCPU (irq->vcpu == vcpu) before moving it.
--- arch/arm64/kvm/vgic/vgic.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
arch/arm64/kvm/vgic/vgic.c +6 -5
@@ -685,15 +685,16 @@ retry:raw_spin_lock (&irq->irq_lock);/* -* If the affinity has been preserved, move the -* interrupt around. Otherwise, it means things have -* changed while the interrupt was unlocked, and we -* need to replay this. +* If the interrupt is still ours and its affinity has +* been preserved, move it around. Otherwise, it means +* things have changed while the interrupt was unlocked +* (it may even have been taken off the list with its +* affinity left untouched), and we need to replay this. * * In all cases, we cannot trust the list not to have * changed, so we restart from the beginning. */ -if (target_vcpu ==vgic_target_oracle (irq)) { +if (irq->vcpu == vcpu && target_vcpu ==vgic_target_oracle (irq)) {struct vgic_cpu *new_cpu = &target_vcpu->arch.vgic_cpu;list_del (&irq->ap_list);
Greg Kroah-Hartman
maintainerPATCH 435/699 fbdev: sm712: Fix operator precedence in big_swap macro
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li RongQing <[email protected]>
commit 5dbe5b65df0b0c0ec77492427c274b7b5011890e upstream.
The big_swap(p) macro was intended to swap bytes within 16-bit halves of a 32-bit value. However, because the bitwise shift operators (<<, >>) have higher precedence than the bitwise AND operator (&), the original code failed to perform any shifting on the masked bits.
For example, 'p & 0xff00ff00 >> 8' was evaluated as 'p & (0xff00ff00 >> 8)', effectively neutralizing the intended swap.
Fix this by adding parentheses to ensure the bitwise AND is performed before the shift, correctly implementing the byte swap logic.
--- drivers/video/fbdev/sm712.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/video/fbdev/sm712.h +1 -1
@@ -101,7 +101,7 @@ struct modeinit {#define mmio_addr 0x00800000#define seqw17 () smtc_seqw(0x17, 0x30)#define big_pixel_depth (p, d) {if (p == 24) {p = 32; d = 32; } } -#define big_swap (p) ((p & 0xff00ff00 >> 8) | (p & 0x00ff00ff << 8)) +#define big_swap (p) (((p & 0xff00ff00) >> 8) | ((p & 0x00ff00ff) << 8))#else #define pal_rgb (r, g, b, val) val#define big_addr 0
Greg Kroah-Hartman
maintainerPATCH 436/699 fbdev: radeon: fix potential memory leak in radeonfb_pci_register()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
commit df8c1101c9a08859da612b5d0a08d55d475522c6 upstream.
The function radeonfb_pci_register() allocates memory for modelist (by calling radeon_check_modes() which calls fb_add_videomode()). The memory is appended to info->modelist, but is not freed in subsequent error paths. Fix this by calling fb_destroy_modelist().
--- drivers/video/fbdev/aty/radeon_base.c | 1 + 1 file changed, 1 insertion(+)
drivers/video/fbdev/aty/radeon_base.c +1 -0
@@ -2492,6 +2492,7 @@ static int radeonfb_pci_register(structreturn 0 ; err_unmap_fb:iounmap (rinfo->fb_base); +fb_destroy_modelist (&info->modelist); err_unmap_rom:kfree (rinfo->mon1_EDID);kfree (rinfo->mon2_EDID);
Greg Kroah-Hartman
maintainerPATCH 437/699 fbdev: i740fb: fix potential memory leak in i740fb_probe()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
commit 5936063409af230a2c88b8700c47b89a19fd70b5 upstream.
In i740fb_probe(), the memory allocated in fb_videomode_to_modelist() for modelist is not freed in the error paths. Fix that by calling fb_destroy_modelist().
--- drivers/video/fbdev/i740fb.c | 1 + 1 file changed, 1 insertion(+)
drivers/video/fbdev/i740fb.c +1 -0
@@ -1150,6 +1150,7 @@ err_reg_framebuffer:fb_dealloc_cmap (&info->cmap); err_alloc_cmap: err_find_mode: +fb_destroy_modelist (&info->modelist);if (par->ddc_registered)i2c_del_adapter (&par->ddc_adapter);pci_iounmap (dev, par->regs);
Greg Kroah-Hartman
maintainerPATCH 438/699 fbdev: s3fb: fix potential memory leak in s3_pci_probe()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
commit 3b0ed04bc852887a9164e1bbf521652e8ef3eb92 upstream.
In s3_pci_probe(), the memory allocated for modelist using fb_videomode_to_modelist() is not freed in subsequent error paths. Fix that by calling fb_destroy_modelist()
--- drivers/video/fbdev/s3fb.c | 1 + 1 file changed, 1 insertion(+)
drivers/video/fbdev/s3fb.c +1 -0
@@ -1366,6 +1366,7 @@ err_reg_fb: err_alloc_cmap: err_find_mode:#ifdef CONFIG_FB_S3_DDC +fb_destroy_modelist (&info->modelist);if (par->ddc_registered)i2c_del_adapter (&par->ddc_adapter);if (par->mmio)
Greg Kroah-Hartman
maintainerPATCH 439/699 fbdev: uvesafb: fix potential memory leak in uvesafb_probe()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
commit 033e56fed09047ee63072e9f58789f40c1c7079d upstream.
Due to an incorrect goto label, memory allocated for modedb and modelist in uvesafb_vbe_init() is not freed in some error paths. Fix this by updating the goto label.
--- drivers/video/fbdev/uvesafb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/video/fbdev/uvesafb.c +2 -2
@@ -1698,14 +1698,14 @@ static int uvesafb_probe(struct platform i =uvesafb_vbe_init_mode (info);if (i <0 ) { err = -EINVAL ; - goto out; + goto out_mode; }else { mode = &par->vbe_modes[i]; }if (fb_alloc_cmap (&info->cmap,256 ,0 ) <0 ) { err = -ENXIO ; - goto out; + goto out_mode; }uvesafb_init_info (info, mode);
Greg Kroah-Hartman
maintainerPATCH 440/699 fbdev: tdfxfb: fix potential memory leak in tdfxfb_probe()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
commit bb019d755366cc3e777a12d4bf457ff289837370 upstream.
In tdfxfb_probe(), the memory allocated for modelist using fb_videomode_to_modelist() when CONFIG_FB_3DFX_I2C is defined, is not freed in the subsequent error paths.
Fix that by calling fb_destroy_modelist().
--- drivers/video/fbdev/tdfxfb.c | 1 + 1 file changed, 1 insertion(+)
drivers/video/fbdev/tdfxfb.c +1 -0
@@ -1548,6 +1548,7 @@ static int tdfxfb_probe(struct pci_dev * out_err_iobase:#ifdef CONFIG_FB_3DFX_I2C +fb_destroy_modelist (&info->modelist);tdfxfb_delete_i2c_busses (default_par);#endif arch_phys_wc_del (default_par->wc_cookie);
Greg Kroah-Hartman
maintainerPATCH 441/699 fbdev: carminefb: fix potential memory leak in alloc_carmine_fb()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
commit 6fcca16a2b19c37f60693c56cbc0c923364ff3ef upstream.
The memory allocated for modelist in fb_videomode_to_modelist() is not freed in the subsequent error path.
Fix that by calling fb_destroy_modelist()
--- drivers/video/fbdev/carminefb.c | 1 + 1 file changed, 1 insertion(+)
drivers/video/fbdev/carminefb.c +1 -0
@@ -592,6 +592,7 @@ static int alloc_carmine_fb(void __iomemreturn 0 ; err_dealloc_cmap: +fb_destroy_modelist (&info->modelist);fb_dealloc_cmap (&info->cmap); err_free_fb:framebuffer_release (info);
Greg Kroah-Hartman
maintainerPATCH 442/699 fbdev: nvidia: fix potential memory leak in nvidiafb_probe()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
commit 85f5e38c162bdf9dbbe197275d416402712f3707 upstream.
In nvidiafb_probe(), the memory allocated for modelist in nvidia_set_fbinfo() is not freed in the subsequent error paths. Fix that by calling fb_destroy_modelist().
--- drivers/video/fbdev/nvidia/nvidia.c | 1 + 1 file changed, 1 insertion(+)
drivers/video/fbdev/nvidia/nvidia.c +1 -0
@@ -1409,6 +1409,7 @@ static int nvidiafb_probe(struct pci_dev err_out_iounmap_fb:iounmap (info->screen_base); +fb_destroy_modelist (&info->modelist); err_out_free_base1:fb_destroy_modedb (info->monspecs.modedb);nvidia_delete_i2c_busses (par);
Greg Kroah-Hartman
maintainerPATCH 443/699 fbdev: tridentfb: fix potential memory leak in trident_pci_probe()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
commit 7a35ec619d9af8ee128320975c1252b8ad65f1e8 upstream.
In trident_pci_probe(), the memory allocated for modelist using fb_videomode_to_modelist() is not freed in subsequent error paths. Fix that by calling fb_destroy_modelist().
--- drivers/video/fbdev/tridentfb.c | 1 + 1 file changed, 1 insertion(+)
drivers/video/fbdev/tridentfb.c +1 -0
@@ -1702,6 +1702,7 @@ static int trident_pci_probe(struct pci_return 0 ; out_unmap2: +fb_destroy_modelist (&info->modelist);if (default_par->ddc_registered)i2c_del_adapter (&default_par->ddc_adapter);kfree (info->pixmap.addr);
Greg Kroah-Hartman
maintainerPATCH 444/699 netfilter: nf_conntrack_irc: fix parse_dcc() off-by-one OOB read
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Muhammad Bilal <[email protected]>
commit ef6400ca25a13fd6dedbe8ef4a1d0979bbbfe88a upstream.
parse_dcc() treats data_end as an inclusive end pointer, but its only caller passes data_limit = ib_ptr + datalen, which points one past the last valid byte.
The newline search loop iterates while tmp <= data_end, so when no newline is present, *tmp is read at tmp == data_end, one byte beyond the region filled by skb_header_pointer().
irc_buffer is kmalloc'd as MAX_SEARCH_SIZE + 1 bytes and datalen is capped at MAX_SEARCH_SIZE, so the stray read does not fault. The byte is uninitialized or stale; if it contains an ASCII digit, simple_strtoul will consume it and produce a wrong DCC IP or port in the conntrack expectation. The extra allocation byte is also a fragile guard: if the cap or allocation size changes, this becomes a real out-of-bounds read.
Change the loop and its post-loop check to use strict less-than, consistent with the caller's exclusive-end convention. Update the function comment accordingly.
--- net/netfilter/nf_conntrack_irc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/netfilter/nf_conntrack_irc.c +3 -3
@@ -63,7 +63,7 @@ static const char *const dccprotos[] = {/* tries to get the ip_addr and port out of a dcc command * return value: -1 on failure, 0 on success * data pointer to first byte of DCC command data -* data_end pointer to last byte of dcc command data +* data_end one past end of data * ip returns parsed ip of dcc command * port returns parsed port of dcc command * ad_beg_p returns pointer to first byte of addr data
@@ -81,10 +81,10 @@ static int parse_dcc(char *data, const c/* Make sure we have a newline character within the packet boundaries * because simple_strtoul parses until the first invalid character. */ -for (tmp = data; tmp <= data_end; tmp++) +for (tmp = data; tmp < data_end; tmp++)if (*tmp =='\n' )break ; -if (tmp > data_end || *tmp !='\n' ) +if (tmp >= data_end || *tmp !='\n' )return -1 ; *ad_beg_p = data;
Greg Kroah-Hartman
maintainerPATCH 445/699 netfilter: nfnl_cthelper: apply per-class values when updating policies
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Carlier <[email protected]>
commit d738feccb98cb224ebabecb703e98f5008276bff upstream.
When a userspace conntrack helper with multiple expectation classes is updated via nfnetlink, every class ends up with the first class's max_expected and timeout values.
nfnl_cthelper_update_policy_all() validates each new policy into the corresponding slot of the temporary new_policy array, but the second loop that commits the values into the live helper dereferences new_policy as a pointer instead of indexing it, so every iteration reads new_policy[0] regardless of i. An update that changes per-class values is silently collapsed onto class 0's values with no error returned to userspace.
Index the temporary array by i in the commit loop so each class gets its own validated values.
--- net/netfilter/nfnetlink_cthelper.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/netfilter/nfnetlink_cthelper.c +2 -2
@@ -344,8 +344,8 @@ static int nfnl_cthelper_update_policy_afor (i =0 ; i < helper->expect_class_max +1 ; i++) { policy = (struct nf_conntrack_expect_policy *) &helper->expect_policy[i]; - policy->max_expected = new_policy->max_expected; - policy->timeout = new_policy->timeout; + policy->max_expected = new_policy[i].max_expected; + policy->timeout = new_policy[i].timeout; } err:
Greg Kroah-Hartman
maintainerPATCH 446/699 netfilter: xt_cluster: reject template conntracks in hash match
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wyatt Feng <[email protected]>
commit 5feba91006ec92da57acc1cc2e34df623b98541e upstream.
xt_cluster_mt() treats any non-NULL nf_ct_get() result as a fully initialized conntrack and passes it to xt_cluster_hash().
This causes a state confusion bug when the raw table CT target attaches a template conntrack to skb->_nfct before normal conntrack processing. Templates carry IPS_TEMPLATE status but do not have a valid tuple for hashing yet, so xt_cluster_hash() can hit its WARN_ON() path on the zeroed l3num field.
Reject template conntracks before hashing them. This matches existing netfilter handling for template objects and avoids hashing incomplete conntrack state.
--- net/netfilter/xt_cluster.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/netfilter/xt_cluster.c +1 -1
@@ -107,7 +107,7 @@ xt_cluster_mt(const struct sk_buff *skb, } ct =nf_ct_get (skb, &ctinfo); -if (ct ==NULL ) +if (!ct ||nf_ct_is_template (ct))return false;if (ct->master)
Greg Kroah-Hartman
maintainerPATCH 447/699 netfilter: nf_nat_sip: reload possible stale data pointer
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Westphal <[email protected]>
commit 77e43bcb7ec177e293a5c3f1b91a2c5aebfb6c68 upstream.
quoting sashiko:
------------------------------------------------------------------------
[..] noticed a potential memory bug and header corruption involving the SIP NAT helper.
In net/netfilter/nf_nat_sip.c:nf_nat_sip():
if (skb_ensure_writable(skb, skb->len)) {
nf_ct_helper_log(skb, ct, "cannot mangle packet");
return NF_DROP;
}
uh = (void *)skb->data + protoff;
uh->dest = ct_sip_info->forced_dport;
if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, protoff,
0, 0, NULL, 0)) { If a cloned or fragmented SKB is reallocated by skb_ensure_writable(), the old data buffer is freed. However, nf_nat_sip() fails to update *dptr to point to the new buffer.
It also appears to use nf_nat_mangle_udp_packet() on what could be a TCP packet, which would overwrite the sequence number with a checksum update.
------------------------------------------------------------------------
nf_conntrack_sip linerizes skbs, hence no fragmented skb can be seen. But clones are possible, so rebuild dptr.
Disable nf_nat_mangle_udp_packet() branch for TCP streams. It doesn't look like this can ever happen, else we should have received bug reports about this, so just check the conntrack is UDP and drop otherwise.
The calling conntrack_sip set ->forced_dport for SIP_HDR_VIA_UDP messages, so I don't think this is ever expected to be true for a TCP stream.
--- net/netfilter/nf_nat_sip.c | 9 +++++++++ 1 file changed, 9 insertions(+)
net/netfilter/nf_nat_sip.c +9 -0
@@ -283,13 +283,22 @@ next:/* Mangle destination port for Cisco phones, then fix up checksums */ if (dir ==IP_CT_DIR_REPLY && ct_sip_info->forced_dport) { +int doff = *dptr - (const char *)skb->data;struct udphdr *uh; +if (doff <=0 ) +return NF_DROP ; + +/* ct_sip_info->forced_dport only expected with UDP */ +if (nf_ct_protonum (ct) !=IPPROTO_UDP ) +return NF_DROP ; +if (skb_ensure_writable (skb, skb->len)) {nf_ct_helper_log (skb, ct,"cannot mangle packet" );return NF_DROP ; } + *dptr = skb->data + doff; uh = (void *)skb->data + protoff; uh->dest = ct_sip_info->forced_dport;
Greg Kroah-Hartman
maintainerPATCH 448/699 netfilter: nf_conntrack_reasm: guard mac_header adjustment after IPv6 defrag
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
commit 3b08fed5b7e0d5e3a25d73ef3ba09cd33ade16c9 upstream.
nf_ct_frag6_reasm() slides the packet head forward to drop the IPv6 fragment header and then unconditionally advances skb->mac_header:
skb->mac_header += sizeof(struct frag_hdr);
On the NF_INET_LOCAL_OUT defrag path the skb has no link-layer header yet, so skb->mac_header is still the "not set" sentinel (u16)~0U. Adding sizeof(struct frag_hdr) wraps it to a small value (0xffff + 8 == 7), after which skb_mac_header_was_set() wrongly reports a MAC header is present and skb_mac_header() points into the headroom.
The reassembler has done this unconditional add since it was introduced; it was harmless while mac_header was a bare pointer, but wrong once mac_header became a u16 offset whose unset state is the ~0U sentinel tested by skb_mac_header_was_set(). The sibling net/ipv6/reassembly.c does the same relocation and does guard the adjustment; mirror the guard here.
--- net/ipv6/netfilter/nf_conntrack_reasm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/ipv6/netfilter/nf_conntrack_reasm.c +2 -1
@@ -344,7 +344,8 @@ static int nf_ct_frag6_reasm(struct fragskb_network_header (skb)[fq->nhoffset] =skb_transport_header (skb)[0 ];memmove (skb->head +sizeof (struct frag_hdr ), skb->head, (skb->data - skb->head) -sizeof (struct frag_hdr )); - skb->mac_header +=sizeof (struct frag_hdr ); +if (skb_mac_header_was_set (skb)) + skb->mac_header +=sizeof (struct frag_hdr ); skb->network_header +=sizeof (struct frag_hdr );skb_reset_transport_header (skb);
Greg Kroah-Hartman
maintainerPATCH 449/699 netfilter: nf_conncount: fix zone comparison in tuple dedup
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yizhou Zhao <[email protected]>
commit f62c41b4910e65da396ec9a8c40c1fe7fe82e449 upstream.
The "already exists" dedup logic in __nf_conncount_add() decides whether a connection has already been counted and can be skipped instead of incrementing the connlimit count. It compares the conntrack zone of a list entry with the zone of the connection being added using nf_ct_zone_id() and nf_ct_zone_equal(), passing conn->zone.dir or zone->dir as the direction argument.
Those helpers take enum ip_conntrack_dir values: IP_CT_DIR_ORIGINAL is 0 and IP_CT_DIR_REPLY is 1. However, zone->dir is a u8 bitmask:NF_CT_ZONE_DIR_ORIG is 1, NF_CT_ZONE_DIR_REPL is 2 and NF_CT_DEFAULT_ZONE_DIR is 3. Passing that bitmask as the enum direction shifts the meaning of every non-zero value. An ORIG-only zone passes 1 and is tested as REPLY, while REPL-only and default zones pass 2 or 3 and test bits beyond the valid direction range. In those cases nf_ct_zone_id() can fall back to NF_CT_DEFAULT_ZONE_ID instead of using the real zone id, so different zones can be treated as equal and dedup collapses to tuple equality alone.
nf_conncount stores and compares the original-direction tuple for a connection. If an skb already has an attached conntrack entry, get_ct_or_tuple_from_skb() explicitly copies ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple, regardless of the packet's ctinfo. Therefore the zone comparison in the tuple dedup path must use IP_CT_DIR_ORIGINAL as well; the zone direction bitmask describes where a zone id applies, not which direction this conncount tuple represents.
Fix the two dedup comparisons by passing IP_CT_DIR_ORIGINAL directly. Do not special-case NF_CT_DEFAULT_ZONE_DIR and do not compare raw zone
ids: using the existing helpers with IP_CT_DIR_ORIGINAL preserves the direction-aware NF_CT_DEFAULT_ZONE_ID fallback. A default bidirectional zone contains the ORIG bit, so it naturally returns the real zone id; reply-only zones continue to fall back for original-direction tuple comparisons.
--- net/netfilter/nf_conncount.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/netfilter/nf_conncount.c +3 -3
@@ -207,8 +207,8 @@ check_connections:/* Not found, but might be about to be confirmed */ if (PTR_ERR (found) == -EAGAIN ) {if (nf_ct_tuple_equal (&conn->tuple, &tuple) && -nf_ct_zone_id (&conn->zone, conn->zone.dir) == -nf_ct_zone_id (zone, zone->dir)) +nf_ct_zone_id (&conn->zone,IP_CT_DIR_ORIGINAL ) == +nf_ct_zone_id (zone,IP_CT_DIR_ORIGINAL )) goto out_put;/* already exists */ }else { collect++;
@@ -219,7 +219,7 @@ check_connections: found_ct =nf_ct_tuplehash_to_ctrack (found);if (nf_ct_tuple_equal (&conn->tuple, &tuple) && -nf_ct_zone_equal (found_ct, zone, zone->dir)) { +nf_ct_zone_equal (found_ct, zone,IP_CT_DIR_ORIGINAL )) {/* * We should not see tuples twice unless someone hooks * this into a table without "-p tcp --syn".
Greg Kroah-Hartman
maintainerPATCH 450/699 netfilter: xt_nat: reject unsupported target families
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wyatt Feng <[email protected]>
commit 5d1a2240935ea47e2673d0ea17fdb058e4dc91dd upstream.
xt_nat SNAT and DNAT target handlers assume IP-family conntrack state is present and can dereference a NULL pointer when instantiated from an unsupported family through nft_compat. A bridge-family compat rule can therefore trigger a NULL-dereference in nf_nat_setup_info().
Reject non-IP families in xt_nat_checkentry() so unsupported targets cannot be installed. Keep NFPROTO_INET allowed for valid inet NAT compat users and leave the runtime fast path unchanged.
[ The crash was fixed via
9dbba7e694ec ("netfilter: nft_compat: ebtables emulation must reject non-bridge targets"), so this patch is no longer critical.
Nevertheless, NAT is only relevant for ipv4/ipv6, so this extra
family check is a good idea in any case. ]
--- net/netfilter/xt_nat.c | 9 +++++++++ 1 file changed, 9 insertions(+)
net/netfilter/xt_nat.c +9 -0
@@ -26,6 +26,15 @@ static int xt_nat_checkentry_v0(const ststatic int xt_nat_checkentry (const struct xt_tgchk_param *par) { +switch (par->family) { +case NFPROTO_IPV4 : +case NFPROTO_IPV6 : +case NFPROTO_INET : +break ; +default : +return -EINVAL ; + } +return nf_ct_netns_get (par->net, par->family); }
Greg Kroah-Hartman
maintainerPATCH 451/699 netfilter: bridge: fix stale prevhdr pointer in br_ip6_fragment()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei (Microsoft) <[email protected]>
commit 86f3ce81dd2b4b0aa2c3016c989a943e4b1b643d upstream.
br_ip6_fragment() gets prevhdr, a pointer into the skb head, from ip6_find_1stfragopt(), then calls skb_checksum_help(). For a cloned skb skb_checksum_help() reallocates the head via pskb_expand_head(), leaving prevhdr dangling. It is later dereferenced in ip6_frag_next(), causing a use-after-free write.
Save prevhdr's offset before skb_checksum_help() and recompute it after, like commit ef0efcd3bd3f ("ipv6: Fix dangling pointer when ipv6 fragment").
BUG: KASAN: slab-use-after-free in ip6_frag_next (net/ipv6/ip6_output.c:857) Write of size 1 at addr ffff888013ff5016 by task exploit/141 Call Trace: ... kasan_report (mm/kasan/report.c:595) ip6_frag_next (net/ipv6/ip6_output.c:857) br_ip6_fragment (net/ipv6/netfilter.c:212) nf_ct_bridge_post (net/bridge/netfilter/nf_conntrack_bridge.c:407) nf_hook_slow (net/netfilter/core.c:619) br_forward_finish (net/bridge/br_forward.c:66) __br_forward (net/bridge/br_forward.c:115) maybe_deliver (net/bridge/br_forward.c:191) br_flood (net/bridge/br_forward.c:245) br_handle_frame_finish (net/bridge/br_input.c:229) br_handle_frame (net/bridge/br_input.c:442) ... packet_sendmsg (net/packet/af_packet.c:3114) ... do_syscall_64 (arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) Kernel panic - not syncing: Fatal exception in interrupt
--- net/ipv6/netfilter.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/ipv6/netfilter.c +3 -1
@@ -122,7 +122,7 @@ int br_ip6_fragment(struct net *net, strktime_t tstamp = skb->tstamp;struct ip6_frag_state state;u8 *prevhdr, nexthdr =0 ; -unsigned int mtu, hlen; +unsigned int mtu, hlen, nexthdr_offset;int hroom, err =0 ;__be32 frag_id;
@@ -131,6 +131,7 @@ int br_ip6_fragment(struct net *net, str goto blackhole; hlen = err; nexthdr = *prevhdr; + nexthdr_offset = prevhdr -skb_network_header (skb); mtu = skb->dev->mtu; if (frag_max_size > mtu ||
@@ -149,6 +150,7 @@ int br_ip6_fragment(struct net *net, str (err = skb_checksum_help(skb))) goto blackhole; + prevhdr =skb_network_header (skb) + nexthdr_offset; hroom =LL_RESERVED_SPACE (skb->dev);if (skb_has_frag_list (skb)) {unsigned int first_len =skb_pagelen (skb);
Greg Kroah-Hartman
maintainerPATCH 452/699 gpu: host1x: Fix device reference leak in host1x_device_parse_dt() error path
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
commit e75717f9aec04355777be41070890c6a815c76df upstream.
After device_initialize(), the embedded struct device in struct host1x_device should be released through the device core with put_device().
In host1x_device_add(), if host1x_device_parse_dt() fails, the current error path frees the object directly with kfree(device). That bypasses the normal device lifetime handling and leaks the reference held on the embedded struct device.
The issue was identified by a static analysis tool I developed and confirmed by manual review.
Fix this by using put_device() in the host1x_device_parse_dt() failure path.
--- drivers/gpu/host1x/bus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/host1x/bus.c +1 -1
@@ -441,7 +441,7 @@ static int host1x_device_add(struct host err =host1x_device_parse_dt (device, driver);if (err <0 ) { -kfree (device); +put_device (&device->dev);return err; }
Greg Kroah-Hartman
maintainerPATCH 453/699 soc: ti: k3-ringacc: Fix access mode for k3_ringacc_ring_pop_tail_io/proxy
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Siddharth Vadapalli <[email protected]>
commit b920352cfd2b0fcd1249ff006618c939b64fc8f7 upstream.
k3_ringacc_ring_pop_tail_io() and k3_ringacc_ring_pop_tail_proxy() incorrectly use K3_RINGACC_ACCESS_MODE_POP_HEAD instead of K3_RINGACC_ACCESS_MODE_POP_TAIL. This will result in ring elements being popped in the reverse order of that which the caller expects. Fix this.
--- drivers/soc/ti/k3-ringacc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/soc/ti/k3-ringacc.c +2 -2
@@ -824,7 +824,7 @@ static int k3_ringacc_ring_pop_head_proxstatic int k3_ringacc_ring_pop_tail_proxy (struct k3_ring *ring,void *elem) {return k3_ringacc_ring_access_proxy (ring, elem, -K3_RINGACC_ACCESS_MODE_POP_HEAD ); +K3_RINGACC_ACCESS_MODE_POP_TAIL ); } static int k3_ringacc_ring_access_io(struct k3_ring *ring, void *elem,
@@ -895,7 +895,7 @@ static int k3_ringacc_ring_pop_io(structstatic int k3_ringacc_ring_pop_tail_io (struct k3_ring *ring,void *elem) {return k3_ringacc_ring_access_io (ring, elem, -K3_RINGACC_ACCESS_MODE_POP_HEAD ); +K3_RINGACC_ACCESS_MODE_POP_TAIL ); }static int k3_ringacc_ring_push_mem (struct k3_ring *ring,void *elem)
Greg Kroah-Hartman
maintainerPATCH 454/699 soc: fsl: qe: panic on ioremap() failure in qe_reset()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wang Jun <[email protected]>
commit a0fe29d20e7822182e12324905af5115c1b3aed3 upstream.
When ioremap() fails in qe_reset(), the global pointer qe_immr remains NULL, leading to a subsequent NULL pointer dereference when the pointer is accessed. Since this happens early in the boot process, a failure to map a few bytes of I/O memory indicates a fatal error from which the system cannot recover.
Follow the same pattern as qe_sdma_init() and panic immediately when ioremap() fails. This avoids a silent NULL pointer dereference later and makes the error explicit.
--- drivers/soc/fsl/qe/qe.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/soc/fsl/qe/qe.c +3 -0
@@ -88,6 +88,9 @@ void qe_reset(void)if (qe_immr ==NULL ) qe_immr =ioremap (get_qe_base (),QE_IMMAP_SIZE ); +if (!qe_immr) +panic ("QE:ioremap failed!" ); +qe_snums_init (); qe_issue_cmd(QE_RESET, QE_CR_SUBBLOCK_INVALID,
Greg Kroah-Hartman
maintainerPATCH 455/699 leds: uleds: Fix potential buffer overread
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Armin Wolf <[email protected]>
commit c19fe864f667afc49d1391d764e20b66555bcf7a upstream.
The name string supplied by userspace is not guaranteed to be null-terminated, so using strchr() on it might result in a buffer overread. The same thing will happen when said string is used by the LED class device.
Fix this by using strnchr() instead and explicitly check that the name string is properly null-terminated.
--- drivers/leds/uleds.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/leds/uleds.c +2 -1
@@ -102,7 +102,8 @@ static ssize_t uleds_write(struct file * name = udev->user_dev.name;if (!name[0 ] || !strcmp (name,"." ) || !strcmp (name,".." ) || -strchr (name,'/' )) { +strnchr (name,sizeof (udev->user_dev.name),'/' ) || + !strnchr (name,sizeof (udev->user_dev.name),'\0' )) { ret = -EINVAL ; goto out; }
Greg Kroah-Hartman
maintainerPATCH 456/699 mfd: sm501: Fix reference leak on failed device registration
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
commit 8c2f0b42fc252e1bf1c7746447091a468e784ca1 upstream.
When platform_device_register() fails in sm501_register_device(), the embedded struct device in pdev has already been initialized by device_initialize(), but the failure path only reports the error and returns without dropping the device reference for the current platform device:
sm501_register_device()
-> platform_device_register(pdev)
-> device_initialize(&pdev->dev)
-> setup_pdev_dma_masks(pdev)
-> platform_device_add(pdev)This leads to a reference leak when platform_device_register() fails. Fix this by calling platform_device_put() before returning the error.
The issue was identified by a static analysis tool I developed and confirmed by manual review.
--- drivers/mfd/sm501.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/mfd/sm501.c +3 -1
@@ -747,9 +747,11 @@ static int sm501_register_device(structif (ret >=0 ) {dev_dbg (sm->dev,"registered %s\n" , pdev->name);list_add_tail (&smdev->list, &sm->devices); - }else + }else {dev_err (sm->dev,"error registering %s (%d)\n" , pdev->name, ret); +platform_device_put (pdev); + }return ret; }
Greg Kroah-Hartman
maintainerPATCH 457/699 x86/boot: Validate console=uart8250 baud rate to fix early boot hang
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
commit ffa0aa5b625fe0bed7463ac613f8b06676ff4542 upstream.
When the baud rate is empty, 0, invalid, or overflows to 0 when stored as an int, the system will hang during early boot because of a division by zero in early_serial_init().
Fall back to DEFAULT_BAUD when the resulting baud rate is 0 to prevent an early system hang.
--- arch/x86/boot/early_serial_console.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
arch/x86/boot/early_serial_console.c +7 -4
@@ -117,7 +117,7 @@ static unsigned int probe_baud(int port)static void parse_console_uart8250 (void ) {char optstr[64 ], *options; -int baud =DEFAULT_BAUD ; +int baud;int port =0 ;/*
@@ -136,10 +136,13 @@ static void parse_console_uart8250(void)else return ; -if (options && (options[0 ] ==',' )) - baud =simple_strtoull (options +1 , &options,0 ); -else +if (options && (options[0 ] ==',' )) { + baud =simple_strtoull (options +1 ,NULL ,0 ); +if (!baud) + baud =DEFAULT_BAUD ; + }else { baud =probe_baud (port); + }if (port)early_serial_init (port, baud);
Greg Kroah-Hartman
maintainerPATCH 458/699 x86/boot: Reject too long acpi_rsdp= values
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
commit d130041a7b96f79cd4c7079a6c2431a6db4c9619 upstream.
cmdline_find_option() returns the full length of the parsed acpi_rsdp= value. get_cmdline_acpi_rsdp() then silently truncates values which do not fit in the val[] buffer.
Prevent boot_kstrtoul() from parsing a truncated value and then the kernel from silently using the wrong RSDP address, see discussion in Link:.
Issue a warning so that the user is aware that s/he supplied a malformed value and can get feedback instead of silent crashes.
[ bp: Make commit message more precise. ]
--- arch/x86/boot/compressed/acpi.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
arch/x86/boot/compressed/acpi.c +6 -1
@@ -288,10 +288,15 @@ static unsigned long get_cmdline_acpi_rschar val[MAX_ADDR_LEN ] = { };int ret; - ret =cmdline_find_option ("acpi_rsdp" , val,MAX_ADDR_LEN ); + ret =cmdline_find_option ("acpi_rsdp" , val,sizeof (val));if (ret <0 )return 0 ; +if (ret >=sizeof (val)) { +warn ("acpi_rsdp= value too long; ignoring" ); +return 0 ; + } +if (boot_kstrtoul (val,16 , &addr))return 0 ;#endif
Greg Kroah-Hartman
maintainerPATCH 459/699 batman-adv: gw: acquire ethernet header only after skb realloc
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 77880a3be88d378d60cc1e8f8ec70430e2ed0518 upstream.
The pskb_may_pull() called by batadv_get_vid() could reallocate the buffer behind the skb. Variables which were pointing to the old buffer need to be reassigned to avoid an use-after-free.
--- net/batman-adv/gateway_client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/batman-adv/gateway_client.c +2 -1
@@ -741,12 +741,13 @@ bool batadv_gw_out_of_range(struct batadstruct batadv_gw_node *gw_node =NULL ;struct batadv_gw_node *curr_gw =NULL ;struct batadv_neigh_ifinfo *curr_ifinfo, *old_ifinfo; -struct ethhdr *ethhdr = (struct ethhdr *)skb->data; +struct ethhdr *ethhdr;bool out_of_range = false;u8 curr_tq_avg;unsigned short vid; vid =batadv_get_vid (skb,0 ); + ethhdr = (struct ethhdr *)skb->data;if (is_multicast_ether_addr (ethhdr->h_dest)) goto out;
Greg Kroah-Hartman
maintainerPATCH 460/699 batman-adv: access unicast_ttvn skb->data only after skb realloc
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 7141990add3f75436f2933cb310654cad3b1e3e9 upstream.
The pskb_may_pull() called by batadv_get_vid() could reallocate the buffer behind the skb. Variables which were pointing to the old buffer need to be reassigned to avoid an use-after-free.
This was done correctly for the ethernet header but missed for the unicast_packet pointer.
--- net/batman-adv/routing.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/batman-adv/routing.c +1 -1
@@ -822,8 +822,8 @@ static bool batadv_check_unicast_ttvn(stif (skb_cow (skb,sizeof (*unicast_packet)) <0 )return false; - unicast_packet = (struct batadv_unicast_packet *)skb->data; vid =batadv_get_vid (skb, hdr_len); + unicast_packet = (struct batadv_unicast_packet *)skb->data; ethhdr = (struct ethhdr *)(skb->data + hdr_len);/* do not reroute multicast frames in a unicast header */
Greg Kroah-Hartman
maintainerPATCH 461/699 batman-adv: dat: acquire ARP hw source only after skb realloc
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 48067b2ae4504500a7093d9e1e16b42e70330480 upstream.
The pskb_may_pull() called by batadv_get_vid() could reallocate the buffer behind the skb. Variables which were pointing to the old buffer need to be reassigned to avoid an use-after-free.
--- net/batman-adv/distributed-arp-table.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/batman-adv/distributed-arp-table.c +4 -1
@@ -1819,6 +1819,7 @@ void batadv_dat_snoop_incoming_dhcp_ack(struct ethhdr *ethhdr;__be32 ip_src, yiaddr;unsigned short vid; +int hdr_size_tmp;__be16 proto;u8 *hw_src;
@@ -1835,8 +1836,10 @@ void batadv_dat_snoop_incoming_dhcp_ack(if (!batadv_dat_check_dhcp_ack (skb, proto, &ip_src, chaddr, &yiaddr))return ; + hdr_size_tmp = hdr_size; + vid =batadv_dat_get_vid (skb, &hdr_size_tmp); + ethhdr = (struct ethhdr *)(skb->data + hdr_size); hw_src = ethhdr->h_source; - vid =batadv_dat_get_vid (skb, &hdr_size);batadv_dat_entry_add (bat_priv, yiaddr, chaddr, vid);batadv_dat_entry_add (bat_priv, ip_src, hw_src, vid);
Greg Kroah-Hartman
maintainerPATCH 462/699 batman-adv: bla: reacquire gw address after skb realloc
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit cdf3b5af2bc4431e58629e8ad2086b1e9185c761 upstream.
The pskb_may_pull() called by batadv_bla_is_backbone_gw() could reallocate the buffer behind the skb. Variables which were pointing to the old buffer need to be reassigned to avoid an use-after-free.
--- net/batman-adv/routing.c | 1 + 1 file changed, 1 insertion(+)
net/batman-adv/routing.c +1 -0
@@ -1002,6 +1002,7 @@ int batadv_recv_unicast_packet(struct sk hdr_size);batadv_orig_node_put (orig_node_gw);if (is_gw) { + orig_addr_gw =eth_hdr (skb)->h_source;batadv_dbg (BATADV_DBG_BLA , bat_priv,"%s(): Dropped unicast pkt received from another backbone gw %pM.\n" , __func__, orig_addr_gw);
Greg Kroah-Hartman
maintainerPATCH 463/699 batman-adv: dat: ensure accessible eth_hdr proto field
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 26560c4a03dc4d607331600c187f59ab2df5f341 upstream.
When batadv_get_vid() accesses the proto field of the ethernet header, it is not checking if the data itself is accessible. The caller is responsible for it. But in contrast to other call sites, batadv_dat_get_vid() and its caller didn't make sure this is true. This could have caused an out-of-bounds access.
--- net/batman-adv/distributed-arp-table.c | 23 +++++++++++++++++++++++ net/batman-adv/main.c | 3 +++ 2 files changed, 26 insertions(+)
net/batman-adv/distributed-arp-table.c +23 -0
@@ -1135,6 +1135,9 @@ out:* @skb: the buffer containing the packet to extract the VID from * @hdr_size: the size of the batman-adv header encapsulating the packet * +* The caller must ensure that at least @hdr_size + ETH_HLEN bytes are +* accessible after skb->data. +* * Return: If the packet embedded in the skb is vlan tagged this function * returns the VID with the BATADV_VLAN_HAS_TAG flag. Otherwise BATADV_NO_FLAGS * is returned.
@@ -1217,6 +1220,10 @@ bool batadv_dat_snoop_outgoing_arp_requeif (!atomic_read (&bat_priv->distributed_arp_table)) goto out; +/* first, find out the vid. */ +if (!pskb_may_pull (skb, hdr_size +ETH_HLEN )) + goto out; + vid =batadv_dat_get_vid (skb, &hdr_size); type =batadv_arp_get_type (bat_priv, skb, hdr_size);
@@ -1313,6 +1320,10 @@ bool batadv_dat_snoop_incoming_arp_requeif (!atomic_read (&bat_priv->distributed_arp_table)) goto out; +/* first, find out the vid. */ +if (!pskb_may_pull (skb, hdr_size +ETH_HLEN )) + goto out; + vid =batadv_dat_get_vid (skb, &hdr_size); type =batadv_arp_get_type (bat_priv, skb, hdr_size);
@@ -1376,6 +1387,10 @@ void batadv_dat_snoop_outgoing_arp_replyif (!atomic_read (&bat_priv->distributed_arp_table))return ; +/* first, find out the vid. */ +if (!pskb_may_pull (skb, hdr_size +ETH_HLEN )) +return ; + vid =batadv_dat_get_vid (skb, &hdr_size); type =batadv_arp_get_type (bat_priv, skb, hdr_size);
@@ -1424,6 +1439,10 @@ bool batadv_dat_snoop_incoming_arp_replyif (!atomic_read (&bat_priv->distributed_arp_table)) goto out; +/* first, find out the vid. */ +if (!pskb_may_pull (skb, hdr_size +ETH_HLEN )) + goto out; + vid =batadv_dat_get_vid (skb, &hdr_size); type =batadv_arp_get_type (bat_priv, skb, hdr_size);
@@ -1879,6 +1898,10 @@ bool batadv_dat_drop_broadcast_packet(stif (batadv_forw_packet_is_rebroadcast (forw_packet)) goto out; +/* first, find out the vid. */ +if (!pskb_may_pull (forw_packet->skb, hdr_size +ETH_HLEN )) + goto out; + vid =batadv_dat_get_vid (forw_packet->skb, &hdr_size); type =batadv_arp_get_type (bat_priv, forw_packet->skb, hdr_size);
net/batman-adv/main.c +3 -0
@@ -663,6 +663,9 @@ __be32 batadv_skb_crc32(struct sk_buff ** @skb: the buffer containing the packet * @header_len: length of the batman header preceding the ethernet header * +* The caller must ensure that at least @header_len + ETH_HLEN bytes are +* accessible after skb->data. +* * Return: VID with the BATADV_VLAN_HAS_TAG flag when the packet embedded in the * skb is vlan tagged. Otherwise BATADV_NO_FLAGS. */
Greg Kroah-Hartman
maintainerPATCH 464/699 batman-adv: dat: fix tie-break for candidate selection
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 98052bdaf6ac1639a63ffc10244eeeab1f62ed2b upstream.
The original version of the candidate selection for DAT attempted to compare both candidate and max_orig_node to identify which has the smaller MAC address. This comparison is required as tie-break when a hash collision happened.
But the used function returned 0 when the function was not equal and a non-zero value when it was equal. As result, the actually selected node was dependent on the order of entries in the orig_hash and not actually on the mac addresses. The last originator in the hash collision would always win.
To have a proper ordering, it must diff the actual MAC address bytes and reject the candidate when the diff is not smaller than 0.
--- net/batman-adv/distributed-arp-table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/batman-adv/distributed-arp-table.c +1 -1
@@ -548,7 +548,7 @@ static bool batadv_is_orig_node_eligible* the one with the lowest address */ if (tmp_max == max && max_orig_node && -batadv_compare_eth (candidate->orig, max_orig_node->orig)) +memcmp (candidate->orig, max_orig_node->orig,ETH_ALEN ) >=0 ) goto out; ret = true;
Greg Kroah-Hartman
maintainerPATCH 465/699 batman-adv: tt: avoid request storms during pending request
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 27c7d40008231ae4140d35501b60087a9de2d2c3 upstream.
batadv_send_tt_request() allocates a tt_req_node when none exists for the destination originator node. This should prevent that a multiple TT requests are send at the same time to an originator.
But if allocation of the send buffer failed, this request must be cleaned up again. But indicator for such a failure is "ret == false". But the actual implementation is checking for "ret == true".
The check must be inverted to not loose the information about the TT request directly after it was attempted to be sent out. This should avoid potential request storms.
--- net/batman-adv/translation-table.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/batman-adv/translation-table.c +1 -1
@@ -3260,7 +3260,7 @@ out:if (primary_if)batadv_hardif_put (primary_if); -if (ret && tt_req_node) { +if (!ret && tt_req_node) {spin_lock_bh (&bat_priv->tt.req_list_lock);if (!hlist_unhashed (&tt_req_node->list)) {hlist_del_init (&tt_req_node->list);
Greg Kroah-Hartman
maintainerPATCH 466/699 batman-adv: fix VLAN priority offset
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit fdb3be00ba4dafa313e699d6b5b90d13f22f3f25 upstream.
The batadv_skb_set_priority() receives an SKB with the inner ethernet header at position "offset". When it tries to extract the IPv4 and IPv6 header, it needs to skip the ethernet header to get access to the IP header.
But for VLAN header, it performs the access with the struct vlan_ethhdr. This struct contains both both the ethernet header and the VLAN header. It is therefore incorrect to skip over the whole vlan_ethhdr size to get access to the vlan_ethhdr.
--- net/batman-adv/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/batman-adv/main.c +1 -1
@@ -420,7 +420,7 @@ void batadv_skb_set_priority(struct sk_bswitch (ethhdr->h_proto) {case htons (ETH_P_8021Q ): - vhdr =skb_header_pointer (skb, offset +sizeof (*vhdr), + vhdr =skb_header_pointer (skb, offset,sizeof (*vhdr), &vhdr_tmp);if (!vhdr)return ;
Greg Kroah-Hartman
maintainerPATCH 467/699 batman-adv: frag: free unfragmentable packet
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 6b628425aed49a1c7a4ffc997583840fc582d32b upstream.
The caller of batadv_frag_send_packet() assume that the skb provided to the function are always consumed. But the pre-check for an empty payload or the zero fragment size returned an error without any further actions.
A failed pre-check must use the same error handling code as the rest of the function.
--- net/batman-adv/fragmentation.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/batman-adv/fragmentation.c +4 -2
@@ -525,8 +525,10 @@ int batadv_frag_send_packet(struct sk_bu mtu = min_t(unsigned int, mtu, BATADV_FRAG_MAX_FRAG_SIZE); max_fragment_size = mtu - header_size; -if (skb->len ==0 || max_fragment_size ==0 ) -return -EINVAL ; +if (skb->len ==0 || max_fragment_size ==0 ) { + ret = -EINVAL ; + goto free_skb; + } num_fragments = (skb->len -1 ) / max_fragment_size +1 ; max_fragment_size = (skb->len -1 ) / num_fragments +1 ;
Greg Kroah-Hartman
maintainerPATCH 468/699 batman-adv: frag: fix primary_if leak on failed linearization
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 353d2c1d5492e53ae34f490a84494124dc3d3531 upstream.
If the skb has a frag_list, it must be linearized before it can be split using skb_split(). But when this step failed, it must not only free the skb but also take care of the reference to the already found primary_if.
--- net/batman-adv/fragmentation.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/batman-adv/fragmentation.c +1 -1
@@ -554,7 +554,7 @@ int batadv_frag_send_packet(struct sk_bu*/ if (skb_has_frag_list (skb) &&__skb_linearize (skb)) { ret = -ENOMEM ; - goto free_skb; + goto put_primary_if; }/* Create one header to be copied to all fragments */
Greg Kroah-Hartman
maintainerPATCH 469/699 batman-adv: tt: prevent TVLV OOB check overflow
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 7a581d9aaba8c82bd6177fa36b2588eea77f6e2b upstream.
A TT unicast TVLV contains the number of VLANs stored in it. This number is an u16 and gets multiplied by the size of the struct batadv_tvlv_tt_vlan_data (8 bytes). The size can therefore overflow the u16 used to store the tt_vlan_len. All additional safety checks to prevent out-of-bounds access of the TVLV buffer are invalid due to this overflow.
Using size_t prevents this overflow and ensures that the safety checks compare against the actual buffer requirements.
--- net/batman-adv/translation-table.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/batman-adv/translation-table.c +2 -1
@@ -4338,7 +4338,8 @@ static int batadv_tt_tvlv_unicast_handle u16 tvlv_value_len) {struct batadv_tvlv_tt_data *tt_data; -u16 tt_vlan_len, tt_num_entries; +u16 tt_num_entries; +size_t tt_vlan_len;char tt_flag;bool ret;
Greg Kroah-Hartman
maintainerPATCH 470/699 mfd: tps6586x: Fix OF node refcount
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bartosz Golaszewski <[email protected]>
commit 3001ed2b4e06da2276c42ace6551617065a5b1f9 upstream.
Platform devices created with platform_device_alloc() call platform_device_release() when the last reference to the device's kobject is dropped. This function calls of_node_put() unconditionally. This works fine for devices created with platform_device_register_full() but users of the split approach (platform_device_alloc() + platform_device_add()) must bump the reference of the of_node they assign manually. Add the missing call to of_node_get().
--- drivers/mfd/tps6586x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mfd/tps6586x.c +1 -1
@@ -399,7 +399,7 @@ static int tps6586x_add_subdevs(struct t pdev->dev.parent = tps6586x->dev; pdev->dev.platform_data = subdev->platform_data; - pdev->dev.of_node = subdev->of_node; + pdev->dev.of_node =of_node_get (subdev->of_node); ret =platform_device_add (pdev);if (ret) {
Greg Kroah-Hartman
maintainerPATCH 471/699 nvdimm/btt: Free arenas on btt_init() error paths
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
commit 1a6b6442a982d0ca5fb6a1a39b6f6dfd760eda57 upstream.
The arenas allocated by discover_arenas() or create_arenas() are not freed on some error paths in btt_init(). This leaks memory when BTT initialization fails.
Call free_arenas() from the affected error paths to release the allocations.
[ as: commit message and log edits ]
--- drivers/nvdimm/btt.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
drivers/nvdimm/btt.c +7 -4
@@ -1615,7 +1615,7 @@ static struct btt *btt_init(struct nd_btif (btt->init_state !=INIT_READY && nd_region->ro) {dev_warn (dev,"%s is read-only, unable to init btt metadata\n" ,dev_name (&nd_region->dev)); -return NULL ; + goto err; }else if (btt->init_state !=INIT_READY ) { btt->num_arenas = (rawsize /ARENA_MAX_SIZE ) + ((rawsize %ARENA_MAX_SIZE ) ?1 :0 );
@@ -1625,25 +1625,28 @@ static struct btt *btt_init(struct nd_bt ret =create_arenas (btt);if (ret) {dev_info (dev,"init: create_arenas: %d\n" , ret); -return NULL ; + goto err; } ret =btt_meta_init (btt);if (ret) {dev_err (dev,"init: error in meta_init: %d\n" , ret); -return NULL ; + goto err; } } ret =btt_blk_init (btt);if (ret) {dev_err (dev,"init: error in blk_init: %d\n" , ret); -return NULL ; + goto err; }btt_debugfs_init (btt);return btt; +err: +free_arenas (btt); +return NULL ; }/**
Greg Kroah-Hartman
maintainerPATCH 472/699 nvdimm/btt: Free arena sub-allocations on discover_arenas() error path
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
commit 13fe4cd9ddd0aacb7777812328be525a11ea3fea upstream.
Memory allocated by btt_freelist_init(), btt_rtt_init(), and btt_maplocks_init() is not freed on some discover_arenas() error paths. This leaks memory when arena discovery fails.
Add the missing kfree() calls to release the allocations before returning an error.
[ as: commit message and log edits ]
--- drivers/nvdimm/btt.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/nvdimm/btt.c +3 -0
@@ -923,6 +923,9 @@ static int discover_arenas(struct btt *breturn ret; out: +kfree (arena->freelist); +kfree (arena->rtt); +kfree (arena->map_locks);kfree (arena);free_arenas (btt); out_super:
Greg Kroah-Hartman
maintainerPATCH 473/699 lockd: Plug nlm_file leak when nlm_do_fopen() fails
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
commit f16a1513452edb532fec81e591c64c320866719c upstream.
A client can repeatedly drive nlm_do_fopen() failures by presenting file handles that the underlying export rejects. After kzalloc_obj() succeeds in nlm_lookup_file(), the freshly allocated nlm_file is not yet inserted into nlm_files[]. The nlm_do_fopen() failure path jumps to out_unlock, which releases nlm_file_mutex and returns without freeing the allocation, so each failure leaks one nlm_file.
Route the failure through out_free so kfree() runs before the function returns.
--- fs/lockd/svcsubs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/lockd/svcsubs.c +1 -1
@@ -139,7 +139,7 @@ nlm_lookup_file(struct svc_rqst *rqstp, nfserr =nlm_do_fopen (rqstp, file, mode);if (nfserr) - goto out_unlock; + goto out_free;hlist_add_head (&file->f_list, &nlm_files[hash]);
Greg Kroah-Hartman
maintainerPATCH 474/699 lockd: Plug nlm_file refcount leak on cached nlm_do_fopen() failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuck Lever <[email protected]>
commit 70a38f87bed7f0694fd07988b47b2db1e10d8df3 upstream.
The cached-file path in nlm_lookup_file() reaches the found: label unconditionally, even when nlm_do_fopen() fails. At that label *result and file->f_count are updated before the error is returned. The wrappers nlm3svc_lookup_file() and nlm4svc_lookup_file() then bail out of their switch without copying *result back to their caller, so the proc handler's local nlm_file pointer remains NULL and the cleanup path skips nlm_release_file(). The f_count increment is never released, and nlm_traverse_files() can no longer reap the file because its refcount never returns to zero between requests.
Short-circuit the cached path so neither *result nor f_count is touched when nlm_do_fopen() fails on a hashed nlm_file.
--- fs/lockd/svcsubs.c | 2 ++ 1 file changed, 2 insertions(+)
fs/lockd/svcsubs.c +2 -0
@@ -123,6 +123,8 @@ nlm_lookup_file(struct svc_rqst *rqstp,mutex_lock (&file->f_mutex); nfserr =nlm_do_fopen (rqstp, file, mode);mutex_unlock (&file->f_mutex); +if (nfserr) + goto out_unlock; goto found; }nlm_debug_print_fh ("creating file for" , &lock->fh);
Greg Kroah-Hartman
maintainerPATCH 475/699 MIPS: ip22-gio: fix gio device memory leak
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit 7de9a1b45f5a95b58145653c525c8fb80292d9ab upstream.
The gio device release callback was never wired up so gio devices are not freed when the last reference is dropped.
--- arch/mips/sgi-ip22/ip22-gio.c | 2 ++ 1 file changed, 2 insertions(+)
arch/mips/sgi-ip22/ip22-gio.c +2 -0
@@ -101,6 +101,8 @@ int gio_device_register(struct gio_devic { giodev->dev.bus = &gio_bus_type; giodev->dev.parent = &gio_bus; + giodev->dev.release = gio_release_dev; +return device_register (&giodev->dev); }EXPORT_SYMBOL_GPL (gio_device_register);
Greg Kroah-Hartman
maintainerPATCH 476/699 MIPS: ip22-gio: fix kfree() of static object
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit c62cdd3e919bdf84c37ec46810f87cdb1736e822 upstream.
The gio bus root device is a statically allocated object which must not be freed by kfree() on failure to register the device or bus.
--- arch/mips/sgi-ip22/ip22-gio.c | 1 - 1 file changed, 1 deletion(-)
arch/mips/sgi-ip22/ip22-gio.c +0 -1
@@ -30,7 +30,6 @@ static struct {static void gio_bus_release (struct device *dev) { -kfree (dev); }static struct device gio_bus = {
Greg Kroah-Hartman
maintainerPATCH 477/699 MIPS: ip22-gio: fix device reference leak in probe
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Johan Hovold <[email protected]>
commit b82930a4c5dbc5c4df39c0f93d968c239f2c6885 upstream.
The gio probe function needlessly takes a device reference which is never released and therefore prevents unbound gio devices from being freed.
--- arch/mips/sgi-ip22/ip22-gio.c | 4 ---- 1 file changed, 4 deletions(-)
arch/mips/sgi-ip22/ip22-gio.c +0 -4
@@ -133,13 +133,9 @@ static int gio_device_probe(struct devicif (!drv->probe)return error; -gio_dev_get (gio_dev); - match =gio_match_device (drv->id_table, gio_dev);if (match) error = drv->probe (gio_dev, match); -if (error) -gio_dev_put (gio_dev);return error; }
Greg Kroah-Hartman
maintainerPATCH 478/699 MIPS: DEC: Ensure 32-bit stack location for o32 prom_printf()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maciej W. Rozycki <[email protected]>
commit 5ff79e8bdc75db51e30298a75939e2308e7658e0 upstream.
In 64-bit configurations calling any firmware entry points 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.
Consequently the stack pointer is no longer a 32-bit value and when the 32-bit firmware code called uses 32-bit ALU operations to manipulate the stack pointer, the calculated result is incorrect (in fact in the 64-bit MIPS ISA almost all 32-bit ALU operations will produce an unpredictable result when executed on 64-bit data) and control goes astray.
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, and the kernel will hang at:
pid_max: default: 32768 minimum: 301
or somewhat later, but always before:
cblist_init_generic: Setting adjustable number of callback queues.
has been printed.
It seems that only the prom_printf() entry point is affected. Of all the other entry points wired only rex_slot_address() and rex_gettcinfo() are called from a kernel thread other than the initial one, specifically kernel_init(), and they are leaf functions that do no business with the stack, having worked with no issue ever since 64-bit support was added for the platform back in 2002.
To address this issue then, arrange for the stack to be switched in the o32 wrapper as required for prom_printf() only, by supplying call_o32() with a pointer to a chunk of initdata space, which is placed in the CKSEG0 32-bit compatibility segment, observing that prom_printf() is only called from console output handler and therefore with the console lock held, implying no need for this code to be reentrant.
Other firmware entry points may be called with interrupts enabled and no lock held, and may therefore require that call_o32() be reentrant. They trigger no issue at this point and "if it ain't broke, don't fix it," so just leave them alone.
--- arch/mips/dec/prom/init.c | 6 +++++- arch/mips/include/asm/dec/prom.h | 15 +++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-)
arch/mips/dec/prom/init.c +5 -1
@@ -3,7 +3,7 @@* init.c: PROM library initialisation code. * * Copyright (C) 1998 Harald Koerfgen -* Copyright (C) 2002, 2004 Maciej W. Rozycki +* Copyright (C) 2002, 2004, 2026 Maciej W. Rozycki */ #include <linux/init.h> #include <linux/kernel.h>
@@ -20,6 +20,10 @@#include <asm/dec/prom.h> +#ifdef CONFIG_64BIT +unsigned long o32_stk[O32_STK_SIZE ]__initdata = {0 }; +#endif +int (*__rex_bootinit)(void );int (*__rex_bootread)(void );int (*__rex_getbitmap)(memmap *);
arch/mips/include/asm/dec/prom.h +13 -2
@@ -4,7 +4,7 @@* * DECstation PROM interface. * -* Copyright (C) 2002 Maciej W. Rozycki +* Copyright (C) 2002, 2026 Maciej W. Rozycki * * Based on arch/mips/dec/prom/prom.h by the Anonymous. */
@@ -97,6 +97,17 @@ extern int (*__pmax_close)(int);#ifdef CONFIG_64BIT +#define O32_STK_SIZE 512 +extern unsigned long o32_stk[]; + +/* Switch the stack if outside the 32-bit address space. */ +static inline unsigned long *o32_get_stk (void ) +{ +long fp = (long )__builtin_frame_address (0 ); + +return fp != (int )fp ? o32_stk +O32_STK_SIZE :NULL ; +} +/* * On MIPS64 we have to call PROM functions via a helper * dispatcher to accommodate ABI incompatibilities.
@@ -128,7 +139,7 @@ int __DEC_PROM_O32(_prom_printf, (int (*#define prom_getchar () _prom_getchar(__prom_getchar, NULL)#define prom_getenv (x) _prom_getenv(__prom_getenv, NULL, x) -#define prom_printf(x...) _prom_printf(__prom_printf, NULL, x) +#define prom_printf(x...) _prom_printf(__prom_printf, o32_get_stk(), x)#else /* !CONFIG_64BIT */
Greg Kroah-Hartman
maintainerPATCH 479/699 power: supply: charger-manager: fix refcount leak in is_full_charged()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: WenTao Liang <[email protected]>
commit 4373cfa38ead58f980362c841b0d0bdf8c4d956c upstream.
In is_full_charged(), power_supply_get_by_name() is called to obtain a reference to the fuel_gauge power supply. If the voltage check (uV >= desc->fullbatt_uV) succeeds, the function returns true directly without releasing the reference, leaking the refcount.
Fix this by setting a flag and jumping to the out label where power_supply_put() properly drops the reference.
--- drivers/power/supply/charger-manager.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/power/supply/charger-manager.c +4 -2
@@ -302,8 +302,10 @@ static bool is_full_charged(struct chargif (cm->battery_status ==POWER_SUPPLY_STATUS_FULL && desc->fullbatt_vchkdrop_uV) uV += desc->fullbatt_vchkdrop_uV; -if (uV >= desc->fullbatt_uV) -return true; +if (uV >= desc->fullbatt_uV) { + is_full = true; + goto out; + } } }
Greg Kroah-Hartman
maintainerPATCH 480/699 proc: only bump parent nlink when registering directories
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Krzysztof Wilczyński <[email protected]>
commit 16b02eb4b9b272c221255c20d34ccd5db53a3ed3 upstream.
proc_register() increments the parent directory's link count for every entry it registers, while remove_proc_entry() and remove_proc_subtree() decrement it only when the removed entry is a directory. Regular files thus inflate the parent's count while they exist, and leak one link permanently on every create and remove cycle.
For example, /proc/bus/pci/00 with twenty-two device files and no subdirectories reports nlink 24 instead of 2, and SR-IOV VF enable and disable cycles, each creating and removing the VF config space entries under /proc/bus/pci/<bus>, inflate the link count of that directory without bound.
Before commit e06689bf5701 ("proc: change ->nlink under proc_subdir_lock"), the increment lived in proc_mkdir_data() and proc_create_mount_point(), and was therefore applied only to directories. Moving it into proc_register() to bring it under proc_subdir_lock dropped the S_ISDIR check.
Thus, move the nlink accounting into pde_subdir_insert() and pde_erase(), only updating it for directories in both, so the link count is always changed together with the directory entry itself.
--- fs/proc/generic.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-)
fs/proc/generic.c +4 -5
@@ -112,6 +112,8 @@ static bool pde_subdir_insert(struct pro/* Add new node and rebalance tree. */ rb_link_node (&de->subdir_node, parent, new);rb_insert_color (&de->subdir_node, root); +if (S_ISDIR (de->mode)) + dir->nlink++;return true; }
@@ -383,7 +385,6 @@ struct proc_dir_entry *proc_register(strwrite_unlock (&proc_subdir_lock); goto out_free_inum; } - dir->nlink++;write_unlock (&proc_subdir_lock);return dp;
@@ -697,6 +698,8 @@ static void pde_erase(struct proc_dir_en {rb_erase (&pde->subdir_node, &parent->subdir);RB_CLEAR_NODE (&pde->subdir_node); +if (S_ISDIR (pde->mode)) + parent->nlink--; }/*
@@ -722,8 +725,6 @@ void remove_proc_entry(const char *name, de =NULL ; }else {pde_erase (de, parent); -if (S_ISDIR (de->mode)) - parent->nlink--; } }write_unlock (&proc_subdir_lock);
@@ -782,8 +783,6 @@ int remove_proc_subtree(const char *namecontinue ; } next = de->parent; -if (S_ISDIR (de->mode)) - next->nlink--;write_unlock (&proc_subdir_lock);proc_entry_rundown (de);
Greg Kroah-Hartman
maintainerPATCH 481/699 mtd: slram: remove failed entries from the device list
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
commit 36f1648644d769c496a8e47e53603e863e358d73 upstream.
register_device() links a new slram_mtdlist entry before allocating all of the state needed by the entry. If a later allocation, memremap(), or mtd_device_register() fails, the partially initialized entry remains on the global list. A later cleanup can then dereference or free invalid state from that failed entry.
Unwind the partially initialized entry and clear the list tail on each failure path after the entry has been linked.
--- drivers/mtd/devices/slram.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-)
drivers/mtd/devices/slram.c +16 -6
@@ -129,6 +129,7 @@ static int slram_write(struct mtd_info *static int register_device (char *name,unsigned long start,unsigned long length) {slram_mtd_list_t **curmtd; +int ret = -ENOMEM ; curmtd = &slram_mtdlist;while (*curmtd) {
@@ -155,14 +156,15 @@ static int register_device(char *name, uif (!(*curmtd)->mtdinfo) {E ("slram: Cannot allocate new MTD device.\n" ); -return (-ENOMEM ); + goto err_free_list; }if (!(((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start =memremap (start, length,MEMREMAP_WB |MEMREMAP_WT |MEMREMAP_WC ))) {E ("slram: memremap failed\n" ); -return -EIO ; + ret = -EIO ; + goto err_free_priv; } ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end = ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start + length;
@@ -183,10 +185,8 @@ static int register_device(char *name, uif (mtd_device_register ((*curmtd)->mtdinfo,NULL ,0 )) {E ("slram: Failed to register new device\n" ); -memunmap (((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start); -kfree ((*curmtd)->mtdinfo->priv); -kfree ((*curmtd)->mtdinfo); -return (-EAGAIN ); + ret = -EAGAIN ; + goto err_unmap; }T ("slram: Registered device %s from %luKiB to %luKiB\n" , name, (start /1024 ), ((start + length) /1024 ));
@@ -194,6 +194,16 @@ static int register_device(char *name, u ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start, ((slram_priv_t *)(*curmtd)->mtdinfo->priv)->end);return (0 ); + +err_unmap: +memunmap (((slram_priv_t *)(*curmtd)->mtdinfo->priv)->start); +err_free_priv: +kfree ((*curmtd)->mtdinfo->priv); +err_free_list: +kfree ((*curmtd)->mtdinfo); +kfree (*curmtd); + *curmtd =NULL ; +return ret; }static void unregister_devices (void )
Greg Kroah-Hartman
maintainerPATCH 482/699 scsi: smartpqi: Use shost_to_hba() in pqi_scan_finished()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Martin Wilck <[email protected]>
commit 57db1307afb1f83d45f5ff53b93f8d040100d13e upstream.
shost_to_hba() is used everywhere except to obtain pqi_ctrl_info from shosti, except in pqi_scan_finished(), where shost_priv() is used. This causes one pointer dereference to be missed, as shost->hostdata is a pointer in smartpqi. Fix it.
--- drivers/scsi/smartpqi/smartpqi_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/scsi/smartpqi/smartpqi_init.c +1 -1
@@ -2191,7 +2191,7 @@ static int pqi_scan_finished(struct Scsi {struct pqi_ctrl_info *ctrl_info; - ctrl_info =shost_priv (shost); + ctrl_info =shost_to_hba (shost);return !mutex_is_locked (&ctrl_info->scan_mutex); }
Greg Kroah-Hartman
maintainerPATCH 483/699 ocfs2: use kzalloc for quota recovery bitmap allocation
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Tristan Madani <[email protected]>
commit 93c8c6ea90be9e9df8fe14048ad4e3caad0770a6 upstream.
ocfs2 quota recovery allocates a bitmap buffer with kmalloc and does not fully initialize it. This can lead to use of uninitialized bits during quota recovery from a corrupted filesystem image.
Use kzalloc instead to ensure the bitmap is zero-initialized.
--- fs/ocfs2/quota_local.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/ocfs2/quota_local.c +1 -1
@@ -302,7 +302,7 @@ static int ocfs2_add_recovery_chunk(struif (!rc)return -ENOMEM ; rc->rc_chunk = chunk; - rc->rc_bitmap =kmalloc (sb->s_blocksize,GFP_NOFS ); + rc->rc_bitmap =kzalloc (sb->s_blocksize,GFP_NOFS );if (!rc->rc_bitmap) {kfree (rc);return -ENOMEM ;
Greg Kroah-Hartman
maintainerPATCH 484/699 mtd: rawnand: fix condition in nand_select_target()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arseniy Krasnov <[email protected]>
commit 8507c2cc9e4fa402401819f44d1e8a5ef4d11d8b upstream.
'cs' here must be in range [0:nanddev_ntargets[.
--- drivers/mtd/nand/raw/nand_base.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/mtd/nand/raw/nand_base.c +1 -1
@@ -174,7 +174,7 @@ void nand_select_target(struct nand_chip* cs should always lie between 0 and nanddev_ntargets(), when that's * not the case it's a bug and the caller should be fixed. */ -if (WARN_ON (cs >nanddev_ntargets (&chip->base))) +if (WARN_ON (cs >=nanddev_ntargets (&chip->base)))return ; chip->cur_cs = cs;
Greg Kroah-Hartman
maintainerPATCH 485/699 ocfs2: avoid moving extents to occupied clusters
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kyle Zeng <[email protected]>
commit 22920541c35a9f23f219038ba5874c843a7c4419 upstream.
For non-auto OCFS2_IOC_MOVE_EXT operations, userspace supplies a physical me_goal. ocfs2_move_extent() initializes new_phys_cpos from that goal and expects ocfs2_probe_alloc_group() to replace it with a free run in the target block group.
The probe currently leaves *phys_cpos unchanged if the scan reaches the end of the group without finding a free run. An occupied goal at the last bit can therefore survive the probe and be passed to __ocfs2_move_extent(), which copies file data into a cluster still owned by another inode before the bitmap is updated.
When the probe does find a free run, it also subtracts move_len from the ending bit. The start of an N-bit run ending at i is i - N + 1, so the current calculation can report the bit immediately before the free run.
Clear *phys_cpos before scanning and use the correct free-run start. Callers already treat a zero result as -ENOSPC, so failed probes no longer continue with an occupied caller-controlled goal.
--- fs/ocfs2/move_extents.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
fs/ocfs2/move_extents.c +3 -1
@@ -536,6 +536,8 @@ static void ocfs2_probe_alloc_group(struu32 base_cpos =ocfs2_blocks_to_clusters (inode->i_sb,le64_to_cpu (gd->bg_blkno)); + *phys_cpos =0 ; +for (i = base_bit; i <le16_to_cpu (gd->bg_bits); i++) { used =ocfs2_test_bit (i, (unsigned long *)gd->bg_bitmap);
@@ -557,7 +559,7 @@ static void ocfs2_probe_alloc_group(stru last_free_bits++;if (last_free_bits == move_len) { - i -= move_len; + i = i - move_len +1 ; *goal_bit = i; *phys_cpos = base_cpos + i;break ;
Greg Kroah-Hartman
maintainerPATCH 486/699 ocfs2: fix NULL h_transaction deref in ocfs2_assure_trans_credits
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ian Bridges <[email protected]>
commit f9ab30c96b0f00c20c6dac93681bdae3a033d229 upstream.
[BUG]
A direct write over unwritten extents can panic the kernel in ocfs2_assure_trans_credits() when the journal aborts during DIO completion. The crash is a general protection fault from a NULL pointer dereference.
[CAUSE]ocfs2_dio_end_io_write() loops over a direct write's unwritten extents, marking each written under a single journal handle. If the journal aborts (for example after an I/O error) while the extent tree is being updated, the handle is left aborted with its transaction pointer cleared. The extent merge treats that failure as not critical and reports success, so the loop keeps using the handle. ocfs2_assure_trans_credits() reads the handle's remaining credits without first checking whether the handle is aborted, and that read dereferences the cleared transaction pointer.
[FIX]
A journal abort is recorded in the handle itself, so callers are expected to test the handle rather than rely on a returned error. Make ocfs2_assure_trans_credits() do that, as the other ocfs2 journal helpers already do, and return -EROFS when the handle is aborted.
--- fs/ocfs2/journal.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
fs/ocfs2/journal.c +5 -1
@@ -480,8 +480,12 @@ bail:*/ int ocfs2_assure_trans_credits (handle_t *handle,int nblocks) { -int old_nblks =jbd2_handle_buffer_credits (handle); +int old_nblks; +if (is_handle_aborted (handle)) +return -EROFS ; + + old_nblks =jbd2_handle_buffer_credits (handle);trace_ocfs2_assure_trans_credits (old_nblks);if (old_nblks >= nblocks)return 0 ;
Greg Kroah-Hartman
maintainerPATCH 487/699 ocfs2: reject dinodes with non-canonical i_mode type
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 5366a017099c6a3c443be908a05f26fd72af12a1 upstream.
Patch series "ocfs2: harden inode validators against forged metadata", v2.
This series adds three structural checks to OCFS2 dinode validation so malformed on-disk fields are rejected before ocfs2_populate_inode() copies them into the in-core inode.
The checks cover:
- i_mode values whose type bits do not name a canonical POSIX file
type;
- non-device dinodes whose id1.dev1.i_rdev field is non-zero; and
- non-inline dinodes that claim non-zero i_size while i_clusters is zero, covering directories unconditionally and regular files on non-sparse volumes.
The normal read path reports these through ocfs2_error(), matching the existing suballoc-slot, inline-data, chain-list, and refcount checks. The online filecheck path uses the same structural predicates but keeps its own reporting contract, returning OCFS2_FILECHECK_ERR_INVALIDINO instead of calling ocfs2_error().
This patch (of 3):
ocfs2_validate_inode_block() currently accepts any non-zero i_mode value. ocfs2_populate_inode() then copies that mode verbatim into inode->i_mode and dispatches on i_mode & S_IFMT to the file/dir/symlink/special_file iops; an unrecognised type falls through to ocfs2_special_file_iops and init_special_inode().
Reject dinodes whose type bits do not name one of the seven canonical POSIX file types. Use fs_umode_to_ftype(), the same generic file-type conversion helper OCFS2 already uses for directory entries, so the accepted inode type set matches the kernel file-type vocabulary instead of open-coding a local switch.
Apply the same structural check to the online filecheck read path. filecheck keeps its own error namespace, so it reports malformed i_mode through the filecheck logger and OCFS2_FILECHECK_ERR_INVALIDINO instead of calling ocfs2_error(), but it must not allow a malformed dinode to proceed into ocfs2_populate_inode().
--- fs/ocfs2/inode.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-)
fs/ocfs2/inode.c +33 -2
@@ -68,7 +68,12 @@ static int ocfs2_filecheck_read_inode_blstatic int ocfs2_filecheck_validate_inode_block (struct super_block *sb,struct buffer_head *bh);static int ocfs2_filecheck_repair_inode_block (struct super_block *sb, -struct buffer_head *bh); +struct buffer_head *bh); + +static bool ocfs2_valid_inode_mode (umode_t mode) +{ +return fs_umode_to_ftype (mode) !=FT_UNKNOWN ; +}void ocfs2_set_inode_flags (struct inode *inode) {
@@ -1418,6 +1423,24 @@ int ocfs2_validate_inode_block(struct su goto bail; } +/* +* Reject dinodes whose i_mode does not name one of the seven +* canonical POSIX file types. ocfs2_populate_inode() copies +* i_mode verbatim into inode->i_mode and then dispatches via +* switch (mode & S_IFMT) to file/dir/symlink/special_file iops; +* an unrecognised type falls into ocfs2_special_file_iops with +* init_special_inode(), which interprets i_rdev. Constrain the +* type here so the dispatch only ever sees a value mkfs.ocfs2 / +* VFS can produce. +*/ +if (!ocfs2_valid_inode_mode (le16_to_cpu (di->i_mode))) { + rc =ocfs2_error (sb, +"Invalid dinode #%llu: mode 0%o has unknown file type\n" , + (unsigned long long )bh->b_blocknr, +le16_to_cpu (di->i_mode)); + goto bail; + } +if (le16_to_cpu (di->i_dyn_features) &OCFS2_INLINE_DATA_FL ) {struct ocfs2_inline_data *data = &di->id2.i_data;
@@ -1514,6 +1537,15 @@ static int ocfs2_filecheck_validate_inod (unsigned long long )bh->b_blocknr, le32_to_cpu(di->i_fs_generation)); rc = -OCFS2_FILECHECK_ERR_GENERATION ; + goto bail; + } + +if (!ocfs2_valid_inode_mode (le16_to_cpu (di->i_mode))) { +mlog (ML_ERROR , +"Filecheck: invalid dinode #%llu: mode 0%o has unknown file type\n" , + (unsigned long long )bh->b_blocknr, +le16_to_cpu (di->i_mode)); + rc = -OCFS2_FILECHECK_ERR_INVALIDINO ; } bail:
@@ -1689,4 +1721,3 @@ const struct ocfs2_caching_operations oc .co_io_lock = ocfs2_inode_cache_io_lock, .co_io_unlock = ocfs2_inode_cache_io_unlock, }; -
Greg Kroah-Hartman
maintainerPATCH 488/699 ocfs2: reject dinodes whose i_rdev disagrees with the file type
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 51407c2d249987a466416890a5c931a2354a46aa upstream.
id1.dev1.i_rdev is the device-number arm of the ocfs2_dinode id1 union. It is only meaningful for character and block device inodes. For any other user-visible file type the on-disk value must be zero.
ocfs2_populate_inode() currently copies id1.dev1.i_rdev into inode->i_rdev before the S_IFMT switch decides whether the inode is a special file. A non-device inode with a non-zero i_rdev can therefore publish stale or attacker-controlled device state into the in-core inode.
System inodes legitimately use other arms of the same union, so keep the cross-check restricted to non-system inodes. Factor that predicate into a helper and use it in both the normal validator and online filecheck path; filecheck reports the malformed dinode through OCFS2_FILECHECK_ERR_INVALIDINO instead of ocfs2_error().
--- fs/ocfs2/inode.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+)
fs/ocfs2/inode.c +55 -0
@@ -75,6 +75,16 @@ static bool ocfs2_valid_inode_mode(umodereturn fs_umode_to_ftype (mode) !=FT_UNKNOWN ; } +static bool ocfs2_dinode_has_unexpected_rdev (struct ocfs2_dinode *di) +{ +umode_t mode =le16_to_cpu (di->i_mode); + +if (le32_to_cpu (di->i_flags) &OCFS2_SYSTEM_FL ) +return false; + +return !S_ISCHR (mode) && !S_ISBLK (mode) && di->id1.dev1.i_rdev !=0 ; +} +void ocfs2_set_inode_flags (struct inode *inode) {unsigned int flags =OCFS2_I (inode)->ip_attr;
@@ -1441,6 +1451,41 @@ int ocfs2_validate_inode_block(struct su goto bail; } +/* +* id1.dev1.i_rdev is the device-number arm of the id1 union and +* is only meaningful for character and block device inodes. For +* any other regular user-visible file type the on-disk value +* must be zero. ocfs2_populate_inode() currently runs +* +* inode->i_rdev = huge_decode_dev(le64_to_cpu(fe->id1.dev1.i_rdev)); +* +* unconditionally, before the S_IFMT switch decides whether the +* inode is a special file. As a result, an i_rdev value present +* on a non-device inode is silently published into the in-core +* inode; a subsequent forced re-read or in-core mode mutation +* (cluster peer with raw write access to the shared LUN, +* on-disk corruption, or a separately forged dinode) can then +* expose the attacker-controlled device number to +* init_special_inode() without ever showing an unusual i_mode +* at validation time. +* +* System inodes (OCFS2_SYSTEM_FL) legitimately use the bitmap1 +* and journal1 arms of the same union (allocator i_used / +* i_total counters and the journal ij_flags / +* ij_recovery_generation pair); those bytes are not an i_rdev +* and must not be checked here. Restrict the cross-check to +* non-system inodes, which is the full attacker-controllable +* surface. +*/ +if (ocfs2_dinode_has_unexpected_rdev (di)) { + rc =ocfs2_error (sb, +"Invalid dinode #%llu: non-device mode 0%o with i_rdev %llu\n" , + (unsigned long long )bh->b_blocknr, +le16_to_cpu (di->i_mode), + (unsigned long long )le64_to_cpu (di->id1.dev1.i_rdev)); + goto bail; + } +if (le16_to_cpu (di->i_dyn_features) &OCFS2_INLINE_DATA_FL ) {struct ocfs2_inline_data *data = &di->id2.i_data;
@@ -1546,6 +1591,16 @@ static int ocfs2_filecheck_validate_inod (unsigned long long )bh->b_blocknr, le16_to_cpu(di->i_mode)); rc = -OCFS2_FILECHECK_ERR_INVALIDINO ; + goto bail; + } + +if (ocfs2_dinode_has_unexpected_rdev (di)) { +mlog (ML_ERROR , +"Filecheck: invalid dinode #%llu: non-device mode 0%o with i_rdev %llu\n" , + (unsigned long long )bh->b_blocknr, +le16_to_cpu (di->i_mode), + (unsigned long long )le64_to_cpu (di->id1.dev1.i_rdev)); + rc = -OCFS2_FILECHECK_ERR_INVALIDINO ; } bail:
Greg Kroah-Hartman
maintainerPATCH 489/699 ocfs2: reject non-inline dinodes with i_size and zero i_clusters
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 7ebc672fab7a76e1e47e0f2fc1ee48118d27fde4 upstream.
On a volume mounted without OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC, a non-inline regular file with non-zero i_size and zero i_clusters is structurally malformed: the extent map declares no allocated clusters yet the size header claims content exists. Keep rejecting that shape, but express it through a shared predicate so the same invariant is available to normal inode reads and online filecheck.
The same zero-cluster shape is also malformed for non-inline directories. ocfs2 directory growth allocates backing storage before advancing i_size, and ocfs2_dir_foreach_blk_el() later walks until ctx->pos reaches i_size_read(inode). A forged directory dinode with a huge i_size and no clusters would repeatedly fail on holes while advancing through the claimed size.
Sparse regular files remain exempt: on sparse-alloc volumes, truncate can legitimately grow i_size without allocating clusters. System inodes and inline-data dinodes also retain their separate storage rules.
Mirror the check in ocfs2_filecheck_validate_inode_block() as well. filecheck reports through its own error namespace, so malformed size/cluster state is logged as a filecheck invalid-inode result rather than via ocfs2_error(), but it must not proceed into ocfs2_populate_inode().
--- fs/ocfs2/inode.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+)
fs/ocfs2/inode.c +60 -0
@@ -85,6 +85,24 @@ static bool ocfs2_dinode_has_unexpected_return !S_ISCHR (mode) && !S_ISBLK (mode) && di->id1.dev1.i_rdev !=0 ; } +static bool ocfs2_dinode_has_size_without_clusters (struct super_block *sb, +struct ocfs2_dinode *di) +{ +umode_t mode =le16_to_cpu (di->i_mode); + +if (le32_to_cpu (di->i_flags) &OCFS2_SYSTEM_FL ) +return false; +if (le16_to_cpu (di->i_dyn_features) &OCFS2_INLINE_DATA_FL ) +return false; +if (!le64_to_cpu (di->i_size) ||le32_to_cpu (di->i_clusters)) +return false; + +if (S_ISDIR (mode)) +return true; + +return !ocfs2_sparse_alloc (OCFS2_SB (sb)) &&S_ISREG (mode); +} +void ocfs2_set_inode_flags (struct inode *inode) {unsigned int flags =OCFS2_I (inode)->ip_attr;
@@ -1486,6 +1504,33 @@ int ocfs2_validate_inode_block(struct su goto bail; } +/* +* Non-inline directories must not have i_size without allocated +* clusters: directory growth adds storage before advancing i_size, +* and readdir walks i_size block-by-block. A forged directory +* with zero clusters and a huge i_size would repeatedly fault on +* holes while advancing through the claimed size. +* +* Non-inline regular files have the same invariant on non-sparse +* volumes. Sparse regular files are different: truncate can +* legitimately grow i_size without allocating clusters, so keep +* the sparse-alloc carveout for S_IFREG only. System inodes and +* inline-data dinodes have their own storage rules. +*/ +if (ocfs2_dinode_has_size_without_clusters (sb, di)) { +if (S_ISDIR (le16_to_cpu (di->i_mode))) + rc =ocfs2_error (sb, +"Invalid dinode #%llu: directory i_size %llu with i_clusters 0 and no inline-data flag\n" , + (unsigned long long )bh->b_blocknr, + (unsigned long long )le64_to_cpu (di->i_size)); +else + rc =ocfs2_error (sb, +"Invalid dinode #%llu: regular file i_size %llu with i_clusters 0 and no inline-data flag on non-sparse volume\n" , + (unsigned long long )bh->b_blocknr, + (unsigned long long )le64_to_cpu (di->i_size)); + goto bail; + } +if (le16_to_cpu (di->i_dyn_features) &OCFS2_INLINE_DATA_FL ) {struct ocfs2_inline_data *data = &di->id2.i_data;
@@ -1601,6 +1646,21 @@ static int ocfs2_filecheck_validate_inodle16_to_cpu (di->i_mode), (unsigned long long)le64_to_cpu(di->id1.dev1.i_rdev)); rc = -OCFS2_FILECHECK_ERR_INVALIDINO ; + goto bail; + } + +if (ocfs2_dinode_has_size_without_clusters (sb, di)) { +if (S_ISDIR (le16_to_cpu (di->i_mode))) +mlog (ML_ERROR , +"Filecheck: invalid dinode #%llu: directory i_size %llu with i_clusters 0 and no inline-data flag\n" , + (unsigned long long )bh->b_blocknr, + (unsigned long long )le64_to_cpu (di->i_size)); +else +mlog (ML_ERROR , +"Filecheck: invalid dinode #%llu: regular file i_size %llu with i_clusters 0 and no inline-data flag on non-sparse volume\n" , + (unsigned long long )bh->b_blocknr, + (unsigned long long )le64_to_cpu (di->i_size)); + rc = -OCFS2_FILECHECK_ERR_INVALIDINO ; } bail:
Greg Kroah-Hartman
maintainerPATCH 490/699 mtd: maps: vmu-flash: fix NULL pointer dereference in initialization
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Florian Fuchs <[email protected]>
commit 357e3b8e3a8769ba36eb8ec5e053e4825f1a9329 upstream.
The mtd_info contains a struct device, which must be linked to its parent. Without this, the initialization of the MTD fails with a NULL pointer dereference.
--- drivers/mtd/maps/vmu-flash.c | 1 + 1 file changed, 1 insertion(+)
drivers/mtd/maps/vmu-flash.c +1 -0
@@ -547,6 +547,7 @@ static void vmu_queryblocks(struct maple mpart->partition = card->partition; mtd_cur->priv = mpart; mtd_cur->owner =THIS_MODULE ; + mtd_cur->dev.parent = &mdev->dev; pcache =kzalloc (sizeof (struct vmu_cache ),GFP_KERNEL );if (!pcache)
Greg Kroah-Hartman
maintainerPATCH 491/699 irqchip/crossbar: Use correct index in crossbar_domain_free()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bhargav Joshi <[email protected]>
commit 043db005a8d6932dc7d217c86307e9af0bc10ddc upstream.
crossbar_domain_free() resets the domain data and then uses the nulled out irq_data->hwirq member as index to reset the irq_map[] entry and to write the relevant crossbar register with a safe entry. That means it never frees the correct index and keeps the crossbar register connection to the source interrupt active.
If it would not reset the domain data, then this would be even worse as irq_data->hwirq holds the source interrupt number, but both the map and register index need the corresponding GIC SPI number and not the source interrupt number. This might even result in an out of bounds access as the source interrupt number can be higher than the maximal index space.
Fix this by using the GIC SPI index from the parent domain's irq_data.
--- drivers/irqchip/irq-crossbar.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/irqchip/irq-crossbar.c +7 -2
@@ -158,9 +158,14 @@ static void crossbar_domain_free(structfor (i =0 ; i < nr_irqs; i++) {struct irq_data *d =irq_domain_get_irq_data (domain, virq + i); +/* +* irq_map[] is indexed by GIC SPI number. The parent domain's +* hwirq contains the GIC interrupt number (GIC SPI + +* GIC_IRQ_START). +*/ + cb->irq_map[d->parent_data->hwirq -GIC_IRQ_START ] =IRQ_FREE ; + cb->write (d->parent_data->hwirq -GIC_IRQ_START , cb->safe_map);irq_domain_reset_irq_data (d); - cb->irq_map[d->hwirq] =IRQ_FREE ; - cb->write (d->hwirq, cb->safe_map); }raw_spin_unlock (&cb->lock);irq_domain_free_irqs_parent (domain, virq, nr_irqs);
Greg Kroah-Hartman
maintainerPATCH 492/699 i2c: mediatek: fix WRRD for SoCs without auto_restart option
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Roman Vivchar <[email protected]>
commit deb35336b5bfed5db9231b5348bc1514db930797 upstream.
MediaTek mt65xx family SoCs have no auto restart, however, they still support the WRRD mode in the hardware. Because auto_restart is set to 0, the WRRD mode will be never enabled, leading to read errors.
Fix this by removing auto_restart check from the WRRD enable path.
--- drivers/i2c/busses/i2c-mt65xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/busses/i2c-mt65xx.c +1 -1
@@ -1075,7 +1075,7 @@ static int mtk_i2c_transfer(struct i2c_a i2c->auto_restart = i2c->dev_comp->auto_restart;/* checking if we can skip restart and optimize using WRRD mode */ -if (i2c->auto_restart && num ==2 ) { +if (num ==2 ) {if (!(msgs[0 ].flags &I2C_M_RD ) && (msgs[1 ].flags &I2C_M_RD ) && msgs[0 ].addr == msgs[1 ].addr) { i2c->auto_restart =0 ;
Greg Kroah-Hartman
maintainerPATCH 493/699 i2c: mlxbf: Fix use-after-free in mlxbf_i2c_init_resource()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xuanqiang Luo <[email protected]>
commit 71356737a7a55c76fee847563e3d33f8e6dc6b6d upstream.
If devm_platform_get_and_ioremap_resource() returns an error, mlxbf_i2c_init_resource() frees tmp_res before reading tmp_res->io to get the error code. This results in a use-after-free.
Save the error code before freeing tmp_res.
--- drivers/i2c/busses/i2c-mlxbf.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/i2c/busses/i2c-mlxbf.c +3 -1
@@ -1063,8 +1063,10 @@ static int mlxbf_i2c_init_resource(struc tmp_res->io =devm_ioremap_resource (dev, tmp_res->params);if (IS_ERR (tmp_res->io)) { +int ret =PTR_ERR (tmp_res->io); +devm_kfree (dev, tmp_res); -return PTR_ERR (tmp_res->io); +return ret; } tmp_res->type = type;
Greg Kroah-Hartman
maintainerPATCH 494/699 xen/gntdev: fix error handling in ioctl
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <[email protected]>
commit 45ca1afe2fd14c04e37227e79d3f8455831d8408 upstream.
When gntdev_ioctl_map_grant_ref() fails to copy the operation result back to userspace after successfully adding the mapping to the list, the error path returns -EFAULT without releasing the reference acquired by gntdev_alloc_map(). The mapping remains in priv->maps with a refcount of 1, causing a memory leak and a dangling list entry.
Additionally, gntdev_add_map() may modify map->index to avoid overlap with existing mappings. Therefore, the index returned to userspace must be obtained after gntdev_add_map() completes.
Fix this by holding the mutex across gntdev_add_map(), retrieving the correct index, and copy_to_user(). If copy_to_user() fails, remove the mapping from the list and release the reference while still holding the lock.
Fix these issues by properly handling all error cases.
Message-ID: <[email protected]>
--- drivers/xen/gntdev.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
drivers/xen/gntdev.c +6 -2
@@ -668,11 +668,15 @@ static long gntdev_ioctl_map_grant_ref(smutex_lock (&priv->lock);gntdev_add_map (priv, map); op.index = map->index <<PAGE_SHIFT ; -mutex_unlock (&priv->lock); -if (copy_to_user (u, &op,sizeof (op)) !=0 ) +if (copy_to_user (u, &op,sizeof (op)) !=0 ) { +list_del (&map->next); +mutex_unlock (&priv->lock); +gntdev_put_map (priv, map);return -EFAULT ; + } +mutex_unlock (&priv->lock);return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 495/699 xfrm: use compat translator only for u64 alignment mismatch
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sanman Pradhan <[email protected]>
commit 355fbcbdc2539cca7890b0d0914d4ce0f985ad74 upstream.
The XFRM compat layer (CONFIG_XFRM_USER_COMPAT) translates 32-bit xfrm netlink and setsockopt messages into the native 64-bit layout. It is only needed on architectures where the 32-bit and 64-bit ABIs disagree on u64 alignment, which the kernel encodes as COMPAT_FOR_U64_ALIGNMENT.
That symbol is defined only by arch/x86. XFRM_USER_COMPAT depends on it, so the translator can never be built on any other architecture, including arm64, which still provides a 32-bit compat ABI (CONFIG_COMPAT) for AArch32 EL0 userspace. On arm64 the AArch32 EABI already aligns u64 to 8 bytes, identical to the AArch64 ABI, so no translation is required and the native code path is correct for 32-bit tasks.
However, xfrm_user_rcv_msg() and xfrm_user_policy() gate on in_compat_syscall() alone and then call xfrm_get_translator(), which returns NULL when no translator is registered. On arm64 that is always the case, so every xfrm netlink message and the XFRM_POLICY setsockopt issued by a 32-bit task returns -EOPNOTSUPP. A 32-bit userspace process on arm64 (and on any other arch with CONFIG_COMPAT but without COMPAT_FOR_U64_ALIGNMENT) therefore cannot configure XFRM state or policy through the XFRM_USER netlink API, and cannot use the XFRM_POLICY setsockopt path, because both fail before reaching the native parser.
The translator series replaced the blanket compat rejection with a translator lookup. That made the path usable on x86 when the translator is available, but left architectures that cannot build the translator permanently rejected even when their compat layout already matches the native layout. Let those architectures use the native parser instead.
Gate the translator requirement on COMPAT_FOR_U64_ALIGNMENT instead of on in_compat_syscall() alone. Gating on the ABI property rather than on CONFIG_XFRM_USER_COMPAT is deliberate: on x86 with IA32_EMULATION=y but XFRM_USER_COMPAT=n, a 32-bit task must still be rejected rather than routed through the native parser, which would misread genuinely 4-byte-aligned x86-32 messages. COMPAT_FOR_U64_ALIGNMENT is the ABI property that makes the XFRM translator mandatory.
Only the receive/input direction needs the guard. The send, dump and notification paths already call the translator as "if (xtr) { ... }" with no error on NULL, so on arches without a translator they no-op and the kernel emits native 64-bit-layout messages, which is what an AArch32 task expects.
Tested on Juniper SRX hardware: with the fix, 32-bit IPsec userspace netlink and XFRM_POLICY setsockopt operations that previously failed with -EOPNOTSUPP now succeed; x86 behaviour is unchanged by inspection.
--- net/xfrm/xfrm_state.c | 2 +- net/xfrm/xfrm_user.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
net/xfrm/xfrm_state.c +1 -1
@@ -2410,7 +2410,7 @@ int xfrm_user_policy(struct sock *sk, inif (IS_ERR (data))return PTR_ERR (data); -if (in_compat_syscall ()) { +if (IS_ENABLED (CONFIG_COMPAT_FOR_U64_ALIGNMENT ) &&in_compat_syscall ()) {struct xfrm_translator *xtr =xfrm_get_translator ();if (!xtr) {
net/xfrm/xfrm_user.c +1 -1
@@ -2833,7 +2833,7 @@ static int xfrm_user_rcv_msg(struct sk_bif (!netlink_net_capable (skb,CAP_NET_ADMIN ))return -EPERM ; -if (in_compat_syscall ()) { +if (IS_ENABLED (CONFIG_COMPAT_FOR_U64_ALIGNMENT ) &&in_compat_syscall ()) {struct xfrm_translator *xtr =xfrm_get_translator ();if (!xtr)
Greg Kroah-Hartman
maintainerPATCH 496/699 xfrm: xfrm_interface: require CAP_NET_ADMIN in the device netns for changelink
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maoyi Xie <[email protected]>
commit 095515d89b19b6cc19dfcdc846f97403ed1ebce3 upstream.
xfrmi_changelink() operates on at most two netns, dev_net(dev) and the interface link netns xi->net. They differ once the device is created in or moved to a netns other than the one the request runs in. The rtnl changelink path checks CAP_NET_ADMIN only against dev_net(dev), so a caller privileged there but not in xi->net can rewrite an interface that lives in xi->net.
Gate xfrmi_changelink() on rtnl_dev_link_net_capable() at its top, before any attribute is parsed.
--- net/xfrm/xfrm_interface_core.c | 3 +++ 1 file changed, 3 insertions(+)
net/xfrm/xfrm_interface_core.c +3 -0
@@ -726,6 +726,9 @@ static int xfrmi_changelink(struct net_dstruct net *net = xi->net;struct xfrm_if_parms p = {}; +if (!rtnl_dev_link_net_capable (dev, net)) +return -EPERM ; +xfrmi_netlink_parms (data, &p);if (!p.if_id) {NL_SET_ERR_MSG (extack,"if_id must be non zero" );
Greg Kroah-Hartman
maintainerPATCH 497/699 tpm: fix event_size output in tpm1_binary_bios_measurements_show
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Thorsten Blum <[email protected]>
commit 1a58f6115bfb34eabcc7de8a3a9745b219179781 upstream.
Commit 186d124f07da ("tpm_eventlog.c: fix binary_bios_measurements") split the output to write the endian-converted event header first and then the variable-length event data.
However, the split was at sizeof(struct tcpa_event) - 1, even though event_data was a zero-length array, and later a flexible array member, both of which already excluded the event data.
Therefore, the current code writes the first three bytes of event_size from the endian-converted header and then the last byte from the raw header, which can emit a corrupted event_size on PPC64, where do_endian_conversion() maps to be32_to_cpu().
Split one byte later to write the full endian-converted header first, followed by the variable-length event->event_data.
--- drivers/char/tpm/eventlog/tpm1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/char/tpm/eventlog/tpm1.c +2 -2
@@ -235,12 +235,12 @@ static int tpm1_binary_bios_measurements temp_ptr = (char *) &temp_event; -for (i =0 ; i < (sizeof (struct tcpa_event ) -1 ) ; i++) +for (i =0 ; i <sizeof (struct tcpa_event ); i++)seq_putc (m, temp_ptr[i]); temp_ptr = (char *) v; -for (i = (sizeof (struct tcpa_event ) -1 ); +for (i =sizeof (struct tcpa_event ); i < (sizeof (struct tcpa_event ) + temp_event.event_size); i++)seq_putc (m, temp_ptr[i]);
Greg Kroah-Hartman
maintainerPATCH 498/699 tpm: Make the TPM character devices non-seekable
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jaewon Yang <[email protected]>
commit f20d61c22bcaf172d6790b6500e3838e532e71c8 upstream.
The TPM character devices expose a sequential command/response interface, but their open handlers leave FMODE_PREAD and FMODE_PWRITE enabled.
After a command leaves a response pending, pread(fd, buf, 16, 0x1400) passes 0x1400 as *off to tpm_common_read(). The transfer length is bounded by response_length, but the offset is used unchecked when forming data_buffer + *off. A sufficiently large offset therefore causes an out-of-bounds heap read through copy_to_user() and, if the copy succeeds, an out-of-bounds zero-write through the following memset().
Positional I/O does not provide coherent semantics for this interface. An arbitrary pread offset cannot represent how much of a response has been consumed sequentially. The write callback always stores a command at the start of data_buffer, while pwrite() does not update file->f_pos and can leave the sequential read cursor stale.
Call nonseekable_open() from both open handlers. This removes FMODE_PREAD and FMODE_PWRITE, causing positional reads and writes to fail with -ESPIPE before reaching the TPM callbacks, and explicitly marks the files non-seekable. Normal read() and write() continue to use the existing sequential f_pos cursor, leaving the response state machine unchanged.
Tested on Linux 6.12 with KASAN and a swtpm TPM2 device:
- sequential partial reads returned the complete response
- pread() and preadv() with offset 0x1400 returned -ESPIPE
- pwrite() and pwritev() with offset zero returned -ESPIPE
- the pending response remained intact after the rejected operations
- a subsequent normal command/response cycle completed normally
- no KASAN report was produced.
--- drivers/char/tpm/tpm-dev.c | 2 +- drivers/char/tpm/tpmrm-dev.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/char/tpm/tpm-dev.c +1 -1
@@ -36,7 +36,7 @@ static int tpm_open(struct inode *inode,tpm_common_open (file, chip, priv,NULL ); -return 0 ; +return nonseekable_open (inode, file); out:clear_bit (0 , &chip->is_open);
drivers/char/tpm/tpmrm-dev.c +1 -1
@@ -29,7 +29,7 @@ static int tpmrm_open(struct inode *inodtpm_common_open (file, chip, &priv->priv, &priv->space); -return 0 ; +return nonseekable_open (inode, file); }static int tpmrm_release (struct inode *inode,struct file *file)
Greg Kroah-Hartman
maintainerPATCH 499/699 time: Fix off-by-one in compat settimeofday() usec validation
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wang Yan <[email protected]>
commit 269f2b43fae692d1f3988c9f888a6301aa537b82 upstream.
The compat version of settimeofday() uses '>' instead of '>=' when validating tv_usec against USEC_PER_SEC, allowing the value 1000000 to pass the check. After the subsequent conversion to nanoseconds (tv_nsec *= NSEC_PER_USEC), this results in tv_nsec == NSEC_PER_SEC, which violates the timespec invariant that tv_nsec must be strictly less than NSEC_PER_SEC.
The native settimeofday() was already fixed in commit ce4abda5e126 ("time:
Fix off-by-one in settimeofday() usec validation"), but the compat counterpart was missed.
Fix it by using '>=' to reject tv_usec values outside the valid range [0, USEC_PER_SEC - 1].
--- kernel/time/time.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
kernel/time/time.c +1 -1
@@ -251,7 +251,7 @@ COMPAT_SYSCALL_DEFINE2(settimeofday, str get_user(new_ts.tv_nsec, &tv->tv_usec))return -EFAULT ; -if (new_ts.tv_nsec >USEC_PER_SEC || new_ts.tv_nsec <0 ) +if (new_ts.tv_nsec >=USEC_PER_SEC || new_ts.tv_nsec <0 )return -EINVAL ; new_ts.tv_nsec *=NSEC_PER_USEC ;
Greg Kroah-Hartman
maintainerPATCH 500/699 spi: uniphier: Fix completion initialization order before devm_request_irq()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kunihiko Hayashi <[email protected]>
commit f3ad1c87d8201e54b66bd6072442f0b5d5a308ee upstream.
The driver calls devm_request_irq() before initializing the completion used by the interrupt handler. Because the interrupt may occur immediately after devm_request_irq(), the handler may execute before init_completion().
This may result in calling complete() on an uninitialized completion, causing undefined behavior. This has been observed with KASAN.
Fix this by initializing the completion before registering the IRQ.
--- drivers/spi/spi-uniphier.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/spi/spi-uniphier.c +2 -2
@@ -659,6 +659,8 @@ static int uniphier_spi_probe(struct pla priv->master = master; priv->is_save_param = false; +init_completion (&priv->xfer_done); + priv->base =devm_platform_get_and_ioremap_resource (pdev,0 , &res);if (IS_ERR (priv->base)) { ret =PTR_ERR (priv->base);
@@ -690,8 +692,6 @@ static int uniphier_spi_probe(struct pla goto out_disable_clk; } -init_completion (&priv->xfer_done); - clk_rate =clk_get_rate (priv->clk); master->max_speed_hz =DIV_ROUND_UP (clk_rate,SSI_MIN_CLK_DIVIDER );
Greg Kroah-Hartman
maintainerPATCH 501/699 sctp: validate STALE_COOKIE cause length before reading staleness
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
commit 1cd23ca80784223fa2204e16203f754da4e821f8 upstream.
When an ERROR chunk with a STALE_COOKIE cause is received in the COOKIE_ECHOED state, sctp_sf_do_5_2_6_stale() reads the 4-byte Measure of Staleness that follows the cause header:
err = (struct sctp_errhdr *)(chunk->skb->data); stale = ntohl(*(__be32 *)((u8 *)err + sizeof(*err)));
err is the first cause in the chunk, not the STALE_COOKIE cause that caused the dispatch, and nothing guarantees the staleness field is present. sctp_walk_errors() only requires a cause to be as long as the 4-byte header, so for a STALE_COOKIE cause of length 4 the read runs past the cause, and for a minimal ERROR chunk past skb->tail. The value is echoed to the peer in the Cookie Preservative of the reply INIT, leaking uninitialized memory.
sctp_sf_cookie_echoed_err() already walks to the STALE_COOKIE cause, so check its length there and pass it to sctp_sf_do_5_2_6_stale(), which reads that cause instead of the first one. A STALE_COOKIE cause too short to hold the staleness field is discarded.
The read is reachable by any peer that can drive an association into COOKIE_ECHOED, including an unprivileged process using a raw SCTP socket in a user and network namespace.
--- net/sctp/sm_statefuns.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-)
net/sctp/sm_statefuns.c +14 -9
@@ -73,7 +73,8 @@ static enum sctp_disposition sctp_sf_do_const struct sctp_association *asoc, const union sctp_subtype type, void *arg, - struct sctp_cmd_seq *commands); + struct sctp_cmd_seq *commands, + struct sctp_errhdr *err); static enum sctp_disposition sctp_sf_shut_8_4_5( struct net *net, const struct sctp_endpoint *ep,
@@ -2419,9 +2420,15 @@ enum sctp_disposition sctp_sf_cookie_ech* errors. */ sctp_walk_errors(err, chunk->chunk_hdr) { -if (SCTP_ERROR_STALE_COOKIE == err->cause) -return sctp_sf_do_5_2_6_stale (net, ep, asoc, type, - arg, commands); +if (err->cause !=SCTP_ERROR_STALE_COOKIE ) +continue ; +/* The staleness is only meaningful if the cause is long +* enough to hold it; a shorter one is malformed. +*/ +if (ntohs (err->length) <sizeof (*err) +sizeof (__be32)) +break ; +return sctp_sf_do_5_2_6_stale (net, ep, asoc, type, + arg, commands, err); }/* It is possible to have malformed error causes, and that
@@ -2463,13 +2470,13 @@ static enum sctp_disposition sctp_sf_do_const struct sctp_association *asoc, const union sctp_subtype type, void *arg, - struct sctp_cmd_seq *commands) + struct sctp_cmd_seq *commands, + struct sctp_errhdr *err) { int attempts = asoc->init_err_counter + 1; -struct sctp_chunk *chunk = arg, *reply;struct sctp_cookie_preserve_param bht;struct sctp_bind_addr *bp; -struct sctp_errhdr *err; +struct sctp_chunk *reply;u32 stale;if (attempts > asoc->max_init_attempts) {
@@ -2480,8 +2487,6 @@ static enum sctp_disposition sctp_sf_do_return SCTP_DISPOSITION_DELETE_TCB ; } - err = (struct sctp_errhdr *)(chunk->skb->data); -/* When calculating the time extension, an implementation * SHOULD use the RTT information measured based on the * previous COOKIE ECHO / ERROR exchange, and should add no
Greg Kroah-Hartman
maintainerPATCH 502/699 nvmet-rdma: handle inline data with a nonzero offset
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit 48c0162f647bb47e6084ffbc71b8f213f5e2f4f8 upstream.
nvmet_rdma_use_inline_sg() maps the host-controlled inline data offset into the per-command inline scatterlist. The bounds check admits any offset with off + len <= inline_data_size, but the mapping still assumes the data begins in the first inline page:
sg->offset = off; sg->length = min_t(int, len, PAGE_SIZE - off);
When a port is configured with inline_data_size > PAGE_SIZE (settable up to max(SZ_16K, PAGE_SIZE)), an offset in (PAGE_SIZE, inline_data_size] makes "PAGE_SIZE - off" underflow, so sg->length is set to ~4 GiB and the block backend reads far past the first inline page. num_pages(len) also ignores the offset, so an in-bounds offset whose [off, off+len) span crosses a page boundary under-counts the scatterlist.
Map the offset properly: split it into a page index and an in-page offset, start the scatterlist at that page, and size the page count from page_off + len. Because the request scatterlist may now start at inline_sg[page_idx] rather than inline_sg[0], generalize the inline-SGL identity test in nvmet_rdma_release_rsp() to a range test; otherwise the persistent inline scatterlist is mistaken for an allocated one and nvmet_req_free_sgls() frees an inline page (and warns in free_large_kmalloc()).
--- drivers/nvme/target/rdma.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
drivers/nvme/target/rdma.c +10 -8
@@ -665,7 +665,8 @@ static void nvmet_rdma_release_rsp(strucif (rsp->n_rdma)nvmet_rdma_rw_ctx_destroy (rsp); -if (rsp->req.sg != rsp->cmd->inline_sg) +if (rsp->req.sg < rsp->cmd->inline_sg || + rsp->req.sg >= rsp->cmd->inline_sg + queue->dev->inline_page_count)nvmet_req_free_sgls (&rsp->req);if (unlikely (!list_empty_careful (&queue->rsp_wr_wait_list)))
@@ -820,24 +821,25 @@ static void nvmet_rdma_write_data_done(sstatic void nvmet_rdma_use_inline_sg (struct nvmet_rdma_rsp *rsp,u32 len,u64 off) { -int sg_count =num_pages (len); +u64 page_off = off %PAGE_SIZE ; +u64 page_idx = off /PAGE_SIZE ; +int sg_count =num_pages (page_off + len);struct scatterlist *sg;int i; - sg = rsp->cmd->inline_sg; + sg = &rsp->cmd->inline_sg[page_idx];for (i =0 ; i < sg_count; i++, sg++) {if (i < sg_count -1 )sg_unmark_end (sg);else sg_mark_end (sg); - sg->offset = off; - sg->length =min_t (int, len,PAGE_SIZE - off); + sg->offset = page_off; + sg->length =min_t (u64, len,PAGE_SIZE - page_off); len -= sg->length; -if (!i) - off =0 ; + page_off =0 ; } - rsp->req.sg = rsp->cmd->inline_sg; + rsp->req.sg = &rsp->cmd->inline_sg[page_idx]; rsp->req.sg_cnt = sg_count; }
Greg Kroah-Hartman
maintainerPATCH 503/699 can: isotp: use unconditional synchronize_rcu() in isotp_release()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Hartkopp <[email protected]>
commit 9b1a02e0d980ac6b0e36a90378f847062f81d7e4 upstream.
isotp_notify() unregisters the (RCU) CAN filters via can_rx_unregister() and clears so->bound without waiting for a grace period. isotp_release() uses so->bound to decide whether it needs to call synchronize_rcu() before cancelling so->rxtimer, so when NETDEV_UNREGISTER runs first it skips that synchronize_rcu() and can cancel the timer while an in-flight isotp_rcv() is still executing and about to re-arm it via isotp_send_fc(), leading to a use-after-free timer callback on the freed socket.
sakisho-bot remarked a problem with rtnl_lock held in isotp_notify(), therefore make isotp_release() always call synchronize_rcu() before cancelling the timers, regardless of so->bound. This still closes the original race (isotp_notify() clearing so->bound without waiting for in-flight isotp_rcv() callers before isotp_release() cancels the RX timer) without adding any RCU wait to the netdevice notifier path.
--- net/can/isotp.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
net/can/isotp.c +8 -1
@@ -1184,11 +1184,18 @@ static int isotp_release(struct socket *SINGLE_MASK (so->txid), isotp_rcv_echo, sk);dev_put (dev); -synchronize_rcu (); } } } +/* Always wait for a grace period before touching the timers below. +* A concurrent NETDEV_UNREGISTER may have already unregistered our +* filters and cleared so->bound in isotp_notify() without waiting +* for in-flight isotp_rcv() callers to finish, so this call must not +* be skipped just because so->bound is already 0 here. +*/ +synchronize_rcu (); +hrtimer_cancel (&so->txfrtimer);hrtimer_cancel (&so->txtimer);hrtimer_cancel (&so->rxtimer);
Greg Kroah-Hartman
maintainerPATCH 504/699 can: bcm: fix lockless bound/ifindex race and silent RX_SETUP failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Hartkopp <[email protected]>
commit d9b091d9d22fee81ec53fb55d2032951993ceadb upstream.
bcm_sendmsg() reads bo->ifindex and checks bo->bound before taking lock_sock(), while bcm_notify(), bcm_connect() and bcm_release() all mutate both fields under that same lock. Because the lockless reads and the locked writes are unordered with respect to each other, a racing bcm_notify() (device unregister) or bcm_connect() (concurrent bind on another thread sharing the socket) can make bcm_sendmsg() observe an inconsistent combination, e.g. a stale bound=1 together with the now-cleared ifindex=0, silently turning a socket bound to a specific CAN interface into one that also matches "any" interface.
Keep the lockless bo->bound check purely as a fast-path reject, and move the ifindex read (and a bo->bound re-check) into the locked section, where every writer already serializes. This removes the possibility of observing the two fields torn against each other, rather than trying to fix it with more READ_ONCE()/WRITE_ONCE() pairs on two independently updated fields. Annotate the now-purely-lockless bo->bound accesses consistently across all its write sites.
Also fix bcm_rx_setup() silently returning success when the target device disappears concurrently instead of reporting -ENODEV, so a broken RX op is no longer left registered as if it had succeeded.
--- net/can/bcm.c | 65 +++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 51 insertions(+), 14 deletions(-)
net/can/bcm.c +51 -14
@@ -1251,6 +1251,11 @@ static int bcm_rx_setup(struct bcm_msg_h op->rx_reg_dev = dev;dev_put (dev); + }else { +/* the requested device is gone - do not +* silently succeed without registering +*/ + err = -ENODEV ; } }else
@@ -1320,12 +1325,13 @@ static int bcm_sendmsg(struct socket *so {struct sock *sk = sock->sk;struct bcm_sock *bo =bcm_sk (sk); -int ifindex = bo->ifindex;/* default ifindex for this bcm_op */ +int ifindex;struct bcm_msg_head msg_head;int cfsiz;int ret;/* read bytes or error codes as return value */ -if (!bo->bound) +/* Lockless fast-path check for bound socket */ +if (!READ_ONCE (bo->bound))return -ENOTCONN ;/* check for valid message length from userspace */
@@ -1341,17 +1347,38 @@ static int bcm_sendmsg(struct socket *soif ((size -MHSIZ ) % cfsiz)return -EINVAL ; +lock_sock (sk); + +/* Re-validate under the socket lock: a concurrent bcm_notify() +* may have unbound this socket (device removal) after the +* lockless fast-path check above. bo->ifindex is only ever +* mutated under lock_sock(), so reading it here - instead of +* before taking the lock - guarantees it can't be observed +* torn against bo->bound. +*/ +if (!bo->bound) { + ret = -ENOTCONN ; + goto out_release; + } + +/* default ifindex for this bcm_op */ + ifindex = bo->ifindex; +/* check for alternative ifindex for this bcm_op */ if (!ifindex && msg->msg_name) {/* no bound device as default => check msg_name */ DECLARE_SOCKADDR(struct sockaddr_can *, addr, msg->msg_name); -if (msg->msg_namelen <BCM_MIN_NAMELEN ) -return -EINVAL ; +if (msg->msg_namelen <BCM_MIN_NAMELEN ) { + ret = -EINVAL ; + goto out_release; + } -if (addr->can_family !=AF_CAN ) -return -EINVAL ; +if (addr->can_family !=AF_CAN ) { + ret = -EINVAL ; + goto out_release; + }/* ifindex from sendto() */ ifindex = addr->can_ifindex;
@@ -1360,20 +1387,21 @@ static int bcm_sendmsg(struct socket *sostruct net_device *dev; dev =dev_get_by_index (sock_net (sk), ifindex); -if (!dev) -return -ENODEV ; +if (!dev) { + ret = -ENODEV ; + goto out_release; + }if (dev->type !=ARPHRD_CAN ) {dev_put (dev); -return -ENODEV ; + ret = -ENODEV ; + goto out_release; }dev_put (dev); } } -lock_sock (sk); -switch (msg_head.opcode) {case TX_SETUP :
@@ -1423,6 +1451,7 @@ static int bcm_sendmsg(struct socket *sobreak ; } +out_release:release_sock (sk);return ret;
@@ -1459,7 +1488,12 @@ static void bcm_notify(struct bcm_sock * bo->bcm_proc_read = NULL; }#endif - bo->bound =0 ; +/* Paired with the lockless fast-path check in +* bcm_sendmsg(); bo->ifindex itself is only ever +* accessed under lock_sock() so it needs no +* annotation. +*/ +WRITE_ONCE (bo->bound,0 ); bo->ifindex =0 ; notify_enodev =1 ; }
@@ -1600,7 +1634,7 @@ static int bcm_release(struct socket *so/* remove device reference */ if (bo->bound) { - bo->bound =0 ; +WRITE_ONCE (bo->bound,0 ); bo->ifindex =0 ; }
@@ -1669,7 +1703,10 @@ static int bcm_connect(struct socket *so }#endif /* CONFIG_PROC_FS */ - bo->bound =1 ; +/* bo->ifindex above is fully assigned before this point; pairs +* with the lockless fast-path check in bcm_sendmsg() +*/ +WRITE_ONCE (bo->bound,1 ); fail:release_sock (sk);
Greg Kroah-Hartman
maintainerPATCH 505/699 can: bcm: add missing rcu list annotations and operations
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Oliver Hartkopp <[email protected]>
commit 7b2c3eabc4dafc062a25e10711154f2107526a78 upstream.
sashiko-bot remarked the missing use of list_add_rcu() in bcm_[rx|tx]_setup() to have a proper initialized bcm_op structure when bcm_proc_show() traverses the bcm_op's under rcu_read_lock().
To cover all initial settings of the bcm_op's the list_add_rcu() calls are moved to the end of the setup code.
While at it, also fix the mirroring removal side: bcm_release() called bcm_remove_op() - which frees the op via call_rcu() - on ops that were still linked in bo->tx_ops/bo->rx_ops, without list_del_rcu() first. Unlink each op with list_del_rcu() before handing it to bcm_remove_op(), matching the existing pattern in bcm_delete_tx_op()/bcm_delete_rx_op().
--- net/can/bcm.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-)
net/can/bcm.c +16 -9
@@ -244,7 +244,7 @@ static int bcm_proc_show(struct seq_file (reduction == 100) ? "near " : "", reduction); } -list_for_each_entry (op, &bo->tx_ops, list) { +list_for_each_entry_rcu (op, &bo->tx_ops, list) {seq_printf (m,"tx_op: %03X %s " , op->can_id,bcm_proc_getifname (net, ifname, op->ifindex));
@@ -877,6 +877,7 @@ static int bcm_tx_setup(struct bcm_msg_hstruct bcm_sock *bo =bcm_sk (sk);struct bcm_op *op;struct canfd_frame *cf; +bool add_op_to_list = false;unsigned int i;int err;
@@ -1018,8 +1019,7 @@ static int bcm_tx_setup(struct bcm_msg_hhrtimer_init (&op->thrtimer,CLOCK_MONOTONIC ,HRTIMER_MODE_REL_SOFT ); -/* add this bcm_op to the list of the tx_ops */ -list_add (&op->list, &bo->tx_ops); + add_op_to_list = true; }/* if ((op = bcm_find_op(&bo->tx_ops, msg_head->can_id, ifindex))) */
@@ -1041,6 +1041,10 @@ static int bcm_tx_setup(struct bcm_msg_h op->flags |=TX_ANNOUNCE ; } +/* add this bcm_op to the list of the tx_ops? */ +if (add_op_to_list) +list_add_rcu (&op->list, &bo->tx_ops); +if (op->flags &TX_ANNOUNCE )bcm_can_tx (op);
@@ -1183,9 +1187,6 @@ static int bcm_rx_setup(struct bcm_msg_h HRTIMER_MODE_REL_SOFT); op->thrtimer.function = bcm_rx_thr_handler; -/* add this bcm_op to the list of the rx_ops */ -list_add (&op->list, &bo->rx_ops); -/* call can_rx_register() */ do_rx_register =1 ;
@@ -1264,10 +1265,12 @@ static int bcm_rx_setup(struct bcm_msg_h bcm_rx_handler, op, "bcm", sk);if (err) {/* this bcm rx op is broken -> remove it */ -list_del_rcu (&op->list);bcm_remove_op (op);return err; } + +/* add this bcm_op to the list of the rx_ops */ +list_add_rcu (&op->list, &bo->rx_ops); }return msg_head->nframes * op->cfsiz +MHSIZ ;
@@ -1597,8 +1600,10 @@ static int bcm_release(struct socket *soremove_proc_entry (bo->procname, net->can.bcmproc_dir);#endif /* CONFIG_PROC_FS */ -list_for_each_entry_safe (op, next, &bo->tx_ops, list) +list_for_each_entry_safe (op, next, &bo->tx_ops, list) { +list_del_rcu (&op->list);bcm_remove_op (op); + }list_for_each_entry_safe (op, next, &bo->rx_ops, list) {/*
@@ -1629,8 +1634,10 @@ static int bcm_release(struct socket *sosynchronize_rcu (); -list_for_each_entry_safe (op, next, &bo->rx_ops, list) +list_for_each_entry_safe (op, next, &bo->rx_ops, list) { +list_del_rcu (&op->list);bcm_remove_op (op); + }/* remove device reference */ if (bo->bound) {
Greg Kroah-Hartman
maintainerPATCH 506/699 dm thin metadata: fix superblock refcount leak on snapshot shadow failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Genjian Zhang <[email protected]>
commit 4b22d0801fadfcae2e106e6ba32e49439c7c7ebf upstream.
__reserve_metadata_snap() increments THIN_SUPERBLOCK_LOCATION in the metadata space map before shadowing it. When dm_tm_shadow_block() fails, a reference is leaked in the metadata space map.
Fix by adding the missing dm_sm_dec_block().
--- drivers/md/dm-thin-metadata.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/md/dm-thin-metadata.c +3 -1
@@ -1308,8 +1308,10 @@ static int __reserve_metadata_snap(strucdm_sm_inc_block (pmd->metadata_sm,THIN_SUPERBLOCK_LOCATION ); r =dm_tm_shadow_block (pmd->tm,THIN_SUPERBLOCK_LOCATION , &sb_validator, ©, &inc); -if (r) +if (r) { +dm_sm_dec_block (pmd->metadata_sm,THIN_SUPERBLOCK_LOCATION );return r; + }BUG_ON (!inc);
Greg Kroah-Hartman
maintainerPATCH 507/699 dm thin metadata: fix metadata snapshot consistency on commit failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ming-Hung Tsai <[email protected]>
commit 5bcd4d3058ebaf46ad2e163829d87dd4870c7a45 upstream.
__reserve_metadata_snap() and __release_metadata_snap() modify the superblock's held_root directly in the block_manager's buffer. If the subsequent metadata commit fails, the held_root gets flushed to disk through the abort_transaction path, resulting in inconsistent metadata.
Reproducer 1: __reserve_metadata_snap()
1. Create a 2 MiB metadata device and make the region after the 14th block inaccessible, to trigger metadata commit failure in the subsequent reserve_metadata_snap operation. The 14th block will be the shadow destination for the index block.
dmsetup create tmeta --table "0 112 linear /dev/sdc 0 112 3984 error"
2. Create a 16 MiB thin-pool
dmsetup create tdata --table "0 32768 zero"
dd if=/dev/zero of=/dev/mapper/tmeta bs=4k count=1 dmsetup create tpool --table "0 32768 thin-pool /dev/mapper/tmeta \/dev/mapper/tdata 128 0 1 skip_block_zeroing"
3. Take a metadata snapshot to trigger metadata commit failure and transaction abort. However, the held_root is written to disk, breaking metadata consistency.
dmsetup message tpool 0 "reserve_metadata_snap"
thin_check v1.2.2 result:
Bad reference count for metadata block 6. Expected 2, but space map contains 1. Bad reference count for metadata block 7. Expected 2, but space map contains 1. Bad reference count for metadata block 13. Expected 1, but space map contains 0.
Reproducer 2: __release_metadata_snap()
1. Create a 2 MiB metadata device and make the region after the 16th block inaccessible, to trigger metadata commit failure in the subsequent release_metadata_snap operation. The 16th block will be the shadow destination for the index block.
dmsetup create tmeta --table "0 128 linear /dev/sdc 0 128 3968 error"
2. Create a 16 MiB thin-pool
dmsetup create tdata --table "0 32768 zero"
dd if=/dev/zero of=/dev/mapper/tmeta bs=4k count=1 dmsetup create tpool --table "0 32768 thin-pool /dev/mapper/tmeta \/dev/mapper/tdata 128 0 1 skip_block_zeroing"
3. Reserve then release the metadata snapshot, to trigger metadata commit failure and transaction abort. The held_root gets removed from the on-disk superblock, causing inconsistent metadata.
dmsetup message tpool 0 "reserve_metadata_snap"
dmsetup message tpool 0 "release_metadata_snap"
thin_check v1.2.2 result:
Bad reference count for metadata block 6. Expected 1, but space map contains 2. Bad reference count for metadata block 7. Expected 1, but space map contains 2. 1 metadata blocks have leaked.
Fix by deferring the held_root update to commit time.
Additionally, move the existing-snapshot check in __reserve_metadata_snap before the shadow operation to avoid unnecessary work. In __release_metadata_snap, clear pmd->held_root before btree deletion so partial failure leaks blocks rather than leaving a stale reference, and unlock the snapshot block before decrementing its refcount.
--- drivers/md/dm-thin-metadata.c | 63 ++++++++++++------------------------------ 1 file changed, 18 insertions(+), 45 deletions(-)
drivers/md/dm-thin-metadata.c +18 -45
@@ -183,6 +183,7 @@ struct dm_pool_metadata {uint32_t time;dm_block_t root;dm_block_t details_root; +dm_block_t held_root;struct list_head thin_devices;uint64_t trans_id;unsigned long flags;
@@ -709,6 +710,7 @@ static int __open_metadata(struct dm_poo*/ pmd->root =le64_to_cpu (disk_super->data_mapping_root); pmd->details_root =le64_to_cpu (disk_super->device_details_root); + pmd->held_root =le64_to_cpu (disk_super->held_root);__setup_btree_details (pmd);dm_bm_unlock (sblock);
@@ -792,6 +794,7 @@ static int __begin_transaction(struct dm pmd->time =le32_to_cpu (disk_super->time); pmd->root =le64_to_cpu (disk_super->data_mapping_root); pmd->details_root =le64_to_cpu (disk_super->device_details_root); + pmd->held_root =le64_to_cpu (disk_super->held_root); pmd->trans_id =le64_to_cpu (disk_super->trans_id); pmd->flags =le32_to_cpu (disk_super->flags); pmd->data_block_size =le32_to_cpu (disk_super->data_block_size);
@@ -882,6 +885,7 @@ static int __commit_transaction(struct d disk_super->time =cpu_to_le32 (pmd->time); disk_super->data_mapping_root =cpu_to_le64 (pmd->root); disk_super->device_details_root =cpu_to_le64 (pmd->details_root); + disk_super->held_root =cpu_to_le64 (pmd->held_root); disk_super->trans_id =cpu_to_le64 (pmd->trans_id); disk_super->flags =cpu_to_le32 (pmd->flags);
@@ -1288,9 +1292,14 @@ static int __reserve_metadata_snap(struc {int r, inc;struct thin_disk_superblock *disk_super; -struct dm_block *copy, *sblock; +struct dm_block *copy;dm_block_t held_root; +if (pmd->held_root) { +DMWARN ("Pool metadata snapshot already exists: release this before taking another." ); +return -EBUSY ; + } +/* * We commit to ensure the btree roots which we increment in a * moment are up to date.
@@ -1318,14 +1327,6 @@ static int __reserve_metadata_snap(struc held_root =dm_block_location (copy); disk_super =dm_block_data (copy); -if (le64_to_cpu (disk_super->held_root)) { -DMWARN ("Pool metadata snapshot already exists: release this before taking another." ); - -dm_tm_dec (pmd->tm, held_root); -dm_tm_unlock (pmd->tm, copy); -return -EBUSY ; - } -/* * Wipe the spacemap since we're not publishing this. */
@@ -1341,18 +1342,8 @@ static int __reserve_metadata_snap(strucdm_tm_inc (pmd->tm,le64_to_cpu (disk_super->device_details_root));dm_tm_unlock (pmd->tm, copy); -/* -* Write the held root into the superblock. -*/ - r =superblock_lock (pmd, &sblock); -if (r) { -dm_tm_dec (pmd->tm, held_root); -return r; - } + pmd->held_root = held_root; - disk_super =dm_block_data (sblock); - disk_super->held_root =cpu_to_le64 (held_root); -dm_bm_unlock (sblock);return 0 ; }
@@ -1372,18 +1363,10 @@ static int __release_metadata_snap(struc {int r;struct thin_disk_superblock *disk_super; -struct dm_block *sblock, *copy; +struct dm_block *copy;dm_block_t held_root; - r =superblock_lock (pmd, &sblock); -if (r) -return r; - - disk_super =dm_block_data (sblock); - held_root =le64_to_cpu (disk_super->held_root); - disk_super->held_root =cpu_to_le64 (0 ); - -dm_bm_unlock (sblock); + held_root = pmd->held_root;if (!held_root) {DMWARN ("No pool metadata snapshot found: nothing to release." );
@@ -1394,13 +1377,15 @@ static int __release_metadata_snap(strucif (r)return r; + pmd->held_root =0 ; + disk_super =dm_block_data (copy);dm_btree_del (&pmd->info,le64_to_cpu (disk_super->data_mapping_root));dm_btree_del (&pmd->details_info,le64_to_cpu (disk_super->device_details_root)); -dm_sm_dec_block (pmd->metadata_sm, held_root); -dm_tm_unlock (pmd->tm, copy); +dm_sm_dec_block (pmd->metadata_sm, held_root); +return 0 ; }
@@ -1419,19 +1404,7 @@ int dm_pool_release_metadata_snap(structstatic int __get_metadata_snap (struct dm_pool_metadata *pmd,dm_block_t *result) { -int r; -struct thin_disk_superblock *disk_super; -struct dm_block *sblock; - - r =dm_bm_read_lock (pmd->bm,THIN_SUPERBLOCK_LOCATION , - &sb_validator, &sblock); -if (r) -return r; - - disk_super =dm_block_data (sblock); - *result =le64_to_cpu (disk_super->held_root); - -dm_bm_unlock (sblock); + *result = pmd->held_root;return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 508/699 dm era: fix out-of-bounds memory access for non-zero start sector
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Samuel Moelius <[email protected]>
commit a868196f03c2b19418ae3d2b69e195d668a271e5 upstream.
dm-era tracks writes in target-relative blocks, but era_map() calculates the writeset block before applying the target offset. Tables with a non-zero start sector can therefore pass an absolute mapped-device block to metadata_current_marked().
If the absolute block is beyond the current writeset size, writeset_marked() tests past the end of the in-core bitset. KASAN reports this as a vmalloc-out-of-bounds access.
Apply the target offset before calculating the era block so writeset lookups use the target-relative block number.
--- drivers/md/dm-era-target.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/md/dm-era-target.c +3 -1
@@ -1210,6 +1210,7 @@ static dm_block_t get_block(struct era *static void remap_to_origin (struct era *era,struct bio *bio) {bio_set_dev (bio, era->origin_dev->bdev); + bio->bi_iter.bi_sector =dm_target_offset (era->ti, bio->bi_iter.bi_sector); }/*----------------------------------------------------------------
@@ -1534,7 +1535,7 @@ static void era_dtr(struct dm_target *tistatic int era_map (struct dm_target *ti,struct bio *bio) {struct era *era = ti->private; -dm_block_t block =get_block (era, bio); +dm_block_t block;/* * All bios get remapped to the origin device. We do this now, but
@@ -1542,6 +1543,7 @@ static int era_map(struct dm_target *ti,* block is marked in this era. */ remap_to_origin (era, bio); + block =get_block (era, bio);/* * REQ_PREFLUSH bios carry no data, so we're not interested in them.
Greg Kroah-Hartman
maintainerPATCH 509/699 dm-bufio: fix wrong count calculation in dm_bufio_issue_discard
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <[email protected]>
commit 422f1d4f141eaa3a6e4199ceec86cc6b9bf26570 upstream.
block_to_sector converts a block number to a sector number and adds c->start to the result. It is inappropriate to use this function for converting the number of blocks to a number to sectors because c->start would be incorrectly added to the result.
Luckily, the only target that uses dm_bufio_issue_discard is dm-ebs, which sets c->start to 0, so this bug is latent.
--- drivers/md/dm-bufio.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/md/dm-bufio.c +3 -1
@@ -1375,7 +1375,9 @@ int dm_bufio_issue_discard(struct dm_bufstruct dm_io_region io_reg = { .bdev = c->bdev, .sector =block_to_sector (c, block), - .count =block_to_sector (c, count), + .count =likely (c->sectors_per_block_bits >=0 ) ? + count << c->sectors_per_block_bits : + count * (c->block_size >>SECTOR_SHIFT ), };BUG_ON (dm_bufio_in_request ());
Greg Kroah-Hartman
maintainerPATCH 510/699 dm-log: fix a bitset_size overflow on 32bit machines
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Marzinski <[email protected]>
commit 9743132a41f4d9d0e54c5f2adcb821b04796bab1 upstream.
Commit c20e36b7631d ("dm log: fix out-of-bounds write due to region_count overflow") made sure that region_count could fit in an unsigned int. But the bitmap memory isn't allocated based on region_count. It uses bitset_size (a size_t variable). The first step of calculating bitset_size is to set it to region_count, rounded up to a multiple of BITS_PER_LONG. If region_size is less than BITS_PER_LONG smaller than UINT_MAX, it will get rounded up to 2^32. On a 32bit architecture, this will make bitset_size wrap around to 0 and fail, despite region_count being valid.
Since bitset_size gets divided by 8, it can hold any valid region_count. It just needs a special case to handle the rollover. If it is 0, the value rolled over, and bitset size should be set to the number of bytes needed to hold 2^32 bits.
--- drivers/md/dm-log.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/md/dm-log.c +3 -0
@@ -421,6 +421,9 @@ static int create_log_context(struct dm_*/ bitset_size =dm_round_up (region_count,BITS_PER_LONG ); bitset_size >>=BYTE_SHIFT ; +/* Handle dm_round_up rollover on 32-bit systems */ +if (!bitset_size) + bitset_size =1UL << (BITS_PER_LONG -BYTE_SHIFT ); lc->bitset_uint32_count = bitset_size /sizeof (*lc->clean_bits);
Greg Kroah-Hartman
maintainerPATCH 511/699 dm-stats: fix dm_jiffies_to_msec64
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <[email protected]>
commit 386df1a57b631c456d14f857cb0c0c2e11c16bef upstream.
There were wrong calculations in dm_jiffies_to_msec64 that produced incorrect output when HZ was different from 1000. This commit fixes them.
--- drivers/md/dm-stats.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/md/dm-stats.c +2 -2
@@ -799,10 +799,10 @@ static unsigned long long dm_jiffies_to_ result =jiffies_to_msecs (j &0x3fffff );if (j >=1 <<22 ) { mult =jiffies_to_msecs (1 <<22 ); - result += (unsigned long long )mult * (unsigned long long )jiffies_to_msecs ((j >>22 ) &0x3fffff ); + result += (unsigned long long )mult * ((j >>22 ) &0x3fffff ); }if (j >=1ULL <<44 ) - result += (unsigned long long )mult * (unsigned long long )mult * (unsigned long long )jiffies_to_msecs (j >>44 ); + result += (unsigned long long )mult * (unsigned long long )(1 <<22 ) * (j >>44 );return result; }
Greg Kroah-Hartman
maintainerPATCH 512/699 dm-stats: fix merge accounting
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <[email protected]>
commit 1917eb2db750ecbdf710f79a8042eaa545a063c7 upstream.
There were wrong parentheses when setting stats_aux->merged, so that merging was never properly accounted. This commit fixes it.
--- drivers/md/dm-stats.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
drivers/md/dm-stats.c +2 -4
@@ -651,10 +651,8 @@ void dm_stats_account_io(struct dm_stats*/ last =raw_cpu_ptr (stats->last); stats_aux->merged = - (bi_sector == (READ_ONCE (last->last_sector) && - ((bi_rw ==WRITE ) == - (READ_ONCE (last->last_rw) ==WRITE )) - )); + bi_sector ==READ_ONCE (last->last_sector) && + (bi_rw ==WRITE ) == (READ_ONCE (last->last_rw) ==WRITE );WRITE_ONCE (last->last_sector, end_sector);WRITE_ONCE (last->last_rw, bi_rw); }
Greg Kroah-Hartman
maintainerPATCH 513/699 dm_early_create: fix freeing used table on dm_resume failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <[email protected]>
commit 366665416f20527ff7cad548a32d1ddf23195740 upstream.
If dm_resume fails, the kernel attempts to free table with dm_table_destroy, but the table was already instantiated with dm_swap_table. This commit skips the call to dm_table_destroy in this case.
--- drivers/md/dm-ioctl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/dm-ioctl.c +1 -1
@@ -2164,7 +2164,7 @@ int __init dm_early_create(struct dm_ioc/* resume device */ r =dm_resume (md);if (r) - goto err_destroy_table; + goto err_hash_remove;DMINFO ("%s (%s) is ready" , md->disk->disk_name, dmi->name);dm_put (md);
Greg Kroah-Hartman
maintainerPATCH 514/699 dm-verity: increase sprintf buffer size
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mikulas Patocka <[email protected]>
commit 88dd117c92a142253fb7a17e791773902b3babc6 upstream.
The prefix "DM_VERITY_ERR_BLOCK_NR" is 22 chars. Add '=', one digit for type, ',', up to 20 digits for a u64 block number, and a NUL terminator:
that's 46 bytes. The buffer is 42 bytes. For block numbers >= 16 decimal digits (devices larger than ~16 EB with 4K blocks), snprintf silently truncates the uevent environment variable.
--- drivers/md/dm-verity-target.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/md/dm-verity-target.c +1 -1
@@ -21,7 +21,7 @@#define DM_MSG_PREFIX "verity" -#define DM_VERITY_ENV_LENGTH 42 +#define DM_VERITY_ENV_LENGTH 46#define DM_VERITY_ENV_VAR_NAME "DM_VERITY_ERR_BLOCK_NR"#define DM_VERITY_DEFAULT_PREFETCH_SIZE 262144
Greg Kroah-Hartman
maintainerPATCH 515/699 scsi: hpsa: Fix DMA mapping leak on IOACCEL2 reset path
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
commit e166bafc483e927150cb9b5f286c9191ea0df84e upstream.
If phys_disk->in_reset is set, the function returns directly without undoing the resources acquired for the command. Add the missing error cleanup by unmapping the IOACCEL2 SG chain block when needed, unmapping the SCSI command, and dropping the outstanding IOACCEL command count before returning.
--- drivers/scsi/hpsa.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/scsi/hpsa.c +4 -0
@@ -5035,6 +5035,10 @@ static int hpsa_scsi_ioaccel2_queue_commif (phys_disk->in_reset) { cmd->result =DID_RESET <<16 ; +atomic_dec (&phys_disk->ioaccel_cmds_out); +scsi_dma_unmap (cmd); +if (use_sg > h->ioaccel_maxsg) +hpsa_unmap_ioaccel2_sg_chain_block (h, cp);return -1 ; }
Greg Kroah-Hartman
maintainerPATCH 516/699 scsi: sg: Report request-table problems when any status is set
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xu Rao <[email protected]>
commit 1d3a742afeb761eaead774691bde1ced699e9a5d upstream.
SG_GET_REQUEST_TABLE reports per-request diagnostic state through sg_req_info::problem. The field is meant to indicate whether there is an error to report for a completed request.
sg_fill_request_table() currently combines masked_status, host_status and driver_status with bitwise AND. This only reports a problem when all three status fields are non-zero at the same time. A normal target check condition, for example, has masked_status set while host_status and driver_status may both be zero, so the request is incorrectly reported as clean.
Use the same condition as sg_new_read(), which sets SG_INFO_CHECK when any of the three status fields is non-zero.
--- drivers/scsi/sg.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-)
drivers/scsi/sg.c +3 -4
@@ -864,10 +864,9 @@ sg_fill_request_table(Sg_fd *sfp, sg_reqif (val >=SG_MAX_QUEUE )break ; rinfo[val].req_state = srp->done +1 ; - rinfo[val].problem = - srp->header.masked_status & - srp->header.host_status & - srp->header.driver_status; + rinfo[val].problem = srp->header.masked_status || + srp->header.host_status || + srp->header.driver_status;if (srp->done) rinfo[val].duration = srp->header.duration;
Greg Kroah-Hartman
maintainerPATCH 517/699 scsi: target: core: Fix iSCSI ISID use-after-free in REGISTER AND MOVE
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit fda6a1f3c3d7047b5ce5654487649c2daa738bfc upstream.
core_scsi3_emulate_pro_register_and_move() maps the PERSISTENT RESERVE OUT parameter list with transport_kmap_data_sg() and parses the destination TransportID with target_parse_pr_out_transport_id(). For an iSCSI TransportID (FORMAT CODE 01b), iscsi_parse_pr_out_transport_id() returns the ISID in iport_ptr as a raw pointer into that mapped buffer.
The function then unmaps the buffer with transport_kunmap_data_sg() before dereferencing iport_ptr in strcmp(), __core_scsi3_locate_pr_reg() and core_scsi3_alloc_registration(). When the parameter list spans more than one page (PARAMETER LIST LENGTH > 4096), transport_kmap_data_sg() uses vmap() and transport_kunmap_data_sg() does vunmap(), so the kernel virtual address backing iport_ptr is torn down and every subsequent dereference is a use-after-free read of the unmapped region.
Keep the parameter list mapped until iport_ptr is no longer needed: drop the early transport_kunmap_data_sg() and unmap once on the success path, right before returning. The error paths already unmap through the existing "if (buf) transport_kunmap_data_sg(cmd)" at the out: label, which now runs on every post-map error exit because buf is no longer cleared early. Only reads of the mapping happen while spinlocks are held; the map and unmap calls remain outside any lock. The sibling caller core_scsi3_decode_spec_i_port() already uses the buffer before unmapping it and is left unchanged.
--- drivers/target/target_core_pr.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/target/target_core_pr.c +5 -3
@@ -3293,9 +3293,6 @@ core_scsi3_emulate_pro_register_and_move goto out; } -transport_kunmap_data_sg (cmd); - buf =NULL ; - pr_debug("SPC-3 PR [%s] Extracted initiator %s identifier: %s" " %s\n", dest_tf_ops->fabric_name, (iport_ptr != NULL) ? "port" : "device", initiator_str, (iport_ptr != NULL) ?
@@ -3529,6 +3526,11 @@ after_iport_check:core_scsi3_update_and_write_aptpl (cmd->se_dev, aptpl);core_scsi3_put_pr_reg (dest_pr_reg); +/* +* iport_ptr aliases the PR-OUT parameter list mapped above, so the +* buffer is unmapped only here on success (and at out: on error). +*/ +transport_kunmap_data_sg (cmd);return 0 ; out:if (buf)
Greg Kroah-Hartman
maintainerPATCH 518/699 Input: ims-pcu - fix use-after-free and double-free in disconnect
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit 462a999917755a3bf77448dfd64307963cf0a9f0 upstream.
ims_pcu_disconnect() only intended to perform cleanup when the primary (control) interface is unbound. However, it currently relies on the interface class to distinguish between control and data interfaces. A malicious device could present a data interface with the same class as the control interface, leading to premature cleanup and potential use-after-free or double-free.
Switch to verifying that the interface being disconnected is indeed the control interface.
--- drivers/input/misc/ims-pcu.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/input/misc/ims-pcu.c +1 -2
@@ -2066,7 +2066,6 @@ err_free_mem:static void ims_pcu_disconnect (struct usb_interface *intf) {struct ims_pcu *pcu =usb_get_intfdata (intf); -struct usb_host_interface *alt = intf->cur_altsetting;usb_set_intfdata (intf,NULL );
@@ -2074,7 +2073,7 @@ static void ims_pcu_disconnect(struct us* See if we are dealing with control or data interface. The cleanup * happens when we unbind primary (control) interface. */ -if (alt->desc.bInterfaceClass !=USB_CLASS_COMM ) +if (intf != pcu->ctrl_intf)return ;sysfs_remove_group (&intf->dev.kobj, &ims_pcu_attr_group);
Greg Kroah-Hartman
maintainerPATCH 519/699 Input: ims-pcu - release data interface on disconnect
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit 441c510a649c8ddce38aa0311334ed8bb546b36c upstream.
During probe the driver claims the data interface, but it never releases it. Release it in disconnect to avoid leaving it permanently claimed.
--- drivers/input/misc/ims-pcu.c | 1 + 1 file changed, 1 insertion(+)
drivers/input/misc/ims-pcu.c +1 -0
@@ -2086,6 +2086,7 @@ static void ims_pcu_disconnect(struct usims_pcu_destroy_application_mode (pcu);ims_pcu_buffers_free (pcu); +usb_driver_release_interface (&ims_pcu_driver, pcu->data_intf);kfree (pcu); }
Greg Kroah-Hartman
maintainerPATCH 520/699 Input: ims-pcu - validate control endpoint type
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit baf56975806534268e24acf9a8abb1c447ce11e9 upstream.
The driver currently assumes that the first endpoint of the control interface is an interrupt IN endpoint without verifying it. A malicious device could provide a different endpoint type, which would then be passed to usb_fill_int_urb(), potentially leading to kernel warnings or undefined behavior.
Verify that the control endpoint is an interrupt IN endpoint.
--- drivers/input/misc/ims-pcu.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/input/misc/ims-pcu.c +6 -0
@@ -1676,6 +1676,12 @@ static int ims_pcu_parse_cdc_data(structreturn -ENODEV ; pcu->ep_ctrl = &alt->endpoint[0 ].desc; +if (!usb_endpoint_is_int_in (pcu->ep_ctrl)) { +dev_err (pcu->dev, +"Control endpoint is not INTERRUPT IN\n" ); +return -EINVAL ; + } + pcu->max_ctrl_size =usb_endpoint_maxp (pcu->ep_ctrl); pcu->data_intf = usb_ifnum_to_if(pcu->udev,
Greg Kroah-Hartman
maintainerPATCH 521/699 Input: ims-pcu - add response length checks
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit 48c9d92fd4ee3a8f5d2cb46c802a0eff8e67c79c upstream.
The driver processes response data from device buffers without verifying that the device actually sent enough data. This can lead to out-of-bounds reads or processing stale data.
Add checks for the expected response length before accessing the buffers.
--- drivers/input/misc/ims-pcu.c | 87 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 6 deletions(-)
drivers/input/misc/ims-pcu.c +81 -6
@@ -407,7 +407,16 @@ static void ims_pcu_destroy_gamepad(strustatic void ims_pcu_report_events (struct ims_pcu *pcu) { -u32 data =get_unaligned_be32 (&pcu->read_buf[3 ]); +u32 data; + +/* 6-axis setting (1 byte) + button data + checksum */ +if (pcu->read_pos <IMS_PCU_DATA_OFFSET +1 +sizeof (data) +1 ) { +dev_warn (pcu->dev,"Short buttons report: %d bytes\n" , + pcu->read_pos); +return ; + } + + data =get_unaligned_be32 (&pcu->read_buf[IMS_PCU_DATA_OFFSET +1 ]);ims_pcu_buttons_report (pcu, data & ~IMS_PCU_GAMEPAD_MASK );if (pcu->gamepad)
@@ -667,11 +676,19 @@ static int __ims_pcu_execute_bl_command(return error; } -if (expected_response && pcu->cmd_buf[2 ] != expected_response) { -dev_err (pcu->dev, -"Unexpected response from bootloader: 0x%02x, wanted 0x%02x\n" , - pcu->cmd_buf[2 ], expected_response); -return -EINVAL ; +if (expected_response) { +if (pcu->cmd_buf_len <3 ) { +dev_err (pcu->dev,"Short response from bootloader: %d bytes\n" , + pcu->cmd_buf_len); +return -EIO ; + } + +if (pcu->cmd_buf[2 ] != expected_response) { +dev_err (pcu->dev, +"Unexpected response from bootloader: 0x%02x, wanted 0x%02x\n" , + pcu->cmd_buf[2 ], expected_response); +return -EINVAL ; + } }return 0 ;
@@ -699,6 +716,12 @@ static int ims_pcu_get_info(struct ims_preturn error; } +if (pcu->cmd_buf_len <IMS_PCU_DATA_OFFSET +IMS_PCU_SET_INFO_SIZE +1 ) { +dev_err (pcu->dev,"Short GET_INFO response: %d bytes\n" , + pcu->cmd_buf_len); +return -EIO ; + } +memcpy (pcu->part_number, &pcu->cmd_buf[IMS_PCU_INFO_PART_OFFSET ],sizeof (pcu->part_number));
@@ -796,6 +819,12 @@ static int ims_pcu_verify_block(struct ireturn error; } +if (pcu->cmd_buf_len <IMS_PCU_BL_DATA_OFFSET +sizeof (*fragment) + len +1 ) { +dev_err (pcu->dev,"Short READ_APP response: %d bytes\n" , + pcu->cmd_buf_len); +return -EIO ; + } + fragment = (void *)&pcu->cmd_buf[IMS_PCU_BL_DATA_OFFSET ];if (get_unaligned_le32 (&fragment->addr) != addr || fragment->len != len) {
@@ -993,6 +1022,10 @@ ims_pcu_backlight_get_brightness(struct error);/* Assume the LED is OFF */ brightness =LED_OFF ; + }else if (pcu->cmd_buf_len <IMS_PCU_DATA_OFFSET +2 +1 ) { +dev_err (pcu->dev,"Short GET_BRIGHTNESS response: %d bytes\n" , + pcu->cmd_buf_len); + brightness =LED_OFF ; }else { brightness =get_unaligned_le16 (&pcu->cmd_buf[IMS_PCU_DATA_OFFSET ]);
@@ -1272,6 +1305,12 @@ static int ims_pcu_read_ofn_config(strucif (error)return error; +if (pcu->cmd_buf_len <OFN_REG_RESULT_OFFSET +2 +1 ) { +dev_err (pcu->dev,"Short OFN_GET_CONFIG response: %d bytes\n" , + pcu->cmd_buf_len); +return -EIO ; + } + result = (s16 )get_unaligned_le16 (pcu->cmd_buf +OFN_REG_RESULT_OFFSET );if (result <0 )return -EIO ;
@@ -1292,6 +1331,12 @@ static int ims_pcu_write_ofn_config(struif (error)return error; +if (pcu->cmd_buf_len <OFN_REG_RESULT_OFFSET +2 +1 ) { +dev_err (pcu->dev,"Short OFN_SET_CONFIG response: %d bytes\n" , + pcu->cmd_buf_len); +return -EIO ; + } + result = (s16 )get_unaligned_le16 (pcu->cmd_buf +OFN_REG_RESULT_OFFSET );if (result <0 )return -EIO ;
@@ -1811,6 +1856,12 @@ static int ims_pcu_get_device_info(strucreturn error; } +if (pcu->cmd_buf_len <IMS_PCU_DATA_OFFSET +6 +1 ) { +dev_err (pcu->dev,"Short GET_FW_VERSION response: %d bytes\n" , + pcu->cmd_buf_len); +return -EIO ; + } + snprintf(pcu->fw_version, sizeof(pcu->fw_version), "%02d%02d%02d%02d.%c%c", pcu->cmd_buf[2], pcu->cmd_buf[3], pcu->cmd_buf[4], pcu->cmd_buf[5],
@@ -1823,6 +1874,12 @@ static int ims_pcu_get_device_info(strucreturn error; } +if (pcu->cmd_buf_len <IMS_PCU_DATA_OFFSET +6 +1 ) { +dev_err (pcu->dev,"Short GET_BL_VERSION response: %d bytes\n" , + pcu->cmd_buf_len); +return -EIO ; + } + snprintf(pcu->bl_version, sizeof(pcu->bl_version), "%02d%02d%02d%02d.%c%c", pcu->cmd_buf[2], pcu->cmd_buf[3], pcu->cmd_buf[4], pcu->cmd_buf[5],
@@ -1835,6 +1892,12 @@ static int ims_pcu_get_device_info(strucreturn error; } +if (pcu->cmd_buf_len <IMS_PCU_DATA_OFFSET +1 +1 ) { +dev_err (pcu->dev,"Short RESET_REASON response: %d bytes\n" , + pcu->cmd_buf_len); +return -EIO ; + } +snprintf (pcu->reset_reason,sizeof (pcu->reset_reason),"%02x" , pcu->cmd_buf[IMS_PCU_DATA_OFFSET ]);
@@ -1861,6 +1924,12 @@ static int ims_pcu_identify_type(structreturn error; } +if (pcu->cmd_buf_len <IMS_PCU_DATA_OFFSET +1 +1 ) { +dev_err (pcu->dev,"Short GET_DEVICE_ID response: %d bytes\n" , + pcu->cmd_buf_len); +return -EIO ; + } + *device_id = pcu->cmd_buf[IMS_PCU_DATA_OFFSET ];dev_dbg (pcu->dev,"Detected device ID: %d\n" , *device_id);
@@ -1966,6 +2035,12 @@ static int ims_pcu_init_bootloader_mode(return error; } +if (pcu->cmd_buf_len <IMS_PCU_DATA_OFFSET +15 +4 +1 ) { +dev_err (pcu->dev,"Short QUERY_DEVICE response: %d bytes\n" , + pcu->cmd_buf_len); +return -EIO ; + } + pcu->fw_start_addr =get_unaligned_le32 (&pcu->cmd_buf[IMS_PCU_DATA_OFFSET +11 ]); pcu->fw_end_addr =
Greg Kroah-Hartman
maintainerPATCH 522/699 Input: ims-pcu - fix DMA mapping violation in line setup
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit 8adf4289d945e8990e4336436a97da71d21d2cae upstream.
In ims_pcu_line_setup(), the driver uses pcu->cmd_buf as a transfer buffer for usb_control_msg(). However, pcu->cmd_buf is embedded in the struct ims_pcu allocation, which violates DMA mapping rules regarding cacheline alignment.
Use a heap-allocated buffer for the line coding data instead.
--- drivers/input/misc/ims-pcu.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/input/misc/ims-pcu.c +7 -2
@@ -1808,11 +1808,16 @@ static void ims_pcu_stop_io(struct ims_pstatic int ims_pcu_line_setup (struct ims_pcu *pcu) {struct usb_host_interface *interface = pcu->ctrl_intf->cur_altsetting; -struct usb_cdc_line_coding *line = (void *)pcu->cmd_buf; + struct usb_cdc_line_coding *line __free(kfree) = +kmalloc (sizeof (*line),GFP_KERNEL );int error; -memset (line,0 ,sizeof (*line)); +if (!line) +return -ENOMEM ; + line->dwDTERate =cpu_to_le32 (57600 ); + line->bCharFormat =USB_CDC_1_STOP_BITS ; + line->bParityType =USB_CDC_NO_PARITY ; line->bDataBits =8 ; error = usb_control_msg(pcu->udev, usb_sndctrlpipe(pcu->udev, 0),
Greg Kroah-Hartman
maintainerPATCH 523/699 Input: ims-pcu - fix out-of-bounds read in ims_pcu_irq() debug logging
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit 403b0a6970b1084bb27907c0f8225801fdd0fe1d upstream.
The debug logging in ims_pcu_irq() unconditionally prints data from pcu->urb_in_buf. However, if the interrupt fired for pcu->urb_ctrl, the actual data resides in pcu->urb_ctrl_buf. If urb->actual_length for the control URB exceeds pcu->max_in_size, this leads to an out-of-bounds read.
Fix this by printing from the correct buffer associated with the URB.
--- drivers/input/misc/ims-pcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/misc/ims-pcu.c +1 -1
@@ -1547,7 +1547,7 @@ static void ims_pcu_irq(struct urb *urb) }dev_dbg (pcu->dev,"%s: received %d: %*ph\n" , __func__, - urb->actual_length, urb->actual_length, pcu->urb_in_buf); + urb->actual_length, urb->actual_length, urb->transfer_buffer);if (urb == pcu->urb_in)ims_pcu_process_data (pcu, urb);
Greg Kroah-Hartman
maintainerPATCH 524/699 Input: ims-pcu - fix potential infinite loop in CDC union descriptor parsing
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit d4579af29e67ca8722db0a1194227f8015c8981d upstream.
The driver parses CDC union descriptors in ims_pcu_get_cdc_union_desc() by iterating through the extra descriptor data. However, it does not verify that the bLength of each descriptor is at least 2. A malicious device could provide a descriptor with bLength = 0, leading to an infinite loop in the driver.
Add a check to ensure bLength is at least 2 before proceeding with parsing.
--- drivers/input/misc/ims-pcu.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/input/misc/ims-pcu.c +3 -2
@@ -1675,8 +1675,9 @@ ims_pcu_get_cdc_union_desc(struct usb_inwhile (buflen >=sizeof (*union_desc)) { union_desc = (struct usb_cdc_union_desc *)buf; -if (union_desc->bLength > buflen) { -dev_err (&intf->dev,"Too large descriptor\n" ); +if (union_desc->bLength <2 || union_desc->bLength > buflen) { +dev_err (&intf->dev,"Invalid descriptor length: %d\n" , + union_desc->bLength);return NULL ; }
Greg Kroah-Hartman
maintainerPATCH 525/699 Input: ims-pcu - fix type confusion in CDC union descriptor parsing
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dmitry Torokhov <[email protected]>
commit ca459e237bc49567649c56bc72e4c602fb92fd67 upstream.
The driver currently trusts the bMasterInterface0 from the CDC union descriptor without verifying that it matches the interface being probed. This could lead to the driver overwriting the private data of another interface.
Validate that the control interface found in the descriptor is indeed the one we are probing.
--- drivers/input/misc/ims-pcu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/input/misc/ims-pcu.c +1 -1
@@ -1713,7 +1713,7 @@ static int ims_pcu_parse_cdc_data(struct pcu->ctrl_intf =usb_ifnum_to_if (pcu->udev, union_desc->bMasterInterface0); -if (!pcu->ctrl_intf) +if (pcu->ctrl_intf != intf)return -EINVAL ; alt = pcu->ctrl_intf->cur_altsetting;
Greg Kroah-Hartman
maintainerPATCH 526/699 cpu: hotplug: Preserve per instance callback errors
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bradley Morgan <[email protected]>
commit 673db10729fb121ea1b16fe57791a0cb9eac1eb5 upstream.
cpuhp_invoke_callback() unwinds earlier callbacks for the same hotplug state when one instance fails. The rollback path currently reuses ret, so a successful rollback can hide the original error and make the failed transition look successful.
Keep the rollback result separate from the original error.
--- kernel/cpu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
kernel/cpu.c +4 -4
@@ -156,7 +156,7 @@ static int cpuhp_invoke_callback(unsignestruct cpuhp_step *step =cpuhp_get_step (state);int (*cbm)(unsigned int cpu,struct hlist_node *node);int (*cb)(unsigned int cpu); -int ret, cnt; +int ret, cnt, rollback_ret;if (st->fail == state) { st->fail =CPUHP_INVALID ;
@@ -222,12 +222,12 @@ err:break ;trace_cpuhp_multi_enter (cpu, st->target, state, cbm, node); - ret =cbm (cpu, node); -trace_cpuhp_exit (cpu, st->state, state, ret); + rollback_ret =cbm (cpu, node); +trace_cpuhp_exit (cpu, st->state, state, rollback_ret);/* * Rollback must not fail, */ -WARN_ON_ONCE (ret); +WARN_ON_ONCE (rollback_ret); }return ret; }
Greg Kroah-Hartman
maintainerPATCH 527/699 gpios: palmas: add .get_direction() op
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andreas Kemnade <[email protected]>
commit db4a79713ed8e252d5e4edf6eaaa80948b6855a2 upstream.
Accessing debug/gpio is quite noisy without a get_direction() implementation. To calm that down add an implementation.
--- drivers/gpio/gpio-palmas.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)
drivers/gpio/gpio-palmas.c +19 -0
@@ -118,6 +118,24 @@ static int palmas_gpio_input(struct gpioreturn ret; } +static int palmas_gpio_get_direction (struct gpio_chip *gc,unsigned int offset) +{ +struct palmas_gpio *pg =gpiochip_get_data (gc); +struct palmas *palmas = pg->palmas; +unsigned int val; +unsigned int reg; +int ret; +int gpio16 = (offset/8 ); + + offset %=8 ; + reg = (gpio16) ?PALMAS_GPIO_DATA_DIR2 :PALMAS_GPIO_DATA_DIR ; + ret =palmas_read (palmas,PALMAS_GPIO_BASE , reg, &val); +if (ret) +return ret; + +return (val &BIT (offset)) ?GPIO_LINE_DIRECTION_OUT :GPIO_LINE_DIRECTION_IN ; +} +static int palmas_gpio_to_irq (struct gpio_chip *gc,unsigned offset) {struct palmas_gpio *pg =gpiochip_get_data (gc);
@@ -166,6 +184,7 @@ static int palmas_gpio_probe(struct plat palmas_gpio->gpio_chip.can_sleep = true; palmas_gpio->gpio_chip.direction_input = palmas_gpio_input; palmas_gpio->gpio_chip.direction_output = palmas_gpio_output; + palmas_gpio->gpio_chip.get_direction = palmas_gpio_get_direction; palmas_gpio->gpio_chip.to_irq = palmas_gpio_to_irq; palmas_gpio->gpio_chip.set = palmas_gpio_set; palmas_gpio->gpio_chip.get = palmas_gpio_get;
Greg Kroah-Hartman
maintainerPATCH 528/699 net: sit: require CAP_NET_ADMIN in the device netns for changelink
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maoyi Xie <[email protected]>
commit 27ccb68e7cccead5d8c611665a45d23032d468b3 upstream.
ipip6_changelink() operates on at most two netns, dev_net(dev) and the tunnel link netns t->net. They differ once the device is created in or moved to a netns other than the one the request runs in. The rtnl changelink path checks CAP_NET_ADMIN only against dev_net(dev), so a caller privileged there but not in t->net can rewrite a tunnel that lives in t->net.
Gate ipip6_changelink() on rtnl_dev_link_net_capable() at its top, before any attribute is parsed. sit was the one tunnel type not covered by the recent series that added this check to the other changelink() handlers.
--- net/ipv6/sit.c | 3 +++ 1 file changed, 3 insertions(+)
net/ipv6/sit.c +3 -0
@@ -1670,6 +1670,9 @@ static int ipip6_changelink(struct net_d__u32 fwmark = t->fwmark;int err; +if (!rtnl_dev_link_net_capable (dev, net)) +return -EPERM ; +if (dev == sitn->fb_tunnel_dev)return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 529/699 net: ena: clean up XDP TX queues when regular TX setup fails
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dawei Feng <[email protected]>
commit 1bd6676254b4ab6acd44b662b5e92822c036463a upstream.
create_queues_with_size_backoff() creates XDP TX queues before setting up the regular TX path. If the subsequent allocation or creation of regular TX queues fails, the error handling paths omit the teardown of the XDP TX queues, leading to a resource leak.
Fix this by explicitly destroying the XDP TX queue subset at the two missing failure points.
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-rc7.
An x86_64 allyesconfig build showed no new warnings. As we do not have an ENA device to test with, no runtime testing was able to be performed.
--- drivers/net/ethernet/amazon/ena/ena_netdev.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
drivers/net/ethernet/amazon/ena/ena_netdev.c +21 -2
@@ -1162,6 +1162,18 @@ static void ena_destroy_all_tx_queues(st } } +static void ena_destroy_xdp_tx_queues (struct ena_adapter *adapter) +{ +u16 ena_qid; +int i; + +for (i = adapter->xdp_first_ring; + i < adapter->xdp_first_ring + adapter->xdp_num_queues; i++) { + ena_qid =ENA_IO_TXQ_IDX (i); +ena_com_destroy_io_queue (adapter->ena_dev, ena_qid); + } +} +static void ena_destroy_all_rx_queues (struct ena_adapter *adapter) {u16 ena_qid;
@@ -2465,14 +2477,21 @@ static int create_queues_with_size_backo rc =ena_setup_tx_resources_in_range (adapter,0 , adapter->num_io_queues); -if (rc) +if (rc) { +ena_destroy_xdp_tx_queues (adapter); +ena_free_all_io_tx_resources_in_range (adapter, + adapter->xdp_first_ring, + adapter->xdp_num_queues); goto err_setup_tx; + } rc =ena_create_io_tx_queues_in_range (adapter,0 , adapter->num_io_queues); -if (rc) +if (rc) { +ena_destroy_xdp_tx_queues (adapter); goto err_create_tx_queues; + } rc =ena_setup_all_rx_resources (adapter);if (rc)
Greg Kroah-Hartman
maintainerPATCH 530/699 net: ip6_vti: require CAP_NET_ADMIN in the device netns for changelink
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maoyi Xie <[email protected]>
commit e2ac3b242c37dff323a964962e43854f4b1a2b79 upstream.
vti6_changelink() operates on at most two netns, dev_net(dev) and the tunnel link netns t->net. They differ once the device is created in or moved to a netns other than the one the request runs in. The rtnl changelink path checks CAP_NET_ADMIN only against dev_net(dev), so a caller privileged there but not in t->net can rewrite a tunnel that lives in t->net.
Gate vti6_changelink() on rtnl_dev_link_net_capable() at its top, before any attribute is parsed.
--- net/ipv6/ip6_vti.c | 3 +++ 1 file changed, 3 insertions(+)
net/ipv6/ip6_vti.c +3 -0
@@ -1048,6 +1048,9 @@ static int vti6_changelink(struct net_destruct __ip6_tnl_parm p;struct vti6_net *ip6n; +if (!rtnl_dev_link_net_capable (dev, net)) +return -EPERM ; + ip6n =net_generic (net, vti6_net_id);if (dev == ip6n->fb_tnl_dev)return -EINVAL ;
Greg Kroah-Hartman
maintainerPATCH 531/699 net: ip_vti: require CAP_NET_ADMIN in the device netns for changelink
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maoyi Xie <[email protected]>
commit 95cceadbfd52d7239bd730afdda0655287d77425 upstream.
vti_changelink() operates on at most two netns, dev_net(dev) and the tunnel link netns t->net. They differ once the device is created in or moved to a netns other than the one the request runs in. The rtnl changelink path checks CAP_NET_ADMIN only against dev_net(dev), so a caller privileged there but not in t->net can rewrite a tunnel that lives in t->net.
Gate vti_changelink() on rtnl_dev_link_net_capable() at its top, before any attribute is parsed.
--- net/ipv4/ip_vti.c | 3 +++ 1 file changed, 3 insertions(+)
net/ipv4/ip_vti.c +3 -0
@@ -576,6 +576,9 @@ static int vti_changelink(struct net_dev__u32 fwmark = t->fwmark;struct ip_tunnel_parm p; +if (!rtnl_dev_link_net_capable (dev, t->net)) +return -EPERM ; +vti_netlink_parms (data, &p, &fwmark);return ip_tunnel_changelink (dev, tb, &p, fwmark); }
Greg Kroah-Hartman
maintainerPATCH 532/699 net: ip6_gre: require CAP_NET_ADMIN in the device netns for changelink
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maoyi Xie <[email protected]>
commit f00a50876d2818bd6dc86fa98b3ef360884c53c8 upstream.
ip6gre_changelink() and ip6erspan_changelink() operate on at most two netns, dev_net(dev) and the tunnel link netns t->net. They differ once the device is created in or moved to a netns other than the one the request runs in. The rtnl changelink path checks CAP_NET_ADMIN only against dev_net(dev), so a caller privileged there but not in t->net can rewrite a tunnel that lives in t->net.
Gate both ops on rtnl_dev_link_net_capable() at their top, before any attribute is parsed.
--- net/ipv6/ip6_gre.c | 6 ++++++ 1 file changed, 6 insertions(+)
net/ipv6/ip6_gre.c +6 -0
@@ -2090,6 +2090,9 @@ static int ip6gre_changelink(struct net_struct ip6gre_net *ign =net_generic (t->net, ip6gre_net_id);struct __ip6_tnl_parm p; +if (!rtnl_dev_link_net_capable (dev, t->net)) +return -EPERM ; + t =ip6gre_changelink_common (dev, tb, data, &p, extack);if (IS_ERR (t))return PTR_ERR (t);
@@ -2304,6 +2307,9 @@ static int ip6erspan_changelink(struct nstruct __ip6_tnl_parm p;struct ip6gre_net *ign; +if (!rtnl_dev_link_net_capable (dev, t->net)) +return -EPERM ; + ign =net_generic (t->net, ip6gre_net_id); t =ip6gre_changelink_common (dev, tb, data, &p, extack);if (IS_ERR (t))
Greg Kroah-Hartman
maintainerPATCH 533/699 ieee802154: admin-gate legacy LLSEC dump operations
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit 9c1e0b6d49471a712511d23fc9d06901561135e8 upstream.
In net/ieee802154/netlink.c, the legacy IEEE802154_NL family ops table builds the LLSEC dump entries (LLSEC_LIST_KEY, LLSEC_LIST_DEV, LLSEC_LIST_DEVKEY, LLSEC_LIST_SECLEVEL) with IEEE802154_DUMP() which sets no .flags, so generic netlink runs them ungated. The modern nl802154 family admin-gates the equivalent reads via NL802154_CMD_GET_SEC_KEY and friends with .flags = GENL_ADMIN_PERM.
Any local uid that can open AF_NETLINK / NETLINK_GENERIC can resolve the "802.15.4 MAC" family and dump LLSEC_LIST_KEY on any wpan netdev that has an LLSEC key installed; the dump handler writes the raw 16-byte AES-128 key bytes (IEEE802154_ATTR_LLSEC_KEY_BYTES, copied verbatim from struct ieee802154_llsec_key.key) into the reply. Recovering the AES key compromises 802.15.4 LLSEC link confidentiality and authenticity, since LLSEC uses CCM* and the same key authenticates and encrypts frames.
Impact: any local uid with no capabilities can read the raw 16-byte AES-128 LLSEC key from the kernel keytable on any wpan netdev that has an administrator-installed LLSEC key, by issuing an LLSEC_LIST_KEY dump on the legacy IEEE802154_NL generic-netlink family.
Introduce IEEE802154_DUMP_PRIV() mirroring IEEE802154_DUMP() but setting .flags = GENL_ADMIN_PERM, and use it for the four LLSEC dump entries. LIST_PHY and LIST_IFACE retain IEEE802154_DUMP() because the modern nl802154 family exposes their equivalents to unprivileged readers by design (NL802154_CMD_GET_WPAN_PHY and NL802154_CMD_GET_INTERFACE carry "can be retrieved by unprivileged users" annotations).
--- net/ieee802154/ieee802154.h | 8 ++++++++ net/ieee802154/netlink.c | 16 ++++++++-------- 2 files changed, 16 insertions(+), 8 deletions(-)
net/ieee802154/ieee802154.h +8 -0
@@ -23,6 +23,14 @@ void ieee802154_nl_exit(void); .dumpit = _dump, \ } +#define IEEE802154_DUMP_PRIV (_cmd, _func, _dump) \ + { \ + .cmd = _cmd, \ + .doit = _func, \ + .dumpit = _dump, \ + .flags = GENL_ADMIN_PERM, \ + } +struct genl_info ;struct sk_buff *ieee802154_nl_create (int flags,u8 req);
net/ieee802154/netlink.c +8 -8
@@ -98,20 +98,20 @@ static const struct genl_small_ops ieee8IEEE802154_OP (IEEE802154_SET_MACPARAMS , ieee802154_set_macparams),IEEE802154_OP (IEEE802154_LLSEC_GETPARAMS , ieee802154_llsec_getparams),IEEE802154_OP (IEEE802154_LLSEC_SETPARAMS , ieee802154_llsec_setparams), -IEEE802154_DUMP (IEEE802154_LLSEC_LIST_KEY ,NULL , - ieee802154_llsec_dump_keys), +IEEE802154_DUMP_PRIV (IEEE802154_LLSEC_LIST_KEY ,NULL , + ieee802154_llsec_dump_keys),IEEE802154_OP (IEEE802154_LLSEC_ADD_KEY , ieee802154_llsec_add_key),IEEE802154_OP (IEEE802154_LLSEC_DEL_KEY , ieee802154_llsec_del_key), -IEEE802154_DUMP (IEEE802154_LLSEC_LIST_DEV ,NULL , - ieee802154_llsec_dump_devs), +IEEE802154_DUMP_PRIV (IEEE802154_LLSEC_LIST_DEV ,NULL , + ieee802154_llsec_dump_devs),IEEE802154_OP (IEEE802154_LLSEC_ADD_DEV , ieee802154_llsec_add_dev),IEEE802154_OP (IEEE802154_LLSEC_DEL_DEV , ieee802154_llsec_del_dev), -IEEE802154_DUMP (IEEE802154_LLSEC_LIST_DEVKEY ,NULL , - ieee802154_llsec_dump_devkeys), +IEEE802154_DUMP_PRIV (IEEE802154_LLSEC_LIST_DEVKEY ,NULL , + ieee802154_llsec_dump_devkeys),IEEE802154_OP (IEEE802154_LLSEC_ADD_DEVKEY , ieee802154_llsec_add_devkey),IEEE802154_OP (IEEE802154_LLSEC_DEL_DEVKEY , ieee802154_llsec_del_devkey), -IEEE802154_DUMP (IEEE802154_LLSEC_LIST_SECLEVEL ,NULL , - ieee802154_llsec_dump_seclevels), +IEEE802154_DUMP_PRIV (IEEE802154_LLSEC_LIST_SECLEVEL ,NULL , + ieee802154_llsec_dump_seclevels),IEEE802154_OP (IEEE802154_LLSEC_ADD_SECLEVEL , ieee802154_llsec_add_seclevel), IEEE802154_OP(IEEE802154_LLSEC_DEL_SECLEVEL,
Greg Kroah-Hartman
maintainerPATCH 534/699 ieee802154: allow legacy LLSEC ADD/DEL ops to pass strict validation
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit a6bfdfcc6711d1d5a92e98644359dedc67c0c858 upstream.
The LLSEC ADD/DEL doit handlers under the legacy IEEE802154_NL family consume IEEE802154_ATTR_LLSEC_KEY_BYTES and IEEE802154_ATTR_LLSEC_KEY_USAGE_COMMANDS, both declared in net/ieee802154/nl_policy.c as bare length entries with no .type (defaulting to NLA_UNSPEC). Generic netlink strict validation rejects all NLA_UNSPEC attributes via validate_nla(), so every LLSEC_ADD_KEY, LLSEC_DEL_KEY, LLSEC_ADD_DEV, LLSEC_DEL_DEV, LLSEC_ADD_DEVKEY, LLSEC_DEL_DEVKEY, LLSEC_ADD_SECLEVEL, and LLSEC_DEL_SECLEVEL request fails at the dispatcher with "Unsupported attribute" before reaching the handler.
The doit path has been silently dead since strict validation became the default for genl families that do not opt out. The dump path is unaffected because dump requests carry no LLSEC attributes to validate, which is why the LLSEC_LIST_KEY read remained reachable (patch 1/2). Introduce IEEE802154_OP_RELAXED() mirroring IEEE802154_OP() but with .validate = GENL_DONT_VALIDATE_STRICT, and use it for the eight legacy LLSEC mutate ops so admin-driven LLSEC configuration via the legacy interface works again.
--- net/ieee802154/ieee802154.h | 9 +++++++++ net/ieee802154/netlink.c | 20 ++++++++++---------- 2 files changed, 19 insertions(+), 10 deletions(-)
net/ieee802154/ieee802154.h +9 -0
@@ -16,6 +16,15 @@ void ieee802154_nl_exit(void); .flags = GENL_ADMIN_PERM, \ } +#define IEEE802154_OP_RELAXED (_cmd, _func) \ + { \ + .cmd = _cmd, \ + .doit = _func, \ + .dumpit = NULL, \ + .flags = GENL_ADMIN_PERM, \ + .validate = GENL_DONT_VALIDATE_STRICT,\ + } +#define IEEE802154_DUMP (_cmd, _func, _dump) \ { \ .cmd = _cmd, \
net/ieee802154/netlink.c +10 -10
@@ -100,22 +100,22 @@ static const struct genl_small_ops ieee8IEEE802154_OP (IEEE802154_LLSEC_SETPARAMS , ieee802154_llsec_setparams),IEEE802154_DUMP_PRIV (IEEE802154_LLSEC_LIST_KEY ,NULL , ieee802154_llsec_dump_keys), -IEEE802154_OP (IEEE802154_LLSEC_ADD_KEY , ieee802154_llsec_add_key), -IEEE802154_OP (IEEE802154_LLSEC_DEL_KEY , ieee802154_llsec_del_key), +IEEE802154_OP_RELAXED (IEEE802154_LLSEC_ADD_KEY , ieee802154_llsec_add_key), +IEEE802154_OP_RELAXED (IEEE802154_LLSEC_DEL_KEY , ieee802154_llsec_del_key),IEEE802154_DUMP_PRIV (IEEE802154_LLSEC_LIST_DEV ,NULL , ieee802154_llsec_dump_devs), -IEEE802154_OP (IEEE802154_LLSEC_ADD_DEV , ieee802154_llsec_add_dev), -IEEE802154_OP (IEEE802154_LLSEC_DEL_DEV , ieee802154_llsec_del_dev), +IEEE802154_OP_RELAXED (IEEE802154_LLSEC_ADD_DEV , ieee802154_llsec_add_dev), +IEEE802154_OP_RELAXED (IEEE802154_LLSEC_DEL_DEV , ieee802154_llsec_del_dev),IEEE802154_DUMP_PRIV (IEEE802154_LLSEC_LIST_DEVKEY ,NULL , ieee802154_llsec_dump_devkeys), -IEEE802154_OP (IEEE802154_LLSEC_ADD_DEVKEY , ieee802154_llsec_add_devkey), -IEEE802154_OP (IEEE802154_LLSEC_DEL_DEVKEY , ieee802154_llsec_del_devkey), +IEEE802154_OP_RELAXED (IEEE802154_LLSEC_ADD_DEVKEY , ieee802154_llsec_add_devkey), +IEEE802154_OP_RELAXED (IEEE802154_LLSEC_DEL_DEVKEY , ieee802154_llsec_del_devkey),IEEE802154_DUMP_PRIV (IEEE802154_LLSEC_LIST_SECLEVEL ,NULL , ieee802154_llsec_dump_seclevels), -IEEE802154_OP (IEEE802154_LLSEC_ADD_SECLEVEL , - ieee802154_llsec_add_seclevel), -IEEE802154_OP (IEEE802154_LLSEC_DEL_SECLEVEL , - ieee802154_llsec_del_seclevel), +IEEE802154_OP_RELAXED (IEEE802154_LLSEC_ADD_SECLEVEL , + ieee802154_llsec_add_seclevel), +IEEE802154_OP_RELAXED (IEEE802154_LLSEC_DEL_SECLEVEL , + ieee802154_llsec_del_seclevel), }; static const struct genl_multicast_group ieee802154_mcgrps[] = {
Greg Kroah-Hartman
maintainerPATCH 535/699 ieee802154: ca8210: fix cas_ctl leak on spi_async failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shitalkumar Gandhi <[email protected]>
commit e09390e439bd7cca30dd10893b1f64802961667a upstream.
ca8210_spi_transfer() allocates cas_ctl with kzalloc_obj(GFP_ATOMIC) and relies entirely on the SPI completion callback ca8210_spi_transfer_complete() to free it.
The spi_async() API only invokes the completion callback on successful submission. On failure it returns a negative error code without ever queuing the callback, which leaves cas_ctl and its embedded spi_message and spi_transfer orphaned. Every kfree(cas_ctl) in the driver is inside the completion callback, so there is no other reclamation path.
ca8210_spi_transfer() is called from ca8210_spi_exchange(), the interrupt handler ca8210_interrupt_handler(), and from the retry path inside the completion callback itself. The exchange and interrupt handler paths loop on -EBUSY, so under sustained SPI bus contention every retry iteration leaks a fresh cas_ctl (~600 bytes per occurrence).
Fix it by freeing cas_ctl on the spi_async() error path. While here, correct the misleading error string: the function calls spi_async(), not spi_sync().
--- drivers/net/ieee802154/ca8210.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/ieee802154/ca8210.c +2 -1
@@ -962,9 +962,10 @@ static int ca8210_spi_transfer(if (status <0 ) {dev_crit ( &spi->dev, -"status %d from spi_sync in write\n" , +"status %d from spi_async in write\n" , status ); +kfree (cas_ctl); }return status;
Greg Kroah-Hartman
maintainerPATCH 536/699 ieee802154: ca8210: fix pointer truncation in kfifo on 64-bit
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shitalkumar Gandhi <[email protected]>
commit 6d7f7bcf225b2d566176bf6229dbd1252940cb3c upstream.
ca8210_test_int_driver_write() and ca8210_test_int_user_read() exchange a kmalloc'd buffer pointer through a struct kfifo, but pass a literal '4' as the byte count to kfifo_in()/kfifo_out().
This is correct on 32-bit (pointer = 4 bytes), but on 64-bit only the low 4 bytes of the 8-byte pointer are written into the FIFO. The reader then reads back 4 bytes into an 8-byte local pointer variable, leaving the upper 4 bytes uninitialized stack data. The first dereference of the reconstructed pointer (fifo_buffer[1]) accesses an arbitrary kernel address and generally results in an oops.
Use sizeof(fifo_buffer) so the byte count matches pointer width on every architecture.
The driver has no architecture restriction in Kconfig, so any 64-bit build with CONFIG_IEEE802154_CA8210_DEBUGFS=y is exposed. Issue has been latent since the driver was added in 2017 because it is most commonly deployed on 32-bit MCUs.
Found via a custom Coccinelle semantic patch hunting for short-byte kfifo I/O on byte-mode kfifos used to shuttle pointers.
--- drivers/net/ieee802154/ca8210.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/ieee802154/ca8210.c +4 -2
@@ -638,7 +638,7 @@ static int ca8210_test_int_driver_write( fifo_buffer =kmemdup (buf, len,GFP_KERNEL );if (!fifo_buffer)return -ENOMEM ; -kfifo_in (&test->up_fifo, &fifo_buffer,4 ); +kfifo_in (&test->up_fifo, &fifo_buffer,sizeof (fifo_buffer));wake_up_interruptible (&priv->test.readq);return 0 ;
@@ -2571,6 +2571,7 @@ static ssize_t ca8210_test_int_user_readstruct ca8210_priv *priv = filp->private_data;unsigned char *fifo_buffer;unsigned long bytes_not_copied; +unsigned int copied;if (filp->f_flags &O_NONBLOCK ) {/* Non-blocking mode */
@@ -2584,7 +2585,8 @@ static ssize_t ca8210_test_int_user_read ); } -if (kfifo_out (&priv->test.up_fifo, &fifo_buffer,4 ) !=4 ) { + copied =kfifo_out (&priv->test.up_fifo, &fifo_buffer,sizeof (fifo_buffer)); +if (copied !=sizeof (fifo_buffer)) {dev_err ( &priv->spi->dev, "test_interface: Wrong number of elements popped from upstream fifo\n"
Greg Kroah-Hartman
maintainerPATCH 537/699 nvmet-tcp: check INIT_FAILED before nvmet_req_uninit in digest error path
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shivam Kumar <[email protected]>
commit 4606467a75cfc16721937272ed29462a750b60c8 upstream.
In nvmet_tcp_try_recv_ddgst(), when a data digest mismatch is detected, nvmet_req_uninit() is called unconditionally. However, if the command arrived via the nvmet_tcp_handle_req_failure() path, nvmet_req_init() had returned false and percpu_ref_tryget_live() was never executed. The unconditional percpu_ref_put() inside nvmet_req_uninit() then causes a refcount underflow, leading to a WARNING in percpu_ref_switch_to_atomic_rcu, a use-after-free diagnostic, and eventually a permanent workqueue deadlock.
Check cmd->flags & NVMET_TCP_F_INIT_FAILED before calling nvmet_req_uninit(), matching the existing pattern in nvmet_tcp_execute_request().
--- drivers/nvme/target/tcp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/nvme/target/tcp.c +3 -1
@@ -1227,7 +1227,9 @@ static int nvmet_tcp_try_recv_ddgst(struct nvmet_tcp_queue *queue) queue->idx, cmd->req.cmd->common.command_id, queue->pdu.cmd.hdr.type,le32_to_cpu (cmd->recv_ddgst), le32_to_cpu(cmd->exp_ddgst)); -nvmet_tcp_finish_cmd (cmd); +if (!(cmd->flags &NVMET_TCP_F_INIT_FAILED )) +nvmet_req_uninit (&cmd->req); +nvmet_tcp_free_cmd_buffers (cmd);nvmet_tcp_fatal_error (queue); ret = -EPROTO ; goto out;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 538/699 batman-adv: retrieve ethhdr after potential skb realloc on RX
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 035e1fed892d3d06002a73ff73668f618a514644 upstream.
pskb_may_pull() in batadv_interface_rx() could reallocate the buffer behind the skb. Variables which were pointing to the old buffer need to be reassigned to avoid an use-after-free.
This was done correctly for the VLAN header but missed for the ethernet header which is later used for the TT and AP isolation handling.
--- net/batman-adv/soft-interface.c | 1 + 1 file changed, 1 insertion(+)
net/batman-adv/soft-interface.c +1 -0
@@ -454,6 +454,7 @@ void batadv_interface_rx(struct net_device *soft_iface,if (!pskb_may_pull (skb,VLAN_ETH_HLEN )) goto dropped; + ethhdr =eth_hdr (skb); vhdr =skb_vlan_eth_hdr (skb);/* drop batman-in-batman packets to prevent loops */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 539/699 batman-adv: ensure minimal ethernet header on TX
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sven Eckelmann <[email protected]>
commit 49df66b7993c80b80c7eb9a84ba5b3410c8296a0 upstream.
As documented in commit 8bd67ebb50c0 ("net: bridge: xmit: make sure we have at least eth header len bytes"), it is possible by for a local user with eBPF TC hook access to attach a tc filter which truncates the packet and redirects to an batadv interface. But the code assumes that at least ETH_HLEN bytes are available and thus might read outside of the available buffer.
The batadv_interface_tx() must therefore always check itself if enough data is available for the ethernet header and don't rely on min_header_len.
--- net/batman-adv/soft-interface.c | 3 +++ 1 file changed, 3 insertions(+)
net/batman-adv/soft-interface.c +3 -0
@@ -210,6 +210,9 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,if (atomic_read (&bat_priv->mesh_state) !=BATADV_MESH_ACTIVE ) goto dropped; +if (!pskb_may_pull (skb,ETH_HLEN )) + goto dropped; +/* reset control block to avoid left overs from previous users */ memset (skb->cb,0 ,sizeof (struct batadv_skb_cb ));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 540/699 rtmutex: Use waiter::task instead of current in remove_waiter()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Keenan Dong <[email protected]>
commit 3bfdc63936dd4773109b7b8c280c0f3b5ae7d349 upstream.
remove_waiter() is used by the slowlock paths, but it is also used for proxy-lock rollback in rt_mutex_start_proxy_lock() when invoked from futex_requeue().
In the latter case waiter::task is not current, but remove_waiter() operates on current for the dequeue operation. That results in several problems:
1) the rbtree dequeue happens without waiter::task::pi_lock being held
2) the waiter task's pi_blocked_on state is not cleared, which leaves a dangling pointer primed for UAF around.
3) rt_mutex_adjust_prio_chain() operates on the wrong top priority waiter task
Use waiter::task instead of current in all related operations in remove_waiter() to cure those problems.
[ tglx: Fixup rt_mutex_adjust_prio_chain(), add a comment and amend the
changelog ]
--- kernel/locking/rtmutex.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
kernel/locking/rtmutex.c +7 -4
@@ -1061,20 +1061,23 @@ static void mark_wakeup_next_waiter(stru* * Must be called with lock->wait_lock held and interrupts disabled. I must * have just failed to try_to_take_rt_mutex(). +* +* When invoked from rt_mutex_start_proxy_lock() waiter::task != current ! */ static void remove_waiter (struct rt_mutex *lock,struct rt_mutex_waiter *waiter) {bool is_top_waiter = (waiter ==rt_mutex_top_waiter (lock));struct task_struct *owner =rt_mutex_owner (lock); +struct task_struct *waiter_task = waiter->task;struct rt_mutex *next_lock;lockdep_assert_held (&lock->wait_lock); -raw_spin_lock (¤t->pi_lock); +raw_spin_lock (&waiter_task->pi_lock);rt_mutex_dequeue (lock, waiter); - current->pi_blocked_on =NULL ; -raw_spin_unlock (¤t->pi_lock); + waiter_task->pi_blocked_on =NULL ; +raw_spin_unlock (&waiter_task->pi_lock);/* * Only update priority if the waiter was the highest priority
@@ -1110,7 +1113,7 @@ static void remove_waiter(struct rt_muteraw_spin_unlock_irq (&lock->wait_lock);rt_mutex_adjust_prio_chain (owner,RT_MUTEX_MIN_CHAINWALK , lock, - next_lock,NULL , current); + next_lock,NULL , waiter_task);raw_spin_lock_irq (&lock->wait_lock); }
Greg Kroah-Hartman
maintainerPATCH 541/699 locking/rtmutex: Skip remove_waiter() when waiter is not enqueued
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Davidlohr Bueso <[email protected]>
commit 40a25d59e85b3c8709ac2424d44f65610467871e upstream.
syzbot triggered the following splat in remove_waiter() via FUTEX_CMP_REQUEUE_PI:
KASAN: null-ptr-deref in range [0x0000000000000a88-0x0000000000000a8f] class_raw_spinlock_constructor remove_waiter+0x159/0x1200 kernel/locking/rtmutex.c:1561 rt_mutex_start_proxy_lock+0x103/0x120 futex_requeue+0x10e4/0x20d0 __x64_sys_futex+0x34f/0x4d0
task_blocks_on_rt_mutex() does not arm the waiter upon deadlock detection, leaving waiter->task nil, where 3bfdc63936dd ("rtmutex: Use waiter::task instead of current in remove_waiter()") made this fatal.
Furthermore, rt_mutex_start_proxy_lock() should not be calling into remove_waiter() upon a successfully grabbing the rtmutex. 1a1fb985f2e2 ("futex: Handle early deadlock return correctly"), moved the remove_waiter() out of __rt_mutex_start_proxy_lock() (where 'ret' was only ever 0 or < 0) into the wrapper. Tighten this check to account for try_to_take_rt_mutex().
--- kernel/locking/rtmutex.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
kernel/locking/rtmutex.c +4 -1
@@ -1074,6 +1074,9 @@ static void remove_waiter(struct rt_mutelockdep_assert_held (&lock->wait_lock); +if (!waiter_task)/* never enqueued */ +return ; +raw_spin_lock (&waiter_task->pi_lock);rt_mutex_dequeue (lock, waiter); waiter_task->pi_blocked_on =NULL ;
@@ -1803,7 +1806,7 @@ int rt_mutex_start_proxy_lock(struct rt_raw_spin_lock_irq (&lock->wait_lock); ret =__rt_mutex_start_proxy_lock (lock, waiter, task); -if (unlikely (ret)) +if (unlikely (ret <0 ))remove_waiter (lock, waiter);raw_spin_unlock_irq (&lock->wait_lock);
Greg Kroah-Hartman
maintainerPATCH 542/699 bnx2x: fix potential memory leak in bnx2x_alloc_mem_bp()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abdun Nihaal <[email protected]>
commit a986fde914d88af47eb78fd29c5d1af7952c3500 upstream.
If the allocation of fp[i].tpa_info fails, the error path will not free the struct bnx2x_fastpath allocated earlier, as it is not linked to the bp structure yet. Fix that by linking it immediately after allocation.
--- drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +1 -2
@@ -4740,6 +4740,7 @@ int bnx2x_alloc_mem_bp(struct bnx2x *bp) fp =kcalloc (bp->fp_array_size,sizeof (*fp),GFP_KERNEL );if (!fp) goto alloc_err; + bp->fp = fp;for (i =0 ; i < bp->fp_array_size; i++) { fp[i].tpa_info = kcalloc(ETH_MAX_AGGREGATION_QUEUES_E1H_E2,
@@ -4748,8 +4749,6 @@ int bnx2x_alloc_mem_bp(struct bnx2x *bp) goto alloc_err; } - bp->fp = fp; -/* allocate sp objs */ bp->sp_objs =kcalloc (bp->fp_array_size,sizeof (struct bnx2x_sp_objs ),GFP_KERNEL );
Greg Kroah-Hartman
maintainerPATCH 543/699 hwmon: (w83627hf) remove VID sysfs files on error and remove
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
commit 5264b389c4e02dec214a46c400eb3ab867a7749a upstream.
w83627hf_probe() creates cpu0_vid and vrm with device_create_file() when VID information is available.
The error path and remove callback only remove the common and optional attribute groups. Those groups do not contain cpu0_vid or vrm, so the files can remain after a later probe failure or after device removal while their callbacks still expect live driver data.
Remove the standalone VID sysfs files from both the probe error path and the remove callback.
--- drivers/hwmon/w83627hf.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/hwmon/w83627hf.c +4 -0
@@ -1551,6 +1551,8 @@ static int w83627hf_probe(struct platforreturn 0 ; error: +device_remove_file (dev, &dev_attr_vrm); +device_remove_file (dev, &dev_attr_cpu0_vid);sysfs_remove_group (&dev->kobj, &w83627hf_group);sysfs_remove_group (&dev->kobj, &w83627hf_group_opt);return err;
@@ -1562,6 +1564,8 @@ static int w83627hf_remove(struct platfohwmon_device_unregister (data->hwmon_dev); +device_remove_file (&pdev->dev, &dev_attr_vrm); +device_remove_file (&pdev->dev, &dev_attr_cpu0_vid);sysfs_remove_group (&pdev->dev.kobj, &w83627hf_group);sysfs_remove_group (&pdev->dev.kobj, &w83627hf_group_opt);
Greg Kroah-Hartman
maintainerPATCH 544/699 hwmon: (w83793) remove vrm sysfs file on probe failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
commit 77b983757280c69b0290811669ff1d31022e5f1d upstream.
w83793_probe() creates the vrm sysfs file after creating the VID files when VID support is present.
The normal remove path deletes vrm, but the probe error path only removes the sensor, SDA, VID, fan, PWM and temperature files. A later probe failure can therefore leave vrm behind after the driver data has been freed.
Remove vrm in the probe error path next to the VID files, matching the normal remove path.
--- drivers/hwmon/w83793.c | 1 + 1 file changed, 1 insertion(+)
drivers/hwmon/w83793.c +1 -0
@@ -1920,6 +1920,7 @@ exit_remove:for (i =0 ; i <ARRAY_SIZE (w83793_vid); i++)device_remove_file (dev, &w83793_vid[i].dev_attr); +device_remove_file (dev, &dev_attr_vrm);for (i =0 ; i <ARRAY_SIZE (w83793_left_fan); i++)device_remove_file (dev, &w83793_left_fan[i].dev_attr);
Greg Kroah-Hartman
maintainerPATCH 545/699 net: liquidio: fix BAR resource leak on PF number failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
commit c63ee62a3c4ac1a1542f4c1a4b87e2f41df5a496 upstream.
If cn23xx_get_pf_num() fails, the function returns without unmapping either BAR. Unmap both BARs before returning from the error path.
Found by manual code review.
--- drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c | 18 ++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-)
drivers/net/ethernet/cavium/liquidio/cn23xx_pf_device.c +10 -8
@@ -1334,18 +1334,14 @@ int setup_cn23xx_octeon_pf_device(structif (octeon_map_pci_barx (oct,1 ,MAX_BAR1_IOREMAP_SIZE )) {dev_err (&oct->pci_dev->dev,"%s CN23XX BAR1 map failed\n" , __func__); -octeon_unmap_pci_barx (oct,0 ); -return 1 ; + goto err_unmap_bar0; }if (cn23xx_get_pf_num (oct) !=0 ) -return 1 ; + goto err_unmap_bar1; -if (cn23xx_sriov_config (oct)) { -octeon_unmap_pci_barx (oct,0 ); -octeon_unmap_pci_barx (oct,1 ); -return 1 ; - } +if (cn23xx_sriov_config (oct)) + goto err_unmap_bar1;octeon_write_csr64 (oct,CN23XX_SLI_MAC_CREDIT_CNT ,0x3F802080802080ULL );
@@ -1376,6 +1372,12 @@ int setup_cn23xx_octeon_pf_device(struct oct->coproc_clock_rate =1000000ULL *cn23xx_coprocessor_clock (oct);return 0 ; + +err_unmap_bar1: +octeon_unmap_pci_barx (oct,1 ); +err_unmap_bar0: +octeon_unmap_pci_barx (oct,0 ); +return 1 ; } int validate_cn23xx_pf_config_info(struct octeon_device *oct,
Greg Kroah-Hartman
maintainerPATCH 546/699 fsl/fman: Free init resources on KeyGen failure in fman_init()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Haoxiang Li <[email protected]>
commit d288efa2b94abc2e45a061fceb156b4f4e5b37be upstream.
fman_muram_alloc() allocates initialization resources before initializing the KeyGen block. If keygen_init() fails, the function returns -EINVAL directly and leaves those resources allocated. Free the initialization resources before returning from the KeyGen failure path.
--- drivers/net/ethernet/freescale/fman/fman.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/net/ethernet/freescale/fman/fman.c +3 -1
@@ -2022,8 +2022,10 @@ static int fman_init(struct fman *fman)/* Init KeyGen */ fman->keygen =keygen_init (fman->kg_regs); -if (!fman->keygen) +if (!fman->keygen) { +free_init_resources (fman);return -EINVAL ; + } err =enable (fman, cfg);if (err !=0 )
Greg Kroah-Hartman
maintainerPATCH 547/699 net/sched: sch_multiq: Replace direct dequeue call with peek and qdisc_dequeue_peeked
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit 54f6b0c843e228d499eb4b6bbb89df68cad9ad5d upstream.
multiq_dequeue() takes a packet from a band's child with a direct ->dequeue() call after multiq_peek() peeked it. When the child is non-work-conserving the peek stashes the skb in the child's gso_skb, so the direct dequeue returns a different skb and orphans the stash, desyncing the child's qlen/backlog. With a qfq child reached through a peeking parent (e.g. tbf) this re-enters the child on an emptied list and dereferences NULL, panicking the kernel from softirq on ordinary egress.
Take the packet through qdisc_dequeue_peeked(), as sch_prio already does and as sch_red and sch_sfb were just fixed to do. The helper is a no-op when the child has no stash, so a work-conserving child is unaffected.
--- net/sched/sch_multiq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sched/sch_multiq.c +1 -1
@@ -103,7 +103,7 @@ static struct sk_buff *multiq_dequeue(stif (!netif_xmit_stopped (netdev_get_tx_queue (qdisc_dev (sch), q->curband))) { qdisc = q->queues[q->curband]; - skb = qdisc->dequeue (qdisc); + skb =qdisc_dequeue_peeked (qdisc);if (skb) {qdisc_bstats_update (sch, skb); sch->q.qlen--;
Greg Kroah-Hartman
maintainerPATCH 548/699 tracing/probes: Fix double addition of offset for @+FOFFSET
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Masami Hiramatsu (Google) <[email protected]>
commit 9a667b7750dda88cbf1cca96a53a2163b2ee71f7 upstream.
Since commit 533059281ee5 ("tracing: probeevent: Introduce new argument
fetching code") wrongly use @offset local variable during the parsing,
the offset value is added twice when dereferencing.
Reset the @offset after setting it in FETCH_OP_FOFFS.
--- kernel/trace/trace_probe.c | 1 + 1 file changed, 1 insertion(+)
kernel/trace/trace_probe.c +1 -0
@@ -401,6 +401,7 @@ parse_probe_arg(char *arg, const struct code->op =FETCH_OP_FOFFS ; code->immediate = (unsigned long )offset;// imm64? + offset =0 ; }else {/* uprobes don't support symbols */ if (!(flags &TPARG_FL_KERNEL )) {
Greg Kroah-Hartman
maintainerPATCH 549/699 orangefs: keep the readdir entry size 64-bit in fill_from_part()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Bryam Vargas <[email protected]>
commit 18227a6bc98bd0ba96ed3ce9d5b28776a5a28dfc upstream.
fill_from_part() computes the size of a directory entry in size_t but stores it in a __u32. An entry length near U32_MAX wraps it to a small value, bypasses the bounds check, and is then used to index the entry, reading far past the directory part -- an out-of-bounds read that oopses the kernel.
Compute the size as a u64 so it cannot truncate; the bounds check then rejects the entry. The trailer is supplied by the userspace client.
--- fs/orangefs/dir.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
fs/orangefs/dir.c +4 -3
@@ -191,7 +191,8 @@ static int fill_from_part(struct orangef {const int offset =sizeof (struct orangefs_readdir_response_s );struct orangefs_khandle *khandle; -__u32 *len, padlen; +__u32 *len; +u64 padlen;loff_t i;char *s; i = ctx->pos & ~PART_MASK ;
@@ -215,8 +216,8 @@ static int fill_from_part(struct orangef* len is the size of the string itself. padlen is the * total size of the encoded string. */ - padlen = (sizeof *len + *len +1 ) + - (8 - (sizeof *len + *len +1 )%8 )%8 ; + padlen = (u64 )sizeof *len + *len +1 ; + padlen += (8 - padlen %8 ) %8 ;if (part->len < i + padlen +sizeof *khandle) goto next; s = (void *)part + offset + i +sizeof *len;
Greg Kroah-Hartman
maintainerPATCH 550/699 ata: pata_pxa: Fix DMA channel leak on probe error
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wentao Liang <[email protected]>
commit fcaf242e7fc406e78f444a35441e3b58f5e28781 upstream.
When dmaengine_slave_config() fails, the DMA channel acquired by dma_request_chan() is not released before returning the error, leaking the channel reference.
Fix by adding dma_release_channel() in the error path.
The ata_host_activate() error path already correctly releases the DMA channel.
--- drivers/ata/pata_pxa.c | 1 + 1 file changed, 1 insertion(+)
drivers/ata/pata_pxa.c +1 -0
@@ -287,6 +287,7 @@ static int pxa_ata_probe(struct platform ret =dmaengine_slave_config (data->dma_chan, &config);if (ret <0 ) {dev_err (&pdev->dev,"dma configuration failed: %d\n" , ret); +dma_release_channel (data->dma_chan);return ret; }
Greg Kroah-Hartman
maintainerPATCH 551/699 hwmon: (asus_atk0110) Check package count before accessing element
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: HyeongJun An <[email protected]>
commit e2735b39f044bad7bf2017aef248935525bc0b97 upstream.
atk_ec_present() walks the management group package returned by the GGRP ACPI method and, for each sub-package, reads its first element:
id = &obj->package.elements[0]; if (id->type != ACPI_TYPE_INTEGER)
without checking that the sub-package is non-empty. ACPICA allocates the element array with exactly package.count entries, so for a sub-package with a zero count this reads past the allocation.
The sibling function atk_debugfs_ggrp_open() performs the same access but skips empty packages with a package.count check first. Add the same check to atk_ec_present() so a malformed firmware package cannot trigger an out-of-bounds read.
--- drivers/hwmon/asus_atk0110.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/hwmon/asus_atk0110.c +3 -0
@@ -1037,6 +1037,9 @@ static int atk_ec_present(struct atk_datif (obj->type !=ACPI_TYPE_PACKAGE )continue ; +if (!obj->package.count) +continue ; + id = &obj->package.elements[0 ];if (id->type !=ACPI_TYPE_INTEGER )continue ;
Greg Kroah-Hartman
maintainerPATCH 552/699 s390/monwriter: Reject buffer reuse with different data length
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gerald Schaefer <[email protected]>
commit 2995ccec260caa9e85b3301a4aba1e66ed80ad74 upstream.
When data buffers are reused, e.g. for interval sample records, the first record determines the data length, and the size of the buffer for user copy. Current monwriter code does not check if the data length was changed for subsequent records, which also would never happen for valid user programs.
However, a malicious user could change the data length, resulting in out of bounds user copy to the kernel buffer, and memory corruption. By default, the monwriter misc device is created with root-only permissions, so practical impact is typically low.
Fix this by checking for changed data length and rejecting such records.
--- drivers/s390/char/monwriter.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/s390/char/monwriter.c +3 -0
@@ -126,6 +126,9 @@ static int monwrite_new_hdr(struct mon_pkfree (monbuf->data);kfree (monbuf); monbuf =NULL ; + }else if (monbuf->hdr.datalen != monhdr->datalen) { +/* Data with buffer reuse must not change its length */ +return -EINVAL ; } }else if (monhdr->mon_function !=MONWRITE_STOP_INTERVAL ) {if (mon_buf_count >= mon_max_bufs)
Greg Kroah-Hartman
maintainerPATCH 553/699 mac802154: remove interfaces with RCU list deletion
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yousef Alhouseen <[email protected]>
commit 539dfcf69105d8d3d4d677b71de6e5ede2e6dfa0 upstream.
Queue wake, stop, and disable paths walk local->interfaces under RCU. The bulk hardware teardown path removes entries with list_del(), so an asynchronous transmit completion can follow a poisoned list node in ieee802154_wake_queue().
Use list_del_rcu() as in the single-interface removal path. The following unregister_netdevice() waits for in-flight RCU readers before freeing the netdevice, so no separate grace-period wait is needed.
--- net/mac802154/iface.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/mac802154/iface.c +1 -1
@@ -705,7 +705,7 @@ void ieee802154_remove_interfaces(structmutex_lock (&local->iflist_mtx);list_for_each_entry_safe (sdata, tmp, &local->interfaces, list) { -list_del (&sdata->list); +list_del_rcu (&sdata->list);unregister_netdevice (sdata->dev); }
Greg Kroah-Hartman
maintainerPATCH 554/699 llc: fix SAP refcount leak in llc_ui_autobind()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuangpeng Bai <[email protected]>
commit 660667cd406648bbaffbd5c0d897c2263a852f11 upstream.
llc_ui_autobind() opens a SAP after choosing a dynamic LSAP. llc_sap_open() returns a reference owned by the caller, and llc_sap_add_socket() takes a second reference for the socket's membership in the SAP hash tables.
llc_ui_bind() drops the caller's reference after adding the socket, but llc_ui_autobind() keeps it. When the socket is closed, llc_sap_remove_socket() releases only the socket reference, leaving the SAP on llc_sap_list with sk_count == 0.
This is user-visible because repeated autobind and close cycles can consume all dynamic SAP values and make later autobinds fail with -EUSERS.
Drop the caller's reference after a successful autobind, matching llc_ui_bind()'s ownership model.
--- net/llc/af_llc.c | 1 + 1 file changed, 1 insertion(+)
net/llc/af_llc.c +1 -0
@@ -317,6 +317,7 @@ static int llc_ui_autobind(struct socket/* assign new connection to its SAP */ llc_sap_add_socket (sap, sk);sock_reset_flag (sk,SOCK_ZAPPED ); +llc_sap_put (sap); rc =0 ; out:dev_put (dev);
Greg Kroah-Hartman
maintainerPATCH 555/699 ipvs: use parsed transport offset in SCTP state lookup
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yizhou Zhao <[email protected]>
commit 2f75c0faa3361b28e36cc0512b3299e163e25789 upstream.
set_sctp_state() reads the SCTP chunk header again in order to drive the IPVS SCTP state table. For IPv6 it computes the offset with sizeof(struct ipv6hdr), while the surrounding IPVS code uses iph.len from ip_vs_fill_iph_skb(), where ipv6_find_hdr() has already skipped extension headers and found the real transport header.
This makes the state machine read from the wrong offset for IPv6 SCTP packets that carry extension headers. For example, an INIT packet with an 8-byte destination options header can be scheduled correctly by sctp_conn_schedule(), but set_sctp_state() reads the first byte of the SCTP verification tag as a DATA chunk type. The connection then moves from NONE to ESTABLISHED instead of INIT1, gets the longer established timeout, and updates the active/inactive destination counters incorrectly. This happens even though the SCTP handshake has not completed.
Use the parsed transport offset passed down from ip_vs_set_state() for the SCTP chunk-header lookup. For IPv4 and IPv6 packets without extension headers this preserves the existing offset.
--- net/netfilter/ipvs/ip_vs_proto_sctp.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-)
net/netfilter/ipvs/ip_vs_proto_sctp.c +5 -10
@@ -372,20 +372,15 @@ static const char *sctp_state_name(int sstatic inline void set_sctp_state (struct ip_vs_proto_data *pd,struct ip_vs_conn *cp, -int direction,const struct sk_buff *skb) +int direction,const struct sk_buff *skb, +unsigned int iph_len) {struct sctp_chunkhdr _sctpch, *sch;unsigned char chunk_type;int event, next_state; -int ihl, cofs; - -#ifdef CONFIG_IP_VS_IPV6 - ihl = cp->af ==AF_INET ?ip_hdrlen (skb) :sizeof (struct ipv6hdr ); -#else - ihl =ip_hdrlen (skb); -#endif +int cofs; - cofs = ihl +sizeof (struct sctphdr ); + cofs = iph_len +sizeof (struct sctphdr ); sch =skb_header_pointer (skb, cofs,sizeof (_sctpch), &_sctpch);if (sch ==NULL )return ;
@@ -472,7 +467,7 @@ sctp_state_transition(struct ip_vs_conn unsigned int iph_len) {spin_lock_bh (&cp->lock); -set_sctp_state (pd, cp, direction, skb); +set_sctp_state (pd, cp, direction, skb, iph_len);spin_unlock_bh (&cp->lock); }
Greg Kroah-Hartman
maintainerPATCH 556/699 ipvs: reset full ip_vs_seq structs in ip_vs_conn_new
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yizhou Zhao <[email protected]>
commit 2975324d164c552b028632f107b567302863b7f6 upstream.
Commit 9a05475cebdd ("ipvs: avoid kmem_cache_zalloc in ip_vs_conn_new") changed ip_vs_conn_new() to allocate an ip_vs_conn object with kmem_cache_alloc(). The function then initializes many fields explicitly, but only resets in_seq.delta and out_seq.delta in the two struct ip_vs_seq members.
That leaves init_seq and previous_delta uninitialized. This is normally harmless while the corresponding IP_VS_CONN_F_IN_SEQ or IP_VS_CONN_F_OUT_SEQ flag is clear. For connections learned from a sync message, however, ip_vs_proc_conn() preserves those flags from IP_VS_CONN_F_BACKUP_MASK and passes opt=NULL when the message omits IPVS_OPT_SEQ_DATA. In that case the new connection can be hashed with SEQ flags set but with the rest of in_seq/out_seq still containing stale slab data.
When a packet for such a connection is later handled by an IPVS application helper, vs_fix_seq() and vs_fix_ack_seq() use previous_delta and init_seq to rewrite TCP sequence numbers. A malformed sync message can therefore make forwarded packets carry stale slab bytes in their TCP seq/ack numbers, and can also corrupt the forwarded TCP flow.
Reset both struct ip_vs_seq members completely before publishing the connection. This matches the existing "reset struct ip_vs_seq" comment and keeps the sequence-adjustment gates inactive unless valid sequence data is installed later.
--- net/netfilter/ipvs/ip_vs_conn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/netfilter/ipvs/ip_vs_conn.c +2 -2
@@ -996,8 +996,8 @@ ip_vs_conn_new(const struct ip_vs_conn_p cp->app =NULL ; cp->app_data =NULL ;/* reset struct ip_vs_seq */ - cp->in_seq.delta =0 ; - cp->out_seq.delta =0 ; +memset (&cp->in_seq,0 ,sizeof (cp->in_seq)); +memset (&cp->out_seq,0 ,sizeof (cp->out_seq));atomic_inc (&ipvs->conn_count);if (flags &IP_VS_CONN_F_NO_CPORT )
Greg Kroah-Hartman
maintainerPATCH 557/699 drbd: reject data replies with an out-of-range payload size
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
commit bd910a7660d280595ef94cb6d193951d855d330f upstream.
recv_dless_read() receives a P_DATA_REPLY from a peer into the bio of an outstanding read request. The peer-supplied payload length reaches it as the signed int data_size, and two peer-controlled inputs can make it negative. With a negotiated data-integrity-alg the digest length is subtracted first, so a reply whose payload is smaller than the digest underflows data_size. With no integrity algorithm (the default) data_size is assigned from the unsigned h95/h100 wire length and drbdd() never bounds it for a payload-carrying command, so a length above INT_MAX casts it negative; this path needs no non-default feature. The bio receive loop then computes expect = min_t(int, data_size, bv_len), which is negative, and drbd_recv_all_warn(mapped, expect) receives with a size_t of SIZE_MAX into the first mapped page.
The sibling receive path read_in_block() is not affected: it uses an unsigned size and rejects it against DRBD_MAX_BIO_SIZE before receiving. Reject a data reply whose size is negative after the optional digest subtraction, covering both triggers.
Impact: a malicious or man-in-the-middle DRBD peer copies attacker-chosen bytes past a bio page in the receiver, corrupting kernel memory. A node that reads from its peer (a diskless node, or read-balancing to the peer) is exposed in the default configuration; data-integrity-alg is not required.
--- drivers/block/drbd/drbd_receiver.c | 5 +++++ 1 file changed, 5 insertions(+)
drivers/block/drbd/drbd_receiver.c +5 -0
@@ -2025,6 +2025,11 @@ static int recv_dless_read(struct drbd_p data_size -= digest_size; } +if (data_size <0 ) { +drbd_err (peer_device,"Invalid data reply size\n" ); +return -EIO ; + } +/* optimistically update recv_cnt. if receiving fails below, * we disconnect anyways, and counters will be reset. */ peer_device->device->recv_cnt += data_size>>9 ;
Greg Kroah-Hartman
maintainerPATCH 558/699 cgroup/cpuset: rebind mm mempolicy to effective_mems, not mems_allowed
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Farhad Alemi <[email protected]>
commit b983c56426383e4a06fa5970c4e33cee879b1482 upstream.
Creating a child cpuset where cpuset.mems is never set leads to a div/0 when a VMA mempolicy with MPOL_F_RELATIVE_NODES rebinds in response to a CPU hotplug event.
Reproduction steps:
1) Create a cgroup w/ cpuset controls (do not set cpuset.mems)
2) Move the task into the child cpuset
3) Create a VMA mempolicy for that task with MPOL_F_RELATIVE_NODES
4) unplug and hotplug a cpu
echo 0 > /sys/devices/system/cpu/cpu1/online
echo 1 > /sys/devices/system/cpu/cpu1/online
5) mempolicy rebind does a div/0 in mpol_relative_nodemask on the call to __nodes_fold()
The cpuset code passes (cs->mems_allowed) which is not guaranteed to have nodes to the rebind routine. Use cs->effective_mems instead, which is guaranteed to have a non-empty nodemask once we reach that code path.
--- kernel/cgroup/cpuset.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
kernel/cgroup/cpuset.c +6 -1
@@ -1768,7 +1768,12 @@ static void update_tasks_nodemask(struct migrate =is_memory_migrate (cs); -mpol_rebind_mm (mm, &cs->mems_allowed); +/* +* For v1 we can have empty effective_mems, but we cannot +* attach any tasks (see cpuset_can_attach_check()). For v2, +* effective_mems is guaranteed to not be empty. +*/ +mpol_rebind_mm (mm, &cs->effective_mems);if (migrate)cpuset_migrate_mm (mm, &cs->old_mems_allowed, &newmems);else
Greg Kroah-Hartman
maintainerPATCH 559/699 wifi: rt2x00: avoid full teardown before work setup in probe
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Runyu Xiao <[email protected]>
commit 536fb3d739d75a03cb318c0c6fe799425cfea501 upstream.
rt2x00lib_probe_dev() uses the full rt2x00lib_remove_dev() teardown for all probe failures. However, drv_data allocation and workqueue allocation can fail before intf_work, autowakeup_work and sleep_work have been initialized.
Do not enter the full remove path until the probe has reached the point where those work items are set up. Return directly for drv_data allocation failure, and use a small early cleanup path for workqueue allocation failure.
This issue was found by our static analysis tool and then confirmed by manual review of rt2x00lib_probe_dev() and rt2x00lib_remove_dev(). The early probe exits should not call a common teardown path that assumes the later work setup has already completed.
A QEMU PoC forced alloc_ordered_workqueue() to fail before the work initializers are reached. The resulting fail path entered rt2x00lib_remove_dev(), and DEBUG_OBJECTS reported invalid work drains with rt2x00lib_probe_dev() and rt2x00lib_remove_dev() in the stack.
--- drivers/net/wireless/ralink/rt2x00/rt2x00dev.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/net/wireless/ralink/rt2x00/rt2x00dev.c +10 -2
@@ -1368,7 +1368,7 @@ int rt2x00lib_probe_dev(struct rt2x00_de GFP_KERNEL);if (!rt2x00dev->drv_data) { retval = -ENOMEM ; - goto exit; +return retval; } }
@@ -1402,7 +1402,7 @@ int rt2x00lib_probe_dev(struct rt2x00_dealloc_ordered_workqueue ("%s" ,0 ,wiphy_name (rt2x00dev->hw->wiphy));if (!rt2x00dev->workqueue) { retval = -ENOMEM ; - goto exit; + goto exit_free_drv_data; }INIT_WORK (&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
@@ -1478,6 +1478,14 @@ exit:rt2x00lib_remove_dev (rt2x00dev);return retval; + +exit_free_drv_data: +clear_bit (DEVICE_STATE_PRESENT , &rt2x00dev->flags); + +kfree (rt2x00dev->drv_data); + rt2x00dev->drv_data =NULL ; + +return retval; }EXPORT_SYMBOL_GPL (rt2x00lib_probe_dev);
Greg Kroah-Hartman
maintainerPATCH 560/699 wifi: mac80211: fix memory leak in ieee80211_register_hw()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Dawei Feng <[email protected]>
commit 95fc02722edde02946d0d475221f2b2054d3d8ba upstream.
If kmemdup() fails while copying supported band structures, the error path jumps to fail_rate. This skips rate_control_deinitialize() and leaks the initialized local->rate_ctrl.
Fix this by adding a fail_band label that shares the rate-control cleanup path before falling through to the remaining teardown.
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-rc7.
An x86_64 allyesconfig build showed no new warnings. As we do not have a suitable mac80211 device/driver combination to test with, no runtime testing was able to be performed.
--- net/mac80211/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
net/mac80211/main.c +2 -1
@@ -1279,7 +1279,7 @@ int ieee80211_register_hw(struct ieee802 sband =kmemdup (sband,sizeof (*sband),GFP_KERNEL );if (!sband) { result = -ENOMEM ; - goto fail_rate; + goto fail_band; } wiphy_dbg(hw->wiphy, "copying sband (band %d) due to VHT EXT NSS BW flag\n",
@@ -1342,6 +1342,7 @@ int ieee80211_register_hw(struct ieee802#endif wiphy_unregister (local->hw.wiphy); fail_wiphy_register: + fail_band:rtnl_lock ();rate_control_deinitialize (local);ieee80211_remove_interfaces (local);
Greg Kroah-Hartman
maintainerPATCH 561/699 regulator: ltc3676: Fix incorrect IRQSTAT bit offsets
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Abhishek Ojha <[email protected]>
commit 50dce2e2f84b56d8b4b406d97a1543709e8a87f5 upstream.
The LTC3676_IRQSTAT_* bit definitions do not match the IRQSTAT (Interrupt Request Status) register layout documented in Table 15 of the LTC3676/LTC3676-1 datasheet:
bit 0 - Pushbutton Status Active
bit 1 - Hard Reset Occurred
bit 2 - PGOOD Timeout Occurred
bit 3 - Undervoltage Warning
bit 4 - Undervoltage Standby (Fault) Occurred bit 5 - Overtemperature Warning
bit 6 - Overtemperature Standby (Fault) Occurred bit 7 - Reserved
The driver instead defines these starting at bit 3, one bit higher than the datasheet specifies, which causes ltc3676_regulator_isr() to check the wrong status bits and misreport (or miss) PGOOD timeout, undervoltage and thermal warning/fault conditions.
Fix the bit offsets to match the datasheet.
--- drivers/regulator/ltc3676.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/regulator/ltc3676.c +5 -5
@@ -45,11 +45,11 @@#define LTC3676_DVBxA_REF_SELECT BIT(5)#define LTC3676_DVBxB_PGOOD_MASK BIT(5) -#define LTC3676_IRQSTAT_PGOOD_TIMEOUT BIT(3) -#define LTC3676_IRQSTAT_UNDERVOLT_WARN BIT(4) -#define LTC3676_IRQSTAT_UNDERVOLT_FAULT BIT(5) -#define LTC3676_IRQSTAT_THERMAL_WARN BIT(6) -#define LTC3676_IRQSTAT_THERMAL_FAULT BIT(7) +#define LTC3676_IRQSTAT_PGOOD_TIMEOUT BIT(2) +#define LTC3676_IRQSTAT_UNDERVOLT_WARN BIT(3) +#define LTC3676_IRQSTAT_UNDERVOLT_FAULT BIT(4) +#define LTC3676_IRQSTAT_THERMAL_WARN BIT(5) +#define LTC3676_IRQSTAT_THERMAL_FAULT BIT(6)enum ltc3676_reg {LTC3676_SW1 ,
Greg Kroah-Hartman
maintainerPATCH 562/699 Bluetooth: btrtl: validate firmware patch bounds
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Laxman Acharya Padhya <[email protected]>
commit 609c5b04a28dc1b0f3af6a7bc93055135b2d2059 upstream.
rtlbt_parse_firmware() copies patch_length - 4 bytes before appending the firmware version. A malformed firmware patch shorter than the version field can make this subtraction underflow and turn the copy into an oversized read and write during Bluetooth setup.
The existing patch_offset + patch_length check can also wrap on 32-bit architectures. Validate the patch length and range without arithmetic overflow before allocating or copying the patch.
--- drivers/bluetooth/btrtl.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/bluetooth/btrtl.c +3 -2
@@ -382,8 +382,9 @@ static int rtlbt_parse_firmware(struct h }BT_DBG ("length=%x offset=%x index %d" , patch_length, patch_offset, i); - min_size = patch_offset + patch_length; -if (btrtl_dev->fw_len < min_size) +if (patch_length <sizeof (epatch_info->fw_version) || + patch_offset > btrtl_dev->fw_len || + patch_length > btrtl_dev->fw_len - patch_offset)return -EINVAL ;/* Copy the firmware into a new buffer and write the version at
Greg Kroah-Hartman
maintainerPATCH 563/699 llc: fix SAP refcount leak when creating incoming sockets
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xuanqiang Luo <[email protected]>
commit 2c72eb6286347d05a885412fb076993bd5286b53 upstream.
llc_sap_add_socket() takes a SAP reference for each socket added to a SAP, and llc_sap_remove_socket() releases it. llc_create_incoming_sock() takes an additional SAP reference after adding the child socket.
This extra reference was balanced by an explicit llc_sap_put() in llc_ui_release() until commit 3100aa9d74db ("llc: fix SAP reference counting w.r.t. socket handling") removed that put. The corresponding hold in the accept path was left behind.
When such a child socket is removed, only the reference taken by llc_sap_add_socket() is released. The extra reference keeps the SAP alive after its last socket is removed. Remove the obsolete hold.
--- net/llc/llc_conn.c | 1 - 1 file changed, 1 deletion(-)
net/llc/llc_conn.c +0 -1
@@ -761,7 +761,6 @@ static struct sock *llc_create_incoming_ newllc->dev = dev;dev_hold (dev);llc_sap_add_socket (llc->sap, newsk); -llc_sap_hold (llc->sap); out:return newsk; }
Greg Kroah-Hartman
maintainerPATCH 564/699 macsec: fix promiscuity refcount leak in macsec_dev_open()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: James Raphael Tiovalen <[email protected]>
commit 7410d11460eb90d6c9281162ccc6a128534d897d upstream.
When a MACsec interface with IFF_PROMISC set is brought up on top of a device that has hardware offload enabled, macsec_dev_open() first calls dev_set_promiscuity(real_dev, 1) and then propagates the open to the offload device. If that propagation fails, the error path jumps to the clear_allmulti label, which only reverts allmulti and the unicast address. The promiscuity taken on the lower device is never dropped, so real_dev is left permanently stuck in promiscuous mode. Its promiscuity count can no longer be balanced from software.
Add a clear_promisc label that drops the promiscuity reference and route the two offload failure paths to it. The dev_set_promiscuity() failure itself still jumps to clear_allmulti, since on that failure the count was not incremented.
--- drivers/net/macsec.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
drivers/net/macsec.c +5 -2
@@ -3560,19 +3560,22 @@ static int macsec_dev_open(struct net_de ops =macsec_get_ops (netdev_priv (dev), &ctx);if (!ops) { err = -EOPNOTSUPP ; - goto clear_allmulti; + goto clear_promisc; } ctx.secy = &macsec->secy; err =macsec_offload (ops->mdo_dev_open, &ctx);if (err) - goto clear_allmulti; + goto clear_promisc; }if (netif_carrier_ok (real_dev))netif_carrier_on (dev);return 0 ; +clear_promisc: +if (dev->flags &IFF_PROMISC ) +dev_set_promiscuity (real_dev,-1 ); clear_allmulti:if (dev->flags &IFF_ALLMULTI )dev_set_allmulti (real_dev,-1 );
Greg Kroah-Hartman
maintainerPATCH 565/699 memstick: ms_block: reject a card that reports too many blocks
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Maoyi Xie <[email protected]>
commit 718178f524b98bc920d74bc771aed823c8b81425 upstream.
msb_ftl_initialize() computes the zone count from the card block count with no bound:
msb->zone_count = msb->block_count / MS_BLOCKS_IN_ZONE; ... for (i = 0; i < msb->zone_count; i++) msb->free_block_count[i] = MS_BLOCKS_IN_ZONE;
msb->block_count is a card value. msb_read_boot_blocks() reads number_of_blocks from the card boot page and byte swaps it. free_block_count is a fixed int[MS_MAX_ZONES]. MS_MAX_ZONES is 16, so the valid indices are 0 to 15. The init loop above indexes it by zone_count. msb_mark_block_used() and msb_mark_block_unused() index it by pba / MS_BLOCKS_IN_ZONE, for pba up to block_count - 1. A card may report up to 65535 blocks. A block_count above 8192 (MS_MAX_ZONES * MS_BLOCKS_IN_ZONE) lets the pba index reach 16. That writes past free_block_count[] and corrupts struct msb_data. A larger count runs the init loop past the end too.
A real Memory Stick has at most 16 zones. So it has at most 8192 blocks. msb_ftl_initialize() now rejects a card that reports more than MS_MAX_ZONES * MS_BLOCKS_IN_ZONE blocks.
--- drivers/memstick/core/ms_block.c | 4 ++++ 1 file changed, 4 insertions(+)
drivers/memstick/core/ms_block.c +4 -0
@@ -1333,6 +1333,10 @@ static int msb_ftl_initialize(struct msbreturn 0 ; msb->zone_count = msb->block_count /MS_BLOCKS_IN_ZONE ; +if (msb->block_count >MS_MAX_ZONES *MS_BLOCKS_IN_ZONE ) { +pr_err ("Too many blocks: %d\n" , msb->block_count); +return -EINVAL ; + } msb->logical_block_count = msb->zone_count *496 -2 ; msb->used_blocks_bitmap =bitmap_zalloc (msb->block_count,GFP_KERNEL );
Greg Kroah-Hartman
maintainerPATCH 566/699 ipvs: fix more places with wrong ipv6 transport offsets
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Anastasov <[email protected]>
commit b3fe4cbd583895987935a9bdad01c8f9d3a02310 upstream.
Sashiko reports for more incorrect IPv6 transport offsets.
The app code for TCP was assuming IPv4 network header even after the ipvsh argument was provided. This can cause problems with apps over IPv6. As for the only official app in the kernel tree (FTP) this problem is harmless because we use Netfilter to mangle the FTP ports and we do not adjust the TCP seq numbers.
Also, provide correct offset of the ICMPV6 header in ip_vs_out_icmp_v6() for correct checksum checks when the IPv6 packet has extension headers.
--- net/netfilter/ipvs/ip_vs_app.c | 10 ++++------ net/netfilter/ipvs/ip_vs_core.c | 3 +-- 2 files changed, 5 insertions(+), 8 deletions(-)
net/netfilter/ipvs/ip_vs_app.c +4 -6
@@ -362,14 +362,13 @@ static inline int app_tcp_pkt_out(struct struct ip_vs_iphdr *ipvsh) {int diff; -const unsigned int tcp_offset =ip_hdrlen (skb);struct tcphdr *th;__u32 seq; -if (skb_ensure_writable (skb, tcp_offset +sizeof (*th))) +if (skb_ensure_writable (skb, ipvsh->len +sizeof (*th)))return 0 ; - th = (struct tcphdr *)(skb_network_header (skb) + tcp_offset); + th = (struct tcphdr *)(skb_network_header (skb) + ipvsh->len);/* * Remember seq number in case this pkt gets resized
@@ -439,14 +438,13 @@ static inline int app_tcp_pkt_in(struct struct ip_vs_iphdr *ipvsh) {int diff; -const unsigned int tcp_offset =ip_hdrlen (skb);struct tcphdr *th;__u32 seq; -if (skb_ensure_writable (skb, tcp_offset +sizeof (*th))) +if (skb_ensure_writable (skb, ipvsh->len +sizeof (*th)))return 0 ; - th = (struct tcphdr *)(skb_network_header (skb) + tcp_offset); + th = (struct tcphdr *)(skb_network_header (skb) + ipvsh->len);/* * Remember seq number in case this pkt gets resized
net/netfilter/ipvs/ip_vs_core.c +1 -2
@@ -1053,8 +1053,7 @@ static int ip_vs_out_icmp_v6(struct netn snet.in6 = ciph.saddr.in6; offset = ciph.len;return handle_response_icmp (AF_INET6 , skb, &snet, ciph.protocol, cp, - pp, offset,sizeof (struct ipv6hdr ), - hooknum); + pp, offset, ipvsh->len, hooknum); }#endif
Greg Kroah-Hartman
maintainerPATCH 567/699 reset: imx7: Correct polarity of MIPI CSI resets on i.MX8MQ
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Robby Cai <[email protected]>
commit 71827776667f4e4677a4fa806bcfb24d4b8dd9d7 upstream.
On i.MX8MQ, the MIPI CSI reset lines are active-low and not self-clearing. Writing '0' asserts reset and it remains asserted until explicitly deasserted by software.
This driver previously treated the MIPI CSI reset signals as active-high, which led to incorrect reset assert/deassert sequencing. This issue was exposed by commit 6d79bb8fd2aa ("media: imx8mq-mipi-csi2: Explicitly release reset").
Fix this by reflecting the correct reset polarity and ensuring proper reset handling.
--- drivers/reset/reset-imx7.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/reset/reset-imx7.c +6 -0
@@ -236,6 +236,12 @@ static int imx8mq_reset_set(struct resetcase IMX8MQ_RESET_PCIE_CTRL_APPS_EN :case IMX8MQ_RESET_PCIE2_CTRL_APPS_EN : +case IMX8MQ_RESET_MIPI_CSI1_CORE_RESET : +case IMX8MQ_RESET_MIPI_CSI1_PHY_REF_RESET : +case IMX8MQ_RESET_MIPI_CSI1_ESC_RESET : +case IMX8MQ_RESET_MIPI_CSI2_CORE_RESET : +case IMX8MQ_RESET_MIPI_CSI2_PHY_REF_RESET : +case IMX8MQ_RESET_MIPI_CSI2_ESC_RESET :case IMX8MQ_RESET_MIPI_DSI_PCLK_RESET_N :case IMX8MQ_RESET_MIPI_DSI_ESC_RESET_N :case IMX8MQ_RESET_MIPI_DSI_DPI_RESET_N :
Greg Kroah-Hartman
maintainerPATCH 568/699 reset: sunxi: fix memory region leak on ioremap failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhao Dongdong <[email protected]>
commit 1a8c89f8c112c75e84ff9a140f969e372aed0c9a upstream.
In sunxi_reset_init(), when ioremap() fails, the memory region obtained via request_mem_region() is not released, leading to a resource leak.
Add an err_mem_region label to properly release the memory region before freeing the data structure.
--- drivers/reset/reset-sunxi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/reset/reset-sunxi.c +3 -1
@@ -44,7 +44,7 @@ static int sunxi_reset_init(struct devic data->membase =ioremap (res.start, size);if (!data->membase) { ret = -ENOMEM ; - goto err_alloc; + goto err_mem_region; }spin_lock_init (&data->lock);
@@ -57,6 +57,8 @@ static int sunxi_reset_init(struct devicreturn reset_controller_register (&data->rcdev); +err_mem_region: +release_mem_region (res.start, size); err_alloc:kfree (data);return ret;
Greg Kroah-Hartman
maintainerPATCH 569/699 powerpc/spufs: fix out-of-bounds access in spufs_mem_mmap_access()
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Junrui Luo <[email protected]>
commit 47b87f469a35b5ffc81c16eee6b13a9b6c8d55c6 upstream.
spufs_mem_mmap_access() computes the local store offset as address - vma->vm_start, but bounds-checks it against vma->vm_end instead of the local store size. On 64-bit, offset is always well below vma->vm_end, so the clamp never fires and len stays unbounded against the LS_SIZE buffer returned by ctx->ops->get_ls().
Reject offsets at or beyond LS_SIZE and clamp len to the remaining space, mirroring the guard already used by spufs_mem_mmap_fault() and spufs_ps_fault().
--- arch/powerpc/platforms/cell/spufs/file.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
arch/powerpc/platforms/cell/spufs/file.c +4 -2
@@ -268,10 +268,12 @@ static int spufs_mem_mmap_access(structif (write && !(vma->vm_flags &VM_WRITE ))return -EACCES ; +if (offset >=LS_SIZE ) +return -EFAULT ;if (spu_acquire (ctx))return -EINTR ; -if ((offset + len) > vma->vm_end) - len = vma->vm_end - offset; +if ((offset + len) >LS_SIZE ) + len =LS_SIZE - offset; local_store = ctx->ops->get_ls (ctx);if (write)memcpy_toio (local_store + offset, buf, len);
Greg Kroah-Hartman
maintainerPATCH 570/699 wifi: mac80211: free ack status frame on TX header build failure
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhiling Zou <[email protected]>
commit 2c51457d930f723e5f2903af90f5847f7df53f42 upstream.
ieee80211_build_hdr() stores an ACK status frame before it has finished all validation and header construction. If a later error path is taken, the transmit skb is freed but the stored ACK status frame remains in local->ack_status_frames.
This can happen for control port frames when the requested MLO link ID does not match the link selected for a non-MLO station. Repeated failures can fill the ACK status IDR and leave pending ACK frames until hardware teardown.
Remove any stored ACK status frame before returning an error after it has been inserted into the IDR.
--- net/mac80211/tx.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-)
net/mac80211/tx.c +16 -1
@@ -2516,6 +2516,18 @@ static u16 ieee80211_store_ack_skb(strucreturn info_id; } +static void ieee80211_remove_ack_skb (struct ieee80211_local *local,u16 info_id) +{ +struct sk_buff *ack_skb; +unsigned long flags; + +spin_lock_irqsave (&local->ack_status_lock, flags); + ack_skb =idr_remove (&local->ack_status_frames, info_id); +spin_unlock_irqrestore (&local->ack_status_lock, flags); + +kfree_skb (ack_skb); +} +/** * ieee80211_build_hdr - build 802.11 header in the given frame * @sdata: virtual interface to build the header for
@@ -2875,7 +2887,8 @@ static struct sk_buff *ieee80211_build_hif (ieee80211_skb_resize (sdata, skb, head_need,ENCRYPT_DATA )) {ieee80211_free_txskb (&local->hw, skb); skb =NULL ; -return ERR_PTR (-ENOMEM ); + ret = -ENOMEM ; + goto free; } }
@@ -2912,6 +2925,8 @@ static struct sk_buff *ieee80211_build_hreturn skb; free: +if (info_id) +ieee80211_remove_ack_skb (local, info_id);kfree_skb (skb);return ERR_PTR (ret); }
Greg Kroah-Hartman
maintainerPATCH 571/699 wifi: mwifiex: fix permanently busy scans after multiple roam iterations
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rafael Beims <[email protected]>
commit d78a407bad6f500884a8606aea1a5a9207be4030 upstream.
In order for the firmware to sleep, the driver has to confirm a previously received sleep request. The normal sequence of evets goes like this:EVENT_SLEEP -> adapter->ps_state = PS_STATE_PRE_SLEEP -> sleep-confirm -> SLEEP -> EVENT_AWAKE -> AWAKE.
Before sending the sleep-confirm command, the driver must make sure there are no commands either running or waiting to be completed.
mwifiex_ret_802_11_associate() unconditionally sets ps_state = PS_STATE_AWAKE when it processes the association command response, outside of the normal powersave management flow. If EVENT_SLEEP arrives while the association command is in flight, ps_state is PRE_SLEEP when the association command response is parsed, and the forced AWAKE overwrites it. The deferred sleep-confirm is never sent.
A subsequent scan_start command is correctly acknowledged, but the firmware doesn't generate scan_result events. The scan request never finishes, and additional requests from userspace fail with -EBUSY.
After testing on both IW412 and W8997, I could only trigger the bug on the IW412 and observed the firmwares behave differently. On the IW412 the firmware still sends EVENT_SLEEP while the authentication / association process is ongoing. A W8997 under the same conditions seems to suppress power-save for the duration of the association, so PRE_SLEEP never coincided with the association response even after extended periods of testing using the loops described below (>12hours).
On the IW412, the delay between commands that triggers an EVENT_SLEEP was empirically determined to be ~20ms. This delay can naturally occur when the driver is outputting debugging information (debug_mask = 0x00000037), in which situation the busy scans issue is repeatable while running "test 1)" as described below. If the delay between commands is less than ~20ms, the firmware stays awake and the issue was not reproducible running the same test.
The host_mlme=false path also behaves differently. In this case, the entire authentication / association transaction is executed by one command (HostCmd_CMD_802_11_ASSOCIATE), and the firmware doesn't emit EVENT_SLEEP while the command is running.
Remove the assignment so the ps_state is only manipulated in the paths that are related to powersave event handling and on the main workqueue for correct sleep confirmation.
The following loop tests were performed (with debugging output enabled):
1) force roaming between two AP's, one 5GHz and one 2.4GHz, same SSID. Use wpa_cli to trigger the roaming behavior, sleep 2s between iterations.
2) force a disconnection to AP 1 and a connection to AP 2, test scan. Use wpa_cli to trigger the connection changes, sleep 2s between iterations.
Each test ran in each device for at least 3 hours.
--- drivers/net/wireless/marvell/mwifiex/join.c | 1 - 1 file changed, 1 deletion(-)
drivers/net/wireless/marvell/mwifiex/join.c +0 -1
@@ -702,7 +702,6 @@ int mwifiex_ret_802_11_associate(struct/* Send a Media Connected event, according to the Spec */ priv->media_connected = true; - priv->adapter->ps_state =PS_STATE_AWAKE ; priv->adapter->pps_uapsd_mode = false; priv->adapter->tx_lock_flag = false;
Greg Kroah-Hartman
maintainerPATCH 572/699 mtd: onenand: samsung: report DMA completion timeouts
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
commit d03a19bd6c7f86b99ca8fb61a6ec2345cee1d9d6 upstream.
The S5PC110 OneNAND DMA helpers have bounded waits for transfer completion. The polling helper falls out of its timeout loop and returns success, and the IRQ helper ignores wait_for_completion_timeout().
Return -ETIMEDOUT when the DMA transfer-done bit or completion does not arrive before the timeout so callers can treat the buffer transfer as failed.
--- drivers/mtd/nand/onenand/onenand_samsung.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/mtd/nand/onenand/onenand_samsung.c +6 -1
@@ -553,6 +553,9 @@ static int s5pc110_dma_poll(dma_addr_t d }while (!(status &S5PC110_DMA_TRANS_STATUS_TD ) &&time_before (jiffies, timeout)); +if (!(status &S5PC110_DMA_TRANS_STATUS_TD )) +return -ETIMEDOUT ; +writel (S5PC110_DMA_TRANS_CMD_TDC , base +S5PC110_DMA_TRANS_CMD );return 0 ;
@@ -607,7 +610,9 @@ static int s5pc110_dma_irq(dma_addr_t dswritel (S5PC110_DMA_TRANS_CMD_TR , base +S5PC110_DMA_TRANS_CMD ); -wait_for_completion_timeout (&onenand->complete,msecs_to_jiffies (20 )); +if (!wait_for_completion_timeout (&onenand->complete, +msecs_to_jiffies (20 ))) +return -ETIMEDOUT ;return 0 ; }
Greg Kroah-Hartman
maintainerPATCH 573/699 mmc: vub300: defer reset until cmd_mutex is unlocked
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Runyu Xiao <[email protected]>
commit ee5fb641c4ccac8406c668d3e947eb20ce44f233 upstream.
vub300_cmndwork_thread() holds cmd_mutex while it sends a command and waits for the command response. If the response wait times out, __vub300_command_response() kills the command URBs and then synchronously resets the USB device through usb_reset_device().
That reset path re-enters the driver through vub300_pre_reset(), which also takes cmd_mutex. The worker therefore tries to acquire the same mutex recursively while it is still holding it from the command path.
This issue was found by our static analysis tool and then manually reviewed against the current tree.
The grounded PoC kept the real worker and timeout/reset carrier:
vub300_cmndwork_thread()
__vub300_command_response()
usb_lock_device_for_reset()
usb_reset_device()
vub300_pre_reset()
Lockdep reported the same-task recursive acquisition on cmd_mutex:
WARNING: possible recursive locking detected
... (&test_vub300.cmd_mutex) ... at: usb_reset_device... [vuln_msv] ... (&test_vub300.cmd_mutex) ... at: vub300_cmndwork_thread+0x12/0x20 [vuln_msv]
Workqueue: vub300_cmd_wq vub300_cmndwork_thread [vuln_msv] *** DEADLOCK ***
Return a flag from __vub300_command_response() when the timeout path needs a device reset, then perform the reset after vub300_cmndwork_thread() has cleared the in-flight command state and dropped cmd_mutex. The reset is still attempted before mmc_request_done(), preserving the existing request completion ordering while avoiding the recursive lock.
--- drivers/mmc/host/vub300.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-)
drivers/mmc/host/vub300.c +17 -9
@@ -1587,7 +1587,7 @@ static int __command_write_data(struct vreturn linear_length; } -static void __vub300_command_response (struct vub300_mmc_host *vub300, +static bool __vub300_command_response (struct vub300_mmc_host *vub300,struct mmc_command *cmd,struct mmc_data *data,int data_length) {
@@ -1599,17 +1599,11 @@ static void __vub300_command_response(st msecs_to_jiffies(msec_timeout));if (respretval ==0 ) {/* TIMED OUT */ /* we don't know which of "out" and "res" if any failed */ -int result; vub300->usb_timed_out =1 ;usb_kill_urb (vub300->command_out_urb);usb_kill_urb (vub300->command_res_urb); cmd->error = -ETIMEDOUT ; - result =usb_lock_device_for_reset (vub300->udev, - vub300->interface); -if (result ==0 ) { - result =usb_reset_device (vub300->udev); -usb_unlock_device (vub300->udev); - } +return true; }else if (respretval <0 ) {/* we don't know which of "out" and "res" if any failed */ usb_kill_urb (vub300->command_out_urb);
@@ -1705,6 +1699,8 @@ static void __vub300_command_response(st }else { cmd->error = -EINVAL ; } + +return false; } static void construct_request_response(struct vub300_mmc_host *vub300,
@@ -1750,6 +1746,7 @@ static void vub300_cmndwork_thread(strucstruct mmc_request *req = vub300->req;struct mmc_command *cmd = vub300->cmd;struct mmc_data *data = vub300->data; +bool reset_device;int data_length;mutex_lock (&vub300->cmd_mutex);init_completion (&vub300->command_complete);
@@ -1772,7 +1769,8 @@ static void vub300_cmndwork_thread(struc data_length =__command_read_data (vub300, cmd, data); else data_length =__command_write_data (vub300, cmd, data); -__vub300_command_response (vub300, cmd, data, data_length); + reset_device =__vub300_command_response (vub300, cmd, + data, data_length); vub300->req =NULL ; vub300->cmd =NULL ; vub300->data =NULL ;
@@ -1780,6 +1778,16 @@ static void vub300_cmndwork_thread(strucif (cmd->error == -ENOMEDIUM )check_vub300_port_status (vub300);mutex_unlock (&vub300->cmd_mutex); +if (reset_device) { +int result; + + result =usb_lock_device_for_reset (vub300->udev, + vub300->interface); +if (result ==0 ) { + result =usb_reset_device (vub300->udev); +usb_unlock_device (vub300->udev); + } + }mmc_request_done (vub300->mmc, req);kref_put (&vub300->kref, vub300_delete);return ;
Greg Kroah-Hartman
maintainerPATCH 574/699 mtd: rawnand: fsl_ifc: return errors for failed page reads
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
commit f9a13e05a327080c3a1c8165adf9e678fb68fef2 upstream.
fsl_ifc_run_command() logs controller timeout and other non-OPC completion states in ctrl->nand_stat. fsl_ifc_read_page() then only increments the ECC failure counter for non-OPC status and still returns max_bitflips, which can be zero.
Return -ETIMEDOUT when the command did not complete at all and -EIO for other non-OPC read completions so the NAND core does not treat a failed page read as a clean page.
--- drivers/mtd/nand/raw/fsl_ifc_nand.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-)
drivers/mtd/nand/raw/fsl_ifc_nand.c +8 -1
@@ -683,8 +683,15 @@ static int fsl_ifc_read_page(struct nandreturn check_erased_page (chip, buf); } -if (ctrl->nand_stat !=IFC_NAND_EVTER_STAT_OPC ) +if (!ctrl->nand_stat) { mtd->ecc_stats.failed++; +return -ETIMEDOUT ; + } + +if (ctrl->nand_stat !=IFC_NAND_EVTER_STAT_OPC ) { + mtd->ecc_stats.failed++; +return -EIO ; + }return nctrl->max_bitflips; }
Greg Kroah-Hartman
maintainerPATCH 575/699 mtd: rawnand: lpc32xx_mlc: fail DMA transfers on timeout
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
commit dbf590b662695b16fbf5917ef129697be4410ea9 upstream.
lpc32xx_xmit_dma() starts a DMA transfer and waits up to one second for its completion, but it ignores the wait result and returns success after unmapping the buffer.
A timed out read can therefore return success with incomplete data, and a timed out write can continue the NAND operation without proof that the DMA payload reached the controller.
Terminate the DMA channel on timeout, unmap the scatterlist through the existing cleanup path, and return -ETIMEDOUT to the NAND read/write callers. Initialize the shared cleanup-path result before using it for dmaengine_prep_slave_sg() failures.
--- drivers/mtd/nand/raw/lpc32xx_mlc.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/mtd/nand/raw/lpc32xx_mlc.c +10 -2
@@ -397,6 +397,7 @@ static int lpc32xx_xmit_dma(struct mtd_istruct lpc32xx_nand_host *host =nand_get_controller_data (chip);struct dma_async_tx_descriptor *desc;int flags =DMA_CTRL_ACK |DMA_PREP_INTERRUPT ; +unsigned long time_left;int res;sg_init_one (&host->sgl, mem, len);
@@ -411,6 +412,7 @@ static int lpc32xx_xmit_dma(struct mtd_i flags);if (!desc) {dev_err (mtd->dev.parent,"Failed to prepare slave sg\n" ); + res = -ENXIO ; goto out1; }
@@ -421,7 +423,13 @@ static int lpc32xx_xmit_dma(struct mtd_idmaengine_submit (desc);dma_async_issue_pending (host->dma_chan); -wait_for_completion_timeout (&host->comp_dma,msecs_to_jiffies (1000 )); + time_left =wait_for_completion_timeout (&host->comp_dma, +msecs_to_jiffies (1000 )); +if (!time_left) { +dmaengine_terminate_sync (host->dma_chan); + res = -ETIMEDOUT ; + goto out1; + }dma_unmap_sg (host->dma_chan->device->dev, &host->sgl,1 ,DMA_BIDIRECTIONAL );
@@ -429,7 +437,7 @@ static int lpc32xx_xmit_dma(struct mtd_i out1:dma_unmap_sg (host->dma_chan->device->dev, &host->sgl,1 ,DMA_BIDIRECTIONAL ); -return -ENXIO ; +return res; } static int lpc32xx_read_page(struct nand_chip *chip, uint8_t *buf,
Greg Kroah-Hartman
maintainerPATCH 576/699 mtd: rawnand: lpc32xx_slc: fail DMA transfer on completion timeout
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
commit 17a8ce84964f243c8f89dc7353ac7e8d3137bc74 upstream.
lpc32xx_xmit_dma() waits for the DMA completion callback but ignores wait_for_completion_timeout(). A timed out DMA transfer is therefore unmapped and reported as successful to the NAND read/write path.
Return -ETIMEDOUT when the completion wait expires. Terminate the DMA channel before unmapping the scatterlist so the timed out transfer cannot continue to access the buffer after the error is returned.
--- drivers/mtd/nand/raw/lpc32xx_slc.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-)
drivers/mtd/nand/raw/lpc32xx_slc.c +10 -2
@@ -432,6 +432,7 @@ static int lpc32xx_xmit_dma(struct mtd_istruct dma_async_tx_descriptor *desc;int flags =DMA_CTRL_ACK |DMA_PREP_INTERRUPT ;int res; +unsigned long time_left; host->dma_slave_config.direction = dir; host->dma_slave_config.src_addr = dma;
@@ -469,12 +470,19 @@ static int lpc32xx_xmit_dma(struct mtd_idmaengine_submit (desc);dma_async_issue_pending (host->dma_chan); -wait_for_completion_timeout (&host->comp,msecs_to_jiffies (1000 )); + time_left =wait_for_completion_timeout (&host->comp, +msecs_to_jiffies (1000 )); +if (!time_left) { +dmaengine_terminate_sync (host->dma_chan); + res = -ETIMEDOUT ; + }else { + res =0 ; + }dma_unmap_sg (host->dma_chan->device->dev, &host->sgl,1 ,DMA_BIDIRECTIONAL ); -return 0 ; +return res; out1:dma_unmap_sg (host->dma_chan->device->dev, &host->sgl,1 ,DMA_BIDIRECTIONAL );
Greg Kroah-Hartman
maintainerPATCH 577/699 crypto: amcc - fix incorrect kernel-doc comment syntax in files
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aditya Srivastava <[email protected]>
commit 73f04d3d800f3c8058bb00447e3e1c4cdc85a2b0 upstream.
The opening comment mark '/**' is used for highlighting the beginning of kernel-doc comments.
There are certain files in drivers/crypto/amcc, which follow this syntax, but the content inside does not comply with kernel-doc.
Such lines were probably not meant for kernel-doc parsing, but are parsed due to the presence of kernel-doc like comment syntax(i.e, '/**'), which causes unexpected warnings from kernel-doc.
E.g., presence of kernel-doc like comment in drivers/crypto/amcc/crypto4xx_alg.c at header, and some other lines, causes these warnings by kernel-doc:
"warning: expecting prototype for AMCC SoC PPC4xx Crypto Driver(). Prototype was for set_dynamic_sa_command_0() instead" "warning: Function parameter or member 'dir' not described in 'set_dynamic_sa_command_0'"
etc..
Provide a simple fix by replacing such occurrences with general comment format, i.e. '/*', to prevent kernel-doc from parsing it.
--- drivers/crypto/amcc/crypto4xx_alg.c | 12 ++++++------ drivers/crypto/amcc/crypto4xx_core.c | 18 +++++++++--------- drivers/crypto/amcc/crypto4xx_core.h | 4 ++-- drivers/crypto/amcc/crypto4xx_reg_def.h | 8 ++++---- drivers/crypto/amcc/crypto4xx_sa.h | 18 +++++++++--------- drivers/crypto/amcc/crypto4xx_trng.h | 2 +- 6 files changed, 31 insertions(+), 31 deletions(-)
drivers/crypto/amcc/crypto4xx_alg.c +6 -6
@@ -1,5 +1,5 @@// SPDX-License-Identifier: GPL-2.0-or-later -/** +/* * AMCC SoC PPC4xx Crypto Driver * * Copyright (c) 2008 Applied Micro Circuits Corporation.
@@ -115,7 +115,7 @@ int crypto4xx_decrypt_iv_block(struct skreturn crypto4xx_crypt (req,AES_IV_SIZE , true, true); } -/** +/* * AES Functions */ static int crypto4xx_setkey_aes(struct crypto_skcipher *cipher,
@@ -374,7 +374,7 @@ static int crypto4xx_aead_setup_fallbackreturn crypto_aead_setkey (ctx->sw_cipher.aead, key, keylen); } -/** +/* * AES-CCM Functions */
@@ -489,7 +489,7 @@ int crypto4xx_setauthsize_aead(struct crreturn crypto_aead_setauthsize (ctx->sw_cipher.aead, authsize); } -/** +/* * AES-GCM Functions */
@@ -617,7 +617,7 @@ int crypto4xx_decrypt_aes_gcm(struct aeareturn crypto4xx_crypt_aes_gcm (req, true); } -/** +/* * HASH SHA1 Functions */ static int crypto4xx_hash_alg_init(struct crypto_tfm *tfm,
@@ -711,7 +711,7 @@ int crypto4xx_hash_digest(struct ahash_r ctx->sa_len, 0, NULL); } -/** +/* * SHA1 Algorithm */ int crypto4xx_sha1_alg_init (struct crypto_tfm *tfm)
drivers/crypto/amcc/crypto4xx_core.c +9 -9
@@ -1,5 +1,5 @@// SPDX-License-Identifier: GPL-2.0-or-later -/** +/* * AMCC SoC PPC4xx Crypto Driver * * Copyright (c) 2008 Applied Micro Circuits Corporation.
@@ -44,7 +44,7 @@#define PPC4XX_SEC_VERSION_STR "0.5" -/** +/* * PPC4xx Crypto Engine Initialization Routine */ static void crypto4xx_hw_init (struct crypto4xx_device *dev)
@@ -159,7 +159,7 @@ void crypto4xx_free_sa(struct crypto4xx_ ctx->sa_len =0 ; } -/** +/* * alloc memory for the gather ring * no need to alloc buf for the ring * gdr_tail, gdr_head and gdr_count are initialized by this function
@@ -268,7 +268,7 @@ static u32 crypto4xx_put_pd_to_pdr(strucreturn tail; } -/** +/* * alloc memory for the gather ring * no need to alloc buf for the ring * gdr_tail, gdr_head and gdr_count are initialized by this function
@@ -346,7 +346,7 @@ static inline struct ce_gd *crypto4xx_gereturn &dev->gdr[idx]; } -/** +/* * alloc memory for the scatter ring * need to alloc buf for the ring * sdr_tail, sdr_head and sdr_count are initialized by this function
@@ -928,7 +928,7 @@ int crypto4xx_build_pd(struct crypto_asyreturn is_busy ? -EBUSY : -EINPROGRESS ; } -/** +/* * Algorithm Registration Functions */ static void crypto4xx_ctx_init(struct crypto4xx_alg *amcc_alg,
@@ -1095,7 +1095,7 @@ static void crypto4xx_bh_tasklet_cb(unsi }while (head != tail); } -/** +/* * Top Half of isr. */ static inline irqreturn_t crypto4xx_interrupt_handler(int irq, void *data,
@@ -1184,7 +1184,7 @@ static int crypto4xx_prng_seed(struct crreturn 0 ; } -/** +/* * Supported Crypto Algorithms */ static struct crypto4xx_alg_common crypto4xx_alg[] = {
@@ -1367,7 +1367,7 @@ static struct crypto4xx_alg_common crypt } }, }; -/** +/* * Module Initialization Routine */ static int crypto4xx_probe (struct platform_device *ofdev)
drivers/crypto/amcc/crypto4xx_core.h +2 -2
@@ -1,5 +1,5 @@/* SPDX-License-Identifier: GPL-2.0-or-later */ -/** +/* * AMCC SoC PPC4xx Crypto Driver * * Copyright (c) 2008 Applied Micro Circuits Corporation.
@@ -188,7 +188,7 @@ int crypto4xx_hash_final(struct ahash_reint crypto4xx_hash_update (struct ahash_request *req);int crypto4xx_hash_init (struct ahash_request *req); -/** +/* * Note: Only use this function to copy items that is word aligned. */ static inline void crypto4xx_memcpy_swab32(u32 *dst, const void *buf,
drivers/crypto/amcc/crypto4xx_reg_def.h +4 -4
@@ -1,5 +1,5 @@/* SPDX-License-Identifier: GPL-2.0-or-later */ -/** +/* * AMCC SoC PPC4xx Crypto Driver * * Copyright (c) 2008 Applied Micro Circuits Corporation.
@@ -104,7 +104,7 @@#define CRYPTO4XX_PRNG_LFSR_L 0x00070030#define CRYPTO4XX_PRNG_LFSR_H 0x00070034 -/** +/* * Initialize CRYPTO ENGINE registers, and memory bases. */ #define PPC4XX_PDR_POLL 0x3ff
@@ -123,7 +123,7 @@#define PPC4XX_INT_TIMEOUT_CNT 0#define PPC4XX_INT_TIMEOUT_CNT_REVB 0x3FF#define PPC4XX_INT_CFG 1 -/** +/* * all follow define are ad hoc */ #define PPC4XX_RING_RETRY 100
@@ -131,7 +131,7 @@#define PPC4XX_SDR_SIZE PPC4XX_NUM_SD#define PPC4XX_GDR_SIZE PPC4XX_NUM_GD -/** +/* * Generic Security Association (SA) with all possible fields. These will * never likely used except for reference purpose. These structure format * can be not changed as the hardware expects them to be layout as defined.
drivers/crypto/amcc/crypto4xx_sa.h +9 -9
@@ -1,5 +1,5 @@/* SPDX-License-Identifier: GPL-2.0-or-later */ -/** +/* * AMCC SoC PPC4xx Crypto Driver * * Copyright (c) 2008 Applied Micro Circuits Corporation.
@@ -14,7 +14,7 @@#define AES_IV_SIZE 16 -/** +/* * Contents of Dynamic Security Association (SA) with all possible fields */ union dynamic_sa_contents {
@@ -122,7 +122,7 @@ union sa_command_0 {#define SA_AES_KEY_LEN_256 4#define SA_REV2 1 -/** +/* * The follow defines bits sa_command_1 * In Basic hash mode this bit define simple hash or hmac. * In IPsec mode, this bit define muting control.
@@ -172,7 +172,7 @@ struct dynamic_sa_ctl {union sa_command_1 sa_command_1; } __attribute__((packed)); -/** +/* * State Record for Security Association (SA) */ struct sa_state_record {
@@ -184,7 +184,7 @@ struct sa_state_record { }; } __attribute__((packed)); -/** +/* * Security Association (SA) for AES128 * */
@@ -213,7 +213,7 @@ struct dynamic_sa_aes192 {#define SA_AES192_LEN (sizeof(struct dynamic_sa_aes192)/4)#define SA_AES192_CONTENTS 0x3e000062 -/** +/* * Security Association (SA) for AES256 */ struct dynamic_sa_aes256 {
@@ -228,7 +228,7 @@ struct dynamic_sa_aes256 {#define SA_AES256_CONTENTS 0x3e000082#define SA_AES_CONTENTS 0x3e000002 -/** +/* * Security Association (SA) for AES128 CCM */ struct dynamic_sa_aes128_ccm {
@@ -242,7 +242,7 @@ struct dynamic_sa_aes128_ccm {#define SA_AES128_CCM_CONTENTS 0x3e000042#define SA_AES_CCM_CONTENTS 0x3e000002 -/** +/* * Security Association (SA) for AES128_GCM */ struct dynamic_sa_aes128_gcm {
@@ -258,7 +258,7 @@ struct dynamic_sa_aes128_gcm {#define SA_AES128_GCM_CONTENTS 0x3e000442#define SA_AES_GCM_CONTENTS 0x3e000402 -/** +/* * Security Association (SA) for HASH160: HMAC-SHA1 */ struct dynamic_sa_hash160 {
drivers/crypto/amcc/crypto4xx_trng.h +1 -1
@@ -1,5 +1,5 @@/* SPDX-License-Identifier: GPL-2.0-or-later */ -/** +/* * AMCC SoC PPC4xx Crypto Driver * * Copyright (c) 2008 Applied Micro Circuits Corporation.
Greg Kroah-Hartman
maintainerPATCH 578/699 crypto: crypto4xx - Remove ahash-related code
In reply to Greg Kroah-Hartman5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Herbert Xu <[email protected]>
commit 97855e7f1ccf4917f305baab199edb9f2595ff5b upstream.
The hash implementation in crypto4xx has been disabled since 2009. As nobody has tried to fix this remove all the dead code.
--- drivers/crypto/amcc/crypto4xx_alg.c | 106 ----------------------------------- drivers/crypto/amcc/crypto4xx_core.c | 43 -------------- drivers/crypto/amcc/crypto4xx_core.h | 7 -- 3 files changed, 1 insertion(+), 155 deletions(-)
drivers/crypto/amcc/crypto4xx_alg.c +0 -106
@@ -12,9 +12,6 @@#include <linux/interrupt.h> #include <linux/spinlock_types.h> #include <linux/scatterlist.h> -#include <linux/crypto.h> -#include <linux/hash.h> -#include <crypto/internal/hash.h> #include <linux/dma-mapping.h> #include <crypto/algapi.h> #include <crypto/aead.h>
@@ -616,106 +613,3 @@ int crypto4xx_decrypt_aes_gcm(struct aea {return crypto4xx_crypt_aes_gcm (req, true); } - -/* -* HASH SHA1 Functions -*/ -static int crypto4xx_hash_alg_init (struct crypto_tfm *tfm, -unsigned int sa_len, -unsigned char ha, -unsigned char hm) -{ -struct crypto_alg *alg = tfm->__crt_alg; -struct crypto4xx_alg *my_alg; -struct crypto4xx_ctx *ctx =crypto_tfm_ctx (tfm); -struct dynamic_sa_hash160 *sa; -int rc; - - my_alg = container_of(__crypto_ahash_alg(alg), struct crypto4xx_alg, - alg.u.hash); - ctx->dev = my_alg->dev; - -/* Create SA */ -if (ctx->sa_in || ctx->sa_out) -crypto4xx_free_sa (ctx); - - rc =crypto4xx_alloc_sa (ctx, sa_len); -if (rc) -return rc; - -crypto_ahash_set_reqsize (__crypto_ahash_cast (tfm), -sizeof (struct crypto4xx_ctx )); - sa = (struct dynamic_sa_hash160 *)ctx->sa_in; -set_dynamic_sa_command_0 (&sa->ctrl,SA_SAVE_HASH ,SA_NOT_SAVE_IV , -SA_NOT_LOAD_HASH ,SA_LOAD_IV_FROM_SA , -SA_NO_HEADER_PROC , ha,SA_CIPHER_ALG_NULL , -SA_PAD_TYPE_ZERO ,SA_OP_GROUP_BASIC , -SA_OPCODE_HASH ,DIR_INBOUND ); -set_dynamic_sa_command_1 (&sa->ctrl,0 ,SA_HASH_MODE_HASH , -CRYPTO_FEEDBACK_MODE_NO_FB ,SA_EXTENDED_SN_OFF , -SA_SEQ_MASK_OFF ,SA_MC_ENABLE , -SA_NOT_COPY_PAD ,SA_NOT_COPY_PAYLOAD , -SA_NOT_COPY_HDR ); -/* Need to zero hash digest in SA */ -memset (sa->inner_digest,0 ,sizeof (sa->inner_digest)); -memset (sa->outer_digest,0 ,sizeof (sa->outer_digest)); - -return 0 ; -} - -int crypto4xx_hash_init (struct ahash_request *req) -{ -struct crypto4xx_ctx *ctx =crypto_tfm_ctx (req->base.tfm); -int ds; -struct dynamic_sa_ctl *sa; - - sa = ctx->sa_in; - ds =crypto_ahash_digestsize ( -__crypto_ahash_cast (req->base.tfm)); - sa->sa_command_0.bf.digest_len = ds >>2 ; - sa->sa_command_0.bf.load_hash_state =SA_LOAD_HASH_FROM_SA ; - -return 0 ; -} - -int crypto4xx_hash_update (struct ahash_request *req) -{ -struct crypto_ahash *ahash =crypto_ahash_reqtfm (req); -struct crypto4xx_ctx *ctx =crypto_tfm_ctx (req->base.tfm); -struct scatterlist dst; -unsigned int ds =crypto_ahash_digestsize (ahash); - -sg_init_one (&dst, req->result, ds); - -return crypto4xx_build_pd (&req->base, ctx, req->src, &dst, - req->nbytes,NULL ,0 , ctx->sa_in, - ctx->sa_len,0 ,NULL ); -} - -int crypto4xx_hash_final (struct ahash_request *req) -{ -return 0 ; -} - -int crypto4xx_hash_digest (struct ahash_request *req) -{ -struct crypto_ahash *ahash =crypto_ahash_reqtfm (req); -struct crypto4xx_ctx *ctx =crypto_tfm_ctx (req->base.tfm); -struct scatterlist dst; -unsigned int ds =crypto_ahash_digestsize (ahash); - -sg_init_one (&dst, req->result, ds); - -return crypto4xx_build_pd (&req->base, ctx, req->src, &dst, - req->nbytes,NULL ,0 , ctx->sa_in, - ctx->sa_len,0 ,NULL ); -} - -/* -* SHA1 Algorithm -*/ -int crypto4xx_sha1_alg_init (struct crypto_tfm *tfm) -{ -return crypto4xx_hash_alg_init (tfm,SA_HASH160_LEN ,SA_HASH_ALG_SHA1 , -SA_HASH_MODE_HASH ); -}
drivers/crypto/amcc/crypto4xx_core.c +1 -42
79 lines not on this page · raw message
drivers/crypto/amcc/crypto4xx_core.h +0 -7
@@ -16,7 +16,6 @@#include <linux/ratelimit.h> #include <linux/mutex.h> #include <linux/scatterlist.h> -#include <crypto/internal/hash.h> #include <crypto/internal/aead.h> #include <crypto/internal/rng.h> #include <crypto/internal/skcipher.h>
@@ -135,7 +134,6 @@ struct crypto4xx_alg_common {u32 type;union {struct skcipher_alg cipher; -struct ahash_alg hash;struct aead_alg aead;struct rng_alg rng; } u;
@@ -182,11 +180,6 @@ int crypto4xx_encrypt_noiv_block(structint crypto4xx_decrypt_noiv_block (struct skcipher_request *req);int crypto4xx_rfc3686_encrypt (struct skcipher_request *req);int crypto4xx_rfc3686_decrypt (struct skcipher_request *req); -int crypto4xx_sha1_alg_init (struct crypto_tfm *tfm); -int crypto4xx_hash_digest (struct ahash_request *req); -int crypto4xx_hash_final (struct ahash_request *req); -int crypto4xx_hash_update (struct ahash_request *req); -int crypto4xx_hash_init (struct ahash_request *req);/* * Note: Only use this function to copy items that is word aligned.