]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
tests: (test_mkfds::foreign-sockets) new factory
authorMasatake YAMATO <yamato@redhat.com>
Wed, 18 Sep 2024 19:04:40 +0000 (04:04 +0900)
committerMasatake YAMATO <yamato@redhat.com>
Tue, 1 Oct 2024 17:43:12 +0000 (02:43 +0900)
The way to make a socket in another net namespace is
suggested by Dmitry Safonov.

Signed-off-by: Masatake YAMATO <yamato@redhat.com>
tests/helpers/test_mkfds.c

index 0f20435df39cb33b31932e3a3a6ecfd3173caa47..309fa6e290a1de94937ac7697325c19b3d450bd7 100644 (file)
@@ -3091,6 +3091,68 @@ static void *make_sockdiag(const struct factory *factory, struct fdesc fdescs[],
        return NULL;
 }
 
+static void *make_foreign_sockets(const struct factory *factory _U_, struct fdesc fdescs[],
+                                 int argc _U_, char ** argv _U_)
+{
+       int foreign_sd[2];      /* These two */
+       int original_ns;
+       int foreign_ns;
+       struct stat foreign_ns_sb;
+
+       original_ns = open("/proc/self/ns/net", O_RDONLY);
+       if (original_ns < 0)
+               err(EXIT_FAILURE, "failed in open(/proc/self/ns/net) before unshare");
+
+       if (unshare(CLONE_NEWNET) < 0)
+               err((errno == EPERM? EXIT_EPERM: EXIT_FAILURE),
+                   "failed in unshare()");
+
+       foreign_ns = open("/proc/self/ns/net", O_RDONLY);
+       if (foreign_ns < 0)
+               err(EXIT_FAILURE, "failed in open(/proc/self/ns/net) after unshare");
+       if (fstat(foreign_ns, &foreign_ns_sb) < 0)
+                       err(EXIT_FAILURE, "failed in fstat(NETNS)");
+
+       if (socketpair(AF_UNIX, SOCK_STREAM, 0, foreign_sd) < 0)
+               err(EXIT_FAILURE, "failed in socketpair(SOCK_STREAM)");
+
+       if (setns(original_ns, CLONE_NEWNET) < 0)
+               err(EXIT_FAILURE, "failed in setns()");
+
+       close(foreign_ns);      /* Make the namespace unreadable. */
+       close(original_ns);
+
+       for (int i = 0; i < 2; i++) {
+               if (foreign_sd[i] != fdescs[i].fd) {
+                       if (dup2(foreign_sd[i], fdescs[i].fd) < 0)
+                               err(EXIT_FAILURE, "failed to dup %d -> %d",
+                                   foreign_sd[i], fdescs[i].fd);
+                       close(foreign_sd[i]);
+               }
+               fdescs[i] = (struct fdesc){
+                       .fd    = fdescs[i].fd,
+                       .close = close_fdesc,
+                       .data  = NULL
+               };
+       }
+
+       return xmemdup(&foreign_ns_sb.st_ino, sizeof(foreign_ns_sb.st_ino));
+}
+
+static void report_foreign_sockets(const struct factory *factory _U_,
+                                  int nth, void *data, FILE *fp)
+{
+       if (nth == 0) {
+               long *netns_id = (long *)data;
+               fprintf(fp, "%ld", *netns_id);
+       }
+}
+
+static void free_foreign_sockets(const struct factory * factory _U_, void *data)
+{
+       free (data);
+}
+
 #define PARAM_END { .name = NULL, }
 static const struct factory factories[] = {
        {
@@ -3982,6 +4044,20 @@ static const struct factory factories[] = {
                        PARAM_END
                }
        },
+       {
+               .name = "foreign-sockets",
+               .desc = "import sockets made in a foreign network namespaec",
+               .priv = true,
+               .N = 2,
+               .EX_N = 0,
+               .EX_O = 1,
+               .make = make_foreign_sockets,
+               .report = report_foreign_sockets,
+               .free = free_foreign_sockets,
+               .params = (struct parameter []) {
+                       PARAM_END
+               }
+       },
 };
 
 static int count_parameters(const struct factory *factory)