From: Greg Kroah-Hartman Date: Sat, 10 Apr 2021 14:34:23 +0000 (+0200) Subject: 5.11-stable patches X-Git-Tag: v4.19.187~57 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=66e8739d2fe75aa45ddc83ff0a64aa739de282b6;p=thirdparty%2Fkernel%2Fstable-queue.git 5.11-stable patches added patches: batman-adv-initialize-struct-batadv_tvlv_tt_vlan_data-reserved-field.patch bpf-enforce-that-struct_ops-programs-be-gpl-only.patch bpf-link-refuse-non-o_rdwr-flags-in-bpf_obj_get.patch bpf-refcount-task-stack-in-bpf_get_task_stack.patch bpf-sockmap-fix-incorrect-fwd_alloc-accounting.patch bpf-sockmap-fix-sk-prot-unhash-op-reset.patch cfg80211-check-s1g-beacon-compat-element-length.patch ethernet-netronome-nfp-fix-a-use-after-free-in-nfp_bpf_ctrl_msg_rx.patch i40e-fix-sparse-error-uninitialized-symbol-ring.patch i40e-fix-sparse-error-vsi-netdev-could-be-null.patch i40e-fix-sparse-errors-in-i40e_txrx.c.patch i40e-fix-sparse-warning-missing-error-code-err.patch ice-cleanup-fltr-list-in-case-of-allocation-issues.patch ice-continue-probe-on-link-phy-errors.patch ice-fix-for-dereference-of-null-pointer.patch ice-fix-memory-allocation-call.patch ice-fix-memory-leak-of-arfs-after-resuming-from-suspend.patch ice-increase-control-queue-timeout.patch ice-prevent-ice_open-and-ice_stop-during-reset.patch ice-remove-dcbnl_devreset-bit-from-pf-state.patch ice-use-port-number-instead-of-pf-id-for-wol.patch iwlwifi-pcie-properly-set-ltr-workarounds-on-22000-devices.patch libbpf-ensure-umem-pointer-is-non-null-before-dereferencing.patch libbpf-fix-bail-out-from-ringbuf_process_ring-on-error.patch libbpf-only-create-rx-and-tx-xdp-rings-when-necessary.patch libbpf-restore-umem-state-after-socket-create-failure.patch mac80211-fix-time-is-after-bug-in-mlme.patch mac80211-fix-txq-ac-confusion.patch net-ensure-mac-header-is-set-in-virtio_net_hdr_to_skb.patch net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch net-hsr-reset-mac-header-for-tx-path.patch net-ipv6-bugfix-raw-sctp-switch-to-ipv6_can_nonlocal_bind.patch net-let-skb_orphan_partial-wake-up-waiters.patch net-sched-fix-action-overwrite-reference-counting.patch net-sched-sch_teql-fix-null-pointer-dereference.patch nl80211-fix-beacon-head-validation.patch nl80211-fix-potential-leak-of-acl-params.patch vdpa-mlx5-fix-suspend-resume-index-restoration.patch virtio_net-do-not-pull-payload-in-skb-head.patch --- diff --git a/queue-5.11/batman-adv-initialize-struct-batadv_tvlv_tt_vlan_data-reserved-field.patch b/queue-5.11/batman-adv-initialize-struct-batadv_tvlv_tt_vlan_data-reserved-field.patch new file mode 100644 index 00000000000..1d32d56ba44 --- /dev/null +++ b/queue-5.11/batman-adv-initialize-struct-batadv_tvlv_tt_vlan_data-reserved-field.patch @@ -0,0 +1,48 @@ +From 08c27f3322fec11950b8f1384aa0f3b11d028528 Mon Sep 17 00:00:00 2001 +From: Tetsuo Handa +Date: Mon, 5 Apr 2021 19:16:50 +0900 +Subject: batman-adv: initialize "struct batadv_tvlv_tt_vlan_data"->reserved field + +From: Tetsuo Handa + +commit 08c27f3322fec11950b8f1384aa0f3b11d028528 upstream. + +KMSAN found uninitialized value at batadv_tt_prepare_tvlv_local_data() +[1], for commit ced72933a5e8ab52 ("batman-adv: use CRC32C instead of CRC16 +in TT code") inserted 'reserved' field into "struct batadv_tvlv_tt_data" +and commit 7ea7b4a142758dea ("batman-adv: make the TT CRC logic VLAN +specific") moved that field to "struct batadv_tvlv_tt_vlan_data" but left +that field uninitialized. + +[1] https://syzkaller.appspot.com/bug?id=07f3e6dba96f0eb3cabab986adcd8a58b9bdbe9d + +Reported-by: syzbot +Tested-by: syzbot +Signed-off-by: Tetsuo Handa +Fixes: ced72933a5e8ab52 ("batman-adv: use CRC32C instead of CRC16 in TT code") +Fixes: 7ea7b4a142758dea ("batman-adv: make the TT CRC logic VLAN specific") +Acked-by: Sven Eckelmann +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/batman-adv/translation-table.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/batman-adv/translation-table.c ++++ b/net/batman-adv/translation-table.c +@@ -890,6 +890,7 @@ batadv_tt_prepare_tvlv_global_data(struc + hlist_for_each_entry(vlan, &orig_node->vlan_list, list) { + tt_vlan->vid = htons(vlan->vid); + tt_vlan->crc = htonl(vlan->tt.crc); ++ tt_vlan->reserved = 0; + + tt_vlan++; + } +@@ -973,6 +974,7 @@ batadv_tt_prepare_tvlv_local_data(struct + + tt_vlan->vid = htons(vlan->vid); + tt_vlan->crc = htonl(vlan->tt.crc); ++ tt_vlan->reserved = 0; + + tt_vlan++; + } diff --git a/queue-5.11/bpf-enforce-that-struct_ops-programs-be-gpl-only.patch b/queue-5.11/bpf-enforce-that-struct_ops-programs-be-gpl-only.patch new file mode 100644 index 00000000000..420bbd50c81 --- /dev/null +++ b/queue-5.11/bpf-enforce-that-struct_ops-programs-be-gpl-only.patch @@ -0,0 +1,48 @@ +From 12aa8a9467b354ef893ce0fc5719a4de4949a9fb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= +Date: Fri, 26 Mar 2021 11:03:13 +0100 +Subject: bpf: Enforce that struct_ops programs be GPL-only +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Toke Høiland-Jørgensen + +commit 12aa8a9467b354ef893ce0fc5719a4de4949a9fb upstream. + +With the introduction of the struct_ops program type, it became possible to +implement kernel functionality in BPF, making it viable to use BPF in place +of a regular kernel module for these particular operations. + +Thus far, the only user of this mechanism is for implementing TCP +congestion control algorithms. These are clearly marked as GPL-only when +implemented as modules (as seen by the use of EXPORT_SYMBOL_GPL for +tcp_register_congestion_control()), so it seems like an oversight that this +was not carried over to BPF implementations. Since this is the only user +of the struct_ops mechanism, just enforcing GPL-only for the struct_ops +program type seems like the simplest way to fix this. + +Fixes: 0baf26b0fcd7 ("bpf: tcp: Support tcp_congestion_ops in bpf") +Signed-off-by: Toke Høiland-Jørgensen +Signed-off-by: Daniel Borkmann +Acked-by: Martin KaFai Lau +Link: https://lore.kernel.org/bpf/20210326100314.121853-1-toke@redhat.com +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/verifier.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -11570,6 +11570,11 @@ static int check_struct_ops_btf_id(struc + u32 btf_id, member_idx; + const char *mname; + ++ if (!prog->gpl_compatible) { ++ verbose(env, "struct ops programs must have a GPL compatible license\n"); ++ return -EINVAL; ++ } ++ + btf_id = prog->aux->attach_btf_id; + st_ops = bpf_struct_ops_find(btf_id); + if (!st_ops) { diff --git a/queue-5.11/bpf-link-refuse-non-o_rdwr-flags-in-bpf_obj_get.patch b/queue-5.11/bpf-link-refuse-non-o_rdwr-flags-in-bpf_obj_get.patch new file mode 100644 index 00000000000..5426a10cb29 --- /dev/null +++ b/queue-5.11/bpf-link-refuse-non-o_rdwr-flags-in-bpf_obj_get.patch @@ -0,0 +1,42 @@ +From 25fc94b2f02d832fa8e29419699dcc20b0b05c6a Mon Sep 17 00:00:00 2001 +From: Lorenz Bauer +Date: Fri, 26 Mar 2021 16:05:00 +0000 +Subject: bpf: link: Refuse non-O_RDWR flags in BPF_OBJ_GET + +From: Lorenz Bauer + +commit 25fc94b2f02d832fa8e29419699dcc20b0b05c6a upstream. + +Invoking BPF_OBJ_GET on a pinned bpf_link checks the path access +permissions based on file_flags, but the returned fd ignores flags. +This means that any user can acquire a "read-write" fd for a pinned +link with mode 0664 by invoking BPF_OBJ_GET with BPF_F_RDONLY in +file_flags. The fd can be used to invoke BPF_LINK_DETACH, etc. + +Fix this by refusing non-O_RDWR flags in BPF_OBJ_GET. This works +because OBJ_GET by default returns a read write mapping and libbpf +doesn't expose a way to override this behaviour for programs +and links. + +Fixes: 70ed506c3bbc ("bpf: Introduce pinnable bpf_link abstraction") +Signed-off-by: Lorenz Bauer +Signed-off-by: Alexei Starovoitov +Acked-by: Andrii Nakryiko +Acked-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/20210326160501.46234-1-lmb@cloudflare.com +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/inode.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/kernel/bpf/inode.c ++++ b/kernel/bpf/inode.c +@@ -546,7 +546,7 @@ int bpf_obj_get_user(const char __user * + else if (type == BPF_TYPE_MAP) + ret = bpf_map_new_fd(raw, f_flags); + else if (type == BPF_TYPE_LINK) +- ret = bpf_link_new_fd(raw); ++ ret = (f_flags != O_RDWR) ? -EINVAL : bpf_link_new_fd(raw); + else + return -ENOENT; + diff --git a/queue-5.11/bpf-refcount-task-stack-in-bpf_get_task_stack.patch b/queue-5.11/bpf-refcount-task-stack-in-bpf_get_task_stack.patch new file mode 100644 index 00000000000..d1267f1e72a --- /dev/null +++ b/queue-5.11/bpf-refcount-task-stack-in-bpf_get_task_stack.patch @@ -0,0 +1,75 @@ +From 06ab134ce8ecfa5a69e850f88f81c8a4c3fa91df Mon Sep 17 00:00:00 2001 +From: Dave Marchevsky +Date: Wed, 31 Mar 2021 17:07:47 -0700 +Subject: bpf: Refcount task stack in bpf_get_task_stack + +From: Dave Marchevsky + +commit 06ab134ce8ecfa5a69e850f88f81c8a4c3fa91df upstream. + +On x86 the struct pt_regs * grabbed by task_pt_regs() points to an +offset of task->stack. The pt_regs are later dereferenced in +__bpf_get_stack (e.g. by user_mode() check). This can cause a fault if +the task in question exits while bpf_get_task_stack is executing, as +warned by task_stack_page's comment: + +* When accessing the stack of a non-current task that might exit, use +* try_get_task_stack() instead. task_stack_page will return a pointer +* that could get freed out from under you. + +Taking the comment's advice and using try_get_task_stack() and +put_task_stack() to hold task->stack refcount, or bail early if it's +already 0. Incrementing stack_refcount will ensure the task's stack +sticks around while we're using its data. + +I noticed this bug while testing a bpf task iter similar to +bpf_iter_task_stack in selftests, except mine grabbed user stack, and +getting intermittent crashes, which resulted in dumps like: + + BUG: unable to handle page fault for address: 0000000000003fe0 + \#PF: supervisor read access in kernel mode + \#PF: error_code(0x0000) - not-present page + RIP: 0010:__bpf_get_stack+0xd0/0x230 + + Call Trace: + bpf_prog_0a2be35c092cb190_get_task_stacks+0x5d/0x3ec + bpf_iter_run_prog+0x24/0x81 + __task_seq_show+0x58/0x80 + bpf_seq_read+0xf7/0x3d0 + vfs_read+0x91/0x140 + ksys_read+0x59/0xd0 + do_syscall_64+0x48/0x120 + entry_SYSCALL_64_after_hwframe+0x44/0xa9 + +Fixes: fa28dcb82a38 ("bpf: Introduce helper bpf_get_task_stack()") +Signed-off-by: Dave Marchevsky +Signed-off-by: Alexei Starovoitov +Acked-by: Song Liu +Link: https://lore.kernel.org/bpf/20210401000747.3648767-1-davemarchevsky@fb.com +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/stackmap.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/kernel/bpf/stackmap.c ++++ b/kernel/bpf/stackmap.c +@@ -652,9 +652,17 @@ const struct bpf_func_proto bpf_get_stac + BPF_CALL_4(bpf_get_task_stack, struct task_struct *, task, void *, buf, + u32, size, u64, flags) + { +- struct pt_regs *regs = task_pt_regs(task); ++ struct pt_regs *regs; ++ long res; + +- return __bpf_get_stack(regs, task, NULL, buf, size, flags); ++ if (!try_get_task_stack(task)) ++ return -EFAULT; ++ ++ regs = task_pt_regs(task); ++ res = __bpf_get_stack(regs, task, NULL, buf, size, flags); ++ put_task_stack(task); ++ ++ return res; + } + + BTF_ID_LIST_SINGLE(bpf_get_task_stack_btf_ids, struct, task_struct) diff --git a/queue-5.11/bpf-sockmap-fix-incorrect-fwd_alloc-accounting.patch b/queue-5.11/bpf-sockmap-fix-incorrect-fwd_alloc-accounting.patch new file mode 100644 index 00000000000..ecb102373bf --- /dev/null +++ b/queue-5.11/bpf-sockmap-fix-incorrect-fwd_alloc-accounting.patch @@ -0,0 +1,135 @@ +From 144748eb0c445091466c9b741ebd0bfcc5914f3d Mon Sep 17 00:00:00 2001 +From: John Fastabend +Date: Thu, 1 Apr 2021 15:00:40 -0700 +Subject: bpf, sockmap: Fix incorrect fwd_alloc accounting + +From: John Fastabend + +commit 144748eb0c445091466c9b741ebd0bfcc5914f3d upstream. + +Incorrect accounting fwd_alloc can result in a warning when the socket +is torn down, + + [18455.319240] WARNING: CPU: 0 PID: 24075 at net/core/stream.c:208 sk_stream_kill_queues+0x21f/0x230 + [...] + [18455.319543] Call Trace: + [18455.319556] inet_csk_destroy_sock+0xba/0x1f0 + [18455.319577] tcp_rcv_state_process+0x1b4e/0x2380 + [18455.319593] ? lock_downgrade+0x3a0/0x3a0 + [18455.319617] ? tcp_finish_connect+0x1e0/0x1e0 + [18455.319631] ? sk_reset_timer+0x15/0x70 + [18455.319646] ? tcp_schedule_loss_probe+0x1b2/0x240 + [18455.319663] ? lock_release+0xb2/0x3f0 + [18455.319676] ? __release_sock+0x8a/0x1b0 + [18455.319690] ? lock_downgrade+0x3a0/0x3a0 + [18455.319704] ? lock_release+0x3f0/0x3f0 + [18455.319717] ? __tcp_close+0x2c6/0x790 + [18455.319736] ? tcp_v4_do_rcv+0x168/0x370 + [18455.319750] tcp_v4_do_rcv+0x168/0x370 + [18455.319767] __release_sock+0xbc/0x1b0 + [18455.319785] __tcp_close+0x2ee/0x790 + [18455.319805] tcp_close+0x20/0x80 + +This currently happens because on redirect case we do skb_set_owner_r() +with the original sock. This increments the fwd_alloc memory accounting +on the original sock. Then on redirect we may push this into the queue +of the psock we are redirecting to. When the skb is flushed from the +queue we give the memory back to the original sock. The problem is if +the original sock is destroyed/closed with skbs on another psocks queue +then the original sock will not have a way to reclaim the memory before +being destroyed. Then above warning will be thrown + + sockA sockB + + sk_psock_strp_read() + sk_psock_verdict_apply() + -- SK_REDIRECT -- + sk_psock_skb_redirect() + skb_queue_tail(psock_other->ingress_skb..) + + sk_close() + sock_map_unref() + sk_psock_put() + sk_psock_drop() + sk_psock_zap_ingress() + +At this point we have torn down our own psock, but have the outstanding +skb in psock_other. Note that SK_PASS doesn't have this problem because +the sk_psock_drop() logic releases the skb, its still associated with +our psock. + +To resolve lets only account for sockets on the ingress queue that are +still associated with the current socket. On the redirect case we will +check memory limits per 6fa9201a89898, but will omit fwd_alloc accounting +until skb is actually enqueued. When the skb is sent via skb_send_sock_locked +or received with sk_psock_skb_ingress memory will be claimed on psock_other. + +Fixes: 6fa9201a89898 ("bpf, sockmap: Avoid returning unneeded EAGAIN when redirecting to self") +Reported-by: Andrii Nakryiko +Signed-off-by: John Fastabend +Signed-off-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/161731444013.68884.4021114312848535993.stgit@john-XPS-13-9370 +Signed-off-by: Greg Kroah-Hartman +--- + net/core/skmsg.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +--- a/net/core/skmsg.c ++++ b/net/core/skmsg.c +@@ -488,6 +488,7 @@ static int sk_psock_skb_ingress_self(str + if (unlikely(!msg)) + return -EAGAIN; + sk_msg_init(msg); ++ skb_set_owner_r(skb, sk); + return sk_psock_skb_ingress_enqueue(skb, psock, sk, msg); + } + +@@ -791,7 +792,6 @@ static void sk_psock_tls_verdict_apply(s + { + switch (verdict) { + case __SK_REDIRECT: +- skb_set_owner_r(skb, sk); + sk_psock_skb_redirect(skb); + break; + case __SK_PASS: +@@ -809,10 +809,6 @@ int sk_psock_tls_strp_read(struct sk_pso + rcu_read_lock(); + prog = READ_ONCE(psock->progs.skb_verdict); + if (likely(prog)) { +- /* We skip full set_owner_r here because if we do a SK_PASS +- * or SK_DROP we can skip skb memory accounting and use the +- * TLS context. +- */ + skb->sk = psock->sk; + tcp_skb_bpf_redirect_clear(skb); + ret = sk_psock_bpf_run(psock, prog, skb); +@@ -881,12 +877,13 @@ static void sk_psock_strp_read(struct st + kfree_skb(skb); + goto out; + } +- skb_set_owner_r(skb, sk); + prog = READ_ONCE(psock->progs.skb_verdict); + if (likely(prog)) { ++ skb->sk = sk; + tcp_skb_bpf_redirect_clear(skb); + ret = sk_psock_bpf_run(psock, prog, skb); + ret = sk_psock_map_verd(ret, tcp_skb_bpf_redirect_fetch(skb)); ++ skb->sk = NULL; + } + sk_psock_verdict_apply(psock, skb, ret); + out: +@@ -957,12 +954,13 @@ static int sk_psock_verdict_recv(read_de + kfree_skb(skb); + goto out; + } +- skb_set_owner_r(skb, sk); + prog = READ_ONCE(psock->progs.skb_verdict); + if (likely(prog)) { ++ skb->sk = sk; + tcp_skb_bpf_redirect_clear(skb); + ret = sk_psock_bpf_run(psock, prog, skb); + ret = sk_psock_map_verd(ret, tcp_skb_bpf_redirect_fetch(skb)); ++ skb->sk = NULL; + } + sk_psock_verdict_apply(psock, skb, ret); + out: diff --git a/queue-5.11/bpf-sockmap-fix-sk-prot-unhash-op-reset.patch b/queue-5.11/bpf-sockmap-fix-sk-prot-unhash-op-reset.patch new file mode 100644 index 00000000000..78b699ffddf --- /dev/null +++ b/queue-5.11/bpf-sockmap-fix-sk-prot-unhash-op-reset.patch @@ -0,0 +1,82 @@ +From 1c84b33101c82683dee8b06761ca1f69e78c8ee7 Mon Sep 17 00:00:00 2001 +From: John Fastabend +Date: Thu, 1 Apr 2021 15:00:19 -0700 +Subject: bpf, sockmap: Fix sk->prot unhash op reset + +From: John Fastabend + +commit 1c84b33101c82683dee8b06761ca1f69e78c8ee7 upstream. + +In '4da6a196f93b1' we fixed a potential unhash loop caused when +a TLS socket in a sockmap was removed from the sockmap. This +happened because the unhash operation on the TLS ctx continued +to point at the sockmap implementation of unhash even though the +psock has already been removed. The sockmap unhash handler when a +psock is removed does the following, + + void sock_map_unhash(struct sock *sk) + { + void (*saved_unhash)(struct sock *sk); + struct sk_psock *psock; + + rcu_read_lock(); + psock = sk_psock(sk); + if (unlikely(!psock)) { + rcu_read_unlock(); + if (sk->sk_prot->unhash) + sk->sk_prot->unhash(sk); + return; + } + [...] + } + +The unlikely() case is there to handle the case where psock is detached +but the proto ops have not been updated yet. But, in the above case +with TLS and removed psock we never fixed sk_prot->unhash() and unhash() +points back to sock_map_unhash resulting in a loop. To fix this we added +this bit of code, + + static inline void sk_psock_restore_proto(struct sock *sk, + struct sk_psock *psock) + { + sk->sk_prot->unhash = psock->saved_unhash; + +This will set the sk_prot->unhash back to its saved value. This is the +correct callback for a TLS socket that has been removed from the sock_map. +Unfortunately, this also overwrites the unhash pointer for all psocks. +We effectively break sockmap unhash handling for any future socks. +Omitting the unhash operation will leave stale entries in the map if +a socket transition through unhash, but does not do close() op. + +To fix set unhash correctly before calling into tls_update. This way the +TLS enabled socket will point to the saved unhash() handler. + +Fixes: 4da6a196f93b1 ("bpf: Sockmap/tls, during free we may call tcp_bpf_unhash() in loop") +Reported-by: Cong Wang +Reported-by: Lorenz Bauer +Suggested-by: Cong Wang +Signed-off-by: John Fastabend +Signed-off-by: Daniel Borkmann +Link: https://lore.kernel.org/bpf/161731441904.68884.15593917809745631972.stgit@john-XPS-13-9370 +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/skmsg.h | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/include/linux/skmsg.h ++++ b/include/linux/skmsg.h +@@ -349,8 +349,13 @@ static inline void sk_psock_update_proto + static inline void sk_psock_restore_proto(struct sock *sk, + struct sk_psock *psock) + { +- sk->sk_prot->unhash = psock->saved_unhash; + if (inet_csk_has_ulp(sk)) { ++ /* TLS does not have an unhash proto in SW cases, but we need ++ * to ensure we stop using the sock_map unhash routine because ++ * the associated psock is being removed. So use the original ++ * unhash handler. ++ */ ++ WRITE_ONCE(sk->sk_prot->unhash, psock->saved_unhash); + tcp_update_ulp(sk, psock->sk_proto, psock->saved_write_space); + } else { + sk->sk_write_space = psock->saved_write_space; diff --git a/queue-5.11/cfg80211-check-s1g-beacon-compat-element-length.patch b/queue-5.11/cfg80211-check-s1g-beacon-compat-element-length.patch new file mode 100644 index 00000000000..2bde8265b18 --- /dev/null +++ b/queue-5.11/cfg80211-check-s1g-beacon-compat-element-length.patch @@ -0,0 +1,45 @@ +From b5ac0146492fc5c199de767e492be8a66471011a Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 8 Apr 2021 14:28:27 +0200 +Subject: cfg80211: check S1G beacon compat element length + +From: Johannes Berg + +commit b5ac0146492fc5c199de767e492be8a66471011a upstream. + +We need to check the length of this element so that we don't +access data beyond its end. Fix that. + +Fixes: 9eaffe5078ca ("cfg80211: convert S1G beacon to scan results") +Link: https://lore.kernel.org/r/20210408142826.f6f4525012de.I9fdeff0afdc683a6024e5ea49d2daa3cd2459d11@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/wireless/scan.c | 14 ++++++++------ + 1 file changed, 8 insertions(+), 6 deletions(-) + +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -2352,14 +2352,16 @@ cfg80211_inform_single_bss_frame_data(st + return NULL; + + if (ext) { +- struct ieee80211_s1g_bcn_compat_ie *compat; +- u8 *ie; ++ const struct ieee80211_s1g_bcn_compat_ie *compat; ++ const struct element *elem; + +- ie = (void *)cfg80211_find_ie(WLAN_EID_S1G_BCN_COMPAT, +- variable, ielen); +- if (!ie) ++ elem = cfg80211_find_elem(WLAN_EID_S1G_BCN_COMPAT, ++ variable, ielen); ++ if (!elem) + return NULL; +- compat = (void *)(ie + 2); ++ if (elem->datalen < sizeof(*compat)) ++ return NULL; ++ compat = (void *)elem->data; + bssid = ext->u.s1g_beacon.sa; + capability = le16_to_cpu(compat->compat_info); + beacon_int = le16_to_cpu(compat->beacon_int); diff --git a/queue-5.11/ethernet-netronome-nfp-fix-a-use-after-free-in-nfp_bpf_ctrl_msg_rx.patch b/queue-5.11/ethernet-netronome-nfp-fix-a-use-after-free-in-nfp_bpf_ctrl_msg_rx.patch new file mode 100644 index 00000000000..e63a42fbdc9 --- /dev/null +++ b/queue-5.11/ethernet-netronome-nfp-fix-a-use-after-free-in-nfp_bpf_ctrl_msg_rx.patch @@ -0,0 +1,34 @@ +From 6e5a03bcba44e080a6bf300194a68ce9bb1e5184 Mon Sep 17 00:00:00 2001 +From: Lv Yunlong +Date: Mon, 29 Mar 2021 04:50:02 -0700 +Subject: ethernet/netronome/nfp: Fix a use after free in nfp_bpf_ctrl_msg_rx + +From: Lv Yunlong + +commit 6e5a03bcba44e080a6bf300194a68ce9bb1e5184 upstream. + +In nfp_bpf_ctrl_msg_rx, if +nfp_ccm_get_type(skb) == NFP_CCM_TYPE_BPF_BPF_EVENT is true, the skb +will be freed. But the skb is still used by nfp_ccm_rx(&bpf->ccm, skb). + +My patch adds a return when the skb was freed. + +Fixes: bcf0cafab44fd ("nfp: split out common control message handling code") +Signed-off-by: Lv Yunlong +Reviewed-by: Jakub Kicinski +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/netronome/nfp/bpf/cmsg.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c ++++ b/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c +@@ -454,6 +454,7 @@ void nfp_bpf_ctrl_msg_rx(struct nfp_app + dev_consume_skb_any(skb); + else + dev_kfree_skb_any(skb); ++ return; + } + + nfp_ccm_rx(&bpf->ccm, skb); diff --git a/queue-5.11/i40e-fix-sparse-error-uninitialized-symbol-ring.patch b/queue-5.11/i40e-fix-sparse-error-uninitialized-symbol-ring.patch new file mode 100644 index 00000000000..be7d22aa6cf --- /dev/null +++ b/queue-5.11/i40e-fix-sparse-error-uninitialized-symbol-ring.patch @@ -0,0 +1,36 @@ +From d6d04ee6d2c9bb5084c8f6074195d6aa0024e825 Mon Sep 17 00:00:00 2001 +From: Arkadiusz Kubalewski +Date: Fri, 26 Mar 2021 19:43:41 +0100 +Subject: i40e: Fix sparse error: uninitialized symbol 'ring' + +From: Arkadiusz Kubalewski + +commit d6d04ee6d2c9bb5084c8f6074195d6aa0024e825 upstream. + +Init pointer with NULL in default switch case statement. + +Previously the error was produced when compiling against sparse. +i40e_debugfs.c:582 i40e_dbg_dump_desc() error: uninitialized symbol 'ring'. + +Fixes: 44ea803e2fa7 ("i40e: introduce new dump desc XDP command") +Signed-off-by: Aleksandr Loktionov +Signed-off-by: Arkadiusz Kubalewski +Tested-by: Dave Switzer +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +@@ -578,6 +578,9 @@ static void i40e_dbg_dump_desc(int cnt, + case RING_TYPE_XDP: + ring = kmemdup(vsi->xdp_rings[ring_id], sizeof(*ring), GFP_KERNEL); + break; ++ default: ++ ring = NULL; ++ break; + } + if (!ring) + return; diff --git a/queue-5.11/i40e-fix-sparse-error-vsi-netdev-could-be-null.patch b/queue-5.11/i40e-fix-sparse-error-vsi-netdev-could-be-null.patch new file mode 100644 index 00000000000..97bf14774f1 --- /dev/null +++ b/queue-5.11/i40e-fix-sparse-error-vsi-netdev-could-be-null.patch @@ -0,0 +1,39 @@ +From 6b5674fe6b9bf05394886ebcec62b2d7dae88c42 Mon Sep 17 00:00:00 2001 +From: Arkadiusz Kubalewski +Date: Fri, 26 Mar 2021 19:43:42 +0100 +Subject: i40e: Fix sparse error: 'vsi->netdev' could be null + +From: Arkadiusz Kubalewski + +commit 6b5674fe6b9bf05394886ebcec62b2d7dae88c42 upstream. + +Remove vsi->netdev->name from the trace. +This is redundant information. With the devinfo trace, the adapter +is already identifiable. + +Previously following error was produced when compiling against sparse. +i40e_main.c:2571 i40e_sync_vsi_filters() error: + we previously assumed 'vsi->netdev' could be null (see line 2323) + +Fixes: b603f9dc20af ("i40e: Log info when PF is entering and leaving Allmulti mode.") +Signed-off-by: Aleksandr Loktionov +Signed-off-by: Arkadiusz Kubalewski +Tested-by: Dave Switzer +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/i40e/i40e_main.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -2560,8 +2560,7 @@ int i40e_sync_vsi_filters(struct i40e_vs + i40e_stat_str(hw, aq_ret), + i40e_aq_str(hw, hw->aq.asq_last_status)); + } else { +- dev_info(&pf->pdev->dev, "%s is %s allmulti mode.\n", +- vsi->netdev->name, ++ dev_info(&pf->pdev->dev, "%s allmulti mode.\n", + cur_multipromisc ? "entering" : "leaving"); + } + } diff --git a/queue-5.11/i40e-fix-sparse-errors-in-i40e_txrx.c.patch b/queue-5.11/i40e-fix-sparse-errors-in-i40e_txrx.c.patch new file mode 100644 index 00000000000..53aaff43c44 --- /dev/null +++ b/queue-5.11/i40e-fix-sparse-errors-in-i40e_txrx.c.patch @@ -0,0 +1,76 @@ +From 12738ac4754ec92a6a45bf3677d8da780a1412b3 Mon Sep 17 00:00:00 2001 +From: Arkadiusz Kubalewski +Date: Fri, 26 Mar 2021 19:43:40 +0100 +Subject: i40e: Fix sparse errors in i40e_txrx.c + +From: Arkadiusz Kubalewski + +commit 12738ac4754ec92a6a45bf3677d8da780a1412b3 upstream. + +Remove error handling through pointers. Instead use plain int +to return value from i40e_run_xdp(...). + +Previously: +- sparse errors were produced during compilation: +i40e_txrx.c:2338 i40e_run_xdp() error: (-2147483647) too low for ERR_PTR +i40e_txrx.c:2558 i40e_clean_rx_irq() error: 'skb' dereferencing possible ERR_PTR() + +- sk_buff* was used to return value, but it has never had valid +pointer to sk_buff. Returned value was always int handled as +a pointer. + +Fixes: 0c8493d90b6b ("i40e: add XDP support for pass and drop actions") +Fixes: 2e6893123830 ("i40e: split XDP_TX tail and XDP_REDIRECT map flushing") +Signed-off-by: Aleksandr Loktionov +Signed-off-by: Arkadiusz Kubalewski +Tested-by: Dave Switzer +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/i40e/i40e_txrx.c | 12 +++++------- + 1 file changed, 5 insertions(+), 7 deletions(-) + +--- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c +@@ -2198,8 +2198,7 @@ int i40e_xmit_xdp_tx_ring(struct xdp_buf + * @rx_ring: Rx ring being processed + * @xdp: XDP buffer containing the frame + **/ +-static struct sk_buff *i40e_run_xdp(struct i40e_ring *rx_ring, +- struct xdp_buff *xdp) ++static int i40e_run_xdp(struct i40e_ring *rx_ring, struct xdp_buff *xdp) + { + int err, result = I40E_XDP_PASS; + struct i40e_ring *xdp_ring; +@@ -2238,7 +2237,7 @@ static struct sk_buff *i40e_run_xdp(stru + } + xdp_out: + rcu_read_unlock(); +- return ERR_PTR(-result); ++ return result; + } + + /** +@@ -2350,6 +2349,7 @@ static int i40e_clean_rx_irq(struct i40e + unsigned int xdp_xmit = 0; + bool failure = false; + struct xdp_buff xdp; ++ int xdp_res = 0; + + #if (PAGE_SIZE < 8192) + xdp.frame_sz = i40e_rx_frame_truesize(rx_ring, 0); +@@ -2416,12 +2416,10 @@ static int i40e_clean_rx_irq(struct i40e + /* At larger PAGE_SIZE, frame_sz depend on len size */ + xdp.frame_sz = i40e_rx_frame_truesize(rx_ring, size); + #endif +- skb = i40e_run_xdp(rx_ring, &xdp); ++ xdp_res = i40e_run_xdp(rx_ring, &xdp); + } + +- if (IS_ERR(skb)) { +- unsigned int xdp_res = -PTR_ERR(skb); +- ++ if (xdp_res) { + if (xdp_res & (I40E_XDP_TX | I40E_XDP_REDIR)) { + xdp_xmit |= xdp_res; + i40e_rx_buffer_flip(rx_ring, rx_buffer, size); diff --git a/queue-5.11/i40e-fix-sparse-warning-missing-error-code-err.patch b/queue-5.11/i40e-fix-sparse-warning-missing-error-code-err.patch new file mode 100644 index 00000000000..e94c3350d0f --- /dev/null +++ b/queue-5.11/i40e-fix-sparse-warning-missing-error-code-err.patch @@ -0,0 +1,45 @@ +From 8a1e918d833ca5c391c4ded5dc006e2d1ce6d37c Mon Sep 17 00:00:00 2001 +From: Arkadiusz Kubalewski +Date: Fri, 26 Mar 2021 19:43:43 +0100 +Subject: i40e: Fix sparse warning: missing error code 'err' + +From: Arkadiusz Kubalewski + +commit 8a1e918d833ca5c391c4ded5dc006e2d1ce6d37c upstream. + +Set proper return values inside error checking if-statements. + +Previously following warning was produced when compiling against sparse. +i40e_main.c:15162 i40e_init_recovery_mode() warn: missing error code 'err' + +Fixes: 4ff0ee1af0169 ("i40e: Introduce recovery mode support") +Signed-off-by: Aleksandr Loktionov +Signed-off-by: Arkadiusz Kubalewski +Tested-by: Dave Switzer +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/i40e/i40e_main.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -14647,12 +14647,16 @@ static int i40e_init_recovery_mode(struc + * in order to register the netdev + */ + v_idx = i40e_vsi_mem_alloc(pf, I40E_VSI_MAIN); +- if (v_idx < 0) ++ if (v_idx < 0) { ++ err = v_idx; + goto err_switch_setup; ++ } + pf->lan_vsi = v_idx; + vsi = pf->vsi[v_idx]; +- if (!vsi) ++ if (!vsi) { ++ err = -EFAULT; + goto err_switch_setup; ++ } + vsi->alloc_queue_pairs = 1; + err = i40e_config_netdev(vsi); + if (err) diff --git a/queue-5.11/ice-cleanup-fltr-list-in-case-of-allocation-issues.patch b/queue-5.11/ice-cleanup-fltr-list-in-case-of-allocation-issues.patch new file mode 100644 index 00000000000..e3f43398d29 --- /dev/null +++ b/queue-5.11/ice-cleanup-fltr-list-in-case-of-allocation-issues.patch @@ -0,0 +1,44 @@ +From b7eeb52721fe417730fc5adc5cbeeb5fe349ab26 Mon Sep 17 00:00:00 2001 +From: Robert Malz +Date: Fri, 26 Feb 2021 13:19:32 -0800 +Subject: ice: Cleanup fltr list in case of allocation issues + +From: Robert Malz + +commit b7eeb52721fe417730fc5adc5cbeeb5fe349ab26 upstream. + +When ice_remove_vsi_lkup_fltr is called, by calling +ice_add_to_vsi_fltr_list local copy of vsi filter list +is created. If any issues during creation of vsi filter +list occurs it up for the caller to free already +allocated memory. This patch ensures proper memory +deallocation in these cases. + +Fixes: 80d144c9ac82 ("ice: Refactor switch rule management structures and functions") +Signed-off-by: Robert Malz +Tested-by: Tony Brelinski +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/ice/ice_switch.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/net/ethernet/intel/ice/ice_switch.c ++++ b/drivers/net/ethernet/intel/ice/ice_switch.c +@@ -2624,7 +2624,7 @@ ice_remove_vsi_lkup_fltr(struct ice_hw * + &remove_list_head); + mutex_unlock(rule_lock); + if (status) +- return; ++ goto free_fltr_list; + + switch (lkup) { + case ICE_SW_LKUP_MAC: +@@ -2647,6 +2647,7 @@ ice_remove_vsi_lkup_fltr(struct ice_hw * + break; + } + ++free_fltr_list: + list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) { + list_del(&fm_entry->list_entry); + devm_kfree(ice_hw_to_dev(hw), fm_entry); diff --git a/queue-5.11/ice-continue-probe-on-link-phy-errors.patch b/queue-5.11/ice-continue-probe-on-link-phy-errors.patch new file mode 100644 index 00000000000..a92f2d7da5d --- /dev/null +++ b/queue-5.11/ice-continue-probe-on-link-phy-errors.patch @@ -0,0 +1,61 @@ +From 08771bce330036d473be6ce851cd00bcd351ebf6 Mon Sep 17 00:00:00 2001 +From: Anirudh Venkataramanan +Date: Fri, 26 Feb 2021 13:19:22 -0800 +Subject: ice: Continue probe on link/PHY errors + +From: Anirudh Venkataramanan + +commit 08771bce330036d473be6ce851cd00bcd351ebf6 upstream. + +An incorrect NVM update procedure can result in the driver failing probe. +In this case, the recommended resolution method is to update the NVM +using the right procedure. However, if the driver fails probe, the user +will not be able to update the NVM. So do not fail probe on link/PHY +errors. + +Fixes: 1a3571b5938c ("ice: restore PHY settings on media insertion") +Signed-off-by: Anirudh Venkataramanan +Tested-by: Tony Brelinski +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/ice/ice_main.c | 15 ++++++--------- + 1 file changed, 6 insertions(+), 9 deletions(-) + +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -4167,28 +4167,25 @@ ice_probe(struct pci_dev *pdev, const st + goto err_send_version_unroll; + } + ++ /* not a fatal error if this fails */ + err = ice_init_nvm_phy_type(pf->hw.port_info); +- if (err) { ++ if (err) + dev_err(dev, "ice_init_nvm_phy_type failed: %d\n", err); +- goto err_send_version_unroll; +- } + ++ /* not a fatal error if this fails */ + err = ice_update_link_info(pf->hw.port_info); +- if (err) { ++ if (err) + dev_err(dev, "ice_update_link_info failed: %d\n", err); +- goto err_send_version_unroll; +- } + + ice_init_link_dflt_override(pf->hw.port_info); + + /* if media available, initialize PHY settings */ + if (pf->hw.port_info->phy.link_info.link_info & + ICE_AQ_MEDIA_AVAILABLE) { ++ /* not a fatal error if this fails */ + err = ice_init_phy_user_cfg(pf->hw.port_info); +- if (err) { ++ if (err) + dev_err(dev, "ice_init_phy_user_cfg failed: %d\n", err); +- goto err_send_version_unroll; +- } + + if (!test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, pf->flags)) { + struct ice_vsi *vsi = ice_get_main_vsi(pf); diff --git a/queue-5.11/ice-fix-for-dereference-of-null-pointer.patch b/queue-5.11/ice-fix-for-dereference-of-null-pointer.patch new file mode 100644 index 00000000000..090a9880c91 --- /dev/null +++ b/queue-5.11/ice-fix-for-dereference-of-null-pointer.patch @@ -0,0 +1,67 @@ +From 7a91d3f02b04b2fb18c2dfa8b6c4e5a40a2753f5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jacek=20Bu=C5=82atek?= +Date: Fri, 26 Feb 2021 13:19:29 -0800 +Subject: ice: Fix for dereference of NULL pointer +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Jacek Bułatek + +commit 7a91d3f02b04b2fb18c2dfa8b6c4e5a40a2753f5 upstream. + +Add handling of allocation fault for ice_vsi_list_map_info. + +Also *fi should not be NULL pointer, it is a reference to raw +data field, so remove this variable and use the reference +directly. + +Fixes: 9daf8208dd4d ("ice: Add support for switch filter programming") +Signed-off-by: Jacek Bułatek +Co-developed-by: Haiyue Wang +Signed-off-by: Haiyue Wang +Tested-by: Tony Brelinski +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/ice/ice_switch.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +--- a/drivers/net/ethernet/intel/ice/ice_switch.c ++++ b/drivers/net/ethernet/intel/ice/ice_switch.c +@@ -1238,6 +1238,9 @@ ice_add_update_vsi_list(struct ice_hw *h + ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, + vsi_list_id); + ++ if (!m_entry->vsi_list_info) ++ return ICE_ERR_NO_MEMORY; ++ + /* If this entry was large action then the large action needs + * to be updated to point to FWD to VSI list + */ +@@ -2220,6 +2223,7 @@ ice_vsi_uses_fltr(struct ice_fltr_mgmt_l + return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI && + fm_entry->fltr_info.vsi_handle == vsi_handle) || + (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST && ++ fm_entry->vsi_list_info && + (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map)))); + } + +@@ -2292,14 +2296,12 @@ ice_add_to_vsi_fltr_list(struct ice_hw * + return ICE_ERR_PARAM; + + list_for_each_entry(fm_entry, lkup_list_head, list_entry) { +- struct ice_fltr_info *fi; +- +- fi = &fm_entry->fltr_info; +- if (!fi || !ice_vsi_uses_fltr(fm_entry, vsi_handle)) ++ if (!ice_vsi_uses_fltr(fm_entry, vsi_handle)) + continue; + + status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, +- vsi_list_head, fi); ++ vsi_list_head, ++ &fm_entry->fltr_info); + if (status) + return status; + } diff --git a/queue-5.11/ice-fix-memory-allocation-call.patch b/queue-5.11/ice-fix-memory-allocation-call.patch new file mode 100644 index 00000000000..dbde9d2a01a --- /dev/null +++ b/queue-5.11/ice-fix-memory-allocation-call.patch @@ -0,0 +1,33 @@ +From 59df14f9cc2326bd6432d60eca0df8201d9d3d4b Mon Sep 17 00:00:00 2001 +From: Bruce Allan +Date: Fri, 26 Feb 2021 13:19:27 -0800 +Subject: ice: fix memory allocation call + +From: Bruce Allan + +commit 59df14f9cc2326bd6432d60eca0df8201d9d3d4b upstream. + +Fix the order of number of array members and member size parameters in a +*calloc() call. + +Fixes: b3c3890489f6 ("ice: avoid unnecessary single-member variable-length structs") +Signed-off-by: Bruce Allan +Tested-by: Tony Brelinski +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/ice/ice_common.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/ethernet/intel/ice/ice_common.c ++++ b/drivers/net/ethernet/intel/ice/ice_common.c +@@ -717,8 +717,8 @@ static enum ice_status ice_cfg_fw_log(st + + if (!data) { + data = devm_kcalloc(ice_hw_to_dev(hw), +- sizeof(*data), + ICE_AQC_FW_LOG_ID_MAX, ++ sizeof(*data), + GFP_KERNEL); + if (!data) + return ICE_ERR_NO_MEMORY; diff --git a/queue-5.11/ice-fix-memory-leak-of-arfs-after-resuming-from-suspend.patch b/queue-5.11/ice-fix-memory-leak-of-arfs-after-resuming-from-suspend.patch new file mode 100644 index 00000000000..8d1d19db590 --- /dev/null +++ b/queue-5.11/ice-fix-memory-leak-of-arfs-after-resuming-from-suspend.patch @@ -0,0 +1,76 @@ +From 1831da7ea5bdf5531d78bcf81f526faa4c4375fa Mon Sep 17 00:00:00 2001 +From: Yongxin Liu +Date: Thu, 1 Apr 2021 11:59:15 -0700 +Subject: ice: fix memory leak of aRFS after resuming from suspend + +From: Yongxin Liu + +commit 1831da7ea5bdf5531d78bcf81f526faa4c4375fa upstream. + +In ice_suspend(), ice_clear_interrupt_scheme() is called, and then +irq_free_descs() will be eventually called to free irq and its descriptor. + +In ice_resume(), ice_init_interrupt_scheme() is called to allocate new +irqs. However, in ice_rebuild_arfs(), struct irq_glue and struct cpu_rmap +maybe cannot be freed, if the irqs that released in ice_suspend() were +reassigned to other devices, which makes irq descriptor's affinity_notify +lost. + +So call ice_free_cpu_rx_rmap() before ice_clear_interrupt_scheme(), which +can make sure all irq_glue and cpu_rmap can be correctly released before +corresponding irq and descriptor are released. + +Fix the following memory leak. + +unreferenced object 0xffff95bd951afc00 (size 512): + comm "kworker/0:1", pid 134, jiffies 4294684283 (age 13051.958s) + hex dump (first 32 bytes): + 18 00 00 00 18 00 18 00 70 fc 1a 95 bd 95 ff ff ........p....... + 00 00 ff ff 01 00 ff ff 02 00 ff ff 03 00 ff ff ................ + backtrace: + [<0000000072e4b914>] __kmalloc+0x336/0x540 + [<0000000054642a87>] alloc_cpu_rmap+0x3b/0xb0 + [<00000000f220deec>] ice_set_cpu_rx_rmap+0x6a/0x110 [ice] + [<000000002370a632>] ice_probe+0x941/0x1180 [ice] + [<00000000d692edba>] local_pci_probe+0x47/0xa0 + [<00000000503934f0>] work_for_cpu_fn+0x1a/0x30 + [<00000000555a9e4a>] process_one_work+0x1dd/0x410 + [<000000002c4b414a>] worker_thread+0x221/0x3f0 + [<00000000bb2b556b>] kthread+0x14c/0x170 + [<00000000ad2cf1cd>] ret_from_fork+0x1f/0x30 +unreferenced object 0xffff95bd81b0a2a0 (size 96): + comm "kworker/0:1", pid 134, jiffies 4294684283 (age 13051.958s) + hex dump (first 32 bytes): + 38 00 00 00 01 00 00 00 e0 ff ff ff 0f 00 00 00 8............... + b0 a2 b0 81 bd 95 ff ff b0 a2 b0 81 bd 95 ff ff ................ + backtrace: + [<00000000582dd5c5>] kmem_cache_alloc_trace+0x31f/0x4c0 + [<000000002659850d>] irq_cpu_rmap_add+0x25/0xe0 + [<00000000495a3055>] ice_set_cpu_rx_rmap+0xb4/0x110 [ice] + [<000000002370a632>] ice_probe+0x941/0x1180 [ice] + [<00000000d692edba>] local_pci_probe+0x47/0xa0 + [<00000000503934f0>] work_for_cpu_fn+0x1a/0x30 + [<00000000555a9e4a>] process_one_work+0x1dd/0x410 + [<000000002c4b414a>] worker_thread+0x221/0x3f0 + [<00000000bb2b556b>] kthread+0x14c/0x170 + [<00000000ad2cf1cd>] ret_from_fork+0x1f/0x30 + +Fixes: 769c500dcc1e ("ice: Add advanced power mgmt for WoL") +Signed-off-by: Yongxin Liu +Tested-by: Tony Brelinski +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/ice/ice_main.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -4535,6 +4535,7 @@ static int __maybe_unused ice_suspend(st + continue; + ice_vsi_free_q_vectors(pf->vsi[v]); + } ++ ice_free_cpu_rx_rmap(ice_get_main_vsi(pf)); + ice_clear_interrupt_scheme(pf); + + pci_save_state(pdev); diff --git a/queue-5.11/ice-increase-control-queue-timeout.patch b/queue-5.11/ice-increase-control-queue-timeout.patch new file mode 100644 index 00000000000..427ab017306 --- /dev/null +++ b/queue-5.11/ice-increase-control-queue-timeout.patch @@ -0,0 +1,34 @@ +From f88c529ac77b3c21819d2cf1dfcfae1937849743 Mon Sep 17 00:00:00 2001 +From: Fabio Pricoco +Date: Fri, 26 Feb 2021 13:19:24 -0800 +Subject: ice: Increase control queue timeout + +From: Fabio Pricoco + +commit f88c529ac77b3c21819d2cf1dfcfae1937849743 upstream. + +250 msec timeout is insufficient for some AQ commands. Advice from FW +team was to increase the timeout. Increase to 1 second. + +Fixes: 7ec59eeac804 ("ice: Add support for control queues") +Signed-off-by: Fabio Pricoco +Tested-by: Tony Brelinski +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/ice/ice_controlq.h | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/intel/ice/ice_controlq.h ++++ b/drivers/net/ethernet/intel/ice/ice_controlq.h +@@ -31,8 +31,8 @@ enum ice_ctl_q { + ICE_CTL_Q_MAILBOX, + }; + +-/* Control Queue timeout settings - max delay 250ms */ +-#define ICE_CTL_Q_SQ_CMD_TIMEOUT 2500 /* Count 2500 times */ ++/* Control Queue timeout settings - max delay 1s */ ++#define ICE_CTL_Q_SQ_CMD_TIMEOUT 10000 /* Count 10000 times */ + #define ICE_CTL_Q_SQ_CMD_USEC 100 /* Check every 100usec */ + #define ICE_CTL_Q_ADMIN_INIT_TIMEOUT 10 /* Count 10 times */ + #define ICE_CTL_Q_ADMIN_INIT_MSEC 100 /* Check every 100msec */ diff --git a/queue-5.11/ice-prevent-ice_open-and-ice_stop-during-reset.patch b/queue-5.11/ice-prevent-ice_open-and-ice_stop-during-reset.patch new file mode 100644 index 00000000000..284f25422fa --- /dev/null +++ b/queue-5.11/ice-prevent-ice_open-and-ice_stop-during-reset.patch @@ -0,0 +1,108 @@ +From e95fc8573e07c5e4825df4650fd8b8c93fad27a7 Mon Sep 17 00:00:00 2001 +From: Krzysztof Goreczny +Date: Fri, 26 Feb 2021 13:19:26 -0800 +Subject: ice: prevent ice_open and ice_stop during reset + +From: Krzysztof Goreczny + +commit e95fc8573e07c5e4825df4650fd8b8c93fad27a7 upstream. + +There is a possibility of race between ice_open or ice_stop calls +performed by OS and reset handling routine both trying to modify VSI +resources. Observed scenarios: +- reset handler deallocates memory in ice_vsi_free_arrays and ice_open + tries to access it in ice_vsi_cfg_txq leading to driver crash +- reset handler deallocates memory in ice_vsi_free_arrays and ice_close + tries to access it in ice_down leading to driver crash +- reset handler clears port scheduler topology and sets port state to + ICE_SCHED_PORT_STATE_INIT leading to ice_ena_vsi_txq fail in ice_open + +To prevent this additional checks in ice_open and ice_stop are +introduced to make sure that OS is not allowed to alter VSI config while +reset is in progress. + +Fixes: cdedef59deb0 ("ice: Configure VSIs for Tx/Rx") +Signed-off-by: Krzysztof Goreczny +Tested-by: Tony Brelinski +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/ice/ice.h | 1 + + drivers/net/ethernet/intel/ice/ice_lib.c | 4 ++-- + drivers/net/ethernet/intel/ice/ice_main.c | 28 ++++++++++++++++++++++++++++ + 3 files changed, 31 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -604,6 +604,7 @@ int ice_fdir_create_dflt_rules(struct ic + int ice_aq_wait_for_event(struct ice_pf *pf, u16 opcode, unsigned long timeout, + struct ice_rq_event_info *event); + int ice_open(struct net_device *netdev); ++int ice_open_internal(struct net_device *netdev); + int ice_stop(struct net_device *netdev); + void ice_service_task_schedule(struct ice_pf *pf); + +--- a/drivers/net/ethernet/intel/ice/ice_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_lib.c +@@ -2489,7 +2489,7 @@ int ice_ena_vsi(struct ice_vsi *vsi, boo + if (!locked) + rtnl_lock(); + +- err = ice_open(vsi->netdev); ++ err = ice_open_internal(vsi->netdev); + + if (!locked) + rtnl_unlock(); +@@ -2518,7 +2518,7 @@ void ice_dis_vsi(struct ice_vsi *vsi, bo + if (!locked) + rtnl_lock(); + +- ice_stop(vsi->netdev); ++ ice_vsi_close(vsi); + + if (!locked) + rtnl_unlock(); +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -6612,6 +6612,28 @@ static void ice_tx_timeout(struct net_de + int ice_open(struct net_device *netdev) + { + struct ice_netdev_priv *np = netdev_priv(netdev); ++ struct ice_pf *pf = np->vsi->back; ++ ++ if (ice_is_reset_in_progress(pf->state)) { ++ netdev_err(netdev, "can't open net device while reset is in progress"); ++ return -EBUSY; ++ } ++ ++ return ice_open_internal(netdev); ++} ++ ++/** ++ * ice_open_internal - Called when a network interface becomes active ++ * @netdev: network interface device structure ++ * ++ * Internal ice_open implementation. Should not be used directly except for ice_open and reset ++ * handling routine ++ * ++ * Returns 0 on success, negative value on failure ++ */ ++int ice_open_internal(struct net_device *netdev) ++{ ++ struct ice_netdev_priv *np = netdev_priv(netdev); + struct ice_vsi *vsi = np->vsi; + struct ice_pf *pf = vsi->back; + struct ice_port_info *pi; +@@ -6690,6 +6712,12 @@ int ice_stop(struct net_device *netdev) + { + struct ice_netdev_priv *np = netdev_priv(netdev); + struct ice_vsi *vsi = np->vsi; ++ struct ice_pf *pf = vsi->back; ++ ++ if (ice_is_reset_in_progress(pf->state)) { ++ netdev_err(netdev, "can't stop net device while reset is in progress"); ++ return -EBUSY; ++ } + + ice_vsi_close(vsi); + diff --git a/queue-5.11/ice-remove-dcbnl_devreset-bit-from-pf-state.patch b/queue-5.11/ice-remove-dcbnl_devreset-bit-from-pf-state.patch new file mode 100644 index 00000000000..72ca3c4f71d --- /dev/null +++ b/queue-5.11/ice-remove-dcbnl_devreset-bit-from-pf-state.patch @@ -0,0 +1,70 @@ +From 741b7b743bbcb5a3848e4e55982064214f900d2f Mon Sep 17 00:00:00 2001 +From: Dave Ertman +Date: Fri, 26 Feb 2021 13:19:28 -0800 +Subject: ice: remove DCBNL_DEVRESET bit from PF state + +From: Dave Ertman + +commit 741b7b743bbcb5a3848e4e55982064214f900d2f upstream. + +The original purpose of the ICE_DCBNL_DEVRESET was to protect +the driver during DCBNL device resets. But, the flow for +DCBNL device resets now consists of only calls up the stack +such as dev_close() and dev_open() that will result in NDO calls +to the driver. These will be handled with state changes from the +stack. Also, there is a problem of the dev_close and dev_open +being blocked by checks for reset in progress also using the +ICE_DCBNL_DEVRESET bit. + +Since the ICE_DCBNL_DEVRESET bit is not necessary for protecting +the driver from DCBNL device resets and it is actually blocking +changes coming from the DCBNL interface, remove the bit from the +PF state and don't block driver function based on DCBNL reset in +progress. + +Fixes: b94b013eb626 ("ice: Implement DCBNL support") +Signed-off-by: Dave Ertman +Tested-by: Tony Brelinski +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/ice/ice.h | 1 - + drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 2 -- + drivers/net/ethernet/intel/ice/ice_lib.c | 1 - + 3 files changed, 4 deletions(-) + +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -194,7 +194,6 @@ enum ice_state { + __ICE_NEEDS_RESTART, + __ICE_PREPARED_FOR_RESET, /* set by driver when prepared */ + __ICE_RESET_OICR_RECV, /* set by driver after rcv reset OICR */ +- __ICE_DCBNL_DEVRESET, /* set by dcbnl devreset */ + __ICE_PFR_REQ, /* set by driver and peers */ + __ICE_CORER_REQ, /* set by driver and peers */ + __ICE_GLOBR_REQ, /* set by driver and peers */ +--- a/drivers/net/ethernet/intel/ice/ice_dcb_nl.c ++++ b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c +@@ -18,12 +18,10 @@ static void ice_dcbnl_devreset(struct ne + while (ice_is_reset_in_progress(pf->state)) + usleep_range(1000, 2000); + +- set_bit(__ICE_DCBNL_DEVRESET, pf->state); + dev_close(netdev); + netdev_state_change(netdev); + dev_open(netdev, NULL); + netdev_state_change(netdev); +- clear_bit(__ICE_DCBNL_DEVRESET, pf->state); + } + + /** +--- a/drivers/net/ethernet/intel/ice/ice_lib.c ++++ b/drivers/net/ethernet/intel/ice/ice_lib.c +@@ -2944,7 +2944,6 @@ err_vsi: + bool ice_is_reset_in_progress(unsigned long *state) + { + return test_bit(__ICE_RESET_OICR_RECV, state) || +- test_bit(__ICE_DCBNL_DEVRESET, state) || + test_bit(__ICE_PFR_REQ, state) || + test_bit(__ICE_CORER_REQ, state) || + test_bit(__ICE_GLOBR_REQ, state); diff --git a/queue-5.11/ice-use-port-number-instead-of-pf-id-for-wol.patch b/queue-5.11/ice-use-port-number-instead-of-pf-id-for-wol.patch new file mode 100644 index 00000000000..2d06cfa0664 --- /dev/null +++ b/queue-5.11/ice-use-port-number-instead-of-pf-id-for-wol.patch @@ -0,0 +1,88 @@ +From 3176551979b92b02756979c0f1e2d03d1fc82b1e Mon Sep 17 00:00:00 2001 +From: Anirudh Venkataramanan +Date: Fri, 26 Feb 2021 13:19:30 -0800 +Subject: ice: Use port number instead of PF ID for WoL + +From: Anirudh Venkataramanan + +commit 3176551979b92b02756979c0f1e2d03d1fc82b1e upstream. + +As per the spec, the WoL control word read from the NVM should be +interpreted as port numbers, and not PF numbers. So when checking +if WoL supported, use the port number instead of the PF ID. + +Also, ice_is_wol_supported doesn't really need a pointer to the pf +struct, but just needs a pointer to the hw instance. + +Fixes: 769c500dcc1e ("ice: Add advanced power mgmt for WoL") +Signed-off-by: Anirudh Venkataramanan +Tested-by: Tony Brelinski +Signed-off-by: Tony Nguyen +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/ethernet/intel/ice/ice.h | 2 +- + drivers/net/ethernet/intel/ice/ice_ethtool.c | 4 ++-- + drivers/net/ethernet/intel/ice/ice_main.c | 9 ++++----- + 3 files changed, 7 insertions(+), 8 deletions(-) + +--- a/drivers/net/ethernet/intel/ice/ice.h ++++ b/drivers/net/ethernet/intel/ice/ice.h +@@ -585,7 +585,7 @@ int ice_schedule_reset(struct ice_pf *pf + void ice_print_link_msg(struct ice_vsi *vsi, bool isup); + const char *ice_stat_str(enum ice_status stat_err); + const char *ice_aq_str(enum ice_aq_err aq_err); +-bool ice_is_wol_supported(struct ice_pf *pf); ++bool ice_is_wol_supported(struct ice_hw *hw); + int + ice_fdir_write_fltr(struct ice_pf *pf, struct ice_fdir_fltr *input, bool add, + bool is_tun); +--- a/drivers/net/ethernet/intel/ice/ice_ethtool.c ++++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c +@@ -3472,7 +3472,7 @@ static void ice_get_wol(struct net_devic + netdev_warn(netdev, "Wake on LAN is not supported on this interface!\n"); + + /* Get WoL settings based on the HW capability */ +- if (ice_is_wol_supported(pf)) { ++ if (ice_is_wol_supported(&pf->hw)) { + wol->supported = WAKE_MAGIC; + wol->wolopts = pf->wol_ena ? WAKE_MAGIC : 0; + } else { +@@ -3492,7 +3492,7 @@ static int ice_set_wol(struct net_device + struct ice_vsi *vsi = np->vsi; + struct ice_pf *pf = vsi->back; + +- if (vsi->type != ICE_VSI_PF || !ice_is_wol_supported(pf)) ++ if (vsi->type != ICE_VSI_PF || !ice_is_wol_supported(&pf->hw)) + return -EOPNOTSUPP; + + /* only magic packet is supported */ +--- a/drivers/net/ethernet/intel/ice/ice_main.c ++++ b/drivers/net/ethernet/intel/ice/ice_main.c +@@ -3512,15 +3512,14 @@ static int ice_init_interrupt_scheme(str + } + + /** +- * ice_is_wol_supported - get NVM state of WoL +- * @pf: board private structure ++ * ice_is_wol_supported - check if WoL is supported ++ * @hw: pointer to hardware info + * + * Check if WoL is supported based on the HW configuration. + * Returns true if NVM supports and enables WoL for this port, false otherwise + */ +-bool ice_is_wol_supported(struct ice_pf *pf) ++bool ice_is_wol_supported(struct ice_hw *hw) + { +- struct ice_hw *hw = &pf->hw; + u16 wol_ctrl; + + /* A bit set to 1 in the NVM Software Reserved Word 2 (WoL control +@@ -3529,7 +3528,7 @@ bool ice_is_wol_supported(struct ice_pf + if (ice_read_sr_word(hw, ICE_SR_NVM_WOL_CFG, &wol_ctrl)) + return false; + +- return !(BIT(hw->pf_id) & wol_ctrl); ++ return !(BIT(hw->port_info->lport) & wol_ctrl); + } + + /** diff --git a/queue-5.11/iwlwifi-pcie-properly-set-ltr-workarounds-on-22000-devices.patch b/queue-5.11/iwlwifi-pcie-properly-set-ltr-workarounds-on-22000-devices.patch new file mode 100644 index 00000000000..b0474c6c339 --- /dev/null +++ b/queue-5.11/iwlwifi-pcie-properly-set-ltr-workarounds-on-22000-devices.patch @@ -0,0 +1,156 @@ +From 25628bc08d4526d3673ca7d039eb636aa9006076 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 26 Mar 2021 12:57:18 +0200 +Subject: iwlwifi: pcie: properly set LTR workarounds on 22000 devices + +From: Johannes Berg + +commit 25628bc08d4526d3673ca7d039eb636aa9006076 upstream. + +As the context info gen3 code is only called for >=AX210 devices +(from iwl_trans_pcie_gen2_start_fw()) the code there to set LTR +on 22000 devices cannot actually do anything (22000 < AX210). + +Fix this by moving the LTR code to iwl_trans_pcie_gen2_start_fw() +where it can handle both devices. This then requires that we kick +the firmware only after that rather than doing it from the context +info code. + +Note that this again had a dead branch in gen3 code, which I've +removed here. + +Signed-off-by: Johannes Berg +Fixes: ed0022da8bd9 ("iwlwifi: pcie: set LTR on more devices") +Signed-off-by: Luca Coelho +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/iwlwifi.20210326125611.675486178ed1.Ib61463aba6920645059e366dcdca4c4c77f0ff58@changeid +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c | 31 ------------- + drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c | 3 - + drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c | 35 +++++++++++++++ + 3 files changed, 37 insertions(+), 32 deletions(-) + +--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c ++++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +@@ -1,6 +1,6 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* +- * Copyright (C) 2018-2020 Intel Corporation ++ * Copyright (C) 2018-2021 Intel Corporation + */ + #include "iwl-trans.h" + #include "iwl-fh.h" +@@ -75,15 +75,6 @@ int iwl_pcie_ctxt_info_gen3_init(struct + const struct fw_img *fw) + { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); +- u32 ltr_val = CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ | +- u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC, +- CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE) | +- u32_encode_bits(250, +- CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL) | +- CSR_LTR_LONG_VAL_AD_SNOOP_REQ | +- u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC, +- CSR_LTR_LONG_VAL_AD_SNOOP_SCALE) | +- u32_encode_bits(250, CSR_LTR_LONG_VAL_AD_SNOOP_VAL); + struct iwl_context_info_gen3 *ctxt_info_gen3; + struct iwl_prph_scratch *prph_scratch; + struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl; +@@ -217,26 +208,6 @@ int iwl_pcie_ctxt_info_gen3_init(struct + iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, + CSR_AUTO_FUNC_BOOT_ENA); + +- /* +- * To workaround hardware latency issues during the boot process, +- * initialize the LTR to ~250 usec (see ltr_val above). +- * The firmware initializes this again later (to a smaller value). +- */ +- if ((trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210 || +- trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) && +- !trans->trans_cfg->integrated) { +- iwl_write32(trans, CSR_LTR_LONG_VAL_AD, ltr_val); +- } else if (trans->trans_cfg->integrated && +- trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) { +- iwl_write_prph(trans, HPM_MAC_LTR_CSR, HPM_MAC_LRT_ENABLE_ALL); +- iwl_write_prph(trans, HPM_UMAC_LTR, ltr_val); +- } +- +- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) +- iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1); +- else +- iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT); +- + return 0; + + err_free_ctxt_info: +--- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c ++++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + /* + * Copyright (C) 2017 Intel Deutschland GmbH +- * Copyright (C) 2018-2020 Intel Corporation ++ * Copyright (C) 2018-2021 Intel Corporation + */ + #include "iwl-trans.h" + #include "iwl-fh.h" +@@ -240,7 +240,6 @@ int iwl_pcie_ctxt_info_init(struct iwl_t + + /* kick FW self load */ + iwl_write64(trans, CSR_CTXT_INFO_BA, trans_pcie->ctxt_info_dma_addr); +- iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1); + + /* Context info will be released upon alive or failure to get one */ + +--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c ++++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +@@ -260,6 +260,34 @@ void iwl_trans_pcie_gen2_fw_alive(struct + mutex_unlock(&trans_pcie->mutex); + } + ++static void iwl_pcie_set_ltr(struct iwl_trans *trans) ++{ ++ u32 ltr_val = CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ | ++ u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC, ++ CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE) | ++ u32_encode_bits(250, ++ CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL) | ++ CSR_LTR_LONG_VAL_AD_SNOOP_REQ | ++ u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC, ++ CSR_LTR_LONG_VAL_AD_SNOOP_SCALE) | ++ u32_encode_bits(250, CSR_LTR_LONG_VAL_AD_SNOOP_VAL); ++ ++ /* ++ * To workaround hardware latency issues during the boot process, ++ * initialize the LTR to ~250 usec (see ltr_val above). ++ * The firmware initializes this again later (to a smaller value). ++ */ ++ if ((trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210 || ++ trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) && ++ !trans->trans_cfg->integrated) { ++ iwl_write32(trans, CSR_LTR_LONG_VAL_AD, ltr_val); ++ } else if (trans->trans_cfg->integrated && ++ trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) { ++ iwl_write_prph(trans, HPM_MAC_LTR_CSR, HPM_MAC_LRT_ENABLE_ALL); ++ iwl_write_prph(trans, HPM_UMAC_LTR, ltr_val); ++ } ++} ++ + int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, + const struct fw_img *fw, bool run_in_rfkill) + { +@@ -326,6 +354,13 @@ int iwl_trans_pcie_gen2_start_fw(struct + if (ret) + goto out; + ++ iwl_pcie_set_ltr(trans); ++ ++ if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) ++ iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1); ++ else ++ iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1); ++ + /* re-check RF-Kill state since we may have missed the interrupt */ + hw_rfkill = iwl_pcie_check_hw_rf_kill(trans); + if (hw_rfkill && !run_in_rfkill) diff --git a/queue-5.11/libbpf-ensure-umem-pointer-is-non-null-before-dereferencing.patch b/queue-5.11/libbpf-ensure-umem-pointer-is-non-null-before-dereferencing.patch new file mode 100644 index 00000000000..1a93426cd1a --- /dev/null +++ b/queue-5.11/libbpf-ensure-umem-pointer-is-non-null-before-dereferencing.patch @@ -0,0 +1,35 @@ +From df662016310aa4475d7986fd726af45c8fe4f362 Mon Sep 17 00:00:00 2001 +From: Ciara Loftus +Date: Wed, 31 Mar 2021 06:12:16 +0000 +Subject: libbpf: Ensure umem pointer is non-NULL before dereferencing + +From: Ciara Loftus + +commit df662016310aa4475d7986fd726af45c8fe4f362 upstream. + +Calls to xsk_socket__create dereference the umem to access the +fill_save and comp_save pointers. Make sure the umem is non-NULL +before doing this. + +Fixes: 2f6324a3937f ("libbpf: Support shared umems between queues and devices") +Signed-off-by: Ciara Loftus +Signed-off-by: Alexei Starovoitov +Acked-by: Magnus Karlsson +Link: https://lore.kernel.org/bpf/20210331061218.1647-2-ciara.loftus@intel.com +Signed-off-by: Greg Kroah-Hartman +--- + tools/lib/bpf/xsk.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/tools/lib/bpf/xsk.c ++++ b/tools/lib/bpf/xsk.c +@@ -944,6 +944,9 @@ int xsk_socket__create(struct xsk_socket + struct xsk_ring_cons *rx, struct xsk_ring_prod *tx, + const struct xsk_socket_config *usr_config) + { ++ if (!umem) ++ return -EFAULT; ++ + return xsk_socket__create_shared(xsk_ptr, ifname, queue_id, umem, + rx, tx, umem->fill_save, + umem->comp_save, usr_config); diff --git a/queue-5.11/libbpf-fix-bail-out-from-ringbuf_process_ring-on-error.patch b/queue-5.11/libbpf-fix-bail-out-from-ringbuf_process_ring-on-error.patch new file mode 100644 index 00000000000..bae7ffb258d --- /dev/null +++ b/queue-5.11/libbpf-fix-bail-out-from-ringbuf_process_ring-on-error.patch @@ -0,0 +1,36 @@ +From 6032ebb54c60cae24329f6aba3ce0c1ca8ad6abe Mon Sep 17 00:00:00 2001 +From: Pedro Tammela +Date: Thu, 25 Mar 2021 12:01:15 -0300 +Subject: libbpf: Fix bail out from 'ringbuf_process_ring()' on error + +From: Pedro Tammela + +commit 6032ebb54c60cae24329f6aba3ce0c1ca8ad6abe upstream. + +The current code bails out with negative and positive returns. +If the callback returns a positive return code, 'ring_buffer__consume()' +and 'ring_buffer__poll()' will return a spurious number of records +consumed, but mostly important will continue the processing loop. + +This patch makes positive returns from the callback a no-op. + +Fixes: bf99c936f947 ("libbpf: Add BPF ring buffer support") +Signed-off-by: Pedro Tammela +Signed-off-by: Andrii Nakryiko +Link: https://lore.kernel.org/bpf/20210325150115.138750-1-pctammela@mojatatu.com +Signed-off-by: Greg Kroah-Hartman +--- + tools/lib/bpf/ringbuf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/tools/lib/bpf/ringbuf.c ++++ b/tools/lib/bpf/ringbuf.c +@@ -227,7 +227,7 @@ static int ringbuf_process_ring(struct r + if ((len & BPF_RINGBUF_DISCARD_BIT) == 0) { + sample = (void *)len_ptr + BPF_RINGBUF_HDR_SZ; + err = r->sample_cb(r->ctx, sample, len); +- if (err) { ++ if (err < 0) { + /* update consumer pos and bail out */ + smp_store_release(r->consumer_pos, + cons_pos); diff --git a/queue-5.11/libbpf-only-create-rx-and-tx-xdp-rings-when-necessary.patch b/queue-5.11/libbpf-only-create-rx-and-tx-xdp-rings-when-necessary.patch new file mode 100644 index 00000000000..c16182c5147 --- /dev/null +++ b/queue-5.11/libbpf-only-create-rx-and-tx-xdp-rings-when-necessary.patch @@ -0,0 +1,87 @@ +From ca7a83e2487ad0bc9a3e0e7a8645354aa1782f13 Mon Sep 17 00:00:00 2001 +From: Ciara Loftus +Date: Wed, 31 Mar 2021 06:12:18 +0000 +Subject: libbpf: Only create rx and tx XDP rings when necessary + +From: Ciara Loftus + +commit ca7a83e2487ad0bc9a3e0e7a8645354aa1782f13 upstream. + +Prior to this commit xsk_socket__create(_shared) always attempted to create +the rx and tx rings for the socket. However this causes an issue when the +socket being setup is that which shares the fd with the UMEM. If a +previous call to this function failed with this socket after the rings were +set up, a subsequent call would always fail because the rings are not torn +down after the first call and when we try to set them up again we encounter +an error because they already exist. Solve this by remembering whether the +rings were set up by introducing new bools to struct xsk_umem which +represent the ring setup status and using them to determine whether or +not to set up the rings. + +Fixes: 1cad07884239 ("libbpf: add support for using AF_XDP sockets") +Signed-off-by: Ciara Loftus +Signed-off-by: Alexei Starovoitov +Link: https://lore.kernel.org/bpf/20210331061218.1647-4-ciara.loftus@intel.com +Signed-off-by: Greg Kroah-Hartman +--- + tools/lib/bpf/xsk.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/tools/lib/bpf/xsk.c ++++ b/tools/lib/bpf/xsk.c +@@ -54,6 +54,8 @@ struct xsk_umem { + int fd; + int refcount; + struct list_head ctx_list; ++ bool rx_ring_setup_done; ++ bool tx_ring_setup_done; + }; + + struct xsk_ctx { +@@ -782,6 +784,7 @@ int xsk_socket__create_shared(struct xsk + struct xsk_ctx *ctx; + int err, ifindex; + bool unmap = umem->fill_save != fill; ++ bool rx_setup_done = false, tx_setup_done = false; + + if (!umem || !xsk_ptr || !(rx || tx)) + return -EFAULT; +@@ -809,6 +812,8 @@ int xsk_socket__create_shared(struct xsk + } + } else { + xsk->fd = umem->fd; ++ rx_setup_done = umem->rx_ring_setup_done; ++ tx_setup_done = umem->tx_ring_setup_done; + } + + ctx = xsk_get_ctx(umem, ifindex, queue_id); +@@ -827,7 +832,7 @@ int xsk_socket__create_shared(struct xsk + } + xsk->ctx = ctx; + +- if (rx) { ++ if (rx && !rx_setup_done) { + err = setsockopt(xsk->fd, SOL_XDP, XDP_RX_RING, + &xsk->config.rx_size, + sizeof(xsk->config.rx_size)); +@@ -835,8 +840,10 @@ int xsk_socket__create_shared(struct xsk + err = -errno; + goto out_put_ctx; + } ++ if (xsk->fd == umem->fd) ++ umem->rx_ring_setup_done = true; + } +- if (tx) { ++ if (tx && !tx_setup_done) { + err = setsockopt(xsk->fd, SOL_XDP, XDP_TX_RING, + &xsk->config.tx_size, + sizeof(xsk->config.tx_size)); +@@ -844,6 +851,8 @@ int xsk_socket__create_shared(struct xsk + err = -errno; + goto out_put_ctx; + } ++ if (xsk->fd == umem->fd) ++ umem->rx_ring_setup_done = true; + } + + err = xsk_get_mmap_offsets(xsk->fd, &off); diff --git a/queue-5.11/libbpf-restore-umem-state-after-socket-create-failure.patch b/queue-5.11/libbpf-restore-umem-state-after-socket-create-failure.patch new file mode 100644 index 00000000000..8c83892d3e9 --- /dev/null +++ b/queue-5.11/libbpf-restore-umem-state-after-socket-create-failure.patch @@ -0,0 +1,118 @@ +From 43f1bc1efff16f553dd573d02eb7a15750925568 Mon Sep 17 00:00:00 2001 +From: Ciara Loftus +Date: Wed, 31 Mar 2021 06:12:17 +0000 +Subject: libbpf: Restore umem state after socket create failure + +From: Ciara Loftus + +commit 43f1bc1efff16f553dd573d02eb7a15750925568 upstream. + +If the call to xsk_socket__create fails, the user may want to retry the +socket creation using the same umem. Ensure that the umem is in the +same state on exit if the call fails by: +1. ensuring the umem _save pointers are unmodified. +2. not unmapping the set of umem rings that were set up with the umem +during xsk_umem__create, since those maps existed before the call to +xsk_socket__create and should remain in tact even in the event of +failure. + +Fixes: 2f6324a3937f ("libbpf: Support shared umems between queues and devices") +Signed-off-by: Ciara Loftus +Signed-off-by: Alexei Starovoitov +Link: https://lore.kernel.org/bpf/20210331061218.1647-3-ciara.loftus@intel.com +Signed-off-by: Greg Kroah-Hartman +--- + tools/lib/bpf/xsk.c | 41 +++++++++++++++++++++++------------------ + 1 file changed, 23 insertions(+), 18 deletions(-) + +--- a/tools/lib/bpf/xsk.c ++++ b/tools/lib/bpf/xsk.c +@@ -668,26 +668,30 @@ static struct xsk_ctx *xsk_get_ctx(struc + return NULL; + } + +-static void xsk_put_ctx(struct xsk_ctx *ctx) ++static void xsk_put_ctx(struct xsk_ctx *ctx, bool unmap) + { + struct xsk_umem *umem = ctx->umem; + struct xdp_mmap_offsets off; + int err; + +- if (--ctx->refcount == 0) { +- err = xsk_get_mmap_offsets(umem->fd, &off); +- if (!err) { +- munmap(ctx->fill->ring - off.fr.desc, +- off.fr.desc + umem->config.fill_size * +- sizeof(__u64)); +- munmap(ctx->comp->ring - off.cr.desc, +- off.cr.desc + umem->config.comp_size * +- sizeof(__u64)); +- } ++ if (--ctx->refcount) ++ return; + +- list_del(&ctx->list); +- free(ctx); +- } ++ if (!unmap) ++ goto out_free; ++ ++ err = xsk_get_mmap_offsets(umem->fd, &off); ++ if (err) ++ goto out_free; ++ ++ munmap(ctx->fill->ring - off.fr.desc, off.fr.desc + umem->config.fill_size * ++ sizeof(__u64)); ++ munmap(ctx->comp->ring - off.cr.desc, off.cr.desc + umem->config.comp_size * ++ sizeof(__u64)); ++ ++out_free: ++ list_del(&ctx->list); ++ free(ctx); + } + + static struct xsk_ctx *xsk_create_ctx(struct xsk_socket *xsk, +@@ -722,8 +726,6 @@ static struct xsk_ctx *xsk_create_ctx(st + memcpy(ctx->ifname, ifname, IFNAMSIZ - 1); + ctx->ifname[IFNAMSIZ - 1] = '\0'; + +- umem->fill_save = NULL; +- umem->comp_save = NULL; + ctx->fill = fill; + ctx->comp = comp; + list_add(&ctx->list, &umem->ctx_list); +@@ -779,6 +781,7 @@ int xsk_socket__create_shared(struct xsk + struct xsk_socket *xsk; + struct xsk_ctx *ctx; + int err, ifindex; ++ bool unmap = umem->fill_save != fill; + + if (!umem || !xsk_ptr || !(rx || tx)) + return -EFAULT; +@@ -919,6 +922,8 @@ int xsk_socket__create_shared(struct xsk + } + + *xsk_ptr = xsk; ++ umem->fill_save = NULL; ++ umem->comp_save = NULL; + return 0; + + out_mmap_tx: +@@ -930,7 +935,7 @@ out_mmap_rx: + munmap(rx_map, off.rx.desc + + xsk->config.rx_size * sizeof(struct xdp_desc)); + out_put_ctx: +- xsk_put_ctx(ctx); ++ xsk_put_ctx(ctx, unmap); + out_socket: + if (--umem->refcount) + close(xsk->fd); +@@ -996,7 +1001,7 @@ void xsk_socket__delete(struct xsk_socke + } + } + +- xsk_put_ctx(ctx); ++ xsk_put_ctx(ctx, true); + + umem->refcount--; + /* Do not close an fd that also has an associated umem connected diff --git a/queue-5.11/mac80211-fix-time-is-after-bug-in-mlme.patch b/queue-5.11/mac80211-fix-time-is-after-bug-in-mlme.patch new file mode 100644 index 00000000000..54ac3a3fc58 --- /dev/null +++ b/queue-5.11/mac80211-fix-time-is-after-bug-in-mlme.patch @@ -0,0 +1,39 @@ +From 7d73cd946d4bc7d44cdc5121b1c61d5d71425dea Mon Sep 17 00:00:00 2001 +From: Ben Greear +Date: Tue, 30 Mar 2021 16:07:49 -0700 +Subject: mac80211: fix time-is-after bug in mlme + +From: Ben Greear + +commit 7d73cd946d4bc7d44cdc5121b1c61d5d71425dea upstream. + +The incorrect timeout check caused probing to happen when it did +not need to happen. This in turn caused tx performance drop +for around 5 seconds in ath10k-ct driver. Possibly that tx drop +is due to a secondary issue, but fixing the probe to not happen +when traffic is running fixes the symptom. + +Signed-off-by: Ben Greear +Fixes: 9abf4e49830d ("mac80211: optimize station connection monitor") +Acked-by: Felix Fietkau +Link: https://lore.kernel.org/r/20210330230749.14097-1-greearb@candelatech.com +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/mac80211/mlme.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -4707,7 +4707,10 @@ static void ieee80211_sta_conn_mon_timer + timeout = sta->rx_stats.last_rx; + timeout += IEEE80211_CONNECTION_IDLE_TIME; + +- if (time_is_before_jiffies(timeout)) { ++ /* If timeout is after now, then update timer to fire at ++ * the later date, but do not actually probe at this time. ++ */ ++ if (time_is_after_jiffies(timeout)) { + mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(timeout)); + return; + } diff --git a/queue-5.11/mac80211-fix-txq-ac-confusion.patch b/queue-5.11/mac80211-fix-txq-ac-confusion.patch new file mode 100644 index 00000000000..03853bda97b --- /dev/null +++ b/queue-5.11/mac80211-fix-txq-ac-confusion.patch @@ -0,0 +1,74 @@ +From 1153a74768a9212daadbb50767aa400bc6a0c9b0 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 23 Mar 2021 21:05:01 +0100 +Subject: mac80211: fix TXQ AC confusion +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Johannes Berg + +commit 1153a74768a9212daadbb50767aa400bc6a0c9b0 upstream. + +Normally, TXQs have + + txq->tid = tid; + txq->ac = ieee80211_ac_from_tid(tid); + +However, the special management TXQ actually has + + txq->tid = IEEE80211_NUM_TIDS; // 16 + txq->ac = IEEE80211_AC_VO; + +This makes sense, but ieee80211_ac_from_tid(16) is the same +as ieee80211_ac_from_tid(0) which is just IEEE80211_AC_BE. + +Now, normally this is fine. However, if the netdev queues +were stopped, then the code in ieee80211_tx_dequeue() will +propagate the stop from the interface (vif->txqs_stopped[]) +if the AC 2 (ieee80211_ac_from_tid(txq->tid)) is marked as +stopped. On wake, however, __ieee80211_wake_txqs() will wake +the TXQ if AC 0 (txq->ac) is woken up. + +If a driver stops all queues with ieee80211_stop_tx_queues() +and then wakes them again with ieee80211_wake_tx_queues(), +the ieee80211_wake_txqs() tasklet will run to resync queue +and TXQ state. If all queues were woken, then what'll happen +is that _ieee80211_wake_txqs() will run in order of HW queues +0-3, typically (and certainly for iwlwifi) corresponding to +ACs 0-3, so it'll call __ieee80211_wake_txqs() for each AC in +order 0-3. + +When __ieee80211_wake_txqs() is called for AC 0 (VO) that'll +wake up the management TXQ (remember its tid is 16), and the +driver's wake_tx_queue() will be called. That tries to get a +frame, which will immediately *stop* the TXQ again, because +now we check against AC 2, and AC 2 hasn't yet been marked as +woken up again in sdata->vif.txqs_stopped[] since we're only +in the __ieee80211_wake_txqs() call for AC 0. + +Thus, the management TXQ will never be started again. + +Fix this by checking txq->ac directly instead of calculating +the AC as ieee80211_ac_from_tid(txq->tid). + +Fixes: adf8ed01e4fd ("mac80211: add an optional TXQ for other PS-buffered frames") +Acked-by: Toke Høiland-Jørgensen +Link: https://lore.kernel.org/r/20210323210500.bf4d50afea4a.I136ffde910486301f8818f5442e3c9bf8670a9c4@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/mac80211/tx.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/mac80211/tx.c ++++ b/net/mac80211/tx.c +@@ -3578,7 +3578,7 @@ begin: + test_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags)) + goto out; + +- if (vif->txqs_stopped[ieee80211_ac_from_tid(txq->tid)]) { ++ if (vif->txqs_stopped[txq->ac]) { + set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags); + goto out; + } diff --git a/queue-5.11/net-ensure-mac-header-is-set-in-virtio_net_hdr_to_skb.patch b/queue-5.11/net-ensure-mac-header-is-set-in-virtio_net_hdr_to_skb.patch new file mode 100644 index 00000000000..001b98e2fe8 --- /dev/null +++ b/queue-5.11/net-ensure-mac-header-is-set-in-virtio_net_hdr_to_skb.patch @@ -0,0 +1,77 @@ +From 61431a5907fc36d0738e9a547c7e1556349a03e9 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Tue, 30 Mar 2021 16:43:43 -0700 +Subject: net: ensure mac header is set in virtio_net_hdr_to_skb() + +From: Eric Dumazet + +commit 61431a5907fc36d0738e9a547c7e1556349a03e9 upstream. + +Commit 924a9bc362a5 ("net: check if protocol extracted by virtio_net_hdr_set_proto is correct") +added a call to dev_parse_header_protocol() but mac_header is not yet set. + +This means that eth_hdr() reads complete garbage, and syzbot complained about it [1] + +This patch resets mac_header earlier, to get more coverage about this change. + +Audit of virtio_net_hdr_to_skb() callers shows that this change should be safe. + +[1] + +BUG: KASAN: use-after-free in eth_header_parse_protocol+0xdc/0xe0 net/ethernet/eth.c:282 +Read of size 2 at addr ffff888017a6200b by task syz-executor313/8409 + +CPU: 1 PID: 8409 Comm: syz-executor313 Not tainted 5.12.0-rc2-syzkaller #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 +Call Trace: + __dump_stack lib/dump_stack.c:79 [inline] + dump_stack+0x141/0x1d7 lib/dump_stack.c:120 + print_address_description.constprop.0.cold+0x5b/0x2f8 mm/kasan/report.c:232 + __kasan_report mm/kasan/report.c:399 [inline] + kasan_report.cold+0x7c/0xd8 mm/kasan/report.c:416 + eth_header_parse_protocol+0xdc/0xe0 net/ethernet/eth.c:282 + dev_parse_header_protocol include/linux/netdevice.h:3177 [inline] + virtio_net_hdr_to_skb.constprop.0+0x99d/0xcd0 include/linux/virtio_net.h:83 + packet_snd net/packet/af_packet.c:2994 [inline] + packet_sendmsg+0x2325/0x52b0 net/packet/af_packet.c:3031 + sock_sendmsg_nosec net/socket.c:654 [inline] + sock_sendmsg+0xcf/0x120 net/socket.c:674 + sock_no_sendpage+0xf3/0x130 net/core/sock.c:2860 + kernel_sendpage.part.0+0x1ab/0x350 net/socket.c:3631 + kernel_sendpage net/socket.c:3628 [inline] + sock_sendpage+0xe5/0x140 net/socket.c:947 + pipe_to_sendpage+0x2ad/0x380 fs/splice.c:364 + splice_from_pipe_feed fs/splice.c:418 [inline] + __splice_from_pipe+0x43e/0x8a0 fs/splice.c:562 + splice_from_pipe fs/splice.c:597 [inline] + generic_splice_sendpage+0xd4/0x140 fs/splice.c:746 + do_splice_from fs/splice.c:767 [inline] + do_splice+0xb7e/0x1940 fs/splice.c:1079 + __do_splice+0x134/0x250 fs/splice.c:1144 + __do_sys_splice fs/splice.c:1350 [inline] + __se_sys_splice fs/splice.c:1332 [inline] + __x64_sys_splice+0x198/0x250 fs/splice.c:1332 + do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 + +Fixes: 924a9bc362a5 ("net: check if protocol extracted by virtio_net_hdr_set_proto is correct") +Signed-off-by: Eric Dumazet +Cc: Balazs Nemeth +Cc: Willem de Bruijn +Reported-by: syzbot +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/virtio_net.h | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/include/linux/virtio_net.h ++++ b/include/linux/virtio_net.h +@@ -62,6 +62,8 @@ static inline int virtio_net_hdr_to_skb( + return -EINVAL; + } + ++ skb_reset_mac_header(skb); ++ + if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { + u16 start = __virtio16_to_cpu(little_endian, hdr->csum_start); + u16 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); diff --git a/queue-5.11/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch b/queue-5.11/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch new file mode 100644 index 00000000000..08afc04de5b --- /dev/null +++ b/queue-5.11/net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch @@ -0,0 +1,143 @@ +From 8a12f8836145ffe37e9c8733dce18c22fb668b66 Mon Sep 17 00:00:00 2001 +From: Anirudh Rayabharam +Date: Wed, 7 Apr 2021 22:57:22 +0530 +Subject: net: hso: fix null-ptr-deref during tty device unregistration + +From: Anirudh Rayabharam + +commit 8a12f8836145ffe37e9c8733dce18c22fb668b66 upstream. + +Multiple ttys try to claim the same the minor number causing a double +unregistration of the same device. The first unregistration succeeds +but the next one results in a null-ptr-deref. + +The get_free_serial_index() function returns an available minor number +but doesn't assign it immediately. The assignment is done by the caller +later. But before this assignment, calls to get_free_serial_index() +would return the same minor number. + +Fix this by modifying get_free_serial_index to assign the minor number +immediately after one is found to be and rename it to obtain_minor() +to better reflect what it does. Similary, rename set_serial_by_index() +to release_minor() and modify it to free up the minor number of the +given hso_serial. Every obtain_minor() should have corresponding +release_minor() call. + +Fixes: 72dc1c096c705 ("HSO: add option hso driver") +Reported-by: syzbot+c49fe6089f295a05e6f8@syzkaller.appspotmail.com +Tested-by: syzbot+c49fe6089f295a05e6f8@syzkaller.appspotmail.com +Reviewed-by: Greg Kroah-Hartman +Signed-off-by: Anirudh Rayabharam +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/hso.c | 33 ++++++++++++--------------------- + 1 file changed, 12 insertions(+), 21 deletions(-) + +--- a/drivers/net/usb/hso.c ++++ b/drivers/net/usb/hso.c +@@ -611,7 +611,7 @@ static struct hso_serial *get_serial_by_ + return serial; + } + +-static int get_free_serial_index(void) ++static int obtain_minor(struct hso_serial *serial) + { + int index; + unsigned long flags; +@@ -619,8 +619,10 @@ static int get_free_serial_index(void) + spin_lock_irqsave(&serial_table_lock, flags); + for (index = 0; index < HSO_SERIAL_TTY_MINORS; index++) { + if (serial_table[index] == NULL) { ++ serial_table[index] = serial->parent; ++ serial->minor = index; + spin_unlock_irqrestore(&serial_table_lock, flags); +- return index; ++ return 0; + } + } + spin_unlock_irqrestore(&serial_table_lock, flags); +@@ -629,15 +631,12 @@ static int get_free_serial_index(void) + return -1; + } + +-static void set_serial_by_index(unsigned index, struct hso_serial *serial) ++static void release_minor(struct hso_serial *serial) + { + unsigned long flags; + + spin_lock_irqsave(&serial_table_lock, flags); +- if (serial) +- serial_table[index] = serial->parent; +- else +- serial_table[index] = NULL; ++ serial_table[serial->minor] = NULL; + spin_unlock_irqrestore(&serial_table_lock, flags); + } + +@@ -2230,6 +2229,7 @@ static int hso_stop_serial_device(struct + static void hso_serial_tty_unregister(struct hso_serial *serial) + { + tty_unregister_device(tty_drv, serial->minor); ++ release_minor(serial); + } + + static void hso_serial_common_free(struct hso_serial *serial) +@@ -2253,24 +2253,22 @@ static void hso_serial_common_free(struc + static int hso_serial_common_create(struct hso_serial *serial, int num_urbs, + int rx_size, int tx_size) + { +- int minor; + int i; + + tty_port_init(&serial->port); + +- minor = get_free_serial_index(); +- if (minor < 0) ++ if (obtain_minor(serial)) + goto exit2; + + /* register our minor number */ + serial->parent->dev = tty_port_register_device_attr(&serial->port, +- tty_drv, minor, &serial->parent->interface->dev, ++ tty_drv, serial->minor, &serial->parent->interface->dev, + serial->parent, hso_serial_dev_groups); +- if (IS_ERR(serial->parent->dev)) ++ if (IS_ERR(serial->parent->dev)) { ++ release_minor(serial); + goto exit2; ++ } + +- /* fill in specific data for later use */ +- serial->minor = minor; + serial->magic = HSO_SERIAL_MAGIC; + spin_lock_init(&serial->serial_lock); + serial->num_rx_urbs = num_urbs; +@@ -2667,9 +2665,6 @@ static struct hso_device *hso_create_bul + + serial->write_data = hso_std_serial_write_data; + +- /* and record this serial */ +- set_serial_by_index(serial->minor, serial); +- + /* setup the proc dirs and files if needed */ + hso_log_port(hso_dev); + +@@ -2726,9 +2721,6 @@ struct hso_device *hso_create_mux_serial + serial->shared_int->ref_count++; + mutex_unlock(&serial->shared_int->shared_int_lock); + +- /* and record this serial */ +- set_serial_by_index(serial->minor, serial); +- + /* setup the proc dirs and files if needed */ + hso_log_port(hso_dev); + +@@ -3113,7 +3105,6 @@ static void hso_free_interface(struct us + cancel_work_sync(&serial_table[i]->async_get_intf); + hso_serial_tty_unregister(serial); + kref_put(&serial_table[i]->ref, hso_serial_ref_free); +- set_serial_by_index(i, NULL); + } + } + diff --git a/queue-5.11/net-hsr-reset-mac-header-for-tx-path.patch b/queue-5.11/net-hsr-reset-mac-header-for-tx-path.patch new file mode 100644 index 00000000000..dce1fa34358 --- /dev/null +++ b/queue-5.11/net-hsr-reset-mac-header-for-tx-path.patch @@ -0,0 +1,66 @@ +From 9d6803921a16f4d768dc41a75375629828f4d91e Mon Sep 17 00:00:00 2001 +From: Kurt Kanzenbach +Date: Tue, 6 Apr 2021 09:35:09 +0200 +Subject: net: hsr: Reset MAC header for Tx path + +From: Kurt Kanzenbach + +commit 9d6803921a16f4d768dc41a75375629828f4d91e upstream. + +Reset MAC header in HSR Tx path. This is needed, because direct packet +transmission, e.g. by specifying PACKET_QDISC_BYPASS does not reset the MAC +header. + +This has been observed using the following setup: + +|$ ip link add name hsr0 type hsr slave1 lan0 slave2 lan1 supervision 45 version 1 +|$ ifconfig hsr0 up +|$ ./test hsr0 + +The test binary is using mmap'ed sockets and is specifying the +PACKET_QDISC_BYPASS socket option. + +This patch resolves the following warning on a non-patched kernel: + +|[ 112.725394] ------------[ cut here ]------------ +|[ 112.731418] WARNING: CPU: 1 PID: 257 at net/hsr/hsr_forward.c:560 hsr_forward_skb+0x484/0x568 +|[ 112.739962] net/hsr/hsr_forward.c:560: Malformed frame (port_src hsr0) + +The warning can be safely removed, because the other call sites of +hsr_forward_skb() make sure that the skb is prepared correctly. + +Fixes: d346a3fae3ff ("packet: introduce PACKET_QDISC_BYPASS socket option") +Signed-off-by: Kurt Kanzenbach +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/hsr/hsr_device.c | 1 + + net/hsr/hsr_forward.c | 6 ------ + 2 files changed, 1 insertion(+), 6 deletions(-) + +--- a/net/hsr/hsr_device.c ++++ b/net/hsr/hsr_device.c +@@ -217,6 +217,7 @@ static netdev_tx_t hsr_dev_xmit(struct s + master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); + if (master) { + skb->dev = master->dev; ++ skb_reset_mac_header(skb); + hsr_forward_skb(skb, master); + } else { + atomic_long_inc(&dev->tx_dropped); +--- a/net/hsr/hsr_forward.c ++++ b/net/hsr/hsr_forward.c +@@ -528,12 +528,6 @@ void hsr_forward_skb(struct sk_buff *skb + { + struct hsr_frame_info frame; + +- if (skb_mac_header(skb) != skb->data) { +- WARN_ONCE(1, "%s:%d: Malformed frame (port_src %s)\n", +- __FILE__, __LINE__, port->dev->name); +- goto out_drop; +- } +- + if (fill_frame_info(&frame, skb, port) < 0) + goto out_drop; + diff --git a/queue-5.11/net-ipv6-bugfix-raw-sctp-switch-to-ipv6_can_nonlocal_bind.patch b/queue-5.11/net-ipv6-bugfix-raw-sctp-switch-to-ipv6_can_nonlocal_bind.patch new file mode 100644 index 00000000000..770361e2a7f --- /dev/null +++ b/queue-5.11/net-ipv6-bugfix-raw-sctp-switch-to-ipv6_can_nonlocal_bind.patch @@ -0,0 +1,85 @@ +From 630e4576f83accf90366686f39808d665d8dbecc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= +Date: Mon, 5 Apr 2021 00:06:52 -0700 +Subject: net-ipv6: bugfix - raw & sctp - switch to ipv6_can_nonlocal_bind() +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Maciej Å»enczykowski + +commit 630e4576f83accf90366686f39808d665d8dbecc upstream. + +Found by virtue of ipv6 raw sockets not honouring the per-socket +IP{,V6}_FREEBIND setting. + +Based on hits found via: + git grep '[.]ip_nonlocal_bind' +We fix both raw ipv6 sockets to honour IP{,V6}_FREEBIND and IP{,V6}_TRANSPARENT, +and we fix sctp sockets to honour IP{,V6}_TRANSPARENT (they already honoured +FREEBIND), and not just the ipv6 'ip_nonlocal_bind' sysctl. + +The helper is defined as: + static inline bool ipv6_can_nonlocal_bind(struct net *net, struct inet_sock *inet) { + return net->ipv6.sysctl.ip_nonlocal_bind || inet->freebind || inet->transparent; + } +so this change only widens the accepted opt-outs and is thus a clean bugfix. + +I'm not entirely sure what 'fixes' tag to add, since this is AFAICT an ancient bug, +but IMHO this should be applied to stable kernels as far back as possible. +As such I'm adding a 'fixes' tag with the commit that originally added the helper, +which happened in 4.19. Backporting to older LTS kernels (at least 4.9 and 4.14) +would presumably require open-coding it or backporting the helper as well. + +Other possibly relevant commits: + v4.18-rc6-1502-g83ba4645152d net: add helpers checking if socket can be bound to nonlocal address + v4.18-rc6-1431-gd0c1f01138c4 net/ipv6: allow any source address for sendmsg pktinfo with ip_nonlocal_bind + v4.14-rc5-271-gb71d21c274ef sctp: full support for ipv6 ip_nonlocal_bind & IP_FREEBIND + v4.7-rc7-1883-g9b9742022888 sctp: support ipv6 nonlocal bind + v4.1-12247-g35a256fee52c ipv6: Nonlocal bind + +Cc: Lorenzo Colitti +Fixes: 83ba4645152d ("net: add helpers checking if socket can be bound to nonlocal address") +Signed-off-by: Maciej Å»enczykowski +Reviewed-By: Lorenzo Colitti +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/raw.c | 2 +- + net/sctp/ipv6.c | 7 +++---- + 2 files changed, 4 insertions(+), 5 deletions(-) + +--- a/net/ipv6/raw.c ++++ b/net/ipv6/raw.c +@@ -298,7 +298,7 @@ static int rawv6_bind(struct sock *sk, s + */ + v4addr = LOOPBACK4_IPV6; + if (!(addr_type & IPV6_ADDR_MULTICAST) && +- !sock_net(sk)->ipv6.sysctl.ip_nonlocal_bind) { ++ !ipv6_can_nonlocal_bind(sock_net(sk), inet)) { + err = -EADDRNOTAVAIL; + if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr, + dev, 0)) { +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -664,8 +664,8 @@ static int sctp_v6_available(union sctp_ + if (!(type & IPV6_ADDR_UNICAST)) + return 0; + +- return sp->inet.freebind || net->ipv6.sysctl.ip_nonlocal_bind || +- ipv6_chk_addr(net, in6, NULL, 0); ++ return ipv6_can_nonlocal_bind(net, &sp->inet) || ++ ipv6_chk_addr(net, in6, NULL, 0); + } + + /* This function checks if the address is a valid address to be used for +@@ -954,8 +954,7 @@ static int sctp_inet6_bind_verify(struct + net = sock_net(&opt->inet.sk); + rcu_read_lock(); + dev = dev_get_by_index_rcu(net, addr->v6.sin6_scope_id); +- if (!dev || !(opt->inet.freebind || +- net->ipv6.sysctl.ip_nonlocal_bind || ++ if (!dev || !(ipv6_can_nonlocal_bind(net, &opt->inet) || + ipv6_chk_addr(net, &addr->v6.sin6_addr, + dev, 0))) { + rcu_read_unlock(); diff --git a/queue-5.11/net-let-skb_orphan_partial-wake-up-waiters.patch b/queue-5.11/net-let-skb_orphan_partial-wake-up-waiters.patch new file mode 100644 index 00000000000..286c28877d4 --- /dev/null +++ b/queue-5.11/net-let-skb_orphan_partial-wake-up-waiters.patch @@ -0,0 +1,78 @@ +From 9adc89af724f12a03b47099cd943ed54e877cd59 Mon Sep 17 00:00:00 2001 +From: Paolo Abeni +Date: Tue, 30 Mar 2021 18:43:54 +0200 +Subject: net: let skb_orphan_partial wake-up waiters. + +From: Paolo Abeni + +commit 9adc89af724f12a03b47099cd943ed54e877cd59 upstream. + +Currently the mentioned helper can end-up freeing the socket wmem +without waking-up any processes waiting for more write memory. + +If the partially orphaned skb is attached to an UDP (or raw) socket, +the lack of wake-up can hang the user-space. + +Even for TCP sockets not calling the sk destructor could have bad +effects on TSQ. + +Address the issue using skb_orphan to release the sk wmem before +setting the new sock_efree destructor. Additionally bundle the +whole ownership update in a new helper, so that later other +potential users could avoid duplicate code. + +v1 -> v2: + - use skb_orphan() instead of sort of open coding it (Eric) + - provide an helper for the ownership change (Eric) + +Fixes: f6ba8d33cfbb ("netem: fix skb_orphan_partial()") +Suggested-by: Eric Dumazet +Signed-off-by: Paolo Abeni +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/sock.h | 9 +++++++++ + net/core/sock.c | 12 +++--------- + 2 files changed, 12 insertions(+), 9 deletions(-) + +--- a/include/net/sock.h ++++ b/include/net/sock.h +@@ -2215,6 +2215,15 @@ static inline void skb_set_owner_r(struc + sk_mem_charge(sk, skb->truesize); + } + ++static inline void skb_set_owner_sk_safe(struct sk_buff *skb, struct sock *sk) ++{ ++ if (sk && refcount_inc_not_zero(&sk->sk_refcnt)) { ++ skb_orphan(skb); ++ skb->destructor = sock_efree; ++ skb->sk = sk; ++ } ++} ++ + void sk_reset_timer(struct sock *sk, struct timer_list *timer, + unsigned long expires); + +--- a/net/core/sock.c ++++ b/net/core/sock.c +@@ -2118,16 +2118,10 @@ void skb_orphan_partial(struct sk_buff * + if (skb_is_tcp_pure_ack(skb)) + return; + +- if (can_skb_orphan_partial(skb)) { +- struct sock *sk = skb->sk; +- +- if (refcount_inc_not_zero(&sk->sk_refcnt)) { +- WARN_ON(refcount_sub_and_test(skb->truesize, &sk->sk_wmem_alloc)); +- skb->destructor = sock_efree; +- } +- } else { ++ if (can_skb_orphan_partial(skb)) ++ skb_set_owner_sk_safe(skb, skb->sk); ++ else + skb_orphan(skb); +- } + } + EXPORT_SYMBOL(skb_orphan_partial); + diff --git a/queue-5.11/net-sched-fix-action-overwrite-reference-counting.patch b/queue-5.11/net-sched-fix-action-overwrite-reference-counting.patch new file mode 100644 index 00000000000..39caa61d182 --- /dev/null +++ b/queue-5.11/net-sched-fix-action-overwrite-reference-counting.patch @@ -0,0 +1,162 @@ +From 87c750e8c38bce706eb32e4d8f1e3402f2cebbd4 Mon Sep 17 00:00:00 2001 +From: Vlad Buslov +Date: Wed, 7 Apr 2021 18:36:03 +0300 +Subject: net: sched: fix action overwrite reference counting + +From: Vlad Buslov + +commit 87c750e8c38bce706eb32e4d8f1e3402f2cebbd4 upstream. + +Action init code increments reference counter when it changes an action. +This is the desired behavior for cls API which needs to obtain action +reference for every classifier that points to action. However, act API just +needs to change the action and releases the reference before returning. +This sequence breaks when the requested action doesn't exist, which causes +act API init code to create new action with specified index, but action is +still released before returning and is deleted (unless it was referenced +concurrently by cls API). + +Reproduction: + +$ sudo tc actions ls action gact +$ sudo tc actions change action gact drop index 1 +$ sudo tc actions ls action gact + +Extend tcf_action_init() to accept 'init_res' array and initialize it with +action->ops->init() result. In tcf_action_add() remove pointers to created +actions from actions array before passing it to tcf_action_put_many(). + +Fixes: cae422f379f3 ("net: sched: use reference counting action init") +Reported-by: Kumar Kartikeya Dwivedi +Signed-off-by: Vlad Buslov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + include/net/act_api.h | 5 +++-- + net/sched/act_api.c | 22 +++++++++++++++------- + net/sched/cls_api.c | 9 +++++---- + 3 files changed, 23 insertions(+), 13 deletions(-) + +--- a/include/net/act_api.h ++++ b/include/net/act_api.h +@@ -185,7 +185,7 @@ int tcf_action_exec(struct sk_buff *skb, + int nr_actions, struct tcf_result *res); + int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, + struct nlattr *est, char *name, int ovr, int bind, +- struct tc_action *actions[], size_t *attr_size, ++ struct tc_action *actions[], int init_res[], size_t *attr_size, + bool rtnl_held, struct netlink_ext_ack *extack); + struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla, + bool rtnl_held, +@@ -193,7 +193,8 @@ struct tc_action_ops *tc_action_load_ops + struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, + struct nlattr *nla, struct nlattr *est, + char *name, int ovr, int bind, +- struct tc_action_ops *ops, bool rtnl_held, ++ struct tc_action_ops *a_o, int *init_res, ++ bool rtnl_held, + struct netlink_ext_ack *extack); + int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[], int bind, + int ref, bool terse); +--- a/net/sched/act_api.c ++++ b/net/sched/act_api.c +@@ -992,7 +992,8 @@ struct tc_action_ops *tc_action_load_ops + struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, + struct nlattr *nla, struct nlattr *est, + char *name, int ovr, int bind, +- struct tc_action_ops *a_o, bool rtnl_held, ++ struct tc_action_ops *a_o, int *init_res, ++ bool rtnl_held, + struct netlink_ext_ack *extack) + { + struct nla_bitfield32 flags = { 0, 0 }; +@@ -1028,6 +1029,7 @@ struct tc_action *tcf_action_init_1(stru + } + if (err < 0) + goto err_out; ++ *init_res = err; + + if (!name && tb[TCA_ACT_COOKIE]) + tcf_set_action_cookie(&a->act_cookie, cookie); +@@ -1056,7 +1058,7 @@ err_out: + + int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, + struct nlattr *est, char *name, int ovr, int bind, +- struct tc_action *actions[], size_t *attr_size, ++ struct tc_action *actions[], int init_res[], size_t *attr_size, + bool rtnl_held, struct netlink_ext_ack *extack) + { + struct tc_action_ops *ops[TCA_ACT_MAX_PRIO] = {}; +@@ -1084,7 +1086,8 @@ int tcf_action_init(struct net *net, str + + for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { + act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind, +- ops[i - 1], rtnl_held, extack); ++ ops[i - 1], &init_res[i - 1], rtnl_held, ++ extack); + if (IS_ERR(act)) { + err = PTR_ERR(act); + goto err; +@@ -1497,12 +1500,13 @@ static int tcf_action_add(struct net *ne + struct netlink_ext_ack *extack) + { + size_t attr_size = 0; +- int loop, ret; ++ int loop, ret, i; + struct tc_action *actions[TCA_ACT_MAX_PRIO] = {}; ++ int init_res[TCA_ACT_MAX_PRIO] = {}; + + for (loop = 0; loop < 10; loop++) { + ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, +- actions, &attr_size, true, extack); ++ actions, init_res, &attr_size, true, extack); + if (ret != -EAGAIN) + break; + } +@@ -1510,8 +1514,12 @@ static int tcf_action_add(struct net *ne + if (ret < 0) + return ret; + ret = tcf_add_notify(net, n, actions, portid, attr_size, extack); +- if (ovr) +- tcf_action_put_many(actions); ++ ++ /* only put existing actions */ ++ for (i = 0; i < TCA_ACT_MAX_PRIO; i++) ++ if (init_res[i] == ACT_P_CREATED) ++ actions[i] = NULL; ++ tcf_action_put_many(actions); + + return ret; + } +--- a/net/sched/cls_api.c ++++ b/net/sched/cls_api.c +@@ -3039,6 +3039,7 @@ int tcf_exts_validate(struct net *net, s + { + #ifdef CONFIG_NET_CLS_ACT + { ++ int init_res[TCA_ACT_MAX_PRIO] = {}; + struct tc_action *act; + size_t attr_size = 0; + +@@ -3050,8 +3051,8 @@ int tcf_exts_validate(struct net *net, s + return PTR_ERR(a_o); + act = tcf_action_init_1(net, tp, tb[exts->police], + rate_tlv, "police", ovr, +- TCA_ACT_BIND, a_o, rtnl_held, +- extack); ++ TCA_ACT_BIND, a_o, init_res, ++ rtnl_held, extack); + if (IS_ERR(act)) { + module_put(a_o->owner); + return PTR_ERR(act); +@@ -3066,8 +3067,8 @@ int tcf_exts_validate(struct net *net, s + + err = tcf_action_init(net, tp, tb[exts->action], + rate_tlv, NULL, ovr, TCA_ACT_BIND, +- exts->actions, &attr_size, +- rtnl_held, extack); ++ exts->actions, init_res, ++ &attr_size, rtnl_held, extack); + if (err < 0) + return err; + exts->nr_actions = err; diff --git a/queue-5.11/net-sched-sch_teql-fix-null-pointer-dereference.patch b/queue-5.11/net-sched-sch_teql-fix-null-pointer-dereference.patch new file mode 100644 index 00000000000..eeead2348b2 --- /dev/null +++ b/queue-5.11/net-sched-sch_teql-fix-null-pointer-dereference.patch @@ -0,0 +1,92 @@ +From 1ffbc7ea91606e4abd10eb60de5367f1c86daf5e Mon Sep 17 00:00:00 2001 +From: Pavel Tikhomirov +Date: Thu, 8 Apr 2021 18:14:31 +0300 +Subject: net: sched: sch_teql: fix null-pointer dereference + +From: Pavel Tikhomirov + +commit 1ffbc7ea91606e4abd10eb60de5367f1c86daf5e upstream. + +Reproduce: + + modprobe sch_teql + tc qdisc add dev teql0 root teql0 + +This leads to (for instance in Centos 7 VM) OOPS: + +[ 532.366633] BUG: unable to handle kernel NULL pointer dereference at 00000000000000a8 +[ 532.366733] IP: [] teql_destroy+0x18/0x100 [sch_teql] +[ 532.366825] PGD 80000001376d5067 PUD 137e37067 PMD 0 +[ 532.366906] Oops: 0000 [#1] SMP +[ 532.366987] Modules linked in: sch_teql ... +[ 532.367945] CPU: 1 PID: 3026 Comm: tc Kdump: loaded Tainted: G ------------ T 3.10.0-1062.7.1.el7.x86_64 #1 +[ 532.368041] Hardware name: Virtuozzo KVM, BIOS 1.11.0-2.vz7.2 04/01/2014 +[ 532.368125] task: ffff8b7d37d31070 ti: ffff8b7c9fdbc000 task.ti: ffff8b7c9fdbc000 +[ 532.368224] RIP: 0010:[] [] teql_destroy+0x18/0x100 [sch_teql] +[ 532.368320] RSP: 0018:ffff8b7c9fdbf8e0 EFLAGS: 00010286 +[ 532.368394] RAX: ffffffffc0612490 RBX: ffff8b7cb1565e00 RCX: ffff8b7d35ba2000 +[ 532.368476] RDX: ffff8b7d35ba2000 RSI: 0000000000000000 RDI: ffff8b7cb1565e00 +[ 532.368557] RBP: ffff8b7c9fdbf8f8 R08: ffff8b7d3fd1f140 R09: ffff8b7d3b001600 +[ 532.368638] R10: ffff8b7d3b001600 R11: ffffffff84c7d65b R12: 00000000ffffffd8 +[ 532.368719] R13: 0000000000008000 R14: ffff8b7d35ba2000 R15: ffff8b7c9fdbf9a8 +[ 532.368800] FS: 00007f6a4e872740(0000) GS:ffff8b7d3fd00000(0000) knlGS:0000000000000000 +[ 532.368885] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 532.368961] CR2: 00000000000000a8 CR3: 00000001396ee000 CR4: 00000000000206e0 +[ 532.369046] Call Trace: +[ 532.369159] [] qdisc_create+0x36e/0x450 +[ 532.369268] [] ? ns_capable+0x29/0x50 +[ 532.369366] [] ? nla_parse+0x32/0x120 +[ 532.369442] [] tc_modify_qdisc+0x13c/0x610 +[ 532.371508] [] rtnetlink_rcv_msg+0xa7/0x260 +[ 532.372668] [] ? sock_has_perm+0x75/0x90 +[ 532.373790] [] ? rtnl_newlink+0x890/0x890 +[ 532.374914] [] netlink_rcv_skb+0xab/0xc0 +[ 532.376055] [] rtnetlink_rcv+0x28/0x30 +[ 532.377204] [] netlink_unicast+0x170/0x210 +[ 532.378333] [] netlink_sendmsg+0x308/0x420 +[ 532.379465] [] sock_sendmsg+0xb6/0xf0 +[ 532.380710] [] ? __xfs_filemap_fault+0x8e/0x1d0 [xfs] +[ 532.381868] [] ? xfs_filemap_fault+0x2c/0x30 [xfs] +[ 532.383037] [] ? __do_fault.isra.61+0x8a/0x100 +[ 532.384144] [] ___sys_sendmsg+0x3e9/0x400 +[ 532.385268] [] ? handle_mm_fault+0x39d/0x9b0 +[ 532.386387] [] ? __do_page_fault+0x238/0x500 +[ 532.387472] [] __sys_sendmsg+0x51/0x90 +[ 532.388560] [] SyS_sendmsg+0x12/0x20 +[ 532.389636] [] system_call_fastpath+0x25/0x2a +[ 532.390704] [] ? system_call_after_swapgs+0xae/0x146 +[ 532.391753] Code: 00 00 00 00 00 00 5b 5d c3 66 2e 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 48 89 e5 41 55 41 54 53 48 8b b7 48 01 00 00 48 89 fb <48> 8b 8e a8 00 00 00 48 85 c9 74 43 48 89 ca eb 0f 0f 1f 80 00 +[ 532.394036] RIP [] teql_destroy+0x18/0x100 [sch_teql] +[ 532.395127] RSP +[ 532.396179] CR2: 00000000000000a8 + +Null pointer dereference happens on master->slaves dereference in +teql_destroy() as master is null-pointer. + +When qdisc_create() calls teql_qdisc_init() it imediately fails after +check "if (m->dev == dev)" because both devices are teql0, and it does +not set qdisc_priv(sch)->m leaving it zero on error path, then +qdisc_create() imediately calls teql_destroy() which does not expect +zero master pointer and we get OOPS. + +Fixes: 87b60cfacf9f ("net_sched: fix error recovery at qdisc creation") +Signed-off-by: Pavel Tikhomirov +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sched/sch_teql.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/sched/sch_teql.c ++++ b/net/sched/sch_teql.c +@@ -134,6 +134,9 @@ teql_destroy(struct Qdisc *sch) + struct teql_sched_data *dat = qdisc_priv(sch); + struct teql_master *master = dat->m; + ++ if (!master) ++ return; ++ + prev = master->slaves; + if (prev) { + do { diff --git a/queue-5.11/nl80211-fix-beacon-head-validation.patch b/queue-5.11/nl80211-fix-beacon-head-validation.patch new file mode 100644 index 00000000000..5d36a4fb2a5 --- /dev/null +++ b/queue-5.11/nl80211-fix-beacon-head-validation.patch @@ -0,0 +1,44 @@ +From 9a6847ba1747858ccac53c5aba3e25c54fbdf846 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 8 Apr 2021 15:45:20 +0200 +Subject: nl80211: fix beacon head validation + +From: Johannes Berg + +commit 9a6847ba1747858ccac53c5aba3e25c54fbdf846 upstream. + +If the beacon head attribute (NL80211_ATTR_BEACON_HEAD) +is too short to even contain the frame control field, +we access uninitialized data beyond the buffer. Fix this +by checking the minimal required size first. We used to +do this until S1G support was added, where the fixed +data portion has a different size. + +Reported-and-tested-by: syzbot+72b99dcf4607e8c770f3@syzkaller.appspotmail.com +Suggested-by: Eric Dumazet +Fixes: 1d47f1198d58 ("nl80211: correctly validate S1G beacon head") +Signed-off-by: Johannes Berg +Link: https://lore.kernel.org/r/20210408154518.d9b06d39b4ee.Iff908997b2a4067e8d456b3cb96cab9771d252b8@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/wireless/nl80211.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -209,9 +209,13 @@ static int validate_beacon_head(const st + unsigned int len = nla_len(attr); + const struct element *elem; + const struct ieee80211_mgmt *mgmt = (void *)data; +- bool s1g_bcn = ieee80211_is_s1g_beacon(mgmt->frame_control); + unsigned int fixedlen, hdrlen; ++ bool s1g_bcn; + ++ if (len < offsetofend(typeof(*mgmt), frame_control)) ++ goto err; ++ ++ s1g_bcn = ieee80211_is_s1g_beacon(mgmt->frame_control); + if (s1g_bcn) { + fixedlen = offsetof(struct ieee80211_ext, + u.s1g_beacon.variable); diff --git a/queue-5.11/nl80211-fix-potential-leak-of-acl-params.patch b/queue-5.11/nl80211-fix-potential-leak-of-acl-params.patch new file mode 100644 index 00000000000..12e96c912dd --- /dev/null +++ b/queue-5.11/nl80211-fix-potential-leak-of-acl-params.patch @@ -0,0 +1,41 @@ +From abaf94ecc9c356d0b885a84edef4905cdd89cfdd Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 8 Apr 2021 14:28:34 +0200 +Subject: nl80211: fix potential leak of ACL params + +From: Johannes Berg + +commit abaf94ecc9c356d0b885a84edef4905cdd89cfdd upstream. + +In case nl80211_parse_unsol_bcast_probe_resp() results in an +error, need to "goto out" instead of just returning to free +possibly allocated data. + +Fixes: 7443dcd1f171 ("nl80211: Unsolicited broadcast probe response support") +Link: https://lore.kernel.org/r/20210408142833.d8bc2e2e454a.If290b1ba85789726a671ff0b237726d4851b5b0f@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/wireless/nl80211.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/net/wireless/nl80211.c ++++ b/net/wireless/nl80211.c +@@ -5,7 +5,7 @@ + * Copyright 2006-2010 Johannes Berg + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright 2015-2017 Intel Deutschland GmbH +- * Copyright (C) 2018-2020 Intel Corporation ++ * Copyright (C) 2018-2021 Intel Corporation + */ + + #include +@@ -5401,7 +5401,7 @@ static int nl80211_start_ap(struct sk_bu + rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP], + ¶ms); + if (err) +- return err; ++ goto out; + } + + nl80211_calculate_ap_params(¶ms); diff --git a/queue-5.11/series b/queue-5.11/series index eda9555a799..03b9d257908 100644 --- a/queue-5.11/series +++ b/queue-5.11/series @@ -36,3 +36,42 @@ of-property-fw_devlink-do-not-link-.-nr-gpios.patch parisc-parisc-agp-requires-sba-iommu-driver.patch parisc-avoid-a-warning-on-u8-cast-for-cmpxchg-on-u8-pointers.patch arm-dts-turris-omnia-configure-led-intn-pin-as-interrupt-pin.patch +batman-adv-initialize-struct-batadv_tvlv_tt_vlan_data-reserved-field.patch +ice-continue-probe-on-link-phy-errors.patch +ice-increase-control-queue-timeout.patch +ice-prevent-ice_open-and-ice_stop-during-reset.patch +ice-fix-memory-allocation-call.patch +ice-remove-dcbnl_devreset-bit-from-pf-state.patch +ice-fix-for-dereference-of-null-pointer.patch +ice-use-port-number-instead-of-pf-id-for-wol.patch +ice-cleanup-fltr-list-in-case-of-allocation-issues.patch +iwlwifi-pcie-properly-set-ltr-workarounds-on-22000-devices.patch +ice-fix-memory-leak-of-arfs-after-resuming-from-suspend.patch +net-hso-fix-null-ptr-deref-during-tty-device-unregistration.patch +libbpf-fix-bail-out-from-ringbuf_process_ring-on-error.patch +bpf-enforce-that-struct_ops-programs-be-gpl-only.patch +bpf-link-refuse-non-o_rdwr-flags-in-bpf_obj_get.patch +ethernet-netronome-nfp-fix-a-use-after-free-in-nfp_bpf_ctrl_msg_rx.patch +libbpf-ensure-umem-pointer-is-non-null-before-dereferencing.patch +libbpf-restore-umem-state-after-socket-create-failure.patch +libbpf-only-create-rx-and-tx-xdp-rings-when-necessary.patch +bpf-refcount-task-stack-in-bpf_get_task_stack.patch +bpf-sockmap-fix-sk-prot-unhash-op-reset.patch +bpf-sockmap-fix-incorrect-fwd_alloc-accounting.patch +net-ensure-mac-header-is-set-in-virtio_net_hdr_to_skb.patch +virtio_net-do-not-pull-payload-in-skb-head.patch +i40e-fix-sparse-warning-missing-error-code-err.patch +i40e-fix-sparse-error-vsi-netdev-could-be-null.patch +i40e-fix-sparse-error-uninitialized-symbol-ring.patch +i40e-fix-sparse-errors-in-i40e_txrx.c.patch +vdpa-mlx5-fix-suspend-resume-index-restoration.patch +net-sched-sch_teql-fix-null-pointer-dereference.patch +net-sched-fix-action-overwrite-reference-counting.patch +nl80211-fix-beacon-head-validation.patch +nl80211-fix-potential-leak-of-acl-params.patch +cfg80211-check-s1g-beacon-compat-element-length.patch +mac80211-fix-time-is-after-bug-in-mlme.patch +mac80211-fix-txq-ac-confusion.patch +net-hsr-reset-mac-header-for-tx-path.patch +net-ipv6-bugfix-raw-sctp-switch-to-ipv6_can_nonlocal_bind.patch +net-let-skb_orphan_partial-wake-up-waiters.patch diff --git a/queue-5.11/vdpa-mlx5-fix-suspend-resume-index-restoration.patch b/queue-5.11/vdpa-mlx5-fix-suspend-resume-index-restoration.patch new file mode 100644 index 00000000000..25f6ef0536b --- /dev/null +++ b/queue-5.11/vdpa-mlx5-fix-suspend-resume-index-restoration.patch @@ -0,0 +1,97 @@ +From bc04d93ea30a0a8eb2a2648b848cef35d1f6f798 Mon Sep 17 00:00:00 2001 +From: Eli Cohen +Date: Thu, 8 Apr 2021 12:10:47 +0300 +Subject: vdpa/mlx5: Fix suspend/resume index restoration + +From: Eli Cohen + +commit bc04d93ea30a0a8eb2a2648b848cef35d1f6f798 upstream. + +When we suspend the VM, the VDPA interface will be reset. When the VM is +resumed again, clear_virtqueues() will clear the available and used +indices resulting in hardware virqtqueue objects becoming out of sync. +We can avoid this function alltogether since qemu will clear them if +required, e.g. when the VM went through a reboot. + +Moreover, since the hw available and used indices should always be +identical on query and should be restored to the same value same value +for virtqueues that complete in order, we set the single value provided +by set_vq_state(). In get_vq_state() we return the value of hardware +used index. + +Fixes: b35ccebe3ef7 ("vdpa/mlx5: Restore the hardware used index after change map") +Fixes: 1a86b377aa21 ("vdpa/mlx5: Add VDPA driver for supported mlx5 devices") +Signed-off-by: Eli Cohen +Link: https://lore.kernel.org/r/20210408091047.4269-6-elic@nvidia.com +Signed-off-by: Michael S. Tsirkin +Acked-by: Jason Wang +Signed-off-by: Greg Kroah-Hartman +--- + drivers/vdpa/mlx5/net/mlx5_vnet.c | 21 ++++++++------------- + 1 file changed, 8 insertions(+), 13 deletions(-) + +--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c ++++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c +@@ -1169,6 +1169,7 @@ static void suspend_vq(struct mlx5_vdpa_ + return; + } + mvq->avail_idx = attr.available_index; ++ mvq->used_idx = attr.used_index; + } + + static void suspend_vqs(struct mlx5_vdpa_net *ndev) +@@ -1426,6 +1427,7 @@ static int mlx5_vdpa_set_vq_state(struct + return -EINVAL; + } + ++ mvq->used_idx = state->avail_index; + mvq->avail_idx = state->avail_index; + return 0; + } +@@ -1443,7 +1445,11 @@ static int mlx5_vdpa_get_vq_state(struct + * that cares about emulating the index after vq is stopped. + */ + if (!mvq->initialized) { +- state->avail_index = mvq->avail_idx; ++ /* Firmware returns a wrong value for the available index. ++ * Since both values should be identical, we take the value of ++ * used_idx which is reported correctly. ++ */ ++ state->avail_index = mvq->used_idx; + return 0; + } + +@@ -1452,7 +1458,7 @@ static int mlx5_vdpa_get_vq_state(struct + mlx5_vdpa_warn(mvdev, "failed to query virtqueue\n"); + return err; + } +- state->avail_index = attr.available_index; ++ state->avail_index = attr.used_index; + return 0; + } + +@@ -1540,16 +1546,6 @@ static void teardown_virtqueues(struct m + } + } + +-static void clear_virtqueues(struct mlx5_vdpa_net *ndev) +-{ +- int i; +- +- for (i = ndev->mvdev.max_vqs - 1; i >= 0; i--) { +- ndev->vqs[i].avail_idx = 0; +- ndev->vqs[i].used_idx = 0; +- } +-} +- + /* TODO: cross-endian support */ + static inline bool mlx5_vdpa_is_little_endian(struct mlx5_vdpa_dev *mvdev) + { +@@ -1785,7 +1781,6 @@ static void mlx5_vdpa_set_status(struct + if (!status) { + mlx5_vdpa_info(mvdev, "performing device reset\n"); + teardown_driver(ndev); +- clear_virtqueues(ndev); + mlx5_vdpa_destroy_mr(&ndev->mvdev); + ndev->mvdev.status = 0; + ndev->mvdev.mlx_features = 0; diff --git a/queue-5.11/virtio_net-do-not-pull-payload-in-skb-head.patch b/queue-5.11/virtio_net-do-not-pull-payload-in-skb-head.patch new file mode 100644 index 00000000000..614b1fccad3 --- /dev/null +++ b/queue-5.11/virtio_net-do-not-pull-payload-in-skb-head.patch @@ -0,0 +1,112 @@ +From 0f6925b3e8da0dbbb52447ca8a8b42b371aac7db Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 2 Apr 2021 06:26:02 -0700 +Subject: virtio_net: Do not pull payload in skb->head + +From: Eric Dumazet + +commit 0f6925b3e8da0dbbb52447ca8a8b42b371aac7db upstream. + +Xuan Zhuo reported that commit 3226b158e67c ("net: avoid 32 x truesize +under-estimation for tiny skbs") brought a ~10% performance drop. + +The reason for the performance drop was that GRO was forced +to chain sk_buff (using skb_shinfo(skb)->frag_list), which +uses more memory but also cause packet consumers to go over +a lot of overhead handling all the tiny skbs. + +It turns out that virtio_net page_to_skb() has a wrong strategy : +It allocates skbs with GOOD_COPY_LEN (128) bytes in skb->head, then +copies 128 bytes from the page, before feeding the packet to GRO stack. + +This was suboptimal before commit 3226b158e67c ("net: avoid 32 x truesize +under-estimation for tiny skbs") because GRO was using 2 frags per MSS, +meaning we were not packing MSS with 100% efficiency. + +Fix is to pull only the ethernet header in page_to_skb() + +Then, we change virtio_net_hdr_to_skb() to pull the missing +headers, instead of assuming they were already pulled by callers. + +This fixes the performance regression, but could also allow virtio_net +to accept packets with more than 128bytes of headers. + +Many thanks to Xuan Zhuo for his report, and his tests/help. + +Fixes: 3226b158e67c ("net: avoid 32 x truesize under-estimation for tiny skbs") +Reported-by: Xuan Zhuo +Link: https://www.spinics.net/lists/netdev/msg731397.html +Co-Developed-by: Xuan Zhuo +Signed-off-by: Xuan Zhuo +Signed-off-by: Eric Dumazet +Cc: "Michael S. Tsirkin" +Cc: Jason Wang +Cc: virtualization@lists.linux-foundation.org +Acked-by: Jason Wang +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/virtio_net.c | 10 +++++++--- + include/linux/virtio_net.h | 14 +++++++++----- + 2 files changed, 16 insertions(+), 8 deletions(-) + +--- a/drivers/net/virtio_net.c ++++ b/drivers/net/virtio_net.c +@@ -406,9 +406,13 @@ static struct sk_buff *page_to_skb(struc + offset += hdr_padded_len; + p += hdr_padded_len; + +- copy = len; +- if (copy > skb_tailroom(skb)) +- copy = skb_tailroom(skb); ++ /* Copy all frame if it fits skb->head, otherwise ++ * we let virtio_net_hdr_to_skb() and GRO pull headers as needed. ++ */ ++ if (len <= skb_tailroom(skb)) ++ copy = len; ++ else ++ copy = ETH_HLEN + metasize; + skb_put_data(skb, p, copy); + + if (metasize) { +--- a/include/linux/virtio_net.h ++++ b/include/linux/virtio_net.h +@@ -65,14 +65,18 @@ static inline int virtio_net_hdr_to_skb( + skb_reset_mac_header(skb); + + if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { +- u16 start = __virtio16_to_cpu(little_endian, hdr->csum_start); +- u16 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); ++ u32 start = __virtio16_to_cpu(little_endian, hdr->csum_start); ++ u32 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); ++ u32 needed = start + max_t(u32, thlen, off + sizeof(__sum16)); ++ ++ if (!pskb_may_pull(skb, needed)) ++ return -EINVAL; + + if (!skb_partial_csum_set(skb, start, off)) + return -EINVAL; + + p_off = skb_transport_offset(skb) + thlen; +- if (p_off > skb_headlen(skb)) ++ if (!pskb_may_pull(skb, p_off)) + return -EINVAL; + } else { + /* gso packets without NEEDS_CSUM do not set transport_offset. +@@ -102,14 +106,14 @@ retry: + } + + p_off = keys.control.thoff + thlen; +- if (p_off > skb_headlen(skb) || ++ if (!pskb_may_pull(skb, p_off) || + keys.basic.ip_proto != ip_proto) + return -EINVAL; + + skb_set_transport_header(skb, keys.control.thoff); + } else if (gso_type) { + p_off = thlen; +- if (p_off > skb_headlen(skb)) ++ if (!pskb_may_pull(skb, p_off)) + return -EINVAL; + } + }