mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-03-25 13:29:03 +02:00
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>
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user