diff mbox series

[1/2] Implement tst_setup_netns() helper function

Message ID 20221125153453.19323-1-mdoucha@suse.cz
State Accepted
Headers show
Series [1/2] Implement tst_setup_netns() helper function | expand

Commit Message

Martin Doucha Nov. 25, 2022, 3:34 p.m. UTC
Namespace setup boilerplate for network tests is getting more complicated
with the need to check or modify some sysfiles. Move it into LTP library.

Signed-off-by: Martin Doucha <mdoucha@suse.cz>
---

Here is the promised .save_restore follow-up patchset which fixes network
namespace setup without root privileges. Since the exact same boilerplate
code is repeated in multiple tests, I've decided to introduce a helper
function to simplify test setup.

 include/tst_net.h | 16 ++++++++++++++++
 lib/tst_net.c     | 23 +++++++++++++++++++++++
 2 files changed, 39 insertions(+)

Comments

Petr Vorel Nov. 25, 2022, 4:43 p.m. UTC | #1
Hi Martin,
> Namespace setup boilerplate for network tests is getting more complicated
> with the need to check or modify some sysfiles. Move it into LTP library.
+1

Reviewed-by: Petr Vorel <pvorel@suse.cz>

>  #define TST_NO_DEFAULT_MAIN
>  #include "tst_test.h"
>  #include "tst_net.h"
>  #include "tst_private.h"
> +#include "lapi/namespaces_constants.h"
WDYT about adding <sched.h> to lapi/namespaces_constants.h?
(not related to this patchset at all).

Kind regards,
Petr
Petr Vorel Nov. 25, 2022, 5:01 p.m. UTC | #2
Hi Martin,

> +void tst_setup_netns(void)
> +{
> +	int real_uid = getuid();
> +	int real_gid = getgid();
> +	int nscount = 1;
> +
> +	if (!access("/proc/sys/user/max_user_namespaces", F_OK)) {
Out of curiosity, this can happen only on old kernel, which does not support
user namespaces (kernel < 3.8) ? I guess there must be other case,
I suppose you would not bother about 3.8, right?

Also asking that if not readable we don't TCONF (int nscount = 1).

Kind regards,
Petr

> +		SAFE_FILE_SCANF("/proc/sys/user/max_user_namespaces", "%d",
> +			&nscount);
> +	}
> +
> +	if (!nscount)
> +		tst_brk(TCONF, "User namespaces are disabled");
> +
> +	SAFE_UNSHARE(CLONE_NEWUSER);
> +	SAFE_UNSHARE(CLONE_NEWNET);
> +	SAFE_FILE_PRINTF("/proc/self/setgroups", "deny");
> +	SAFE_FILE_PRINTF("/proc/self/uid_map", "0 %d 1", real_uid);
> +	SAFE_FILE_PRINTF("/proc/self/gid_map", "0 %d 1", real_gid);
> +}
Martin Doucha Nov. 25, 2022, 5:09 p.m. UTC | #3
On 25. 11. 22 18:01, Petr Vorel wrote:
> Hi Martin,
> 
>> +void tst_setup_netns(void)
>> +{
>> +	int real_uid = getuid();
>> +	int real_gid = getgid();
>> +	int nscount = 1;
>> +
>> +	if (!access("/proc/sys/user/max_user_namespaces", F_OK)) {
> Out of curiosity, this can happen only on old kernel, which does not support
> user namespaces (kernel < 3.8) ? I guess there must be other case,
> I suppose you would not bother about 3.8, right?
> 
> Also asking that if not readable we don't TCONF (int nscount = 1).

This is very much still happening on kernel 4.4.180 even though user 
namespaces are supported and enabled by default. That's why 
tst_setup_netns() fails with TCONF only when max_user_namespaces sysfile 
exists, is read-only AND the value inside is zero.
Petr Vorel Nov. 25, 2022, 5:17 p.m. UTC | #4
> On 25. 11. 22 18:01, Petr Vorel wrote:
> > Hi Martin,

> > > +void tst_setup_netns(void)
> > > +{
> > > +	int real_uid = getuid();
> > > +	int real_gid = getgid();
> > > +	int nscount = 1;
> > > +
> > > +	if (!access("/proc/sys/user/max_user_namespaces", F_OK)) {
> > Out of curiosity, this can happen only on old kernel, which does not support
> > user namespaces (kernel < 3.8) ? I guess there must be other case,
> > I suppose you would not bother about 3.8, right?

> > Also asking that if not readable we don't TCONF (int nscount = 1).

> This is very much still happening on kernel 4.4.180 even though user
> namespaces are supported and enabled by default. That's why
> tst_setup_netns() fails with TCONF only when max_user_namespaces sysfile
> exists, is read-only AND the value inside is zero.

Makes sense.

And missing file: if I'm correct sysctl files were added in v4.9-rc1 in
25f9c0817c53 ("userns: Generalize the user namespace count into ucount")

Kind regards,
Petr
Petr Vorel Nov. 25, 2022, 5:20 p.m. UTC | #5
Hi Martin,

Patchset merged, thanks for this cleanup.

Kind regards,
Petr
diff mbox series

Patch

diff --git a/include/tst_net.h b/include/tst_net.h
index daefdd9d9..9d8b842dd 100644
--- a/include/tst_net.h
+++ b/include/tst_net.h
@@ -32,4 +32,20 @@  void safe_getaddrinfo(const char *file, const int lineno, const char *src_addr,
 					  const char *port, const struct addrinfo *hints,
 					  struct addrinfo **addr_info);
 
+/*
+ * Create new network namespace for netdevice/socket tests. A test which calls
+ * tst_setup_netns() must declare the following entries in its struct tst_test:
+ *
+ * .needs_kconfigs = (const char *[]) {
+ *	"CONFIG_USER_NS=y",
+ *	"CONFIG_NET_NS=y",
+ *	NULL
+ * },
+ * .save_restore = (const struct tst_path_val[]) {
+ *	{"/proc/sys/user/max_user_namespaces", "1024", TST_SR_SKIP},
+ *	{}
+ * },
+ */
+void tst_setup_netns(void);
+
 #endif /* TST_NET_H_ */
diff --git a/lib/tst_net.c b/lib/tst_net.c
index de343bb39..61fc0ea76 100644
--- a/lib/tst_net.c
+++ b/lib/tst_net.c
@@ -8,11 +8,13 @@ 
 #include <netdb.h>
 #include <string.h>
 #include <stdlib.h>
+#include <unistd.h>
 
 #define TST_NO_DEFAULT_MAIN
 #include "tst_test.h"
 #include "tst_net.h"
 #include "tst_private.h"
+#include "lapi/namespaces_constants.h"
 
 void tst_print_svar(const char *name, const char *val)
 {
@@ -220,3 +222,24 @@  void safe_getaddrinfo(const char *file, const int lineno, const char *src_addr,
 	if (!*addr_info)
 		tst_brk_(file, lineno, TBROK, "failed to get the address");
 }
+
+void tst_setup_netns(void)
+{
+	int real_uid = getuid();
+	int real_gid = getgid();
+	int nscount = 1;
+
+	if (!access("/proc/sys/user/max_user_namespaces", F_OK)) {
+		SAFE_FILE_SCANF("/proc/sys/user/max_user_namespaces", "%d",
+			&nscount);
+	}
+
+	if (!nscount)
+		tst_brk(TCONF, "User namespaces are disabled");
+
+	SAFE_UNSHARE(CLONE_NEWUSER);
+	SAFE_UNSHARE(CLONE_NEWNET);
+	SAFE_FILE_PRINTF("/proc/self/setgroups", "deny");
+	SAFE_FILE_PRINTF("/proc/self/uid_map", "0 %d 1", real_uid);
+	SAFE_FILE_PRINTF("/proc/self/gid_map", "0 %d 1", real_gid);
+}