diff options
Diffstat (limited to 'net')
64 files changed, 480 insertions, 288 deletions
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index dbf9b47681f..a2e0dd047e9 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -228,6 +228,8 @@ ax25_cb *ax25_find_cb(ax25_address *src_addr, ax25_address *dest_addr, return NULL; } +EXPORT_SYMBOL(ax25_find_cb); + void ax25_send_to_raw(ax25_address *addr, struct sk_buff *skb, int proto) { ax25_cb *s; @@ -424,6 +426,26 @@ static int ax25_ctl_ioctl(const unsigned int cmd, void __user *arg) return 0; } +static void ax25_fillin_cb_from_dev(ax25_cb *ax25, ax25_dev *ax25_dev) +{ + ax25->rtt = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]) / 2; + ax25->t1 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]); + ax25->t2 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T2]); + ax25->t3 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T3]); + ax25->n2 = ax25_dev->values[AX25_VALUES_N2]; + ax25->paclen = ax25_dev->values[AX25_VALUES_PACLEN]; + ax25->idle = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_IDLE]); + ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF]; + + if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) { + ax25->modulus = AX25_EMODULUS; + ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW]; + } else { + ax25->modulus = AX25_MODULUS; + ax25->window = ax25_dev->values[AX25_VALUES_WINDOW]; + } +} + /* * Fill in a created AX.25 created control block with the default * values for a particular device. @@ -433,39 +455,28 @@ void ax25_fillin_cb(ax25_cb *ax25, ax25_dev *ax25_dev) ax25->ax25_dev = ax25_dev; if (ax25->ax25_dev != NULL) { - ax25->rtt = ax25_dev->values[AX25_VALUES_T1] / 2; - ax25->t1 = ax25_dev->values[AX25_VALUES_T1]; - ax25->t2 = ax25_dev->values[AX25_VALUES_T2]; - ax25->t3 = ax25_dev->values[AX25_VALUES_T3]; - ax25->n2 = ax25_dev->values[AX25_VALUES_N2]; - ax25->paclen = ax25_dev->values[AX25_VALUES_PACLEN]; - ax25->idle = ax25_dev->values[AX25_VALUES_IDLE]; - ax25->backoff = ax25_dev->values[AX25_VALUES_BACKOFF]; - - if (ax25_dev->values[AX25_VALUES_AXDEFMODE]) { - ax25->modulus = AX25_EMODULUS; - ax25->window = ax25_dev->values[AX25_VALUES_EWINDOW]; - } else { - ax25->modulus = AX25_MODULUS; - ax25->window = ax25_dev->values[AX25_VALUES_WINDOW]; - } + ax25_fillin_cb_from_dev(ax25, ax25_dev); + return; + } + + /* + * No device, use kernel / AX.25 spec default values + */ + ax25->rtt = msecs_to_jiffies(AX25_DEF_T1) / 2; + ax25->t1 = msecs_to_jiffies(AX25_DEF_T1); + ax25->t2 = msecs_to_jiffies(AX25_DEF_T2); + ax25->t3 = msecs_to_jiffies(AX25_DEF_T3); + ax25->n2 = AX25_DEF_N2; + ax25->paclen = AX25_DEF_PACLEN; + ax25->idle = msecs_to_jiffies(AX25_DEF_IDLE); + ax25->backoff = AX25_DEF_BACKOFF; + + if (AX25_DEF_AXDEFMODE) { + ax25->modulus = AX25_EMODULUS; + ax25->window = AX25_DEF_EWINDOW; } else { - ax25->rtt = AX25_DEF_T1 / 2; - ax25->t1 = AX25_DEF_T1; - ax25->t2 = AX25_DEF_T2; - ax25->t3 = AX25_DEF_T3; - ax25->n2 = AX25_DEF_N2; - ax25->paclen = AX25_DEF_PACLEN; - ax25->idle = AX25_DEF_IDLE; - ax25->backoff = AX25_DEF_BACKOFF; - - if (AX25_DEF_AXDEFMODE) { - ax25->modulus = AX25_EMODULUS; - ax25->window = AX25_DEF_EWINDOW; - } else { - ax25->modulus = AX25_MODULUS; - ax25->window = AX25_DEF_WINDOW; - } + ax25->modulus = AX25_MODULUS; + ax25->window = AX25_DEF_WINDOW; } } @@ -1979,24 +1990,6 @@ static struct notifier_block ax25_dev_notifier = { .notifier_call =ax25_device_event, }; -EXPORT_SYMBOL(ax25_hard_header); -EXPORT_SYMBOL(ax25_rebuild_header); -EXPORT_SYMBOL(ax25_findbyuid); -EXPORT_SYMBOL(ax25_find_cb); -EXPORT_SYMBOL(ax25_linkfail_register); -EXPORT_SYMBOL(ax25_linkfail_release); -EXPORT_SYMBOL(ax25_listen_register); -EXPORT_SYMBOL(ax25_listen_release); -EXPORT_SYMBOL(ax25_protocol_register); -EXPORT_SYMBOL(ax25_protocol_release); -EXPORT_SYMBOL(ax25_send_frame); -EXPORT_SYMBOL(ax25_uid_policy); -EXPORT_SYMBOL(ax25cmp); -EXPORT_SYMBOL(ax2asc); -EXPORT_SYMBOL(asc2ax); -EXPORT_SYMBOL(null_ax25_address); -EXPORT_SYMBOL(ax25_display_timer); - static int __init ax25_init(void) { int rc = proto_register(&ax25_proto, 0); diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c index 0164a155b8c..5f0896ad004 100644 --- a/net/ax25/ax25_addr.c +++ b/net/ax25/ax25_addr.c @@ -11,6 +11,7 @@ #include <linux/socket.h> #include <linux/in.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/sched.h> #include <linux/timer.h> #include <linux/string.h> @@ -33,6 +34,8 @@ */ ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}}; +EXPORT_SYMBOL(null_ax25_address); + /* * ax25 -> ascii conversion */ @@ -64,6 +67,8 @@ char *ax2asc(char *buf, ax25_address *a) } +EXPORT_SYMBOL(ax2asc); + /* * ascii -> ax25 conversion */ @@ -97,6 +102,8 @@ void asc2ax(ax25_address *addr, char *callsign) addr->ax25_call[6] &= 0x1E; } +EXPORT_SYMBOL(asc2ax); + /* * Compare two ax.25 addresses */ @@ -116,6 +123,8 @@ int ax25cmp(ax25_address *a, ax25_address *b) return 2; /* Partial match */ } +EXPORT_SYMBOL(ax25cmp); + /* * Compare two AX.25 digipeater paths. */ diff --git a/net/ax25/ax25_ds_timer.c b/net/ax25/ax25_ds_timer.c index 061083efc1d..5961459935e 100644 --- a/net/ax25/ax25_ds_timer.c +++ b/net/ax25/ax25_ds_timer.c @@ -61,7 +61,8 @@ void ax25_ds_set_timer(ax25_dev *ax25_dev) return; del_timer(&ax25_dev->dama.slave_timer); - ax25_dev->dama.slave_timeout = ax25_dev->values[AX25_VALUES_DS_TIMEOUT] / 10; + ax25_dev->dama.slave_timeout = + msecs_to_jiffies(ax25_dev->values[AX25_VALUES_DS_TIMEOUT]) / 10; ax25_ds_add_timer(ax25_dev); } diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c index d68aff10072..3bb152710b7 100644 --- a/net/ax25/ax25_iface.c +++ b/net/ax25/ax25_iface.c @@ -12,6 +12,7 @@ #include <linux/socket.h> #include <linux/in.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/sched.h> #include <linux/spinlock.h> #include <linux/timer.h> @@ -74,6 +75,8 @@ int ax25_protocol_register(unsigned int pid, return 1; } +EXPORT_SYMBOL(ax25_protocol_register); + void ax25_protocol_release(unsigned int pid) { struct protocol_struct *s, *protocol; @@ -106,6 +109,8 @@ void ax25_protocol_release(unsigned int pid) write_unlock(&protocol_list_lock); } +EXPORT_SYMBOL(ax25_protocol_release); + int ax25_linkfail_register(void (*func)(ax25_cb *, int)) { struct linkfail_struct *linkfail; @@ -123,6 +128,8 @@ int ax25_linkfail_register(void (*func)(ax25_cb *, int)) return 1; } +EXPORT_SYMBOL(ax25_linkfail_register); + void ax25_linkfail_release(void (*func)(ax25_cb *, int)) { struct linkfail_struct *s, *linkfail; @@ -155,6 +162,8 @@ void ax25_linkfail_release(void (*func)(ax25_cb *, int)) spin_unlock_bh(&linkfail_lock); } +EXPORT_SYMBOL(ax25_linkfail_release); + int ax25_listen_register(ax25_address *callsign, struct net_device *dev) { struct listen_struct *listen; @@ -176,6 +185,8 @@ int ax25_listen_register(ax25_address *callsign, struct net_device *dev) return 1; } +EXPORT_SYMBOL(ax25_listen_register); + void ax25_listen_release(ax25_address *callsign, struct net_device *dev) { struct listen_struct *s, *listen; @@ -208,6 +219,8 @@ void ax25_listen_release(ax25_address *callsign, struct net_device *dev) spin_unlock_bh(&listen_lock); } +EXPORT_SYMBOL(ax25_listen_release); + int (*ax25_protocol_function(unsigned int pid))(struct sk_buff *, ax25_cb *) { int (*res)(struct sk_buff *, ax25_cb *) = NULL; diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c index d643dac3ecc..a0b534f80f1 100644 --- a/net/ax25/ax25_ip.c +++ b/net/ax25/ax25_ip.c @@ -12,6 +12,7 @@ #include <linux/socket.h> #include <linux/in.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/sched.h> #include <linux/timer.h> #include <linux/string.h> @@ -221,3 +222,5 @@ int ax25_rebuild_header(struct sk_buff *skb) #endif +EXPORT_SYMBOL(ax25_hard_header); +EXPORT_SYMBOL(ax25_rebuild_header); diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c index 5fc048dcd39..5d99852b239 100644 --- a/net/ax25/ax25_out.c +++ b/net/ax25/ax25_out.c @@ -14,6 +14,7 @@ #include <linux/socket.h> #include <linux/in.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/sched.h> #include <linux/timer.h> #include <linux/string.h> @@ -104,6 +105,8 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, ax25_address *src, ax2 return ax25; /* We had to create it */ } +EXPORT_SYMBOL(ax25_send_frame); + /* * All outgoing AX.25 I frames pass via this routine. Therefore this is * where the fragmentation of frames takes place. If fragment is set to diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c index f04f8630fd2..5ac98250797 100644 --- a/net/ax25/ax25_route.c +++ b/net/ax25/ax25_route.c @@ -360,7 +360,7 @@ struct file_operations ax25_route_fops = { /* * Find AX.25 route * - * Only routes with a refernce rout of zero can be destroyed. + * Only routes with a reference count of zero can be destroyed. */ static ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev) { diff --git a/net/ax25/ax25_timer.c b/net/ax25/ax25_timer.c index 7a6b50a1455..ec254057f21 100644 --- a/net/ax25/ax25_timer.c +++ b/net/ax25/ax25_timer.c @@ -18,6 +18,7 @@ #include <linux/socket.h> #include <linux/in.h> #include <linux/kernel.h> +#include <linux/module.h> #include <linux/jiffies.h> #include <linux/timer.h> #include <linux/string.h> @@ -137,6 +138,8 @@ unsigned long ax25_display_timer(struct timer_list *timer) return timer->expires - jiffies; } +EXPORT_SYMBOL(ax25_display_timer); + static void ax25_heartbeat_expiry(unsigned long param) { int proto = AX25_PROTO_STD_SIMPLEX; diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index b8b5854bce9..5e9a81e8b21 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c @@ -49,6 +49,8 @@ static DEFINE_RWLOCK(ax25_uid_lock); int ax25_uid_policy = 0; +EXPORT_SYMBOL(ax25_uid_policy); + ax25_uid_assoc *ax25_findbyuid(uid_t uid) { ax25_uid_assoc *ax25_uid, *res = NULL; @@ -67,6 +69,8 @@ ax25_uid_assoc *ax25_findbyuid(uid_t uid) return res; } +EXPORT_SYMBOL(ax25_findbyuid); + int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) { ax25_uid_assoc *ax25_uid; diff --git a/net/ax25/sysctl_net_ax25.c b/net/ax25/sysctl_net_ax25.c index 894a22558d9..bdb64c36df1 100644 --- a/net/ax25/sysctl_net_ax25.c +++ b/net/ax25/sysctl_net_ax25.c @@ -18,14 +18,14 @@ static int min_backoff[1], max_backoff[] = {2}; static int min_conmode[1], max_conmode[] = {2}; static int min_window[] = {1}, max_window[] = {7}; static int min_ewindow[] = {1}, max_ewindow[] = {63}; -static int min_t1[] = {1}, max_t1[] = {30 * HZ}; -static int min_t2[] = {1}, max_t2[] = {20 * HZ}; -static int min_t3[1], max_t3[] = {3600 * HZ}; -static int min_idle[1], max_idle[] = {65535 * HZ}; +static int min_t1[] = {1}, max_t1[] = {30000}; +static int min_t2[] = {1}, max_t2[] = {20000}; +static int min_t3[1], max_t3[] = {3600000}; +static int min_idle[1], max_idle[] = {65535000}; static int min_n2[] = {1}, max_n2[] = {31}; static int min_paclen[] = {1}, max_paclen[] = {512}; static int min_proto[1], max_proto[] = { AX25_PROTO_MAX }; -static int min_ds_timeout[1], max_ds_timeout[] = {65535 * HZ}; +static int min_ds_timeout[1], max_ds_timeout[] = {65535000}; static struct ctl_table_header *ax25_table_header; diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index 2d24fb400e0..56f3aa47e75 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c @@ -16,6 +16,7 @@ #include <linux/kernel.h> #include <linux/netdevice.h> #include <linux/skbuff.h> +#include <linux/if_vlan.h> #include <linux/netfilter_bridge.h> #include "br_private.h" @@ -29,10 +30,15 @@ static inline int should_deliver(const struct net_bridge_port *p, return 1; } +static inline unsigned packet_length(const struct sk_buff *skb) +{ + return skb->len - (skb->protocol == htons(ETH_P_8021Q) ? VLAN_HLEN : 0); +} + int br_dev_queue_push_xmit(struct sk_buff *skb) { /* drop mtu oversized packets except tso */ - if (skb->len > skb->dev->mtu && !skb_shinfo(skb)->tso_size) + if (packet_length(skb) > skb->dev->mtu && !skb_shinfo(skb)->tso_size) kfree_skb(skb); else { #ifdef CONFIG_BRIDGE_NETFILTER diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index b0b7f55c1ed..bfa4d8c333f 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c @@ -66,6 +66,7 @@ int br_handle_frame_finish(struct sk_buff *skb) } if (is_multicast_ether_addr(dest)) { + br->statistics.multicast++; br_flood_forward(br, skb, !passedup); if (!passedup) br_pass_frame_up(br, skb); diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 84b9af76f0a..3a13ed64345 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -831,7 +831,7 @@ static int translate_table(struct ebt_replace *repl, return -ENOMEM; for_each_possible_cpu(i) { newinfo->chainstack[i] = - vmalloc(udc_cnt * sizeof(struct ebt_chainstack)); + vmalloc(udc_cnt * sizeof(*(newinfo->chainstack[0]))); if (!newinfo->chainstack[i]) { while (i) vfree(newinfo->chainstack[--i]); @@ -841,8 +841,7 @@ static int translate_table(struct ebt_replace *repl, } } - cl_s = (struct ebt_cl_stack *) - vmalloc(udc_cnt * sizeof(struct ebt_cl_stack)); + cl_s = vmalloc(udc_cnt * sizeof(*cl_s)); if (!cl_s) return -ENOMEM; i = 0; /* the i'th udc */ @@ -944,8 +943,7 @@ static int do_replace(void __user *user, unsigned int len) countersize = COUNTER_OFFSET(tmp.nentries) * (highest_possible_processor_id()+1); - newinfo = (struct ebt_table_info *) - vmalloc(sizeof(struct ebt_table_info) + countersize); + newinfo = vmalloc(sizeof(*newinfo) + countersize); if (!newinfo) return -ENOMEM; @@ -967,8 +965,7 @@ static int do_replace(void __user *user, unsigned int len) /* the user wants counters back the check on the size is done later, when we have the lock */ if (tmp.num_counters) { - counterstmp = (struct ebt_counter *) - vmalloc(tmp.num_counters * sizeof(struct ebt_counter)); + counterstmp = vmalloc(tmp.num_counters * sizeof(*counterstmp)); if (!counterstmp) { ret = -ENOMEM; goto free_entries; @@ -1148,8 +1145,7 @@ int ebt_register_table(struct ebt_table *table) countersize = COUNTER_OFFSET(table->table->nentries) * (highest_possible_processor_id()+1); - newinfo = (struct ebt_table_info *) - vmalloc(sizeof(struct ebt_table_info) + countersize); + newinfo = vmalloc(sizeof(*newinfo) + countersize); ret = -ENOMEM; if (!newinfo) return -ENOMEM; @@ -1247,8 +1243,7 @@ static int update_counters(void __user *user, unsigned int len) if (hlp.num_counters == 0) return -EINVAL; - if ( !(tmp = (struct ebt_counter *) - vmalloc(hlp.num_counters * sizeof(struct ebt_counter))) ){ + if (!(tmp = vmalloc(hlp.num_counters * sizeof(*tmp)))) { MEMPRINT("Update_counters && nomemory\n"); return -ENOMEM; } @@ -1377,8 +1372,7 @@ static int copy_everything_to_user(struct ebt_table *t, void __user *user, BUGPRINT("Num_counters wrong\n"); return -EINVAL; } - counterstmp = (struct ebt_counter *) - vmalloc(nentries * sizeof(struct ebt_counter)); + counterstmp = vmalloc(nentries * sizeof(*counterstmp)); if (!counterstmp) { MEMPRINT("Couldn't copy counters, out of memory\n"); return -ENOMEM; diff --git a/net/core/dev.c b/net/core/dev.c index 83231a27ae0..9ab3cfa5846 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -2698,7 +2698,8 @@ int dev_ioctl(unsigned int cmd, void __user *arg) /* If command is `set a parameter', or * `get the encoding parameters', check if * the user has the right to do it */ - if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE) { + if (IW_IS_SET(cmd) || cmd == SIOCGIWENCODE + || cmd == SIOCGIWENCODEEXT) { if (!capable(CAP_NET_ADMIN)) return -EPERM; } @@ -3042,11 +3043,11 @@ void netdev_run_todo(void) switch(dev->reg_state) { case NETREG_REGISTERING: - dev->reg_state = NETREG_REGISTERED; err = netdev_register_sysfs(dev); if (err) printk(KERN_ERR "%s: failed sysfs registration (%d)\n", dev->name, err); + dev->reg_state = NETREG_REGISTERED; break; case NETREG_UNREGISTERING: diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index c12990c9c60..47a6fceb677 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -29,7 +29,7 @@ static const char fmt_ulong[] = "%lu\n"; static inline int dev_isalive(const struct net_device *dev) { - return dev->reg_state == NETREG_REGISTERED; + return dev->reg_state <= NETREG_REGISTERED; } /* use same locking rules as GIF* ioctl's */ @@ -445,58 +445,33 @@ static struct class net_class = { void netdev_unregister_sysfs(struct net_device * net) { - struct class_device * class_dev = &(net->class_dev); - - if (net->get_stats) - sysfs_remove_group(&class_dev->kobj, &netstat_group); - -#ifdef WIRELESS_EXT - if (net->get_wireless_stats || (net->wireless_handlers && - net->wireless_handlers->get_wireless_stats)) - sysfs_remove_group(&class_dev->kobj, &wireless_group); -#endif - class_device_del(class_dev); - + class_device_del(&(net->class_dev)); } /* Create sysfs entries for network device. */ int netdev_register_sysfs(struct net_device *net) { struct class_device *class_dev = &(net->class_dev); - int ret; + struct attribute_group **groups = net->sysfs_groups; + class_device_initialize(class_dev); class_dev->class = &net_class; class_dev->class_data = net; + class_dev->groups = groups; + BUILD_BUG_ON(BUS_ID_SIZE < IFNAMSIZ); strlcpy(class_dev->class_id, net->name, BUS_ID_SIZE); - if ((ret = class_device_register(class_dev))) - goto out; - if (net->get_stats && - (ret = sysfs_create_group(&class_dev->kobj, &netstat_group))) - goto out_unreg; + if (net->get_stats) + *groups++ = &netstat_group; #ifdef WIRELESS_EXT - if (net->get_wireless_stats || (net->wireless_handlers && - net->wireless_handlers->get_wireless_stats)) { - ret = sysfs_create_group(&class_dev->kobj, &wireless_group); - if (ret) - goto out_cleanup; - } - return 0; -out_cleanup: - if (net->get_stats) - sysfs_remove_group(&class_dev->kobj, &netstat_group); -#else - return 0; + if (net->get_wireless_stats + || (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)) + *groups++ = &wireless_group; #endif -out_unreg: - printk(KERN_WARNING "%s: sysfs attribute registration failed %d\n", - net->name, ret); - class_device_unregister(class_dev); -out: - return ret; + return class_device_add(class_dev); } int netdev_sysfs_init(void) diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 09464fa8d72..fb3770f9c09 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c @@ -112,6 +112,14 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here) BUG(); } +void skb_truesize_bug(struct sk_buff *skb) +{ + printk(KERN_ERR "SKB BUG: Invalid truesize (%u) " + "len=%u, sizeof(sk_buff)=%Zd\n", + skb->truesize, skb->len, sizeof(struct sk_buff)); +} +EXPORT_SYMBOL(skb_truesize_bug); + /* Allocate a new skbuff. We do this ourselves so we can fill in a few * 'private' fields and also do memory statistics to find all the * [BEEP] leaks. diff --git a/net/core/stream.c b/net/core/stream.c index 35e25259fd9..e9489696f69 100644 --- a/net/core/stream.c +++ b/net/core/stream.c @@ -176,6 +176,7 @@ void sk_stream_rfree(struct sk_buff *skb) { struct sock *sk = skb->sk; + skb_truesize_check(skb); atomic_sub(skb->truesize, &sk->sk_rmem_alloc); sk->sk_forward_alloc += skb->truesize; } diff --git a/net/core/wireless.c b/net/core/wireless.c index 81d6995fcfd..d2bc72d318f 100644 --- a/net/core/wireless.c +++ b/net/core/wireless.c @@ -1726,6 +1726,14 @@ int wireless_rtnetlink_get(struct net_device * dev, if(!IW_IS_GET(request->cmd)) return -EOPNOTSUPP; + /* If command is `get the encoding parameters', check if + * the user has the right to do it */ + if (request->cmd == SIOCGIWENCODE || + request->cmd == SIOCGIWENCODEEXT) { + if (!capable(CAP_NET_ADMIN)) + return -EPERM; + } + /* Special cases */ if(request->cmd == SIOCGIWSTATS) /* Get Wireless Stats */ diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 1ff7328b0e1..2e0ee8355c4 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -848,6 +848,7 @@ static int dccp_close_state(struct sock *sk) void dccp_close(struct sock *sk, long timeout) { struct sk_buff *skb; + int state; lock_sock(sk); @@ -882,6 +883,11 @@ void dccp_close(struct sock *sk, long timeout) sk_stream_wait_close(sk, timeout); adjudge_to_death: + state = sk->sk_state; + sock_hold(sk); + sock_orphan(sk); + atomic_inc(sk->sk_prot->orphan_count); + /* * It is the last release_sock in its life. It will remove backlog. */ @@ -894,8 +900,9 @@ adjudge_to_death: bh_lock_sock(sk); BUG_TRAP(!sock_owned_by_user(sk)); - sock_hold(sk); - sock_orphan(sk); + /* Have we already been destroyed by a softirq or backlog? */ + if (state != DCCP_CLOSED && sk->sk_state == DCCP_CLOSED) + goto out; /* * The last release_sock may have processed the CLOSE or RESET @@ -915,12 +922,12 @@ adjudge_to_death: #endif } - atomic_inc(sk->sk_prot->orphan_count); if (sk->sk_state == DCCP_CLOSED) inet_csk_destroy_sock(sk); /* Otherwise, socket is reprieved until protocol close. */ +out: bh_unlock_sock(sk); local_bh_enable(); sock_put(sk); diff --git a/net/decnet/dn_neigh.c b/net/decnet/dn_neigh.c index 7c8692c26bf..66e230c3b32 100644 --- a/net/decnet/dn_neigh.c +++ b/net/decnet/dn_neigh.c @@ -493,7 +493,6 @@ struct elist_cb_state { static void neigh_elist_cb(struct neighbour *neigh, void *_info) { struct elist_cb_state *s = _info; - struct dn_dev *dn_db; struct dn_neigh *dn; if (neigh->dev != s->dev) @@ -503,10 +502,6 @@ static void neigh_elist_cb(struct neighbour *neigh, void *_info) if (!(dn->flags & (DN_NDFLAG_R1|DN_NDFLAG_R2))) return; - dn_db = (struct dn_dev *) s->dev->dn_ptr; - if (dn_db->parms.forwarding == 1 && (dn->flags & DN_NDFLAG_R2)) - return; - if (s->t == s->n) s->rs = dn_find_slot(s->ptr, s->n, dn->priority); else diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig index 6cd9f3427be..f2a27cc6ecb 100644 --- a/net/ieee80211/softmac/Kconfig +++ b/net/ieee80211/softmac/Kconfig @@ -1,6 +1,7 @@ config IEEE80211_SOFTMAC tristate "Software MAC add-on to the IEEE 802.11 networking stack" depends on IEEE80211 && EXPERIMENTAL + select WIRELESS_EXT ---help--- This option enables the hardware independent software MAC addon for the IEEE 802.11 networking stack. diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c index be61de78dfa..57ea9f6f465 100644 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ b/net/ieee80211/softmac/ieee80211softmac_assoc.c @@ -51,11 +51,12 @@ ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211soft spin_lock_irqsave(&mac->lock, flags); mac->associnfo.associating = 1; mac->associated = 0; /* just to make sure */ - spin_unlock_irqrestore(&mac->lock, flags); /* Set a timer for timeout */ /* FIXME: make timeout configurable */ - schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ); + if (likely(mac->running)) + schedule_delayed_work(&mac->associnfo.timeout, 5 * HZ); + spin_unlock_irqrestore(&mac->lock, flags); } void @@ -101,6 +102,7 @@ ieee80211softmac_disassoc(struct ieee80211softmac_device *mac, u16 reason) /* Do NOT clear bssvalid as that will break ieee80211softmac_assoc_work! */ mac->associated = 0; mac->associnfo.associating = 0; + ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL); spin_unlock_irqrestore(&mac->lock, flags); } @@ -143,6 +145,12 @@ network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_ne if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len)) return 0; + /* assume that users know what they're doing ... + * (note we don't let them select a net we're incompatible with) */ + if (mac->associnfo.bssfixed) { + return !memcmp(mac->associnfo.bssid, net->bssid, ETH_ALEN); + } + /* if 'ANY' network requested, take any that doesn't have privacy enabled */ if (mac->associnfo.req_essid.len == 0 && !(net->capability & WLAN_CAPABILITY_PRIVACY)) @@ -175,7 +183,7 @@ ieee80211softmac_assoc_work(void *d) ieee80211softmac_disassoc(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); /* try to find the requested network in our list, if we found one already */ - if (mac->associnfo.bssvalid) + if (mac->associnfo.bssvalid || mac->associnfo.bssfixed) found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); /* Search the ieee80211 networks for this network if we didn't find it by bssid, @@ -240,19 +248,25 @@ ieee80211softmac_assoc_work(void *d) if (ieee80211softmac_start_scan(mac)) dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); return; - } - else { + } else { spin_lock_irqsave(&mac->lock, flags); mac->associnfo.associating = 0; mac->associated = 0; spin_unlock_irqrestore(&mac->lock, flags); dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); + /* reset the retry counter for the next user request since we + * break out and don't reschedule ourselves after this point. */ + mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); return; } } - + + /* reset the retry counter for the next user request since we + * now found a net and will try to associate to it, but not + * schedule this function again. */ + mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; mac->associnfo.bssvalid = 1; memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN); /* copy the ESSID for displaying it */ @@ -306,6 +320,9 @@ ieee80211softmac_handle_assoc_response(struct net_device * dev, u16 status = le16_to_cpup(&resp->status); struct ieee80211softmac_network *network = NULL; unsigned long flags; + + if (unlikely(!mac->running)) + return -ENODEV; spin_lock_irqsave(&mac->lock, flags); @@ -364,15 +381,22 @@ ieee80211softmac_handle_disassoc(struct net_device * dev, { struct ieee80211softmac_device *mac = ieee80211_priv(dev); unsigned long flags; + + if (unlikely(!mac->running)) + return -ENODEV; + if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN)) return 0; + if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN)) return 0; + dprintk(KERN_INFO PFX "got disassoc frame\n"); netif_carrier_off(dev); spin_lock_irqsave(&mac->lock, flags); mac->associnfo.bssvalid = 0; mac->associated = 0; + ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL); schedule_work(&mac->associnfo.work); spin_unlock_irqrestore(&mac->lock, flags); @@ -386,11 +410,15 @@ ieee80211softmac_handle_reassoc_req(struct net_device * dev, struct ieee80211softmac_device *mac = ieee80211_priv(dev); struct ieee80211softmac_network *network; + if (unlikely(!mac->running)) + return -ENODEV; + network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3); if (!network) { dprintkl(KERN_INFO PFX "reassoc request from unknown network\n"); return 0; } - ieee80211softmac_assoc(mac, network); + schedule_work(&mac->associnfo.work); + return 0; } diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c index 9a0eac6c61e..06e33262466 100644 --- a/net/ieee80211/softmac/ieee80211softmac_auth.c +++ b/net/ieee80211/softmac/ieee80211softmac_auth.c @@ -86,6 +86,11 @@ ieee80211softmac_auth_queue(void *data) /* Lock and set flags */ spin_lock_irqsave(&mac->lock, flags); + if (unlikely(!mac->running)) { + /* Prevent reschedule on workqueue flush */ + spin_unlock_irqrestore(&mac->lock, flags); + return; + } net->authenticated = 0; net->authenticating = 1; /* add a timeout call so we eventually give up waiting for an auth reply */ @@ -124,6 +129,9 @@ ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) unsigned long flags; u8 * data; + if (unlikely(!mac->running)) + return -ENODEV; + /* Find correct auth queue item */ spin_lock_irqsave(&mac->lock, flags); list_for_each(list_ptr, &mac->auth_queue) { @@ -298,8 +306,6 @@ ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac, /* can't transmit data right now... */ netif_carrier_off(mac->dev); - /* let's try to re-associate */ - schedule_work(&mac->associnfo.work); spin_unlock_irqrestore(&mac->lock, flags); } @@ -338,6 +344,9 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de struct ieee80211softmac_network *net = NULL; struct ieee80211softmac_device *mac = ieee80211_priv(dev); + if (unlikely(!mac->running)) + return -ENODEV; + if (!deauth) { dprintk("deauth without deauth packet. eek!\n"); return 0; @@ -360,5 +369,8 @@ ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *de } ieee80211softmac_deauth_from_net(mac, net); + + /* let's try to re-associate */ + schedule_work(&mac->associnfo.work); return 0; } diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c index 0a52bbda1e4..8cc8f3f0f8e 100644 --- a/net/ieee80211/softmac/ieee80211softmac_event.c +++ b/net/ieee80211/softmac/ieee80211softmac_event.c @@ -67,6 +67,7 @@ static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = { "authenticating failed", "authenticating timed out", "associating failed because no suitable network was found", + "disassociated", }; @@ -128,13 +129,42 @@ void ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx) { struct ieee80211softmac_event *eventptr, *tmp; - union iwreq_data wrqu; - char *msg; + struct ieee80211softmac_network *network; if (event >= 0) { - msg = event_descriptions[event]; - wrqu.data.length = strlen(msg); - wireless_send_event(mac->dev, IWEVCUSTOM, &wrqu, msg); + union iwreq_data wrqu; + int we_event; + char *msg = NULL; + + switch(event) { + case IEEE80211SOFTMAC_EVENT_ASSOCIATED: + network = (struct ieee80211softmac_network *)event_ctx; + wrqu.data.length = 0; + wrqu.data.flags = 0; + memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + we_event = SIOCGIWAP; + break; + case IEEE80211SOFTMAC_EVENT_DISASSOCIATED: + wrqu.data.length = 0; + wrqu.data.flags = 0; + memset(&wrqu, '\0', sizeof (union iwreq_data)); + wrqu.ap_addr.sa_family = ARPHRD_ETHER; + we_event = SIOCGIWAP; + break; + case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED: + wrqu.data.length = 0; + wrqu.data.flags = 0; + memset(&wrqu, '\0', sizeof (union iwreq_data)); + we_event = SIOCGIWSCAN; + break; + default: + msg = event_descriptions[event]; + wrqu.data.length = strlen(msg); + we_event = IWEVCUSTOM; + break; + } + wireless_send_event(mac->dev, we_event, &wrqu, msg); } if (!list_empty(&mac->events)) diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c index febc51dbb41..cc6cd56c85b 100644 --- a/net/ieee80211/softmac/ieee80211softmac_io.c +++ b/net/ieee80211/softmac/ieee80211softmac_io.c @@ -180,9 +180,21 @@ ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt, ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid); /* Fill in capability Info */ - (*pkt)->capability = (mac->ieee->iw_mode == IW_MODE_MASTER) || (mac->ieee->iw_mode == IW_MODE_INFRA) ? - cpu_to_le16(WLAN_CAPABILITY_ESS) : - cpu_to_le16(WLAN_CAPABILITY_IBSS); + switch (mac->ieee->iw_mode) { + case IW_MODE_INFRA: + (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_ESS); + break; + case IW_MODE_ADHOC: + (*pkt)->capability = cpu_to_le16(WLAN_CAPABILITY_IBSS); + break; + case IW_MODE_AUTO: + (*pkt)->capability = net->capabilities & (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS); + break; + default: + /* bleh. we don't ever go to these modes */ + printk(KERN_ERR PFX "invalid iw_mode!\n"); + break; + } /* Need to add this (*pkt)->capability |= mac->ieee->short_slot ? cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME) : 0; diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c index 60f06a31f0d..6252be2c0db 100644 --- a/net/ieee80211/softmac/ieee80211softmac_module.c +++ b/net/ieee80211/softmac/ieee80211softmac_module.c @@ -45,6 +45,8 @@ struct net_device *alloc_ieee80211softmac(int sizeof_priv) softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc; softmac->scaninfo = NULL; + softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; + /* TODO: initialise all the other callbacks in the ieee struct * (once they're written) */ @@ -87,6 +89,8 @@ ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm) ieee80211softmac_wait_for_scan(sm); spin_lock_irqsave(&sm->lock, flags); + sm->running = 0; + /* Free all pending assoc work items */ cancel_delayed_work(&sm->associnfo.work); @@ -202,6 +206,8 @@ void ieee80211softmac_start(struct net_device *dev) assert(0); if (mac->txrates_change) mac->txrates_change(dev, change, &oldrates); + + mac->running = 1; } EXPORT_SYMBOL_GPL(ieee80211softmac_start); diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c index bb9ab8b45d0..d31cf77498c 100644 --- a/net/ieee80211/softmac/ieee80211softmac_scan.c +++ b/net/ieee80211/softmac/ieee80211softmac_scan.c @@ -47,6 +47,7 @@ ieee80211softmac_start_scan(struct ieee80211softmac_device *sm) sm->scanning = 1; spin_unlock_irqrestore(&sm->lock, flags); + netif_tx_disable(sm->ieee->dev); ret = sm->start_scan(sm->dev); if (ret) { spin_lock_irqsave(&sm->lock, flags); @@ -114,7 +115,15 @@ void ieee80211softmac_scan(void *d) // TODO: is this if correct, or should we do this only if scanning from assoc request? if (sm->associnfo.req_essid.len) ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0); + + spin_lock_irqsave(&sm->lock, flags); + if (unlikely(!sm->running)) { + /* Prevent reschedule on workqueue flush */ + spin_unlock_irqrestore(&sm->lock, flags); + break; + } schedule_delayed_work(&si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY); + spin_unlock_irqrestore(&sm->lock, flags); return; } else { dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel); @@ -239,6 +248,7 @@ void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm) if (net) sm->set_channel(sm->dev, net->channel); } + netif_wake_queue(sm->ieee->dev); ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL); } EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished); diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c index b559aa9b550..27edb2b5581 100644 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ b/net/ieee80211/softmac/ieee80211softmac_wx.c @@ -27,7 +27,8 @@ #include "ieee80211softmac_priv.h" #include <net/iw_handler.h> - +/* for is_broadcast_ether_addr and is_zero_ether_addr */ +#include <linux/etherdevice.h> int ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, @@ -41,13 +42,23 @@ ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan); +/* if we're still scanning, return -EAGAIN so that userspace tools + * can get the complete scan results, otherwise return 0. */ int ieee80211softmac_wx_get_scan_results(struct net_device *net_dev, struct iw_request_info *info, union iwreq_data *data, char *extra) { + unsigned long flags; struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); + + spin_lock_irqsave(&sm->lock, flags); + if (sm->scanning) { + spin_unlock_irqrestore(&sm->lock, flags); + return -EAGAIN; + } + spin_unlock_irqrestore(&sm->lock, flags); return ieee80211_wx_get_scan(sm->ieee, info, data, extra); } EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results); @@ -73,7 +84,6 @@ ieee80211softmac_wx_set_essid(struct net_device *net_dev, sm->associnfo.static_essid = 1; } } - sm->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; /* set our requested ESSID length. * If applicable, we have already copied the data in */ @@ -300,8 +310,6 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, char *extra) { struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); - static const unsigned char any[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - static const unsigned char off[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; unsigned long flags; /* sanity check */ @@ -310,10 +318,17 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, } spin_lock_irqsave(&mac->lock, flags); - if (!memcmp(any, data->ap_addr.sa_data, ETH_ALEN) || - !memcmp(off, data->ap_addr.sa_data, ETH_ALEN)) { - schedule_work(&mac->associnfo.work); - goto out; + if (is_broadcast_ether_addr(data->ap_addr.sa_data)) { + /* the bssid we have is not to be fixed any longer, + * and we should reassociate to the best AP. */ + mac->associnfo.bssfixed = 0; + /* force reassociation */ + mac->associnfo.bssvalid = 0; + if (mac->associated) + schedule_work(&mac->associnfo.work); + } else if (is_zero_ether_addr(data->ap_addr.sa_data)) { + /* the bssid we have is no longer fixed */ + mac->associnfo.bssfixed = 0; } else { if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { if (mac->associnfo.associating || mac->associated) { @@ -323,12 +338,14 @@ ieee80211softmac_wx_set_wap(struct net_device *net_dev, } else { /* copy new value in data->ap_addr.sa_data to bssid */ memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN); - } + } + /* tell the other code that this bssid should be used no matter what */ + mac->associnfo.bssfixed = 1; /* queue associate if new bssid or (old one again and not associated) */ schedule_work(&mac->associnfo.work); } -out: + out: spin_unlock_irqrestore(&mac->lock, flags); return 0; } diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index dc206f1f914..0a277453526 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c @@ -1257,7 +1257,7 @@ out_unregister_udp_proto: goto out; } -module_init(inet_init); +fs_initcall(inet_init); /* ------------------------------------------------------------------------ */ diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index 18d7fad474d..c9026dbf4c9 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c @@ -337,7 +337,7 @@ static inline int ip_rcv_finish(struct sk_buff *skb) * Initialise the virtual path cache for the packet. It describes * how the packet travels inside Linux networking. */ - if (likely(skb->dst == NULL)) { + if (skb->dst == NULL) { int err = ip_route_input(skb, iph->daddr, iph->saddr, iph->tos, skb->dev); if (unlikely(err)) { diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index c60fd5c4ea1..3d560dec63a 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig @@ -345,7 +345,7 @@ config IP_NF_TARGET_LOG To compile it as a module, choose M here. If unsure, say N. config IP_NF_TARGET_ULOG - tristate "ULOG target support (OBSOLETE)" + tristate "ULOG target support" depends on IP_NF_IPTABLES ---help--- diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323.c b/net/ipv4/netfilter/ip_conntrack_helper_h323.c index 2c2fb700d83..518f581d39e 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323.c @@ -162,6 +162,8 @@ static int get_tpkt_data(struct sk_buff **pskb, struct ip_conntrack *ct, /* Validate TPKT length */ tpktlen = tpkt[2] * 256 + tpkt[3]; + if (tpktlen < 4) + goto clear_out; if (tpktlen > tcpdatalen) { if (tcpdatalen == 4) { /* Separate TPKT header */ /* Netmeeting sends TPKT header and data separately */ diff --git a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c index 48078002e45..355a53a5b6c 100644 --- a/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c +++ b/net/ipv4/netfilter/ip_conntrack_helper_h323_asn1.c @@ -2,7 +2,7 @@ * ip_conntrack_helper_h323_asn1.c - BER and PER decoding library for H.323 * conntrack/NAT module. * - * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@hotmail.com> + * Copyright (c) 2006 by Jing Min Zhao <zhaojingmin@users.sourceforge.net> * * This source code is licensed under General Public License version 2. * @@ -703,6 +703,10 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level) type = get_bits(bs, f->sz); } + /* Write Type */ + if (base) + *(unsigned *) base = type; + /* Check Range */ if (type >= f->ub) { /* Newer version? */ BYTE_ALIGN(bs); @@ -712,10 +716,6 @@ int decode_choice(bitstr_t * bs, field_t * f, char *base, int level) return H323_ERROR_NONE; } - /* Write Type */ - if (base) - *(unsigned *) base = type; - /* Transfer to son level */ son = &f->fields[type]; if (son->attr & STOP) { diff --git a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c index 5259abd0fb4..0416073c560 100644 --- a/net/ipv4/netfilter/ip_conntrack_proto_sctp.c +++ b/net/ipv4/netfilter/ip_conntrack_proto_sctp.c @@ -235,12 +235,15 @@ static int do_basic_checks(struct ip_conntrack *conntrack, flag = 1; } - /* Cookie Ack/Echo chunks not the first OR - Init / Init Ack / Shutdown compl chunks not the only chunks */ - if ((sch->type == SCTP_CID_COOKIE_ACK + /* + * Cookie Ack/Echo chunks not the first OR + * Init / Init Ack / Shutdown compl chunks not the only chunks + * OR zero-length. + */ + if (((sch->type == SCTP_CID_COOKIE_ACK || sch->type == SCTP_CID_COOKIE_ECHO || flag) - && count !=0 ) { + && count !=0) || !sch->length) { DEBUGP("Basic checks failed\n"); return 1; } diff --git a/net/ipv4/netfilter/ip_nat_standalone.c b/net/ipv4/netfilter/ip_nat_standalone.c index 8f760b28617..67e676783da 100644 --- a/net/ipv4/netfilter/ip_nat_standalone.c +++ b/net/ipv4/netfilter/ip_nat_standalone.c @@ -219,8 +219,10 @@ ip_nat_out(unsigned int hooknum, const struct net_device *out, int (*okfn)(struct sk_buff *)) { +#ifdef CONFIG_XFRM struct ip_conntrack *ct; enum ip_conntrack_info ctinfo; +#endif unsigned int ret; /* root is playing with raw sockets. */ diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index d25ac8ba6eb..cee3397ec27 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -956,15 +956,16 @@ struct compat_ipt_standard_target compat_int_t verdict; }; -#define IPT_ST_OFFSET (sizeof(struct ipt_standard_target) - \ - sizeof(struct compat_ipt_standard_target)) - struct compat_ipt_standard { struct compat_ipt_entry entry; struct compat_ipt_standard_target target; }; +#define IPT_ST_LEN XT_ALIGN(sizeof(struct ipt_standard_target)) +#define IPT_ST_COMPAT_LEN COMPAT_XT_ALIGN(sizeof(struct compat_ipt_standard_target)) +#define IPT_ST_OFFSET (IPT_ST_LEN - IPT_ST_COMPAT_LEN) + static int compat_ipt_standard_fn(void *target, void **dstptr, int *size, int convert) { @@ -975,35 +976,29 @@ static int compat_ipt_standard_fn(void *target, ret = 0; switch (convert) { case COMPAT_TO_USER: - pst = (struct ipt_standard_target *)target; + pst = target; memcpy(&compat_st.target, &pst->target, - sizeof(struct ipt_entry_target)); + sizeof(compat_st.target)); compat_st.verdict = pst->verdict; if (compat_st.verdict > 0) compat_st.verdict -= compat_calc_jump(compat_st.verdict); - compat_st.target.u.user.target_size = - sizeof(struct compat_ipt_standard_target); - if (__copy_to_user(*dstptr, &compat_st, - sizeof(struct compat_ipt_standard_target))) + compat_st.target.u.user.target_size = IPT_ST_COMPAT_LEN; + if (copy_to_user(*dstptr, &compat_st, IPT_ST_COMPAT_LEN)) ret = -EFAULT; *size -= IPT_ST_OFFSET; - *dstptr += sizeof(struct compat_ipt_standard_target); + *dstptr += IPT_ST_COMPAT_LEN; break; case COMPAT_FROM_USER: - pcompat_st = - (struct compat_ipt_standard_target *)target; - memcpy(&st.target, &pcompat_st->target, - sizeof(struct ipt_entry_target)); + pcompat_st = target; + memcpy(&st.target, &pcompat_st->target, IPT_ST_COMPAT_LEN); st.verdict = pcompat_st->verdict; if (st.verdict > 0) st.verdict += compat_calc_jump(st.verdict); - st.target.u.user.target_size = - sizeof(struct ipt_standard_target); - memcpy(*dstptr, &st, - sizeof(struct ipt_standard_target)); + st.target.u.user.target_size = IPT_ST_LEN; + memcpy(*dstptr, &st, IPT_ST_LEN); *size += IPT_ST_OFFSET; - *dstptr += sizeof(struct ipt_standard_target); + *dstptr += IPT_ST_LEN; break; case COMPAT_CALC_SIZE: *size += IPT_ST_OFFSET; @@ -1446,7 +1441,7 @@ static int compat_copy_entry_to_user(struct ipt_entry *e, ret = -EFAULT; origsize = *size; ce = (struct compat_ipt_entry __user *)*dstptr; - if (__copy_to_user(ce, e, sizeof(struct ipt_entry))) + if (copy_to_user(ce, e, sizeof(struct ipt_entry))) goto out; *dstptr += sizeof(struct compat_ipt_entry); @@ -1464,9 +1459,9 @@ static int compat_copy_entry_to_user(struct ipt_entry *e, goto out; ret = -EFAULT; next_offset = e->next_offset - (origsize - *size); - if (__put_user(target_offset, &ce->target_offset)) + if (put_user(target_offset, &ce->target_offset)) goto out; - if (__put_user(next_offset, &ce->next_offset)) + if (put_user(next_offset, &ce->next_offset)) goto out; return 0; out: diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 87f68e787d0..e2b7b805503 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c @@ -1468,6 +1468,7 @@ void tcp_close(struct sock *sk, long timeout) { struct sk_buff *skb; int data_was_unread = 0; + int state; lock_sock(sk); sk->sk_shutdown = SHUTDOWN_MASK; @@ -1544,6 +1545,11 @@ void tcp_close(struct sock *sk, long timeout) sk_stream_wait_close(sk, timeout); adjudge_to_death: + state = sk->sk_state; + sock_hold(sk); + sock_orphan(sk); + atomic_inc(sk->sk_prot->orphan_count); + /* It is the last release_sock in its life. It will remove backlog. */ release_sock(sk); @@ -1555,8 +1561,9 @@ adjudge_to_death: bh_lock_sock(sk); BUG_TRAP(!sock_owned_by_user(sk)); - sock_hold(sk); - sock_orphan(sk); + /* Have we already been destroyed by a softirq or backlog? */ + if (state != TCP_CLOSE && sk->sk_state == TCP_CLOSE) + goto out; /* This is a (useful) BSD violating of the RFC. There is a * problem with TCP as specified in that the other end could @@ -1584,7 +1591,6 @@ adjudge_to_death: if (tmo > TCP_TIMEWAIT_LEN) { inet_csk_reset_keepalive_timer(sk, tcp_fin_time(sk)); } else { - atomic_inc(sk->sk_prot->orphan_count); tcp_time_wait(sk, TCP_FIN_WAIT2, tmo); goto out; } @@ -1603,7 +1609,6 @@ adjudge_to_death: NET_INC_STATS_BH(LINUX_MIB_TCPABORTONMEMORY); } } - atomic_inc(sk->sk_prot->orphan_count); if (sk->sk_state == TCP_CLOSE) inet_csk_destroy_sock(sk); diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c index e0e9d1383c7..b72fa55dfb8 100644 --- a/net/ipv4/tcp_highspeed.c +++ b/net/ipv4/tcp_highspeed.c @@ -137,8 +137,8 @@ static void hstcp_cong_avoid(struct sock *sk, u32 adk, u32 rtt, if (tp->snd_cwnd < tp->snd_cwnd_clamp) { tp->snd_cwnd_cnt += ca->ai; if (tp->snd_cwnd_cnt >= tp->snd_cwnd) { - tp->snd_cwnd++; tp->snd_cwnd_cnt -= tp->snd_cwnd; + tp->snd_cwnd++; } } } diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 44df1db726a..743016baa04 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -465,7 +465,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, TCP_INC_STATS(TCP_MIB_OUTSEGS); err = icsk->icsk_af_ops->queue_xmit(skb, 0); - if (unlikely(err <= 0)) + if (likely(err <= 0)) return err; tcp_enter_cwr(sk); @@ -533,6 +533,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss struct tcp_sock *tp = tcp_sk(sk); struct sk_buff *buff; int nsize, old_factor; + int nlen; u16 flags; BUG_ON(len > skb->len); @@ -552,8 +553,10 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss if (buff == NULL) return -ENOMEM; /* We'll just try again later. */ - buff->truesize = skb->len - len; - skb->truesize -= buff->truesize; + sk_charge_skb(sk, buff); + nlen = skb->len - len - nsize; + buff->truesize += nlen; + skb->truesize -= nlen; /* Correct the sequence numbers. */ TCP_SKB_CB(buff)->seq = TCP_SKB_CB(skb)->seq + len; @@ -1039,7 +1042,8 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len, if (unlikely(buff == NULL)) return -ENOMEM; - buff->truesize = nlen; + sk_charge_skb(sk, buff); + buff->truesize += nlen; skb->truesize -= nlen; /* Correct the sequence numbers. */ diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 32ad229b4fe..4ef8efaf6a6 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c @@ -62,7 +62,7 @@ static void xfrm4_encap(struct sk_buff *skb) top_iph->frag_off = (flags & XFRM_STATE_NOPMTUDISC) ? 0 : (iph->frag_off & htons(IP_DF)); if (!top_iph->frag_off) - __ip_select_ident(top_iph, dst, 0); + __ip_select_ident(top_iph, dst->child, 0); top_iph->ttl = dst_metric(dst->child, RTAX_HOPLIMIT); diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 642b4b11464..0a673038344 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -288,19 +288,6 @@ ip6t_do_table(struct sk_buff **pskb, table_base = (void *)private->entries[smp_processor_id()]; e = get_entry(table_base, private->hook_entry[hook]); -#ifdef CONFIG_NETFILTER_DEBUG - /* Check noone else using our table */ - if (((struct ip6t_entry *)table_base)->comefrom != 0xdead57ac - && ((struct ip6t_entry *)table_base)->comefrom != 0xeeeeeeec) { - printk("ASSERT: CPU #%u, %s comefrom(%p) = %X\n", - smp_processor_id(), - table->name, - &((struct ip6t_entry *)table_base)->comefrom, - ((struct ip6t_entry *)table_base)->comefrom); - } - ((struct ip6t_entry *)table_base)->comefrom = 0x57acc001; -#endif - /* For return from builtin chain */ back = get_entry(table_base, private->underflow[hook]); diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 79078747a64..0190e39096b 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -317,7 +317,7 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif, __FUNCTION__, head, head ? *head : NULL, oif); for (rt = rt0, metric = rt0->rt6i_metric; - rt && rt->rt6i_metric == metric; + rt && rt->rt6i_metric == metric && (!last || rt != rt0); rt = rt->u.next) { int m; @@ -343,9 +343,12 @@ static struct rt6_info *rt6_select(struct rt6_info **head, int oif, (strict & RT6_SELECT_F_REACHABLE) && last && last != rt0) { /* no entries matched; do round-robin */ + static spinlock_t lock = SPIN_LOCK_UNLOCKED; + spin_lock(&lock); *head = rt0->u.next; rt0->u.next = last->u.next; last->u.next = rt0; + spin_unlock(&lock); } RT6_TRACE("%s() => %p, score=%d\n", diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index 8f3addf0724..d62e0f9b9da 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c @@ -118,7 +118,8 @@ static inline int llc_fixup_skb(struct sk_buff *skb) u16 pdulen = eth_hdr(skb)->h_proto, data_size = ntohs(pdulen) - llc_len; - skb_trim(skb, data_size); + if (unlikely(pskb_trim_rcsum(skb, data_size))) + return 0; } return 1; } diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index e581190fb6c..f9b83f91371 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c @@ -178,9 +178,6 @@ static struct { /* allocated slab cache + modules which uses this slab cache */ int use; - /* Initialization */ - int (*init_conntrack)(struct nf_conn *, u_int32_t); - } nf_ct_cache[NF_CT_F_NUM]; /* protect members of nf_ct_cache except of "use" */ @@ -208,10 +205,8 @@ nf_ct_proto_find_get(u_int16_t l3proto, u_int8_t protocol) preempt_disable(); p = __nf_ct_proto_find(l3proto, protocol); - if (p) { - if (!try_module_get(p->me)) - p = &nf_conntrack_generic_protocol; - } + if (!try_module_get(p->me)) + p = &nf_conntrack_generic_protocol; preempt_enable(); return p; @@ -229,10 +224,8 @@ nf_ct_l3proto_find_get(u_int16_t l3proto) preempt_disable(); p = __nf_ct_l3proto_find(l3proto); - if (p) { - if (!try_module_get(p->me)) - p = &nf_conntrack_generic_l3proto; - } + if (!try_module_get(p->me)) + p = &nf_conntrack_generic_l3proto; preempt_enable(); return p; diff --git a/net/netfilter/nf_conntrack_l3proto_generic.c b/net/netfilter/nf_conntrack_l3proto_generic.c index 7de4f06c63c..3fc58e454d4 100644 --- a/net/netfilter/nf_conntrack_l3proto_generic.c +++ b/net/netfilter/nf_conntrack_l3proto_generic.c @@ -94,5 +94,4 @@ struct nf_conntrack_l3proto nf_conntrack_generic_l3proto = { .print_conntrack = generic_print_conntrack, .prepare = generic_prepare, .get_features = generic_get_features, - .me = THIS_MODULE, }; diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 9cccc325b68..0c6da496cfa 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c @@ -240,12 +240,15 @@ static int do_basic_checks(struct nf_conn *conntrack, flag = 1; } - /* Cookie Ack/Echo chunks not the first OR - Init / Init Ack / Shutdown compl chunks not the only chunks */ - if ((sch->type == SCTP_CID_COOKIE_ACK + /* + * Cookie Ack/Echo chunks not the first OR + * Init / Init Ack / Shutdown compl chunks not the only chunks + * OR zero-length. + */ + if (((sch->type == SCTP_CID_COOKIE_ACK || sch->type == SCTP_CID_COOKIE_ECHO || flag) - && count !=0 ) { + && count !=0) || !sch->length) { DEBUGP("Basic checks failed\n"); return 1; } diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 00cf0a4f4d9..99293c63ff7 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -289,7 +289,7 @@ int xt_compat_match(void *match, void **dstptr, int *size, int convert) case COMPAT_TO_USER: pm = (struct xt_entry_match *)match; msize = pm->u.user.match_size; - if (__copy_to_user(*dstptr, pm, msize)) { + if (copy_to_user(*dstptr, pm, msize)) { ret = -EFAULT; break; } @@ -366,7 +366,7 @@ int xt_compat_target(void *target, void **dstptr, int *size, int convert) case COMPAT_TO_USER: pt = (struct xt_entry_target *)target; tsize = pt->u.user.target_size; - if (__copy_to_user(*dstptr, pt, tsize)) { + if (copy_to_user(*dstptr, pt, tsize)) { ret = -EFAULT; break; } @@ -529,6 +529,7 @@ int xt_register_table(struct xt_table *table, /* Simplifies replace_table code. */ table->private = bootstrap; + rwlock_init(&table->lock); if (!xt_replace_table(table, 0, newinfo, &ret)) goto unlock; @@ -538,7 +539,6 @@ int xt_register_table(struct xt_table *table, /* save number of initial entries */ private->initial_entries = private->number; - rwlock_init(&table->lock); list_prepend(&xt[table->af].tables, table); ret = 0; diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 2a233ffcf61..3862e73d14d 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -56,12 +56,12 @@ #include <linux/mm.h> #include <linux/types.h> #include <linux/audit.h> +#include <linux/selinux.h> #include <net/sock.h> #include <net/scm.h> #include <net/netlink.h> -#define Nprintk(a...) #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) struct netlink_sock { @@ -1157,6 +1157,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, NETLINK_CB(skb).dst_pid = dst_pid; NETLINK_CB(skb).dst_group = dst_group; NETLINK_CB(skb).loginuid = audit_get_loginuid(current->audit_context); + selinux_get_task_sid(current, &(NETLINK_CB(skb).sid)); memcpy(NETLINK_CREDS(skb), &siocb->scm->creds, sizeof(struct ucred)); /* What can I do? Netlink is asynchronous, so that diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index d44981f5a61..3669cb953e6 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -425,11 +425,16 @@ static int nr_create(struct socket *sock, int protocol) nr_init_timers(sk); - nr->t1 = sysctl_netrom_transport_timeout; - nr->t2 = sysctl_netrom_transport_acknowledge_delay; - nr->n2 = sysctl_netrom_transport_maximum_tries; - nr->t4 = sysctl_netrom_transport_busy_delay; - nr->idle = sysctl_netrom_transport_no_activity_timeout; + nr->t1 = + msecs_to_jiffies(sysctl_netrom_transport_timeout); + nr->t2 = + msecs_to_jiffies(sysctl_netrom_transport_acknowledge_delay); + nr->n2 = + msecs_to_jiffies(sysctl_netrom_transport_maximum_tries); + nr->t4 = + msecs_to_jiffies(sysctl_netrom_transport_busy_delay); + nr->idle = + msecs_to_jiffies(sysctl_netrom_transport_no_activity_timeout); nr->window = sysctl_netrom_transport_requested_window_size; nr->bpqext = 1; @@ -1365,8 +1370,6 @@ static struct notifier_block nr_dev_notifier = { static struct net_device **dev_nr; -static char banner[] __initdata = KERN_INFO "G4KLX NET/ROM for Linux. Version 0.7 for AX25.037 Linux 2.4\n"; - static int __init nr_proto_init(void) { int i; @@ -1414,7 +1417,6 @@ static int __init nr_proto_init(void) } register_netdevice_notifier(&nr_dev_notifier); - printk(banner); ax25_protocol_register(AX25_P_NETROM, nr_route_frame); ax25_linkfail_register(nr_link_failed); diff --git a/net/netrom/nr_dev.c b/net/netrom/nr_dev.c index 509afddae56..621e5586ab0 100644 --- a/net/netrom/nr_dev.c +++ b/net/netrom/nr_dev.c @@ -185,7 +185,6 @@ static struct net_device_stats *nr_get_stats(struct net_device *dev) void nr_setup(struct net_device *dev) { - SET_MODULE_OWNER(dev); dev->mtu = NR_MAX_PACKET_SIZE; dev->hard_start_xmit = nr_xmit; dev->open = nr_open; diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index ea65396d161..55564efccf1 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -518,11 +518,11 @@ static int rose_create(struct socket *sock, int protocol) init_timer(&rose->timer); init_timer(&rose->idletimer); - rose->t1 = sysctl_rose_call_request_timeout; - rose->t2 = sysctl_rose_reset_request_timeout; - rose->t3 = sysctl_rose_clear_request_timeout; - rose->hb = sysctl_rose_ack_hold_back_timeout; - rose->idle = sysctl_rose_no_activity_timeout; + rose->t1 = msecs_to_jiffies(sysctl_rose_call_request_timeout); + rose->t2 = msecs_to_jiffies(sysctl_rose_reset_request_timeout); + rose->t3 = msecs_to_jiffies(sysctl_rose_clear_request_timeout); + rose->hb = msecs_to_jiffies(sysctl_rose_ack_hold_back_timeout); + rose->idle = msecs_to_jiffies(sysctl_rose_no_activity_timeout); rose->state = ROSE_STATE_0; @@ -1469,8 +1469,6 @@ static struct notifier_block rose_dev_notifier = { static struct net_device **dev_rose; -static const char banner[] = KERN_INFO "F6FBB/G4KLX ROSE for Linux. Version 0.62 for AX25.037 Linux 2.4\n"; - static int __init rose_proto_init(void) { int i; @@ -1519,7 +1517,6 @@ static int __init rose_proto_init(void) sock_register(&rose_family_ops); register_netdevice_notifier(&rose_dev_notifier); - printk(banner); ax25_protocol_register(AX25_P_ROSE, rose_route_frame); ax25_linkfail_register(rose_link_failed); diff --git a/net/rose/rose_dev.c b/net/rose/rose_dev.c index d297af737d1..2a1bf8e119e 100644 --- a/net/rose/rose_dev.c +++ b/net/rose/rose_dev.c @@ -135,7 +135,6 @@ static struct net_device_stats *rose_get_stats(struct net_device *dev) void rose_setup(struct net_device *dev) { - SET_MODULE_OWNER(dev); dev->mtu = ROSE_MAX_PACKET_SIZE - 2; dev->hard_start_xmit = rose_xmit; dev->open = rose_open; diff --git a/net/rose/rose_link.c b/net/rose/rose_link.c index 09e9e9d04d9..bd86a63960c 100644 --- a/net/rose/rose_link.c +++ b/net/rose/rose_link.c @@ -40,7 +40,8 @@ void rose_start_ftimer(struct rose_neigh *neigh) neigh->ftimer.data = (unsigned long)neigh; neigh->ftimer.function = &rose_ftimer_expiry; - neigh->ftimer.expires = jiffies + sysctl_rose_link_fail_timeout; + neigh->ftimer.expires = + jiffies + msecs_to_jiffies(sysctl_rose_link_fail_timeout); add_timer(&neigh->ftimer); } @@ -51,7 +52,8 @@ static void rose_start_t0timer(struct rose_neigh *neigh) neigh->t0timer.data = (unsigned long)neigh; neigh->t0timer.function = &rose_t0timer_expiry; - neigh->t0timer.expires = jiffies + sysctl_rose_restart_request_timeout; + neigh->t0timer.expires = + jiffies + msecs_to_jiffies(sysctl_rose_restart_request_timeout); add_timer(&neigh->t0timer); } diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 8631b65a731..a22542fa1bc 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c @@ -48,8 +48,6 @@ static DEFINE_SPINLOCK(rose_route_list_lock); struct rose_neigh *rose_loopback_neigh; -static void rose_remove_neigh(struct rose_neigh *); - /* * Add a new route to a node, and in the process add the node and the * neighbour if it is new. @@ -235,11 +233,8 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) skb_queue_purge(&rose_neigh->queue); - spin_lock_bh(&rose_neigh_list_lock); - if ((s = rose_neigh_list) == rose_neigh) { rose_neigh_list = rose_neigh->next; - spin_unlock_bh(&rose_neigh_list_lock); kfree(rose_neigh->digipeat); kfree(rose_neigh); return; @@ -248,7 +243,6 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) while (s != NULL && s->next != NULL) { if (s->next == rose_neigh) { s->next = rose_neigh->next; - spin_unlock_bh(&rose_neigh_list_lock); kfree(rose_neigh->digipeat); kfree(rose_neigh); return; @@ -256,7 +250,6 @@ static void rose_remove_neigh(struct rose_neigh *rose_neigh) s = s->next; } - spin_unlock_bh(&rose_neigh_list_lock); } /* diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 6056d20ef42..37640c6fc01 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c @@ -69,6 +69,11 @@ ipt_init_target(struct ipt_entry_target *t, char *table, unsigned int hook) DPRINTK("ipt_init_target: found %s\n", target->name); t->u.kernel.target = target; + ret = xt_check_target(target, AF_INET, t->u.target_size - sizeof(*t), + table, hook, 0, 0); + if (ret) + return ret; + if (t->u.kernel.target->checkentry && !t->u.kernel.target->checkentry(table, NULL, t->u.kernel.target, t->data, diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index 7228d30512c..5a4a4d0ae50 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c @@ -167,7 +167,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch) if (count == 0) { sch->qstats.drops++; kfree_skb(skb); - return NET_XMIT_DROP; + return NET_XMIT_BYPASS; } /* diff --git a/net/sctp/inqueue.c b/net/sctp/inqueue.c index 297b8951463..cf0c767d43a 100644 --- a/net/sctp/inqueue.c +++ b/net/sctp/inqueue.c @@ -149,6 +149,7 @@ struct sctp_chunk *sctp_inq_pop(struct sctp_inq *queue) /* This is the first chunk in the packet. */ chunk->singleton = 1; ch = (sctp_chunkhdr_t *) chunk->skb->data; + chunk->data_accepted = 0; } chunk->chunk_hdr = ch; diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 2b9a832b29a..8cdba51ec07 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -636,8 +636,9 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, */ chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data; - skb_pull(chunk->skb, - ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t)); + if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - + sizeof(sctp_chunkhdr_t))) + goto nomem; /* 5.1 D) Upon reception of the COOKIE ECHO chunk, Endpoint * "Z" will reply with a COOKIE ACK chunk after building a TCB @@ -965,7 +966,8 @@ sctp_disposition_t sctp_sf_beat_8_3(const struct sctp_endpoint *ep, */ chunk->subh.hb_hdr = (sctp_heartbeathdr_t *) chunk->skb->data; paylen = ntohs(chunk->chunk_hdr->length) - sizeof(sctp_chunkhdr_t); - skb_pull(chunk->skb, paylen); + if (!pskb_pull(chunk->skb, paylen)) + goto nomem; reply = sctp_make_heartbeat_ack(asoc, chunk, chunk->subh.hb_hdr, paylen); @@ -1860,8 +1862,9 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep, * are in good shape. */ chunk->subh.cookie_hdr = (struct sctp_signed_cookie *)chunk->skb->data; - skb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - - sizeof(sctp_chunkhdr_t)); + if (!pskb_pull(chunk->skb, ntohs(chunk->chunk_hdr->length) - + sizeof(sctp_chunkhdr_t))) + goto nomem; /* In RFC 2960 5.2.4 3, if both Verification Tags in the State Cookie * of a duplicate COOKIE ECHO match the Verification Tags of the @@ -5151,7 +5154,9 @@ static int sctp_eat_data(const struct sctp_association *asoc, int tmp; __u32 tsn; int account_value; + struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; struct sock *sk = asoc->base.sk; + int rcvbuf_over = 0; data_hdr = chunk->subh.data_hdr = (sctp_datahdr_t *)chunk->skb->data; skb_pull(chunk->skb, sizeof(sctp_datahdr_t)); @@ -5162,10 +5167,16 @@ static int sctp_eat_data(const struct sctp_association *asoc, /* ASSERT: Now skb->data is really the user data. */ /* - * if we are established, and we have used up our receive - * buffer memory, drop the frame - */ - if (asoc->state == SCTP_STATE_ESTABLISHED) { + * If we are established, and we have used up our receive buffer + * memory, think about droping the frame. + * Note that we have an opportunity to improve performance here. + * If we accept one chunk from an skbuff, we have to keep all the + * memory of that skbuff around until the chunk is read into user + * space. Therefore, once we accept 1 chunk we may as well accept all + * remaining chunks in the skbuff. The data_accepted flag helps us do + * that. + */ + if ((asoc->state == SCTP_STATE_ESTABLISHED) && (!chunk->data_accepted)) { /* * If the receive buffer policy is 1, then each * association can allocate up to sk_rcvbuf bytes @@ -5176,9 +5187,25 @@ static int sctp_eat_data(const struct sctp_association *asoc, account_value = atomic_read(&asoc->rmem_alloc); else account_value = atomic_read(&sk->sk_rmem_alloc); - - if (account_value > sk->sk_rcvbuf) - return SCTP_IERROR_IGNORE_TSN; + if (account_value > sk->sk_rcvbuf) { + /* + * We need to make forward progress, even when we are + * under memory pressure, so we always allow the + * next tsn after the ctsn ack point to be accepted. + * This lets us avoid deadlocks in which we have to + * drop frames that would otherwise let us drain the + * receive queue. + */ + if ((sctp_tsnmap_get_ctsn(map) + 1) != tsn) + return SCTP_IERROR_IGNORE_TSN; + + /* + * We're going to accept the frame but we should renege + * to make space for it. This will send us down that + * path later in this function. + */ + rcvbuf_over = 1; + } } /* Process ECN based congestion. @@ -5226,6 +5253,7 @@ static int sctp_eat_data(const struct sctp_association *asoc, datalen -= sizeof(sctp_data_chunk_t); deliver = SCTP_CMD_CHUNK_ULP; + chunk->data_accepted = 1; /* Think about partial delivery. */ if ((datalen >= asoc->rwnd) && (!asoc->ulpq.pd_mode)) { @@ -5242,7 +5270,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, * large spill over. */ if (!asoc->rwnd || asoc->rwnd_over || - (datalen > asoc->rwnd + asoc->frag_point)) { + (datalen > asoc->rwnd + asoc->frag_point) || + rcvbuf_over) { /* If this is the next TSN, consider reneging to make * room. Note: Playing nice with a confused sender. A @@ -5250,8 +5279,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, * space and in the future we may want to detect and * do more drastic reneging. */ - if (sctp_tsnmap_has_gap(&asoc->peer.tsn_map) && - (sctp_tsnmap_get_ctsn(&asoc->peer.tsn_map) + 1) == tsn) { + if (sctp_tsnmap_has_gap(map) && + (sctp_tsnmap_get_ctsn(map) + 1) == tsn) { SCTP_DEBUG_PRINTK("Reneging for tsn:%u\n", tsn); deliver = SCTP_CMD_RENEGE; } else { diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 75ef1040876..8bcca567615 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c @@ -366,9 +366,9 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, /* SCTP_STATE_EMPTY */ \ {.fn = sctp_sf_ootb, .name = "sctp_sf_ootb"}, \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ /* SCTP_STATE_COOKIE_WAIT */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ /* SCTP_STATE_COOKIE_ECHOED */ \ {.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \ /* SCTP_STATE_ESTABLISHED */ \ @@ -380,7 +380,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ {.fn = sctp_sf_do_ecne, .name = "sctp_sf_do_ecne"}, \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ } /* TYPE_SCTP_ECN_ECNE */ #define TYPE_SCTP_ECN_CWR { \ @@ -401,7 +401,7 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, /* SCTP_STATE_SHUTDOWN_RECEIVED */ \ {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ /* SCTP_STATE_SHUTDOWN_ACK_SENT */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + {.fn = sctp_sf_discard_chunk, .name = "sctp_sf_discard_chunk"}, \ } /* TYPE_SCTP_ECN_CWR */ #define TYPE_SCTP_SHUTDOWN_COMPLETE { \ @@ -647,7 +647,7 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { /* SCTP_STATE_EMPTY */ \ {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ /* SCTP_STATE_CLOSED */ \ - {.fn = sctp_sf_bug, .name = "sctp_sf_bug"}, \ + {.fn = sctp_sf_error_closed, .name = "sctp_sf_error_closed"}, \ /* SCTP_STATE_COOKIE_WAIT */ \ {.fn = sctp_sf_do_prm_requestheartbeat, \ .name = "sctp_sf_do_prm_requestheartbeat"}, \ diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 2080b2d28c9..575e556aeb3 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c @@ -279,6 +279,7 @@ static inline void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq, static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *queue, struct sk_buff *f_frag, struct sk_buff *l_frag) { struct sk_buff *pos; + struct sk_buff *new = NULL; struct sctp_ulpevent *event; struct sk_buff *pnext, *last; struct sk_buff *list = skb_shinfo(f_frag)->frag_list; @@ -297,11 +298,33 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *qu */ if (last) last->next = pos; - else - skb_shinfo(f_frag)->frag_list = pos; + else { + if (skb_cloned(f_frag)) { + /* This is a cloned skb, we can't just modify + * the frag_list. We need a new skb to do that. + * Instead of calling skb_unshare(), we'll do it + * ourselves since we need to delay the free. + */ + new = skb_copy(f_frag, GFP_ATOMIC); + if (!new) + return NULL; /* try again later */ + + new->sk = f_frag->sk; + + skb_shinfo(new)->frag_list = pos; + } else + skb_shinfo(f_frag)->frag_list = pos; + } /* Remove the first fragment from the reassembly queue. */ __skb_unlink(f_frag, queue); + + /* if we did unshare, then free the old skb and re-assign */ + if (new) { + kfree_skb(f_frag); + f_frag = new; + } + while (pos) { pnext = pos->next; diff --git a/net/socket.c b/net/socket.c index 23898f45f71..02948b622bd 100644 --- a/net/socket.c +++ b/net/socket.c @@ -267,6 +267,8 @@ int move_addr_to_user(void *kaddr, int klen, void __user *uaddr, int __user *ule return -EINVAL; if(len) { + if (audit_sockaddr(klen, kaddr)) + return -ENOMEM; if(copy_to_user(uaddr,kaddr,len)) return -EFAULT; } @@ -490,6 +492,7 @@ static struct socket *sockfd_lookup_light(int fd, int *err, int *fput_needed) struct file *file; struct socket *sock; + *err = -EBADF; file = fget_light(fd, fput_needed); if (file) { sock = sock_from_file(file, err); diff --git a/net/x25/x25_timer.c b/net/x25/x25_timer.c index 0a92e1da392..71ff3088f6f 100644 --- a/net/x25/x25_timer.c +++ b/net/x25/x25_timer.c @@ -114,8 +114,9 @@ static void x25_heartbeat_expiry(unsigned long param) if (sock_flag(sk, SOCK_DESTROY) || (sk->sk_state == TCP_LISTEN && sock_flag(sk, SOCK_DEAD))) { + bh_unlock_sock(sk); x25_destroy_socket(sk); - goto unlock; + return; } break; @@ -128,7 +129,6 @@ static void x25_heartbeat_expiry(unsigned long param) } restart_heartbeat: x25_start_heartbeat(sk); -unlock: bh_unlock_sock(sk); } diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index c3725fe2a8f..b469c8b5461 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -57,12 +57,12 @@ int xfrm_register_type(struct xfrm_type *type, unsigned short family) return -EAFNOSUPPORT; typemap = afinfo->type_map; - write_lock(&typemap->lock); + write_lock_bh(&typemap->lock); if (likely(typemap->map[type->proto] == NULL)) typemap->map[type->proto] = type; else err = -EEXIST; - write_unlock(&typemap->lock); + write_unlock_bh(&typemap->lock); xfrm_policy_put_afinfo(afinfo); return err; } @@ -78,12 +78,12 @@ int xfrm_unregister_type(struct xfrm_type *type, unsigned short family) return -EAFNOSUPPORT; typemap = afinfo->type_map; - write_lock(&typemap->lock); + write_lock_bh(&typemap->lock); if (unlikely(typemap->map[type->proto] != type)) err = -ENOENT; else typemap->map[type->proto] = NULL; - write_unlock(&typemap->lock); + write_unlock_bh(&typemap->lock); xfrm_policy_put_afinfo(afinfo); return err; } @@ -1251,7 +1251,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) return -EINVAL; if (unlikely(afinfo->family >= NPROTO)) return -EAFNOSUPPORT; - write_lock(&xfrm_policy_afinfo_lock); + write_lock_bh(&xfrm_policy_afinfo_lock); if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL)) err = -ENOBUFS; else { @@ -1268,7 +1268,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) afinfo->garbage_collect = __xfrm_garbage_collect; xfrm_policy_afinfo[afinfo->family] = afinfo; } - write_unlock(&xfrm_policy_afinfo_lock); + write_unlock_bh(&xfrm_policy_afinfo_lock); return err; } EXPORT_SYMBOL(xfrm_policy_register_afinfo); @@ -1280,7 +1280,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) return -EINVAL; if (unlikely(afinfo->family >= NPROTO)) return -EAFNOSUPPORT; - write_lock(&xfrm_policy_afinfo_lock); + write_lock_bh(&xfrm_policy_afinfo_lock); if (likely(xfrm_policy_afinfo[afinfo->family] != NULL)) { if (unlikely(xfrm_policy_afinfo[afinfo->family] != afinfo)) err = -EINVAL; @@ -1294,7 +1294,7 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) afinfo->garbage_collect = NULL; } } - write_unlock(&xfrm_policy_afinfo_lock); + write_unlock_bh(&xfrm_policy_afinfo_lock); return err; } EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 3dc3e1f3b7a..93a2f36ad3d 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -1061,7 +1061,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo) return -EINVAL; if (unlikely(afinfo->family >= NPROTO)) return -EAFNOSUPPORT; - write_lock(&xfrm_state_afinfo_lock); + write_lock_bh(&xfrm_state_afinfo_lock); if (unlikely(xfrm_state_afinfo[afinfo->family] != NULL)) err = -ENOBUFS; else { @@ -1069,7 +1069,7 @@ int xfrm_state_register_afinfo(struct xfrm_state_afinfo *afinfo) afinfo->state_byspi = xfrm_state_byspi; xfrm_state_afinfo[afinfo->family] = afinfo; } - write_unlock(&xfrm_state_afinfo_lock); + write_unlock_bh(&xfrm_state_afinfo_lock); return err; } EXPORT_SYMBOL(xfrm_state_register_afinfo); @@ -1081,7 +1081,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) return -EINVAL; if (unlikely(afinfo->family >= NPROTO)) return -EAFNOSUPPORT; - write_lock(&xfrm_state_afinfo_lock); + write_lock_bh(&xfrm_state_afinfo_lock); if (likely(xfrm_state_afinfo[afinfo->family] != NULL)) { if (unlikely(xfrm_state_afinfo[afinfo->family] != afinfo)) err = -EINVAL; @@ -1091,7 +1091,7 @@ int xfrm_state_unregister_afinfo(struct xfrm_state_afinfo *afinfo) afinfo->state_bydst = NULL; } } - write_unlock(&xfrm_state_afinfo_lock); + write_unlock_bh(&xfrm_state_afinfo_lock); return err; } EXPORT_SYMBOL(xfrm_state_unregister_afinfo); |
