From: Greg Kroah-Hartman Date: Tue, 31 Jan 2012 19:46:27 +0000 (-0800) Subject: 3.0-stable patches X-Git-Tag: v3.0.19~5 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e803a251e97241b006a8433c92372e88c8c2dd81;p=thirdparty%2Fkernel%2Fstable-queue.git 3.0-stable patches 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 --- 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 index 00000000000..949410694af --- /dev/null +++ b/queue-3.0/bonding-fix-enslaving-in-alb-mode-when-link-down.patch @@ -0,0 +1,114 @@ +From fc9c8ea2fbebcb07185e7a46a0739b7b5f6b6f48 Mon Sep 17 00:00:00 2001 +From: Jiri Bohac +Date: Wed, 18 Jan 2012 12:24:54 +0000 +Subject: bonding: fix enslaving in alb mode when link down + + +From: Jiri Bohac + +[ 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 +Signed-off-by: Jiri Bohac +Signed-off-by: Jay Vosburgh +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..875a579faa7 --- /dev/null +++ b/queue-3.0/l2tp-l2tp_ip-fix-possible-oops-on-packet-receive.patch @@ -0,0 +1,71 @@ +From 3743c4f45ca07a3f16f229d475e1cdd2416e8b83 Mon Sep 17 00:00:00 2001 +From: James Chapman +Date: Wed, 25 Jan 2012 02:39:05 +0000 +Subject: l2tp: l2tp_ip - fix possible oops on packet receive + + +From: James Chapman + +[ 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:[] 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: + [] sock_common_recvmsg+0x31/0x46 + [] __sock_recvmsg_nosec+0x45/0x4d + [] __sock_recvmsg+0x31/0x3b + [] sock_recvmsg+0x96/0xab + [] ? might_fault+0x47/0x81 + [] ? might_fault+0x47/0x81 + [] ? _copy_from_user+0x31/0x115 + [] ? copy_from_user+0x8/0xa + [] ? verify_iovec+0x3e/0x78 + [] __sys_recvmsg+0x10a/0x1aa + [] ? sock_recvmsg+0x0/0xab + [] ? __lock_acquire+0xbdf/0xbee + [] ? do_page_fault+0x193/0x375 + [] ? fcheck_files+0x9b/0xca + [] ? fget_light+0x2a/0x9c + [] sys_recvmsg+0x2b/0x43 + [] sys_socketcall+0x16d/0x1a5 + [] ? trace_hardirqs_on_thunk+0xc/0x10 + [] 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 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 +Acked-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..30e9dde25b7 --- /dev/null +++ b/queue-3.0/net-bpf_jit-fix-divide-by-0-generation.patch @@ -0,0 +1,127 @@ +From c8ea21c1241f80a07698dc06fb67f921fe85b57c Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Wed, 18 Jan 2012 07:21:42 +0000 +Subject: net: bpf_jit: fix divide by 0 generation + + +From: Eric Dumazet + +[ 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 +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..957b46341e2 --- /dev/null +++ b/queue-3.0/net-caif-register-properly-as-a-pernet-subsystem.patch @@ -0,0 +1,110 @@ +From 41bb35907b7ae0bf515a895c78650d696214436e Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +Date: Thu, 26 Jan 2012 14:04:53 +0000 +Subject: net caif: Register properly as a pernet subsystem. + + +From: "Eric W. Biederman" + +[ 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 +Acked-by: Sjur Brændeland +Tested-by: Sasha Levin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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, ¶m); 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 index 00000000000..a4a6ac935ab --- /dev/null +++ b/queue-3.0/netns-fail-conspicously-if-someone-uses-net_generic-at-an-inappropriate-time.patch @@ -0,0 +1,39 @@ +From 5a05ab92ada965456811637347939e181cb55adc Mon Sep 17 00:00:00 2001 +From: "Eric W. Biederman" +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" + +[ 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 +Tested-by: Sasha Levin +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..1c08aff942f --- /dev/null +++ b/queue-3.0/netns-fix-net_alloc_generic.patch @@ -0,0 +1,115 @@ +From c05de4c3c615a6a4fe8c01e8c3aa8fec6a511048 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Thu, 26 Jan 2012 00:41:38 +0000 +Subject: netns: fix net_alloc_generic() + + +From: Eric Dumazet + +[ 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] [] ? get_cfcnfg+0x3a/0x180 +[ 200.752016] [] ? lockdep_rtnl_is_held+0x10/0x20 +[ 200.752016] [] caif_device_notify+0x2e/0x530 +[ 200.752016] [] notifier_call_chain+0x67/0x110 +[ 200.752016] [] raw_notifier_call_chain+0x11/0x20 +[ 200.752016] [] call_netdevice_notifiers+0x32/0x60 +[ 200.752016] [] register_netdevice+0x196/0x300 +[ 200.752016] [] register_netdev+0x19/0x30 +[ 200.752016] [] loopback_net_init+0x4a/0xa0 +[ 200.752016] [] ops_init+0x42/0x180 +[ 200.752016] [] setup_net+0x6b/0x100 +[ 200.752016] [] copy_net_ns+0x86/0x110 +[ 200.752016] [] 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 +Tested-by: Sasha Levin +Signed-off-by: Eric Dumazet +Cc: Sjur Brændeland +Cc: Eric W. Biederman +Cc: Pavel Emelyanov +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..ddda14a1fb8 --- /dev/null +++ b/queue-3.0/rds-make-rds_sock_lock-bh-rather-than-irq-safe.patch @@ -0,0 +1,117 @@ +From 035a546266c1300c07d327efc996e844dae390f6 Mon Sep 17 00:00:00 2001 +From: "David S. Miller" +Date: Tue, 24 Jan 2012 17:03:44 -0500 +Subject: rds: Make rds_sock_lock BH rather than IRQ safe. + + +From: "David S. Miller" + +[ 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 +Reported-by: Josh Boyer +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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) diff --git a/queue-3.0/series b/queue-3.0/series index 15c225b457e..31ddf7d7fae 100644 --- a/queue-3.0/series +++ b/queue-3.0/series @@ -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 index 00000000000..401f39f62f5 --- /dev/null +++ b/queue-3.0/tcp-fix-tcp_trim_head-to-adjust-segment-count-with-skb-mss.patch @@ -0,0 +1,55 @@ +From fa64178e5045e80aec929053ebabea3961025359 Mon Sep 17 00:00:00 2001 +From: Neal Cardwell +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 + +[ 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 +Acked-by: Nandita Dukkipati +Acked-by: Ilpo Järvinen +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 00000000000..a4b1a5e8dbf --- /dev/null +++ b/queue-3.0/tcp-md5-using-remote-adress-for-md5-lookup-in-rst-packet.patch @@ -0,0 +1,44 @@ +From bf18a633817d6dd47c2a608503149ab0649e24f6 Mon Sep 17 00:00:00 2001 +From: shawnlu +Date: Fri, 20 Jan 2012 12:22:04 +0000 +Subject: tcp: md5: using remote adress for md5 lookup in rst packet + + +From: shawnlu + +[ 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 +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + 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)