mirror of
https://github.com/systemd/systemd.git
synced 2024-10-28 20:25:38 +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:
parent
14eb41b2a4
commit
c4b4170746
@ -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>
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 }
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user