Merge pull request #11283 from yuwata/fix-11276

core/namespace: introduce new mount mode READWRITE_IMPLICIT
This commit is contained in:
Lennart Poettering
2019-03-13 09:57:18 +01:00
committed by GitHub
4 changed files with 70 additions and 32 deletions
+55 -32
View File
@@ -49,6 +49,8 @@ typedef enum MountMode {
READONLY,
READWRITE,
TMPFS,
READWRITE_IMPLICIT, /* Should have the lowest priority. */
_MOUNT_MODE_MAX,
} MountMode;
typedef struct MountEntry {
@@ -77,26 +79,26 @@ static const MountEntry apivfs_table[] = {
/* ProtectKernelTunables= option and the related filesystem APIs */
static const MountEntry protect_kernel_tunables_table[] = {
{ "/proc/acpi", READONLY, true },
{ "/proc/apm", READONLY, true }, /* Obsolete API, there's no point in permitting access to this, ever */
{ "/proc/asound", READONLY, true },
{ "/proc/bus", READONLY, true },
{ "/proc/fs", READONLY, true },
{ "/proc/irq", READONLY, true },
{ "/proc/kallsyms", INACCESSIBLE, true },
{ "/proc/kcore", INACCESSIBLE, true },
{ "/proc/latency_stats", READONLY, true },
{ "/proc/mtrr", READONLY, true },
{ "/proc/scsi", READONLY, true },
{ "/proc/sys", READONLY, false },
{ "/proc/sysrq-trigger", READONLY, true },
{ "/proc/timer_stats", READONLY, true },
{ "/sys", READONLY, false },
{ "/sys/fs/bpf", READONLY, true },
{ "/sys/fs/cgroup", READWRITE, false }, /* READONLY is set by ProtectControlGroups= option */
{ "/sys/fs/selinux", READWRITE, true },
{ "/sys/kernel/debug", READONLY, true },
{ "/sys/kernel/tracing", READONLY, true },
{ "/proc/acpi", READONLY, true },
{ "/proc/apm", READONLY, true }, /* Obsolete API, there's no point in permitting access to this, ever */
{ "/proc/asound", READONLY, true },
{ "/proc/bus", READONLY, true },
{ "/proc/fs", READONLY, true },
{ "/proc/irq", READONLY, true },
{ "/proc/kallsyms", INACCESSIBLE, true },
{ "/proc/kcore", INACCESSIBLE, true },
{ "/proc/latency_stats", READONLY, true },
{ "/proc/mtrr", READONLY, true },
{ "/proc/scsi", READONLY, true },
{ "/proc/sys", READONLY, false },
{ "/proc/sysrq-trigger", READONLY, true },
{ "/proc/timer_stats", READONLY, true },
{ "/sys", READONLY, false },
{ "/sys/fs/bpf", READONLY, true },
{ "/sys/fs/cgroup", READWRITE_IMPLICIT, false }, /* READONLY is set by ProtectControlGroups= option */
{ "/sys/fs/selinux", READWRITE_IMPLICIT, true },
{ "/sys/kernel/debug", READONLY, true },
{ "/sys/kernel/tracing", READONLY, true },
};
/* ProtectKernelModules= option */
@@ -171,15 +173,33 @@ static const MountEntry protect_system_full_table[] = {
* shall manage those, orthogonally).
*/
static const MountEntry protect_system_strict_table[] = {
{ "/", READONLY, false },
{ "/proc", READWRITE, false }, /* ProtectKernelTunables= */
{ "/sys", READWRITE, false }, /* ProtectKernelTunables= */
{ "/dev", READWRITE, false }, /* PrivateDevices= */
{ "/home", READWRITE, true }, /* ProtectHome= */
{ "/run/user", READWRITE, true }, /* ProtectHome= */
{ "/root", READWRITE, true }, /* ProtectHome= */
{ "/", READONLY, false },
{ "/proc", READWRITE_IMPLICIT, false }, /* ProtectKernelTunables= */
{ "/sys", READWRITE_IMPLICIT, false }, /* ProtectKernelTunables= */
{ "/dev", READWRITE_IMPLICIT, false }, /* PrivateDevices= */
{ "/home", READWRITE_IMPLICIT, true }, /* ProtectHome= */
{ "/run/user", READWRITE_IMPLICIT, true }, /* ProtectHome= */
{ "/root", READWRITE_IMPLICIT, true }, /* ProtectHome= */
};
static const char * const mount_mode_table[_MOUNT_MODE_MAX] = {
[INACCESSIBLE] = "inaccessible",
[BIND_MOUNT] = "bind",
[BIND_MOUNT_RECURSIVE] = "rbind",
[PRIVATE_TMP] = "private-tmp",
[PRIVATE_DEV] = "private-dev",
[BIND_DEV] = "bind-dev",
[EMPTY_DIR] = "empty",
[SYSFS] = "sysfs",
[PROCFS] = "procfs",
[READONLY] = "read-only",
[READWRITE] = "read-write",
[TMPFS] = "tmpfs",
[READWRITE_IMPLICIT] = "rw-implicit",
};
DEFINE_PRIVATE_STRING_TABLE_LOOKUP_TO_STRING(mount_mode, MountMode);
static const char *mount_entry_path(const MountEntry *p) {
assert(p);
@@ -220,7 +240,7 @@ static int append_access_mounts(MountEntry **p, char **strv, MountMode mode, boo
assert(p);
/* Adds a list of user-supplied READWRITE/READONLY/INACCESSIBLE entries */
/* Adds a list of user-supplied READWRITE/READWRITE_IMPLICIT/READONLY/INACCESSIBLE entries */
STRV_FOREACH(i, strv) {
bool ignore = false, needs_prefix = false;
@@ -446,7 +466,7 @@ static void drop_duplicates(MountEntry *m, size_t *n) {
if (previous &&
path_equal(mount_entry_path(f), mount_entry_path(previous)) &&
!f->applied && !previous->applied) {
log_debug("%s is duplicate.", mount_entry_path(f));
log_debug("%s (%s) is duplicate.", mount_entry_path(f), mount_mode_to_string(f->mode));
previous->read_only = previous->read_only || mount_entry_read_only(f); /* Propagate the read-only flag to the remaining entry */
mount_entry_done(f);
continue;
@@ -500,8 +520,8 @@ static void drop_nop(MountEntry *m, size_t *n) {
for (f = m, t = m; f < m + *n; f++) {
/* Only suppress such subtrees for READONLY and READWRITE entries */
if (IN_SET(f->mode, READONLY, READWRITE)) {
/* Only suppress such subtrees for READONLY, READWRITE and READWRITE_IMPLICIT entries */
if (IN_SET(f->mode, READONLY, READWRITE, READWRITE_IMPLICIT)) {
MountEntry *p;
bool found = false;
@@ -515,7 +535,9 @@ static void drop_nop(MountEntry *m, size_t *n) {
/* We found it, let's see if it's the same mode, if so, we can drop this entry */
if (found && p->mode == f->mode) {
log_debug("%s is redundant by %s", mount_entry_path(f), mount_entry_path(p));
log_debug("%s (%s) is made redundant by %s (%s)",
mount_entry_path(f), mount_mode_to_string(f->mode),
mount_entry_path(p), mount_mode_to_string(p->mode));
mount_entry_done(f);
continue;
}
@@ -908,6 +930,7 @@ static int apply_mount(
case READONLY:
case READWRITE:
case READWRITE_IMPLICIT:
r = path_is_mount_point(mount_entry_path(m), root_directory, 0);
if (r == -ENOENT && m->ignore)
return 0;
+5
View File
@@ -269,6 +269,10 @@ static void test_exec_privatedevices(Manager *m) {
test(m, "exec-privatedevices-no-capability-sys-rawio.service", 0, CLD_EXITED);
}
static void test_exec_protecthome(Manager *m) {
test(m, "exec-protecthome-tmpfs-vs-protectsystem-strict.service", can_unshare ? 0 : EXIT_FAILURE, CLD_EXITED);
}
static void test_exec_protectkernelmodules(Manager *m) {
int r;
@@ -732,6 +736,7 @@ int main(int argc, char *argv[]) {
test_exec_privatedevices,
test_exec_privatenetwork,
test_exec_privatetmp,
test_exec_protecthome,
test_exec_protectkernelmodules,
test_exec_readonlypaths,
test_exec_readwritepaths,
+1
View File
@@ -94,6 +94,7 @@ test_data_files = '''
test-execute/exec-privatenetwork-yes.service
test-execute/exec-privatetmp-no.service
test-execute/exec-privatetmp-yes.service
test-execute/exec-protecthome-tmpfs-vs-protectsystem-strict.service
test-execute/exec-protectkernelmodules-no-capabilities.service
test-execute/exec-protectkernelmodules-yes-capabilities.service
test-execute/exec-protectkernelmodules-yes-mount-propagation.service
@@ -0,0 +1,9 @@
[Unit]
Description=Test ProtectHome=tmpfs vs ProtectSystem=strict
# Test for #11276
[Service]
ProtectHome=tmpfs
ProtectSystem=strict
Type=oneshot
ExecStart=/bin/sh -x -c 'test "$$(stat -fc %%T /home)" = "tmpfs"'