WIP: remove local mode in mkhtemp + cleanup

bloat

unveil can get pledged

Signed-off-by: Leah Rowe <leah@libreboot.org>
This commit is contained in:
Leah Rowe
2026-03-22 19:49:50 +00:00
parent b8ababa2be
commit a505cb261a
3 changed files with 33 additions and 125 deletions

View File

@@ -2,6 +2,7 @@
* Copyright (c) 2022-2026 Leah Rowe <leah@libreboot.org>
*/
#ifndef COMMON_H
#define COMMON_H
@@ -477,8 +478,8 @@ const char *getnvmprogname(void);
/* libc hardening
*/
char *new_tmpfile(int *fd, int local, const char *path);
char *new_tmplate(int *fd, int local, const char *path);
char *new_tmpfile(int *fd);
char *new_tmplate(int *fd);
int mkhtemp(int *fd, struct stat *st,
char *template, int dirfd, const char *fname,
struct stat *st_dir_initial);

View File

@@ -4,6 +4,11 @@
* Pathless i/o
*/
#if defined(__linux__) && !defined(_GNU_SOURCE)
/* for openat2 syscall on linux */
#define _GNU_SOURCE 1
#endif
#include <sys/types.h>
#include <sys/stat.h>
@@ -227,31 +232,20 @@ err_fsync_dir:
}
/* hardened tmpfile creation
*
* if not local, a standard world
* writeable directory (e.g. /tmp)
* will be used. otherwise,
* the path is simply suffixed for
* local tmp file (no world check)
*
* sets a file descriptor by pointer
* fd, and returns the path as a
* string (for your new tmp file)
*
* on error, the descriptor will be
* set to -1 and errno will be set,
* to indicate the error, and then
* a NULL pointer will be returned.
*/
char *
new_tmpfile(int *fd, int local,
const char *path)
new_tmpfile(int *fd)
{
/* TODO:
* directory support (currently only files)
*/
size_t maxlen;
#if defined(PATH_LEN) && \
(PATH_LEN) >= 256
size_t maxlen = PATH_LEN;
#else
size_t maxlen = 4096;
#endif
struct stat st;
char suffix[] =
@@ -262,11 +256,8 @@ new_tmpfile(int *fd, int local,
size_t pathlen;
size_t destlen;
size_t baselen;
char *dest = NULL; /* final path */
int saved_errno = errno;
int dirfd = -1;
const char *fname = NULL;
@@ -276,7 +267,6 @@ new_tmpfile(int *fd, int local,
* attack mitigation
*/
struct stat st_dir_initial;
char *dir = NULL;
char *base = NULL;
@@ -302,63 +292,24 @@ new_tmpfile(int *fd, int local,
*/
*fd = -1;
#if defined(PATH_LEN) && \
(PATH_LEN) >= 256
maxlen = PATH_LEN;
#else
maxlen = 4096;
#endif
/* base dir e.g. /tmp
*/
if (!local) {
#if defined(PERMIT_NON_STICKY_ALWAYS) && \
((PERMIT_NON_STICKY_ALWAYS) > 0)
tmpdir = env_tmpdir(PERMIT_NON_STICKY_ALWAYS);
tmpdir = env_tmpdir(PERMIT_NON_STICKY_ALWAYS);
#else
tmpdir = env_tmpdir(0);
tmpdir = env_tmpdir(0);
#endif
if (tmpdir == NULL)
goto err_new_tmpfile;
}
if (tmpdir == NULL)
goto err_new_tmpfile;
/* local means we want
* e.g. hello.txt to then
* have a tmpfile created
* for it. useful for
* atomic writes
*/
if (local) {
if (path == NULL) {
errno = EFAULT;
goto err_new_tmpfile;
}
if (*path == '\0') {
errno = EINVAL;
goto err_new_tmpfile;
}
if (slen(tmpdir, maxlen, &dirlen) < 0)
goto err_new_tmpfile;
if (slen(path, maxlen, &pathlen) < 0)
goto err_new_tmpfile;
if (path[pathlen - 1] == '/') {
errno = EINVAL;
goto err_new_tmpfile;
}
dirlen = 0;
} else {
if (slen(tmpdir, maxlen, &dirlen) < 0)
goto err_new_tmpfile;
pathlen = 0;
}
pathlen = 0;
/* now we want the base dir,
* with the file appended,
@@ -394,51 +345,17 @@ new_tmpfile(int *fd, int local,
goto err_new_tmpfile; /* pre-emptive fix */
}
if (local) {
*(dest + dirlen) = '/';
memcpy(dest, tmpdir, dirlen);
memcpy(dest + dirlen + 1, suffix,
sizeof(suffix) - 1);
if (fs_dirname_basename(path, &dir, &base, 0) < 0)
goto err_new_tmpfile;
dirfd = fs_open(tmpdir,
O_RDONLY | O_DIRECTORY);
if (dirfd < 0)
goto err_new_tmpfile;
if (slen(base, maxlen, &baselen) < 0)
goto err_new_tmpfile;
/* ALWAYS set this right after
* split path, to avoid leaking fd:
*/
dirfd = fs_open(dir, O_RDONLY | O_DIRECTORY);
if (dirfd < 0)
goto err_new_tmpfile;
*(dest) = '.';
memcpy(dest + 1, base, baselen);
memcpy(dest + 1 + baselen,
suffix, sizeof(suffix) - 1);
fname = base;
} else {
memcpy(dest, tmpdir, dirlen);
*(dest + dirlen) = '/';
memcpy(dest + dirlen + 1, suffix,
sizeof(suffix) - 1);
dirfd = fs_open(tmpdir,
O_RDONLY | O_DIRECTORY);
if (dirfd < 0)
goto err_new_tmpfile;
/* we will use this later, throughout,
* for detecting **directory replacement**
*/
fname = dest + dirlen + 1;
}
fname = dest + dirlen + 1;
if (fstat(dirfd, &st_dir_initial) < 0)
goto err_new_tmpfile;
@@ -446,7 +363,6 @@ new_tmpfile(int *fd, int local,
*(dest + destlen) = '\0';
*fd = mkhtemp(fd, &st, dest, dirfd, fname, &st_dir_initial);
if (*fd < 0)
goto err_new_tmpfile;

View File

@@ -89,8 +89,6 @@ xstart(int argc, char *argv[])
};
struct xstate *x = &us;
if (!first_run) {
if (pre_init)
err_no_cleanup(ECANCELED,
@@ -114,17 +112,10 @@ xstart(int argc, char *argv[])
us.argv0 = argv[0];
us.f.fname = argv[1];
#if defined(__OpenBSD__) && defined(OpenBSD) && \
(OpenBSD) >= 604
/* can only use local tmp on openbsd, due to unveil */
us.f.tname = new_tmpfile(&us.f.tmp_fd, 1, NULL);
#else
// TODO: new_tmplate (do for above too)
us.f.tname = new_tmpfile(&us.f.tmp_fd, 0, NULL); // TODO: NULL BAD!
#endif
us.f.tname = new_tmpfile(&us.f.tmp_fd);
/* parse user command */
// TODO: CHECK ACCESSES VIA xstatus()
/* TODO: CHECK ACCESSES VIA xstatus() */
set_cmd(argc, argv);
set_cmd_args(argc, argv);