From: Greg Kroah-Hartman Date: Fri, 3 Apr 2020 09:10:39 +0000 (+0200) Subject: 4.4-stable patches X-Git-Tag: v5.4.31~45 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3dd3dadcef2962982102952663f740bae25d1925;p=thirdparty%2Fkernel%2Fstable-queue.git 4.4-stable patches added patches: ipv4-fix-a-rcu-list-lock-in-fib_triestat_seq_show.patch net-ip_tunnel-fix-interface-lookup-with-no-key.patch sctp-fix-possibly-using-a-bad-saddr-with-a-given-dst.patch --- diff --git a/queue-4.4/ipv4-fix-a-rcu-list-lock-in-fib_triestat_seq_show.patch b/queue-4.4/ipv4-fix-a-rcu-list-lock-in-fib_triestat_seq_show.patch new file mode 100644 index 00000000000..5fcd48c28df --- /dev/null +++ b/queue-4.4/ipv4-fix-a-rcu-list-lock-in-fib_triestat_seq_show.patch @@ -0,0 +1,63 @@ +From foo@baz Fri 03 Apr 2020 11:06:15 AM CEST +From: Qian Cai +Date: Wed, 25 Mar 2020 18:01:00 -0400 +Subject: ipv4: fix a RCU-list lock in fib_triestat_seq_show + +From: Qian Cai + +[ Upstream commit fbe4e0c1b298b4665ee6915266c9d6c5b934ef4a ] + +fib_triestat_seq_show() calls hlist_for_each_entry_rcu(tb, head, +tb_hlist) without rcu_read_lock() will trigger a warning, + + net/ipv4/fib_trie.c:2579 RCU-list traversed in non-reader section!! + + other info that might help us debug this: + + rcu_scheduler_active = 2, debug_locks = 1 + 1 lock held by proc01/115277: + #0: c0000014507acf00 (&p->lock){+.+.}-{3:3}, at: seq_read+0x58/0x670 + + Call Trace: + dump_stack+0xf4/0x164 (unreliable) + lockdep_rcu_suspicious+0x140/0x164 + fib_triestat_seq_show+0x750/0x880 + seq_read+0x1a0/0x670 + proc_reg_read+0x10c/0x1b0 + __vfs_read+0x3c/0x70 + vfs_read+0xac/0x170 + ksys_read+0x7c/0x140 + system_call+0x5c/0x68 + +Fix it by adding a pair of rcu_read_lock/unlock() and use +cond_resched_rcu() to avoid the situation where walking of a large +number of items may prevent scheduling for a long time. + +Signed-off-by: Qian Cai +Reviewed-by: Eric Dumazet +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/fib_trie.c | 3 +++ + 1 file changed, 3 insertions(+) + +--- a/net/ipv4/fib_trie.c ++++ b/net/ipv4/fib_trie.c +@@ -2230,6 +2230,7 @@ static int fib_triestat_seq_show(struct + " %Zd bytes, size of tnode: %Zd bytes.\n", + LEAF_SIZE, TNODE_SIZE(0)); + ++ rcu_read_lock(); + for (h = 0; h < FIB_TABLE_HASHSZ; h++) { + struct hlist_head *head = &net->ipv4.fib_table_hash[h]; + struct fib_table *tb; +@@ -2249,7 +2250,9 @@ static int fib_triestat_seq_show(struct + trie_show_usage(seq, t->stats); + #endif + } ++ cond_resched_rcu(); + } ++ rcu_read_unlock(); + + return 0; + } diff --git a/queue-4.4/net-ip_tunnel-fix-interface-lookup-with-no-key.patch b/queue-4.4/net-ip_tunnel-fix-interface-lookup-with-no-key.patch new file mode 100644 index 00000000000..b837b08a97e --- /dev/null +++ b/queue-4.4/net-ip_tunnel-fix-interface-lookup-with-no-key.patch @@ -0,0 +1,54 @@ +From foo@baz Fri 03 Apr 2020 11:06:15 AM CEST +From: William Dauchy +Date: Fri, 27 Mar 2020 19:56:39 +0100 +Subject: net, ip_tunnel: fix interface lookup with no key + +From: William Dauchy + +[ Upstream commit 25629fdaff2ff509dd0b3f5ff93d70a75e79e0a1 ] + +when creating a new ipip interface with no local/remote configuration, +the lookup is done with TUNNEL_NO_KEY flag, making it impossible to +match the new interface (only possible match being fallback or metada +case interface); e.g: `ip link add tunl1 type ipip dev eth0` + +To fix this case, adding a flag check before the key comparison so we +permit to match an interface with no local/remote config; it also avoids +breaking possible userland tools relying on TUNNEL_NO_KEY flag and +uninitialised key. + +context being on my side, I'm creating an extra ipip interface attached +to the physical one, and moving it to a dedicated namespace. + +Fixes: c54419321455 ("GRE: Refactor GRE tunneling code.") +Signed-off-by: William Dauchy +Signed-off-by: Nicolas Dichtel +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/ipv4/ip_tunnel.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +--- a/net/ipv4/ip_tunnel.c ++++ b/net/ipv4/ip_tunnel.c +@@ -155,11 +155,8 @@ struct ip_tunnel *ip_tunnel_lookup(struc + cand = t; + } + +- if (flags & TUNNEL_NO_KEY) +- goto skip_key_lookup; +- + hlist_for_each_entry_rcu(t, head, hash_node) { +- if (t->parms.i_key != key || ++ if ((!(flags & TUNNEL_NO_KEY) && t->parms.i_key != key) || + t->parms.iph.saddr != 0 || + t->parms.iph.daddr != 0 || + !(t->dev->flags & IFF_UP)) +@@ -171,7 +168,6 @@ struct ip_tunnel *ip_tunnel_lookup(struc + cand = t; + } + +-skip_key_lookup: + if (cand) + return cand; + diff --git a/queue-4.4/sctp-fix-possibly-using-a-bad-saddr-with-a-given-dst.patch b/queue-4.4/sctp-fix-possibly-using-a-bad-saddr-with-a-given-dst.patch new file mode 100644 index 00000000000..8064725ca0b --- /dev/null +++ b/queue-4.4/sctp-fix-possibly-using-a-bad-saddr-with-a-given-dst.patch @@ -0,0 +1,187 @@ +From foo@baz Fri 03 Apr 2020 10:57:34 AM CEST +From: Marcelo Ricardo Leitner +Date: Thu, 26 Mar 2020 20:47:46 -0300 +Subject: sctp: fix possibly using a bad saddr with a given dst + +From: Marcelo Ricardo Leitner + +[ Upstream commit 582eea230536a6f104097dd46205822005d5fe3a ] + +Under certain circumstances, depending on the order of addresses on the +interfaces, it could be that sctp_v[46]_get_dst() would return a dst +with a mismatched struct flowi. + +For example, if when walking through the bind addresses and the first +one is not a match, it saves the dst as a fallback (added in +410f03831c07), but not the flowi. Then if the next one is also not a +match, the previous dst will be returned but with the flowi information +for the 2nd address, which is wrong. + +The fix is to use a locally stored flowi that can be used for such +attempts, and copy it to the parameter only in case it is a possible +match, together with the corresponding dst entry. + +The patch updates IPv6 code mostly just to be in sync. Even though the issue +is also present there, it fallback is not expected to work with IPv6. + +Fixes: 410f03831c07 ("sctp: add routing output fallback") +Reported-by: Jin Meng +Signed-off-by: Marcelo Ricardo Leitner +Tested-by: Xin Long +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman +--- + net/sctp/ipv6.c | 20 ++++++++++++++------ + net/sctp/protocol.c | 28 +++++++++++++++++++--------- + 2 files changed, 33 insertions(+), 15 deletions(-) + +--- a/net/sctp/ipv6.c ++++ b/net/sctp/ipv6.c +@@ -234,7 +234,8 @@ static void sctp_v6_get_dst(struct sctp_ + { + struct sctp_association *asoc = t->asoc; + struct dst_entry *dst = NULL; +- struct flowi6 *fl6 = &fl->u.ip6; ++ struct flowi _fl; ++ struct flowi6 *fl6 = &_fl.u.ip6; + struct sctp_bind_addr *bp; + struct ipv6_pinfo *np = inet6_sk(sk); + struct sctp_sockaddr_entry *laddr; +@@ -244,7 +245,7 @@ static void sctp_v6_get_dst(struct sctp_ + __u8 matchlen = 0; + sctp_scope_t scope; + +- memset(fl6, 0, sizeof(struct flowi6)); ++ memset(&_fl, 0, sizeof(_fl)); + fl6->daddr = daddr->v6.sin6_addr; + fl6->fl6_dport = daddr->v6.sin6_port; + fl6->flowi6_proto = IPPROTO_SCTP; +@@ -268,8 +269,11 @@ static void sctp_v6_get_dst(struct sctp_ + rcu_read_unlock(); + + dst = ip6_dst_lookup_flow(sk, fl6, final_p); +- if (!asoc || saddr) ++ if (!asoc || saddr) { ++ t->dst = dst; ++ memcpy(fl, &_fl, sizeof(_fl)); + goto out; ++ } + + bp = &asoc->base.bind_addr; + scope = sctp_scope(daddr); +@@ -292,6 +296,8 @@ static void sctp_v6_get_dst(struct sctp_ + if ((laddr->a.sa.sa_family == AF_INET6) && + (sctp_v6_cmp_addr(&dst_saddr, &laddr->a))) { + rcu_read_unlock(); ++ t->dst = dst; ++ memcpy(fl, &_fl, sizeof(_fl)); + goto out; + } + } +@@ -330,6 +336,8 @@ static void sctp_v6_get_dst(struct sctp_ + if (!IS_ERR_OR_NULL(dst)) + dst_release(dst); + dst = bdst; ++ t->dst = dst; ++ memcpy(fl, &_fl, sizeof(_fl)); + break; + } + +@@ -343,6 +351,8 @@ static void sctp_v6_get_dst(struct sctp_ + dst_release(dst); + dst = bdst; + matchlen = bmatchlen; ++ t->dst = dst; ++ memcpy(fl, &_fl, sizeof(_fl)); + } + rcu_read_unlock(); + +@@ -351,14 +361,12 @@ out: + struct rt6_info *rt; + + rt = (struct rt6_info *)dst; +- t->dst = dst; + t->dst_cookie = rt6_get_cookie(rt); + pr_debug("rt6_dst:%pI6/%d rt6_src:%pI6\n", + &rt->rt6i_dst.addr, rt->rt6i_dst.plen, +- &fl6->saddr); ++ &fl->u.ip6.saddr); + } else { + t->dst = NULL; +- + pr_debug("no route\n"); + } + } +--- a/net/sctp/protocol.c ++++ b/net/sctp/protocol.c +@@ -428,14 +428,15 @@ static void sctp_v4_get_dst(struct sctp_ + { + struct sctp_association *asoc = t->asoc; + struct rtable *rt; +- struct flowi4 *fl4 = &fl->u.ip4; ++ struct flowi _fl; ++ struct flowi4 *fl4 = &_fl.u.ip4; + struct sctp_bind_addr *bp; + struct sctp_sockaddr_entry *laddr; + struct dst_entry *dst = NULL; + union sctp_addr *daddr = &t->ipaddr; + union sctp_addr dst_saddr; + +- memset(fl4, 0x0, sizeof(struct flowi4)); ++ memset(&_fl, 0x0, sizeof(_fl)); + fl4->daddr = daddr->v4.sin_addr.s_addr; + fl4->fl4_dport = daddr->v4.sin_port; + fl4->flowi4_proto = IPPROTO_SCTP; +@@ -453,8 +454,11 @@ static void sctp_v4_get_dst(struct sctp_ + &fl4->saddr); + + rt = ip_route_output_key(sock_net(sk), fl4); +- if (!IS_ERR(rt)) ++ if (!IS_ERR(rt)) { + dst = &rt->dst; ++ t->dst = dst; ++ memcpy(fl, &_fl, sizeof(_fl)); ++ } + + /* If there is no association or if a source address is passed, no + * more validation is required. +@@ -517,27 +521,33 @@ static void sctp_v4_get_dst(struct sctp_ + odev = __ip_dev_find(sock_net(sk), laddr->a.v4.sin_addr.s_addr, + false); + if (!odev || odev->ifindex != fl4->flowi4_oif) { +- if (!dst) ++ if (!dst) { + dst = &rt->dst; +- else ++ t->dst = dst; ++ memcpy(fl, &_fl, sizeof(_fl)); ++ } else { + dst_release(&rt->dst); ++ } + continue; + } + + dst_release(dst); + dst = &rt->dst; ++ t->dst = dst; ++ memcpy(fl, &_fl, sizeof(_fl)); + break; + } + + out_unlock: + rcu_read_unlock(); + out: +- t->dst = dst; +- if (dst) ++ if (dst) { + pr_debug("rt_dst:%pI4, rt_src:%pI4\n", +- &fl4->daddr, &fl4->saddr); +- else ++ &fl->u.ip4.daddr, &fl->u.ip4.saddr); ++ } else { ++ t->dst = NULL; + pr_debug("no route\n"); ++ } + } + + /* For v4, the source address is cached in the route entry(dst). So no need diff --git a/queue-4.4/series b/queue-4.4/series index c01f499c84a..9f283d408d2 100644 --- a/queue-4.4/series +++ b/queue-4.4/series @@ -1 +1,4 @@ drm-bochs-downgrade-pci_request_region-failure-from-.patch +ipv4-fix-a-rcu-list-lock-in-fib_triestat_seq_show.patch +net-ip_tunnel-fix-interface-lookup-with-no-key.patch +sctp-fix-possibly-using-a-bad-saddr-with-a-given-dst.patch