On Tue, Jan 18, 2011 at 6:25 AM, M. Mohan Kumar <mo...@in.ibm.com> wrote: > Implement chroot server side interfaces like sending the file > descriptor to qemu process, reading the object request from socket etc. > Also add chroot main function and other helper routines. > > Signed-off-by: M. Mohan Kumar <mo...@in.ibm.com> > --- > Makefile.objs | 1 + > hw/9pfs/virtio-9p-chroot.c | 183 > ++++++++++++++++++++++++++++++++++++++++++++ > hw/9pfs/virtio-9p-chroot.h | 39 +++++++++ > hw/9pfs/virtio-9p.c | 23 ++++++ > hw/file-op-9p.h | 2 + > 5 files changed, 248 insertions(+), 0 deletions(-) > create mode 100644 hw/9pfs/virtio-9p-chroot.c > create mode 100644 hw/9pfs/virtio-9p-chroot.h > > diff --git a/Makefile.objs b/Makefile.objs > index bc0344c..3007b6d 100644 > --- a/Makefile.objs > +++ b/Makefile.objs > @@ -273,6 +273,7 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y) > 9pfs-nested-$(CONFIG_VIRTFS) = virtio-9p-debug.o > 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-local.o virtio-9p-xattr.o > 9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o > virtio-9p-posix-acl.o > +9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-chroot.o > > hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y)) > $(addprefix 9pfs/, $(9pfs-nested-y)): CFLAGS += -I$(SRC_PATH)/hw/ > diff --git a/hw/9pfs/virtio-9p-chroot.c b/hw/9pfs/virtio-9p-chroot.c > new file mode 100644 > index 0000000..dcde2cc > --- /dev/null > +++ b/hw/9pfs/virtio-9p-chroot.c > @@ -0,0 +1,183 @@ > +/* > + * Virtio 9p chroot environment for contained access to exported path > + * > + * Copyright IBM, Corp. 2011 > + * > + * Authors: > + * M. Mohan Kumar <mo...@in.ibm.com> > + * > + * This work is licensed under the terms of the GNU GPL, version 2. See > + * the copying file in the top-level directory > + * > + */ > + > +#include <sys/fsuid.h> > +#include <sys/resource.h> > +#include <signal.h> > +#include "virtio.h" > +#include "qemu_socket.h" > +#include "qemu-thread.h" > +#include "qerror.h" > +#include "virtio-9p.h" > +#include "virtio-9p-chroot.h" > + > +/* > + * Structure used by chroot functions to transmit file descriptor and > + * error info > + */ > +typedef struct { > + int fi_fd; > + int fi_error; > +} FdInfo; > + > +union MsgControl { > + struct cmsghdr cmsg; > + char control[CMSG_SPACE(sizeof(int))]; > +}; > + > +/* Send file descriptor and error status to qemu process */ > +static int chroot_sendfd(int sockfd, FdInfo *fd_info)
const FdInfo *? > +{ > + struct msghdr msg = { }; > + struct iovec iov; > + struct cmsghdr *cmsg; > + int retval; > + union MsgControl msg_control; > + > + iov.iov_base = fd_info; > + iov.iov_len = sizeof(*fd_info); > + > + memset(&msg, 0, sizeof(msg)); > + msg.msg_iov = &iov; > + msg.msg_iovlen = 1; > + /* No ancillary data on error */ > + if (!fd_info->fi_error) { > + msg.msg_control = &msg_control; > + msg.msg_controllen = sizeof(msg_control); > + > + cmsg = &msg_control.cmsg; > + cmsg->cmsg_len = CMSG_LEN(sizeof(fd_info->fi_fd)); > + cmsg->cmsg_level = SOL_SOCKET; > + cmsg->cmsg_type = SCM_RIGHTS; > + memcpy(CMSG_DATA(cmsg), &fd_info->fi_fd, sizeof(fd_info->fi_fd)); > + } > + retval = sendmsg(sockfd, &msg, 0); > + close(fd_info->fi_fd); > + return retval; > +} > + > +/* Read V9fsFileObjectRequest written by QEMU process */ > +static void chroot_read_request(int sockfd, V9fsFileObjectRequest *request) > +{ > + int retval; > + retval = qemu_read_full(sockfd, request, sizeof(request->data)); > + if (retval <= 0 || request->data.path_len <= 0) { > + _exit(-1); > + } > + request->path.path = qemu_mallocz(request->data.path_len + 1); > + retval = qemu_read_full(sockfd, (void *)request->path.path, > + request->data.path_len); > + if (retval <= 0) { > + _exit(-1); > + } > + if (request->data.oldpath_len > 0) { > + request->path.old_path = > + qemu_mallocz(request->data.oldpath_len + 1); > + retval = qemu_read_full(sockfd, (void *)request->path.old_path, > + request->data.oldpath_len); > + if (retval <= 0) { > + _exit(-1); > + } > + } > +} > + > +static int chroot_daemonize(int chroot_sock) > +{ > + sigset_t sigset; > + struct rlimit nr_fd; > + int fd; > + > + /* Block all signals for this process */ > + sigprocmask(SIG_SETMASK, &sigset, NULL); > + > + /* Daemonize */ > + if (setsid() < 0) { > + error_report("setsid %s", strerror(errno)); > + return -1; > + } > + > + /* Close other file descriptors */ > + getrlimit(RLIMIT_NOFILE, &nr_fd); > + for (fd = 0; fd < nr_fd.rlim_cur; fd++) { > + if (fd != chroot_sock) { > + close(fd); > + } > + } > + > + /* Create files with mode as requested by client */ > + umask(0); > + return 0; > +} > + > +static void chroot_dummy(void) > +{ > + (void)chroot_sendfd; > +} > + > +/* > + * Fork a process and chroot into the share path. Communication > + * between qemu process and chroot process happens via socket > + */ > +int v9fs_chroot(FsContext *fs_ctx) > +{ > + int fd_pair[2], pid, chroot_sock, error; The type of pid should be pid_t. > + V9fsFileObjectRequest request; > + > + if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd_pair) < 0) { > + error_report("socketpair %s", strerror(errno)); > + return -1; > + } > + > + pid = fork(); > + if (pid < 0) { > + error_report("fork %s", strerror(errno)); > + return -1; > + } > + if (pid != 0) { > + fs_ctx->chroot_socket = fd_pair[0]; > + close(fd_pair[1]); > + return 0; > + } > + > + close(fd_pair[0]); > + chroot_sock = fd_pair[1]; > + if (chroot(fs_ctx->fs_root) < 0) { > + error_report("chroot %s", strerror(errno)); > + return -1; > + } > + > + chroot_dummy(); > + if (chroot_daemonize(chroot_sock) < 0) { > + _exit(-1); > + } > + > + /* > + * Write 0 to chroot socket to indicate chroot process creation is > + * successful > + */ > + error = 0; > + if (qemu_write_full(chroot_sock, &error, sizeof(error)) != > sizeof(error)) { > + _exit(-1); > + } > + /* get the request from the socket */ > + while (1) { > + chroot_read_request(chroot_sock, &request); > + qemu_free(request.path.path); > + if (request.data.oldpath_len) { > + qemu_free(request.path.old_path); > + } > + if (error) { > + _exit(error); > + } > + } > +} > diff --git a/hw/9pfs/virtio-9p-chroot.h b/hw/9pfs/virtio-9p-chroot.h > new file mode 100644 > index 0000000..3bee5e3 > --- /dev/null > +++ b/hw/9pfs/virtio-9p-chroot.h > @@ -0,0 +1,39 @@ > +#ifndef _QEMU_VIRTIO_9P_CHROOT_H > +#define _QEMU_VIRTIO_9P_CHROOT_H > + > +/* types for V9fsFileObjectRequest */ > +#define T_OPEN 1 > +#define T_CREATE 2 > +#define T_MKDIR 3 > +#define T_MKNOD 4 > +#define T_SYMLINK 5 > +#define T_LINK 6 > + > +struct V9fsFileObjectData > +{ > + int flags; > + int mode; > + uid_t uid; > + gid_t gid; > + dev_t dev; > + int path_len; > + int oldpath_len; > + int type; > +}; > + > +struct V9fsFileObjectPath > +{ > + char *path; > + char *old_path; Can these be const char *?