diff options
| -rw-r--r-- | util/nvmutil/nvmutil.c | 158 |
1 files changed, 100 insertions, 58 deletions
diff --git a/util/nvmutil/nvmutil.c b/util/nvmutil/nvmutil.c index 2182348a..b40a0910 100644 --- a/util/nvmutil/nvmutil.c +++ b/util/nvmutil/nvmutil.c @@ -373,8 +373,7 @@ 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); unsigned short hextonum(char ch_s); -unsigned short rhex(void); -unsigned short read_urandom(void); +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); @@ -472,7 +471,13 @@ const char *getnvmprogname(void); char *new_tmpfile(int *fd, int local, const char *path); int x_i_mkstemp(char *template); char *x_c_strrchr(const char *s, int c); +/* x_i_rename not suitable + * for atomic writes. kept + * commentted for use in a + * library in the future */ +/* int x_i_rename(const char *src, const char *dst); +*/ char *x_c_tmpdir(void); int x_i_close(int fd); void *x_v_memcpy(void *dst, @@ -709,11 +714,25 @@ ino_t tmp_ino; int tmp_fd = -1; char *tname = NULL; +/* + * Used for checking whether. + * a file is a file via stat(). + * + * Portable macro for compatibility + * with older unix e.g. v7 unix (has S_IFREG), + * 4.2bsd (has S_IFMT) or POSIX (has S_ISREG) + * + * Fallback works where S_IFREG == 0100000 + * (classic unix bitmask) + */ + #ifndef S_ISREG -#ifdef S_IFMT -#define S_ISREG(m) (((m) & (S_IFMT)) == (S_IFREG)) +#if defined(S_IFMT) && defined(S_IFREG) +#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) +#elif defined(S_IFREG) +#define S_ISREG(m) (((m) & S_IFREG) != 0) #else -#define S_ISREG(m) (((m) & (S_IFREG)) == (S_IFREG)) +#error "can't determine types with stat()" #endif #endif @@ -1358,30 +1377,25 @@ hextonum(char ch_s) return ch - 'a' + 10; if (ch == '?' || ch == 'x') - return rhex(); /* random character */ + return (unsigned short)rlong() & 0xf; return 16; /* invalid character */ } -unsigned short -rhex(void) +unsigned long +rlong(void) { struct x_st_timeval tv; - unsigned long mix; + static unsigned long mix = 0; static unsigned long counter = 0; - unsigned short r; - - /* Read /dev/urandom - * if possible */ - r = read_urandom(); - if (r < 16) - return r; - /* Fallback */ + static int fd = -1; + unsigned long rval = 0; + long nr = -1; x_i_gettimeofday(&tv, NULL); - mix = (unsigned long)tv.tv_sec + mix ^= (unsigned long)tv.tv_sec ^ (unsigned long)tv.tv_usec ^ (unsigned long)getpid() ^ (unsigned long)&mix @@ -1396,45 +1410,45 @@ rhex(void) mix ^= (unsigned long)&tv; mix ^= (unsigned long)&counter; - return (unsigned short)(mix & 0xf); -} - -unsigned short -read_urandom(void) -{ - static int fd = -1; - static long n = -1; - - static unsigned char r[256]; + /* + * 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 + */ - if (fd < 0) { + if (fd < 0) + fd = open("/dev/urandom", O_RDONLY | O_BINARY | O_NONBLOCK); - fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK); -#ifndef NVMUTIL_UNVEIL - if (fd < 0) /* older openbsd */ - fd = open("/dev/arandom", O_RDONLY | O_NONBLOCK); +#if !(defined(__OpenBSD__) && defined(OpenBSD)) || \ + (defined(__OpenBSD__) && defined(OpenBSD) && \ + OpenBSD < 604) + if (fd < 0) /* old openbsd */ + fd = open("/dev/arandom", O_RDONLY | O_BINARY | O_NONBLOCK); #endif - if (fd < 0) /* super old unix (could block) */ - fd = open("/dev/random", O_RDONLY | O_NONBLOCK); - - if (fd < 0) - return 16; - } - if (n < 0) { - - n = rw_file_exact(fd, r, 256, 0, IO_READ, - LOOP_EAGAIN, LOOP_EINTR, 2, OFF_ERR); + if (fd < 0) + fd = open("/dev/random", O_RDONLY | O_BINARY | O_NONBLOCK); - if (n == 0) - n = -1; - if (n < 0) - return 16; + nr = rw_file_exact(fd, (unsigned char *)&rval, + sizeof(unsigned long), 0, IO_READ, LOOP_EAGAIN, + LOOP_EINTR, MAX_ZERO_RW_RETRY, OFF_ERR); - --n; - } + if (nr == sizeof(unsigned long)) + return rval; - return r[n--] & 0xf; + return mix; } unsigned long @@ -1445,8 +1459,9 @@ entropy_jitter(void) long mix_diff; int i; + x_i_gettimeofday(&a, NULL); + for (i = 0; i < 8; i++) { - x_i_gettimeofday(&a, NULL); getpid(); x_i_gettimeofday(&b, NULL); @@ -1477,7 +1492,7 @@ x_i_gettimeofday(struct x_st_timeval *tv, void *tz) t = time(NULL); tv->tv_sec = t; - tv->tv_usec = (long)clock() % 1000000; + tv->tv_usec = (long)((unsigned long)clock() % 1000000UL); return 0; } @@ -1999,7 +2014,7 @@ gbe_mv(void) saved_errno = errno; - r = x_i_rename(tname, fname); + r = rename(tname, fname); if (r > -1) { /* @@ -2052,7 +2067,7 @@ gbe_mv(void) if (x_i_close(dest_fd) == -1) goto ret_gbe_mv; - if (x_i_rename(dest_tmp, fname) == -1) + if (rename(dest_tmp, fname) == -1) goto ret_gbe_mv; if (fsync_dir(fname) < 0) @@ -2105,7 +2120,7 @@ ret_gbe_mv: } /* - * Ensure x_i_rename() is durable by syncing the + * Ensure rename() is durable by syncing the * directory containing the target file. */ int @@ -2134,6 +2149,12 @@ fsync_dir(const char *path) goto err_fsync_dir; } + if (pathlen == 0) + { + errno = EINVAL; + goto err_fsync_dir; + } + dirbuf = malloc(pathlen + 1); if (dirbuf == NULL) goto err_fsync_dir; @@ -2149,7 +2170,14 @@ fsync_dir(const char *path) strcpy(dirbuf, "."); } - dfd = open(dirbuf, O_RDONLY); + dfd = open(dirbuf, O_RDONLY +#ifdef O_DIRECTORY + | O_DIRECTORY +#endif +#ifdef O_NOFOLLOW + | O_NOFOLLOW +#endif + ); if (dfd == -1) goto err_fsync_dir; @@ -3025,6 +3053,7 @@ x_i_mkstemp(char *template) char *p; char ch[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + unsigned long r = rlong(); len = xstrxlen(template, PATH_LEN); @@ -3037,7 +3066,7 @@ x_i_mkstemp(char *template) for (i = 0; i < 100; i++) { for (j = 0; j < 6; j++) - p[j] = ch[rhex() & 31]; + p[j] = ch[r % (sizeof(ch) - 1)]; fd = open(template, O_RDWR | O_CREAT | O_EXCL, 0600); @@ -3069,6 +3098,7 @@ x_c_strrchr(const char *s, int c) return (char *)p; } +/* int x_i_rename(const char *src, const char *dst) { @@ -3111,6 +3141,7 @@ x_i_rename(const char *src, const char *dst) return 0; } +*/ char * x_c_tmpdir(void) @@ -3173,6 +3204,12 @@ 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) { @@ -3195,13 +3232,18 @@ x_try_fdpath(const char *prefix, int fd, mode_t mode) unsigned long j; while (prefix[i]) { + if (i >= PATH_LEN - 1) + return -1; path[i] = prefix[i]; i++; } j = x_conv_fd(path + i, (unsigned long)fd); - i += j; + if (i + j >= PATH_LEN) + return -1; + + i += j; path[i] = '\0'; return chmod(path, mode); |
