From: Greg Kroah-Hartman Date: Tue, 10 Sep 2019 14:37:32 +0000 (+0100) Subject: 4.14-stable patches X-Git-Tag: v4.4.193~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=bac09255fb779ac209b9259a20489a06c8598810;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: ip6-fix-skb-leak-in-ip6frag_expire_frag_queue.patch pci-designware-ep-fix-find_first_zero_bit-usage.patch pci-dra7xx-fix-legacy-intd-irq-handling.patch xfrm-clean-up-xfrm-protocol-checks.patch --- diff --git a/queue-4.14/ip6-fix-skb-leak-in-ip6frag_expire_frag_queue.patch b/queue-4.14/ip6-fix-skb-leak-in-ip6frag_expire_frag_queue.patch new file mode 100644 index 00000000000..765ef9825a8 --- /dev/null +++ b/queue-4.14/ip6-fix-skb-leak-in-ip6frag_expire_frag_queue.patch @@ -0,0 +1,58 @@ +From 47d3d7fdb10a21c223036b58bd70ffdc24a472c4 Mon Sep 17 00:00:00 2001 +From: Eric Dumazet +Date: Fri, 3 May 2019 08:24:44 -0700 +Subject: ip6: fix skb leak in ip6frag_expire_frag_queue() + +From: Eric Dumazet + +commit 47d3d7fdb10a21c223036b58bd70ffdc24a472c4 upstream. + +Since ip6frag_expire_frag_queue() now pulls the head skb +from frag queue, we should no longer use skb_get(), since +this leads to an skb leak. + +Stefan Bader initially reported a problem in 4.4.stable [1] caused +by the skb_get(), so this patch should also fix this issue. + +296583.091021] kernel BUG at /build/linux-6VmqmP/linux-4.4.0/net/core/skbuff.c:1207! +[296583.091734] Call Trace: +[296583.091749] [] __pskb_pull_tail+0x50/0x350 +[296583.091764] [] _decode_session6+0x26a/0x400 +[296583.091779] [] __xfrm_decode_session+0x39/0x50 +[296583.091795] [] icmpv6_route_lookup+0xf0/0x1c0 +[296583.091809] [] icmp6_send+0x5e1/0x940 +[296583.091823] [] ? __netif_receive_skb+0x18/0x60 +[296583.091838] [] ? netif_receive_skb_internal+0x32/0xa0 +[296583.091858] [] ? ixgbe_clean_rx_irq+0x594/0xac0 [ixgbe] +[296583.091876] [] ? nf_ct_net_exit+0x50/0x50 [nf_defrag_ipv6] +[296583.091893] [] icmpv6_send+0x21/0x30 +[296583.091906] [] ip6_expire_frag_queue+0xe0/0x120 +[296583.091921] [] nf_ct_frag6_expire+0x1f/0x30 [nf_defrag_ipv6] +[296583.091938] [] call_timer_fn+0x37/0x140 +[296583.091951] [] ? nf_ct_net_exit+0x50/0x50 [nf_defrag_ipv6] +[296583.091968] [] run_timer_softirq+0x234/0x330 +[296583.091982] [] __do_softirq+0x109/0x2b0 + +Fixes: d4289fcc9b16 ("net: IP6 defrag: use rbtrees for IPv6 defrag") +Signed-off-by: Eric Dumazet +Reported-by: Stefan Bader +Cc: Peter Oskolkov +Cc: Florian Westphal +Signed-off-by: David S. Miller +Signed-off-by: Baolin Wang +Signed-off-by: Greg Kroah-Hartman + +--- + include/net/ipv6_frag.h | 1 - + 1 file changed, 1 deletion(-) + +--- a/include/net/ipv6_frag.h ++++ b/include/net/ipv6_frag.h +@@ -94,7 +94,6 @@ ip6frag_expire_frag_queue(struct net *ne + goto out; + + head->dev = dev; +- skb_get(head); + spin_unlock(&fq->q.lock); + + icmpv6_send(head, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0); diff --git a/queue-4.14/pci-designware-ep-fix-find_first_zero_bit-usage.patch b/queue-4.14/pci-designware-ep-fix-find_first_zero_bit-usage.patch new file mode 100644 index 00000000000..185ed12bab1 --- /dev/null +++ b/queue-4.14/pci-designware-ep-fix-find_first_zero_bit-usage.patch @@ -0,0 +1,151 @@ +From ad4a5becc689c3f32bbbc2b37eff89efe19dc2f9 Mon Sep 17 00:00:00 2001 +From: Niklas Cassel +Date: Thu, 14 Dec 2017 14:01:44 +0100 +Subject: PCI: designware-ep: Fix find_first_zero_bit() usage + +From: Niklas Cassel + +commit ad4a5becc689c3f32bbbc2b37eff89efe19dc2f9 upstream. + +find_first_zero_bit()'s parameter 'size' is defined in bits, +not in bytes. + +find_first_zero_bit() is called with size in bytes rather than bits, +which thus defines a too low upper limit, causing +dw_pcie_ep_inbound_atu() to assign iatu index #4 to both bar 4 +and bar 5, which makes bar 5 overwrite the settings set by bar 4. + +Since the sizes of the bitmaps are known, dynamically allocate the +bitmaps, and use the correct size when calling find_first_zero_bit(). + +Additionally, make sure that ep->num_ob_windows and ep->num_ib_windows, +which are obtained from device tree, are smaller than the maximum number +of iATUs (MAX_IATU_IN/MAX_IATU_OUT). + +Fixes: f8aed6ec624f ("PCI: dwc: designware: Add EP mode support") +Signed-off-by: Niklas Cassel +Signed-off-by: Lorenzo Pieralisi +Acked-by: Kishon Vijay Abraham I +Signed-off-by: Mathieu Poirier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/dwc/pcie-designware-ep.c | 34 ++++++++++++++++++++++++++-------- + drivers/pci/dwc/pcie-designware.h | 8 ++++++-- + 2 files changed, 32 insertions(+), 10 deletions(-) + +--- a/drivers/pci/dwc/pcie-designware-ep.c ++++ b/drivers/pci/dwc/pcie-designware-ep.c +@@ -74,8 +74,7 @@ static int dw_pcie_ep_inbound_atu(struct + u32 free_win; + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + +- free_win = find_first_zero_bit(&ep->ib_window_map, +- sizeof(ep->ib_window_map)); ++ free_win = find_first_zero_bit(ep->ib_window_map, ep->num_ib_windows); + if (free_win >= ep->num_ib_windows) { + dev_err(pci->dev, "no free inbound window\n"); + return -EINVAL; +@@ -89,7 +88,7 @@ static int dw_pcie_ep_inbound_atu(struct + } + + ep->bar_to_atu[bar] = free_win; +- set_bit(free_win, &ep->ib_window_map); ++ set_bit(free_win, ep->ib_window_map); + + return 0; + } +@@ -100,8 +99,7 @@ static int dw_pcie_ep_outbound_atu(struc + u32 free_win; + struct dw_pcie *pci = to_dw_pcie_from_ep(ep); + +- free_win = find_first_zero_bit(&ep->ob_window_map, +- sizeof(ep->ob_window_map)); ++ free_win = find_first_zero_bit(ep->ob_window_map, ep->num_ob_windows); + if (free_win >= ep->num_ob_windows) { + dev_err(pci->dev, "no free outbound window\n"); + return -EINVAL; +@@ -110,7 +108,7 @@ static int dw_pcie_ep_outbound_atu(struc + dw_pcie_prog_outbound_atu(pci, free_win, PCIE_ATU_TYPE_MEM, + phys_addr, pci_addr, size); + +- set_bit(free_win, &ep->ob_window_map); ++ set_bit(free_win, ep->ob_window_map); + ep->outbound_addr[free_win] = phys_addr; + + return 0; +@@ -125,7 +123,7 @@ static void dw_pcie_ep_clear_bar(struct + dw_pcie_ep_reset_bar(pci, bar); + + dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_INBOUND); +- clear_bit(atu_index, &ep->ib_window_map); ++ clear_bit(atu_index, ep->ib_window_map); + } + + static int dw_pcie_ep_set_bar(struct pci_epc *epc, enum pci_barno bar, +@@ -181,7 +179,7 @@ static void dw_pcie_ep_unmap_addr(struct + return; + + dw_pcie_disable_atu(pci, atu_index, DW_PCIE_REGION_OUTBOUND); +- clear_bit(atu_index, &ep->ob_window_map); ++ clear_bit(atu_index, ep->ob_window_map); + } + + static int dw_pcie_ep_map_addr(struct pci_epc *epc, phys_addr_t addr, +@@ -302,12 +300,32 @@ int dw_pcie_ep_init(struct dw_pcie_ep *e + dev_err(dev, "unable to read *num-ib-windows* property\n"); + return ret; + } ++ if (ep->num_ib_windows > MAX_IATU_IN) { ++ dev_err(dev, "invalid *num-ib-windows*\n"); ++ return -EINVAL; ++ } + + ret = of_property_read_u32(np, "num-ob-windows", &ep->num_ob_windows); + if (ret < 0) { + dev_err(dev, "unable to read *num-ob-windows* property\n"); + return ret; + } ++ if (ep->num_ob_windows > MAX_IATU_OUT) { ++ dev_err(dev, "invalid *num-ob-windows*\n"); ++ return -EINVAL; ++ } ++ ++ ep->ib_window_map = devm_kzalloc(dev, sizeof(long) * ++ BITS_TO_LONGS(ep->num_ib_windows), ++ GFP_KERNEL); ++ if (!ep->ib_window_map) ++ return -ENOMEM; ++ ++ ep->ob_window_map = devm_kzalloc(dev, sizeof(long) * ++ BITS_TO_LONGS(ep->num_ob_windows), ++ GFP_KERNEL); ++ if (!ep->ob_window_map) ++ return -ENOMEM; + + addr = devm_kzalloc(dev, sizeof(phys_addr_t) * ep->num_ob_windows, + GFP_KERNEL); +--- a/drivers/pci/dwc/pcie-designware.h ++++ b/drivers/pci/dwc/pcie-designware.h +@@ -114,6 +114,10 @@ + #define MAX_MSI_IRQS 32 + #define MAX_MSI_CTRLS (MAX_MSI_IRQS / 32) + ++/* Maximum number of inbound/outbound iATUs */ ++#define MAX_IATU_IN 256 ++#define MAX_IATU_OUT 256 ++ + struct pcie_port; + struct dw_pcie; + struct dw_pcie_ep; +@@ -193,8 +197,8 @@ struct dw_pcie_ep { + size_t page_size; + u8 bar_to_atu[6]; + phys_addr_t *outbound_addr; +- unsigned long ib_window_map; +- unsigned long ob_window_map; ++ unsigned long *ib_window_map; ++ unsigned long *ob_window_map; + u32 num_ib_windows; + u32 num_ob_windows; + }; diff --git a/queue-4.14/pci-dra7xx-fix-legacy-intd-irq-handling.patch b/queue-4.14/pci-dra7xx-fix-legacy-intd-irq-handling.patch new file mode 100644 index 00000000000..b9ea0bcd8ef --- /dev/null +++ b/queue-4.14/pci-dra7xx-fix-legacy-intd-irq-handling.patch @@ -0,0 +1,51 @@ +From 524d59f6e30aab5b618da55e604c802ccd83e708 Mon Sep 17 00:00:00 2001 +From: Vignesh R +Date: Fri, 29 Dec 2017 17:11:30 +0530 +Subject: PCI: dra7xx: Fix legacy INTD IRQ handling + +From: Vignesh R + +commit 524d59f6e30aab5b618da55e604c802ccd83e708 upstream. + +Legacy INTD IRQ handling is broken on dra7xx due to fact that driver +uses hwirq in range of 1-4 for INTA, INTD whereas IRQ domain is of size +4 which is numbered 0-3. Therefore when INTD IRQ line is used with +pci-dra7xx driver following warning is seen: + + WARNING: CPU: 0 PID: 1 at kernel/irq/irqdomain.c:342 irq_domain_associate+0x12c/0x1c4 + error: hwirq 0x4 is too large for dummy + +Fix this by using pci_irqd_intx_xlate() helper to translate the INTx 1-4 +range into the 0-3 as done in other PCIe drivers. + +Suggested-by: Bjorn Helgaas +Reported-by: Chris Welch +Signed-off-by: Vignesh R +Signed-off-by: Lorenzo Pieralisi +Acked-by: Kishon Vijay Abraham I +Signed-off-by: Mathieu Poirier +Signed-off-by: Greg Kroah-Hartman + +--- + drivers/pci/dwc/pci-dra7xx.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/pci/dwc/pci-dra7xx.c ++++ b/drivers/pci/dwc/pci-dra7xx.c +@@ -227,6 +227,7 @@ static int dra7xx_pcie_intx_map(struct i + + static const struct irq_domain_ops intx_domain_ops = { + .map = dra7xx_pcie_intx_map, ++ .xlate = pci_irqd_intx_xlate, + }; + + static int dra7xx_pcie_init_irq_domain(struct pcie_port *pp) +@@ -270,7 +271,7 @@ static irqreturn_t dra7xx_pcie_msi_irq_h + case INTC: + case INTD: + generic_handle_irq(irq_find_mapping(dra7xx->irq_domain, +- ffs(reg))); ++ ffs(reg) - 1)); + break; + } + diff --git a/queue-4.14/series b/queue-4.14/series index d26f7116cb1..81098b89983 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -4,3 +4,7 @@ alsa-hda-realtek-fix-the-problem-of-two-front-mics-on-a-thinkcentre.patch sched-fair-don-t-assign-runtime-for-throttled-cfs_rq.patch drm-vmwgfx-fix-double-free-in-vmw_recv_msg.patch powerpc-tm-fix-fp-vmx-unavailable-exceptions-inside-a-transaction.patch +xfrm-clean-up-xfrm-protocol-checks.patch +ip6-fix-skb-leak-in-ip6frag_expire_frag_queue.patch +pci-designware-ep-fix-find_first_zero_bit-usage.patch +pci-dra7xx-fix-legacy-intd-irq-handling.patch diff --git a/queue-4.14/xfrm-clean-up-xfrm-protocol-checks.patch b/queue-4.14/xfrm-clean-up-xfrm-protocol-checks.patch new file mode 100644 index 00000000000..40ccee323c2 --- /dev/null +++ b/queue-4.14/xfrm-clean-up-xfrm-protocol-checks.patch @@ -0,0 +1,116 @@ +From dbb2483b2a46fbaf833cfb5deb5ed9cace9c7399 Mon Sep 17 00:00:00 2001 +From: Cong Wang +Date: Fri, 22 Mar 2019 16:26:19 -0700 +Subject: xfrm: clean up xfrm protocol checks + +From: Cong Wang + +commit dbb2483b2a46fbaf833cfb5deb5ed9cace9c7399 upstream. + +In commit 6a53b7593233 ("xfrm: check id proto in validate_tmpl()") +I introduced a check for xfrm protocol, but according to Herbert +IPSEC_PROTO_ANY should only be used as a wildcard for lookup, so +it should be removed from validate_tmpl(). + +And, IPSEC_PROTO_ANY is expected to only match 3 IPSec-specific +protocols, this is why xfrm_state_flush() could still miss +IPPROTO_ROUTING, which leads that those entries are left in +net->xfrm.state_all before exit net. Fix this by replacing +IPSEC_PROTO_ANY with zero. + +This patch also extracts the check from validate_tmpl() to +xfrm_id_proto_valid() and uses it in parse_ipsecrequest(). +With this, no other protocols should be added into xfrm. + +Fixes: 6a53b7593233 ("xfrm: check id proto in validate_tmpl()") +Reported-by: syzbot+0bf0519d6e0de15914fe@syzkaller.appspotmail.com +Cc: Steffen Klassert +Cc: Herbert Xu +Signed-off-by: Cong Wang +Acked-by: Herbert Xu +Signed-off-by: Steffen Klassert +Signed-off-by: Zubin Mithra +Signed-off-by: Greg Kroah-Hartman + +--- + include/net/xfrm.h | 17 +++++++++++++++++ + net/key/af_key.c | 4 +++- + net/xfrm/xfrm_state.c | 2 +- + net/xfrm/xfrm_user.c | 14 +------------- + 4 files changed, 22 insertions(+), 15 deletions(-) + +--- a/include/net/xfrm.h ++++ b/include/net/xfrm.h +@@ -1366,6 +1366,23 @@ static inline int xfrm_state_kern(const + return atomic_read(&x->tunnel_users); + } + ++static inline bool xfrm_id_proto_valid(u8 proto) ++{ ++ switch (proto) { ++ case IPPROTO_AH: ++ case IPPROTO_ESP: ++ case IPPROTO_COMP: ++#if IS_ENABLED(CONFIG_IPV6) ++ case IPPROTO_ROUTING: ++ case IPPROTO_DSTOPTS: ++#endif ++ return true; ++ default: ++ return false; ++ } ++} ++ ++/* IPSEC_PROTO_ANY only matches 3 IPsec protocols, 0 could match all. */ + static inline int xfrm_id_proto_match(u8 proto, u8 userproto) + { + return (!userproto || proto == userproto || +--- a/net/key/af_key.c ++++ b/net/key/af_key.c +@@ -1951,8 +1951,10 @@ parse_ipsecrequest(struct xfrm_policy *x + + if (rq->sadb_x_ipsecrequest_mode == 0) + return -EINVAL; ++ if (!xfrm_id_proto_valid(rq->sadb_x_ipsecrequest_proto)) ++ return -EINVAL; + +- t->id.proto = rq->sadb_x_ipsecrequest_proto; /* XXX check proto */ ++ t->id.proto = rq->sadb_x_ipsecrequest_proto; + if ((mode = pfkey_mode_to_xfrm(rq->sadb_x_ipsecrequest_mode)) < 0) + return -EINVAL; + t->mode = mode; +--- a/net/xfrm/xfrm_state.c ++++ b/net/xfrm/xfrm_state.c +@@ -2330,7 +2330,7 @@ void xfrm_state_fini(struct net *net) + unsigned int sz; + + flush_work(&net->xfrm.state_hash_work); +- xfrm_state_flush(net, IPSEC_PROTO_ANY, false); ++ xfrm_state_flush(net, 0, false); + flush_work(&xfrm_state_gc_work); + + WARN_ON(!list_empty(&net->xfrm.state_all)); +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -1489,20 +1489,8 @@ static int validate_tmpl(int nr, struct + return -EINVAL; + } + +- switch (ut[i].id.proto) { +- case IPPROTO_AH: +- case IPPROTO_ESP: +- case IPPROTO_COMP: +-#if IS_ENABLED(CONFIG_IPV6) +- case IPPROTO_ROUTING: +- case IPPROTO_DSTOPTS: +-#endif +- case IPSEC_PROTO_ANY: +- break; +- default: ++ if (!xfrm_id_proto_valid(ut[i].id.proto)) + return -EINVAL; +- } +- + } + + return 0;