From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: passt.top; dmarc=none (p=none dis=none) header.from=gibson.dropbear.id.au Authentication-Results: passt.top; dkim=pass (2048-bit key; secure) header.d=gibson.dropbear.id.au header.i=@gibson.dropbear.id.au header.a=rsa-sha256 header.s=202410 header.b=QUqGsGN8; dkim-atps=neutral Received: from mail.ozlabs.org (mail.ozlabs.org [IPv6:2404:9400:2221:ea00::3]) by passt.top (Postfix) with ESMTPS id 2A7B65A004E for ; Wed, 30 Oct 2024 09:46:13 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202410; t=1730277962; bh=7gxjuI2p/jMokyxEnPjJeiNICSfcipV4/GKX831a5bk=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=QUqGsGN8KaxB50gg82SlFWPr1srNusUqF+78m9hXrvEHCLBdApagRvfAOFbLpas4x 67U5o7tOYIPPEtNKXmajSRoOGa3/Ylub+bDe6uPzN0yU57NR3BMgxg+VoUaKHOIjzz C+RDQb2LPuv2S7Kxg8jgYoYeLNffY4y3or+NiW4ycc/9Unq/w6hySn0VL/00YXoHAW bVs7eB/gcWmaFEHoqg6bUcRY7SbXb3wMR6sEMtMfnISRI+1jcYZGSzv4exgUqlwE9y HRTHi7P7/423wjPGqPdXpbPWFq3C9WqVW7VyNG9OUORaWULcpDwRkDx9rG+h7SBm58 ua2v13/fNirnQ== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4XdghB0lfHz4xM1; Wed, 30 Oct 2024 19:46:02 +1100 (AEDT) Date: Wed, 30 Oct 2024 19:45:50 +1100 From: David Gibson To: Stefano Brivio Subject: Re: [PATCH v5 2/8] treewide: Comply with CERT C rule ERR33-C for snprintf() Message-ID: References: <20241030080909.2781504-1-sbrivio@redhat.com> <20241030080909.2781504-3-sbrivio@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="n5LJ3LUBP43ryiwN" Content-Disposition: inline In-Reply-To: <20241030080909.2781504-3-sbrivio@redhat.com> Message-ID-Hash: 62RYGAJXBRCEXDAG2OY6QPZGR7HEKGRI X-Message-ID-Hash: 62RYGAJXBRCEXDAG2OY6QPZGR7HEKGRI X-MailFrom: dgibson@gandalf.ozlabs.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: passt-dev@passt.top X-Mailman-Version: 3.3.8 Precedence: list List-Id: Development discussion and patches for passt Archived-At: Archived-At: List-Archive: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: --n5LJ3LUBP43ryiwN Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Wed, Oct 30, 2024 at 09:09:03AM +0100, Stefano Brivio wrote: > clang-tidy, starting from LLVM version 16, up to at least LLVM version > 19, now checks that we detect and handle errors for snprintf() as > requested by CERT C rule ERR33-C. These warnings were logged with LLVM > version 19.1.2 (at least Debian and Fedora match): >=20 > /home/sbrivio/passt/arch.c:43:3: error: the value returned by this functi= on should not be disregarded; neglecting it may lead to errors [cert-err33-= c,-warnings-as-errors] > 43 | snprintf(new_path, PATH_MAX + sizeof(".avx2"), "%= s.avx2", exe); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~= ~~~~~~~~~~~~~ > /home/sbrivio/passt/arch.c:43:3: note: cast the expression to void to sil= ence this warning > /home/sbrivio/passt/conf.c:577:4: error: the value returned by this funct= ion should not be disregarded; neglecting it may lead to errors [cert-err33= -c,-warnings-as-errors] > 577 | snprintf(netns, PATH_MAX, "/proc/%ld/ns/n= et", pidval); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~= ~~~~~~~~~~~~ > /home/sbrivio/passt/conf.c:577:4: note: cast the expression to void to si= lence this warning > /home/sbrivio/passt/conf.c:579:5: error: the value returned by this funct= ion should not be disregarded; neglecting it may lead to errors [cert-err33= -c,-warnings-as-errors] > 579 | snprintf(userns, PATH_MAX, "/proc= /%ld/ns/user", > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~= ~~~~~~~~~~~~~~ > 580 | pidval); > | ~~~~~~~ > /home/sbrivio/passt/conf.c:579:5: note: cast the expression to void to si= lence this warning > /home/sbrivio/passt/pasta.c:105:2: error: the value returned by this func= tion should not be disregarded; neglecting it may lead to errors [cert-err3= 3-c,-warnings-as-errors] > 105 | snprintf(ns, PATH_MAX, "/proc/%i/ns/net", pasta_child_pid= ); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > /home/sbrivio/passt/pasta.c:105:2: note: cast the expression to void to s= ilence this warning > /home/sbrivio/passt/pasta.c:242:2: error: the value returned by this func= tion should not be disregarded; neglecting it may lead to errors [cert-err3= 3-c,-warnings-as-errors] > 242 | snprintf(uidmap, BUFSIZ, "0 %u 1", uid); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > /home/sbrivio/passt/pasta.c:242:2: note: cast the expression to void to s= ilence this warning > /home/sbrivio/passt/pasta.c:243:2: error: the value returned by this func= tion should not be disregarded; neglecting it may lead to errors [cert-err3= 3-c,-warnings-as-errors] > 243 | snprintf(gidmap, BUFSIZ, "0 %u 1", gid); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > /home/sbrivio/passt/pasta.c:243:2: note: cast the expression to void to s= ilence this warning > /home/sbrivio/passt/tap.c:1155:4: error: the value returned by this funct= ion should not be disregarded; neglecting it may lead to errors [cert-err33= -c,-warnings-as-errors] > 1155 | snprintf(path, UNIX_PATH_MAX - 1, UNIX_SO= CK_PATH, i); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~= ~~~~~~~~~~~ > /home/sbrivio/passt/tap.c:1155:4: note: cast the expression to void to si= lence this warning >=20 > Don't silence the warnings as they might actually have some merit. Add > an snprintf_check() function, instead, checking that we're not > truncating messages while printing to buffers, and terminate if the > check fails. >=20 > Signed-off-by: Stefano Brivio Reviewed-by: David Gibson > --- > arch.c | 6 +++++- > conf.c | 13 +++++++++---- > pasta.c | 11 ++++++++--- > tap.c | 5 +++-- > util.c | 30 ++++++++++++++++++++++++++++++ > util.h | 2 ++ > 6 files changed, 57 insertions(+), 10 deletions(-) >=20 > diff --git a/arch.c b/arch.c > index 04bebfc..d1dfb73 100644 > --- a/arch.c > +++ b/arch.c > @@ -19,6 +19,7 @@ > #include > =20 > #include "log.h" > +#include "util.h" > =20 > /** > * arch_avx2_exec() - Switch to AVX2 build if supported > @@ -40,7 +41,10 @@ void arch_avx2_exec(char **argv) > if (__builtin_cpu_supports("avx2")) { > char new_path[PATH_MAX + sizeof(".avx2")]; > =20 > - snprintf(new_path, PATH_MAX + sizeof(".avx2"), "%s.avx2", exe); > + if (snprintf_check(new_path, PATH_MAX + sizeof(".avx2"), > + "%s.avx2", exe)) > + die_perror("Can't build AVX2 executable path"); > + > execve(new_path, argv, environ); > warn_perror("Can't run AVX2 build, using non-AVX2 version"); > } > diff --git a/conf.c b/conf.c > index b3b5342..fa5cec3 100644 > --- a/conf.c > +++ b/conf.c > @@ -574,10 +574,15 @@ static void conf_pasta_ns(int *netns_only, char *us= erns, char *netns, > if (pidval < 0 || pidval > INT_MAX) > die("Invalid PID %s", argv[optind]); > =20 > - snprintf(netns, PATH_MAX, "/proc/%ld/ns/net", pidval); > - if (!*userns) > - snprintf(userns, PATH_MAX, "/proc/%ld/ns/user", > - pidval); > + if (snprintf_check(netns, PATH_MAX, > + "/proc/%ld/ns/net", pidval)) > + die_perror("Can't build netns path"); > + > + if (!*userns) { > + if (snprintf_check(userns, PATH_MAX, > + "/proc/%ld/ns/user", pidval)) > + die_perror("Can't build userns path"); > + } > } > } > =20 > diff --git a/pasta.c b/pasta.c > index 307fb4a..a117704 100644 > --- a/pasta.c > +++ b/pasta.c > @@ -102,7 +102,9 @@ static int pasta_wait_for_ns(void *arg) > int flags =3D O_RDONLY | O_CLOEXEC; > char ns[PATH_MAX]; > =20 > - snprintf(ns, PATH_MAX, "/proc/%i/ns/net", pasta_child_pid); > + if (snprintf_check(ns, PATH_MAX, "/proc/%i/ns/net", pasta_child_pid)) > + die_perror("Can't build netns path"); > + > do { > while ((c->pasta_netns_fd =3D open(ns, flags)) < 0) { > if (errno !=3D ENOENT) > @@ -239,8 +241,11 @@ void pasta_start_ns(struct ctx *c, uid_t uid, gid_t = gid, > c->quiet =3D 1; > =20 > /* Configure user and group mappings */ > - snprintf(uidmap, BUFSIZ, "0 %u 1", uid); > - snprintf(gidmap, BUFSIZ, "0 %u 1", gid); > + if (snprintf_check(uidmap, BUFSIZ, "0 %u 1", uid)) > + die_perror("Can't build uidmap"); > + > + if (snprintf_check(gidmap, BUFSIZ, "0 %u 1", gid)) > + die_perror("Can't build gidmap"); > =20 > if (write_file("/proc/self/uid_map", uidmap) || > write_file("/proc/self/setgroups", "deny") || > diff --git a/tap.c b/tap.c > index c53a39b..cfb82e9 100644 > --- a/tap.c > +++ b/tap.c > @@ -1151,8 +1151,9 @@ int tap_sock_unix_open(char *sock_path) > =20 > if (*sock_path) > memcpy(path, sock_path, UNIX_PATH_MAX); > - else > - snprintf(path, UNIX_PATH_MAX - 1, UNIX_SOCK_PATH, i); > + else if (snprintf_check(path, UNIX_PATH_MAX - 1, > + UNIX_SOCK_PATH, i)) > + die_perror("Can't build UNIX domain socket path"); > =20 > ex =3D socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0); > if (ex < 0) > diff --git a/util.c b/util.c > index eba7d52..21ce0a8 100644 > --- a/util.c > +++ b/util.c > @@ -749,3 +749,33 @@ void close_open_files(int argc, char **argv) > if (rc) > die_perror("Failed to close files leaked by parent"); > } > + > +/** > + * snprintf_check() - snprintf() wrapper, checking for truncation and er= rors > + * @str: Output buffer > + * @size: Maximum size to write to @str > + * @format: Message > + * > + * Return: false on success, true on truncation or error, sets errno on = failure > + */ > +bool snprintf_check(char *str, size_t size, const char *format, ...) > +{ > + va_list ap; > + int rc; > + > + va_start(ap, format); > + rc =3D vsnprintf(str, size, format, ap); > + va_end(ap); > + > + if (rc < 0) { > + errno =3D EIO; > + return true; > + } > + > + if ((size_t)rc >=3D size) { > + errno =3D ENOBUFS; > + return true; > + } > + > + return false; > +} > diff --git a/util.h b/util.h > index 2c1e08e..96f178c 100644 > --- a/util.h > +++ b/util.h > @@ -11,6 +11,7 @@ > #include > #include > #include > +#include > #include > #include > #include > @@ -200,6 +201,7 @@ int write_file(const char *path, const char *buf); > int write_all_buf(int fd, const void *buf, size_t len); > int write_remainder(int fd, const struct iovec *iov, size_t iovcnt, size= _t skip); > void close_open_files(int argc, char **argv); > +bool snprintf_check(char *str, size_t size, const char *format, ...); > =20 > /** > * af_name() - Return name of an address family --=20 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 --n5LJ3LUBP43ryiwN Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEEO+dNsU4E3yXUXRK2zQJF27ox2GcFAmch8i8ACgkQzQJF27ox 2Gfosg/+OJ92M52KJ/7DTENNoQxe65S1m6t2H0Rh9+V9Ms9aeS7hg5/Txhb2kpj9 wnbzplEWkXdm5pyvjom/Mi/5L0YAoAGbjt74omQMfwXa+9PU/TPSXqGj+3EErJyV vLZMwaj7PcihDtKJu4RoHfXTqtuoQ6ndwHYztlRNQkjcima74nnS3HwiME8oy5p7 Tu3OxSM/LcElgIZO+UBX/UWTOhUEgZMbs3etEigBUtSFlM9EPZKQk+NXSa2l79Ig acV9sTArDWJMbVPFeWxCqbvQ7R2N9KfcusZCY09fol9MInDPqLmk2nfJ/T9eqA5Q x8+scGf+Cgaue44lQ/IS4u2uAH1/bTONttHfyMpqdcMdrNMLGUWaoLxd3umOIC6V fTSlTztPncD21MZxZp4LA1mvWPkPXTHo2f24RmrYvnNSjb+0s8AsDmZPsDfbd+TC sQH3y/x7zYEjL7OedDemK40E00uOgytSBa7gSrumaMVJozxKrS1g5b2M9CEIJiNn t84vadv93dJkyCVZSiU04NNa6d8vejO+CwXN+fQhPYjuNaQ0NFAszOOAVvs6+jPM ohMVSQU2qVwC3QUfqaNtCQL9RmUMYmhUFVVK/mbckjb1oud2Wf+U8GDkY8nSYN72 XNW/0Pb2k/vR/+rQYObocJiBED+52hU/C5cmeMzSchWRaky6+Mc= =dver -----END PGP SIGNATURE----- --n5LJ3LUBP43ryiwN--