/* See LICENSE file for copyright and license details. */ #include #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 # include #endif #include #include #include 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 :"); eprintf("this usually indicates that the user not exist"); } else { eprintf("getpwuid :"); } } 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 \"\" 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 :"); if (seteuid(getuid())) eprintf("seteuid :"); execvp(argv[0], argv); enprintf(errno == ENOENT ? 127 : 126, "execvp %s:", argv[0]); return 0; }