treewide: Comply with CERT C rule ERR33-C for snprintf()
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): /home/sbrivio/passt/arch.c:43:3: error: the value returned by this function 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 silence this warning /home/sbrivio/passt/conf.c:577:4: error: the value returned by this function should not be disregarded; neglecting it may lead to errors [cert-err33-c,-warnings-as-errors] 577 | snprintf(netns, PATH_MAX, "/proc/%ld/ns/net", pidval); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/sbrivio/passt/conf.c:577:4: note: cast the expression to void to silence this warning /home/sbrivio/passt/conf.c:579:5: error: the value returned by this function 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 silence this warning /home/sbrivio/passt/pasta.c:105:2: error: the value returned by this function should not be disregarded; neglecting it may lead to errors [cert-err33-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 silence this warning /home/sbrivio/passt/pasta.c:242:2: error: the value returned by this function should not be disregarded; neglecting it may lead to errors [cert-err33-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 silence this warning /home/sbrivio/passt/pasta.c:243:2: error: the value returned by this function should not be disregarded; neglecting it may lead to errors [cert-err33-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 silence this warning /home/sbrivio/passt/tap.c:1155:4: error: the value returned by this function should not be disregarded; neglecting it may lead to errors [cert-err33-c,-warnings-as-errors] 1155 | snprintf(path, UNIX_PATH_MAX - 1, UNIX_SOCK_PATH, i); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ /home/sbrivio/passt/tap.c:1155:4: note: cast the expression to void to silence this warning 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. Signed-off-by: Stefano Brivio <sbrivio@redhat.com> Reviewed-by: David Gibson <david@gibson.dropbear.id.au>
This commit is contained in:
parent
988a4d75f8
commit
98efe7c2fd
6 changed files with 57 additions and 10 deletions
6
arch.c
6
arch.c
|
@ -19,6 +19,7 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* arch_avx2_exec() - Switch to AVX2 build if supported
|
* arch_avx2_exec() - Switch to AVX2 build if supported
|
||||||
|
@ -40,7 +41,10 @@ void arch_avx2_exec(char **argv)
|
||||||
if (__builtin_cpu_supports("avx2")) {
|
if (__builtin_cpu_supports("avx2")) {
|
||||||
char new_path[PATH_MAX + sizeof(".avx2")];
|
char new_path[PATH_MAX + sizeof(".avx2")];
|
||||||
|
|
||||||
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);
|
execve(new_path, argv, environ);
|
||||||
warn_perror("Can't run AVX2 build, using non-AVX2 version");
|
warn_perror("Can't run AVX2 build, using non-AVX2 version");
|
||||||
}
|
}
|
||||||
|
|
13
conf.c
13
conf.c
|
@ -574,10 +574,15 @@ static void conf_pasta_ns(int *netns_only, char *userns, char *netns,
|
||||||
if (pidval < 0 || pidval > INT_MAX)
|
if (pidval < 0 || pidval > INT_MAX)
|
||||||
die("Invalid PID %s", argv[optind]);
|
die("Invalid PID %s", argv[optind]);
|
||||||
|
|
||||||
snprintf(netns, PATH_MAX, "/proc/%ld/ns/net", pidval);
|
if (snprintf_check(netns, PATH_MAX,
|
||||||
if (!*userns)
|
"/proc/%ld/ns/net", pidval))
|
||||||
snprintf(userns, PATH_MAX, "/proc/%ld/ns/user",
|
die_perror("Can't build netns path");
|
||||||
pidval);
|
|
||||||
|
if (!*userns) {
|
||||||
|
if (snprintf_check(userns, PATH_MAX,
|
||||||
|
"/proc/%ld/ns/user", pidval))
|
||||||
|
die_perror("Can't build userns path");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
pasta.c
11
pasta.c
|
@ -102,7 +102,9 @@ static int pasta_wait_for_ns(void *arg)
|
||||||
int flags = O_RDONLY | O_CLOEXEC;
|
int flags = O_RDONLY | O_CLOEXEC;
|
||||||
char ns[PATH_MAX];
|
char ns[PATH_MAX];
|
||||||
|
|
||||||
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 {
|
do {
|
||||||
while ((c->pasta_netns_fd = open(ns, flags)) < 0) {
|
while ((c->pasta_netns_fd = open(ns, flags)) < 0) {
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
|
@ -239,8 +241,11 @@ void pasta_start_ns(struct ctx *c, uid_t uid, gid_t gid,
|
||||||
c->quiet = 1;
|
c->quiet = 1;
|
||||||
|
|
||||||
/* Configure user and group mappings */
|
/* Configure user and group mappings */
|
||||||
snprintf(uidmap, BUFSIZ, "0 %u 1", uid);
|
if (snprintf_check(uidmap, BUFSIZ, "0 %u 1", uid))
|
||||||
snprintf(gidmap, BUFSIZ, "0 %u 1", gid);
|
die_perror("Can't build uidmap");
|
||||||
|
|
||||||
|
if (snprintf_check(gidmap, BUFSIZ, "0 %u 1", gid))
|
||||||
|
die_perror("Can't build gidmap");
|
||||||
|
|
||||||
if (write_file("/proc/self/uid_map", uidmap) ||
|
if (write_file("/proc/self/uid_map", uidmap) ||
|
||||||
write_file("/proc/self/setgroups", "deny") ||
|
write_file("/proc/self/setgroups", "deny") ||
|
||||||
|
|
5
tap.c
5
tap.c
|
@ -1151,8 +1151,9 @@ int tap_sock_unix_open(char *sock_path)
|
||||||
|
|
||||||
if (*sock_path)
|
if (*sock_path)
|
||||||
memcpy(path, sock_path, UNIX_PATH_MAX);
|
memcpy(path, sock_path, UNIX_PATH_MAX);
|
||||||
else
|
else if (snprintf_check(path, UNIX_PATH_MAX - 1,
|
||||||
snprintf(path, UNIX_PATH_MAX - 1, UNIX_SOCK_PATH, i);
|
UNIX_SOCK_PATH, i))
|
||||||
|
die_perror("Can't build UNIX domain socket path");
|
||||||
|
|
||||||
ex = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
|
ex = socket(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK, 0);
|
||||||
if (ex < 0)
|
if (ex < 0)
|
||||||
|
|
30
util.c
30
util.c
|
@ -749,3 +749,33 @@ void close_open_files(int argc, char **argv)
|
||||||
if (rc)
|
if (rc)
|
||||||
die_perror("Failed to close files leaked by parent");
|
die_perror("Failed to close files leaked by parent");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* snprintf_check() - snprintf() wrapper, checking for truncation and errors
|
||||||
|
* @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 = vsnprintf(str, size, format, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
if (rc < 0) {
|
||||||
|
errno = EIO;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((size_t)rc >= size) {
|
||||||
|
errno = ENOBUFS;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
2
util.h
2
util.h
|
@ -11,6 +11,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
@ -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_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);
|
int write_remainder(int fd, const struct iovec *iov, size_t iovcnt, size_t skip);
|
||||||
void close_open_files(int argc, char **argv);
|
void close_open_files(int argc, char **argv);
|
||||||
|
bool snprintf_check(char *str, size_t size, const char *format, ...);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* af_name() - Return name of an address family
|
* af_name() - Return name of an address family
|
||||||
|
|
Loading…
Reference in a new issue