]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.6
authorSasha Levin <sashal@kernel.org>
Sat, 26 Oct 2024 07:36:44 +0000 (03:36 -0400)
committerSasha Levin <sashal@kernel.org>
Sat, 26 Oct 2024 07:36:44 +0000 (03:36 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
34 files changed:
queue-6.6/be2net-fix-potential-memory-leak-in-be_xmit.patch [new file with mode: 0644]
queue-6.6/bluetooth-iso-fix-uaf-on-iso_sock_timeout.patch [new file with mode: 0644]
queue-6.6/bluetooth-sco-fix-uaf-on-sco_sock_timeout.patch [new file with mode: 0644]
queue-6.6/bpf-add-mem_write-attribute.patch [new file with mode: 0644]
queue-6.6/bpf-fix-overloading-of-mem_uninit-s-meaning.patch [new file with mode: 0644]
queue-6.6/bpf-perf-fix-perf_event_detach_bpf_prog-error-handli.patch [new file with mode: 0644]
queue-6.6/bpf-remove-mem_uninit-from-skb-xdp-mtu-helpers.patch [new file with mode: 0644]
queue-6.6/bpf-simplify-checking-size-of-helper-accesses.patch [new file with mode: 0644]
queue-6.6/fsl-fman-fix-refcount-handling-of-fman-related-devic.patch [new file with mode: 0644]
queue-6.6/fsl-fman-save-device-references-taken-in-mac_probe.patch [new file with mode: 0644]
queue-6.6/net-dsa-mv88e6xxx-fix-error-when-setting-port-policy.patch [new file with mode: 0644]
queue-6.6/net-dsa-mv88e6xxx-group-cycle-counter-coefficients.patch [new file with mode: 0644]
queue-6.6/net-dsa-mv88e6xxx-read-cycle-counter-period-from-har.patch [new file with mode: 0644]
queue-6.6/net-dsa-mv88e6xxx-support-4000ps-cycle-counter-perio.patch [new file with mode: 0644]
queue-6.6/net-fix-races-in-netdev_tx_sent_queue-dev_watchdog.patch [new file with mode: 0644]
queue-6.6/net-plip-fix-break-causing-plip-to-never-transmit.patch [new file with mode: 0644]
queue-6.6/net-sched-act_api-deny-mismatched-skip_sw-skip_hw-fl.patch [new file with mode: 0644]
queue-6.6/net-sched-adjust-device-watchdog-timer-to-detect-sto.patch [new file with mode: 0644]
queue-6.6/net-sched-fix-use-after-free-in-taprio_change.patch [new file with mode: 0644]
queue-6.6/net-sched-use-rcu-read-side-critical-section-in-tapr.patch [new file with mode: 0644]
queue-6.6/net-sun3_82586-fix-potential-memory-leak-in-sun3_825.patch [new file with mode: 0644]
queue-6.6/net-usb-usbnet-fix-name-regression.patch [new file with mode: 0644]
queue-6.6/net-wwan-fix-global-oob-in-wwan_rtnl_policy.patch [new file with mode: 0644]
queue-6.6/netfilter-bpf-must-hold-reference-on-net-namespace.patch [new file with mode: 0644]
queue-6.6/netfilter-xtables-fix-typo-causing-some-targets-not-.patch [new file with mode: 0644]
queue-6.6/octeon_ep-add-skb-allocation-failures-handling-in-__.patch [new file with mode: 0644]
queue-6.6/octeon_ep-implement-helper-for-iterating-packets-in-.patch [new file with mode: 0644]
queue-6.6/posix-clock-posix-clock-fix-unbalanced-locking-in-pc.patch [new file with mode: 0644]
queue-6.6/r8169-avoid-unsolicited-interrupts.patch [new file with mode: 0644]
queue-6.6/series
queue-6.6/xfrm-add-direction-to-the-sa-in-or-out.patch [new file with mode: 0644]
queue-6.6/xfrm-extract-dst-lookup-parameters-into-a-struct.patch [new file with mode: 0644]
queue-6.6/xfrm-respect-ip-protocols-rules-criteria-when-perfor.patch [new file with mode: 0644]
queue-6.6/xfrm-validate-new-sa-s-prefixlen-using-sa-family-whe.patch [new file with mode: 0644]

diff --git a/queue-6.6/be2net-fix-potential-memory-leak-in-be_xmit.patch b/queue-6.6/be2net-fix-potential-memory-leak-in-be_xmit.patch
new file mode 100644 (file)
index 0000000..138ecc1
--- /dev/null
@@ -0,0 +1,61 @@
+From 29e3f2182eee5e8f83a48ace97f9e653385eee7f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Oct 2024 22:48:02 +0800
+Subject: be2net: fix potential memory leak in be_xmit()
+
+From: Wang Hai <wanghai38@huawei.com>
+
+[ Upstream commit e4dd8bfe0f6a23acd305f9b892c00899089bd621 ]
+
+The be_xmit() returns NETDEV_TX_OK without freeing skb
+in case of be_xmit_enqueue() fails, add dev_kfree_skb_any() to fix it.
+
+Fixes: 760c295e0e8d ("be2net: Support for OS2BMC.")
+Signed-off-by: Wang Hai <wanghai38@huawei.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
+Message-ID: <20241015144802.12150-1-wanghai38@huawei.com>
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/emulex/benet/be_main.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
+index ad862ed7888ac..9d425ece33fd2 100644
+--- a/drivers/net/ethernet/emulex/benet/be_main.c
++++ b/drivers/net/ethernet/emulex/benet/be_main.c
+@@ -1381,10 +1381,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev)
+       be_get_wrb_params_from_skb(adapter, skb, &wrb_params);
+       wrb_cnt = be_xmit_enqueue(adapter, txo, skb, &wrb_params);
+-      if (unlikely(!wrb_cnt)) {
+-              dev_kfree_skb_any(skb);
+-              goto drop;
+-      }
++      if (unlikely(!wrb_cnt))
++              goto drop_skb;
+       /* if os2bmc is enabled and if the pkt is destined to bmc,
+        * enqueue the pkt a 2nd time with mgmt bit set.
+@@ -1393,7 +1391,7 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev)
+               BE_WRB_F_SET(wrb_params.features, OS2BMC, 1);
+               wrb_cnt = be_xmit_enqueue(adapter, txo, skb, &wrb_params);
+               if (unlikely(!wrb_cnt))
+-                      goto drop;
++                      goto drop_skb;
+               else
+                       skb_get(skb);
+       }
+@@ -1407,6 +1405,8 @@ static netdev_tx_t be_xmit(struct sk_buff *skb, struct net_device *netdev)
+               be_xmit_flush(adapter, txo);
+       return NETDEV_TX_OK;
++drop_skb:
++      dev_kfree_skb_any(skb);
+ drop:
+       tx_stats(txo)->tx_drv_drops++;
+       /* Flush the already enqueued tx requests */
+-- 
+2.43.0
+
diff --git a/queue-6.6/bluetooth-iso-fix-uaf-on-iso_sock_timeout.patch b/queue-6.6/bluetooth-iso-fix-uaf-on-iso_sock_timeout.patch
new file mode 100644 (file)
index 0000000..38ccb32
--- /dev/null
@@ -0,0 +1,66 @@
+From 3010c1aeb000dbbb53aa645e3b55921f471059fa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Oct 2024 15:35:49 -0400
+Subject: Bluetooth: ISO: Fix UAF on iso_sock_timeout
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 246b435ad668596aa0e2bbb9d491b6413861211a ]
+
+conn->sk maybe have been unlinked/freed while waiting for iso_conn_lock
+so this checks if the conn->sk is still valid by checking if it part of
+iso_sk_list.
+
+Fixes: ccf74f2390d6 ("Bluetooth: Add BTPROTO_ISO socket type")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/iso.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
+index 9b365fb44fac6..c2c80d6000836 100644
+--- a/net/bluetooth/iso.c
++++ b/net/bluetooth/iso.c
+@@ -90,6 +90,16 @@ static struct sock *iso_get_sock_listen(bdaddr_t *src, bdaddr_t *dst,
+ #define ISO_CONN_TIMEOUT      (HZ * 40)
+ #define ISO_DISCONN_TIMEOUT   (HZ * 2)
++static struct sock *iso_sock_hold(struct iso_conn *conn)
++{
++      if (!conn || !bt_sock_linked(&iso_sk_list, conn->sk))
++              return NULL;
++
++      sock_hold(conn->sk);
++
++      return conn->sk;
++}
++
+ static void iso_sock_timeout(struct work_struct *work)
+ {
+       struct iso_conn *conn = container_of(work, struct iso_conn,
+@@ -97,9 +107,7 @@ static void iso_sock_timeout(struct work_struct *work)
+       struct sock *sk;
+       iso_conn_lock(conn);
+-      sk = conn->sk;
+-      if (sk)
+-              sock_hold(sk);
++      sk = iso_sock_hold(conn);
+       iso_conn_unlock(conn);
+       if (!sk)
+@@ -217,9 +225,7 @@ static void iso_conn_del(struct hci_conn *hcon, int err)
+       /* Kill socket */
+       iso_conn_lock(conn);
+-      sk = conn->sk;
+-      if (sk)
+-              sock_hold(sk);
++      sk = iso_sock_hold(conn);
+       iso_conn_unlock(conn);
+       if (sk) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/bluetooth-sco-fix-uaf-on-sco_sock_timeout.patch b/queue-6.6/bluetooth-sco-fix-uaf-on-sco_sock_timeout.patch
new file mode 100644 (file)
index 0000000..84213bd
--- /dev/null
@@ -0,0 +1,116 @@
+From d7b65cca11ddf5483851933808cfd119d0cb4a97 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 22 Oct 2024 12:31:08 -0400
+Subject: Bluetooth: SCO: Fix UAF on sco_sock_timeout
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 1bf4470a3939c678fb822073e9ea77a0560bc6bb ]
+
+conn->sk maybe have been unlinked/freed while waiting for sco_conn_lock
+so this checks if the conn->sk is still valid by checking if it part of
+sco_sk_list.
+
+Reported-by: syzbot+4c0d0c4cde787116d465@syzkaller.appspotmail.com
+Tested-by: syzbot+4c0d0c4cde787116d465@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=4c0d0c4cde787116d465
+Fixes: ba316be1b6a0 ("Bluetooth: schedule SCO timeouts with delayed_work")
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/bluetooth/bluetooth.h |  1 +
+ net/bluetooth/af_bluetooth.c      | 22 ++++++++++++++++++++++
+ net/bluetooth/sco.c               | 18 ++++++++++++------
+ 3 files changed, 35 insertions(+), 6 deletions(-)
+
+diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
+index e4a6831133f81..4763a47bf8c8a 100644
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -403,6 +403,7 @@ int  bt_sock_register(int proto, const struct net_proto_family *ops);
+ void bt_sock_unregister(int proto);
+ void bt_sock_link(struct bt_sock_list *l, struct sock *s);
+ void bt_sock_unlink(struct bt_sock_list *l, struct sock *s);
++bool bt_sock_linked(struct bt_sock_list *l, struct sock *s);
+ struct sock *bt_sock_alloc(struct net *net, struct socket *sock,
+                          struct proto *prot, int proto, gfp_t prio, int kern);
+ int  bt_sock_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
+diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
+index e39fba5565c5d..0b4d0a8bd3614 100644
+--- a/net/bluetooth/af_bluetooth.c
++++ b/net/bluetooth/af_bluetooth.c
+@@ -185,6 +185,28 @@ void bt_sock_unlink(struct bt_sock_list *l, struct sock *sk)
+ }
+ EXPORT_SYMBOL(bt_sock_unlink);
++bool bt_sock_linked(struct bt_sock_list *l, struct sock *s)
++{
++      struct sock *sk;
++
++      if (!l || !s)
++              return false;
++
++      read_lock(&l->lock);
++
++      sk_for_each(sk, &l->head) {
++              if (s == sk) {
++                      read_unlock(&l->lock);
++                      return true;
++              }
++      }
++
++      read_unlock(&l->lock);
++
++      return false;
++}
++EXPORT_SYMBOL(bt_sock_linked);
++
+ void bt_accept_enqueue(struct sock *parent, struct sock *sk, bool bh)
+ {
+       const struct cred *old_cred;
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index 3c3650902c839..fb368540139a1 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -76,6 +76,16 @@ struct sco_pinfo {
+ #define SCO_CONN_TIMEOUT      (HZ * 40)
+ #define SCO_DISCONN_TIMEOUT   (HZ * 2)
++static struct sock *sco_sock_hold(struct sco_conn *conn)
++{
++      if (!conn || !bt_sock_linked(&sco_sk_list, conn->sk))
++              return NULL;
++
++      sock_hold(conn->sk);
++
++      return conn->sk;
++}
++
+ static void sco_sock_timeout(struct work_struct *work)
+ {
+       struct sco_conn *conn = container_of(work, struct sco_conn,
+@@ -87,9 +97,7 @@ static void sco_sock_timeout(struct work_struct *work)
+               sco_conn_unlock(conn);
+               return;
+       }
+-      sk = conn->sk;
+-      if (sk)
+-              sock_hold(sk);
++      sk = sco_sock_hold(conn);
+       sco_conn_unlock(conn);
+       if (!sk)
+@@ -194,9 +202,7 @@ static void sco_conn_del(struct hci_conn *hcon, int err)
+       /* Kill socket */
+       sco_conn_lock(conn);
+-      sk = conn->sk;
+-      if (sk)
+-              sock_hold(sk);
++      sk = sco_sock_hold(conn);
+       sco_conn_unlock(conn);
+       if (sk) {
+-- 
+2.43.0
+
diff --git a/queue-6.6/bpf-add-mem_write-attribute.patch b/queue-6.6/bpf-add-mem_write-attribute.patch
new file mode 100644 (file)
index 0000000..c9351f0
--- /dev/null
@@ -0,0 +1,197 @@
+From 80df920c353fe2a5b9de0d5509b1ac4b7276bcae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Oct 2024 17:28:05 +0200
+Subject: bpf: Add MEM_WRITE attribute
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+[ Upstream commit 6fad274f06f038c29660aa53fbad14241c9fd976 ]
+
+Add a MEM_WRITE attribute for BPF helper functions which can be used in
+bpf_func_proto to annotate an argument type in order to let the verifier
+know that the helper writes into the memory passed as an argument. In
+the past MEM_UNINIT has been (ab)used for this function, but the latter
+merely tells the verifier that the passed memory can be uninitialized.
+
+There have been bugs with overloading the latter but aside from that
+there are also cases where the passed memory is read + written which
+currently cannot be expressed, see also 4b3786a6c539 ("bpf: Zero former
+ARG_PTR_TO_{LONG,INT} args in case of error").
+
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Link: https://lore.kernel.org/r/20241021152809.33343-1-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Stable-dep-of: 8ea607330a39 ("bpf: Fix overloading of MEM_UNINIT's meaning")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/bpf.h      | 14 +++++++++++---
+ kernel/bpf/helpers.c     | 10 +++++-----
+ kernel/bpf/ringbuf.c     |  2 +-
+ kernel/bpf/syscall.c     |  2 +-
+ kernel/trace/bpf_trace.c |  4 ++--
+ net/core/filter.c        |  4 ++--
+ 6 files changed, 22 insertions(+), 14 deletions(-)
+
+diff --git a/include/linux/bpf.h b/include/linux/bpf.h
+index 1e05cc80e0485..5a27fd533fabc 100644
+--- a/include/linux/bpf.h
++++ b/include/linux/bpf.h
+@@ -616,6 +616,7 @@ enum bpf_type_flag {
+        */
+       PTR_UNTRUSTED           = BIT(6 + BPF_BASE_TYPE_BITS),
++      /* MEM can be uninitialized. */
+       MEM_UNINIT              = BIT(7 + BPF_BASE_TYPE_BITS),
+       /* DYNPTR points to memory local to the bpf program. */
+@@ -681,6 +682,13 @@ enum bpf_type_flag {
+        */
+       MEM_ALIGNED             = BIT(17 + BPF_BASE_TYPE_BITS),
++      /* MEM is being written to, often combined with MEM_UNINIT. Non-presence
++       * of MEM_WRITE means that MEM is only being read. MEM_WRITE without the
++       * MEM_UNINIT means that memory needs to be initialized since it is also
++       * read.
++       */
++      MEM_WRITE               = BIT(18 + BPF_BASE_TYPE_BITS),
++
+       __BPF_TYPE_FLAG_MAX,
+       __BPF_TYPE_LAST_FLAG    = __BPF_TYPE_FLAG_MAX - 1,
+ };
+@@ -738,10 +746,10 @@ enum bpf_arg_type {
+       ARG_PTR_TO_SOCKET_OR_NULL       = PTR_MAYBE_NULL | ARG_PTR_TO_SOCKET,
+       ARG_PTR_TO_STACK_OR_NULL        = PTR_MAYBE_NULL | ARG_PTR_TO_STACK,
+       ARG_PTR_TO_BTF_ID_OR_NULL       = PTR_MAYBE_NULL | ARG_PTR_TO_BTF_ID,
+-      /* pointer to memory does not need to be initialized, helper function must fill
+-       * all bytes or clear them in error case.
++      /* Pointer to memory does not need to be initialized, since helper function
++       * fills all bytes or clears them in error case.
+        */
+-      ARG_PTR_TO_UNINIT_MEM           = MEM_UNINIT | ARG_PTR_TO_MEM,
++      ARG_PTR_TO_UNINIT_MEM           = MEM_UNINIT | MEM_WRITE | ARG_PTR_TO_MEM,
+       /* Pointer to valid memory of size known at compile time. */
+       ARG_PTR_TO_FIXED_SIZE_MEM       = MEM_FIXED_SIZE | ARG_PTR_TO_MEM,
+diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
+index 3dba5bb294d8e..41d62405c8521 100644
+--- a/kernel/bpf/helpers.c
++++ b/kernel/bpf/helpers.c
+@@ -110,7 +110,7 @@ const struct bpf_func_proto bpf_map_pop_elem_proto = {
+       .gpl_only       = false,
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_CONST_MAP_PTR,
+-      .arg2_type      = ARG_PTR_TO_MAP_VALUE | MEM_UNINIT,
++      .arg2_type      = ARG_PTR_TO_MAP_VALUE | MEM_UNINIT | MEM_WRITE,
+ };
+ BPF_CALL_2(bpf_map_peek_elem, struct bpf_map *, map, void *, value)
+@@ -123,7 +123,7 @@ const struct bpf_func_proto bpf_map_peek_elem_proto = {
+       .gpl_only       = false,
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_CONST_MAP_PTR,
+-      .arg2_type      = ARG_PTR_TO_MAP_VALUE | MEM_UNINIT,
++      .arg2_type      = ARG_PTR_TO_MAP_VALUE | MEM_UNINIT | MEM_WRITE,
+ };
+ BPF_CALL_3(bpf_map_lookup_percpu_elem, struct bpf_map *, map, void *, key, u32, cpu)
+@@ -538,7 +538,7 @@ const struct bpf_func_proto bpf_strtol_proto = {
+       .arg1_type      = ARG_PTR_TO_MEM | MEM_RDONLY,
+       .arg2_type      = ARG_CONST_SIZE,
+       .arg3_type      = ARG_ANYTHING,
+-      .arg4_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED,
++      .arg4_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED,
+       .arg4_size      = sizeof(s64),
+ };
+@@ -568,7 +568,7 @@ const struct bpf_func_proto bpf_strtoul_proto = {
+       .arg1_type      = ARG_PTR_TO_MEM | MEM_RDONLY,
+       .arg2_type      = ARG_CONST_SIZE,
+       .arg3_type      = ARG_ANYTHING,
+-      .arg4_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED,
++      .arg4_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED,
+       .arg4_size      = sizeof(u64),
+ };
+@@ -1607,7 +1607,7 @@ static const struct bpf_func_proto bpf_dynptr_from_mem_proto = {
+       .arg1_type      = ARG_PTR_TO_UNINIT_MEM,
+       .arg2_type      = ARG_CONST_SIZE_OR_ZERO,
+       .arg3_type      = ARG_ANYTHING,
+-      .arg4_type      = ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_LOCAL | MEM_UNINIT,
++      .arg4_type      = ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_LOCAL | MEM_UNINIT | MEM_WRITE,
+ };
+ BPF_CALL_5(bpf_dynptr_read, void *, dst, u32, len, const struct bpf_dynptr_kern *, src,
+diff --git a/kernel/bpf/ringbuf.c b/kernel/bpf/ringbuf.c
+index 238d9b206bbde..246559c3e93d0 100644
+--- a/kernel/bpf/ringbuf.c
++++ b/kernel/bpf/ringbuf.c
+@@ -632,7 +632,7 @@ const struct bpf_func_proto bpf_ringbuf_reserve_dynptr_proto = {
+       .arg1_type      = ARG_CONST_MAP_PTR,
+       .arg2_type      = ARG_ANYTHING,
+       .arg3_type      = ARG_ANYTHING,
+-      .arg4_type      = ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_RINGBUF | MEM_UNINIT,
++      .arg4_type      = ARG_PTR_TO_DYNPTR | DYNPTR_TYPE_RINGBUF | MEM_UNINIT | MEM_WRITE,
+ };
+ BPF_CALL_2(bpf_ringbuf_submit_dynptr, struct bpf_dynptr_kern *, ptr, u64, flags)
+diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
+index b43302c80cac5..8a1cadc1ff9dd 100644
+--- a/kernel/bpf/syscall.c
++++ b/kernel/bpf/syscall.c
+@@ -5689,7 +5689,7 @@ static const struct bpf_func_proto bpf_kallsyms_lookup_name_proto = {
+       .arg1_type      = ARG_PTR_TO_MEM,
+       .arg2_type      = ARG_CONST_SIZE_OR_ZERO,
+       .arg3_type      = ARG_ANYTHING,
+-      .arg4_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED,
++      .arg4_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED,
+       .arg4_size      = sizeof(u64),
+ };
+diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
+index bbdc4199748bd..ecc86a595b754 100644
+--- a/kernel/trace/bpf_trace.c
++++ b/kernel/trace/bpf_trace.c
+@@ -1220,7 +1220,7 @@ static const struct bpf_func_proto bpf_get_func_arg_proto = {
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_PTR_TO_CTX,
+       .arg2_type      = ARG_ANYTHING,
+-      .arg3_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED,
++      .arg3_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED,
+       .arg3_size      = sizeof(u64),
+ };
+@@ -1237,7 +1237,7 @@ static const struct bpf_func_proto bpf_get_func_ret_proto = {
+       .func           = get_func_ret,
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_PTR_TO_CTX,
+-      .arg2_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED,
++      .arg2_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED,
+       .arg2_size      = sizeof(u64),
+ };
+diff --git a/net/core/filter.c b/net/core/filter.c
+index bbb1432488430..a7d928345b1f4 100644
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -6310,7 +6310,7 @@ static const struct bpf_func_proto bpf_skb_check_mtu_proto = {
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_PTR_TO_CTX,
+       .arg2_type      = ARG_ANYTHING,
+-      .arg3_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED,
++      .arg3_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED,
+       .arg3_size      = sizeof(u32),
+       .arg4_type      = ARG_ANYTHING,
+       .arg5_type      = ARG_ANYTHING,
+@@ -6322,7 +6322,7 @@ static const struct bpf_func_proto bpf_xdp_check_mtu_proto = {
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_PTR_TO_CTX,
+       .arg2_type      = ARG_ANYTHING,
+-      .arg3_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_ALIGNED,
++      .arg3_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED,
+       .arg3_size      = sizeof(u32),
+       .arg4_type      = ARG_ANYTHING,
+       .arg5_type      = ARG_ANYTHING,
+-- 
+2.43.0
+
diff --git a/queue-6.6/bpf-fix-overloading-of-mem_uninit-s-meaning.patch b/queue-6.6/bpf-fix-overloading-of-mem_uninit-s-meaning.patch
new file mode 100644 (file)
index 0000000..9c93d3c
--- /dev/null
@@ -0,0 +1,269 @@
+From 5ff6d27d6c922cc3f0f3c39f1c4c0a98d2c7d0b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Oct 2024 17:28:06 +0200
+Subject: bpf: Fix overloading of MEM_UNINIT's meaning
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+[ Upstream commit 8ea607330a39184f51737c6ae706db7fdca7628e ]
+
+Lonial reported an issue in the BPF verifier where check_mem_size_reg()
+has the following code:
+
+    if (!tnum_is_const(reg->var_off))
+        /* For unprivileged variable accesses, disable raw
+         * mode so that the program is required to
+         * initialize all the memory that the helper could
+         * just partially fill up.
+         */
+         meta = NULL;
+
+This means that writes are not checked when the register containing the
+size of the passed buffer has not a fixed size. Through this bug, a BPF
+program can write to a map which is marked as read-only, for example,
+.rodata global maps.
+
+The problem is that MEM_UNINIT's initial meaning that "the passed buffer
+to the BPF helper does not need to be initialized" which was added back
+in commit 435faee1aae9 ("bpf, verifier: add ARG_PTR_TO_RAW_STACK type")
+got overloaded over time with "the passed buffer is being written to".
+
+The problem however is that checks such as the above which were added later
+via 06c1c049721a ("bpf: allow helpers access to variable memory") set meta
+to NULL in order force the user to always initialize the passed buffer to
+the helper. Due to the current double meaning of MEM_UNINIT, this bypasses
+verifier write checks to the memory (not boundary checks though) and only
+assumes the latter memory is read instead.
+
+Fix this by reverting MEM_UNINIT back to its original meaning, and having
+MEM_WRITE as an annotation to BPF helpers in order to then trigger the
+BPF verifier checks for writing to memory.
+
+Some notes: check_arg_pair_ok() ensures that for ARG_CONST_SIZE{,_OR_ZERO}
+we can access fn->arg_type[arg - 1] since it must contain a preceding
+ARG_PTR_TO_MEM. For check_mem_reg() the meta argument can be removed
+altogether since we do check both BPF_READ and BPF_WRITE. Same for the
+equivalent check_kfunc_mem_size_reg().
+
+Fixes: 7b3552d3f9f6 ("bpf: Reject writes for PTR_TO_MAP_KEY in check_helper_mem_access")
+Fixes: 97e6d7dab1ca ("bpf: Check PTR_TO_MEM | MEM_RDONLY in check_helper_mem_access")
+Fixes: 15baa55ff5b0 ("bpf/verifier: allow all functions to read user provided context")
+Reported-by: Lonial Con <kongln9170@gmail.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Link: https://lore.kernel.org/r/20241021152809.33343-2-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c | 73 +++++++++++++++++++++----------------------
+ 1 file changed, 35 insertions(+), 38 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index f24d570d67ca5..03b5797b8fca9 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -7198,7 +7198,8 @@ static int check_stack_range_initialized(
+ }
+ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
+-                                 int access_size, bool zero_size_allowed,
++                                 int access_size, enum bpf_access_type access_type,
++                                 bool zero_size_allowed,
+                                  struct bpf_call_arg_meta *meta)
+ {
+       struct bpf_reg_state *regs = cur_regs(env), *reg = &regs[regno];
+@@ -7210,7 +7211,7 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
+               return check_packet_access(env, regno, reg->off, access_size,
+                                          zero_size_allowed);
+       case PTR_TO_MAP_KEY:
+-              if (meta && meta->raw_mode) {
++              if (access_type == BPF_WRITE) {
+                       verbose(env, "R%d cannot write into %s\n", regno,
+                               reg_type_str(env, reg->type));
+                       return -EACCES;
+@@ -7218,15 +7219,13 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
+               return check_mem_region_access(env, regno, reg->off, access_size,
+                                              reg->map_ptr->key_size, false);
+       case PTR_TO_MAP_VALUE:
+-              if (check_map_access_type(env, regno, reg->off, access_size,
+-                                        meta && meta->raw_mode ? BPF_WRITE :
+-                                        BPF_READ))
++              if (check_map_access_type(env, regno, reg->off, access_size, access_type))
+                       return -EACCES;
+               return check_map_access(env, regno, reg->off, access_size,
+                                       zero_size_allowed, ACCESS_HELPER);
+       case PTR_TO_MEM:
+               if (type_is_rdonly_mem(reg->type)) {
+-                      if (meta && meta->raw_mode) {
++                      if (access_type == BPF_WRITE) {
+                               verbose(env, "R%d cannot write into %s\n", regno,
+                                       reg_type_str(env, reg->type));
+                               return -EACCES;
+@@ -7237,7 +7236,7 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
+                                              zero_size_allowed);
+       case PTR_TO_BUF:
+               if (type_is_rdonly_mem(reg->type)) {
+-                      if (meta && meta->raw_mode) {
++                      if (access_type == BPF_WRITE) {
+                               verbose(env, "R%d cannot write into %s\n", regno,
+                                       reg_type_str(env, reg->type));
+                               return -EACCES;
+@@ -7265,7 +7264,6 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
+                * Dynamically check it now.
+                */
+               if (!env->ops->convert_ctx_access) {
+-                      enum bpf_access_type atype = meta && meta->raw_mode ? BPF_WRITE : BPF_READ;
+                       int offset = access_size - 1;
+                       /* Allow zero-byte read from PTR_TO_CTX */
+@@ -7273,7 +7271,7 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
+                               return zero_size_allowed ? 0 : -EACCES;
+                       return check_mem_access(env, env->insn_idx, regno, offset, BPF_B,
+-                                              atype, -1, false, false);
++                                              access_type, -1, false, false);
+               }
+               fallthrough;
+@@ -7292,6 +7290,7 @@ static int check_helper_mem_access(struct bpf_verifier_env *env, int regno,
+ static int check_mem_size_reg(struct bpf_verifier_env *env,
+                             struct bpf_reg_state *reg, u32 regno,
++                            enum bpf_access_type access_type,
+                             bool zero_size_allowed,
+                             struct bpf_call_arg_meta *meta)
+ {
+@@ -7307,15 +7306,12 @@ static int check_mem_size_reg(struct bpf_verifier_env *env,
+        */
+       meta->msize_max_value = reg->umax_value;
+-      /* The register is SCALAR_VALUE; the access check
+-       * happens using its boundaries.
++      /* The register is SCALAR_VALUE; the access check happens using
++       * its boundaries. For unprivileged variable accesses, disable
++       * raw mode so that the program is required to initialize all
++       * the memory that the helper could just partially fill up.
+        */
+       if (!tnum_is_const(reg->var_off))
+-              /* For unprivileged variable accesses, disable raw
+-               * mode so that the program is required to
+-               * initialize all the memory that the helper could
+-               * just partially fill up.
+-               */
+               meta = NULL;
+       if (reg->smin_value < 0) {
+@@ -7335,9 +7331,8 @@ static int check_mem_size_reg(struct bpf_verifier_env *env,
+                       regno);
+               return -EACCES;
+       }
+-      err = check_helper_mem_access(env, regno - 1,
+-                                    reg->umax_value,
+-                                    zero_size_allowed, meta);
++      err = check_helper_mem_access(env, regno - 1, reg->umax_value,
++                                    access_type, zero_size_allowed, meta);
+       if (!err)
+               err = mark_chain_precision(env, regno);
+       return err;
+@@ -7348,13 +7343,11 @@ int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
+ {
+       bool may_be_null = type_may_be_null(reg->type);
+       struct bpf_reg_state saved_reg;
+-      struct bpf_call_arg_meta meta;
+       int err;
+       if (register_is_null(reg))
+               return 0;
+-      memset(&meta, 0, sizeof(meta));
+       /* Assuming that the register contains a value check if the memory
+        * access is safe. Temporarily save and restore the register's state as
+        * the conversion shouldn't be visible to a caller.
+@@ -7364,10 +7357,8 @@ int check_mem_reg(struct bpf_verifier_env *env, struct bpf_reg_state *reg,
+               mark_ptr_not_null_reg(reg);
+       }
+-      err = check_helper_mem_access(env, regno, mem_size, true, &meta);
+-      /* Check access for BPF_WRITE */
+-      meta.raw_mode = true;
+-      err = err ?: check_helper_mem_access(env, regno, mem_size, true, &meta);
++      err = check_helper_mem_access(env, regno, mem_size, BPF_READ, true, NULL);
++      err = err ?: check_helper_mem_access(env, regno, mem_size, BPF_WRITE, true, NULL);
+       if (may_be_null)
+               *reg = saved_reg;
+@@ -7393,13 +7384,12 @@ static int check_kfunc_mem_size_reg(struct bpf_verifier_env *env, struct bpf_reg
+               mark_ptr_not_null_reg(mem_reg);
+       }
+-      err = check_mem_size_reg(env, reg, regno, true, &meta);
+-      /* Check access for BPF_WRITE */
+-      meta.raw_mode = true;
+-      err = err ?: check_mem_size_reg(env, reg, regno, true, &meta);
++      err = check_mem_size_reg(env, reg, regno, BPF_READ, true, &meta);
++      err = err ?: check_mem_size_reg(env, reg, regno, BPF_WRITE, true, &meta);
+       if (may_be_null)
+               *mem_reg = saved_reg;
++
+       return err;
+ }
+@@ -8585,9 +8575,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
+                       verbose(env, "invalid map_ptr to access map->key\n");
+                       return -EACCES;
+               }
+-              err = check_helper_mem_access(env, regno,
+-                                            meta->map_ptr->key_size, false,
+-                                            NULL);
++              err = check_helper_mem_access(env, regno, meta->map_ptr->key_size,
++                                            BPF_READ, false, NULL);
+               break;
+       case ARG_PTR_TO_MAP_VALUE:
+               if (type_may_be_null(arg_type) && register_is_null(reg))
+@@ -8602,9 +8591,9 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
+                       return -EACCES;
+               }
+               meta->raw_mode = arg_type & MEM_UNINIT;
+-              err = check_helper_mem_access(env, regno,
+-                                            meta->map_ptr->value_size, false,
+-                                            meta);
++              err = check_helper_mem_access(env, regno, meta->map_ptr->value_size,
++                                            arg_type & MEM_WRITE ? BPF_WRITE : BPF_READ,
++                                            false, meta);
+               break;
+       case ARG_PTR_TO_PERCPU_BTF_ID:
+               if (!reg->btf_id) {
+@@ -8646,7 +8635,9 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
+                */
+               meta->raw_mode = arg_type & MEM_UNINIT;
+               if (arg_type & MEM_FIXED_SIZE) {
+-                      err = check_helper_mem_access(env, regno, fn->arg_size[arg], false, meta);
++                      err = check_helper_mem_access(env, regno, fn->arg_size[arg],
++                                                    arg_type & MEM_WRITE ? BPF_WRITE : BPF_READ,
++                                                    false, meta);
+                       if (err)
+                               return err;
+                       if (arg_type & MEM_ALIGNED)
+@@ -8654,10 +8645,16 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
+               }
+               break;
+       case ARG_CONST_SIZE:
+-              err = check_mem_size_reg(env, reg, regno, false, meta);
++              err = check_mem_size_reg(env, reg, regno,
++                                       fn->arg_type[arg - 1] & MEM_WRITE ?
++                                       BPF_WRITE : BPF_READ,
++                                       false, meta);
+               break;
+       case ARG_CONST_SIZE_OR_ZERO:
+-              err = check_mem_size_reg(env, reg, regno, true, meta);
++              err = check_mem_size_reg(env, reg, regno,
++                                       fn->arg_type[arg - 1] & MEM_WRITE ?
++                                       BPF_WRITE : BPF_READ,
++                                       true, meta);
+               break;
+       case ARG_PTR_TO_DYNPTR:
+               err = process_dynptr_func(env, regno, insn_idx, arg_type, 0);
+-- 
+2.43.0
+
diff --git a/queue-6.6/bpf-perf-fix-perf_event_detach_bpf_prog-error-handli.patch b/queue-6.6/bpf-perf-fix-perf_event_detach_bpf_prog-error-handli.patch
new file mode 100644 (file)
index 0000000..5116aaf
--- /dev/null
@@ -0,0 +1,46 @@
+From 648ee4de16798e24fe06a1e47d9ba0b7e24f6fc6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 23 Oct 2024 22:03:52 +0200
+Subject: bpf,perf: Fix perf_event_detach_bpf_prog error handling
+
+From: Jiri Olsa <jolsa@kernel.org>
+
+[ Upstream commit 0ee288e69d033850bc87abe0f9cc3ada24763d7f ]
+
+Peter reported that perf_event_detach_bpf_prog might skip to release
+the bpf program for -ENOENT error from bpf_prog_array_copy.
+
+This can't happen because bpf program is stored in perf event and is
+detached and released only when perf event is freed.
+
+Let's drop the -ENOENT check and make sure the bpf program is released
+in any case.
+
+Fixes: 170a7e3ea070 ("bpf: bpf_prog_array_copy() should return -ENOENT if exclude_prog not found")
+Reported-by: Peter Zijlstra <peterz@infradead.org>
+Signed-off-by: Jiri Olsa <jolsa@kernel.org>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20241023200352.3488610-1-jolsa@kernel.org
+
+Closes: https://lore.kernel.org/lkml/20241022111638.GC16066@noisy.programming.kicks-ass.net/
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/bpf_trace.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
+index ecc86a595b754..9064f75de7e46 100644
+--- a/kernel/trace/bpf_trace.c
++++ b/kernel/trace/bpf_trace.c
+@@ -2217,8 +2217,6 @@ void perf_event_detach_bpf_prog(struct perf_event *event)
+       old_array = bpf_event_rcu_dereference(event->tp_event->prog_array);
+       ret = bpf_prog_array_copy(old_array, event->prog, NULL, 0, &new_array);
+-      if (ret == -ENOENT)
+-              goto unlock;
+       if (ret < 0) {
+               bpf_prog_array_delete_safe(old_array, event->prog);
+       } else {
+-- 
+2.43.0
+
diff --git a/queue-6.6/bpf-remove-mem_uninit-from-skb-xdp-mtu-helpers.patch b/queue-6.6/bpf-remove-mem_uninit-from-skb-xdp-mtu-helpers.patch
new file mode 100644 (file)
index 0000000..f28bab1
--- /dev/null
@@ -0,0 +1,122 @@
+From 2c51c014f160f7c0ccf57a8baa9dba4e03e31da5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 21 Oct 2024 17:28:07 +0200
+Subject: bpf: Remove MEM_UNINIT from skb/xdp MTU helpers
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+[ Upstream commit 14a3d3ef02ba53447d5112a2641aac0d10dc994f ]
+
+We can now undo parts of 4b3786a6c539 ("bpf: Zero former ARG_PTR_TO_{LONG,INT}
+args in case of error") as discussed in [0].
+
+Given the BPF helpers now have MEM_WRITE tag, the MEM_UNINIT can be cleared.
+
+The mtu_len is an input as well as output argument, meaning, the BPF program
+has to set it to something. It cannot be uninitialized. Therefore, allowing
+uninitialized memory and zeroing it on error would be odd. It was done as
+an interim step in 4b3786a6c539 as the desired behavior could not have been
+expressed before the introduction of MEM_WRITE tag.
+
+Fixes: 4b3786a6c539 ("bpf: Zero former ARG_PTR_TO_{LONG,INT} args in case of error")
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/bpf/a86eb76d-f52f-dee4-e5d2-87e45de3e16f@iogearbox.net [0]
+Acked-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
+Link: https://lore.kernel.org/r/20241021152809.33343-3-daniel@iogearbox.net
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/core/filter.c | 42 +++++++++++++++---------------------------
+ 1 file changed, 15 insertions(+), 27 deletions(-)
+
+diff --git a/net/core/filter.c b/net/core/filter.c
+index a7d928345b1f4..a2467a7c01f9e 100644
+--- a/net/core/filter.c
++++ b/net/core/filter.c
+@@ -6223,24 +6223,16 @@ BPF_CALL_5(bpf_skb_check_mtu, struct sk_buff *, skb,
+ {
+       int ret = BPF_MTU_CHK_RET_FRAG_NEEDED;
+       struct net_device *dev = skb->dev;
+-      int skb_len, dev_len;
+-      int mtu = 0;
++      int mtu, dev_len, skb_len;
+-      if (unlikely(flags & ~(BPF_MTU_CHK_SEGS))) {
+-              ret = -EINVAL;
+-              goto out;
+-      }
+-
+-      if (unlikely(flags & BPF_MTU_CHK_SEGS && (len_diff || *mtu_len))) {
+-              ret = -EINVAL;
+-              goto out;
+-      }
++      if (unlikely(flags & ~(BPF_MTU_CHK_SEGS)))
++              return -EINVAL;
++      if (unlikely(flags & BPF_MTU_CHK_SEGS && (len_diff || *mtu_len)))
++              return -EINVAL;
+       dev = __dev_via_ifindex(dev, ifindex);
+-      if (unlikely(!dev)) {
+-              ret = -ENODEV;
+-              goto out;
+-      }
++      if (unlikely(!dev))
++              return -ENODEV;
+       mtu = READ_ONCE(dev->mtu);
+       dev_len = mtu + dev->hard_header_len;
+@@ -6275,19 +6267,15 @@ BPF_CALL_5(bpf_xdp_check_mtu, struct xdp_buff *, xdp,
+       struct net_device *dev = xdp->rxq->dev;
+       int xdp_len = xdp->data_end - xdp->data;
+       int ret = BPF_MTU_CHK_RET_SUCCESS;
+-      int mtu = 0, dev_len;
++      int mtu, dev_len;
+       /* XDP variant doesn't support multi-buffer segment check (yet) */
+-      if (unlikely(flags)) {
+-              ret = -EINVAL;
+-              goto out;
+-      }
++      if (unlikely(flags))
++              return -EINVAL;
+       dev = __dev_via_ifindex(dev, ifindex);
+-      if (unlikely(!dev)) {
+-              ret = -ENODEV;
+-              goto out;
+-      }
++      if (unlikely(!dev))
++              return -ENODEV;
+       mtu = READ_ONCE(dev->mtu);
+       dev_len = mtu + dev->hard_header_len;
+@@ -6299,7 +6287,7 @@ BPF_CALL_5(bpf_xdp_check_mtu, struct xdp_buff *, xdp,
+       xdp_len += len_diff; /* minus result pass check */
+       if (xdp_len > dev_len)
+               ret = BPF_MTU_CHK_RET_FRAG_NEEDED;
+-out:
++
+       *mtu_len = mtu;
+       return ret;
+ }
+@@ -6310,7 +6298,7 @@ static const struct bpf_func_proto bpf_skb_check_mtu_proto = {
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_PTR_TO_CTX,
+       .arg2_type      = ARG_ANYTHING,
+-      .arg3_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED,
++      .arg3_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_WRITE | MEM_ALIGNED,
+       .arg3_size      = sizeof(u32),
+       .arg4_type      = ARG_ANYTHING,
+       .arg5_type      = ARG_ANYTHING,
+@@ -6322,7 +6310,7 @@ static const struct bpf_func_proto bpf_xdp_check_mtu_proto = {
+       .ret_type       = RET_INTEGER,
+       .arg1_type      = ARG_PTR_TO_CTX,
+       .arg2_type      = ARG_ANYTHING,
+-      .arg3_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_UNINIT | MEM_WRITE | MEM_ALIGNED,
++      .arg3_type      = ARG_PTR_TO_FIXED_SIZE_MEM | MEM_WRITE | MEM_ALIGNED,
+       .arg3_size      = sizeof(u32),
+       .arg4_type      = ARG_ANYTHING,
+       .arg5_type      = ARG_ANYTHING,
+-- 
+2.43.0
+
diff --git a/queue-6.6/bpf-simplify-checking-size-of-helper-accesses.patch b/queue-6.6/bpf-simplify-checking-size-of-helper-accesses.patch
new file mode 100644 (file)
index 0000000..254d51a
--- /dev/null
@@ -0,0 +1,134 @@
+From 4b174ee3c878d42aae8c6bea4555f54faad5981f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Dec 2023 18:22:24 -0500
+Subject: bpf: Simplify checking size of helper accesses
+
+From: Andrei Matei <andreimatei1@gmail.com>
+
+[ Upstream commit 8a021e7fa10576eeb3938328f39bbf98fe7d4715 ]
+
+This patch simplifies the verification of size arguments associated to
+pointer arguments to helpers and kfuncs. Many helpers take a pointer
+argument followed by the size of the memory access performed to be
+performed through that pointer. Before this patch, the handling of the
+size argument in check_mem_size_reg() was confusing and wasteful: if the
+size register's lower bound was 0, then the verification was done twice:
+once considering the size of the access to be the lower-bound of the
+respective argument, and once considering the upper bound (even if the
+two are the same). The upper bound checking is a super-set of the
+lower-bound checking(*), except: the only point of the lower-bound check
+is to handle the case where zero-sized-accesses are explicitly not
+allowed and the lower-bound is zero. This static condition is now
+checked explicitly, replacing a much more complex, expensive and
+confusing verification call to check_helper_mem_access().
+
+Error messages change in this patch. Before, messages about illegal
+zero-size accesses depended on the type of the pointer and on other
+conditions, and sometimes the message was plain wrong: in some tests
+that changed you'll see that the old message was something like "R1 min
+value is outside of the allowed memory range", where R1 is the pointer
+register; the error was wrongly claiming that the pointer was bad
+instead of the size being bad. Other times the information that the size
+came for a register with a possible range of values was wrong, and the
+error presented the size as a fixed zero. Now the errors refer to the
+right register. However, the old error messages did contain useful
+information about the pointer register which is now lost; recovering
+this information was deemed not important enough.
+
+(*) Besides standing to reason that the checks for a bigger size access
+are a super-set of the checks for a smaller size access, I have also
+mechanically verified this by reading the code for all types of
+pointers. I could convince myself that it's true for all but
+PTR_TO_BTF_ID (check_ptr_to_btf_access). There, simply looking
+line-by-line does not immediately prove what we want. If anyone has any
+qualms, let me know.
+
+Signed-off-by: Andrei Matei <andreimatei1@gmail.com>
+Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
+Acked-by: Andrii Nakryiko <andrii@kernel.org>
+Link: https://lore.kernel.org/bpf/20231221232225.568730-2-andreimatei1@gmail.com
+Stable-dep-of: 8ea607330a39 ("bpf: Fix overloading of MEM_UNINIT's meaning")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/bpf/verifier.c                                  | 10 ++++------
+ .../selftests/bpf/progs/verifier_helper_value_access.c |  8 ++++----
+ tools/testing/selftests/bpf/progs/verifier_raw_stack.c |  2 +-
+ 3 files changed, 9 insertions(+), 11 deletions(-)
+
+diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
+index 28b09ca5525f0..f24d570d67ca5 100644
+--- a/kernel/bpf/verifier.c
++++ b/kernel/bpf/verifier.c
+@@ -7324,12 +7324,10 @@ static int check_mem_size_reg(struct bpf_verifier_env *env,
+               return -EACCES;
+       }
+-      if (reg->umin_value == 0) {
+-              err = check_helper_mem_access(env, regno - 1, 0,
+-                                            zero_size_allowed,
+-                                            meta);
+-              if (err)
+-                      return err;
++      if (reg->umin_value == 0 && !zero_size_allowed) {
++              verbose(env, "R%d invalid zero-sized read: u64=[%lld,%lld]\n",
++                      regno, reg->umin_value, reg->umax_value);
++              return -EACCES;
+       }
+       if (reg->umax_value >= BPF_MAX_VAR_SIZ) {
+diff --git a/tools/testing/selftests/bpf/progs/verifier_helper_value_access.c b/tools/testing/selftests/bpf/progs/verifier_helper_value_access.c
+index 692216c0ad3d4..3e8340c2408f3 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_helper_value_access.c
++++ b/tools/testing/selftests/bpf/progs/verifier_helper_value_access.c
+@@ -91,7 +91,7 @@ l0_%=:       exit;                                           \
+ SEC("tracepoint")
+ __description("helper access to map: empty range")
+-__failure __msg("invalid access to map value, value_size=48 off=0 size=0")
++__failure __msg("R2 invalid zero-sized read")
+ __naked void access_to_map_empty_range(void)
+ {
+       asm volatile ("                                 \
+@@ -221,7 +221,7 @@ l0_%=:     exit;                                           \
+ SEC("tracepoint")
+ __description("helper access to adjusted map (via const imm): empty range")
+-__failure __msg("invalid access to map value, value_size=48 off=4 size=0")
++__failure __msg("R2 invalid zero-sized read")
+ __naked void via_const_imm_empty_range(void)
+ {
+       asm volatile ("                                 \
+@@ -386,7 +386,7 @@ l0_%=:     exit;                                           \
+ SEC("tracepoint")
+ __description("helper access to adjusted map (via const reg): empty range")
+-__failure __msg("R1 min value is outside of the allowed memory range")
++__failure __msg("R2 invalid zero-sized read")
+ __naked void via_const_reg_empty_range(void)
+ {
+       asm volatile ("                                 \
+@@ -556,7 +556,7 @@ l0_%=:     exit;                                           \
+ SEC("tracepoint")
+ __description("helper access to adjusted map (via variable): empty range")
+-__failure __msg("R1 min value is outside of the allowed memory range")
++__failure __msg("R2 invalid zero-sized read")
+ __naked void map_via_variable_empty_range(void)
+ {
+       asm volatile ("                                 \
+diff --git a/tools/testing/selftests/bpf/progs/verifier_raw_stack.c b/tools/testing/selftests/bpf/progs/verifier_raw_stack.c
+index f67390224a9cf..7cc83acac7271 100644
+--- a/tools/testing/selftests/bpf/progs/verifier_raw_stack.c
++++ b/tools/testing/selftests/bpf/progs/verifier_raw_stack.c
+@@ -64,7 +64,7 @@ __naked void load_bytes_negative_len_2(void)
+ SEC("tc")
+ __description("raw_stack: skb_load_bytes, zero len")
+-__failure __msg("invalid zero-sized read")
++__failure __msg("R4 invalid zero-sized read: u64=[0,0]")
+ __naked void skb_load_bytes_zero_len(void)
+ {
+       asm volatile ("                                 \
+-- 
+2.43.0
+
diff --git a/queue-6.6/fsl-fman-fix-refcount-handling-of-fman-related-devic.patch b/queue-6.6/fsl-fman-fix-refcount-handling-of-fman-related-devic.patch
new file mode 100644 (file)
index 0000000..2f09416
--- /dev/null
@@ -0,0 +1,190 @@
+From e4b3a96888905e26e6b82e67797cf6220ecc1e4d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Oct 2024 09:01:22 +0300
+Subject: fsl/fman: Fix refcount handling of fman-related devices
+
+From: Aleksandr Mishin <amishin@t-argos.ru>
+
+[ Upstream commit 1dec67e0d9fbb087c2ab17bf1bd17208231c3bb1 ]
+
+In mac_probe() there are multiple calls to of_find_device_by_node(),
+fman_bind() and fman_port_bind() which takes references to of_dev->dev.
+Not all references taken by these calls are released later on error path
+in mac_probe() and in mac_remove() which lead to reference leaks.
+
+Add references release.
+
+Fixes: 3933961682a3 ("fsl/fman: Add FMan MAC driver")
+Signed-off-by: Aleksandr Mishin <amishin@t-argos.ru>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fman/mac.c | 62 +++++++++++++++++------
+ 1 file changed, 47 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
+index 9b863db0bf087..11da139082e1b 100644
+--- a/drivers/net/ethernet/freescale/fman/mac.c
++++ b/drivers/net/ethernet/freescale/fman/mac.c
+@@ -204,7 +204,7 @@ static int mac_probe(struct platform_device *_of_dev)
+       if (err) {
+               dev_err(dev, "failed to read cell-index for %pOF\n", dev_node);
+               err = -EINVAL;
+-              goto _return_of_node_put;
++              goto _return_dev_put;
+       }
+       /* cell-index 0 => FMan id 1 */
+       fman_id = (u8)(val + 1);
+@@ -213,40 +213,51 @@ static int mac_probe(struct platform_device *_of_dev)
+       if (!priv->fman) {
+               dev_err(dev, "fman_bind(%pOF) failed\n", dev_node);
+               err = -ENODEV;
+-              goto _return_of_node_put;
++              goto _return_dev_put;
+       }
++      /* Two references have been taken in of_find_device_by_node()
++       * and fman_bind(). Release one of them here. The second one
++       * will be released in mac_remove().
++       */
++      put_device(mac_dev->fman_dev);
+       of_node_put(dev_node);
++      dev_node = NULL;
+       /* Get the address of the memory mapped registers */
+       mac_dev->res = platform_get_mem_or_io(_of_dev, 0);
+       if (!mac_dev->res) {
+               dev_err(dev, "could not get registers\n");
+-              return -EINVAL;
++              err = -EINVAL;
++              goto _return_dev_put;
+       }
+       err = devm_request_resource(dev, fman_get_mem_region(priv->fman),
+                                   mac_dev->res);
+       if (err) {
+               dev_err_probe(dev, err, "could not request resource\n");
+-              return err;
++              goto _return_dev_put;
+       }
+       mac_dev->vaddr = devm_ioremap(dev, mac_dev->res->start,
+                                     resource_size(mac_dev->res));
+       if (!mac_dev->vaddr) {
+               dev_err(dev, "devm_ioremap() failed\n");
+-              return -EIO;
++              err = -EIO;
++              goto _return_dev_put;
+       }
+-      if (!of_device_is_available(mac_node))
+-              return -ENODEV;
++      if (!of_device_is_available(mac_node)) {
++              err = -ENODEV;
++              goto _return_dev_put;
++      }
+       /* Get the cell-index */
+       err = of_property_read_u32(mac_node, "cell-index", &val);
+       if (err) {
+               dev_err(dev, "failed to read cell-index for %pOF\n", mac_node);
+-              return -EINVAL;
++              err = -EINVAL;
++              goto _return_dev_put;
+       }
+       priv->cell_index = (u8)val;
+@@ -260,22 +271,26 @@ static int mac_probe(struct platform_device *_of_dev)
+       if (unlikely(nph < 0)) {
+               dev_err(dev, "of_count_phandle_with_args(%pOF, fsl,fman-ports) failed\n",
+                       mac_node);
+-              return nph;
++              err = nph;
++              goto _return_dev_put;
+       }
+       if (nph != ARRAY_SIZE(mac_dev->port)) {
+               dev_err(dev, "Not supported number of fman-ports handles of mac node %pOF from device tree\n",
+                       mac_node);
+-              return -EINVAL;
++              err = -EINVAL;
++              goto _return_dev_put;
+       }
+-      for (i = 0; i < ARRAY_SIZE(mac_dev->port); i++) {
++      /* PORT_NUM determines the size of the port array */
++      for (i = 0; i < PORT_NUM; i++) {
+               /* Find the port node */
+               dev_node = of_parse_phandle(mac_node, "fsl,fman-ports", i);
+               if (!dev_node) {
+                       dev_err(dev, "of_parse_phandle(%pOF, fsl,fman-ports) failed\n",
+                               mac_node);
+-                      return -EINVAL;
++                      err = -EINVAL;
++                      goto _return_dev_arr_put;
+               }
+               of_dev = of_find_device_by_node(dev_node);
+@@ -283,7 +298,7 @@ static int mac_probe(struct platform_device *_of_dev)
+                       dev_err(dev, "of_find_device_by_node(%pOF) failed\n",
+                               dev_node);
+                       err = -EINVAL;
+-                      goto _return_of_node_put;
++                      goto _return_dev_arr_put;
+               }
+               mac_dev->fman_port_devs[i] = &of_dev->dev;
+@@ -292,9 +307,15 @@ static int mac_probe(struct platform_device *_of_dev)
+                       dev_err(dev, "dev_get_drvdata(%pOF) failed\n",
+                               dev_node);
+                       err = -EINVAL;
+-                      goto _return_of_node_put;
++                      goto _return_dev_arr_put;
+               }
++              /* Two references have been taken in of_find_device_by_node()
++               * and fman_port_bind(). Release one of them here. The second
++               * one will be released in mac_remove().
++               */
++              put_device(mac_dev->fman_port_devs[i]);
+               of_node_put(dev_node);
++              dev_node = NULL;
+       }
+       /* Get the PHY connection type */
+@@ -314,7 +335,7 @@ static int mac_probe(struct platform_device *_of_dev)
+       err = init(mac_dev, mac_node, &params);
+       if (err < 0)
+-              return err;
++              goto _return_dev_arr_put;
+       if (!is_zero_ether_addr(mac_dev->addr))
+               dev_info(dev, "FMan MAC address: %pM\n", mac_dev->addr);
+@@ -329,6 +350,12 @@ static int mac_probe(struct platform_device *_of_dev)
+       return err;
++_return_dev_arr_put:
++      /* mac_dev is kzalloc'ed */
++      for (i = 0; i < PORT_NUM; i++)
++              put_device(mac_dev->fman_port_devs[i]);
++_return_dev_put:
++      put_device(mac_dev->fman_dev);
+ _return_of_node_put:
+       of_node_put(dev_node);
+       return err;
+@@ -337,6 +364,11 @@ static int mac_probe(struct platform_device *_of_dev)
+ static void mac_remove(struct platform_device *pdev)
+ {
+       struct mac_device *mac_dev = platform_get_drvdata(pdev);
++      int                i;
++
++      for (i = 0; i < PORT_NUM; i++)
++              put_device(mac_dev->fman_port_devs[i]);
++      put_device(mac_dev->fman_dev);
+       platform_device_unregister(mac_dev->priv->eth_dev);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/fsl-fman-save-device-references-taken-in-mac_probe.patch b/queue-6.6/fsl-fman-save-device-references-taken-in-mac_probe.patch
new file mode 100644 (file)
index 0000000..117e957
--- /dev/null
@@ -0,0 +1,91 @@
+From b7af72858551f2cc77145e3ddc482118ae43744b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Oct 2024 09:01:21 +0300
+Subject: fsl/fman: Save device references taken in mac_probe()
+
+From: Aleksandr Mishin <amishin@t-argos.ru>
+
+[ Upstream commit efeddd552ec6767e4c8884caa516ac80b65f8823 ]
+
+In mac_probe() there are calls to of_find_device_by_node() which takes
+references to of_dev->dev. These references are not saved and not released
+later on error path in mac_probe() and in mac_remove().
+
+Add new fields into mac_device structure to save references taken for
+future use in mac_probe() and mac_remove().
+
+This is a preparation for further reference leaks fix.
+
+Signed-off-by: Aleksandr Mishin <amishin@t-argos.ru>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Stable-dep-of: 1dec67e0d9fb ("fsl/fman: Fix refcount handling of fman-related devices")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/freescale/fman/mac.c | 6 ++++--
+ drivers/net/ethernet/freescale/fman/mac.h | 6 +++++-
+ 2 files changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/freescale/fman/mac.c b/drivers/net/ethernet/freescale/fman/mac.c
+index 9767586b4eb32..9b863db0bf087 100644
+--- a/drivers/net/ethernet/freescale/fman/mac.c
++++ b/drivers/net/ethernet/freescale/fman/mac.c
+@@ -197,6 +197,7 @@ static int mac_probe(struct platform_device *_of_dev)
+               err = -EINVAL;
+               goto _return_of_node_put;
+       }
++      mac_dev->fman_dev = &of_dev->dev;
+       /* Get the FMan cell-index */
+       err = of_property_read_u32(dev_node, "cell-index", &val);
+@@ -208,7 +209,7 @@ static int mac_probe(struct platform_device *_of_dev)
+       /* cell-index 0 => FMan id 1 */
+       fman_id = (u8)(val + 1);
+-      priv->fman = fman_bind(&of_dev->dev);
++      priv->fman = fman_bind(mac_dev->fman_dev);
+       if (!priv->fman) {
+               dev_err(dev, "fman_bind(%pOF) failed\n", dev_node);
+               err = -ENODEV;
+@@ -284,8 +285,9 @@ static int mac_probe(struct platform_device *_of_dev)
+                       err = -EINVAL;
+                       goto _return_of_node_put;
+               }
++              mac_dev->fman_port_devs[i] = &of_dev->dev;
+-              mac_dev->port[i] = fman_port_bind(&of_dev->dev);
++              mac_dev->port[i] = fman_port_bind(mac_dev->fman_port_devs[i]);
+               if (!mac_dev->port[i]) {
+                       dev_err(dev, "dev_get_drvdata(%pOF) failed\n",
+                               dev_node);
+diff --git a/drivers/net/ethernet/freescale/fman/mac.h b/drivers/net/ethernet/freescale/fman/mac.h
+index fe747915cc737..8b5b43d50f8ef 100644
+--- a/drivers/net/ethernet/freescale/fman/mac.h
++++ b/drivers/net/ethernet/freescale/fman/mac.h
+@@ -19,12 +19,13 @@
+ struct fman_mac;
+ struct mac_priv_s;
++#define PORT_NUM 2
+ struct mac_device {
+       void __iomem            *vaddr;
+       struct device           *dev;
+       struct resource         *res;
+       u8                       addr[ETH_ALEN];
+-      struct fman_port        *port[2];
++      struct fman_port        *port[PORT_NUM];
+       struct phylink          *phylink;
+       struct phylink_config   phylink_config;
+       phy_interface_t         phy_if;
+@@ -52,6 +53,9 @@ struct mac_device {
+       struct fman_mac         *fman_mac;
+       struct mac_priv_s       *priv;
++
++      struct device           *fman_dev;
++      struct device           *fman_port_devs[PORT_NUM];
+ };
+ static inline struct mac_device
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-dsa-mv88e6xxx-fix-error-when-setting-port-policy.patch b/queue-6.6/net-dsa-mv88e6xxx-fix-error-when-setting-port-policy.patch
new file mode 100644 (file)
index 0000000..c5c945f
--- /dev/null
@@ -0,0 +1,41 @@
+From 4774189b3784b17f1c0ea7edbec3106898c4f865 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Oct 2024 21:08:22 -0700
+Subject: net: dsa: mv88e6xxx: Fix error when setting port policy on mv88e6393x
+
+From: Peter Rashleigh <peter@rashleigh.ca>
+
+[ Upstream commit 12bc14949c4a7272b509af0f1022a0deeb215fd8 ]
+
+mv88e6393x_port_set_policy doesn't correctly shift the ptr value when
+converting the policy format between the old and new styles, so the
+target register ends up with the ptr being written over the data bits.
+
+Shift the pointer to align with the format expected by
+mv88e6393x_port_policy_write().
+
+Fixes: 6584b26020fc ("net: dsa: mv88e6xxx: implement .port_set_policy for Amethyst")
+Signed-off-by: Peter Rashleigh <peter@rashleigh.ca>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Message-ID: <20241016040822.3917-1-peter@rashleigh.ca>
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/mv88e6xxx/port.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
+index 5394a8cf7bf1d..04053fdc6489a 100644
+--- a/drivers/net/dsa/mv88e6xxx/port.c
++++ b/drivers/net/dsa/mv88e6xxx/port.c
+@@ -1713,6 +1713,7 @@ int mv88e6393x_port_set_policy(struct mv88e6xxx_chip *chip, int port,
+       ptr = shift / 8;
+       shift %= 8;
+       mask >>= ptr * 8;
++      ptr <<= 8;
+       err = mv88e6393x_port_policy_read(chip, port, ptr, &reg);
+       if (err)
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-dsa-mv88e6xxx-group-cycle-counter-coefficients.patch b/queue-6.6/net-dsa-mv88e6xxx-group-cycle-counter-coefficients.patch
new file mode 100644 (file)
index 0000000..90ec297
--- /dev/null
@@ -0,0 +1,176 @@
+From 6d5e884963ef0e77c77ebf1accc6fbeaa9992056 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 20 Oct 2024 14:38:28 +0800
+Subject: net: dsa: mv88e6xxx: group cycle counter coefficients
+
+From: Shenghao Yang <me@shenghaoyang.info>
+
+[ Upstream commit 67af86afff74c914944374a103c04e4d9868dd15 ]
+
+Instead of having them as individual fields in ptp_ops, wrap the
+coefficients in a separate struct so they can be referenced together.
+
+Fixes: de776d0d316f ("net: dsa: mv88e6xxx: add support for mv88e6393x family")
+Signed-off-by: Shenghao Yang <me@shenghaoyang.info>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/mv88e6xxx/chip.h |  6 ++--
+ drivers/net/dsa/mv88e6xxx/ptp.c  | 59 ++++++++++++++++----------------
+ 2 files changed, 32 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
+index f48a3c0ac7f96..bfc3a1040cccd 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.h
++++ b/drivers/net/dsa/mv88e6xxx/chip.h
+@@ -206,6 +206,7 @@ struct mv88e6xxx_gpio_ops;
+ struct mv88e6xxx_avb_ops;
+ struct mv88e6xxx_ptp_ops;
+ struct mv88e6xxx_pcs_ops;
++struct mv88e6xxx_cc_coeffs;
+ struct mv88e6xxx_irq {
+       u16 masked;
+@@ -719,10 +720,7 @@ struct mv88e6xxx_ptp_ops {
+       int arr1_sts_reg;
+       int dep_sts_reg;
+       u32 rx_filters;
+-      u32 cc_shift;
+-      u32 cc_mult;
+-      u32 cc_mult_num;
+-      u32 cc_mult_dem;
++      const struct mv88e6xxx_cc_coeffs *cc_coeffs;
+ };
+ struct mv88e6xxx_pcs_ops {
+diff --git a/drivers/net/dsa/mv88e6xxx/ptp.c b/drivers/net/dsa/mv88e6xxx/ptp.c
+index ea17231dc34e3..4d5498dac1533 100644
+--- a/drivers/net/dsa/mv88e6xxx/ptp.c
++++ b/drivers/net/dsa/mv88e6xxx/ptp.c
+@@ -18,6 +18,13 @@
+ #define MV88E6XXX_MAX_ADJ_PPB 1000000
++struct mv88e6xxx_cc_coeffs {
++      u32 cc_shift;
++      u32 cc_mult;
++      u32 cc_mult_num;
++      u32 cc_mult_dem;
++};
++
+ /* Family MV88E6250:
+  * Raw timestamps are in units of 10-ns clock periods.
+  *
+@@ -25,10 +32,13 @@
+  * simplifies to
+  * clkadj = scaled_ppm * 2^7 / 5^5
+  */
+-#define MV88E6250_CC_SHIFT    28
+-#define MV88E6250_CC_MULT     (10 << MV88E6250_CC_SHIFT)
+-#define MV88E6250_CC_MULT_NUM (1 << 7)
+-#define MV88E6250_CC_MULT_DEM 3125ULL
++#define MV88E6250_CC_SHIFT 28
++static const struct mv88e6xxx_cc_coeffs mv88e6250_cc_coeffs = {
++      .cc_shift = MV88E6250_CC_SHIFT,
++      .cc_mult = 10 << MV88E6250_CC_SHIFT,
++      .cc_mult_num = 1 << 7,
++      .cc_mult_dem = 3125ULL,
++};
+ /* Other families:
+  * Raw timestamps are in units of 8-ns clock periods.
+@@ -37,10 +47,13 @@
+  * simplifies to
+  * clkadj = scaled_ppm * 2^9 / 5^6
+  */
+-#define MV88E6XXX_CC_SHIFT    28
+-#define MV88E6XXX_CC_MULT     (8 << MV88E6XXX_CC_SHIFT)
+-#define MV88E6XXX_CC_MULT_NUM (1 << 9)
+-#define MV88E6XXX_CC_MULT_DEM 15625ULL
++#define MV88E6XXX_CC_SHIFT 28
++static const struct mv88e6xxx_cc_coeffs mv88e6xxx_cc_coeffs = {
++      .cc_shift = MV88E6XXX_CC_SHIFT,
++      .cc_mult = 8 << MV88E6XXX_CC_SHIFT,
++      .cc_mult_num = 1 << 9,
++      .cc_mult_dem = 15625ULL
++};
+ #define TAI_EVENT_WORK_INTERVAL msecs_to_jiffies(100)
+@@ -210,10 +223,10 @@ static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+               scaled_ppm = -scaled_ppm;
+       }
+-      mult = ptp_ops->cc_mult;
+-      adj = ptp_ops->cc_mult_num;
++      mult = ptp_ops->cc_coeffs->cc_mult;
++      adj = ptp_ops->cc_coeffs->cc_mult_num;
+       adj *= scaled_ppm;
+-      diff = div_u64(adj, ptp_ops->cc_mult_dem);
++      diff = div_u64(adj, ptp_ops->cc_coeffs->cc_mult_dem);
+       mv88e6xxx_reg_lock(chip);
+@@ -360,10 +373,7 @@ const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {
+               (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
+-      .cc_shift = MV88E6XXX_CC_SHIFT,
+-      .cc_mult = MV88E6XXX_CC_MULT,
+-      .cc_mult_num = MV88E6XXX_CC_MULT_NUM,
+-      .cc_mult_dem = MV88E6XXX_CC_MULT_DEM,
++      .cc_coeffs = &mv88e6xxx_cc_coeffs
+ };
+ const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {
+@@ -387,10 +397,7 @@ const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {
+               (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
+-      .cc_shift = MV88E6250_CC_SHIFT,
+-      .cc_mult = MV88E6250_CC_MULT,
+-      .cc_mult_num = MV88E6250_CC_MULT_NUM,
+-      .cc_mult_dem = MV88E6250_CC_MULT_DEM,
++      .cc_coeffs = &mv88e6250_cc_coeffs,
+ };
+ const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
+@@ -414,10 +421,7 @@ const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
+               (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
+-      .cc_shift = MV88E6XXX_CC_SHIFT,
+-      .cc_mult = MV88E6XXX_CC_MULT,
+-      .cc_mult_num = MV88E6XXX_CC_MULT_NUM,
+-      .cc_mult_dem = MV88E6XXX_CC_MULT_DEM,
++      .cc_coeffs = &mv88e6xxx_cc_coeffs,
+ };
+ const struct mv88e6xxx_ptp_ops mv88e6390_ptp_ops = {
+@@ -442,10 +446,7 @@ const struct mv88e6xxx_ptp_ops mv88e6390_ptp_ops = {
+               (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
+-      .cc_shift = MV88E6XXX_CC_SHIFT,
+-      .cc_mult = MV88E6XXX_CC_MULT,
+-      .cc_mult_num = MV88E6XXX_CC_MULT_NUM,
+-      .cc_mult_dem = MV88E6XXX_CC_MULT_DEM,
++      .cc_coeffs = &mv88e6xxx_cc_coeffs,
+ };
+ static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
+@@ -483,8 +484,8 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
+       memset(&chip->tstamp_cc, 0, sizeof(chip->tstamp_cc));
+       chip->tstamp_cc.read    = mv88e6xxx_ptp_clock_read;
+       chip->tstamp_cc.mask    = CYCLECOUNTER_MASK(32);
+-      chip->tstamp_cc.mult    = ptp_ops->cc_mult;
+-      chip->tstamp_cc.shift   = ptp_ops->cc_shift;
++      chip->tstamp_cc.mult    = ptp_ops->cc_coeffs->cc_mult;
++      chip->tstamp_cc.shift   = ptp_ops->cc_coeffs->cc_shift;
+       timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc,
+                        ktime_to_ns(ktime_get_real()));
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-dsa-mv88e6xxx-read-cycle-counter-period-from-har.patch b/queue-6.6/net-dsa-mv88e6xxx-read-cycle-counter-period-from-har.patch
new file mode 100644 (file)
index 0000000..68800a1
--- /dev/null
@@ -0,0 +1,188 @@
+From 7793de1e24ce37d1641bc2f1582142cf81f939bf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 20 Oct 2024 14:38:29 +0800
+Subject: net: dsa: mv88e6xxx: read cycle counter period from hardware
+
+From: Shenghao Yang <me@shenghaoyang.info>
+
+[ Upstream commit 7e3c18097a709e9b958e721066e5fe76e563739b ]
+
+Instead of relying on a fixed mapping of hardware family to cycle
+counter frequency, pull this information from the
+MV88E6XXX_TAI_CLOCK_PERIOD register.
+
+This lets us support switches whose cycle counter frequencies depend on
+board design.
+
+Fixes: de776d0d316f ("net: dsa: mv88e6xxx: add support for mv88e6393x family")
+Suggested-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Shenghao Yang <me@shenghaoyang.info>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/mv88e6xxx/chip.h |  2 +-
+ drivers/net/dsa/mv88e6xxx/ptp.c  | 60 ++++++++++++++++++++++----------
+ 2 files changed, 43 insertions(+), 19 deletions(-)
+
+diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
+index bfc3a1040cccd..f02518e93b60d 100644
+--- a/drivers/net/dsa/mv88e6xxx/chip.h
++++ b/drivers/net/dsa/mv88e6xxx/chip.h
+@@ -398,6 +398,7 @@ struct mv88e6xxx_chip {
+       struct cyclecounter     tstamp_cc;
+       struct timecounter      tstamp_tc;
+       struct delayed_work     overflow_work;
++      const struct mv88e6xxx_cc_coeffs *cc_coeffs;
+       struct ptp_clock        *ptp_clock;
+       struct ptp_clock_info   ptp_clock_info;
+@@ -720,7 +721,6 @@ struct mv88e6xxx_ptp_ops {
+       int arr1_sts_reg;
+       int dep_sts_reg;
+       u32 rx_filters;
+-      const struct mv88e6xxx_cc_coeffs *cc_coeffs;
+ };
+ struct mv88e6xxx_pcs_ops {
+diff --git a/drivers/net/dsa/mv88e6xxx/ptp.c b/drivers/net/dsa/mv88e6xxx/ptp.c
+index 4d5498dac1533..a62b4ce7ff61d 100644
+--- a/drivers/net/dsa/mv88e6xxx/ptp.c
++++ b/drivers/net/dsa/mv88e6xxx/ptp.c
+@@ -32,10 +32,10 @@ struct mv88e6xxx_cc_coeffs {
+  * simplifies to
+  * clkadj = scaled_ppm * 2^7 / 5^5
+  */
+-#define MV88E6250_CC_SHIFT 28
+-static const struct mv88e6xxx_cc_coeffs mv88e6250_cc_coeffs = {
+-      .cc_shift = MV88E6250_CC_SHIFT,
+-      .cc_mult = 10 << MV88E6250_CC_SHIFT,
++#define MV88E6XXX_CC_10NS_SHIFT 28
++static const struct mv88e6xxx_cc_coeffs mv88e6xxx_cc_10ns_coeffs = {
++      .cc_shift = MV88E6XXX_CC_10NS_SHIFT,
++      .cc_mult = 10 << MV88E6XXX_CC_10NS_SHIFT,
+       .cc_mult_num = 1 << 7,
+       .cc_mult_dem = 3125ULL,
+ };
+@@ -47,10 +47,10 @@ static const struct mv88e6xxx_cc_coeffs mv88e6250_cc_coeffs = {
+  * simplifies to
+  * clkadj = scaled_ppm * 2^9 / 5^6
+  */
+-#define MV88E6XXX_CC_SHIFT 28
+-static const struct mv88e6xxx_cc_coeffs mv88e6xxx_cc_coeffs = {
+-      .cc_shift = MV88E6XXX_CC_SHIFT,
+-      .cc_mult = 8 << MV88E6XXX_CC_SHIFT,
++#define MV88E6XXX_CC_8NS_SHIFT 28
++static const struct mv88e6xxx_cc_coeffs mv88e6xxx_cc_8ns_coeffs = {
++      .cc_shift = MV88E6XXX_CC_8NS_SHIFT,
++      .cc_mult = 8 << MV88E6XXX_CC_8NS_SHIFT,
+       .cc_mult_num = 1 << 9,
+       .cc_mult_dem = 15625ULL
+ };
+@@ -96,6 +96,31 @@ static int mv88e6352_set_gpio_func(struct mv88e6xxx_chip *chip, int pin,
+       return chip->info->ops->gpio_ops->set_pctl(chip, pin, func);
+ }
++static const struct mv88e6xxx_cc_coeffs *
++mv88e6xxx_cc_coeff_get(struct mv88e6xxx_chip *chip)
++{
++      u16 period_ps;
++      int err;
++
++      err = mv88e6xxx_tai_read(chip, MV88E6XXX_TAI_CLOCK_PERIOD, &period_ps, 1);
++      if (err) {
++              dev_err(chip->dev, "failed to read cycle counter period: %d\n",
++                      err);
++              return ERR_PTR(err);
++      }
++
++      switch (period_ps) {
++      case 8000:
++              return &mv88e6xxx_cc_8ns_coeffs;
++      case 10000:
++              return &mv88e6xxx_cc_10ns_coeffs;
++      default:
++              dev_err(chip->dev, "unexpected cycle counter period of %u ps\n",
++                      period_ps);
++              return ERR_PTR(-ENODEV);
++      }
++}
++
+ static u64 mv88e6352_ptp_clock_read(const struct cyclecounter *cc)
+ {
+       struct mv88e6xxx_chip *chip = cc_to_chip(cc);
+@@ -213,7 +238,6 @@ static void mv88e6352_tai_event_work(struct work_struct *ugly)
+ static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+ {
+       struct mv88e6xxx_chip *chip = ptp_to_chip(ptp);
+-      const struct mv88e6xxx_ptp_ops *ptp_ops = chip->info->ops->ptp_ops;
+       int neg_adj = 0;
+       u32 diff, mult;
+       u64 adj;
+@@ -223,10 +247,10 @@ static int mv88e6xxx_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
+               scaled_ppm = -scaled_ppm;
+       }
+-      mult = ptp_ops->cc_coeffs->cc_mult;
+-      adj = ptp_ops->cc_coeffs->cc_mult_num;
++      mult = chip->cc_coeffs->cc_mult;
++      adj = chip->cc_coeffs->cc_mult_num;
+       adj *= scaled_ppm;
+-      diff = div_u64(adj, ptp_ops->cc_coeffs->cc_mult_dem);
++      diff = div_u64(adj, chip->cc_coeffs->cc_mult_dem);
+       mv88e6xxx_reg_lock(chip);
+@@ -373,7 +397,6 @@ const struct mv88e6xxx_ptp_ops mv88e6165_ptp_ops = {
+               (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
+-      .cc_coeffs = &mv88e6xxx_cc_coeffs
+ };
+ const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {
+@@ -397,7 +420,6 @@ const struct mv88e6xxx_ptp_ops mv88e6250_ptp_ops = {
+               (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
+-      .cc_coeffs = &mv88e6250_cc_coeffs,
+ };
+ const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
+@@ -421,7 +443,6 @@ const struct mv88e6xxx_ptp_ops mv88e6352_ptp_ops = {
+               (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
+-      .cc_coeffs = &mv88e6xxx_cc_coeffs,
+ };
+ const struct mv88e6xxx_ptp_ops mv88e6390_ptp_ops = {
+@@ -446,7 +467,6 @@ const struct mv88e6xxx_ptp_ops mv88e6390_ptp_ops = {
+               (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) |
+               (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ),
+-      .cc_coeffs = &mv88e6xxx_cc_coeffs,
+ };
+ static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
+@@ -481,11 +501,15 @@ int mv88e6xxx_ptp_setup(struct mv88e6xxx_chip *chip)
+       int i;
+       /* Set up the cycle counter */
++      chip->cc_coeffs = mv88e6xxx_cc_coeff_get(chip);
++      if (IS_ERR(chip->cc_coeffs))
++              return PTR_ERR(chip->cc_coeffs);
++
+       memset(&chip->tstamp_cc, 0, sizeof(chip->tstamp_cc));
+       chip->tstamp_cc.read    = mv88e6xxx_ptp_clock_read;
+       chip->tstamp_cc.mask    = CYCLECOUNTER_MASK(32);
+-      chip->tstamp_cc.mult    = ptp_ops->cc_coeffs->cc_mult;
+-      chip->tstamp_cc.shift   = ptp_ops->cc_coeffs->cc_shift;
++      chip->tstamp_cc.mult    = chip->cc_coeffs->cc_mult;
++      chip->tstamp_cc.shift   = chip->cc_coeffs->cc_shift;
+       timecounter_init(&chip->tstamp_tc, &chip->tstamp_cc,
+                        ktime_to_ns(ktime_get_real()));
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-dsa-mv88e6xxx-support-4000ps-cycle-counter-perio.patch b/queue-6.6/net-dsa-mv88e6xxx-support-4000ps-cycle-counter-perio.patch
new file mode 100644 (file)
index 0000000..1e5a6e6
--- /dev/null
@@ -0,0 +1,88 @@
+From e24eda471112c2fbbc13ff5541dd63acddc83a98 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 20 Oct 2024 14:38:30 +0800
+Subject: net: dsa: mv88e6xxx: support 4000ps cycle counter period
+
+From: Shenghao Yang <me@shenghaoyang.info>
+
+[ Upstream commit 3e65ede526cf4f95636dbc835598d100c7668ab3 ]
+
+The MV88E6393X family of devices can run its cycle counter off
+an internal 250MHz clock instead of an external 125MHz one.
+
+Add support for this cycle counter period by adding another set
+of coefficients and lowering the periodic cycle counter read interval
+to compensate for faster overflows at the increased frequency.
+
+Otherwise, the PHC runs at 2x real time in userspace and cannot be
+synchronized.
+
+Fixes: de776d0d316f ("net: dsa: mv88e6xxx: add support for mv88e6393x family")
+Signed-off-by: Shenghao Yang <me@shenghaoyang.info>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/dsa/mv88e6xxx/ptp.c | 23 ++++++++++++++++++++---
+ 1 file changed, 20 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/dsa/mv88e6xxx/ptp.c b/drivers/net/dsa/mv88e6xxx/ptp.c
+index a62b4ce7ff61d..5980bb4ce43e0 100644
+--- a/drivers/net/dsa/mv88e6xxx/ptp.c
++++ b/drivers/net/dsa/mv88e6xxx/ptp.c
+@@ -40,7 +40,7 @@ static const struct mv88e6xxx_cc_coeffs mv88e6xxx_cc_10ns_coeffs = {
+       .cc_mult_dem = 3125ULL,
+ };
+-/* Other families:
++/* Other families except MV88E6393X in internal clock mode:
+  * Raw timestamps are in units of 8-ns clock periods.
+  *
+  * clkadj = scaled_ppm * 8*2^28 / (10^6 * 2^16)
+@@ -55,6 +55,21 @@ static const struct mv88e6xxx_cc_coeffs mv88e6xxx_cc_8ns_coeffs = {
+       .cc_mult_dem = 15625ULL
+ };
++/* Family MV88E6393X using internal clock:
++ * Raw timestamps are in units of 4-ns clock periods.
++ *
++ * clkadj = scaled_ppm * 4*2^28 / (10^6 * 2^16)
++ * simplifies to
++ * clkadj = scaled_ppm * 2^8 / 5^6
++ */
++#define MV88E6XXX_CC_4NS_SHIFT 28
++static const struct mv88e6xxx_cc_coeffs mv88e6xxx_cc_4ns_coeffs = {
++      .cc_shift = MV88E6XXX_CC_4NS_SHIFT,
++      .cc_mult = 4 << MV88E6XXX_CC_4NS_SHIFT,
++      .cc_mult_num = 1 << 8,
++      .cc_mult_dem = 15625ULL
++};
++
+ #define TAI_EVENT_WORK_INTERVAL msecs_to_jiffies(100)
+ #define cc_to_chip(cc) container_of(cc, struct mv88e6xxx_chip, tstamp_cc)
+@@ -110,6 +125,8 @@ mv88e6xxx_cc_coeff_get(struct mv88e6xxx_chip *chip)
+       }
+       switch (period_ps) {
++      case 4000:
++              return &mv88e6xxx_cc_4ns_coeffs;
+       case 8000:
+               return &mv88e6xxx_cc_8ns_coeffs;
+       case 10000:
+@@ -479,10 +496,10 @@ static u64 mv88e6xxx_ptp_clock_read(const struct cyclecounter *cc)
+       return 0;
+ }
+-/* With a 125MHz input clock, the 32-bit timestamp counter overflows in ~34.3
++/* With a 250MHz input clock, the 32-bit timestamp counter overflows in ~17.2
+  * seconds; this task forces periodic reads so that we don't miss any.
+  */
+-#define MV88E6XXX_TAI_OVERFLOW_PERIOD (HZ * 16)
++#define MV88E6XXX_TAI_OVERFLOW_PERIOD (HZ * 8)
+ static void mv88e6xxx_ptp_overflow_check(struct work_struct *work)
+ {
+       struct delayed_work *dw = to_delayed_work(work);
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-fix-races-in-netdev_tx_sent_queue-dev_watchdog.patch b/queue-6.6/net-fix-races-in-netdev_tx_sent_queue-dev_watchdog.patch
new file mode 100644 (file)
index 0000000..41f046e
--- /dev/null
@@ -0,0 +1,118 @@
+From ef2042b8df5bc2848ca6b65cc4f804b13e0cdc38 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Oct 2024 19:41:18 +0000
+Subject: net: fix races in netdev_tx_sent_queue()/dev_watchdog()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 95ecba62e2fd201bcdcca636f5d774f1cd4f1458 ]
+
+Some workloads hit the infamous dev_watchdog() message:
+
+"NETDEV WATCHDOG: eth0 (xxxx): transmit queue XX timed out"
+
+It seems possible to hit this even for perfectly normal
+BQL enabled drivers:
+
+1) Assume a TX queue was idle for more than dev->watchdog_timeo
+   (5 seconds unless changed by the driver)
+
+2) Assume a big packet is sent, exceeding current BQL limit.
+
+3) Driver ndo_start_xmit() puts the packet in TX ring,
+   and netdev_tx_sent_queue() is called.
+
+4) QUEUE_STATE_STACK_XOFF could be set from netdev_tx_sent_queue()
+   before txq->trans_start has been written.
+
+5) txq->trans_start is written later, from netdev_start_xmit()
+
+    if (rc == NETDEV_TX_OK)
+          txq_trans_update(txq)
+
+dev_watchdog() running on another cpu could read the old
+txq->trans_start, and then see QUEUE_STATE_STACK_XOFF, because 5)
+did not happen yet.
+
+To solve the issue, write txq->trans_start right before one XOFF bit
+is set :
+
+- _QUEUE_STATE_DRV_XOFF from netif_tx_stop_queue()
+- __QUEUE_STATE_STACK_XOFF from netdev_tx_sent_queue()
+
+From dev_watchdog(), we have to read txq->state before txq->trans_start.
+
+Add memory barriers to enforce correct ordering.
+
+In the future, we could avoid writing over txq->trans_start for normal
+operations, and rename this field to txq->xoff_start_time.
+
+Fixes: bec251bc8b6a ("net: no longer stop all TX queues in dev_watchdog()")
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Willem de Bruijn <willemb@google.com>
+Reviewed-by: Toke Høiland-Jørgensen <toke@redhat.com>
+Link: https://patch.msgid.link/20241015194118.3951657-1-edumazet@google.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/netdevice.h | 12 ++++++++++++
+ net/sched/sch_generic.c   |  8 +++++++-
+ 2 files changed, 19 insertions(+), 1 deletion(-)
+
+diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
+index 8f5ac20b4c03d..1576e7443eee5 100644
+--- a/include/linux/netdevice.h
++++ b/include/linux/netdevice.h
+@@ -3363,6 +3363,12 @@ static inline void netif_tx_wake_all_queues(struct net_device *dev)
+ static __always_inline void netif_tx_stop_queue(struct netdev_queue *dev_queue)
+ {
++      /* Paired with READ_ONCE() from dev_watchdog() */
++      WRITE_ONCE(dev_queue->trans_start, jiffies);
++
++      /* This barrier is paired with smp_mb() from dev_watchdog() */
++      smp_mb__before_atomic();
++
+       /* Must be an atomic op see netif_txq_try_stop() */
+       set_bit(__QUEUE_STATE_DRV_XOFF, &dev_queue->state);
+ }
+@@ -3479,6 +3485,12 @@ static inline void netdev_tx_sent_queue(struct netdev_queue *dev_queue,
+       if (likely(dql_avail(&dev_queue->dql) >= 0))
+               return;
++      /* Paired with READ_ONCE() from dev_watchdog() */
++      WRITE_ONCE(dev_queue->trans_start, jiffies);
++
++      /* This barrier is paired with smp_mb() from dev_watchdog() */
++      smp_mb__before_atomic();
++
+       set_bit(__QUEUE_STATE_STACK_XOFF, &dev_queue->state);
+       /*
+diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
+index 7f0c8df7b63e0..b51af871a621c 100644
+--- a/net/sched/sch_generic.c
++++ b/net/sched/sch_generic.c
+@@ -511,9 +511,15 @@ static void dev_watchdog(struct timer_list *t)
+                               struct netdev_queue *txq;
+                               txq = netdev_get_tx_queue(dev, i);
+-                              trans_start = READ_ONCE(txq->trans_start);
+                               if (!netif_xmit_stopped(txq))
+                                       continue;
++
++                              /* Paired with WRITE_ONCE() + smp_mb...() in
++                               * netdev_tx_sent_queue() and netif_tx_stop_queue().
++                               */
++                              smp_mb();
++                              trans_start = READ_ONCE(txq->trans_start);
++
+                               if (time_after(jiffies, trans_start + dev->watchdog_timeo)) {
+                                       timedout_ms = jiffies_to_msecs(jiffies - trans_start);
+                                       atomic_long_inc(&txq->trans_timeout);
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-plip-fix-break-causing-plip-to-never-transmit.patch b/queue-6.6/net-plip-fix-break-causing-plip-to-never-transmit.patch
new file mode 100644 (file)
index 0000000..3f37f05
--- /dev/null
@@ -0,0 +1,45 @@
+From f5193e1dc23562bfa27f8fa197d78613a6fe9a1e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Oct 2024 17:16:04 +0200
+Subject: net: plip: fix break; causing plip to never transmit
+
+From: Jakub Boehm <boehm.jakub@gmail.com>
+
+[ Upstream commit f99cf996ba5a315f8b9f13cc21dff0604a0eb749 ]
+
+Since commit
+  71ae2cb30531 ("net: plip: Fix fall-through warnings for Clang")
+
+plip was not able to send any packets, this patch replaces one
+unintended break; with fallthrough; which was originally missed by
+commit 9525d69a3667 ("net: plip: mark expected switch fall-throughs").
+
+I have verified with a real hardware PLIP connection that everything
+works once again after applying this patch.
+
+Fixes: 71ae2cb30531 ("net: plip: Fix fall-through warnings for Clang")
+Signed-off-by: Jakub Boehm <boehm.jakub@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Message-ID: <20241015-net-plip-tx-fix-v1-1-32d8be1c7e0b@gmail.com>
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/plip/plip.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/plip/plip.c b/drivers/net/plip/plip.c
+index 40ce8abe69995..6019811920a44 100644
+--- a/drivers/net/plip/plip.c
++++ b/drivers/net/plip/plip.c
+@@ -815,7 +815,7 @@ plip_send_packet(struct net_device *dev, struct net_local *nl,
+                               return HS_TIMEOUT;
+                       }
+               }
+-              break;
++              fallthrough;
+       case PLIP_PK_LENGTH_LSB:
+               if (plip_send(nibble_timeout, dev,
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-sched-act_api-deny-mismatched-skip_sw-skip_hw-fl.patch b/queue-6.6/net-sched-act_api-deny-mismatched-skip_sw-skip_hw-fl.patch
new file mode 100644 (file)
index 0000000..9fc2577
--- /dev/null
@@ -0,0 +1,135 @@
+From 8ef875b805f8828c722a1d9c332a66276b253e1d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Oct 2024 19:10:48 +0300
+Subject: net/sched: act_api: deny mismatched skip_sw/skip_hw flags for actions
+ created by classifiers
+
+From: Vladimir Oltean <vladimir.oltean@nxp.com>
+
+[ Upstream commit 34d35b4edbbe890a91bec939bfd29ad92517a52b ]
+
+tcf_action_init() has logic for checking mismatches between action and
+filter offload flags (skip_sw/skip_hw). AFAIU, this is intended to run
+on the transition between the new tc_act_bind(flags) returning true (aka
+now gets bound to classifier) and tc_act_bind(act->tcfa_flags) returning
+false (aka action was not bound to classifier before). Otherwise, the
+check is skipped.
+
+For the case where an action is not standalone, but rather it was
+created by a classifier and is bound to it, tcf_action_init() skips the
+check entirely, and this means it allows mismatched flags to occur.
+
+Taking the matchall classifier code path as an example (with mirred as
+an action), the reason is the following:
+
+ 1 | mall_change()
+ 2 | -> mall_replace_hw_filter()
+ 3 |   -> tcf_exts_validate_ex()
+ 4 |      -> flags |= TCA_ACT_FLAGS_BIND;
+ 5 |      -> tcf_action_init()
+ 6 |         -> tcf_action_init_1()
+ 7 |            -> a_o->init()
+ 8 |               -> tcf_mirred_init()
+ 9 |                  -> tcf_idr_create_from_flags()
+10 |                     -> tcf_idr_create()
+11 |                        -> p->tcfa_flags = flags;
+12 |         -> tc_act_bind(flags))
+13 |         -> tc_act_bind(act->tcfa_flags)
+
+When invoked from tcf_exts_validate_ex() like matchall does (but other
+classifiers validate their extensions as well), tcf_action_init() runs
+in a call path where "flags" always contains TCA_ACT_FLAGS_BIND (set by
+line 4). So line 12 is always true, and line 13 is always true as well.
+No transition ever takes place, and the check is skipped.
+
+The code was added in this form in commit c86e0209dc77 ("flow_offload:
+validate flags of filter and actions"), but I'm attributing the blame
+even earlier in that series, to when TCA_ACT_FLAGS_SKIP_HW and
+TCA_ACT_FLAGS_SKIP_SW were added to the UAPI.
+
+Following the development process of this change, the check did not
+always exist in this form. A change took place between v3 [1] and v4 [2],
+AFAIU due to review feedback that it doesn't make sense for action flags
+to be different than classifier flags. I think I agree with that
+feedback, but it was translated into code that omits enforcing this for
+"classic" actions created at the same time with the filters themselves.
+
+There are 3 more important cases to discuss. First there is this command:
+
+$ tc qdisc add dev eth0 clasct
+$ tc filter add dev eth0 ingress matchall skip_sw \
+       action mirred ingress mirror dev eth1
+
+which should be allowed, because prior to the concept of dedicated
+action flags, it used to work and it used to mean the action inherited
+the skip_sw/skip_hw flags from the classifier. It's not a mismatch.
+
+Then we have this command:
+
+$ tc qdisc add dev eth0 clasct
+$ tc filter add dev eth0 ingress matchall skip_sw \
+       action mirred ingress mirror dev eth1 skip_hw
+
+where there is a mismatch and it should be rejected.
+
+Finally, we have:
+
+$ tc qdisc add dev eth0 clasct
+$ tc filter add dev eth0 ingress matchall skip_sw \
+       action mirred ingress mirror dev eth1 skip_sw
+
+where the offload flags coincide, and this should be treated the same as
+the first command based on inheritance, and accepted.
+
+[1]: https://lore.kernel.org/netdev/20211028110646.13791-9-simon.horman@corigine.com/
+[2]: https://lore.kernel.org/netdev/20211118130805.23897-10-simon.horman@corigine.com/
+Fixes: 7adc57651211 ("flow_offload: add skip_hw and skip_sw to control if offload the action")
+Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Ido Schimmel <idosch@nvidia.com>
+Tested-by: Ido Schimmel <idosch@nvidia.com>
+Link: https://patch.msgid.link/20241017161049.3570037-1-vladimir.oltean@nxp.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/act_api.c | 23 ++++++++++++++++++++++-
+ 1 file changed, 22 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/act_api.c b/net/sched/act_api.c
+index 2d6d58e1b278a..4572aa6e0273f 100644
+--- a/net/sched/act_api.c
++++ b/net/sched/act_api.c
+@@ -1489,8 +1489,29 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla,
+                       bool skip_sw = tc_skip_sw(fl_flags);
+                       bool skip_hw = tc_skip_hw(fl_flags);
+-                      if (tc_act_bind(act->tcfa_flags))
++                      if (tc_act_bind(act->tcfa_flags)) {
++                              /* Action is created by classifier and is not
++                               * standalone. Check that the user did not set
++                               * any action flags different than the
++                               * classifier flags, and inherit the flags from
++                               * the classifier for the compatibility case
++                               * where no flags were specified at all.
++                               */
++                              if ((tc_act_skip_sw(act->tcfa_flags) && !skip_sw) ||
++                                  (tc_act_skip_hw(act->tcfa_flags) && !skip_hw)) {
++                                      NL_SET_ERR_MSG(extack,
++                                                     "Mismatch between action and filter offload flags");
++                                      err = -EINVAL;
++                                      goto err;
++                              }
++                              if (skip_sw)
++                                      act->tcfa_flags |= TCA_ACT_FLAGS_SKIP_SW;
++                              if (skip_hw)
++                                      act->tcfa_flags |= TCA_ACT_FLAGS_SKIP_HW;
+                               continue;
++                      }
++
++                      /* Action is standalone */
+                       if (skip_sw != tc_act_skip_sw(act->tcfa_flags) ||
+                           skip_hw != tc_act_skip_hw(act->tcfa_flags)) {
+                               NL_SET_ERR_MSG(extack,
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-sched-adjust-device-watchdog-timer-to-detect-sto.patch b/queue-6.6/net-sched-adjust-device-watchdog-timer-to-detect-sto.patch
new file mode 100644 (file)
index 0000000..330c009
--- /dev/null
@@ -0,0 +1,72 @@
+From 33a37149769132a1d415047a6873798e22a7672e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 8 May 2024 19:06:17 +0530
+Subject: net/sched: adjust device watchdog timer to detect stopped queue at
+ right time
+
+From: Praveen Kumar Kannoju <praveen.kannoju@oracle.com>
+
+[ Upstream commit 33fb988b67050d9bb512f77f08453fa00088943c ]
+
+Applications are sensitive to long network latency, particularly
+heartbeat monitoring ones. Longer the tx timeout recovery higher the
+risk with such applications on a production machines. This patch
+remedies, yet honoring device set tx timeout.
+
+Modify watchdog next timeout to be shorter than the device specified.
+Compute the next timeout be equal to device watchdog timeout less the
+how long ago queue stop had been done. At next watchdog timeout tx
+timeout handler is called into if still in stopped state. Either called
+or not called, restore the watchdog timeout back to device specified.
+
+Signed-off-by: Praveen Kumar Kannoju <praveen.kannoju@oracle.com>
+Link: https://lore.kernel.org/r/20240508133617.4424-1-praveen.kannoju@oracle.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 95ecba62e2fd ("net: fix races in netdev_tx_sent_queue()/dev_watchdog()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_generic.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
+index 6ab9359c1706f..7f0c8df7b63e0 100644
+--- a/net/sched/sch_generic.c
++++ b/net/sched/sch_generic.c
+@@ -505,19 +505,22 @@ static void dev_watchdog(struct timer_list *t)
+                       unsigned int timedout_ms = 0;
+                       unsigned int i;
+                       unsigned long trans_start;
++                      unsigned long oldest_start = jiffies;
+                       for (i = 0; i < dev->num_tx_queues; i++) {
+                               struct netdev_queue *txq;
+                               txq = netdev_get_tx_queue(dev, i);
+                               trans_start = READ_ONCE(txq->trans_start);
+-                              if (netif_xmit_stopped(txq) &&
+-                                  time_after(jiffies, (trans_start +
+-                                                       dev->watchdog_timeo))) {
++                              if (!netif_xmit_stopped(txq))
++                                      continue;
++                              if (time_after(jiffies, trans_start + dev->watchdog_timeo)) {
+                                       timedout_ms = jiffies_to_msecs(jiffies - trans_start);
+                                       atomic_long_inc(&txq->trans_timeout);
+                                       break;
+                               }
++                              if (time_after(oldest_start, trans_start))
++                                      oldest_start = trans_start;
+                       }
+                       if (unlikely(timedout_ms)) {
+@@ -530,7 +533,7 @@ static void dev_watchdog(struct timer_list *t)
+                               netif_unfreeze_queues(dev);
+                       }
+                       if (!mod_timer(&dev->watchdog_timer,
+-                                     round_jiffies(jiffies +
++                                     round_jiffies(oldest_start +
+                                                    dev->watchdog_timeo)))
+                               release = false;
+               }
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-sched-fix-use-after-free-in-taprio_change.patch b/queue-6.6/net-sched-fix-use-after-free-in-taprio_change.patch
new file mode 100644 (file)
index 0000000..fae0d32
--- /dev/null
@@ -0,0 +1,45 @@
+From 7b34a867d65069090fb688001d5034d8a50b5b6d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Oct 2024 08:13:38 +0300
+Subject: net: sched: fix use-after-free in taprio_change()
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit f504465970aebb2467da548f7c1efbbf36d0f44b ]
+
+In 'taprio_change()', 'admin' pointer may become dangling due to sched
+switch / removal caused by 'advance_sched()', and critical section
+protected by 'q->current_entry_lock' is too small to prevent from such
+a scenario (which causes use-after-free detected by KASAN). Fix this
+by prefer 'rcu_replace_pointer()' over 'rcu_assign_pointer()' to update
+'admin' immediately before an attempt to schedule freeing.
+
+Fixes: a3d43c0d56f1 ("taprio: Add support adding an admin schedule")
+Reported-by: syzbot+b65e0af58423fc8a73aa@syzkaller.appspotmail.com
+Closes: https://syzkaller.appspot.com/bug?extid=b65e0af58423fc8a73aa
+Acked-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Link: https://patch.msgid.link/20241018051339.418890-1-dmantipov@yandex.ru
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_taprio.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
+index 87090d6790362..bc8e55c6d63d1 100644
+--- a/net/sched/sch_taprio.c
++++ b/net/sched/sch_taprio.c
+@@ -1988,7 +1988,8 @@ static int taprio_change(struct Qdisc *sch, struct nlattr *opt,
+               taprio_start_sched(sch, start, new_admin);
+-              rcu_assign_pointer(q->admin_sched, new_admin);
++              admin = rcu_replace_pointer(q->admin_sched, new_admin,
++                                          lockdep_rtnl_is_held());
+               if (admin)
+                       call_rcu(&admin->rcu, taprio_free_sched_cb);
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-sched-use-rcu-read-side-critical-section-in-tapr.patch b/queue-6.6/net-sched-use-rcu-read-side-critical-section-in-tapr.patch
new file mode 100644 (file)
index 0000000..590bba4
--- /dev/null
@@ -0,0 +1,155 @@
+From d6f2b7babde7c2d92aab3ebb19760d6e967e0684 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Oct 2024 08:13:39 +0300
+Subject: net: sched: use RCU read-side critical section in taprio_dump()
+
+From: Dmitry Antipov <dmantipov@yandex.ru>
+
+[ Upstream commit b22db8b8befe90b61c98626ca1a2fbb0505e9fe3 ]
+
+Fix possible use-after-free in 'taprio_dump()' by adding RCU
+read-side critical section there. Never seen on x86 but
+found on a KASAN-enabled arm64 system when investigating
+https://syzkaller.appspot.com/bug?extid=b65e0af58423fc8a73aa:
+
+[T15862] BUG: KASAN: slab-use-after-free in taprio_dump+0xa0c/0xbb0
+[T15862] Read of size 4 at addr ffff0000d4bb88f8 by task repro/15862
+[T15862]
+[T15862] CPU: 0 UID: 0 PID: 15862 Comm: repro Not tainted 6.11.0-rc1-00293-gdefaf1a2113a-dirty #2
+[T15862] Hardware name: QEMU QEMU Virtual Machine, BIOS edk2-20240524-5.fc40 05/24/2024
+[T15862] Call trace:
+[T15862]  dump_backtrace+0x20c/0x220
+[T15862]  show_stack+0x2c/0x40
+[T15862]  dump_stack_lvl+0xf8/0x174
+[T15862]  print_report+0x170/0x4d8
+[T15862]  kasan_report+0xb8/0x1d4
+[T15862]  __asan_report_load4_noabort+0x20/0x2c
+[T15862]  taprio_dump+0xa0c/0xbb0
+[T15862]  tc_fill_qdisc+0x540/0x1020
+[T15862]  qdisc_notify.isra.0+0x330/0x3a0
+[T15862]  tc_modify_qdisc+0x7b8/0x1838
+[T15862]  rtnetlink_rcv_msg+0x3c8/0xc20
+[T15862]  netlink_rcv_skb+0x1f8/0x3d4
+[T15862]  rtnetlink_rcv+0x28/0x40
+[T15862]  netlink_unicast+0x51c/0x790
+[T15862]  netlink_sendmsg+0x79c/0xc20
+[T15862]  __sock_sendmsg+0xe0/0x1a0
+[T15862]  ____sys_sendmsg+0x6c0/0x840
+[T15862]  ___sys_sendmsg+0x1ac/0x1f0
+[T15862]  __sys_sendmsg+0x110/0x1d0
+[T15862]  __arm64_sys_sendmsg+0x74/0xb0
+[T15862]  invoke_syscall+0x88/0x2e0
+[T15862]  el0_svc_common.constprop.0+0xe4/0x2a0
+[T15862]  do_el0_svc+0x44/0x60
+[T15862]  el0_svc+0x50/0x184
+[T15862]  el0t_64_sync_handler+0x120/0x12c
+[T15862]  el0t_64_sync+0x190/0x194
+[T15862]
+[T15862] Allocated by task 15857:
+[T15862]  kasan_save_stack+0x3c/0x70
+[T15862]  kasan_save_track+0x20/0x3c
+[T15862]  kasan_save_alloc_info+0x40/0x60
+[T15862]  __kasan_kmalloc+0xd4/0xe0
+[T15862]  __kmalloc_cache_noprof+0x194/0x334
+[T15862]  taprio_change+0x45c/0x2fe0
+[T15862]  tc_modify_qdisc+0x6a8/0x1838
+[T15862]  rtnetlink_rcv_msg+0x3c8/0xc20
+[T15862]  netlink_rcv_skb+0x1f8/0x3d4
+[T15862]  rtnetlink_rcv+0x28/0x40
+[T15862]  netlink_unicast+0x51c/0x790
+[T15862]  netlink_sendmsg+0x79c/0xc20
+[T15862]  __sock_sendmsg+0xe0/0x1a0
+[T15862]  ____sys_sendmsg+0x6c0/0x840
+[T15862]  ___sys_sendmsg+0x1ac/0x1f0
+[T15862]  __sys_sendmsg+0x110/0x1d0
+[T15862]  __arm64_sys_sendmsg+0x74/0xb0
+[T15862]  invoke_syscall+0x88/0x2e0
+[T15862]  el0_svc_common.constprop.0+0xe4/0x2a0
+[T15862]  do_el0_svc+0x44/0x60
+[T15862]  el0_svc+0x50/0x184
+[T15862]  el0t_64_sync_handler+0x120/0x12c
+[T15862]  el0t_64_sync+0x190/0x194
+[T15862]
+[T15862] Freed by task 6192:
+[T15862]  kasan_save_stack+0x3c/0x70
+[T15862]  kasan_save_track+0x20/0x3c
+[T15862]  kasan_save_free_info+0x4c/0x80
+[T15862]  poison_slab_object+0x110/0x160
+[T15862]  __kasan_slab_free+0x3c/0x74
+[T15862]  kfree+0x134/0x3c0
+[T15862]  taprio_free_sched_cb+0x18c/0x220
+[T15862]  rcu_core+0x920/0x1b7c
+[T15862]  rcu_core_si+0x10/0x1c
+[T15862]  handle_softirqs+0x2e8/0xd64
+[T15862]  __do_softirq+0x14/0x20
+
+Fixes: 18cdd2f0998a ("net/sched: taprio: taprio_dump and taprio_change are protected by rtnl_mutex")
+Acked-by: Vinicius Costa Gomes <vinicius.gomes@intel.com>
+Signed-off-by: Dmitry Antipov <dmantipov@yandex.ru>
+Link: https://patch.msgid.link/20241018051339.418890-2-dmantipov@yandex.ru
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/sched/sch_taprio.c | 18 ++++++++++++------
+ 1 file changed, 12 insertions(+), 6 deletions(-)
+
+diff --git a/net/sched/sch_taprio.c b/net/sched/sch_taprio.c
+index bc8e55c6d63d1..951a87909c297 100644
+--- a/net/sched/sch_taprio.c
++++ b/net/sched/sch_taprio.c
+@@ -2397,9 +2397,6 @@ static int taprio_dump(struct Qdisc *sch, struct sk_buff *skb)
+       struct tc_mqprio_qopt opt = { 0 };
+       struct nlattr *nest, *sched_nest;
+-      oper = rtnl_dereference(q->oper_sched);
+-      admin = rtnl_dereference(q->admin_sched);
+-
+       mqprio_qopt_reconstruct(dev, &opt);
+       nest = nla_nest_start_noflag(skb, TCA_OPTIONS);
+@@ -2420,18 +2417,23 @@ static int taprio_dump(struct Qdisc *sch, struct sk_buff *skb)
+           nla_put_u32(skb, TCA_TAPRIO_ATTR_TXTIME_DELAY, q->txtime_delay))
+               goto options_error;
++      rcu_read_lock();
++
++      oper = rtnl_dereference(q->oper_sched);
++      admin = rtnl_dereference(q->admin_sched);
++
+       if (oper && taprio_dump_tc_entries(skb, q, oper))
+-              goto options_error;
++              goto options_error_rcu;
+       if (oper && dump_schedule(skb, oper))
+-              goto options_error;
++              goto options_error_rcu;
+       if (!admin)
+               goto done;
+       sched_nest = nla_nest_start_noflag(skb, TCA_TAPRIO_ATTR_ADMIN_SCHED);
+       if (!sched_nest)
+-              goto options_error;
++              goto options_error_rcu;
+       if (dump_schedule(skb, admin))
+               goto admin_error;
+@@ -2439,11 +2441,15 @@ static int taprio_dump(struct Qdisc *sch, struct sk_buff *skb)
+       nla_nest_end(skb, sched_nest);
+ done:
++      rcu_read_unlock();
+       return nla_nest_end(skb, nest);
+ admin_error:
+       nla_nest_cancel(skb, sched_nest);
++options_error_rcu:
++      rcu_read_unlock();
++
+ options_error:
+       nla_nest_cancel(skb, nest);
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-sun3_82586-fix-potential-memory-leak-in-sun3_825.patch b/queue-6.6/net-sun3_82586-fix-potential-memory-leak-in-sun3_825.patch
new file mode 100644 (file)
index 0000000..993d46d
--- /dev/null
@@ -0,0 +1,37 @@
+From 3cccc08d8c4ffb882681823d794e035c54d6b8d6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Oct 2024 22:41:48 +0800
+Subject: net/sun3_82586: fix potential memory leak in sun3_82586_send_packet()
+
+From: Wang Hai <wanghai38@huawei.com>
+
+[ Upstream commit 2cb3f56e827abb22c4168ad0c1bbbf401bb2f3b8 ]
+
+The sun3_82586_send_packet() returns NETDEV_TX_OK without freeing skb
+in case of skb->len being too long, add dev_kfree_skb() to fix it.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Wang Hai <wanghai38@huawei.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Message-ID: <20241015144148.7918-1-wanghai38@huawei.com>
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/i825xx/sun3_82586.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/drivers/net/ethernet/i825xx/sun3_82586.c b/drivers/net/ethernet/i825xx/sun3_82586.c
+index f2d4669c81cf2..58a3d28d938c3 100644
+--- a/drivers/net/ethernet/i825xx/sun3_82586.c
++++ b/drivers/net/ethernet/i825xx/sun3_82586.c
+@@ -1012,6 +1012,7 @@ sun3_82586_send_packet(struct sk_buff *skb, struct net_device *dev)
+       if(skb->len > XMIT_BUFF_SIZE)
+       {
+               printk("%s: Sorry, max. framelength is %d bytes. The length of your frame is %d bytes.\n",dev->name,XMIT_BUFF_SIZE,skb->len);
++              dev_kfree_skb(skb);
+               return NETDEV_TX_OK;
+       }
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-usb-usbnet-fix-name-regression.patch b/queue-6.6/net-usb-usbnet-fix-name-regression.patch
new file mode 100644 (file)
index 0000000..10972e0
--- /dev/null
@@ -0,0 +1,46 @@
+From 3b24a9e8927d866acc72110550d5c51f65a5ef19 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Oct 2024 09:18:37 +0200
+Subject: net: usb: usbnet: fix name regression
+
+From: Oliver Neukum <oneukum@suse.com>
+
+[ Upstream commit 8a7d12d674ac6f2147c18f36d1e15f1a48060edf ]
+
+The fix for MAC addresses broke detection of the naming convention
+because it gave network devices no random MAC before bind()
+was called. This means that the check for the local assignment bit
+was always negative as the address was zeroed from allocation,
+instead of from overwriting the MAC with a unique hardware address.
+
+The correct check for whether bind() has altered the MAC is
+done with is_zero_ether_addr
+
+Signed-off-by: Oliver Neukum <oneukum@suse.com>
+Reported-by: Greg Thelen <gthelen@google.com>
+Diagnosed-by: John Sperbeck <jsperbeck@google.com>
+Fixes: bab8eb0dd4cb9 ("usbnet: modern method to get random MAC")
+Link: https://patch.msgid.link/20241017071849.389636-1-oneukum@suse.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/usbnet.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
+index 4f5a3a4aac89e..9f66c47dc58bc 100644
+--- a/drivers/net/usb/usbnet.c
++++ b/drivers/net/usb/usbnet.c
+@@ -1771,7 +1771,8 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
+               // can rename the link if it knows better.
+               if ((dev->driver_info->flags & FLAG_ETHER) != 0 &&
+                   ((dev->driver_info->flags & FLAG_POINTTOPOINT) == 0 ||
+-                   (net->dev_addr [0] & 0x02) == 0))
++                   /* somebody touched it*/
++                   !is_zero_ether_addr(net->dev_addr)))
+                       strscpy(net->name, "eth%d", sizeof(net->name));
+               /* WLAN devices should always be named "wlan%d" */
+               if ((dev->driver_info->flags & FLAG_WLAN) != 0)
+-- 
+2.43.0
+
diff --git a/queue-6.6/net-wwan-fix-global-oob-in-wwan_rtnl_policy.patch b/queue-6.6/net-wwan-fix-global-oob-in-wwan_rtnl_policy.patch
new file mode 100644 (file)
index 0000000..45c3fbb
--- /dev/null
@@ -0,0 +1,107 @@
+From 13b6fb4c66ae798080fcea1a6b585034030fb0f1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 15 Oct 2024 21:16:21 +0800
+Subject: net: wwan: fix global oob in wwan_rtnl_policy
+
+From: Lin Ma <linma@zju.edu.cn>
+
+[ Upstream commit 47dd5447cab8ce30a847a0337d5341ae4c7476a7 ]
+
+The variable wwan_rtnl_link_ops assign a *bigger* maxtype which leads to
+a global out-of-bounds read when parsing the netlink attributes. Exactly
+same bug cause as the oob fixed in commit b33fb5b801c6 ("net: qualcomm:
+rmnet: fix global oob in rmnet_policy").
+
+==================================================================
+BUG: KASAN: global-out-of-bounds in validate_nla lib/nlattr.c:388 [inline]
+BUG: KASAN: global-out-of-bounds in __nla_validate_parse+0x19d7/0x29a0 lib/nlattr.c:603
+Read of size 1 at addr ffffffff8b09cb60 by task syz.1.66276/323862
+
+CPU: 0 PID: 323862 Comm: syz.1.66276 Not tainted 6.1.70 #1
+Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014
+Call Trace:
+ <TASK>
+ __dump_stack lib/dump_stack.c:88 [inline]
+ dump_stack_lvl+0x177/0x231 lib/dump_stack.c:106
+ print_address_description mm/kasan/report.c:284 [inline]
+ print_report+0x14f/0x750 mm/kasan/report.c:395
+ kasan_report+0x139/0x170 mm/kasan/report.c:495
+ validate_nla lib/nlattr.c:388 [inline]
+ __nla_validate_parse+0x19d7/0x29a0 lib/nlattr.c:603
+ __nla_parse+0x3c/0x50 lib/nlattr.c:700
+ nla_parse_nested_deprecated include/net/netlink.h:1269 [inline]
+ __rtnl_newlink net/core/rtnetlink.c:3514 [inline]
+ rtnl_newlink+0x7bc/0x1fd0 net/core/rtnetlink.c:3623
+ rtnetlink_rcv_msg+0x794/0xef0 net/core/rtnetlink.c:6122
+ netlink_rcv_skb+0x1de/0x420 net/netlink/af_netlink.c:2508
+ netlink_unicast_kernel net/netlink/af_netlink.c:1326 [inline]
+ netlink_unicast+0x74b/0x8c0 net/netlink/af_netlink.c:1352
+ netlink_sendmsg+0x882/0xb90 net/netlink/af_netlink.c:1874
+ sock_sendmsg_nosec net/socket.c:716 [inline]
+ __sock_sendmsg net/socket.c:728 [inline]
+ ____sys_sendmsg+0x5cc/0x8f0 net/socket.c:2499
+ ___sys_sendmsg+0x21c/0x290 net/socket.c:2553
+ __sys_sendmsg net/socket.c:2582 [inline]
+ __do_sys_sendmsg net/socket.c:2591 [inline]
+ __se_sys_sendmsg+0x19e/0x270 net/socket.c:2589
+ do_syscall_x64 arch/x86/entry/common.c:51 [inline]
+ do_syscall_64+0x45/0x90 arch/x86/entry/common.c:81
+ entry_SYSCALL_64_after_hwframe+0x63/0xcd
+RIP: 0033:0x7f67b19a24ad
+RSP: 002b:00007f67b17febb8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e
+RAX: ffffffffffffffda RBX: 00007f67b1b45f80 RCX: 00007f67b19a24ad
+RDX: 0000000000000000 RSI: 0000000020005e40 RDI: 0000000000000004
+RBP: 00007f67b1a1e01d R08: 0000000000000000 R09: 0000000000000000
+R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+R13: 00007ffd2513764f R14: 00007ffd251376e0 R15: 00007f67b17fed40
+ </TASK>
+
+The buggy address belongs to the variable:
+ wwan_rtnl_policy+0x20/0x40
+
+The buggy address belongs to the physical page:
+page:ffffea00002c2700 refcount:1 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0xb09c
+flags: 0xfff00000001000(reserved|node=0|zone=1|lastcpupid=0x7ff)
+raw: 00fff00000001000 ffffea00002c2708 ffffea00002c2708 0000000000000000
+raw: 0000000000000000 0000000000000000 00000001ffffffff 0000000000000000
+page dumped because: kasan: bad access detected
+page_owner info is not present (never set?)
+
+Memory state around the buggy address:
+ ffffffff8b09ca00: 05 f9 f9 f9 05 f9 f9 f9 00 01 f9 f9 00 01 f9 f9
+ ffffffff8b09ca80: 00 00 00 05 f9 f9 f9 f9 00 00 03 f9 f9 f9 f9 f9
+>ffffffff8b09cb00: 00 00 00 00 05 f9 f9 f9 00 00 00 00 f9 f9 f9 f9
+                                                       ^
+ ffffffff8b09cb80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+==================================================================
+
+According to the comment of `nla_parse_nested_deprecated`, use correct size
+`IFLA_WWAN_MAX` here to fix this issue.
+
+Fixes: 88b710532e53 ("wwan: add interface creation support")
+Signed-off-by: Lin Ma <linma@zju.edu.cn>
+Reviewed-by: Loic Poulain <loic.poulain@linaro.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20241015131621.47503-1-linma@zju.edu.cn
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wwan/wwan_core.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/wwan/wwan_core.c b/drivers/net/wwan/wwan_core.c
+index 284ab1f56391a..45ed3afc443df 100644
+--- a/drivers/net/wwan/wwan_core.c
++++ b/drivers/net/wwan/wwan_core.c
+@@ -1031,7 +1031,7 @@ static const struct nla_policy wwan_rtnl_policy[IFLA_WWAN_MAX + 1] = {
+ static struct rtnl_link_ops wwan_rtnl_link_ops __read_mostly = {
+       .kind = "wwan",
+-      .maxtype = __IFLA_WWAN_MAX,
++      .maxtype = IFLA_WWAN_MAX,
+       .alloc = wwan_rtnl_alloc,
+       .validate = wwan_rtnl_validate,
+       .newlink = wwan_rtnl_newlink,
+-- 
+2.43.0
+
diff --git a/queue-6.6/netfilter-bpf-must-hold-reference-on-net-namespace.patch b/queue-6.6/netfilter-bpf-must-hold-reference-on-net-namespace.patch
new file mode 100644 (file)
index 0000000..4f178d9
--- /dev/null
@@ -0,0 +1,72 @@
+From 273be4ceb2ca5d9a2e2f72351181f37cad162ea4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Oct 2024 18:34:05 +0200
+Subject: netfilter: bpf: must hold reference on net namespace
+
+From: Florian Westphal <fw@strlen.de>
+
+[ Upstream commit 1230fe7ad3974f7bf6c78901473e039b34d4fb1f ]
+
+BUG: KASAN: slab-use-after-free in __nf_unregister_net_hook+0x640/0x6b0
+Read of size 8 at addr ffff8880106fe400 by task repro/72=
+bpf_nf_link_release+0xda/0x1e0
+bpf_link_free+0x139/0x2d0
+bpf_link_release+0x68/0x80
+__fput+0x414/0xb60
+
+Eric says:
+ It seems that bpf was able to defer the __nf_unregister_net_hook()
+ after exit()/close() time.
+ Perhaps a netns reference is missing, because the netns has been
+ dismantled/freed already.
+ bpf_nf_link_attach() does :
+ link->net = net;
+ But I do not see a reference being taken on net.
+
+Add such a reference and release it after hook unreg.
+Note that I was unable to get syzbot reproducer to work, so I
+do not know if this resolves this splat.
+
+Fixes: 84601d6ee68a ("bpf: add bpf_link support for BPF_NETFILTER programs")
+Diagnosed-by: Eric Dumazet <edumazet@google.com>
+Reported-by: Lai, Yi <yi1.lai@linux.intel.com>
+Signed-off-by: Florian Westphal <fw@strlen.de>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/nf_bpf_link.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/net/netfilter/nf_bpf_link.c b/net/netfilter/nf_bpf_link.c
+index 96015a59db09e..2aad0562a4135 100644
+--- a/net/netfilter/nf_bpf_link.c
++++ b/net/netfilter/nf_bpf_link.c
+@@ -23,6 +23,7 @@ static unsigned int nf_hook_run_bpf(void *bpf_prog, struct sk_buff *skb,
+ struct bpf_nf_link {
+       struct bpf_link link;
+       struct nf_hook_ops hook_ops;
++      netns_tracker ns_tracker;
+       struct net *net;
+       u32 dead;
+       const struct nf_defrag_hook *defrag_hook;
+@@ -120,6 +121,7 @@ static void bpf_nf_link_release(struct bpf_link *link)
+       if (!cmpxchg(&nf_link->dead, 0, 1)) {
+               nf_unregister_net_hook(nf_link->net, &nf_link->hook_ops);
+               bpf_nf_disable_defrag(nf_link);
++              put_net_track(nf_link->net, &nf_link->ns_tracker);
+       }
+ }
+@@ -258,6 +260,8 @@ int bpf_nf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
+               return err;
+       }
++      get_net_track(net, &link->ns_tracker, GFP_KERNEL);
++
+       return bpf_link_settle(&link_primer);
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/netfilter-xtables-fix-typo-causing-some-targets-not-.patch b/queue-6.6/netfilter-xtables-fix-typo-causing-some-targets-not-.patch
new file mode 100644 (file)
index 0000000..bd10feb
--- /dev/null
@@ -0,0 +1,74 @@
+From 12a6ba687e2ec2679db8cf0be527b814fe08b39a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 20 Oct 2024 14:49:51 +0200
+Subject: netfilter: xtables: fix typo causing some targets not to load on IPv6
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Pablo Neira Ayuso <pablo@netfilter.org>
+
+[ Upstream commit 306ed1728e8438caed30332e1ab46b28c25fe3d8 ]
+
+- There is no NFPROTO_IPV6 family for mark and NFLOG.
+- TRACE is also missing module autoload with NFPROTO_IPV6.
+
+This results in ip6tables failing to restore a ruleset. This issue has been
+reported by several users providing incomplete patches.
+
+Very similar to Ilya Katsnelson's patch including a missing chunk in the
+TRACE extension.
+
+Fixes: 0bfcb7b71e73 ("netfilter: xtables: avoid NFPROTO_UNSPEC where needed")
+Reported-by: Ignat Korchagin <ignat@cloudflare.com>
+Reported-by: Ilya Katsnelson <me@0upti.me>
+Reported-by: Krzysztof OlÄ™dzki <ole@ans.pl>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/netfilter/xt_NFLOG.c | 2 +-
+ net/netfilter/xt_TRACE.c | 1 +
+ net/netfilter/xt_mark.c  | 2 +-
+ 3 files changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/netfilter/xt_NFLOG.c b/net/netfilter/xt_NFLOG.c
+index d80abd6ccaf8f..6dcf4bc7e30b2 100644
+--- a/net/netfilter/xt_NFLOG.c
++++ b/net/netfilter/xt_NFLOG.c
+@@ -79,7 +79,7 @@ static struct xt_target nflog_tg_reg[] __read_mostly = {
+       {
+               .name       = "NFLOG",
+               .revision   = 0,
+-              .family     = NFPROTO_IPV4,
++              .family     = NFPROTO_IPV6,
+               .checkentry = nflog_tg_check,
+               .destroy    = nflog_tg_destroy,
+               .target     = nflog_tg,
+diff --git a/net/netfilter/xt_TRACE.c b/net/netfilter/xt_TRACE.c
+index f3fa4f11348cd..a642ff09fc8e8 100644
+--- a/net/netfilter/xt_TRACE.c
++++ b/net/netfilter/xt_TRACE.c
+@@ -49,6 +49,7 @@ static struct xt_target trace_tg_reg[] __read_mostly = {
+               .target         = trace_tg,
+               .checkentry     = trace_tg_check,
+               .destroy        = trace_tg_destroy,
++              .me             = THIS_MODULE,
+       },
+ #endif
+ };
+diff --git a/net/netfilter/xt_mark.c b/net/netfilter/xt_mark.c
+index f76fe04fc9a4e..65b965ca40ea7 100644
+--- a/net/netfilter/xt_mark.c
++++ b/net/netfilter/xt_mark.c
+@@ -62,7 +62,7 @@ static struct xt_target mark_tg_reg[] __read_mostly = {
+       {
+               .name           = "MARK",
+               .revision       = 2,
+-              .family         = NFPROTO_IPV4,
++              .family         = NFPROTO_IPV6,
+               .target         = mark_tg,
+               .targetsize     = sizeof(struct xt_mark_tginfo2),
+               .me             = THIS_MODULE,
+-- 
+2.43.0
+
diff --git a/queue-6.6/octeon_ep-add-skb-allocation-failures-handling-in-__.patch b/queue-6.6/octeon_ep-add-skb-allocation-failures-handling-in-__.patch
new file mode 100644 (file)
index 0000000..28c8826
--- /dev/null
@@ -0,0 +1,84 @@
+From 770f4785a39d489a7a88f794a191aca890e85189 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Oct 2024 13:06:51 +0300
+Subject: octeon_ep: Add SKB allocation failures handling in
+ __octep_oq_process_rx()
+
+From: Aleksandr Mishin <amishin@t-argos.ru>
+
+[ Upstream commit eb592008f79be52ccef88cd9a5249b3fc0367278 ]
+
+build_skb() returns NULL in case of a memory allocation failure so handle
+it inside __octep_oq_process_rx() to avoid NULL pointer dereference.
+
+__octep_oq_process_rx() is called during NAPI polling by the driver. If
+skb allocation fails, keep on pulling packets out of the Rx DMA queue: we
+shouldn't break the polling immediately and thus falsely indicate to the
+octep_napi_poll() that the Rx pressure is going down. As there is no
+associated skb in this case, don't process the packets and don't push them
+up the network stack - they are skipped.
+
+Helper function is implemented to unmmap/flush all the fragment buffers
+used by the dropped packet. 'alloc_failures' counter is incremented to
+mark the skb allocation error in driver statistics.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Fixes: 37d79d059606 ("octeon_ep: add Tx/Rx processing and interrupt support")
+Suggested-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Aleksandr Mishin <amishin@t-argos.ru>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/marvell/octeon_ep/octep_rx.c | 27 +++++++++++++++++++
+ 1 file changed, 27 insertions(+)
+
+diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
+index cfbfad95b0211..c7f4e3c058b7f 100644
+--- a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
+@@ -360,6 +360,27 @@ static void octep_oq_next_pkt(struct octep_oq *oq,
+               *read_idx = 0;
+ }
++/**
++ * octep_oq_drop_rx() - Free the resources associated with a packet.
++ *
++ * @oq: Octeon Rx queue data structure.
++ * @buff_info: Current packet buffer info.
++ * @read_idx: Current packet index in the ring.
++ * @desc_used: Current packet descriptor number.
++ *
++ */
++static void octep_oq_drop_rx(struct octep_oq *oq,
++                           struct octep_rx_buffer *buff_info,
++                           u32 *read_idx, u32 *desc_used)
++{
++      int data_len = buff_info->len - oq->max_single_buffer_size;
++
++      while (data_len > 0) {
++              octep_oq_next_pkt(oq, buff_info, read_idx, desc_used);
++              data_len -= oq->buffer_size;
++      };
++}
++
+ /**
+  * __octep_oq_process_rx() - Process hardware Rx queue and push to stack.
+  *
+@@ -415,6 +436,12 @@ static int __octep_oq_process_rx(struct octep_device *oct,
+               octep_oq_next_pkt(oq, buff_info, &read_idx, &desc_used);
+               skb = build_skb((void *)resp_hw, PAGE_SIZE);
++              if (!skb) {
++                      octep_oq_drop_rx(oq, buff_info,
++                                       &read_idx, &desc_used);
++                      oq->stats.alloc_failures++;
++                      continue;
++              }
+               skb_reserve(skb, data_offset);
+               rx_bytes += buff_info->len;
+-- 
+2.43.0
+
diff --git a/queue-6.6/octeon_ep-implement-helper-for-iterating-packets-in-.patch b/queue-6.6/octeon_ep-implement-helper-for-iterating-packets-in-.patch
new file mode 100644 (file)
index 0000000..2e9c8d4
--- /dev/null
@@ -0,0 +1,132 @@
+From c4f8e8411684feba349ea11582b035afdb0677a1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 17 Oct 2024 13:06:50 +0300
+Subject: octeon_ep: Implement helper for iterating packets in Rx queue
+
+From: Aleksandr Mishin <amishin@t-argos.ru>
+
+[ Upstream commit bd28df26197b2bd0913bf1b36770836481975143 ]
+
+The common code with some packet and index manipulations is extracted and
+moved to newly implemented helper to make the code more readable and avoid
+duplication. This is a preparation for skb allocation failure handling.
+
+Found by Linux Verification Center (linuxtesting.org) with SVACE.
+
+Suggested-by: Simon Horman <horms@kernel.org>
+Suggested-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Aleksandr Mishin <amishin@t-argos.ru>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Signed-off-by: Andrew Lunn <andrew@lunn.ch>
+Stable-dep-of: eb592008f79b ("octeon_ep: Add SKB allocation failures handling in __octep_oq_process_rx()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../net/ethernet/marvell/octeon_ep/octep_rx.c | 55 +++++++++++--------
+ 1 file changed, 32 insertions(+), 23 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
+index 3c43f80785285..cfbfad95b0211 100644
+--- a/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
++++ b/drivers/net/ethernet/marvell/octeon_ep/octep_rx.c
+@@ -336,6 +336,30 @@ static int octep_oq_check_hw_for_pkts(struct octep_device *oct,
+       return new_pkts;
+ }
++/**
++ * octep_oq_next_pkt() - Move to the next packet in Rx queue.
++ *
++ * @oq: Octeon Rx queue data structure.
++ * @buff_info: Current packet buffer info.
++ * @read_idx: Current packet index in the ring.
++ * @desc_used: Current packet descriptor number.
++ *
++ * Free the resources associated with a packet.
++ * Increment packet index in the ring and packet descriptor number.
++ */
++static void octep_oq_next_pkt(struct octep_oq *oq,
++                            struct octep_rx_buffer *buff_info,
++                            u32 *read_idx, u32 *desc_used)
++{
++      dma_unmap_page(oq->dev, oq->desc_ring[*read_idx].buffer_ptr,
++                     PAGE_SIZE, DMA_FROM_DEVICE);
++      buff_info->page = NULL;
++      (*read_idx)++;
++      (*desc_used)++;
++      if (*read_idx == oq->max_count)
++              *read_idx = 0;
++}
++
+ /**
+  * __octep_oq_process_rx() - Process hardware Rx queue and push to stack.
+  *
+@@ -365,10 +389,7 @@ static int __octep_oq_process_rx(struct octep_device *oct,
+       desc_used = 0;
+       for (pkt = 0; pkt < pkts_to_process; pkt++) {
+               buff_info = (struct octep_rx_buffer *)&oq->buff_info[read_idx];
+-              dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
+-                             PAGE_SIZE, DMA_FROM_DEVICE);
+               resp_hw = page_address(buff_info->page);
+-              buff_info->page = NULL;
+               /* Swap the length field that is in Big-Endian to CPU */
+               buff_info->len = be64_to_cpu(resp_hw->length);
+@@ -390,36 +411,27 @@ static int __octep_oq_process_rx(struct octep_device *oct,
+                        */
+                       data_offset = OCTEP_OQ_RESP_HW_SIZE;
+               }
++
++              octep_oq_next_pkt(oq, buff_info, &read_idx, &desc_used);
++
++              skb = build_skb((void *)resp_hw, PAGE_SIZE);
++              skb_reserve(skb, data_offset);
++
+               rx_bytes += buff_info->len;
+               if (buff_info->len <= oq->max_single_buffer_size) {
+-                      skb = build_skb((void *)resp_hw, PAGE_SIZE);
+-                      skb_reserve(skb, data_offset);
+                       skb_put(skb, buff_info->len);
+-                      read_idx++;
+-                      desc_used++;
+-                      if (read_idx == oq->max_count)
+-                              read_idx = 0;
+               } else {
+                       struct skb_shared_info *shinfo;
+                       u16 data_len;
+-                      skb = build_skb((void *)resp_hw, PAGE_SIZE);
+-                      skb_reserve(skb, data_offset);
+                       /* Head fragment includes response header(s);
+                        * subsequent fragments contains only data.
+                        */
+                       skb_put(skb, oq->max_single_buffer_size);
+-                      read_idx++;
+-                      desc_used++;
+-                      if (read_idx == oq->max_count)
+-                              read_idx = 0;
+-
+                       shinfo = skb_shinfo(skb);
+                       data_len = buff_info->len - oq->max_single_buffer_size;
+                       while (data_len) {
+-                              dma_unmap_page(oq->dev, oq->desc_ring[read_idx].buffer_ptr,
+-                                             PAGE_SIZE, DMA_FROM_DEVICE);
+                               buff_info = (struct octep_rx_buffer *)
+                                           &oq->buff_info[read_idx];
+                               if (data_len < oq->buffer_size) {
+@@ -434,11 +446,8 @@ static int __octep_oq_process_rx(struct octep_device *oct,
+                                               buff_info->page, 0,
+                                               buff_info->len,
+                                               buff_info->len);
+-                              buff_info->page = NULL;
+-                              read_idx++;
+-                              desc_used++;
+-                              if (read_idx == oq->max_count)
+-                                      read_idx = 0;
++
++                              octep_oq_next_pkt(oq, buff_info, &read_idx, &desc_used);
+                       }
+               }
+-- 
+2.43.0
+
diff --git a/queue-6.6/posix-clock-posix-clock-fix-unbalanced-locking-in-pc.patch b/queue-6.6/posix-clock-posix-clock-fix-unbalanced-locking-in-pc.patch
new file mode 100644 (file)
index 0000000..4066c0d
--- /dev/null
@@ -0,0 +1,58 @@
+From 7987f7b7e055ed8f38eafc47973fdd90a70f5436 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Oct 2024 18:07:48 +0800
+Subject: posix-clock: posix-clock: Fix unbalanced locking in
+ pc_clock_settime()
+
+From: Jinjie Ruan <ruanjinjie@huawei.com>
+
+[ Upstream commit 6e62807c7fbb3c758d233018caf94dfea9c65dbd ]
+
+If get_clock_desc() succeeds, it calls fget() for the clockid's fd,
+and get the clk->rwsem read lock, so the error path should release
+the lock to make the lock balance and fput the clockid's fd to make
+the refcount balance and release the fd related resource.
+
+However the below commit left the error path locked behind resulting in
+unbalanced locking. Check timespec64_valid_strict() before
+get_clock_desc() to fix it, because the "ts" is not changed
+after that.
+
+Fixes: d8794ac20a29 ("posix-clock: Fix missing timespec64 check in pc_clock_settime()")
+Acked-by: Richard Cochran <richardcochran@gmail.com>
+Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
+Acked-by: Anna-Maria Behnsen <anna-maria@linutronix.de>
+[pabeni@redhat.com: fixed commit message typo]
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/posix-clock.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/time/posix-clock.c b/kernel/time/posix-clock.c
+index 8127673bfc45e..05e73d209aa87 100644
+--- a/kernel/time/posix-clock.c
++++ b/kernel/time/posix-clock.c
+@@ -290,6 +290,9 @@ static int pc_clock_settime(clockid_t id, const struct timespec64 *ts)
+       struct posix_clock_desc cd;
+       int err;
++      if (!timespec64_valid_strict(ts))
++              return -EINVAL;
++
+       err = get_clock_desc(id, &cd);
+       if (err)
+               return err;
+@@ -299,9 +302,6 @@ static int pc_clock_settime(clockid_t id, const struct timespec64 *ts)
+               goto out;
+       }
+-      if (!timespec64_valid_strict(ts))
+-              return -EINVAL;
+-
+       if (cd.clk->ops.clock_settime)
+               err = cd.clk->ops.clock_settime(cd.clk, ts);
+       else
+-- 
+2.43.0
+
diff --git a/queue-6.6/r8169-avoid-unsolicited-interrupts.patch b/queue-6.6/r8169-avoid-unsolicited-interrupts.patch
new file mode 100644 (file)
index 0000000..91e3adc
--- /dev/null
@@ -0,0 +1,49 @@
+From e3db6f73fc531a0bd84bc0b3e81b65a9ea8b768d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 18 Oct 2024 11:08:16 +0200
+Subject: r8169: avoid unsolicited interrupts
+
+From: Heiner Kallweit <hkallweit1@gmail.com>
+
+[ Upstream commit 10ce0db787004875f4dba068ea952207d1d8abeb ]
+
+It was reported that after resume from suspend a PCI error is logged
+and connectivity is broken. Error message is:
+PCI error (cmd = 0x0407, status_errs = 0x0000)
+The message seems to be a red herring as none of the error bits is set,
+and the PCI command register value also is normal. Exception handling
+for a PCI error includes a chip reset what apparently brakes connectivity
+here. The interrupt status bit triggering the PCI error handling isn't
+actually used on PCIe chip versions, so it's not clear why this bit is
+set by the chip. Fix this by ignoring this bit on PCIe chip versions.
+
+Fixes: 0e4851502f84 ("r8169: merge with version 8.001.00 of Realtek's r8168 driver")
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219388
+Tested-by: Atlas Yu <atlas.yu@canonical.com>
+Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/78e2f535-438f-4212-ad94-a77637ac6c9c@gmail.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/realtek/r8169_main.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
+index b499d8ea6d216..6856eb602f826 100644
+--- a/drivers/net/ethernet/realtek/r8169_main.c
++++ b/drivers/net/ethernet/realtek/r8169_main.c
+@@ -4576,7 +4576,9 @@ static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance)
+       if ((status & 0xffff) == 0xffff || !(status & tp->irq_mask))
+               return IRQ_NONE;
+-      if (unlikely(status & SYSErr)) {
++      /* At least RTL8168fp may unexpectedly set the SYSErr bit */
++      if (unlikely(status & SYSErr &&
++          tp->mac_version <= RTL_GIGA_MAC_VER_06)) {
+               rtl8169_pcierr_interrupt(tp->dev);
+               goto out;
+       }
+-- 
+2.43.0
+
index eac81e486f941025b56e0c6e0550d00bebb396ac..aaffe41c89608ee5bb7521b0ff7e2ab5e4560536 100644 (file)
@@ -128,3 +128,36 @@ loongarch-don-t-crash-in-stack_top-for-tasks-without.patch
 jfs-fix-sanity-check-in-dbmount.patch
 tracing-probes-fix-max_trace_args-limit-handling.patch
 tracing-consider-the-null-character-when-validating-.patch
+xfrm-extract-dst-lookup-parameters-into-a-struct.patch
+xfrm-respect-ip-protocols-rules-criteria-when-perfor.patch
+xfrm-add-direction-to-the-sa-in-or-out.patch
+xfrm-validate-new-sa-s-prefixlen-using-sa-family-whe.patch
+netfilter-bpf-must-hold-reference-on-net-namespace.patch
+net-sun3_82586-fix-potential-memory-leak-in-sun3_825.patch
+be2net-fix-potential-memory-leak-in-be_xmit.patch
+net-plip-fix-break-causing-plip-to-never-transmit.patch
+octeon_ep-implement-helper-for-iterating-packets-in-.patch
+octeon_ep-add-skb-allocation-failures-handling-in-__.patch
+net-dsa-mv88e6xxx-fix-error-when-setting-port-policy.patch
+fsl-fman-save-device-references-taken-in-mac_probe.patch
+fsl-fman-fix-refcount-handling-of-fman-related-devic.patch
+netfilter-xtables-fix-typo-causing-some-targets-not-.patch
+net-wwan-fix-global-oob-in-wwan_rtnl_policy.patch
+net-sched-adjust-device-watchdog-timer-to-detect-sto.patch
+net-fix-races-in-netdev_tx_sent_queue-dev_watchdog.patch
+net-usb-usbnet-fix-name-regression.patch
+bpf-simplify-checking-size-of-helper-accesses.patch
+bpf-add-mem_write-attribute.patch
+bpf-fix-overloading-of-mem_uninit-s-meaning.patch
+bpf-remove-mem_uninit-from-skb-xdp-mtu-helpers.patch
+net-sched-act_api-deny-mismatched-skip_sw-skip_hw-fl.patch
+net-sched-fix-use-after-free-in-taprio_change.patch
+net-sched-use-rcu-read-side-critical-section-in-tapr.patch
+r8169-avoid-unsolicited-interrupts.patch
+posix-clock-posix-clock-fix-unbalanced-locking-in-pc.patch
+bluetooth-sco-fix-uaf-on-sco_sock_timeout.patch
+bluetooth-iso-fix-uaf-on-iso_sock_timeout.patch
+bpf-perf-fix-perf_event_detach_bpf_prog-error-handli.patch
+net-dsa-mv88e6xxx-group-cycle-counter-coefficients.patch
+net-dsa-mv88e6xxx-read-cycle-counter-period-from-har.patch
+net-dsa-mv88e6xxx-support-4000ps-cycle-counter-perio.patch
diff --git a/queue-6.6/xfrm-add-direction-to-the-sa-in-or-out.patch b/queue-6.6/xfrm-add-direction-to-the-sa-in-or-out.patch
new file mode 100644 (file)
index 0000000..9321c75
--- /dev/null
@@ -0,0 +1,429 @@
+From 3f97c69c749f417158bc3d69478204562fc8c98d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 30 Apr 2024 09:08:52 +0200
+Subject: xfrm: Add Direction to the SA in or out
+
+From: Antony Antony <antony.antony@secunet.com>
+
+[ Upstream commit a4a87fa4e96c7746e009de06a567688fd9af6013 ]
+
+This patch introduces the 'dir' attribute, 'in' or 'out', to the
+xfrm_state, SA, enhancing usability by delineating the scope of values
+based on direction. An input SA will restrict values pertinent to input,
+effectively segregating them from output-related values.
+And an output SA will restrict attributes for output. This change aims
+to streamline the configuration process and improve the overall
+consistency of SA attributes during configuration.
+
+This feature sets the groundwork for future patches, including
+the upcoming IP-TFS patch.
+
+Signed-off-by: Antony Antony <antony.antony@secunet.com>
+Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Stable-dep-of: 3f0ab59e6537 ("xfrm: validate new SA's prefixlen using SA family when sel.family is unset")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/xfrm.h        |   1 +
+ include/uapi/linux/xfrm.h |   6 ++
+ net/xfrm/xfrm_compat.c    |   7 +-
+ net/xfrm/xfrm_device.c    |   6 ++
+ net/xfrm/xfrm_replay.c    |   3 +-
+ net/xfrm/xfrm_state.c     |   8 +++
+ net/xfrm/xfrm_user.c      | 138 ++++++++++++++++++++++++++++++++++++--
+ 7 files changed, 160 insertions(+), 9 deletions(-)
+
+diff --git a/include/net/xfrm.h b/include/net/xfrm.h
+index 93a9866ee481f..c5cf062afd4a2 100644
+--- a/include/net/xfrm.h
++++ b/include/net/xfrm.h
+@@ -292,6 +292,7 @@ struct xfrm_state {
+       /* Private data of this transformer, format is opaque,
+        * interpreted by xfrm_type methods. */
+       void                    *data;
++      u8                      dir;
+ };
+ static inline struct net *xs_net(struct xfrm_state *x)
+diff --git a/include/uapi/linux/xfrm.h b/include/uapi/linux/xfrm.h
+index 23543c33fee82..7cd491caef354 100644
+--- a/include/uapi/linux/xfrm.h
++++ b/include/uapi/linux/xfrm.h
+@@ -140,6 +140,11 @@ enum {
+       XFRM_POLICY_MAX = 3
+ };
++enum xfrm_sa_dir {
++      XFRM_SA_DIR_IN  = 1,
++      XFRM_SA_DIR_OUT = 2
++};
++
+ enum {
+       XFRM_SHARE_ANY,         /* No limitations */
+       XFRM_SHARE_SESSION,     /* For this session only */
+@@ -314,6 +319,7 @@ enum xfrm_attr_type_t {
+       XFRMA_SET_MARK_MASK,    /* __u32 */
+       XFRMA_IF_ID,            /* __u32 */
+       XFRMA_MTIMER_THRESH,    /* __u32 in seconds for input SA */
++      XFRMA_SA_DIR,           /* __u8 */
+       __XFRMA_MAX
+ #define XFRMA_OUTPUT_MARK XFRMA_SET_MARK      /* Compatibility */
+diff --git a/net/xfrm/xfrm_compat.c b/net/xfrm/xfrm_compat.c
+index 655fe4ff86212..703d4172c7d73 100644
+--- a/net/xfrm/xfrm_compat.c
++++ b/net/xfrm/xfrm_compat.c
+@@ -98,6 +98,7 @@ static const int compat_msg_min[XFRM_NR_MSGTYPES] = {
+ };
+ static const struct nla_policy compat_policy[XFRMA_MAX+1] = {
++      [XFRMA_UNSPEC]          = { .strict_start_type = XFRMA_SA_DIR },
+       [XFRMA_SA]              = { .len = XMSGSIZE(compat_xfrm_usersa_info)},
+       [XFRMA_POLICY]          = { .len = XMSGSIZE(compat_xfrm_userpolicy_info)},
+       [XFRMA_LASTUSED]        = { .type = NLA_U64},
+@@ -129,6 +130,7 @@ static const struct nla_policy compat_policy[XFRMA_MAX+1] = {
+       [XFRMA_SET_MARK_MASK]   = { .type = NLA_U32 },
+       [XFRMA_IF_ID]           = { .type = NLA_U32 },
+       [XFRMA_MTIMER_THRESH]   = { .type = NLA_U32 },
++      [XFRMA_SA_DIR]          = NLA_POLICY_RANGE(NLA_U8, XFRM_SA_DIR_IN, XFRM_SA_DIR_OUT),
+ };
+ static struct nlmsghdr *xfrm_nlmsg_put_compat(struct sk_buff *skb,
+@@ -277,9 +279,10 @@ static int xfrm_xlate64_attr(struct sk_buff *dst, const struct nlattr *src)
+       case XFRMA_SET_MARK_MASK:
+       case XFRMA_IF_ID:
+       case XFRMA_MTIMER_THRESH:
++      case XFRMA_SA_DIR:
+               return xfrm_nla_cpy(dst, src, nla_len(src));
+       default:
+-              BUILD_BUG_ON(XFRMA_MAX != XFRMA_MTIMER_THRESH);
++              BUILD_BUG_ON(XFRMA_MAX != XFRMA_SA_DIR);
+               pr_warn_once("unsupported nla_type %d\n", src->nla_type);
+               return -EOPNOTSUPP;
+       }
+@@ -434,7 +437,7 @@ static int xfrm_xlate32_attr(void *dst, const struct nlattr *nla,
+       int err;
+       if (type > XFRMA_MAX) {
+-              BUILD_BUG_ON(XFRMA_MAX != XFRMA_MTIMER_THRESH);
++              BUILD_BUG_ON(XFRMA_MAX != XFRMA_SA_DIR);
+               NL_SET_ERR_MSG(extack, "Bad attribute");
+               return -EOPNOTSUPP;
+       }
+diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
+index 04dc0c8a83707..fc18b9b4f22f3 100644
+--- a/net/xfrm/xfrm_device.c
++++ b/net/xfrm/xfrm_device.c
+@@ -253,6 +253,12 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
+               return -EINVAL;
+       }
++      if ((xuo->flags & XFRM_OFFLOAD_INBOUND && x->dir == XFRM_SA_DIR_OUT) ||
++          (!(xuo->flags & XFRM_OFFLOAD_INBOUND) && x->dir == XFRM_SA_DIR_IN)) {
++              NL_SET_ERR_MSG(extack, "Mismatched SA and offload direction");
++              return -EINVAL;
++      }
++
+       is_packet_offload = xuo->flags & XFRM_OFFLOAD_PACKET;
+       /* We don't yet support UDP encapsulation and TFC padding. */
+diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
+index ce56d659c55a6..bc56c63057252 100644
+--- a/net/xfrm/xfrm_replay.c
++++ b/net/xfrm/xfrm_replay.c
+@@ -778,7 +778,8 @@ int xfrm_init_replay(struct xfrm_state *x, struct netlink_ext_ack *extack)
+               }
+               if (x->props.flags & XFRM_STATE_ESN) {
+-                      if (replay_esn->replay_window == 0) {
++                      if (replay_esn->replay_window == 0 &&
++                          (!x->dir || x->dir == XFRM_SA_DIR_IN)) {
+                               NL_SET_ERR_MSG(extack, "ESN replay window must be > 0");
+                               return -EINVAL;
+                       }
+diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
+index 8a6e8656d014f..93c19f64746fa 100644
+--- a/net/xfrm/xfrm_state.c
++++ b/net/xfrm/xfrm_state.c
+@@ -1349,6 +1349,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr,
+               if (km_query(x, tmpl, pol) == 0) {
+                       spin_lock_bh(&net->xfrm.xfrm_state_lock);
+                       x->km.state = XFRM_STATE_ACQ;
++                      x->dir = XFRM_SA_DIR_OUT;
+                       list_add(&x->km.all, &net->xfrm.state_all);
+                       XFRM_STATE_INSERT(bydst, &x->bydst,
+                                         net->xfrm.state_bydst + h,
+@@ -1801,6 +1802,7 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig,
+       x->lastused = orig->lastused;
+       x->new_mapping = 0;
+       x->new_mapping_sport = 0;
++      x->dir = orig->dir;
+       return x;
+@@ -1921,8 +1923,14 @@ int xfrm_state_update(struct xfrm_state *x)
+       }
+       if (x1->km.state == XFRM_STATE_ACQ) {
++              if (x->dir && x1->dir != x->dir)
++                      goto out;
++
+               __xfrm_state_insert(x);
+               x = NULL;
++      } else {
++              if (x1->dir != x->dir)
++                      goto out;
+       }
+       err = 0;
+diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
+index 979f23cded401..4328e81ea6a31 100644
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -130,7 +130,7 @@ static inline int verify_sec_ctx_len(struct nlattr **attrs, struct netlink_ext_a
+ }
+ static inline int verify_replay(struct xfrm_usersa_info *p,
+-                              struct nlattr **attrs,
++                              struct nlattr **attrs, u8 sa_dir,
+                               struct netlink_ext_ack *extack)
+ {
+       struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];
+@@ -168,6 +168,30 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
+               return -EINVAL;
+       }
++      if (sa_dir == XFRM_SA_DIR_OUT)  {
++              if (rs->replay_window) {
++                      NL_SET_ERR_MSG(extack, "Replay window should be 0 for output SA");
++                      return -EINVAL;
++              }
++              if (rs->seq || rs->seq_hi) {
++                      NL_SET_ERR_MSG(extack,
++                                     "Replay seq and seq_hi should be 0 for output SA");
++                      return -EINVAL;
++              }
++              if (rs->bmp_len) {
++                      NL_SET_ERR_MSG(extack, "Replay bmp_len should 0 for output SA");
++                      return -EINVAL;
++              }
++      }
++
++      if (sa_dir == XFRM_SA_DIR_IN)  {
++              if (rs->oseq || rs->oseq_hi) {
++                      NL_SET_ERR_MSG(extack,
++                                     "Replay oseq and oseq_hi should be 0 for input SA");
++                      return -EINVAL;
++              }
++      }
++
+       return 0;
+ }
+@@ -176,6 +200,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
+                            struct netlink_ext_ack *extack)
+ {
+       int err;
++      u8 sa_dir = attrs[XFRMA_SA_DIR] ? nla_get_u8(attrs[XFRMA_SA_DIR]) : 0;
+       err = -EINVAL;
+       switch (p->family) {
+@@ -334,7 +359,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
+               goto out;
+       if ((err = verify_sec_ctx_len(attrs, extack)))
+               goto out;
+-      if ((err = verify_replay(p, attrs, extack)))
++      if ((err = verify_replay(p, attrs, sa_dir, extack)))
+               goto out;
+       err = -EINVAL;
+@@ -358,6 +383,77 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
+                       err = -EINVAL;
+                       goto out;
+               }
++
++              if (sa_dir == XFRM_SA_DIR_OUT) {
++                      NL_SET_ERR_MSG(extack,
++                                     "MTIMER_THRESH attribute should not be set on output SA");
++                      err = -EINVAL;
++                      goto out;
++              }
++      }
++
++      if (sa_dir == XFRM_SA_DIR_OUT) {
++              if (p->flags & XFRM_STATE_DECAP_DSCP) {
++                      NL_SET_ERR_MSG(extack, "Flag DECAP_DSCP should not be set for output SA");
++                      err = -EINVAL;
++                      goto out;
++              }
++
++              if (p->flags & XFRM_STATE_ICMP) {
++                      NL_SET_ERR_MSG(extack, "Flag ICMP should not be set for output SA");
++                      err = -EINVAL;
++                      goto out;
++              }
++
++              if (p->flags & XFRM_STATE_WILDRECV) {
++                      NL_SET_ERR_MSG(extack, "Flag WILDRECV should not be set for output SA");
++                      err = -EINVAL;
++                      goto out;
++              }
++
++              if (p->replay_window) {
++                      NL_SET_ERR_MSG(extack, "Replay window should be 0 for output SA");
++                      err = -EINVAL;
++                      goto out;
++              }
++
++              if (attrs[XFRMA_REPLAY_VAL]) {
++                      struct xfrm_replay_state *replay;
++
++                      replay = nla_data(attrs[XFRMA_REPLAY_VAL]);
++
++                      if (replay->seq || replay->bitmap) {
++                              NL_SET_ERR_MSG(extack,
++                                             "Replay seq and bitmap should be 0 for output SA");
++                              err = -EINVAL;
++                              goto out;
++                      }
++              }
++      }
++
++      if (sa_dir == XFRM_SA_DIR_IN) {
++              if (p->flags & XFRM_STATE_NOPMTUDISC) {
++                      NL_SET_ERR_MSG(extack, "Flag NOPMTUDISC should not be set for input SA");
++                      err = -EINVAL;
++                      goto out;
++              }
++
++              if (attrs[XFRMA_SA_EXTRA_FLAGS]) {
++                      u32 xflags = nla_get_u32(attrs[XFRMA_SA_EXTRA_FLAGS]);
++
++                      if (xflags & XFRM_SA_XFLAG_DONT_ENCAP_DSCP) {
++                              NL_SET_ERR_MSG(extack, "Flag DONT_ENCAP_DSCP should not be set for input SA");
++                              err = -EINVAL;
++                              goto out;
++                      }
++
++                      if (xflags & XFRM_SA_XFLAG_OSEQ_MAY_WRAP) {
++                              NL_SET_ERR_MSG(extack, "Flag OSEQ_MAY_WRAP should not be set for input SA");
++                              err = -EINVAL;
++                              goto out;
++                      }
++
++              }
+       }
+ out:
+@@ -734,6 +830,9 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
+       if (attrs[XFRMA_IF_ID])
+               x->if_id = nla_get_u32(attrs[XFRMA_IF_ID]);
++      if (attrs[XFRMA_SA_DIR])
++              x->dir = nla_get_u8(attrs[XFRMA_SA_DIR]);
++
+       err = __xfrm_init_state(x, false, attrs[XFRMA_OFFLOAD_DEV], extack);
+       if (err)
+               goto error;
+@@ -1182,8 +1281,13 @@ static int copy_to_user_state_extra(struct xfrm_state *x,
+               if (ret)
+                       goto out;
+       }
+-      if (x->mapping_maxage)
++      if (x->mapping_maxage) {
+               ret = nla_put_u32(skb, XFRMA_MTIMER_THRESH, x->mapping_maxage);
++              if (ret)
++                      goto out;
++      }
++      if (x->dir)
++              ret = nla_put_u8(skb, XFRMA_SA_DIR, x->dir);
+ out:
+       return ret;
+ }
+@@ -1618,6 +1722,9 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
+       if (err)
+               goto out;
++      if (attrs[XFRMA_SA_DIR])
++              x->dir = nla_get_u8(attrs[XFRMA_SA_DIR]);
++
+       resp_skb = xfrm_state_netlink(skb, x, nlh->nlmsg_seq);
+       if (IS_ERR(resp_skb)) {
+               err = PTR_ERR(resp_skb);
+@@ -2401,7 +2508,8 @@ static inline unsigned int xfrm_aevent_msgsize(struct xfrm_state *x)
+              + nla_total_size_64bit(sizeof(struct xfrm_lifetime_cur))
+              + nla_total_size(sizeof(struct xfrm_mark))
+              + nla_total_size(4) /* XFRM_AE_RTHR */
+-             + nla_total_size(4); /* XFRM_AE_ETHR */
++             + nla_total_size(4) /* XFRM_AE_ETHR */
++             + nla_total_size(sizeof(x->dir)); /* XFRMA_SA_DIR */
+ }
+ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c)
+@@ -2458,6 +2566,12 @@ static int build_aevent(struct sk_buff *skb, struct xfrm_state *x, const struct
+       if (err)
+               goto out_cancel;
++      if (x->dir) {
++              err = nla_put_u8(skb, XFRMA_SA_DIR, x->dir);
++              if (err)
++                      goto out_cancel;
++      }
++
+       nlmsg_end(skb, nlh);
+       return 0;
+@@ -3017,6 +3131,7 @@ EXPORT_SYMBOL_GPL(xfrm_msg_min);
+ #undef XMSGSIZE
+ const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
++      [XFRMA_UNSPEC]          = { .strict_start_type = XFRMA_SA_DIR },
+       [XFRMA_SA]              = { .len = sizeof(struct xfrm_usersa_info)},
+       [XFRMA_POLICY]          = { .len = sizeof(struct xfrm_userpolicy_info)},
+       [XFRMA_LASTUSED]        = { .type = NLA_U64},
+@@ -3048,6 +3163,7 @@ const struct nla_policy xfrma_policy[XFRMA_MAX+1] = {
+       [XFRMA_SET_MARK_MASK]   = { .type = NLA_U32 },
+       [XFRMA_IF_ID]           = { .type = NLA_U32 },
+       [XFRMA_MTIMER_THRESH]   = { .type = NLA_U32 },
++      [XFRMA_SA_DIR]          = NLA_POLICY_RANGE(NLA_U8, XFRM_SA_DIR_IN, XFRM_SA_DIR_OUT),
+ };
+ EXPORT_SYMBOL_GPL(xfrma_policy);
+@@ -3188,8 +3304,9 @@ static void xfrm_netlink_rcv(struct sk_buff *skb)
+ static inline unsigned int xfrm_expire_msgsize(void)
+ {
+-      return NLMSG_ALIGN(sizeof(struct xfrm_user_expire))
+-             + nla_total_size(sizeof(struct xfrm_mark));
++      return NLMSG_ALIGN(sizeof(struct xfrm_user_expire)) +
++             nla_total_size(sizeof(struct xfrm_mark)) +
++             nla_total_size(sizeof_field(struct xfrm_state, dir));
+ }
+ static int build_expire(struct sk_buff *skb, struct xfrm_state *x, const struct km_event *c)
+@@ -3216,6 +3333,12 @@ static int build_expire(struct sk_buff *skb, struct xfrm_state *x, const struct
+       if (err)
+               return err;
++      if (x->dir) {
++              err = nla_put_u8(skb, XFRMA_SA_DIR, x->dir);
++              if (err)
++                      return err;
++      }
++
+       nlmsg_end(skb, nlh);
+       return 0;
+ }
+@@ -3323,6 +3446,9 @@ static inline unsigned int xfrm_sa_len(struct xfrm_state *x)
+       if (x->mapping_maxage)
+               l += nla_total_size(sizeof(x->mapping_maxage));
++      if (x->dir)
++              l += nla_total_size(sizeof(x->dir));
++
+       return l;
+ }
+-- 
+2.43.0
+
diff --git a/queue-6.6/xfrm-extract-dst-lookup-parameters-into-a-struct.patch b/queue-6.6/xfrm-extract-dst-lookup-parameters-into-a-struct.patch
new file mode 100644 (file)
index 0000000..724d514
--- /dev/null
@@ -0,0 +1,325 @@
+From 3227c37e6d5344fe2247c8405fb0695f5111e0f5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Sep 2024 17:07:09 -0700
+Subject: xfrm: extract dst lookup parameters into a struct
+
+From: Eyal Birger <eyal.birger@gmail.com>
+
+[ Upstream commit e509996b16728e37d5a909a5c63c1bd64f23b306 ]
+
+Preparation for adding more fields to dst lookup functions without
+changing their signatures.
+
+Signed-off-by: Eyal Birger <eyal.birger@gmail.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Stable-dep-of: b84697210343 ("xfrm: respect ip protocols rules criteria when performing dst lookups")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/xfrm.h      | 26 +++++++++++++-------------
+ net/ipv4/xfrm4_policy.c | 38 ++++++++++++++++----------------------
+ net/ipv6/xfrm6_policy.c | 28 +++++++++++++---------------
+ net/xfrm/xfrm_device.c  | 11 ++++++++---
+ net/xfrm/xfrm_policy.c  | 35 +++++++++++++++++++++++------------
+ 5 files changed, 73 insertions(+), 65 deletions(-)
+
+diff --git a/include/net/xfrm.h b/include/net/xfrm.h
+index b280e7c460116..93207d87e1c7f 100644
+--- a/include/net/xfrm.h
++++ b/include/net/xfrm.h
+@@ -342,20 +342,23 @@ struct xfrm_if_cb {
+ void xfrm_if_register_cb(const struct xfrm_if_cb *ifcb);
+ void xfrm_if_unregister_cb(void);
++struct xfrm_dst_lookup_params {
++      struct net *net;
++      int tos;
++      int oif;
++      xfrm_address_t *saddr;
++      xfrm_address_t *daddr;
++      u32 mark;
++};
++
+ struct net_device;
+ struct xfrm_type;
+ struct xfrm_dst;
+ struct xfrm_policy_afinfo {
+       struct dst_ops          *dst_ops;
+-      struct dst_entry        *(*dst_lookup)(struct net *net,
+-                                             int tos, int oif,
+-                                             const xfrm_address_t *saddr,
+-                                             const xfrm_address_t *daddr,
+-                                             u32 mark);
+-      int                     (*get_saddr)(struct net *net, int oif,
+-                                           xfrm_address_t *saddr,
+-                                           xfrm_address_t *daddr,
+-                                           u32 mark);
++      struct dst_entry        *(*dst_lookup)(const struct xfrm_dst_lookup_params *params);
++      int                     (*get_saddr)(xfrm_address_t *saddr,
++                                           const struct xfrm_dst_lookup_params *params);
+       int                     (*fill_dst)(struct xfrm_dst *xdst,
+                                           struct net_device *dev,
+                                           const struct flowi *fl);
+@@ -1728,10 +1731,7 @@ static inline int xfrm_user_policy(struct sock *sk, int optname,
+ }
+ #endif
+-struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
+-                                  const xfrm_address_t *saddr,
+-                                  const xfrm_address_t *daddr,
+-                                  int family, u32 mark);
++struct dst_entry *__xfrm_dst_lookup(int family, const struct xfrm_dst_lookup_params *params);
+ struct xfrm_policy *xfrm_policy_alloc(struct net *net, gfp_t gfp);
+diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
+index c33bca2c38415..01d4f6f4dbb8c 100644
+--- a/net/ipv4/xfrm4_policy.c
++++ b/net/ipv4/xfrm4_policy.c
+@@ -17,47 +17,41 @@
+ #include <net/ip.h>
+ #include <net/l3mdev.h>
+-static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4,
+-                                          int tos, int oif,
+-                                          const xfrm_address_t *saddr,
+-                                          const xfrm_address_t *daddr,
+-                                          u32 mark)
++static struct dst_entry *__xfrm4_dst_lookup(struct flowi4 *fl4,
++                                          const struct xfrm_dst_lookup_params *params)
+ {
+       struct rtable *rt;
+       memset(fl4, 0, sizeof(*fl4));
+-      fl4->daddr = daddr->a4;
+-      fl4->flowi4_tos = tos;
+-      fl4->flowi4_l3mdev = l3mdev_master_ifindex_by_index(net, oif);
+-      fl4->flowi4_mark = mark;
+-      if (saddr)
+-              fl4->saddr = saddr->a4;
+-
+-      rt = __ip_route_output_key(net, fl4);
++      fl4->daddr = params->daddr->a4;
++      fl4->flowi4_tos = params->tos;
++      fl4->flowi4_l3mdev = l3mdev_master_ifindex_by_index(params->net,
++                                                          params->oif);
++      fl4->flowi4_mark = params->mark;
++      if (params->saddr)
++              fl4->saddr = params->saddr->a4;
++
++      rt = __ip_route_output_key(params->net, fl4);
+       if (!IS_ERR(rt))
+               return &rt->dst;
+       return ERR_CAST(rt);
+ }
+-static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, int oif,
+-                                        const xfrm_address_t *saddr,
+-                                        const xfrm_address_t *daddr,
+-                                        u32 mark)
++static struct dst_entry *xfrm4_dst_lookup(const struct xfrm_dst_lookup_params *params)
+ {
+       struct flowi4 fl4;
+-      return __xfrm4_dst_lookup(net, &fl4, tos, oif, saddr, daddr, mark);
++      return __xfrm4_dst_lookup(&fl4, params);
+ }
+-static int xfrm4_get_saddr(struct net *net, int oif,
+-                         xfrm_address_t *saddr, xfrm_address_t *daddr,
+-                         u32 mark)
++static int xfrm4_get_saddr(xfrm_address_t *saddr,
++                         const struct xfrm_dst_lookup_params *params)
+ {
+       struct dst_entry *dst;
+       struct flowi4 fl4;
+-      dst = __xfrm4_dst_lookup(net, &fl4, 0, oif, NULL, daddr, mark);
++      dst = __xfrm4_dst_lookup(&fl4, params);
+       if (IS_ERR(dst))
+               return -EHOSTUNREACH;
+diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
+index 444b0b4469a49..246a0cea77c26 100644
+--- a/net/ipv6/xfrm6_policy.c
++++ b/net/ipv6/xfrm6_policy.c
+@@ -23,23 +23,21 @@
+ #include <net/ip6_route.h>
+ #include <net/l3mdev.h>
+-static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
+-                                        const xfrm_address_t *saddr,
+-                                        const xfrm_address_t *daddr,
+-                                        u32 mark)
++static struct dst_entry *xfrm6_dst_lookup(const struct xfrm_dst_lookup_params *params)
+ {
+       struct flowi6 fl6;
+       struct dst_entry *dst;
+       int err;
+       memset(&fl6, 0, sizeof(fl6));
+-      fl6.flowi6_l3mdev = l3mdev_master_ifindex_by_index(net, oif);
+-      fl6.flowi6_mark = mark;
+-      memcpy(&fl6.daddr, daddr, sizeof(fl6.daddr));
+-      if (saddr)
+-              memcpy(&fl6.saddr, saddr, sizeof(fl6.saddr));
++      fl6.flowi6_l3mdev = l3mdev_master_ifindex_by_index(params->net,
++                                                         params->oif);
++      fl6.flowi6_mark = params->mark;
++      memcpy(&fl6.daddr, params->daddr, sizeof(fl6.daddr));
++      if (params->saddr)
++              memcpy(&fl6.saddr, params->saddr, sizeof(fl6.saddr));
+-      dst = ip6_route_output(net, NULL, &fl6);
++      dst = ip6_route_output(params->net, NULL, &fl6);
+       err = dst->error;
+       if (dst->error) {
+@@ -50,15 +48,14 @@ static struct dst_entry *xfrm6_dst_lookup(struct net *net, int tos, int oif,
+       return dst;
+ }
+-static int xfrm6_get_saddr(struct net *net, int oif,
+-                         xfrm_address_t *saddr, xfrm_address_t *daddr,
+-                         u32 mark)
++static int xfrm6_get_saddr(xfrm_address_t *saddr,
++                         const struct xfrm_dst_lookup_params *params)
+ {
+       struct dst_entry *dst;
+       struct net_device *dev;
+       struct inet6_dev *idev;
+-      dst = xfrm6_dst_lookup(net, 0, oif, NULL, daddr, mark);
++      dst = xfrm6_dst_lookup(params);
+       if (IS_ERR(dst))
+               return -EHOSTUNREACH;
+@@ -68,7 +65,8 @@ static int xfrm6_get_saddr(struct net *net, int oif,
+               return -EHOSTUNREACH;
+       }
+       dev = idev->dev;
+-      ipv6_dev_get_saddr(dev_net(dev), dev, &daddr->in6, 0, &saddr->in6);
++      ipv6_dev_get_saddr(dev_net(dev), dev, &params->daddr->in6, 0,
++                         &saddr->in6);
+       dst_release(dst);
+       return 0;
+ }
+diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
+index 6346690d5c699..04dc0c8a83707 100644
+--- a/net/xfrm/xfrm_device.c
++++ b/net/xfrm/xfrm_device.c
+@@ -263,6 +263,8 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
+       dev = dev_get_by_index(net, xuo->ifindex);
+       if (!dev) {
++              struct xfrm_dst_lookup_params params;
++
+               if (!(xuo->flags & XFRM_OFFLOAD_INBOUND)) {
+                       saddr = &x->props.saddr;
+                       daddr = &x->id.daddr;
+@@ -271,9 +273,12 @@ int xfrm_dev_state_add(struct net *net, struct xfrm_state *x,
+                       daddr = &x->props.saddr;
+               }
+-              dst = __xfrm_dst_lookup(net, 0, 0, saddr, daddr,
+-                                      x->props.family,
+-                                      xfrm_smark_get(0, x));
++              memset(&params, 0, sizeof(params));
++              params.net = net;
++              params.saddr = saddr;
++              params.daddr = daddr;
++              params.mark = xfrm_smark_get(0, x);
++              dst = __xfrm_dst_lookup(x->props.family, &params);
+               if (IS_ERR(dst))
+                       return (is_packet_offload) ? -EINVAL : 0;
+diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
+index b699cc2ec35ac..1395d3de1ec70 100644
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -251,10 +251,8 @@ static const struct xfrm_if_cb *xfrm_if_get_cb(void)
+       return rcu_dereference(xfrm_if_cb);
+ }
+-struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
+-                                  const xfrm_address_t *saddr,
+-                                  const xfrm_address_t *daddr,
+-                                  int family, u32 mark)
++struct dst_entry *__xfrm_dst_lookup(int family,
++                                  const struct xfrm_dst_lookup_params *params)
+ {
+       const struct xfrm_policy_afinfo *afinfo;
+       struct dst_entry *dst;
+@@ -263,7 +261,7 @@ struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, int oif,
+       if (unlikely(afinfo == NULL))
+               return ERR_PTR(-EAFNOSUPPORT);
+-      dst = afinfo->dst_lookup(net, tos, oif, saddr, daddr, mark);
++      dst = afinfo->dst_lookup(params);
+       rcu_read_unlock();
+@@ -277,6 +275,7 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x,
+                                               xfrm_address_t *prev_daddr,
+                                               int family, u32 mark)
+ {
++      struct xfrm_dst_lookup_params params;
+       struct net *net = xs_net(x);
+       xfrm_address_t *saddr = &x->props.saddr;
+       xfrm_address_t *daddr = &x->id.daddr;
+@@ -291,7 +290,14 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x,
+               daddr = x->coaddr;
+       }
+-      dst = __xfrm_dst_lookup(net, tos, oif, saddr, daddr, family, mark);
++      params.net = net;
++      params.saddr = saddr;
++      params.daddr = daddr;
++      params.tos = tos;
++      params.oif = oif;
++      params.mark = mark;
++
++      dst = __xfrm_dst_lookup(family, &params);
+       if (!IS_ERR(dst)) {
+               if (prev_saddr != saddr)
+@@ -2424,15 +2430,15 @@ int __xfrm_sk_clone_policy(struct sock *sk, const struct sock *osk)
+ }
+ static int
+-xfrm_get_saddr(struct net *net, int oif, xfrm_address_t *local,
+-             xfrm_address_t *remote, unsigned short family, u32 mark)
++xfrm_get_saddr(unsigned short family, xfrm_address_t *saddr,
++             const struct xfrm_dst_lookup_params *params)
+ {
+       int err;
+       const struct xfrm_policy_afinfo *afinfo = xfrm_policy_get_afinfo(family);
+       if (unlikely(afinfo == NULL))
+               return -EINVAL;
+-      err = afinfo->get_saddr(net, oif, local, remote, mark);
++      err = afinfo->get_saddr(saddr, params);
+       rcu_read_unlock();
+       return err;
+ }
+@@ -2461,9 +2467,14 @@ xfrm_tmpl_resolve_one(struct xfrm_policy *policy, const struct flowi *fl,
+                       remote = &tmpl->id.daddr;
+                       local = &tmpl->saddr;
+                       if (xfrm_addr_any(local, tmpl->encap_family)) {
+-                              error = xfrm_get_saddr(net, fl->flowi_oif,
+-                                                     &tmp, remote,
+-                                                     tmpl->encap_family, 0);
++                              struct xfrm_dst_lookup_params params;
++
++                              memset(&params, 0, sizeof(params));
++                              params.net = net;
++                              params.oif = fl->flowi_oif;
++                              params.daddr = remote;
++                              error = xfrm_get_saddr(tmpl->encap_family, &tmp,
++                                                     &params);
+                               if (error)
+                                       goto fail;
+                               local = &tmp;
+-- 
+2.43.0
+
diff --git a/queue-6.6/xfrm-respect-ip-protocols-rules-criteria-when-perfor.patch b/queue-6.6/xfrm-respect-ip-protocols-rules-criteria-when-perfor.patch
new file mode 100644 (file)
index 0000000..17e1947
--- /dev/null
@@ -0,0 +1,99 @@
+From 05afeb8e381e45ae416bf75da00897307d6afb09 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Sep 2024 17:07:10 -0700
+Subject: xfrm: respect ip protocols rules criteria when performing dst lookups
+
+From: Eyal Birger <eyal.birger@gmail.com>
+
+[ Upstream commit b8469721034300bbb6dec5b4bf32492c95e16a0c ]
+
+The series in the "fixes" tag added the ability to consider L4 attributes
+in routing rules.
+
+The dst lookup on the outer packet of encapsulated traffic in the xfrm
+code was not adapted to this change, thus routing behavior that relies
+on L4 information is not respected.
+
+Pass the ip protocol information when performing dst lookups.
+
+Fixes: a25724b05af0 ("Merge branch 'fib_rules-support-sport-dport-and-proto-match'")
+Signed-off-by: Eyal Birger <eyal.birger@gmail.com>
+Tested-by: Antony Antony <antony.antony@secunet.com>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/xfrm.h      |  2 ++
+ net/ipv4/xfrm4_policy.c |  2 ++
+ net/ipv6/xfrm6_policy.c |  3 +++
+ net/xfrm/xfrm_policy.c  | 15 +++++++++++++++
+ 4 files changed, 22 insertions(+)
+
+diff --git a/include/net/xfrm.h b/include/net/xfrm.h
+index 93207d87e1c7f..93a9866ee481f 100644
+--- a/include/net/xfrm.h
++++ b/include/net/xfrm.h
+@@ -349,6 +349,8 @@ struct xfrm_dst_lookup_params {
+       xfrm_address_t *saddr;
+       xfrm_address_t *daddr;
+       u32 mark;
++      __u8 ipproto;
++      union flowi_uli uli;
+ };
+ struct net_device;
+diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c
+index 01d4f6f4dbb8c..63bbc7f6a5a88 100644
+--- a/net/ipv4/xfrm4_policy.c
++++ b/net/ipv4/xfrm4_policy.c
+@@ -30,6 +30,8 @@ static struct dst_entry *__xfrm4_dst_lookup(struct flowi4 *fl4,
+       fl4->flowi4_mark = params->mark;
+       if (params->saddr)
+               fl4->saddr = params->saddr->a4;
++      fl4->flowi4_proto = params->ipproto;
++      fl4->uli = params->uli;
+       rt = __ip_route_output_key(params->net, fl4);
+       if (!IS_ERR(rt))
+diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c
+index 246a0cea77c26..4cd625af91e6c 100644
+--- a/net/ipv6/xfrm6_policy.c
++++ b/net/ipv6/xfrm6_policy.c
+@@ -37,6 +37,9 @@ static struct dst_entry *xfrm6_dst_lookup(const struct xfrm_dst_lookup_params *p
+       if (params->saddr)
+               memcpy(&fl6.saddr, params->saddr, sizeof(fl6.saddr));
++      fl6.flowi4_proto = params->ipproto;
++      fl6.uli = params->uli;
++
+       dst = ip6_route_output(params->net, NULL, &fl6);
+       err = dst->error;
+diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
+index 1395d3de1ec70..d788baffbf104 100644
+--- a/net/xfrm/xfrm_policy.c
++++ b/net/xfrm/xfrm_policy.c
+@@ -296,6 +296,21 @@ static inline struct dst_entry *xfrm_dst_lookup(struct xfrm_state *x,
+       params.tos = tos;
+       params.oif = oif;
+       params.mark = mark;
++      params.ipproto = x->id.proto;
++      if (x->encap) {
++              switch (x->encap->encap_type) {
++              case UDP_ENCAP_ESPINUDP:
++                      params.ipproto = IPPROTO_UDP;
++                      params.uli.ports.sport = x->encap->encap_sport;
++                      params.uli.ports.dport = x->encap->encap_dport;
++                      break;
++              case TCP_ENCAP_ESPINTCP:
++                      params.ipproto = IPPROTO_TCP;
++                      params.uli.ports.sport = x->encap->encap_sport;
++                      params.uli.ports.dport = x->encap->encap_dport;
++                      break;
++              }
++      }
+       dst = __xfrm_dst_lookup(family, &params);
+-- 
+2.43.0
+
diff --git a/queue-6.6/xfrm-validate-new-sa-s-prefixlen-using-sa-family-whe.patch b/queue-6.6/xfrm-validate-new-sa-s-prefixlen-using-sa-family-whe.patch
new file mode 100644 (file)
index 0000000..a9b32af
--- /dev/null
@@ -0,0 +1,60 @@
+From 2509ee204c957aeb677d90083f814e8963ca813e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Oct 2024 18:48:14 +0200
+Subject: xfrm: validate new SA's prefixlen using SA family when sel.family is
+ unset
+
+From: Sabrina Dubroca <sd@queasysnail.net>
+
+[ Upstream commit 3f0ab59e6537c6a8f9e1b355b48f9c05a76e8563 ]
+
+This expands the validation introduced in commit 07bf7908950a ("xfrm:
+Validate address prefix lengths in the xfrm selector.")
+
+syzbot created an SA with
+    usersa.sel.family = AF_UNSPEC
+    usersa.sel.prefixlen_s = 128
+    usersa.family = AF_INET
+
+Because of the AF_UNSPEC selector, verify_newsa_info doesn't put
+limits on prefixlen_{s,d}. But then copy_from_user_state sets
+x->sel.family to usersa.family (AF_INET). Do the same conversion in
+verify_newsa_info before validating prefixlen_{s,d}, since that's how
+prefixlen is going to be used later on.
+
+Reported-by: syzbot+cc39f136925517aed571@syzkaller.appspotmail.com
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
+Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xfrm/xfrm_user.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
+index 4328e81ea6a31..12e9d0e703e70 100644
+--- a/net/xfrm/xfrm_user.c
++++ b/net/xfrm/xfrm_user.c
+@@ -201,6 +201,7 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
+ {
+       int err;
+       u8 sa_dir = attrs[XFRMA_SA_DIR] ? nla_get_u8(attrs[XFRMA_SA_DIR]) : 0;
++      u16 family = p->sel.family;
+       err = -EINVAL;
+       switch (p->family) {
+@@ -221,7 +222,10 @@ static int verify_newsa_info(struct xfrm_usersa_info *p,
+               goto out;
+       }
+-      switch (p->sel.family) {
++      if (!family && !(p->flags & XFRM_STATE_AF_UNSPEC))
++              family = p->family;
++
++      switch (family) {
+       case AF_UNSPEC:
+               break;
+-- 
+2.43.0
+