WIP cleanup

Signed-off-by: Leah Rowe <leah@libreboot.org>
This commit is contained in:
Leah Rowe
2026-03-22 21:59:22 +00:00
parent ca92e7831a
commit 79376a900a
2 changed files with 129 additions and 67 deletions

View File

@@ -324,6 +324,12 @@ size_t conv_argv_part_num(const char *part_str);
*/
void open_gbe_file(void);
int fd_verify_regular(int fd,
const struct stat *expected,
struct stat *out);
int fd_verify_identity(int fd,
const struct stat *expected,
struct stat *out);
int is_owner(struct stat *st);
int lock_file(int fd, int flags);
int same_file(int fd, struct stat *st_old, int check_size);

View File

@@ -56,13 +56,8 @@ same_file(int fd, struct stat *st_old,
if (fstat(fd, &st) == -1)
goto err_same_file;
if (st.st_dev != st_old->st_dev ||
st.st_ino != st_old->st_ino ||
!S_ISREG(st.st_mode)) {
errno = ESTALE;
if (fd_verify_regular(fd, st_old, &st) < 0)
goto err_same_file;
}
if (check_size &&
st.st_size != st_old->st_size)
@@ -90,6 +85,17 @@ err_same_file:
make it return, and handle the return value/errno
(this could return e.g. EINTR)
TODO: this function is not used by mkhtemp, nor will
it probably be, it's currently used by nvmutil,
for opening intel gbe nvm config files. i can
probably remove it though and unify witth some
of the verification code now used for mkhtemp
TODO: and don't abort. return -1. and handle in the caller.
minor obstacle: the mkhtemp code always requires absolute
paths, whereas the gbe editor takes relative paths.
*/
void
xopen(int *fd_ptr, const char *path, int flags, struct stat *st)
@@ -259,15 +265,12 @@ new_tmpfile(int *fd, char **path)
size_t dirlen;
size_t destlen;
size_t baselen;
char *dest = NULL; /* final path */
int saved_errno = errno;
int dirfd = -1;
const char *fname = NULL;
struct stat st_dir_initial;
char *dir = NULL;
char *base = NULL;
if (path == NULL || fd == NULL) {
errno = EFAULT;
@@ -294,6 +297,10 @@ new_tmpfile(int *fd, char **path)
if (slen(tmpdir, maxlen, &dirlen) < 0)
goto err_new_tmpfile;
if (*tmpdir == '\0')
goto err_new_tmpfile;
if (*tmpdir != '/')
goto err_new_tmpfile;
/* using sizeof (not slen) adds an extra byte,
* useful because we either want '.' or '/'
@@ -336,10 +343,6 @@ new_tmpfile(int *fd, char **path)
(void) close_on_eintr(dirfd);
dirfd = -1;
}
if (dir != NULL) {
free(dir);
dir = NULL;
}
errno = saved_errno;
@@ -371,11 +374,6 @@ err_new_tmpfile:
*fd = -1;
}
if (dir != NULL) {
free(dir);
dir = NULL;
}
errno = saved_errno;
return -1;
@@ -694,6 +692,7 @@ mkhtemp(int *fd,
size_t max_len = 4096;
#endif
int r;
char *end;
if (fd == NULL ||
template == NULL ||
@@ -736,14 +735,11 @@ mkhtemp(int *fd,
}
/* count trailing X */
{
char *end = template + len;
end = template + len;
while (end > template && *--end == 'X')
xc++;
while (end > template && *--end == 'X')
xc++;
}
if (xc < 6 || xc > len) {
if (xc < 12 || xc > len) {
errno = EINVAL;
return -1;
}
@@ -784,9 +780,11 @@ mkhtemp(int *fd,
fd,
st);
/* DoS mitigation; add jitter delay (01023 µs) */
if (r != 1 && retries >= MKHTEMP_SPIN_THRESHOLD)
usleep((useconds_t)rlong() & 0x3FF);
if (r != 1) {
if (retries >= MKHTEMP_SPIN_THRESHOLD)
usleep((useconds_t)rlong() & 0x3FF);
continue;
}
/* success: copy final name back */
memcpy(template + len - fname_len,
@@ -825,17 +823,18 @@ mkhtemp_try_create(int dirfd,
struct stat st_open;
int saved_errno = errno;
int close_errno;
int rval = -1;
if (mkhtemp_fill_random(p, xc) < 0)
return -1;
goto err;
if (fstat(dirfd, &st_dir_now) < 0)
return -1;
goto err;
if (st_dir_now.st_dev != st_dir_initial->st_dev ||
st_dir_now.st_ino != st_dir_initial->st_ino) {
errno = ESTALE;
return -1;
goto err;
}
*fd = openat2p(dirfd, fname_copy,
@@ -843,40 +842,53 @@ mkhtemp_try_create(int dirfd,
O_NOFOLLOW | O_CLOEXEC | O_NOCTTY,
0600);
if (*fd >= 0) {
if (*fd < 0) {
if (errno == EEXIST ||
errno == EINTR ||
errno == EAGAIN ||
errno == EWOULDBLOCK ||
errno == ETXTBSY) {
if (fstat(*fd, &st_open) < 0)
return -1;
if (fstat(dirfd, &st_dir_now) < 0)
return -1;
if (st_dir_now.st_dev != st_dir_initial->st_dev ||
st_dir_now.st_ino != st_dir_initial->st_ino) {
close_errno = errno;
(void) close_on_eintr(*fd);
errno = close_errno;
errno = ESTALE;
return -1;
rval = 0;
goto out;
}
if (secure_file(fd, st, &st_open, O_APPEND, 1, 1, 0600) < 0)
return -1;
errno = saved_errno;
return 1; /* success */
goto err;
}
if (errno == EEXIST ||
errno == EINTR ||
errno == EAGAIN ||
errno == EWOULDBLOCK ||
errno == ETXTBSY)
return 0; /* retry */
/* fd is now live */
return -1; /* fatal */
if (fstat(*fd, &st_open) < 0)
goto err;
if (fstat(dirfd, &st_dir_now) < 0)
goto err;
if (st_dir_now.st_dev != st_dir_initial->st_dev ||
st_dir_now.st_ino != st_dir_initial->st_ino) {
errno = ESTALE;
goto err;
}
if (secure_file(fd, st, &st_open,
O_APPEND, 1, 1, 0600) < 0)
goto err;
errno = saved_errno;
rval = 1;
goto out;
err:
close_errno = errno;
if (fd != NULL && *fd >= 0) {
(void) close_on_eintr(*fd);
*fd = -1;
}
errno = close_errno;
rval = -1;
out:
return rval;
}
int
@@ -985,21 +997,17 @@ int secure_file(int *fd,
}
}
if (fstat(*fd, st) == -1)
if (fstat(*fd, &st_now) == -1)
goto err_secure_file;
/* verify inode/device stability */
if (expected != NULL) {
if (st_now.st_dev != expected->st_dev ||
st_now.st_ino != expected->st_ino) {
st_now.st_ino != expected->st_ino) {
errno = ESTALE;
goto err_secure_file;
}
}
/* now copy to caller */
*st = st_now;
if (!S_ISREG(st->st_mode)) {
@@ -1007,6 +1015,9 @@ int secure_file(int *fd,
goto err_secure_file;
}
if (fd_verify_regular(*fd, expected, st) < 0)
goto err_secure_file;
if (check_seek) {
/* check if it's seekable */
@@ -1057,6 +1068,51 @@ err_secure_file:
return -1;
}
int
fd_verify_regular(int fd,
const struct stat *expected,
struct stat *out)
{
if (fd_verify_identity(fd, expected, out) < 0)
return -1;
if (!S_ISREG(out->st_mode)) {
errno = EBADF;
return -1;
}
return 0; /* regular file */
}
int
fd_verify_identity(int fd,
const struct stat *expected,
struct stat *out)
{
struct stat st_now;
int saved_errno = errno;
if (fd < 0 || expected == NULL) {
errno = EFAULT;
return -1;
}
if (fstat(fd, &st_now) < 0)
return -1;
if (st_now.st_dev != expected->st_dev ||
st_now.st_ino != expected->st_ino) {
errno = ESTALE;
return -1;
}
if (out != NULL)
*out = st_now;
errno = saved_errno;
return 0;
}
int
is_owner(struct stat *st)
{
@@ -1812,7 +1868,7 @@ fs_open(const char *path, int flags)
}
fs = rootfs();
if (!fs)
if (fs == NULL)
return -1;
rel = path + 1;