7.1.6-rc1 review
Subsystems (4)
Greg Kroah-Hartman
maintainerPATCH 222/744 ovpn: avoid putting unrelated P2P peer on socket release
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qing Ming <[email protected]>
[ Upstream commit b52c5103f64ee825996ca1ab8df7283cde8c5f86 ]
ovpn_peer_release_p2p() is called when an OVPN UDP socket is being destroyed. It checks the currently published P2P peer and releases it only if that peer still uses the socket being destroyed.
A peer replacement can publish a new peer before the old UDP socket is destroyed. When the old socket destruction path runs afterwards, ovpn_peer_release_p2p() observes the new peer through ovpn->peer. Since the new peer uses a different socket, the function takes the socket mismatch branch.
That branch still calls ovpn_peer_put(peer). At this point, however, peer is the currently published replacement peer, not the peer associated with the socket being destroyed. Dropping its reference can free it while ovpn->peer still points to it, leading to later use-after-free accesses from the peer and socket cleanup paths.
KASAN reports this as a slab-use-after-free on the kmalloc-1k ovpn_peer object. In the reproducer, the object is allocated from ovpn_peer_new() via ovpn_nl_peer_new_doit(), and freed through ovpn_peer_release_rcu() from RCU callback processing. Observed access sites include ovpn_peer_remove(), ovpn_socket_release(), ovpn_nl_peer_del_notify(), and unlock_ovpn().
Fix this by returning from the socket mismatch branch without putting the peer.
--- drivers/net/ovpn/peer.c | 1 - 1 file changed, 1 deletion(-)
drivers/net/ovpn/peer.c +0 -1
@@ -1167,7 +1167,6 @@ static void ovpn_peer_release_p2p(struct ovpn_priv *ovpn, struct sock *sk, ovpn_sock =rcu_access_pointer (peer->sock);if (!ovpn_sock || ovpn_sock->sk != sk) {spin_unlock_bh (&ovpn->lock); -ovpn_peer_put (peer);return ; } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 223/744 selftests/net: ovpn: fix getaddrinfo memory leak in ovpn_parse_remote()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: longlong yan <[email protected]>
[ Upstream commit 0bd9cfebc1c91e1066e56d6261b99691b9df6008 ]
The ovpn_parse_remote() function has two memory management issues:
1. When both 'host' and 'vpnip' are non-NULL, the first getaddrinfo() allocation is leaked because 'result' is overwritten by the second getaddrinfo() call without freeing the first allocation.
2. When both 'host' and 'vpnip' are NULL, 'result' is an uninitialized stack variable passed to freeaddrinfo(), which is undefined behavior.
Fix by initializing 'result' to NULL and calling freeaddrinfo() after the first getaddrinfo() result is consumed.
--- tools/testing/selftests/net/ovpn/ovpn-cli.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
tools/testing/selftests/net/ovpn/ovpn-cli.c +3 -1
@@ -1785,7 +1785,7 @@ static int ovpn_parse_remote(struct ovpn_ctx *ovpn, const char *host, const char *service, const char *vpnip) { int ret; -struct addrinfo *result; +struct addrinfo *result =NULL ; struct addrinfo hints = { .ai_family = ovpn->sa_family, .ai_socktype = SOCK_DGRAM,
@@ -1809,6 +1809,8 @@ static int ovpn_parse_remote(struct ovpn_ctx *ovpn, const char *host, }memcpy (&ovpn->remote, result->ai_addr, result->ai_addrlen); +freeaddrinfo (result); + result =NULL ; }if (vpnip) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 224/744 ovpn: fix use after free in unlock_ovpn()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marco Baffo <[email protected]>
[ Upstream commit e1ad6fe5db719874efa45b2caf9934552e09fc43 ]
unlock_ovpn() iterates over the release_list using llist_for_each_entry() and drops the peer reference inside the loop body via ovpn_peer_put().
If this drops the last reference, the peer is eventually freed. However, llist_for_each_entry() reads peer->release_entry.next in the loop advance expression, which runs after the body. By that time the peer may have already been freed, resulting in a use after free when advancing to the next list entry.
Fix this by using llist_for_each_entry_safe(), which caches the next pointer before executing the loop body.
--- drivers/net/ovpn/peer.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/ovpn/peer.c +3 -2
@@ -26,11 +26,12 @@ static void unlock_ovpn(struct ovpn_priv *ovpn, struct llist_head *release_list) __releases(&ovpn->lock) { -struct ovpn_peer *peer; +struct ovpn_peer *peer, *next;spin_unlock_bh (&ovpn->lock); -llist_for_each_entry (peer, release_list->first, release_entry) { +llist_for_each_entry_safe (peer, next, release_list->first, + release_entry) {ovpn_socket_release (peer);ovpn_peer_put (peer); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 225/744 ovpn: use monotonic clock for peer keepalive timeouts
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marco Baffo <[email protected]>
[ Upstream commit f7e6287ccd3abeed9e638b581dc3fdf742106ba3 ]
Replace ktime_get_real_seconds() with the monotonic ktime_get_boottime_seconds() to ensure the keepalive mechanism is robust against system clock modifications.
Right now, the driver uses ktime_get_real_seconds() to track peer timeouts, relying on the system wall-clock.
An administrative time adjustment or an NTP sync that steps the clock forward can cause now' to instantly exceed last_recv + timeout'.
When this occurs, the driver artificially expires healthy peers. Depending on the OpenVPN user-space configuration, this triggers a premature tunnel restart (if --keepalive or --ping-restart is used) or a complete disconnection of the client (if --ping-exit is used).
--- drivers/net/ovpn/io.c | 4 ++-- drivers/net/ovpn/peer.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
drivers/net/ovpn/io.c +2 -2
@@ -142,7 +142,7 @@ void ovpn_decrypt_post(void *data, int ret) }/* keep track of last received authenticated packet for keepalive */ -WRITE_ONCE (peer->last_recv,ktime_get_real_seconds ()); +WRITE_ONCE (peer->last_recv,ktime_get_boottime_seconds ());rcu_read_lock (); sock =rcu_dereference (peer->sock);
@@ -294,7 +294,7 @@ void ovpn_encrypt_post(void *data, int ret)ovpn_peer_stats_increment_tx (&peer->link_stats, orig_len);/* keep track of last sent packet for keepalive */ -WRITE_ONCE (peer->last_sent,ktime_get_real_seconds ()); +WRITE_ONCE (peer->last_sent,ktime_get_boottime_seconds ());/* skb passed down the stack - don't free it */ skb =NULL ; err_unlock:
drivers/net/ovpn/peer.c +2 -2
@@ -45,7 +45,7 @@ static void unlock_ovpn(struct ovpn_priv *ovpn,*/ void ovpn_peer_keepalive_set (struct ovpn_peer *peer,u32 interval,u32 timeout) { -time64_t now =ktime_get_real_seconds (); +time64_t now =ktime_get_boottime_seconds (); netdev_dbg(peer->ovpn->dev, "scheduling keepalive for peer %u: interval=%u timeout=%u\n",
@@ -1357,7 +1357,7 @@ void ovpn_peer_keepalive_work(struct work_struct *work) { struct ovpn_priv *ovpn = container_of(work, struct ovpn_priv, keepalive_work.work); -time64_t next_run =0 , now =ktime_get_real_seconds (); +time64_t next_run =0 , now =ktime_get_boottime_seconds ();LLIST_HEAD (release_list);spin_lock_bh (&ovpn->lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 226/744 hwmon: occ: validate poll response sensor blocks
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit 70e76e700fc6c46afb4e17aec099a1ea089b4a22 ]
The OCC poll response parser walks a counted list of sensor data blocks. It used the static backing-array capacity as the parse boundary, but a transport response makes only data_length bytes current and valid. A truncated response can therefore make the parser consume a block header or block extent outside the current response.
Use data_length as the parent boundary, prove the fixed poll header and each current block header before reading them, and prove the complete block before advancing. Keep parsed sensor metadata local until the complete response has passed validation, then publish it. Propagate malformed-response errors before publishing the OCC as active.
--- drivers/hwmon/occ/common.c | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-)
drivers/hwmon/occ/common.c +30 -8
@@ -1052,32 +1052,49 @@ static int occ_setup_sensor_attrs(struct occ *occ) }/* only need to do this once at startup, as OCC won't change sensors on us */ -static void occ_parse_poll_response (struct occ *occ) +static int occ_parse_poll_response (struct occ *occ) {unsigned int i, old_offset, offset =0 , size =0 ; +u16 data_length;struct occ_sensor *sensor; -struct occ_sensors *sensors = &occ->sensors; +struct occ_sensors parsed = {}; +struct occ_sensors *sensors = &parsed;struct occ_response *resp = &occ->resp;struct occ_poll_response *poll = (struct occ_poll_response *)&resp->data[0 ];struct occ_poll_response_header *header = &poll->header;struct occ_sensor_data_block *block = &poll->block; + data_length =get_unaligned_be16 (&resp->data_length); +if (data_length <sizeof (*header) || data_length >OCC_RESP_DATA_BYTES ) { +dev_err (occ->bus_dev,"invalid OCC poll response length %u\n" , + data_length); +return -EMSGSIZE ; + } +dev_info (occ->bus_dev,"OCC found, code level: %.16s\n" , header->occ_code_level);for (i =0 ; i < header->num_sensor_data_blocks; ++i) { block = (struct occ_sensor_data_block *)((u8 *)block + offset); +if (size +sizeof (*header) +sizeof (block->header) > + data_length) { +dev_err (occ->bus_dev, +"truncated OCC sensor block header\n" ); +return -EMSGSIZE ; + } + old_offset = offset; offset = (block->header.num_sensors * block->header.sensor_length) +sizeof (block->header); - size += offset;/* validate all the length/size fields */ -if ((size +sizeof (*header)) >=OCC_RESP_DATA_BYTES ) { -dev_warn (occ->bus_dev,"exceeded response buffer\n" ); -return ; +if (size +sizeof (*header) + offset > data_length) { +dev_err (occ->bus_dev, +"exceeded OCC poll response length\n" ); +return -EMSGSIZE ; } + size += offset; dev_dbg(occ->bus_dev, " %04x..%04x: %.4s (%d sensors)\n", old_offset, offset - 1, block->header.eye_catcher,
@@ -1107,6 +1124,9 @@ static void occ_parse_poll_response(struct occ *occ)dev_dbg (occ->bus_dev,"Max resp size: %u+%zd=%zd\n" , size,sizeof (*header), size +sizeof (*header)); + occ->sensors = parsed; + +return 0 ; }int occ_active (struct occ *occ,bool active)
@@ -1138,10 +1158,12 @@ int occ_active(struct occ *occ, bool active) goto unlock; } - occ->active = true; occ->next_update = jiffies +OCC_UPDATE_FREQUENCY ; -occ_parse_poll_response (occ); + rc =occ_parse_poll_response (occ); +if (rc) + goto unlock; + occ->active = true; rc =occ_setup_sensor_attrs (occ);if (rc) { dev_err(occ->bus_dev,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 227/744 regulator: mt6358: use regmap helper to read fixed LDO calibration
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Golle <[email protected]>
[ Upstream commit 1d26f125501f3fbe6c259ab75bf6516299a0bf0e ]
The "fixed" LDOs with output voltage calibration use mt6358_get_buck_voltage_sel as their get_voltage_sel op, but the MT6358_REG_FIXED and MT6366_REG_FIXED entries do not populate da_vsel_reg/da_vsel_mask. The op therefore reads register 0x0 with a zero mask and shifts the result by ffs(0) - 1 = -1, which is undefined behaviour and gets flagged by UBSAN on every boot on MT6366 boards:
UBSAN: shift-out-of-bounds in drivers/regulator/mt6358-regulator.c:384:38 shift exponent -1 is negative Call trace: mt6358_get_buck_voltage_sel+0xc8/0x120 regulator_get_voltage_rdev+0x70/0x170 set_machine_constraints+0x504/0xc38 regulator_register+0x324/0xc68
Besides the undefined shift, the returned selector is always 0, so the actual calibration offset programmed in <reg>_ANA_CON0 is never reported.
The descriptor already carries the correct vsel_reg/vsel_mask (the ANA_CON0 calibration field), matching the regulator_set_voltage_sel_regmap op already in use. Read the selector back through regulator_get_voltage_sel_regmap instead.
--- drivers/regulator/mt6358-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/regulator/mt6358-regulator.c +1 -1
@@ -492,7 +492,7 @@ static const struct regulator_ops mt6358_volt_fixed_ops = { .list_voltage = regulator_list_voltage_linear, .map_voltage = regulator_map_voltage_linear, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .get_voltage_sel = mt6358_get_buck_voltage_sel, + .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_time_sel = regulator_set_voltage_time_sel, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 228/744 Bluetooth: btusb: validate Realtek vendor event length
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit df541cd485ff80a5ddc579d99687bc7506df9851 ]
btusb_recv_event_realtek() reads the event code at data[0] and the Realtek subevent code at data[2] before deciding whether to consume a vendor event as a coredump.
For example, the two-byte event ff 00 contains a complete vendor-event header declaring zero parameters. The old classifier still reads a nonexistent third byte and can misclassify the event as a coredump if the adjacent byte is 0x34.
Require the HCI event header and first parameter to be present before inspecting the Realtek subevent code. Short events continue through the normal HCI receive path, which owns their protocol validation.
--- drivers/bluetooth/btusb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/bluetooth/btusb.c +3 -1
@@ -2765,7 +2765,9 @@ static int btusb_setup_realtek(struct hci_dev *hdev)static int btusb_recv_event_realtek (struct hci_dev *hdev,struct sk_buff *skb) { -if (skb->data[0 ] ==HCI_VENDOR_PKT && skb->data[2 ] ==RTK_SUB_EVENT_CODE_COREDUMP ) { +if (skb->len >=HCI_EVENT_HDR_SIZE +1 && + skb->data[0 ] ==HCI_VENDOR_PKT && + skb->data[2 ] ==RTK_SUB_EVENT_CODE_COREDUMP ) {struct rtk_dev_coredump_hdr hdr = { .code =RTK_DEVCOREDUMP_CODE_MEMDUMP , };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 229/744 net: phy: marvell: fix return code
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Walle <[email protected]>
[ Upstream commit 7d8ca62d6a9ef593780161586b4efc811ac094fe ]
Return the correct error code, not the value written to the register.
--- drivers/net/phy/marvell.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/phy/marvell.c +1 -1
@@ -753,7 +753,7 @@ static int m88e1111_config_inband(struct phy_device *phydev, unsigned int modes) err =phy_modify (phydev,MII_M1111_PHY_EXT_SR ,MII_M1111_HWCFG_SERIAL_AN_BYPASS , extsr);if (err <0 ) -return extsr; +return err;return phy_modify_paged (phydev,MII_MARVELL_FIBER_PAGE ,MII_BMCR ,BMCR_ANENABLE , bmcr);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 230/744 selftests/net: Fix tun IPv6 test addresses to avoid 6to4 range
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ricardo B. Marlière <[email protected]>
[ Upstream commit ef01724fa235a228e3d3e8b117e89403cd8feb25 ]
The IPv6 addresses used for the tun_vnet_udptnl fixture currently fall in the 2002::/16 prefix, which is reserved for the 6to4 transition mechanism (RFC 3056).
On systems where the sit module is loaded, the kernel automatically claims 2002::/16 as a 6to4 tunnel prefix. When the test assigns a 2002:: address to a TUN interface, sit registers a competing local route for the same address. This ambiguity breaks the GENEVE decapsulation path: packets injected via the TUN fd are not delivered to the test socket, causing the IPv6-outer gtgso send_gso_packet variants to fail.
Replace all four IPv6 test addresses with addresses from the fd00:db8::/32 range, which is part of the ULA space (fc00::/7, RFC 4193) and carries no special kernel semantics.
--- tools/testing/selftests/net/tun.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
tools/testing/selftests/net/tun.c +4 -4
@@ -42,19 +42,19 @@ static struct in_addr param_ipaddr4_inner_src = { };static struct in6_addr param_ipaddr6_outer_dst = { - { {0x20 ,0x02 ,0x0d ,0xb8 ,0x01 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 } }, + { {0xfd ,0x00 ,0x0d ,0xb8 ,0x01 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 } }, };static struct in6_addr param_ipaddr6_outer_src = { - { {0x20 ,0x02 ,0x0d ,0xb8 ,0x01 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,2 } }, + { {0xfd ,0x00 ,0x0d ,0xb8 ,0x01 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,2 } }, };static struct in6_addr param_ipaddr6_inner_dst = { - { {0x20 ,0x02 ,0x0d ,0xb8 ,0x02 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 } }, + { {0xfd ,0x00 ,0x0d ,0xb8 ,0x02 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 } }, };static struct in6_addr param_ipaddr6_inner_src = { - { {0x20 ,0x02 ,0x0d ,0xb8 ,0x02 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,2 } }, + { {0xfd ,0x00 ,0x0d ,0xb8 ,0x02 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,2 } }, };#ifndef BIT
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 231/744 netlink: specs: rt-link: convert bridge port flag attributes to u8
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Danielle Ratson <[email protected]>
[ Upstream commit f6e3b21608e974c4aaa4cfd73a239dacf1d8a9a3 ]
A number of IFLA_BRPORT_* attributes are documented in the rt-link spec as having the "flag" type, i.e. a payload-less NLA_FLAG attribute whose meaning is presence-only. This does not match the kernel, which emits these attributes with nla_put_u8() and validates them as NLA_U8 in br_port_policy[]. The values are not mere presence flags but carry a u8 payload (0/1).
Convert these bridge port attributes from "flag" to "u8" so the spec reflects the actual wire format.
--- Documentation/netlink/specs/rt-link.yaml | 40 ++++++++++++------------ 1 file changed, 20 insertions(+), 20 deletions(-)
Documentation/netlink/specs/rt-link.yaml +20 -20
@@ -1583,31 +1583,31 @@ attribute-sets: type: u32 - name: mode - type: flag + type: u8 - name: guard - type: flag + type: u8 - name: protect - type: flag + type: u8 - name: fast-leave - type: flag + type: u8 - name: learning - type: flag + type: u8 - name: unicast-flood - type: flag + type: u8 - name: proxyarp - type: flag + type: u8 - name: learning-sync - type: flag + type: u8 - name: proxyarp-wifi - type: flag + type: u8 - name: root-id type: binary
@@ -1654,34 +1654,34 @@ attribute-sets: type: pad - name: mcast-flood - type: flag + type: u8 - name: mcast-to-ucast - type: flag + type: u8 - name: vlan-tunnel - type: flag + type: u8 - name: bcast-flood - type: flag + type: u8 - name: group-fwd-mask type: u16 - name: neigh-suppress - type: flag + type: u8 - name: isolated - type: flag + type: u8 - name: backup-port type: u32 - name: mrp-ring-open - type: flag + type: u8 - name: mrp-in-open - type: flag + type: u8 - name: mcast-eht-hosts-limit type: u32
@@ -1690,10 +1690,10 @@ attribute-sets: type: u32 - name: locked - type: flag + type: u8 - name: mab - type: flag + type: u8 - name: mcast-n-groups type: u32
@@ -1702,7 +1702,7 @@ attribute-sets: type: u32 - name: neigh-vlan-suppress - type: flag + type: u8 - name: backup-nhid type: u32
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 232/744 net/packet: avoid fanout hook re-registration after unregister
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: David Lee <[email protected]>
[ Upstream commit 50aff80475abd3533eef4320477037e6fcc6b56e ]
packet_set_ring() temporarily detaches a socket from packet delivery while reconfiguring its ring. It records the previous running state, clears po->num, unregisters the protocol hook when needed, drops po->bind_lock, and later restores po->num and re-registers the hook from the saved was_running value.
That unlocked window can race with NETDEV_UNREGISTER. The notifier can observe the socket as not running, skip __unregister_prot_hook(), and invalidate the per-socket binding by setting po->ifindex to -1 and clearing po->prot_hook.dev. A one-member fanout group can still retain its shared fanout hook device pointer. When packet_set_ring() resumes, re-registering solely from the stale was_running state can re-add the fanout hook after the device has been unregistered.
Treat po->ifindex == -1 as an invalidated binding after reacquiring po->bind_lock. This is distinct from ifindex 0, the normal unbound/wildcard state: ifindex -1 marks an existing device binding that was invalidated when the device was unregistered. Restore po->num as before, but do not re-register the hook if device unregister already detached the socket.
--- net/packet/af_packet.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/packet/af_packet.c +5 -1
@@ -4561,7 +4561,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,spin_lock (&po->bind_lock);WRITE_ONCE (po->num, num); -if (was_running) +/* +* NETDEV_UNREGISTER may have invalidated the binding while bind_lock +* was dropped above. Do not re-add a fanout hook to a dead device. +*/ +if (was_running &&READ_ONCE (po->ifindex) !=-1 )register_prot_hook (sk);spin_unlock (&po->bind_lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 233/744 bpf: Reject redirect helpers without a bpf_net_context
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Daniel Borkmann <[email protected]>
[ Upstream commit 3f4920d165b29052255527d8ae7619e7ec132ece ]
The bpf_redirect*() helpers and skb_do_redirect() obtain the per-task bpf_redirect_info via bpf_net_ctx_get_ri(), which dereferences the current->bpf_net_context unconditionally. That context is established on the paths that run tc BPF such as sch_handle_{ingress,egress}(), *except* for the case where {cls,act}_bpf was attached to a proper qdisc. A program running from there reaches the NULL deref in two ways:
* It calls bpf_redirect() directly, which dereferences the context at the top of the helper:
tc qdisc add dev eth0 root handle 1: red limit 1MB min 10KB max 20KB \
avpkt 1000 burst 100 qevent early_drop block 10
tc filter add block 10 pref 1 bpf obj redirect.o
* It simply returns TC_ACT_REDIRECT without helper call: tcf_qevent_handle() then dispatches to skb_do_redirect(), which dereferences the context
Rather than extending bpf_net_context management into the qdisc path, make the redirect helpers refuse to operate when no context exists, and have tcf_qevent_handle() drop a TC_ACT_REDIRECT verdict instead of calling skb_do_redirect(). Previous behaviour was a crash, so nothing regresses by not supporting it.
--- net/core/filter.c | 17 +++++++++++------ net/sched/cls_api.c | 6 ++---- 2 files changed, 13 insertions(+), 10 deletions(-)
net/core/filter.c +11 -6
@@ -2552,11 +2552,13 @@ int skb_do_redirect(struct sk_buff *skb) BPF_CALL_2(bpf_redirect, u32, ifindex, u64, flags) { -struct bpf_redirect_info *ri =bpf_net_ctx_get_ri (); +struct bpf_redirect_info *ri; -if (unlikely (flags & (~(BPF_F_INGRESS ) |BPF_F_REDIRECT_INTERNAL ))) +if (unlikely (!bpf_net_ctx_get () || + (flags & (~(BPF_F_INGRESS ) |BPF_F_REDIRECT_INTERNAL ))))return TC_ACT_SHOT ; + ri =bpf_net_ctx_get_ri (); ri->flags = flags; ri->tgt_index = ifindex;
@@ -2573,11 +2575,12 @@ static const struct bpf_func_proto bpf_redirect_proto = { BPF_CALL_2(bpf_redirect_peer, u32, ifindex, u64, flags) { -struct bpf_redirect_info *ri =bpf_net_ctx_get_ri (); +struct bpf_redirect_info *ri; -if (unlikely (flags)) +if (unlikely (!bpf_net_ctx_get () || flags))return TC_ACT_SHOT ; + ri =bpf_net_ctx_get_ri (); ri->flags =BPF_F_PEER ; ri->tgt_index = ifindex;
@@ -2595,11 +2598,13 @@ static const struct bpf_func_proto bpf_redirect_peer_proto = { BPF_CALL_4(bpf_redirect_neigh, u32, ifindex, struct bpf_redir_neigh *, params, int, plen, u64, flags) { -struct bpf_redirect_info *ri =bpf_net_ctx_get_ri (); +struct bpf_redirect_info *ri; -if (unlikely ((plen && plen <sizeof (*params)) || flags)) +if (unlikely ((plen && plen <sizeof (*params)) || + !bpf_net_ctx_get () || flags))return TC_ACT_SHOT ; + ri =bpf_net_ctx_get_ri (); ri->flags =BPF_F_NEIGH | (plen ?BPF_F_NEXTHOP :0 ); ri->tgt_index = ifindex;
net/sched/cls_api.c +2 -4
@@ -4046,6 +4046,8 @@ struct sk_buff *tcf_qevent_handle(struct tcf_qevent *qe, struct Qdisc *sch, stru fl =rcu_dereference_bh (qe->filter_chain);switch (tcf_classify (skb,NULL , fl, &cl_res, false)) { +case TC_ACT_REDIRECT : + fallthrough;case TC_ACT_SHOT :qdisc_qstats_drop (sch);__qdisc_drop (skb, to_free);
@@ -4057,10 +4059,6 @@ struct sk_buff *tcf_qevent_handle(struct tcf_qevent *qe, struct Qdisc *sch, stru__qdisc_drop (skb, to_free); *ret = __NET_XMIT_STOLEN;return NULL ; -case TC_ACT_REDIRECT : -skb_do_redirect (skb); - *ret = __NET_XMIT_STOLEN; -return NULL ;case TC_ACT_CONSUMED : *ret = __NET_XMIT_STOLEN;return NULL ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 234/744 net/sched: Handle TC_ACT_REDIRECT from qdisc filter chains
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Jamal Hadi Salim <[email protected]>
[ Upstream commit ec48b3be2c8595dd290be883dbd4fb8b2f9f5d5e ]
When a TC filter attached to a qdisc filter chain returns TC_ACT_REDIRECT (ex: via an eBPF program calling bpf_redirect() or an act_bpf action), the redirect was silently lost i.e no qdisc classify function handled TC_ACT_REDIRECT, so the packet fell through the switch and was enqueued normally instead of being redirected.
This has been broken since bpf_redirect() was introduced for TC in commit 27b29f63058d ("bpf: add bpf_redirect() helper"). We got lucky for a long time because bpf_net_context was a per-CPU variable that was always available.
commit 401cb7dae813 ("net: Reference bpf_redirect_info via task_struct on PREEMPT_RT.") turned bpf_net_context into a task_struct member that is only set up by explicit callers. Without a caller setting it up, bpf_redirect() itself crashes with a NULL pointer dereference in bpf_net_ctx_get_ri(). However, even with bpf_net_context available, TC_ACT_REDIRECT from qdisc filter chains cannot be honored without adding skb_do_redirect() calls to every qdisc classify function, which would require changes across net/sched/. Isolate it to ebpf core where it belongs.
Instead, add a tcf_classify_qdisc() inline helper in pkt_cls.h, as a wrapper around tcf_classify() for use by qdisc classify functions and tcf_qevent_handle(). When the classify verdict is TC_ACT_REDIRECT, the wrapper converts it to TC_ACT_SHOT, dropping the packet rather than letting it continue silently. Dropping is preferred over letting the packet through because the user immediately sees packet loss. Silently passing the packet through would hide the problem and leave the user wondering why their redirect is not working.
The clsact fast path, tc_run() continues to call tcf_classify() directly and is unaffected: TC_ACT_REDIRECT is returned as-is and handled by sch_handle_egress/ingress() calling skb_do_redirect() as before.
--- include/net/pkt_cls.h | 14 +++++++++++++- net/sched/cls_api.c | 4 +--- net/sched/sch_cake.c | 2 +- net/sched/sch_drr.c | 2 +- net/sched/sch_dualpi2.c | 2 +- net/sched/sch_ets.c | 2 +- net/sched/sch_fq_codel.c | 2 +- net/sched/sch_fq_pie.c | 2 +- net/sched/sch_hfsc.c | 2 +- net/sched/sch_htb.c | 2 +- net/sched/sch_multiq.c | 2 +- net/sched/sch_prio.c | 2 +- net/sched/sch_qfq.c | 2 +- net/sched/sch_sfb.c | 2 +- net/sched/sch_sfq.c | 2 +- 15 files changed, 27 insertions(+), 17 deletions(-)
include/net/pkt_cls.h +13 -1
@@ -156,8 +156,20 @@ static inline int tcf_classify(struct sk_buff *skb, {return TC_ACT_UNSPEC ; } -#endif +static inline int tcf_classify_qdisc (struct sk_buff *skb, +const struct tcf_proto *tp, +struct tcf_result *res,bool compat_mode) +{ +int ret =tcf_classify (skb,NULL , tp, res, compat_mode); + +/* TC_ACT_REDIRECT from qdisc filter chains is not supported. +* Use BPF via tcx or mirred redirect instead. +*/ +if (unlikely (ret ==TC_ACT_REDIRECT )) + ret =TC_ACT_SHOT ; +return ret; +}static inline unsigned long __cls_set_class (unsigned long *clp,unsigned long cl)
net/sched/cls_api.c +1 -3
@@ -4045,9 +4045,7 @@ struct sk_buff *tcf_qevent_handle(struct tcf_qevent *qe, struct Qdisc *sch, stru fl =rcu_dereference_bh (qe->filter_chain); -switch (tcf_classify (skb,NULL , fl, &cl_res, false)) { -case TC_ACT_REDIRECT : - fallthrough; +switch (tcf_classify_qdisc (skb, fl, &cl_res, false)) {case TC_ACT_SHOT :qdisc_qstats_drop (sch);__qdisc_drop (skb, to_free);
net/sched/sch_cake.c +1 -1
@@ -1727,7 +1727,7 @@ static u32 cake_classify(struct Qdisc *sch, struct cake_tin_data **t, goto hash; *qerr =NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; - result =tcf_classify (skb,NULL , filter, &res, false); + result =tcf_classify_qdisc (skb, filter, &res, false);if (result >=0 ) {#ifdef CONFIG_NET_CLS_ACT
net/sched/sch_drr.c +1 -1
@@ -314,7 +314,7 @@ static struct drr_class *drr_classify(struct sk_buff *skb, struct Qdisc *sch, *qerr =NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; fl =rcu_dereference_bh (q->filter_list); - result =tcf_classify (skb,NULL , fl, &res, false); + result =tcf_classify_qdisc (skb, fl, &res, false);if (result >=0 ) {#ifdef CONFIG_NET_CLS_ACT switch (result) {
net/sched/sch_dualpi2.c +1 -1
@@ -364,7 +364,7 @@ static int dualpi2_skb_classify(struct dualpi2_sched_data *q,if (!fl)return NET_XMIT_SUCCESS ; - result =tcf_classify (skb,NULL , fl, &res, false); + result =tcf_classify_qdisc (skb, fl, &res, false);if (result >=0 ) {#ifdef CONFIG_NET_CLS_ACT switch (result) {
net/sched/sch_ets.c +1 -1
@@ -393,7 +393,7 @@ static struct ets_class *ets_classify(struct sk_buff *skb, struct Qdisc *sch, *qerr =NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;if (TC_H_MAJ (skb->priority) != sch->handle) { fl =rcu_dereference_bh (q->filter_list); - err =tcf_classify (skb,NULL , fl, &res, false); + err =tcf_classify_qdisc (skb, fl, &res, false);#ifdef CONFIG_NET_CLS_ACT switch (err) {case TC_ACT_STOLEN :
net/sched/sch_fq_codel.c +1 -1
@@ -91,7 +91,7 @@ static unsigned int fq_codel_classify(struct sk_buff *skb, struct Qdisc *sch,return fq_codel_hash (q, skb) +1 ; *qerr =NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; - result =tcf_classify (skb,NULL , filter, &res, false); + result =tcf_classify_qdisc (skb, filter, &res, false);if (result >=0 ) {#ifdef CONFIG_NET_CLS_ACT switch (result) {
net/sched/sch_fq_pie.c +1 -1
@@ -96,7 +96,7 @@ static unsigned int fq_pie_classify(struct sk_buff *skb, struct Qdisc *sch,return fq_pie_hash (q, skb) +1 ; *qerr =NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; - result =tcf_classify (skb,NULL , filter, &res, false); + result =tcf_classify_qdisc (skb, filter, &res, false);if (result >=0 ) {#ifdef CONFIG_NET_CLS_ACT switch (result) {
net/sched/sch_hfsc.c +1 -1
@@ -1143,7 +1143,7 @@ hfsc_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) *qerr =NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; head = &q->root; tcf =rcu_dereference_bh (q->root.filter_list); -while (tcf && (result =tcf_classify (skb,NULL , tcf, &res, false)) >=0 ) { +while (tcf && (result =tcf_classify_qdisc (skb, tcf, &res, false)) >=0 ) {#ifdef CONFIG_NET_CLS_ACT switch (result) {case TC_ACT_QUEUED :
net/sched/sch_htb.c +1 -1
@@ -242,7 +242,7 @@ static struct htb_class *htb_classify(struct sk_buff *skb, struct Qdisc *sch, } *qerr =NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; -while (tcf && (result =tcf_classify (skb,NULL , tcf, &res, false)) >=0 ) { +while (tcf && (result =tcf_classify_qdisc (skb, tcf, &res, false)) >=0 ) {#ifdef CONFIG_NET_CLS_ACT switch (result) {case TC_ACT_QUEUED :
net/sched/sch_multiq.c +1 -1
@@ -36,7 +36,7 @@ multiq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)int err; *qerr =NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; - err =tcf_classify (skb,NULL , fl, &res, false); + err =tcf_classify_qdisc (skb, fl, &res, false);#ifdef CONFIG_NET_CLS_ACT switch (err) {case TC_ACT_STOLEN :
net/sched/sch_prio.c +1 -1
@@ -39,7 +39,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr) *qerr =NET_XMIT_SUCCESS | __NET_XMIT_BYPASS;if (TC_H_MAJ (skb->priority) != sch->handle) { fl =rcu_dereference_bh (q->filter_list); - err =tcf_classify (skb,NULL , fl, &res, false); + err =tcf_classify_qdisc (skb, fl, &res, false);#ifdef CONFIG_NET_CLS_ACT switch (err) {case TC_ACT_STOLEN :
net/sched/sch_qfq.c +1 -1
@@ -709,7 +709,7 @@ static struct qfq_class *qfq_classify(struct sk_buff *skb, struct Qdisc *sch, *qerr =NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; fl =rcu_dereference_bh (q->filter_list); - result =tcf_classify (skb,NULL , fl, &res, false); + result =tcf_classify_qdisc (skb, fl, &res, false);if (result >=0 ) {#ifdef CONFIG_NET_CLS_ACT switch (result) {
net/sched/sch_sfb.c +1 -1
@@ -260,7 +260,7 @@ static bool sfb_classify(struct sk_buff *skb, struct tcf_proto *fl,struct tcf_result res;int result; - result =tcf_classify (skb,NULL , fl, &res, false); + result =tcf_classify_qdisc (skb, fl, &res, false);if (result >=0 ) {#ifdef CONFIG_NET_CLS_ACT switch (result) {
net/sched/sch_sfq.c +1 -1
@@ -171,7 +171,7 @@ static unsigned int sfq_classify(struct sk_buff *skb, struct Qdisc *sch,return sfq_hash (q, skb) +1 ; *qerr =NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; - result =tcf_classify (skb,NULL , fl, &res, false); + result =tcf_classify_qdisc (skb, fl, &res, false);if (result >=0 ) {#ifdef CONFIG_NET_CLS_ACT switch (result) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 235/744 bonding: fix devconf_all NULL dereference when IPv6 is disabled
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhaolong Zhang <[email protected]>
[ Upstream commit 1c975de3343cdef506f2eecc833cc1f14b0401c4 ]
When booting with the 'ipv6.disable=1' parameter, the devconf_all is never initialized because inet6_init() exits before addrconf_init() is called which initializes it. bond_send_validate(), however, will still call bond_ns_send_all() even ipv6 is indeed disabled. It will lead to NULL derefence of net->ipv6.devconf_all in ip6_pol_route().
BUG: kernel NULL pointer dereference, address: 000000000000000c [...] Workqueue: bond0 bond_arp_monitor [bonding] RIP: 0010:ip6_pol_route+0x69/0x480 [...] Call Trace: <TASK> ? srso_return_thunk+0x5/0x5f ? __pfx_ip6_pol_route_output+0x10/0x10 fib6_rule_lookup+0xfe/0x260 ? wakeup_preempt+0x8a/0x90 ? srso_return_thunk+0x5/0x5f ? srso_return_thunk+0x5/0x5f ? sched_balance_rq+0x369/0x810 ip6_route_output_flags+0xd7/0x170 bond_ns_send_all+0xde/0x280 [bonding] bond_ab_arp_probe+0x296/0x320 [bonding] ? srso_return_thunk+0x5/0x5f bond_activebackup_arp_mon+0xb4/0x2c0 [bonding] process_one_work+0x196/0x370 worker_thread+0x1af/0x320 ? srso_return_thunk+0x5/0x5f ? __pfx_worker_thread+0x10/0x10 kthread+0xe3/0x120 ? __pfx_kthread+0x10/0x10 ret_from_fork+0x199/0x260 ? __pfx_kthread+0x10/0x10 ret_from_fork_asm+0x1a/0x30 </TASK>
Fix this by adding ipv6_mod_enabled() condition check in the caller.
--- drivers/net/bonding/bond_main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/bonding/bond_main.c +2 -1
@@ -3446,7 +3446,8 @@ static void bond_send_validate(struct bonding *bond, struct slave *slave) {bond_arp_send_all (bond, slave);#if IS_ENABLED (CONFIG_IPV6 ) -bond_ns_send_all (bond, slave); +if (likely (ipv6_mod_enabled ())) +bond_ns_send_all (bond, slave);#endif }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 236/744 rds: drop incoming messages that cross network namespace boundaries
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aldo Ariel Panzardo <[email protected]>
[ Upstream commit 5521ae71e32a8069ed4ca6e792179dc57bc43ab2 ]
rds_find_bound() looks up the destination socket using a global rhashtable keyed solely on (addr, port, scope_id). Network namespaces are not part of the key, so a sender in netns A can deliver an incoming message (inc) to a socket that lives in a different netns B.
When this happens, inc->i_conn points to an rds_connection whose c_net is netns A, but the receiving rs lives in netns B. Once the child process that created netns A exits, cleanup_net() calls rds_loop_exit_net() -> rds_loop_kill_conns() -> rds_conn_destroy(), freeing that connection. If the survivor socket in netns B still holds the inc, any subsequent dereference of inc->i_conn is a use-after-free.
There are two dangerous sites in rds_clear_recv_queue():
1. inc->i_conn->c_lcong (offset 88 of freed rds_connection, size 200) read via rds_recv_rcvbuf_delta() -- confirmed by KASAN.
2. inc->i_conn->c_trans->inc_free(inc) (function pointer at offset 80) called via rds_inc_put() when the inc refcount reaches zero -- same race window, potential call-through-freed-object primitive.
The bug is reachable from unprivileged user namespaces (CLONE_NEWUSER + CLONE_NEWNET), available since Linux 3.8.
Fix this by rejecting the delivery in rds_recv_incoming() when the socket returned by rds_find_bound() belongs to a different network namespace than the connection that carried the message. Use the existing rds_conn_net() / sock_net() helpers and net_eq() for the comparison.
--- net/rds/recv.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+)
net/rds/recv.c +15 -0
@@ -399,6 +399,21 @@ void rds_recv_incoming(struct rds_connection *conn, struct in6_addr *saddr, goto out; } +/* +* rds_find_bound() uses a global (netns-agnostic) hash table. +* An RDS connection created in netns A can match a socket bound +* in the init netns, delivering inc cross-netns with inc->i_conn +* pointing into netns A. When cleanup_net() then frees that conn, +* any subsequent dereference of inc->i_conn is a use-after-free. +* Drop the inc if the receiving socket lives in a different netns. +*/ +if (!net_eq (sock_net (rds_rs_to_sk (rs)),rds_conn_net (conn))) { +rds_stats_inc (s_recv_drop_no_sock); +rds_sock_put (rs); + rs =NULL ; + goto out; + } +/* Process extension headers */ rds_recv_incoming_exthdrs (inc, rs);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 237/744 gtp: parse extension headers before reading inner protocol
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhixing Chen <[email protected]>
[ Upstream commit 96e37e2f618e931aa97af95e707dcdfb1ec41264 ]
GTPv1-U packets may carry a chain of extension headers before the inner IP packet. The receive path already parses and skips these extension headers, but it currently reads the inner protocol before doing so.
As a result, the first extension header byte is interpreted as the inner IP version. Packets with extension headers are then dropped before PDP lookup.
Parse the extension header chain before calling gtp_inner_proto(), so the inner protocol is read from the actual inner IP header.
--- drivers/net/gtp.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
drivers/net/gtp.c +6 -6
@@ -826,13 +826,17 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)if (!pskb_may_pull (skb, hdrlen))return -1 ; + gtp1 = (struct gtp1_header *)(skb->data +sizeof (struct udphdr )); + +if (gtp1->flags >P1_F_EXTHDR && +gtp_parse_exthdrs (skb, &hdrlen) <0 ) +return -1 ; +if (gtp_inner_proto (skb, hdrlen, &inner_proto) <0 ) {netdev_dbg (gtp->dev,"GTP packet does not encapsulate an IP packet\n" );return -1 ; } - gtp1 = (struct gtp1_header *)(skb->data +sizeof (struct udphdr )); - pctx =gtp1_pdp_find (gtp,ntohl (gtp1->tid),gtp_proto_to_family (inner_proto));if (!pctx) {
@@ -840,10 +844,6 @@ static int gtp1u_udp_encap_recv(struct gtp_dev *gtp, struct sk_buff *skb)return 1 ; } -if (gtp1->flags >P1_F_EXTHDR && -gtp_parse_exthdrs (skb, &hdrlen) <0 ) -return -1 ; -return gtp_rx (pctx, skb, hdrlen, gtp->role, inner_proto); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 238/744 rxrpc: fix io_thread race in rxrpc_wake_up_io_thread()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xuanqiang Luo <[email protected]>
[ Upstream commit 745fb794c3e933c023af9dbb5876a5e16ad2dc71 ]
rxrpc_wake_up_io_thread() checks local->io_thread before waking it, but then reloads the pointer for wake_up_process().
local->io_thread is cleared with WRITE_ONCE() when the I/O thread exits, so the second load can see NULL even if the first load did not.
Take a READ_ONCE() snapshot and use it for both the NULL check and the wake_up_process() call, as rxrpc_encap_rcv() already does.
--- net/rxrpc/ar-internal.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/rxrpc/ar-internal.h +4 -2
@@ -1266,9 +1266,11 @@ int rxrpc_io_thread(void *data);void rxrpc_post_response (struct rxrpc_connection *conn,struct sk_buff *skb);static inline void rxrpc_wake_up_io_thread (struct rxrpc_local *local) { -if (!local->io_thread) +struct task_struct *io_thread =READ_ONCE (local->io_thread); + +if (!io_thread)return ; -wake_up_process (READ_ONCE (local->io_thread)); +wake_up_process (io_thread); }static inline bool rxrpc_protocol_error (struct sk_buff *skb,enum rxrpc_abort_reason why)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 239/744 dpaa2-switch: put MAC endpoint device on disconnect
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit 4c1eabbef7a1707635652e956e39db1269c3af2b ]
fsl_mc_get_endpoint() returns the MAC endpoint device with a reference taken through device_find_child(). The switch port connect path stores that device in mac->mc_dev and keeps it for the lifetime of the connected MAC object.
However, the disconnect path only closes the MAC and frees the dpaa2_mac object. It does not drop the endpoint device reference stored in mac->mc_dev, so every successful connect leaks that device reference when the MAC is later disconnected.
Drop the endpoint device reference before freeing the dpaa2_mac object.
--- drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c +1 -0
@@ -1511,6 +1511,7 @@ static void dpaa2_switch_port_disconnect_mac(struct ethsw_port_priv *port_priv)dpaa2_mac_disconnect (mac);dpaa2_mac_close (mac); +put_device (&mac->mc_dev->dev);kfree (mac); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 240/744 net: airoha: Fix potential use-after-free in airoha_ppe_deinit()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wayen Yan <[email protected]>
[ Upstream commit 2484568a335cd7bda951c75b3a7d95ea36161ae7 ]
airoha_ppe_deinit() replaces the NPU pointer with NULL via rcu_replace_pointer() but does not wait for existing RCU readers to exit before calling ppe_deinit() and airoha_npu_put(). This can cause a use-after-free if a reader in an RCU read-side critical section still holds a reference to the NPU when it is freed.
The init path (airoha_ppe_init) already calls synchronize_rcu() after rcu_assign_pointer(), but the deinit path introduced in commit 6abcf751bc08 ("net: airoha: Fix schedule while atomic in airoha_ppe_deinit()") omitted the matching barrier when switching from rcu_read_lock()/rcu_dereference() to rcu_replace_pointer().
Add synchronize_rcu() before ppe_deinit() to ensure all existing RCU readers have completed before the NPU resources are released.
--- drivers/net/ethernet/airoha/airoha_ppe.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/airoha/airoha_ppe.c +1 -0
@@ -1619,6 +1619,7 @@ void airoha_ppe_deinit(struct airoha_eth *eth) npu =rcu_replace_pointer (eth->npu,NULL ,lockdep_is_held (&flow_offload_mutex));if (npu) { +synchronize_rcu (); npu->ops.ppe_deinit (npu);airoha_npu_put (npu); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 241/744 dpaa2-eth: put MAC endpoint device on disconnect
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit b4b201cc93ff70150853aba03e14d314d1980ca0 ]
fsl_mc_get_endpoint() returns the MAC endpoint device with a reference taken through device_find_child(). The Ethernet connect path stores that device in mac->mc_dev and keeps it for the lifetime of the connected MAC object.
However, the disconnect path only disconnects and closes the MAC before freeing the dpaa2_mac object. It does not drop the endpoint device reference stored in mac->mc_dev, so every successful connect leaks that device reference when the MAC is later disconnected.
Drop the endpoint device reference after closing the MAC and before freeing the dpaa2_mac object.
--- drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +1 -0
@@ -4732,6 +4732,7 @@ static void dpaa2_eth_disconnect_mac(struct dpaa2_eth_priv *priv)dpaa2_mac_disconnect (mac);dpaa2_mac_close (mac); +put_device (&mac->mc_dev->dev);kfree (mac); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 242/744 net: airoha: Fix DMA direction for NPU mailbox buffer
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Wayen Yan <[email protected]>
[ Upstream commit 6f884eb87a79e0c482baef2ad96c96b81d024235 ]
airoha_npu_send_msg() always maps the mailbox buffer with DMA_TO_DEVICE, but some callers expect the NPU to write response data back into the same buffer:
- airoha_npu_wlan_msg_get() (NPU_OP_GET): NPU writes response into the buffer, then the caller reads it via memcpy()
- airoha_npu_ppe_stats_setup() (NPU_OP_SET): NPU writes back npu_stats_addr field in the response
On non-cache-coherent architectures like EN7581 (Cortex-A53 without hardware cache coherency for NPU DMA), DMA_TO_DEVICE unmap is a no-op — it does not invalidate the CPU cache. If the NPU-written cache line is still present in the CPU cache when the caller reads the buffer, the CPU observes stale data instead of the NPU response.
This is a timing-sensitive bug: small mailbox buffers (~24 bytes) typically fit in a single cache line and may survive in the cache until the caller reads them, producing silent data corruption rather than a crash. The bug is more likely to trigger when the caller reads the response immediately after dma_unmap_single() without intervening cache-evicting operations.
Fix by using DMA_BIDIRECTIONAL for both map and unmap, which ensures dma_unmap_single() invalidates the CPU cache on non-coherent systems. The mailbox buffers are small so there is no performance concern.
--- drivers/net/ethernet/airoha/airoha_npu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/net/ethernet/airoha/airoha_npu.c +2 -2
@@ -168,7 +168,7 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id,dma_addr_t dma_addr;int ret; - dma_addr =dma_map_single (npu->dev, p, size,DMA_TO_DEVICE ); + dma_addr =dma_map_single (npu->dev, p, size,DMA_BIDIRECTIONAL ); ret =dma_mapping_error (npu->dev, dma_addr);if (ret)return ret;
@@ -191,7 +191,7 @@ static int airoha_npu_send_msg(struct airoha_npu *npu, int func_id,spin_unlock_bh (&npu->cores[core].lock); -dma_unmap_single (npu->dev, dma_addr, size,DMA_TO_DEVICE ); +dma_unmap_single (npu->dev, dma_addr, size,DMA_BIDIRECTIONAL );return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 243/744 iommu/amd: Wait for completion instead of returning early in iommu_completion_wait()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guanghui Feng <[email protected]>
[ Upstream commit 1e75a8255f11c81fb07e81e5029cfd75804350a0 ]
need_sync is a per-IOMMU flag shared by all domains and devices behind that IOMMU. It is set whenever a command is queued with sync == true and cleared when a completion-wait (CWAIT) command is queued. However, a cleared need_sync only means that a covering CWAIT has been queued, not that all previously queued commands have actually completed in hardware.
iommu_completion_wait() read need_sync locklessly and returned early when it was false. This breaks the "block until all previously queued commands have completed" contract in a multi-CPU scenario:
CPU2: queue inv-B => need_sync = true
CPU1: queue CWAIT(N); need_sync = false; then wait_on_sem(N)
CPU2: read need_sync == false => return 0 (no wait!)
CPU2 returns without waiting for any sequence number even though its inv-B may not have completed yet (CWAIT(N), queued after inv-B, has not been signaled). CPU2 then proceeds to, for example, free page-table pages while the IOMMU can still walk stale translations, opening a use-after-free window. This is a logical race in the meaning of the flag, not a memory-visibility issue, so barriers alone do not help.
Fix it without losing the optimization of avoiding redundant CWAIT
commands: take iommu->lock before testing need_sync, and when it is false do not return early but wait for the last allocated sequence number (cmd_sem_val). Since need_sync == false implies no sync command was queued after the last CWAIT, that CWAIT is FIFO-ordered after every not-yet-completed command, so waiting for its sequence number guarantees all prior commands (possibly queued by another CPU) have completed. The common path with pending work is unchanged and no extra hardware command is issued.
--- drivers/iommu/amd/iommu.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-)
drivers/iommu/amd/iommu.c +16 -6
@@ -1456,11 +1456,23 @@ static int iommu_completion_wait(struct amd_iommu *iommu)int ret;u64 data; -if (!iommu->need_sync) -return 0 ; -raw_spin_lock_irqsave (&iommu->lock, flags); +if (!iommu->need_sync) { +/* +* No command has been queued since the last completion-wait. +* A concurrent CPU may have already queued that CWAIT and +* cleared need_sync; need_sync == false only means a covering +* CWAIT is queued, not that all prior commands have completed. +* Wait for the last allocated sequence number so that any +* command queued before this call (possibly on another CPU) +* is guaranteed to have completed before returning. +*/ + data = iommu->cmd_sem_val; +raw_spin_unlock_irqrestore (&iommu->lock, flags); +return wait_on_sem (iommu, data); + } + data =get_cmdsem_val (iommu);build_completion_wait (&cmd, iommu, data);
@@ -1470,9 +1482,7 @@ static int iommu_completion_wait(struct amd_iommu *iommu)if (ret)return ret; - ret =wait_on_sem (iommu, data); - -return ret; +return wait_on_sem (iommu, data); }static void domain_flush_complete (struct protection_domain *domain)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 244/744 wifi: mac80211: tear down new links on vif update error path
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei <[email protected]>
[ Upstream commit 952c02b33f56207a160421bcd61e7ac53c9c59ae ]
When ieee80211_vif_update_links() adds new links it allocates a link container for each and calls ieee80211_link_init() (which registers the per-link debugfs files with file->private_data pointing into the container) and ieee80211_link_setup(). If the subsequent drv_change_vif_links() fails, the error path restores the old pointers and jumps to 'free', which frees the new containers but never removes their debugfs entries or stops the links. The debugfs files survive with file->private_data dangling at the freed container, so a later open()+read() (e.g. link-1/txpower) dereferences freed memory in ieee80211_if_read_link(), a use-after-free.
The removal path already dismantles links correctly via ieee80211_tear_down_links(), which removes each link's keys and debugfs entries and calls ieee80211_link_stop(); the add path on the error branch does not. Commit be1ba9ed221f ("wifi: mac80211: avoid weird state in error path") hardened this same error path for the link-removal case (new_links == 0) but left the newly-added links' teardown unaddressed.
drv_change_vif_links() can fail at runtime on MLO drivers (internal allocation / queue / firmware command failures).
Remove the new links' debugfs entries and stop them before freeing.
BUG: KASAN: slab-use-after-free in ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) Read of size 8 at addr ffff888011290000 by task exploit/145 Call Trace: ... ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) short_proxy_read (fs/debugfs/file.c:373) vfs_read (fs/read_write.c:572) ksys_read (fs/read_write.c:716) do_syscall_64 (arch/x86/entry/syscall_64.c:94) entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121) ... Oops: general protection fault, probably for non-canonical address 0xdffffc000000000a RIP: 0010:ieee80211_if_read_link (net/mac80211/debugfs_netdev.c:127) Kernel panic - not syncing: Fatal exception
--- net/mac80211/link.c | 4 ++++ 1 file changed, 4 insertions(+)
net/mac80211/link.c +4 -0
@@ -394,6 +394,10 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,memcpy (sdata->link, old_data,sizeof (old_data));memcpy (sdata->vif.link_conf, old,sizeof (old));ieee80211_set_vif_links_bitmaps (sdata, old_links, dormant_links); +for_each_set_bit (link_id, &add,IEEE80211_MLD_MAX_NUM_LINKS ) { +ieee80211_link_debugfs_remove (&links[link_id]->data); +ieee80211_link_stop (&links[link_id]->data); + }/* and free (only) the newly allocated links */ memset (to_free,0 ,sizeof (links)); goto free;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 245/744 nfp: Check resource mutex allocation
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit a61b4db34a753bdf5c9e77a7f3d3dddd41dcfacc ]
nfp_cpp_resource_find() allocates a CPP mutex handle for the matching resource-table entry and then reports success. nfp_resource_try_acquire() immediately passes that handle to nfp_cpp_mutex_trylock().
However, nfp_cpp_mutex_alloc() returns NULL on failure. If that happens for a matching table entry, the resource lookup still returns success and the following trylock dereferences a NULL mutex pointer while opening the resource.
nfp_resource_acquire() already treats failure to allocate the table mutex as -ENOMEM. Do the same for the resource mutex and fail the lookup before publishing the rest of the resource handle.
This issue was found by a static analysis checker and confirmed by manual source review.
--- drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ethernet/netronome/nfp/nfpcore/nfp_resource.c +3 -0
@@ -96,6 +96,9 @@ static int nfp_cpp_resource_find(struct nfp_cpp *cpp, struct nfp_resource *res) res->mutex =nfp_cpp_mutex_alloc (cpp,NFP_RESOURCE_TBL_TARGET , addr, key); +if (!res->mutex) +return -ENOMEM ; + res->cpp_id =NFP_CPP_ID (entry.region.cpp_target, entry.region.cpp_action, entry.region.cpp_token);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 246/744 wan: wanxl: Only reset hardware after BAR mapping
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit 91957b89da995607cb654b1f9a3c126ddbaee10f ]
wanxl_pci_init_one() stores the freshly allocated card in driver data before the PLX BAR is mapped. Several early probe failures then unwind through wanxl_pci_remove_one(), including failure to allocate the coherent status area or to restore the DMA mask.
wanxl_pci_remove_one() unconditionally calls wanxl_reset(), and wanxl_reset() dereferences card->plx. On those early failures card->plx is still NULL, so the error path can dereference a NULL MMIO pointer.
Only issue the hardware reset once the BAR mapping exists. The remaining cleanup in wanxl_pci_remove_one() already checks whether later resources were allocated.
This issue was found by a static analysis checker and confirmed by manual source review.
--- drivers/net/wan/wanxl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/net/wan/wanxl.c +2 -1
@@ -514,7 +514,8 @@ static void wanxl_pci_remove_one(struct pci_dev *pdev)if (card->irq)free_irq (card->irq, card); -wanxl_reset (card); +if (card->plx) +wanxl_reset (card);for (i =0 ; i <RX_QUEUE_LENGTH ; i++)if (card->rx_skbs[i]) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 247/744 vhost-net: fix TX stall when vhost owns virtio-net header
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Enrico Zanda <[email protected]>
[ Upstream commit 3c0d10f233f19153f81fef685b5c6716776a5af3 ]
When vhost owns the virtio-net header, i.e. when VHOST_NET_F_VIRTIO_NET_HDR is negotiated, sock_hlen is 0, meaning that no header will be forwarded to the TAP device.
In the current vhost_net_build_xdp() implementation,
when sock_hlen == 0, the gso pointer can point at the start of the Ethernet frame instead of a virtio-net header.
This results in a wrong interpretation of the destination MAC address bytes as struct virtio_net_hdr fields.
This can, for some MAC addresses, trigger -EINVAL and return early before the TX descriptor is completed, which can stall vhost-net TX.
Before 97b2409f28e0, the gso pointer was set to the zeroed padding area, using it as a synthetic virtio-net header. Restore that behavior.
--- drivers/vhost/net.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
drivers/vhost/net.c +5 -3
@@ -722,10 +722,12 @@ static int vhost_net_build_xdp(struct vhost_net_virtqueue *nvq, goto err; } - gso = buf + pad - sock_hlen; - -if (!sock_hlen) +if (!sock_hlen) {memset (buf,0 , pad); + gso = buf; + }else { + gso = buf + pad - sock_hlen; + }if ((gso->flags &VIRTIO_NET_HDR_F_NEEDS_CSUM ) && vhost16_to_cpu(vq, gso->csum_start) +
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 248/744 wifi: mac80211: copy aggregation information
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Benjamin Berg <[email protected]>
[ Upstream commit 0fe2d5be7ab59717adb3f9cfab3832c6c4dd770c ]
This information can be considered part of the capabilities and should also be copied to the NAN data station.
--- net/mac80211/cfg.c | 3 +++ 1 file changed, 3 insertions(+)
net/mac80211/cfg.c +3 -0
@@ -2414,6 +2414,9 @@ static int sta_apply_parameters(struct ieee80211_local *local,memcpy (&sta->deflink.pub->supp_rates, &nmi_sta->deflink.pub->supp_rates,sizeof (sta->deflink.pub->supp_rates)); + + sta->deflink.pub->agg = nmi_sta->deflink.pub->agg; +__ieee80211_sta_recalc_aggregates (sta,0 ); }/* set the STA state after all sta info from usermode has been set */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 249/744 wifi: mwifiex: bound uAP association event IEs to the event buffer
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: HE WEI (ギカク) <[email protected]>
[ Upstream commit f0858bfc7d3cab411a447b88e3ef970e575032c9 ]
mwifiex_process_uap_event() handles EVENT_UAP_STA_ASSOC by exposing the (re)association request IEs that the firmware copies into the event:
sinfo->assoc_req_ies = &event->data[len]; len = (u8 *)sinfo->assoc_req_ies - (u8 *)&event->frame_control; sinfo->assoc_req_ies_len = le16_to_cpu(event->len) - (u16)len;
event->len is supplied by the device firmware and is never validated, and the subtraction is unchecked. assoc_req_ies points into adapter->event_body[MAX_EVENT_SIZE], a fixed-size array embedded in the kmalloc()'d struct mwifiex_adapter.
On the ap_11n_enabled path mwifiex_set_sta_ht_cap() walks these IEs with cfg80211_find_ie(), whose for_each_element() loop dereferences each element header. A firmware-reported event->len larger than the bytes actually received makes assoc_req_ies_len describe IEs that extend past event_body, so the walk reads out of the adapter slab object, a slab-out-of-bounds read (KASAN: slab-out-of-bounds in cfg80211_find_ie). An event->len smaller than the header instead makes the int subtraction negative, which wraps to a huge size_t when stored in assoc_req_ies_len. The same length is handed to cfg80211_new_sta(), so a more modest over-claim can also copy stale event_body bytes into the NL80211_CMD_NEW_STATION notification.
A malicious or malfunctioning mwifiex device (USB/SDIO/PCIe) can deliver such an event while the interface is in AP/uAP mode.
Validate event->len before use: reject a length that underflows the header or that would place the IEs outside the event_body[] buffer the event was copied into. event->len here is struct mwifiex_assoc_event.len, a payload field internal to this event, not the transport frame length, so it is validated in this handler rather than at the generic MWIFIEX_TYPE_EVENT receive path, which only sees the event cause and the transport frame length. The bound is against event_body[MAX_EVENT_SIZE] rather than the actually-received length because the transports store the event differently (USB and SDIO leave the 4-byte event header in event_skb, PCIe strips it via skb_pull), whereas event_body is the single fixed buffer all of them copy the event into. This is the event-path analogue of the receive-path bounds checks added in commit 119585281617 ("wifi: mwifiex: Fix OOB and integer underflow when rx packets").
--- .../net/wireless/marvell/mwifiex/uap_event.c | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-)
drivers/net/wireless/marvell/mwifiex/uap_event.c +22 -2
@@ -123,11 +123,31 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv) len =ETH_ALEN ;if (len !=-1 ) { +u16 evt_len =le16_to_cpu (event->len); + sinfo->assoc_req_ies = &event->data[len]; len = (u8 *)sinfo->assoc_req_ies - (u8 *)&event->frame_control; - sinfo->assoc_req_ies_len = -le16_to_cpu (event->len) - (u16 )len; + +/* +* event->len is reported by the device firmware +* and is not otherwise validated. Reject a +* length that underflows the header, or that +* would place the association request IEs +* outside the fixed-size event_body[] buffer the +* event was copied into; otherwise the IE walk +* in mwifiex_set_sta_ht_cap() reads past +* event_body and out of the adapter slab object. +*/ +if (evt_len < len || + (u8 *)&event->frame_control + evt_len > + adapter->event_body +MAX_EVENT_SIZE ) { +mwifiex_dbg (adapter,ERROR , +"invalid STA assoc event length\n" ); +kfree (sinfo); +return -1 ; + } + sinfo->assoc_req_ies_len = evt_len - (u16 )len; } } cfg80211_new_sta(priv->netdev->ieee80211_ptr, event->sta_addr,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 250/744 iommu/amd: Bound the early ACPI HID map
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pengpeng Hou <[email protected]>
[ Upstream commit fb80117fddb5b477218dc99bb53911b72c3847f8 ]
The ivrs_acpihid command-line parser appends entries to a fixed four-element early_acpihid_map array. Unlike the sibling IOAPIC and HPET parsers, it does not reject a fifth entry before incrementing the map size.
Check the capacity at the common found label before parsing the HID and UID or writing the entry.
--- drivers/iommu/amd/init.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/iommu/amd/init.c +6 -0
@@ -3872,6 +3872,12 @@ static int __init parse_ivrs_acpihid(char *str)return 1 ; found: +if (early_acpihid_map_size ==EARLY_MAP_SIZE ) { +pr_err ("Early ACPI HID map overflow - ignoring ivrs_acpihid%s\n" , + str); +return 1 ; + } + p = acpiid; hid =strsep (&p,":" ); uid = p;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 251/744 iommu/intel: Fix out-of-bounds memset in dmar_latency_disable()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li RongQing <[email protected]>
[ Upstream commit 754f8efe45f87e3a9c6871b645b2f9d46d1b407b ]
dmar_latency_disable() intends to zero out only the single latency_statistic entry for the given type, but the memset size was computed as sizeof(*lstat) * DMAR_LATENCY_NUM, which clears the entire array starting from &lstat[type].
When type > 0, this writes beyond the end of the allocated array, corrupting adjacent memory.
Fix by using sizeof(*lstat) to clear only the target entry.
--- drivers/iommu/intel/perf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/iommu/intel/perf.c +1 -1
@@ -63,7 +63,7 @@ void dmar_latency_disable(struct intel_iommu *iommu, enum latency_type type)return ;spin_lock_irqsave (&latency_lock, flags); -memset (&lstat[type],0 ,sizeof (*lstat) *DMAR_LATENCY_NUM ); +memset (&lstat[type],0 ,sizeof (*lstat));spin_unlock_irqrestore (&latency_lock, flags); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 252/744 wifi: mac80211: recalculate TIM when a station enters power save
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Andrew Pope <[email protected]>
[ Upstream commit a007a384c9eb17610f53a53e2f59944c31f1565a ]
When an AP buffers frames for a station on its per-station TXQs and the station subsequently enters power save, sta_ps_start() records the buffered TIDs in txq_buffered_tids but does not update the TIM. The station's TIM bit is only ever set when a further frame is buffered while the station is already asleep (ieee80211_tx_h_unicast_ps_buf() -> sta_info_recalc_tim()).
If no further downlink frame arrives for that station the beacon TIM never advertises the buffered traffic. A station relying on the TIM then remains in doze indefinitely on top of a non-empty queue. Its TXQs were removed from the scheduler's active list at PS entry, nothing pages it, and the flow deadlocks until an unrelated event wakes the station.
Recalculate the TIM at the end of sta_ps_start(), so traffic already buffered at PS entry is advertised immediately. sta_info_recalc_tim() already consults txq_buffered_tids, which is updated above, and is safe in this context (it is already called from equivalent paths such as the tx handlers and ieee80211_handle_filtered_frame()).
--- net/mac80211/rx.c | 2 ++ 1 file changed, 2 insertions(+)
net/mac80211/rx.c +2 -0
@@ -1717,6 +1717,8 @@ static void sta_ps_start(struct sta_info *sta)else clear_bit (tid, &sta->txq_buffered_tids); } + +sta_info_recalc_tim (sta); }static void sta_ps_end (struct sta_info *sta)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 253/744 pds_core: reject component parameter in legacy firmware update
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <[email protected]>
[ Upstream commit 7be2552e601c247a328a5aba6fc06ac844b94a16 ]
The legacy firmware update path does not support per-component updates. If a user specifies a component parameter with devlink flash, reject the request with -EOPNOTSUPP rather than silently ignoring the component parameter and flashing the entire firmware image.
--- drivers/net/ethernet/amd/pds_core/devlink.c | 6 ++++++ 1 file changed, 6 insertions(+)
drivers/net/ethernet/amd/pds_core/devlink.c +6 -0
@@ -90,6 +90,12 @@ int pdsc_dl_flash_update(struct devlink *dl, {struct pdsc *pdsc =devlink_priv (dl); +if (params->component) { +NL_SET_ERR_MSG_MOD (extack, +"Component update not supported by this device" ); +return -EOPNOTSUPP ; + } +return pdsc_firmware_update (pdsc, params->fw, extack); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 254/744 arm64: Correct value returned by ESR_ELx_FSC_ADDRSZ_nL()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Steven Price <[email protected]>
[ Upstream commit b877075d0baa22c225842c2f19e3ea0a9cbcbe39 ]
Address size fault, level -1 is encoded as 0b101001 or 0x29 according to the Arm ARM. Correct the value to match the spec. This also matches the offset of "level -1 address size fault" in the fault_info array in fault.c.
--- arch/arm64/include/asm/esr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/include/asm/esr.h +1 -1
@@ -131,7 +131,7 @@* Annoyingly, the negative levels for Address size faults aren't laid out * contiguously (or in the desired order) */ -#define ESR_ELx_FSC_ADDRSZ_nL (n) ((n) == -1 ? 0x25 : 0x2C) +#define ESR_ELx_FSC_ADDRSZ_nL (n) ((n) == -1 ? 0x29 : 0x2C)#define ESR_ELx_FSC_ADDRSZ_L (n) ((n) < 0 ? ESR_ELx_FSC_ADDRSZ_nL(n) : \ (ESR_ELx_FSC_ADDRSZ + (n)))
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 255/744 arm64/mm: Check the requested PFN range during memory removal
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Richard Cheng <[email protected]>
[ Upstream commit 285f90a4d1141c7594f2368e19cbb307388eff30 ]
prevent_memory_remove_notifier() advances pfn while scanning the requested range for early memory. When the loop completes, pfn is at or beyond end_pfn. Passing it to can_unmap_without_split() therefore checks a range after the one being offlined.
Consequently, a valid request can be rejected based on the following range, while a request that would split a leaf mapping can be accepted if the shifted range can be unmapped without a split. This was observed with CXL DAX memory, where the final memory block was incorrectly allowed to be offlined.
Pass arg->start_pfn into can_unmap_without_split() so it checks the requested range.
--- arch/arm64/mm/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
arch/arm64/mm/mmu.c +1 -1
@@ -2201,7 +2201,7 @@ static int prevent_memory_remove_notifier(struct notifier_block *nb, } } -if (!can_unmap_without_split (pfn, arg->nr_pages)) +if (!can_unmap_without_split (arg->start_pfn, arg->nr_pages))return NOTIFY_BAD ;return NOTIFY_OK ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 256/744 amd-xgbe: fix MAC_AUTO_SW handling in CL37 AN
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Prashanth Kumar KR <[email protected]>
[ Upstream commit 4bf22afe53a1de4b44b04cf677fd5199089cbdff ]
MAC_AUTO_SW (VR_MII_DIG_CTRL1 bit 9) enables automatic XPCS speed mode switching after CL37 auto-negotiation and is only meaningful in SGMII MAC mode. The original code unconditionally set this bit on every call to xgbe_an37_set(), including when called from xgbe_an37_disable() with enable=false. This left MAC_AUTO_SW=1 after AN was disabled, causing the XPCS to autonomously switch speed from stale AN state during subsequent mode changes, breaking SGMII speed negotiation on 1G copper SFP modules.
Patrick: This was breaking negotiation for all 1G SFP modules, not just copper modules.
--- drivers/net/ethernet/amd/xgbe/xgbe-mdio.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-)
drivers/net/ethernet/amd/xgbe/xgbe-mdio.c +8 -3
@@ -267,9 +267,14 @@ static void xgbe_an37_set(struct xgbe_prv_data *pdata, bool enable,XMDIO_WRITE (pdata,MDIO_MMD_VEND2 ,MDIO_CTRL1 , reg); - reg =XMDIO_READ (pdata,MDIO_MMD_VEND2 ,MDIO_PCS_DIG_CTRL ); - reg |=XGBE_VEND2_MAC_AUTO_SW ; -XMDIO_WRITE (pdata,MDIO_MMD_VEND2 ,MDIO_PCS_DIG_CTRL , reg); +if (pdata->an_mode ==XGBE_AN_MODE_CL37_SGMII ) { + reg =XMDIO_READ (pdata,MDIO_MMD_VEND2 ,MDIO_PCS_DIG_CTRL ); +if (enable) + reg |=XGBE_VEND2_MAC_AUTO_SW ; +else + reg &= ~XGBE_VEND2_MAC_AUTO_SW ; +XMDIO_WRITE (pdata,MDIO_MMD_VEND2 ,MDIO_PCS_DIG_CTRL , reg); + } }static void xgbe_an37_restart (struct xgbe_prv_data *pdata)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 257/744 soreuseport: Clear sk_reuseport_cb before failure in sk_clone().
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 98da8ce87dd561f08fbe44f75865edc5d9b2ba5f ]
When sk_clone() fails, sk_destruct() is called for the new socket.
If the parent socket has sk->sk_reuseport_cb, the child will call reuseport_detach_sock() for the reuseport group.
Let's clear sk->sk_reuseport_cb before any failure path in sk_clone().
Note that this was not a problem before the cited commit because reuseport_detach_sock() did nothing if the socket was not found in the reuseport array.
--- net/core/sock.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/core/sock.c +2 -2
@@ -2547,6 +2547,8 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority,cgroup_sk_clone (&newsk->sk_cgrp_data); +RCU_INIT_POINTER (newsk->sk_reuseport_cb,NULL ); +rcu_read_lock (); filter =rcu_dereference (sk->sk_filter);if (filter !=NULL )
@@ -2569,8 +2571,6 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority, goto free; } -RCU_INIT_POINTER (newsk->sk_reuseport_cb,NULL ); -if (bpf_sk_storage_clone (sk, newsk)) goto free;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 258/744 net: Call net_enable_timestamp() before failure in sk_clone().
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit d50557779257a00162411e3048d82971ff1f644c ]
When sk_clone() fails, sk_destruct() is called for the new socket.
If the parent socket has SK_FLAGS_TIMESTAMP in sk->sk_flags, net_disable_timestamp() is called for the child socket even though net_enable_timestamp() is not called for it.
Let's call net_enable_timestamp() before any failure path in sk_clone().
--- net/core/sock.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/core/sock.c +3 -3
@@ -2549,6 +2549,9 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority,RCU_INIT_POINTER (newsk->sk_reuseport_cb,NULL ); +if (sock_needs_netstamp (sk) && newsk->sk_flags &SK_FLAGS_TIMESTAMP ) +net_enable_timestamp (); +rcu_read_lock (); filter =rcu_dereference (sk->sk_filter);if (filter !=NULL )
@@ -2598,9 +2601,6 @@ struct sock *sk_clone(const struct sock *sk, const gfp_t priority,if (newsk->sk_prot->sockets_allocated)sk_sockets_allocated_inc (newsk); - -if (sock_needs_netstamp (sk) && newsk->sk_flags &SK_FLAGS_TIMESTAMP ) -net_enable_timestamp (); out:return newsk; free:
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 259/744 geneve: fix hint header definition wrt endianness
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Antoine Tenart <[email protected]>
[ Upstream commit 751bfa982b4a6de8275a552804f6971adcf08473 ]
Bitfields are packed differently depending on the endianness, take it into account in the GRO hint header definition.
--- drivers/net/geneve.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-)
drivers/net/geneve.c +10 -1
@@ -43,8 +43,17 @@ MODULE_PARM_DESC(log_ecn_error, "Log packets received with corrupted ECN");#define GENEVE_OPT_GRO_HINT_LEN 1struct geneve_opt_gro_hint { +#if defined(__LITTLE_ENDIAN_BITFIELD)u8 inner_proto_id:2 , - nested_is_v6:1 ; + nested_is_v6:1 , + rsvd:5 ; +#elif defined(__BIG_ENDIAN_BITFIELD) +u8 rsvd:5 , + nested_is_v6:1 , + inner_proto_id:2 ; +#else +#error "Please fix <asm/byteorder.h>" +#endif u8 nested_nh_offset;u8 nested_tp_offset;u8 nested_hdr_len;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 260/744 geneve: ensure the skb is writable before fixing its headers
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Antoine Tenart <[email protected]>
[ Upstream commit 447ec540233c60d6af4d68a164a5bc8ce7e975c1 ]
Make sure the IPv4/6 and UDP headers are writable before fixing them up in geneve_post_decap_hint. As skb_ensure_writable can reallocate the skb linear area, reload the GRO hint header pointer and only set the IPv4/6 header ones after the call.
--- drivers/net/geneve.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
drivers/net/geneve.c +11 -2
@@ -585,6 +585,7 @@ static int geneve_post_decap_hint(const struct sock *sk, struct sk_buff *skb,struct iphdr *iph;struct udphdr *uh;__be16 p; +int err; hint_off =geneve_sk_gro_hint_off (sk, *geneveh, &p, &len);if (!hint_off)
@@ -609,12 +610,20 @@ static int geneve_post_decap_hint(const struct sock *sk, struct sk_buff *skb, !geneve_opt_gro_hint_validate(skb->data, gro_hint)))return -EINVAL ; - ipv6h = (void *)skb->data + gro_hint->nested_nh_offset; - iph = (struct iphdr *)ipv6h; total_len = skb->len - gro_hint->nested_nh_offset;if (total_len >=GRO_LEGACY_MAX_SIZE )return -E2BIG ; + err =skb_ensure_writable (skb, gro_hint->nested_tp_offset +sizeof (*uh)); +if (unlikely (err)) +return err; + + *geneveh =geneve_hdr (skb); + gro_hint =geneve_opt_gro_hint (*geneveh, hint_off); + + ipv6h = (void *)skb->data + gro_hint->nested_nh_offset; + iph = (struct iphdr *)ipv6h; +/* * After stripping the outer encap, the packet still carries a * tunnel encapsulation: the nested one.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 261/744 tipc: serialize udp bearer replicast list updates
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Weiming Shi <[email protected]>
[ Upstream commit 350e592ff4e30e48ffb55e142d11a73e63f4869c ]
tipc_udp_rcast_add() and cleanup_bearer() both update ub->rcast.list with list_add_rcu() / list_del_rcu(), but nothing serializes them. The add runs from the encap receive softirq (via tipc_udp_rcast_disc()) without rtnl_lock(), so it can race the cleanup delete and corrupt the list:
list_del corruption. prev->next should be ffff8880298d7ab8,
but was ffff88802449ad38. (prev=ffff888027e3ec98) kernel BUG at lib/list_debug.c:62! RIP: __list_del_entry_valid_or_report+0x17a/0x200 Workqueue: events cleanup_bearer Call Trace: cleanup_bearer (net/tipc/udp_media.c:811) process_one_work (kernel/workqueue.c:3302) worker_thread (kernel/workqueue.c:3466)
The bearer can be enabled from an unprivileged user namespace, as the TIPCv2 generic-netlink ops carry no GENL_ADMIN_PERM.
Add a spinlock to struct udp_bearer and take it around the list_add_rcu() in tipc_udp_rcast_add() and the list_del_rcu() loop in cleanup_bearer() so the two writers can no longer corrupt the list.
Reject a duplicate peer under the same lock before allocating, and remove tipc_udp_is_known_peer(). The old lockless pre-check in tipc_udp_rcast_disc() was racy: two softirqs discovering the same peer could both find it absent and add it twice.
cleanup_bearer() runs from a workqueue after tipc_udp_disable() clears the bearer's up bit, so an encap softirq can still reach tipc_udp_rcast_add() and add a peer after cleanup_bearer() has already emptied the list, leaking that entry when the bearer is freed. Mark the bearer disabled under rcast_lock once the list is emptied and refuse further additions.
--- net/tipc/udp_media.c | 56 +++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 29 deletions(-)
net/tipc/udp_media.c +27 -29
@@ -94,6 +94,8 @@ struct udp_replicast {* @ifindex: local address scope * @work: used to schedule deferred work on a bearer * @rcast: associated udp_replicast container +* @rcast_lock: serialize updates to @rcast.list against concurrent updaters +* @disabled: bearer is being torn down; reject further @rcast.list additions */ struct udp_bearer {struct tipc_bearer __rcu *bearer;
@@ -101,6 +103,8 @@ struct udp_bearer {u32 ifindex;struct work_struct work;struct udp_replicast rcast; +spinlock_t rcast_lock; +bool disabled; };static int tipc_udp_is_mcast_addr (struct udp_media_addr *addr)
@@ -278,26 +282,6 @@ static int tipc_udp_send_msg(struct net *net, struct sk_buff *skb,return err; } -static bool tipc_udp_is_known_peer (struct tipc_bearer *b, -struct udp_media_addr *addr) -{ -struct udp_replicast *rcast, *tmp; -struct udp_bearer *ub; - - ub =rcu_dereference_rtnl (b->media_ptr); -if (!ub) { -pr_err_ratelimited ("UDP bearer instance not found\n" ); -return false; - } - -list_for_each_entry_safe (rcast, tmp, &ub->rcast.list, list) { -if (!memcmp (&rcast->addr, addr,sizeof (struct udp_media_addr ))) -return true; - } - -return false; -} -static int tipc_udp_rcast_add (struct tipc_bearer *b,struct udp_media_addr *addr) {
@@ -308,16 +292,34 @@ static int tipc_udp_rcast_add(struct tipc_bearer *b,if (!ub)return -ENODEV ; +spin_lock_bh (&ub->rcast_lock); +if (ub->disabled) { +spin_unlock_bh (&ub->rcast_lock); +return 0 ; + } +list_for_each_entry (rcast, &ub->rcast.list, list) { +if (!memcmp (&rcast->addr, addr,sizeof (*addr))) { +spin_unlock_bh (&ub->rcast_lock); +return 0 ; + } + } + rcast =kmalloc_obj (*rcast,GFP_ATOMIC ); -if (!rcast) +if (!rcast) { +spin_unlock_bh (&ub->rcast_lock);return -ENOMEM ; + }if (dst_cache_init (&rcast->dst_cache,GFP_ATOMIC )) { +spin_unlock_bh (&ub->rcast_lock);kfree (rcast);return -ENOMEM ; }memcpy (&rcast->addr, addr,sizeof (struct udp_media_addr )); +list_add_rcu (&rcast->list, &ub->rcast.list); + b->bcast_addr.broadcast =TIPC_REPLICAST_SUPPORT ; +spin_unlock_bh (&ub->rcast_lock);if (ntohs (addr->proto) ==ETH_P_IP )pr_info ("New replicast peer: %pI4\n" , &rcast->addr.ipv4);
@@ -325,8 +327,6 @@ static int tipc_udp_rcast_add(struct tipc_bearer *b, else if (ntohs(addr->proto) == ETH_P_IPV6) pr_info("New replicast peer: %pI6\n", &rcast->addr.ipv6);#endif - b->bcast_addr.broadcast =TIPC_REPLICAST_SUPPORT ; -list_add_rcu (&rcast->list, &ub->rcast.list);return 0 ; }
@@ -361,9 +361,6 @@ static int tipc_udp_rcast_disc(struct tipc_bearer *b, struct sk_buff *skb)return 0 ; } -if (likely (tipc_udp_is_known_peer (b, &src))) -return 0 ; -return tipc_udp_rcast_add (b, &src); }
@@ -644,9 +641,6 @@ int tipc_udp_nl_bearer_add(struct tipc_bearer *b, struct nlattr *attr)return -EINVAL ; } -if (tipc_udp_is_known_peer (b, &addr)) -return 0 ; -return tipc_udp_rcast_add (b, &addr); }
@@ -679,6 +673,7 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,return -ENOMEM ;INIT_LIST_HEAD (&ub->rcast.list); +spin_lock_init (&ub->rcast_lock);if (!attrs[TIPC_NLA_BEARER_UDP_OPTS ]) goto err;
@@ -819,10 +814,13 @@ static void cleanup_bearer(struct work_struct *work)struct udp_replicast *rcast, *tmp;struct tipc_net *tn; +spin_lock_bh (&ub->rcast_lock);list_for_each_entry_safe (rcast, tmp, &ub->rcast.list, list) {list_del_rcu (&rcast->list);call_rcu_hurry (&rcast->rcu, rcast_free_rcu); } + ub->disabled = true; +spin_unlock_bh (&ub->rcast_lock); tn =tipc_net (sock_net (ub->sk));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 262/744 net: txgbe: fix heap overflow when reading module EEPROM
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenguang Zhao <[email protected]>
[ Upstream commit 6a905a71fd43ce8b45f05044b11491337f232c9d ]
txgbe_read_eeprom_hostif() always copies round_up(length, 4) bytes into the caller buffer, which ethtool allocates with exactly 'length' bytes. A non-4-aligned length therefore causes an out-of-bounds write. Copy only the remaining bytes on the final dword instead.
--- drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
drivers/net/ethernet/wangxun/txgbe/txgbe_aml.c +4 -2
@@ -96,11 +96,13 @@ int txgbe_read_eeprom_hostif(struct wx *wx, dword_len =round_up (length,4 ) >>2 ;for (i =0 ; i < dword_len; i++) { +u32 copy_len =min_t (u32,4 , length - i *4 ); + value =rd32a (wx,WX_FW2SW_MBOX , i + offset);le32_to_cpus (&value); -memcpy (data, &value,4 ); - data +=4 ; +memcpy (data, &value, copy_len); + data += copy_len; }return 0 ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 263/744 rds: Fix inet6_addr_lst NULL dereference when IPv6 is disabled
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ilia Gavrilov <[email protected]>
[ Upstream commit 9c805e592a29be9e4e61ff1bd567da04aa8fd6f9 ]
When booting with the 'ipv6.disable=1' parameter, inet6_addr_lst is never initialized because inet6_init() exits before addrconf_init() is called to initialize it. An attempt to bind an RDS socket to an ipv6 address results in a crash in __ipv6_chk_addr_and_flags()
KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] RIP: 0010:__ipv6_chk_addr_and_flags+0x1df/0x7e0 Call Trace: <TASK> ipv6_chk_addr+0x3b/0x50 rds_tcp_laddr_check+0x155/0x3b0 [rds_tcp] rds_trans_get_preferred+0x15d/0x2d0 [rds] ? trace_hardirqs_on+0x2d/0x110 rds_bind+0x1433/0x1d60 [rds] ? rds_remove_bound+0xd50/0xd50 [rds] ? aa_af_perm+0x250/0x250 ? __might_fault+0xde/0x190 ? __sys_bind+0x1dc/0x210 __sys_bind+0x1dc/0x210 ? __ia32_sys_socketpair+0x100/0x100 ? restore_fpregs_from_fpstate+0x53/0x100 __x64_sys_bind+0x73/0xb0 ? syscall_enter_from_user_mode+0x1c/0x50 do_syscall_64+0x34/0x80 entry_SYSCALL_64_after_hwframe+0x6e/0xd8 RIP: 0033:0x7f47f8269ea9 </TASK>
The following code reproduces the issue:
struct sockaddr_in6 addr;
s = socket(PF_RDS, SOCK_SEQPACKET, 0);
memset(&addr, 0, sizeof(addr));inet_pton(AF_INET6, ADDRESS, &addr.sin6_addr);
addr.sin6_family = AF_INET6;
addr.sin6_port = htons(PORT);
bind(s, &addr, sizeof(addr));
Found by InfoTeCS on behalf of Linux Verification Center (linuxtesting.org) with Syzkaller.
--- net/rds/ib.c | 4 ++++ net/rds/ib_cm.c | 4 ++++ net/rds/tcp.c | 8 +++++--- 3 files changed, 13 insertions(+), 3 deletions(-)
net/rds/ib.c +4 -0
@@ -429,6 +429,10 @@ static int rds_ib_laddr_check_cm(struct net *net, const struct in6_addr *addr, sa = (struct sockaddr *)&sin; }else {#if IS_ENABLED (CONFIG_IPV6 ) +if (!ipv6_mod_enabled ()) { + ret = -EADDRNOTAVAIL ; + goto out; + }memset (&sin6,0 ,sizeof (sin6)); sin6.sin6_family =AF_INET6 ; sin6.sin6_addr = *addr;
net/rds/ib_cm.c +4 -0
@@ -810,6 +810,10 @@ int rds_ib_cm_handle_connect(struct rdma_cm_id *cm_id, dp = event->param.conn.private_data;if (isv6) {#if IS_ENABLED (CONFIG_IPV6 ) +if (!ipv6_mod_enabled ()) { + err = -EOPNOTSUPP ; + goto out; + } dp_cmn = &dp->ricp_v6.dp_cmn; saddr6 = &dp->ricp_v6.dp_saddr; daddr6 = &dp->ricp_v6.dp_daddr;
net/rds/tcp.c +5 -3
@@ -347,9 +347,11 @@ int rds_tcp_laddr_check(struct net *net, const struct in6_addr *addr,rcu_read_unlock (); }#if IS_ENABLED (CONFIG_IPV6 ) - ret =ipv6_chk_addr (net, addr, dev,0 ); -if (ret) -return 0 ; +if (ipv6_mod_enabled ()) { + ret =ipv6_chk_addr (net, addr, dev,0 ); +if (ret) +return 0 ; + }#endif return -EADDRNOTAVAIL ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 264/744 net: txgbe: fix FDIR filter leak on remove
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenguang Zhao <[email protected]>
[ Upstream commit ecaa37826340520664a4e5522f803ff48fc3f564 ]
Perfect FDIR filters can be added while the interface is down and are kept on the software list for later restore. unregister_netdev() only calls ndo_stop when the device is up, so txgbe_fdir_filter_exit() in txgbe_close() is skipped in that case and the filters are leaked on driver remove. Free the filter list from txgbe_remove() as well.
--- drivers/net/ethernet/wangxun/txgbe/txgbe_main.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/wangxun/txgbe/txgbe_main.c +1 -0
@@ -951,6 +951,7 @@ static void txgbe_remove(struct pci_dev *pdev) netdev = wx->netdev;wx_disable_sriov (wx);unregister_netdev (netdev); +txgbe_fdir_filter_exit (wx);timer_shutdown_sync (&wx->service_timer);cancel_work_sync (&wx->service_task);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 265/744 sctp: fix auth_chunk_list capacity check in sctp_auth_ep_add_chunkid
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: HanQuan <[email protected]>
[ Upstream commit ff04b26794a16a8a879eb4fd2c02c2d6b03850e9 ]
sctp_auth_ep_add_chunkid() uses SCTP_NUM_CHUNK_TYPES (20) as the capacity limit for ep->auth_chunk_list, allowing it to hold up to 20 chunk entries (param_hdr.length up to 24). However, the copy destination asoc->c.auth_chunks in struct sctp_cookie is only SCTP_AUTH_MAX_CHUNKS (16) entries (20 bytes). When more than 16 chunks are added, sctp_association_init() memcpy overflows the destination by up to 4 bytes.
Fix by using SCTP_AUTH_MAX_CHUNKS as the capacity limit, matching the destination capacity.
--- net/sctp/auth.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sctp/auth.c +1 -1
@@ -672,7 +672,7 @@ int sctp_auth_ep_add_chunkid(struct sctp_endpoint *ep, __u8 chunk_id)/* Check if we can add this chunk to the array */ param_len =ntohs (p->param_hdr.length); nchunks = param_len -sizeof (struct sctp_paramhdr ); -if (nchunks ==SCTP_NUM_CHUNK_TYPES ) +if (nchunks ==SCTP_AUTH_MAX_CHUNKS )return -EINVAL ; p->chunks[nchunks] = chunk_id;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 266/744 pds_core: fix deadlock between reset thread and remove
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <[email protected]>
[ Upstream commit ab0eec0ff0a421737a37f510ceab5c6ea59cd05a ]
pci_reset_function() acquires device_lock before performing the reset. pdsc_remove() is called by the PCI core with device_lock already held. If pdsc_pci_reset_thread() is running when pdsc_remove() is called, destroy_workqueue() will block waiting for the work to complete, while the work is blocked waiting for device_lock - deadlock.
Use pci_try_reset_function() which uses pci_dev_trylock() internally. This acquires both the device lock and the PCI config access lock without blocking - if either lock is contended, it returns -EAGAIN immediately. This avoids the deadlock while also ensuring proper config space access serialization during the reset.
The pci_dev_get/put calls are also removed as they were unnecessary - the driver-owned workqueue is destroyed in pdsc_remove(), guaranteeing the work completes before remove returns. The PCI core holds its reference to pci_dev throughout the entire unbind sequence.
--- drivers/net/ethernet/amd/pds_core/core.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/net/ethernet/amd/pds_core/core.c +4 -3
@@ -602,9 +602,10 @@ void pdsc_pci_reset_thread(struct work_struct *work) struct pdsc *pdsc = container_of(work, struct pdsc, pci_reset_work);struct pci_dev *pdev = pdsc->pdev; -pci_dev_get (pdev); -pci_reset_function (pdev); -pci_dev_put (pdev); +/* Use try variant to avoid deadlock with pdsc_remove(). +* If lock is contended, the watchdog timer will retry. +*/ +pci_try_reset_function (pdev); }static void pdsc_check_pci_health (struct pdsc *pdsc)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 267/744 pds_core: fix use-after-free on workqueue during remove
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <[email protected]>
[ Upstream commit 0ad134881508c36b65c1a8864f8bec53adbd3327 ]
In pdsc_remove(), the workqueue is destroyed before pdsc_teardown() is called. This ordering allows two paths to queue work on the destroyed workqueue:
1. If pdsc_teardown() -> pdsc_devcmd_reset() times out, the error path in pdsc_devcmd_locked() queues health_work.
2. A NotifyQ event can trigger the ISR and queue work before free_irq() is called in pdsc_teardown().
Fix by moving destroy_workqueue() after pdsc_teardown() so the workqueue outlives every queuer; destroy_workqueue() then flushes any work still pending.
Draining the queued work also requires ordering the teardown so the resources that work touches are freed last:
- In pdsc_qcq_free(), after freeing the interrupt, cancel_work_sync()
the queue's work and only then clear qcq->intx, so
pdsc_process_adminq()'s read of qcq->intx for interrupt-credit
return cannot race with the clear.- Free adminqcq before notifyqcq: the shared adminq ISR is released when adminqcq is freed, and the adminq work accesses notifyqcq, so both must be stopped before notifyqcq is freed.
--- drivers/net/ethernet/amd/pds_core/core.c | 14 ++++++++++---- drivers/net/ethernet/amd/pds_core/main.c | 5 +++-- 2 files changed, 13 insertions(+), 6 deletions(-)
drivers/net/ethernet/amd/pds_core/core.c +10 -4
@@ -110,7 +110,6 @@ static void pdsc_qcq_intr_free(struct pdsc *pdsc, struct pdsc_qcq *qcq)return ;pdsc_intr_free (pdsc, qcq->intx); - qcq->intx =PDS_CORE_INTR_INDEX_NOT_ASSIGNED ; }static int pdsc_qcq_intr_alloc (struct pdsc *pdsc,struct pdsc_qcq *qcq)
@@ -145,6 +144,12 @@ void pdsc_qcq_free(struct pdsc *pdsc, struct pdsc_qcq *qcq)pdsc_qcq_intr_free (pdsc, qcq); +/* Drain any work queued by ISR before it was freed above */ +if (qcq->work.func) +cancel_work_sync (&qcq->work); + + qcq->intx =PDS_CORE_INTR_INDEX_NOT_ASSIGNED ; +if (qcq->q_base)dma_free_coherent (dev, qcq->q_size, qcq->q_base, qcq->q_base_pa);
@@ -304,8 +309,11 @@ int pdsc_qcq_alloc(struct pdsc *pdsc, unsigned int type, unsigned int index,static void pdsc_core_uninit (struct pdsc *pdsc) { -pdsc_qcq_free (pdsc, &pdsc->notifyqcq); +/* Free adminqcq first: its work accesses notifyqcq, so we must +* disable its IRQ and drain its work before freeing notifyqcq. +*/ pdsc_qcq_free (pdsc, &pdsc->adminqcq); +pdsc_qcq_free (pdsc, &pdsc->notifyqcq);if (pdsc->kern_dbpage) {iounmap (pdsc->kern_dbpage);
@@ -477,8 +485,6 @@ void pdsc_teardown(struct pdsc *pdsc, bool removing) {if (!pdsc->pdev->is_virtfn)pdsc_devcmd_reset (pdsc); -if (pdsc->adminqcq.work.func) -cancel_work_sync (&pdsc->adminqcq.work);pdsc_core_uninit (pdsc);
drivers/net/ethernet/amd/pds_core/main.c +3 -2
@@ -435,8 +435,6 @@ static void pdsc_remove(struct pci_dev *pdev)pdsc_auxbus_dev_del (pdsc, pdsc, &pdsc->padev);timer_shutdown_sync (&pdsc->wdtimer); -if (pdsc->wq) -destroy_workqueue (pdsc->wq);mutex_lock (&pdsc->config_lock);set_bit (PDSC_S_STOPPING_DRIVER , &pdsc->state);
@@ -444,6 +442,9 @@ static void pdsc_remove(struct pci_dev *pdev)pdsc_stop (pdsc);pdsc_teardown (pdsc,PDSC_TEARDOWN_REMOVING );mutex_unlock (&pdsc->config_lock); + +if (pdsc->wq) +destroy_workqueue (pdsc->wq);mutex_destroy (&pdsc->config_lock);mutex_destroy (&pdsc->devcmd_lock);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 268/744 pds_core: yield the CPU while waiting for the adminq to drain
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <[email protected]>
[ Upstream commit a11f0b8a204296fe7db9eaec53441012222cb004 ]
pdsc_adminq_wait_and_dec_once_unused() busy-waits for adminq_refcnt to drop to one:
while (!refcount_dec_if_one(&pdsc->adminq_refcnt)) cpu_relax();
The refcount is held by pdsc_adminq_post() for the duration of an in-flight command, which can wait up to devcmd_timeout seconds (PDS_CORE_DEVCMD_TIMEOUT is 5) for the hardware to complete. cpu_relax() is not a reschedule point, so on a non-preemptible kernel this loop can spin on the CPU for several seconds, starving other tasks on that core.
Add cond_resched() to the loop so the waiter yields to other runnable tasks while it polls, keeping cpu_relax() as the busy-wait hint between checks.
--- drivers/net/ethernet/amd/pds_core/core.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/amd/pds_core/core.c +1 -0
@@ -535,6 +535,7 @@ static void pdsc_adminq_wait_and_dec_once_unused(struct pdsc *pdsc)dev_dbg_ratelimited (pdsc->dev,"%s: adminq in use\n" , __func__);cpu_relax (); +cond_resched (); } }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 269/744 pds_core: order completion reads after the ownership check
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <[email protected]>
[ Upstream commit dd6b1cc748cd28147c113f9daa76393916ad9494 ]
pdsc_process_adminq() and pdsc_process_notifyq() decide a completion is valid from its ownership field - the color bit for the adminq, the event id for the notifyq - then read the rest of the descriptor, with no barrier in between.
On a weakly ordered architecture the CPU may read the payload first. Add dma_rmb() between the ownership read and the payload reads.
--- drivers/net/ethernet/amd/pds_core/adminq.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-)
drivers/net/ethernet/amd/pds_core/adminq.c +11 -1
@@ -18,7 +18,13 @@ static int pdsc_process_notifyq(struct pdsc_qcq *qcq) comp = cq_info->comp; eid =le64_to_cpu (comp->event.eid);while (eid > pdsc->last_eid) { -u16 ecode =le16_to_cpu (comp->event.ecode); +u16 ecode; + +/* Order the payload read after the event id, the field the +* driver uses to detect a new completion. +*/ +dma_rmb (); + ecode =le16_to_cpu (comp->event.ecode);switch (ecode) {case PDS_EVENT_LINK_CHANGE :
@@ -101,6 +107,10 @@ void pdsc_process_adminq(struct pdsc_qcq *qcq)spin_lock_irqsave (&pdsc->adminq_lock, irqflags); comp = cq->info[cq->tail_idx].comp;while (pdsc_color_match (comp->color, cq->done_color)) { +/* Order the payload reads after the color bit, the field the +* driver uses to detect a new completion. +*/ +dma_rmb (); q_info = &q->info[q->tail_idx]; q->tail_idx = (q->tail_idx +1 ) & (q->num_descs -1 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 270/744 pds_core: fix auxiliary device add/del races
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <[email protected]>
[ Upstream commit bfa33cd513c7ceb93c5a4c30e5662acd73c0a916 ]
Two paths add or delete the same slot (pf->vfs[vf_id].padev): a VF's pdsc_reset_done() and the PF's devlink enable_vnet/disable_vnet handler. They serialize on config_lock, but neither guards the slot under it correctly.
add() registers and stores a new auxiliary device without first checking the slot, so a second add of an already-populated slot leaks the first device. del() makes that check outside config_lock, so two concurrent dels can both pass it; the first clears the slot, and the second dereferences a NULL pointer.
Check and update the slot under config_lock in both paths.
--- drivers/net/ethernet/amd/pds_core/auxbus.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-)
drivers/net/ethernet/amd/pds_core/auxbus.c +14 -3
@@ -177,17 +177,21 @@ void pdsc_auxbus_dev_del(struct pdsc *cf, struct pdsc *pf, {struct pds_auxiliary_dev *padev; -if (!*pd_ptr) -return ; -mutex_lock (&pf->config_lock); +/* A concurrent del may have already torn this device down and +* cleared it. +*/ padev = *pd_ptr; +if (!padev) + goto out_unlock; +pds_client_unregister (pf, padev->client_id);auxiliary_device_delete (&padev->aux_dev);auxiliary_device_uninit (&padev->aux_dev); *pd_ptr =NULL ; +out_unlock:mutex_unlock (&pf->config_lock); }
@@ -210,6 +214,13 @@ int pdsc_auxbus_dev_add(struct pdsc *cf, struct pdsc *pf,mutex_lock (&pf->config_lock); +/* Nothing to do if the aux device is already present. This also +* guards against a second add overwriting *pd_ptr and leaking the +* first, symmetric with the check in pdsc_auxbus_dev_del(). +*/ +if (*pd_ptr) + goto out_unlock; + mask =BIT_ULL (PDSC_S_FW_DEAD ) |BIT_ULL (PDSC_S_STOPPING_DRIVER );if (cf->state & mask) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 271/744 pds_core: check for workqueue allocation failure
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikhil P. Rao <[email protected]>
[ Upstream commit 3a660ca49e2c3807bffe0519db3cff677a5906e0 ]
pdsc_init_pf() does not check whether create_singlethread_workqueue() succeeded.
Fail probe on failure. The workqueue is set up before the timer and mutexes, so its failure path must unwind only the earlier setup.
--- drivers/net/ethernet/amd/pds_core/main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-)
drivers/net/ethernet/amd/pds_core/main.c +7 -2
@@ -238,6 +238,10 @@ static int pdsc_init_pf(struct pdsc *pdsc)/* General workqueue and timer, but don't start timer yet */ snprintf (wq_name,sizeof (wq_name),"%s.%d" ,PDS_CORE_DRV_NAME , pdsc->uid); pdsc->wq =create_singlethread_workqueue (wq_name); +if (!pdsc->wq) { + err = -ENOMEM ; + goto err_out_unmap_bars; + }INIT_WORK (&pdsc->health_work, pdsc_health_thread);INIT_WORK (&pdsc->pci_reset_work, pdsc_pci_reset_thread);timer_setup (&pdsc->wdtimer, pdsc_wdtimer_cb,0 );
@@ -253,7 +257,7 @@ static int pdsc_init_pf(struct pdsc *pdsc) err =pdsc_setup (pdsc,PDSC_SETUP_INIT );if (err) {mutex_unlock (&pdsc->config_lock); - goto err_out_unmap_bars; + goto err_out_shutdown_timer; } err =pdsc_start (pdsc);
@@ -305,13 +309,14 @@ static int pdsc_init_pf(struct pdsc *pdsc)pdsc_stop (pdsc); err_out_teardown:pdsc_teardown (pdsc,PDSC_TEARDOWN_REMOVING ); -err_out_unmap_bars: +err_out_shutdown_timer:timer_shutdown_sync (&pdsc->wdtimer);if (pdsc->wq)destroy_workqueue (pdsc->wq);mutex_destroy (&pdsc->config_lock);mutex_destroy (&pdsc->devcmd_lock);pci_free_irq_vectors (pdsc->pdev); +err_out_unmap_bars:pdsc_unmap_bars (pdsc); err_out_release_regions:pci_release_regions (pdsc->pdev);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 272/744 accel: ethosu: Fix element size accounting for cmd stream validation
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rob Herring (Arm) <[email protected]>
[ Upstream commit 18a551482a4a326790698b273e76d7575a51a57d ]
There are 2 issues with the element size handling in the command stream validation which result in too small of a size calculated when the element size is 16/32/64 bits.
For NHWC format, the element size is simply missing from the calculation.
The bitfield for the element size is different between IFM/IFM2 and OFM. IFM and IFM2 encode the precision in parameter bits 2:3, while OFM uses bits 1:2.
--- drivers/accel/ethosu/ethosu_gem.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-)
drivers/accel/ethosu/ethosu_gem.c +10 -9
@@ -194,7 +194,7 @@ static u64 dma_length(struct ethosu_validated_cmdstream_info *info,static u64 feat_matrix_length (struct ethosu_validated_cmdstream_info *info,struct feat_matrix *fm, -u32 x,u32 y,u32 c) +u32 x,u32 y,u32 c,bool ofm) {u32 element_size, storage = fm->precision >>14 ;int tile =0 ;
@@ -231,10 +231,11 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,switch ((fm->precision >>6 ) &0x3 ) {// format case 0 ://nhwc: - addr += x * fm->stride_x + c; + element_size =BIT ((fm->precision >> (ofm ?1 :2 )) &0x3 ); + addr += x * fm->stride_x + c * element_size;break ;case 1 ://nhcwb16: - element_size =BIT ((fm->precision >>1 ) &0x3 ); + element_size =BIT ((fm->precision >> (ofm ?1 :2 )) &0x3 ); addr += (c /16 ) * fm->stride_c + (16 * x + (c &0xf )) * element_size;break ;
@@ -268,7 +269,7 @@ static int calc_sizes(struct drm_device *ddev,return -EINVAL ; len =feat_matrix_length (info, &st->ifm, ifm_width, - ifm_height, st->ifm.depth); + ifm_height, st->ifm.depth, false);dev_dbg (ddev->dev,"op %d: IFM:%d:0x%llx-0x%llx\n" , op, st->ifm.region, st->ifm.base[0 ], len);if (len ==U64_MAX )
@@ -277,7 +278,7 @@ static int calc_sizes(struct drm_device *ddev,if (ifm2) { len =feat_matrix_length (info, &st->ifm2, st->ifm.depth, -0 , st->ofm.depth); +0 , st->ofm.depth, false);dev_dbg (ddev->dev,"op %d: IFM2:%d:0x%llx-0x%llx\n" , op, st->ifm2.region, st->ifm2.base[0 ], len);if (len ==U64_MAX )
@@ -309,7 +310,7 @@ static int calc_sizes(struct drm_device *ddev, } len =feat_matrix_length (info, &st->ofm, st->ofm.width, - st->ofm.height[2 ], st->ofm.depth); + st->ofm.height[2 ], st->ofm.depth, true);dev_dbg (ddev->dev,"op %d: OFM:%d:0x%llx-0x%llx\n" , op, st->ofm.region, st->ofm.base[0 ], len);if (len ==U64_MAX )
@@ -333,7 +334,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev, depth = st->ifm.broadcast &0x4 ?0 : st->ofm.depth; len =feat_matrix_length (info, &st->ifm, width, - height, depth); + height, depth, false);dev_dbg (ddev->dev,"op %d: IFM:%d:0x%llx-0x%llx\n" , op, st->ifm.region, st->ifm.base[0 ], len);if (len ==U64_MAX )
@@ -346,7 +347,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev, depth = st->ifm2.broadcast &0x4 ?0 : st->ofm.depth; len =feat_matrix_length (info, &st->ifm2, width, - height, depth); + height, depth, false);dev_dbg (ddev->dev,"op %d: IFM2:%d:0x%llx-0x%llx\n" , op, st->ifm2.region, st->ifm2.base[0 ], len);if (len ==U64_MAX )
@@ -354,7 +355,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev, } len =feat_matrix_length (info, &st->ofm, st->ofm.width, - st->ofm.height[2 ], st->ofm.depth); + st->ofm.height[2 ], st->ofm.depth, true);dev_dbg (ddev->dev,"op %d: OFM:%d:0x%llx-0x%llx\n" , op, st->ofm.region, st->ofm.base[0 ], len);if (len ==U64_MAX )
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 273/744 accel: ethosu: Handle U85 internal chaining buffer
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rob Herring (Arm) <[email protected]>
[ Upstream commit 6b7e0066294d23ad1fd37f4326c32e8090fb8b65 ]
The Ethos-U85 supports an internal chaining buffer as temporary storage between some operations. When chaining is activated, the IFM/OFM region setting selects a chaining buffer rather than a region, and the IFM/OFM base addresses don't matter. In this case, the feature matrix size calculations should be skipped. Otherwise, the command stream will be intermittently rejected depending on prior feature matrix base addresses.
--- drivers/accel/ethosu/ethosu_gem.c | 35 +++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 9 deletions(-)
drivers/accel/ethosu/ethosu_gem.c +26 -9
@@ -192,7 +192,15 @@ static u64 dma_length(struct ethosu_validated_cmdstream_info *info,return len; } -static u64 feat_matrix_length (struct ethosu_validated_cmdstream_info *info, +static bool feat_matrix_chained (struct ethosu_device *edev,struct feat_matrix *fm) +{ +u32 storage = fm->precision >>14 ; + +return !ethosu_is_u65 (edev) && storage ==2 ; +} + +static u64 feat_matrix_length (struct ethosu_device *edev, +struct ethosu_validated_cmdstream_info *info,struct feat_matrix *fm,u32 x,u32 y,u32 c,bool ofm) {
@@ -203,6 +211,9 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info,if (fm->region <0 )return U64_MAX ; +if (feat_matrix_chained (edev, fm)) +return 0 ; +switch (storage) {case 0 :if (x >= fm->width0 +1 ) {
@@ -223,6 +234,8 @@ static u64 feat_matrix_length(struct ethosu_validated_cmdstream_info *info, tile =1 ; }break ; +default : +return U64_MAX ; }if (fm->base[tile] ==U64_MAX )return U64_MAX ;
@@ -251,6 +264,7 @@ static int calc_sizes(struct drm_device *ddev, u16 op, struct cmd_state *st, bool ifm, bool ifm2, bool weight, bool scale) { + struct ethosu_device *edev = to_ethosu_device(ddev);u64 len;if (ifm) {
@@ -268,7 +282,7 @@ static int calc_sizes(struct drm_device *ddev,if (ifm_height <0 || ifm_width <0 )return -EINVAL ; - len =feat_matrix_length (info, &st->ifm, ifm_width, + len =feat_matrix_length (edev, info, &st->ifm, ifm_width, ifm_height, st->ifm.depth, false);dev_dbg (ddev->dev,"op %d: IFM:%d:0x%llx-0x%llx\n" , op, st->ifm.region, st->ifm.base[0 ], len);
@@ -277,7 +291,7 @@ static int calc_sizes(struct drm_device *ddev, }if (ifm2) { - len =feat_matrix_length (info, &st->ifm2, st->ifm.depth, + len =feat_matrix_length (edev, info, &st->ifm2, st->ifm.depth,0 , st->ofm.depth, false);dev_dbg (ddev->dev,"op %d: IFM2:%d:0x%llx-0x%llx\n" , op, st->ifm2.region, st->ifm2.base[0 ], len);
@@ -309,13 +323,14 @@ static int calc_sizes(struct drm_device *ddev, st->scale[0].base + st->scale[0].length); } - len =feat_matrix_length (info, &st->ofm, st->ofm.width, + len =feat_matrix_length (edev, info, &st->ofm, st->ofm.width, st->ofm.height[2 ], st->ofm.depth, true);dev_dbg (ddev->dev,"op %d: OFM:%d:0x%llx-0x%llx\n" , op, st->ofm.region, st->ofm.base[0 ], len);if (len ==U64_MAX )return -EINVAL ; - info->output_region[st->ofm.region] = true; +if (!feat_matrix_chained (edev, &st->ofm)) + info->output_region[st->ofm.region] = true;return 0 ; }
@@ -325,6 +340,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev, u16 op, struct cmd_state *st, bool ifm, bool ifm2) { + struct ethosu_device *edev = to_ethosu_device(ddev);u32 height, width, depth;u64 len;
@@ -333,7 +349,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev, width = st->ifm.broadcast &0x2 ?0 : st->ofm.width; depth = st->ifm.broadcast &0x4 ?0 : st->ofm.depth; - len =feat_matrix_length (info, &st->ifm, width, + len =feat_matrix_length (edev, info, &st->ifm, width, height, depth, false);dev_dbg (ddev->dev,"op %d: IFM:%d:0x%llx-0x%llx\n" , op, st->ifm.region, st->ifm.base[0 ], len);
@@ -346,7 +362,7 @@ static int calc_sizes_elemwise(struct drm_device *ddev, width = st->ifm2.broadcast &0x2 ?0 : st->ofm.width; depth = st->ifm2.broadcast &0x4 ?0 : st->ofm.depth; - len =feat_matrix_length (info, &st->ifm2, width, + len =feat_matrix_length (edev, info, &st->ifm2, width, height, depth, false);dev_dbg (ddev->dev,"op %d: IFM2:%d:0x%llx-0x%llx\n" , op, st->ifm2.region, st->ifm2.base[0 ], len);
@@ -354,13 +370,14 @@ static int calc_sizes_elemwise(struct drm_device *ddev,return -EINVAL ; } - len =feat_matrix_length (info, &st->ofm, st->ofm.width, + len =feat_matrix_length (edev, info, &st->ofm, st->ofm.width, st->ofm.height[2 ], st->ofm.depth, true);dev_dbg (ddev->dev,"op %d: OFM:%d:0x%llx-0x%llx\n" , op, st->ofm.region, st->ofm.base[0 ], len);if (len ==U64_MAX )return -EINVAL ; - info->output_region[st->ofm.region] = true; +if (!feat_matrix_chained (edev, &st->ofm)) + info->output_region[st->ofm.region] = true;return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 274/744 sctp: validate stream count in sctp_process_strreset_inreq()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang (Microsoft) <[email protected]>
[ Upstream commit 18ae07691d43183d270de8be9dc8e027906015d9 ]
When processing a RESET_IN_REQUEST from a peer, sctp_process_strreset_inreq() derives the stream count from the parameter length but does not check whether the resulting RESET_OUT_REQUEST would exceed SCTP_MAX_CHUNK_LEN.
The OUT request header (sctp_strreset_outreq, 16 bytes) is 8 bytes larger than the IN request header (sctp_strreset_inreq, 8 bytes). Generally, the IP payload is bounded to 65535 bytes, so the stream list cannot be large enough to trigger the overflow. However, on interfaces with MTU > 65535 (e.g., loopback with IPv6 jumbograms), a stream list that fits within the incoming IN parameter can cause a __u16 overflow in sctp_make_strreset_req() when computing the OUT request size, leading to an undersized skb allocation and a kernel BUG:
net/core/skbuff.c:207 skb_panic
net/core/skbuff.c:2625 skb_put
net/sctp/sm_make_chunk.c:1535 sctp_addto_chunk net/sctp/sm_make_chunk.c:3695 sctp_make_strreset_req
net/sctp/stream.c:655 sctp_process_strreset_inreq
The local setsockopt path validates the generated reset request size. However, for an incoming-only reset, it accounts for the smaller IN request even though the peer must generate an OUT request with the same stream list. Such a request cannot be completed successfully by the peer.
Reject peer IN requests whose corresponding OUT request would exceed SCTP_MAX_CHUNK_LEN. Also tighten the local check so it does not send an IN request that would require an oversized OUT request from the peer.
--- net/sctp/stream.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/sctp/stream.c +5 -1
@@ -308,7 +308,8 @@ int sctp_send_reset_streams(struct sctp_association *asoc, goto out; param_len += str_nums *sizeof (__u16) + -sizeof (struct sctp_strreset_inreq ); + (out ?sizeof (struct sctp_strreset_inreq ) + :sizeof (struct sctp_strreset_outreq )); } if (param_len > SCTP_MAX_CHUNK_LEN -
@@ -639,6 +640,9 @@ struct sctp_chunk *sctp_process_strreset_inreq( nums = (ntohs (param.p->length) -sizeof (*inreq)) /sizeof (__u16); str_p = inreq->list_of_streams; +if (nums *sizeof (__u16) +sizeof (struct sctp_strreset_outreq ) > +SCTP_MAX_CHUNK_LEN -sizeof (struct sctp_reconf_chunk )) + goto out;for (i =0 ; i < nums; i++) {if (ntohs (str_p[i]) >= stream->outcnt) { result =SCTP_STRRESET_ERR_WRONG_SSN ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 275/744 net: mctp i3c: clean up notifier and buses if driver register fails
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Myeonghun Pak <[email protected]>
[ Upstream commit 03d1057305ef17ac3f5936ac1580bc9a1a826e14 ]
mctp_i3c_mod_init() registers the I3C bus notifier and then walks the existing buses with i3c_for_each_bus_locked(mctp_i3c_bus_add_new, NULL) before registering the I3C device driver. If i3c_driver_register() fails, the function returns the error directly, leaving the notifier registered and every mctp_i3c_bus object created for the existing buses allocated. The notifier is left pointing into the module that failed to load and the bus list is leaked.
Mirror the module exit path on this failure: unregister the notifier and tear down the buses that were added before returning the error.
This issue was identified during our ongoing static-analysis research while reviewing kernel code.
--- drivers/net/mctp/mctp-i3c.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
drivers/net/mctp/mctp-i3c.c +7 -4
@@ -731,18 +731,21 @@ static __init int mctp_i3c_mod_init(void)int rc; rc =i3c_register_notifier (&mctp_i3c_notifier); -if (rc <0 ) { -i3c_driver_unregister (&mctp_i3c_driver); +if (rc <0 )return rc; - }i3c_for_each_bus_locked (mctp_i3c_bus_add_new,NULL ); rc =i3c_driver_register (&mctp_i3c_driver);if (rc <0 ) -return rc; + goto err_unregister_notifier;return 0 ; + +err_unregister_notifier: +i3c_unregister_notifier (&mctp_i3c_notifier); +mctp_i3c_bus_remove_all (); +return rc; } static __exit void mctp_i3c_mod_exit(void)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 276/744 tls: device: push pending open record on splice EOF
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Rishikesh Jethwani <[email protected]>
[ Upstream commit eaa39f9f8ac8c1d032cd26b9cd572804e9d7683f ]
On kTLS device-offload sockets, sendfile() with count > EOF can reach ->splice_eof() with a fully assembled but still-open TLS record left pending. tls_device_splice_eof() only flushes partially sent records, so an abrupt close() can drop the final record and the peer receives a short file.
Fix tls_device_splice_eof() to also push pending open records. This matches the software path, where splice EOF already flushes pending open records.
--- net/tls/tls_device.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
net/tls/tls_device.c +4 -2
@@ -595,13 +595,15 @@ void tls_device_splice_eof(struct socket *sock)struct tls_context *tls_ctx =tls_get_ctx (sk);struct iov_iter iter = {}; -if (!tls_is_partially_sent_record (tls_ctx)) +if (!tls_is_partially_sent_record (tls_ctx) && + !tls_is_pending_open_record (tls_ctx))return ;mutex_lock (&tls_ctx->tx_lock);lock_sock (sk); -if (tls_is_partially_sent_record (tls_ctx)) { +if (tls_is_partially_sent_record (tls_ctx) || +tls_is_pending_open_record (tls_ctx)) {iov_iter_bvec (&iter,ITER_SOURCE ,NULL ,0 ,0 );tls_push_data (sk, &iter,0 ,0 ,TLS_RECORD_TYPE_DATA ); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 277/744 selftests: af_unix: add USER_NS config
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
[ Upstream commit f8b1abed736111f914b2c567d9a3db1f71e788e8 ]
This is required to use unshare(CLONE_NEWUSER).
This has not been seen on NIPA before, because the 'af_unix' tests are executed with the 'net' ones, merging their config files. USER_NS is present in tools/testing/selftests/net/config.
This issue is visible when only the af_unix config is used on top of the default one. This is the recommended way to execute selftest targets.
--- tools/testing/selftests/net/af_unix/config | 1 + 1 file changed, 1 insertion(+)
tools/testing/selftests/net/af_unix/config +1 -0
@@ -1,3 +1,4 @@ CONFIG_AF_UNIX_OOB=y CONFIG_UNIX=y CONFIG_UNIX_DIAG=m +CONFIG_USER_NS=y
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 278/744 selftests: openvswitch: add config file
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
[ Upstream commit 441a820ccef9af80a9ac5a4c85b9c396e595967c ]
The kselftests doc mentions that a config file should be present "if a test needs specific kernel config options enabled". This selftest requires some kernel config, but no config file was provided.
We could say that a sub-target could use the parent's config file, but the kselftests doc doesn't mention anything about that. Plus the net/openvswitch target is the only net target without a config file.
Here is a new config file, which is a trimmed version of the net one, with hopefully the minimal required kconfig on top of 'make defconfig'.
The Fixes tag points to the introduction of the net/openvswitch target, just to help validating this target on stable kernels.
--- tools/testing/selftests/net/openvswitch/config | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 tools/testing/selftests/net/openvswitch/config
tools/testing/selftests/net/openvswitch/config new file +16 -0
@@ -0,0 +1,16 @@ +CONFIG_GENEVE=m +CONFIG_INET_DIAG=y +CONFIG_IPV6=y +CONFIG_NETFILTER=y +CONFIG_NET_IPGRE=m +CONFIG_NET_IPGRE_DEMUX=m +CONFIG_NF_CONNTRACK=m +CONFIG_NF_CONNTRACK_OVS=y +CONFIG_OPENVSWITCH=m +CONFIG_OPENVSWITCH_GENEVE=m +CONFIG_OPENVSWITCH_GRE=m +CONFIG_OPENVSWITCH_VXLAN=m +CONFIG_PSAMPLE=m +CONFIG_VETH=y +CONFIG_VLAN_8021Q=y +CONFIG_VXLAN=m
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 279/744 selftests: ovpn: add IPV6 and VETH configs
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
[ Upstream commit 90c792681a3732caaf7bf5bc435877736baf591a ]
They are required to run the selftests:
- Tests are executed in v4 and v6.
- Virtual Ethernet are used between the different netns.
This has not been seen on NIPA before, because the 'ovpn' tests are executed with the 'tcp_ao' ones, merging their config files. These two kernel config are present in tools/testing/selftests/net/tcp_ao/config.
This issue is visible when only the ovpn config is used on top of the default one. This is the recommended way to execute selftest targets.
--- tools/testing/selftests/net/ovpn/config | 2 ++ 1 file changed, 2 insertions(+)
tools/testing/selftests/net/ovpn/config +2 -0
@@ -4,6 +4,7 @@ CONFIG_CRYPTO_CHACHA20POLY1305=y CONFIG_CRYPTO_GCM=y CONFIG_DST_CACHE=y CONFIG_INET=y +CONFIG_IPV6=y CONFIG_NET=y CONFIG_NETFILTER=y CONFIG_NET_UDP_TUNNEL=y
@@ -11,3 +12,4 @@ CONFIG_NF_TABLES=m CONFIG_NF_TABLES_INET=y CONFIG_OVPN=m CONFIG_STREAM_PARSER=y +CONFIG_VETH=y
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 280/744 selftests: ovpn: increase timeout
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
[ Upstream commit 61ac7049aaa86ae044e8a5b94d852218163d5bf8 ]
The default timeout is 45 seconds, that's too low for a few ovpn tests.
Indeed, these tests can take up to 50 seconds with some debug kernel config on NIPA. Set a timeout to 90 seconds, just to be on the safe side.
Note that the Fixes tag here points to the introduction of the ovpn tests because I don't know when they started to take more than 45 seconds. That's OK because a timeout of 1.5 minutes is not exaggerated.
--- tools/testing/selftests/net/ovpn/settings | 1 + 1 file changed, 1 insertion(+) create mode 100644 tools/testing/selftests/net/ovpn/settings
tools/testing/selftests/net/ovpn/settings new file +1 -0
@@ -0,0 +1 @@ +timeout=90
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 281/744 selftests: drv-net: increase timeout
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Matthieu Baerts (NGI0) <[email protected]>
[ Upstream commit 3529d75d67411497341cd804a045185d6035dff2 ]
The default timeout is 45 seconds, that's too low for the xdp.py test.
Indeed, this test can take up to 3 minutes with some debug kernel config on NIPA. Set a timeout to 6 minutes, just to be on the safe side.
Note that the Fixes tag here points to the introduction of the xdp.py test because I don't know when this test started to take more than 45 seconds. That's OK because a timeout of 6 minutes is not exaggerated.
--- tools/testing/selftests/drivers/net/settings | 1 + 1 file changed, 1 insertion(+) create mode 100644 tools/testing/selftests/drivers/net/settings
tools/testing/selftests/drivers/net/settings new file +1 -0
@@ -0,0 +1 @@ +timeout=360
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 282/744 selftests: drv-net: convert so_txtime to drv-net
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Willem de Bruijn <[email protected]>
[ Upstream commit 5c6baef3885c0e16e63d432fe31aa6f7e98e18dc ]
In preparation for extending to pacing hardware offload, convert the so_txtime.sh test to a drv-net test that can be run against netdevsim and real hardware.
Also update so_txtime.c to not exit on first failure, but run to completion and report exit code there. This helps with debugging unexpected results, especially when processing multiple packets, as happens in the "reverse_order" testcase.
----
v6 -> v7
- update test to use new argument expect_fail
- v6 received Reviewed-by, but dropped due to above (minor) change
v5 -> v6
- fix order in tools/testing/selftests/drivers/net/config
v4 -> v5
- move qdisc setup/restore into each test
- add tc to utils.py (separate patch)
- test expected failure (separate patch)
- fix pylint
- convert fail to pass for timing errors if KSFT_MACHINE_SLOW (cmd does not special case KSFT_SKIP process returncode yet)
Responses to sashiko review
- The test converts per packet failure to errors, to continue testing other packets, but other error() cases are not in scope.
- The test starts sender and receiver at an absolute future time, like the original test. This assumes ~msec scale sync'ed clocks.
- The tc qdisc replace command works fine with noqueue. Tested manually.
v3 -> v4
- restore original qdisc after test
- drop unnecessary underscore in tap test names
v2 -> v3
- Makefile: so_txtime from YNL_GEN_FILES to TEST_GEN_FILES (Sashiko, NIPA)
v1 -> v2
- move so_txtime.c for net/lib to drivers/net (Jakub)
- fix drivers/net/config order (Jakub)
- detect passing when failure is expected (Jakub, Sashiko)
- pass pylint --disable=R (Jakub)
- only call ksft_run once (Jakub)
- do not sleep if waiting time is negative (Sashiko)
- add \n when converting error() to fprintf() (Sashiko)
- 4 space indentation, instead of 2 space
- increase sync delay from 100 to 200ms, to fix rare vng flakes
Stable-dep-of: c25dd7439f84 ("selftests: drv-net: add missing kconfig for psp.py")
---
.../testing/selftests/drivers/net/.gitignore | 1 +
tools/testing/selftests/drivers/net/Makefile | 2 +
tools/testing/selftests/drivers/net/config | 2 +
.../selftests/{ => drivers}/net/so_txtime.c | 25 +++-
.../selftests/drivers/net/so_txtime.py | 96 +++++++++++++++
tools/testing/selftests/net/.gitignore | 1 -
tools/testing/selftests/net/Makefile | 2 -
tools/testing/selftests/net/so_txtime.sh | 110 ------------------
8 files changed, 121 insertions(+), 118 deletions(-)
rename tools/testing/selftests/{ => drivers}/net/so_txtime.c (96%)
create mode 100755 tools/testing/selftests/drivers/net/so_txtime.py
delete mode 100755 tools/testing/selftests/net/so_txtime.shtools/testing/selftests/drivers/net/.gitignore +1 -0
@@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only napi_id_helper psp_responder +so_txtime
tools/testing/selftests/drivers/net/Makefile +2 -0
@@ -7,6 +7,7 @@ TEST_INCLUDES := $(wildcard lib/py/*.py) \ TEST_GEN_FILES := \ napi_id_helper \ + so_txtime \ # end of TEST_GEN_FILES TEST_PROGS := \
@@ -21,6 +22,7 @@ TEST_PROGS := \ queues.py \ ring_reconfig.py \ shaper.py \ + so_txtime.py \ stats.py \ xdp.py \ # end of TEST_PROGS
tools/testing/selftests/drivers/net/config +2 -0
@@ -8,5 +8,7 @@ CONFIG_NETCONSOLE=m CONFIG_NETCONSOLE_DYNAMIC=y CONFIG_NETCONSOLE_EXTENDED_LOG=y CONFIG_NETDEVSIM=m +CONFIG_NET_SCH_ETF=m +CONFIG_NET_SCH_FQ=m CONFIG_VLAN_8021Q=m CONFIG_XDP_SOCKETS=y
tools/testing/selftests/drivers/net/so_txtime.c renamed from tools/testing/selftests/net/so_txtime.c +20 -5
@@ -33,6 +33,8 @@#include <unistd.h> #include <poll.h> +#include "kselftest.h" +static int cfg_clockid =CLOCK_TAI ;static uint16_t cfg_port =8000 ;static int cfg_variance_us =4000 ;
@@ -43,6 +45,8 @@ static bool cfg_rx;static uint64_t glob_tstart;static uint64_t tdeliver_max; +static int errors; +/* encode one timed transmission (of a 1B payload) */ struct timed_send {char data;
@@ -131,13 +135,15 @@ static void do_recv_one(int fdr, struct timed_send *ts)fprintf (stderr,"payload:%c delay:%lld expected:%lld (us)\n" , rbuf[0 ], (long long )tstop, (long long )texpect); -if (rbuf[0 ] != ts->data) -error (1 ,0 ,"payload mismatch. expected %c" , ts->data); +if (rbuf[0 ] != ts->data) { +fprintf (stderr,"payload mismatch. expected %c\n" , ts->data); + errors++; + }if (llabs (tstop - texpect) > cfg_variance_us) {fprintf (stderr,"exceeds variance (%d us)\n" , cfg_variance_us);if (!getenv ("KSFT_MACHINE_SLOW" )) -exit (1 ); + errors++; } }
@@ -255,8 +261,12 @@ static void start_time_wait(void)return ; now =gettime_ns (CLOCK_REALTIME ); -if (cfg_start_time_ns < now) +if (cfg_start_time_ns < now) { +fprintf (stderr,"FAIL: start time already passed\n" ); +if (!getenv ("KSFT_MACHINE_SLOW" )) + errors++;return ; + } err =usleep ((cfg_start_time_ns - now) /1000 );if (err)
@@ -513,5 +523,10 @@ int main(int argc, char **argv)else do_test_tx ((void *)&cfg_src_addr, cfg_alen); -return 0 ; +if (errors) { +fprintf (stderr,"FAIL: %d errors\n" , errors); +return KSFT_FAIL ; + } + +return KSFT_PASS ; }
tools/testing/selftests/drivers/net/so_txtime.py new file +96 -0
96 lines not on this page · raw message
tools/testing/selftests/net/.gitignore +0 -1
@@ -40,7 +40,6 @@ skf_net_off socket so_incoming_cpu so_netns_cookie -so_txtime so_rcv_listener stress_reuseport_listen tap
tools/testing/selftests/net/Makefile +0 -2
@@ -83,7 +83,6 @@ TEST_PROGS := \ rxtimestamp.sh \ sctp_vrf.sh \ skf_net_off.sh \ - so_txtime.sh \ srv6_end_dt46_l3vpn_test.sh \ srv6_end_dt4_l3vpn_test.sh \ srv6_end_dt6_l3vpn_test.sh \
@@ -159,7 +158,6 @@ TEST_GEN_FILES := \ skf_net_off \ so_netns_cookie \ so_rcv_listener \ - so_txtime \ socket \ stress_reuseport_listen \ tcp_fastopen_backup_key \
tools/testing/selftests/net/so_txtime.sh deleted +0 -110
110 lines not on this page · raw message
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 283/744 gtp: check skb_pull_data() return in gtp1u_send_echo_resp()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei (Microsoft) <[email protected]>
[ Upstream commit cd170f051dba9ac146fabcd1b91726487c0cb9fa ]
gtp1u_send_echo_resp() ignores skb_pull_data()'s return value. Its caller gtp1u_udp_encap_recv() only guarantees 16 bytes (udphdr + gtp1_header), but the pull requests 20 (gtp1_header_long + udphdr). For a 16-19 byte echo request the pull fails and returns NULL without advancing skb->data; execution continues, and the following skb_push() plus the IP header pushed by iptunnel_xmit() move skb->data below skb->head, tripping skb_under_panic().
Fix it by dropping the packet when skb_pull_data() fails.
skbuff: skb_under_panic: ...
kernel BUG at net/core/skbuff.c:214!
Call Trace: skb_push (net/core/skbuff.c:2648) iptunnel_xmit (net/ipv4/ip_tunnel_core.c:82) gtp_encap_recv (drivers/net/gtp.c:701 drivers/net/gtp.c:808 drivers/net/gtp.c:920) udp_queue_rcv_one_skb (net/ipv4/udp.c:2388) ... Kernel panic - not syncing: Fatal exception in interrupt
--- drivers/net/gtp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-)
drivers/net/gtp.c +3 -2
@@ -669,8 +669,9 @@ static int gtp1u_send_echo_resp(struct gtp_dev *gtp, struct sk_buff *skb)return -1 ;/* pull GTP and UDP headers */ -skb_pull_data (skb, -sizeof (struct gtp1_header_long ) +sizeof (struct udphdr )); +if (!skb_pull_data (skb,sizeof (struct gtp1_header_long ) + +sizeof (struct udphdr ))) +return -1 ; gtp_pkt =skb_push (skb,sizeof (struct gtp1u_packet ));memset (gtp_pkt,0 ,sizeof (struct gtp1u_packet ));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 284/744 nexthop: initialize extack in nh_res_bucket_migrate()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei (Microsoft) <[email protected]>
[ Upstream commit 6347c5314cee49f364aaf2e40ff15415a57a116e ]
nh_res_bucket_migrate() passes an uninitialized netlink_ext_ack to call_nexthop_res_bucket_notifiers(). When nh_notifier_res_bucket_info_init() fails (e.g. the kzalloc returns -ENOMEM), the error is propagated back before any notifier sets extack._msg, and the error path formats the stale pointer with pr_err_ratelimited("%s\n", extack._msg). With CONFIG_INIT_STACK_NONE this dereferences uninitialized stack memory:
Oops: general protection fault, probably for non-canonical address ... KASAN: maybe wild-memory-access in range [...] RIP: 0010:string (lib/vsprintf.c:730) vsnprintf (lib/vsprintf.c:2945) _printk (kernel/printk/printk.c:2504) nh_res_bucket_migrate (net/ipv4/nexthop.c:1816) nh_res_table_upkeep (net/ipv4/nexthop.c:1866) rtm_new_nexthop (net/ipv4/nexthop.c:3323) rtnetlink_rcv_msg (net/core/rtnetlink.c:7076) netlink_sendmsg (net/netlink/af_netlink.c:1900) Kernel panic - not syncing: Fatal exception
Zero-initialize extack so _msg is NULL on error paths that never set it.
--- net/ipv4/nexthop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv4/nexthop.c +1 -1
@@ -1788,8 +1788,8 @@ static bool nh_res_bucket_migrate(struct nh_res_table *res_table, bool notify_nl, bool force) {struct nh_res_bucket *bucket = &res_table->nh_buckets[bucket_index]; +struct netlink_ext_ack extack = {};struct nh_grp_entry *new_nhge; -struct netlink_ext_ack extack;int err; new_nhge = list_first_entry_or_null(&res_table->uw_nh_entries,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 285/744 tipc: fix infinite loop in __tipc_nl_compat_dumpit
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Helen Koike <[email protected]>
[ Upstream commit 22f8aa35964e8f2ab026578f45befc9605fd1b28 ]
cmd->dumpit callback can return a negative errno, causing an infinite loop due to the while(len) condition. As the loop never terminates, genl_mutex is never released, and other tasks waiting on it starve in D state.
Check dumpit's return value, propagate it and jump to err_out on error.
--- net/tipc/netlink_compat.c | 4 ++++ 1 file changed, 4 insertions(+)
net/tipc/netlink_compat.c +4 -0
@@ -221,6 +221,10 @@ static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,int rem; len = (*cmd->dumpit)(buf, &cb); +if (len <0 ) { + err = len; + goto err_out; + }nlmsg_for_each_msg (nlmsg,nlmsg_hdr (buf), len, rem) { err = nlmsg_parse_deprecated(nlmsg, GENL_HDRLEN,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 286/744 cifs: prevent readdir from changing file size due to stale directory metadata
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frank Sorenson <[email protected]>
[ Upstream commit e8a8d54c2d508891c142a928fc7d298c4c8bd0dd ]
Windows Server's directory enumeration metadata lags behind the actual file size after a write+close or rename. A concurrent readdir() in the window between close() returning to userspace and stat() being called overwrites the correct cached i_size with the stale server value, causing stat() to return the wrong size.
Once _cifsFileInfo_put() removes the last writable handle from openFileList, is_size_safe_to_change() permits readdir to overwrite i_size. smb2_close_getattr() then stamps cifs_i->time = jiffies, making the corrupt cached value appear fresh to the next stat().
The existing check (see Fixes:) only blocked stale size updates while an active RW lease was held, not after the last writable handle closes.
Add cifsInodeInfo->time_last_write, written via smp_store_release() at writable close and on setattr/truncate. is_size_safe_to_change() checks is_inode_writable() first (acquiring open_file_lock), then rejects a readdir size update if time_last_write falls within acregmax jiffies. The spinlock release in _cifsFileInfo_put() forms a store-release barrier that pairs with the spin_lock() (load-acquire) in is_inode_writable(), ensuring the subsequent smp_load_acquire() on time_last_write observes any update from a concurrent close(). When a size update is rejected and the server value differs from the cached one, cifs_i->time is cleared to force a fresh QUERY_INFO on the next stat().
readdir is also blocked from changing i_size while writable handles are open or an RW lease is held, even on direct-IO mounts.
For deferred close (closetimeo > 0), time_last_write is refreshed at the actual server close in smb2_deferred_work_close() and in the cifs_close_deferred_file*() drain paths invoked by lease/oplock breaks and tcon teardown, anchoring the protection window to the real close time rather than the earlier userspace close.
time_last_write == 0 skips the time_before() check to avoid false positives near boot on 32-bit systems where jiffies starts close to INITIAL_JIFFIES.
Does not reproduce against Samba or with actimeo=0.
--- fs/smb/client/cifsfs.c | 1 + fs/smb/client/cifsglob.h | 1 + fs/smb/client/file.c | 69 +++++++++++++++++++++++++++++++++++++--- fs/smb/client/inode.c | 6 ++++ fs/smb/client/misc.c | 27 ++++++++++++++-- 5 files changed, 96 insertions(+), 8 deletions(-)
fs/smb/client/cifsfs.c +1 -0
@@ -438,6 +438,7 @@ cifs_alloc_inode(struct super_block *sb)return NULL ; cifs_inode->cifsAttrs =ATTR_ARCHIVE ;/* default */ cifs_inode->time =0 ; + cifs_inode->time_last_write =0 ;/* * Until the file is open and we have gotten oplock info back from the * server, can not assume caching of file data or metadata.
fs/smb/client/cifsglob.h +1 -0
@@ -1562,6 +1562,7 @@ struct cifsInodeInfo {spinlock_t writers_lock;unsigned int writers;/* Number of writers on this inode */ unsigned long time;/* jiffies of last update of inode */ +unsigned long time_last_write;/* jiffies of last writable close or truncate */ u64 uniqueid;/* server inode number */ u64 createtime;/* creation time on server */ __u8 lease_key[SMB2_LEASE_KEY_SIZE ];/* lease key for this inode */
fs/smb/client/file.c +64 -5
102 lines not on this page · raw message
fs/smb/client/inode.c +6 -0
@@ -237,6 +237,8 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr,if (is_size_safe_to_change (cifs_i, fattr->cf_eof, from_readdir)) {i_size_write (inode, fattr->cf_eof); inode->i_blocks =CIFS_INO_BLOCKS (fattr->cf_bytes); + }else if (from_readdir &&i_size_read (inode) != fattr->cf_eof) { + cifs_i->time =0 ; }if (S_ISLNK (fattr->cf_mode) && fattr->cf_symlink_target) {
@@ -3269,6 +3271,8 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)if ((attrs->ia_valid &ATTR_SIZE ) && attrs->ia_size !=i_size_read (inode)) { +/* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ +smp_store_release (&cifsInode->time_last_write, jiffies);truncate_setsize (inode, attrs->ia_size);netfs_resize_file (&cifsInode->netfs, attrs->ia_size, true);fscache_resize_cookie (cifs_inode_cookie (inode), attrs->ia_size);
@@ -3470,6 +3474,8 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)if ((attrs->ia_valid &ATTR_SIZE ) && attrs->ia_size !=i_size_read (inode)) { +/* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ +smp_store_release (&cifsInode->time_last_write, jiffies);truncate_setsize (inode, attrs->ia_size);netfs_resize_file (&cifsInode->netfs, attrs->ia_size, true);fscache_resize_cookie (cifs_inode_cookie (inode), attrs->ia_size);
fs/smb/client/misc.c +24 -3
@@ -520,7 +520,14 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)spin_unlock (&cifs_inode->open_file_lock);list_for_each_entry_safe (tmp_list, tmp_next_list, &file_head, list) { -_cifsFileInfo_put (tmp_list->cfile, false, false); +struct cifsFileInfo *cfile = tmp_list->cfile; + +if (OPEN_FMODE (cfile->f_flags) &FMODE_WRITE ) { +/* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ +smp_store_release (&CIFS_I (d_inode (cfile->dentry))->time_last_write, + jiffies); + } +_cifsFileInfo_put (cfile, false, false);list_del (&tmp_list->list);kfree (tmp_list); }
@@ -553,7 +560,14 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon)spin_unlock (&tcon->open_file_lock);list_for_each_entry_safe (tmp_list, tmp_next_list, &file_head, list) { -_cifsFileInfo_put (tmp_list->cfile, true, false); +struct cifsFileInfo *cfile = tmp_list->cfile; + +if (OPEN_FMODE (cfile->f_flags) &FMODE_WRITE ) { +/* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ +smp_store_release (&CIFS_I (d_inode (cfile->dentry))->time_last_write, + jiffies); + } +_cifsFileInfo_put (cfile, true, false);list_del (&tmp_list->list);kfree (tmp_list); }
@@ -622,7 +636,14 @@ void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,spin_unlock (&tcon->open_file_lock);list_for_each_entry_safe (tmp_list, tmp_next_list, &file_head, list) { -_cifsFileInfo_put (tmp_list->cfile, true, false); +struct cifsFileInfo *cfile = tmp_list->cfile; + +if (OPEN_FMODE (cfile->f_flags) &FMODE_WRITE ) { +/* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ +smp_store_release (&CIFS_I (d_inode (cfile->dentry))->time_last_write, + jiffies); + } +_cifsFileInfo_put (cfile, true, false);list_del (&tmp_list->list);kfree (tmp_list); }
Signature · 1 line
2.53.0
Re: [PATCH 7.1 286/744] cifs: prevent readdir from changing file size due to stale directory metadata
Quoted 7 lines · Greg Kroah-Hartman
7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frank Sorenson <[email protected]>
[ Upstream commit
e8a8d54c2d508891c142a928fc7d298c4c8bd0dd]
These two allegedly fix the above:ecababf08905 ("cifs: fix time_last_write stamp placement in setattr/truncate paths") 0e3ea5445c22 ("cifs: consolidate time_last_write stamp into _cifsFileInfo_put()")
thanks,
Signature · 2 lines
js suse labs
Greg Kroah-Hartman
maintainerRe: [PATCH 7.1 286/744] cifs: prevent readdir from changing file size due to stale directory metadata
Quoted 7 lines · Jiri Slaby
Quoted 6 lines · Greg Kroah-Hartman
7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frank Sorenson <[email protected]>
Quoted 7 lines
Quoted 1 line
[ Upstream commit
e8a8d54c2d508891c142a928fc7d298c4c8bd0dd]These two allegedly fix the above:
ecababf08905("cifs: fixtime_last_writestamp placement in setattr/truncate paths")0e3ea5445c22("cifs: consolidatetime_last_writestamp into_cifsFileInfo_put()")
I don't scan Linus's tree (i.e. stuff before a -rc) so I missed these. Thanks for that, I'll go queue them up now.
greg k-h
Greg Kroah-Hartman
maintainerPATCH 287/744 cifs: fix cifsFileInfo leak on kmalloc failure in deferred close drain paths
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Frank Sorenson <[email protected]>
[ Upstream commit c2f2e83e3bbc5483730fd4ee903182761f1ae50f ]
In cifs_close_deferred_file(), cifs_close_all_deferred_files(), and cifs_close_deferred_file_under_dentry(), when a pending deferred close is cancelled via cancel_delayed_work(), the subsequent kmalloc_obj() to add the file to the local processing list may fail under memory pressure. The loop breaks immediately, but the cancelled work is no longer pending (it would have called _cifsFileInfo_put()), and the cfile is never added to file_head for processing. The cifsFileInfo reference and the open server handle both leak.
Fix by saving the cfile that failed allocation in a local variable, breaking as before, and calling _cifsFileInfo_put() on it after releasing the lock. Any files later in the iteration are unaffected since their deferred work is still pending and will fire normally.
--- fs/smb/client/misc.c | 45 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 6 deletions(-)
fs/smb/client/misc.c +39 -6
@@ -493,7 +493,7 @@ cifs_del_deferred_close(struct cifsFileInfo *cfile)void cifs_close_deferred_file (struct cifsInodeInfo *cifs_inode) { -struct cifsFileInfo *cfile =NULL ; +struct cifsFileInfo *cfile =NULL , *failed_cfile =NULL ;struct file_list *tmp_list, *tmp_next_list;LIST_HEAD (file_head);
@@ -510,8 +510,10 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode) tmp_list = kmalloc_obj(struct file_list,GFP_ATOMIC ); -if (tmp_list ==NULL ) +if (tmp_list ==NULL ) { + failed_cfile = cfile;break ; + } tmp_list->cfile = cfile;list_add_tail (&tmp_list->list, &file_head); }
@@ -519,6 +521,15 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode) }spin_unlock (&cifs_inode->open_file_lock); +if (failed_cfile) { +if (OPEN_FMODE (failed_cfile->f_flags) &FMODE_WRITE ) { +/* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ +smp_store_release (&CIFS_I (d_inode (failed_cfile->dentry))->time_last_write, + jiffies); + } +_cifsFileInfo_put (failed_cfile, false, false); + } +list_for_each_entry_safe (tmp_list, tmp_next_list, &file_head, list) {struct cifsFileInfo *cfile = tmp_list->cfile;
@@ -536,7 +547,7 @@ cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode)void cifs_close_all_deferred_files (struct cifs_tcon *tcon) { -struct cifsFileInfo *cfile; +struct cifsFileInfo *cfile, *failed_cfile =NULL ;struct file_list *tmp_list, *tmp_next_list;LIST_HEAD (file_head);
@@ -550,8 +561,10 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon) tmp_list = kmalloc_obj(struct file_list,GFP_ATOMIC ); -if (tmp_list ==NULL ) +if (tmp_list ==NULL ) { + failed_cfile = cfile;break ; + } tmp_list->cfile = cfile;list_add_tail (&tmp_list->list, &file_head); }
@@ -559,6 +572,15 @@ cifs_close_all_deferred_files(struct cifs_tcon *tcon) }spin_unlock (&tcon->open_file_lock); +if (failed_cfile) { +if (OPEN_FMODE (failed_cfile->f_flags) &FMODE_WRITE ) { +/* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ +smp_store_release (&CIFS_I (d_inode (failed_cfile->dentry))->time_last_write, + jiffies); + } +_cifsFileInfo_put (failed_cfile, true, false); + } +list_for_each_entry_safe (tmp_list, tmp_next_list, &file_head, list) {struct cifsFileInfo *cfile = tmp_list->cfile;
@@ -614,7 +636,7 @@ void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon, struct dentry *dentry) {struct file_list *tmp_list, *tmp_next_list; -struct cifsFileInfo *cfile; +struct cifsFileInfo *cfile, *failed_cfile =NULL ;LIST_HEAD (file_head);spin_lock (&tcon->open_file_lock);
@@ -627,14 +649,25 @@ void cifs_close_deferred_file_under_dentry(struct cifs_tcon *tcon,spin_unlock (&CIFS_I (d_inode (cfile->dentry))->deferred_lock); tmp_list = kmalloc_obj(struct file_list, GFP_ATOMIC); -if (tmp_list ==NULL ) +if (tmp_list ==NULL ) { + failed_cfile = cfile;break ; + } tmp_list->cfile = cfile;list_add_tail (&tmp_list->list, &file_head); } }spin_unlock (&tcon->open_file_lock); +if (failed_cfile) { +if (OPEN_FMODE (failed_cfile->f_flags) &FMODE_WRITE ) { +/* Pairs with smp_load_acquire() in is_size_safe_to_change(). */ +smp_store_release (&CIFS_I (d_inode (failed_cfile->dentry))->time_last_write, + jiffies); + } +_cifsFileInfo_put (failed_cfile, true, false); + } +list_for_each_entry_safe (tmp_list, tmp_next_list, &file_head, list) {struct cifsFileInfo *cfile = tmp_list->cfile;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 288/744 ppp: annotate concurrent dev->stats accesses
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit ba712ecfd942b68b21a4b0a5daaf72f6616cc66d ]
dev->stats fields can be updated concurrently from multiple CPUs without synchronization.
Use DEV_STATS_INC() for stats increments and DEV_STATS_READ() when reading dev->stats in ppp_get_stats64() and ppp_get_stats() to avoid data races.
--- drivers/net/ppp/ppp_generic.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-)
drivers/net/ppp/ppp_generic.c +16 -16
@@ -1482,7 +1482,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) outf:kfree_skb (skb); - ++dev->stats.tx_dropped; +DEV_STATS_INC (dev, tx_dropped);return NETDEV_TX_OK ; }
@@ -1532,11 +1532,11 @@ ppp_net_siocdevprivate(struct net_device *dev, struct ifreq *ifr,static void ppp_get_stats64 (struct net_device *dev,struct rtnl_link_stats64 *stats64) { - stats64->rx_errors = dev->stats.rx_errors; - stats64->tx_errors = dev->stats.tx_errors; - stats64->rx_dropped = dev->stats.rx_dropped; - stats64->tx_dropped = dev->stats.tx_dropped; - stats64->rx_length_errors = dev->stats.rx_length_errors; + stats64->rx_errors =DEV_STATS_READ (dev, rx_errors); + stats64->tx_errors =DEV_STATS_READ (dev, tx_errors); + stats64->rx_dropped =DEV_STATS_READ (dev, rx_dropped); + stats64->tx_dropped =DEV_STATS_READ (dev, tx_dropped); + stats64->rx_length_errors =DEV_STATS_READ (dev, rx_length_errors);dev_fetch_sw_netstats (stats64, dev->tstats); }
@@ -1889,7 +1889,7 @@ ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb) drop:kfree_skb (skb); - ++ppp->dev->stats.tx_errors; +DEV_STATS_INC (ppp->dev, tx_errors);return 1 ; }
@@ -2156,7 +2156,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) err_linearize:if (ppp->debug &1 )netdev_err (ppp->dev,"PPP: no memory (fragment)\n" ); - ++ppp->dev->stats.tx_errors; +DEV_STATS_INC (ppp->dev, tx_errors); ++ppp->nxseq;return 1 ;/* abandon the frame */ }
@@ -2329,7 +2329,7 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)if (!ppp_decompress_proto (skb)) {kfree_skb (skb);if (ppp) { - ++ppp->dev->stats.rx_length_errors; +DEV_STATS_INC (ppp->dev, rx_length_errors);ppp_receive_error (ppp); } goto done;
@@ -2391,7 +2391,7 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)static void ppp_receive_error (struct ppp *ppp) { - ++ppp->dev->stats.rx_errors; +DEV_STATS_INC (ppp->dev, rx_errors);if (ppp->vj)slhc_toss (ppp->vj); }
@@ -2658,7 +2658,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)*/ if (seq_before (seq, ppp->nextseq)) {kfree_skb (skb); - ++ppp->dev->stats.rx_dropped; +DEV_STATS_INC (ppp->dev, rx_dropped);ppp_receive_error (ppp);return ; }
@@ -2694,7 +2694,7 @@ ppp_receive_mp_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)if (pskb_may_pull (skb,2 ))ppp_receive_nonmp_frame (ppp, skb);else { - ++ppp->dev->stats.rx_length_errors; +DEV_STATS_INC (ppp->dev, rx_length_errors);kfree_skb (skb);ppp_receive_error (ppp); }
@@ -2800,7 +2800,7 @@ ppp_mp_reconstruct(struct ppp *ppp)if (lost ==0 && (PPP_MP_CB (p)->BEbits &E ) && (PPP_MP_CB (head)->BEbits &B )) {if (len > ppp->mrru +2 ) { - ++ppp->dev->stats.rx_length_errors; +DEV_STATS_INC (ppp->dev, rx_length_errors);netdev_printk (KERN_DEBUG , ppp->dev,"PPP: reconstructed packet" " is too long (%d)\n" , len);
@@ -2855,7 +2855,7 @@ ppp_mp_reconstruct(struct ppp *ppp)" missed pkts %u..%u\n" , ppp->nextseq, PPP_MP_CB(head)->sequence-1); - ++ppp->dev->stats.rx_dropped; +DEV_STATS_INC (ppp->dev, rx_dropped);ppp_receive_error (ppp); }
@@ -3322,8 +3322,8 @@ ppp_get_stats(struct ppp *ppp, struct ppp_stats *st) st->p.ppp_opackets += tx_packets; st->p.ppp_obytes += tx_bytes; } - st->p.ppp_ierrors = ppp->dev->stats.rx_errors; - st->p.ppp_oerrors = ppp->dev->stats.tx_errors; + st->p.ppp_ierrors =DEV_STATS_READ (ppp->dev, rx_errors); + st->p.ppp_oerrors =DEV_STATS_READ (ppp->dev, tx_errors);if (!vj)return ; st->vj.vjs_packets = vj->sls_o_compressed + vj->sls_o_uncompressed;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 289/744 wifi: mt76: mt7925: guard link STA in decap offload
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Guangshuo Li <[email protected]>
[ Upstream commit 96ea44f2269f30364cffa054ee3a87e595bef0d4 ]
mt7925_sta_set_decap_offload() iterates over the vif valid_links mask when updating decap offload state for an MLO station. The station may not have a link STA for every valid link of the vif, so mt792x_sta_to_link() can return NULL for a link that belongs to the vif but not to the station.
The function currently dereferences mlink before checking whether the link WCID is ready. If mlink is NULL, setting or clearing MT_WCID_FLAG_HDR_TRANS dereferences a NULL pointer.
Skip links without a station link before touching mlink->wcid.
--- drivers/net/wireless/mediatek/mt76/mt7925/main.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7925/main.c +3 -0
@@ -1678,6 +1678,9 @@ static void mt7925_sta_set_decap_offload(struct ieee80211_hw *hw, mconf =mt792x_vif_to_link (mvif, i); mlink =mt792x_sta_to_link (msta, i); +if (!mlink) +continue ; +if (enabled)set_bit (MT_WCID_FLAG_HDR_TRANS , &mlink->wcid.flags);else
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 290/744 wifi: mt76: mt7915: guard HE capability lookups
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Ruoyu Wang <[email protected]>
[ Upstream commit 8e9db062654a388d0fa587acbeeae68dd33eba41 ]
mt7915_mcu_bss_he_tlv() and mt7915_mcu_sta_bfer_tlv() both run after checking HE support, then dereference the HE PHY capability returned by mt76_connac_get_he_phy_cap(). That helper can return NULL when no capability entry matches the vif type.
Fetch the capability before appending the TLV and skip the HE-specific setup when no matching capability is available.
--- .../net/wireless/mediatek/mt76/mt7915/mcu.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +13 -5
@@ -595,6 +595,8 @@ mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,struct tlv *tlv; cap =mt76_connac_get_he_phy_cap (phy->mt76, vif); +if (!cap) +return ; tlv =mt76_connac_mcu_add_tlv (skb,BSS_INFO_HE_BASIC ,sizeof (*he));
@@ -1177,13 +1179,12 @@ mt7915_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7915_phy *phy, }static void -mt7915_mcu_sta_bfer_he (struct ieee80211_sta *sta,struct ieee80211_vif *vif, -struct mt7915_phy *phy,struct sta_rec_bf *bf) +mt7915_mcu_sta_bfer_he (struct ieee80211_sta *sta, +const struct ieee80211_sta_he_cap *vc, +struct sta_rec_bf *bf) {struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap;struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; -const struct ieee80211_sta_he_cap *vc = -mt76_connac_get_he_phy_cap (phy->mt76, vif);const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem;u16 mcs_map =le16_to_cpu (pc->he_mcs_nss_supp.rx_mcs_80);u8 nss_mcs =mt7915_mcu_get_sta_nss (mcs_map);
@@ -1242,6 +1243,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb, {struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv;struct mt7915_phy *phy = mvif->phy; +const struct ieee80211_sta_he_cap *vc =NULL ;int tx_ant =hweight8 (phy->mt76->chainmask) -1 ;struct sta_rec_bf *bf;struct tlv *tlv;
@@ -1260,6 +1262,12 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,if (!ebf && !dev->ibf)return ; +if (sta->deflink.he_cap.has_he && ebf) { + vc =mt76_connac_get_he_phy_cap (phy->mt76, vif); +if (!vc) +return ; + } + tlv =mt76_connac_mcu_add_tlv (skb,STA_REC_BF ,sizeof (*bf)); bf = (struct sta_rec_bf *)tlv;
@@ -1268,7 +1276,7 @@ mt7915_mcu_sta_bfer_tlv(struct mt7915_dev *dev, struct sk_buff *skb,* ht: iBF only, since mac80211 lacks of eBF support */ if (sta->deflink.he_cap.has_he && ebf) -mt7915_mcu_sta_bfer_he (sta, vif, phy, bf); +mt7915_mcu_sta_bfer_he (sta, vc, bf);else if (sta->deflink.vht_cap.vht_supported)mt7915_mcu_sta_bfer_vht (sta, phy, bf, ebf);else if (sta->deflink.ht_cap.ht_supported)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 291/744 wifi: mt76: connac: fix possible NULL-pointer deref in mt76_connac_mcu_uni_bss_he_tlv()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 2c1fb2335f5e3afb34f91bc07ecb63517c328090 ]
mt76_connac_get_he_phy_cap routine can theoretically return NULL so check cap pointer before dereferencing it.
--- drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +2 -0
@@ -1446,6 +1446,8 @@ mt76_connac_mcu_uni_bss_he_tlv(struct mt76_phy *phy, struct ieee80211_vif *vif,struct bss_info_uni_he *he; cap =mt76_connac_get_he_phy_cap (phy, vif); +if (!cap) +return ; he = (struct bss_info_uni_he *)tlv; he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 292/744 wifi: mt76: mt7925: fix possible NULL-pointer deref in mt7925_mcu_bss_he_tlv()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 8d1b6738c1ab48c086b17e7994034aca94258931 ]
mt76_connac_get_he_phy_cap routine can theoretically return NULL so check cap pointer before dereferencing it.
--- drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 2 ++ 1 file changed, 2 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7925/mcu.c +2 -0
@@ -2694,6 +2694,8 @@ mt7925_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_bss_conf *link_conf,struct tlv *tlv; cap =mt76_connac_get_he_phy_cap (phy->mt76, link_conf->vif); +if (!cap) +return ; tlv =mt76_connac_mcu_add_tlv (skb,UNI_BSS_INFO_HE_BASIC ,sizeof (*he));
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 293/744 wifi: mt76: mt7996: check pointer returned by mt76_connac_get_he_phy_cap()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit e858cf6bf99880343348ff1e8c942aaff1d9d592 ]
mt76_connac_get_he_phy_cap routine can theoretically return NULL so check cap pointer before dereferencing it.
--- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +6 -3
@@ -935,6 +935,8 @@ mt7996_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,struct tlv *tlv; cap =mt76_connac_get_he_phy_cap (phy->mt76, vif); +if (!cap) +return ; tlv =mt7996_mcu_add_uni_tlv (skb,UNI_BSS_INFO_HE_BASIC ,sizeof (*he));
@@ -1851,17 +1853,18 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_link_sta *link_sta, {struct ieee80211_sta_he_cap *pc = &link_sta->he_cap;struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; -const struct ieee80211_sta_he_cap *vc = -mt76_connac_get_he_phy_cap (phy->mt76, vif); -const struct ieee80211_he_cap_elem *ve = &vc->he_cap_elem;u16 mcs_map =le16_to_cpu (pc->he_mcs_nss_supp.rx_mcs_80);u8 nss_mcs =mt7996_mcu_get_sta_nss (mcs_map); +const struct ieee80211_he_cap_elem *ve; +const struct ieee80211_sta_he_cap *vc;u8 snd_dim, sts; + vc =mt76_connac_get_he_phy_cap (phy->mt76, vif);if (!vc)return ; bf->tx_mode =MT_PHY_TYPE_HE_SU ; + ve = &vc->he_cap_elem;mt7996_mcu_sta_sounding_rate (bf, phy);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 294/744 wifi: mt76: fix airoha_npu dependency tracking
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Arnd Bergmann <[email protected]>
[ Upstream commit 7cd57ff6c6263519e6e463cbc2e0898828a70c42 ]
There is a new build failure with MT7996E=m MT76_CORE=y and NET_AIROHA_NPU=m:
ld.lld: error: undefined symbol: airoha_npu_get
ld.lld: error: undefined symbol: airoha_npu_put
Quoted 2 lines
Quoted 2 lines
Quoted 2 lines
referenced by
npu.c
drivers/net/wireless/mediatek/mt76/npu.o:(mt76_npu_init) in archive vmlinux.a
Fix this by reworking the dependency for the MT7996_NPU to only allow enabling that when mt76_core can link against the npu driver.
To make sure this gets caught more easily in the future when additional mt76 variants need the same dependency, also turn CONFIG_MT76_NPU into a tristate symbol that has the same dependency.
--- drivers/net/wireless/mediatek/mt76/Kconfig | 4 ++-- drivers/net/wireless/mediatek/mt76/Makefile | 6 +++++- drivers/net/wireless/mediatek/mt76/mt76.h | 2 +- drivers/net/wireless/mediatek/mt76/mt7996/Kconfig | 2 +- 4 files changed, 9 insertions(+), 5 deletions(-)
drivers/net/wireless/mediatek/mt76/Kconfig +2 -2
@@ -38,8 +38,8 @@ config MT792x_USB select MT76_USB config MT76_NPU - bool - depends on MT76_CORE + tristate + depends on NET_AIROHA_NPU=y || MT76_CORE=NET_AIROHA_NPU source "drivers/net/wireless/mediatek/mt76/mt76x0/Kconfig" source "drivers/net/wireless/mediatek/mt76/mt76x2/Kconfig"
drivers/net/wireless/mediatek/mt76/Makefile +5 -1
@@ -12,7 +12,11 @@ mt76-y := \ mmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \ tx.o agg-rx.o mcu.o wed.o scan.o channel.o -mt76-$(CONFIG_MT76_NPU) += npu.o +ifdef CONFIG_MT76_NPU +# CONFIG_MT76_NPU is tristate to simplify dependency tracking, +# but it behaves as a bool symbol here. +mt76-y += npu.o +endif mt76-$(CONFIG_PCI) += pci.o mt76-$(CONFIG_NL80211_TESTMODE) += testmode.o
drivers/net/wireless/mediatek/mt76/mt76.h +1 -1
@@ -1646,7 +1646,7 @@ int mt76_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *skb,int mt76_testmode_set_state (struct mt76_phy *phy,enum mt76_testmode_state state);int mt76_testmode_alloc_skb (struct mt76_phy *phy,u32 len); -#ifdef CONFIG_MT76_NPU +#if IS_ENABLED (CONFIG_MT76_NPU )void mt76_npu_check_ppe (struct mt76_dev *dev,struct sk_buff *skb,u32 info); int mt76_npu_dma_add_buf(struct mt76_phy *phy, struct mt76_queue *q,
drivers/net/wireless/mediatek/mt76/mt7996/Kconfig +1 -1
@@ -16,6 +16,6 @@ config MT7996E config MT7996_NPU bool "MT7996 (PCIe) NPU support" depends on MT7996E - depends on NET_AIROHA_NPU=y || MT7996E=NET_AIROHA_NPU + depends on NET_AIROHA_NPU=y || MT76_CORE=NET_AIROHA_NPU select MT76_NPU default n
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 295/744 wifi: mt76: mt7925: fix crash in reset link replay
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sean Wang <[email protected]>
[ Upstream commit bd8b2ec838184236c3fcbf738a926328836adf12 ]
During reset recovery, mt7925_vif_connect_iter() replays firmware state for links tracked in mvif->valid_links. After MLO link changes or MCU timeout recovery, the driver bitmap can temporarily contain a link whose mac80211 bss_conf has already gone away.
This can pass a NULL bss_conf to mt76_connac_mcu_uni_add_dev(), matching the crash where x1, the second argument, is NULL:
pc : mt76_connac_mcu_uni_add_dev+0x8c/0x1f8 [mt76_connac_lib] lr : mt7925_vif_connect_iter+0x9c/0x168 [mt7925_common] x2 : ffffff80a77f6018 x1 : 0000000000000000 x0 : ffffff8099402080 Call trace: mt76_connac_mcu_uni_add_dev+0x8c/0x1f8 [mt76_connac_lib] mt7925_vif_connect_iter+0x9c/0x168 [mt7925_common] mt7925_mac_reset_work+0x264/0x2f8 [mt7925_common]
Skip missing bss_conf entries before replaying the link. Non-MLO AP/STA reset replay is unchanged because the helper still returns &vif->bss_conf for the legacy link.
--- drivers/net/wireless/mediatek/mt76/mt7925/mac.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/wireless/mediatek/mt76/mt7925/mac.c +3 -0
@@ -1275,6 +1275,9 @@ mt7925_vif_connect_iter(void *priv, u8 *mac,for_each_set_bit (i, &valid,IEEE80211_MLD_MAX_NUM_LINKS ) { bss_conf =mt792x_vif_to_bss_conf (vif, i); +if (!bss_conf) +continue ; + mconf =mt792x_vif_to_link (mvif, i); mt76_connac_mcu_uni_add_dev(&dev->mphy, bss_conf, &mconf->mt76,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 296/744 wifi: mt76: mt7996: fix possible NULL-pointer deref in mt7996_mcu_sta_bfer_eht()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 2fffc472bec490c8357defcee9c075ca74467352 ]
mt76_connac_get_eht_phy_cap routine can theoretically return NULL so check cap pointer before dereferencing it.
--- drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-)
drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +7 -3
@@ -1920,14 +1920,18 @@ mt7996_mcu_sta_bfer_eht(struct ieee80211_link_sta *link_sta,struct ieee80211_sta_eht_cap *pc = &link_sta->eht_cap;struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem;struct ieee80211_eht_mcs_nss_supp *eht_nss = &pc->eht_mcs_nss_supp; -const struct ieee80211_sta_eht_cap *vc = -mt76_connac_get_eht_phy_cap (phy->mt76, vif); -const struct ieee80211_eht_cap_elem_fixed *ve = &vc->eht_cap_elem;u8 nss_mcs =u8_get_bits (eht_nss->bw._80.rx_tx_mcs9_max_nss,IEEE80211_EHT_MCS_NSS_RX ) -1 ; +const struct ieee80211_eht_cap_elem_fixed *ve; +const struct ieee80211_sta_eht_cap *vc;u8 snd_dim, sts; + vc =mt76_connac_get_eht_phy_cap (phy->mt76, vif); +if (!vc) +return ; + bf->tx_mode =MT_PHY_TYPE_EHT_MU ; + ve = &vc->eht_cap_elem;mt7996_mcu_sta_sounding_rate (bf, phy);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 297/744 drm/xe/vf: Add drm_dev guards when detaching CCS read/write buffers
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Satyanarayana K V P <[email protected]>
[ Upstream commit 4c92afb4c143526d340545ca581e88e6952ea511 ]
CCS read/write buffers are freed during BO destruction. In some cases, BOs may be destroyed after the device is unbound but while the DRM structure remains valid, leading to NULL pointer dereferences when accessing device resources.
BUG: kernel NULL pointer dereference, address: 0000000000000000 PGD 0 P4D 0 Oops: Oops: 0000 [#1] SMP NOPTI CPU: 0 UID: 0 PID: 9376 Comm: xe_pat Not tainted 7.2.0-rc2+ #1 PREEMPT(lazy) RIP: 0010:xe_sriov_vf_ccs_rw_update_bb_addr+0x4d/0xa0 [xe] RSP: 0018:ffffcf304110b9c8 EFLAGS: 00010246 RAX: ffff8a85c38a0a00 RBX: 00000000810ef000 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff8a85c39c1888 RBP: ffffcf304110b9e8 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: ffff8a85c39c1888 R13: 0000000000000000 R14: ffff8a85c39b4f28 R15: ffff8a85c3885000 FS: 0000000000000000(0000) GS:ffff8a878b809000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 000000010314a002 CR4: 0000000000772ef0 PKRU: 55555554 Call Trace: <TASK> xe_migrate_ccs_rw_copy_clear+0x98/0x120 [xe] xe_sriov_vf_ccs_detach_bo+0x2c/0x60 [xe] xe_ttm_bo_delete_mem_notify+0xc8/0xe0 [xe] ttm_bo_cleanup_memtype_use+0x26/0x80 [ttm] ttm_bo_release+0x29e/0x2d0 [ttm] ttm_bo_fini+0x39/0x70 [ttm] xe_gem_object_free+0x1f/0x30 [xe] drm_gem_object_free+0x1d/0x40 ttm_bo_vm_close+0x5f/0x90 [ttm] remove_vma+0x2c/0x70 tear_down_vmas+0x63/0xf0 exit_mmap+0x20d/0x3f0 __mmput+0x45/0x170 mmput+0x31/0x40 do_exit+0x2ba/0xac0 do_group_exit+0x2d/0xb0 __x64_sys_exit_group+0x18/0x20 x64_sys_call+0x14a0/0x2390 do_syscall_64+0xdd/0x640 ? count_memcg_events+0xea/0x240 ? handle_mm_fault+0x1ec/0x2f0
--- drivers/gpu/drm/xe/xe_migrate.c | 16 ++++++++++------ drivers/gpu/drm/xe/xe_migrate.h | 3 ++- drivers/gpu/drm/xe/xe_sriov_vf_ccs.c | 14 ++++++++++++-- 3 files changed, 24 insertions(+), 9 deletions(-)
drivers/gpu/drm/xe/xe_migrate.c +10 -6
@@ -1292,6 +1292,7 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q,* content. * @src_bo: The buffer object @src is currently bound to. * @read_write : Creates BB commands for CCS read/write. +* @bound: Device is bound * * Directly clearing the BB lacks atomicity and can lead to undefined * behavior if the vCPU is halted mid-operation during the clearing
@@ -1304,7 +1305,8 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q,* Returns: None. */ void xe_migrate_ccs_rw_copy_clear (struct xe_bo *src_bo, -enum xe_sriov_vf_ccs_rw_ctxs read_write) +enum xe_sriov_vf_ccs_rw_ctxs read_write, +bool bound) {struct xe_mem_pool_node *bb = src_bo->bb_ccs[read_write];struct xe_device *xe =xe_bo_device (src_bo);
@@ -1318,13 +1320,15 @@ void xe_migrate_ccs_rw_copy_clear(struct xe_bo *src_bo, bb_pool = ctx->mem.ccs_bb_pool; scoped_guard(mutex, xe_mem_pool_bo_swap_guard(bb_pool)) { -xe_mem_pool_swap_shadow_locked (bb_pool); +if (bound) { +xe_mem_pool_swap_shadow_locked (bb_pool); - cs =xe_mem_pool_node_cpu_addr (bb); -memset (cs,MI_NOOP , bb->sa_node.size); -xe_sriov_vf_ccs_rw_update_bb_addr (ctx); + cs =xe_mem_pool_node_cpu_addr (bb); +memset (cs,MI_NOOP , bb->sa_node.size); +xe_sriov_vf_ccs_rw_update_bb_addr (ctx); -xe_mem_pool_sync_shadow_locked (bb); +xe_mem_pool_sync_shadow_locked (bb); + }xe_mem_pool_free_node (bb); src_bo->bb_ccs[read_write] =NULL ; }
drivers/gpu/drm/xe/xe_migrate.h +2 -1
@@ -142,7 +142,8 @@ int xe_migrate_ccs_rw_copy(struct xe_tile *tile, struct xe_exec_queue *q, enum xe_sriov_vf_ccs_rw_ctxs read_write);void xe_migrate_ccs_rw_copy_clear (struct xe_bo *src_bo, -enum xe_sriov_vf_ccs_rw_ctxs read_write); +enum xe_sriov_vf_ccs_rw_ctxs read_write, +bool bound);struct xe_lrc *xe_migrate_lrc (struct xe_migrate *migrate);struct xe_exec_queue *xe_migrate_exec_queue (struct xe_migrate *migrate);
drivers/gpu/drm/xe/xe_sriov_vf_ccs.c +12 -2
@@ -3,6 +3,8 @@* Copyright © 2025 Intel Corporation */ +#include <drm/drm_drv.h> +#include "instructions/xe_mi_commands.h" #include "instructions/xe_gpu_commands.h" #include "xe_bb.h"
@@ -446,7 +448,7 @@ int xe_sriov_vf_ccs_attach_bo(struct xe_bo *bo, struct ttm_resource *new_mem)*/ for_each_ccs_rw_ctx (ctx_id) {if (bo->bb_ccs[ctx_id]) -xe_migrate_ccs_rw_copy_clear (bo, ctx_id); +xe_migrate_ccs_rw_copy_clear (bo, ctx_id, true); }return err; }
@@ -466,19 +468,27 @@ int xe_sriov_vf_ccs_detach_bo(struct xe_bo *bo)struct xe_device *xe =xe_bo_device (bo);enum xe_sriov_vf_ccs_rw_ctxs ctx_id;struct xe_mem_pool_node *bb; +bool bound; +int idx;xe_assert (xe,IS_VF_CCS_READY (xe));if (!xe_bo_has_valid_ccs_bb (bo))return 0 ; + bound =drm_dev_enter (&xe->drm, &idx); +for_each_ccs_rw_ctx (ctx_id) { bb = bo->bb_ccs[ctx_id];if (!bb)continue ; -xe_migrate_ccs_rw_copy_clear (bo, ctx_id); +xe_migrate_ccs_rw_copy_clear (bo, ctx_id, bound); } + +if (bound) +drm_dev_exit (idx); +return 0 ; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 298/744 wifi: brcmfmac: fix 802.1X-SHA256 call trace warning
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shelley Yang <[email protected]>
[ Upstream commit 7cb34f6c4fe8a68af621d870abe63bfca2275dd6 ]
Based on wpa_auth as 1x_256 mode, need to set up "use_fwsup" with BRCMF_PROFILE_FWSUP_1X.
Or it will happen trace warning when call brcmf_cfg80211_set_pmk().
[ 4481.831101] ------------[ cut here ]------------ [ 4481.831102] WARNING: CPU: 1 PID: 2997 at drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:7242 brcmf_cfg80211_set_pmk+0x77/0xd0 [brcmfmac] [...] [ 4481.831202] Call Trace: [ 4481.831204] <TASK> [ 4481.831205] nl80211_set_pmk+0x183/0x250 [cfg80211] [ 4481.831233] genl_family_rcv_msg_doit+0xea/0x150 [ 4481.831237] genl_rcv_msg+0x104/0x240 [ 4481.831239] ? cfg80211_probe_status+0x2c0/0x2c0 [cfg80211] [ 4481.831257] ? genl_family_rcv_msg_doit+0x150/0x150 [ 4481.831259] netlink_rcv_skb+0x4e/0x100 [ 4481.831261] genl_rcv+0x24/0x40 [ 4481.831262] netlink_unicast+0x236/0x380 [ 4481.831264] netlink_sendmsg+0x250/0x4b0 [ 4481.831266] sock_sendmsg+0x5c/0x70 [ 4481.831269] ____sys_sendmsg+0x236/0x2b0 [ 4481.831271] ? copy_msghdr_from_user+0x6d/0xa0 [ 4481.831272] ___sys_sendmsg+0x86/0xd0 [ 4481.831274] ? avc_has_perm+0x8c/0x1a0 [ 4481.831276] ? preempt_count_add+0x6a/0xa0 [ 4481.831279] ? sock_has_perm+0x82/0xa0 [ 4481.831280] __sys_sendmsg+0x57/0xa0 [ 4481.831282] do_syscall_64+0x38/0x90 [ 4481.831284] entry_SYSCALL_64_after_hwframe+0x63/0xcd [ 4481.831286] RIP: 0033:0x7fd270d369b4
--- drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +1 -1
@@ -2146,7 +2146,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) sme->crypto.akm_suites[0]);return -EINVAL ; } - }else if (val & (WPA2_AUTH_PSK |WPA2_AUTH_UNSPECIFIED )) { + }else if (val & (WPA2_AUTH_PSK |WPA2_AUTH_UNSPECIFIED |WPA2_AUTH_1X_SHA256 )) {switch (sme->crypto.akm_suites[0 ]) {case WLAN_AKM_SUITE_8021X : val =WPA2_AUTH_UNSPECIFIED ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 299/744 ovl: fix trusted xattr escape prefix matching
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yichong Chen <[email protected]>
[ Upstream commit a8e72879cd0d8422c0b47d6d3c1802274fe73b98 ]
In the trusted.* xattr namespace, ovl_is_escaped_xattr() compares one byte less than the escaped overlay xattr prefix length. This makes it match "trusted.overlay.overlay" without requiring the trailing dot.
As a result, an xattr such as "trusted.overlay.overlayfoo" is incorrectly treated as an escaped overlay xattr. This can be reproduced by setting "trusted.overlay.overlayfoo" on a lower file and listing xattrs through an overlay mount. listxattr() then exposes it as "trusted.overlay.oo", and a following getxattr() on that listed name fails with ENODATA.
Compare the full escaped prefix, including the trailing dot, so similarly-prefixed private xattrs are not misclassified.
--- fs/overlayfs/xattrs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/overlayfs/xattrs.c +1 -1
@@ -13,7 +13,7 @@ static bool ovl_is_escaped_xattr(struct super_block *sb, const char *name) OVL_XATTR_ESCAPE_USER_PREFIX_LEN) == 0; else return strncmp(name, OVL_XATTR_ESCAPE_TRUSTED_PREFIX, -OVL_XATTR_ESCAPE_TRUSTED_PREFIX_LEN -1 ) ==0 ; +OVL_XATTR_ESCAPE_TRUSTED_PREFIX_LEN ) ==0 ; }static bool ovl_is_own_xattr (struct super_block *sb,const char *name)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 300/744 drm/panel: ilitek-ili9882t: fix unmet dependency for DRM_PANEL_ILITEK_ILI9882T
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Braha <[email protected]>
[ Upstream commit fc03f930bd9fd7c09617e41b1743e50ba659707c ]
Currently, DRM_PANEL_ILITEK_ILI9882T selects DRM_DISPLAY_DSC_HELPER without ensuring DRM_DISPLAY_HELPER is also enabled, causing an unmet dependency and build failure.
Other similar options select DRM_DISPLAY_HELPER, let's do the same here.
This unmet dependency bug was found by kconfirm, a static analysis tool for Kconfig.
--- drivers/gpu/drm/panel/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/panel/Kconfig +1 -0
@@ -308,6 +308,7 @@ config DRM_PANEL_ILITEK_ILI9882T depends on OF depends on DRM_MIPI_DSI depends on BACKLIGHT_CLASS_DEVICE + select DRM_DISPLAY_HELPER select DRM_DISPLAY_DSC_HELPER help Say Y if you want to enable support for panels based on the
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 301/744 drm/panel: s6e3ha8: fix unmet dependency on DRM_DISPLAY_HELPER
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Braha <[email protected]>
[ Upstream commit 3667bc164849fee4f1b18b182bdfe643f758ca17 ]
Currently, DRM_PANEL_SAMSUNG_S6E3HA8 selects DRM_DISPLAY_DSC_HELPER without ensuring its dependency, DRM_DISPLAY_HELPER, is enabled, causing an unmet dependency.
Let's select DRM_DISPLAY_HELPER as other similar options do.
This unmet dependency bug was found by kconfirm, a static analysis tool for Kconfig.
--- drivers/gpu/drm/panel/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/panel/Kconfig +1 -0
@@ -915,6 +915,7 @@ config DRM_PANEL_SAMSUNG_S6E3HA8 depends on OF depends on DRM_MIPI_DSI depends on BACKLIGHT_CLASS_DEVICE + select DRM_DISPLAY_HELPER select DRM_DISPLAY_DSC_HELPER help Say Y or M here if you want to enable support for the
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 302/744 drm/panel: fix unmet dependency bug for DRM_PANEL_HIMAX_HX83121A
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Julian Braha <[email protected]>
[ Upstream commit aaa5be0258db1709e254b4150af5c2fa5518c548 ]
Currently, DRM_PANEL_HIMAX_HX83121A selects DRM_DISPLAY_DSC_HELPER without also ensuring DRM_DISPLAY_HELPER is enabled, causing an unmet dependency:
WARNING: unmet direct dependencies detected for DRM_DISPLAY_DSC_HELPER
Depends on [n]: HAS_IOMEM [=y] && DRM [=m] && DRM_DISPLAY_HELPER [=n]
Selected by [m]:
- DRM_PANEL_HIMAX_HX83121A [=m] && HAS_IOMEM [=y] && DRM [=m] && DRM_PANEL [=y] && OF [=y] && DRM_MIPI_DSI [=y] && BACKLIGHT_CLASS_DEVICE [=m]
- DRM_PANEL_ILITEK_ILI9882T [=m] && HAS_IOMEM [=y] && DRM [=m] && DRM_PANEL [=y] && OF [=y] && DRM_MIPI_DSI [=y] && BACKLIGHT_CLASS_DEVICE [=m]
Many other DRM_PANEL_* options select DRM_DISPLAY_HELPER when selecting DRM_DISPLAY_DSC_HELPER, let's do the same here.
This unmet dependency bug was found by kconfirm, a static analysis tool for Kconfig.
--- drivers/gpu/drm/panel/Kconfig | 1 + 1 file changed, 1 insertion(+)
drivers/gpu/drm/panel/Kconfig +1 -0
@@ -208,6 +208,7 @@ config DRM_PANEL_HIMAX_HX83121A depends on OF depends on DRM_MIPI_DSI depends on BACKLIGHT_CLASS_DEVICE + select DRM_DISPLAY_HELPER select DRM_DISPLAY_DSC_HELPER select DRM_KMS_HELPER help
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 303/744 drm/vc4: hvs/v3d: Fix null dereference in unbind
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gregor Herburger <[email protected]>
[ Upstream commit 7dc3680b7ffe01add3e9299fde8471d2dd53a8ae ]
The hvs and v3d drivers use dev_get_drvdata(master) in their unbind functions. Since the vc4-drm gets removed before its dependent drivers (vc4_hvs/vc4_v3d) the vc4_hvs_unbind/vc4_v3d_unbind functions try to get drvdata of its master and fails with a null dereference error.
Use the data pointer passed to the unbind functions directly instead of dev_get_drvdata(master). This avoids using potentially freed memory.
--- drivers/gpu/drm/vc4/vc4_hvs.c | 2 +- drivers/gpu/drm/vc4/vc4_v3d.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-)
drivers/gpu/drm/vc4/vc4_hvs.c +1 -1
@@ -1752,7 +1752,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)static void vc4_hvs_unbind (struct device *dev,struct device *master,void *data) { -struct drm_device *drm =dev_get_drvdata (master); +struct drm_device *drm = data;struct vc4_dev *vc4 =to_vc4_dev (drm);struct vc4_hvs *hvs = vc4->hvs;struct drm_mm_node *node, *next;
drivers/gpu/drm/vc4/vc4_v3d.c +1 -1
@@ -494,7 +494,7 @@ static int vc4_v3d_bind(struct device *dev, struct device *master, void *data)static void vc4_v3d_unbind (struct device *dev,struct device *master,void *data) { -struct drm_device *drm =dev_get_drvdata (master); +struct drm_device *drm = data;struct vc4_dev *vc4 =to_vc4_dev (drm);vc4_irq_uninstall (drm);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 304/744 ovl: check access to copy_file_range source with src mounter creds
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Amir Goldstein <[email protected]>
[ Upstream commit a1e0eb8f55cfe09bb31a202a388babc411292656 ]
Commit 5dae222a5ff0c ("vfs: allow copy_file_range to copy across devices") allowed filesystems that implement the copy_file_range() f_op to decide if they want to access cross-sb copy from/to the same fs type.
The same commit added checks to verify same sb copy for filesystems that implement ->copy_file_range() and do not support cross-sb copy at the time, namely, to ceph, fuse and nfs.
The two remaining fs which implement ->copy_file_range(), cifs and overlayfs started to support cross-sb copy from this time.
While overlayfs does support cross-sb copy when the two underlying files are on the same base fs, the copy operation on the two real files from two different overalyfs filesystems is performed with the mounter creds of the destination overlayfs and the read permission access hook for the source file was called with the wrong creds.
This could cause either deny of access to copy which would otherwise be allowed (e.g. with splice) or allow read access to file which would otherwise be denied.
Fix the latter case by explicitly verifying read access to source file with the source overlayfs mounter creds.
The former case remains a quirk of cross-sb overlayfs copy, but userspace could fall back to regular copy so no harm done.
--- fs/overlayfs/file.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-)
fs/overlayfs/file.c +15 -1
@@ -528,6 +528,7 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in, struct file *file_out, loff_t pos_out, loff_t len, unsigned int flags, enum ovl_copyop op) { + struct inode *inode_in = file_inode(file_in);struct inode *inode_out =file_inode (file_out);struct file *realfile_in, *realfile_out;loff_t ret;
@@ -551,7 +552,20 @@ static loff_t ovl_copyfile(struct file *file_in, loff_t pos_in,if (IS_ERR (realfile_in)) goto out_unlock; - with_ovl_creds(file_inode(file_out)->i_sb) { +/* +* For cross-sb copy, vfs_copy_file_range() will verify read access with +* the mounter creds of the dest fs mounter, so we need to explicitly +* verify read access with the source mounter creds. +*/ +if (unlikely (inode_in->i_sb != inode_out->i_sb)) { + with_ovl_creds(inode_in->i_sb) { + ret =rw_verify_area (READ , realfile_in, &pos_in, len); +if (unlikely (ret)) + goto out_unlock; + } + } + + with_ovl_creds(inode_out->i_sb) {switch (op) {case OVL_COPY : ret = vfs_copy_file_range(realfile_in, pos_in,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 305/744 amt: re-read skb header pointers after every pull
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
[ Upstream commit 3656a79f94c471827a08f2cacce5f94ad5e52c24 ]
Several AMT receive and transmit paths cache a pointer into the skb head (ip_hdr(), ipv6_hdr(), eth_hdr() or the AMT message header) and then call a helper that can reallocate that head before the cached pointer is used again. pskb_may_pull(), ip_mc_may_pull(), ipv6_mc_may_pull(), iptunnel_pull_header(), ip_mc_check_igmp() and ipv6_mc_check_mld() can all free the old head and move the data, so a pointer taken before the call dangles afterwards and the later access is a use-after-free of the freed head.
The affected sites are:
amt_rcv() caches ip_hdr() before amt_parse_type() pulls, then reads iph->saddr.
amt_dev_xmit() caches ip_hdr()/ipv6_hdr() before ip_mc_check_igmp()/ ipv6_mc_check_mld() and pskb_may_pull(), then reads the group address.
amt_multicast_data_handler() caches eth_hdr() before pskb_may_pull(), then writes the L2 header.
amt_membership_query_handler() caches the AMT header, the outer and inner eth_hdr() and ip_hdr() before iptunnel_pull_header() and several pulls, then reads and writes them.
amt_igmpv3_report_handler() and amt_mldv2_report_handler() cache ip_hdr()/ipv6_hdr() and the current group record and read the record count from the report header inside the record loop, across the *_mc_may_pull() calls.
amt_update_handler() caches ip_hdr() and the AMT membership-update header before pskb_may_pull(), iptunnel_pull_header(), ip_mc_check_igmp() and the report handler, then reads iph->daddr and amtmu->nonce / amtmu->response_mac.
Fix each site by either snapshotting the scalar that is used after the pull before the first pull runs, or re-deriving the header pointer from the skb after the last pull that can move the head. Values that are stable across the pull (source and group address, the response MAC and nonce, the record count, the outer source MAC) are snapshotted; pointers that are written through or read repeatedly are re-derived.
--- drivers/net/amt.c | 79 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 55 insertions(+), 24 deletions(-)
drivers/net/amt.c +55 -24
@@ -1211,7 +1211,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) data = true; } v6 = false; - group.ip4 = iph->daddr; + group.ip4 =ip_hdr (skb)->daddr;#if IS_ENABLED (CONFIG_IPV6 ) } else if (iph->version == 6) { ip6h =ipv6_hdr (skb);
@@ -1235,7 +1235,7 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev) data = true; } v6 = true; - group.ip6 = ip6h->daddr; + group.ip6 =ipv6_hdr (skb)->daddr;#endif }else { dev->stats.tx_errors++;
@@ -1278,12 +1278,12 @@ static netdev_tx_t amt_dev_xmit(struct sk_buff *skb, struct net_device *dev)hlist_for_each_entry_rcu (gnode, &tunnel->groups[hash], node) {if (!v6) { -if (gnode->group_addr.ip4 == iph->daddr) +if (gnode->group_addr.ip4 == group.ip4) goto found;#if IS_ENABLED (CONFIG_IPV6 ) } else {if (ipv6_addr_equal (&gnode->group_addr.ip6, - &ip6h->daddr)) + &group.ip6)) goto found;#endif }
@@ -2000,14 +2000,18 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb,struct igmpv3_report *ihrv3 =igmpv3_report_hdr (skb);int len =skb_transport_offset (skb) +sizeof (*ihrv3);void *zero_grec = (void *)&igmpv3_zero_grec; -struct iphdr *iph =ip_hdr (skb);struct amt_group_node *gnode;union amt_addr group, host;struct igmpv3_grec *grec; +__be32 saddr;u16 nsrcs; +u16 ngrec;int i; -for (i =0 ; i <ntohs (ihrv3->ngrec); i++) { + saddr =ip_hdr (skb)->saddr; + ngrec =ntohs (ihrv3->ngrec); + +for (i =0 ; i < ngrec; i++) { len +=sizeof (*grec);if (!ip_mc_may_pull (skb, len))break ;
@@ -2019,10 +2023,13 @@ static void amt_igmpv3_report_handler(struct amt_dev *amt, struct sk_buff *skb,if (!ip_mc_may_pull (skb, len))break ; + grec = (void *)(skb->data + len -sizeof (*grec) - + nsrcs *sizeof (__be32)); +memset (&group,0 ,sizeof (union amt_addr )); group.ip4 = grec->grec_mca;memset (&host,0 ,sizeof (union amt_addr )); - host.ip4 = iph->saddr; + host.ip4 = saddr; gnode =amt_lookup_group (tunnel, &group, &host, false);if (!gnode) { gnode = amt_add_group(amt, tunnel, &group, &host,
@@ -2162,14 +2169,18 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb,struct mld2_report *mld2r = (struct mld2_report *)icmp6_hdr (skb);int len =skb_transport_offset (skb) +sizeof (*mld2r);void *zero_grec = (void *)&mldv2_zero_grec; -struct ipv6hdr *ip6h =ipv6_hdr (skb);struct amt_group_node *gnode;union amt_addr group, host;struct mld2_grec *grec; +struct in6_addr saddr;u16 nsrcs; +u16 ngrec;int i; -for (i =0 ; i <ntohs (mld2r->mld2r_ngrec); i++) { + saddr =ipv6_hdr (skb)->saddr; + ngrec =ntohs (mld2r->mld2r_ngrec); + +for (i =0 ; i < ngrec; i++) { len +=sizeof (*grec);if (!ipv6_mc_may_pull (skb, len))break ;
@@ -2181,10 +2192,13 @@ static void amt_mldv2_report_handler(struct amt_dev *amt, struct sk_buff *skb,if (!ipv6_mc_may_pull (skb, len))break ; + grec = (void *)(skb->data + len -sizeof (*grec) - + nsrcs *sizeof (struct in6_addr )); +memset (&group,0 ,sizeof (union amt_addr )); group.ip6 = grec->grec_mca;memset (&host,0 ,sizeof (union amt_addr )); - host.ip6 = ip6h->saddr; + host.ip6 = saddr; gnode =amt_lookup_group (tunnel, &group, &host, true);if (!gnode) { gnode = amt_add_group(amt, tunnel, &group, &host,
@@ -2305,7 +2319,6 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)skb_push (skb,sizeof (*eth));skb_reset_mac_header (skb);skb_pull (skb,sizeof (*eth)); - eth =eth_hdr (skb);if (!pskb_may_pull (skb,sizeof (*iph)))return true;
@@ -2315,6 +2328,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)if (!ipv4_is_multicast (iph->daddr))return true; skb->protocol =htons (ETH_P_IP ); + eth =eth_hdr (skb); eth->h_proto =htons (ETH_P_IP );ip_eth_mc_map (iph->daddr, eth->h_dest);#if IS_ENABLED (CONFIG_IPV6 )
@@ -2328,6 +2342,7 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)if (!ipv6_addr_is_multicast (&ip6h->daddr))return true; skb->protocol =htons (ETH_P_IPV6 ); + eth =eth_hdr (skb); eth->h_proto =htons (ETH_P_IPV6 );ipv6_eth_mc_map (&ip6h->daddr, eth->h_dest);#endif
@@ -2351,10 +2366,12 @@ static bool amt_membership_query_handler(struct amt_dev *amt, struct sk_buff *skb) {struct amt_header_membership_query *amtmq; -struct igmpv3_query *ihv3;struct ethhdr *eth, *oeth; +struct igmpv3_query *ihv3; +u8 h_source[ETH_ALEN ];struct iphdr *iph;int hdr_size, len; +u64 response_mac; hdr_size =sizeof (*amtmq) +sizeof (struct udphdr );if (!pskb_may_pull (skb, hdr_size))
@@ -2367,6 +2384,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt,if (amtmq->nonce != amt->nonce)return true; + response_mac = amtmq->response_mac; + hdr_size -=sizeof (*eth);if (iptunnel_pull_header (skb, hdr_size,htons (ETH_P_TEB ), false))return true;
@@ -2376,6 +2395,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt,skb_pull (skb,sizeof (*eth));skb_reset_network_header (skb); eth =eth_hdr (skb); +ether_addr_copy (h_source, oeth->h_source);if (!pskb_may_pull (skb,sizeof (*iph)))return true;
@@ -2388,6 +2408,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt, sizeof(*ihv3)))return true; + iph =ip_hdr (skb);if (!ipv4_is_multicast (iph->daddr))return true;
@@ -2395,10 +2416,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt,skb_reset_transport_header (skb);skb_push (skb,sizeof (*iph) +AMT_IPHDR_OPTS );WRITE_ONCE (amt->ready4, true); - amt->mac = amtmq->response_mac; + amt->mac = response_mac; amt->req_cnt =0 ; amt->qi = ihv3->qqic; skb->protocol =htons (ETH_P_IP ); + eth =eth_hdr (skb); eth->h_proto =htons (ETH_P_IP );ip_eth_mc_map (iph->daddr, eth->h_dest);#if IS_ENABLED (CONFIG_IPV6 )
@@ -2421,10 +2443,11 @@ static bool amt_membership_query_handler(struct amt_dev *amt,skb_reset_transport_header (skb);skb_push (skb,sizeof (*ip6h) +AMT_IP6HDR_OPTS );WRITE_ONCE (amt->ready6, true); - amt->mac = amtmq->response_mac; + amt->mac = response_mac; amt->req_cnt =0 ; amt->qi = mld2q->mld2q_qqic; skb->protocol =htons (ETH_P_IPV6 ); + eth =eth_hdr (skb); eth->h_proto =htons (ETH_P_IPV6 );ipv6_eth_mc_map (&ip6h->daddr, eth->h_dest);#endif
@@ -2432,7 +2455,7 @@ static bool amt_membership_query_handler(struct amt_dev *amt,return true; } -ether_addr_copy (eth->h_source, oeth->h_source); +ether_addr_copy (eth->h_source, h_source); skb->pkt_type =PACKET_MULTICAST ; skb->ip_summed =CHECKSUM_NONE ; len = skb->len;
@@ -2455,8 +2478,11 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)struct ethhdr *eth;struct iphdr *iph;int len, hdr_size; +u64 response_mac; +__be32 saddr; +__be32 nonce; - iph =ip_hdr (skb); + saddr =ip_hdr (skb)->saddr; hdr_size =sizeof (*amtmu) +sizeof (struct udphdr );if (!pskb_may_pull (skb, hdr_size))
@@ -2466,15 +2492,18 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)if (amtmu->reserved || amtmu->version)return true; + nonce = amtmu->nonce; + response_mac = amtmu->response_mac; +if (iptunnel_pull_header (skb, hdr_size, skb->protocol, false))return true;skb_reset_network_header (skb);list_for_each_entry_rcu (tunnel, &amt->tunnel_list, list) { -if (tunnel->ip4 == iph->saddr) { -if ((amtmu->nonce == tunnel->nonce && - amtmu->response_mac == tunnel->mac)) { +if (tunnel->ip4 == saddr) { +if ((nonce == tunnel->nonce && + response_mac == tunnel->mac)) {mod_delayed_work (amt_wq, &tunnel->gc_wq,msecs_to_jiffies (amt_gmi (amt)) *3 );
@@ -2508,6 +2537,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) eth =eth_hdr (skb); skb->protocol =htons (ETH_P_IP ); eth->h_proto =htons (ETH_P_IP ); + iph =ip_hdr (skb);ip_eth_mc_map (iph->daddr, eth->h_dest);#if IS_ENABLED (CONFIG_IPV6 ) } else if (iph->version == 6) {
@@ -2527,6 +2557,7 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb) eth =eth_hdr (skb); skb->protocol =htons (ETH_P_IPV6 ); eth->h_proto =htons (ETH_P_IPV6 ); + ip6h =ipv6_hdr (skb);ipv6_eth_mc_map (&ip6h->daddr, eth->h_dest);#endif }else {
@@ -2772,7 +2803,7 @@ static void amt_gw_rcv(struct amt_dev *amt, struct sk_buff *skb)static int amt_rcv (struct sock *sk,struct sk_buff *skb) {struct amt_dev *amt; -struct iphdr *iph; +__be32 saddr;int type;bool err;
@@ -2785,7 +2816,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) } skb->dev = amt->dev; - iph =ip_hdr (skb); + saddr =ip_hdr (skb)->saddr; type =amt_parse_type (skb);if (type ==-1 ) { err = true;
@@ -2795,7 +2826,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)if (amt->mode ==AMT_MODE_GATEWAY ) {switch (type) {case AMT_MSG_ADVERTISEMENT : -if (iph->saddr != amt->discovery_ip) { +if (saddr != amt->discovery_ip) {netdev_dbg (amt->dev,"Invalid Relay IP\n" ); err = true; goto drop;
@@ -2807,7 +2838,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb) } goto out;case AMT_MSG_MULTICAST_DATA : -if (iph->saddr != amt->remote_ip) { +if (saddr != amt->remote_ip) {netdev_dbg (amt->dev,"Invalid Relay IP\n" ); err = true; goto drop;
@@ -2818,7 +2849,7 @@ static int amt_rcv(struct sock *sk, struct sk_buff *skb)else goto out;case AMT_MSG_MEMBERSHIP_QUERY : -if (iph->saddr != amt->remote_ip) { +if (saddr != amt->remote_ip) {netdev_dbg (amt->dev,"Invalid Relay IP\n" ); err = true; goto drop;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 306/744 amt: make the head writable before rewriting the L2 header
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Bommarito <[email protected]>
[ Upstream commit 53969d704fa5b7c1751e277fac96bfc22b435eac ]
amt_multicast_data_handler(), amt_membership_query_handler() and amt_update_handler() rewrite the ethernet header of the decapsulated skb in place (eth->h_proto, eth->h_dest and, for the query, also eth->h_source) before handing it up the stack. The skb head may be shared, for example when a packet tap has cloned it on the underlay interface, so writing through it corrupts the other reader's copy.
Call skb_cow_head() before the rewrite so the head is private. It is placed before the pointers into the head are (re-)derived, so a reallocation caused by the copy is picked up by those derivations.
--- drivers/net/amt.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/net/amt.c +8 -0
@@ -2320,6 +2320,9 @@ static bool amt_multicast_data_handler(struct amt_dev *amt, struct sk_buff *skb)skb_reset_mac_header (skb);skb_pull (skb,sizeof (*eth)); +if (skb_cow_head (skb,0 )) +return true; +if (!pskb_may_pull (skb,sizeof (*iph)))return true; iph =ip_hdr (skb);
@@ -2396,6 +2399,8 @@ static bool amt_membership_query_handler(struct amt_dev *amt,skb_reset_network_header (skb); eth =eth_hdr (skb);ether_addr_copy (h_source, oeth->h_source); +if (skb_cow_head (skb,0 )) +return true;if (!pskb_may_pull (skb,sizeof (*iph)))return true;
@@ -2521,6 +2526,9 @@ static bool amt_update_handler(struct amt_dev *amt, struct sk_buff *skb)if (!pskb_may_pull (skb,sizeof (*iph)))return true; +if (skb_cow_head (skb,0 )) +return true; + iph =ip_hdr (skb);if (iph->version ==4 ) {if (ip_mc_check_igmp (skb)) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 307/744 net: bridge: vlan: fix vlan range dumps starting with pvid
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikolay Aleksandrov <[email protected]>
[ Upstream commit 43171c97e4714bf601b468401b37732244639c21 ]
There is a bug in all range dumps that rely on br_vlan_can_enter_range() when the PVID is a range starting VLAN, all following VLANs that match its flags can enter the range, but when the range is filled in only the PVID VLAN is dumped and the rest of the range is discarded because br_vlan_fill_vids() checks for the PVID flag. Since the PVID VLAN can be only one, we need to break ranges around it, the best way to do that consistently for all is to alter br_vlan_can_enter_range() to take into account the PVID and return false to break the range when it's matched.
Before the fix:
$ ip l add br0 type bridge vlan_filtering 1
$ ip l add dumdum type dummy
$ ip l set dumdum master br0
$ ip l set br0 up
$ ip l set dumdum up
$ bridge vlan add dev dumdum vid 1 pvid untagged master
$ bridge vlan add dev dumdum vid 2 untagged master
$ bridge vlan show dev dumdum # use legacy dump to show all vlans
port vlan-id
dumdum 1 PVID Egress Untagged
2 Egress Untagged$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN)
port vlan-id
dumdum 1 PVID Egress Untagged
state forwarding mcast_router 1VLAN 2 is missing, and if there are more matching VLANs afterwards they'd be missing too.
After the fix:
[ same setup steps ]
$ bridge vlan show dev dumdum
port vlan-id
dumdum 1 PVID Egress Untagged
2 Egress Untagged
$ bridge -d vlan show dev dumdum # use the new dump (RTM_GETVLAN)
port vlan-id
dumdum 1 PVID Egress Untagged
state forwarding mcast_router 1
2 Egress Untagged
state forwarding mcast_router 1--- net/bridge/br_netlink_tunnel.c | 3 ++- net/bridge/br_private.h | 6 ++++-- net/bridge/br_vlan.c | 10 ++++++---- net/bridge/br_vlan_options.c | 3 +-- 4 files changed, 13 insertions(+), 9 deletions(-)
net/bridge/br_netlink_tunnel.c +2 -1
@@ -271,7 +271,8 @@ static void __vlan_tunnel_handle_range(const struct net_bridge_port *p,if (!*v_start) goto out_init; -if (v && curr_change &&br_vlan_can_enter_range (v, *v_end)) { +if (v && curr_change && +br_vlan_can_enter_range (v, *v_end,br_get_pvid (vg))) { *v_end = v;return ; }
net/bridge/br_private.h +4 -2
@@ -1625,7 +1625,8 @@ void br_vlan_notify(const struct net_bridge *br, u16 vid, u16 vid_range, int cmd);bool br_vlan_can_enter_range (const struct net_bridge_vlan *v_curr, -const struct net_bridge_vlan *range_end); +const struct net_bridge_vlan *range_end, +u16 pvid); void br_vlan_fill_forward_path_pvid(struct net_bridge *br, struct net_device_path_ctx *ctx,
@@ -1872,7 +1873,8 @@ static inline void br_vlan_notify(const struct net_bridge *br, }static inline bool br_vlan_can_enter_range (const struct net_bridge_vlan *v_curr, -const struct net_bridge_vlan *range_end) +const struct net_bridge_vlan *range_end, +u16 pvid) {return true; }
net/bridge/br_vlan.c +6 -4
@@ -1982,9 +1982,11 @@ void br_vlan_notify(const struct net_bridge *br,/* check if v_curr can enter a range ending in range_end */ bool br_vlan_can_enter_range (const struct net_bridge_vlan *v_curr, -const struct net_bridge_vlan *range_end) +const struct net_bridge_vlan *range_end, +u16 pvid) { -return v_curr->vid - range_end->vid ==1 && +return v_curr->vid != pvid && range_end->vid != pvid && + v_curr->vid - range_end->vid ==1 && range_end->flags == v_curr->flags &&br_vlan_opts_eq_range (v_curr, range_end); }
@@ -2066,8 +2068,8 @@ static int br_vlan_dump_dev(const struct net_device *dev, idx += range_end->vid - range_start->vid +1 ; range_start = v; - } else if (dump_stats || v->vid == pvid || - !br_vlan_can_enter_range(v, range_end)) { + } else if (dump_stats || + !br_vlan_can_enter_range(v, range_end, pvid)) { u16 vlan_flags = br_vlan_flags(range_start, pvid); if (!br_vlan_fill_vids(skb, range_start->vid,
net/bridge/br_vlan_options.c +1 -2
@@ -330,8 +330,7 @@ int br_vlan_process_options(const struct net_bridge *br,continue ; } -if (v->vid == pvid || - !br_vlan_can_enter_range (v, curr_end)) { +if (!br_vlan_can_enter_range (v, curr_end, pvid)) {br_vlan_notify (br, p, curr_start->vid, curr_end->vid,RTM_NEWVLAN ); curr_start = v;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 308/744 net: hsr: fix memory leak on slave unregistration by removing synced VLANs
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit dcf15eaf5641812f1cfc5e96537380132a7da89d ]
When an HSR master device is brought UP, it auto-adds VLAN 0 via vlan_vid0_add(), which propagates VID 0 to its slave devices (slave A and B).
If a slave device is later unregistered while HSR is active (e.g., during netns cleanup or interface destruction), hsr_del_port() is called to detach the slave port from the HSR master. However, hsr_del_port() currently does not delete the VLAN IDs that were synced to the slave device by HSR.
As a result, the slave device retains a refcount on VID 0 (and any other synced VLANs). When the slave device is destroyed, its vlan_info / vlan_vid_info structure remains allocated, leading to a memory leak.
Fix this by calling vlan_vids_del_by_dev(port->dev, master->dev) in hsr_del_port() before unlinking slave A or slave B ports, matching the propagation logic in hsr_ndo_vlan_rx_add_vid() / hsr_ndo_vlan_rx_kill_vid() and the cleanup behavior in bonding and team drivers.
--- net/hsr/hsr_slave.c | 2 ++ 1 file changed, 2 insertions(+)
net/hsr/hsr_slave.c +2 -0
@@ -242,6 +242,8 @@ void hsr_del_port(struct hsr_port *port)netdev_rx_handler_unregister (port->dev);if (!port->hsr->fwd_offloaded)dev_set_promiscuity (port->dev,-1 ); +if (port->type ==HSR_PT_SLAVE_A || port->type ==HSR_PT_SLAVE_B ) +vlan_vids_del_by_dev (port->dev, master->dev);netdev_upper_dev_unlink (port->dev, master->dev);if (hsr->prot_version ==PRP_V1 && port->type ==HSR_PT_SLAVE_B ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 309/744 smp: Avoid invalid per-CPU CSD lookup with CSD lock debug
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuyi Zhou <[email protected]>
[ Upstream commit c58ea9adf7342508c6ac0b7ad79ef10d589f9c6e ]
Commit b0473dcd4b1d ("smp: Improve smp_call_function_single() CSD-lock diagnostics") made smp_call_function_single() use the destination CPU's csd_data when CSD lock debugging is enabled. That lets the debug code associate a stuck CSD lock with the target CPU, but it also means the CPU argument is used in per_cpu_ptr() before generic_exec_single() has a chance to validate it.
This becomes unsafe when smp_call_function_any() cannot find an online CPU in the supplied mask. In that case the selected CPU can be nr_cpu_ids, and the !wait path calls get_single_csd_data(cpu) before generic_exec_single() returns -ENXIO. With csdlock_debug_enabled set, that indexes the per-CPU offset array with an invalid CPU number.
Use the destination CPU's csd_data only when the CPU number is within nr_cpu_ids. For invalid CPU numbers, fall back to the local CPU's csd_data and let generic_exec_single() perform the existing validation and return -ENXIO.
--- kernel/smp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/smp.c +2 -1
@@ -380,7 +380,8 @@ static DEFINE_PER_CPU_SHARED_ALIGNED(call_single_data_t, csd_data);#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG static call_single_data_t *get_single_csd_data (int cpu) { -if (static_branch_unlikely (&csdlock_debug_enabled)) +if (static_branch_unlikely (&csdlock_debug_enabled) && + (unsigned int )cpu < nr_cpu_ids)return per_cpu_ptr (&csd_data, cpu);return this_cpu_ptr (&csd_data); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 310/744 smp: Make CSD lock acquisition atomic for debug mode
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chuyi Zhou <[email protected]>
[ Upstream commit 35551efb155e3b83445a6c3f66cb498d5efc182c ]
Commit b0473dcd4b1d ("smp: Improve smp_call_function_single() CSD-lock diagnostics") changed smp_call_function_single() so that, when CSD lock debugging is enabled, async !wait calls use the destination CPU csd_data. That improves diagnostics, but it also removes the single-writer property that made the old csd_lock() safe: multiple CPUs can now prepare the same destination CPU CSD concurrently.
csd_lock() currently waits for CSD_FLAG_LOCK to clear and then sets the bit with a non-atomic read-modify-write. Two senders can both see an unlocked CSD, set the bit, overwrite the callback fields, and enqueue the same llist node. Re-adding a node that is already the queue head can make node->next point to itself, leaving the target CPU stuck walking call_single_queue. Later synchronous work, such as a TLB shootdown, can then remain queued and trigger soft-lockup warnings or panics.
Keep the single csd_lock() implementation, but when CSD lock debugging is enabled, acquire CSD_FLAG_LOCK with try_cmpxchg_acquire(). This makes the destination CPU CSD a real atomic lock in the only configuration where it can be shared by multiple remote senders, while preserving the existing non-debug fast path.
--- kernel/smp.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-)
kernel/smp.c +23 -4
@@ -137,10 +137,10 @@ csd_do_func(smp_call_func_t func, void *info, call_single_data_t *csd)trace_csd_function_exit (func, csd); } -#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG - static DEFINE_STATIC_KEY_MAYBE(CONFIG_CSD_LOCK_WAIT_DEBUG_DEFAULT, csdlock_debug_enabled); +#ifdef CONFIG_CSD_LOCK_WAIT_DEBUG +/* * Parse the csdlock_debug= kernel boot parameter. *
@@ -342,6 +342,10 @@ static __always_inline void csd_lock_wait(call_single_data_t *csd)smp_cond_load_acquire (&csd->node.u_flags, !(VAL &CSD_FLAG_LOCK )); }#else +static __always_inline void __csd_lock_wait(call_single_data_t *csd) +{ +} +static void csd_lock_record (call_single_data_t *csd) { }
@@ -354,8 +358,23 @@ static __always_inline void csd_lock_wait(call_single_data_t *csd) static __always_inline void csd_lock(call_single_data_t *csd) { -csd_lock_wait (csd); - csd->node.u_flags |=CSD_FLAG_LOCK ; +if (IS_ENABLED (CONFIG_CSD_LOCK_WAIT_DEBUG ) && +static_branch_unlikely (&csdlock_debug_enabled)) { + +for (;;) { +unsigned int flags; + +__csd_lock_wait (csd); + flags =READ_ONCE (csd->node.u_flags); + +if (!(flags &CSD_FLAG_LOCK ) && +try_cmpxchg_acquire (&csd->node.u_flags, &flags, flags |CSD_FLAG_LOCK )) +break ; + } + }else { +csd_lock_wait (csd); + csd->node.u_flags |=CSD_FLAG_LOCK ; + }/* * prevent CPU from reordering the above assignment
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 311/744 net: dpaa: fix mode setting
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Michael Walle <[email protected]>
[ Upstream commit da2c6bcc5e30b1496ac587785dcacf6e849eb6ef ]
Before converting to the phylink interface, the init function would have set a non-reserved I/F mode in the maccfg2 register. After converting to phylink, 0 is written as mode, which is a reserved value (although it's the hardware default). Without a valid mode, a SGMII link is never established between the MAC and the PHY and thus .link_up() is never called which could set the correct mode according to the actual speed.
Fix it by setting the maximum speed of the phy_interface_t in use in .mac_config() - just like the driver did before the phylink conversion.
--- .../net/ethernet/freescale/fman/fman_dtsec.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-)
drivers/net/ethernet/freescale/fman/fman_dtsec.c +12 -5
@@ -900,22 +900,28 @@ static void dtsec_mac_config(struct phylink_config *config, unsigned int mode, {struct mac_device *mac_dev =fman_config_to_mac (config);struct dtsec_regs __iomem *regs = mac_dev->fman_mac->regs; -u32 tmp; +u32 ecntrl, maccfg2; + + maccfg2 =ioread32be (®s->maccfg2); + maccfg2 &= ~(MACCFG2_NIBBLE_MODE |MACCFG2_BYTE_MODE );switch (state->interface) {case PHY_INTERFACE_MODE_RMII : - tmp =DTSEC_ECNTRL_RMM ; + ecntrl =DTSEC_ECNTRL_RMM ; + maccfg2 |=MACCFG2_NIBBLE_MODE ;break ;case PHY_INTERFACE_MODE_RGMII :case PHY_INTERFACE_MODE_RGMII_ID :case PHY_INTERFACE_MODE_RGMII_RXID :case PHY_INTERFACE_MODE_RGMII_TXID : - tmp =DTSEC_ECNTRL_GMIIM |DTSEC_ECNTRL_RPM ; + ecntrl =DTSEC_ECNTRL_GMIIM |DTSEC_ECNTRL_RPM ; + maccfg2 |=MACCFG2_BYTE_MODE ;break ;case PHY_INTERFACE_MODE_SGMII :case PHY_INTERFACE_MODE_1000BASEX :case PHY_INTERFACE_MODE_2500BASEX : - tmp =DTSEC_ECNTRL_TBIM |DTSEC_ECNTRL_SGMIIM ; + ecntrl =DTSEC_ECNTRL_TBIM |DTSEC_ECNTRL_SGMIIM ; + maccfg2 |=MACCFG2_BYTE_MODE ;break ;default : dev_warn(mac_dev->dev, "cannot configure dTSEC for %s\n",
@@ -923,7 +929,8 @@ static void dtsec_mac_config(struct phylink_config *config, unsigned int mode,return ; } -iowrite32be (tmp, ®s->ecntrl); +iowrite32be (ecntrl, ®s->ecntrl); +iowrite32be (maccfg2, ®s->maccfg2); } static void dtsec_link_up(struct phylink_config *config, struct phy_device *phy,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 312/744 net: stmmac: dwmac4: mask interrupts when stopping DMA in suspend
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Luis Lang <[email protected]>
[ Upstream commit 59a57128ae5231f9aa9d544fa9d3e38986f0efaa ]
Since commit 1b9707e6f1a9 ("net: stmmac: enable RPS and RBU interrupts"), suspending causes an interrupt storm from the RPS interrupt.
Fix this by adding a deinit_chan() op to stmmac_dma_ops, which masks all default dma channel interrupts. This is called from stmmac_stop_all_dma(), so interrupts don't trigger while suspending.
--- .../net/ethernet/stmicro/stmmac/dwmac4_dma.c | 24 +++++++++++++++++++ drivers/net/ethernet/stmicro/stmmac/hwif.h | 4 ++++ .../net/ethernet/stmicro/stmmac/stmmac_main.c | 4 ++++ 3 files changed, 32 insertions(+)
drivers/net/ethernet/stmicro/stmmac/dwmac4_dma.c +24 -0
@@ -106,6 +106,17 @@ static void dwmac4_dma_init_channel(struct stmmac_priv *priv, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); } +static void dwmac4_dma_deinit_channel (struct stmmac_priv *priv, +void __iomem *ioaddr,u32 chan) +{ +const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; +u32 value; + + value =readl (ioaddr +DMA_CHAN_INTR_ENA (dwmac4_addrs, chan)); + value &= ~DMA_CHAN_INTR_DEFAULT_MASK ; +writel (value, ioaddr +DMA_CHAN_INTR_ENA (dwmac4_addrs, chan)); +} +static void dwmac410_dma_init_channel (struct stmmac_priv *priv,void __iomem *ioaddr,struct stmmac_dma_cfg *dma_cfg,u32 chan)
@@ -125,6 +136,17 @@ static void dwmac410_dma_init_channel(struct stmmac_priv *priv, ioaddr + DMA_CHAN_INTR_ENA(dwmac4_addrs, chan)); } +static void dwmac410_dma_deinit_channel (struct stmmac_priv *priv, +void __iomem *ioaddr,u32 chan) +{ +const struct dwmac4_addrs *dwmac4_addrs = priv->plat->dwmac4_addrs; +u32 value; + + value =readl (ioaddr +DMA_CHAN_INTR_ENA (dwmac4_addrs, chan)); + value &= ~DMA_CHAN_INTR_DEFAULT_MASK_4_10 ; +writel (value, ioaddr +DMA_CHAN_INTR_ENA (dwmac4_addrs, chan)); +} +static void dwmac4_dma_init (void __iomem *ioaddr,struct stmmac_dma_cfg *dma_cfg) {
@@ -547,6 +569,7 @@ const struct stmmac_dma_ops dwmac4_dma_ops = { .reset = dwmac4_dma_reset, .init = dwmac4_dma_init, .init_chan = dwmac4_dma_init_channel, + .deinit_chan = dwmac4_dma_deinit_channel, .init_rx_chan = dwmac4_dma_init_rx_chan, .init_tx_chan = dwmac4_dma_init_tx_chan, .axi = dwmac4_dma_axi,
@@ -576,6 +599,7 @@ const struct stmmac_dma_ops dwmac410_dma_ops = { .reset = dwmac4_dma_reset, .init = dwmac4_dma_init, .init_chan = dwmac410_dma_init_channel, + .deinit_chan = dwmac410_dma_deinit_channel, .init_rx_chan = dwmac4_dma_init_rx_chan, .init_tx_chan = dwmac4_dma_init_tx_chan, .axi = dwmac4_dma_axi,
drivers/net/ethernet/stmicro/stmmac/hwif.h +4 -0
@@ -170,6 +170,8 @@ struct stmmac_dma_ops {void (*init)(void __iomem *ioaddr,struct stmmac_dma_cfg *dma_cfg);void (*init_chan)(struct stmmac_priv *priv,void __iomem *ioaddr,struct stmmac_dma_cfg *dma_cfg,u32 chan); +void (*deinit_chan)(struct stmmac_priv *priv,void __iomem *ioaddr, +u32 chan);void (*init_rx_chan)(struct stmmac_priv *priv,void __iomem *ioaddr,struct stmmac_dma_cfg *dma_cfg,dma_addr_t phy,u32 chan);
@@ -235,6 +237,8 @@ struct stmmac_dma_ops { stmmac_do_void_callback(__priv, dma, init, __args) #define stmmac_init_chan(__priv, __args...) \ stmmac_do_void_callback(__priv, dma, init_chan, __priv, __args) +#define stmmac_deinit_chan(__priv, __args...) \ + stmmac_do_void_callback(__priv, dma, deinit_chan, __priv, __args) #define stmmac_init_rx_chan(__priv, __args...) \ stmmac_do_void_callback(__priv, dma, init_rx_chan, __priv, __args) #define stmmac_init_tx_chan(__priv, __args...) \
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +4 -0
@@ -2560,6 +2560,7 @@ static void stmmac_stop_all_dma(struct stmmac_priv *priv) {u8 rx_channels_count = priv->plat->rx_queues_to_use;u8 tx_channels_count = priv->plat->tx_queues_to_use; +u8 dma_csr_ch =max (rx_channels_count, tx_channels_count);u8 chan;for (chan =0 ; chan < rx_channels_count; chan++)
@@ -2567,6 +2568,9 @@ static void stmmac_stop_all_dma(struct stmmac_priv *priv)for (chan =0 ; chan < tx_channels_count; chan++)stmmac_stop_tx_dma (priv, chan); + +for (chan =0 ; chan < dma_csr_ch; chan++) +stmmac_deinit_chan (priv, priv->ioaddr, chan); }/**
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 313/744 sctp: auth: verify auth requirement when auth_chunk is NULL
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Qing Luo <[email protected]>
[ Upstream commit 8e04823c120b376ef7dab14b60ebf6823aa16c14 ]
sctp_auth_chunk_verify() returns true unconditionally when chunk->auth_chunk is NULL, silently skipping authentication. This is incorrect when:
1. skb_clone() failed in the BH receive path, leaving auth_chunk NULL. In sctp_endpoint_bh_rcv() asoc is NULL for new connections, so the early sctp_auth_recv_cid() check cannot catch this.
2. No AUTH chunk precedes COOKIE-ECHO, so skb_clone() is never called and auth_chunk remains NULL.
Fix by checking sctp_auth_recv_cid() when auth_chunk is NULL:
if authentication is required, return false to drop the chunk; otherwise continue normally.
--- net/sctp/sm_statefuns.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/sctp/sm_statefuns.c +1 -1
@@ -643,7 +643,7 @@ static bool sctp_auth_chunk_verify(struct net *net, struct sctp_chunk *chunk,struct sctp_chunk auth;if (!chunk->auth_chunk) -return true; +return !sctp_auth_recv_cid (chunk->chunk_hdr->type, asoc);/* SCTP-AUTH: auth_chunk pointer is only set when the cookie-echo * is supposed to be authenticated and we have to do delayed
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 314/744 vmxnet3: fix BUG_ON in vmxnet3_get_hdr_len() for Geneve packets
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Harshaka Narayana <[email protected]>
[ Upstream commit 34a71f5361fc3adb5b7138da78750b0d535a8252 ]
vmxnet3_get_hdr_len() assumes gdesc->rcd.v4/v6/tcp always describe the outer header, but for a Geneve-encapsulated packet the device can set them based on the inner header instead, signalled by the VMXNET3_RCD_HDR_INNER_SHIFT bit in the completion descriptor. Since the function never skips the outer encapsulation, this mismatch triggers:
- BUG_ON(hdr.ipv4->protocol != IPPROTO_TCP), because the outer protocol is UDP (Geneve), not TCP.
- BUG_ON(hdr.eth->h_proto != ...), when the tunnel's outer and inner IP versions differ (e.g. outer IPv6/inner IPv4 or vice versa).
Check VMXNET3_RCD_HDR_INNER_SHIFT up front and bail out, since the function cannot locate the inner header it would need to parse. Also convert the remaining BUG_ON()s in this function to return 0 defensively.
--- drivers/net/vmxnet3/vmxnet3_drv.c | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-)
drivers/net/vmxnet3/vmxnet3_drv.c +16 -6
@@ -1530,7 +1530,11 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb,struct ipv6hdr *ipv6;struct tcphdr *tcp; } hdr; -BUG_ON (gdesc->rcd.tcp ==0 ); + +/* v4/v6/tcp then describe the inner header, which we can't locate. */ +if ((le32_to_cpu (gdesc->dword[0 ]) & (1UL <<VMXNET3_RCD_HDR_INNER_SHIFT )) || + gdesc->rcd.tcp ==0 ) +return 0 ; maplen =skb_headlen (skb);if (unlikely (sizeof (struct iphdr ) +sizeof (struct tcphdr ) > maplen))
@@ -1544,15 +1548,21 @@ vmxnet3_get_hdr_len(struct vmxnet3_adapter *adapter, struct sk_buff *skb, hdr.eth =eth_hdr (skb);if (gdesc->rcd.v4) { -BUG_ON (hdr.eth->h_proto !=htons (ETH_P_IP ) && - hdr.veth->h_vlan_encapsulated_proto !=htons (ETH_P_IP )); +if (hdr.eth->h_proto !=htons (ETH_P_IP ) && + hdr.veth->h_vlan_encapsulated_proto !=htons (ETH_P_IP )) +return 0 ; + hdr.ptr += hlen; -BUG_ON (hdr.ipv4->protocol !=IPPROTO_TCP ); +if (hdr.ipv4->protocol !=IPPROTO_TCP ) +return 0 ; + hlen = hdr.ipv4->ihl <<2 ; hdr.ptr += hdr.ipv4->ihl <<2 ; }else if (gdesc->rcd.v6) { -BUG_ON (hdr.eth->h_proto !=htons (ETH_P_IPV6 ) && - hdr.veth->h_vlan_encapsulated_proto !=htons (ETH_P_IPV6 )); +if (hdr.eth->h_proto !=htons (ETH_P_IPV6 ) && + hdr.veth->h_vlan_encapsulated_proto !=htons (ETH_P_IPV6 )) +return 0 ; + hdr.ptr += hlen;/* Use an estimated value, since we also need to handle * TSO case.
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 315/744 drm/xe/i2c: Allow per domain unique id
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Raag Jadav <[email protected]>
[ Upstream commit 5d8ed6b64220ad629aade5f174e3f690c37435f9 ]
PCI bus, device and function can be same for devices existing across different domains. Allow per domain unique identifier while registering platform device to prevent name conflict.
--- drivers/gpu/drm/xe/xe_i2c.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
drivers/gpu/drm/xe/xe_i2c.c +4 -1
@@ -95,18 +95,21 @@ static int xe_i2c_register_adapter(struct xe_i2c *i2c)struct platform_device *pdev;struct fwnode_handle *fwnode;int ret; +u32 id; fwnode =fwnode_create_software_node (xe_i2c_adapter_properties,NULL );if (IS_ERR (fwnode))return PTR_ERR (fwnode); + id = (pci_domain_nr (pci->bus) <<16 ) |pci_dev_id (pci); +/* * Not using platform_device_register_full() here because we don't have * a handle to the platform_device before it returns. xe_i2c_notifier() * uses that handle, but it may be called before * platform_device_register_full() is done. */ - pdev =platform_device_alloc (adapter_name,pci_dev_id (pci)); + pdev =platform_device_alloc (adapter_name, id);if (!pdev) { ret = -ENOMEM ; goto err_fwnode_remove;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 316/744 drm/xe/vm: Fix SVM leak on resv obj alloc failure in xe_vm_create()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Shuicheng Lin <[email protected]>
[ Upstream commit d2c6800ad1802bed72a6de1416536737f114f1d6 ]
Commit 9e9787414882 ("drm/xe/userptr: replace xe_hmm with gpusvm") made xe_svm_init() unconditional in xe_vm_create() and extended it to also initialize a "simple" gpusvm state for non-fault-mode VMs. The matching xe_svm_fini() call in xe_vm_close_and_put() was updated to run unconditionally, but the error unwind path in xe_vm_create() was not.
On the drm_gpuvm_resv_object_alloc() failure path, xe_svm_init() has already succeeded but xe_svm_fini() is only called when XE_VM_FLAG_FAULT_MODE is set. For non-fault-mode VMs this leaves vm->svm.gpusvm partially initialized and leaks the resources allocated by drm_gpusvm_init().
For fault-mode VMs, xe_svm_init() additionally acquires the pagemap owner via drm_pagemap_acquire_owner() and the pagemaps via xe_svm_get_pagemaps(). Those resources are released by xe_svm_close(), not xe_svm_fini(). On the same error path, xe_svm_close() is not called either, so fault-mode VMs leak the pagemap owner and pagemaps.
Fix both leaks:
- Call xe_svm_fini() unconditionally on the err_svm_fini path, matching the unconditional xe_svm_init() call. Move the vm->size = 0 assignment out of the conditional so the xe_vm_is_closed() assert in xe_svm_fini() (and xe_svm_close()) holds for both modes.
- Call xe_svm_close() for fault-mode VMs before xe_svm_fini(), matching the ordering used in xe_vm_close_and_put().
--- drivers/gpu/drm/xe/xe_vm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/gpu/drm/xe/xe_vm.c +4 -4
@@ -1810,10 +1810,10 @@ struct xe_vm *xe_vm_create(struct xe_device *xe, u32 flags, struct xe_file *xef)return ERR_PTR (err); err_svm_fini: -if (flags &XE_VM_FLAG_FAULT_MODE ) { - vm->size =0 ;/* close the vm */ -xe_svm_fini (vm); - } + vm->size =0 ;/* close the vm */ +if (flags &XE_VM_FLAG_FAULT_MODE ) +xe_svm_close (vm); +xe_svm_fini (vm); err_no_resv:mutex_destroy (&vm->snap_mutex);for_each_tile (tile, xe, id)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 317/744 iomap: correct the range of a partial dirty clear
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Yi <[email protected]>
[ Upstream commit 88c26515313169806a412a362b32a1eca53d21bd ]
The block range calculation in ifs_clear_range_dirty() is incorrect when partially clearing a range in a folio. We cannot clear the dirty bit of the first block or the last block if the start or end offset is not blocksize-aligned. This has not yet caused any issues since we always clear a whole folio in iomap_writeback_folio().
Fix this by rounding up the first block to blocksize alignment, and calculate the last block by rounding down (using truncation). Correct the nr_blks calculation accordingly.
--- fs/iomap/buffered-io.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
fs/iomap/buffered-io.c +8 -4
@@ -176,13 +176,17 @@ static void ifs_clear_range_dirty(struct folio *folio, {struct inode *inode = folio->mapping->host;unsigned int blks_per_folio =i_blocks_per_folio (inode, folio); -unsigned int first_blk = (off >> inode->i_blkbits); -unsigned int last_blk = (off + len -1 ) >> inode->i_blkbits; -unsigned int nr_blks = last_blk - first_blk +1 ; +unsigned int first_blk =round_up (off,i_blocksize (inode)) >> + inode->i_blkbits; +unsigned int last_blk = (off + len) >> inode->i_blkbits;unsigned long flags; +if (first_blk >= last_blk) +return ; +spin_lock_irqsave (&ifs->state_lock, flags); -bitmap_clear (ifs->state, first_blk + blks_per_folio, nr_blks); +bitmap_clear (ifs->state, first_blk + blks_per_folio, + last_blk - first_blk);spin_unlock_irqrestore (&ifs->state_lock, flags); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 318/744 iomap: fix incorrect did_zero setting in iomap_zero_iter()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Zhang Yi <[email protected]>
[ Upstream commit 7a6fd6b21d7e1737b40de1a210acf9e6a1e4d59e ]
The did_zero output parameter was unconditionally set after the loop, which is incorrect. It should only be set when the zeroing operation actually completes, not when IOMAP_F_STALE is set or when IOMAP_F_FOLIO_BATCH is set but !folio causes the loop to break early, or when iomap_iter_advance() returns an error.
This causes did_zero to be incorrectly set when zeroing a clean unwritten extent because the loop exits early without actually zeroing any data.
Fix it by using a local variable to track whether any folio was actually zeroed, and only set did_zero after the loop if zeroing happened.
--- fs/iomap/buffered-io.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-)
fs/iomap/buffered-io.c +6 -2
@@ -1540,6 +1540,7 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero, const struct iomap_write_ops *write_ops) {u64 bytes =iomap_length (iter); +bool zeroed = false;int status; do {
@@ -1558,6 +1559,8 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero,/* a NULL folio means we're done with a folio batch */ if (!folio) { status =iomap_iter_advance_full (iter); +if (status) +return status;break ; }
@@ -1568,6 +1571,7 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero, bytes);folio_zero_range (folio, offset, bytes); + zeroed = true;folio_mark_accessed (folio); ret =iomap_write_end (iter, bytes, bytes, folio);
@@ -1577,10 +1581,10 @@ static int iomap_zero_iter(struct iomap_iter *iter, bool *did_zero, status =iomap_iter_advance (iter, bytes);if (status) -break ; +return status; }while ((bytes =iomap_length (iter)) >0 ); -if (did_zero) +if (did_zero && zeroed) *did_zero = true;return status; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 319/744 tipc: fix u16 MTU truncation in media and bearer MTU validation
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang (Microsoft) <[email protected]>
[ Upstream commit 9f29cd8a8e7901a2617c8064ce9f50fc67b97cb8 ]
Both TIPC_NL_MEDIA_SET and TIPC_NL_BEARER_SET accept user-supplied MTU values but only enforce a minimum bound, not a maximum. When a user sets the MTU to a value exceeding U16_MAX (65535), it passes validation but is silently truncated when assigned to u16 fields l->mtu and l->advertised_mtu in tipc_link_create(). Values like 65536 (0x10000) truncate to 0, causing a division by zero in tipc_link_set_queue_limits() which computes TIPC_MAX_PUBL / (l->mtu / ITEM_SIZE). Other overflowing values (e.g. 65537-131071) produce small incorrect MTU values, resulting in link malfunction behaviors.
Crash stack (triggered as unprivileged user via user namespace):
tipc_link_set_queue_limits net/tipc/link.c:2531 tipc_link_create net/tipc/link.c:520 tipc_node_check_dest net/tipc/node.c:1279 tipc_disc_rcv net/tipc/discover.c:252 tipc_rcv net/tipc/node.c:2129 tipc_udp_recv net/tipc/udp_media.c:392
Two independent paths lack the upper bound check:
1. tipc_udp_mtu_bad() -- called from __tipc_nl_media_set() (MEDIA_SET)
2. inline check in __tipc_nl_bearer_set() at bearer.c:1160 (BEARER_SET)
Fix both by rejecting MTU values above U16_MAX.
--- net/tipc/netlink.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
net/tipc/netlink.c +5 -1
@@ -113,12 +113,16 @@ const struct nla_policy tipc_nl_node_policy[TIPC_NLA_NODE_MAX + 1] = { };/* Properties valid for media, bearer and link */ +static const struct netlink_range_validation tipc_nl_mtu_range = { + .max =U16_MAX , +}; +const struct nla_policy tipc_nl_prop_policy[TIPC_NLA_PROP_MAX +1 ] = { [TIPC_NLA_PROP_UNSPEC ] = { .type =NLA_UNSPEC }, [TIPC_NLA_PROP_PRIO ] = { .type =NLA_U32 }, [TIPC_NLA_PROP_TOL ] = { .type =NLA_U32 }, [TIPC_NLA_PROP_WIN ] = { .type =NLA_U32 }, - [TIPC_NLA_PROP_MTU ] = { .type =NLA_U32 }, + [TIPC_NLA_PROP_MTU ] =NLA_POLICY_FULL_RANGE (NLA_U32 , &tipc_nl_mtu_range), [TIPC_NLA_PROP_BROADCAST ] = { .type =NLA_U32 }, [TIPC_NLA_PROP_BROADCAST_RATIO ] = { .type =NLA_U32 } };
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 320/744 drm/tests: shmem: Set DMA mask to 64-bit in drm_gem_shmem
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: José Expósito <[email protected]>
[ Upstream commit b04a248cfa6cfa1e7dc9ce91cb1eb88b1a70dd69 ]
drm_gem_shmem_test_purge [1] and drm_gem_shmem_test_get_pages_sgt [2] intermittently fail on ppc64le and s390x CI systems with a DMA address overflow:
DMA addr 0x0000000100307000+4096 overflow (mask ffffffff, bus limit 0)
WARNING: kernel/dma/direct.h:114 dma_direct_map_sg+0x778/0x920
drm_gem_shmem_test_purge: ASSERTION FAILED at
drivers/gpu/drm/tests/drm_gem_shmem_test.c:330 Expected sgt is not error, but is: -5
The call chain leading to the failure is:
drm_gem_shmem_test_purge() / drm_gem_shmem_test_get_pages_sgt()
drm_gem_shmem_get_pages_sgt()
drm_gem_shmem_get_pages_sgt_locked() [drm_gem_shmem_helper.c]
dma_map_sgtable() [mapping.c]
__dma_map_sg_attrs()
dma_direct_map_sg() [direct.c]
dma_direct_map_phys() [kernel/dma/direct.h]
dma_capable() Checks addr against DMA mask
-> FAILS: addr > 0xFFFFFFFFThe root cause is that KUnit devices are initialized with a 32-bit DMA mask (DMA_BIT_MASK(32)) in lib/kunit/device.c. On ppc64le and s390x systems with physical memory above 4GB, page allocations can land at addresses that exceed this mask. When drm_gem_shmem_get_pages_sgt() attempts to DMA-map these pages via dma_map_sgtable(), the DMA layer rejects the mapping because the physical address overflows the 32-bit mask.
The failure is intermittent because pages may or may not be allocated above 4GB on any given run depend on memory pressure.
Fix by setting a 64-bit DMA mask on the device before calling drm_gem_shmem_get_pages_sgt() for all tests, following the same pattern already used in drm_gem_shmem_test_obj_create_private().
[1] https://s3.amazonaws.com/arr-cki-prod-trusted-artifacts/trusted-artifacts/2643976103/test_s390x/15128551935/artifacts/jobwatch/logs/recipes/21561049/tasks/220716793/results/1014626315/logs/dmesg.log
[2] https://s3.amazonaws.com/arr-cki-prod-trusted-artifacts/trusted-artifacts/2643976103/test_ppc64le/15128551933/artifacts/jobwatch/logs/recipes/21561041/tasks/220716705/results/1014628163/logs/dmesg.log
--- drivers/gpu/drm/tests/drm_gem_shmem_test.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-)
drivers/gpu/drm/tests/drm_gem_shmem_test.c +10 -6
@@ -95,13 +95,9 @@ static void drm_gem_shmem_test_obj_create_private(struct kunit *test)sg_init_one (sgt->sgl, buf,TEST_SIZE );/* -* Set the DMA mask to 64-bits and map the sgtables -* otherwise drm_gem_shmem_free will cause a warning -* on debug kernels. +* Map the sgtables otherwise drm_gem_shmem_free will cause a warning on +* debug kernels. */ - ret =dma_set_mask (drm_dev->dev,DMA_BIT_MASK (64 )); -KUNIT_ASSERT_EQ (test, ret,0 ); - ret =dma_map_sgtable (drm_dev->dev, sgt,DMA_BIDIRECTIONAL ,0 );KUNIT_ASSERT_EQ (test, ret,0 );
@@ -352,11 +348,19 @@ static int drm_gem_shmem_test_init(struct kunit *test) {struct device *dev;struct drm_device *drm_dev; +int ret;/* Allocate a parent device */ dev =drm_kunit_helper_alloc_device (test);KUNIT_ASSERT_NOT_ERR_OR_NULL (test, dev); +/* +* Set the DMA mask to 64-bits to avoid intermittent failures calling +* drm_gem_shmem_get_pages_sgt(). +*/ + ret =dma_set_mask (dev,DMA_BIT_MASK (64 )); +KUNIT_ASSERT_EQ (test, ret,0 ); +/* * The DRM core will automatically initialize the GEM core and create * a DRM Memory Manager object which provides an address space pool
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 321/744 bpf: tcp: fix double sock release on batch realloc
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Xiang Mei (Microsoft) <[email protected]>
[ Upstream commit 980a813452754f8001704744e92f7aa697c53dd3 ]
bpf_iter_tcp_batch() releases the current batch via bpf_iter_tcp_put_batch(), which drops the socket refs and rewrites each slot with the socket cookie, then grows the batch. cur_sk/end_sk are kept for bpf_iter_tcp_resume(), but on realloc failure the function returns ERR_PTR() before resume runs, leaving cur_sk < end_sk over slots that now hold cookies rather than sock pointers. bpf_iter_tcp_seq_stop() then calls bpf_iter_tcp_put_batch() again and dereferences a cookie as a struct sock.
Empty the batch on the failure path so stop() does not release it again. The sockets were already freed by the first bpf_iter_tcp_put_batch(), so nothing leaks, and a later read() rescans the bucket from the start instead of skipping it. The sibling GFP_NOWAIT failure path still holds real socket references and is left for stop() to release.
BUG: KASAN: null-ptr-deref in __sock_gen_cookie Read of size 8 at addr 0000000000000059 by task exploit ... __sock_gen_cookie (net/core/sock_diag.c:28) bpf_iter_tcp_put_batch (net/ipv4/tcp_ipv4.c:2918) bpf_iter_tcp_seq_stop (net/ipv4/tcp_ipv4.c:3270) bpf_seq_read (kernel/bpf/bpf_iter.c:205) vfs_read (fs/read_write.c:572) ksys_read (fs/read_write.c:716) do_syscall_64 entry_SYSCALL_64_after_hwframe Kernel panic - not syncing: Fatal exception
--- net/ipv4/tcp_ipv4.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
net/ipv4/tcp_ipv4.c +4 -1
@@ -3144,8 +3144,11 @@ static struct sock *bpf_iter_tcp_batch(struct seq_file *seq)bpf_iter_tcp_put_batch (iter); err =bpf_iter_tcp_realloc_batch (iter, expected *3 /2 ,GFP_USER ); -if (err) +if (err) { + iter->cur_sk =0 ; + iter->end_sk =0 ;return ERR_PTR (err); + } sk =bpf_iter_tcp_resume (seq);if (!sk)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 322/744 net: stmmac: xgmac: fix l4 filter port overwrite on register update
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nazim Amirul <[email protected]>
[ Upstream commit 9fcf274d93af17396f20cccb63f1d4c17492a000 ]
The XGMAC_L4_ADDR register holds both source and destination port match values. The current implementation overwrites the entire register when configuring either port, so setting one silently erases the other.
Fix this by reading the register first, then masking and updating only the relevant field before writing back.
--- .../ethernet/stmicro/stmmac/dwxgmac2_core.c | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-)
drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c +16 -12
@@ -1370,36 +1370,40 @@ static int dwxgmac2_config_l4_filter(struct mac_device_info *hw, u32 filter_no, value &= ~XGMAC_L4PEN0 ; } - value &= ~(XGMAC_L4SPM0 |XGMAC_L4SPIM0 ); - value &= ~(XGMAC_L4DPM0 |XGMAC_L4DPIM0 );if (sa) { value |=XGMAC_L4SPM0 ;if (inv) value |=XGMAC_L4SPIM0 ; +else + value &= ~XGMAC_L4SPIM0 ; }else { value |=XGMAC_L4DPM0 ;if (inv) value |=XGMAC_L4DPIM0 ; +else + value &= ~XGMAC_L4DPIM0 ; } ret =dwxgmac2_filter_write (hw, filter_no,XGMAC_L3L4_CTRL , value);if (ret)return ret; -if (sa) { - value =FIELD_PREP (XGMAC_L4SP0 , match); + ret =dwxgmac2_filter_read (hw, filter_no,XGMAC_L4_ADDR , &value); +if (ret) +return ret; - ret =dwxgmac2_filter_write (hw, filter_no,XGMAC_L4_ADDR , value); -if (ret) -return ret; +if (sa) { + value &= ~XGMAC_L4SP0 ; + value |=FIELD_PREP (XGMAC_L4SP0 , match); }else { - value =FIELD_PREP (XGMAC_L4DP0 , match); - - ret =dwxgmac2_filter_write (hw, filter_no,XGMAC_L4_ADDR , value); -if (ret) -return ret; + value &= ~XGMAC_L4DP0 ; + value |=FIELD_PREP (XGMAC_L4DP0 , match); } + ret =dwxgmac2_filter_write (hw, filter_no,XGMAC_L4_ADDR , value); +if (ret) +return ret; +if (!en)return dwxgmac2_filter_write (hw, filter_no,XGMAC_L3L4_CTRL ,0 );
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 323/744 net: stmmac: fix l3l4 filter rejecting unsupported offload requests
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nazim Amirul <[email protected]>
[ Upstream commit 5536d7c843637e9430279b94935fcf7df98babb3 ]
The basic flow parser in tc_add_basic_flow() does not validate match keys before proceeding. Unsupported offload configurations such as partial protocol masks, non-IPv4 network proto, or non-TCP/UDP transport proto are silently accepted instead of returning -EOPNOTSUPP.
Add validation to return -EOPNOTSUPP early for:
- No network or transport proto present in the key
- Partial protocol mask (only full mask supported)
- Network proto is not IPv4
- Transport proto is not TCP or UDP
Each rejection includes an extack message so the user knows which part of the match is unsupported.
Also propagate -EOPNOTSUPP from tc_add_basic_flow() in tc_add_flow() by returning it directly rather than using break. The break was silently discarding the error for FLOW_CLS_REPLACE operations where entry->in_use is already true, causing tc_add_flow() to return 0 (success) for unsupported replace requests.
--- .../net/ethernet/stmicro/stmmac/stmmac_tc.c | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+)
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +34 -0
@@ -446,6 +446,7 @@ static int tc_parse_flow_actions(struct stmmac_priv *priv, }#define ETHER_TYPE_FULL_MASK cpu_to_be16(~0) +#define IP_PROTO_FULL_MASK 0xFF static int tc_add_basic_flow(struct stmmac_priv *priv, struct flow_cls_offload *cls,
@@ -461,6 +462,37 @@ static int tc_add_basic_flow(struct stmmac_priv *priv,flow_rule_match_basic (rule, &match); +/* Both network proto and transport proto not present in the key */ +if (!match.mask || !(match.mask->n_proto || match.mask->ip_proto)) { +NL_SET_ERR_MSG_MOD (cls->common.extack, +"filter must specify network or transport protocol" ); +return -EOPNOTSUPP ; + } + +/* If the proto is present in the key and is not full mask */ +if ((match.mask->n_proto && match.mask->n_proto !=ETHER_TYPE_FULL_MASK ) || + (match.mask->ip_proto && match.mask->ip_proto !=IP_PROTO_FULL_MASK )) { +NL_SET_ERR_MSG_MOD (cls->common.extack, +"only full protocol mask is supported" ); +return -EOPNOTSUPP ; + } + +/* Network proto is present in the key and is not IPv4 */ +if (match.mask->n_proto && match.key->n_proto !=cpu_to_be16 (ETH_P_IP )) { +NL_SET_ERR_MSG_MOD (cls->common.extack, +"only IPv4 network protocol is supported" ); +return -EOPNOTSUPP ; + } + +/* Transport proto is present in the key and is not TCP or UDP */ +if (match.mask->ip_proto && + match.key->ip_proto !=IPPROTO_TCP && + match.key->ip_proto !=IPPROTO_UDP ) { +NL_SET_ERR_MSG_MOD (cls->common.extack, +"only TCP and UDP transport protocols are supported" ); +return -EOPNOTSUPP ; + } + entry->ip_proto = match.key->ip_proto;return 0 ; }
@@ -598,6 +630,8 @@ static int tc_add_flow(struct stmmac_priv *priv, ret = tc_flow_parsers[i].fn (priv, cls, entry);if (!ret) entry->in_use = true; +else if (ret == -EOPNOTSUPP ) +return ret; }if (!entry->in_use)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 324/744 net: stmmac: reset residual action in L3L4 filters on delete
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nazim Amirul <[email protected]>
[ Upstream commit a448f821289934b961dd9d8d0beb006cc8937ba2 ]
When deleting an L3/L4 flower filter entry, the action field is not reset. If a filter was previously configured with a drop action, that action may persist and affect subsequent filter configurations unintentionally.
Clear the action field when the filter entry is deleted.
--- drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c +1 -0
@@ -661,6 +661,7 @@ static int tc_del_flow(struct stmmac_priv *priv, entry->in_use = false; entry->cookie =0 ; entry->is_l4 = false; + entry->action =0 ;return ret; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 325/744 net: stmmac: enable the MAC on link up for all supported speeds
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: vadik likholetov <[email protected]>
[ Upstream commit 9c99db3a2080b8c2cbbb1100369586a9bea43321 ]
stmmac_mac_link_down() clears the MAC's transmit and receive enable bits. stmmac_mac_link_up() is expected to set them again through stmmac_mac_set(..., true), but it first switches on the negotiated speed and returns early for a speed the switch does not list. The MAC is then left gated off.
The speed selection is split into three switches, keyed on the interface. The generic branch -- taken for everything that is neither USXGMII nor XLGMII, so including PHY_INTERFACE_MODE_10GBASER -- lists only SPEED_2500, SPEED_1000, SPEED_100 and SPEED_10.
MGBE on Tegra234 runs 10GBASE-R into an Aquantia AQR113C. That PHY does rate matching, so phylink_link_up() replaces the media speed with the MAC-side interface speed before calling into the MAC:
case RATE_MATCH_PAUSE: speed = phylink_interface_max_speed(link_state.interface); duplex = DUPLEX_FULL;
The driver is therefore called as
stmmac_mac_link_up(interface=10GBASER, speed=10000, duplex=1)
which falls through to "default: return;". The interface stops passing traffic after the first link flap.
The failure is easy to misread. The link still comes up, because the PHY is polled over MDIO and needs no MAC, so the interface reports carrier 1 at the media speed. The DMA is untouched, so its start bits stay set and descriptors are still consumed. Only the MAC itself is gated off: the receiver counts nothing (mmc_rx_framecount_gb stops advancing, RE is 0) and nothing reaches the wire (TE is 0). The interface survives boot only because stmmac_hw_setup(), called from ndo_open, enables the MAC unconditionally -- so the problem appears only once the cable has been unplugged and plugged back in, and "ip link set dev <ethX> down && ip link set dev <ethX> up" appears to fix it.
The interface is not what the speed bits depend on: with the single exception of 2.5G, which is selected through the XGMII block on USXGMII and through the regular speed bits otherwise, each speed maps to one field of struct mac_link. The per-interface switches are speed validation, and phylink already validates the speed against priv->hw->link.caps. So collapse the three switches into one keyed on the speed alone, keeping the interface test only for the 2.5G case. This covers 10G on 10GBASE-R, and equally 5G, and 1G/100/10 on USXGMII, all of which hit "default: return;" today.
A core that does not support a speed leaves the corresponding mac_link field at 0, and phylink will not offer it that speed in the first place. For dwxgmac2 at 10G, link.xgmii.speed10000 is XGMAC_CONFIG_SS_10000, which is 0 and is the correct speed selection for a 10GBASE-R MAC: ctrl then equals old_ctrl, the register write is skipped, and execution reaches stmmac_mac_set(..., true).
Log an error in the default case, since a speed with no entry here leaves the MAC disabled and the symptom does not point at the cause.
--- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 92 ++++++++----------- 1 file changed, 37 insertions(+), 55 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +37 -55
@@ -1083,63 +1083,45 @@ static void stmmac_mac_link_up(struct phylink_config *config, old_ctrl =readl (priv->ioaddr +MAC_CTRL_REG ); ctrl = old_ctrl & ~priv->hw->link.speed_mask; -if (interface ==PHY_INTERFACE_MODE_USXGMII ) { -switch (speed) { -case SPEED_10000 : - ctrl |= priv->hw->link.xgmii.speed10000; -break ; -case SPEED_5000 : - ctrl |= priv->hw->link.xgmii.speed5000; -break ; -case SPEED_2500 : +switch (speed) { +case SPEED_100000 : + ctrl |= priv->hw->link.xlgmii.speed100000; +break ; +case SPEED_50000 : + ctrl |= priv->hw->link.xlgmii.speed50000; +break ; +case SPEED_40000 : + ctrl |= priv->hw->link.xlgmii.speed40000; +break ; +case SPEED_25000 : + ctrl |= priv->hw->link.xlgmii.speed25000; +break ; +case SPEED_10000 : + ctrl |= priv->hw->link.xgmii.speed10000; +break ; +case SPEED_5000 : + ctrl |= priv->hw->link.xgmii.speed5000; +break ; +case SPEED_2500 : +if (interface ==PHY_INTERFACE_MODE_USXGMII ) ctrl |= priv->hw->link.xgmii.speed2500; -break ; -default : -return ; - } - }else if (interface ==PHY_INTERFACE_MODE_XLGMII ) { -switch (speed) { -case SPEED_100000 : - ctrl |= priv->hw->link.xlgmii.speed100000; -break ; -case SPEED_50000 : - ctrl |= priv->hw->link.xlgmii.speed50000; -break ; -case SPEED_40000 : - ctrl |= priv->hw->link.xlgmii.speed40000; -break ; -case SPEED_25000 : - ctrl |= priv->hw->link.xlgmii.speed25000; -break ; -case SPEED_10000 : - ctrl |= priv->hw->link.xgmii.speed10000; -break ; -case SPEED_2500 : - ctrl |= priv->hw->link.speed2500; -break ; -case SPEED_1000 : - ctrl |= priv->hw->link.speed1000; -break ; -default : -return ; - } - }else { -switch (speed) { -case SPEED_2500 : +else ctrl |= priv->hw->link.speed2500; -break ; -case SPEED_1000 : - ctrl |= priv->hw->link.speed1000; -break ; -case SPEED_100 : - ctrl |= priv->hw->link.speed100; -break ; -case SPEED_10 : - ctrl |= priv->hw->link.speed10; -break ; -default : -return ; - } +break ; +case SPEED_1000 : + ctrl |= priv->hw->link.speed1000; +break ; +case SPEED_100 : + ctrl |= priv->hw->link.speed100; +break ; +case SPEED_10 : + ctrl |= priv->hw->link.speed10; +break ; +default : +netdev_err (priv->dev, +"unsupported speed %s on %s, leaving the MAC disabled\n" , +phy_speed_to_str (speed),phy_modes (interface)); +return ; }if (priv->plat->fix_mac_speed)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 326/744 net: gre: fix lltx regression for GRE tunnels with SEQ/CSUM
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yun Zhou <[email protected]>
[ Upstream commit 675ed582c1aa4d919dd535490de08c015005c653 ]
Before commit 00d066a4d4ed ("netdev_features: convert NETIF_F_LLTX to dev->lltx"), NETIF_F_LLTX was set unconditionally in both __gre_tunnel_init() and ip6gre_tnl_init_features() alongside GRE_FEATURES:
dev->features |= GRE_FEATURES | NETIF_F_LLTX;
When that commit converted NETIF_F_LLTX to the dev->lltx flag, it placed 'dev->lltx = true' after the SEQ/CSUM early returns instead of before them. This causes GRE/GRETAP/ip6gre tunnels with SEQ or CSUM+encap to lose lockless TX, reintroducing _xmit_lock acquisition around their ndo_start_xmit. Since GRE xmit re-enters the stack via ip_tunnel_xmit(), holding _xmit_lock risks ABBA deadlock with the underlay device.
CPU0 CPU1
---- ----
lock(&qdisc_xmit_lock_key#6);
lock(&qdisc_xmit_lock_key#3);
lock(&qdisc_xmit_lock_key#6);
lock(&qdisc_xmit_lock_key#3);Fix by moving dev->lltx = true before the early returns in both functions, restoring the original unconditional behavior.
--- net/ipv4/ip_gre.c | 4 ++-- net/ipv6/ip6_gre.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-)
net/ipv4/ip_gre.c +2 -2
@@ -1018,6 +1018,8 @@ static void __gre_tunnel_init(struct net_device *dev) dev->features |=GRE_FEATURES ; dev->hw_features |=GRE_FEATURES ; + dev->lltx = true; +/* TCP offload with GRE SEQ is not supported, nor can we support 2 * levels of outer headers requiring an update. */
@@ -1029,8 +1031,6 @@ static void __gre_tunnel_init(struct net_device *dev) dev->features |=NETIF_F_GSO_SOFTWARE ; dev->hw_features |=NETIF_F_GSO_SOFTWARE ; - - dev->lltx = true; }static int ipgre_tunnel_init (struct net_device *dev)
net/ipv6/ip6_gre.c +2 -2
@@ -1455,6 +1455,8 @@ static void ip6gre_tnl_init_features(struct net_device *dev) dev->features |=GRE6_FEATURES ; dev->hw_features |=GRE6_FEATURES ; + dev->lltx = true; +/* TCP offload with GRE SEQ is not supported, nor can we support 2 * levels of outer headers requiring an update. */
@@ -1466,8 +1468,6 @@ static void ip6gre_tnl_init_features(struct net_device *dev) dev->features |=NETIF_F_GSO_SOFTWARE ; dev->hw_features |=NETIF_F_GSO_SOFTWARE ; - - dev->lltx = true; }static int ip6gre_tunnel_init_common (struct net_device *dev)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 327/744 mpls: Set rt->rt_nhn just before returning from mpls_nh_build_multi().
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit 3671f0419d90b98a02f313830595ab958c8b2025 ]
Commit f0914b8436c5 ("mpls: Hold dev refcnt for mpls_nh.") added change_nexthops() loop to call netdev_put() for the nexthop devices before freeing mpls_route.
Then, mpls_nh_build_multi() was also changed to avoid iterating uninitialised nexthops in mpls_rt_free_rcu().
However, setting rt->rt_nhn to 0 at the entry of mpls_nh_build_multi() makes the following change_nexthops() no-op.
Let's set rt->rt_nhn just before returning from mpls_nh_build_multi().
--- net/mpls/af_mpls.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-)
net/mpls/af_mpls.c +5 -3
@@ -922,8 +922,7 @@ static int mpls_nh_build_multi(struct mpls_route_config *cfg,struct nlattr *nla_via, *nla_newdst;int remaining = cfg->rc_mp_len;int err =0 ; - - rt->rt_nhn =0 ; +u8 nhs =0 ;change_nexthops (rt) {int attrlen;
@@ -959,12 +958,15 @@ static int mpls_nh_build_multi(struct mpls_route_config *cfg, rt->rt_nhn_alive--; rtnh =rtnh_next (rtnh, &remaining); - rt->rt_nhn++; + nhs++; }endfor_nexthops (rt); + rt->rt_nhn = nhs; +return 0 ; errout: + rt->rt_nhn = nhs;return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 328/744 octeontx2-vf: set TC flower flag on MCAM entry allocation
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Suman Ghosh <[email protected]>
[ Upstream commit 0d4d31e3cc5dd6204fa1495c4107f5075acce5ed ]
When MCAM entries are allocated for a VF netdev via the devlink mcam_count parameter, only OTX2_FLAG_NTUPLE_SUPPORT was set. That enabled ethtool ntuple filters but not tc flower offload. Also set OTX2_FLAG_TC_FLOWER_SUPPORT when entries are successfully allocated.
--- drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c | 1 + 1 file changed, 1 insertion(+)
drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c +1 -0
@@ -270,6 +270,7 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf, u16 count)if (allocated) { pfvf->flags |=OTX2_FLAG_MCAM_ENTRIES_ALLOC ; pfvf->flags |=OTX2_FLAG_NTUPLE_SUPPORT ; + pfvf->flags |=OTX2_FLAG_TC_FLOWER_SUPPORT ; }if (allocated != count)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 329/744 ipv4: icmp: fill flow parameters in icmp_route_lookup decoy lookup
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 853e164c2b321f0711361bc23505aaeb7dc432c3 ]
When Linux forwards a packet and needs to generate an ICMP error, icmp_route_lookup() performs a reverse-path relookup. For non-local destinations, it performs a decoy lookup to find the expected egress interface (rt2->dst.dev) before validating the path with ip_route_input().
Currently, the decoy flow structure (fl4_2) only sets .daddr = fl4_dec.saddr, leaving .saddr, .flowi4_dscp, .flowi4_proto, .flowi4_mark, .flowi4_oif, .fl4_sport, .fl4_dport, and .flowi4_uid zeroed out.
When policy routing rules (such as ip rule add from $SRC lookup 100, or dscp/fwmark/ipproto/port rules, or VRF bindings) are configured:
1. The decoy lookup fails to match the policy rule because saddr and other key flow selectors are missing in fl4_2.
2. It resolves a route using the default table instead, returning an incorrect egress netdev.
3. Passing the wrong netdev to ip_route_input() causes strict reverse-path filtering (rp_filter=1) to fail, logging false-positive "martian source" warnings and causing the relookup to fail.
Fix this by initializing fl4_2 from fl4_dec and:
- Swapping source/destination IP addresses.
- Swapping L4 ports for transport protocols with ports (TCP, UDP, SCTP, DCCP) so port-based policy routing matches correctly. Non-port protocols (such as ICMP or GRE) leave the flowi_uli union fields intact to prevent corruption.
- Setting .flowi4_oif = l3mdev_master_ifindex(route_lookup_dev) to ensure VRF routing tables are respected.
- Setting .flowi4_flags |= FLOWI_FLAG_ANYSRC to allow output route lookups for non-local source IP addresses.
- Using __ip_route_output_key() instead of ip_route_output_key() for fl4_2 so that raw FIB routing is used without triggering spurious XFRM policy lookups on the decoy flow (the actual XFRM lookup is performed later using fl4_dec).
--- net/ipv4/icmp.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-)
net/ipv4/icmp.c +15 -3
@@ -548,11 +548,23 @@ static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4,if (IS_ERR (rt2)) err =PTR_ERR (rt2); }else { -struct flowi4 fl4_2 = {}; +struct flowi4 fl4_2 = fl4_dec;unsigned long orefdst; - fl4_2.daddr = fl4_dec.saddr; - rt2 =ip_route_output_key (net, &fl4_2); +swap (fl4_2.daddr, fl4_2.saddr); +switch (fl4_2.flowi4_proto) { +case IPPROTO_TCP : +case IPPROTO_UDP : +case IPPROTO_SCTP : +case IPPROTO_DCCP : +swap (fl4_2.fl4_sport, fl4_2.fl4_dport); +break ; + } + + fl4_2.flowi4_oif =l3mdev_master_ifindex (route_lookup_dev); + fl4_2.flowi4_flags |=FLOWI_FLAG_ANYSRC ; + + rt2 =__ip_route_output_key (net, &fl4_2);if (IS_ERR (rt2)) { err =PTR_ERR (rt2); goto relookup_failed;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 330/744 ppp: annotate data races in ppp_generic
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 543adf072165aaf2e3b635c0476204f9658ed3bf ]
Several fields in struct ppp can be read or updated concurrently from multiple CPUs without synchronization, causing data races:
1. ppp->mru is read concurrently in ppp_receive_nonmp_frame() while being updated via PPPIOCSMRU ioctl. Protect ppp->mru updates in PPPIOCSMRU with ppp_recv_lock(ppp).
2. PPPIOCGFLAGS reads ppp->flags, ppp->xstate, and ppp->rstate unlocked. Wrap the read in ppp_lock(ppp) to get a consistent snapshot.
3. ppp->debug is updated via PPPIOCSDEBUG and read concurrently on fast paths. Annotate reads with READ_ONCE() and writes with WRITE_ONCE().
4. ppp->last_xmit and ppp->last_recv are updated on TX/RX data paths and read via PPPIOCGIDLE32 / PPPIOCGIDLE64 ioctls. Annotate with WRITE_ONCE() / READ_ONCE() and use max() to handle jiffies subtraction.
5. ppp->npmode[] is updated via PPPIOCSNPMODE and read on TX/RX paths. Annotate with WRITE_ONCE() / READ_ONCE().
--- drivers/net/ppp/ppp_generic.c | 50 ++++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 22 deletions(-)
drivers/net/ppp/ppp_generic.c +28 -22
@@ -810,7 +810,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)case PPPIOCSMRU :if (get_user (val, p))break ; +ppp_recv_lock (ppp); ppp->mru = val; +ppp_recv_unlock (ppp); err =0 ;break ;
@@ -831,7 +833,9 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)break ;case PPPIOCGFLAGS : +ppp_lock (ppp); val = ppp->flags | ppp->xstate | ppp->rstate; +ppp_unlock (ppp);if (put_user (val, p))break ; err =0 ;
@@ -855,7 +859,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)case PPPIOCSDEBUG :if (get_user (val, p))break ; - ppp->debug = val; +WRITE_ONCE (ppp->debug, val); err =0 ;break ;
@@ -866,16 +870,16 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)break ;case PPPIOCGIDLE32 : - idle32.xmit_idle = (jiffies - ppp->last_xmit) /HZ ; - idle32.recv_idle = (jiffies - ppp->last_recv) /HZ ; -if (copy_to_user (argp, &idle32,sizeof (idle32))) + idle32.xmit_idle =max (0L , (long )(jiffies -READ_ONCE (ppp->last_xmit))) /HZ ; + idle32.recv_idle =max (0L , (long )(jiffies -READ_ONCE (ppp->last_recv))) /HZ ; +if (copy_to_user (argp, &idle32,sizeof (idle32)))break ; err =0 ;break ;case PPPIOCGIDLE64 : - idle64.xmit_idle = (jiffies - ppp->last_xmit) /HZ ; - idle64.recv_idle = (jiffies - ppp->last_recv) /HZ ; + idle64.xmit_idle =max (0L , (long )(jiffies -READ_ONCE (ppp->last_xmit))) /HZ ; + idle64.recv_idle =max (0L , (long )(jiffies -READ_ONCE (ppp->last_recv))) /HZ ;if (copy_to_user (argp, &idle64,sizeof (idle64)))break ; err =0 ;
@@ -916,7 +920,7 @@ static long ppp_ioctl(struct file *file, unsigned int cmd, unsigned long arg)if (copy_to_user (argp, &npi,sizeof (npi)))break ; }else { - ppp->npmode[i] = npi.mode; +WRITE_ONCE (ppp->npmode[i], npi.mode);/* we may be able to transmit more packets now (??) */ netif_wake_queue (ppp->dev); }
@@ -1454,7 +1458,7 @@ ppp_start_xmit(struct sk_buff *skb, struct net_device *dev) goto outf;/* Drop, accept or reject the packet */ -switch (ppp->npmode[npi]) { +switch (READ_ONCE (ppp->npmode[npi])) {case NPMODE_PASS :break ;case NPMODE_QUEUE :
@@ -1790,7 +1794,7 @@ ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb) *(__be16 *)skb_push (skb,2 ) =htons (PPP_FILTER_OUTBOUND_TAG );if (ppp->pass_filter &&bpf_prog_run (ppp->pass_filter, skb) ==0 ) { -if (ppp->debug &1 ) +if (READ_ONCE (ppp->debug) &1 )netdev_printk (KERN_DEBUG , ppp->dev,"PPP: outbound frame " "not passed\n" );
@@ -1800,11 +1804,11 @@ ppp_prepare_tx_skb(struct ppp *ppp, struct sk_buff **pskb)/* if this packet passes the active filter, record the time */ if (!(ppp->active_filter &&bpf_prog_run (ppp->active_filter, skb) ==0 )) - ppp->last_xmit = jiffies; +WRITE_ONCE (ppp->last_xmit, jiffies);skb_pull (skb,2 );#else /* for data packets, record the time */ - ppp->last_xmit = jiffies; +WRITE_ONCE (ppp->last_xmit, jiffies);#endif /* CONFIG_PPP_FILTER */ }
@@ -2154,7 +2158,7 @@ static int ppp_mp_explode(struct ppp *ppp, struct sk_buff *skb) noskb:spin_unlock (&pch->downl); err_linearize: -if (ppp->debug &1 ) +if (READ_ONCE (ppp->debug) &1 )netdev_err (ppp->dev,"PPP: no memory (fragment)\n" );DEV_STATS_INC (ppp->dev, tx_errors); ++ppp->nxseq;
@@ -2502,7 +2506,7 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) *(__be16 *)skb_push (skb,2 ) =htons (PPP_FILTER_INBOUND_TAG );if (ppp->pass_filter &&bpf_prog_run (ppp->pass_filter, skb) ==0 ) { -if (ppp->debug &1 ) +if (READ_ONCE (ppp->debug) &1 )netdev_printk (KERN_DEBUG , ppp->dev,"PPP: inbound frame " "not passed\n" );
@@ -2511,14 +2515,14 @@ ppp_receive_nonmp_frame(struct ppp *ppp, struct sk_buff *skb) }if (!(ppp->active_filter &&bpf_prog_run (ppp->active_filter, skb) ==0 )) - ppp->last_recv = jiffies; +WRITE_ONCE (ppp->last_recv, jiffies);__skb_pull (skb,2 ); } else#endif /* CONFIG_PPP_FILTER */ - ppp->last_recv = jiffies; +WRITE_ONCE (ppp->last_recv, jiffies);if ((ppp->dev->flags &IFF_UP ) ==0 || - ppp->npmode[npi] !=NPMODE_PASS ) { +READ_ONCE (ppp->npmode[npi]) !=NPMODE_PASS ) {kfree_skb (skb); }else {/* chop off protocol */
@@ -2771,7 +2775,7 @@ ppp_mp_reconstruct(struct ppp *ppp) seq =seq_before (minseq,PPP_MP_CB (p)->sequence)? minseq +1 :PPP_MP_CB (p)->sequence; -if (ppp->debug &1 ) +if (READ_ONCE (ppp->debug) &1 )netdev_printk (KERN_DEBUG , ppp->dev,"lost frag %u..%u\n" , oldseq, seq-1 );
@@ -2820,7 +2824,7 @@ ppp_mp_reconstruct(struct ppp *ppp)struct sk_buff *tmp2; skb_queue_reverse_walk_from_safe(list, p, tmp2) { -if (ppp->debug &1 ) +if (READ_ONCE (ppp->debug) &1 )netdev_printk (KERN_DEBUG , ppp->dev,"discarding frag %u\n" ,PPP_MP_CB (p)->sequence);
@@ -2842,7 +2846,7 @@ ppp_mp_reconstruct(struct ppp *ppp) skb_queue_walk_safe(list, p, tmp) {if (p == head)break ; -if (ppp->debug &1 ) +if (READ_ONCE (ppp->debug) &1 )netdev_printk (KERN_DEBUG , ppp->dev,"discarding frag %u\n" ,PPP_MP_CB (p)->sequence);
@@ -2850,7 +2854,7 @@ ppp_mp_reconstruct(struct ppp *ppp)kfree_skb (p); } -if (ppp->debug &1 ) +if (READ_ONCE (ppp->debug) &1 ) netdev_printk(KERN_DEBUG, ppp->dev, " missed pkts %u..%u\n", ppp->nextseq,
@@ -3161,7 +3165,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)if (!ppp->rc_state)break ;if (ppp->rcomp->decomp_init (ppp->rc_state, dp, len, - ppp->file.index,0 , ppp->mru, ppp->debug)) { + ppp->file.index,0 , ppp->mru, +READ_ONCE (ppp->debug))) { ppp->rstate |=SC_DECOMP_RUN ; ppp->rstate &= ~(SC_DC_ERROR |SC_DC_FERROR ); }
@@ -3170,7 +3175,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)if (!ppp->xc_state)break ;if (ppp->xcomp->comp_init (ppp->xc_state, dp, len, - ppp->file.index,0 , ppp->debug)) + ppp->file.index,0 , +READ_ONCE (ppp->debug))) ppp->xstate |=SC_COMP_RUN ; }break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 331/744 hinic: remove unused ethtool RSS user configuration buffers
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Chenguang Zhao <[email protected]>
[ Upstream commit fe0c002928c6749b7f4a726f6f600f6dd70280ea ]
rss_indir_user and rss_hkey_user are allocated and filled in __set_rss_rxfh() when the user configures RSS via ethtool, but nothing ever reads them. hinic_get_rxfh() fetches the state from the device, and the hardware is programmed from the original indir/key arguments. These buffers only leaked on driver unload.
Drop the unused allocations, memcpys, and struct fields.
--- drivers/net/ethernet/huawei/hinic/hinic_dev.h | 2 -- .../net/ethernet/huawei/hinic/hinic_ethtool.c | 21 ------------------- 2 files changed, 23 deletions(-)
drivers/net/ethernet/huawei/hinic/hinic_dev.h +0 -2
@@ -104,8 +104,6 @@ struct hinic_dev {u16 num_rss;u16 rss_limit;struct hinic_rss_type rss_type; -u8 *rss_hkey_user; -s32 *rss_indir_user;struct hinic_intr_coal_info *rx_intr_coalesce;struct hinic_intr_coal_info *tx_intr_coalesce;struct hinic_sriov_info sriov_info;
drivers/net/ethernet/huawei/hinic/hinic_ethtool.c +0 -21
@@ -1064,17 +1064,6 @@ static int __set_rss_rxfh(struct net_device *netdev,int err;if (indir) { -if (!nic_dev->rss_indir_user) { - nic_dev->rss_indir_user = -kzalloc (sizeof (u32) *HINIC_RSS_INDIR_SIZE , -GFP_KERNEL ); -if (!nic_dev->rss_indir_user) -return -ENOMEM ; - } - -memcpy (nic_dev->rss_indir_user, indir, -sizeof (u32) *HINIC_RSS_INDIR_SIZE ); - err =hinic_rss_set_indir_tbl (nic_dev, nic_dev->rss_tmpl_idx, indir);if (err)
@@ -1082,16 +1071,6 @@ static int __set_rss_rxfh(struct net_device *netdev, }if (key) { -if (!nic_dev->rss_hkey_user) { - nic_dev->rss_hkey_user = -kzalloc (HINIC_RSS_KEY_SIZE *2 ,GFP_KERNEL ); - -if (!nic_dev->rss_hkey_user) -return -ENOMEM ; - } - -memcpy (nic_dev->rss_hkey_user, key,HINIC_RSS_KEY_SIZE ); - err =hinic_rss_set_template_tbl (nic_dev, nic_dev->rss_tmpl_idx, key);if (err)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 332/744 LoongArch: BPF: Zero-extend signed ALU32 div/mod results
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nicholas Dudar <[email protected]>
[ Upstream commit dacd348b8a993373576fe2ee2d8b114740ba57a6 ]
ALU32 operations write a 32-bit result and leave the upper 32 bits of the BPF register zero. The LoongArch JIT sign-extends the result of signed ALU32 BPF_DIV and BPF_MOD (off=1), so a negative 32-bit quotient or remainder leaves bits 63:32 set in JITted code while the verifier and interpreter model those bits as zero.
Keep sign-extension on the operands, which signed divide needs, and zero-extend the ALU32 result after the divide or modulo instruction, matching the unsigned ALU32 div/mod paths and every other ALU32 operation in this JIT.
--- arch/loongarch/net/bpf_jit.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
arch/loongarch/net/bpf_jit.c +4 -4
@@ -834,7 +834,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool extmove_reg (ctx, t1, src);emit_sext_32 (ctx, t1, is32);emit_insn (ctx, divd, dst, dst, t1); -emit_sext_32 (ctx, dst, is32); +emit_zext_32 (ctx, dst, is32); }break ;
@@ -851,7 +851,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool extemit_sext_32 (ctx, t1, is32);emit_sext_32 (ctx, dst, is32);emit_insn (ctx, divd, dst, dst, t1); -emit_sext_32 (ctx, dst, is32); +emit_zext_32 (ctx, dst, is32); }break ;
@@ -869,7 +869,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool extmove_reg (ctx, t1, src);emit_sext_32 (ctx, t1, is32);emit_insn (ctx, modd, dst, dst, t1); -emit_sext_32 (ctx, dst, is32); +emit_zext_32 (ctx, dst, is32); }break ;
@@ -886,7 +886,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool extemit_sext_32 (ctx, t1, is32);emit_sext_32 (ctx, dst, is32);emit_insn (ctx, modd, dst, dst, t1); -emit_sext_32 (ctx, dst, is32); +emit_zext_32 (ctx, dst, is32); }break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 333/744 net: qrtr: restrict socket creation to the initial network namespace
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Aldo Ariel Panzardo <[email protected]>
[ Upstream commit 3b536db8fb32da9e9c62f2bb45e2e319331f0426 ]
QRTR keeps its entire port and node state in module-global variables that are not partitioned per network namespace: qrtr_local_nid is a single global node id (always 1) and qrtr_ports is a single global xarray. qrtr_port_lookup() and qrtr_local_enqueue() operate on that global state with no network-namespace check, and qrtr_create() places no restriction on the namespace a socket is created in.
As a result an unprivileged process that creates an AF_QIPCRTR socket in a separate network namespace, e.g. via unshare(CLONE_NEWUSER | CLONE_NEWNET), can send QRTR datagrams - including control-plane messages such as QRTR_TYPE_NEW_SERVER - to QRTR sockets owned by another namespace, and vice versa. The receiving socket sees such a message as coming from node id 1, indistinguishable from a legitimate local client, breaking the isolation that network namespaces are expected to provide.
QRTR is a transport to global hardware endpoints (the modem and other remote processors) and has no per-namespace semantics; its in-kernel name service already creates its socket in init_net only. Confine the socket family to the initial network namespace, as other non-namespace-aware socket families do (see llc_ui_create() and the ieee802154 socket code).
--- net/qrtr/af_qrtr.c | 8 ++++++++ 1 file changed, 8 insertions(+)
net/qrtr/af_qrtr.c +8 -0
@@ -1261,6 +1261,14 @@ static int qrtr_create(struct net *net, struct socket *sock,if (sock->type !=SOCK_DGRAM )return -EPROTOTYPE ; +/* QRTR keeps its port and node state in module-global variables that +* are not partitioned per network namespace, and the in-kernel name +* service only operates in init_net. Confine the family to init_net so +* a socket in another namespace cannot reach the global control plane. +*/ +if (!net_eq (net, &init_net)) +return -EAFNOSUPPORT ; + sk =sk_alloc (net,AF_QIPCRTR ,GFP_KERNEL , &qrtr_proto, kern);if (!sk)return -ENOMEM ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 334/744 raw: annotate lockless match fields in raw_v4_match()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Runyu Xiao <[email protected]>
[ Upstream commit 18f116931f52e3c3303ad4b15ff41eb89b0e4239 ]
raw_v4_match() is a lockless match helper under sk_for_each_rcu(). It still reads inet->inet_daddr, inet->inet_rcv_saddr and sk->sk_bound_dev_if with plain loads while bind, connect and bind-to-device paths can update the same match fields concurrently.
Annotate only those mutable match fields in raw_v4_match(), and do so at the point of use instead of hoisting the bound-device read before the earlier short-circuit tests.
Also annotate the raw bind writer and the shared IPv4 datagram connect writer used by raw sockets, so the address fields updated on bind and connect match explicit WRITE_ONCE() updates.
This version intentionally leaves the shared disconnect-side IPv4 writers to follow-up cleanup and limits the writer changes here to the raw bind path and the datagram connect path directly exercised by raw sockets.
--- net/ipv4/datagram.c | 4 ++-- net/ipv4/raw.c | 23 ++++++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-)
net/ipv4/datagram.c +2 -2
@@ -63,12 +63,12 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr_unsized *uaddr, int }/* Update addresses before rehashing */ - inet->inet_daddr = fl4->daddr; +WRITE_ONCE (inet->inet_daddr, fl4->daddr); inet->inet_dport = usin->sin_port;if (!inet->inet_saddr) inet->inet_saddr = fl4->saddr;if (!inet->inet_rcv_saddr) { - inet->inet_rcv_saddr = fl4->saddr; +WRITE_ONCE (inet->inet_rcv_saddr, fl4->saddr);if (sk->sk_prot->rehash) sk->sk_prot->rehash (sk); }
net/ipv4/raw.c +16 -7
@@ -120,13 +120,21 @@ bool raw_v4_match(struct net *net, const struct sock *sk, unsigned short num, __be32 raddr, __be32 laddr, int dif, int sdif) { const struct inet_sock *inet = inet_sk(sk); +__be32 daddr, rcv_saddr; -if (net_eq (sock_net (sk), net) && inet->inet_num == num && - !(inet->inet_daddr && inet->inet_daddr != raddr) && - !(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) && -raw_sk_bound_dev_eq (net, sk->sk_bound_dev_if, dif, sdif)) -return true; -return false; +if (!net_eq (sock_net (sk), net) || inet->inet_num != num) +return false; + + daddr =READ_ONCE (inet->inet_daddr); +if (daddr && daddr != raddr) +return false; + + rcv_saddr =READ_ONCE (inet->inet_rcv_saddr); +if (rcv_saddr && rcv_saddr != laddr) +return false; + +return raw_sk_bound_dev_eq (net,READ_ONCE (sk->sk_bound_dev_if), + dif, sdif); }EXPORT_SYMBOL_GPL (raw_v4_match);
@@ -724,7 +732,8 @@ static int raw_bind(struct sock *sk, struct sockaddr_unsized *uaddr, chk_addr_ret)) goto out; - inet->inet_rcv_saddr = inet->inet_saddr = addr->sin_addr.s_addr; + inet->inet_saddr = addr->sin_addr.s_addr; +WRITE_ONCE (inet->inet_rcv_saddr, addr->sin_addr.s_addr);if (chk_addr_ret ==RTN_MULTICAST || chk_addr_ret ==RTN_BROADCAST ) inet->inet_saddr =0 ;/* Use device */ sk_dst_reset (sk);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 335/744 net/mlx5: Fix MCIA register buffer overflow on 32 dword reads
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Gal Pressman <[email protected]>
[ Upstream commit 11c057d23465c7a5817a7284c896d19d54c0b616 ]
The MCIA register can return up to 32 dwords (128 bytes) when the device advertises the mcia_32dwords capability, but struct mlx5_ifc_mcia_reg_bits only defines dword_0..11, leaving room for just 12 dwords (48 bytes) of data.
mlx5_query_mcia() clamps the read size to mlx5_mcia_max_bytes() and then memcpy()s that many bytes out of the register, potentially reading past the end of the 'out' buffer. On kernels built with FORTIFY_SOURCE this is caught as a buffer overflow while reading the module EEPROM via ethtool:
detected buffer overflow in memcpy
kernel BUG at lib/string_helpers.c:1048!
RIP: 0010:fortify_panic+0x13/0x20 Call Trace: mlx5_query_mcia.isra.0+0x200/0x210 [mlx5_core] mlx5_query_module_eeprom_by_page+0x4a/0xa0 [mlx5_core] mlx5e_get_module_eeprom_by_page+0xbb/0x120 [mlx5_core] eeprom_prepare_data+0xf3/0x170 ethnl_default_doit+0xf1/0x3b0
Extend the mcia_reg layout to 32 dwords.
--- drivers/net/ethernet/mellanox/mlx5/core/port.c | 4 ++-- include/linux/mlx5/mlx5_ifc.h | 13 +------------ 2 files changed, 3 insertions(+), 14 deletions(-)
drivers/net/ethernet/mellanox/mlx5/core/port.c +2 -2
@@ -314,7 +314,7 @@ static int mlx5_query_module_id(struct mlx5_core_dev *dev, int module_num,return -EIO ; } - ptr =MLX5_ADDR_OF (mcia_reg, out, dword_0); + ptr =MLX5_ADDR_OF (mcia_reg, out, dwords); *module_id = ptr[0 ];
@@ -399,7 +399,7 @@ static int mlx5_query_mcia(struct mlx5_core_dev *dev,return -EIO ; } - ptr =MLX5_ADDR_OF (mcia_reg, out, dword_0); + ptr =MLX5_ADDR_OF (mcia_reg, out, dwords);memcpy (data, ptr, size);return size;
include/linux/mlx5/mlx5_ifc.h +1 -12
@@ -12203,18 +12203,7 @@ struct mlx5_ifc_mcia_reg_bits {u8 reserved_at_60[0x20 ]; -u8 dword_0[0x20 ]; -u8 dword_1[0x20 ]; -u8 dword_2[0x20 ]; -u8 dword_3[0x20 ]; -u8 dword_4[0x20 ]; -u8 dword_5[0x20 ]; -u8 dword_6[0x20 ]; -u8 dword_7[0x20 ]; -u8 dword_8[0x20 ]; -u8 dword_9[0x20 ]; -u8 dword_10[0x20 ]; -u8 dword_11[0x20 ]; +u8 dwords[0x400 ]; };struct mlx5_ifc_dcbx_param_bits {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 336/744 net/mlx5: E-Switch, fix zero num_dest in prio_tag egress vlan rule
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yael Chemla <[email protected]>
[ Upstream commit d12956d083eb70f2c6d72711aebaf8c2ce21e170 ]
esw_egress_acl_vlan_create() hardcodes num_dest=0 in its mlx5_add_flow_rules() call. When invoked from the non-bond path fwd_dest is NULL and num_dest=0 is correct. When invoked from esw_acl_egress_ofld_rules_create() during a bond event, fwd_dest is non-NULL and flow_act.action carries MLX5_FLOW_CONTEXT_ACTION_FWD_DEST, but _mlx5_add_flow_rules() rejects a non-NULL dest pointer paired with dest_num<=0 and returns -EINVAL. The error propagates as "configure slave vport egress fwd, err(-22)". The passive vport's egress ACL table ends up with its flow groups allocated but no FTEs, so prio-tagged packets are not popped and bond failover is broken on prio_tag_required devices.
Fix by passing fwd_dest ? 1 : 0 as num_dest to match the actual number of destinations supplied.
--- drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/mellanox/mlx5/core/esw/acl/helper.c +1 -1
@@ -71,7 +71,7 @@ int esw_egress_acl_vlan_create(struct mlx5_eswitch *esw, flow_act.action = flow_action; vport->egress.allowed_vlan =mlx5_add_flow_rules (vport->egress.acl, spec, - &flow_act, fwd_dest,0 ); + &flow_act, fwd_dest, fwd_dest ?1 :0 );if (IS_ERR (vport->egress.allowed_vlan)) { err =PTR_ERR (vport->egress.allowed_vlan); esw_warn(esw->dev,
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 337/744 net/mlx5e: Report zero bandwidth for non-ETS traffic classes
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexei Lazar <[email protected]>
[ Upstream commit ffb1873b2df11945b8c395e859169248675c91c5 ]
The IEEE 802.1Qaz standard defines that bandwidth allocation percentages only apply to Enhanced Transmission Selection (ETS) traffic classes. For STRICT and VENDOR transmission selection algorithms, bandwidth percentage values are not applicable.
Currently for non-ETS 100 bandwidth is being reported for all traffic classes in the get operation due to hardware limitation, regardless of their TSA type.
Fix this by reporting 0 for non-ETS traffic classes.
--- drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 7 +++++++ 1 file changed, 7 insertions(+)
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +7 -0
@@ -173,6 +173,13 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev, }memcpy (ets->tc_tsa, priv->dcbx.tc_tsa,sizeof (ets->tc_tsa)); +/* Report 0 for non ETS TSA */ +for (i =0 ; i < ets->ets_cap; i++) { +if (ets->tc_tx_bw[i] ==MLX5E_MAX_BW_ALLOC && + priv->dcbx.tc_tsa[i] !=IEEE_8021QAZ_TSA_ETS ) + ets->tc_tx_bw[i] =0 ; + } +return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 338/744 net/mlx5e: Reject unsupported CB Shaper TSA in ETS validation
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Alexei Lazar <[email protected]>
[ Upstream commit 9173e1d3c7c7d49a71eee813091f9e834ec7cee5 ]
Credit Based (CB) TSA is not supported by the mlx5 driver, so reject any configurations that specify it.
--- drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c | 8 ++++++++ 1 file changed, 8 insertions(+)
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c +8 -0
@@ -324,6 +324,14 @@ static int mlx5e_dbcnl_validate_ets(struct net_device *netdev, } } +for (i =0 ; i <IEEE_8021QAZ_MAX_TCS ; i++) { +if (ets->tc_tsa[i] ==IEEE_8021QAZ_TSA_CB_SHAPER ) { +netdev_err (netdev, +"Failed to validate ETS: CB Shaper is not supported\n" ); +return -EOPNOTSUPP ; + } + } +/* Validate Bandwidth Sum */ for (i =0 ; i <IEEE_8021QAZ_MAX_TCS ; i++) {if (ets->tc_tsa[i] ==IEEE_8021QAZ_TSA_ETS ) {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 339/744 octeontx2-pf: tc: fix egress ratelimiting
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Hariprasad Kelam <[email protected]>
[ Upstream commit bb0d96ebe5f4d1acccf4dc36ca7f01f9a8fa1ba1 ]
The egress rate calculation computes an incorrect mantissa and exponent, causing up to ~50% deviation from the configured rate at lower speeds.
Rework the computation to follow the hardware rate formula:
rate = 2 * (1 + mantissa/256) * 2^exp / (1 << div_exp)
Keep div_exp = 0 and derive exp and mantissa from half of the requested rate. Rates below 2 Mbps are floored to the smallest encodable step (exp = 0, mantissa = 0).
--- .../ethernet/marvell/octeontx2/nic/otx2_tc.c | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-)
drivers/net/ethernet/marvell/octeontx2/nic/otx2_tc.c +16 -13
@@ -30,6 +30,7 @@#define OTX2_UNSUPP_LSE_DEPTH GENMASK(6, 4)#define MCAST_INVALID_GRP (-1U) +#define RATE_MANTISSA_BITS 8static void otx2_get_egress_burst_cfg (struct otx2_nic *nic,u32 burst,u32 *burst_exp,u32 *burst_mantissa)
@@ -66,28 +67,30 @@ static void otx2_get_egress_burst_cfg(struct otx2_nic *nic, u32 burst,static void otx2_get_egress_rate_cfg (u64 maxrate,u32 *exp,u32 *mantissa,u32 *div_exp) { -u64 tmp; -/* Rate calculation by hardware * * PIR_ADD = ((256 + mantissa) << exp) / 256 * rate = (2 * PIR_ADD) / ( 1 << div_exp) * The resultant rate is in Mbps. +* +* Use div_exp = 0 and compute exp/mantissa for maxrate / 2; the +* leading factor of two yields the full rate. Rates below 2 Mbps +* are floored to the smallest step (exp = 0, mantissa = 0). */ -/* 2Mbps to 100Gbps can be expressed with div_exp = 0. -* Setting this to '0' will ease the calculation of -* exponent and mantissa. -*/ *div_exp =0 ; -if (maxrate) { - *exp =ilog2 (maxrate) ?ilog2 (maxrate) -1 :0 ; - tmp = maxrate -rounddown_pow_of_two (maxrate); -if (maxrate <MAX_RATE_MANTISSA ) - *mantissa = tmp *2 ; -else - *mantissa = tmp / (1ULL << (*exp -7 )); + maxrate = maxrate /2 ; +if (!maxrate) { +/* Rates below 2 Mbps map to the smallest step */ + *exp =0 ; + *mantissa =0 ; + }else { + *exp =ilog2 (maxrate); +/* Clear MSB and derive fractional bits */ + maxrate &= ~BIT (*exp); + *mantissa = (maxrate <<RATE_MANTISSA_BITS ) >> *exp; + } }else {/* Instead of disabling rate limiting, set all values to max */ *exp =MAX_RATE_EXPONENT ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 340/744 net: ipv6: fix dif and sdif mismatch in raw6_icmp_error
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Li RongQing <[email protected]>
[ Upstream commit 440e274da4d1b93c7df2cb0ce893c3009dd4db55 ]
In raw6_icmp_error(), raw_v6_match() is called with inet6_iif(skb) passed to both the 'dif' and 'sdif' arguments. This is a copy-paste or typo error, as the last argument should represent the secondary interface index (sdif).
This mismatch breaks ICMPv6 error handling for IPv6 raw sockets in VRF (Virtual Routing and Forwarding) environments. When a raw socket is bound to a VRF master device, raw_v6_match() fails to find a match because it is not given the correct sdif value, causing the socket to miss relevant ICMPv6 error notifications.
Fix this by properly passing inet6_sdif(skb) as the last argument to raw_v6_match().
--- net/ipv6/raw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
net/ipv6/raw.c +1 -1
@@ -349,7 +349,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr,const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data;if (!raw_v6_match (net, sk, nexthdr, &ip6h->saddr, &ip6h->daddr, -inet6_iif (skb),inet6_iif (skb))) +inet6_iif (skb),inet6_sdif (skb)))continue ;rawv6_err (sk, skb, type, code, inner_offset, info); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 341/744 ice: allow creating VFs when !CONFIG_ICE_SWITCHDEV
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vincent Chen <[email protected]>
[ Upstream commit 99d0f42b0e5c57e4c02070a908aaff082881293a ]
Currently ice_eswitch_attach_vf() is called unconditionally in ice_start_vfs(), which causes VF creation to fail when CONFIG_ICE_SWITCHDEV is not defined.
Fix this by adding switchdev mode checks at the call sites before calling ice_eswitch_attach_vf(), consistent with how ice_eswitch_attach_sf() is already handled in ice_devlink_port_new(). This is similar to commit aacca7a83b97 ("ice: allow creating VFs for !CONFIG_NET_SWITCHDEV") which fixed the same issue for the previous ice_eswitch_configure() API.
--- drivers/net/ethernet/intel/ice/ice_eswitch.c | 3 --- drivers/net/ethernet/intel/ice/ice_sriov.c | 14 ++++++++------ drivers/net/ethernet/intel/ice/ice_vf_lib.c | 3 ++- 3 files changed, 10 insertions(+), 10 deletions(-)
drivers/net/ethernet/intel/ice/ice_eswitch.c +0 -3
@@ -512,9 +512,6 @@ int ice_eswitch_attach_vf(struct ice_pf *pf, struct ice_vf *vf)struct ice_repr *repr;int err; -if (!ice_is_eswitch_mode_switchdev (pf)) -return 0 ; - repr =ice_repr_create_vf (vf);if (IS_ERR (repr))return PTR_ERR (repr);
drivers/net/ethernet/intel/ice/ice_sriov.c +8 -6
@@ -484,12 +484,14 @@ static int ice_start_vfs(struct ice_pf *pf) goto teardown; } - retval =ice_eswitch_attach_vf (pf, vf); -if (retval) { -dev_err (ice_pf_to_dev (pf),"Failed to attach VF %d to eswitch, error %d" , - vf->vf_id, retval); -ice_vf_vsi_release (vf); - goto teardown; +if (ice_is_eswitch_mode_switchdev (pf)) { + retval =ice_eswitch_attach_vf (pf, vf); +if (retval) { +dev_err (ice_pf_to_dev (pf),"Failed to attach VF %d to eswitch, error %d" , + vf->vf_id, retval); +ice_vf_vsi_release (vf); + goto teardown; + } }set_bit (ICE_VF_STATE_INIT , vf->vf_states);
drivers/net/ethernet/intel/ice/ice_vf_lib.c +2 -1
@@ -812,7 +812,8 @@ void ice_reset_all_vfs(struct ice_pf *pf) }ice_vf_post_vsi_rebuild (vf); -ice_eswitch_attach_vf (pf, vf); +if (ice_is_eswitch_mode_switchdev (pf)) +ice_eswitch_attach_vf (pf, vf);mutex_unlock (&vf->cfg_lock); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 342/744 ice: fix LAG recipe to profile association
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Marcin Szycik <[email protected]>
[ Upstream commit d6da9b7d48599db078aea6144997a381f8d90d45 ]
ice_init_lag() associates recipes to profiles, assuming that Link Aggregation-related profiles will always have profile ID lower than 70 (ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER). This value seems arbitrary and might not always be valid for some versions of DDP package, i.e. LAG profiles may have profile ID greater than 70. This would lead to misconfigured switch and LAG not working properly.
Fix it by checking up to maximum profile ID.
--- drivers/net/ethernet/intel/ice/ice_lag.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/net/ethernet/intel/ice/ice_lag.c +1 -1
@@ -2623,7 +2623,7 @@ int ice_init_lag(struct ice_pf *pf) goto free_lport_res;/* associate recipes to profiles */ -for (n =0 ; n <ICE_PROFID_IPV6_GTPU_IPV6_TCP_INNER ; n++) { +for (n =0 ; n <ICE_MAX_NUM_PROFILES ; n++) { err =ice_aq_get_recipe_to_profile (&pf->hw, n, &recipe_bits,NULL );if (err)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 343/744 ice: prevent tstamp ring allocation for non-PF VSI types
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Paul Greenwalt <[email protected]>
[ Upstream commit 144539bbfd3cea1ab0fb6f5216d6004c1f4f029b ]
The pf->txtime_txqs bitmap tracks which Tx queues have ETF (Earliest TxTime First) offload enabled. This bitmap is indexed by queue number and is set by ice_offload_txtime(), which only operates on PF VSI queues.
However, ice_is_txtime_ena() does not check the VSI type before consulting the bitmap. When ETF offload is enabled on PF Tx queue 0, bit 0 is set in pf->txtime_txqs. During a subsequent PCI reset rebuild, the CTRL VSI's Tx queue 0 is reconfigured and ice_is_txtime_ena() is called for that ring. Since it only checks pf->txtime_txqs by queue index without distinguishing VSI type, it finds bit 0 set and returns true, matching the PF VSI's ETF queue, not the CTRL VSI's. This causes ice_vsi_cfg_txq() to spuriously allocate a tstamp_ring for the CTRL VSI ring.
Since CTRL VSI rings have no associated netdev, ice_clean_tx_ring() takes an early return at the !netdev check before reaching ice_free_tx_tstamp_ring(), leaking the allocation. Each PCI reset leaks one 64-byte tstamp_ring.
Fix this by restricting ice_is_txtime_ena() to return true only for PF VSI rings, since txtime_txqs is only meaningful for PF VSI queues.
--- drivers/net/ethernet/intel/ice/ice.h | 3 +++ 1 file changed, 3 insertions(+)
drivers/net/ethernet/intel/ice/ice.h +3 -0
@@ -767,6 +767,9 @@ static inline bool ice_is_txtime_ena(const struct ice_tx_ring *ring)struct ice_vsi *vsi = ring->vsi;struct ice_pf *pf = vsi->back; +if (vsi->type !=ICE_VSI_PF ) +return false; +return test_bit (ring->q_index, pf->txtime_txqs); }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 344/744 idpf: fix max_vport related crash on allocation error during init
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Emil Tantilov <[email protected]>
[ Upstream commit 237f1f7653b8729169af11fae79f01b90d00b87e ]
Set adapter->max_vports only after successful allocation of vports, netdevs and vport_config buffers. This fixes possible crashes on reset or rmmod, following failed allocation on init
[ 305.981402] idpf 0000:83:00.0: enabling device (0100 -> 0102) [ 305.994464] idpf 0000:83:00.0: Device HW Reset initiated [ 320.416872] BUG: kernel NULL pointer dereference, address: 0000000000000000 [ 320.416918] #PF: supervisor read access in kernel mode [ 320.416942] #PF: error_code(0x0000) - not-present page [ 320.416963] PGD 2099657067 P4D 0 [ 320.416983] Oops: Oops: 0000 [#1] SMP NOPTI ... [ 320.417093] RIP: 0010:idpf_remove+0x118/0x200 [idpf] [ 320.417130] Code: 8b bb 98 09 00 00 e8 17 0f 5b e5 48 8b bb e8 08 00 00 e8 0b 0f 5b e5 66 83 bb 28 06 00 00 00 48 8b bb 20 06 00 00 74 49 31 ed <48> 8b 04 ef 48 85 c0 74 2f 48 8b 78 20 e8 66 58 91 e5 48 8b 83 20 [ 320.417183] RSP: 0018:ff7322212903fdb8 EFLAGS: 00010246 [ 320.417205] RAX: 0000000000000000 RBX: ff4463de40300000 RCX: ff7322212903fd4c [ 320.417228] RDX: 0000000000000001 RSI: ffffffffa7f7d100 RDI: 0000000000000000 [ 320.417250] RBP: 0000000000000000 R08: 0000000000000001 R09: 0000000000000000 [ 320.417272] R10: 0000000000000001 R11: ff4463de3a638f58 R12: ff4463be89ac7000 [ 320.417294] R13: ff4463be89ac7198 R14: ff4463be94fc7198 R15: ffffffffc0f10f20 [ 320.417317] FS: 00007f963c0e6740(0000) GS:ff4463fdd65d8000(0000) knlGS:0000000000000000 [ 320.417342] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 320.417362] CR2: 0000000000000000 CR3: 00000020ba674002 CR4: 0000000000773ef0 [ 320.417385] PKRU: 55555554 [ 320.417398] Call Trace: [ 320.417412] <TASK> [ 320.417429] pci_device_remove+0x42/0xb0 [ 320.417459] device_release_driver_internal+0x1a9/0x210 [ 320.417492] driver_detach+0x4b/0x90 [ 320.417516] bus_remove_driver+0x70/0x100 [ 320.417539] pci_unregister_driver+0x2e/0xb0 [ 320.417564] __do_sys_delete_module.constprop.0+0x190/0x2f0 [ 320.417592] ? kmem_cache_free+0x31e/0x550 [ 320.417619] ? lockdep_hardirqs_on_prepare+0xde/0x190 [ 320.417644] ? do_syscall_64+0x38/0x6b0 [ 320.417665] do_syscall_64+0xc8/0x6b0 [ 320.417683] ? clear_bhb_loop+0x30/0x80 [ 320.417706] entry_SYSCALL_64_after_hwframe+0x76/0x7e [ 320.417727] RIP: 0033:0x7f963bb30beb
--- drivers/net/ethernet/intel/idpf/idpf_virtchnl.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
drivers/net/ethernet/intel/idpf/idpf_virtchnl.c +6 -1
@@ -3555,7 +3555,6 @@ int idpf_vc_core_init(struct idpf_adapter *adapter)pci_sriov_set_totalvfs (adapter->pdev,idpf_get_max_vfs (adapter)); num_max_vports =idpf_get_max_vports (adapter); - adapter->max_vports = num_max_vports; adapter->vports =kzalloc_objs (*adapter->vports, num_max_vports);if (!adapter->vports)return -ENOMEM ;
@@ -3576,6 +3575,12 @@ int idpf_vc_core_init(struct idpf_adapter *adapter) goto err_netdev_alloc; } +/* Set max_vports only after vports, netdevs and vport_config buffers +* are allocated to make sure max_vport bound loops don't end up +* crashing, following allocation errors on init. +*/ + adapter->max_vports = num_max_vports; +/* Start the mailbox task before requesting vectors. This will ensure * vector information response from mailbox is handled */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 345/744 ipv6: Change allocation flags to match rcu_read_lock section requirements
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Nikola Z. Ivanov <[email protected]>
[ Upstream commit 313a123e1fca8827bb463db1f4bb211309764563 ]
Since the call to __ip6_del_rt_siblings has been converted under rcu read lock and it only has one call point
we should no longer block or yield.
Our stack trace from the syzbot reproducer looks as follows:
__ip6_del_rt_siblings
rtnl_notify (Here we pass gfp_any() -> GFP_KERNEL)
nlmsg_notify
nlmsg_multicast
nlmsg_multicast_filtered
netlink_broadcast_filtered (GFP_KERNEL passed from earlier)
netlink_broadcast_filtered can yield if GFP_KERNEL is passed, which we do not want to happen.
Fix this by changing the allocation flag of rtnl_notify.
Also change the flag passed to nlmsg_new. Even though it is not related to the syzbot generated bug it still falls under the same requirements.
--- net/ipv6/route.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/ipv6/route.c +2 -2
@@ -4020,7 +4020,7 @@ static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg)struct fib6_node *fn;/* prefer to send a single notification with all hops */ - skb =nlmsg_new (rt6_nlmsg_size (rt),gfp_any ()); + skb =nlmsg_new (rt6_nlmsg_size (rt),GFP_ATOMIC );if (skb) {u32 seq = info->nlh ? info->nlh->nlmsg_seq :0 ;
@@ -4076,7 +4076,7 @@ static int __ip6_del_rt_siblings(struct fib6_info *rt, struct fib6_config *cfg)if (skb) {rtnl_notify (skb, net, info->portid,RTNLGRP_IPV6_ROUTE , - info->nlh,gfp_any ()); + info->nlh,GFP_ATOMIC ); }return err; }
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 346/744 rds: tcp: unregister sysctl before tearing down listen socket
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang (Microsoft) <[email protected]>
[ Upstream commit 167e54c703ccd4fa028feb568b0d1002020cff86 ]
rds_tcp_exit_net() frees the per-netns RDS TCP listen socket via rds_tcp_kill_sock() before unregistering the per-netns sysctl table. Since rds_tcp_skbuf_handler() derives the netns from rtn->rds_tcp_listen_sock->sk, a concurrent sysctl write can race with netns teardown and dereference the freed socket/sk.
KASAN reports the race as:
BUG: KASAN: slab-use-after-free in rds_tcp_skbuf_handler+0x2aa/0x2e0 rds_tcp_skbuf_handler net/rds/tcp.c:721 proc_sys_call_handler fs/proc/proc_sysctl.c vfs_write fs/read_write.c __x64_sys_pwrite64 fs/read_write.c
Fix this by unregistering the RDS TCP sysctl table before calling rds_tcp_kill_sock(). unregister_net_sysctl_table() prevents new sysctl handlers from starting and waits for in-flight handlers to finish, so the listen socket can then be released safely. The fix was tested against the linked reproducer.
--- net/rds/tcp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/rds/tcp.c +2 -2
@@ -638,13 +638,13 @@ static void __net_exit rds_tcp_exit_net(struct net *net) {struct rds_tcp_net *rtn =net_generic (net, rds_tcp_netid); -rds_tcp_kill_sock (net); -if (rtn->rds_tcp_sysctl)unregister_net_sysctl_table (rtn->rds_tcp_sysctl);if (net != &init_net)kfree (rtn->ctl_table); + +rds_tcp_kill_sock (net); }static struct pernet_operations rds_tcp_net_ops = {
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 347/744 ptp: netc: explicitly clear TMR_OFF during initialization
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Clark Wang <[email protected]>
[ Upstream commit c3f2fc231a39e29fe9f0adc14a3ecc3c1260d3c5 ]
The NETC timer does not support function level reset, so TMR_OFF_L/H registers are not cleared by pcie_flr(). If TMR_OFF was set to a non-zero value in a previous binding, it will persist across driver rebind and cause inaccurate PTP time.
There is also a hardware issue: after a warm reset or soft reset, TMR_OFF_L/H registers appear to be cleared to zero, but the timer clock domain internally retains the stale value. When the timer is re-enabled, TMR_CUR_TIME continues to track the old offset until TMR_OFF is written explicitly. This can cause incorrect PTP timestamps and even PTP clock synchronization failures.
Per the recommendation from the IP team, explicitly write 0 to TMR_OFF in netc_timer_init() to flush the internally cached value and ensure TMR_CUR_TIME follows the freshly initialized counter.
--- drivers/ptp/ptp_netc.c | 1 + 1 file changed, 1 insertion(+)
drivers/ptp/ptp_netc.c +1 -0
@@ -779,6 +779,7 @@ static void netc_timer_init(struct netc_timer *priv)netc_timer_wr (priv,NETC_TMR_FIPER_CTRL , fiper_ctrl);netc_timer_wr (priv,NETC_TMR_ECTRL ,NETC_TMR_DEFAULT_ETTF_THR ); +netc_timer_offset_write (priv,0 );ktime_get_real_ts64 (&now); ns =timespec64_to_ns (&now);netc_timer_cnt_write (priv, ns);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 348/744 mctp: check register_netdevice_notifier() error in mctp_device_init()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Minhong He <[email protected]>
[ Upstream commit d9a33cadc70a94c1582f65e6042e81027cd200c6 ]
mctp_device_init() handles errors from rtnl_af_register() and rtnl_register_many(), but ignores the return value of register_netdevice_notifier(). If notifier registration fails, init can still return success while the module is only partially initialized.
Check the notifier registration error and fail module init early.
--- net/mctp/device.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
net/mctp/device.c +3 -1
@@ -536,7 +536,9 @@ int __init mctp_device_init(void) {int err; -register_netdevice_notifier (&mctp_dev_nb); + err =register_netdevice_notifier (&mctp_dev_nb); +if (err) +return err; err =rtnl_af_register (&mctp_af_ops);if (err)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 349/744 net: airoha: fix ETS channel derivation in airoha_tc_setup_qdisc_ets()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Lorenzo Bianconi <[email protected]>
[ Upstream commit 649ea07fc25a17aa51bff710baac1ab161022a7c ]
Derive the hardware QoS channel from opt->parent instead of opt->handle in airoha_tc_setup_qdisc_ets(). The ETS qdisc handle is either user-specified or auto-allocated by qdisc_alloc_handle() and bears no relation to the HTB leaf classid that identifies the hardware channel. HTB derives the channel from TC_H_MIN(opt->classid), and ETS is always attached as a child of an HTB leaf, so its opt->parent matches that classid. Using opt->handle instead can cause two ETS qdiscs on different HTB leaves to collide on the same hardware channel, corrupting scheduler configuration and stats.
--- drivers/net/ethernet/airoha/airoha_eth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
drivers/net/ethernet/airoha/airoha_eth.c +1 -2
@@ -2326,8 +2326,7 @@ static int airoha_tc_setup_qdisc_ets(struct net_device *dev,if (opt->parent ==TC_H_ROOT )return -EINVAL ; - channel =TC_H_MAJ (opt->handle) >>16 ; - channel = channel %AIROHA_NUM_QOS_CHANNELS ; + channel =TC_H_MIN (opt->parent) %AIROHA_NUM_QOS_CHANNELS ;switch (opt->command) {case TC_ETS_REPLACE :
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 350/744 tipc: fix integer overflow in tipc_recvmsg() and tipc_recvstream()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Cen Zhang (Microsoft) <[email protected]>
[ Upstream commit 47f42ff521b4eeb46e82f9a46a4783a99f7570d7 ]
In tipc_recvmsg(), the copy length is computed as:
copy = min_t(int, dlen - offset, buflen);
buflen is size_t but min_t(int, ...) casts it to int. When buflen exceeds INT_MAX (e.g. 0xFFFFFFFF via io_uring provided buffers), it wraps negative, wins the comparison, and the negative copy length propagates to simple_copy_to_iter() where int-to-size_t promotion makes it SIZE_MAX, triggering a WARN_ON. tipc_recvstream() has the same pattern.
Kernel panic - not syncing: kernel: panic_on_warn set ... RIP: 0010:simple_copy_to_iter+0x9e/0xd0 (net/core/datagram.c:521) Call Trace: __skb_datagram_iter+0x123/0x8b0 (net/core/datagram.c:402) skb_copy_datagram_iter+0x77/0x1a0 (net/core/datagram.c:534) tipc_recvmsg+0x3d7/0xe80 (net/tipc/socket.c:1934) io_recvmsg+0x47e/0xda0
Fix by changing min_t(int, ...) to min_t(size_t, ...) in both functions. The result is always <= (dlen - offset), which is bounded by TIPC maximum message size (0x1ffff bytes), so the implicit narrowing on assignment to int copy is always safe.
--- net/tipc/socket.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/tipc/socket.c +2 -2
@@ -1934,7 +1934,7 @@ static int tipc_recvmsg(struct socket *sock, struct msghdr *m,if (likely (!err)) {int offset = skb_cb->bytes_read; - copy =min_t (int, dlen - offset, buflen); + copy =min_t (size_t, dlen - offset, buflen); rc =skb_copy_datagram_msg (skb, hlen + offset, m, copy);if (unlikely (rc)) goto exit;
@@ -2066,7 +2066,7 @@ static int tipc_recvstream(struct socket *sock, struct msghdr *m,/* Copy data if msg ok, otherwise return error/partial data */ if (likely (!err)) { offset = skb_cb->bytes_read; - copy =min_t (int, dlen - offset, buflen - copied); + copy =min_t (size_t, dlen - offset, buflen - copied); rc =skb_copy_datagram_msg (skb, hlen + offset, m, copy);if (unlikely (rc))break ;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 351/744 bnge/bng_re: fix ring ID widths
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Vikas Gupta <[email protected]>
[ Upstream commit b9e558976bb968162c35ddccdb076a77fc906993 ]
Firmware requires more than 16 bits to address TX ring IDs for its internal QP management. Widen the associated HSI ring ID fields to 32 bits. The values firmware assigns remain within 24 bits, bounded by the hardware doorbell XID field.
The fw_ring_id field belongs to bnge_ring_struct, a common struct shared by all ring types, so widening it to u32 applies uniformly across TX, RX, CP, and NQ rings but firmware assigns values within 16-bit range for all ring types except TX, which requires the wider field.
Note that, Thor Ultra hardware has not yet been deployed and no firmware has been released to field, so backward compatibility is not a concern.
--- drivers/infiniband/hw/bng_re/bng_dev.c | 6 +-- drivers/net/ethernet/broadcom/bnge/bnge.h | 1 + .../ethernet/broadcom/bnge/bnge_hwrm_lib.c | 8 +-- .../ethernet/broadcom/bnge/bnge_hwrm_lib.h | 2 +- .../net/ethernet/broadcom/bnge/bnge_netdev.c | 50 +++++++++---------- .../net/ethernet/broadcom/bnge/bnge_netdev.h | 4 +- .../net/ethernet/broadcom/bnge/bnge_rmem.h | 2 +- include/linux/bnge/hsi.h | 7 ++- 8 files changed, 39 insertions(+), 41 deletions(-)
drivers/infiniband/hw/bng_re/bng_dev.c +3 -3
@@ -113,7 +113,7 @@ static void bng_re_fill_fw_msg(struct bnge_fw_msg *fw_msg, void *msg, }static int bng_re_net_ring_free (struct bng_re_dev *rdev, -u16 fw_ring_id,int type) +u32 fw_ring_id,int type) {struct bnge_auxr_dev *aux_dev = rdev->aux_dev;struct hwrm_ring_free_input req = {};
@@ -123,7 +123,7 @@ static int bng_re_net_ring_free(struct bng_re_dev *rdev,bng_re_init_hwrm_hdr ((void *)&req,HWRM_RING_FREE ); req.ring_type = type; - req.ring_id =cpu_to_le16 (fw_ring_id); + req.ring_id =cpu_to_le32 (fw_ring_id);bng_re_fill_fw_msg (&fw_msg, (void *)&req,sizeof (req), (void *)&resp,sizeof (resp),BNGE_DFLT_HWRM_CMD_TIMEOUT ); rc =bnge_send_msg (aux_dev, &fw_msg);
@@ -161,7 +161,7 @@ static int bng_re_net_ring_alloc(struct bng_re_dev *rdev, sizeof(resp), BNGE_DFLT_HWRM_CMD_TIMEOUT); rc =bnge_send_msg (aux_dev, &fw_msg);if (!rc) - *fw_ring_id =le16_to_cpu (resp.ring_id); + *fw_ring_id = (u16 )le32_to_cpu (resp.ring_id);return rc; }
drivers/net/ethernet/broadcom/bnge/bnge.h +1 -0
@@ -36,6 +36,7 @@ struct bnge_pf_info { };#define INVALID_HW_RING_ID ((u16)-1) +#define INVALID_HW_RING_ID_32BIT (U32_MAX)enum {BNGE_FW_CAP_SHORT_CMD =BIT_ULL (0 ),
drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.c +4 -4
@@ -1283,7 +1283,7 @@ int bnge_hwrm_stat_ctx_alloc(struct bnge_net *bn)int hwrm_ring_free_send_msg (struct bnge_net *bn,struct bnge_ring_struct *ring, -u32 ring_type,int cmpl_ring_id) +u32 ring_type,u32 cmpl_ring_id) {struct hwrm_ring_free_input *req;struct bnge_dev *bd = bn->bd;
@@ -1295,7 +1295,7 @@ int hwrm_ring_free_send_msg(struct bnge_net *bn, req->cmpl_ring =cpu_to_le16 (cmpl_ring_id); req->ring_type = ring_type; - req->ring_id =cpu_to_le16 (ring->fw_ring_id); + req->ring_id =cpu_to_le32 (ring->fw_ring_id);bnge_hwrm_req_hold (bd, req); rc =bnge_hwrm_req_send (bd, req);
@@ -1317,7 +1317,7 @@ int hwrm_ring_alloc_send_msg(struct bnge_net *bn,struct hwrm_ring_alloc_output *resp;struct hwrm_ring_alloc_input *req;struct bnge_dev *bd = bn->bd; -u16 ring_id, flags =0 ; +u32 ring_id, flags =0 ;int rc; rc =bnge_hwrm_req_init (bd, req,HWRM_RING_ALLOC );
@@ -1401,7 +1401,7 @@ int hwrm_ring_alloc_send_msg(struct bnge_net *bn, resp =bnge_hwrm_req_hold (bd, req); rc =bnge_hwrm_req_send (bd, req); - ring_id =le16_to_cpu (resp->ring_id); + ring_id =le32_to_cpu (resp->ring_id);bnge_hwrm_req_drop (bd, req); exit:
drivers/net/ethernet/broadcom/bnge/bnge_hwrm_lib.h +1 -1
@@ -50,7 +50,7 @@ int bnge_hwrm_cfa_l2_set_rx_mask(struct bnge_dev *bd,void bnge_hwrm_stat_ctx_free (struct bnge_net *bn);int bnge_hwrm_stat_ctx_alloc (struct bnge_net *bn);int hwrm_ring_free_send_msg (struct bnge_net *bn,struct bnge_ring_struct *ring, -u32 ring_type,int cmpl_ring_id); +u32 ring_type,u32 cmpl_ring_id);int hwrm_ring_alloc_send_msg (struct bnge_net *bn,struct bnge_ring_struct *ring,u32 ring_type,u32 map_index);
drivers/net/ethernet/broadcom/bnge/bnge_netdev.c +24 -26
177 lines not on this page · raw message
drivers/net/ethernet/broadcom/bnge/bnge_netdev.h +2 -2
@@ -630,8 +630,8 @@ struct bnge_l2_filter {refcount_t refcnt; }; -u16 bnge_cp_ring_for_rx (struct bnge_rx_ring_info *rxr); -u16 bnge_cp_ring_for_tx (struct bnge_tx_ring_info *txr); +u32 bnge_cp_ring_for_rx (struct bnge_rx_ring_info *rxr); +u32 bnge_cp_ring_for_tx (struct bnge_tx_ring_info *txr);void bnge_fill_hw_rss_tbl (struct bnge_net *bn,struct bnge_vnic_info *vnic);int bnge_alloc_rx_data (struct bnge_net *bn,struct bnge_rx_ring_info *rxr,u16 prod,gfp_t gfp);
drivers/net/ethernet/broadcom/bnge/bnge_rmem.h +1 -1
@@ -184,7 +184,7 @@ struct bnge_ctx_mem_info {struct bnge_ring_struct {struct bnge_ring_mem_info ring_mem; -u16 fw_ring_id; +u32 fw_ring_id;union {u16 grp_idx;u16 map_idx;/* Used by NQs */
include/linux/bnge/hsi.h +3 -4
@@ -8317,8 +8317,7 @@ struct hwrm_ring_alloc_output {__le16 req_type;__le16 seq_id;__le16 resp_len; -__le16 ring_id; -__le16 logical_ring_id; +__le32 ring_id;u8 push_buffer_index;#define RING_ALLOC_RESP_PUSH_BUFFER_INDEX_PING_BUFFER 0x0UL#define RING_ALLOC_RESP_PUSH_BUFFER_INDEX_PONG_BUFFER 0x1UL
@@ -8345,10 +8344,10 @@ struct hwrm_ring_free_input {u8 flags;#define RING_FREE_REQ_FLAGS_VIRTIO_RING_VALID 0x1UL#define RING_FREE_REQ_FLAGS_LAST RING_FREE_REQ_FLAGS_VIRTIO_RING_VALID -__le16 ring_id; +__le16 unused_1;__le32 prod_idx;__le32 opaque; -__le32 unused_1; +__le32 ring_id; };/* hwrm_ring_free_output (size:128b/16B) */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 352/744 net: drop_monitor: fix info leak in NET_DM_ATTR_PAYLOAD
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Yehyeong Lee <[email protected]>
[ Upstream commit 5e9c8baee0329fbefe7c67aea945e2a07f15e98b ]
net_dm_packet_report_fill() and net_dm_hw_packet_report_fill() open code the NET_DM_ATTR_PAYLOAD attribute to avoid zeroing the packet payload before overwriting it with skb_copy_bits().
skb_put() reserves nla_total_size(payload_len), i.e. the header plus the NLA_ALIGN() padding, but only payload_len bytes are copied in. When payload_len is not a multiple of 4 the 1-3 padding bytes are never initialized and are leaked to user space inside the netlink message.
KMSAN confirms the leak for the software path when the packet payload length is not 4-byte aligned:
BUG: KMSAN: kernel-infoleak in _copy_to_iter _copy_to_iter __skb_datagram_iter skb_copy_datagram_iter netlink_recvmsg sock_recvmsg __sys_recvfrom Uninit was created at: kmem_cache_alloc_node_noprof __alloc_skb net_dm_packet_work Bytes 173-175 of 176 are uninitialized
Use __nla_reserve(), which sets up the attribute header and zeroes the padding, instead of open coding the attribute construction.
--- net/core/drop_monitor.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-)
net/core/drop_monitor.c +2 -6
@@ -671,9 +671,7 @@ static int net_dm_packet_report_fill(struct sk_buff *msg, struct sk_buff *skb,if (nla_put_u16 (msg,NET_DM_ATTR_PROTO ,be16_to_cpu (skb->protocol))) goto nla_put_failure; - attr =skb_put (msg,nla_total_size (payload_len)); - attr->nla_type =NET_DM_ATTR_PAYLOAD ; - attr->nla_len =nla_attr_size (payload_len); + attr =__nla_reserve (msg,NET_DM_ATTR_PAYLOAD , payload_len);if (skb_copy_bits (skb,0 ,nla_data (attr), payload_len)) goto nla_put_failure;
@@ -831,9 +829,7 @@ static int net_dm_hw_packet_report_fill(struct sk_buff *msg,if (nla_put_u16 (msg,NET_DM_ATTR_PROTO ,be16_to_cpu (skb->protocol))) goto nla_put_failure; - attr =skb_put (msg,nla_total_size (payload_len)); - attr->nla_type =NET_DM_ATTR_PAYLOAD ; - attr->nla_len =nla_attr_size (payload_len); + attr =__nla_reserve (msg,NET_DM_ATTR_PAYLOAD , payload_len);if (skb_copy_bits (skb,0 ,nla_data (attr), payload_len)) goto nla_put_failure;
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 353/744 drop_monitor: fix size calculations for 64-bit attributes
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit 7089f7ab99c89f443c92d8fcc585e63f2727f0b3 ]
net_dm_packet_report_fill() and net_dm_hw_packet_report_fill() use nla_put_u64_64bit() to append 64-bit attributes (NET_DM_ATTR_PC and NET_DM_ATTR_TIMESTAMP).
On 32-bit architectures without CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS, nla_put_u64_64bit() may append a 4-byte NET_DM_ATTR_PAD attribute for 64-bit alignment.
However, net_dm_packet_report_size() and net_dm_hw_packet_report_size() used nla_total_size(sizeof(u64)) instead of nla_total_size_64bit(sizeof(u64)), budgeting 12 bytes instead of up to 16 bytes.
This under-estimation of SKB size can lead to an skb_over_panic() when __nla_reserve() or skb_put() is subsequently called.
Fix this by using nla_total_size_64bit(sizeof(u64)) in both size calculations.
--- net/core/drop_monitor.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-)
net/core/drop_monitor.c +3 -3
@@ -566,13 +566,13 @@ static size_t net_dm_packet_report_size(size_t payload_len)/* NET_DM_ATTR_ORIGIN */ nla_total_size (sizeof (u16)) +/* NET_DM_ATTR_PC */ -nla_total_size (sizeof (u64)) + +nla_total_size_64bit (sizeof (u64)) +/* NET_DM_ATTR_SYMBOL */ nla_total_size (NET_DM_MAX_SYMBOL_LEN +1 ) +/* NET_DM_ATTR_IN_PORT */ net_dm_in_port_size () +/* NET_DM_ATTR_TIMESTAMP */ -nla_total_size (sizeof (u64)) + +nla_total_size_64bit (sizeof (u64)) +/* NET_DM_ATTR_ORIG_LEN */ nla_total_size (sizeof (u32)) + /* NET_DM_ATTR_PROTO */
@@ -766,7 +766,7 @@ net_dm_hw_packet_report_size(size_t payload_len,/* NET_DM_ATTR_FLOW_ACTION_COOKIE */ net_dm_flow_action_cookie_size (hw_metadata) +/* NET_DM_ATTR_TIMESTAMP */ -nla_total_size (sizeof (u64)) + +nla_total_size_64bit (sizeof (u64)) +/* NET_DM_ATTR_ORIG_LEN */ nla_total_size (sizeof (u32)) + /* NET_DM_ATTR_PROTO */
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 354/744 drop_monitor: perform u64_stats updates under IRQ-disabled section
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Eric Dumazet <[email protected]>
[ Upstream commit fd098a23bf8fda7eae48db9b06e7c34fc4d228fa ]
In net_dm_packet_trace_kfree_skb_hit() and net_dm_hw_trap_packet_probe(), u64_stats_update_begin() / u64_stats_inc() / u64_stats_update_end() were called after spin_unlock_irqrestore(&...drop_queue.lock, flags), when local IRQs had already been re-enabled.
Tracepoint probes can execute in IRQ or softirq context. On 32-bit architectures, u64_stats_update_begin() disables preemption but not interrupts, relying on seqcount writes. If a nested interrupt occurs on the same CPU during the 64-bit stats update, the reentrant seqcount update can corrupt the seqcount state or stats value.
Fix this by performing the 64-bit per-CPU stats update before releasing drop_queue.lock via spin_unlock_irqrestore(), ensuring local interrupts remain disabled during the u64_stats update.
--- net/core/drop_monitor.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/core/drop_monitor.c +2 -2
@@ -530,10 +530,10 @@ static void net_dm_packet_trace_kfree_skb_hit(void *ignore,return ; unlock_free: -spin_unlock_irqrestore (&data->drop_queue.lock, flags);u64_stats_update_begin (&data->stats.syncp);u64_stats_inc (&data->stats.dropped);u64_stats_update_end (&data->stats.syncp); +spin_unlock_irqrestore (&data->drop_queue.lock, flags);consume_skb (nskb); }
@@ -997,10 +997,10 @@ net_dm_hw_trap_packet_probe(void *ignore, const struct devlink *devlink,return ; unlock_free: -spin_unlock_irqrestore (&hw_data->drop_queue.lock, flags);u64_stats_update_begin (&hw_data->stats.syncp);u64_stats_inc (&hw_data->stats.dropped);u64_stats_update_end (&hw_data->stats.syncp); +spin_unlock_irqrestore (&hw_data->drop_queue.lock, flags);net_dm_hw_metadata_free (n_hw_metadata); free:consume_skb (nskb);
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 355/744 pidfs: make pidfs_ino_lock static
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Mateusz Guzik <[email protected]>
[ Upstream commit c1d04c1bce98f9dd984a9c6657278a7761854c9c ]
--- fs/pidfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
fs/pidfs.c +1 -1
@@ -107,7 +107,7 @@ struct pidfs_attr {#if BITS_PER_LONG ==32 -DEFINE_SPINLOCK (pidfs_ino_lock); +static DEFINE_SPINLOCK (pidfs_ino_lock);static u64 pidfs_ino_nr =1 ;static inline unsigned long pidfs_ino (u64 ino)
Signature · 1 line
2.53.0
Greg Kroah-Hartman
maintainerPATCH 356/744 LoongArch: BPF: Fix memory leak in bpf_jit_free()
In reply to Greg Kroah-Hartman7.1-stable review patch. If anyone has any objections, please let me know.
------------------
From: Pu Lehui <[email protected]>
[ Upstream commit 47e20d4b3da97ef3881d1e55e43545c22424f3fc ]
When bpf_int_jit_compile() is called for subprograms, it returns early during the first pass (!prog->is_func || extra_pass is false), keeping ctx->offset alive for the subsequent extra pass.
If JIT compilation fails for a later subprogram, the BPF core aborts and calls bpf_jit_free() to clean up the first subprogram. However, bpf_jit_free() fails to free jit_data->ctx.offset, which causes a memory leak of the JIT context offsets array.
So fix this by adding the missing kvfree(jit_data->ctx.offset) in bpf_jit_free().
--- arch/loongarch/net/bpf_jit.c | 1 + 1 file changed, 1 insertion(+)
arch/loongarch/net/bpf_jit.c +1 -0
@@ -2347,6 +2347,7 @@ void bpf_jit_free(struct bpf_prog *prog)*/ if (jit_data) {bpf_jit_binary_pack_finalize (jit_data->ro_header, jit_data->header); +kvfree (jit_data->ctx.offset);kfree (jit_data); } hdr =bpf_jit_binary_pack_hdr (prog);
Signature · 1 line
2.53.0