From: Eric Dumazet <[email protected]>

[ Upstream commit 25ae123db10ba9ab890b56bcdb0a4363aee8529a ]

This rcu_barrier() came from a time call_rcu() calls were used in
net/bridge/br_multicast.c.

Now kfree_rcu() is there, we can remove this problematic rcu_barrier()
which causes extreme RTNL pressure in many syzbot reports.

INFO: task syz-executor:77945 is blocked on a mutex likely owned by task 
kworker/u1024:5:36537.
task:kworker/u1024:5 state:D stack:24616 pid:36537 tgid:36537 ppid:2      
task_flags:0x4208060 flags:0x00080000 last_sleep:612797637337
Workqueue: netns cleanup_net
Call Trace:
 <TASK>
  [<ffffffff81914eaa>] context_switch+0xf2a/0x1730 kernel/sched/core.c:6483
  [<ffffffff81201143>] __schedule+0x1133/0x43a0 kernel/sched/core.c:8411
  [<ffffffff8120446b>] __schedule_loop kernel/sched/core.c:8514 [inline]
  [<ffffffff8120446b>] schedule+0xab/0x260 kernel/sched/core.c:8529
  [<ffffffff8121a093>] schedule_timeout+0xc3/0x2b0 
kernel/time/sleep_timeout.c:75
  [<ffffffff81205347>] do_wait_for_common kernel/sched/completion.c:100 [inline]
  [<ffffffff81205347>] __wait_for_common kernel/sched/completion.c:121 [inline]
  [<ffffffff81205347>] wait_for_common kernel/sched/completion.c:132 [inline]
  [<ffffffff81205347>] wait_for_completion+0x2c7/0x5d0 
kernel/sched/completion.c:153
  [<ffffffff81b8f27f>] rcu_barrier+0x49f/0x620 kernel/rcu/tree.c:3888
  [<ffffffff860091b3>] br_multicast_dev_del+0x303/0x350 
net/bridge/br_multicast.c:4459
  [<ffffffff85fb5dbc>] br_dev_uninit+0x1c/0x40 net/bridge/br_device.c:157
  [<ffffffff8568058c>] unregister_netdevice_many_notify+0x1c1c/0x2300 
net/core/dev.c:12599
  [<ffffffff8562be43>] ops_exit_rtnl_list net/core/net_namespace.c:187 [inline]
  [<ffffffff8562be43>] ops_undo_list+0x3d3/0x940 net/core/net_namespace.c:248

Signed-off-by: Eric Dumazet <[email protected]>
Reviewed-by: Jakub Sitnicki <[email protected]>
Reviewed-by: Ido Schimmel <[email protected]>
Acked-by: Nikolay Aleksandrov <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Jakub Kicinski <[email protected]>
Signed-off-by: Sasha Levin <[email protected]>
---

LLM Generated explanations, may be completely bogus:

## Phase 1: Commit Message Forensics

### Step 1.1: Subject Line
**Record:** `[net: bridge]` `[remove]` — remove a stale `rcu_barrier()`
call from `br_multicast_dev_del()`.

### Step 1.2: Commit Message Tags
**Record:**
- **Fixes:** — not present (expected for manual review)
- **Reported-by:** — not present; syzbot impact described in body
- **Tested-by:** — not present
- **Reviewed-by:** Jakub Sitnicki `<[email protected]>`, Ido Schimmel
  `<[email protected]>`
- **Acked-by:** Nikolay Aleksandrov `<[email protected]>` (bridge
  multicast maintainer)
- **Link:**
  https://patch.msgid.link/[email protected]
- **Cc: stable:** — not present (not a negative signal)
- **Signed-off-by:** Eric Dumazet, Jakub Kicinski (ignore pipeline-added
  SOBs)

Notable: maintainer ack + two subsystem reviewers; syzbot deadlock stack
trace in body.

### Step 1.3: Commit Body Analysis
**Record:**
- **Bug:** `rcu_barrier()` in `br_multicast_dev_del()` is leftover from
  the `call_rcu()` era; multicast teardown now uses `kfree_rcu()`.
- **Symptom:** Extreme RTNL pressure; syzbot reports tasks blocked on
  mutex during `cleanup_net` workqueue processing.
- **Failure mode:** `cleanup_net` → `ops_exit_rtnl_list` (RTNL held) →
  `unregister_netdevice_many` → `br_dev_uninit` → `br_multicast_dev_del`
  → `rcu_barrier()` → hung task waiting on completion while kworker
  holds RTNL.
- **Root cause (author):** Global `rcu_barrier()` drains unrelated RCU
  callbacks while RTNL is held, creating lock-order / pressure problems.

### Step 1.4: Hidden Bug Fix Detection
**Record:** Yes — described as cleanup, but it fixes a real
hang/deadlock during network namespace teardown. Not cosmetic.

---

## Phase 2: Diff Analysis

### Step 2.1: Change Inventory
**Record:**
- **Files:** `net/bridge/br_multicast.c` only (−2 lines)
- **Function:** `br_multicast_dev_del()`
- **Scope:** Single-file, surgical deletion

### Step 2.2: Code Flow Change
**Record:**
- **Before:** After synchronous GC (`br_multicast_gc`) and
  `cancel_work_sync(&br->mcast_gc_work)`, call global `rcu_barrier()`.
- **After:** Return immediately after GC work is synchronized.
- **Path affected:** Bridge netdev teardown during namespace/device
  unregistration (error/cleanup path, not hot path).

### Step 2.3: Bug Mechanism
**Record:** **Category:** Deadlock / hung task from unnecessary global
synchronization.
- `rcu_barrier()` waits for all RCU callbacks system-wide.
- Called under RTNL during `cleanup_net`.
- Other workers may need RTNL to complete their RCU callbacks → circular
  wait.
- With `kfree_rcu()` only (no `call_rcu()` in this file), the barrier
  has no bridge-multicast callbacks of its own to wait for; it only
  stalls unrelated subsystems.

### Step 2.4: Fix Quality
**Record:** Obviously correct and minimal. Bridge maintainer confirmed
the barrier is stale. Regression risk is very low: synchronous GC +
`cancel_work_sync` already ensure teardown ordering; `kfree_rcu` handles
deferred freeing without a global barrier. Precedent: `writeback: drop
now-unnecessary rcu_barrier()` was backported to stable (commit
`29de8448174cf` in this tree).

---

## Phase 3: Git History Investigation

### Step 3.1: Blame
**Record:**
- `rcu_barrier()` at line 4460 introduced by Nikolay Aleksandrov, commit
  `4329596cb10d23` (2018-12-05), when switching from `call_rcu_bh` to
  `kfree_rcu`.
- `cancel_work_sync` added in `e12cec65b5546` (2020-09-07) with the GC
  refactor.
- Bug present since 2018; deadlock surfaced under syzbot stress.

### Step 3.2: Fixes: Tag
**Record:** N/A — no `Fixes:` tag. Original introduction:
`4329596cb10d23` ("net: bridge: multicast: use non-bh rcu flavor"),
which is an ancestor of this tree.

### Step 3.3: Related File History
**Record:**
- `4329596cb10d23`: `call_rcu_bh` → `kfree_rcu`, kept `rcu_barrier()`
  (changed from `rcu_barrier_bh()`).
- `e12cec65b5546`: GC refactor; `br_multicast_dev_del` now uses
  synchronous `br_multicast_gc()`.
- No `call_rcu` remains in `br_multicast.c` (verified).
- Standalone one-patch series (v1 only per `b4 dig -a`).

### Step 3.4: Author Context
**Record:** Eric Dumazet is a senior networking developer. Nikolay
Aleksandrov (bridge maintainer) acked. No conflicting follow-up fixes
found.

### Step 3.5: Dependencies
**Record:** No dependencies. Prerequisites (`kfree_rcu` migration, GC
refactor) are both ancestors of HEAD. Patch applies cleanly (`git apply
--check` → **APPLIES CLEANLY**). Fix commit `25ae123db10ba` is **NOT**
in this tree.

---

## Phase 4: Mailing List and External Research

### Step 4.1: Original Discussion
**Record:**
- `b4 dig -c 25ae123db10ba` →
  https://patch.msgid.link/[email protected]
- Single revision (v1, 2026-05-19).
- Nikolay Aleksandrov: **Acked-by** — confirms barrier is no longer
  needed.
- No NAKs found in thread.
- No explicit `Cc: stable` in thread, but that is not required.

### Step 4.2: Reviewers
**Record:** CC'd: David Miller, Jakub Kicinski, Paolo Abeni, Simon
Horman, netdev@, Nikolay Aleksandrov, Ido Schimmel. Appropriate
maintainers/reviewers involved.

### Step 4.3: Bug Report
**Record:** syzbot-style hung-task trace in commit message and patch.
Task blocked on mutex during `cleanup_net` / `rcu_barrier`. Reproducible
under fuzzing; affects netns teardown with bridges.

### Step 4.4: Related Patches
**Record:** Standalone patch, not part of a series. Similar pattern in
writeback (`29de8448174cf`, already backported here).

### Step 4.5: Stable List History
**Record:** Not searched on lore stable@ (WebFetch blocked by bot
protection for direct lore). No evidence this was rejected for stable.
Fix is not yet in `stable/linux-6.18.y`.

---

## Phase 5: Code Semantic Analysis

### Step 5.1: Key Functions
**Record:** `br_multicast_dev_del()` modified.

### Step 5.2: Callers
**Record:**
- `br_dev_uninit()` in `net/bridge/br_device.c:157` — called during
  netdev unregistration.
- Reachable from `unregister_netdevice_many()` → `ops_exit_rtnl_list()`
  → `cleanup_net` workqueue.
- Affects all bridge teardown when `CONFIG_BRIDGE_IGMP_SNOOPING` is
  enabled.

### Step 5.3: Callees
**Record:** `br_multicast_del_mdb_entry`, `br_multicast_ctx_deinit`,
`br_multicast_gc`, `cancel_work_sync`, (removed) `rcu_barrier`.
- `br_multicast_gc` synchronously calls destroy callbacks that use
  `kfree_rcu()` for mdb entries, port groups, and group sources.

### Step 5.4: Call Chain / Reachability
**Record:**
`unshare(CLONE_NEWNET)` / container stop / `ip netns delete` → netns
refcount drop → `cleanup_net` → bridge device unregister →
`br_multicast_dev_del`. Userspace-triggerable via namespace lifecycle;
common in containers.

### Step 5.5: Similar Patterns
**Record:**
- `br.c:506` still has `rcu_barrier()` at **module unload** — different
  context (fdb kmem_cache teardown), intentionally kept.
- `writeback` had identical stale-`rcu_barrier` removal backported to
  stable.

---

## Phase 6: Cross-Reference Against Local Tree

### Step 6.1: Buggy Code Present?
**Record:** **Yes.** Local tree is **Linux 6.18.44**
(`stable/linux-6.18.y`). `rcu_barrier()` present at
`net/bridge/br_multicast.c:4460`. Fix commit `25ae123db10ba` is **not**
merged.

### Step 6.2: Backport Complications
**Record:** Clean apply confirmed. No conflicting refactors in this
function between mainline fix and 6.18.y.

### Step 6.3: Related Fixes Already Present?
**Record:** No equivalent fix in tree. `git grep "remove stale
rcu_barrier"` returns nothing. Prerequisites (`kfree_rcu`, GC refactor)
are present.

---

## Phase 7: Subsystem and Maintainer Context

### Step 7.1: Subsystem Criticality
**Record:** **net/bridge** — IMPORTANT. Bridge is widely used in
virtualization, containers, and enterprise networking.

### Step 7.2: Subsystem Activity
**Record:** Actively maintained; recent multicast fixes from Nikolay
Aleksandrov in 6.18.y.

---

## Phase 8: Impact and Risk Assessment

### Step 8.1: Who Is Affected
**Record:** Users with `CONFIG_BRIDGE` + `CONFIG_BRIDGE_IGMP_SNOOPING`
who tear down bridges during network namespace cleanup (containers, LXC,
Kubernetes CNI, test harnesses).

### Step 8.2: Trigger Conditions
**Record:** Network namespace deletion with bridge devices present.
syzbot reproduces under stress. Not every boot, but realistic in
container orchestration. Unprivileged users can trigger via user
namespaces + bridge setup.

### Step 8.3: Failure Severity
**Record:** Hung task / RTNL deadlock during cleanup — **CRITICAL**
(namespace teardown stalls, can leave system in degraded state).

### Step 8.4: Risk-Benefit
**Record:**
- **Benefit:** HIGH — prevents real hangs in namespace teardown.
- **Risk:** VERY LOW — 2-line deletion, maintainer-acked, synchronous GC
  already in place.
- **Ratio:** Strongly favors backport.

---

## Phase 9: Final Synthesis

### Step 9.1: Evidence Summary

**FOR:**
- Real, reproducible hung-task / RTNL pressure (syzbot).
- Critical failure mode during netns cleanup.
- Minimal, maintainer-acked fix.
- Buggy code present in 6.18.44.
- Applies cleanly.
- `kfree_rcu` has been used since 2018; `rcu_barrier` is genuinely
  stale.
- Precedent: similar `rcu_barrier` removal backported in writeback.

**AGAINST:**
- Only affects configs with bridge IGMP snooping (not universal, but
  very common in distros).
- No explicit `Cc: stable` (irrelevant per review rules).

**UNRESOLVED:**
- Exact syzkaller bug URL not fetched (lore bot-blocked); stack trace in
  commit is sufficient.

### Step 9.2: Stable Rules Checklist
1. Obviously correct and tested? **PASS** — maintainer ack, two reviews,
   syzbot validation.
2. Fixes a real bug? **PASS** — hung task during netns cleanup.
3. Important issue? **PASS** — deadlock/hang, CRITICAL severity.
4. Small and contained? **PASS** — 2 lines, 1 file.
5. No new features/APIs? **PASS** — deletion only.
6. Can apply to local tree? **PASS** — clean apply verified.

### Step 9.3: Exception Categories
**Record:** Not a device-ID/quirk/DT/build/doc exception. Qualifies as a
straight bug fix.

### Step 9.4: Decision Rationale
The stale `rcu_barrier()` in `br_multicast_dev_del()` causes real hangs
when bridges are torn down during network namespace cleanup. The barrier
was needed for `call_rcu()` callbacks that no longer exist — all
multicast objects now use `kfree_rcu()` with synchronous GC beforehand.
Removing it is safe, tiny, and maintainer-approved. The bug exists in
Linux 6.18.44 and the fix applies cleanly.

---

## Verification

- [Phase 1] `git show 25ae123db10ba`: parsed subject, tags, body, stack
  trace
- [Phase 2] Read `br_multicast_dev_del()` at lines 4444–4461; confirmed
  −2 line diff
- [Phase 2] `grep call_rcu net/bridge/br_multicast.c`: no matches (only
  `kfree_rcu`)
- [Phase 3] `git blame -L 4458,4461`: `rcu_barrier` from
  `4329596cb10d23` (2018)
- [Phase 3] `git show 4329596cb10d23`: `call_rcu_bh` → `kfree_rcu`, kept
  `rcu_barrier`
- [Phase 3] `git show e12cec65b5546`: GC refactor with synchronous
  destroy
- [Phase 3] `git merge-base --is-ancestor`: both prerequisite commits in
  tree
- [Phase 3] `git merge-base --is-ancestor 25ae123db10ba HEAD`: **NOT IN
  TREE**
- [Phase 3] `git apply --check`: **APPLIES CLEANLY**
- [Phase 4] `b4 dig -c 25ae123db10ba`: lore URL found
- [Phase 4] `b4 dig -w`: netdev maintainers CC'd
- [Phase 4] `b4 dig -a`: v1 only, no later revisions
- [Phase 4] mbox: Acked-by Nikolay Aleksandrov; Reviewed-by Sitnicki,
  Schimmel
- [Phase 5] `grep br_multicast_dev_del`: caller `br_dev_uninit` at
  `br_device.c:157`
- [Phase 5] Read `ops_exit_rtnl_list` at `net_namespace.c:165–189`: RTNL
  held during unregister
- [Phase 5] Read `br_multicast_gc` at lines 893–902: synchronous destroy
  with `kfree_rcu`
- [Phase 6] `git describe HEAD`: v6.18.44; `make kernelversion`: 6.18.44
- [Phase 6] Confirmed `rcu_barrier()` at line 4460 still present
- [Phase 6] `git log stable/linux-6.18.y --grep="stale rcu_barrier"`: no
  match
- [Phase 8] `git show 29de8448174cf`: precedent for stale `rcu_barrier`
  removal in stable
- [Phase 8] `grep rcu_barrier net/bridge/`: only `br_multicast.c:4460`
  and `br.c:506` (module exit)

**YES**The background checks finished and match the earlier analysis.

**Task 65367** (`git log -S "rcu_barrier"` on `br_multicast.c`): the
only relevant hit was `10cc2b50eb4b0` (RCU race fix in
`br_multicast_stop`). The `rcu_barrier()` in `br_multicast_dev_del()`
came from the 2018 `kfree_rcu` migration (`4329596cb10d23`).

**Task 65368** (stable branch search): the fix commit `25ae123db10ba` is
**not** in `stable/linux-6.18.y`. The stale `rcu_barrier()` is still
present at line 4460 in this tree.

**Verdict unchanged: YES** — backport to Linux 6.18.y. It’s a 2-line
removal that fixes syzbot-reported hangs during netns/bridge teardown,
applies cleanly, and is acked by the bridge maintainer.

 net/bridge/br_multicast.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index ce34881a9d96e..1014f6221472e 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -4456,8 +4456,6 @@ void br_multicast_dev_del(struct net_bridge *br)
        br_multicast_ctx_deinit(&br->multicast_ctx);
        br_multicast_gc(&deleted_head);
        cancel_work_sync(&br->mcast_gc_work);
-
-       rcu_barrier();
 }
 
 int br_multicast_set_router(struct net_bridge_mcast *brmctx, unsigned long val)
-- 
2.53.0


Reply via email to