Skip to content

Commit

Permalink
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
Linus Torvalds committed Jun 21, 2008
2 parents b732d96 + b9f75f4 commit a192144
Show file tree
Hide file tree
Showing 9 changed files with 52 additions and 7 deletions.
2 changes: 1 addition & 1 deletion drivers/net/pppoe.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
6 changes: 6 additions & 0 deletions include/net/ipv6.h
Original file line number Diff line number Diff line change
Expand Up @@ -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] |
Expand Down
11 changes: 11 additions & 0 deletions include/net/net_namespace.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 4 additions & 0 deletions net/core/dev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 3 additions & 0 deletions net/core/net_namespace.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
9 changes: 9 additions & 0 deletions net/ipv6/ip6_input.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
11 changes: 7 additions & 4 deletions net/ipv6/ipv6_sockglue.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
9 changes: 8 additions & 1 deletion net/mac80211/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));

Expand Down Expand Up @@ -1216,6 +1216,13 @@ static int ieee80211_tx(struct net_device *dev, struct sk_buff *skb,
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,
Expand Down
4 changes: 3 additions & 1 deletion net/sctp/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit a192144

Please sign in to comment.