+ const char *what;
+ int r;
+
+ assert(m);
+
+ switch (m->mode) {
+
+ case INACCESSIBLE:
+
+ /* First, get rid of everything that is below if there
+ * is anything... Then, overmount it with an
+ * inaccessible directory. */
+ umount_recursive(m->path, 0);
+
+ what = "/run/systemd/inaccessible";
+ break;
+
+ case READONLY:
+ case READWRITE:
+ /* Nothing to mount here, we just later toggle the
+ * MS_RDONLY bit for the mount point */
+ return 0;
+
+ case PRIVATE_TMP:
+ what = tmp_dir;
+ break;
+
+ case PRIVATE_VAR_TMP:
+ what = var_tmp_dir;
+ break;
+
+ case PRIVATE_DEV:
+ return mount_dev(m);
+
+ case PRIVATE_BUS_ENDPOINT:
+ return mount_kdbus(m);
+
+ default:
+ assert_not_reached("Unknown mode");
+ }
+
+ assert(what);
+
+ r = mount(what, m->path, NULL, MS_BIND|MS_REC, NULL);
+ if (r >= 0)
+ log_debug("Successfully mounted %s to %s", what, m->path);
+ else if (m->ignore && errno == ENOENT)
+ return 0;
+
+ return r;
+}
+
+static int make_read_only(BindMount *m) {
+ int r;
+
+ assert(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))
+ r = bind_remount_recursive(m->path, false);
+ else
+ r = 0;
+
+ if (m->ignore && r == -ENOENT)
+ return 0;
+
+ return r;
+}
+
+int setup_namespace(
+ char** read_write_dirs,
+ char** read_only_dirs,
+ char** inaccessible_dirs,
+ const char* tmp_dir,
+ const char* var_tmp_dir,
+ const char* bus_endpoint_path,
+ bool private_dev,
+ ProtectHome protect_home,
+ ProtectSystem protect_system,
+ unsigned long mount_flags) {
+
+ BindMount *m, *mounts = NULL;
+ unsigned n;
+ int r = 0;
+
+ if (mount_flags == 0)
+ mount_flags = MS_SHARED;
+
+ if (unshare(CLONE_NEWNS) < 0)
+ return -errno;
+
+ n = !!tmp_dir + !!var_tmp_dir + !!bus_endpoint_path +
+ strv_length(read_write_dirs) +
+ strv_length(read_only_dirs) +
+ strv_length(inaccessible_dirs) +
+ private_dev +
+ (protect_home != PROTECT_HOME_NO ? 3 : 0) +
+ (protect_system != PROTECT_SYSTEM_NO ? 2 : 0) +
+ (protect_system == PROTECT_SYSTEM_FULL ? 1 : 0);
+
+ if (n > 0) {
+ m = mounts = (BindMount *) alloca0(n * sizeof(BindMount));
+ r = append_mounts(&m, read_write_dirs, READWRITE);
+ if (r < 0)
+ return r;
+
+ r = append_mounts(&m, read_only_dirs, READONLY);
+ if (r < 0)
+ return r;
+
+ r = append_mounts(&m, inaccessible_dirs, INACCESSIBLE);
+ if (r < 0)
+ return r;
+
+ if (tmp_dir) {
+ m->path = "/tmp";
+ m->mode = PRIVATE_TMP;
+ m++;
+ }
+
+ if (var_tmp_dir) {
+ m->path = "/var/tmp";
+ m->mode = PRIVATE_VAR_TMP;
+ m++;
+ }
+
+ if (private_dev) {
+ m->path = "/dev";
+ m->mode = PRIVATE_DEV;
+ m++;
+ }
+
+ if (bus_endpoint_path) {
+ m->path = bus_endpoint_path;
+ m->mode = PRIVATE_BUS_ENDPOINT;
+ m++;