Commit
fcb41decf6c6 ("config: enable some useful features on
!SMALL_FLASH devices") enabled netns, which in turn lead to the crash in
the flow offload target.
When the flow offloading framework intends to delete a flow from the
hardware table, it is necessary to retrieve the namespace from
nf_flowtable->ft_net. However, no one ever wrote the namespace into
nf_flowtable->ft_net in advance. So the framework will mistakenly use a
NULL namespace to execute dev_get_by_index_rcu(net, ifindex), leading to
the kernel panic.
Ref: FS#2321
Fixes: fcb41decf6c6 ("config: enable some useful features on !SMALL_FLASH devices")
Tested-by: Simon Tretter <simon@mediaarchitectu.re>
Signed-off-by: HsiuWen Yen <y.hsiuwen@gmail.com>
[merged patch into offload patch, fix for 4.19, SOB fix, commit subj/msg touches]
Signed-off-by: Petr Štetiar <ynezz@true.cz>
obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
--- /dev/null
+++ b/net/netfilter/xt_FLOWOFFLOAD.c
obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
--- /dev/null
+++ b/net/netfilter/xt_FLOWOFFLOAD.c
+/*
+ * Copyright (C) 2018 Felix Fietkau <nbd@nbd.name>
+ *
+/*
+ * Copyright (C) 2018 Felix Fietkau <nbd@nbd.name>
+ *
+flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+ const struct xt_flowoffload_target_info *info = par->targinfo;
+flowoffload_tg(struct sk_buff *skb, const struct xt_action_param *par)
+{
+ const struct xt_flowoffload_target_info *info = par->targinfo;
++ const struct nf_conn_help *help;
+ enum ip_conntrack_info ctinfo;
+ enum ip_conntrack_dir dir;
+ struct nf_flow_route route;
+ struct flow_offload *flow;
+ struct nf_conn *ct;
+ enum ip_conntrack_info ctinfo;
+ enum ip_conntrack_dir dir;
+ struct nf_flow_route route;
+ struct flow_offload *flow;
+ struct nf_conn *ct;
-+ const struct nf_conn_help *help;
+
+ if (xt_flowoffload_skip(skb))
+ return XT_CONTINUE;
+
+ if (xt_flowoffload_skip(skb))
+ return XT_CONTINUE;
+ xt_flowoffload_check_device(xt_in(par));
+ xt_flowoffload_check_device(xt_out(par));
+
+ xt_flowoffload_check_device(xt_in(par));
+ xt_flowoffload_check_device(xt_out(par));
+
++ net = read_pnet(&nf_flowtable.ft_net);
++ if (!net)
++ write_pnet(&nf_flowtable.ft_net, xt_net(par));
++
+ if (info->flags & XT_FLOWOFFLOAD_HW)
+ nf_flow_offload_hw_add(xt_net(par), flow, ct);
+
+ if (info->flags & XT_FLOWOFFLOAD_HW)
+ nf_flow_offload_hw_add(xt_net(par), flow, ct);
+
obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
--- /dev/null
+++ b/net/netfilter/xt_FLOWOFFLOAD.c
obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
--- /dev/null
+++ b/net/netfilter/xt_FLOWOFFLOAD.c
+/*
+ * Copyright (C) 2018 Felix Fietkau <nbd@nbd.name>
+ *
+/*
+ * Copyright (C) 2018 Felix Fietkau <nbd@nbd.name>
+ *
+ struct nf_flow_route route;
+ struct flow_offload *flow;
+ struct nf_conn *ct;
+ struct nf_flow_route route;
+ struct flow_offload *flow;
+ struct nf_conn *ct;
+
+ if (xt_flowoffload_skip(skb))
+ return XT_CONTINUE;
+
+ if (xt_flowoffload_skip(skb))
+ return XT_CONTINUE;
+ xt_flowoffload_check_device(xt_in(par));
+ xt_flowoffload_check_device(xt_out(par));
+
+ xt_flowoffload_check_device(xt_in(par));
+ xt_flowoffload_check_device(xt_out(par));
+
++ net = read_pnet(&nf_flowtable.ft_net);
++ if (!net)
++ write_pnet(&nf_flowtable.ft_net, xt_net(par));
++
+ if (info->flags & XT_FLOWOFFLOAD_HW)
+ nf_flow_offload_hw_add(xt_net(par), flow, ct);
+
+ if (info->flags & XT_FLOWOFFLOAD_HW)
+ nf_flow_offload_hw_add(xt_net(par), flow, ct);
+