diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-20177/0001-netfilter-add-and-use-nf_hook_slow_list.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-20177/0001-netfilter-add-and-use-nf_hook_slow_list.patch | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-20177/0001-netfilter-add-and-use-nf_hook_slow_list.patch b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-20177/0001-netfilter-add-and-use-nf_hook_slow_list.patch new file mode 100644 index 000000000..8563d5cae --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-kernel/linux/linux-aspeed/CVE-2021-20177/0001-netfilter-add-and-use-nf_hook_slow_list.patch @@ -0,0 +1,119 @@ +From ca58fbe06c54795f00db79e447f94c2028d30124 Mon Sep 17 00:00:00 2001 +From: Florian Westphal <fw@strlen.de> +Date: Fri, 11 Oct 2019 00:30:37 +0200 +Subject: [PATCH] netfilter: add and use nf_hook_slow_list() + +At this time, NF_HOOK_LIST() macro will iterate the list and then calls +nf_hook() for each individual skb. + +This makes it so the entire list is passed into the netfilter core. +The advantage is that we only need to fetch the rule blob once per list +instead of per-skb. + +NF_HOOK_LIST now only works for ipv4 and ipv6, as those are the only +callers. + +v2: use skb_list_del_init() instead of list_del (Edward Cree) + +Signed-off-by: Florian Westphal <fw@strlen.de> +Acked-by: Edward Cree <ecree@solarflare.com> +Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> +--- + include/linux/netfilter.h | 41 +++++++++++++++++++++++++++++---------- + net/netfilter/core.c | 20 +++++++++++++++++++ + 2 files changed, 51 insertions(+), 10 deletions(-) + +diff --git a/include/linux/netfilter.h b/include/linux/netfilter.h +index 77ebb61faf48..eb312e7ca36e 100644 +--- a/include/linux/netfilter.h ++++ b/include/linux/netfilter.h +@@ -199,6 +199,8 @@ extern struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; + int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state, + const struct nf_hook_entries *e, unsigned int i); + ++void nf_hook_slow_list(struct list_head *head, struct nf_hook_state *state, ++ const struct nf_hook_entries *e); + /** + * nf_hook - call a netfilter hook + * +@@ -311,17 +313,36 @@ NF_HOOK_LIST(uint8_t pf, unsigned int hook, struct net *net, struct sock *sk, + struct list_head *head, struct net_device *in, struct net_device *out, + int (*okfn)(struct net *, struct sock *, struct sk_buff *)) + { +- struct sk_buff *skb, *next; +- struct list_head sublist; +- +- INIT_LIST_HEAD(&sublist); +- list_for_each_entry_safe(skb, next, head, list) { +- list_del(&skb->list); +- if (nf_hook(pf, hook, net, sk, skb, in, out, okfn) == 1) +- list_add_tail(&skb->list, &sublist); ++ struct nf_hook_entries *hook_head = NULL; ++ ++#ifdef CONFIG_JUMP_LABEL ++ if (__builtin_constant_p(pf) && ++ __builtin_constant_p(hook) && ++ !static_key_false(&nf_hooks_needed[pf][hook])) ++ return; ++#endif ++ ++ rcu_read_lock(); ++ switch (pf) { ++ case NFPROTO_IPV4: ++ hook_head = rcu_dereference(net->nf.hooks_ipv4[hook]); ++ break; ++ case NFPROTO_IPV6: ++ hook_head = rcu_dereference(net->nf.hooks_ipv6[hook]); ++ break; ++ default: ++ WARN_ON_ONCE(1); ++ break; + } +- /* Put passed packets back on main list */ +- list_splice(&sublist, head); ++ ++ if (hook_head) { ++ struct nf_hook_state state; ++ ++ nf_hook_state_init(&state, hook, pf, in, out, sk, net, okfn); ++ ++ nf_hook_slow_list(head, &state, hook_head); ++ } ++ rcu_read_unlock(); + } + + /* Call setsockopt() */ +diff --git a/net/netfilter/core.c b/net/netfilter/core.c +index 5d5bdf450091..78f046ec506f 100644 +--- a/net/netfilter/core.c ++++ b/net/netfilter/core.c +@@ -536,6 +536,26 @@ int nf_hook_slow(struct sk_buff *skb, struct nf_hook_state *state, + } + EXPORT_SYMBOL(nf_hook_slow); + ++void nf_hook_slow_list(struct list_head *head, struct nf_hook_state *state, ++ const struct nf_hook_entries *e) ++{ ++ struct sk_buff *skb, *next; ++ struct list_head sublist; ++ int ret; ++ ++ INIT_LIST_HEAD(&sublist); ++ ++ list_for_each_entry_safe(skb, next, head, list) { ++ skb_list_del_init(skb); ++ ret = nf_hook_slow(skb, state, e, 0); ++ if (ret == 1) ++ list_add_tail(&skb->list, &sublist); ++ } ++ /* Put passed packets back on main list */ ++ list_splice(&sublist, head); ++} ++EXPORT_SYMBOL(nf_hook_slow_list); ++ + /* This needs to be compiled in any case to avoid dependencies between the + * nfnetlink_queue code and nf_conntrack. + */ +-- +2.17.1 + |