From 7f87a3cd95e1c51fd624a4d3ed5bb7cc0da611e1 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Mon, 15 Apr 2024 04:56:17 -0400 Subject: [PATCH] Fixes for 5.10 Signed-off-by: Sasha Levin --- ...se-atomic-ops-for-unix_sk-sk-infligh.patch | 147 +++++++ ...age-collector-racing-against-connect.patch | 122 ++++++ ...pport-for-reading-aosp-vendor-capabi.patch | 179 ++++++++ ...querying-of-supported-offload-codecs.patch | 212 ++++++++++ ...setting-of-codec-for-hfp-offload-use.patch | 139 +++++++ ...ate-local-supported-codec-and-cache-.patch | 384 ++++++++++++++++++ ...mt-status-for-ll-privacy-experimenta.patch | 37 ++ ...or-set_exp_feature-with-a-feature-ta.patch | 330 +++++++++++++++ ...x-not-validating-setsockopt-user-inp.patch | 122 ++++++ ...th-support-the-quality-report-events.patch | 218 ++++++++++ ...der-validation-in-geneve-6-_xmit_skb.patch | 166 ++++++++ ...ate-local-memory-for-page-request-qu.patch | 39 ++ ...void-unused-but-set-variable-warning.patch | 51 +++ .../ipv6-fib-hide-unused-pn-variable.patch | 60 +++ ...ndition-between-ipv6_get_ifaddr-and-.patch | 133 ++++++ ...x-incorrect-descriptor-free-behavior.patch | 72 ++++ ...a-fix-potential-sign-extension-issue.patch | 66 +++ ...g-missing-io-completions-check-order.patch | 108 +++++ ...erly-link-new-fs-rules-into-the-tree.patch | 66 +++ ...fix-unwanted-error-log-on-timeout-po.patch | 60 +++ ...er-complete-validation-of-user-input.patch | 102 +++++ .../nouveau-fix-function-cast-warning.patch | 51 +++ ...tx2-af-fix-nix-sq-mode-and-bp-config.patch | 59 +++ queue-5.10/series | 27 ++ ...e-preemption-on-32bit-up-smp-preempt.patch | 164 ++++++++ ...4_stats_init-for-lockdep-when-used-r.patch | 56 +++ ..._stats-streamline-the-implementation.patch | 274 +++++++++++++ ...r-input-for-xdp_-umem-completion-_fi.patch | 176 ++++++++ 28 files changed, 3620 insertions(+) create mode 100644 queue-5.10/af_unix-do-not-use-atomic-ops-for-unix_sk-sk-infligh.patch create mode 100644 queue-5.10/af_unix-fix-garbage-collector-racing-against-connect.patch create mode 100644 queue-5.10/bluetooth-add-support-for-reading-aosp-vendor-capabi.patch create mode 100644 queue-5.10/bluetooth-allow-querying-of-supported-offload-codecs.patch create mode 100644 queue-5.10/bluetooth-allow-setting-of-codec-for-hfp-offload-use.patch create mode 100644 queue-5.10/bluetooth-enumerate-local-supported-codec-and-cache-.patch create mode 100644 queue-5.10/bluetooth-fix-mgmt-status-for-ll-privacy-experimenta.patch create mode 100644 queue-5.10/bluetooth-refactor-set_exp_feature-with-a-feature-ta.patch create mode 100644 queue-5.10/bluetooth-sco-fix-not-validating-setsockopt-user-inp.patch create mode 100644 queue-5.10/bluetooth-support-the-quality-report-events.patch create mode 100644 queue-5.10/geneve-fix-header-validation-in-geneve-6-_xmit_skb.patch create mode 100644 queue-5.10/iommu-vt-d-allocate-local-memory-for-page-request-qu.patch create mode 100644 queue-5.10/ipv4-route-avoid-unused-but-set-variable-warning.patch create mode 100644 queue-5.10/ipv6-fib-hide-unused-pn-variable.patch create mode 100644 queue-5.10/ipv6-fix-race-condition-between-ipv6_get_ifaddr-and-.patch create mode 100644 queue-5.10/net-ena-fix-incorrect-descriptor-free-behavior.patch create mode 100644 queue-5.10/net-ena-fix-potential-sign-extension-issue.patch create mode 100644 queue-5.10/net-ena-wrong-missing-io-completions-check-order.patch create mode 100644 queue-5.10/net-mlx5-properly-link-new-fs-rules-into-the-tree.patch create mode 100644 queue-5.10/net-openvswitch-fix-unwanted-error-log-on-timeout-po.patch create mode 100644 queue-5.10/netfilter-complete-validation-of-user-input.patch create mode 100644 queue-5.10/nouveau-fix-function-cast-warning.patch create mode 100644 queue-5.10/octeontx2-af-fix-nix-sq-mode-and-bp-config.patch create mode 100644 queue-5.10/u64_stats-disable-preemption-on-32bit-up-smp-preempt.patch create mode 100644 queue-5.10/u64_stats-fix-u64_stats_init-for-lockdep-when-used-r.patch create mode 100644 queue-5.10/u64_stats-streamline-the-implementation.patch create mode 100644 queue-5.10/xsk-validate-user-input-for-xdp_-umem-completion-_fi.patch 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 index 00000000000..4536a7905c7 --- /dev/null +++ b/queue-5.10/af_unix-do-not-use-atomic-ops-for-unix_sk-sk-infligh.patch @@ -0,0 +1,147 @@ +From 89981f90ebaff79a5d86f72eb4afe37393e11fdf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Simon Horman +Link: https://lore.kernel.org/r/20240123170856.41348-3-kuniyu@amazon.com +Signed-off-by: Jakub Kicinski +Stable-dep-of: 47d8ac011fe1 ("af_unix: Fix garbage collector racing against connect()") +Signed-off-by: Sasha Levin +--- + 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, ¬_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 index 00000000000..d98529ec4fd --- /dev/null +++ b/queue-5.10/af_unix-fix-garbage-collector-racing-against-connect.patch @@ -0,0 +1,122 @@ +From 2ec6731a78b7246b538dec88213111c200f95738 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Apr 2024 22:09:39 +0200 +Subject: af_unix: Fix garbage collector racing against connect() + +From: Michal Luczaj + +[ 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 +Reviewed-by: Kuniyuki Iwashima +Link: https://lore.kernel.org/r/20240409201047.1032217-1-mhal@rbox.co +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..4df389e249f --- /dev/null +++ b/queue-5.10/bluetooth-add-support-for-reading-aosp-vendor-capabi.patch @@ -0,0 +1,179 @@ +From a18146e51c874d5e9cfddb143e56023462004f3f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 6 Apr 2021 21:55:52 +0200 +Subject: Bluetooth: Add support for reading AOSP vendor capabilities + +From: Marcel Holtmann + +[ Upstream commit f67743f9e03a67dbbf931d1787e6faf50766e521 ] + +When drivers indicate support for AOSP vendor extension, initialize them +and read its capabilities. + +Signed-off-by: Marcel Holtmann +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input") +Signed-off-by: Sasha Levin +--- + 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 ++#include ++ ++#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 index 00000000000..b7647a8730e --- /dev/null +++ b/queue-5.10/bluetooth-allow-querying-of-supported-offload-codecs.patch @@ -0,0 +1,212 @@ +From 8bf980068612e7431ce14077b115729a05ebd523 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Sep 2021 15:42:40 +0530 +Subject: Bluetooth: Allow querying of supported offload codecs over SCO socket + +From: Kiran K + +[ 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 +Reviewed-by: Chethan T N +Reviewed-by: Srivatsa Ravishankar +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..84e6062d2f9 --- /dev/null +++ b/queue-5.10/bluetooth-allow-setting-of-codec-for-hfp-offload-use.patch @@ -0,0 +1,139 @@ +From 7e59316473bc029ca3bfcea291cd36332f76dd57 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Sep 2021 15:42:42 +0530 +Subject: Bluetooth: Allow setting of codec for HFP offload use case + +From: Kiran K + +[ 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 +Reviewed-by: Chethan T N +Reviewed-by: Srivatsa Ravishankar +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..5dce1d87b42 --- /dev/null +++ b/queue-5.10/bluetooth-enumerate-local-supported-codec-and-cache-.patch @@ -0,0 +1,384 @@ +From 2db9c07bee1bfa5bd156e52dfb5f31eeb313e545 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 7 Sep 2021 15:42:37 +0530 +Subject: Bluetooth: Enumerate local supported codec and cache details + +From: Kiran K + +[ 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 +Signed-off-by: Chethan T N +Signed-off-by: Srivatsa Ravishankar +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input") +Signed-off-by: Sasha Levin +--- + 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 ++#include ++#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 index 00000000000..6a6e1e9bf82 --- /dev/null +++ b/queue-5.10/bluetooth-fix-mgmt-status-for-ll-privacy-experimenta.patch @@ -0,0 +1,37 @@ +From 704cacb29acbc095280862f903c7c19487f5f6f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 14 Mar 2021 14:49:38 +0100 +Subject: Bluetooth: Fix mgmt status for LL Privacy experimental feature + +From: Marcel Holtmann + +[ 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 +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..3c8fb448468 --- /dev/null +++ b/queue-5.10/bluetooth-refactor-set_exp_feature-with-a-feature-ta.patch @@ -0,0 +1,330 @@ +From 2530dd42cf909251594d1aa00c51ae026bf5926d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Aug 2021 20:17:15 +0800 +Subject: Bluetooth: refactor set_exp_feature with a feature table + +From: Joseph Hwang + +[ 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 +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e073a6c6fb0 --- /dev/null +++ b/queue-5.10/bluetooth-sco-fix-not-validating-setsockopt-user-inp.patch @@ -0,0 +1,122 @@ +From 9ed24baace071a8d8d8d02e3d755d9e7e9b8142c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Apr 2024 15:41:52 -0400 +Subject: Bluetooth: SCO: Fix not validating setsockopt user input + +From: Luiz Augusto von Dentz + +[ 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 +Signed-off-by: Eric Dumazet +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e61e5795f71 --- /dev/null +++ b/queue-5.10/bluetooth-support-the-quality-report-events.patch @@ -0,0 +1,218 @@ +From e3e2c7a31fbb58c63dfa1ac477ee297e979f7eab Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 15 Aug 2021 20:17:16 +0800 +Subject: Bluetooth: Support the quality report events + +From: Joseph Hwang + +[ 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 +Signed-off-by: Joseph Hwang +Signed-off-by: Luiz Augusto von Dentz +Stable-dep-of: 51eda36d33e4 ("Bluetooth: SCO: Fix not validating setsockopt user input") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..a60a9c5d420 --- /dev/null +++ b/queue-5.10/geneve-fix-header-validation-in-geneve-6-_xmit_skb.patch @@ -0,0 +1,166 @@ +From 2277a5c4398835a1c6df53d596275476438e722e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 Apr 2024 10:30:34 +0000 +Subject: geneve: fix header validation in geneve[6]_xmit_skb + +From: Eric Dumazet + +[ 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 +Cc: Phillip Potter +Cc: Sabrina Dubroca +Reviewed-by: Sabrina Dubroca +Reviewed-by: Phillip Potter +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..56123cc040e --- /dev/null +++ b/queue-5.10/iommu-vt-d-allocate-local-memory-for-page-request-qu.patch @@ -0,0 +1,39 @@ +From a6e0a0dbd53b649a706589f5674eb10942d4f026 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Apr 2024 11:07:43 +0800 +Subject: iommu/vt-d: Allocate local memory for page request queue + +From: Jacob Pan + +[ 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 +Reviewed-by: Kevin Tian +Link: https://lore.kernel.org/r/20240403214007.985600-1-jacob.jun.pan@linux.intel.com +Signed-off-by: Lu Baolu +Signed-off-by: Joerg Roedel +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e8da41b0918 --- /dev/null +++ b/queue-5.10/ipv4-route-avoid-unused-but-set-variable-warning.patch @@ -0,0 +1,51 @@ +From e7fb60a18ff9b60ae60063381a08a76263c46958 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Apr 2024 09:42:03 +0200 +Subject: ipv4/route: avoid unused-but-set-variable warning + +From: Arnd Bergmann + +[ 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 +Signed-off-by: Arnd Bergmann +Reviewed-by: Eric Dumazet +Link: https://lore.kernel.org/r/20240408074219.3030256-2-arnd@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..fc943c57363 --- /dev/null +++ b/queue-5.10/ipv6-fib-hide-unused-pn-variable.patch @@ -0,0 +1,60 @@ +From 351dafcc6015d7c3c7f31988b6c33d97cf46c1d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Apr 2024 09:42:02 +0200 +Subject: ipv6: fib: hide unused 'pn' variable + +From: Arnd Bergmann + +[ 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 +Signed-off-by: Arnd Bergmann +Reviewed-by: Eric Dumazet +Link: https://lore.kernel.org/r/20240408074219.3030256-1-arnd@kernel.org +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..67cf3d51ca7 --- /dev/null +++ b/queue-5.10/ipv6-fix-race-condition-between-ipv6_get_ifaddr-and-.patch @@ -0,0 +1,133 @@ +From fd1c84d9164e1c72e2e4862c91578d518956b4a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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] +[ 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] + +Fixes: 5c578aedcb21d ("IPv6: convert addrconf hash list to RCU") +Reviewed-by: Eric Dumazet +Reviewed-by: David Ahern +Signed-off-by: Jiri Benc +Link: https://lore.kernel.org/r/8ab821e36073a4a406c50ec83c9e8dc586c539e4.1712585809.git.jbenc@redhat.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f7333cc85be --- /dev/null +++ b/queue-5.10/net-ena-fix-incorrect-descriptor-free-behavior.patch @@ -0,0 +1,72 @@ +From 6f047f38a013d31fdea54e0eb8c2168885e53296 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Apr 2024 09:13:57 +0000 +Subject: net: ena: Fix incorrect descriptor free behavior + +From: David Arinzon + +[ 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 +Signed-off-by: David Arinzon +Reviewed-by: Shannon Nelson +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..0e120abd003 --- /dev/null +++ b/queue-5.10/net-ena-fix-potential-sign-extension-issue.patch @@ -0,0 +1,66 @@ +From 9ef7dfaead7c3b1a9d18e36529a497cdebb60d75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Apr 2024 09:13:55 +0000 +Subject: net: ena: Fix potential sign extension issue + +From: David Arinzon + +[ 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 +Signed-off-by: David Arinzon +Reviewed-by: Shannon Nelson +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..fcdac9e78a5 --- /dev/null +++ b/queue-5.10/net-ena-wrong-missing-io-completions-check-order.patch @@ -0,0 +1,108 @@ +From 3c20a3e37153bca1580e092b0d1d2051e1236cf9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 10 Apr 2024 09:13:56 +0000 +Subject: net: ena: Wrong missing IO completions check order + +From: David Arinzon + +[ 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 +Signed-off-by: David Arinzon +Reviewed-by: Shannon Nelson +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..de11fcf0cb9 --- /dev/null +++ b/queue-5.10/net-mlx5-properly-link-new-fs-rules-into-the-tree.patch @@ -0,0 +1,66 @@ +From 403ee7c649ddae48d71ce42c39f92cdf3712309d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Apr 2024 22:08:12 +0300 +Subject: net/mlx5: Properly link new fs rules into the tree + +From: Cosmin Ratiu + +[ 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 +Reviewed-by: Tariq Toukan +Reviewed-by: Mark Bloch +Signed-off-by: Saeed Mahameed +Signed-off-by: Tariq Toukan +Link: https://lore.kernel.org/r/20240409190820.227554-5-tariqt@nvidia.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..8500b07dc79 --- /dev/null +++ b/queue-5.10/net-openvswitch-fix-unwanted-error-log-on-timeout-po.patch @@ -0,0 +1,60 @@ +From 83a1d0356b634cc4da3d5c4b058a3cf8eedc1e98 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 3 Apr 2024 22:38:01 +0200 +Subject: net: openvswitch: fix unwanted error log on timeout policy probing + +From: Ilya Maximets + +[ 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 +Acked-by: Eelco Chaudron +Link: https://lore.kernel.org/r/20240403203803.2137962-1-i.maximets@ovn.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..dd42fce5b7f --- /dev/null +++ b/queue-5.10/netfilter-complete-validation-of-user-input.patch @@ -0,0 +1,102 @@ +From c45826228a42a4b51d8ec1e29bc6e4d8f099ff71 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 9 Apr 2024 12:07:41 +0000 +Subject: netfilter: complete validation of user input + +From: Eric Dumazet + +[ 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 +Signed-off-by: Eric Dumazet +Reviewed-by: Pablo Neira Ayuso +Link: https://lore.kernel.org/r/20240409120741.3538135-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..44565c72433 --- /dev/null +++ b/queue-5.10/nouveau-fix-function-cast-warning.patch @@ -0,0 +1,51 @@ +From 8d461fe6bb42e953f8813284e11209823edab676 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 4 Apr 2024 18:02:25 +0200 +Subject: nouveau: fix function cast warning + +From: Arnd Bergmann + +[ 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 +Signed-off-by: Danilo Krummrich +Link: https://patchwork.freedesktop.org/patch/msgid/20240404160234.2923554-1-arnd@kernel.org +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..ea26207055c --- /dev/null +++ b/queue-5.10/octeontx2-af-fix-nix-sq-mode-and-bp-config.patch @@ -0,0 +1,59 @@ +From e10120d3b6250122ec39443111ce426c60fee6d5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 8 Apr 2024 12:06:43 +0530 +Subject: octeontx2-af: Fix NIX SQ mode and BP config + +From: Geetha sowjanya + +[ 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 +Link: https://lore.kernel.org/r/20240408063643.26288-1-gakula@marvell.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../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 + diff --git a/queue-5.10/series b/queue-5.10/series index e781fabc2ab..5bd9bf7abc3 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -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 index 00000000000..9de0b8539d1 --- /dev/null +++ b/queue-5.10/u64_stats-disable-preemption-on-32bit-up-smp-preempt.patch @@ -0,0 +1,164 @@ +From 34ec7b09c7f0abc2e742f68e5ce91cc53054406f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Signed-off-by: David S. Miller +Stable-dep-of: 38a15d0a50e0 ("u64_stats: fix u64_stats_init() for lockdep when used repeatedly in one file") +Signed-off-by: Sasha Levin +--- + 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 + + 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 index 00000000000..e34b450b8e6 --- /dev/null +++ b/queue-5.10/u64_stats-fix-u64_stats_init-for-lockdep-when-used-r.patch @@ -0,0 +1,56 @@ +From d126067245d71c1d4a831a86eedbc702a5c6480a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Simon Horman +Reviewed-by: Eric Dumazet +Link: https://lore.kernel.org/r/20240404075740.30682-1-petr@tesarici.cz +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..ebfe04ebf3f --- /dev/null +++ b/queue-5.10/u64_stats-streamline-the-implementation.patch @@ -0,0 +1,274 @@ +From 2253d0d81b05aa0961a0c4f8a1199b5626bb15d0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Aug 2022 18:41:31 +0200 +Subject: u64_stats: Streamline the implementation + +From: Thomas Gleixner + +[ 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 +Signed-off-by: Sebastian Andrzej Siewior +Signed-off-by: Thomas Gleixner +Acked-by: Peter Zijlstra (Intel) +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 +--- + 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 + + 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 index 00000000000..e3afa4d56cf --- /dev/null +++ b/queue-5.10/xsk-validate-user-input-for-xdp_-umem-completion-_fi.patch @@ -0,0 +1,176 @@ +From fb948fe60edd2f39910ed9e8f95fc99cf6934ed0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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: + + __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 + + +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 +Signed-off-by: Eric Dumazet +Cc: "Björn Töpel" +Cc: Magnus Karlsson +Cc: Maciej Fijalkowski +Cc: Jonathan Lemon +Acked-by: Daniel Borkmann +Link: https://lore.kernel.org/r/20240404202738.3634547-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + 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 + -- 2.47.2