]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
3.0-stable patches
authorGreg Kroah-Hartman <gregkh@suse.de>
Tue, 31 Jan 2012 19:46:27 +0000 (11:46 -0800)
committerGreg Kroah-Hartman <gregkh@suse.de>
Tue, 31 Jan 2012 19:46:27 +0000 (11:46 -0800)
added patches:
bonding-fix-enslaving-in-alb-mode-when-link-down.patch
l2tp-l2tp_ip-fix-possible-oops-on-packet-receive.patch
net-bpf_jit-fix-divide-by-0-generation.patch
net-caif-register-properly-as-a-pernet-subsystem.patch
netns-fail-conspicously-if-someone-uses-net_generic-at-an-inappropriate-time.patch
netns-fix-net_alloc_generic.patch
rds-make-rds_sock_lock-bh-rather-than-irq-safe.patch
tcp-fix-tcp_trim_head-to-adjust-segment-count-with-skb-mss.patch
tcp-md5-using-remote-adress-for-md5-lookup-in-rst-packet.patch

queue-3.0/bonding-fix-enslaving-in-alb-mode-when-link-down.patch [new file with mode: 0644]
queue-3.0/l2tp-l2tp_ip-fix-possible-oops-on-packet-receive.patch [new file with mode: 0644]
queue-3.0/net-bpf_jit-fix-divide-by-0-generation.patch [new file with mode: 0644]
queue-3.0/net-caif-register-properly-as-a-pernet-subsystem.patch [new file with mode: 0644]
queue-3.0/netns-fail-conspicously-if-someone-uses-net_generic-at-an-inappropriate-time.patch [new file with mode: 0644]
queue-3.0/netns-fix-net_alloc_generic.patch [new file with mode: 0644]
queue-3.0/rds-make-rds_sock_lock-bh-rather-than-irq-safe.patch [new file with mode: 0644]
queue-3.0/series
queue-3.0/tcp-fix-tcp_trim_head-to-adjust-segment-count-with-skb-mss.patch [new file with mode: 0644]
queue-3.0/tcp-md5-using-remote-adress-for-md5-lookup-in-rst-packet.patch [new file with mode: 0644]

diff --git a/queue-3.0/bonding-fix-enslaving-in-alb-mode-when-link-down.patch b/queue-3.0/bonding-fix-enslaving-in-alb-mode-when-link-down.patch
new file mode 100644 (file)
index 0000000..9494106
--- /dev/null
@@ -0,0 +1,114 @@
+From fc9c8ea2fbebcb07185e7a46a0739b7b5f6b6f48 Mon Sep 17 00:00:00 2001
+From: Jiri Bohac <jbohac@suse.cz>
+Date: Wed, 18 Jan 2012 12:24:54 +0000
+Subject: bonding: fix enslaving in alb mode when link down
+
+
+From: Jiri Bohac <jbohac@suse.cz>
+
+[ Upstream commit b924551bed09f61b64f21bffe241afc5526b091a ]
+
+bond_alb_init_slave() is called from bond_enslave() and sets the slave's MAC
+address. This is done differently for TLB and ALB modes.
+bond->alb_info.rlb_enabled is used to discriminate between the two modes but
+this flag may be uninitialized if the slave is being enslaved prior to calling
+bond_open() -> bond_alb_initialize() on the master.
+
+It turns out all the callers of alb_set_slave_mac_addr() pass
+bond->alb_info.rlb_enabled as the hw parameter.
+
+This patch cleans up the unnecessary parameter of alb_set_slave_mac_addr() and
+makes the function decide based on the bonding mode instead, which fixes the
+above problem.
+
+Reported-by: Narendra K <Narendra_K@Dell.com>
+Signed-off-by: Jiri Bohac <jbohac@suse.cz>
+Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/net/bonding/bond_alb.c |   27 +++++++++------------------
+ 1 file changed, 9 insertions(+), 18 deletions(-)
+
+--- a/drivers/net/bonding/bond_alb.c
++++ b/drivers/net/bonding/bond_alb.c
+@@ -871,16 +871,12 @@ static void alb_send_learning_packets(st
+       }
+ }
+-/* hw is a boolean parameter that determines whether we should try and
+- * set the hw address of the device as well as the hw address of the
+- * net_device
+- */
+-static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[], int hw)
++static int alb_set_slave_mac_addr(struct slave *slave, u8 addr[])
+ {
+       struct net_device *dev = slave->dev;
+       struct sockaddr s_addr;
+-      if (!hw) {
++      if (slave->bond->params.mode == BOND_MODE_TLB) {
+               memcpy(dev->dev_addr, addr, dev->addr_len);
+               return 0;
+       }
+@@ -910,8 +906,8 @@ static void alb_swap_mac_addr(struct bon
+       u8 tmp_mac_addr[ETH_ALEN];
+       memcpy(tmp_mac_addr, slave1->dev->dev_addr, ETH_ALEN);
+-      alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr, bond->alb_info.rlb_enabled);
+-      alb_set_slave_mac_addr(slave2, tmp_mac_addr, bond->alb_info.rlb_enabled);
++      alb_set_slave_mac_addr(slave1, slave2->dev->dev_addr);
++      alb_set_slave_mac_addr(slave2, tmp_mac_addr);
+ }
+@@ -1058,8 +1054,7 @@ static int alb_handle_addr_collision_on_
+               /* Try setting slave mac to bond address and fall-through
+                  to code handling that situation below... */
+-              alb_set_slave_mac_addr(slave, bond->dev->dev_addr,
+-                                     bond->alb_info.rlb_enabled);
++              alb_set_slave_mac_addr(slave, bond->dev->dev_addr);
+       }
+       /* The slave's address is equal to the address of the bond.
+@@ -1095,8 +1090,7 @@ static int alb_handle_addr_collision_on_
+       }
+       if (free_mac_slave) {
+-              alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr,
+-                                     bond->alb_info.rlb_enabled);
++              alb_set_slave_mac_addr(slave, free_mac_slave->perm_hwaddr);
+               pr_warning("%s: Warning: the hw address of slave %s is in use by the bond; giving it the hw address of %s\n",
+                          bond->dev->name, slave->dev->name,
+@@ -1452,8 +1446,7 @@ int bond_alb_init_slave(struct bonding *
+ {
+       int res;
+-      res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr,
+-                                   bond->alb_info.rlb_enabled);
++      res = alb_set_slave_mac_addr(slave, slave->perm_hwaddr);
+       if (res) {
+               return res;
+       }
+@@ -1604,8 +1597,7 @@ void bond_alb_handle_active_change(struc
+               alb_swap_mac_addr(bond, swap_slave, new_slave);
+       } else {
+               /* set the new_slave to the bond mac address */
+-              alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr,
+-                                     bond->alb_info.rlb_enabled);
++              alb_set_slave_mac_addr(new_slave, bond->dev->dev_addr);
+       }
+       if (swap_slave) {
+@@ -1665,8 +1657,7 @@ int bond_alb_set_mac_address(struct net_
+               alb_swap_mac_addr(bond, swap_slave, bond->curr_active_slave);
+               alb_fasten_mac_swap(bond, swap_slave, bond->curr_active_slave);
+       } else {
+-              alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr,
+-                                     bond->alb_info.rlb_enabled);
++              alb_set_slave_mac_addr(bond->curr_active_slave, bond_dev->dev_addr);
+               read_lock(&bond->lock);
+               alb_send_learning_packets(bond->curr_active_slave, bond_dev->dev_addr);
diff --git a/queue-3.0/l2tp-l2tp_ip-fix-possible-oops-on-packet-receive.patch b/queue-3.0/l2tp-l2tp_ip-fix-possible-oops-on-packet-receive.patch
new file mode 100644 (file)
index 0000000..875a579
--- /dev/null
@@ -0,0 +1,71 @@
+From 3743c4f45ca07a3f16f229d475e1cdd2416e8b83 Mon Sep 17 00:00:00 2001
+From: James Chapman <jchapman@katalix.com>
+Date: Wed, 25 Jan 2012 02:39:05 +0000
+Subject: l2tp: l2tp_ip - fix possible oops on packet receive
+
+
+From: James Chapman <jchapman@katalix.com>
+
+[ Upstream commit 68315801dbf3ab2001679fd2074c9dc5dcf87dfa ]
+
+When a packet is received on an L2TP IP socket (L2TPv3 IP link
+encapsulation), the l2tpip socket's backlog_rcv function calls
+xfrm4_policy_check(). This is not necessary, since it was called
+before the skb was added to the backlog. With CONFIG_NET_NS enabled,
+xfrm4_policy_check() will oops if skb->dev is null, so this trivial
+patch removes the call.
+
+This bug has always been present, but only when CONFIG_NET_NS is
+enabled does it cause problems. Most users are probably using UDP
+encapsulation for L2TP, hence the problem has only recently
+surfaced.
+
+EIP: 0060:[<c12bb62b>] EFLAGS: 00210246 CPU: 0
+EIP is at l2tp_ip_recvmsg+0xd4/0x2a7
+EAX: 00000001 EBX: d77b5180 ECX: 00000000 EDX: 00200246
+ESI: 00000000 EDI: d63cbd30 EBP: d63cbd18 ESP: d63cbcf4
+ DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
+Call Trace:
+ [<c1218568>] sock_common_recvmsg+0x31/0x46
+ [<c1215c92>] __sock_recvmsg_nosec+0x45/0x4d
+ [<c12163a1>] __sock_recvmsg+0x31/0x3b
+ [<c1216828>] sock_recvmsg+0x96/0xab
+ [<c10b2693>] ? might_fault+0x47/0x81
+ [<c10b2693>] ? might_fault+0x47/0x81
+ [<c1167fd0>] ? _copy_from_user+0x31/0x115
+ [<c121e8c8>] ? copy_from_user+0x8/0xa
+ [<c121ebd6>] ? verify_iovec+0x3e/0x78
+ [<c1216604>] __sys_recvmsg+0x10a/0x1aa
+ [<c1216792>] ? sock_recvmsg+0x0/0xab
+ [<c105a99b>] ? __lock_acquire+0xbdf/0xbee
+ [<c12d5a99>] ? do_page_fault+0x193/0x375
+ [<c10d1200>] ? fcheck_files+0x9b/0xca
+ [<c10d1259>] ? fget_light+0x2a/0x9c
+ [<c1216bbb>] sys_recvmsg+0x2b/0x43
+ [<c1218145>] sys_socketcall+0x16d/0x1a5
+ [<c11679f0>] ? trace_hardirqs_on_thunk+0xc/0x10
+ [<c100305f>] sysenter_do_call+0x12/0x38
+Code: c6 05 8c ea a8 c1 01 e8 0c d4 d9 ff 85 f6 74 07 3e ff 86 80 00 00 00 b9 17 b6 2b c1 ba 01 00 00 00 b8 78 ed 48 c1 e8 23 f6 d9 ff <ff> 76 0c 68 28 e3 30 c1 68 2d 44 41 c1 e8 89 57 01 00 83 c4 0c
+
+Signed-off-by: James Chapman <jchapman@katalix.com>
+Acked-by: Eric Dumazet <eric.dumazet@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/l2tp/l2tp_ip.c |    5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/net/l2tp/l2tp_ip.c
++++ b/net/l2tp/l2tp_ip.c
+@@ -393,11 +393,6 @@ static int l2tp_ip_backlog_recv(struct s
+ {
+       int rc;
+-      if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
+-              goto drop;
+-
+-      nf_reset(skb);
+-
+       /* Charge it to the socket, dropping if the queue is full. */
+       rc = sock_queue_rcv_skb(sk, skb);
+       if (rc < 0)
diff --git a/queue-3.0/net-bpf_jit-fix-divide-by-0-generation.patch b/queue-3.0/net-bpf_jit-fix-divide-by-0-generation.patch
new file mode 100644 (file)
index 0000000..30e9dde
--- /dev/null
@@ -0,0 +1,127 @@
+From c8ea21c1241f80a07698dc06fb67f921fe85b57c Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <eric.dumazet@gmail.com>
+Date: Wed, 18 Jan 2012 07:21:42 +0000
+Subject: net: bpf_jit: fix divide by 0 generation
+
+
+From: Eric Dumazet <eric.dumazet@gmail.com>
+
+[ Upstream commit d00a9dd21bdf7908b70866794c8313ee8a5abd5c ]
+
+Several problems fixed in this patch :
+
+1) Target of the conditional jump in case a divide by 0 is performed
+   by a bpf is wrong.
+
+2) Must 'generate' the full function prologue/epilogue at pass=0,
+   or else we can stop too early in pass=1 if the proglen doesnt change.
+   (if the increase of prologue/epilogue equals decrease of all
+    instructions length because some jumps are converted to near jumps)
+
+3) Change the wrong length detection at the end of code generation to
+   issue a more explicit message, no need for a full stack trace.
+
+Reported-by: Phil Oester <kernel@linuxace.com>
+Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ arch/x86/net/bpf_jit_comp.c |   36 ++++++++++++++++++++++--------------
+ 1 file changed, 22 insertions(+), 14 deletions(-)
+
+--- a/arch/x86/net/bpf_jit_comp.c
++++ b/arch/x86/net/bpf_jit_comp.c
+@@ -151,17 +151,18 @@ void bpf_jit_compile(struct sk_filter *f
+       cleanup_addr = proglen; /* epilogue address */
+       for (pass = 0; pass < 10; pass++) {
++              u8 seen_or_pass0 = (pass == 0) ? (SEEN_XREG | SEEN_DATAREF | SEEN_MEM) : seen;
+               /* no prologue/epilogue for trivial filters (RET something) */
+               proglen = 0;
+               prog = temp;
+-              if (seen) {
++              if (seen_or_pass0) {
+                       EMIT4(0x55, 0x48, 0x89, 0xe5); /* push %rbp; mov %rsp,%rbp */
+                       EMIT4(0x48, 0x83, 0xec, 96);    /* subq  $96,%rsp       */
+                       /* note : must save %rbx in case bpf_error is hit */
+-                      if (seen & (SEEN_XREG | SEEN_DATAREF))
++                      if (seen_or_pass0 & (SEEN_XREG | SEEN_DATAREF))
+                               EMIT4(0x48, 0x89, 0x5d, 0xf8); /* mov %rbx, -8(%rbp) */
+-                      if (seen & SEEN_XREG)
++                      if (seen_or_pass0 & SEEN_XREG)
+                               CLEAR_X(); /* make sure we dont leek kernel memory */
+                       /*
+@@ -170,7 +171,7 @@ void bpf_jit_compile(struct sk_filter *f
+                        *  r9 = skb->len - skb->data_len
+                        *  r8 = skb->data
+                        */
+-                      if (seen & SEEN_DATAREF) {
++                      if (seen_or_pass0 & SEEN_DATAREF) {
+                               if (offsetof(struct sk_buff, len) <= 127)
+                                       /* mov    off8(%rdi),%r9d */
+                                       EMIT4(0x44, 0x8b, 0x4f, offsetof(struct sk_buff, len));
+@@ -260,9 +261,14 @@ void bpf_jit_compile(struct sk_filter *f
+                       case BPF_S_ALU_DIV_X: /* A /= X; */
+                               seen |= SEEN_XREG;
+                               EMIT2(0x85, 0xdb);      /* test %ebx,%ebx */
+-                              if (pc_ret0 != -1)
+-                                      EMIT_COND_JMP(X86_JE, addrs[pc_ret0] - (addrs[i] - 4));
+-                              else {
++                              if (pc_ret0 > 0) {
++                                      /* addrs[pc_ret0 - 1] is start address of target
++                                       * (addrs[i] - 4) is the address following this jmp
++                                       * ("xor %edx,%edx; div %ebx" being 4 bytes long)
++                                       */
++                                      EMIT_COND_JMP(X86_JE, addrs[pc_ret0 - 1] -
++                                                              (addrs[i] - 4));
++                              } else {
+                                       EMIT_COND_JMP(X86_JNE, 2 + 5);
+                                       CLEAR_A();
+                                       EMIT1_off32(0xe9, cleanup_addr - (addrs[i] - 4)); /* jmp .+off32 */
+@@ -335,12 +341,12 @@ void bpf_jit_compile(struct sk_filter *f
+                               }
+                               /* fallinto */
+                       case BPF_S_RET_A:
+-                              if (seen) {
++                              if (seen_or_pass0) {
+                                       if (i != flen - 1) {
+                                               EMIT_JMP(cleanup_addr - addrs[i]);
+                                               break;
+                                       }
+-                                      if (seen & SEEN_XREG)
++                                      if (seen_or_pass0 & SEEN_XREG)
+                                               EMIT4(0x48, 0x8b, 0x5d, 0xf8);  /* mov  -8(%rbp),%rbx */
+                                       EMIT1(0xc9);            /* leaveq */
+                               }
+@@ -483,8 +489,9 @@ common_load:                       seen |= SEEN_DATAREF;
+                               goto common_load;
+                       case BPF_S_LDX_B_MSH:
+                               if ((int)K < 0) {
+-                                      if (pc_ret0 != -1) {
+-                                              EMIT_JMP(addrs[pc_ret0] - addrs[i]);
++                                      if (pc_ret0 > 0) {
++                                              /* addrs[pc_ret0 - 1] is the start address */
++                                              EMIT_JMP(addrs[pc_ret0 - 1] - addrs[i]);
+                                               break;
+                                       }
+                                       CLEAR_A();
+@@ -599,13 +606,14 @@ cond_branch:                     f_offset = addrs[i + filt
+                * use it to give the cleanup instruction(s) addr
+                */
+               cleanup_addr = proglen - 1; /* ret */
+-              if (seen)
++              if (seen_or_pass0)
+                       cleanup_addr -= 1; /* leaveq */
+-              if (seen & SEEN_XREG)
++              if (seen_or_pass0 & SEEN_XREG)
+                       cleanup_addr -= 4; /* mov  -8(%rbp),%rbx */
+               if (image) {
+-                      WARN_ON(proglen != oldproglen);
++                      if (proglen != oldproglen)
++                              pr_err("bpb_jit_compile proglen=%u != oldproglen=%u\n", proglen, oldproglen);
+                       break;
+               }
+               if (proglen == oldproglen) {
diff --git a/queue-3.0/net-caif-register-properly-as-a-pernet-subsystem.patch b/queue-3.0/net-caif-register-properly-as-a-pernet-subsystem.patch
new file mode 100644 (file)
index 0000000..957b463
--- /dev/null
@@ -0,0 +1,110 @@
+From 41bb35907b7ae0bf515a895c78650d696214436e Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Thu, 26 Jan 2012 14:04:53 +0000
+Subject: net caif: Register properly as a pernet subsystem.
+
+
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+
+[ Upstream commit 8a8ee9aff6c3077dd9c2c7a77478e8ed362b96c6 ]
+
+caif is a subsystem and as such it needs to register with
+register_pernet_subsys instead of register_pernet_device.
+
+Among other problems using register_pernet_device was resulting in
+net_generic being called before the caif_net structure was allocated.
+Which has been causing net_generic to fail with either BUG_ON's or by
+return NULL pointers.
+
+A more ugly problem that could be caused is packets in flight why the
+subsystem is shutting down.
+
+To remove confusion also remove the cruft cause by inappropriately
+trying to fix this bug.
+
+With the aid of the previous patch I have tested this patch and
+confirmed that using register_pernet_subsys makes the failure go away as
+it should.
+
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Acked-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
+Tested-by: Sasha Levin <levinsasha928@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/caif/caif_dev.c |   11 ++++-------
+ net/caif/cfcnfg.c   |    1 -
+ 2 files changed, 4 insertions(+), 8 deletions(-)
+
+--- a/net/caif/caif_dev.c
++++ b/net/caif/caif_dev.c
+@@ -53,7 +53,6 @@ struct cfcnfg *get_cfcnfg(struct net *ne
+       struct caif_net *caifn;
+       BUG_ON(!net);
+       caifn = net_generic(net, caif_net_id);
+-      BUG_ON(!caifn);
+       return caifn->cfg;
+ }
+ EXPORT_SYMBOL(get_cfcnfg);
+@@ -63,7 +62,6 @@ static struct caif_device_entry_list *ca
+       struct caif_net *caifn;
+       BUG_ON(!net);
+       caifn = net_generic(net, caif_net_id);
+-      BUG_ON(!caifn);
+       return &caifn->caifdevs;
+ }
+@@ -92,7 +90,6 @@ static struct caif_device_entry *caif_de
+       struct caif_device_entry *caifd;
+       caifdevs = caif_device_list(dev_net(dev));
+-      BUG_ON(!caifdevs);
+       caifd = kzalloc(sizeof(*caifd), GFP_ATOMIC);
+       if (!caifd)
+@@ -108,7 +105,7 @@ static struct caif_device_entry *caif_ge
+       struct caif_device_entry_list *caifdevs =
+           caif_device_list(dev_net(dev));
+       struct caif_device_entry *caifd;
+-      BUG_ON(!caifdevs);
++
+       list_for_each_entry_rcu(caifd, &caifdevs->list, list) {
+               if (caifd->netdev == dev)
+                       return caifd;
+@@ -349,7 +346,7 @@ static struct notifier_block caif_device
+ static int caif_init_net(struct net *net)
+ {
+       struct caif_net *caifn = net_generic(net, caif_net_id);
+-      BUG_ON(!caifn);
++
+       INIT_LIST_HEAD(&caifn->caifdevs.list);
+       mutex_init(&caifn->caifdevs.lock);
+@@ -414,7 +411,7 @@ static int __init caif_device_init(void)
+ {
+       int result;
+-      result = register_pernet_device(&caif_net_ops);
++      result = register_pernet_subsys(&caif_net_ops);
+       if (result)
+               return result;
+@@ -427,7 +424,7 @@ static int __init caif_device_init(void)
+ static void __exit caif_device_exit(void)
+ {
+-      unregister_pernet_device(&caif_net_ops);
++      unregister_pernet_subsys(&caif_net_ops);
+       unregister_netdevice_notifier(&caif_device_notifier);
+       dev_remove_pack(&caif_packet_type);
+ }
+--- a/net/caif/cfcnfg.c
++++ b/net/caif/cfcnfg.c
+@@ -313,7 +313,6 @@ int caif_connect_client(struct net *net,
+       int err;
+       struct cfctrl_link_param param;
+       struct cfcnfg *cfg = get_cfcnfg(net);
+-      caif_assert(cfg != NULL);
+       rcu_read_lock();
+       err = caif_connect_req_to_link_param(cfg, conn_req, &param);
diff --git a/queue-3.0/netns-fail-conspicously-if-someone-uses-net_generic-at-an-inappropriate-time.patch b/queue-3.0/netns-fail-conspicously-if-someone-uses-net_generic-at-an-inappropriate-time.patch
new file mode 100644 (file)
index 0000000..a4a6ac9
--- /dev/null
@@ -0,0 +1,39 @@
+From 5a05ab92ada965456811637347939e181cb55adc Mon Sep 17 00:00:00 2001
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+Date: Thu, 26 Jan 2012 14:02:55 +0000
+Subject: netns: Fail conspicously if someone uses net_generic at an inappropriate time.
+
+
+From: "Eric W. Biederman" <ebiederm@xmission.com>
+
+[ Upstream commit 5ee4433efe99b9f39f6eff5052a177bbcfe72cea ]
+
+By definition net_generic should never be called when it can return
+NULL.  Fail conspicously with a BUG_ON to make it clear when people mess
+up that a NULL return should never happen.
+
+Recently there was a bug in the CAIF subsystem where it was registered
+with register_pernet_device instead of register_pernet_subsys.  It was
+erroneously concluded that net_generic could validly return NULL and
+that net_assign_generic was buggy (when it was just inefficient).
+Hopefully this BUG_ON will prevent people to coming to similar erroneous
+conclusions in the futrue.
+
+Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
+Tested-by: Sasha Levin <levinsasha928@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ include/net/netns/generic.h |    1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/include/net/netns/generic.h
++++ b/include/net/netns/generic.h
+@@ -41,6 +41,7 @@ static inline void *net_generic(const st
+       ptr = ng->ptr[id - 1];
+       rcu_read_unlock();
++      BUG_ON(!ptr);
+       return ptr;
+ }
+ #endif
diff --git a/queue-3.0/netns-fix-net_alloc_generic.patch b/queue-3.0/netns-fix-net_alloc_generic.patch
new file mode 100644 (file)
index 0000000..1c08aff
--- /dev/null
@@ -0,0 +1,115 @@
+From c05de4c3c615a6a4fe8c01e8c3aa8fec6a511048 Mon Sep 17 00:00:00 2001
+From: Eric Dumazet <eric.dumazet@gmail.com>
+Date: Thu, 26 Jan 2012 00:41:38 +0000
+Subject: netns: fix net_alloc_generic()
+
+
+From: Eric Dumazet <eric.dumazet@gmail.com>
+
+[ Upstream commit 073862ba5d249c20bd5c49fc6d904ff0e1f6a672 ]
+
+When a new net namespace is created, we should attach to it a "struct
+net_generic" with enough slots (even empty), or we can hit the following
+BUG_ON() :
+
+[  200.752016] kernel BUG at include/net/netns/generic.h:40!
+...
+[  200.752016]  [<ffffffff825c3cea>] ? get_cfcnfg+0x3a/0x180
+[  200.752016]  [<ffffffff821cf0b0>] ? lockdep_rtnl_is_held+0x10/0x20
+[  200.752016]  [<ffffffff825c41be>] caif_device_notify+0x2e/0x530
+[  200.752016]  [<ffffffff810d61b7>] notifier_call_chain+0x67/0x110
+[  200.752016]  [<ffffffff810d67c1>] raw_notifier_call_chain+0x11/0x20
+[  200.752016]  [<ffffffff821bae82>] call_netdevice_notifiers+0x32/0x60
+[  200.752016]  [<ffffffff821c2b26>] register_netdevice+0x196/0x300
+[  200.752016]  [<ffffffff821c2ca9>] register_netdev+0x19/0x30
+[  200.752016]  [<ffffffff81c1c67a>] loopback_net_init+0x4a/0xa0
+[  200.752016]  [<ffffffff821b5e62>] ops_init+0x42/0x180
+[  200.752016]  [<ffffffff821b600b>] setup_net+0x6b/0x100
+[  200.752016]  [<ffffffff821b6466>] copy_net_ns+0x86/0x110
+[  200.752016]  [<ffffffff810d5789>] create_new_namespaces+0xd9/0x190
+
+net_alloc_generic() should take into account the maximum index into the
+ptr array, as a subsystem might use net_generic() anytime.
+
+This also reduces number of reallocations in net_assign_generic()
+
+Reported-by: Sasha Levin <levinsasha928@gmail.com>
+Tested-by: Sasha Levin <levinsasha928@gmail.com>
+Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
+Cc: Sjur Brændeland <sjur.brandeland@stericsson.com>
+Cc: Eric W. Biederman <ebiederm@xmission.com>
+Cc: Pavel Emelyanov <xemul@openvz.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/core/net_namespace.c |   31 ++++++++++++++++---------------
+ 1 file changed, 16 insertions(+), 15 deletions(-)
+
+--- a/net/core/net_namespace.c
++++ b/net/core/net_namespace.c
+@@ -29,6 +29,20 @@ EXPORT_SYMBOL(init_net);
+ #define INITIAL_NET_GEN_PTRS  13 /* +1 for len +2 for rcu_head */
++static unsigned int max_gen_ptrs = INITIAL_NET_GEN_PTRS;
++
++static struct net_generic *net_alloc_generic(void)
++{
++      struct net_generic *ng;
++      size_t generic_size = offsetof(struct net_generic, ptr[max_gen_ptrs]);
++
++      ng = kzalloc(generic_size, GFP_KERNEL);
++      if (ng)
++              ng->len = max_gen_ptrs;
++
++      return ng;
++}
++
+ static int net_assign_generic(struct net *net, int id, void *data)
+ {
+       struct net_generic *ng, *old_ng;
+@@ -42,8 +56,7 @@ static int net_assign_generic(struct net
+       if (old_ng->len >= id)
+               goto assign;
+-      ng = kzalloc(sizeof(struct net_generic) +
+-                      id * sizeof(void *), GFP_KERNEL);
++      ng = net_alloc_generic();
+       if (ng == NULL)
+               return -ENOMEM;
+@@ -58,7 +71,6 @@ static int net_assign_generic(struct net
+        * the old copy for kfree after a grace period.
+        */
+-      ng->len = id;
+       memcpy(&ng->ptr, &old_ng->ptr, old_ng->len * sizeof(void*));
+       rcu_assign_pointer(net->gen, ng);
+@@ -159,18 +171,6 @@ out_undo:
+       goto out;
+ }
+-static struct net_generic *net_alloc_generic(void)
+-{
+-      struct net_generic *ng;
+-      size_t generic_size = sizeof(struct net_generic) +
+-              INITIAL_NET_GEN_PTRS * sizeof(void *);
+-
+-      ng = kzalloc(generic_size, GFP_KERNEL);
+-      if (ng)
+-              ng->len = INITIAL_NET_GEN_PTRS;
+-
+-      return ng;
+-}
+ #ifdef CONFIG_NET_NS
+ static struct kmem_cache *net_cachep;
+@@ -481,6 +481,7 @@ again:
+                       }
+                       return error;
+               }
++              max_gen_ptrs = max_t(unsigned int, max_gen_ptrs, *ops->id);
+       }
+       error = __register_pernet_operations(list, ops);
+       if (error) {
diff --git a/queue-3.0/rds-make-rds_sock_lock-bh-rather-than-irq-safe.patch b/queue-3.0/rds-make-rds_sock_lock-bh-rather-than-irq-safe.patch
new file mode 100644 (file)
index 0000000..ddda14a
--- /dev/null
@@ -0,0 +1,117 @@
+From 035a546266c1300c07d327efc996e844dae390f6 Mon Sep 17 00:00:00 2001
+From: "David S. Miller" <davem@davemloft.net>
+Date: Tue, 24 Jan 2012 17:03:44 -0500
+Subject: rds: Make rds_sock_lock BH rather than IRQ safe.
+
+
+From: "David S. Miller" <davem@davemloft.net>
+
+[ Upstream commit efc3dbc37412c027e363736b4f4c74ee5e8ecffc ]
+
+rds_sock_info() triggers locking warnings because we try to perform a
+local_bh_enable() (via sock_i_ino()) while hardware interrupts are
+disabled (via taking rds_sock_lock).
+
+There is no reason for rds_sock_lock to be a hardware IRQ disabling
+lock, none of these access paths run in hardware interrupt context.
+
+Therefore making it a BH disabling lock is safe and sufficient to
+fix this bug.
+
+Reported-by: Kumar Sanghvi <kumaras@chelsio.com>
+Reported-by: Josh Boyer <jwboyer@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/rds/af_rds.c |   20 ++++++++------------
+ 1 file changed, 8 insertions(+), 12 deletions(-)
+
+--- a/net/rds/af_rds.c
++++ b/net/rds/af_rds.c
+@@ -68,7 +68,6 @@ static int rds_release(struct socket *so
+ {
+       struct sock *sk = sock->sk;
+       struct rds_sock *rs;
+-      unsigned long flags;
+       if (!sk)
+               goto out;
+@@ -94,10 +93,10 @@ static int rds_release(struct socket *so
+       rds_rdma_drop_keys(rs);
+       rds_notify_queue_get(rs, NULL);
+-      spin_lock_irqsave(&rds_sock_lock, flags);
++      spin_lock_bh(&rds_sock_lock);
+       list_del_init(&rs->rs_item);
+       rds_sock_count--;
+-      spin_unlock_irqrestore(&rds_sock_lock, flags);
++      spin_unlock_bh(&rds_sock_lock);
+       rds_trans_put(rs->rs_transport);
+@@ -409,7 +408,6 @@ static const struct proto_ops rds_proto_
+ static int __rds_create(struct socket *sock, struct sock *sk, int protocol)
+ {
+-      unsigned long flags;
+       struct rds_sock *rs;
+       sock_init_data(sock, sk);
+@@ -426,10 +424,10 @@ static int __rds_create(struct socket *s
+       spin_lock_init(&rs->rs_rdma_lock);
+       rs->rs_rdma_keys = RB_ROOT;
+-      spin_lock_irqsave(&rds_sock_lock, flags);
++      spin_lock_bh(&rds_sock_lock);
+       list_add_tail(&rs->rs_item, &rds_sock_list);
+       rds_sock_count++;
+-      spin_unlock_irqrestore(&rds_sock_lock, flags);
++      spin_unlock_bh(&rds_sock_lock);
+       return 0;
+ }
+@@ -471,12 +469,11 @@ static void rds_sock_inc_info(struct soc
+ {
+       struct rds_sock *rs;
+       struct rds_incoming *inc;
+-      unsigned long flags;
+       unsigned int total = 0;
+       len /= sizeof(struct rds_info_message);
+-      spin_lock_irqsave(&rds_sock_lock, flags);
++      spin_lock_bh(&rds_sock_lock);
+       list_for_each_entry(rs, &rds_sock_list, rs_item) {
+               read_lock(&rs->rs_recv_lock);
+@@ -492,7 +489,7 @@ static void rds_sock_inc_info(struct soc
+               read_unlock(&rs->rs_recv_lock);
+       }
+-      spin_unlock_irqrestore(&rds_sock_lock, flags);
++      spin_unlock_bh(&rds_sock_lock);
+       lens->nr = total;
+       lens->each = sizeof(struct rds_info_message);
+@@ -504,11 +501,10 @@ static void rds_sock_info(struct socket
+ {
+       struct rds_info_socket sinfo;
+       struct rds_sock *rs;
+-      unsigned long flags;
+       len /= sizeof(struct rds_info_socket);
+-      spin_lock_irqsave(&rds_sock_lock, flags);
++      spin_lock_bh(&rds_sock_lock);
+       if (len < rds_sock_count)
+               goto out;
+@@ -529,7 +525,7 @@ out:
+       lens->nr = rds_sock_count;
+       lens->each = sizeof(struct rds_info_socket);
+-      spin_unlock_irqrestore(&rds_sock_lock, flags);
++      spin_unlock_bh(&rds_sock_lock);
+ }
+ static void rds_exit(void)
index 15c225b457e2244319fbbbe49f2bbe5c1302752e..31ddf7d7fae026715f328b867c13195d0234d7a1 100644 (file)
@@ -46,3 +46,12 @@ hwmon-sht15-fix-bad-error-code.patch
 usb-cdc-wdm-call-wake_up_all-to-allow-driver-to-shutdown-on-device-removal.patch
 usb-cdc-wdm-better-allocate-a-buffer-that-is-at-least-as-big-as-we-tell-the-usb-core.patch
 usb-cdc-wdm-avoid-hanging-on-interface-with-no-usb_cdc_dmm_type.patch
+netns-fix-net_alloc_generic.patch
+netns-fail-conspicously-if-someone-uses-net_generic-at-an-inappropriate-time.patch
+net-caif-register-properly-as-a-pernet-subsystem.patch
+bonding-fix-enslaving-in-alb-mode-when-link-down.patch
+l2tp-l2tp_ip-fix-possible-oops-on-packet-receive.patch
+net-bpf_jit-fix-divide-by-0-generation.patch
+rds-make-rds_sock_lock-bh-rather-than-irq-safe.patch
+tcp-fix-tcp_trim_head-to-adjust-segment-count-with-skb-mss.patch
+tcp-md5-using-remote-adress-for-md5-lookup-in-rst-packet.patch
diff --git a/queue-3.0/tcp-fix-tcp_trim_head-to-adjust-segment-count-with-skb-mss.patch b/queue-3.0/tcp-fix-tcp_trim_head-to-adjust-segment-count-with-skb-mss.patch
new file mode 100644 (file)
index 0000000..401f39f
--- /dev/null
@@ -0,0 +1,55 @@
+From fa64178e5045e80aec929053ebabea3961025359 Mon Sep 17 00:00:00 2001
+From: Neal Cardwell <ncardwell@google.com>
+Date: Sat, 28 Jan 2012 17:29:46 +0000
+Subject: tcp: fix tcp_trim_head() to adjust segment count with skb MSS
+
+
+From: Neal Cardwell <ncardwell@google.com>
+
+[ Upstream commit 5b35e1e6e9ca651e6b291c96d1106043c9af314a ]
+
+This commit fixes tcp_trim_head() to recalculate the number of
+segments in the skb with the skb's existing MSS, so trimming the head
+causes the skb segment count to be monotonically non-increasing - it
+should stay the same or go down, but not increase.
+
+Previously tcp_trim_head() used the current MSS of the connection. But
+if there was a decrease in MSS between original transmission and ACK
+(e.g. due to PMTUD), this could cause tcp_trim_head() to
+counter-intuitively increase the segment count when trimming bytes off
+the head of an skb. This violated assumptions in tcp_tso_acked() that
+tcp_trim_head() only decreases the packet count, so that packets_acked
+in tcp_tso_acked() could underflow, leading tcp_clean_rtx_queue() to
+pass u32 pkts_acked values as large as 0xffffffff to
+ca_ops->pkts_acked().
+
+As an aside, if tcp_trim_head() had really wanted the skb to reflect
+the current MSS, it should have called tcp_set_skb_tso_segs()
+unconditionally, since a decrease in MSS would mean that a
+single-packet skb should now be sliced into multiple segments.
+
+Signed-off-by: Neal Cardwell <ncardwell@google.com>
+Acked-by: Nandita Dukkipati <nanditad@google.com>
+Acked-by: Ilpo Järvinen <ilpo.jarvinen@helsinki.fi>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/ipv4/tcp_output.c |    6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/net/ipv4/tcp_output.c
++++ b/net/ipv4/tcp_output.c
+@@ -1134,11 +1134,9 @@ int tcp_trim_head(struct sock *sk, struc
+       sk_mem_uncharge(sk, len);
+       sock_set_flag(sk, SOCK_QUEUE_SHRUNK);
+-      /* Any change of skb->len requires recalculation of tso
+-       * factor and mss.
+-       */
++      /* Any change of skb->len requires recalculation of tso factor. */
+       if (tcp_skb_pcount(skb) > 1)
+-              tcp_set_skb_tso_segs(sk, skb, tcp_current_mss(sk));
++              tcp_set_skb_tso_segs(sk, skb, tcp_skb_mss(skb));
+       return 0;
+ }
diff --git a/queue-3.0/tcp-md5-using-remote-adress-for-md5-lookup-in-rst-packet.patch b/queue-3.0/tcp-md5-using-remote-adress-for-md5-lookup-in-rst-packet.patch
new file mode 100644 (file)
index 0000000..a4b1a5e
--- /dev/null
@@ -0,0 +1,44 @@
+From bf18a633817d6dd47c2a608503149ab0649e24f6 Mon Sep 17 00:00:00 2001
+From: shawnlu <shawn.lu@ericsson.com>
+Date: Fri, 20 Jan 2012 12:22:04 +0000
+Subject: tcp: md5: using remote adress for md5 lookup in rst packet
+
+
+From: shawnlu <shawn.lu@ericsson.com>
+
+[ Upstream commit 8a622e71f58ec9f092fc99eacae0e6cf14f6e742 ]
+
+md5 key is added in socket through remote address.
+remote address should be used in finding md5 key when
+sending out reset packet.
+
+Signed-off-by: shawnlu <shawn.lu@ericsson.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ net/ipv4/tcp_ipv4.c |    2 +-
+ net/ipv6/tcp_ipv6.c |    2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+--- a/net/ipv4/tcp_ipv4.c
++++ b/net/ipv4/tcp_ipv4.c
+@@ -630,7 +630,7 @@ static void tcp_v4_send_reset(struct soc
+       arg.iov[0].iov_len  = sizeof(rep.th);
+ #ifdef CONFIG_TCP_MD5SIG
+-      key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->daddr) : NULL;
++      key = sk ? tcp_v4_md5_do_lookup(sk, ip_hdr(skb)->saddr) : NULL;
+       if (key) {
+               rep.opt[0] = htonl((TCPOPT_NOP << 24) |
+                                  (TCPOPT_NOP << 16) |
+--- a/net/ipv6/tcp_ipv6.c
++++ b/net/ipv6/tcp_ipv6.c
+@@ -1096,7 +1096,7 @@ static void tcp_v6_send_reset(struct soc
+ #ifdef CONFIG_TCP_MD5SIG
+       if (sk)
+-              key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr);
++              key = tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->saddr);
+ #endif
+       if (th->ack)