summaryrefslogtreecommitdiff
path: root/util/libreboot-utils/lib/mkhtemp.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/libreboot-utils/lib/mkhtemp.c')
-rw-r--r--util/libreboot-utils/lib/mkhtemp.c85
1 files changed, 24 insertions, 61 deletions
diff --git a/util/libreboot-utils/lib/mkhtemp.c b/util/libreboot-utils/lib/mkhtemp.c
index 61479b25..2ef26d67 100644
--- a/util/libreboot-utils/lib/mkhtemp.c
+++ b/util/libreboot-utils/lib/mkhtemp.c
@@ -135,19 +135,12 @@ new_tmp_common(int *fd, char **path, int type,
if (slen(templatestr, maxlen, &templatestr_len) < 0)
goto err;
- /* sizeof adds an extra byte, useful
- * because we also want '.' or '/'
- */
+ /* may as well calculate in advance */
destlen = dirlen + 1 + templatestr_len;
- if (destlen > maxlen - 1) {
- errno = EOVERFLOW;
+ /* full path: */
+ if (scatn(3, (const char *[]) { tmpdir, "/", templatestr },
+ maxlen, &dest) < 0)
goto err;
- }
-
- memcpy(smalloc(&dest, destlen + 1), tmpdir, dirlen);
- *(dest + dirlen) = '/';
- memcpy(dest + dirlen + 1, templatestr, templatestr_len);
- *(dest + destlen) = '\0';
fname = dest + dirlen + 1;
@@ -533,7 +526,7 @@ mkhtemp(int *fd,
struct stat *st_dir_initial,
int type)
{
- size_t len = 0;
+ size_t template_len = 0;
size_t xc = 0;
size_t fname_len = 0;
@@ -559,28 +552,28 @@ mkhtemp(int *fd,
if_err(*fd >= 0, EEXIST) ||
if_err(dirfd < 0, EBADF)
||
- if_err_sys(slen(template, max_len, &len) < 0) ||
- if_err(len >= max_len, EMSGSIZE)
+ if_err_sys(slen(template, max_len, &template_len) < 0) ||
+ if_err(template_len >= max_len, EMSGSIZE)
||
if_err_sys(slen(fname, max_len, &fname_len) < 0) ||
if_err(fname == NULL, EINVAL) ||
if_err(strrchr(fname, '/') != NULL, EINVAL))
return -1;
- for (end = template + len; /* count X */
+ for (end = template + template_len; /* count X */
end > template && *--end == 'X'; xc++);
- if (if_err(xc < 3 || xc > len, EINVAL) ||
- if_err(fname_len > len, EOVERFLOW))
+ if (if_err(xc < 3 || xc > template_len, EINVAL) ||
+ if_err(fname_len > template_len, EOVERFLOW))
return -1;
- if (if_err(memcmp(fname, template + len - fname_len,
+ if (if_err(vcmp(fname, template + template_len - fname_len,
fname_len) != 0, EINVAL))
return -1;
/* fname_copy = templatestr region only; p points to trailing XXXXXX */
memcpy(smalloc(&fname_copy, fname_len + 1),
- template + len - fname_len,
+ template + template_len - fname_len,
fname_len + 1);
p = fname_copy + fname_len - xc;
@@ -596,7 +589,7 @@ mkhtemp(int *fd,
goto err;
/* success: copy final name back */
- memcpy(template + len - fname_len,
+ memcpy(template + template_len - fname_len,
fname_copy, fname_len);
errno = saved_errno;
@@ -627,6 +620,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 +630,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 +764,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 +785,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 +832,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