aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c23
-rw-r--r--net/core/fib_rules.c34
-rw-r--r--net/core/neighbour.c14
-rw-r--r--net/core/rtnetlink.c3
-rw-r--r--net/core/skbuff.c3
-rw-r--r--net/core/sock.c2
-rw-r--r--net/core/wireless.c82
7 files changed, 107 insertions, 54 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index cf71614dae93..4dc93cc4d5b7 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -751,13 +751,10 @@ int dev_change_name(struct net_device *dev, char *newname)
else
strlcpy(dev->name, newname, IFNAMSIZ);
- err = device_rename(&dev->dev, dev->name);
- if (!err) {
- hlist_del(&dev->name_hlist);
- hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
- raw_notifier_call_chain(&netdev_chain,
- NETDEV_CHANGENAME, dev);
- }
+ device_rename(&dev->dev, dev->name);
+ hlist_del(&dev->name_hlist);
+ hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name));
+ raw_notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev);
return err;
}
@@ -1741,8 +1738,8 @@ static int ing_filter(struct sk_buff *skb)
if (dev->qdisc_ingress) {
__u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd);
if (MAX_RED_LOOP < ttl++) {
- printk(KERN_WARNING "Redir loop detected Dropping packet (%s->%s)\n",
- skb->input_dev->name, skb->dev->name);
+ printk(KERN_WARNING "Redir loop detected Dropping packet (%d->%d)\n",
+ skb->iif, skb->dev->ifindex);
return TC_ACT_SHOT;
}
@@ -1750,10 +1747,10 @@ static int ing_filter(struct sk_buff *skb)
skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS);
- spin_lock(&dev->ingress_lock);
+ spin_lock(&dev->queue_lock);
if ((q = dev->qdisc_ingress) != NULL)
result = q->enqueue(skb, q);
- spin_unlock(&dev->ingress_lock);
+ spin_unlock(&dev->queue_lock);
}
@@ -1775,8 +1772,8 @@ int netif_receive_skb(struct sk_buff *skb)
if (!skb->tstamp.off_sec)
net_timestamp(skb);
- if (!skb->input_dev)
- skb->input_dev = skb->dev;
+ if (!skb->iif)
+ skb->iif = skb->dev->ifindex;
orig_dev = skb_bond(skb);
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 215f1bff048f..7174ced75efc 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -143,7 +143,7 @@ int fib_rules_lookup(struct fib_rules_ops *ops, struct flowi *fl,
}
}
- err = -ENETUNREACH;
+ err = -ESRCH;
out:
rcu_read_unlock();
@@ -152,6 +152,28 @@ out:
EXPORT_SYMBOL_GPL(fib_rules_lookup);
+static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb,
+ struct fib_rules_ops *ops)
+{
+ int err = -EINVAL;
+
+ if (frh->src_len)
+ if (tb[FRA_SRC] == NULL ||
+ frh->src_len > (ops->addr_size * 8) ||
+ nla_len(tb[FRA_SRC]) != ops->addr_size)
+ goto errout;
+
+ if (frh->dst_len)
+ if (tb[FRA_DST] == NULL ||
+ frh->dst_len > (ops->addr_size * 8) ||
+ nla_len(tb[FRA_DST]) != ops->addr_size)
+ goto errout;
+
+ err = 0;
+errout:
+ return err;
+}
+
int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
{
struct fib_rule_hdr *frh = nlmsg_data(nlh);
@@ -173,6 +195,10 @@ int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (err < 0)
goto errout;
+ err = validate_rulemsg(frh, tb, ops);
+ if (err < 0)
+ goto errout;
+
rule = kzalloc(ops->rule_size, GFP_KERNEL);
if (rule == NULL) {
err = -ENOMEM;
@@ -260,6 +286,10 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (err < 0)
goto errout;
+ err = validate_rulemsg(frh, tb, ops);
+ if (err < 0)
+ goto errout;
+
list_for_each_entry(rule, ops->rules_list, list) {
if (frh->action && (frh->action != rule->action))
continue;
@@ -374,7 +404,7 @@ int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family)
return -EAFNOSUPPORT;
rcu_read_lock();
- list_for_each_entry(rule, ops->rules_list, list) {
+ list_for_each_entry_rcu(rule, ops->rules_list, list) {
if (idx < cb->args[0])
goto skip;
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 3183142c6044..cfc60019cf92 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -140,6 +140,8 @@ static int neigh_forced_gc(struct neigh_table *tbl)
n->dead = 1;
shrunk = 1;
write_unlock(&n->lock);
+ if (n->parms->neigh_cleanup)
+ n->parms->neigh_cleanup(n);
neigh_release(n);
continue;
}
@@ -211,6 +213,8 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev)
NEIGH_PRINTK2("neigh %p is stray.\n", n);
}
write_unlock(&n->lock);
+ if (n->parms->neigh_cleanup)
+ n->parms->neigh_cleanup(n);
neigh_release(n);
}
}
@@ -582,9 +586,6 @@ void neigh_destroy(struct neighbour *neigh)
kfree(hh);
}
- if (neigh->parms->neigh_destructor)
- (neigh->parms->neigh_destructor)(neigh);
-
skb_queue_purge(&neigh->arp_queue);
dev_put(neigh->dev);
@@ -675,6 +676,8 @@ static void neigh_periodic_timer(unsigned long arg)
*np = n->next;
n->dead = 1;
write_unlock(&n->lock);
+ if (n->parms->neigh_cleanup)
+ n->parms->neigh_cleanup(n);
neigh_release(n);
continue;
}
@@ -2088,8 +2091,11 @@ void __neigh_for_each_release(struct neigh_table *tbl,
} else
np = &n->next;
write_unlock(&n->lock);
- if (release)
+ if (release) {
+ if (n->parms->neigh_cleanup)
+ n->parms->neigh_cleanup(n);
neigh_release(n);
+ }
}
}
}
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 6055074c4b81..33ea8eac7fe0 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -621,7 +621,8 @@ static int rtnl_getlink(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg)
if (err < 0)
goto errout;
- iw += IW_EV_POINT_OFF;
+ /* Payload is at an offset in buffer */
+ iw = iw_buf + IW_EV_POINT_OFF;
}
#endif /* CONFIG_NET_WIRELESS_RTNETLINK */
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 820761f9eeef..87573ae35b02 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -463,6 +463,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
memcpy(n->cb, skb->cb, sizeof(skb->cb));
C(len);
C(data_len);
+ C(mac_len);
C(csum);
C(local_df);
n->cloned = 1;
@@ -495,7 +496,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask)
n->tc_verd = SET_TC_VERD(skb->tc_verd,0);
n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd);
n->tc_verd = CLR_TC_MUNGED(n->tc_verd);
- C(input_dev);
+ C(iif);
#endif
skb_copy_secmark(n, skb);
#endif
diff --git a/net/core/sock.c b/net/core/sock.c
index 8d65d6478dcd..27c4f62382bd 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -808,7 +808,7 @@ lenout:
*
* (We also register the sk_lock with the lock validator.)
*/
-static void inline sock_lock_init(struct sock *sk)
+static inline void sock_lock_init(struct sock *sk)
{
sock_lock_init_class_and_name(sk,
af_family_slock_key_strings[sk->sk_family],
diff --git a/net/core/wireless.c b/net/core/wireless.c
index 9936ab11e6e0..b07fe270a508 100644
--- a/net/core/wireless.c
+++ b/net/core/wireless.c
@@ -2,7 +2,7 @@
* This file implement the Wireless Extensions APIs.
*
* Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com>
- * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved.
+ * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved.
*
* (As all part of the Linux kernel, this file is GPL)
*/
@@ -76,6 +76,9 @@
* o Change length in ESSID and NICK to strlen() instead of strlen()+1
* o Make standard_ioctl_num and standard_event_num unsigned
* o Remove (struct net_device *)->get_wireless_stats()
+ *
+ * v10 - 16.3.07 - Jean II
+ * o Prevent leaking of kernel space in stream on 64 bits.
*/
/***************************** INCLUDES *****************************/
@@ -427,6 +430,21 @@ static const int event_type_size[] = {
IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */
};
+/* Size (in bytes) of various events, as packed */
+static const int event_type_pk_size[] = {
+ IW_EV_LCP_PK_LEN, /* IW_HEADER_TYPE_NULL */
+ 0,
+ IW_EV_CHAR_PK_LEN, /* IW_HEADER_TYPE_CHAR */
+ 0,
+ IW_EV_UINT_PK_LEN, /* IW_HEADER_TYPE_UINT */
+ IW_EV_FREQ_PK_LEN, /* IW_HEADER_TYPE_FREQ */
+ IW_EV_ADDR_PK_LEN, /* IW_HEADER_TYPE_ADDR */
+ 0,
+ IW_EV_POINT_PK_LEN, /* Without variable payload */
+ IW_EV_PARAM_PK_LEN, /* IW_HEADER_TYPE_PARAM */
+ IW_EV_QUAL_PK_LEN, /* IW_HEADER_TYPE_QUAL */
+};
+
/************************ COMMON SUBROUTINES ************************/
/*
* Stuff that may be used in various place or doesn't fit in one
@@ -1217,7 +1235,7 @@ static int rtnetlink_standard_get(struct net_device * dev,
memcpy(buffer + IW_EV_POINT_OFF, request, request_len);
/* Use our own copy of wrqu */
wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF
- + IW_EV_LCP_LEN);
+ + IW_EV_LCP_PK_LEN);
/* No extra arguments. Trivial to handle */
ret = handler(dev, &info, wrqu, NULL);
@@ -1229,8 +1247,8 @@ static int rtnetlink_standard_get(struct net_device * dev,
/* Get a temp copy of wrqu (skip pointer) */
memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
- ((char *) request) + IW_EV_LCP_LEN,
- IW_EV_POINT_LEN - IW_EV_LCP_LEN);
+ ((char *) request) + IW_EV_LCP_PK_LEN,
+ IW_EV_POINT_LEN - IW_EV_LCP_PK_LEN);
/* Calculate space needed by arguments. Always allocate
* for max space. Easier, and won't last long... */
@@ -1240,7 +1258,7 @@ static int rtnetlink_standard_get(struct net_device * dev,
(wrqu_point.data.length > descr->max_tokens))
extra_size = (wrqu_point.data.length
* descr->token_size);
- buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF;
+ buffer_size = extra_size + IW_EV_POINT_PK_LEN + IW_EV_POINT_OFF;
#ifdef WE_RTNETLINK_DEBUG
printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n",
dev->name, extra_size, buffer_size);
@@ -1254,15 +1272,15 @@ static int rtnetlink_standard_get(struct net_device * dev,
/* Put wrqu in the right place (just before extra).
* Leave space for IWE header and dummy pointer...
- * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned...
+ * Note that IW_EV_LCP_PK_LEN==4 bytes, so it's still aligned.
*/
- memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
+ memcpy(buffer + IW_EV_LCP_PK_LEN + IW_EV_POINT_OFF,
((char *) &wrqu_point) + IW_EV_POINT_OFF,
- IW_EV_POINT_LEN - IW_EV_LCP_LEN);
- wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN);
+ IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
+ wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_PK_LEN);
/* Extra comes logically after that. Offset +12 bytes. */
- extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN;
+ extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_PK_LEN;
/* Call the handler */
ret = handler(dev, &info, wrqu, extra);
@@ -1270,11 +1288,11 @@ static int rtnetlink_standard_get(struct net_device * dev,
/* Calculate real returned length */
extra_size = (wrqu->data.length * descr->token_size);
/* Re-adjust reply size */
- request->len = extra_size + IW_EV_POINT_LEN;
+ request->len = extra_size + IW_EV_POINT_PK_LEN;
/* Put the iwe header where it should, i.e. scrap the
* dummy pointer. */
- memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN);
+ memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_PK_LEN);
#ifdef WE_RTNETLINK_DEBUG
printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size);
@@ -1331,10 +1349,10 @@ static inline int rtnetlink_standard_set(struct net_device * dev,
#endif /* WE_RTNETLINK_DEBUG */
/* Extract fixed header from request. This is properly aligned. */
- wrqu = &request->u;
+ wrqu = (union iwreq_data *) (((char *) request) + IW_EV_LCP_PK_LEN);
/* Check if wrqu is complete */
- hdr_len = event_type_size[descr->header_type];
+ hdr_len = event_type_pk_size[descr->header_type];
if(request_len < hdr_len) {
#ifdef WE_RTNETLINK_DEBUG
printk(KERN_DEBUG
@@ -1359,7 +1377,7 @@ static inline int rtnetlink_standard_set(struct net_device * dev,
/* Put wrqu in the right place (skip pointer) */
memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
- wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN);
+ wrqu, IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
/* Don't forget about the event code... */
wrqu = &wrqu_point;
@@ -1483,7 +1501,7 @@ static inline int rtnetlink_private_get(struct net_device * dev,
hdr_len = extra_size;
extra_size = 0;
} else {
- hdr_len = IW_EV_POINT_LEN;
+ hdr_len = IW_EV_POINT_PK_LEN;
}
/* Check if wrqu is complete */
@@ -1514,7 +1532,7 @@ static inline int rtnetlink_private_get(struct net_device * dev,
memcpy(buffer + IW_EV_POINT_OFF, request, request_len);
/* Use our own copy of wrqu */
wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF
- + IW_EV_LCP_LEN);
+ + IW_EV_LCP_PK_LEN);
/* No extra arguments. Trivial to handle */
ret = handler(dev, &info, wrqu, (char *) wrqu);
@@ -1523,7 +1541,7 @@ static inline int rtnetlink_private_get(struct net_device * dev,
char * extra;
/* Buffer for full reply */
- buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF;
+ buffer_size = extra_size + IW_EV_POINT_PK_LEN + IW_EV_POINT_OFF;
#ifdef WE_RTNETLINK_DEBUG
printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n",
@@ -1538,15 +1556,15 @@ static inline int rtnetlink_private_get(struct net_device * dev,
/* Put wrqu in the right place (just before extra).
* Leave space for IWE header and dummy pointer...
- * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned...
+ * Note that IW_EV_LCP_PK_LEN==4 bytes, so it's still aligned.
*/
- memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF,
- ((char *) request) + IW_EV_LCP_LEN,
- IW_EV_POINT_LEN - IW_EV_LCP_LEN);
- wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN);
+ memcpy(buffer + IW_EV_LCP_PK_LEN + IW_EV_POINT_OFF,
+ ((char *) request) + IW_EV_LCP_PK_LEN,
+ IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
+ wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_PK_LEN);
/* Extra comes logically after that. Offset +12 bytes. */
- extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN;
+ extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_PK_LEN;
/* Call the handler */
ret = handler(dev, &info, wrqu, extra);
@@ -1556,11 +1574,11 @@ static inline int rtnetlink_private_get(struct net_device * dev,
if (!(descr->get_args & IW_PRIV_SIZE_FIXED))
extra_size = adjust_priv_size(descr->get_args, wrqu);
/* Re-adjust reply size */
- request->len = extra_size + IW_EV_POINT_LEN;
+ request->len = extra_size + IW_EV_POINT_PK_LEN;
/* Put the iwe header where it should, i.e. scrap the
* dummy pointer. */
- memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN);
+ memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_PK_LEN);
#ifdef WE_RTNETLINK_DEBUG
printk(KERN_DEBUG "%s (WE.r) : Reply 0x%04X, hdr_len %d, tokens %d, extra_size %d, buffer_size %d\n", dev->name, cmd, hdr_len, wrqu->data.length, extra_size, buffer_size);
@@ -1641,14 +1659,14 @@ static inline int rtnetlink_private_set(struct net_device * dev,
/* Does it fits in wrqu ? */
if((descr->set_args & IW_PRIV_SIZE_FIXED) &&
(extra_size <= IFNAMSIZ)) {
- hdr_len = IW_EV_LCP_LEN + extra_size;
+ hdr_len = IW_EV_LCP_PK_LEN + extra_size;
extra_size = 0;
} else {
- hdr_len = IW_EV_POINT_LEN;
+ hdr_len = IW_EV_POINT_PK_LEN;
}
/* Extract fixed header from request. This is properly aligned. */
- wrqu = &request->u;
+ wrqu = (union iwreq_data *) (((char *) request) + IW_EV_LCP_PK_LEN);
/* Check if wrqu is complete */
if(request_len < hdr_len) {
@@ -1675,7 +1693,7 @@ static inline int rtnetlink_private_set(struct net_device * dev,
/* Put wrqu in the right place (skip pointer) */
memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF,
- wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN);
+ wrqu, IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN);
/* Does it fits within bounds ? */
if(wrqu_point.data.length > (descr->set_args &
@@ -1738,7 +1756,7 @@ int wireless_rtnetlink_get(struct net_device * dev,
iw_handler handler;
/* Check length */
- if(len < IW_EV_LCP_LEN) {
+ if(len < IW_EV_LCP_PK_LEN) {
printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n",
dev->name, len);
return -EINVAL;
@@ -1822,7 +1840,7 @@ int wireless_rtnetlink_set(struct net_device * dev,
iw_handler handler;
/* Check length */
- if(len < IW_EV_LCP_LEN) {
+ if(len < IW_EV_LCP_PK_LEN) {
printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n",
dev->name, len);
return -EINVAL;