24 #include <sys/syscall.h>
27 #include <sys/socket.h>
42 return syscall (__NR_setns, fd, nstype);
52 #ifndef MSG_CMSG_CLOEXEC
53 #define MSG_CMSG_CLOEXEC 0
83 static char filename[PATH_MAX];
86 xsnprintf (filename,
sizeof (filename),
"/proc/%d/ns/%s", pid,
98 static struct linux_ns namespaces[NUM_LINUX_NS_TYPES] =
109 gdb_assert (type >= 0 && type < NUM_LINUX_NS_TYPES);
110 ns = &namespaces[type];
150 if (stat (filename, &sb) != 0)
153 return sb.st_ino == ns->
id;
260 int fd,
int int1,
int int2,
261 const void *buf,
int bufsiz)
307 debug_printf (*c >=
' ' && *c <=
'~' ?
"%c" :
"\\%o", *c);
324 int fd,
int int1,
int int2,
325 const void *buf,
int bufsiz)
329 char fdbuf[CMSG_SPACE (
sizeof (fd))];
333 memset (&msg, 0,
sizeof (msg));
336 iov[0].iov_base = &type;
337 iov[0].iov_len =
sizeof (type);
338 iov[1].iov_base = &int1;
339 iov[1].iov_len =
sizeof (int1);
340 iov[2].iov_base = &int2;
341 iov[2].iov_len =
sizeof (int2);
346 if (buf != NULL && bufsiz > 0)
348 iov[3].iov_base =
alloca (bufsiz);
349 memcpy (iov[3].iov_base, buf, bufsiz);
350 iov[3].iov_len = bufsiz;
358 struct cmsghdr *cmsg;
360 msg.msg_control = fdbuf;
361 msg.msg_controllen =
sizeof (fdbuf);
363 cmsg = CMSG_FIRSTHDR (&msg);
364 cmsg->cmsg_level = SOL_SOCKET;
365 cmsg->cmsg_type = SCM_RIGHTS;
366 cmsg->cmsg_len = CMSG_LEN (
sizeof (
int));
368 memcpy (CMSG_DATA (cmsg), &fd,
sizeof (
int));
370 msg.msg_controllen = cmsg->cmsg_len;
374 size = sendmsg (sock, &msg, 0);
399 int *fd,
int *int1,
int *int2,
400 void *buf,
int bufsiz)
404 char fdbuf[CMSG_SPACE (
sizeof (*fd))];
405 struct cmsghdr *cmsg;
406 ssize_t size, fixed_size;
410 memset (&msg, 0,
sizeof (msg));
413 iov[0].iov_base = type;
414 iov[0].iov_len =
sizeof (*type);
415 iov[1].iov_base = int1;
416 iov[1].iov_len =
sizeof (*int1);
417 iov[2].iov_base = int2;
418 iov[2].iov_len =
sizeof (*int2);
419 iov[3].iov_base = buf;
420 iov[3].iov_len = bufsiz;
424 for (fixed_size = i = 0; i < msg.msg_iovlen - 1; i++)
425 fixed_size += iov[i].iov_len;
427 msg.msg_control = fdbuf;
428 msg.msg_controllen =
sizeof (fdbuf);
444 if (size < fixed_size || (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)))
447 debug_printf (
"namespace-helper: recv truncated (%s 0x%x)\n",
457 cmsg = CMSG_FIRSTHDR (&msg);
459 && cmsg->cmsg_len == CMSG_LEN (
sizeof (
int))
460 && cmsg->cmsg_level == SOL_SOCKET
461 && cmsg->cmsg_type == SCM_RIGHTS)
462 memcpy (fd, CMSG_DATA (cmsg),
sizeof (
int));
475 return size - fixed_size;
480 #define mnsh_return_int(sock, result, error) \
481 mnsh_send_message (sock, MNSH_RET_INT, -1, result, error, NULL, 0)
483 #define mnsh_return_fd(sock, fd, error) \
484 mnsh_send_message (sock, MNSH_RET_FD, \
485 (fd) < 0 ? -1 : (fd), \
486 (fd) < 0 ? (fd) : 0, \
489 #define mnsh_return_intstr(sock, result, buf, bufsiz, error) \
490 mnsh_send_message (sock, MNSH_RET_INTSTR, -1, result, error, \
498 int result =
setns (fd, nstype);
507 int flags, mode_t mode)
523 int result = unlink (filename);
534 int len = readlink (filename, buf,
sizeof (buf));
537 buf, len < 0 ? 0 : len,
543 static void mnsh_main (
int sock) ATTRIBUTE_NORETURN;
553 ssize_t size, response = -1;
559 if (size >= 0 && size <
sizeof (buf))
569 if (size > 0 && buf[size - 1] ==
'\0')
574 if (size > 0 && buf[size - 1] ==
'\0')
579 if (size > 0 && buf[size - 1] ==
'\0')
599 -1, int1, int2, buf, size);
637 pid_t helper_creator = getpid ();
650 int saved_errno =
errno;
676 helper->
sock = sv[0];
680 debug_printf (
"Started mount namespace helper process %d\n",
717 pid = waitpid (helper->
pid, &status,
WNOHANG);
726 warning (
_(
"mount namespace helper vanished?"));
729 _(
"unhandled error %d"),
errno);
731 else if (pid == helper->
pid)
734 warning (
_(
"mount namespace helper exited with status %d"),
737 warning (
_(
"mount namespace helper killed by signal %d"),
741 _(
"unhandled status %d"), status);
745 _(
"unknown pid %d"), pid);
754 #define mnsh_send_setns(helper, fd, nstype) \
755 mnsh_send_message (helper->sock, MNSH_REQ_SETNS, fd, nstype, 0, \
758 #define mnsh_send_open(helper, filename, flags, mode) \
759 mnsh_send_message (helper->sock, MNSH_REQ_OPEN, -1, flags, mode, \
760 filename, strlen (filename) + 1)
762 #define mnsh_send_unlink(helper, filename) \
763 mnsh_send_message (helper->sock, MNSH_REQ_UNLINK, -1, 0, 0, \
764 filename, strlen (filename) + 1)
766 #define mnsh_send_readlink(helper, filename) \
767 mnsh_send_message (helper->sock, MNSH_REQ_READLINK, -1, 0, 0, \
768 filename, strlen (filename) + 1)
835 int *result,
int *
error,
836 void *buf,
int bufsiz)
884 if (pid == getpid ())
899 if (fstat (fd, &sb) != 0)
902 if (sb.st_ino == ns->
id)
913 if (sb.st_ino != helper->
nsid)
938 helper->
nsid = sb.st_ino;
958 int flags, mode_t mode)
1002 return unlink (filename);
1025 char *buf,
size_t bufsiz)
1036 return readlink (filename, buf, bufsiz);
static ssize_t mnsh_handle_unlink(int sock, const char *filename)
int gdb_socketpair_cloexec(int domain, int style, int protocol, int filedes[2])
#define mnsh_send_setns(helper, fd, nstype)
static struct linux_mnsh * linux_mntns_get_helper(void)
#define mnsh_send_open(helper, filename, flags, mode)
static ssize_t mnsh_handle_readlink(int sock, const char *filename)
void warning(const char *fmt,...)
static int mnsh_recv_fd(struct linux_mnsh *helper, int *fd, int *error)
static int mnsh_creator_pid
static ssize_t mnsh_recv_message(int sock, enum mnsh_msg_type *type, int *fd, int *int1, int *int2, void *buf, int bufsiz)
#define mnsh_send_readlink(helper, filename)
#define mnsh_send_unlink(helper, filename)
int debug_linux_namespaces
void null_cleanup(void *arg)
static ssize_t mnsh_handle_open(int sock, const char *filename, int flags, mode_t mode)
static enum mnsh_fs_code linux_mntns_access_fs(pid_t pid)
int linux_ns_same(pid_t pid, enum linux_ns_type type)
static struct linux_ns * linux_ns_get_namespace(enum linux_ns_type type)
static int mnsh_recv_int(struct linux_mnsh *helper, int *result, int *error)
static void mnsh_main(int sock) ATTRIBUTE_NORETURN
struct cleanup * make_cleanup(make_cleanup_ftype *function, void *arg)
char * pulongest(ULONGEST u)
struct cleanup * make_cleanup_close(int fd)
static const char * linux_ns_filename(struct linux_ns *ns, int pid)
static void mnsh_maybe_mourn_peer(void)
static void mnsh_debug_print_message(enum mnsh_msg_type type, int fd, int int1, int int2, const void *buf, int bufsiz)
int linux_mntns_unlink(pid_t pid, const char *filename)
#define mnsh_return_fd(sock, fd, error)
static ssize_t mnsh_send_message(int sock, enum mnsh_msg_type type, int fd, int int1, int int2, const void *buf, int bufsiz)
int xsnprintf(char *str, size_t size, const char *format,...)
static int setns(int fd, int nstype)
void perror_with_name(const char *string)
int gdb_open_cloexec(const char *filename, int flags, unsigned long mode)
#define mnsh_return_int(sock, result, error)
int linux_mntns_open_cloexec(pid_t pid, const char *filename, int flags, mode_t mode)
#define mnsh_return_intstr(sock, result, buf, bufsiz, error)
ssize_t linux_mntns_readlink(pid_t pid, const char *filename, char *buf, size_t bufsiz)
static ssize_t mnsh_recv_intstr(struct linux_mnsh *helper, int *result, int *error, void *buf, int bufsiz)
void debug_printf(const char *fmt,...)
void internal_warning(const char *file, int line, const char *fmt,...)
static ssize_t mnsh_handle_setns(int sock, int fd, int nstype)
void error(const char *fmt,...)
void do_cleanups(struct cleanup *old_chain)