Skip to content

Commit

Permalink
test: skip tests without permissions to create netns
Browse files Browse the repository at this point in the history
  • Loading branch information
thom311 committed Jan 12, 2025
1 parent 40b0c16 commit 36bf398
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 4 deletions.
13 changes: 12 additions & 1 deletion tests/cksuite-all-netns.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ START_TEST(cache_and_clone)
size_t i;
int r;

if (_nltst_skip_no_netns())
return;

for (i = 0; i < _NL_N_ELEMENTS(links); i++) {
if (links[i].add)
_nltst_add_link(NULL, links[i].ifname, links[i].kind,
Expand Down Expand Up @@ -132,11 +135,16 @@ START_TEST(test_create_iface)
_nl_auto_rtnl_link struct rtnl_link *link2 = NULL;
_nl_auto_rtnl_link struct rtnl_link *peer = NULL;
_nltst_auto_delete_link const char *IFNAME_DUMMY = NULL;
_nltst_auto_delete_link const char *IFNAME = "ifname";
_nltst_auto_delete_link const char *IFNAME = NULL;
int ifindex_dummy;
uint32_t u32;
int r;

if (_nltst_skip_no_netns())
return;

IFNAME = "ifname";

switch (TEST_IDX) {
case 0:
link = _nltst_assert(rtnl_link_bridge_alloc());
Expand Down Expand Up @@ -317,6 +325,9 @@ START_TEST(route_1)
_nl_auto_nl_socket struct nl_sock *sk = NULL;
_nl_auto_nl_cache struct nl_cache *cache = NULL;

if (_nltst_skip_no_netns())
return;

if (_nltst_skip_no_iproute2("route_1"))
return;

Expand Down
48 changes: 45 additions & 3 deletions tests/nl-test-util.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ uint32_t _nltst_rand_u32(void)

struct nltst_netns {
int canary;
bool is_unshared;
};

/*****************************************************************************/
Expand All @@ -103,7 +104,6 @@ static struct {
void nltst_netns_fixture_setup(void)
{
ck_assert(!_netns_fixture_global.nsdata);

_netns_fixture_global.nsdata = nltst_netns_enter();
_assert_nltst_netns(_netns_fixture_global.nsdata);
}
Expand All @@ -114,6 +114,20 @@ void nltst_netns_fixture_teardown(void)
_nl_clear_pointer(&_netns_fixture_global.nsdata, nltst_netns_leave);
}

bool nltst_netns_has_netns(void)
{
_assert_nltst_netns(_netns_fixture_global.nsdata);
return _netns_fixture_global.nsdata->is_unshared;
}

bool _nltst_skip_no_netns(void)
{
if (nltst_netns_has_netns())
return false;
printf("skip test due to having no private netns\n");
return true;
}

/*****************************************************************************/

static void unshare_user(void)
Expand All @@ -125,6 +139,10 @@ static void unshare_user(void)

/* Become a root in new user NS. */
r = unshare(CLONE_NEWUSER);
if (r != 0 && errno == EPERM) {
/* No permissions? Ignore. Will be handled later. */
return;
}
_nltst_assert_errno(r == 0);

/* Since Linux 3.19 we have to disable setgroups() in order to map users.
Expand All @@ -149,14 +167,28 @@ static void unshare_user(void)
}
r = fprintf(f, "0 %d 1", uid);
_nltst_assert_errno(r > 0);
_nltst_fclose(f);
r = fclose(f);
if (r != 0 && errno == EPERM) {
/* Oddly, it seems close() can fail at this point. Ignore it,
* but we probably will be unable to unshare (which we handle
* later).
*/
} else
_nltst_assert_errno(r == 0);

/* Map current GID to root in NS to be created. */
f = fopen("/proc/self/gid_map", "we");
_nltst_assert_errno(f);
r = fprintf(f, "0 %d 1", gid);
_nltst_assert_errno(r > 0);
_nltst_fclose(f);
r = fclose(f);
if (r != 0 && errno == EPERM) {
/* Oddly, it seems close() can fail at this point. Ignore it, but
* we probably will be unable to unshare (which we handle
* later).
*/
} else
_nltst_assert_errno(r == 0);
}

struct nltst_netns *nltst_netns_enter(void)
Expand All @@ -172,13 +204,23 @@ struct nltst_netns *nltst_netns_enter(void)
unshare_user();

r = unshare(CLONE_NEWNET | CLONE_NEWNS);
if (r != 0 && errno == EPERM) {
/* The system is probably sandboxed somehow and we are unable
* to create a private netns. That seems questionable, because
* a point of a private netns is to sandbox an application.
* Not having permissions to sandbox sounds bad.
*
* Anyway. We accept this and will later skip some tests. */
return nsdata;
}
_nltst_assert_errno(r == 0);

/* We need a read-only /sys so that the platform knows there's no udev. */
mount(NULL, "/sys", "sysfs", MS_SLAVE, NULL);
r = mount("sys", "/sys", "sysfs", MS_RDONLY, NULL);
_nltst_assert_errno(r == 0);

nsdata->is_unshared = true;
return nsdata;
}

Expand Down
3 changes: 3 additions & 0 deletions tests/nl-test-util.h
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,9 @@ char **_nltst_strtokv(const char *str);

void nltst_netns_fixture_setup(void);
void nltst_netns_fixture_teardown(void);
bool nltst_netns_has_netns(void);

bool _nltst_skip_no_netns(void);

struct nltst_netns;

Expand Down

0 comments on commit 36bf398

Please sign in to comment.