[REGRESSION] net/ipv6/addrconf: Temporary addresses with short lifetimes generating when they shouldn't, causing applications to fail

From: Dan Moulding
Date: Thu Dec 21 2023 - 18:12:40 EST


I started running v6.7-rc5 on a desktop and began having problems
where Chromium would frequently fail to load pages and give an
"ERR_NETWORK_CHANGED" message instead. I also noticed instability in
avahi-daemon (it would stop resolving local names and/or consume 100%
CPU). Eventually I discovered that what is happening is that new
temporary IPv6 addresses for a ULA address are being generated once
every second, with very short preferred lifetimes (and I had an
interface with thousands of such temporary addresses). I also found
that it seems to be triggered when one of the devices on the network
sends a router advertisement with a prefix that has a preferred
lifetime of 0 (presumably it's sending that because it wants to
deprecate that prefix).

I bisected it to commit 629df6701c8a ("net: ipv6/addrconf: clamp
preferred_lft to the minimum required"). Upon reviewing that change, I
see that it has changed when generation of temporary addresses will be
allowed. I believe that change might have inadvertently caused the
kernel to violate RFC 4941 and might need to be reverted.

In particular RFC 4941 specifies that the preferred lifetime of a
temporary address must not be greater than the preferred lifetime of
the public address it is derived from. However, this change allows a
temporary address to be generated with a preferred lifetime greater
than the public address' preferred lifetime.

>From RFC 4941:

4. When creating a temporary address, the lifetime values MUST be
derived from the corresponding prefix as follows:

* Its Valid Lifetime is the lower of the Valid Lifetime of the
public address or TEMP_VALID_LIFETIME.

* Its Preferred Lifetime is the lower of the Preferred Lifetime
of the public address or TEMP_PREFERRED_LIFETIME -
DESYNC_FACTOR.

Previously temporary addresses would not be generated for an interface
if the administratively configured preferred lifetime on that
interface was too short. This change tries to avoid that, and allow
generating temporary addresses even on interfaces with very short
configured lifetimes, by simply increasing the preferred lifetime of
the generated address. However, doing so runs afoul of the above
requirement. It allows the preferred lifetime of the temporary address
to be increased to a value that is larger than the public address'
preferred lifetime. For example, in my case where the router
advertisement causes the public address' preferred lifetime to be set
to 0, the current code allows a temporary address to be generated with
a preferred lifetime of (regen_advance + age + 1), which is obviously
greater than 0. It also, in my case, leads to new temporary addresses
with very short lifetimes being generated, about once every second,
leading to the application-level issues I described above.

Cheers,

-- Dan