From: Sasha Levin Date: Mon, 3 Aug 2026 20:46:32 +0000 (-0400) Subject: Fixes for all trees X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8de2c875deccecc6191ba1a7b7e4fc967eb831d5;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for all trees Signed-off-by: Sasha Levin --- diff --git a/queue-5.10/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch b/queue-5.10/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch new file mode 100644 index 0000000000..8d275df4b4 --- /dev/null +++ b/queue-5.10/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch @@ -0,0 +1,45 @@ +From 638ad3e9919dac6bbeab70501fb0dd6f0a9b1acd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Apr 2026 16:03:07 +0200 +Subject: HID: logitech-dj: fix wrong detection of bad DJ_SHORT output report + +From: Benjamin Tissoires + +[ Upstream commit 8b9a097eb2fc37b486afd81388c693bf3ab44466 ] + +commit b6a57912854e ("HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT +related user initiated OOB write") assumed that all HID devices attached +to the logitech-dj driver was having an output report of DJ_SHORT. + +However, on the receiver itself, we have 2 other HID device we attach +here: the mouse emulation and the keyboard emulation. For those devices +the value of rep is NULL and we are triggered a segfault here. + +This is doubly required because logitech-dj also handles non DJ devices +that might not have the DJ collection. + +Fixes: b6a57912854e ("HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated OOB write") +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index d3f63bac518ae..4bb324b73629e 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1715,7 +1715,8 @@ static int logi_dj_probe(struct hid_device *hdev, + output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; + rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; + +- if (rep->maxfield < 1 || rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1) { ++ if (rep && (rep->maxfield < 1 || ++ rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1)) { + hid_err(hdev, "Expected size of DJ short report is %d, but got %d", + DJREPORT_SHORT_LENGTH - 1, rep->field[0]->report_count); + return -EINVAL; +-- +2.53.0 + diff --git a/queue-5.10/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch b/queue-5.10/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch new file mode 100644 index 0000000000..92785aa127 --- /dev/null +++ b/queue-5.10/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch @@ -0,0 +1,56 @@ +From 8b3be89fa8e28f0dd9a954a319b9e31d610e6a39 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 14:36:44 +0000 +Subject: HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated + OOB write + +From: Lee Jones + +[ Upstream commit b6a57912854e7ea36f3b270032661140cc4209cd ] + +logi_dj_recv_send_report() assumes that all incoming REPORT_ID_DJ_SHORT +reports are 14 Bytes (DJREPORT_SHORT_LENGTH - 1) long. It uses that +assumption to load the associated field's 'value' array with 14 Bytes of +data. However, if a malicious user only sends say 1 Byte of data, +'report_count' will be 1 and only 1 Byte of memory will be allocated to +the 'value' Byte array. When we come to populate 'value[1-13]' we will +experience an OOB write. + +Signed-off-by: Lee Jones +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 91804ebabc69a..d3f63bac518ae 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1669,6 +1669,7 @@ static int logi_dj_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { + struct hid_report_enum *input_report_enum; ++ struct hid_report_enum *output_report_enum; + struct hid_report *rep; + struct dj_receiver_dev *djrcv_dev; + struct usb_interface *intf; +@@ -1711,6 +1712,15 @@ static int logi_dj_probe(struct hid_device *hdev, + } + } + ++ output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; ++ rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; ++ ++ if (rep->maxfield < 1 || rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1) { ++ hid_err(hdev, "Expected size of DJ short report is %d, but got %d", ++ DJREPORT_SHORT_LENGTH - 1, rep->field[0]->report_count); ++ return -EINVAL; ++ } ++ + input_report_enum = &hdev->report_enum[HID_INPUT_REPORT]; + + /* no input reports, bail out */ +-- +2.53.0 + diff --git a/queue-5.10/hid-logitech-dj-standardise-hid_report_enum-variable.patch b/queue-5.10/hid-logitech-dj-standardise-hid_report_enum-variable.patch new file mode 100644 index 0000000000..38a81e40bb --- /dev/null +++ b/queue-5.10/hid-logitech-dj-standardise-hid_report_enum-variable.patch @@ -0,0 +1,78 @@ +From 97ddf36d9465ff2795c739f9585e142254f7ce6b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 14:36:43 +0000 +Subject: HID: logitech-dj: Standardise hid_report_enum variable nomenclature + +From: Lee Jones + +[ Upstream commit a940aee176437046598dfc786b719bd96db3c74c ] + +Since we will need to differentiate between the two report_enum types +soon, let's unify the naming conventions now to save confusion and/or +unnecessary/unrelated changes in upcoming commits. + +{input,output}_report_enum is used in other places to let's conform. + +Signed-off-by: Lee Jones +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index bd31315fdaf5e..91804ebabc69a 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1668,7 +1668,7 @@ static int logi_dj_raw_event(struct hid_device *hdev, + static int logi_dj_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +- struct hid_report_enum *rep_enum; ++ struct hid_report_enum *input_report_enum; + struct hid_report *rep; + struct dj_receiver_dev *djrcv_dev; + struct usb_interface *intf; +@@ -1711,10 +1711,10 @@ static int logi_dj_probe(struct hid_device *hdev, + } + } + +- rep_enum = &hdev->report_enum[HID_INPUT_REPORT]; ++ input_report_enum = &hdev->report_enum[HID_INPUT_REPORT]; + + /* no input reports, bail out */ +- if (list_empty(&rep_enum->report_list)) ++ if (list_empty(&input_report_enum->report_list)) + return -ENODEV; + + /* +@@ -1722,7 +1722,7 @@ static int logi_dj_probe(struct hid_device *hdev, + * Note: we should theoretically check for HID++ and DJ + * collections, but this will do. + */ +- list_for_each_entry(rep, &rep_enum->report_list, list) { ++ list_for_each_entry(rep, &input_report_enum->report_list, list) { + if (rep->application == 0xff000001) + has_hidpp = true; + } +@@ -1735,7 +1735,7 @@ static int logi_dj_probe(struct hid_device *hdev, + return -ENODEV; + + /* get the current application attached to the node */ +- rep = list_first_entry(&rep_enum->report_list, struct hid_report, list); ++ rep = list_first_entry(&input_report_enum->report_list, struct hid_report, list); + djrcv_dev = dj_get_receiver_dev(hdev, id->driver_data, + rep->application, has_hidpp); + if (!djrcv_dev) { +@@ -1743,7 +1743,7 @@ static int logi_dj_probe(struct hid_device *hdev, + return -ENOMEM; + } + +- if (!rep_enum->numbered) ++ if (!input_report_enum->numbered) + djrcv_dev->unnumbered_application = rep->application; + + /* Starts the usb device and connects to upper interfaces hiddev and +-- +2.53.0 + diff --git a/queue-5.10/net-qrtr-ns-limit-the-maximum-server-registration-pe.patch b/queue-5.10/net-qrtr-ns-limit-the-maximum-server-registration-pe.patch new file mode 100644 index 0000000000..dec975ca2f --- /dev/null +++ b/queue-5.10/net-qrtr-ns-limit-the-maximum-server-registration-pe.patch @@ -0,0 +1,111 @@ +From 7bd488e577cc406fda56d8a7511ab7d9c687941c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Aug 2026 22:21:06 +0200 +Subject: net: qrtr: ns: Limit the maximum server registration per node + +From: Manivannan Sadhasivam + +[ Upstream commit d5ee2ff98322337951c56398e79d51815acbf955 ] + +Current code does no bound checking on the number of servers added per +node. A malicious client can flood NEW_SERVER messages and exhaust memory. + +Fix this issue by limiting the maximum number of server registrations to +256 per node. If the NEW_SERVER message is received for an old port, then +don't restrict it as it will get replaced. While at it, also rate limit +the error messages in the failure path of qrtr_ns_worker(). + +Note that the limit of 256 is chosen based on the current platform +requirements. If requirement changes in the future, this limit can be +increased. + +Cc: stable@vger.kernel.org +Fixes: 0c2204a4ad71 ("net: qrtr: Migrate nameservice to kernel from userspace") +Reported-by: Yiming Qian +Reviewed-by: Simon Horman +Signed-off-by: Manivannan Sadhasivam +Link: https://patch.msgid.link/20260409-qrtr-fix-v3-1-00a8a5ff2b51@oss.qualcomm.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Youssef Samir +Signed-off-by: Sasha Levin +--- + net/qrtr/ns.c | 26 ++++++++++++++++---------- + 1 file changed, 16 insertions(+), 10 deletions(-) + +diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c +index 36a7a9ad6b503..440e68601e251 100644 +--- a/net/qrtr/ns.c ++++ b/net/qrtr/ns.c +@@ -68,13 +68,9 @@ struct qrtr_server { + struct qrtr_node { + unsigned int id; + struct xarray servers; ++ u32 server_count; + }; + +-/* Max lookup limit is chosen based on the current platform requirements. If the +- * requirement changes in the future, this value can be increased. +- */ +-#define QRTR_NS_MAX_LOOKUPS 64 +- + /* Max nodes, server, lookup limits are chosen based on the current platform + * requirements. If the requirement changes in the future, these values can be + * increased. +@@ -249,6 +245,17 @@ static struct qrtr_server *server_add(unsigned int service, + if (!service || !port) + return NULL; + ++ node = node_get(node_id); ++ if (!node) ++ return NULL; ++ ++ /* Make sure the new servers per port are capped at the maximum value */ ++ old = xa_load(&node->servers, port); ++ if (!old && node->server_count >= QRTR_NS_MAX_SERVERS) { ++ pr_err_ratelimited("QRTR client node %u exceeds max server limit!\n", node_id); ++ return NULL; ++ } ++ + srv = kzalloc(sizeof(*srv), GFP_KERNEL); + if (!srv) + return NULL; +@@ -258,10 +265,6 @@ static struct qrtr_server *server_add(unsigned int service, + srv->node = node_id; + srv->port = port; + +- node = node_get(node_id); +- if (!node) +- goto err; +- + /* Delete the old server on the same port */ + old = xa_store(&node->servers, port, srv, GFP_KERNEL); + if (old) { +@@ -272,6 +275,8 @@ static struct qrtr_server *server_add(unsigned int service, + } else { + kfree(old); + } ++ } else { ++ node->server_count++; + } + + trace_qrtr_ns_server_add(srv->service, srv->instance, +@@ -312,6 +317,7 @@ static int server_del(struct qrtr_node *node, unsigned int port, bool bcast) + } + + kfree(srv); ++ node->server_count--; + + return 0; + } +@@ -716,7 +722,7 @@ static void qrtr_ns_worker(struct work_struct *work) + } + + if (ret < 0) +- pr_err("failed while handling packet from %d:%d", ++ pr_err_ratelimited("failed while handling packet from %d:%d", + sq.sq_node, sq.sq_port); + } + +-- +2.53.0 + diff --git a/queue-5.10/net-qrtr-ns-raise-node-count-limit-to-512.patch b/queue-5.10/net-qrtr-ns-raise-node-count-limit-to-512.patch new file mode 100644 index 0000000000..779a1bb198 --- /dev/null +++ b/queue-5.10/net-qrtr-ns-raise-node-count-limit-to-512.patch @@ -0,0 +1,56 @@ +From e593be74e085cf6e386701414f00ec5e3df14e5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Aug 2026 23:33:52 +0200 +Subject: net: qrtr: ns: Raise node count limit to 512 + +From: Youssef Samir + +[ Upstream commit ff194cffd586cbd4cc49eccb002c65f2a902a277 ] + +The current node limit of 64 breaks the functionality for a number of AI200 +deployments that have up to 384 nodes. Raise the limit to 512. + +Also, the backport of commit 27d5e84e810b ("net: qrtr: ns: Limit the total +number of nodes") to 5.10, 5.15 and 6.1 dropped the node_count-- hunk in +ctrl_cmd_bye(). Add it back. + +Fixes: 27d5e84e810b ("net: qrtr: ns: Limit the total number of nodes") +Cc: stable@vger.kernel.org +Signed-off-by: Youssef Samir +Link: https://patch.msgid.link/20260713145901.212396-1-youssef.abdulrahman@oss.qualcomm.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Youssef Samir +Signed-off-by: Sasha Levin +--- + net/qrtr/ns.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c +index 440e68601e251..3ebb5d39e153f 100644 +--- a/net/qrtr/ns.c ++++ b/net/qrtr/ns.c +@@ -75,11 +75,11 @@ struct qrtr_node { + * requirements. If the requirement changes in the future, these values can be + * increased. + */ +-#define QRTR_NS_MAX_NODES 64 ++#define QRTR_NS_MAX_NODES 512 + #define QRTR_NS_MAX_SERVERS 256 + #define QRTR_NS_MAX_LOOKUPS 64 + +-static u8 node_count; ++static u16 node_count; + + static struct qrtr_node *node_get(unsigned int node_id) + { +@@ -412,6 +412,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) + delete_node: + xa_erase(&nodes, from->sq_node); + kfree(node); ++ node_count--; + + return ret; + } +-- +2.53.0 + diff --git a/queue-5.10/series b/queue-5.10/series index e2e855f699..f7bfe5c1ca 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -194,3 +194,8 @@ net-bridge-vlan-fix-global-vlan-option-range-dumping.patch net-mpls-initialize-rtm_tos-in-mpls_getroute.patch media-uvcvideo-implement-dual-stream-quirk-to-fix-lo.patch media-uvcvideo-fix-sequence-number-when-no-eof.patch +hid-logitech-dj-standardise-hid_report_enum-variable.patch +hid-logitech-dj-prevent-report_id_dj_short-related-u.patch +hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch +net-qrtr-ns-limit-the-maximum-server-registration-pe.patch +net-qrtr-ns-raise-node-count-limit-to-512.patch diff --git a/queue-5.15/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch b/queue-5.15/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch new file mode 100644 index 0000000000..5b63d08aef --- /dev/null +++ b/queue-5.15/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch @@ -0,0 +1,45 @@ +From 3b1cdda168ef4a580461eb7eb77d0879372cac0e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Apr 2026 16:03:07 +0200 +Subject: HID: logitech-dj: fix wrong detection of bad DJ_SHORT output report + +From: Benjamin Tissoires + +[ Upstream commit 8b9a097eb2fc37b486afd81388c693bf3ab44466 ] + +commit b6a57912854e ("HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT +related user initiated OOB write") assumed that all HID devices attached +to the logitech-dj driver was having an output report of DJ_SHORT. + +However, on the receiver itself, we have 2 other HID device we attach +here: the mouse emulation and the keyboard emulation. For those devices +the value of rep is NULL and we are triggered a segfault here. + +This is doubly required because logitech-dj also handles non DJ devices +that might not have the DJ collection. + +Fixes: b6a57912854e ("HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated OOB write") +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 591a8f56ad2e9..8b11aade46c4d 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1797,7 +1797,8 @@ static int logi_dj_probe(struct hid_device *hdev, + output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; + rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; + +- if (rep->maxfield < 1 || rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1) { ++ if (rep && (rep->maxfield < 1 || ++ rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1)) { + hid_err(hdev, "Expected size of DJ short report is %d, but got %d", + DJREPORT_SHORT_LENGTH - 1, rep->field[0]->report_count); + return -EINVAL; +-- +2.53.0 + diff --git a/queue-5.15/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch b/queue-5.15/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch new file mode 100644 index 0000000000..06f08ffb50 --- /dev/null +++ b/queue-5.15/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch @@ -0,0 +1,56 @@ +From e110716b1dcc4e4cf089643b504caf30a9c1df4f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 14:36:44 +0000 +Subject: HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated + OOB write + +From: Lee Jones + +[ Upstream commit b6a57912854e7ea36f3b270032661140cc4209cd ] + +logi_dj_recv_send_report() assumes that all incoming REPORT_ID_DJ_SHORT +reports are 14 Bytes (DJREPORT_SHORT_LENGTH - 1) long. It uses that +assumption to load the associated field's 'value' array with 14 Bytes of +data. However, if a malicious user only sends say 1 Byte of data, +'report_count' will be 1 and only 1 Byte of memory will be allocated to +the 'value' Byte array. When we come to populate 'value[1-13]' we will +experience an OOB write. + +Signed-off-by: Lee Jones +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 97b679e4cdbe3..591a8f56ad2e9 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1750,6 +1750,7 @@ static int logi_dj_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { + struct hid_report_enum *input_report_enum; ++ struct hid_report_enum *output_report_enum; + struct hid_report *rep; + struct dj_receiver_dev *djrcv_dev; + struct usb_interface *intf; +@@ -1793,6 +1794,15 @@ static int logi_dj_probe(struct hid_device *hdev, + } + } + ++ output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; ++ rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; ++ ++ if (rep->maxfield < 1 || rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1) { ++ hid_err(hdev, "Expected size of DJ short report is %d, but got %d", ++ DJREPORT_SHORT_LENGTH - 1, rep->field[0]->report_count); ++ return -EINVAL; ++ } ++ + input_report_enum = &hdev->report_enum[HID_INPUT_REPORT]; + + /* no input reports, bail out */ +-- +2.53.0 + diff --git a/queue-5.15/hid-logitech-dj-standardise-hid_report_enum-variable.patch b/queue-5.15/hid-logitech-dj-standardise-hid_report_enum-variable.patch new file mode 100644 index 0000000000..067eaf41cc --- /dev/null +++ b/queue-5.15/hid-logitech-dj-standardise-hid_report_enum-variable.patch @@ -0,0 +1,78 @@ +From 9a80fd84857e2b72d13144bddb2189bbcb7426b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 14:36:43 +0000 +Subject: HID: logitech-dj: Standardise hid_report_enum variable nomenclature + +From: Lee Jones + +[ Upstream commit a940aee176437046598dfc786b719bd96db3c74c ] + +Since we will need to differentiate between the two report_enum types +soon, let's unify the naming conventions now to save confusion and/or +unnecessary/unrelated changes in upcoming commits. + +{input,output}_report_enum is used in other places to let's conform. + +Signed-off-by: Lee Jones +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index be9fbf14f1371..97b679e4cdbe3 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1749,7 +1749,7 @@ static int logi_dj_raw_event(struct hid_device *hdev, + static int logi_dj_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +- struct hid_report_enum *rep_enum; ++ struct hid_report_enum *input_report_enum; + struct hid_report *rep; + struct dj_receiver_dev *djrcv_dev; + struct usb_interface *intf; +@@ -1793,10 +1793,10 @@ static int logi_dj_probe(struct hid_device *hdev, + } + } + +- rep_enum = &hdev->report_enum[HID_INPUT_REPORT]; ++ input_report_enum = &hdev->report_enum[HID_INPUT_REPORT]; + + /* no input reports, bail out */ +- if (list_empty(&rep_enum->report_list)) ++ if (list_empty(&input_report_enum->report_list)) + return -ENODEV; + + /* +@@ -1804,7 +1804,7 @@ static int logi_dj_probe(struct hid_device *hdev, + * Note: we should theoretically check for HID++ and DJ + * collections, but this will do. + */ +- list_for_each_entry(rep, &rep_enum->report_list, list) { ++ list_for_each_entry(rep, &input_report_enum->report_list, list) { + if (rep->application == 0xff000001) + has_hidpp = true; + } +@@ -1817,7 +1817,7 @@ static int logi_dj_probe(struct hid_device *hdev, + return -ENODEV; + + /* get the current application attached to the node */ +- rep = list_first_entry(&rep_enum->report_list, struct hid_report, list); ++ rep = list_first_entry(&input_report_enum->report_list, struct hid_report, list); + djrcv_dev = dj_get_receiver_dev(hdev, id->driver_data, + rep->application, has_hidpp); + if (!djrcv_dev) { +@@ -1825,7 +1825,7 @@ static int logi_dj_probe(struct hid_device *hdev, + return -ENOMEM; + } + +- if (!rep_enum->numbered) ++ if (!input_report_enum->numbered) + djrcv_dev->unnumbered_application = rep->application; + + /* Starts the usb device and connects to upper interfaces hiddev and +-- +2.53.0 + diff --git a/queue-5.15/net-qrtr-ns-limit-the-maximum-server-registration-pe.patch b/queue-5.15/net-qrtr-ns-limit-the-maximum-server-registration-pe.patch new file mode 100644 index 0000000000..48a61cc2c4 --- /dev/null +++ b/queue-5.15/net-qrtr-ns-limit-the-maximum-server-registration-pe.patch @@ -0,0 +1,111 @@ +From 7b867e2f3b19e46b2693a9cb5680b97ab42748a2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Aug 2026 22:20:04 +0200 +Subject: net: qrtr: ns: Limit the maximum server registration per node + +From: Manivannan Sadhasivam + +[ Upstream commit d5ee2ff98322337951c56398e79d51815acbf955 ] + +Current code does no bound checking on the number of servers added per +node. A malicious client can flood NEW_SERVER messages and exhaust memory. + +Fix this issue by limiting the maximum number of server registrations to +256 per node. If the NEW_SERVER message is received for an old port, then +don't restrict it as it will get replaced. While at it, also rate limit +the error messages in the failure path of qrtr_ns_worker(). + +Note that the limit of 256 is chosen based on the current platform +requirements. If requirement changes in the future, this limit can be +increased. + +Cc: stable@vger.kernel.org +Fixes: 0c2204a4ad71 ("net: qrtr: Migrate nameservice to kernel from userspace") +Reported-by: Yiming Qian +Reviewed-by: Simon Horman +Signed-off-by: Manivannan Sadhasivam +Link: https://patch.msgid.link/20260409-qrtr-fix-v3-1-00a8a5ff2b51@oss.qualcomm.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Youssef Samir +Signed-off-by: Sasha Levin +--- + net/qrtr/ns.c | 26 ++++++++++++++++---------- + 1 file changed, 16 insertions(+), 10 deletions(-) + +diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c +index 559aad0e36215..91e43b0fd5669 100644 +--- a/net/qrtr/ns.c ++++ b/net/qrtr/ns.c +@@ -68,13 +68,9 @@ struct qrtr_server { + struct qrtr_node { + unsigned int id; + struct xarray servers; ++ u32 server_count; + }; + +-/* Max lookup limit is chosen based on the current platform requirements. If the +- * requirement changes in the future, this value can be increased. +- */ +-#define QRTR_NS_MAX_LOOKUPS 64 +- + /* Max nodes, server, lookup limits are chosen based on the current platform + * requirements. If the requirement changes in the future, these values can be + * increased. +@@ -249,6 +245,17 @@ static struct qrtr_server *server_add(unsigned int service, + if (!service || !port) + return NULL; + ++ node = node_get(node_id); ++ if (!node) ++ return NULL; ++ ++ /* Make sure the new servers per port are capped at the maximum value */ ++ old = xa_load(&node->servers, port); ++ if (!old && node->server_count >= QRTR_NS_MAX_SERVERS) { ++ pr_err_ratelimited("QRTR client node %u exceeds max server limit!\n", node_id); ++ return NULL; ++ } ++ + srv = kzalloc(sizeof(*srv), GFP_KERNEL); + if (!srv) + return NULL; +@@ -258,10 +265,6 @@ static struct qrtr_server *server_add(unsigned int service, + srv->node = node_id; + srv->port = port; + +- node = node_get(node_id); +- if (!node) +- goto err; +- + /* Delete the old server on the same port */ + old = xa_store(&node->servers, port, srv, GFP_KERNEL); + if (old) { +@@ -272,6 +275,8 @@ static struct qrtr_server *server_add(unsigned int service, + } else { + kfree(old); + } ++ } else { ++ node->server_count++; + } + + trace_qrtr_ns_server_add(srv->service, srv->instance, +@@ -312,6 +317,7 @@ static int server_del(struct qrtr_node *node, unsigned int port, bool bcast) + } + + kfree(srv); ++ node->server_count--; + + return 0; + } +@@ -708,7 +714,7 @@ static void qrtr_ns_worker(struct work_struct *work) + } + + if (ret < 0) +- pr_err("failed while handling packet from %d:%d", ++ pr_err_ratelimited("failed while handling packet from %d:%d", + sq.sq_node, sq.sq_port); + } + +-- +2.53.0 + diff --git a/queue-5.15/net-qrtr-ns-raise-node-count-limit-to-512.patch b/queue-5.15/net-qrtr-ns-raise-node-count-limit-to-512.patch new file mode 100644 index 0000000000..eae02ba8a0 --- /dev/null +++ b/queue-5.15/net-qrtr-ns-raise-node-count-limit-to-512.patch @@ -0,0 +1,56 @@ +From a96d1069f1f40b2a0e14a2b432cfc8af9cf26dad Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Aug 2026 23:33:52 +0200 +Subject: net: qrtr: ns: Raise node count limit to 512 + +From: Youssef Samir + +[ Upstream commit ff194cffd586cbd4cc49eccb002c65f2a902a277 ] + +The current node limit of 64 breaks the functionality for a number of AI200 +deployments that have up to 384 nodes. Raise the limit to 512. + +Also, the backport of commit 27d5e84e810b ("net: qrtr: ns: Limit the total +number of nodes") to 5.10, 5.15 and 6.1 dropped the node_count-- hunk in +ctrl_cmd_bye(). Add it back. + +Fixes: 27d5e84e810b ("net: qrtr: ns: Limit the total number of nodes") +Cc: stable@vger.kernel.org +Signed-off-by: Youssef Samir +Link: https://patch.msgid.link/20260713145901.212396-1-youssef.abdulrahman@oss.qualcomm.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Youssef Samir +Signed-off-by: Sasha Levin +--- + net/qrtr/ns.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c +index 91e43b0fd5669..5220529a4c62d 100644 +--- a/net/qrtr/ns.c ++++ b/net/qrtr/ns.c +@@ -75,11 +75,11 @@ struct qrtr_node { + * requirements. If the requirement changes in the future, these values can be + * increased. + */ +-#define QRTR_NS_MAX_NODES 64 ++#define QRTR_NS_MAX_NODES 512 + #define QRTR_NS_MAX_SERVERS 256 + #define QRTR_NS_MAX_LOOKUPS 64 + +-static u8 node_count; ++static u16 node_count; + + static struct qrtr_node *node_get(unsigned int node_id) + { +@@ -412,6 +412,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) + delete_node: + xa_erase(&nodes, from->sq_node); + kfree(node); ++ node_count--; + + return ret; + } +-- +2.53.0 + diff --git a/queue-5.15/series b/queue-5.15/series index 868b3b4ec3..825d3fff9e 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -237,3 +237,8 @@ net-mpls-initialize-rtm_tos-in-mpls_getroute.patch media-uvcvideo-implement-dual-stream-quirk-to-fix-lo.patch media-uvcvideo-fix-sequence-number-when-no-eof.patch gve-fix-rx-queue-stall-on-alloc-failure.patch +hid-logitech-dj-standardise-hid_report_enum-variable.patch +hid-logitech-dj-prevent-report_id_dj_short-related-u.patch +hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch +net-qrtr-ns-limit-the-maximum-server-registration-pe.patch +net-qrtr-ns-raise-node-count-limit-to-512.patch diff --git a/queue-6.1/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch b/queue-6.1/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch new file mode 100644 index 0000000000..6006a10354 --- /dev/null +++ b/queue-6.1/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch @@ -0,0 +1,45 @@ +From 7ad2b475c1176699f4742e835bb9e88f5b53dc28 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Apr 2026 16:03:07 +0200 +Subject: HID: logitech-dj: fix wrong detection of bad DJ_SHORT output report + +From: Benjamin Tissoires + +[ Upstream commit 8b9a097eb2fc37b486afd81388c693bf3ab44466 ] + +commit b6a57912854e ("HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT +related user initiated OOB write") assumed that all HID devices attached +to the logitech-dj driver was having an output report of DJ_SHORT. + +However, on the receiver itself, we have 2 other HID device we attach +here: the mouse emulation and the keyboard emulation. For those devices +the value of rep is NULL and we are triggered a segfault here. + +This is doubly required because logitech-dj also handles non DJ devices +that might not have the DJ collection. + +Fixes: b6a57912854e ("HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated OOB write") +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 591a8f56ad2e9..8b11aade46c4d 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1797,7 +1797,8 @@ static int logi_dj_probe(struct hid_device *hdev, + output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; + rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; + +- if (rep->maxfield < 1 || rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1) { ++ if (rep && (rep->maxfield < 1 || ++ rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1)) { + hid_err(hdev, "Expected size of DJ short report is %d, but got %d", + DJREPORT_SHORT_LENGTH - 1, rep->field[0]->report_count); + return -EINVAL; +-- +2.53.0 + diff --git a/queue-6.1/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch b/queue-6.1/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch new file mode 100644 index 0000000000..82ce2dce23 --- /dev/null +++ b/queue-6.1/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch @@ -0,0 +1,56 @@ +From c5ef7c3f3e92ac5e188e5be6d9449a668984ced9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 14:36:44 +0000 +Subject: HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated + OOB write + +From: Lee Jones + +[ Upstream commit b6a57912854e7ea36f3b270032661140cc4209cd ] + +logi_dj_recv_send_report() assumes that all incoming REPORT_ID_DJ_SHORT +reports are 14 Bytes (DJREPORT_SHORT_LENGTH - 1) long. It uses that +assumption to load the associated field's 'value' array with 14 Bytes of +data. However, if a malicious user only sends say 1 Byte of data, +'report_count' will be 1 and only 1 Byte of memory will be allocated to +the 'value' Byte array. When we come to populate 'value[1-13]' we will +experience an OOB write. + +Signed-off-by: Lee Jones +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 97b679e4cdbe3..591a8f56ad2e9 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1750,6 +1750,7 @@ static int logi_dj_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { + struct hid_report_enum *input_report_enum; ++ struct hid_report_enum *output_report_enum; + struct hid_report *rep; + struct dj_receiver_dev *djrcv_dev; + struct usb_interface *intf; +@@ -1793,6 +1794,15 @@ static int logi_dj_probe(struct hid_device *hdev, + } + } + ++ output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; ++ rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; ++ ++ if (rep->maxfield < 1 || rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1) { ++ hid_err(hdev, "Expected size of DJ short report is %d, but got %d", ++ DJREPORT_SHORT_LENGTH - 1, rep->field[0]->report_count); ++ return -EINVAL; ++ } ++ + input_report_enum = &hdev->report_enum[HID_INPUT_REPORT]; + + /* no input reports, bail out */ +-- +2.53.0 + diff --git a/queue-6.1/hid-logitech-dj-standardise-hid_report_enum-variable.patch b/queue-6.1/hid-logitech-dj-standardise-hid_report_enum-variable.patch new file mode 100644 index 0000000000..bed871c87d --- /dev/null +++ b/queue-6.1/hid-logitech-dj-standardise-hid_report_enum-variable.patch @@ -0,0 +1,78 @@ +From 4ee36d38b2011b3b1203262f77fda766df1b429c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 14:36:43 +0000 +Subject: HID: logitech-dj: Standardise hid_report_enum variable nomenclature + +From: Lee Jones + +[ Upstream commit a940aee176437046598dfc786b719bd96db3c74c ] + +Since we will need to differentiate between the two report_enum types +soon, let's unify the naming conventions now to save confusion and/or +unnecessary/unrelated changes in upcoming commits. + +{input,output}_report_enum is used in other places to let's conform. + +Signed-off-by: Lee Jones +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index be9fbf14f1371..97b679e4cdbe3 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1749,7 +1749,7 @@ static int logi_dj_raw_event(struct hid_device *hdev, + static int logi_dj_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +- struct hid_report_enum *rep_enum; ++ struct hid_report_enum *input_report_enum; + struct hid_report *rep; + struct dj_receiver_dev *djrcv_dev; + struct usb_interface *intf; +@@ -1793,10 +1793,10 @@ static int logi_dj_probe(struct hid_device *hdev, + } + } + +- rep_enum = &hdev->report_enum[HID_INPUT_REPORT]; ++ input_report_enum = &hdev->report_enum[HID_INPUT_REPORT]; + + /* no input reports, bail out */ +- if (list_empty(&rep_enum->report_list)) ++ if (list_empty(&input_report_enum->report_list)) + return -ENODEV; + + /* +@@ -1804,7 +1804,7 @@ static int logi_dj_probe(struct hid_device *hdev, + * Note: we should theoretically check for HID++ and DJ + * collections, but this will do. + */ +- list_for_each_entry(rep, &rep_enum->report_list, list) { ++ list_for_each_entry(rep, &input_report_enum->report_list, list) { + if (rep->application == 0xff000001) + has_hidpp = true; + } +@@ -1817,7 +1817,7 @@ static int logi_dj_probe(struct hid_device *hdev, + return -ENODEV; + + /* get the current application attached to the node */ +- rep = list_first_entry(&rep_enum->report_list, struct hid_report, list); ++ rep = list_first_entry(&input_report_enum->report_list, struct hid_report, list); + djrcv_dev = dj_get_receiver_dev(hdev, id->driver_data, + rep->application, has_hidpp); + if (!djrcv_dev) { +@@ -1825,7 +1825,7 @@ static int logi_dj_probe(struct hid_device *hdev, + return -ENOMEM; + } + +- if (!rep_enum->numbered) ++ if (!input_report_enum->numbered) + djrcv_dev->unnumbered_application = rep->application; + + /* Starts the usb device and connects to upper interfaces hiddev and +-- +2.53.0 + diff --git a/queue-6.1/net-qrtr-ns-limit-the-maximum-server-registration-pe.patch b/queue-6.1/net-qrtr-ns-limit-the-maximum-server-registration-pe.patch new file mode 100644 index 0000000000..1d37253c96 --- /dev/null +++ b/queue-6.1/net-qrtr-ns-limit-the-maximum-server-registration-pe.patch @@ -0,0 +1,111 @@ +From 5aa16a1d25c6280c0680a3948be2072cda1bb8b1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Aug 2026 22:18:25 +0200 +Subject: net: qrtr: ns: Limit the maximum server registration per node + +From: Manivannan Sadhasivam + +[ Upstream commit d5ee2ff98322337951c56398e79d51815acbf955 ] + +Current code does no bound checking on the number of servers added per +node. A malicious client can flood NEW_SERVER messages and exhaust memory. + +Fix this issue by limiting the maximum number of server registrations to +256 per node. If the NEW_SERVER message is received for an old port, then +don't restrict it as it will get replaced. While at it, also rate limit +the error messages in the failure path of qrtr_ns_worker(). + +Note that the limit of 256 is chosen based on the current platform +requirements. If requirement changes in the future, this limit can be +increased. + +Cc: stable@vger.kernel.org +Fixes: 0c2204a4ad71 ("net: qrtr: Migrate nameservice to kernel from userspace") +Reported-by: Yiming Qian +Reviewed-by: Simon Horman +Signed-off-by: Manivannan Sadhasivam +Link: https://patch.msgid.link/20260409-qrtr-fix-v3-1-00a8a5ff2b51@oss.qualcomm.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Youssef Samir +Signed-off-by: Sasha Levin +--- + net/qrtr/ns.c | 26 ++++++++++++++++---------- + 1 file changed, 16 insertions(+), 10 deletions(-) + +diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c +index 559aad0e36215..91e43b0fd5669 100644 +--- a/net/qrtr/ns.c ++++ b/net/qrtr/ns.c +@@ -68,13 +68,9 @@ struct qrtr_server { + struct qrtr_node { + unsigned int id; + struct xarray servers; ++ u32 server_count; + }; + +-/* Max lookup limit is chosen based on the current platform requirements. If the +- * requirement changes in the future, this value can be increased. +- */ +-#define QRTR_NS_MAX_LOOKUPS 64 +- + /* Max nodes, server, lookup limits are chosen based on the current platform + * requirements. If the requirement changes in the future, these values can be + * increased. +@@ -249,6 +245,17 @@ static struct qrtr_server *server_add(unsigned int service, + if (!service || !port) + return NULL; + ++ node = node_get(node_id); ++ if (!node) ++ return NULL; ++ ++ /* Make sure the new servers per port are capped at the maximum value */ ++ old = xa_load(&node->servers, port); ++ if (!old && node->server_count >= QRTR_NS_MAX_SERVERS) { ++ pr_err_ratelimited("QRTR client node %u exceeds max server limit!\n", node_id); ++ return NULL; ++ } ++ + srv = kzalloc(sizeof(*srv), GFP_KERNEL); + if (!srv) + return NULL; +@@ -258,10 +265,6 @@ static struct qrtr_server *server_add(unsigned int service, + srv->node = node_id; + srv->port = port; + +- node = node_get(node_id); +- if (!node) +- goto err; +- + /* Delete the old server on the same port */ + old = xa_store(&node->servers, port, srv, GFP_KERNEL); + if (old) { +@@ -272,6 +275,8 @@ static struct qrtr_server *server_add(unsigned int service, + } else { + kfree(old); + } ++ } else { ++ node->server_count++; + } + + trace_qrtr_ns_server_add(srv->service, srv->instance, +@@ -312,6 +317,7 @@ static int server_del(struct qrtr_node *node, unsigned int port, bool bcast) + } + + kfree(srv); ++ node->server_count--; + + return 0; + } +@@ -708,7 +714,7 @@ static void qrtr_ns_worker(struct work_struct *work) + } + + if (ret < 0) +- pr_err("failed while handling packet from %d:%d", ++ pr_err_ratelimited("failed while handling packet from %d:%d", + sq.sq_node, sq.sq_port); + } + +-- +2.53.0 + diff --git a/queue-6.1/net-qrtr-ns-raise-node-count-limit-to-512.patch b/queue-6.1/net-qrtr-ns-raise-node-count-limit-to-512.patch new file mode 100644 index 0000000000..adbbb1e4e4 --- /dev/null +++ b/queue-6.1/net-qrtr-ns-raise-node-count-limit-to-512.patch @@ -0,0 +1,56 @@ +From 0b83a435d8842d551f7b3df0757bd59c153561b4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 2 Aug 2026 23:33:52 +0200 +Subject: net: qrtr: ns: Raise node count limit to 512 + +From: Youssef Samir + +[ Upstream commit ff194cffd586cbd4cc49eccb002c65f2a902a277 ] + +The current node limit of 64 breaks the functionality for a number of AI200 +deployments that have up to 384 nodes. Raise the limit to 512. + +Also, the backport of commit 27d5e84e810b ("net: qrtr: ns: Limit the total +number of nodes") to 5.10, 5.15 and 6.1 dropped the node_count-- hunk in +ctrl_cmd_bye(). Add it back. + +Fixes: 27d5e84e810b ("net: qrtr: ns: Limit the total number of nodes") +Cc: stable@vger.kernel.org +Signed-off-by: Youssef Samir +Link: https://patch.msgid.link/20260713145901.212396-1-youssef.abdulrahman@oss.qualcomm.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Youssef Samir +Signed-off-by: Sasha Levin +--- + net/qrtr/ns.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/qrtr/ns.c b/net/qrtr/ns.c +index 91e43b0fd5669..5220529a4c62d 100644 +--- a/net/qrtr/ns.c ++++ b/net/qrtr/ns.c +@@ -75,11 +75,11 @@ struct qrtr_node { + * requirements. If the requirement changes in the future, these values can be + * increased. + */ +-#define QRTR_NS_MAX_NODES 64 ++#define QRTR_NS_MAX_NODES 512 + #define QRTR_NS_MAX_SERVERS 256 + #define QRTR_NS_MAX_LOOKUPS 64 + +-static u8 node_count; ++static u16 node_count; + + static struct qrtr_node *node_get(unsigned int node_id) + { +@@ -412,6 +412,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) + delete_node: + xa_erase(&nodes, from->sq_node); + kfree(node); ++ node_count--; + + return ret; + } +-- +2.53.0 + diff --git a/queue-6.1/series b/queue-6.1/series index 94f646b982..8124209bec 100644 --- a/queue-6.1/series +++ b/queue-6.1/series @@ -301,3 +301,8 @@ net-mpls-initialize-rtm_tos-in-mpls_getroute.patch media-uvcvideo-implement-dual-stream-quirk-to-fix-lo.patch media-uvcvideo-fix-sequence-number-when-no-eof.patch gve-fix-rx-queue-stall-on-alloc-failure.patch +hid-logitech-dj-standardise-hid_report_enum-variable.patch +hid-logitech-dj-prevent-report_id_dj_short-related-u.patch +hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch +net-qrtr-ns-limit-the-maximum-server-registration-pe.patch +net-qrtr-ns-raise-node-count-limit-to-512.patch diff --git a/queue-6.12/bpf-reset-register-bounds-before-narrowing-retval-ra.patch b/queue-6.12/bpf-reset-register-bounds-before-narrowing-retval-ra.patch new file mode 100644 index 0000000000..c31f86bb74 --- /dev/null +++ b/queue-6.12/bpf-reset-register-bounds-before-narrowing-retval-ra.patch @@ -0,0 +1,53 @@ +From 52fc8cff0b7af347b9224c4463fc7dd440f7aa66 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 22 Jun 2026 23:01:22 +0000 +Subject: bpf: Reset register bounds before narrowing retval range in + check_mem_access() + +From: Tristan Madani + +[ Upstream commit 5e0b273e0a62cc04ec338c7b502797c66c2ed42a ] + +When the BPF verifier processes a context load of an LSM hook return +value, it calls __mark_reg_s32_range() to narrow the register to the +hook's valid range. However, __mark_reg_s32_range() intersects the new +range with the register's existing bounds using max_t()/min_t() rather +than replacing them. + +If the destination register carries stale bounds from a prior instruction +(e.g. BPF_MOV64_IMM), the intersection can produce a range narrower than +reality. The verifier then believes it knows the register's exact value, +while at runtime the actual hook return value is loaded, creating a +verifier/runtime mismatch that can be used to bypass BPF memory safety +checks. + +The else branch already calls mark_reg_unknown() to reset register state +before any narrowing. Apply the same reset in the is_retval path so +stale bounds are cleared before __mark_reg_s32_range() intersects. + +Fixes: 5d99e198be27 ("bpf, lsm: Add check for BPF LSM return value") +Cc: stable@vger.kernel.org +Signed-off-by: Tristan Madani +Acked-by: Eduard Zingerman +Link: https://lore.kernel.org/r/20260622230123.3695446-2-tristmd@gmail.com +Signed-off-by: Alexei Starovoitov +Signed-off-by: Sasha Levin +--- + kernel/bpf/verifier.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c +index 8c3c4ab989a05..77183b436da5e 100644 +--- a/kernel/bpf/verifier.c ++++ b/kernel/bpf/verifier.c +@@ -7234,6 +7234,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn + */ + if (reg_type == SCALAR_VALUE) { + if (is_retval && get_func_retval_range(env->prog, &range)) { ++ mark_reg_unknown(env, regs, value_regno); + err = __mark_reg_s32_range(env, regs, value_regno, + range.minval, range.maxval); + if (err) +-- +2.53.0 + diff --git a/queue-6.12/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch b/queue-6.12/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch new file mode 100644 index 0000000000..52d73d0fb1 --- /dev/null +++ b/queue-6.12/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch @@ -0,0 +1,45 @@ +From d75f6abd34a9c4869d1460c2c89f5fdcf2a400e6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Apr 2026 16:03:07 +0200 +Subject: HID: logitech-dj: fix wrong detection of bad DJ_SHORT output report + +From: Benjamin Tissoires + +[ Upstream commit 8b9a097eb2fc37b486afd81388c693bf3ab44466 ] + +commit b6a57912854e ("HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT +related user initiated OOB write") assumed that all HID devices attached +to the logitech-dj driver was having an output report of DJ_SHORT. + +However, on the receiver itself, we have 2 other HID device we attach +here: the mouse emulation and the keyboard emulation. For those devices +the value of rep is NULL and we are triggered a segfault here. + +This is doubly required because logitech-dj also handles non DJ devices +that might not have the DJ collection. + +Fixes: b6a57912854e ("HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated OOB write") +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 3a37d61616293..f1e923ed9d1c5 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1797,7 +1797,8 @@ static int logi_dj_probe(struct hid_device *hdev, + output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; + rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; + +- if (rep->maxfield < 1 || rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1) { ++ if (rep && (rep->maxfield < 1 || ++ rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1)) { + hid_err(hdev, "Expected size of DJ short report is %d, but got %d", + DJREPORT_SHORT_LENGTH - 1, rep->field[0]->report_count); + return -EINVAL; +-- +2.53.0 + diff --git a/queue-6.12/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch b/queue-6.12/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch new file mode 100644 index 0000000000..8c52517d91 --- /dev/null +++ b/queue-6.12/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch @@ -0,0 +1,56 @@ +From a80e23c37e2d91de5a333d0b5e196bbf4612c535 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 14:36:44 +0000 +Subject: HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated + OOB write + +From: Lee Jones + +[ Upstream commit b6a57912854e7ea36f3b270032661140cc4209cd ] + +logi_dj_recv_send_report() assumes that all incoming REPORT_ID_DJ_SHORT +reports are 14 Bytes (DJREPORT_SHORT_LENGTH - 1) long. It uses that +assumption to load the associated field's 'value' array with 14 Bytes of +data. However, if a malicious user only sends say 1 Byte of data, +'report_count' will be 1 and only 1 Byte of memory will be allocated to +the 'value' Byte array. When we come to populate 'value[1-13]' we will +experience an OOB write. + +Signed-off-by: Lee Jones +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index d6fb7015f0d77..3a37d61616293 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1750,6 +1750,7 @@ static int logi_dj_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { + struct hid_report_enum *input_report_enum; ++ struct hid_report_enum *output_report_enum; + struct hid_report *rep; + struct dj_receiver_dev *djrcv_dev; + struct usb_interface *intf; +@@ -1793,6 +1794,15 @@ static int logi_dj_probe(struct hid_device *hdev, + } + } + ++ output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; ++ rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; ++ ++ if (rep->maxfield < 1 || rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1) { ++ hid_err(hdev, "Expected size of DJ short report is %d, but got %d", ++ DJREPORT_SHORT_LENGTH - 1, rep->field[0]->report_count); ++ return -EINVAL; ++ } ++ + input_report_enum = &hdev->report_enum[HID_INPUT_REPORT]; + + /* no input reports, bail out */ +-- +2.53.0 + diff --git a/queue-6.12/hid-logitech-dj-standardise-hid_report_enum-variable.patch b/queue-6.12/hid-logitech-dj-standardise-hid_report_enum-variable.patch new file mode 100644 index 0000000000..17f2d12f3b --- /dev/null +++ b/queue-6.12/hid-logitech-dj-standardise-hid_report_enum-variable.patch @@ -0,0 +1,78 @@ +From 3a52e2a64369a845f434ac2eb131f1fce5f707b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 14:36:43 +0000 +Subject: HID: logitech-dj: Standardise hid_report_enum variable nomenclature + +From: Lee Jones + +[ Upstream commit a940aee176437046598dfc786b719bd96db3c74c ] + +Since we will need to differentiate between the two report_enum types +soon, let's unify the naming conventions now to save confusion and/or +unnecessary/unrelated changes in upcoming commits. + +{input,output}_report_enum is used in other places to let's conform. + +Signed-off-by: Lee Jones +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 3b5412541c925..d6fb7015f0d77 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1749,7 +1749,7 @@ static int logi_dj_raw_event(struct hid_device *hdev, + static int logi_dj_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +- struct hid_report_enum *rep_enum; ++ struct hid_report_enum *input_report_enum; + struct hid_report *rep; + struct dj_receiver_dev *djrcv_dev; + struct usb_interface *intf; +@@ -1793,10 +1793,10 @@ static int logi_dj_probe(struct hid_device *hdev, + } + } + +- rep_enum = &hdev->report_enum[HID_INPUT_REPORT]; ++ input_report_enum = &hdev->report_enum[HID_INPUT_REPORT]; + + /* no input reports, bail out */ +- if (list_empty(&rep_enum->report_list)) ++ if (list_empty(&input_report_enum->report_list)) + return -ENODEV; + + /* +@@ -1804,7 +1804,7 @@ static int logi_dj_probe(struct hid_device *hdev, + * Note: we should theoretically check for HID++ and DJ + * collections, but this will do. + */ +- list_for_each_entry(rep, &rep_enum->report_list, list) { ++ list_for_each_entry(rep, &input_report_enum->report_list, list) { + if (rep->application == 0xff000001) + has_hidpp = true; + } +@@ -1817,7 +1817,7 @@ static int logi_dj_probe(struct hid_device *hdev, + return -ENODEV; + + /* get the current application attached to the node */ +- rep = list_first_entry(&rep_enum->report_list, struct hid_report, list); ++ rep = list_first_entry(&input_report_enum->report_list, struct hid_report, list); + djrcv_dev = dj_get_receiver_dev(hdev, id->driver_data, + rep->application, has_hidpp); + if (!djrcv_dev) { +@@ -1825,7 +1825,7 @@ static int logi_dj_probe(struct hid_device *hdev, + return -ENOMEM; + } + +- if (!rep_enum->numbered) ++ if (!input_report_enum->numbered) + djrcv_dev->unnumbered_application = rep->application; + + /* Starts the usb device and connects to upper interfaces hiddev and +-- +2.53.0 + diff --git a/queue-6.12/series b/queue-6.12/series index ab6e78e7a2..4065f68f20 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -11,3 +11,7 @@ um-preserve-errno-within-signal-handler.patch netfilter-br_netfilter-reallocate-headroom-if-necess.patch net-airoha-fix-register-index-for-tx-fwd-counter-con.patch net-mpls-initialize-rtm_tos-in-mpls_getroute.patch +hid-logitech-dj-standardise-hid_report_enum-variable.patch +hid-logitech-dj-prevent-report_id_dj_short-related-u.patch +hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch +bpf-reset-register-bounds-before-narrowing-retval-ra.patch diff --git a/queue-6.18/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch b/queue-6.18/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch new file mode 100644 index 0000000000..95510834e5 --- /dev/null +++ b/queue-6.18/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch @@ -0,0 +1,45 @@ +From d0e76b38d261fa5f81eaf56eaaaeb7faa830cf72 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Apr 2026 16:03:07 +0200 +Subject: HID: logitech-dj: fix wrong detection of bad DJ_SHORT output report + +From: Benjamin Tissoires + +[ Upstream commit 8b9a097eb2fc37b486afd81388c693bf3ab44466 ] + +commit b6a57912854e ("HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT +related user initiated OOB write") assumed that all HID devices attached +to the logitech-dj driver was having an output report of DJ_SHORT. + +However, on the receiver itself, we have 2 other HID device we attach +here: the mouse emulation and the keyboard emulation. For those devices +the value of rep is NULL and we are triggered a segfault here. + +This is doubly required because logitech-dj also handles non DJ devices +that might not have the DJ collection. + +Fixes: b6a57912854e ("HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated OOB write") +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 3a37d61616293..f1e923ed9d1c5 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1797,7 +1797,8 @@ static int logi_dj_probe(struct hid_device *hdev, + output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; + rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; + +- if (rep->maxfield < 1 || rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1) { ++ if (rep && (rep->maxfield < 1 || ++ rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1)) { + hid_err(hdev, "Expected size of DJ short report is %d, but got %d", + DJREPORT_SHORT_LENGTH - 1, rep->field[0]->report_count); + return -EINVAL; +-- +2.53.0 + diff --git a/queue-6.18/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch b/queue-6.18/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch new file mode 100644 index 0000000000..2123e93d04 --- /dev/null +++ b/queue-6.18/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch @@ -0,0 +1,56 @@ +From b809ec91217abe5e0d246ec07e0a2aa25e9a513c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 14:36:44 +0000 +Subject: HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated + OOB write + +From: Lee Jones + +[ Upstream commit b6a57912854e7ea36f3b270032661140cc4209cd ] + +logi_dj_recv_send_report() assumes that all incoming REPORT_ID_DJ_SHORT +reports are 14 Bytes (DJREPORT_SHORT_LENGTH - 1) long. It uses that +assumption to load the associated field's 'value' array with 14 Bytes of +data. However, if a malicious user only sends say 1 Byte of data, +'report_count' will be 1 and only 1 Byte of memory will be allocated to +the 'value' Byte array. When we come to populate 'value[1-13]' we will +experience an OOB write. + +Signed-off-by: Lee Jones +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index d6fb7015f0d77..3a37d61616293 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1750,6 +1750,7 @@ static int logi_dj_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { + struct hid_report_enum *input_report_enum; ++ struct hid_report_enum *output_report_enum; + struct hid_report *rep; + struct dj_receiver_dev *djrcv_dev; + struct usb_interface *intf; +@@ -1793,6 +1794,15 @@ static int logi_dj_probe(struct hid_device *hdev, + } + } + ++ output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; ++ rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; ++ ++ if (rep->maxfield < 1 || rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1) { ++ hid_err(hdev, "Expected size of DJ short report is %d, but got %d", ++ DJREPORT_SHORT_LENGTH - 1, rep->field[0]->report_count); ++ return -EINVAL; ++ } ++ + input_report_enum = &hdev->report_enum[HID_INPUT_REPORT]; + + /* no input reports, bail out */ +-- +2.53.0 + diff --git a/queue-6.18/hid-logitech-dj-standardise-hid_report_enum-variable.patch b/queue-6.18/hid-logitech-dj-standardise-hid_report_enum-variable.patch new file mode 100644 index 0000000000..9f86c96f68 --- /dev/null +++ b/queue-6.18/hid-logitech-dj-standardise-hid_report_enum-variable.patch @@ -0,0 +1,78 @@ +From 6d59139f5c5a499fafe011db0173c9e57f1d189b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 14:36:43 +0000 +Subject: HID: logitech-dj: Standardise hid_report_enum variable nomenclature + +From: Lee Jones + +[ Upstream commit a940aee176437046598dfc786b719bd96db3c74c ] + +Since we will need to differentiate between the two report_enum types +soon, let's unify the naming conventions now to save confusion and/or +unnecessary/unrelated changes in upcoming commits. + +{input,output}_report_enum is used in other places to let's conform. + +Signed-off-by: Lee Jones +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 3b5412541c925..d6fb7015f0d77 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1749,7 +1749,7 @@ static int logi_dj_raw_event(struct hid_device *hdev, + static int logi_dj_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +- struct hid_report_enum *rep_enum; ++ struct hid_report_enum *input_report_enum; + struct hid_report *rep; + struct dj_receiver_dev *djrcv_dev; + struct usb_interface *intf; +@@ -1793,10 +1793,10 @@ static int logi_dj_probe(struct hid_device *hdev, + } + } + +- rep_enum = &hdev->report_enum[HID_INPUT_REPORT]; ++ input_report_enum = &hdev->report_enum[HID_INPUT_REPORT]; + + /* no input reports, bail out */ +- if (list_empty(&rep_enum->report_list)) ++ if (list_empty(&input_report_enum->report_list)) + return -ENODEV; + + /* +@@ -1804,7 +1804,7 @@ static int logi_dj_probe(struct hid_device *hdev, + * Note: we should theoretically check for HID++ and DJ + * collections, but this will do. + */ +- list_for_each_entry(rep, &rep_enum->report_list, list) { ++ list_for_each_entry(rep, &input_report_enum->report_list, list) { + if (rep->application == 0xff000001) + has_hidpp = true; + } +@@ -1817,7 +1817,7 @@ static int logi_dj_probe(struct hid_device *hdev, + return -ENODEV; + + /* get the current application attached to the node */ +- rep = list_first_entry(&rep_enum->report_list, struct hid_report, list); ++ rep = list_first_entry(&input_report_enum->report_list, struct hid_report, list); + djrcv_dev = dj_get_receiver_dev(hdev, id->driver_data, + rep->application, has_hidpp); + if (!djrcv_dev) { +@@ -1825,7 +1825,7 @@ static int logi_dj_probe(struct hid_device *hdev, + return -ENOMEM; + } + +- if (!rep_enum->numbered) ++ if (!input_report_enum->numbered) + djrcv_dev->unnumbered_application = rep->application; + + /* Starts the usb device and connects to upper interfaces hiddev and +-- +2.53.0 + diff --git a/queue-6.18/lib-alloc_tag-introduce-mem_alloc_profiling_permanen.patch b/queue-6.18/lib-alloc_tag-introduce-mem_alloc_profiling_permanen.patch new file mode 100644 index 0000000000..ff5d71833f --- /dev/null +++ b/queue-6.18/lib-alloc_tag-introduce-mem_alloc_profiling_permanen.patch @@ -0,0 +1,76 @@ +From d4dbc617c3b8ba03a2d575c12854ce83084b80fc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Aug 2026 07:15:10 +0000 +Subject: lib/alloc_tag: introduce mem_alloc_profiling_permanently_disabled() + +From: Harry Yoo (Oracle) + +commit a37b0066a10aabf3c968b4566706fb866eaf9a85 upstream. + +mem_alloc_profiling_enabled() tells whether memalloc profiling is +currently enabled. However, even when this function returns false, +it can be enabled later. + +However, this is not enough. Some optimizations can be applied only when +memalloc profiling is permanently disabled. For example, to skip the +creation of KMALLOC_NO_OBJ_EXT caches at boot time, mem_profiling must +be set to "never", "0" w/ debugging on, or have been shutdown so that +it can no longer be enabled. + +Introduce mem_alloc_profiling_permanently_disabled() for this purpose. + +Signed-off-by: Harry Yoo (Oracle) +Acked-by: Suren Baghdasaryan +Link: https://patch.msgid.link/20260713-kmalloc-no-objext-v3-3-47c7bd138de7@kernel.org +Signed-off-by: Vlastimil Babka (SUSE) +Signed-off-by: Harry Yoo +Signed-off-by: Sasha Levin +--- + include/linux/alloc_tag.h | 3 +++ + lib/alloc_tag.c | 9 +++++++++ + 2 files changed, 12 insertions(+) + +diff --git a/include/linux/alloc_tag.h b/include/linux/alloc_tag.h +index 02de2ede560f3..7e7cdc7612bed 100644 +--- a/include/linux/alloc_tag.h ++++ b/include/linux/alloc_tag.h +@@ -134,6 +134,8 @@ static inline bool mem_alloc_profiling_enabled(void) + &mem_alloc_profiling_key); + } + ++bool mem_alloc_profiling_permanently_disabled(void); ++ + static inline struct alloc_tag_counters alloc_tag_read(struct alloc_tag *tag) + { + struct alloc_tag_counters v = { 0, 0 }; +@@ -239,6 +241,7 @@ static inline bool alloc_tag_is_inaccurate(struct alloc_tag *tag) + + #define DEFINE_ALLOC_TAG(_alloc_tag) + static inline bool mem_alloc_profiling_enabled(void) { return false; } ++static inline bool mem_alloc_profiling_permanently_disabled(void) { return true; } + static inline void alloc_tag_add(union codetag_ref *ref, struct alloc_tag *tag, + size_t bytes) {} + static inline void alloc_tag_sub(union codetag_ref *ref, size_t bytes) {} +diff --git a/lib/alloc_tag.c b/lib/alloc_tag.c +index 3082d977efaae..7c6d3a086fdc4 100644 +--- a/lib/alloc_tag.c ++++ b/lib/alloc_tag.c +@@ -26,6 +26,15 @@ static bool mem_profiling_support = true; + static bool mem_profiling_support; + #endif + ++/* ++ * Memory allocation profiling is permanently disabled and cannot be enabled. ++ * Must be called after setup_early_mem_profiling(). ++ */ ++bool mem_alloc_profiling_permanently_disabled(void) ++{ ++ return !mem_profiling_support; ++} ++ + static struct codetag_type *alloc_tag_cttype; + + #ifdef CONFIG_ARCH_MODULE_NEEDS_WEAK_PER_CPU +-- +2.53.0 + diff --git a/queue-6.18/mm-slab-prevent-unbounded-recursion-in-free-path-wit.patch b/queue-6.18/mm-slab-prevent-unbounded-recursion-in-free-path-wit.patch new file mode 100644 index 0000000000..8e90ac62e3 --- /dev/null +++ b/queue-6.18/mm-slab-prevent-unbounded-recursion-in-free-path-wit.patch @@ -0,0 +1,387 @@ +From 34dcda1699b4a6e0c983ffb0983fc875fb41f4b2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 3 Aug 2026 07:15:11 +0000 +Subject: mm/slab: prevent unbounded recursion in free path with new kmalloc + type + +From: Harry Yoo (Oracle) + +commit d9e6a7623938968e3752b67e37eaff097e559a54 upstream. + +Commit 280ea9c3154b ("mm/slab: avoid allocating slabobj_ext array from +its own slab") avoided recursive allocation of obj_exts from kmalloc +caches of the same size, by bumping the obj_exts array's allocation +size whenever the array size equals the size of the object being +allocated. + +However, as reported by Danielle Costantino and Shakeel Butt, +even slabs from kmalloc caches of different sizes can form a cycle +by allocating obj_exts arrays from each other [1]: + + What happened: a KMALLOC_NORMAL slab's obj_exts array (used by + allocation profiling / memcg accounting) is itself kmalloc()'d from a + KMALLOC_NORMAL cache, so the "slab holds another slab's obj_exts array" + relation can form cycles. With sizeof(struct slabobj_ext) == 16 and + the host's geometry: + + - kmalloc-512 has 64 objects/slab -> array is 64*16 == 1024 bytes, + served from kmalloc-1k; + - kmalloc-1k has 32 objects/slab -> array is 32*16 == 512 bytes, + served from kmalloc-512. + + A kmalloc-512 slab and a kmalloc-1k slab therefore hold each other's + obj_exts array. Discarding one frees the other's array, which empties + and discards that slab, which frees the first's array, and so on: + __free_slab() -> free_slab_obj_exts() -> kfree() -> discard_slab() -> + __free_slab() recurses along the cycle until the stack is exhausted. + +With memory allocation profiling, this allows unbounded recursion +in the free path and led to a stack overflow on a production host in +the Meta fleet [1]: + + BUG: TASK stack guard page was hit + Oops: stack guard page + RIP: 0010:kfree+0x8/0x5d0 + Call Trace: + __free_slab+0x66/0xc0 + kfree+0x3f0/0x5d0 + ... ( ~125x __free_slab <-> kfree ) ... + + do_syscall_64 + +It is proposed [1] to resolve this issue by always serving the obj_exts +array allocation from kmalloc caches (or large kmalloc) of sizes larger +than the object size. However, as pointed out by Vlastimil Babka [2], +this can waste an excessive amount of memory as slabs from large +kmalloc sizes (e.g. kmalloc-8k) generally need obj_exts arrays much +smaller than the object size. + +Therefore, rather than bumping the size, let us take a different +approach; disallow formation of cycles between kmalloc types when +allocating obj_exts arrays. Currently, all obj_exts arrays are served +from normal kmalloc caches. Cycles cannot be created if obj_exts arrays +of normal kmalloc caches are served from a special kmalloc type that can +never have obj_exts arrays. + +To achieve this, create a new kmalloc type called KMALLOC_NO_OBJ_EXT. +KMALLOC_NO_OBJ_EXT caches are created with SLAB_NO_OBJ_EXT flag when +either 1) memory allocation profiling is not permanently disabled, +or 2) kmalloc types with a priority higher than KMALLOC_CGROUP are +aliased with KMALLOC_NORMAL. + +Sheaf bootstrapping for KMALLOC_NO_OBJ_EXT caches now must be deferred +because allocation of a barn can trigger obj_exts array allocation of +normal kmalloc caches when the KMALLOC_NO_OBJ_EXT cache for that size +is not ready yet. For simplicity, perform bootstrapping of sheaves for +all kmalloc caches later. + +Introduce a new slab alloc flag, SLAB_ALLOC_NO_OBJ_EXT, to prevent +allocation of obj_exts arrays, and let kmalloc_slab() override the type +to KMALLOC_NO_OBJ_EXT when specified. Note that kmalloc_type() remains +unchanged because kmalloc_flags() bypasses the kmalloc fastpath. + +Do not pass SLAB_ALLOC_NO_RECURSE to kmalloc_flags() in +alloc_slab_obj_exts() and instead use SLAB_ALLOC_NO_OBJ_EXT only when +the objects are allocated from normal kmalloc caches. While this +prevents unbounded recursive allocation of obj_exts, it allows +KMALLOC_NO_OBJ_EXT caches to have sheaves. + +Since sheaf allocations specify SLAB_ALLOC_NO_RECURSE that prevents +allocation of both sheaves and obj_exts arrays, the recursion depth +is bounded. + +obj_exts arrays for non-kmalloc-normal caches can now have a valid tag. +Do not call mark_obj_codetag_empty() when freeing an obj_exts array to +avoid false warnings. KMALLOC_NO_OBJ_EXT don't need this as they never +allocate those arrays. + +Reported-by: Danielle Costantino +Reported-by: Shakeel Butt +Closes: https://lore.kernel.org/linux-mm/20260625230029.703750-1-shakeel.butt@linux.dev [1] +Fixes: 4b8736964640 ("mm/slab: add allocation accounting into slab allocation and free paths") +Cc: stable@vger.kernel.org +Link: https://lore.kernel.org/linux-mm/c5c4208d-a6f0-413e-bad9-49be12f12d55@kernel.org [2] +Signed-off-by: Harry Yoo (Oracle) +Reviewed-by: Suren Baghdasaryan +Link: https://patch.msgid.link/20260713-kmalloc-no-objext-v3-4-47c7bd138de7@kernel.org +Signed-off-by: Vlastimil Babka (SUSE) +[harry@kernel.org: Backport notes: + - Fix a minor conflict due to missing partitioned + kmalloc caches in 6.18. + + - Use __GFP_NO_OBJ_EXT instead of SLAB_ALLOC_NO_OBJ_EXT + since slab's internal alloc_flags do not exist in 6.18. + + - Deferring sheaf bootstrapping for kmalloc caches is not applied + as they don't have sheaves in 6.18. + + - Adjust the comment for SLAB_NO_OBJ_EXT, like in the commit + 982e31382d9a ("mm/slab: decouple SLAB_NO_SHEAVES from + SLAB_NO_OBJ_EXT"). The rest of that commit is a no-op in 6.18 as + kmalloc caches don't have sheaves and thus only adjust the comment. + + - Apply the __GFP_NO_OBJ_EXT flag to the !allow_spin path in + alloc_slab_obj_exts(). ] +Signed-off-by: Harry Yoo +Signed-off-by: Sasha Levin +--- + include/linux/slab.h | 8 ++++- + mm/slab.h | 28 ++++++++++++++-- + mm/slab_common.c | 13 ++++++++ + mm/slub.c | 76 ++++++++++++++------------------------------ + 4 files changed, 70 insertions(+), 55 deletions(-) + +diff --git a/include/linux/slab.h b/include/linux/slab.h +index 22daf3f34a76f..a12601cc93a1b 100644 +--- a/include/linux/slab.h ++++ b/include/linux/slab.h +@@ -238,7 +238,7 @@ enum _slab_flag_bits { + #endif + #define SLAB_TEMPORARY SLAB_RECLAIM_ACCOUNT /* Objects are short-lived */ + +-/* Slab created using create_boot_cache */ ++/* Slab caches without obj_exts array */ + #ifdef CONFIG_SLAB_OBJ_EXT + #define SLAB_NO_OBJ_EXT __SLAB_FLAG_BIT(_SLAB_NO_OBJ_EXT) + #else +@@ -641,6 +641,9 @@ enum kmalloc_cache_type { + #endif + #ifndef CONFIG_MEMCG + KMALLOC_CGROUP = KMALLOC_NORMAL, ++#endif ++#ifndef CONFIG_SLAB_OBJ_EXT ++ KMALLOC_NO_OBJ_EXT = KMALLOC_NORMAL, + #endif + KMALLOC_RANDOM_START = KMALLOC_NORMAL, + KMALLOC_RANDOM_END = KMALLOC_RANDOM_START + RANDOM_KMALLOC_CACHES_NR, +@@ -654,6 +657,9 @@ enum kmalloc_cache_type { + #endif + #ifdef CONFIG_MEMCG + KMALLOC_CGROUP, ++#endif ++#ifdef CONFIG_SLAB_OBJ_EXT ++ KMALLOC_NO_OBJ_EXT, + #endif + NR_KMALLOC_TYPES + }; +diff --git a/mm/slab.h b/mm/slab.h +index 36893299fa67c..c452f2a32c801 100644 +--- a/mm/slab.h ++++ b/mm/slab.h +@@ -394,9 +394,13 @@ static inline struct kmem_cache * + kmalloc_slab(size_t size, kmem_buckets *b, gfp_t flags, unsigned long caller) + { + unsigned int index; ++ enum kmalloc_cache_type type = kmalloc_type(flags, caller); ++ ++ if (flags & __GFP_NO_OBJ_EXT) ++ type = KMALLOC_NO_OBJ_EXT; + + if (!b) +- b = &kmalloc_caches[kmalloc_type(flags, caller)]; ++ b = &kmalloc_caches[type]; + if (size <= 192) + index = kmalloc_size_index[size_index_elem(size)]; + else +@@ -435,7 +439,8 @@ static inline bool is_kmalloc_normal(struct kmem_cache *s) + { + if (!is_kmalloc_cache(s)) + return false; +- return !(s->flags & (SLAB_CACHE_DMA|SLAB_ACCOUNT|SLAB_RECLAIM_ACCOUNT)); ++ ++ return !(s->flags & (SLAB_CACHE_DMA|SLAB_ACCOUNT|SLAB_RECLAIM_ACCOUNT|SLAB_NO_OBJ_EXT)); + } + + bool __kfree_rcu_sheaf(struct kmem_cache *s, void *obj); +@@ -520,6 +525,25 @@ bool slab_in_kunit_test(void); + static inline bool slab_in_kunit_test(void) { return false; } + #endif + ++/* ++ * Return true if KMALLOC_NORMAL caches may need obj_exts arrays. ++ * ++ * Memory allocation profiling requires obj_exts for all caches. ++ * Memcg usually doesn't need them for normal kmalloc caches, but kmalloc types ++ * with a priority higher than KMALLOC_CGROUP can be aliased with KMALLOC_NORMAL. ++ */ ++static inline bool need_kmalloc_no_objext(void) ++{ ++ if (!mem_alloc_profiling_permanently_disabled()) ++ return true; ++ ++ if (!mem_cgroup_kmem_disabled() && ++ (KMALLOC_NORMAL == KMALLOC_RECLAIM)) ++ return true; ++ ++ return false; ++} ++ + #ifdef CONFIG_SLAB_OBJ_EXT + + /* +diff --git a/mm/slab_common.c b/mm/slab_common.c +index 04583044a2bf0..085af9a96fd92 100644 +--- a/mm/slab_common.c ++++ b/mm/slab_common.c +@@ -803,6 +803,12 @@ EXPORT_SYMBOL(kmalloc_size_roundup); + #define KMALLOC_RANDOM_NAME(N, sz) + #endif + ++#ifdef CONFIG_SLAB_OBJ_EXT ++#define KMALLOC_NO_OBJ_EXT_NAME(sz) .name[KMALLOC_NO_OBJ_EXT] = "kmalloc-no-objext-" #sz, ++#else ++#define KMALLOC_NO_OBJ_EXT_NAME(sz) ++#endif ++ + #define INIT_KMALLOC_INFO(__size, __short_size) \ + { \ + .name[KMALLOC_NORMAL] = "kmalloc-" #__short_size, \ +@@ -810,6 +816,7 @@ EXPORT_SYMBOL(kmalloc_size_roundup); + KMALLOC_CGROUP_NAME(__short_size) \ + KMALLOC_DMA_NAME(__short_size) \ + KMALLOC_RANDOM_NAME(RANDOM_KMALLOC_CACHES_NR, __short_size) \ ++ KMALLOC_NO_OBJ_EXT_NAME(__short_size) \ + .size = __size, \ + } + +@@ -917,6 +924,12 @@ new_kmalloc_cache(int idx, enum kmalloc_cache_type type) + return; + } + flags |= SLAB_ACCOUNT; ++ } else if (IS_ENABLED(CONFIG_SLAB_OBJ_EXT) && type == KMALLOC_NO_OBJ_EXT) { ++ if (!need_kmalloc_no_objext()) { ++ kmalloc_caches[type][idx] = kmalloc_caches[KMALLOC_NORMAL][idx]; ++ return; ++ } ++ flags |= SLAB_NO_OBJ_EXT | SLAB_NO_MERGE; + } else if (IS_ENABLED(CONFIG_ZONE_DMA) && (type == KMALLOC_DMA)) { + flags |= SLAB_CACHE_DMA; + } +diff --git a/mm/slub.c b/mm/slub.c +index 71e09c675047d..5ddd2a5c9e79b 100644 +--- a/mm/slub.c ++++ b/mm/slub.c +@@ -2096,42 +2096,6 @@ static inline void init_slab_obj_exts(struct slab *slab) + slab->obj_exts = 0; + } + +-/* +- * Calculate the allocation size for slabobj_ext array. +- * +- * When memory allocation profiling is enabled, the obj_exts array +- * could be allocated from the same slab cache it's being allocated for. +- * This would prevent the slab from ever being freed because it would +- * always contain at least one allocated object (its own obj_exts array). +- * +- * To avoid this, increase the allocation size when we detect the array +- * may come from the same cache, forcing it to use a different cache. +- */ +-static inline size_t obj_exts_alloc_size(struct kmem_cache *s, +- struct slab *slab, gfp_t gfp) +-{ +- size_t sz = sizeof(struct slabobj_ext) * slab->objects; +- struct kmem_cache *obj_exts_cache; +- +- if (sz > KMALLOC_MAX_CACHE_SIZE) +- return sz; +- +- if (!is_kmalloc_normal(s)) +- return sz; +- +- obj_exts_cache = kmalloc_slab(sz, NULL, gfp, 0); +- /* +- * We can't simply compare s with obj_exts_cache, because random kmalloc +- * caches have multiple caches per size, selected by caller address. +- * Since caller address may differ between kmalloc_slab() and actual +- * allocation, bump size when sizes are equal. +- */ +- if (s->object_size == obj_exts_cache->object_size) +- return obj_exts_cache->object_size + 1; +- +- return sz; +-} +- + int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s, + gfp_t gfp, bool new_slab) + { +@@ -2140,13 +2104,17 @@ int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s, + unsigned long new_exts; + unsigned long old_exts; + struct slabobj_ext *vec; +- size_t sz; ++ size_t sz = sizeof(struct slabobj_ext) * slab->objects; + + gfp &= ~OBJCGS_CLEAR_MASK; +- /* Prevent recursive extension vector allocation */ +- gfp |= __GFP_NO_OBJ_EXT; + +- sz = obj_exts_alloc_size(s, slab, gfp); ++ /* ++ * In most cases, obj_exts arrays are allocated from normal kmalloc. ++ * However, normal kmalloc caches must allocate them from ++ * KMALLOC_NO_OBJ_EXT caches to prevent recursion. ++ */ ++ if (is_kmalloc_normal(s)) ++ gfp |= __GFP_NO_OBJ_EXT; + + /* + * Note that allow_spin may be false during early boot and its +@@ -2155,7 +2123,7 @@ int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s, + * very early allocations on those. + */ + if (unlikely(!allow_spin)) +- vec = kmalloc_nolock(sz, __GFP_ZERO | __GFP_NO_OBJ_EXT, ++ vec = kmalloc_nolock(sz, __GFP_ZERO | (gfp & __GFP_NO_OBJ_EXT), + slab_nid(slab)); + else + vec = kmalloc_node(sz, gfp | __GFP_ZERO, slab_nid(slab)); +@@ -2173,8 +2141,21 @@ int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s, + return -ENOMEM; + } + +- VM_WARN_ON_ONCE(virt_to_slab(vec) != NULL && +- virt_to_slab(vec)->slab_cache == s); ++ if (IS_ENABLED(CONFIG_DEBUG_VM)) { ++ struct kmem_cache *exts_cache; ++ struct slab *exts_slab; ++ ++ exts_slab = virt_to_slab(vec); ++ if (exts_slab) { ++ /* ++ * The vector must be allocated from either normal or ++ * KMALLOC_NO_OBJ_EXT kmalloc caches to avoid cycles. ++ */ ++ exts_cache = exts_slab->slab_cache; ++ WARN_ON_ONCE(!is_kmalloc_normal(exts_cache) && ++ !(exts_cache->flags & SLAB_NO_OBJ_EXT)); ++ } ++ } + + new_exts = (unsigned long)vec; + if (unlikely(!allow_spin)) +@@ -2198,7 +2179,6 @@ int alloc_slab_obj_exts(struct slab *slab, struct kmem_cache *s, + * assign slabobj_exts in parallel. In this case the existing + * objcg vector should be reused. + */ +- mark_objexts_empty(vec); + if (unlikely(!allow_spin)) + kfree_nolock(vec); + else +@@ -2229,14 +2209,6 @@ static inline void free_slab_obj_exts(struct slab *slab) + return; + } + +- /* +- * obj_exts was created with __GFP_NO_OBJ_EXT flag, therefore its +- * corresponding extension will be NULL. alloc_tag_sub() will throw a +- * warning if slab has extensions but the extension of an object is +- * NULL, therefore replace NULL with CODETAG_EMPTY to indicate that +- * the extension for obj_exts is expected to be NULL. +- */ +- mark_objexts_empty(obj_exts); + if (unlikely(READ_ONCE(slab->obj_exts) & OBJEXTS_NOSPIN_ALLOC)) + kfree_nolock(obj_exts); + else +-- +2.53.0 + diff --git a/queue-6.18/series b/queue-6.18/series index f4d8d3fb1c..f199159411 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -5,3 +5,8 @@ netfilter-br_netfilter-reallocate-headroom-if-necess.patch net-mpls-initialize-rtm_tos-in-mpls_getroute.patch drm-gpusvm-publish-dpagemap-early-to-avoid-device-ma.patch alsa-hda-realtek-add-quirk-for-hp-dragonfly-folio-g3.patch +hid-logitech-dj-standardise-hid_report_enum-variable.patch +hid-logitech-dj-prevent-report_id_dj_short-related-u.patch +hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch +lib-alloc_tag-introduce-mem_alloc_profiling_permanen.patch +mm-slab-prevent-unbounded-recursion-in-free-path-wit.patch diff --git a/queue-6.6/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch b/queue-6.6/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch new file mode 100644 index 0000000000..143e7d44f1 --- /dev/null +++ b/queue-6.6/hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch @@ -0,0 +1,45 @@ +From c3237696fdc9e7161d3e93a03611348bd8695af0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Apr 2026 16:03:07 +0200 +Subject: HID: logitech-dj: fix wrong detection of bad DJ_SHORT output report + +From: Benjamin Tissoires + +[ Upstream commit 8b9a097eb2fc37b486afd81388c693bf3ab44466 ] + +commit b6a57912854e ("HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT +related user initiated OOB write") assumed that all HID devices attached +to the logitech-dj driver was having an output report of DJ_SHORT. + +However, on the receiver itself, we have 2 other HID device we attach +here: the mouse emulation and the keyboard emulation. For those devices +the value of rep is NULL and we are triggered a segfault here. + +This is doubly required because logitech-dj also handles non DJ devices +that might not have the DJ collection. + +Fixes: b6a57912854e ("HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated OOB write") +Signed-off-by: Benjamin Tissoires +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 3529fb55689a1..5ab415939da0f 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1797,7 +1797,8 @@ static int logi_dj_probe(struct hid_device *hdev, + output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; + rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; + +- if (rep->maxfield < 1 || rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1) { ++ if (rep && (rep->maxfield < 1 || ++ rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1)) { + hid_err(hdev, "Expected size of DJ short report is %d, but got %d", + DJREPORT_SHORT_LENGTH - 1, rep->field[0]->report_count); + return -EINVAL; +-- +2.53.0 + diff --git a/queue-6.6/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch b/queue-6.6/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch new file mode 100644 index 0000000000..39824f03ea --- /dev/null +++ b/queue-6.6/hid-logitech-dj-prevent-report_id_dj_short-related-u.patch @@ -0,0 +1,56 @@ +From a0666095694a93acbfb27236469ac017abe79be7 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 14:36:44 +0000 +Subject: HID: logitech-dj: Prevent REPORT_ID_DJ_SHORT related user initiated + OOB write + +From: Lee Jones + +[ Upstream commit b6a57912854e7ea36f3b270032661140cc4209cd ] + +logi_dj_recv_send_report() assumes that all incoming REPORT_ID_DJ_SHORT +reports are 14 Bytes (DJREPORT_SHORT_LENGTH - 1) long. It uses that +assumption to load the associated field's 'value' array with 14 Bytes of +data. However, if a malicious user only sends say 1 Byte of data, +'report_count' will be 1 and only 1 Byte of memory will be allocated to +the 'value' Byte array. When we come to populate 'value[1-13]' we will +experience an OOB write. + +Signed-off-by: Lee Jones +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 8b14a6062d181..3529fb55689a1 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1750,6 +1750,7 @@ static int logi_dj_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { + struct hid_report_enum *input_report_enum; ++ struct hid_report_enum *output_report_enum; + struct hid_report *rep; + struct dj_receiver_dev *djrcv_dev; + struct usb_interface *intf; +@@ -1793,6 +1794,15 @@ static int logi_dj_probe(struct hid_device *hdev, + } + } + ++ output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; ++ rep = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; ++ ++ if (rep->maxfield < 1 || rep->field[0]->report_count != DJREPORT_SHORT_LENGTH - 1) { ++ hid_err(hdev, "Expected size of DJ short report is %d, but got %d", ++ DJREPORT_SHORT_LENGTH - 1, rep->field[0]->report_count); ++ return -EINVAL; ++ } ++ + input_report_enum = &hdev->report_enum[HID_INPUT_REPORT]; + + /* no input reports, bail out */ +-- +2.53.0 + diff --git a/queue-6.6/hid-logitech-dj-standardise-hid_report_enum-variable.patch b/queue-6.6/hid-logitech-dj-standardise-hid_report_enum-variable.patch new file mode 100644 index 0000000000..dbf08e9841 --- /dev/null +++ b/queue-6.6/hid-logitech-dj-standardise-hid_report_enum-variable.patch @@ -0,0 +1,78 @@ +From f17a309ce10913e688ef1cacb7ae6da4cd92a57b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 24 Mar 2026 14:36:43 +0000 +Subject: HID: logitech-dj: Standardise hid_report_enum variable nomenclature + +From: Lee Jones + +[ Upstream commit a940aee176437046598dfc786b719bd96db3c74c ] + +Since we will need to differentiate between the two report_enum types +soon, let's unify the naming conventions now to save confusion and/or +unnecessary/unrelated changes in upcoming commits. + +{input,output}_report_enum is used in other places to let's conform. + +Signed-off-by: Lee Jones +Signed-off-by: Jiri Kosina +Signed-off-by: Sasha Levin +--- + drivers/hid/hid-logitech-dj.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c +index 84ad70c9d0383..8b14a6062d181 100644 +--- a/drivers/hid/hid-logitech-dj.c ++++ b/drivers/hid/hid-logitech-dj.c +@@ -1749,7 +1749,7 @@ static int logi_dj_raw_event(struct hid_device *hdev, + static int logi_dj_probe(struct hid_device *hdev, + const struct hid_device_id *id) + { +- struct hid_report_enum *rep_enum; ++ struct hid_report_enum *input_report_enum; + struct hid_report *rep; + struct dj_receiver_dev *djrcv_dev; + struct usb_interface *intf; +@@ -1793,10 +1793,10 @@ static int logi_dj_probe(struct hid_device *hdev, + } + } + +- rep_enum = &hdev->report_enum[HID_INPUT_REPORT]; ++ input_report_enum = &hdev->report_enum[HID_INPUT_REPORT]; + + /* no input reports, bail out */ +- if (list_empty(&rep_enum->report_list)) ++ if (list_empty(&input_report_enum->report_list)) + return -ENODEV; + + /* +@@ -1804,7 +1804,7 @@ static int logi_dj_probe(struct hid_device *hdev, + * Note: we should theoretically check for HID++ and DJ + * collections, but this will do. + */ +- list_for_each_entry(rep, &rep_enum->report_list, list) { ++ list_for_each_entry(rep, &input_report_enum->report_list, list) { + if (rep->application == 0xff000001) + has_hidpp = true; + } +@@ -1817,7 +1817,7 @@ static int logi_dj_probe(struct hid_device *hdev, + return -ENODEV; + + /* get the current application attached to the node */ +- rep = list_first_entry(&rep_enum->report_list, struct hid_report, list); ++ rep = list_first_entry(&input_report_enum->report_list, struct hid_report, list); + djrcv_dev = dj_get_receiver_dev(hdev, id->driver_data, + rep->application, has_hidpp); + if (!djrcv_dev) { +@@ -1825,7 +1825,7 @@ static int logi_dj_probe(struct hid_device *hdev, + return -ENOMEM; + } + +- if (!rep_enum->numbered) ++ if (!input_report_enum->numbered) + djrcv_dev->unnumbered_application = rep->application; + + /* Starts the usb device and connects to upper interfaces hiddev and +-- +2.53.0 + diff --git a/queue-6.6/series b/queue-6.6/series index e69d2a5006..6542c4811d 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -2,3 +2,7 @@ netfilter-nf_conntrack_expect-restore-helper-propaga.patch netfilter-br_netfilter-reallocate-headroom-if-necess.patch net-mpls-initialize-rtm_tos-in-mpls_getroute.patch gve-fix-rx-queue-stall-on-alloc-failure.patch +hid-logitech-dj-standardise-hid_report_enum-variable.patch +hid-logitech-dj-prevent-report_id_dj_short-related-u.patch +hid-logitech-dj-fix-wrong-detection-of-bad-dj_short-.patch +soc-qcom-ice-allow-explicit-votes-on-iface-clock-for.patch diff --git a/queue-6.6/soc-qcom-ice-allow-explicit-votes-on-iface-clock-for.patch b/queue-6.6/soc-qcom-ice-allow-explicit-votes-on-iface-clock-for.patch new file mode 100644 index 0000000000..5847379a52 --- /dev/null +++ b/queue-6.6/soc-qcom-ice-allow-explicit-votes-on-iface-clock-for.patch @@ -0,0 +1,87 @@ +From 99d8af7cf74840aa93ef05e972c633d7c3dc452b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 16 Apr 2026 17:29:19 +0530 +Subject: soc: qcom: ice: Allow explicit votes on 'iface' clock for ICE + +From: Harshal Dev + +[ Upstream commit 0d5dc5818191b55e4364d04b1b898a14a2ccac38 ] + +Since Qualcomm inline-crypto engine (ICE) is now a dedicated driver +de-coupled from the QCOM UFS driver, it explicitly votes for its required +clocks during probe. For scenarios where the 'clk_ignore_unused' flag is +not passed on the kernel command line, to avoid potential unclocked ICE +hardware register access during probe the ICE driver should additionally +vote on the 'iface' clock. +Also update the suspend and resume callbacks to handle un-voting and voting +on the 'iface' clock. + +Fixes: 2afbf43a4aec6 ("soc: qcom: Make the Qualcomm UFS/SDCC ICE a dedicated driver") +Reviewed-by: Manivannan Sadhasivam +Reviewed-by: Kuldeep Singh +Reviewed-by: Konrad Dybcio +Signed-off-by: Harshal Dev +Link: https://lore.kernel.org/r/20260416-qcom_ice_power_and_clk_vote-v5-2-5ccf5d7e2846@oss.qualcomm.com +Signed-off-by: Bjorn Andersson +Signed-off-by: Sasha Levin +--- + drivers/soc/qcom/ice.c | 17 +++++++++++++++-- + 1 file changed, 15 insertions(+), 2 deletions(-) + +diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c +index 94e91835062b2..b20214027fc26 100644 +--- a/drivers/soc/qcom/ice.c ++++ b/drivers/soc/qcom/ice.c +@@ -48,6 +48,7 @@ struct qcom_ice { + struct device_link *link; + + struct clk *core_clk; ++ struct clk *iface_clk; + }; + + static DEFINE_XARRAY(ice_handles); +@@ -149,8 +150,13 @@ int qcom_ice_resume(struct qcom_ice *ice) + + err = clk_prepare_enable(ice->core_clk); + if (err) { +- dev_err(dev, "failed to enable core clock (%d)\n", +- err); ++ dev_err(dev, "Failed to enable core clock: %d\n", err); ++ return err; ++ } ++ ++ err = clk_prepare_enable(ice->iface_clk); ++ if (err) { ++ dev_err(dev, "Failed to enable iface clock: %d\n", err); + return err; + } + +@@ -160,6 +166,7 @@ EXPORT_SYMBOL_GPL(qcom_ice_resume); + + int qcom_ice_suspend(struct qcom_ice *ice) + { ++ clk_disable_unprepare(ice->iface_clk); + clk_disable_unprepare(ice->core_clk); + + return 0; +@@ -240,11 +247,17 @@ static struct qcom_ice *qcom_ice_create(struct device *dev, + engine->core_clk = devm_clk_get_optional_enabled(dev, "ice_core_clk"); + if (!engine->core_clk) + engine->core_clk = devm_clk_get_optional_enabled(dev, "ice"); ++ if (!engine->core_clk) ++ engine->core_clk = devm_clk_get_optional_enabled(dev, "core"); + if (!engine->core_clk) + engine->core_clk = devm_clk_get_enabled(dev, NULL); + if (IS_ERR(engine->core_clk)) + return ERR_CAST(engine->core_clk); + ++ engine->iface_clk = devm_clk_get_optional_enabled(dev, "iface"); ++ if (IS_ERR(engine->iface_clk)) ++ return ERR_CAST(engine->iface_clk); ++ + if (!qcom_ice_check_supported(engine)) + return ERR_PTR(-EOPNOTSUPP); + +-- +2.53.0 +