summaryrefslogtreecommitdiff
path: root/src/nspawn
diff options
context:
space:
mode:
authorAdrian Szyndela <adrian.s@samsung.com>2020-03-26 16:03:37 +0100
committerAdrian Szyndela <adrian.s@samsung.com>2020-03-26 16:03:37 +0100
commit0dbfabccd0e6d8fecc58a19bb5b4db2842e88364 (patch)
treeaaac28e9f4d8588f149f12f8a2f70e866e26ed6c /src/nspawn
parent6926d6fb85cdf9148d949c6e29fad3651c2efb4b (diff)
parent738ab7502afb7663d9aacdd73e79025aa7cd0a9b (diff)
downloadsystemd-0dbfabccd0e6d8fecc58a19bb5b4db2842e88364.tar.gz
systemd-0dbfabccd0e6d8fecc58a19bb5b4db2842e88364.tar.bz2
systemd-0dbfabccd0e6d8fecc58a19bb5b4db2842e88364.zip
Merge v238 into tizen
systemd 238
Diffstat (limited to 'src/nspawn')
-rw-r--r--src/nspawn/nspawn-mount.c59
-rw-r--r--src/nspawn/nspawn-setuid.c78
-rw-r--r--src/nspawn/nspawn.c28
3 files changed, 48 insertions, 117 deletions
diff --git a/src/nspawn/nspawn-mount.c b/src/nspawn/nspawn-mount.c
index 68b4f64909..7fb41c126f 100644
--- a/src/nspawn/nspawn-mount.c
+++ b/src/nspawn/nspawn-mount.c
@@ -48,7 +48,7 @@ CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t) {
assert(t >= 0);
assert(t < _CUSTOM_MOUNT_TYPE_MAX);
- c = realloc_multiply(*l, (*n + 1), sizeof(CustomMount));
+ c = reallocarray(*l, *n + 1, sizeof(CustomMount));
if (!c)
return NULL;
@@ -548,21 +548,21 @@ int mount_all(const char *dest,
{ "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND, MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */
{ "/proc/sys/net", "/proc/sys/net", NULL, NULL, MS_BIND, MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO|MOUNT_APPLY_APIVFS_NETNS }, /* (except for this) */
{ NULL, "/proc/sys", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* ... then, make it r/o */
- { "/proc/sysrq-trigger", "/proc/sysrq-trigger", NULL, NULL, MS_BIND, MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */
- { NULL, "/proc/sysrq-trigger", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* ... then, make it r/o */
+ { "/proc/sysrq-trigger", "/proc/sysrq-trigger", NULL, NULL, MS_BIND, MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */
+ { NULL, "/proc/sysrq-trigger", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* ... then, make it r/o */
/* outer child mounts */
- { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, MOUNT_FATAL },
+ { "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, MOUNT_FATAL },
{ "tmpfs", "/sys", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS },
{ "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO }, /* skipped if above was mounted */
- { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL }, /* skipped if above was mounted */
+ { "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV, MOUNT_FATAL }, /* skipped if above was mounted */
{ "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME, MOUNT_FATAL },
{ "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, MOUNT_FATAL },
{ "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, MOUNT_FATAL },
#if HAVE_SELINUX
- { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, 0 }, /* Bind mount first */
- { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, 0 }, /* Then, make it r/o */
+ { "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND, 0 }, /* Bind mount first */
+ { NULL, "/sys/fs/selinux", NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, 0 }, /* Then, make it r/o */
#endif
};
@@ -637,56 +637,15 @@ int mount_all(const char *dest,
return 0;
}
-static int parse_mount_bind_options(const char *options, unsigned long *mount_flags, char **mount_opts) {
- const char *p = options;
- unsigned long flags = *mount_flags;
- char *opts = NULL;
- int r;
-
- assert(options);
-
- for (;;) {
- _cleanup_free_ char *word = NULL;
-
- r = extract_first_word(&p, &word, ",", 0);
- if (r < 0)
- return log_error_errno(r, "Failed to extract mount option: %m");
- if (r == 0)
- break;
-
- if (streq(word, "rbind"))
- flags |= MS_REC;
- else if (streq(word, "norbind"))
- flags &= ~MS_REC;
- else {
- log_error("Invalid bind mount option: %s", word);
- return -EINVAL;
- }
- }
-
- *mount_flags = flags;
- /* in the future mount_opts will hold string options for mount(2) */
- *mount_opts = opts;
-
- return 0;
-}
-
static int mount_bind(const char *dest, CustomMount *m) {
- _cleanup_free_ char *mount_opts = NULL, *where = NULL;
- unsigned long mount_flags = MS_BIND | MS_REC;
+ _cleanup_free_ char *where = NULL;
struct stat source_st, dest_st;
int r;
assert(dest);
assert(m);
- if (m->options) {
- r = parse_mount_bind_options(m->options, &mount_flags, &mount_opts);
- if (r < 0)
- return r;
- }
-
if (stat(m->source, &source_st) < 0)
return log_error_errno(errno, "Failed to stat %s: %m", m->source);
@@ -726,7 +685,7 @@ static int mount_bind(const char *dest, CustomMount *m) {
}
- r = mount_verbose(LOG_ERR, m->source, where, NULL, mount_flags, mount_opts);
+ r = mount_verbose(LOG_ERR, m->source, where, NULL, MS_BIND | MS_REC, m->options);
if (r < 0)
return r;
diff --git a/src/nspawn/nspawn-setuid.c b/src/nspawn/nspawn-setuid.c
index b08bcd988a..2dee5f8ec8 100644
--- a/src/nspawn/nspawn-setuid.c
+++ b/src/nspawn/nspawn-setuid.c
@@ -23,13 +23,16 @@
#include <unistd.h>
#include "alloc-util.h"
+#include "def.h"
#include "errno.h"
#include "fd-util.h"
+#include "fileio.h"
#include "mkdir.h"
#include "nspawn-setuid.h"
#include "process-util.h"
#include "signal-util.h"
#include "string-util.h"
+#include "strv.h"
#include "user-util.h"
#include "util.h"
@@ -45,33 +48,18 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
return log_error_errno(errno, "Failed to allocate pipe: %m");
r = safe_fork("(getent)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
- if (r < 0)
+ if (r < 0) {
+ safe_close_pair(pipe_fds);
return r;
+ }
if (r == 0) {
- int nullfd;
char *empty_env = NULL;
- if (dup3(pipe_fds[1], STDOUT_FILENO, 0) < 0)
- _exit(EXIT_FAILURE);
-
- if (pipe_fds[0] > 2)
- safe_close(pipe_fds[0]);
- if (pipe_fds[1] > 2)
- safe_close(pipe_fds[1]);
+ safe_close(pipe_fds[0]);
- nullfd = open("/dev/null", O_RDWR);
- if (nullfd < 0)
+ if (rearrange_stdio(-1, pipe_fds[1], -1) < 0)
_exit(EXIT_FAILURE);
- if (dup3(nullfd, STDIN_FILENO, 0) < 0)
- _exit(EXIT_FAILURE);
-
- if (dup3(nullfd, STDERR_FILENO, 0) < 0)
- _exit(EXIT_FAILURE);
-
- if (nullfd > 2)
- safe_close(nullfd);
-
close_all_fds(NULL, 0);
execle("/usr/bin/getent", "getent", database, key, NULL, &empty_env);
@@ -87,10 +75,10 @@ static int spawn_getent(const char *database, const char *key, pid_t *rpid) {
}
int change_uid_gid(const char *user, char **_home) {
- char line[LINE_MAX], *x, *u, *g, *h;
+ char *x, *u, *g, *h;
const char *word, *state;
_cleanup_free_ uid_t *uids = NULL;
- _cleanup_free_ char *home = NULL;
+ _cleanup_free_ char *home = NULL, *line = NULL;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_close_ int fd = -1;
unsigned n_uids = 0;
@@ -102,7 +90,7 @@ int change_uid_gid(const char *user, char **_home) {
assert(_home);
- if (!user || streq(user, "root") || streq(user, "0")) {
+ if (!user || STR_IN_SET(user, "root", "0")) {
/* Reset everything fully to 0, just in case */
r = reset_uid_gid();
@@ -118,21 +106,18 @@ int change_uid_gid(const char *user, char **_home) {
if (fd < 0)
return fd;
- f = fdopen(fd, "r");
+ f = fdopen(fd, "re");
if (!f)
return log_oom();
fd = -1;
- if (!fgets(line, sizeof(line), f)) {
- if (!ferror(f)) {
- log_error("Failed to resolve user %s.", user);
- return -ESRCH;
- }
-
- return log_error_errno(errno, "Failed to read from getent: %m");
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r == 0) {
+ log_error("Failed to resolve user %s.", user);
+ return -ESRCH;
}
-
- truncate_nl(line);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read from getent: %m");
(void) wait_for_terminate_and_check("getent passwd", pid, WAIT_LOG);
@@ -195,27 +180,26 @@ int change_uid_gid(const char *user, char **_home) {
if (!home)
return log_oom();
+ f = safe_fclose(f);
+ line = mfree(line);
+
/* Second, get group memberships */
fd = spawn_getent("initgroups", user, &pid);
if (fd < 0)
return fd;
- fclose(f);
- f = fdopen(fd, "r");
+ f = fdopen(fd, "re");
if (!f)
return log_oom();
fd = -1;
- if (!fgets(line, sizeof(line), f)) {
- if (!ferror(f)) {
- log_error("Failed to resolve user %s.", user);
- return -ESRCH;
- }
-
- return log_error_errno(errno, "Failed to read from getent: %m");
+ r = read_line(f, LONG_LINE_MAX, &line);
+ if (r == 0) {
+ log_error("Failed to resolve user %s.", user);
+ return -ESRCH;
}
-
- truncate_nl(line);
+ if (r < 0)
+ return log_error_errno(r, "Failed to read from getent: %m");
(void) wait_for_terminate_and_check("getent initgroups", pid, WAIT_LOG);
@@ -234,10 +218,8 @@ int change_uid_gid(const char *user, char **_home) {
return log_oom();
r = parse_uid(c, &uids[n_uids++]);
- if (r < 0) {
- log_error("Failed to parse group data from getent.");
- return -EIO;
- }
+ if (r < 0)
+ return log_error_errno(r, "Failed to parse group data from getent: %m");
}
r = mkdir_parents(home, 0775);
diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c
index 0f05ecff03..90f1c4184f 100644
--- a/src/nspawn/nspawn.c
+++ b/src/nspawn/nspawn.c
@@ -2233,10 +2233,8 @@ static int chase_symlinks_and_update(char **p, unsigned flags) {
if (r < 0)
return log_error_errno(r, "Failed to resolve path %s: %m", *p);
- free(*p);
- *p = chased;
-
- return 0;
+ free_and_replace(*p, chased);
+ return r; /* r might be an fd here in case we ever use CHASE_OPEN in flags */
}
static int determine_uid_shift(const char *directory) {
@@ -2584,23 +2582,15 @@ static int outer_child(
return log_error_errno(errno, "PR_SET_PDEATHSIG failed: %m");
if (interactive) {
- close_nointr(STDIN_FILENO);
- close_nointr(STDOUT_FILENO);
- close_nointr(STDERR_FILENO);
-
- r = open_terminal(console, O_RDWR);
- if (r != STDIN_FILENO) {
- if (r >= 0) {
- safe_close(r);
- r = -EINVAL;
- }
+ int terminal;
- return log_error_errno(r, "Failed to open console: %m");
- }
+ terminal = open_terminal(console, O_RDWR);
+ if (terminal < 0)
+ return log_error_errno(terminal, "Failed to open console: %m");
- if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO ||
- dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO)
- return log_error_errno(errno, "Failed to duplicate console: %m");
+ r = rearrange_stdio(terminal, terminal, terminal); /* invalidates 'terminal' on success and failure */
+ if (r < 0)
+ return log_error_errno(r, "Failed to move console to stdin/stdout/stderr: %m");
}
r = reset_audit_loginuid();