diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-06-21 11:44:08 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-06-21 11:44:08 -0400 |
| commit | a19214430d27a3af6f1672ec26f3c893ef899ede (patch) | |
| tree | ecd998eaf216f6e195c65cb050f4335db86b26f6 | |
| parent | b732d9680b7a2968823851f1163507ad9c45c8cb (diff) | |
| parent | b9f75f45a6b46a0ab4eb0857d437a0845871f314 (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.c | 2 | ||||
| -rw-r--r-- | include/net/ipv6.h | 6 | ||||
| -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 | ||||
| -rw-r--r-- | net/ipv6/ip6_input.c | 9 | ||||
| -rw-r--r-- | net/ipv6/ipv6_sockglue.c | 11 | ||||
| -rw-r--r-- | net/mac80211/tx.c | 9 | ||||
| -rw-r--r-- | net/sctp/socket.c | 4 |
9 files changed, 52 insertions, 7 deletions
diff --git a/drivers/net/pppoe.c b/drivers/net/pppoe.c index bafb69b6f7cb..fc6f4b8c64b3 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 e0a612bc9c4e..f422f7218e1c 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 | ||
| 370 | static 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 | |||
| 370 | static inline int ipv6_addr_v4mapped(const struct in6_addr *a) | 376 | static 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 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); |
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index 4e5c8615832c..17eb48b8e329 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 c042ce19bd14..86e28a75267f 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 28d8bd53bd3a..c80d5899f279 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 e7e3baf7009e..0dbcde6758ea 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 |
