diff options
author | Mattias Andrée <m@maandree.se> | 2025-01-29 21:07:06 +0100 |
---|---|---|
committer | Mattias Andrée <m@maandree.se> | 2025-01-29 21:07:06 +0100 |
commit | fde1d802203869236ae5678082626cca55f1f50d (patch) | |
tree | 8bd6f5c1ebbf8acd6932fe6f22abfe367dcd7de5 /nokeyrings.c | |
download | nokeyrings-fde1d802203869236ae5678082626cca55f1f50d.tar.gz nokeyrings-fde1d802203869236ae5678082626cca55f1f50d.tar.bz2 nokeyrings-fde1d802203869236ae5678082626cca55f1f50d.tar.xz |
First commit
Signed-off-by: Mattias Andrée <m@maandree.se>
Diffstat (limited to '')
-rw-r--r-- | nokeyrings.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/nokeyrings.c b/nokeyrings.c new file mode 100644 index 0000000..aaa32c7 --- /dev/null +++ b/nokeyrings.c @@ -0,0 +1,127 @@ +/* See LICENSE file for copyright and license details. */ +#include <sys/mount.h> +#ifndef OPEN_TREE_CLONE +# define MISSING_OPEN_TREE +#endif +#ifndef MOVE_MOUNT_F_EMPTY_PATH +# define MISSING_MOVE_MOUNT +#endif +#if defined(MISSING_OPEN_TREE) || defined(MISSING_MOVE_MOUNT) +# include <linux/mount.h> +# include <sys/syscall.h> +#endif +#include <sched.h> +#include <libsimple.h> +#include <libsimple-arg.h> + +NUSAGE(125, "utility [argument] ..."); + + + +#ifdef MISSING_OPEN_TREE +static int +open_tree(int dirfd, const char *path, int flags) +{ + return syscall(SYS_open_tree, dirfd, path, flags); +} +#endif + + +#ifdef MISSING_MOVE_MOUNT +static int +move_mount(int dirfd1, const char *path1, int dirfd2, const char *path2, int flags) +{ + return syscall(SYS_move_mount, dirfd1, path1, dirfd2, path2, flags); +} +#endif + + +int +main(int argc, char *argv[]) +{ + struct stat st; + int emptyfd = -1; + int keyringsfd = -1; + char *path = NULL; + struct passwd *pwd; + + libsimple_default_failure_exit = 125; + + ARGBEGIN { + default: + usage(); + } ARGEND; + + if (!argc) + usage(); + + errno = 0; + pwd = getpwuid(getuid()); + if (!pwd) { + if (!errno) { + eprintf("your user does not exist"); + } else if (errno == EIO) { + weprintf("getpwuid <real user>:"); + eprintf("this usually indicates that the user not exist"); + } else { + eprintf("getpwuid <real user>:"); + } + } + if (!pwd->pw_dir || !*pwd->pw_dir) + eprintf("your user does not have a home directory"); + + path = emalloc(strlen(pwd->pw_dir) + sizeof("/.local/share/keyrings")); + stpcpy(stpcpy(path, pwd->pw_dir), "/.local/share/keyrings"); + + keyringsfd = open(path, O_DIRECTORY); + if (keyringsfd < 0) { + if (errno != ENOENT) + weprintf("open %s O_DIRECTORY:", path); + goto exec; + } + + if (unshare(CLONE_NEWNS)) { + weprintf("unshare CLONE_NEWNS:"); + goto exec; + } + if (mount("none", "/", NULL, MS_REC | MS_SLAVE, NULL)) { + weprintf("mount none / NULL MS_REC|MS_SLAVE NULL:"); + goto exec; + } + + emptyfd = open_tree(AT_FDCWD, "/var/empty", OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC); + if (emptyfd < 0) { + weprintf("open_tree AT_FDCWD /var/empty OPEN_TREE_CLONE|OPEN_TREE_CLOEXEC:"); + goto exec; + } + + if (fstatat(emptyfd, "", &st, AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW)) { + weprintf("fstatat /var/empty \"\" <buffer> AT_EMPTY_PATH | AT_SYMLINK_NOFOLLOW:"); + goto exec; + } + if (!S_ISDIR(st.st_mode)) { + weprintf("/var/empty exists but is not a directory:"); + goto exec; + } + + if (move_mount(emptyfd, "", AT_FDCWD, path, MOVE_MOUNT_F_EMPTY_PATH)) { + weprintf("move_mount /var/empty \"\" AT_FDCWD %s MOVE_MOUNT_F_EMPTY_PATH:", path); + goto exec; + } + +exec: + free(path); + if (emptyfd >= 0) + close(emptyfd); + if (keyringsfd >= 0) + close(keyringsfd); + + if (setegid(getgid())) + eprintf("setegid <real group>:"); + if (seteuid(getuid())) + eprintf("seteuid <real user>:"); + + execvp(argv[0], argv); + enprintf(errno == ENOENT ? 127 : 126, "execvp %s:", argv[0]); + return 0; +} |