Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/snap-confine: introduce sc_invocation #6571

Merged
merged 4 commits into from
Mar 7, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
78 changes: 61 additions & 17 deletions cmd/snap-confine/snap-confine.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat!


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.
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand 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);
Expand All @@ -274,15 +305,17 @@ 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
("unsharing the mount namespace (per-user)");
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
Expand All @@ -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.
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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)
{
}