From: Greg Kroah-Hartman Date: Tue, 24 Mar 2015 10:04:31 +0000 (+0100) Subject: 3.10-stable patches X-Git-Tag: v3.19.3~25 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6f64316c509b5adc802ec404d06c4e8b89173de0;p=thirdparty%2Fkernel%2Fstable-queue.git 3.10-stable patches added patches: caif-fix-msg_oob-test-in-caif_seqpkt_recvmsg.patch inet_diag-fix-possible-overflow-in-inet_diag_dump_one_icsk.patch ipv6-fix-backtracking-for-throw-routes.patch net-compat-update-get_compat_msghdr-to-match-copy_msghdr_from_user-behaviour.patch net-sysctl_net_core-check-sndbuf-and-rcvbuf-for-min-length.patch rds-avoid-potential-stack-overflow.patch revert-net-cx82310_eth-use-common-match-macro.patch rxrpc-bogus-msg_peek-test-in-rxrpc_recvmsg.patch tcp-fix-tcp-fin-memory-accounting.patch tcp-make-connect-mem-charging-friendly.patch --- diff --git a/queue-3.10/caif-fix-msg_oob-test-in-caif_seqpkt_recvmsg.patch b/queue-3.10/caif-fix-msg_oob-test-in-caif_seqpkt_recvmsg.patch new file mode 100644 index 00000000000..6f7143b5f2f --- /dev/null +++ b/queue-3.10/caif-fix-msg_oob-test-in-caif_seqpkt_recvmsg.patch @@ -0,0 +1,34 @@ +From foo@baz Tue Mar 24 11:01:55 CET 2015 +From: Al Viro +Date: Sat, 14 Mar 2015 05:22:21 +0000 +Subject: caif: fix MSG_OOB test in caif_seqpkt_recvmsg() + +From: Al Viro + +[ Upstream commit 3eeff778e00c956875c70b145c52638c313dfb23 ] + +It should be checking flags, not msg->msg_flags. It's ->sendmsg() +instances that need to look for that in ->msg_flags, ->recvmsg() ones +(including the other ->recvmsg() instance in that file, as well as +unix_dgram_recvmsg() this one claims to be imitating) check in flags. +Braino had been introduced in commit dcda13 ("caif: Bugfix - use MSG_TRUNC +in receive") back in 2010, so it goes quite a while back. + +Signed-off-by: Al Viro +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/caif/caif_socket.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/caif/caif_socket.c ++++ b/net/caif/caif_socket.c +@@ -283,7 +283,7 @@ static int caif_seqpkt_recvmsg(struct ki + int copylen; + + ret = -EOPNOTSUPP; +- if (m->msg_flags&MSG_OOB) ++ if (flags & MSG_OOB) + goto read_error; + + skb = skb_recv_datagram(sk, flags, 0 , &ret); diff --git a/queue-3.10/inet_diag-fix-possible-overflow-in-inet_diag_dump_one_icsk.patch b/queue-3.10/inet_diag-fix-possible-overflow-in-inet_diag_dump_one_icsk.patch new file mode 100644 index 00000000000..a7a453fd69d --- /dev/null +++ b/queue-3.10/inet_diag-fix-possible-overflow-in-inet_diag_dump_one_icsk.patch @@ -0,0 +1,58 @@ +From foo@baz Tue Mar 24 11:01:55 CET 2015 +From: Eric Dumazet +Date: Fri, 13 Mar 2015 09:49:59 -0700 +Subject: inet_diag: fix possible overflow in inet_diag_dump_one_icsk() + +From: Eric Dumazet + +[ Upstream commit c8e2c80d7ec00d020320f905822bf49c5ad85250 ] + +inet_diag_dump_one_icsk() allocates too small skb. + +Add inet_sk_attr_size() helper right before inet_sk_diag_fill() +so that it can be updated if/when new attributes are added. + +iproute2/ss currently does not use this dump_one() interface, +this might explain nobody noticed this problem yet. + +Signed-off-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/inet_diag.c | 18 +++++++++++++++--- + 1 file changed, 15 insertions(+), 3 deletions(-) + +--- a/net/ipv4/inet_diag.c ++++ b/net/ipv4/inet_diag.c +@@ -71,6 +71,20 @@ static inline void inet_diag_unlock_hand + mutex_unlock(&inet_diag_table_mutex); + } + ++static size_t inet_sk_attr_size(void) ++{ ++ return nla_total_size(sizeof(struct tcp_info)) ++ + nla_total_size(1) /* INET_DIAG_SHUTDOWN */ ++ + nla_total_size(1) /* INET_DIAG_TOS */ ++ + nla_total_size(1) /* INET_DIAG_TCLASS */ ++ + nla_total_size(sizeof(struct inet_diag_meminfo)) ++ + nla_total_size(sizeof(struct inet_diag_msg)) ++ + nla_total_size(SK_MEMINFO_VARS * sizeof(u32)) ++ + nla_total_size(TCP_CA_NAME_MAX) ++ + nla_total_size(sizeof(struct tcpvegas_info)) ++ + 64; ++} ++ + int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, + struct sk_buff *skb, struct inet_diag_req_v2 *req, + struct user_namespace *user_ns, +@@ -326,9 +340,7 @@ int inet_diag_dump_one_icsk(struct inet_ + if (err) + goto out; + +- rep = nlmsg_new(sizeof(struct inet_diag_msg) + +- sizeof(struct inet_diag_meminfo) + +- sizeof(struct tcp_info) + 64, GFP_KERNEL); ++ rep = nlmsg_new(inet_sk_attr_size(), GFP_KERNEL); + if (!rep) { + err = -ENOMEM; + goto out; diff --git a/queue-3.10/ipv6-fix-backtracking-for-throw-routes.patch b/queue-3.10/ipv6-fix-backtracking-for-throw-routes.patch new file mode 100644 index 00000000000..90683c1fda5 --- /dev/null +++ b/queue-3.10/ipv6-fix-backtracking-for-throw-routes.patch @@ -0,0 +1,37 @@ +From foo@baz Tue Mar 24 11:01:55 CET 2015 +From: Steven Barth +Date: Thu, 19 Mar 2015 16:16:04 +0100 +Subject: ipv6: fix backtracking for throw routes + +From: Steven Barth + +[ Upstream commit 73ba57bfae4a1914f6a6dac71e3168dd900e00af ] + +for throw routes to trigger evaluation of other policy rules +EAGAIN needs to be propagated up to fib_rules_lookup +similar to how its done for IPv4 + +A simple testcase for verification is: + +ip -6 rule add lookup 33333 priority 33333 +ip -6 route add throw 2001:db8::1 +ip -6 route add 2001:db8::1 via fe80::1 dev wlan0 table 33333 +ip route get 2001:db8::1 + +Signed-off-by: Steven Barth +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv6/fib6_rules.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/net/ipv6/fib6_rules.c ++++ b/net/ipv6/fib6_rules.c +@@ -97,6 +97,7 @@ static int fib6_rule_action(struct fib_r + goto again; + flp6->saddr = saddr; + } ++ err = rt->dst.error; + goto out; + } + again: diff --git a/queue-3.10/net-compat-update-get_compat_msghdr-to-match-copy_msghdr_from_user-behaviour.patch b/queue-3.10/net-compat-update-get_compat_msghdr-to-match-copy_msghdr_from_user-behaviour.patch new file mode 100644 index 00000000000..374de23f397 --- /dev/null +++ b/queue-3.10/net-compat-update-get_compat_msghdr-to-match-copy_msghdr_from_user-behaviour.patch @@ -0,0 +1,50 @@ +From foo@baz Tue Mar 24 11:01:55 CET 2015 +From: Catalin Marinas +Date: Fri, 20 Mar 2015 16:48:13 +0000 +Subject: net: compat: Update get_compat_msghdr() to match copy_msghdr_from_user() behaviour + +From: Catalin Marinas + +[ Upstream commit 91edd096e224941131f896b86838b1e59553696a ] + +Commit db31c55a6fb2 (net: clamp ->msg_namelen instead of returning an +error) introduced the clamping of msg_namelen when the unsigned value +was larger than sizeof(struct sockaddr_storage). This caused a +msg_namelen of -1 to be valid. The native code was subsequently fixed by +commit dbb490b96584 (net: socket: error on a negative msg_namelen). + +In addition, the native code sets msg_namelen to 0 when msg_name is +NULL. This was done in commit (6a2a2b3ae075 net:socket: set msg_namelen +to 0 if msg_name is passed as NULL in msghdr struct from userland) and +subsequently updated by 08adb7dabd48 (fold verify_iovec() into +copy_msghdr_from_user()). + +This patch brings the get_compat_msghdr() in line with +copy_msghdr_from_user(). + +Fixes: db31c55a6fb2 (net: clamp ->msg_namelen instead of returning an error) +Cc: David S. Miller +Cc: Dan Carpenter +Signed-off-by: Catalin Marinas +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/compat.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +--- a/net/compat.c ++++ b/net/compat.c +@@ -71,6 +71,13 @@ int get_compat_msghdr(struct msghdr *kms + __get_user(kmsg->msg_controllen, &umsg->msg_controllen) || + __get_user(kmsg->msg_flags, &umsg->msg_flags)) + return -EFAULT; ++ ++ if (!tmp1) ++ kmsg->msg_namelen = 0; ++ ++ if (kmsg->msg_namelen < 0) ++ return -EINVAL; ++ + if (kmsg->msg_namelen > sizeof(struct sockaddr_storage)) + kmsg->msg_namelen = sizeof(struct sockaddr_storage); + kmsg->msg_name = compat_ptr(tmp1); diff --git a/queue-3.10/net-sysctl_net_core-check-sndbuf-and-rcvbuf-for-min-length.patch b/queue-3.10/net-sysctl_net_core-check-sndbuf-and-rcvbuf-for-min-length.patch new file mode 100644 index 00000000000..6643c0a467b --- /dev/null +++ b/queue-3.10/net-sysctl_net_core-check-sndbuf-and-rcvbuf-for-min-length.patch @@ -0,0 +1,116 @@ +From foo@baz Tue Mar 24 11:01:55 CET 2015 +From: Alexey Kodanev +Date: Wed, 11 Mar 2015 14:29:17 +0300 +Subject: net: sysctl_net_core: check SNDBUF and RCVBUF for min length + +From: Alexey Kodanev + +[ Upstream commit b1cb59cf2efe7971d3d72a7b963d09a512d994c9 ] + +sysctl has sysctl.net.core.rmem_*/wmem_* parameters which can be +set to incorrect values. Given that 'struct sk_buff' allocates from +rcvbuf, incorrectly set buffer length could result to memory +allocation failures. For example, set them as follows: + + # sysctl net.core.rmem_default=64 + net.core.wmem_default = 64 + # sysctl net.core.wmem_default=64 + net.core.wmem_default = 64 + # ping localhost -s 1024 -i 0 > /dev/null + +This could result to the following failure: + +skbuff: skb_over_panic: text:ffffffff81628db4 len:-32 put:-32 +head:ffff88003a1cc200 data:ffff88003a1cc200 tail:0xffffffe0 end:0xc0 dev: +kernel BUG at net/core/skbuff.c:102! +invalid opcode: 0000 [#1] SMP +... +task: ffff88003b7f5550 ti: ffff88003ae88000 task.ti: ffff88003ae88000 +RIP: 0010:[] [] skb_put+0xa1/0xb0 +RSP: 0018:ffff88003ae8bc68 EFLAGS: 00010296 +RAX: 000000000000008d RBX: 00000000ffffffe0 RCX: 0000000000000000 +RDX: ffff88003fdcf598 RSI: ffff88003fdcd9c8 RDI: ffff88003fdcd9c8 +RBP: ffff88003ae8bc88 R08: 0000000000000001 R09: 0000000000000000 +R10: 0000000000000001 R11: 00000000000002b2 R12: 0000000000000000 +R13: 0000000000000000 R14: ffff88003d3f7300 R15: ffff88000012a900 +FS: 00007fa0e2b4a840(0000) GS:ffff88003fc00000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 0000000000d0f7e0 CR3: 000000003b8fb000 CR4: 00000000000006f0 +Stack: + ffff88003a1cc200 00000000ffffffe0 00000000000000c0 ffffffff818cab1d + ffff88003ae8bd68 ffffffff81628db4 ffff88003ae8bd48 ffff88003b7f5550 + ffff880031a09408 ffff88003b7f5550 ffff88000012aa48 ffff88000012ab00 +Call Trace: + [] unix_stream_sendmsg+0x2c4/0x470 + [] sock_write_iter+0x146/0x160 + [] new_sync_write+0x92/0xd0 + [] vfs_write+0xd6/0x180 + [] SyS_write+0x59/0xd0 + [] system_call_fastpath+0x12/0x17 +Code: 00 00 48 89 44 24 10 8b 87 c8 00 00 00 48 89 44 24 08 48 8b 87 d8 00 + 00 00 48 c7 c7 30 db 91 81 48 89 04 24 31 c0 e8 4f a8 0e 00 <0f> 0b + eb fe 66 66 2e 0f 1f 84 00 00 00 00 00 55 48 89 e5 48 83 +RIP [] skb_put+0xa1/0xb0 +RSP +Kernel panic - not syncing: Fatal exception + +Moreover, the possible minimum is 1, so we can get another kernel panic: +... +BUG: unable to handle kernel paging request at ffff88013caee5c0 +IP: [] __alloc_skb+0x12f/0x1f0 +... + +Signed-off-by: Alexey Kodanev +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/core/sysctl_net_core.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/net/core/sysctl_net_core.c ++++ b/net/core/sysctl_net_core.c +@@ -23,6 +23,8 @@ + static int zero = 0; + static int one = 1; + static int ushort_max = USHRT_MAX; ++static int min_sndbuf = SOCK_MIN_SNDBUF; ++static int min_rcvbuf = SOCK_MIN_RCVBUF; + + #ifdef CONFIG_RPS + static int rps_sock_flow_sysctl(ctl_table *table, int write, +@@ -97,7 +99,7 @@ static struct ctl_table net_core_table[] + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_sndbuf, + }, + { + .procname = "rmem_max", +@@ -105,7 +107,7 @@ static struct ctl_table net_core_table[] + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_rcvbuf, + }, + { + .procname = "wmem_default", +@@ -113,7 +115,7 @@ static struct ctl_table net_core_table[] + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_sndbuf, + }, + { + .procname = "rmem_default", +@@ -121,7 +123,7 @@ static struct ctl_table net_core_table[] + .maxlen = sizeof(int), + .mode = 0644, + .proc_handler = proc_dointvec_minmax, +- .extra1 = &one, ++ .extra1 = &min_rcvbuf, + }, + { + .procname = "dev_weight", diff --git a/queue-3.10/rds-avoid-potential-stack-overflow.patch b/queue-3.10/rds-avoid-potential-stack-overflow.patch new file mode 100644 index 00000000000..39e45fb3659 --- /dev/null +++ b/queue-3.10/rds-avoid-potential-stack-overflow.patch @@ -0,0 +1,116 @@ +From foo@baz Tue Mar 24 11:01:55 CET 2015 +From: Arnd Bergmann +Date: Wed, 11 Mar 2015 22:46:59 +0100 +Subject: rds: avoid potential stack overflow + +From: Arnd Bergmann + +[ Upstream commit f862e07cf95d5b62a5fc5e981dd7d0dbaf33a501 ] + +The rds_iw_update_cm_id function stores a large 'struct rds_sock' object +on the stack in order to pass a pair of addresses. This happens to just +fit withint the 1024 byte stack size warning limit on x86, but just +exceed that limit on ARM, which gives us this warning: + +net/rds/iw_rdma.c:200:1: warning: the frame size of 1056 bytes is larger than 1024 bytes [-Wframe-larger-than=] + +As the use of this large variable is basically bogus, we can rearrange +the code to not do that. Instead of passing an rds socket into +rds_iw_get_device, we now just pass the two addresses that we have +available in rds_iw_update_cm_id, and we change rds_iw_get_mr accordingly, +to create two address structures on the stack there. + +Signed-off-by: Arnd Bergmann +Acked-by: Sowmini Varadhan +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/rds/iw_rdma.c | 40 ++++++++++++++++++++++------------------ + 1 file changed, 22 insertions(+), 18 deletions(-) + +--- a/net/rds/iw_rdma.c ++++ b/net/rds/iw_rdma.c +@@ -88,7 +88,9 @@ static unsigned int rds_iw_unmap_fastreg + int *unpinned); + static void rds_iw_destroy_fastreg(struct rds_iw_mr_pool *pool, struct rds_iw_mr *ibmr); + +-static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwdev, struct rdma_cm_id **cm_id) ++static int rds_iw_get_device(struct sockaddr_in *src, struct sockaddr_in *dst, ++ struct rds_iw_device **rds_iwdev, ++ struct rdma_cm_id **cm_id) + { + struct rds_iw_device *iwdev; + struct rds_iw_cm_id *i_cm_id; +@@ -112,15 +114,15 @@ static int rds_iw_get_device(struct rds_ + src_addr->sin_port, + dst_addr->sin_addr.s_addr, + dst_addr->sin_port, +- rs->rs_bound_addr, +- rs->rs_bound_port, +- rs->rs_conn_addr, +- rs->rs_conn_port); ++ src->sin_addr.s_addr, ++ src->sin_port, ++ dst->sin_addr.s_addr, ++ dst->sin_port); + #ifdef WORKING_TUPLE_DETECTION +- if (src_addr->sin_addr.s_addr == rs->rs_bound_addr && +- src_addr->sin_port == rs->rs_bound_port && +- dst_addr->sin_addr.s_addr == rs->rs_conn_addr && +- dst_addr->sin_port == rs->rs_conn_port) { ++ if (src_addr->sin_addr.s_addr == src->sin_addr.s_addr && ++ src_addr->sin_port == src->sin_port && ++ dst_addr->sin_addr.s_addr == dst->sin_addr.s_addr && ++ dst_addr->sin_port == dst->sin_port) { + #else + /* FIXME - needs to compare the local and remote + * ipaddr/port tuple, but the ipaddr is the only +@@ -128,7 +130,7 @@ static int rds_iw_get_device(struct rds_ + * zero'ed. It doesn't appear to be properly populated + * during connection setup... + */ +- if (src_addr->sin_addr.s_addr == rs->rs_bound_addr) { ++ if (src_addr->sin_addr.s_addr == src->sin_addr.s_addr) { + #endif + spin_unlock_irq(&iwdev->spinlock); + *rds_iwdev = iwdev; +@@ -180,19 +182,13 @@ int rds_iw_update_cm_id(struct rds_iw_de + { + struct sockaddr_in *src_addr, *dst_addr; + struct rds_iw_device *rds_iwdev_old; +- struct rds_sock rs; + struct rdma_cm_id *pcm_id; + int rc; + + src_addr = (struct sockaddr_in *)&cm_id->route.addr.src_addr; + dst_addr = (struct sockaddr_in *)&cm_id->route.addr.dst_addr; + +- rs.rs_bound_addr = src_addr->sin_addr.s_addr; +- rs.rs_bound_port = src_addr->sin_port; +- rs.rs_conn_addr = dst_addr->sin_addr.s_addr; +- rs.rs_conn_port = dst_addr->sin_port; +- +- rc = rds_iw_get_device(&rs, &rds_iwdev_old, &pcm_id); ++ rc = rds_iw_get_device(src_addr, dst_addr, &rds_iwdev_old, &pcm_id); + if (rc) + rds_iw_remove_cm_id(rds_iwdev, cm_id); + +@@ -598,9 +594,17 @@ void *rds_iw_get_mr(struct scatterlist * + struct rds_iw_device *rds_iwdev; + struct rds_iw_mr *ibmr = NULL; + struct rdma_cm_id *cm_id; ++ struct sockaddr_in src = { ++ .sin_addr.s_addr = rs->rs_bound_addr, ++ .sin_port = rs->rs_bound_port, ++ }; ++ struct sockaddr_in dst = { ++ .sin_addr.s_addr = rs->rs_conn_addr, ++ .sin_port = rs->rs_conn_port, ++ }; + int ret; + +- ret = rds_iw_get_device(rs, &rds_iwdev, &cm_id); ++ ret = rds_iw_get_device(&src, &dst, &rds_iwdev, &cm_id); + if (ret || !cm_id) { + ret = -ENODEV; + goto out; diff --git a/queue-3.10/revert-net-cx82310_eth-use-common-match-macro.patch b/queue-3.10/revert-net-cx82310_eth-use-common-match-macro.patch new file mode 100644 index 00000000000..8471996f55b --- /dev/null +++ b/queue-3.10/revert-net-cx82310_eth-use-common-match-macro.patch @@ -0,0 +1,47 @@ +From foo@baz Tue Mar 24 11:01:55 CET 2015 +From: Ondrej Zary +Date: Wed, 18 Mar 2015 23:01:01 +0100 +Subject: Revert "net: cx82310_eth: use common match macro" + +From: Ondrej Zary + +[ Upstream commit 8d006e0105978619fb472e150c88b0d49337fe2b ] + +This reverts commit 11ad714b98f6d9ca0067568442afe3e70eb94845 because +it breaks cx82310_eth. + +The custom USB_DEVICE_CLASS macro matches +bDeviceClass, bDeviceSubClass and bDeviceProtocol +but the common USB_DEVICE_AND_INTERFACE_INFO matches +bInterfaceClass, bInterfaceSubClass and bInterfaceProtocol instead, which are +not specified. + +Signed-off-by: Ondrej Zary +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/usb/cx82310_eth.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +--- a/drivers/net/usb/cx82310_eth.c ++++ b/drivers/net/usb/cx82310_eth.c +@@ -302,9 +302,18 @@ static const struct driver_info cx82310_ + .tx_fixup = cx82310_tx_fixup, + }; + ++#define USB_DEVICE_CLASS(vend, prod, cl, sc, pr) \ ++ .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \ ++ USB_DEVICE_ID_MATCH_DEV_INFO, \ ++ .idVendor = (vend), \ ++ .idProduct = (prod), \ ++ .bDeviceClass = (cl), \ ++ .bDeviceSubClass = (sc), \ ++ .bDeviceProtocol = (pr) ++ + static const struct usb_device_id products[] = { + { +- USB_DEVICE_AND_INTERFACE_INFO(0x0572, 0xcb01, 0xff, 0, 0), ++ USB_DEVICE_CLASS(0x0572, 0xcb01, 0xff, 0, 0), + .driver_info = (unsigned long) &cx82310_info + }, + { }, diff --git a/queue-3.10/rxrpc-bogus-msg_peek-test-in-rxrpc_recvmsg.patch b/queue-3.10/rxrpc-bogus-msg_peek-test-in-rxrpc_recvmsg.patch new file mode 100644 index 00000000000..5dde5f4cfea --- /dev/null +++ b/queue-3.10/rxrpc-bogus-msg_peek-test-in-rxrpc_recvmsg.patch @@ -0,0 +1,39 @@ +From foo@baz Tue Mar 24 11:01:55 CET 2015 +From: Al Viro +Date: Sat, 14 Mar 2015 05:34:56 +0000 +Subject: rxrpc: bogus MSG_PEEK test in rxrpc_recvmsg() + +From: Al Viro + +[ Upstream commit 7d985ed1dca5c90535d67ce92ef6ca520302340a ] + +[I would really like an ACK on that one from dhowells; it appears to be +quite straightforward, but...] + +MSG_PEEK isn't passed to ->recvmsg() via msg->msg_flags; as the matter of +fact, neither the kernel users of rxrpc, nor the syscalls ever set that bit +in there. It gets passed via flags; in fact, another such check in the same +function is done correctly - as flags & MSG_PEEK. + +It had been that way (effectively disabled) for 8 years, though, so the patch +needs beating up - that case had never been tested. If it is correct, it's +-stable fodder. + +Signed-off-by: Al Viro +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/rxrpc/ar-recvmsg.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/rxrpc/ar-recvmsg.c ++++ b/net/rxrpc/ar-recvmsg.c +@@ -87,7 +87,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, st + if (!skb) { + /* nothing remains on the queue */ + if (copied && +- (msg->msg_flags & MSG_PEEK || timeo == 0)) ++ (flags & MSG_PEEK || timeo == 0)) + goto out; + + /* wait for a message to turn up */ diff --git a/queue-3.10/series b/queue-3.10/series index 7c1c80e5213..61b3831c4b6 100644 --- a/queue-3.10/series +++ b/queue-3.10/series @@ -4,3 +4,13 @@ sparc-perf-remove-redundant-perf_pmu_-en-dis-able-calls.patch sparc-perf-make-counting-mode-actually-work.patch sparc-touch-nmi-watchdog-when-walking-cpus-and-calling-printk.patch sparc64-fix-several-bugs-in-memmove.patch +net-sysctl_net_core-check-sndbuf-and-rcvbuf-for-min-length.patch +rds-avoid-potential-stack-overflow.patch +inet_diag-fix-possible-overflow-in-inet_diag_dump_one_icsk.patch +caif-fix-msg_oob-test-in-caif_seqpkt_recvmsg.patch +rxrpc-bogus-msg_peek-test-in-rxrpc_recvmsg.patch +revert-net-cx82310_eth-use-common-match-macro.patch +ipv6-fix-backtracking-for-throw-routes.patch +tcp-fix-tcp-fin-memory-accounting.patch +net-compat-update-get_compat_msghdr-to-match-copy_msghdr_from_user-behaviour.patch +tcp-make-connect-mem-charging-friendly.patch diff --git a/queue-3.10/tcp-fix-tcp-fin-memory-accounting.patch b/queue-3.10/tcp-fix-tcp-fin-memory-accounting.patch new file mode 100644 index 00000000000..a9f84879d1c --- /dev/null +++ b/queue-3.10/tcp-fix-tcp-fin-memory-accounting.patch @@ -0,0 +1,42 @@ +From foo@baz Tue Mar 24 11:01:55 CET 2015 +From: Josh Hunt +Date: Thu, 19 Mar 2015 19:19:30 -0400 +Subject: tcp: fix tcp fin memory accounting + +From: Josh Hunt + +[ Upstream commit d22e1537181188e5dc8cbc51451832625035bdc2 ] + +tcp_send_fin() does not account for the memory it allocates properly, so +sk_forward_alloc can be negative in cases where we've sent a FIN: + +ss example output (ss -amn | grep -B1 f4294): +tcp FIN-WAIT-1 0 1 192.168.0.1:45520 192.0.2.1:8080 + skmem:(r0,rb87380,t0,tb87380,f4294966016,w1280,o0,bl0) +Acked-by: Eric Dumazet + +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp_output.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -2593,15 +2593,11 @@ void tcp_send_fin(struct sock *sk) + } else { + /* Socket is locked, keep trying until memory is available. */ + for (;;) { +- skb = alloc_skb_fclone(MAX_TCP_HEADER, +- sk->sk_allocation); ++ skb = sk_stream_alloc_skb(sk, 0, sk->sk_allocation); + if (skb) + break; + yield(); + } +- +- /* Reserve space for headers and prepare control bits. */ +- skb_reserve(skb, MAX_TCP_HEADER); + /* FIN eats a sequence byte, write_seq advanced by tcp_queue_skb(). */ + tcp_init_nondata_skb(skb, tp->write_seq, + TCPHDR_ACK | TCPHDR_FIN); diff --git a/queue-3.10/tcp-make-connect-mem-charging-friendly.patch b/queue-3.10/tcp-make-connect-mem-charging-friendly.patch new file mode 100644 index 00000000000..75c699d40fa --- /dev/null +++ b/queue-3.10/tcp-make-connect-mem-charging-friendly.patch @@ -0,0 +1,142 @@ +From foo@baz Tue Mar 24 11:01:55 CET 2015 +From: Eric Dumazet +Date: Mon, 17 Nov 2014 23:06:20 -0800 +Subject: tcp: make connect() mem charging friendly + +From: Eric Dumazet + +[ Upstream commit 355a901e6cf1b2b763ec85caa2a9f04fbcc4ab4a ] + +While working on sk_forward_alloc problems reported by Denys +Fedoryshchenko, we found that tcp connect() (and fastopen) do not call +sk_wmem_schedule() for SYN packet (and/or SYN/DATA packet), so +sk_forward_alloc is negative while connect is in progress. + +We can fix this by calling regular sk_stream_alloc_skb() both for the +SYN packet (in tcp_connect()) and the syn_data packet in +tcp_send_syn_data() + +Then, tcp_send_syn_data() can avoid copying syn_data as we simply +can manipulate syn_data->cb[] to remove SYN flag (and increment seq) + +Instead of open coding memcpy_fromiovecend(), simply use this helper. + +This leaves in socket write queue clean fast clone skbs. + +This was tested against our fastopen packetdrill tests. + +Reported-by: Denys Fedoryshchenko +Signed-off-by: Eric Dumazet +Acked-by: Yuchung Cheng +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/tcp_output.c | 66 +++++++++++++++++++++----------------------------- + 1 file changed, 29 insertions(+), 37 deletions(-) + +--- a/net/ipv4/tcp_output.c ++++ b/net/ipv4/tcp_output.c +@@ -2871,9 +2871,9 @@ static int tcp_send_syn_data(struct sock + { + struct tcp_sock *tp = tcp_sk(sk); + struct tcp_fastopen_request *fo = tp->fastopen_req; +- int syn_loss = 0, space, i, err = 0, iovlen = fo->data->msg_iovlen; +- struct sk_buff *syn_data = NULL, *data; ++ int syn_loss = 0, space, err = 0; + unsigned long last_syn_loss = 0; ++ struct sk_buff *syn_data; + + tp->rx_opt.mss_clamp = tp->advmss; /* If MSS is not cached */ + tcp_fastopen_cache_get(sk, &tp->rx_opt.mss_clamp, &fo->cookie, +@@ -2904,42 +2904,38 @@ static int tcp_send_syn_data(struct sock + /* limit to order-0 allocations */ + space = min_t(size_t, space, SKB_MAX_HEAD(MAX_TCP_HEADER)); + +- syn_data = skb_copy_expand(syn, MAX_TCP_HEADER, space, +- sk->sk_allocation); +- if (syn_data == NULL) ++ syn_data = sk_stream_alloc_skb(sk, space, sk->sk_allocation); ++ if (!syn_data) + goto fallback; +- +- for (i = 0; i < iovlen && syn_data->len < space; ++i) { +- struct iovec *iov = &fo->data->msg_iov[i]; +- unsigned char __user *from = iov->iov_base; +- int len = iov->iov_len; +- +- if (syn_data->len + len > space) +- len = space - syn_data->len; +- else if (i + 1 == iovlen) +- /* No more data pending in inet_wait_for_connect() */ +- fo->data = NULL; +- +- if (skb_add_data(syn_data, from, len)) +- goto fallback; +- } +- +- /* Queue a data-only packet after the regular SYN for retransmission */ +- data = pskb_copy(syn_data, sk->sk_allocation); +- if (data == NULL) ++ syn_data->ip_summed = CHECKSUM_PARTIAL; ++ memcpy(syn_data->cb, syn->cb, sizeof(syn->cb)); ++ if (unlikely(memcpy_fromiovecend(skb_put(syn_data, space), ++ fo->data->msg_iov, 0, space))) { ++ kfree_skb(syn_data); + goto fallback; +- TCP_SKB_CB(data)->seq++; +- TCP_SKB_CB(data)->tcp_flags &= ~TCPHDR_SYN; +- TCP_SKB_CB(data)->tcp_flags = (TCPHDR_ACK|TCPHDR_PSH); +- tcp_connect_queue_skb(sk, data); +- fo->copied = data->len; ++ } + +- if (tcp_transmit_skb(sk, syn_data, 0, sk->sk_allocation) == 0) { ++ /* No more data pending in inet_wait_for_connect() */ ++ if (space == fo->size) ++ fo->data = NULL; ++ fo->copied = space; ++ ++ tcp_connect_queue_skb(sk, syn_data); ++ ++ err = tcp_transmit_skb(sk, syn_data, 1, sk->sk_allocation); ++ ++ /* Now full SYN+DATA was cloned and sent (or not), ++ * remove the SYN from the original skb (syn_data) ++ * we keep in write queue in case of a retransmit, as we ++ * also have the SYN packet (with no data) in the same queue. ++ */ ++ TCP_SKB_CB(syn_data)->seq++; ++ TCP_SKB_CB(syn_data)->tcp_flags = TCPHDR_ACK | TCPHDR_PSH; ++ if (!err) { + tp->syn_data = (fo->copied > 0); + NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE); + goto done; + } +- syn_data = NULL; + + fallback: + /* Send a regular SYN with Fast Open cookie request option */ +@@ -2948,7 +2944,6 @@ fallback: + err = tcp_transmit_skb(sk, syn, 1, sk->sk_allocation); + if (err) + tp->syn_fastopen = 0; +- kfree_skb(syn_data); + done: + fo->cookie.len = -1; /* Exclude Fast Open option for SYN retries */ + return err; +@@ -2968,13 +2963,10 @@ int tcp_connect(struct sock *sk) + return 0; + } + +- buff = alloc_skb_fclone(MAX_TCP_HEADER + 15, sk->sk_allocation); +- if (unlikely(buff == NULL)) ++ buff = sk_stream_alloc_skb(sk, 0, sk->sk_allocation); ++ if (unlikely(!buff)) + return -ENOBUFS; + +- /* Reserve space for headers. */ +- skb_reserve(buff, MAX_TCP_HEADER); +- + tcp_init_nondata_skb(buff, tp->write_seq++, TCPHDR_SYN); + tp->retrans_stamp = TCP_SKB_CB(buff)->when = tcp_time_stamp; + tcp_connect_queue_skb(sk, buff);