summaryrefslogtreecommitdiff
path: root/util/nvmutil
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2026-03-22 15:54:48 +0000
committerLeah Rowe <leah@libreboot.org>2026-03-22 16:32:52 +0000
commit7694b307b82d58bd6b08876c432e196baea5d0dc (patch)
tree14569de373758ecdd1aac60dca5ec3be41e80529 /util/nvmutil
parent825d5205757e067f95fb76eefd2c22dcc0edd00c (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>
Diffstat (limited to 'util/nvmutil')
-rw-r--r--util/nvmutil/include/common.h15
-rw-r--r--util/nvmutil/lib/file.c125
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;