summaryrefslogtreecommitdiff
path: root/util
diff options
context:
space:
mode:
Diffstat (limited to 'util')
-rw-r--r--util/libreboot-utils/include/common.h12
-rw-r--r--util/libreboot-utils/lib/command.c4
-rw-r--r--util/libreboot-utils/lib/file.c8
-rw-r--r--util/libreboot-utils/lib/mkhtemp.c20
-rw-r--r--util/libreboot-utils/lib/num.c2
-rw-r--r--util/libreboot-utils/lib/state.c26
-rw-r--r--util/libreboot-utils/lib/string.c158
-rw-r--r--util/libreboot-utils/mkhtemp.c54
-rw-r--r--util/libreboot-utils/nvmutil.c14
9 files changed, 201 insertions, 97 deletions
diff --git a/util/libreboot-utils/include/common.h b/util/libreboot-utils/include/common.h
index 196f2810..97bbdf0c 100644
--- a/util/libreboot-utils/include/common.h
+++ b/util/libreboot-utils/include/common.h
@@ -384,7 +384,13 @@ int slen(const char *scmp, size_t maxlen,
size_t *rval);
int scmp(const char *a, const char *b,
size_t maxlen, int *rval);
-
+int sdup(const char *s,
+ size_t n, char **dest);
+int scat(const char *s1, const char *s2,
+ size_t n, char **dest);
+int dcat(const char *s, size_t n,
+ size_t off, char **dest1,
+ char **dest2);
/* numerical functions
*/
@@ -494,11 +500,13 @@ int try_err(int loop_err, int errval);
*/
void usage(void);
-void err_no_cleanup(int nvm_errval, const char *msg, ...);
+void err_no_cleanup(int stfu, int nvm_errval, const char *msg, ...);
void b0rk(int nvm_errval, const char *msg, ...);
int exit_cleanup(void);
const char *getnvmprogname(void);
+void err_mkhtemp(int stfu, int errval, const char *msg, ...);
+
/* libc hardening
*/
diff --git a/util/libreboot-utils/lib/command.c b/util/libreboot-utils/lib/command.c
index 6d0e8856..c7048a23 100644
--- a/util/libreboot-utils/lib/command.c
+++ b/util/libreboot-utils/lib/command.c
@@ -110,7 +110,7 @@ set_cmd(int argc, char *argv[])
cmd = x->cmd[c].str;
if (scmp(argv[2], cmd, MAX_CMD_LEN, &rval) < 0)
- err_no_cleanup(EINVAL,
+ err_no_cleanup(0, EINVAL,
"could not compare command strings");
if (rval != 0)
continue; /* not the right command */
@@ -123,7 +123,7 @@ set_cmd(int argc, char *argv[])
return;
}
- err_no_cleanup(EINVAL,
+ err_no_cleanup(0, EINVAL,
"Too few args on command '%s'", cmd);
}
diff --git a/util/libreboot-utils/lib/file.c b/util/libreboot-utils/lib/file.c
index 46d5e016..552618d6 100644
--- a/util/libreboot-utils/lib/file.c
+++ b/util/libreboot-utils/lib/file.c
@@ -96,16 +96,16 @@ void
xopen(int *fd_ptr, const char *path, int flags, struct stat *st)
{
if ((*fd_ptr = open(path, flags)) < 0)
- err_no_cleanup(errno, "%s", path);
+ err_no_cleanup(0, errno, "%s", path);
if (fstat(*fd_ptr, st) < 0)
- err_no_cleanup(errno, "%s: stat", path);
+ err_no_cleanup(0, errno, "%s: stat", path);
if (!S_ISREG(st->st_mode))
- err_no_cleanup(errno, "%s: not a regular file", path);
+ err_no_cleanup(0, errno, "%s: not a regular file", path);
if (lseek_on_eintr(*fd_ptr, 0, SEEK_CUR, 1, 1) == (off_t)-1)
- err_no_cleanup(errno, "%s: file not seekable", path);
+ err_no_cleanup(0, errno, "%s: file not seekable", path);
}
/* fsync() the directory of a file,
diff --git a/util/libreboot-utils/lib/mkhtemp.c b/util/libreboot-utils/lib/mkhtemp.c
index 6b4898fd..2fb2f01a 100644
--- a/util/libreboot-utils/lib/mkhtemp.c
+++ b/util/libreboot-utils/lib/mkhtemp.c
@@ -79,8 +79,8 @@ new_tmp_common(int *fd, char **path, int type,
#endif
struct stat st;
- const char *suffix;
- size_t suffix_len;
+ const char *templatestr;
+ size_t templatestr_len;
size_t dirlen;
size_t destlen;
@@ -144,17 +144,17 @@ new_tmp_common(int *fd, char **path, int type,
goto err;
if (template != NULL)
- suffix = template;
+ templatestr = template;
else
- suffix = "tmp.XXXXXXXXXX";
+ templatestr = "tmp.XXXXXXXXXX";
- if (slen(suffix, maxlen, &suffix_len) < 0)
+ if (slen(templatestr, maxlen, &templatestr_len) < 0)
goto err;
/* sizeof adds an extra byte, useful
* because we also want '.' or '/'
*/
- destlen = dirlen + 1 + suffix_len;
+ destlen = dirlen + 1 + templatestr_len;
if (destlen > maxlen - 1) {
errno = EOVERFLOW;
goto err;
@@ -168,7 +168,7 @@ new_tmp_common(int *fd, char **path, int type,
memcpy(dest, tmpdir, dirlen);
*(dest + dirlen) = '/';
- memcpy(dest + dirlen + 1, suffix, suffix_len);
+ memcpy(dest + dirlen + 1, templatestr, templatestr_len);
*(dest + destlen) = '\0';
fname = dest + dirlen + 1;
@@ -603,7 +603,7 @@ mkhtemp(int *fd,
if_err_sys(slen(template, max_len, &len) < 0) ||
if_err(len >= max_len, EMSGSIZE)
||
- if_err_sys(slen(fname, max_len, &fname_len)) ||
+ if_err_sys(slen(fname, max_len, &fname_len) < 0) ||
if_err(fname == NULL, EINVAL) ||
if_err(strrchr(fname, '/') != NULL, EINVAL))
return -1;
@@ -611,7 +611,7 @@ mkhtemp(int *fd,
for (end = template + len; /* count X */
end > template && *--end == 'X'; xc++);
- if (if_err(xc < 6 || xc > len, EINVAL) ||
+ if (if_err(xc < 3 || xc > len, EINVAL) ||
if_err(fname_len > len, EOVERFLOW))
return -1;
@@ -622,7 +622,7 @@ mkhtemp(int *fd,
if((fname_copy = malloc(fname_len + 1)) == NULL)
goto err;
- /* fname_copy = suffix region only; p points to trailing XXXXXX */
+ /* fname_copy = templatestr region only; p points to trailing XXXXXX */
memcpy(fname_copy,
template + len - fname_len,
fname_len + 1);
diff --git a/util/libreboot-utils/lib/num.c b/util/libreboot-utils/lib/num.c
index 43efba71..0b76e257 100644
--- a/util/libreboot-utils/lib/num.c
+++ b/util/libreboot-utils/lib/num.c
@@ -436,6 +436,6 @@ void
check_bin(size_t a, const char *a_name)
{
if (a > 1)
- err_no_cleanup(EINVAL, "%s must be 0 or 1, but is %lu",
+ err_no_cleanup(0, EINVAL, "%s must be 0 or 1, but is %lu",
a_name, (size_t)a);
}
diff --git a/util/libreboot-utils/lib/state.c b/util/libreboot-utils/lib/state.c
index 4ef7163f..42d060b7 100644
--- a/util/libreboot-utils/lib/state.c
+++ b/util/libreboot-utils/lib/state.c
@@ -98,9 +98,9 @@ xstart(int argc, char *argv[])
return &us;
if (argc < 3)
- err_no_cleanup(EINVAL, "xstart: Too few arguments");
+ err_no_cleanup(0, EINVAL, "xstart: Too few arguments");
if (argv == NULL)
- err_no_cleanup(EINVAL, "xstart: NULL argv");
+ err_no_cleanup(0, EINVAL, "xstart: NULL argv");
first_run = 0;
@@ -113,41 +113,41 @@ xstart(int argc, char *argv[])
us.f.tname = NULL;
if ((realdir = realpath(us.f.fname, NULL)) == NULL)
- err_no_cleanup(errno, "xstart: can't get realpath of %s",
+ err_no_cleanup(0, errno, "xstart: can't get realpath of %s",
us.f.fname);
if (fs_dirname_basename(realdir, &dir, &base, 0) < 0)
- err_no_cleanup(errno, "xstart: don't know CWD of %s",
+ err_no_cleanup(0, errno, "xstart: don't know CWD of %s",
us.f.fname);
if ((us.f.base = strdup(base)) == NULL)
- err_no_cleanup(errno, "strdup base");
+ err_no_cleanup(0, errno, "strdup base");
us.f.dirfd = fs_open(dir,
O_RDONLY | O_DIRECTORY);
if (us.f.dirfd < 0)
- err_no_cleanup(errno, "%s: open dir", dir);
+ err_no_cleanup(0, errno, "%s: open dir", dir);
if (new_tmpfile(&us.f.tmp_fd, &us.f.tname, dir, ".gbe.XXXXXXXXXX") < 0)
- err_no_cleanup(errno, "%s", us.f.tname);
+ err_no_cleanup(0, errno, "%s", us.f.tname);
if (fs_dirname_basename(us.f.tname,
&tmpdir, &tmpbase_local, 0) < 0)
- err_no_cleanup(errno, "tmp basename");
+ err_no_cleanup(0, errno, "tmp basename");
us.f.tmpbase = strdup(tmpbase_local);
if (us.f.tmpbase == NULL)
- err_no_cleanup(errno, "strdup tmpbase");
+ err_no_cleanup(0, errno, "strdup tmpbase");
free_if_null(&tmpdir);
if (us.f.tname == NULL)
- err_no_cleanup(errno, "x->f.tname null");
+ err_no_cleanup(0, errno, "x->f.tname null");
if (*us.f.tname == '\0')
- err_no_cleanup(errno, "x->f.tname empty");
+ err_no_cleanup(0, errno, "x->f.tname empty");
if (fstat(us.f.tmp_fd, &us.f.tmp_st) < 0)
- err_no_cleanup(errno, "%s: stat", us.f.tname);
+ err_no_cleanup(0, errno, "%s: stat", us.f.tname);
memset(us.f.real_buf, 0, sizeof(us.f.real_buf));
memset(us.f.bufcmp, 0, sizeof(us.f.bufcmp));
@@ -164,7 +164,7 @@ xstatus(void)
struct xstate *x = xstart(0, NULL);
if (x == NULL)
- err_no_cleanup(EACCES, "NULL pointer to xstate");
+ err_no_cleanup(0, EACCES, "NULL pointer to xstate");
return x;
}
diff --git a/util/libreboot-utils/lib/string.c b/util/libreboot-utils/lib/string.c
index 2f2be5f3..0329c6c3 100644
--- a/util/libreboot-utils/lib/string.c
+++ b/util/libreboot-utils/lib/string.c
@@ -14,25 +14,12 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
+#include <limits.h>
+#include <stdint.h>
#include "../include/common.h"
-/* scmp() - strict string comparison
- *
- * strict string comparison
- * similar to strncmp, but null and
- * unterminated inputs do not produce
- * a return value; on error, errno is
- * set and -1 is returned.
- *
- * the real return value is stored in
- * the 4th argument by pointer.
- *
- * the value at rval pointer is set,
- * only upon success. callers should
- * check the return value accordingly.
- */
-
+/* strict strcmp */
int
scmp(const char *a,
const char *b,
@@ -46,9 +33,8 @@ scmp(const char *a,
if (a == NULL ||
b == NULL ||
rval == NULL) {
-
errno = EFAULT;
- return -1;
+ goto err;
}
for (ch = 0; ch < maxlen; ch++) {
@@ -67,27 +53,14 @@ scmp(const char *a,
}
}
- /* block unterminated strings */
+err:
errno = EFAULT;
+ if (rval != NULL)
+ *rval = -1;
return -1;
}
-/* slen() - strict strict length
- *
- * strict string length calculation
- * similar to strnlen, but null and
- * unterminated inputs do not produce
- * a return value; on error, errno is
- * set and -1 is returned.
- *
- * the real return value is stored in
- * the 3rd argument by pointer.
- *
- * the value at rval pointer is set,
- * only upon success. callers should
- * check the return value accordingly.
- */
-
+/* strict strlen */
int
slen(const char *s,
size_t maxlen,
@@ -97,9 +70,8 @@ slen(const char *s,
if (s == NULL ||
rval == NULL) {
-
errno = EFAULT;
- return -1;
+ goto err;
}
for (ch = 0;
@@ -109,17 +81,120 @@ slen(const char *s,
if (ch == maxlen) {
/* unterminated */
errno = EFAULT;
- return -1;
+ goto err;
}
*rval = ch;
return 0;
+err:
+ if (rval != NULL)
+ *rval = 0;
+ return -1;
+}
+
+/* strict strdup */
+int
+sdup(const char *s,
+ size_t n, char **dest)
+{
+ size_t size;
+ char *rval;
+
+ if (dest == NULL ||
+ slen(s, n, &size) < 0 ||
+ if_err(size == SIZE_MAX, EOVERFLOW) ||
+ (rval = malloc(size + 1)) == NULL) {
+
+ if (dest != NULL)
+ *dest = NULL;
+ return -1;
+ }
+
+ memcpy(rval, s, size);
+ *(rval + size) = '\0';
+
+ *dest = rval;
+ return 0;
+}
+
+/* strict strcat */
+int
+scat(const char *s1, const char *s2,
+ size_t n, char **dest)
+{
+ size_t size1;
+ size_t size2;
+ char *rval;
+
+ if (dest == NULL ||
+ slen(s1, n, &size1) < 0 ||
+ slen(s2, n, &size2) < 0 ||
+ if_err(size1 > SIZE_MAX - size2 - 1, EOVERFLOW) ||
+ (rval = malloc(size1 + size2 + 1)) == NULL) {
+
+ if (dest != NULL)
+ *dest = NULL;
+ return -1;
+ }
+
+ memcpy(rval, s1, size1);
+ memcpy(rval + size1, s2, size2);
+ *(rval + size1 + size2) = '\0';
+
+ *dest = rval;
+ return 0;
+}
+
+/* strict split/de-cat - off is where
+ 2nd buffer will start from */
+int
+dcat(const char *s, size_t n,
+ size_t off, char **dest1,
+ char **dest2)
+{
+ size_t size;
+ char *rval1 = NULL;
+ char *rval2 = NULL;
+
+ if (dest1 == NULL || dest2 == NULL ||
+ slen(s, n, &size) < 0 ||
+ if_err(size == SIZE_MAX, EOVERFLOW) ||
+ if_err(off >= size, EOVERFLOW) ||
+ (rval1 = malloc(off + 1)) == NULL ||
+ (rval2 = malloc(size - off + 1)) == NULL) {
+
+ goto err;
+ }
+
+ memcpy(rval1, s, off);
+ *(rval1 + off) = '\0';
+
+ memcpy(rval2, s + off, size - off);
+ *(rval2 + size - off) = '\0';
+
+ *dest1 = rval1;
+ *dest2 = rval2;
+
+ return 0;
+
+err:
+ if (rval1 != NULL)
+ free(rval1);
+ if (rval2 != NULL)
+ free(rval2);
+
+ if (dest1 != NULL)
+ *dest1 = NULL;
+ if (dest2 != NULL)
+ *dest2 = NULL;
+
+ return -1;
}
/* the one for nvmutil state is in state.c */
/* this one just exits */
void
-err_no_cleanup(int nvm_errval, const char *msg, ...)
+err_no_cleanup(int stfu, int nvm_errval, const char *msg, ...)
{
va_list args;
int saved_errno = errno;
@@ -141,7 +216,10 @@ err_no_cleanup(int nvm_errval, const char *msg, ...)
vfprintf(stderr, msg, args);
va_end(args);
- fprintf(stderr, ": %s\n", strerror(errno));
+ if (p != NULL)
+ fprintf(stderr, ": %s\n", strerror(errno));
+ else
+ fprintf(stderr, "%s\n", strerror(errno));
exit(EXIT_FAILURE);
}
diff --git a/util/libreboot-utils/mkhtemp.c b/util/libreboot-utils/mkhtemp.c
index 4408f763..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
@@ -87,9 +91,10 @@ main(int argc, char *argv[])
int fd = -1;
int type = MKHTEMP_FILE;
+ int stfu = 0; /* -q option */
if (lbgetprogname(argv[0]) == NULL)
- err_no_cleanup(errno, "could not set progname");
+ err_no_cleanup(stfu, errno, "could not set progname");
/* https://man.openbsd.org/pledge.2 */
#if defined(__OpenBSD__) && defined(OpenBSD)
@@ -100,7 +105,7 @@ main(int argc, char *argv[])
#endif
while ((c =
- getopt(argc, argv, "dp:")) != -1) {
+ getopt(argc, argv, "qdp:")) != -1) {
switch (c) {
case 'd':
@@ -111,6 +116,11 @@ main(int argc, char *argv[])
tmpdir = optarg;
break;
+ case 'q': /* don't print errors */
+ /* (exit status unchanged) */
+ stfu = 1;
+ break;
+
default:
goto err_usage;
}
@@ -119,21 +129,20 @@ main(int argc, char *argv[])
if (optind < argc)
template = argv[optind];
if (optind + 1 < argc)
- err_no_cleanup(EINVAL,
- "usage: mkhtemp [-d] [-p dir] [template]\n");
+ goto err_usage;
/* custom template e.g. foo.XXXXXXXXXXXXXXXXXXXXX */
if (template != NULL) {
if (slen(template, maxlen, &tlen) < 0)
- err_no_cleanup(EINVAL,
+ err_no_cleanup(stfu, EINVAL,
"invalid template");
for (p = template + tlen;
p > template && *--p == 'X'; xc++);
- if (xc < 6)
- err_no_cleanup(EINVAL,
- "template must end in at least 6 X");
+ 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:
@@ -146,38 +155,35 @@ main(int argc, char *argv[])
if (tmpdir != NULL) {
rp = realpath(tmpdir, resolved);
if (rp == NULL)
- err_no_cleanup(errno,
- "%s", tmpdir);
+ err_no_cleanup(stfu, errno, "%s", tmpdir);
tmpdir = resolved;
}
if (new_tmp_common(&fd, &s, type,
tmpdir, template) < 0)
- err_no_cleanup(errno, "%s", s);
+ 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(EINVAL,
+ err_no_cleanup(stfu, EINVAL,
"usage: %s [-d] [-p dir] [template]\n", getnvmprogname());
}/*
@@ -191,3 +197,15 @@ err_usage:
*/
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/util/libreboot-utils/nvmutil.c b/util/libreboot-utils/nvmutil.c
index d9b91349..e02f60af 100644
--- a/util/libreboot-utils/nvmutil.c
+++ b/util/libreboot-utils/nvmutil.c
@@ -36,34 +36,34 @@ main(int argc, char *argv[])
size_t c;
if (lbgetprogname(argv[0]) == NULL)
- err_no_cleanup(errno, "could not set progname");
+ err_no_cleanup(0, errno, "could not set progname");
/* https://man.openbsd.org/pledge.2
https://man.openbsd.org/unveil.2 */
#if defined(__OpenBSD__) && defined(OpenBSD)
#if (OpenBSD) >= 604
if (pledge("stdio flock rpath wpath cpath unveil", NULL) == -1)
- err_no_cleanup(errno, "pledge plus unveil, main");
+ err_no_cleanup(0, errno, "pledge plus unveil, main");
if (unveil("/dev/null", "r") == -1)
- err_no_cleanup(errno, "unveil r: /dev/null");
+ err_no_cleanup(0, errno, "unveil r: /dev/null");
#elif (OpenBSD) >= 509
if (pledge("stdio flock rpath wpath cpath", NULL) == -1)
- err_no_cleanup(errno, "pledge, main");
+ err_no_cleanup(0, errno, "pledge, main");
#endif
#endif
#ifndef S_ISREG
- err_no_cleanup(ECANCELED,
+ err_no_cleanup(0, ECANCELED,
"Can't determine file types (S_ISREG undefined)");
#endif
#if ((CHAR_BIT) != 8)
- err_no_cleanup(ECANCELED, "Unsupported char size");
+ err_no_cleanup(0, ECANCELED, "Unsupported char size");
#endif
x = xstart(argc, argv);
if (x == NULL)
- err_no_cleanup(ECANCELED, "NULL state on init");
+ err_no_cleanup(0, ECANCELED, "NULL state on init");
/* parse user command */
/* TODO: CHECK ACCESSES VIA xstatus() */