Commit 8d5806c6 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by Paolo Abeni
Browse files

net: shaper: reject handle IDs exceeding internal bit-width



net_shaper_parse_handle() reads the user-supplied handle ID via
nla_get_u32(), accepting the full u32 range. However, the xarray key
is built by net_shaper_handle_to_index() using
FIELD_PREP(NET_SHAPER_ID_MASK, handle->id), where NET_SHAPER_ID_MASK
is GENMASK(25, 0) - only 26 bits wide. FIELD_PREP silently masks off
the upper bits at runtime. A user-supplied NODE id like 0x04000123
becomes id 0x123.

Additionally, a user-supplied id equal to NET_SHAPER_ID_UNSPEC
(0x03FFFFFF, which is NET_SHAPER_ID_MASK itself) would collide with
the sentinel used internally by the group operation to signal
"allocate a new NODE id".

Reject user-supplied IDs >= NET_SHAPER_ID_MASK (i.e., >= 0x03FFFFFF)
in the policy.

Fixes: 4b623f9f ("net-shapers: implement NL get operation")
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
Link: https://patch.msgid.link/20260510192904.3987113-9-kuba@kernel.org


Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent fbf5df34
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -33,6 +33,11 @@ doc: |
  @cap-get operation.

definitions:
  -
    type: const
    name: max-handle-id
    value: 0x3fffffe
    scope: kernel
  -
    type: enum
    name: scope
@@ -140,6 +145,8 @@ attribute-sets:
      -
        name: id
        type: u32
        checks:
          max: max-handle-id
        doc: |
          Numeric identifier of a shaper. The id semantic depends on
          the scope. For @queue scope it's the queue id and for @node
+3 −1
Original line number Diff line number Diff line
@@ -21,6 +21,8 @@

#define NET_SHAPER_ID_UNSPEC NET_SHAPER_ID_MASK

static_assert(NET_SHAPER_ID_UNSPEC == NET_SHAPER_MAX_HANDLE_ID + 1);

struct net_shaper_hierarchy {
	struct xarray shapers;
};
@@ -360,7 +362,7 @@ static int net_shaper_pre_insert(struct net_shaper_binding *binding,
	    handle->id == NET_SHAPER_ID_UNSPEC) {
		u32 min, max;

		handle->id = NET_SHAPER_ID_MASK - 1;
		handle->id = NET_SHAPER_MAX_HANDLE_ID;
		max = net_shaper_handle_to_index(handle);
		handle->id = 0;
		min = net_shaper_handle_to_index(handle);
+6 −1
Original line number Diff line number Diff line
@@ -11,10 +11,15 @@

#include <uapi/linux/net_shaper.h>

/* Integer value ranges */
static const struct netlink_range_validation net_shaper_a_handle_id_range = {
	.max	= NET_SHAPER_MAX_HANDLE_ID,
};

/* Common nested types */
const struct nla_policy net_shaper_handle_nl_policy[NET_SHAPER_A_HANDLE_ID + 1] = {
	[NET_SHAPER_A_HANDLE_SCOPE] = NLA_POLICY_MAX(NLA_U32, 3),
	[NET_SHAPER_A_HANDLE_ID] = { .type = NLA_U32, },
	[NET_SHAPER_A_HANDLE_ID] = NLA_POLICY_FULL_RANGE(NLA_U32, &net_shaper_a_handle_id_range),
};

const struct nla_policy net_shaper_leaf_info_nl_policy[NET_SHAPER_A_WEIGHT + 1] = {
+2 −0
Original line number Diff line number Diff line
@@ -12,6 +12,8 @@

#include <uapi/linux/net_shaper.h>

#define NET_SHAPER_MAX_HANDLE_ID	67108862

/* Common nested types */
extern const struct nla_policy net_shaper_handle_nl_policy[NET_SHAPER_A_HANDLE_ID + 1];
extern const struct nla_policy net_shaper_leaf_info_nl_policy[NET_SHAPER_A_WEIGHT + 1];