ret = read_nointr(h->fd_event, &c, 1); if (ret < 0) return syserror("failure: read from socketpair");
/* Only switch ids if someone actually wrote a mapping for us. */ if (c == '1') { if (!switch_ids(0, 0)) return syserror("failure: switch ids to 0");
}
ret = write_nointr(h->fd_event, "1", 1); if (ret < 0) return syserror("failure: write to socketpair");
ret = create_userns_hierarchy(++h); if (ret < 0) return syserror("failure: userns level %d", h->level);
return 0;
}
staticint create_userns_hierarchy(struct userns_hierarchy *h)
{ int fret = -1; char c; int fd_socket[2]; int fd_userns = -EBADF, ret = -1;
ssize_t bytes;
pid_t pid; char path[256];
if (h->level == MAX_USERNS_LEVEL) return 0;
ret = socketpair(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0, fd_socket); if (ret < 0) return syserror("failure: create socketpair");
/* Note the CLONE_FILES | CLONE_VM when mucking with fds and memory. */
h->fd_event = fd_socket[1];
pid = do_clone(userns_fd_cb, h, CLONE_NEWUSER | CLONE_FILES | CLONE_VM); if (pid < 0) {
syserror("failure: userns level %d", h->level); goto out_close;
}
ret = map_ids_from_idmap(&h->id_map, pid); if (ret < 0) {
kill(pid, SIGKILL);
syserror("failure: writing id mapping for userns level %d for %d", h->level, pid); goto out_wait;
}
if (!list_empty(&h->id_map))
bytes = write_nointr(fd_socket[0], "1", 1); /* Inform the child we wrote a mapping. */ else
bytes = write_nointr(fd_socket[0], "0", 1); /* Inform the child we didn't write a mapping. */ if (bytes < 0) {
kill(pid, SIGKILL);
syserror("failure: write to socketpair"); goto out_wait;
}
/* Wait for child to set*id() and become dumpable. */
bytes = read_nointr(fd_socket[0], &c, 1); if (bytes < 0) {
kill(pid, SIGKILL);
syserror("failure: read from socketpair"); goto out_wait;
}
snprintf(path, sizeof(path), "/proc/%d/ns/user", pid);
fd_userns = open(path, O_RDONLY | O_CLOEXEC); if (fd_userns < 0) {
kill(pid, SIGKILL);
syserror("failure: open userns level %d for %d", h->level, pid); goto out_wait;
}
staticint write_file(constchar *path, constchar *val)
{ int fd = open(path, O_WRONLY);
size_t len = strlen(val); int ret;
if (fd == -1) {
ksft_print_msg("opening %s for write: %s\n", path, strerror(errno)); return -1;
}
ret = write(fd, val, len); if (ret == -1) {
ksft_print_msg("writing to %s: %s\n", path, strerror(errno)); return -1;
} if (ret != len) {
ksft_print_msg("short write to %s\n", path); return -1;
}
ret = close(fd); if (ret == -1) {
ksft_print_msg("closing %s\n", path); return -1;
}
return 0;
}
int setup_userns(void)
{ int ret; char buf[32];
uid_t uid = getuid();
gid_t gid = getgid();
ret = unshare(CLONE_NEWNS|CLONE_NEWUSER|CLONE_NEWPID); if (ret) {
ksft_exit_fail_msg("unsharing mountns and userns: %s\n",
strerror(errno)); return ret;
}
sprintf(buf, "0 %d 1", uid);
ret = write_file("/proc/self/uid_map", buf); if (ret) return ret;
ret = write_file("/proc/self/setgroups", "deny"); if (ret) return ret;
sprintf(buf, "0 %d 1", gid);
ret = write_file("/proc/self/gid_map", buf); if (ret) return ret;
ret = mount("", "/", NULL, MS_REC|MS_PRIVATE, NULL); if (ret) {
ksft_print_msg("making mount tree private: %s\n", strerror(errno)); return ret;
}
return 0;
}
/* caps_down - lower all effective caps */ int caps_down(void)
{ bool fret = false;
cap_t caps = NULL; int ret = -1;
caps = cap_get_proc(); if (!caps) goto out;
ret = cap_clear_flag(caps, CAP_EFFECTIVE); if (ret) goto out;
ret = cap_set_proc(caps); if (ret) goto out;
fret = true;
out:
cap_free(caps); return fret;
}
/* cap_down - lower an effective cap */ int cap_down(cap_value_t down)
{ bool fret = false;
cap_t caps = NULL;
cap_value_t cap = down; int ret = -1;
caps = cap_get_proc(); if (!caps) goto out;
ret = cap_set_flag(caps, CAP_EFFECTIVE, 1, &cap, 0); if (ret) goto out;
ret = cap_set_proc(caps); if (ret) goto out;
fret = true;
out:
cap_free(caps); return fret;
}
uint64_t get_unique_mnt_id(constchar *path)
{ struct statx sx; int ret;
ret = statx(AT_FDCWD, path, 0, STATX_MNT_ID_UNIQUE, &sx); if (ret == -1) {
ksft_print_msg("retrieving unique mount ID for %s: %s\n", path,
strerror(errno)); return 0;
}
if (!(sx.stx_mask & STATX_MNT_ID_UNIQUE)) {
ksft_print_msg("no unique mount ID available for %s\n", path); return 0;
}
return sx.stx_mnt_id;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.9 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.