mirror of
https://github.com/torvalds/linux.git
synced 2026-09-12 12:34:02 +02:00
Merge branch 'net-cap-tx_queue_len-at-s16_max-to-prevent-oversized-ring-allocations'
Jamal Hadi Salim says: ==================== net: cap tx_queue_len at S16_MAX to prevent oversized ring allocations An unprivileged user (via unshare -Urn) can set a huge tx_queue_len and exhaust global memory through ring allocations sized from it (pfifo_fast skb_arrays, tun/tap ptr_rings). The reproducer from vega@nebusec.ai set the following params for illustration: txqlen of 500000 -> ~32 GiB/ring attempts, 1.6 GB tun, ~960 MB tap. Gets worse when you consider qdiscs like mq. What we fix: every path an unprivileged user can use to install an oversized tx_queue_len is rejected with -ERANGE before any ring is allocated; per-ring memory is bounded at 256 KiB. This is for you sashikos: What we deliberately _do not fix_ bound the NUMBER of rings. With the cap in place the worst case moves from "one knob" to the aggregate of ring x queues x devices, example: ip link add v0 numtxqueues 4096 txqueuelen 32767 type veth tc qdisc add dev v0 root mq -> 4096 * 3 * 32767 * 8 = ~3.0 GiB (one command) 50 tun devices x 256 queues x 32767 x 8 = ~3.1 GiB Unfortunately tx_queue_len is a bit ambigious in meaning: In some cases it means a ring size (which is pre-allocated, ex: tun, tap, and pfifo_fast); a cap of 4096 seems reasonable here. but in other cases it is used to indicate a queue limit ex: the qdisc consumers that allocate nothing (pfifo/bfifo/gred/plug/sfb, htb direct_qlen, qfq, teql). 32767 is a legitimate high-BDP queue length, so we are going to keep that value. Getting back to you sashikos, after this is merged and shows up in net-next we will send followup patches as follows: this series is not misread as "closes the OOM class"): a) Per-site ring limits at six identified locations - pfifo_fast init/resize, - tun attach/resize, - tap minor/resize) if you can spot more in your review we will take care of those as well. b) memcg accounting (GFP_KERNEL_ACCOUNT) for those ring allocations: contains a memcg-limited container's ring memory. Not GFP_KERNEL_ACCOUNT has no effect on the unshare attacker but will protect against containers (memory.max in its cgroup) ==================== Link: https://patch.msgid.link/QDISC-2899.v2.20260901233641@mojatatu.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
commit
6262acad9d
|
|
@ -898,6 +898,8 @@ attribute-sets:
|
|||
-
|
||||
name: txqlen
|
||||
type: u32
|
||||
checks:
|
||||
max: 32767
|
||||
-
|
||||
name: map
|
||||
type: binary
|
||||
|
|
|
|||
|
|
@ -9982,7 +9982,7 @@ int netif_change_tx_queue_len(struct net_device *dev, unsigned long new_len)
|
|||
unsigned int orig_len = dev->tx_queue_len;
|
||||
int res;
|
||||
|
||||
if (new_len != (unsigned int)new_len)
|
||||
if (new_len > S16_MAX)
|
||||
return -ERANGE;
|
||||
|
||||
if (new_len != orig_len) {
|
||||
|
|
|
|||
|
|
@ -2287,6 +2287,11 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb,
|
|||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
static const struct netlink_range_validation txqlen_range = {
|
||||
.min = 0,
|
||||
.max = S16_MAX,
|
||||
};
|
||||
|
||||
static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
|
||||
[IFLA_UNSPEC] = { .strict_start_type = IFLA_DPLL_PIN },
|
||||
[IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 },
|
||||
|
|
@ -2297,7 +2302,7 @@ static const struct nla_policy ifla_policy[IFLA_MAX+1] = {
|
|||
[IFLA_LINK] = { .type = NLA_U32 },
|
||||
[IFLA_MASTER] = { .type = NLA_U32 },
|
||||
[IFLA_CARRIER] = { .type = NLA_U8 },
|
||||
[IFLA_TXQLEN] = { .type = NLA_U32 },
|
||||
[IFLA_TXQLEN] = NLA_POLICY_FULL_RANGE(NLA_U32, &txqlen_range),
|
||||
[IFLA_WEIGHT] = { .type = NLA_U32 },
|
||||
[IFLA_OPERSTATE] = { .type = NLA_U8 },
|
||||
[IFLA_LINKMODE] = { .type = NLA_U8 },
|
||||
|
|
|
|||
|
|
@ -105,5 +105,209 @@
|
|||
"teardown": [
|
||||
"$TC qdisc del dev $DUMMY handle 1: root"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "dbe3",
|
||||
"name": "Set tx_queue_len to S16_MAX boundary (32767 accepted)",
|
||||
"category": [
|
||||
"qdisc",
|
||||
"pfifo_fast"
|
||||
],
|
||||
"plugins": {
|
||||
"requires": "nsPlugin"
|
||||
},
|
||||
"setup": [],
|
||||
"cmdUnderTest": "$IP link set dev $DUMMY txqueuelen 32767",
|
||||
"expExitCode": "0",
|
||||
"verifyCmd": "$IP link show dev $DUMMY",
|
||||
"matchPattern": "qlen 32767$",
|
||||
"matchCount": "1",
|
||||
"teardown": []
|
||||
},
|
||||
{
|
||||
"id": "b50e",
|
||||
"name": "Reject tx_queue_len above S16_MAX at set time (32768)",
|
||||
"category": [
|
||||
"qdisc",
|
||||
"pfifo_fast"
|
||||
],
|
||||
"plugins": {
|
||||
"requires": "nsPlugin"
|
||||
},
|
||||
"setup": [],
|
||||
"cmdUnderTest": "$IP link set dev $DUMMY txqueuelen 32768",
|
||||
"expExitCode": "2",
|
||||
"verifyCmd": "$IP link show dev $DUMMY",
|
||||
"matchPattern": "qlen 1000$",
|
||||
"matchCount": "1",
|
||||
"teardown": []
|
||||
},
|
||||
{
|
||||
"id": "40f8",
|
||||
"name": "Reject tx_queue_len above S16_MAX via sysfs (32768)",
|
||||
"category": [
|
||||
"qdisc",
|
||||
"pfifo_fast"
|
||||
],
|
||||
"plugins": {
|
||||
"requires": "nsPlugin"
|
||||
},
|
||||
"setup": [],
|
||||
"cmdUnderTest": "sh -c 'echo 32768 > /sys/class/net/$DUMMY/tx_queue_len'",
|
||||
"expExitCode": "1",
|
||||
"verifyCmd": "$IP link show dev $DUMMY",
|
||||
"matchPattern": "qlen 1000$",
|
||||
"matchCount": "1",
|
||||
"teardown": []
|
||||
},
|
||||
{
|
||||
"id": "4b6e",
|
||||
"name": "Set tx_queue_len to S16_MAX via sysfs (32767 accepted)",
|
||||
"category": [
|
||||
"qdisc",
|
||||
"pfifo_fast"
|
||||
],
|
||||
"plugins": {
|
||||
"requires": "nsPlugin"
|
||||
},
|
||||
"setup": [],
|
||||
"cmdUnderTest": "sh -c 'echo 32767 > /sys/class/net/$DUMMY/tx_queue_len'",
|
||||
"expExitCode": "0",
|
||||
"verifyCmd": "$IP link show dev $DUMMY",
|
||||
"matchPattern": "qlen 32767$",
|
||||
"matchCount": "1",
|
||||
"teardown": []
|
||||
},
|
||||
{
|
||||
"id": "b90d",
|
||||
"name": "Create device with tx_queue_len at S16_MAX boundary (32767 accepted)",
|
||||
"category": [
|
||||
"qdisc",
|
||||
"pfifo_fast"
|
||||
],
|
||||
"plugins": {
|
||||
"requires": "nsPlugin"
|
||||
},
|
||||
"setup": [
|
||||
[
|
||||
"$IP link del dev $DUMMY",
|
||||
0,
|
||||
1
|
||||
]
|
||||
],
|
||||
"cmdUnderTest": "$IP link add dev $DUMMY txqueuelen 32767 type dummy",
|
||||
"expExitCode": "0",
|
||||
"verifyCmd": "$IP link show dev $DUMMY",
|
||||
"matchPattern": "qlen 32767$",
|
||||
"matchCount": "1",
|
||||
"teardown": [
|
||||
[
|
||||
"$IP link del dev $DUMMY",
|
||||
0,
|
||||
1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "57ab",
|
||||
"name": "Reject creating device with tx_queue_len above S16_MAX (32768)",
|
||||
"category": [
|
||||
"qdisc",
|
||||
"pfifo_fast"
|
||||
],
|
||||
"plugins": {
|
||||
"requires": "nsPlugin"
|
||||
},
|
||||
"setup": [
|
||||
[
|
||||
"$IP link del dev $DUMMY",
|
||||
0,
|
||||
1
|
||||
]
|
||||
],
|
||||
"cmdUnderTest": "$IP link add dev $DUMMY txqueuelen 32768 type dummy",
|
||||
"expExitCode": "2",
|
||||
"verifyCmd": "$IP -o link show",
|
||||
"matchPattern": "^[0-9]+: $DUMMY",
|
||||
"matchCount": "0",
|
||||
"teardown": []
|
||||
},
|
||||
{
|
||||
"id": "e777",
|
||||
"name": "Reject creating device with oversized tx_queue_len (500000)",
|
||||
"category": [
|
||||
"qdisc",
|
||||
"pfifo_fast"
|
||||
],
|
||||
"plugins": {
|
||||
"requires": "nsPlugin"
|
||||
},
|
||||
"setup": [
|
||||
[
|
||||
"$IP link del dev $DUMMY",
|
||||
0,
|
||||
1
|
||||
]
|
||||
],
|
||||
"cmdUnderTest": "$IP link add dev $DUMMY txqueuelen 500000 type dummy",
|
||||
"expExitCode": "2",
|
||||
"verifyCmd": "$IP -o link show",
|
||||
"matchPattern": "^[0-9]+: $DUMMY",
|
||||
"matchCount": "0",
|
||||
"teardown": []
|
||||
},
|
||||
{
|
||||
"id": "31ac",
|
||||
"name": "Reject veth peer nest tx_queue_len above S16_MAX at create",
|
||||
"category": [
|
||||
"qdisc",
|
||||
"pfifo_fast"
|
||||
],
|
||||
"plugins": {
|
||||
"requires": "nsPlugin"
|
||||
},
|
||||
"setup": [
|
||||
[
|
||||
"$IP link del dev $DEV1",
|
||||
0,
|
||||
1
|
||||
]
|
||||
],
|
||||
"cmdUnderTest": "$IP link add dev $DEV1 type veth peer name $DEV0 txqueuelen 500000",
|
||||
"expExitCode": "2",
|
||||
"verifyCmd": "$IP -o link show",
|
||||
"matchPattern": "^[0-9]+: $DEV1",
|
||||
"matchCount": "0",
|
||||
"teardown": []
|
||||
},
|
||||
{
|
||||
"id": "b567",
|
||||
"name": "Accept veth peer nest tx_queue_len within S16_MAX",
|
||||
"category": [
|
||||
"qdisc",
|
||||
"pfifo_fast"
|
||||
],
|
||||
"plugins": {
|
||||
"requires": "nsPlugin"
|
||||
},
|
||||
"setup": [
|
||||
[
|
||||
"$IP link del dev $DEV1",
|
||||
0,
|
||||
1
|
||||
]
|
||||
],
|
||||
"cmdUnderTest": "$IP link add dev $DEV1 txqueuelen 100 type veth peer name $DEV0 txqueuelen 200",
|
||||
"expExitCode": "0",
|
||||
"verifyCmd": "$IP link show",
|
||||
"matchPattern": "qlen (100|200)$",
|
||||
"matchCount": "2",
|
||||
"teardown": [
|
||||
[
|
||||
"$IP link del dev $DEV0",
|
||||
0,
|
||||
1
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user