support: Helper functions for entering namespaces

This commit is contained in:
Florian Weimer 2016-12-31 18:51:07 +01:00
parent a851999f61
commit 5707a64d94
8 changed files with 280 additions and 0 deletions

View File

@ -1,3 +1,15 @@
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]

View File

@ -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)

53
support/namespace.h Normal file
View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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>

36
support/xsocket.c Normal file
View File

@ -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;
}

27
support/xsocket.h Normal file
View File

@ -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 */