* [PATCH v3 0/5] Fixes for Fedora 43
@ 2026-01-07 1:46 David Gibson
2026-01-07 1:46 ` [PATCH v3 1/5] util: Be more defensive about buffer overruns in read_file() David Gibson
` (5 more replies)
0 siblings, 6 replies; 9+ messages in thread
From: David Gibson @ 2026-01-07 1:46 UTC (permalink / raw)
To: Stefano Brivio, passt-dev; +Cc: David Gibson
While away, I updated my laptop to Fedora 43. Naturally a bunch of
things in the passt tests broke. First there were the usual breakages
due to a new static checker version (also one real bug). Then several
other problems.
Changes in v3:
* Fixed a really stupid mistake in applying the change to 2/5
Changes in v2:
* Trivial whitespace fix from Laurent
* Used more natural array iteration in 2/5 (suggested by Laurent)
* Added Laurent's R-b tags
David Gibson (5):
util: Be more defensive about buffer overruns in read_file()
migrate: Don't use terminator element for versions[] array
treewide: Don't rely on terminator records in ip[46].dns arrays
test: Handle Operating System Command escapes in terminal output
test: Include sshd-auth in mbuto guest image
conf.c | 8 ++++++--
dhcp.c | 4 +++-
dhcpv6.c | 4 +++-
migrate.c | 9 ++++-----
ndp.c | 4 +++-
passt.h | 4 ++--
test/lib/term | 4 ++--
test/passt.mbuto | 6 ++++++
util.c | 2 +-
9 files changed, 30 insertions(+), 15 deletions(-)
--
2.52.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 1/5] util: Be more defensive about buffer overruns in read_file()
2026-01-07 1:46 [PATCH v3 0/5] Fixes for Fedora 43 David Gibson
@ 2026-01-07 1:46 ` David Gibson
2026-01-07 1:46 ` [PATCH v3 2/5] migrate: Don't use terminator element for versions[] array David Gibson
` (4 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: David Gibson @ 2026-01-07 1:46 UTC (permalink / raw)
To: Stefano Brivio, passt-dev; +Cc: David Gibson, Laurent Vivier
clang-21.1.7 complains about read_file(), thinking that total_read might
come to exceed buf_size, leading to an out of bounds access at the end of
the function. In fact, the semantics of read()'s return mean this can't
ever happen. But we already have to check for the total_read == buf_size
case, so it's basically free to change it to >= and suppress the error.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
---
util.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/util.c b/util.c
index 27303950..a48f727c 100644
--- a/util.c
+++ b/util.c
@@ -715,7 +715,7 @@ static ssize_t read_file(const char *path, char *buf, size_t buf_size)
close(fd);
- if (total_read == buf_size) {
+ if (total_read >= buf_size) {
buf[buf_size - 1] = '\0';
return -ENOBUFS;
}
--
2.52.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 2/5] migrate: Don't use terminator element for versions[] array
2026-01-07 1:46 [PATCH v3 0/5] Fixes for Fedora 43 David Gibson
2026-01-07 1:46 ` [PATCH v3 1/5] util: Be more defensive about buffer overruns in read_file() David Gibson
@ 2026-01-07 1:46 ` David Gibson
2026-01-07 1:46 ` [PATCH v3 3/5] treewide: Don't rely on terminator records in ip[46].dns arrays David Gibson
` (3 subsequent siblings)
5 siblings, 0 replies; 9+ messages in thread
From: David Gibson @ 2026-01-07 1:46 UTC (permalink / raw)
To: Stefano Brivio, passt-dev; +Cc: David Gibson, Laurent Vivier
When scanning the versions[] array we use a dummy entry to detect when
we're finished. Use ARRAY_SIZE() instead, which is almost as easy, a
little safer, and doesn't cause clang-tidy 21.1.7 to complain.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
---
migrate.c | 9 ++++-----
1 file changed, 4 insertions(+), 5 deletions(-)
diff --git a/migrate.c b/migrate.c
index 48d63a07..13bacab7 100644
--- a/migrate.c
+++ b/migrate.c
@@ -123,7 +123,6 @@ static const struct migrate_version versions[] = {
* MSS and omitted timestamps, which meant it usually wouldn't work.
* Therefore we don't attempt to support compatibility with it.
*/
- { 0 },
};
/* Current encoding version */
@@ -177,9 +176,9 @@ static int migrate_source(struct ctx *c, int fd)
*/
static const struct migrate_version *migrate_target_read_header(int fd)
{
- const struct migrate_version *v;
struct migrate_header h;
uint32_t id, compat_id;
+ unsigned i;
if (read_all_buf(fd, &h, sizeof(h)))
return NULL;
@@ -196,9 +195,9 @@ static const struct migrate_version *migrate_target_read_header(int fd)
return NULL;
}
- for (v = versions; v->id; v++)
- if (v->id <= id && v->id >= compat_id)
- return v;
+ for (i = 0; i < ARRAY_SIZE(versions); i++)
+ if (versions[i].id <= id && versions[i].id >= compat_id)
+ return &versions[i];
errno = ENOTSUP;
err("Unsupported device state version: %u", id);
--
2.52.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 3/5] treewide: Don't rely on terminator records in ip[46].dns arrays
2026-01-07 1:46 [PATCH v3 0/5] Fixes for Fedora 43 David Gibson
2026-01-07 1:46 ` [PATCH v3 1/5] util: Be more defensive about buffer overruns in read_file() David Gibson
2026-01-07 1:46 ` [PATCH v3 2/5] migrate: Don't use terminator element for versions[] array David Gibson
@ 2026-01-07 1:46 ` David Gibson
2026-01-10 23:33 ` Stefano Brivio
2026-01-07 1:46 ` [PATCH v3 4/5] test: Handle Operating System Command escapes in terminal output David Gibson
` (2 subsequent siblings)
5 siblings, 1 reply; 9+ messages in thread
From: David Gibson @ 2026-01-07 1:46 UTC (permalink / raw)
To: Stefano Brivio, passt-dev; +Cc: David Gibson, Laurent Vivier
In our arrays of DNS resolvers to pass to the guest we use a blank entry
to indicate the end of the list. We rely on this when scanning the array,
not having separate bounds checking. clang-tidy 21.1.7 has fancier
checking for array overruns in loops, but it's not able to reason that
there's always a terminating entry, so complains.
Indeed, it's correct to do so in this case. Although we allow space in the
arrays for the terminator (size MAXNS + 1), add_dns[46]() check only for
idx >= ARRAY_SIZE()
before adding an entry. This allows it to consume the last slot with a
"real" entry, meaning the places where we scan really could overrun.
Fix the bug, and make it easier to reason about (for both clang-tidy and
people) by using ARRAY_SIZE() base bounds checking. Treat the terminator
explicitly as an early exit case using 'break'.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
---
conf.c | 8 ++++++--
dhcp.c | 4 +++-
dhcpv6.c | 4 +++-
ndp.c | 4 +++-
passt.h | 4 ++--
5 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/conf.c b/conf.c
index 84ae12b2..b1fc4b9f 100644
--- a/conf.c
+++ b/conf.c
@@ -1159,7 +1159,9 @@ static void conf_print(const struct ctx *c)
buf4, sizeof(buf4)));
}
- for (i = 0; !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]); i++) {
+ for (i = 0; i < ARRAY_SIZE(c->ip4.dns); i++) {
+ if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]))
+ break;
if (!i)
info("DNS:");
inet_ntop(AF_INET, &c->ip4.dns[i], buf4, sizeof(buf4));
@@ -1197,7 +1199,9 @@ static void conf_print(const struct ctx *c)
buf6, sizeof(buf6)));
dns6:
- for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]); i++) {
+ for (i = 0; i < ARRAY_SIZE(c->ip6.dns); i++) {
+ if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]))
+ break;
if (!i)
info("DNS:");
inet_ntop(AF_INET6, &c->ip6.dns[i], buf6, sizeof(buf6));
diff --git a/dhcp.c b/dhcp.c
index 6b9c2e3b..1ff8cba9 100644
--- a/dhcp.c
+++ b/dhcp.c
@@ -430,7 +430,9 @@ int dhcp(const struct ctx *c, struct iov_tail *data)
}
for (i = 0, opts[6].slen = 0;
- !c->no_dhcp_dns && !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]); i++) {
+ !c->no_dhcp_dns && i < ARRAY_SIZE(c->ip4.dns); i++) {
+ if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]))
+ break;
((struct in_addr *)opts[6].s)[i] = c->ip4.dns[i];
opts[6].slen += sizeof(uint32_t);
}
diff --git a/dhcpv6.c b/dhcpv6.c
index e4df0db5..d94be23a 100644
--- a/dhcpv6.c
+++ b/dhcpv6.c
@@ -425,7 +425,9 @@ static size_t dhcpv6_dns_fill(const struct ctx *c, char *buf, int offset)
if (c->no_dhcp_dns)
goto search;
- for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]); i++) {
+ for (i = 0; i < ARRAY_SIZE(c->ip6.dns); i++) {
+ if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]))
+ break;
if (!i) {
srv = (struct opt_dns_servers *)(buf + offset);
offset += sizeof(struct opt_hdr);
diff --git a/ndp.c b/ndp.c
index eb9e3139..1f2bcb0c 100644
--- a/ndp.c
+++ b/ndp.c
@@ -285,7 +285,9 @@ static void ndp_ra(const struct ctx *c, const struct in6_addr *dst)
size_t dns_s_len = 0;
int i, n;
- for (n = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[n]); n++);
+ for (n = 0; n < ARRAY_SIZE(c->ip6.dns); n++)
+ if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[n]))
+ break;
if (n) {
struct opt_rdnss *rdnss = (struct opt_rdnss *)ptr;
*rdnss = (struct opt_rdnss) {
diff --git a/passt.h b/passt.h
index 79d01ddb..87da76d3 100644
--- a/passt.h
+++ b/passt.h
@@ -91,7 +91,7 @@ struct ip4_ctx {
struct in_addr guest_gw;
struct in_addr map_host_loopback;
struct in_addr map_guest_addr;
- struct in_addr dns[MAXNS + 1];
+ struct in_addr dns[MAXNS];
struct in_addr dns_match;
struct in_addr our_tap_addr;
@@ -132,7 +132,7 @@ struct ip6_ctx {
struct in6_addr guest_gw;
struct in6_addr map_host_loopback;
struct in6_addr map_guest_addr;
- struct in6_addr dns[MAXNS + 1];
+ struct in6_addr dns[MAXNS];
struct in6_addr dns_match;
struct in6_addr our_tap_ll;
--
2.52.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 4/5] test: Handle Operating System Command escapes in terminal output
2026-01-07 1:46 [PATCH v3 0/5] Fixes for Fedora 43 David Gibson
` (2 preceding siblings ...)
2026-01-07 1:46 ` [PATCH v3 3/5] treewide: Don't rely on terminator records in ip[46].dns arrays David Gibson
@ 2026-01-07 1:46 ` David Gibson
2026-01-07 1:46 ` [PATCH v3 5/5] test: Include sshd-auth in mbuto guest image David Gibson
2026-01-10 23:33 ` [PATCH v3 0/5] Fixes for Fedora 43 Stefano Brivio
5 siblings, 0 replies; 9+ messages in thread
From: David Gibson @ 2026-01-07 1:46 UTC (permalink / raw)
To: Stefano Brivio, passt-dev; +Cc: David Gibson, Laurent Vivier
Our "old style" test script stuff uses raw terminal output scraped from
tmux. This might include terminal escape sequences from the shell, or
whatever we run in it: they think they're talking to a terminal emulator
not a script, and they're not entirely incorrect.
In several places we filter out ANSI ESC-[ sequences to make this work.
However, this doesn't include ESC-] "Operating System Command" sequences.
Something I've updated in Fedora 43 generates heaps of these, which break
everything.
Add more hairy regexps to filter these out as well.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
---
test/lib/term | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/test/lib/term b/test/lib/term
index f596364c..89e4fdbe 100755
--- a/test/lib/term
+++ b/test/lib/term
@@ -203,7 +203,7 @@ pane_wait() {
__done=0
while
- __l="$(tail -1 ${LOGDIR}/pane_${__lc}.log | sed 's/^[[[][^a-zA-Z]*[a-zA-Z]//g')"
+ __l="$(tail -1 ${LOGDIR}/pane_${__lc}.log | sed 's/^[[[][^a-zA-Z]*[a-zA-Z]//g;s/^[[]][^^[]*^[[\]//g')"
case ${__l} in
*"$ " | *"# ") return ;;
esac
@@ -215,7 +215,7 @@ pane_wait() {
pane_parse() {
__pane_lc="$(echo "${1}" | tr [A-Z] [a-z])"
- __buf="$(tail -n2 ${LOGDIR}/pane_${__pane_lc}.log | head -n1 | sed 's/^[^\r]*\r\([^\r]\)/\1/' | tr -d '\r\n')"
+ __buf="$(tail -n2 ${LOGDIR}/pane_${__pane_lc}.log | head -n1 | sed 's/^[^\r]*\r\([^\r]\)/\1/;s/^[[]][^^[]*^[[\]//g' | tr -d '\r\n')"
[ "# $(eval printf '%s' \"\$${1}_LAST_CMD\")" != "${__buf}" ] && \
[ "$ $(eval printf '%s' \"\$${1}_LAST_CMD\")" != "${__buf}" ] &&
--
2.52.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 5/5] test: Include sshd-auth in mbuto guest image
2026-01-07 1:46 [PATCH v3 0/5] Fixes for Fedora 43 David Gibson
` (3 preceding siblings ...)
2026-01-07 1:46 ` [PATCH v3 4/5] test: Handle Operating System Command escapes in terminal output David Gibson
@ 2026-01-07 1:46 ` David Gibson
2026-01-10 23:33 ` [PATCH v3 0/5] Fixes for Fedora 43 Stefano Brivio
5 siblings, 0 replies; 9+ messages in thread
From: David Gibson @ 2026-01-07 1:46 UTC (permalink / raw)
To: Stefano Brivio, passt-dev; +Cc: David Gibson, Laurent Vivier
OpenSSH has split itself into several binaries for greater security. We
already have logic to make sure we include the sshd-session binary.
OpenSSH 10 has added another: sshd-auth which we also need for a working
sshd within the guest.
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Laurent Vivier <lvivier@redhat.com>
---
test/passt.mbuto | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/test/passt.mbuto b/test/passt.mbuto
index 598c2547..de35c3ce 100755
--- a/test/passt.mbuto
+++ b/test/passt.mbuto
@@ -24,6 +24,12 @@ for bin in /usr/lib/openssh/sshd-session /usr/lib/ssh/sshd-session \
command -v "${bin}" >/dev/null && PROGS="${PROGS} ${bin}"
done
+# OpenSSH 10 adds sshd-auth as well
+for bin in /usr/lib/openssh/sshd-auth /usr/lib/ssh/sshd-auth \
+ /usr/libexec/openssh/sshd-auth; do
+ command -v "${bin}" >/dev/null && PROGS="${PROGS} ${bin}"
+done
+
KMODS="${KMODS:- virtio_net virtio_pci vmw_vsock_virtio_transport}"
LINKS="${LINKS:-
--
2.52.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 3/5] treewide: Don't rely on terminator records in ip[46].dns arrays
2026-01-07 1:46 ` [PATCH v3 3/5] treewide: Don't rely on terminator records in ip[46].dns arrays David Gibson
@ 2026-01-10 23:33 ` Stefano Brivio
2026-01-11 2:32 ` David Gibson
0 siblings, 1 reply; 9+ messages in thread
From: Stefano Brivio @ 2026-01-10 23:33 UTC (permalink / raw)
To: David Gibson; +Cc: passt-dev, Laurent Vivier
On Wed, 7 Jan 2026 12:46:04 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:
> In our arrays of DNS resolvers to pass to the guest we use a blank entry
> to indicate the end of the list. We rely on this when scanning the array,
> not having separate bounds checking. clang-tidy 21.1.7 has fancier
> checking for array overruns in loops, but it's not able to reason that
> there's always a terminating entry, so complains.
>
> Indeed, it's correct to do so in this case. Although we allow space in the
> arrays for the terminator (size MAXNS + 1), add_dns[46]() check only for
> idx >= ARRAY_SIZE()
> before adding an entry. This allows it to consume the last slot with a
> "real" entry, meaning the places where we scan really could overrun.
>
> Fix the bug, and make it easier to reason about (for both clang-tidy and
> people)
I'm not really sure about people. This change turns some for loops from
"iterate until we find a terminator" to "iterate n times: while
iterating, if we find a terminator, exit the loop".
In any case, the annoyance is minor enough, at least to me, so let's
make clang-tidy happy by all means.
> by using ARRAY_SIZE() base bounds checking. Treat the terminator
> explicitly as an early exit case using 'break'.
>
> Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> Reviewed-by: Laurent Vivier <lvivier@redhat.com>
> ---
> conf.c | 8 ++++++--
> dhcp.c | 4 +++-
> dhcpv6.c | 4 +++-
> ndp.c | 4 +++-
> passt.h | 4 ++--
> 5 files changed, 17 insertions(+), 7 deletions(-)
>
> diff --git a/conf.c b/conf.c
> index 84ae12b2..b1fc4b9f 100644
> --- a/conf.c
> +++ b/conf.c
> @@ -1159,7 +1159,9 @@ static void conf_print(const struct ctx *c)
> buf4, sizeof(buf4)));
> }
>
> - for (i = 0; !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]); i++) {
> + for (i = 0; i < ARRAY_SIZE(c->ip4.dns); i++) {
> + if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]))
> + break;
> if (!i)
> info("DNS:");
> inet_ntop(AF_INET, &c->ip4.dns[i], buf4, sizeof(buf4));
> @@ -1197,7 +1199,9 @@ static void conf_print(const struct ctx *c)
> buf6, sizeof(buf6)));
>
> dns6:
> - for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]); i++) {
> + for (i = 0; i < ARRAY_SIZE(c->ip6.dns); i++) {
> + if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]))
> + break;
> if (!i)
> info("DNS:");
> inet_ntop(AF_INET6, &c->ip6.dns[i], buf6, sizeof(buf6));
> diff --git a/dhcp.c b/dhcp.c
> index 6b9c2e3b..1ff8cba9 100644
> --- a/dhcp.c
> +++ b/dhcp.c
> @@ -430,7 +430,9 @@ int dhcp(const struct ctx *c, struct iov_tail *data)
> }
>
> for (i = 0, opts[6].slen = 0;
> - !c->no_dhcp_dns && !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]); i++) {
> + !c->no_dhcp_dns && i < ARRAY_SIZE(c->ip4.dns); i++) {
> + if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]))
> + break;
> ((struct in_addr *)opts[6].s)[i] = c->ip4.dns[i];
> opts[6].slen += sizeof(uint32_t);
> }
> diff --git a/dhcpv6.c b/dhcpv6.c
> index e4df0db5..d94be23a 100644
> --- a/dhcpv6.c
> +++ b/dhcpv6.c
> @@ -425,7 +425,9 @@ static size_t dhcpv6_dns_fill(const struct ctx *c, char *buf, int offset)
> if (c->no_dhcp_dns)
> goto search;
>
> - for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]); i++) {
> + for (i = 0; i < ARRAY_SIZE(c->ip6.dns); i++) {
> + if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]))
> + break;
> if (!i) {
> srv = (struct opt_dns_servers *)(buf + offset);
> offset += sizeof(struct opt_hdr);
> diff --git a/ndp.c b/ndp.c
> index eb9e3139..1f2bcb0c 100644
> --- a/ndp.c
> +++ b/ndp.c
> @@ -285,7 +285,9 @@ static void ndp_ra(const struct ctx *c, const struct in6_addr *dst)
> size_t dns_s_len = 0;
> int i, n;
>
> - for (n = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[n]); n++);
> + for (n = 0; n < ARRAY_SIZE(c->ip6.dns); n++)
> + if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[n]))
> + break;
> if (n) {
> struct opt_rdnss *rdnss = (struct opt_rdnss *)ptr;
> *rdnss = (struct opt_rdnss) {
> diff --git a/passt.h b/passt.h
> index 79d01ddb..87da76d3 100644
> --- a/passt.h
> +++ b/passt.h
> @@ -91,7 +91,7 @@ struct ip4_ctx {
> struct in_addr guest_gw;
> struct in_addr map_host_loopback;
> struct in_addr map_guest_addr;
> - struct in_addr dns[MAXNS + 1];
> + struct in_addr dns[MAXNS];
The comment still says:
* @dns: DNS addresses for DHCP, zero-terminated
> struct in_addr dns_match;
> struct in_addr our_tap_addr;
>
> @@ -132,7 +132,7 @@ struct ip6_ctx {
> struct in6_addr guest_gw;
> struct in6_addr map_host_loopback;
> struct in6_addr map_guest_addr;
> - struct in6_addr dns[MAXNS + 1];
> + struct in6_addr dns[MAXNS];
...same here. But as this is the only remark I have on the whole
series, I took the liberty to fix up the comment directly on merge.
> struct in6_addr dns_match;
> struct in6_addr our_tap_ll;
>
--
Stefano
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 0/5] Fixes for Fedora 43
2026-01-07 1:46 [PATCH v3 0/5] Fixes for Fedora 43 David Gibson
` (4 preceding siblings ...)
2026-01-07 1:46 ` [PATCH v3 5/5] test: Include sshd-auth in mbuto guest image David Gibson
@ 2026-01-10 23:33 ` Stefano Brivio
5 siblings, 0 replies; 9+ messages in thread
From: Stefano Brivio @ 2026-01-10 23:33 UTC (permalink / raw)
To: David Gibson; +Cc: passt-dev
On Wed, 7 Jan 2026 12:46:01 +1100
David Gibson <david@gibson.dropbear.id.au> wrote:
> While away, I updated my laptop to Fedora 43. Naturally a bunch of
> things in the passt tests broke. First there were the usual breakages
> due to a new static checker version (also one real bug). Then several
> other problems.
>
> Changes in v3:
> * Fixed a really stupid mistake in applying the change to 2/5
> Changes in v2:
> * Trivial whitespace fix from Laurent
> * Used more natural array iteration in 2/5 (suggested by Laurent)
> * Added Laurent's R-b tags
>
> David Gibson (5):
> util: Be more defensive about buffer overruns in read_file()
> migrate: Don't use terminator element for versions[] array
> treewide: Don't rely on terminator records in ip[46].dns arrays
> test: Handle Operating System Command escapes in terminal output
> test: Include sshd-auth in mbuto guest image
Applied.
--
Stefano
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 3/5] treewide: Don't rely on terminator records in ip[46].dns arrays
2026-01-10 23:33 ` Stefano Brivio
@ 2026-01-11 2:32 ` David Gibson
0 siblings, 0 replies; 9+ messages in thread
From: David Gibson @ 2026-01-11 2:32 UTC (permalink / raw)
To: Stefano Brivio; +Cc: passt-dev, Laurent Vivier
[-- Attachment #1: Type: text/plain, Size: 5852 bytes --]
On Sun, Jan 11, 2026 at 12:33:00AM +0100, Stefano Brivio wrote:
> On Wed, 7 Jan 2026 12:46:04 +1100
> David Gibson <david@gibson.dropbear.id.au> wrote:
>
> > In our arrays of DNS resolvers to pass to the guest we use a blank entry
> > to indicate the end of the list. We rely on this when scanning the array,
> > not having separate bounds checking. clang-tidy 21.1.7 has fancier
> > checking for array overruns in loops, but it's not able to reason that
> > there's always a terminating entry, so complains.
> >
> > Indeed, it's correct to do so in this case. Although we allow space in the
> > arrays for the terminator (size MAXNS + 1), add_dns[46]() check only for
> > idx >= ARRAY_SIZE()
> > before adding an entry. This allows it to consume the last slot with a
> > "real" entry, meaning the places where we scan really could overrun.
> >
> > Fix the bug, and make it easier to reason about (for both clang-tidy and
> > people)
>
> I'm not really sure about people. This change turns some for loops from
> "iterate until we find a terminator" to "iterate n times: while
> iterating, if we find a terminator, exit the loop".
That's true of the loop itself. But to convince myself it can't
overrun the buffer, I have to go look elsewhere to see if the
terminator is always applied. In this case, it wasn't. With the
explicitly bounded iteration it's immediately clear it can't overrun.
> In any case, the annoyance is minor enough, at least to me, so let's
> make clang-tidy happy by all means.
>
> > by using ARRAY_SIZE() base bounds checking. Treat the terminator
> > explicitly as an early exit case using 'break'.
> >
> > Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
> > Reviewed-by: Laurent Vivier <lvivier@redhat.com>
> > ---
> > conf.c | 8 ++++++--
> > dhcp.c | 4 +++-
> > dhcpv6.c | 4 +++-
> > ndp.c | 4 +++-
> > passt.h | 4 ++--
> > 5 files changed, 17 insertions(+), 7 deletions(-)
> >
> > diff --git a/conf.c b/conf.c
> > index 84ae12b2..b1fc4b9f 100644
> > --- a/conf.c
> > +++ b/conf.c
> > @@ -1159,7 +1159,9 @@ static void conf_print(const struct ctx *c)
> > buf4, sizeof(buf4)));
> > }
> >
> > - for (i = 0; !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]); i++) {
> > + for (i = 0; i < ARRAY_SIZE(c->ip4.dns); i++) {
> > + if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]))
> > + break;
> > if (!i)
> > info("DNS:");
> > inet_ntop(AF_INET, &c->ip4.dns[i], buf4, sizeof(buf4));
> > @@ -1197,7 +1199,9 @@ static void conf_print(const struct ctx *c)
> > buf6, sizeof(buf6)));
> >
> > dns6:
> > - for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]); i++) {
> > + for (i = 0; i < ARRAY_SIZE(c->ip6.dns); i++) {
> > + if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]))
> > + break;
> > if (!i)
> > info("DNS:");
> > inet_ntop(AF_INET6, &c->ip6.dns[i], buf6, sizeof(buf6));
> > diff --git a/dhcp.c b/dhcp.c
> > index 6b9c2e3b..1ff8cba9 100644
> > --- a/dhcp.c
> > +++ b/dhcp.c
> > @@ -430,7 +430,9 @@ int dhcp(const struct ctx *c, struct iov_tail *data)
> > }
> >
> > for (i = 0, opts[6].slen = 0;
> > - !c->no_dhcp_dns && !IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]); i++) {
> > + !c->no_dhcp_dns && i < ARRAY_SIZE(c->ip4.dns); i++) {
> > + if (IN4_IS_ADDR_UNSPECIFIED(&c->ip4.dns[i]))
> > + break;
> > ((struct in_addr *)opts[6].s)[i] = c->ip4.dns[i];
> > opts[6].slen += sizeof(uint32_t);
> > }
> > diff --git a/dhcpv6.c b/dhcpv6.c
> > index e4df0db5..d94be23a 100644
> > --- a/dhcpv6.c
> > +++ b/dhcpv6.c
> > @@ -425,7 +425,9 @@ static size_t dhcpv6_dns_fill(const struct ctx *c, char *buf, int offset)
> > if (c->no_dhcp_dns)
> > goto search;
> >
> > - for (i = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]); i++) {
> > + for (i = 0; i < ARRAY_SIZE(c->ip6.dns); i++) {
> > + if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[i]))
> > + break;
> > if (!i) {
> > srv = (struct opt_dns_servers *)(buf + offset);
> > offset += sizeof(struct opt_hdr);
> > diff --git a/ndp.c b/ndp.c
> > index eb9e3139..1f2bcb0c 100644
> > --- a/ndp.c
> > +++ b/ndp.c
> > @@ -285,7 +285,9 @@ static void ndp_ra(const struct ctx *c, const struct in6_addr *dst)
> > size_t dns_s_len = 0;
> > int i, n;
> >
> > - for (n = 0; !IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[n]); n++);
> > + for (n = 0; n < ARRAY_SIZE(c->ip6.dns); n++)
> > + if (IN6_IS_ADDR_UNSPECIFIED(&c->ip6.dns[n]))
> > + break;
> > if (n) {
> > struct opt_rdnss *rdnss = (struct opt_rdnss *)ptr;
> > *rdnss = (struct opt_rdnss) {
> > diff --git a/passt.h b/passt.h
> > index 79d01ddb..87da76d3 100644
> > --- a/passt.h
> > +++ b/passt.h
> > @@ -91,7 +91,7 @@ struct ip4_ctx {
> > struct in_addr guest_gw;
> > struct in_addr map_host_loopback;
> > struct in_addr map_guest_addr;
> > - struct in_addr dns[MAXNS + 1];
> > + struct in_addr dns[MAXNS];
>
> The comment still says:
>
> * @dns: DNS addresses for DHCP, zero-terminated
>
> > struct in_addr dns_match;
> > struct in_addr our_tap_addr;
> >
> > @@ -132,7 +132,7 @@ struct ip6_ctx {
> > struct in6_addr guest_gw;
> > struct in6_addr map_host_loopback;
> > struct in6_addr map_guest_addr;
> > - struct in6_addr dns[MAXNS + 1];
> > + struct in6_addr dns[MAXNS];
>
> ...same here. But as this is the only remark I have on the whole
> series, I took the liberty to fix up the comment directly on merge.
Ah, thanks.
> > struct in6_addr dns_match;
> > struct in6_addr our_tap_ll;
> >
>
> --
> Stefano
>
--
David Gibson (he or they) | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you, not the other way
| around.
http://www.ozlabs.org/~dgibson
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-01-11 2:32 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-01-07 1:46 [PATCH v3 0/5] Fixes for Fedora 43 David Gibson
2026-01-07 1:46 ` [PATCH v3 1/5] util: Be more defensive about buffer overruns in read_file() David Gibson
2026-01-07 1:46 ` [PATCH v3 2/5] migrate: Don't use terminator element for versions[] array David Gibson
2026-01-07 1:46 ` [PATCH v3 3/5] treewide: Don't rely on terminator records in ip[46].dns arrays David Gibson
2026-01-10 23:33 ` Stefano Brivio
2026-01-11 2:32 ` David Gibson
2026-01-07 1:46 ` [PATCH v3 4/5] test: Handle Operating System Command escapes in terminal output David Gibson
2026-01-07 1:46 ` [PATCH v3 5/5] test: Include sshd-auth in mbuto guest image David Gibson
2026-01-10 23:33 ` [PATCH v3 0/5] Fixes for Fedora 43 Stefano Brivio
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).