diff --git a/cmd/snap-confine/mount-support.c b/cmd/snap-confine/mount-support.c index 6004b6391a7..bf67e8d3402 100644 --- a/cmd/snap-confine/mount-support.c +++ b/cmd/snap-confine/mount-support.c @@ -516,7 +516,8 @@ static bool __attribute__ ((used)) } void sc_populate_mount_ns(struct sc_apparmor *apparmor, int snap_update_ns_fd, - const char *base_snap_name, const char *snap_name) + const char *base_snap_name, const char *snap_name, + bool is_normal_mode) { // Get the current working directory before we start fiddling with // mounts and possibly pivot_root. At the end of the whole process, we @@ -529,7 +530,7 @@ void sc_populate_mount_ns(struct sc_apparmor *apparmor, int snap_update_ns_fd, // Classify the current distribution, as claimed by /etc/os-release. sc_distro distro = sc_classify_distro(); // Check which mode we should run in, normal or legacy. - if (sc_should_use_normal_mode(distro, base_snap_name)) { + if (is_normal_mode) { // In normal mode we use the base snap as / and set up several bind mounts. const struct sc_mount mounts[] = { {"/dev"}, // because it contains devices on host OS diff --git a/cmd/snap-confine/mount-support.h b/cmd/snap-confine/mount-support.h index 082c304fcc8..55a97701b17 100644 --- a/cmd/snap-confine/mount-support.h +++ b/cmd/snap-confine/mount-support.h @@ -51,7 +51,8 @@ int sc_open_snap_discard_ns(void); * this is impossible it will chdir to SC_VOID_DIR. **/ void sc_populate_mount_ns(struct sc_apparmor *apparmor, int snap_update_ns_fd, - const char *base_snap_name, const char *snap_name); + const char *base_snap_name, const char *snap_name, + bool is_normal_mode); /** * Ensure that / or /snap is mounted with the SHARED option. diff --git a/cmd/snap-confine/ns-support.c b/cmd/snap-confine/ns-support.c index 2071a5e5450..97f52542039 100644 --- a/cmd/snap-confine/ns-support.c +++ b/cmd/snap-confine/ns-support.c @@ -308,7 +308,8 @@ enum sc_discard_vote { static int sc_inspect_and_maybe_discard_stale_ns(int mnt_fd, const char *snap_name, const char *base_snap_name, - int snap_discard_ns_fd) + int snap_discard_ns_fd, + bool is_normal_mode) { char base_snap_rev[PATH_MAX] = { 0 }; char fname[PATH_MAX] = { 0 }; @@ -328,12 +329,6 @@ static int sc_inspect_and_maybe_discard_stale_ns(int mnt_fd, // Find the device that is backing the current revision of the base snap. base_snap_dev = find_base_snap_device(base_snap_name, base_snap_rev); - // Check if we are running in normal mode with pivot root. Do this here - // because once on the inside of the transformed mount namespace we can no - // longer tell. - bool is_normal_mode = - sc_should_use_normal_mode(sc_classify_distro(), base_snap_name); - // Store the PID of this process. This is done instead of calls to // getppid() below because then we can reliably track the PID of the // parent even if the child process is re-parented. @@ -448,7 +443,8 @@ static void helper_capture_per_user_ns(struct sc_mount_ns *group, pid_t parent); int sc_join_preserved_ns(struct sc_mount_ns *group, struct sc_apparmor *apparmor, const char *base_snap_name, - const char *snap_name, int snap_discard_ns_fd) + const char *snap_name, int snap_discard_ns_fd, + bool is_normal_mode) { // Open the mount namespace file. char mnt_fname[PATH_MAX] = { 0 }; @@ -490,7 +486,7 @@ int sc_join_preserved_ns(struct sc_mount_ns *group, struct sc_apparmor // Inspect and perhaps discard the preserved mount namespace. if (sc_inspect_and_maybe_discard_stale_ns (mnt_fd, snap_name, base_snap_name, - snap_discard_ns_fd) == EAGAIN) { + snap_discard_ns_fd, is_normal_mode) == EAGAIN) { return ESRCH; } // Remember the vanilla working directory so that we may attempt to restore it later. diff --git a/cmd/snap-confine/ns-support.h b/cmd/snap-confine/ns-support.h index 288ad10a109..2d3957aff47 100644 --- a/cmd/snap-confine/ns-support.h +++ b/cmd/snap-confine/ns-support.h @@ -92,7 +92,8 @@ void sc_close_mount_ns(struct sc_mount_ns *group); **/ int sc_join_preserved_ns(struct sc_mount_ns *group, struct sc_apparmor *apparmor, const char *base_snap_name, - const char *snap_name, int snap_discard_ns_fd); + const char *snap_name, int snap_discard_ns_fd, + bool is_normal_mode); /** * Join a preserved, per-user, mount namespace if one exists. diff --git a/cmd/snap-confine/snap-confine.c b/cmd/snap-confine/snap-confine.c index 063b9143723..2573d62095f 100644 --- a/cmd/snap-confine/snap-confine.c +++ b/cmd/snap-confine/snap-confine.c @@ -96,13 +96,16 @@ static void sc_maybe_fixup_udev(void) } typedef struct sc_invocation { + /* Things declared by the system. */ const char *base_snap_name; const char *security_tag; const char *snap_instance; + /* Things derived at runtime. */ + bool is_normal_mode; } sc_invocation; static void enter_classic_execution_environment(void); -static void enter_non_classic_execution_environment(const sc_invocation * inv, +static void enter_non_classic_execution_environment(sc_invocation * inv, struct sc_apparmor *aa, uid_t real_uid, gid_t real_gid, @@ -201,9 +204,10 @@ int main(int argc, char **argv) .snap_instance = snap_instance, .base_snap_name = base_snap_name, .security_tag = security_tag, + /* is_normal_mode is not probed yet */ }; /* For the ease of introducing inv to the if branch below. */ - const sc_invocation *inv = &invocation; + sc_invocation *inv = &invocation; struct sc_apparmor *aa = &apparmor; // TODO: check for similar situation and linux capabilities. @@ -284,7 +288,7 @@ static void enter_classic_execution_environment(void) debug("skipping sandbox setup, classic confinement in use"); } -static void enter_non_classic_execution_environment(const sc_invocation * inv, +static void enter_non_classic_execution_environment(sc_invocation * inv, struct sc_apparmor *aa, uid_t real_uid, gid_t real_gid, @@ -326,6 +330,12 @@ static void enter_non_classic_execution_environment(const sc_invocation * inv, struct sc_mount_ns *group = NULL; group = sc_open_mount_ns(inv->snap_instance); + // Check if we are running in normal mode with pivot root. Do this here + // because once on the inside of the transformed mount namespace we can no + // longer tell. + inv->is_normal_mode = sc_should_use_normal_mode(sc_classify_distro(), + inv->base_snap_name); + /* Stale mount namespace discarded or no mount namespace to join. We need to construct a new mount namespace ourselves. To capture it we will need a helper process so make one. */ @@ -333,7 +343,8 @@ static void enter_non_classic_execution_environment(const sc_invocation * inv, int retval = sc_join_preserved_ns(group, aa, inv->base_snap_name, inv->snap_instance, - snap_discard_ns_fd); + snap_discard_ns_fd, + inv->is_normal_mode); if (retval == ESRCH) { /* Create and populate the mount namespace. This performs all of the bootstrapping mounts, pivots into the new root filesystem and @@ -344,7 +355,7 @@ static void enter_non_classic_execution_environment(const sc_invocation * inv, } sc_populate_mount_ns(aa, snap_update_ns_fd, inv->base_snap_name, - inv->snap_instance); + inv->snap_instance, inv->is_normal_mode); /* Preserve the mount namespace. */ sc_preserve_populated_mount_ns(group);