diff options
| author | Leah Rowe <leah@libreboot.org> | 2026-03-22 15:54:48 +0000 |
|---|---|---|
| committer | Leah Rowe <leah@libreboot.org> | 2026-03-22 16:32:52 +0000 |
| commit | 7694b307b82d58bd6b08876c432e196baea5d0dc (patch) | |
| tree | 14569de373758ecdd1aac60dca5ec3be41e80529 | |
| parent | 825d5205757e067f95fb76eefd2c22dcc0edd00c (diff) | |
WIP: always use openat
why would i write a secure mktemp to be used
on linux from 1999?????
Signed-off-by: Leah Rowe <leah@libreboot.org>
| -rw-r--r-- | util/nvmutil/include/common.h | 15 | ||||
| -rw-r--r-- | util/nvmutil/lib/file.c | 125 |
2 files changed, 21 insertions, 119 deletions
diff --git a/util/nvmutil/include/common.h b/util/nvmutil/include/common.h index cec06b25..48de3b97 100644 --- a/util/nvmutil/include/common.h +++ b/util/nvmutil/include/common.h @@ -69,13 +69,6 @@ int fchmod(int fd, mode_t mode); #define OFF_RESET 1 #endif -/* by default: allow use - of openat in hardened mkstemp - */ -#ifndef DISABLE_OPENAT -#define DISABLE_OPENAT 0 /* change to 1 if you don't have openat (old unix) */ -#endif - #ifndef S_ISVTX #define S_ISVTX 01000 #endif @@ -482,17 +475,9 @@ const char *getnvmprogname(void); char *new_tmpfile(int *fd, int local, const char *path); char *new_tmplate(int *fd, int local, const char *path); -#if !(defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0)) /* for openat dir replacement mitigation - in mkhtemp() - */ int mkhtemp(int *fd, struct stat *st, char *template, int dirfd, const char *fname, struct stat *st_dir_initial); -#else -int mkhtemp(int *fd, struct stat *st, - char *template); -#endif int world_writeable_and_sticky(const char *s, int sticky_allowed, int always_sticky); int same_dir(const char *a, const char *b); diff --git a/util/nvmutil/lib/file.c b/util/nvmutil/lib/file.c index ec45ac3f..fd93bd6b 100644 --- a/util/nvmutil/lib/file.c +++ b/util/nvmutil/lib/file.c @@ -16,7 +16,6 @@ #include "../include/common.h" - /* check that a file changed */ @@ -261,10 +260,6 @@ new_tmpfile(int *fd, int local, int saved_errno = errno; -#if !(defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0)) /* for openat dir replacement mitigation - in mkhtemp() - */ int dirfd = -1; const char *fname = NULL; @@ -274,7 +269,6 @@ new_tmpfile(int *fd, int local, * attack mitigation */ struct stat st_dir_initial; -#endif char *dir = NULL; char *base = NULL; @@ -415,12 +409,7 @@ new_tmpfile(int *fd, int local, memcpy(dest + 1 + baselen, suffix, sizeof(suffix) - 1); -#if !(defined(DISABLE_OPENAT) && \ -((DISABLE_OPENAT) > 0)) /* for openat dir replacement mitigation - * in mkhtemp( - */ fname = base; -#endif } else { @@ -431,10 +420,6 @@ new_tmpfile(int *fd, int local, memcpy(dest + dirlen + 1, suffix, sizeof(suffix) - 1); -#if !(defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0)) /* for openat dir replacement mitigation - in mkhtemp() - */ dirfd = fs_resolve(tmpdir, O_RDONLY | O_DIRECTORY); if (dirfd < 0) @@ -447,32 +432,24 @@ new_tmpfile(int *fd, int local, goto err_new_tmpfile; fname = dest + dirlen + 1; -#endif } *(dest + destlen) = '\0'; -#if !(defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0)) /* for openat dir replacement mitigation - in mkhtemp() - */ *fd = mkhtemp(fd, &st, dest, dirfd, fname, &st_dir_initial); -#else - *fd = mkhtemp(fd, &st, dest); -#endif if (*fd < 0) goto err_new_tmpfile; -#if !(defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0)) /* for openat dir replacement mitigation - in mkhtemp() - */ if (dirfd >= 0) { (void) close_on_eintr(dirfd); dirfd = -1; } -#endif + + if (dir != NULL) { + free(dir); + dir = NULL; + } errno = saved_errno; return dest; @@ -489,16 +466,11 @@ err_new_tmpfile: dest = NULL; } -#if !(defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0)) /* for openat dir replacement mitigation - in mkhtemp() - */ if (dirfd >= 0) { (void) close_on_eintr(dirfd); dirfd = -1; } -#endif if (*fd >= 0) { @@ -506,6 +478,11 @@ err_new_tmpfile: *fd = -1; } + if (dir != NULL) { + free(dir); + dir = NULL; + } + errno = saved_errno; return NULL; @@ -798,20 +775,12 @@ sticky_hell: * generates files) */ -#if defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0) -int -mkhtemp(int *fd, - struct stat *st, - char *template) -#else int mkhtemp(int *fd, struct stat *st, char *template, int dirfd, const char *fname, struct stat *st_dir_initial) -#endif { /* NOTE: this function currently * only supports *files*. @@ -857,8 +826,6 @@ int mkhtemp(int *fd, int saved_rand_error = 0; -#if !(defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0)) char *fname_copy = NULL; size_t fname_len = 0; @@ -894,7 +861,6 @@ int mkhtemp(int *fd, errno = EBADF; goto err_mkhtemp; } -#endif if (fd == NULL || template == NULL) { @@ -918,9 +884,6 @@ int mkhtemp(int *fd, goto err_mkhtemp; } -#if !(defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0)) - if (strrchr(fname, '/') != NULL) { /* otherwise, a mangled @@ -956,8 +919,6 @@ int mkhtemp(int *fd, } } -#endif - p = template + len; while (p > template && @@ -970,9 +931,6 @@ int mkhtemp(int *fd, goto err_mkhtemp; } -#if !(defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0)) - if (fname_len > len || fname_len > (len - xc)) { @@ -990,8 +948,6 @@ int mkhtemp(int *fd, goto err_mkhtemp; } -#endif - template_copy = malloc(len + 1); if (template_copy == NULL) { @@ -1005,9 +961,6 @@ int mkhtemp(int *fd, */ memcpy(template_copy, template, len + 1); -#if !(defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0)) - /* redundant copy, reduce chance of * mangling (regression mitigation) */ @@ -1025,9 +978,6 @@ int mkhtemp(int *fd, fname_len + 1); p = fname_copy + fname_len - xc; -#else - p = template_copy + len - xc; -#endif for (retries = 0; retries < max_retries; retries++) { @@ -1068,13 +1018,6 @@ retry_rand: p[chx] = ch[r % (sizeof(ch) - 1)]; } -#if defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0) /* openat(2) added to linux in 2006, BSDs later - */ - *fd = open(template_copy, - O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC | - O_NOCTTY, 0600); -#else /* * use the file descriptor instead. * (danach prüfen wir die Sicherheit des Verzeichnisses) @@ -1093,18 +1036,13 @@ retry_rand: *fd = openat(dirfd, fname_copy, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW | O_CLOEXEC | O_NOCTTY, 0600); -#endif if (*fd >= 0) { file_created = 1; -#if !(defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0)) - memcpy(template_copy + len - fname_len, fname_copy, fname_len); -#endif if (secure_file(fd, st, O_APPEND, 1, 1, 0600) < 0) goto err_mkhtemp; @@ -1157,34 +1095,21 @@ err_mkhtemp: /* we created it, so *we* nuke it */ -#if !(defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0)) - if (file_created && fname_copy != NULL) (void) unlinkat(dirfd, fname_copy, 0); -#else - if (file_created) - (void) unlink(template_copy); - -#endif free(template_copy); template_copy = NULL; } -#if !(defined(DISABLE_OPENAT) && \ - ((DISABLE_OPENAT) > 0)) - if (fname_copy != NULL) { free(fname_copy); fname_copy = NULL; } -#endif - errno = saved_errno; /* returning EINTR/EAGAIN @@ -1946,6 +1871,16 @@ fs_resolve(const char *path, int flags) return -1; } + /* block "/" if flags pertain to creation/write. + don't mess with the user's root! + */ + if (path[0] == '/' && path[1] == '\0') { + if (flags & (O_CREAT | O_TRUNC | O_RDWR | O_WRONLY)) { + errno = EISDIR; + return -1; + } + } + if (slen(path, maxlen, &len) < 0) return -1; @@ -2047,26 +1982,11 @@ fs_open_component(int dirfd, const char *name, { int fd; -/* TODO: - open() fallback if DISABLE_OPENAT > 0 - change function signature - and ditto any callers using - the same ifdefs. this would - allow us to implement somewhat - openat-like functionality with - openat2-like features, even on - systems that lack openat(2), - let alone openat2 - */ - fd = openat(dirfd, name, (is_last ? flags : (O_RDONLY | O_DIRECTORY)) | O_NOFOLLOW | O_CLOEXEC); - /* on some systems, O_DIRECTORY is - * ignored or unreliable. We must - * assume that your operating system - * is lying. the OS always lies. + /* the patient always lies */ if (!is_last) { @@ -2091,9 +2011,6 @@ fs_dirname_basename(const char *path, char **dir, char **base, int allow_relative) { -/* TODO: audit maxlen use vs PATH_LEN - -- should implement length checks - */ char *buf; char *slash; size_t len; |
