mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-03-25 13:29:03 +02:00
Compare commits
28 Commits
fbe2986a6e
...
c8e6a6870f
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c8e6a6870f | ||
|
|
2a2b37127b | ||
|
|
19f888d52d | ||
|
|
a9a4cfc614 | ||
|
|
5cf2905379 | ||
|
|
dca488ee50 | ||
|
|
130b25e676 | ||
|
|
dfbdffc6a6 | ||
|
|
5287a80a7e | ||
|
|
e64b9b3e15 | ||
|
|
6b158a8610 | ||
|
|
7302714e48 | ||
|
|
d3a0cce466 | ||
|
|
d894240574 | ||
|
|
8ca953ec79 | ||
|
|
c2c483dcbe | ||
|
|
6315bf0025 | ||
|
|
995f25e199 | ||
|
|
969e98c78d | ||
|
|
2b294eda37 | ||
|
|
d67e0809ca | ||
|
|
2d129c257c | ||
|
|
087c7a6ad2 | ||
|
|
e2f55af07f | ||
|
|
b95aacb8c6 | ||
|
|
7d1aeea97f | ||
|
|
b57e61a3fa | ||
|
|
9714a0d448 |
@@ -22,7 +22,7 @@
|
||||
* Make most of nvmutil a *library* for re-use
|
||||
*
|
||||
* TODO: gettimeofday not posible - use portable functions.
|
||||
* TODO: uint32_t fallback: modify the program instead
|
||||
* TODO: ux fallback: modify the program instead
|
||||
* to run on 16-bit systems: smaller buffers, and do
|
||||
* operations byte-based instead of word-based.
|
||||
*
|
||||
@@ -135,11 +135,12 @@ CFLAGS += -fstack-protector-strong
|
||||
CFLAGS += -fno-common
|
||||
CFLAGS += -D_FORTIFY_SOURCE=2
|
||||
CFLAGS += -fPIE
|
||||
*/
|
||||
|
||||
#ifndef _XOPEN_SOURCE
|
||||
#define _XOPEN_SOURCE 500
|
||||
#endif
|
||||
also consider:
|
||||
-fstack-clash-protection
|
||||
-Wl,-z,relro
|
||||
-Wl,-z,now
|
||||
*/
|
||||
|
||||
#ifndef _FILE_OFFSET_BITS
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
@@ -156,31 +157,23 @@ CFLAGS += -fPIE
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#if defined(__has_include)
|
||||
#if __has_include(<stdint.h>)
|
||||
#include <stdint.h>
|
||||
#else
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#endif
|
||||
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
|
||||
#include <stdint.h>
|
||||
#else
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned int uint32_t;
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
|
||||
/* type asserts */
|
||||
typedef char static_assert_char_is_8_bits[(CHAR_BIT == 8) ? 1 : -1];
|
||||
typedef char static_assert_uint8_is_1[(sizeof(uint8_t) == 1) ? 1 : -1];
|
||||
typedef char static_assert_uint16_is_2[(sizeof(uint16_t) == 2) ? 1 : -1];
|
||||
typedef char static_assert_uint32_is_4[(sizeof(uint32_t) == 4) ? 1 : -1];
|
||||
typedef char static_assert_char_is_1[(sizeof(char) == 1) ? 1 : -1];
|
||||
typedef char static_assert_uint8_is_1[(sizeof(u8) == 1) ? 1 : -1];
|
||||
typedef char static_assert_uint16_is_2[(sizeof(ushort) >= 2) ? 1 : -1];
|
||||
typedef char static_assert_short_is_2[(sizeof(short) >= 2) ? 1 : -1];
|
||||
typedef char static_assert_uint32_is_4[(sizeof(uint) >= 4) ? 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
|
||||
@@ -225,8 +218,8 @@ typedef char static_assert_off_t_is_32[(sizeof(off_t) >= 4) ? 1 : -1];
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
|
||||
#ifndef O_NONBLOCK
|
||||
#define O_NONBLOCK 0
|
||||
#ifndef O_NOFOLLOW
|
||||
#define O_NOFOLLOW 0
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -234,8 +227,6 @@ typedef char static_assert_off_t_is_32[(sizeof(off_t) >= 4) ? 1 : -1];
|
||||
*/
|
||||
static void sanitize_command_list(void);
|
||||
static void sanitize_command_index(size_t c);
|
||||
static void check_enum_bin(size_t a, const char *a_name,
|
||||
size_t b, const char *b_name);
|
||||
|
||||
/*
|
||||
* Argument handling (user input)
|
||||
@@ -254,6 +245,7 @@ static int xstrxcmp(const char *a, const char *b, size_t maxlen);
|
||||
*/
|
||||
static void open_dev_urandom(void);
|
||||
static void open_gbe_file(void);
|
||||
static void lock_gbe_file(void);
|
||||
static void xopen(int *fd, const char *path, int flags, struct stat *st);
|
||||
|
||||
/*
|
||||
@@ -272,7 +264,7 @@ static int good_checksum(size_t partnum);
|
||||
*/
|
||||
static void run_cmd(size_t c);
|
||||
static void check_command_num(size_t c);
|
||||
static uint8_t valid_command(size_t c);
|
||||
static u8 valid_command(size_t c);
|
||||
|
||||
/*
|
||||
* Helper functions for command: setmac
|
||||
@@ -283,9 +275,9 @@ static size_t xstrxlen(const char *scmp, size_t maxlen);
|
||||
static void set_mac_byte(size_t mac_byte_pos);
|
||||
static void set_mac_nib(size_t mac_str_pos,
|
||||
size_t mac_byte_pos, size_t mac_nib_pos);
|
||||
static uint16_t hextonum(char ch_s);
|
||||
static uint16_t rhex(void);
|
||||
static uint16_t fallback_rand(void);
|
||||
static ushort hextonum(char ch_s);
|
||||
static ushort rhex(void);
|
||||
static ushort fallback_rand(void);
|
||||
static unsigned long entropy_jitter(void);
|
||||
static void write_mac_part(size_t partnum);
|
||||
|
||||
@@ -301,7 +293,7 @@ static void hexdump(size_t partnum);
|
||||
* cat, cat16 and cat128
|
||||
*/
|
||||
static void cmd_helper_cat(void);
|
||||
static void gbe_cat_buf(uint8_t *b);
|
||||
static void gbe_cat_buf(u8 *b);
|
||||
|
||||
/*
|
||||
* After command processing, write
|
||||
@@ -313,14 +305,14 @@ static void gbe_cat_buf(uint8_t *b);
|
||||
static void write_gbe_file(void);
|
||||
static void override_part_modified(void);
|
||||
static void set_checksum(size_t part);
|
||||
static uint16_t calculated_checksum(size_t p);
|
||||
static ushort calculated_checksum(size_t p);
|
||||
|
||||
/*
|
||||
* Helper functions for accessing
|
||||
* the NVM area during operation.
|
||||
*/
|
||||
static uint16_t nvm_word(size_t pos16, size_t part);
|
||||
static void set_nvm_word(size_t pos16, size_t part, uint16_t val16);
|
||||
static ushort nvm_word(size_t pos16, size_t part);
|
||||
static void set_nvm_word(size_t pos16, size_t part, ushort val16);
|
||||
static void set_part_modified(size_t p);
|
||||
static void check_nvm_bound(size_t pos16, size_t part);
|
||||
static void check_bin(size_t a, const char *a_name);
|
||||
@@ -331,19 +323,21 @@ static void check_bin(size_t a, const char *a_name);
|
||||
*/
|
||||
static void rw_gbe_file_part(size_t p, int rw_type,
|
||||
const char *rw_type_str);
|
||||
static uint8_t *gbe_mem_offset(size_t part, const char *f_op);
|
||||
static u8 *gbe_mem_offset(size_t part, const char *f_op);
|
||||
static off_t gbe_file_offset(size_t part, const char *f_op);
|
||||
static off_t gbe_x_offset(size_t part, const char *f_op,
|
||||
const char *d_type, off_t nsize, off_t ncmp);
|
||||
static ssize_t rw_file_exact(int fd, uint8_t *mem, size_t len,
|
||||
static ssize_t rw_file_exact(int fd, u8 *mem, size_t len,
|
||||
off_t off, int rw_type);
|
||||
static ssize_t rw_file_once(int fd, uint8_t *mem, size_t len,
|
||||
static ssize_t rw_file_once(int fd, u8 *mem, size_t len,
|
||||
off_t off, int rw_type, size_t rc);
|
||||
static ssize_t do_rw(int fd,
|
||||
uint8_t *mem, size_t len, off_t off, int rw_type);
|
||||
u8 *mem, size_t len, off_t off, int rw_type);
|
||||
static ssize_t prw(int fd, void *mem, size_t nrw,
|
||||
off_t off, int rw_type);
|
||||
static off_t lseek_eintr(int fd, off_t off, int whence);
|
||||
static int io_args(int fd, void *mem, size_t nrw,
|
||||
off_t off, int rw_type);
|
||||
|
||||
/*
|
||||
* Error handling and cleanup
|
||||
@@ -351,7 +345,7 @@ static off_t lseek_eintr(int fd, off_t off, int whence);
|
||||
static void err(int nvm_errval, const char *msg, ...);
|
||||
static void close_files(void);
|
||||
static const char *getnvmprogname(void);
|
||||
static void usage(uint8_t usage_exit);
|
||||
static void usage(u8 usage_exit);
|
||||
|
||||
/*
|
||||
* Sizes in bytes:
|
||||
@@ -381,6 +375,9 @@ static void usage(uint8_t usage_exit);
|
||||
#define NVM_WORDS (NVM_SIZE >> 1)
|
||||
#define NVM_CHECKSUM_WORD (NVM_WORDS - 1)
|
||||
|
||||
#define NUM_RANDOM_BYTES 12
|
||||
static u8 rnum[NUM_RANDOM_BYTES];
|
||||
|
||||
/*
|
||||
* Portable macro based on BSD nitems.
|
||||
* Used to count the number of commands (see below).
|
||||
@@ -399,17 +396,17 @@ static const char *rname = NULL;
|
||||
*
|
||||
* The code will handle this properly.
|
||||
*/
|
||||
static uint8_t buf[GBE_FILE_SIZE];
|
||||
static uint8_t pad[GBE_PART_SIZE]; /* the file that wouldn't die */
|
||||
static u8 buf[GBE_FILE_SIZE];
|
||||
static u8 pad[GBE_PART_SIZE]; /* the file that wouldn't die */
|
||||
|
||||
static uint16_t mac_buf[3];
|
||||
static ushort mac_buf[3];
|
||||
static off_t gbe_file_size;
|
||||
|
||||
static int urandom_fd = -1;
|
||||
static int gbe_fd = -1;
|
||||
static size_t part;
|
||||
static uint8_t part_modified[2];
|
||||
static uint8_t part_valid[2];
|
||||
static u8 part_modified[2];
|
||||
static u8 part_valid[2];
|
||||
|
||||
static const char rmac[] = "xx:xx:xx:xx:xx:xx";
|
||||
static const char *mac_str;
|
||||
@@ -486,11 +483,11 @@ struct commands {
|
||||
const char *str;
|
||||
void (*run)(void);
|
||||
int argc;
|
||||
uint8_t invert;
|
||||
uint8_t set_modified;
|
||||
uint8_t arg_part;
|
||||
uint8_t chksum_read;
|
||||
uint8_t chksum_write;
|
||||
u8 invert;
|
||||
u8 set_modified;
|
||||
u8 arg_part;
|
||||
u8 chksum_read;
|
||||
u8 chksum_write;
|
||||
size_t rw_size; /* within the 4KB GbE part */
|
||||
int flags; /* e.g. O_RDWR or O_RDONLY */
|
||||
};
|
||||
@@ -558,12 +555,40 @@ static const struct commands command[] = {
|
||||
*/
|
||||
static size_t cmd_index = CMD_NULL;
|
||||
|
||||
/*
|
||||
* asserts (variables/defines sanity check)
|
||||
*/
|
||||
typedef char assert_argc3[(ARGC_3==3)?1:-1];
|
||||
typedef char assert_argc4[(ARGC_4==4)?1:-1];
|
||||
typedef char assert_read[(IO_READ==0)?1:-1];
|
||||
typedef char assert_write[(IO_WRITE==1)?1:-1];
|
||||
typedef char assert_pread[(IO_PREAD==2)?1:-1];
|
||||
typedef char assert_pwrite[(IO_PWRITE==3)?1:-1];
|
||||
typedef char assert_rand_byte[(NUM_RANDOM_BYTES>0)?1:-1];
|
||||
typedef char assert_rand_len[(NUM_RANDOM_BYTES<NVM_SIZE)?1:-1];
|
||||
/* commands */
|
||||
typedef char assert_cmd_dump[(CMD_DUMP==0)?1:-1];
|
||||
typedef char assert_cmd_setmac[(CMD_SETMAC==1)?1:-1];
|
||||
typedef char assert_cmd_swap[(CMD_SWAP==2)?1:-1];
|
||||
typedef char assert_cmd_copy[(CMD_COPY==3)?1:-1];
|
||||
typedef char assert_cmd_cat[(CMD_CAT==4)?1:-1];
|
||||
typedef char assert_cmd_cat16[(CMD_CAT16==5)?1:-1];
|
||||
typedef char assert_cmd_cat128[(CMD_CAT128==6)?1:-1];
|
||||
/* mod_type */
|
||||
typedef char assert_mod_off[(SET_MOD_OFF==0)?1:-1];
|
||||
typedef char assert_mod_0[(SET_MOD_0==1)?1:-1];
|
||||
typedef char assert_mod_1[(SET_MOD_1==2)?1:-1];
|
||||
typedef char assert_mod_n[(SET_MOD_N==3)?1:-1];
|
||||
typedef char assert_mod_both[(SET_MOD_BOTH==4)?1:-1];
|
||||
/* bool */
|
||||
typedef char bool_arg_nopart[(ARG_NOPART==0)?1:-1];
|
||||
typedef char bool_arg_part[(ARG_PART==1)?1:-1];
|
||||
typedef char bool_skip_checksum_read[(SKIP_CHECKSUM_READ==0)?1:-1];
|
||||
typedef char bool_checksum_read[(CHECKSUM_READ==1)?1:-1];
|
||||
typedef char bool_skip_checksum_write[(SKIP_CHECKSUM_WRITE==0)?1:-1];
|
||||
typedef char bool_checksum_write[(CHECKSUM_WRITE==1)?1:-1];
|
||||
typedef char bool_no_invert[(NO_INVERT==0)?1:-1];
|
||||
typedef char bool_part_invert[(PART_INVERT==1)?1:-1];
|
||||
|
||||
static int use_prng = 0;
|
||||
|
||||
@@ -621,6 +646,7 @@ main(int argc, char *argv[])
|
||||
open_dev_urandom();
|
||||
|
||||
open_gbe_file();
|
||||
lock_gbe_file();
|
||||
|
||||
#ifdef NVMUTIL_PLEDGE
|
||||
if (pledge("stdio", NULL) == -1)
|
||||
@@ -657,10 +683,13 @@ sanitize_command_list(void)
|
||||
sanitize_command_index(c);
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: specific config checks per command
|
||||
*/
|
||||
static void
|
||||
sanitize_command_index(size_t c)
|
||||
{
|
||||
uint8_t mod_type;
|
||||
u8 mod_type;
|
||||
size_t gbe_rw_size;
|
||||
|
||||
check_command_num(c);
|
||||
@@ -682,15 +711,6 @@ sanitize_command_index(size_t c)
|
||||
(unsigned long)c, command[c].str);
|
||||
}
|
||||
|
||||
if (!((CMD_SETMAC > CMD_DUMP) && (CMD_SWAP > CMD_SETMAC) &&
|
||||
(CMD_COPY > CMD_SWAP) && (CMD_CAT > CMD_COPY) &&
|
||||
(CMD_CAT16 > CMD_CAT) && (CMD_CAT128 > CMD_CAT16)))
|
||||
err(EINVAL, "Some command integers are the same");
|
||||
|
||||
if (!((SET_MOD_0 > SET_MOD_OFF) && (SET_MOD_1 > SET_MOD_0) &&
|
||||
(SET_MOD_N > SET_MOD_1) && (SET_MOD_BOTH > SET_MOD_N)))
|
||||
err(EINVAL, "Some modtype integers are the same");
|
||||
|
||||
mod_type = command[c].set_modified;
|
||||
switch (mod_type) {
|
||||
case SET_MOD_0:
|
||||
@@ -708,13 +728,6 @@ sanitize_command_index(size_t c)
|
||||
check_bin(command[c].chksum_read, "cmd.chksum_read");
|
||||
check_bin(command[c].chksum_write, "cmd.chksum_write");
|
||||
|
||||
check_enum_bin(ARG_NOPART, "ARG_NOPART", ARG_PART, "ARG_PART");
|
||||
check_enum_bin(SKIP_CHECKSUM_READ, "SKIP_CHECKSUM_READ",
|
||||
CHECKSUM_READ, "CHECKSUM_READ");
|
||||
check_enum_bin(SKIP_CHECKSUM_WRITE, "SKIP_CHECKSUM_WRITE",
|
||||
CHECKSUM_WRITE, "CHECKSUM_WRITE");
|
||||
check_enum_bin(NO_INVERT, "NO_INVERT", PART_INVERT, "PART_INVERT");
|
||||
|
||||
gbe_rw_size = command[c].rw_size;
|
||||
|
||||
switch (gbe_rw_size) {
|
||||
@@ -735,17 +748,6 @@ sanitize_command_index(size_t c)
|
||||
err(EINVAL, "invalid cmd.flags setting");
|
||||
}
|
||||
|
||||
static void
|
||||
check_enum_bin(size_t a, const char *a_name,
|
||||
size_t b, const char *b_name)
|
||||
{
|
||||
if (a)
|
||||
err(EINVAL, "%s is non-zero", a_name);
|
||||
|
||||
if (b != 1)
|
||||
err(EINVAL, "%s is a value other than 1", b_name);
|
||||
}
|
||||
|
||||
static void
|
||||
set_cmd(int argc, char *argv[])
|
||||
{
|
||||
@@ -768,7 +770,7 @@ set_cmd(int argc, char *argv[])
|
||||
static void
|
||||
set_cmd_args(int argc, char *argv[])
|
||||
{
|
||||
uint8_t arg_part;
|
||||
u8 arg_part;
|
||||
|
||||
if (!valid_command(cmd_index) || argc < 3)
|
||||
usage(1);
|
||||
@@ -858,7 +860,8 @@ open_gbe_file(void)
|
||||
{
|
||||
struct stat gbe_st;
|
||||
|
||||
xopen(&gbe_fd, fname, command[cmd_index].flags | O_BINARY, &gbe_st);
|
||||
xopen(&gbe_fd, fname,
|
||||
command[cmd_index].flags | O_BINARY | O_NOFOLLOW, &gbe_st);
|
||||
|
||||
gbe_file_size = gbe_st.st_size;
|
||||
|
||||
@@ -872,6 +875,24 @@ open_gbe_file(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
lock_gbe_file(void)
|
||||
{
|
||||
struct flock fl;
|
||||
|
||||
memset(&fl, 0, sizeof(fl));
|
||||
|
||||
if (command[cmd_index].flags == O_RDONLY)
|
||||
fl.l_type = F_RDLCK;
|
||||
else
|
||||
fl.l_type = F_WRLCK;
|
||||
|
||||
fl.l_whence = SEEK_SET;
|
||||
|
||||
if (fcntl(gbe_fd, F_SETLK, &fl) == -1)
|
||||
err(errno, "file is locked by another process");
|
||||
}
|
||||
|
||||
static void
|
||||
xopen(int *fd_ptr, const char *path, int flags, struct stat *st)
|
||||
{
|
||||
@@ -889,7 +910,7 @@ static void
|
||||
read_gbe_file(void)
|
||||
{
|
||||
size_t p;
|
||||
uint8_t do_read[2] = {1, 1};
|
||||
u8 do_read[2] = {1, 1};
|
||||
|
||||
/*
|
||||
* Commands specifying a partnum only
|
||||
@@ -909,10 +930,10 @@ read_checksums(void)
|
||||
{
|
||||
size_t p;
|
||||
size_t skip_part;
|
||||
uint8_t invert;
|
||||
uint8_t arg_part;
|
||||
uint8_t num_invalid;
|
||||
uint8_t max_invalid;
|
||||
u8 invert;
|
||||
u8 arg_part;
|
||||
u8 num_invalid;
|
||||
u8 max_invalid;
|
||||
|
||||
part_valid[0] = 0;
|
||||
part_valid[1] = 0;
|
||||
@@ -958,8 +979,8 @@ read_checksums(void)
|
||||
static int
|
||||
good_checksum(size_t partnum)
|
||||
{
|
||||
uint16_t expected_checksum = calculated_checksum(partnum);
|
||||
uint16_t current_checksum = nvm_word(NVM_CHECKSUM_WORD, partnum);
|
||||
ushort expected_checksum = calculated_checksum(partnum);
|
||||
ushort current_checksum = nvm_word(NVM_CHECKSUM_WORD, partnum);
|
||||
|
||||
if (current_checksum == expected_checksum)
|
||||
return 1;
|
||||
@@ -983,7 +1004,7 @@ check_command_num(size_t c)
|
||||
(unsigned long)c);
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
static u8
|
||||
valid_command(size_t c)
|
||||
{
|
||||
if (c >= N_COMMANDS)
|
||||
@@ -1077,7 +1098,7 @@ set_mac_nib(size_t mac_str_pos,
|
||||
size_t mac_byte_pos, size_t mac_nib_pos)
|
||||
{
|
||||
char mac_ch;
|
||||
uint16_t hex_num;
|
||||
ushort hex_num;
|
||||
|
||||
mac_ch = mac_str[mac_str_pos + mac_nib_pos];
|
||||
|
||||
@@ -1102,7 +1123,7 @@ set_mac_nib(size_t mac_str_pos,
|
||||
| ((mac_nib_pos ^ 1) << 2)); /* left or right nib? */
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
static ushort
|
||||
hextonum(char ch_s)
|
||||
{
|
||||
unsigned char ch = (unsigned char)ch_s;
|
||||
@@ -1121,11 +1142,10 @@ hextonum(char ch_s)
|
||||
return 16; /* invalid character */
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
static ushort
|
||||
rhex(void)
|
||||
{
|
||||
static size_t n = 0;
|
||||
static uint8_t rnum[12];
|
||||
|
||||
if (use_prng)
|
||||
return fallback_rand();
|
||||
@@ -1136,10 +1156,10 @@ rhex(void)
|
||||
err(errno, "Randomisation failed");
|
||||
}
|
||||
|
||||
return (uint16_t)(rnum[--n] & 0xf);
|
||||
return (ushort)(rnum[--n] & 0xf);
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
static ushort
|
||||
fallback_rand(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
@@ -1163,7 +1183,7 @@ fallback_rand(void)
|
||||
mix ^= (unsigned long)&tv;
|
||||
mix ^= (unsigned long)&counter;
|
||||
|
||||
return (uint16_t)(mix & 0xf);
|
||||
return (ushort)(mix & 0xf);
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
@@ -1171,6 +1191,7 @@ entropy_jitter(void)
|
||||
{
|
||||
struct timeval a, b;
|
||||
unsigned long mix = 0;
|
||||
long mix_diff;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
@@ -1178,7 +1199,15 @@ entropy_jitter(void)
|
||||
getpid();
|
||||
gettimeofday(&b, NULL);
|
||||
|
||||
mix ^= (unsigned long)(b.tv_usec - a.tv_usec);
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
@@ -1229,11 +1258,13 @@ static void
|
||||
print_mac_from_nvm(size_t partnum)
|
||||
{
|
||||
size_t c;
|
||||
uint16_t val16;
|
||||
ushort val16;
|
||||
|
||||
for (c = 0; c < 3; c++) {
|
||||
val16 = nvm_word(c, partnum);
|
||||
printf("%02x:%02x", val16 & 0xff, val16 >> 8);
|
||||
printf("%02x:%02x",
|
||||
(unsigned int)(val16 & 0xff),
|
||||
(unsigned int)(val16 >> 8));
|
||||
if (c == 2)
|
||||
printf("\n");
|
||||
else
|
||||
@@ -1246,7 +1277,7 @@ hexdump(size_t partnum)
|
||||
{
|
||||
size_t c;
|
||||
size_t row;
|
||||
uint16_t val16;
|
||||
ushort val16;
|
||||
|
||||
for (row = 0; row < 8; row++) {
|
||||
printf("%08lx ", (unsigned long)((size_t)row << 4));
|
||||
@@ -1254,7 +1285,9 @@ hexdump(size_t partnum)
|
||||
val16 = nvm_word((row << 3) + c, partnum);
|
||||
if (c == 4)
|
||||
printf(" ");
|
||||
printf(" %02x %02x", val16 & 0xff, val16 >> 8);
|
||||
printf(" %02x %02x",
|
||||
(unsigned int)(val16 & 0xff),
|
||||
(unsigned int)(val16 >> 8));
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
@@ -1285,7 +1318,7 @@ cmd_helper_cat(void)
|
||||
}
|
||||
|
||||
static void
|
||||
gbe_cat_buf(uint8_t *b)
|
||||
gbe_cat_buf(u8 *b)
|
||||
{
|
||||
ssize_t rval;
|
||||
|
||||
@@ -1312,9 +1345,11 @@ gbe_cat_buf(uint8_t *b)
|
||||
static void
|
||||
write_gbe_file(void)
|
||||
{
|
||||
struct stat gbe_st;
|
||||
|
||||
size_t p;
|
||||
size_t partnum;
|
||||
uint8_t update_checksum;
|
||||
u8 update_checksum;
|
||||
|
||||
if (command[cmd_index].flags == O_RDONLY)
|
||||
return;
|
||||
@@ -1322,6 +1357,15 @@ write_gbe_file(void)
|
||||
update_checksum = command[cmd_index].chksum_write;
|
||||
|
||||
override_part_modified();
|
||||
|
||||
if (fstat(gbe_fd, &gbe_st) == -1)
|
||||
err(errno, "%s: re-check", fname);
|
||||
|
||||
if (gbe_st.st_size != gbe_file_size)
|
||||
err(errno, "%s: file size changed before write", fname);
|
||||
|
||||
if (!S_ISREG(gbe_st.st_mode))
|
||||
err(errno, "%s: file type changed before write", fname);
|
||||
|
||||
for (p = 0; p < 2; p++) {
|
||||
partnum = p ^ command[cmd_index].invert;
|
||||
@@ -1339,7 +1383,7 @@ write_gbe_file(void)
|
||||
static void
|
||||
override_part_modified(void)
|
||||
{
|
||||
uint8_t mod_type = command[cmd_index].set_modified;
|
||||
u8 mod_type = command[cmd_index].set_modified;
|
||||
|
||||
switch (mod_type) {
|
||||
case SET_MOD_0:
|
||||
@@ -1370,16 +1414,16 @@ set_checksum(size_t p)
|
||||
set_nvm_word(NVM_CHECKSUM_WORD, p, calculated_checksum(p));
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
static ushort
|
||||
calculated_checksum(size_t p)
|
||||
{
|
||||
size_t c;
|
||||
uint32_t val16 = 0;
|
||||
uint val16 = 0;
|
||||
|
||||
for (c = 0; c < NVM_CHECKSUM_WORD; c++)
|
||||
val16 += (uint32_t)nvm_word(c, p);
|
||||
val16 += (uint)nvm_word(c, p);
|
||||
|
||||
return (uint16_t)((NVM_CHECKSUM - val16) & 0xffff);
|
||||
return (ushort)((NVM_CHECKSUM - val16) & 0xffff);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1390,7 +1434,7 @@ calculated_checksum(size_t p)
|
||||
* file, but we assume otherwise and adapt accordingly.
|
||||
*/
|
||||
|
||||
static uint16_t
|
||||
static ushort
|
||||
nvm_word(size_t pos16, size_t p)
|
||||
{
|
||||
size_t pos;
|
||||
@@ -1398,20 +1442,20 @@ nvm_word(size_t pos16, size_t p)
|
||||
check_nvm_bound(pos16, p);
|
||||
pos = (pos16 << 1) + (p * GBE_PART_SIZE);
|
||||
|
||||
return (uint16_t)buf[pos] |
|
||||
((uint16_t)buf[pos + 1] << 8);
|
||||
return (ushort)buf[pos] |
|
||||
((ushort)buf[pos + 1] << 8);
|
||||
}
|
||||
|
||||
static void
|
||||
set_nvm_word(size_t pos16, size_t p, uint16_t val16)
|
||||
set_nvm_word(size_t pos16, size_t p, ushort val16)
|
||||
{
|
||||
size_t pos;
|
||||
|
||||
check_nvm_bound(pos16, p);
|
||||
pos = (pos16 << 1) + (p * GBE_PART_SIZE);
|
||||
|
||||
buf[pos] = (uint8_t)(val16 & 0xff);
|
||||
buf[pos + 1] = (uint8_t)(val16 >> 8);
|
||||
buf[pos] = (u8)(val16 & 0xff);
|
||||
buf[pos + 1] = (u8)(val16 >> 8);
|
||||
|
||||
set_part_modified(p);
|
||||
}
|
||||
@@ -1452,9 +1496,9 @@ rw_gbe_file_part(size_t p, int rw_type,
|
||||
const char *rw_type_str)
|
||||
{
|
||||
size_t gbe_rw_size = command[cmd_index].rw_size;
|
||||
uint8_t invert = command[cmd_index].invert;
|
||||
u8 invert = command[cmd_index].invert;
|
||||
|
||||
uint8_t *mem_offset;
|
||||
u8 *mem_offset;
|
||||
|
||||
if (rw_type < IO_PREAD || rw_type > IO_PWRITE)
|
||||
err(errno, "%s: %s: part %lu: invalid rw_type, %d",
|
||||
@@ -1481,13 +1525,13 @@ rw_gbe_file_part(size_t p, int rw_type,
|
||||
* but used to check Gbe bounds in memory,
|
||||
* and it is *also* used during file I/O.
|
||||
*/
|
||||
static uint8_t *
|
||||
static u8 *
|
||||
gbe_mem_offset(size_t p, const char *f_op)
|
||||
{
|
||||
off_t gbe_off = gbe_x_offset(p, f_op, "mem",
|
||||
GBE_PART_SIZE, GBE_FILE_SIZE);
|
||||
|
||||
return (uint8_t *)(buf + gbe_off);
|
||||
return (u8 *)(buf + gbe_off);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1530,7 +1574,7 @@ gbe_x_offset(size_t p, const char *f_op, const char *d_type,
|
||||
/*
|
||||
* Read or write the exact contents of a file,
|
||||
* along with a buffer, (if applicable) offset,
|
||||
* and number of bytes to be read. It unified
|
||||
* and number of bytes to be read. It unifies
|
||||
* the functionality of read(), pread(), write()
|
||||
* and pwrite(), with retry-on-EINTR and also
|
||||
* prevents infinite loop on zero-reads.
|
||||
@@ -1543,33 +1587,21 @@ gbe_x_offset(size_t p, const char *f_op, const char *d_type,
|
||||
* be used on sockets or pipes, because 0-byte
|
||||
* reads are treated like fatal errors. This
|
||||
* means that EOF is also considered fatal.
|
||||
*
|
||||
* WARNING: Do not use O_APPEND on open() when
|
||||
* using this function. If you do, POSIX allows
|
||||
* write() to ignore the current file offset and
|
||||
* write at EOF, which means that our use of
|
||||
* lseek in prw() does not guarantee writing at
|
||||
* a specified offset. So if using IO_PWRITE or
|
||||
* IO_PREAD, make sure not to pass a file descriptor
|
||||
* with the O_APPEND flag. Alternatively, modify
|
||||
* do_rw() to directly use pwrite() and pread()
|
||||
* instead of prw().
|
||||
*/
|
||||
static ssize_t
|
||||
rw_file_exact(int fd, uint8_t *mem, size_t len,
|
||||
rw_file_exact(int fd, u8 *mem, size_t nrw,
|
||||
off_t off, int rw_type)
|
||||
{
|
||||
ssize_t rv;
|
||||
size_t rc;
|
||||
|
||||
if (fd < 0 || !len || len > (size_t)SSIZE_MAX
|
||||
|| (unsigned int)rw_type > IO_PWRITE) {
|
||||
if (io_args(fd, mem, nrw, off, rw_type) == -1) {
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (rc = 0, rv = 0; rc < len; ) {
|
||||
if ((rv = rw_file_once(fd, mem, len, off, rw_type, rc)) <= 0)
|
||||
for (rc = 0, rv = 0; rc < nrw; ) {
|
||||
if ((rv = rw_file_once(fd, mem, nrw, off, rw_type, rc)) <= 0)
|
||||
return -1;
|
||||
|
||||
rc += (size_t)rv;
|
||||
@@ -1583,18 +1615,18 @@ rw_file_exact(int fd, uint8_t *mem, size_t len,
|
||||
* Use rw_file_exact for guaranteed length.
|
||||
*/
|
||||
static ssize_t
|
||||
rw_file_once(int fd, uint8_t *mem, size_t len,
|
||||
rw_file_once(int fd, u8 *mem, size_t nrw,
|
||||
off_t off, int rw_type, size_t rc)
|
||||
{
|
||||
ssize_t rv;
|
||||
size_t retries_on_zero = 0;
|
||||
size_t max_retries = 10;
|
||||
|
||||
read_again:
|
||||
if ((unsigned int)rw_type > IO_PWRITE)
|
||||
if (io_args(fd, mem, nrw, off, rw_type) == -1)
|
||||
goto err_rw_file_once;
|
||||
|
||||
rv = do_rw(fd, mem + rc, len - rc, off + rc, rw_type);
|
||||
read_again:
|
||||
rv = do_rw(fd, mem + rc, nrw - rc, off + rc, rw_type);
|
||||
|
||||
if (rv < 0 && errno == EINTR)
|
||||
goto read_again;
|
||||
@@ -1603,7 +1635,7 @@ read_again:
|
||||
return -1;
|
||||
|
||||
if ((size_t)rv > SSIZE_MAX /* theoretical buggy libc */
|
||||
|| (size_t)rv > (len - rc))/* don't overflow */
|
||||
|| (size_t)rv > (nrw - rc))/* don't overflow */
|
||||
goto err_rw_file_once;
|
||||
|
||||
if (rv != 0)
|
||||
@@ -1618,18 +1650,22 @@ err_rw_file_once:
|
||||
}
|
||||
|
||||
static ssize_t
|
||||
do_rw(int fd, uint8_t *mem,
|
||||
size_t len, off_t off, int rw_type)
|
||||
do_rw(int fd, u8 *mem,
|
||||
size_t nrw, off_t off, int rw_type)
|
||||
{
|
||||
if (io_args(fd, mem, nrw, off, rw_type) == -1)
|
||||
goto err_do_rw;
|
||||
|
||||
if (rw_type == IO_READ)
|
||||
return read(fd, mem, len);
|
||||
return read(fd, mem, nrw);
|
||||
|
||||
if (rw_type == IO_WRITE)
|
||||
return write(fd, mem, len);
|
||||
return write(fd, mem, nrw);
|
||||
|
||||
if (rw_type == IO_PREAD || rw_type == IO_PWRITE)
|
||||
return prw(fd, mem, len, off, rw_type);
|
||||
return prw(fd, mem, nrw, off, rw_type);
|
||||
|
||||
err_do_rw:
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
@@ -1651,16 +1687,32 @@ prw(int fd, void *mem, size_t nrw,
|
||||
ssize_t r;
|
||||
int saved_errno;
|
||||
int prw_type;
|
||||
int flags;
|
||||
|
||||
if (io_args(fd, mem, nrw, off, rw_type) == -1)
|
||||
goto err_prw;
|
||||
|
||||
prw_type = rw_type ^ IO_PREAD;
|
||||
|
||||
if ((unsigned int)prw_type > IO_WRITE) {
|
||||
errno = EIO;
|
||||
if ((unsigned int)prw_type > IO_WRITE)
|
||||
goto err_prw;
|
||||
|
||||
flags = fcntl(fd, F_GETFL);
|
||||
if (flags == -1)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* O_APPEND must not be used, because this
|
||||
* allows POSIX write() to ignore the
|
||||
* current write offset and write at EOF,
|
||||
* which would therefore break pread/pwrite
|
||||
*/
|
||||
if (flags & O_APPEND)
|
||||
goto err_prw;
|
||||
|
||||
if ((off_orig = lseek_eintr(fd, (off_t)0, SEEK_CUR)) == (off_t)-1)
|
||||
return -1;
|
||||
|
||||
if (lseek_eintr(fd, off, SEEK_SET) == (off_t)-1)
|
||||
return -1;
|
||||
|
||||
@@ -1672,11 +1724,50 @@ prw(int fd, void *mem, size_t nrw,
|
||||
if (lseek_eintr(fd, off_orig, SEEK_SET) == (off_t)-1) {
|
||||
if (r < 0)
|
||||
errno = saved_errno;
|
||||
|
||||
return -1;
|
||||
}
|
||||
errno = saved_errno;
|
||||
|
||||
return r;
|
||||
|
||||
err_prw:
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int
|
||||
io_args(int fd, void *mem, size_t nrw,
|
||||
off_t off, int rw_type)
|
||||
{
|
||||
if (mem == NULL)
|
||||
goto err_io_args;
|
||||
|
||||
if (mem != (void *)pad
|
||||
&& mem != (void *)rnum
|
||||
&& (mem < (void *)buf || mem >= (void *)(buf + GBE_FILE_SIZE)))
|
||||
goto err_io_args;
|
||||
|
||||
if (off < 0 || off >= gbe_file_size)
|
||||
goto err_io_args;
|
||||
|
||||
if (nrw > (size_t)(gbe_file_size - off))
|
||||
goto err_io_args;
|
||||
|
||||
if (nrw > GBE_PART_SIZE)
|
||||
goto err_io_args;
|
||||
|
||||
if (fd < 0
|
||||
|| !nrw /* prevent zero read request */
|
||||
|| nrw > (size_t)SSIZE_MAX /* prevent overflow */
|
||||
|| (unsigned int)rw_type > IO_PWRITE)
|
||||
goto err_io_args;
|
||||
|
||||
return 0;
|
||||
|
||||
err_io_args:
|
||||
errno = EIO;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static off_t
|
||||
@@ -1748,7 +1839,7 @@ getnvmprogname(void)
|
||||
}
|
||||
|
||||
static void
|
||||
usage(uint8_t usage_exit)
|
||||
usage(u8 usage_exit)
|
||||
{
|
||||
const char *util = getnvmprogname();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user