Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions include/linux/netdevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -2683,6 +2683,12 @@ struct net *dev_net(const struct net_device *dev)
return read_pnet(&dev->nd_net);
}

static inline
struct net *dev_net_rcu(const struct net_device *dev)
{
return read_pnet_rcu(&dev->nd_net);
}

static inline
void dev_net_set(struct net_device *dev, struct net *net)
{
Expand Down
15 changes: 12 additions & 3 deletions include/net/net_namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -350,21 +350,30 @@ static inline void put_net_track(struct net *net, netns_tracker *tracker)

typedef struct {
#ifdef CONFIG_NET_NS
struct net *net;
struct net __rcu *net;
#endif
} possible_net_t;

static inline void write_pnet(possible_net_t *pnet, struct net *net)
{
#ifdef CONFIG_NET_NS
pnet->net = net;
rcu_assign_pointer(pnet->net, net);
#endif
}

static inline struct net *read_pnet(const possible_net_t *pnet)
{
#ifdef CONFIG_NET_NS
return pnet->net;
return rcu_dereference_protected(pnet->net, true);
#else
return &init_net;
#endif
}

static inline struct net *read_pnet_rcu(const possible_net_t *pnet)
{
#ifdef CONFIG_NET_NS
return rcu_dereference(pnet->net);
#else
return &init_net;
#endif
Expand Down
10 changes: 4 additions & 6 deletions net/ipv6/ndisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -414,15 +414,11 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
{
int hlen = LL_RESERVED_SPACE(dev);
int tlen = dev->needed_tailroom;
struct sock *sk = dev_net(dev)->ipv6.ndisc_sk;
struct sk_buff *skb;

skb = alloc_skb(hlen + sizeof(struct ipv6hdr) + len + tlen, GFP_ATOMIC);
if (!skb) {
ND_PRINTK(0, err, "ndisc: %s failed to allocate an skb\n",
__func__);
if (!skb)
return NULL;
}

skb->protocol = htons(ETH_P_IPV6);
skb->dev = dev;
Expand All @@ -433,7 +429,9 @@ static struct sk_buff *ndisc_alloc_skb(struct net_device *dev,
/* Manually assign socket ownership as we avoid calling
* sock_alloc_send_pskb() to bypass wmem buffer limits
*/
skb_set_owner_w(skb, sk);
rcu_read_lock();
skb_set_owner_w(skb, dev_net_rcu(dev)->ipv6.ndisc_sk);
rcu_read_unlock();

return skb;
}
Expand Down
Loading