All of lore.kernel.org
 help / color / mirror / Atom feed
From: Florian Westphal <fw@strlen.de>
To: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
Cc: netfilter-devel@vger.kernel.org, netdev@vger.kernel.org,
	Pablo Neira Ayuso <pablo@netfilter.org>
Subject: Re: [PATCH] netfilter: nf_tables: prevent OOB access in nft_byteorder_eval
Date: Wed, 5 Jul 2023 15:03:36 +0200	[thread overview]
Message-ID: <20230705130336.GD3751@breakpoint.cc> (raw)
In-Reply-To: <20230705121515.747251-1-cascardo@canonical.com>

Thadeu Lima de Souza Cascardo <cascardo@canonical.com> wrote:
> When evaluating byteorder expressions with size 2, a union with 32-bit and
> 16-bit members is used. Since the 16-bit members are aligned to 32-bit,
> the array accesses will be out-of-bounds.
> 
> It may lead to a stack-out-of-bounds access like the one below:

Yes, this is broken.

> Using simple s32 and s16 pointers for each of these accesses fixes the
> problem.

I'm not sure this is correct.  Its certainly less wrong of course.

> Fixes: 96518518cc41 ("netfilter: add nftables")
> Cc: stable@vger.kernel.org
> Reported-by: Tanguy DUBROCA (@SidewayRE) from @Synacktiv working with ZDI
> Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
> ---
>  net/netfilter/nft_byteorder.c | 17 ++++++++++-------
>  1 file changed, 10 insertions(+), 7 deletions(-)
> 
> diff --git a/net/netfilter/nft_byteorder.c b/net/netfilter/nft_byteorder.c
> index 9a85e797ed58..aa16bd2e92e2 100644
> --- a/net/netfilter/nft_byteorder.c
> +++ b/net/netfilter/nft_byteorder.c
> @@ -30,11 +30,14 @@ void nft_byteorder_eval(const struct nft_expr *expr,
>  	const struct nft_byteorder *priv = nft_expr_priv(expr);
>  	u32 *src = &regs->data[priv->sreg];
>  	u32 *dst = &regs->data[priv->dreg];
> -	union { u32 u32; u16 u16; } *s, *d;
> +	u32 *s32, *d32;
> +	u16 *s16, *d16;
>  	unsigned int i;
>  
> -	s = (void *)src;
> -	d = (void *)dst;
> +	s32 = (void *)src;
> +	d32 = (void *)dst;
> +	s16 = (void *)src;
> +	d16 = (void *)dst;
>  
>  	switch (priv->size) {
>  	case 8: {
> @@ -62,11 +65,11 @@ void nft_byteorder_eval(const struct nft_expr *expr,
>  		switch (priv->op) {
>  		case NFT_BYTEORDER_NTOH:
>  			for (i = 0; i < priv->len / 4; i++)
> -				d[i].u32 = ntohl((__force __be32)s[i].u32);
> +				d32[i] = ntohl((__force __be32)s32[i]);
>  			break;
>  		case NFT_BYTEORDER_HTON:
>  			for (i = 0; i < priv->len / 4; i++)
> -				d[i].u32 = (__force __u32)htonl(s[i].u32);
> +				d32[i] = (__force __u32)htonl(s32[i]);
>  			break;

Ack, this looks better, but I'd just use src[i] and dst[i] rather than
the weird union pointers the original has.

> @@ -74,11 +77,11 @@ void nft_byteorder_eval(const struct nft_expr *expr,
>  		switch (priv->op) {
>  		case NFT_BYTEORDER_NTOH:
>  			for (i = 0; i < priv->len / 2; i++)
> -				d[i].u16 = ntohs((__force __be16)s[i].u16);
> +				d16[i] = ntohs((__force __be16)s16[i]);

This on the other hand... I'd say this should mimic what the 64bit
case is doing and use nft_reg_store16() nft_reg_load16() helpers for
the register accesses.

something like:

for (i = 0; i < priv->len / 2; i++) {
     v16 = nft_reg_load16(&src[i]);
     nft_reg_store16(&dst[i], + ntohs((__force __be16)v16));
}

[ not even compile tested ]

Same for the htons case.

On a slightly related note, some of the nftables test cases create bogus
conversions, e.g.:

# src/nft --debug=netlink add rule ip6 t c 'ct mark set ip6 dscp << 2 |
# 0x10'
ip6 t c
  [ payload load 2b @ network header + 0 => reg 1 ]
  [ bitwise reg 1 = ( reg 1 & 0x0000c00f ) ^ 0x00000000 ]
  [ bitwise reg 1 = ( reg 1 >> 0x00000006 ) ]
  [ byteorder reg 1 = ntoh(reg 1, 2, 1) ]	// NO-OP! should be reg 1, 2, 2) I presume?

I'd suggest to add a patch for nf-next that rejects such crap.

  reply	other threads:[~2023-07-05 13:03 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-07-05 12:15 [PATCH] netfilter: nf_tables: prevent OOB access in nft_byteorder_eval Thadeu Lima de Souza Cascardo
2023-07-05 13:03 ` Florian Westphal [this message]
2023-07-05 13:50   ` Pablo Neira Ayuso
2023-07-05 18:17   ` Thadeu Lima de Souza Cascardo
2023-07-05 20:12     ` Florian Westphal
2023-07-05 21:05       ` [PATCH v2] " Thadeu Lima de Souza Cascardo
2023-07-05 21:29         ` Florian Westphal
2023-07-05 22:56         ` Pablo Neira Ayuso
2023-11-02 10:16         ` Dan Carpenter
2023-11-02 10:28           ` Florian Westphal
2023-11-02 12:27             ` Dan Carpenter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230705130336.GD3751@breakpoint.cc \
    --to=fw@strlen.de \
    --cc=cascardo@canonical.com \
    --cc=netdev@vger.kernel.org \
    --cc=netfilter-devel@vger.kernel.org \
    --cc=pablo@netfilter.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.