From: Sasha Levin Date: Sat, 7 Oct 2023 12:15:42 +0000 (-0400) Subject: Fixes for 6.1 X-Git-Tag: v4.14.327~53^2~6 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7ff7e61d46beecd99a31a3fec95f734ba200aec4;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.1 Signed-off-by: Sasha Levin --- diff --git a/queue-6.1/bluetooth-delete-unused-hci_req_prepare_suspend-decl.patch b/queue-6.1/bluetooth-delete-unused-hci_req_prepare_suspend-decl.patch new file mode 100644 index 00000000000..bb600a44b07 --- /dev/null +++ b/queue-6.1/bluetooth-delete-unused-hci_req_prepare_suspend-decl.patch @@ -0,0 +1,35 @@ +From 4f53ce07db6914c71f70c921fe7ad6192988e5bd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 26 Aug 2023 16:13:13 +0800 +Subject: Bluetooth: Delete unused hci_req_prepare_suspend() declaration + +From: Yao Xiao + +[ Upstream commit cbaabbcdcbd355f0a1ccc09a925575c51c270750 ] + +hci_req_prepare_suspend() has been deprecated in favor of +hci_suspend_sync(). + +Fixes: 182ee45da083 ("Bluetooth: hci_sync: Rework hci_suspend_notifier") +Signed-off-by: Yao Xiao +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/hci_request.h | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h +index b9c5a98238374..0be75cf0efed8 100644 +--- a/net/bluetooth/hci_request.h ++++ b/net/bluetooth/hci_request.h +@@ -71,7 +71,5 @@ struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, u32 plen, + void hci_req_add_le_scan_disable(struct hci_request *req, bool rpa_le_conn); + void hci_req_add_le_passive_scan(struct hci_request *req); + +-void hci_req_prepare_suspend(struct hci_dev *hdev, enum suspended_state next); +- + void hci_request_setup(struct hci_dev *hdev); + void hci_request_cancel_all(struct hci_dev *hdev); +-- +2.40.1 + diff --git a/queue-6.1/bluetooth-iso-fix-handling-of-listen-for-unicast.patch b/queue-6.1/bluetooth-iso-fix-handling-of-listen-for-unicast.patch new file mode 100644 index 00000000000..98e7cf4d0f9 --- /dev/null +++ b/queue-6.1/bluetooth-iso-fix-handling-of-listen-for-unicast.patch @@ -0,0 +1,57 @@ +From 88965576c56c6c7b8efa06ebaff331a29c4fc6be Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 28 Aug 2023 13:05:45 -0700 +Subject: Bluetooth: ISO: Fix handling of listen for unicast + +From: Luiz Augusto von Dentz + +[ Upstream commit e0275ea52169412b8faccb4e2f4fed8a057844c6 ] + +iso_listen_cis shall only return -EADDRINUSE if the listening socket has +the destination set to BDADDR_ANY otherwise if the destination is set to +a specific address it is for broadcast which shall be ignored. + +Fixes: f764a6c2c1e4 ("Bluetooth: ISO: Add broadcast support") +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + net/bluetooth/iso.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c +index 5cd2e775915be..91e990accbf20 100644 +--- a/net/bluetooth/iso.c ++++ b/net/bluetooth/iso.c +@@ -458,7 +458,7 @@ static void iso_recv_frame(struct iso_conn *conn, struct sk_buff *skb) + } + + /* -------- Socket interface ---------- */ +-static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *ba) ++static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *src, bdaddr_t *dst) + { + struct sock *sk; + +@@ -466,7 +466,10 @@ static struct sock *__iso_get_sock_listen_by_addr(bdaddr_t *ba) + if (sk->sk_state != BT_LISTEN) + continue; + +- if (!bacmp(&iso_pi(sk)->src, ba)) ++ if (bacmp(&iso_pi(sk)->dst, dst)) ++ continue; ++ ++ if (!bacmp(&iso_pi(sk)->src, src)) + return sk; + } + +@@ -910,7 +913,7 @@ static int iso_listen_cis(struct sock *sk) + + write_lock(&iso_sk_list.lock); + +- if (__iso_get_sock_listen_by_addr(&iso_pi(sk)->src)) ++ if (__iso_get_sock_listen_by_addr(&iso_pi(sk)->src, &iso_pi(sk)->dst)) + err = -EADDRINUSE; + + write_unlock(&iso_sk_list.lock); +-- +2.40.1 + diff --git a/queue-6.1/bpf-add-bpf_fib_lookup_skip_neigh-for-bpf_fib_lookup.patch b/queue-6.1/bpf-add-bpf_fib_lookup_skip_neigh-for-bpf_fib_lookup.patch new file mode 100644 index 00000000000..ef3671914b1 --- /dev/null +++ b/queue-6.1/bpf-add-bpf_fib_lookup_skip_neigh-for-bpf_fib_lookup.patch @@ -0,0 +1,184 @@ +From ac8edd5765ff616b44db2115b52b8084da24dc22 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 17 Feb 2023 12:55:14 -0800 +Subject: bpf: Add BPF_FIB_LOOKUP_SKIP_NEIGH for bpf_fib_lookup + +From: Martin KaFai Lau + +[ Upstream commit 31de4105f00d64570139bc5494a201b0bd57349f ] + +The bpf_fib_lookup() also looks up the neigh table. +This was done before bpf_redirect_neigh() was added. + +In the use case that does not manage the neigh table +and requires bpf_fib_lookup() to lookup a fib to +decide if it needs to redirect or not, the bpf prog can +depend only on using bpf_redirect_neigh() to lookup the +neigh. It also keeps the neigh entries fresh and connected. + +This patch adds a bpf_fib_lookup flag, SKIP_NEIGH, to avoid +the double neigh lookup when the bpf prog always call +bpf_redirect_neigh() to do the neigh lookup. The params->smac +output is skipped together when SKIP_NEIGH is set because +bpf_redirect_neigh() will figure out the smac also. + +Signed-off-by: Martin KaFai Lau +Signed-off-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/20230217205515.3583372-1-martin.lau@linux.dev +Stable-dep-of: 5baa0433a15e ("neighbour: fix data-races around n->output") +Signed-off-by: Sasha Levin +--- + include/uapi/linux/bpf.h | 6 ++++++ + net/core/filter.c | 39 ++++++++++++++++++++++------------ + tools/include/uapi/linux/bpf.h | 6 ++++++ + 3 files changed, 38 insertions(+), 13 deletions(-) + +diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h +index 53bc487947197..92dbe89dafbf5 100644 +--- a/include/uapi/linux/bpf.h ++++ b/include/uapi/linux/bpf.h +@@ -3112,6 +3112,11 @@ union bpf_attr { + * **BPF_FIB_LOOKUP_OUTPUT** + * Perform lookup from an egress perspective (default is + * ingress). ++ * **BPF_FIB_LOOKUP_SKIP_NEIGH** ++ * Skip the neighbour table lookup. *params*->dmac ++ * and *params*->smac will not be set as output. A common ++ * use case is to call **bpf_redirect_neigh**\ () after ++ * doing **bpf_fib_lookup**\ (). + * + * *ctx* is either **struct xdp_md** for XDP programs or + * **struct sk_buff** tc cls_act programs. +@@ -6678,6 +6683,7 @@ struct bpf_raw_tracepoint_args { + enum { + BPF_FIB_LOOKUP_DIRECT = (1U << 0), + BPF_FIB_LOOKUP_OUTPUT = (1U << 1), ++ BPF_FIB_LOOKUP_SKIP_NEIGH = (1U << 2), + }; + + enum { +diff --git a/net/core/filter.c b/net/core/filter.c +index 9fd7c88b5db4e..6ef62d84dcac5 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -5674,12 +5674,8 @@ static const struct bpf_func_proto bpf_skb_get_xfrm_state_proto = { + #endif + + #if IS_ENABLED(CONFIG_INET) || IS_ENABLED(CONFIG_IPV6) +-static int bpf_fib_set_fwd_params(struct bpf_fib_lookup *params, +- const struct neighbour *neigh, +- const struct net_device *dev, u32 mtu) ++static int bpf_fib_set_fwd_params(struct bpf_fib_lookup *params, u32 mtu) + { +- memcpy(params->dmac, neigh->ha, ETH_ALEN); +- memcpy(params->smac, dev->dev_addr, ETH_ALEN); + params->h_vlan_TCI = 0; + params->h_vlan_proto = 0; + if (mtu) +@@ -5790,21 +5786,29 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params, + if (likely(nhc->nhc_gw_family != AF_INET6)) { + if (nhc->nhc_gw_family) + params->ipv4_dst = nhc->nhc_gw.ipv4; +- +- neigh = __ipv4_neigh_lookup_noref(dev, +- (__force u32)params->ipv4_dst); + } else { + struct in6_addr *dst = (struct in6_addr *)params->ipv6_dst; + + params->family = AF_INET6; + *dst = nhc->nhc_gw.ipv6; +- neigh = __ipv6_neigh_lookup_noref_stub(dev, dst); + } + ++ if (flags & BPF_FIB_LOOKUP_SKIP_NEIGH) ++ goto set_fwd_params; ++ ++ if (likely(nhc->nhc_gw_family != AF_INET6)) ++ neigh = __ipv4_neigh_lookup_noref(dev, ++ (__force u32)params->ipv4_dst); ++ else ++ neigh = __ipv6_neigh_lookup_noref_stub(dev, params->ipv6_dst); ++ + if (!neigh || !(neigh->nud_state & NUD_VALID)) + return BPF_FIB_LKUP_RET_NO_NEIGH; ++ memcpy(params->dmac, neigh->ha, ETH_ALEN); ++ memcpy(params->smac, dev->dev_addr, ETH_ALEN); + +- return bpf_fib_set_fwd_params(params, neigh, dev, mtu); ++set_fwd_params: ++ return bpf_fib_set_fwd_params(params, mtu); + } + #endif + +@@ -5912,24 +5916,33 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params, + params->rt_metric = res.f6i->fib6_metric; + params->ifindex = dev->ifindex; + ++ if (flags & BPF_FIB_LOOKUP_SKIP_NEIGH) ++ goto set_fwd_params; ++ + /* xdp and cls_bpf programs are run in RCU-bh so rcu_read_lock_bh is + * not needed here. + */ + neigh = __ipv6_neigh_lookup_noref_stub(dev, dst); + if (!neigh || !(neigh->nud_state & NUD_VALID)) + return BPF_FIB_LKUP_RET_NO_NEIGH; ++ memcpy(params->dmac, neigh->ha, ETH_ALEN); ++ memcpy(params->smac, dev->dev_addr, ETH_ALEN); + +- return bpf_fib_set_fwd_params(params, neigh, dev, mtu); ++set_fwd_params: ++ return bpf_fib_set_fwd_params(params, mtu); + } + #endif + ++#define BPF_FIB_LOOKUP_MASK (BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_OUTPUT | \ ++ BPF_FIB_LOOKUP_SKIP_NEIGH) ++ + BPF_CALL_4(bpf_xdp_fib_lookup, struct xdp_buff *, ctx, + struct bpf_fib_lookup *, params, int, plen, u32, flags) + { + if (plen < sizeof(*params)) + return -EINVAL; + +- if (flags & ~(BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_OUTPUT)) ++ if (flags & ~BPF_FIB_LOOKUP_MASK) + return -EINVAL; + + switch (params->family) { +@@ -5967,7 +5980,7 @@ BPF_CALL_4(bpf_skb_fib_lookup, struct sk_buff *, skb, + if (plen < sizeof(*params)) + return -EINVAL; + +- if (flags & ~(BPF_FIB_LOOKUP_DIRECT | BPF_FIB_LOOKUP_OUTPUT)) ++ if (flags & ~BPF_FIB_LOOKUP_MASK) + return -EINVAL; + + if (params->tot_len) +diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h +index 53bc487947197..92dbe89dafbf5 100644 +--- a/tools/include/uapi/linux/bpf.h ++++ b/tools/include/uapi/linux/bpf.h +@@ -3112,6 +3112,11 @@ union bpf_attr { + * **BPF_FIB_LOOKUP_OUTPUT** + * Perform lookup from an egress perspective (default is + * ingress). ++ * **BPF_FIB_LOOKUP_SKIP_NEIGH** ++ * Skip the neighbour table lookup. *params*->dmac ++ * and *params*->smac will not be set as output. A common ++ * use case is to call **bpf_redirect_neigh**\ () after ++ * doing **bpf_fib_lookup**\ (). + * + * *ctx* is either **struct xdp_md** for XDP programs or + * **struct sk_buff** tc cls_act programs. +@@ -6678,6 +6683,7 @@ struct bpf_raw_tracepoint_args { + enum { + BPF_FIB_LOOKUP_DIRECT = (1U << 0), + BPF_FIB_LOOKUP_OUTPUT = (1U << 1), ++ BPF_FIB_LOOKUP_SKIP_NEIGH = (1U << 2), + }; + + enum { +-- +2.40.1 + diff --git a/queue-6.1/bpf-fix-tr-dereferencing.patch b/queue-6.1/bpf-fix-tr-dereferencing.patch new file mode 100644 index 00000000000..cfb5de6daba --- /dev/null +++ b/queue-6.1/bpf-fix-tr-dereferencing.patch @@ -0,0 +1,42 @@ +From cced480fe9d91660cb2f0159309d1f12d76e77a6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 17 Sep 2023 23:38:46 +0800 +Subject: bpf: Fix tr dereferencing + +From: Leon Hwang + +[ Upstream commit b724a6418f1f853bcb39c8923bf14a50c7bdbd07 ] + +Fix 'tr' dereferencing bug when CONFIG_BPF_JIT is turned off. + +When CONFIG_BPF_JIT is turned off, 'bpf_trampoline_get()' returns NULL, +which is same as the cases when CONFIG_BPF_JIT is turned on. + +Closes: https://lore.kernel.org/r/202309131936.5Nc8eUD0-lkp@intel.com/ +Fixes: f7b12b6fea00 ("bpf: verifier: refactor check_attach_btf_id()") +Reported-by: kernel test robot +Reported-by: Dan Carpenter +Signed-off-by: Leon Hwang +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20230917153846.88732-1-hffilwlqm@gmail.com +Signed-off-by: Sasha Levin +--- + include/linux/bpf.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/bpf.h b/include/linux/bpf.h +index 1ed2ec035e779..1fba826f0acef 100644 +--- a/include/linux/bpf.h ++++ b/include/linux/bpf.h +@@ -1065,7 +1065,7 @@ static inline int bpf_trampoline_unlink_prog(struct bpf_tramp_link *link, + static inline struct bpf_trampoline *bpf_trampoline_get(u64 key, + struct bpf_attach_target_info *tgt_info) + { +- return ERR_PTR(-EOPNOTSUPP); ++ return NULL; + } + static inline void bpf_trampoline_put(struct bpf_trampoline *tr) {} + #define DEFINE_BPF_DISPATCHER(name) +-- +2.40.1 + diff --git a/queue-6.1/bpf-sockmap-do-not-inc-copied_seq-when-peek-flag-set.patch b/queue-6.1/bpf-sockmap-do-not-inc-copied_seq-when-peek-flag-set.patch new file mode 100644 index 00000000000..12187f9c291 --- /dev/null +++ b/queue-6.1/bpf-sockmap-do-not-inc-copied_seq-when-peek-flag-set.patch @@ -0,0 +1,59 @@ +From 4d3a6bf061c2fc98147d0b3f38173fdac2238a81 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Sep 2023 20:52:59 -0700 +Subject: bpf, sockmap: Do not inc copied_seq when PEEK flag set + +From: John Fastabend + +[ Upstream commit da9e915eaf5dadb1963b7738cdfa42ed55212445 ] + +When data is peek'd off the receive queue we shouldn't considered it +copied from tcp_sock side. When we increment copied_seq this will confuse +tcp_data_ready() because copied_seq can be arbitrarily increased. From +application side it results in poll() operations not waking up when +expected. + +Notice tcp stack without BPF recvmsg programs also does not increment +copied_seq. + +We broke this when we moved copied_seq into recvmsg to only update when +actual copy was happening. But, it wasn't working correctly either before +because the tcp_data_ready() tried to use the copied_seq value to see +if data was read by user yet. See fixes tags. + +Fixes: e5c6de5fa0258 ("bpf, sockmap: Incorrectly handling copied_seq") +Fixes: 04919bed948dc ("tcp: Introduce tcp_read_skb()") +Signed-off-by: John Fastabend +Signed-off-by: Daniel Borkmann +Reviewed-by: Jakub Sitnicki +Link: https://lore.kernel.org/bpf/20230926035300.135096-3-john.fastabend@gmail.com +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_bpf.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c +index 5f93918c063c7..f53380fd89bcf 100644 +--- a/net/ipv4/tcp_bpf.c ++++ b/net/ipv4/tcp_bpf.c +@@ -217,6 +217,7 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, + int *addr_len) + { + struct tcp_sock *tcp = tcp_sk(sk); ++ int peek = flags & MSG_PEEK; + u32 seq = tcp->copied_seq; + struct sk_psock *psock; + int copied = 0; +@@ -306,7 +307,8 @@ static int tcp_bpf_recvmsg_parser(struct sock *sk, + copied = -EAGAIN; + } + out: +- WRITE_ONCE(tcp->copied_seq, seq); ++ if (!peek) ++ WRITE_ONCE(tcp->copied_seq, seq); + tcp_rcv_space_adjust(sk); + if (copied > 0) + __tcp_cleanup_rbuf(sk, copied); +-- +2.40.1 + diff --git a/queue-6.1/bpf-sockmap-reject-sk_msg-egress-redirects-to-non-tc.patch b/queue-6.1/bpf-sockmap-reject-sk_msg-egress-redirects-to-non-tc.patch new file mode 100644 index 00000000000..c0aa32563bc --- /dev/null +++ b/queue-6.1/bpf-sockmap-reject-sk_msg-egress-redirects-to-non-tc.patch @@ -0,0 +1,102 @@ +From c9dfc35768f2edbd512083b1cb72d74fc19fdef2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Sep 2023 12:20:55 +0200 +Subject: bpf, sockmap: Reject sk_msg egress redirects to non-TCP sockets + +From: Jakub Sitnicki + +[ Upstream commit b80e31baa43614e086a9d29dc1151932b1bd7fc5 ] + +With a SOCKMAP/SOCKHASH map and an sk_msg program user can steer messages +sent from one TCP socket (s1) to actually egress from another TCP +socket (s2): + +tcp_bpf_sendmsg(s1) // = sk_prot->sendmsg + tcp_bpf_send_verdict(s1) // __SK_REDIRECT case + tcp_bpf_sendmsg_redir(s2) + tcp_bpf_push_locked(s2) + tcp_bpf_push(s2) + tcp_rate_check_app_limited(s2) // expects tcp_sock + tcp_sendmsg_locked(s2) // ditto + +There is a hard-coded assumption in the call-chain, that the egress +socket (s2) is a TCP socket. + +However in commit 122e6c79efe1 ("sock_map: Update sock type checks for +UDP") we have enabled redirects to non-TCP sockets. This was done for the +sake of BPF sk_skb programs. There was no indention to support sk_msg +send-to-egress use case. + +As a result, attempts to send-to-egress through a non-TCP socket lead to a +crash due to invalid downcast from sock to tcp_sock: + + BUG: kernel NULL pointer dereference, address: 000000000000002f + ... + Call Trace: + + ? show_regs+0x60/0x70 + ? __die+0x1f/0x70 + ? page_fault_oops+0x80/0x160 + ? do_user_addr_fault+0x2d7/0x800 + ? rcu_is_watching+0x11/0x50 + ? exc_page_fault+0x70/0x1c0 + ? asm_exc_page_fault+0x27/0x30 + ? tcp_tso_segs+0x14/0xa0 + tcp_write_xmit+0x67/0xce0 + __tcp_push_pending_frames+0x32/0xf0 + tcp_push+0x107/0x140 + tcp_sendmsg_locked+0x99f/0xbb0 + tcp_bpf_push+0x19d/0x3a0 + tcp_bpf_sendmsg_redir+0x55/0xd0 + tcp_bpf_send_verdict+0x407/0x550 + tcp_bpf_sendmsg+0x1a1/0x390 + inet_sendmsg+0x6a/0x70 + sock_sendmsg+0x9d/0xc0 + ? sockfd_lookup_light+0x12/0x80 + __sys_sendto+0x10e/0x160 + ? syscall_enter_from_user_mode+0x20/0x60 + ? __this_cpu_preempt_check+0x13/0x20 + ? lockdep_hardirqs_on+0x82/0x110 + __x64_sys_sendto+0x1f/0x30 + do_syscall_64+0x38/0x90 + entry_SYSCALL_64_after_hwframe+0x63/0xcd + +Reject selecting a non-TCP sockets as redirect target from a BPF sk_msg +program to prevent the crash. When attempted, user will receive an EACCES +error from send/sendto/sendmsg() syscall. + +Fixes: 122e6c79efe1 ("sock_map: Update sock type checks for UDP") +Signed-off-by: Jakub Sitnicki +Signed-off-by: Daniel Borkmann +Acked-by: John Fastabend +Link: https://lore.kernel.org/bpf/20230920102055.42662-1-jakub@cloudflare.com +Signed-off-by: Sasha Levin +--- + net/core/sock_map.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/net/core/sock_map.c b/net/core/sock_map.c +index 96db7409baa12..38e01f82f2ef3 100644 +--- a/net/core/sock_map.c ++++ b/net/core/sock_map.c +@@ -670,6 +670,8 @@ BPF_CALL_4(bpf_msg_redirect_map, struct sk_msg *, msg, + sk = __sock_map_lookup_elem(map, key); + if (unlikely(!sk || !sock_map_redirect_allowed(sk))) + return SK_DROP; ++ if (!(flags & BPF_F_INGRESS) && !sk_is_tcp(sk)) ++ return SK_DROP; + + msg->flags = flags; + msg->sk_redir = sk; +@@ -1262,6 +1264,8 @@ BPF_CALL_4(bpf_msg_redirect_hash, struct sk_msg *, msg, + sk = __sock_hash_lookup_elem(map, key); + if (unlikely(!sk || !sock_map_redirect_allowed(sk))) + return SK_DROP; ++ if (!(flags & BPF_F_INGRESS) && !sk_is_tcp(sk)) ++ return SK_DROP; + + msg->flags = flags; + msg->sk_redir = sk; +-- +2.40.1 + diff --git a/queue-6.1/bpf-tcp_read_skb-needs-to-pop-skb-regardless-of-seq.patch b/queue-6.1/bpf-tcp_read_skb-needs-to-pop-skb-regardless-of-seq.patch new file mode 100644 index 00000000000..79756ec0bdf --- /dev/null +++ b/queue-6.1/bpf-tcp_read_skb-needs-to-pop-skb-regardless-of-seq.patch @@ -0,0 +1,99 @@ +From 4aaf9d7f800dc13345bcf22bf5d848662be1a42c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 25 Sep 2023 20:52:58 -0700 +Subject: bpf: tcp_read_skb needs to pop skb regardless of seq + +From: John Fastabend + +[ Upstream commit 9b7177b1df64b8d7f85700027c324aadd6aded00 ] + +Before fix e5c6de5fa0258 tcp_read_skb() would increment the tp->copied-seq +value. This (as described in the commit) would cause an error for apps +because once that is incremented the application might believe there is no +data to be read. Then some apps would stall or abort believing no data is +available. + +However, the fix is incomplete because it introduces another issue in +the skb dequeue. The loop does tcp_recv_skb() in a while loop to consume +as many skbs as possible. The problem is the call is ... + + tcp_recv_skb(sk, seq, &offset) + +... where 'seq' is: + + u32 seq = tp->copied_seq; + +Now we can hit a case where we've yet incremented copied_seq from BPF side, +but then tcp_recv_skb() fails this test ... + + if (offset < skb->len || (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)) + +... so that instead of returning the skb we call tcp_eat_recv_skb() which +frees the skb. This is because the routine believes the SKB has been collapsed +per comment: + + /* This looks weird, but this can happen if TCP collapsing + * splitted a fat GRO packet, while we released socket lock + * in skb_splice_bits() + */ + +This can't happen here we've unlinked the full SKB and orphaned it. Anyways +it would confuse any BPF programs if the data were suddenly moved underneath +it. + +To fix this situation do simpler operation and just skb_peek() the data +of the queue followed by the unlink. It shouldn't need to check this +condition and tcp_read_skb() reads entire skbs so there is no need to +handle the 'offset!=0' case as we would see in tcp_read_sock(). + +Fixes: e5c6de5fa0258 ("bpf, sockmap: Incorrectly handling copied_seq") +Fixes: 04919bed948dc ("tcp: Introduce tcp_read_skb()") +Signed-off-by: John Fastabend +Signed-off-by: Daniel Borkmann +Reviewed-by: Jakub Sitnicki +Link: https://lore.kernel.org/bpf/20230926035300.135096-2-john.fastabend@gmail.com +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp.c | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c +index fab25d4f3a6f1..96fdde6e42b1b 100644 +--- a/net/ipv4/tcp.c ++++ b/net/ipv4/tcp.c +@@ -1755,16 +1755,13 @@ EXPORT_SYMBOL(tcp_read_sock); + + int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) + { +- struct tcp_sock *tp = tcp_sk(sk); +- u32 seq = tp->copied_seq; + struct sk_buff *skb; + int copied = 0; +- u32 offset; + + if (sk->sk_state == TCP_LISTEN) + return -ENOTCONN; + +- while ((skb = tcp_recv_skb(sk, seq, &offset)) != NULL) { ++ while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) { + u8 tcp_flags; + int used; + +@@ -1777,13 +1774,10 @@ int tcp_read_skb(struct sock *sk, skb_read_actor_t recv_actor) + copied = used; + break; + } +- seq += used; + copied += used; + +- if (tcp_flags & TCPHDR_FIN) { +- ++seq; ++ if (tcp_flags & TCPHDR_FIN) + break; +- } + } + return copied; + } +-- +2.40.1 + diff --git a/queue-6.1/drivers-net-process-the-result-of-hdlc_open-and-add-.patch b/queue-6.1/drivers-net-process-the-result-of-hdlc_open-and-add-.patch new file mode 100644 index 00000000000..9c35c846c23 --- /dev/null +++ b/queue-6.1/drivers-net-process-the-result-of-hdlc_open-and-add-.patch @@ -0,0 +1,78 @@ +From db6eec7850b1d562c10d86a30b549b8c80062f77 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Sep 2023 17:25:02 +0300 +Subject: drivers/net: process the result of hdlc_open() and add call of + hdlc_close() in uhdlc_close() + +From: Alexandra Diupina + +[ Upstream commit a59addacf899b1b21a7b7449a1c52c98704c2472 ] + +Process the result of hdlc_open() and call uhdlc_close() +in case of an error. It is necessary to pass the error +code up the control flow, similar to a possible +error in request_irq(). +Also add a hdlc_close() call to the uhdlc_close() +because the comment to hdlc_close() says it must be called +by the hardware driver when the HDLC device is being closed + +Found by Linux Verification Center (linuxtesting.org) with SVACE. + +Fixes: c19b6d246a35 ("drivers/net: support hdlc function for QE-UCC") +Signed-off-by: Alexandra Diupina +Reviewed-by: Christophe Leroy +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/wan/fsl_ucc_hdlc.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c +index 1c53b55469270..5fec8abe8e1d3 100644 +--- a/drivers/net/wan/fsl_ucc_hdlc.c ++++ b/drivers/net/wan/fsl_ucc_hdlc.c +@@ -34,6 +34,8 @@ + #define TDM_PPPOHT_SLIC_MAXIN + #define RX_BD_ERRORS (R_CD_S | R_OV_S | R_CR_S | R_AB_S | R_NO_S | R_LG_S) + ++static int uhdlc_close(struct net_device *dev); ++ + static struct ucc_tdm_info utdm_primary_info = { + .uf_info = { + .tsa = 0, +@@ -708,6 +710,7 @@ static int uhdlc_open(struct net_device *dev) + hdlc_device *hdlc = dev_to_hdlc(dev); + struct ucc_hdlc_private *priv = hdlc->priv; + struct ucc_tdm *utdm = priv->utdm; ++ int rc = 0; + + if (priv->hdlc_busy != 1) { + if (request_irq(priv->ut_info->uf_info.irq, +@@ -731,10 +734,13 @@ static int uhdlc_open(struct net_device *dev) + napi_enable(&priv->napi); + netdev_reset_queue(dev); + netif_start_queue(dev); +- hdlc_open(dev); ++ ++ rc = hdlc_open(dev); ++ if (rc) ++ uhdlc_close(dev); + } + +- return 0; ++ return rc; + } + + static void uhdlc_memclean(struct ucc_hdlc_private *priv) +@@ -824,6 +830,8 @@ static int uhdlc_close(struct net_device *dev) + netdev_reset_queue(dev); + priv->hdlc_busy = 0; + ++ hdlc_close(dev); ++ + return 0; + } + +-- +2.40.1 + diff --git a/queue-6.1/erofs-fix-memory-leak-of-lzma-global-compressed-dedu.patch b/queue-6.1/erofs-fix-memory-leak-of-lzma-global-compressed-dedu.patch new file mode 100644 index 00000000000..6588449e030 --- /dev/null +++ b/queue-6.1/erofs-fix-memory-leak-of-lzma-global-compressed-dedu.patch @@ -0,0 +1,45 @@ +From f3db9a070ca35d59630002ea2b49bd7db5b86fe7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 7 Sep 2023 13:05:42 +0800 +Subject: erofs: fix memory leak of LZMA global compressed deduplication + +From: Gao Xiang + +[ Upstream commit 75a5221630fe5aa3fedba7a06be618db0f79ba1e ] + +When stressing microLZMA EROFS images with the new global compressed +deduplication feature enabled (`-Ededupe`), I found some short-lived +temporary pages weren't properly released, which could slowly cause +unexpected OOMs hours later. + +Let's fix it now (LZ4 and DEFLATE don't have this issue.) + +Fixes: 5c2a64252c5d ("erofs: introduce partial-referenced pclusters") +Signed-off-by: Gao Xiang +Link: https://lore.kernel.org/r/20230907050542.97152-1-hsiangkao@linux.alibaba.com +Signed-off-by: Sasha Levin +--- + fs/erofs/decompressor_lzma.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/fs/erofs/decompressor_lzma.c b/fs/erofs/decompressor_lzma.c +index 5cd612a8f8584..49addc345aebe 100644 +--- a/fs/erofs/decompressor_lzma.c ++++ b/fs/erofs/decompressor_lzma.c +@@ -217,9 +217,12 @@ int z_erofs_lzma_decompress(struct z_erofs_decompress_req *rq, + strm->buf.out_size = min_t(u32, outlen, + PAGE_SIZE - pageofs); + outlen -= strm->buf.out_size; +- if (!rq->out[no] && rq->fillgaps) /* deduped */ ++ if (!rq->out[no] && rq->fillgaps) { /* deduped */ + rq->out[no] = erofs_allocpage(pagepool, + GFP_KERNEL | __GFP_NOFAIL); ++ set_page_private(rq->out[no], ++ Z_EROFS_SHORTLIVED_PAGE); ++ } + if (rq->out[no]) + strm->buf.out = kmap(rq->out[no]) + pageofs; + pageofs = 0; +-- +2.40.1 + diff --git a/queue-6.1/hid-intel-ish-hid-ipc-disable-and-reenable-acpi-gpe-.patch b/queue-6.1/hid-intel-ish-hid-ipc-disable-and-reenable-acpi-gpe-.patch new file mode 100644 index 00000000000..3abb3979c99 --- /dev/null +++ b/queue-6.1/hid-intel-ish-hid-ipc-disable-and-reenable-acpi-gpe-.patch @@ -0,0 +1,55 @@ +From d416776961722288846eabda3a0f7dccacd41ee7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Oct 2023 08:53:32 -0700 +Subject: HID: intel-ish-hid: ipc: Disable and reenable ACPI GPE bit + +From: Srinivas Pandruvada + +[ Upstream commit 8f02139ad9a7e6e5c05712f8c1501eebed8eacfd ] + +The EHL (Elkhart Lake) based platforms provide a OOB (Out of band) +service, which allows to wakup device when the system is in S5 (Soft-Off +state). This OOB service can be enabled/disabled from BIOS settings. When +enabled, the ISH device gets PME wake capability. To enable PME wakeup, +driver also needs to enable ACPI GPE bit. + +On resume, BIOS will clear the wakeup bit. So driver need to re-enable it +in resume function to keep the next wakeup capability. But this BIOS +clearing of wakeup bit doesn't decrement internal OS GPE reference count, +so this reenabling on every resume will cause reference count to overflow. + +So first disable and reenable ACPI GPE bit using acpi_disable_gpe(). + +Fixes: 2e23a70edabe ("HID: intel-ish-hid: ipc: finish power flow for EHL OOB") +Reported-by: Kai-Heng Feng +Closes: https://lore.kernel.org/lkml/CAAd53p4=oLYiH2YbVSmrPNj1zpMcfp=Wxbasb5vhMXOWCArLCg@mail.gmail.com/T/ +Tested-by: Kai-Heng Feng +Signed-off-by: Srinivas Pandruvada +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/intel-ish-hid/ipc/pci-ish.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c +index 55cb25038e632..710fda5f19e1c 100644 +--- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c ++++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c +@@ -133,6 +133,14 @@ static int enable_gpe(struct device *dev) + } + wakeup = &adev->wakeup; + ++ /* ++ * Call acpi_disable_gpe(), so that reference count ++ * gpe_event_info->runtime_count doesn't overflow. ++ * When gpe_event_info->runtime_count = 0, the call ++ * to acpi_disable_gpe() simply return. ++ */ ++ acpi_disable_gpe(wakeup->gpe_device, wakeup->gpe_number); ++ + acpi_sts = acpi_enable_gpe(wakeup->gpe_device, wakeup->gpe_number); + if (ACPI_FAILURE(acpi_sts)) { + dev_err(dev, "enable ose_gpe failed\n"); +-- +2.40.1 + diff --git a/queue-6.1/hid-sony-fix-a-potential-memory-leak-in-sony_probe.patch b/queue-6.1/hid-sony-fix-a-potential-memory-leak-in-sony_probe.patch new file mode 100644 index 00000000000..b4df0e16195 --- /dev/null +++ b/queue-6.1/hid-sony-fix-a-potential-memory-leak-in-sony_probe.patch @@ -0,0 +1,37 @@ +From 697c2e49a066dbd6bdbe33a98c1bba4ef9c8342c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Sep 2023 18:04:00 +0200 +Subject: HID: sony: Fix a potential memory leak in sony_probe() + +From: Christophe JAILLET + +[ Upstream commit e1cd4004cde7c9b694bbdd8def0e02288ee58c74 ] + +If an error occurs after a successful usb_alloc_urb() call, usb_free_urb() +should be called. + +Fixes: fb1a79a6b6e1 ("HID: sony: fix freeze when inserting ghlive ps3/wii dongles") +Signed-off-by: Christophe JAILLET +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-sony.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c +index 03691cdcfb8e1..5b3f58e068807 100644 +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -3074,6 +3074,9 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) + return ret; + + err: ++ if (sc->ghl_urb) ++ usb_free_urb(sc->ghl_urb); ++ + hid_hw_stop(hdev); + return ret; + } +-- +2.40.1 + diff --git a/queue-6.1/hid-sony-remove-duplicate-null-check-before-calling-.patch b/queue-6.1/hid-sony-remove-duplicate-null-check-before-calling-.patch new file mode 100644 index 00000000000..c18b2004301 --- /dev/null +++ b/queue-6.1/hid-sony-remove-duplicate-null-check-before-calling-.patch @@ -0,0 +1,37 @@ +From 08ed744451cd06f1bf4aa44d4b8afef442c7fdf8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Oct 2023 21:10:41 +0200 +Subject: HID: sony: remove duplicate NULL check before calling usb_free_urb() + +From: Jiri Kosina + +[ Upstream commit b328dd02e19cb9d3b35de4322f5363516a20ac8c ] + +usb_free_urb() does the NULL check itself, so there is no need to duplicate +it prior to calling. + +Reported-by: kernel test robot +Fixes: e1cd4004cde7c9 ("HID: sony: Fix a potential memory leak in sony_probe()") +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-sony.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c +index 5b3f58e068807..f7f7252d839ee 100644 +--- a/drivers/hid/hid-sony.c ++++ b/drivers/hid/hid-sony.c +@@ -3074,8 +3074,7 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) + return ret; + + err: +- if (sc->ghl_urb) +- usb_free_urb(sc->ghl_urb); ++ usb_free_urb(sc->ghl_urb); + + hid_hw_stop(hdev); + return ret; +-- +2.40.1 + diff --git a/queue-6.1/ibmveth-remove-condition-to-recompute-tcp-header-che.patch b/queue-6.1/ibmveth-remove-condition-to-recompute-tcp-header-che.patch new file mode 100644 index 00000000000..691de5bcb67 --- /dev/null +++ b/queue-6.1/ibmveth-remove-condition-to-recompute-tcp-header-che.patch @@ -0,0 +1,72 @@ +From c4d95420b88c01f53401bf0aff886d5202006949 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Sep 2023 16:42:51 -0500 +Subject: ibmveth: Remove condition to recompute TCP header checksum. + +From: David Wilder + +[ Upstream commit 51e7a66666e0ca9642c59464ef8359f0ac604d41 ] + +In some OVS environments the TCP pseudo header checksum may need to be +recomputed. Currently this is only done when the interface instance is +configured for "Trunk Mode". We found the issue also occurs in some +Kubernetes environments, these environments do not use "Trunk Mode", +therefor the condition is removed. + +Performance tests with this change show only a fractional decrease in +throughput (< 0.2%). + +Fixes: 7525de2516fb ("ibmveth: Set CHECKSUM_PARTIAL if NULL TCP CSUM.") +Signed-off-by: David Wilder +Reviewed-by: Nick Child +Reviewed-by: Jacob Keller +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ibm/ibmveth.c | 25 ++++++++++++------------- + 1 file changed, 12 insertions(+), 13 deletions(-) + +diff --git a/drivers/net/ethernet/ibm/ibmveth.c b/drivers/net/ethernet/ibm/ibmveth.c +index 0b4ec6e41eb41..1d21a281222d9 100644 +--- a/drivers/net/ethernet/ibm/ibmveth.c ++++ b/drivers/net/ethernet/ibm/ibmveth.c +@@ -1308,24 +1308,23 @@ static void ibmveth_rx_csum_helper(struct sk_buff *skb, + * the user space for finding a flow. During this process, OVS computes + * checksum on the first packet when CHECKSUM_PARTIAL flag is set. + * +- * So, re-compute TCP pseudo header checksum when configured for +- * trunk mode. ++ * So, re-compute TCP pseudo header checksum. + */ ++ + if (iph_proto == IPPROTO_TCP) { + struct tcphdr *tcph = (struct tcphdr *)(skb->data + iphlen); ++ + if (tcph->check == 0x0000) { + /* Recompute TCP pseudo header checksum */ +- if (adapter->is_active_trunk) { +- tcphdrlen = skb->len - iphlen; +- if (skb_proto == ETH_P_IP) +- tcph->check = +- ~csum_tcpudp_magic(iph->saddr, +- iph->daddr, tcphdrlen, iph_proto, 0); +- else if (skb_proto == ETH_P_IPV6) +- tcph->check = +- ~csum_ipv6_magic(&iph6->saddr, +- &iph6->daddr, tcphdrlen, iph_proto, 0); +- } ++ tcphdrlen = skb->len - iphlen; ++ if (skb_proto == ETH_P_IP) ++ tcph->check = ++ ~csum_tcpudp_magic(iph->saddr, ++ iph->daddr, tcphdrlen, iph_proto, 0); ++ else if (skb_proto == ETH_P_IPV6) ++ tcph->check = ++ ~csum_ipv6_magic(&iph6->saddr, ++ &iph6->daddr, tcphdrlen, iph_proto, 0); + /* Setup SKB fields for checksum offload */ + skb_partial_csum_set(skb, iphlen, + offsetof(struct tcphdr, check)); +-- +2.40.1 + diff --git a/queue-6.1/ima-finish-deprecation-of-ima_trusted_keyring-kconfi.patch b/queue-6.1/ima-finish-deprecation-of-ima_trusted_keyring-kconfi.patch new file mode 100644 index 00000000000..d9e3f4bc3b0 --- /dev/null +++ b/queue-6.1/ima-finish-deprecation-of-ima_trusted_keyring-kconfi.patch @@ -0,0 +1,50 @@ +From 722f609c6bb2979d2d72ff5989b292ea732b53db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Sep 2023 06:45:05 +0000 +Subject: ima: Finish deprecation of IMA_TRUSTED_KEYRING Kconfig + +From: Oleksandr Tymoshenko + +[ Upstream commit be210c6d3597faf330cb9af33b9f1591d7b2a983 ] + +The removal of IMA_TRUSTED_KEYRING made IMA_LOAD_X509 +and IMA_BLACKLIST_KEYRING unavailable because the latter +two depend on the former. Since IMA_TRUSTED_KEYRING was +deprecated in favor of INTEGRITY_TRUSTED_KEYRING use it +as a dependency for the two Kconfigs affected by the +deprecation. + +Fixes: 5087fd9e80e5 ("ima: Remove deprecated IMA_TRUSTED_KEYRING Kconfig") +Signed-off-by: Oleksandr Tymoshenko +Reviewed-by: Nayna Jain +Signed-off-by: Mimi Zohar +Signed-off-by: Sasha Levin +--- + security/integrity/ima/Kconfig | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig +index c17660bf5f347..e6df7c930397c 100644 +--- a/security/integrity/ima/Kconfig ++++ b/security/integrity/ima/Kconfig +@@ -268,7 +268,7 @@ config IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY + config IMA_BLACKLIST_KEYRING + bool "Create IMA machine owner blacklist keyrings (EXPERIMENTAL)" + depends on SYSTEM_TRUSTED_KEYRING +- depends on IMA_TRUSTED_KEYRING ++ depends on INTEGRITY_TRUSTED_KEYRING + default n + help + This option creates an IMA blacklist keyring, which contains all +@@ -278,7 +278,7 @@ config IMA_BLACKLIST_KEYRING + + config IMA_LOAD_X509 + bool "Load X509 certificate onto the '.ima' trusted keyring" +- depends on IMA_TRUSTED_KEYRING ++ depends on INTEGRITY_TRUSTED_KEYRING + default n + help + File signature verification is based on the public keys +-- +2.40.1 + diff --git a/queue-6.1/ima-rework-config_ima-dependency-block.patch b/queue-6.1/ima-rework-config_ima-dependency-block.patch new file mode 100644 index 00000000000..5c6eca347c4 --- /dev/null +++ b/queue-6.1/ima-rework-config_ima-dependency-block.patch @@ -0,0 +1,141 @@ +From 5067c4014110158d000fca1136d787d4b315daf7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Sep 2023 09:22:14 +0200 +Subject: ima: rework CONFIG_IMA dependency block + +From: Arnd Bergmann + +[ Upstream commit 91e326563ee34509c35267808a4b1b3ea3db62a8 ] + +Changing the direct dependencies of IMA_BLACKLIST_KEYRING and +IMA_LOAD_X509 caused them to no longer depend on IMA, but a +a configuration without IMA results in link failures: + +arm-linux-gnueabi-ld: security/integrity/iint.o: in function `integrity_load_keys': +iint.c:(.init.text+0xd8): undefined reference to `ima_load_x509' + +aarch64-linux-ld: security/integrity/digsig_asymmetric.o: in function `asymmetric_verify': +digsig_asymmetric.c:(.text+0x104): undefined reference to `ima_blacklist_keyring' + +Adding explicit dependencies on IMA would fix this, but a more reliable +way to do this is to enclose the entire Kconfig file in an 'if IMA' block. +This also allows removing the existing direct dependencies. + +Fixes: be210c6d3597f ("ima: Finish deprecation of IMA_TRUSTED_KEYRING Kconfig") +Signed-off-by: Arnd Bergmann +Signed-off-by: Mimi Zohar +Signed-off-by: Sasha Levin +--- + security/integrity/ima/Kconfig | 18 ++++++------------ + 1 file changed, 6 insertions(+), 12 deletions(-) + +diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig +index e6df7c930397c..6ef7bde551263 100644 +--- a/security/integrity/ima/Kconfig ++++ b/security/integrity/ima/Kconfig +@@ -29,9 +29,11 @@ config IMA + to learn more about IMA. + If unsure, say N. + ++if IMA ++ + config IMA_KEXEC + bool "Enable carrying the IMA measurement list across a soft boot" +- depends on IMA && TCG_TPM && HAVE_IMA_KEXEC ++ depends on TCG_TPM && HAVE_IMA_KEXEC + default n + help + TPM PCRs are only reset on a hard reboot. In order to validate +@@ -43,7 +45,6 @@ config IMA_KEXEC + + config IMA_MEASURE_PCR_IDX + int +- depends on IMA + range 8 14 + default 10 + help +@@ -53,7 +54,7 @@ config IMA_MEASURE_PCR_IDX + + config IMA_LSM_RULES + bool +- depends on IMA && AUDIT && (SECURITY_SELINUX || SECURITY_SMACK || SECURITY_APPARMOR) ++ depends on AUDIT && (SECURITY_SELINUX || SECURITY_SMACK || SECURITY_APPARMOR) + default y + help + Disabling this option will disregard LSM based policy rules. +@@ -61,7 +62,6 @@ config IMA_LSM_RULES + choice + prompt "Default template" + default IMA_NG_TEMPLATE +- depends on IMA + help + Select the default IMA measurement template. + +@@ -80,14 +80,12 @@ endchoice + + config IMA_DEFAULT_TEMPLATE + string +- depends on IMA + default "ima-ng" if IMA_NG_TEMPLATE + default "ima-sig" if IMA_SIG_TEMPLATE + + choice + prompt "Default integrity hash algorithm" + default IMA_DEFAULT_HASH_SHA1 +- depends on IMA + help + Select the default hash algorithm used for the measurement + list, integrity appraisal and audit log. The compiled default +@@ -117,7 +115,6 @@ endchoice + + config IMA_DEFAULT_HASH + string +- depends on IMA + default "sha1" if IMA_DEFAULT_HASH_SHA1 + default "sha256" if IMA_DEFAULT_HASH_SHA256 + default "sha512" if IMA_DEFAULT_HASH_SHA512 +@@ -126,7 +123,6 @@ config IMA_DEFAULT_HASH + + config IMA_WRITE_POLICY + bool "Enable multiple writes to the IMA policy" +- depends on IMA + default n + help + IMA policy can now be updated multiple times. The new rules get +@@ -137,7 +133,6 @@ config IMA_WRITE_POLICY + + config IMA_READ_POLICY + bool "Enable reading back the current IMA policy" +- depends on IMA + default y if IMA_WRITE_POLICY + default n if !IMA_WRITE_POLICY + help +@@ -147,7 +142,6 @@ config IMA_READ_POLICY + + config IMA_APPRAISE + bool "Appraise integrity measurements" +- depends on IMA + default n + help + This option enables local measurement integrity appraisal. +@@ -303,7 +297,6 @@ config IMA_APPRAISE_SIGNED_INIT + + config IMA_MEASURE_ASYMMETRIC_KEYS + bool +- depends on IMA + depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y + default y + +@@ -322,7 +315,8 @@ config IMA_SECURE_AND_OR_TRUSTED_BOOT + + config IMA_DISABLE_HTABLE + bool "Disable htable to allow measurement of duplicate records" +- depends on IMA + default n + help + This option disables htable to allow measurement of duplicate records. ++ ++endif +-- +2.40.1 + diff --git a/queue-6.1/intel_idle-add-emerald-rapids-xeon-support.patch b/queue-6.1/intel_idle-add-emerald-rapids-xeon-support.patch new file mode 100644 index 00000000000..e6d02cbda1e --- /dev/null +++ b/queue-6.1/intel_idle-add-emerald-rapids-xeon-support.patch @@ -0,0 +1,46 @@ +From 9988912f1984ebdcd99fd84d5698646676997cd8 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 20 Jan 2023 11:15:28 +0200 +Subject: intel_idle: add Emerald Rapids Xeon support + +From: Artem Bityutskiy + +[ Upstream commit 74528edfbc664f9d2c927c4e5a44f1285598ed0f ] + +Emerald Rapids (EMR) is the next Intel Xeon processor after Sapphire +Rapids (SPR). + +EMR C-states are the same as SPR C-states, and we expect that EMR +C-state characteristics (latency and target residency) will be the +same as in SPR. Therefore, add EMR support by using SPR C-states table. + +Signed-off-by: Artem Bityutskiy +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Sasha Levin +--- + drivers/idle/intel_idle.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c +index cfeb24d40d378..bb3d10099ba44 100644 +--- a/drivers/idle/intel_idle.c ++++ b/drivers/idle/intel_idle.c +@@ -1430,6 +1430,7 @@ static const struct x86_cpu_id intel_idle_ids[] __initconst = { + X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, &idle_cpu_adl_l), + X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_N, &idle_cpu_adl_n), + X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, &idle_cpu_spr), ++ X86_MATCH_INTEL_FAM6_MODEL(EMERALDRAPIDS_X, &idle_cpu_spr), + X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNL, &idle_cpu_knl), + X86_MATCH_INTEL_FAM6_MODEL(XEON_PHI_KNM, &idle_cpu_knl), + X86_MATCH_INTEL_FAM6_MODEL(ATOM_GOLDMONT, &idle_cpu_bxt), +@@ -1862,6 +1863,7 @@ static void __init intel_idle_init_cstates_icpu(struct cpuidle_driver *drv) + skx_idle_state_table_update(); + break; + case INTEL_FAM6_SAPPHIRERAPIDS_X: ++ case INTEL_FAM6_EMERALDRAPIDS_X: + spr_idle_state_table_update(); + break; + case INTEL_FAM6_ALDERLAKE: +-- +2.40.1 + diff --git a/queue-6.1/iommu-mediatek-fix-share-pgtable-for-iova-over-4gb.patch b/queue-6.1/iommu-mediatek-fix-share-pgtable-for-iova-over-4gb.patch new file mode 100644 index 00000000000..65066fd3101 --- /dev/null +++ b/queue-6.1/iommu-mediatek-fix-share-pgtable-for-iova-over-4gb.patch @@ -0,0 +1,68 @@ +From bc1c0e89f08390f49c92cb6f0ed9c6e9efb22bc1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 19 Aug 2023 16:14:43 +0800 +Subject: iommu/mediatek: Fix share pgtable for iova over 4GB + +From: Yong Wu + +[ Upstream commit b07eba71a512eb196cbcc29765c29c8c29b11b59 ] + +In mt8192/mt8186, there is only one MM IOMMU that supports 16GB iova +space, which is shared by display, vcodec and camera. These two SoC use +one pgtable and have not the flag SHARE_PGTABLE, we should also keep +share pgtable for this case. + +In mtk_iommu_domain_finalise, MM IOMMU always share pgtable, thus remove +the flag SHARE_PGTABLE checking. Infra IOMMU always uses independent +pgtable. + +Fixes: cf69ef46dbd9 ("iommu/mediatek: Fix two IOMMU share pagetable issue") +Reported-by: Laura Nao +Closes: https://lore.kernel.org/linux-iommu/20230818154156.314742-1-laura.nao@collabora.com/ +Signed-off-by: Yong Wu +Reviewed-by: AngeloGioacchino Del Regno +Tested-by: Laura Nao +Link: https://lore.kernel.org/r/20230819081443.8333-1-yong.wu@mediatek.com +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + drivers/iommu/mtk_iommu.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c +index 9673cd60c84fc..0ba2a63a9538a 100644 +--- a/drivers/iommu/mtk_iommu.c ++++ b/drivers/iommu/mtk_iommu.c +@@ -223,7 +223,7 @@ struct mtk_iommu_data { + struct device *smicomm_dev; + + struct mtk_iommu_bank_data *bank; +- struct mtk_iommu_domain *share_dom; /* For 2 HWs share pgtable */ ++ struct mtk_iommu_domain *share_dom; + + struct regmap *pericfg; + struct mutex mutex; /* Protect m4u_group/m4u_dom above */ +@@ -579,8 +579,8 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, + struct mtk_iommu_domain *share_dom = data->share_dom; + const struct mtk_iommu_iova_region *region; + +- /* Always use share domain in sharing pgtable case */ +- if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE) && share_dom) { ++ /* Share pgtable when 2 MM IOMMU share the pgtable or one IOMMU use multiple iova ranges */ ++ if (share_dom) { + dom->iop = share_dom->iop; + dom->cfg = share_dom->cfg; + dom->domain.pgsize_bitmap = share_dom->cfg.pgsize_bitmap; +@@ -613,8 +613,7 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_domain *dom, + /* Update our support page sizes bitmap */ + dom->domain.pgsize_bitmap = dom->cfg.pgsize_bitmap; + +- if (MTK_IOMMU_HAS_FLAG(data->plat_data, SHARE_PGTABLE)) +- data->share_dom = dom; ++ data->share_dom = dom; + + update_iova_region: + /* Update the iova region for this domain */ +-- +2.40.1 + diff --git a/queue-6.1/ipv4-ipv6-fix-handling-of-transhdrlen-in-__ip-6-_app.patch b/queue-6.1/ipv4-ipv6-fix-handling-of-transhdrlen-in-__ip-6-_app.patch new file mode 100644 index 00000000000..211d32e6297 --- /dev/null +++ b/queue-6.1/ipv4-ipv6-fix-handling-of-transhdrlen-in-__ip-6-_app.patch @@ -0,0 +1,81 @@ +From 566c500f4fdfcee7d255a1aa828a1b259b4ccb35 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Sep 2023 11:41:19 +0100 +Subject: ipv4, ipv6: Fix handling of transhdrlen in __ip{,6}_append_data() + +From: David Howells + +[ Upstream commit 9d4c75800f61e5d75c1659ba201b6c0c7ead3070 ] + +Including the transhdrlen in length is a problem when the packet is +partially filled (e.g. something like send(MSG_MORE) happened previously) +when appending to an IPv4 or IPv6 packet as we don't want to repeat the +transport header or account for it twice. This can happen under some +circumstances, such as splicing into an L2TP socket. + +The symptom observed is a warning in __ip6_append_data(): + + WARNING: CPU: 1 PID: 5042 at net/ipv6/ip6_output.c:1800 __ip6_append_data.isra.0+0x1be8/0x47f0 net/ipv6/ip6_output.c:1800 + +that occurs when MSG_SPLICE_PAGES is used to append more data to an already +partially occupied skbuff. The warning occurs when 'copy' is larger than +the amount of data in the message iterator. This is because the requested +length includes the transport header length when it shouldn't. This can be +triggered by, for example: + + sfd = socket(AF_INET6, SOCK_DGRAM, IPPROTO_L2TP); + bind(sfd, ...); // ::1 + connect(sfd, ...); // ::1 port 7 + send(sfd, buffer, 4100, MSG_MORE); + sendfile(sfd, dfd, NULL, 1024); + +Fix this by only adding transhdrlen into the length if the write queue is +empty in l2tp_ip6_sendmsg(), analogously to how UDP does things. + +l2tp_ip_sendmsg() looks like it won't suffer from this problem as it builds +the UDP packet itself. + +Fixes: a32e0eec7042 ("l2tp: introduce L2TPv3 IP encapsulation support for IPv6") +Reported-by: syzbot+62cbf263225ae13ff153@syzkaller.appspotmail.com +Link: https://lore.kernel.org/r/0000000000001c12b30605378ce8@google.com/ +Suggested-by: Willem de Bruijn +Signed-off-by: David Howells +cc: Eric Dumazet +cc: Willem de Bruijn +cc: "David S. Miller" +cc: David Ahern +cc: Paolo Abeni +cc: Jakub Kicinski +cc: netdev@vger.kernel.org +cc: bpf@vger.kernel.org +cc: syzkaller-bugs@googlegroups.com +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/l2tp/l2tp_ip6.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c +index bce4132b0a5c8..314ec3a51e8de 100644 +--- a/net/l2tp/l2tp_ip6.c ++++ b/net/l2tp/l2tp_ip6.c +@@ -510,7 +510,6 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + */ + if (len > INT_MAX - transhdrlen) + return -EMSGSIZE; +- ulen = len + transhdrlen; + + /* Mirror BSD error message compatibility */ + if (msg->msg_flags & MSG_OOB) +@@ -631,6 +630,7 @@ static int l2tp_ip6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len) + + back_from_confirm: + lock_sock(sk); ++ ulen = len + skb_queue_empty(&sk->sk_write_queue) ? transhdrlen : 0; + err = ip6_append_data(sk, ip_generic_getfrag, msg, + ulen, transhdrlen, &ipc6, + &fl6, (struct rt6_info *)dst, +-- +2.40.1 + diff --git a/queue-6.1/ipv4-set-offload_failed-flag-in-fibmatch-results.patch b/queue-6.1/ipv4-set-offload_failed-flag-in-fibmatch-results.patch new file mode 100644 index 00000000000..f3e0b608d0f --- /dev/null +++ b/queue-6.1/ipv4-set-offload_failed-flag-in-fibmatch-results.patch @@ -0,0 +1,57 @@ +From acbbbc65745fb8b07cf5941dd1dddaacfb89fae2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Sep 2023 14:27:30 -0400 +Subject: ipv4: Set offload_failed flag in fibmatch results + +From: Benjamin Poirier + +[ Upstream commit 0add5c597f3253a9c6108a0a81d57f44ab0d9d30 ] + +Due to a small omission, the offload_failed flag is missing from ipv4 +fibmatch results. Make sure it is set correctly. + +The issue can be witnessed using the following commands: +echo "1 1" > /sys/bus/netdevsim/new_device +ip link add dummy1 up type dummy +ip route add 192.0.2.0/24 dev dummy1 +echo 1 > /sys/kernel/debug/netdevsim/netdevsim1/fib/fail_route_offload +ip route add 198.51.100.0/24 dev dummy1 +ip route + # 192.168.15.0/24 has rt_trap + # 198.51.100.0/24 has rt_offload_failed +ip route get 192.168.15.1 fibmatch + # Result has rt_trap +ip route get 198.51.100.1 fibmatch + # Result differs from the route shown by `ip route`, it is missing + # rt_offload_failed +ip link del dev dummy1 +echo 1 > /sys/bus/netdevsim/del_device + +Fixes: 36c5100e859d ("IPv4: Add "offload failed" indication to routes") +Signed-off-by: Benjamin Poirier +Reviewed-by: Ido Schimmel +Reviewed-by: Simon Horman +Reviewed-by: David Ahern +Link: https://lore.kernel.org/r/20230926182730.231208-1-bpoirier@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/route.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 608bd9f8dbc86..9cbaae4f5ee71 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -3421,6 +3421,8 @@ static int inet_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh, + fa->fa_type == fri.type) { + fri.offload = READ_ONCE(fa->offload); + fri.trap = READ_ONCE(fa->trap); ++ fri.offload_failed = ++ READ_ONCE(fa->offload_failed); + break; + } + } +-- +2.40.1 + diff --git a/queue-6.1/ipv6-tcp-add-a-missing-nf_reset_ct-in-3whs-handling.patch b/queue-6.1/ipv6-tcp-add-a-missing-nf_reset_ct-in-3whs-handling.patch new file mode 100644 index 00000000000..c926899b0a9 --- /dev/null +++ b/queue-6.1/ipv6-tcp-add-a-missing-nf_reset_ct-in-3whs-handling.patch @@ -0,0 +1,72 @@ +From dad19c72b1950c4722746ef9caa4f1839d60a46a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Sep 2023 23:04:58 +0200 +Subject: ipv6: tcp: add a missing nf_reset_ct() in 3WHS handling + +From: Ilya Maximets + +[ Upstream commit 9593c7cb6cf670ef724d17f7f9affd7a8d2ad0c5 ] + +Commit b0e214d21203 ("netfilter: keep conntrack reference until +IPsecv6 policy checks are done") is a direct copy of the old +commit b59c270104f0 ("[NETFILTER]: Keep conntrack reference until +IPsec policy checks are done") but for IPv6. However, it also +copies a bug that this old commit had. That is: when the third +packet of 3WHS connection establishment contains payload, it is +added into socket receive queue without the XFRM check and the +drop of connection tracking context. + +That leads to nf_conntrack module being impossible to unload as +it waits for all the conntrack references to be dropped while +the packet release is deferred in per-cpu cache indefinitely, if +not consumed by the application. + +The issue for IPv4 was fixed in commit 6f0012e35160 ("tcp: add a +missing nf_reset_ct() in 3WHS handling") by adding a missing XFRM +check and correctly dropping the conntrack context. However, the +issue was introduced to IPv6 code afterwards. Fixing it the +same way for IPv6 now. + +Fixes: b0e214d21203 ("netfilter: keep conntrack reference until IPsecv6 policy checks are done") +Link: https://lore.kernel.org/netdev/d589a999-d4dd-2768-b2d5-89dec64a4a42@ovn.org/ +Signed-off-by: Ilya Maximets +Acked-by: Florian Westphal +Reviewed-by: Eric Dumazet +Link: https://lore.kernel.org/r/20230922210530.2045146-1-i.maximets@ovn.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv6/tcp_ipv6.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c +index 4bdd356bb5c46..7be89dcfd5fc5 100644 +--- a/net/ipv6/tcp_ipv6.c ++++ b/net/ipv6/tcp_ipv6.c +@@ -1644,9 +1644,12 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb) + struct sock *nsk; + + sk = req->rsk_listener; +- drop_reason = tcp_inbound_md5_hash(sk, skb, +- &hdr->saddr, &hdr->daddr, +- AF_INET6, dif, sdif); ++ if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) ++ drop_reason = SKB_DROP_REASON_XFRM_POLICY; ++ else ++ drop_reason = tcp_inbound_md5_hash(sk, skb, ++ &hdr->saddr, &hdr->daddr, ++ AF_INET6, dif, sdif); + if (drop_reason) { + sk_drops_add(sk, skb); + reqsk_put(req); +@@ -1693,6 +1696,7 @@ INDIRECT_CALLABLE_SCOPE int tcp_v6_rcv(struct sk_buff *skb) + } + goto discard_and_relse; + } ++ nf_reset_ct(skb); + if (nsk == sk) { + reqsk_put(req); + tcp_v6_restore_cb(skb); +-- +2.40.1 + diff --git a/queue-6.1/leds-drop-bug_on-check-for-led_color_id_multi.patch b/queue-6.1/leds-drop-bug_on-check-for-led_color_id_multi.patch new file mode 100644 index 00000000000..87ac2136fbf --- /dev/null +++ b/queue-6.1/leds-drop-bug_on-check-for-led_color_id_multi.patch @@ -0,0 +1,48 @@ +From 5658e27c09c00fd48d029915eb2634f87270656c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Sep 2023 16:07:24 +0200 +Subject: leds: Drop BUG_ON check for LED_COLOR_ID_MULTI +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Marek Behún + +[ Upstream commit 9dc1664fab2246bc2c3e9bf2cf21518a857f9b5b ] + +Commit c3f853184bed ("leds: Fix BUG_ON check for LED_COLOR_ID_MULTI that +is always false") fixed a no-op BUG_ON. This turned out to cause a +regression, since some in-tree device-tree files already use +LED_COLOR_ID_MULTI. + +Drop the BUG_ON altogether. + +Fixes: c3f853184bed ("leds: Fix BUG_ON check for LED_COLOR_ID_MULTI that is always false") +Reported-by: Da Xue +Closes: https://lore.kernel.org/linux-leds/ZQLelWcNjjp2xndY@duo.ucw.cz/T/ +Signed-off-by: Marek Behún +Link: https://lore.kernel.org/r/20230918140724.18634-1-kabel@kernel.org +Signed-off-by: Lee Jones +Signed-off-by: Sasha Levin +--- + drivers/leds/led-core.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/drivers/leds/led-core.c b/drivers/leds/led-core.c +index aad8bc44459fe..d94d60b526461 100644 +--- a/drivers/leds/led-core.c ++++ b/drivers/leds/led-core.c +@@ -424,10 +424,6 @@ int led_compose_name(struct device *dev, struct led_init_data *init_data, + + led_parse_fwnode_props(dev, fwnode, &props); + +- /* We want to label LEDs that can produce full range of colors +- * as RGB, not multicolor */ +- BUG_ON(props.color == LED_COLOR_ID_MULTI); +- + if (props.label) { + /* + * If init_data.devicename is NULL, then it indicates that +-- +2.40.1 + diff --git a/queue-6.1/modpost-add-missing-else-to-the-of-check.patch b/queue-6.1/modpost-add-missing-else-to-the-of-check.patch new file mode 100644 index 00000000000..ab389331a74 --- /dev/null +++ b/queue-6.1/modpost-add-missing-else-to-the-of-check.patch @@ -0,0 +1,54 @@ +From b8bc83d86fa3d8c377b8a8d4e7634b3a00ab1597 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Sep 2023 17:28:07 -0300 +Subject: modpost: add missing else to the "of" check + +From: Mauricio Faria de Oliveira + +[ Upstream commit cbc3d00cf88fda95dbcafee3b38655b7a8f2650a ] + +Without this 'else' statement, an "usb" name goes into two handlers: +the first/previous 'if' statement _AND_ the for-loop over 'devtable', +but the latter is useless as it has no 'usb' device_id entry anyway. + +Tested with allmodconfig before/after patch; no changes to *.mod.c: + + git checkout v6.6-rc3 + make -j$(nproc) allmodconfig + make -j$(nproc) olddefconfig + + make -j$(nproc) + find . -name '*.mod.c' | cpio -pd /tmp/before + + # apply patch + + make -j$(nproc) + find . -name '*.mod.c' | cpio -pd /tmp/after + + diff -r /tmp/before/ /tmp/after/ + # no difference + +Fixes: acbef7b76629 ("modpost: fix module autoloading for OF devices with generic compatible property") +Signed-off-by: Mauricio Faria de Oliveira +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + scripts/mod/file2alias.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c +index 80d973144fded..111d5464c12df 100644 +--- a/scripts/mod/file2alias.c ++++ b/scripts/mod/file2alias.c +@@ -1577,7 +1577,7 @@ void handle_moddevtable(struct module *mod, struct elf_info *info, + /* First handle the "special" cases */ + if (sym_is(name, namelen, "usb")) + do_usb_table(symval, sym->st_size, mod); +- if (sym_is(name, namelen, "of")) ++ else if (sym_is(name, namelen, "of")) + do_of_table(symval, sym->st_size, mod); + else if (sym_is(name, namelen, "pnp")) + do_pnp_device_entry(symval, sym->st_size, mod); +-- +2.40.1 + diff --git a/queue-6.1/neighbour-annotate-lockless-accesses-to-n-nud_state.patch b/queue-6.1/neighbour-annotate-lockless-accesses-to-n-nud_state.patch new file mode 100644 index 00000000000..ccb110c8918 --- /dev/null +++ b/queue-6.1/neighbour-annotate-lockless-accesses-to-n-nud_state.patch @@ -0,0 +1,401 @@ +From 9b8875d07b819aa8de6894937031ef5d369ab45c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 13 Mar 2023 20:17:31 +0000 +Subject: neighbour: annotate lockless accesses to n->nud_state + +From: Eric Dumazet + +[ Upstream commit b071af523579df7341cabf0f16fc661125e9a13f ] + +We have many lockless accesses to n->nud_state. + +Before adding another one in the following patch, +add annotations to readers and writers. + +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Reviewed-by: Martin KaFai Lau +Signed-off-by: Jakub Kicinski +Stable-dep-of: 5baa0433a15e ("neighbour: fix data-races around n->output") +Signed-off-by: Sasha Levin +--- + drivers/net/vxlan/vxlan_core.c | 4 ++-- + include/net/neighbour.h | 2 +- + net/bridge/br_arp_nd_proxy.c | 4 ++-- + net/bridge/br_netfilter_hooks.c | 3 ++- + net/core/filter.c | 4 ++-- + net/core/neighbour.c | 28 ++++++++++++++-------------- + net/ipv4/arp.c | 8 ++++---- + net/ipv4/fib_semantics.c | 4 ++-- + net/ipv4/nexthop.c | 4 ++-- + net/ipv4/route.c | 2 +- + net/ipv6/ip6_output.c | 2 +- + net/ipv6/ndisc.c | 4 ++-- + net/ipv6/route.c | 2 +- + 13 files changed, 36 insertions(+), 35 deletions(-) + +diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c +index 0c3eb850fcb79..619dd71c9d75e 100644 +--- a/drivers/net/vxlan/vxlan_core.c ++++ b/drivers/net/vxlan/vxlan_core.c +@@ -1910,7 +1910,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) + struct vxlan_fdb *f; + struct sk_buff *reply; + +- if (!(n->nud_state & NUD_CONNECTED)) { ++ if (!(READ_ONCE(n->nud_state) & NUD_CONNECTED)) { + neigh_release(n); + goto out; + } +@@ -2074,7 +2074,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni) + struct vxlan_fdb *f; + struct sk_buff *reply; + +- if (!(n->nud_state & NUD_CONNECTED)) { ++ if (!(READ_ONCE(n->nud_state) & NUD_CONNECTED)) { + neigh_release(n); + goto out; + } +diff --git a/include/net/neighbour.h b/include/net/neighbour.h +index 794e45981891a..cd30aac9ec835 100644 +--- a/include/net/neighbour.h ++++ b/include/net/neighbour.h +@@ -464,7 +464,7 @@ static __always_inline int neigh_event_send_probe(struct neighbour *neigh, + + if (READ_ONCE(neigh->used) != now) + WRITE_ONCE(neigh->used, now); +- if (!(neigh->nud_state & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))) ++ if (!(READ_ONCE(neigh->nud_state) & (NUD_CONNECTED | NUD_DELAY | NUD_PROBE))) + return __neigh_event_send(neigh, skb, immediate_ok); + return 0; + } +diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c +index e5e48c6e35d78..b45c00c01dea1 100644 +--- a/net/bridge/br_arp_nd_proxy.c ++++ b/net/bridge/br_arp_nd_proxy.c +@@ -192,7 +192,7 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br, + if (n) { + struct net_bridge_fdb_entry *f; + +- if (!(n->nud_state & NUD_VALID)) { ++ if (!(READ_ONCE(n->nud_state) & NUD_VALID)) { + neigh_release(n); + return; + } +@@ -452,7 +452,7 @@ void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br, + if (n) { + struct net_bridge_fdb_entry *f; + +- if (!(n->nud_state & NUD_VALID)) { ++ if (!(READ_ONCE(n->nud_state) & NUD_VALID)) { + neigh_release(n); + return; + } +diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c +index 812bd7e1750b6..442198cb83909 100644 +--- a/net/bridge/br_netfilter_hooks.c ++++ b/net/bridge/br_netfilter_hooks.c +@@ -277,7 +277,8 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_ + struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb); + int ret; + +- if ((neigh->nud_state & NUD_CONNECTED) && neigh->hh.hh_len) { ++ if ((READ_ONCE(neigh->nud_state) & NUD_CONNECTED) && ++ READ_ONCE(neigh->hh.hh_len)) { + neigh_hh_bridge(&neigh->hh, skb); + skb->dev = nf_bridge->physindev; + ret = br_handle_frame_finish(net, sk, skb); +diff --git a/net/core/filter.c b/net/core/filter.c +index 6ef62d84dcac5..d32c6bd4d579a 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -5802,7 +5802,7 @@ static int bpf_ipv4_fib_lookup(struct net *net, struct bpf_fib_lookup *params, + else + neigh = __ipv6_neigh_lookup_noref_stub(dev, params->ipv6_dst); + +- if (!neigh || !(neigh->nud_state & NUD_VALID)) ++ if (!neigh || !(READ_ONCE(neigh->nud_state) & NUD_VALID)) + return BPF_FIB_LKUP_RET_NO_NEIGH; + memcpy(params->dmac, neigh->ha, ETH_ALEN); + memcpy(params->smac, dev->dev_addr, ETH_ALEN); +@@ -5923,7 +5923,7 @@ static int bpf_ipv6_fib_lookup(struct net *net, struct bpf_fib_lookup *params, + * not needed here. + */ + neigh = __ipv6_neigh_lookup_noref_stub(dev, dst); +- if (!neigh || !(neigh->nud_state & NUD_VALID)) ++ if (!neigh || !(READ_ONCE(neigh->nud_state) & NUD_VALID)) + return BPF_FIB_LKUP_RET_NO_NEIGH; + memcpy(params->dmac, neigh->ha, ETH_ALEN); + memcpy(params->smac, dev->dev_addr, ETH_ALEN); +diff --git a/net/core/neighbour.c b/net/core/neighbour.c +index 8e726eb0548f6..51393079487ae 100644 +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -1095,13 +1095,13 @@ static void neigh_timer_handler(struct timer_list *t) + neigh->used + + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) { + neigh_dbg(2, "neigh %p is delayed\n", neigh); +- neigh->nud_state = NUD_DELAY; ++ WRITE_ONCE(neigh->nud_state, NUD_DELAY); + neigh->updated = jiffies; + neigh_suspect(neigh); + next = now + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME); + } else { + neigh_dbg(2, "neigh %p is suspected\n", neigh); +- neigh->nud_state = NUD_STALE; ++ WRITE_ONCE(neigh->nud_state, NUD_STALE); + neigh->updated = jiffies; + neigh_suspect(neigh); + notify = 1; +@@ -1111,14 +1111,14 @@ static void neigh_timer_handler(struct timer_list *t) + neigh->confirmed + + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME))) { + neigh_dbg(2, "neigh %p is now reachable\n", neigh); +- neigh->nud_state = NUD_REACHABLE; ++ WRITE_ONCE(neigh->nud_state, NUD_REACHABLE); + neigh->updated = jiffies; + neigh_connect(neigh); + notify = 1; + next = neigh->confirmed + neigh->parms->reachable_time; + } else { + neigh_dbg(2, "neigh %p is probed\n", neigh); +- neigh->nud_state = NUD_PROBE; ++ WRITE_ONCE(neigh->nud_state, NUD_PROBE); + neigh->updated = jiffies; + atomic_set(&neigh->probes, 0); + notify = 1; +@@ -1132,7 +1132,7 @@ static void neigh_timer_handler(struct timer_list *t) + + if ((neigh->nud_state & (NUD_INCOMPLETE | NUD_PROBE)) && + atomic_read(&neigh->probes) >= neigh_max_probes(neigh)) { +- neigh->nud_state = NUD_FAILED; ++ WRITE_ONCE(neigh->nud_state, NUD_FAILED); + notify = 1; + neigh_invalidate(neigh); + goto out; +@@ -1181,7 +1181,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb, + atomic_set(&neigh->probes, + NEIGH_VAR(neigh->parms, UCAST_PROBES)); + neigh_del_timer(neigh); +- neigh->nud_state = NUD_INCOMPLETE; ++ WRITE_ONCE(neigh->nud_state, NUD_INCOMPLETE); + neigh->updated = now; + if (!immediate_ok) { + next = now + 1; +@@ -1193,7 +1193,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb, + } + neigh_add_timer(neigh, next); + } else { +- neigh->nud_state = NUD_FAILED; ++ WRITE_ONCE(neigh->nud_state, NUD_FAILED); + neigh->updated = jiffies; + write_unlock_bh(&neigh->lock); + +@@ -1203,7 +1203,7 @@ int __neigh_event_send(struct neighbour *neigh, struct sk_buff *skb, + } else if (neigh->nud_state & NUD_STALE) { + neigh_dbg(2, "neigh %p is delayed\n", neigh); + neigh_del_timer(neigh); +- neigh->nud_state = NUD_DELAY; ++ WRITE_ONCE(neigh->nud_state, NUD_DELAY); + neigh->updated = jiffies; + neigh_add_timer(neigh, jiffies + + NEIGH_VAR(neigh->parms, DELAY_PROBE_TIME)); +@@ -1315,7 +1315,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr, + neigh_update_flags(neigh, flags, ¬ify, &gc_update, &managed_update); + if (flags & (NEIGH_UPDATE_F_USE | NEIGH_UPDATE_F_MANAGED)) { + new = old & ~NUD_PERMANENT; +- neigh->nud_state = new; ++ WRITE_ONCE(neigh->nud_state, new); + err = 0; + goto out; + } +@@ -1324,7 +1324,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr, + neigh_del_timer(neigh); + if (old & NUD_CONNECTED) + neigh_suspect(neigh); +- neigh->nud_state = new; ++ WRITE_ONCE(neigh->nud_state, new); + err = 0; + notify = old & NUD_VALID; + if ((old & (NUD_INCOMPLETE | NUD_PROBE)) && +@@ -1403,7 +1403,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr, + ((new & NUD_REACHABLE) ? + neigh->parms->reachable_time : + 0))); +- neigh->nud_state = new; ++ WRITE_ONCE(neigh->nud_state, new); + notify = 1; + } + +@@ -1490,7 +1490,7 @@ void __neigh_set_probe_once(struct neighbour *neigh) + neigh->updated = jiffies; + if (!(neigh->nud_state & NUD_FAILED)) + return; +- neigh->nud_state = NUD_INCOMPLETE; ++ WRITE_ONCE(neigh->nud_state, NUD_INCOMPLETE); + atomic_set(&neigh->probes, neigh_max_probes(neigh)); + neigh_add_timer(neigh, + jiffies + max(NEIGH_VAR(neigh->parms, RETRANS_TIME), +@@ -3190,7 +3190,7 @@ static struct neighbour *neigh_get_first(struct seq_file *seq) + } + if (!(state->flags & NEIGH_SEQ_SKIP_NOARP)) + break; +- if (n->nud_state & ~NUD_NOARP) ++ if (READ_ONCE(n->nud_state) & ~NUD_NOARP) + break; + next: + n = rcu_dereference_bh(n->next); +@@ -3232,7 +3232,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq, + if (!(state->flags & NEIGH_SEQ_SKIP_NOARP)) + break; + +- if (n->nud_state & ~NUD_NOARP) ++ if (READ_ONCE(n->nud_state) & ~NUD_NOARP) + break; + next: + n = rcu_dereference_bh(n->next); +diff --git a/net/ipv4/arp.c b/net/ipv4/arp.c +index 4f7237661afb9..9456f5bb35e5d 100644 +--- a/net/ipv4/arp.c ++++ b/net/ipv4/arp.c +@@ -375,7 +375,7 @@ static void arp_solicit(struct neighbour *neigh, struct sk_buff *skb) + + probes -= NEIGH_VAR(neigh->parms, UCAST_PROBES); + if (probes < 0) { +- if (!(neigh->nud_state & NUD_VALID)) ++ if (!(READ_ONCE(neigh->nud_state) & NUD_VALID)) + pr_debug("trying to ucast probe in NUD_INVALID\n"); + neigh_ha_snapshot(dst_ha, neigh, dev); + dst_hw = dst_ha; +@@ -1123,7 +1123,7 @@ static int arp_req_get(struct arpreq *r, struct net_device *dev) + + neigh = neigh_lookup(&arp_tbl, &ip, dev); + if (neigh) { +- if (!(neigh->nud_state & NUD_NOARP)) { ++ if (!(READ_ONCE(neigh->nud_state) & NUD_NOARP)) { + read_lock_bh(&neigh->lock); + memcpy(r->arp_ha.sa_data, neigh->ha, dev->addr_len); + r->arp_flags = arp_state_to_flags(neigh); +@@ -1144,12 +1144,12 @@ int arp_invalidate(struct net_device *dev, __be32 ip, bool force) + struct neigh_table *tbl = &arp_tbl; + + if (neigh) { +- if ((neigh->nud_state & NUD_VALID) && !force) { ++ if ((READ_ONCE(neigh->nud_state) & NUD_VALID) && !force) { + neigh_release(neigh); + return 0; + } + +- if (neigh->nud_state & ~NUD_NOARP) ++ if (READ_ONCE(neigh->nud_state) & ~NUD_NOARP) + err = neigh_update(neigh, NULL, NUD_FAILED, + NEIGH_UPDATE_F_OVERRIDE| + NEIGH_UPDATE_F_ADMIN, 0); +diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c +index 3b6e6bc80dc1c..158ad3c2662f5 100644 +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -564,7 +564,7 @@ static int fib_detect_death(struct fib_info *fi, int order, + n = NULL; + + if (n) { +- state = n->nud_state; ++ state = READ_ONCE(n->nud_state); + neigh_release(n); + } else { + return 0; +@@ -2205,7 +2205,7 @@ static bool fib_good_nh(const struct fib_nh *nh) + else + n = NULL; + if (n) +- state = n->nud_state; ++ state = READ_ONCE(n->nud_state); + + rcu_read_unlock_bh(); + } +diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c +index 9cc2879024541..d699a41c9d955 100644 +--- a/net/ipv4/nexthop.c ++++ b/net/ipv4/nexthop.c +@@ -1128,7 +1128,7 @@ static bool ipv6_good_nh(const struct fib6_nh *nh) + + n = __ipv6_neigh_lookup_noref_stub(nh->fib_nh_dev, &nh->fib_nh_gw6); + if (n) +- state = n->nud_state; ++ state = READ_ONCE(n->nud_state); + + rcu_read_unlock_bh(); + +@@ -1145,7 +1145,7 @@ static bool ipv4_good_nh(const struct fib_nh *nh) + n = __ipv4_neigh_lookup_noref(nh->fib_nh_dev, + (__force u32)nh->fib_nh_gw4); + if (n) +- state = n->nud_state; ++ state = READ_ONCE(n->nud_state); + + rcu_read_unlock_bh(); + +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 84a0a71a6f4e7..8d838b0046900 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -784,7 +784,7 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow + if (!n) + n = neigh_create(&arp_tbl, &new_gw, rt->dst.dev); + if (!IS_ERR(n)) { +- if (!(n->nud_state & NUD_VALID)) { ++ if (!(READ_ONCE(n->nud_state) & NUD_VALID)) { + neigh_event_send(n, NULL); + } else { + if (fib_lookup(net, fl4, &res, 0) == 0) { +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 34192f7a166fb..5bf15a530fe73 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -1153,7 +1153,7 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk, + rcu_read_lock_bh(); + n = __ipv6_neigh_lookup_noref(rt->dst.dev, + rt6_nexthop(rt, &fl6->daddr)); +- err = n && !(n->nud_state & NUD_VALID) ? -EINVAL : 0; ++ err = n && !(READ_ONCE(n->nud_state) & NUD_VALID) ? -EINVAL : 0; + rcu_read_unlock_bh(); + + if (err) { +diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c +index 6cb2d6a536a84..8c5a99fe68030 100644 +--- a/net/ipv6/ndisc.c ++++ b/net/ipv6/ndisc.c +@@ -746,7 +746,7 @@ static void ndisc_solicit(struct neighbour *neigh, struct sk_buff *skb) + saddr = &ipv6_hdr(skb)->saddr; + probes -= NEIGH_VAR(neigh->parms, UCAST_PROBES); + if (probes < 0) { +- if (!(neigh->nud_state & NUD_VALID)) { ++ if (!(READ_ONCE(neigh->nud_state) & NUD_VALID)) { + ND_PRINTK(1, dbg, + "%s: trying to ucast probe in NUD_INVALID: %pI6\n", + __func__, target); +@@ -1092,7 +1092,7 @@ static void ndisc_recv_na(struct sk_buff *skb) + u8 old_flags = neigh->flags; + struct net *net = dev_net(dev); + +- if (neigh->nud_state & NUD_FAILED) ++ if (READ_ONCE(neigh->nud_state) & NUD_FAILED) + goto out; + + /* +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 93957b20fccce..4f103e7c4ea25 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -641,7 +641,7 @@ static void rt6_probe(struct fib6_nh *fib6_nh) + idev = __in6_dev_get(dev); + neigh = __ipv6_neigh_lookup_noref(dev, nh_gw); + if (neigh) { +- if (neigh->nud_state & NUD_VALID) ++ if (READ_ONCE(neigh->nud_state) & NUD_VALID) + goto out; + + write_lock(&neigh->lock); +-- +2.40.1 + diff --git a/queue-6.1/neighbour-fix-data-races-around-n-output.patch b/queue-6.1/neighbour-fix-data-races-around-n-output.patch new file mode 100644 index 00000000000..766350401df --- /dev/null +++ b/queue-6.1/neighbour-fix-data-races-around-n-output.patch @@ -0,0 +1,103 @@ +From 0f65c7bd482f8d2f4e15fd008e92efa287fda59c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Sep 2023 09:27:13 +0000 +Subject: neighbour: fix data-races around n->output + +From: Eric Dumazet + +[ Upstream commit 5baa0433a15eadd729625004c37463acb982eca7 ] + +n->output field can be read locklessly, while a writer +might change the pointer concurrently. + +Add missing annotations to prevent load-store tearing. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + include/net/neighbour.h | 2 +- + net/bridge/br_netfilter_hooks.c | 2 +- + net/core/neighbour.c | 10 +++++----- + 3 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/include/net/neighbour.h b/include/net/neighbour.h +index f6a8ecc6b1fa7..ccc4a0f8b4ad8 100644 +--- a/include/net/neighbour.h ++++ b/include/net/neighbour.h +@@ -541,7 +541,7 @@ static inline int neigh_output(struct neighbour *n, struct sk_buff *skb, + READ_ONCE(hh->hh_len)) + return neigh_hh_output(hh, skb); + +- return n->output(n, skb); ++ return READ_ONCE(n->output)(n, skb); + } + + static inline struct neighbour * +diff --git a/net/bridge/br_netfilter_hooks.c b/net/bridge/br_netfilter_hooks.c +index 442198cb83909..01d690d9fe5f8 100644 +--- a/net/bridge/br_netfilter_hooks.c ++++ b/net/bridge/br_netfilter_hooks.c +@@ -294,7 +294,7 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_ + /* tell br_dev_xmit to continue with forwarding */ + nf_bridge->bridged_dnat = 1; + /* FIXME Need to refragment */ +- ret = neigh->output(neigh, skb); ++ ret = READ_ONCE(neigh->output)(neigh, skb); + } + neigh_release(neigh); + return ret; +diff --git a/net/core/neighbour.c b/net/core/neighbour.c +index bafd72e5f5886..b20c9768d9f3f 100644 +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -410,7 +410,7 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev, + */ + __skb_queue_purge(&n->arp_queue); + n->arp_queue_len_bytes = 0; +- n->output = neigh_blackhole; ++ WRITE_ONCE(n->output, neigh_blackhole); + if (n->nud_state & NUD_VALID) + n->nud_state = NUD_NOARP; + else +@@ -920,7 +920,7 @@ static void neigh_suspect(struct neighbour *neigh) + { + neigh_dbg(2, "neigh %p is suspected\n", neigh); + +- neigh->output = neigh->ops->output; ++ WRITE_ONCE(neigh->output, neigh->ops->output); + } + + /* Neighbour state is OK; +@@ -932,7 +932,7 @@ static void neigh_connect(struct neighbour *neigh) + { + neigh_dbg(2, "neigh %p is connected\n", neigh); + +- neigh->output = neigh->ops->connected_output; ++ WRITE_ONCE(neigh->output, neigh->ops->connected_output); + } + + static void neigh_periodic_work(struct work_struct *work) +@@ -1449,7 +1449,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr, + if (n2) + n1 = n2; + } +- n1->output(n1, skb); ++ READ_ONCE(n1->output)(n1, skb); + if (n2) + neigh_release(n2); + rcu_read_unlock(); +@@ -3145,7 +3145,7 @@ int neigh_xmit(int index, struct net_device *dev, + rcu_read_unlock(); + goto out_kfree_skb; + } +- err = neigh->output(neigh, skb); ++ err = READ_ONCE(neigh->output)(neigh, skb); + rcu_read_unlock(); + } + else if (index == NEIGH_LINK_TABLE) { +-- +2.40.1 + diff --git a/queue-6.1/neighbour-switch-to-standard-rcu-instead-of-rcu_bh.patch b/queue-6.1/neighbour-switch-to-standard-rcu-instead-of-rcu_bh.patch new file mode 100644 index 00000000000..a91d4e89239 --- /dev/null +++ b/queue-6.1/neighbour-switch-to-standard-rcu-instead-of-rcu_bh.patch @@ -0,0 +1,690 @@ +From e92681d10e258bce6fb4e49861bbe01973b4791f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 21 Mar 2023 04:01:14 +0000 +Subject: neighbour: switch to standard rcu, instead of rcu_bh + +From: Eric Dumazet + +[ Upstream commit 09eed1192cec1755967f2af8394207acdde579a1 ] + +rcu_bh is no longer a win, especially for objects freed +with standard call_rcu(). + +Switch neighbour code to no longer disable BH when not necessary. + +Signed-off-by: Eric Dumazet +Signed-off-by: Jakub Kicinski +Stable-dep-of: 5baa0433a15e ("neighbour: fix data-races around n->output") +Signed-off-by: Sasha Levin +--- + include/net/arp.h | 8 ++--- + include/net/ndisc.h | 12 ++++---- + include/net/neighbour.h | 6 ++-- + include/net/nexthop.h | 6 ++-- + net/core/filter.c | 16 ++++++---- + net/core/neighbour.c | 64 ++++++++++++++++++++-------------------- + net/ipv4/fib_semantics.c | 4 +-- + net/ipv4/ip_output.c | 6 ++-- + net/ipv4/nexthop.c | 8 ++--- + net/ipv4/route.c | 4 +-- + net/ipv6/addrconf.c | 14 ++++----- + net/ipv6/ip6_output.c | 10 +++---- + net/ipv6/route.c | 12 ++++---- + 13 files changed, 87 insertions(+), 83 deletions(-) + +diff --git a/include/net/arp.h b/include/net/arp.h +index d7ef4ec71dfeb..e8747e0713c79 100644 +--- a/include/net/arp.h ++++ b/include/net/arp.h +@@ -38,11 +38,11 @@ static inline struct neighbour *__ipv4_neigh_lookup(struct net_device *dev, u32 + { + struct neighbour *n; + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + n = __ipv4_neigh_lookup_noref(dev, key); + if (n && !refcount_inc_not_zero(&n->refcnt)) + n = NULL; +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + + return n; + } +@@ -51,10 +51,10 @@ static inline void __ipv4_confirm_neigh(struct net_device *dev, u32 key) + { + struct neighbour *n; + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + n = __ipv4_neigh_lookup_noref(dev, key); + neigh_confirm(n); +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + } + + void arp_init(void); +diff --git a/include/net/ndisc.h b/include/net/ndisc.h +index da7eec8669ec4..325a6fb65c896 100644 +--- a/include/net/ndisc.h ++++ b/include/net/ndisc.h +@@ -395,11 +395,11 @@ static inline struct neighbour *__ipv6_neigh_lookup(struct net_device *dev, cons + { + struct neighbour *n; + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + n = __ipv6_neigh_lookup_noref(dev, pkey); + if (n && !refcount_inc_not_zero(&n->refcnt)) + n = NULL; +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + + return n; + } +@@ -409,10 +409,10 @@ static inline void __ipv6_confirm_neigh(struct net_device *dev, + { + struct neighbour *n; + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + n = __ipv6_neigh_lookup_noref(dev, pkey); + neigh_confirm(n); +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + } + + static inline void __ipv6_confirm_neigh_stub(struct net_device *dev, +@@ -420,10 +420,10 @@ static inline void __ipv6_confirm_neigh_stub(struct net_device *dev, + { + struct neighbour *n; + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + n = __ipv6_neigh_lookup_noref_stub(dev, pkey); + neigh_confirm(n); +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + } + + /* uses ipv6_stub and is meant for use outside of IPv6 core */ +diff --git a/include/net/neighbour.h b/include/net/neighbour.h +index cd30aac9ec835..f6a8ecc6b1fa7 100644 +--- a/include/net/neighbour.h ++++ b/include/net/neighbour.h +@@ -299,14 +299,14 @@ static inline struct neighbour *___neigh_lookup_noref( + const void *pkey, + struct net_device *dev) + { +- struct neigh_hash_table *nht = rcu_dereference_bh(tbl->nht); ++ struct neigh_hash_table *nht = rcu_dereference(tbl->nht); + struct neighbour *n; + u32 hash_val; + + hash_val = hash(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift); +- for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]); ++ for (n = rcu_dereference(nht->hash_buckets[hash_val]); + n != NULL; +- n = rcu_dereference_bh(n->next)) { ++ n = rcu_dereference(n->next)) { + if (n->dev == dev && key_eq(n, pkey)) + return n; + } +diff --git a/include/net/nexthop.h b/include/net/nexthop.h +index 28085b995ddcf..9fa291a046211 100644 +--- a/include/net/nexthop.h ++++ b/include/net/nexthop.h +@@ -498,7 +498,7 @@ static inline struct fib6_nh *nexthop_fib6_nh(struct nexthop *nh) + } + + /* Variant of nexthop_fib6_nh(). +- * Caller should either hold rcu_read_lock_bh(), or RTNL. ++ * Caller should either hold rcu_read_lock(), or RTNL. + */ + static inline struct fib6_nh *nexthop_fib6_nh_bh(struct nexthop *nh) + { +@@ -507,13 +507,13 @@ static inline struct fib6_nh *nexthop_fib6_nh_bh(struct nexthop *nh) + if (nh->is_group) { + struct nh_group *nh_grp; + +- nh_grp = rcu_dereference_bh_rtnl(nh->nh_grp); ++ nh_grp = rcu_dereference_rtnl(nh->nh_grp); + nh = nexthop_mpath_select(nh_grp, 0); + if (!nh) + return NULL; + } + +- nhi = rcu_dereference_bh_rtnl(nh->nh_info); ++ nhi = rcu_dereference_rtnl(nh->nh_info); + if (nhi->family == AF_INET6) + return &nhi->fib6_nh; + +diff --git a/net/core/filter.c b/net/core/filter.c +index d32c6bd4d579a..adc327f4af1e9 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -2197,7 +2197,7 @@ static int bpf_out_neigh_v6(struct net *net, struct sk_buff *skb, + return -ENOMEM; + } + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + if (!nh) { + dst = skb_dst(skb); + nexthop = rt6_nexthop(container_of(dst, struct rt6_info, dst), +@@ -2210,10 +2210,12 @@ static int bpf_out_neigh_v6(struct net *net, struct sk_buff *skb, + int ret; + + sock_confirm_neigh(skb, neigh); ++ local_bh_disable(); + dev_xmit_recursion_inc(); + ret = neigh_output(neigh, skb, false); + dev_xmit_recursion_dec(); +- rcu_read_unlock_bh(); ++ local_bh_enable(); ++ rcu_read_unlock(); + return ret; + } + rcu_read_unlock_bh(); +@@ -2295,7 +2297,7 @@ static int bpf_out_neigh_v4(struct net *net, struct sk_buff *skb, + return -ENOMEM; + } + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + if (!nh) { + struct dst_entry *dst = skb_dst(skb); + struct rtable *rt = container_of(dst, struct rtable, dst); +@@ -2307,7 +2309,7 @@ static int bpf_out_neigh_v4(struct net *net, struct sk_buff *skb, + } else if (nh->nh_family == AF_INET) { + neigh = ip_neigh_gw4(dev, nh->ipv4_nh); + } else { +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + goto out_drop; + } + +@@ -2315,13 +2317,15 @@ static int bpf_out_neigh_v4(struct net *net, struct sk_buff *skb, + int ret; + + sock_confirm_neigh(skb, neigh); ++ local_bh_disable(); + dev_xmit_recursion_inc(); + ret = neigh_output(neigh, skb, is_v6gw); + dev_xmit_recursion_dec(); +- rcu_read_unlock_bh(); ++ local_bh_enable(); ++ rcu_read_unlock(); + return ret; + } +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + out_drop: + kfree_skb(skb); + return -ENETDOWN; +diff --git a/net/core/neighbour.c b/net/core/neighbour.c +index 51393079487ae..bafd72e5f5886 100644 +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -614,7 +614,7 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, + + NEIGH_CACHE_STAT_INC(tbl, lookups); + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + n = __neigh_lookup_noref(tbl, pkey, dev); + if (n) { + if (!refcount_inc_not_zero(&n->refcnt)) +@@ -622,7 +622,7 @@ struct neighbour *neigh_lookup(struct neigh_table *tbl, const void *pkey, + NEIGH_CACHE_STAT_INC(tbl, hits); + } + +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + return n; + } + EXPORT_SYMBOL(neigh_lookup); +@@ -2176,11 +2176,11 @@ static int neightbl_fill_info(struct sk_buff *skb, struct neigh_table *tbl, + .ndtc_proxy_qlen = tbl->proxy_queue.qlen, + }; + +- rcu_read_lock_bh(); +- nht = rcu_dereference_bh(tbl->nht); ++ rcu_read_lock(); ++ nht = rcu_dereference(tbl->nht); + ndc.ndtc_hash_rnd = nht->hash_rnd[0]; + ndc.ndtc_hash_mask = ((1 << nht->hash_shift) - 1); +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + + if (nla_put(skb, NDTA_CONFIG, sizeof(ndc), &ndc)) + goto nla_put_failure; +@@ -2695,15 +2695,15 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, + if (filter->dev_idx || filter->master_idx) + flags |= NLM_F_DUMP_FILTERED; + +- rcu_read_lock_bh(); +- nht = rcu_dereference_bh(tbl->nht); ++ rcu_read_lock(); ++ nht = rcu_dereference(tbl->nht); + + for (h = s_h; h < (1 << nht->hash_shift); h++) { + if (h > s_h) + s_idx = 0; +- for (n = rcu_dereference_bh(nht->hash_buckets[h]), idx = 0; ++ for (n = rcu_dereference(nht->hash_buckets[h]), idx = 0; + n != NULL; +- n = rcu_dereference_bh(n->next)) { ++ n = rcu_dereference(n->next)) { + if (idx < s_idx || !net_eq(dev_net(n->dev), net)) + goto next; + if (neigh_ifindex_filtered(n->dev, filter->dev_idx) || +@@ -2722,7 +2722,7 @@ static int neigh_dump_table(struct neigh_table *tbl, struct sk_buff *skb, + } + rc = skb->len; + out: +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + cb->args[1] = h; + cb->args[2] = idx; + return rc; +@@ -3067,20 +3067,20 @@ void neigh_for_each(struct neigh_table *tbl, void (*cb)(struct neighbour *, void + int chain; + struct neigh_hash_table *nht; + +- rcu_read_lock_bh(); +- nht = rcu_dereference_bh(tbl->nht); ++ rcu_read_lock(); ++ nht = rcu_dereference(tbl->nht); + +- read_lock(&tbl->lock); /* avoid resizes */ ++ read_lock_bh(&tbl->lock); /* avoid resizes */ + for (chain = 0; chain < (1 << nht->hash_shift); chain++) { + struct neighbour *n; + +- for (n = rcu_dereference_bh(nht->hash_buckets[chain]); ++ for (n = rcu_dereference(nht->hash_buckets[chain]); + n != NULL; +- n = rcu_dereference_bh(n->next)) ++ n = rcu_dereference(n->next)) + cb(n, cookie); + } +- read_unlock(&tbl->lock); +- rcu_read_unlock_bh(); ++ read_unlock_bh(&tbl->lock); ++ rcu_read_unlock(); + } + EXPORT_SYMBOL(neigh_for_each); + +@@ -3130,7 +3130,7 @@ int neigh_xmit(int index, struct net_device *dev, + tbl = neigh_tables[index]; + if (!tbl) + goto out; +- rcu_read_lock_bh(); ++ rcu_read_lock(); + if (index == NEIGH_ARP_TABLE) { + u32 key = *((u32 *)addr); + +@@ -3142,11 +3142,11 @@ int neigh_xmit(int index, struct net_device *dev, + neigh = __neigh_create(tbl, addr, dev, false); + err = PTR_ERR(neigh); + if (IS_ERR(neigh)) { +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + goto out_kfree_skb; + } + err = neigh->output(neigh, skb); +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + } + else if (index == NEIGH_LINK_TABLE) { + err = dev_hard_header(skb, dev, ntohs(skb->protocol), +@@ -3175,7 +3175,7 @@ static struct neighbour *neigh_get_first(struct seq_file *seq) + + state->flags &= ~NEIGH_SEQ_IS_PNEIGH; + for (bucket = 0; bucket < (1 << nht->hash_shift); bucket++) { +- n = rcu_dereference_bh(nht->hash_buckets[bucket]); ++ n = rcu_dereference(nht->hash_buckets[bucket]); + + while (n) { + if (!net_eq(dev_net(n->dev), net)) +@@ -3193,7 +3193,7 @@ static struct neighbour *neigh_get_first(struct seq_file *seq) + if (READ_ONCE(n->nud_state) & ~NUD_NOARP) + break; + next: +- n = rcu_dereference_bh(n->next); ++ n = rcu_dereference(n->next); + } + + if (n) +@@ -3217,7 +3217,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq, + if (v) + return n; + } +- n = rcu_dereference_bh(n->next); ++ n = rcu_dereference(n->next); + + while (1) { + while (n) { +@@ -3235,7 +3235,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq, + if (READ_ONCE(n->nud_state) & ~NUD_NOARP) + break; + next: +- n = rcu_dereference_bh(n->next); ++ n = rcu_dereference(n->next); + } + + if (n) +@@ -3244,7 +3244,7 @@ static struct neighbour *neigh_get_next(struct seq_file *seq, + if (++state->bucket >= (1 << nht->hash_shift)) + break; + +- n = rcu_dereference_bh(nht->hash_buckets[state->bucket]); ++ n = rcu_dereference(nht->hash_buckets[state->bucket]); + } + + if (n && pos) +@@ -3346,7 +3346,7 @@ static void *neigh_get_idx_any(struct seq_file *seq, loff_t *pos) + + void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl, unsigned int neigh_seq_flags) + __acquires(tbl->lock) +- __acquires(rcu_bh) ++ __acquires(rcu) + { + struct neigh_seq_state *state = seq->private; + +@@ -3354,9 +3354,9 @@ void *neigh_seq_start(struct seq_file *seq, loff_t *pos, struct neigh_table *tbl + state->bucket = 0; + state->flags = (neigh_seq_flags & ~NEIGH_SEQ_IS_PNEIGH); + +- rcu_read_lock_bh(); +- state->nht = rcu_dereference_bh(tbl->nht); +- read_lock(&tbl->lock); ++ rcu_read_lock(); ++ state->nht = rcu_dereference(tbl->nht); ++ read_lock_bh(&tbl->lock); + + return *pos ? neigh_get_idx_any(seq, pos) : SEQ_START_TOKEN; + } +@@ -3391,13 +3391,13 @@ EXPORT_SYMBOL(neigh_seq_next); + + void neigh_seq_stop(struct seq_file *seq, void *v) + __releases(tbl->lock) +- __releases(rcu_bh) ++ __releases(rcu) + { + struct neigh_seq_state *state = seq->private; + struct neigh_table *tbl = state->tbl; + +- read_unlock(&tbl->lock); +- rcu_read_unlock_bh(); ++ read_unlock_bh(&tbl->lock); ++ rcu_read_unlock(); + } + EXPORT_SYMBOL(neigh_seq_stop); + +diff --git a/net/ipv4/fib_semantics.c b/net/ipv4/fib_semantics.c +index 158ad3c2662f5..eafa4a0335157 100644 +--- a/net/ipv4/fib_semantics.c ++++ b/net/ipv4/fib_semantics.c +@@ -2194,7 +2194,7 @@ static bool fib_good_nh(const struct fib_nh *nh) + if (nh->fib_nh_scope == RT_SCOPE_LINK) { + struct neighbour *n; + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + + if (likely(nh->fib_nh_gw_family == AF_INET)) + n = __ipv4_neigh_lookup_noref(nh->fib_nh_dev, +@@ -2207,7 +2207,7 @@ static bool fib_good_nh(const struct fib_nh *nh) + if (n) + state = READ_ONCE(n->nud_state); + +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + } + + return !!(state & NUD_VALID); +diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c +index 66908ce2dd116..493c679ea54f3 100644 +--- a/net/ipv4/ip_output.c ++++ b/net/ipv4/ip_output.c +@@ -218,7 +218,7 @@ static int ip_finish_output2(struct net *net, struct sock *sk, struct sk_buff *s + return res; + } + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + neigh = ip_neigh_for_gw(rt, skb, &is_v6gw); + if (!IS_ERR(neigh)) { + int res; +@@ -226,10 +226,10 @@ static int ip_finish_output2(struct net *net, struct sock *sk, struct sk_buff *s + sock_confirm_neigh(skb, neigh); + /* if crossing protocols, can not use the cached header */ + res = neigh_output(neigh, skb, is_v6gw); +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + return res; + } +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + + net_dbg_ratelimited("%s: No header cache and no neighbour!\n", + __func__); +diff --git a/net/ipv4/nexthop.c b/net/ipv4/nexthop.c +index d699a41c9d955..be5498f5dd319 100644 +--- a/net/ipv4/nexthop.c ++++ b/net/ipv4/nexthop.c +@@ -1124,13 +1124,13 @@ static bool ipv6_good_nh(const struct fib6_nh *nh) + int state = NUD_REACHABLE; + struct neighbour *n; + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + + n = __ipv6_neigh_lookup_noref_stub(nh->fib_nh_dev, &nh->fib_nh_gw6); + if (n) + state = READ_ONCE(n->nud_state); + +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + + return !!(state & NUD_VALID); + } +@@ -1140,14 +1140,14 @@ static bool ipv4_good_nh(const struct fib_nh *nh) + int state = NUD_REACHABLE; + struct neighbour *n; + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + + n = __ipv4_neigh_lookup_noref(nh->fib_nh_dev, + (__force u32)nh->fib_nh_gw4); + if (n) + state = READ_ONCE(n->nud_state); + +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + + return !!(state & NUD_VALID); + } +diff --git a/net/ipv4/route.c b/net/ipv4/route.c +index 8d838b0046900..608bd9f8dbc86 100644 +--- a/net/ipv4/route.c ++++ b/net/ipv4/route.c +@@ -408,7 +408,7 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, + struct net_device *dev = dst->dev; + struct neighbour *n; + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + + if (likely(rt->rt_gw_family == AF_INET)) { + n = ip_neigh_gw4(dev, rt->rt_gw4); +@@ -424,7 +424,7 @@ static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst, + if (!IS_ERR(n) && !refcount_inc_not_zero(&n->refcnt)) + n = NULL; + +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + + return n; + } +diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c +index 96f4351b55a6f..c63ccd39fc552 100644 +--- a/net/ipv6/addrconf.c ++++ b/net/ipv6/addrconf.c +@@ -1035,7 +1035,7 @@ static int ipv6_add_addr_hash(struct net_device *dev, struct inet6_ifaddr *ifa) + unsigned int hash = inet6_addr_hash(net, &ifa->addr); + int err = 0; + +- spin_lock(&net->ipv6.addrconf_hash_lock); ++ spin_lock_bh(&net->ipv6.addrconf_hash_lock); + + /* Ignore adding duplicate addresses on an interface */ + if (ipv6_chk_same_addr(net, &ifa->addr, dev, hash)) { +@@ -1045,7 +1045,7 @@ static int ipv6_add_addr_hash(struct net_device *dev, struct inet6_ifaddr *ifa) + hlist_add_head_rcu(&ifa->addr_lst, &net->ipv6.inet6_addr_lst[hash]); + } + +- spin_unlock(&net->ipv6.addrconf_hash_lock); ++ spin_unlock_bh(&net->ipv6.addrconf_hash_lock); + + return err; + } +@@ -1140,15 +1140,15 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg, + /* For caller */ + refcount_set(&ifa->refcnt, 1); + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + + err = ipv6_add_addr_hash(idev->dev, ifa); + if (err < 0) { +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + goto out; + } + +- write_lock(&idev->lock); ++ write_lock_bh(&idev->lock); + + /* Add to inet6_dev unicast addr list. */ + ipv6_link_dev_addr(idev, ifa); +@@ -1159,9 +1159,9 @@ ipv6_add_addr(struct inet6_dev *idev, struct ifa6_config *cfg, + } + + in6_ifa_hold(ifa); +- write_unlock(&idev->lock); ++ write_unlock_bh(&idev->lock); + +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + + inet6addr_notifier_call_chain(NETDEV_UP, ifa); + out: +diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c +index 5bf15a530fe73..ce2c5e728745f 100644 +--- a/net/ipv6/ip6_output.c ++++ b/net/ipv6/ip6_output.c +@@ -116,7 +116,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + return res; + } + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + nexthop = rt6_nexthop((struct rt6_info *)dst, daddr); + neigh = __ipv6_neigh_lookup_noref(dev, nexthop); + +@@ -124,7 +124,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + if (unlikely(!neigh)) + neigh = __neigh_create(&nd_tbl, nexthop, dev, false); + if (IS_ERR(neigh)) { +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTNOROUTES); + kfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_CREATEFAIL); + return -EINVAL; +@@ -132,7 +132,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff * + } + sock_confirm_neigh(skb, neigh); + ret = neigh_output(neigh, skb, false); +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + return ret; + } + +@@ -1150,11 +1150,11 @@ static int ip6_dst_lookup_tail(struct net *net, const struct sock *sk, + * dst entry of the nexthop router + */ + rt = (struct rt6_info *) *dst; +- rcu_read_lock_bh(); ++ rcu_read_lock(); + n = __ipv6_neigh_lookup_noref(rt->dst.dev, + rt6_nexthop(rt, &fl6->daddr)); + err = n && !(READ_ONCE(n->nud_state) & NUD_VALID) ? -EINVAL : 0; +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + + if (err) { + struct inet6_ifaddr *ifp; +diff --git a/net/ipv6/route.c b/net/ipv6/route.c +index 4f103e7c4ea25..0a9f854bfa50c 100644 +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -636,7 +636,7 @@ static void rt6_probe(struct fib6_nh *fib6_nh) + + nh_gw = &fib6_nh->fib_nh_gw6; + dev = fib6_nh->fib_nh_dev; +- rcu_read_lock_bh(); ++ rcu_read_lock(); + last_probe = READ_ONCE(fib6_nh->last_probe); + idev = __in6_dev_get(dev); + neigh = __ipv6_neigh_lookup_noref(dev, nh_gw); +@@ -644,7 +644,7 @@ static void rt6_probe(struct fib6_nh *fib6_nh) + if (READ_ONCE(neigh->nud_state) & NUD_VALID) + goto out; + +- write_lock(&neigh->lock); ++ write_lock_bh(&neigh->lock); + if (!(neigh->nud_state & NUD_VALID) && + time_after(jiffies, + neigh->updated + idev->cnf.rtr_probe_interval)) { +@@ -652,7 +652,7 @@ static void rt6_probe(struct fib6_nh *fib6_nh) + if (work) + __neigh_set_probe_once(neigh); + } +- write_unlock(&neigh->lock); ++ write_unlock_bh(&neigh->lock); + } else if (time_after(jiffies, last_probe + + idev->cnf.rtr_probe_interval)) { + work = kmalloc(sizeof(*work), GFP_ATOMIC); +@@ -670,7 +670,7 @@ static void rt6_probe(struct fib6_nh *fib6_nh) + } + + out: +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + } + #else + static inline void rt6_probe(struct fib6_nh *fib6_nh) +@@ -686,7 +686,7 @@ static enum rt6_nud_state rt6_check_neigh(const struct fib6_nh *fib6_nh) + enum rt6_nud_state ret = RT6_NUD_FAIL_HARD; + struct neighbour *neigh; + +- rcu_read_lock_bh(); ++ rcu_read_lock(); + neigh = __ipv6_neigh_lookup_noref(fib6_nh->fib_nh_dev, + &fib6_nh->fib_nh_gw6); + if (neigh) { +@@ -704,7 +704,7 @@ static enum rt6_nud_state rt6_check_neigh(const struct fib6_nh *fib6_nh) + ret = IS_ENABLED(CONFIG_IPV6_ROUTER_PREF) ? + RT6_NUD_SUCCEED : RT6_NUD_FAIL_DO_RR; + } +- rcu_read_unlock_bh(); ++ rcu_read_unlock(); + + return ret; + } +-- +2.40.1 + diff --git a/queue-6.1/net-dsa-mv88e6xxx-avoid-eeprom-timeout-when-eeprom-i.patch b/queue-6.1/net-dsa-mv88e6xxx-avoid-eeprom-timeout-when-eeprom-i.patch new file mode 100644 index 00000000000..09e368b11c3 --- /dev/null +++ b/queue-6.1/net-dsa-mv88e6xxx-avoid-eeprom-timeout-when-eeprom-i.patch @@ -0,0 +1,175 @@ +From 6d3398a194df302745f3d970983e01c4de197c96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Sep 2023 09:47:41 -0300 +Subject: net: dsa: mv88e6xxx: Avoid EEPROM timeout when EEPROM is absent + +From: Fabio Estevam + +[ Upstream commit 6ccf50d4d4741e064ba35511a95402c63bbe21a8 ] + +Since commit 23d775f12dcd ("net: dsa: mv88e6xxx: Wait for EEPROM done +before HW reset") the following error is seen on a imx8mn board with +a 88E6320 switch: + +mv88e6085 30be0000.ethernet-1:00: Timeout waiting for EEPROM done + +This board does not have an EEPROM attached to the switch though. + +This problem is well explained by Andrew Lunn: + +"If there is an EEPROM, and the EEPROM contains a lot of data, it could +be that when we perform a hardware reset towards the end of probe, it +interrupts an I2C bus transaction, leaving the I2C bus in a bad state, +and future reads of the EEPROM do not work. + +The work around for this was to poll the EEInt status and wait for it +to go true before performing the hardware reset. + +However, we have discovered that for some boards which do not have an +EEPROM, EEInt never indicates complete. As a result, +mv88e6xxx_g1_wait_eeprom_done() spins for a second and then prints a +warning. + +We probably need a different solution than calling +mv88e6xxx_g1_wait_eeprom_done(). The datasheet for 6352 documents the +EEPROM Command register: + +bit 15 is: + + EEPROM Unit Busy. This bit must be set to a one to start an EEPROM + operation (see EEOp below). Only one EEPROM operation can be + executing at one time so this bit must be zero before setting it to + a one. When the requested EEPROM operation completes this bit will + automatically be cleared to a zero. The transition of this bit from + a one to a zero can be used to generate an interrupt (the EEInt in + Global 1, offset 0x00). + +and more interesting is bit 11: + + Register Loader Running. This bit is set to one whenever the + register loader is busy executing instructions contained in the + EEPROM." + +Change to using mv88e6xxx_g2_eeprom_wait() to fix the timeout error +when the EEPROM chip is not present. + +Fixes: 23d775f12dcd ("net: dsa: mv88e6xxx: Wait for EEPROM done before HW reset") +Suggested-by: Andrew Lunn +Signed-off-by: Fabio Estevam +Reviewed-by: Florian Fainelli +Reviewed-by: Andrew Lunn +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/dsa/mv88e6xxx/chip.c | 6 ++++-- + drivers/net/dsa/mv88e6xxx/global1.c | 31 ----------------------------- + drivers/net/dsa/mv88e6xxx/global1.h | 1 - + drivers/net/dsa/mv88e6xxx/global2.c | 2 +- + drivers/net/dsa/mv88e6xxx/global2.h | 1 + + 5 files changed, 6 insertions(+), 35 deletions(-) + +diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c +index a73008b9e0b3c..ba906dfab055c 100644 +--- a/drivers/net/dsa/mv88e6xxx/chip.c ++++ b/drivers/net/dsa/mv88e6xxx/chip.c +@@ -3012,14 +3012,16 @@ static void mv88e6xxx_hardware_reset(struct mv88e6xxx_chip *chip) + * from the wrong location resulting in the switch booting + * to wrong mode and inoperable. + */ +- mv88e6xxx_g1_wait_eeprom_done(chip); ++ if (chip->info->ops->get_eeprom) ++ mv88e6xxx_g2_eeprom_wait(chip); + + gpiod_set_value_cansleep(gpiod, 1); + usleep_range(10000, 20000); + gpiod_set_value_cansleep(gpiod, 0); + usleep_range(10000, 20000); + +- mv88e6xxx_g1_wait_eeprom_done(chip); ++ if (chip->info->ops->get_eeprom) ++ mv88e6xxx_g2_eeprom_wait(chip); + } + } + +diff --git a/drivers/net/dsa/mv88e6xxx/global1.c b/drivers/net/dsa/mv88e6xxx/global1.c +index 5848112036b08..964928285782c 100644 +--- a/drivers/net/dsa/mv88e6xxx/global1.c ++++ b/drivers/net/dsa/mv88e6xxx/global1.c +@@ -75,37 +75,6 @@ static int mv88e6xxx_g1_wait_init_ready(struct mv88e6xxx_chip *chip) + return mv88e6xxx_g1_wait_bit(chip, MV88E6XXX_G1_STS, bit, 1); + } + +-void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip) +-{ +- const unsigned long timeout = jiffies + 1 * HZ; +- u16 val; +- int err; +- +- /* Wait up to 1 second for the switch to finish reading the +- * EEPROM. +- */ +- while (time_before(jiffies, timeout)) { +- err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &val); +- if (err) { +- dev_err(chip->dev, "Error reading status"); +- return; +- } +- +- /* If the switch is still resetting, it may not +- * respond on the bus, and so MDIO read returns +- * 0xffff. Differentiate between that, and waiting for +- * the EEPROM to be done by bit 0 being set. +- */ +- if (val != 0xffff && +- val & BIT(MV88E6XXX_G1_STS_IRQ_EEPROM_DONE)) +- return; +- +- usleep_range(1000, 2000); +- } +- +- dev_err(chip->dev, "Timeout waiting for EEPROM done"); +-} +- + /* Offset 0x01: Switch MAC Address Register Bytes 0 & 1 + * Offset 0x02: Switch MAC Address Register Bytes 2 & 3 + * Offset 0x03: Switch MAC Address Register Bytes 4 & 5 +diff --git a/drivers/net/dsa/mv88e6xxx/global1.h b/drivers/net/dsa/mv88e6xxx/global1.h +index 65958b2a0d3a3..04b57a21f7868 100644 +--- a/drivers/net/dsa/mv88e6xxx/global1.h ++++ b/drivers/net/dsa/mv88e6xxx/global1.h +@@ -281,7 +281,6 @@ int mv88e6xxx_g1_set_switch_mac(struct mv88e6xxx_chip *chip, u8 *addr); + int mv88e6185_g1_reset(struct mv88e6xxx_chip *chip); + int mv88e6352_g1_reset(struct mv88e6xxx_chip *chip); + int mv88e6250_g1_reset(struct mv88e6xxx_chip *chip); +-void mv88e6xxx_g1_wait_eeprom_done(struct mv88e6xxx_chip *chip); + + int mv88e6185_g1_ppu_enable(struct mv88e6xxx_chip *chip); + int mv88e6185_g1_ppu_disable(struct mv88e6xxx_chip *chip); +diff --git a/drivers/net/dsa/mv88e6xxx/global2.c b/drivers/net/dsa/mv88e6xxx/global2.c +index ec49939968fac..ac302a935ce69 100644 +--- a/drivers/net/dsa/mv88e6xxx/global2.c ++++ b/drivers/net/dsa/mv88e6xxx/global2.c +@@ -340,7 +340,7 @@ int mv88e6xxx_g2_pot_clear(struct mv88e6xxx_chip *chip) + * Offset 0x15: EEPROM Addr (for 8-bit data access) + */ + +-static int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip) ++int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip) + { + int bit = __bf_shf(MV88E6XXX_G2_EEPROM_CMD_BUSY); + int err; +diff --git a/drivers/net/dsa/mv88e6xxx/global2.h b/drivers/net/dsa/mv88e6xxx/global2.h +index c05fad5c9f19d..751a6c988de42 100644 +--- a/drivers/net/dsa/mv88e6xxx/global2.h ++++ b/drivers/net/dsa/mv88e6xxx/global2.h +@@ -359,6 +359,7 @@ int mv88e6xxx_g2_trunk_clear(struct mv88e6xxx_chip *chip); + + int mv88e6xxx_g2_device_mapping_write(struct mv88e6xxx_chip *chip, int target, + int port); ++int mv88e6xxx_g2_eeprom_wait(struct mv88e6xxx_chip *chip); + + extern const struct mv88e6xxx_irq_ops mv88e6097_watchdog_ops; + extern const struct mv88e6xxx_irq_ops mv88e6250_watchdog_ops; +-- +2.40.1 + diff --git a/queue-6.1/net-ethernet-ti-am65-cpsw-fix-error-code-in-am65_cps.patch b/queue-6.1/net-ethernet-ti-am65-cpsw-fix-error-code-in-am65_cps.patch new file mode 100644 index 00000000000..b33065cc8e3 --- /dev/null +++ b/queue-6.1/net-ethernet-ti-am65-cpsw-fix-error-code-in-am65_cps.patch @@ -0,0 +1,37 @@ +From 0b1db8e8e8d7e81aff8ee17b2ca00c6a6ee9337a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Sep 2023 17:04:43 +0300 +Subject: net: ethernet: ti: am65-cpsw: Fix error code in + am65_cpsw_nuss_init_tx_chns() + +From: Dan Carpenter + +[ Upstream commit 37d4f55567982e445f86dc0ff4ecfa72921abfe8 ] + +This accidentally returns success, but it should return a negative error +code. + +Fixes: 93a76530316a ("net: ethernet: ti: introduce am65x/j721e gigabit eth subsystem driver") +Signed-off-by: Dan Carpenter +Reviewed-by: Roger Quadros +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/ti/am65-cpsw-nuss.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c +index 25466cbdc16bd..9f2553799895d 100644 +--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c ++++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c +@@ -1614,6 +1614,7 @@ static int am65_cpsw_nuss_init_tx_chns(struct am65_cpsw_common *common) + if (tx_chn->irq <= 0) { + dev_err(dev, "Failed to get tx dma irq %d\n", + tx_chn->irq); ++ ret = tx_chn->irq ?: -ENXIO; + goto err; + } + +-- +2.40.1 + diff --git a/queue-6.1/net-fix-possible-store-tearing-in-neigh_periodic_wor.patch b/queue-6.1/net-fix-possible-store-tearing-in-neigh_periodic_wor.patch new file mode 100644 index 00000000000..11c99cd2782 --- /dev/null +++ b/queue-6.1/net-fix-possible-store-tearing-in-neigh_periodic_wor.patch @@ -0,0 +1,48 @@ +From 0d679e940ffa1b28a8c11f1742d91394726b865b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 21 Sep 2023 08:46:26 +0000 +Subject: net: fix possible store tearing in neigh_periodic_work() + +From: Eric Dumazet + +[ Upstream commit 25563b581ba3a1f263a00e8c9a97f5e7363be6fd ] + +While looking at a related syzbot report involving neigh_periodic_work(), +I found that I forgot to add an annotation when deleting an +RCU protected item from a list. + +Readers use rcu_deference(*np), we need to use either +rcu_assign_pointer() or WRITE_ONCE() on writer side +to prevent store tearing. + +I use rcu_assign_pointer() to have lockdep support, +this was the choice made in neigh_flush_dev(). + +Fixes: 767e97e1e0db ("neigh: RCU conversion of struct neighbour") +Signed-off-by: Eric Dumazet +Reviewed-by: David Ahern +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/core/neighbour.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/core/neighbour.c b/net/core/neighbour.c +index 6c0f2149f2c72..8e726eb0548f6 100644 +--- a/net/core/neighbour.c ++++ b/net/core/neighbour.c +@@ -988,7 +988,9 @@ static void neigh_periodic_work(struct work_struct *work) + (state == NUD_FAILED || + !time_in_range_open(jiffies, n->used, + n->used + NEIGH_VAR(n->parms, GC_STALETIME)))) { +- *np = n->next; ++ rcu_assign_pointer(*np, ++ rcu_dereference_protected(n->next, ++ lockdep_is_held(&tbl->lock))); + neigh_mark_dead(n); + write_unlock(&n->lock); + neigh_cleanup_and_release(n); +-- +2.40.1 + diff --git a/queue-6.1/net-nfc-llcp-add-lock-when-modifying-device-list.patch b/queue-6.1/net-nfc-llcp-add-lock-when-modifying-device-list.patch new file mode 100644 index 00000000000..f6a07a3891f --- /dev/null +++ b/queue-6.1/net-nfc-llcp-add-lock-when-modifying-device-list.patch @@ -0,0 +1,41 @@ +From c94c55104952800d08d8716d3bf95e4a1bd83e18 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Sep 2023 19:58:53 -0400 +Subject: net: nfc: llcp: Add lock when modifying device list + +From: Jeremy Cline + +[ Upstream commit dfc7f7a988dad34c3bf4c053124fb26aa6c5f916 ] + +The device list needs its associated lock held when modifying it, or the +list could become corrupted, as syzbot discovered. + +Reported-and-tested-by: syzbot+c1d0a03d305972dbbe14@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=c1d0a03d305972dbbe14 +Signed-off-by: Jeremy Cline +Reviewed-by: Simon Horman +Fixes: 6709d4b7bc2e ("net: nfc: Fix use-after-free caused by nfc_llcp_find_local") +Link: https://lore.kernel.org/r/20230908235853.1319596-1-jeremy@jcline.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/nfc/llcp_core.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c +index f60e424e06076..6705bb895e239 100644 +--- a/net/nfc/llcp_core.c ++++ b/net/nfc/llcp_core.c +@@ -1636,7 +1636,9 @@ int nfc_llcp_register_device(struct nfc_dev *ndev) + timer_setup(&local->sdreq_timer, nfc_llcp_sdreq_timer, 0); + INIT_WORK(&local->sdreq_timeout_work, nfc_llcp_sdreq_timeout_work); + ++ spin_lock(&llcp_devices_lock); + list_add(&local->list, &llcp_devices); ++ spin_unlock(&llcp_devices_lock); + + return 0; + } +-- +2.40.1 + diff --git a/queue-6.1/net-stmmac-dwmac-stm32-fix-resume-on-stm32-mcu.patch b/queue-6.1/net-stmmac-dwmac-stm32-fix-resume-on-stm32-mcu.patch new file mode 100644 index 00000000000..1434615254f --- /dev/null +++ b/queue-6.1/net-stmmac-dwmac-stm32-fix-resume-on-stm32-mcu.patch @@ -0,0 +1,68 @@ +From 11e13b9b3922e888ff2a28a9627b6a4d30215a5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Sep 2023 13:57:49 -0400 +Subject: net: stmmac: dwmac-stm32: fix resume on STM32 MCU + +From: Ben Wolsieffer + +[ Upstream commit 6f195d6b0da3b689922ba9e302af2f49592fa9fc ] + +The STM32MP1 keeps clk_rx enabled during suspend, and therefore the +driver does not enable the clock in stm32_dwmac_init() if the device was +suspended. The problem is that this same code runs on STM32 MCUs, which +do disable clk_rx during suspend, causing the clock to never be +re-enabled on resume. + +This patch adds a variant flag to indicate that clk_rx remains enabled +during suspend, and uses this to decide whether to enable the clock in +stm32_dwmac_init() if the device was suspended. + +This approach fixes this specific bug with limited opportunity for +unintended side-effects, but I have a follow up patch that will refactor +the clock configuration and hopefully make it less error prone. + +Fixes: 6528e02cc9ff ("net: ethernet: stmmac: add adaptation for stm32mp157c.") +Signed-off-by: Ben Wolsieffer +Reviewed-by: Jacob Keller +Link: https://lore.kernel.org/r/20230927175749.1419774-1-ben.wolsieffer@hefring.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c +index 2b38a499a4045..533f5245ad945 100644 +--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c ++++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c +@@ -105,6 +105,7 @@ struct stm32_ops { + int (*parse_data)(struct stm32_dwmac *dwmac, + struct device *dev); + u32 syscfg_eth_mask; ++ bool clk_rx_enable_in_suspend; + }; + + static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat) +@@ -122,7 +123,8 @@ static int stm32_dwmac_init(struct plat_stmmacenet_data *plat_dat) + if (ret) + return ret; + +- if (!dwmac->dev->power.is_suspended) { ++ if (!dwmac->ops->clk_rx_enable_in_suspend || ++ !dwmac->dev->power.is_suspended) { + ret = clk_prepare_enable(dwmac->clk_rx); + if (ret) { + clk_disable_unprepare(dwmac->clk_tx); +@@ -515,7 +517,8 @@ static struct stm32_ops stm32mp1_dwmac_data = { + .suspend = stm32mp1_suspend, + .resume = stm32mp1_resume, + .parse_data = stm32mp1_parse_data, +- .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK ++ .syscfg_eth_mask = SYSCFG_MP1_ETH_MASK, ++ .clk_rx_enable_in_suspend = true + }; + + static const struct of_device_id stm32_dwmac_match[] = { +-- +2.40.1 + diff --git a/queue-6.1/net-usb-smsc75xx-fix-uninit-value-access-in-__smsc75.patch b/queue-6.1/net-usb-smsc75xx-fix-uninit-value-access-in-__smsc75.patch new file mode 100644 index 00000000000..53723b3de22 --- /dev/null +++ b/queue-6.1/net-usb-smsc75xx-fix-uninit-value-access-in-__smsc75.patch @@ -0,0 +1,99 @@ +From c9706d8ec5f7738eb57072fc4e66c8e84fcbcdaa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 24 Sep 2023 02:35:49 +0900 +Subject: net: usb: smsc75xx: Fix uninit-value access in __smsc75xx_read_reg + +From: Shigeru Yoshida + +[ Upstream commit e9c65989920f7c28775ec4e0c11b483910fb67b8 ] + +syzbot reported the following uninit-value access issue: + +===================================================== +BUG: KMSAN: uninit-value in smsc75xx_wait_ready drivers/net/usb/smsc75xx.c:975 [inline] +BUG: KMSAN: uninit-value in smsc75xx_bind+0x5c9/0x11e0 drivers/net/usb/smsc75xx.c:1482 +CPU: 0 PID: 8696 Comm: kworker/0:3 Not tainted 5.8.0-rc5-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Workqueue: usb_hub_wq hub_event +Call Trace: + __dump_stack lib/dump_stack.c:77 [inline] + dump_stack+0x21c/0x280 lib/dump_stack.c:118 + kmsan_report+0xf7/0x1e0 mm/kmsan/kmsan_report.c:121 + __msan_warning+0x58/0xa0 mm/kmsan/kmsan_instr.c:215 + smsc75xx_wait_ready drivers/net/usb/smsc75xx.c:975 [inline] + smsc75xx_bind+0x5c9/0x11e0 drivers/net/usb/smsc75xx.c:1482 + usbnet_probe+0x1152/0x3f90 drivers/net/usb/usbnet.c:1737 + usb_probe_interface+0xece/0x1550 drivers/usb/core/driver.c:374 + really_probe+0xf20/0x20b0 drivers/base/dd.c:529 + driver_probe_device+0x293/0x390 drivers/base/dd.c:701 + __device_attach_driver+0x63f/0x830 drivers/base/dd.c:807 + bus_for_each_drv+0x2ca/0x3f0 drivers/base/bus.c:431 + __device_attach+0x4e2/0x7f0 drivers/base/dd.c:873 + device_initial_probe+0x4a/0x60 drivers/base/dd.c:920 + bus_probe_device+0x177/0x3d0 drivers/base/bus.c:491 + device_add+0x3b0e/0x40d0 drivers/base/core.c:2680 + usb_set_configuration+0x380f/0x3f10 drivers/usb/core/message.c:2032 + usb_generic_driver_probe+0x138/0x300 drivers/usb/core/generic.c:241 + usb_probe_device+0x311/0x490 drivers/usb/core/driver.c:272 + really_probe+0xf20/0x20b0 drivers/base/dd.c:529 + driver_probe_device+0x293/0x390 drivers/base/dd.c:701 + __device_attach_driver+0x63f/0x830 drivers/base/dd.c:807 + bus_for_each_drv+0x2ca/0x3f0 drivers/base/bus.c:431 + __device_attach+0x4e2/0x7f0 drivers/base/dd.c:873 + device_initial_probe+0x4a/0x60 drivers/base/dd.c:920 + bus_probe_device+0x177/0x3d0 drivers/base/bus.c:491 + device_add+0x3b0e/0x40d0 drivers/base/core.c:2680 + usb_new_device+0x1bd4/0x2a30 drivers/usb/core/hub.c:2554 + hub_port_connect drivers/usb/core/hub.c:5208 [inline] + hub_port_connect_change drivers/usb/core/hub.c:5348 [inline] + port_event drivers/usb/core/hub.c:5494 [inline] + hub_event+0x5e7b/0x8a70 drivers/usb/core/hub.c:5576 + process_one_work+0x1688/0x2140 kernel/workqueue.c:2269 + worker_thread+0x10bc/0x2730 kernel/workqueue.c:2415 + kthread+0x551/0x590 kernel/kthread.c:292 + ret_from_fork+0x1f/0x30 arch/x86/entry/entry_64.S:293 + +Local variable ----buf.i87@smsc75xx_bind created at: + __smsc75xx_read_reg drivers/net/usb/smsc75xx.c:83 [inline] + smsc75xx_wait_ready drivers/net/usb/smsc75xx.c:968 [inline] + smsc75xx_bind+0x485/0x11e0 drivers/net/usb/smsc75xx.c:1482 + __smsc75xx_read_reg drivers/net/usb/smsc75xx.c:83 [inline] + smsc75xx_wait_ready drivers/net/usb/smsc75xx.c:968 [inline] + smsc75xx_bind+0x485/0x11e0 drivers/net/usb/smsc75xx.c:1482 + +This issue is caused because usbnet_read_cmd() reads less bytes than requested +(zero byte in the reproducer). In this case, 'buf' is not properly filled. + +This patch fixes the issue by returning -ENODATA if usbnet_read_cmd() reads +less bytes than requested. + +Fixes: d0cad871703b ("smsc75xx: SMSC LAN75xx USB gigabit ethernet adapter driver") +Reported-and-tested-by: syzbot+6966546b78d050bb0b5d@syzkaller.appspotmail.com +Closes: https://syzkaller.appspot.com/bug?extid=6966546b78d050bb0b5d +Signed-off-by: Shigeru Yoshida +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/20230923173549.3284502-1-syoshida@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + drivers/net/usb/smsc75xx.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/usb/smsc75xx.c b/drivers/net/usb/smsc75xx.c +index 5d6454fedb3f1..78ad2da3ee29b 100644 +--- a/drivers/net/usb/smsc75xx.c ++++ b/drivers/net/usb/smsc75xx.c +@@ -90,7 +90,9 @@ static int __must_check __smsc75xx_read_reg(struct usbnet *dev, u32 index, + ret = fn(dev, USB_VENDOR_REQUEST_READ_REGISTER, USB_DIR_IN + | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + 0, index, &buf, 4); +- if (unlikely(ret < 0)) { ++ if (unlikely(ret < 4)) { ++ ret = ret < 0 ? ret : -ENODATA; ++ + netdev_warn(dev->net, "Failed to read reg index 0x%08x: %d\n", + index, ret); + return ret; +-- +2.40.1 + diff --git a/queue-6.1/netfilter-handle-the-connecting-collision-properly-i.patch b/queue-6.1/netfilter-handle-the-connecting-collision-properly-i.patch new file mode 100644 index 00000000000..6d9a2965018 --- /dev/null +++ b/queue-6.1/netfilter-handle-the-connecting-collision-properly-i.patch @@ -0,0 +1,175 @@ +From 4db39a9e3efc34bf9425d59a5916296d87aac754 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Oct 2023 13:17:53 -0400 +Subject: netfilter: handle the connecting collision properly in + nf_conntrack_proto_sctp + +From: Xin Long + +[ Upstream commit 8e56b063c86569e51eed1c5681ce6361fa97fc7a ] + +In Scenario A and B below, as the delayed INIT_ACK always changes the peer +vtag, SCTP ct with the incorrect vtag may cause packet loss. + +Scenario A: INIT_ACK is delayed until the peer receives its own INIT_ACK + + 192.168.1.2 > 192.168.1.1: [INIT] [init tag: 1328086772] + 192.168.1.1 > 192.168.1.2: [INIT] [init tag: 1414468151] + 192.168.1.2 > 192.168.1.1: [INIT ACK] [init tag: 1328086772] + 192.168.1.1 > 192.168.1.2: [INIT ACK] [init tag: 1650211246] * + 192.168.1.2 > 192.168.1.1: [COOKIE ECHO] + 192.168.1.1 > 192.168.1.2: [COOKIE ECHO] + 192.168.1.2 > 192.168.1.1: [COOKIE ACK] + +Scenario B: INIT_ACK is delayed until the peer completes its own handshake + + 192.168.1.2 > 192.168.1.1: sctp (1) [INIT] [init tag: 3922216408] + 192.168.1.1 > 192.168.1.2: sctp (1) [INIT] [init tag: 144230885] + 192.168.1.2 > 192.168.1.1: sctp (1) [INIT ACK] [init tag: 3922216408] + 192.168.1.1 > 192.168.1.2: sctp (1) [COOKIE ECHO] + 192.168.1.2 > 192.168.1.1: sctp (1) [COOKIE ACK] + 192.168.1.1 > 192.168.1.2: sctp (1) [INIT ACK] [init tag: 3914796021] * + +This patch fixes it as below: + +In SCTP_CID_INIT processing: +- clear ct->proto.sctp.init[!dir] if ct->proto.sctp.init[dir] && + ct->proto.sctp.init[!dir]. (Scenario E) +- set ct->proto.sctp.init[dir]. + +In SCTP_CID_INIT_ACK processing: +- drop it if !ct->proto.sctp.init[!dir] && ct->proto.sctp.vtag[!dir] && + ct->proto.sctp.vtag[!dir] != ih->init_tag. (Scenario B, Scenario C) +- drop it if ct->proto.sctp.init[dir] && ct->proto.sctp.init[!dir] && + ct->proto.sctp.vtag[!dir] != ih->init_tag. (Scenario A) + +In SCTP_CID_COOKIE_ACK processing: +- clear ct->proto.sctp.init[dir] and ct->proto.sctp.init[!dir]. + (Scenario D) + +Also, it's important to allow the ct state to move forward with cookie_echo +and cookie_ack from the opposite dir for the collision scenarios. + +There are also other Scenarios where it should allow the packet through, +addressed by the processing above: + +Scenario C: new CT is created by INIT_ACK. + +Scenario D: start INIT on the existing ESTABLISHED ct. + +Scenario E: start INIT after the old collision on the existing ESTABLISHED +ct. + + 192.168.1.2 > 192.168.1.1: sctp (1) [INIT] [init tag: 3922216408] + 192.168.1.1 > 192.168.1.2: sctp (1) [INIT] [init tag: 144230885] + (both side are stopped, then start new connection again in hours) + 192.168.1.2 > 192.168.1.1: sctp (1) [INIT] [init tag: 242308742] + +Fixes: 9fb9cbb1082d ("[NETFILTER]: Add nf_conntrack subsystem.") +Signed-off-by: Xin Long +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + include/linux/netfilter/nf_conntrack_sctp.h | 1 + + net/netfilter/nf_conntrack_proto_sctp.c | 43 ++++++++++++++++----- + 2 files changed, 34 insertions(+), 10 deletions(-) + +diff --git a/include/linux/netfilter/nf_conntrack_sctp.h b/include/linux/netfilter/nf_conntrack_sctp.h +index 625f491b95de8..fb31312825ae5 100644 +--- a/include/linux/netfilter/nf_conntrack_sctp.h ++++ b/include/linux/netfilter/nf_conntrack_sctp.h +@@ -9,6 +9,7 @@ struct ip_ct_sctp { + enum sctp_conntrack state; + + __be32 vtag[IP_CT_DIR_MAX]; ++ u8 init[IP_CT_DIR_MAX]; + u8 last_dir; + u8 flags; + }; +diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c +index 7247af51bdfc4..c94a9971d790c 100644 +--- a/net/netfilter/nf_conntrack_proto_sctp.c ++++ b/net/netfilter/nf_conntrack_proto_sctp.c +@@ -112,7 +112,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { + /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA, sSA}, + /* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't have Stale cookie*/ + /* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA, sCL},/* 5.2.4 - Big TODO */ +-/* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sCL},/* Can't come in orig dir */ ++/* cookie_ack */ {sCL, sCL, sCW, sES, sES, sSS, sSR, sSA, sCL},/* Can't come in orig dir */ + /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL, sCL}, + /* heartbeat */ {sHS, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, + /* heartbeat_ack*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, +@@ -126,7 +126,7 @@ static const u8 sctp_conntracks[2][11][SCTP_CONNTRACK_MAX] = { + /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA, sIV}, + /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA, sIV}, + /* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA, sIV}, +-/* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sIV},/* Can't come in reply dir */ ++/* cookie_echo */ {sIV, sCL, sCE, sCE, sES, sSS, sSR, sSA, sIV},/* Can't come in reply dir */ + /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA, sIV}, + /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL, sIV}, + /* heartbeat */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA, sHS}, +@@ -426,6 +426,9 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, + /* (D) vtag must be same as init_vtag as found in INIT_ACK */ + if (sh->vtag != ct->proto.sctp.vtag[dir]) + goto out_unlock; ++ } else if (sch->type == SCTP_CID_COOKIE_ACK) { ++ ct->proto.sctp.init[dir] = 0; ++ ct->proto.sctp.init[!dir] = 0; + } else if (sch->type == SCTP_CID_HEARTBEAT) { + if (ct->proto.sctp.vtag[dir] == 0) { + pr_debug("Setting %d vtag %x for dir %d\n", sch->type, sh->vtag, dir); +@@ -474,16 +477,18 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, + } + + /* If it is an INIT or an INIT ACK note down the vtag */ +- if (sch->type == SCTP_CID_INIT || +- sch->type == SCTP_CID_INIT_ACK) { +- struct sctp_inithdr _inithdr, *ih; ++ if (sch->type == SCTP_CID_INIT) { ++ struct sctp_inithdr _ih, *ih; + +- ih = skb_header_pointer(skb, offset + sizeof(_sch), +- sizeof(_inithdr), &_inithdr); +- if (ih == NULL) ++ ih = skb_header_pointer(skb, offset + sizeof(_sch), sizeof(*ih), &_ih); ++ if (!ih) + goto out_unlock; +- pr_debug("Setting vtag %x for dir %d\n", +- ih->init_tag, !dir); ++ ++ if (ct->proto.sctp.init[dir] && ct->proto.sctp.init[!dir]) ++ ct->proto.sctp.init[!dir] = 0; ++ ct->proto.sctp.init[dir] = 1; ++ ++ pr_debug("Setting vtag %x for dir %d\n", ih->init_tag, !dir); + ct->proto.sctp.vtag[!dir] = ih->init_tag; + + /* don't renew timeout on init retransmit so +@@ -494,6 +499,24 @@ int nf_conntrack_sctp_packet(struct nf_conn *ct, + old_state == SCTP_CONNTRACK_CLOSED && + nf_ct_is_confirmed(ct)) + ignore = true; ++ } else if (sch->type == SCTP_CID_INIT_ACK) { ++ struct sctp_inithdr _ih, *ih; ++ __be32 vtag; ++ ++ ih = skb_header_pointer(skb, offset + sizeof(_sch), sizeof(*ih), &_ih); ++ if (!ih) ++ goto out_unlock; ++ ++ vtag = ct->proto.sctp.vtag[!dir]; ++ if (!ct->proto.sctp.init[!dir] && vtag && vtag != ih->init_tag) ++ goto out_unlock; ++ /* collision */ ++ if (ct->proto.sctp.init[dir] && ct->proto.sctp.init[!dir] && ++ vtag != ih->init_tag) ++ goto out_unlock; ++ ++ pr_debug("Setting vtag %x for dir %d\n", ih->init_tag, !dir); ++ ct->proto.sctp.vtag[!dir] = ih->init_tag; + } + + ct->proto.sctp.state = new_state; +-- +2.40.1 + diff --git a/queue-6.1/netfilter-nf_tables-deduplicate-nft_register_obj-aud.patch b/queue-6.1/netfilter-nf_tables-deduplicate-nft_register_obj-aud.patch new file mode 100644 index 00000000000..2c0c1d53484 --- /dev/null +++ b/queue-6.1/netfilter-nf_tables-deduplicate-nft_register_obj-aud.patch @@ -0,0 +1,130 @@ +From 18649677d56eedac0a6ff0a613021184fb121338 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Sep 2023 03:53:50 +0200 +Subject: netfilter: nf_tables: Deduplicate nft_register_obj audit logs + +From: Phil Sutter + +[ Upstream commit 0d880dc6f032e0b541520e9926f398a77d3d433c ] + +When adding/updating an object, the transaction handler emits suitable +audit log entries already, the one in nft_obj_notify() is redundant. To +fix that (and retain the audit logging from objects' 'update' callback), +Introduce an "audit log free" variant for internal use. + +Fixes: c520292f29b8 ("audit: log nftables configuration change events once per table") +Signed-off-by: Phil Sutter +Reviewed-by: Richard Guy Briggs +Acked-by: Paul Moore (Audit) +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nf_tables_api.c | 44 ++++++++++++------- + .../testing/selftests/netfilter/nft_audit.sh | 20 +++++++++ + 2 files changed, 48 insertions(+), 16 deletions(-) + +diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c +index 52b81dc1fcf5b..5e3dbe2652dbd 100644 +--- a/net/netfilter/nf_tables_api.c ++++ b/net/netfilter/nf_tables_api.c +@@ -7576,24 +7576,14 @@ static int nf_tables_delobj(struct sk_buff *skb, const struct nfnl_info *info, + return nft_delobj(&ctx, obj); + } + +-void nft_obj_notify(struct net *net, const struct nft_table *table, +- struct nft_object *obj, u32 portid, u32 seq, int event, +- u16 flags, int family, int report, gfp_t gfp) ++static void ++__nft_obj_notify(struct net *net, const struct nft_table *table, ++ struct nft_object *obj, u32 portid, u32 seq, int event, ++ u16 flags, int family, int report, gfp_t gfp) + { + struct nftables_pernet *nft_net = nft_pernet(net); + struct sk_buff *skb; + int err; +- char *buf = kasprintf(gfp, "%s:%u", +- table->name, nft_net->base_seq); +- +- audit_log_nfcfg(buf, +- family, +- obj->handle, +- event == NFT_MSG_NEWOBJ ? +- AUDIT_NFT_OP_OBJ_REGISTER : +- AUDIT_NFT_OP_OBJ_UNREGISTER, +- gfp); +- kfree(buf); + + if (!report && + !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES)) +@@ -7616,13 +7606,35 @@ void nft_obj_notify(struct net *net, const struct nft_table *table, + err: + nfnetlink_set_err(net, portid, NFNLGRP_NFTABLES, -ENOBUFS); + } ++ ++void nft_obj_notify(struct net *net, const struct nft_table *table, ++ struct nft_object *obj, u32 portid, u32 seq, int event, ++ u16 flags, int family, int report, gfp_t gfp) ++{ ++ struct nftables_pernet *nft_net = nft_pernet(net); ++ char *buf = kasprintf(gfp, "%s:%u", ++ table->name, nft_net->base_seq); ++ ++ audit_log_nfcfg(buf, ++ family, ++ obj->handle, ++ event == NFT_MSG_NEWOBJ ? ++ AUDIT_NFT_OP_OBJ_REGISTER : ++ AUDIT_NFT_OP_OBJ_UNREGISTER, ++ gfp); ++ kfree(buf); ++ ++ __nft_obj_notify(net, table, obj, portid, seq, event, ++ flags, family, report, gfp); ++} + EXPORT_SYMBOL_GPL(nft_obj_notify); + + static void nf_tables_obj_notify(const struct nft_ctx *ctx, + struct nft_object *obj, int event) + { +- nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ctx->seq, event, +- ctx->flags, ctx->family, ctx->report, GFP_KERNEL); ++ __nft_obj_notify(ctx->net, ctx->table, obj, ctx->portid, ++ ctx->seq, event, ctx->flags, ctx->family, ++ ctx->report, GFP_KERNEL); + } + + /* +diff --git a/tools/testing/selftests/netfilter/nft_audit.sh b/tools/testing/selftests/netfilter/nft_audit.sh +index 0b3255e7b3538..bb34329e02a7f 100755 +--- a/tools/testing/selftests/netfilter/nft_audit.sh ++++ b/tools/testing/selftests/netfilter/nft_audit.sh +@@ -85,6 +85,26 @@ do_test "nft add set t1 s2 $setblock; add set t1 s3 { $settype; }" \ + do_test "nft add element t1 s3 $setelem" \ + "table=t1 family=2 entries=3 op=nft_register_setelem" + ++# adding counters ++ ++do_test 'nft add counter t1 c1' \ ++'table=t1 family=2 entries=1 op=nft_register_obj' ++ ++do_test 'nft add counter t2 c1; add counter t2 c2' \ ++'table=t2 family=2 entries=2 op=nft_register_obj' ++ ++# adding/updating quotas ++ ++do_test 'nft add quota t1 q1 { 10 bytes }' \ ++'table=t1 family=2 entries=1 op=nft_register_obj' ++ ++do_test 'nft add quota t2 q1 { 10 bytes }; add quota t2 q2 { 10 bytes }' \ ++'table=t2 family=2 entries=2 op=nft_register_obj' ++ ++# changing the quota value triggers obj update path ++do_test 'nft add quota t1 q1 { 20 bytes }' \ ++'table=t1 family=2 entries=1 op=nft_register_obj' ++ + # resetting rules + + do_test 'nft reset rules t1 c2' \ +-- +2.40.1 + diff --git a/queue-6.1/netfilter-nf_tables-nft_set_rbtree-fix-spurious-inse.patch b/queue-6.1/netfilter-nf_tables-nft_set_rbtree-fix-spurious-inse.patch new file mode 100644 index 00000000000..4dea526f51e --- /dev/null +++ b/queue-6.1/netfilter-nf_tables-nft_set_rbtree-fix-spurious-inse.patch @@ -0,0 +1,181 @@ +From 57cb886580900aa6b0868338d4bb75abcd81cd51 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Sep 2023 15:12:44 +0200 +Subject: netfilter: nf_tables: nft_set_rbtree: fix spurious insertion failure + +From: Florian Westphal + +[ Upstream commit 087388278e0f301f4c61ddffb1911d3a180f84b8 ] + +nft_rbtree_gc_elem() walks back and removes the end interval element that +comes before the expired element. + +There is a small chance that we've cached this element as 'rbe_ge'. +If this happens, we hold and test a pointer that has been queued for +freeing. + +It also causes spurious insertion failures: + +$ cat test-testcases-sets-0044interval_overlap_0.1/testout.log +Error: Could not process rule: File exists +add element t s { 0 - 2 } + ^^^^^^ +Failed to insert 0 - 2 given: +table ip t { + set s { + type inet_service + flags interval,timeout + timeout 2s + gc-interval 2s + } +} + +The set (rbtree) is empty. The 'failure' doesn't happen on next attempt. + +Reason is that when we try to insert, the tree may hold an expired +element that collides with the range we're adding. +While we do evict/erase this element, we can trip over this check: + +if (rbe_ge && nft_rbtree_interval_end(rbe_ge) && nft_rbtree_interval_end(new)) + return -ENOTEMPTY; + +rbe_ge was erased by the synchronous gc, we should not have done this +check. Next attempt won't find it, so retry results in successful +insertion. + +Restart in-kernel to avoid such spurious errors. + +Such restart are rare, unless userspace intentionally adds very large +numbers of elements with very short timeouts while setting a huge +gc interval. + +Even in this case, this cannot loop forever, on each retry an existing +element has been removed. + +As the caller is holding the transaction mutex, its impossible +for a second entity to add more expiring elements to the tree. + +After this it also becomes feasible to remove the async gc worker +and perform all garbage collection from the commit path. + +Fixes: c9e6978e2725 ("netfilter: nft_set_rbtree: Switch to node list walk for overlap detection") +Signed-off-by: Florian Westphal +Signed-off-by: Sasha Levin +--- + net/netfilter/nft_set_rbtree.c | 46 +++++++++++++++++++++------------- + 1 file changed, 29 insertions(+), 17 deletions(-) + +diff --git a/net/netfilter/nft_set_rbtree.c b/net/netfilter/nft_set_rbtree.c +index 487572dcd6144..2660ceab3759d 100644 +--- a/net/netfilter/nft_set_rbtree.c ++++ b/net/netfilter/nft_set_rbtree.c +@@ -233,10 +233,9 @@ static void nft_rbtree_gc_remove(struct net *net, struct nft_set *set, + rb_erase(&rbe->node, &priv->root); + } + +-static int nft_rbtree_gc_elem(const struct nft_set *__set, +- struct nft_rbtree *priv, +- struct nft_rbtree_elem *rbe, +- u8 genmask) ++static const struct nft_rbtree_elem * ++nft_rbtree_gc_elem(const struct nft_set *__set, struct nft_rbtree *priv, ++ struct nft_rbtree_elem *rbe, u8 genmask) + { + struct nft_set *set = (struct nft_set *)__set; + struct rb_node *prev = rb_prev(&rbe->node); +@@ -246,7 +245,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, + + gc = nft_trans_gc_alloc(set, 0, GFP_ATOMIC); + if (!gc) +- return -ENOMEM; ++ return ERR_PTR(-ENOMEM); + + /* search for end interval coming before this element. + * end intervals don't carry a timeout extension, they +@@ -261,6 +260,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, + prev = rb_prev(prev); + } + ++ rbe_prev = NULL; + if (prev) { + rbe_prev = rb_entry(prev, struct nft_rbtree_elem, node); + nft_rbtree_gc_remove(net, set, priv, rbe_prev); +@@ -272,7 +272,7 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, + */ + gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); + if (WARN_ON_ONCE(!gc)) +- return -ENOMEM; ++ return ERR_PTR(-ENOMEM); + + nft_trans_gc_elem_add(gc, rbe_prev); + } +@@ -280,13 +280,13 @@ static int nft_rbtree_gc_elem(const struct nft_set *__set, + nft_rbtree_gc_remove(net, set, priv, rbe); + gc = nft_trans_gc_queue_sync(gc, GFP_ATOMIC); + if (WARN_ON_ONCE(!gc)) +- return -ENOMEM; ++ return ERR_PTR(-ENOMEM); + + nft_trans_gc_elem_add(gc, rbe); + + nft_trans_gc_queue_sync_done(gc); + +- return 0; ++ return rbe_prev; + } + + static bool nft_rbtree_update_first(const struct nft_set *set, +@@ -314,7 +314,7 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, + struct nft_rbtree *priv = nft_set_priv(set); + u8 cur_genmask = nft_genmask_cur(net); + u8 genmask = nft_genmask_next(net); +- int d, err; ++ int d; + + /* Descend the tree to search for an existing element greater than the + * key value to insert that is greater than the new element. This is the +@@ -363,9 +363,14 @@ static int __nft_rbtree_insert(const struct net *net, const struct nft_set *set, + */ + if (nft_set_elem_expired(&rbe->ext) && + nft_set_elem_active(&rbe->ext, cur_genmask)) { +- err = nft_rbtree_gc_elem(set, priv, rbe, genmask); +- if (err < 0) +- return err; ++ const struct nft_rbtree_elem *removed_end; ++ ++ removed_end = nft_rbtree_gc_elem(set, priv, rbe, genmask); ++ if (IS_ERR(removed_end)) ++ return PTR_ERR(removed_end); ++ ++ if (removed_end == rbe_le || removed_end == rbe_ge) ++ return -EAGAIN; + + continue; + } +@@ -486,11 +491,18 @@ static int nft_rbtree_insert(const struct net *net, const struct nft_set *set, + struct nft_rbtree_elem *rbe = elem->priv; + int err; + +- write_lock_bh(&priv->lock); +- write_seqcount_begin(&priv->count); +- err = __nft_rbtree_insert(net, set, rbe, ext); +- write_seqcount_end(&priv->count); +- write_unlock_bh(&priv->lock); ++ do { ++ if (fatal_signal_pending(current)) ++ return -EINTR; ++ ++ cond_resched(); ++ ++ write_lock_bh(&priv->lock); ++ write_seqcount_begin(&priv->count); ++ err = __nft_rbtree_insert(net, set, rbe, ext); ++ write_seqcount_end(&priv->count); ++ write_unlock_bh(&priv->lock); ++ } while (err == -EAGAIN); + + return err; + } +-- +2.40.1 + diff --git a/queue-6.1/netlink-annotate-data-races-around-sk-sk_err.patch b/queue-6.1/netlink-annotate-data-races-around-sk-sk_err.patch new file mode 100644 index 00000000000..3da415ce715 --- /dev/null +++ b/queue-6.1/netlink-annotate-data-races-around-sk-sk_err.patch @@ -0,0 +1,100 @@ +From ccc9fcf0536a18f4679be52a36b25bb85466f5db Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 3 Oct 2023 18:34:55 +0000 +Subject: netlink: annotate data-races around sk->sk_err + +From: Eric Dumazet + +[ Upstream commit d0f95894fda7d4f895b29c1097f92d7fee278cb2 ] + +syzbot caught another data-race in netlink when +setting sk->sk_err. + +Annotate all of them for good measure. + +BUG: KCSAN: data-race in netlink_recvmsg / netlink_recvmsg + +write to 0xffff8881613bb220 of 4 bytes by task 28147 on cpu 0: +netlink_recvmsg+0x448/0x780 net/netlink/af_netlink.c:1994 +sock_recvmsg_nosec net/socket.c:1027 [inline] +sock_recvmsg net/socket.c:1049 [inline] +__sys_recvfrom+0x1f4/0x2e0 net/socket.c:2229 +__do_sys_recvfrom net/socket.c:2247 [inline] +__se_sys_recvfrom net/socket.c:2243 [inline] +__x64_sys_recvfrom+0x78/0x90 net/socket.c:2243 +do_syscall_x64 arch/x86/entry/common.c:50 [inline] +do_syscall_64+0x41/0xc0 arch/x86/entry/common.c:80 +entry_SYSCALL_64_after_hwframe+0x63/0xcd + +write to 0xffff8881613bb220 of 4 bytes by task 28146 on cpu 1: +netlink_recvmsg+0x448/0x780 net/netlink/af_netlink.c:1994 +sock_recvmsg_nosec net/socket.c:1027 [inline] +sock_recvmsg net/socket.c:1049 [inline] +__sys_recvfrom+0x1f4/0x2e0 net/socket.c:2229 +__do_sys_recvfrom net/socket.c:2247 [inline] +__se_sys_recvfrom net/socket.c:2243 [inline] +__x64_sys_recvfrom+0x78/0x90 net/socket.c:2243 +do_syscall_x64 arch/x86/entry/common.c:50 [inline] +do_syscall_64+0x41/0xc0 arch/x86/entry/common.c:80 +entry_SYSCALL_64_after_hwframe+0x63/0xcd + +value changed: 0x00000000 -> 0x00000016 + +Reported by Kernel Concurrency Sanitizer on: +CPU: 1 PID: 28146 Comm: syz-executor.0 Not tainted 6.6.0-rc3-syzkaller-00055-g9ed22ae6be81 #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/06/2023 + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Eric Dumazet +Reported-by: syzbot +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/20231003183455.3410550-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/netlink/af_netlink.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 845ac56a3ac2e..a572a30dfd98d 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -352,7 +352,7 @@ static void netlink_overrun(struct sock *sk) + if (!nlk_test_bit(RECV_NO_ENOBUFS, sk)) { + if (!test_and_set_bit(NETLINK_S_CONGESTED, + &nlk_sk(sk)->state)) { +- sk->sk_err = ENOBUFS; ++ WRITE_ONCE(sk->sk_err, ENOBUFS); + sk_error_report(sk); + } + } +@@ -1566,7 +1566,7 @@ static int do_one_set_err(struct sock *sk, struct netlink_set_err_data *p) + goto out; + } + +- sk->sk_err = p->code; ++ WRITE_ONCE(sk->sk_err, p->code); + sk_error_report(sk); + out: + return ret; +@@ -1955,7 +1955,7 @@ static int netlink_recvmsg(struct socket *sock, struct msghdr *msg, size_t len, + atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) { + ret = netlink_dump(sk); + if (ret) { +- sk->sk_err = -ret; ++ WRITE_ONCE(sk->sk_err, -ret); + sk_error_report(sk); + } + } +@@ -2474,7 +2474,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err, + err_bad_put: + nlmsg_free(skb); + err_skb: +- NETLINK_CB(in_skb).sk->sk_err = ENOBUFS; ++ WRITE_ONCE(NETLINK_CB(in_skb).sk->sk_err, ENOBUFS); + sk_error_report(NETLINK_CB(in_skb).sk); + } + EXPORT_SYMBOL(netlink_ack); +-- +2.40.1 + diff --git a/queue-6.1/netlink-fix-potential-skb-memleak-in-netlink_ack.patch b/queue-6.1/netlink-fix-potential-skb-memleak-in-netlink_ack.patch new file mode 100644 index 00000000000..04d4bd06d91 --- /dev/null +++ b/queue-6.1/netlink-fix-potential-skb-memleak-in-netlink_ack.patch @@ -0,0 +1,48 @@ +From d5d1c6bac9529e2e1b91f9a603e2a0cffe6dca9b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 5 Nov 2022 17:05:04 +0800 +Subject: netlink: Fix potential skb memleak in netlink_ack + +From: Tao Chen + +[ Upstream commit e69761483361f3df455bc493c99af0ef1744a14f ] + +Fix coverity issue 'Resource leak'. + +We should clean the skb resource if nlmsg_put/append failed. + +Fixes: 738136a0e375 ("netlink: split up copies in the ack construction") +Signed-off-by: Tao Chen +Link: https://lore.kernel.org/r/bff442d62c87de6299817fe1897cc5a5694ba9cc.1667638204.git.chentao.kernel@linux.alibaba.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: d0f95894fda7 ("netlink: annotate data-races around sk->sk_err") +Signed-off-by: Sasha Levin +--- + net/netlink/af_netlink.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 4ddb2ed7706ad..845ac56a3ac2e 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -2444,7 +2444,7 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err, + + skb = nlmsg_new(payload + tlvlen, GFP_KERNEL); + if (!skb) +- goto err_bad_put; ++ goto err_skb; + + rep = nlmsg_put(skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, + NLMSG_ERROR, sizeof(*errmsg), flags); +@@ -2472,6 +2472,8 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err, + return; + + err_bad_put: ++ nlmsg_free(skb); ++err_skb: + NETLINK_CB(in_skb).sk->sk_err = ENOBUFS; + sk_error_report(NETLINK_CB(in_skb).sk); + } +-- +2.40.1 + diff --git a/queue-6.1/netlink-split-up-copies-in-the-ack-construction.patch b/queue-6.1/netlink-split-up-copies-in-the-ack-construction.patch new file mode 100644 index 00000000000..77de6ea5b26 --- /dev/null +++ b/queue-6.1/netlink-split-up-copies-in-the-ack-construction.patch @@ -0,0 +1,130 @@ +From 1cb9bb4256b0bf587b446892e84c28a13c146fd6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 27 Oct 2022 14:25:53 -0700 +Subject: netlink: split up copies in the ack construction + +From: Jakub Kicinski + +[ Upstream commit 738136a0e3757a8534df3ad97d6ff6d7f429f6c1 ] + +Clean up the use of unsafe_memcpy() by adding a flexible array +at the end of netlink message header and splitting up the header +and data copies. + +Reviewed-by: Kees Cook +Signed-off-by: Jakub Kicinski +Signed-off-by: David S. Miller +Stable-dep-of: d0f95894fda7 ("netlink: annotate data-races around sk->sk_err") +Signed-off-by: Sasha Levin +--- + include/net/netlink.h | 21 +++++++++++++++++++++ + include/uapi/linux/netlink.h | 2 ++ + net/netlink/af_netlink.c | 29 ++++++++++++++++++++--------- + 3 files changed, 43 insertions(+), 9 deletions(-) + +diff --git a/include/net/netlink.h b/include/net/netlink.h +index 6bfa972f2fbf2..a686c9041ddc0 100644 +--- a/include/net/netlink.h ++++ b/include/net/netlink.h +@@ -937,6 +937,27 @@ static inline struct nlmsghdr *nlmsg_put(struct sk_buff *skb, u32 portid, u32 se + return __nlmsg_put(skb, portid, seq, type, payload, flags); + } + ++/** ++ * nlmsg_append - Add more data to a nlmsg in a skb ++ * @skb: socket buffer to store message in ++ * @size: length of message payload ++ * ++ * Append data to an existing nlmsg, used when constructing a message ++ * with multiple fixed-format headers (which is rare). ++ * Returns NULL if the tailroom of the skb is insufficient to store ++ * the extra payload. ++ */ ++static inline void *nlmsg_append(struct sk_buff *skb, u32 size) ++{ ++ if (unlikely(skb_tailroom(skb) < NLMSG_ALIGN(size))) ++ return NULL; ++ ++ if (NLMSG_ALIGN(size) - size) ++ memset(skb_tail_pointer(skb) + size, 0, ++ NLMSG_ALIGN(size) - size); ++ return __skb_put(skb, NLMSG_ALIGN(size)); ++} ++ + /** + * nlmsg_put_answer - Add a new callback based netlink message to an skb + * @skb: socket buffer to store message in +diff --git a/include/uapi/linux/netlink.h b/include/uapi/linux/netlink.h +index e2ae82e3f9f71..5da0da59bf010 100644 +--- a/include/uapi/linux/netlink.h ++++ b/include/uapi/linux/netlink.h +@@ -48,6 +48,7 @@ struct sockaddr_nl { + * @nlmsg_flags: Additional flags + * @nlmsg_seq: Sequence number + * @nlmsg_pid: Sending process port ID ++ * @nlmsg_data: Message payload + */ + struct nlmsghdr { + __u32 nlmsg_len; +@@ -55,6 +56,7 @@ struct nlmsghdr { + __u16 nlmsg_flags; + __u32 nlmsg_seq; + __u32 nlmsg_pid; ++ __u8 nlmsg_data[]; + }; + + /* Flags values */ +diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c +index 387e430a35ccc..4ddb2ed7706ad 100644 +--- a/net/netlink/af_netlink.c ++++ b/net/netlink/af_netlink.c +@@ -2443,19 +2443,24 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err, + flags |= NLM_F_ACK_TLVS; + + skb = nlmsg_new(payload + tlvlen, GFP_KERNEL); +- if (!skb) { +- NETLINK_CB(in_skb).sk->sk_err = ENOBUFS; +- sk_error_report(NETLINK_CB(in_skb).sk); +- return; +- } ++ if (!skb) ++ goto err_bad_put; + + rep = nlmsg_put(skb, NETLINK_CB(in_skb).portid, nlh->nlmsg_seq, +- NLMSG_ERROR, payload, flags); ++ NLMSG_ERROR, sizeof(*errmsg), flags); ++ if (!rep) ++ goto err_bad_put; + errmsg = nlmsg_data(rep); + errmsg->error = err; +- unsafe_memcpy(&errmsg->msg, nlh, payload > sizeof(*errmsg) +- ? nlh->nlmsg_len : sizeof(*nlh), +- /* Bounds checked by the skb layer. */); ++ errmsg->msg = *nlh; ++ ++ if (!(flags & NLM_F_CAPPED)) { ++ if (!nlmsg_append(skb, nlmsg_len(nlh))) ++ goto err_bad_put; ++ ++ memcpy(errmsg->msg.nlmsg_data, nlh->nlmsg_data, ++ nlmsg_len(nlh)); ++ } + + if (tlvlen) + netlink_ack_tlv_fill(in_skb, skb, nlh, err, extack); +@@ -2463,6 +2468,12 @@ void netlink_ack(struct sk_buff *in_skb, struct nlmsghdr *nlh, int err, + nlmsg_end(skb, rep); + + nlmsg_unicast(in_skb->sk, skb, NETLINK_CB(in_skb).portid); ++ ++ return; ++ ++err_bad_put: ++ NETLINK_CB(in_skb).sk->sk_err = ENOBUFS; ++ sk_error_report(NETLINK_CB(in_skb).sk); + } + EXPORT_SYMBOL(netlink_ack); + +-- +2.40.1 + diff --git a/queue-6.1/nfsv4-fix-a-nfs4_state_manager-race.patch b/queue-6.1/nfsv4-fix-a-nfs4_state_manager-race.patch new file mode 100644 index 00000000000..9896debd4d4 --- /dev/null +++ b/queue-6.1/nfsv4-fix-a-nfs4_state_manager-race.patch @@ -0,0 +1,43 @@ +From 23966503daa327e529f021824c9298797d367878 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 17 Sep 2023 19:05:50 -0400 +Subject: NFSv4: Fix a nfs4_state_manager() race + +From: Trond Myklebust + +[ Upstream commit ed1cc05aa1f7fe8197d300e914afc28ab9818f89 ] + +If the NFS4CLNT_RUN_MANAGER flag got set just before we cleared +NFS4CLNT_MANAGER_RUNNING, then we might have won the race against +nfs4_schedule_state_manager(), and are responsible for handling the +recovery situation. + +Fixes: aeabb3c96186 ("NFSv4: Fix a NFSv4 state manager deadlock") +Signed-off-by: Trond Myklebust +Signed-off-by: Anna Schumaker +Signed-off-by: Sasha Levin +--- + fs/nfs/nfs4state.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c +index ed789e0cb9431..457b2b2f804ab 100644 +--- a/fs/nfs/nfs4state.c ++++ b/fs/nfs/nfs4state.c +@@ -2710,6 +2710,13 @@ static void nfs4_state_manager(struct nfs_client *clp) + nfs4_end_drain_session(clp); + nfs4_clear_state_manager_bit(clp); + ++ if (test_bit(NFS4CLNT_RUN_MANAGER, &clp->cl_state) && ++ !test_and_set_bit(NFS4CLNT_MANAGER_RUNNING, ++ &clp->cl_state)) { ++ memflags = memalloc_nofs_save(); ++ continue; ++ } ++ + if (!test_and_set_bit(NFS4CLNT_RECALL_RUNNING, &clp->cl_state)) { + if (test_and_clear_bit(NFS4CLNT_DELEGRETURN, &clp->cl_state)) { + nfs_client_return_marked_delegations(clp); +-- +2.40.1 + diff --git a/queue-6.1/perf-x86-amd-core-fix-overflow-reset-on-hotplug.patch b/queue-6.1/perf-x86-amd-core-fix-overflow-reset-on-hotplug.patch new file mode 100644 index 00000000000..29722b45ad5 --- /dev/null +++ b/queue-6.1/perf-x86-amd-core-fix-overflow-reset-on-hotplug.patch @@ -0,0 +1,90 @@ +From c33f0a52e0ec88cb3a7af0802916a639511ff964 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Sep 2023 19:36:04 +0530 +Subject: perf/x86/amd/core: Fix overflow reset on hotplug + +From: Sandipan Das + +[ Upstream commit 23d2626b841c2adccdeb477665313c02dff02dc3 ] + +Kernels older than v5.19 do not support PerfMonV2 and the PMI handler +does not clear the overflow bits of the PerfCntrGlobalStatus register. +Because of this, loading a recent kernel using kexec from an older +kernel can result in inconsistent register states on Zen 4 systems. + +The PMI handler of the new kernel gets confused and shows a warning when +an overflow occurs because some of the overflow bits are set even if the +corresponding counters are inactive. These are remnants from overflows +that were handled by the older kernel. + +During CPU hotplug, the PerfCntrGlobalCtl and PerfCntrGlobalStatus +registers should always be cleared for PerfMonV2-capable processors. +However, a condition used for NB event constaints applicable only to +older processors currently prevents this from happening. Move the reset +sequence to an appropriate place and also clear the LBR Freeze bit. + +Fixes: 21d59e3e2c40 ("perf/x86/amd/core: Detect PerfMonV2 support") +Signed-off-by: Sandipan Das +Signed-off-by: Ingo Molnar +Link: https://lore.kernel.org/r/882a87511af40792ba69bb0e9026f19a2e71e8a3.1694696888.git.sandipan.das@amd.com +Signed-off-by: Sasha Levin +--- + arch/x86/events/amd/core.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c +index 6672a3f05fc68..bb9d99b45a459 100644 +--- a/arch/x86/events/amd/core.c ++++ b/arch/x86/events/amd/core.c +@@ -534,8 +534,12 @@ static void amd_pmu_cpu_reset(int cpu) + /* Clear enable bits i.e. PerfCntrGlobalCtl.PerfCntrEn */ + wrmsrl(MSR_AMD64_PERF_CNTR_GLOBAL_CTL, 0); + +- /* Clear overflow bits i.e. PerfCntrGLobalStatus.PerfCntrOvfl */ +- wrmsrl(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, amd_pmu_global_cntr_mask); ++ /* ++ * Clear freeze and overflow bits i.e. PerfCntrGLobalStatus.LbrFreeze ++ * and PerfCntrGLobalStatus.PerfCntrOvfl ++ */ ++ wrmsrl(MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR, ++ GLOBAL_STATUS_LBRS_FROZEN | amd_pmu_global_cntr_mask); + } + + static int amd_pmu_cpu_prepare(int cpu) +@@ -570,6 +574,7 @@ static void amd_pmu_cpu_starting(int cpu) + int i, nb_id; + + cpuc->perf_ctr_virt_mask = AMD64_EVENTSEL_HOSTONLY; ++ amd_pmu_cpu_reset(cpu); + + if (!x86_pmu.amd_nb_constraints) + return; +@@ -591,8 +596,6 @@ static void amd_pmu_cpu_starting(int cpu) + + cpuc->amd_nb->nb_id = nb_id; + cpuc->amd_nb->refcnt++; +- +- amd_pmu_cpu_reset(cpu); + } + + static void amd_pmu_cpu_dead(int cpu) +@@ -601,6 +604,7 @@ static void amd_pmu_cpu_dead(int cpu) + + kfree(cpuhw->lbr_sel); + cpuhw->lbr_sel = NULL; ++ amd_pmu_cpu_reset(cpu); + + if (!x86_pmu.amd_nb_constraints) + return; +@@ -613,8 +617,6 @@ static void amd_pmu_cpu_dead(int cpu) + + cpuhw->amd_nb = NULL; + } +- +- amd_pmu_cpu_reset(cpu); + } + + static inline void amd_pmu_set_global_ctl(u64 ctl) +-- +2.40.1 + diff --git a/queue-6.1/perf-x86-amd-do-not-warn-on-every-irq.patch b/queue-6.1/perf-x86-amd-do-not-warn-on-every-irq.patch new file mode 100644 index 00000000000..21742775e9e --- /dev/null +++ b/queue-6.1/perf-x86-amd-do-not-warn-on-every-irq.patch @@ -0,0 +1,87 @@ +From 232df8a9560dbc4f1565bd8e80f88dd6b8b6f68a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 14 Sep 2023 19:58:40 +0530 +Subject: perf/x86/amd: Do not WARN() on every IRQ +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Breno Leitao + +[ Upstream commit 599522d9d2e19d6240e4312577f1c5f3ffca22f6 ] + +Zen 4 systems running buggy microcode can hit a WARN_ON() in the PMI +handler, as shown below, several times while perf runs. A simple +`perf top` run is enough to render the system unusable: + + WARNING: CPU: 18 PID: 20608 at arch/x86/events/amd/core.c:944 amd_pmu_v2_handle_irq+0x1be/0x2b0 + +This happens because the Performance Counter Global Status Register +(PerfCntGlobalStatus) has one or more bits set which are considered +reserved according to the "AMD64 Architecture Programmer’s Manual, +Volume 2: System Programming, 24593": + + https://www.amd.com/system/files/TechDocs/24593.pdf + +To make this less intrusive, warn just once if any reserved bit is set +and prompt the user to update the microcode. Also sanitize the value to +what the code is handling, so that the overflow events continue to be +handled for the number of counters that are known to be sane. + +Going forward, the following microcode patch levels are recommended +for Zen 4 processors in order to avoid such issues with reserved bits: + + Family=0x19 Model=0x11 Stepping=0x01: Patch=0x0a10113e + Family=0x19 Model=0x11 Stepping=0x02: Patch=0x0a10123e + Family=0x19 Model=0xa0 Stepping=0x01: Patch=0x0aa00116 + Family=0x19 Model=0xa0 Stepping=0x02: Patch=0x0aa00212 + +Commit f2eb058afc57 ("linux-firmware: Update AMD cpu microcode") from +the linux-firmware tree has binaries that meet the minimum required +patch levels. + + [ sandipan: - add message to prompt users to update microcode + - rework commit message and call out required microcode levels ] + +Fixes: 7685665c390d ("perf/x86/amd/core: Add PerfMonV2 overflow handling") +Reported-by: Jirka Hladky +Signed-off-by: Breno Leitao +Signed-off-by: Sandipan Das +Signed-off-by: Ingo Molnar +Link: https://lore.kernel.org/all/3540f985652f41041e54ee82aa53e7dbd55739ae.1694696888.git.sandipan.das@amd.com/ +Signed-off-by: Sasha Levin +--- + arch/x86/events/amd/core.c | 10 +++++++++- + 1 file changed, 9 insertions(+), 1 deletion(-) + +diff --git a/arch/x86/events/amd/core.c b/arch/x86/events/amd/core.c +index bb9d99b45a459..04f4b96dec6df 100644 +--- a/arch/x86/events/amd/core.c ++++ b/arch/x86/events/amd/core.c +@@ -886,7 +886,7 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs) + struct hw_perf_event *hwc; + struct perf_event *event; + int handled = 0, idx; +- u64 status, mask; ++ u64 reserved, status, mask; + bool pmu_enabled; + + /* +@@ -911,6 +911,14 @@ static int amd_pmu_v2_handle_irq(struct pt_regs *regs) + status &= ~GLOBAL_STATUS_LBRS_FROZEN; + } + ++ reserved = status & ~amd_pmu_global_cntr_mask; ++ if (reserved) ++ pr_warn_once("Reserved PerfCntrGlobalStatus bits are set (0x%llx), please consider updating microcode\n", ++ reserved); ++ ++ /* Clear any reserved bits set by buggy microcode */ ++ status &= amd_pmu_global_cntr_mask; ++ + for (idx = 0; idx < x86_pmu.num_counters; idx++) { + if (!test_bit(idx, cpuc->active_mask)) + continue; +-- +2.40.1 + diff --git a/queue-6.1/ptp-ocp-fix-error-handling-in-ptp_ocp_device_init.patch b/queue-6.1/ptp-ocp-fix-error-handling-in-ptp_ocp_device_init.patch new file mode 100644 index 00000000000..8852295ccb0 --- /dev/null +++ b/queue-6.1/ptp-ocp-fix-error-handling-in-ptp_ocp_device_init.patch @@ -0,0 +1,37 @@ +From f1ad194004ef811c7a6d50456334178a48a7cabd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Sep 2023 17:40:44 +0800 +Subject: ptp: ocp: Fix error handling in ptp_ocp_device_init + +From: Dinghao Liu + +[ Upstream commit caa0578c1d487d39e4bb947a1b4965417053b409 ] + +When device_add() fails, ptp_ocp_dev_release() will be called +after put_device(). Therefore, it seems that the +ptp_ocp_dev_release() before put_device() is redundant. + +Fixes: 773bda964921 ("ptp: ocp: Expose various resources on the timecard.") +Signed-off-by: Dinghao Liu +Reviewed-by: Vadim Feodrenko +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/ptp/ptp_ocp.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c +index a48d9b7d29217..8fee9b330b613 100644 +--- a/drivers/ptp/ptp_ocp.c ++++ b/drivers/ptp/ptp_ocp.c +@@ -3532,7 +3532,6 @@ ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev) + return 0; + + out: +- ptp_ocp_dev_release(&bp->dev); + put_device(&bp->dev); + return err; + } +-- +2.40.1 + diff --git a/queue-6.1/regmap-rbtree-fix-wrong-register-marked-as-in-cache-.patch b/queue-6.1/regmap-rbtree-fix-wrong-register-marked-as-in-cache-.patch new file mode 100644 index 00000000000..b6a0548b3fe --- /dev/null +++ b/queue-6.1/regmap-rbtree-fix-wrong-register-marked-as-in-cache-.patch @@ -0,0 +1,50 @@ +From cc7b68a4727c8dac77853769296be0d800352eb0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Sep 2023 16:37:11 +0100 +Subject: regmap: rbtree: Fix wrong register marked as in-cache when creating + new node + +From: Richard Fitzgerald + +[ Upstream commit 7a795ac8d49e2433e1b97caf5e99129daf8e1b08 ] + +When regcache_rbtree_write() creates a new rbtree_node it was passing the +wrong bit number to regcache_rbtree_set_register(). The bit number is the +offset __in number of registers__, but in the case of creating a new block +regcache_rbtree_write() was not dividing by the address stride to get the +number of registers. + +Fix this by dividing by map->reg_stride. +Compare with regcache_rbtree_read() where the bit is checked. + +This bug meant that the wrong register was marked as present. The register +that was written to the cache could not be read from the cache because it +was not marked as cached. But a nearby register could be marked as having +a cached value even if it was never written to the cache. + +Signed-off-by: Richard Fitzgerald +Fixes: 3f4ff561bc88 ("regmap: rbtree: Make cache_present bitmap per node") +Link: https://lore.kernel.org/r/20230922153711.28103-1-rf@opensource.cirrus.com +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/base/regmap/regcache-rbtree.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/base/regmap/regcache-rbtree.c b/drivers/base/regmap/regcache-rbtree.c +index ae6b8788d5f3f..d65715b9e129e 100644 +--- a/drivers/base/regmap/regcache-rbtree.c ++++ b/drivers/base/regmap/regcache-rbtree.c +@@ -453,7 +453,8 @@ static int regcache_rbtree_write(struct regmap *map, unsigned int reg, + if (!rbnode) + return -ENOMEM; + regcache_rbtree_set_register(map, rbnode, +- reg - rbnode->base_reg, value); ++ (reg - rbnode->base_reg) / map->reg_stride, ++ value); + regcache_rbtree_insert(map, &rbtree_ctx->root, rbnode); + rbtree_ctx->cached_rbnode = rbnode; + } +-- +2.40.1 + diff --git a/queue-6.1/regulator-core-regulator_register-set-device-class-e.patch b/queue-6.1/regulator-core-regulator_register-set-device-class-e.patch new file mode 100644 index 00000000000..b96f8a98d59 --- /dev/null +++ b/queue-6.1/regulator-core-regulator_register-set-device-class-e.patch @@ -0,0 +1,60 @@ +From f5d426eddc1200d63ac70c42948c1bc1c971ee52 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Sep 2023 00:50:26 +0200 +Subject: regulator/core: regulator_register: set device->class earlier +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Michał Mirosław + +[ Upstream commit 8adb4e647a83cb5928c05dae95b010224aea0705 ] + +When fixing a memory leak in commit d3c731564e09 ("regulator: plug +of_node leak in regulator_register()'s error path") it moved the +device_initialize() call earlier, but did not move the `dev->class` +initialization. The bug was spotted and fixed by reverting part of +the commit (in commit 5f4b204b6b81 "regulator: core: fix kobject +release warning and memory leak in regulator_register()") but +introducing a different bug: now early error paths use `kfree(dev)` +instead of `put_device()` for an already initialized `struct device`. + +Move the missing assignments to just after `device_initialize()`. + +Fixes: d3c731564e09 ("regulator: plug of_node leak in regulator_register()'s error path") +Signed-off-by: Michał Mirosław +Link: https://lore.kernel.org/r/b5b19cb458c40c9d02f3d5a7bd1ba7d97ba17279.1695077303.git.mirq-linux@rere.qmqm.pl +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/core.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c +index 351f0fd225b14..f6a95f72af18d 100644 +--- a/drivers/regulator/core.c ++++ b/drivers/regulator/core.c +@@ -5543,6 +5543,8 @@ regulator_register(struct device *dev, + goto rinse; + } + device_initialize(&rdev->dev); ++ dev_set_drvdata(&rdev->dev, rdev); ++ rdev->dev.class = ®ulator_class; + spin_lock_init(&rdev->err_lock); + + /* +@@ -5604,11 +5606,9 @@ regulator_register(struct device *dev, + rdev->supply_name = regulator_desc->supply_name; + + /* register with sysfs */ +- rdev->dev.class = ®ulator_class; + rdev->dev.parent = config->dev; + dev_set_name(&rdev->dev, "regulator.%lu", + (unsigned long) atomic_inc_return(®ulator_no)); +- dev_set_drvdata(&rdev->dev, rdev); + + /* set regulator constraints */ + if (init_data) +-- +2.40.1 + diff --git a/queue-6.1/regulator-mt6358-drop-_sshub-regulators.patch b/queue-6.1/regulator-mt6358-drop-_sshub-regulators.patch new file mode 100644 index 00000000000..ea17ff8ed99 --- /dev/null +++ b/queue-6.1/regulator-mt6358-drop-_sshub-regulators.patch @@ -0,0 +1,101 @@ +From fb60a5ee7ebbe3dcf718b81ad54eb654ffd6f355 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Jun 2023 16:30:01 +0800 +Subject: regulator: mt6358: Drop *_SSHUB regulators + +From: Chen-Yu Tsai + +[ Upstream commit 04ba665248ed91576d326041108e5fc2ec2254eb ] + +The *_SSHUB regulators are actually alternate configuration interfaces +for their non *_SSHUB counterparts. They are not separate regulator +outputs. These registers are intended for the companion processor to +use to configure the power rails while the main processor is sleeping. +They are not intended for the main operating system to use. + +Since they are not real outputs they shouldn't be modeled separately. +Remove them. Luckily no device tree actually uses them. + +Signed-off-by: Chen-Yu Tsai +Reviewed-by: AngeloGioacchino Del Regno +Reviewed-by: Matthias Brugger +Link: https://lore.kernel.org/r/20230609083009.2822259-5-wenst@chromium.org +Signed-off-by: Mark Brown +Stable-dep-of: 7e37c851374e ("regulator: mt6358: split ops for buck and linear range LDO regulators") +Signed-off-by: Sasha Levin +--- + drivers/regulator/mt6358-regulator.c | 14 -------------- + include/linux/regulator/mt6358-regulator.h | 4 ---- + 2 files changed, 18 deletions(-) + +diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c +index 8a5ce990f1bf9..153c1fd5fb0b7 100644 +--- a/drivers/regulator/mt6358-regulator.c ++++ b/drivers/regulator/mt6358-regulator.c +@@ -505,9 +505,6 @@ static struct mt6358_regulator_info mt6358_regulators[] = { + MT6358_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250, + buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, + MT6358_VCORE_VGPU_ANA_CON0, 1), +- MT6358_BUCK("buck_vcore_sshub", VCORE_SSHUB, 500000, 1293750, 6250, +- buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_SSHUB_ELR0, 0x7f, +- MT6358_VCORE_VGPU_ANA_CON0, 1), + MT6358_BUCK("buck_vpa", VPA, 500000, 3650000, 50000, + buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, + MT6358_VPA_ANA_CON0, 3), +@@ -587,10 +584,6 @@ static struct mt6358_regulator_info mt6358_regulators[] = { + MT6358_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250, + buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, + MT6358_LDO_VSRAM_CON2, 0x7f), +- MT6358_LDO1("ldo_vsram_others_sshub", VSRAM_OTHERS_SSHUB, 500000, +- 1293750, 6250, buck_volt_range1, +- MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f, +- MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f), + MT6358_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250, + buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, + MT6358_LDO_VSRAM_CON3, 0x7f), +@@ -607,9 +600,6 @@ static struct mt6358_regulator_info mt6366_regulators[] = { + MT6366_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250, + buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, + MT6358_VCORE_VGPU_ANA_CON0, 1), +- MT6366_BUCK("buck_vcore_sshub", VCORE_SSHUB, 500000, 1293750, 6250, +- buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_SSHUB_ELR0, 0x7f, +- MT6358_VCORE_VGPU_ANA_CON0, 1), + MT6366_BUCK("buck_vpa", VPA, 500000, 3650000, 50000, + buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, + MT6358_VPA_ANA_CON0, 3), +@@ -678,10 +668,6 @@ static struct mt6358_regulator_info mt6366_regulators[] = { + MT6366_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250, + buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, + MT6358_LDO_VSRAM_CON2, 0x7f), +- MT6366_LDO1("ldo_vsram_others_sshub", VSRAM_OTHERS_SSHUB, 500000, +- 1293750, 6250, buck_volt_range1, +- MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f, +- MT6358_LDO_VSRAM_OTHERS_SSHUB_CON1, 0x7f), + MT6366_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250, + buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, + MT6358_LDO_VSRAM_CON3, 0x7f), +diff --git a/include/linux/regulator/mt6358-regulator.h b/include/linux/regulator/mt6358-regulator.h +index bdcf83cd719ef..be9f61e3e8e6d 100644 +--- a/include/linux/regulator/mt6358-regulator.h ++++ b/include/linux/regulator/mt6358-regulator.h +@@ -48,8 +48,6 @@ enum { + MT6358_ID_VLDO28, + MT6358_ID_VAUD28, + MT6358_ID_VSIM2, +- MT6358_ID_VCORE_SSHUB, +- MT6358_ID_VSRAM_OTHERS_SSHUB, + MT6358_ID_RG_MAX, + }; + +@@ -90,8 +88,6 @@ enum { + MT6366_ID_VMC, + MT6366_ID_VAUD28, + MT6366_ID_VSIM2, +- MT6366_ID_VCORE_SSHUB, +- MT6366_ID_VSRAM_OTHERS_SSHUB, + MT6366_ID_RG_MAX, + }; + +-- +2.40.1 + diff --git a/queue-6.1/regulator-mt6358-split-ops-for-buck-and-linear-range.patch b/queue-6.1/regulator-mt6358-split-ops-for-buck-and-linear-range.patch new file mode 100644 index 00000000000..f4800b5fe00 --- /dev/null +++ b/queue-6.1/regulator-mt6358-split-ops-for-buck-and-linear-range.patch @@ -0,0 +1,81 @@ +From 88b3d5388269c18898d3cb454e4c8c2895e90cf4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 20 Sep 2023 16:53:34 +0800 +Subject: regulator: mt6358: split ops for buck and linear range LDO regulators + +From: Chen-Yu Tsai + +[ Upstream commit 7e37c851374eca2d1f6128de03195c9f7b4baaf2 ] + +The buck and linear range LDO (VSRAM_*) regulators share one set of ops. +This set includes support for get/set mode. However this only makes +sense for buck regulators, not LDOs. The callbacks were not checking +whether the register offset and/or mask for mode setting was valid or +not. This ends up making the kernel report "normal" mode operation for +the LDOs. + +Create a new set of ops without the get/set mode callbacks for the +linear range LDO regulators. + +Fixes: f67ff1bd58f0 ("regulator: mt6358: Add support for MT6358 regulator") +Signed-off-by: Chen-Yu Tsai +Link: https://lore.kernel.org/r/20230920085336.136238-1-wenst@chromium.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +--- + drivers/regulator/mt6358-regulator.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c +index 56b5fc9f62c94..a0441b8086712 100644 +--- a/drivers/regulator/mt6358-regulator.c ++++ b/drivers/regulator/mt6358-regulator.c +@@ -41,7 +41,7 @@ struct mt6358_regulator_info { + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ +- .ops = &mt6358_volt_range_ops, \ ++ .ops = &mt6358_buck_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6358_ID_##vreg, \ + .owner = THIS_MODULE, \ +@@ -137,7 +137,7 @@ struct mt6358_regulator_info { + .desc = { \ + .name = #vreg, \ + .of_match = of_match_ptr(match), \ +- .ops = &mt6358_volt_range_ops, \ ++ .ops = &mt6358_buck_ops, \ + .type = REGULATOR_VOLTAGE, \ + .id = MT6366_ID_##vreg, \ + .owner = THIS_MODULE, \ +@@ -448,7 +448,7 @@ static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev) + } + } + +-static const struct regulator_ops mt6358_volt_range_ops = { ++static const struct regulator_ops mt6358_buck_ops = { + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, + .set_voltage_sel = regulator_set_voltage_sel_regmap, +@@ -462,6 +462,18 @@ static const struct regulator_ops mt6358_volt_range_ops = { + .get_mode = mt6358_regulator_get_mode, + }; + ++static const struct regulator_ops mt6358_volt_range_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, ++ .set_voltage_time_sel = regulator_set_voltage_time_sel, ++ .enable = regulator_enable_regmap, ++ .disable = regulator_disable_regmap, ++ .is_enabled = regulator_is_enabled_regmap, ++ .get_status = mt6358_get_status, ++}; ++ + static const struct regulator_ops mt6358_volt_table_ops = { + .list_voltage = regulator_list_voltage_table, + .map_voltage = regulator_map_voltage_iterate, +-- +2.40.1 + diff --git a/queue-6.1/regulator-mt6358-use-linear-voltage-helpers-for-sing.patch b/queue-6.1/regulator-mt6358-use-linear-voltage-helpers-for-sing.patch new file mode 100644 index 00000000000..0231176b729 --- /dev/null +++ b/queue-6.1/regulator-mt6358-use-linear-voltage-helpers-for-sing.patch @@ -0,0 +1,274 @@ +From 217ed2bdb9b6c26ffb825646900c277fedfbf7ee Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 9 Jun 2023 16:30:03 +0800 +Subject: regulator: mt6358: Use linear voltage helpers for single range + regulators + +From: Chen-Yu Tsai + +[ Upstream commit ea861df772fd8cca715d43f62fe13c09c975f7a2 ] + +Some of the regulators on the MT6358/MT6366 PMICs have just one linear +voltage range. These are the bulk regulators and VSRAM_* LDOs. Currently +they are modeled with one linear range, but also have their minimum, +maximum, and step voltage described. + +Convert them to the linear voltage helpers. These helpers are a bit +simpler, and we can also drop the linear range definitions. Also reflow +the touched lines now that they are shorter. + +Signed-off-by: Chen-Yu Tsai +Link: https://lore.kernel.org/r/20230609083009.2822259-7-wenst@chromium.org +Signed-off-by: Mark Brown +Stable-dep-of: 7e37c851374e ("regulator: mt6358: split ops for buck and linear range LDO regulators") +Signed-off-by: Sasha Levin +--- + drivers/regulator/mt6358-regulator.c | 121 +++++++++------------------ + 1 file changed, 40 insertions(+), 81 deletions(-) + +diff --git a/drivers/regulator/mt6358-regulator.c b/drivers/regulator/mt6358-regulator.c +index 153c1fd5fb0b7..56b5fc9f62c94 100644 +--- a/drivers/regulator/mt6358-regulator.c ++++ b/drivers/regulator/mt6358-regulator.c +@@ -35,7 +35,7 @@ struct mt6358_regulator_info { + }; + + #define MT6358_BUCK(match, vreg, min, max, step, \ +- volt_ranges, vosel_mask, _da_vsel_reg, _da_vsel_mask, \ ++ vosel_mask, _da_vsel_reg, _da_vsel_mask, \ + _modeset_reg, _modeset_shift) \ + [MT6358_ID_##vreg] = { \ + .desc = { \ +@@ -46,8 +46,8 @@ struct mt6358_regulator_info { + .id = MT6358_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ +- .linear_ranges = volt_ranges, \ +- .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ ++ .min_uV = (min), \ ++ .uV_step = (step), \ + .vsel_reg = MT6358_BUCK_##vreg##_ELR0, \ + .vsel_mask = vosel_mask, \ + .enable_reg = MT6358_BUCK_##vreg##_CON0, \ +@@ -87,7 +87,7 @@ struct mt6358_regulator_info { + } + + #define MT6358_LDO1(match, vreg, min, max, step, \ +- volt_ranges, _da_vsel_reg, _da_vsel_mask, \ ++ _da_vsel_reg, _da_vsel_mask, \ + vosel, vosel_mask) \ + [MT6358_ID_##vreg] = { \ + .desc = { \ +@@ -98,8 +98,8 @@ struct mt6358_regulator_info { + .id = MT6358_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ +- .linear_ranges = volt_ranges, \ +- .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ ++ .min_uV = (min), \ ++ .uV_step = (step), \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + .enable_reg = MT6358_LDO_##vreg##_CON0, \ +@@ -131,7 +131,7 @@ struct mt6358_regulator_info { + } + + #define MT6366_BUCK(match, vreg, min, max, step, \ +- volt_ranges, vosel_mask, _da_vsel_reg, _da_vsel_mask, \ ++ vosel_mask, _da_vsel_reg, _da_vsel_mask, \ + _modeset_reg, _modeset_shift) \ + [MT6366_ID_##vreg] = { \ + .desc = { \ +@@ -142,8 +142,8 @@ struct mt6358_regulator_info { + .id = MT6366_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ +- .linear_ranges = volt_ranges, \ +- .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ ++ .min_uV = (min), \ ++ .uV_step = (step), \ + .vsel_reg = MT6358_BUCK_##vreg##_ELR0, \ + .vsel_mask = vosel_mask, \ + .enable_reg = MT6358_BUCK_##vreg##_CON0, \ +@@ -183,7 +183,7 @@ struct mt6358_regulator_info { + } + + #define MT6366_LDO1(match, vreg, min, max, step, \ +- volt_ranges, _da_vsel_reg, _da_vsel_mask, \ ++ _da_vsel_reg, _da_vsel_mask, \ + vosel, vosel_mask) \ + [MT6366_ID_##vreg] = { \ + .desc = { \ +@@ -194,8 +194,8 @@ struct mt6358_regulator_info { + .id = MT6366_ID_##vreg, \ + .owner = THIS_MODULE, \ + .n_voltages = ((max) - (min)) / (step) + 1, \ +- .linear_ranges = volt_ranges, \ +- .n_linear_ranges = ARRAY_SIZE(volt_ranges), \ ++ .min_uV = (min), \ ++ .uV_step = (step), \ + .vsel_reg = vosel, \ + .vsel_mask = vosel_mask, \ + .enable_reg = MT6358_LDO_##vreg##_CON0, \ +@@ -226,21 +226,6 @@ struct mt6358_regulator_info { + .qi = BIT(15), \ + } + +-static const struct linear_range buck_volt_range1[] = { +- REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 6250), +-}; +- +-static const struct linear_range buck_volt_range2[] = { +- REGULATOR_LINEAR_RANGE(500000, 0, 0x7f, 12500), +-}; +- +-static const struct linear_range buck_volt_range3[] = { +- REGULATOR_LINEAR_RANGE(500000, 0, 0x3f, 50000), +-}; +- +-static const struct linear_range buck_volt_range4[] = { +- REGULATOR_LINEAR_RANGE(1000000, 0, 0x7f, 12500), +-}; + + static const unsigned int vdram2_voltages[] = { + 600000, 1800000, +@@ -464,8 +449,8 @@ static unsigned int mt6358_regulator_get_mode(struct regulator_dev *rdev) + } + + static const struct regulator_ops mt6358_volt_range_ops = { +- .list_voltage = regulator_list_voltage_linear_range, +- .map_voltage = regulator_map_voltage_linear_range, ++ .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, + .set_voltage_time_sel = regulator_set_voltage_time_sel, +@@ -500,32 +485,23 @@ static const struct regulator_ops mt6358_volt_fixed_ops = { + /* The array is indexed by id(MT6358_ID_XXX) */ + static struct mt6358_regulator_info mt6358_regulators[] = { + MT6358_BUCK("buck_vdram1", VDRAM1, 500000, 2087500, 12500, +- buck_volt_range2, 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f, +- MT6358_VDRAM1_ANA_CON0, 8), ++ 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f, MT6358_VDRAM1_ANA_CON0, 8), + MT6358_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250, +- buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, +- MT6358_VCORE_VGPU_ANA_CON0, 1), ++ 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 1), + MT6358_BUCK("buck_vpa", VPA, 500000, 3650000, 50000, +- buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, +- MT6358_VPA_ANA_CON0, 3), ++ 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, MT6358_VPA_ANA_CON0, 3), + MT6358_BUCK("buck_vproc11", VPROC11, 500000, 1293750, 6250, +- buck_volt_range1, 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f, +- MT6358_VPROC_ANA_CON0, 1), ++ 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 1), + MT6358_BUCK("buck_vproc12", VPROC12, 500000, 1293750, 6250, +- buck_volt_range1, 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f, +- MT6358_VPROC_ANA_CON0, 2), ++ 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 2), + MT6358_BUCK("buck_vgpu", VGPU, 500000, 1293750, 6250, +- buck_volt_range1, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, +- MT6358_VCORE_VGPU_ANA_CON0, 2), ++ 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 2), + MT6358_BUCK("buck_vs2", VS2, 500000, 2087500, 12500, +- buck_volt_range2, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, +- MT6358_VS2_ANA_CON0, 8), ++ 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, MT6358_VS2_ANA_CON0, 8), + MT6358_BUCK("buck_vmodem", VMODEM, 500000, 1293750, 6250, +- buck_volt_range1, 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f, +- MT6358_VMODEM_ANA_CON0, 8), ++ 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f, MT6358_VMODEM_ANA_CON0, 8), + MT6358_BUCK("buck_vs1", VS1, 1000000, 2587500, 12500, +- buck_volt_range4, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, +- MT6358_VS1_ANA_CON0, 8), ++ 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, MT6358_VS1_ANA_CON0, 8), + MT6358_REG_FIXED("ldo_vrf12", VRF12, + MT6358_LDO_VRF12_CON0, 0, 1200000), + MT6358_REG_FIXED("ldo_vio18", VIO18, +@@ -579,48 +555,35 @@ static struct mt6358_regulator_info mt6358_regulators[] = { + MT6358_LDO("ldo_vsim2", VSIM2, vsim_voltages, vsim_idx, + MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00), + MT6358_LDO1("ldo_vsram_proc11", VSRAM_PROC11, 500000, 1293750, 6250, +- buck_volt_range1, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00, +- MT6358_LDO_VSRAM_CON0, 0x7f), ++ MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON0, 0x7f), + MT6358_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250, +- buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, +- MT6358_LDO_VSRAM_CON2, 0x7f), ++ MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON2, 0x7f), + MT6358_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250, +- buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, +- MT6358_LDO_VSRAM_CON3, 0x7f), ++ MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON3, 0x7f), + MT6358_LDO1("ldo_vsram_proc12", VSRAM_PROC12, 500000, 1293750, 6250, +- buck_volt_range1, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00, +- MT6358_LDO_VSRAM_CON1, 0x7f), ++ MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON1, 0x7f), + }; + + /* The array is indexed by id(MT6366_ID_XXX) */ + static struct mt6358_regulator_info mt6366_regulators[] = { + MT6366_BUCK("buck_vdram1", VDRAM1, 500000, 2087500, 12500, +- buck_volt_range2, 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f, +- MT6358_VDRAM1_ANA_CON0, 8), ++ 0x7f, MT6358_BUCK_VDRAM1_DBG0, 0x7f, MT6358_VDRAM1_ANA_CON0, 8), + MT6366_BUCK("buck_vcore", VCORE, 500000, 1293750, 6250, +- buck_volt_range1, 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, +- MT6358_VCORE_VGPU_ANA_CON0, 1), ++ 0x7f, MT6358_BUCK_VCORE_DBG0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 1), + MT6366_BUCK("buck_vpa", VPA, 500000, 3650000, 50000, +- buck_volt_range3, 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, +- MT6358_VPA_ANA_CON0, 3), ++ 0x3f, MT6358_BUCK_VPA_DBG0, 0x3f, MT6358_VPA_ANA_CON0, 3), + MT6366_BUCK("buck_vproc11", VPROC11, 500000, 1293750, 6250, +- buck_volt_range1, 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f, +- MT6358_VPROC_ANA_CON0, 1), ++ 0x7f, MT6358_BUCK_VPROC11_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 1), + MT6366_BUCK("buck_vproc12", VPROC12, 500000, 1293750, 6250, +- buck_volt_range1, 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f, +- MT6358_VPROC_ANA_CON0, 2), ++ 0x7f, MT6358_BUCK_VPROC12_DBG0, 0x7f, MT6358_VPROC_ANA_CON0, 2), + MT6366_BUCK("buck_vgpu", VGPU, 500000, 1293750, 6250, +- buck_volt_range1, 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, +- MT6358_VCORE_VGPU_ANA_CON0, 2), ++ 0x7f, MT6358_BUCK_VGPU_ELR0, 0x7f, MT6358_VCORE_VGPU_ANA_CON0, 2), + MT6366_BUCK("buck_vs2", VS2, 500000, 2087500, 12500, +- buck_volt_range2, 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, +- MT6358_VS2_ANA_CON0, 8), ++ 0x7f, MT6358_BUCK_VS2_DBG0, 0x7f, MT6358_VS2_ANA_CON0, 8), + MT6366_BUCK("buck_vmodem", VMODEM, 500000, 1293750, 6250, +- buck_volt_range1, 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f, +- MT6358_VMODEM_ANA_CON0, 8), ++ 0x7f, MT6358_BUCK_VMODEM_DBG0, 0x7f, MT6358_VMODEM_ANA_CON0, 8), + MT6366_BUCK("buck_vs1", VS1, 1000000, 2587500, 12500, +- buck_volt_range4, 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, +- MT6358_VS1_ANA_CON0, 8), ++ 0x7f, MT6358_BUCK_VS1_DBG0, 0x7f, MT6358_VS1_ANA_CON0, 8), + MT6366_REG_FIXED("ldo_vrf12", VRF12, + MT6358_LDO_VRF12_CON0, 0, 1200000), + MT6366_REG_FIXED("ldo_vio18", VIO18, +@@ -663,17 +626,13 @@ static struct mt6358_regulator_info mt6366_regulators[] = { + MT6366_LDO("ldo_vsim2", VSIM2, vsim_voltages, vsim_idx, + MT6358_LDO_VSIM2_CON0, 0, MT6358_VSIM2_ANA_CON0, 0xf00), + MT6366_LDO1("ldo_vsram_proc11", VSRAM_PROC11, 500000, 1293750, 6250, +- buck_volt_range1, MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00, +- MT6358_LDO_VSRAM_CON0, 0x7f), ++ MT6358_LDO_VSRAM_PROC11_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON0, 0x7f), + MT6366_LDO1("ldo_vsram_others", VSRAM_OTHERS, 500000, 1293750, 6250, +- buck_volt_range1, MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, +- MT6358_LDO_VSRAM_CON2, 0x7f), ++ MT6358_LDO_VSRAM_OTHERS_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON2, 0x7f), + MT6366_LDO1("ldo_vsram_gpu", VSRAM_GPU, 500000, 1293750, 6250, +- buck_volt_range1, MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, +- MT6358_LDO_VSRAM_CON3, 0x7f), ++ MT6358_LDO_VSRAM_GPU_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON3, 0x7f), + MT6366_LDO1("ldo_vsram_proc12", VSRAM_PROC12, 500000, 1293750, 6250, +- buck_volt_range1, MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00, +- MT6358_LDO_VSRAM_CON1, 0x7f), ++ MT6358_LDO_VSRAM_PROC12_DBG0, 0x7f00, MT6358_LDO_VSRAM_CON1, 0x7f), + }; + + static int mt6358_regulator_probe(struct platform_device *pdev) +-- +2.40.1 + diff --git a/queue-6.1/scsi-target-core-fix-deadlock-due-to-recursive-locki.patch b/queue-6.1/scsi-target-core-fix-deadlock-due-to-recursive-locki.patch new file mode 100644 index 00000000000..e39fea18f78 --- /dev/null +++ b/queue-6.1/scsi-target-core-fix-deadlock-due-to-recursive-locki.patch @@ -0,0 +1,98 @@ +From e3b9fb4b84a0fad9868d5d263318cd06683df806 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 18 Sep 2023 15:58:48 -0700 +Subject: scsi: target: core: Fix deadlock due to recursive locking + +From: Junxiao Bi + +[ Upstream commit a154f5f643c6ecddd44847217a7a3845b4350003 ] + +The following call trace shows a deadlock issue due to recursive locking of +mutex "device_mutex". First lock acquire is in target_for_each_device() and +second in target_free_device(). + + PID: 148266 TASK: ffff8be21ffb5d00 CPU: 10 COMMAND: "iscsi_ttx" + #0 [ffffa2bfc9ec3b18] __schedule at ffffffffa8060e7f + #1 [ffffa2bfc9ec3ba0] schedule at ffffffffa8061224 + #2 [ffffa2bfc9ec3bb8] schedule_preempt_disabled at ffffffffa80615ee + #3 [ffffa2bfc9ec3bc8] __mutex_lock at ffffffffa8062fd7 + #4 [ffffa2bfc9ec3c40] __mutex_lock_slowpath at ffffffffa80631d3 + #5 [ffffa2bfc9ec3c50] mutex_lock at ffffffffa806320c + #6 [ffffa2bfc9ec3c68] target_free_device at ffffffffc0935998 [target_core_mod] + #7 [ffffa2bfc9ec3c90] target_core_dev_release at ffffffffc092f975 [target_core_mod] + #8 [ffffa2bfc9ec3ca0] config_item_put at ffffffffa79d250f + #9 [ffffa2bfc9ec3cd0] config_item_put at ffffffffa79d2583 + #10 [ffffa2bfc9ec3ce0] target_devices_idr_iter at ffffffffc0933f3a [target_core_mod] + #11 [ffffa2bfc9ec3d00] idr_for_each at ffffffffa803f6fc + #12 [ffffa2bfc9ec3d60] target_for_each_device at ffffffffc0935670 [target_core_mod] + #13 [ffffa2bfc9ec3d98] transport_deregister_session at ffffffffc0946408 [target_core_mod] + #14 [ffffa2bfc9ec3dc8] iscsit_close_session at ffffffffc09a44a6 [iscsi_target_mod] + #15 [ffffa2bfc9ec3df0] iscsit_close_connection at ffffffffc09a4a88 [iscsi_target_mod] + #16 [ffffa2bfc9ec3df8] finish_task_switch at ffffffffa76e5d07 + #17 [ffffa2bfc9ec3e78] iscsit_take_action_for_connection_exit at ffffffffc0991c23 [iscsi_target_mod] + #18 [ffffa2bfc9ec3ea0] iscsi_target_tx_thread at ffffffffc09a403b [iscsi_target_mod] + #19 [ffffa2bfc9ec3f08] kthread at ffffffffa76d8080 + #20 [ffffa2bfc9ec3f50] ret_from_fork at ffffffffa8200364 + +Fixes: 36d4cb460bcb ("scsi: target: Avoid that EXTENDED COPY commands trigger lock inversion") +Signed-off-by: Junxiao Bi +Link: https://lore.kernel.org/r/20230918225848.66463-1-junxiao.bi@oracle.com +Reviewed-by: Mike Christie +Signed-off-by: Martin K. Petersen +Signed-off-by: Sasha Levin +--- + drivers/target/target_core_device.c | 11 ++++------- + 1 file changed, 4 insertions(+), 7 deletions(-) + +diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c +index d21f88de197c7..301fe376a1206 100644 +--- a/drivers/target/target_core_device.c ++++ b/drivers/target/target_core_device.c +@@ -883,7 +883,6 @@ sector_t target_to_linux_sector(struct se_device *dev, sector_t lb) + EXPORT_SYMBOL(target_to_linux_sector); + + struct devices_idr_iter { +- struct config_item *prev_item; + int (*fn)(struct se_device *dev, void *data); + void *data; + }; +@@ -893,11 +892,9 @@ static int target_devices_idr_iter(int id, void *p, void *data) + { + struct devices_idr_iter *iter = data; + struct se_device *dev = p; ++ struct config_item *item; + int ret; + +- config_item_put(iter->prev_item); +- iter->prev_item = NULL; +- + /* + * We add the device early to the idr, so it can be used + * by backend modules during configuration. We do not want +@@ -907,12 +904,13 @@ static int target_devices_idr_iter(int id, void *p, void *data) + if (!target_dev_configured(dev)) + return 0; + +- iter->prev_item = config_item_get_unless_zero(&dev->dev_group.cg_item); +- if (!iter->prev_item) ++ item = config_item_get_unless_zero(&dev->dev_group.cg_item); ++ if (!item) + return 0; + mutex_unlock(&device_mutex); + + ret = iter->fn(dev, iter->data); ++ config_item_put(item); + + mutex_lock(&device_mutex); + return ret; +@@ -935,7 +933,6 @@ int target_for_each_device(int (*fn)(struct se_device *dev, void *data), + mutex_lock(&device_mutex); + ret = idr_for_each(&devices_idr, target_devices_idr_iter, &iter); + mutex_unlock(&device_mutex); +- config_item_put(iter.prev_item); + return ret; + } + +-- +2.40.1 + diff --git a/queue-6.1/sctp-update-hb-timer-immediately-after-users-change-.patch b/queue-6.1/sctp-update-hb-timer-immediately-after-users-change-.patch new file mode 100644 index 00000000000..dae6335b528 --- /dev/null +++ b/queue-6.1/sctp-update-hb-timer-immediately-after-users-change-.patch @@ -0,0 +1,48 @@ +From 93aea21e9fa074adcf5f908d5b993aaf3435e83f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Oct 2023 11:04:20 -0400 +Subject: sctp: update hb timer immediately after users change hb_interval + +From: Xin Long + +[ Upstream commit 1f4e803cd9c9166eb8b6c8b0b8e4124f7499fc07 ] + +Currently, when hb_interval is changed by users, it won't take effect +until the next expiry of hb timer. As the default value is 30s, users +have to wait up to 30s to wait its hb_interval update to work. + +This becomes pretty bad in containers where a much smaller value is +usually set on hb_interval. This patch improves it by resetting the +hb timer immediately once the value of hb_interval is updated by users. + +Note that we don't address the already existing 'problem' when sending +a heartbeat 'on demand' if one hb has just been sent(from the timer) +mentioned in: + + https://www.mail-archive.com/linux-kernel@vger.kernel.org/msg590224.html + +Signed-off-by: Xin Long +Reviewed-by: Simon Horman +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Link: https://lore.kernel.org/r/75465785f8ee5df2fb3acdca9b8fafdc18984098.1696172660.git.lucien.xin@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/socket.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/net/sctp/socket.c b/net/sctp/socket.c +index 32e3669adf146..e25dc17091311 100644 +--- a/net/sctp/socket.c ++++ b/net/sctp/socket.c +@@ -2449,6 +2449,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, + if (trans) { + trans->hbinterval = + msecs_to_jiffies(params->spp_hbinterval); ++ sctp_transport_reset_hb_timer(trans); + } else if (asoc) { + asoc->hbinterval = + msecs_to_jiffies(params->spp_hbinterval); +-- +2.40.1 + diff --git a/queue-6.1/sctp-update-transport-state-when-processing-a-dupcoo.patch b/queue-6.1/sctp-update-transport-state-when-processing-a-dupcoo.patch new file mode 100644 index 00000000000..42ea7dab9ee --- /dev/null +++ b/queue-6.1/sctp-update-transport-state-when-processing-a-dupcoo.patch @@ -0,0 +1,67 @@ +From 373f722c1018632ca6c1853bd4c3c5f31ec28878 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Oct 2023 10:58:45 -0400 +Subject: sctp: update transport state when processing a dupcook packet + +From: Xin Long + +[ Upstream commit 2222a78075f0c19ca18db53fd6623afb4aff602d ] + +During the 4-way handshake, the transport's state is set to ACTIVE in +sctp_process_init() when processing INIT_ACK chunk on client or +COOKIE_ECHO chunk on server. + +In the collision scenario below: + + 192.168.1.2 > 192.168.1.1: sctp (1) [INIT] [init tag: 3922216408] + 192.168.1.1 > 192.168.1.2: sctp (1) [INIT] [init tag: 144230885] + 192.168.1.2 > 192.168.1.1: sctp (1) [INIT ACK] [init tag: 3922216408] + 192.168.1.1 > 192.168.1.2: sctp (1) [COOKIE ECHO] + 192.168.1.2 > 192.168.1.1: sctp (1) [COOKIE ACK] + 192.168.1.1 > 192.168.1.2: sctp (1) [INIT ACK] [init tag: 3914796021] + +when processing COOKIE_ECHO on 192.168.1.2, as it's in COOKIE_WAIT state, +sctp_sf_do_dupcook_b() is called by sctp_sf_do_5_2_4_dupcook() where it +creates a new association and sets its transport to ACTIVE then updates +to the old association in sctp_assoc_update(). + +However, in sctp_assoc_update(), it will skip the transport update if it +finds a transport with the same ipaddr already existing in the old asoc, +and this causes the old asoc's transport state not to move to ACTIVE +after the handshake. + +This means if DATA retransmission happens at this moment, it won't be able +to enter PF state because of the check 'transport->state == SCTP_ACTIVE' +in sctp_do_8_2_transport_strike(). + +This patch fixes it by updating the transport in sctp_assoc_update() with +sctp_assoc_add_peer() where it updates the transport state if there is +already a transport with the same ipaddr exists in the old asoc. + +Signed-off-by: Xin Long +Reviewed-by: Simon Horman +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Link: https://lore.kernel.org/r/fd17356abe49713ded425250cc1ae51e9f5846c6.1696172325.git.lucien.xin@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/sctp/associola.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/net/sctp/associola.c b/net/sctp/associola.c +index 3460abceba443..2965a12fe8aa2 100644 +--- a/net/sctp/associola.c ++++ b/net/sctp/associola.c +@@ -1161,8 +1161,7 @@ int sctp_assoc_update(struct sctp_association *asoc, + /* Add any peer addresses from the new association. */ + list_for_each_entry(trans, &new->peer.transport_addr_list, + transports) +- if (!sctp_assoc_lookup_paddr(asoc, &trans->ipaddr) && +- !sctp_assoc_add_peer(asoc, &trans->ipaddr, ++ if (!sctp_assoc_add_peer(asoc, &trans->ipaddr, + GFP_ATOMIC, trans->state)) + return -ENOMEM; + +-- +2.40.1 + diff --git a/queue-6.1/selftests-netfilter-extend-nft_audit.sh.patch b/queue-6.1/selftests-netfilter-extend-nft_audit.sh.patch new file mode 100644 index 00000000000..3978fc820be --- /dev/null +++ b/queue-6.1/selftests-netfilter-extend-nft_audit.sh.patch @@ -0,0 +1,171 @@ +From df7ed112a553d8cf389514338223df00770ae024 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 23 Sep 2023 03:53:49 +0200 +Subject: selftests: netfilter: Extend nft_audit.sh + +From: Phil Sutter + +[ Upstream commit 203bb9d39866d3c5a8135433ce3742fe4f9d5741 ] + +Add tests for sets and elements and deletion of all kinds. Also +reorder rule reset tests: By moving the bulk rule add command up, the +two 'reset rules' tests become identical. + +While at it, fix for a failing bulk rule add test's error status getting +lost due to its use in a pipe. Avoid this by using a temporary file. + +Headings in diff output for failing tests contain no useful data, strip +them. + +Signed-off-by: Phil Sutter +Signed-off-by: Florian Westphal +Stable-dep-of: 0d880dc6f032 ("netfilter: nf_tables: Deduplicate nft_register_obj audit logs") +Signed-off-by: Sasha Levin +--- + .../testing/selftests/netfilter/nft_audit.sh | 97 ++++++++++++++++--- + 1 file changed, 81 insertions(+), 16 deletions(-) + +diff --git a/tools/testing/selftests/netfilter/nft_audit.sh b/tools/testing/selftests/netfilter/nft_audit.sh +index 83c271b1c7352..0b3255e7b3538 100755 +--- a/tools/testing/selftests/netfilter/nft_audit.sh ++++ b/tools/testing/selftests/netfilter/nft_audit.sh +@@ -12,10 +12,11 @@ nft --version >/dev/null 2>&1 || { + } + + logfile=$(mktemp) ++rulefile=$(mktemp) + echo "logging into $logfile" + ./audit_logread >"$logfile" & + logread_pid=$! +-trap 'kill $logread_pid; rm -f $logfile' EXIT ++trap 'kill $logread_pid; rm -f $logfile $rulefile' EXIT + exec 3<"$logfile" + + do_test() { # (cmd, log) +@@ -26,12 +27,14 @@ do_test() { # (cmd, log) + res=$(diff -a -u <(echo "$2") - <&3) + [ $? -eq 0 ] && { echo "OK"; return; } + echo "FAIL" +- echo "$res" +- ((RC++)) ++ grep -v '^\(---\|+++\|@@\)' <<< "$res" ++ ((RC--)) + } + + nft flush ruleset + ++# adding tables, chains and rules ++ + for table in t1 t2; do + do_test "nft add table $table" \ + "table=$table family=2 entries=1 op=nft_register_table" +@@ -62,6 +65,28 @@ for table in t1 t2; do + "table=$table family=2 entries=6 op=nft_register_rule" + done + ++for ((i = 0; i < 500; i++)); do ++ echo "add rule t2 c3 counter accept comment \"rule $i\"" ++done >$rulefile ++do_test "nft -f $rulefile" \ ++'table=t2 family=2 entries=500 op=nft_register_rule' ++ ++# adding sets and elements ++ ++settype='type inet_service; counter' ++setelem='{ 22, 80, 443 }' ++setblock="{ $settype; elements = $setelem; }" ++do_test "nft add set t1 s $setblock" \ ++"table=t1 family=2 entries=4 op=nft_register_set" ++ ++do_test "nft add set t1 s2 $setblock; add set t1 s3 { $settype; }" \ ++"table=t1 family=2 entries=5 op=nft_register_set" ++ ++do_test "nft add element t1 s3 $setelem" \ ++"table=t1 family=2 entries=3 op=nft_register_setelem" ++ ++# resetting rules ++ + do_test 'nft reset rules t1 c2' \ + 'table=t1 family=2 entries=3 op=nft_reset_rule' + +@@ -70,19 +95,6 @@ do_test 'nft reset rules table t1' \ + table=t1 family=2 entries=3 op=nft_reset_rule + table=t1 family=2 entries=3 op=nft_reset_rule' + +-do_test 'nft reset rules' \ +-'table=t1 family=2 entries=3 op=nft_reset_rule +-table=t1 family=2 entries=3 op=nft_reset_rule +-table=t1 family=2 entries=3 op=nft_reset_rule +-table=t2 family=2 entries=3 op=nft_reset_rule +-table=t2 family=2 entries=3 op=nft_reset_rule +-table=t2 family=2 entries=3 op=nft_reset_rule' +- +-for ((i = 0; i < 500; i++)); do +- echo "add rule t2 c3 counter accept comment \"rule $i\"" +-done | do_test 'nft -f -' \ +-'table=t2 family=2 entries=500 op=nft_register_rule' +- + do_test 'nft reset rules t2 c3' \ + 'table=t2 family=2 entries=189 op=nft_reset_rule + table=t2 family=2 entries=188 op=nft_reset_rule +@@ -105,4 +117,57 @@ table=t2 family=2 entries=180 op=nft_reset_rule + table=t2 family=2 entries=188 op=nft_reset_rule + table=t2 family=2 entries=135 op=nft_reset_rule' + ++# resetting sets and elements ++ ++elem=(22 ,80 ,443) ++relem="" ++for i in {1..3}; do ++ relem+="${elem[((i - 1))]}" ++ do_test "nft reset element t1 s { $relem }" \ ++ "table=t1 family=2 entries=$i op=nft_reset_setelem" ++done ++ ++do_test 'nft reset set t1 s' \ ++'table=t1 family=2 entries=3 op=nft_reset_setelem' ++ ++# deleting rules ++ ++readarray -t handles < <(nft -a list chain t1 c1 | \ ++ sed -n 's/.*counter.* handle \(.*\)$/\1/p') ++ ++do_test "nft delete rule t1 c1 handle ${handles[0]}" \ ++'table=t1 family=2 entries=1 op=nft_unregister_rule' ++ ++cmd='delete rule t1 c1 handle' ++do_test "nft $cmd ${handles[1]}; $cmd ${handles[2]}" \ ++'table=t1 family=2 entries=2 op=nft_unregister_rule' ++ ++do_test 'nft flush chain t1 c2' \ ++'table=t1 family=2 entries=3 op=nft_unregister_rule' ++ ++do_test 'nft flush table t2' \ ++'table=t2 family=2 entries=509 op=nft_unregister_rule' ++ ++# deleting chains ++ ++do_test 'nft delete chain t2 c2' \ ++'table=t2 family=2 entries=1 op=nft_unregister_chain' ++ ++# deleting sets and elements ++ ++do_test 'nft delete element t1 s { 22 }' \ ++'table=t1 family=2 entries=1 op=nft_unregister_setelem' ++ ++do_test 'nft delete element t1 s { 80, 443 }' \ ++'table=t1 family=2 entries=2 op=nft_unregister_setelem' ++ ++do_test 'nft flush set t1 s2' \ ++'table=t1 family=2 entries=3 op=nft_unregister_setelem' ++ ++do_test 'nft delete set t1 s2' \ ++'table=t1 family=2 entries=1 op=nft_unregister_set' ++ ++do_test 'nft delete set t1 s3' \ ++'table=t1 family=2 entries=1 op=nft_unregister_set' ++ + exit $RC +-- +2.40.1 + diff --git a/queue-6.1/selftests-netfilter-test-nf_tables-audit-logging.patch b/queue-6.1/selftests-netfilter-test-nf_tables-audit-logging.patch new file mode 100644 index 00000000000..ff588d88714 --- /dev/null +++ b/queue-6.1/selftests-netfilter-test-nf_tables-audit-logging.patch @@ -0,0 +1,352 @@ +From 04aa2c5ed0619a43a8fa3a7d8bd31d6013529bff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Sep 2023 15:51:37 +0200 +Subject: selftests: netfilter: Test nf_tables audit logging + +From: Phil Sutter + +[ Upstream commit e8dbde59ca3fe925d0105bfb380e8429928b16dd ] + +Compare NETFILTER_CFG type audit logs emitted from kernel upon ruleset +modifications against expected output. + +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +Stable-dep-of: 0d880dc6f032 ("netfilter: nf_tables: Deduplicate nft_register_obj audit logs") +Signed-off-by: Sasha Levin +--- + tools/testing/selftests/netfilter/.gitignore | 1 + + tools/testing/selftests/netfilter/Makefile | 4 +- + .../selftests/netfilter/audit_logread.c | 165 ++++++++++++++++++ + tools/testing/selftests/netfilter/config | 1 + + .../testing/selftests/netfilter/nft_audit.sh | 108 ++++++++++++ + 5 files changed, 277 insertions(+), 2 deletions(-) + create mode 100644 tools/testing/selftests/netfilter/audit_logread.c + create mode 100755 tools/testing/selftests/netfilter/nft_audit.sh + +diff --git a/tools/testing/selftests/netfilter/.gitignore b/tools/testing/selftests/netfilter/.gitignore +index 4cb887b574138..4b2928e1c19d8 100644 +--- a/tools/testing/selftests/netfilter/.gitignore ++++ b/tools/testing/selftests/netfilter/.gitignore +@@ -1,3 +1,4 @@ + # SPDX-License-Identifier: GPL-2.0-only + nf-queue + connect_close ++audit_logread +diff --git a/tools/testing/selftests/netfilter/Makefile b/tools/testing/selftests/netfilter/Makefile +index 3686bfa6c58d7..321db8850da00 100644 +--- a/tools/testing/selftests/netfilter/Makefile ++++ b/tools/testing/selftests/netfilter/Makefile +@@ -6,13 +6,13 @@ TEST_PROGS := nft_trans_stress.sh nft_fib.sh nft_nat.sh bridge_brouter.sh \ + nft_concat_range.sh nft_conntrack_helper.sh \ + nft_queue.sh nft_meta.sh nf_nat_edemux.sh \ + ipip-conntrack-mtu.sh conntrack_tcp_unreplied.sh \ +- conntrack_vrf.sh nft_synproxy.sh rpath.sh ++ conntrack_vrf.sh nft_synproxy.sh rpath.sh nft_audit.sh + + HOSTPKG_CONFIG := pkg-config + + CFLAGS += $(shell $(HOSTPKG_CONFIG) --cflags libmnl 2>/dev/null) + LDLIBS += $(shell $(HOSTPKG_CONFIG) --libs libmnl 2>/dev/null || echo -lmnl) + +-TEST_GEN_FILES = nf-queue connect_close ++TEST_GEN_FILES = nf-queue connect_close audit_logread + + include ../lib.mk +diff --git a/tools/testing/selftests/netfilter/audit_logread.c b/tools/testing/selftests/netfilter/audit_logread.c +new file mode 100644 +index 0000000000000..a0a880fc2d9de +--- /dev/null ++++ b/tools/testing/selftests/netfilter/audit_logread.c +@@ -0,0 +1,165 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#define _GNU_SOURCE ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++static int fd; ++ ++#define MAX_AUDIT_MESSAGE_LENGTH 8970 ++struct audit_message { ++ struct nlmsghdr nlh; ++ union { ++ struct audit_status s; ++ char data[MAX_AUDIT_MESSAGE_LENGTH]; ++ } u; ++}; ++ ++int audit_recv(int fd, struct audit_message *rep) ++{ ++ struct sockaddr_nl addr; ++ socklen_t addrlen = sizeof(addr); ++ int ret; ++ ++ do { ++ ret = recvfrom(fd, rep, sizeof(*rep), 0, ++ (struct sockaddr *)&addr, &addrlen); ++ } while (ret < 0 && errno == EINTR); ++ ++ if (ret < 0 || ++ addrlen != sizeof(addr) || ++ addr.nl_pid != 0 || ++ rep->nlh.nlmsg_type == NLMSG_ERROR) /* short-cut for now */ ++ return -1; ++ ++ return ret; ++} ++ ++int audit_send(int fd, uint16_t type, uint32_t key, uint32_t val) ++{ ++ static int seq = 0; ++ struct audit_message msg = { ++ .nlh = { ++ .nlmsg_len = NLMSG_SPACE(sizeof(msg.u.s)), ++ .nlmsg_type = type, ++ .nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK, ++ .nlmsg_seq = ++seq, ++ }, ++ .u.s = { ++ .mask = key, ++ .enabled = key == AUDIT_STATUS_ENABLED ? val : 0, ++ .pid = key == AUDIT_STATUS_PID ? val : 0, ++ } ++ }; ++ struct sockaddr_nl addr = { ++ .nl_family = AF_NETLINK, ++ }; ++ int ret; ++ ++ do { ++ ret = sendto(fd, &msg, msg.nlh.nlmsg_len, 0, ++ (struct sockaddr *)&addr, sizeof(addr)); ++ } while (ret < 0 && errno == EINTR); ++ ++ if (ret != (int)msg.nlh.nlmsg_len) ++ return -1; ++ return 0; ++} ++ ++int audit_set(int fd, uint32_t key, uint32_t val) ++{ ++ struct audit_message rep = { 0 }; ++ int ret; ++ ++ ret = audit_send(fd, AUDIT_SET, key, val); ++ if (ret) ++ return ret; ++ ++ ret = audit_recv(fd, &rep); ++ if (ret < 0) ++ return ret; ++ return 0; ++} ++ ++int readlog(int fd) ++{ ++ struct audit_message rep = { 0 }; ++ int ret = audit_recv(fd, &rep); ++ const char *sep = ""; ++ char *k, *v; ++ ++ if (ret < 0) ++ return ret; ++ ++ if (rep.nlh.nlmsg_type != AUDIT_NETFILTER_CFG) ++ return 0; ++ ++ /* skip the initial "audit(...): " part */ ++ strtok(rep.u.data, " "); ++ ++ while ((k = strtok(NULL, "="))) { ++ v = strtok(NULL, " "); ++ ++ /* these vary and/or are uninteresting, ignore */ ++ if (!strcmp(k, "pid") || ++ !strcmp(k, "comm") || ++ !strcmp(k, "subj")) ++ continue; ++ ++ /* strip the varying sequence number */ ++ if (!strcmp(k, "table")) ++ *strchrnul(v, ':') = '\0'; ++ ++ printf("%s%s=%s", sep, k, v); ++ sep = " "; ++ } ++ if (*sep) { ++ printf("\n"); ++ fflush(stdout); ++ } ++ return 0; ++} ++ ++void cleanup(int sig) ++{ ++ audit_set(fd, AUDIT_STATUS_ENABLED, 0); ++ close(fd); ++ if (sig) ++ exit(0); ++} ++ ++int main(int argc, char **argv) ++{ ++ struct sigaction act = { ++ .sa_handler = cleanup, ++ }; ++ ++ fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_AUDIT); ++ if (fd < 0) { ++ perror("Can't open netlink socket"); ++ return -1; ++ } ++ ++ if (sigaction(SIGTERM, &act, NULL) < 0 || ++ sigaction(SIGINT, &act, NULL) < 0) { ++ perror("Can't set signal handler"); ++ close(fd); ++ return -1; ++ } ++ ++ audit_set(fd, AUDIT_STATUS_ENABLED, 1); ++ audit_set(fd, AUDIT_STATUS_PID, getpid()); ++ ++ while (1) ++ readlog(fd); ++} +diff --git a/tools/testing/selftests/netfilter/config b/tools/testing/selftests/netfilter/config +index 4faf2ce021d90..7c42b1b2c69b4 100644 +--- a/tools/testing/selftests/netfilter/config ++++ b/tools/testing/selftests/netfilter/config +@@ -6,3 +6,4 @@ CONFIG_NFT_REDIR=m + CONFIG_NFT_MASQ=m + CONFIG_NFT_FLOW_OFFLOAD=m + CONFIG_NF_CT_NETLINK=m ++CONFIG_AUDIT=y +diff --git a/tools/testing/selftests/netfilter/nft_audit.sh b/tools/testing/selftests/netfilter/nft_audit.sh +new file mode 100755 +index 0000000000000..83c271b1c7352 +--- /dev/null ++++ b/tools/testing/selftests/netfilter/nft_audit.sh +@@ -0,0 +1,108 @@ ++#!/bin/bash ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Check that audit logs generated for nft commands are as expected. ++ ++SKIP_RC=4 ++RC=0 ++ ++nft --version >/dev/null 2>&1 || { ++ echo "SKIP: missing nft tool" ++ exit $SKIP_RC ++} ++ ++logfile=$(mktemp) ++echo "logging into $logfile" ++./audit_logread >"$logfile" & ++logread_pid=$! ++trap 'kill $logread_pid; rm -f $logfile' EXIT ++exec 3<"$logfile" ++ ++do_test() { # (cmd, log) ++ echo -n "testing for cmd: $1 ... " ++ cat <&3 >/dev/null ++ $1 >/dev/null || exit 1 ++ sleep 0.1 ++ res=$(diff -a -u <(echo "$2") - <&3) ++ [ $? -eq 0 ] && { echo "OK"; return; } ++ echo "FAIL" ++ echo "$res" ++ ((RC++)) ++} ++ ++nft flush ruleset ++ ++for table in t1 t2; do ++ do_test "nft add table $table" \ ++ "table=$table family=2 entries=1 op=nft_register_table" ++ ++ do_test "nft add chain $table c1" \ ++ "table=$table family=2 entries=1 op=nft_register_chain" ++ ++ do_test "nft add chain $table c2; add chain $table c3" \ ++ "table=$table family=2 entries=2 op=nft_register_chain" ++ ++ cmd="add rule $table c1 counter" ++ ++ do_test "nft $cmd" \ ++ "table=$table family=2 entries=1 op=nft_register_rule" ++ ++ do_test "nft $cmd; $cmd" \ ++ "table=$table family=2 entries=2 op=nft_register_rule" ++ ++ cmd="" ++ sep="" ++ for chain in c2 c3; do ++ for i in {1..3}; do ++ cmd+="$sep add rule $table $chain counter" ++ sep=";" ++ done ++ done ++ do_test "nft $cmd" \ ++ "table=$table family=2 entries=6 op=nft_register_rule" ++done ++ ++do_test 'nft reset rules t1 c2' \ ++'table=t1 family=2 entries=3 op=nft_reset_rule' ++ ++do_test 'nft reset rules table t1' \ ++'table=t1 family=2 entries=3 op=nft_reset_rule ++table=t1 family=2 entries=3 op=nft_reset_rule ++table=t1 family=2 entries=3 op=nft_reset_rule' ++ ++do_test 'nft reset rules' \ ++'table=t1 family=2 entries=3 op=nft_reset_rule ++table=t1 family=2 entries=3 op=nft_reset_rule ++table=t1 family=2 entries=3 op=nft_reset_rule ++table=t2 family=2 entries=3 op=nft_reset_rule ++table=t2 family=2 entries=3 op=nft_reset_rule ++table=t2 family=2 entries=3 op=nft_reset_rule' ++ ++for ((i = 0; i < 500; i++)); do ++ echo "add rule t2 c3 counter accept comment \"rule $i\"" ++done | do_test 'nft -f -' \ ++'table=t2 family=2 entries=500 op=nft_register_rule' ++ ++do_test 'nft reset rules t2 c3' \ ++'table=t2 family=2 entries=189 op=nft_reset_rule ++table=t2 family=2 entries=188 op=nft_reset_rule ++table=t2 family=2 entries=126 op=nft_reset_rule' ++ ++do_test 'nft reset rules t2' \ ++'table=t2 family=2 entries=3 op=nft_reset_rule ++table=t2 family=2 entries=3 op=nft_reset_rule ++table=t2 family=2 entries=186 op=nft_reset_rule ++table=t2 family=2 entries=188 op=nft_reset_rule ++table=t2 family=2 entries=129 op=nft_reset_rule' ++ ++do_test 'nft reset rules' \ ++'table=t1 family=2 entries=3 op=nft_reset_rule ++table=t1 family=2 entries=3 op=nft_reset_rule ++table=t1 family=2 entries=3 op=nft_reset_rule ++table=t2 family=2 entries=3 op=nft_reset_rule ++table=t2 family=2 entries=3 op=nft_reset_rule ++table=t2 family=2 entries=180 op=nft_reset_rule ++table=t2 family=2 entries=188 op=nft_reset_rule ++table=t2 family=2 entries=135 op=nft_reset_rule' ++ ++exit $RC +-- +2.40.1 + diff --git a/queue-6.1/series b/queue-6.1/series index de781467fb0..88522b59be2 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -54,3 +54,68 @@ block-fix-use-after-free-of-q-q_usage_counter.patch hwmon-nzxt-smart2-add-device-id.patch hwmon-nzxt-smart2-add-another-usb-id.patch i40e-fix-the-wrong-ptp-frequency-calculation.patch +hid-sony-fix-a-potential-memory-leak-in-sony_probe.patch +ubi-refuse-attaching-if-mtd-s-erasesize-is-0.patch +erofs-fix-memory-leak-of-lzma-global-compressed-dedu.patch +wifi-iwlwifi-dbg_ini-fix-structure-packing.patch +wifi-iwlwifi-mvm-fix-a-memory-corruption-issue.patch +wifi-cfg80211-hold-wiphy-lock-in-auto-disconnect.patch +wifi-cfg80211-move-wowlan-disable-under-locks.patch +wifi-cfg80211-add-a-work-abstraction-with-special-se.patch +wifi-cfg80211-fix-cqm_config-access-race.patch +wifi-cfg80211-add-missing-kernel-doc-for-cqm_rssi_wo.patch +wifi-mwifiex-fix-oob-check-condition-in-mwifiex_proc.patch +leds-drop-bug_on-check-for-led_color_id_multi.patch +bpf-fix-tr-dereferencing.patch +regulator-mt6358-drop-_sshub-regulators.patch +regulator-mt6358-use-linear-voltage-helpers-for-sing.patch +regulator-mt6358-split-ops-for-buck-and-linear-range.patch +bluetooth-delete-unused-hci_req_prepare_suspend-decl.patch +bluetooth-iso-fix-handling-of-listen-for-unicast.patch +drivers-net-process-the-result-of-hdlc_open-and-add-.patch +wifi-mt76-mt76x02-fix-mt76x0-external-lna-gain-handl.patch +perf-x86-amd-core-fix-overflow-reset-on-hotplug.patch +regmap-rbtree-fix-wrong-register-marked-as-in-cache-.patch +wifi-mac80211-fix-potential-key-use-after-free.patch +perf-x86-amd-do-not-warn-on-every-irq.patch +iommu-mediatek-fix-share-pgtable-for-iova-over-4gb.patch +regulator-core-regulator_register-set-device-class-e.patch +ima-finish-deprecation-of-ima_trusted_keyring-kconfi.patch +scsi-target-core-fix-deadlock-due-to-recursive-locki.patch +ima-rework-config_ima-dependency-block.patch +nfsv4-fix-a-nfs4_state_manager-race.patch +bpf-tcp_read_skb-needs-to-pop-skb-regardless-of-seq.patch +bpf-sockmap-do-not-inc-copied_seq-when-peek-flag-set.patch +bpf-sockmap-reject-sk_msg-egress-redirects-to-non-tc.patch +modpost-add-missing-else-to-the-of-check.patch +net-fix-possible-store-tearing-in-neigh_periodic_wor.patch +bpf-add-bpf_fib_lookup_skip_neigh-for-bpf_fib_lookup.patch +neighbour-annotate-lockless-accesses-to-n-nud_state.patch +neighbour-switch-to-standard-rcu-instead-of-rcu_bh.patch +neighbour-fix-data-races-around-n-output.patch +ipv4-ipv6-fix-handling-of-transhdrlen-in-__ip-6-_app.patch +ptp-ocp-fix-error-handling-in-ptp_ocp_device_init.patch +net-dsa-mv88e6xxx-avoid-eeprom-timeout-when-eeprom-i.patch +ipv6-tcp-add-a-missing-nf_reset_ct-in-3whs-handling.patch +net-usb-smsc75xx-fix-uninit-value-access-in-__smsc75.patch +net-nfc-llcp-add-lock-when-modifying-device-list.patch +net-ethernet-ti-am65-cpsw-fix-error-code-in-am65_cps.patch +ibmveth-remove-condition-to-recompute-tcp-header-che.patch +netfilter-handle-the-connecting-collision-properly-i.patch +selftests-netfilter-test-nf_tables-audit-logging.patch +selftests-netfilter-extend-nft_audit.sh.patch +netfilter-nf_tables-deduplicate-nft_register_obj-aud.patch +netfilter-nf_tables-nft_set_rbtree-fix-spurious-inse.patch +ipv4-set-offload_failed-flag-in-fibmatch-results.patch +net-stmmac-dwmac-stm32-fix-resume-on-stm32-mcu.patch +tipc-fix-a-potential-deadlock-on-tx-lock.patch +tcp-fix-quick-ack-counting-to-count-actual-acks-of-n.patch +tcp-fix-delayed-acks-for-mss-boundary-condition.patch +sctp-update-transport-state-when-processing-a-dupcoo.patch +sctp-update-hb-timer-immediately-after-users-change-.patch +netlink-split-up-copies-in-the-ack-construction.patch +netlink-fix-potential-skb-memleak-in-netlink_ack.patch +netlink-annotate-data-races-around-sk-sk_err.patch +hid-sony-remove-duplicate-null-check-before-calling-.patch +hid-intel-ish-hid-ipc-disable-and-reenable-acpi-gpe-.patch +intel_idle-add-emerald-rapids-xeon-support.patch diff --git a/queue-6.1/tcp-fix-delayed-acks-for-mss-boundary-condition.patch b/queue-6.1/tcp-fix-delayed-acks-for-mss-boundary-condition.patch new file mode 100644 index 00000000000..c0381c69879 --- /dev/null +++ b/queue-6.1/tcp-fix-delayed-acks-for-mss-boundary-condition.patch @@ -0,0 +1,99 @@ +From 161aba22ed911cc65a6e09508dda5e962825afac Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Oct 2023 11:12:39 -0400 +Subject: tcp: fix delayed ACKs for MSS boundary condition + +From: Neal Cardwell + +[ Upstream commit 4720852ed9afb1c5ab84e96135cb5b73d5afde6f ] + +This commit fixes poor delayed ACK behavior that can cause poor TCP +latency in a particular boundary condition: when an application makes +a TCP socket write that is an exact multiple of the MSS size. + +The problem is that there is painful boundary discontinuity in the +current delayed ACK behavior. With the current delayed ACK behavior, +we have: + +(1) If an app reads data when > 1*MSS is unacknowledged, then + tcp_cleanup_rbuf() ACKs immediately because of: + + tp->rcv_nxt - tp->rcv_wup > icsk->icsk_ack.rcv_mss || + +(2) If an app reads all received data, and the packets were < 1*MSS, + and either (a) the app is not ping-pong or (b) we received two + packets < 1*MSS, then tcp_cleanup_rbuf() ACKs immediately beecause + of: + + ((icsk->icsk_ack.pending & ICSK_ACK_PUSHED2) || + ((icsk->icsk_ack.pending & ICSK_ACK_PUSHED) && + !inet_csk_in_pingpong_mode(sk))) && + +(3) *However*: if an app reads exactly 1*MSS of data, + tcp_cleanup_rbuf() does not send an immediate ACK. This is true + even if the app is not ping-pong and the 1*MSS of data had the PSH + bit set, suggesting the sending application completed an + application write. + +Thus if the app is not ping-pong, we have this painful case where +>1*MSS gets an immediate ACK, and <1*MSS gets an immediate ACK, but a +write whose last skb is an exact multiple of 1*MSS can get a 40ms +delayed ACK. This means that any app that transfers data in one +direction and takes care to align write size or packet size with MSS +can suffer this problem. With receive zero copy making 4KB MSS values +more common, it is becoming more common to have application writes +naturally align with MSS, and more applications are likely to +encounter this delayed ACK problem. + +The fix in this commit is to refine the delayed ACK heuristics with a +simple check: immediately ACK a received 1*MSS skb with PSH bit set if +the app reads all data. Why? If an skb has a len of exactly 1*MSS and +has the PSH bit set then it is likely the end of an application +write. So more data may not be arriving soon, and yet the data sender +may be waiting for an ACK if cwnd-bound or using TX zero copy. Thus we +set ICSK_ACK_PUSHED in this case so that tcp_cleanup_rbuf() will send +an ACK immediately if the app reads all of the data and is not +ping-pong. Note that this logic is also executed for the case where +len > MSS, but in that case this logic does not matter (and does not +hurt) because tcp_cleanup_rbuf() will always ACK immediately if the +app reads data and there is more than an MSS of unACKed data. + +Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") +Signed-off-by: Neal Cardwell +Reviewed-by: Yuchung Cheng +Reviewed-by: Eric Dumazet +Cc: Xin Guo +Link: https://lore.kernel.org/r/20231001151239.1866845-2-ncardwell.sw@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_input.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index c697836f2b5b4..068221e742425 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -243,6 +243,19 @@ static void tcp_measure_rcv_mss(struct sock *sk, const struct sk_buff *skb) + if (unlikely(len > icsk->icsk_ack.rcv_mss + + MAX_TCP_OPTION_SPACE)) + tcp_gro_dev_warn(sk, skb, len); ++ /* If the skb has a len of exactly 1*MSS and has the PSH bit ++ * set then it is likely the end of an application write. So ++ * more data may not be arriving soon, and yet the data sender ++ * may be waiting for an ACK if cwnd-bound or using TX zero ++ * copy. So we set ICSK_ACK_PUSHED here so that ++ * tcp_cleanup_rbuf() will send an ACK immediately if the app ++ * reads all of the data and is not ping-pong. If len > MSS ++ * then this logic does not matter (and does not hurt) because ++ * tcp_cleanup_rbuf() will always ACK immediately if the app ++ * reads data and there is more than an MSS of unACKed data. ++ */ ++ if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_PSH) ++ icsk->icsk_ack.pending |= ICSK_ACK_PUSHED; + } else { + /* Otherwise, we make more careful check taking into account, + * that SACKs block is variable. +-- +2.40.1 + diff --git a/queue-6.1/tcp-fix-quick-ack-counting-to-count-actual-acks-of-n.patch b/queue-6.1/tcp-fix-quick-ack-counting-to-count-actual-acks-of-n.patch new file mode 100644 index 00000000000..61daa479be3 --- /dev/null +++ b/queue-6.1/tcp-fix-quick-ack-counting-to-count-actual-acks-of-n.patch @@ -0,0 +1,102 @@ +From be5ded608328576a379fe15c434d70df65dd6629 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 1 Oct 2023 11:12:38 -0400 +Subject: tcp: fix quick-ack counting to count actual ACKs of new data + +From: Neal Cardwell + +[ Upstream commit 059217c18be6757b95bfd77ba53fb50b48b8a816 ] + +This commit fixes quick-ack counting so that it only considers that a +quick-ack has been provided if we are sending an ACK that newly +acknowledges data. + +The code was erroneously using the number of data segments in outgoing +skbs when deciding how many quick-ack credits to remove. This logic +does not make sense, and could cause poor performance in +request-response workloads, like RPC traffic, where requests or +responses can be multi-segment skbs. + +When a TCP connection decides to send N quick-acks, that is to +accelerate the cwnd growth of the congestion control module +controlling the remote endpoint of the TCP connection. That quick-ack +decision is purely about the incoming data and outgoing ACKs. It has +nothing to do with the outgoing data or the size of outgoing data. + +And in particular, an ACK only serves the intended purpose of allowing +the remote congestion control to grow the congestion window quickly if +the ACK is ACKing or SACKing new data. + +The fix is simple: only count packets as serving the goal of the +quickack mechanism if they are ACKing/SACKing new data. We can tell +whether this is the case by checking inet_csk_ack_scheduled(), since +we schedule an ACK exactly when we are ACKing/SACKing new data. + +Fixes: fc6415bcb0f5 ("[TCP]: Fix quick-ack decrementing with TSO.") +Signed-off-by: Neal Cardwell +Reviewed-by: Yuchung Cheng +Reviewed-by: Eric Dumazet +Link: https://lore.kernel.org/r/20231001151239.1866845-1-ncardwell.sw@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + include/net/tcp.h | 6 ++++-- + net/ipv4/tcp_output.c | 7 +++---- + 2 files changed, 7 insertions(+), 6 deletions(-) + +diff --git a/include/net/tcp.h b/include/net/tcp.h +index 5fd69f2342a44..9ebb54122bb71 100644 +--- a/include/net/tcp.h ++++ b/include/net/tcp.h +@@ -355,12 +355,14 @@ ssize_t tcp_splice_read(struct socket *sk, loff_t *ppos, + struct sk_buff *tcp_stream_alloc_skb(struct sock *sk, int size, gfp_t gfp, + bool force_schedule); + +-static inline void tcp_dec_quickack_mode(struct sock *sk, +- const unsigned int pkts) ++static inline void tcp_dec_quickack_mode(struct sock *sk) + { + struct inet_connection_sock *icsk = inet_csk(sk); + + if (icsk->icsk_ack.quick) { ++ /* How many ACKs S/ACKing new data have we sent? */ ++ const unsigned int pkts = inet_csk_ack_scheduled(sk) ? 1 : 0; ++ + if (pkts >= icsk->icsk_ack.quick) { + icsk->icsk_ack.quick = 0; + /* Leaving quickack mode we deflate ATO. */ +diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c +index dc3166e56169f..5921b0f6f9f41 100644 +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -177,8 +177,7 @@ static void tcp_event_data_sent(struct tcp_sock *tp, + } + + /* Account for an ACK we sent. */ +-static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts, +- u32 rcv_nxt) ++static inline void tcp_event_ack_sent(struct sock *sk, u32 rcv_nxt) + { + struct tcp_sock *tp = tcp_sk(sk); + +@@ -192,7 +191,7 @@ static inline void tcp_event_ack_sent(struct sock *sk, unsigned int pkts, + + if (unlikely(rcv_nxt != tp->rcv_nxt)) + return; /* Special ACK sent by DCTCP to reflect ECN */ +- tcp_dec_quickack_mode(sk, pkts); ++ tcp_dec_quickack_mode(sk); + inet_csk_clear_xmit_timer(sk, ICSK_TIME_DACK); + } + +@@ -1373,7 +1372,7 @@ static int __tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, + sk, skb); + + if (likely(tcb->tcp_flags & TCPHDR_ACK)) +- tcp_event_ack_sent(sk, tcp_skb_pcount(skb), rcv_nxt); ++ tcp_event_ack_sent(sk, rcv_nxt); + + if (skb->len != tcp_header_size) { + tcp_event_data_sent(tp, sk); +-- +2.40.1 + diff --git a/queue-6.1/tipc-fix-a-potential-deadlock-on-tx-lock.patch b/queue-6.1/tipc-fix-a-potential-deadlock-on-tx-lock.patch new file mode 100644 index 00000000000..700181ffab2 --- /dev/null +++ b/queue-6.1/tipc-fix-a-potential-deadlock-on-tx-lock.patch @@ -0,0 +1,70 @@ +From 3ba9752c45507a0caccf3849323a7c936cf1d9c3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 27 Sep 2023 18:14:14 +0000 +Subject: tipc: fix a potential deadlock on &tx->lock + +From: Chengfeng Ye + +[ Upstream commit 08e50cf071847323414df0835109b6f3560d44f5 ] + +It seems that tipc_crypto_key_revoke() could be be invoked by +wokequeue tipc_crypto_work_rx() under process context and +timer/rx callback under softirq context, thus the lock acquisition +on &tx->lock seems better use spin_lock_bh() to prevent possible +deadlock. + +This flaw was found by an experimental static analysis tool I am +developing for irq-related deadlock. + +tipc_crypto_work_rx() +--> tipc_crypto_key_distr() +--> tipc_bcast_xmit() +--> tipc_bcbase_xmit() +--> tipc_bearer_bc_xmit() +--> tipc_crypto_xmit() +--> tipc_ehdr_build() +--> tipc_crypto_key_revoke() +--> spin_lock(&tx->lock) + + --> tipc_disc_timeout() + --> tipc_bearer_xmit_skb() + --> tipc_crypto_xmit() + --> tipc_ehdr_build() + --> tipc_crypto_key_revoke() + --> spin_lock(&tx->lock) + +Signed-off-by: Chengfeng Ye +Reviewed-by: Jacob Keller +Acked-by: Jon Maloy +Fixes: fc1b6d6de220 ("tipc: introduce TIPC encryption & authentication") +Link: https://lore.kernel.org/r/20230927181414.59928-1-dg573847474@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/tipc/crypto.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/net/tipc/crypto.c b/net/tipc/crypto.c +index 2b236d95a6469..65f59739a041a 100644 +--- a/net/tipc/crypto.c ++++ b/net/tipc/crypto.c +@@ -1441,14 +1441,14 @@ static int tipc_crypto_key_revoke(struct net *net, u8 tx_key) + struct tipc_crypto *tx = tipc_net(net)->crypto_tx; + struct tipc_key key; + +- spin_lock(&tx->lock); ++ spin_lock_bh(&tx->lock); + key = tx->key; + WARN_ON(!key.active || tx_key != key.active); + + /* Free the active key */ + tipc_crypto_key_set_state(tx, key.passive, 0, key.pending); + tipc_crypto_key_detach(tx->aead[key.active], &tx->lock); +- spin_unlock(&tx->lock); ++ spin_unlock_bh(&tx->lock); + + pr_warn("%s: key is revoked\n", tx->name); + return -EKEYREVOKED; +-- +2.40.1 + diff --git a/queue-6.1/ubi-refuse-attaching-if-mtd-s-erasesize-is-0.patch b/queue-6.1/ubi-refuse-attaching-if-mtd-s-erasesize-is-0.patch new file mode 100644 index 00000000000..76b46d45409 --- /dev/null +++ b/queue-6.1/ubi-refuse-attaching-if-mtd-s-erasesize-is-0.patch @@ -0,0 +1,45 @@ +From e3577ea872d6ad98d1cfeabd34823618f0a00491 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 23 Apr 2023 19:10:41 +0800 +Subject: ubi: Refuse attaching if mtd's erasesize is 0 + +From: Zhihao Cheng + +[ Upstream commit 017c73a34a661a861712f7cc1393a123e5b2208c ] + +There exists mtd devices with zero erasesize, which will trigger a +divide-by-zero exception while attaching ubi device. +Fix it by refusing attaching if mtd's erasesize is 0. + +Fixes: 801c135ce73d ("UBI: Unsorted Block Images") +Reported-by: Yu Hao +Link: https://lore.kernel.org/lkml/977347543.226888.1682011999468.JavaMail.zimbra@nod.at/T/ +Signed-off-by: Zhihao Cheng +Reviewed-by: Miquel Raynal +Signed-off-by: Richard Weinberger +Signed-off-by: Sasha Levin +--- + drivers/mtd/ubi/build.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c +index 1662c12e24ada..6fbd77dc1d18f 100644 +--- a/drivers/mtd/ubi/build.c ++++ b/drivers/mtd/ubi/build.c +@@ -893,6 +893,13 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, + return -EINVAL; + } + ++ /* UBI cannot work on flashes with zero erasesize. */ ++ if (!mtd->erasesize) { ++ pr_err("ubi: refuse attaching mtd%d - zero erasesize flash is not supported\n", ++ mtd->index); ++ return -EINVAL; ++ } ++ + if (ubi_num == UBI_DEV_NUM_AUTO) { + /* Search for an empty slot in the @ubi_devices array */ + for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) +-- +2.40.1 + diff --git a/queue-6.1/wifi-cfg80211-add-a-work-abstraction-with-special-se.patch b/queue-6.1/wifi-cfg80211-add-a-work-abstraction-with-special-se.patch new file mode 100644 index 00000000000..838ae2cb000 --- /dev/null +++ b/queue-6.1/wifi-cfg80211-add-a-work-abstraction-with-special-se.patch @@ -0,0 +1,377 @@ +From cc69ae9c246731c74fc0e1f70c1fc86734cb4700 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Jun 2023 14:49:25 +0200 +Subject: wifi: cfg80211: add a work abstraction with special semantics + +From: Johannes Berg + +[ Upstream commit a3ee4dc84c4e9d14cb34dad095fd678127aca5b6 ] + +Add a work abstraction at the cfg80211 level that will always +hold the wiphy_lock() for any work executed and therefore also +can be canceled safely (without waiting) while holding that. +This improves on what we do now as with the new wiphy works we +don't have to worry about locking while cancelling them safely. + +Also, don't let such works run while the device is suspended, +since they'll likely need to interact with the device. Flush +them before suspend though. + +Signed-off-by: Johannes Berg +Stable-dep-of: 37c20b2effe9 ("wifi: cfg80211: fix cqm_config access race") +Signed-off-by: Sasha Levin +--- + include/net/cfg80211.h | 95 ++++++++++++++++++++++++++++++-- + net/wireless/core.c | 122 +++++++++++++++++++++++++++++++++++++++++ + net/wireless/core.h | 7 +++ + net/wireless/sysfs.c | 8 ++- + 4 files changed, 227 insertions(+), 5 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index 5976545aa26b9..f2144db89183c 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -5621,12 +5621,17 @@ struct cfg80211_cqm_config; + * wiphy_lock - lock the wiphy + * @wiphy: the wiphy to lock + * +- * This is mostly exposed so it can be done around registering and +- * unregistering netdevs that aren't created through cfg80211 calls, +- * since that requires locking in cfg80211 when the notifiers is +- * called, but that cannot differentiate which way it's called. ++ * This is needed around registering and unregistering netdevs that ++ * aren't created through cfg80211 calls, since that requires locking ++ * in cfg80211 when the notifiers is called, but that cannot ++ * differentiate which way it's called. ++ * ++ * It can also be used by drivers for their own purposes. + * + * When cfg80211 ops are called, the wiphy is already locked. ++ * ++ * Note that this makes sure that no workers that have been queued ++ * with wiphy_queue_work() are running. + */ + static inline void wiphy_lock(struct wiphy *wiphy) + __acquires(&wiphy->mtx) +@@ -5646,6 +5651,88 @@ static inline void wiphy_unlock(struct wiphy *wiphy) + mutex_unlock(&wiphy->mtx); + } + ++struct wiphy_work; ++typedef void (*wiphy_work_func_t)(struct wiphy *, struct wiphy_work *); ++ ++struct wiphy_work { ++ struct list_head entry; ++ wiphy_work_func_t func; ++}; ++ ++static inline void wiphy_work_init(struct wiphy_work *work, ++ wiphy_work_func_t func) ++{ ++ INIT_LIST_HEAD(&work->entry); ++ work->func = func; ++} ++ ++/** ++ * wiphy_work_queue - queue work for the wiphy ++ * @wiphy: the wiphy to queue for ++ * @work: the work item ++ * ++ * This is useful for work that must be done asynchronously, and work ++ * queued here has the special property that the wiphy mutex will be ++ * held as if wiphy_lock() was called, and that it cannot be running ++ * after wiphy_lock() was called. Therefore, wiphy_cancel_work() can ++ * use just cancel_work() instead of cancel_work_sync(), it requires ++ * being in a section protected by wiphy_lock(). ++ */ ++void wiphy_work_queue(struct wiphy *wiphy, struct wiphy_work *work); ++ ++/** ++ * wiphy_work_cancel - cancel previously queued work ++ * @wiphy: the wiphy, for debug purposes ++ * @work: the work to cancel ++ * ++ * Cancel the work *without* waiting for it, this assumes being ++ * called under the wiphy mutex acquired by wiphy_lock(). ++ */ ++void wiphy_work_cancel(struct wiphy *wiphy, struct wiphy_work *work); ++ ++struct wiphy_delayed_work { ++ struct wiphy_work work; ++ struct wiphy *wiphy; ++ struct timer_list timer; ++}; ++ ++void wiphy_delayed_work_timer(struct timer_list *t); ++ ++static inline void wiphy_delayed_work_init(struct wiphy_delayed_work *dwork, ++ wiphy_work_func_t func) ++{ ++ timer_setup(&dwork->timer, wiphy_delayed_work_timer, 0); ++ wiphy_work_init(&dwork->work, func); ++} ++ ++/** ++ * wiphy_delayed_work_queue - queue delayed work for the wiphy ++ * @wiphy: the wiphy to queue for ++ * @dwork: the delayable worker ++ * @delay: number of jiffies to wait before queueing ++ * ++ * This is useful for work that must be done asynchronously, and work ++ * queued here has the special property that the wiphy mutex will be ++ * held as if wiphy_lock() was called, and that it cannot be running ++ * after wiphy_lock() was called. Therefore, wiphy_cancel_work() can ++ * use just cancel_work() instead of cancel_work_sync(), it requires ++ * being in a section protected by wiphy_lock(). ++ */ ++void wiphy_delayed_work_queue(struct wiphy *wiphy, ++ struct wiphy_delayed_work *dwork, ++ unsigned long delay); ++ ++/** ++ * wiphy_delayed_work_cancel - cancel previously queued delayed work ++ * @wiphy: the wiphy, for debug purposes ++ * @dwork: the delayed work to cancel ++ * ++ * Cancel the work *without* waiting for it, this assumes being ++ * called under the wiphy mutex acquired by wiphy_lock(). ++ */ ++void wiphy_delayed_work_cancel(struct wiphy *wiphy, ++ struct wiphy_delayed_work *dwork); ++ + /** + * struct wireless_dev - wireless device state + * +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 28ae86c62f805..8a1f34e95c4f0 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -408,6 +408,34 @@ static void cfg80211_propagate_cac_done_wk(struct work_struct *work) + rtnl_unlock(); + } + ++static void cfg80211_wiphy_work(struct work_struct *work) ++{ ++ struct cfg80211_registered_device *rdev; ++ struct wiphy_work *wk; ++ ++ rdev = container_of(work, struct cfg80211_registered_device, wiphy_work); ++ ++ wiphy_lock(&rdev->wiphy); ++ if (rdev->suspended) ++ goto out; ++ ++ spin_lock_irq(&rdev->wiphy_work_lock); ++ wk = list_first_entry_or_null(&rdev->wiphy_work_list, ++ struct wiphy_work, entry); ++ if (wk) { ++ list_del_init(&wk->entry); ++ if (!list_empty(&rdev->wiphy_work_list)) ++ schedule_work(work); ++ spin_unlock_irq(&rdev->wiphy_work_lock); ++ ++ wk->func(&rdev->wiphy, wk); ++ } else { ++ spin_unlock_irq(&rdev->wiphy_work_lock); ++ } ++out: ++ wiphy_unlock(&rdev->wiphy); ++} ++ + /* exported functions */ + + struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, +@@ -533,6 +561,9 @@ struct wiphy *wiphy_new_nm(const struct cfg80211_ops *ops, int sizeof_priv, + return NULL; + } + ++ INIT_WORK(&rdev->wiphy_work, cfg80211_wiphy_work); ++ INIT_LIST_HEAD(&rdev->wiphy_work_list); ++ spin_lock_init(&rdev->wiphy_work_lock); + INIT_WORK(&rdev->rfkill_block, cfg80211_rfkill_block_work); + INIT_WORK(&rdev->conn_work, cfg80211_conn_work); + INIT_WORK(&rdev->event_work, cfg80211_event_work); +@@ -1011,6 +1042,31 @@ void wiphy_rfkill_start_polling(struct wiphy *wiphy) + } + EXPORT_SYMBOL(wiphy_rfkill_start_polling); + ++void cfg80211_process_wiphy_works(struct cfg80211_registered_device *rdev) ++{ ++ unsigned int runaway_limit = 100; ++ unsigned long flags; ++ ++ lockdep_assert_held(&rdev->wiphy.mtx); ++ ++ spin_lock_irqsave(&rdev->wiphy_work_lock, flags); ++ while (!list_empty(&rdev->wiphy_work_list)) { ++ struct wiphy_work *wk; ++ ++ wk = list_first_entry(&rdev->wiphy_work_list, ++ struct wiphy_work, entry); ++ list_del_init(&wk->entry); ++ spin_unlock_irqrestore(&rdev->wiphy_work_lock, flags); ++ ++ wk->func(&rdev->wiphy, wk); ++ ++ spin_lock_irqsave(&rdev->wiphy_work_lock, flags); ++ if (WARN_ON(--runaway_limit == 0)) ++ INIT_LIST_HEAD(&rdev->wiphy_work_list); ++ } ++ spin_unlock_irqrestore(&rdev->wiphy_work_lock, flags); ++} ++ + void wiphy_unregister(struct wiphy *wiphy) + { + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); +@@ -1053,9 +1109,15 @@ void wiphy_unregister(struct wiphy *wiphy) + if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) + rdev_set_wakeup(rdev, false); + #endif ++ ++ /* surely nothing is reachable now, clean up work */ ++ cfg80211_process_wiphy_works(rdev); + wiphy_unlock(&rdev->wiphy); + rtnl_unlock(); + ++ /* this has nothing to do now but make sure it's gone */ ++ cancel_work_sync(&rdev->wiphy_work); ++ + flush_work(&rdev->scan_done_wk); + cancel_work_sync(&rdev->conn_work); + flush_work(&rdev->event_work); +@@ -1546,6 +1608,66 @@ static struct pernet_operations cfg80211_pernet_ops = { + .exit = cfg80211_pernet_exit, + }; + ++void wiphy_work_queue(struct wiphy *wiphy, struct wiphy_work *work) ++{ ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ unsigned long flags; ++ ++ spin_lock_irqsave(&rdev->wiphy_work_lock, flags); ++ if (list_empty(&work->entry)) ++ list_add_tail(&work->entry, &rdev->wiphy_work_list); ++ spin_unlock_irqrestore(&rdev->wiphy_work_lock, flags); ++ ++ schedule_work(&rdev->wiphy_work); ++} ++EXPORT_SYMBOL_GPL(wiphy_work_queue); ++ ++void wiphy_work_cancel(struct wiphy *wiphy, struct wiphy_work *work) ++{ ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ unsigned long flags; ++ ++ lockdep_assert_held(&wiphy->mtx); ++ ++ spin_lock_irqsave(&rdev->wiphy_work_lock, flags); ++ if (!list_empty(&work->entry)) ++ list_del_init(&work->entry); ++ spin_unlock_irqrestore(&rdev->wiphy_work_lock, flags); ++} ++EXPORT_SYMBOL_GPL(wiphy_work_cancel); ++ ++void wiphy_delayed_work_timer(struct timer_list *t) ++{ ++ struct wiphy_delayed_work *dwork = from_timer(dwork, t, timer); ++ ++ wiphy_work_queue(dwork->wiphy, &dwork->work); ++} ++EXPORT_SYMBOL(wiphy_delayed_work_timer); ++ ++void wiphy_delayed_work_queue(struct wiphy *wiphy, ++ struct wiphy_delayed_work *dwork, ++ unsigned long delay) ++{ ++ if (!delay) { ++ wiphy_work_queue(wiphy, &dwork->work); ++ return; ++ } ++ ++ dwork->wiphy = wiphy; ++ mod_timer(&dwork->timer, jiffies + delay); ++} ++EXPORT_SYMBOL_GPL(wiphy_delayed_work_queue); ++ ++void wiphy_delayed_work_cancel(struct wiphy *wiphy, ++ struct wiphy_delayed_work *dwork) ++{ ++ lockdep_assert_held(&wiphy->mtx); ++ ++ del_timer_sync(&dwork->timer); ++ wiphy_work_cancel(wiphy, &dwork->work); ++} ++EXPORT_SYMBOL_GPL(wiphy_delayed_work_cancel); ++ + static int __init cfg80211_init(void) + { + int err; +diff --git a/net/wireless/core.h b/net/wireless/core.h +index 775e16cb99eda..0481a8a539d5d 100644 +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -108,6 +108,12 @@ struct cfg80211_registered_device { + /* lock for all wdev lists */ + spinlock_t mgmt_registrations_lock; + ++ struct work_struct wiphy_work; ++ struct list_head wiphy_work_list; ++ /* protects the list above */ ++ spinlock_t wiphy_work_lock; ++ bool suspended; ++ + /* must be last because of the way we do wiphy_priv(), + * and it should at least be aligned to NETDEV_ALIGN */ + struct wiphy wiphy __aligned(NETDEV_ALIGN); +@@ -450,6 +456,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, + struct net_device *dev, enum nl80211_iftype ntype, + struct vif_params *params); + void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); ++void cfg80211_process_wiphy_works(struct cfg80211_registered_device *rdev); + void cfg80211_process_wdev_events(struct wireless_dev *wdev); + + bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range, +diff --git a/net/wireless/sysfs.c b/net/wireless/sysfs.c +index 0c3f05c9be27a..4d3b658030105 100644 +--- a/net/wireless/sysfs.c ++++ b/net/wireless/sysfs.c +@@ -5,7 +5,7 @@ + * + * Copyright 2005-2006 Jiri Benc + * Copyright 2006 Johannes Berg +- * Copyright (C) 2020-2021 Intel Corporation ++ * Copyright (C) 2020-2021, 2023 Intel Corporation + */ + + #include +@@ -105,14 +105,18 @@ static int wiphy_suspend(struct device *dev) + cfg80211_leave_all(rdev); + cfg80211_process_rdev_events(rdev); + } ++ cfg80211_process_wiphy_works(rdev); + if (rdev->ops->suspend) + ret = rdev_suspend(rdev, rdev->wiphy.wowlan_config); + if (ret == 1) { + /* Driver refuse to configure wowlan */ + cfg80211_leave_all(rdev); + cfg80211_process_rdev_events(rdev); ++ cfg80211_process_wiphy_works(rdev); + ret = rdev_suspend(rdev, NULL); + } ++ if (ret == 0) ++ rdev->suspended = true; + } + wiphy_unlock(&rdev->wiphy); + rtnl_unlock(); +@@ -132,6 +136,8 @@ static int wiphy_resume(struct device *dev) + wiphy_lock(&rdev->wiphy); + if (rdev->wiphy.registered && rdev->ops->resume) + ret = rdev_resume(rdev); ++ rdev->suspended = false; ++ schedule_work(&rdev->wiphy_work); + wiphy_unlock(&rdev->wiphy); + + if (ret) +-- +2.40.1 + diff --git a/queue-6.1/wifi-cfg80211-add-missing-kernel-doc-for-cqm_rssi_wo.patch b/queue-6.1/wifi-cfg80211-add-missing-kernel-doc-for-cqm_rssi_wo.patch new file mode 100644 index 00000000000..a34fe6e0434 --- /dev/null +++ b/queue-6.1/wifi-cfg80211-add-missing-kernel-doc-for-cqm_rssi_wo.patch @@ -0,0 +1,35 @@ +From 6fd718a4892b387cbb034475cf5d4a050350db0b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Sep 2023 09:36:57 +0200 +Subject: wifi: cfg80211: add missing kernel-doc for cqm_rssi_work + +From: Johannes Berg + +[ Upstream commit d1383077c225ceb87ac7a3b56b2c505193f77ed7 ] + +As reported by Stephen, I neglected to add the kernel-doc +for the new struct member. Fix that. + +Reported-by: Stephen Rothwell +Fixes: 37c20b2effe9 ("wifi: cfg80211: fix cqm_config access race") +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + include/net/cfg80211.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index ab64bb94c92fd..7a6c3059d50b5 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -5805,6 +5805,7 @@ void wiphy_delayed_work_cancel(struct wiphy *wiphy, + * @event_lock: (private) lock for event list + * @owner_nlportid: (private) owner socket port ID + * @nl_owner_dead: (private) owner socket went away ++ * @cqm_rssi_work: (private) CQM RSSI reporting work + * @cqm_config: (private) nl80211 RSSI monitor state + * @pmsr_list: (private) peer measurement requests + * @pmsr_lock: (private) peer measurements requests/results lock +-- +2.40.1 + diff --git a/queue-6.1/wifi-cfg80211-fix-cqm_config-access-race.patch b/queue-6.1/wifi-cfg80211-fix-cqm_config-access-race.patch new file mode 100644 index 00000000000..8df5598997b --- /dev/null +++ b/queue-6.1/wifi-cfg80211-fix-cqm_config-access-race.patch @@ -0,0 +1,330 @@ +From d9f62a9614369b0b0f5007cd2500f477c1919047 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 16 Aug 2023 15:38:04 +0200 +Subject: wifi: cfg80211: fix cqm_config access race + +From: Johannes Berg + +[ Upstream commit 37c20b2effe987b806c8de6d12978e4ffeff026f ] + +Max Schulze reports crashes with brcmfmac. The reason seems +to be a race between userspace removing the CQM config and +the driver calling cfg80211_cqm_rssi_notify(), where if the +data is freed while cfg80211_cqm_rssi_notify() runs it will +crash since it assumes wdev->cqm_config is set. This can't +be fixed with a simple non-NULL check since there's nothing +we can do for locking easily, so use RCU instead to protect +the pointer, but that requires pulling the updates out into +an asynchronous worker so they can sleep and call back into +the driver. + +Since we need to change the free anyway, also change it to +go back to the old settings if changing the settings fails. + +Reported-and-tested-by: Max Schulze +Closes: https://lore.kernel.org/r/ac96309a-8d8d-4435-36e6-6d152eb31876@online.de +Fixes: 4a4b8169501b ("cfg80211: Accept multiple RSSI thresholds for CQM") +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + include/net/cfg80211.h | 3 +- + net/wireless/core.c | 14 +++---- + net/wireless/core.h | 7 +++- + net/wireless/nl80211.c | 93 +++++++++++++++++++++++++++--------------- + 4 files changed, 75 insertions(+), 42 deletions(-) + +diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h +index f2144db89183c..ab64bb94c92fd 100644 +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -5877,7 +5877,8 @@ struct wireless_dev { + } wext; + #endif + +- struct cfg80211_cqm_config *cqm_config; ++ struct wiphy_work cqm_rssi_work; ++ struct cfg80211_cqm_config __rcu *cqm_config; + + struct list_head pmsr_list; + spinlock_t pmsr_lock; +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 8a1f34e95c4f0..2c79604672062 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1176,16 +1176,11 @@ void wiphy_rfkill_set_hw_state_reason(struct wiphy *wiphy, bool blocked, + } + EXPORT_SYMBOL(wiphy_rfkill_set_hw_state_reason); + +-void cfg80211_cqm_config_free(struct wireless_dev *wdev) +-{ +- kfree(wdev->cqm_config); +- wdev->cqm_config = NULL; +-} +- + static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, + bool unregister_netdev) + { + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); ++ struct cfg80211_cqm_config *cqm_config; + unsigned int link_id; + + ASSERT_RTNL(); +@@ -1224,7 +1219,10 @@ static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, + kfree_sensitive(wdev->wext.keys); + wdev->wext.keys = NULL; + #endif +- cfg80211_cqm_config_free(wdev); ++ wiphy_work_cancel(wdev->wiphy, &wdev->cqm_rssi_work); ++ /* deleted from the list, so can't be found from nl80211 any more */ ++ cqm_config = rcu_access_pointer(wdev->cqm_config); ++ kfree_rcu(cqm_config, rcu_head); + + /* + * Ensure that all events have been processed and +@@ -1376,6 +1374,8 @@ void cfg80211_init_wdev(struct wireless_dev *wdev) + wdev->wext.connect.auth_type = NL80211_AUTHTYPE_AUTOMATIC; + #endif + ++ wiphy_work_init(&wdev->cqm_rssi_work, cfg80211_cqm_rssi_notify_work); ++ + if (wdev->wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT) + wdev->ps = true; + else +diff --git a/net/wireless/core.h b/net/wireless/core.h +index 0481a8a539d5d..86fd79912254d 100644 +--- a/net/wireless/core.h ++++ b/net/wireless/core.h +@@ -293,12 +293,17 @@ struct cfg80211_beacon_registration { + }; + + struct cfg80211_cqm_config { ++ struct rcu_head rcu_head; + u32 rssi_hyst; + s32 last_rssi_event_value; ++ enum nl80211_cqm_rssi_threshold_event last_rssi_event_type; + int n_rssi_thresholds; + s32 rssi_thresholds[]; + }; + ++void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, ++ struct wiphy_work *work); ++ + void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev); + + /* free object */ +@@ -563,8 +568,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *rdev, + #define CFG80211_DEV_WARN_ON(cond) ({bool __r = (cond); __r; }) + #endif + +-void cfg80211_cqm_config_free(struct wireless_dev *wdev); +- + void cfg80211_release_pmsr(struct wireless_dev *wdev, u32 portid); + void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev); + void cfg80211_pmsr_free_wk(struct work_struct *work); +diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c +index 12c7c89d5be1d..1d993a490ac4b 100644 +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -12565,7 +12565,8 @@ static int nl80211_set_cqm_txe(struct genl_info *info, + } + + static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, +- struct net_device *dev) ++ struct net_device *dev, ++ struct cfg80211_cqm_config *cqm_config) + { + struct wireless_dev *wdev = dev->ieee80211_ptr; + s32 last, low, high; +@@ -12574,7 +12575,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, + int err; + + /* RSSI reporting disabled? */ +- if (!wdev->cqm_config) ++ if (!cqm_config) + return rdev_set_cqm_rssi_range_config(rdev, dev, 0, 0); + + /* +@@ -12583,7 +12584,7 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, + * connection is established and enough beacons received to calculate + * the average. + */ +- if (!wdev->cqm_config->last_rssi_event_value && ++ if (!cqm_config->last_rssi_event_value && + wdev->links[0].client.current_bss && + rdev->ops->get_station) { + struct station_info sinfo = {}; +@@ -12597,30 +12598,30 @@ static int cfg80211_cqm_rssi_update(struct cfg80211_registered_device *rdev, + + cfg80211_sinfo_release_content(&sinfo); + if (sinfo.filled & BIT_ULL(NL80211_STA_INFO_BEACON_SIGNAL_AVG)) +- wdev->cqm_config->last_rssi_event_value = ++ cqm_config->last_rssi_event_value = + (s8) sinfo.rx_beacon_signal_avg; + } + +- last = wdev->cqm_config->last_rssi_event_value; +- hyst = wdev->cqm_config->rssi_hyst; +- n = wdev->cqm_config->n_rssi_thresholds; ++ last = cqm_config->last_rssi_event_value; ++ hyst = cqm_config->rssi_hyst; ++ n = cqm_config->n_rssi_thresholds; + + for (i = 0; i < n; i++) { + i = array_index_nospec(i, n); +- if (last < wdev->cqm_config->rssi_thresholds[i]) ++ if (last < cqm_config->rssi_thresholds[i]) + break; + } + + low_index = i - 1; + if (low_index >= 0) { + low_index = array_index_nospec(low_index, n); +- low = wdev->cqm_config->rssi_thresholds[low_index] - hyst; ++ low = cqm_config->rssi_thresholds[low_index] - hyst; + } else { + low = S32_MIN; + } + if (i < n) { + i = array_index_nospec(i, n); +- high = wdev->cqm_config->rssi_thresholds[i] + hyst - 1; ++ high = cqm_config->rssi_thresholds[i] + hyst - 1; + } else { + high = S32_MAX; + } +@@ -12633,6 +12634,7 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, + u32 hysteresis) + { + struct cfg80211_registered_device *rdev = info->user_ptr[0]; ++ struct cfg80211_cqm_config *cqm_config = NULL, *old; + struct net_device *dev = info->user_ptr[1]; + struct wireless_dev *wdev = dev->ieee80211_ptr; + int i, err; +@@ -12650,10 +12652,6 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, + wdev->iftype != NL80211_IFTYPE_P2P_CLIENT) + return -EOPNOTSUPP; + +- wdev_lock(wdev); +- cfg80211_cqm_config_free(wdev); +- wdev_unlock(wdev); +- + if (n_thresholds <= 1 && rdev->ops->set_cqm_rssi_config) { + if (n_thresholds == 0 || thresholds[0] == 0) /* Disabling */ + return rdev_set_cqm_rssi_config(rdev, dev, 0, 0); +@@ -12670,9 +12668,10 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, + n_thresholds = 0; + + wdev_lock(wdev); +- if (n_thresholds) { +- struct cfg80211_cqm_config *cqm_config; ++ old = rcu_dereference_protected(wdev->cqm_config, ++ lockdep_is_held(&wdev->mtx)); + ++ if (n_thresholds) { + cqm_config = kzalloc(struct_size(cqm_config, rssi_thresholds, + n_thresholds), + GFP_KERNEL); +@@ -12687,11 +12686,18 @@ static int nl80211_set_cqm_rssi(struct genl_info *info, + flex_array_size(cqm_config, rssi_thresholds, + n_thresholds)); + +- wdev->cqm_config = cqm_config; ++ rcu_assign_pointer(wdev->cqm_config, cqm_config); ++ } else { ++ RCU_INIT_POINTER(wdev->cqm_config, NULL); + } + +- err = cfg80211_cqm_rssi_update(rdev, dev); +- ++ err = cfg80211_cqm_rssi_update(rdev, dev, cqm_config); ++ if (err) { ++ rcu_assign_pointer(wdev->cqm_config, old); ++ kfree_rcu(cqm_config, rcu_head); ++ } else { ++ kfree_rcu(old, rcu_head); ++ } + unlock: + wdev_unlock(wdev); + +@@ -18719,9 +18725,8 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, + enum nl80211_cqm_rssi_threshold_event rssi_event, + s32 rssi_level, gfp_t gfp) + { +- struct sk_buff *msg; + struct wireless_dev *wdev = dev->ieee80211_ptr; +- struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); ++ struct cfg80211_cqm_config *cqm_config; + + trace_cfg80211_cqm_rssi_notify(dev, rssi_event, rssi_level); + +@@ -18729,18 +18734,41 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, + rssi_event != NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH)) + return; + +- if (wdev->cqm_config) { +- wdev->cqm_config->last_rssi_event_value = rssi_level; ++ rcu_read_lock(); ++ cqm_config = rcu_dereference(wdev->cqm_config); ++ if (cqm_config) { ++ cqm_config->last_rssi_event_value = rssi_level; ++ cqm_config->last_rssi_event_type = rssi_event; ++ wiphy_work_queue(wdev->wiphy, &wdev->cqm_rssi_work); ++ } ++ rcu_read_unlock(); ++} ++EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); ++ ++void cfg80211_cqm_rssi_notify_work(struct wiphy *wiphy, struct wiphy_work *work) ++{ ++ struct wireless_dev *wdev = container_of(work, struct wireless_dev, ++ cqm_rssi_work); ++ struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy); ++ enum nl80211_cqm_rssi_threshold_event rssi_event; ++ struct cfg80211_cqm_config *cqm_config; ++ struct sk_buff *msg; ++ s32 rssi_level; + +- cfg80211_cqm_rssi_update(rdev, dev); ++ wdev_lock(wdev); ++ cqm_config = rcu_dereference_protected(wdev->cqm_config, ++ lockdep_is_held(&wdev->mtx)); ++ if (!wdev->cqm_config) ++ goto unlock; + +- if (rssi_level == 0) +- rssi_level = wdev->cqm_config->last_rssi_event_value; +- } ++ cfg80211_cqm_rssi_update(rdev, wdev->netdev, cqm_config); + +- msg = cfg80211_prepare_cqm(dev, NULL, gfp); ++ rssi_level = cqm_config->last_rssi_event_value; ++ rssi_event = cqm_config->last_rssi_event_type; ++ ++ msg = cfg80211_prepare_cqm(wdev->netdev, NULL, GFP_KERNEL); + if (!msg) +- return; ++ goto unlock; + + if (nla_put_u32(msg, NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, + rssi_event)) +@@ -18750,14 +18778,15 @@ void cfg80211_cqm_rssi_notify(struct net_device *dev, + rssi_level)) + goto nla_put_failure; + +- cfg80211_send_cqm(msg, gfp); ++ cfg80211_send_cqm(msg, GFP_KERNEL); + +- return; ++ goto unlock; + + nla_put_failure: + nlmsg_free(msg); ++ unlock: ++ wdev_unlock(wdev); + } +-EXPORT_SYMBOL(cfg80211_cqm_rssi_notify); + + void cfg80211_cqm_txe_notify(struct net_device *dev, + const u8 *peer, u32 num_packets, +-- +2.40.1 + diff --git a/queue-6.1/wifi-cfg80211-hold-wiphy-lock-in-auto-disconnect.patch b/queue-6.1/wifi-cfg80211-hold-wiphy-lock-in-auto-disconnect.patch new file mode 100644 index 00000000000..d80797bc6ab --- /dev/null +++ b/queue-6.1/wifi-cfg80211-hold-wiphy-lock-in-auto-disconnect.patch @@ -0,0 +1,76 @@ +From 529ae57eb2d26afdd940af0f8413082c8c08367f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Jun 2023 14:49:20 +0200 +Subject: wifi: cfg80211: hold wiphy lock in auto-disconnect + +From: Johannes Berg + +[ Upstream commit e9da6df7492a981b071bafd169fb4c35b45f5ebf ] + +Most code paths in cfg80211 already hold the wiphy lock, +mostly by virtue of being called from nl80211, so make +the auto-disconnect worker also hold it, aligning the +locking promises between different parts of cfg80211. + +Signed-off-by: Johannes Berg +Stable-dep-of: 37c20b2effe9 ("wifi: cfg80211: fix cqm_config access race") +Signed-off-by: Sasha Levin +--- + net/wireless/core.c | 6 ++---- + net/wireless/sme.c | 4 +++- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 609b79fe4a748..9ac7c54379cf3 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1162,10 +1162,6 @@ static void _cfg80211_unregister_wdev(struct wireless_dev *wdev, + kfree_sensitive(wdev->wext.keys); + wdev->wext.keys = NULL; + #endif +- /* only initialized if we have a netdev */ +- if (wdev->netdev) +- flush_work(&wdev->disconnect_wk); +- + cfg80211_cqm_config_free(wdev); + + /* +@@ -1439,6 +1435,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, + cfg80211_leave(rdev, wdev); + cfg80211_remove_links(wdev); + wiphy_unlock(&rdev->wiphy); ++ /* since we just did cfg80211_leave() nothing to do there */ ++ cancel_work_sync(&wdev->disconnect_wk); + break; + case NETDEV_DOWN: + wiphy_lock(&rdev->wiphy); +diff --git a/net/wireless/sme.c b/net/wireless/sme.c +index 6e87d2cd83456..b97834284baef 100644 +--- a/net/wireless/sme.c ++++ b/net/wireless/sme.c +@@ -5,7 +5,7 @@ + * (for nl80211's connect() and wext) + * + * Copyright 2009 Johannes Berg +- * Copyright (C) 2009, 2020, 2022 Intel Corporation. All rights reserved. ++ * Copyright (C) 2009, 2020, 2022-2023 Intel Corporation. All rights reserved. + * Copyright 2017 Intel Deutschland GmbH + */ + +@@ -1555,6 +1555,7 @@ void cfg80211_autodisconnect_wk(struct work_struct *work) + container_of(work, struct wireless_dev, disconnect_wk); + struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); + ++ wiphy_lock(wdev->wiphy); + wdev_lock(wdev); + + if (wdev->conn_owner_nlportid) { +@@ -1593,4 +1594,5 @@ void cfg80211_autodisconnect_wk(struct work_struct *work) + } + + wdev_unlock(wdev); ++ wiphy_unlock(wdev->wiphy); + } +-- +2.40.1 + diff --git a/queue-6.1/wifi-cfg80211-move-wowlan-disable-under-locks.patch b/queue-6.1/wifi-cfg80211-move-wowlan-disable-under-locks.patch new file mode 100644 index 00000000000..69d401f7877 --- /dev/null +++ b/queue-6.1/wifi-cfg80211-move-wowlan-disable-under-locks.patch @@ -0,0 +1,51 @@ +From c319b0ed6daf30cd719f1a95c5181f395330ce6e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Jun 2023 14:49:22 +0200 +Subject: wifi: cfg80211: move wowlan disable under locks + +From: Johannes Berg + +[ Upstream commit a993df0f9143e63eca38c96a30daf08db99a98a3 ] + +This is a driver callback, and the driver should be able +to assume that it's called with the wiphy lock held. Move +the call up so that's true, it has no other effect since +the device is already unregistering and we cannot reach +this function through other paths. + +Signed-off-by: Johannes Berg +Stable-dep-of: 37c20b2effe9 ("wifi: cfg80211: fix cqm_config access race") +Signed-off-by: Sasha Levin +--- + net/wireless/core.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/net/wireless/core.c b/net/wireless/core.c +index 9ac7c54379cf3..28ae86c62f805 100644 +--- a/net/wireless/core.c ++++ b/net/wireless/core.c +@@ -1049,6 +1049,10 @@ void wiphy_unregister(struct wiphy *wiphy) + cfg80211_rdev_list_generation++; + device_del(&rdev->wiphy.dev); + ++#ifdef CONFIG_PM ++ if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) ++ rdev_set_wakeup(rdev, false); ++#endif + wiphy_unlock(&rdev->wiphy); + rtnl_unlock(); + +@@ -1064,10 +1068,6 @@ void wiphy_unregister(struct wiphy *wiphy) + flush_work(&rdev->mgmt_registrations_update_wk); + flush_work(&rdev->background_cac_abort_wk); + +-#ifdef CONFIG_PM +- if (rdev->wiphy.wowlan_config && rdev->ops->set_wakeup) +- rdev_set_wakeup(rdev, false); +-#endif + cfg80211_rdev_free_wowlan(rdev); + cfg80211_rdev_free_coalesce(rdev); + } +-- +2.40.1 + diff --git a/queue-6.1/wifi-iwlwifi-dbg_ini-fix-structure-packing.patch b/queue-6.1/wifi-iwlwifi-dbg_ini-fix-structure-packing.patch new file mode 100644 index 00000000000..c4ba5aebeea --- /dev/null +++ b/queue-6.1/wifi-iwlwifi-dbg_ini-fix-structure-packing.patch @@ -0,0 +1,50 @@ +From 18c35fa7d73ce7ea4182d5ecacbf278b9be9e30c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Jun 2023 11:03:34 +0200 +Subject: wifi: iwlwifi: dbg_ini: fix structure packing + +From: Arnd Bergmann + +[ Upstream commit 424c82e8ad56756bb98b08268ffcf68d12d183eb ] + +The iwl_fw_ini_error_dump_range structure has conflicting alignment +requirements for the inner union and the outer struct: + +In file included from drivers/net/wireless/intel/iwlwifi/fw/dbg.c:9: +drivers/net/wireless/intel/iwlwifi/fw/error-dump.h:312:2: error: field within 'struct iwl_fw_ini_error_dump_range' is less aligned than 'union iwl_fw_ini_error_dump_range::(anonymous at drivers/net/wireless/intel/iwlwifi/fw/error-dump.h:312:2)' and is usually due to 'struct iwl_fw_ini_error_dump_range' being packed, which can lead to unaligned accesses [-Werror,-Wunaligned-access] + union { + +As the original intention was apparently to make the entire structure +unaligned, mark the innermost members the same way so the union +becomes packed as well. + +Fixes: 973193554cae6 ("iwlwifi: dbg_ini: dump headers cleanup") +Signed-off-by: Arnd Bergmann +Acked-by: Gregory Greenman +Link: https://lore.kernel.org/r/20230616090343.2454061-1-arnd@kernel.org +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/fw/error-dump.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +index c62576e442bdf..2d481849a9c23 100644 +--- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h ++++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +@@ -295,9 +295,9 @@ struct iwl_fw_ini_fifo_hdr { + struct iwl_fw_ini_error_dump_range { + __le32 range_data_size; + union { +- __le32 internal_base_addr; +- __le64 dram_base_addr; +- __le32 page_num; ++ __le32 internal_base_addr __packed; ++ __le64 dram_base_addr __packed; ++ __le32 page_num __packed; + struct iwl_fw_ini_fifo_hdr fifo_hdr; + struct iwl_cmd_header fw_pkt_hdr; + }; +-- +2.40.1 + diff --git a/queue-6.1/wifi-iwlwifi-mvm-fix-a-memory-corruption-issue.patch b/queue-6.1/wifi-iwlwifi-mvm-fix-a-memory-corruption-issue.patch new file mode 100644 index 00000000000..59bc332d765 --- /dev/null +++ b/queue-6.1/wifi-iwlwifi-mvm-fix-a-memory-corruption-issue.patch @@ -0,0 +1,63 @@ +From 1e77cf2616bd4f72edab7f67441982b252b8f8e7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 23 Jul 2023 22:24:59 +0200 +Subject: wifi: iwlwifi: mvm: Fix a memory corruption issue + +From: Christophe JAILLET + +[ Upstream commit 8ba438ef3cacc4808a63ed0ce24d4f0942cfe55d ] + +A few lines above, space is kzalloc()'ed for: + sizeof(struct iwl_nvm_data) + + sizeof(struct ieee80211_channel) + + sizeof(struct ieee80211_rate) + +'mvm->nvm_data' is a 'struct iwl_nvm_data', so it is fine. + +At the end of this structure, there is the 'channels' flex array. +Each element is of type 'struct ieee80211_channel'. +So only 1 element is allocated in this array. + +When doing: + mvm->nvm_data->bands[0].channels = mvm->nvm_data->channels; +We point at the first element of the 'channels' flex array. +So this is fine. + +However, when doing: + mvm->nvm_data->bands[0].bitrates = + (void *)((u8 *)mvm->nvm_data->channels + 1); +because of the "(u8 *)" cast, we add only 1 to the address of the beginning +of the flex array. + +It is likely that we want point at the 'struct ieee80211_rate' allocated +just after. + +Remove the spurious casting so that the pointer arithmetic works as +expected. + +Fixes: 8ca151b568b6 ("iwlwifi: add the MVM driver") +Signed-off-by: Christophe JAILLET +Acked-by: Gregory Greenman +Link: https://lore.kernel.org/r/23f0ec986ef1529055f4f93dcb3940a6cf8d9a94.1690143750.git.christophe.jaillet@wanadoo.fr +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +index 887d0789c96c3..2e3c98eaa400c 100644 +--- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c ++++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +@@ -796,7 +796,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm) + mvm->nvm_data->bands[0].n_channels = 1; + mvm->nvm_data->bands[0].n_bitrates = 1; + mvm->nvm_data->bands[0].bitrates = +- (void *)((u8 *)mvm->nvm_data->channels + 1); ++ (void *)(mvm->nvm_data->channels + 1); + mvm->nvm_data->bands[0].bitrates->hw_value = 10; + } + +-- +2.40.1 + diff --git a/queue-6.1/wifi-mac80211-fix-potential-key-use-after-free.patch b/queue-6.1/wifi-mac80211-fix-potential-key-use-after-free.patch new file mode 100644 index 00000000000..0247d5c6e9a --- /dev/null +++ b/queue-6.1/wifi-mac80211-fix-potential-key-use-after-free.patch @@ -0,0 +1,58 @@ +From f5f82238f8d774751dea488297257f5ab91b6764 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Sep 2023 08:34:15 +0200 +Subject: wifi: mac80211: fix potential key use-after-free + +From: Johannes Berg + +[ Upstream commit 31db78a4923ef5e2008f2eed321811ca79e7f71b ] + +When ieee80211_key_link() is called by ieee80211_gtk_rekey_add() +but returns 0 due to KRACK protection (identical key reinstall), +ieee80211_gtk_rekey_add() will still return a pointer into the +key, in a potential use-after-free. This normally doesn't happen +since it's only called by iwlwifi in case of WoWLAN rekey offload +which has its own KRACK protection, but still better to fix, do +that by returning an error code and converting that to success on +the cfg80211 boundary only, leaving the error for bad callers of +ieee80211_gtk_rekey_add(). + +Reported-by: Dan Carpenter +Fixes: fdf7cb4185b6 ("mac80211: accept key reinstall without changing anything") +Signed-off-by: Johannes Berg +Signed-off-by: Sasha Levin +--- + net/mac80211/cfg.c | 3 +++ + net/mac80211/key.c | 2 +- + 2 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c +index cf3453b532d67..0167413d56972 100644 +--- a/net/mac80211/cfg.c ++++ b/net/mac80211/cfg.c +@@ -566,6 +566,9 @@ static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev, + } + + err = ieee80211_key_link(key, link, sta); ++ /* KRACK protection, shouldn't happen but just silently accept key */ ++ if (err == -EALREADY) ++ err = 0; + + out_unlock: + mutex_unlock(&local->sta_mtx); +diff --git a/net/mac80211/key.c b/net/mac80211/key.c +index e8f6c1e5eabfc..23bb24243c6e9 100644 +--- a/net/mac80211/key.c ++++ b/net/mac80211/key.c +@@ -901,7 +901,7 @@ int ieee80211_key_link(struct ieee80211_key *key, + */ + if (ieee80211_key_identical(sdata, old_key, key)) { + ieee80211_key_free_unused(key); +- ret = 0; ++ ret = -EALREADY; + goto out; + } + +-- +2.40.1 + diff --git a/queue-6.1/wifi-mt76-mt76x02-fix-mt76x0-external-lna-gain-handl.patch b/queue-6.1/wifi-mt76-mt76x02-fix-mt76x0-external-lna-gain-handl.patch new file mode 100644 index 00000000000..edc35e50310 --- /dev/null +++ b/queue-6.1/wifi-mt76-mt76x02-fix-mt76x0-external-lna-gain-handl.patch @@ -0,0 +1,78 @@ +From fefa6bff101e8caedac02461280e51e6976d351e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 19 Sep 2023 21:47:47 +0200 +Subject: wifi: mt76: mt76x02: fix MT76x0 external LNA gain handling + +From: Felix Fietkau + +[ Upstream commit 684e45e120b82deccaf8b85633905304a3bbf56d ] + +On MT76x0, LNA gain should be applied for both external and internal LNA. +On MT76x2, LNA gain should be treated as 0 for external LNA. +Move the LNA type based logic to mt76x2 in order to fix mt76x0. + +Fixes: 2daa67588f34 ("mt76x0: unify lna_gain parsing") +Reported-by: Shiji Yang +Signed-off-by: Felix Fietkau +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230919194747.31647-1-nbd@nbd.name +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c | 7 ------- + drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c | 13 +++++++++++-- + 2 files changed, 11 insertions(+), 9 deletions(-) + +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c +index 0acabba2d1a50..5d402cf2951cb 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x02_eeprom.c +@@ -131,15 +131,8 @@ u8 mt76x02_get_lna_gain(struct mt76x02_dev *dev, + s8 *lna_2g, s8 *lna_5g, + struct ieee80211_channel *chan) + { +- u16 val; + u8 lna; + +- val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1); +- if (val & MT_EE_NIC_CONF_1_LNA_EXT_2G) +- *lna_2g = 0; +- if (val & MT_EE_NIC_CONF_1_LNA_EXT_5G) +- memset(lna_5g, 0, sizeof(s8) * 3); +- + if (chan->band == NL80211_BAND_2GHZ) + lna = *lna_2g; + else if (chan->hw_value <= 64) +diff --git a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c +index c57e05a5c65e4..91807bf662dde 100644 +--- a/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c ++++ b/drivers/net/wireless/mediatek/mt76/mt76x2/eeprom.c +@@ -256,7 +256,8 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev) + struct ieee80211_channel *chan = dev->mphy.chandef.chan; + int channel = chan->hw_value; + s8 lna_5g[3], lna_2g; +- u8 lna; ++ bool use_lna; ++ u8 lna = 0; + u16 val; + + if (chan->band == NL80211_BAND_2GHZ) +@@ -275,7 +276,15 @@ void mt76x2_read_rx_gain(struct mt76x02_dev *dev) + dev->cal.rx.mcu_gain |= (lna_5g[1] & 0xff) << 16; + dev->cal.rx.mcu_gain |= (lna_5g[2] & 0xff) << 24; + +- lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan); ++ val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1); ++ if (chan->band == NL80211_BAND_2GHZ) ++ use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_2G); ++ else ++ use_lna = !(val & MT_EE_NIC_CONF_1_LNA_EXT_5G); ++ ++ if (use_lna) ++ lna = mt76x02_get_lna_gain(dev, &lna_2g, lna_5g, chan); ++ + dev->cal.rx.lna_gain = mt76x02_sign_extend(lna, 8); + } + EXPORT_SYMBOL_GPL(mt76x2_read_rx_gain); +-- +2.40.1 + diff --git a/queue-6.1/wifi-mwifiex-fix-oob-check-condition-in-mwifiex_proc.patch b/queue-6.1/wifi-mwifiex-fix-oob-check-condition-in-mwifiex_proc.patch new file mode 100644 index 00000000000..f240c95ce48 --- /dev/null +++ b/queue-6.1/wifi-mwifiex-fix-oob-check-condition-in-mwifiex_proc.patch @@ -0,0 +1,61 @@ +From c6a9b1821e0e82f5ed4c46fbe703342e8e290de7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 8 Sep 2023 18:41:12 +0800 +Subject: wifi: mwifiex: Fix oob check condition in mwifiex_process_rx_packet + +From: Pin-yen Lin + +[ Upstream commit aef7a0300047e7b4707ea0411dc9597cba108fc8 ] + +Only skip the code path trying to access the rfc1042 headers when the +buffer is too small, so the driver can still process packets without +rfc1042 headers. + +Fixes: 119585281617 ("wifi: mwifiex: Fix OOB and integer underflow when rx packets") +Signed-off-by: Pin-yen Lin +Acked-by: Brian Norris +Reviewed-by: Matthew Wang +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230908104308.1546501-1-treapking@chromium.org +Signed-off-by: Sasha Levin +--- + drivers/net/wireless/marvell/mwifiex/sta_rx.c | 16 +++++++++------- + 1 file changed, 9 insertions(+), 7 deletions(-) + +diff --git a/drivers/net/wireless/marvell/mwifiex/sta_rx.c b/drivers/net/wireless/marvell/mwifiex/sta_rx.c +index 65420ad674167..257737137cd70 100644 +--- a/drivers/net/wireless/marvell/mwifiex/sta_rx.c ++++ b/drivers/net/wireless/marvell/mwifiex/sta_rx.c +@@ -86,7 +86,8 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, + rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length); + rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off; + +- if (sizeof(*rx_pkt_hdr) + rx_pkt_off > skb->len) { ++ if (sizeof(rx_pkt_hdr->eth803_hdr) + sizeof(rfc1042_header) + ++ rx_pkt_off > skb->len) { + mwifiex_dbg(priv->adapter, ERROR, + "wrong rx packet offset: len=%d, rx_pkt_off=%d\n", + skb->len, rx_pkt_off); +@@ -95,12 +96,13 @@ int mwifiex_process_rx_packet(struct mwifiex_private *priv, + return -1; + } + +- if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, +- sizeof(bridge_tunnel_header))) || +- (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, +- sizeof(rfc1042_header)) && +- ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && +- ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) { ++ if (sizeof(*rx_pkt_hdr) + rx_pkt_off <= skb->len && ++ ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, ++ sizeof(bridge_tunnel_header))) || ++ (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, ++ sizeof(rfc1042_header)) && ++ ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && ++ ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX))) { + /* + * Replace the 803 header and rfc1042 header (llc/snap) with an + * EthernetII header, keep the src/dst and snap_type +-- +2.40.1 +