From: Lennart Poettering Date: Thu, 28 Sep 2017 16:35:51 +0000 (+0200) Subject: namespace: if we can create the destination of bind and PrivateTmp= mounts X-Git-Tag: v235~36^2~9 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=a227a4be489333b1b149df124ab284d82397ff2d;p=platform%2Fupstream%2Fsystemd.git namespace: if we can create the destination of bind and PrivateTmp= mounts When putting together the namespace, always create the file or directory we are supposed to bind mount on, the same way we do it for most other stuff, for example mount units or systemd-nspawn's --bind= option. This has the big benefit that we can use namespace bind mounts on dirs in /tmp or /var/tmp even in conjunction with PrivateTmp=. --- diff --git a/src/core/namespace.c b/src/core/namespace.c index 069e0ed..03a18d4 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -688,7 +688,9 @@ static int mount_entry_chase( * chase the symlinks on our own first. This is called for the destination path, as well as the source path (if * that applies). The result is stored in "location". */ - r = chase_symlinks(path, root_directory, 0, &chased); + r = chase_symlinks(path, root_directory, + IN_SET(m->mode, BIND_MOUNT, BIND_MOUNT_RECURSIVE, PRIVATE_TMP, PRIVATE_VAR_TMP, PRIVATE_DEV, BIND_DEV, EMPTY_DIR, SYSFS, PROCFS) ? CHASE_NONEXISTENT : 0, + &chased); if (r == -ENOENT && m->ignore) { log_debug_errno(r, "Path %s does not exist, ignoring.", path); return 0; @@ -710,8 +712,8 @@ static int apply_mount( const char *tmp_dir, const char *var_tmp_dir) { + bool rbind = true, make = false; const char *what; - bool rbind = true; int r; assert(m); @@ -766,14 +768,17 @@ static int apply_mount( return r; what = mount_entry_source(m); + make = true; break; case PRIVATE_TMP: what = tmp_dir; + make = true; break; case PRIVATE_VAR_TMP: what = var_tmp_dir; + make = true; break; case PRIVATE_DEV: @@ -794,8 +799,36 @@ static int apply_mount( assert(what); - if (mount(what, mount_entry_path(m), NULL, MS_BIND|(rbind ? MS_REC : 0), NULL) < 0) - return log_debug_errno(errno, "Failed to mount %s to %s: %m", what, mount_entry_path(m)); + if (mount(what, mount_entry_path(m), NULL, MS_BIND|(rbind ? MS_REC : 0), NULL) < 0) { + bool try_again = false; + r = -errno; + + if (r == -ENOENT && make) { + struct stat st; + + /* Hmm, either the source or the destination are missing. Let's see if we can create the destination, then try again */ + + if (stat(what, &st) >= 0) { + + (void) mkdir_parents(mount_entry_path(m), 0755); + + if (S_ISDIR(st.st_mode)) + try_again = mkdir(mount_entry_path(m), 0755) >= 0; + else + try_again = touch(mount_entry_path(m)) >= 0; + } + } + + if (try_again) { + if (mount(what, mount_entry_path(m), NULL, MS_BIND|(rbind ? MS_REC : 0), NULL) < 0) + r = -errno; + else + r = 0; + } + + if (r < 0) + return log_debug_errno(r, "Failed to mount %s to %s: %m", what, mount_entry_path(m)); + } log_debug("Successfully mounted %s to %s", what, mount_entry_path(m)); return 0;