mirror of
https://github.com/systemd/systemd.git
synced 2024-12-26 03:22:00 +03:00
Merge pull request #7494 from poettering/nspawn-cgroups
some nspawn cgroup fixes + dissecting and testing love
This commit is contained in:
commit
fa9be0a6f0
@ -673,6 +673,22 @@ bool fstype_can_discard(const char *fstype) {
|
||||
"xfs");
|
||||
}
|
||||
|
||||
bool fstype_can_uid_gid(const char *fstype) {
|
||||
|
||||
/* All file systems that have a uid=/gid= mount option that fixates the owners of all files and directories,
|
||||
* current and future. */
|
||||
|
||||
return STR_IN_SET(fstype,
|
||||
"adfs",
|
||||
"fat",
|
||||
"hfs",
|
||||
"hpfs",
|
||||
"iso9660",
|
||||
"msdos",
|
||||
"ntfs",
|
||||
"vfat");
|
||||
}
|
||||
|
||||
int repeat_unmount(const char *path, int flags) {
|
||||
bool done = false;
|
||||
|
||||
|
@ -52,6 +52,7 @@ bool fstype_is_network(const char *fstype);
|
||||
bool fstype_is_api_vfs(const char *fstype);
|
||||
bool fstype_is_ro(const char *fsype);
|
||||
bool fstype_can_discard(const char *fstype);
|
||||
bool fstype_can_uid_gid(const char *fstype);
|
||||
|
||||
const char* mode_to_inaccessible_node(mode_t mode);
|
||||
|
||||
|
@ -882,7 +882,9 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version)
|
||||
* for Gentoo which does a merge without making /lib a symlink.
|
||||
*/
|
||||
"lib/systemd/libsystemd-shared-*.so\0"
|
||||
"usr/lib/systemd/libsystemd-shared-*.so\0") {
|
||||
"lib64/systemd/libsystemd-shared-*.so\0"
|
||||
"usr/lib/systemd/libsystemd-shared-*.so\0"
|
||||
"usr/lib64/systemd/libsystemd-shared-*.so\0") {
|
||||
|
||||
_cleanup_strv_free_ char **names = NULL;
|
||||
_cleanup_free_ char *path = NULL;
|
||||
|
@ -734,16 +734,20 @@ char *strip_tab_ansi(char **ibuf, size_t *_isz) {
|
||||
return obuf;
|
||||
}
|
||||
|
||||
char *strextend(char **x, ...) {
|
||||
va_list ap;
|
||||
size_t f, l;
|
||||
char *strextend_with_separator(char **x, const char *separator, ...) {
|
||||
bool need_separator;
|
||||
size_t f, l, l_separator;
|
||||
char *r, *p;
|
||||
va_list ap;
|
||||
|
||||
assert(x);
|
||||
|
||||
l = f = strlen_ptr(*x);
|
||||
|
||||
va_start(ap, x);
|
||||
need_separator = !isempty(*x);
|
||||
l_separator = strlen_ptr(separator);
|
||||
|
||||
va_start(ap, separator);
|
||||
for (;;) {
|
||||
const char *t;
|
||||
size_t n;
|
||||
@ -753,22 +757,29 @@ char *strextend(char **x, ...) {
|
||||
break;
|
||||
|
||||
n = strlen(t);
|
||||
|
||||
if (need_separator)
|
||||
n += l_separator;
|
||||
|
||||
if (n > ((size_t) -1) - l) {
|
||||
va_end(ap);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
l += n;
|
||||
need_separator = true;
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
need_separator = !isempty(*x);
|
||||
|
||||
r = realloc(*x, l+1);
|
||||
if (!r)
|
||||
return NULL;
|
||||
|
||||
p = r + f;
|
||||
|
||||
va_start(ap, x);
|
||||
va_start(ap, separator);
|
||||
for (;;) {
|
||||
const char *t;
|
||||
|
||||
@ -776,10 +787,17 @@ char *strextend(char **x, ...) {
|
||||
if (!t)
|
||||
break;
|
||||
|
||||
if (need_separator && separator)
|
||||
p = stpcpy(p, separator);
|
||||
|
||||
p = stpcpy(p, t);
|
||||
|
||||
need_separator = true;
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
assert(p == r + l);
|
||||
|
||||
*p = 0;
|
||||
*x = r;
|
||||
|
||||
|
@ -179,7 +179,9 @@ char *strreplace(const char *text, const char *old_string, const char *new_strin
|
||||
|
||||
char *strip_tab_ansi(char **p, size_t *l);
|
||||
|
||||
char *strextend(char **x, ...) _sentinel_;
|
||||
char *strextend_with_separator(char **x, const char *separator, ...) _sentinel_;
|
||||
|
||||
#define strextend(x, ...) strextend_with_separator(x, NULL, __VA_ARGS__)
|
||||
|
||||
char *strrep(const char *s, unsigned n);
|
||||
|
||||
|
@ -1155,7 +1155,7 @@ int setup_namespace(
|
||||
|
||||
if (root_image) {
|
||||
/* A root image is specified, mount it to the right place */
|
||||
r = dissected_image_mount(dissected_image, root, dissect_image_flags);
|
||||
r = dissected_image_mount(dissected_image, root, UID_INVALID, dissect_image_flags);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "loop-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "user-util.h"
|
||||
#include "util.h"
|
||||
|
||||
static enum {
|
||||
@ -303,7 +304,7 @@ int main(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = dissected_image_mount(m, arg_path, arg_flags);
|
||||
r = dissected_image_mount(m, arg_path, UID_INVALID, arg_flags);
|
||||
if (r < 0) {
|
||||
log_error_errno(r, "Failed to mount image: %m");
|
||||
goto finish;
|
||||
|
@ -820,19 +820,13 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
||||
return log_oom();
|
||||
|
||||
} else if (streq(key, "rootflags")) {
|
||||
char *o;
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
o = arg_root_options ?
|
||||
strjoin(arg_root_options, ",", value) :
|
||||
strdup(value);
|
||||
if (!o)
|
||||
if (!strextend_with_separator(&arg_root_options, ",", value, NULL))
|
||||
return log_oom();
|
||||
|
||||
free(arg_root_options);
|
||||
arg_root_options = o;
|
||||
} else if (streq(key, "roothash")) {
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
@ -858,20 +852,13 @@ static int parse_proc_cmdline_item(const char *key, const char *value, void *dat
|
||||
return log_oom();
|
||||
|
||||
} else if (streq(key, "mount.usrflags")) {
|
||||
char *o;
|
||||
|
||||
if (proc_cmdline_value_missing(key, value))
|
||||
return 0;
|
||||
|
||||
o = arg_usr_options ?
|
||||
strjoin(arg_usr_options, ",", value) :
|
||||
strdup(value);
|
||||
if (!o)
|
||||
if (!strextend_with_separator(&arg_usr_options, ",", value, NULL))
|
||||
return log_oom();
|
||||
|
||||
free(arg_usr_options);
|
||||
arg_usr_options = o;
|
||||
|
||||
} else if (streq(key, "rw") && !value)
|
||||
arg_root_rw = true;
|
||||
else if (streq(key, "ro") && !value)
|
||||
|
@ -41,13 +41,15 @@ static int chown_cgroup_path(const char *path, uid_t uid_shift) {
|
||||
|
||||
FOREACH_STRING(fn,
|
||||
".",
|
||||
"tasks",
|
||||
"notify_on_release",
|
||||
"cgroup.procs",
|
||||
"cgroup.events",
|
||||
"cgroup.clone_children",
|
||||
"cgroup.controllers",
|
||||
"cgroup.subtree_control")
|
||||
"cgroup.events",
|
||||
"cgroup.procs",
|
||||
"cgroup.stat",
|
||||
"cgroup.subtree_control",
|
||||
"cgroup.threads",
|
||||
"notify_on_release",
|
||||
"tasks")
|
||||
if (fchownat(fd, fn, uid_shift, uid_shift, 0) < 0)
|
||||
log_full_errno(errno == ENOENT ? LOG_DEBUG : LOG_WARNING, errno,
|
||||
"Failed to chown \"%s/%s\", ignoring: %m", path, fn);
|
||||
@ -55,7 +57,7 @@ static int chown_cgroup_path(const char *path, uid_t uid_shift) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chown_cgroup(pid_t pid, uid_t uid_shift) {
|
||||
int chown_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift) {
|
||||
_cleanup_free_ char *path = NULL, *fs = NULL;
|
||||
int r;
|
||||
|
||||
@ -71,6 +73,19 @@ int chown_cgroup(pid_t pid, uid_t uid_shift) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to chown() cgroup %s: %m", fs);
|
||||
|
||||
if (unified_requested == CGROUP_UNIFIED_SYSTEMD) {
|
||||
_cleanup_free_ char *lfs = NULL;
|
||||
/* Always propagate access rights from unified to legacy controller */
|
||||
|
||||
r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER_LEGACY, path, NULL, &lfs);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to get file system path for container cgroup: %m");
|
||||
|
||||
r = chown_cgroup_path(lfs, uid_shift);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to chown() cgroup %s: %m", lfs);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,6 @@
|
||||
|
||||
#include "cgroup-util.h"
|
||||
|
||||
int chown_cgroup(pid_t pid, uid_t uid_shift);
|
||||
int chown_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift);
|
||||
int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift);
|
||||
int create_subcgroup(pid_t pid, CGroupUnified unified_requested);
|
||||
|
@ -320,7 +320,7 @@ static int custom_mount_check_all(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int detect_unified_cgroup_hierarchy(const char *directory) {
|
||||
static int detect_unified_cgroup_hierarchy_from_environment(void) {
|
||||
const char *e;
|
||||
int r;
|
||||
|
||||
@ -334,11 +334,16 @@ static int detect_unified_cgroup_hierarchy(const char *directory) {
|
||||
arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_ALL;
|
||||
else
|
||||
arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Otherwise inherit the default from the host system */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int detect_unified_cgroup_hierarchy_from_image(const char *directory) {
|
||||
int r;
|
||||
|
||||
/* Let's inherit the mode to use from the host system, but let's take into consideration what systemd in the
|
||||
* image actually supports. */
|
||||
r = cg_all_unified();
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to determine whether we are in all unified mode.");
|
||||
@ -364,6 +369,10 @@ static int detect_unified_cgroup_hierarchy(const char *directory) {
|
||||
} else
|
||||
arg_unified_cgroup_hierarchy = CGROUP_UNIFIED_NONE;
|
||||
|
||||
log_debug("Using %s hierarchy for container.",
|
||||
arg_unified_cgroup_hierarchy == CGROUP_UNIFIED_NONE ? "legacy" :
|
||||
arg_unified_cgroup_hierarchy == CGROUP_UNIFIED_SYSTEMD ? "hybrid" : "unified");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2522,6 +2531,7 @@ static int outer_child(
|
||||
int kmsg_socket,
|
||||
int rtnl_socket,
|
||||
int uid_shift_socket,
|
||||
int unified_cgroup_hierarchy_socket,
|
||||
FDSet *fds) {
|
||||
|
||||
pid_t pid;
|
||||
@ -2572,7 +2582,13 @@ static int outer_child(
|
||||
return r;
|
||||
|
||||
if (dissected_image) {
|
||||
r = dissected_image_mount(dissected_image, directory, DISSECT_IMAGE_DISCARD_ON_LOOP|(arg_read_only ? DISSECT_IMAGE_READ_ONLY : 0));
|
||||
/* If we are operating on a disk image, then mount its root directory now, but leave out the rest. We
|
||||
* can read the UID shift from it if we need to. Further down we'll mount the rest, but then with the
|
||||
* uid shift known. That way we can mount VFAT file systems shifted to the right place right away. This
|
||||
* makes sure ESP partitions and userns are compatible. */
|
||||
|
||||
r = dissected_image_mount(dissected_image, directory, arg_uid_shift,
|
||||
DISSECT_IMAGE_MOUNT_ROOT_ONLY|DISSECT_IMAGE_DISCARD_ON_LOOP|(arg_read_only ? DISSECT_IMAGE_READ_ONLY : 0));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -2608,6 +2624,32 @@ static int outer_child(
|
||||
log_info("Selected user namespace base " UID_FMT " and range " UID_FMT ".", arg_uid_shift, arg_uid_range);
|
||||
}
|
||||
|
||||
if (dissected_image) {
|
||||
/* Now we know the uid shift, let's now mount everything else that might be in the image. */
|
||||
r = dissected_image_mount(dissected_image, directory, arg_uid_shift,
|
||||
DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY|DISSECT_IMAGE_DISCARD_ON_LOOP|(arg_read_only ? DISSECT_IMAGE_READ_ONLY : 0));
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (arg_unified_cgroup_hierarchy == CGROUP_UNIFIED_UNKNOWN) {
|
||||
/* OK, we don't know yet which cgroup mode to use yet. Let's figure it out, and tell the parent. */
|
||||
|
||||
r = detect_unified_cgroup_hierarchy_from_image(directory);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
l = send(unified_cgroup_hierarchy_socket, &arg_unified_cgroup_hierarchy, sizeof(arg_unified_cgroup_hierarchy), MSG_NOSIGNAL);
|
||||
if (l < 0)
|
||||
return log_error_errno(errno, "Failed to send cgroup mode: %m");
|
||||
if (l != sizeof(arg_unified_cgroup_hierarchy)) {
|
||||
log_error("Short write while sending cgroup mode: %m");
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
unified_cgroup_hierarchy_socket = safe_close(unified_cgroup_hierarchy_socket);
|
||||
}
|
||||
|
||||
/* Turn directory into bind mount */
|
||||
r = mount_verbose(LOG_ERR, directory, directory, NULL, MS_BIND|MS_REC, NULL);
|
||||
if (r < 0)
|
||||
@ -3254,7 +3296,9 @@ static int run(int master,
|
||||
pid_socket_pair[2] = { -1, -1 },
|
||||
uuid_socket_pair[2] = { -1, -1 },
|
||||
notify_socket_pair[2] = { -1, -1 },
|
||||
uid_shift_socket_pair[2] = { -1, -1 };
|
||||
uid_shift_socket_pair[2] = { -1, -1 },
|
||||
unified_cgroup_hierarchy_socket_pair[2] = { -1, -1};
|
||||
|
||||
_cleanup_close_ int notify_socket= -1;
|
||||
_cleanup_(barrier_destroy) Barrier barrier = BARRIER_NULL;
|
||||
_cleanup_(sd_event_source_unrefp) sd_event_source *notify_event_source = NULL;
|
||||
@ -3307,6 +3351,10 @@ static int run(int master,
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, uid_shift_socket_pair) < 0)
|
||||
return log_error_errno(errno, "Failed to create uid shift socket pair: %m");
|
||||
|
||||
if (arg_unified_cgroup_hierarchy == CGROUP_UNIFIED_UNKNOWN)
|
||||
if (socketpair(AF_UNIX, SOCK_SEQPACKET|SOCK_CLOEXEC, 0, unified_cgroup_hierarchy_socket_pair) < 0)
|
||||
return log_error_errno(errno, "Failed to create unified cgroup socket pair: %m");
|
||||
|
||||
/* Child can be killed before execv(), so handle SIGCHLD in order to interrupt
|
||||
* parent's blocking calls and give it a chance to call wait() and terminate. */
|
||||
r = sigprocmask(SIG_UNBLOCK, &mask_chld, NULL);
|
||||
@ -3335,6 +3383,7 @@ static int run(int master,
|
||||
uuid_socket_pair[0] = safe_close(uuid_socket_pair[0]);
|
||||
notify_socket_pair[0] = safe_close(notify_socket_pair[0]);
|
||||
uid_shift_socket_pair[0] = safe_close(uid_shift_socket_pair[0]);
|
||||
unified_cgroup_hierarchy_socket_pair[0] = safe_close(unified_cgroup_hierarchy_socket_pair[0]);
|
||||
|
||||
(void) reset_all_signal_handlers();
|
||||
(void) reset_signal_mask();
|
||||
@ -3351,6 +3400,7 @@ static int run(int master,
|
||||
kmsg_socket_pair[1],
|
||||
rtnl_socket_pair[1],
|
||||
uid_shift_socket_pair[1],
|
||||
unified_cgroup_hierarchy_socket_pair[1],
|
||||
fds);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
@ -3368,6 +3418,7 @@ static int run(int master,
|
||||
uuid_socket_pair[1] = safe_close(uuid_socket_pair[1]);
|
||||
notify_socket_pair[1] = safe_close(notify_socket_pair[1]);
|
||||
uid_shift_socket_pair[1] = safe_close(uid_shift_socket_pair[1]);
|
||||
unified_cgroup_hierarchy_socket_pair[1] = safe_close(unified_cgroup_hierarchy_socket_pair[1]);
|
||||
|
||||
if (arg_userns_mode != USER_NAMESPACE_NO) {
|
||||
/* The child just let us know the UID shift it might have read from the image. */
|
||||
@ -3398,6 +3449,17 @@ static int run(int master,
|
||||
}
|
||||
}
|
||||
|
||||
if (arg_unified_cgroup_hierarchy == CGROUP_UNIFIED_UNKNOWN) {
|
||||
/* The child let us know the support cgroup mode it might have read from the image. */
|
||||
l = recv(unified_cgroup_hierarchy_socket_pair[0], &arg_unified_cgroup_hierarchy, sizeof(arg_unified_cgroup_hierarchy), 0);
|
||||
if (l < 0)
|
||||
return log_error_errno(errno, "Failed to read cgroup mode: %m");
|
||||
if (l != sizeof(arg_unified_cgroup_hierarchy)) {
|
||||
log_error("Short read while reading cgroup mode.");
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for the outer child. */
|
||||
r = wait_for_terminate_and_warn("namespace helper", *pid, NULL);
|
||||
if (r != 0)
|
||||
@ -3557,7 +3619,7 @@ static int run(int master,
|
||||
return r;
|
||||
}
|
||||
|
||||
r = chown_cgroup(*pid, arg_uid_shift);
|
||||
r = chown_cgroup(*pid, arg_unified_cgroup_hierarchy, arg_uid_shift);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -3736,6 +3798,10 @@ int main(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = detect_unified_cgroup_hierarchy_from_environment();
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
n_fd_passed = sd_listen_fds(false);
|
||||
if (n_fd_passed > 0) {
|
||||
r = fdset_new_listen_fds(&fds, false);
|
||||
@ -3983,10 +4049,6 @@ int main(int argc, char *argv[]) {
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
r = detect_unified_cgroup_hierarchy(arg_directory);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
interactive =
|
||||
isatty(STDIN_FILENO) > 0 &&
|
||||
isatty(STDOUT_FILENO) > 0;
|
||||
|
@ -49,6 +49,7 @@
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "udev-util.h"
|
||||
#include "user-util.h"
|
||||
#include "xattr-util.h"
|
||||
|
||||
int probe_filesystem(const char *node, char **ret_fstype) {
|
||||
@ -686,10 +687,11 @@ static int mount_partition(
|
||||
DissectedPartition *m,
|
||||
const char *where,
|
||||
const char *directory,
|
||||
uid_t uid_shift,
|
||||
DissectImageFlags flags) {
|
||||
|
||||
const char *p, *options = NULL, *node, *fstype;
|
||||
_cleanup_free_ char *chased = NULL;
|
||||
_cleanup_free_ char *chased = NULL, *options = NULL;
|
||||
const char *p, *node, *fstype;
|
||||
bool rw;
|
||||
int r;
|
||||
|
||||
@ -720,13 +722,26 @@ static int mount_partition(
|
||||
/* If requested, turn on discard support. */
|
||||
if (fstype_can_discard(fstype) &&
|
||||
((flags & DISSECT_IMAGE_DISCARD) ||
|
||||
((flags & DISSECT_IMAGE_DISCARD_ON_LOOP) && is_loop_device(m->node))))
|
||||
options = "discard";
|
||||
((flags & DISSECT_IMAGE_DISCARD_ON_LOOP) && is_loop_device(m->node)))) {
|
||||
options = strdup("discard");
|
||||
if (!options)
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (uid_is_valid(uid_shift) && uid_shift != 0 && fstype_can_uid_gid(fstype)) {
|
||||
_cleanup_free_ char *uid_option = NULL;
|
||||
|
||||
if (asprintf(&uid_option, "uid=" UID_FMT ",gid=" GID_FMT, uid_shift, (gid_t) uid_shift) < 0)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!strextend_with_separator(&options, ",", uid_option, NULL))
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
return mount_verbose(LOG_DEBUG, node, p, fstype, MS_NODEV|(rw ? 0 : MS_RDONLY), options);
|
||||
}
|
||||
|
||||
int dissected_image_mount(DissectedImage *m, const char *where, DissectImageFlags flags) {
|
||||
int dissected_image_mount(DissectedImage *m, const char *where, uid_t uid_shift, DissectImageFlags flags) {
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@ -735,15 +750,20 @@ int dissected_image_mount(DissectedImage *m, const char *where, DissectImageFlag
|
||||
if (!m->partitions[PARTITION_ROOT].found)
|
||||
return -ENXIO;
|
||||
|
||||
r = mount_partition(m->partitions + PARTITION_ROOT, where, NULL, flags);
|
||||
if ((flags & DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY) == 0) {
|
||||
r = mount_partition(m->partitions + PARTITION_ROOT, where, NULL, uid_shift, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if ((flags & DISSECT_IMAGE_MOUNT_ROOT_ONLY))
|
||||
return 0;
|
||||
|
||||
r = mount_partition(m->partitions + PARTITION_HOME, where, "/home", uid_shift, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mount_partition(m->partitions + PARTITION_HOME, where, "/home", flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = mount_partition(m->partitions + PARTITION_SRV, where, "/srv", flags);
|
||||
r = mount_partition(m->partitions + PARTITION_SRV, where, "/srv", uid_shift, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
@ -761,7 +781,7 @@ int dissected_image_mount(DissectedImage *m, const char *where, DissectImageFlag
|
||||
|
||||
r = dir_is_empty(p);
|
||||
if (r > 0) {
|
||||
r = mount_partition(m->partitions + PARTITION_ESP, where, mp, flags);
|
||||
r = mount_partition(m->partitions + PARTITION_ESP, where, mp, uid_shift, flags);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
@ -1254,7 +1274,7 @@ int dissected_image_acquire_metadata(DissectedImage *m) {
|
||||
if (mount(NULL, "/", NULL, MS_SLAVE | MS_REC, NULL) < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
r = dissected_image_mount(m, t, DISSECT_IMAGE_READ_ONLY);
|
||||
r = dissected_image_mount(m, t, UID_INVALID, DISSECT_IMAGE_READ_ONLY);
|
||||
if (r < 0)
|
||||
_exit(EXIT_FAILURE);
|
||||
|
||||
|
@ -62,15 +62,17 @@ static inline int PARTITION_VERITY_OF(int p) {
|
||||
}
|
||||
|
||||
typedef enum DissectImageFlags {
|
||||
DISSECT_IMAGE_READ_ONLY = 1,
|
||||
DISSECT_IMAGE_DISCARD_ON_LOOP = 2, /* Turn on "discard" if on a loop device and file system supports it */
|
||||
DISSECT_IMAGE_DISCARD = 4, /* Turn on "discard" if file system supports it, on all block devices */
|
||||
DISSECT_IMAGE_DISCARD_ON_CRYPTO = 8, /* Turn on "discard" also on crypto devices */
|
||||
DISSECT_IMAGE_READ_ONLY = 1 << 0,
|
||||
DISSECT_IMAGE_DISCARD_ON_LOOP = 1 << 1, /* Turn on "discard" if on a loop device and file system supports it */
|
||||
DISSECT_IMAGE_DISCARD = 1 << 2, /* Turn on "discard" if file system supports it, on all block devices */
|
||||
DISSECT_IMAGE_DISCARD_ON_CRYPTO = 1 << 3, /* Turn on "discard" also on crypto devices */
|
||||
DISSECT_IMAGE_DISCARD_ANY = DISSECT_IMAGE_DISCARD_ON_LOOP |
|
||||
DISSECT_IMAGE_DISCARD |
|
||||
DISSECT_IMAGE_DISCARD_ON_CRYPTO,
|
||||
DISSECT_IMAGE_GPT_ONLY = 16, /* Only recognize images with GPT partition tables */
|
||||
DISSECT_IMAGE_REQUIRE_ROOT = 32, /* Don't accept disks without root partition */
|
||||
DISSECT_IMAGE_GPT_ONLY = 1 << 4, /* Only recognize images with GPT partition tables */
|
||||
DISSECT_IMAGE_REQUIRE_ROOT = 1 << 5, /* Don't accept disks without root partition */
|
||||
DISSECT_IMAGE_MOUNT_ROOT_ONLY = 1 << 6, /* Mount only the root partition */
|
||||
DISSECT_IMAGE_MOUNT_NON_ROOT_ONLY = 1 << 7, /* Mount only non-root partitions */
|
||||
} DissectImageFlags;
|
||||
|
||||
struct DissectedImage {
|
||||
@ -94,7 +96,7 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(DissectedImage*, dissected_image_unref);
|
||||
|
||||
int dissected_image_decrypt(DissectedImage *m, const char *passphrase, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DecryptedImage **ret);
|
||||
int dissected_image_decrypt_interactively(DissectedImage *m, const char *passphrase, const void *root_hash, size_t root_hash_size, DissectImageFlags flags, DecryptedImage **ret);
|
||||
int dissected_image_mount(DissectedImage *m, const char *dest, DissectImageFlags flags);
|
||||
int dissected_image_mount(DissectedImage *m, const char *dest, uid_t uid_shift, DissectImageFlags flags);
|
||||
|
||||
int dissected_image_acquire_metadata(DissectedImage *m);
|
||||
|
||||
|
@ -104,9 +104,37 @@ static void test_strstrip(void) {
|
||||
}
|
||||
|
||||
static void test_strextend(void) {
|
||||
_cleanup_free_ char *str = strdup("0123");
|
||||
strextend(&str, "456", "78", "9", NULL);
|
||||
assert_se(streq(str, "0123456789"));
|
||||
_cleanup_free_ char *str = NULL;
|
||||
|
||||
assert_se(strextend(&str, NULL));
|
||||
assert_se(streq_ptr(str, ""));
|
||||
assert_se(strextend(&str, "", "0", "", "", "123", NULL));
|
||||
assert_se(streq_ptr(str, "0123"));
|
||||
assert_se(strextend(&str, "456", "78", "9", NULL));
|
||||
assert_se(streq_ptr(str, "0123456789"));
|
||||
}
|
||||
|
||||
static void test_strextend_with_separator(void) {
|
||||
_cleanup_free_ char *str = NULL;
|
||||
|
||||
assert_se(strextend_with_separator(&str, NULL, NULL));
|
||||
assert_se(streq_ptr(str, ""));
|
||||
str = mfree(str);
|
||||
|
||||
assert_se(strextend_with_separator(&str, "...", NULL));
|
||||
assert_se(streq_ptr(str, ""));
|
||||
assert_se(strextend_with_separator(&str, "...", NULL));
|
||||
assert_se(streq_ptr(str, ""));
|
||||
str = mfree(str);
|
||||
|
||||
assert_se(strextend_with_separator(&str, "xyz", "a", "bb", "ccc", NULL));
|
||||
assert_se(streq_ptr(str, "axyzbbxyzccc"));
|
||||
str = mfree(str);
|
||||
|
||||
assert_se(strextend_with_separator(&str, ",", "start", "", "1", "234", NULL));
|
||||
assert_se(streq_ptr(str, "start,,1,234"));
|
||||
assert_se(strextend_with_separator(&str, ";", "more", "5", "678", NULL));
|
||||
assert_se(streq_ptr(str, "start,,1,234;more;5;678"));
|
||||
}
|
||||
|
||||
static void test_strrep(void) {
|
||||
@ -399,6 +427,7 @@ int main(int argc, char *argv[]) {
|
||||
test_streq_ptr();
|
||||
test_strstrip();
|
||||
test_strextend();
|
||||
test_strextend_with_separator();
|
||||
test_strrep();
|
||||
test_strappend();
|
||||
test_string_has_cc();
|
||||
|
@ -3,7 +3,6 @@
|
||||
# ex: ts=8 sw=4 sts=4 et filetype=sh
|
||||
set -e
|
||||
TEST_DESCRIPTION="https://github.com/systemd/systemd/issues/2467"
|
||||
TEST_NO_NSPAWN=1
|
||||
|
||||
. $TEST_BASE_DIR/test-functions
|
||||
SKIP_INITRD=yes
|
||||
@ -19,7 +18,7 @@ test_setup() {
|
||||
eval $(udevadm info --export --query=env --name=${LOOPDEV}p2)
|
||||
|
||||
setup_basic_environment
|
||||
dracut_install nc true rm
|
||||
dracut_install true rm
|
||||
|
||||
# setup the testsuite service
|
||||
cat >$initdir/etc/systemd/system/testsuite.service <<'EOF'
|
||||
@ -29,13 +28,15 @@ After=multi-user.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/bin/sh -e -x -c 'rm -f /tmp/nonexistent; systemctl start test.socket; echo a | nc -U /run/test.ctl; >/testok'
|
||||
StandardOutput=tty
|
||||
StandardError=tty
|
||||
ExecStart=/bin/sh -e -x -c 'rm -f /tmp/nonexistent; systemctl start test.socket; echo > /run/test.ctl; >/testok'
|
||||
TimeoutStartSec=10s
|
||||
EOF
|
||||
|
||||
cat >$initdir/etc/systemd/system/test.socket <<'EOF'
|
||||
[Socket]
|
||||
ListenStream=/run/test.ctl
|
||||
ListenFIFO=/run/test.ctl
|
||||
EOF
|
||||
|
||||
cat > $initdir/etc/systemd/system/test.service <<'EOF'
|
||||
@ -49,6 +50,7 @@ EOF
|
||||
|
||||
setup_testsuite
|
||||
) || return 1
|
||||
setup_nspawn_root
|
||||
|
||||
# mask some services that we do not want to run in these tests
|
||||
ln -s /dev/null $initdir/etc/systemd/system/systemd-hwdb-update.service
|
||||
|
45
test/run-integration-tests.sh
Executable file
45
test/run-integration-tests.sh
Executable file
@ -0,0 +1,45 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
if ! test -d ../build ; then
|
||||
echo "Expected build directory in ../build, but couldn't find it." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ninja -C ../build
|
||||
|
||||
declare -A results
|
||||
|
||||
RESULT=0
|
||||
FAILURES=0
|
||||
|
||||
for TEST in TEST-??-* ; do
|
||||
echo -e "\n--x-- Starting $TEST --x--"
|
||||
set +e
|
||||
make -C "$TEST" BUILD_DIR=$(pwd)/../build clean setup run
|
||||
RESULT=$?
|
||||
set -e
|
||||
echo "--x-- Result of $TEST: $RESULT --x--"
|
||||
|
||||
results["$TEST"]="$RESULT"
|
||||
|
||||
[ "$RESULT" -ne "0" ] && FAILURES=$(($FAILURES+1))
|
||||
done
|
||||
|
||||
echo ""
|
||||
|
||||
for TEST in ${!results[@]}; do
|
||||
RESULT="${results[$TEST]}"
|
||||
if [ "$RESULT" -eq "0" ] ; then
|
||||
echo "$TEST: SUCCESS"
|
||||
else
|
||||
echo "$TEST: FAIL"
|
||||
fi
|
||||
done | sort
|
||||
|
||||
if [ "$FAILURES" -eq 0 ] ; then
|
||||
echo -e "\nALL PASSED"
|
||||
else
|
||||
echo -e "\nTOTAL FAILURES: $FAILURES"
|
||||
fi
|
||||
|
||||
exit "$FAILURES"
|
Loading…
Reference in New Issue
Block a user