]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Mon, 15 Apr 2024 08:56:17 +0000 (04:56 -0400)
committerSasha Levin <sashal@kernel.org>
Mon, 15 Apr 2024 08:56:17 +0000 (04:56 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
28 files changed:
queue-5.10/af_unix-do-not-use-atomic-ops-for-unix_sk-sk-infligh.patch [new file with mode: 0644]
queue-5.10/af_unix-fix-garbage-collector-racing-against-connect.patch [new file with mode: 0644]
queue-5.10/bluetooth-add-support-for-reading-aosp-vendor-capabi.patch [new file with mode: 0644]
queue-5.10/bluetooth-allow-querying-of-supported-offload-codecs.patch [new file with mode: 0644]
queue-5.10/bluetooth-allow-setting-of-codec-for-hfp-offload-use.patch [new file with mode: 0644]
queue-5.10/bluetooth-enumerate-local-supported-codec-and-cache-.patch [new file with mode: 0644]
queue-5.10/bluetooth-fix-mgmt-status-for-ll-privacy-experimenta.patch [new file with mode: 0644]
queue-5.10/bluetooth-refactor-set_exp_feature-with-a-feature-ta.patch [new file with mode: 0644]
queue-5.10/bluetooth-sco-fix-not-validating-setsockopt-user-inp.patch [new file with mode: 0644]
queue-5.10/bluetooth-support-the-quality-report-events.patch [new file with mode: 0644]
queue-5.10/geneve-fix-header-validation-in-geneve-6-_xmit_skb.patch [new file with mode: 0644]
queue-5.10/iommu-vt-d-allocate-local-memory-for-page-request-qu.patch [new file with mode: 0644]
queue-5.10/ipv4-route-avoid-unused-but-set-variable-warning.patch [new file with mode: 0644]
queue-5.10/ipv6-fib-hide-unused-pn-variable.patch [new file with mode: 0644]
queue-5.10/ipv6-fix-race-condition-between-ipv6_get_ifaddr-and-.patch [new file with mode: 0644]
queue-5.10/net-ena-fix-incorrect-descriptor-free-behavior.patch [new file with mode: 0644]
queue-5.10/net-ena-fix-potential-sign-extension-issue.patch [new file with mode: 0644]
queue-5.10/net-ena-wrong-missing-io-completions-check-order.patch [new file with mode: 0644]
queue-5.10/net-mlx5-properly-link-new-fs-rules-into-the-tree.patch [new file with mode: 0644]
queue-5.10/net-openvswitch-fix-unwanted-error-log-on-timeout-po.patch [new file with mode: 0644]
queue-5.10/netfilter-complete-validation-of-user-input.patch [new file with mode: 0644]
queue-5.10/nouveau-fix-function-cast-warning.patch [new file with mode: 0644]
queue-5.10/octeontx2-af-fix-nix-sq-mode-and-bp-config.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/u64_stats-disable-preemption-on-32bit-up-smp-preempt.patch [new file with mode: 0644]
queue-5.10/u64_stats-fix-u64_stats_init-for-lockdep-when-used-r.patch [new file with mode: 0644]
queue-5.10/u64_stats-streamline-the-implementation.patch [new file with mode: 0644]
queue-5.10/xsk-validate-user-input-for-xdp_-umem-completion-_fi.patch [new file with mode: 0644]

diff --git a/queue-5.10/af_unix-do-not-use-atomic-ops-for-unix_sk-sk-infligh.patch b/queue-5.10/af_unix-do-not-use-atomic-ops-for-unix_sk-sk-infligh.patch
new file mode 100644 (file)
index 0000000..4536a79
--- /dev/null
@@ -0,0 +1,147 @@
+From 89981f90ebaff79a5d86f72eb4afe37393e11fdf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 23 Jan 2024 09:08:53 -0800
+Subject: af_unix: Do not use atomic ops for unix_sk(sk)->inflight.
+
+From: Kuniyuki Iwashima <kuniyu@amazon.com>
+
+[ Upstream commit 97af84a6bba2ab2b9c704c08e67de3b5ea551bb2 ]
+
+When touching unix_sk(sk)->inflight, we are always under
+spin_lock(&unix_gc_lock).
+
+Let's convert unix_sk(sk)->inflight to the normal unsigned long.
+
+Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://lore.kernel.org/r/20240123170856.41348-3-kuniyu@amazon.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Stable-dep-of: 47d8ac011fe1 ("af_unix: Fix garbage collector racing against connect()")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/af_unix.h |  2 +-
+ net/unix/af_unix.c    |  4 ++--
+ net/unix/garbage.c    | 17 ++++++++---------
+ net/unix/scm.c        |  8 +++++---
+ 4 files changed, 16 insertions(+), 15 deletions(-)
+
+diff --git a/include/net/af_unix.h b/include/net/af_unix.h
+index a6b6ce8b918b7..67eeca1013ade 100644
+--- a/include/net/af_unix.h
++++ b/include/net/af_unix.h
+@@ -56,7 +56,7 @@ struct unix_sock {
+       struct mutex            iolock, bindlock;
+       struct sock             *peer;
+       struct list_head        link;
+-      atomic_long_t           inflight;
++      unsigned long           inflight;
+       spinlock_t              lock;
+       unsigned long           gc_flags;
+ #define UNIX_GC_CANDIDATE     0
+diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
+index b003d0597f4bd..224b1fdc82279 100644
+--- a/net/unix/af_unix.c
++++ b/net/unix/af_unix.c
+@@ -817,11 +817,11 @@ static struct sock *unix_create1(struct net *net, struct socket *sock, int kern)
+       sk->sk_write_space      = unix_write_space;
+       sk->sk_max_ack_backlog  = net->unx.sysctl_max_dgram_qlen;
+       sk->sk_destruct         = unix_sock_destructor;
+-      u         = unix_sk(sk);
++      u = unix_sk(sk);
++      u->inflight = 0;
+       u->path.dentry = NULL;
+       u->path.mnt = NULL;
+       spin_lock_init(&u->lock);
+-      atomic_long_set(&u->inflight, 0);
+       INIT_LIST_HEAD(&u->link);
+       mutex_init(&u->iolock); /* single task reading lock */
+       mutex_init(&u->bindlock); /* single task binding lock */
+diff --git a/net/unix/garbage.c b/net/unix/garbage.c
+index 9121a4d5436d5..675fbe594dbb3 100644
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -166,17 +166,18 @@ static void scan_children(struct sock *x, void (*func)(struct unix_sock *),
+ static void dec_inflight(struct unix_sock *usk)
+ {
+-      atomic_long_dec(&usk->inflight);
++      usk->inflight--;
+ }
+ static void inc_inflight(struct unix_sock *usk)
+ {
+-      atomic_long_inc(&usk->inflight);
++      usk->inflight++;
+ }
+ static void inc_inflight_move_tail(struct unix_sock *u)
+ {
+-      atomic_long_inc(&u->inflight);
++      u->inflight++;
++
+       /* If this still might be part of a cycle, move it to the end
+        * of the list, so that it's checked even if it was already
+        * passed over
+@@ -237,14 +238,12 @@ void unix_gc(void)
+        */
+       list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
+               long total_refs;
+-              long inflight_refs;
+               total_refs = file_count(u->sk.sk_socket->file);
+-              inflight_refs = atomic_long_read(&u->inflight);
+-              BUG_ON(inflight_refs < 1);
+-              BUG_ON(total_refs < inflight_refs);
+-              if (total_refs == inflight_refs) {
++              BUG_ON(!u->inflight);
++              BUG_ON(total_refs < u->inflight);
++              if (total_refs == u->inflight) {
+                       list_move_tail(&u->link, &gc_candidates);
+                       __set_bit(UNIX_GC_CANDIDATE, &u->gc_flags);
+                       __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
+@@ -271,7 +270,7 @@ void unix_gc(void)
+               /* Move cursor to after the current position. */
+               list_move(&cursor, &u->link);
+-              if (atomic_long_read(&u->inflight) > 0) {
++              if (u->inflight) {
+                       list_move_tail(&u->link, &not_cycle_list);
+                       __clear_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
+                       scan_children(&u->sk, inc_inflight_move_tail, NULL);
+diff --git a/net/unix/scm.c b/net/unix/scm.c
+index d1048b4c2baaf..4eff7da9f6f96 100644
+--- a/net/unix/scm.c
++++ b/net/unix/scm.c
+@@ -52,12 +52,13 @@ void unix_inflight(struct user_struct *user, struct file *fp)
+       if (s) {
+               struct unix_sock *u = unix_sk(s);
+-              if (atomic_long_inc_return(&u->inflight) == 1) {
++              if (!u->inflight) {
+                       BUG_ON(!list_empty(&u->link));
+                       list_add_tail(&u->link, &gc_inflight_list);
+               } else {
+                       BUG_ON(list_empty(&u->link));
+               }
++              u->inflight++;
+               /* Paired with READ_ONCE() in wait_for_unix_gc() */
+               WRITE_ONCE(unix_tot_inflight, unix_tot_inflight + 1);
+       }
+@@ -74,10 +75,11 @@ void unix_notinflight(struct user_struct *user, struct file *fp)
+       if (s) {
+               struct unix_sock *u = unix_sk(s);
+-              BUG_ON(!atomic_long_read(&u->inflight));
++              BUG_ON(!u->inflight);
+               BUG_ON(list_empty(&u->link));
+-              if (atomic_long_dec_and_test(&u->inflight))
++              u->inflight--;
++              if (!u->inflight)
+                       list_del_init(&u->link);
+               /* Paired with READ_ONCE() in wait_for_unix_gc() */
+               WRITE_ONCE(unix_tot_inflight, unix_tot_inflight - 1);
+-- 
+2.43.0
+
diff --git a/queue-5.10/af_unix-fix-garbage-collector-racing-against-connect.patch b/queue-5.10/af_unix-fix-garbage-collector-racing-against-connect.patch
new file mode 100644 (file)
index 0000000..d98529e
--- /dev/null
@@ -0,0 +1,122 @@
+From 2ec6731a78b7246b538dec88213111c200f95738 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Apr 2024 22:09:39 +0200
+Subject: af_unix: Fix garbage collector racing against connect()
+
+From: Michal Luczaj <mhal@rbox.co>
+
+[ Upstream commit 47d8ac011fe1c9251070e1bd64cb10b48193ec51 ]
+
+Garbage collector does not take into account the risk of embryo getting
+enqueued during the garbage collection. If such embryo has a peer that
+carries SCM_RIGHTS, two consecutive passes of scan_children() may see a
+different set of children. Leading to an incorrectly elevated inflight
+count, and then a dangling pointer within the gc_inflight_list.
+
+sockets are AF_UNIX/SOCK_STREAM
+S is an unconnected socket
+L is a listening in-flight socket bound to addr, not in fdtable
+V's fd will be passed via sendmsg(), gets inflight count bumped
+
+connect(S, addr)       sendmsg(S, [V]); close(V)       __unix_gc()
+----------------       -------------------------       -----------
+
+NS = unix_create1()
+skb1 = sock_wmalloc(NS)
+L = unix_find_other(addr)
+unix_state_lock(L)
+unix_peer(S) = NS
+                       // V count=1 inflight=0
+
+                       NS = unix_peer(S)
+                       skb2 = sock_alloc()
+                       skb_queue_tail(NS, skb2[V])
+
+                       // V became in-flight
+                       // V count=2 inflight=1
+
+                       close(V)
+
+                       // V count=1 inflight=1
+                       // GC candidate condition met
+
+                                               for u in gc_inflight_list:
+                                                 if (total_refs == inflight_refs)
+                                                   add u to gc_candidates
+
+                                               // gc_candidates={L, V}
+
+                                               for u in gc_candidates:
+                                                 scan_children(u, dec_inflight)
+
+                                               // embryo (skb1) was not
+                                               // reachable from L yet, so V's
+                                               // inflight remains unchanged
+__skb_queue_tail(L, skb1)
+unix_state_unlock(L)
+                                               for u in gc_candidates:
+                                                 if (u.inflight)
+                                                   scan_children(u, inc_inflight_move_tail)
+
+                                               // V count=1 inflight=2 (!)
+
+If there is a GC-candidate listening socket, lock/unlock its state. This
+makes GC wait until the end of any ongoing connect() to that socket. After
+flipping the lock, a possibly SCM-laden embryo is already enqueued. And if
+there is another embryo coming, it can not possibly carry SCM_RIGHTS. At
+this point, unix_inflight() can not happen because unix_gc_lock is already
+taken. Inflight graph remains unaffected.
+
+Fixes: 1fd05ba5a2f2 ("[AF_UNIX]: Rewrite garbage collector, fixes race.")
+Signed-off-by: Michal Luczaj <mhal@rbox.co>
+Reviewed-by: Kuniyuki Iwashima <kuniyu@amazon.com>
+Link: https://lore.kernel.org/r/20240409201047.1032217-1-mhal@rbox.co
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/unix/garbage.c | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/net/unix/garbage.c b/net/unix/garbage.c
+index 675fbe594dbb3..58525311e903a 100644
+--- a/net/unix/garbage.c
++++ b/net/unix/garbage.c
+@@ -235,11 +235,22 @@ void unix_gc(void)
+        * receive queues.  Other, non candidate sockets _can_ be
+        * added to queue, so we must make sure only to touch
+        * candidates.
++       *
++       * Embryos, though never candidates themselves, affect which
++       * candidates are reachable by the garbage collector.  Before
++       * being added to a listener's queue, an embryo may already
++       * receive data carrying SCM_RIGHTS, potentially making the
++       * passed socket a candidate that is not yet reachable by the
++       * collector.  It becomes reachable once the embryo is
++       * enqueued.  Therefore, we must ensure that no SCM-laden
++       * embryo appears in a (candidate) listener's queue between
++       * consecutive scan_children() calls.
+        */
+       list_for_each_entry_safe(u, next, &gc_inflight_list, link) {
++              struct sock *sk = &u->sk;
+               long total_refs;
+-              total_refs = file_count(u->sk.sk_socket->file);
++              total_refs = file_count(sk->sk_socket->file);
+               BUG_ON(!u->inflight);
+               BUG_ON(total_refs < u->inflight);
+@@ -247,6 +258,11 @@ void unix_gc(void)
+                       list_move_tail(&u->link, &gc_candidates);
+                       __set_bit(UNIX_GC_CANDIDATE, &u->gc_flags);
+                       __set_bit(UNIX_GC_MAYBE_CYCLE, &u->gc_flags);
++
++                      if (sk->sk_state == TCP_LISTEN) {
++                              unix_state_lock(sk);
++                              unix_state_unlock(sk);
++                      }
+               }
+       }
+-- 
+2.43.0
+
diff --git a/queue-5.10/bluetooth-add-support-for-reading-aosp-vendor-capabi.patch b/queue-5.10/bluetooth-add-support-for-reading-aosp-vendor-capabi.patch
new file mode 100644 (file)
index 0000000..4df389e
--- /dev/null
@@ -0,0 +1,179 @@
+From a18146e51c874d5e9cfddb143e56023462004f3f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Apr 2021 21:55:52 +0200
+Subject: Bluetooth: Add support for reading AOSP vendor capabilities
+
+From: Marcel Holtmann <marcel@holtmann.org>
+
+[ Upstream commit f67743f9e03a67dbbf931d1787e6faf50766e521 ]
+
+When drivers indicate support for AOSP vendor extension, initialize them
+and read its capabilities.
+
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/bluetooth/hci_core.h | 11 ++++++++++
+ net/bluetooth/Kconfig            |  7 +++++++
+ net/bluetooth/Makefile           |  1 +
+ net/bluetooth/aosp.c             | 35 ++++++++++++++++++++++++++++++++
+ net/bluetooth/aosp.h             | 16 +++++++++++++++
+ net/bluetooth/hci_core.c         |  3 +++
+ 6 files changed, 73 insertions(+)
+ create mode 100644 net/bluetooth/aosp.c
+ create mode 100644 net/bluetooth/aosp.h
+
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index 33873266b2bc7..daafca376cb7c 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -569,6 +569,10 @@ struct hci_dev {
+       void                    *msft_data;
+ #endif
++#if IS_ENABLED(CONFIG_BT_AOSPEXT)
++      bool                    aosp_capable;
++#endif
++
+       int (*open)(struct hci_dev *hdev);
+       int (*close)(struct hci_dev *hdev);
+       int (*flush)(struct hci_dev *hdev);
+@@ -1222,6 +1226,13 @@ static inline void hci_set_msft_opcode(struct hci_dev *hdev, __u16 opcode)
+ #endif
+ }
++static inline void hci_set_aosp_capable(struct hci_dev *hdev)
++{
++#if IS_ENABLED(CONFIG_BT_AOSPEXT)
++      hdev->aosp_capable = true;
++#endif
++}
++
+ int hci_dev_open(__u16 dev);
+ int hci_dev_close(__u16 dev);
+ int hci_dev_do_close(struct hci_dev *hdev);
+diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig
+index 64e669acd42f9..11a563d95e67b 100644
+--- a/net/bluetooth/Kconfig
++++ b/net/bluetooth/Kconfig
+@@ -99,6 +99,13 @@ config BT_MSFTEXT
+         This options enables support for the Microsoft defined HCI
+         vendor extensions.
++config BT_AOSPEXT
++      bool "Enable Android Open Source Project extensions"
++      depends on BT
++      help
++        This options enables support for the Android Open Source
++        Project defined HCI vendor extensions.
++
+ config BT_DEBUGFS
+       bool "Export Bluetooth internals in debugfs"
+       depends on BT && DEBUG_FS
+diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
+index 1c645fba8c493..cc0995301f93f 100644
+--- a/net/bluetooth/Makefile
++++ b/net/bluetooth/Makefile
+@@ -20,5 +20,6 @@ bluetooth-$(CONFIG_BT_BREDR) += sco.o
+ bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o
+ bluetooth-$(CONFIG_BT_LEDS) += leds.o
+ bluetooth-$(CONFIG_BT_MSFTEXT) += msft.o
++bluetooth-$(CONFIG_BT_AOSPEXT) += aosp.o
+ bluetooth-$(CONFIG_BT_DEBUGFS) += hci_debugfs.o
+ bluetooth-$(CONFIG_BT_SELFTEST) += selftest.o
+diff --git a/net/bluetooth/aosp.c b/net/bluetooth/aosp.c
+new file mode 100644
+index 0000000000000..a1b7762335a51
+--- /dev/null
++++ b/net/bluetooth/aosp.c
+@@ -0,0 +1,35 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Copyright (C) 2021 Intel Corporation
++ */
++
++#include <net/bluetooth/bluetooth.h>
++#include <net/bluetooth/hci_core.h>
++
++#include "aosp.h"
++
++void aosp_do_open(struct hci_dev *hdev)
++{
++      struct sk_buff *skb;
++
++      if (!hdev->aosp_capable)
++              return;
++
++      bt_dev_dbg(hdev, "Initialize AOSP extension");
++
++      /* LE Get Vendor Capabilities Command */
++      skb = __hci_cmd_sync(hdev, hci_opcode_pack(0x3f, 0x153), 0, NULL,
++                           HCI_CMD_TIMEOUT);
++      if (IS_ERR(skb))
++              return;
++
++      kfree_skb(skb);
++}
++
++void aosp_do_close(struct hci_dev *hdev)
++{
++      if (!hdev->aosp_capable)
++              return;
++
++      bt_dev_dbg(hdev, "Cleanup of AOSP extension");
++}
+diff --git a/net/bluetooth/aosp.h b/net/bluetooth/aosp.h
+new file mode 100644
+index 0000000000000..328fc6d39f703
+--- /dev/null
++++ b/net/bluetooth/aosp.h
+@@ -0,0 +1,16 @@
++// SPDX-License-Identifier: GPL-2.0-only
++/*
++ * Copyright (C) 2021 Intel Corporation
++ */
++
++#if IS_ENABLED(CONFIG_BT_AOSPEXT)
++
++void aosp_do_open(struct hci_dev *hdev);
++void aosp_do_close(struct hci_dev *hdev);
++
++#else
++
++static inline void aosp_do_open(struct hci_dev *hdev) {}
++static inline void aosp_do_close(struct hci_dev *hdev) {}
++
++#endif
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index b9cf5bc9364c1..f4fc5a81ae928 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -44,6 +44,7 @@
+ #include "smp.h"
+ #include "leds.h"
+ #include "msft.h"
++#include "aosp.h"
+ static void hci_rx_work(struct work_struct *work);
+ static void hci_cmd_work(struct work_struct *work);
+@@ -1586,6 +1587,7 @@ static int hci_dev_do_open(struct hci_dev *hdev)
+               ret = hdev->set_diag(hdev, true);
+       msft_do_open(hdev);
++      aosp_do_open(hdev);
+       clear_bit(HCI_INIT, &hdev->flags);
+@@ -1788,6 +1790,7 @@ int hci_dev_do_close(struct hci_dev *hdev)
+       hci_sock_dev_event(hdev, HCI_DEV_DOWN);
++      aosp_do_close(hdev);
+       msft_do_close(hdev);
+       if (hdev->flush)
+-- 
+2.43.0
+
diff --git a/queue-5.10/bluetooth-allow-querying-of-supported-offload-codecs.patch b/queue-5.10/bluetooth-allow-querying-of-supported-offload-codecs.patch
new file mode 100644 (file)
index 0000000..b7647a8
--- /dev/null
@@ -0,0 +1,212 @@
+From 8bf980068612e7431ce14077b115729a05ebd523 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Sep 2021 15:42:40 +0530
+Subject: Bluetooth: Allow querying of supported offload codecs over SCO socket
+
+From: Kiran K <kiran.k@intel.com>
+
+[ Upstream commit 248733e87d503e75624a2e95e241f51334fdd320 ]
+
+Add BT_CODEC option for getsockopt systemcall to get the details
+of offload codecs supported over SCO socket
+
+Signed-off-by: Kiran K <kiran.k@intel.com>
+Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com>
+Reviewed-by: Srivatsa Ravishankar <ravishankar.srivatsa@intel.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/bluetooth/bluetooth.h |  20 ++++++
+ include/net/bluetooth/hci.h       |   4 ++
+ include/net/bluetooth/hci_core.h  |   1 +
+ net/bluetooth/sco.c               | 101 ++++++++++++++++++++++++++++++
+ 4 files changed, 126 insertions(+)
+
+diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
+index 355835639ae58..8700635f08a69 100644
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -153,6 +153,26 @@ struct bt_voice {
+ #define BT_SCM_PKT_STATUS     0x03
++#define BT_CODEC      19
++
++struct        bt_codec_caps {
++      __u8    len;
++      __u8    data[];
++} __packed;
++
++struct bt_codec {
++      __u8    id;
++      __u16   cid;
++      __u16   vid;
++      __u8    data_path;
++      __u8    num_caps;
++} __packed;
++
++struct bt_codecs {
++      __u8            num_codecs;
++      struct bt_codec codecs[];
++} __packed;
++
+ __printf(1, 2)
+ void bt_info(const char *fmt, ...);
+ __printf(1, 2)
+diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
+index 17ed339b54c73..fcb2852df3268 100644
+--- a/include/net/bluetooth/hci.h
++++ b/include/net/bluetooth/hci.h
+@@ -330,6 +330,7 @@ enum {
+       HCI_CMD_PENDING,
+       HCI_FORCE_NO_MITM,
+       HCI_QUALITY_REPORT,
++      HCI_OFFLOAD_CODECS_ENABLED,
+       __HCI_NUM_FLAGS,
+ };
+@@ -2584,6 +2585,9 @@ static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb)
+ #define hci_iso_data_len(h)           ((h) & 0x3fff)
+ #define hci_iso_data_flags(h)         ((h) >> 14)
++/* codec transport types */
++#define HCI_TRANSPORT_SCO_ESCO        0x01
++
+ /* le24 support */
+ static inline void hci_cpu_to_le24(__u32 val, __u8 dst[3])
+ {
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index 12d78527b0935..cb4d42a7a9f1f 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -599,6 +599,7 @@ struct hci_dev {
+       void (*cmd_timeout)(struct hci_dev *hdev);
+       bool (*prevent_wake)(struct hci_dev *hdev);
+       int (*set_quality_report)(struct hci_dev *hdev, bool enable);
++      int (*get_data_path_id)(struct hci_dev *hdev, __u8 *data_path);
+ };
+ #define HCI_PHY_HANDLE(handle)        (handle & 0xff)
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index 8244d3ae185bf..5e518a6d5e13d 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -967,6 +967,12 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
+       struct bt_voice voice;
+       u32 phys;
+       int pkt_status;
++      int buf_len;
++      struct codec_list *c;
++      u8 num_codecs, i, __user *ptr;
++      struct hci_dev *hdev;
++      struct hci_codec_caps *caps;
++      struct bt_codec codec;
+       BT_DBG("sk %p", sk);
+@@ -1031,6 +1037,101 @@ static int sco_sock_getsockopt(struct socket *sock, int level, int optname,
+                       err = -EFAULT;
+               break;
++      case BT_CODEC:
++              num_codecs = 0;
++              buf_len = 0;
++
++              hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR);
++              if (!hdev) {
++                      err = -EBADFD;
++                      break;
++              }
++
++              if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED)) {
++                      hci_dev_put(hdev);
++                      err = -EOPNOTSUPP;
++                      break;
++              }
++
++              if (!hdev->get_data_path_id) {
++                      hci_dev_put(hdev);
++                      err = -EOPNOTSUPP;
++                      break;
++              }
++
++              /* find total buffer size required to copy codec + caps */
++              hci_dev_lock(hdev);
++              list_for_each_entry(c, &hdev->local_codecs, list) {
++                      if (c->transport != HCI_TRANSPORT_SCO_ESCO)
++                              continue;
++                      num_codecs++;
++                      for (i = 0, caps = c->caps; i < c->num_caps; i++) {
++                              buf_len += 1 + caps->len;
++                              caps = (void *)&caps->data[caps->len];
++                      }
++                      buf_len += sizeof(struct bt_codec);
++              }
++              hci_dev_unlock(hdev);
++
++              buf_len += sizeof(struct bt_codecs);
++              if (buf_len > len) {
++                      hci_dev_put(hdev);
++                      err = -ENOBUFS;
++                      break;
++              }
++              ptr = optval;
++
++              if (put_user(num_codecs, ptr)) {
++                      hci_dev_put(hdev);
++                      err = -EFAULT;
++                      break;
++              }
++              ptr += sizeof(num_codecs);
++
++              /* Iterate all the codecs supported over SCO and populate
++               * codec data
++               */
++              hci_dev_lock(hdev);
++              list_for_each_entry(c, &hdev->local_codecs, list) {
++                      if (c->transport != HCI_TRANSPORT_SCO_ESCO)
++                              continue;
++
++                      codec.id = c->id;
++                      codec.cid = c->cid;
++                      codec.vid = c->vid;
++                      err = hdev->get_data_path_id(hdev, &codec.data_path);
++                      if (err < 0)
++                              break;
++                      codec.num_caps = c->num_caps;
++                      if (copy_to_user(ptr, &codec, sizeof(codec))) {
++                              err = -EFAULT;
++                              break;
++                      }
++                      ptr += sizeof(codec);
++
++                      /* find codec capabilities data length */
++                      len = 0;
++                      for (i = 0, caps = c->caps; i < c->num_caps; i++) {
++                              len += 1 + caps->len;
++                              caps = (void *)&caps->data[caps->len];
++                      }
++
++                      /* copy codec capabilities data */
++                      if (len && copy_to_user(ptr, c->caps, len)) {
++                              err = -EFAULT;
++                              break;
++                      }
++                      ptr += len;
++              }
++
++              if (!err && put_user(buf_len, optlen))
++                      err = -EFAULT;
++
++              hci_dev_unlock(hdev);
++              hci_dev_put(hdev);
++
++              break;
++
+       default:
+               err = -ENOPROTOOPT;
+               break;
+-- 
+2.43.0
+
diff --git a/queue-5.10/bluetooth-allow-setting-of-codec-for-hfp-offload-use.patch b/queue-5.10/bluetooth-allow-setting-of-codec-for-hfp-offload-use.patch
new file mode 100644 (file)
index 0000000..84e6062
--- /dev/null
@@ -0,0 +1,139 @@
+From 7e59316473bc029ca3bfcea291cd36332f76dd57 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Sep 2021 15:42:42 +0530
+Subject: Bluetooth: Allow setting of codec for HFP offload use case
+
+From: Kiran K <kiran.k@intel.com>
+
+[ Upstream commit f6873401a60865702069fb2e3f67671fff9c082c ]
+
+This patch allows user space to set the codec that needs to
+be used for HFP offload use case. The codec details are cached and
+the controller is configured before opening the SCO connection.
+
+Signed-off-by: Kiran K <kiran.k@intel.com>
+Reviewed-by: Chethan T N <chethan.tumkur.narayan@intel.com>
+Reviewed-by: Srivatsa Ravishankar <ravishankar.srivatsa@intel.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/bluetooth/bluetooth.h |  2 ++
+ net/bluetooth/sco.c               | 60 +++++++++++++++++++++++++++++++
+ 2 files changed, 62 insertions(+)
+
+diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
+index 8700635f08a69..4191edbb0641d 100644
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -173,6 +173,8 @@ struct bt_codecs {
+       struct bt_codec codecs[];
+ } __packed;
++#define BT_CODEC_CVSD 0x02
++
+ __printf(1, 2)
+ void bt_info(const char *fmt, ...);
+ __printf(1, 2)
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index 5e518a6d5e13d..cef26f1d8a583 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -69,6 +69,7 @@ struct sco_pinfo {
+       __u32           flags;
+       __u16           setting;
+       __u8            cmsg_mask;
++      struct bt_codec codec;
+       struct sco_conn *conn;
+ };
+@@ -434,6 +435,7 @@ static void __sco_sock_close(struct sock *sk)
+               sock_set_flag(sk, SOCK_ZAPPED);
+               break;
+       }
++
+ }
+ /* Must be called on unlocked socket. */
+@@ -494,6 +496,10 @@ static struct sock *sco_sock_alloc(struct net *net, struct socket *sock,
+       sk->sk_state    = BT_OPEN;
+       sco_pi(sk)->setting = BT_VOICE_CVSD_16BIT;
++      sco_pi(sk)->codec.id = BT_CODEC_CVSD;
++      sco_pi(sk)->codec.cid = 0xffff;
++      sco_pi(sk)->codec.vid = 0xffff;
++      sco_pi(sk)->codec.data_path = 0x00;
+       bt_sock_link(&sco_sk_list, sk);
+       return sk;
+@@ -828,6 +834,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+       int len, err = 0;
+       struct bt_voice voice;
+       u32 opt;
++      struct bt_codecs *codecs;
++      struct hci_dev *hdev;
++      __u8 buffer[255];
+       BT_DBG("sk %p", sk);
+@@ -889,6 +898,57 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+                       sco_pi(sk)->cmsg_mask &= SCO_CMSG_PKT_STATUS;
+               break;
++      case BT_CODEC:
++              if (sk->sk_state != BT_OPEN && sk->sk_state != BT_BOUND &&
++                  sk->sk_state != BT_CONNECT2) {
++                      err = -EINVAL;
++                      break;
++              }
++
++              hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src,
++                                   BDADDR_BREDR);
++              if (!hdev) {
++                      err = -EBADFD;
++                      break;
++              }
++
++              if (!hci_dev_test_flag(hdev, HCI_OFFLOAD_CODECS_ENABLED)) {
++                      hci_dev_put(hdev);
++                      err = -EOPNOTSUPP;
++                      break;
++              }
++
++              if (!hdev->get_data_path_id) {
++                      hci_dev_put(hdev);
++                      err = -EOPNOTSUPP;
++                      break;
++              }
++
++              if (optlen < sizeof(struct bt_codecs) ||
++                  optlen > sizeof(buffer)) {
++                      hci_dev_put(hdev);
++                      err = -EINVAL;
++                      break;
++              }
++
++              if (copy_from_sockptr(buffer, optval, optlen)) {
++                      hci_dev_put(hdev);
++                      err = -EFAULT;
++                      break;
++              }
++
++              codecs = (void *)buffer;
++
++              if (codecs->num_codecs > 1) {
++                      hci_dev_put(hdev);
++                      err = -EINVAL;
++                      break;
++              }
++
++              sco_pi(sk)->codec = codecs->codecs[0];
++              hci_dev_put(hdev);
++              break;
++
+       default:
+               err = -ENOPROTOOPT;
+               break;
+-- 
+2.43.0
+
diff --git a/queue-5.10/bluetooth-enumerate-local-supported-codec-and-cache-.patch b/queue-5.10/bluetooth-enumerate-local-supported-codec-and-cache-.patch
new file mode 100644 (file)
index 0000000..5dce1d8
--- /dev/null
@@ -0,0 +1,384 @@
+From 2db9c07bee1bfa5bd156e52dfb5f31eeb313e545 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Sep 2021 15:42:37 +0530
+Subject: Bluetooth: Enumerate local supported codec and cache details
+
+From: Kiran K <kiran.k@intel.com>
+
+[ Upstream commit 8961987f3f5fa2f2618e72304d013c8dd5e604a6 ]
+
+Move reading of supported local codecs into a separate init function,
+query codecs capabilities and cache the data
+
+Signed-off-by: Kiran K <kiran.k@intel.com>
+Signed-off-by: Chethan T N <chethan.tumkur.narayan@intel.com>
+Signed-off-by: Srivatsa Ravishankar <ravishankar.srivatsa@intel.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/bluetooth/hci.h      |  41 ++++++++
+ include/net/bluetooth/hci_core.h |  17 +++
+ net/bluetooth/Makefile           |   2 +-
+ net/bluetooth/hci_codec.c        | 172 +++++++++++++++++++++++++++++++
+ net/bluetooth/hci_codec.h        |   6 ++
+ net/bluetooth/hci_core.c         |  11 +-
+ 6 files changed, 244 insertions(+), 5 deletions(-)
+ create mode 100644 net/bluetooth/hci_codec.c
+ create mode 100644 net/bluetooth/hci_codec.h
+
+diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
+index 0e36974da384c..17ed339b54c73 100644
+--- a/include/net/bluetooth/hci.h
++++ b/include/net/bluetooth/hci.h
+@@ -1306,6 +1306,28 @@ struct hci_rp_read_data_block_size {
+ } __packed;
+ #define HCI_OP_READ_LOCAL_CODECS      0x100b
++struct hci_std_codecs {
++      __u8    num;
++      __u8    codec[];
++} __packed;
++
++struct hci_vnd_codec {
++      /* company id */
++      __le16  cid;
++      /* vendor codec id */
++      __le16  vid;
++} __packed;
++
++struct hci_vnd_codecs {
++      __u8    num;
++      struct hci_vnd_codec codec[];
++} __packed;
++
++struct hci_rp_read_local_supported_codecs {
++      __u8    status;
++      struct hci_std_codecs std_codecs;
++      struct hci_vnd_codecs vnd_codecs;
++} __packed;
+ #define HCI_OP_READ_LOCAL_PAIRING_OPTS        0x100c
+ struct hci_rp_read_local_pairing_opts {
+@@ -1314,6 +1336,25 @@ struct hci_rp_read_local_pairing_opts {
+       __u8     max_key_size;
+ } __packed;
++#define HCI_OP_READ_LOCAL_CODEC_CAPS  0x100e
++struct hci_op_read_local_codec_caps {
++      __u8    id;
++      __le16  cid;
++      __le16  vid;
++      __u8    transport;
++      __u8    direction;
++} __packed;
++
++struct hci_codec_caps {
++      __u8    len;
++      __u8    data[];
++} __packed;
++
++struct hci_rp_read_local_codec_caps {
++      __u8    status;
++      __u8    num_caps;
++} __packed;
++
+ #define HCI_OP_READ_PAGE_SCAN_ACTIVITY        0x0c1b
+ struct hci_rp_read_page_scan_activity {
+       __u8     status;
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index c8f11dde54837..12d78527b0935 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -132,6 +132,17 @@ struct bdaddr_list {
+       u8 bdaddr_type;
+ };
++struct codec_list {
++      struct list_head list;
++      u8      id;
++      __u16   cid;
++      __u16   vid;
++      u8      transport;
++      u8      num_caps;
++      u32     len;
++      struct hci_codec_caps caps[];
++};
++
+ struct bdaddr_list_with_irk {
+       struct list_head list;
+       bdaddr_t bdaddr;
+@@ -517,6 +528,7 @@ struct hci_dev {
+       struct list_head        pend_le_conns;
+       struct list_head        pend_le_reports;
+       struct list_head        blocked_keys;
++      struct list_head        local_codecs;
+       struct hci_dev_stats    stat;
+@@ -1819,4 +1831,9 @@ void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr,
+ #define SCO_AIRMODE_CVSD       0x0000
+ #define SCO_AIRMODE_TRANSP     0x0003
++#define LOCAL_CODEC_ACL_MASK  BIT(0)
++#define LOCAL_CODEC_SCO_MASK  BIT(1)
++
++#define TRANSPORT_TYPE_MAX    0x04
++
+ #endif /* __HCI_CORE_H */
+diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile
+index cc0995301f93f..f3e439d98b85a 100644
+--- a/net/bluetooth/Makefile
++++ b/net/bluetooth/Makefile
+@@ -14,7 +14,7 @@ bluetooth_6lowpan-y := 6lowpan.o
+ bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \
+       hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o lib.o \
+-      ecdh_helper.o hci_request.o mgmt_util.o mgmt_config.o
++      ecdh_helper.o hci_request.o mgmt_util.o mgmt_config.o hci_codec.o
+ bluetooth-$(CONFIG_BT_BREDR) += sco.o
+ bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o
+diff --git a/net/bluetooth/hci_codec.c b/net/bluetooth/hci_codec.c
+new file mode 100644
+index 0000000000000..f86ca6ba5814f
+--- /dev/null
++++ b/net/bluetooth/hci_codec.c
+@@ -0,0 +1,172 @@
++// SPDX-License-Identifier: GPL-2.0
++
++/* Copyright (C) 2021 Intel Corporation */
++
++#include <net/bluetooth/bluetooth.h>
++#include <net/bluetooth/hci_core.h>
++#include "hci_codec.h"
++
++static int hci_codec_list_add(struct list_head *list,
++                            struct hci_op_read_local_codec_caps *sent,
++                            struct hci_rp_read_local_codec_caps *rp,
++                            void *caps,
++                            __u32 len)
++{
++      struct codec_list *entry;
++
++      entry = kzalloc(sizeof(*entry) + len, GFP_KERNEL);
++      if (!entry)
++              return -ENOMEM;
++
++      entry->id = sent->id;
++      if (sent->id == 0xFF) {
++              entry->cid = __le16_to_cpu(sent->cid);
++              entry->vid = __le16_to_cpu(sent->vid);
++      }
++      entry->transport = sent->transport;
++      entry->len = len;
++      entry->num_caps = rp->num_caps;
++      if (rp->num_caps)
++              memcpy(entry->caps, caps, len);
++      list_add(&entry->list, list);
++
++      return 0;
++}
++
++void hci_codec_list_clear(struct list_head *codec_list)
++{
++      struct codec_list *c, *n;
++
++      list_for_each_entry_safe(c, n, codec_list, list) {
++              list_del(&c->list);
++              kfree(c);
++      }
++}
++
++static void hci_read_codec_capabilities(struct hci_dev *hdev, __u8 transport,
++                                      struct hci_op_read_local_codec_caps
++                                      *cmd)
++{
++      __u8 i;
++
++      for (i = 0; i < TRANSPORT_TYPE_MAX; i++) {
++              if (transport & BIT(i)) {
++                      struct hci_rp_read_local_codec_caps *rp;
++                      struct hci_codec_caps *caps;
++                      struct sk_buff *skb;
++                      __u8 j;
++                      __u32 len;
++
++                      cmd->transport = i;
++                      skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_CODEC_CAPS,
++                                           sizeof(*cmd), cmd,
++                                           HCI_CMD_TIMEOUT);
++                      if (IS_ERR(skb)) {
++                              bt_dev_err(hdev, "Failed to read codec capabilities (%ld)",
++                                         PTR_ERR(skb));
++                              continue;
++                      }
++
++                      if (skb->len < sizeof(*rp))
++                              goto error;
++
++                      rp = (void *)skb->data;
++
++                      if (rp->status)
++                              goto error;
++
++                      if (!rp->num_caps) {
++                              len = 0;
++                              /* this codec doesn't have capabilities */
++                              goto skip_caps_parse;
++                      }
++
++                      skb_pull(skb, sizeof(*rp));
++
++                      for (j = 0, len = 0; j < rp->num_caps; j++) {
++                              caps = (void *)skb->data;
++                              if (skb->len < sizeof(*caps))
++                                      goto error;
++                              if (skb->len < caps->len)
++                                      goto error;
++                              len += sizeof(caps->len) + caps->len;
++                              skb_pull(skb,  sizeof(caps->len) + caps->len);
++                      }
++
++skip_caps_parse:
++                      hci_dev_lock(hdev);
++                      hci_codec_list_add(&hdev->local_codecs, cmd, rp,
++                                         (__u8 *)rp + sizeof(*rp), len);
++                      hci_dev_unlock(hdev);
++error:
++                      kfree_skb(skb);
++              }
++      }
++}
++
++void hci_read_supported_codecs(struct hci_dev *hdev)
++{
++      struct sk_buff *skb;
++      struct hci_rp_read_local_supported_codecs *rp;
++      struct hci_std_codecs *std_codecs;
++      struct hci_vnd_codecs *vnd_codecs;
++      struct hci_op_read_local_codec_caps caps;
++      __u8 i;
++
++      skb = __hci_cmd_sync(hdev, HCI_OP_READ_LOCAL_CODECS, 0, NULL,
++                           HCI_CMD_TIMEOUT);
++
++      if (IS_ERR(skb)) {
++              bt_dev_err(hdev, "Failed to read local supported codecs (%ld)",
++                         PTR_ERR(skb));
++              return;
++      }
++
++      if (skb->len < sizeof(*rp))
++              goto error;
++
++      rp = (void *)skb->data;
++
++      if (rp->status)
++              goto error;
++
++      skb_pull(skb, sizeof(rp->status));
++
++      std_codecs = (void *)skb->data;
++
++      /* validate codecs length before accessing */
++      if (skb->len < flex_array_size(std_codecs, codec, std_codecs->num)
++          + sizeof(std_codecs->num))
++              goto error;
++
++      /* enumerate codec capabilities of standard codecs */
++      memset(&caps, 0, sizeof(caps));
++      for (i = 0; i < std_codecs->num; i++) {
++              caps.id = std_codecs->codec[i];
++              caps.direction = 0x00;
++              hci_read_codec_capabilities(hdev, LOCAL_CODEC_ACL_MASK, &caps);
++      }
++
++      skb_pull(skb, flex_array_size(std_codecs, codec, std_codecs->num)
++               + sizeof(std_codecs->num));
++
++      vnd_codecs = (void *)skb->data;
++
++      /* validate vendor codecs length before accessing */
++      if (skb->len <
++          flex_array_size(vnd_codecs, codec, vnd_codecs->num)
++          + sizeof(vnd_codecs->num))
++              goto error;
++
++      /* enumerate vendor codec capabilities */
++      for (i = 0; i < vnd_codecs->num; i++) {
++              caps.id = 0xFF;
++              caps.cid = vnd_codecs->codec[i].cid;
++              caps.vid = vnd_codecs->codec[i].vid;
++              caps.direction = 0x00;
++              hci_read_codec_capabilities(hdev, LOCAL_CODEC_ACL_MASK, &caps);
++      }
++
++error:
++      kfree_skb(skb);
++}
+diff --git a/net/bluetooth/hci_codec.h b/net/bluetooth/hci_codec.h
+new file mode 100644
+index 0000000000000..efb0df634ac6b
+--- /dev/null
++++ b/net/bluetooth/hci_codec.h
+@@ -0,0 +1,6 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++
++/* Copyright (C) 2014 Intel Corporation */
++
++void hci_read_supported_codecs(struct hci_dev *hdev);
++void hci_codec_list_clear(struct list_head *codec_list);
+diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
+index f4fc5a81ae928..0944721a786ba 100644
+--- a/net/bluetooth/hci_core.c
++++ b/net/bluetooth/hci_core.c
+@@ -45,6 +45,7 @@
+ #include "leds.h"
+ #include "msft.h"
+ #include "aosp.h"
++#include "hci_codec.h"
+ static void hci_rx_work(struct work_struct *work);
+ static void hci_cmd_work(struct work_struct *work);
+@@ -832,10 +833,6 @@ static int hci_init4_req(struct hci_request *req, unsigned long opt)
+       if (hdev->commands[22] & 0x04)
+               hci_set_event_mask_page_2(req);
+-      /* Read local codec list if the HCI command is supported */
+-      if (hdev->commands[29] & 0x20)
+-              hci_req_add(req, HCI_OP_READ_LOCAL_CODECS, 0, NULL);
+-
+       /* Read local pairing options if the HCI command is supported */
+       if (hdev->commands[41] & 0x08)
+               hci_req_add(req, HCI_OP_READ_LOCAL_PAIRING_OPTS, 0, NULL);
+@@ -931,6 +928,10 @@ static int __hci_init(struct hci_dev *hdev)
+       if (err < 0)
+               return err;
++      /* Read local codec list if the HCI command is supported */
++      if (hdev->commands[29] & 0x20)
++              hci_read_supported_codecs(hdev);
++
+       /* This function is only called when the controller is actually in
+        * configured state. When the controller is marked as unconfigured,
+        * this initialization procedure is not run.
+@@ -1841,6 +1842,7 @@ int hci_dev_do_close(struct hci_dev *hdev)
+       memset(hdev->eir, 0, sizeof(hdev->eir));
+       memset(hdev->dev_class, 0, sizeof(hdev->dev_class));
+       bacpy(&hdev->random_addr, BDADDR_ANY);
++      hci_codec_list_clear(&hdev->local_codecs);
+       hci_req_sync_unlock(hdev);
+@@ -3678,6 +3680,7 @@ struct hci_dev *hci_alloc_dev(void)
+       INIT_LIST_HEAD(&hdev->adv_instances);
+       INIT_LIST_HEAD(&hdev->blocked_keys);
++      INIT_LIST_HEAD(&hdev->local_codecs);
+       INIT_WORK(&hdev->rx_work, hci_rx_work);
+       INIT_WORK(&hdev->cmd_work, hci_cmd_work);
+       INIT_WORK(&hdev->tx_work, hci_tx_work);
+-- 
+2.43.0
+
diff --git a/queue-5.10/bluetooth-fix-mgmt-status-for-ll-privacy-experimenta.patch b/queue-5.10/bluetooth-fix-mgmt-status-for-ll-privacy-experimenta.patch
new file mode 100644 (file)
index 0000000..6a6e1e9
--- /dev/null
@@ -0,0 +1,37 @@
+From 704cacb29acbc095280862f903c7c19487f5f6f0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 14 Mar 2021 14:49:38 +0100
+Subject: Bluetooth: Fix mgmt status for LL Privacy experimental feature
+
+From: Marcel Holtmann <marcel@holtmann.org>
+
+[ Upstream commit 353cac0e108f0484b101fd8cc6c2c0c5d9100ca6 ]
+
+The return error when trying to change the setting when a controller is
+powered up, shall be MGMT_STATUS_REJECTED. However instead now the error
+MGMT_STATUS_NOT_POWERED is used which is exactly the opposite.
+
+Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index bd8cfcfca7aef..fd8bdafb71a0e 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -3968,7 +3968,7 @@ static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
+               if (hdev_is_powered(hdev))
+                       return mgmt_cmd_status(sk, hdev->id,
+                                              MGMT_OP_SET_EXP_FEATURE,
+-                                             MGMT_STATUS_NOT_POWERED);
++                                             MGMT_STATUS_REJECTED);
+               /* Parameters are limited to a single octet */
+               if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
+-- 
+2.43.0
+
diff --git a/queue-5.10/bluetooth-refactor-set_exp_feature-with-a-feature-ta.patch b/queue-5.10/bluetooth-refactor-set_exp_feature-with-a-feature-ta.patch
new file mode 100644 (file)
index 0000000..3c8fb44
--- /dev/null
@@ -0,0 +1,330 @@
+From 2530dd42cf909251594d1aa00c51ae026bf5926d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 15 Aug 2021 20:17:15 +0800
+Subject: Bluetooth: refactor set_exp_feature with a feature table
+
+From: Joseph Hwang <josephsih@chromium.org>
+
+[ Upstream commit 93fb70bc112e922def6e50b37e20ccfce0c67c0a ]
+
+This patch refactors the set_exp_feature with a feature table
+consisting of UUIDs and the corresponding callback functions.
+In this way, a new experimental feature setting function can be
+simply added with its UUID and callback function.
+
+Signed-off-by: Joseph Hwang <josephsih@chromium.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/bluetooth/mgmt.c | 248 +++++++++++++++++++++++++------------------
+ 1 file changed, 142 insertions(+), 106 deletions(-)
+
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index fd8bdafb71a0e..8acfd9db00d63 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -3784,7 +3784,7 @@ static const u8 rpa_resolution_uuid[16] = {
+ static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
+                                 void *data, u16 data_len)
+ {
+-      char buf[62];   /* Enough space for 3 features */
++      char buf[62];   /* Enough space for 3 features */
+       struct mgmt_rp_read_exp_features_info *rp = (void *)buf;
+       u16 idx = 0;
+       u32 flags;
+@@ -3870,150 +3870,186 @@ static int exp_debug_feature_changed(bool enabled, struct sock *skip)
+ }
+ #endif
+-static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
+-                         void *data, u16 data_len)
++#define EXP_FEAT(_uuid, _set_func)    \
++{                                     \
++      .uuid = _uuid,                  \
++      .set_func = _set_func,          \
++}
++
++/* The zero key uuid is special. Multiple exp features are set through it. */
++static int set_zero_key_func(struct sock *sk, struct hci_dev *hdev,
++                           struct mgmt_cp_set_exp_feature *cp, u16 data_len)
+ {
+-      struct mgmt_cp_set_exp_feature *cp = data;
+       struct mgmt_rp_set_exp_feature rp;
+-      bt_dev_dbg(hdev, "sock %p", sk);
+-
+-      if (!memcmp(cp->uuid, ZERO_KEY, 16)) {
+-              memset(rp.uuid, 0, 16);
+-              rp.flags = cpu_to_le32(0);
++      memset(rp.uuid, 0, 16);
++      rp.flags = cpu_to_le32(0);
+ #ifdef CONFIG_BT_FEATURE_DEBUG
+-              if (!hdev) {
+-                      bool changed = bt_dbg_get();
++      if (!hdev) {
++              bool changed = bt_dbg_get();
+-                      bt_dbg_set(false);
++              bt_dbg_set(false);
+-                      if (changed)
+-                              exp_debug_feature_changed(false, sk);
+-              }
++              if (changed)
++                      exp_debug_feature_changed(false, sk);
++      }
+ #endif
+-              if (hdev && use_ll_privacy(hdev) && !hdev_is_powered(hdev)) {
+-                      bool changed = hci_dev_test_flag(hdev,
+-                                                       HCI_ENABLE_LL_PRIVACY);
++      if (hdev && use_ll_privacy(hdev) && !hdev_is_powered(hdev)) {
++              bool changed = hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY);
+-                      hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
++              hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
+-                      if (changed)
+-                              exp_ll_privacy_feature_changed(false, hdev, sk);
+-              }
++              if (changed)
++                      exp_ll_privacy_feature_changed(false, hdev, sk);
++      }
+-              hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
++      hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
+-              return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
+-                                       MGMT_OP_SET_EXP_FEATURE, 0,
+-                                       &rp, sizeof(rp));
+-      }
++      return mgmt_cmd_complete(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
++                               MGMT_OP_SET_EXP_FEATURE, 0,
++                               &rp, sizeof(rp));
++}
+ #ifdef CONFIG_BT_FEATURE_DEBUG
+-      if (!memcmp(cp->uuid, debug_uuid, 16)) {
+-              bool val, changed;
+-              int err;
++static int set_debug_func(struct sock *sk, struct hci_dev *hdev,
++                        struct mgmt_cp_set_exp_feature *cp, u16 data_len)
++{
++      struct mgmt_rp_set_exp_feature rp;
+-              /* Command requires to use the non-controller index */
+-              if (hdev)
+-                      return mgmt_cmd_status(sk, hdev->id,
+-                                             MGMT_OP_SET_EXP_FEATURE,
+-                                             MGMT_STATUS_INVALID_INDEX);
++      bool val, changed;
++      int err;
+-              /* Parameters are limited to a single octet */
+-              if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
+-                      return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
+-                                             MGMT_OP_SET_EXP_FEATURE,
+-                                             MGMT_STATUS_INVALID_PARAMS);
++      /* Command requires to use the non-controller index */
++      if (hdev)
++              return mgmt_cmd_status(sk, hdev->id,
++                                     MGMT_OP_SET_EXP_FEATURE,
++                                     MGMT_STATUS_INVALID_INDEX);
+-              /* Only boolean on/off is supported */
+-              if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
+-                      return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
+-                                             MGMT_OP_SET_EXP_FEATURE,
+-                                             MGMT_STATUS_INVALID_PARAMS);
++      /* Parameters are limited to a single octet */
++      if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
++              return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
++                                     MGMT_OP_SET_EXP_FEATURE,
++                                     MGMT_STATUS_INVALID_PARAMS);
+-              val = !!cp->param[0];
+-              changed = val ? !bt_dbg_get() : bt_dbg_get();
+-              bt_dbg_set(val);
++      /* Only boolean on/off is supported */
++      if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
++              return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
++                                     MGMT_OP_SET_EXP_FEATURE,
++                                     MGMT_STATUS_INVALID_PARAMS);
+-              memcpy(rp.uuid, debug_uuid, 16);
+-              rp.flags = cpu_to_le32(val ? BIT(0) : 0);
++      val = !!cp->param[0];
++      changed = val ? !bt_dbg_get() : bt_dbg_get();
++      bt_dbg_set(val);
+-              hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
++      memcpy(rp.uuid, debug_uuid, 16);
++      rp.flags = cpu_to_le32(val ? BIT(0) : 0);
+-              err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
+-                                      MGMT_OP_SET_EXP_FEATURE, 0,
+-                                      &rp, sizeof(rp));
++      hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
+-              if (changed)
+-                      exp_debug_feature_changed(val, sk);
++      err = mgmt_cmd_complete(sk, MGMT_INDEX_NONE,
++                              MGMT_OP_SET_EXP_FEATURE, 0,
++                              &rp, sizeof(rp));
+-              return err;
+-      }
++      if (changed)
++              exp_debug_feature_changed(val, sk);
++
++      return err;
++}
+ #endif
+-      if (!memcmp(cp->uuid, rpa_resolution_uuid, 16)) {
+-              bool val, changed;
+-              int err;
+-              u32 flags;
++static int set_rpa_resolution_func(struct sock *sk, struct hci_dev *hdev,
++                                 struct mgmt_cp_set_exp_feature *cp,
++                                 u16 data_len)
++{
++      struct mgmt_rp_set_exp_feature rp;
++      bool val, changed;
++      int err;
++      u32 flags;
++
++      /* Command requires to use the controller index */
++      if (!hdev)
++              return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
++                                     MGMT_OP_SET_EXP_FEATURE,
++                                     MGMT_STATUS_INVALID_INDEX);
+-              /* Command requires to use the controller index */
+-              if (!hdev)
+-                      return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
+-                                             MGMT_OP_SET_EXP_FEATURE,
+-                                             MGMT_STATUS_INVALID_INDEX);
++      /* Changes can only be made when controller is powered down */
++      if (hdev_is_powered(hdev))
++              return mgmt_cmd_status(sk, hdev->id,
++                                     MGMT_OP_SET_EXP_FEATURE,
++                                     MGMT_STATUS_REJECTED);
+-              /* Changes can only be made when controller is powered down */
+-              if (hdev_is_powered(hdev))
+-                      return mgmt_cmd_status(sk, hdev->id,
+-                                             MGMT_OP_SET_EXP_FEATURE,
+-                                             MGMT_STATUS_REJECTED);
++      /* Parameters are limited to a single octet */
++      if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
++              return mgmt_cmd_status(sk, hdev->id,
++                                     MGMT_OP_SET_EXP_FEATURE,
++                                     MGMT_STATUS_INVALID_PARAMS);
+-              /* Parameters are limited to a single octet */
+-              if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
+-                      return mgmt_cmd_status(sk, hdev->id,
+-                                             MGMT_OP_SET_EXP_FEATURE,
+-                                             MGMT_STATUS_INVALID_PARAMS);
++      /* Only boolean on/off is supported */
++      if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
++              return mgmt_cmd_status(sk, hdev->id,
++                                     MGMT_OP_SET_EXP_FEATURE,
++                                     MGMT_STATUS_INVALID_PARAMS);
+-              /* Only boolean on/off is supported */
+-              if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
+-                      return mgmt_cmd_status(sk, hdev->id,
+-                                             MGMT_OP_SET_EXP_FEATURE,
+-                                             MGMT_STATUS_INVALID_PARAMS);
++      val = !!cp->param[0];
+-              val = !!cp->param[0];
++      if (val) {
++              changed = !hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY);
++              hci_dev_set_flag(hdev, HCI_ENABLE_LL_PRIVACY);
++              hci_dev_clear_flag(hdev, HCI_ADVERTISING);
+-              if (val) {
+-                      changed = !hci_dev_test_flag(hdev,
+-                                                   HCI_ENABLE_LL_PRIVACY);
+-                      hci_dev_set_flag(hdev, HCI_ENABLE_LL_PRIVACY);
+-                      hci_dev_clear_flag(hdev, HCI_ADVERTISING);
++              /* Enable LL privacy + supported settings changed */
++              flags = BIT(0) | BIT(1);
++      } else {
++              changed = hci_dev_test_flag(hdev, HCI_ENABLE_LL_PRIVACY);
++              hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
+-                      /* Enable LL privacy + supported settings changed */
+-                      flags = BIT(0) | BIT(1);
+-              } else {
+-                      changed = hci_dev_test_flag(hdev,
+-                                                  HCI_ENABLE_LL_PRIVACY);
+-                      hci_dev_clear_flag(hdev, HCI_ENABLE_LL_PRIVACY);
++              /* Disable LL privacy + supported settings changed */
++              flags = BIT(1);
++      }
+-                      /* Disable LL privacy + supported settings changed */
+-                      flags = BIT(1);
+-              }
++      memcpy(rp.uuid, rpa_resolution_uuid, 16);
++      rp.flags = cpu_to_le32(flags);
+-              memcpy(rp.uuid, rpa_resolution_uuid, 16);
+-              rp.flags = cpu_to_le32(flags);
++      hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
+-              hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
++      err = mgmt_cmd_complete(sk, hdev->id,
++                              MGMT_OP_SET_EXP_FEATURE, 0,
++                              &rp, sizeof(rp));
+-              err = mgmt_cmd_complete(sk, hdev->id,
+-                                      MGMT_OP_SET_EXP_FEATURE, 0,
+-                                      &rp, sizeof(rp));
++      if (changed)
++              exp_ll_privacy_feature_changed(val, hdev, sk);
+-              if (changed)
+-                      exp_ll_privacy_feature_changed(val, hdev, sk);
++      return err;
++}
+-              return err;
++static const struct mgmt_exp_feature {
++      const u8 *uuid;
++      int (*set_func)(struct sock *sk, struct hci_dev *hdev,
++                      struct mgmt_cp_set_exp_feature *cp, u16 data_len);
++} exp_features[] = {
++      EXP_FEAT(ZERO_KEY, set_zero_key_func),
++#ifdef CONFIG_BT_FEATURE_DEBUG
++      EXP_FEAT(debug_uuid, set_debug_func),
++#endif
++      EXP_FEAT(rpa_resolution_uuid, set_rpa_resolution_func),
++
++      /* end with a null feature */
++      EXP_FEAT(NULL, NULL)
++};
++
++static int set_exp_feature(struct sock *sk, struct hci_dev *hdev,
++                         void *data, u16 data_len)
++{
++      struct mgmt_cp_set_exp_feature *cp = data;
++      size_t i = 0;
++
++      bt_dev_dbg(hdev, "sock %p", sk);
++
++      for (i = 0; exp_features[i].uuid; i++) {
++              if (!memcmp(cp->uuid, exp_features[i].uuid, 16))
++                      return exp_features[i].set_func(sk, hdev, cp, data_len);
+       }
+       return mgmt_cmd_status(sk, hdev ? hdev->id : MGMT_INDEX_NONE,
+-- 
+2.43.0
+
diff --git a/queue-5.10/bluetooth-sco-fix-not-validating-setsockopt-user-inp.patch b/queue-5.10/bluetooth-sco-fix-not-validating-setsockopt-user-inp.patch
new file mode 100644 (file)
index 0000000..e073a6c
--- /dev/null
@@ -0,0 +1,122 @@
+From 9ed24baace071a8d8d8d02e3d755d9e7e9b8142c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Apr 2024 15:41:52 -0400
+Subject: Bluetooth: SCO: Fix not validating setsockopt user input
+
+From: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+
+[ Upstream commit 51eda36d33e43201e7a4fd35232e069b2c850b01 ]
+
+syzbot reported sco_sock_setsockopt() is copying data without
+checking user input length.
+
+BUG: KASAN: slab-out-of-bounds in copy_from_sockptr_offset
+include/linux/sockptr.h:49 [inline]
+BUG: KASAN: slab-out-of-bounds in copy_from_sockptr
+include/linux/sockptr.h:55 [inline]
+BUG: KASAN: slab-out-of-bounds in sco_sock_setsockopt+0xc0b/0xf90
+net/bluetooth/sco.c:893
+Read of size 4 at addr ffff88805f7b15a3 by task syz-executor.5/12578
+
+Fixes: ad10b1a48754 ("Bluetooth: Add Bluetooth socket voice option")
+Fixes: b96e9c671b05 ("Bluetooth: Add BT_DEFER_SETUP option to sco socket")
+Fixes: 00398e1d5183 ("Bluetooth: Add support for BT_PKT_STATUS CMSG data for SCO connections")
+Fixes: f6873401a608 ("Bluetooth: Allow setting of codec for HFP offload use case")
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+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 |  9 +++++++++
+ net/bluetooth/sco.c               | 23 ++++++++++-------------
+ 2 files changed, 19 insertions(+), 13 deletions(-)
+
+diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
+index 4191edbb0641d..2761db375836b 100644
+--- a/include/net/bluetooth/bluetooth.h
++++ b/include/net/bluetooth/bluetooth.h
+@@ -509,6 +509,15 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
+       return skb;
+ }
++static inline int bt_copy_from_sockptr(void *dst, size_t dst_size,
++                                     sockptr_t src, size_t src_size)
++{
++      if (dst_size > src_size)
++              return -EINVAL;
++
++      return copy_from_sockptr(dst, src, dst_size);
++}
++
+ int bt_to_errno(u16 code);
+ void hci_sock_set_flag(struct sock *sk, int nr);
+diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
+index cef26f1d8a583..6509c40e898e2 100644
+--- a/net/bluetooth/sco.c
++++ b/net/bluetooth/sco.c
+@@ -831,7 +831,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+                              sockptr_t optval, unsigned int optlen)
+ {
+       struct sock *sk = sock->sk;
+-      int len, err = 0;
++      int err = 0;
+       struct bt_voice voice;
+       u32 opt;
+       struct bt_codecs *codecs;
+@@ -850,10 +850,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+                       break;
+               }
+-              if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+-                      err = -EFAULT;
++              err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++              if (err)
+                       break;
+-              }
+               if (opt)
+                       set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags);
+@@ -870,11 +869,10 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+               voice.setting = sco_pi(sk)->setting;
+-              len = min_t(unsigned int, sizeof(voice), optlen);
+-              if (copy_from_sockptr(&voice, optval, len)) {
+-                      err = -EFAULT;
++              err = bt_copy_from_sockptr(&voice, sizeof(voice), optval,
++                                         optlen);
++              if (err)
+                       break;
+-              }
+               /* Explicitly check for these values */
+               if (voice.setting != BT_VOICE_TRANSPARENT &&
+@@ -887,10 +885,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+               break;
+       case BT_PKT_STATUS:
+-              if (copy_from_sockptr(&opt, optval, sizeof(u32))) {
+-                      err = -EFAULT;
++              err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
++              if (err)
+                       break;
+-              }
+               if (opt)
+                       sco_pi(sk)->cmsg_mask |= SCO_CMSG_PKT_STATUS;
+@@ -931,9 +928,9 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
+                       break;
+               }
+-              if (copy_from_sockptr(buffer, optval, optlen)) {
++              err = bt_copy_from_sockptr(buffer, optlen, optval, optlen);
++              if (err) {
+                       hci_dev_put(hdev);
+-                      err = -EFAULT;
+                       break;
+               }
+-- 
+2.43.0
+
diff --git a/queue-5.10/bluetooth-support-the-quality-report-events.patch b/queue-5.10/bluetooth-support-the-quality-report-events.patch
new file mode 100644 (file)
index 0000000..e61e579
--- /dev/null
@@ -0,0 +1,218 @@
+From e3e2c7a31fbb58c63dfa1ac477ee297e979f7eab Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 15 Aug 2021 20:17:16 +0800
+Subject: Bluetooth: Support the quality report events
+
+From: Joseph Hwang <josephsih@chromium.org>
+
+[ Upstream commit ae7d925b5c0432c058fd175a70f1de6eee7a3f89 ]
+
+This patch allows a user space process to enable/disable the quality
+report events dynamically through the set experimental feature mgmt
+interface.
+
+Since the quality report feature needs to invoke the callback function
+provided by the driver, i.e., hdev->set_quality_report, a valid
+controller index is required.
+
+Reviewed-by: Miao-chen Chou <mcchou@chromium.org>
+Signed-off-by: Joseph Hwang <josephsih@chromium.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/bluetooth/hci.h      |   1 +
+ include/net/bluetooth/hci_core.h |   2 +
+ net/bluetooth/mgmt.c             | 109 ++++++++++++++++++++++++++++++-
+ 3 files changed, 111 insertions(+), 1 deletion(-)
+
+diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
+index ede7a153c69a5..0e36974da384c 100644
+--- a/include/net/bluetooth/hci.h
++++ b/include/net/bluetooth/hci.h
+@@ -329,6 +329,7 @@ enum {
+       HCI_ENABLE_LL_PRIVACY,
+       HCI_CMD_PENDING,
+       HCI_FORCE_NO_MITM,
++      HCI_QUALITY_REPORT,
+       __HCI_NUM_FLAGS,
+ };
+diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
+index daafca376cb7c..c8f11dde54837 100644
+--- a/include/net/bluetooth/hci_core.h
++++ b/include/net/bluetooth/hci_core.h
+@@ -586,6 +586,7 @@ struct hci_dev {
+       int (*set_bdaddr)(struct hci_dev *hdev, const bdaddr_t *bdaddr);
+       void (*cmd_timeout)(struct hci_dev *hdev);
+       bool (*prevent_wake)(struct hci_dev *hdev);
++      int (*set_quality_report)(struct hci_dev *hdev, bool enable);
+ };
+ #define HCI_PHY_HANDLE(handle)        (handle & 0xff)
+@@ -739,6 +740,7 @@ extern struct mutex hci_cb_list_lock;
+               hci_dev_clear_flag(hdev, HCI_LE_ADV);           \
+               hci_dev_clear_flag(hdev, HCI_LL_RPA_RESOLUTION);\
+               hci_dev_clear_flag(hdev, HCI_PERIODIC_INQ);     \
++              hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT);   \
+       } while (0)
+ /* ----- HCI interface to upper protocols ----- */
+diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
+index 8acfd9db00d63..b19ad142b8ba5 100644
+--- a/net/bluetooth/mgmt.c
++++ b/net/bluetooth/mgmt.c
+@@ -3769,6 +3769,12 @@ static const u8 debug_uuid[16] = {
+ };
+ #endif
++/* 330859bc-7506-492d-9370-9a6f0614037f */
++static const u8 quality_report_uuid[16] = {
++      0x7f, 0x03, 0x14, 0x06, 0x6f, 0x9a, 0x70, 0x93,
++      0x2d, 0x49, 0x06, 0x75, 0xbc, 0x59, 0x08, 0x33,
++};
++
+ /* 671b10b5-42c0-4696-9227-eb28d1b049d6 */
+ static const u8 simult_central_periph_uuid[16] = {
+       0xd6, 0x49, 0xb0, 0xd1, 0x28, 0xeb, 0x27, 0x92,
+@@ -3784,7 +3790,7 @@ static const u8 rpa_resolution_uuid[16] = {
+ static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
+                                 void *data, u16 data_len)
+ {
+-      char buf[62];   /* Enough space for 3 features */
++      char buf[82];   /* Enough space for 4 features: 2 + 20 * 4 */
+       struct mgmt_rp_read_exp_features_info *rp = (void *)buf;
+       u16 idx = 0;
+       u32 flags;
+@@ -3828,6 +3834,24 @@ static int read_exp_features_info(struct sock *sk, struct hci_dev *hdev,
+               idx++;
+       }
++      if (hdev) {
++              if (hdev->set_quality_report) {
++                      /* BIT(0): indicating if set_quality_report is
++                       * supported by controller.
++                       */
++                      flags = BIT(0);
++
++                      /* BIT(1): indicating if the feature is enabled. */
++                      if (hci_dev_test_flag(hdev, HCI_QUALITY_REPORT))
++                              flags |= BIT(1);
++              } else {
++                      flags = 0;
++              }
++              memcpy(rp->features[idx].uuid, quality_report_uuid, 16);
++              rp->features[idx].flags = cpu_to_le32(flags);
++              idx++;
++      }
++
+       rp->feature_count = cpu_to_le16(idx);
+       /* After reading the experimental features information, enable
+@@ -3870,6 +3894,19 @@ static int exp_debug_feature_changed(bool enabled, struct sock *skip)
+ }
+ #endif
++static int exp_quality_report_feature_changed(bool enabled, struct sock *skip)
++{
++      struct mgmt_ev_exp_feature_changed ev;
++
++      memset(&ev, 0, sizeof(ev));
++      memcpy(ev.uuid, quality_report_uuid, 16);
++      ev.flags = cpu_to_le32(enabled ? BIT(0) : 0);
++
++      return mgmt_limited_event(MGMT_EV_EXP_FEATURE_CHANGED, NULL,
++                                &ev, sizeof(ev),
++                                HCI_MGMT_EXP_FEATURE_EVENTS, skip);
++}
++
+ #define EXP_FEAT(_uuid, _set_func)    \
+ {                                     \
+       .uuid = _uuid,                  \
+@@ -4024,6 +4061,75 @@ static int set_rpa_resolution_func(struct sock *sk, struct hci_dev *hdev,
+       return err;
+ }
++static int set_quality_report_func(struct sock *sk, struct hci_dev *hdev,
++                                 struct mgmt_cp_set_exp_feature *cp,
++                                 u16 data_len)
++{
++      struct mgmt_rp_set_exp_feature rp;
++      bool val, changed;
++      int err;
++
++      /* Command requires to use a valid controller index */
++      if (!hdev)
++              return mgmt_cmd_status(sk, MGMT_INDEX_NONE,
++                                     MGMT_OP_SET_EXP_FEATURE,
++                                     MGMT_STATUS_INVALID_INDEX);
++
++      /* Parameters are limited to a single octet */
++      if (data_len != MGMT_SET_EXP_FEATURE_SIZE + 1)
++              return mgmt_cmd_status(sk, hdev->id,
++                                     MGMT_OP_SET_EXP_FEATURE,
++                                     MGMT_STATUS_INVALID_PARAMS);
++
++      /* Only boolean on/off is supported */
++      if (cp->param[0] != 0x00 && cp->param[0] != 0x01)
++              return mgmt_cmd_status(sk, hdev->id,
++                                     MGMT_OP_SET_EXP_FEATURE,
++                                     MGMT_STATUS_INVALID_PARAMS);
++
++      hci_req_sync_lock(hdev);
++
++      val = !!cp->param[0];
++      changed = (val != hci_dev_test_flag(hdev, HCI_QUALITY_REPORT));
++
++      if (!hdev->set_quality_report) {
++              err = mgmt_cmd_status(sk, hdev->id,
++                                    MGMT_OP_SET_EXP_FEATURE,
++                                    MGMT_STATUS_NOT_SUPPORTED);
++              goto unlock_quality_report;
++      }
++
++      if (changed) {
++              err = hdev->set_quality_report(hdev, val);
++              if (err) {
++                      err = mgmt_cmd_status(sk, hdev->id,
++                                            MGMT_OP_SET_EXP_FEATURE,
++                                            MGMT_STATUS_FAILED);
++                      goto unlock_quality_report;
++              }
++              if (val)
++                      hci_dev_set_flag(hdev, HCI_QUALITY_REPORT);
++              else
++                      hci_dev_clear_flag(hdev, HCI_QUALITY_REPORT);
++      }
++
++      bt_dev_dbg(hdev, "quality report enable %d changed %d", val, changed);
++
++      memcpy(rp.uuid, quality_report_uuid, 16);
++      rp.flags = cpu_to_le32(val ? BIT(0) : 0);
++      hci_sock_set_flag(sk, HCI_MGMT_EXP_FEATURE_EVENTS);
++      err = mgmt_cmd_complete(sk, hdev->id,
++                              MGMT_OP_SET_EXP_FEATURE, 0,
++                              &rp, sizeof(rp));
++
++      if (changed)
++              exp_quality_report_feature_changed(val, sk);
++
++unlock_quality_report:
++      hci_req_sync_unlock(hdev);
++      return err;
++}
++
+ static const struct mgmt_exp_feature {
+       const u8 *uuid;
+       int (*set_func)(struct sock *sk, struct hci_dev *hdev,
+@@ -4034,6 +4140,7 @@ static const struct mgmt_exp_feature {
+       EXP_FEAT(debug_uuid, set_debug_func),
+ #endif
+       EXP_FEAT(rpa_resolution_uuid, set_rpa_resolution_func),
++      EXP_FEAT(quality_report_uuid, set_quality_report_func),
+       /* end with a null feature */
+       EXP_FEAT(NULL, NULL)
+-- 
+2.43.0
+
diff --git a/queue-5.10/geneve-fix-header-validation-in-geneve-6-_xmit_skb.patch b/queue-5.10/geneve-fix-header-validation-in-geneve-6-_xmit_skb.patch
new file mode 100644 (file)
index 0000000..a60a9c5
--- /dev/null
@@ -0,0 +1,166 @@
+From 2277a5c4398835a1c6df53d596275476438e722e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 Apr 2024 10:30:34 +0000
+Subject: geneve: fix header validation in geneve[6]_xmit_skb
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit d8a6213d70accb403b82924a1c229e733433a5ef ]
+
+syzbot is able to trigger an uninit-value in geneve_xmit() [1]
+
+Problem : While most ip tunnel helpers (like ip_tunnel_get_dsfield())
+uses skb_protocol(skb, true), pskb_inet_may_pull() is only using
+skb->protocol.
+
+If anything else than ETH_P_IPV6 or ETH_P_IP is found in skb->protocol,
+pskb_inet_may_pull() does nothing at all.
+
+If a vlan tag was provided by the caller (af_packet in the syzbot case),
+the network header might not point to the correct location, and skb
+linear part could be smaller than expected.
+
+Add skb_vlan_inet_prepare() to perform a complete mac validation.
+
+Use this in geneve for the moment, I suspect we need to adopt this
+more broadly.
+
+v4 - Jakub reported v3 broke l2_tos_ttl_inherit.sh selftest
+   - Only call __vlan_get_protocol() for vlan types.
+Link: https://lore.kernel.org/netdev/20240404100035.3270a7d5@kernel.org/
+
+v2,v3 - Addressed Sabrina comments on v1 and v2
+Link: https://lore.kernel.org/netdev/Zg1l9L2BNoZWZDZG@hog/
+
+[1]
+
+BUG: KMSAN: uninit-value in geneve_xmit_skb drivers/net/geneve.c:910 [inline]
+ BUG: KMSAN: uninit-value in geneve_xmit+0x302d/0x5420 drivers/net/geneve.c:1030
+  geneve_xmit_skb drivers/net/geneve.c:910 [inline]
+  geneve_xmit+0x302d/0x5420 drivers/net/geneve.c:1030
+  __netdev_start_xmit include/linux/netdevice.h:4903 [inline]
+  netdev_start_xmit include/linux/netdevice.h:4917 [inline]
+  xmit_one net/core/dev.c:3531 [inline]
+  dev_hard_start_xmit+0x247/0xa20 net/core/dev.c:3547
+  __dev_queue_xmit+0x348d/0x52c0 net/core/dev.c:4335
+  dev_queue_xmit include/linux/netdevice.h:3091 [inline]
+  packet_xmit+0x9c/0x6c0 net/packet/af_packet.c:276
+  packet_snd net/packet/af_packet.c:3081 [inline]
+  packet_sendmsg+0x8bb0/0x9ef0 net/packet/af_packet.c:3113
+  sock_sendmsg_nosec net/socket.c:730 [inline]
+  __sock_sendmsg+0x30f/0x380 net/socket.c:745
+  __sys_sendto+0x685/0x830 net/socket.c:2191
+  __do_sys_sendto net/socket.c:2203 [inline]
+  __se_sys_sendto net/socket.c:2199 [inline]
+  __x64_sys_sendto+0x125/0x1d0 net/socket.c:2199
+ do_syscall_64+0xd5/0x1f0
+ entry_SYSCALL_64_after_hwframe+0x6d/0x75
+
+Uninit was created at:
+  slab_post_alloc_hook mm/slub.c:3804 [inline]
+  slab_alloc_node mm/slub.c:3845 [inline]
+  kmem_cache_alloc_node+0x613/0xc50 mm/slub.c:3888
+  kmalloc_reserve+0x13d/0x4a0 net/core/skbuff.c:577
+  __alloc_skb+0x35b/0x7a0 net/core/skbuff.c:668
+  alloc_skb include/linux/skbuff.h:1318 [inline]
+  alloc_skb_with_frags+0xc8/0xbf0 net/core/skbuff.c:6504
+  sock_alloc_send_pskb+0xa81/0xbf0 net/core/sock.c:2795
+  packet_alloc_skb net/packet/af_packet.c:2930 [inline]
+  packet_snd net/packet/af_packet.c:3024 [inline]
+  packet_sendmsg+0x722d/0x9ef0 net/packet/af_packet.c:3113
+  sock_sendmsg_nosec net/socket.c:730 [inline]
+  __sock_sendmsg+0x30f/0x380 net/socket.c:745
+  __sys_sendto+0x685/0x830 net/socket.c:2191
+  __do_sys_sendto net/socket.c:2203 [inline]
+  __se_sys_sendto net/socket.c:2199 [inline]
+  __x64_sys_sendto+0x125/0x1d0 net/socket.c:2199
+ do_syscall_64+0xd5/0x1f0
+ entry_SYSCALL_64_after_hwframe+0x6d/0x75
+
+CPU: 0 PID: 5033 Comm: syz-executor346 Not tainted 6.9.0-rc1-syzkaller-00005-g928a87efa423 #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 02/29/2024
+
+Fixes: d13f048dd40e ("net: geneve: modify IP header check in geneve6_xmit_skb and geneve_xmit_skb")
+Reported-by: syzbot+9ee20ec1de7b3168db09@syzkaller.appspotmail.com
+Closes: https://lore.kernel.org/netdev/000000000000d19c3a06152f9ee4@google.com/
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Phillip Potter <phil@philpotter.co.uk>
+Cc: Sabrina Dubroca <sd@queasysnail.net>
+Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
+Reviewed-by: Phillip Potter <phil@philpotter.co.uk>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/geneve.c     |  4 ++--
+ include/net/ip_tunnels.h | 33 +++++++++++++++++++++++++++++++++
+ 2 files changed, 35 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
+index 2bb9820c66641..af35361a3dcee 100644
+--- a/drivers/net/geneve.c
++++ b/drivers/net/geneve.c
+@@ -907,7 +907,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
+       __be16 sport;
+       int err;
+-      if (!pskb_inet_may_pull(skb))
++      if (!skb_vlan_inet_prepare(skb))
+               return -EINVAL;
+       sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
+@@ -1004,7 +1004,7 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
+       __be16 sport;
+       int err;
+-      if (!pskb_inet_may_pull(skb))
++      if (!skb_vlan_inet_prepare(skb))
+               return -EINVAL;
+       sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
+diff --git a/include/net/ip_tunnels.h b/include/net/ip_tunnels.h
+index 58d8e6260aa13..1f016af0622bd 100644
+--- a/include/net/ip_tunnels.h
++++ b/include/net/ip_tunnels.h
+@@ -333,6 +333,39 @@ static inline bool pskb_inet_may_pull(struct sk_buff *skb)
+       return pskb_network_may_pull(skb, nhlen);
+ }
++/* Variant of pskb_inet_may_pull().
++ */
++static inline bool skb_vlan_inet_prepare(struct sk_buff *skb)
++{
++      int nhlen = 0, maclen = ETH_HLEN;
++      __be16 type = skb->protocol;
++
++      /* Essentially this is skb_protocol(skb, true)
++       * And we get MAC len.
++       */
++      if (eth_type_vlan(type))
++              type = __vlan_get_protocol(skb, type, &maclen);
++
++      switch (type) {
++#if IS_ENABLED(CONFIG_IPV6)
++      case htons(ETH_P_IPV6):
++              nhlen = sizeof(struct ipv6hdr);
++              break;
++#endif
++      case htons(ETH_P_IP):
++              nhlen = sizeof(struct iphdr);
++              break;
++      }
++      /* For ETH_P_IPV6/ETH_P_IP we make sure to pull
++       * a base network header in skb->head.
++       */
++      if (!pskb_may_pull(skb, maclen + nhlen))
++              return false;
++
++      skb_set_network_header(skb, maclen);
++      return true;
++}
++
+ static inline int ip_encap_hlen(struct ip_tunnel_encap *e)
+ {
+       const struct ip_tunnel_encap_ops *ops;
+-- 
+2.43.0
+
diff --git a/queue-5.10/iommu-vt-d-allocate-local-memory-for-page-request-qu.patch b/queue-5.10/iommu-vt-d-allocate-local-memory-for-page-request-qu.patch
new file mode 100644 (file)
index 0000000..56123cc
--- /dev/null
@@ -0,0 +1,39 @@
+From a6e0a0dbd53b649a706589f5674eb10942d4f026 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 11 Apr 2024 11:07:43 +0800
+Subject: iommu/vt-d: Allocate local memory for page request queue
+
+From: Jacob Pan <jacob.jun.pan@linux.intel.com>
+
+[ Upstream commit a34f3e20ddff02c4f12df2c0635367394e64c63d ]
+
+The page request queue is per IOMMU, its allocation should be made
+NUMA-aware for performance reasons.
+
+Fixes: a222a7f0bb6c ("iommu/vt-d: Implement page request handling")
+Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
+Reviewed-by: Kevin Tian <kevin.tian@intel.com>
+Link: https://lore.kernel.org/r/20240403214007.985600-1-jacob.jun.pan@linux.intel.com
+Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Joerg Roedel <jroedel@suse.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/svm.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
+index aabf56272b86d..02e3183a4c67e 100644
+--- a/drivers/iommu/intel/svm.c
++++ b/drivers/iommu/intel/svm.c
+@@ -33,7 +33,7 @@ int intel_svm_enable_prq(struct intel_iommu *iommu)
+       struct page *pages;
+       int irq, ret;
+-      pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, PRQ_ORDER);
++      pages = alloc_pages_node(iommu->node, GFP_KERNEL | __GFP_ZERO, PRQ_ORDER);
+       if (!pages) {
+               pr_warn("IOMMU: %s: Failed to allocate page request queue\n",
+                       iommu->name);
+-- 
+2.43.0
+
diff --git a/queue-5.10/ipv4-route-avoid-unused-but-set-variable-warning.patch b/queue-5.10/ipv4-route-avoid-unused-but-set-variable-warning.patch
new file mode 100644 (file)
index 0000000..e8da41b
--- /dev/null
@@ -0,0 +1,51 @@
+From e7fb60a18ff9b60ae60063381a08a76263c46958 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Apr 2024 09:42:03 +0200
+Subject: ipv4/route: avoid unused-but-set-variable warning
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit cf1b7201df59fb936f40f4a807433fe3f2ce310a ]
+
+The log_martians variable is only used in an #ifdef, causing a 'make W=1'
+warning with gcc:
+
+net/ipv4/route.c: In function 'ip_rt_send_redirect':
+net/ipv4/route.c:880:13: error: variable 'log_martians' set but not used [-Werror=unused-but-set-variable]
+
+Change the #ifdef to an equivalent IS_ENABLED() to let the compiler
+see where the variable is used.
+
+Fixes: 30038fc61adf ("net: ip_rt_send_redirect() optimization")
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://lore.kernel.org/r/20240408074219.3030256-2-arnd@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/route.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/net/ipv4/route.c b/net/ipv4/route.c
+index d360c7d70e8a2..b7cba4bdc5786 100644
+--- a/net/ipv4/route.c
++++ b/net/ipv4/route.c
+@@ -955,13 +955,11 @@ void ip_rt_send_redirect(struct sk_buff *skb)
+               icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, gw);
+               peer->rate_last = jiffies;
+               ++peer->n_redirects;
+-#ifdef CONFIG_IP_ROUTE_VERBOSE
+-              if (log_martians &&
++              if (IS_ENABLED(CONFIG_IP_ROUTE_VERBOSE) && log_martians &&
+                   peer->n_redirects == ip_rt_redirect_number)
+                       net_warn_ratelimited("host %pI4/if%d ignores redirects for %pI4 to %pI4\n",
+                                            &ip_hdr(skb)->saddr, inet_iif(skb),
+                                            &ip_hdr(skb)->daddr, &gw);
+-#endif
+       }
+ out_put_peer:
+       inet_putpeer(peer);
+-- 
+2.43.0
+
diff --git a/queue-5.10/ipv6-fib-hide-unused-pn-variable.patch b/queue-5.10/ipv6-fib-hide-unused-pn-variable.patch
new file mode 100644 (file)
index 0000000..fc943c5
--- /dev/null
@@ -0,0 +1,60 @@
+From 351dafcc6015d7c3c7f31988b6c33d97cf46c1d0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Apr 2024 09:42:02 +0200
+Subject: ipv6: fib: hide unused 'pn' variable
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit 74043489fcb5e5ca4074133582b5b8011b67f9e7 ]
+
+When CONFIG_IPV6_SUBTREES is disabled, the only user is hidden, causing
+a 'make W=1' warning:
+
+net/ipv6/ip6_fib.c: In function 'fib6_add':
+net/ipv6/ip6_fib.c:1388:32: error: variable 'pn' set but not used [-Werror=unused-but-set-variable]
+
+Add another #ifdef around the variable declaration, matching the other
+uses in this file.
+
+Fixes: 66729e18df08 ("[IPV6] ROUTE: Make sure we have fn->leaf when adding a node on subtree.")
+Link: https://lore.kernel.org/netdev/20240322131746.904943-1-arnd@kernel.org/
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://lore.kernel.org/r/20240408074219.3030256-1-arnd@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv6/ip6_fib.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
+index d70783283a417..b79e571e5a863 100644
+--- a/net/ipv6/ip6_fib.c
++++ b/net/ipv6/ip6_fib.c
+@@ -1373,7 +1373,10 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
+            struct nl_info *info, struct netlink_ext_ack *extack)
+ {
+       struct fib6_table *table = rt->fib6_table;
+-      struct fib6_node *fn, *pn = NULL;
++      struct fib6_node *fn;
++#ifdef CONFIG_IPV6_SUBTREES
++      struct fib6_node *pn = NULL;
++#endif
+       int err = -ENOMEM;
+       int allow_create = 1;
+       int replace_required = 0;
+@@ -1397,9 +1400,9 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt,
+               goto out;
+       }
++#ifdef CONFIG_IPV6_SUBTREES
+       pn = fn;
+-#ifdef CONFIG_IPV6_SUBTREES
+       if (rt->fib6_src.plen) {
+               struct fib6_node *sn;
+-- 
+2.43.0
+
diff --git a/queue-5.10/ipv6-fix-race-condition-between-ipv6_get_ifaddr-and-.patch b/queue-5.10/ipv6-fix-race-condition-between-ipv6_get_ifaddr-and-.patch
new file mode 100644 (file)
index 0000000..67cf3d5
--- /dev/null
@@ -0,0 +1,133 @@
+From fd1c84d9164e1c72e2e4862c91578d518956b4a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Apr 2024 16:18:21 +0200
+Subject: ipv6: fix race condition between ipv6_get_ifaddr and ipv6_del_addr
+
+From: Jiri Benc <jbenc@redhat.com>
+
+[ Upstream commit 7633c4da919ad51164acbf1aa322cc1a3ead6129 ]
+
+Although ipv6_get_ifaddr walks inet6_addr_lst under the RCU lock, it
+still means hlist_for_each_entry_rcu can return an item that got removed
+from the list. The memory itself of such item is not freed thanks to RCU
+but nothing guarantees the actual content of the memory is sane.
+
+In particular, the reference count can be zero. This can happen if
+ipv6_del_addr is called in parallel. ipv6_del_addr removes the entry
+from inet6_addr_lst (hlist_del_init_rcu(&ifp->addr_lst)) and drops all
+references (__in6_ifa_put(ifp) + in6_ifa_put(ifp)). With bad enough
+timing, this can happen:
+
+1. In ipv6_get_ifaddr, hlist_for_each_entry_rcu returns an entry.
+
+2. Then, the whole ipv6_del_addr is executed for the given entry. The
+   reference count drops to zero and kfree_rcu is scheduled.
+
+3. ipv6_get_ifaddr continues and tries to increments the reference count
+   (in6_ifa_hold).
+
+4. The rcu is unlocked and the entry is freed.
+
+5. The freed entry is returned.
+
+Prevent increasing of the reference count in such case. The name
+in6_ifa_hold_safe is chosen to mimic the existing fib6_info_hold_safe.
+
+[   41.506330] refcount_t: addition on 0; use-after-free.
+[   41.506760] WARNING: CPU: 0 PID: 595 at lib/refcount.c:25 refcount_warn_saturate+0xa5/0x130
+[   41.507413] Modules linked in: veth bridge stp llc
+[   41.507821] CPU: 0 PID: 595 Comm: python3 Not tainted 6.9.0-rc2.main-00208-g49563be82afa #14
+[   41.508479] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996)
+[   41.509163] RIP: 0010:refcount_warn_saturate+0xa5/0x130
+[   41.509586] Code: ad ff 90 0f 0b 90 90 c3 cc cc cc cc 80 3d c0 30 ad 01 00 75 a0 c6 05 b7 30 ad 01 01 90 48 c7 c7 38 cc 7a 8c e8 cc 18 ad ff 90 <0f> 0b 90 90 c3 cc cc cc cc 80 3d 98 30 ad 01 00 0f 85 75 ff ff ff
+[   41.510956] RSP: 0018:ffffbda3c026baf0 EFLAGS: 00010282
+[   41.511368] RAX: 0000000000000000 RBX: ffff9e9c46914800 RCX: 0000000000000000
+[   41.511910] RDX: ffff9e9c7ec29c00 RSI: ffff9e9c7ec1c900 RDI: ffff9e9c7ec1c900
+[   41.512445] RBP: ffff9e9c43660c9c R08: 0000000000009ffb R09: 00000000ffffdfff
+[   41.512998] R10: 00000000ffffdfff R11: ffffffff8ca58a40 R12: ffff9e9c4339a000
+[   41.513534] R13: 0000000000000001 R14: ffff9e9c438a0000 R15: ffffbda3c026bb48
+[   41.514086] FS:  00007fbc4cda1740(0000) GS:ffff9e9c7ec00000(0000) knlGS:0000000000000000
+[   41.514726] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[   41.515176] CR2: 000056233b337d88 CR3: 000000000376e006 CR4: 0000000000370ef0
+[   41.515713] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[   41.516252] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[   41.516799] Call Trace:
+[   41.517037]  <TASK>
+[   41.517249]  ? __warn+0x7b/0x120
+[   41.517535]  ? refcount_warn_saturate+0xa5/0x130
+[   41.517923]  ? report_bug+0x164/0x190
+[   41.518240]  ? handle_bug+0x3d/0x70
+[   41.518541]  ? exc_invalid_op+0x17/0x70
+[   41.520972]  ? asm_exc_invalid_op+0x1a/0x20
+[   41.521325]  ? refcount_warn_saturate+0xa5/0x130
+[   41.521708]  ipv6_get_ifaddr+0xda/0xe0
+[   41.522035]  inet6_rtm_getaddr+0x342/0x3f0
+[   41.522376]  ? __pfx_inet6_rtm_getaddr+0x10/0x10
+[   41.522758]  rtnetlink_rcv_msg+0x334/0x3d0
+[   41.523102]  ? netlink_unicast+0x30f/0x390
+[   41.523445]  ? __pfx_rtnetlink_rcv_msg+0x10/0x10
+[   41.523832]  netlink_rcv_skb+0x53/0x100
+[   41.524157]  netlink_unicast+0x23b/0x390
+[   41.524484]  netlink_sendmsg+0x1f2/0x440
+[   41.524826]  __sys_sendto+0x1d8/0x1f0
+[   41.525145]  __x64_sys_sendto+0x1f/0x30
+[   41.525467]  do_syscall_64+0xa5/0x1b0
+[   41.525794]  entry_SYSCALL_64_after_hwframe+0x72/0x7a
+[   41.526213] RIP: 0033:0x7fbc4cfcea9a
+[   41.526528] Code: d8 64 89 02 48 c7 c0 ff ff ff ff eb b8 0f 1f 00 f3 0f 1e fa 41 89 ca 64 8b 04 25 18 00 00 00 85 c0 75 15 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 7e c3 0f 1f 44 00 00 41 54 48 83 ec 30 44 89
+[   41.527942] RSP: 002b:00007ffcf54012a8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
+[   41.528593] RAX: ffffffffffffffda RBX: 00007ffcf5401368 RCX: 00007fbc4cfcea9a
+[   41.529173] RDX: 000000000000002c RSI: 00007fbc4b9d9bd0 RDI: 0000000000000005
+[   41.529786] RBP: 00007fbc4bafb040 R08: 00007ffcf54013e0 R09: 000000000000000c
+[   41.530375] R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000
+[   41.530977] R13: ffffffffc4653600 R14: 0000000000000001 R15: 00007fbc4ca85d1b
+[   41.531573]  </TASK>
+
+Fixes: 5c578aedcb21d ("IPv6: convert addrconf hash list to RCU")
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Signed-off-by: Jiri Benc <jbenc@redhat.com>
+Link: https://lore.kernel.org/r/8ab821e36073a4a406c50ec83c9e8dc586c539e4.1712585809.git.jbenc@redhat.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/net/addrconf.h | 4 ++++
+ net/ipv6/addrconf.c    | 7 ++++---
+ 2 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/include/net/addrconf.h b/include/net/addrconf.h
+index 4d0c4cf1d4c88..f666d3628d6aa 100644
+--- a/include/net/addrconf.h
++++ b/include/net/addrconf.h
+@@ -437,6 +437,10 @@ static inline void in6_ifa_hold(struct inet6_ifaddr *ifp)
+       refcount_inc(&ifp->refcnt);
+ }
++static inline bool in6_ifa_hold_safe(struct inet6_ifaddr *ifp)
++{
++      return refcount_inc_not_zero(&ifp->refcnt);
++}
+ /*
+  *    compute link-local solicited-node multicast address
+diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
+index 0429c1d50fc92..8a6f4cdd5a486 100644
+--- a/net/ipv6/addrconf.c
++++ b/net/ipv6/addrconf.c
+@@ -2044,9 +2044,10 @@ struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net, const struct in6_addr *add
+               if (ipv6_addr_equal(&ifp->addr, addr)) {
+                       if (!dev || ifp->idev->dev == dev ||
+                           !(ifp->scope&(IFA_LINK|IFA_HOST) || strict)) {
+-                              result = ifp;
+-                              in6_ifa_hold(ifp);
+-                              break;
++                              if (in6_ifa_hold_safe(ifp)) {
++                                      result = ifp;
++                                      break;
++                              }
+                       }
+               }
+       }
+-- 
+2.43.0
+
diff --git a/queue-5.10/net-ena-fix-incorrect-descriptor-free-behavior.patch b/queue-5.10/net-ena-fix-incorrect-descriptor-free-behavior.patch
new file mode 100644 (file)
index 0000000..f7333cc
--- /dev/null
@@ -0,0 +1,72 @@
+From 6f047f38a013d31fdea54e0eb8c2168885e53296 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Apr 2024 09:13:57 +0000
+Subject: net: ena: Fix incorrect descriptor free behavior
+
+From: David Arinzon <darinzon@amazon.com>
+
+[ Upstream commit bf02d9fe00632d22fa91d34749c7aacf397b6cde ]
+
+ENA has two types of TX queues:
+- queues which only process TX packets arriving from the network stack
+- queues which only process TX packets forwarded to it by XDP_REDIRECT
+  or XDP_TX instructions
+
+The ena_free_tx_bufs() cycles through all descriptors in a TX queue
+and unmaps + frees every descriptor that hasn't been acknowledged yet
+by the device (uncompleted TX transactions).
+The function assumes that the processed TX queue is necessarily from
+the first category listed above and ends up using napi_consume_skb()
+for descriptors belonging to an XDP specific queue.
+
+This patch solves a bug in which, in case of a VF reset, the
+descriptors aren't freed correctly, leading to crashes.
+
+Fixes: 548c4940b9f1 ("net: ena: Implement XDP_TX action")
+Signed-off-by: Shay Agroskin <shayagr@amazon.com>
+Signed-off-by: David Arinzon <darinzon@amazon.com>
+Reviewed-by: Shannon Nelson <shannon.nelson@amd.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amazon/ena/ena_netdev.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
+index f403a5acda5b0..9149c82c0a564 100644
+--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
++++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
+@@ -1105,8 +1105,11 @@ static void ena_unmap_tx_buff(struct ena_ring *tx_ring,
+ static void ena_free_tx_bufs(struct ena_ring *tx_ring)
+ {
+       bool print_once = true;
++      bool is_xdp_ring;
+       u32 i;
++      is_xdp_ring = ENA_IS_XDP_INDEX(tx_ring->adapter, tx_ring->qid);
++
+       for (i = 0; i < tx_ring->ring_size; i++) {
+               struct ena_tx_buffer *tx_info = &tx_ring->tx_buffer_info[i];
+@@ -1126,10 +1129,15 @@ static void ena_free_tx_bufs(struct ena_ring *tx_ring)
+               ena_unmap_tx_buff(tx_ring, tx_info);
+-              dev_kfree_skb_any(tx_info->skb);
++              if (is_xdp_ring)
++                      xdp_return_frame(tx_info->xdpf);
++              else
++                      dev_kfree_skb_any(tx_info->skb);
+       }
+-      netdev_tx_reset_queue(netdev_get_tx_queue(tx_ring->netdev,
+-                                                tx_ring->qid));
++
++      if (!is_xdp_ring)
++              netdev_tx_reset_queue(netdev_get_tx_queue(tx_ring->netdev,
++                                                        tx_ring->qid));
+ }
+ static void ena_free_all_tx_bufs(struct ena_adapter *adapter)
+-- 
+2.43.0
+
diff --git a/queue-5.10/net-ena-fix-potential-sign-extension-issue.patch b/queue-5.10/net-ena-fix-potential-sign-extension-issue.patch
new file mode 100644 (file)
index 0000000..0e120ab
--- /dev/null
@@ -0,0 +1,66 @@
+From 9ef7dfaead7c3b1a9d18e36529a497cdebb60d75 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Apr 2024 09:13:55 +0000
+Subject: net: ena: Fix potential sign extension issue
+
+From: David Arinzon <darinzon@amazon.com>
+
+[ Upstream commit 713a85195aad25d8a26786a37b674e3e5ec09e3c ]
+
+Small unsigned types are promoted to larger signed types in
+the case of multiplication, the result of which may overflow.
+In case the result of such a multiplication has its MSB
+turned on, it will be sign extended with '1's.
+This changes the multiplication result.
+
+Code example of the phenomenon:
+-------------------------------
+u16 x, y;
+size_t z1, z2;
+
+x = y = 0xffff;
+printk("x=%x y=%x\n",x,y);
+
+z1 = x*y;
+z2 = (size_t)x*y;
+
+printk("z1=%lx z2=%lx\n", z1, z2);
+
+Output:
+-------
+x=ffff y=ffff
+z1=fffffffffffe0001 z2=fffe0001
+
+The expected result of ffff*ffff is fffe0001, and without the
+explicit casting to avoid the unwanted sign extension we got
+fffffffffffe0001.
+
+This commit adds an explicit casting to avoid the sign extension
+issue.
+
+Fixes: 689b2bdaaa14 ("net: ena: add functions for handling Low Latency Queues in ena_com")
+Signed-off-by: Arthur Kiyanovski <akiyano@amazon.com>
+Signed-off-by: David Arinzon <darinzon@amazon.com>
+Reviewed-by: Shannon Nelson <shannon.nelson@amd.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amazon/ena/ena_com.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/amazon/ena/ena_com.c b/drivers/net/ethernet/amazon/ena/ena_com.c
+index d59ea5148c16c..60645ea7c0f80 100644
+--- a/drivers/net/ethernet/amazon/ena/ena_com.c
++++ b/drivers/net/ethernet/amazon/ena/ena_com.c
+@@ -352,7 +352,7 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev,
+                       ENA_COM_BOUNCE_BUFFER_CNTRL_CNT;
+               io_sq->bounce_buf_ctrl.next_to_use = 0;
+-              size = io_sq->bounce_buf_ctrl.buffer_size *
++              size = (size_t)io_sq->bounce_buf_ctrl.buffer_size *
+                       io_sq->bounce_buf_ctrl.buffers_num;
+               dev_node = dev_to_node(ena_dev->dmadev);
+-- 
+2.43.0
+
diff --git a/queue-5.10/net-ena-wrong-missing-io-completions-check-order.patch b/queue-5.10/net-ena-wrong-missing-io-completions-check-order.patch
new file mode 100644 (file)
index 0000000..fcdac9e
--- /dev/null
@@ -0,0 +1,108 @@
+From 3c20a3e37153bca1580e092b0d1d2051e1236cf9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 10 Apr 2024 09:13:56 +0000
+Subject: net: ena: Wrong missing IO completions check order
+
+From: David Arinzon <darinzon@amazon.com>
+
+[ Upstream commit f7e417180665234fdb7af2ebe33d89aaa434d16f ]
+
+Missing IO completions check is called every second (HZ jiffies).
+This commit fixes several issues with this check:
+
+1. Duplicate queues check:
+   Max of 4 queues are scanned on each check due to monitor budget.
+   Once reaching the budget, this check exits under the assumption that
+   the next check will continue to scan the remainder of the queues,
+   but in practice, next check will first scan the last already scanned
+   queue which is not necessary and may cause the full queue scan to
+   last a couple of seconds longer.
+   The fix is to start every check with the next queue to scan.
+   For example, on 8 IO queues:
+   Bug: [0,1,2,3], [3,4,5,6], [6,7]
+   Fix: [0,1,2,3], [4,5,6,7]
+
+2. Unbalanced queues check:
+   In case the number of active IO queues is not a multiple of budget,
+   there will be checks which don't utilize the full budget
+   because the full scan exits when reaching the last queue id.
+   The fix is to run every TX completion check with exact queue budget
+   regardless of the queue id.
+   For example, on 7 IO queues:
+   Bug: [0,1,2,3], [4,5,6], [0,1,2,3]
+   Fix: [0,1,2,3], [4,5,6,0], [1,2,3,4]
+   The budget may be lowered in case the number of IO queues is less
+   than the budget (4) to make sure there are no duplicate queues on
+   the same check.
+   For example, on 3 IO queues:
+   Bug: [0,1,2,0], [1,2,0,1]
+   Fix: [0,1,2], [0,1,2]
+
+Fixes: 1738cd3ed342 ("net: ena: Add a driver for Amazon Elastic Network Adapters (ENA)")
+Signed-off-by: Amit Bernstein <amitbern@amazon.com>
+Signed-off-by: David Arinzon <darinzon@amazon.com>
+Reviewed-by: Shannon Nelson <shannon.nelson@amd.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/amazon/ena/ena_netdev.c | 21 +++++++++++---------
+ 1 file changed, 12 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
+index fa65971949fce..f403a5acda5b0 100644
+--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
++++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
+@@ -3672,10 +3672,11 @@ static void check_for_missing_completions(struct ena_adapter *adapter)
+ {
+       struct ena_ring *tx_ring;
+       struct ena_ring *rx_ring;
+-      int i, budget, rc;
++      int qid, budget, rc;
+       int io_queue_count;
+       io_queue_count = adapter->xdp_num_queues + adapter->num_io_queues;
++
+       /* Make sure the driver doesn't turn the device in other process */
+       smp_rmb();
+@@ -3688,27 +3689,29 @@ static void check_for_missing_completions(struct ena_adapter *adapter)
+       if (adapter->missing_tx_completion_to == ENA_HW_HINTS_NO_TIMEOUT)
+               return;
+-      budget = ENA_MONITORED_TX_QUEUES;
++      budget = min_t(u32, io_queue_count, ENA_MONITORED_TX_QUEUES);
+-      for (i = adapter->last_monitored_tx_qid; i < io_queue_count; i++) {
+-              tx_ring = &adapter->tx_ring[i];
+-              rx_ring = &adapter->rx_ring[i];
++      qid = adapter->last_monitored_tx_qid;
++
++      while (budget) {
++              qid = (qid + 1) % io_queue_count;
++
++              tx_ring = &adapter->tx_ring[qid];
++              rx_ring = &adapter->rx_ring[qid];
+               rc = check_missing_comp_in_tx_queue(adapter, tx_ring);
+               if (unlikely(rc))
+                       return;
+-              rc =  !ENA_IS_XDP_INDEX(adapter, i) ?
++              rc =  !ENA_IS_XDP_INDEX(adapter, qid) ?
+                       check_for_rx_interrupt_queue(adapter, rx_ring) : 0;
+               if (unlikely(rc))
+                       return;
+               budget--;
+-              if (!budget)
+-                      break;
+       }
+-      adapter->last_monitored_tx_qid = i % io_queue_count;
++      adapter->last_monitored_tx_qid = qid;
+ }
+ /* trigger napi schedule after 2 consecutive detections */
+-- 
+2.43.0
+
diff --git a/queue-5.10/net-mlx5-properly-link-new-fs-rules-into-the-tree.patch b/queue-5.10/net-mlx5-properly-link-new-fs-rules-into-the-tree.patch
new file mode 100644 (file)
index 0000000..de11fcf
--- /dev/null
@@ -0,0 +1,66 @@
+From 403ee7c649ddae48d71ce42c39f92cdf3712309d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Apr 2024 22:08:12 +0300
+Subject: net/mlx5: Properly link new fs rules into the tree
+
+From: Cosmin Ratiu <cratiu@nvidia.com>
+
+[ Upstream commit 7c6782ad4911cbee874e85630226ed389ff2e453 ]
+
+Previously, add_rule_fg would only add newly created rules from the
+handle into the tree when they had a refcount of 1. On the other hand,
+create_flow_handle tries hard to find and reference already existing
+identical rules instead of creating new ones.
+
+These two behaviors can result in a situation where create_flow_handle
+1) creates a new rule and references it, then
+2) in a subsequent step during the same handle creation references it
+   again,
+resulting in a rule with a refcount of 2 that is not linked into the
+tree, will have a NULL parent and root and will result in a crash when
+the flow group is deleted because del_sw_hw_rule, invoked on rule
+deletion, assumes node->parent is != NULL.
+
+This happened in the wild, due to another bug related to incorrect
+handling of duplicate pkt_reformat ids, which lead to the code in
+create_flow_handle incorrectly referencing a just-added rule in the same
+flow handle, resulting in the problem described above. Full details are
+at [1].
+
+This patch changes add_rule_fg to add new rules without parents into
+the tree, properly initializing them and avoiding the crash. This makes
+it more consistent with how rules are added to an FTE in
+create_flow_handle.
+
+Fixes: 74491de93712 ("net/mlx5: Add multi dest support")
+Link: https://lore.kernel.org/netdev/ea5264d6-6b55-4449-a602-214c6f509c1e@163.com/T/#u [1]
+Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
+Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
+Reviewed-by: Mark Bloch <mbloch@nvidia.com>
+Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
+Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
+Link: https://lore.kernel.org/r/20240409190820.227554-5-tariqt@nvidia.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/ethernet/mellanox/mlx5/core/fs_core.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+index 4e8e3797aed08..074c9eb44ab73 100644
+--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
++++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+@@ -1675,8 +1675,9 @@ static struct mlx5_flow_handle *add_rule_fg(struct mlx5_flow_group *fg,
+       }
+       trace_mlx5_fs_set_fte(fte, false);
++      /* Link newly added rules into the tree. */
+       for (i = 0; i < handle->num_rules; i++) {
+-              if (refcount_read(&handle->rule[i]->node.refcount) == 1) {
++              if (!handle->rule[i]->node.parent) {
+                       tree_add_node(&handle->rule[i]->node, &fte->node);
+                       trace_mlx5_fs_add_rule(handle->rule[i]);
+               }
+-- 
+2.43.0
+
diff --git a/queue-5.10/net-openvswitch-fix-unwanted-error-log-on-timeout-po.patch b/queue-5.10/net-openvswitch-fix-unwanted-error-log-on-timeout-po.patch
new file mode 100644 (file)
index 0000000..8500b07
--- /dev/null
@@ -0,0 +1,60 @@
+From 83a1d0356b634cc4da3d5c4b058a3cf8eedc1e98 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 3 Apr 2024 22:38:01 +0200
+Subject: net: openvswitch: fix unwanted error log on timeout policy probing
+
+From: Ilya Maximets <i.maximets@ovn.org>
+
+[ Upstream commit 4539f91f2a801c0c028c252bffae56030cfb2cae ]
+
+On startup, ovs-vswitchd probes different datapath features including
+support for timeout policies.  While probing, it tries to execute
+certain operations with OVS_PACKET_ATTR_PROBE or OVS_FLOW_ATTR_PROBE
+attributes set.  These attributes tell the openvswitch module to not
+log any errors when they occur as it is expected that some of the
+probes will fail.
+
+For some reason, setting the timeout policy ignores the PROBE attribute
+and logs a failure anyway.  This is causing the following kernel log
+on each re-start of ovs-vswitchd:
+
+  kernel: Failed to associated timeout policy `ovs_test_tp'
+
+Fix that by using the same logging macro that all other messages are
+using.  The message will still be printed at info level when needed
+and will be rate limited, but with a net rate limiter instead of
+generic printk one.
+
+The nf_ct_set_timeout() itself will still print some info messages,
+but at least this change makes logging in openvswitch module more
+consistent.
+
+Fixes: 06bd2bdf19d2 ("openvswitch: Add timeout support to ct action")
+Signed-off-by: Ilya Maximets <i.maximets@ovn.org>
+Acked-by: Eelco Chaudron <echaudro@redhat.com>
+Link: https://lore.kernel.org/r/20240403203803.2137962-1-i.maximets@ovn.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/openvswitch/conntrack.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c
+index 0f0f380e81a40..d452a63d2f4b0 100644
+--- a/net/openvswitch/conntrack.c
++++ b/net/openvswitch/conntrack.c
+@@ -1692,8 +1692,9 @@ int ovs_ct_copy_action(struct net *net, const struct nlattr *attr,
+       if (ct_info.timeout[0]) {
+               if (nf_ct_set_timeout(net, ct_info.ct, family, key->ip.proto,
+                                     ct_info.timeout))
+-                      pr_info_ratelimited("Failed to associated timeout "
+-                                          "policy `%s'\n", ct_info.timeout);
++                      OVS_NLERR(log,
++                                "Failed to associated timeout policy '%s'",
++                                ct_info.timeout);
+               else
+                       ct_info.nf_ct_timeout = rcu_dereference(
+                               nf_ct_timeout_find(ct_info.ct)->timeout);
+-- 
+2.43.0
+
diff --git a/queue-5.10/netfilter-complete-validation-of-user-input.patch b/queue-5.10/netfilter-complete-validation-of-user-input.patch
new file mode 100644 (file)
index 0000000..dd42fce
--- /dev/null
@@ -0,0 +1,102 @@
+From c45826228a42a4b51d8ec1e29bc6e4d8f099ff71 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 9 Apr 2024 12:07:41 +0000
+Subject: netfilter: complete validation of user input
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 65acf6e0501ac8880a4f73980d01b5d27648b956 ]
+
+In my recent commit, I missed that do_replace() handlers
+use copy_from_sockptr() (which I fixed), followed
+by unsafe copy_from_sockptr_offset() calls.
+
+In all functions, we can perform the @optlen validation
+before even calling xt_alloc_table_info() with the following
+check:
+
+if ((u64)optlen < (u64)tmp.size + sizeof(tmp))
+        return -EINVAL;
+
+Fixes: 0c83842df40f ("netfilter: validate user input for expected length")
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Link: https://lore.kernel.org/r/20240409120741.3538135-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/ipv4/netfilter/arp_tables.c | 4 ++++
+ net/ipv4/netfilter/ip_tables.c  | 4 ++++
+ net/ipv6/netfilter/ip6_tables.c | 4 ++++
+ 3 files changed, 12 insertions(+)
+
+diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c
+index 48c6aa3d91ae8..5823e89b8a734 100644
+--- a/net/ipv4/netfilter/arp_tables.c
++++ b/net/ipv4/netfilter/arp_tables.c
+@@ -965,6 +965,8 @@ static int do_replace(struct net *net, sockptr_t arg, unsigned int len)
+               return -ENOMEM;
+       if (tmp.num_counters == 0)
+               return -EINVAL;
++      if ((u64)len < (u64)tmp.size + sizeof(tmp))
++              return -EINVAL;
+       tmp.name[sizeof(tmp.name)-1] = 0;
+@@ -1265,6 +1267,8 @@ static int compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
+               return -ENOMEM;
+       if (tmp.num_counters == 0)
+               return -EINVAL;
++      if ((u64)len < (u64)tmp.size + sizeof(tmp))
++              return -EINVAL;
+       tmp.name[sizeof(tmp.name)-1] = 0;
+diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c
+index b46d58b9f3fe4..22e9ff592cd75 100644
+--- a/net/ipv4/netfilter/ip_tables.c
++++ b/net/ipv4/netfilter/ip_tables.c
+@@ -1119,6 +1119,8 @@ do_replace(struct net *net, sockptr_t arg, unsigned int len)
+               return -ENOMEM;
+       if (tmp.num_counters == 0)
+               return -EINVAL;
++      if ((u64)len < (u64)tmp.size + sizeof(tmp))
++              return -EINVAL;
+       tmp.name[sizeof(tmp.name)-1] = 0;
+@@ -1505,6 +1507,8 @@ compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
+               return -ENOMEM;
+       if (tmp.num_counters == 0)
+               return -EINVAL;
++      if ((u64)len < (u64)tmp.size + sizeof(tmp))
++              return -EINVAL;
+       tmp.name[sizeof(tmp.name)-1] = 0;
+diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
+index d013395be05fc..df7cd3d285e4f 100644
+--- a/net/ipv6/netfilter/ip6_tables.c
++++ b/net/ipv6/netfilter/ip6_tables.c
+@@ -1137,6 +1137,8 @@ do_replace(struct net *net, sockptr_t arg, unsigned int len)
+               return -ENOMEM;
+       if (tmp.num_counters == 0)
+               return -EINVAL;
++      if ((u64)len < (u64)tmp.size + sizeof(tmp))
++              return -EINVAL;
+       tmp.name[sizeof(tmp.name)-1] = 0;
+@@ -1515,6 +1517,8 @@ compat_do_replace(struct net *net, sockptr_t arg, unsigned int len)
+               return -ENOMEM;
+       if (tmp.num_counters == 0)
+               return -EINVAL;
++      if ((u64)len < (u64)tmp.size + sizeof(tmp))
++              return -EINVAL;
+       tmp.name[sizeof(tmp.name)-1] = 0;
+-- 
+2.43.0
+
diff --git a/queue-5.10/nouveau-fix-function-cast-warning.patch b/queue-5.10/nouveau-fix-function-cast-warning.patch
new file mode 100644 (file)
index 0000000..44565c7
--- /dev/null
@@ -0,0 +1,51 @@
+From 8d461fe6bb42e953f8813284e11209823edab676 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Apr 2024 18:02:25 +0200
+Subject: nouveau: fix function cast warning
+
+From: Arnd Bergmann <arnd@arndb.de>
+
+[ Upstream commit 185fdb4697cc9684a02f2fab0530ecdd0c2f15d4 ]
+
+Calling a function through an incompatible pointer type causes breaks
+kcfi, so clang warns about the assignment:
+
+drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c:73:10: error: cast from 'void (*)(const void *)' to 'void (*)(void *)' converts to incompatible function type [-Werror,-Wcast-function-type-strict]
+   73 |         .fini = (void(*)(void *))kfree,
+
+Avoid this with a trivial wrapper.
+
+Fixes: c39f472e9f14 ("drm/nouveau: remove symlinks, move core/ to nvkm/ (no code changes)")
+Signed-off-by: Arnd Bergmann <arnd@arndb.de>
+Signed-off-by: Danilo Krummrich <dakr@redhat.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240404160234.2923554-1-arnd@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
+index 4bf486b571013..cb05f7f48a98b 100644
+--- a/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
++++ b/drivers/gpu/drm/nouveau/nvkm/subdev/bios/shadowof.c
+@@ -66,11 +66,16 @@ of_init(struct nvkm_bios *bios, const char *name)
+       return ERR_PTR(-EINVAL);
+ }
++static void of_fini(void *p)
++{
++      kfree(p);
++}
++
+ const struct nvbios_source
+ nvbios_of = {
+       .name = "OpenFirmware",
+       .init = of_init,
+-      .fini = (void(*)(void *))kfree,
++      .fini = of_fini,
+       .read = of_read,
+       .size = of_size,
+       .rw = false,
+-- 
+2.43.0
+
diff --git a/queue-5.10/octeontx2-af-fix-nix-sq-mode-and-bp-config.patch b/queue-5.10/octeontx2-af-fix-nix-sq-mode-and-bp-config.patch
new file mode 100644 (file)
index 0000000..ea26207
--- /dev/null
@@ -0,0 +1,59 @@
+From e10120d3b6250122ec39443111ce426c60fee6d5 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 8 Apr 2024 12:06:43 +0530
+Subject: octeontx2-af: Fix NIX SQ mode and BP config
+
+From: Geetha sowjanya <gakula@marvell.com>
+
+[ Upstream commit faf23006185e777db18912685922c5ddb2df383f ]
+
+NIX SQ mode and link backpressure configuration is required for
+all platforms. But in current driver this code is wrongly placed
+under specific platform check. This patch fixes the issue by
+moving the code out of platform check.
+
+Fixes: 5d9b976d4480 ("octeontx2-af: Support fixed transmit scheduler topology")
+Signed-off-by: Geetha sowjanya <gakula@marvell.com>
+Link: https://lore.kernel.org/r/20240408063643.26288-1-gakula@marvell.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../ethernet/marvell/octeontx2/af/rvu_nix.c   | 20 +++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+index e549b09c347a7..fb4b18be503c5 100644
+--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
++++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+@@ -3146,18 +3146,18 @@ int rvu_nix_init(struct rvu *rvu)
+                */
+               rvu_write64(rvu, blkaddr, NIX_AF_CFG,
+                           rvu_read64(rvu, blkaddr, NIX_AF_CFG) | 0x40ULL);
++      }
+-              /* Set chan/link to backpressure TL3 instead of TL2 */
+-              rvu_write64(rvu, blkaddr, NIX_AF_PSE_CHANNEL_LEVEL, 0x01);
++      /* Set chan/link to backpressure TL3 instead of TL2 */
++      rvu_write64(rvu, blkaddr, NIX_AF_PSE_CHANNEL_LEVEL, 0x01);
+-              /* Disable SQ manager's sticky mode operation (set TM6 = 0)
+-               * This sticky mode is known to cause SQ stalls when multiple
+-               * SQs are mapped to same SMQ and transmitting pkts at a time.
+-               */
+-              cfg = rvu_read64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS);
+-              cfg &= ~BIT_ULL(15);
+-              rvu_write64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS, cfg);
+-      }
++      /* Disable SQ manager's sticky mode operation (set TM6 = 0)
++       * This sticky mode is known to cause SQ stalls when multiple
++       * SQs are mapped to same SMQ and transmitting pkts at a time.
++       */
++      cfg = rvu_read64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS);
++      cfg &= ~BIT_ULL(15);
++      rvu_write64(rvu, blkaddr, NIX_AF_SQM_DBG_CTL_STATUS, cfg);
+       ltdefs = rvu->kpu.lt_def;
+       /* Calibrate X2P bus to check if CGX/LBK links are fine */
+-- 
+2.43.0
+
index e781fabc2ab919704deeaa164be5f90216bdd1e8..5bd9bf7abc3c6ec4726c9cb78c1efcbc5da8e7d9 100644 (file)
@@ -1,3 +1,30 @@
 batman-adv-avoid-infinite-loop-trying-to-resize-local-tt.patch
 bluetooth-fix-memory-leak-in-hci_req_sync_complete.patch
 media-cec-core-remove-length-check-of-timer-status.patch
+nouveau-fix-function-cast-warning.patch
+net-openvswitch-fix-unwanted-error-log-on-timeout-po.patch
+u64_stats-disable-preemption-on-32bit-up-smp-preempt.patch
+u64_stats-streamline-the-implementation.patch
+u64_stats-fix-u64_stats_init-for-lockdep-when-used-r.patch
+xsk-validate-user-input-for-xdp_-umem-completion-_fi.patch
+geneve-fix-header-validation-in-geneve-6-_xmit_skb.patch
+octeontx2-af-fix-nix-sq-mode-and-bp-config.patch
+ipv6-fib-hide-unused-pn-variable.patch
+ipv4-route-avoid-unused-but-set-variable-warning.patch
+ipv6-fix-race-condition-between-ipv6_get_ifaddr-and-.patch
+bluetooth-fix-mgmt-status-for-ll-privacy-experimenta.patch
+bluetooth-add-support-for-reading-aosp-vendor-capabi.patch
+bluetooth-refactor-set_exp_feature-with-a-feature-ta.patch
+bluetooth-support-the-quality-report-events.patch
+bluetooth-enumerate-local-supported-codec-and-cache-.patch
+bluetooth-allow-querying-of-supported-offload-codecs.patch
+bluetooth-allow-setting-of-codec-for-hfp-offload-use.patch
+bluetooth-sco-fix-not-validating-setsockopt-user-inp.patch
+netfilter-complete-validation-of-user-input.patch
+net-mlx5-properly-link-new-fs-rules-into-the-tree.patch
+af_unix-do-not-use-atomic-ops-for-unix_sk-sk-infligh.patch
+af_unix-fix-garbage-collector-racing-against-connect.patch
+net-ena-fix-potential-sign-extension-issue.patch
+net-ena-wrong-missing-io-completions-check-order.patch
+net-ena-fix-incorrect-descriptor-free-behavior.patch
+iommu-vt-d-allocate-local-memory-for-page-request-qu.patch
diff --git a/queue-5.10/u64_stats-disable-preemption-on-32bit-up-smp-preempt.patch b/queue-5.10/u64_stats-disable-preemption-on-32bit-up-smp-preempt.patch
new file mode 100644 (file)
index 0000000..9de0b85
--- /dev/null
@@ -0,0 +1,164 @@
+From 34ec7b09c7f0abc2e742f68e5ce91cc53054406f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Dec 2021 21:29:59 +0100
+Subject: u64_stats: Disable preemption on 32bit UP+SMP PREEMPT_RT during
+ updates.
+
+From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+
+[ Upstream commit 3c118547f87e930d45a5787e386734015dd93b32 ]
+
+On PREEMPT_RT the seqcount_t for synchronisation is required on 32bit
+architectures even on UP because the softirq (and the threaded IRQ handler) can
+be preempted.
+
+With the seqcount_t for synchronisation, a reader with higher priority can
+preempt the writer and then spin endlessly in read_seqcount_begin() while the
+writer can't make progress.
+
+To avoid such a lock up on PREEMPT_RT the writer must disable preemption during
+the update. There is no need to disable interrupts because no writer is using
+this API in hard-IRQ context on PREEMPT_RT.
+
+Disable preemption on 32bit-RT within the u64_stats write section.
+
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 38a15d0a50e0 ("u64_stats: fix u64_stats_init() for lockdep when used repeatedly in one file")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/u64_stats_sync.h | 42 ++++++++++++++++++++++------------
+ 1 file changed, 28 insertions(+), 14 deletions(-)
+
+diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h
+index e81856c0ba134..6a0f2097d3709 100644
+--- a/include/linux/u64_stats_sync.h
++++ b/include/linux/u64_stats_sync.h
+@@ -66,7 +66,7 @@
+ #include <linux/seqlock.h>
+ struct u64_stats_sync {
+-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+       seqcount_t      seq;
+ #endif
+ };
+@@ -115,7 +115,7 @@ static inline void u64_stats_inc(u64_stats_t *p)
+ }
+ #endif
+-#if BITS_PER_LONG == 32 && defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+ #define u64_stats_init(syncp) seqcount_init(&(syncp)->seq)
+ #else
+ static inline void u64_stats_init(struct u64_stats_sync *syncp)
+@@ -125,15 +125,19 @@ static inline void u64_stats_init(struct u64_stats_sync *syncp)
+ static inline void u64_stats_update_begin(struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
++      if (IS_ENABLED(CONFIG_PREEMPT_RT))
++              preempt_disable();
+       write_seqcount_begin(&syncp->seq);
+ #endif
+ }
+ static inline void u64_stats_update_end(struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+       write_seqcount_end(&syncp->seq);
++      if (IS_ENABLED(CONFIG_PREEMPT_RT))
++              preempt_enable();
+ #endif
+ }
+@@ -142,8 +146,11 @@ u64_stats_update_begin_irqsave(struct u64_stats_sync *syncp)
+ {
+       unsigned long flags = 0;
+-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
+-      local_irq_save(flags);
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
++      if (IS_ENABLED(CONFIG_PREEMPT_RT))
++              preempt_disable();
++      else
++              local_irq_save(flags);
+       write_seqcount_begin(&syncp->seq);
+ #endif
+       return flags;
+@@ -153,15 +160,18 @@ static inline void
+ u64_stats_update_end_irqrestore(struct u64_stats_sync *syncp,
+                               unsigned long flags)
+ {
+-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+       write_seqcount_end(&syncp->seq);
+-      local_irq_restore(flags);
++      if (IS_ENABLED(CONFIG_PREEMPT_RT))
++              preempt_enable();
++      else
++              local_irq_restore(flags);
+ #endif
+ }
+ static inline unsigned int __u64_stats_fetch_begin(const struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+       return read_seqcount_begin(&syncp->seq);
+ #else
+       return 0;
+@@ -170,7 +180,7 @@ static inline unsigned int __u64_stats_fetch_begin(const struct u64_stats_sync *
+ static inline unsigned int u64_stats_fetch_begin(const struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG==32 && !defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (!defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_RT))
+       preempt_disable();
+ #endif
+       return __u64_stats_fetch_begin(syncp);
+@@ -179,7 +189,7 @@ static inline unsigned int u64_stats_fetch_begin(const struct u64_stats_sync *sy
+ static inline bool __u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
+                                        unsigned int start)
+ {
+-#if BITS_PER_LONG==32 && defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+       return read_seqcount_retry(&syncp->seq, start);
+ #else
+       return false;
+@@ -189,7 +199,7 @@ static inline bool __u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
+ static inline bool u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
+                                        unsigned int start)
+ {
+-#if BITS_PER_LONG==32 && !defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && (!defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_RT))
+       preempt_enable();
+ #endif
+       return __u64_stats_fetch_retry(syncp, start);
+@@ -203,7 +213,9 @@ static inline bool u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
+  */
+ static inline unsigned int u64_stats_fetch_begin_irq(const struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG==32 && !defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && defined(CONFIG_PREEMPT_RT)
++      preempt_disable();
++#elif BITS_PER_LONG == 32 && !defined(CONFIG_SMP)
+       local_irq_disable();
+ #endif
+       return __u64_stats_fetch_begin(syncp);
+@@ -212,7 +224,9 @@ static inline unsigned int u64_stats_fetch_begin_irq(const struct u64_stats_sync
+ static inline bool u64_stats_fetch_retry_irq(const struct u64_stats_sync *syncp,
+                                            unsigned int start)
+ {
+-#if BITS_PER_LONG==32 && !defined(CONFIG_SMP)
++#if BITS_PER_LONG == 32 && defined(CONFIG_PREEMPT_RT)
++      preempt_enable();
++#elif BITS_PER_LONG == 32 && !defined(CONFIG_SMP)
+       local_irq_enable();
+ #endif
+       return __u64_stats_fetch_retry(syncp, start);
+-- 
+2.43.0
+
diff --git a/queue-5.10/u64_stats-fix-u64_stats_init-for-lockdep-when-used-r.patch b/queue-5.10/u64_stats-fix-u64_stats_init-for-lockdep-when-used-r.patch
new file mode 100644 (file)
index 0000000..e34b450
--- /dev/null
@@ -0,0 +1,56 @@
+From d126067245d71c1d4a831a86eedbc702a5c6480a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Apr 2024 09:57:40 +0200
+Subject: u64_stats: fix u64_stats_init() for lockdep when used repeatedly in
+ one file
+
+From: Petr Tesarik <petr@tesarici.cz>
+
+[ Upstream commit 38a15d0a50e0a43778561a5861403851f0b0194c ]
+
+Fix bogus lockdep warnings if multiple u64_stats_sync variables are
+initialized in the same file.
+
+With CONFIG_LOCKDEP, seqcount_init() is a macro which declares:
+
+       static struct lock_class_key __key;
+
+Since u64_stats_init() is a function (albeit an inline one), all calls
+within the same file end up using the same instance, effectively treating
+them all as a single lock-class.
+
+Fixes: 9464ca650008 ("net: make u64_stats_init() a function")
+Closes: https://lore.kernel.org/netdev/ea1567d9-ce66-45e6-8168-ac40a47d1821@roeck-us.net/
+Signed-off-by: Petr Tesarik <petr@tesarici.cz>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Link: https://lore.kernel.org/r/20240404075740.30682-1-petr@tesarici.cz
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/u64_stats_sync.h | 9 +++++----
+ 1 file changed, 5 insertions(+), 4 deletions(-)
+
+diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h
+index 51f2e16b9540b..11c3162dade3b 100644
+--- a/include/linux/u64_stats_sync.h
++++ b/include/linux/u64_stats_sync.h
+@@ -125,10 +125,11 @@ static inline void u64_stats_inc(u64_stats_t *p)
+       p->v++;
+ }
+-static inline void u64_stats_init(struct u64_stats_sync *syncp)
+-{
+-      seqcount_init(&syncp->seq);
+-}
++#define u64_stats_init(syncp)                         \
++      do {                                            \
++              struct u64_stats_sync *__s = (syncp);   \
++              seqcount_init(&__s->seq);               \
++      } while (0)
+ static inline void __u64_stats_update_begin(struct u64_stats_sync *syncp)
+ {
+-- 
+2.43.0
+
diff --git a/queue-5.10/u64_stats-streamline-the-implementation.patch b/queue-5.10/u64_stats-streamline-the-implementation.patch
new file mode 100644 (file)
index 0000000..ebfe04e
--- /dev/null
@@ -0,0 +1,274 @@
+From 2253d0d81b05aa0961a0c4f8a1199b5626bb15d0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Aug 2022 18:41:31 +0200
+Subject: u64_stats: Streamline the implementation
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+[ Upstream commit 44b0c2957adc62b86fcd51adeaf8e993171bc319 ]
+
+The u64 stats code handles 3 different cases:
+
+  - 32bit UP
+  - 32bit SMP
+  - 64bit
+
+with an unreadable #ifdef maze, which was recently expanded with PREEMPT_RT
+conditionals.
+
+Reduce it to two cases (32bit and 64bit) and drop the optimization for
+32bit UP as suggested by Linus.
+
+Use the new preempt_disable/enable_nested() helpers to get rid of the
+CONFIG_PREEMPT_RT conditionals.
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Link: https://lore.kernel.org/r/20220825164131.402717-9-bigeasy@linutronix.de
+Stable-dep-of: 38a15d0a50e0 ("u64_stats: fix u64_stats_init() for lockdep when used repeatedly in one file")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/u64_stats_sync.h | 145 +++++++++++++++------------------
+ 1 file changed, 64 insertions(+), 81 deletions(-)
+
+diff --git a/include/linux/u64_stats_sync.h b/include/linux/u64_stats_sync.h
+index 6a0f2097d3709..51f2e16b9540b 100644
+--- a/include/linux/u64_stats_sync.h
++++ b/include/linux/u64_stats_sync.h
+@@ -8,7 +8,7 @@
+  *
+  * Key points :
+  *
+- * -  Use a seqcount on 32-bit SMP, only disable preemption for 32-bit UP.
++ * -  Use a seqcount on 32-bit
+  * -  The whole thing is a no-op on 64-bit architectures.
+  *
+  * Usage constraints:
+@@ -20,7 +20,8 @@
+  *    writer and also spin forever.
+  *
+  * 3) Write side must use the _irqsave() variant if other writers, or a reader,
+- *    can be invoked from an IRQ context.
++ *    can be invoked from an IRQ context. On 64bit systems this variant does not
++ *    disable interrupts.
+  *
+  * 4) If reader fetches several counters, there is no guarantee the whole values
+  *    are consistent w.r.t. each other (remember point #2: seqcounts are not
+@@ -29,11 +30,6 @@
+  * 5) Readers are allowed to sleep or be preempted/interrupted: they perform
+  *    pure reads.
+  *
+- * 6) Readers must use both u64_stats_fetch_{begin,retry}_irq() if the stats
+- *    might be updated from a hardirq or softirq context (remember point #1:
+- *    seqcounts are not used for UP kernels). 32-bit UP stat readers could read
+- *    corrupted 64-bit values otherwise.
+- *
+  * Usage :
+  *
+  * Stats producer (writer) should use following template granted it already got
+@@ -66,7 +62,7 @@
+ #include <linux/seqlock.h>
+ struct u64_stats_sync {
+-#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
++#if BITS_PER_LONG == 32
+       seqcount_t      seq;
+ #endif
+ };
+@@ -93,7 +89,22 @@ static inline void u64_stats_inc(u64_stats_t *p)
+       local64_inc(&p->v);
+ }
+-#else
++static inline void u64_stats_init(struct u64_stats_sync *syncp) { }
++static inline void __u64_stats_update_begin(struct u64_stats_sync *syncp) { }
++static inline void __u64_stats_update_end(struct u64_stats_sync *syncp) { }
++static inline unsigned long __u64_stats_irqsave(void) { return 0; }
++static inline void __u64_stats_irqrestore(unsigned long flags) { }
++static inline unsigned int __u64_stats_fetch_begin(const struct u64_stats_sync *syncp)
++{
++      return 0;
++}
++static inline bool __u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
++                                         unsigned int start)
++{
++      return false;
++}
++
++#else /* 64 bit */
+ typedef struct {
+       u64             v;
+@@ -113,123 +124,95 @@ static inline void u64_stats_inc(u64_stats_t *p)
+ {
+       p->v++;
+ }
+-#endif
+-#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+-#define u64_stats_init(syncp) seqcount_init(&(syncp)->seq)
+-#else
+ static inline void u64_stats_init(struct u64_stats_sync *syncp)
+ {
++      seqcount_init(&syncp->seq);
+ }
+-#endif
+-static inline void u64_stats_update_begin(struct u64_stats_sync *syncp)
++static inline void __u64_stats_update_begin(struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+-      if (IS_ENABLED(CONFIG_PREEMPT_RT))
+-              preempt_disable();
++      preempt_disable_nested();
+       write_seqcount_begin(&syncp->seq);
+-#endif
+ }
+-static inline void u64_stats_update_end(struct u64_stats_sync *syncp)
++static inline void __u64_stats_update_end(struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+       write_seqcount_end(&syncp->seq);
+-      if (IS_ENABLED(CONFIG_PREEMPT_RT))
+-              preempt_enable();
+-#endif
++      preempt_enable_nested();
+ }
+-static inline unsigned long
+-u64_stats_update_begin_irqsave(struct u64_stats_sync *syncp)
++static inline unsigned long __u64_stats_irqsave(void)
+ {
+-      unsigned long flags = 0;
++      unsigned long flags;
+-#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+-      if (IS_ENABLED(CONFIG_PREEMPT_RT))
+-              preempt_disable();
+-      else
+-              local_irq_save(flags);
+-      write_seqcount_begin(&syncp->seq);
+-#endif
++      local_irq_save(flags);
+       return flags;
+ }
+-static inline void
+-u64_stats_update_end_irqrestore(struct u64_stats_sync *syncp,
+-                              unsigned long flags)
++static inline void __u64_stats_irqrestore(unsigned long flags)
+ {
+-#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+-      write_seqcount_end(&syncp->seq);
+-      if (IS_ENABLED(CONFIG_PREEMPT_RT))
+-              preempt_enable();
+-      else
+-              local_irq_restore(flags);
+-#endif
++      local_irq_restore(flags);
+ }
+ static inline unsigned int __u64_stats_fetch_begin(const struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+       return read_seqcount_begin(&syncp->seq);
+-#else
+-      return 0;
+-#endif
+ }
+-static inline unsigned int u64_stats_fetch_begin(const struct u64_stats_sync *syncp)
++static inline bool __u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
++                                         unsigned int start)
+ {
+-#if BITS_PER_LONG == 32 && (!defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_RT))
+-      preempt_disable();
+-#endif
+-      return __u64_stats_fetch_begin(syncp);
++      return read_seqcount_retry(&syncp->seq, start);
+ }
++#endif /* !64 bit */
+-static inline bool __u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
+-                                       unsigned int start)
++static inline void u64_stats_update_begin(struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG == 32 && (defined(CONFIG_SMP) || defined(CONFIG_PREEMPT_RT))
+-      return read_seqcount_retry(&syncp->seq, start);
+-#else
+-      return false;
+-#endif
++      __u64_stats_update_begin(syncp);
++}
++
++static inline void u64_stats_update_end(struct u64_stats_sync *syncp)
++{
++      __u64_stats_update_end(syncp);
++}
++
++static inline unsigned long u64_stats_update_begin_irqsave(struct u64_stats_sync *syncp)
++{
++      unsigned long flags = __u64_stats_irqsave();
++
++      __u64_stats_update_begin(syncp);
++      return flags;
++}
++
++static inline void u64_stats_update_end_irqrestore(struct u64_stats_sync *syncp,
++                                                 unsigned long flags)
++{
++      __u64_stats_update_end(syncp);
++      __u64_stats_irqrestore(flags);
++}
++
++static inline unsigned int u64_stats_fetch_begin(const struct u64_stats_sync *syncp)
++{
++      return __u64_stats_fetch_begin(syncp);
+ }
+ static inline bool u64_stats_fetch_retry(const struct u64_stats_sync *syncp,
+                                        unsigned int start)
+ {
+-#if BITS_PER_LONG == 32 && (!defined(CONFIG_SMP) && !defined(CONFIG_PREEMPT_RT))
+-      preempt_enable();
+-#endif
+       return __u64_stats_fetch_retry(syncp, start);
+ }
+-/*
+- * In case irq handlers can update u64 counters, readers can use following helpers
+- * - SMP 32bit arches use seqcount protection, irq safe.
+- * - UP 32bit must disable irqs.
+- * - 64bit have no problem atomically reading u64 values, irq safe.
+- */
++/* Obsolete interfaces */
+ static inline unsigned int u64_stats_fetch_begin_irq(const struct u64_stats_sync *syncp)
+ {
+-#if BITS_PER_LONG == 32 && defined(CONFIG_PREEMPT_RT)
+-      preempt_disable();
+-#elif BITS_PER_LONG == 32 && !defined(CONFIG_SMP)
+-      local_irq_disable();
+-#endif
+-      return __u64_stats_fetch_begin(syncp);
++      return u64_stats_fetch_begin(syncp);
+ }
+ static inline bool u64_stats_fetch_retry_irq(const struct u64_stats_sync *syncp,
+                                            unsigned int start)
+ {
+-#if BITS_PER_LONG == 32 && defined(CONFIG_PREEMPT_RT)
+-      preempt_enable();
+-#elif BITS_PER_LONG == 32 && !defined(CONFIG_SMP)
+-      local_irq_enable();
+-#endif
+-      return __u64_stats_fetch_retry(syncp, start);
++      return u64_stats_fetch_retry(syncp, start);
+ }
+ #endif /* _LINUX_U64_STATS_SYNC_H */
+-- 
+2.43.0
+
diff --git a/queue-5.10/xsk-validate-user-input-for-xdp_-umem-completion-_fi.patch b/queue-5.10/xsk-validate-user-input-for-xdp_-umem-completion-_fi.patch
new file mode 100644 (file)
index 0000000..e3afa4d
--- /dev/null
@@ -0,0 +1,176 @@
+From fb948fe60edd2f39910ed9e8f95fc99cf6934ed0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 4 Apr 2024 20:27:38 +0000
+Subject: xsk: validate user input for XDP_{UMEM|COMPLETION}_FILL_RING
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ Upstream commit 237f3cf13b20db183d3706d997eedc3c49eacd44 ]
+
+syzbot reported an illegal copy in xsk_setsockopt() [1]
+
+Make sure to validate setsockopt() @optlen parameter.
+
+[1]
+
+ BUG: KASAN: slab-out-of-bounds in copy_from_sockptr_offset include/linux/sockptr.h:49 [inline]
+ BUG: KASAN: slab-out-of-bounds in copy_from_sockptr include/linux/sockptr.h:55 [inline]
+ BUG: KASAN: slab-out-of-bounds in xsk_setsockopt+0x909/0xa40 net/xdp/xsk.c:1420
+Read of size 4 at addr ffff888028c6cde3 by task syz-executor.0/7549
+
+CPU: 0 PID: 7549 Comm: syz-executor.0 Not tainted 6.8.0-syzkaller-08951-gfe46a7dd189e #0
+Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 03/27/2024
+Call Trace:
+ <TASK>
+  __dump_stack lib/dump_stack.c:88 [inline]
+  dump_stack_lvl+0x241/0x360 lib/dump_stack.c:114
+  print_address_description mm/kasan/report.c:377 [inline]
+  print_report+0x169/0x550 mm/kasan/report.c:488
+  kasan_report+0x143/0x180 mm/kasan/report.c:601
+  copy_from_sockptr_offset include/linux/sockptr.h:49 [inline]
+  copy_from_sockptr include/linux/sockptr.h:55 [inline]
+  xsk_setsockopt+0x909/0xa40 net/xdp/xsk.c:1420
+  do_sock_setsockopt+0x3af/0x720 net/socket.c:2311
+  __sys_setsockopt+0x1ae/0x250 net/socket.c:2334
+  __do_sys_setsockopt net/socket.c:2343 [inline]
+  __se_sys_setsockopt net/socket.c:2340 [inline]
+  __x64_sys_setsockopt+0xb5/0xd0 net/socket.c:2340
+ do_syscall_64+0xfb/0x240
+ entry_SYSCALL_64_after_hwframe+0x6d/0x75
+RIP: 0033:0x7fb40587de69
+Code: 28 00 00 00 75 05 48 83 c4 28 c3 e8 e1 20 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b0 ff ff ff f7 d8 64 89 01 48
+RSP: 002b:00007fb40665a0c8 EFLAGS: 00000246 ORIG_RAX: 0000000000000036
+RAX: ffffffffffffffda RBX: 00007fb4059abf80 RCX: 00007fb40587de69
+RDX: 0000000000000005 RSI: 000000000000011b RDI: 0000000000000006
+RBP: 00007fb4058ca47a R08: 0000000000000002 R09: 0000000000000000
+R10: 0000000020001980 R11: 0000000000000246 R12: 0000000000000000
+R13: 000000000000000b R14: 00007fb4059abf80 R15: 00007fff57ee4d08
+ </TASK>
+
+Allocated by task 7549:
+  kasan_save_stack mm/kasan/common.c:47 [inline]
+  kasan_save_track+0x3f/0x80 mm/kasan/common.c:68
+  poison_kmalloc_redzone mm/kasan/common.c:370 [inline]
+  __kasan_kmalloc+0x98/0xb0 mm/kasan/common.c:387
+  kasan_kmalloc include/linux/kasan.h:211 [inline]
+  __do_kmalloc_node mm/slub.c:3966 [inline]
+  __kmalloc+0x233/0x4a0 mm/slub.c:3979
+  kmalloc include/linux/slab.h:632 [inline]
+  __cgroup_bpf_run_filter_setsockopt+0xd2f/0x1040 kernel/bpf/cgroup.c:1869
+  do_sock_setsockopt+0x6b4/0x720 net/socket.c:2293
+  __sys_setsockopt+0x1ae/0x250 net/socket.c:2334
+  __do_sys_setsockopt net/socket.c:2343 [inline]
+  __se_sys_setsockopt net/socket.c:2340 [inline]
+  __x64_sys_setsockopt+0xb5/0xd0 net/socket.c:2340
+ do_syscall_64+0xfb/0x240
+ entry_SYSCALL_64_after_hwframe+0x6d/0x75
+
+The buggy address belongs to the object at ffff888028c6cde0
+ which belongs to the cache kmalloc-8 of size 8
+The buggy address is located 1 bytes to the right of
+ allocated 2-byte region [ffff888028c6cde0, ffff888028c6cde2)
+
+The buggy address belongs to the physical page:
+page:ffffea0000a31b00 refcount:1 mapcount:0 mapping:0000000000000000 index:0xffff888028c6c9c0 pfn:0x28c6c
+anon flags: 0xfff00000000800(slab|node=0|zone=1|lastcpupid=0x7ff)
+page_type: 0xffffffff()
+raw: 00fff00000000800 ffff888014c41280 0000000000000000 dead000000000001
+raw: ffff888028c6c9c0 0000000080800057 00000001ffffffff 0000000000000000
+page dumped because: kasan: bad access detected
+page_owner tracks the page as allocated
+page last allocated via order 0, migratetype Unmovable, gfp_mask 0x112cc0(GFP_USER|__GFP_NOWARN|__GFP_NORETRY), pid 6648, tgid 6644 (syz-executor.0), ts 133906047828, free_ts 133859922223
+  set_page_owner include/linux/page_owner.h:31 [inline]
+  post_alloc_hook+0x1ea/0x210 mm/page_alloc.c:1533
+  prep_new_page mm/page_alloc.c:1540 [inline]
+  get_page_from_freelist+0x33ea/0x3580 mm/page_alloc.c:3311
+  __alloc_pages+0x256/0x680 mm/page_alloc.c:4569
+  __alloc_pages_node include/linux/gfp.h:238 [inline]
+  alloc_pages_node include/linux/gfp.h:261 [inline]
+  alloc_slab_page+0x5f/0x160 mm/slub.c:2175
+  allocate_slab mm/slub.c:2338 [inline]
+  new_slab+0x84/0x2f0 mm/slub.c:2391
+  ___slab_alloc+0xc73/0x1260 mm/slub.c:3525
+  __slab_alloc mm/slub.c:3610 [inline]
+  __slab_alloc_node mm/slub.c:3663 [inline]
+  slab_alloc_node mm/slub.c:3835 [inline]
+  __do_kmalloc_node mm/slub.c:3965 [inline]
+  __kmalloc_node+0x2db/0x4e0 mm/slub.c:3973
+  kmalloc_node include/linux/slab.h:648 [inline]
+  __vmalloc_area_node mm/vmalloc.c:3197 [inline]
+  __vmalloc_node_range+0x5f9/0x14a0 mm/vmalloc.c:3392
+  __vmalloc_node mm/vmalloc.c:3457 [inline]
+  vzalloc+0x79/0x90 mm/vmalloc.c:3530
+  bpf_check+0x260/0x19010 kernel/bpf/verifier.c:21162
+  bpf_prog_load+0x1667/0x20f0 kernel/bpf/syscall.c:2895
+  __sys_bpf+0x4ee/0x810 kernel/bpf/syscall.c:5631
+  __do_sys_bpf kernel/bpf/syscall.c:5738 [inline]
+  __se_sys_bpf kernel/bpf/syscall.c:5736 [inline]
+  __x64_sys_bpf+0x7c/0x90 kernel/bpf/syscall.c:5736
+ do_syscall_64+0xfb/0x240
+ entry_SYSCALL_64_after_hwframe+0x6d/0x75
+page last free pid 6650 tgid 6647 stack trace:
+  reset_page_owner include/linux/page_owner.h:24 [inline]
+  free_pages_prepare mm/page_alloc.c:1140 [inline]
+  free_unref_page_prepare+0x95d/0xa80 mm/page_alloc.c:2346
+  free_unref_page_list+0x5a3/0x850 mm/page_alloc.c:2532
+  release_pages+0x2117/0x2400 mm/swap.c:1042
+  tlb_batch_pages_flush mm/mmu_gather.c:98 [inline]
+  tlb_flush_mmu_free mm/mmu_gather.c:293 [inline]
+  tlb_flush_mmu+0x34d/0x4e0 mm/mmu_gather.c:300
+  tlb_finish_mmu+0xd4/0x200 mm/mmu_gather.c:392
+  exit_mmap+0x4b6/0xd40 mm/mmap.c:3300
+  __mmput+0x115/0x3c0 kernel/fork.c:1345
+  exit_mm+0x220/0x310 kernel/exit.c:569
+  do_exit+0x99e/0x27e0 kernel/exit.c:865
+  do_group_exit+0x207/0x2c0 kernel/exit.c:1027
+  get_signal+0x176e/0x1850 kernel/signal.c:2907
+  arch_do_signal_or_restart+0x96/0x860 arch/x86/kernel/signal.c:310
+  exit_to_user_mode_loop kernel/entry/common.c:105 [inline]
+  exit_to_user_mode_prepare include/linux/entry-common.h:328 [inline]
+  __syscall_exit_to_user_mode_work kernel/entry/common.c:201 [inline]
+  syscall_exit_to_user_mode+0xc9/0x360 kernel/entry/common.c:212
+  do_syscall_64+0x10a/0x240 arch/x86/entry/common.c:89
+ entry_SYSCALL_64_after_hwframe+0x6d/0x75
+
+Memory state around the buggy address:
+ ffff888028c6cc80: fa fc fc fc fa fc fc fc fa fc fc fc fa fc fc fc
+ ffff888028c6cd00: fa fc fc fc fa fc fc fc 00 fc fc fc 06 fc fc fc
+>ffff888028c6cd80: fa fc fc fc fa fc fc fc fa fc fc fc 02 fc fc fc
+                                                       ^
+ ffff888028c6ce00: fa fc fc fc fa fc fc fc fa fc fc fc fa fc fc fc
+ ffff888028c6ce80: fa fc fc fc fa fc fc fc fa fc fc fc fa fc fc fc
+
+Fixes: 423f38329d26 ("xsk: add umem fill queue support and mmap")
+Reported-by: syzbot <syzkaller@googlegroups.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: "Björn Töpel" <bjorn@kernel.org>
+Cc: Magnus Karlsson <magnus.karlsson@intel.com>
+Cc: Maciej Fijalkowski <maciej.fijalkowski@intel.com>
+Cc: Jonathan Lemon <jonathan.lemon@gmail.com>
+Acked-by: Daniel Borkmann <daniel@iogearbox.net>
+Link: https://lore.kernel.org/r/20240404202738.3634547-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ net/xdp/xsk.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/net/xdp/xsk.c b/net/xdp/xsk.c
+index d04f91f4d09df..562d69f17b4c0 100644
+--- a/net/xdp/xsk.c
++++ b/net/xdp/xsk.c
+@@ -895,6 +895,8 @@ static int xsk_setsockopt(struct socket *sock, int level, int optname,
+               struct xsk_queue **q;
+               int entries;
++              if (optlen < sizeof(entries))
++                      return -EINVAL;
+               if (copy_from_sockptr(&entries, optval, sizeof(entries)))
+                       return -EFAULT;
+-- 
+2.43.0
+