aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-06-21 11:44:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-06-21 11:44:08 -0400
commita19214430d27a3af6f1672ec26f3c893ef899ede (patch)
treeecd998eaf216f6e195c65cb050f4335db86b26f6
parentb732d9680b7a2968823851f1163507ad9c45c8cb (diff)
parentb9f75f45a6b46a0ab4eb0857d437a0845871f314 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: netns: Don't receive new packets in a dead network namespace. sctp: Make sure N * sizeof(union sctp_addr) does not overflow. pppoe: warning fix ipv6: Drop packets for loopback address from outside of the box. ipv6: Remove options header when setsockopt's optlen is 0 mac80211: detect driver tx bugs
-rw-r--r--drivers/net/pppoe.c2
-rw-r--r--include/net/ipv6.h6
-rw-r--r--include/net/net_namespace.h11
-rw-r--r--net/core/dev.c4
-rw-r--r--net/core/net_namespace.c3
-rw-r--r--net/ipv6/ip6_input.c9
-rw-r--r--net/ipv6/ipv6_sockglue.c11
-rw-r--r--net/mac80211/tx.c9
-rw-r--r--net/sctp/socket.c4
9 files changed, 52 insertions, 7 deletions
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c
index bafb69b6f7c..fc6f4b8c64b 100644
--- a/drivers/net/pppoe.c
+++ b/drivers/net/pppoe.c
@@ -942,7 +942,7 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
942 m->msg_namelen = 0; 942 m->msg_namelen = 0;
943 943
944 if (skb) { 944 if (skb) {
945 total_len = min(total_len, skb->len); 945 total_len = min_t(size_t, total_len, skb->len);
946 error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len); 946 error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len);
947 if (error == 0) 947 if (error == 0)
948 error = total_len; 948 error = total_len;
diff --git a/include/net/ipv6.h b/include/net/ipv6.h
index e0a612bc9c4..f422f7218e1 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -367,6 +367,12 @@ static inline int ipv6_addr_any(const struct in6_addr *a)
367 a->s6_addr32[2] | a->s6_addr32[3] ) == 0); 367 a->s6_addr32[2] | a->s6_addr32[3] ) == 0);
368} 368}
369 369
370static inline int ipv6_addr_loopback(const struct in6_addr *a)
371{
372 return ((a->s6_addr32[0] | a->s6_addr32[1] |
373 a->s6_addr32[2] | (a->s6_addr32[3] ^ htonl(1))) == 0);
374}
375
370static inline int ipv6_addr_v4mapped(const struct in6_addr *a) 376static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
371{ 377{
372 return ((a->s6_addr32[0] | a->s6_addr32[1] | 378 return ((a->s6_addr32[0] | a->s6_addr32[1] |
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index aa540e6be50..d9dd0f70729 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
96extern void __put_net(struct net *net); 96extern void __put_net(struct net *net);
97 97
98static inline int net_alive(struct net *net)
99{
100 return net && atomic_read(&net->count);
101}
102
98static inline struct net *get_net(struct net *net) 103static 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
134static inline int net_alive(struct net *net)
135{
136 return 1;
137}
138
128static inline struct net *get_net(struct net *net) 139static 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 68d8df0992a..c421a1f8f0b 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 72b4c184dd8..7c52fe277b6 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);
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c
index 4e5c8615832..17eb48b8e32 100644
--- a/net/ipv6/ip6_input.c
+++ b/net/ipv6/ip6_input.c
@@ -102,6 +102,15 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
102 if (hdr->version != 6) 102 if (hdr->version != 6)
103 goto err; 103 goto err;
104 104
105 /*
106 * RFC4291 2.5.3
107 * A packet received on an interface with a destination address
108 * of loopback must be dropped.
109 */
110 if (!(dev->flags & IFF_LOOPBACK) &&
111 ipv6_addr_loopback(&hdr->daddr))
112 goto err;
113
105 skb->transport_header = skb->network_header + sizeof(*hdr); 114 skb->transport_header = skb->network_header + sizeof(*hdr);
106 IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr); 115 IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
107 116
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c
index c042ce19bd1..86e28a75267 100644
--- a/net/ipv6/ipv6_sockglue.c
+++ b/net/ipv6/ipv6_sockglue.c
@@ -345,18 +345,21 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
345 case IPV6_DSTOPTS: 345 case IPV6_DSTOPTS:
346 { 346 {
347 struct ipv6_txoptions *opt; 347 struct ipv6_txoptions *opt;
348
349 /* remove any sticky options header with a zero option
350 * length, per RFC3542.
351 */
348 if (optlen == 0) 352 if (optlen == 0)
349 optval = NULL; 353 optval = NULL;
354 else if (optlen < sizeof(struct ipv6_opt_hdr) ||
355 optlen & 0x7 || optlen > 8 * 255)
356 goto e_inval;
350 357
351 /* hop-by-hop / destination options are privileged option */ 358 /* hop-by-hop / destination options are privileged option */
352 retv = -EPERM; 359 retv = -EPERM;
353 if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) 360 if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW))
354 break; 361 break;
355 362
356 if (optlen < sizeof(struct ipv6_opt_hdr) ||
357 optlen & 0x7 || optlen > 8 * 255)
358 goto e_inval;
359
360 opt = ipv6_renew_options(sk, np->opt, optname, 363 opt = ipv6_renew_options(sk, np->opt, optname,
361 (struct ipv6_opt_hdr __user *)optval, 364 (struct ipv6_opt_hdr __user *)optval,
362 optlen); 365 optlen);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 28d8bd53bd3..c80d5899f27 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1132,7 +1132,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
1132 ieee80211_tx_handler *handler; 1132 ieee80211_tx_handler *handler;
1133 struct ieee80211_tx_data tx; 1133 struct ieee80211_tx_data tx;
1134 ieee80211_tx_result res = TX_DROP, res_prepare; 1134 ieee80211_tx_result res = TX_DROP, res_prepare;
1135 int ret, i; 1135 int ret, i, retries = 0;
1136 1136
1137 WARN_ON(__ieee80211_queue_pending(local, control->queue)); 1137 WARN_ON(__ieee80211_queue_pending(local, control->queue));
1138 1138
@@ -1216,6 +1216,13 @@ retry:
1216 if (!__ieee80211_queue_stopped(local, control->queue)) { 1216 if (!__ieee80211_queue_stopped(local, control->queue)) {
1217 clear_bit(IEEE80211_LINK_STATE_PENDING, 1217 clear_bit(IEEE80211_LINK_STATE_PENDING,
1218 &local->state[control->queue]); 1218 &local->state[control->queue]);
1219 retries++;
1220 /*
1221 * Driver bug, it's rejecting packets but
1222 * not stopping queues.
1223 */
1224 if (WARN_ON_ONCE(retries > 5))
1225 goto drop;
1219 goto retry; 1226 goto retry;
1220 } 1227 }
1221 memcpy(&store->control, control, 1228 memcpy(&store->control, control,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index e7e3baf7009..0dbcde6758e 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -4401,7 +4401,9 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
4401 if (copy_from_user(&getaddrs, optval, len)) 4401 if (copy_from_user(&getaddrs, optval, len))
4402 return -EFAULT; 4402 return -EFAULT;
4403 4403
4404 if (getaddrs.addr_num <= 0) return -EINVAL; 4404 if (getaddrs.addr_num <= 0 ||
4405 getaddrs.addr_num >= (INT_MAX / sizeof(union sctp_addr)))
4406 return -EINVAL;
4405 /* 4407 /*
4406 * For UDP-style sockets, id specifies the association to query. 4408 * For UDP-style sockets, id specifies the association to query.
4407 * If the id field is set to the value '0' then the locally bound 4409 * If the id field is set to the value '0' then the locally bound