--- /dev/null
+From ede95a63b5e84ddeea6b0c473b36ab8bfd8c6ce3 Mon Sep 17 00:00:00 2001
+From: Daniel Borkmann <daniel@iogearbox.net>
+Date: Tue, 23 Oct 2018 01:11:04 +0200
+Subject: bpf: add bpf_jit_limit knob to restrict unpriv allocations
+
+From: Daniel Borkmann <daniel@iogearbox.net>
+
+commit ede95a63b5e84ddeea6b0c473b36ab8bfd8c6ce3 upstream.
+
+Rick reported that the BPF JIT could potentially fill the entire module
+space with BPF programs from unprivileged users which would prevent later
+attempts to load normal kernel modules or privileged BPF programs, for
+example. If JIT was enabled but unsuccessful to generate the image, then
+before commit 290af86629b2 ("bpf: introduce BPF_JIT_ALWAYS_ON config")
+we would always fall back to the BPF interpreter. Nowadays in the case
+where the CONFIG_BPF_JIT_ALWAYS_ON could be set, then the load will abort
+with a failure since the BPF interpreter was compiled out.
+
+Add a global limit and enforce it for unprivileged users such that in case
+of BPF interpreter compiled out we fail once the limit has been reached
+or we fall back to BPF interpreter earlier w/o using module mem if latter
+was compiled in. In a next step, fair share among unprivileged users can
+be resolved in particular for the case where we would fail hard once limit
+is reached.
+
+Fixes: 290af86629b2 ("bpf: introduce BPF_JIT_ALWAYS_ON config")
+Fixes: 0a14842f5a3c ("net: filter: Just In Time compiler for x86-64")
+Co-Developed-by: Rick Edgecombe <rick.p.edgecombe@intel.com>
+Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
+Acked-by: Alexei Starovoitov <ast@kernel.org>
+Cc: Eric Dumazet <eric.dumazet@gmail.com>
+Cc: Jann Horn <jannh@google.com>
+Cc: Kees Cook <keescook@chromium.org>
+Cc: LKML <linux-kernel@vger.kernel.org>
+Signed-off-by: Alexei Starovoitov <ast@kernel.org>
+Cc: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ Documentation/sysctl/net.txt | 8 +++++++
+ include/linux/filter.h | 1
+ kernel/bpf/core.c | 49 ++++++++++++++++++++++++++++++++++++++++---
+ net/core/sysctl_net_core.c | 10 +++++++-
+ 4 files changed, 63 insertions(+), 5 deletions(-)
+
+--- a/Documentation/sysctl/net.txt
++++ b/Documentation/sysctl/net.txt
+@@ -92,6 +92,14 @@ Values :
+ 0 - disable JIT kallsyms export (default value)
+ 1 - enable JIT kallsyms export for privileged users only
+
++bpf_jit_limit
++-------------
++
++This enforces a global limit for memory allocations to the BPF JIT
++compiler in order to reject unprivileged JIT requests once it has
++been surpassed. bpf_jit_limit contains the value of the global limit
++in bytes.
++
+ dev_weight
+ --------------
+
+--- a/include/linux/filter.h
++++ b/include/linux/filter.h
+@@ -836,6 +836,7 @@ bpf_run_sk_reuseport(struct sock_reusepo
+ extern int bpf_jit_enable;
+ extern int bpf_jit_harden;
+ extern int bpf_jit_kallsyms;
++extern int bpf_jit_limit;
+
+ typedef void (*bpf_jit_fill_hole_t)(void *area, unsigned int size);
+
+--- a/kernel/bpf/core.c
++++ b/kernel/bpf/core.c
+@@ -366,10 +366,13 @@ void bpf_prog_kallsyms_del_all(struct bp
+ }
+
+ #ifdef CONFIG_BPF_JIT
++# define BPF_JIT_LIMIT_DEFAULT (PAGE_SIZE * 40000)
++
+ /* All BPF JIT sysctl knobs here. */
+ int bpf_jit_enable __read_mostly = IS_BUILTIN(CONFIG_BPF_JIT_ALWAYS_ON);
+ int bpf_jit_harden __read_mostly;
+ int bpf_jit_kallsyms __read_mostly;
++int bpf_jit_limit __read_mostly = BPF_JIT_LIMIT_DEFAULT;
+
+ static __always_inline void
+ bpf_get_prog_addr_region(const struct bpf_prog *prog,
+@@ -578,27 +581,64 @@ int bpf_get_kallsym(unsigned int symnum,
+ return ret;
+ }
+
++static atomic_long_t bpf_jit_current;
++
++#if defined(MODULES_VADDR)
++static int __init bpf_jit_charge_init(void)
++{
++ /* Only used as heuristic here to derive limit. */
++ bpf_jit_limit = min_t(u64, round_up((MODULES_END - MODULES_VADDR) >> 2,
++ PAGE_SIZE), INT_MAX);
++ return 0;
++}
++pure_initcall(bpf_jit_charge_init);
++#endif
++
++static int bpf_jit_charge_modmem(u32 pages)
++{
++ if (atomic_long_add_return(pages, &bpf_jit_current) >
++ (bpf_jit_limit >> PAGE_SHIFT)) {
++ if (!capable(CAP_SYS_ADMIN)) {
++ atomic_long_sub(pages, &bpf_jit_current);
++ return -EPERM;
++ }
++ }
++
++ return 0;
++}
++
++static void bpf_jit_uncharge_modmem(u32 pages)
++{
++ atomic_long_sub(pages, &bpf_jit_current);
++}
++
+ struct bpf_binary_header *
+ bpf_jit_binary_alloc(unsigned int proglen, u8 **image_ptr,
+ unsigned int alignment,
+ bpf_jit_fill_hole_t bpf_fill_ill_insns)
+ {
+ struct bpf_binary_header *hdr;
+- unsigned int size, hole, start;
++ u32 size, hole, start, pages;
+
+ /* Most of BPF filters are really small, but if some of them
+ * fill a page, allow at least 128 extra bytes to insert a
+ * random section of illegal instructions.
+ */
+ size = round_up(proglen + sizeof(*hdr) + 128, PAGE_SIZE);
++ pages = size / PAGE_SIZE;
++
++ if (bpf_jit_charge_modmem(pages))
++ return NULL;
+ hdr = module_alloc(size);
+- if (hdr == NULL)
++ if (!hdr) {
++ bpf_jit_uncharge_modmem(pages);
+ return NULL;
++ }
+
+ /* Fill space with illegal/arch-dep instructions. */
+ bpf_fill_ill_insns(hdr, size);
+
+- hdr->pages = size / PAGE_SIZE;
++ hdr->pages = pages;
+ hole = min_t(unsigned int, size - (proglen + sizeof(*hdr)),
+ PAGE_SIZE - sizeof(*hdr));
+ start = (get_random_int() % hole) & ~(alignment - 1);
+@@ -611,7 +651,10 @@ bpf_jit_binary_alloc(unsigned int progle
+
+ void bpf_jit_binary_free(struct bpf_binary_header *hdr)
+ {
++ u32 pages = hdr->pages;
++
+ module_memfree(hdr);
++ bpf_jit_uncharge_modmem(pages);
+ }
+
+ /* This symbol is only overridden by archs that have different
+--- a/net/core/sysctl_net_core.c
++++ b/net/core/sysctl_net_core.c
+@@ -279,7 +279,6 @@ static int proc_dointvec_minmax_bpf_enab
+ return ret;
+ }
+
+-# ifdef CONFIG_HAVE_EBPF_JIT
+ static int
+ proc_dointvec_minmax_bpf_restricted(struct ctl_table *table, int write,
+ void __user *buffer, size_t *lenp,
+@@ -290,7 +289,6 @@ proc_dointvec_minmax_bpf_restricted(stru
+
+ return proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+ }
+-# endif
+ #endif
+
+ static struct ctl_table net_core_table[] = {
+@@ -397,6 +395,14 @@ static struct ctl_table net_core_table[]
+ .extra2 = &one,
+ },
+ # endif
++ {
++ .procname = "bpf_jit_limit",
++ .data = &bpf_jit_limit,
++ .maxlen = sizeof(int),
++ .mode = 0600,
++ .proc_handler = proc_dointvec_minmax_bpf_restricted,
++ .extra1 = &one,
++ },
+ #endif
+ {
+ .procname = "netdev_tstamp_prequeue",
--- /dev/null
+From a4176ec356c73a46c07c181c6d04039fafa34a9f Mon Sep 17 00:00:00 2001
+From: Arend van Spriel <arend.vanspriel@broadcom.com>
+Date: Thu, 14 Feb 2019 13:43:48 +0100
+Subject: brcmfmac: add subtype check for event handling in data path
+
+From: Arend van Spriel <arend.vanspriel@broadcom.com>
+
+commit a4176ec356c73a46c07c181c6d04039fafa34a9f upstream.
+
+For USB there is no separate channel being used to pass events
+from firmware to the host driver and as such are passed over the
+data path. In order to detect mock event messages an additional
+check is needed on event subtype. This check is added conditionally
+using unlikely() keyword.
+
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Cc: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c | 5 ++--
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h | 16 ++++++++++----
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 2 -
+ 3 files changed, 16 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+@@ -464,7 +464,8 @@ void brcmf_rx_frame(struct device *dev,
+ } else {
+ /* Process special event packets */
+ if (handle_event)
+- brcmf_fweh_process_skb(ifp->drvr, skb);
++ brcmf_fweh_process_skb(ifp->drvr, skb,
++ BCMILCP_SUBTYPE_VENDOR_LONG);
+
+ brcmf_netif_rx(ifp, skb);
+ }
+@@ -481,7 +482,7 @@ void brcmf_rx_event(struct device *dev,
+ if (brcmf_rx_hdrpull(drvr, skb, &ifp))
+ return;
+
+- brcmf_fweh_process_skb(ifp->drvr, skb);
++ brcmf_fweh_process_skb(ifp->drvr, skb, 0);
+ brcmu_pkt_buf_free_skb(skb);
+ }
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
+@@ -211,7 +211,7 @@ enum brcmf_fweh_event_code {
+ */
+ #define BRCM_OUI "\x00\x10\x18"
+ #define BCMILCP_BCM_SUBTYPE_EVENT 1
+-
++#define BCMILCP_SUBTYPE_VENDOR_LONG 32769
+
+ /**
+ * struct brcm_ethhdr - broadcom specific ether header.
+@@ -334,10 +334,10 @@ void brcmf_fweh_process_event(struct brc
+ void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing);
+
+ static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
+- struct sk_buff *skb)
++ struct sk_buff *skb, u16 stype)
+ {
+ struct brcmf_event *event_packet;
+- u16 usr_stype;
++ u16 subtype, usr_stype;
+
+ /* only process events when protocol matches */
+ if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL))
+@@ -346,8 +346,16 @@ static inline void brcmf_fweh_process_sk
+ if ((skb->len + ETH_HLEN) < sizeof(*event_packet))
+ return;
+
+- /* check for BRCM oui match */
+ event_packet = (struct brcmf_event *)skb_mac_header(skb);
++
++ /* check subtype if needed */
++ if (unlikely(stype)) {
++ subtype = get_unaligned_be16(&event_packet->hdr.subtype);
++ if (subtype != stype)
++ return;
++ }
++
++ /* check for BRCM oui match */
+ if (memcmp(BRCM_OUI, &event_packet->hdr.oui[0],
+ sizeof(event_packet->hdr.oui)))
+ return;
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+@@ -1116,7 +1116,7 @@ static void brcmf_msgbuf_process_event(s
+
+ skb->protocol = eth_type_trans(skb, ifp->ndev);
+
+- brcmf_fweh_process_skb(ifp->drvr, skb);
++ brcmf_fweh_process_skb(ifp->drvr, skb, 0);
+
+ exit:
+ brcmu_pkt_buf_free_skb(skb);
--- /dev/null
+From 1b5e2423164b3670e8bc9174e4762d297990deff Mon Sep 17 00:00:00 2001
+From: Arend van Spriel <arend.vanspriel@broadcom.com>
+Date: Thu, 14 Feb 2019 13:43:47 +0100
+Subject: brcmfmac: assure SSID length from firmware is limited
+
+From: Arend van Spriel <arend.vanspriel@broadcom.com>
+
+commit 1b5e2423164b3670e8bc9174e4762d297990deff upstream.
+
+The SSID length as received from firmware should not exceed
+IEEE80211_MAX_SSID_LEN as that would result in heap overflow.
+
+Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
+Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
+Reviewed-by: Franky Lin <franky.lin@broadcom.com>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+Cc: Ben Hutchings <ben.hutchings@codethink.co.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+@@ -3466,6 +3466,8 @@ brcmf_wowl_nd_results(struct brcmf_if *i
+ }
+
+ netinfo = brcmf_get_netinfo_array(pfn_result);
++ if (netinfo->SSID_len > IEEE80211_MAX_SSID_LEN)
++ netinfo->SSID_len = IEEE80211_MAX_SSID_LEN;
+ memcpy(cfg->wowl.nd->ssid.ssid, netinfo->SSID, netinfo->SSID_len);
+ cfg->wowl.nd->ssid.ssid_len = netinfo->SSID_len;
+ cfg->wowl.nd->n_channels = 1;