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 e113f22 commit 486710f
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 31 deletions.
58 changes: 34 additions & 24 deletions ns.c
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <sched.h>
#include <stdlib.h>
Expand Down Expand Up @@ -104,13 +105,21 @@ static int is_setns(const struct nsid *ns)
are entered via unshare (or not changed at all). */
static int cmp_nsids(const void *lhs, const void *rhs)
{
const struct nsid *lns = lhs;
const struct nsid *rns = rhs;
printf("\tcomparing lhs=%d (is_setns=%d) with rhs=%d (is_setns=%d): ",
lns->ns, is_setns(lhs),
rns->ns, is_setns(rhs));
int diff = is_setns(rhs) - is_setns(lhs);
if (diff != 0) {
printf("%d via setns diff\n", diff);
return diff;
}
/* Both namespaces are the same kind -- keep ordering intact by comparing
pointer values. */
return (int) ((intptr_t) lhs - (intptr_t) rhs);
diff = (int) ((intptr_t) lhs - (intptr_t) rhs);
printf("%d via pointer comparison\n", diff);
return diff;
}

static void ns_enter_one(struct nsid *ns)
Expand Down Expand Up @@ -140,6 +149,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 +162,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 486710f

Please sign in to comment.