diff options
| author | Leah Rowe <leah@libreboot.org> | 2026-03-20 04:02:51 +0000 |
|---|---|---|
| committer | Leah Rowe <leah@libreboot.org> | 2026-03-22 13:50:44 +0000 |
| commit | 6838db4647b600bf5b356429f54850bf801e7ba4 (patch) | |
| tree | cc98541897703d2949af27dc050cad8cba5061a0 /util/nvmutil/include/common.h | |
| parent | f50ffd6bb13c04cb185fb6311f8875582bf18388 (diff) | |
WIP: hardened mktemp
i'm pretty much nearly there. still no dir support,
only files.
i won't keep amending now - will do more, then
squash later.
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'util/nvmutil/include/common.h')
| -rw-r--r-- | util/nvmutil/include/common.h | 176 |
1 files changed, 118 insertions, 58 deletions
diff --git a/util/nvmutil/include/common.h b/util/nvmutil/include/common.h index 46fbcb38..6cdeba18 100644 --- a/util/nvmutil/include/common.h +++ b/util/nvmutil/include/common.h @@ -35,11 +35,20 @@ int fchmod(int fd, mode_t mode); -/* analog of SSIZE_MAX +/* if 1: on operations that + * check ownership, always + * permit root to access even + * if not the file/dir owner */ +#ifndef ALLOW_ROOT_OVERRIDE +#define ALLOW_ROOT_OVERRIDE 0 +#endif -#ifndef X_LONG_MAX -#define X_LONG_MAX ((long)(~((long)1 << (sizeof(long)*CHAR_BIT-1)))) +/* + */ + +#ifndef SSIZE_MAX +#define SSIZE_MAX ((ssize_t)(~((ssize_t)1 << (sizeof(ssize_t)*CHAR_BIT-1)))) #endif @@ -60,6 +69,13 @@ int fchmod(int fd, mode_t mode); #define OFF_RESET 1 #endif +/* by default: allow use + of openat in hardened mkstemp + */ +#ifndef DISABLE_OPENAT +#define DISABLE_OPENAT 0 /* change to 1 if you don't have openat (old unix) */ +#endif + #ifndef S_ISVTX #define S_ISVTX 01000 #endif @@ -72,8 +88,8 @@ int fchmod(int fd, mode_t mode); #define MAX_ZERO_RW_RETRY 5 #endif -#ifndef HAVE_REAL_PREAD_PWRITE -#define HAVE_REAL_PREAD_PWRITE 0 +#ifndef REAL_POS_IO +#define REAL_POS_IO 0 #endif #ifndef LOOP_EAGAIN @@ -95,6 +111,10 @@ int fchmod(int fd, mode_t mode); #define EXIT_SUCCESS 0 #endif +#ifndef O_NOCTTY +#define O_NOCTTY 0 +#endif + #ifndef O_ACCMODE #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR) #endif @@ -208,14 +228,14 @@ int fchmod(int fd, mode_t mode); */ struct commands { - unsigned long chk; + size_t chk; char *str; void (*run)(void); int argc; unsigned char arg_part; unsigned char chksum_read; unsigned char chksum_write; - unsigned long rw_size; /* within the 4KB GbE part */ + size_t rw_size; /* within the 4KB GbE part */ int flags; /* e.g. O_RDWR or O_RDONLY */ }; @@ -254,7 +274,7 @@ struct xfile { off_t gbe_file_size; off_t gbe_tmp_size; - unsigned long part; + size_t part; unsigned char part_modified[2]; unsigned char part_valid[2]; @@ -278,7 +298,7 @@ struct xstate { char *argv0; - unsigned long i; /* index to cmd[] for current command */ + size_t i; /* index to cmd[] for current command */ int no_cmd; /* Cat commands set this. @@ -286,28 +306,33 @@ struct xstate { int cat; }; +struct path_split { + int dirfd; + char *buf; + const char *base; +}; - -struct xstate *xstatus(int argc, char *argv[]); +struct xstate *xstart(int argc, char *argv[]); +struct xstate *xstatus(void); /* Sanitize command tables. */ void sanitize_command_list(void); -void sanitize_command_index(unsigned long c); +void sanitize_command_index(size_t c); /* Argument handling (user input) */ void set_cmd(int argc, char *argv[]); void set_cmd_args(int argc, char *argv[]); -unsigned long conv_argv_part_num(const char *part_str); -int xstrxcmp(const char *a, const char *b, unsigned long maxlen); +size_t conv_argv_part_num(const char *part_str); /* Prep files for reading */ void open_gbe_file(void); +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); void xopen(int *fd, const char *path, int flags, struct stat *st); @@ -318,25 +343,37 @@ void xopen(int *fd, const char *path, int flags, struct stat *st); void copy_gbe(void); void read_file(void); void read_checksums(void); -int good_checksum(unsigned long partnum); +int good_checksum(size_t partnum); /* validate commands */ -void check_command_num(unsigned long c); -unsigned char valid_command(unsigned long c); +void check_command_num(size_t c); +unsigned char valid_command(size_t c); /* Helper functions for command: setmac */ void cmd_helper_setmac(void); void parse_mac_string(void); -unsigned long xstrxlen(const char *scmp, unsigned long maxlen); -void set_mac_byte(unsigned long mac_byte_pos); -void set_mac_nib(unsigned long mac_str_pos, - unsigned long mac_byte_pos, unsigned long mac_nib_pos); +void set_mac_byte(size_t mac_byte_pos); +void set_mac_nib(size_t mac_str_pos, + size_t mac_byte_pos, size_t mac_nib_pos); +void write_mac_part(size_t partnum); + +/* string functions + */ + +int slen(const char *scmp, size_t maxlen, + size_t *rval); +int scmp(const char *a, const char *b, + size_t maxlen, int *rval); + +/* numerical functions + */ + unsigned short hextonum(char ch_s); -unsigned long rlong(void); +size_t rlong(void); #if !(defined(FALLBACK_RAND_1989) && \ ((FALLBACK_RAND_1989) > 0)) #if defined(__linux__) @@ -346,17 +383,16 @@ int fallback_rand_getrandom(void *buf, size_t len); #endif #endif #else -unsigned long fallback_rand_1989(void); -unsigned long entropy_jitter(void); +size_t fallback_rand_1989(void); +size_t entropy_jitter(void); #endif -void write_mac_part(unsigned long partnum); /* Helper functions for command: dump */ void cmd_helper_dump(void); -void print_mac_from_nvm(unsigned long partnum); -void hexdump(unsigned long partnum); +void print_mac_from_nvm(size_t partnum); +void hexdump(size_t partnum); /* Helper functions for command: swap */ @@ -375,7 +411,7 @@ void cmd_helper_copy(void); void cmd_helper_cat(void); void cmd_helper_cat16(void); void cmd_helper_cat128(void); -void cat(unsigned long nff); +void cat(size_t nff); void cat_buf(unsigned char *b); /* Command verification/control @@ -388,51 +424,51 @@ void cmd_helper_err(void); */ void write_gbe_file(void); -void set_checksum(unsigned long part); -unsigned short calculated_checksum(unsigned long p); +void set_checksum(size_t part); +unsigned short calculated_checksum(size_t p); /* NVM read/write */ -unsigned short nvm_word(unsigned long pos16, unsigned long part); -void set_nvm_word(unsigned long pos16, - unsigned long part, unsigned short val16); -void set_part_modified(unsigned long p); -void check_nvm_bound(unsigned long pos16, unsigned long part); -void check_bin(unsigned long a, const char *a_name); +unsigned short nvm_word(size_t pos16, size_t part); +void set_nvm_word(size_t pos16, + size_t part, unsigned short val16); +void set_part_modified(size_t p); +void check_nvm_bound(size_t pos16, size_t part); +void check_bin(size_t a, const char *a_name); /* GbE file read/write */ -void rw_gbe_file_part(unsigned long p, int rw_type, +void rw_gbe_file_part(size_t p, int rw_type, const char *rw_type_str); void write_to_gbe_bin(void); int gbe_mv(void); -void check_written_part(unsigned long p); +void check_written_part(size_t p); void report_io_err_rw(void); -unsigned char *gbe_mem_offset(unsigned long part, const char *f_op); -off_t gbe_file_offset(unsigned long part, const char *f_op); -off_t gbe_x_offset(unsigned long part, const char *f_op, +unsigned char *gbe_mem_offset(size_t part, const char *f_op); +off_t gbe_file_offset(size_t part, const char *f_op); +off_t gbe_x_offset(size_t part, const char *f_op, const char *d_type, off_t nsize, off_t ncmp); -long rw_gbe_file_exact(int fd, unsigned char *mem, unsigned long nrw, +ssize_t rw_gbe_file_exact(int fd, unsigned char *mem, size_t nrw, off_t off, int rw_type); /* Generic read/write */ int fsync_dir(const char *path); -long rw_file_exact(int fd, unsigned char *mem, unsigned long len, +ssize_t rw_file_exact(int fd, unsigned char *mem, size_t len, off_t off, int rw_type, int loop_eagain, int loop_eintr, - unsigned long max_retries, int off_reset); -long prw(int fd, void *mem, unsigned long nrw, + size_t max_retries, int off_reset); +ssize_t prw(int fd, void *mem, size_t nrw, off_t off, int rw_type, int loop_eagain, int loop_eintr, int off_reset); -int io_args(int fd, void *mem, unsigned long nrw, +int io_args(int fd, void *mem, size_t nrw, off_t off, int rw_type); int check_file(int fd, struct stat *st); -long rw_over_nrw(long r, unsigned long nrw); -#if !defined(HAVE_REAL_PREAD_PWRITE) || \ - HAVE_REAL_PREAD_PWRITE < 1 +ssize_t rw_over_nrw(ssize_t r, size_t nrw); +#if !defined(REAL_POS_IO) || \ + REAL_POS_IO < 1 off_t lseek_on_eintr(int fd, off_t off, int whence, int loop_eagain, int loop_eintr); #endif @@ -442,16 +478,40 @@ int try_err(int loop_err, int errval); */ void usage(void); +void err_no_cleanup(int nvm_errval, const char *msg, ...); void err(int nvm_errval, const char *msg, ...); int exit_cleanup(void); const char *getnvmprogname(void); -/* Portable libc functions +/* libc hardening */ char *new_tmpfile(int *fd, int local, const char *path); -int mkstemp_n(char *template); -char *get_tmpdir(void); +char *new_tmplate(int *fd, int local, const char *path); +#if !(defined(DISABLE_OPENAT) && \ + ((DISABLE_OPENAT) > 0)) /* for openat dir replacement mitigation + in mkhtemp() + */ +int mkhtemp(int *fd, struct stat *st, + char *template, int dirfd, const char *fname, + struct stat *st_dir_initial); +#else +int mkhtemp(int *fd, struct stat *st, + char *template); +#endif +int world_writeable_and_sticky(const char *s, + int sticky_allowed, int always_sticky); +int same_dir(const char *a, const char *b); +int tmpdir_policy(const char *path, + int *allow_noworld_unsticky); +char *env_tmpdir(int always_sticky); +int split_path(const char *path, + struct path_split *ps); +int open_verified_dir(const char *path); +int check_dirfd(int dirfd, const char *path); +int secure_file(int *fd, struct stat *st, + int bad_flags, int check_seek, + int do_lock, mode_t mode); int close_on_eintr(int fd); int fsync_on_eintr(int fd); @@ -467,16 +527,16 @@ typedef char static_assert_unsigned_short_is_2[ typedef char static_assert_short_is_2[(sizeof(short) >= 2) ? 1 : -1]; typedef char static_assert_unsigned_int_is_4[ (sizeof(unsigned int) >= 4) ? 1 : -1]; -typedef char static_assert_unsigned_long_is_4[ - (sizeof(unsigned long) >= 4) ? 1 : -1]; -typedef char static_assert_long_ulong[ - (sizeof(unsigned long) == sizeof(long)) ? 1 : -1]; +typedef char static_assert_unsigned_ssize_t_is_4[ + (sizeof(size_t) >= 4) ? 1 : -1]; +typedef char static_assert_ssize_t_ussize_t[ + (sizeof(size_t) == sizeof(ssize_t)) ? 1 : -1]; typedef char static_assert_int_ge_32[(sizeof(int) >= 4) ? 1 : -1]; typedef char static_assert_twos_complement[ ((-1 & 3) == 3) ? 1 : -1 ]; -typedef char assert_unsigned_long_ptr[ - (sizeof(unsigned long) >= sizeof(void *)) ? 1 : -1 +typedef char assert_unsigned_ssize_t_ptr[ + (sizeof(size_t) >= sizeof(void *)) ? 1 : -1 ]; /* |
