From: "M. Mohan Kumar" <mohan@in.ibm.com>
To: qemu-devel@nongnu.org, aneesh.kumar@linux.vnet.ibm.com
Cc: "M. Mohan Kumar" <mohan@in.ibm.com>
Subject: [Qemu-devel] [PATCH 06/13] hw/9pfs: Open and create files
Date: Tue, 1 Nov 2011 02:23:25 +0530 [thread overview]
Message-ID: <1320094412-19091-7-git-send-email-mohan@in.ibm.com> (raw)
In-Reply-To: <1320094412-19091-1-git-send-email-mohan@in.ibm.com>
From: "M. Mohan Kumar" <mohan@in.ibm.com>
Add interfaces to open and create files for proxy file system driver.
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
Makefile | 2 +
configure | 1 +
hw/9pfs/proxy.h | 6 ++
hw/9pfs/virtfs-proxy-helper.c | 135 ++++++++++++++++++++++++++++++-
hw/9pfs/virtio-9p-marshal.c | 12 +++
hw/9pfs/virtio-9p-proxy.c | 178 +++++++++++++++++++++++++++++++++++++++--
hw/9pfs/virtio-9p.c | 12 ---
7 files changed, 325 insertions(+), 21 deletions(-)
diff --git a/Makefile b/Makefile
index 1fd443d..d13b167 100644
--- a/Makefile
+++ b/Makefile
@@ -153,6 +153,8 @@ qemu-img$(EXESUF): qemu-img.o $(tools-obj-y)
qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y)
qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y)
+hw/9pfs/virtfs-proxy-helper$(EXESUF): QEMU_CFLAGS += -DTARGET_PHYS_ADDR_BITS=$(PROXY_PHYS_ADDR_BITS)
+hw/9pfs/virtfs-proxy-helper$(EXESUF): hw/9pfs/virtfs-proxy-helper.o hw/9pfs/virtio-9p-marshal.o
hw/9pfs/virtfs-proxy-helper$(EXESUF): LIBS+=$(LIBS_PROXY)
qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
diff --git a/configure b/configure
index 8abd17c..ae64f84 100755
--- a/configure
+++ b/configure
@@ -3474,6 +3474,7 @@ if test "$smartcard_nss" = "yes" ; then
echo "libcacard_libs=$libcacard_libs" >> $config_host_mak
echo "libcacard_cflags=$libcacard_cflags" >> $config_host_mak
fi
+echo "PROXY_PHYS_ADDR_BITS=$target_phys_bits" >> $config_host_mak
list=""
if test ! -z "$gdb_xml_files" ; then
for x in $gdb_xml_files; do
diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
index 205d7b7..69e7baa 100644
--- a/hw/9pfs/proxy.h
+++ b/hw/9pfs/proxy.h
@@ -13,4 +13,10 @@ typedef struct {
int type;
int size;
} ProxyHeader;
+
+enum {
+ T_OPEN = 1,
+ T_CREATE,
+};
+
#endif
diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
index 9d925e0..73609e1 100644
--- a/hw/9pfs/virtfs-proxy-helper.c
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -18,6 +18,7 @@
#include "bswap.h"
#include <sys/socket.h>
#include "qemu-common.h"
+#include "virtio-9p.h"
#include "hw/9pfs/proxy.h"
#define PROGNAME "virtfs-proxy-helper"
@@ -202,6 +203,110 @@ static int proxy_socket(const char *path, uid_t uid, gid_t gid)
return client;
}
+static void sendfd(int sockfd, int fd, int fd_valid)
+{
+ struct msghdr msg = { };
+ struct iovec iov;
+ struct cmsghdr *cmsg;
+ int retval, data;
+ union MsgControl msg_control;
+
+ iov.iov_base = &data;
+ iov.iov_len = sizeof(data);
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ /* No ancillary data on error */
+ if (!fd_valid) {
+ /*
+ * fd is really negative errno if the request failed. Or simply
+ * zero if the request is successful and it doesn't need a file
+ * descriptor.
+ */
+ data = fd;
+ } else {
+ data = V9FS_FD_VALID;
+ msg.msg_control = &msg_control;
+ msg.msg_controllen = sizeof(msg_control);
+
+ cmsg = &msg_control.cmsg;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+ }
+
+ do {
+ retval = sendmsg(sockfd, &msg, 0);
+ } while (retval < 0 && errno == EINTR);
+ if (retval < 0) {
+ do_perror("sendmsg");
+ exit(1);
+ }
+ if (fd_valid) {
+ close(fd);
+ }
+}
+
+/*
+ * from man 7 capabilities, section
+ * Effect of User ID Changes on Capabilities:
+ * 4. If the file system user ID is changed from 0 to nonzero (see setfsuid(2))
+ * then the following capabilities are cleared from the effective set:
+ * CAP_CHOWN, CAP_DAC_OVERRIDE, CAP_DAC_READ_SEARCH, CAP_FOWNER, CAP_FSETID,
+ * CAP_LINUX_IMMUTABLE (since Linux 2.2.30), CAP_MAC_OVERRIDE, and CAP_MKNOD
+ * (since Linux 2.2.30). If the file system UID is changed from nonzero to 0,
+ * then any of these capabilities that are enabled in the permitted set
+ * are enabled in the effective set.
+ */
+static int setfsugid(int uid, int gid)
+{
+ setfsgid(gid);
+ setfsuid(uid);
+ return cap_set();
+}
+
+/*
+ * create a file and send fd on success
+ * return -errno on error
+ */
+static int do_create(struct iovec *iovec)
+{
+ V9fsString path;
+ int flags, fd, mode, uid, gid, cur_uid, cur_gid;
+ v9fs_unmarshal(iovec, 1, 0, "sdddd", &path, &flags, &mode, &uid, &gid);
+ cur_uid = geteuid();
+ cur_gid = getegid();
+ if (setfsugid(uid, gid) < 0) {
+ return -EPERM;
+ }
+ fd = open(path.data, flags, mode);
+ if (fd < 0) {
+ fd = -errno;
+ }
+ v9fs_string_free(&path);
+ setfsugid(cur_uid, cur_gid);
+ return fd;
+}
+
+/*
+ * open a file and send fd on success
+ * return -errno on error
+ */
+static int do_open(struct iovec *iovec)
+{
+ V9fsString path;
+ int flags, fd;
+ v9fs_unmarshal(iovec, 1, 0, "sd", &path, &flags);
+ fd = open(path.data, flags);
+ if (fd < 0) {
+ fd = -errno;
+ }
+ v9fs_string_free(&path);
+ return fd;
+}
+
static void usage(char *prog)
{
fprintf(stderr, "usage: %s\n"
@@ -217,15 +322,41 @@ static void usage(char *prog)
static int process_requests(int sock)
{
- int type;
+ int type, retval;
struct iovec iovec;
+ int valid_fd;
iovec.iov_base = g_malloc(BUFF_SZ);
iovec.iov_len = BUFF_SZ;
while (1) {
+ valid_fd = 0;
type = read_request(sock, &iovec);
- if (type <= 0) {
+ switch (type) {
+ case T_OPEN:
+ retval = do_open(&iovec);
+ if (retval >= 0) {
+ valid_fd = 1;
+ }
+ break;
+ case T_CREATE:
+ retval = do_create(&iovec);
+ if (retval >= 0) {
+ valid_fd = 1;
+ }
+ break;
+ default:
goto error;
+ break;
+ }
+
+ /* Send response */
+ switch (type) {
+ case T_OPEN:
+ case T_CREATE:
+ sendfd(sock, retval, valid_fd);
+ break;
+ default:
+ break;
}
}
(void)socket_write;
diff --git a/hw/9pfs/virtio-9p-marshal.c b/hw/9pfs/virtio-9p-marshal.c
index 1a21254..364e4df 100644
--- a/hw/9pfs/virtio-9p-marshal.c
+++ b/hw/9pfs/virtio-9p-marshal.c
@@ -12,6 +12,18 @@
*/
#include "virtio-9p.h"
+void v9fs_string_free(V9fsString *str)
+{
+ g_free(str->data);
+ str->data = NULL;
+ str->size = 0;
+}
+
+void v9fs_string_null(V9fsString *str)
+{
+ v9fs_string_free(str);
+}
+
static size_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count,
size_t offset, size_t size, int pack)
{
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 0ec686c..d686454 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -26,6 +26,145 @@ typedef struct V9fsProxy {
struct iovec iovec;
} V9fsProxy;
+/*
+ * Return received file descriptor on success and -errno on failure.
+ * sock_error is set to 1 whenever there is error in socket IO
+ */
+static int v9fs_receivefd(int sockfd, int *sock_error)
+{
+ struct msghdr msg = { };
+ struct iovec iov;
+ union MsgControl msg_control;
+ struct cmsghdr *cmsg;
+ int retval, data, fd;
+
+ iov.iov_base = &data;
+ iov.iov_len = sizeof(data);
+
+ *sock_error = 0;
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = &msg_control;
+ msg.msg_controllen = sizeof(msg_control);
+
+ do {
+ retval = recvmsg(sockfd, &msg, 0);
+ } while (retval < 0 && errno == EINTR);
+ if (retval <= 0) {
+ *sock_error = 1;
+ return -EIO;
+ }
+
+ /*
+ * data is set to V9FS_FD_VALID, if ancillary data is sent. If this
+ * request doesn't need ancillary data (fd) or an error occurred,
+ * data is set to negative errno value.
+ */
+ if (data != V9FS_FD_VALID) {
+ return data;
+ }
+
+ /*
+ * File descriptor (fd) is sent in the ancillary data. Check if we
+ * indeed received it. One of the reasons to fail to receive it is if
+ * we exceeded the maximum number of file descriptors!
+ */
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)) ||
+ cmsg->cmsg_level != SOL_SOCKET ||
+ cmsg->cmsg_type != SCM_RIGHTS) {
+ continue;
+ }
+ fd = *((int *)CMSG_DATA(cmsg));
+ return fd;
+ }
+
+ return -ENFILE; /* Ancillary data sent but not received */
+}
+
+/*
+ * Proxy->header and proxy->buff written into the socket by QEMU process.
+ * This request read by proxy helper process
+ * @proxy: v9fsproxy
+ * @message: buffer where the response is written
+ * @size: size of request structure
+ * returns 0 on success and -errno on error
+ */
+static int v9fs_request(V9fsProxy *proxy, int type,
+ void *response, const char *fmt, ...)
+{
+ int retval;
+ ProxyHeader header;
+ va_list ap;
+ V9fsString *path;
+ int sock_error, flags, mode, uid, gid;
+ struct iovec *iovec = NULL;
+
+ qemu_mutex_lock(&proxy->mutex);
+
+ if (proxy->sockfd == -1) {
+ goto error;
+ }
+ iovec = &proxy->iovec;
+
+ va_start(ap, fmt);
+ switch (type) {
+ case T_OPEN:
+ path = va_arg(ap, V9fsString *);
+ flags = va_arg(ap, int);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sd", path,
+ flags);
+ header.type = T_OPEN;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ case T_CREATE:
+ path = va_arg(ap, V9fsString *);
+ flags = va_arg(ap, int);
+ mode = va_arg(ap, int);
+ uid = va_arg(ap, int);
+ gid = va_arg(ap, int);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sdddd", path,
+ flags, mode, uid, gid);
+ header.type = T_CREATE;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ default:
+ fprintf(stderr, "Invalid type %d\n", type);
+ goto close_error;
+ }
+ va_end(ap);
+
+ retval = qemu_write_full(proxy->sockfd, iovec->iov_base, header.size);
+ if (retval != header.size) {
+ goto close_error;
+ }
+
+ /*
+ * Response for T_OPEN is a file descriptor
+ * and returns the file descriptor
+ */
+ switch (type) {
+ case T_OPEN:
+ case T_CREATE:
+ retval = v9fs_receivefd(proxy->sockfd, &sock_error);
+ if (sock_error) {
+ goto close_error;
+ }
+ break;
+ }
+ qemu_mutex_unlock(&proxy->mutex);
+ return retval;
+close_error:
+ close(proxy->sockfd);
+ proxy->sockfd = -1;
+error:
+ qemu_mutex_unlock(&proxy->mutex);
+ return -EIO;
+}
+
static int proxy_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
{
errno = EOPNOTSUPP;
@@ -52,16 +191,30 @@ static int proxy_closedir(FsContext *ctx, V9fsFidOpenState *fs)
static int proxy_open(FsContext *ctx, V9fsPath *fs_path,
int flags, V9fsFidOpenState *fs)
{
- fs->fd = -1;
+ fs->fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd",
+ fs_path, flags);
return fs->fd;
}
static int proxy_opendir(FsContext *ctx,
V9fsPath *fs_path, V9fsFidOpenState *fs)
{
- fs->dir = NULL;
- errno = EOPNOTSUPP;
- return -1;
+ int serrno, fd;
+
+ fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd",
+ fs_path, O_DIRECTORY);
+ if (fd < 0) {
+ errno = -fd;
+ return -1;
+ }
+ fs->dir = fdopendir(fd);
+ if (!fs->dir) {
+ serrno = errno;
+ close(fd);
+ errno = serrno;
+ return -1;
+ }
+ return 0;
}
static void proxy_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
@@ -163,9 +316,20 @@ static int proxy_fstat(FsContext *fs_ctx,
static int proxy_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
int flags, FsCred *credp, V9fsFidOpenState *fs)
{
- fs->fd = -1;
- errno = EOPNOTSUPP;
- return -1;
+ V9fsString fullname;
+
+ v9fs_string_init(&fullname);
+ v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+
+ fs->fd = v9fs_request(fs_ctx->private, T_CREATE, NULL, "sdddd",
+ &fullname, flags, credp->fc_mode,
+ credp->fc_uid, credp->fc_gid);
+ v9fs_string_free(&fullname);
+ if (fs->fd < 0) {
+ errno = -fs->fd;
+ fs->fd = -1;
+ }
+ return fs->fd;
}
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 177c0ee..f0cb000 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -149,18 +149,6 @@ void v9fs_string_init(V9fsString *str)
str->size = 0;
}
-void v9fs_string_free(V9fsString *str)
-{
- g_free(str->data);
- str->data = NULL;
- str->size = 0;
-}
-
-void v9fs_string_null(V9fsString *str)
-{
- v9fs_string_free(str);
-}
-
static int number_to_string(void *arg, char type)
{
unsigned int ret = 0;
--
1.7.6
next prev parent reply other threads:[~2011-10-31 20:54 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2011-10-31 20:53 [Qemu-devel] [PATCH 00/13] Proxy FS driver for VirtFS M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 01/13] hw/9pfs: Move opt validation to FsDriver callback M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 02/13] hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 03/13] hw/9pfs: Add new proxy filesystem driver M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 04/13] hw/9pfs: File system helper process for qemu 9p proxy FS M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 05/13] hw/9pfs: Add support to use named socket for " M. Mohan Kumar
2011-10-31 20:53 ` M. Mohan Kumar [this message]
2011-10-31 20:53 ` [Qemu-devel] [PATCH 07/13] hw/9pfs: Create other filesystem objects M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 08/13] hw/9pfs: Add stat/readlink/statfs for proxy FS M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 09/13] hw/9pfs: File ownership and others M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 10/13] hw/9pfs: xattr interfaces in proxy filesystem driver M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 12/13] hw/9pfs: Documentation changes related to proxy fs M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 13/13] hw/9pfs: man page for proxy helper M. Mohan Kumar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1320094412-19091-7-git-send-email-mohan@in.ibm.com \
--to=mohan@in.ibm.com \
--cc=aneesh.kumar@linux.vnet.ibm.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.