From e4da7d8c796a1fd11ecfa80fb8a48eac9e823f06 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 21 Feb 2018 09:13:11 +0900 Subject: [PATCH] core: add new option 'tmpfs' to ProtectHome= This make ProtectHome= setting can take 'tmpfs'. This is mostly equivalent to `TemporaryFileSystem=/home /run/user /root`. --- man/systemd.exec.xml | 26 ++++++++++++++++++-------- src/core/namespace.c | 15 ++++++++++++++- src/core/namespace.h | 1 + 3 files changed, 33 insertions(+), 9 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 169a4496325..3e4a7f33590 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -788,14 +788,24 @@ CapabilityBoundingSet=~CAP_B CAP_C ProtectHome= - Takes a boolean argument or read-only. If true, the directories - /home, /root and /run/user are made inaccessible - and empty for processes invoked by this unit. If set to read-only, the three directories are - made read-only instead. It is recommended to enable this setting for all long-running services (in particular - network-facing ones), to ensure they cannot get access to private user data, unless the services actually - require access to the user's private data. This setting is implied if DynamicUser= is - set. For this setting the same restrictions regarding mount propagation and privileges apply as for - ReadOnlyPaths= and related calls, see below. + Takes a boolean argument or the special values read-only or + tmpfs. If true, the directories /home, /root and + /run/user are made inaccessible and empty for processes invoked by this unit. If set to + read-only, the three directories are made read-only instead. If set to tmpfs, + temporary file systems are mounted on the three directories in read-only mode. The value tmpfs + is useful to hide home directories not relevant to the processes invoked by the unit, while necessary directories + are still visible by combining with BindPaths= or BindReadOnlyPaths=. + + Setting this to yes is mostly equivalent to set the three directories in + InaccessiblePaths=. Similary, read-only is mostly equivalent to + ReadOnlyPaths=, and tmpfs is mostly equivalent to + TemporaryFileSystem=. + + It is recommended to enable this setting for all long-running services (in particular network-facing ones), + to ensure they cannot get access to private user data, unless the services actually require access to the user's + private data. This setting is implied if DynamicUser= is set. For this setting the same + restrictions regarding mount propagation and privileges apply as for ReadOnlyPaths= and related + calls, see below. diff --git a/src/core/namespace.c b/src/core/namespace.c index 2d82a0778cf..f605d239bc2 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -128,6 +128,13 @@ static const MountEntry protect_home_read_only_table[] = { { "/root", READONLY, true }, }; +/* ProtectHome=tmpfs table */ +static const MountEntry protect_home_tmpfs_table[] = { + { "/home", TMPFS, true, .read_only = true, .options_const = "mode=0755", .flags = MS_NODEV|MS_STRICTATIME }, + { "/run/user", TMPFS, true, .read_only = true, .options_const = "mode=0755", .flags = MS_NODEV|MS_STRICTATIME }, + { "/root", TMPFS, true, .read_only = true, .options_const = "mode=0700", .flags = MS_NODEV|MS_STRICTATIME }, +}; + /* ProtectHome=yes table */ static const MountEntry protect_home_yes_table[] = { { "/home", INACCESSIBLE, true }, @@ -354,6 +361,9 @@ static int append_protect_home(MountEntry **p, ProtectHome protect_home, bool ig case PROTECT_HOME_READ_ONLY: return append_static_mounts(p, protect_home_read_only_table, ELEMENTSOF(protect_home_read_only_table), ignore_protect); + case PROTECT_HOME_TMPFS: + return append_static_mounts(p, protect_home_tmpfs_table, ELEMENTSOF(protect_home_tmpfs_table), ignore_protect); + case PROTECT_HOME_YES: return append_static_mounts(p, protect_home_yes_table, ELEMENTSOF(protect_home_yes_table), ignore_protect); @@ -1011,7 +1021,9 @@ static unsigned namespace_calculate_mounts( (protect_home == PROTECT_HOME_YES ? ELEMENTSOF(protect_home_yes_table) : ((protect_home == PROTECT_HOME_READ_ONLY) ? - ELEMENTSOF(protect_home_read_only_table) : 0)); + ELEMENTSOF(protect_home_read_only_table) : + ((protect_home == PROTECT_HOME_TMPFS) ? + ELEMENTSOF(protect_home_tmpfs_table) : 0))); return !!tmp_dir + !!var_tmp_dir + strv_length(read_write_paths) + @@ -1576,6 +1588,7 @@ static const char *const protect_home_table[_PROTECT_HOME_MAX] = { [PROTECT_HOME_NO] = "no", [PROTECT_HOME_YES] = "yes", [PROTECT_HOME_READ_ONLY] = "read-only", + [PROTECT_HOME_TMPFS] = "tmpfs", }; DEFINE_STRING_TABLE_LOOKUP(protect_home, ProtectHome); diff --git a/src/core/namespace.h b/src/core/namespace.h index df7be7d1f2a..3d56a7302dc 100644 --- a/src/core/namespace.h +++ b/src/core/namespace.h @@ -34,6 +34,7 @@ typedef enum ProtectHome { PROTECT_HOME_NO, PROTECT_HOME_YES, PROTECT_HOME_READ_ONLY, + PROTECT_HOME_TMPFS, _PROTECT_HOME_MAX, _PROTECT_HOME_INVALID = -1 } ProtectHome; -- 2.39.2