public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: Stefano Brivio <sbrivio@redhat.com>
To: David Gibson <david@gibson.dropbear.id.au>
Cc: passt-dev@passt.top
Subject: Re: [PATCH 2/4] dhcp: Make option parsing more robust, explicitly handle options 0 and 255
Date: Thu, 16 Jul 2026 09:22:37 +0200 (CEST)	[thread overview]
Message-ID: <20260716092235.0e0e8af3@elisabeth> (raw)
In-Reply-To: <alhuADvrv2QedEt4@zatzit>

On Thu, 16 Jul 2026 15:37:13 +1000
David Gibson <david@gibson.dropbear.id.au> wrote:

> On Thu, Jul 16, 2026 at 01:25:21AM +0200, Stefano Brivio wrote:
> > The initial option-scanning loop in dhcp(), so far, ignored options 0
> > (Pad Option, RFC 2132, Section 3.1) and 255 (End Option, RFC 2132,
> > Section 3.2).
> > 
> > As a result:
> > 
> > - if we ever encountered option 0 in the middle of option fields
> >   (never seen in practice), we would potentially terminate the loop
> >   too early, before scanning remaining options
> > 
> > - a malformed message with an option 255 followed by a length byte
> >   would (reliably) cause us to terminate as we would exceed the
> >   allocated size for the 'opts' array, which is detected as buffer
> >   overflow by the FORTIFY_SOURCE mechanism
> > 
> > The latter was reported as potential vulnerability by AISLE, but it's
> > not actually a vulnerability as we always terminate without carrying
> > on further handling, and in our security model the guest is able to
> > sabotage its own connectivity in any case (for example, a malformed
> > frame from the hypervisor would cause us to reset the connection, or
> > entirely flooding the flow table would cause inbound connectivity to
> > stop working, etc.).
> > 
> > The reported behaviour, however, is indeed a defect, as it affects
> > the functional robustness to a hypothetical issue in a DHCP client,
> > and that's something we definitely want to fix.
> > 
> > Make the option parsing loop more robust by:
> > 
> > - resizing 'opts' from 255 to 256 elements: there's no particular
> >   reason to try to save a tiny bit of memory (which shouldn't even
> >   be allocated in practice) instead of being defensive about it
> > 
> > - explicitly handle options 0 (skip one byte, continue) and 255 (stop
> >   processing options) in the option-scanning loop
> > 
> > This bug was found and an initial version of the patch was written by
> > the AISLE AI security scanning tool (https://aisle.com/platform).
> > 
> > Reported-by: AISLE
> > Signed-off-by: Stefano Brivio <sbrivio@redhat.com>
> > ---
> >  dhcp.c | 10 +++++++++-
> >  1 file changed, 9 insertions(+), 1 deletion(-)
> > 
> > diff --git a/dhcp.c b/dhcp.c
> > index 1ff8cba..632019a 100644
> > --- a/dhcp.c
> > +++ b/dhcp.c
> > @@ -49,7 +49,7 @@ struct opt {
> >  	uint8_t c[255];
> >  };
> >  
> > -static struct opt opts[255];
> > +static struct opt opts[256];
> >  
> >  #define DHCPDISCOVER	1
> >  #define DHCPOFFER	2
> > @@ -374,6 +374,14 @@ int dhcp(const struct ctx *c, struct iov_tail *data)
> >  		if (!type || !olen)
> >  			return -1;
> >  
> > +		if (*type == 255)
> > +			break;
> > +
> > +		if (*type == 0) { /* Pad Option (RFC 2132, 3.1): one byte */
> > +			opt_len--;
> > +			continue;
> > +		}
> > +  
> 
> I don't think this is quite right: at this point we've already
> stripped off the non-existent length-byte with IOV_REMOVE_HEADER,
> meaning opt_len will get out of sync with iov_tail_size(data).

Oops, right, I just tested that we would decrease opt_len "enough" for
the loop to terminate when we meet pad options at the end (which, in
practice, is the only place where we'll find them nowadays), but indeed
it's wrong.

> I think we instead need to check for the 1-byte option cases between
> the two IOV_REMOVE_HEADER() calls.

Right, done.

> And.. since presumably the options could theoretically end with some
> padding options,

That's actually the only place where I've seen the pad option occurring,
in a long while.

> we probably want the loop to be while (opt_len >= 1) instead of 2.

Not strictly needed I think as we don't necessarily want to validate
the last bytes. But anyway:

> In fact the way we
> mix recalculating opt_len from iov_tail_size() with sometimes directly
> updating it is pretty nasty.  We might be better off with
> 	while ((opt_len = iov_tail_size(data)))

...that looks much more natural indeed. I'm using that in v2.

-- 
Stefano


  reply	other threads:[~2026-07-16  7:22 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-15 23:25 [PATCH 0/4] Assorted fixes, address a static checker warning Stefano Brivio
2026-07-15 23:25 ` [PATCH 1/4] CONTRIBUTING.md: The tag is "Link:", regardless of how many we have Stefano Brivio
2026-07-16  5:26   ` David Gibson
2026-07-15 23:25 ` [PATCH 2/4] dhcp: Make option parsing more robust, explicitly handle options 0 and 255 Stefano Brivio
2026-07-16  5:37   ` David Gibson
2026-07-16  7:22     ` Stefano Brivio [this message]
2026-07-15 23:25 ` [PATCH 3/4] passt.1, pesto.1: ::1 is an address, not a port Stefano Brivio
2026-07-16  5:38   ` David Gibson
2026-07-15 23:25 ` [PATCH 4/4] ndp: Use high quality entropy in NDP timer even if not needed Stefano Brivio
2026-07-16  5:45   ` David Gibson
2026-07-16  7:22     ` Stefano Brivio
2026-07-16  7:38       ` David Gibson

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=20260716092235.0e0e8af3@elisabeth \
    --to=sbrivio@redhat.com \
    --cc=david@gibson.dropbear.id.au \
    --cc=passt-dev@passt.top \
    /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.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

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 IMAP folder(s).