Merge pull request #11283 from yuwata/fix-11276
core/namespace: introduce new mount mode READWRITE_IMPLICIT
This commit is contained in:
+55
-32
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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"'
|
||||
Reference in New Issue
Block a user