diff options
Diffstat (limited to 'net/core')
| -rw-r--r-- | net/core/dev.c | 23 | ||||
| -rw-r--r-- | net/core/fib_rules.c | 34 | ||||
| -rw-r--r-- | net/core/neighbour.c | 19 | ||||
| -rw-r--r-- | net/core/netpoll.c | 7 | ||||
| -rw-r--r-- | net/core/pktgen.c | 3 | ||||
| -rw-r--r-- | net/core/rtnetlink.c | 3 | ||||
| -rw-r--r-- | net/core/skbuff.c | 58 | ||||
| -rw-r--r-- | net/core/sock.c | 2 | ||||
| -rw-r--r-- | net/core/wireless.c | 82 |
9 files changed, 121 insertions, 110 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) | |||
| 751 | else | 751 | else |
| 752 | strlcpy(dev->name, newname, IFNAMSIZ); | 752 | strlcpy(dev->name, newname, IFNAMSIZ); |
| 753 | 753 | ||
| 754 | err = device_rename(&dev->dev, dev->name); | 754 | device_rename(&dev->dev, dev->name); |
| 755 | if (!err) { | 755 | hlist_del(&dev->name_hlist); |
| 756 | hlist_del(&dev->name_hlist); | 756 | hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name)); |
| 757 | hlist_add_head(&dev->name_hlist, dev_name_hash(dev->name)); | 757 | raw_notifier_call_chain(&netdev_chain, NETDEV_CHANGENAME, dev); |
| 758 | raw_notifier_call_chain(&netdev_chain, | ||
| 759 | NETDEV_CHANGENAME, dev); | ||
| 760 | } | ||
| 761 | 758 | ||
| 762 | return err; | 759 | return err; |
| 763 | } | 760 | } |
| @@ -1741,8 +1738,8 @@ static int ing_filter(struct sk_buff *skb) | |||
| 1741 | if (dev->qdisc_ingress) { | 1738 | if (dev->qdisc_ingress) { |
| 1742 | __u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd); | 1739 | __u32 ttl = (__u32) G_TC_RTTL(skb->tc_verd); |
| 1743 | if (MAX_RED_LOOP < ttl++) { | 1740 | if (MAX_RED_LOOP < ttl++) { |
| 1744 | printk(KERN_WARNING "Redir loop detected Dropping packet (%s->%s)\n", | 1741 | printk(KERN_WARNING "Redir loop detected Dropping packet (%d->%d)\n", |
| 1745 | skb->input_dev->name, skb->dev->name); | 1742 | skb->iif, skb->dev->ifindex); |
| 1746 | return TC_ACT_SHOT; | 1743 | return TC_ACT_SHOT; |
| 1747 | } | 1744 | } |
| 1748 | 1745 | ||
| @@ -1750,10 +1747,10 @@ static int ing_filter(struct sk_buff *skb) | |||
| 1750 | 1747 | ||
| 1751 | skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS); | 1748 | skb->tc_verd = SET_TC_AT(skb->tc_verd,AT_INGRESS); |
| 1752 | 1749 | ||
| 1753 | spin_lock(&dev->ingress_lock); | 1750 | spin_lock(&dev->queue_lock); |
| 1754 | if ((q = dev->qdisc_ingress) != NULL) | 1751 | if ((q = dev->qdisc_ingress) != NULL) |
| 1755 | result = q->enqueue(skb, q); | 1752 | result = q->enqueue(skb, q); |
| 1756 | spin_unlock(&dev->ingress_lock); | 1753 | spin_unlock(&dev->queue_lock); |
| 1757 | 1754 | ||
| 1758 | } | 1755 | } |
| 1759 | 1756 | ||
| @@ -1775,8 +1772,8 @@ int netif_receive_skb(struct sk_buff *skb) | |||
| 1775 | if (!skb->tstamp.off_sec) | 1772 | if (!skb->tstamp.off_sec) |
| 1776 | net_timestamp(skb); | 1773 | net_timestamp(skb); |
| 1777 | 1774 | ||
| 1778 | if (!skb->input_dev) | 1775 | if (!skb->iif) |
| 1779 | skb->input_dev = skb->dev; | 1776 | skb->iif = skb->dev->ifindex; |
| 1780 | 1777 | ||
| 1781 | orig_dev = skb_bond(skb); | 1778 | orig_dev = skb_bond(skb); |
| 1782 | 1779 | ||
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, | |||
| 143 | } | 143 | } |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | err = -ENETUNREACH; | 146 | err = -ESRCH; |
| 147 | out: | 147 | out: |
| 148 | rcu_read_unlock(); | 148 | rcu_read_unlock(); |
| 149 | 149 | ||
| @@ -152,6 +152,28 @@ out: | |||
| 152 | 152 | ||
| 153 | EXPORT_SYMBOL_GPL(fib_rules_lookup); | 153 | EXPORT_SYMBOL_GPL(fib_rules_lookup); |
| 154 | 154 | ||
| 155 | static int validate_rulemsg(struct fib_rule_hdr *frh, struct nlattr **tb, | ||
| 156 | struct fib_rules_ops *ops) | ||
| 157 | { | ||
| 158 | int err = -EINVAL; | ||
| 159 | |||
| 160 | if (frh->src_len) | ||
| 161 | if (tb[FRA_SRC] == NULL || | ||
| 162 | frh->src_len > (ops->addr_size * 8) || | ||
| 163 | nla_len(tb[FRA_SRC]) != ops->addr_size) | ||
| 164 | goto errout; | ||
| 165 | |||
| 166 | if (frh->dst_len) | ||
| 167 | if (tb[FRA_DST] == NULL || | ||
| 168 | frh->dst_len > (ops->addr_size * 8) || | ||
| 169 | nla_len(tb[FRA_DST]) != ops->addr_size) | ||
| 170 | goto errout; | ||
| 171 | |||
| 172 | err = 0; | ||
| 173 | errout: | ||
| 174 | return err; | ||
| 175 | } | ||
| 176 | |||
| 155 | int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | 177 | int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) |
| 156 | { | 178 | { |
| 157 | struct fib_rule_hdr *frh = nlmsg_data(nlh); | 179 | 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) | |||
| 173 | if (err < 0) | 195 | if (err < 0) |
| 174 | goto errout; | 196 | goto errout; |
| 175 | 197 | ||
| 198 | err = validate_rulemsg(frh, tb, ops); | ||
| 199 | if (err < 0) | ||
| 200 | goto errout; | ||
| 201 | |||
| 176 | rule = kzalloc(ops->rule_size, GFP_KERNEL); | 202 | rule = kzalloc(ops->rule_size, GFP_KERNEL); |
| 177 | if (rule == NULL) { | 203 | if (rule == NULL) { |
| 178 | err = -ENOMEM; | 204 | err = -ENOMEM; |
| @@ -260,6 +286,10 @@ int fib_nl_delrule(struct sk_buff *skb, struct nlmsghdr* nlh, void *arg) | |||
| 260 | if (err < 0) | 286 | if (err < 0) |
| 261 | goto errout; | 287 | goto errout; |
| 262 | 288 | ||
| 289 | err = validate_rulemsg(frh, tb, ops); | ||
| 290 | if (err < 0) | ||
| 291 | goto errout; | ||
| 292 | |||
| 263 | list_for_each_entry(rule, ops->rules_list, list) { | 293 | list_for_each_entry(rule, ops->rules_list, list) { |
| 264 | if (frh->action && (frh->action != rule->action)) | 294 | if (frh->action && (frh->action != rule->action)) |
| 265 | continue; | 295 | continue; |
| @@ -374,7 +404,7 @@ int fib_rules_dump(struct sk_buff *skb, struct netlink_callback *cb, int family) | |||
| 374 | return -EAFNOSUPPORT; | 404 | return -EAFNOSUPPORT; |
| 375 | 405 | ||
| 376 | rcu_read_lock(); | 406 | rcu_read_lock(); |
| 377 | list_for_each_entry(rule, ops->rules_list, list) { | 407 | list_for_each_entry_rcu(rule, ops->rules_list, list) { |
| 378 | if (idx < cb->args[0]) | 408 | if (idx < cb->args[0]) |
| 379 | goto skip; | 409 | goto skip; |
| 380 | 410 | ||
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index 3183142c6044..841e3f32cab1 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
| @@ -140,6 +140,8 @@ static int neigh_forced_gc(struct neigh_table *tbl) | |||
| 140 | n->dead = 1; | 140 | n->dead = 1; |
| 141 | shrunk = 1; | 141 | shrunk = 1; |
| 142 | write_unlock(&n->lock); | 142 | write_unlock(&n->lock); |
| 143 | if (n->parms->neigh_cleanup) | ||
| 144 | n->parms->neigh_cleanup(n); | ||
| 143 | neigh_release(n); | 145 | neigh_release(n); |
| 144 | continue; | 146 | continue; |
| 145 | } | 147 | } |
| @@ -211,6 +213,8 @@ static void neigh_flush_dev(struct neigh_table *tbl, struct net_device *dev) | |||
| 211 | NEIGH_PRINTK2("neigh %p is stray.\n", n); | 213 | NEIGH_PRINTK2("neigh %p is stray.\n", n); |
| 212 | } | 214 | } |
| 213 | write_unlock(&n->lock); | 215 | write_unlock(&n->lock); |
| 216 | if (n->parms->neigh_cleanup) | ||
| 217 | n->parms->neigh_cleanup(n); | ||
| 214 | neigh_release(n); | 218 | neigh_release(n); |
| 215 | } | 219 | } |
| 216 | } | 220 | } |
| @@ -582,9 +586,6 @@ void neigh_destroy(struct neighbour *neigh) | |||
| 582 | kfree(hh); | 586 | kfree(hh); |
| 583 | } | 587 | } |
| 584 | 588 | ||
| 585 | if (neigh->parms->neigh_destructor) | ||
| 586 | (neigh->parms->neigh_destructor)(neigh); | ||
| 587 | |||
| 588 | skb_queue_purge(&neigh->arp_queue); | 589 | skb_queue_purge(&neigh->arp_queue); |
| 589 | 590 | ||
| 590 | dev_put(neigh->dev); | 591 | dev_put(neigh->dev); |
| @@ -675,6 +676,8 @@ static void neigh_periodic_timer(unsigned long arg) | |||
| 675 | *np = n->next; | 676 | *np = n->next; |
| 676 | n->dead = 1; | 677 | n->dead = 1; |
| 677 | write_unlock(&n->lock); | 678 | write_unlock(&n->lock); |
| 679 | if (n->parms->neigh_cleanup) | ||
| 680 | n->parms->neigh_cleanup(n); | ||
| 678 | neigh_release(n); | 681 | neigh_release(n); |
| 679 | continue; | 682 | continue; |
| 680 | } | 683 | } |
| @@ -1328,6 +1331,8 @@ void neigh_parms_destroy(struct neigh_parms *parms) | |||
| 1328 | kfree(parms); | 1331 | kfree(parms); |
| 1329 | } | 1332 | } |
| 1330 | 1333 | ||
| 1334 | static struct lock_class_key neigh_table_proxy_queue_class; | ||
| 1335 | |||
| 1331 | void neigh_table_init_no_netlink(struct neigh_table *tbl) | 1336 | void neigh_table_init_no_netlink(struct neigh_table *tbl) |
| 1332 | { | 1337 | { |
| 1333 | unsigned long now = jiffies; | 1338 | unsigned long now = jiffies; |
| @@ -1376,7 +1381,8 @@ void neigh_table_init_no_netlink(struct neigh_table *tbl) | |||
| 1376 | init_timer(&tbl->proxy_timer); | 1381 | init_timer(&tbl->proxy_timer); |
| 1377 | tbl->proxy_timer.data = (unsigned long)tbl; | 1382 | tbl->proxy_timer.data = (unsigned long)tbl; |
| 1378 | tbl->proxy_timer.function = neigh_proxy_process; | 1383 | tbl->proxy_timer.function = neigh_proxy_process; |
| 1379 | skb_queue_head_init(&tbl->proxy_queue); | 1384 | skb_queue_head_init_class(&tbl->proxy_queue, |
| 1385 | &neigh_table_proxy_queue_class); | ||
| 1380 | 1386 | ||
| 1381 | tbl->last_flush = now; | 1387 | tbl->last_flush = now; |
| 1382 | tbl->last_rand = now + tbl->parms.reachable_time * 20; | 1388 | tbl->last_rand = now + tbl->parms.reachable_time * 20; |
| @@ -2088,8 +2094,11 @@ void __neigh_for_each_release(struct neigh_table *tbl, | |||
| 2088 | } else | 2094 | } else |
| 2089 | np = &n->next; | 2095 | np = &n->next; |
| 2090 | write_unlock(&n->lock); | 2096 | write_unlock(&n->lock); |
| 2091 | if (release) | 2097 | if (release) { |
| 2098 | if (n->parms->neigh_cleanup) | ||
| 2099 | n->parms->neigh_cleanup(n); | ||
| 2092 | neigh_release(n); | 2100 | neigh_release(n); |
| 2101 | } | ||
| 2093 | } | 2102 | } |
| 2094 | } | 2103 | } |
| 2095 | } | 2104 | } |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index da1019451ccb..4581ece48bb2 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -471,6 +471,13 @@ int __netpoll_rx(struct sk_buff *skb) | |||
| 471 | if (skb->len < len || len < iph->ihl*4) | 471 | if (skb->len < len || len < iph->ihl*4) |
| 472 | goto out; | 472 | goto out; |
| 473 | 473 | ||
| 474 | /* | ||
| 475 | * Our transport medium may have padded the buffer out. | ||
| 476 | * Now We trim to the true length of the frame. | ||
| 477 | */ | ||
| 478 | if (pskb_trim_rcsum(skb, len)) | ||
| 479 | goto out; | ||
| 480 | |||
| 474 | if (iph->protocol != IPPROTO_UDP) | 481 | if (iph->protocol != IPPROTO_UDP) |
| 475 | goto out; | 482 | goto out; |
| 476 | 483 | ||
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index 74a9a32b906d..4b01496dc33d 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
| @@ -129,6 +129,7 @@ | |||
| 129 | #include <linux/ioport.h> | 129 | #include <linux/ioport.h> |
| 130 | #include <linux/interrupt.h> | 130 | #include <linux/interrupt.h> |
| 131 | #include <linux/capability.h> | 131 | #include <linux/capability.h> |
| 132 | #include <linux/freezer.h> | ||
| 132 | #include <linux/delay.h> | 133 | #include <linux/delay.h> |
| 133 | #include <linux/timer.h> | 134 | #include <linux/timer.h> |
| 134 | #include <linux/list.h> | 135 | #include <linux/list.h> |
| @@ -3333,6 +3334,8 @@ static int pktgen_thread_worker(void *arg) | |||
| 3333 | t->control &= ~(T_REMDEV); | 3334 | t->control &= ~(T_REMDEV); |
| 3334 | } | 3335 | } |
| 3335 | 3336 | ||
| 3337 | try_to_freeze(); | ||
| 3338 | |||
| 3336 | set_current_state(TASK_INTERRUPTIBLE); | 3339 | set_current_state(TASK_INTERRUPTIBLE); |
| 3337 | } | 3340 | } |
| 3338 | 3341 | ||
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) | |||
| 621 | if (err < 0) | 621 | if (err < 0) |
| 622 | goto errout; | 622 | goto errout; |
| 623 | 623 | ||
| 624 | iw += IW_EV_POINT_OFF; | 624 | /* Payload is at an offset in buffer */ |
| 625 | iw = iw_buf + IW_EV_POINT_OFF; | ||
| 625 | } | 626 | } |
| 626 | #endif /* CONFIG_NET_WIRELESS_RTNETLINK */ | 627 | #endif /* CONFIG_NET_WIRELESS_RTNETLINK */ |
| 627 | 628 | ||
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 820761f9eeef..336958fbbcb2 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -197,61 +197,6 @@ nodata: | |||
| 197 | } | 197 | } |
| 198 | 198 | ||
| 199 | /** | 199 | /** |
| 200 | * alloc_skb_from_cache - allocate a network buffer | ||
| 201 | * @cp: kmem_cache from which to allocate the data area | ||
| 202 | * (object size must be big enough for @size bytes + skb overheads) | ||
| 203 | * @size: size to allocate | ||
| 204 | * @gfp_mask: allocation mask | ||
| 205 | * | ||
| 206 | * Allocate a new &sk_buff. The returned buffer has no headroom and | ||
| 207 | * tail room of size bytes. The object has a reference count of one. | ||
| 208 | * The return is the buffer. On a failure the return is %NULL. | ||
| 209 | * | ||
| 210 | * Buffers may only be allocated from interrupts using a @gfp_mask of | ||
| 211 | * %GFP_ATOMIC. | ||
| 212 | */ | ||
| 213 | struct sk_buff *alloc_skb_from_cache(struct kmem_cache *cp, | ||
| 214 | unsigned int size, | ||
| 215 | gfp_t gfp_mask) | ||
| 216 | { | ||
| 217 | struct sk_buff *skb; | ||
| 218 | u8 *data; | ||
| 219 | |||
| 220 | /* Get the HEAD */ | ||
| 221 | skb = kmem_cache_alloc(skbuff_head_cache, | ||
| 222 | gfp_mask & ~__GFP_DMA); | ||
| 223 | if (!skb) | ||
| 224 | goto out; | ||
| 225 | |||
| 226 | /* Get the DATA. */ | ||
| 227 | size = SKB_DATA_ALIGN(size); | ||
| 228 | data = kmem_cache_alloc(cp, gfp_mask); | ||
| 229 | if (!data) | ||
| 230 | goto nodata; | ||
| 231 | |||
| 232 | memset(skb, 0, offsetof(struct sk_buff, truesize)); | ||
| 233 | skb->truesize = size + sizeof(struct sk_buff); | ||
| 234 | atomic_set(&skb->users, 1); | ||
| 235 | skb->head = data; | ||
| 236 | skb->data = data; | ||
| 237 | skb->tail = data; | ||
| 238 | skb->end = data + size; | ||
| 239 | |||
| 240 | atomic_set(&(skb_shinfo(skb)->dataref), 1); | ||
| 241 | skb_shinfo(skb)->nr_frags = 0; | ||
| 242 | skb_shinfo(skb)->gso_size = 0; | ||
| 243 | skb_shinfo(skb)->gso_segs = 0; | ||
| 244 | skb_shinfo(skb)->gso_type = 0; | ||
| 245 | skb_shinfo(skb)->frag_list = NULL; | ||
| 246 | out: | ||
| 247 | return skb; | ||
| 248 | nodata: | ||
| 249 | kmem_cache_free(skbuff_head_cache, skb); | ||
| 250 | skb = NULL; | ||
| 251 | goto out; | ||
| 252 | } | ||
| 253 | |||
| 254 | /** | ||
| 255 | * __netdev_alloc_skb - allocate an skbuff for rx on a specific device | 200 | * __netdev_alloc_skb - allocate an skbuff for rx on a specific device |
| 256 | * @dev: network device to receive on | 201 | * @dev: network device to receive on |
| 257 | * @length: length to allocate | 202 | * @length: length to allocate |
| @@ -463,6 +408,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
| 463 | memcpy(n->cb, skb->cb, sizeof(skb->cb)); | 408 | memcpy(n->cb, skb->cb, sizeof(skb->cb)); |
| 464 | C(len); | 409 | C(len); |
| 465 | C(data_len); | 410 | C(data_len); |
| 411 | C(mac_len); | ||
| 466 | C(csum); | 412 | C(csum); |
| 467 | C(local_df); | 413 | C(local_df); |
| 468 | n->cloned = 1; | 414 | n->cloned = 1; |
| @@ -495,7 +441,7 @@ struct sk_buff *skb_clone(struct sk_buff *skb, gfp_t gfp_mask) | |||
| 495 | n->tc_verd = SET_TC_VERD(skb->tc_verd,0); | 441 | n->tc_verd = SET_TC_VERD(skb->tc_verd,0); |
| 496 | n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd); | 442 | n->tc_verd = CLR_TC_OK2MUNGE(n->tc_verd); |
| 497 | n->tc_verd = CLR_TC_MUNGED(n->tc_verd); | 443 | n->tc_verd = CLR_TC_MUNGED(n->tc_verd); |
| 498 | C(input_dev); | 444 | C(iif); |
| 499 | #endif | 445 | #endif |
| 500 | skb_copy_secmark(n, skb); | 446 | skb_copy_secmark(n, skb); |
| 501 | #endif | 447 | #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: | |||
| 808 | * | 808 | * |
| 809 | * (We also register the sk_lock with the lock validator.) | 809 | * (We also register the sk_lock with the lock validator.) |
| 810 | */ | 810 | */ |
| 811 | static void inline sock_lock_init(struct sock *sk) | 811 | static inline void sock_lock_init(struct sock *sk) |
| 812 | { | 812 | { |
| 813 | sock_lock_init_class_and_name(sk, | 813 | sock_lock_init_class_and_name(sk, |
| 814 | af_family_slock_key_strings[sk->sk_family], | 814 | 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 @@ | |||
| 2 | * This file implement the Wireless Extensions APIs. | 2 | * This file implement the Wireless Extensions APIs. |
| 3 | * | 3 | * |
| 4 | * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> | 4 | * Authors : Jean Tourrilhes - HPL - <jt@hpl.hp.com> |
| 5 | * Copyright (c) 1997-2006 Jean Tourrilhes, All Rights Reserved. | 5 | * Copyright (c) 1997-2007 Jean Tourrilhes, All Rights Reserved. |
| 6 | * | 6 | * |
| 7 | * (As all part of the Linux kernel, this file is GPL) | 7 | * (As all part of the Linux kernel, this file is GPL) |
| 8 | */ | 8 | */ |
| @@ -76,6 +76,9 @@ | |||
| 76 | * o Change length in ESSID and NICK to strlen() instead of strlen()+1 | 76 | * o Change length in ESSID and NICK to strlen() instead of strlen()+1 |
| 77 | * o Make standard_ioctl_num and standard_event_num unsigned | 77 | * o Make standard_ioctl_num and standard_event_num unsigned |
| 78 | * o Remove (struct net_device *)->get_wireless_stats() | 78 | * o Remove (struct net_device *)->get_wireless_stats() |
| 79 | * | ||
| 80 | * v10 - 16.3.07 - Jean II | ||
| 81 | * o Prevent leaking of kernel space in stream on 64 bits. | ||
| 79 | */ | 82 | */ |
| 80 | 83 | ||
| 81 | /***************************** INCLUDES *****************************/ | 84 | /***************************** INCLUDES *****************************/ |
| @@ -427,6 +430,21 @@ static const int event_type_size[] = { | |||
| 427 | IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */ | 430 | IW_EV_QUAL_LEN, /* IW_HEADER_TYPE_QUAL */ |
| 428 | }; | 431 | }; |
| 429 | 432 | ||
| 433 | /* Size (in bytes) of various events, as packed */ | ||
| 434 | static const int event_type_pk_size[] = { | ||
| 435 | IW_EV_LCP_PK_LEN, /* IW_HEADER_TYPE_NULL */ | ||
| 436 | 0, | ||
| 437 | IW_EV_CHAR_PK_LEN, /* IW_HEADER_TYPE_CHAR */ | ||
| 438 | 0, | ||
| 439 | IW_EV_UINT_PK_LEN, /* IW_HEADER_TYPE_UINT */ | ||
| 440 | IW_EV_FREQ_PK_LEN, /* IW_HEADER_TYPE_FREQ */ | ||
| 441 | IW_EV_ADDR_PK_LEN, /* IW_HEADER_TYPE_ADDR */ | ||
| 442 | 0, | ||
| 443 | IW_EV_POINT_PK_LEN, /* Without variable payload */ | ||
| 444 | IW_EV_PARAM_PK_LEN, /* IW_HEADER_TYPE_PARAM */ | ||
| 445 | IW_EV_QUAL_PK_LEN, /* IW_HEADER_TYPE_QUAL */ | ||
| 446 | }; | ||
| 447 | |||
| 430 | /************************ COMMON SUBROUTINES ************************/ | 448 | /************************ COMMON SUBROUTINES ************************/ |
| 431 | /* | 449 | /* |
| 432 | * Stuff that may be used in various place or doesn't fit in one | 450 | * 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, | |||
| 1217 | memcpy(buffer + IW_EV_POINT_OFF, request, request_len); | 1235 | memcpy(buffer + IW_EV_POINT_OFF, request, request_len); |
| 1218 | /* Use our own copy of wrqu */ | 1236 | /* Use our own copy of wrqu */ |
| 1219 | wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF | 1237 | wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF |
| 1220 | + IW_EV_LCP_LEN); | 1238 | + IW_EV_LCP_PK_LEN); |
| 1221 | 1239 | ||
| 1222 | /* No extra arguments. Trivial to handle */ | 1240 | /* No extra arguments. Trivial to handle */ |
| 1223 | ret = handler(dev, &info, wrqu, NULL); | 1241 | ret = handler(dev, &info, wrqu, NULL); |
| @@ -1229,8 +1247,8 @@ static int rtnetlink_standard_get(struct net_device * dev, | |||
| 1229 | 1247 | ||
| 1230 | /* Get a temp copy of wrqu (skip pointer) */ | 1248 | /* Get a temp copy of wrqu (skip pointer) */ |
| 1231 | memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, | 1249 | memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, |
| 1232 | ((char *) request) + IW_EV_LCP_LEN, | 1250 | ((char *) request) + IW_EV_LCP_PK_LEN, |
| 1233 | IW_EV_POINT_LEN - IW_EV_LCP_LEN); | 1251 | IW_EV_POINT_LEN - IW_EV_LCP_PK_LEN); |
| 1234 | 1252 | ||
| 1235 | /* Calculate space needed by arguments. Always allocate | 1253 | /* Calculate space needed by arguments. Always allocate |
| 1236 | * for max space. Easier, and won't last long... */ | 1254 | * for max space. Easier, and won't last long... */ |
| @@ -1240,7 +1258,7 @@ static int rtnetlink_standard_get(struct net_device * dev, | |||
| 1240 | (wrqu_point.data.length > descr->max_tokens)) | 1258 | (wrqu_point.data.length > descr->max_tokens)) |
| 1241 | extra_size = (wrqu_point.data.length | 1259 | extra_size = (wrqu_point.data.length |
| 1242 | * descr->token_size); | 1260 | * descr->token_size); |
| 1243 | buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF; | 1261 | buffer_size = extra_size + IW_EV_POINT_PK_LEN + IW_EV_POINT_OFF; |
| 1244 | #ifdef WE_RTNETLINK_DEBUG | 1262 | #ifdef WE_RTNETLINK_DEBUG |
| 1245 | printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", | 1263 | printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", |
| 1246 | dev->name, extra_size, buffer_size); | 1264 | dev->name, extra_size, buffer_size); |
| @@ -1254,15 +1272,15 @@ static int rtnetlink_standard_get(struct net_device * dev, | |||
| 1254 | 1272 | ||
| 1255 | /* Put wrqu in the right place (just before extra). | 1273 | /* Put wrqu in the right place (just before extra). |
| 1256 | * Leave space for IWE header and dummy pointer... | 1274 | * Leave space for IWE header and dummy pointer... |
| 1257 | * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned... | 1275 | * Note that IW_EV_LCP_PK_LEN==4 bytes, so it's still aligned. |
| 1258 | */ | 1276 | */ |
| 1259 | memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF, | 1277 | memcpy(buffer + IW_EV_LCP_PK_LEN + IW_EV_POINT_OFF, |
| 1260 | ((char *) &wrqu_point) + IW_EV_POINT_OFF, | 1278 | ((char *) &wrqu_point) + IW_EV_POINT_OFF, |
| 1261 | IW_EV_POINT_LEN - IW_EV_LCP_LEN); | 1279 | IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); |
| 1262 | wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN); | 1280 | wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_PK_LEN); |
| 1263 | 1281 | ||
| 1264 | /* Extra comes logically after that. Offset +12 bytes. */ | 1282 | /* Extra comes logically after that. Offset +12 bytes. */ |
| 1265 | extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN; | 1283 | extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_PK_LEN; |
| 1266 | 1284 | ||
| 1267 | /* Call the handler */ | 1285 | /* Call the handler */ |
| 1268 | ret = handler(dev, &info, wrqu, extra); | 1286 | ret = handler(dev, &info, wrqu, extra); |
| @@ -1270,11 +1288,11 @@ static int rtnetlink_standard_get(struct net_device * dev, | |||
| 1270 | /* Calculate real returned length */ | 1288 | /* Calculate real returned length */ |
| 1271 | extra_size = (wrqu->data.length * descr->token_size); | 1289 | extra_size = (wrqu->data.length * descr->token_size); |
| 1272 | /* Re-adjust reply size */ | 1290 | /* Re-adjust reply size */ |
| 1273 | request->len = extra_size + IW_EV_POINT_LEN; | 1291 | request->len = extra_size + IW_EV_POINT_PK_LEN; |
| 1274 | 1292 | ||
| 1275 | /* Put the iwe header where it should, i.e. scrap the | 1293 | /* Put the iwe header where it should, i.e. scrap the |
| 1276 | * dummy pointer. */ | 1294 | * dummy pointer. */ |
| 1277 | memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN); | 1295 | memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_PK_LEN); |
| 1278 | 1296 | ||
| 1279 | #ifdef WE_RTNETLINK_DEBUG | 1297 | #ifdef WE_RTNETLINK_DEBUG |
| 1280 | 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); | 1298 | 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, | |||
| 1331 | #endif /* WE_RTNETLINK_DEBUG */ | 1349 | #endif /* WE_RTNETLINK_DEBUG */ |
| 1332 | 1350 | ||
| 1333 | /* Extract fixed header from request. This is properly aligned. */ | 1351 | /* Extract fixed header from request. This is properly aligned. */ |
| 1334 | wrqu = &request->u; | 1352 | wrqu = (union iwreq_data *) (((char *) request) + IW_EV_LCP_PK_LEN); |
| 1335 | 1353 | ||
| 1336 | /* Check if wrqu is complete */ | 1354 | /* Check if wrqu is complete */ |
| 1337 | hdr_len = event_type_size[descr->header_type]; | 1355 | hdr_len = event_type_pk_size[descr->header_type]; |
| 1338 | if(request_len < hdr_len) { | 1356 | if(request_len < hdr_len) { |
| 1339 | #ifdef WE_RTNETLINK_DEBUG | 1357 | #ifdef WE_RTNETLINK_DEBUG |
| 1340 | printk(KERN_DEBUG | 1358 | printk(KERN_DEBUG |
| @@ -1359,7 +1377,7 @@ static inline int rtnetlink_standard_set(struct net_device * dev, | |||
| 1359 | 1377 | ||
| 1360 | /* Put wrqu in the right place (skip pointer) */ | 1378 | /* Put wrqu in the right place (skip pointer) */ |
| 1361 | memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, | 1379 | memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, |
| 1362 | wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN); | 1380 | wrqu, IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); |
| 1363 | /* Don't forget about the event code... */ | 1381 | /* Don't forget about the event code... */ |
| 1364 | wrqu = &wrqu_point; | 1382 | wrqu = &wrqu_point; |
| 1365 | 1383 | ||
| @@ -1483,7 +1501,7 @@ static inline int rtnetlink_private_get(struct net_device * dev, | |||
| 1483 | hdr_len = extra_size; | 1501 | hdr_len = extra_size; |
| 1484 | extra_size = 0; | 1502 | extra_size = 0; |
| 1485 | } else { | 1503 | } else { |
| 1486 | hdr_len = IW_EV_POINT_LEN; | 1504 | hdr_len = IW_EV_POINT_PK_LEN; |
| 1487 | } | 1505 | } |
| 1488 | 1506 | ||
| 1489 | /* Check if wrqu is complete */ | 1507 | /* Check if wrqu is complete */ |
| @@ -1514,7 +1532,7 @@ static inline int rtnetlink_private_get(struct net_device * dev, | |||
| 1514 | memcpy(buffer + IW_EV_POINT_OFF, request, request_len); | 1532 | memcpy(buffer + IW_EV_POINT_OFF, request, request_len); |
| 1515 | /* Use our own copy of wrqu */ | 1533 | /* Use our own copy of wrqu */ |
| 1516 | wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF | 1534 | wrqu = (union iwreq_data *) (buffer + IW_EV_POINT_OFF |
| 1517 | + IW_EV_LCP_LEN); | 1535 | + IW_EV_LCP_PK_LEN); |
| 1518 | 1536 | ||
| 1519 | /* No extra arguments. Trivial to handle */ | 1537 | /* No extra arguments. Trivial to handle */ |
| 1520 | ret = handler(dev, &info, wrqu, (char *) wrqu); | 1538 | ret = handler(dev, &info, wrqu, (char *) wrqu); |
| @@ -1523,7 +1541,7 @@ static inline int rtnetlink_private_get(struct net_device * dev, | |||
| 1523 | char * extra; | 1541 | char * extra; |
| 1524 | 1542 | ||
| 1525 | /* Buffer for full reply */ | 1543 | /* Buffer for full reply */ |
| 1526 | buffer_size = extra_size + IW_EV_POINT_LEN + IW_EV_POINT_OFF; | 1544 | buffer_size = extra_size + IW_EV_POINT_PK_LEN + IW_EV_POINT_OFF; |
| 1527 | 1545 | ||
| 1528 | #ifdef WE_RTNETLINK_DEBUG | 1546 | #ifdef WE_RTNETLINK_DEBUG |
| 1529 | printk(KERN_DEBUG "%s (WE.r) : Malloc %d bytes (%d bytes)\n", | 1547 | 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, | |||
| 1538 | 1556 | ||
| 1539 | /* Put wrqu in the right place (just before extra). | 1557 | /* Put wrqu in the right place (just before extra). |
| 1540 | * Leave space for IWE header and dummy pointer... | 1558 | * Leave space for IWE header and dummy pointer... |
| 1541 | * Note that IW_EV_LCP_LEN==4 bytes, so it's still aligned... | 1559 | * Note that IW_EV_LCP_PK_LEN==4 bytes, so it's still aligned. |
| 1542 | */ | 1560 | */ |
| 1543 | memcpy(buffer + IW_EV_LCP_LEN + IW_EV_POINT_OFF, | 1561 | memcpy(buffer + IW_EV_LCP_PK_LEN + IW_EV_POINT_OFF, |
| 1544 | ((char *) request) + IW_EV_LCP_LEN, | 1562 | ((char *) request) + IW_EV_LCP_PK_LEN, |
| 1545 | IW_EV_POINT_LEN - IW_EV_LCP_LEN); | 1563 | IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); |
| 1546 | wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_LEN); | 1564 | wrqu = (union iwreq_data *) (buffer + IW_EV_LCP_PK_LEN); |
| 1547 | 1565 | ||
| 1548 | /* Extra comes logically after that. Offset +12 bytes. */ | 1566 | /* Extra comes logically after that. Offset +12 bytes. */ |
| 1549 | extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_LEN; | 1567 | extra = buffer + IW_EV_POINT_OFF + IW_EV_POINT_PK_LEN; |
| 1550 | 1568 | ||
| 1551 | /* Call the handler */ | 1569 | /* Call the handler */ |
| 1552 | ret = handler(dev, &info, wrqu, extra); | 1570 | ret = handler(dev, &info, wrqu, extra); |
| @@ -1556,11 +1574,11 @@ static inline int rtnetlink_private_get(struct net_device * dev, | |||
| 1556 | if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) | 1574 | if (!(descr->get_args & IW_PRIV_SIZE_FIXED)) |
| 1557 | extra_size = adjust_priv_size(descr->get_args, wrqu); | 1575 | extra_size = adjust_priv_size(descr->get_args, wrqu); |
| 1558 | /* Re-adjust reply size */ | 1576 | /* Re-adjust reply size */ |
| 1559 | request->len = extra_size + IW_EV_POINT_LEN; | 1577 | request->len = extra_size + IW_EV_POINT_PK_LEN; |
| 1560 | 1578 | ||
| 1561 | /* Put the iwe header where it should, i.e. scrap the | 1579 | /* Put the iwe header where it should, i.e. scrap the |
| 1562 | * dummy pointer. */ | 1580 | * dummy pointer. */ |
| 1563 | memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_LEN); | 1581 | memcpy(buffer + IW_EV_POINT_OFF, request, IW_EV_LCP_PK_LEN); |
| 1564 | 1582 | ||
| 1565 | #ifdef WE_RTNETLINK_DEBUG | 1583 | #ifdef WE_RTNETLINK_DEBUG |
| 1566 | 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); | 1584 | 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, | |||
| 1641 | /* Does it fits in wrqu ? */ | 1659 | /* Does it fits in wrqu ? */ |
| 1642 | if((descr->set_args & IW_PRIV_SIZE_FIXED) && | 1660 | if((descr->set_args & IW_PRIV_SIZE_FIXED) && |
| 1643 | (extra_size <= IFNAMSIZ)) { | 1661 | (extra_size <= IFNAMSIZ)) { |
| 1644 | hdr_len = IW_EV_LCP_LEN + extra_size; | 1662 | hdr_len = IW_EV_LCP_PK_LEN + extra_size; |
| 1645 | extra_size = 0; | 1663 | extra_size = 0; |
| 1646 | } else { | 1664 | } else { |
| 1647 | hdr_len = IW_EV_POINT_LEN; | 1665 | hdr_len = IW_EV_POINT_PK_LEN; |
| 1648 | } | 1666 | } |
| 1649 | 1667 | ||
| 1650 | /* Extract fixed header from request. This is properly aligned. */ | 1668 | /* Extract fixed header from request. This is properly aligned. */ |
| 1651 | wrqu = &request->u; | 1669 | wrqu = (union iwreq_data *) (((char *) request) + IW_EV_LCP_PK_LEN); |
| 1652 | 1670 | ||
| 1653 | /* Check if wrqu is complete */ | 1671 | /* Check if wrqu is complete */ |
| 1654 | if(request_len < hdr_len) { | 1672 | if(request_len < hdr_len) { |
| @@ -1675,7 +1693,7 @@ static inline int rtnetlink_private_set(struct net_device * dev, | |||
| 1675 | 1693 | ||
| 1676 | /* Put wrqu in the right place (skip pointer) */ | 1694 | /* Put wrqu in the right place (skip pointer) */ |
| 1677 | memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, | 1695 | memcpy(((char *) &wrqu_point) + IW_EV_POINT_OFF, |
| 1678 | wrqu, IW_EV_POINT_LEN - IW_EV_LCP_LEN); | 1696 | wrqu, IW_EV_POINT_PK_LEN - IW_EV_LCP_PK_LEN); |
| 1679 | 1697 | ||
| 1680 | /* Does it fits within bounds ? */ | 1698 | /* Does it fits within bounds ? */ |
| 1681 | if(wrqu_point.data.length > (descr->set_args & | 1699 | if(wrqu_point.data.length > (descr->set_args & |
| @@ -1738,7 +1756,7 @@ int wireless_rtnetlink_get(struct net_device * dev, | |||
| 1738 | iw_handler handler; | 1756 | iw_handler handler; |
| 1739 | 1757 | ||
| 1740 | /* Check length */ | 1758 | /* Check length */ |
| 1741 | if(len < IW_EV_LCP_LEN) { | 1759 | if(len < IW_EV_LCP_PK_LEN) { |
| 1742 | printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", | 1760 | printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", |
| 1743 | dev->name, len); | 1761 | dev->name, len); |
| 1744 | return -EINVAL; | 1762 | return -EINVAL; |
| @@ -1822,7 +1840,7 @@ int wireless_rtnetlink_set(struct net_device * dev, | |||
| 1822 | iw_handler handler; | 1840 | iw_handler handler; |
| 1823 | 1841 | ||
| 1824 | /* Check length */ | 1842 | /* Check length */ |
| 1825 | if(len < IW_EV_LCP_LEN) { | 1843 | if(len < IW_EV_LCP_PK_LEN) { |
| 1826 | printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", | 1844 | printk(KERN_DEBUG "%s (WE.r) : RtNetlink request too short (%d)\n", |
| 1827 | dev->name, len); | 1845 | dev->name, len); |
| 1828 | return -EINVAL; | 1846 | return -EINVAL; |
