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.
This commit is contained in:
Lennart Poettering 2016-11-22 20:19:08 +01:00
parent 9ef4e1e5a2
commit 835552511e
8 changed files with 141 additions and 21 deletions

1
.gitignore vendored
View File

@ -239,6 +239,7 @@
/test-loopback
/test-machine-tables
/test-mmap-cache
/test-mount-util
/test-namespace
/test-ndisc-rs
/test-netlink

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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");

View File

@ -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;

View File

@ -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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
***/
#include <sys/mount.h>
#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;
}