From: Lennart Poettering Date: Tue, 7 Jan 2020 15:25:11 +0000 (+0100) Subject: namespace: tweak checks whether we can mount image read-only X-Git-Tag: v245-rc1~150^2~1 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=c8c535d589cce28f586e03a291be93cb2e48cb97;p=thirdparty%2Fsystemd.git namespace: tweak checks whether we can mount image read-only So far we set up a loopback file read-only iff ProtectSystem= and ProtectHome= both where set to values that mark these dirs read-only. Let's extend that and also be happy if /home and the root dir are marked read-only by some other means. Fixes: #14442 --- diff --git a/src/core/namespace.c b/src/core/namespace.c index fee4c980964..fd38174ac02 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -1190,6 +1190,57 @@ static void normalize_mounts(const char *root_directory, MountEntry *mounts, siz drop_nop(mounts, n_mounts); } +static bool root_read_only( + char **read_only_paths, + ProtectSystem protect_system) { + + /* Determine whether the root directory is going to be read-only given the configured settings. */ + + if (protect_system == PROTECT_SYSTEM_STRICT) + return true; + + if (path_strv_contains(read_only_paths, "/")) + return true; + + return false; +} + +static bool home_read_only( + char** read_only_paths, + char** inaccessible_paths, + char** empty_directories, + const BindMount *bind_mounts, + size_t n_bind_mounts, + const TemporaryFileSystem *temporary_filesystems, + size_t n_temporary_filesystems, + ProtectHome protect_home) { + + size_t i; + + /* Determine whether the /home directory is going to be read-only given the configured settings. Yes, + * this is a bit sloppy, since we don't bother checking for cases where / is affected by multiple + * settings. */ + + if (protect_home != PROTECT_HOME_NO) + return true; + + if (path_strv_contains(read_only_paths, "/home") || + path_strv_contains(inaccessible_paths, "/home") || + path_strv_contains(empty_directories, "/home")) + return true; + + for (i = 0; i < n_temporary_filesystems; i++) + if (path_equal(temporary_filesystems[i].path, "/home")) + return true; + + /* If /home is overmounted with some dir from the host it's not writable. */ + for (i = 0; i < n_bind_mounts; i++) + if (path_equal(bind_mounts[i].destination, "/home")) + return true; + + return false; +} + int setup_namespace( const char* root_directory, const char* root_image, @@ -1228,8 +1279,12 @@ int setup_namespace( if (root_image) { dissect_image_flags |= DISSECT_IMAGE_REQUIRE_ROOT; - if (protect_system == PROTECT_SYSTEM_STRICT && - protect_home != PROTECT_HOME_NO && + /* Make the whole image read-only if we can determine that we only access it in a read-only fashion. */ + if (root_read_only(read_only_paths, + protect_system) && + home_read_only(read_only_paths, inaccessible_paths, empty_directories, + bind_mounts, n_bind_mounts, temporary_filesystems, n_temporary_filesystems, + protect_home) && strv_isempty(read_write_paths)) dissect_image_flags |= DISSECT_IMAGE_READ_ONLY;