Skip to content

Commit

Permalink
NOMERGE make namespace order verbose
Browse files Browse the repository at this point in the history
  • Loading branch information
yabberyabber committed Nov 27, 2024
1 parent 0632120 commit 084399c
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 55 deletions.
72 changes: 24 additions & 48 deletions ns.c
Original file line number Diff line number Diff line change
Expand Up @@ -88,31 +88,6 @@ void opts_to_nsactions(const char *shares[], enum nsaction *nsactions)
}
}

static int is_setns(const struct nsid *ns)
{
switch (ns->action) {
case NSACTION_UNSHARE:
case NSACTION_SHARE_WITH_PARENT:
return 0;
default:
return 1;
}
}

/* cmp_nsids compares two ns IDs in a stable manner, such that
namespaces that are entered via setns are sorted before those that
are entered via unshare (or not changed at all). */
static int cmp_nsids(const void *lhs, const void *rhs)
{
int diff = is_setns(rhs) - is_setns(lhs);
if (diff != 0) {
return diff;
}
/* Both namespaces are the same kind -- keep ordering intact by comparing
pointer values. */
return (int) ((intptr_t) lhs - (intptr_t) rhs);
}

static void ns_enter_one(struct nsid *ns)
{
switch (ns->action) {
Expand Down Expand Up @@ -140,6 +115,8 @@ static void ns_enter_one(struct nsid *ns)
}
}

// Note that for namespaces that want to enter into a specific namespace,
// we actually setns those before forking.
static bool is_postfork_ns(struct nsid *ns)
{
/* For now, only the cgroup namespace needs to be unshared postfork */
Expand All @@ -151,40 +128,39 @@ void ns_enter_prefork(struct nsid *namespaces, size_t *len)
/* Enter all relevant namespaces. It's hard to check in advance which
namespaces are supported, so we unshare them one by one in order. */

/* If we have CAP_SYS_ADMIN from the get-go, starting by entering
the userns may restrict us from joining additional namespaces, so
we rearrange the order so that we setns into target nsfs files first. */
if (capable(BST_CAP_SYS_ADMIN)) {
qsort(namespaces, *len, sizeof (namespaces[0]),
cmp_nsids);
}

struct nsid *first_postfork = NULL;
// First we setns the things that have a specific fd to share into.
struct nsid *ns = &namespaces[0];
for (; ns < namespaces + *len; ++ns) {
if (ns->action != NSACTION_SHARE_WITH_PARENT && is_postfork_ns(ns)) {
first_postfork = ns;
break;
}
if (ns->action < 0) {
continue;
}
ns_enter_one(ns);
}

size_t i = 0;
for (; ns < namespaces + *len; ++ns, ++i) {
if (first_postfork != NULL && !is_postfork_ns(ns)) {
errx(1, "incompatible options: %s namespace must be entered before "
"forking, but must be done after %s namespace is entered post-fork.",
ns_name(ns->ns),
ns_name(first_postfork->ns));
}
namespaces[i] = *ns;
// Then setns the things that just need a blanket unshare (postfork
// namespaces with NSACTION_UNSHARE need to be shard post-fork).
ns = &namespaces[0];
for (; ns < namespaces + *len; ++ns) {
if (is_postfork_ns(ns)) {
continue;
}
if (ns->action >= 0) {
continue;
}
ns_enter_one(ns);
}
*len = i;
}

void ns_enter_postfork(struct nsid *namespaces, size_t len)
{
for (struct nsid *ns = &namespaces[0]; ns < namespaces + len; ++ns) {
if (!is_postfork_ns(ns)) {
continue;
}
if (ns->action > 0) {
// If there is an fd action then we already did this prefork.
continue;
}
ns_enter_one(ns);
}
}
14 changes: 7 additions & 7 deletions ns.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ enum {

enum nstype {
NS_CGROUP = 0,
NS_IPC,
NS_MNT,
NS_NET,
NS_PID,
NS_TIME,
NS_USER,
NS_UTS,
NS_IPC, // 1
NS_MNT, // 2
NS_NET, // 3
NS_PID, // 4
NS_TIME,// 5
NS_USER,// 6
NS_UTS, // 7

MAX_NS
};
Expand Down

0 comments on commit 084399c

Please sign in to comment.