netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net 0/3] net/sched: act_ipt bug fixes
@ 2023-06-07 14:59 Florian Westphal
  2023-06-07 14:59 ` [PATCH net 1/3] net/sched: act_ipt: add sanity checks on table name and hook locations Florian Westphal
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Florian Westphal @ 2023-06-07 14:59 UTC (permalink / raw)
  To: netdev; +Cc: jhs, xiyou.wangcong, jiri, Florian Westphal

While checking if netfilter could be updated to replace selected
instances of NF_DROP with kfree_skb_reason+NF_STOLEN to improve
debugging info via drop monitor I found that act_ipt is incompatible
with such an approach.  Moreover, it lacks multiple sanity checks
to avoid certain code paths that make assumptions that the tc layer
doesn't meet, such as header sanity checks, availability of skb_dst,
skb_nfct() and so on.

act_ipt test in the tc selftest still pass with this applied.

I think that we should consider removal of this module, while
this should take care of all problems, its ipv4 only and I don't
think there are any netfilter targets that lack a native tc
equivalent, even when ignoring bpf.

Florian Westphal (3):
  net/sched: act_ipt: add sanity checks on table name and hook locations
  net/sched: act_ipt: add sanity checks on skb before calling target
  net/sched: act_ipt: zero skb->cb before calling target

 net/sched/act_ipt.c | 70 ++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 63 insertions(+), 7 deletions(-)

-- 
2.39.3


^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH net 1/3] net/sched: act_ipt: add sanity checks on table name and hook locations
  2023-06-07 14:59 [PATCH net 0/3] net/sched: act_ipt bug fixes Florian Westphal
@ 2023-06-07 14:59 ` Florian Westphal
  2023-06-08 10:44   ` Simon Horman
  2023-06-07 14:59 ` [PATCH net 2/3] net/sched: act_ipt: add sanity checks on skb before calling target Florian Westphal
  2023-06-07 14:59 ` [PATCH net 3/3] net/sched: act_ipt: zero skb->cb " Florian Westphal
  2 siblings, 1 reply; 9+ messages in thread
From: Florian Westphal @ 2023-06-07 14:59 UTC (permalink / raw)
  To: netdev; +Cc: jhs, xiyou.wangcong, jiri, Florian Westphal

Looks like "tc" hard-codes "mangle" as the only supported table
name, but on kernel side there are no checks.

This is wrong.  Not all xtables targets are safe to call from tc.
E.g. "nat" targets assume skb has a conntrack object assigned to it.
Normally those get called from netfilter nat core which consults the
nat table to obtain the address mapping.

"tc" userspace either sets PRE or POSTROUTING as hook number, but there
is no validation of this on kernel side, so update netlink policy to
reject bogus numbers.  Some targets may assume skb_dst is set for
input/forward hooks, so prevent those from being used.

act_ipt uses the hook number in two places:
1. the state hook number, this is fine as-is
2. to set par.hook_mask

The latter is a bit mask, so update the assignment to make
xt_check_target() to the right thing.

Followup patch adds required checks for the skb/packet headers before
calling the targets evaluation function.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/sched/act_ipt.c | 27 ++++++++++++++++++++-------
 1 file changed, 20 insertions(+), 7 deletions(-)

diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 5d96ffebd40f..ea7f151e7dd2 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -48,7 +48,7 @@ static int ipt_init_target(struct net *net, struct xt_entry_target *t,
 	par.entryinfo = &e;
 	par.target    = target;
 	par.targinfo  = t->data;
-	par.hook_mask = hook;
+	par.hook_mask = 1 << hook;
 	par.family    = NFPROTO_IPV4;
 
 	ret = xt_check_target(&par, t->u.target_size - sizeof(*t), 0, false);
@@ -85,7 +85,8 @@ static void tcf_ipt_release(struct tc_action *a)
 
 static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = {
 	[TCA_IPT_TABLE]	= { .type = NLA_STRING, .len = IFNAMSIZ },
-	[TCA_IPT_HOOK]	= { .type = NLA_U32 },
+	[TCA_IPT_HOOK]	= NLA_POLICY_RANGE(NLA_U32, NF_INET_PRE_ROUTING,
+					   NF_INET_NUMHOOKS),
 	[TCA_IPT_INDEX]	= { .type = NLA_U32 },
 	[TCA_IPT_TARG]	= { .len = sizeof(struct xt_entry_target) },
 };
@@ -158,15 +159,27 @@ static int __tcf_ipt_init(struct net *net, unsigned int id, struct nlattr *nla,
 			return -EEXIST;
 		}
 	}
+
+	err = -EINVAL;
 	hook = nla_get_u32(tb[TCA_IPT_HOOK]);
+	switch (hook) {
+	case NF_INET_PRE_ROUTING:
+		break;
+	case NF_INET_POST_ROUTING:
+		break;
+	default:
+		goto err1;
+	}
+
+	if (tb[TCA_IPT_TABLE]) {
+		/* mangle only for now */
+		if (nla_strcmp(tb[TCA_IPT_TABLE], "mangle"))
+			goto err1;
+	}
 
-	err = -ENOMEM;
-	tname = kmalloc(IFNAMSIZ, GFP_KERNEL);
+	tname = kstrdup("mangle", GFP_KERNEL);
 	if (unlikely(!tname))
 		goto err1;
-	if (tb[TCA_IPT_TABLE] == NULL ||
-	    nla_strscpy(tname, tb[TCA_IPT_TABLE], IFNAMSIZ) >= IFNAMSIZ)
-		strcpy(tname, "mangle");
 
 	t = kmemdup(td, td->u.target_size, GFP_KERNEL);
 	if (unlikely(!t))
-- 
2.39.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH net 2/3] net/sched: act_ipt: add sanity checks on skb before calling target
  2023-06-07 14:59 [PATCH net 0/3] net/sched: act_ipt bug fixes Florian Westphal
  2023-06-07 14:59 ` [PATCH net 1/3] net/sched: act_ipt: add sanity checks on table name and hook locations Florian Westphal
@ 2023-06-07 14:59 ` Florian Westphal
  2023-06-08 10:44   ` Simon Horman
  2023-06-07 14:59 ` [PATCH net 3/3] net/sched: act_ipt: zero skb->cb " Florian Westphal
  2 siblings, 1 reply; 9+ messages in thread
From: Florian Westphal @ 2023-06-07 14:59 UTC (permalink / raw)
  To: netdev; +Cc: jhs, xiyou.wangcong, jiri, Florian Westphal

Netfilter targets make assumptions on the skb state, for example
iphdr is supposed to be in the linear area.

This is normally done by IP stack, but in act_ipt case no
such checks are made.

Some targets can even assume that skb_dst will be valid.
Make a minimum effort to check for this:

- Don't call the targets eval function for non-ipv4 skbs.
- Don't call the targets eval function for POSTROUTING
  emulation when the skb has no dst set.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/sched/act_ipt.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index ea7f151e7dd2..2f0b39cc4e37 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -230,6 +230,26 @@ static int tcf_xt_init(struct net *net, struct nlattr *nla,
 			      a, &act_xt_ops, tp, flags);
 }
 
+static bool tcf_ipt_act_check(struct sk_buff *skb)
+{
+	const struct iphdr *iph;
+	unsigned int nhoff, len;
+
+	if (!pskb_may_pull(skb, sizeof(struct iphdr)))
+		return false;
+
+	nhoff = skb_network_offset(skb);
+	iph = ip_hdr(skb);
+	if (iph->ihl < 5 || iph->version != 4)
+		return false;
+
+	len = skb_ip_totlen(skb);
+	if (skb->len < nhoff + len || len < (iph->ihl * 4u))
+		return false;
+
+	return pskb_may_pull(skb, iph->ihl * 4u);
+}
+
 TC_INDIRECT_SCOPE int tcf_ipt_act(struct sk_buff *skb,
 				  const struct tc_action *a,
 				  struct tcf_result *res)
@@ -244,9 +264,22 @@ TC_INDIRECT_SCOPE int tcf_ipt_act(struct sk_buff *skb,
 		.pf	= NFPROTO_IPV4,
 	};
 
+	if (skb->protocol != htons(ETH_P_IP))
+		return TC_ACT_UNSPEC;
+
 	if (skb_unclone(skb, GFP_ATOMIC))
 		return TC_ACT_UNSPEC;
 
+	if (!tcf_ipt_act_check(skb))
+		return TC_ACT_UNSPEC;
+
+	if (state.hook == NF_INET_POST_ROUTING) {
+		if (!skb_dst(skb))
+			return TC_ACT_UNSPEC;
+
+		state.out = skb->dev;
+	}
+
 	spin_lock(&ipt->tcf_lock);
 
 	tcf_lastuse_update(&ipt->tcf_tm);
-- 
2.39.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH net 3/3] net/sched: act_ipt: zero skb->cb before calling target
  2023-06-07 14:59 [PATCH net 0/3] net/sched: act_ipt bug fixes Florian Westphal
  2023-06-07 14:59 ` [PATCH net 1/3] net/sched: act_ipt: add sanity checks on table name and hook locations Florian Westphal
  2023-06-07 14:59 ` [PATCH net 2/3] net/sched: act_ipt: add sanity checks on skb before calling target Florian Westphal
@ 2023-06-07 14:59 ` Florian Westphal
  2023-06-08 10:45   ` Simon Horman
  2 siblings, 1 reply; 9+ messages in thread
From: Florian Westphal @ 2023-06-07 14:59 UTC (permalink / raw)
  To: netdev; +Cc: jhs, xiyou.wangcong, jiri, Florian Westphal

xtables relies on skb being owned by ip stack, i.e. with ipv4
check in place skb->cb is supposed to be IPCB.

I don't see an immediate problem (REJECT target cannot be used anymore
now that PRE/POSTROUTING hook validation has been fixed), but better be
safe than sorry.

A much better patch would be to either mark act_ipt as
"depends on BROKEN" or remove it altogether. I plan to do this
for -next in the near future.

This tc extension is broken in the sense that tc lacks an
equivalent of NF_STOLEN verdict.

With NF_STOLEN, target function takes complete ownership of skb, caller
cannot dereference it anymore.

ACT_STOLEN cannot be used for this: it has a different meaning, caller
is allowed to dereference the skb.

At this time NF_STOLEN won't be returned by any targets as far as I can
see, but this may change in the future.

It might be possible to work around this via explcit list of allowed
target extensions, that only return DROP or ACCEPT verdicts, but this
seems to be error prone.

Existing selftest only validates xt_LOG and act_ipt is restricted
to ipv4 so I don't think this action is used widely.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 net/sched/act_ipt.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 2f0b39cc4e37..ec04bcfa0f4b 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -21,6 +21,7 @@
 #include <linux/tc_act/tc_ipt.h>
 #include <net/tc_act/tc_ipt.h>
 #include <net/tc_wrapper.h>
+#include <net/ip.h>
 
 #include <linux/netfilter_ipv4/ip_tables.h>
 
@@ -254,6 +255,7 @@ TC_INDIRECT_SCOPE int tcf_ipt_act(struct sk_buff *skb,
 				  const struct tc_action *a,
 				  struct tcf_result *res)
 {
+	char saved_cb[sizeof_field(struct sk_buff, cb)];
 	int ret = 0, result = 0;
 	struct tcf_ipt *ipt = to_ipt(a);
 	struct xt_action_param par;
@@ -280,6 +282,8 @@ TC_INDIRECT_SCOPE int tcf_ipt_act(struct sk_buff *skb,
 		state.out = skb->dev;
 	}
 
+	memcpy(saved_cb, skb->cb, sizeof(saved_cb));
+
 	spin_lock(&ipt->tcf_lock);
 
 	tcf_lastuse_update(&ipt->tcf_tm);
@@ -292,6 +296,9 @@ TC_INDIRECT_SCOPE int tcf_ipt_act(struct sk_buff *skb,
 	par.state    = &state;
 	par.target   = ipt->tcfi_t->u.kernel.target;
 	par.targinfo = ipt->tcfi_t->data;
+
+	memset(IPCB(skb), 0, sizeof(struct inet_skb_parm));
+
 	ret = par.target->target(skb, &par);
 
 	switch (ret) {
@@ -312,6 +319,9 @@ TC_INDIRECT_SCOPE int tcf_ipt_act(struct sk_buff *skb,
 		break;
 	}
 	spin_unlock(&ipt->tcf_lock);
+
+	memcpy(skb->cb, saved_cb, sizeof(skb->cb));
+
 	return result;
 
 }
-- 
2.39.3


^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH net 1/3] net/sched: act_ipt: add sanity checks on table name and hook locations
  2023-06-07 14:59 ` [PATCH net 1/3] net/sched: act_ipt: add sanity checks on table name and hook locations Florian Westphal
@ 2023-06-08 10:44   ` Simon Horman
  2023-06-08 13:57     ` Florian Westphal
  0 siblings, 1 reply; 9+ messages in thread
From: Simon Horman @ 2023-06-08 10:44 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netdev, jhs, xiyou.wangcong, jiri

On Wed, Jun 07, 2023 at 04:59:52PM +0200, Florian Westphal wrote:
> Looks like "tc" hard-codes "mangle" as the only supported table
> name, but on kernel side there are no checks.
> 
> This is wrong.  Not all xtables targets are safe to call from tc.
> E.g. "nat" targets assume skb has a conntrack object assigned to it.
> Normally those get called from netfilter nat core which consults the
> nat table to obtain the address mapping.
> 
> "tc" userspace either sets PRE or POSTROUTING as hook number, but there
> is no validation of this on kernel side, so update netlink policy to
> reject bogus numbers.  Some targets may assume skb_dst is set for
> input/forward hooks, so prevent those from being used.
> 
> act_ipt uses the hook number in two places:
> 1. the state hook number, this is fine as-is
> 2. to set par.hook_mask
> 
> The latter is a bit mask, so update the assignment to make
> xt_check_target() to the right thing.
> 
> Followup patch adds required checks for the skb/packet headers before
> calling the targets evaluation function.
> 
> Signed-off-by: Florian Westphal <fw@strlen.de>

Hi Florian,

I think that patches for 'net' usually come with a fixes tag.
Likewise for the other patches in this series.

That aside, this looks good to me.

Reviewed-by: Simon Horman <simon.horman@corigine.com>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net 2/3] net/sched: act_ipt: add sanity checks on skb before calling target
  2023-06-07 14:59 ` [PATCH net 2/3] net/sched: act_ipt: add sanity checks on skb before calling target Florian Westphal
@ 2023-06-08 10:44   ` Simon Horman
  0 siblings, 0 replies; 9+ messages in thread
From: Simon Horman @ 2023-06-08 10:44 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netdev, jhs, xiyou.wangcong, jiri

On Wed, Jun 07, 2023 at 04:59:53PM +0200, Florian Westphal wrote:
> Netfilter targets make assumptions on the skb state, for example
> iphdr is supposed to be in the linear area.
> 
> This is normally done by IP stack, but in act_ipt case no
> such checks are made.
> 
> Some targets can even assume that skb_dst will be valid.
> Make a minimum effort to check for this:
> 
> - Don't call the targets eval function for non-ipv4 skbs.
> - Don't call the targets eval function for POSTROUTING
>   emulation when the skb has no dst set.
> 
> Signed-off-by: Florian Westphal <fw@strlen.de>

Reviewed-by: Simon Horman <simon.horman@corigine.com>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net 3/3] net/sched: act_ipt: zero skb->cb before calling target
  2023-06-07 14:59 ` [PATCH net 3/3] net/sched: act_ipt: zero skb->cb " Florian Westphal
@ 2023-06-08 10:45   ` Simon Horman
  0 siblings, 0 replies; 9+ messages in thread
From: Simon Horman @ 2023-06-08 10:45 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netdev, jhs, xiyou.wangcong, jiri

On Wed, Jun 07, 2023 at 04:59:54PM +0200, Florian Westphal wrote:
> xtables relies on skb being owned by ip stack, i.e. with ipv4
> check in place skb->cb is supposed to be IPCB.
> 
> I don't see an immediate problem (REJECT target cannot be used anymore
> now that PRE/POSTROUTING hook validation has been fixed), but better be
> safe than sorry.
> 
> A much better patch would be to either mark act_ipt as
> "depends on BROKEN" or remove it altogether. I plan to do this
> for -next in the near future.
> 
> This tc extension is broken in the sense that tc lacks an
> equivalent of NF_STOLEN verdict.
> 
> With NF_STOLEN, target function takes complete ownership of skb, caller
> cannot dereference it anymore.
> 
> ACT_STOLEN cannot be used for this: it has a different meaning, caller
> is allowed to dereference the skb.
> 
> At this time NF_STOLEN won't be returned by any targets as far as I can
> see, but this may change in the future.
> 
> It might be possible to work around this via explcit list of allowed

nit: explcit -> explicit

> target extensions, that only return DROP or ACCEPT verdicts, but this
> seems to be error prone.
> 
> Existing selftest only validates xt_LOG and act_ipt is restricted
> to ipv4 so I don't think this action is used widely.
> 
> Signed-off-by: Florian Westphal <fw@strlen.de>

Reviewed-by: Simon Horman <simon.horman@corigine.com>


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net 1/3] net/sched: act_ipt: add sanity checks on table name and hook locations
  2023-06-08 10:44   ` Simon Horman
@ 2023-06-08 13:57     ` Florian Westphal
  2023-06-08 16:44       ` Jamal Hadi Salim
  0 siblings, 1 reply; 9+ messages in thread
From: Florian Westphal @ 2023-06-08 13:57 UTC (permalink / raw)
  To: Simon Horman; +Cc: Florian Westphal, netdev, jhs, xiyou.wangcong, jiri

Simon Horman <simon.horman@corigine.com> wrote:
> I think that patches for 'net' usually come with a fixes tag.
> Likewise for the other patches in this series.

Right, I'll add
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH net 1/3] net/sched: act_ipt: add sanity checks on table name and hook locations
  2023-06-08 13:57     ` Florian Westphal
@ 2023-06-08 16:44       ` Jamal Hadi Salim
  0 siblings, 0 replies; 9+ messages in thread
From: Jamal Hadi Salim @ 2023-06-08 16:44 UTC (permalink / raw)
  To: Florian Westphal; +Cc: Simon Horman, netdev, xiyou.wangcong, jiri

On Thu, Jun 8, 2023 at 9:57 AM Florian Westphal <fw@strlen.de> wrote:
>
> Simon Horman <simon.horman@corigine.com> wrote:
> > I think that patches for 'net' usually come with a fixes tag.
> > Likewise for the other patches in this series.
>
> Right, I'll add
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")

If we want to be pedantic (not trying to be) that cannot be the
correct Fixes tag since some of these issues are a result of feature
additions to netfilter (post 2.6.12-rc2) . But it's ok to use that
tag.

cheers,
jamal

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2023-06-08 16:44 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-06-07 14:59 [PATCH net 0/3] net/sched: act_ipt bug fixes Florian Westphal
2023-06-07 14:59 ` [PATCH net 1/3] net/sched: act_ipt: add sanity checks on table name and hook locations Florian Westphal
2023-06-08 10:44   ` Simon Horman
2023-06-08 13:57     ` Florian Westphal
2023-06-08 16:44       ` Jamal Hadi Salim
2023-06-07 14:59 ` [PATCH net 2/3] net/sched: act_ipt: add sanity checks on skb before calling target Florian Westphal
2023-06-08 10:44   ` Simon Horman
2023-06-07 14:59 ` [PATCH net 3/3] net/sched: act_ipt: zero skb->cb " Florian Westphal
2023-06-08 10:45   ` Simon Horman

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).