diff options
Diffstat (limited to 'util/libreboot-utils/mkhtemp.c')
| -rw-r--r-- | util/libreboot-utils/mkhtemp.c | 116 |
1 files changed, 94 insertions, 22 deletions
diff --git a/util/libreboot-utils/mkhtemp.c b/util/libreboot-utils/mkhtemp.c index 3e148a4a..261227cb 100644 --- a/util/libreboot-utils/mkhtemp.c +++ b/util/libreboot-utils/mkhtemp.c @@ -10,6 +10,10 @@ * generally provides much higher strictness than previous * implementations such as mktemp, mkstemp or even mkdtemp. * + * It uses several modern features by default, e.g. openat2 + * and O_TMPFILE on Linux, with additional hardening; BSD + * projects only have openat so the code uses that there. + * * Many programs rely on mktemp, and they use TMPDIR in a way * that is quite insecure. Mkhtemp intends to change that, * quite dramatically, with: userspace sandbox (and use OS @@ -67,64 +71,120 @@ int main(int argc, char *argv[]) { - char *s = NULL; - int fd = -1; - char c; - int type = MKHTEMP_FILE; - size_t len; - #if defined (PATH_LEN) && \ (PATH_LEN) >= 256 size_t maxlen = PATH_LEN; #else size_t maxlen = 4096; #endif + size_t len; + size_t tlen; + size_t xc = 0; + + char *tmpdir = NULL; + char *template = NULL; + char *p; + char *s = NULL; + char *rp; + char resolved[maxlen]; + char c; + + int fd = -1; + int type = MKHTEMP_FILE; + int stfu = 0; /* -q option */ + + if (lbgetprogname(argv[0]) == NULL) + err_no_cleanup(stfu, errno, "could not set progname"); /* https://man.openbsd.org/pledge.2 */ #if defined(__OpenBSD__) && defined(OpenBSD) #if (OpenBSD) >= 509 if (pledge("stdio flock rpath wpath cpath", NULL) == -1) - err_no_cleanup(errno, "pledge, main"); + goto err_usage; #endif #endif - while ((c = - getopt(argc, argv, "d")) != -1) { + while ((c = + getopt(argc, argv, "qdp:")) != -1) { - switch(c) { + switch (c) { case 'd': - type = MKHTEMP_DIR; break; - default: - err_no_cleanup(EINVAL, - "usage: mkhtemp [-d]\n"); + case 'p': + tmpdir = optarg; + break; + + case 'q': /* don't print errors */ + /* (exit status unchanged) */ + stfu = 1; + break; + + default: + goto err_usage; } } - if (new_tmp_common(&fd, &s, type) < 0) - err_no_cleanup(errno, "%s", s); + if (optind < argc) + template = argv[optind]; + if (optind + 1 < argc) + goto err_usage; + + /* custom template e.g. foo.XXXXXXXXXXXXXXXXXXXXX */ + if (template != NULL) { + if (slen(template, maxlen, &tlen) < 0) + err_no_cleanup(stfu, EINVAL, + "invalid template"); + + for (p = template + tlen; + p > template && *--p == 'X'; xc++); + + if (xc < 3) /* the gnu mktemp errs on less than 3 */ + err_no_cleanup(stfu, EINVAL, + "template must have 3 X or more on end (12+ advised"); + } + + /* user supplied -p PATH - WARNING: + * this permits symlinks, but only here, + * not in the library, so they are resolved + * here first, and *only here*. the mkhtemp + * library blocks them. be careful + * when using -p + */ + if (tmpdir != NULL) { + rp = realpath(tmpdir, resolved); + if (rp == NULL) + err_no_cleanup(stfu, errno, "%s", tmpdir); + + tmpdir = resolved; + } + + if (new_tmp_common(&fd, &s, type, + tmpdir, template) < 0) + err_no_cleanup(stfu, errno, "%s", s); #if defined(__OpenBSD__) && defined(OpenBSD) #if (OpenBSD) >= 509 if (pledge("stdio", NULL) == -1) - err_no_cleanup(errno, "pledge, exit"); + err_no_cleanup(stfu, errno, "pledge, exit"); #endif #endif if (s == NULL) - err_no_cleanup(EFAULT, "bad string initialisation"); - + err_no_cleanup(stfu, EFAULT, "bad string initialisation"); if (*s == '\0') - err_no_cleanup(EFAULT, "empty string initialisation"); - + err_no_cleanup(stfu, EFAULT, "empty string initialisation"); if (slen(s, maxlen, &len) < 0) - err_no_cleanup(EFAULT, "unterminated string initialisation"); + err_no_cleanup(stfu, EFAULT, "unterminated string initialisiert"); printf("%s\n", s); return EXIT_SUCCESS; + +err_usage: + err_no_cleanup(stfu, EINVAL, + "usage: %s [-d] [-p dir] [template]\n", getnvmprogname()); }/* @@ -137,3 +197,15 @@ main(int argc, char *argv[]) */ + + + + + + + + + + + + |
