From 534f81a5068799799e264fd162e9488a129f98d4 Mon Sep 17 00:00:00 2001 From: "Mark H. Weaver" Date: Mon, 23 Mar 2009 13:46:12 +0100 Subject: netfilter: nf_conntrack_tcp: fix unaligned memory access in tcp_sack This patch fixes an unaligned memory access in tcp_sack while reading sequence numbers from TCP selective acknowledgement options. Prior to applying this patch, upstream linux-2.6.27.20 was occasionally generating messages like this on my sparc64 system: [54678.532071] Kernel unaligned access at TPC[6b17d4] tcp_packet+0xcd4/0xd00 Acked-by: David S. Miller Signed-off-by: Patrick McHardy --- net/netfilter/nf_conntrack_proto_tcp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index f3fd154d1ddd..56ac4ee77a1d 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -466,7 +467,7 @@ static void tcp_sack(const struct sk_buff *skb, unsigned int dataoff, for (i = 0; i < (opsize - TCPOLEN_SACK_BASE); i += TCPOLEN_SACK_PERBLOCK) { - tmp = ntohl(*((__be32 *)(ptr+i)+1)); + tmp = get_unaligned_be32((__be32 *)(ptr+i)+1); if (after(tmp, *sack)) *sack = tmp; -- cgit v1.2.3 From 30842f2989aacfaba3ccb39829b3417be9313dbe Mon Sep 17 00:00:00 2001 From: Vitaly Mayatskikh Date: Mon, 23 Mar 2009 15:22:33 -0700 Subject: udp: Wrong locking code in udp seq_file infrastructure Reading zero bytes from /proc/net/udp or other similar files which use the same seq_file udp infrastructure panics kernel in that way: ===================================== [ BUG: bad unlock balance detected! ] ------------------------------------- read/1985 is trying to release lock (&table->hash[i].lock) at: [] udp_seq_stop+0x27/0x29 but there are no more locks to release! other info that might help us debug this: 1 lock held by read/1985: #0: (&p->lock){--..}, at: [] seq_read+0x38/0x348 stack backtrace: Pid: 1985, comm: read Not tainted 2.6.29-rc8 #9 Call Trace: [] ? udp_seq_stop+0x27/0x29 [] print_unlock_inbalance_bug+0xd6/0xe1 [] lock_release_non_nested+0x9e/0x1c6 [] ? seq_read+0xb2/0x348 [] ? mark_held_locks+0x68/0x86 [] ? udp_seq_stop+0x27/0x29 [] lock_release+0x15d/0x189 [] _spin_unlock_bh+0x1e/0x34 [] udp_seq_stop+0x27/0x29 [] seq_read+0x2bb/0x348 [] ? seq_read+0x0/0x348 [] proc_reg_read+0x90/0xaf [] vfs_read+0xa6/0x103 [] ? trace_hardirqs_on_caller+0x12f/0x153 [] sys_read+0x45/0x69 [] system_call_fastpath+0x16/0x1b BUG: scheduling while atomic: read/1985/0xffffff00 INFO: lockdep is turned off. Modules linked in: cpufreq_ondemand acpi_cpufreq freq_table dm_multipath kvm ppdev snd_hda_codec_analog snd_hda_intel snd_hda_codec snd_hwdep snd_seq_dummy snd_seq_oss snd_seq_midi_event arc4 snd_s eq ecb thinkpad_acpi snd_seq_device iwl3945 hwmon sdhci_pci snd_pcm_oss sdhci rfkill mmc_core snd_mixer_oss i2c_i801 mac80211 yenta_socket ricoh_mmc i2c_core iTCO_wdt snd_pcm iTCO_vendor_support rs rc_nonstatic snd_timer snd lib80211 cfg80211 soundcore snd_page_alloc video parport_pc output parport e1000e [last unloaded: scsi_wait_scan] Pid: 1985, comm: read Not tainted 2.6.29-rc8 #9 Call Trace: [] ? __debug_show_held_locks+0x1b/0x24 [] __schedule_bug+0x7e/0x83 [] schedule+0xce/0x838 [] ? fsnotify_access+0x5f/0x67 [] ? sysret_careful+0xb/0x37 [] ? trace_hardirqs_on_caller+0x1f/0x153 [] ? trace_hardirqs_on_thunk+0x3a/0x3f [] sysret_careful+0x31/0x37 read[1985]: segfault at 7fffc479bfe8 ip 0000003e7420a180 sp 00007fffc479bfa0 error 6 Kernel panic - not syncing: Aiee, killing interrupt handler! udp_seq_stop() tries to unlock not yet locked spinlock. The lock was lost during splitting global udp_hash_lock to subsequent spinlocks. Signed-off by: Vitaly Mayatskikh Acked-by: Eric Dumazet Signed-off-by: David S. Miller --- net/ipv4/udp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'net') diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index c47c989cb1fb..c8bee189a193 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -1614,7 +1614,8 @@ static struct sock *udp_get_next(struct seq_file *seq, struct sock *sk) } while (sk && (!net_eq(sock_net(sk), net) || sk->sk_family != state->family)); if (!sk) { - spin_unlock_bh(&state->udp_table->hash[state->bucket].lock); + if (state->bucket < UDP_HTABLE_SIZE) + spin_unlock_bh(&state->udp_table->hash[state->bucket].lock); return udp_get_first(seq, state->bucket + 1); } return sk; @@ -1632,6 +1633,9 @@ static struct sock *udp_get_idx(struct seq_file *seq, loff_t pos) static void *udp_seq_start(struct seq_file *seq, loff_t *pos) { + struct udp_iter_state *state = seq->private; + state->bucket = UDP_HTABLE_SIZE; + return *pos ? udp_get_idx(seq, *pos-1) : SEQ_START_TOKEN; } -- cgit v1.2.3 From cda6d377ec6b2ee2e58d563d0bd7eb313e0165df Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 25 Mar 2009 21:01:47 -0700 Subject: bridge: bad error handling when adding invalid ether address This fixes an crash when empty bond device is added to a bridge. If an interface with invalid ethernet address (all zero) is added to a bridge, then bridge code detects it when setting up the forward databas entry. But the error unwind is broken, the bridge port object can get freed twice: once when ref count went to zeo, and once by kfree. Since object is never really accessible, just free it. Signed-off-by: Stephen Hemminger Signed-off-by: David S. Miller --- net/bridge/br_if.c | 1 - 1 file changed, 1 deletion(-) (limited to 'net') diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 727c5c510a60..8a96672e2c5c 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -426,7 +426,6 @@ err2: err1: kobject_del(&p->kobj); err0: - kobject_put(&p->kobj); dev_set_promiscuity(dev, -1); put_back: dev_put(dev); -- cgit v1.2.3