#include "sd-event.h"
#include "capability-util.h"
-#include "copy.h"
#include "dirent-util.h"
#include "dissect-image.h"
#include "fd-util.h"
return 1;
}
-int import_copy_foreign(
- int source_fd,
- int target_fd,
- int *userns_fd) {
-
- int r;
-
- assert(source_fd >= 0);
- assert(target_fd >= 0);
- assert(userns_fd);
-
- /* Copies dir referenced by source_fd into dir referenced by source_fd, moves to the specified userns
- * for that (allocated if needed), which should be foreign UID range */
-
- r = import_make_foreign_userns(userns_fd);
- if (r < 0)
- return r;
-
- r = pidref_safe_fork_full(
- "copy-tree",
- /* stdio_fds= */ NULL,
- (int[]) { *userns_fd, source_fd, target_fd }, 3,
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_REOPEN_LOG|FORK_WAIT,
- /* ret= */ NULL);
- if (r < 0)
- return r;
- if (r == 0) {
- r = namespace_enter(
- /* pidns_fd= */ -EBADF,
- /* mntns_fd= */ -EBADF,
- /* netns_fd= */ -EBADF,
- *userns_fd,
- /* root_fd= */ -EBADF);
- if (r < 0) {
- log_error_errno(r, "Failed to join user namespace: %m");
- _exit(EXIT_FAILURE);
- }
-
- r = copy_tree_at(
- source_fd, /* from= */ NULL,
- target_fd, /* to= */ NULL,
- /* override_uid= */ UID_INVALID,
- /* override_gid= */ GID_INVALID,
- COPY_REFLINK|COPY_HARDLINKS|COPY_MERGE_EMPTY|COPY_MERGE_APPLY_STAT|COPY_SAME_MOUNT|COPY_ALL_XATTRS,
- /* denylist= */ NULL,
- /* subvolumes= */ NULL);
- if (r < 0) {
- log_error_errno(r, "Failed to copy tree: %m");
- _exit(EXIT_FAILURE);
- }
-
- _exit(EXIT_SUCCESS);
- }
-
- return 0;
-}
-
-int import_remove_tree_foreign(const char *path, int *userns_fd) {
+int import_remove_tree(const char *path, int *userns_fd, ImportFlags flags) {
int r;
assert(path);
if (r < 0)
return r;
- _cleanup_close_ int tree_fd = -EBADF;
- r = mountfsd_mount_directory(
- path,
- *userns_fd,
- DISSECT_IMAGE_FOREIGN_UID,
- &tree_fd);
- if (r < 0)
- return r;
-
- r = pidref_safe_fork_full(
- "rm-tree",
- /* stdio_fds= */ NULL,
- (int[]) { *userns_fd, tree_fd }, 2,
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_REOPEN_LOG|FORK_WAIT,
- /* ret= */ NULL);
- if (r < 0)
- return r;
- if (r == 0) {
- /* child */
-
- r = namespace_enter(
- /* pidns_fd= */ -EBADF,
- /* mntns_fd= */ -EBADF,
- /* netns_fd= */ -EBADF,
- *userns_fd,
- /* root_fd= */ -EBADF);
- if (r < 0) {
- log_error_errno(r, "Failed to join user namespace: %m");
- _exit(EXIT_FAILURE);
- }
-
- _cleanup_close_ int dfd = fd_reopen(tree_fd, O_DIRECTORY|O_CLOEXEC);
- if (dfd < 0) {
- log_error_errno(r, "Failed to reopen tree fd: %m");
- _exit(EXIT_FAILURE);
- }
-
- r = rm_rf_children(dfd, REMOVE_PHYSICAL|REMOVE_SUBVOLUME|REMOVE_CHMOD, /* root_dev= */ NULL);
- if (r < 0)
- log_warning_errno(r, "Failed to empty '%s' directory in foreign UID mode, ignoring: %m", path);
-
- _exit(EXIT_SUCCESS);
- }
-
- return 0;
-}
-
-int import_remove_tree(const char *path, int *userns_fd, ImportFlags flags) {
- int r;
-
- assert(path);
- assert(userns_fd);
-
/* Try the userns dance first, to remove foreign UID range owned trees */
if (FLAGS_SET(flags, IMPORT_FOREIGN_UID))
- (void) import_remove_tree_foreign(path, userns_fd);
+ (void) remove_tree_foreign(path, *userns_fd);
r = rm_rf(path, REMOVE_ROOT|REMOVE_PHYSICAL|REMOVE_SUBVOLUME|REMOVE_MISSING_OK|REMOVE_CHMOD);
if (r < 0)
int import_make_foreign_userns(int *userns_fd);
-int import_copy_foreign(int source_fd, int target_fd, int *userns_fd);
-
-int import_remove_tree_foreign(const char *path, int *userns_fd);
int import_remove_tree(const char *path, int *userns_fd, ImportFlags flags);
#define IMPORT_BUFFER_SIZE (128U*1024U)
if (r < 0)
return r;
- r = import_copy_foreign(p->tree_fd, copy_fd, &p->userns_fd);
+ r = copy_tree_at_foreign(p->tree_fd, copy_fd, p->userns_fd);
if (r < 0)
return r;
} else {
return 0;
}
-static int unpriviled_clone(Image *i, const char *new_path) {
+static int unprivileged_clone(Image *i, const char *new_path) {
int r;
assert(i);
return r;
/* Fork off child that moves into userns and does the copying */
- r = pidref_safe_fork_full(
- "clone-tree",
- /* stdio_fds= */ NULL,
- (int[]) { userns_fd, tree_fd, target_fd }, 3,
- FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_REOPEN_LOG,
- /* ret= */ NULL);
- if (r < 0)
- return log_debug_errno(r, "Process that was supposed to clone tree failed: %m");
- if (r == 0) {
- /* child */
-
- r = namespace_enter(
- /* pidns_fd= */ -EBADF,
- /* mntns_fd= */ -EBADF,
- /* netns_fd= */ -EBADF,
- userns_fd,
- /* root_fd= */ -EBADF);
- if (r < 0) {
- log_debug_errno(r, "Failed to join user namespace: %m");
- _exit(EXIT_FAILURE);
- }
-
- r = copy_tree_at(
- tree_fd, /* from= */ NULL,
- target_fd, /* to= */ NULL,
- /* override_uid= */ UID_INVALID,
- /* override_gid= */ GID_INVALID,
- COPY_REFLINK|COPY_HARDLINKS|COPY_MERGE_EMPTY|COPY_MERGE_APPLY_STAT|COPY_SAME_MOUNT|COPY_ALL_XATTRS,
- /* denylist= */ NULL,
- /* subvolumes= */ NULL);
- if (r < 0) {
- log_debug_errno(r, "Failed to copy clone tree: %m");
- _exit(EXIT_FAILURE);
- }
-
- _exit(EXIT_SUCCESS);
- }
-
- return 0;
+ return copy_tree_at_foreign(tree_fd, target_fd, userns_fd);
}
int image_clone(Image *i, const char *new_name, bool read_only, RuntimeScope scope) {
return r;
if (i->foreign_uid_owned)
- r = unpriviled_clone(i, new_path);
+ r = unprivileged_clone(i, new_path);
else {
r = btrfs_subvol_snapshot_at(
AT_FDCWD, i->path,
#include "proc-cmdline.h"
#include "process-util.h"
#include "resize-fs.h"
+#include "rm-rf.h"
#include "runtime-scope.h"
#include "siphash24.h"
#include "stat-util.h"
return mountfsd_make_directory_fd(fd, dirname, mode, flags, ret_directory_fd);
}
+
+int copy_tree_at_foreign(int source_fd, int target_fd, int userns_fd) {
+ int r;
+
+ assert(source_fd >= 0);
+ assert(target_fd >= 0);
+ assert(userns_fd >= 0);
+
+ /* Copies dir referenced by source_fd into dir referenced by source_fd, moves to the specified userns
+ * for that, which should be foreign UID range */
+
+ r = pidref_safe_fork_full(
+ "copy-tree",
+ /* stdio_fds= */ NULL,
+ (int[]) { userns_fd, source_fd, target_fd }, 3,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_WAIT|FORK_REOPEN_LOG,
+ /* ret= */ NULL);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ r = namespace_enter(
+ /* pidns_fd= */ -EBADF,
+ /* mntns_fd= */ -EBADF,
+ /* netns_fd= */ -EBADF,
+ userns_fd,
+ /* root_fd= */ -EBADF);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to join user namespace: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ r = copy_tree_at(
+ source_fd, /* from= */ NULL,
+ target_fd, /* to= */ NULL,
+ /* override_uid= */ UID_INVALID,
+ /* override_gid= */ GID_INVALID,
+ COPY_REFLINK|COPY_HARDLINKS|COPY_MERGE_EMPTY|COPY_MERGE_APPLY_STAT|COPY_SAME_MOUNT|COPY_ALL_XATTRS,
+ /* denylist= */ NULL,
+ /* subvolumes= */ NULL);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to copy tree: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ return 0;
+}
+
+int remove_tree_foreign(const char *path, int userns_fd) {
+ int r;
+
+ assert(path);
+ assert(userns_fd >= 0);
+
+ _cleanup_close_ int tree_fd = -EBADF;
+ r = mountfsd_mount_directory(
+ path,
+ userns_fd,
+ DISSECT_IMAGE_FOREIGN_UID,
+ &tree_fd);
+ if (r < 0)
+ return r;
+
+ r = pidref_safe_fork_full(
+ "rm-tree",
+ /* stdio_fds= */ NULL,
+ (int[]) { userns_fd, tree_fd }, 2,
+ FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG_SIGTERM|FORK_LOG|FORK_REOPEN_LOG|FORK_WAIT,
+ /* ret= */ NULL);
+ if (r < 0)
+ return r;
+ if (r == 0) {
+ /* child */
+
+ r = namespace_enter(
+ /* pidns_fd= */ -EBADF,
+ /* mntns_fd= */ -EBADF,
+ /* netns_fd= */ -EBADF,
+ userns_fd,
+ /* root_fd= */ -EBADF);
+ if (r < 0) {
+ log_error_errno(r, "Failed to join user namespace: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ _cleanup_close_ int dfd = fd_reopen(tree_fd, O_DIRECTORY|O_CLOEXEC);
+ if (dfd < 0) {
+ log_error_errno(r, "Failed to reopen tree fd: %m");
+ _exit(EXIT_FAILURE);
+ }
+
+ r = rm_rf_children(dfd, REMOVE_PHYSICAL|REMOVE_SUBVOLUME|REMOVE_CHMOD, /* root_dev= */ NULL);
+ if (r < 0)
+ log_warning_errno(r, "Failed to empty '%s' directory in foreign UID mode, ignoring: %m", path);
+
+ _exit(EXIT_SUCCESS);
+ }
+
+ return 0;
+}
int mountfsd_make_directory_fd(int parent_fd, const char *name, mode_t mode, DissectImageFlags flags, int *ret_directory_fd);
int mountfsd_make_directory(const char *path, mode_t mode, DissectImageFlags flags, int *ret_directory_fd);
+
+int copy_tree_at_foreign(int source_fd, int target_fd, int userns_fd);
+int remove_tree_foreign(const char *path, int userns_fd);