@@ -84,6 +84,7 @@ uint32_t _nltst_rand_u32(void)
8484
8585struct nltst_netns {
8686 int canary ;
87+ bool is_unshared ;
8788};
8889
8990/*****************************************************************************/
@@ -114,6 +115,30 @@ void nltst_netns_fixture_teardown(void)
114115 _nl_clear_pointer (& _netns_fixture_global .nsdata , nltst_netns_leave );
115116}
116117
118+ bool nltst_netns_fixture_is_unshared (void )
119+ {
120+ _assert_nltst_netns (_netns_fixture_global .nsdata );
121+ return _netns_fixture_global .nsdata -> is_unshared ;
122+ }
123+
124+ bool _nltst_skip_no_netns (void )
125+ {
126+ if (nltst_netns_fixture_is_unshared ())
127+ return false;
128+
129+ if (_nltst_in_ci ()) {
130+ /* In CI, we exepect normal tests to have a netns, but under
131+ * valgrind this might fail. */
132+ if (!_nl_streq0 (getenv ("NLTST_IN_CI_VALGRIND" ), "1" )) {
133+ ck_abort_msg (
134+ "Unable to create private netns under CI (NLTST_IN_CI=1) while not running valgind (NLTST_IN_CI_VALGRIND!=1)" );
135+ }
136+ }
137+
138+ printf ("skip test due to having no private netns\n" );
139+ return true;
140+ }
141+
117142/*****************************************************************************/
118143
119144static void unshare_user (void )
@@ -125,6 +150,10 @@ static void unshare_user(void)
125150
126151 /* Become a root in new user NS. */
127152 r = unshare (CLONE_NEWUSER );
153+ if (r != 0 && errno == EPERM ) {
154+ /* No permissions? Ignore. Will be handled later. */
155+ return ;
156+ }
128157 _nltst_assert_errno (r == 0 );
129158
130159 /* Since Linux 3.19 we have to disable setgroups() in order to map users.
@@ -149,14 +178,28 @@ static void unshare_user(void)
149178 }
150179 r = fprintf (f , "0 %d 1" , uid );
151180 _nltst_assert_errno (r > 0 );
152- _nltst_fclose (f );
181+ r = fclose (f );
182+ if (r != 0 && errno == EPERM ) {
183+ /* Oddly, it seems close() can fail at this point. Ignore it,
184+ * but we probably will be unable to unshare (which we handle
185+ * later).
186+ */
187+ } else
188+ _nltst_assert_errno (r == 0 );
153189
154190 /* Map current GID to root in NS to be created. */
155191 f = fopen ("/proc/self/gid_map" , "we" );
156192 _nltst_assert_errno (f );
157193 r = fprintf (f , "0 %d 1" , gid );
158194 _nltst_assert_errno (r > 0 );
159- _nltst_fclose (f );
195+ r = fclose (f );
196+ if (r != 0 && errno == EPERM ) {
197+ /* Oddly, it seems close() can fail at this point. Ignore it, but
198+ * we probably will be unable to unshare (which we handle
199+ * later).
200+ */
201+ } else
202+ _nltst_assert_errno (r == 0 );
160203}
161204
162205struct nltst_netns * nltst_netns_enter (void )
@@ -172,13 +215,23 @@ struct nltst_netns *nltst_netns_enter(void)
172215 unshare_user ();
173216
174217 r = unshare (CLONE_NEWNET | CLONE_NEWNS );
218+ if (r != 0 && errno == EPERM ) {
219+ /* The system is probably sandboxed somehow and we are unable
220+ * to create a private netns. That seems questionable, because
221+ * a point of a private netns is to sandbox an application.
222+ * Not having permissions to sandbox sounds bad.
223+ *
224+ * Anyway. We accept this and will later skip some tests. */
225+ return nsdata ;
226+ }
175227 _nltst_assert_errno (r == 0 );
176228
177229 /* We need a read-only /sys so that the platform knows there's no udev. */
178230 mount (NULL , "/sys" , "sysfs" , MS_SLAVE , NULL );
179231 r = mount ("sys" , "/sys" , "sysfs" , MS_RDONLY , NULL );
180232 _nltst_assert_errno (r == 0 );
181233
234+ nsdata -> is_unshared = true;
182235 return nsdata ;
183236}
184237
0 commit comments