Skip to content

Commit d87f8bc

Browse files
qsnklassert
authored andcommitted
xfrm: avoid RCU warnings around the per-netns netlink socket
net->xfrm.nlsk is used in 2 types of contexts: - fully under RCU, with rcu_read_lock + rcu_dereference and a NULL check - in the netlink handlers, with requests coming from a userspace socket In the 2nd case, net->xfrm.nlsk is guaranteed to stay non-NULL and the object is alive, since we can't enter the netns destruction path while the user socket holds a reference on the netns. After adding the __rcu annotation to netns_xfrm.nlsk (which silences sparse warnings in the RCU users and __net_init code), we need to tell sparse that the 2nd case is safe. Add a helper for that. Signed-off-by: Sabrina Dubroca <[email protected]> Reviewed-by: Simon Horman <[email protected]> Signed-off-by: Steffen Klassert <[email protected]>
1 parent 103b4f5 commit d87f8bc

2 files changed

Lines changed: 18 additions & 9 deletions

File tree

include/net/netns/xfrm.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ struct netns_xfrm {
5959
struct list_head inexact_bins;
6060

6161

62-
struct sock *nlsk;
62+
struct sock __rcu *nlsk;
6363
struct sock *nlsk_stash;
6464

6565
u32 sysctl_aevent_etime;

net/xfrm/xfrm_user.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,15 @@
3535
#endif
3636
#include <linux/unaligned.h>
3737

38+
static struct sock *xfrm_net_nlsk(const struct net *net, const struct sk_buff *skb)
39+
{
40+
/* get the source of this request, see netlink_unicast_kernel */
41+
const struct sock *sk = NETLINK_CB(skb).sk;
42+
43+
/* sk is refcounted, the netns stays alive and nlsk with it */
44+
return rcu_dereference_protected(net->xfrm.nlsk, sk->sk_net_refcnt);
45+
}
46+
3847
static int verify_one_alg(struct nlattr **attrs, enum xfrm_attr_type_t type,
3948
struct netlink_ext_ack *extack)
4049
{
@@ -1727,7 +1736,7 @@ static int xfrm_get_spdinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
17271736
err = build_spdinfo(r_skb, net, sportid, seq, *flags);
17281737
BUG_ON(err < 0);
17291738

1730-
return nlmsg_unicast(net->xfrm.nlsk, r_skb, sportid);
1739+
return nlmsg_unicast(xfrm_net_nlsk(net, skb), r_skb, sportid);
17311740
}
17321741

17331742
static inline unsigned int xfrm_sadinfo_msgsize(void)
@@ -1787,7 +1796,7 @@ static int xfrm_get_sadinfo(struct sk_buff *skb, struct nlmsghdr *nlh,
17871796
err = build_sadinfo(r_skb, net, sportid, seq, *flags);
17881797
BUG_ON(err < 0);
17891798

1790-
return nlmsg_unicast(net->xfrm.nlsk, r_skb, sportid);
1799+
return nlmsg_unicast(xfrm_net_nlsk(net, skb), r_skb, sportid);
17911800
}
17921801

17931802
static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -1807,7 +1816,7 @@ static int xfrm_get_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
18071816
if (IS_ERR(resp_skb)) {
18081817
err = PTR_ERR(resp_skb);
18091818
} else {
1810-
err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).portid);
1819+
err = nlmsg_unicast(xfrm_net_nlsk(net, skb), resp_skb, NETLINK_CB(skb).portid);
18111820
}
18121821
xfrm_state_put(x);
18131822
out_noput:
@@ -1898,7 +1907,7 @@ static int xfrm_alloc_userspi(struct sk_buff *skb, struct nlmsghdr *nlh,
18981907
}
18991908
}
19001909

1901-
err = nlmsg_unicast(net->xfrm.nlsk, resp_skb, NETLINK_CB(skb).portid);
1910+
err = nlmsg_unicast(xfrm_net_nlsk(net, skb), resp_skb, NETLINK_CB(skb).portid);
19021911

19031912
out:
19041913
xfrm_state_put(x);
@@ -2543,7 +2552,7 @@ static int xfrm_get_default(struct sk_buff *skb, struct nlmsghdr *nlh,
25432552
r_up->out = net->xfrm.policy_default[XFRM_POLICY_OUT];
25442553
nlmsg_end(r_skb, r_nlh);
25452554

2546-
return nlmsg_unicast(net->xfrm.nlsk, r_skb, portid);
2555+
return nlmsg_unicast(xfrm_net_nlsk(net, skb), r_skb, portid);
25472556
}
25482557

25492558
static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -2609,7 +2618,7 @@ static int xfrm_get_policy(struct sk_buff *skb, struct nlmsghdr *nlh,
26092618
if (IS_ERR(resp_skb)) {
26102619
err = PTR_ERR(resp_skb);
26112620
} else {
2612-
err = nlmsg_unicast(net->xfrm.nlsk, resp_skb,
2621+
err = nlmsg_unicast(xfrm_net_nlsk(net, skb), resp_skb,
26132622
NETLINK_CB(skb).portid);
26142623
}
26152624
} else {
@@ -2782,7 +2791,7 @@ static int xfrm_get_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
27822791
err = build_aevent(r_skb, x, &c);
27832792
BUG_ON(err < 0);
27842793

2785-
err = nlmsg_unicast(net->xfrm.nlsk, r_skb, NETLINK_CB(skb).portid);
2794+
err = nlmsg_unicast(xfrm_net_nlsk(net, skb), r_skb, NETLINK_CB(skb).portid);
27862795
spin_unlock_bh(&x->lock);
27872796
xfrm_state_put(x);
27882797
return err;
@@ -3486,7 +3495,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
34863495
goto err;
34873496
}
34883497

3489-
err = netlink_dump_start(net->xfrm.nlsk, skb, nlh, &c);
3498+
err = netlink_dump_start(xfrm_net_nlsk(net, skb), skb, nlh, &c);
34903499
goto err;
34913500
}
34923501

0 commit comments

Comments
 (0)