diff options
author | Florian Weimer <fweimer@redhat.com> | 2016-12-31 18:51:07 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2016-12-31 18:51:07 +0100 |
commit | 5707a64d9462001f9c7c2e02d3f52cf8b0181658 (patch) | |
tree | 21d7c8e03848524dd858199032194665847ee7b5 | |
parent | a851999f61ad7ceabc2a945a3c31c60e8c914a4b (diff) | |
download | glibc-5707a64d9462001f9c7c2e02d3f52cf8b0181658.tar.gz glibc-5707a64d9462001f9c7c2e02d3f52cf8b0181658.tar.xz glibc-5707a64d9462001f9c7c2e02d3f52cf8b0181658.zip |
support: Helper functions for entering namespaces
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | support/Makefile | 4 | ||||
-rw-r--r-- | support/namespace.h | 53 | ||||
-rw-r--r-- | support/support_become_root.c | 40 | ||||
-rw-r--r-- | support/support_enter_network_namespace.c | 74 | ||||
-rw-r--r-- | support/tst-support-namespace.c | 34 | ||||
-rw-r--r-- | support/xsocket.c | 36 | ||||
-rw-r--r-- | support/xsocket.h | 27 |
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 */ |