diff options
Diffstat (limited to 'util/libreboot-utils/lib/mkhtemp.c')
| -rw-r--r-- | util/libreboot-utils/lib/mkhtemp.c | 85 |
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 |
