[PATCH net-next 1/2] ipv4: devinet: list global scope addresses before link scope addresses

From: Tim Wong

Date: Mon Jul 20 2026 - 14:27:56 EST


__inet_insert_ifa() inserts a new primary address by advancing an
insertion pointer past every existing primary address whose scope
is >= the new address's scope. Because IPv4 scope values are
numerically smaller for wider scopes (RT_SCOPE_UNIVERSE < ... <
RT_SCOPE_LINK < RT_SCOPE_HOST), the comparison

ifa->ifa_scope <= ifa1->ifa_scope

is true for a global-scope new address against essentially every
existing entry, so the new address is pushed all the way to the
tail of the primary address list, ending up *after* any link-scope
addresses that were configured earlier.

On an interface carrying a mix of global- and link-scope IPv4
addresses (e.g. a routable address alongside an RFC 3927
169.254.0.0/16 address, or any address explicitly assigned link
scope), this makes the resulting order in in_dev->ifa_list -- and
therefore the order addresses are reported via netlink
(RTM_GETADDR), ioctl (SIOCGIFCONF), and /proc/net -- depend on
configuration order rather than scope. Userspace consumers that
pick the first address returned for an interface (e.g. via
getifaddrs()) can end up preferring a link-scope address over a
global one.

IPv6 already avoids this: ipv6_add_addr() keeps idev->addr_list
ordered so global-scope addresses precede link-local ones
regardless of configuration order.

Fix the comparison so the insertion pointer only advances past
addresses that are at least as global as the new one:

ifa->ifa_scope >= ifa1->ifa_scope

This groups global-scope primary addresses ahead of link-scope
primary addresses in in_dev->ifa_list, preserving insertion order
within each scope group, and brings IPv4 address enumeration order
in line with existing IPv6 behavior.

Signed-off-by: kanman.wong <kanman.wong@xxxxxxxx>
---
net/ipv4/devinet.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c
index a35b72662e43..056f2169c6a3 100644
--- a/net/ipv4/devinet.c
+++ b/net/ipv4/devinet.c
@@ -510,7 +510,7 @@ static int __inet_insert_ifa(struct in_ifaddr
*ifa, struct nlmsghdr *nlh,

while (ifa1) {
if (!(ifa1->ifa_flags & IFA_F_SECONDARY) &&
- ifa->ifa_scope <= ifa1->ifa_scope)
+ ifa->ifa_scope >= ifa1->ifa_scope)
last_primary = &ifa1->ifa_next;
if (ifa1->ifa_mask == ifa->ifa_mask &&
inet_ifa_match(ifa1->ifa_address, ifa)) {

base-commit: ce6b4d3216b63f902bb8e9695ee6c10c83415f65
--
2.51.0