24 #include <sys/syscall.h> 27 #include <sys/socket.h> 54 return setns (fd, nstype);
55 #elif defined __NR_setns 56 return syscall (__NR_setns, fd, nstype);
65 #ifndef MSG_CMSG_CLOEXEC 66 #define MSG_CMSG_CLOEXEC 0 96 static char filename[PATH_MAX];
99 xsnprintf (filename,
sizeof (filename),
"/proc/%d/ns/%s", pid,
123 ns = &namespaces[type];
163 if (stat (filename, &sb) != 0)
166 return sb.st_ino == ns->
id;
273 int fd,
int int1,
int int2,
274 const void *buf,
int bufsiz)
320 debug_printf (*c >=
' ' && *c <=
'~' ?
"%c" :
"\\%o", *c);
337 int fd,
int int1,
int int2,
338 const void *buf,
int bufsiz)
342 char fdbuf[CMSG_SPACE (
sizeof (fd))];
346 memset (&msg, 0,
sizeof (msg));
349 iov[0].iov_base = &type;
350 iov[0].iov_len =
sizeof (type);
351 iov[1].iov_base = &int1;
352 iov[1].iov_len =
sizeof (int1);
353 iov[2].iov_base = &int2;
354 iov[2].iov_len =
sizeof (int2);
359 if (buf != NULL && bufsiz > 0)
361 iov[3].iov_base =
alloca (bufsiz);
362 memcpy (iov[3].iov_base, buf, bufsiz);
363 iov[3].iov_len = bufsiz;
371 struct cmsghdr *cmsg;
373 msg.msg_control = fdbuf;
374 msg.msg_controllen =
sizeof (fdbuf);
376 cmsg = CMSG_FIRSTHDR (&msg);
377 cmsg->cmsg_level = SOL_SOCKET;
378 cmsg->cmsg_type = SCM_RIGHTS;
379 cmsg->cmsg_len = CMSG_LEN (
sizeof (
int));
381 memcpy (CMSG_DATA (cmsg), &fd,
sizeof (
int));
383 msg.msg_controllen = cmsg->cmsg_len;
387 size = sendmsg (sock, &msg, 0);
412 int *fd,
int *int1,
int *int2,
413 void *buf,
int bufsiz)
417 char fdbuf[CMSG_SPACE (
sizeof (*fd))];
418 struct cmsghdr *cmsg;
419 ssize_t size, fixed_size;
423 memset (&msg, 0,
sizeof (msg));
426 iov[0].iov_base = type;
427 iov[0].iov_len =
sizeof (*type);
428 iov[1].iov_base = int1;
429 iov[1].iov_len =
sizeof (*int1);
430 iov[2].iov_base = int2;
431 iov[2].iov_len =
sizeof (*int2);
432 iov[3].iov_base = buf;
433 iov[3].iov_len = bufsiz;
437 for (fixed_size = i = 0; i < msg.msg_iovlen - 1; i++)
438 fixed_size += iov[i].iov_len;
440 msg.msg_control = fdbuf;
441 msg.msg_controllen =
sizeof (fdbuf);
457 if (size < fixed_size || (msg.msg_flags & (MSG_TRUNC | MSG_CTRUNC)))
460 debug_printf (
"namespace-helper: recv truncated (%s 0x%x)\n",
470 cmsg = CMSG_FIRSTHDR (&msg);
472 && cmsg->cmsg_len == CMSG_LEN (
sizeof (
int))
473 && cmsg->cmsg_level == SOL_SOCKET
474 && cmsg->cmsg_type == SCM_RIGHTS)
475 memcpy (fd, CMSG_DATA (cmsg),
sizeof (
int));
488 return size - fixed_size;
493 #define mnsh_return_int(sock, result, error) \ 494 mnsh_send_message (sock, MNSH_RET_INT, -1, result, error, NULL, 0) 496 #define mnsh_return_fd(sock, fd, error) \ 497 mnsh_send_message (sock, MNSH_RET_FD, \ 498 (fd) < 0 ? -1 : (fd), \ 499 (fd) < 0 ? (fd) : 0, \ 502 #define mnsh_return_intstr(sock, result, buf, bufsiz, error) \ 503 mnsh_send_message (sock, MNSH_RET_INTSTR, -1, result, error, \ 520 int flags, mode_t mode)
536 int result = unlink (filename);
547 int len = readlink (filename, buf,
sizeof (buf));
550 buf, len < 0 ? 0 : len,
556 static void mnsh_main (
int sock) ATTRIBUTE_NORETURN;
566 ssize_t size, response = -1;
572 if (size >= 0 && size <
sizeof (buf))
582 if (size > 0 && buf[size - 1] ==
'\0')
587 if (size > 0 && buf[size - 1] ==
'\0')
592 if (size > 0 && buf[size - 1] ==
'\0')
612 -1, int1, int2, buf, size);
650 pid_t helper_creator = getpid ();
663 int saved_errno =
errno;
689 helper->
sock = sv[0];
693 debug_printf (
"Started mount namespace helper process %d\n",
739 warning (
_(
"mount namespace helper vanished?"));
742 _(
"unhandled error %d"),
errno);
744 else if (
pid == helper->
pid)
747 warning (
_(
"mount namespace helper exited with status %d"),
750 warning (
_(
"mount namespace helper killed by signal %d"),
754 _(
"unhandled status %d"), status);
758 _(
"unknown pid %d"),
pid);
767 #define mnsh_send_setns(helper, fd, nstype) \ 768 mnsh_send_message (helper->sock, MNSH_REQ_SETNS, fd, nstype, 0, \ 771 #define mnsh_send_open(helper, filename, flags, mode) \ 772 mnsh_send_message (helper->sock, MNSH_REQ_OPEN, -1, flags, mode, \ 773 filename, strlen (filename) + 1) 775 #define mnsh_send_unlink(helper, filename) \ 776 mnsh_send_message (helper->sock, MNSH_REQ_UNLINK, -1, 0, 0, \ 777 filename, strlen (filename) + 1) 779 #define mnsh_send_readlink(helper, filename) \ 780 mnsh_send_message (helper->sock, MNSH_REQ_READLINK, -1, 0, 0, \ 781 filename, strlen (filename) + 1) 848 int *result,
int *
error,
849 void *buf,
int bufsiz)
897 if (
pid == getpid ())
912 if (fstat (fd, &sb) != 0)
915 if (sb.st_ino == ns->
id)
926 if (sb.st_ino != helper->
nsid)
951 helper->
nsid = sb.st_ino;
971 int flags, mode_t mode)
1015 return unlink (filename);
1038 char *buf,
size_t bufsiz)
1049 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,...)
void * memset(T *s, int c, size_t n)=delete
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 pid_t do_fork(void)
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 do_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)