/* Second, we mount the source file or directory to a directory inside of our MS_SLAVE playground. */
mount_tmp = strjoina(mount_slave, "/mount");
- if (flags & MOUNT_IN_NAMESPACE_IS_IMAGE)
- r = mkdir_p(mount_tmp, 0700);
- else
- r = make_mount_point_inode_from_stat(chased_src_st, mount_tmp, 0700);
+ r = make_mount_point_inode_from_mode(AT_FDCWD, mount_tmp, (flags & MOUNT_IN_NAMESPACE_IS_IMAGE) ? S_IFDIR : chased_src_st->st_mode, 0700);
if (r < 0) {
log_debug_errno(r, "Failed to create temporary mount point %s: %m", mount_tmp);
goto finish;
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
- if (flags & MOUNT_IN_NAMESPACE_MAKE_FILE_OR_DIRECTORY) {
- if (!(flags & MOUNT_IN_NAMESPACE_IS_IMAGE)) {
- (void) mkdir_parents(dest, 0755);
- (void) make_mount_point_inode_from_stat(chased_src_st, dest, 0700);
- } else
- (void) mkdir_p(dest, 0755);
+ _cleanup_close_ int dest_fd = -EBADF;
+ _cleanup_free_ char *dest_fn = NULL;
+ r = chase(dest, /* root= */ NULL, CHASE_PARENT|CHASE_EXTRACT_FILENAME|((flags & MOUNT_IN_NAMESPACE_MAKE_FILE_OR_DIRECTORY) ? CHASE_MKDIR_0755 : 0), &dest_fn, &dest_fd);
+ if (r < 0)
+ log_debug_errno(r, "Failed to pin parent directory of mount '%s', ignoring: %m", dest);
+ else if (flags & MOUNT_IN_NAMESPACE_MAKE_FILE_OR_DIRECTORY) {
+ r = make_mount_point_inode_from_mode(dest_fd, dest_fn, (flags & MOUNT_IN_NAMESPACE_IS_IMAGE) ? S_IFDIR : chased_src_st->st_mode, 0700);
+ if (r < 0)
+ log_debug_errno(r, "Failed to make mount point inode of mount '%s', ignoring: %m", dest);
}
/* Fifth, move the mount to the right place inside */
if (!mount_inside)
report_errno_and_exit(errno_pipe_fd[1], log_oom_debug());
- r = mount_nofollow_verbose(LOG_DEBUG, mount_inside, dest, NULL, MS_MOVE, NULL);
+ r = mount_nofollow_verbose(LOG_DEBUG, mount_inside, dest_fd >= 0 ? FORMAT_PROC_FD_PATH(dest_fd) : dest, /* fstype= */ NULL, MS_MOVE, /* options= */ NULL);
if (r < 0)
report_errno_and_exit(errno_pipe_fd[1], r);
if (r == 0) {
errno_pipe_fd[0] = safe_close(errno_pipe_fd[0]);
+ _cleanup_close_ int dest_fd = -EBADF;
+ _cleanup_free_ char *dest_fn = NULL;
+ r = chase(dest, /* root= */ NULL, CHASE_PARENT|CHASE_EXTRACT_FILENAME|((flags & MOUNT_IN_NAMESPACE_MAKE_FILE_OR_DIRECTORY) ? CHASE_MKDIR_0755 : 0), &dest_fn, &dest_fd);
+ if (r < 0)
+ report_errno_and_exit(errno_pipe_fd[1], r);
+
if (flags & MOUNT_IN_NAMESPACE_MAKE_FILE_OR_DIRECTORY)
- (void) mkdir_parents(dest, 0755);
+ (void) make_mount_point_inode_from_mode(dest_fd, dest_fn, img ? S_IFDIR : st.st_mode, 0700);
if (img) {
DissectImageFlags f =
/* uid_range= */ UID_INVALID,
/* userns_fd= */ -EBADF,
f);
- } else {
- if (flags & MOUNT_IN_NAMESPACE_MAKE_FILE_OR_DIRECTORY)
- (void) make_mount_point_inode_from_stat(&st, dest, 0700);
-
+ } else
r = mount_exchange_graceful(new_mount_fd, dest, /* mount_beneath= */ true);
- }
report_errno_and_exit(errno_pipe_fd[1], r);
}
return ret;
}
-int make_mount_point_inode_from_stat(const struct stat *st, const char *dest, mode_t mode) {
- assert(st);
+int make_mount_point_inode_from_mode(int dir_fd, const char *dest, mode_t source_mode, mode_t target_mode) {
+ assert(dir_fd >= 0 || dir_fd == AT_FDCWD);
assert(dest);
- if (S_ISDIR(st->st_mode))
- return mkdir_label(dest, mode);
+ if (S_ISDIR(source_mode))
+ return mkdirat_label(dir_fd, dest, target_mode & 07777);
else
- return RET_NERRNO(mknod(dest, S_IFREG|(mode & ~0111), 0));
+ return RET_NERRNO(mknodat(dir_fd, dest, S_IFREG|(target_mode & 07666), 0)); /* Mask off X bit */
}
-int make_mount_point_inode_from_path(const char *source, const char *dest, mode_t mode) {
+int make_mount_point_inode_from_path(const char *source, const char *dest, mode_t access_mode) {
struct stat st;
assert(source);
if (stat(source, &st) < 0)
return -errno;
- return make_mount_point_inode_from_stat(&st, dest, mode);
+ return make_mount_point_inode_from_mode(AT_FDCWD, dest, st.st_mode, access_mode);
}
int trigger_automount_at(int dir_fd, const char *path) {
assert_se(suffix = path_startswith(m->path, src));
+ if (fstat(m->mount_fd, &st) < 0)
+ return log_error_errno(errno, "Failed to stat %s: %m", m->path);
+
t = path_join(dst, suffix);
if (!t)
return log_oom();
- if (fstat(m->mount_fd, &st) < 0)
- return log_error_errno(errno, "Failed to stat %s: %m", m->path);
-
- r = mkdir_parents(t, 0755);
+ _cleanup_free_ char *fn = NULL;
+ _cleanup_close_ int fd = -EBADF;
+ r = chase(t, /* root= */ NULL, CHASE_PARENT|CHASE_EXTRACT_FILENAME|CHASE_PROHIBIT_SYMLINKS|CHASE_MKDIR_0755, &fn, &fd);
if (r < 0)
- return log_error_errno(r, "Failed to create parent directories of %s: %m", t);
+ return log_error_errno(r, "Failed to create and pin parent directory of %s: %m", t);
- r = make_mount_point_inode_from_stat(&st, t, 0755);
+ r = make_mount_point_inode_from_mode(fd, fn, st.st_mode, 0755);
if (r < 0 && r != -EEXIST)
return log_error_errno(r, "Failed to create mountpoint %s: %m", t);
- r = mount_follow_verbose(LOG_ERR, m->path, t, NULL, MS_BIND|MS_REC, NULL);
+ _cleanup_close_ int child_fd = openat(fd, fn, O_PATH|O_CLOEXEC);
+ if (child_fd < 0)
+ return log_error_errno(errno, "Failed to pin mountpoint %s: %m", t);
+
+ r = mount_follow_verbose(LOG_ERR, m->path, FORMAT_PROC_FD_PATH(child_fd), /* fstype= */ NULL, MS_BIND|MS_REC, /* options= */ NULL);
if (r < 0)
return r;