X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fshared%2Futil.c;h=20aec2a5c9cafa236b76806dd21b84b934a11ee6;hp=c71293106f228910d52323957b78e1baa9cbaf4b;hb=2cfbd749af308bdbe56edcfed7f3eea0fc2b93d2;hpb=85ca9433abc00d8cc641fceafe9e87dfcd92af4a diff --git a/src/shared/util.c b/src/shared/util.c index c71293106..20aec2a5c 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -59,6 +59,7 @@ #include #include #include +#undef basename #include "macro.h" #include "util.h" @@ -3961,8 +3962,8 @@ int fopen_temporary(const char *path, FILE **_f, char **_temp_path) { if (!t) return -ENOMEM; - fn = path_get_file_name(path); - k = fn-path; + fn = basename(path); + k = fn - path; memcpy(t, path, k); t[k] = '.'; stpcpy(stpcpy(t+k+1, fn), "XXXXXX"); @@ -4147,7 +4148,7 @@ int symlink_atomic(const char *from, const char *to) { if (!t) return -ENOMEM; - fn = path_get_file_name(to); + fn = basename(to); k = fn-to; memcpy(t, to, k); t[k] = '.'; @@ -5219,10 +5220,10 @@ int make_console_stdio(void) { } int get_home_dir(char **_h) { - char *h; + struct passwd *p; const char *e; + char *h; uid_t u; - struct passwd *p; assert(_h); @@ -5265,6 +5266,53 @@ int get_home_dir(char **_h) { return 0; } +int get_shell(char **_s) { + struct passwd *p; + const char *e; + char *s; + uid_t u; + + assert(_s); + + /* Take the user specified one */ + e = getenv("SHELL"); + if (e) { + s = strdup(e); + if (!s) + return -ENOMEM; + + *_s = s; + return 0; + } + + /* Hardcode home directory for root to avoid NSS */ + u = getuid(); + if (u == 0) { + s = strdup("/bin/sh"); + if (!s) + return -ENOMEM; + + *_s = s; + return 0; + } + + /* Check the database... */ + errno = 0; + p = getpwuid(u); + if (!p) + return errno > 0 ? -errno : -ESRCH; + + if (!path_is_absolute(p->pw_shell)) + return -EINVAL; + + s = strdup(p->pw_shell); + if (!s) + return -ENOMEM; + + *_s = s; + return 0; +} + bool filename_is_safe(const char *p) { if (isempty(p)) @@ -5791,12 +5839,18 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need) { size_t a; void *q; + assert(p); assert(allocated); if (*allocated >= need) return *p; a = MAX(64u, need * 2); + + /* check for overflows */ + if (a < need) + return NULL; + q = realloc(*p, a); if (!q) return NULL; @@ -5807,9 +5861,14 @@ void* greedy_realloc(void **p, size_t *allocated, size_t need) { } void* greedy_realloc0(void **p, size_t *allocated, size_t need) { - size_t prev = *allocated; + size_t prev; uint8_t *q; + assert(p); + assert(allocated); + + prev = *allocated; + q = greedy_realloc(p, allocated, need); if (!q) return NULL; @@ -5939,3 +5998,82 @@ int proc_cmdline(char **ret) { return 1; } + +int container_get_leader(const char *machine, pid_t *pid) { + _cleanup_free_ char *s = NULL, *class = NULL; + const char *p; + pid_t leader; + int r; + + assert(machine); + assert(pid); + + p = strappenda("/run/systemd/machines/", machine); + r = parse_env_file(p, NEWLINE, "LEADER", &s, "CLASS", &class, NULL); + if (r == -ENOENT) + return -EHOSTDOWN; + if (r < 0) + return r; + if (!s) + return -EIO; + + if (!streq_ptr(class, "container")) + return -EIO; + + r = parse_pid(s, &leader); + if (r < 0) + return r; + if (leader <= 1) + return -EIO; + + *pid = leader; + return 0; +} + +int namespace_open(pid_t pid, int *namespace_fd, int *root_fd) { + _cleanup_close_ int nsfd = -1; + const char *ns, *root; + int rfd; + + assert(pid >= 0); + assert(namespace_fd); + assert(root_fd); + + ns = procfs_file_alloca(pid, "ns/mnt"); + nsfd = open(ns, O_RDONLY|O_NOCTTY|O_CLOEXEC); + if (nsfd < 0) + return -errno; + + root = procfs_file_alloca(pid, "root"); + rfd = open(root, O_RDONLY|O_NOCTTY|O_CLOEXEC|O_DIRECTORY); + if (rfd < 0) + return -errno; + + *namespace_fd = nsfd; + *root_fd = rfd; + nsfd = -1; + + return 0; +} + +int namespace_enter(int namespace_fd, int root_fd) { + assert(namespace_fd >= 0); + assert(root_fd >= 0); + + if (setns(namespace_fd, CLONE_NEWNS) < 0) + return -errno; + + if (fchdir(root_fd) < 0) + return -errno; + + if (chroot(".") < 0) + return -errno; + + if (setresgid(0, 0, 0) < 0) + return -errno; + + if (setresuid(0, 0, 0) < 0) + return -errno; + + return 0; +}