Skip to content

Commit 867b385

Browse files
q2venkuba-moo
authored andcommitted
ipv6: Move lifetime validation to inet6_rtm_newaddr().
inet6_addr_add() and inet6_addr_modify() have the same code to validate IPv6 lifetime that is done under RTNL. Let's factorise it out to inet6_rtm_newaddr() so that we can validate the lifetime without RTNL later. Note that inet6_addr_add() is called from addrconf_add_ifaddr(), but the lifetime is INFINITY_LIFE_TIME in the path, so expires and flags are 0. Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> Link: https://patch.msgid.link/20250115080608.28127-10-kuniyu@amazon.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 2f1ace4 commit 867b385

File tree

1 file changed

+35
-58
lines changed

1 file changed

+35
-58
lines changed

net/ipv6/addrconf.c

Lines changed: 35 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -3008,14 +3008,11 @@ static int ipv6_mc_config(struct sock *sk, bool join,
30083008
* Manual configuration of address on an interface
30093009
*/
30103010
static int inet6_addr_add(struct net *net, struct net_device *dev,
3011-
struct ifa6_config *cfg,
3011+
struct ifa6_config *cfg, clock_t expires, u32 flags,
30123012
struct netlink_ext_ack *extack)
30133013
{
30143014
struct inet6_ifaddr *ifp;
30153015
struct inet6_dev *idev;
3016-
unsigned long timeout;
3017-
clock_t expires;
3018-
u32 flags;
30193016

30203017
ASSERT_RTNL();
30213018

@@ -3024,12 +3021,6 @@ static int inet6_addr_add(struct net *net, struct net_device *dev,
30243021
return -EINVAL;
30253022
}
30263023

3027-
/* check the lifetime */
3028-
if (!cfg->valid_lft || cfg->preferred_lft > cfg->valid_lft) {
3029-
NL_SET_ERR_MSG_MOD(extack, "address lifetime invalid");
3030-
return -EINVAL;
3031-
}
3032-
30333024
if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR && cfg->plen != 64) {
30343025
NL_SET_ERR_MSG_MOD(extack, "address with \"mngtmpaddr\" flag must have a prefix length of 64");
30353026
return -EINVAL;
@@ -3053,24 +3044,6 @@ static int inet6_addr_add(struct net *net, struct net_device *dev,
30533044

30543045
cfg->scope = ipv6_addr_scope(cfg->pfx);
30553046

3056-
timeout = addrconf_timeout_fixup(cfg->valid_lft, HZ);
3057-
if (addrconf_finite_timeout(timeout)) {
3058-
expires = jiffies_to_clock_t(timeout * HZ);
3059-
cfg->valid_lft = timeout;
3060-
flags = RTF_EXPIRES;
3061-
} else {
3062-
expires = 0;
3063-
flags = 0;
3064-
cfg->ifa_flags |= IFA_F_PERMANENT;
3065-
}
3066-
3067-
timeout = addrconf_timeout_fixup(cfg->preferred_lft, HZ);
3068-
if (addrconf_finite_timeout(timeout)) {
3069-
if (timeout == 0)
3070-
cfg->ifa_flags |= IFA_F_DEPRECATED;
3071-
cfg->preferred_lft = timeout;
3072-
}
3073-
30743047
ifp = ipv6_add_addr(idev, cfg, true, extack);
30753048
if (!IS_ERR(ifp)) {
30763049
if (!(cfg->ifa_flags & IFA_F_NOPREFIXROUTE)) {
@@ -3180,7 +3153,7 @@ int addrconf_add_ifaddr(struct net *net, void __user *arg)
31803153
rtnl_net_lock(net);
31813154
dev = __dev_get_by_index(net, ireq.ifr6_ifindex);
31823155
if (dev)
3183-
err = inet6_addr_add(net, dev, &cfg, NULL);
3156+
err = inet6_addr_add(net, dev, &cfg, 0, 0, NULL);
31843157
else
31853158
err = -ENODEV;
31863159
rtnl_net_unlock(net);
@@ -4869,45 +4842,22 @@ static int modify_prefix_route(struct net *net, struct inet6_ifaddr *ifp,
48694842
}
48704843

48714844
static int inet6_addr_modify(struct net *net, struct inet6_ifaddr *ifp,
4872-
struct ifa6_config *cfg)
4845+
struct ifa6_config *cfg, clock_t expires,
4846+
u32 flags)
48734847
{
4874-
u32 flags;
4875-
clock_t expires;
4876-
unsigned long timeout;
48774848
bool was_managetempaddr;
4878-
bool had_prefixroute;
48794849
bool new_peer = false;
4850+
bool had_prefixroute;
48804851

48814852
ASSERT_RTNL();
48824853

4883-
if (!cfg->valid_lft || cfg->preferred_lft > cfg->valid_lft)
4884-
return -EINVAL;
4885-
48864854
if (cfg->ifa_flags & IFA_F_MANAGETEMPADDR &&
48874855
(ifp->flags & IFA_F_TEMPORARY || ifp->prefix_len != 64))
48884856
return -EINVAL;
48894857

48904858
if (!(ifp->flags & IFA_F_TENTATIVE) || ifp->flags & IFA_F_DADFAILED)
48914859
cfg->ifa_flags &= ~IFA_F_OPTIMISTIC;
48924860

4893-
timeout = addrconf_timeout_fixup(cfg->valid_lft, HZ);
4894-
if (addrconf_finite_timeout(timeout)) {
4895-
expires = jiffies_to_clock_t(timeout * HZ);
4896-
cfg->valid_lft = timeout;
4897-
flags = RTF_EXPIRES;
4898-
} else {
4899-
expires = 0;
4900-
flags = 0;
4901-
cfg->ifa_flags |= IFA_F_PERMANENT;
4902-
}
4903-
4904-
timeout = addrconf_timeout_fixup(cfg->preferred_lft, HZ);
4905-
if (addrconf_finite_timeout(timeout)) {
4906-
if (timeout == 0)
4907-
cfg->ifa_flags |= IFA_F_DEPRECATED;
4908-
cfg->preferred_lft = timeout;
4909-
}
4910-
49114861
if (cfg->peer_pfx &&
49124862
memcmp(&ifp->peer_addr, cfg->peer_pfx, sizeof(struct in6_addr))) {
49134863
if (!ipv6_addr_any(&ifp->peer_addr))
@@ -4992,13 +4942,16 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
49924942
struct netlink_ext_ack *extack)
49934943
{
49944944
struct net *net = sock_net(skb->sk);
4995-
struct ifaddrmsg *ifm;
49964945
struct nlattr *tb[IFA_MAX+1];
49974946
struct in6_addr *peer_pfx;
49984947
struct inet6_ifaddr *ifa;
49994948
struct net_device *dev;
50004949
struct inet6_dev *idev;
50014950
struct ifa6_config cfg;
4951+
struct ifaddrmsg *ifm;
4952+
unsigned long timeout;
4953+
clock_t expires;
4954+
u32 flags;
50024955
int err;
50034956

50044957
err = nlmsg_parse_deprecated(nlh, sizeof(*ifm), tb, IFA_MAX,
@@ -5028,15 +4981,39 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
50284981
IFA_F_MANAGETEMPADDR | IFA_F_NOPREFIXROUTE |
50294982
IFA_F_MCAUTOJOIN | IFA_F_OPTIMISTIC;
50304983

4984+
cfg.ifa_flags |= IFA_F_PERMANENT;
50314985
cfg.valid_lft = INFINITY_LIFE_TIME;
50324986
cfg.preferred_lft = INFINITY_LIFE_TIME;
4987+
expires = 0;
4988+
flags = 0;
50334989

50344990
if (tb[IFA_CACHEINFO]) {
50354991
struct ifa_cacheinfo *ci;
50364992

50374993
ci = nla_data(tb[IFA_CACHEINFO]);
50384994
cfg.valid_lft = ci->ifa_valid;
50394995
cfg.preferred_lft = ci->ifa_prefered;
4996+
4997+
if (!cfg.valid_lft || cfg.preferred_lft > cfg.valid_lft) {
4998+
NL_SET_ERR_MSG_MOD(extack, "address lifetime invalid");
4999+
return -EINVAL;
5000+
}
5001+
5002+
timeout = addrconf_timeout_fixup(cfg.valid_lft, HZ);
5003+
if (addrconf_finite_timeout(timeout)) {
5004+
cfg.ifa_flags &= ~IFA_F_PERMANENT;
5005+
cfg.valid_lft = timeout;
5006+
expires = jiffies_to_clock_t(timeout * HZ);
5007+
flags = RTF_EXPIRES;
5008+
}
5009+
5010+
timeout = addrconf_timeout_fixup(cfg.preferred_lft, HZ);
5011+
if (addrconf_finite_timeout(timeout)) {
5012+
if (timeout == 0)
5013+
cfg.ifa_flags |= IFA_F_DEPRECATED;
5014+
5015+
cfg.preferred_lft = timeout;
5016+
}
50405017
}
50415018

50425019
dev = __dev_get_by_index(net, ifm->ifa_index);
@@ -5064,15 +5041,15 @@ inet6_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh,
50645041
* It would be best to check for !NLM_F_CREATE here but
50655042
* userspace already relies on not having to provide this.
50665043
*/
5067-
return inet6_addr_add(net, dev, &cfg, extack);
5044+
return inet6_addr_add(net, dev, &cfg, expires, flags, extack);
50685045
}
50695046

50705047
if (nlh->nlmsg_flags & NLM_F_EXCL ||
50715048
!(nlh->nlmsg_flags & NLM_F_REPLACE)) {
50725049
NL_SET_ERR_MSG_MOD(extack, "address already assigned");
50735050
err = -EEXIST;
50745051
} else {
5075-
err = inet6_addr_modify(net, ifa, &cfg);
5052+
err = inet6_addr_modify(net, ifa, &cfg, expires, flags);
50765053
}
50775054

50785055
in6_ifa_put(ifa);

0 commit comments

Comments
 (0)