util/mkhtemp: add -q option (silence errors)

Signed-off-by: Leah Rowe <leah@libreboot.org>
This commit is contained in:
Leah Rowe
2026-03-24 23:23:16 +00:00
parent 2cee58188c
commit 3ddd7a0d36
2 changed files with 62 additions and 24 deletions

View File

@@ -499,6 +499,8 @@ void b0rk(int nvm_errval, const char *msg, ...);
int exit_cleanup(void); int exit_cleanup(void);
const char *getnvmprogname(void); const char *getnvmprogname(void);
void err_mkhtemp(int stfu, int errval, const char *msg, ...);
/* libc hardening /* libc hardening
*/ */

View File

@@ -10,6 +10,10 @@
* generally provides much higher strictness than previous * generally provides much higher strictness than previous
* implementations such as mktemp, mkstemp or even mkdtemp. * implementations such as mktemp, mkstemp or even mkdtemp.
* *
* It uses several modern features by default, e.g. openat2
* and O_TMPFILE on Linux, with additional hardening; BSD
* projects only have openat so the code uses that there.
*
* Many programs rely on mktemp, and they use TMPDIR in a way * Many programs rely on mktemp, and they use TMPDIR in a way
* that is quite insecure. Mkhtemp intends to change that, * that is quite insecure. Mkhtemp intends to change that,
* quite dramatically, with: userspace sandbox (and use OS * quite dramatically, with: userspace sandbox (and use OS
@@ -87,20 +91,13 @@ main(int argc, char *argv[])
int fd = -1; int fd = -1;
int type = MKHTEMP_FILE; int type = MKHTEMP_FILE;
int stfu = 0; /* -q option */
if (lbgetprogname(argv[0]) == NULL) if (lbgetprogname(argv[0]) == NULL)
err_no_cleanup(errno, "could not set progname"); err_mkhtemp(0, errno, "could not set progname");
/* https://man.openbsd.org/pledge.2 */
#if defined(__OpenBSD__) && defined(OpenBSD)
#if (OpenBSD) >= 509
if (pledge("stdio flock rpath wpath cpath", NULL) == -1)
goto err_usage;
#endif
#endif
while ((c = while ((c =
getopt(argc, argv, "dp:")) != -1) { getopt(argc, argv, "qdp:")) != -1) {
switch (c) { switch (c) {
case 'd': case 'd':
@@ -111,28 +108,40 @@ main(int argc, char *argv[])
tmpdir = optarg; tmpdir = optarg;
break; break;
case 'q': /* don't print errors */
/* (exit status unchanged) */
stfu = 1;
break;
default: default:
goto err_usage; goto err_usage;
} }
} }
/* https://man.openbsd.org/pledge.2 */
#if defined(__OpenBSD__) && defined(OpenBSD)
#if (OpenBSD) >= 509
if (pledge("stdio flock rpath wpath cpath", NULL) == -1)
goto err_usage;
#endif
#endif
if (optind < argc) if (optind < argc)
template = argv[optind]; template = argv[optind];
if (optind + 1 < argc) if (optind + 1 < argc)
err_no_cleanup(EINVAL, goto err_usage;
"usage: mkhtemp [-d] [-p dir] [template]\n");
/* custom template e.g. foo.XXXXXXXXXXXXXXXXXXXXX */ /* custom template e.g. foo.XXXXXXXXXXXXXXXXXXXXX */
if (template != NULL) { if (template != NULL) {
if (slen(template, maxlen, &tlen) < 0) if (slen(template, maxlen, &tlen) < 0)
err_no_cleanup(EINVAL, err_mkhtemp(stfu, EINVAL,
"invalid template"); "invalid template");
for (p = template + tlen; for (p = template + tlen;
p > template && *--p == 'X'; xc++); p > template && *--p == 'X'; xc++);
if (xc < 6) if (xc < 6)
err_no_cleanup(EINVAL, err_mkhtemp(stfu, EINVAL,
"template must end in at least 6 X"); "template must end in at least 6 X");
} }
@@ -146,38 +155,35 @@ main(int argc, char *argv[])
if (tmpdir != NULL) { if (tmpdir != NULL) {
rp = realpath(tmpdir, resolved); rp = realpath(tmpdir, resolved);
if (rp == NULL) if (rp == NULL)
err_no_cleanup(errno, err_mkhtemp(stfu, errno, "%s", tmpdir);
"%s", tmpdir);
tmpdir = resolved; tmpdir = resolved;
} }
if (new_tmp_common(&fd, &s, type, if (new_tmp_common(&fd, &s, type,
tmpdir, template) < 0) tmpdir, template) < 0)
err_no_cleanup(errno, "%s", s); err_mkhtemp(stfu, errno, "%s", s);
#if defined(__OpenBSD__) && defined(OpenBSD) #if defined(__OpenBSD__) && defined(OpenBSD)
#if (OpenBSD) >= 509 #if (OpenBSD) >= 509
if (pledge("stdio", NULL) == -1) if (pledge("stdio", NULL) == -1)
err_no_cleanup(errno, "pledge, exit"); err_mkhtemp(errno, "pledge, exit");
#endif #endif
#endif #endif
if (s == NULL) if (s == NULL)
err_no_cleanup(EFAULT, "bad string initialisation"); err_mkhtemp(stfu, EFAULT, "bad string initialisation");
if (*s == '\0') if (*s == '\0')
err_no_cleanup(EFAULT, "empty string initialisation"); err_mkhtemp(stfu, EFAULT, "empty string initialisation");
if (slen(s, maxlen, &len) < 0) if (slen(s, maxlen, &len) < 0)
err_no_cleanup(EFAULT, "unterminated string initialisation"); err_mkhtemp(stfu, EFAULT, "unterminated string initialisiert");
printf("%s\n", s); printf("%s\n", s);
return EXIT_SUCCESS; return EXIT_SUCCESS;
err_usage: err_usage:
err_no_cleanup(EINVAL, err_mkhtemp(stfu, EINVAL,
"usage: %s [-d] [-p dir] [template]\n", getnvmprogname()); "usage: %s [-d] [-p dir] [template]\n", getnvmprogname());
}/* }/*
@@ -191,3 +197,33 @@ err_usage:
*/ */
void
err_mkhtemp(int stfu,
int errval, const char *msg, ...)
{
va_list args;
if (stfu || msg == NULL)
goto out;
va_start(args, msg);
vfprintf(stderr, msg, args);
va_end(args);
err_no_cleanup(errval, msg, args);
out:
exit(EXIT_FAILURE);
}