* [Qemu-devel] [PATCH 00/13] Proxy FS driver for VirtFS
@ 2011-10-31 20:53 M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 01/13] hw/9pfs: Move opt validation to FsDriver callback M. Mohan Kumar
` (11 more replies)
0 siblings, 12 replies; 13+ messages in thread
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
From: "M. Mohan Kumar" <mohan@in.ibm.com>
Pass-through security model in QEMU 9p server needs root privilege to do
few file operations (like chown, chmod to any mode/uid:gid). There are two
issues in pass-through security model
1) TOCTTOU vulnerability: Following symbolic links in the server could
provide access to files beyond 9p export path.
2) Running QEMU with root privilege could be a security issue.
To overcome above issues, following approach is used: A new filesytem
type 'proxy' is introduced. Proxy FS uses chroot + socket combination
for securing the vulnerability known with following symbolic links.
Intention of adding a new filesystem type is to allow qemu to run
in non-root mode, but doing privileged operations using socket IO.
Proxy helper(a stand alone binary part of qemu) is invoked with
root privileges. Proxy helper chroots into 9p export path and creates
a socket pair or a named socket based on the command line parameter.
Qemu and proxy helper communicate using this socket. QEMU proxy fs
driver sends filesystem request to proxy helper and receives the
response from it.
Proxy helper is designed so that it can drop the root privilege but
retaining capbilities that are needed for doing filesystem operations
(like CAP_DAC_OVERRIDE, CAP_FOWNER etc)
Aneesh Kumar K.V (1):
hw/9pfs: Move opt validation to FsDriver callback
M. Mohan Kumar (12):
hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file
hw/9pfs: Add new proxy filesystem driver
hw/9pfs: File system helper process for qemu 9p proxy FS
hw/9pfs: Add support to use named socket for proxy FS
hw/9pfs: Open and create files
hw/9pfs: Create other filesystem objects
hw/9pfs: Add stat/readlink/statfs for proxy FS
hw/9pfs: File ownership and others
hw/9pfs: xattr interfaces in proxy filesystem driver
hw/9pfs: Proxy getversion
hw/9pfs: Documentation changes related to proxy fs
hw/9pfs: man page for proxy helper
Makefile | 16 +-
Makefile.objs | 3 +-
configure | 26 +
fsdev/file-op-9p.h | 15 +-
fsdev/qemu-fsdev.c | 45 +--
fsdev/qemu-fsdev.h | 11 +-
hw/9pfs/proxy.h | 40 ++
hw/9pfs/virtfs-proxy-helper.c | 792 +++++++++++++++++++++++++++++++
hw/9pfs/virtfs-proxy-helper.texi | 63 +++
hw/9pfs/virtio-9p-device.c | 13 +-
hw/9pfs/virtio-9p-handle.c | 20 +
hw/9pfs/virtio-9p-local.c | 34 ++
hw/9pfs/virtio-9p-marshal.c | 269 +++++++++++
hw/9pfs/virtio-9p-proxy.c | 974 ++++++++++++++++++++++++++++++++++++++
hw/9pfs/virtio-9p.c | 270 +-----------
hw/9pfs/virtio-9p.h | 12 +
qemu-config.c | 13 +
qemu-options.hx | 30 +-
vl.c | 18 +-
19 files changed, 2326 insertions(+), 338 deletions(-)
create mode 100644 hw/9pfs/proxy.h
create mode 100644 hw/9pfs/virtfs-proxy-helper.c
create mode 100644 hw/9pfs/virtfs-proxy-helper.texi
create mode 100644 hw/9pfs/virtio-9p-marshal.c
create mode 100644 hw/9pfs/virtio-9p-proxy.c
--
1.7.6
^ permalink raw reply [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 01/13] hw/9pfs: Move opt validation to FsDriver callback
2011-10-31 20:53 [Qemu-devel] [PATCH 00/13] Proxy FS driver for VirtFS M. Mohan Kumar
@ 2011-10-31 20:53 ` 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
` (10 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
To: qemu-devel, aneesh.kumar
From: "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
This remove all conditional code from common code path and
make opt validation a FSDriver callback.
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
fsdev/file-op-9p.h | 15 +++++++++++++--
fsdev/qemu-fsdev.c | 44 ++++++--------------------------------------
fsdev/qemu-fsdev.h | 10 ----------
hw/9pfs/virtio-9p-device.c | 13 ++++++++-----
hw/9pfs/virtio-9p-handle.c | 20 ++++++++++++++++++++
hw/9pfs/virtio-9p-local.c | 34 ++++++++++++++++++++++++++++++++++
vl.c | 8 ++------
7 files changed, 83 insertions(+), 61 deletions(-)
diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 1928da2..22849c9 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -61,6 +61,16 @@ typedef struct extended_ops {
#define V9FS_SEC_MASK 0x0000001C
+typedef struct FileOperations FileOperations;
+/*
+ * Structure to store the various fsdev's passed through command line.
+ */
+typedef struct FsDriverEntry {
+ char *fsdev_id;
+ char *path;
+ int export_flags;
+ FileOperations *ops;
+} FsDriverEntry;
typedef struct FsContext
{
@@ -82,8 +92,9 @@ typedef union V9fsFidOpenState V9fsFidOpenState;
void cred_init(FsCred *);
-typedef struct FileOperations
+struct FileOperations
{
+ int (*parse_opts)(QemuOpts *, struct FsDriverEntry *);
int (*init)(struct FsContext *);
int (*lstat)(FsContext *, V9fsPath *, struct stat *);
ssize_t (*readlink)(FsContext *, V9fsPath *, char *, size_t);
@@ -128,6 +139,6 @@ typedef struct FileOperations
V9fsPath *newdir, const char *new_name);
int (*unlinkat)(FsContext *ctx, V9fsPath *dir, const char *name, int flags);
void *opaque;
-} FileOperations;
+};
#endif
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index 7fd2aa7..efbfea1 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -29,12 +29,10 @@ static FsDriverTable FsDrivers[] = {
int qemu_fsdev_add(QemuOpts *opts)
{
- struct FsDriverListEntry *fsle;
int i;
+ struct FsDriverListEntry *fsle;
const char *fsdev_id = qemu_opts_id(opts);
const char *fsdriver = qemu_opt_get(opts, "fsdriver");
- const char *path = qemu_opt_get(opts, "path");
- const char *sec_model = qemu_opt_get(opts, "security_model");
const char *writeout = qemu_opt_get(opts, "writeout");
bool ro = qemu_opt_get_bool(opts, "readonly", 0);
@@ -59,29 +57,9 @@ int qemu_fsdev_add(QemuOpts *opts)
return -1;
}
- if (!strcmp(fsdriver, "local") && !sec_model) {
- fprintf(stderr, "security model not specified, "
- "local fs needs security model\nvalid options are:"
- "\tsecurity_model=[passthrough|mapped|none]\n");
- return -1;
- }
-
- if (strcmp(fsdriver, "local") && sec_model) {
- fprintf(stderr, "only local fs driver needs security model\n");
- return -1;
- }
-
- if (!path) {
- fprintf(stderr, "fsdev: No path specified.\n");
- return -1;
- }
-
- fsle = g_malloc(sizeof(*fsle));
-
+ fsle = g_malloc0(sizeof(*fsle));
fsle->fse.fsdev_id = g_strdup(fsdev_id);
- fsle->fse.path = g_strdup(path);
fsle->fse.ops = FsDrivers[i].ops;
- fsle->fse.export_flags = 0;
if (writeout) {
if (!strcmp(writeout, "immediate")) {
fsle->fse.export_flags |= V9FS_IMMEDIATE_WRITEOUT;
@@ -93,22 +71,12 @@ int qemu_fsdev_add(QemuOpts *opts)
fsle->fse.export_flags &= ~V9FS_RDONLY;
}
- if (strcmp(fsdriver, "local")) {
- goto done;
+ if (fsle->fse.ops->parse_opts) {
+ if (fsle->fse.ops->parse_opts(opts, &fsle->fse)) {
+ return -1;
+ }
}
- if (!strcmp(sec_model, "passthrough")) {
- fsle->fse.export_flags |= V9FS_SM_PASSTHROUGH;
- } else if (!strcmp(sec_model, "mapped")) {
- fsle->fse.export_flags |= V9FS_SM_MAPPED;
- } else if (!strcmp(sec_model, "none")) {
- fsle->fse.export_flags |= V9FS_SM_NONE;
- } else {
- fprintf(stderr, "Invalid security model %s specified, valid options are"
- "\n\t [passthrough|mapped|none]\n", sec_model);
- return -1;
- }
-done:
QTAILQ_INSERT_TAIL(&fsdriver_entries, fsle, next);
return 0;
}
diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h
index 8ef8473..921452d 100644
--- a/fsdev/qemu-fsdev.h
+++ b/fsdev/qemu-fsdev.h
@@ -34,16 +34,6 @@ typedef struct FsDriverTable {
FileOperations *ops;
} FsDriverTable;
-/*
- * Structure to store the various fsdev's passed through command line.
- */
-typedef struct FsDriverEntry {
- char *fsdev_id;
- char *path;
- int export_flags;
- FileOperations *ops;
-} FsDriverEntry;
-
typedef struct FsDriverListEntry {
FsDriverEntry fse;
QTAILQ_ENTRY(FsDriverListEntry) next;
diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index bba4c54..d5cfae0 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -75,16 +75,19 @@ VirtIODevice *virtio_9p_init(DeviceState *dev, V9fsConf *conf)
exit(1);
}
- if (!fse->path || !conf->tag) {
- /* we haven't specified a mount_tag or the path */
- fprintf(stderr, "fsdev with id %s needs path "
- "and Virtio-9p device needs mount_tag arguments\n",
+ if (!conf->tag) {
+ /* we haven't specified a mount_tag */
+ fprintf(stderr, "fsdev with id %s needs mount_tag arguments\n",
conf->fsdev_id);
exit(1);
}
s->ctx.export_flags = fse->export_flags;
- s->ctx.fs_root = g_strdup(fse->path);
+ if (fse->path) {
+ s->ctx.fs_root = g_strdup(fse->path);
+ } else {
+ s->ctx.fs_root = NULL;
+ }
s->ctx.exops.get_st_gen = NULL;
if (fse->export_flags & V9FS_SM_PASSTHROUGH) {
diff --git a/hw/9pfs/virtio-9p-handle.c b/hw/9pfs/virtio-9p-handle.c
index c38e0e7..456ebc1 100644
--- a/hw/9pfs/virtio-9p-handle.c
+++ b/hw/9pfs/virtio-9p-handle.c
@@ -647,7 +647,27 @@ out:
return ret;
}
+static int handle_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
+{
+ const char *sec_model = qemu_opt_get(opts, "security_model");
+ const char *path = qemu_opt_get(opts, "path");
+
+ if (sec_model) {
+ fprintf(stderr, "Invalid argument security_model specified with handle fsdriver\n");
+ return -1;
+ }
+
+ if (!path) {
+ fprintf(stderr, "fsdev: No path specified.\n");
+ return -1;
+ }
+ fse->path = g_strdup(path);
+ return 0;
+
+}
+
FileOperations handle_ops = {
+ .parse_opts = handle_parse_opts,
.init = handle_init,
.lstat = handle_lstat,
.readlink = handle_readlink,
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 782dc0a..41bcdf7 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -732,7 +732,41 @@ static int local_init(FsContext *ctx)
return err;
}
+static int local_parse_opts(QemuOpts *opts, struct FsDriverEntry *fse)
+{
+ const char *sec_model = qemu_opt_get(opts, "security_model");
+ const char *path = qemu_opt_get(opts, "path");
+
+ if (!sec_model) {
+ fprintf(stderr, "security model not specified, "
+ "local fs needs security model\nvalid options are:"
+ "\tsecurity_model=[passthrough|mapped|none]\n");
+ return -1;
+ }
+
+ if (!strcmp(sec_model, "passthrough")) {
+ fse->export_flags |= V9FS_SM_PASSTHROUGH;
+ } else if (!strcmp(sec_model, "mapped")) {
+ fse->export_flags |= V9FS_SM_MAPPED;
+ } else if (!strcmp(sec_model, "none")) {
+ fse->export_flags |= V9FS_SM_NONE;
+ } else {
+ fprintf(stderr, "Invalid security model %s specified, valid options are"
+ "\n\t [passthrough|mapped|none]\n", sec_model);
+ return -1;
+ }
+
+ if (!path) {
+ fprintf(stderr, "fsdev: No path specified.\n");
+ return -1;
+ }
+ fse->path = g_strdup(path);
+
+ return 0;
+}
+
FileOperations local_ops = {
+ .parse_opts = local_parse_opts,
.init = local_init,
.lstat = local_lstat,
.readlink = local_readlink,
diff --git a/vl.c b/vl.c
index 37a79e5..cf538b2 100644
--- a/vl.c
+++ b/vl.c
@@ -2677,11 +2677,8 @@ int main(int argc, char **argv, char **envp)
}
if (qemu_opt_get(opts, "fsdriver") == NULL ||
- qemu_opt_get(opts, "mount_tag") == NULL ||
- qemu_opt_get(opts, "path") == NULL) {
- fprintf(stderr, "Usage: -virtfs fsdriver,path=/share_path/,"
- "[security_model={mapped|passthrough|none}],"
- "mount_tag=tag.\n");
+ qemu_opt_get(opts, "mount_tag") == NULL) {
+ fprintf(stderr, "Usage: -virtfs fsdriver,mount_tag=tag.\n");
exit(1);
}
fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
@@ -2727,7 +2724,6 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
qemu_opt_set(fsdev, "fsdriver", "synth");
- qemu_opt_set(fsdev, "path", "/"); /* ignored */
device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
qemu_opt_set(device, "driver", "virtio-9p-pci");
--
1.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 02/13] hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file
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 ` M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 03/13] hw/9pfs: Add new proxy filesystem driver M. Mohan Kumar
` (9 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
From: "M. Mohan Kumar" <mohan@in.ibm.com>
Move p9 marshaling/unmarshaling code to a separate file so that
proxy filesytem driver can use these calls. Also made marshaling
code generic to accept "struct iovec" instead of V9fsPDU.
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
Makefile.objs | 2 +-
hw/9pfs/virtio-9p-marshal.c | 257 ++++++++++++++++++++++++++++++++++++++++++
hw/9pfs/virtio-9p.c | 258 +------------------------------------------
hw/9pfs/virtio-9p.h | 12 ++
4 files changed, 274 insertions(+), 255 deletions(-)
create mode 100644 hw/9pfs/virtio-9p-marshal.c
diff --git a/Makefile.objs b/Makefile.objs
index 3dead4e..804bc3c 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -310,7 +310,7 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-xattr-user.o virtio-9p-posix-acl.o
9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o codir.o cofile.o
9pfs-nested-$(CONFIG_VIRTFS) += coxattr.o virtio-9p-handle.o
-9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-synth.o
+9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-synth.o virtio-9p-marshal.o
hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
$(addprefix 9pfs/, $(9pfs-nested-y)): QEMU_CFLAGS+=$(GLIB_CFLAGS)
diff --git a/hw/9pfs/virtio-9p-marshal.c b/hw/9pfs/virtio-9p-marshal.c
new file mode 100644
index 0000000..1a21254
--- /dev/null
+++ b/hw/9pfs/virtio-9p-marshal.c
@@ -0,0 +1,257 @@
+/*
+ * Virtio 9p backend
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ * Anthony Liguori <aliguori@us.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 "virtio-9p.h"
+
+static size_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count,
+ size_t offset, size_t size, int pack)
+{
+ int i = 0;
+ size_t copied = 0;
+
+ for (i = 0; size && i < sg_count; i++) {
+ size_t len;
+ if (offset >= sg[i].iov_len) {
+ /* skip this sg */
+ offset -= sg[i].iov_len;
+ continue;
+ } else {
+ len = MIN(sg[i].iov_len - offset, size);
+ if (pack) {
+ memcpy(sg[i].iov_base + offset, addr, len);
+ } else {
+ memcpy(addr, sg[i].iov_base + offset, len);
+ }
+ size -= len;
+ copied += len;
+ addr += len;
+ if (size) {
+ offset = 0;
+ continue;
+ }
+ }
+ }
+
+ return copied;
+}
+
+static size_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num,
+ size_t offset, size_t size)
+{
+ return v9fs_packunpack(dst, out_sg, out_num, offset, size, 0);
+}
+
+size_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset, const void *src,
+ size_t size)
+{
+ return v9fs_packunpack((void *)src, in_sg, in_num, offset, size, 1);
+}
+
+static int v9fs_copy_sg(struct iovec *src_sg, unsigned int num,
+ size_t offset, struct iovec *sg)
+{
+ size_t pos = 0;
+ int i, j;
+
+ j = 0;
+ for (i = 0; i < num; i++) {
+ if (offset <= pos) {
+ sg[j].iov_base = src_sg[i].iov_base;
+ sg[j].iov_len = src_sg[i].iov_len;
+ j++;
+ } else if (offset < (src_sg[i].iov_len + pos)) {
+ sg[j].iov_base = src_sg[i].iov_base;
+ sg[j].iov_len = src_sg[i].iov_len;
+ sg[j].iov_base += (offset - pos);
+ sg[j].iov_len -= (offset - pos);
+ j++;
+ }
+ pos += src_sg[i].iov_len;
+ }
+
+ return j;
+}
+
+size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
+ const char *fmt, ...)
+{
+ size_t old_offset = offset;
+ va_list ap;
+ int i;
+
+ va_start(ap, fmt);
+ for (i = 0; fmt[i]; i++) {
+ switch (fmt[i]) {
+ case 'b': {
+ uint8_t *valp = va_arg(ap, uint8_t *);
+ offset += v9fs_unpack(valp, out_sg, out_num, offset, sizeof(*valp));
+ break;
+ }
+ case 'w': {
+ uint16_t val, *valp;
+ valp = va_arg(ap, uint16_t *);
+ offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
+ *valp = le16_to_cpu(val);
+ break;
+ }
+ case 'd': {
+ uint32_t val, *valp;
+ valp = va_arg(ap, uint32_t *);
+ offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
+ *valp = le32_to_cpu(val);
+ break;
+ }
+ case 'q': {
+ uint64_t val, *valp;
+ valp = va_arg(ap, uint64_t *);
+ offset += v9fs_unpack(&val, out_sg, out_num, offset, sizeof(val));
+ *valp = le64_to_cpu(val);
+ break;
+ }
+ case 'v': {
+ struct iovec *iov = va_arg(ap, struct iovec *);
+ int *iovcnt = va_arg(ap, int *);
+ *iovcnt = v9fs_copy_sg(out_sg, out_num, offset, iov);
+ break;
+ }
+ case 's': {
+ V9fsString *str = va_arg(ap, V9fsString *);
+ offset += v9fs_unmarshal(out_sg, out_num, offset, "w", &str->size);
+ /* FIXME: sanity check str->size */
+ str->data = g_malloc(str->size + 1);
+ offset += v9fs_unpack(str->data, out_sg, out_num, offset, str->size);
+ str->data[str->size] = 0;
+ break;
+ }
+ case 'Q': {
+ V9fsQID *qidp = va_arg(ap, V9fsQID *);
+ offset += v9fs_unmarshal(out_sg, out_num, offset, "bdq",
+ &qidp->type, &qidp->version, &qidp->path);
+ break;
+ }
+ case 'S': {
+ V9fsStat *statp = va_arg(ap, V9fsStat *);
+ offset += v9fs_unmarshal(out_sg, out_num, offset, "wwdQdddqsssssddd",
+ &statp->size, &statp->type, &statp->dev,
+ &statp->qid, &statp->mode, &statp->atime,
+ &statp->mtime, &statp->length,
+ &statp->name, &statp->uid, &statp->gid,
+ &statp->muid, &statp->extension,
+ &statp->n_uid, &statp->n_gid,
+ &statp->n_muid);
+ break;
+ }
+ case 'I': {
+ V9fsIattr *iattr = va_arg(ap, V9fsIattr *);
+ offset += v9fs_unmarshal(out_sg, out_num, offset, "ddddqqqqq",
+ &iattr->valid, &iattr->mode,
+ &iattr->uid, &iattr->gid, &iattr->size,
+ &iattr->atime_sec, &iattr->atime_nsec,
+ &iattr->mtime_sec, &iattr->mtime_nsec);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+
+ va_end(ap);
+
+ return offset - old_offset;
+}
+
+size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset,
+ const char *fmt, ...)
+{
+ size_t old_offset = offset;
+ va_list ap;
+ int i;
+
+ va_start(ap, fmt);
+ for (i = 0; fmt[i]; i++) {
+ switch (fmt[i]) {
+ case 'b': {
+ uint8_t val = va_arg(ap, int);
+ offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+ break;
+ }
+ case 'w': {
+ uint16_t val;
+ cpu_to_le16w(&val, va_arg(ap, int));
+ offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+ break;
+ }
+ case 'd': {
+ uint32_t val;
+ cpu_to_le32w(&val, va_arg(ap, uint32_t));
+ offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+ break;
+ }
+ case 'q': {
+ uint64_t val;
+ cpu_to_le64w(&val, va_arg(ap, uint64_t));
+ offset += v9fs_pack(in_sg, in_num, offset, &val, sizeof(val));
+ break;
+ }
+ case 'v': {
+ struct iovec *iov = va_arg(ap, struct iovec *);
+ int *iovcnt = va_arg(ap, int *);
+ *iovcnt = v9fs_copy_sg(in_sg, in_num, offset, iov);
+ break;
+ }
+ case 's': {
+ V9fsString *str = va_arg(ap, V9fsString *);
+ offset += v9fs_marshal(in_sg, in_num, offset, "w", str->size);
+ offset += v9fs_pack(in_sg, in_num, offset, str->data, str->size);
+ break;
+ }
+ case 'Q': {
+ V9fsQID *qidp = va_arg(ap, V9fsQID *);
+ offset += v9fs_marshal(in_sg, in_num, offset, "bdq",
+ qidp->type, qidp->version, qidp->path);
+ break;
+ }
+ case 'S': {
+ V9fsStat *statp = va_arg(ap, V9fsStat *);
+ offset += v9fs_marshal(in_sg, in_num, offset, "wwdQdddqsssssddd",
+ statp->size, statp->type, statp->dev,
+ &statp->qid, statp->mode, statp->atime,
+ statp->mtime, statp->length, &statp->name,
+ &statp->uid, &statp->gid, &statp->muid,
+ &statp->extension, statp->n_uid,
+ statp->n_gid, statp->n_muid);
+ break;
+ }
+ case 'A': {
+ V9fsStatDotl *statp = va_arg(ap, V9fsStatDotl *);
+ offset += v9fs_marshal(in_sg, in_num, offset, "qQdddqqqqqqqqqqqqqqq",
+ statp->st_result_mask,
+ &statp->qid, statp->st_mode,
+ statp->st_uid, statp->st_gid,
+ statp->st_nlink, statp->st_rdev,
+ statp->st_size, statp->st_blksize,
+ statp->st_blocks, statp->st_atime_sec,
+ statp->st_atime_nsec, statp->st_mtime_sec,
+ statp->st_mtime_nsec, statp->st_ctime_sec,
+ statp->st_ctime_nsec, statp->st_btime_sec,
+ statp->st_btime_nsec, statp->st_gen,
+ statp->st_data_version);
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ va_end(ap);
+
+ return offset - old_offset;
+}
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 0777ece..177c0ee 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -695,257 +695,6 @@ static void free_pdu(V9fsState *s, V9fsPDU *pdu)
}
}
-size_t pdu_packunpack(void *addr, struct iovec *sg, int sg_count,
- size_t offset, size_t size, int pack)
-{
- int i = 0;
- size_t copied = 0;
-
- for (i = 0; size && i < sg_count; i++) {
- size_t len;
- if (offset >= sg[i].iov_len) {
- /* skip this sg */
- offset -= sg[i].iov_len;
- continue;
- } else {
- len = MIN(sg[i].iov_len - offset, size);
- if (pack) {
- memcpy(sg[i].iov_base + offset, addr, len);
- } else {
- memcpy(addr, sg[i].iov_base + offset, len);
- }
- size -= len;
- copied += len;
- addr += len;
- if (size) {
- offset = 0;
- continue;
- }
- }
- }
-
- return copied;
-}
-
-static size_t pdu_unpack(void *dst, V9fsPDU *pdu, size_t offset, size_t size)
-{
- return pdu_packunpack(dst, pdu->elem.out_sg, pdu->elem.out_num,
- offset, size, 0);
-}
-
-static size_t pdu_pack(V9fsPDU *pdu, size_t offset, const void *src,
- size_t size)
-{
- return pdu_packunpack((void *)src, pdu->elem.in_sg, pdu->elem.in_num,
- offset, size, 1);
-}
-
-static int pdu_copy_sg(V9fsPDU *pdu, size_t offset, int rx, struct iovec *sg)
-{
- size_t pos = 0;
- int i, j;
- struct iovec *src_sg;
- unsigned int num;
-
- if (rx) {
- src_sg = pdu->elem.in_sg;
- num = pdu->elem.in_num;
- } else {
- src_sg = pdu->elem.out_sg;
- num = pdu->elem.out_num;
- }
-
- j = 0;
- for (i = 0; i < num; i++) {
- if (offset <= pos) {
- sg[j].iov_base = src_sg[i].iov_base;
- sg[j].iov_len = src_sg[i].iov_len;
- j++;
- } else if (offset < (src_sg[i].iov_len + pos)) {
- sg[j].iov_base = src_sg[i].iov_base;
- sg[j].iov_len = src_sg[i].iov_len;
- sg[j].iov_base += (offset - pos);
- sg[j].iov_len -= (offset - pos);
- j++;
- }
- pos += src_sg[i].iov_len;
- }
-
- return j;
-}
-
-static size_t pdu_unmarshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
-{
- size_t old_offset = offset;
- va_list ap;
- int i;
-
- va_start(ap, fmt);
- for (i = 0; fmt[i]; i++) {
- switch (fmt[i]) {
- case 'b': {
- uint8_t *valp = va_arg(ap, uint8_t *);
- offset += pdu_unpack(valp, pdu, offset, sizeof(*valp));
- break;
- }
- case 'w': {
- uint16_t val, *valp;
- valp = va_arg(ap, uint16_t *);
- offset += pdu_unpack(&val, pdu, offset, sizeof(val));
- *valp = le16_to_cpu(val);
- break;
- }
- case 'd': {
- uint32_t val, *valp;
- valp = va_arg(ap, uint32_t *);
- offset += pdu_unpack(&val, pdu, offset, sizeof(val));
- *valp = le32_to_cpu(val);
- break;
- }
- case 'q': {
- uint64_t val, *valp;
- valp = va_arg(ap, uint64_t *);
- offset += pdu_unpack(&val, pdu, offset, sizeof(val));
- *valp = le64_to_cpu(val);
- break;
- }
- case 'v': {
- struct iovec *iov = va_arg(ap, struct iovec *);
- int *iovcnt = va_arg(ap, int *);
- *iovcnt = pdu_copy_sg(pdu, offset, 0, iov);
- break;
- }
- case 's': {
- V9fsString *str = va_arg(ap, V9fsString *);
- offset += pdu_unmarshal(pdu, offset, "w", &str->size);
- /* FIXME: sanity check str->size */
- str->data = g_malloc(str->size + 1);
- offset += pdu_unpack(str->data, pdu, offset, str->size);
- str->data[str->size] = 0;
- break;
- }
- case 'Q': {
- V9fsQID *qidp = va_arg(ap, V9fsQID *);
- offset += pdu_unmarshal(pdu, offset, "bdq",
- &qidp->type, &qidp->version, &qidp->path);
- break;
- }
- case 'S': {
- V9fsStat *statp = va_arg(ap, V9fsStat *);
- offset += pdu_unmarshal(pdu, offset, "wwdQdddqsssssddd",
- &statp->size, &statp->type, &statp->dev,
- &statp->qid, &statp->mode, &statp->atime,
- &statp->mtime, &statp->length,
- &statp->name, &statp->uid, &statp->gid,
- &statp->muid, &statp->extension,
- &statp->n_uid, &statp->n_gid,
- &statp->n_muid);
- break;
- }
- case 'I': {
- V9fsIattr *iattr = va_arg(ap, V9fsIattr *);
- offset += pdu_unmarshal(pdu, offset, "ddddqqqqq",
- &iattr->valid, &iattr->mode,
- &iattr->uid, &iattr->gid, &iattr->size,
- &iattr->atime_sec, &iattr->atime_nsec,
- &iattr->mtime_sec, &iattr->mtime_nsec);
- break;
- }
- default:
- break;
- }
- }
-
- va_end(ap);
-
- return offset - old_offset;
-}
-
-static size_t pdu_marshal(V9fsPDU *pdu, size_t offset, const char *fmt, ...)
-{
- size_t old_offset = offset;
- va_list ap;
- int i;
-
- va_start(ap, fmt);
- for (i = 0; fmt[i]; i++) {
- switch (fmt[i]) {
- case 'b': {
- uint8_t val = va_arg(ap, int);
- offset += pdu_pack(pdu, offset, &val, sizeof(val));
- break;
- }
- case 'w': {
- uint16_t val;
- cpu_to_le16w(&val, va_arg(ap, int));
- offset += pdu_pack(pdu, offset, &val, sizeof(val));
- break;
- }
- case 'd': {
- uint32_t val;
- cpu_to_le32w(&val, va_arg(ap, uint32_t));
- offset += pdu_pack(pdu, offset, &val, sizeof(val));
- break;
- }
- case 'q': {
- uint64_t val;
- cpu_to_le64w(&val, va_arg(ap, uint64_t));
- offset += pdu_pack(pdu, offset, &val, sizeof(val));
- break;
- }
- case 'v': {
- struct iovec *iov = va_arg(ap, struct iovec *);
- int *iovcnt = va_arg(ap, int *);
- *iovcnt = pdu_copy_sg(pdu, offset, 1, iov);
- break;
- }
- case 's': {
- V9fsString *str = va_arg(ap, V9fsString *);
- offset += pdu_marshal(pdu, offset, "w", str->size);
- offset += pdu_pack(pdu, offset, str->data, str->size);
- break;
- }
- case 'Q': {
- V9fsQID *qidp = va_arg(ap, V9fsQID *);
- offset += pdu_marshal(pdu, offset, "bdq",
- qidp->type, qidp->version, qidp->path);
- break;
- }
- case 'S': {
- V9fsStat *statp = va_arg(ap, V9fsStat *);
- offset += pdu_marshal(pdu, offset, "wwdQdddqsssssddd",
- statp->size, statp->type, statp->dev,
- &statp->qid, statp->mode, statp->atime,
- statp->mtime, statp->length, &statp->name,
- &statp->uid, &statp->gid, &statp->muid,
- &statp->extension, statp->n_uid,
- statp->n_gid, statp->n_muid);
- break;
- }
- case 'A': {
- V9fsStatDotl *statp = va_arg(ap, V9fsStatDotl *);
- offset += pdu_marshal(pdu, offset, "qQdddqqqqqqqqqqqqqqq",
- statp->st_result_mask,
- &statp->qid, statp->st_mode,
- statp->st_uid, statp->st_gid,
- statp->st_nlink, statp->st_rdev,
- statp->st_size, statp->st_blksize, statp->st_blocks,
- statp->st_atime_sec, statp->st_atime_nsec,
- statp->st_mtime_sec, statp->st_mtime_nsec,
- statp->st_ctime_sec, statp->st_ctime_nsec,
- statp->st_btime_sec, statp->st_btime_nsec,
- statp->st_gen, statp->st_data_version);
- break;
- }
- default:
- break;
- }
- }
- va_end(ap);
-
- return offset - old_offset;
-}
-
static void complete_pdu(V9fsState *s, V9fsPDU *pdu, ssize_t len)
{
int8_t id = pdu->id + 1; /* Response */
@@ -1853,9 +1602,10 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu,
read_count = 0;
}
offset += pdu_marshal(pdu, offset, "d", read_count);
- offset += pdu_pack(pdu, offset,
- ((char *)fidp->fs.xattr.value) + off,
- read_count);
+ offset += v9fs_pack(pdu->elem.in_sg, pdu->elem.in_num, offset,
+ ((char *)fidp->fs.xattr.value) + off,
+ read_count);
+
return offset;
}
diff --git a/hw/9pfs/virtio-9p.h b/hw/9pfs/virtio-9p.h
index 7f88356..1d8665e 100644
--- a/hw/9pfs/virtio-9p.h
+++ b/hw/9pfs/virtio-9p.h
@@ -468,4 +468,16 @@ extern void v9fs_path_free(V9fsPath *path);
extern void v9fs_path_copy(V9fsPath *lhs, V9fsPath *rhs);
extern int v9fs_name_to_path(V9fsState *s, V9fsPath *dirpath,
const char *name, V9fsPath *path);
+
+size_t v9fs_pack(struct iovec *in_sg, int in_num, size_t offset,
+ const void *src, size_t size);
+size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
+ const char *fmt, ...);
+size_t v9fs_marshal(struct iovec *in_sg, int in_num, size_t offset,
+ const char *fmt, ...);
+#define pdu_marshal(pdu, offset, fmt, args...) \
+ v9fs_marshal(pdu->elem.in_sg, pdu->elem.in_num, offset, fmt, ##args)
+#define pdu_unmarshal(pdu, offset, fmt, args...) \
+ v9fs_unmarshal(pdu->elem.out_sg, pdu->elem.out_num, offset, fmt, ##args)
+
#endif
--
1.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 03/13] hw/9pfs: Add new proxy filesystem driver
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 ` 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
` (8 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
From: "M. Mohan Kumar" <mohan@in.ibm.com>
Add new proxy filesystem driver to add root privilege to qemu process.
It needs a helper process to be started by root user.
Following command line can be used to utilize proxy filesystem driver
-virtfs proxy,id=<id>,mount_tag=<tag>,sock_fd=<socket-fd>
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
Makefile.objs | 1 +
fsdev/qemu-fsdev.c | 1 +
fsdev/qemu-fsdev.h | 1 +
hw/9pfs/proxy.h | 10 ++
hw/9pfs/virtio-9p-proxy.c | 374 +++++++++++++++++++++++++++++++++++++++++++++
qemu-config.c | 7 +
vl.c | 6 +-
7 files changed, 399 insertions(+), 1 deletions(-)
create mode 100644 hw/9pfs/proxy.h
create mode 100644 hw/9pfs/virtio-9p-proxy.c
diff --git a/Makefile.objs b/Makefile.objs
index 804bc3c..fd5f73c 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -311,6 +311,7 @@ hw-obj-$(CONFIG_SOUND) += $(sound-obj-y)
9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-coth.o cofs.o codir.o cofile.o
9pfs-nested-$(CONFIG_VIRTFS) += coxattr.o virtio-9p-handle.o
9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-synth.o virtio-9p-marshal.o
+9pfs-nested-$(CONFIG_VIRTFS) += virtio-9p-proxy.o
hw-obj-$(CONFIG_REALLY_VIRTFS) += $(addprefix 9pfs/, $(9pfs-nested-y))
$(addprefix 9pfs/, $(9pfs-nested-y)): QEMU_CFLAGS+=$(GLIB_CFLAGS)
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index efbfea1..b31d116 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -25,6 +25,7 @@ static FsDriverTable FsDrivers[] = {
{ .name = "local", .ops = &local_ops},
{ .name = "handle", .ops = &handle_ops},
{ .name = "synth", .ops = &synth_ops},
+ { .name = "proxy", .ops = &proxy_ops},
};
int qemu_fsdev_add(QemuOpts *opts)
diff --git a/fsdev/qemu-fsdev.h b/fsdev/qemu-fsdev.h
index 921452d..1af1f54 100644
--- a/fsdev/qemu-fsdev.h
+++ b/fsdev/qemu-fsdev.h
@@ -44,4 +44,5 @@ FsDriverEntry *get_fsdev_fsentry(char *id);
extern FileOperations local_ops;
extern FileOperations handle_ops;
extern FileOperations synth_ops;
+extern FileOperations proxy_ops;
#endif
diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
new file mode 100644
index 0000000..1a47509
--- /dev/null
+++ b/hw/9pfs/proxy.h
@@ -0,0 +1,10 @@
+#ifndef __PROXY_HELP_H
+#define __PROXY_HELP_H
+
+#define BUFF_SZ (4 * 1024)
+
+typedef struct {
+ int type;
+ int size;
+} ProxyHeader;
+#endif
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
new file mode 100644
index 0000000..c682e36
--- /dev/null
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -0,0 +1,374 @@
+/*
+ * Virtio 9p Proxy callback
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * M. Mohan Kumar <mohan@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/socket.h>
+#include <sys/un.h>
+#include "hw/virtio.h"
+#include "virtio-9p.h"
+#include "fsdev/qemu-fsdev.h"
+#include "proxy.h"
+
+typedef struct V9fsProxy {
+ int sockfd;
+ QemuMutex mutex;
+ struct iovec iovec;
+} V9fsProxy;
+
+static int proxy_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static ssize_t proxy_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
+ char *buf, size_t bufsz)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int proxy_close(FsContext *ctx, V9fsFidOpenState *fs)
+{
+ return close(fs->fd);
+}
+
+static int proxy_closedir(FsContext *ctx, V9fsFidOpenState *fs)
+{
+ return closedir(fs->dir);
+}
+
+static int proxy_open(FsContext *ctx, V9fsPath *fs_path,
+ int flags, V9fsFidOpenState *fs)
+{
+ fs->fd = -1;
+ return fs->fd;
+}
+
+static int proxy_opendir(FsContext *ctx,
+ V9fsPath *fs_path, V9fsFidOpenState *fs)
+{
+ fs->dir = NULL;
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static void proxy_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
+{
+ return rewinddir(fs->dir);
+}
+
+static off_t proxy_telldir(FsContext *ctx, V9fsFidOpenState *fs)
+{
+ return telldir(fs->dir);
+}
+
+static int proxy_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
+ struct dirent *entry,
+ struct dirent **result)
+{
+ return readdir_r(fs->dir, entry, result);
+}
+
+static void proxy_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
+{
+ return seekdir(fs->dir, off);
+}
+
+static ssize_t proxy_preadv(FsContext *ctx, V9fsFidOpenState *fs,
+ const struct iovec *iov,
+ int iovcnt, off_t offset)
+{
+#ifdef CONFIG_PREADV
+ return preadv(fs->fd, iov, iovcnt, offset);
+#else
+ int err = lseek(fs->fd, offset, SEEK_SET);
+ if (err == -1) {
+ return err;
+ } else {
+ return readv(fs->fd, iov, iovcnt);
+ }
+#endif
+}
+
+static ssize_t proxy_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
+ const struct iovec *iov,
+ int iovcnt, off_t offset)
+{
+ ssize_t ret
+;
+#ifdef CONFIG_PREADV
+ ret = pwritev(fs->fd, iov, iovcnt, offset);
+#else
+ int err = lseek(fs->fd, offset, SEEK_SET);
+ if (err == -1) {
+ return err;
+ } else {
+ ret = writev(fs->fd, iov, iovcnt);
+ }
+#endif
+#ifdef CONFIG_SYNC_FILE_RANGE
+ if (ret > 0 && ctx->export_flags & V9FS_IMMEDIATE_WRITEOUT) {
+ /*
+ * Initiate a writeback. This is not a data integrity sync.
+ * We want to ensure that we don't leave dirty pages in the cache
+ * after write when writeout=immediate is sepcified.
+ */
+ sync_file_range(fs->fd, offset, ret,
+ SYNC_FILE_RANGE_WAIT_BEFORE | SYNC_FILE_RANGE_WRITE);
+ }
+#endif
+ return ret;
+}
+
+static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
+ const char *name, FsCred *credp)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int proxy_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
+ const char *name, FsCred *credp)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int proxy_fstat(FsContext *fs_ctx,
+ V9fsFidOpenState *fs, struct stat *stbuf)
+{
+ int err;
+ err = fstat(fs->fd, stbuf);
+ return err;
+}
+
+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;
+}
+
+
+static int proxy_symlink(FsContext *fs_ctx, const char *oldpath,
+ V9fsPath *dir_path, const char *name, FsCred *credp)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
+ V9fsPath *dirpath, const char *name)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int proxy_rename(FsContext *ctx, const char *oldpath,
+ const char *newpath)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int proxy_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int proxy_utimensat(FsContext *s, V9fsPath *fs_path,
+ const struct timespec *buf)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int proxy_remove(FsContext *ctx, const char *path)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int proxy_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)
+{
+ if (datasync) {
+ return qemu_fdatasync(fs->fd);
+ } else {
+ return fsync(fs->fd);
+ }
+}
+
+static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
+ const char *name, void *value, size_t size)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static ssize_t proxy_llistxattr(FsContext *ctx, V9fsPath *fs_path,
+ void *value, size_t size)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int proxy_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
+ void *value, size_t size, int flags)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int proxy_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
+ const char *name)
+{
+ errno = EOPNOTSUPP;
+ return -1;
+}
+
+static int proxy_name_to_path(FsContext *ctx, V9fsPath *dir_path,
+ const char *name, V9fsPath *target)
+{
+ if (dir_path) {
+ v9fs_string_sprintf((V9fsString *)target, "%s/%s",
+ dir_path->data, name);
+ } else {
+ v9fs_string_sprintf((V9fsString *)target, "%s", name);
+ }
+ /* Bump the size for including terminating NULL */
+ target->size++;
+ return 0;
+}
+
+static int proxy_renameat(FsContext *ctx, V9fsPath *olddir,
+ const char *old_name, V9fsPath *newdir,
+ const char *new_name)
+{
+ int ret;
+ V9fsString old_full_name, new_full_name;
+
+ v9fs_string_init(&old_full_name);
+ v9fs_string_init(&new_full_name);
+
+ v9fs_string_sprintf(&old_full_name, "%s/%s", olddir->data, old_name);
+ v9fs_string_sprintf(&new_full_name, "%s/%s", newdir->data, new_name);
+
+ ret = proxy_rename(ctx, old_full_name.data, new_full_name.data);
+ v9fs_string_free(&old_full_name);
+ v9fs_string_free(&new_full_name);
+ return ret;
+}
+
+static int proxy_unlinkat(FsContext *ctx, V9fsPath *dir,
+ const char *name, int flags)
+{
+ int ret;
+ V9fsString fullname;
+ v9fs_string_init(&fullname);
+
+ v9fs_string_sprintf(&fullname, "%s/%s", dir->data, name);
+ ret = proxy_remove(ctx, fullname.data);
+ v9fs_string_free(&fullname);
+
+ return ret;
+}
+
+static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
+{
+ const char *sock_fd = qemu_opt_get(opts, "sock_fd");
+
+ if (sock_fd) {
+ fprintf(stderr, "sock_fd option not specified\n");
+ return -1;
+ }
+ fs->path = g_strdup(sock_fd);
+ return 0;
+}
+
+static int proxy_init(FsContext *ctx)
+{
+ V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy));
+ int sock_id;
+
+ sock_id = atoi(ctx->fs_root);
+ if (sock_id < 0) {
+ fprintf(stderr, "socket descriptor not initialized\n");
+ return -1;
+ }
+ g_free(ctx->fs_root);
+
+ proxy->iovec.iov_base = g_malloc(BUFF_SZ);
+ proxy->iovec.iov_len = BUFF_SZ;
+ ctx->private = proxy;
+ proxy->sockfd = sock_id;
+ qemu_mutex_init(&proxy->mutex);
+
+ ctx->export_flags |= V9FS_PATHNAME_FSCONTEXT;
+ return 0;
+}
+
+FileOperations proxy_ops = {
+ .parse_opts = proxy_parse_opts,
+ .init = proxy_init,
+ .lstat = proxy_lstat,
+ .readlink = proxy_readlink,
+ .close = proxy_close,
+ .closedir = proxy_closedir,
+ .open = proxy_open,
+ .opendir = proxy_opendir,
+ .rewinddir = proxy_rewinddir,
+ .telldir = proxy_telldir,
+ .readdir_r = proxy_readdir_r,
+ .seekdir = proxy_seekdir,
+ .preadv = proxy_preadv,
+ .pwritev = proxy_pwritev,
+ .chmod = proxy_chmod,
+ .mknod = proxy_mknod,
+ .mkdir = proxy_mkdir,
+ .fstat = proxy_fstat,
+ .open2 = proxy_open2,
+ .symlink = proxy_symlink,
+ .link = proxy_link,
+ .truncate = proxy_truncate,
+ .rename = proxy_rename,
+ .chown = proxy_chown,
+ .utimensat = proxy_utimensat,
+ .remove = proxy_remove,
+ .fsync = proxy_fsync,
+ .statfs = proxy_statfs,
+ .lgetxattr = proxy_lgetxattr,
+ .llistxattr = proxy_llistxattr,
+ .lsetxattr = proxy_lsetxattr,
+ .lremovexattr = proxy_lremovexattr,
+ .name_to_path = proxy_name_to_path,
+ .renameat = proxy_renameat,
+ .unlinkat = proxy_unlinkat,
+};
diff --git a/qemu-config.c b/qemu-config.c
index 597d7e1..5e63c14 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -183,6 +183,10 @@ QemuOptsList qemu_fsdev_opts = {
}, {
.name = "readonly",
.type = QEMU_OPT_BOOL,
+
+ }, {
+ .name = "sock_fd",
+ .type = QEMU_OPT_NUMBER,
},
{ /*End of list */ }
@@ -212,6 +216,9 @@ QemuOptsList qemu_virtfs_opts = {
}, {
.name = "readonly",
.type = QEMU_OPT_BOOL,
+ }, {
+ .name = "sock_fd",
+ .type = QEMU_OPT_NUMBER,
},
{ /*End of list */ }
diff --git a/vl.c b/vl.c
index cf538b2..5a5ab7f 100644
--- a/vl.c
+++ b/vl.c
@@ -2663,7 +2663,7 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_virtfs: {
QemuOpts *fsdev;
QemuOpts *device;
- const char *writeout;
+ const char *writeout, *sock_fd;
olist = qemu_find_opts("virtfs");
if (!olist) {
@@ -2703,6 +2703,10 @@ int main(int argc, char **argv, char **envp)
qemu_opt_set(fsdev, "path", qemu_opt_get(opts, "path"));
qemu_opt_set(fsdev, "security_model",
qemu_opt_get(opts, "security_model"));
+ sock_fd = qemu_opt_get(opts, "sock_fd");
+ if (sock_fd) {
+ qemu_opt_set(fsdev, "sock_fd", sock_fd);
+ }
qemu_opt_set_bool(fsdev, "readonly",
qemu_opt_get_bool(opts, "readonly", 0));
--
1.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 04/13] hw/9pfs: File system helper process for qemu 9p proxy FS
2011-10-31 20:53 [Qemu-devel] [PATCH 00/13] Proxy FS driver for VirtFS M. Mohan Kumar
` (2 preceding siblings ...)
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 ` 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
` (7 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
From: "M. Mohan Kumar" <mohan@in.ibm.com>
Provide root privilege access to QEMU 9p proxy filesystem using socket
communication.
Proxy helper is started by root user as:
~ # virtfs-proxy-helper
{{-s|--socket <socketname> -u|--uid -g|--gid}|{-f|--fd <socket descriptor>}}
-p <path-to-share> [-r <runasuid> -t <runasgid>]
Where uid:gid gives socket access to uid:gid, -r:t combination drops the
privilege to given uid:gid
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
Makefile | 2 +
configure | 25 ++++
hw/9pfs/proxy.h | 6 +
hw/9pfs/virtfs-proxy-helper.c | 262 +++++++++++++++++++++++++++++++++++++++++
4 files changed, 295 insertions(+), 0 deletions(-)
create mode 100644 hw/9pfs/virtfs-proxy-helper.c
diff --git a/Makefile b/Makefile
index f63fc02..1fd443d 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): LIBS+=$(LIBS_PROXY)
+
qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
$(call quiet-command,sh $(SRC_PATH)/scripts/hxtool -h < $< > $@," GEN $@")
diff --git a/configure b/configure
index 19e8394..8abd17c 100755
--- a/configure
+++ b/configure
@@ -1866,6 +1866,23 @@ else
fi
##########################################
+# libcap probe
+
+if test "$cap" != "no" ; then
+ cat > $TMPC <<EOF
+#include <stdio.h>
+#include <sys/capability.h>
+int main(void) { cap_t caps; caps = cap_init(); }
+EOF
+ if compile_prog "" "-lcap" ; then
+ cap=yes
+ libs_proxy="-lcap"
+ else
+ cap=no
+ fi
+fi
+
+##########################################
# pthread probe
PTHREADLIBS_LIST="-pthread -lpthread -lpthreadGC2"
@@ -2636,6 +2653,9 @@ confdir=$sysconfdir$confsuffix
tools=
if test "$softmmu" = yes ; then
tools="qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools"
+if test "$cap" = yes; then
+ tools="$tools hw/9pfs/virtfs-proxy-helper\$(EXESUF)"
+fi
if [ "$linux" = "yes" -o "$bsd" = "yes" -o "$solaris" = "yes" ] ; then
tools="qemu-nbd\$(EXESUF) $tools"
if [ "$guest_agent" = "yes" ]; then
@@ -3068,6 +3088,10 @@ if test "$linux_magic_h" = "yes" ; then
echo "CONFIG_LINUX_MAGIC_H=y" >> $config_host_mak
fi
+if test "$cap" = "yes" ; then
+ echo "CONFIG_CAPABILITY=y" >> $config_host_mak
+fi
+
# USB host support
case "$usb" in
linux)
@@ -3143,6 +3167,7 @@ echo "LIBS+=$LIBS" >> $config_host_mak
echo "LIBS_TOOLS+=$libs_tools" >> $config_host_mak
echo "EXESUF=$EXESUF" >> $config_host_mak
echo "LIBS_QGA+=$libs_qga" >> $config_host_mak
+echo "LIBS_PROXY+=$libs_proxy" >> $config_host_mak
# generate list of library paths for linker script
diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
index 1a47509..205d7b7 100644
--- a/hw/9pfs/proxy.h
+++ b/hw/9pfs/proxy.h
@@ -2,6 +2,12 @@
#define __PROXY_HELP_H
#define BUFF_SZ (4 * 1024)
+#define V9FS_FD_VALID INT_MAX
+
+union MsgControl {
+ struct cmsghdr cmsg;
+ char control[CMSG_SPACE(sizeof(int))];
+};
typedef struct {
int type;
diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
new file mode 100644
index 0000000..8e82ca7
--- /dev/null
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -0,0 +1,262 @@
+#include <stdio.h>
+#include <sys/socket.h>
+#include <string.h>
+#include <sys/un.h>
+#include <limits.h>
+#include <signal.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+#include <sys/stat.h>
+#include <getopt.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <sys/prctl.h>
+#include <sys/capability.h>
+#include <sys/fsuid.h>
+#include <stdarg.h>
+#include "bswap.h"
+#include <sys/socket.h>
+#include "qemu-common.h"
+#include "hw/9pfs/proxy.h"
+
+#define PROGNAME "virtfs-proxy-helper"
+
+static struct option helper_opts[] = {
+ {"fd", required_argument, NULL, 'f'},
+ {"path", required_argument, NULL, 'p'},
+ {"nodaemon", no_argument, NULL, 'n'},
+};
+
+int is_daemon;
+
+static void do_perror(const char *string)
+{
+ if (is_daemon) {
+ syslog(LOG_CRIT, "%s:%s", string, strerror(errno));
+ } else {
+ fprintf(stderr, "%s:%s\n", string, strerror(errno));
+ }
+}
+
+static void do_log(int level, const char *string)
+{
+ if (is_daemon) {
+ syslog(level, "%s", string);
+ } else {
+ fprintf(stderr, "%s\n", string);
+ }
+}
+
+static int cap_set(void)
+{
+ int retval;
+ cap_t caps;
+ cap_value_t cap_list[10];
+
+ /* helper needs following capbabilities only */
+ cap_list[0] = CAP_CHOWN;
+ cap_list[1] = CAP_DAC_OVERRIDE;
+ cap_list[2] = CAP_DAC_READ_SEARCH;
+ cap_list[3] = CAP_FOWNER;
+ cap_list[4] = CAP_FSETID;
+ cap_list[5] = CAP_SETGID;
+ cap_list[6] = CAP_MKNOD;
+ cap_list[7] = CAP_SETUID;
+
+ caps = cap_init();
+ if (caps == NULL) {
+ do_perror("cap_init");
+ return -1;
+ }
+ retval = cap_set_flag(caps, CAP_PERMITTED, 8, cap_list, CAP_SET);
+ if (retval < 0) {
+ do_perror("cap_set_flag");
+ goto error;
+ }
+ retval = cap_set_proc(caps);
+ if (retval < 0) {
+ do_perror("cap_set_proc");
+ }
+ retval = cap_set_flag(caps, CAP_EFFECTIVE, 8, cap_list, CAP_SET);
+ if (retval < 0) {
+ do_perror("cap_set_flag");
+ goto error;
+ }
+ retval = cap_set_proc(caps);
+ if (retval < 0) {
+ do_perror("cap_set_proc");
+ }
+
+error:
+ cap_free(caps);
+ return retval;
+}
+
+static int init_capabilities(void)
+{
+ if (prctl(PR_SET_KEEPCAPS, 1) < 0) {
+ do_perror("prctl");
+ return -1;
+ }
+ if (cap_set() < 0) {
+ return -1;
+ }
+ return 0;
+}
+
+static int socket_read(int sockfd, void *buff, ssize_t size)
+{
+ int retval;
+
+ do {
+ retval = read(sockfd, buff, size);
+ } while (retval < 0 && errno == EINTR);
+ if (retval != size) {
+ if (errno != ENOENT) {
+ do_perror("socket read");
+ }
+ return -EIO;
+ }
+ return retval;
+}
+
+static int socket_write(int sockfd, void *buff, ssize_t size)
+{
+ int retval;
+
+ do {
+ retval = write(sockfd, buff, size);
+ } while (retval < 0 && errno == EINTR);
+ if (retval != size) {
+ do_perror("socket_write");
+ return -EIO;
+ }
+ return retval;
+}
+
+static int read_request(int sockfd, struct iovec *iovec)
+{
+ int retval;
+ ProxyHeader header;
+
+ do {
+ retval = socket_read(sockfd, &header, sizeof(header));
+ if (retval != sizeof(header)) {
+ return -EIO;
+ }
+ retval = socket_read(sockfd, iovec->iov_base, header.size);
+ if (retval != header.size) {
+ return -EIO;
+ }
+ return header.type;
+ } while (1);
+}
+
+static void usage(char *prog)
+{
+ fprintf(stderr, "usage: %s\n"
+ " -p|--path <path> 9p path to export\n"
+ " {-f|--fd <socket-descriptor>} socket file descriptor to be used\n"
+ " [-n|--nodaemon] Run as a normal program\n",
+ basename(prog));
+}
+
+static int process_requests(int sock)
+{
+ int type;
+ struct iovec iovec;
+
+ iovec.iov_base = g_malloc(BUFF_SZ);
+ iovec.iov_len = BUFF_SZ;
+ while (1) {
+ type = read_request(sock, &iovec);
+ if (type <= 0) {
+ goto error;
+ }
+ }
+ (void)socket_write;
+error:
+ g_free(iovec.iov_base);
+ return -1;
+}
+
+int main(int argc, char **argv)
+{
+ int sock;
+ char rpath[PATH_MAX];
+ struct stat stbuf;
+ int c, option_index;
+
+ is_daemon = 1;
+ rpath[0] = '\0';
+ sock = -1;
+ while (1) {
+ option_index = 0;
+ c = getopt_long(argc, argv, "p:nh?f:", helper_opts,
+ &option_index);
+ if (c == -1) {
+ break;
+ }
+ switch (c) {
+ case 'p':
+ strcpy(rpath, optarg);
+ break;
+ case 'n':
+ is_daemon = 0;
+ break;
+ case 'f':
+ sock = atoi(optarg);
+ break;
+ case '?':
+ case 'h':
+ default:
+ usage(argv[0]);
+ return -1;
+ break;
+ }
+ }
+
+ /* Parameter validation */
+ if (sock == -1 || rpath[0] == '\0') {
+ fprintf(stderr, "socket descriptor or path not specified\n");
+ usage(argv[0]);
+ return -1;
+ }
+
+ if (lstat(rpath, &stbuf) < 0) {
+ fprintf(stderr, "invalid path \"%s\" specified?\n", rpath);
+ return -1;
+ }
+
+ if (!S_ISDIR(stbuf.st_mode)) {
+ fprintf(stderr, "specified path \"%s\" is not directory\n", rpath);
+ return -1;
+ }
+
+ if (is_daemon) {
+ if (daemon(1, 0) < 0) {
+ fprintf(stderr, "deamon error\n");
+ return -1;
+ }
+ openlog(PROGNAME, LOG_PID, LOG_DAEMON);
+ }
+
+ do_log(LOG_INFO, "Started");
+
+ if (chroot(rpath) < 0) {
+ do_perror("chroot");
+ goto error;
+ }
+ umask(0);
+
+ if (init_capabilities() < 0) {
+ goto error;
+ }
+
+ process_requests(sock);
+error:
+ do_log(LOG_INFO, "Done");
+ closelog();
+ return 0;
+}
--
1.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 05/13] hw/9pfs: Add support to use named socket for proxy FS
2011-10-31 20:53 [Qemu-devel] [PATCH 00/13] Proxy FS driver for VirtFS M. Mohan Kumar
` (3 preceding siblings ...)
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 ` M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 06/13] hw/9pfs: Open and create files M. Mohan Kumar
` (6 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
From: "M. Mohan Kumar" <mohan@in.ibm.com>
Add option to use named socket for communicating between proxy helper
and qemu proxy FS. Access to socket can be given by using command line
options -u and -g.
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
hw/9pfs/virtfs-proxy-helper.c | 89 ++++++++++++++++++++++++++++++++++++++--
hw/9pfs/virtio-9p-proxy.c | 56 ++++++++++++++++++++++---
qemu-config.c | 6 +++
vl.c | 6 ++-
4 files changed, 144 insertions(+), 13 deletions(-)
diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
index 8e82ca7..9d925e0 100644
--- a/hw/9pfs/virtfs-proxy-helper.c
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -26,6 +26,9 @@ static struct option helper_opts[] = {
{"fd", required_argument, NULL, 'f'},
{"path", required_argument, NULL, 'p'},
{"nodaemon", no_argument, NULL, 'n'},
+ {"socket", required_argument, NULL, 's'},
+ {"uid", required_argument, NULL, 'u'},
+ {"gid", required_argument, NULL, 'g'},
};
int is_daemon;
@@ -153,11 +156,61 @@ static int read_request(int sockfd, struct iovec *iovec)
} while (1);
}
+/* create unix domain socket and return the descriptor */
+static int proxy_socket(const char *path, uid_t uid, gid_t gid)
+{
+ int sock, client;
+ struct sockaddr_un proxy, qemu;
+ socklen_t size;
+
+ /* requested socket already exists, refuse to start */
+ if (!access(path, F_OK)) {
+ do_log(LOG_CRIT, "socket already exists\n");
+ return -1;
+ }
+
+ sock = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sock < 0) {
+ do_perror("socket");
+ return -1;
+ }
+
+ /* mask other part of mode bits */
+ umask(7);
+
+ proxy.sun_family = AF_UNIX;
+ strcpy(proxy.sun_path, path);
+ if (bind(sock, (struct sockaddr *)&proxy,
+ sizeof(struct sockaddr_un)) < 0) {
+ do_perror("bind");
+ return -1;
+ }
+ if (chown(proxy.sun_path, uid, gid) < 0) {
+ do_perror("chown");
+ return -1;
+ }
+ if (listen(sock, 1) < 0) {
+ do_perror("listen");
+ return -1;
+ }
+
+ client = accept(sock, (struct sockaddr *)&qemu, &size);
+ if (client < 0) {
+ do_perror("accept");
+ return -1;
+ }
+ return client;
+}
+
static void usage(char *prog)
{
fprintf(stderr, "usage: %s\n"
" -p|--path <path> 9p path to export\n"
" {-f|--fd <socket-descriptor>} socket file descriptor to be used\n"
+ " {-s|--socket <socketname> socket file used for communication\n"
+ " \t-u|--uid <uid> -g|--gid <gid>} - uid:gid combination to give "
+ " access to this socket\n"
+ " \tNote: -s & -f can not be used together\n"
" [-n|--nodaemon] Run as a normal program\n",
basename(prog));
}
@@ -184,16 +237,20 @@ error:
int main(int argc, char **argv)
{
int sock;
+ char sock_name[PATH_MAX];
char rpath[PATH_MAX];
struct stat stbuf;
int c, option_index;
+ uid_t own_u;
+ gid_t own_g;
is_daemon = 1;
- rpath[0] = '\0';
+ sock_name[0] = rpath[0] = '\0';
sock = -1;
+ own_u = own_g = -1;
while (1) {
option_index = 0;
- c = getopt_long(argc, argv, "p:nh?f:", helper_opts,
+ c = getopt_long(argc, argv, "p:nh?f:s:u:g:", helper_opts,
&option_index);
if (c == -1) {
break;
@@ -205,9 +262,18 @@ int main(int argc, char **argv)
case 'n':
is_daemon = 0;
break;
- case 'f':
+ case 'f':
sock = atoi(optarg);
break;
+ case 's':
+ strcpy(sock_name, optarg);
+ break;
+ case 'u':
+ own_u = atoi(optarg);
+ break;
+ case 'g':
+ own_g = atoi(optarg);
+ break;
case '?':
case 'h':
default:
@@ -218,8 +284,15 @@ int main(int argc, char **argv)
}
/* Parameter validation */
- if (sock == -1 || rpath[0] == '\0') {
- fprintf(stderr, "socket descriptor or path not specified\n");
+ if ((sock_name[0] == '\0' && sock == -1) || rpath[0] == '\0') {
+ fprintf(stderr, "socket, socket descriptor or path not specified\n");
+ usage(argv[0]);
+ return -1;
+ }
+
+ if (*sock_name && (own_u == -1 || own_g == -1)) {
+ fprintf(stderr, "owner uid:gid not specified, ");
+ fprintf(stderr, "owner specifies who can access the socket file\n");
usage(argv[0]);
return -1;
}
@@ -243,6 +316,12 @@ int main(int argc, char **argv)
}
do_log(LOG_INFO, "Started");
+ if (*sock_name) {
+ sock = proxy_socket(sock_name, own_u, own_g);
+ if (sock < 0) {
+ goto error;
+ }
+ }
if (chroot(rpath) < 0) {
do_perror("chroot");
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index c682e36..0ec686c 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -16,6 +16,10 @@
#include "fsdev/qemu-fsdev.h"
#include "proxy.h"
+/* FS specific flags */
+#define V9FS_PROXY_SOCK_FD (1 << 9)
+#define V9FS_PROXY_SOCK_NAME (1 << 10)
+
typedef struct V9fsProxy {
int sockfd;
QemuMutex mutex;
@@ -301,15 +305,49 @@ static int proxy_unlinkat(FsContext *ctx, V9fsPath *dir,
return ret;
}
+static int connect_namedsocket(const char *path)
+{
+ int sockfd, size;
+ struct sockaddr_un helper;
+
+ sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (sockfd < 0) {
+ fprintf(stderr, "socket %s\n", strerror(errno));
+ return -1;
+ }
+ strcpy(helper.sun_path, path);
+ helper.sun_family = AF_UNIX;
+ size = strlen(helper.sun_path) + sizeof(helper.sun_family);
+ if (connect(sockfd, (struct sockaddr *)&helper, size) < 0) {
+ fprintf(stderr, "socket error\n");
+ return -1;
+ }
+
+ /* remove the socket for security reasons */
+ unlink(path);
+ return sockfd;
+}
+
static int proxy_parse_opts(QemuOpts *opts, struct FsDriverEntry *fs)
{
+ const char *socket = qemu_opt_get(opts, "socket");
const char *sock_fd = qemu_opt_get(opts, "sock_fd");
- if (sock_fd) {
- fprintf(stderr, "sock_fd option not specified\n");
+ if (!socket && !sock_fd) {
+ fprintf(stderr, "socket and sock_fd none of the option specified\n");
+ return -1;
+ }
+ if (socket && sock_fd) {
+ fprintf(stderr, "Both socket and sock_fd options specified\n");
return -1;
}
- fs->path = g_strdup(sock_fd);
+ if (socket) {
+ fs->path = g_strdup(socket);
+ fs->export_flags = V9FS_PROXY_SOCK_NAME;
+ } else {
+ fs->path = g_strdup(sock_fd);
+ fs->export_flags = V9FS_PROXY_SOCK_FD;
+ }
return 0;
}
@@ -318,10 +356,14 @@ static int proxy_init(FsContext *ctx)
V9fsProxy *proxy = g_malloc(sizeof(V9fsProxy));
int sock_id;
- sock_id = atoi(ctx->fs_root);
- if (sock_id < 0) {
- fprintf(stderr, "socket descriptor not initialized\n");
- return -1;
+ if (ctx->export_flags & V9FS_PROXY_SOCK_NAME) {
+ sock_id = connect_namedsocket(ctx->fs_root);
+ } else {
+ sock_id = atoi(ctx->fs_root);
+ if (sock_id < 0) {
+ fprintf(stderr, "socket descriptor not initialized\n");
+ return -1;
+ }
}
g_free(ctx->fs_root);
diff --git a/qemu-config.c b/qemu-config.c
index 5e63c14..6203e7b 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -187,6 +187,9 @@ QemuOptsList qemu_fsdev_opts = {
}, {
.name = "sock_fd",
.type = QEMU_OPT_NUMBER,
+ }, {
+ .name = "socket",
+ .type = QEMU_OPT_STRING,
},
{ /*End of list */ }
@@ -219,6 +222,9 @@ QemuOptsList qemu_virtfs_opts = {
}, {
.name = "sock_fd",
.type = QEMU_OPT_NUMBER,
+ }, {
+ .name = "socket",
+ .type = QEMU_OPT_STRING,
},
{ /*End of list */ }
diff --git a/vl.c b/vl.c
index 5a5ab7f..8fbf481 100644
--- a/vl.c
+++ b/vl.c
@@ -2663,7 +2663,7 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_virtfs: {
QemuOpts *fsdev;
QemuOpts *device;
- const char *writeout, *sock_fd;
+ const char *writeout, *sock_fd, *socket;
olist = qemu_find_opts("virtfs");
if (!olist) {
@@ -2703,6 +2703,10 @@ int main(int argc, char **argv, char **envp)
qemu_opt_set(fsdev, "path", qemu_opt_get(opts, "path"));
qemu_opt_set(fsdev, "security_model",
qemu_opt_get(opts, "security_model"));
+ socket = qemu_opt_get(opts, "socket");
+ if (socket) {
+ qemu_opt_set(fsdev, "socket", socket);
+ }
sock_fd = qemu_opt_get(opts, "sock_fd");
if (sock_fd) {
qemu_opt_set(fsdev, "sock_fd", sock_fd);
--
1.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 06/13] hw/9pfs: Open and create files
2011-10-31 20:53 [Qemu-devel] [PATCH 00/13] Proxy FS driver for VirtFS M. Mohan Kumar
` (4 preceding siblings ...)
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
2011-10-31 20:53 ` [Qemu-devel] [PATCH 07/13] hw/9pfs: Create other filesystem objects M. Mohan Kumar
` (5 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
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
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 07/13] hw/9pfs: Create other filesystem objects
2011-10-31 20:53 [Qemu-devel] [PATCH 00/13] Proxy FS driver for VirtFS M. Mohan Kumar
` (5 preceding siblings ...)
2011-10-31 20:53 ` [Qemu-devel] [PATCH 06/13] hw/9pfs: Open and create files M. Mohan Kumar
@ 2011-10-31 20:53 ` 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
` (4 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
From: "M. Mohan Kumar" <mohan@in.ibm.com>
Add interfaces to create filesystem objects like directory,
device nodes, symbolic links, links for proxy filesytem driver
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
hw/9pfs/proxy.h | 4 ++
hw/9pfs/virtfs-proxy-helper.c | 63 +++++++++++++++++++++-
hw/9pfs/virtio-9p-proxy.c | 119 +++++++++++++++++++++++++++++++++++++----
3 files changed, 175 insertions(+), 11 deletions(-)
diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
index 69e7baa..5564eb5 100644
--- a/hw/9pfs/proxy.h
+++ b/hw/9pfs/proxy.h
@@ -17,6 +17,10 @@ typedef struct {
enum {
T_OPEN = 1,
T_CREATE,
+ T_MKNOD,
+ T_MKDIR,
+ T_SYMLINK,
+ T_LINK,
};
#endif
diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
index 73609e1..82aa267 100644
--- a/hw/9pfs/virtfs-proxy-helper.c
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -268,6 +268,48 @@ static int setfsugid(int uid, int gid)
}
/*
+ * create a other filesystem objects and send 0 on success
+ * return -errno on error
+ */
+static int do_create_others(int type, struct iovec *iovec)
+{
+ V9fsString oldpath, path;
+ int retval, mode, uid, gid, cur_uid, cur_gid;
+ dev_t rdev;
+ int offset;
+
+ cur_uid = geteuid();
+ cur_gid = getegid();
+
+ offset = v9fs_unmarshal(iovec, 1, 0, "dd", &uid, &gid);
+ if (setfsugid(uid, gid) < 0) {
+ return -EPERM;
+ }
+ switch (type) {
+ case T_MKNOD:
+ v9fs_unmarshal(iovec, 1, offset, "sdq", &path, &mode, &rdev);
+ retval = mknod(path.data, mode, rdev);
+ break;
+ case T_MKDIR:
+ v9fs_unmarshal(iovec, 1, offset, "sd", &path, &mode);
+ retval = mkdir(path.data, mode);
+ break;
+ case T_SYMLINK:
+ v9fs_unmarshal(iovec, 1, offset, "ss", &oldpath, &path);
+ retval = symlink(oldpath.data, path.data);
+ v9fs_string_free(&oldpath);
+ break;
+ }
+
+ if (retval < 0) {
+ retval = -errno;
+ }
+ v9fs_string_free(&path);
+ setfsugid(cur_uid, cur_gid);
+ return retval;
+}
+
+/*
* create a file and send fd on success
* return -errno on error
*/
@@ -325,6 +367,7 @@ static int process_requests(int sock)
int type, retval;
struct iovec iovec;
int valid_fd;
+ V9fsString oldpath, path;
iovec.iov_base = g_malloc(BUFF_SZ);
iovec.iov_len = BUFF_SZ;
@@ -344,6 +387,20 @@ static int process_requests(int sock)
valid_fd = 1;
}
break;
+ case T_MKNOD:
+ case T_MKDIR:
+ case T_SYMLINK:
+ retval = do_create_others(type, &iovec);
+ break;
+ case T_LINK:
+ v9fs_unmarshal(&iovec, 1, 0, "ss", &oldpath, &path);
+ retval = link(oldpath.data, path.data);
+ if (retval < 0) {
+ retval = -errno;
+ }
+ v9fs_string_free(&oldpath);
+ v9fs_string_free(&path);
+ break;
default:
goto error;
break;
@@ -353,7 +410,11 @@ static int process_requests(int sock)
switch (type) {
case T_OPEN:
case T_CREATE:
- sendfd(sock, retval, valid_fd);
+ case T_MKNOD:
+ case T_MKDIR:
+ case T_SYMLINK:
+ case T_LINK:
+ sendfd(sock, retval, valid_fd);
break;
default:
break;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index d686454..5f5eb35 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -97,9 +97,10 @@ static int v9fs_request(V9fsProxy *proxy, int type,
int retval;
ProxyHeader header;
va_list ap;
- V9fsString *path;
+ V9fsString *path, *oldpath;
int sock_error, flags, mode, uid, gid;
struct iovec *iovec = NULL;
+ dev_t rdev;
qemu_mutex_lock(&proxy->mutex);
@@ -131,6 +132,49 @@ static int v9fs_request(V9fsProxy *proxy, int type,
v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
header.size += sizeof(header);
break;
+ case T_MKNOD:
+ path = va_arg(ap, V9fsString *);
+ mode = va_arg(ap, int);
+ rdev = va_arg(ap, long int);
+ uid = va_arg(ap, int);
+ gid = va_arg(ap, int);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ddsdq",
+ uid, gid, path, mode, rdev);
+ header.type = T_MKNOD;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ case T_MKDIR:
+ path = va_arg(ap, V9fsString *);
+ mode = va_arg(ap, int);
+ uid = va_arg(ap, int);
+ gid = va_arg(ap, int);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ddsd",
+ uid, gid, path, mode);
+ header.type = T_MKDIR;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ case T_SYMLINK:
+ oldpath = va_arg(ap, V9fsString *);
+ path = va_arg(ap, V9fsString *);
+ uid = va_arg(ap, int);
+ gid = va_arg(ap, int);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ddss",
+ uid, gid, oldpath, path);
+ header.type = T_SYMLINK;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ case T_LINK:
+ oldpath = va_arg(ap, V9fsString *);
+ path = va_arg(ap, V9fsString *);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ss",
+ oldpath, path);
+ header.type = T_LINK;
+ 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;
@@ -149,6 +193,10 @@ static int v9fs_request(V9fsProxy *proxy, int type,
switch (type) {
case T_OPEN:
case T_CREATE:
+ case T_MKNOD:
+ case T_MKDIR:
+ case T_SYMLINK:
+ case T_LINK:
retval = v9fs_receivefd(proxy->sockfd, &sock_error);
if (sock_error) {
goto close_error;
@@ -294,15 +342,40 @@ static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
const char *name, FsCred *credp)
{
- errno = EOPNOTSUPP;
- return -1;
+ V9fsString fullname;
+ int retval;
+ v9fs_string_init(&fullname);
+ v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+
+ retval = v9fs_request(fs_ctx->private, T_MKNOD, NULL, "sdqdd",
+ &fullname, credp->fc_mode, credp->fc_rdev,
+ credp->fc_uid, credp->fc_gid);
+ v9fs_string_free(&fullname);
+ if (retval < 0) {
+ errno = -retval;
+ retval = -1;
+ }
+ return retval;
}
static int proxy_mkdir(FsContext *fs_ctx, V9fsPath *dir_path,
const char *name, FsCred *credp)
{
- errno = EOPNOTSUPP;
- return -1;
+ V9fsString fullname;
+ int retval;
+
+ v9fs_string_init(&fullname);
+ v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+
+ retval = v9fs_request(fs_ctx->private, T_MKDIR, NULL, "sddd", &fullname,
+ credp->fc_mode, credp->fc_uid, credp->fc_gid);
+ v9fs_string_free(&fullname);
+ if (retval < 0) {
+ errno = -retval;
+ retval = -1;
+ }
+ v9fs_string_free(&fullname);
+ return retval;
}
static int proxy_fstat(FsContext *fs_ctx,
@@ -332,19 +405,45 @@ static int proxy_open2(FsContext *fs_ctx, V9fsPath *dir_path, const char *name,
return fs->fd;
}
-
static int proxy_symlink(FsContext *fs_ctx, const char *oldpath,
V9fsPath *dir_path, const char *name, FsCred *credp)
{
- errno = EOPNOTSUPP;
- return -1;
+ V9fsString fullname, target;
+ int retval;
+
+ v9fs_string_init(&fullname);
+ v9fs_string_sprintf(&fullname, "%s/%s", dir_path->data, name);
+ v9fs_string_init(&target);
+ v9fs_string_sprintf(&target, "%s", oldpath);
+
+ retval = v9fs_request(fs_ctx->private, T_SYMLINK, NULL, "ssdd",
+ &target, &fullname, credp->fc_uid, credp->fc_gid);
+ v9fs_string_free(&fullname);
+ if (retval < 0) {
+ errno = -retval;
+ retval = -1;
+ }
+ return retval;
}
static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
V9fsPath *dirpath, const char *name)
{
- errno = EOPNOTSUPP;
- return -1;
+ int retval;
+ V9fsString newpath;
+
+ v9fs_string_init(&newpath);
+ v9fs_string_sprintf(&newpath, "%s/%s", dirpath->data, name);
+
+ retval = v9fs_request(ctx->private, T_LINK, NULL, "ss",
+ oldpath, &newpath);
+ v9fs_string_free(&newpath);
+ if (retval < 0) {
+ errno = -retval;
+ retval = -1;
+ }
+ v9fs_string_free(&newpath);
+ return retval;
}
static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
--
1.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 08/13] hw/9pfs: Add stat/readlink/statfs for proxy FS
2011-10-31 20:53 [Qemu-devel] [PATCH 00/13] Proxy FS driver for VirtFS M. Mohan Kumar
` (6 preceding siblings ...)
2011-10-31 20:53 ` [Qemu-devel] [PATCH 07/13] hw/9pfs: Create other filesystem objects M. Mohan Kumar
@ 2011-10-31 20:53 ` M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 09/13] hw/9pfs: File ownership and others M. Mohan Kumar
` (3 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
From: "M. Mohan Kumar" <mohan@in.ibm.com>
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
hw/9pfs/proxy.h | 3 ++
hw/9pfs/virtfs-proxy-helper.c | 81 ++++++++++++++++++++++++++++++++++++++++-
hw/9pfs/virtio-9p-proxy.c | 67 +++++++++++++++++++++++++++++++---
3 files changed, 144 insertions(+), 7 deletions(-)
diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
index 5564eb5..5a13b5f 100644
--- a/hw/9pfs/proxy.h
+++ b/hw/9pfs/proxy.h
@@ -21,6 +21,9 @@ enum {
T_MKDIR,
T_SYMLINK,
T_LINK,
+ T_LSTAT,
+ T_READLINK,
+ T_STATFS,
};
#endif
diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
index 82aa267..9fa4a30 100644
--- a/hw/9pfs/virtfs-proxy-helper.c
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -17,6 +17,7 @@
#include <stdarg.h>
#include "bswap.h"
#include <sys/socket.h>
+#include <sys/vfs.h>
#include "qemu-common.h"
#include "virtio-9p.h"
#include "hw/9pfs/proxy.h"
@@ -268,6 +269,59 @@ static int setfsugid(int uid, int gid)
}
/*
+ * send response in two parts
+ * 1) Size of the response
+ * 2) Response
+ * If there was a error send -errno only
+ */
+static int send_response(int sock, int size, char *response)
+{
+ int retval;
+ retval = socket_write(sock, &size, sizeof(size));
+ if (retval > 0 && size > 0) {
+ retval = socket_write(sock, response, size);
+ }
+ if (size > 0) {
+ g_free(response);
+ }
+ return retval;
+}
+
+static int do_stat(int type, struct iovec *iovec, char **response)
+{
+ V9fsString path;
+ int size = 0, retval = -1;
+
+ v9fs_unmarshal(iovec, 1, 0, "s", &path);
+
+ switch (type) {
+ case T_LSTAT:
+ size = sizeof(struct stat);
+ *response = g_malloc(size);
+ retval = lstat(path.data, (struct stat *)*response);
+ break;
+ case T_STATFS:
+ size = sizeof(struct statfs);
+ *response = g_malloc(size);
+ retval = statfs(path.data, (struct statfs *)*response);
+ break;
+ default:
+ retval = -EOPNOTSUPP;
+ goto error;
+ }
+
+ if (retval < 0) {
+ retval = -errno;
+ g_free(*response);
+ } else {
+ retval = size;
+ }
+error:
+ v9fs_string_free(&path);
+ return retval;
+}
+
+/*
* create a other filesystem objects and send 0 on success
* return -errno on error
*/
@@ -368,6 +422,8 @@ static int process_requests(int sock)
struct iovec iovec;
int valid_fd;
V9fsString oldpath, path;
+ char *response = NULL;
+ int size;
iovec.iov_base = g_malloc(BUFF_SZ);
iovec.iov_len = BUFF_SZ;
@@ -401,6 +457,22 @@ static int process_requests(int sock)
v9fs_string_free(&oldpath);
v9fs_string_free(&path);
break;
+ case T_LSTAT:
+ case T_STATFS:
+ retval = do_stat(type, &iovec, &response);
+ break;
+ case T_READLINK:
+ response = g_malloc(size);
+ v9fs_unmarshal(&iovec, 1, 0, "sd", &path, &size);
+ retval = readlink(path.data, response, size);
+ if (retval > 0) {
+ response[retval++] = '\0';
+ } else {
+ retval = -errno;
+ g_free(response);
+ }
+ v9fs_string_free(&path);
+ break;
default:
goto error;
break;
@@ -416,11 +488,18 @@ static int process_requests(int sock)
case T_LINK:
sendfd(sock, retval, valid_fd);
break;
+ case T_LSTAT:
+ case T_READLINK:
+ case T_STATFS:
+ if (send_response(sock, retval, response) < 0) {
+ do_perror("send_response");
+ goto error;
+ }
+ break;
default:
break;
}
}
- (void)socket_write;
error:
g_free(iovec.iov_base);
return -1;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 5f5eb35..1328e59 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -101,6 +101,7 @@ static int v9fs_request(V9fsProxy *proxy, int type,
int sock_error, flags, mode, uid, gid;
struct iovec *iovec = NULL;
dev_t rdev;
+ int msg_size, size;
qemu_mutex_lock(&proxy->mutex);
@@ -175,6 +176,29 @@ static int v9fs_request(V9fsProxy *proxy, int type,
v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
header.size += sizeof(header);
break;
+ case T_LSTAT:
+ path = va_arg(ap, V9fsString *);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "s", path);
+ header.type = T_LSTAT;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ case T_READLINK:
+ path = va_arg(ap, V9fsString *);
+ size = va_arg(ap, int);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sd",
+ path, size);
+ header.type = T_READLINK;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ case T_STATFS:
+ path = va_arg(ap, V9fsString *);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "s", path);
+ header.type = T_STATFS;
+ 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;
@@ -202,6 +226,23 @@ static int v9fs_request(V9fsProxy *proxy, int type,
goto close_error;
}
break;
+ case T_LSTAT:
+ case T_READLINK:
+ case T_STATFS:
+ retval = read(proxy->sockfd, &msg_size, sizeof(msg_size));
+ if (retval != sizeof(msg_size)) {
+ goto close_error;
+ }
+ if (msg_size < 0) {
+ qemu_mutex_unlock(&proxy->mutex);
+ return msg_size;
+ }
+ retval = read(proxy->sockfd, response, msg_size);
+ if (retval != msg_size) {
+ goto close_error;
+ }
+ retval = 0; /* success */
+ break;
}
qemu_mutex_unlock(&proxy->mutex);
return retval;
@@ -215,15 +256,25 @@ error:
static int proxy_lstat(FsContext *fs_ctx, V9fsPath *fs_path, struct stat *stbuf)
{
- errno = EOPNOTSUPP;
- return -1;
+ int retval;
+ retval = v9fs_request(fs_ctx->private, T_LSTAT, stbuf, "s", fs_path);
+ if (retval < 0) {
+ errno = -retval;
+ }
+ return retval;
}
static ssize_t proxy_readlink(FsContext *fs_ctx, V9fsPath *fs_path,
char *buf, size_t bufsz)
{
- errno = EOPNOTSUPP;
- return -1;
+ int retval;
+ retval = v9fs_request(fs_ctx->private, T_READLINK, buf, "sd",
+ fs_path, bufsz);
+ if (retval < 0) {
+ errno = -retval;
+ return -1;
+ }
+ return strlen(buf);
}
static int proxy_close(FsContext *ctx, V9fsFidOpenState *fs)
@@ -489,8 +540,12 @@ static int proxy_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)
static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
{
- errno = EOPNOTSUPP;
- return -1;
+ int retval;
+ retval = v9fs_request(s->private, T_STATFS, stbuf, "s", fs_path);
+ if (retval < 0) {
+ errno = -retval;
+ }
+ return retval;
}
static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
--
1.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 09/13] hw/9pfs: File ownership and others
2011-10-31 20:53 [Qemu-devel] [PATCH 00/13] Proxy FS driver for VirtFS M. Mohan Kumar
` (7 preceding siblings ...)
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 ` M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 10/13] hw/9pfs: xattr interfaces in proxy filesystem driver M. Mohan Kumar
` (2 subsequent siblings)
11 siblings, 0 replies; 13+ messages in thread
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
From: "M. Mohan Kumar" <mohan@in.ibm.com>
Add file ownership interfaces like chmod/chown, utime update, rename,
remove and truncating files for proxy FS
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
hw/9pfs/proxy.h | 6 ++
hw/9pfs/virtfs-proxy-helper.c | 61 ++++++++++++++++++-
hw/9pfs/virtio-9p-proxy.c | 134 +++++++++++++++++++++++++++++++++++++----
3 files changed, 188 insertions(+), 13 deletions(-)
diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
index 5a13b5f..557a8f4 100644
--- a/hw/9pfs/proxy.h
+++ b/hw/9pfs/proxy.h
@@ -24,6 +24,12 @@ enum {
T_LSTAT,
T_READLINK,
T_STATFS,
+ T_CHMOD,
+ T_CHOWN,
+ T_TRUNCATE,
+ T_UTIME,
+ T_RENAME,
+ T_REMOVE,
};
#endif
diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
index 9fa4a30..845e3c6 100644
--- a/hw/9pfs/virtfs-proxy-helper.c
+++ b/hw/9pfs/virtfs-proxy-helper.c
@@ -423,7 +423,9 @@ static int process_requests(int sock)
int valid_fd;
V9fsString oldpath, path;
char *response = NULL;
- int size;
+ int size, mode, uid, gid;
+ struct timespec spec[2];
+ uint64_t offset;
iovec.iov_base = g_malloc(BUFF_SZ);
iovec.iov_len = BUFF_SZ;
@@ -473,6 +475,57 @@ static int process_requests(int sock)
}
v9fs_string_free(&path);
break;
+ case T_CHMOD:
+ v9fs_unmarshal(&iovec, 1, 0, "sd", &path, &mode);
+ retval = chmod(path.data, mode);
+ if (retval < 0) {
+ retval = -errno;
+ }
+ v9fs_string_free(&path);
+ break;
+ case T_CHOWN:
+ v9fs_unmarshal(&iovec, 1, 0, "sdd", &path, &uid, &gid);
+ retval = lchown(path.data, uid, gid);
+ if (retval < 0) {
+ retval = -errno;
+ }
+ v9fs_string_free(&path);
+ break;
+ case T_TRUNCATE:
+ v9fs_unmarshal(&iovec, 1, 0, "sq", &path, &offset);
+ retval = truncate(path.data, offset);
+ if (retval < 0) {
+ retval = -errno;
+ }
+ v9fs_string_free(&path);
+ break;
+ case T_UTIME:
+ v9fs_unmarshal(&iovec, 1, 0, "sqqqq", &path,
+ &spec[0].tv_sec, &spec[0].tv_nsec,
+ &spec[1].tv_sec, &spec[1].tv_nsec);
+ retval = utimensat(AT_FDCWD, path.data, spec, AT_SYMLINK_NOFOLLOW);
+ if (retval < 0) {
+ retval = -errno;
+ }
+ v9fs_string_free(&path);
+ break;
+ case T_RENAME:
+ v9fs_unmarshal(&iovec, 1, 0, "ss", &oldpath, &path);
+ retval = rename(oldpath.data, path.data);
+ if (retval < 0) {
+ retval = -errno;
+ }
+ v9fs_string_free(&oldpath);
+ v9fs_string_free(&path);
+ break;
+ case T_REMOVE:
+ v9fs_unmarshal(&iovec, 1, 0, "s", &path);
+ retval = remove(path.data);
+ if (retval < 0) {
+ retval = -errno;
+ }
+ v9fs_string_free(&path);
+ break;
default:
goto error;
break;
@@ -486,6 +539,12 @@ static int process_requests(int sock)
case T_MKDIR:
case T_SYMLINK:
case T_LINK:
+ case T_CHMOD:
+ case T_CHOWN:
+ case T_TRUNCATE:
+ case T_UTIME:
+ case T_RENAME:
+ case T_REMOVE:
sendfd(sock, retval, valid_fd);
break;
case T_LSTAT:
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 1328e59..47419dd 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -102,6 +102,8 @@ static int v9fs_request(V9fsProxy *proxy, int type,
struct iovec *iovec = NULL;
dev_t rdev;
int msg_size, size;
+ struct timespec spec[2];
+ uint64_t offset;
qemu_mutex_lock(&proxy->mutex);
@@ -199,6 +201,63 @@ static int v9fs_request(V9fsProxy *proxy, int type,
v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
header.size += sizeof(header);
break;
+ case T_CHMOD:
+ path = va_arg(ap, V9fsString *);
+ mode = va_arg(ap, int);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sd",
+ path, mode);
+ header.type = T_CHMOD;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ case T_CHOWN:
+ path = va_arg(ap, V9fsString *);
+ uid = va_arg(ap, int);
+ gid = va_arg(ap, int);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sdd",
+ path, uid, gid);
+ header.type = T_CHOWN;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ case T_TRUNCATE:
+ path = va_arg(ap, V9fsString *);
+ offset = va_arg(ap, uint64_t);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sq",
+ path, offset);
+ header.type = T_TRUNCATE;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ case T_UTIME:
+ path = va_arg(ap, V9fsString *);
+ spec[0].tv_sec = va_arg(ap, long);
+ spec[0].tv_nsec = va_arg(ap, long);
+ spec[1].tv_sec = va_arg(ap, long);
+ spec[1].tv_nsec = va_arg(ap, long);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sqqqq",
+ path, spec[0].tv_sec, spec[1].tv_nsec,
+ spec[1].tv_sec, spec[1].tv_nsec);
+ header.type = T_UTIME;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ case T_RENAME:
+ oldpath = va_arg(ap, V9fsString *);
+ path = va_arg(ap, V9fsString *);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ss",
+ oldpath, path);
+ header.type = T_RENAME;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ case T_REMOVE:
+ path = va_arg(ap, V9fsString *);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "s", path);
+ header.type = T_REMOVE;
+ 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;
@@ -221,6 +280,12 @@ static int v9fs_request(V9fsProxy *proxy, int type,
case T_MKDIR:
case T_SYMLINK:
case T_LINK:
+ case T_CHMOD:
+ case T_CHOWN:
+ case T_RENAME:
+ case T_TRUNCATE:
+ case T_UTIME:
+ case T_REMOVE:
retval = v9fs_receivefd(proxy->sockfd, &sock_error);
if (sock_error) {
goto close_error;
@@ -386,8 +451,13 @@ static ssize_t proxy_pwritev(FsContext *ctx, V9fsFidOpenState *fs,
static int proxy_chmod(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
{
- errno = EOPNOTSUPP;
- return -1;
+ int retval;
+ retval = v9fs_request(fs_ctx->private, T_CHMOD, NULL, "sd",
+ fs_path, credp->fc_mode);
+ if (retval < 0) {
+ errno = -retval;
+ }
+ return retval;
}
static int proxy_mknod(FsContext *fs_ctx, V9fsPath *dir_path,
@@ -499,34 +569,74 @@ static int proxy_link(FsContext *ctx, V9fsPath *oldpath,
static int proxy_truncate(FsContext *ctx, V9fsPath *fs_path, off_t size)
{
- errno = EOPNOTSUPP;
- return -1;
+ int retval;
+
+ retval = v9fs_request(ctx->private, T_TRUNCATE, NULL, "sq", fs_path, size);
+ if (retval < 0) {
+ errno = -retval;
+ return -1;
+ }
+ return 0;
}
static int proxy_rename(FsContext *ctx, const char *oldpath,
const char *newpath)
{
- errno = EOPNOTSUPP;
- return -1;
+ int retval;
+ V9fsString oldname, newname;
+
+ v9fs_string_init(&oldname);
+ v9fs_string_init(&newname);
+
+ v9fs_string_sprintf(&oldname, "%s", oldpath);
+ v9fs_string_sprintf(&newname, "%s", newpath);
+ retval = v9fs_request(ctx->private, T_RENAME, NULL, "ss",
+ &oldname, &newname);
+ if (retval < 0) {
+ errno = -retval;
+ }
+ v9fs_string_free(&oldname);
+ v9fs_string_free(&newname);
+ return retval;
}
static int proxy_chown(FsContext *fs_ctx, V9fsPath *fs_path, FsCred *credp)
{
- errno = EOPNOTSUPP;
- return -1;
+ int retval;
+ retval = v9fs_request(fs_ctx->private, T_CHOWN, NULL, "sdd",
+ fs_path, credp->fc_uid, credp->fc_gid);
+ if (retval < 0) {
+ errno = -retval;
+ }
+ return retval;
}
static int proxy_utimensat(FsContext *s, V9fsPath *fs_path,
const struct timespec *buf)
{
- errno = EOPNOTSUPP;
- return -1;
+ int retval;
+ retval = v9fs_request(s->private, T_UTIME, NULL, "sqqqq",
+ fs_path,
+ buf[0].tv_sec, buf[0].tv_nsec,
+ buf[1].tv_sec, buf[1].tv_nsec);
+ if (retval < 0) {
+ errno = -retval;
+ }
+ return retval;
}
static int proxy_remove(FsContext *ctx, const char *path)
{
- errno = EOPNOTSUPP;
- return -1;
+ int retval;
+ V9fsString name;
+ v9fs_string_init(&name);
+ v9fs_string_sprintf(&name, "%s", path);
+ retval = v9fs_request(ctx->private, T_REMOVE, NULL, "s", &name);
+ if (retval < 0) {
+ errno = -retval;
+ }
+ v9fs_string_free(&name);
+ return retval;
}
static int proxy_fsync(FsContext *ctx, V9fsFidOpenState *fs, int datasync)
--
1.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 10/13] hw/9pfs: xattr interfaces in proxy filesystem driver
2011-10-31 20:53 [Qemu-devel] [PATCH 00/13] Proxy FS driver for VirtFS M. Mohan Kumar
` (8 preceding siblings ...)
2011-10-31 20:53 ` [Qemu-devel] [PATCH 09/13] hw/9pfs: File ownership and others M. Mohan Kumar
@ 2011-10-31 20:53 ` 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
11 siblings, 0 replies; 13+ messages in thread
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
From: "M. Mohan Kumar" <mohan@in.ibm.com>
Add xattr support for proxy FS
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
hw/9pfs/proxy.h | 4 ++
hw/9pfs/virtfs-proxy-helper.c | 60 ++++++++++++++++++++
hw/9pfs/virtio-9p-proxy.c | 121 ++++++++++++++++++++++++++++++++++++++---
3 files changed, 176 insertions(+), 9 deletions(-)
diff --git a/hw/9pfs/proxy.h b/hw/9pfs/proxy.h
index 557a8f4..fdfa651 100644
--- a/hw/9pfs/proxy.h
+++ b/hw/9pfs/proxy.h
@@ -30,6 +30,10 @@ enum {
T_UTIME,
T_RENAME,
T_REMOVE,
+ T_LGETXATTR,
+ T_LLISTXATTR,
+ T_LSETXATTR,
+ T_LREMOVEXATTR,
};
#endif
diff --git a/hw/9pfs/virtfs-proxy-helper.c b/hw/9pfs/virtfs-proxy-helper.c
index 845e3c6..78669d0 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 <sys/vfs.h>
+#include <attr/xattr.h>
#include "qemu-common.h"
#include "virtio-9p.h"
#include "hw/9pfs/proxy.h"
@@ -426,6 +427,8 @@ static int process_requests(int sock)
int size, mode, uid, gid;
struct timespec spec[2];
uint64_t offset;
+ V9fsString name, value;
+ int flags;
iovec.iov_base = g_malloc(BUFF_SZ);
iovec.iov_len = BUFF_SZ;
@@ -526,6 +529,49 @@ static int process_requests(int sock)
}
v9fs_string_free(&path);
break;
+ case T_LGETXATTR:
+ if (size) {
+ response = g_malloc(size);
+ }
+ v9fs_unmarshal(&iovec, 1, 0, "ssd", &path, &name, &size);
+ retval = lgetxattr(path.data, name.data, response, size);
+ if (retval < 0) {
+ retval = -errno;
+ }
+ v9fs_string_free(&path);
+ v9fs_string_free(&name);
+ break;
+ case T_LLISTXATTR:
+ if (size) {
+ response = g_malloc(size);
+ }
+ v9fs_unmarshal(&iovec, 1, 0, "sd", &path, &size);
+ retval = llistxattr(path.data, response, size);
+ if (retval < 0) {
+ retval = -errno;
+ }
+ v9fs_string_free(&path);
+ break;
+ case T_LSETXATTR:
+ v9fs_unmarshal(&iovec, 1, 0, "sssdd", &path, &name, &value, &size,
+ &flags);
+ retval = lsetxattr(path.data, name.data, value.data, size, flags);
+ if (retval < 0) {
+ retval = -errno;
+ }
+ v9fs_string_free(&path);
+ v9fs_string_free(&name);
+ v9fs_string_free(&value);
+ break;
+ case T_LREMOVEXATTR:
+ v9fs_unmarshal(&iovec, 1, 0, "ss", &path, &name);
+ retval = lremovexattr(path.data, name.data);
+ if (retval < 0) {
+ retval = -errno;
+ }
+ v9fs_string_free(&path);
+ v9fs_string_free(&name);
+ break;
default:
goto error;
break;
@@ -545,6 +591,8 @@ static int process_requests(int sock)
case T_UTIME:
case T_RENAME:
case T_REMOVE:
+ case T_LSETXATTR:
+ case T_LREMOVEXATTR:
sendfd(sock, retval, valid_fd);
break;
case T_LSTAT:
@@ -555,6 +603,18 @@ static int process_requests(int sock)
goto error;
}
break;
+ case T_LGETXATTR:
+ case T_LLISTXATTR:
+ /* send only size of xattr attribute as per request */
+ if (!size) {
+ socket_write(sock, &retval, sizeof(retval));
+ } else { /* send value of xattr 'name' */
+ if (send_response(sock, retval, response) < 0) {
+ do_perror("send_response");
+ goto error;
+ }
+ }
+ break;
default:
break;
}
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 47419dd..143a784 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -101,9 +101,10 @@ static int v9fs_request(V9fsProxy *proxy, int type,
int sock_error, flags, mode, uid, gid;
struct iovec *iovec = NULL;
dev_t rdev;
- int msg_size, size;
+ int msg_size, size = 0;
struct timespec spec[2];
uint64_t offset;
+ V9fsString *name, *value;
qemu_mutex_lock(&proxy->mutex);
@@ -258,6 +259,46 @@ static int v9fs_request(V9fsProxy *proxy, int type,
v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
header.size += sizeof(header);
break;
+ case T_LGETXATTR:
+ path = va_arg(ap, V9fsString *);
+ name = va_arg(ap, V9fsString *);
+ size = va_arg(ap, int);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ssd", path,
+ name, size);
+ header.type = T_LGETXATTR;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ case T_LLISTXATTR:
+ path = va_arg(ap, V9fsString *);
+ size = va_arg(ap, int);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sd",
+ path, size);
+ header.type = T_LLISTXATTR;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ case T_LSETXATTR:
+ path = va_arg(ap, V9fsString *);
+ name = va_arg(ap, V9fsString *);
+ value = va_arg(ap, V9fsString *);
+ size = va_arg(ap, int);
+ flags = va_arg(ap, int);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "sssdd",
+ path, name, value, size, flags);
+ header.type = T_LSETXATTR;
+ v9fs_marshal(iovec, 1, 0, "dd", header.type, header.size);
+ header.size += sizeof(header);
+ break;
+ case T_LREMOVEXATTR:
+ path = va_arg(ap, V9fsString *);
+ name = va_arg(ap, V9fsString *);
+ header.size = v9fs_marshal(iovec, 1, sizeof(ProxyHeader), "ss",
+ path, name);
+ header.type = T_LREMOVEXATTR;
+ 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;
@@ -286,6 +327,8 @@ static int v9fs_request(V9fsProxy *proxy, int type,
case T_TRUNCATE:
case T_UTIME:
case T_REMOVE:
+ case T_LSETXATTR:
+ case T_LREMOVEXATTR:
retval = v9fs_receivefd(proxy->sockfd, &sock_error);
if (sock_error) {
goto close_error;
@@ -308,6 +351,24 @@ static int v9fs_request(V9fsProxy *proxy, int type,
}
retval = 0; /* success */
break;
+ case T_LGETXATTR:
+ case T_LLISTXATTR:
+ if (!size) {
+ if (read(proxy->sockfd, &retval, sizeof(int)) < 0) {
+ retval = -errno;
+ }
+ } else {
+ retval = read(proxy->sockfd, &msg_size, sizeof(msg_size));
+ if (msg_size < 0) {
+ qemu_mutex_unlock(&proxy->mutex);
+ return msg_size;
+ }
+ retval = read(proxy->sockfd, response, msg_size);
+ if (retval != msg_size) {
+ goto close_error;
+ }
+ }
+ break;
}
qemu_mutex_unlock(&proxy->mutex);
return retval;
@@ -661,29 +722,71 @@ static int proxy_statfs(FsContext *s, V9fsPath *fs_path, struct statfs *stbuf)
static ssize_t proxy_lgetxattr(FsContext *ctx, V9fsPath *fs_path,
const char *name, void *value, size_t size)
{
- errno = EOPNOTSUPP;
- return -1;
+ int retval;
+ V9fsString xname;
+
+ v9fs_string_init(&xname);
+ v9fs_string_sprintf(&xname, "%s", name);
+ retval = v9fs_request(ctx->private, T_LGETXATTR, value, "ssd",
+ fs_path, &xname, size);
+ if (retval < 0) {
+ errno = -retval;
+ }
+ v9fs_string_free(&xname);
+ return retval;
}
static ssize_t proxy_llistxattr(FsContext *ctx, V9fsPath *fs_path,
void *value, size_t size)
{
- errno = EOPNOTSUPP;
- return -1;
+ int retval;
+ retval = v9fs_request(ctx->private, T_LLISTXATTR, value, "sd",
+ fs_path, size);
+ if (retval < 0) {
+ errno = -retval;
+ }
+ return retval;
}
static int proxy_lsetxattr(FsContext *ctx, V9fsPath *fs_path, const char *name,
void *value, size_t size, int flags)
{
- errno = EOPNOTSUPP;
- return -1;
+ int retval;
+ V9fsString xname, xvalue;
+
+ v9fs_string_init(&xname);
+ v9fs_string_sprintf(&xname, "%s", name);
+
+ v9fs_string_init(&xvalue);
+ xvalue.size = size;
+ xvalue.data = g_malloc(size);
+ memcpy(xvalue.data, value, size);
+
+ retval = v9fs_request(ctx->private, T_LSETXATTR, value, "sssdd",
+ fs_path, xname, xvalue, size, flags);
+ if (retval < 0) {
+ errno = -retval;
+ }
+ v9fs_string_free(&xname);
+ v9fs_string_free(&xvalue);
+ return retval;
}
static int proxy_lremovexattr(FsContext *ctx, V9fsPath *fs_path,
const char *name)
{
- errno = EOPNOTSUPP;
- return -1;
+ int retval;
+ V9fsString xname;
+
+ v9fs_string_init(&xname);
+ v9fs_string_sprintf(&xname, "%s", name);
+ retval = v9fs_request(ctx->private, T_LREMOVEXATTR, NULL, "ss",
+ fs_path, &xname);
+ if (retval < 0) {
+ errno = -retval;
+ }
+ v9fs_string_free(&xname);
+ return retval;
}
static int proxy_name_to_path(FsContext *ctx, V9fsPath *dir_path,
--
1.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 12/13] hw/9pfs: Documentation changes related to proxy fs
2011-10-31 20:53 [Qemu-devel] [PATCH 00/13] Proxy FS driver for VirtFS M. Mohan Kumar
` (9 preceding siblings ...)
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 ` M. Mohan Kumar
2011-10-31 20:53 ` [Qemu-devel] [PATCH 13/13] hw/9pfs: man page for proxy helper M. Mohan Kumar
11 siblings, 0 replies; 13+ messages in thread
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
From: "M. Mohan Kumar" <mohan@in.ibm.com>
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
qemu-options.hx | 30 ++++++++++++++++++++++--------
1 files changed, 22 insertions(+), 8 deletions(-)
diff --git a/qemu-options.hx b/qemu-options.hx
index 8df6165..eef98c5 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -527,19 +527,19 @@ DEFHEADING()
DEFHEADING(File system options:)
DEF("fsdev", HAS_ARG, QEMU_OPTION_fsdev,
- "-fsdev fsdriver,id=id,path=path,[security_model={mapped|passthrough|none}]\n"
- " [,writeout=immediate][,readonly]\n",
+ "-fsdev fsdriver,id=id[,path=path,][security_model={mapped|passthrough|none}]\n"
+ " [,writeout=immediate][,readonly][,socket=socket|sock_fd=sock_fd]\n",
QEMU_ARCH_ALL)
STEXI
-@item -fsdev @var{fsdriver},id=@var{id},path=@var{path},[security_model=@var{security_model}][,writeout=@var{writeout}][,readonly]
+@item -fsdev @var{fsdriver},id=@var{id},path=@var{path},[security_model=@var{security_model}][,writeout=@var{writeout}][,readonly][,socket=@var{socket}|sock_fd=@var{sock_fd}]
@findex -fsdev
Define a new file system device. Valid options are:
@table @option
@item @var{fsdriver}
This option specifies the fs driver backend to use.
-Currently "local" and "handle" file system drivers are supported.
+Currently "local", "handle" and "proxy" file system drivers are supported.
@item id=@var{id}
Specifies identifier for this device
@item path=@var{path}
@@ -556,7 +556,7 @@ file attributes. Directories exported by this security model cannot
interact with other unix tools. "none" security model is same as
passthrough except the sever won't report failures if it fails to
set file attributes like ownership. Security model is mandatory
-only for local fsdriver. Other fsdrivers (like handle) don't take
+only for local fsdriver. Other fsdrivers (like handle, proxy) don't take
security model as a parameter.
@item writeout=@var{writeout}
This is an optional argument. The only supported value is "immediate".
@@ -566,6 +566,13 @@ reported as written by the storage subsystem.
@item readonly
Enables exporting 9p share as a readonly mount for guests. By default
read-write access is given.
+@item socket=@var{socket}
+Enables proxy filesystem driver to use passed socket file for communicating
+with virtfs-proxy-helper
+@item sock_fd=@var{sock_fd}
+Enables proxy filesystem driver to use passed socket descriptor for
+communicating with virtfs-proxy-helper. Usually a helper like libvirt
+will create socketpair and pass one of the fds as sock_fd
@end table
-fsdev option is used along with -device driver "virtio-9p-pci".
@@ -591,14 +598,14 @@ DEF("virtfs", HAS_ARG, QEMU_OPTION_virtfs,
STEXI
-@item -virtfs @var{fsdriver},path=@var{path},mount_tag=@var{mount_tag},security_model=@var{security_model}[,writeout=@var{writeout}][,readonly]
+@item -virtfs @var{fsdriver}[,path=@var{path}],mount_tag=@var{mount_tag}[,security_model=@var{security_model}][,writeout=@var{writeout}][,readonly][,socket=@var{socket}|sock_fd=@var{sock_fd}]
@findex -virtfs
The general form of a Virtual File system pass-through options are:
@table @option
@item @var{fsdriver}
This option specifies the fs driver backend to use.
-Currently "local" and "handle" file system drivers are supported.
+Currently "local", "handle" and "proxy" file system drivers are supported.
@item id=@var{id}
Specifies identifier for this device
@item path=@var{path}
@@ -615,7 +622,7 @@ file attributes. Directories exported by this security model cannot
interact with other unix tools. "none" security model is same as
passthrough except the sever won't report failures if it fails to
set file attributes like ownership. Security model is mandatory only
-for local fsdriver. Other fsdrivers (like handle) don't take security
+for local fsdriver. Other fsdrivers (like handle, proxy) don't take security
model as a parameter.
@item writeout=@var{writeout}
This is an optional argument. The only supported value is "immediate".
@@ -625,6 +632,13 @@ reported as written by the storage subsystem.
@item readonly
Enables exporting 9p share as a readonly mount for guests. By default
read-write access is given.
+@item socket=@var{socket}
+Enables proxy filesystem driver to use passed socket file for
+communicating with virtfs-proxy-helper. Usually a helper like libvirt
+will create socketpair and pass one of the fds as sock_fd
+@item sock_fd
+Enables proxy filesystem driver to use passed 'sock_fd' as the socket
+descriptor for interfacing with virtfs-proxy-helper
@end table
ETEXI
--
1.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [Qemu-devel] [PATCH 13/13] hw/9pfs: man page for proxy helper
2011-10-31 20:53 [Qemu-devel] [PATCH 00/13] Proxy FS driver for VirtFS M. Mohan Kumar
` (10 preceding siblings ...)
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 ` M. Mohan Kumar
11 siblings, 0 replies; 13+ messages in thread
From: M. Mohan Kumar @ 2011-10-31 20:53 UTC (permalink / raw)
To: qemu-devel, aneesh.kumar; +Cc: M. Mohan Kumar
From: "M. Mohan Kumar" <mohan@in.ibm.com>
Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
---
Makefile | 12 ++++++-
hw/9pfs/virtfs-proxy-helper.texi | 63 ++++++++++++++++++++++++++++++++++++++
2 files changed, 74 insertions(+), 1 deletions(-)
create mode 100644 hw/9pfs/virtfs-proxy-helper.texi
diff --git a/Makefile b/Makefile
index d13b167..cff1170 100644
--- a/Makefile
+++ b/Makefile
@@ -37,6 +37,7 @@ LIBS+=-lz $(LIBS_TOOLS)
ifdef BUILD_DOCS
DOCS=qemu-doc.html qemu-tech.html qemu.1 qemu-img.1 qemu-nbd.8 QMP/qmp-commands.txt
+DOCS+=hw/9pfs/virtfs-proxy-helper.1
else
DOCS=
endif
@@ -283,7 +284,10 @@ ifdef CONFIG_POSIX
$(INSTALL_DIR) "$(DESTDIR)$(mandir)/man8"
$(INSTALL_DATA) qemu-nbd.8 "$(DESTDIR)$(mandir)/man8"
endif
-
+ifdef CONFIG_VIRTFS
+ $(INSTALL_DIR) "$(DESTDIR)$(mandir)/man1"
+ $(INSTALL_DATA) hw/9pfs/virtfs-proxy-helper.1 "$(DESTDIR)$(mandir)/man1"
+endif
install-sysconfig:
$(INSTALL_DIR) "$(DESTDIR)$(sysconfdir)/qemu"
$(INSTALL_DATA) $(SRC_PATH)/sysconfigs/target/target-x86_64.conf "$(DESTDIR)$(sysconfdir)/qemu"
@@ -361,6 +365,12 @@ qemu-img.1: qemu-img.texi qemu-img-cmds.texi
pod2man --section=1 --center=" " --release=" " qemu-img.pod > $@, \
" GEN $@")
+hw/9pfs/virtfs-proxy-helper.1: hw/9pfs/virtfs-proxy-helper.texi
+ $(call quiet-command, \
+ perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< hw/9pfs/virtfs-proxy-helper.pod && \
+ pod2man --section=1 --center=" " --release=" " hw/9pfs/virtfs-proxy-helper.pod > $@, \
+ " GEN $@")
+
qemu-nbd.8: qemu-nbd.texi
$(call quiet-command, \
perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $< qemu-nbd.pod && \
diff --git a/hw/9pfs/virtfs-proxy-helper.texi b/hw/9pfs/virtfs-proxy-helper.texi
new file mode 100644
index 0000000..faa0434
--- /dev/null
+++ b/hw/9pfs/virtfs-proxy-helper.texi
@@ -0,0 +1,63 @@
+@example
+@c man begin SYNOPSIS
+usage: virtfs-proxy-helper options
+@c man end
+@end example
+
+@c man begin DESCRIPTION
+@table @description
+Pass-through security model in QEMU 9p server needs root privilege to do
+few file operations (like chown, chmod to any mode/uid:gid). There are two
+issues in pass-through security model
+
+1) TOCTTOU vulnerability: Following symbolic links in the server could
+provide access to files beyond 9p export path.
+
+2) Running QEMU with root privilege could be a security issue.
+
+To overcome above issues, following approach is used: A new filesytem
+type 'proxy' is introduced. Proxy FS uses chroot + socket combination
+for securing the vulnerability known with following symbolic links.
+Intention of adding a new filesystem type is to allow qemu to run
+in non-root mode, but doing privileged operations using socket IO.
+
+Proxy helper(a stand alone binary part of qemu) is invoked with
+root privileges. Proxy helper chroots into 9p export path and creates
+a socket pair or a named socket based on the command line parameter.
+Qemu and proxy helper communicate using this socket. QEMU proxy fs
+driver sends filesystem request to proxy helper and receives the
+response from it.
+
+Proxy helper is designed so that it can drop the root privilege with
+retaining capbilities needed for doing filesystem operations only.
+
+@end table
+@c man end
+
+@c man begin OPTIONS
+The following options are supported:
+@table @option
+@item -h
+@findex -h
+Display help and exit
+@item -p|--path path
+Path to export for proxy filesystem driver
+@item -f|--fd socket-id
+Use given file descriptor as socket descriptor for communicating with
+qemu proxy fs drier. Usually a helper like libvirt will create
+socketpair and pass one of the fds as parameter to -f|--fd
+@item -s|--socket socket-file
+Creates named socket file for communicating with qemu proxy fs driver
+@item -u|--uid uid -g|--gid gid
+uid:gid combination to give access to named socket file
+@item -n|--nodaemon
+Run as a normal program. By default program will run in daemon mode
+@end table
+@c man end
+
+@setfilename virtfs-proxy-helper
+@settitle QEMU 9p virtfs proxy filesystem helper
+
+@c man begin AUTHOR
+M. Mohan Kumar
+@c man end
--
1.7.6
^ permalink raw reply related [flat|nested] 13+ messages in thread
end of thread, other threads:[~2011-10-31 20:54 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [Qemu-devel] [PATCH 06/13] hw/9pfs: Open and create files M. Mohan Kumar
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
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).