From 835552511ef5edec94b567441251ada2a37ea333 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 22 Nov 2016 20:19:08 +0100 Subject: [PATCH] core: hook up MountFlags= to the transient unit logic This makes "systemd-run -p MountFlags=shared -t /bin/sh" work, by making MountFlags= to the list of properties that may be accessed transiently. --- .gitignore | 1 + Makefile.am | 7 ++++++ src/basic/mount-util.c | 32 +++++++++++++++++++++++++++ src/basic/mount-util.h | 3 +++ src/core/dbus-execute.c | 18 ++++++++++++++- src/core/load-fragment.c | 39 +++++++++++++++++---------------- src/shared/bus-unit-util.c | 17 +++++++++++++- src/test/test-mount-util.c | 45 ++++++++++++++++++++++++++++++++++++++ 8 files changed, 141 insertions(+), 21 deletions(-) create mode 100644 src/test/test-mount-util.c diff --git a/.gitignore b/.gitignore index 016ba625e3..ec4b7bd672 100644 --- a/.gitignore +++ b/.gitignore @@ -239,6 +239,7 @@ /test-loopback /test-machine-tables /test-mmap-cache +/test-mount-util /test-namespace /test-ndisc-rs /test-netlink diff --git a/Makefile.am b/Makefile.am index 3bd8c29dd3..8f7b83f0ab 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1512,6 +1512,7 @@ tests += \ test-utf8 \ test-ellipsize \ test-util \ + test-mount-util \ test-cpu-set-util \ test-hexdecoct \ test-escape \ @@ -1890,6 +1891,12 @@ test_util_SOURCES = \ test_util_LDADD = \ libsystemd-shared.la +test_mount_util_SOURCES = \ + src/test/test-mount-util.c + +test_mount_util_LDADD = \ + libsystemd-shared.la + test_hexdecoct_SOURCES = \ src/test/test-hexdecoct.c diff --git a/src/basic/mount-util.c b/src/basic/mount-util.c index 352c3505fb..8970050408 100644 --- a/src/basic/mount-util.c +++ b/src/basic/mount-util.c @@ -689,3 +689,35 @@ int umount_verbose(const char *what) { return log_error_errno(errno, "Failed to unmount %s: %m", what); return 0; } + +const char *mount_propagation_flags_to_string(unsigned long flags) { + + switch (flags & (MS_SHARED|MS_SLAVE|MS_PRIVATE)) { + + case MS_SHARED: + return "shared"; + + case MS_SLAVE: + return "slave"; + + case MS_PRIVATE: + return "private"; + } + + return NULL; +} + +unsigned long mount_propagation_flags_from_string(const char *name) { + + if (isempty(name)) + return 0; + + if (streq(name, "shared")) + return MS_SHARED; + if (streq(name, "slave")) + return MS_SLAVE; + if (streq(name, "private")) + return MS_PRIVATE; + + return 0; +} diff --git a/src/basic/mount-util.h b/src/basic/mount-util.h index b840956d63..c8049198d4 100644 --- a/src/basic/mount-util.h +++ b/src/basic/mount-util.h @@ -61,3 +61,6 @@ int mount_verbose( unsigned long flags, const char *options); int umount_verbose(const char *where); + +const char *mount_propagation_flags_to_string(unsigned long flags); +unsigned long mount_propagation_flags_from_string(const char *name); diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 23c1b44573..78b177e107 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -34,6 +34,7 @@ #include "fileio.h" #include "ioprio.h" #include "missing.h" +#include "mount-util.h" #include "namespace.h" #include "parse-util.h" #include "path-util.h" @@ -1613,8 +1614,23 @@ int bus_exec_context_set_transient_property( } return 1; - } + } else if (streq(name, "MountFlags")) { + uint64_t flags; + r = sd_bus_message_read(message, "t", &flags); + if (r < 0) + return r; + if (!IN_SET(flags, 0, MS_SHARED, MS_PRIVATE, MS_SLAVE)) + return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unknown mount propagation flags"); + + if (mode != UNIT_CHECK) { + c->mount_flags = flags; + + unit_write_drop_in_private_format(u, mode, name, "%s=%s", name, strempty(mount_propagation_flags_to_string(flags))); + } + + return 1; + } ri = rlimit_from_string(name); if (ri < 0) { soft = endswith(name, "Soft"); diff --git a/src/core/load-fragment.c b/src/core/load-fragment.c index 687cd1dd31..a2e7097de0 100644 --- a/src/core/load-fragment.c +++ b/src/core/load-fragment.c @@ -49,6 +49,7 @@ #include "load-fragment.h" #include "log.h" #include "missing.h" +#include "mount-util.h" #include "parse-util.h" #include "path-util.h" #include "process-util.h" @@ -1264,19 +1265,20 @@ int config_parse_sysv_priority(const char *unit, DEFINE_CONFIG_PARSE_ENUM(config_parse_exec_utmp_mode, exec_utmp_mode, ExecUtmpMode, "Failed to parse utmp mode"); DEFINE_CONFIG_PARSE_ENUM(config_parse_kill_mode, kill_mode, KillMode, "Failed to parse kill mode"); -int config_parse_exec_mount_flags(const char *unit, - const char *filename, - unsigned line, - const char *section, - unsigned section_line, - const char *lvalue, - int ltype, - const char *rvalue, - void *data, - void *userdata) { +int config_parse_exec_mount_flags( + const char *unit, + const char *filename, + unsigned line, + const char *section, + unsigned section_line, + const char *lvalue, + int ltype, + const char *rvalue, + void *data, + void *userdata) { - unsigned long flags = 0; + unsigned long flags; ExecContext *c = data; assert(filename); @@ -1284,15 +1286,14 @@ int config_parse_exec_mount_flags(const char *unit, assert(rvalue); assert(data); - if (streq(rvalue, "shared")) - flags = MS_SHARED; - else if (streq(rvalue, "slave")) - flags = MS_SLAVE; - else if (streq(rvalue, "private")) - flags = MS_PRIVATE; + if (isempty(rvalue)) + flags = 0; else { - log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring.", rvalue); - return 0; + flags = mount_propagation_flags_from_string(rvalue); + if (flags == 0) { + log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse mount flag %s, ignoring.", rvalue); + return 0; + } } c->mount_flags = flags; diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c index 3114275c85..6dd9f2ccd4 100644 --- a/src/shared/bus-unit-util.c +++ b/src/shared/bus-unit-util.c @@ -27,6 +27,7 @@ #include "hashmap.h" #include "list.h" #include "locale-util.h" +#include "mount-util.h" #include "nsflags.h" #include "parse-util.h" #include "path-util.h" @@ -575,7 +576,21 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen r = sd_bus_message_append(m, "v", "t", flags); } else if ((dep = unit_dependency_from_string(field)) >= 0) r = sd_bus_message_append(m, "v", "as", 1, eq); - else { + else if (streq(field, "MountFlags")) { + unsigned long f; + + if (isempty(eq)) + f = 0; + else { + f = mount_propagation_flags_from_string(eq); + if (f == 0) { + log_error("Failed to parse mount propagation type: %s", eq); + return -EINVAL; + } + } + + r = sd_bus_message_append(m, "v", "t", f); + } else { log_error("Unknown assignment %s.", assignment); return -EINVAL; } diff --git a/src/test/test-mount-util.c b/src/test/test-mount-util.c new file mode 100644 index 0000000000..da7f35623b --- /dev/null +++ b/src/test/test-mount-util.c @@ -0,0 +1,45 @@ +/*** + This file is part of systemd. + + Copyright 2016 Lennart Poettering + + systemd is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1 of the License, or + (at your option) any later version. + + systemd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with systemd; If not, see . +***/ + +#include + +#include "log.h" +#include "mount-util.h" +#include "string-util.h" + +static void test_mount_propagation_flags(const char *name, unsigned long f) { + assert(mount_propagation_flags_from_string(name) == f); + + if (f != 0) + assert_se(streq_ptr(mount_propagation_flags_to_string(f), name)); +} + +int main(int argc, char *argv[]) { + + log_set_max_level(LOG_DEBUG); + + test_mount_propagation_flags("shared", MS_SHARED); + test_mount_propagation_flags("slave", MS_SLAVE); + test_mount_propagation_flags("private", MS_PRIVATE); + test_mount_propagation_flags(NULL, 0); + test_mount_propagation_flags("", 0); + test_mount_propagation_flags("xxxx", 0); + + return 0; +}