diff --git a/cmd/snap-confine/snap-confine.c b/cmd/snap-confine/snap-confine.c index a129317e4d6..0534e0b4754 100644 --- a/cmd/snap-confine/snap-confine.c +++ b/cmd/snap-confine/snap-confine.c @@ -95,6 +95,19 @@ static void sc_maybe_fixup_udev(void) } } +typedef struct sc_invocation { + const char *base_snap_name; + const char *security_tag; + const char *snap_instance; +} sc_invocation; + +static void enter_classic_execution_environment(void); +static void enter_non_classic_execution_environment(const sc_invocation * inv, + struct sc_apparmor *aa, + uid_t real_uid, + gid_t real_gid, + gid_t saved_gid); + int main(int argc, char **argv) { // Use our super-defensive parser to figure out what we've been asked to do. @@ -182,9 +195,22 @@ int main(int argc, char **argv) " but should be. Refusing to continue to avoid" " permission escalation attacks"); } + + /* Invocation helps to pass relevant data to various parts of snap-confine. */ + sc_invocation invocation = { + .snap_instance = snap_instance, + .base_snap_name = base_snap_name, + .security_tag = security_tag, + }; + /* For the ease of introducing inv to the if branch below. */ + const sc_invocation *inv = &invocation; + struct sc_apparmor *aa = &apparmor; + // TODO: check for similar situation and linux capabilities. if (geteuid() == 0) { if (classic_confinement) { + /* TODO: move everything into this call */ + enter_classic_execution_environment(); /* 'classic confinement' is designed to run without the sandbox * inside the shared namespace. Specifically: * - snap-confine skips using the snap-specific mount namespace @@ -195,6 +221,11 @@ int main(int argc, char **argv) debug ("skipping sandbox setup, classic confinement in use"); } else { + /* TODO: move everything into this call */ + enter_non_classic_execution_environment(inv, aa, + real_uid, + real_gid, + saved_gid); /* snap-confine uses privately-shared /run/snapd/ns to store * bind-mounted mount namespaces of each snap. In the case that * snap-confine is invoked from the mount namespace it typically @@ -229,19 +260,19 @@ int main(int argc, char **argv) snap_discard_ns_fd = sc_open_snap_discard_ns(); // Do per-snap initialization. - int snap_lock_fd = sc_lock_snap(snap_instance); + int snap_lock_fd = sc_lock_snap(inv->snap_instance); debug("initializing mount namespace: %s", - snap_instance); + inv->snap_instance); struct sc_mount_ns *group = NULL; - group = sc_open_mount_ns(snap_instance); + group = sc_open_mount_ns(inv->snap_instance); /* 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. */ - sc_fork_helper(group, &apparmor); - int retval = sc_join_preserved_ns(group, &apparmor, - base_snap_name, - snap_instance, + sc_fork_helper(group, aa); + int retval = sc_join_preserved_ns(group, aa, + inv->base_snap_name, + inv->snap_instance, snap_discard_ns_fd); if (retval == ESRCH) { /* Create and populate the mount namespace. This performs all @@ -253,10 +284,10 @@ int main(int argc, char **argv) if (unshare(CLONE_NEWNS) < 0) { die("cannot unshare the mount namespace"); } - sc_populate_mount_ns(&apparmor, + sc_populate_mount_ns(aa, snap_update_ns_fd, - base_snap_name, - snap_instance); + inv->base_snap_name, + inv->snap_instance); /* Preserve the mount namespace. */ sc_preserve_populated_mount_ns(group); @@ -274,6 +305,7 @@ int main(int argc, char **argv) ("joining preserved per-user mount namespace"); retval = sc_join_preserved_per_user_ns(group, + inv-> snap_instance); if (retval == ESRCH) { debug @@ -281,8 +313,9 @@ int main(int argc, char **argv) if (unshare(CLONE_NEWNS) < 0) { die("cannot unshare the mount namespace"); } - sc_setup_user_mounts(&apparmor, + sc_setup_user_mounts(aa, snap_update_ns_fd, + inv-> snap_instance); /* Preserve the mount per-user namespace. But only if the * experimental feature is enabled. This way if the feature is @@ -300,7 +333,6 @@ int main(int argc, char **argv) } } } - // Associate each snap process with a dedicated snap freezer // control group. This simplifies testing if any processes // belonging to a given snap are still alive. @@ -312,14 +344,13 @@ int main(int argc, char **argv) die("cannot set effective group id to root"); } } - sc_cgroup_freezer_join(snap_instance, getpid()); + sc_cgroup_freezer_join(inv->snap_instance, getpid()); if (geteuid() == 0 && real_gid != 0) { if (setegid(real_gid) != 0) { die("cannot set effective group id to %d", real_gid); } } - sc_unlock(snap_lock_fd); sc_close_mount_ns(group); @@ -350,8 +381,9 @@ int main(int argc, char **argv) } } struct snappy_udev udev_s; - if (snappy_udev_init(security_tag, &udev_s) == 0) - setup_devices_cgroup(security_tag, &udev_s); + if (snappy_udev_init(inv->security_tag, &udev_s) == 0) + setup_devices_cgroup(inv->security_tag, + &udev_s); snappy_udev_cleanup(&udev_s); } // The rest does not so temporarily drop privs back to calling @@ -372,7 +404,7 @@ int main(int argc, char **argv) setup_user_xdg_runtime_dir(); #endif // https://wiki.ubuntu.com/SecurityTeam/Specifications/SnappyConfinement - sc_maybe_aa_change_onexec(&apparmor, security_tag); + sc_maybe_aa_change_onexec(aa, security_tag); #ifdef HAVE_SECCOMP if (sc_apply_seccomp_profile_for_security_tag(security_tag)) { /* If the process is not explicitly unconfined then load the global @@ -409,3 +441,15 @@ int main(int argc, char **argv) perror("execv failed"); return 1; } + +static void enter_classic_execution_environment(void) +{ +} + +static void enter_non_classic_execution_environment(const sc_invocation * inv, + struct sc_apparmor *aa, + uid_t real_uid, + gid_t real_gid, + gid_t saved_gid) +{ +}