summaryrefslogtreecommitdiff
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
parenta851999f61ad7ceabc2a945a3c31c60e8c914a4b (diff)
downloadglibc-5707a64d9462001f9c7c2e02d3f52cf8b0181658.tar.gz
support: Helper functions for entering namespaces
-rw-r--r--ChangeLog12
-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
8 files changed, 280 insertions, 0 deletions
diff --git a/ChangeLog b/ChangeLog
index 9685fde488..e7b2fa130b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
2016-12-31 Florian Weimer <fweimer@redhat.com>
+ * support/namespace.h: New file.
+ * support/support_become_root.c: Likewise.
+ * support/support_enter_network_namespace.c: Likewise.
+ * support/tst-support-namespace.c: Likewise.
+ * support/xsocket.c: Likewise.
+ * support/xsocket.h: Likewise.
+ * support/Makefile (libsupport-routines): Add support_become_root,
+ support_enter_network_namespace, xsocket.
+ (tests): Add tst-support-namespace.
+
+2016-12-31 Florian Weimer <fweimer@redhat.com>
+
[BZ #17252]
* posix/unistd.h (getentropy): Declare for __USE_MISC, not just
__USE_GNU.
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 */