mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-07-11 05:52:36 +02:00
d2abde5303
where possible, try not to clobber sys errno. override it only when relatively safe. also: when a syscall succeeds, it may set errno. this is rare, but permitted (nothing specified against it in specs, and the specs say that errno is undefined on success). i'm not libc, but i'm wrapping around it, so i need to be careful in how i handle the errno value. also: i removed the requirement for directories to be executable, in mkhtemp.c, because this isn't required and will only break certain setups. in world_writeable and sticky, i made the checks stricter: the faccessat check was being skipped on some paths, so i've closed that loophole now. i also generally cleaned up some code, as part of the errno handling refactoring, where it made sense to do so, plus a few other bits of code cleanup. Signed-off-by: Leah Rowe <leah@libreboot.org>
145 lines
3.0 KiB
C
145 lines
3.0 KiB
C
/* SPDX-License-Identifier: MIT ( >:3 )
|
|
* Copyright (c) 2026 Leah Rowe <leah@libreboot.org> /| |\
|
|
* / \
|
|
* Hardened mktemp (mkhtemp!)
|
|
*
|
|
* WORK IN PROGRESS (proof of concept), or, v0.0000001
|
|
* DO NOT PUT THIS IN YOUR LINUX DISTRO YET.
|
|
*
|
|
* In other words: for reference only -- PATCHES WELCOME!
|
|
*
|
|
* I will remove this notice when the code is mature, and
|
|
* probably contact several of your projects myself.
|
|
*
|
|
* See README. This is an ongoing project; no proper docs
|
|
* yet, and no manpage (yet!) - the code is documentation,
|
|
* while the specification that it implements evolves.
|
|
*/
|
|
|
|
#if defined(__linux__) && !defined(_GNU_SOURCE)
|
|
/* for openat2 on linux */
|
|
#define _GNU_SOURCE 1
|
|
#endif
|
|
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <limits.h>
|
|
#include <stdarg.h>
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <unistd.h>
|
|
|
|
#include "include/common.h"
|
|
|
|
static void
|
|
exit_cleanup(void);
|
|
|
|
int
|
|
main(int argc, char *argv[])
|
|
{
|
|
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[PATH_MAX];
|
|
char c;
|
|
|
|
int fd = -1;
|
|
int type = MKHTEMP_FILE;
|
|
|
|
(void) errhook(exit_cleanup);
|
|
(void) lbsetprogname(argv[0]);
|
|
|
|
/* https://man.openbsd.org/pledge.2 */
|
|
xpledgex("stdio flock rpath wpath cpath", NULL);
|
|
|
|
while ((c =
|
|
getopt(argc, argv, "qdp:")) != -1) {
|
|
|
|
switch (c) {
|
|
case 'd':
|
|
type = MKHTEMP_DIR;
|
|
break;
|
|
|
|
case 'p':
|
|
tmpdir = optarg;
|
|
break;
|
|
|
|
case 'q': /* don't print errors */
|
|
/* (exit status unchanged) */
|
|
break;
|
|
|
|
default:
|
|
goto err_usage;
|
|
}
|
|
}
|
|
|
|
if (optind < argc)
|
|
template = argv[optind];
|
|
if (optind + 1 < argc)
|
|
goto err_usage;
|
|
|
|
/* custom template e.g. foo.XXXXXXXXXXXXXXXXXXXXX */
|
|
if (template != NULL) {
|
|
for (p = template + slen(template, PATH_MAX, &tlen);
|
|
p > template && *--p == 'X'; xc++);
|
|
|
|
if (xc < 3) /* the gnu mktemp errs on less than 3 */
|
|
err_exit(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_exit(errno, "%s", tmpdir);
|
|
|
|
tmpdir = resolved;
|
|
}
|
|
|
|
if (new_tmp_common(&fd, &s, type,
|
|
tmpdir, template) < 0)
|
|
err_exit(errno, "%s", s);
|
|
|
|
xpledgex("stdio", NULL);
|
|
|
|
if (s == NULL)
|
|
err_exit(EFAULT, "bad string initialisation");
|
|
if (*s == '\0')
|
|
err_exit(EFAULT, "empty string initialisation");
|
|
|
|
slen(s, PATH_MAX, &len); /* Nullterminierung prüfen */
|
|
/* for good measure. (bonus: also re-checks length overflow) */
|
|
|
|
printf("%s\n", s);
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
err_usage:
|
|
err_exit(EINVAL,
|
|
"usage: %s [-d] [-p dir] [template]\n", lbgetprogname());
|
|
}
|
|
|
|
static void
|
|
exit_cleanup(void)
|
|
{
|
|
return;
|
|
}
|