1
1
mirror of https://github.com/systemd/systemd-stable.git synced 2024-10-28 03:25:27 +03:00

namespace: unify limit behavior on non-directory paths

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
This commit is contained in:
Alessandro Puccetti 2016-07-06 09:48:58 +02:00
parent 14eb41b2a4
commit c4b4170746
6 changed files with 68 additions and 23 deletions

View File

@ -855,24 +855,26 @@
<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>

View 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;
}

View 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 }

View 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);

View 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;
}

View 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) {