diff options
| author | Leah Rowe <leah@libreboot.org> | 2026-03-31 15:43:43 +0100 |
|---|---|---|
| committer | Leah Rowe <leah@libreboot.org> | 2026-03-31 17:49:23 +0100 |
| commit | d2abde53033d58b6665becd75f854ad87aba33f6 (patch) | |
| tree | b1cd0849ae62dc950f4b07205bf2dadf7bc484aa | |
| parent | c0fd88155a83a0e080eaa769d5035a3c36d6d0fe (diff) | |
libreboot-utils: stricter errno handling
where possible, try not to clobber sys errno. override
it only when relatively safe.
also: when a syscall succeeds, it may set errno. this
is rare, but permitted (nothing specified against it
in specs, and the specs say that errno is undefined
on success).
i'm not libc, but i'm wrapping around it, so i need
to be careful in how i handle the errno value.
also:
i removed the requirement for directories to be
executable, in mkhtemp.c, because this isn't required
and will only break certain setups.
in world_writeable and sticky, i made the checks stricter:
the faccessat check was being skipped on some paths, so
i've closed that loophole now.
i also generally cleaned up some code, as part of the errno
handling refactoring, where it made sense to do so, plus a
few other bits of code cleanup.
Signed-off-by: Leah Rowe <leah@libreboot.org>
| -rw-r--r-- | util/libreboot-utils/include/common.h | 28 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/command.c | 6 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/file.c | 288 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/io.c | 7 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/mkhtemp.c | 398 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/num.c | 6 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/rand.c | 11 | ||||
| -rw-r--r-- | util/libreboot-utils/lib/string.c | 54 | ||||
| -rw-r--r-- | util/libreboot-utils/lottery.c | 1 | ||||
| -rw-r--r-- | util/libreboot-utils/mkhtemp.c | 14 | ||||
| -rw-r--r-- | util/libreboot-utils/nvmutil.c | 6 |
11 files changed, 370 insertions, 449 deletions
diff --git a/util/libreboot-utils/include/common.h b/util/libreboot-utils/include/common.h index bc0eb3b3..48831ea3 100644 --- a/util/libreboot-utils/include/common.h +++ b/util/libreboot-utils/include/common.h @@ -26,6 +26,24 @@ #include <unistd.h> #endif +/* dangerously cool macros: + */ + +#define SUCCESS(x) ((x) >= 0) + +/* syscalls can set errno even on success; this + * is rare, but permitted. in various functions, we + * reset errno on success, to what the caller had, + * but we must still honour what was returned. + * + * lib/file.c is littered with examples + */ +#define reset_caller_errno(return_value) \ + do { \ + if (SUCCESS(return_value) && (!errno)) \ + errno = saved_errno; \ + } while (0) + #define items(x) (sizeof((x)) / sizeof((x)[0])) /* system prototypes @@ -464,7 +482,7 @@ ssize_t rw_gbe_file_exact(int fd, unsigned char *mem, size_t nrw, int fsync_dir(const char *path); ssize_t rw_file_exact(int fd, unsigned char *mem, size_t len, off_t off, int rw_type, size_t max_retries, int off_reset); -ssize_t prw(int fd, void *mem, size_t nrw, +ssize_t rw(int fd, void *mem, size_t nrw, off_t off, int rw_type); int io_args(int fd, void *mem, size_t nrw, off_t off, int rw_type); @@ -489,7 +507,7 @@ int rw_retry(int saved_errno, ssize_t rval); */ void usage(void); -int set_errno(int saved_errno, int fallback); +int with_fallback_errno(int fallback); void err_exit(int nvm_errval, const char *msg, ...); func_t errhook(func_t ptr); /* hook function for cleanup on err */ const char *lbgetprogname(void); @@ -506,7 +524,7 @@ int new_tmpdir(int *fd, char **path, char *tmpdir, int new_tmp_common(int *fd, char **path, int type, char *tmpdir, const char *template); int mkhtemp_try_create(int dirfd, - struct stat *st_dir_initial, + struct stat *st_dir_first, char *fname_copy, char *p, size_t xc, @@ -515,7 +533,7 @@ int mkhtemp_try_create(int dirfd, int type); int mkhtemp_tmpfile_linux(int dirfd, - struct stat *st_dir_initial, + struct stat *st_dir_first, char *fname_copy, char *p, size_t xc, @@ -523,7 +541,7 @@ mkhtemp_tmpfile_linux(int dirfd, struct stat *st); int mkhtemp(int *fd, struct stat *st, char *template, int dirfd, const char *fname, - struct stat *st_dir_initial, int type); + struct stat *st_dir_first, int type); 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/libreboot-utils/lib/command.c b/util/libreboot-utils/lib/command.c index 16ca8346..5ccf9de9 100644 --- a/util/libreboot-utils/lib/command.c +++ b/util/libreboot-utils/lib/command.c @@ -15,9 +15,6 @@ #include "../include/common.h" -/* Guard against regressions by maintainers (command table) - */ - void sanitize_command_list(void) { @@ -496,8 +493,7 @@ cat_buf(unsigned char *b) err_exit(errno, "null pointer in cat command"); if (rw_file_exact(STDOUT_FILENO, b, - GBE_PART_SIZE, 0, IO_WRITE, MAX_ZERO_RW_RETRY, OFF_ERR) - < 0) + GBE_PART_SIZE, 0, IO_WRITE, MAX_ZERO_RW_RETRY, OFF_ERR) < 0) err_exit(errno, "stdout: cat"); } void diff --git a/util/libreboot-utils/lib/file.c b/util/libreboot-utils/lib/file.c index 42c91843..805db726 100644 --- a/util/libreboot-utils/lib/file.c +++ b/util/libreboot-utils/lib/file.c @@ -44,51 +44,31 @@ same_file(int fd, struct stat *st_old, { struct stat st; int saved_errno = errno; + int rval = 0; + errno = 0; - /* TODO: null/-1 checks - * like this can be - * generalised - */ - if (st_old == NULL) { - errno = EFAULT; - goto err_same_file; - } - if (fd < 0) { - errno = EBADF; - goto err_same_file; - } - - if (fstat(fd, &st) == -1) - goto err_same_file; - - if (fd_verify_regular(fd, st_old, &st) < 0) - goto err_same_file; - - if (check_size && - st.st_size != st_old->st_size) - goto err_same_file; + if (if_err(st_old == NULL, EFAULT) || + if_err(fd < 0, EBADF) || + (rval = fstat(fd, &st)) < 0 || + (rval = fd_verify_regular(fd, st_old, &st)) < 0 || + if_err(check_size && st.st_size != st_old->st_size, ESTALE)) + return with_fallback_errno(ESTALE); - errno = saved_errno; + reset_caller_errno(rval); return 0; - -err_same_file: - return set_errno(saved_errno, ESTALE); } int fsync_dir(const char *path) { int saved_errno = errno; - size_t pathlen = 0; - char *dirbuf = NULL; int dirfd = -1; - char *slash = NULL; struct stat st = {0}; - - int close_errno; + int rval = 0; + errno = 0; if (if_err(slen(path, PATH_MAX, &pathlen) == 0, EINVAL)) goto err_fsync_dir; @@ -119,26 +99,23 @@ fsync_dir(const char *path) ); if (if_err_sys(dirfd < 0) || - if_err_sys(fstat(dirfd, &st) < 0) || + if_err_sys((rval = fstat(dirfd, &st)) < 0) || if_err(!S_ISDIR(st.st_mode), ENOTDIR) || - if_err_sys(fsync_on_eintr(dirfd) == -1)) + if_err_sys((rval = fsync_on_eintr(dirfd)) == -1)) goto err_fsync_dir; close_on_eintr(&dirfd); - free_and_set_null(&dirbuf); - errno = saved_errno; + reset_caller_errno(rval); return 0; err_fsync_dir: - - free_and_set_null(&dirbuf); close_on_eintr(&dirfd); - return set_errno(saved_errno, EIO); + return with_fallback_errno(EIO); } /* rw_file_exact() - Read perfectly or die @@ -162,34 +139,23 @@ ssize_t rw_file_exact(int fd, unsigned char *mem, size_t nrw, off_t off, int rw_type, size_t max_retries, int off_reset) { - ssize_t rval; - ssize_t rc; - + int saved_errno = errno; + ssize_t rval = 0; + ssize_t rc = 0; size_t nrw_cur; - off_t off_cur; void *mem_cur; - - size_t retries_on_zero; - - int saved_errno = errno; + size_t retries_on_zero = 0; errno = 0; - rval = 0; - - rc = 0; - retries_on_zero = 0; - if (io_args(fd, mem, nrw, off, rw_type) == -1) goto err_rw_file_exact; while (1) { /* Prevent theoretical overflow */ - if (rval >= 0 && (size_t)rval > (nrw - rc)) { - errno = EOVERFLOW; + if (if_err(rval >= 0 && (size_t)rval > (nrw - rc), EOVERFLOW)) goto err_rw_file_exact; - } rc += rval; if ((size_t)rc >= nrw) @@ -198,50 +164,36 @@ rw_file_exact(int fd, unsigned char *mem, size_t nrw, mem_cur = (void *)(mem + (size_t)rc); nrw_cur = (size_t)(nrw - (size_t)rc); - if (off < 0) { - errno = EOVERFLOW; + if (if_err(off < 0, EOVERFLOW)) goto err_rw_file_exact; - } off_cur = off + (off_t)rc; - rval = prw(fd, mem_cur, nrw_cur, off_cur, - rw_type); - - if (rval < 0) + if ((rval = rw(fd, mem_cur, nrw_cur, off_cur, rw_type)) < 0) goto err_rw_file_exact; if (rval == 0) { if (retries_on_zero++ < max_retries) continue; - errno = EIO; goto err_rw_file_exact; } retries_on_zero = 0; } - if ((size_t)rc != nrw) { - - errno = EIO; - goto err_rw_file_exact; - } - - rval = rw_over_nrw(rc, nrw); - if (rval < 0) + if (if_err((size_t)rc != nrw, EIO) || + (rval = rw_over_nrw(rc, nrw)) < 0) goto err_rw_file_exact; - errno = saved_errno; - + reset_caller_errno(rval); return rval; err_rw_file_exact: - - return set_errno(saved_errno, EIO); + return with_fallback_errno(EIO); } -/* prw() - portable read-write with more +/* rw() - read-write but with more * safety checks than barebones libc * * A fallback is provided for regular read/write. @@ -250,35 +202,40 @@ err_rw_file_exact: */ ssize_t -prw(int fd, void *mem, size_t nrw, +rw(int fd, void *mem, size_t nrw, off_t off, int rw_type) { - ssize_t rval; - ssize_t r; + ssize_t rval = 0; + ssize_t r = -1; struct stat st; int saved_errno = errno; errno = 0; if (io_args(fd, mem, nrw, off, rw_type) == -1) - return set_errno(saved_errno, EIO); - - r = -1; + return with_fallback_errno(EINVAL); - if (rw_type == IO_WRITE) + switch (rw_type) { + case IO_WRITE: r = write_on_eintr(fd, mem, nrw); - else if (rw_type == IO_READ) + break; + case IO_READ: r = read_on_eintr(fd, mem, nrw); - else if (rw_type == IO_PWRITE) + break; + case IO_PWRITE: r = pwrite_on_eintr(fd, mem, nrw, off); - else if (rw_type == IO_PREAD) + break; + case IO_PREAD: r = pread_on_eintr(fd, mem, nrw, off); + break; + default: + errno = EINVAL; + break; + } if ((rval = rw_over_nrw(r, nrw)) < 0) - return set_errno(saved_errno, EIO); - - if (rval >= 0 && !errno) - errno = saved_errno; + return with_fallback_errno(EIO); + reset_caller_errno(rval); return rval; } @@ -287,6 +244,7 @@ io_args(int fd, void *mem, size_t nrw, off_t off, int rw_type) { int saved_errno = errno; + errno = 0; if (if_err(mem == NULL, EFAULT) || if_err(fd < 0, EBADF) || @@ -297,29 +255,31 @@ io_args(int fd, void *mem, size_t nrw, if_err(rw_type > IO_PWRITE, EINVAL)) goto err_io_args; - errno = saved_errno; + reset_caller_errno(0); return 0; err_io_args: - return set_errno(saved_errno, EINVAL); + return with_fallback_errno(EINVAL); } int check_file(int fd, struct stat *st) { int saved_errno = errno; + int rval = 0; + errno = 0; if (if_err(fd < 0, EBADF) || if_err(st == NULL, EFAULT) || - if_err(fstat(fd, st) == -1, 0) || + ((rval = fstat(fd, st)) == -1) || if_err(!S_ISREG(st->st_mode), EBADF)) goto err_is_file; - errno = saved_errno; + reset_caller_errno(rval); return 0; err_is_file: - return set_errno(saved_errno, EINVAL); + return with_fallback_errno(EINVAL); } /* POSIX can say whatever it wants. @@ -328,15 +288,12 @@ err_is_file: ssize_t rw_over_nrw(ssize_t r, size_t nrw) { - int saved_errno = errno; - - if (if_err(!nrw, 0) || - if_err(r == -1, 0) || + if (if_err(!nrw, EIO) || + (r == -1) || if_err((size_t)r > SSIZE_MAX, ERANGE) || if_err((size_t)r > nrw, ERANGE)) - return set_errno(saved_errno, EIO); + return with_fallback_errno(EIO); - errno = saved_errno; return r; } @@ -347,10 +304,8 @@ if_err(int condition, int errval) { if (!condition) return 0; - if (errval) errno = errval; - return 1; } int @@ -431,6 +386,7 @@ fs_resolve_at(int dirfd, const char *path, int flags) int saved_errno = errno; int r; int is_last; + errno = 0; if (dirfd < 0 || path == NULL || *path == '\0') { errno = EINVAL; @@ -461,7 +417,7 @@ fs_resolve_at(int dirfd, const char *path, int flags) nextfd = -1; } - errno = saved_errno; + reset_caller_errno(0); return curfd; err: @@ -475,7 +431,7 @@ err: close_on_eintr(&curfd); errno = saved_errno; - return -1; + return with_fallback_errno(EIO); } /* NOTE: @@ -515,41 +471,36 @@ fs_next_component(const char **p, name[len] = '\0'; /* reject . and .. */ - if ((name[0] == '.' && name[1] == '\0') || - (name[0] == '.' && name[1] == '.' && name[2] == '\0')) { - errno = EPERM; - return -1; - } + if (if_err((name[0] == '.' && name[1] == '\0') || + (name[0] == '.' && name[1] == '.' && name[2] == '\0'), EPERM)) + goto err; *p = s + len; return 1; +err: + return with_fallback_errno(EPERM); } int fs_open_component(int dirfd, const char *name, int flags, int is_last) { + int saved_errno = errno; int fd; struct stat st; + errno = 0; fd = openat_on_eintr(dirfd, name, (is_last ? flags : (O_RDONLY | O_DIRECTORY)) | O_NOFOLLOW | O_CLOEXEC, (flags & O_CREAT) ? 0600 : 0); - if (!is_last) { - - if (if_err(fd < 0, EBADF) || - if_err_sys(fstat(fd, &st) < 0)) - return -1; - - if (!S_ISDIR(st.st_mode)) { - - close_on_eintr(&fd); - errno = ENOTDIR; - return -1; - } - } + if (!is_last && + (if_err(fd < 0, EBADF) || + if_err_sys(fstat(fd, &st) < 0) || + if_err(!S_ISDIR(st.st_mode), ENOTDIR))) + return with_fallback_errno(EIO); + reset_caller_errno(fd); return fd; } @@ -558,13 +509,14 @@ fs_dirname_basename(const char *path, char **dir, char **base, int allow_relative) { + int saved_errno = errno; char *buf = NULL; char *slash; size_t len; - int rval; + errno = 0; if (if_err(path == NULL || dir == NULL || base == NULL, EFAULT)) - return -1; + goto err; slen(path, PATH_MAX, &len); memcpy(smalloc(&buf, len + 1), @@ -591,12 +543,14 @@ fs_dirname_basename(const char *path, sdup(".", PATH_MAX, dir); *base = buf; } else { - errno = EINVAL; free_and_set_null(&buf); - return -1; + goto err; } + reset_caller_errno(0); return 0; +err: + return with_fallback_errno(EINVAL); } /* TODO: why does this abort, but others @@ -608,7 +562,8 @@ open_file_on_eintr(const char *path, struct stat *st) { int saved_errno = errno; - int rval; + int rval = 0; + errno = 0; if (path == NULL) err_exit(EINVAL, "open_file_on_eintr: null path"); @@ -626,8 +581,17 @@ open_file_on_eintr(const char *path, err_exit(errno, "%s: open_file_on_eintr: could not close", path); + reset_caller_errno(rval); *fd = rval; + /* we don't care about edge case behaviour here, + even if the next operation sets errno on success, + because the open() call is our main concern. + however, we also must preserve the new errno, + assuming it changed above under the same edge case */ + + saved_errno = errno; + if (st != NULL) { if (fstat(*fd, st) < 0) err_exit(errno, "%s: stat", path); @@ -639,7 +603,7 @@ open_file_on_eintr(const char *path, if (lseek_on_eintr(*fd, 0, SEEK_CUR, 1, 1) == (off_t)-1) err_exit(errno, "%s: file not seekable", path); - errno = saved_errno; + errno = saved_errno; /* see previous comment */ } @@ -657,20 +621,24 @@ openat_on_eintr(int dirfd, const char *path, RESOLVE_NO_MAGICLINKS }; int saved_errno = errno; - long rval; + long rval = 0; + errno = 0; if (if_err(dirfd < 0, EBADF) || if_err(path == NULL, EFAULT)) - return set_errno(saved_errno, EIO); + goto err; errno = 0; while (sys_retry(saved_errno, rval = syscall(SYS_openat2, dirfd, path, &how, sizeof(how)))); if (rval == -1) /* avoid long->int UB for -1 */ - return -1; + goto err; + reset_caller_errno(rval); return (int)rval; +err: + return with_fallback_errno(EIO); /* -1 */ } #else /* regular openat on non-linux e.g. openbsd */ int @@ -678,16 +646,17 @@ openat_on_eintr(int dirfd, const char *path, int flags, mode_t mode) { int saved_errno = errno; - int rval; + int rval = 0; + errno = 0; if (if_err(dirfd < 0, EBADF) || if_err(path == NULL, EFAULT)) - return set_errno(saved_errno, EIO); + return with_fallback_errno(EIO); - errno = 0; while (fs_retry(saved_errno, rval = openat(dirfd, path, flags, mode))); + reset_caller_errno(rval); return rval; } #endif @@ -697,12 +666,13 @@ lseek_on_eintr(int fd, off_t off, int whence, int loop_eagain, int loop_eintr) { int saved_errno = errno; - off_t rval; - + off_t rval = 0; errno = 0; + while (off_retry(saved_errno, rval = lseek(fd, off, whence))); + reset_caller_errno(rval); return rval; } @@ -711,16 +681,17 @@ mkdirat_on_eintr(int dirfd, const char *path, mode_t mode) { int saved_errno = errno; - int rval; + int rval = 0; + errno = 0; if (if_err(dirfd < 0, EBADF) || if_err(path == NULL, EFAULT)) - return set_errno(saved_errno, EIO); + return with_fallback_errno(EIO); - errno = 0; while (fs_retry(saved_errno, rval = mkdirat(dirfd, path, mode))); + reset_caller_errno(rval); return rval; } @@ -729,17 +700,18 @@ read_on_eintr(int fd, void *buf, size_t count) { int saved_errno = errno; - ssize_t rval; + ssize_t rval = 0; + errno = 0; if (if_err(buf == NULL, EFAULT) || if_err(fd < 0, EBADF) || if_err(count == 0, EINVAL)) - return set_errno(saved_errno, EIO); + return with_fallback_errno(EIO); - errno = 0; while (rw_retry(saved_errno, rval = read(fd, buf, count))); + reset_caller_errno(rval); return rval; } @@ -749,18 +721,19 @@ pread_on_eintr(int fd, off_t off) { int saved_errno = errno; - ssize_t rval; + ssize_t rval = 0; + errno = 0; if (if_err(buf == NULL, EFAULT) || if_err(fd < 0, EBADF) || if_err(off < 0, EFAULT) || if_err(count == 0, EINVAL)) - return set_errno(saved_errno, EIO); + return with_fallback_errno(EIO); - errno = 0; while (rw_retry(saved_errno, rval = pread(fd, buf, count, off))); + reset_caller_errno(rval); return rval; } @@ -769,17 +742,18 @@ write_on_eintr(int fd, void *buf, size_t count) { int saved_errno = errno; - ssize_t rval; + ssize_t rval = 0; + errno = 0; if (if_err(buf == NULL, EFAULT) || if_err(fd < 0, EBADF) || if_err(count == 0, EINVAL)) - return set_errno(saved_errno, EIO); + return with_fallback_errno(EIO); - errno = 0; while (rw_retry(saved_errno, rval = write(fd, buf, count))); + reset_caller_errno(rval); return rval; } @@ -789,18 +763,19 @@ pwrite_on_eintr(int fd, off_t off) { int saved_errno = errno; - ssize_t rval; + ssize_t rval = 0; + errno = 0; if (if_err(buf == NULL, EFAULT) || if_err(fd < 0, EBADF) || if_err(off < 0, EFAULT) || if_err(count == 0, EINVAL)) - return set_errno(saved_errno, EIO); + return with_fallback_errno(EIO); - errno = 0; while (rw_retry(saved_errno, rval = pwrite(fd, buf, count, off))); + reset_caller_errno(rval); return rval; } @@ -808,15 +783,16 @@ int fsync_on_eintr(int fd) { int saved_errno = errno; - int rval; + int rval = 0; + errno = 0; if (if_err(fd < 0, EBADF)) - return set_errno(saved_errno, EIO); + return with_fallback_errno(EIO); - errno = 0; while (fs_retry(saved_errno, rval = fsync(fd))); + reset_caller_errno(rval); return rval; } @@ -824,7 +800,7 @@ void close_on_eintr(int *fd) { int saved_errno = errno; - int rval; + int rval = 0; if (fd == NULL) err_exit(EINVAL, "close_on_eintr: null pointer"); @@ -839,6 +815,8 @@ close_on_eintr(int *fd) err_exit(errno, "close_on_eintr: could not close"); *fd = -1; + + reset_caller_errno(rval); } /* unified eintr looping. diff --git a/util/libreboot-utils/lib/io.c b/util/libreboot-utils/lib/io.c index f74ce261..9bbf1f30 100644 --- a/util/libreboot-utils/lib/io.c +++ b/util/libreboot-utils/lib/io.c @@ -470,9 +470,9 @@ ret_gbe_mv: if (rval >= 0) goto out; - return set_errno(saved_errno, EIO); + return with_fallback_errno(EIO); out: - errno = saved_errno; + reset_caller_errno(rval); return rval; } @@ -572,6 +572,5 @@ rw_gbe_file_exact(int fd, unsigned char *mem, size_t nrw, return rw_over_nrw(r, nrw); err_rw_gbe_file_exact: - errno = EIO; - return -1; + return with_fallback_errno(EIO); } diff --git a/util/libreboot-utils/lib/mkhtemp.c b/util/libreboot-utils/lib/mkhtemp.c index 7589a410..c1574634 100644 --- a/util/libreboot-utils/lib/mkhtemp.c +++ b/util/libreboot-utils/lib/mkhtemp.c @@ -67,20 +67,15 @@ new_tmp_common(int *fd, char **path, int type, int dirfd = -1; const char *fname = NULL; - struct stat st_dir_initial; + struct stat st_dir_first; char *fail_dir = NULL; - if (path == NULL || fd == NULL) { - errno = EFAULT; - goto err; - } + errno = 0; - /* don't mess with someone elses file */ - if (*fd >= 0) { - errno = EEXIST; + if (if_err(path == NULL || fd == NULL, EFAULT) || + if_err(*fd >= 0, EEXIST)) /* don't touch someone else's file */ goto err; - } /* regarding **path: * the pointer (to the pointer) @@ -111,12 +106,7 @@ new_tmp_common(int *fd, char **path, int type, tmpdir = env_tmpdir(0, &fail_dir, tmpdir); #endif } - if (tmpdir == NULL) - goto err; - - if (*tmpdir == '\0') - goto err; - if (*tmpdir != '/') + if (if_err(tmpdir ==NULL || *tmpdir == '\0' || *tmpdir != '/', EINVAL)) goto err; if (template != NULL) @@ -138,11 +128,11 @@ new_tmp_common(int *fd, char **path, int type, if (dirfd < 0) goto err; - if (fstat(dirfd, &st_dir_initial) < 0) + if (fstat(dirfd, &st_dir_first) < 0) goto err; *fd = mkhtemp(fd, &st, dest, dirfd, - fname, &st_dir_initial, type); + fname, &st_dir_first, type); if (*fd < 0) goto err; @@ -151,15 +141,10 @@ new_tmp_common(int *fd, char **path, int type, errno = saved_errno; *path = dest; + reset_caller_errno(0); return 0; err: - - if (errno != saved_errno) - saved_errno = errno; - else - saved_errno = errno = EIO; - free_and_set_null(&dest); close_on_eintr(&dirfd); @@ -173,7 +158,7 @@ err: *path = fail_dir; errno = saved_errno; - return -1; + return with_fallback_errno(EIO); } @@ -184,13 +169,17 @@ char * env_tmpdir(int bypass_all_sticky_checks, char **tmpdir, char *override_tmpdir) { - char *t; + char *t = NULL; int allow_noworld_unsticky; int saved_errno = errno; static const char tmp[] = "/tmp"; static const char vartmp[] = "/var/tmp"; + char *rval = NULL; + + errno = 0; + /* tmpdir is a user override, if set */ if (override_tmpdir == NULL) t = getenv("TMPDIR"); @@ -200,48 +189,38 @@ env_tmpdir(int bypass_all_sticky_checks, char **tmpdir, if (t != NULL && *t != '\0') { if (tmpdir_policy(t, - &allow_noworld_unsticky) < 0) { - if (tmpdir != NULL) - *tmpdir = t; - return NULL; /* errno already set */ - } + &allow_noworld_unsticky) < 0) + goto err; if (!world_writeable_and_sticky(t, allow_noworld_unsticky, - bypass_all_sticky_checks)) { - if (tmpdir != NULL) - *tmpdir = t; - return NULL; - } + bypass_all_sticky_checks)) + goto err; - errno = saved_errno; - return t; + rval = t; + goto out; } allow_noworld_unsticky = 0; - if (world_writeable_and_sticky(tmp, - allow_noworld_unsticky, - bypass_all_sticky_checks)) { - - if (tmpdir != NULL) - *tmpdir = (char *)tmp; - - errno = saved_errno; - return (char *)tmp; - } - - if (world_writeable_and_sticky(vartmp, - allow_noworld_unsticky, - bypass_all_sticky_checks)) { - - if (tmpdir != NULL) - *tmpdir = (char *)vartmp; - - errno = saved_errno; - return (char *)vartmp; - } + if (world_writeable_and_sticky(tmp, allow_noworld_unsticky, + bypass_all_sticky_checks)) + rval = (char *)tmp; + else if (world_writeable_and_sticky(vartmp, + allow_noworld_unsticky, bypass_all_sticky_checks)) + rval = (char *)vartmp; + else + goto err; +out: + reset_caller_errno(0); + if (tmpdir != NULL) + *tmpdir = rval; + return rval; +err: + if (tmpdir != NULL && t != NULL) + *tmpdir = t; + (void) with_fallback_errno(EPERM); return NULL; } @@ -251,13 +230,11 @@ tmpdir_policy(const char *path, { int saved_errno = errno; int r; + errno = 0; - if (path == NULL || - allow_noworld_unsticky == NULL) { - - errno = EFAULT; - return -1; - } + if (if_err(path == NULL || + allow_noworld_unsticky == NULL, EFAULT)) + goto err_tmpdir_policy; *allow_noworld_unsticky = 1; @@ -273,11 +250,11 @@ tmpdir_policy(const char *path, if (r > 0) *allow_noworld_unsticky = 0; - errno = saved_errno; + reset_caller_errno(0); return 0; err_tmpdir_policy: - return set_errno(saved_errno, EIO); + return with_fallback_errno(EPERM); } int @@ -290,63 +267,48 @@ same_dir(const char *a, const char *b) struct stat st_b; int saved_errno = errno; - int rval_scmp; + int rval = 0; /* LOGICAL error, 0, if 0 is returned */ + errno = 0; /* optimisation: if both dirs are the same, we don't need to check anything. sehr schnell! */ /* bonus: scmp checks null for us */ - if (!scmp(a, b, PATH_MAX, &rval_scmp)) + if (!scmp(a, b, PATH_MAX, &rval)) goto success_same_dir; + else + rval = 0; /* reset */ - fd_a = fs_open(a, O_RDONLY | O_DIRECTORY | O_NOFOLLOW); - if (fd_a < 0) - goto err_same_dir; - - fd_b = fs_open(b, O_RDONLY | O_DIRECTORY | O_NOFOLLOW); - if (fd_b < 0) - goto err_same_dir; - - if (fstat(fd_a, &st_a) < 0) - goto err_same_dir; - - if (fstat(fd_b, &st_b) < 0) + if ((fd_a = fs_open(a, O_RDONLY | O_DIRECTORY | O_NOFOLLOW)) < 0 || + (fd_b = fs_open(b, O_RDONLY | O_DIRECTORY | O_NOFOLLOW)) < 0 || + fstat(fd_a, &st_a) < 0 || + fstat(fd_b, &st_b) < 0) goto err_same_dir; if (st_a.st_dev == st_b.st_dev && st_a.st_ino == st_b.st_ino) { - - close_on_eintr(&fd_a); - close_on_eintr(&fd_b); - success_same_dir: - - /* SUCCESS - */ - - errno = saved_errno; - return 1; + rval = 1; /* SUCCESS */ } close_on_eintr(&fd_a); close_on_eintr(&fd_b); - /* FAILURE (logical) + /* we reset caller errno regardless + * of success, so long as it's not + * a syscall error */ - - errno = saved_errno; - return 0; + reset_caller_errno(0); + return rval; err_same_dir: - - /* FAILURE (probably syscall) + /* FAILURE (probably syscall) - returns -1 */ - close_on_eintr(&fd_a); close_on_eintr(&fd_b); - return set_errno(saved_errno, EIO); + return with_fallback_errno(EIO); /* -1 */ } /* bypass_all_sticky_checks: if set, @@ -367,81 +329,45 @@ world_writeable_and_sticky( int dirfd = -1; int saved_errno = errno; + errno = 0; - if (s == NULL || *s == '\0') { - errno = EINVAL; - goto sticky_hell; - } - - /* mitigate symlink attacks* - */ - dirfd = fs_open(s, O_RDONLY | O_DIRECTORY); - if (dirfd < 0) - goto sticky_hell; - - if (fstat(dirfd, &st) < 0) - goto sticky_hell; - - if (!S_ISDIR(st.st_mode)) { - errno = ENOTDIR; - goto sticky_hell; - } - - /* all of these checks are probably - * redundant (execution rights) - if (!(st.st_mode & S_IXUSR) || - !(st.st_mode & S_IXGRP) || - !(st.st_mode & S_IXOTH)) { - */ - /* just require it for *you*, for now */ - if (!(st.st_mode & S_IXUSR)) { - errno = EACCES; + if (if_err(s == NULL || *s == '\0', EINVAL) || + (dirfd = fs_open(s, O_RDONLY | O_DIRECTORY)) < 0 || + fstat(dirfd, &st) < 0 || + if_err(!S_ISDIR(st.st_mode), ENOTDIR)) goto sticky_hell; - } /* *normal-**ish mode (libc): */ - if (bypass_all_sticky_checks) goto sticky_heaven; /* normal == no security */ /* extremely not-libc mode: + * only require stickiness on world-writeable dirs: */ - if (st.st_mode & S_IWOTH) { /* world writeable */ - /* if world-writeable, only - * allow sticky files - */ - if (st.st_mode & S_ISVTX) - goto sticky_heaven; /* sticky */ + if (if_err(!(st.st_mode & S_ISVTX), EPERM)) + goto sticky_hell; /* not sticky */ - errno = EPERM; - goto sticky_hell; /* not sticky */ + goto sticky_heaven; /* sticky! */ + } else if (allow_noworld_unsticky) { + goto sticky_heaven; /* sticky visa */ + } else { + goto sticky_hell; /* visa denied */ } - /* for good measure */ +sticky_heaven: if (faccessat(dirfd, ".", X_OK, AT_EACCESS) < 0) - goto sticky_hell; + goto sticky_hell; /* down you go! */ - /* non-world-writeable, so - * stickiness is do-not-care - */ - if (allow_noworld_unsticky) - goto sticky_heaven; /* sticky! */ - - goto sticky_hell; /* heaven visa denied */ - -sticky_heaven: close_on_eintr(&dirfd); - errno = saved_errno; - + reset_caller_errno(0); return 1; sticky_hell: close_on_eintr(&dirfd); - - (void) set_errno(saved_errno, EPERM); + (void) with_fallback_errno(EPERM); return 0; } @@ -503,7 +429,7 @@ mkhtemp(int *fd, char *template, int dirfd, const char *fname, - struct stat *st_dir_initial, + struct stat *st_dir_first, int type) { size_t template_len = 0; @@ -521,11 +447,13 @@ mkhtemp(int *fd, int r; char *end; + errno = 0; + if (if_err(fd == NULL || template == NULL || fname == NULL || - st_dir_initial == NULL, EFAULT) || + st_dir_first == NULL, EFAULT) || if_err(*fd >= 0, EEXIST) || if_err(dirfd < 0, EBADF)) - return -1; + goto err; /* count X */ for (end = template + slen(template, PATH_MAX, &template_len); @@ -533,15 +461,15 @@ mkhtemp(int *fd, fname_len = slen(fname, PATH_MAX, &fname_len); if (if_err(strrchr(fname, '/') != NULL, EINVAL)) - return -1; + goto err; if (if_err(xc < 3 || xc > template_len, EINVAL) || if_err(fname_len > template_len, EOVERFLOW)) - return -1; + goto err; if (if_err(vcmp(fname, template + template_len - fname_len, fname_len) != 0, EINVAL)) - return -1; + goto err; /* fname_copy = templatestr region only; p points to trailing XXXXXX */ memcpy(smalloc(&fname_copy, fname_len + 1), @@ -552,7 +480,7 @@ mkhtemp(int *fd, for (retries = 0; retries < MKHTEMP_RETRY_MAX; retries++) { r = mkhtemp_try_create(dirfd, - st_dir_initial, fname_copy, + st_dir_first, fname_copy, p, xc, fd, st, type); if (r == 0) @@ -569,19 +497,22 @@ mkhtemp(int *fd, } errno = EEXIST; - err: close_on_eintr(fd); + free_and_set_null(&fname_copy); + + return with_fallback_errno(EIO); success: free_and_set_null(&fname_copy); - return (*fd >= 0) ? *fd : -1; + reset_caller_errno(0); + return *fd; } int mkhtemp_try_create(int dirfd, - struct stat *st_dir_initial, + struct stat *st_dir_first, char *fname_copy, char *p, size_t xc, @@ -597,8 +528,10 @@ mkhtemp_try_create(int dirfd, int file_created = 0; int dir_created = 0; + errno = 0; + if (if_err(fd == NULL || st == NULL || p ==NULL || fname_copy ==NULL || - st_dir_initial == NULL, EFAULT) || + st_dir_first == NULL, EFAULT) || if_err(*fd >= 0, EEXIST)) goto err; @@ -608,14 +541,14 @@ mkhtemp_try_create(int dirfd, memcpy(p, rstr = rchars(xc), xc); free_and_set_null(&rstr); - if (if_err_sys(fd_verify_dir_identity(dirfd, st_dir_initial) < 0)) + if (if_err_sys(fd_verify_dir_identity(dirfd, st_dir_first) < 0)) goto err; if (type == MKHTEMP_FILE) { #ifdef __linux__ /* try O_TMPFILE fast path */ if (mkhtemp_tmpfile_linux(dirfd, - st_dir_initial, fname_copy, + st_dir_first, fname_copy, p, xc, fd, st) == 0) { errno = saved_errno; @@ -645,7 +578,7 @@ mkhtemp_try_create(int dirfd, dir_created = 1; /* do it again (mitigate directory race) */ - if (fd_verify_dir_identity(dirfd, st_dir_initial) < 0) + if (fd_verify_dir_identity(dirfd, st_dir_first) < 0) goto err; if ((*fd = openat_on_eintr(dirfd, fname_copy, @@ -657,7 +590,7 @@ mkhtemp_try_create(int dirfd, goto err; /* NOTE: pointless to check nlink here (only just opened) */ - if (fd_verify_dir_identity(dirfd, st_dir_initial) < 0) + if (fd_verify_dir_identity(dirfd, st_dir_first) < 0) goto err; } @@ -680,7 +613,7 @@ mkhtemp_try_create(int dirfd, if (type == MKHTEMP_FILE) { - if (fd_verify_dir_identity(dirfd, st_dir_initial) < 0) + if (fd_verify_dir_identity(dirfd, st_dir_first) < 0) goto err; if (secure_file(fd, st, &st_open, @@ -689,7 +622,7 @@ mkhtemp_try_create(int dirfd, } else { /* dir: MKHTEMP_DIR */ - if (fd_verify_identity(*fd, &st_open, st_dir_initial) < 0) + if (fd_verify_identity(*fd, &st_open, st_dir_first) < 0) goto err; if (if_err(!S_ISDIR(st_open.st_mode), ENOTDIR) || @@ -698,10 +631,11 @@ mkhtemp_try_create(int dirfd, goto err; } - errno = saved_errno; rval = 1; - goto out; +out: + reset_caller_errno(0); + return rval; err: close_on_eintr(fd); @@ -710,9 +644,7 @@ err: if (dir_created) (void) unlinkat(dirfd, fname_copy, AT_REMOVEDIR); - rval = -1; -out: - return rval; + return with_fallback_errno(EPERM); } /* linux has its own special hardening @@ -725,7 +657,7 @@ out: #ifdef __linux__ int mkhtemp_tmpfile_linux(int dirfd, - struct stat *st_dir_initial, + struct stat *st_dir_first, char *fname_copy, char *p, size_t xc, @@ -737,22 +669,21 @@ mkhtemp_tmpfile_linux(int dirfd, size_t retries; int linked = 0; char *rstr = NULL; + errno = 0; - if (fd == NULL || st == NULL || + if (if_err(fd == NULL || st == NULL || fname_copy == NULL || p == NULL || - st_dir_initial == NULL) { - errno = EFAULT; - return -1; - } + st_dir_first == NULL, EFAULT)) + goto err; /* create unnamed tmpfile */ tmpfd = openat(dirfd, ".", O_TMPFILE | O_RDWR | O_CLOEXEC, 0600); if (tmpfd < 0) - return -1; + goto err; - if (fd_verify_dir_identity(dirfd, st_dir_initial) < 0) + if (fd_verify_dir_identity(dirfd, st_dir_first) < 0) goto err; for (retries = 0; retries < MKHTEMP_RETRY_MAX; retries++) { @@ -761,30 +692,19 @@ mkhtemp_tmpfile_linux(int dirfd, free_and_set_null(&rstr); if (fd_verify_dir_identity(dirfd, - st_dir_initial) < 0) + st_dir_first) < 0) goto err; - if (linkat(tmpfd, "", - dirfd, fname_copy, - AT_EMPTY_PATH) == 0) { + if (linkat(tmpfd, "", dirfd, fname_copy, AT_EMPTY_PATH) == 0) { linked = 1; /* file created */ - if (fd_verify_dir_identity(dirfd, st_dir_initial) < 0) - goto err; - - /* success */ - *fd = tmpfd; - - if (fstat(*fd, st) < 0) + if (fd_verify_dir_identity(dirfd, st_dir_first) < 0 || + fstat(*fd = tmpfd, st) < 0 || + secure_file(fd, st, st, O_APPEND, 1, 1, 0600) < 0) goto err; - if (secure_file(fd, st, st, - O_APPEND, 1, 1, 0600) < 0) - goto err; - - errno = saved_errno; - return 0; + goto out; } if (errno != EEXIST) @@ -794,13 +714,15 @@ mkhtemp_tmpfile_linux(int dirfd, } errno = EEXIST; - err: if (linked) (void) unlinkat(dirfd, fname_copy, 0); close_on_eintr(&tmpfd); - return -1; + return with_fallback_errno(EIO); +out: + reset_caller_errno(0); + return 0; } #endif @@ -821,6 +743,7 @@ int secure_file(int *fd, int flags; struct stat st_now; int saved_errno = errno; + errno = 0; if (if_err(fd == NULL || st == NULL, EFAULT) || if_err(*fd < 0, EBADF) || @@ -862,23 +785,28 @@ int secure_file(int *fd, if (fchmod(*fd, mode) == -1) goto err_demons; - errno = saved_errno; + reset_caller_errno(0); return 0; err_demons: - return set_errno(saved_errno, EIO); + return with_fallback_errno(EIO); } int fd_verify_regular(int fd, const struct stat *expected, struct stat *out) -{if ( - if_err_sys(fd_verify_identity(fd, expected, out) < 0) || - if_err(!S_ISREG(out->st_mode), EBADF) - ) return -1; - else +{ + int saved_errno = errno; + errno = 0; + + if (if_err_sys(fd_verify_identity(fd, expected, out) < 0) || + if_err(!S_ISREG(out->st_mode), EBADF)) { + return with_fallback_errno(EIO); + } else { + reset_caller_errno(0); return 0; /* regular file */ + } } int @@ -888,17 +816,18 @@ fd_verify_identity(int fd, { struct stat st_now; int saved_errno = errno; + errno = 0; if( if_err(fd < 0 || expected == NULL, EFAULT) || if_err_sys(fstat(fd, &st_now)) || if_err(st_now.st_dev != expected->st_dev || st_now.st_ino != expected->st_ino, ESTALE)) - return -1; + return with_fallback_errno(EIO); if (out != NULL) *out = st_now; - errno = saved_errno; + reset_caller_errno(0); return 0; } @@ -908,45 +837,35 @@ fd_verify_dir_identity(int fd, { struct stat st_now; int saved_errno = errno; + errno = 0; if (if_err(fd < 0 || expected == NULL, EFAULT) || - if_err_sys(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 (!S_ISDIR(st_now.st_mode)) { - errno = ENOTDIR; - return -1; - } + if_err_sys(fstat(fd, &st_now) < 0) || + if_err(st_now.st_dev != expected->st_dev, ESTALE) || + if_err(st_now.st_ino != expected->st_ino, ESTALE) || + if_err(!S_ISDIR(st_now.st_mode), ENOTDIR)) + goto err; - errno = saved_errno; + reset_caller_errno(0); return 0; +err: + return with_fallback_errno(EIO); } int is_owner(struct stat *st) { - if (st == NULL) { - - errno = EFAULT; - return -1; - } + int saved_errno = errno; + errno = 0; -#if ALLOW_ROOT_OVERRIDE - if (st->st_uid != geteuid() && /* someone else's file */ - geteuid() != 0) { /* override for root */ -#else - if (st->st_uid != geteuid()) { /* someone else's file */ -#endif /* and no root override */ - errno = EPERM; - return -1; - } + if (if_err(st == NULL, EFAULT) || + if_err(st->st_uid != geteuid() /* someone else's file */ +#if defined(ALLOW_ROOT_OVERRIDE) && ((ALLOW_ROOT_OVERRIDE) > 0) + && geteuid() != 0 /* override for root */ +#endif + , EPERM)) return with_fallback_errno(EIO); + reset_caller_errno(0); return 0; } @@ -955,6 +874,7 @@ lock_file(int fd, int flags) { struct flock fl; int saved_errno = errno; + errno = 0; if (if_err(fd < 0, EBADF) || if_err(flags < 0, EINVAL)) @@ -972,9 +892,9 @@ lock_file(int fd, int flags) if (fcntl(fd, F_SETLK, &fl) == -1) goto err_lock_file; - saved_errno = errno; + reset_caller_errno(0); return 0; err_lock_file: - return set_errno(saved_errno, EIO); + return with_fallback_errno(EIO); } diff --git a/util/libreboot-utils/lib/num.c b/util/libreboot-utils/lib/num.c index e13a8853..ad349173 100644 --- a/util/libreboot-utils/lib/num.c +++ b/util/libreboot-utils/lib/num.c @@ -28,8 +28,6 @@ unsigned short hextonum(char ch_s) { - int saved_errno = errno; - unsigned char ch; size_t rval; @@ -43,8 +41,8 @@ hextonum(char ch_s) if ((unsigned int)(ch - 'a') <= 5) return ch - 'a' + 10; - if (ch == '?' || ch == 'x') - return rsize(16); /* <-- with rejection sampling! */ + if (ch == '?' || ch == 'x') /* random */ + return (short)rsize(16); /* <-- with rejection sampling! */ return 16; } diff --git a/util/libreboot-utils/lib/rand.c b/util/libreboot-utils/lib/rand.c index 20dc33cd..adfad3d7 100644 --- a/util/libreboot-utils/lib/rand.c +++ b/util/libreboot-utils/lib/rand.c @@ -127,6 +127,7 @@ void rset(void *buf, size_t n) { int saved_errno = errno; + errno = 0; if (if_err(buf == NULL, EFAULT)) goto err; @@ -140,7 +141,6 @@ rset(void *buf, size_t n) ((USE_URANDOM) > 0)) arc4random_buf(buf, n); - goto out; #else size_t off = 0; @@ -166,7 +166,7 @@ retry_rand: #endif if (rc < 0) - goto err; + goto err; /* syscall fehler */ if (rc == 0) goto err; /* prevent infinite loop on fatal err */ @@ -180,16 +180,15 @@ retry_rand: #endif #endif -out: - errno = saved_errno; + reset_caller_errno(0); return; err: #if defined(USE_URANDOM) && \ ((USE_URANDOM) > 0) close_on_eintr(&fd); #endif - err_exit(ECANCELED, - "Randomisation failure, possibly unsupported in your kernel"); + (void) with_fallback_errno(ECANCELED); + err_exit(errno, "Randomisierungsfehler"); exit(EXIT_FAILURE); } #endif diff --git a/util/libreboot-utils/lib/string.c b/util/libreboot-utils/lib/string.c index ad11d29d..ce54a524 100644 --- a/util/libreboot-utils/lib/string.c +++ b/util/libreboot-utils/lib/string.c @@ -50,6 +50,7 @@ pagesize(void) { static long rval = 0; static int set = 0; + int saved_errno = 0; if (!set) { if ((rval = sysconf(_SC_PAGESIZE)) < 0) @@ -57,6 +58,7 @@ pagesize(void) set = 1; } + reset_caller_errno(0); return rval; } @@ -92,7 +94,9 @@ smalloc(char **buf, size_t size) void * vmalloc(void **buf, size_t size) { + int saved_errno = errno; void *rval = NULL; + errno = 0; if (size >= SIZE_MAX - 1) err_exit(EOVERFLOW, "integer overflow in vmalloc"); @@ -116,6 +120,7 @@ vmalloc(void **buf, size_t size) if ((rval = malloc(size)) == NULL) err_exit(errno, "malloc fail in vmalloc"); + reset_caller_errno(0); return *buf = rval; } @@ -131,6 +136,7 @@ scmp(const char *a, size_t wa; size_t wb; int saved_errno = errno; + errno = 0; if (if_err(a == NULL || b == NULL || rval == NULL, EFAULT)) goto err; @@ -171,14 +177,14 @@ scmp(const char *a, goto out; err: - (void) set_errno(saved_errno, EFAULT); + (void) with_fallback_errno(EFAULT); if (rval != NULL) *rval = -1; err_exit(errno, "scmp"); return -1; out: - errno = saved_errno; + reset_caller_errno(0); return *rval; } @@ -215,13 +221,14 @@ slen(const char *s, size_t i = 0; size_t w; size_t j; + errno = 0; if (if_err(s == NULL || rval == NULL, EFAULT)) goto err; for ( ; ((uintptr_t)(s + i) % sizeof(size_t)) != 0; i++) { - if (i >= maxlen) + if (if_err(i >= maxlen, EOVERFLOW)) goto err; if (s[i] == '\0') { *rval = i; @@ -252,14 +259,14 @@ slen(const char *s, } err: - (void) set_errno(saved_errno, EFAULT); + (void) with_fallback_errno(EFAULT); if (rval != NULL) *rval = 0; err_exit(errno, "slen"); /* abort */ return 0; /* gcc15 is happy */ out: - errno = saved_errno; + reset_caller_errno(0); return *rval; } @@ -273,6 +280,7 @@ sdup(const char *s, size_t i = 0; char *out = NULL; int saved_errno = errno; + errno = 0; if (if_err(dest == NULL || *dest != NULL || s == NULL, EFAULT)) goto err; @@ -326,12 +334,12 @@ err: if (dest != NULL) *dest = NULL; - (void) set_errno(saved_errno, EFAULT); + (void) with_fallback_errno(EFAULT); err_exit(errno, "sdup"); return NULL; out: - errno = saved_errno; + reset_caller_errno(0); return *dest; } @@ -345,6 +353,7 @@ scatn(ssize_t sc, const char **sv, char *rcur = NULL; char *rtmp = NULL; size_t i; + errno = 0; if (if_err(sc < 2, EINVAL) || if_err(sv == NULL, EFAULT) || @@ -368,7 +377,7 @@ scatn(ssize_t sc, const char **sv, rtmp = NULL; } - errno = saved_errno; + reset_caller_errno(0); *rval = final; return *rval; err: @@ -376,7 +385,7 @@ err: free_and_set_null(&rtmp); free_and_set_null(&final); - (void) set_errno(saved_errno, EFAULT); + (void) with_fallback_errno(EFAULT); err_exit(errno, "scatn"); return NULL; @@ -391,6 +400,7 @@ scat(const char *s1, const char *s2, size_t size2; char *rval = NULL; int saved_errno = errno; + errno = 0; if (if_err(dest == NULL || *dest != NULL, EFAULT)) goto err; @@ -408,11 +418,11 @@ scat(const char *s1, const char *s2, memcpy(rval + size1, s2, size2); *(rval + size1 + size2) = '\0'; + reset_caller_errno(0); *dest = rval; - errno = saved_errno; return *dest; err: - (void) set_errno(saved_errno, EINVAL); + (void) with_fallback_errno(EINVAL); if (dest != NULL) *dest = NULL; err_exit(errno, "scat"); @@ -431,6 +441,7 @@ dcat(const char *s, size_t n, char *rval1 = NULL; char *rval2 = NULL; int saved_errno = errno; + errno = 0; if (if_err(dest1 == NULL || dest2 == NULL, EFAULT)) goto err; @@ -450,7 +461,7 @@ dcat(const char *s, size_t n, *dest1 = rval1; *dest2 = rval2; - errno = saved_errno; + reset_caller_errno(0); return; err: @@ -459,7 +470,7 @@ err: free_and_set_null(&rval1); free_and_set_null(&rval2); - (void) set_errno(saved_errno, EINVAL); + (void) with_fallback_errno(EINVAL); err_exit(errno, "dcat"); } @@ -477,6 +488,7 @@ vcmp(const void *s1, const void *s2, size_t n) const unsigned char *x; const unsigned char *y; + errno = 0; if (if_err(s1 == NULL || s2 == NULL, EFAULT)) err_exit(EFAULT, "vcmp: null input"); @@ -497,7 +509,7 @@ vcmp(const void *s1, const void *s2, size_t n) if (x[i] != y[i]) return (int)x[i] - (int)y[i]; - errno = saved_errno; + reset_caller_errno(0); return 0; } @@ -507,9 +519,9 @@ vcmp(const void *s1, const void *s2, size_t n) * under error condition. */ int -set_errno(int saved_errno, int fallback) +with_fallback_errno(int fallback) { - if (errno == saved_errno) + if (!errno) errno = fallback; return -1; } @@ -525,7 +537,8 @@ err_exit(int nvm_errval, const char *msg, ...) func_t err_cleanup = errhook(NULL); err_cleanup(); - errno = saved_errno; + reset_caller_errno(0); + saved_errno = errno; if (!errno) saved_errno = errno = ECANCELED; @@ -536,6 +549,7 @@ err_exit(int nvm_errval, const char *msg, ...) vfprintf(stderr, msg, args); va_end(args); + errno = saved_errno; fprintf(stderr, ": %s\n", strerror(errno)); exit(EXIT_FAILURE); @@ -615,11 +629,12 @@ xpledgex(const char *promises, const char *execpromises) { int saved_errno = errno; (void) promises, (void) execpromises, (void) saved_errno; + errno = 0; #ifdef __OpenBSD__ if (pledge(promises, execpromises) == -1) err_exit(errno, "pledge"); #endif - errno = saved_errno; + reset_caller_errno(0); return 0; } int @@ -627,10 +642,11 @@ xunveilx(const char *path, const char *permissions) { int saved_errno = errno; (void) path, (void) permissions, (void) saved_errno; + errno = 0; #ifdef __OpenBSD__ if (pledge(promises, execpromises) == -1) err_exit(errno, "pledge"); #endif - errno = saved_errno; + reset_caller_errno(0); return 0; } diff --git a/util/libreboot-utils/lottery.c b/util/libreboot-utils/lottery.c index 9906ed11..1648cbc7 100644 --- a/util/libreboot-utils/lottery.c +++ b/util/libreboot-utils/lottery.c @@ -37,7 +37,6 @@ main(int argc, char **argv) fprintf(stderr, "\n%s\n", same ? "You win!" : "You lose!"); - printf("%lu\n", PATH_MAX); return same ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/util/libreboot-utils/mkhtemp.c b/util/libreboot-utils/mkhtemp.c index f7480ed6..65e637e9 100644 --- a/util/libreboot-utils/mkhtemp.c +++ b/util/libreboot-utils/mkhtemp.c @@ -1,11 +1,13 @@ -/* SPDX-License-Identifier: MIT - * Copyright (c) 2026 Leah Rowe <leah@libreboot.org> - * +/* SPDX-License-Identifier: MIT ( >:3 ) + * Copyright (c) 2026 Leah Rowe <leah@libreboot.org> /| |\ + * / \ * Hardened mktemp (mkhtemp!) * * WORK IN PROGRESS (proof of concept), or, v0.0000001 * DO NOT PUT THIS IN YOUR LINUX DISTRO YET. * + * In other words: for reference only -- PATCHES WELCOME! + * * I will remove this notice when the code is mature, and * probably contact several of your projects myself. * @@ -139,8 +141,4 @@ static void exit_cleanup(void) { return; -}/* - - ( >:3 ) - /| |\ - / \ */ +} diff --git a/util/libreboot-utils/nvmutil.c b/util/libreboot-utils/nvmutil.c index ec41371f..3102bd50 100644 --- a/util/libreboot-utils/nvmutil.c +++ b/util/libreboot-utils/nvmutil.c @@ -1,6 +1,6 @@ -/* SPDX-License-Identifier: MIT - * Copyright (c) 2022-2026 Leah Rowe <leah@libreboot.org> - * +/* SPDX-License-Identifier: MIT ( >:3 ) + * Copyright (c) 2022-2026 Leah Rowe <leah@libreboot.org> /| |\ + * / \ * This tool lets you modify Intel GbE NVM (Gigabit Ethernet * Non-Volatile Memory) images, e.g. change the MAC address. * These images configure your Intel Gigabit Ethernet adapter. |
