Reuse -v/--volume to mount named/host volumes into -r/--run
Volume names now reject '/', which lets a -v spec used with -r be told apart as either an existing named volume or a host directory path. -v becomes repeatable with -r, each mounting a volume at an absolute container path; if the host directory is empty and the image already has content there, it's copied in first (preserving numeric ownership/permissions/links/xattrs-ACLs, degrading gracefully with a warning if the host filesystem doesn't support xattrs). The existence-check and copy run through the same nsenter-wrapped namespace bwrap itself needs, since a rootless containers-storage mount's content isn't otherwise visible to this process at all. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Gv3s5jckJKzh6JkMoi2Akz
This commit is contained in:
+23
-5
@@ -20,6 +20,8 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "volume_mount.h"
|
||||
|
||||
// Probes the running kernel for which Linux namespace types can actually be
|
||||
// unshared and returns the corresponding bwrap --unshare-xxx flags for the
|
||||
// ones that are supported. Intended for kernels with partial namespace
|
||||
@@ -27,6 +29,19 @@
|
||||
// --unshare-xxx flag to bwrap would make it fail outright.
|
||||
std::vector<std::string> detect_bwrap_unshare_args();
|
||||
|
||||
// Wraps `argv` so it runs inside the mount+user namespace that containers-storage's
|
||||
// rootless fuse-overlayfs daemon created for `root` (the merged mount path from
|
||||
// mount_layer()), via nsenter -- needed to reach anything under `root` at all from a
|
||||
// plain process outside that namespace (containers-storage mount reexecs itself
|
||||
// into a private namespace to get the privilege an unprivileged overlay mount
|
||||
// needs; only nsenter targeting that live daemon's PID can rejoin it). If
|
||||
// use_nsenter is false, returns argv unchanged (the mount is already directly
|
||||
// visible, e.g. when running as root -- see run_container() in main.cpp). Returns
|
||||
// nullopt (and logs) if the fuse-overlayfs process or nsenter itself can't be
|
||||
// found.
|
||||
std::optional<std::vector<std::string>> wrap_for_root_namespace(const std::string& root, bool use_nsenter,
|
||||
const std::vector<std::string>& argv);
|
||||
|
||||
struct ResolvedUser {
|
||||
int uid;
|
||||
int gid;
|
||||
@@ -34,12 +49,15 @@ struct ResolvedUser {
|
||||
|
||||
// Assembles the full bwrap argv (program name included) to run `command` with
|
||||
// `root` bound as the sandbox's filesystem root, using whichever --unshare-xxx
|
||||
// flags the kernel supports (see detect_bwrap_unshare_args()). If `user` is set,
|
||||
// the command is wrapped so it drops to that uid/gid before running -- see
|
||||
// run_bwrap() for how, since bwrap's own --uid/--gid require --unshare-user, which
|
||||
// isn't requested when running as root (see detect_bwrap_unshare_args()).
|
||||
// flags the kernel supports (see detect_bwrap_unshare_args()). Each entry in
|
||||
// `volumes` is bound writably at its container_path (see resolve_volume_mount()
|
||||
// in volume_mount.h). If `user` is set, the command is wrapped so it drops to that
|
||||
// uid/gid before running -- see run_bwrap() for how, since bwrap's own --uid/--gid
|
||||
// require --unshare-user, which isn't requested when running as root (see
|
||||
// detect_bwrap_unshare_args()).
|
||||
std::vector<std::string> build_bwrap_args(const std::string& root,
|
||||
const std::vector<std::string>& command,
|
||||
const std::vector<ResolvedVolumeMount>& volumes,
|
||||
std::optional<ResolvedUser> user);
|
||||
|
||||
// Runs bwrap against `root` (the merged mount path from mount_layer()) in the
|
||||
@@ -54,4 +72,4 @@ std::vector<std::string> build_bwrap_args(const std::string& root,
|
||||
// used to drop privileges to that uid/gid before running `command` -- see
|
||||
// build_bwrap_args(). Returns bwrap's exit code, or -1 on failure to launch.
|
||||
int run_bwrap(const std::string& root, const std::vector<std::string>& command, bool use_nsenter,
|
||||
std::optional<ResolvedUser> user);
|
||||
const std::vector<ResolvedVolumeMount>& volumes, std::optional<ResolvedUser> user);
|
||||
|
||||
Reference in New Issue
Block a user