namespace.c revision 6b46ea73e3b1d8a1e65f58ac04772821bd4a72fb
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering/***
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering This file is part of systemd.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering Copyright 2010 Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering systemd is free software; you can redistribute it and/or modify it
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering under the terms of the GNU Lesser General Public License as published by
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering (at your option) any later version.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering systemd is distributed in the hope that it will be useful, but
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering Lesser General Public License for more details.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
5430f7f2bc7330f3088b894166bf3524a067e3d8Lennart Poettering You should have received a copy of the GNU Lesser General Public License
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering***/
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include <errno.h>
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include <sys/mount.h>
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include <string.h>
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include <stdio.h>
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering#include <unistd.h>
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering#include <sys/stat.h>
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering#include <sys/types.h>
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include <sched.h>
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering#include <sys/syscall.h>
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering#include <limits.h>
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include <linux/fs.h>
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include <sys/file.h>
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering#include "strv.h"
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering#include "util.h"
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering#include "path-util.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "namespace.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "missing.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "execute.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering#include "loopback-setup.h"
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poetteringtypedef enum MountMode {
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering /* This is ordered by priority! */
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering INACCESSIBLE,
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering READONLY,
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering PRIVATE_TMP,
3ed08c446cfaaae2b234fdfeb0c34ab6b4748c3eLennart Poettering PRIVATE_VAR_TMP,
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering READWRITE
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering} MountMode;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringtypedef struct BindMount {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering const char *path;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering MountMode mode;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering bool done;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering bool ignore;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering} BindMount;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic int append_mounts(BindMount **p, char **strv, MountMode mode) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering char **i;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering assert(p);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering STRV_FOREACH(i, strv) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering (*p)->ignore = false;
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if ((mode == INACCESSIBLE || mode == READONLY) && (*i)[0] == '-') {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering (*p)->ignore = true;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering (*i)++;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (!path_is_absolute(*i))
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return -EINVAL;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering (*p)->path = *i;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering (*p)->mode = mode;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering (*p)++;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering return 0;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering}
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic int mount_path_compare(const void *a, const void *b) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering const BindMount *p = a, *q = b;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering if (path_equal(p->path, q->path)) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering /* If the paths are equal, check the mode */
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering if (p->mode < q->mode)
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering return -1;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering if (p->mode > q->mode)
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen return 1;
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen return 0;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering }
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering /* If the paths are not equal, then order prefixes first */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (path_startswith(p->path, q->path))
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return 1;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (path_startswith(q->path, p->path))
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return -1;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering return 0;
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poettering}
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
d0bbc21caa6e68693a47db60c93e99422bf2a858Lennart Poetteringstatic void drop_duplicates(BindMount *m, unsigned *n) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering BindMount *f, *t, *previous;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
44b601bc79e46722bc0f0862ee0ce34a2284ef11Lennart Poettering assert(m);
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering assert(n);
25d042e81516246b1ebf706a57c47ac19abb0b8aLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering for (f = m, t = m, previous = NULL; f < m+*n; f++) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering /* The first one wins */
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (previous && path_equal(f->path, previous->path))
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering continue;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering t->path = f->path;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering t->mode = f->mode;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering previous = t;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering t++;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering }
25d042e81516246b1ebf706a57c47ac19abb0b8aLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering *n = t - m;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering}
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringstatic int apply_mount(
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering BindMount *m,
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering const char *tmp_dir,
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering const char *var_tmp_dir) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering const char *what;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering int r;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering assert(m);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering switch (m->mode) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering case INACCESSIBLE:
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering what = "/run/systemd/inaccessible";
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering break;
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering case READONLY:
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering case READWRITE:
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering what = m->path;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering break;
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering case PRIVATE_TMP:
72f1d5a2880d103dc1c1746f5c02e192e054705eLennart Poettering what = tmp_dir;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering break;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering case PRIVATE_VAR_TMP:
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering what = var_tmp_dir;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering break;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering default:
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering assert_not_reached("Unknown mode");
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering }
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering assert(what);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering r = mount(what, m->path, NULL, MS_BIND|MS_REC, NULL);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (r >= 0)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering log_debug("Successfully mounted %s to %s", what, m->path);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering else if (m->ignore && errno == ENOENT)
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering r = 0;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return r;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering}
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poetteringstatic int make_read_only(BindMount *m) {
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering int r;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering assert(m);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (m->mode != INACCESSIBLE && m->mode != READONLY)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return 0;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering r = mount(NULL, m->path, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_REC, NULL);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering if (r < 0 && !(m->ignore && errno == ENOENT))
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering return -errno;
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return 0;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering}
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringint setup_namespace(
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering char** read_write_dirs,
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering char** read_only_dirs,
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering char** inaccessible_dirs,
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering char* tmp_dir,
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering char* var_tmp_dir,
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering unsigned mount_flags) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering BindMount *m, *mounts = NULL;
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering unsigned n;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering int r = 0;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (mount_flags == 0)
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering mount_flags = MS_SHARED;
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek if (unshare(CLONE_NEWNS) < 0)
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek return -errno;
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek n = !!tmp_dir + !!var_tmp_dir +
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek strv_length(read_write_dirs) +
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek strv_length(read_only_dirs) +
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek strv_length(inaccessible_dirs);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering if (n > 0) {
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering m = mounts = (BindMount *) alloca(n * sizeof(BindMount));
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering r = append_mounts(&m, read_write_dirs, READWRITE);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering if (r < 0)
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering return r;
9058851be7821edac08c1fa7ecafe5cba9ab9022Lennart Poettering
9058851be7821edac08c1fa7ecafe5cba9ab9022Lennart Poettering r = append_mounts(&m, read_only_dirs, READONLY);
9058851be7821edac08c1fa7ecafe5cba9ab9022Lennart Poettering if (r < 0)
9058851be7821edac08c1fa7ecafe5cba9ab9022Lennart Poettering return r;
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = append_mounts(&m, inaccessible_dirs, INACCESSIBLE);
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen if (r < 0)
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen return r;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering if (tmp_dir) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering m->path = "/tmp";
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering m->mode = PRIVATE_TMP;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering m++;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering if (var_tmp_dir) {
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering m->path = "/var/tmp";
a5344d2c3b0f14e954ce1c0ef905c5b44bc5bf0aLennart Poettering m->mode = PRIVATE_VAR_TMP;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering m++;
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering }
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering assert(mounts + n == m);
29abad107f8610e73b2fc091216040b579c75453Zbigniew Jędrzejewski-Szmek
29abad107f8610e73b2fc091216040b579c75453Zbigniew Jędrzejewski-Szmek qsort(mounts, n, sizeof(BindMount), mount_path_compare);
2a0e0692565f0435657c93498e09cbb2d3517152Shawn Landden drop_duplicates(mounts, &n);
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering /* Remount / as SLAVE so that nothing now mounted in the namespace
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering shows up in the parent */
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering if (mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL) < 0)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return -errno;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering for (m = mounts; m < mounts + n; ++m) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = apply_mount(m, tmp_dir, var_tmp_dir);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (r < 0)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering goto fail;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering for (m = mounts; m < mounts + n; ++m) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = make_read_only(m);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (r < 0)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering goto fail;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering /* Remount / as the desired mode */
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (mount(NULL, "/", NULL, mount_flags | MS_REC, NULL) < 0) {
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = -errno;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering goto fail;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering }
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return 0;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringfail:
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering for (m = mounts; m < mounts + n; ++m)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (m->done)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering umount2(m->path, MNT_DETACH);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return r;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering}
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poetteringstatic int setup_one_tmp_dir(const char *id, const char *prefix, char **path) {
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering _cleanup_free_ char *x = NULL;
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering char bid[SD_ID128_STRING_MAX];
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering sd_id128_t boot_id;
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering int r;
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering assert(id);
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering assert(prefix);
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering assert(path);
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering /* We include the boot id in the directory so that after a
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering * reboot we can easily identify obsolete directories. */
ee55db41442ad8055f5a84a339b1e0e22bc037c4Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering r = sd_id128_get_boot(&boot_id);
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering if (r < 0)
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering return r;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering x = strjoin(prefix, "/systemd-private-", sd_id128_to_string(boot_id, bid), "-", id, "-XXXXXX", NULL);
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering if (!x)
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering return -ENOMEM;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering RUN_WITH_UMASK(0077)
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering if (!mkdtemp(x))
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering return -errno;
6c045c0b4c49c88a1d3b9360c05efa5084796d2dZbigniew Jędrzejewski-Szmek
6c045c0b4c49c88a1d3b9360c05efa5084796d2dZbigniew Jędrzejewski-Szmek RUN_WITH_UMASK(0000) {
6c045c0b4c49c88a1d3b9360c05efa5084796d2dZbigniew Jędrzejewski-Szmek char *y;
6c045c0b4c49c88a1d3b9360c05efa5084796d2dZbigniew Jędrzejewski-Szmek
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering y = strappenda(x, "/tmp");
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering if (mkdir(y, 0777 | S_ISVTX) < 0)
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering return -errno;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering }
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering *path = x;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering x = NULL;
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering return 0;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering}
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poetteringint setup_tmp_dirs(const char *id, char **tmp_dir, char **var_tmp_dir) {
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering char *a, *b;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering int r;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering assert(id);
b070e7f3c9ed680c821bd89d42506695f2438506Lennart Poettering assert(tmp_dir);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering assert(var_tmp_dir);
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering r = setup_one_tmp_dir(id, "/tmp", &a);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering if (r < 0)
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering return r;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering r = setup_one_tmp_dir(id, "/var/tmp", &b);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering if (r < 0) {
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering char *t;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering t = strappenda(a, "/tmp");
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering rmdir(t);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering rmdir(a);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering free(a);
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering return r;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering }
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering *tmp_dir = a;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering *var_tmp_dir = b;
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering
0dad12c190b7493955cd60d2a1625199b1709f69Lennart Poettering return 0;
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering}
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poetteringint setup_netns(int netns_storage_socket[2]) {
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering _cleanup_close_ int netns = -1;
7f3e62571a63ac90de6ac5eefeeb8d3e9aa6f49eLennart Poettering union {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering struct cmsghdr cmsghdr;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering uint8_t buf[CMSG_SPACE(sizeof(int))];
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering } control = {};
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering struct msghdr mh = {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering .msg_control = &control,
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering .msg_controllen = sizeof(control),
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering };
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering struct cmsghdr *cmsg;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering int r;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering assert(netns_storage_socket);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering assert(netns_storage_socket[0] >= 0);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering assert(netns_storage_socket[1] >= 0);
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering /* We use the passed socketpair as a storage buffer for our
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering * namespace reference fd. Whatever process runs this first
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering * shall create a new namespace, all others should just join
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering * it. To serialize that we use a file lock on the socket
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering * pair.
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering *
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering * It's a bit crazy, but hey, works great! */
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering if (lockf(netns_storage_socket[0], F_LOCK, 0) < 0)
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering return -errno;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering if (recvmsg(netns_storage_socket[0], &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC) < 0) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering if (errno != EAGAIN) {
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering r = -errno;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering goto fail;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering }
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering /* Nothing stored yet, so let's create a new namespace */
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering if (unshare(CLONE_NEWNET) < 0) {
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering r = -errno;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering goto fail;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering }
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering
5c0aa72a4999bdcf03fe93ed5c8213c2b4c681f0Lennart Poettering loopback_setup();
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering netns = open("/proc/self/ns/net", O_RDONLY|O_CLOEXEC|O_NOCTTY);
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering if (netns < 0) {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering r = -errno;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering goto fail;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering }
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering r = 1;
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering } else {
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering /* Yay, found something, so let's join the namespace */
18c7ed186be28800a2eeb37ad31c9c44480d3d9cLennart Poettering
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek assert(cmsg->cmsg_len == CMSG_LEN(sizeof(int)));
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek netns = *(int*) CMSG_DATA(cmsg);
6e5abe1564070a760196b97031eca9cf5e95e8a2Zbigniew Jędrzejewski-Szmek }
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering }
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering if (setns(netns, CLONE_NEWNET) < 0) {
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering r = -errno;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering goto fail;
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen }
1ae464e09376853c52075ec4d8a6bfc4b4036d0cThomas Hindoe Paaboel Andersen
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering r = 0;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering }
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering cmsg = CMSG_FIRSTHDR(&mh);
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering cmsg->cmsg_level = SOL_SOCKET;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering cmsg->cmsg_type = SCM_RIGHTS;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering cmsg->cmsg_len = CMSG_LEN(sizeof(int));
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering memcpy(CMSG_DATA(cmsg), &netns, sizeof(int));
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering mh.msg_controllen = cmsg->cmsg_len;
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering if (sendmsg(netns_storage_socket[1], &mh, MSG_DONTWAIT|MSG_NOSIGNAL) < 0) {
86b9b8e70d54e79db3ff4f67bbd5280ecfc82537Lennart Poettering r = -errno;
86b9b8e70d54e79db3ff4f67bbd5280ecfc82537Lennart Poettering goto fail;
86b9b8e70d54e79db3ff4f67bbd5280ecfc82537Lennart Poettering }
86b9b8e70d54e79db3ff4f67bbd5280ecfc82537Lennart Poettering
86b9b8e70d54e79db3ff4f67bbd5280ecfc82537Lennart Poetteringfail:
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering lockf(netns_storage_socket[0], F_ULOCK, 0);
bb99a35a873c35e80b0b47fe045081022660374dLennart Poettering
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering return r;
4cd9a9d9ecf3a8835e21930f3215a5f5b74144beLennart Poettering}
fe6521272ba203ec8f0d5a94f0729960b3f90525Lennart Poettering