diff options
| author | Leah Rowe <leah@libreboot.org> | 2026-03-23 05:22:01 +0000 |
|---|---|---|
| committer | Leah Rowe <leah@libreboot.org> | 2026-03-23 05:32:34 +0000 |
| commit | 186d612ac76cd4c12db47cc2cb92590145a65a40 (patch) | |
| tree | e9addd598864cb24560623a9c7cf4bc3dbc4faba | |
| parent | 1f7d4c72f4d8b01d72a0e2bb27fa19689533ca25 (diff) | |
WIP: "finished"
Signed-off-by: Leah Rowe <leah@libreboot.org>
| -rw-r--r-- | util/nvmutil/include/common.h | 2 | ||||
| -rw-r--r-- | util/nvmutil/lib/file.c | 121 |
2 files changed, 83 insertions, 40 deletions
diff --git a/util/nvmutil/include/common.h b/util/nvmutil/include/common.h index a546e464..4aca1772 100644 --- a/util/nvmutil/include/common.h +++ b/util/nvmutil/include/common.h @@ -494,6 +494,8 @@ const char *getnvmprogname(void); */ int new_tmpfile(int *fd, char **path); +int new_tmpdir(int *fd, char **path); +static int new_tmp_common(int *fd, char **path, int type); static int mkhtemp_try_create(int dirfd, struct stat *st_dir_initial, char *fname_copy, diff --git a/util/nvmutil/lib/file.c b/util/nvmutil/lib/file.c index b605d488..5dfe5947 100644 --- a/util/nvmutil/lib/file.c +++ b/util/nvmutil/lib/file.c @@ -1,7 +1,8 @@ /* SPDX-License-Identifier: MIT * Copyright (c) 2026 Leah Rowe <leah@libreboot.org> * - * Pathless i/o + * Pathless i/o, and some stuff you probably never saw. + * Be nice to the demon. */ #if defined(__linux__) && !defined(_GNU_SOURCE) @@ -241,17 +242,62 @@ err_fsync_dir: return -1; } -/* hardened tmpfile creation +/* hardened tmpfile and tmpdir creation. + * obsessively hardened, to the point that + * you could even say it is unhinged. + * + * much stricter than mkstemp. + * + * userspace sandboxing. TOCTOU-aware, + * much stricter than typical libc/mkstemp. + * TODO: write docs! right now the documentation + * is both tthe code and the specification. + * this code will likely be hardened more, over + * time, until a matured stable release can be + * made. i intend for this to go in linux distros + * and BSD source trees eventually, as a standalone + * utility. + * + * NOTE TO LINUX DISTROS / BSDs: more testing + * and auditing needed before putting this + * in your project. this comment will be removed + * after the code has matured for a while. this + * is a rough implementation, already carefully + * audited by one person: me + * + * expect bugs. one day, when this is ready, + * i will make a lot more of the options configurable + * at runtime, and add a special compatibility mode + * so that it can also run like regular mktemp, + * for compatibility; running mkhtemp with all the + * hardening means you get very non-standard behaviour, + * e.g. it's much stricter about ownership/permissions, + * sticky bits, and regards as fault conditions, what + * would be considered normal in mkstemp/mktemp. + * + * a full manual and specification will be written when + * this code is fully matured, and then i will probably + * start spamming your mailing lists myself ;) */ /* returns opened fd, sets fd and *path at pointers *fd and *path */ /* also sets external stat */ + int new_tmpfile(int *fd, char **path) { -/* TODO: - * directory support (currently only files) - */ + return new_tmp_common(fd, path, MKHTEMP_FILE); +} + +int +new_tmpdir(int *fd, char **path) +{ + return new_tmp_common(fd, path, MKHTEMP_DIR); +} + +static int +new_tmp_common(int *fd, char **path, int type) +{ #if defined(PATH_LEN) && \ (PATH_LEN) >= 256 size_t maxlen = PATH_LEN; @@ -267,7 +313,7 @@ new_tmpfile(int *fd, char **path) int close_errno; size_t dirlen; size_t destlen; - char *dest = NULL; /* final path */ + char *dest = NULL; /* final path (will be written into "path") */ int saved_errno = errno; int dirfd = -1; const char *fname = NULL; @@ -276,26 +322,25 @@ new_tmpfile(int *fd, char **path) if (path == NULL || fd == NULL) { errno = EFAULT; - goto err_new_tmpfile; + goto err; } - /* don't mess with someone's file - * if already opened - */ + /* don't mess with someone elses file */ if (*fd >= 0) { errno = EEXIST; - goto err_new_tmpfile; + goto err; } /* regarding **path: - * the pointer (to the pointer) - * must nott be null, but we don't - * care about the pointer it points - * to. you should expect it to be - * replaced upon successful return - * - * (on error, it will not be touched) - */ + * the pointer (to the pointer) + * must nott be null, but we don't + * care about the pointer it points + * to. you should expect it to be + * replaced upon successful return + * + * (on error, it will not be touched) + */ + *fd = -1; @@ -306,30 +351,28 @@ new_tmpfile(int *fd, char **path) tmpdir = env_tmpdir(0); #endif if (tmpdir == NULL) - goto err_new_tmpfile; + goto err; if (slen(tmpdir, maxlen, &dirlen) < 0) - goto err_new_tmpfile; + goto err; if (*tmpdir == '\0') - goto err_new_tmpfile; + goto err; if (*tmpdir != '/') - goto err_new_tmpfile; + goto err; - /* using sizeof (not slen) adds an extra byte, - * useful because we either want '.' or '/' + /* sizeof adds an extra byte, useful + * because we also want '.' or '/' */ destlen = dirlen + sizeof(suffix); - if (destlen > maxlen - 1) { /* -1 for NULL */ - + if (destlen > maxlen - 1) { errno = EOVERFLOW; - goto err_new_tmpfile; + goto err; } - dest = malloc(destlen + 1); /* +1 for NULL */ + dest = malloc(destlen + 1); if (dest == NULL) { - errno = ENOMEM; - goto err_new_tmpfile; + goto err; } memcpy(dest, tmpdir, dirlen); @@ -337,21 +380,20 @@ new_tmpfile(int *fd, char **path) memcpy(dest + dirlen + 1, suffix, sizeof(suffix) - 1); *(dest + destlen) = '\0'; - /* new tmpfile name */ fname = dest + dirlen + 1; dirfd = fs_open(tmpdir, O_RDONLY | O_DIRECTORY); if (dirfd < 0) - goto err_new_tmpfile; + goto err; if (fstat(dirfd, &st_dir_initial) < 0) - goto err_new_tmpfile; + goto err; *fd = mkhtemp(fd, &st, dest, dirfd, - fname, &st_dir_initial, MKHTEMP_FILE); + fname, &st_dir_initial, type); if (*fd < 0) - goto err_new_tmpfile; + goto err; if (dirfd >= 0) { close_errno = errno; @@ -361,12 +403,11 @@ new_tmpfile(int *fd, char **path) } errno = saved_errno; - *path = dest; return 0; - -err_new_tmpfile: + +err: if (errno != saved_errno) saved_errno = errno; @@ -393,10 +434,10 @@ err_new_tmpfile: } errno = saved_errno; - return -1; } + /* hardened TMPDIR parsing */ |
