diff options
| -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. |
