From 737ba3c82c71c15de498f63527d264dc996ffa11 Mon Sep 17 00:00:00 2001 From: topimiettinen Date: Mon, 16 May 2016 02:34:05 +0000 Subject: namespace: Make private /dev noexec and readonly (#3263) Private /dev will not be managed by udev or others, so we can make it noexec and readonly after we have made all device nodes. As /dev/shm needs to be writable, we can't use bind_remount_recursive(). --- man/systemd.exec.xml | 5 ++++- src/core/namespace.c | 10 +++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 2a93760428..3cf6de8256 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -933,7 +933,10 @@ (propagation in the opposite direction continues to work). This means that this setting may not be used for services which shall be able to install mount points in the main mount - namespace. + namespace. The /dev namespace will be mounted read-only and 'noexec'. + The latter may break old programs which try to set up executable + memory by using mmap2 + of /dev/zero instead of using MAP_ANON. diff --git a/src/core/namespace.c b/src/core/namespace.c index ef85bfec23..203d122810 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -44,6 +44,8 @@ #include "user-util.h" #include "util.h" +#define DEV_MOUNT_OPTIONS (MS_NOSUID|MS_STRICTATIME|MS_NOEXEC) + typedef enum MountMode { /* This is ordered by priority! */ INACCESSIBLE, @@ -153,7 +155,7 @@ static int mount_dev(BindMount *m) { dev = strjoina(temporary_mount, "/dev"); (void) mkdir(dev, 0755); - if (mount("tmpfs", dev, "tmpfs", MS_NOSUID|MS_STRICTATIME, "mode=755") < 0) { + if (mount("tmpfs", dev, "tmpfs", DEV_MOUNT_OPTIONS, "mode=755") < 0) { r = -errno; goto fail; } @@ -330,9 +332,11 @@ static int make_read_only(BindMount *m) { if (IN_SET(m->mode, INACCESSIBLE, READONLY)) r = bind_remount_recursive(m->path, true); - else if (IN_SET(m->mode, READWRITE, PRIVATE_TMP, PRIVATE_VAR_TMP, PRIVATE_DEV)) + else if (IN_SET(m->mode, READWRITE, PRIVATE_TMP, PRIVATE_VAR_TMP, PRIVATE_DEV)) { r = bind_remount_recursive(m->path, false); - else + if (r == 0 && m->mode == PRIVATE_DEV) /* can be readonly but the submounts can't*/ + r = mount(NULL, m->path, NULL, MS_REMOUNT|DEV_MOUNT_OPTIONS|MS_RDONLY, NULL); + } else r = 0; if (m->ignore && r == -ENOENT) -- cgit v1.2.3-54-g00ecf