diff options
| -rw-r--r-- | include/net/net_namespace.h | 11 | ||||
| -rw-r--r-- | net/core/dev.c | 4 | ||||
| -rw-r--r-- | net/core/net_namespace.c | 3 |
3 files changed, 18 insertions, 0 deletions
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h index aa540e6be502..d9dd0f707296 100644 --- a/include/net/net_namespace.h +++ b/include/net/net_namespace.h | |||
| @@ -95,6 +95,11 @@ extern struct list_head net_namespace_list; | |||
| 95 | #ifdef CONFIG_NET_NS | 95 | #ifdef CONFIG_NET_NS |
| 96 | extern void __put_net(struct net *net); | 96 | extern void __put_net(struct net *net); |
| 97 | 97 | ||
| 98 | static inline int net_alive(struct net *net) | ||
| 99 | { | ||
| 100 | return net && atomic_read(&net->count); | ||
| 101 | } | ||
| 102 | |||
| 98 | static inline struct net *get_net(struct net *net) | 103 | static inline struct net *get_net(struct net *net) |
| 99 | { | 104 | { |
| 100 | atomic_inc(&net->count); | 105 | atomic_inc(&net->count); |
| @@ -125,6 +130,12 @@ int net_eq(const struct net *net1, const struct net *net2) | |||
| 125 | return net1 == net2; | 130 | return net1 == net2; |
| 126 | } | 131 | } |
| 127 | #else | 132 | #else |
| 133 | |||
| 134 | static inline int net_alive(struct net *net) | ||
| 135 | { | ||
| 136 | return 1; | ||
| 137 | } | ||
| 138 | |||
| 128 | static inline struct net *get_net(struct net *net) | 139 | static inline struct net *get_net(struct net *net) |
| 129 | { | 140 | { |
| 130 | return net; | 141 | return net; |
diff --git a/net/core/dev.c b/net/core/dev.c index 68d8df0992ab..c421a1f8f0b9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -2077,6 +2077,10 @@ int netif_receive_skb(struct sk_buff *skb) | |||
| 2077 | 2077 | ||
| 2078 | rcu_read_lock(); | 2078 | rcu_read_lock(); |
| 2079 | 2079 | ||
| 2080 | /* Don't receive packets in an exiting network namespace */ | ||
| 2081 | if (!net_alive(dev_net(skb->dev))) | ||
| 2082 | goto out; | ||
| 2083 | |||
| 2080 | #ifdef CONFIG_NET_CLS_ACT | 2084 | #ifdef CONFIG_NET_CLS_ACT |
| 2081 | if (skb->tc_verd & TC_NCLS) { | 2085 | if (skb->tc_verd & TC_NCLS) { |
| 2082 | skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); | 2086 | skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 72b4c184dd84..7c52fe277b62 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
| @@ -140,6 +140,9 @@ static void cleanup_net(struct work_struct *work) | |||
| 140 | struct pernet_operations *ops; | 140 | struct pernet_operations *ops; |
| 141 | struct net *net; | 141 | struct net *net; |
| 142 | 142 | ||
| 143 | /* Be very certain incoming network packets will not find us */ | ||
| 144 | rcu_barrier(); | ||
| 145 | |||
| 143 | net = container_of(work, struct net, work); | 146 | net = container_of(work, struct net, work); |
| 144 | 147 | ||
| 145 | mutex_lock(&net_mutex); | 148 | mutex_lock(&net_mutex); |
