]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
namespace: unify limit behavior on non-directory paths
authorAlessandro Puccetti <alessandro@kinvolk.io>
Wed, 6 Jul 2016 07:48:58 +0000 (09:48 +0200)
committerAlessandro Puccetti <alessandro@kinvolk.io>
Tue, 19 Jul 2016 15:22:02 +0000 (17:22 +0200)
Despite the name, `Read{Write,Only}Directories=` already allows for
regular file paths to be masked. This commit adds the same behavior
to `InaccessibleDirectories=` and makes it explicit in the doc.
This patch introduces `/run/systemd/inaccessible/{reg,dir,chr,blk,fifo,sock}`
{dile,device}nodes and mounts on the appropriate one the paths specified
in `InacessibleDirectories=`.

Based on Luca's patch from https://github.com/systemd/systemd/pull/3327

man/systemd.exec.xml
src/basic/mount-util.c
src/basic/mount-util.h
src/core/dbus-execute.c
src/core/mount-setup.c
src/core/namespace.c

index ed02666daf8aaf26a210c259b1cca3f67b5483ff..e9823334340f23484ff8b3ba6c59e964d1a62d9b 100644 (file)
         <listitem><para>Sets up a new file system namespace for
         executed processes. These options may be used to limit access
         a process might have to the main file system hierarchy. Each
-        setting takes a space-separated list of directory paths relative to
+        setting takes a space-separated list of paths relative to
         the host's root directory (i.e. the system running the service manager).
-        Directories listed in
+        Note that if entries contain symlinks, they are resolved from the host's root directory as well.
+        Entries (files or directories) listed in 
         <varname>ReadWriteDirectories=</varname> are accessible from
         within the namespace with the same access rights as from
-        outside. Directories listed in
+        outside. Entries listed in
         <varname>ReadOnlyDirectories=</varname> are accessible for
         reading only, writing will be refused even if the usual file
-        access controls would permit this. Directories listed in
+        access controls would permit this. Entries listed in
         <varname>InaccessibleDirectories=</varname> will be made
         inaccessible for processes inside the namespace, and may not
         countain any other mountpoints, including those specified by
         <varname>ReadWriteDirectories=</varname> or
         <varname>ReadOnlyDirectories=</varname>.
         Note that restricting access with these options does not extend
-        to submounts of a directory that are created later on. These
+        to submounts of a directory that are created later on.
+        Non-directory paths can be specified as well. These
         options may be specified more than once, in which case all
-        directories listed will have limited access from within the
+        paths listed will have limited access from within the
         namespace. If the empty string is assigned to this option, the
         specific list is reset, and all prior assignments have no
         effect.</para>
index 90b7a885a87df82e5c9f72428aed0acacd857ecf..63dff3dd5cb5262ca995b15cbed6956085d566a7 100644 (file)
@@ -532,3 +532,21 @@ int repeat_unmount(const char *path, int flags) {
                 done = true;
         }
 }
+
+const char* mode_to_inaccessible_node(mode_t mode) {
+        switch(mode & S_IFMT) {
+                case S_IFREG:
+                        return "/run/systemd/inaccessible/reg";
+                case S_IFDIR:
+                        return "/run/systemd/inaccessible/dir";
+                case S_IFCHR:
+                        return "/run/systemd/inaccessible/chr";
+                case S_IFBLK:
+                        return "/run/systemd/inaccessible/blk";
+                case S_IFIFO:
+                        return "/run/systemd/inaccessible/fifo";
+                case S_IFSOCK:
+                        return "/run/systemd/inaccessible/sock";
+        }
+        return NULL;
+}
index bdb525d6b0aaa6011695047c6a957304416b0c55..f46989ebb32d25c4996bdf2de96b0ab8a0bbbc9a 100644 (file)
@@ -49,4 +49,6 @@ union file_handle_union {
         char padding[sizeof(struct file_handle) + MAX_HANDLE_SZ];
 };
 
+const char* mode_to_inaccessible_node(mode_t mode);
+
 #define FILE_HANDLE_INIT { .handle.handle_bytes = MAX_HANDLE_SZ }
index 644b9561b570110e9214ee8d01bf5e9b23cc3487..4588ecad09c2a87037efa1b0853c9c8f105c6ad7 100644 (file)
@@ -1346,12 +1346,12 @@ int bus_exec_context_set_transient_property(
                 if (mode != UNIT_CHECK) {
                         _cleanup_free_ char *joined = NULL;
 
-                        if (streq(name, "ReadWriteDirectories"))
-                                dirs = &c->read_write_dirs;
-                        else if (streq(name, "ReadOnlyDirectories"))
-                                dirs = &c->read_only_dirs;
-                        else /* "InaccessibleDirectories" */
-                                dirs = &c->inaccessible_dirs;
+                        if (STR_IN_SET(name, "ReadWriteDirectories", "ReadWritePaths"))
+                                dirs = &c->read_write_paths;
+                        else if (STR_IN_SET(name, "ReadOnlyDirectories", "ReadOnlyPaths"))
+                                dirs = &c->read_only_paths;
+                        else /* "InaccessiblePaths" */
+                                dirs = &c->inaccessible_paths;
 
                         if (strv_length(l) == 0) {
                                 *dirs = strv_free(*dirs);
index f9c9b4a91fff59b84bb5bf39b9d56fd1934586f1..5d8ab0ec706336317803ca0a43974aa4eb1b8546 100644 (file)
@@ -28,6 +28,7 @@
 #include "cgroup-util.h"
 #include "dev-setup.h"
 #include "efivars.h"
+#include "fs-util.h"
 #include "label.h"
 #include "log.h"
 #include "macro.h"
@@ -403,9 +404,16 @@ int mount_setup(bool loaded_policy) {
          * really needs to stay for good, otherwise software that
          * copied sd-daemon.c into their sources will misdetect
          * systemd. */
-        mkdir_label("/run/systemd", 0755);
-        mkdir_label("/run/systemd/system", 0755);
-        mkdir_label("/run/systemd/inaccessible", 0000);
+        (void) mkdir_label("/run/systemd", 0755);
+        (void) mkdir_label("/run/systemd/system", 0755);
+        (void) mkdir_label("/run/systemd/inaccessible", 0000);
+        /* Set up inaccessible items */
+        (void) mknod("/run/systemd/inaccessible/reg", S_IFREG | 0000, 0);
+        (void) mkdir_label("/run/systemd/inaccessible/dir", 0000);
+        (void) mknod("/run/systemd/inaccessible/chr", S_IFCHR | 0000, makedev(0, 0));
+        (void) mknod("/run/systemd/inaccessible/blk", S_IFBLK | 0000, makedev(0, 0));
+        (void) mkfifo("/run/systemd/inaccessible/fifo", 0000);
+        (void) mknod("/run/systemd/inaccessible/sock", S_IFSOCK | 0000, 0);
 
         return 0;
 }
index 203d1228102b06d8a72ae22b7b2af08540e25eb6..e465e825a18bfa2d1b2cf7f957251a8e60768acf 100644 (file)
@@ -278,6 +278,7 @@ static int apply_mount(
 
         const char *what;
         int r;
+        struct stat target;
 
         assert(m);
 
@@ -287,12 +288,22 @@ static int apply_mount(
 
                 /* First, get rid of everything that is below if there
                  * is anything... Then, overmount it with an
-                 * inaccessible directory. */
+                 * inaccessible path. */
                 umount_recursive(m->path, 0);
 
-                what = "/run/systemd/inaccessible";
-                break;
+                r = lstat(m->path, &target);
+                if (r != 0) {
+                        if (m->ignore && errno == ENOENT)
+                                return 0;
+                        return -errno;
+                }
 
+                what = mode_to_inaccessible_node(target.st_mode);
+                if (what == NULL) {
+                        log_debug("File type not supported. Note that symlinks are not allowed");
+                        return -ELOOP;
+                }
+                break;
         case READONLY:
         case READWRITE:
                 /* Nothing to mount here, we just later toggle the
@@ -317,12 +328,16 @@ static int apply_mount(
         assert(what);
 
         r = mount(what, m->path, NULL, MS_BIND|MS_REC, NULL);
-        if (r >= 0)
+        if (r >= 0) {
                 log_debug("Successfully mounted %s to %s", what, m->path);
-        else if (m->ignore && errno == ENOENT)
-                return 0;
-
-        return r;
+                return r;
+        }
+        else {
+                if (m->ignore && errno == ENOENT)
+                        return 0;
+                log_debug("Failed mounting %s to %s: %s", what, m->path, strerror(errno));
+                return -errno;
+        }
 }
 
 static int make_read_only(BindMount *m) {