All of lore.kernel.org
 help / color / mirror / Atom feed
* Raw Payload Expressions - out of bounds write?
@ 2025-01-23  3:31 Sunny73Cr
  2025-01-26 13:50 ` Florian Westphal
  0 siblings, 1 reply; 15+ messages in thread
From: Sunny73Cr @ 2025-01-23  3:31 UTC (permalink / raw)
  To: netfilter@vger.kernel.org

Hi,

Raw Payload Expressions - does this cause an out of bounds write?

1. Input configuration file (modification to /etc/nftables.conf):

chain output {
  type filter hook output priority filter;

  @ih,58,6 set 0 \
  @ih,86,6 set 0 \
  @ih,170,22 set 0 \
  accept;
}

2. run /etc/nftables.conf

3. Output ruleset (/usr/sbin/nft list rulset):

chain output {
 type filter hook output priority filter; policy accept;
 @ih,48,16 set @ih,48,16 & 0x3f \
 @ih,80,16 set @ih,80,16 & 0x3f0 \
 @ih,160,32 set @ih,160,32 @0x3fffff \
 accept;
}

The mask appears correct for the first re-write, but subsequent re-writes appear to be too large.

Please advise.

sunny

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

* Re: Raw Payload Expressions - out of bounds write?
  2025-01-23  3:31 Raw Payload Expressions - out of bounds write? Sunny73Cr
@ 2025-01-26 13:50 ` Florian Westphal
  2025-01-26 18:08   ` Sunny73Cr
  0 siblings, 1 reply; 15+ messages in thread
From: Florian Westphal @ 2025-01-26 13:50 UTC (permalink / raw)
  To: Sunny73Cr; +Cc: netfilter@vger.kernel.org

Sunny73Cr <Sunny73Cr@protonmail.com> wrote:
>   @ih,58,6 set 0 \
>   @ih,86,6 set 0 \
>   @ih,170,22 set 0 \

> 3. Output ruleset (/usr/sbin/nft list rulset):
> 
> chain output {
>  type filter hook output priority filter; policy accept;
>  @ih,48,16 set @ih,48,16 & 0x3f \
>  @ih,80,16 set @ih,80,16 & 0x3f0 \
>  @ih,160,32 set @ih,160,32 @0x3fffff \
>  accept;
> }
> 
> The mask appears correct for the first re-write, but subsequent re-writes appear to be too large.

What do you mean?
Please elaborate as what is wrong here in listing 3.

The nft interpreter cannot load individual bits,
the length/size has to be byte aligned.

6 bits from offset 86 straddles two bytes (bits 86-7,88-91).

22 from offset 170 touch 4 bytes: bits 168-169, 170-177, 178-185,
186-195.

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

* Re: Raw Payload Expressions - out of bounds write?
  2025-01-26 13:50 ` Florian Westphal
@ 2025-01-26 18:08   ` Sunny73Cr
  2025-01-28  0:37     ` Florian Westphal
  0 siblings, 1 reply; 15+ messages in thread
From: Sunny73Cr @ 2025-01-26 18:08 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netfilter@vger.kernel.org

> Please elaborate as what is wrong here in listing 3.

Within the second line of the rule (@ih,80,16 set @ih,80,16 & 0x3f0 \)

The mask 0x3f0 equates to 1,008 in decimal.
(3 * 16**2) + (15 * 16**1) + (0 * 16^0) = 1,008
Here '**' indicates exponent.

1,008 is far larger than the 34 bit range that I covered.
I understand that within NetFilter, there may be safeguards that which prevent writing beyond array bounds; but, that section of the rule still covers the bits that I did not wish to zero.

Apologies, but I have not checked the code as of yet.

sunny

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

* Re: Raw Payload Expressions - out of bounds write?
  2025-01-26 18:08   ` Sunny73Cr
@ 2025-01-28  0:37     ` Florian Westphal
  2025-01-28  4:19       ` Sunny73Cr
  2025-01-28 12:41       ` Pablo Neira Ayuso
  0 siblings, 2 replies; 15+ messages in thread
From: Florian Westphal @ 2025-01-28  0:37 UTC (permalink / raw)
  To: Sunny73Cr; +Cc: Florian Westphal, netfilter@vger.kernel.org

Sunny73Cr <Sunny73Cr@protonmail.com> wrote:
> > Please elaborate as what is wrong here in listing 3.
> 
> Within the second line of the rule (@ih,80,16 set @ih,80,16 & 0x3f0 \)
> 
> The mask 0x3f0 equates to 1,008 in decimal.
> (3 * 16**2) + (15 * 16**1) + (0 * 16^0) = 1,008
> Here '**' indicates exponent.
> 
> 1,008 is far larger than the 34 bit range that I covered.

Sigh.  Why did you not say something like:

The mask is provided as '0x3f0' in the listing, but I had expected
0xfc0f, as only 6 bits should be cleared, but the mask KEEPS 6 bits.

It would have saved me a headache figuring out bug you refer to.
I am not a mind reader :-/

Use --debug=netlink, it looks like its a display bug.

I'll have a look.

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

* Re: Raw Payload Expressions - out of bounds write?
  2025-01-28  0:37     ` Florian Westphal
@ 2025-01-28  4:19       ` Sunny73Cr
  2025-01-28 12:02         ` Jeremy Sowden
  2025-01-28 12:41       ` Pablo Neira Ayuso
  1 sibling, 1 reply; 15+ messages in thread
From: Sunny73Cr @ 2025-01-28  4:19 UTC (permalink / raw)
  To: Florian Westphal; +Cc: netfilter@vger.kernel.org


> ...but I had expected
> 0xfc0f...

I disagree with the proposed mask: the message is likely not 64,527 bits in length (0xfc0f -> decimal: 64,527).

> Use --debug=netlink

Apologies, I am not sure what this refers to: I assume it is a compilation argument; and I cannot recompile NetFilter as of yet.

I am using the `nft` command via '/etc/nftables.conf'; on an installation of the latest Debian 12.9 release. `/usr/sbin/nft -v` prints "nftables v1.0.6 (Lester Gooch #5)".

Debian CD Signing key fingerprint: DF9B9C49EAA9298432589D76DA87E80D6294BE9B
Debian 12 Bookwork release key fingerprint: 4D64FEC119C2029067D6E791F8D2585B8783D481

An example of the problem. Hopefully my explanation is easy to understand:

To match "Version 4" of IPv4 header, and to clear DSCP code point (DSCP isn't used on my network):

- At network header, bit offset 0, select the next 4 bits, and match the decimal value 4.
- At network header, bit offset 8, select the next 6 bits and set the value to 0.

@nh,0,4 0x4 \
@nh,8,6 set 0x0 \
accept;

Translates to:

@nh,0,8 & 0xf0 == 0x40 @nh,8,8 set @nh,8,8 & 0x7e accept

I view this as:

"Version and Internet Header Length, mask 240 bits, match a value of 64."
My issue: I did not match IHL before translation. The rule may cause dropped frames that I was not concerned with.

Then;

"DSCP, and ECN, set to the same value, covering 124 bits at some offset" (I am assuming the offset is @nh,8).
My issue: It has not set the bits to zero as I intended, and what to do if the bits selected (0x7e / 124 bits) is larger than the destination section to copy to (@nh8,8 / 8 bits at 8 bits from beginning of network header.)

I cannot be certain of the correct way to translate the rule given the 8-bit backing store restriction. If I am only concerned with 4 bits, then, in order for my rules to function, a mask of 4 bits must be valid.

I propose that a 'bit array' backing store may assist (though I sense that may reduce performance). Without a given socket buffer in memory; it is difficult to form the correct mask, where the mask must be larger than the selected bits.

I would love to assist, though, I haven't read the source code of NetFilter. It is possible that I suggest an incorrect change without reading the source.

sunny

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

* Re: Raw Payload Expressions - out of bounds write?
  2025-01-28  4:19       ` Sunny73Cr
@ 2025-01-28 12:02         ` Jeremy Sowden
  2025-01-28 12:12           ` Sunny73Cr
  0 siblings, 1 reply; 15+ messages in thread
From: Jeremy Sowden @ 2025-01-28 12:02 UTC (permalink / raw)
  To: Sunny73Cr; +Cc: Florian Westphal, netfilter@vger.kernel.org

[-- Attachment #1: Type: text/plain, Size: 565 bytes --]

On 2025-01-28, at 04:19:55 +0000, Sunny73Cr wrote:
> > Use --debug=netlink
> 
> Apologies, I am not sure what this refers to: I assume it is a
> compilation argument; and I cannot recompile NetFilter as of yet.

It's one of nft's command-line arguments.  From the man-page:

      -d, --debug level
           Enable debugging output. The debug level can be any of
           scanner, parser, eval, netlink, mnl, proto-ctx, segtree,
           all. You can combine more than one by separating by the ,
           symbol, for example -d eval,mnl.

J.

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 931 bytes --]

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

* Re: Raw Payload Expressions - out of bounds write?
  2025-01-28 12:02         ` Jeremy Sowden
@ 2025-01-28 12:12           ` Sunny73Cr
  0 siblings, 0 replies; 15+ messages in thread
From: Sunny73Cr @ 2025-01-28 12:12 UTC (permalink / raw)
  To: Jeremy Sowden; +Cc: Florian Westphal, netfilter@vger.kernel.org

Thank you! I text searched but skipped over it.

sunny

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

* Re: Raw Payload Expressions - out of bounds write?
  2025-01-28  0:37     ` Florian Westphal
  2025-01-28  4:19       ` Sunny73Cr
@ 2025-01-28 12:41       ` Pablo Neira Ayuso
  2025-01-30 11:27         ` Sunny73Cr
  1 sibling, 1 reply; 15+ messages in thread
From: Pablo Neira Ayuso @ 2025-01-28 12:41 UTC (permalink / raw)
  To: Florian Westphal; +Cc: Sunny73Cr, netfilter@vger.kernel.org

On Tue, Jan 28, 2025 at 01:37:06AM +0100, Florian Westphal wrote:
> Sunny73Cr <Sunny73Cr@protonmail.com> wrote:
> > > Please elaborate as what is wrong here in listing 3.
> > 
> > Within the second line of the rule (@ih,80,16 set @ih,80,16 & 0x3f0 \)
> > 
> > The mask 0x3f0 equates to 1,008 in decimal.
> > (3 * 16**2) + (15 * 16**1) + (0 * 16^0) = 1,008
> > Here '**' indicates exponent.
> > 
> > 1,008 is far larger than the 34 bit range that I covered.
> 
> Sigh.  Why did you not say something like:
> 
> The mask is provided as '0x3f0' in the listing, but I had expected
> 0xfc0f, as only 6 bits should be cleared, but the mask KEEPS 6 bits.
> 
> It would have saved me a headache figuring out bug you refer to.
> I am not a mind reader :-/
> 
> Use --debug=netlink, it looks like its a display bug.
> 
> I'll have a look.

It looks like netlink_delinearize is missing code to compact the
expression.

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

* Re: Raw Payload Expressions - out of bounds write?
  2025-01-28 12:41       ` Pablo Neira Ayuso
@ 2025-01-30 11:27         ` Sunny73Cr
  2025-02-08 20:26           ` Sunny73Cr
  0 siblings, 1 reply; 15+ messages in thread
From: Sunny73Cr @ 2025-01-30 11:27 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter@vger.kernel.org


I can't see the problem within the code.

Aside from the latter half of NTP timestamps, which expressions do not work?

sunny

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

* Re: Raw Payload Expressions - out of bounds write?
  2025-01-30 11:27         ` Sunny73Cr
@ 2025-02-08 20:26           ` Sunny73Cr
  2025-02-09  1:47             ` Florian Westphal
  0 siblings, 1 reply; 15+ messages in thread
From: Sunny73Cr @ 2025-02-08 20:26 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter@vger.kernel.org

Hi,

Apologies for my mistake in these threads. I think the title should read 'out of bounds read'.

I noticed there may be a floating point error or another miscellaneous approximation error when calculating the mask for raw payload expressions. It is somewhat related to this thread.

using nft -d all (debug all); I found:

inet filter output 5 4
[ payload load 2b @ inner header + 6 => reg 1 ]
[ bitwise reg 1 = ( reg 1 & 0x0000c0ff ) ^ 0x00000000 ]

After careful consideration, I realised that here; '2b' indicates two bytes, not two bits. I suggest it should read '2 Bytes'. Additionally, the "+ 6" section should really read as "+ 6 Bytes". "2B" or "6B" may get misread as 28, or 68; if the user makes a poor choice in font. Poor choice in font is not my concern, particularly; but fault-tolerant design is always nice.

Anyhow, with the alterations to expression; I can then match it (2 bytes, offset of 6 bytes) to the 'mangled' input of @ih,48,16

> [ bitwise reg 1 = ( reg 1 & 0x0000c0ff ) ^ 0x00000000 ]

Assuming that the mask is stored in a 32-bit integer field, the length of the string is fine. Otherwise, the mask of "0x0000c0ff" equates to 49,407 bits.
Since raw payload expression includes the starting position in payload expressions; it is really 49,408 bits to match.
Via empirical calculation, the closest base 2 logarithm I can find for 49,407 (bits) is approximately ~15.5924570373.
If the mask is intended to cover 16 bits; should it not equate to 65,535 bits; or "0x0000ffff".

Though, the intent was not to read and set the same value; rather, it was to redact 6 bits of data. Considering the intent of my input statement (@ih,58,6); I think the mask should be ((2^16) - (2^6)); or 65,472 in decimal; or 0xfff9 in hexadecimal.

This leaves us with an output statement of (little endian mask, as it seems is the case):

@ih,48,16 set @ih,48,16 & 0xfff9

The statement:

> [ bitwise reg 1 = ( reg 1 & 0x0000c0ff ) ^ 0x00000000 ]

Should then read:

> [ bitwise reg 1 = ( reg 1 & 0x0000fff9 ) ^ 0x00000000 ]

sunny

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

* Re: Raw Payload Expressions - out of bounds write?
  2025-02-08 20:26           ` Sunny73Cr
@ 2025-02-09  1:47             ` Florian Westphal
  2025-02-09  3:12               ` Sunny73Cr
  0 siblings, 1 reply; 15+ messages in thread
From: Florian Westphal @ 2025-02-09  1:47 UTC (permalink / raw)
  To: Sunny73Cr; +Cc: Pablo Neira Ayuso, Florian Westphal, netfilter@vger.kernel.org

Sunny73Cr <Sunny73Cr@protonmail.com> wrote:
> I noticed there may be a floating point error or another miscellaneous approximation error when calculating the mask for raw payload expressions. It is somewhat related to this thread.

There is no approximation.  And no floating point math is involved.

> using nft -d all (debug all); I found:
> 
> inet filter output 5 4
> [ payload load 2b @ inner header + 6 => reg 1 ]
> [ bitwise reg 1 = ( reg 1 & 0x0000c0ff ) ^ 0x00000000 ]
> 
> After careful consideration, I realised that here; '2b' indicates two bytes, not two bits. I suggest it should read '2 Bytes'. Additionally, the "+ 6" section should really read as "+ 6 Bytes". "2B" or "6B" may get misread as 28, or 68; if the user makes a poor choice in font. Poor choice in font is not my concern, particularly; but fault-tolerant design is always nice.
> 
> Anyhow, with the alterations to expression; I can then match it (2 bytes, offset of 6 bytes) to the 'mangled' input of @ih,48,16
> 
> > [ bitwise reg 1 = ( reg 1 & 0x0000c0ff ) ^ 0x00000000 ]
> 
> Assuming that the mask is stored in a 32-bit integer field, the length of the string is fine. Otherwise, the mask of "0x0000c0ff" equates to 49,407 bits.

0x0c0ff in decimal notation is 49407. But I do not know how "0x0000c0ff"
equates to "49407 bits".

> Since raw payload expression includes the starting position in payload expressions; it is really 49,408 bits to match.

I don't know what that is supposed to mean.

> Via empirical calculation, the closest base 2 logarithm I can find for 49,407 (bits) is approximately ~15.5924570373.
> If the mask is intended to cover 16 bits; should it not equate to 65,535 bits; or "0x0000ffff".
> 
> Though, the intent was not to read and set the same value; rather, it was to redact 6 bits of data. Considering the intent of my input statement (@ih,58,6); I think the mask should be ((2^16) - (2^6)); or 65,472 in decimal; or 0xfff9 in hexadecimal.

I have no idea what you mean.

The mask cannot be computed by ((2^16) - (2^6)).
The location (offset) matters, not just the amount of bits
to retain/zero out.

> This leaves us with an output statement of (little endian mask, as it seems is the case):
> 
> @ih,48,16 set @ih,48,16 & 0xfff9
>
> The statement:
> 
> > [ bitwise reg 1 = ( reg 1 & 0x0000c0ff ) ^ 0x00000000 ]
> 
> Should then read:
> 
> > [ bitwise reg 1 = ( reg 1 & 0x0000fff9 ) ^ 0x00000000 ]

That mask is 1111100111111111 which translates to '@ih,53,2 set ...'

Please show a real bug, i.e.:

1. the rule you made
2. a text explaining what you wanted the rule to do
3. a packet capture showing packet after mangling
4. a text explaing what yhe packet capture SHOULD have
   shown instead

else I will never be able to help.

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

* Re: Raw Payload Expressions - out of bounds write?
  2025-02-09  1:47             ` Florian Westphal
@ 2025-02-09  3:12               ` Sunny73Cr
  2025-02-09 22:23                 ` Pablo Neira Ayuso
  0 siblings, 1 reply; 15+ messages in thread
From: Sunny73Cr @ 2025-02-09  3:12 UTC (permalink / raw)
  To: Florian Westphal; +Cc: Pablo Neira Ayuso, netfilter@vger.kernel.org

Hi,

Still confusing, my bad. Here's what I'm looking for.

Input:
@ih,56,6 set 0

Expected output:
[ payload load 1 byte @ inner header + 6 bytes => reg 1 ]
[ bitwise reg 1 = ( reg 1 & 0xc0 ) ]
[ payload write reg 1 => 1 byte @ inner header + 6 bytes ... ]

I plan to propose a fix at some point, if possible.

sunny

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

* Re: Raw Payload Expressions - out of bounds write?
  2025-02-09  3:12               ` Sunny73Cr
@ 2025-02-09 22:23                 ` Pablo Neira Ayuso
  2025-02-09 22:45                   ` Sunny73Cr
  0 siblings, 1 reply; 15+ messages in thread
From: Pablo Neira Ayuso @ 2025-02-09 22:23 UTC (permalink / raw)
  To: Sunny73Cr; +Cc: Florian Westphal, netfilter@vger.kernel.org

On Sun, Feb 09, 2025 at 03:12:48AM +0000, Sunny73Cr wrote:
> Hi,
> 
> Still confusing, my bad. Here's what I'm looking for.
> 
> Input:
> @ih,56,6 set 0
         ^
this is in bits.

> Expected output:
> [ payload load 1 byte @ inner header + 6 bytes => reg 1 ]
> [ bitwise reg 1 = ( reg 1 & 0xc0 ) ]
> [ payload write reg 1 => 1 byte @ inner header + 6 bytes ... ]

and you use 6 bytes in this bytecode.

This makes no sense at all.

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

* Re: Raw Payload Expressions - out of bounds write?
  2025-02-09 22:23                 ` Pablo Neira Ayuso
@ 2025-02-09 22:45                   ` Sunny73Cr
  2025-12-02  5:22                     ` Sunny73Cr
  0 siblings, 1 reply; 15+ messages in thread
From: Sunny73Cr @ 2025-02-09 22:45 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter@vger.kernel.org

> this is in bits.

> [ payload load 1 byte @ inner header + 6 bytes => reg 1 ]
> [ bitwise reg 1 = ( reg 1 & 0xc0 ) ]
> [ payload write reg 1 => 1 byte @ inner header + 6 bytes ... ]

haha

[ payload load 1 byte (8 bits) @ inner header + 7 bytes (56 bits) => reg 1 ]
[ bitwise reg 1 = ( reg 1 & 0xc0 ) ]
[ payload write reg 1 => 1 byte (8 bits) @ inner header + 7 bytes (56 bits) ... ]

I suppose you are correct there, I forgot to adjust the offset.

sunny

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

* Re: Raw Payload Expressions - out of bounds write?
  2025-02-09 22:45                   ` Sunny73Cr
@ 2025-12-02  5:22                     ` Sunny73Cr
  0 siblings, 0 replies; 15+ messages in thread
From: Sunny73Cr @ 2025-12-02  5:22 UTC (permalink / raw)
  To: Pablo Neira Ayuso; +Cc: Florian Westphal, netfilter@vger.kernel.org

Hi all,

In regard to this chain; I would like to contribute code to the NetFilter project: what is the best way to exchange PGP keys?

sunny

SIGNATURE NOTICE: sunny_0xAD0EBA5C_public.asc
[KEY REDACTED, WE HAVE NOT MET]

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

end of thread, other threads:[~2025-12-02  5:22 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-23  3:31 Raw Payload Expressions - out of bounds write? Sunny73Cr
2025-01-26 13:50 ` Florian Westphal
2025-01-26 18:08   ` Sunny73Cr
2025-01-28  0:37     ` Florian Westphal
2025-01-28  4:19       ` Sunny73Cr
2025-01-28 12:02         ` Jeremy Sowden
2025-01-28 12:12           ` Sunny73Cr
2025-01-28 12:41       ` Pablo Neira Ayuso
2025-01-30 11:27         ` Sunny73Cr
2025-02-08 20:26           ` Sunny73Cr
2025-02-09  1:47             ` Florian Westphal
2025-02-09  3:12               ` Sunny73Cr
2025-02-09 22:23                 ` Pablo Neira Ayuso
2025-02-09 22:45                   ` Sunny73Cr
2025-12-02  5:22                     ` Sunny73Cr

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.