diff options
| author | Leah Rowe <leah@libreboot.org> | 2026-03-19 19:55:27 +0000 |
|---|---|---|
| committer | Leah Rowe <leah@libreboot.org> | 2026-03-19 20:01:57 +0000 |
| commit | 3a0460607dbb66094a26231c3fdb23b27305294a (patch) | |
| tree | a3efd6d977d7b397455464ba3a187b35b0dcce8d /util/nvmutil/lib/num.c | |
| parent | 2c211d385eb3efdd184895cefb4e242593f8107e (diff) | |
util/nvmutil: better getrandom safety
err if buf NULL, len -1
also getrandom may return fewer bytes, so
loop that too.
why can't linux be like bsd? bsd is:
arc4random_buf(buf, len);
no checks needed. it never errs.
Signed-off-by: Leah Rowe <leah@libreboot.org>
Diffstat (limited to 'util/nvmutil/lib/num.c')
| -rw-r--r-- | util/nvmutil/lib/num.c | 52 |
1 files changed, 28 insertions, 24 deletions
diff --git a/util/nvmutil/lib/num.c b/util/nvmutil/lib/num.c index 99503e8c..bbb5a83e 100644 --- a/util/nvmutil/lib/num.c +++ b/util/nvmutil/lib/num.c @@ -227,40 +227,44 @@ rlong_next: #if defined(HAVE_GETRANDOM) || \ defined(HAVE_GETRANDOM_SYSCALL) int -fallback_rand_getrandom(void *buf, size_t len) +fallback_rand_getrandom(void *buf, unsigned long len) { - ssize_t rval = -1; + unsigned long off = 0; + long rval = -1; - /* keep strict compiler - * happy if unused - */ - (void)rval; - (void)buf; - (void)len; + if (!len) + return -1; -#if defined(HAVE_GETRANDOM) - do { - rval = getrandom(buf, len, 0); - } while (rval < 0 && errno == EINTR); + if (buf == NULL) + return -1; -#elif defined(HAVE_GETRANDOM_SYSCALL) - do { - rval = syscall(SYS_getrandom, buf, len, 0); - } while (rval < 0 && errno == EINTR); +#if defined(HAVE_GETRANDOM) || \ + defined(HAVE_GETRANDOM_SYSCALL) -#else - return -1; + while (off < len) { + +#if defined(HAVE_GETRANDOM) + rval = (long)getrandom((char *)buf + off, len - off, 0); +#elif defined(HAVE_GETRANDOM_SYSCALL) + rval = (long)syscall(SYS_getrandom, + (char *)buf + off, len - off, 0); #endif -#if defined(HAVE_GETRANDOM) || \ - defined(HAVE_GETRANDOM_SYSCALL) + if (rval < 0) { + if (errno == EINTR) + continue; + + return -1; /* unsupported by kernel */ + } - if (rval == (ssize_t)len) { - return 0; + off += (unsigned long)rval; } - if (rval < 0 && errno == ENOSYS) - return -1; /* not supported by kernel */ + return 0; + +#else + (void)buf; + (void)len; return -1; #endif |
