CVE-2026-46003
Description
In the Linux kernel, the following vulnerability has been resolved:
net: qrtr: ns: Limit the total number of nodes
Currently, the nameserver doesn't limit the number of nodes it handles. This can be an attack vector if a malicious client starts registering random nodes, leading to memory exhaustion.
Hence, limit the maximum number of nodes to 64. Note that, limit of 64 is chosen based on the current platform requirements. If requirement changes in the future, this limit can be increased.
AI Insight
LLM-synthesized narrative grounded in this CVE's description and references.
Linux kernel QRTR nameserver lacks node limit, allowing memory exhaustion via malicious registration; fixed by capping at 64 nodes.
Vulnerability
The vulnerability resides in the Linux kernel's QRTR (Qualcomm Remote Transport) nameserver, implemented in net/qrtr/ns.c. The nameserver does not enforce any limit on the number of nodes it tracks. A malicious client can register arbitrary nodes, causing the kernel to allocate memory for each registration. This can lead to memory exhaustion. The issue affects all kernel versions with QRTR support prior to the commit that introduces a maximum node limit of 64 [1].
Exploitation
An attacker requires network access to the QRTR nameserver, typically within the same local system or a Qualcomm-based environment. No authentication is necessary. The attacker sends crafted QRTR control messages to register fake nodes. By repeatedly registering nodes, the attacker can exhaust kernel memory, leading to a denial-of-service condition.
Impact
Successful exploitation results in memory exhaustion, causing system instability, potential crashes, or denial of service. No privilege escalation or information disclosure is described in the available references.
Mitigation
The fix is included in commit 4c46413661431aa60fb134cd4ecdf8beaa39f824 in the stable Linux kernel tree [1]. Users should update to a kernel version containing this commit. If QRTR is not required, disabling the module or restricting access to the QRTR socket can serve as a workaround. No entry in the Known Exploited Vulnerabilities (KEV) catalog has been reported.
AI Insight generated on May 27, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.
Affected products
1Patches
1027d5e84e810bnet: qrtr: ns: Limit the total number of nodes
2 files changed · +28 −6
net/qrtr/ns.c+14 −3 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index 1b9a90240a6802..c0418764470bed 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -71,12 +71,16 @@ struct qrtr_node { u32 server_count; }; -/* Max server, lookup limits are chosen based on the current platform requirements. - * If the requirement changes in the future, these values can be increased. +/* 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. */ +#define QRTR_NS_MAX_NODES 64 #define QRTR_NS_MAX_SERVERS 256 #define QRTR_NS_MAX_LOOKUPS 64 +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -85,6 +89,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc_obj(*node); if (!node) @@ -98,6 +107,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -404,6 +415,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
net/qrtr/ns.c+14 −3 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index 1b9a90240a6802..c0418764470bed 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -71,12 +71,16 @@ struct qrtr_node { u32 server_count; }; -/* Max server, lookup limits are chosen based on the current platform requirements. - * If the requirement changes in the future, these values can be increased. +/* 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. */ +#define QRTR_NS_MAX_NODES 64 #define QRTR_NS_MAX_SERVERS 256 #define QRTR_NS_MAX_LOOKUPS 64 +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -85,6 +89,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc_obj(*node); if (!node) @@ -98,6 +107,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -404,6 +415,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
4c4641366143net: qrtr: ns: Limit the total number of nodes
2 files changed · +30 −2
net/qrtr/ns.c+15 −1 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index b83f1aa2a0c8a3..ecf49172307f1b 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -82,6 +82,13 @@ struct qrtr_node { */ #define QRTR_NS_MAX_LOOKUPS 64 +/* Max nodes 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_NODES 64 + +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -90,6 +97,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) @@ -103,6 +115,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -406,6 +420,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
net/qrtr/ns.c+15 −1 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index b83f1aa2a0c8a3..ecf49172307f1b 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -82,6 +82,13 @@ struct qrtr_node { */ #define QRTR_NS_MAX_LOOKUPS 64 +/* Max nodes 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_NODES 64 + +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -90,6 +97,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) @@ -103,6 +115,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -406,6 +420,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
4665a29c08e1net: qrtr: ns: Limit the total number of nodes
2 files changed · +30 −2
net/qrtr/ns.c+15 −1 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index b6da0e7d72a5db..a10e8de4f7e105 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -82,6 +82,13 @@ struct qrtr_node { */ #define QRTR_NS_MAX_LOOKUPS 64 +/* Max nodes 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_NODES 64 + +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -90,6 +97,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) @@ -103,6 +115,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -409,6 +423,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
net/qrtr/ns.c+15 −1 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index b6da0e7d72a5db..a10e8de4f7e105 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -82,6 +82,13 @@ struct qrtr_node { */ #define QRTR_NS_MAX_LOOKUPS 64 +/* Max nodes 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_NODES 64 + +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -90,6 +97,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) @@ -103,6 +115,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -409,6 +423,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
5cf6d5e5e3b8net: qrtr: ns: Limit the total number of nodes
2 files changed · +30 −2
net/qrtr/ns.c+15 −1 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index b6da0e7d72a5db..a10e8de4f7e105 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -82,6 +82,13 @@ struct qrtr_node { */ #define QRTR_NS_MAX_LOOKUPS 64 +/* Max nodes 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_NODES 64 + +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -90,6 +97,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) @@ -103,6 +115,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -409,6 +423,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
net/qrtr/ns.c+15 −1 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index b6da0e7d72a5db..a10e8de4f7e105 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -82,6 +82,13 @@ struct qrtr_node { */ #define QRTR_NS_MAX_LOOKUPS 64 +/* Max nodes 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_NODES 64 + +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -90,6 +97,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) @@ -103,6 +115,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -409,6 +423,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
8022876894d0net: qrtr: ns: Limit the total number of nodes
2 files changed · +28 −6
net/qrtr/ns.c+14 −3 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index f189e1092d44cb..b3f9bbcf9ab9ba 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -72,12 +72,16 @@ struct qrtr_node { u32 server_count; }; -/* Max server, lookup limits are chosen based on the current platform requirements. - * If the requirement changes in the future, these values can be increased. +/* 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. */ +#define QRTR_NS_MAX_NODES 64 #define QRTR_NS_MAX_SERVERS 256 #define QRTR_NS_MAX_LOOKUPS 64 +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -86,6 +90,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc_obj(*node); if (!node) @@ -99,6 +108,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -405,6 +416,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
net/qrtr/ns.c+14 −3 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index f189e1092d44cb..b3f9bbcf9ab9ba 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -72,12 +72,16 @@ struct qrtr_node { u32 server_count; }; -/* Max server, lookup limits are chosen based on the current platform requirements. - * If the requirement changes in the future, these values can be increased. +/* 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. */ +#define QRTR_NS_MAX_NODES 64 #define QRTR_NS_MAX_SERVERS 256 #define QRTR_NS_MAX_LOOKUPS 64 +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -86,6 +90,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc_obj(*node); if (!node) @@ -99,6 +108,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -405,6 +416,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
4c4641366143net: qrtr: ns: Limit the total number of nodes
2 files changed · +30 −2
net/qrtr/ns.c+15 −1 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index b83f1aa2a0c8a3..ecf49172307f1b 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -82,6 +82,13 @@ struct qrtr_node { */ #define QRTR_NS_MAX_LOOKUPS 64 +/* Max nodes 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_NODES 64 + +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -90,6 +97,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) @@ -103,6 +115,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -406,6 +420,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
net/qrtr/ns.c+15 −1 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index b83f1aa2a0c8a3..ecf49172307f1b 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -82,6 +82,13 @@ struct qrtr_node { */ #define QRTR_NS_MAX_LOOKUPS 64 +/* Max nodes 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_NODES 64 + +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -90,6 +97,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) @@ -103,6 +115,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -406,6 +420,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
4665a29c08e1net: qrtr: ns: Limit the total number of nodes
2 files changed · +30 −2
net/qrtr/ns.c+15 −1 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index b6da0e7d72a5db..a10e8de4f7e105 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -82,6 +82,13 @@ struct qrtr_node { */ #define QRTR_NS_MAX_LOOKUPS 64 +/* Max nodes 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_NODES 64 + +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -90,6 +97,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) @@ -103,6 +115,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -409,6 +423,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
net/qrtr/ns.c+15 −1 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index b6da0e7d72a5db..a10e8de4f7e105 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -82,6 +82,13 @@ struct qrtr_node { */ #define QRTR_NS_MAX_LOOKUPS 64 +/* Max nodes 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_NODES 64 + +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -90,6 +97,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) @@ -103,6 +115,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -409,6 +423,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
8022876894d0net: qrtr: ns: Limit the total number of nodes
2 files changed · +28 −6
net/qrtr/ns.c+14 −3 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index f189e1092d44cb..b3f9bbcf9ab9ba 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -72,12 +72,16 @@ struct qrtr_node { u32 server_count; }; -/* Max server, lookup limits are chosen based on the current platform requirements. - * If the requirement changes in the future, these values can be increased. +/* 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. */ +#define QRTR_NS_MAX_NODES 64 #define QRTR_NS_MAX_SERVERS 256 #define QRTR_NS_MAX_LOOKUPS 64 +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -86,6 +90,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc_obj(*node); if (!node) @@ -99,6 +108,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -405,6 +416,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
net/qrtr/ns.c+14 −3 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index f189e1092d44cb..b3f9bbcf9ab9ba 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -72,12 +72,16 @@ struct qrtr_node { u32 server_count; }; -/* Max server, lookup limits are chosen based on the current platform requirements. - * If the requirement changes in the future, these values can be increased. +/* 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. */ +#define QRTR_NS_MAX_NODES 64 #define QRTR_NS_MAX_SERVERS 256 #define QRTR_NS_MAX_LOOKUPS 64 +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -86,6 +90,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc_obj(*node); if (!node) @@ -99,6 +108,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -405,6 +416,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
27d5e84e810bnet: qrtr: ns: Limit the total number of nodes
2 files changed · +28 −6
net/qrtr/ns.c+14 −3 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index 1b9a90240a6802..c0418764470bed 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -71,12 +71,16 @@ struct qrtr_node { u32 server_count; }; -/* Max server, lookup limits are chosen based on the current platform requirements. - * If the requirement changes in the future, these values can be increased. +/* 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. */ +#define QRTR_NS_MAX_NODES 64 #define QRTR_NS_MAX_SERVERS 256 #define QRTR_NS_MAX_LOOKUPS 64 +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -85,6 +89,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc_obj(*node); if (!node) @@ -98,6 +107,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -404,6 +415,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
net/qrtr/ns.c+14 −3 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index 1b9a90240a6802..c0418764470bed 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -71,12 +71,16 @@ struct qrtr_node { u32 server_count; }; -/* Max server, lookup limits are chosen based on the current platform requirements. - * If the requirement changes in the future, these values can be increased. +/* 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. */ +#define QRTR_NS_MAX_NODES 64 #define QRTR_NS_MAX_SERVERS 256 #define QRTR_NS_MAX_LOOKUPS 64 +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -85,6 +89,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc_obj(*node); if (!node) @@ -98,6 +107,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -404,6 +415,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
5cf6d5e5e3b8net: qrtr: ns: Limit the total number of nodes
2 files changed · +30 −2
net/qrtr/ns.c+15 −1 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index b6da0e7d72a5db..a10e8de4f7e105 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -82,6 +82,13 @@ struct qrtr_node { */ #define QRTR_NS_MAX_LOOKUPS 64 +/* Max nodes 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_NODES 64 + +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -90,6 +97,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) @@ -103,6 +115,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -409,6 +423,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
net/qrtr/ns.c+15 −1 modifieddiff --git a/net/qrtr/ns.c b/net/qrtr/ns.c index b6da0e7d72a5db..a10e8de4f7e105 100644 --- a/net/qrtr/ns.c +++ b/net/qrtr/ns.c @@ -82,6 +82,13 @@ struct qrtr_node { */ #define QRTR_NS_MAX_LOOKUPS 64 +/* Max nodes 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_NODES 64 + +static u8 node_count; + static struct qrtr_node *node_get(unsigned int node_id) { struct qrtr_node *node; @@ -90,6 +97,11 @@ static struct qrtr_node *node_get(unsigned int node_id) if (node) return node; + if (node_count >= QRTR_NS_MAX_NODES) { + pr_err_ratelimited("QRTR clients exceed max node limit!\n"); + return NULL; + } + /* If node didn't exist, allocate and insert it to the tree */ node = kzalloc(sizeof(*node), GFP_KERNEL); if (!node) @@ -103,6 +115,8 @@ static struct qrtr_node *node_get(unsigned int node_id) return NULL; } + node_count++; + return node; } @@ -409,6 +423,7 @@ static int ctrl_cmd_bye(struct sockaddr_qrtr *from) delete_node: xa_erase(&nodes, from->sq_node); kfree(node); + node_count--; return ret; } -- cgit 1.3-korg
Vulnerability mechanics
Root cause
"Missing upper bound on the number of QRTR nodes the nameserver will allocate, allowing an unprivileged client to exhaust kernel memory by registering arbitrary nodes."
Attack vector
A malicious client on the QRTR bus sends registration requests for many different node IDs. The nameserver's `node_get()` function in `net/qrtr/ns.c` [patch_id=2660520] allocates a new `qrtr_node` structure for each unseen node ID without any limit. By repeatedly registering random node IDs, the attacker causes the kernel to allocate an unbounded number of these structures, leading to memory exhaustion and a denial of service. No authentication is required beyond the ability to send QRTR control messages.
Affected code
The vulnerability resides in `net/qrtr/ns.c` in the `node_get()` function, which allocates a `struct qrtr_node` for any unseen node ID without an upper bound. The `ctrl_cmd_bye()` function handles node teardown but previously had no corresponding counter to enforce a limit.
What the fix does
The patch introduces a static `node_count` variable and a `QRTR_NS_MAX_NODES` constant set to 64 [patch_id=2660520]. In `node_get()`, before allocating a new node, the code now checks whether `node_count` has already reached the limit and returns NULL if so, printing a rate-limited error. The count is incremented after a successful allocation and decremented in `ctrl_cmd_bye()` when a node is freed. This caps the total number of concurrently tracked nodes, preventing the unbounded memory allocation that a malicious client could trigger.
Preconditions
- networkAttacker must be able to send QRTR control messages (e.g., NEW_SERVER or BYE commands) to the kernel nameserver.
- authNo authentication or authorization check is enforced on node registration by the nameserver.
Generated on May 27, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
5- git.kernel.org/stable/c/27d5e84e810b0849d08b9aec68e48570461ce313nvd
- git.kernel.org/stable/c/4665a29c08e1b36bc9db4814f9dde3d23e8fd1b0nvd
- git.kernel.org/stable/c/4c46413661431aa60fb134cd4ecdf8beaa39f824nvd
- git.kernel.org/stable/c/5cf6d5e5e3b804a44692fbf548a5179442e2e923nvd
- git.kernel.org/stable/c/8022876894d09ae485b499058c3357da683bcc5dnvd
News mentions
0No linked articles in our index yet.