From 4bfaab5c7e584799de4b74eed03aa32c2f78f67e Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 5 May 2025 11:30:14 +0200 Subject: [PATCH] 6.6-stable patches added patches: bpf-add-find_containing_subprog-utility-function.patch bpf-check-changes_pkt_data-property-for-extension-programs.patch bpf-consider-that-tail-calls-invalidate-packet-pointers.patch bpf-fix-null-dereference-when-computing-changes_pkt_data-of-prog-w-o-subprogs.patch bpf-refactor-bpf_helper_changes_pkt_data-to-use-helper-number.patch bpf-track-changes_pkt_data-property-for-global-functions.patch iommu-handle-race-with-default-domain-setup.patch kvm-x86-load-dr6-with-guest-value-only-before-entering-.vcpu_run-loop.patch pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch revert-pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch selftests-bpf-extend-changes_pkt_data-with-cases-w-o-subprograms.patch selftests-bpf-freplace-tests-for-tracking-of-changes_packet_data.patch selftests-bpf-test-for-changing-packet-data-from-global-functions.patch selftests-bpf-validate-that-tail-call-invalidates-packet-pointers.patch --- ..._containing_subprog-utility-function.patch | 67 +++++ ...data-property-for-extension-programs.patch | 129 ++++++++++ ...ail-calls-invalidate-packet-pointers.patch | 63 +++++ ...hanges_pkt_data-of-prog-w-o-subprogs.patch | 73 ++++++ ...hanges_pkt_data-to-use-helper-number.patch | 135 +++++++++++ ...t_data-property-for-global-functions.patch | 165 +++++++++++++ ...andle-race-with-default-domain-setup.patch | 73 ++++++ ...-only-before-entering-.vcpu_run-loop.patch | 228 ++++++++++++++++++ ...oller_id-generation-logic-for-i.mx7d.patch | 47 ++++ ...oller_id-generation-logic-for-i.mx7d.patch | 41 ++++ ..._pkt_data-with-cases-w-o-subprograms.patch | 185 ++++++++++++++ ...-for-tracking-of-changes_packet_data.patch | 161 +++++++++++++ ...ng-packet-data-from-global-functions.patch | 62 +++++ ...ail-call-invalidates-packet-pointers.patch | 67 +++++ queue-6.6/series | 14 ++ 15 files changed, 1510 insertions(+) create mode 100644 queue-6.6/bpf-add-find_containing_subprog-utility-function.patch create mode 100644 queue-6.6/bpf-check-changes_pkt_data-property-for-extension-programs.patch create mode 100644 queue-6.6/bpf-consider-that-tail-calls-invalidate-packet-pointers.patch create mode 100644 queue-6.6/bpf-fix-null-dereference-when-computing-changes_pkt_data-of-prog-w-o-subprogs.patch create mode 100644 queue-6.6/bpf-refactor-bpf_helper_changes_pkt_data-to-use-helper-number.patch create mode 100644 queue-6.6/bpf-track-changes_pkt_data-property-for-global-functions.patch create mode 100644 queue-6.6/iommu-handle-race-with-default-domain-setup.patch create mode 100644 queue-6.6/kvm-x86-load-dr6-with-guest-value-only-before-entering-.vcpu_run-loop.patch create mode 100644 queue-6.6/pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch create mode 100644 queue-6.6/revert-pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch create mode 100644 queue-6.6/selftests-bpf-extend-changes_pkt_data-with-cases-w-o-subprograms.patch create mode 100644 queue-6.6/selftests-bpf-freplace-tests-for-tracking-of-changes_packet_data.patch create mode 100644 queue-6.6/selftests-bpf-test-for-changing-packet-data-from-global-functions.patch create mode 100644 queue-6.6/selftests-bpf-validate-that-tail-call-invalidates-packet-pointers.patch diff --git a/queue-6.6/bpf-add-find_containing_subprog-utility-function.patch b/queue-6.6/bpf-add-find_containing_subprog-utility-function.patch new file mode 100644 index 0000000000..8d12aca403 --- /dev/null +++ b/queue-6.6/bpf-add-find_containing_subprog-utility-function.patch @@ -0,0 +1,67 @@ +From stable+bounces-139108-greg=kroah.com@vger.kernel.org Wed Apr 30 10:20:21 2025 +From: Shung-Hsi Yu +Date: Wed, 30 Apr 2025 16:19:43 +0800 +Subject: bpf: add find_containing_subprog() utility function +To: stable@vger.kernel.org +Cc: Alexei Starovoitov , Eduard Zingerman , Nick Zavaritsky , Dan Carpenter , Shung-Hsi Yu +Message-ID: <20250430081955.49927-2-shung-hsi.yu@suse.com> + +From: Eduard Zingerman + +commit 27e88bc4df1d80888fe1aaca786a7cc6e69587e2 upstream. + +Add a utility function, looking for a subprogram containing a given +instruction index, rewrite find_subprog() to use this function. + +Signed-off-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20241210041100.1898468-2-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Shung-Hsi Yu +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/verifier.c | 28 ++++++++++++++++++++++++---- + 1 file changed, 24 insertions(+), 4 deletions(-) + +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -2636,16 +2636,36 @@ static int cmp_subprogs(const void *a, c + ((struct bpf_subprog_info *)b)->start; + } + ++/* Find subprogram that contains instruction at 'off' */ ++static struct bpf_subprog_info *find_containing_subprog(struct bpf_verifier_env *env, int off) ++{ ++ struct bpf_subprog_info *vals = env->subprog_info; ++ int l, r, m; ++ ++ if (off >= env->prog->len || off < 0 || env->subprog_cnt == 0) ++ return NULL; ++ ++ l = 0; ++ r = env->subprog_cnt - 1; ++ while (l < r) { ++ m = l + (r - l + 1) / 2; ++ if (vals[m].start <= off) ++ l = m; ++ else ++ r = m - 1; ++ } ++ return &vals[l]; ++} ++ ++/* Find subprogram that starts exactly at 'off' */ + static int find_subprog(struct bpf_verifier_env *env, int off) + { + struct bpf_subprog_info *p; + +- p = bsearch(&off, env->subprog_info, env->subprog_cnt, +- sizeof(env->subprog_info[0]), cmp_subprogs); +- if (!p) ++ p = find_containing_subprog(env, off); ++ if (!p || p->start != off) + return -ENOENT; + return p - env->subprog_info; +- + } + + static int add_subprog(struct bpf_verifier_env *env, int off) diff --git a/queue-6.6/bpf-check-changes_pkt_data-property-for-extension-programs.patch b/queue-6.6/bpf-check-changes_pkt_data-property-for-extension-programs.patch new file mode 100644 index 0000000000..960871579c --- /dev/null +++ b/queue-6.6/bpf-check-changes_pkt_data-property-for-extension-programs.patch @@ -0,0 +1,129 @@ +From stable+bounces-139112-greg=kroah.com@vger.kernel.org Wed Apr 30 10:20:34 2025 +From: Shung-Hsi Yu +Date: Wed, 30 Apr 2025 16:19:47 +0800 +Subject: bpf: check changes_pkt_data property for extension programs +To: stable@vger.kernel.org +Cc: Alexei Starovoitov , Eduard Zingerman , Nick Zavaritsky , Dan Carpenter , Shung-Hsi Yu , Alexei Starovoitov +Message-ID: <20250430081955.49927-6-shung-hsi.yu@suse.com> + +From: Eduard Zingerman + +commit 81f6d0530ba031b5f038a091619bf2ff29568852 upstream. + +When processing calls to global sub-programs, verifier decides whether +to invalidate all packet pointers in current state depending on the +changes_pkt_data property of the global sub-program. + +Because of this, an extension program replacing a global sub-program +must be compatible with changes_pkt_data property of the sub-program +being replaced. + +This commit: +- adds changes_pkt_data flag to struct bpf_prog_aux: + - this flag is set in check_cfg() for main sub-program; + - in jit_subprogs() for other sub-programs; +- modifies bpf_check_attach_btf_id() to check changes_pkt_data flag; +- moves call to check_attach_btf_id() after the call to check_cfg(), + because it needs changes_pkt_data flag to be set: + + bpf_check: + ... ... + - check_attach_btf_id resolve_pseudo_ldimm64 + resolve_pseudo_ldimm64 --> bpf_prog_is_offloaded + bpf_prog_is_offloaded check_cfg + check_cfg + check_attach_btf_id + ... ... + +The following fields are set by check_attach_btf_id(): +- env->ops +- prog->aux->attach_btf_trace +- prog->aux->attach_func_name +- prog->aux->attach_func_proto +- prog->aux->dst_trampoline +- prog->aux->mod +- prog->aux->saved_dst_attach_type +- prog->aux->saved_dst_prog_type +- prog->expected_attach_type + +Neither of these fields are used by resolve_pseudo_ldimm64() or +bpf_prog_offload_verifier_prep() (for netronome and netdevsim +drivers), so the reordering is safe. + +Suggested-by: Alexei Starovoitov +Signed-off-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20241210041100.1898468-6-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +[ shung-hsi.yu: adapt to missing fields in "struct bpf_prog_aux". Context +difference in jit_subprogs() because BPF Exception is not supported. Context +difference in bpf_check() because commit 5b5f51bff1b6 "bpf: +no_caller_saved_registers attribute for helper calls" is not present. ] +Signed-off-by: Shung-Hsi Yu +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/bpf.h | 1 + + kernel/bpf/verifier.c | 16 ++++++++++++---- + 2 files changed, 13 insertions(+), 4 deletions(-) + +--- a/include/linux/bpf.h ++++ b/include/linux/bpf.h +@@ -1430,6 +1430,7 @@ struct bpf_prog_aux { + bool sleepable; + bool tail_call_reachable; + bool xdp_has_frags; ++ bool changes_pkt_data; + /* BTF_KIND_FUNC_PROTO for valid attach_btf_id */ + const struct btf_type *attach_func_proto; + /* function name for valid attach_btf_id */ +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -15462,6 +15462,7 @@ static int check_cfg(struct bpf_verifier + } + } + ret = 0; /* cfg looks good */ ++ env->prog->aux->changes_pkt_data = env->subprog_info[0].changes_pkt_data; + + err_free: + kvfree(insn_state); +@@ -18622,6 +18623,7 @@ static int jit_subprogs(struct bpf_verif + } + func[i]->aux->num_exentries = num_exentries; + func[i]->aux->tail_call_reachable = env->subprog_info[i].tail_call_reachable; ++ func[i]->aux->changes_pkt_data = env->subprog_info[i].changes_pkt_data; + func[i] = bpf_int_jit_compile(func[i]); + if (!func[i]->jited) { + err = -ENOTSUPP; +@@ -19934,6 +19936,12 @@ int bpf_check_attach_target(struct bpf_v + "Extension programs should be JITed\n"); + return -EINVAL; + } ++ if (prog->aux->changes_pkt_data && ++ !aux->func[subprog]->aux->changes_pkt_data) { ++ bpf_log(log, ++ "Extension program changes packet data, while original does not\n"); ++ return -EINVAL; ++ } + } + if (!tgt_prog->jited) { + bpf_log(log, "Can attach to only JITed progs\n"); +@@ -20393,10 +20401,6 @@ int bpf_check(struct bpf_prog **prog, un + if (ret < 0) + goto skip_full_check; + +- ret = check_attach_btf_id(env); +- if (ret) +- goto skip_full_check; +- + ret = resolve_pseudo_ldimm64(env); + if (ret < 0) + goto skip_full_check; +@@ -20411,6 +20415,10 @@ int bpf_check(struct bpf_prog **prog, un + if (ret < 0) + goto skip_full_check; + ++ ret = check_attach_btf_id(env); ++ if (ret) ++ goto skip_full_check; ++ + ret = do_check_subprogs(env); + ret = ret ?: do_check_main(env); + diff --git a/queue-6.6/bpf-consider-that-tail-calls-invalidate-packet-pointers.patch b/queue-6.6/bpf-consider-that-tail-calls-invalidate-packet-pointers.patch new file mode 100644 index 0000000000..f6dbb48738 --- /dev/null +++ b/queue-6.6/bpf-consider-that-tail-calls-invalidate-packet-pointers.patch @@ -0,0 +1,63 @@ +From stable+bounces-139114-greg=kroah.com@vger.kernel.org Wed Apr 30 10:20:40 2025 +From: Shung-Hsi Yu +Date: Wed, 30 Apr 2025 16:19:49 +0800 +Subject: bpf: consider that tail calls invalidate packet pointers +To: stable@vger.kernel.org +Cc: Alexei Starovoitov , Eduard Zingerman , Nick Zavaritsky , Dan Carpenter , Shung-Hsi Yu +Message-ID: <20250430081955.49927-8-shung-hsi.yu@suse.com> + +From: Eduard Zingerman + +commit 1a4607ffba35bf2a630aab299e34dd3f6e658d70 upstream. + +Tail-called programs could execute any of the helpers that invalidate +packet pointers. Hence, conservatively assume that each tail call +invalidates packet pointers. + +Making the change in bpf_helper_changes_pkt_data() automatically makes +use of check_cfg() logic that computes 'changes_pkt_data' effect for +global sub-programs, such that the following program could be +rejected: + + int tail_call(struct __sk_buff *sk) + { + bpf_tail_call_static(sk, &jmp_table, 0); + return 0; + } + + SEC("tc") + int not_safe(struct __sk_buff *sk) + { + int *p = (void *)(long)sk->data; + ... make p valid ... + tail_call(sk); + *p = 42; /* this is unsafe */ + ... + } + +The tc_bpf2bpf.c:subprog_tc() needs change: mark it as a function that +can invalidate packet pointers. Otherwise, it can't be freplaced with +tailcall_freplace.c:entry_freplace() that does a tail call. + +Signed-off-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20241210041100.1898468-8-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +[ shung-hsi.yu: drop changes to tools/testing/selftests/bpf/progs/tc_bpf2bpf.c +because it is not present. ] +Signed-off-by: Shung-Hsi Yu +Signed-off-by: Greg Kroah-Hartman +--- + net/core/filter.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -7893,6 +7893,8 @@ bool bpf_helper_changes_pkt_data(enum bp + case BPF_FUNC_xdp_adjust_head: + case BPF_FUNC_xdp_adjust_meta: + case BPF_FUNC_xdp_adjust_tail: ++ /* tail-called program could call any of the above */ ++ case BPF_FUNC_tail_call: + return true; + default: + return false; diff --git a/queue-6.6/bpf-fix-null-dereference-when-computing-changes_pkt_data-of-prog-w-o-subprogs.patch b/queue-6.6/bpf-fix-null-dereference-when-computing-changes_pkt_data-of-prog-w-o-subprogs.patch new file mode 100644 index 0000000000..000a03209c --- /dev/null +++ b/queue-6.6/bpf-fix-null-dereference-when-computing-changes_pkt_data-of-prog-w-o-subprogs.patch @@ -0,0 +1,73 @@ +From stable+bounces-139116-greg=kroah.com@vger.kernel.org Wed Apr 30 10:20:43 2025 +From: Shung-Hsi Yu +Date: Wed, 30 Apr 2025 16:19:51 +0800 +Subject: bpf: fix null dereference when computing changes_pkt_data of prog w/o subprogs +To: stable@vger.kernel.org +Cc: Alexei Starovoitov , Eduard Zingerman , Nick Zavaritsky , Dan Carpenter , Shung-Hsi Yu , kernel test robot +Message-ID: <20250430081955.49927-10-shung-hsi.yu@suse.com> + +From: Eduard Zingerman + +commit ac6542ad92759cda383ad62b4e4cbfc28136abc1 upstream. + +bpf_prog_aux->func field might be NULL if program does not have +subprograms except for main sub-program. The fixed commit does +bpf_prog_aux->func access unconditionally, which might lead to null +pointer dereference. + +The bug could be triggered by replacing the following BPF program: + + SEC("tc") + int main_changes(struct __sk_buff *sk) + { + bpf_skb_pull_data(sk, 0); + return 0; + } + +With the following BPF program: + + SEC("freplace") + long changes_pkt_data(struct __sk_buff *sk) + { + return bpf_skb_pull_data(sk, 0); + } + +bpf_prog_aux instance itself represents the main sub-program, +use this property to fix the bug. + +Fixes: 81f6d0530ba0 ("bpf: check changes_pkt_data property for extension programs") +Reported-by: kernel test robot +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/r/202412111822.qGw6tOyB-lkp@intel.com/ +Signed-off-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20241212070711.427443-1-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Shung-Hsi Yu +Signed-off-by: Greg Kroah-Hartman +--- + kernel/bpf/verifier.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -19908,6 +19908,7 @@ int bpf_check_attach_target(struct bpf_v + } + if (tgt_prog) { + struct bpf_prog_aux *aux = tgt_prog->aux; ++ bool tgt_changes_pkt_data; + + if (bpf_prog_is_dev_bound(prog->aux) && + !bpf_prog_dev_bound_match(prog, tgt_prog)) { +@@ -19936,8 +19937,10 @@ int bpf_check_attach_target(struct bpf_v + "Extension programs should be JITed\n"); + return -EINVAL; + } +- if (prog->aux->changes_pkt_data && +- !aux->func[subprog]->aux->changes_pkt_data) { ++ tgt_changes_pkt_data = aux->func ++ ? aux->func[subprog]->aux->changes_pkt_data ++ : aux->changes_pkt_data; ++ if (prog->aux->changes_pkt_data && !tgt_changes_pkt_data) { + bpf_log(log, + "Extension program changes packet data, while original does not\n"); + return -EINVAL; diff --git a/queue-6.6/bpf-refactor-bpf_helper_changes_pkt_data-to-use-helper-number.patch b/queue-6.6/bpf-refactor-bpf_helper_changes_pkt_data-to-use-helper-number.patch new file mode 100644 index 0000000000..2abc143648 --- /dev/null +++ b/queue-6.6/bpf-refactor-bpf_helper_changes_pkt_data-to-use-helper-number.patch @@ -0,0 +1,135 @@ +From stable+bounces-139109-greg=kroah.com@vger.kernel.org Wed Apr 30 10:20:23 2025 +From: Shung-Hsi Yu +Date: Wed, 30 Apr 2025 16:19:44 +0800 +Subject: bpf: refactor bpf_helper_changes_pkt_data to use helper number +To: stable@vger.kernel.org +Cc: Alexei Starovoitov , Eduard Zingerman , Nick Zavaritsky , Dan Carpenter , Shung-Hsi Yu +Message-ID: <20250430081955.49927-3-shung-hsi.yu@suse.com> + +From: Eduard Zingerman + +commit b238e187b4a2d3b54d80aec05a9cab6466b79dde upstream. + +Use BPF helper number instead of function pointer in +bpf_helper_changes_pkt_data(). This would simplify usage of this +function in verifier.c:check_cfg() (in a follow-up patch), +where only helper number is easily available and there is no real need +to lookup helper proto. + +Signed-off-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20241210041100.1898468-3-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Shung-Hsi Yu +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/filter.h | 2 - + kernel/bpf/core.c | 2 - + kernel/bpf/verifier.c | 2 - + net/core/filter.c | 61 +++++++++++++++++++++---------------------------- + 4 files changed, 30 insertions(+), 37 deletions(-) + +--- a/include/linux/filter.h ++++ b/include/linux/filter.h +@@ -915,7 +915,7 @@ bool bpf_jit_needs_zext(void); + bool bpf_jit_supports_subprog_tailcalls(void); + bool bpf_jit_supports_kfunc_call(void); + bool bpf_jit_supports_far_kfunc_call(void); +-bool bpf_helper_changes_pkt_data(void *func); ++bool bpf_helper_changes_pkt_data(enum bpf_func_id func_id); + + static inline bool bpf_dump_raw_ok(const struct cred *cred) + { +--- a/kernel/bpf/core.c ++++ b/kernel/bpf/core.c +@@ -2893,7 +2893,7 @@ void __weak bpf_jit_compile(struct bpf_p + { + } + +-bool __weak bpf_helper_changes_pkt_data(void *func) ++bool __weak bpf_helper_changes_pkt_data(enum bpf_func_id func_id) + { + return false; + } +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -10007,7 +10007,7 @@ static int check_helper_call(struct bpf_ + } + + /* With LD_ABS/IND some JITs save/restore skb from r1. */ +- changes_data = bpf_helper_changes_pkt_data(fn->func); ++ changes_data = bpf_helper_changes_pkt_data(func_id); + if (changes_data && fn->arg1_type != ARG_PTR_TO_CTX) { + verbose(env, "kernel subsystem misconfigured func %s#%d: r1 != ctx\n", + func_id_name(func_id), func_id); +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -7868,42 +7868,35 @@ static const struct bpf_func_proto bpf_t + + #endif /* CONFIG_INET */ + +-bool bpf_helper_changes_pkt_data(void *func) ++bool bpf_helper_changes_pkt_data(enum bpf_func_id func_id) + { +- if (func == bpf_skb_vlan_push || +- func == bpf_skb_vlan_pop || +- func == bpf_skb_store_bytes || +- func == bpf_skb_change_proto || +- func == bpf_skb_change_head || +- func == sk_skb_change_head || +- func == bpf_skb_change_tail || +- func == sk_skb_change_tail || +- func == bpf_skb_adjust_room || +- func == sk_skb_adjust_room || +- func == bpf_skb_pull_data || +- func == sk_skb_pull_data || +- func == bpf_clone_redirect || +- func == bpf_l3_csum_replace || +- func == bpf_l4_csum_replace || +- func == bpf_xdp_adjust_head || +- func == bpf_xdp_adjust_meta || +- func == bpf_msg_pull_data || +- func == bpf_msg_push_data || +- func == bpf_msg_pop_data || +- func == bpf_xdp_adjust_tail || +-#if IS_ENABLED(CONFIG_IPV6_SEG6_BPF) +- func == bpf_lwt_seg6_store_bytes || +- func == bpf_lwt_seg6_adjust_srh || +- func == bpf_lwt_seg6_action || +-#endif +-#ifdef CONFIG_INET +- func == bpf_sock_ops_store_hdr_opt || +-#endif +- func == bpf_lwt_in_push_encap || +- func == bpf_lwt_xmit_push_encap) ++ switch (func_id) { ++ case BPF_FUNC_clone_redirect: ++ case BPF_FUNC_l3_csum_replace: ++ case BPF_FUNC_l4_csum_replace: ++ case BPF_FUNC_lwt_push_encap: ++ case BPF_FUNC_lwt_seg6_action: ++ case BPF_FUNC_lwt_seg6_adjust_srh: ++ case BPF_FUNC_lwt_seg6_store_bytes: ++ case BPF_FUNC_msg_pop_data: ++ case BPF_FUNC_msg_pull_data: ++ case BPF_FUNC_msg_push_data: ++ case BPF_FUNC_skb_adjust_room: ++ case BPF_FUNC_skb_change_head: ++ case BPF_FUNC_skb_change_proto: ++ case BPF_FUNC_skb_change_tail: ++ case BPF_FUNC_skb_pull_data: ++ case BPF_FUNC_skb_store_bytes: ++ case BPF_FUNC_skb_vlan_pop: ++ case BPF_FUNC_skb_vlan_push: ++ case BPF_FUNC_store_hdr_opt: ++ case BPF_FUNC_xdp_adjust_head: ++ case BPF_FUNC_xdp_adjust_meta: ++ case BPF_FUNC_xdp_adjust_tail: + return true; +- +- return false; ++ default: ++ return false; ++ } + } + + const struct bpf_func_proto bpf_event_output_data_proto __weak; diff --git a/queue-6.6/bpf-track-changes_pkt_data-property-for-global-functions.patch b/queue-6.6/bpf-track-changes_pkt_data-property-for-global-functions.patch new file mode 100644 index 0000000000..2daa340f75 --- /dev/null +++ b/queue-6.6/bpf-track-changes_pkt_data-property-for-global-functions.patch @@ -0,0 +1,165 @@ +From stable+bounces-139110-greg=kroah.com@vger.kernel.org Wed Apr 30 10:20:25 2025 +From: Shung-Hsi Yu +Date: Wed, 30 Apr 2025 16:19:45 +0800 +Subject: bpf: track changes_pkt_data property for global functions +To: stable@vger.kernel.org +Cc: Alexei Starovoitov , Eduard Zingerman , Nick Zavaritsky , Dan Carpenter , Shung-Hsi Yu +Message-ID: <20250430081955.49927-4-shung-hsi.yu@suse.com> + +From: Eduard Zingerman + +commit 51081a3f25c742da5a659d7fc6fd77ebfdd555be upstream. + +When processing calls to certain helpers, verifier invalidates all +packet pointers in a current state. For example, consider the +following program: + + __attribute__((__noinline__)) + long skb_pull_data(struct __sk_buff *sk, __u32 len) + { + return bpf_skb_pull_data(sk, len); + } + + SEC("tc") + int test_invalidate_checks(struct __sk_buff *sk) + { + int *p = (void *)(long)sk->data; + if ((void *)(p + 1) > (void *)(long)sk->data_end) return TCX_DROP; + skb_pull_data(sk, 0); + *p = 42; + return TCX_PASS; + } + +After a call to bpf_skb_pull_data() the pointer 'p' can't be used +safely. See function filter.c:bpf_helper_changes_pkt_data() for a list +of such helpers. + +At the moment verifier invalidates packet pointers when processing +helper function calls, and does not traverse global sub-programs when +processing calls to global sub-programs. This means that calls to +helpers done from global sub-programs do not invalidate pointers in +the caller state. E.g. the program above is unsafe, but is not +rejected by verifier. + +This commit fixes the omission by computing field +bpf_subprog_info->changes_pkt_data for each sub-program before main +verification pass. +changes_pkt_data should be set if: +- subprogram calls helper for which bpf_helper_changes_pkt_data + returns true; +- subprogram calls a global function, + for which bpf_subprog_info->changes_pkt_data should be set. + +The verifier.c:check_cfg() pass is modified to compute this +information. The commit relies on depth first instruction traversal +done by check_cfg() and absence of recursive function calls: +- check_cfg() would eventually visit every call to subprogram S in a + state when S is fully explored; +- when S is fully explored: + - every direct helper call within S is explored + (and thus changes_pkt_data is set if needed); + - every call to subprogram S1 called by S was visited with S1 fully + explored (and thus S inherits changes_pkt_data from S1). + +The downside of such approach is that dead code elimination is not +taken into account: if a helper call inside global function is dead +because of current configuration, verifier would conservatively assume +that the call occurs for the purpose of the changes_pkt_data +computation. + +Reported-by: Nick Zavaritsky +Closes: https://lore.kernel.org/bpf/0498CA22-5779-4767-9C0C-A9515CEA711F@gmail.com/ +Signed-off-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20241210041100.1898468-4-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +[shung-hsi.yu: do not use bitfield in "struct bpf_subprog_info" because commit +406a6fa44bfb ("bpf: use bitfields for simple per-subprog bool flags") is not +present and minor context difference in check_func_call() because commit +491dd8edecbc ("bpf: Emit global subprog name in verifier logs") is not present. ] +Signed-off-by: Shung-Hsi Yu +Signed-off-by: Greg Kroah-Hartman +--- + include/linux/bpf_verifier.h | 1 + + kernel/bpf/verifier.c | 32 +++++++++++++++++++++++++++++++- + 2 files changed, 32 insertions(+), 1 deletion(-) + +--- a/include/linux/bpf_verifier.h ++++ b/include/linux/bpf_verifier.h +@@ -573,6 +573,7 @@ struct bpf_subprog_info { + bool tail_call_reachable; + bool has_ld_abs; + bool is_async_cb; ++ bool changes_pkt_data; + }; + + struct bpf_verifier_env; +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -9364,6 +9364,8 @@ static int check_func_call(struct bpf_ve + + if (env->log.level & BPF_LOG_LEVEL) + verbose(env, "Func#%d is global and valid. Skipping.\n", subprog); ++ if (env->subprog_info[subprog].changes_pkt_data) ++ clear_all_pkt_pointers(env); + clear_caller_saved_regs(env, caller->regs); + + /* All global functions return a 64-bit SCALAR_VALUE */ +@@ -15114,6 +15116,29 @@ static int check_return_code(struct bpf_ + return 0; + } + ++static void mark_subprog_changes_pkt_data(struct bpf_verifier_env *env, int off) ++{ ++ struct bpf_subprog_info *subprog; ++ ++ subprog = find_containing_subprog(env, off); ++ subprog->changes_pkt_data = true; ++} ++ ++/* 't' is an index of a call-site. ++ * 'w' is a callee entry point. ++ * Eventually this function would be called when env->cfg.insn_state[w] == EXPLORED. ++ * Rely on DFS traversal order and absence of recursive calls to guarantee that ++ * callee's change_pkt_data marks would be correct at that moment. ++ */ ++static void merge_callee_effects(struct bpf_verifier_env *env, int t, int w) ++{ ++ struct bpf_subprog_info *caller, *callee; ++ ++ caller = find_containing_subprog(env, t); ++ callee = find_containing_subprog(env, w); ++ caller->changes_pkt_data |= callee->changes_pkt_data; ++} ++ + /* non-recursive DFS pseudo code + * 1 procedure DFS-iterative(G,v): + * 2 label v as discovered +@@ -15247,6 +15272,7 @@ static int visit_func_call_insn(int t, s + bool visit_callee) + { + int ret, insn_sz; ++ int w; + + insn_sz = bpf_is_ldimm64(&insns[t]) ? 2 : 1; + ret = push_insn(t, t + insn_sz, FALLTHROUGH, env); +@@ -15258,8 +15284,10 @@ static int visit_func_call_insn(int t, s + mark_jmp_point(env, t + insn_sz); + + if (visit_callee) { ++ w = t + insns[t].imm + 1; + mark_prune_point(env, t); +- ret = push_insn(t, t + insns[t].imm + 1, BRANCH, env); ++ merge_callee_effects(env, t, w); ++ ret = push_insn(t, w, BRANCH, env); + } + return ret; + } +@@ -15311,6 +15339,8 @@ static int visit_insn(int t, struct bpf_ + mark_prune_point(env, t); + mark_jmp_point(env, t); + } ++ if (bpf_helper_call(insn) && bpf_helper_changes_pkt_data(insn->imm)) ++ mark_subprog_changes_pkt_data(env, t); + if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) { + struct bpf_kfunc_call_arg_meta meta; + diff --git a/queue-6.6/iommu-handle-race-with-default-domain-setup.patch b/queue-6.6/iommu-handle-race-with-default-domain-setup.patch new file mode 100644 index 0000000000..93110be093 --- /dev/null +++ b/queue-6.6/iommu-handle-race-with-default-domain-setup.patch @@ -0,0 +1,73 @@ +From b46064a18810bad3aea089a79993ca5ea7a3d2b2 Mon Sep 17 00:00:00 2001 +From: Robin Murphy +Date: Fri, 28 Feb 2025 15:46:30 +0000 +Subject: iommu: Handle race with default domain setup + +From: Robin Murphy + +commit b46064a18810bad3aea089a79993ca5ea7a3d2b2 upstream. + +It turns out that deferred default domain creation leaves a subtle +race window during iommu_device_register() wherein a client driver may +asynchronously probe in parallel and get as far as performing DMA API +operations with dma-direct, only to be switched to iommu-dma underfoot +once the default domain attachment finally happens, with obviously +disastrous consequences. Even the wonky of_iommu_configure() path is at +risk, since iommu_fwspec_init() will no longer defer client probe as the +instance ops are (necessarily) already registered, and the "replay" +iommu_probe_device() call can see dev->iommu_group already set and so +think there's nothing to do either. + +Fortunately we already have the right tool in the right place in the +form of iommu_device_use_default_domain(), which just needs to ensure +that said default domain is actually ready to *be* used. Deferring the +client probe shouldn't have too much impact, given that this only +happens while the IOMMU driver is probing, and thus due to kick the +deferred probe list again once it finishes. + +Reported-by: Charan Teja Kalla +Fixes: 98ac73f99bc4 ("iommu: Require a default_domain for all iommu drivers") +Reviewed-by: Jason Gunthorpe +Signed-off-by: Robin Murphy +Link: https://lore.kernel.org/r/e88b94c9b575034a2c98a48b3d383654cbda7902.1740753261.git.robin.murphy@arm.com +Signed-off-by: Joerg Roedel +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Robin Murphy +--- + drivers/iommu/iommu.c | 18 ++++++++++++++++++ + 1 file changed, 18 insertions(+) + +--- a/drivers/iommu/iommu.c ++++ b/drivers/iommu/iommu.c +@@ -566,6 +566,18 @@ int iommu_probe_device(struct device *de + mutex_lock(&iommu_probe_device_lock); + ret = __iommu_probe_device(dev, NULL); + mutex_unlock(&iommu_probe_device_lock); ++ ++ /* ++ * The dma_configure replay paths need bus_iommu_probe() to ++ * finish before they can call arch_setup_dma_ops() ++ */ ++ if (IS_ENABLED(CONFIG_IOMMU_DMA) && !ret && dev->iommu_group) { ++ mutex_lock(&dev->iommu_group->mutex); ++ if (!dev->iommu_group->default_domain && ++ !dev_iommu_ops(dev)->set_platform_dma_ops) ++ ret = -EPROBE_DEFER; ++ mutex_unlock(&dev->iommu_group->mutex); ++ } + if (ret) + return ret; + +@@ -3149,6 +3161,12 @@ int iommu_device_use_default_domain(stru + return 0; + + mutex_lock(&group->mutex); ++ /* We may race against bus_iommu_probe() finalising groups here */ ++ if (IS_ENABLED(CONFIG_IOMMU_DMA) && !group->default_domain && ++ !dev_iommu_ops(dev)->set_platform_dma_ops) { ++ ret = -EPROBE_DEFER; ++ goto unlock_out; ++ } + if (group->owner_cnt) { + if (group->owner || !iommu_is_default_domain(group) || + !xa_empty(&group->pasid_array)) { diff --git a/queue-6.6/kvm-x86-load-dr6-with-guest-value-only-before-entering-.vcpu_run-loop.patch b/queue-6.6/kvm-x86-load-dr6-with-guest-value-only-before-entering-.vcpu_run-loop.patch new file mode 100644 index 0000000000..9967d2f21a --- /dev/null +++ b/queue-6.6/kvm-x86-load-dr6-with-guest-value-only-before-entering-.vcpu_run-loop.patch @@ -0,0 +1,228 @@ +From c2fee09fc167c74a64adb08656cb993ea475197e Mon Sep 17 00:00:00 2001 +From: Sean Christopherson +Date: Fri, 24 Jan 2025 17:18:33 -0800 +Subject: KVM: x86: Load DR6 with guest value only before entering .vcpu_run() loop + +From: Sean Christopherson + +commit c2fee09fc167c74a64adb08656cb993ea475197e upstream. + +Move the conditional loading of hardware DR6 with the guest's DR6 value +out of the core .vcpu_run() loop to fix a bug where KVM can load hardware +with a stale vcpu->arch.dr6. + +When the guest accesses a DR and host userspace isn't debugging the guest, +KVM disables DR interception and loads the guest's values into hardware on +VM-Enter and saves them on VM-Exit. This allows the guest to access DRs +at will, e.g. so that a sequence of DR accesses to configure a breakpoint +only generates one VM-Exit. + +For DR0-DR3, the logic/behavior is identical between VMX and SVM, and also +identical between KVM_DEBUGREG_BP_ENABLED (userspace debugging the guest) +and KVM_DEBUGREG_WONT_EXIT (guest using DRs), and so KVM handles loading +DR0-DR3 in common code, _outside_ of the core kvm_x86_ops.vcpu_run() loop. + +But for DR6, the guest's value doesn't need to be loaded into hardware for +KVM_DEBUGREG_BP_ENABLED, and SVM provides a dedicated VMCB field whereas +VMX requires software to manually load the guest value, and so loading the +guest's value into DR6 is handled by {svm,vmx}_vcpu_run(), i.e. is done +_inside_ the core run loop. + +Unfortunately, saving the guest values on VM-Exit is initiated by common +x86, again outside of the core run loop. If the guest modifies DR6 (in +hardware, when DR interception is disabled), and then the next VM-Exit is +a fastpath VM-Exit, KVM will reload hardware DR6 with vcpu->arch.dr6 and +clobber the guest's actual value. + +The bug shows up primarily with nested VMX because KVM handles the VMX +preemption timer in the fastpath, and the window between hardware DR6 +being modified (in guest context) and DR6 being read by guest software is +orders of magnitude larger in a nested setup. E.g. in non-nested, the +VMX preemption timer would need to fire precisely between #DB injection +and the #DB handler's read of DR6, whereas with a KVM-on-KVM setup, the +window where hardware DR6 is "dirty" extends all the way from L1 writing +DR6 to VMRESUME (in L1). + + L1's view: + ========== + + CPU 0/KVM-7289 [023] d.... 2925.640961: kvm_entry: vcpu 0 + A: L1 Writes DR6 + CPU 0/KVM-7289 [023] d.... 2925.640963: : Set DRs, DR6 = 0xffff0ff1 + + B: CPU 0/KVM-7289 [023] d.... 2925.640967: kvm_exit: vcpu 0 reason EXTERNAL_INTERRUPT intr_info 0x800000ec + + D: L1 reads DR6, arch.dr6 = 0 + CPU 0/KVM-7289 [023] d.... 2925.640969: : Sync DRs, DR6 = 0xffff0ff0 + + CPU 0/KVM-7289 [023] d.... 2925.640976: kvm_entry: vcpu 0 + L2 reads DR6, L1 disables DR interception + CPU 0/KVM-7289 [023] d.... 2925.640980: kvm_exit: vcpu 0 reason DR_ACCESS info1 0x0000000000000216 + CPU 0/KVM-7289 [023] d.... 2925.640983: kvm_entry: vcpu 0 + + CPU 0/KVM-7289 [023] d.... 2925.640983: : Set DRs, DR6 = 0xffff0ff0 + + L2 detects failure + CPU 0/KVM-7289 [023] d.... 2925.640987: kvm_exit: vcpu 0 reason HLT + L1 reads DR6 (confirms failure) + CPU 0/KVM-7289 [023] d.... 2925.640990: : Sync DRs, DR6 = 0xffff0ff0 + + L0's view: + ========== + L2 reads DR6, arch.dr6 = 0 + CPU 23/KVM-5046 [001] d.... 3410.005610: kvm_exit: vcpu 23 reason DR_ACCESS info1 0x0000000000000216 + CPU 23/KVM-5046 [001] ..... 3410.005610: kvm_nested_vmexit: vcpu 23 reason DR_ACCESS info1 0x0000000000000216 + + L2 => L1 nested VM-Exit + CPU 23/KVM-5046 [001] ..... 3410.005610: kvm_nested_vmexit_inject: reason: DR_ACCESS ext_inf1: 0x0000000000000216 + + CPU 23/KVM-5046 [001] d.... 3410.005610: kvm_entry: vcpu 23 + CPU 23/KVM-5046 [001] d.... 3410.005611: kvm_exit: vcpu 23 reason VMREAD + CPU 23/KVM-5046 [001] d.... 3410.005611: kvm_entry: vcpu 23 + CPU 23/KVM-5046 [001] d.... 3410.005612: kvm_exit: vcpu 23 reason VMREAD + CPU 23/KVM-5046 [001] d.... 3410.005612: kvm_entry: vcpu 23 + + L1 writes DR7, L0 disables DR interception + CPU 23/KVM-5046 [001] d.... 3410.005612: kvm_exit: vcpu 23 reason DR_ACCESS info1 0x0000000000000007 + CPU 23/KVM-5046 [001] d.... 3410.005613: kvm_entry: vcpu 23 + + L0 writes DR6 = 0 (arch.dr6) + CPU 23/KVM-5046 [001] d.... 3410.005613: : Set DRs, DR6 = 0xffff0ff0 + + A: + + B: CPU 23/KVM-5046 [001] d.... 3410.005614: kvm_exit: vcpu 23 reason PREEMPTION_TIMER + CPU 23/KVM-5046 [001] d.... 3410.005614: kvm_entry: vcpu 23 + + C: L0 writes DR6 = 0 (arch.dr6) + CPU 23/KVM-5046 [001] d.... 3410.005614: : Set DRs, DR6 = 0xffff0ff0 + + L1 => L2 nested VM-Enter + CPU 23/KVM-5046 [001] d.... 3410.005616: kvm_exit: vcpu 23 reason VMRESUME + + L0 reads DR6, arch.dr6 = 0 + +Reported-by: John Stultz +Closes: https://lkml.kernel.org/r/CANDhNCq5_F3HfFYABqFGCA1bPd_%2BxgNj-iDQhH4tDk%2Bwi8iZZg%40mail.gmail.com +Fixes: 375e28ffc0cf ("KVM: X86: Set host DR6 only on VMX and for KVM_DEBUGREG_WONT_EXIT") +Fixes: d67668e9dd76 ("KVM: x86, SVM: isolate vcpu->arch.dr6 from vmcb->save.dr6") +Cc: stable@vger.kernel.org +Cc: Jim Mattson +Tested-by: John Stultz +Link: https://lore.kernel.org/r/20250125011833.3644371-1-seanjc@google.com +Signed-off-by: Sean Christopherson +[jth: Handled conflicts with kvm_x86_ops reshuffle] +Signed-off-by: James Houghton +Signed-off-by: Greg Kroah-Hartman +--- + arch/x86/include/asm/kvm-x86-ops.h | 1 + + arch/x86/include/asm/kvm_host.h | 1 + + arch/x86/kvm/svm/svm.c | 13 ++++++------- + arch/x86/kvm/vmx/vmx.c | 11 +++++++---- + arch/x86/kvm/x86.c | 3 +++ + 5 files changed, 18 insertions(+), 11 deletions(-) + +--- a/arch/x86/include/asm/kvm-x86-ops.h ++++ b/arch/x86/include/asm/kvm-x86-ops.h +@@ -48,6 +48,7 @@ KVM_X86_OP(set_idt) + KVM_X86_OP(get_gdt) + KVM_X86_OP(set_gdt) + KVM_X86_OP(sync_dirty_debug_regs) ++KVM_X86_OP(set_dr6) + KVM_X86_OP(set_dr7) + KVM_X86_OP(cache_reg) + KVM_X86_OP(get_rflags) +--- a/arch/x86/include/asm/kvm_host.h ++++ b/arch/x86/include/asm/kvm_host.h +@@ -1595,6 +1595,7 @@ struct kvm_x86_ops { + void (*get_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); + void (*set_gdt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt); + void (*sync_dirty_debug_regs)(struct kvm_vcpu *vcpu); ++ void (*set_dr6)(struct kvm_vcpu *vcpu, unsigned long value); + void (*set_dr7)(struct kvm_vcpu *vcpu, unsigned long value); + void (*cache_reg)(struct kvm_vcpu *vcpu, enum kvm_reg reg); + unsigned long (*get_rflags)(struct kvm_vcpu *vcpu); +--- a/arch/x86/kvm/svm/svm.c ++++ b/arch/x86/kvm/svm/svm.c +@@ -2014,11 +2014,11 @@ static void new_asid(struct vcpu_svm *sv + svm->asid = sd->next_asid++; + } + +-static void svm_set_dr6(struct vcpu_svm *svm, unsigned long value) ++static void svm_set_dr6(struct kvm_vcpu *vcpu, unsigned long value) + { +- struct vmcb *vmcb = svm->vmcb; ++ struct vmcb *vmcb = to_svm(vcpu)->vmcb; + +- if (svm->vcpu.arch.guest_state_protected) ++ if (vcpu->arch.guest_state_protected) + return; + + if (unlikely(value != vmcb->save.dr6)) { +@@ -4220,10 +4220,8 @@ static __no_kcsan fastpath_t svm_vcpu_ru + * Run with all-zero DR6 unless needed, so that we can get the exact cause + * of a #DB. + */ +- if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) +- svm_set_dr6(svm, vcpu->arch.dr6); +- else +- svm_set_dr6(svm, DR6_ACTIVE_LOW); ++ if (likely(!(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT))) ++ svm_set_dr6(vcpu, DR6_ACTIVE_LOW); + + clgi(); + kvm_load_guest_xsave_state(vcpu); +@@ -5002,6 +5000,7 @@ static struct kvm_x86_ops svm_x86_ops __ + .set_idt = svm_set_idt, + .get_gdt = svm_get_gdt, + .set_gdt = svm_set_gdt, ++ .set_dr6 = svm_set_dr6, + .set_dr7 = svm_set_dr7, + .sync_dirty_debug_regs = svm_sync_dirty_debug_regs, + .cache_reg = svm_cache_reg, +--- a/arch/x86/kvm/vmx/vmx.c ++++ b/arch/x86/kvm/vmx/vmx.c +@@ -5617,6 +5617,12 @@ static void vmx_sync_dirty_debug_regs(st + set_debugreg(DR6_RESERVED, 6); + } + ++static void vmx_set_dr6(struct kvm_vcpu *vcpu, unsigned long val) ++{ ++ lockdep_assert_irqs_disabled(); ++ set_debugreg(vcpu->arch.dr6, 6); ++} ++ + static void vmx_set_dr7(struct kvm_vcpu *vcpu, unsigned long val) + { + vmcs_writel(GUEST_DR7, val); +@@ -7356,10 +7362,6 @@ static fastpath_t vmx_vcpu_run(struct kv + vmx->loaded_vmcs->host_state.cr4 = cr4; + } + +- /* When KVM_DEBUGREG_WONT_EXIT, dr6 is accessible in guest. */ +- if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) +- set_debugreg(vcpu->arch.dr6, 6); +- + /* When single-stepping over STI and MOV SS, we must clear the + * corresponding interruptibility bits in the guest state. Otherwise + * vmentry fails as it then expects bit 14 (BS) in pending debug +@@ -8292,6 +8294,7 @@ static struct kvm_x86_ops vmx_x86_ops __ + .set_idt = vmx_set_idt, + .get_gdt = vmx_get_gdt, + .set_gdt = vmx_set_gdt, ++ .set_dr6 = vmx_set_dr6, + .set_dr7 = vmx_set_dr7, + .sync_dirty_debug_regs = vmx_sync_dirty_debug_regs, + .cache_reg = vmx_cache_reg, +--- a/arch/x86/kvm/x86.c ++++ b/arch/x86/kvm/x86.c +@@ -10772,6 +10772,9 @@ static int vcpu_enter_guest(struct kvm_v + set_debugreg(vcpu->arch.eff_db[1], 1); + set_debugreg(vcpu->arch.eff_db[2], 2); + set_debugreg(vcpu->arch.eff_db[3], 3); ++ /* When KVM_DEBUGREG_WONT_EXIT, dr6 is accessible in guest. */ ++ if (unlikely(vcpu->arch.switch_db_regs & KVM_DEBUGREG_WONT_EXIT)) ++ static_call(kvm_x86_set_dr6)(vcpu, vcpu->arch.dr6); + } else if (unlikely(hw_breakpoint_active())) { + set_debugreg(0, 7); + } diff --git a/queue-6.6/pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch b/queue-6.6/pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch new file mode 100644 index 0000000000..bcf62749e8 --- /dev/null +++ b/queue-6.6/pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch @@ -0,0 +1,47 @@ +From stable+bounces-139573-greg=kroah.com@vger.kernel.org Sun May 4 21:15:49 2025 +From: Ryan Matthews +Date: Sun, 4 May 2025 15:13:56 -0400 +Subject: PCI: imx6: Skip controller_id generation logic for i.MX7D +To: Greg Kroah-Hartman +Cc: "Richard Zhu" , "Lucas Stach" , stable@vger.kernel.org, linux-pci@vger.kernel.org, "Ryan Matthews" , "Krzysztof Wilczyński" , "Bjorn Helgaas" , "Manivannan Sadhasivam" , "Frank Li" +Message-ID: <20250504191356.17732-3-ryanmatthews@fastmail.com> + +From: Richard Zhu + +[ Upstream commit f068ffdd034c93f0c768acdc87d4d2d7023c1379 ] + +The i.MX7D only has one PCIe controller, so controller_id should always be +0. The previous code is incorrect although yielding the correct result. + +Fix by removing "IMX7D" from the switch case branch. + +Fixes: 2d8ed461dbc9 ("PCI: imx6: Add support for i.MX8MQ") +Link: https://lore.kernel.org/r/20241126075702.4099164-5-hongxing.zhu@nxp.com +Signed-off-by: Richard Zhu +Signed-off-by: Krzysztof Wilczyński +Signed-off-by: Bjorn Helgaas +Reviewed-by: Manivannan Sadhasivam +Reviewed-by: Frank Li +[Because this switch case does more than just controller_id + logic, move the "IMX7D" case label instead of removing it entirely.] +Signed-off-by: Ryan Matthews +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/dwc/pci-imx6.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/pci/controller/dwc/pci-imx6.c ++++ b/drivers/pci/controller/dwc/pci-imx6.c +@@ -1281,10 +1281,10 @@ static int imx6_pcie_probe(struct platfo + switch (imx6_pcie->drvdata->variant) { + case IMX8MQ: + case IMX8MQ_EP: +- case IMX7D: + if (dbi_base->start == IMX8MQ_PCIE2_BASE_ADDR) + imx6_pcie->controller_id = 1; +- ++ fallthrough; ++ case IMX7D: + imx6_pcie->pciephy_reset = devm_reset_control_get_exclusive(dev, + "pciephy"); + if (IS_ERR(imx6_pcie->pciephy_reset)) { diff --git a/queue-6.6/revert-pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch b/queue-6.6/revert-pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch new file mode 100644 index 0000000000..26c94bf0cd --- /dev/null +++ b/queue-6.6/revert-pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch @@ -0,0 +1,41 @@ +From stable+bounces-139572-greg=kroah.com@vger.kernel.org Sun May 4 21:15:30 2025 +From: Ryan Matthews +Date: Sun, 4 May 2025 15:13:55 -0400 +Subject: Revert "PCI: imx6: Skip controller_id generation logic for i.MX7D" +To: Greg Kroah-Hartman +Cc: Richard Zhu , Lucas Stach , stable@vger.kernel.org, linux-pci@vger.kernel.org, Ryan Matthews +Message-ID: <20250504191356.17732-2-ryanmatthews@fastmail.com> + +From: Ryan Matthews + +This reverts commit 2a12efc567a270a155e3b886258297abd79cdea0 which is +commit f068ffdd034c93f0c768acdc87d4d2d7023c1379 upstream. + +This is a backport mistake. + +Deleting "IMX7D" here skips more than just controller_id logic. It skips +reset assignments too, which causes: + + imx6q-pcie 33800000.pcie: PCIe PLL lock timeout + +In my case, in addition to broken PCIe, kernel boot hangs entirely. + +This isn't a problem upstream because before this, they moved the rest of +the code out of the switch case. + +Signed-off-by: Ryan Matthews +Signed-off-by: Greg Kroah-Hartman +--- + drivers/pci/controller/dwc/pci-imx6.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/pci/controller/dwc/pci-imx6.c ++++ b/drivers/pci/controller/dwc/pci-imx6.c +@@ -1281,6 +1281,7 @@ static int imx6_pcie_probe(struct platfo + switch (imx6_pcie->drvdata->variant) { + case IMX8MQ: + case IMX8MQ_EP: ++ case IMX7D: + if (dbi_base->start == IMX8MQ_PCIE2_BASE_ADDR) + imx6_pcie->controller_id = 1; + diff --git a/queue-6.6/selftests-bpf-extend-changes_pkt_data-with-cases-w-o-subprograms.patch b/queue-6.6/selftests-bpf-extend-changes_pkt_data-with-cases-w-o-subprograms.patch new file mode 100644 index 0000000000..7ef4430db7 --- /dev/null +++ b/queue-6.6/selftests-bpf-extend-changes_pkt_data-with-cases-w-o-subprograms.patch @@ -0,0 +1,185 @@ +From stable+bounces-139117-greg=kroah.com@vger.kernel.org Wed Apr 30 10:20:50 2025 +From: Shung-Hsi Yu +Date: Wed, 30 Apr 2025 16:19:52 +0800 +Subject: selftests/bpf: extend changes_pkt_data with cases w/o subprograms +To: stable@vger.kernel.org +Cc: Alexei Starovoitov , Eduard Zingerman , Nick Zavaritsky , Dan Carpenter , Shung-Hsi Yu +Message-ID: <20250430081955.49927-11-shung-hsi.yu@suse.com> + +From: Eduard Zingerman + +commit 04789af756a4a43e72986185f66f148e65b32fed upstream. + +Extend changes_pkt_data tests with test cases freplacing the main +program that does not have subprograms. Try four combinations when +both main program and replacement do and do not change packet data. + +Signed-off-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20241212070711.427443-2-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Shung-Hsi Yu +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/bpf/prog_tests/changes_pkt_data.c | 55 +++++++--- + tools/testing/selftests/bpf/progs/changes_pkt_data.c | 27 +++- + tools/testing/selftests/bpf/progs/changes_pkt_data_freplace.c | 6 - + 3 files changed, 66 insertions(+), 22 deletions(-) + +--- a/tools/testing/selftests/bpf/prog_tests/changes_pkt_data.c ++++ b/tools/testing/selftests/bpf/prog_tests/changes_pkt_data.c +@@ -10,10 +10,14 @@ static void print_verifier_log(const cha + fprintf(stdout, "VERIFIER LOG:\n=============\n%s=============\n", log); + } + +-static void test_aux(const char *main_prog_name, const char *freplace_prog_name, bool expect_load) ++static void test_aux(const char *main_prog_name, ++ const char *to_be_replaced, ++ const char *replacement, ++ bool expect_load) + { + struct changes_pkt_data_freplace *freplace = NULL; + struct bpf_program *freplace_prog = NULL; ++ struct bpf_program *main_prog = NULL; + LIBBPF_OPTS(bpf_object_open_opts, opts); + struct changes_pkt_data *main = NULL; + char log[16*1024]; +@@ -26,6 +30,10 @@ static void test_aux(const char *main_pr + main = changes_pkt_data__open_opts(&opts); + if (!ASSERT_OK_PTR(main, "changes_pkt_data__open")) + goto out; ++ main_prog = bpf_object__find_program_by_name(main->obj, main_prog_name); ++ if (!ASSERT_OK_PTR(main_prog, "main_prog")) ++ goto out; ++ bpf_program__set_autoload(main_prog, true); + err = changes_pkt_data__load(main); + print_verifier_log(log); + if (!ASSERT_OK(err, "changes_pkt_data__load")) +@@ -33,14 +41,14 @@ static void test_aux(const char *main_pr + freplace = changes_pkt_data_freplace__open_opts(&opts); + if (!ASSERT_OK_PTR(freplace, "changes_pkt_data_freplace__open")) + goto out; +- freplace_prog = bpf_object__find_program_by_name(freplace->obj, freplace_prog_name); ++ freplace_prog = bpf_object__find_program_by_name(freplace->obj, replacement); + if (!ASSERT_OK_PTR(freplace_prog, "freplace_prog")) + goto out; + bpf_program__set_autoload(freplace_prog, true); + bpf_program__set_autoattach(freplace_prog, true); + bpf_program__set_attach_target(freplace_prog, +- bpf_program__fd(main->progs.dummy), +- main_prog_name); ++ bpf_program__fd(main_prog), ++ to_be_replaced); + err = changes_pkt_data_freplace__load(freplace); + print_verifier_log(log); + if (expect_load) { +@@ -62,15 +70,38 @@ out: + * that either do or do not. It is only ok to freplace subprograms + * that do not change packet data with those that do not as well. + * The below tests check outcomes for each combination of such freplace. ++ * Also test a case when main subprogram itself is replaced and is a single ++ * subprogram in a program. + */ + void test_changes_pkt_data_freplace(void) + { +- if (test__start_subtest("changes_with_changes")) +- test_aux("changes_pkt_data", "changes_pkt_data", true); +- if (test__start_subtest("changes_with_doesnt_change")) +- test_aux("changes_pkt_data", "does_not_change_pkt_data", true); +- if (test__start_subtest("doesnt_change_with_changes")) +- test_aux("does_not_change_pkt_data", "changes_pkt_data", false); +- if (test__start_subtest("doesnt_change_with_doesnt_change")) +- test_aux("does_not_change_pkt_data", "does_not_change_pkt_data", true); ++ struct { ++ const char *main; ++ const char *to_be_replaced; ++ bool changes; ++ } mains[] = { ++ { "main_with_subprogs", "changes_pkt_data", true }, ++ { "main_with_subprogs", "does_not_change_pkt_data", false }, ++ { "main_changes", "main_changes", true }, ++ { "main_does_not_change", "main_does_not_change", false }, ++ }; ++ struct { ++ const char *func; ++ bool changes; ++ } replacements[] = { ++ { "changes_pkt_data", true }, ++ { "does_not_change_pkt_data", false } ++ }; ++ char buf[64]; ++ ++ for (int i = 0; i < ARRAY_SIZE(mains); ++i) { ++ for (int j = 0; j < ARRAY_SIZE(replacements); ++j) { ++ snprintf(buf, sizeof(buf), "%s_with_%s", ++ mains[i].to_be_replaced, replacements[j].func); ++ if (!test__start_subtest(buf)) ++ continue; ++ test_aux(mains[i].main, mains[i].to_be_replaced, replacements[j].func, ++ mains[i].changes || !replacements[j].changes); ++ } ++ } + } +--- a/tools/testing/selftests/bpf/progs/changes_pkt_data.c ++++ b/tools/testing/selftests/bpf/progs/changes_pkt_data.c +@@ -4,22 +4,35 @@ + #include + + __noinline +-long changes_pkt_data(struct __sk_buff *sk, __u32 len) ++long changes_pkt_data(struct __sk_buff *sk) + { +- return bpf_skb_pull_data(sk, len); ++ return bpf_skb_pull_data(sk, 0); + } + + __noinline __weak +-long does_not_change_pkt_data(struct __sk_buff *sk, __u32 len) ++long does_not_change_pkt_data(struct __sk_buff *sk) + { + return 0; + } + +-SEC("tc") +-int dummy(struct __sk_buff *sk) ++SEC("?tc") ++int main_with_subprogs(struct __sk_buff *sk) ++{ ++ changes_pkt_data(sk); ++ does_not_change_pkt_data(sk); ++ return 0; ++} ++ ++SEC("?tc") ++int main_changes(struct __sk_buff *sk) ++{ ++ bpf_skb_pull_data(sk, 0); ++ return 0; ++} ++ ++SEC("?tc") ++int main_does_not_change(struct __sk_buff *sk) + { +- changes_pkt_data(sk, 0); +- does_not_change_pkt_data(sk, 0); + return 0; + } + +--- a/tools/testing/selftests/bpf/progs/changes_pkt_data_freplace.c ++++ b/tools/testing/selftests/bpf/progs/changes_pkt_data_freplace.c +@@ -4,13 +4,13 @@ + #include + + SEC("?freplace") +-long changes_pkt_data(struct __sk_buff *sk, __u32 len) ++long changes_pkt_data(struct __sk_buff *sk) + { +- return bpf_skb_pull_data(sk, len); ++ return bpf_skb_pull_data(sk, 0); + } + + SEC("?freplace") +-long does_not_change_pkt_data(struct __sk_buff *sk, __u32 len) ++long does_not_change_pkt_data(struct __sk_buff *sk) + { + return 0; + } diff --git a/queue-6.6/selftests-bpf-freplace-tests-for-tracking-of-changes_packet_data.patch b/queue-6.6/selftests-bpf-freplace-tests-for-tracking-of-changes_packet_data.patch new file mode 100644 index 0000000000..2df16774f8 --- /dev/null +++ b/queue-6.6/selftests-bpf-freplace-tests-for-tracking-of-changes_packet_data.patch @@ -0,0 +1,161 @@ +From stable+bounces-139113-greg=kroah.com@vger.kernel.org Wed Apr 30 10:20:36 2025 +From: Shung-Hsi Yu +Date: Wed, 30 Apr 2025 16:19:48 +0800 +Subject: selftests/bpf: freplace tests for tracking of changes_packet_data +To: stable@vger.kernel.org +Cc: Alexei Starovoitov , Eduard Zingerman , Nick Zavaritsky , Dan Carpenter , Shung-Hsi Yu +Message-ID: <20250430081955.49927-7-shung-hsi.yu@suse.com> + +From: Eduard Zingerman + +commit 89ff40890d8f12a7d7e93fb602cc27562f3834f0 upstream. + +Try different combinations of global functions replacement: +- replace function that changes packet data with one that doesn't; +- replace function that changes packet data with one that does; +- replace function that doesn't change packet data with one that does; +- replace function that doesn't change packet data with one that doesn't; + +Signed-off-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20241210041100.1898468-7-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Shung-Hsi Yu +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/bpf/prog_tests/changes_pkt_data.c | 76 ++++++++++ + tools/testing/selftests/bpf/progs/changes_pkt_data.c | 26 +++ + tools/testing/selftests/bpf/progs/changes_pkt_data_freplace.c | 18 ++ + 3 files changed, 120 insertions(+) + create mode 100644 tools/testing/selftests/bpf/prog_tests/changes_pkt_data.c + create mode 100644 tools/testing/selftests/bpf/progs/changes_pkt_data.c + create mode 100644 tools/testing/selftests/bpf/progs/changes_pkt_data_freplace.c + +--- /dev/null ++++ b/tools/testing/selftests/bpf/prog_tests/changes_pkt_data.c +@@ -0,0 +1,76 @@ ++// SPDX-License-Identifier: GPL-2.0 ++#include "bpf/libbpf.h" ++#include "changes_pkt_data_freplace.skel.h" ++#include "changes_pkt_data.skel.h" ++#include ++ ++static void print_verifier_log(const char *log) ++{ ++ if (env.verbosity >= VERBOSE_VERY) ++ fprintf(stdout, "VERIFIER LOG:\n=============\n%s=============\n", log); ++} ++ ++static void test_aux(const char *main_prog_name, const char *freplace_prog_name, bool expect_load) ++{ ++ struct changes_pkt_data_freplace *freplace = NULL; ++ struct bpf_program *freplace_prog = NULL; ++ LIBBPF_OPTS(bpf_object_open_opts, opts); ++ struct changes_pkt_data *main = NULL; ++ char log[16*1024]; ++ int err; ++ ++ opts.kernel_log_buf = log; ++ opts.kernel_log_size = sizeof(log); ++ if (env.verbosity >= VERBOSE_SUPER) ++ opts.kernel_log_level = 1 | 2 | 4; ++ main = changes_pkt_data__open_opts(&opts); ++ if (!ASSERT_OK_PTR(main, "changes_pkt_data__open")) ++ goto out; ++ err = changes_pkt_data__load(main); ++ print_verifier_log(log); ++ if (!ASSERT_OK(err, "changes_pkt_data__load")) ++ goto out; ++ freplace = changes_pkt_data_freplace__open_opts(&opts); ++ if (!ASSERT_OK_PTR(freplace, "changes_pkt_data_freplace__open")) ++ goto out; ++ freplace_prog = bpf_object__find_program_by_name(freplace->obj, freplace_prog_name); ++ if (!ASSERT_OK_PTR(freplace_prog, "freplace_prog")) ++ goto out; ++ bpf_program__set_autoload(freplace_prog, true); ++ bpf_program__set_autoattach(freplace_prog, true); ++ bpf_program__set_attach_target(freplace_prog, ++ bpf_program__fd(main->progs.dummy), ++ main_prog_name); ++ err = changes_pkt_data_freplace__load(freplace); ++ print_verifier_log(log); ++ if (expect_load) { ++ ASSERT_OK(err, "changes_pkt_data_freplace__load"); ++ } else { ++ ASSERT_ERR(err, "changes_pkt_data_freplace__load"); ++ ASSERT_HAS_SUBSTR(log, "Extension program changes packet data", "error log"); ++ } ++ ++out: ++ changes_pkt_data_freplace__destroy(freplace); ++ changes_pkt_data__destroy(main); ++} ++ ++/* There are two global subprograms in both changes_pkt_data.skel.h: ++ * - one changes packet data; ++ * - another does not. ++ * It is ok to freplace subprograms that change packet data with those ++ * that either do or do not. It is only ok to freplace subprograms ++ * that do not change packet data with those that do not as well. ++ * The below tests check outcomes for each combination of such freplace. ++ */ ++void test_changes_pkt_data_freplace(void) ++{ ++ if (test__start_subtest("changes_with_changes")) ++ test_aux("changes_pkt_data", "changes_pkt_data", true); ++ if (test__start_subtest("changes_with_doesnt_change")) ++ test_aux("changes_pkt_data", "does_not_change_pkt_data", true); ++ if (test__start_subtest("doesnt_change_with_changes")) ++ test_aux("does_not_change_pkt_data", "changes_pkt_data", false); ++ if (test__start_subtest("doesnt_change_with_doesnt_change")) ++ test_aux("does_not_change_pkt_data", "does_not_change_pkt_data", true); ++} +--- /dev/null ++++ b/tools/testing/selftests/bpf/progs/changes_pkt_data.c +@@ -0,0 +1,26 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++ ++__noinline ++long changes_pkt_data(struct __sk_buff *sk, __u32 len) ++{ ++ return bpf_skb_pull_data(sk, len); ++} ++ ++__noinline __weak ++long does_not_change_pkt_data(struct __sk_buff *sk, __u32 len) ++{ ++ return 0; ++} ++ ++SEC("tc") ++int dummy(struct __sk_buff *sk) ++{ ++ changes_pkt_data(sk, 0); ++ does_not_change_pkt_data(sk, 0); ++ return 0; ++} ++ ++char _license[] SEC("license") = "GPL"; +--- /dev/null ++++ b/tools/testing/selftests/bpf/progs/changes_pkt_data_freplace.c +@@ -0,0 +1,18 @@ ++// SPDX-License-Identifier: GPL-2.0 ++ ++#include ++#include ++ ++SEC("?freplace") ++long changes_pkt_data(struct __sk_buff *sk, __u32 len) ++{ ++ return bpf_skb_pull_data(sk, len); ++} ++ ++SEC("?freplace") ++long does_not_change_pkt_data(struct __sk_buff *sk, __u32 len) ++{ ++ return 0; ++} ++ ++char _license[] SEC("license") = "GPL"; diff --git a/queue-6.6/selftests-bpf-test-for-changing-packet-data-from-global-functions.patch b/queue-6.6/selftests-bpf-test-for-changing-packet-data-from-global-functions.patch new file mode 100644 index 0000000000..f0989ba202 --- /dev/null +++ b/queue-6.6/selftests-bpf-test-for-changing-packet-data-from-global-functions.patch @@ -0,0 +1,62 @@ +From stable+bounces-139111-greg=kroah.com@vger.kernel.org Wed Apr 30 10:20:26 2025 +From: Shung-Hsi Yu +Date: Wed, 30 Apr 2025 16:19:46 +0800 +Subject: selftests/bpf: test for changing packet data from global functions +To: stable@vger.kernel.org +Cc: Alexei Starovoitov , Eduard Zingerman , Nick Zavaritsky , Dan Carpenter , Shung-Hsi Yu +Message-ID: <20250430081955.49927-5-shung-hsi.yu@suse.com> + +From: Eduard Zingerman + +commit 3f23ee5590d9605dbde9a5e1d4b97637a4803329 upstream. + +Check if verifier is aware of packet pointers invalidation done in +global functions. Based on a test shared by Nick Zavaritsky in [0]. + +[0] https://lore.kernel.org/bpf/0498CA22-5779-4767-9C0C-A9515CEA711F@gmail.com/ + +Suggested-by: Nick Zavaritsky +Signed-off-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20241210041100.1898468-5-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Shung-Hsi Yu +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/bpf/progs/verifier_sock.c | 28 ++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +--- a/tools/testing/selftests/bpf/progs/verifier_sock.c ++++ b/tools/testing/selftests/bpf/progs/verifier_sock.c +@@ -977,4 +977,32 @@ l1_%=: r0 = *(u8*)(r7 + 0); \ + : __clobber_all); + } + ++__noinline ++long skb_pull_data2(struct __sk_buff *sk, __u32 len) ++{ ++ return bpf_skb_pull_data(sk, len); ++} ++ ++__noinline ++long skb_pull_data1(struct __sk_buff *sk, __u32 len) ++{ ++ return skb_pull_data2(sk, len); ++} ++ ++/* global function calls bpf_skb_pull_data(), which invalidates packet ++ * pointers established before global function call. ++ */ ++SEC("tc") ++__failure __msg("invalid mem access") ++int invalidate_pkt_pointers_from_global_func(struct __sk_buff *sk) ++{ ++ int *p = (void *)(long)sk->data; ++ ++ if ((void *)(p + 1) > (void *)(long)sk->data_end) ++ return TCX_DROP; ++ skb_pull_data1(sk, 0); ++ *p = 42; /* this is unsafe */ ++ return TCX_PASS; ++} ++ + char _license[] SEC("license") = "GPL"; diff --git a/queue-6.6/selftests-bpf-validate-that-tail-call-invalidates-packet-pointers.patch b/queue-6.6/selftests-bpf-validate-that-tail-call-invalidates-packet-pointers.patch new file mode 100644 index 0000000000..cc8aab4a4b --- /dev/null +++ b/queue-6.6/selftests-bpf-validate-that-tail-call-invalidates-packet-pointers.patch @@ -0,0 +1,67 @@ +From stable+bounces-139115-greg=kroah.com@vger.kernel.org Wed Apr 30 10:20:40 2025 +From: Shung-Hsi Yu +Date: Wed, 30 Apr 2025 16:19:50 +0800 +Subject: selftests/bpf: validate that tail call invalidates packet pointers +To: stable@vger.kernel.org +Cc: Alexei Starovoitov , Eduard Zingerman , Nick Zavaritsky , Dan Carpenter , Shung-Hsi Yu +Message-ID: <20250430081955.49927-9-shung-hsi.yu@suse.com> + +From: Eduard Zingerman + +commit d9706b56e13b7916461ca6b4b731e169ed44ed09 upstream. + +Add a test case with a tail call done from a global sub-program. Such +tails calls should be considered as invalidating packet pointers. + +Signed-off-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20241210041100.1898468-9-eddyz87@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Shung-Hsi Yu +Signed-off-by: Greg Kroah-Hartman +--- + tools/testing/selftests/bpf/progs/verifier_sock.c | 28 ++++++++++++++++++++++ + 1 file changed, 28 insertions(+) + +--- a/tools/testing/selftests/bpf/progs/verifier_sock.c ++++ b/tools/testing/selftests/bpf/progs/verifier_sock.c +@@ -50,6 +50,13 @@ struct { + __uint(map_flags, BPF_F_NO_PREALLOC); + } sk_storage_map SEC(".maps"); + ++struct { ++ __uint(type, BPF_MAP_TYPE_PROG_ARRAY); ++ __uint(max_entries, 1); ++ __uint(key_size, sizeof(__u32)); ++ __uint(value_size, sizeof(__u32)); ++} jmp_table SEC(".maps"); ++ + SEC("cgroup/skb") + __description("skb->sk: no NULL check") + __failure __msg("invalid mem access 'sock_common_or_null'") +@@ -1004,5 +1011,26 @@ int invalidate_pkt_pointers_from_global_ + *p = 42; /* this is unsafe */ + return TCX_PASS; + } ++ ++__noinline ++int tail_call(struct __sk_buff *sk) ++{ ++ bpf_tail_call_static(sk, &jmp_table, 0); ++ return 0; ++} ++ ++/* Tail calls invalidate packet pointers. */ ++SEC("tc") ++__failure __msg("invalid mem access") ++int invalidate_pkt_pointers_by_tail_call(struct __sk_buff *sk) ++{ ++ int *p = (void *)(long)sk->data; ++ ++ if ((void *)(p + 1) > (void *)(long)sk->data_end) ++ return TCX_DROP; ++ tail_call(sk); ++ *p = 42; /* this is unsafe */ ++ return TCX_PASS; ++} + + char _license[] SEC("license") = "GPL"; diff --git a/queue-6.6/series b/queue-6.6/series index 405d9bcdbe..86622cd627 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -30,3 +30,17 @@ smb-client-fix-zero-length-for-mkdir-posix-create-context.patch cpufreq-avoid-using-inconsistent-policy-min-and-policy-max.patch cpufreq-fix-setting-policy-limits-when-frequency-tables-are-used.patch tracing-fix-oob-write-in-trace_seq_to_buffer.patch +bpf-add-find_containing_subprog-utility-function.patch +bpf-refactor-bpf_helper_changes_pkt_data-to-use-helper-number.patch +bpf-track-changes_pkt_data-property-for-global-functions.patch +selftests-bpf-test-for-changing-packet-data-from-global-functions.patch +bpf-check-changes_pkt_data-property-for-extension-programs.patch +selftests-bpf-freplace-tests-for-tracking-of-changes_packet_data.patch +bpf-consider-that-tail-calls-invalidate-packet-pointers.patch +selftests-bpf-validate-that-tail-call-invalidates-packet-pointers.patch +bpf-fix-null-dereference-when-computing-changes_pkt_data-of-prog-w-o-subprogs.patch +selftests-bpf-extend-changes_pkt_data-with-cases-w-o-subprograms.patch +revert-pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch +pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch +kvm-x86-load-dr6-with-guest-value-only-before-entering-.vcpu_run-loop.patch +iommu-handle-race-with-default-domain-setup.patch -- 2.47.3