mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 09:02:00 +00:00
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
This commit is contained in:
commit
a19214430d
@ -942,7 +942,7 @@ static int pppoe_recvmsg(struct kiocb *iocb, struct socket *sock,
|
||||
m->msg_namelen = 0;
|
||||
|
||||
if (skb) {
|
||||
total_len = min(total_len, skb->len);
|
||||
total_len = min_t(size_t, total_len, skb->len);
|
||||
error = skb_copy_datagram_iovec(skb, 0, m->msg_iov, total_len);
|
||||
if (error == 0)
|
||||
error = total_len;
|
||||
|
@ -367,6 +367,12 @@ static inline int ipv6_addr_any(const struct in6_addr *a)
|
||||
a->s6_addr32[2] | a->s6_addr32[3] ) == 0);
|
||||
}
|
||||
|
||||
static inline int ipv6_addr_loopback(const struct in6_addr *a)
|
||||
{
|
||||
return ((a->s6_addr32[0] | a->s6_addr32[1] |
|
||||
a->s6_addr32[2] | (a->s6_addr32[3] ^ htonl(1))) == 0);
|
||||
}
|
||||
|
||||
static inline int ipv6_addr_v4mapped(const struct in6_addr *a)
|
||||
{
|
||||
return ((a->s6_addr32[0] | a->s6_addr32[1] |
|
||||
|
@ -95,6 +95,11 @@ extern struct list_head net_namespace_list;
|
||||
#ifdef CONFIG_NET_NS
|
||||
extern void __put_net(struct net *net);
|
||||
|
||||
static inline int net_alive(struct net *net)
|
||||
{
|
||||
return net && atomic_read(&net->count);
|
||||
}
|
||||
|
||||
static inline struct net *get_net(struct net *net)
|
||||
{
|
||||
atomic_inc(&net->count);
|
||||
@ -125,6 +130,12 @@ int net_eq(const struct net *net1, const struct net *net2)
|
||||
return net1 == net2;
|
||||
}
|
||||
#else
|
||||
|
||||
static inline int net_alive(struct net *net)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static inline struct net *get_net(struct net *net)
|
||||
{
|
||||
return net;
|
||||
|
@ -2077,6 +2077,10 @@ int netif_receive_skb(struct sk_buff *skb)
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
/* Don't receive packets in an exiting network namespace */
|
||||
if (!net_alive(dev_net(skb->dev)))
|
||||
goto out;
|
||||
|
||||
#ifdef CONFIG_NET_CLS_ACT
|
||||
if (skb->tc_verd & TC_NCLS) {
|
||||
skb->tc_verd = CLR_TC_NCLS(skb->tc_verd);
|
||||
|
@ -140,6 +140,9 @@ static void cleanup_net(struct work_struct *work)
|
||||
struct pernet_operations *ops;
|
||||
struct net *net;
|
||||
|
||||
/* Be very certain incoming network packets will not find us */
|
||||
rcu_barrier();
|
||||
|
||||
net = container_of(work, struct net, work);
|
||||
|
||||
mutex_lock(&net_mutex);
|
||||
|
@ -102,6 +102,15 @@ int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt
|
||||
if (hdr->version != 6)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* RFC4291 2.5.3
|
||||
* A packet received on an interface with a destination address
|
||||
* of loopback must be dropped.
|
||||
*/
|
||||
if (!(dev->flags & IFF_LOOPBACK) &&
|
||||
ipv6_addr_loopback(&hdr->daddr))
|
||||
goto err;
|
||||
|
||||
skb->transport_header = skb->network_header + sizeof(*hdr);
|
||||
IP6CB(skb)->nhoff = offsetof(struct ipv6hdr, nexthdr);
|
||||
|
||||
|
@ -345,18 +345,21 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname,
|
||||
case IPV6_DSTOPTS:
|
||||
{
|
||||
struct ipv6_txoptions *opt;
|
||||
|
||||
/* remove any sticky options header with a zero option
|
||||
* length, per RFC3542.
|
||||
*/
|
||||
if (optlen == 0)
|
||||
optval = NULL;
|
||||
else if (optlen < sizeof(struct ipv6_opt_hdr) ||
|
||||
optlen & 0x7 || optlen > 8 * 255)
|
||||
goto e_inval;
|
||||
|
||||
/* hop-by-hop / destination options are privileged option */
|
||||
retv = -EPERM;
|
||||
if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW))
|
||||
break;
|
||||
|
||||
if (optlen < sizeof(struct ipv6_opt_hdr) ||
|
||||
optlen & 0x7 || optlen > 8 * 255)
|
||||
goto e_inval;
|
||||
|
||||
opt = ipv6_renew_options(sk, np->opt, optname,
|
||||
(struct ipv6_opt_hdr __user *)optval,
|
||||
optlen);
|
||||
|
@ -1132,7 +1132,7 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
|
||||
ieee80211_tx_handler *handler;
|
||||
struct ieee80211_tx_data tx;
|
||||
ieee80211_tx_result res = TX_DROP, res_prepare;
|
||||
int ret, i;
|
||||
int ret, i, retries = 0;
|
||||
|
||||
WARN_ON(__ieee80211_queue_pending(local, control->queue));
|
||||
|
||||
@ -1216,6 +1216,13 @@ retry:
|
||||
if (!__ieee80211_queue_stopped(local, control->queue)) {
|
||||
clear_bit(IEEE80211_LINK_STATE_PENDING,
|
||||
&local->state[control->queue]);
|
||||
retries++;
|
||||
/*
|
||||
* Driver bug, it's rejecting packets but
|
||||
* not stopping queues.
|
||||
*/
|
||||
if (WARN_ON_ONCE(retries > 5))
|
||||
goto drop;
|
||||
goto retry;
|
||||
}
|
||||
memcpy(&store->control, control,
|
||||
|
@ -4401,7 +4401,9 @@ static int sctp_getsockopt_local_addrs_old(struct sock *sk, int len,
|
||||
if (copy_from_user(&getaddrs, optval, len))
|
||||
return -EFAULT;
|
||||
|
||||
if (getaddrs.addr_num <= 0) return -EINVAL;
|
||||
if (getaddrs.addr_num <= 0 ||
|
||||
getaddrs.addr_num >= (INT_MAX / sizeof(union sctp_addr)))
|
||||
return -EINVAL;
|
||||
/*
|
||||
* For UDP-style sockets, id specifies the association to query.
|
||||
* If the id field is set to the value '0' then the locally bound
|
||||
|
Loading…
Reference in New Issue
Block a user