diff options
Diffstat (limited to 'util')
| -rw-r--r-- | util/nvmutil/nvmutil.c | 859 | ||||
| -rw-r--r-- | util/nvmutil/nvmutil.h | 33 |
2 files changed, 510 insertions, 382 deletions
diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c index 4e4d75b3..0df6ce89 100644 --- a/util/nvmutil/nvmutil.c +++ b/util/nvmutil/nvmutil.c @@ -154,12 +154,18 @@ main(int argc, char *argv[]) { struct commands *cmd; struct xfile *f; - int fd; + unsigned long i; + + char *tmp_path; + struct stat st; + int fd; - char *tmp_path = NULL; + tmp_path = NULL; - unsigned long *i; +#ifndef S_ISREG + err(ECANCELED, "Can't determine file types (S_ISREG undefined)"); +#endif #ifndef CHAR_BIT err(ECANCELED, "Unknown char size"); @@ -189,10 +195,8 @@ main(int argc, char *argv[]) #ifdef NVMUTIL_UNVEIL if (pledge("stdio flock rpath wpath cpath unveil", NULL) == -1) err(errno, "pledge, unveil"); - if (unveil("/dev/urandom", "r") == -1) - err(errno, "unveil: /dev/urandom"); - if (unveil("/dev/random", "r") == -1) - err(errno, "unveil: /dev/random"); + if (unveil("/dev/null", "r") == -1) + err(errno, "unveil: /dev/null"); #else if (pledge("stdio flock rpath wpath cpath", NULL) == -1) err(errno, "pledge"); @@ -224,8 +228,8 @@ main(int argc, char *argv[]) set_cmd(argc, argv); set_cmd_args(argc, argv); - i = &x->i; - cmd = &x->cmd[*i]; + i = x->i; + cmd = &x->cmd[i]; #ifdef NVMUTIL_UNVEIL if ((cmd->flags & O_ACCMODE) == O_RDONLY) { @@ -236,8 +240,8 @@ main(int argc, char *argv[]) err(errno, "%s: unveil rw", f->tname); } - if (unveil(tname, "rwc") == -1) - err(errno, "%s: unveil rwc", tname); + if (unveil(f->tname, "rwc") == -1) + err(errno, "%s: unveil rwc", f->tname); if (unveil(NULL, NULL) == -1) err(errno, "unveil block (rw)"); @@ -246,8 +250,6 @@ main(int argc, char *argv[]) err(errno, "pledge (kill unveil)"); #endif - srand((unsigned int)(time(NULL) ^ getpid())); - open_gbe_file(); memset(f->buf, 0, GBE_BUF_SIZE); @@ -281,7 +283,11 @@ void sanitize_command_list(void) { unsigned long c; - unsigned long num_commands = items(x->cmd); + unsigned long num_commands; + + check_null_command("sanitize_command_list"); + + num_commands = items(x->cmd); for (c = 0; c < num_commands; c++) sanitize_command_index(c); @@ -293,11 +299,14 @@ sanitize_command_list(void) void sanitize_command_index(unsigned long c) { + struct commands *cmd; + + int _flag; unsigned long gbe_rw_size; - struct commands *cmd = &x->cmd[c]; + check_null_command("sanitize_command_index"); - int _flag; + cmd = &x->cmd[c]; check_command_num(c); @@ -354,20 +363,22 @@ set_cmd(int argc, char *argv[]) { const char *cmd; - unsigned long i = 0; + unsigned long c; + + check_null_command("set_cmd"); - for (i = 0; i < items(x->cmd); i++) { + for (c = 0; c < items(x->cmd); c++) { - cmd = x->cmd[i].str; + cmd = x->cmd[c].str; /* not the right command */ if (xstrxcmp(argv[2], cmd, MAX_CMD_LEN) != 0) continue; /* valid command found */ - if (argc >= x->cmd[i].argc) { + if (argc >= x->cmd[c].argc) { x->no_cmd = 0; - x->i = i; /* set command */ + x->i = c; /* set command */ return; } @@ -382,31 +393,28 @@ set_cmd(int argc, char *argv[]) void set_cmd_args(int argc, char *argv[]) { - unsigned char arg_part; - unsigned long i; - - struct xfile *f; struct commands *cmd; + struct xfile *f; + unsigned long i; - if (!valid_command(x->i) || argc < 3) - usage(); - - if (x->no_cmd) - usage(); + check_null_command("set_cmd_args"); i = x->i; + cmd = &x->cmd[i]; f = &x->f; - cmd = &x->cmd[i]; + if (!valid_command(i) || argc < 3) + usage(); - arg_part = cmd->arg_part; + if (x->no_cmd) + usage(); /* Maintainer bugs */ - if (arg_part && argc < 4) + if (cmd->arg_part && argc < 4) err(EINVAL, "arg_part set for command that needs argc4"); - if (arg_part && i == CMD_SETMAC) + if (cmd->arg_part && i == CMD_SETMAC) err(EINVAL, "arg_part set on CMD_SETMAC"); @@ -417,7 +425,7 @@ set_cmd_args(int argc, char *argv[]) else x->mac.str = x->mac.rmac; - } else if (arg_part) { + } else if (cmd->arg_part) { f->part = conv_argv_part_num(argv[3]); } @@ -455,6 +463,7 @@ xstrxcmp(const char *a, const char *b, unsigned long maxlen) 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]; @@ -483,14 +492,16 @@ xstrxcmp(const char *a, const char *b, unsigned long maxlen) void open_gbe_file(void) { + struct commands *cmd; + struct xfile *f; + struct stat _st; int _flags; - unsigned long *i = &x->i; - - struct commands *cmd = &x->cmd[*i]; + check_null_command("open_gbe_file"); - struct xfile *f = &x->f; + cmd = &x->cmd[x->i]; + f = &x->f; xopen(&f->gbe_fd, f->fname, cmd->flags | O_BINARY | @@ -601,7 +612,11 @@ xopen(int *fd_ptr, const char *path, int flags, struct stat *st) void copy_gbe(void) { - struct xfile *f = &x->f; + struct xfile *f; + + check_null_command("copy_gbe"); + + f = &x->f; read_file(); @@ -626,10 +641,14 @@ copy_gbe(void) void read_file(void) { - long _r; + struct xfile *f; + struct stat _st; + long _r; + + check_null_command("read_file"); - struct xfile *f = &x->f; + f = &x->f; /* read main file */ _r = rw_file_exact(f->gbe_fd, f->buf, f->gbe_file_size, @@ -684,13 +703,19 @@ read_file(void) void read_checksums(void) { + struct commands *cmd; + struct xfile *f; + unsigned long _p; unsigned long _skip_part; + unsigned char _num_invalid; unsigned char _max_invalid; - struct xfile *f = &x->f; - struct commands *cmd = &x->cmd[x->i]; + check_null_command("read_checksums"); + + cmd = &x->cmd[x->i]; + f = &x->f; f->part_valid[0] = 0; f->part_valid[1] = 0; @@ -734,35 +759,51 @@ read_checksums(void) int good_checksum(unsigned long partnum) { - unsigned short expected_checksum = + unsigned short expected_checksum; + unsigned short actual_checksum; + + check_null_command("good_checksum"); + + expected_checksum = calculated_checksum(partnum); - unsigned short current_checksum = + actual_checksum = nvm_word(NVM_CHECKSUM_WORD, partnum); - return current_checksum == expected_checksum; + if (expected_checksum == actual_checksum) { + return 1; + } else { + return 0; + } } void run_cmd(void) { - unsigned long cmd_num; - struct commands *cmd; + unsigned long i; + void (*run)(void); - cmd_num = x->i; - cmd = &x->cmd[cmd_num]; + check_null_command("run_cmd"); - check_command_num(cmd_num); + i = x->i; + run = x->cmd[i].run; - if (cmd->run == NULL) - err(EINVAL, "Command %lu: null ptr", cmd_num); + check_command_num(i); + + if (run == NULL) + err(EINVAL, "Command %lu: null ptr", i); + + run(); - cmd->run(); + for (i = 0; i < items(x->cmd); i++) + x->cmd[i].run = cmd_helper_err; } void check_command_num(unsigned long c) { + check_null_command("check_command_num"); + if (!valid_command(c)) err(EINVAL, "Invalid run_cmd arg: %lu", (unsigned long)c); @@ -773,6 +814,8 @@ valid_command(unsigned long c) { struct commands *cmd; + check_null_command("valid_command"); + if (c >= items(x->cmd)) return 0; @@ -790,7 +833,11 @@ void cmd_helper_setmac(void) { unsigned long partnum; - struct macaddr *mac = &x->mac; + struct macaddr *mac; + + check_null_command("cmd_helper_setmac"); + + mac = &x->mac; check_cmd(cmd_helper_setmac, "setmac"); @@ -804,9 +851,13 @@ cmd_helper_setmac(void) void parse_mac_string(void) { + struct macaddr *mac; + unsigned long mac_byte; - struct macaddr *mac = &x->mac; + check_null_command("parse_mac_string"); + + mac = &x->mac; if (xstrxlen(x->mac.str, 18) != 17) err(EINVAL, "MAC address is the wrong length"); @@ -853,11 +904,18 @@ xstrxlen(const char *scmp, unsigned long maxlen) void set_mac_byte(unsigned long mac_byte_pos) { - unsigned long mac_str_pos = mac_byte_pos * 3; - unsigned long mac_nib_pos; + struct macaddr *mac; + char separator; - struct macaddr *mac = &x->mac; + unsigned long mac_str_pos; + unsigned long mac_nib_pos; + + check_null_command("set_mac_byte"); + + mac = &x->mac; + + mac_str_pos = mac_byte_pos * 3; if (mac_str_pos < 15) { if ((separator = mac->str[mac_str_pos + 2]) != ':') @@ -873,10 +931,14 @@ void set_mac_nib(unsigned long mac_str_pos, unsigned long mac_byte_pos, unsigned long mac_nib_pos) { + struct macaddr *mac; + char mac_ch; unsigned short hex_num; - struct macaddr *mac = &x->mac; + check_null_command("sanitize_command_list"); + + mac = &x->mac; mac_ch = mac->str[mac_str_pos + mac_nib_pos]; @@ -904,7 +966,9 @@ set_mac_nib(unsigned long mac_str_pos, unsigned short hextonum(char ch_s) { - unsigned char ch = (unsigned char)ch_s; + unsigned char ch; + + ch = (unsigned char)ch_s; if ((unsigned int)(ch - '0') <= 9) return ch - '0'; @@ -923,125 +987,60 @@ hextonum(char ch_s) unsigned long rlong(void) { - struct x_st_timeval tv; - static unsigned long mix = 0; - static unsigned long counter = 0; - - static int fd = -1; - unsigned long rval = 0; - long nr = -1; +#if (defined(__OpenBSD__) && (OpenBSD) >= 201) || \ + defined(__FreeBSD__) || \ + defined(__NetBSD__) || defined(__APPLE__) - x_i_gettimeofday(&tv, NULL); + unsigned long rval; + arc4random_buf(&rval, sizeof(unsigned long)); - mix ^= (unsigned long)tv.tv_sec - ^ (unsigned long)tv.tv_usec - ^ (unsigned long)getpid() - ^ (unsigned long)&mix - ^ counter++ - ^ entropy_jitter(); + return rval; +#else + int fd; - /* - * Stack addresses can vary between - * calls, thus increasing entropy. - */ - mix ^= (unsigned long)&mix; - mix ^= (unsigned long)&tv; - mix ^= (unsigned long)&counter; + long nr; - /* - * Now, we won't use this mix - * immediately. We'll try to - * read urandom first, which is - * likely safer, and pass that, - * falling back to the mixture - * if urandom fails. - * - * Since urandom is likely - * reliable, the number of - * times it will fail is - * likely extremely random, - * thus, building more than - * sufficient entropy by the - * time we do eventually use - * the fallback code - */ + unsigned long rval; - if (fd < 0) - fd = open("/dev/urandom", O_RDONLY | O_BINARY | O_NONBLOCK); + fd = open("/dev/urandom", O_RDONLY | O_BINARY); -#if !(defined(__OpenBSD__) && defined(OpenBSD)) || \ - (defined(__OpenBSD__) && defined(OpenBSD) && \ - OpenBSD < 604) +#ifdef __OpenBSD__ if (fd < 0) /* old openbsd */ - fd = open("/dev/arandom", O_RDONLY | O_BINARY | O_NONBLOCK); + fd = open("/dev/arandom", O_RDONLY | O_BINARY); #endif if (fd < 0) - fd = open("/dev/random", O_RDONLY | O_BINARY | O_NONBLOCK); + fd = open("/dev/random", O_RDONLY | O_BINARY); + + if (fd < 0) + err(errno, "can't open random device"); nr = rw_file_exact(fd, (unsigned char *)&rval, sizeof(unsigned long), 0, IO_READ, LOOP_EAGAIN, LOOP_EINTR, MAX_ZERO_RW_RETRY, OFF_ERR); - if (nr == sizeof(unsigned long)) - return rval; - - return mix; -} - -unsigned long -entropy_jitter(void) -{ - struct x_st_timeval a, b; - unsigned long mix = 0; - long mix_diff; - int i; + if (x_i_close(fd) < 0) + err(errno, "Can't close randomness fd"); - x_i_gettimeofday(&a, NULL); + if (nr != sizeof(unsigned long)) + err(errno, "Incomplete read from random device"); - for (i = 0; i < 32; i++) { - getpid(); - x_i_gettimeofday(&b, NULL); - - /* - * prevent negative numbers to prevent overflow, - * which would bias rand to large numbers - */ - mix_diff = (long)(b.tv_usec - a.tv_usec); - if (mix_diff < 0) - mix_diff = -mix_diff; - - mix ^= (unsigned long)(mix_diff); - mix ^= (unsigned long)&mix; - } - - return mix; -} - - - -int -x_i_gettimeofday(struct x_st_timeval *tv, void *tz) -{ - time_t t; - - (void)tz; - - t = time(NULL); - - tv->tv_sec = t; - tv->tv_usec = (long)((unsigned long)clock() % 1000000UL); - - return 0; + return rval; +#endif } void write_mac_part(unsigned long partnum) { + struct xfile *f; + struct macaddr *mac; + unsigned long w; - struct xfile *f = &x->f; - struct macaddr *mac = &x->mac; + check_null_command("write_mac_part"); + + f = &x->f; + mac = &x->mac; check_bin(partnum, "part number"); if (!f->part_valid[partnum]) @@ -1058,27 +1057,36 @@ write_mac_part(unsigned long partnum) void cmd_helper_dump(void) { - unsigned long partnum; + struct xfile *f; + + unsigned long p; + + check_null_command("cmd_helper_dump"); - struct xfile *f = &x->f; + f = &x->f; check_cmd(cmd_helper_dump, "dump"); f->part_valid[0] = good_checksum(0); f->part_valid[1] = good_checksum(1); - for (partnum = 0; partnum < 2; partnum++) { - if (!f->part_valid[partnum]) + for (p = 0; p < 2; p++) { + + if (!f->part_valid[p]) { + fprintf(stderr, "BAD checksum %04x in part %lu (expected %04x)\n", - nvm_word(NVM_CHECKSUM_WORD, partnum), - (unsigned long)partnum, - calculated_checksum(partnum)); + nvm_word(NVM_CHECKSUM_WORD, p), + (unsigned long)p, + calculated_checksum(p)); + } printf("MAC (part %lu): ", - (unsigned long)partnum); - print_mac_from_nvm(partnum); - hexdump(partnum); + (unsigned long)p); + + print_mac_from_nvm(p); + + hexdump(p); } } @@ -1088,6 +1096,8 @@ print_mac_from_nvm(unsigned long partnum) unsigned long c; unsigned short val16; + check_null_command("print_mac_from_nvm"); + for (c = 0; c < 3; c++) { val16 = nvm_word(c, partnum); printf("%02x:%02x", @@ -1107,16 +1117,26 @@ hexdump(unsigned long partnum) unsigned long row; unsigned short val16; + check_null_command("hexdump"); + for (row = 0; row < 8; row++) { - printf("%08lx ", (unsigned long)((unsigned long)row << 4)); + + printf("%08lx ", + (unsigned long)((unsigned long)row << 4)); + for (c = 0; c < 8; c++) { + val16 = nvm_word((row << 3) + c, partnum); + if (c == 4) printf(" "); + printf(" %02x %02x", (unsigned int)(val16 & 0xff), (unsigned int)(val16 >> 8)); + } + printf("\n"); } } @@ -1124,10 +1144,14 @@ hexdump(unsigned long partnum) void cmd_helper_swap(void) { - struct xfile *f = &x->f; + struct xfile *f; + + check_null_command("cmd_helper_swap"); check_cmd(cmd_helper_swap, "swap"); + f = &x->f; + x_v_memcpy( f->buf + (unsigned long)GBE_WORK_SIZE, f->buf, @@ -1150,10 +1174,14 @@ cmd_helper_swap(void) void cmd_helper_copy(void) { - struct xfile *f = &x->f; + struct xfile *f; + + check_null_command("cmd_helper_copy"); check_cmd(cmd_helper_copy, "copy"); + f = &x->f; + x_v_memcpy( f->buf + (unsigned long)((f->part ^ 1) * GBE_PART_SIZE), f->buf + (unsigned long)(f->part * GBE_PART_SIZE), @@ -1163,7 +1191,10 @@ cmd_helper_copy(void) } void -cmd_helper_cat(void) { +cmd_helper_cat(void) +{ + check_null_command("cmd_helper_cat"); + check_cmd(cmd_helper_cat, "cat"); x->cat = 0; @@ -1171,7 +1202,10 @@ cmd_helper_cat(void) { } void -cmd_helper_cat16(void) { +cmd_helper_cat16(void) +{ + check_null_command("cmd_helper_cat16"); + check_cmd(cmd_helper_cat16, "cat16"); x->cat = 1; @@ -1179,7 +1213,10 @@ cmd_helper_cat16(void) { } void -cmd_helper_cat128(void) { +cmd_helper_cat128(void) +{ + check_null_command("cmd_helper_cat128"); + check_cmd(cmd_helper_cat128, "cat128"); x->cat = 15; @@ -1187,10 +1224,13 @@ cmd_helper_cat128(void) { } void -check_cmd(void (*fn)(void), const char *name) +check_cmd(void (*fn)(void), + const char *name) { unsigned long i; + check_null_command("check_cmd"); + if (x->cmd[x->i].run != fn) err(ECANCELED, "Running %s, but cmd %s is set", name, x->cmd[x->i].str); @@ -1211,46 +1251,51 @@ check_cmd(void (*fn)(void), const char *name) void cmd_helper_err(void) { - err(ECANCELED, "Erroneously running command twice"); + err(ECANCELED, + "Erroneously running command twice"); } void cat(unsigned long nff) { - struct xfile *f = &x->f; - struct commands *cmd = &x->cmd[x->i]; + struct xfile *f; + + unsigned long p; + unsigned long ff; - unsigned long p = 0; - unsigned long ff = 0; + check_null_command("cat"); + + f = &x->f; + + p = 0; + ff = 0; + + if ((unsigned long)x->cat != nff) { - if ((unsigned long)x->cat != nff || - !((cmd->run == cmd_helper_cat && nff == 0) || - (cmd->run == cmd_helper_cat16 && nff == 1) || - (cmd->run == cmd_helper_cat128 && nff == 15))) err(ECANCELED, "erroneous call to cat"); + } fflush(NULL); memset(f->pad, 0xff, GBE_PART_SIZE); for (p = 0; p < 2; p++) { + cat_buf(f->bufcmp + (unsigned long)(p * (f->gbe_file_size >> 1))); - for (ff = 0; ff < nff; ff++) + for (ff = 0; ff < nff; ff++) { + cat_buf(f->pad); + } } } void cat_buf(unsigned char *b) { - struct commands *cmd = &x->cmd[x->i]; - - if (!((cmd->run == cmd_helper_cat && x->cat == 0) || - (cmd->run == cmd_helper_cat16 && x->cat == 1) || - (cmd->run == cmd_helper_cat128 && x->cat == 15))) - err(ECANCELED, "erroneous call to cat"); + if (b == NULL) + err(errno, "null pointer in cat command"); if (rw_file_exact(STDOUT_FILENO, b, GBE_PART_SIZE, 0, IO_WRITE, LOOP_EAGAIN, LOOP_EINTR, @@ -1261,14 +1306,19 @@ cat_buf(unsigned char *b) void write_gbe_file(void) { + struct commands *cmd; + struct xfile *f; + struct stat _gbe_st; struct stat _tmp_st; unsigned long p; unsigned char update_checksum; - struct commands *cmd = &x->cmd[x->i]; - struct xfile *f = &x->f; + check_null_command("write_gbe_file"); + + cmd = &x->cmd[x->i]; + f = &x->f; if ((cmd->flags & O_ACCMODE) == O_RDONLY) return; @@ -1307,6 +1357,8 @@ write_gbe_file(void) void set_checksum(unsigned long p) { + check_null_command("set_checksum"); + check_bin(p, "part number"); set_nvm_word(NVM_CHECKSUM_WORD, p, calculated_checksum(p)); } @@ -1315,7 +1367,11 @@ unsigned short calculated_checksum(unsigned long p) { unsigned long c; - unsigned int val16 = 0; + unsigned int val16; + + check_null_command("calculated_checksum"); + + val16 = 0; for (c = 0; c < NVM_CHECKSUM_WORD; c++) val16 += (unsigned int)nvm_word(c, p); @@ -1334,10 +1390,14 @@ calculated_checksum(unsigned long p) unsigned short nvm_word(unsigned long pos16, unsigned long p) { - struct xfile *f = &x->f; + struct xfile *f; unsigned long pos; + check_null_command("nvm_word"); + + f = &x->f; + check_nvm_bound(pos16, p); pos = (pos16 << 1) + (p * GBE_PART_SIZE); @@ -1348,9 +1408,14 @@ nvm_word(unsigned long pos16, unsigned long p) void set_nvm_word(unsigned long pos16, unsigned long p, unsigned short val16) { - struct xfile *f = &x->f; + struct xfile *f; + unsigned long pos; + check_null_command("set_nvm_word"); + + f = &x->f; + check_nvm_bound(pos16, p); pos = (pos16 << 1) + (p * GBE_PART_SIZE); @@ -1363,7 +1428,11 @@ set_nvm_word(unsigned long pos16, unsigned long p, unsigned short val16) void set_part_modified(unsigned long p) { - struct xfile *f = &x->f; + struct xfile *f; + + check_null_command("set_part_modified"); + + f = &x->f; check_bin(p, "part number"); f->part_modified[p] = 1; @@ -1378,6 +1447,8 @@ check_nvm_bound(unsigned long c, unsigned long p) * ever modified the NVM area. */ + check_null_command("check_nvm_bound"); + check_bin(p, "part number"); if (c >= NVM_WORDS) @@ -1397,15 +1468,20 @@ void rw_gbe_file_part(unsigned long p, int rw_type, const char *rw_type_str) { - struct xfile *f = &x->f; - struct commands *cmd = &x->cmd[x->i]; + struct commands *cmd; + struct xfile *f; - long r; - unsigned long gbe_rw_size; + long rval; + off_t file_offset; + + unsigned long gbe_rw_size; unsigned char *mem_offset; - off_t file_offset; + check_null_command("rw_gbe_file_part"); + + cmd = &x->cmd[x->i]; + f = &x->f; gbe_rw_size = cmd->rw_size; @@ -1416,14 +1492,14 @@ rw_gbe_file_part(unsigned long p, int rw_type, mem_offset = gbe_mem_offset(p, rw_type_str); file_offset = (off_t)gbe_file_offset(p, rw_type_str); - r = rw_gbe_file_exact(f->tmp_fd, mem_offset, + rval = rw_gbe_file_exact(f->tmp_fd, mem_offset, gbe_rw_size, file_offset, rw_type); - if (r == -1) + if (rval == -1) err(errno, "%s: %s: part %lu", f->fname, rw_type_str, (unsigned long)p); - if ((unsigned long)r != gbe_rw_size) + if ((unsigned long)rval != gbe_rw_size) err(EIO, "%s: partial %s: part %lu", f->fname, rw_type_str, (unsigned long)p); } @@ -1431,12 +1507,16 @@ rw_gbe_file_part(unsigned long p, int rw_type, void write_to_gbe_bin(void) { - struct xfile *f = &x->f; + struct commands *cmd; + struct xfile *f; int saved_errno; int mv; - struct commands *cmd = &x->cmd[x->i]; + check_null_command("write_to_gbe_bin"); + + cmd = &x->cmd[x->i]; + f = &x->f; if ((cmd->flags & O_ACCMODE) != O_RDWR) return; @@ -1523,16 +1603,23 @@ write_to_gbe_bin(void) void check_written_part(unsigned long p) { - struct commands *cmd = &x->cmd[x->i]; - struct xfile *f = &x->f; + struct commands *cmd; + struct xfile *f; + + long rval; unsigned long gbe_rw_size; - unsigned char *mem_offset; + off_t file_offset; - unsigned char *buf_restore; + unsigned char *mem_offset; + struct stat st; + unsigned char *buf_restore; - long r; + check_null_command("check_written_part"); + + cmd = &x->cmd[x->i]; + f = &x->f; if (!f->part_modified[p]) return; @@ -1554,12 +1641,12 @@ check_written_part(unsigned long p) if (st.st_dev != f->tmp_dev || st.st_ino != f->tmp_ino) err(EIO, "%s: file changed during write", f->tname); - r = rw_gbe_file_exact(f->tmp_fd, f->pad, + rval = rw_gbe_file_exact(f->tmp_fd, f->pad, gbe_rw_size, file_offset, IO_PREAD); - if (r == -1) + if (rval == -1) f->rw_check_err_read[p] = f->io_err_gbe = 1; - else if ((unsigned long)r != gbe_rw_size) + else if ((unsigned long)rval != gbe_rw_size) f->rw_check_partial_read[p] = f->io_err_gbe = 1; else if (x_i_memcmp(mem_offset, f->pad, gbe_rw_size) != 0) f->rw_check_bad_part[p] = f->io_err_gbe = 1; @@ -1574,18 +1661,30 @@ check_written_part(unsigned long p) * That's why we hardcode good_checksum(0). */ buf_restore = f->buf; + + /* + * good_checksum works on f->buf + * so let's change f->buf for now + */ f->buf = f->pad; - f->post_rw_checksum[p] = good_checksum(0); + + if (good_checksum(0)) + f->post_rw_checksum[p] = 1; + f->buf = buf_restore; } void report_io_err_rw(void) { - struct xfile *f = &x->f; + struct xfile *f; unsigned long p; + check_null_command("report_io_err_rw"); + + f = &x->f; + if (!f->io_err_gbe) return; @@ -1637,20 +1736,31 @@ report_io_err_rw(void) int gbe_mv(void) { - struct xfile *f = &x->f; + struct xfile *f; + + int rval; - int r; int saved_errno; - int tmp_gbe_bin_exists = 1; + int tmp_gbe_bin_exists; + + char *dest_tmp; + int dest_fd; - char *dest_tmp = NULL; - int dest_fd = -1; + check_null_command("gbe_mv"); + + f = &x->f; + + /* will be set 0 if it doesn't */ + tmp_gbe_bin_exists = 1; + + dest_tmp = NULL; + dest_fd = -1; saved_errno = errno; - r = rename(f->tname, f->fname); + rval = rename(f->tname, f->fname); - if (r > -1) { + if (rval > -1) { /* * same filesystem */ @@ -1659,7 +1769,7 @@ gbe_mv(void) if (fsync_dir(f->fname) < 0) { f->io_err_gbe_bin = 1; - r = -1; + rval = -1; } goto ret_gbe_mv; @@ -1670,7 +1780,7 @@ gbe_mv(void) /* cross-filesystem rename */ - if ((r = f->tmp_fd = open(f->tname, + if ((rval = f->tmp_fd = open(f->tname, O_RDONLY | O_BINARY)) == -1) goto ret_gbe_mv; @@ -1681,20 +1791,20 @@ gbe_mv(void) /* copy data */ - r = rw_file_exact(f->tmp_fd, f->bufcmp, + rval = rw_file_exact(f->tmp_fd, f->bufcmp, f->gbe_file_size, 0, IO_PREAD, NO_LOOP_EAGAIN, LOOP_EINTR, MAX_ZERO_RW_RETRY, OFF_ERR); - if (r < 0) + if (rval < 0) goto ret_gbe_mv; - r = rw_file_exact(dest_fd, f->bufcmp, + rval = rw_file_exact(dest_fd, f->bufcmp, f->gbe_file_size, 0, IO_PWRITE, NO_LOOP_EAGAIN, LOOP_EINTR, MAX_ZERO_RW_RETRY, OFF_ERR); - if (r < 0) + if (rval < 0) goto ret_gbe_mv; if (x_i_fsync(dest_fd) == -1) @@ -1718,17 +1828,17 @@ ret_gbe_mv: if (f->gbe_fd > -1) { if (x_i_close(f->gbe_fd) < 0) - r = -1; + rval = -1; if (fsync_dir(f->fname) < 0) { f->io_err_gbe_bin = 1; - r = -1; + rval = -1; } f->gbe_fd = -1; } if (f->tmp_fd > -1) { if (x_i_close(f->tmp_fd) < 0) - r = -1; + rval = -1; f->tmp_fd = -1; } @@ -1739,12 +1849,12 @@ ret_gbe_mv: */ if (tmp_gbe_bin_exists) { if (unlink(f->tname) < 0) - r = -1; + rval = -1; else tmp_gbe_bin_exists = 0; } - if (r < 0) { + if (rval < 0) { /* * if nothing set errno, * we assume EIO, or we @@ -1756,7 +1866,7 @@ ret_gbe_mv: errno = saved_errno; } - return r; + return rval; } /* @@ -1766,21 +1876,27 @@ ret_gbe_mv: int fsync_dir(const char *path) { -#if defined(PATH_LEN) && \ - (PATH_LEN) >= 256 - unsigned long maxlen = PATH_LEN; -#else - unsigned long maxlen = 1024; -#endif + int saved_errno = errno; + unsigned long pathlen; -/* char dirbuf[maxlen]; */ - char *dirbuf = NULL; + unsigned long maxlen; + + char *dirbuf; + int dirfd; + char *slash; - int dfd = -1; struct stat st; - int saved_errno = errno; +#if defined(PATH_LEN) && \ + (PATH_LEN) >= 256 + maxlen = PATH_LEN; +#else + maxlen = 1024; +#endif + + dirbuf = NULL; + dirfd = -1; pathlen = xstrxlen(path, maxlen); @@ -1813,7 +1929,7 @@ fsync_dir(const char *path) dirbuf[1] = '\0'; } - dfd = open(dirbuf, O_RDONLY + dirfd = open(dirbuf, O_RDONLY #ifdef O_DIRECTORY | O_DIRECTORY #endif @@ -1821,10 +1937,10 @@ fsync_dir(const char *path) | O_NOFOLLOW #endif ); - if (dfd == -1) + if (dirfd == -1) goto err_fsync_dir; - if (fstat(dfd, &st) < 0) + if (fstat(dirfd, &st) < 0) goto err_fsync_dir; if (!S_ISDIR(st.st_mode)) { @@ -1833,10 +1949,10 @@ fsync_dir(const char *path) } /* sync file on disk */ - if (x_i_fsync(dfd) == -1) + if (x_i_fsync(dirfd) == -1) goto err_fsync_dir; - if (x_i_close(dfd) == -1) + if (x_i_close(dirfd) == -1) goto err_fsync_dir; if (dirbuf != NULL) @@ -1855,8 +1971,8 @@ err_fsync_dir: if (dirbuf != NULL) free(dirbuf); - if (dfd > -1) - x_i_close(dfd); + if (dirfd > -1) + x_i_close(dirfd); errno = saved_errno; @@ -1871,12 +1987,19 @@ err_fsync_dir: unsigned char * gbe_mem_offset(unsigned long p, const char *f_op) { - struct xfile *f = &x->f; + struct xfile *f; - off_t gbe_off = gbe_x_offset(p, f_op, "mem", + off_t gbe_off; + + check_null_command("gbe_mem_offset"); + + f = &x->f; + + gbe_off = gbe_x_offset(p, f_op, "mem", GBE_PART_SIZE, GBE_WORK_SIZE); - return (unsigned char *)(f->buf + (unsigned long)gbe_off); + return (unsigned char *) + (f->buf + (unsigned long)gbe_off); } /* @@ -1889,9 +2012,15 @@ gbe_mem_offset(unsigned long p, const char *f_op) off_t gbe_file_offset(unsigned long p, const char *f_op) { - struct xfile *f = &x->f; + struct xfile *f; + + off_t gbe_file_half_size; + + check_null_command("gbe_file_offset"); + + f = &x->f; - off_t gbe_file_half_size = f->gbe_file_size >> 1; + gbe_file_half_size = f->gbe_file_size >> 1; return gbe_x_offset(p, f_op, "file", gbe_file_half_size, f->gbe_file_size); @@ -1901,12 +2030,16 @@ off_t gbe_x_offset(unsigned long p, const char *f_op, const char *d_type, off_t nsize, off_t ncmp) { - struct xfile *f = &x->f; + struct xfile *f; off_t off; + check_null_command("gbe_x_offset"); + check_bin(p, "part number"); + f = &x->f; + off = ((off_t)p) * (off_t)nsize; if (off > ncmp - GBE_PART_SIZE) @@ -1924,10 +2057,14 @@ long rw_gbe_file_exact(int fd, unsigned char *mem, unsigned long nrw, off_t off, int rw_type) { - struct xfile *f = &x->f; + struct xfile *f; long r; + check_null_command("rw_gbe_file_exact"); + + f = &x->f; + if (io_args(fd, mem, nrw, off, rw_type) == -1) return -1; @@ -1959,6 +2096,26 @@ err_rw_gbe_file_exact: return -1; } +void +check_null_command(const char *c) +{ + char msg[] = "undefined function name"; + char *func_name = msg; + + if (c != NULL) { + + if (*c != '\0') { + + func_name = (char *)c; + } + } + + if (x == NULL) { + + err(ECANCELED, "%s: x ptr is null", func_name); + } +} + /* * Safe I/O functions wrapping around * read(), write() and providing a portable @@ -1995,23 +2152,31 @@ rw_file_exact(int fd, unsigned char *mem, unsigned long nrw, int loop_eintr, unsigned long max_retries, int off_reset) { - long rv = 0; - long rc = 0; - unsigned long retries_on_zero = 0; - off_t off_cur; + long rval; + long rc; + unsigned long nrw_cur; + + off_t off_cur; void *mem_cur; + unsigned long retries_on_zero; + + rval = 0; + + rc = 0; + retries_on_zero = 0; + if (io_args(fd, mem, nrw, off, rw_type) == -1) return -1; while (1) { /* Prevent theoretical overflow */ - if (rv >= 0 && (unsigned long)rv > (nrw - rc)) + if (rval >= 0 && (unsigned long)rval > (nrw - rc)) goto err_rw_file_exact; - rc += rv; + rc += rval; if ((unsigned long)rc >= nrw) break; @@ -2021,14 +2186,14 @@ rw_file_exact(int fd, unsigned char *mem, unsigned long nrw, goto err_rw_file_exact; off_cur = off + (off_t)rc; - rv = prw(fd, mem_cur, nrw_cur, off_cur, + rval = prw(fd, mem_cur, nrw_cur, off_cur, rw_type, loop_eagain, loop_eintr, off_reset); - if (rv < 0) + if (rval < 0) return -1; - if (rv == 0) { + if (rval == 0) { if (retries_on_zero++ < max_retries) continue; goto err_rw_file_exact; @@ -2095,6 +2260,12 @@ prw(int fd, void *mem, unsigned long nrw, int loop_eagain, int loop_eintr, int off_reset) { +#ifndef MAX_EAGAIN_RETRIES + unsigned long retries = 100000; +#else + unsigned long retries = MAX_EAGAIN_RETRIES; +#endif + long r; int positional_rw; struct stat st; @@ -2106,8 +2277,10 @@ prw(int fd, void *mem, unsigned long nrw, off_t off_last; #endif - if (io_args(fd, mem, nrw, off, rw_type) == -1) + if (io_args(fd, mem, nrw, off, rw_type) + == -1) { return -1; + } r = -1; @@ -2220,8 +2393,9 @@ real_pread_pwrite: } } while (r == -1 && - (errno == try_err(loop_eintr, EINTR) - || errno == try_err(loop_eagain, EAGAIN))); + (errno == try_err(loop_eintr, EINTR) || + errno == try_err(loop_eagain, EAGAIN)) && + retries++ < MAX_EAGAIN_RETRIES); } saved_errno = errno; @@ -2318,7 +2492,9 @@ rw_over_nrw(long r, unsigned long nrw) if (r == -1) return r; - if ((unsigned long)r > X_LONG_MAX) { + if ((unsigned long) + r > X_LONG_MAX) { + /* * Theoretical buggy libc * check. Extremely academic. @@ -2361,7 +2537,9 @@ off_t lseek_loop(int fd, off_t off, int whence, int loop_eagain, int loop_eintr) { - off_t old = -1; + off_t old; + + old = -1; do { old = lseek(fd, off, whence); @@ -2394,7 +2572,9 @@ try_err(int loop_err, int errval) void usage(void) { - const char *util = getnvmprogname(); + const char *util; + + util = getnvmprogname(); fprintf(stderr, "Modify Intel GbE NVM images e.g. set MAC\n" @@ -2424,7 +2604,8 @@ err(int nvm_errval, const char *msg, ...) (void)exit_cleanup(); - fprintf(stderr, "%s: ", getnvmprogname()); + if (x != NULL) + fprintf(stderr, "%s: ", getnvmprogname()); va_start(args, msg); vfprintf(stderr, msg, args); @@ -2440,8 +2621,11 @@ exit_cleanup(void) { struct xfile *f; - int close_err = 0; - int saved_errno = errno; + int close_err; + int saved_errno; + + close_err = 0; + saved_errno = errno; if (x != NULL) { f = &x->f; @@ -2478,16 +2662,23 @@ const char * getnvmprogname(void) { const char *p; + static char fallback[] = "nvmutil"; - if (x->argv0 == NULL || *x->argv0 == '\0') - return ""; + char *rval = fallback; - p = x_c_strrchr(x->argv0, '/'); + if (x != NULL) { + if (x->argv0 == NULL || *x->argv0 == '\0') + return ""; + + rval = x->argv0; + } + + p = x_c_strrchr(rval, '/'); if (p) return p + 1; else - return x->argv0; + return rval; } /* @@ -2578,7 +2769,7 @@ new_tmpfile(int *fd, int local, const char *path) /* * appended to filename for tmp: */ - tmpdir_len = sizeof(default_tmpname); + tmpdir_len = xstrxlen(default_tmpname, maxlen); } else { base = x_c_tmpdir(); @@ -2630,7 +2821,7 @@ new_tmpfile(int *fd, int local, const char *path) if (fd_tmp == -1) goto err_new_tmpfile; - if (x_i_fchmod(fd_tmp, 0600) == -1) + if (fchmod(fd_tmp, 0600) == -1) goto err_new_tmpfile; flags = fcntl(fd_tmp, F_GETFL); @@ -2716,7 +2907,7 @@ x_i_mkstemp(char *template) for (j = 0; j < 6; j++) { r = rlong(); - p[j] = ch[r % (sizeof(ch) - 1)]; + p[j] = ch[(unsigned long)(r >> 1) % (sizeof(ch) - 1)]; } fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600); @@ -2760,7 +2951,7 @@ x_c_strrchr(const char *s, int c) int x_i_rename(const char *src, const char *dst) { - int sfd, dfd; + int sfd, dirfd; ssize_t r; char buf[8192]; @@ -2768,31 +2959,31 @@ x_i_rename(const char *src, const char *dst) if (sfd < 0) return -1; - dfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (dfd < 0) { + dirfd = open(dst, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (dirfd < 0) { x_i_close(sfd); return -1; } while ((r = read(sfd, buf, sizeof(buf))) > 0) { - ssize_t w = write(dfd, buf, r); + ssize_t w = write(dirfd, buf, r); if (w != r) { x_i_close(sfd); - x_i_close(dfd); + x_i_close(dirfd); return -1; } } if (r < 0) { x_i_close(sfd); - x_i_close(dfd); + x_i_close(dirfd); return -1; } - x_i_fsync(dfd); + x_i_fsync(dirfd); x_i_close(sfd); - x_i_close(dfd); + x_i_close(dirfd); if (unlink(src) < 0) return -1; @@ -2808,9 +2999,13 @@ x_c_tmpdir(void) struct stat st; t = getenv("TMPDIR"); + t = getenv("TMPDIR"); if (t && *t) { - if (stat(t, &st) == 0 && S_ISDIR(st.st_mode)) + if (stat(t, &st) == 0 && S_ISDIR(st.st_mode)) { + if ((st.st_mode & S_IWOTH) && !(st.st_mode & S_ISVTX)) + return NULL; return t; + } } if (stat("/tmp", &st) == 0 && S_ISDIR(st.st_mode)) @@ -2826,11 +3021,15 @@ int x_i_close(int fd) { int r; + int saved_errno = errno; do { r = close(fd); } while (r == -1 && errno == EINTR); + if (r > -1) + errno = saved_errno; + return r; } @@ -2859,80 +3058,6 @@ x_i_memcmp(const void *a, const void *b, unsigned long n) return 0; } -/* - * emulate fchmod() using file descriptor - * paths, for old unix portability. should - * work on e.g. BSD/MacOS (/dev/fd/N), - * Linux (/proc/self/fd/N) and others - */ -int -x_i_fchmod(int fd, mode_t mode) -{ - if (x_try_fdpath("/dev/fd/", fd, mode) == 0) - return 0; - - if (x_try_fdpath("/proc/self/fd/", fd, mode) == 0) - return 0; - - errno = ENOSYS; - return -1; -} - -int -x_try_fdpath(const char *prefix, int fd, mode_t mode) -{ - char path[PATH_LEN]; - - unsigned long i = 0; - unsigned long j; - - struct stat st; - - while (prefix[i]) { - if (i >= PATH_LEN - 1) - return -1; - path[i] = prefix[i]; - i++; - } - - j = x_conv_fd(path + i, (unsigned long)fd); - - if (i + j >= PATH_LEN) - return -1; - - i += j; - path[i] = '\0'; - - if (stat(path, &st) < 0) - return -1; - - return chmod(path, mode); -} - -unsigned long -x_conv_fd(char *buf, unsigned long n) -{ - char tmp[256]; - - unsigned long i = 0; - unsigned long j = 0; - - if (n == 0) { - buf[0] = '0'; - return 1; - } - - while (n > 0) { - tmp[i++] = (char)('0' + (n % 10)); - n /= 10; - } - - while (i > 0) - buf[j++] = tmp[--i]; - - return j; -} - int x_i_fsync(int fd) { diff --git a/util/nvmutil/nvmutil.h b/util/nvmutil/nvmutil.h index ce38772c..4d8c3ab2 100644 --- a/util/nvmutil/nvmutil.h +++ b/util/nvmutil/nvmutil.h @@ -9,6 +9,11 @@ check_cmd(cmd_helper_cat); */ +/* + * system prototypes + */ +int fchmod(int fd, mode_t mode); + #ifndef NVMUTIL_H #define NVMUTIL_H @@ -23,6 +28,14 @@ #define OFF_RESET 1 #endif +#ifndef S_ISVTX +#define S_ISVTX 01000 +#endif + +#if defined(S_IFMT) && ((S_ISVTX & S_IFMT) != 0) +#error "Unexpected bit layout" +#endif + #ifndef MAX_ZERO_RW_RETRY #define MAX_ZERO_RW_RETRY 5 #endif @@ -31,6 +44,10 @@ #define HAVE_REAL_PREAD_PWRITE 0 #endif +#ifndef MAX_EAGAIN_RETRIES +#define MAX_EAGAIN_RETRIES 100000 +#endif + #ifndef LOOP_EAGAIN #define LOOP_EAGAIN 1 #endif @@ -215,14 +232,6 @@ #define SKIP_CHECKSUM_WRITE 0 #define CHECKSUM_WRITE 1 -/* - * portable timeval - */ -struct x_st_timeval { - long tv_sec; - long tv_usec; -}; - struct commands { unsigned long chk; char *str; @@ -357,8 +366,6 @@ void set_mac_nib(unsigned long mac_str_pos, unsigned long mac_byte_pos, unsigned long mac_nib_pos); unsigned short hextonum(char ch_s); unsigned long rlong(void); -unsigned long entropy_jitter(void); -int x_i_gettimeofday(struct x_st_timeval *tv, void *tz); void write_mac_part(unsigned long partnum); /* @@ -430,6 +437,7 @@ off_t gbe_x_offset(unsigned long 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, off_t off, int rw_type); +void check_null_command(const char *c); long rw_file_exact(int fd, unsigned char *mem, unsigned long len, off_t off, int rw_type, int loop_eagain, int loop_eintr, unsigned long max_retries, int off_reset); @@ -474,11 +482,6 @@ void *x_v_memcpy(void *dst, const void *src, unsigned long n); int x_i_memcmp(const void *a, const void *b, unsigned long n); -int x_i_fchmod(int fd, mode_t mode); -int x_try_fdpath(const char *prefix, - int fd, mode_t mode); -unsigned long x_conv_fd(char *buf, - unsigned long n); int x_i_fsync(int fd); |
