summary refs log tree commit diff
path: root/support
diff options
context:
space:
mode:
authorFlorian Weimer <fweimer@redhat.com>2016-12-31 18:51:07 +0100
committerFlorian Weimer <fweimer@redhat.com>2016-12-31 18:51:07 +0100
commit5707a64d9462001f9c7c2e02d3f52cf8b0181658 (patch)
tree21d7c8e03848524dd858199032194665847ee7b5 /support
parenta851999f61ad7ceabc2a945a3c31c60e8c914a4b (diff)
downloadglibc-5707a64d9462001f9c7c2e02d3f52cf8b0181658.tar.gz
glibc-5707a64d9462001f9c7c2e02d3f52cf8b0181658.tar.xz
glibc-5707a64d9462001f9c7c2e02d3f52cf8b0181658.zip
support: Helper functions for entering namespaces
Diffstat (limited to 'support')
-rw-r--r--support/Makefile4
-rw-r--r--support/namespace.h53
-rw-r--r--support/support_become_root.c40
-rw-r--r--support/support_enter_network_namespace.c74
-rw-r--r--support/tst-support-namespace.c34
-rw-r--r--support/xsocket.c36
-rw-r--r--support/xsocket.h27
7 files changed, 268 insertions, 0 deletions
diff --git a/support/Makefile b/support/Makefile
index 4e9d42ef09..9544a08573 100644
--- a/support/Makefile
+++ b/support/Makefile
@@ -30,6 +30,8 @@ libsupport-routines = \
   ignore_stderr \
   oom_error \
   set_fortify_handler \
+  support_become_root \
+  support_enter_network_namespace \
   support_record_failure \
   support_test_main \
   support_test_verify_impl \
@@ -54,6 +56,7 @@ libsupport-routines = \
   xpthread_spin_lock \
   xpthread_spin_unlock \
   xrealloc \
+  xsocket \
   xwaitpid \
 
 libsupport-static-only-routines := $(libsupport-routines)
@@ -65,6 +68,7 @@ endif
 
 tests = \
   README-testing \
+  tst-support-namespace \
   tst-support_record_failure \
 
 ifeq ($(run-built-tests),yes)
diff --git a/support/namespace.h b/support/namespace.h
new file mode 100644
index 0000000000..4692907676
--- /dev/null
+++ b/support/namespace.h
@@ -0,0 +1,53 @@
+/* Entering namespaces for test case isolation.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef SUPPORT_NAMESPACE_H
+#define SUPPORT_NAMESPACE_H
+
+#include <stdbool.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/* Attempts to become root (or acquire root-like privileges), possibly
+   with the help of user namespaces.  Return true if (restricted) root
+   privileges could be attained in some way.  Print diagnostics to
+   standard output.
+
+   Note that this function generally has to be called before a process
+   becomes multi-threaded, otherwise it may fail with insufficient
+   privileges on systems which would support this operation for
+   single-threaded processes.  */
+bool support_become_root (void);
+
+/* Enter a network namespace (and a UTS namespace if possible) and
+   configure the loopback interface.  Return true if a network
+   namespace could be created.  Print diagnostics to standard output.
+   If a network namespace could be created, but networking in it could
+   not be configured, terminate the process.  It is recommended to
+   call support_become_root before this function so that the process
+   has sufficient privileges.  */
+bool support_enter_network_namespace (void);
+
+/* Return true if support_enter_network_namespace managed to enter a
+   UTS namespace.  */
+bool support_in_uts_namespace (void);
+
+__END_DECLS
+
+#endif
diff --git a/support/support_become_root.c b/support/support_become_root.c
new file mode 100644
index 0000000000..d13954c4dd
--- /dev/null
+++ b/support/support_become_root.c
@@ -0,0 +1,40 @@
+/* Acquire root privileges.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <support/namespace.h>
+
+#include <sched.h>
+#include <stdio.h>
+#include <unistd.h>
+
+bool
+support_become_root (void)
+{
+#ifdef CLONE_NEWUSER
+  if (unshare (CLONE_NEWUSER | CLONE_NEWNS) == 0)
+    /* Even if we do not have UID zero, we have extended privileges at
+       this point.  */
+    return true;
+#endif
+  if (setuid (0) != 0)
+    {
+      printf ("warning: could not become root outside namespace (%m)\n");
+      return false;
+    }
+  return true;
+}
diff --git a/support/support_enter_network_namespace.c b/support/support_enter_network_namespace.c
new file mode 100644
index 0000000000..3af18e6f5d
--- /dev/null
+++ b/support/support_enter_network_namespace.c
@@ -0,0 +1,74 @@
+/* Enter a network namespace.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <support/namespace.h>
+
+#include <net/if.h>
+#include <sched.h>
+#include <stdio.h>
+#include <string.h>
+#include <support/check.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <xsocket.h>
+
+static bool in_uts_namespace;
+
+bool
+support_enter_network_namespace (void)
+{
+#ifdef CLONE_NEWUTS
+  if (unshare (CLONE_NEWUTS) == 0)
+    in_uts_namespace = true;
+  else
+    printf ("warning: unshare (CLONE_NEWUTS) failed: %m\n");
+#endif
+
+#ifdef CLONE_NEWNET
+  if (unshare (CLONE_NEWNET) == 0)
+    {
+      /* Bring up the loopback interface.  */
+      int fd = xsocket (AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0);
+      struct ifreq req;
+      strcpy (req.ifr_name, "lo");
+      TEST_VERIFY_EXIT (ioctl (fd, SIOCGIFFLAGS, &req) == 0);
+      bool already_up = req.ifr_flags & IFF_UP;
+      if (already_up)
+        /* This means that we likely have not achieved isolation from
+           the parent namespace.  */
+        printf ("warning: loopback interface already exists"
+                " in new network namespace\n");
+      else
+        {
+          req.ifr_flags |= IFF_UP | IFF_RUNNING;
+          TEST_VERIFY_EXIT (ioctl (fd, SIOCSIFFLAGS, &req) == 0);
+        }
+      close (fd);
+
+      return !already_up;
+    }
+#endif
+  printf ("warning: could not enter network namespace\n");
+  return false;
+}
+
+bool
+support_in_uts_namespace (void)
+{
+  return in_uts_namespace;
+}
diff --git a/support/tst-support-namespace.c b/support/tst-support-namespace.c
new file mode 100644
index 0000000000..bd2a2a62e8
--- /dev/null
+++ b/support/tst-support-namespace.c
@@ -0,0 +1,34 @@
+/* Test entering namespaces.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+#include <support/namespace.h>
+
+static int
+do_test (void)
+{
+  if (support_become_root ())
+    printf ("info: acquired root-like privileges\n");
+  if (support_enter_network_namespace ())
+    printf ("info: entered network namespace\n");
+  if (support_in_uts_namespace ())
+    printf ("info: also entered UTS namespace\n");
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/support/xsocket.c b/support/xsocket.c
new file mode 100644
index 0000000000..9ebe63fc73
--- /dev/null
+++ b/support/xsocket.c
@@ -0,0 +1,36 @@
+/* socket with error checking.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <support/xsocket.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <support/check.h>
+
+int
+xsocket (int domain, int type, int protocol)
+{
+  int fd = socket (domain, type, protocol);
+  if (fd < 0)
+    {
+      support_record_failure ();
+      printf ("error: socket (%d, %d, %d): %m\n", domain, type, protocol);
+      exit (1);
+    }
+  return fd;
+}
diff --git a/support/xsocket.h b/support/xsocket.h
new file mode 100644
index 0000000000..e9ff49e54e
--- /dev/null
+++ b/support/xsocket.h
@@ -0,0 +1,27 @@
+/* Error-checking wrappers for socket functions.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef SUPPORT_XSOCKET_H
+#define SUPPORT_XSOCKET_H
+
+#include <sys/socket.h>
+#include <sys/types.h>
+
+int xsocket (int, int, int);
+
+#endif /* SUPPORT_XSOCKET_H */