summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLeah Rowe <leah@libreboot.org>2026-03-29 09:10:57 +0100
committerLeah Rowe <leah@libreboot.org>2026-03-29 09:18:36 +0100
commitc2a70b7de0e15dc80d5b56d438a6d4ed47647b44 (patch)
tree5c5281bb789f0ea9ab1d8766f5cea6e7182d431b
parent45edcf33f7d4b2f405c0f59fccc71b6ac15f5c65 (diff)
libreboot-utils: simplify random tmpdir namegen
generalise it in rand.c because this logic will be useful for other programs in the future. Signed-off-by: Leah Rowe <leah@libreboot.org>
-rw-r--r--util/libreboot-utils/include/common.h3
-rw-r--r--util/libreboot-utils/lib/file.c14
-rw-r--r--util/libreboot-utils/lib/mkhtemp.c52
-rw-r--r--util/libreboot-utils/lib/rand.c54
-rw-r--r--util/libreboot-utils/lib/string.c14
-rw-r--r--util/libreboot-utils/lottery.c2
6 files changed, 57 insertions, 82 deletions
diff --git a/util/libreboot-utils/include/common.h b/util/libreboot-utils/include/common.h
index b5b251d3..4b736808 100644
--- a/util/libreboot-utils/include/common.h
+++ b/util/libreboot-utils/include/common.h
@@ -399,7 +399,7 @@ void spew_hex(const void *data, size_t len);
void *rmalloc(size_t n);
void rset(void *buf, size_t n);
void *rmalloc(size_t n);
-char *mkrstr(size_t n);
+char *rchars(size_t n);
size_t rsize(size_t n);
/* Helper functions for command: dump
@@ -524,7 +524,6 @@ mkhtemp_tmpfile_linux(int dirfd,
int mkhtemp(int *fd, struct stat *st,
char *template, int dirfd, const char *fname,
struct stat *st_dir_initial, int type);
-int mkhtemp_fill_random(char *p, size_t xc);
int world_writeable_and_sticky(const char *s,
int sticky_allowed, int always_sticky);
int same_dir(const char *a, const char *b);
diff --git a/util/libreboot-utils/lib/file.c b/util/libreboot-utils/lib/file.c
index 3620f425..48eb37ed 100644
--- a/util/libreboot-utils/lib/file.c
+++ b/util/libreboot-utils/lib/file.c
@@ -538,20 +538,6 @@ try_err(int loop_err, int errval)
}
void
-free_and_set_null(char **buf)
-{
- if (buf == NULL)
- err_exit(EFAULT,
- "null ptr (to ptr for freeing) in free_and_set_null");
-
- if (*buf == NULL)
- return;
-
- free(*buf);
- *buf = NULL;
-}
-
-void
open_on_eintr(const char *path,
int *fd, int flags, mode_t mode,
struct stat *st)
diff --git a/util/libreboot-utils/lib/mkhtemp.c b/util/libreboot-utils/lib/mkhtemp.c
index 61479b25..72942868 100644
--- a/util/libreboot-utils/lib/mkhtemp.c
+++ b/util/libreboot-utils/lib/mkhtemp.c
@@ -627,6 +627,7 @@ mkhtemp_try_create(int dirfd,
struct stat st_open;
int saved_errno = errno;
int rval = -1;
+ char *rstr = NULL;
int file_created = 0;
int dir_created = 0;
@@ -636,8 +637,13 @@ mkhtemp_try_create(int dirfd,
if_err(*fd >= 0, EEXIST))
goto err;
- if (if_err_sys(mkhtemp_fill_random(p, xc) < 0) ||
- if_err_sys(fd_verify_dir_identity(dirfd, st_dir_initial) < 0))
+ /* TODO: potential infinite loop under entropy failure.
+ * if attacker has control of rand - TODO: maybe add timeout
+ */
+ memcpy(p, rstr = rchars(xc), xc);
+ free_and_set_null(&rstr);
+
+ if (if_err_sys(fd_verify_dir_identity(dirfd, st_dir_initial) < 0))
goto err;
if (type == MKHTEMP_FILE) {
@@ -765,6 +771,7 @@ mkhtemp_tmpfile_linux(int dirfd,
int tmpfd = -1;
size_t retries;
int linked = 0;
+ char *rstr = NULL;
if (fd == NULL || st == NULL ||
fname_copy == NULL || p == NULL ||
@@ -785,8 +792,8 @@ mkhtemp_tmpfile_linux(int dirfd,
for (retries = 0; retries < MKHTEMP_RETRY_MAX; retries++) {
- if (mkhtemp_fill_random(p, xc) < 0)
- goto err;
+ memcpy(p, rstr = rchars(xc), xc);
+ free_and_set_null(&rstr);
if (fd_verify_dir_identity(dirfd,
st_dir_initial) < 0)
@@ -832,43 +839,6 @@ err:
}
#endif
-/* TODO: potential infinite loop under entropy failure.
- * e.g. keeps returning low quality RNG, or atacker
- * has control (DoS attack potential).
- * possible solution: add a timeout (and abort if
- * the timeout is reached)
- */
-int
-mkhtemp_fill_random(char *p, size_t xc)
-{
- static const char ch[] =
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
-
- unsigned char scratch[64];
-
- size_t off = 0;
- size_t i;
-
- /* clamp rand to prevent modulo bias */
- size_t limit = 256 - (256 % (sizeof(ch) - 1));
-
- if (if_err(p == NULL, EFAULT))
- return -1;
-
-retry_rand:
- rset(scratch, sizeof(scratch));
-
- for (i = 0; i < sizeof(scratch) && off < xc; i++) {
- if (scratch[i] < limit)
- p[off++] = ch[scratch[i] % (sizeof(ch) - 1)];
- }
-
- if (off < xc)
- goto retry_rand;
-
- return 0;
-}
-
/* WARNING: **ONCE** per file.
*
* some of these checks will trip up
diff --git a/util/libreboot-utils/lib/rand.c b/util/libreboot-utils/lib/rand.c
index 2cb0f56d..2aa0de3a 100644
--- a/util/libreboot-utils/lib/rand.c
+++ b/util/libreboot-utils/lib/rand.c
@@ -72,6 +72,36 @@
* or your program dies.
*/
+/* random string generator, with
+ * rejection sampling. NOTE: only
+ * uses ASCII-safe characters, for
+ * printing on a unix terminal
+ *
+ * you still shouldn't use this for
+ * password generation; open diceware
+ * passphrases are better for that
+ *
+ * NOTE: the generated strings must
+ * ALSO be safe for file/directory names
+ * on unix-like os e.g. linux/bsd
+ */
+char *
+rchars(size_t n) /* emulates spkmodem-decode */
+{
+ static char ch[] =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+
+ char *s = NULL;
+ size_t i;
+
+ smalloc(&s, n + 1);
+ for (i = 0; i < n; i++)
+ s[i] = ch[rsize(sizeof(ch) - 1)];
+
+ *(s + n) = '\0';
+ return s;
+}
+
size_t
rsize(size_t n)
{
@@ -85,30 +115,6 @@ rsize(size_t n)
return rval % n;
}
-char *
-mkrstr(size_t n) /* emulates spkmodem-decode */
-{
- char *s;
- size_t i;
-
- if (n == 0)
- err_exit(EPERM, "rmalloc: zero-byte request");
-
- if (n >= SIZE_MAX - 1)
- err_exit(EOVERFLOW, "rmalloc: overflow");
-
- if (if_err((s = rmalloc(n + 1)) == NULL, EFAULT))
- err_exit(EFAULT, "mkrstr: null");
-
- for (i = 0; i < n; i++)
- while(*(s + i) == '\0')
- rset(s + i, 1);
-
- *(s + n) = '\0';
-
- return s;
-}
-
void *
rmalloc(size_t n)
{
diff --git a/util/libreboot-utils/lib/string.c b/util/libreboot-utils/lib/string.c
index 6a372dcf..c3cf4519 100644
--- a/util/libreboot-utils/lib/string.c
+++ b/util/libreboot-utils/lib/string.c
@@ -19,6 +19,20 @@
#include "../include/common.h"
+void
+free_and_set_null(char **buf)
+{
+ if (buf == NULL)
+ err_exit(EFAULT,
+ "null ptr (to ptr for freeing) in free_and_set_null");
+
+ if (*buf == NULL)
+ return;
+
+ free(*buf);
+ *buf = NULL;
+}
+
/* safe(ish) malloc.
use this and free_and_set_null()
diff --git a/util/libreboot-utils/lottery.c b/util/libreboot-utils/lottery.c
index 87637123..48565c87 100644
--- a/util/libreboot-utils/lottery.c
+++ b/util/libreboot-utils/lottery.c
@@ -33,7 +33,7 @@ main(int argc, char **argv)
if (argc < 2) /* no spew */
spew_hex(buf, BUFSIZ);
- free(buf);
+ free_and_set_null(&buf);
fprintf(stderr, "\n%s\n", same ? "You win!" : "You lose!");
return same ^ 1;