]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
core: on DynamicUser= make sure that protecting sensitive paths is enforced (#4596)
authorDjalal Harouni <tixxdz@opendz.org>
Sun, 6 Nov 2016 22:31:55 +0000 (23:31 +0100)
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>
Wed, 9 Nov 2016 02:57:32 +0000 (21:57 -0500)
This adds a variable that is always set to false to make sure that
protect paths inside sandbox are always enforced and not ignored. The only
case when it is set to true is on DynamicUser=no and RootDirectory=/chroot
is set. This allows users to use more our sandbox features inside RootDirectory=

The only exception is ProtectSystem=full|strict and when DynamicUser=yes
is implied. Currently RootDirectory= is not fully compatible with these
due to two reasons:

* /chroot/usr|etc has to be present on ProtectSystem=full
* /chroot// has to be a mount point on ProtectSystem=strict.

src/core/execute.c
src/core/namespace.c
src/core/namespace.h

index 8015aa2cb9f144fd2096107182bd21bda6d9dc7c..f666f7c6ce0de9373b38666cdfcf42456f2eb087 100644 (file)
@@ -2034,6 +2034,7 @@ static int apply_mount_namespace(Unit *u, const ExecContext *context,
         char *tmp = NULL, *var = NULL;
         const char *root_dir = NULL;
         NameSpaceInfo ns_info = {
+                .ignore_protect_paths = false,
                 .private_dev = context->private_devices,
                 .protect_control_groups = context->protect_control_groups,
                 .protect_kernel_tunables = context->protect_kernel_tunables,
@@ -2060,6 +2061,14 @@ static int apply_mount_namespace(Unit *u, const ExecContext *context,
         if (params->flags & EXEC_APPLY_CHROOT)
                 root_dir = context->root_directory;
 
+        /*
+         * If DynamicUser=no and RootDirectory= is set then lets pass a relaxed
+         * sandbox info, otherwise enforce it, don't ignore protected paths and
+         * fail if we are enable to apply the sandbox inside the mount namespace.
+         */
+        if (!context->dynamic_user && root_dir)
+                ns_info.ignore_protect_paths = true;
+
         r = setup_namespace(root_dir, &ns_info, rw,
                             context->read_only_paths,
                             context->inaccessible_paths,
index f361e139ace918b636bbdfd6909f72b4bdded619..308e4d768e4320adec22e2808b5ba6b00e45f4d5 100644 (file)
@@ -200,13 +200,15 @@ static int append_mounts(BindMount **p, char **strv, MountMode mode) {
         return 0;
 }
 
-static int append_target_mounts(BindMount **p, const char *root_directory, const TargetMount *mounts, const size_t size) {
+static int append_target_mounts(BindMount **p, const char *root_directory,
+                                const TargetMount *mounts, const size_t size, bool ignore_protect) {
         unsigned i;
 
         assert(p);
         assert(mounts);
 
         for (i = 0; i < size; i++) {
+                bool ignore;
                 /*
                  * Here we assume that the ignore field is set during
                  * declaration we do not support "-" at the beginning.
@@ -221,27 +223,33 @@ static int append_target_mounts(BindMount **p, const char *root_directory, const
                 if (!path_is_absolute(path))
                         return -EINVAL;
 
-                set_bind_mount((*p)++, path, m->mode, m->ignore);
+                /*
+                 * Ignore paths if they are not present. First we use our
+                 * static tables otherwise fallback to Unit context.
+                 */
+                ignore = m->ignore || ignore_protect;
+
+                set_bind_mount((*p)++, path, m->mode, ignore);
         }
 
         return 0;
 }
 
-static int append_protect_kernel_tunables(BindMount **p, const char *root_directory) {
+static int append_protect_kernel_tunables(BindMount **p, const char *root_directory, bool ignore_protect) {
         assert(p);
 
         return append_target_mounts(p, root_directory, protect_kernel_tunables_table,
-                                    ELEMENTSOF(protect_kernel_tunables_table));
+                                    ELEMENTSOF(protect_kernel_tunables_table), ignore_protect);
 }
 
-static int append_protect_kernel_modules(BindMount **p, const char *root_directory) {
+static int append_protect_kernel_modules(BindMount **p, const char *root_directory, bool ignore_protect) {
         assert(p);
 
         return append_target_mounts(p, root_directory, protect_kernel_modules_table,
-                                    ELEMENTSOF(protect_kernel_modules_table));
+                                    ELEMENTSOF(protect_kernel_modules_table), ignore_protect);
 }
 
-static int append_protect_home(BindMount **p, const char *root_directory, ProtectHome protect_home) {
+static int append_protect_home(BindMount **p, const char *root_directory, ProtectHome protect_home, bool ignore_protect) {
         int r = 0;
 
         assert(p);
@@ -252,11 +260,12 @@ static int append_protect_home(BindMount **p, const char *root_directory, Protec
         switch (protect_home) {
         case PROTECT_HOME_READ_ONLY:
                 r = append_target_mounts(p, root_directory, protect_home_read_only_table,
-                                         ELEMENTSOF(protect_home_read_only_table));
+                                         ELEMENTSOF(protect_home_read_only_table),
+                                         ignore_protect);
                 break;
         case PROTECT_HOME_YES:
                 r = append_target_mounts(p, root_directory, protect_home_yes_table,
-                                         ELEMENTSOF(protect_home_yes_table));
+                                         ELEMENTSOF(protect_home_yes_table), ignore_protect);
                 break;
         default:
                 r = -EINVAL;
@@ -266,7 +275,7 @@ static int append_protect_home(BindMount **p, const char *root_directory, Protec
         return r;
 }
 
-static int append_protect_system(BindMount **p, const char *root_directory, ProtectSystem protect_system) {
+static int append_protect_system(BindMount **p, const char *root_directory, ProtectSystem protect_system, bool ignore_protect) {
         int r = 0;
 
         assert(p);
@@ -277,15 +286,15 @@ static int append_protect_system(BindMount **p, const char *root_directory, Prot
         switch (protect_system) {
         case PROTECT_SYSTEM_STRICT:
                 r = append_target_mounts(p, root_directory, protect_system_strict_table,
-                                         ELEMENTSOF(protect_system_strict_table));
+                                         ELEMENTSOF(protect_system_strict_table), ignore_protect);
                 break;
         case PROTECT_SYSTEM_YES:
                 r = append_target_mounts(p, root_directory, protect_system_yes_table,
-                                         ELEMENTSOF(protect_system_yes_table));
+                                         ELEMENTSOF(protect_system_yes_table), ignore_protect);
                 break;
         case PROTECT_SYSTEM_FULL:
                 r = append_target_mounts(p, root_directory, protect_system_full_table,
-                                         ELEMENTSOF(protect_system_full_table));
+                                         ELEMENTSOF(protect_system_full_table), ignore_protect);
                 break;
         default:
                 r = -EINVAL;
@@ -614,7 +623,6 @@ static int apply_mount(
                         return log_debug_errno(r, "Failed to determine whether %s is already a mount point: %m", m->path);
                 if (r > 0) /* Nothing to do here, it is already a mount. We just later toggle the MS_RDONLY bit for the mount point if needed. */
                         return 0;
-
                 /* This isn't a mount point yet, let's make it one. */
                 what = m->path;
                 break;
@@ -801,13 +809,15 @@ int setup_namespace(
                 }
 
                 if (ns_info->protect_kernel_tunables) {
-                        r = append_protect_kernel_tunables(&m, root_directory);
+                        r = append_protect_kernel_tunables(&m, root_directory,
+                                                           ns_info->ignore_protect_paths);
                         if (r < 0)
                                 goto finish;
                 }
 
                 if (ns_info->protect_kernel_modules) {
-                        r = append_protect_kernel_modules(&m, root_directory);
+                        r = append_protect_kernel_modules(&m, root_directory,
+                                                          ns_info->ignore_protect_paths);
                         if (r < 0)
                                 goto finish;
                 }
@@ -818,11 +828,12 @@ int setup_namespace(
                                 goto finish;
                 }
 
-                r = append_protect_home(&m, root_directory, protect_home);
+                r = append_protect_home(&m, root_directory, protect_home,
+                                        ns_info->ignore_protect_paths);
                 if (r < 0)
                         goto finish;
 
-                r = append_protect_system(&m, root_directory, protect_system);
+                r = append_protect_system(&m, root_directory, protect_system, false);
                 if (r < 0)
                         goto finish;
 
index 6310638e9ad8a49618a8783f3a7db8bcd76f738a..2c278fd457cf82e98d8dc16f2d2f3ff3d1f9fc02 100644 (file)
@@ -44,6 +44,7 @@ typedef enum ProtectSystem {
 } ProtectSystem;
 
 struct NameSpaceInfo {
+        bool ignore_protect_paths:1;
         bool private_dev:1;
         bool protect_control_groups:1;
         bool protect_kernel_tunables:1;