/* Linux namespaces(7) support.
- Copyright (C) 2015 Free Software Foundation, Inc.
+ Copyright (C) 2015-2021 Free Software Foundation, Inc.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#include "common-defs.h"
+#include "gdbsupport/common-defs.h"
#include "nat/linux-namespaces.h"
-#include "filestuff.h"
+#include "gdbsupport/filestuff.h"
#include <fcntl.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
-#include "gdb_wait.h"
+#include "gdbsupport/gdb_wait.h"
#include <signal.h>
#include <sched.h>
+#include "gdbsupport/scope-exit.h"
/* See nat/linux-namespaces.h. */
-int debug_linux_namespaces;
+bool debug_linux_namespaces;
+
+/* Handle systems without fork. */
+
+static inline pid_t
+do_fork (void)
+{
+#ifdef HAVE_FORK
+ return fork ();
+#else
+ errno = ENOSYS;
+ return -1;
+#endif
+}
/* Handle systems without setns. */
-#ifndef HAVE_SETNS
-static int
-setns (int fd, int nstype)
+static inline int
+do_setns (int fd, int nstype)
{
-#ifdef __NR_setns
+#ifdef HAVE_SETNS
+ return setns (fd, nstype);
+#elif defined __NR_setns
return syscall (__NR_setns, fd, nstype);
#else
errno = ENOSYS;
return -1;
#endif
}
+
+/* Handle systems without MSG_CMSG_CLOEXEC. */
+
+#ifndef MSG_CMSG_CLOEXEC
+#define MSG_CMSG_CLOEXEC 0
#endif
/* A Linux namespace. */
- TYPE (enum mnsh_msg_type, always sent) - the message type.
- INT1 and
- INT2 (int, always sent, though not always used) - two
- values whose meaning is message-type-dependent.
+ values whose meaning is message-type-dependent.
See enum mnsh_msg_type documentation below.
- FD (int, optional, sent using SCM_RIGHTS) - an open file
- descriptor.
+ descriptor.
- BUF (unstructured data, optional) - some data with message-
- type-dependent meaning.
+ type-dependent meaning.
Note that the helper process is the child of a call to fork,
so all code in the helper must be async-signal-safe. */
{
debug_printf ("mnsh: send: ");
mnsh_debug_print_message (type, fd, int1, int2, buf, bufsiz);
- debug_printf (" -> %ld\n", size);
+ debug_printf (" -> %s\n", pulongest (size));
}
return size;
if (size < 0)
{
if (debug_linux_namespaces)
- debug_printf ("namespace-helper: recv failed (%ld)\n", size);
+ debug_printf ("namespace-helper: recv failed (%s)\n",
+ pulongest (size));
mnsh_maybe_mourn_peer ();
if (size < fixed_size || (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)))
{
if (debug_linux_namespaces)
- debug_printf ("namespace-helper: recv truncated (%ld 0x%x)\n",
- size, msg.msg_flags);
+ debug_printf ("namespace-helper: recv truncated (%s 0x%x)\n",
+ pulongest (size), msg.msg_flags);
mnsh_maybe_mourn_peer ();
static ssize_t
mnsh_handle_setns (int sock, int fd, int nstype)
{
- int result = setns (fd, nstype);
+ int result = do_setns (fd, nstype);
return mnsh_return_int (sock, result, errno);
}
while (1)
{
enum mnsh_msg_type type;
- int fd, int1, int2;
+ int fd = -1, int1, int2;
char buf[PATH_MAX];
ssize_t size, response = -1;
if (gdb_socketpair_cloexec (AF_UNIX, SOCK_STREAM, 0, sv) < 0)
return NULL;
- h.pid = fork ();
+ h.pid = do_fork ();
if (h.pid < 0)
{
int saved_errno = errno;
static enum mnsh_fs_code
linux_mntns_access_fs (pid_t pid)
{
- struct cleanup *old_chain;
struct linux_ns *ns;
struct stat sb;
struct linux_mnsh *helper;
ssize_t size;
- int fd, saved_errno;
+ int fd;
if (pid == getpid ())
return MNSH_FS_DIRECT;
if (ns == NULL)
return MNSH_FS_DIRECT;
- old_chain = make_cleanup (null_cleanup, NULL);
-
fd = gdb_open_cloexec (linux_ns_filename (ns, pid), O_RDONLY, 0);
if (fd < 0)
- goto error;
+ return MNSH_FS_ERROR;
- old_chain = make_cleanup_close (fd);
+ SCOPE_EXIT
+ {
+ int save_errno = errno;
+ close (fd);
+ errno = save_errno;
+ };
if (fstat (fd, &sb) != 0)
- goto error;
+ return MNSH_FS_ERROR;
if (sb.st_ino == ns->id)
- {
- do_cleanups (old_chain);
-
- return MNSH_FS_DIRECT;
- }
+ return MNSH_FS_DIRECT;
helper = linux_mntns_get_helper ();
if (helper == NULL)
- goto error;
+ return MNSH_FS_ERROR;
if (sb.st_ino != helper->nsid)
{
size = mnsh_send_setns (helper, fd, 0);
if (size < 0)
- goto error;
+ return MNSH_FS_ERROR;
if (mnsh_recv_int (helper, &result, &error) != 0)
- goto error;
+ return MNSH_FS_ERROR;
if (result != 0)
{
error = ENOTSUP;
errno = error;
- goto error;
+ return MNSH_FS_ERROR;
}
helper->nsid = sb.st_ino;
}
- do_cleanups (old_chain);
-
return MNSH_FS_HELPER;
-
-error:
- saved_errno = errno;
-
- do_cleanups (old_chain);
-
- errno = saved_errno;
- return MNSH_FS_ERROR;
}
/* See nat/linux-namespaces.h. */