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=kP4Y1i6W; dkim-atps=neutral Received: from mail.ozlabs.org (gandalf.ozlabs.org [150.107.74.76]) by passt.top (Postfix) with ESMTPS id 939DF5A061A for ; Mon, 28 Oct 2024 03:14:29 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gibson.dropbear.id.au; s=202410; t=1730081660; bh=rFn3ndZmucFKupGezuUgAptO7XkNeI6hBiRiOjFVktg=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=kP4Y1i6WuiFWebQ6IgvimdkrlWxzjXDAsm3Sw6TpdGI1fGK2ccT9IPk+C+qPCT4v7 JnfXWcZ94BLvi7HMm4Vx7lqjSHF6FVTLS2tTCMozD704jQhob5R4efntFkuTnCU+bm SEMshAEdsqX5eWejvNtQjBA1Nk+5rg9K15NYvm0p2jIqCNtoYpz3wC013oS06XbBkk VTR5jUldAxj/maBb3qOnKcQNCH/pgwZgBhRabuxD94xVcK1iEty8PiQIrHkZLPUswk tafL5VzIWmrKY7HaDXd6HXPQ2dhAO253LAWWvM/5uB3gXGleXV18j6vmLkMJkY0VQ8 UBrcejLJEUnEQ== Received: by gandalf.ozlabs.org (Postfix, from userid 1007) id 4XcH585lzkz4x3J; Mon, 28 Oct 2024 13:14:20 +1100 (AEDT) Date: Mon, 28 Oct 2024 11:58:36 +1100 From: David Gibson To: Stefano Brivio Subject: Re: [PATCH v2 2/8] treewide: Comply with CERT C rule ERR33-C for snprintf() Message-ID: References: <20241025120814.3449347-1-sbrivio@redhat.com> <20241025120814.3449347-3-sbrivio@redhat.com> MIME-Version: 1.0 Content-Type: multipart/signed; micalg=pgp-sha256; protocol="application/pgp-signature"; boundary="ovTefzuRd41EGNCX" Content-Disposition: inline In-Reply-To: <20241025120814.3449347-3-sbrivio@redhat.com> Message-ID-Hash: 5EGKFIHEDPFXCDGUYWRYJB6IKO7DEZXE X-Message-ID-Hash: 5EGKFIHEDPFXCDGUYWRYJB6IKO7DEZXE 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: --ovTefzuRd41EGNCX Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable On Fri, Oct 25, 2024 at 02:08:08PM +0200, 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..9cb705e 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 snprintf(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 --ovTefzuRd41EGNCX Content-Type: application/pgp-signature; name="signature.asc" -----BEGIN PGP SIGNATURE----- iQIzBAEBCAAdFiEEO+dNsU4E3yXUXRK2zQJF27ox2GcFAmce4bgACgkQzQJF27ox 2GfeWg//WySLK19SFJgNZh5vuCjws0LcbBzfLCB59pLYKvyny5IF2X5fQQs98ARD kP2b8h6fTNSqVO9SoHHOJetlB9kW0jcmF6xDy1pLnYLTCfsco9hb//aOPuqpd31W ciadHVYAC/L6CUD/mF7NMSQjNGmVNCw9NptnGEjp4g4VeIOYAKQHD39q7v628xaD 6lWg591UkmYTGrhZoyGabYUEdk97cNMdh5twDnl6j724dKOEW/Ll8Bt9vIqmFjCd IGa+QNGWBKAxjbrDILeuWNz1cI6aecbCrkBoyTM+9Pbp1Ko+6O1PEOUffM+q7Cpx HTe1HxwwGMEI3VDLF/sOPdYOZL1Tb5RhHdPBTCeENTJXs9ts5ZwTSS5MCPx6QglT QBvYjqi/bnmHHKHX3NEokoW4FtwXdz6L1nMQmpVUrUOAs7soF1yWoKzgakw+VNVm WUUZ1g3Bc9f3nN41e1uX0hgTHKF2/Ak2ydK5nFrHzL2hdVAe/e/6e06jf8p3l+hV WLrAi+Ze0aPUElVi/4tmH+rBEgCs17HS2STMl4LkcDSfJPgAKHMIuPW0JQu6GPEH VYzdsJHNx8OkWLuGf+TXMdUHyqooCV/qFwwYnSp9+6yy34IRSFEowDLRffL30J8M Za+uNFf+ArWXXLX9mEz4shiAf1kMjkblHV1Yc4FC7zHtctfPSQ8= =8BML -----END PGP SIGNATURE----- --ovTefzuRd41EGNCX--