mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-03-25 13:29:03 +02:00
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>
This commit is contained in:
@@ -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
|
||||
];
|
||||
|
||||
/*
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
void
|
||||
read_checksums(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct commands *cmd = &x->cmd[x->i];
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
unsigned long _p;
|
||||
unsigned long _skip_part;
|
||||
size_t _p;
|
||||
size_t _skip_part;
|
||||
|
||||
unsigned char _num_invalid;
|
||||
unsigned char _max_invalid;
|
||||
@@ -60,7 +60,7 @@ read_checksums(void)
|
||||
|
||||
if (_max_invalid == 1)
|
||||
err(ECANCELED, "%s: part %lu has a bad checksum",
|
||||
f->fname, (unsigned long)f->part);
|
||||
f->fname, (size_t)f->part);
|
||||
|
||||
err(ECANCELED, "%s: No valid checksum found in file",
|
||||
f->fname);
|
||||
@@ -68,7 +68,7 @@ read_checksums(void)
|
||||
}
|
||||
|
||||
int
|
||||
good_checksum(unsigned long partnum)
|
||||
good_checksum(size_t partnum)
|
||||
{
|
||||
unsigned short expected_checksum;
|
||||
unsigned short actual_checksum;
|
||||
@@ -87,16 +87,16 @@ good_checksum(unsigned long partnum)
|
||||
}
|
||||
|
||||
void
|
||||
set_checksum(unsigned long p)
|
||||
set_checksum(size_t p)
|
||||
{
|
||||
check_bin(p, "part number");
|
||||
set_nvm_word(NVM_CHECKSUM_WORD, p, calculated_checksum(p));
|
||||
}
|
||||
|
||||
unsigned short
|
||||
calculated_checksum(unsigned long p)
|
||||
calculated_checksum(size_t p)
|
||||
{
|
||||
unsigned long c;
|
||||
size_t c;
|
||||
unsigned int val16;
|
||||
|
||||
val16 = 0;
|
||||
|
||||
@@ -21,10 +21,10 @@
|
||||
void
|
||||
sanitize_command_list(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
|
||||
unsigned long c;
|
||||
unsigned long num_commands;
|
||||
size_t c;
|
||||
size_t num_commands;
|
||||
|
||||
num_commands = items(x->cmd);
|
||||
|
||||
@@ -33,37 +33,41 @@ sanitize_command_list(void)
|
||||
}
|
||||
|
||||
void
|
||||
sanitize_command_index(unsigned long c)
|
||||
sanitize_command_index(size_t c)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct commands *cmd = &x->cmd[c];
|
||||
|
||||
int _flag;
|
||||
unsigned long gbe_rw_size;
|
||||
size_t gbe_rw_size;
|
||||
|
||||
size_t rval;
|
||||
|
||||
check_command_num(c);
|
||||
|
||||
if (cmd->argc < 3)
|
||||
err(EINVAL, "cmd index %lu: argc below 3, %d",
|
||||
(unsigned long)c, cmd->argc);
|
||||
(size_t)c, cmd->argc);
|
||||
|
||||
if (cmd->str == NULL)
|
||||
err(EINVAL, "cmd index %lu: NULL str",
|
||||
(unsigned long)c);
|
||||
(size_t)c);
|
||||
|
||||
if (*cmd->str == '\0')
|
||||
err(EINVAL, "cmd index %lu: empty str",
|
||||
(unsigned long)c);
|
||||
(size_t)c);
|
||||
|
||||
if (xstrxlen(cmd->str, MAX_CMD_LEN + 1) >
|
||||
MAX_CMD_LEN) {
|
||||
if (slen(cmd->str, MAX_CMD_LEN +1, &rval) < 0)
|
||||
err(errno, "Could not get command length");
|
||||
|
||||
if (rval > MAX_CMD_LEN) {
|
||||
err(EINVAL, "cmd index %lu: str too long: %s",
|
||||
(unsigned long)c, cmd->str);
|
||||
(size_t)c, cmd->str);
|
||||
}
|
||||
|
||||
if (cmd->run == NULL)
|
||||
err(EINVAL, "cmd index %lu: cmd ptr null",
|
||||
(unsigned long)c);
|
||||
(size_t)c);
|
||||
|
||||
check_bin(cmd->arg_part, "cmd.arg_part");
|
||||
check_bin(cmd->chksum_read, "cmd.chksum_read");
|
||||
@@ -77,12 +81,12 @@ sanitize_command_index(unsigned long c)
|
||||
break;
|
||||
default:
|
||||
err(EINVAL, "Unsupported rw_size: %lu",
|
||||
(unsigned long)gbe_rw_size);
|
||||
(size_t)gbe_rw_size);
|
||||
}
|
||||
|
||||
if (gbe_rw_size > GBE_PART_SIZE)
|
||||
err(EINVAL, "rw_size larger than GbE part: %lu",
|
||||
(unsigned long)gbe_rw_size);
|
||||
(size_t)gbe_rw_size);
|
||||
|
||||
_flag = (cmd->flags & O_ACCMODE);
|
||||
|
||||
@@ -94,18 +98,22 @@ sanitize_command_index(unsigned long c)
|
||||
void
|
||||
set_cmd(int argc, char *argv[])
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
const char *cmd;
|
||||
|
||||
unsigned long c;
|
||||
int rval;
|
||||
|
||||
size_t c;
|
||||
|
||||
for (c = 0; c < items(x->cmd); c++) {
|
||||
|
||||
cmd = x->cmd[c].str;
|
||||
|
||||
/* not the right command */
|
||||
if (xstrxcmp(argv[2], cmd, MAX_CMD_LEN) != 0)
|
||||
continue;
|
||||
if (scmp(argv[2], cmd, MAX_CMD_LEN, &rval) < 0)
|
||||
err_no_cleanup(EINVAL,
|
||||
"could not compare command strings");
|
||||
if (rval != 0)
|
||||
continue; /* not the right command */
|
||||
|
||||
/* valid command found */
|
||||
if (argc >= x->cmd[c].argc) {
|
||||
@@ -115,7 +123,7 @@ set_cmd(int argc, char *argv[])
|
||||
return;
|
||||
}
|
||||
|
||||
err(EINVAL,
|
||||
err_no_cleanup(EINVAL,
|
||||
"Too few args on command '%s'", cmd);
|
||||
}
|
||||
|
||||
@@ -125,8 +133,8 @@ set_cmd(int argc, char *argv[])
|
||||
void
|
||||
set_cmd_args(int argc, char *argv[])
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
unsigned long i = x->i;
|
||||
struct xstate *x = xstatus();
|
||||
size_t i = x->i;
|
||||
struct commands *cmd = &x->cmd[i];
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
@@ -159,7 +167,7 @@ set_cmd_args(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long
|
||||
size_t
|
||||
conv_argv_part_num(const char *part_str)
|
||||
{
|
||||
unsigned char ch;
|
||||
@@ -173,21 +181,21 @@ conv_argv_part_num(const char *part_str)
|
||||
if (ch < '0' || ch > '1')
|
||||
err(EINVAL, "Bad part number (%c)", ch);
|
||||
|
||||
return (unsigned long)(ch - '0');
|
||||
return (size_t)(ch - '0');
|
||||
}
|
||||
|
||||
void
|
||||
check_command_num(unsigned long c)
|
||||
check_command_num(size_t c)
|
||||
{
|
||||
if (!valid_command(c))
|
||||
err(EINVAL, "Invalid run_cmd arg: %lu",
|
||||
(unsigned long)c);
|
||||
(size_t)c);
|
||||
}
|
||||
|
||||
unsigned char
|
||||
valid_command(unsigned long c)
|
||||
valid_command(size_t c)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct commands *cmd;
|
||||
|
||||
if (c >= items(x->cmd))
|
||||
@@ -206,10 +214,10 @@ valid_command(unsigned long c)
|
||||
void
|
||||
cmd_helper_setmac(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct macaddr *mac = &x->mac;
|
||||
|
||||
unsigned long partnum;
|
||||
size_t partnum;
|
||||
|
||||
check_cmd(cmd_helper_setmac, "setmac");
|
||||
|
||||
@@ -223,12 +231,17 @@ cmd_helper_setmac(void)
|
||||
void
|
||||
parse_mac_string(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct macaddr *mac = &x->mac;
|
||||
|
||||
unsigned long mac_byte;
|
||||
size_t mac_byte;
|
||||
|
||||
if (xstrxlen(x->mac.str, 18) != 17)
|
||||
size_t rval;
|
||||
|
||||
if (slen(x->mac.str, 18, &rval) < 0)
|
||||
err(EINVAL, "Could not determine MAC length");
|
||||
|
||||
if (rval != 17)
|
||||
err(EINVAL, "MAC address is the wrong length");
|
||||
|
||||
memset(mac->mac_buf, 0, sizeof(mac->mac_buf));
|
||||
@@ -244,15 +257,15 @@ parse_mac_string(void)
|
||||
}
|
||||
|
||||
void
|
||||
set_mac_byte(unsigned long mac_byte_pos)
|
||||
set_mac_byte(size_t mac_byte_pos)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct macaddr *mac = &x->mac;
|
||||
|
||||
char separator;
|
||||
|
||||
unsigned long mac_str_pos;
|
||||
unsigned long mac_nib_pos;
|
||||
size_t mac_str_pos;
|
||||
size_t mac_nib_pos;
|
||||
|
||||
mac_str_pos = mac_byte_pos * 3;
|
||||
|
||||
@@ -267,10 +280,10 @@ 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)
|
||||
set_mac_nib(size_t mac_str_pos,
|
||||
size_t mac_byte_pos, size_t mac_nib_pos)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct macaddr *mac = &x->mac;
|
||||
|
||||
char mac_ch;
|
||||
@@ -278,9 +291,13 @@ set_mac_nib(unsigned long mac_str_pos,
|
||||
|
||||
mac_ch = mac->str[mac_str_pos + mac_nib_pos];
|
||||
|
||||
if ((hex_num = hextonum(mac_ch)) > 15)
|
||||
err(EINVAL, "Invalid character '%c'",
|
||||
mac->str[mac_str_pos + mac_nib_pos]);
|
||||
if ((hex_num = hextonum(mac_ch)) > 15) {
|
||||
if (hex_num >= 17)
|
||||
err(EIO, "Randomisation failure");
|
||||
else
|
||||
err(EINVAL, "Invalid character '%c'",
|
||||
mac->str[mac_str_pos + mac_nib_pos]);
|
||||
}
|
||||
|
||||
/* If random, ensure that local/unicast bits are set.
|
||||
*/
|
||||
@@ -298,13 +315,13 @@ set_mac_nib(unsigned long mac_str_pos,
|
||||
}
|
||||
|
||||
void
|
||||
write_mac_part(unsigned long partnum)
|
||||
write_mac_part(size_t partnum)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
struct macaddr *mac = &x->mac;
|
||||
|
||||
unsigned long w;
|
||||
size_t w;
|
||||
|
||||
check_bin(partnum, "part number");
|
||||
if (!f->part_valid[partnum])
|
||||
@@ -314,17 +331,17 @@ write_mac_part(unsigned long partnum)
|
||||
set_nvm_word(w, partnum, mac->mac_buf[w]);
|
||||
|
||||
printf("Wrote MAC address to part %lu: ",
|
||||
(unsigned long)partnum);
|
||||
(size_t)partnum);
|
||||
print_mac_from_nvm(partnum);
|
||||
}
|
||||
|
||||
void
|
||||
cmd_helper_dump(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
unsigned long p;
|
||||
size_t p;
|
||||
|
||||
check_cmd(cmd_helper_dump, "dump");
|
||||
|
||||
@@ -338,12 +355,12 @@ cmd_helper_dump(void)
|
||||
fprintf(stderr,
|
||||
"BAD checksum %04x in part %lu (expected %04x)\n",
|
||||
nvm_word(NVM_CHECKSUM_WORD, p),
|
||||
(unsigned long)p,
|
||||
(size_t)p,
|
||||
calculated_checksum(p));
|
||||
}
|
||||
|
||||
printf("MAC (part %lu): ",
|
||||
(unsigned long)p);
|
||||
(size_t)p);
|
||||
|
||||
print_mac_from_nvm(p);
|
||||
|
||||
@@ -352,9 +369,9 @@ cmd_helper_dump(void)
|
||||
}
|
||||
|
||||
void
|
||||
print_mac_from_nvm(unsigned long partnum)
|
||||
print_mac_from_nvm(size_t partnum)
|
||||
{
|
||||
unsigned long c;
|
||||
size_t c;
|
||||
unsigned short val16;
|
||||
|
||||
for (c = 0; c < 3; c++) {
|
||||
@@ -373,16 +390,16 @@ print_mac_from_nvm(unsigned long partnum)
|
||||
}
|
||||
|
||||
void
|
||||
hexdump(unsigned long partnum)
|
||||
hexdump(size_t partnum)
|
||||
{
|
||||
unsigned long c;
|
||||
unsigned long row;
|
||||
size_t c;
|
||||
size_t row;
|
||||
unsigned short val16;
|
||||
|
||||
for (row = 0; row < 8; row++) {
|
||||
|
||||
printf("%08lx ",
|
||||
(unsigned long)((unsigned long)row << 4));
|
||||
(size_t)((size_t)row << 4));
|
||||
|
||||
for (c = 0; c < 8; c++) {
|
||||
|
||||
@@ -404,24 +421,24 @@ hexdump(unsigned long partnum)
|
||||
void
|
||||
cmd_helper_swap(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
check_cmd(cmd_helper_swap, "swap");
|
||||
|
||||
memcpy(
|
||||
f->buf + (unsigned long)GBE_WORK_SIZE,
|
||||
f->buf + (size_t)GBE_WORK_SIZE,
|
||||
f->buf,
|
||||
GBE_PART_SIZE);
|
||||
|
||||
memcpy(
|
||||
f->buf,
|
||||
f->buf + (unsigned long)GBE_PART_SIZE,
|
||||
f->buf + (size_t)GBE_PART_SIZE,
|
||||
GBE_PART_SIZE);
|
||||
|
||||
memcpy(
|
||||
f->buf + (unsigned long)GBE_PART_SIZE,
|
||||
f->buf + (unsigned long)GBE_WORK_SIZE,
|
||||
f->buf + (size_t)GBE_PART_SIZE,
|
||||
f->buf + (size_t)GBE_WORK_SIZE,
|
||||
GBE_PART_SIZE);
|
||||
|
||||
set_part_modified(0);
|
||||
@@ -431,14 +448,14 @@ cmd_helper_swap(void)
|
||||
void
|
||||
cmd_helper_copy(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
check_cmd(cmd_helper_copy, "copy");
|
||||
|
||||
memcpy(
|
||||
f->buf + (unsigned long)((f->part ^ 1) * GBE_PART_SIZE),
|
||||
f->buf + (unsigned long)(f->part * GBE_PART_SIZE),
|
||||
f->buf + (size_t)((f->part ^ 1) * GBE_PART_SIZE),
|
||||
f->buf + (size_t)(f->part * GBE_PART_SIZE),
|
||||
GBE_PART_SIZE);
|
||||
|
||||
set_part_modified(f->part ^ 1);
|
||||
@@ -447,7 +464,7 @@ cmd_helper_copy(void)
|
||||
void
|
||||
cmd_helper_cat(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
|
||||
check_cmd(cmd_helper_cat, "cat");
|
||||
|
||||
@@ -458,7 +475,7 @@ cmd_helper_cat(void)
|
||||
void
|
||||
cmd_helper_cat16(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
|
||||
check_cmd(cmd_helper_cat16, "cat16");
|
||||
|
||||
@@ -469,7 +486,7 @@ cmd_helper_cat16(void)
|
||||
void
|
||||
cmd_helper_cat128(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
|
||||
check_cmd(cmd_helper_cat128, "cat128");
|
||||
|
||||
@@ -478,18 +495,18 @@ cmd_helper_cat128(void)
|
||||
}
|
||||
|
||||
void
|
||||
cat(unsigned long nff)
|
||||
cat(size_t nff)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
unsigned long p;
|
||||
unsigned long ff;
|
||||
size_t p;
|
||||
size_t ff;
|
||||
|
||||
p = 0;
|
||||
ff = 0;
|
||||
|
||||
if ((unsigned long)x->cat != nff) {
|
||||
if ((size_t)x->cat != nff) {
|
||||
|
||||
err(ECANCELED, "erroneous call to cat");
|
||||
}
|
||||
@@ -501,7 +518,7 @@ cat(unsigned long nff)
|
||||
for (p = 0; p < 2; p++) {
|
||||
|
||||
cat_buf(f->bufcmp +
|
||||
(unsigned long)(p * (f->gbe_file_size >> 1)));
|
||||
(size_t)(p * (f->gbe_file_size >> 1)));
|
||||
|
||||
for (ff = 0; ff < nff; ff++) {
|
||||
|
||||
@@ -525,8 +542,8 @@ void
|
||||
check_cmd(void (*fn)(void),
|
||||
const char *name)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
unsigned long i = x->i;
|
||||
struct xstate *x = xstatus();
|
||||
size_t i = x->i;
|
||||
|
||||
if (x->cmd[i].run != fn)
|
||||
err(ECANCELED, "Running %s, but cmd %s is set",
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,7 +21,7 @@
|
||||
void
|
||||
open_gbe_file(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct commands *cmd = &x->cmd[x->i];
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
@@ -29,12 +29,12 @@ open_gbe_file(void)
|
||||
|
||||
xopen(&f->gbe_fd, f->fname,
|
||||
cmd->flags | O_BINARY |
|
||||
O_NOFOLLOW | O_CLOEXEC, &f->gbe_st);
|
||||
O_NOFOLLOW | O_CLOEXEC | O_NOCTTY, &f->gbe_st);
|
||||
|
||||
if (f->gbe_st.st_nlink > 1)
|
||||
err(EINVAL,
|
||||
"%s: warning: file has multiple (%lu) hard links\n",
|
||||
f->fname, (unsigned long)f->gbe_st.st_nlink);
|
||||
f->fname, (size_t)f->gbe_st.st_nlink);
|
||||
|
||||
if (f->gbe_st.st_nlink == 0)
|
||||
err(EIO, "%s: file unlinked while open", f->fname);
|
||||
@@ -69,7 +69,7 @@ open_gbe_file(void)
|
||||
void
|
||||
copy_gbe(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
read_file();
|
||||
@@ -77,19 +77,19 @@ copy_gbe(void)
|
||||
if (f->gbe_file_size == SIZE_8KB)
|
||||
return;
|
||||
|
||||
memcpy(f->buf + (unsigned long)GBE_PART_SIZE,
|
||||
f->buf + (unsigned long)(f->gbe_file_size >> 1),
|
||||
(unsigned long)GBE_PART_SIZE);
|
||||
memcpy(f->buf + (size_t)GBE_PART_SIZE,
|
||||
f->buf + (size_t)(f->gbe_file_size >> 1),
|
||||
(size_t)GBE_PART_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
read_file(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
struct stat _st;
|
||||
long _r;
|
||||
ssize_t _r;
|
||||
|
||||
/* read main file
|
||||
*/
|
||||
@@ -141,11 +141,11 @@ read_file(void)
|
||||
void
|
||||
write_gbe_file(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct commands *cmd = &x->cmd[x->i];
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
unsigned long p;
|
||||
size_t p;
|
||||
unsigned char update_checksum;
|
||||
|
||||
if ((cmd->flags & O_ACCMODE) == O_RDONLY)
|
||||
@@ -171,25 +171,25 @@ write_gbe_file(void)
|
||||
}
|
||||
|
||||
void
|
||||
rw_gbe_file_part(unsigned long p, int rw_type,
|
||||
rw_gbe_file_part(size_t p, int rw_type,
|
||||
const char *rw_type_str)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct commands *cmd = &x->cmd[x->i];
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
long rval;
|
||||
ssize_t rval;
|
||||
|
||||
off_t file_offset;
|
||||
|
||||
unsigned long gbe_rw_size;
|
||||
size_t gbe_rw_size;
|
||||
unsigned char *mem_offset;
|
||||
|
||||
gbe_rw_size = cmd->rw_size;
|
||||
|
||||
if (rw_type < IO_PREAD || rw_type > IO_PWRITE)
|
||||
err(errno, "%s: %s: part %lu: invalid rw_type, %d",
|
||||
f->fname, rw_type_str, (unsigned long)p, rw_type);
|
||||
f->fname, rw_type_str, (size_t)p, rw_type);
|
||||
|
||||
mem_offset = gbe_mem_offset(p, rw_type_str);
|
||||
file_offset = (off_t)gbe_file_offset(p, rw_type_str);
|
||||
@@ -199,17 +199,17 @@ rw_gbe_file_part(unsigned long p, int rw_type,
|
||||
|
||||
if (rval == -1)
|
||||
err(errno, "%s: %s: part %lu",
|
||||
f->fname, rw_type_str, (unsigned long)p);
|
||||
f->fname, rw_type_str, (size_t)p);
|
||||
|
||||
if ((unsigned long)rval != gbe_rw_size)
|
||||
if ((size_t)rval != gbe_rw_size)
|
||||
err(EIO, "%s: partial %s: part %lu",
|
||||
f->fname, rw_type_str, (unsigned long)p);
|
||||
f->fname, rw_type_str, (size_t)p);
|
||||
}
|
||||
|
||||
void
|
||||
write_to_gbe_bin(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct commands *cmd = &x->cmd[x->i];
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
@@ -240,14 +240,20 @@ write_to_gbe_bin(void)
|
||||
saved_errno = errno;
|
||||
|
||||
if (close_on_eintr(f->tmp_fd) == -1) {
|
||||
f->tmp_fd = -1;
|
||||
|
||||
fprintf(stderr, "FAIL: %s: close\n", f->tname);
|
||||
f->io_err_gbe_bin = 1;
|
||||
}
|
||||
f->tmp_fd = -1;
|
||||
|
||||
if (close_on_eintr(f->gbe_fd) == -1) {
|
||||
f->gbe_fd = -1;
|
||||
|
||||
fprintf(stderr, "FAIL: %s: close\n", f->fname);
|
||||
f->io_err_gbe_bin = 1;
|
||||
}
|
||||
f->gbe_fd = -1;
|
||||
|
||||
errno = saved_errno;
|
||||
|
||||
@@ -274,8 +280,10 @@ write_to_gbe_bin(void)
|
||||
/* removed by rename
|
||||
*/
|
||||
|
||||
if (f->tname != NULL)
|
||||
if (f->tname != NULL) {
|
||||
free(f->tname);
|
||||
f->tname = NULL;
|
||||
}
|
||||
|
||||
f->tname = NULL;
|
||||
}
|
||||
@@ -292,15 +300,15 @@ write_to_gbe_bin(void)
|
||||
}
|
||||
|
||||
void
|
||||
check_written_part(unsigned long p)
|
||||
check_written_part(size_t p)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct commands *cmd = &x->cmd[x->i];
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
long rval;
|
||||
ssize_t rval;
|
||||
|
||||
unsigned long gbe_rw_size;
|
||||
size_t gbe_rw_size;
|
||||
|
||||
off_t file_offset;
|
||||
unsigned char *mem_offset;
|
||||
@@ -328,7 +336,7 @@ check_written_part(unsigned long p)
|
||||
|
||||
if (rval == -1)
|
||||
f->rw_check_err_read[p] = f->io_err_gbe = 1;
|
||||
else if ((unsigned long)rval != gbe_rw_size)
|
||||
else if ((size_t)rval != gbe_rw_size)
|
||||
f->rw_check_partial_read[p] = f->io_err_gbe = 1;
|
||||
else if (memcmp(mem_offset, f->pad, gbe_rw_size) != 0)
|
||||
f->rw_check_bad_part[p] = f->io_err_gbe = 1;
|
||||
@@ -359,10 +367,10 @@ check_written_part(unsigned long p)
|
||||
void
|
||||
report_io_err_rw(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
unsigned long p;
|
||||
size_t p;
|
||||
|
||||
if (!f->io_err_gbe)
|
||||
return;
|
||||
@@ -374,22 +382,22 @@ report_io_err_rw(void)
|
||||
if (f->rw_check_err_read[p])
|
||||
fprintf(stderr,
|
||||
"%s: pread: p%lu (post-verification)\n",
|
||||
f->fname, (unsigned long)p);
|
||||
f->fname, (size_t)p);
|
||||
if (f->rw_check_partial_read[p])
|
||||
fprintf(stderr,
|
||||
"%s: partial pread: p%lu (post-verification)\n",
|
||||
f->fname, (unsigned long)p);
|
||||
f->fname, (size_t)p);
|
||||
if (f->rw_check_bad_part[p])
|
||||
fprintf(stderr,
|
||||
"%s: pwrite: corrupt write on p%lu\n",
|
||||
f->fname, (unsigned long)p);
|
||||
f->fname, (size_t)p);
|
||||
|
||||
if (f->rw_check_err_read[p] ||
|
||||
f->rw_check_partial_read[p]) {
|
||||
fprintf(stderr,
|
||||
"%s: p%lu: skipped checksum verification "
|
||||
"(because read failed)\n",
|
||||
f->fname, (unsigned long)p);
|
||||
f->fname, (size_t)p);
|
||||
|
||||
continue;
|
||||
}
|
||||
@@ -402,7 +410,7 @@ report_io_err_rw(void)
|
||||
fprintf(stderr, "BAD");
|
||||
|
||||
fprintf(stderr, " checksum in p%lu on-disk.\n",
|
||||
(unsigned long)p);
|
||||
(size_t)p);
|
||||
|
||||
if (f->post_rw_checksum[p]) {
|
||||
fprintf(stderr,
|
||||
@@ -415,7 +423,7 @@ report_io_err_rw(void)
|
||||
int
|
||||
gbe_mv(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
int rval;
|
||||
@@ -490,8 +498,11 @@ gbe_mv(void)
|
||||
if (fsync_on_eintr(dest_fd) == -1)
|
||||
goto ret_gbe_mv;
|
||||
|
||||
if (close_on_eintr(dest_fd) == -1)
|
||||
if (close_on_eintr(dest_fd) == -1) {
|
||||
dest_fd = -1;
|
||||
goto ret_gbe_mv;
|
||||
}
|
||||
dest_fd = -1;
|
||||
|
||||
if (rename(dest_tmp, f->fname) == -1)
|
||||
goto ret_gbe_mv;
|
||||
@@ -501,25 +512,37 @@ gbe_mv(void)
|
||||
goto ret_gbe_mv;
|
||||
}
|
||||
|
||||
free(dest_tmp);
|
||||
if (dest_tmp != NULL) {
|
||||
free(dest_tmp);
|
||||
dest_tmp = NULL;
|
||||
}
|
||||
|
||||
dest_tmp = NULL;
|
||||
|
||||
ret_gbe_mv:
|
||||
|
||||
/* TODO: this whole section is bloat.
|
||||
it can be generalised
|
||||
*/
|
||||
|
||||
if (f->gbe_fd > -1) {
|
||||
if (close_on_eintr(f->gbe_fd) < 0)
|
||||
if (close_on_eintr(f->gbe_fd) < 0) {
|
||||
f->gbe_fd = -1;
|
||||
rval = -1;
|
||||
}
|
||||
f->gbe_fd = -1;
|
||||
|
||||
if (fsync_dir(f->fname) < 0) {
|
||||
f->io_err_gbe_bin = 1;
|
||||
rval = -1;
|
||||
}
|
||||
f->gbe_fd = -1;
|
||||
}
|
||||
|
||||
if (f->tmp_fd > -1) {
|
||||
if (close_on_eintr(f->tmp_fd) < 0)
|
||||
if (close_on_eintr(f->tmp_fd) < 0) {
|
||||
f->tmp_fd = -1;
|
||||
rval = -1;
|
||||
|
||||
}
|
||||
f->tmp_fd = -1;
|
||||
}
|
||||
|
||||
@@ -552,9 +575,9 @@ ret_gbe_mv:
|
||||
* and it is *also* used during file I/O.
|
||||
*/
|
||||
unsigned char *
|
||||
gbe_mem_offset(unsigned long p, const char *f_op)
|
||||
gbe_mem_offset(size_t p, const char *f_op)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
off_t gbe_off;
|
||||
@@ -563,7 +586,7 @@ gbe_mem_offset(unsigned long p, const char *f_op)
|
||||
GBE_PART_SIZE, GBE_WORK_SIZE);
|
||||
|
||||
return (unsigned char *)
|
||||
(f->buf + (unsigned long)gbe_off);
|
||||
(f->buf + (size_t)gbe_off);
|
||||
}
|
||||
|
||||
/* I/O operations filtered here. These operations must
|
||||
@@ -571,9 +594,9 @@ gbe_mem_offset(unsigned long p, const char *f_op)
|
||||
* within the GbE file, and write 4KB of data.
|
||||
*/
|
||||
off_t
|
||||
gbe_file_offset(unsigned long p, const char *f_op)
|
||||
gbe_file_offset(size_t p, const char *f_op)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
off_t gbe_file_half_size;
|
||||
@@ -585,10 +608,10 @@ gbe_file_offset(unsigned long p, const char *f_op)
|
||||
}
|
||||
|
||||
off_t
|
||||
gbe_x_offset(unsigned long p, const char *f_op, const char *d_type,
|
||||
gbe_x_offset(size_t p, const char *f_op, const char *d_type,
|
||||
off_t nsize, off_t ncmp)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
off_t off;
|
||||
@@ -608,14 +631,14 @@ gbe_x_offset(unsigned long p, const char *f_op, const char *d_type,
|
||||
return off;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
long r;
|
||||
ssize_t r;
|
||||
|
||||
if (io_args(fd, mem, nrw, off, rw_type) == -1)
|
||||
return -1;
|
||||
@@ -624,17 +647,17 @@ rw_gbe_file_exact(int fd, unsigned char *mem, unsigned long nrw,
|
||||
if (mem < f->buf)
|
||||
goto err_rw_gbe_file_exact;
|
||||
|
||||
if ((unsigned long)(mem - f->buf) >= GBE_WORK_SIZE)
|
||||
if ((size_t)(mem - f->buf) >= GBE_WORK_SIZE)
|
||||
goto err_rw_gbe_file_exact;
|
||||
}
|
||||
|
||||
if (off < 0 || off >= f->gbe_file_size)
|
||||
goto err_rw_gbe_file_exact;
|
||||
|
||||
if (nrw > (unsigned long)(f->gbe_file_size - off))
|
||||
if (nrw > (size_t)(f->gbe_file_size - off))
|
||||
goto err_rw_gbe_file_exact;
|
||||
|
||||
if (nrw > (unsigned long)GBE_PART_SIZE)
|
||||
if (nrw > (size_t)GBE_PART_SIZE)
|
||||
goto err_rw_gbe_file_exact;
|
||||
|
||||
r = rw_file_exact(fd, mem, nrw, off, rw_type,
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
* Numerical functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
TODO: properly handle errno in this file
|
||||
*/
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
@@ -30,31 +34,108 @@
|
||||
|
||||
#include "../include/common.h"
|
||||
|
||||
/* TODO:
|
||||
* make this and errno handling more
|
||||
* flexible
|
||||
|
||||
in particular:
|
||||
hextonum could be modified to
|
||||
write into a buffer instead,
|
||||
with the converted numbers,
|
||||
of an arbitrary length
|
||||
*/
|
||||
unsigned short
|
||||
hextonum(char ch_s)
|
||||
{
|
||||
int saved_errno = errno;
|
||||
|
||||
/* rlong() can return error,
|
||||
but preserves errno if no
|
||||
error. we need to detect
|
||||
this because it handles
|
||||
/dev/urandom sometimes
|
||||
|
||||
therefore, if it's zero
|
||||
at start, we know if there
|
||||
was an err at the end, by
|
||||
return value zero, if errno
|
||||
was set; this is technically
|
||||
valid, since zero is also
|
||||
a valid random number!
|
||||
|
||||
it's an edge case that i had
|
||||
to fix. i'll rewrite the code
|
||||
better later. for now, it
|
||||
should be ok.
|
||||
*/
|
||||
errno = 0;
|
||||
|
||||
unsigned char ch;
|
||||
size_t rval;
|
||||
|
||||
ch = (unsigned char)ch_s;
|
||||
|
||||
if ((unsigned int)(ch - '0') <= 9)
|
||||
return ch - '0';
|
||||
if ((unsigned int)(ch - '0') <= 9) {
|
||||
|
||||
rval = ch - '0';
|
||||
goto hextonum_success;
|
||||
}
|
||||
|
||||
ch |= 0x20;
|
||||
|
||||
if ((unsigned int)(ch - 'a') <= 5)
|
||||
return ch - 'a' + 10;
|
||||
if ((unsigned int)(ch - 'a') <= 5) {
|
||||
|
||||
if (ch == '?' || ch == 'x')
|
||||
return (unsigned short)rlong() & 0xf;
|
||||
rval = ch - 'a' + 10;
|
||||
goto hextonum_success;
|
||||
}
|
||||
|
||||
if (ch == '?' || ch == 'x') {
|
||||
|
||||
rval = rlong();
|
||||
if (errno > 0)
|
||||
goto err_hextonum;
|
||||
|
||||
goto hextonum_success;
|
||||
}
|
||||
|
||||
goto err_hextonum;
|
||||
|
||||
hextonum_success:
|
||||
|
||||
errno = saved_errno;
|
||||
return (unsigned short)rval & 0xf;
|
||||
|
||||
err_hextonum:
|
||||
|
||||
if (errno == saved_errno)
|
||||
errno = EINVAL;
|
||||
else
|
||||
return 17; /* 17 indicates getrandom/urandom fail */
|
||||
|
||||
return 16; /* invalid character */
|
||||
|
||||
/* caller just checks >15. */
|
||||
}
|
||||
|
||||
/* Random numbers
|
||||
*/
|
||||
|
||||
unsigned long
|
||||
/* when calling this: save errno
|
||||
* first, then set errno to zero.
|
||||
* on error, this function will
|
||||
* set errno and possibly return
|
||||
*
|
||||
* rlong also preserves errno
|
||||
* and leaves it unchanged on
|
||||
* success, so if you do it
|
||||
* right, you can detect error.
|
||||
* this is because it uses
|
||||
* /dev/urandom which can err.
|
||||
* ditto getrandom (EINTR),
|
||||
* theoretically.
|
||||
*/
|
||||
|
||||
size_t
|
||||
rlong(void)
|
||||
{
|
||||
#if !(defined(FALLBACK_RAND_1989) && \
|
||||
@@ -63,14 +144,17 @@ rlong(void)
|
||||
defined(__FreeBSD__) || \
|
||||
defined(__NetBSD__) || defined(__APPLE__)
|
||||
|
||||
unsigned long rval;
|
||||
arc4random_buf(&rval, sizeof(unsigned long));
|
||||
int saved_errno = errno;
|
||||
size_t rval;
|
||||
|
||||
arc4random_buf(&rval, sizeof(size_t));
|
||||
|
||||
errno = saved_errno;
|
||||
return rval;
|
||||
#else
|
||||
static int fd = -1;
|
||||
static long nr = -1;
|
||||
static unsigned long off = 0;
|
||||
static ssize_t nr = -1;
|
||||
static size_t off = 0;
|
||||
#if defined (BUFSIZ)
|
||||
static char rbuf[BUFSIZ];
|
||||
#else
|
||||
@@ -82,12 +166,14 @@ rlong(void)
|
||||
static char rbuf[4096]; /* typical 32-bit BUFSIZ */
|
||||
#endif
|
||||
#endif
|
||||
unsigned long rval;
|
||||
long new_nr;
|
||||
size_t rval;
|
||||
ssize_t new_nr;
|
||||
|
||||
int retries = 0;
|
||||
int max_retries = 100;
|
||||
|
||||
int saved_errno = errno;
|
||||
|
||||
#if defined(__linux__)
|
||||
#if defined(HAVE_GETRANDOM) || \
|
||||
defined(HAVE_GETRANDOM_SYSCALL)
|
||||
@@ -98,17 +184,12 @@ rlong(void)
|
||||
* modern linux, but not on
|
||||
* every libc. better use the
|
||||
* official linux function
|
||||
*
|
||||
* similar benefits to arc4random
|
||||
* e.g. works in chroot, blocks
|
||||
* until it has enough entropy,
|
||||
* and works even when /dev/urandom
|
||||
* is available (doesn't use it);
|
||||
* it's generally more reliable
|
||||
*/
|
||||
|
||||
if (fallback_rand_getrandom(&rval, sizeof(rval)) == 0)
|
||||
if (fallback_rand_getrandom(&rval, sizeof(rval)) == 0) {
|
||||
errno = saved_errno;
|
||||
return rval;
|
||||
}
|
||||
|
||||
/*
|
||||
* now fall back to urandom if getrandom failed:
|
||||
@@ -131,15 +212,15 @@ rlong(void)
|
||||
retry_urandom_read:
|
||||
|
||||
if (++retries > max_retries)
|
||||
goto rlong_next;
|
||||
goto err_rlong;
|
||||
|
||||
if (nr < 0 || nr < (long)sizeof(unsigned long)) {
|
||||
if (nr < 0 || nr < (ssize_t)sizeof(size_t)) {
|
||||
|
||||
if (fd < 0) {
|
||||
|
||||
fd = open("/dev/urandom",
|
||||
O_RDONLY | O_BINARY | O_NOFOLLOW |
|
||||
O_CLOEXEC);
|
||||
O_CLOEXEC | O_NOCTTY);
|
||||
|
||||
#ifdef USE_OLD_DEV_RANDOM
|
||||
#if (USE_OLD_DEV_RANDOM) > 0
|
||||
@@ -155,7 +236,7 @@ retry_urandom_read:
|
||||
if (fd < 0)
|
||||
fd = open("/dev/random",
|
||||
O_RDONLY | O_BINARY | O_NOFOLLOW |
|
||||
O_CLOEXEC);
|
||||
O_CLOEXEC | O_NOCTTY);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -169,7 +250,7 @@ retry_urandom_read:
|
||||
sizeof(rbuf), 0, IO_READ, LOOP_EAGAIN,
|
||||
LOOP_EINTR, MAX_ZERO_RW_RETRY, OFF_ERR);
|
||||
|
||||
if (new_nr < 0 || new_nr < (long)sizeof(rbuf))
|
||||
if (new_nr < 0 || new_nr < (ssize_t)sizeof(rbuf))
|
||||
goto retry_urandom_read;
|
||||
|
||||
/* only reset buffer after successful refill */
|
||||
@@ -187,37 +268,37 @@ retry_urandom_read:
|
||||
fd = -1;
|
||||
retries = 0;
|
||||
|
||||
memcpy(&rval, rbuf + off, sizeof(unsigned long));
|
||||
memcpy(&rval, rbuf + off, sizeof(size_t));
|
||||
|
||||
nr -= (long)sizeof(unsigned long);
|
||||
off += sizeof(unsigned long);
|
||||
nr -= (ssize_t)sizeof(size_t);
|
||||
off += sizeof(size_t);
|
||||
|
||||
errno = saved_errno;
|
||||
|
||||
return rval;
|
||||
|
||||
rlong_next:
|
||||
err_rlong:
|
||||
|
||||
fd = -1;
|
||||
off = 0;
|
||||
nr = -1;
|
||||
if (errno == saved_errno)
|
||||
errno = EIO;
|
||||
|
||||
err(EIO, "Can't read from /dev/[ua]random");
|
||||
return 0;
|
||||
|
||||
#endif
|
||||
#else /* FALLBACK_RAND_1989 */
|
||||
/* your computer is from a museum
|
||||
*/
|
||||
unsigned long mix = 0;
|
||||
int nr;
|
||||
size_t mix = 0;
|
||||
int nr = 0;
|
||||
int saved_errno = errno;
|
||||
|
||||
/* 100 times, for entropy
|
||||
*/
|
||||
for (nr = 0; nr < 100; nr++)
|
||||
mix ^= fallback_rand_1989();
|
||||
|
||||
/* 101 times ;)
|
||||
*/
|
||||
return fallback_rand_1989();
|
||||
errno = saved_errno;
|
||||
return mix;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -226,17 +307,22 @@ rlong_next:
|
||||
#if defined(__linux__)
|
||||
#if defined(HAVE_GETRANDOM) || \
|
||||
defined(HAVE_GETRANDOM_SYSCALL)
|
||||
int
|
||||
fallback_rand_getrandom(void *buf, unsigned long len)
|
||||
int /* yes, linux is a fallback */
|
||||
fallback_rand_getrandom(void *buf, size_t len)
|
||||
{
|
||||
unsigned long off = 0;
|
||||
long rval = -1;
|
||||
size_t off = 0;
|
||||
ssize_t rval = -1;
|
||||
int saved_errno = errno;
|
||||
|
||||
if (!len)
|
||||
if (!len) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (buf == NULL)
|
||||
if (buf == NULL) {
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if defined(HAVE_GETRANDOM) || \
|
||||
defined(HAVE_GETRANDOM_SYSCALL)
|
||||
@@ -244,51 +330,60 @@ fallback_rand_getrandom(void *buf, unsigned long len)
|
||||
while (off < len) {
|
||||
|
||||
#if defined(HAVE_GETRANDOM)
|
||||
rval = (long)getrandom((char *)buf + off, len - off, 0);
|
||||
rval = (ssize_t)getrandom((char *)buf + off, len - off, 0);
|
||||
#elif defined(HAVE_GETRANDOM_SYSCALL)
|
||||
rval = (long)syscall(SYS_getrandom,
|
||||
rval = (ssize_t)syscall(SYS_getrandom,
|
||||
(char *)buf + off, len - off, 0);
|
||||
#endif
|
||||
|
||||
if (rval < 0) {
|
||||
if (errno == EINTR)
|
||||
if (errno == EINTR || errno == EAGAIN)
|
||||
continue;
|
||||
|
||||
errno = EIO;
|
||||
return -1; /* unsupported by kernel */
|
||||
}
|
||||
|
||||
off += (unsigned long)rval;
|
||||
if (rval == 0) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
off += (size_t)rval;
|
||||
}
|
||||
|
||||
errno = saved_errno;
|
||||
return 0;
|
||||
|
||||
#else
|
||||
(void)buf;
|
||||
(void)len;
|
||||
|
||||
errno = EIO;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
/* nobody should use this
|
||||
* (not crypto-safe)
|
||||
*/
|
||||
unsigned long
|
||||
size_t
|
||||
fallback_rand_1989(void)
|
||||
{
|
||||
static unsigned long mix = 0;
|
||||
static unsigned long counter = 0;
|
||||
static size_t mix = 0;
|
||||
static size_t counter = 0;
|
||||
|
||||
struct timeval tv;
|
||||
|
||||
/* nobody should use this
|
||||
* (not crypto-safe)
|
||||
*/
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
mix ^= (unsigned long)tv.tv_sec
|
||||
^ (unsigned long)tv.tv_usec
|
||||
^ (unsigned long)getpid()
|
||||
^ (unsigned long)&mix
|
||||
mix ^= (size_t)tv.tv_sec
|
||||
^ (size_t)tv.tv_usec
|
||||
^ (size_t)getpid()
|
||||
^ (size_t)&mix
|
||||
^ counter++
|
||||
^ entropy_jitter();
|
||||
|
||||
@@ -296,20 +391,20 @@ fallback_rand_1989(void)
|
||||
* Stack addresses can vary between
|
||||
* calls, thus increasing entropy.
|
||||
*/
|
||||
mix ^= (unsigned long)&mix;
|
||||
mix ^= (unsigned long)&tv;
|
||||
mix ^= (unsigned long)&counter;
|
||||
mix ^= (size_t)&mix;
|
||||
mix ^= (size_t)&tv;
|
||||
mix ^= (size_t)&counter;
|
||||
|
||||
return mix;
|
||||
}
|
||||
|
||||
unsigned long
|
||||
size_t
|
||||
entropy_jitter(void)
|
||||
{
|
||||
unsigned long mix;
|
||||
size_t mix;
|
||||
|
||||
struct timeval a, b;
|
||||
long mix_diff;
|
||||
ssize_t mix_diff;
|
||||
|
||||
int c;
|
||||
|
||||
@@ -326,13 +421,13 @@ entropy_jitter(void)
|
||||
* prevent negative numbers to prevent overflow,
|
||||
* which would bias rand to large numbers
|
||||
*/
|
||||
mix_diff = (long)(b.tv_usec - a.tv_usec);
|
||||
mix_diff = (ssize_t)(b.tv_usec - a.tv_usec);
|
||||
if (mix_diff < 0)
|
||||
mix_diff = -mix_diff;
|
||||
|
||||
mix ^= (unsigned long)(mix_diff);
|
||||
mix ^= (size_t)(mix_diff);
|
||||
|
||||
mix ^= (unsigned long)&mix;
|
||||
mix ^= (size_t)&mix;
|
||||
|
||||
}
|
||||
|
||||
@@ -341,9 +436,9 @@ entropy_jitter(void)
|
||||
#endif
|
||||
|
||||
void
|
||||
check_bin(unsigned long a, const char *a_name)
|
||||
check_bin(size_t a, const char *a_name)
|
||||
{
|
||||
if (a > 1)
|
||||
err(EINVAL, "%s must be 0 or 1, but is %lu",
|
||||
a_name, (unsigned long)a);
|
||||
a_name, (size_t)a);
|
||||
}
|
||||
|
||||
@@ -23,8 +23,11 @@
|
||||
#include "../include/common.h"
|
||||
|
||||
struct xstate *
|
||||
xstatus(int argc, char *argv[])
|
||||
xstart(int argc, char *argv[])
|
||||
{
|
||||
static int first_run = 1;
|
||||
static int pre_init = 0;
|
||||
|
||||
static struct xstate us = {
|
||||
/* DO NOT MESS THIS UP, OR THERE WILL BE DEMONS */
|
||||
{
|
||||
@@ -86,92 +89,52 @@ xstatus(int argc, char *argv[])
|
||||
|
||||
};
|
||||
|
||||
static int first_run = 1;
|
||||
struct xstate *x = &us;
|
||||
|
||||
if (!first_run) {
|
||||
if (pre_init)
|
||||
err_no_cleanup(ECANCELED,
|
||||
"Outside access to state during init");
|
||||
|
||||
first_run = 0;
|
||||
|
||||
if (!first_run)
|
||||
return &us;
|
||||
}
|
||||
|
||||
if (argc < 3)
|
||||
err_no_cleanup(EINVAL, "xstart: Too few arguments");
|
||||
if (argv == NULL)
|
||||
err_no_cleanup(EINVAL, "xstart: NULL argv");
|
||||
|
||||
first_run = 0;
|
||||
pre_init = 1;
|
||||
|
||||
us.f.buf = us.f.real_buf;
|
||||
|
||||
first_run = 0;
|
||||
us.argv0 = argv[0];
|
||||
|
||||
if (argc > 1)
|
||||
us.f.fname = argv[1];
|
||||
|
||||
if (argc < 3)
|
||||
usage();
|
||||
|
||||
/* https://man.openbsd.org/pledge.2
|
||||
https://man.openbsd.org/unveil.2 */
|
||||
#if defined(__OpenBSD__) && defined(OpenBSD)
|
||||
#if (OpenBSD) >= 604
|
||||
if (pledge("stdio flock rpath wpath cpath unveil", NULL) == -1)
|
||||
err(errno, "pledge plus unveil");
|
||||
#elif (OpenBSD) >= 509
|
||||
if (pledge("stdio flock rpath wpath cpath", NULL) == -1)
|
||||
err(errno, "pledge");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef S_ISREG
|
||||
err(ECANCELED, "Can't determine file types (S_ISREG undefined)");
|
||||
#endif
|
||||
|
||||
#ifndef CHAR_BIT
|
||||
err(ECANCELED, "Unknown char size");
|
||||
#else
|
||||
if (CHAR_BIT != 8)
|
||||
err(EINVAL, "Unsupported char size");
|
||||
#endif
|
||||
us.f.fname = argv[1];
|
||||
|
||||
#if defined(__OpenBSD__) && defined(OpenBSD) && \
|
||||
(OpenBSD) >= 604
|
||||
/* can only use local tmp on openbsd, due to unveil */
|
||||
us.f.tname = new_tmpfile(&us.f.tmp_fd, 1, NULL);
|
||||
#else
|
||||
us.f.tname = new_tmpfile(&us.f.tmp_fd, 0, NULL);
|
||||
// TODO: new_tmplate (do for above too)
|
||||
us.f.tname = new_tmpfile(&us.f.tmp_fd, 0, NULL); // TODO: NULL BAD!
|
||||
#endif
|
||||
if (us.f.tname == NULL)
|
||||
err(errno, "Can't create tmpfile");
|
||||
if (*us.f.tname == '\0')
|
||||
err(errno, "tmp dir is an empty string");
|
||||
|
||||
#if defined(__OpenBSD__) && defined(OpenBSD) && \
|
||||
OpenBSD >= 604
|
||||
if (unveil(us.f.tname, "rwc") == -1)
|
||||
err(errno, "unveil rwc: %s", us.f.tname);
|
||||
#endif
|
||||
if (fstat(us.f.tmp_fd, &us.f.tmp_st) < 0)
|
||||
err(errno, "%s: stat", us.f.tname);
|
||||
|
||||
sanitize_command_list();
|
||||
|
||||
/* parse user command */
|
||||
// TODO: CHECK ACCESSES VIA xstatus()
|
||||
set_cmd(argc, argv);
|
||||
set_cmd_args(argc, argv);
|
||||
|
||||
#if defined(__OpenBSD__) && defined(OpenBSD) && \
|
||||
(OpenBSD) >= 604
|
||||
if ((us.cmd[i].flags & O_ACCMODE) == O_RDONLY) {
|
||||
if (unveil(us.f.fname, "r") == -1)
|
||||
err(errno, "%s: unveil r", us.f.fname);
|
||||
} else {
|
||||
if (unveil(us.f.fname, "rwc") == -1)
|
||||
err(errno, "%s: unveil rw", us.f.fname);
|
||||
}
|
||||
if (us.f.tname == NULL)
|
||||
err_no_cleanup(errno, "x->f.tname null");
|
||||
if (*us.f.tname == '\0')
|
||||
err_no_cleanup(errno, "x->f.tname empty");
|
||||
|
||||
if (unveil(us.f.tname, "rwc") == -1)
|
||||
err(errno, "%s: unveil rwc", us.f.tname);
|
||||
|
||||
if (unveil(NULL, NULL) == -1)
|
||||
err(errno, "unveil block (rw)");
|
||||
|
||||
if (pledge("stdio flock rpath wpath cpath", NULL) == -1)
|
||||
err(errno, "pledge (kill unveil)");
|
||||
#endif
|
||||
|
||||
open_gbe_file();
|
||||
if (fstat(us.f.tmp_fd, &us.f.tmp_st) < 0)
|
||||
err_no_cleanup(errno, "%s: stat", us.f.tname);
|
||||
|
||||
memset(us.f.real_buf, 0, sizeof(us.f.real_buf));
|
||||
memset(us.f.bufcmp, 0, sizeof(us.f.bufcmp));
|
||||
@@ -179,16 +142,55 @@ xstatus(int argc, char *argv[])
|
||||
/* for good measure */
|
||||
memset(us.f.pad, 0, sizeof(us.f.pad));
|
||||
|
||||
copy_gbe();
|
||||
read_checksums();
|
||||
pre_init = 0;
|
||||
|
||||
return &us;
|
||||
}
|
||||
|
||||
struct xstate *
|
||||
xstatus(void)
|
||||
{
|
||||
struct xstate *x = xstart(0, NULL);
|
||||
|
||||
if (x == NULL)
|
||||
err_no_cleanup(EACCES, "NULL pointer to xstate");
|
||||
|
||||
sanitize_command_list();
|
||||
|
||||
return x;
|
||||
}
|
||||
|
||||
/* early init functions that
|
||||
should not access state
|
||||
WARNING:
|
||||
does not do cleanup. only
|
||||
call this during pre-init
|
||||
*/
|
||||
void
|
||||
err_no_cleanup(int nvm_errval, const char *msg, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if (errno == 0)
|
||||
errno = nvm_errval;
|
||||
if (!errno)
|
||||
errno = ECANCELED;
|
||||
|
||||
fprintf(stderr, "nvmutil: ");
|
||||
|
||||
va_start(args, msg);
|
||||
vfprintf(stderr, msg, args);
|
||||
va_end(args);
|
||||
|
||||
fprintf(stderr, ": %s\n", strerror(errno));
|
||||
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
void
|
||||
err(int nvm_errval, const char *msg, ...)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
|
||||
va_list args;
|
||||
|
||||
@@ -214,7 +216,7 @@ err(int nvm_errval, const char *msg, ...)
|
||||
const char *
|
||||
getnvmprogname(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
|
||||
const char *p;
|
||||
static char fallback[] = "nvmutil";
|
||||
@@ -239,7 +241,7 @@ getnvmprogname(void)
|
||||
int
|
||||
exit_cleanup(void)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f;
|
||||
|
||||
int close_err;
|
||||
@@ -252,14 +254,19 @@ exit_cleanup(void)
|
||||
f = &x->f;
|
||||
|
||||
if (f->gbe_fd > -1) {
|
||||
if (close_on_eintr(f->gbe_fd) == -1)
|
||||
if (close_on_eintr(f->gbe_fd) == -1) {
|
||||
f->gbe_fd = -1;
|
||||
close_err = 1;
|
||||
}
|
||||
f->gbe_fd = -1;
|
||||
}
|
||||
|
||||
if (f->tmp_fd > -1) {
|
||||
if (close_on_eintr(f->tmp_fd) == -1)
|
||||
if (close_on_eintr(f->tmp_fd) == -1) {
|
||||
f->tmp_fd = -1;
|
||||
close_err = 1;
|
||||
}
|
||||
f->tmp_fd = -1;
|
||||
}
|
||||
|
||||
if (f->tname != NULL) {
|
||||
|
||||
@@ -9,67 +9,106 @@
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../include/common.h"
|
||||
|
||||
/* Portable strncmp() that blocks
|
||||
* NULL/empty/unterminated strings
|
||||
/* scmp() - strict string comparison
|
||||
*
|
||||
* strict string comparison
|
||||
* similar to strncmp, but null and
|
||||
* unterminated inputs do not produce
|
||||
* a return value; on error, errno is
|
||||
* set and -1 is returned.
|
||||
*
|
||||
* the real return value is stored in
|
||||
* the 4th argument by pointer.
|
||||
*
|
||||
* the value at rval pointer is set,
|
||||
* only upon success. callers should
|
||||
* check the return value accordingly.
|
||||
*/
|
||||
|
||||
int
|
||||
xstrxcmp(const char *a, const char *b, unsigned long maxlen)
|
||||
scmp(const char *a,
|
||||
const char *b,
|
||||
size_t maxlen,
|
||||
int *rval)
|
||||
{
|
||||
unsigned long i;
|
||||
size_t ch;
|
||||
unsigned char ac;
|
||||
unsigned char bc;
|
||||
|
||||
if (a == NULL || b == NULL)
|
||||
err(EINVAL, "NULL input to xstrxcmp");
|
||||
if (a == NULL ||
|
||||
b == NULL ||
|
||||
rval == NULL) {
|
||||
|
||||
if (*a == '\0' || *b == '\0')
|
||||
err(EINVAL, "Empty string in xstrxcmp");
|
||||
|
||||
for (i = 0; i < maxlen; i++) {
|
||||
|
||||
unsigned char ac = (unsigned char)a[i];
|
||||
unsigned char bc = (unsigned char)b[i];
|
||||
|
||||
if (ac == '\0' || bc == '\0') {
|
||||
if (ac == bc)
|
||||
return 0;
|
||||
return ac - bc;
|
||||
}
|
||||
|
||||
if (ac != bc)
|
||||
return ac - bc;
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
err(EINVAL, "Unterminated string in xstrxcmp");
|
||||
for (ch = 0; ch < maxlen; ch++) {
|
||||
|
||||
errno = EINVAL;
|
||||
ac = (unsigned char)a[ch];
|
||||
bc = (unsigned char)b[ch];
|
||||
|
||||
if (ac != bc) {
|
||||
*rval = ac - bc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ac == '\0') {
|
||||
*rval = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* block unterminated strings */
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Portable strncmp() that blocks
|
||||
* NULL/empty/unterminated strings
|
||||
/* slen() - strict strict length
|
||||
*
|
||||
* strict string length calculation
|
||||
* similar to strnlen, but null and
|
||||
* unterminated inputs do not produce
|
||||
* a return value; on error, errno is
|
||||
* set and -1 is returned.
|
||||
*
|
||||
* the real return value is stored in
|
||||
* the 3rd argument by pointer.
|
||||
*
|
||||
* the value at rval pointer is set,
|
||||
* only upon success. callers should
|
||||
* check the return value accordingly.
|
||||
*/
|
||||
|
||||
unsigned long
|
||||
xstrxlen(const char *scmp, unsigned long maxlen)
|
||||
int
|
||||
slen(const char *s,
|
||||
size_t maxlen,
|
||||
size_t *rval)
|
||||
{
|
||||
unsigned long xstr_index;
|
||||
size_t ch;
|
||||
|
||||
if (scmp == NULL)
|
||||
err(EINVAL, "NULL input to xstrxlen");
|
||||
if (s == NULL ||
|
||||
rval == NULL) {
|
||||
|
||||
if (*scmp == '\0')
|
||||
err(EINVAL, "Empty string in xstrxlen");
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (xstr_index = 0;
|
||||
xstr_index < maxlen && scmp[xstr_index] != '\0';
|
||||
xstr_index++);
|
||||
for (ch = 0;
|
||||
ch < maxlen && s[ch] != '\0';
|
||||
ch++);
|
||||
|
||||
if (xstr_index == maxlen)
|
||||
err(EINVAL, "Unterminated string in xstrxlen");
|
||||
if (ch == maxlen) {
|
||||
/* unterminated */
|
||||
errno = EFAULT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
return xstr_index;
|
||||
*rval = ch;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -13,12 +13,12 @@
|
||||
#include "../include/common.h"
|
||||
|
||||
unsigned short
|
||||
nvm_word(unsigned long pos16, unsigned long p)
|
||||
nvm_word(size_t pos16, size_t p)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
unsigned long pos;
|
||||
size_t pos;
|
||||
|
||||
check_nvm_bound(pos16, p);
|
||||
pos = (pos16 << 1) + (p * GBE_PART_SIZE);
|
||||
@@ -28,12 +28,12 @@ nvm_word(unsigned long pos16, unsigned long p)
|
||||
}
|
||||
|
||||
void
|
||||
set_nvm_word(unsigned long pos16, unsigned long p, unsigned short val16)
|
||||
set_nvm_word(size_t pos16, size_t p, unsigned short val16)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
unsigned long pos;
|
||||
size_t pos;
|
||||
|
||||
check_nvm_bound(pos16, p);
|
||||
pos = (pos16 << 1) + (p * GBE_PART_SIZE);
|
||||
@@ -45,9 +45,9 @@ set_nvm_word(unsigned long pos16, unsigned long p, unsigned short val16)
|
||||
}
|
||||
|
||||
void
|
||||
set_part_modified(unsigned long p)
|
||||
set_part_modified(size_t p)
|
||||
{
|
||||
struct xstate *x = xstatus(0, NULL);
|
||||
struct xstate *x = xstatus();
|
||||
struct xfile *f = &x->f;
|
||||
|
||||
check_bin(p, "part number");
|
||||
@@ -55,7 +55,7 @@ set_part_modified(unsigned long p)
|
||||
}
|
||||
|
||||
void
|
||||
check_nvm_bound(unsigned long c, unsigned long p)
|
||||
check_nvm_bound(size_t c, size_t p)
|
||||
{
|
||||
/* Block out of bound NVM access
|
||||
*/
|
||||
@@ -64,5 +64,5 @@ check_nvm_bound(unsigned long c, unsigned long p)
|
||||
|
||||
if (c >= NVM_WORDS)
|
||||
err(ECANCELED, "check_nvm_bound: out of bounds %lu",
|
||||
(unsigned long)c);
|
||||
(size_t)c);
|
||||
}
|
||||
|
||||
@@ -6,6 +6,12 @@
|
||||
* These images configure your Intel Gigabit Ethernet adapter.
|
||||
*/
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
/* for pledge/unveil test:
|
||||
*/
|
||||
#include <sys/param.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
@@ -13,22 +19,88 @@
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "include/common.h"
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct xstate *x = xstatus(argc, argv);
|
||||
struct commands *cmd = &x->cmd[x->i];
|
||||
struct xfile *f = &x->f;
|
||||
struct xstate *x;
|
||||
|
||||
unsigned long c;
|
||||
struct commands *cmd;
|
||||
struct xfile *f;
|
||||
|
||||
size_t c;
|
||||
|
||||
/* https://man.openbsd.org/pledge.2
|
||||
https://man.openbsd.org/unveil.2 */
|
||||
#if defined(__OpenBSD__) && defined(OpenBSD)
|
||||
#if (OpenBSD) >= 604
|
||||
if (pledge("stdio flock rpath wpath cpath unveil", NULL) == -1)
|
||||
err_no_cleanup(errno, "pledge plus unveil, main");
|
||||
if (unveil("/dev/null", "r") == -1)
|
||||
err_no_cleanup(errno, "unveil r: /dev/null");
|
||||
#elif (OpenBSD) >= 509
|
||||
if (pledge("stdio flock rpath wpath cpath", NULL) == -1)
|
||||
err_no_cleanup(errno, "pledge, main");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef S_ISREG
|
||||
err_no_cleanup(ECANCELED,
|
||||
"Can't determine file types (S_ISREG undefined)");
|
||||
#endif
|
||||
#if ((CHAR_BIT) != 8)
|
||||
err_no_cleanup(ECANCELED, "Unsupported char size");
|
||||
#endif
|
||||
|
||||
x = xstart(argc, argv);
|
||||
|
||||
if (x == NULL)
|
||||
err_no_cleanup(ECANCELED, "NULL state on init");
|
||||
|
||||
cmd = &x->cmd[x->i];
|
||||
f = &x->f;
|
||||
|
||||
/* https://man.openbsd.org/pledge.2
|
||||
https://man.openbsd.org/unveil.2 */
|
||||
#if defined(__OpenBSD__) && defined(OpenBSD)
|
||||
#if (OpenBSD) >= 604
|
||||
|
||||
if ((us.cmd[i].flags & O_ACCMODE) == O_RDONLY) {
|
||||
if (unveil(us.f.fname, "r") == -1)
|
||||
err(errno, "%s: unveil r", us.f.fname);
|
||||
} else {
|
||||
if (unveil(us.f.fname, "rwc") == -1)
|
||||
err(errno, "%s: unveil rw", us.f.fname);
|
||||
}
|
||||
|
||||
if (unveil(us.f.tname, "rwc") == -1)
|
||||
err(errno, "unveil rwc: %s", us.f.tname);
|
||||
|
||||
if (unveil(NULL, NULL) == -1)
|
||||
err(errno, "unveil block (rw)");
|
||||
|
||||
if (pledge("stdio flock rpath wpath cpath", NULL) == -1)
|
||||
err(errno, "pledge (kill unveil)");
|
||||
|
||||
#elif (OpenBSD) >= 509
|
||||
if (pledge("stdio flock rpath wpath cpath", NULL) == -1)
|
||||
err(errno, "pledge");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (cmd->run == NULL)
|
||||
err(errno, "Command not set");
|
||||
|
||||
open_gbe_file();
|
||||
|
||||
copy_gbe();
|
||||
read_checksums();
|
||||
|
||||
cmd->run();
|
||||
|
||||
for (c = 0; c < items(x->cmd); c++)
|
||||
@@ -43,8 +115,10 @@ main(int argc, char *argv[])
|
||||
if (f->io_err_gbe_bin)
|
||||
err(EIO, "%s: error writing final file");
|
||||
|
||||
if (f->tname != NULL)
|
||||
if (f->tname != NULL) {
|
||||
free(f->tname);
|
||||
f->tname = NULL;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user