]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.6-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 5 May 2025 09:30:14 +0000 (11:30 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 5 May 2025 09:30:14 +0000 (11:30 +0200)
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

15 files changed:
queue-6.6/bpf-add-find_containing_subprog-utility-function.patch [new file with mode: 0644]
queue-6.6/bpf-check-changes_pkt_data-property-for-extension-programs.patch [new file with mode: 0644]
queue-6.6/bpf-consider-that-tail-calls-invalidate-packet-pointers.patch [new file with mode: 0644]
queue-6.6/bpf-fix-null-dereference-when-computing-changes_pkt_data-of-prog-w-o-subprogs.patch [new file with mode: 0644]
queue-6.6/bpf-refactor-bpf_helper_changes_pkt_data-to-use-helper-number.patch [new file with mode: 0644]
queue-6.6/bpf-track-changes_pkt_data-property-for-global-functions.patch [new file with mode: 0644]
queue-6.6/iommu-handle-race-with-default-domain-setup.patch [new file with mode: 0644]
queue-6.6/kvm-x86-load-dr6-with-guest-value-only-before-entering-.vcpu_run-loop.patch [new file with mode: 0644]
queue-6.6/pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch [new file with mode: 0644]
queue-6.6/revert-pci-imx6-skip-controller_id-generation-logic-for-i.mx7d.patch [new file with mode: 0644]
queue-6.6/selftests-bpf-extend-changes_pkt_data-with-cases-w-o-subprograms.patch [new file with mode: 0644]
queue-6.6/selftests-bpf-freplace-tests-for-tracking-of-changes_packet_data.patch [new file with mode: 0644]
queue-6.6/selftests-bpf-test-for-changing-packet-data-from-global-functions.patch [new file with mode: 0644]
queue-6.6/selftests-bpf-validate-that-tail-call-invalidates-packet-pointers.patch [new file with mode: 0644]
queue-6.6/series

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 (file)
index 0000000..8d12aca
--- /dev/null
@@ -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 <shung-hsi.yu@suse.com>
+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 <ast@kernel.org>, Eduard Zingerman <eddyz87@gmail.com>, Nick Zavaritsky <mejedi@gmail.com>, Dan Carpenter <dan.carpenter@linaro.org>, Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Message-ID: <20250430081955.49927-2-shung-hsi.yu@suse.com>
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+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 <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20241210041100.1898468-2-eddyz87@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..9608715
--- /dev/null
@@ -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 <shung-hsi.yu@suse.com>
+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 <ast@kernel.org>, Eduard Zingerman <eddyz87@gmail.com>, Nick Zavaritsky <mejedi@gmail.com>, Dan Carpenter <dan.carpenter@linaro.org>, Shung-Hsi Yu <shung-hsi.yu@suse.com>, Alexei Starovoitov <alexei.starovoitov@gmail.com>
+Message-ID: <20250430081955.49927-6-shung-hsi.yu@suse.com>
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+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 <alexei.starovoitov@gmail.com>
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20241210041100.1898468-6-eddyz87@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+[ 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 <shung-hsi.yu@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..f6dbb48
--- /dev/null
@@ -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 <shung-hsi.yu@suse.com>
+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 <ast@kernel.org>, Eduard Zingerman <eddyz87@gmail.com>, Nick Zavaritsky <mejedi@gmail.com>, Dan Carpenter <dan.carpenter@linaro.org>, Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Message-ID: <20250430081955.49927-8-shung-hsi.yu@suse.com>
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+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 <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20241210041100.1898468-8-eddyz87@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+[ 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 <shung-hsi.yu@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..000a032
--- /dev/null
@@ -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 <shung-hsi.yu@suse.com>
+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 <ast@kernel.org>, Eduard Zingerman <eddyz87@gmail.com>, Nick Zavaritsky <mejedi@gmail.com>, Dan Carpenter <dan.carpenter@linaro.org>, Shung-Hsi Yu <shung-hsi.yu@suse.com>, kernel test robot <lkp@intel.com>
+Message-ID: <20250430081955.49927-10-shung-hsi.yu@suse.com>
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+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 <lkp@intel.com>
+Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
+Closes: https://lore.kernel.org/r/202412111822.qGw6tOyB-lkp@intel.com/
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20241212070711.427443-1-eddyz87@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..2abc143
--- /dev/null
@@ -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 <shung-hsi.yu@suse.com>
+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 <ast@kernel.org>, Eduard Zingerman <eddyz87@gmail.com>, Nick Zavaritsky <mejedi@gmail.com>, Dan Carpenter <dan.carpenter@linaro.org>, Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Message-ID: <20250430081955.49927-3-shung-hsi.yu@suse.com>
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+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 <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20241210041100.1898468-3-eddyz87@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..2daa340
--- /dev/null
@@ -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 <shung-hsi.yu@suse.com>
+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 <ast@kernel.org>, Eduard Zingerman <eddyz87@gmail.com>, Nick Zavaritsky <mejedi@gmail.com>, Dan Carpenter <dan.carpenter@linaro.org>, Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Message-ID: <20250430081955.49927-4-shung-hsi.yu@suse.com>
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+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 <mejedi@gmail.com>
+Closes: https://lore.kernel.org/bpf/0498CA22-5779-4767-9C0C-A9515CEA711F@gmail.com/
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20241210041100.1898468-4-eddyz87@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+[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 <shung-hsi.yu@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..93110be
--- /dev/null
@@ -0,0 +1,73 @@
+From b46064a18810bad3aea089a79993ca5ea7a3d2b2 Mon Sep 17 00:00:00 2001
+From: Robin Murphy <robin.murphy@arm.com>
+Date: Fri, 28 Feb 2025 15:46:30 +0000
+Subject: iommu: Handle race with default domain setup
+
+From: Robin Murphy <robin.murphy@arm.com>
+
+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 <quic_charante@quicinc.com>
+Fixes: 98ac73f99bc4 ("iommu: Require a default_domain for all iommu drivers")
+Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+Link: https://lore.kernel.org/r/e88b94c9b575034a2c98a48b3d383654cbda7902.1740753261.git.robin.murphy@arm.com
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Robin Murphy <robin.murphy@arm.com>
+---
+ 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 (file)
index 0000000..9967d2f
--- /dev/null
@@ -0,0 +1,228 @@
+From c2fee09fc167c74a64adb08656cb993ea475197e Mon Sep 17 00:00:00 2001
+From: Sean Christopherson <seanjc@google.com>
+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 <seanjc@google.com>
+
+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:
+    ==========
+    <L1 disables DR interception>
+           CPU 0/KVM-7289    [023] d....  2925.640961: kvm_entry: vcpu 0
+ A:  L1 Writes DR6
+           CPU 0/KVM-7289    [023] d....  2925.640963: <hack>: 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: <hack>: 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: <hack>: 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: <hack>: 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: <hack>: Set DRs, DR6 = 0xffff0ff0
+
+ A: <L1 writes DR6 = 1, no interception, arch.dr6 is still '0'>
+
+ 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: <hack>: 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 <jstultz@google.com>
+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 <jmattson@google.com>
+Tested-by: John Stultz <jstultz@google.com>
+Link: https://lore.kernel.org/r/20250125011833.3644371-1-seanjc@google.com
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+[jth: Handled conflicts with kvm_x86_ops reshuffle]
+Signed-off-by: James Houghton <jthoughton@google.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..bcf6274
--- /dev/null
@@ -0,0 +1,47 @@
+From stable+bounces-139573-greg=kroah.com@vger.kernel.org Sun May  4 21:15:49 2025
+From: Ryan Matthews <ryanmatthews@fastmail.com>
+Date: Sun,  4 May 2025 15:13:56 -0400
+Subject: PCI: imx6: Skip controller_id generation logic for i.MX7D
+To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Cc: "Richard Zhu" <hongxing.zhu@nxp.com>, "Lucas Stach" <l.stach@pengutronix.de>, stable@vger.kernel.org, linux-pci@vger.kernel.org, "Ryan Matthews" <ryanmatthews@fastmail.com>, "Krzysztof WilczyÅ„ski" <kwilczynski@kernel.org>, "Bjorn Helgaas" <bhelgaas@google.com>, "Manivannan Sadhasivam" <manivannan.sadhasivam@linaro.org>, "Frank Li" <Frank.Li@nxp.com>
+Message-ID: <20250504191356.17732-3-ryanmatthews@fastmail.com>
+
+From: Richard Zhu <hongxing.zhu@nxp.com>
+
+[ 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 <hongxing.zhu@nxp.com>
+Signed-off-by: Krzysztof WilczyÅ„ski <kwilczynski@kernel.org>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Reviewed-by: Frank Li <Frank.Li@nxp.com>
+[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 <ryanmatthews@fastmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..26c94bf
--- /dev/null
@@ -0,0 +1,41 @@
+From stable+bounces-139572-greg=kroah.com@vger.kernel.org Sun May  4 21:15:30 2025
+From: Ryan Matthews <ryanmatthews@fastmail.com>
+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 <gregkh@linuxfoundation.org>
+Cc: Richard Zhu <hongxing.zhu@nxp.com>, Lucas Stach <l.stach@pengutronix.de>, stable@vger.kernel.org, linux-pci@vger.kernel.org, Ryan Matthews <ryanmatthews@fastmail.com>
+Message-ID: <20250504191356.17732-2-ryanmatthews@fastmail.com>
+
+From: Ryan Matthews <ryanmatthews@fastmail.com>
+
+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 <ryanmatthews@fastmail.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..7ef4430
--- /dev/null
@@ -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 <shung-hsi.yu@suse.com>
+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 <ast@kernel.org>, Eduard Zingerman <eddyz87@gmail.com>, Nick Zavaritsky <mejedi@gmail.com>, Dan Carpenter <dan.carpenter@linaro.org>, Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Message-ID: <20250430081955.49927-11-shung-hsi.yu@suse.com>
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+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 <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20241212070711.427443-2-eddyz87@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 <bpf/bpf_helpers.h>
+ __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 <bpf/bpf_helpers.h>
+ 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 (file)
index 0000000..2df1677
--- /dev/null
@@ -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 <shung-hsi.yu@suse.com>
+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 <ast@kernel.org>, Eduard Zingerman <eddyz87@gmail.com>, Nick Zavaritsky <mejedi@gmail.com>, Dan Carpenter <dan.carpenter@linaro.org>, Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Message-ID: <20250430081955.49927-7-shung-hsi.yu@suse.com>
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+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 <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20241210041100.1898468-7-eddyz87@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 <test_progs.h>
++
++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 <linux/bpf.h>
++#include <bpf/bpf_helpers.h>
++
++__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 <linux/bpf.h>
++#include <bpf/bpf_helpers.h>
++
++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 (file)
index 0000000..f0989ba
--- /dev/null
@@ -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 <shung-hsi.yu@suse.com>
+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 <ast@kernel.org>, Eduard Zingerman <eddyz87@gmail.com>, Nick Zavaritsky <mejedi@gmail.com>, Dan Carpenter <dan.carpenter@linaro.org>, Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Message-ID: <20250430081955.49927-5-shung-hsi.yu@suse.com>
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+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 <mejedi@gmail.com>
+Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20241210041100.1898468-5-eddyz87@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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 (file)
index 0000000..cc8aab4
--- /dev/null
@@ -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 <shung-hsi.yu@suse.com>
+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 <ast@kernel.org>, Eduard Zingerman <eddyz87@gmail.com>, Nick Zavaritsky <mejedi@gmail.com>, Dan Carpenter <dan.carpenter@linaro.org>, Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Message-ID: <20250430081955.49927-9-shung-hsi.yu@suse.com>
+
+From: Eduard Zingerman <eddyz87@gmail.com>
+
+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 <eddyz87@gmail.com>
+Link: https://lore.kernel.org/r/20241210041100.1898468-9-eddyz87@gmail.com
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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";
index 405d9bcdbe959e1ed88e0dd57daf4c8ff4b75d85..86622cd627a08c93062cfcb7667237a0af7bb60e 100644 (file)
@@ -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