From 476181cb05c6a3aea3ef42309388e255c934a06f Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 4 Aug 2009 21:44:39 +0000 Subject: dccp: missing destroy of percpu counter variable while unload module percpu counter dccp_orphan_count is init in dccp_init() by percpu_counter_init() while dccp module is loaded, but the destroy of it is missing while dccp module is unloaded. We can get the kernel WARNING about this. Reproduct by the following commands: $ modprobe dccp $ rmmod dccp $ modprobe dccp WARNING: at lib/list_debug.c:26 __list_add+0x27/0x5c() Hardware name: VMware Virtual Platform list_add corruption. next->prev should be prev (c080c0c4), but was (null). (next =ca7188cc). Modules linked in: dccp(+) nfsd lockd nfs_acl auth_rpcgss exportfs sunrpc Pid: 1956, comm: modprobe Not tainted 2.6.31-rc5 #55 Call Trace: [] warn_slowpath_common+0x6a/0x81 [] ? __list_add+0x27/0x5c [] warn_slowpath_fmt+0x29/0x2c [] __list_add+0x27/0x5c [] __percpu_counter_init+0x4d/0x5d [] dccp_init+0x19/0x2ed [dccp] [] do_one_initcall+0x4f/0x111 [] ? dccp_init+0x0/0x2ed [dccp] [] ? notifier_call_chain+0x26/0x48 [] ? __blocking_notifier_call_chain+0x45/0x51 [] sys_init_module+0xac/0x1bd [] sysenter_do_call+0x12/0x22 Signed-off-by: Wei Yongjun Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/dccp/proto.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 94ca8eaace7d..6294f57162bb 100644 --- a/net/dccp/proto.c +++ b/net/dccp/proto.c @@ -1159,6 +1159,7 @@ static void __exit dccp_fini(void) kmem_cache_destroy(dccp_hashinfo.bind_bucket_cachep); dccp_ackvec_exit(); dccp_sysctl_exit(); + percpu_counter_destroy(&dccp_orphan_count); } module_init(dccp_init); -- cgit v1.2.3 From cf39c4c572dc54adbdf8933d1e6cd87ee94d8fc0 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Mon, 27 Jul 2009 08:03:18 -0700 Subject: phonet: phonet_device_get() fix net/phonet/pn_dev.c: In function `phonet_device_get': net/phonet/pn_dev.c:99: warning: 'dev' might be used uninitialized in this function Signed-off-by: Eric Dumazet Acked-by: Rémi Denis-Courmont Signed-off-by: David S. Miller --- net/phonet/pn_dev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index b0d6ddd82a9d..c2b77a698695 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c @@ -96,7 +96,7 @@ struct net_device *phonet_device_get(struct net *net) { struct phonet_device_list *pndevs = phonet_device_list(net); struct phonet_device *pnd; - struct net_device *dev; + struct net_device *dev = NULL; spin_lock_bh(&pndevs->lock); list_for_each_entry(pnd, &pndevs->list, list) { -- cgit v1.2.3 From 45a41d147a3a31bb218201b0dd70cfe4e9ed5105 Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Sun, 2 Aug 2009 14:12:01 +0400 Subject: af_ieee802154: fix ioctl processing fix two errors in ioctl processing: 1) if the ioctl isn't supported one should return -ENOIOCTLCMD 2) don't call ndo_do_ioctl if the device doesn't provide it Signed-off-by: Dmitry Eremin-Solenikov --- net/ieee802154/af_ieee802154.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'net') diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c index 3bb6bdb1dac1..af661805b9fa 100644 --- a/net/ieee802154/af_ieee802154.c +++ b/net/ieee802154/af_ieee802154.c @@ -136,7 +136,7 @@ static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg, unsigned int cmd) { struct ifreq ifr; - int ret = -EINVAL; + int ret = -ENOIOCTLCMD; struct net_device *dev; if (copy_from_user(&ifr, arg, sizeof(struct ifreq))) @@ -146,8 +146,10 @@ static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg, dev_load(sock_net(sk), ifr.ifr_name); dev = dev_get_by_name(sock_net(sk), ifr.ifr_name); - if (dev->type == ARPHRD_IEEE802154 || - dev->type == ARPHRD_IEEE802154_PHY) + + if ((dev->type == ARPHRD_IEEE802154 || + dev->type == ARPHRD_IEEE802154_PHY) && + dev->netdev_ops->ndo_do_ioctl) ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, cmd); if (!ret && copy_to_user(arg, &ifr, sizeof(struct ifreq))) -- cgit v1.2.3 From a9dfac3353b03432e3d46a0dde6795588c46256d Mon Sep 17 00:00:00 2001 From: Dmitry Eremin-Solenikov Date: Mon, 3 Aug 2009 17:53:00 +0400 Subject: af_ieee802154: provide dummy get/setsockopt Provide dummt get/setsockopt implementations to stop these syscalls from oopsing on our sockets. Signed-off-by: Dmitry Eremin-Solenikov --- net/ieee802154/dgram.c | 14 ++++++++++++++ net/ieee802154/raw.c | 14 ++++++++++++++ 2 files changed, 28 insertions(+) (limited to 'net') diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c index 14d39840dd62..ba8b214dda8f 100644 --- a/net/ieee802154/dgram.c +++ b/net/ieee802154/dgram.c @@ -377,6 +377,18 @@ int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb) return ret; } +static int dgram_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ + return -EOPNOTSUPP; +} + +static int dgram_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user optlen) +{ + return -EOPNOTSUPP; +} + struct proto ieee802154_dgram_prot = { .name = "IEEE-802.15.4-MAC", .owner = THIS_MODULE, @@ -391,5 +403,7 @@ struct proto ieee802154_dgram_prot = { .connect = dgram_connect, .disconnect = dgram_disconnect, .ioctl = dgram_ioctl, + .getsockopt = dgram_getsockopt, + .setsockopt = dgram_setsockopt, }; diff --git a/net/ieee802154/raw.c b/net/ieee802154/raw.c index fca44d59f97e..9315977c4c61 100644 --- a/net/ieee802154/raw.c +++ b/net/ieee802154/raw.c @@ -238,6 +238,18 @@ void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb) read_unlock(&raw_lock); } +static int raw_getsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user *optlen) +{ + return -EOPNOTSUPP; +} + +static int raw_setsockopt(struct sock *sk, int level, int optname, + char __user *optval, int __user optlen) +{ + return -EOPNOTSUPP; +} + struct proto ieee802154_raw_prot = { .name = "IEEE-802.15.4-RAW", .owner = THIS_MODULE, @@ -250,5 +262,7 @@ struct proto ieee802154_raw_prot = { .unhash = raw_unhash, .connect = raw_connect, .disconnect = raw_disconnect, + .getsockopt = raw_getsockopt, + .setsockopt = raw_setsockopt, }; -- cgit v1.2.3 From 17ac2e9c58b69a1e25460a568eae1b0dc0188c25 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 6 Aug 2009 03:34:06 +0000 Subject: rose: Fix rose_getname() leak rose_getname() can leak kernel memory to user. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/rose/af_rose.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index f0a76f6bca71..e5f478ca3d61 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c @@ -954,6 +954,7 @@ static int rose_getname(struct socket *sock, struct sockaddr *uaddr, struct rose_sock *rose = rose_sk(sk); int n; + memset(srose, 0, sizeof(*srose)); if (peer != 0) { if (sk->sk_state != TCP_ESTABLISHED) return -ENOTCONN; -- cgit v1.2.3 From 80922bbb12a105f858a8f0abb879cb4302d0ecaa Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 6 Aug 2009 03:48:36 +0000 Subject: econet: Fix econet_getname() leak econet_getname() can leak kernel memory to user. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/econet/af_econet.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 2e1f836d4240..f0bbc57926cd 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c @@ -520,6 +520,7 @@ static int econet_getname(struct socket *sock, struct sockaddr *uaddr, if (peer) return -EOPNOTSUPP; + memset(sec, 0, sizeof(*sec)); mutex_lock(&econet_mutex); sk = sock->sk; -- cgit v1.2.3 From f6b97b29513950bfbf621a83d85b6f86b39ec8db Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 6 Aug 2009 03:31:07 +0000 Subject: netrom: Fix nr_getname() leak nr_getname() can leak kernel memory to user. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/netrom/af_netrom.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index ce51ce012cda..ce1a34b99c23 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c @@ -847,6 +847,7 @@ static int nr_getname(struct socket *sock, struct sockaddr *uaddr, sax->fsa_ax25.sax25_family = AF_NETROM; sax->fsa_ax25.sax25_ndigis = 1; sax->fsa_ax25.sax25_call = nr->user_addr; + memset(sax->fsa_digipeater, 0, sizeof(sax->fsa_digipeater)); sax->fsa_digipeater[0] = nr->dest_addr; *uaddr_len = sizeof(struct full_sockaddr_ax25); } else { -- cgit v1.2.3 From 3d392475c873c10c10d6d96b94d092a34ebd4791 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 6 Aug 2009 02:27:43 +0000 Subject: appletalk: fix atalk_getname() leak atalk_getname() can leak 8 bytes of kernel memory to user Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/appletalk/ddp.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 590b83963622..9ef6ff26eb0c 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c @@ -1237,6 +1237,7 @@ static int atalk_getname(struct socket *sock, struct sockaddr *uaddr, return -ENOBUFS; *uaddr_len = sizeof(struct sockaddr_at); + memset(&sat.sat_zero, 0, sizeof(sat.sat_zero)); if (peer) { if (sk->sk_state != TCP_ESTABLISHED) -- cgit v1.2.3 From 09384dfc76e526c3993c09c42e016372dc9dd22c Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 6 Aug 2009 03:55:04 +0000 Subject: irda: Fix irda_getname() leak irda_getname() can leak kernel memory to user. Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- net/irda/af_irda.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index cb762c8723ea..3ec2b434ea75 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c @@ -714,6 +714,7 @@ static int irda_getname(struct socket *sock, struct sockaddr *uaddr, struct sock *sk = sock->sk; struct irda_sock *self = irda_sk(sk); + memset(&saddr, 0, sizeof(saddr)); if (peer) { if (sk->sk_state != TCP_ESTABLISHED) return -ENOTCONN; -- cgit v1.2.3 From b79a79471bd31d737c939a6ddc347417047b4320 Mon Sep 17 00:00:00 2001 From: Jussi Mäki Date: Thu, 6 Aug 2009 21:38:14 +0000 Subject: Fix xfrm hash collisions by changing __xfrm4_daddr_saddr_hash to hash addresses with addition This patch fixes hash collisions in cases where number of entries have incrementing IP source and destination addresses from single respective subnets (i.e. 192.168.0.1-172.16.0.1, 192.168.0.2-172.16.0.2, and so on.). Signed-off-by: Jussi Maki Signed-off-by: David S. Miller --- net/xfrm/xfrm_hash.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/xfrm/xfrm_hash.h b/net/xfrm/xfrm_hash.h index d401dc8f05ed..e5195c99f71e 100644 --- a/net/xfrm/xfrm_hash.h +++ b/net/xfrm/xfrm_hash.h @@ -16,7 +16,7 @@ static inline unsigned int __xfrm6_addr_hash(xfrm_address_t *addr) static inline unsigned int __xfrm4_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) { - return ntohl(daddr->a4 ^ saddr->a4); + return ntohl(daddr->a4 + saddr->a4); } static inline unsigned int __xfrm6_daddr_saddr_hash(xfrm_address_t *daddr, xfrm_address_t *saddr) -- cgit v1.2.3 From e84b90ae5eb3c112d1f208964df1d8156a538289 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 6 Aug 2009 20:27:04 +0000 Subject: can: Fix raw_getname() leak raw_getname() can leak 10 bytes of kernel memory to user (two bytes hole between can_family and can_ifindex, 8 bytes at the end of sockaddr_can structure) Signed-off-by: Eric Dumazet Acked-by: Oliver Hartkopp Signed-off-by: David S. Miller --- net/can/raw.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/can/raw.c b/net/can/raw.c index f4cc44548bda..db3152df7d2b 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -401,6 +401,7 @@ static int raw_getname(struct socket *sock, struct sockaddr *uaddr, if (peer) return -EOPNOTSUPP; + memset(addr, 0, sizeof(*addr)); addr->can_family = AF_CAN; addr->can_ifindex = ro->ifindex; -- cgit v1.2.3 From 418372b0ab7a3bbcc59d71e8e4d322ef18263dab Mon Sep 17 00:00:00 2001 From: Rafael Laufer Date: Fri, 7 Aug 2009 05:17:17 +0000 Subject: sctp: fix missing destroy of percpu counter variable in sctp_proc_exit() Commit 1748376b6626acf59c24e9592ac67b3fe2a0e026, net: Use a percpu_counter for sockets_allocated added percpu_counter function calls to sctp_proc_init code path, but forgot to add them to sctp_proc_exit(). This resulted in a following Ooops when performing this test # modprobe sctp # rmmod -f sctp # modprobe sctp [ 573.862512] BUG: unable to handle kernel paging request at f8214a24 [ 573.862518] IP: [] __percpu_counter_init+0x3f/0x70 [ 573.862530] *pde = 37010067 *pte = 00000000 [ 573.862534] Oops: 0002 [#1] SMP [ 573.862537] last sysfs file: /sys/module/libcrc32c/initstate [ 573.862540] Modules linked in: sctp(+) crc32c libcrc32c binfmt_misc bridge stp bnep lp snd_hda_codec_analog snd_hda_intel snd_hda_codec snd_hwdep snd_pcm_oss snd_mixer_oss arc4 joydev snd_pcm ecb pcmcia snd_seq_dummy snd_seq_oss iwlagn iwlcore snd_seq_midi snd_rawmidi snd_seq_midi_event yenta_socket rsrc_nonstatic thinkpad_acpi snd_seq snd_timer snd_seq_device mac80211 psmouse sdhci_pci sdhci nvidia(P) ppdev video snd soundcore serio_raw pcspkr iTCO_wdt iTCO_vendor_support led_class ricoh_mmc pcmcia_core intel_agp nvram agpgart usbhid parport_pc parport output snd_page_alloc cfg80211 btusb ohci1394 ieee1394 e1000e [last unloaded: sctp] [ 573.862589] [ 573.862593] Pid: 5373, comm: modprobe Tainted: P R (2.6.31-rc3 #6) 7663B15 [ 573.862596] EIP: 0060:[] EFLAGS: 00010286 CPU: 1 [ 573.862599] EIP is at __percpu_counter_init+0x3f/0x70 [ 573.862602] EAX: f8214a20 EBX: f80faa14 ECX: c48c0000 EDX: f80faa20 [ 573.862604] ESI: f80a7000 EDI: 00000000 EBP: f69d5ef0 ESP: f69d5eec [ 573.862606] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 [ 573.862610] Process modprobe (pid: 5373, ti=f69d4000 task=c2130c70 task.ti=f69d4000) [ 573.862612] Stack: [ 573.862613] 00000000 f69d5f18 f80a70a8 f80fa9fc 00000000 fffffffc f69d5f30 c018e2d4 [ 573.862619] <0> 00000000 f80a7000 00000000 f69d5f88 c010112b 00000000 c07029c0 fffffffb [ 573.862626] <0> 00000000 f69d5f38 c018f83f f69d5f54 c0557cad f80fa860 00000001 c07010c0 [ 573.862634] Call Trace: [ 573.862644] [] ? sctp_init+0xa8/0x7d4 [sctp] [ 573.862650] [] ? marker_update_probe_range+0x184/0x260 [ 573.862659] [] ? sctp_init+0x0/0x7d4 [sctp] [ 573.862662] [] ? do_one_initcall+0x2b/0x160 [ 573.862666] [] ? tracepoint_module_notify+0x2f/0x40 [ 573.862671] [] ? notifier_call_chain+0x2d/0x70 [ 573.862678] [] ? __blocking_notifier_call_chain+0x4d/0x60 [ 573.862682] [] ? sys_init_module+0xb1/0x1f0 [ 573.862686] [] ? sysenter_do_call+0x12/0x28 [ 573.862688] Code: 89 48 08 b8 04 00 00 00 e8 df aa ec ff ba f4 ff ff ff 85 c0 89 43 14 74 31 b8 b0 18 71 c0 e8 19 b9 24 00 a1 c4 18 71 c0 8d 53 0c <89> 50 04 89 43 0c b8 b0 18 71 c0 c7 43 10 c4 18 71 c0 89 15 c4 [ 573.862725] EIP: [] __percpu_counter_init+0x3f/0x70 SS:ESP 0068:f69d5eec [ 573.862730] CR2: 00000000f8214a24 [ 573.862734] ---[ end trace 39c4e0b55e7cf54d ]--- Signed-off-by: Rafael Laufer Signed-off-by: Vlad Yasevich Signed-off-by: David S. Miller --- net/sctp/protocol.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net') diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 79cbd47f4df7..a76da657244a 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c @@ -160,6 +160,7 @@ static void sctp_proc_exit(void) remove_proc_entry("sctp", init_net.proc_net); } #endif + percpu_counter_destroy(&sctp_sockets_allocated); } /* Private helper to extract ipv4 address and stash them in -- cgit v1.2.3 From 416fbdff2137e8d8cc8f23f517bee3a26b11526f Mon Sep 17 00:00:00 2001 From: Luis R. Rodriguez Date: Tue, 11 Aug 2009 13:10:33 -0700 Subject: mac80211: fix panic when splicing unprepared TIDs We splice skbs from the pending queue for a TID onto the local pending queue when tearing down a block ack request. This is not necessary unless we actually have received a request to start a block ack request (rate control, for example). If we never received that request we should not be splicing the tid pending queue as it would be null, causing a panic. Not sure yet how exactly we allowed through a call when the tid state does not have at least HT_ADDBA_REQUESTED_MSK set, that will require some further review as it is not quite obvious. For more information see the bug report: http://bugzilla.kernel.org/show_bug.cgi?id=13922 This fixes this oops: BUG: unable to handle kernel NULL pointer dereference at 00000030 IP: [] ieee80211_agg_splice_packets+0x40/0xc0 [mac80211] *pdpt = 0000000002d1e001 *pde = 0000000000000000 Thread overran stack, or stack corrupted Oops: 0000 [#1] SMP last sysfs file: /sys/module/aes_generic/initstate Modules linked in: Pid: 0, comm: swapper Not tainted (2.6.31-rc5-wl #2) Dell DV051 EIP: 0060:[] EFLAGS: 00010292 CPU: 0 EIP is at ieee80211_agg_splice_packets+0x40/0xc0 [mac80211] EAX: 00000030 EBX: 0000004c ECX: 00000003 EDX: 00000000 ESI: c1c98000 EDI: f745a1c0 EBP: c076be58 ESP: c076be38 DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068 Process swapper (pid: 0, ti=c076a000 task=c0709160 task.ti=c076a000) Stack: Call Trace: [] ? ieee80211_stop_tx_ba_cb+0xab/0x150 [mac80211] [] ? ieee80211_tasklet_handler+0xce/0x110 [mac80211] [] ? net_rx_action+0xef/0x1d0 [] ? tasklet_action+0x58/0xc0 [] ? __do_softirq+0xc2/0x190 [] ? handle_IRQ_event+0x58/0x140 [] ? ack_apic_level+0x7e/0x270 [] ? do_softirq+0x3d/0x40 [] ? irq_exit+0x65/0x90 [] ? do_IRQ+0x4f/0xc0 [] ? irq_exit+0x7d/0x90 [] ? smp_apic_timer_interrupt+0x57/0x90 [] ? common_interrupt+0x29/0x30 [] ? mwait_idle+0xbe/0x100 [] ? cpu_idle+0x52/0x90 [] ? rest_init+0x55/0x60 [] ? start_kernel+0x315/0x37d [] ? unknown_bootoption+0x0/0x1f9 [] ? i386_start_kernel+0x79/0x81 Code: EIP: [] ieee80211_agg_splice_packets+0x40/0xc0 [mac80211] SS:ESP 0068:c076be38 CR2: 0000000000000030 Cc: stable@kernel.org Testedy-by: Jack Lau Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- net/mac80211/agg-tx.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'net') diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 9e5762ad307d..a24e59816b93 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c @@ -381,6 +381,14 @@ static void ieee80211_agg_splice_packets(struct ieee80211_local *local, &local->hw, queue, IEEE80211_QUEUE_STOP_REASON_AGGREGATION); + if (!(sta->ampdu_mlme.tid_state_tx[tid] & HT_ADDBA_REQUESTED_MSK)) + return; + + if (WARN(!sta->ampdu_mlme.tid_tx[tid], + "TID %d gone but expected when splicing aggregates from" + "the pending queue\n", tid)) + return; + if (!skb_queue_empty(&sta->ampdu_mlme.tid_tx[tid]->pending)) { spin_lock_irqsave(&local->queue_stop_reason_lock, flags); /* mark queue as pending, it is stopped already */ -- cgit v1.2.3 From 8cdb045632e5ee22854538619ac6f150eb0a4894 Mon Sep 17 00:00:00 2001 From: Tom Goff Date: Fri, 14 Aug 2009 16:33:56 -0700 Subject: gre: Fix MTU calculation for bound GRE tunnels The GRE header length should be subtracted when the tunnel MTU is calculated. This just corrects for the associativity change introduced by commit 42aa916265d740d66ac1f17290366e9494c884c2 ("gre: Move MTU setting out of ipgre_tunnel_bind_dev"). Signed-off-by: Tom Goff Signed-off-by: David S. Miller --- net/ipv4/ip_gre.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index cb4a0f4bd5e5..82c11dd10a62 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c @@ -951,7 +951,7 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev) addend += 4; } dev->needed_headroom = addend + hlen; - mtu -= dev->hard_header_len - addend; + mtu -= dev->hard_header_len + addend; if (mtu < 68) mtu = 68; -- cgit v1.2.3 From c6ba973b8fa97422aab4204f7d79f1d413cde925 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 17 Aug 2009 18:05:32 -0700 Subject: NETROM: Fix use of static buffer The static variable used by nr_call_to_digi might result in corruption if multiple threads are trying to usee a node or neighbour via ioctl. Fixed by having the caller pass a structure in. This is safe because nr_add_node rsp. nr_add_neigh will allocate a permanent structure, if needed. Signed-off-by: Ralf Baechle Signed-off-by: David S. Miller --- net/netrom/nr_route.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'net') diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c index e943c16552a2..4eb1ac9a7679 100644 --- a/net/netrom/nr_route.c +++ b/net/netrom/nr_route.c @@ -630,23 +630,23 @@ out: return dev; } -static ax25_digi *nr_call_to_digi(int ndigis, ax25_address *digipeaters) +static ax25_digi *nr_call_to_digi(ax25_digi *digi, int ndigis, + ax25_address *digipeaters) { - static ax25_digi ax25_digi; int i; if (ndigis == 0) return NULL; for (i = 0; i < ndigis; i++) { - ax25_digi.calls[i] = digipeaters[i]; - ax25_digi.repeated[i] = 0; + digi->calls[i] = digipeaters[i]; + digi->repeated[i] = 0; } - ax25_digi.ndigi = ndigis; - ax25_digi.lastrepeat = -1; + digi->ndigi = ndigis; + digi->lastrepeat = -1; - return &ax25_digi; + return digi; } /* @@ -656,6 +656,7 @@ int nr_rt_ioctl(unsigned int cmd, void __user *arg) { struct nr_route_struct nr_route; struct net_device *dev; + ax25_digi digi; int ret; switch (cmd) { @@ -673,13 +674,15 @@ int nr_rt_ioctl(unsigned int cmd, void __user *arg) ret = nr_add_node(&nr_route.callsign, nr_route.mnemonic, &nr_route.neighbour, - nr_call_to_digi(nr_route.ndigis, nr_route.digipeaters), + nr_call_to_digi(&digi, nr_route.ndigis, + nr_route.digipeaters), dev, nr_route.quality, nr_route.obs_count); break; case NETROM_NEIGH: ret = nr_add_neigh(&nr_route.callsign, - nr_call_to_digi(nr_route.ndigis, nr_route.digipeaters), + nr_call_to_digi(&digi, nr_route.ndigis, + nr_route.digipeaters), dev, nr_route.quality); break; default: -- cgit v1.2.3 From c1a8f1f1c8e01eab5862c8db39b49ace814e6c66 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Sun, 16 Aug 2009 09:36:49 +0000 Subject: net: restore gnet_stats_basic to previous definition In 5e140dfc1fe87eae27846f193086724806b33c7d "net: reorder struct Qdisc for better SMP performance" the definition of struct gnet_stats_basic changed incompatibly, as copies of this struct are shipped to userland via netlink. Restoring old behavior is not welcome, for performance reason. Fix is to use a private structure for kernel, and teach gnet_stats_copy_basic() to convert from kernel to user land, using legacy structure (struct gnet_stats_basic) Based on a report and initial patch from Michael Spang. Reported-by: Michael Spang Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/linux/gen_stats.h | 5 +++++ include/net/act_api.h | 2 +- include/net/gen_stats.h | 10 +++++----- include/net/netfilter/xt_rateest.h | 2 +- include/net/sch_generic.h | 2 +- net/core/gen_estimator.c | 12 ++++++------ net/core/gen_stats.c | 11 ++++++++--- net/netfilter/xt_RATEEST.c | 2 +- net/sched/sch_atm.c | 2 +- net/sched/sch_cbq.c | 2 +- net/sched/sch_drr.c | 2 +- net/sched/sch_hfsc.c | 2 +- net/sched/sch_htb.c | 2 +- 13 files changed, 33 insertions(+), 23 deletions(-) (limited to 'net') diff --git a/include/linux/gen_stats.h b/include/linux/gen_stats.h index 0ffa41df0ee8..710e901085d0 100644 --- a/include/linux/gen_stats.h +++ b/include/linux/gen_stats.h @@ -19,6 +19,11 @@ enum { * @packets: number of seen packets */ struct gnet_stats_basic +{ + __u64 bytes; + __u32 packets; +}; +struct gnet_stats_basic_packed { __u64 bytes; __u32 packets; diff --git a/include/net/act_api.h b/include/net/act_api.h index 565eed8fe496..c05fd717c588 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -16,7 +16,7 @@ struct tcf_common { u32 tcfc_capab; int tcfc_action; struct tcf_t tcfc_tm; - struct gnet_stats_basic tcfc_bstats; + struct gnet_stats_basic_packed tcfc_bstats; struct gnet_stats_queue tcfc_qstats; struct gnet_stats_rate_est tcfc_rate_est; spinlock_t tcfc_lock; diff --git a/include/net/gen_stats.h b/include/net/gen_stats.h index d136b5240ef2..c1488553e349 100644 --- a/include/net/gen_stats.h +++ b/include/net/gen_stats.h @@ -28,7 +28,7 @@ extern int gnet_stats_start_copy_compat(struct sk_buff *skb, int type, spinlock_t *lock, struct gnet_dump *d); extern int gnet_stats_copy_basic(struct gnet_dump *d, - struct gnet_stats_basic *b); + struct gnet_stats_basic_packed *b); extern int gnet_stats_copy_rate_est(struct gnet_dump *d, struct gnet_stats_rate_est *r); extern int gnet_stats_copy_queue(struct gnet_dump *d, @@ -37,14 +37,14 @@ extern int gnet_stats_copy_app(struct gnet_dump *d, void *st, int len); extern int gnet_stats_finish_copy(struct gnet_dump *d); -extern int gen_new_estimator(struct gnet_stats_basic *bstats, +extern int gen_new_estimator(struct gnet_stats_basic_packed *bstats, struct gnet_stats_rate_est *rate_est, spinlock_t *stats_lock, struct nlattr *opt); -extern void gen_kill_estimator(struct gnet_stats_basic *bstats, +extern void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, struct gnet_stats_rate_est *rate_est); -extern int gen_replace_estimator(struct gnet_stats_basic *bstats, +extern int gen_replace_estimator(struct gnet_stats_basic_packed *bstats, struct gnet_stats_rate_est *rate_est, spinlock_t *stats_lock, struct nlattr *opt); -extern bool gen_estimator_active(const struct gnet_stats_basic *bstats, +extern bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats, const struct gnet_stats_rate_est *rate_est); #endif diff --git a/include/net/netfilter/xt_rateest.h b/include/net/netfilter/xt_rateest.h index 65d594dffbff..ddbf37e19616 100644 --- a/include/net/netfilter/xt_rateest.h +++ b/include/net/netfilter/xt_rateest.h @@ -8,7 +8,7 @@ struct xt_rateest { spinlock_t lock; struct gnet_estimator params; struct gnet_stats_rate_est rstats; - struct gnet_stats_basic bstats; + struct gnet_stats_basic_packed bstats; }; extern struct xt_rateest *xt_rateest_lookup(const char *name); diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index 964ffa0d8815..5482e9582f55 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -72,7 +72,7 @@ struct Qdisc */ unsigned long state; struct sk_buff_head q; - struct gnet_stats_basic bstats; + struct gnet_stats_basic_packed bstats; struct gnet_stats_queue qstats; }; diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 78e5bfc454ae..493775f4f2f1 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c @@ -81,7 +81,7 @@ struct gen_estimator { struct list_head list; - struct gnet_stats_basic *bstats; + struct gnet_stats_basic_packed *bstats; struct gnet_stats_rate_est *rate_est; spinlock_t *stats_lock; int ewma_log; @@ -165,7 +165,7 @@ static void gen_add_node(struct gen_estimator *est) } static -struct gen_estimator *gen_find_node(const struct gnet_stats_basic *bstats, +struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats, const struct gnet_stats_rate_est *rate_est) { struct rb_node *p = est_root.rb_node; @@ -202,7 +202,7 @@ struct gen_estimator *gen_find_node(const struct gnet_stats_basic *bstats, * * NOTE: Called under rtnl_mutex */ -int gen_new_estimator(struct gnet_stats_basic *bstats, +int gen_new_estimator(struct gnet_stats_basic_packed *bstats, struct gnet_stats_rate_est *rate_est, spinlock_t *stats_lock, struct nlattr *opt) @@ -262,7 +262,7 @@ static void __gen_kill_estimator(struct rcu_head *head) * * NOTE: Called under rtnl_mutex */ -void gen_kill_estimator(struct gnet_stats_basic *bstats, +void gen_kill_estimator(struct gnet_stats_basic_packed *bstats, struct gnet_stats_rate_est *rate_est) { struct gen_estimator *e; @@ -292,7 +292,7 @@ EXPORT_SYMBOL(gen_kill_estimator); * * Returns 0 on success or a negative error code. */ -int gen_replace_estimator(struct gnet_stats_basic *bstats, +int gen_replace_estimator(struct gnet_stats_basic_packed *bstats, struct gnet_stats_rate_est *rate_est, spinlock_t *stats_lock, struct nlattr *opt) { @@ -308,7 +308,7 @@ EXPORT_SYMBOL(gen_replace_estimator); * * Returns true if estimator is active, and false if not. */ -bool gen_estimator_active(const struct gnet_stats_basic *bstats, +bool gen_estimator_active(const struct gnet_stats_basic_packed *bstats, const struct gnet_stats_rate_est *rate_est) { ASSERT_RTNL(); diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c index c3d0ffeac243..8569310268ab 100644 --- a/net/core/gen_stats.c +++ b/net/core/gen_stats.c @@ -106,16 +106,21 @@ gnet_stats_start_copy(struct sk_buff *skb, int type, spinlock_t *lock, * if the room in the socket buffer was not sufficient. */ int -gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic *b) +gnet_stats_copy_basic(struct gnet_dump *d, struct gnet_stats_basic_packed *b) { if (d->compat_tc_stats) { d->tc_stats.bytes = b->bytes; d->tc_stats.packets = b->packets; } - if (d->tail) - return gnet_stats_copy(d, TCA_STATS_BASIC, b, sizeof(*b)); + if (d->tail) { + struct gnet_stats_basic sb; + memset(&sb, 0, sizeof(sb)); + sb.bytes = b->bytes; + sb.packets = b->packets; + return gnet_stats_copy(d, TCA_STATS_BASIC, &sb, sizeof(sb)); + } return 0; } diff --git a/net/netfilter/xt_RATEEST.c b/net/netfilter/xt_RATEEST.c index 43f5676b1af4..d80b8192e0d4 100644 --- a/net/netfilter/xt_RATEEST.c +++ b/net/netfilter/xt_RATEEST.c @@ -74,7 +74,7 @@ static unsigned int xt_rateest_tg(struct sk_buff *skb, const struct xt_target_param *par) { const struct xt_rateest_target_info *info = par->targinfo; - struct gnet_stats_basic *stats = &info->est->bstats; + struct gnet_stats_basic_packed *stats = &info->est->bstats; spin_lock_bh(&info->est->lock); stats->bytes += skb->len; diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 2a8b83af7c47..ab82f145f689 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c @@ -49,7 +49,7 @@ struct atm_flow_data { struct socket *sock; /* for closing */ u32 classid; /* x:y type ID */ int ref; /* reference count */ - struct gnet_stats_basic bstats; + struct gnet_stats_basic_packed bstats; struct gnet_stats_queue qstats; struct atm_flow_data *next; struct atm_flow_data *excess; /* flow for excess traffic; diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 23a167670fd5..d5798e17a832 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c @@ -128,7 +128,7 @@ struct cbq_class long avgidle; long deficit; /* Saved deficit for WRR */ psched_time_t penalized; - struct gnet_stats_basic bstats; + struct gnet_stats_basic_packed bstats; struct gnet_stats_queue qstats; struct gnet_stats_rate_est rate_est; struct tc_cbq_xstats xstats; diff --git a/net/sched/sch_drr.c b/net/sched/sch_drr.c index 7597fe146866..12b2fb04b29b 100644 --- a/net/sched/sch_drr.c +++ b/net/sched/sch_drr.c @@ -22,7 +22,7 @@ struct drr_class { unsigned int refcnt; unsigned int filter_cnt; - struct gnet_stats_basic bstats; + struct gnet_stats_basic_packed bstats; struct gnet_stats_queue qstats; struct gnet_stats_rate_est rate_est; struct list_head alist; diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index 362c2811b2df..dad0144423da 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c @@ -116,7 +116,7 @@ struct hfsc_class struct Qdisc_class_common cl_common; unsigned int refcnt; /* usage count */ - struct gnet_stats_basic bstats; + struct gnet_stats_basic_packed bstats; struct gnet_stats_queue qstats; struct gnet_stats_rate_est rate_est; unsigned int level; /* class level in hierarchy */ diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 88cd02626621..ec4d46399d59 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -74,7 +74,7 @@ enum htb_cmode { struct htb_class { struct Qdisc_class_common common; /* general class parameters */ - struct gnet_stats_basic bstats; + struct gnet_stats_basic_packed bstats; struct gnet_stats_queue qstats; struct gnet_stats_rate_est rate_est; struct tc_htb_xstats xstats; /* our special stats */ -- cgit v1.2.3