core:sandbox: lets make /lib/modules/ inaccessible on ProtectKernelModules=
Lets go further and make /lib/modules/ inaccessible for services that do not have business with modules, this is a minor improvment but it may help on setups with custom modules and they are limited... in regard of kernel auto-load feature. This change introduce NameSpaceInfo struct which we may embed later inside ExecContext but for now lets just reduce the argument number to setup_namespace() and merge ProtectKernelModules feature.
This commit is contained in:
parent
ac246d9868
commit
c575770b75
|
@ -1415,7 +1415,10 @@
|
||||||
kernels. It is recomended to turn this on for most services that do not need special
|
kernels. It is recomended to turn this on for most services that do not need special
|
||||||
file systems or extra kernel modules to work. Default to off. Enabling this option
|
file systems or extra kernel modules to work. Default to off. Enabling this option
|
||||||
removes <constant>CAP_SYS_MODULE</constant> from the capability bounding set for
|
removes <constant>CAP_SYS_MODULE</constant> from the capability bounding set for
|
||||||
the unit, and installs a system call filter to block module system calls.
|
the unit, and installs a system call filter to block module system calls,
|
||||||
|
also <filename>/usr/lib/modules</filename> is made inaccessible. For this
|
||||||
|
setting the same restrictions regarding mount propagation and privileges
|
||||||
|
apply as for <varname>ReadOnlyPaths=</varname> and related calls, see above.
|
||||||
Note that limited automatic module loading due to user configuration or kernel
|
Note that limited automatic module loading due to user configuration or kernel
|
||||||
mapping tables might still happen as side effect of requested user operations,
|
mapping tables might still happen as side effect of requested user operations,
|
||||||
both privileged and unprivileged. To disable module auto-load feature please see
|
both privileged and unprivileged. To disable module auto-load feature please see
|
||||||
|
|
|
@ -1766,6 +1766,7 @@ static bool exec_needs_mount_namespace(
|
||||||
context->protect_system != PROTECT_SYSTEM_NO ||
|
context->protect_system != PROTECT_SYSTEM_NO ||
|
||||||
context->protect_home != PROTECT_HOME_NO ||
|
context->protect_home != PROTECT_HOME_NO ||
|
||||||
context->protect_kernel_tunables ||
|
context->protect_kernel_tunables ||
|
||||||
|
context->protect_kernel_modules ||
|
||||||
context->protect_control_groups)
|
context->protect_control_groups)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
@ -2493,6 +2494,12 @@ static int exec_child(
|
||||||
if (needs_mount_namespace) {
|
if (needs_mount_namespace) {
|
||||||
_cleanup_free_ char **rw = NULL;
|
_cleanup_free_ char **rw = NULL;
|
||||||
char *tmp = NULL, *var = NULL;
|
char *tmp = NULL, *var = NULL;
|
||||||
|
NameSpaceInfo ns_info = {
|
||||||
|
.private_dev = context->private_devices,
|
||||||
|
.protect_control_groups = context->protect_control_groups,
|
||||||
|
.protect_kernel_tunables = context->protect_kernel_tunables,
|
||||||
|
.protect_kernel_modules = context->protect_kernel_modules,
|
||||||
|
};
|
||||||
|
|
||||||
/* The runtime struct only contains the parent
|
/* The runtime struct only contains the parent
|
||||||
* of the private /tmp, which is
|
* of the private /tmp, which is
|
||||||
|
@ -2515,14 +2522,12 @@ static int exec_child(
|
||||||
|
|
||||||
r = setup_namespace(
|
r = setup_namespace(
|
||||||
(params->flags & EXEC_APPLY_CHROOT) ? context->root_directory : NULL,
|
(params->flags & EXEC_APPLY_CHROOT) ? context->root_directory : NULL,
|
||||||
|
&ns_info,
|
||||||
rw,
|
rw,
|
||||||
context->read_only_paths,
|
context->read_only_paths,
|
||||||
context->inaccessible_paths,
|
context->inaccessible_paths,
|
||||||
tmp,
|
tmp,
|
||||||
var,
|
var,
|
||||||
context->private_devices,
|
|
||||||
context->protect_kernel_tunables,
|
|
||||||
context->protect_control_groups,
|
|
||||||
context->protect_home,
|
context->protect_home,
|
||||||
context->protect_system,
|
context->protect_system,
|
||||||
context->mount_flags);
|
context->mount_flags);
|
||||||
|
|
|
@ -97,6 +97,14 @@ static const TargetMount protect_kernel_tunables_table[] = {
|
||||||
{ "/sys/fs/cgroup", READWRITE, false }, /* READONLY is set by ProtectControlGroups= option */
|
{ "/sys/fs/cgroup", READWRITE, false }, /* READONLY is set by ProtectControlGroups= option */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* ProtectKernelModules= option */
|
||||||
|
static const TargetMount protect_kernel_modules_table[] = {
|
||||||
|
#ifdef HAVE_SPLIT_USR
|
||||||
|
{ "/lib/modules", INACCESSIBLE, true },
|
||||||
|
#endif
|
||||||
|
{ "/usr/lib/modules", INACCESSIBLE, true },
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ProtectHome=read-only table, protect $HOME and $XDG_RUNTIME_DIR and rest of
|
* ProtectHome=read-only table, protect $HOME and $XDG_RUNTIME_DIR and rest of
|
||||||
* system should be protected by ProtectSystem=
|
* system should be protected by ProtectSystem=
|
||||||
|
@ -207,6 +215,13 @@ static int append_protect_kernel_tunables(BindMount **p, const char *root_direct
|
||||||
ELEMENTSOF(protect_kernel_tunables_table));
|
ELEMENTSOF(protect_kernel_tunables_table));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int append_protect_kernel_modules(BindMount **p, const char *root_directory) {
|
||||||
|
assert(p);
|
||||||
|
|
||||||
|
return append_target_mounts(p, root_directory, protect_kernel_modules_table,
|
||||||
|
ELEMENTSOF(protect_kernel_modules_table));
|
||||||
|
}
|
||||||
|
|
||||||
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) {
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
|
||||||
|
@ -660,14 +675,12 @@ static int chase_all_symlinks(const char *root_directory, BindMount *m, unsigned
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned namespace_calculate_mounts(
|
static unsigned namespace_calculate_mounts(
|
||||||
|
const NameSpaceInfo *ns_info,
|
||||||
char** read_write_paths,
|
char** read_write_paths,
|
||||||
char** read_only_paths,
|
char** read_only_paths,
|
||||||
char** inaccessible_paths,
|
char** inaccessible_paths,
|
||||||
const char* tmp_dir,
|
const char* tmp_dir,
|
||||||
const char* var_tmp_dir,
|
const char* var_tmp_dir,
|
||||||
bool private_dev,
|
|
||||||
bool protect_sysctl,
|
|
||||||
bool protect_cgroups,
|
|
||||||
ProtectHome protect_home,
|
ProtectHome protect_home,
|
||||||
ProtectSystem protect_system) {
|
ProtectSystem protect_system) {
|
||||||
|
|
||||||
|
@ -690,22 +703,21 @@ static unsigned namespace_calculate_mounts(
|
||||||
strv_length(read_write_paths) +
|
strv_length(read_write_paths) +
|
||||||
strv_length(read_only_paths) +
|
strv_length(read_only_paths) +
|
||||||
strv_length(inaccessible_paths) +
|
strv_length(inaccessible_paths) +
|
||||||
private_dev +
|
ns_info->private_dev +
|
||||||
(protect_sysctl ? ELEMENTSOF(protect_kernel_tunables_table) : 0) +
|
(ns_info->protect_kernel_tunables ? ELEMENTSOF(protect_kernel_tunables_table) : 0) +
|
||||||
(protect_cgroups ? 1 : 0) +
|
(ns_info->protect_control_groups ? 1 : 0) +
|
||||||
|
(ns_info->protect_kernel_modules ? ELEMENTSOF(protect_kernel_modules_table) : 0) +
|
||||||
protect_home_cnt + protect_system_cnt;
|
protect_home_cnt + protect_system_cnt;
|
||||||
}
|
}
|
||||||
|
|
||||||
int setup_namespace(
|
int setup_namespace(
|
||||||
const char* root_directory,
|
const char* root_directory,
|
||||||
|
const NameSpaceInfo *ns_info,
|
||||||
char** read_write_paths,
|
char** read_write_paths,
|
||||||
char** read_only_paths,
|
char** read_only_paths,
|
||||||
char** inaccessible_paths,
|
char** inaccessible_paths,
|
||||||
const char* tmp_dir,
|
const char* tmp_dir,
|
||||||
const char* var_tmp_dir,
|
const char* var_tmp_dir,
|
||||||
bool private_dev,
|
|
||||||
bool protect_sysctl,
|
|
||||||
bool protect_cgroups,
|
|
||||||
ProtectHome protect_home,
|
ProtectHome protect_home,
|
||||||
ProtectSystem protect_system,
|
ProtectSystem protect_system,
|
||||||
unsigned long mount_flags) {
|
unsigned long mount_flags) {
|
||||||
|
@ -718,13 +730,12 @@ int setup_namespace(
|
||||||
if (mount_flags == 0)
|
if (mount_flags == 0)
|
||||||
mount_flags = MS_SHARED;
|
mount_flags = MS_SHARED;
|
||||||
|
|
||||||
n = namespace_calculate_mounts(read_write_paths,
|
n = namespace_calculate_mounts(ns_info,
|
||||||
|
read_write_paths,
|
||||||
read_only_paths,
|
read_only_paths,
|
||||||
inaccessible_paths,
|
inaccessible_paths,
|
||||||
tmp_dir, var_tmp_dir,
|
tmp_dir, var_tmp_dir,
|
||||||
private_dev, protect_sysctl,
|
protect_home, protect_system);
|
||||||
protect_cgroups, protect_home,
|
|
||||||
protect_system);
|
|
||||||
|
|
||||||
/* Set mount slave mode */
|
/* Set mount slave mode */
|
||||||
if (root_directory || n > 0)
|
if (root_directory || n > 0)
|
||||||
|
@ -756,16 +767,25 @@ int setup_namespace(
|
||||||
m++;
|
m++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (private_dev) {
|
if (ns_info->private_dev) {
|
||||||
m->path = prefix_roota(root_directory, "/dev");
|
m->path = prefix_roota(root_directory, "/dev");
|
||||||
m->mode = PRIVATE_DEV;
|
m->mode = PRIVATE_DEV;
|
||||||
m++;
|
m++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (protect_sysctl)
|
if (ns_info->protect_kernel_tunables) {
|
||||||
append_protect_kernel_tunables(&m, root_directory);
|
r = append_protect_kernel_tunables(&m, root_directory);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
if (protect_cgroups) {
|
if (ns_info->protect_kernel_modules) {
|
||||||
|
r = append_protect_kernel_modules(&m, root_directory);
|
||||||
|
if (r < 0)
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ns_info->protect_control_groups) {
|
||||||
m->path = prefix_roota(root_directory, "/sys/fs/cgroup");
|
m->path = prefix_roota(root_directory, "/sys/fs/cgroup");
|
||||||
m->mode = READONLY;
|
m->mode = READONLY;
|
||||||
m++;
|
m++;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
This file is part of systemd.
|
This file is part of systemd.
|
||||||
|
|
||||||
Copyright 2010 Lennart Poettering
|
Copyright 2010 Lennart Poettering
|
||||||
|
Copyright 2016 Djalal Harouni
|
||||||
|
|
||||||
systemd is free software; you can redistribute it and/or modify it
|
systemd is free software; you can redistribute it and/or modify it
|
||||||
under the terms of the GNU Lesser General Public License as published by
|
under the terms of the GNU Lesser General Public License as published by
|
||||||
|
@ -19,6 +20,8 @@
|
||||||
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
along with systemd; If not, see <http://www.gnu.org/licenses/>.
|
||||||
***/
|
***/
|
||||||
|
|
||||||
|
typedef struct NameSpaceInfo NameSpaceInfo;
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
#include "macro.h"
|
#include "macro.h"
|
||||||
|
@ -40,15 +43,20 @@ typedef enum ProtectSystem {
|
||||||
_PROTECT_SYSTEM_INVALID = -1
|
_PROTECT_SYSTEM_INVALID = -1
|
||||||
} ProtectSystem;
|
} ProtectSystem;
|
||||||
|
|
||||||
|
struct NameSpaceInfo {
|
||||||
|
bool private_dev:1;
|
||||||
|
bool protect_control_groups:1;
|
||||||
|
bool protect_kernel_tunables:1;
|
||||||
|
bool protect_kernel_modules:1;
|
||||||
|
};
|
||||||
|
|
||||||
int setup_namespace(const char *chroot,
|
int setup_namespace(const char *chroot,
|
||||||
|
const NameSpaceInfo *ns_info,
|
||||||
char **read_write_paths,
|
char **read_write_paths,
|
||||||
char **read_only_paths,
|
char **read_only_paths,
|
||||||
char **inaccessible_paths,
|
char **inaccessible_paths,
|
||||||
const char *tmp_dir,
|
const char *tmp_dir,
|
||||||
const char *var_tmp_dir,
|
const char *var_tmp_dir,
|
||||||
bool private_dev,
|
|
||||||
bool protect_sysctl,
|
|
||||||
bool protect_cgroups,
|
|
||||||
ProtectHome protect_home,
|
ProtectHome protect_home,
|
||||||
ProtectSystem protect_system,
|
ProtectSystem protect_system,
|
||||||
unsigned long mount_flags);
|
unsigned long mount_flags);
|
||||||
|
|
|
@ -45,6 +45,14 @@ int main(int argc, char *argv[]) {
|
||||||
"/home/lennart/projects",
|
"/home/lennart/projects",
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const NameSpaceInfo ns_info = {
|
||||||
|
.private_dev = true,
|
||||||
|
.protect_control_groups = true,
|
||||||
|
.protect_kernel_tunables = true,
|
||||||
|
.protect_kernel_modules = true,
|
||||||
|
};
|
||||||
|
|
||||||
char *root_directory;
|
char *root_directory;
|
||||||
char *projects_directory;
|
char *projects_directory;
|
||||||
int r;
|
int r;
|
||||||
|
@ -69,14 +77,12 @@ int main(int argc, char *argv[]) {
|
||||||
log_info("Not chrooted");
|
log_info("Not chrooted");
|
||||||
|
|
||||||
r = setup_namespace(root_directory,
|
r = setup_namespace(root_directory,
|
||||||
|
&ns_info,
|
||||||
(char **) writable,
|
(char **) writable,
|
||||||
(char **) readonly,
|
(char **) readonly,
|
||||||
(char **) inaccessible,
|
(char **) inaccessible,
|
||||||
tmp_dir,
|
tmp_dir,
|
||||||
var_tmp_dir,
|
var_tmp_dir,
|
||||||
true,
|
|
||||||
true,
|
|
||||||
true,
|
|
||||||
PROTECT_HOME_NO,
|
PROTECT_HOME_NO,
|
||||||
PROTECT_SYSTEM_NO,
|
PROTECT_SYSTEM_NO,
|
||||||
0);
|
0);
|
||||||
|
|
Loading…
Reference in a new issue