From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 928FD3E1CEA; Mon, 20 Apr 2026 13:24:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776691473; cv=none; b=gkM1H6dgHC7NdpGau/6+MVM5NxTULePqv7EouU5izmiH60cwT1X28gGZzHIVfRcnMIWSwcXniDtsW9nUbpNKf2Ez0sp4FtoCd3bTE5iC1lAE1cd1GoOyhxe+yP84uj/isp0+qkbb4nGjqbdG5gAYZTwRvMYa7Hy46rmSIoqoX5k= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1776691473; c=relaxed/simple; bh=+27N1xGHeU6Dmf1YeZVJF54/zCyaS9Z9RMo0NGp5aiM=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=aagR+lqgWyTDdAfwt0oyyabkCmVe7+jbdw5ha5sG9TM7UVXWgci5pbQWYe2Mu+g7uvZawAc9OjbUEiaZg8kJIaMSKH/7qJvhOD4Tb2vmFSCZWX3ab2QnvX8/ZTFLnXu484tIt4bSaXSJb+SK8N1c8RRhVB/bsoTSsK7jzmKZM4s= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=FmI32t3N; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="FmI32t3N" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 67E02C2BCB8; Mon, 20 Apr 2026 13:24:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1776691473; bh=+27N1xGHeU6Dmf1YeZVJF54/zCyaS9Z9RMo0NGp5aiM=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FmI32t3NtflQ1piDTJ5uR5YeC+hLydS6f5ExTOCpLsOEWGor27s+O7PufS7O/RmdL qrA/GWrN6kQyu5rc7m3lNhhG1jRndb1EFNrVMn53DYA7LxEin+OR/5ioqA8VImL4vW xoo425jriLW2PbKXGoP5I5gl7xYvh4HqC+Ob9CH6h4Zax7udKgi5GmlTaiXHshgFvP Fuw3Dk5Wxe2SYgGmkXTD4NR1fOaw6B0GuD/4wicB6s2uRcoY59JChrEF3m1eJq9Nxo jpT1IOe2jAHSNxAuCsGGvkaBv+6hW+Q/9yggJdENHykAExcko6ZYlHlFkBIBAAlHcD Z5ZM+mhoG62Iw== From: Sasha Levin To: patches@lists.linux.dev, stable@vger.kernel.org Cc: Paolo Abeni , David Ahern , Jakub Kicinski , Sasha Levin , davem@davemloft.net, edumazet@google.com, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH AUTOSEL 7.0-6.6] ipv6: move IFA_F_PERMANENT percpu allocation in process scope Date: Mon, 20 Apr 2026 09:17:24 -0400 Message-ID: <20260420132314.1023554-50-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20260420132314.1023554-1-sashal@kernel.org> References: <20260420132314.1023554-1-sashal@kernel.org> Precedence: bulk X-Mailing-List: patches@lists.linux.dev List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-stable: review X-Patchwork-Hint: Ignore X-stable-base: Linux 7.0 Content-Transfer-Encoding: 8bit From: Paolo Abeni [ Upstream commit 8e6405f8218b3f412d36b772318e94d589513eba ] Observed at boot time: CPU: 43 UID: 0 PID: 3595 Comm: (t-daemon) Not tainted 6.12.0 #1 Call Trace: dump_stack_lvl+0x4e/0x70 pcpu_alloc_noprof.cold+0x1f/0x4b fib_nh_common_init+0x4c/0x110 fib6_nh_init+0x387/0x740 ip6_route_info_create+0x46d/0x640 addrconf_f6i_alloc+0x13b/0x180 addrconf_permanent_addr+0xd0/0x220 addrconf_notify+0x93/0x540 notifier_call_chain+0x5a/0xd0 __dev_notify_flags+0x5c/0xf0 dev_change_flags+0x54/0x70 do_setlink+0x36c/0xce0 rtnl_setlink+0x11f/0x1d0 rtnetlink_rcv_msg+0x142/0x3f0 netlink_rcv_skb+0x50/0x100 netlink_unicast+0x242/0x390 netlink_sendmsg+0x21b/0x470 __sys_sendto+0x1dc/0x1f0 __x64_sys_sendto+0x24/0x30 do_syscall_64+0x7d/0x160 entry_SYSCALL_64_after_hwframe+0x76/0x7e RIP: 0033:0x7f5c3852f127 Code: 0c 00 f7 d8 64 89 02 48 c7 c0 ff ff ff ff eb b8 0f 1f 00 f3 0f 1e fa 80 3d 85 ef 0c 00 00 41 89 ca 74 10 b8 2c 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 71 c3 55 48 83 ec 30 44 89 4c 24 2c 4c 89 44 RSP: 002b:00007ffe86caf4c8 EFLAGS: 00000202 ORIG_RAX: 000000000000002c RAX: ffffffffffffffda RBX: 0000556c5cd93210 RCX: 00007f5c3852f127 RDX: 0000000000000020 RSI: 0000556c5cd938b0 RDI: 0000000000000003 RBP: 00007ffe86caf5a0 R08: 00007ffe86caf4e0 R09: 0000000000000080 R10: 0000000000000000 R11: 0000000000000202 R12: 0000556c5cd932d0 R13: 00000000021d05d1 R14: 00000000021d05d1 R15: 0000000000000001 IFA_F_PERMANENT addresses require the allocation of a bunch of percpu pointers, currently in atomic scope. Similar to commit 51454ea42c1a ("ipv6: fix locking issues with loops over idev->addr_list"), move fixup_permanent_addr() outside the &idev->lock scope, and do the allocations with GFP_KERNEL. With such change fixup_permanent_addr() is invoked with the BH enabled, and the ifp lock acquired there needs the BH variant. Note that we don't need to acquire a reference to the permanent addresses before releasing the mentioned write lock, because addrconf_permanent_addr() runs under RTNL and ifa removal always happens under RTNL, too. Also the PERMANENT flag is constant in the relevant scope, as it can be cleared only by inet6_addr_modify() under the RTNL lock. Reviewed-by: David Ahern Signed-off-by: Paolo Abeni Link: https://patch.msgid.link/46a7a030727e236af2dc7752994cd4f04f4a91d2.1775658924.git.pabeni@redhat.com Signed-off-by: Jakub Kicinski Signed-off-by: Sasha Levin --- LLM Generated explanations, may be completely bogus: Now I have all the information needed. Let me compile my analysis. --- ## PHASE 1: COMMIT MESSAGE FORENSICS ### Step 1.1: PARSE THE SUBJECT LINE - **Subsystem**: ipv6 (networking) - **Action verb**: "move" - restructuring allocation scope - **Summary**: Move IFA_F_PERMANENT percpu allocation from atomic to process (GFP_KERNEL) scope - Record: [ipv6] [move] [Change percpu allocation from GFP_ATOMIC to GFP_KERNEL by restructuring lock scope] ### Step 1.2: PARSE ALL COMMIT MESSAGE TAGS - **Reviewed-by**: David Ahern - former networking subsystem maintainer, very authoritative - **Signed-off-by**: Paolo Abeni - current net-next maintainer, author - **Link**: https://patch.msgid.link/46a7a030727e236af2dc7752994cd4f04f4 a91d2.1775658924.git.pabeni@redhat.com - **Signed-off-by**: Jakub Kicinski - committer, net/net-next maintainer - No Fixes: tag (expected for candidates) - No Cc: stable (expected) - Record: Reviewed by David Ahern, authored by Paolo Abeni (net-next co- maintainer), committed by Jakub Kicinski. Applied to net-next (not net). ### Step 1.3: ANALYZE THE COMMIT BODY TEXT - **Bug described**: At boot time, `pcpu_alloc_noprof.cold` is triggered during IPv6 permanent address route setup. This is the cold (warning/failure) path of per-cpu allocation. - **Symptom**: GFP_ATOMIC percpu allocation failure when setting up permanent IPv6 addresses during NETDEV_UP handling. The call trace shows: `addrconf_permanent_addr -> fixup_permanent_addr -> addrconf_f6i_alloc -> ip6_route_info_create -> fib6_nh_init -> fib_nh_common_init -> pcpu_alloc_noprof.cold` - **Root cause**: `addrconf_permanent_addr()` holds `idev->lock` (write spinlock with BH disabled) while calling `fixup_permanent_addr()`, forcing GFP_ATOMIC for all allocations inside. Per-cpu allocations with GFP_ATOMIC are unreliable, especially on systems with many CPUs. - **Kernel version**: Observed on 6.12.0 with 43+ CPUs - Record: Real boot-time allocation failure. IPv6 permanent address setup fails when percpu allocation with GFP_ATOMIC fails, causing the address to be dropped. ### Step 1.4: DETECT HIDDEN BUG FIXES This IS a bug fix despite being described as "move". When GFP_ATOMIC percpu allocation fails, `fixup_permanent_addr()` returns an error, and `addrconf_permanent_addr()` then DROPS the IPv6 address (`ipv6_del_addr`). Users lose permanent IPv6 addresses at boot. - Record: Yes, this is a real bug fix. The "move" language hides the fact that GFP_ATOMIC failures cause IPv6 addresses to be lost. ## PHASE 2: DIFF ANALYSIS ### Step 2.1: INVENTORY THE CHANGES - **File**: `net/ipv6/addrconf.c` - 19 lines added, 12 removed (net +7) - **Functions modified**: `fixup_permanent_addr()` and `addrconf_permanent_addr()` - **Scope**: Single-file, well-contained change in two related functions - Record: Single file, ~31 lines total change, two functions in same call chain. ### Step 2.2: UNDERSTAND THE CODE FLOW CHANGE **Hunk 1** (`fixup_permanent_addr`): - Before: GFP_ATOMIC for route allocation, plain spin_lock/unlock for ifp->lock - After: GFP_KERNEL for route allocation, spin_lock_bh/unlock_bh (needed because BH is now enabled) - GFP_ATOMIC -> GFP_KERNEL in both `addrconf_f6i_alloc()` and `addrconf_prefix_route()` calls **Hunk 2** (`addrconf_permanent_addr`): - Before: Holds `idev->lock` throughout iteration and calls `fixup_permanent_addr()` inside the lock - After: Builds temporary list of PERMANENT addresses while holding lock, releases lock, then iterates temporary list calling `fixup_permanent_addr()` without lock held - Uses existing `if_list_aux` infrastructure (same pattern as commit 51454ea42c1a) - Adds ASSERT_RTNL() for safety ### Step 2.3: IDENTIFY THE BUG MECHANISM **Category**: Allocation failure in atomic context / resource setup failure - The bug is that percpu allocations (via `alloc_percpu_gfp()` in `fib_nh_common_init()`) with GFP_ATOMIC can fail, especially on high- CPU-count systems - When the allocation fails, the permanent IPv6 address is dropped - The fix moves the work outside the spinlock so GFP_KERNEL can be used - Record: Allocation failure bug. GFP_ATOMIC percpu allocation in fib_nh_common_init fails -> route creation fails -> permanent IPv6 address dropped. ### Step 2.4: ASSESS THE FIX QUALITY - **Obviously correct**: Yes - the if_list_aux pattern is proven (already used in `addrconf_ifdown` and `dev_forward_change`) - **Minimal/surgical**: Yes - single file, two functions, well-contained - **Regression risk**: Low - the lock restructuring is safe per RTNL protection. The spin_lock -> spin_lock_bh change is correct because BH is now enabled. - **Red flags**: None. The locking argument is well-explained in the commit message (RTNL protects against concurrent ifa removal). - Record: High quality fix. Proven pattern, correct BH handling, well- documented safety argument. ## PHASE 3: GIT HISTORY INVESTIGATION ### Step 3.1: BLAME THE CHANGED LINES - `fixup_permanent_addr()` introduced by f1705ec197e7 (Feb 2016, "net: ipv6: Make address flushing on ifdown optional") in v4.5 - The buggy GFP_ATOMIC has been present since this code was created - `addrconf_permanent_addr()` also from the same commit - Record: Buggy code introduced in v4.5 (f1705ec197e7, 2016). Present in ALL stable trees. ### Step 3.2: FOLLOW THE FIXES TAG No Fixes: tag present (expected). ### Step 3.3: CHECK FILE HISTORY - fd63f185979b0 ("ipv6: prevent possible UaF in addrconf_permanent_addr()") is a prerequisite - already in v7.0 - 51454ea42c1a ("ipv6: fix locking issues with loops over idev->addr_list") introduced the if_list_aux pattern - in v5.19+ - Record: Two prerequisites identified, both present in v7.0. ### Step 3.4: CHECK THE AUTHOR - Paolo Abeni is the net-next co-maintainer - maximum authority for networking code - David Ahern reviewed it - he's the original author of much of this code - Record: Author is subsystem co-maintainer. Reviewer is the original code author. ### Step 3.5: CHECK FOR DEPENDENCIES - Requires `if_list_aux` field in `inet6_ifaddr` (from commit 51454ea42c1a, v5.19+) - present in v7.0 - Requires fd63f185979b0 UaF fix (already in v7.0) - Requires `d465bd07d16e3` gfp_flags passdown through `ip6_route_info_create_nh()` - present in v7.0 - The diff applies cleanly against v7.0 (verified) - Record: All dependencies satisfied in v7.0. Clean apply confirmed. ## PHASE 4: MAILING LIST RESEARCH ### Step 4.1: ORIGINAL PATCH DISCUSSION - Found via b4 am: Applied to netdev/net-next.git (main) as commit 8e6405f8218b - This is v2 of the patch (v1 was the initial UaF fix that became fd63f185979b0) - Applied by Jakub Kicinski - Submitted to net-next, not net - Record: v2 patch, applied to net-next. Upstream commit is 8e6405f8218b. ### Step 4.2: REVIEWERS - Paolo Abeni (author, net-next co-maintainer) - David Ahern (reviewer, original code author) - Jakub Kicinski (committer, net maintainer) - All key networking maintainers involved - Record: Maximum authority review chain. ### Step 4.3: BUG REPORT - The stack trace in the commit is from a real system (6.12.0, 43+ CPUs) - `pcpu_alloc_noprof.cold` is the failure/warning path for percpu allocations - Record: Real-world observation on production system. ### Step 4.4: SERIES CONTEXT - This is standalone (v2 of a single patch), not part of a multi-patch series - Record: Standalone fix. ### Step 4.5: STABLE DISCUSSION - No specific stable discussion found - Note: applied to net-next, not net, suggesting author didn't consider it urgent ## PHASE 5: CODE SEMANTIC ANALYSIS ### Step 5.1-5.4: FUNCTION ANALYSIS - `addrconf_permanent_addr()` is called from `addrconf_notify()` on `NETDEV_UP` events - This is the boot-time path for restoring permanent IPv6 addresses when interfaces come up - Call chain: `addrconf_notify() -> addrconf_permanent_addr() -> fixup_permanent_addr() -> addrconf_f6i_alloc() -> ... -> fib_nh_common_init() -> alloc_percpu_gfp()` - The allocation in `fib_nh_common_init()` is `alloc_percpu_gfp(struct rtable __rcu *, gfp_flags)` - this allocates per-CPU pointers - On high-CPU systems, percpu allocations are larger and more likely to fail with GFP_ATOMIC - This path runs on every NETDEV_UP event for every interface - Record: Code is in a common boot path. Allocation failure causes permanent address loss. ## PHASE 6: STABLE TREE ANALYSIS ### Step 6.1: BUGGY CODE IN STABLE TREES - The buggy GFP_ATOMIC code exists since v4.5 (f1705ec197e7) - Present in ALL active stable trees - Record: Bug present in all stable trees from v4.5 onward. ### Step 6.2: BACKPORT COMPLICATIONS - For 7.0: Clean apply (verified via `git diff v7.0 8e6405f8218b`) - For 6.12 and older: Would need checking for gfp_flags passdown chain - Record: Clean apply for 7.0.y. May need adjustment for older trees. ### Step 6.3: RELATED FIXES IN STABLE - None found for this specific GFP_ATOMIC issue - Record: No related fix already in stable. ## PHASE 7: SUBSYSTEM CONTEXT ### Step 7.1: SUBSYSTEM CRITICALITY - **Subsystem**: net/ipv6 (networking, IPv6 address configuration) - **Criticality**: IMPORTANT - IPv6 connectivity affects many users, especially on servers - Record: IMPORTANT subsystem. IPv6 permanent address loss at boot affects server connectivity. ### Step 7.2: SUBSYSTEM ACTIVITY - `net/ipv6/addrconf.c` has 106+ commits between v6.6 and v7.0 - Actively maintained area - Record: Very active subsystem. ## PHASE 8: IMPACT AND RISK ASSESSMENT ### Step 8.1: WHO IS AFFECTED - Systems with many CPUs (43+ shown in trace) using IPv6 permanent addresses - More likely on servers/enterprise systems - Record: Affects multi-CPU systems with IPv6, primarily servers. ### Step 8.2: TRIGGER CONDITIONS - Triggered at boot time during interface bring-up (NETDEV_UP) - Also triggered whenever `rtnl_setlink` brings an interface up - More likely under memory pressure or on high-CPU-count systems - Record: Triggered at boot/interface-up. More common on high-CPU systems. ### Step 8.3: FAILURE MODE SEVERITY - When triggered: permanent IPv6 address is DROPPED from the interface - This means IPv6 connectivity loss for that address - Not a crash, but an operational failure (lost connectivity) - Record: Severity HIGH - IPv6 address loss leads to connectivity failure. ### Step 8.4: RISK-BENEFIT RATIO - **Benefit**: Prevents IPv6 address loss on multi-CPU systems at boot - **Risk**: Low - proven pattern (if_list_aux), well-reviewed, single file - Record: Benefit HIGH / Risk LOW = favorable ratio. ## PHASE 9: FINAL SYNTHESIS ### Step 9.1: EVIDENCE COMPILATION **FOR backporting:** - Fixes real boot-time IPv6 address loss on multi-CPU systems - Stack trace from a real 6.12.0 deployment - Written by net-next co-maintainer, reviewed by original code author - Uses proven if_list_aux pattern already in the same file - Single file, ~31 lines, well-contained - Bug present since v4.5 - affects all stable trees - Clean apply against v7.0 **AGAINST backporting:** - Applied to net-next, not net (author didn't consider it critical) - No Fixes: tag or Cc: stable from author - Structural change (lock restructuring), not a one-line fix - Not a crash - "just" drops IPv6 addresses when allocation fails **UNRESOLVED:** - Exact failure rate on real systems unknown (depends on CPU count and memory state) - Could not access lore.kernel.org for full review discussion (Anubis protection) ### Step 9.2: STABLE RULES CHECKLIST 1. Obviously correct and tested? **YES** - proven pattern, reviewed by original code author and subsystem maintainer 2. Fixes a real bug? **YES** - GFP_ATOMIC percpu allocation failure causes IPv6 address loss 3. Important issue? **YES** - IPv6 connectivity loss at boot on multi- CPU systems 4. Small and contained? **YES** - single file, ~31 lines, two functions in same call chain 5. No new features or APIs? **YES** - pure internal restructuring 6. Can apply to stable? **YES** - clean apply to v7.0 verified ### Step 9.3: EXCEPTION CATEGORIES Not an exception category - this is a standard bug fix. ### Step 9.4: DECISION The fix addresses a real operational issue (IPv6 permanent address loss at boot due to GFP_ATOMIC percpu allocation failure). While it was routed to net-next rather than net, the bug has real-world impact on multi-CPU systems. The fix is well-reviewed by the most authoritative people for this code, uses a proven pattern, and applies cleanly to v7.0. ## Verification - [Phase 1] Parsed tags: Reviewed-by David Ahern, Signed-off-by Paolo Abeni and Jakub Kicinski. No Fixes/Cc-stable (expected). - [Phase 2] Diff analysis: GFP_ATOMIC -> GFP_KERNEL in fixup_permanent_addr(), lock restructuring in addrconf_permanent_addr() using proven if_list_aux pattern. - [Phase 3] git blame: Code introduced by f1705ec197e7 (v4.5, 2016). Bug present since v4.5. - [Phase 3] git merge-base: 51454ea42c1a (if_list_aux) in v5.19+, fd63f185979b0 (UaF fix) in v7.0, d465bd07d16e3 (gfp passdown) in v7.0. - [Phase 3] git diff v7.0 8e6405f8218b: Clean apply confirmed. - [Phase 4] b4 am: Found upstream commit 8e6405f8218b, applied to net- next by Jakub Kicinski. v2 patch. - [Phase 4] Mailing list thread: Confirmed patchwork-bot shows clean application to netdev/net-next.git. - [Phase 4] b4 dig -w on related commit: Confirmed all key networking maintainers were involved. - [Phase 5] Call chain: addrconf_notify -> addrconf_permanent_addr -> fixup_permanent_addr -> addrconf_f6i_alloc -> ... -> fib_nh_common_init -> alloc_percpu_gfp with GFP_ATOMIC fails. - [Phase 5] fib_nh_common_init: Verified it does alloc_percpu_gfp() at line 619-620 of fib_semantics.c. - [Phase 6] v7.0: All dependencies present, clean apply verified. - [Phase 8] Failure mode: IPv6 permanent address dropped (ipv6_del_addr called) when allocation fails - HIGH severity. - UNVERIFIED: Could not access lore.kernel.org review comments due to Anubis bot protection. The full reviewer feedback on v1->v2 evolution could not be examined. **YES** net/ipv6/addrconf.c | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index dd0b4d80e0f84..77c77e843c96c 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3585,15 +3585,15 @@ static int fixup_permanent_addr(struct net *net, struct fib6_info *f6i, *prev; f6i = addrconf_f6i_alloc(net, idev, &ifp->addr, false, - GFP_ATOMIC, NULL); + GFP_KERNEL, NULL); if (IS_ERR(f6i)) return PTR_ERR(f6i); /* ifp->rt can be accessed outside of rtnl */ - spin_lock(&ifp->lock); + spin_lock_bh(&ifp->lock); prev = ifp->rt; ifp->rt = f6i; - spin_unlock(&ifp->lock); + spin_unlock_bh(&ifp->lock); fib6_info_release(prev); } @@ -3601,7 +3601,7 @@ static int fixup_permanent_addr(struct net *net, if (!(ifp->flags & IFA_F_NOPREFIXROUTE)) { addrconf_prefix_route(&ifp->addr, ifp->prefix_len, ifp->rt_priority, idev->dev, 0, 0, - GFP_ATOMIC); + GFP_KERNEL); } if (ifp->state == INET6_IFADDR_STATE_PREDAD) @@ -3612,29 +3612,36 @@ static int fixup_permanent_addr(struct net *net, static void addrconf_permanent_addr(struct net *net, struct net_device *dev) { - struct inet6_ifaddr *ifp, *tmp; + struct inet6_ifaddr *ifp; + LIST_HEAD(tmp_addr_list); struct inet6_dev *idev; + /* Mutual exclusion with other if_list_aux users. */ + ASSERT_RTNL(); + idev = __in6_dev_get(dev); if (!idev) return; write_lock_bh(&idev->lock); + list_for_each_entry(ifp, &idev->addr_list, if_list) { + if (ifp->flags & IFA_F_PERMANENT) + list_add_tail(&ifp->if_list_aux, &tmp_addr_list); + } + write_unlock_bh(&idev->lock); - list_for_each_entry_safe(ifp, tmp, &idev->addr_list, if_list) { - if ((ifp->flags & IFA_F_PERMANENT) && - fixup_permanent_addr(net, idev, ifp) < 0) { - write_unlock_bh(&idev->lock); + while (!list_empty(&tmp_addr_list)) { + ifp = list_first_entry(&tmp_addr_list, + struct inet6_ifaddr, if_list_aux); + list_del(&ifp->if_list_aux); + if (fixup_permanent_addr(net, idev, ifp) < 0) { net_info_ratelimited("%s: Failed to add prefix route for address %pI6c; dropping\n", idev->dev->name, &ifp->addr); in6_ifa_hold(ifp); ipv6_del_addr(ifp); - write_lock_bh(&idev->lock); } } - - write_unlock_bh(&idev->lock); } static int addrconf_notify(struct notifier_block *this, unsigned long event, -- 2.53.0