From: Greg Kroah-Hartman Date: Wed, 19 Apr 2017 13:09:12 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v4.4.63~9 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=82f012e8d1ec6bccab6241e19ab21171647074c2;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: ibmveth-calculate-gso_segs-for-large-packets.patch net-ipv6-check-route-protocol-when-deleting-routes.patch sunrpc-fix-refcounting-problems-with-auth_gss-messages.patch tty-serial-atmel-rs485-half-duplex-w-dma-enable-rx-after-tx-is-done.patch --- diff --git a/queue-4.4/ibmveth-calculate-gso_segs-for-large-packets.patch b/queue-4.4/ibmveth-calculate-gso_segs-for-large-packets.patch new file mode 100644 index 00000000000..64695708d6d --- /dev/null +++ b/queue-4.4/ibmveth-calculate-gso_segs-for-large-packets.patch @@ -0,0 +1,58 @@ +From 94acf164dc8f1184e8d0737be7125134c2701dbe Mon Sep 17 00:00:00 2001 +From: Thomas Falcon +Date: Tue, 13 Dec 2016 18:15:09 -0600 +Subject: ibmveth: calculate gso_segs for large packets + +From: Thomas Falcon + +commit 94acf164dc8f1184e8d0737be7125134c2701dbe upstream. + +Include calculations to compute the number of segments +that comprise an aggregated large packet. + +Signed-off-by: Thomas Falcon +Reviewed-by: Marcelo Ricardo Leitner +Reviewed-by: Jonathan Maxwell +Signed-off-by: David S. Miller +Signed-off-by: Sumit Semwal +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/net/ethernet/ibm/ibmveth.c | 12 ++++++++++-- + 1 file changed, 10 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/ibm/ibmveth.c ++++ b/drivers/net/ethernet/ibm/ibmveth.c +@@ -1179,7 +1179,9 @@ map_failed: + + static void ibmveth_rx_mss_helper(struct sk_buff *skb, u16 mss, int lrg_pkt) + { ++ struct tcphdr *tcph; + int offset = 0; ++ int hdr_len; + + /* only TCP packets will be aggregated */ + if (skb->protocol == htons(ETH_P_IP)) { +@@ -1206,14 +1208,20 @@ static void ibmveth_rx_mss_helper(struct + /* if mss is not set through Large Packet bit/mss in rx buffer, + * expect that the mss will be written to the tcp header checksum. + */ ++ tcph = (struct tcphdr *)(skb->data + offset); + if (lrg_pkt) { + skb_shinfo(skb)->gso_size = mss; + } else if (offset) { +- struct tcphdr *tcph = (struct tcphdr *)(skb->data + offset); +- + skb_shinfo(skb)->gso_size = ntohs(tcph->check); + tcph->check = 0; + } ++ ++ if (skb_shinfo(skb)->gso_size) { ++ hdr_len = offset + tcph->doff * 4; ++ skb_shinfo(skb)->gso_segs = ++ DIV_ROUND_UP(skb->len - hdr_len, ++ skb_shinfo(skb)->gso_size); ++ } + } + + static int ibmveth_poll(struct napi_struct *napi, int budget) diff --git a/queue-4.4/net-ipv6-check-route-protocol-when-deleting-routes.patch b/queue-4.4/net-ipv6-check-route-protocol-when-deleting-routes.patch new file mode 100644 index 00000000000..47bf0b06315 --- /dev/null +++ b/queue-4.4/net-ipv6-check-route-protocol-when-deleting-routes.patch @@ -0,0 +1,38 @@ +From c2ed1880fd61a998e3ce40254a99a2ad000f1a7d Mon Sep 17 00:00:00 2001 +From: Mantas M +Date: Fri, 16 Dec 2016 10:30:59 +0200 +Subject: net: ipv6: check route protocol when deleting routes +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Mantas M + +commit c2ed1880fd61a998e3ce40254a99a2ad000f1a7d upstream. + +The protocol field is checked when deleting IPv4 routes, but ignored for +IPv6, which causes problems with routing daemons accidentally deleting +externally set routes (observed by multiple bird6 users). + +This can be verified using `ip -6 route del proto something`. + +Signed-off-by: Mantas Mikulėnas +Signed-off-by: David S. Miller +Cc: Ben Hutchings +Signed-off-by: Greg Kroah-Hartman + +--- + net/ipv6/route.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/net/ipv6/route.c ++++ b/net/ipv6/route.c +@@ -2084,6 +2084,8 @@ static int ip6_route_del(struct fib6_con + continue; + if (cfg->fc_metric && cfg->fc_metric != rt->rt6i_metric) + continue; ++ if (cfg->fc_protocol && cfg->fc_protocol != rt->rt6i_protocol) ++ continue; + dst_hold(&rt->dst); + read_unlock_bh(&table->tb6_lock); + diff --git a/queue-4.4/series b/queue-4.4/series index e5f877fc9be..15ea943a79d 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -37,3 +37,7 @@ pegasus-use-heap-buffers-for-all-register-access.patch rtl8150-use-heap-buffers-for-all-register-access.patch catc-combine-failure-cleanup-code-in-catc_probe.patch catc-use-heap-buffer-for-memory-size-test.patch +ibmveth-calculate-gso_segs-for-large-packets.patch +sunrpc-fix-refcounting-problems-with-auth_gss-messages.patch +tty-serial-atmel-rs485-half-duplex-w-dma-enable-rx-after-tx-is-done.patch +net-ipv6-check-route-protocol-when-deleting-routes.patch diff --git a/queue-4.4/sunrpc-fix-refcounting-problems-with-auth_gss-messages.patch b/queue-4.4/sunrpc-fix-refcounting-problems-with-auth_gss-messages.patch new file mode 100644 index 00000000000..c47732266a5 --- /dev/null +++ b/queue-4.4/sunrpc-fix-refcounting-problems-with-auth_gss-messages.patch @@ -0,0 +1,85 @@ +From 1cded9d2974fe4fe339fc0ccd6638b80d465ab2c Mon Sep 17 00:00:00 2001 +From: NeilBrown +Date: Mon, 5 Dec 2016 15:10:11 +1100 +Subject: SUNRPC: fix refcounting problems with auth_gss messages. + +From: NeilBrown + +commit 1cded9d2974fe4fe339fc0ccd6638b80d465ab2c upstream. + +There are two problems with refcounting of auth_gss messages. + +First, the reference on the pipe->pipe list (taken by a call +to rpc_queue_upcall()) is not counted. It seems to be +assumed that a message in pipe->pipe will always also be in +pipe->in_downcall, where it is correctly reference counted. + +However there is no guaranty of this. I have a report of a +NULL dereferences in rpc_pipe_read() which suggests a msg +that has been freed is still on the pipe->pipe list. + +One way I imagine this might happen is: +- message is queued for uid=U and auth->service=S1 +- rpc.gssd reads this message and starts processing. + This removes the message from pipe->pipe +- message is queued for uid=U and auth->service=S2 +- rpc.gssd replies to the first message. gss_pipe_downcall() + calls __gss_find_upcall(pipe, U, NULL) and it finds the + *second* message, as new messages are placed at the head + of ->in_downcall, and the service type is not checked. +- This second message is removed from ->in_downcall and freed + by gss_release_msg() (even though it is still on pipe->pipe) +- rpc.gssd tries to read another message, and dereferences a pointer + to this message that has just been freed. + +I fix this by incrementing the reference count before calling +rpc_queue_upcall(), and decrementing it if that fails, or normally in +gss_pipe_destroy_msg(). + +It seems strange that the reply doesn't target the message more +precisely, but I don't know all the details. In any case, I think the +reference counting irregularity became a measureable bug when the +extra arg was added to __gss_find_upcall(), hence the Fixes: line +below. + +The second problem is that if rpc_queue_upcall() fails, the new +message is not freed. gss_alloc_msg() set the ->count to 1, +gss_add_msg() increments this to 2, gss_unhash_msg() decrements to 1, +then the pointer is discarded so the memory never gets freed. + +Fixes: 9130b8dbc6ac ("SUNRPC: allow for upcalls for same uid but different gss service") +Link: https://bugzilla.opensuse.org/show_bug.cgi?id=1011250 +Signed-off-by: NeilBrown +Signed-off-by: Trond Myklebust +Signed-off-by: Sumit Semwal +Signed-off-by: Greg Kroah-Hartman + +--- + net/sunrpc/auth_gss/auth_gss.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +--- a/net/sunrpc/auth_gss/auth_gss.c ++++ b/net/sunrpc/auth_gss/auth_gss.c +@@ -541,9 +541,13 @@ gss_setup_upcall(struct gss_auth *gss_au + return gss_new; + gss_msg = gss_add_msg(gss_new); + if (gss_msg == gss_new) { +- int res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg); ++ int res; ++ atomic_inc(&gss_msg->count); ++ res = rpc_queue_upcall(gss_new->pipe, &gss_new->msg); + if (res) { + gss_unhash_msg(gss_new); ++ atomic_dec(&gss_msg->count); ++ gss_release_msg(gss_new); + gss_msg = ERR_PTR(res); + } + } else +@@ -836,6 +840,7 @@ gss_pipe_destroy_msg(struct rpc_pipe_msg + warn_gssd(); + gss_release_msg(gss_msg); + } ++ gss_release_msg(gss_msg); + } + + static void gss_pipe_dentry_destroy(struct dentry *dir, diff --git a/queue-4.4/tty-serial-atmel-rs485-half-duplex-w-dma-enable-rx-after-tx-is-done.patch b/queue-4.4/tty-serial-atmel-rs485-half-duplex-w-dma-enable-rx-after-tx-is-done.patch new file mode 100644 index 00000000000..4f8ec82dd8c --- /dev/null +++ b/queue-4.4/tty-serial-atmel-rs485-half-duplex-w-dma-enable-rx-after-tx-is-done.patch @@ -0,0 +1,67 @@ +From b389f173aaa1204d6dc1f299082a162eb0491545 Mon Sep 17 00:00:00 2001 +From: Richard Genoud +Date: Tue, 6 Dec 2016 13:05:33 +0100 +Subject: tty/serial: atmel: RS485 half duplex w/DMA: enable RX after TX is done + +From: Richard Genoud + +commit b389f173aaa1204d6dc1f299082a162eb0491545 upstream. + +When using RS485 in half duplex, RX should be enabled when TX is +finished, and stopped when TX starts. + +Before commit 0058f0871efe7b01c6 ("tty/serial: atmel: fix RS485 half +duplex with DMA"), RX was not disabled in atmel_start_tx() if the DMA +was used. So, collisions could happened. + +But disabling RX in atmel_start_tx() uncovered another bug: +RX was enabled again in the wrong place (in atmel_tx_dma) instead of +being enabled when TX is finished (in atmel_complete_tx_dma), so the +transmission simply stopped. + +This bug was not triggered before commit 0058f0871efe7b01c6 +("tty/serial: atmel: fix RS485 half duplex with DMA") because RX was +never disabled before. + +Moving atmel_start_rx() in atmel_complete_tx_dma() corrects the problem. + +Reported-by: Gil Weber +Fixes: 0058f0871efe7b01c6 +Tested-by: Gil Weber +Signed-off-by: Richard Genoud +Acked-by: Alexandre Belloni +Signed-off-by: Alexandre Belloni +Tested-by: Bryan Evenson +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/tty/serial/atmel_serial.c | 11 +++++------ + 1 file changed, 5 insertions(+), 6 deletions(-) + +--- a/drivers/tty/serial/atmel_serial.c ++++ b/drivers/tty/serial/atmel_serial.c +@@ -810,6 +810,11 @@ static void atmel_complete_tx_dma(void * + */ + if (!uart_circ_empty(xmit)) + tasklet_schedule(&atmel_port->tasklet); ++ else if ((port->rs485.flags & SER_RS485_ENABLED) && ++ !(port->rs485.flags & SER_RS485_RX_DURING_TX)) { ++ /* DMA done, stop TX, start RX for RS485 */ ++ atmel_start_rx(port); ++ } + + spin_unlock_irqrestore(&port->lock, flags); + } +@@ -912,12 +917,6 @@ static void atmel_tx_dma(struct uart_por + desc->callback = atmel_complete_tx_dma; + desc->callback_param = atmel_port; + atmel_port->cookie_tx = dmaengine_submit(desc); +- +- } else { +- if (port->rs485.flags & SER_RS485_ENABLED) { +- /* DMA done, stop TX, start RX for RS485 */ +- atmel_start_rx(port); +- } + } + + if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)