[Qemu-devel] [PATCH 1/1] block: Dont ignore previously set bdrv_flags

2013-08-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

bdrv_flags is set by bdrv_parse_discard_flags(), but later it is reset
to zero.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 blockdev.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/blockdev.c b/blockdev.c
index e174b7d..bc7016a 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -454,7 +454,6 @@ static DriveInfo *blockdev_init(QemuOpts *all_opts,
 }
 }
 
-bdrv_flags = 0;
 if (qemu_opt_get_bool(opts, cache.writeback, true)) {
 bdrv_flags |= BDRV_O_CACHE_WB;
 }
-- 
1.7.11.7




Re: [Qemu-devel] [PATCH] hw/9pfs: Fix potential memory leak and avoid reuse of freed memory

2013-07-04 Thread M. Mohan Kumar
Stefan Weil s...@weilnetz.de writes:

 The leak was reported by cppcheck.

 Function proxy_init also calls g_free for ctx-fs_root.
 Avoid reuse of this memory by setting ctx-fs_root to NULL.

 Signed-off-by: Stefan Weil s...@weilnetz.de
Reviewed-by: M. Mohan Kumar mo...@in.ibm.com
 ---

 Hi,

 I'm not sure whether ctx-fs_root should also be freed in the error case.
 Please feel free to modify my patch if needed.

 Regards
 Stefan Weil

  hw/9pfs/virtio-9p-proxy.c |2 ++
  1 file changed, 2 insertions(+)

 diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
 index 8ba2959..5f44bb7 100644
 --- a/hw/9pfs/virtio-9p-proxy.c
 +++ b/hw/9pfs/virtio-9p-proxy.c
 @@ -1153,10 +1153,12 @@ static int proxy_init(FsContext *ctx)
  sock_id = atoi(ctx-fs_root);
  if (sock_id  0) {
  fprintf(stderr, socket descriptor not initialized\n);
 +g_free(proxy);
  return -1;
  }
  }
  g_free(ctx-fs_root);
 +ctx-fs_root = NULL;

  proxy-in_iovec.iov_base  = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
  proxy-in_iovec.iov_len   = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
 -- 
 1.7.10.4




[Qemu-devel] [PATCH 1/1] hw/9pfs: Fix memory leak in error path

2013-07-04 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Fix few more memory leaks in virtio-9p-device.c detected using valgrind.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 hw/9pfs/virtio-9p-device.c | 26 +-
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index dc6f4e4..35e2af4 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -68,14 +68,14 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
 fprintf(stderr, Virtio-9p device couldn't find fsdev with the 
 id = %s\n,
 s-fsconf.fsdev_id ? s-fsconf.fsdev_id : NULL);
-return -1;
+goto out;
 }
 
 if (!s-fsconf.tag) {
 /* we haven't specified a mount_tag */
 fprintf(stderr, fsdev with id %s needs mount_tag arguments\n,
 s-fsconf.fsdev_id);
-return -1;
+goto out;
 }
 
 s-ctx.export_flags = fse-export_flags;
@@ -85,10 +85,10 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
 if (len  MAX_TAG_LEN - 1) {
 fprintf(stderr, mount tag '%s' (%d bytes) is longer than 
 maximum (%d bytes), s-fsconf.tag, len, MAX_TAG_LEN - 1);
-return -1;
+goto out;
 }
 
-s-tag = strdup(s-fsconf.tag);
+s-tag = g_strdup(s-fsconf.tag);
 s-ctx.uid = -1;
 
 s-ops = fse-ops;
@@ -99,11 +99,11 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
 if (s-ops-init(s-ctx)  0) {
 fprintf(stderr, Virtio-9p Failed to initialize fs-driver with id:%s
  and export path:%s\n, s-fsconf.fsdev_id, s-ctx.fs_root);
-return -1;
+goto out;
 }
 if (v9fs_init_worker_threads()  0) {
 fprintf(stderr, worker thread initialization failed\n);
-return -1;
+goto out;
 }
 
 /*
@@ -115,18 +115,26 @@ static int virtio_9p_device_init(VirtIODevice *vdev)
 if (s-ops-name_to_path(s-ctx, NULL, /, path)  0) {
 fprintf(stderr,
 error in converting name to path %s, strerror(errno));
-return -1;
+goto out;
 }
 if (s-ops-lstat(s-ctx, path, stat)) {
 fprintf(stderr, share path %s does not exist\n, fse-path);
-return -1;
+goto out;
 } else if (!S_ISDIR(stat.st_mode)) {
 fprintf(stderr, share path %s is not a directory\n, fse-path);
-return -1;
+goto out;
 }
 v9fs_path_free(path);
 
 return 0;
+out:
+g_free(s-ctx.fs_root);
+g_free(s-tag);
+virtio_cleanup(vdev);
+v9fs_path_free(path);
+
+return -1;
+
 }
 
 /* virtio-9p device */
-- 
1.7.11.7




Re: [Qemu-devel] [PATCH] fsdev: Fix potential memory leak

2013-07-03 Thread M. Mohan Kumar
Stefan Weil s...@weilnetz.de writes:

 This leak was reported by cppcheck.

 Signed-off-by: Stefan Weil s...@weilnetz.de

Reviewed-by: M. Mohan Kumar mo...@in.ibm.com
 ---
  fsdev/qemu-fsdev.c |2 ++
  1 file changed, 2 insertions(+)

 diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
 index 6eaf36d..ccfec13 100644
 --- a/fsdev/qemu-fsdev.c
 +++ b/fsdev/qemu-fsdev.c
 @@ -76,6 +76,8 @@ int qemu_fsdev_add(QemuOpts *opts)

  if (fsle-fse.ops-parse_opts) {
  if (fsle-fse.ops-parse_opts(opts, fsle-fse)) {
 +g_free(fsle-fse.fsdev_id);
 +g_free(fsle);
  return -1;
  }
  }
 -- 
 1.7.10.4




Re: [Qemu-devel] [PATCH trivial] configure: explicitly disable virtfs if softmmu=no

2013-06-11 Thread M. Mohan Kumar
Michael Tokarev m...@tls.msk.ru writes:

 11.06.2013 00:47, Michael Tokarev wrote:
 Or else
 
  ./configure --disable-system --enable-virtfs
 
 (which makes no sense by its own but does not error out)
 will fail to build, because it will define CONFIG_VIRTFS,
 and the makefile will try to build virtfs-proxy-helper
 manpage (but not the executable).

 The build fails in this case in a separate build tree, because
 the fsdev directory is not created and scripts/texi2pod.pl
 will be called with output = fsdev/virtfs-proxy-helper.pod,
 which can't be created because fsdev/ does not exist.


Hi,

I tried ./configure --disable-system --enable-virtfs and make. But didnt
face any build failure. Could you please share your build failure
information? virtfs-proxy-helper.1 is created inside the fsdev folder.

 
 Cc: qemu-triv...@nongnu.org
 Cc: M. Mohan Kumar mo...@in.ibm.com
 Signed-off-by: Michael Tokarev m...@tls.msk.ru
 ---
  configure |2 ++
  1 file changed, 2 insertions(+)
 
 diff --git a/configure b/configure
 index a3f0b7a..0ff0380 100755
 --- a/configure
 +++ b/configure
 @@ -3423,6 +3423,8 @@ if test $softmmu = yes ; then
tools=qemu-ga\$(EXESUF) $tools
  fi
fi
 +else
 +  virtfs=no
  fi
  
  # Mac OS X ships with a broken assembler
 




Re: [Qemu-devel] [PATCH trivial] configure: explicitly disable virtfs if softmmu=no

2013-06-11 Thread M. Mohan Kumar
Peter Maydell peter.mayd...@linaro.org writes:

How about this approach?

[PATCH] configure: Disable virtfs if softmmu not enabled

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 configure | 11 +--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/configure b/configure
index 1654413..88c2b0f 100755
--- a/configure
+++ b/configure
@@ -3404,8 +3404,9 @@ if test $want_tools = yes ; then
 tools=qemu-nbd\$(EXESUF) $tools
   fi
 fi
-if test $softmmu = yes ; then
-  if test $virtfs != no ; then
+
+if test $virtfs != no ; then
+  if test $softmmu = yes ; then
 if test $cap = yes  test $linux = yes  test $attr = yes ; then
   virtfs=yes
   tools=$tools fsdev/virtfs-proxy-helper\$(EXESUF)
@@ -3415,6 +3416,12 @@ if test $softmmu = yes ; then
   fi
   virtfs=no
 fi
+  else
+if test $virtfs = yes; then
+  error_exit VirtFS is supported only on Linux and requires softmmu
+else
+ virtfs=no
+fi
   fi
   if [ $linux = yes -o $bsd = yes -o $solaris = yes ] ; then
 if [ $guest_agent = yes ]; then
-- 
1.7.11.7

Tested with following configure options

$ ./configure '--target-list=x86_64-linux-user' --disable-system
[snip]
VirtFS supportno

$ ./configure '--target-list=x86_64-linux-user' --disable-system --enable-virtfs

ERROR: VirtFS is supported only on Linux and requires softmmu

$ ./configure '--target-list=x86_64-softmmu' --enable-virtfs
[snip]
VirtFS supportyes

$ ./configure '--target-list=x86_64-softmmu'
VirtFS supportyes



 On 11 June 2013 13:29, Michael Tokarev m...@tls.msk.ru wrote:
 11.06.2013 01:45, Peter Maydell wrote:
 This doesn't feel to me like it's quite the right way
 to fix this bug. The current code in configure seems
 to tangle up (a) was virtfs requested and can we do it?
 with (b) what do we need to do if it was? (build some
 extra tools) and (c) when does it make sense? not for
 linux-user targets. So you end up with an 'else virtfs=no'
 clause added in an odd place. If the mess was untangled
 then this probably wouldn't be necessary.

 Um. I don't think that tangling is a bad thing really.
 Having different variables or options for it will be
 too bloated, in my opinion.  I don't think there should
 be anything done with it.

 I don't want more variables. I just don't think we
 should have if not softmmu then do some other thing;
 just check for whether the user asked for virtfs and
 we can do it, and if so set virtfs=yes.

 How about something like this:

 --- a/configure
 +++ b/configure
 @@ -3810,7 +3810,7 @@ fi
  if test $libattr = yes ; then
echo CONFIG_LIBATTR=y  $config_host_mak
  fi
 -if test $virtfs = yes ; then
 +if test $virtfs = yes  test $target_softmmu = yes ; then
echo CONFIG_VIRTFS=y  $config_host_mak
  fi

 This seems like a step backwards to me. virtfs=yes should
 just translate straight to CONFIG_VIRTFS and the makefile
 should just not care if it's set if we happen not to be
 building anything virtfs related.

 Also, disabling building tools and docs in general seems
 broken: --disable-tools disables building qemu-img, for
 instance, but not its documentation. So maybe we should
 fix this by generally making sure we don't build the docs
 unless we build the tool as well.

 This has been addressed by a separate patch sent by afaerber.

 That patch didn't touch anything virtfs proxy related.

 thanks
 -- PMM




Re: [Qemu-devel] [PATCH trivial] configure: explicitly disable virtfs if softmmu=no

2013-06-11 Thread M. Mohan Kumar
Michael Tokarev m...@tls.msk.ru writes:

 11.06.2013 21:23, M. Mohan Kumar wrote:
 Peter Maydell peter.mayd...@linaro.org writes:
 
 How about this approach?

 Well, this is definitely wrong :)

 -if test $softmmu = yes ; then
 -  if test $virtfs != no ; then
 +
 +if test $virtfs != no ; then
 +  if test $softmmu = yes ; then
  if test $cap = yes  test $linux = yes  test $attr = yes ; then
virtfs=yes
tools=$tools fsdev/virtfs-proxy-helper\$(EXESUF)
 @@ -3415,6 +3416,12 @@ if test $softmmu = yes ; then
fi
virtfs=no
  fi
 +  else
 +if test $virtfs = yes; then
 +  error_exit VirtFS is supported only on Linux and requires softmmu
 +else
 + virtfs=no
 +fi
fi
if [ $linux = yes -o $bsd = yes -o $solaris = yes ] ; then
  if [ $guest_agent = yes ]; then

 Now this if [ $linux... test is only checked
 if $virtfs != no.  Before, it was checked when
 $softmmu != no...
My bad :(, I missed check for guest_agent inside softmmu case.


 FWIW, I still don't understand what Peter Maydell dislikes
 in a simplest case I posted initially, where we merely ignore
 (disable) virtfs in case !softmmu.  We should probably do the
 same for alot of other features which makes sense only if
 softmmu==yes, and omit many configure tests which are still
 done even if softmmu is disabled, but that's a different
 patch for sure.  Maube we should separate out this last linux|bsd|solaris
 test and add another if softmmu there, for readability, so that
 disabling of virtfs will be closer to other virtfs tests.

 I applied my initial patch to our debian tree to fix build
 failure for now, because else it fails during build.

 Thanks,

 /mjt




[Qemu-devel] [Bug 1130769] Re: VirtFS (virtio-9p-pci) error: Parameter 'driver' expects device type

2013-03-01 Thread M. Mohan Kumar
-fsdev can take local, handle and proxy. Could you please use try with
one of them?

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1130769

Title:
  VirtFS (virtio-9p-pci) error: Parameter 'driver' expects device type

Status in QEMU:
  New
Status in “qemu-kvm” package in Gentoo Linux:
  New

Bug description:
  Getting error Parameter 'driver' expects device type when trying to
  share a file system with a guest.

  Command line:
  qemu-kvm
  -m 4096 -cpu host -smp 4,sockets=1
  -net nic,model=virtio,macaddr=00:00:00:00:00:00 -net 
tap,ifname=tap0,script=no,downscript=no
  -rtc base=localtime
  -drive file=/vm/VM.img,cache=none,if=virtio
  -curses
  -boot menu=off
  -fsdev 
fsdriver,id=fsdev-fs0,path=/srv/files,security_model=passthrough,writeout=writeout
  -device virtio-9p-pci,fsdev=fsdev-fs0,mount_tag=files

  OS (host/guest): Gentoo
  Kernel (host/guest): 3.7.5-hardened
  CPU: AMD Opteron(TM) Processor 6272 (host: 16 cores, guest: 4)
  Arch (host/guest): x86_64
  Version: QEMU emulator version 1.2.2 (qemu-kvm-1.2.0), Copyright (c) 
2003-2008 Fabrice Bellard
  Package: app-emulation/qemu-1.2.2-r3

  -no-kvm-irqchip  did not have effect
  -no-kvm-pit   did not have effect other than Warning: KVM PIT can no 
longer be disabled separately.
  -no-kvmdid not work with Could not allocate dynamic translator 
buffer

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1130769/+subscriptions



Re: [Qemu-devel] 9pfs segfaults on chmod(special)

2013-02-28 Thread M. Mohan Kumar
Michael Tokarev m...@tls.msk.ru writes:

 28.02.2013 13:12, Aneesh Kumar K.V wrote:
 Michael Tokarev m...@tls.msk.ru writes:
 
 When guest tries to chmod a block or char device file over 9pfs,
 the qemu process segfaults.

 On host:
  qemu-system-x86_64 -virtfs 
 local,path=/dev,security_model=mapped-file,mount_tag=tag

 On guest:
  mount -t 9p -o trans=virtio tag /mnt
  chmod 0777 /mnt/tty
 
 any specific reason why you are trying 9p .u ?

 Sorry?  What _is_ 9p .u ? :)

Hi,

9p.u is the extension of 9p protocol developed during Linux porting of
9p. Original 9p was designed for Plan 9 operating system. 9p.u has
support for numerical uids, gids, additional mode and permissio bits.

But still 9p.u lacked support for full Linux VFS operations. Such as
xattrs, locking etc. In order to overcome these issues and address
functionalities provides by Linux VFS a new protocol 9p2000.L was
developed (http://code.google.com/p/diod/wiki/protocol)

By default 9p.u is used, you can override by that
 mount -t 9p -otrans=virtio,version=9p2000.L tag /mnt



 []
 Maybe the buffer (extension-data) should be passed to it instead of
 the whole structure (extension)?  Or the check be extended (or,
 since this function isn't called from any other place, _replaced_) to
 test for non-NULL -data too?

 
 Thanks for the detailed analysis. Something like below ?
 
 diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
 index f526467..073067f 100644
 --- a/hw/9pfs/virtio-9p.c
 +++ b/hw/9pfs/virtio-9p.c
 @@ -659,7 +659,7 @@ static mode_t v9mode_to_mode(uint32_t mode, V9fsString 
 *extension)
  ret |= S_IFIFO;
  }
  if (mode  P9_STAT_MODE_DEVICE) {
 -if (extension  extension-data[0] == 'c') {
 +if (extension-size  extension-data[0] == 'c') {
  ret |= S_IFCHR;
  } else {
  ret |= S_IFBLK;
 

 Yeah, that looks much saner.  And it obviously works, just
 like testing ext-data to be non-null.

 It has been this way since about beginning (as in, for example,
 1.1 version of qemu is also affected), and probably is a good
 candidate for -stable too.

 Reviewed-By: Michael Tokarev m...@tls.msk.ru

 Thank you!

 /mjt




Re: [Qemu-devel] 9pfs: unreadable dirs with random errors in guest

2013-02-28 Thread M. Mohan Kumar
Michael Tokarev m...@tls.msk.ru writes:

Hi,

Please try mounting with -oversion=9p2000.L

With qemu-1.4.0 and 9p2000.L, I could not recreate this issue. ie not
getting Unknown error during directory listing.

I am using Guest kernel 3.8.0-rc5+.

 When I mount a 9pfs filesystem in guest with no write permission for
 some dirs, I'm getting strange errors in guest.

 Host (as a regular user):
  qemu-system-x86_64 -virtfs 
 local,path=/,security_model=mapped-file,mount_tag=tag

 Guest:
  # mount -t 9p -o trans=virtio,ro tag /mnt
  # ls /mnt
  ls: reading directory /mnt: Unknown error 593
  # ls /mnt/dev
  ls: reading directory /mnt/dev: Unknown error 849
  # ls /mnt/tmp
  [works]
  # ls /mnt/root
  ls: cannot open directory /mnt/root: Permission denied

 So, it reports errors while trying to _read_ (not open)
 readable but non-writable dirs, and these errors are _random_.
 It correctly reports errors when trying to open an unreadable
 dir.

 This is 1.4.0.  Similar problem exists with earlier versions
 of qemu.

 Thanks!

 /mjt




Re: [Qemu-devel] 9pfs: unWRITAble dirs with random errors in guest

2013-02-28 Thread M. Mohan Kumar
Michael Tokarev m...@tls.msk.ru writes:


 28.02.2013 17:55, M. Mohan Kumar wrote:
 Michael Tokarev m...@tls.msk.ru writes:
 
 Hi,
 
 Please try mounting with -oversion=9p2000.L
 
 With qemu-1.4.0 and 9p2000.L, I could not recreate this issue. ie not
 getting Unknown error during directory listing.

 Yes, with 9p2000.L it works fine, both reported
 issues are gone.

 I am using Guest kernel 3.8.0-rc5+.

 But do you see my original error, with the default mount version?
 (I'm using 3.2 guest kernel if that matters, and it is also 32bits,
 which should not matter).
Yes, with default mount option, i am getting same error.


 When I mount a 9pfs filesystem in guest with no write permission for
 some dirs, I'm getting strange errors in guest.

 Host (as a regular user):
  qemu-system-x86_64 -virtfs 
 local,path=/,security_model=mapped-file,mount_tag=tag

 Guest:
  # mount -t 9p -o trans=virtio,ro tag /mnt
  # ls /mnt
  ls: reading directory /mnt: Unknown error 593
  # ls /mnt/dev
  ls: reading directory /mnt/dev: Unknown error 849
  # ls /mnt/tmp
  [works]
  # ls /mnt/root
  ls: cannot open directory /mnt/root: Permission denied

 So, it reports errors while trying to _read_ (not open)
 readable but non-writable dirs, and these errors are _random_.
 It correctly reports errors when trying to open an unreadable
 dir.

 This is 1.4.0.  Similar problem exists with earlier versions
 of qemu.

 Thanks!

 /mjt
 




Re: [Qemu-devel] [PATCH] virtfs-proxy-helper: check return code of setfsgid/setfsuid

2012-12-04 Thread M. Mohan Kumar
Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com writes:

 I found this to be confusing. How about avoiding all those pointers, something
 like below ? If you are ok can I add the signed-off-by for this ? I can
 test this and get a pull request out with the build fix.

 commit 24cc9f0d07c2a505bfafbdcb72006f2eda1288a4
 Author: Paolo Bonzini pbon...@redhat.com
 Date:   Thu Oct 11 14:20:23 2012 +0200

 virtfs-proxy-helper: use setresuid and setresgid
 
 The setfsuid and setfsgid system calls are obscure and they complicate
 the error checking (that glibc's warn_unused_result feature forces
 us to do).  Switch to the standard setresuid and setresgid functions.

 diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
 index f9a8270..49ab0eb 100644
 --- a/fsdev/virtfs-proxy-helper.c
 +++ b/fsdev/virtfs-proxy-helper.c
 @@ -272,31 +272,59 @@ static int send_status(int sockfd, struct iovec *iovec, 
 int status)
  /*
   * 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.
 + * If the effective user ID is changed from nonzero to 0, then the permitted
 + * set is copied to the effective set.  If the effective user ID is changed
 + * from 0 to nonzero, then all capabilities are are cleared from the 
 effective
 + * set.
 + *
 + * The setfsuid/setfsgid man pages warn that changing the effective user ID 
 may
 + * expose the program to unwanted signals, but this is not true anymore: for 
 an
 + * unprivileged (without CAP_KILL) program to send a signal, the real or
 + * effective user ID of the sending process must equal the real or saved user
 + * ID of the target process.  Even when dropping privileges, it is enough to
 + * keep the saved UID to a privileged value and virtfs-proxy-helper won't
 + * be exposed to signals.  So just use setresuid/setresgid.
   */
 -static int setfsugid(int uid, int gid)
 +static int setugid(int uid, int gid, int suid, int sgid)
  {
 +int retval;
 +
  /*
 - * We still need DAC_OVERRIDE because  we don't change
 + * We still need DAC_OVERRIDE because we don't change
   * supplementary group ids, and hence may be subjected DAC rules
   */
  cap_value_t cap_list[] = {
  CAP_DAC_OVERRIDE,
  };

 -setfsgid(gid);
 -setfsuid(uid);
 +if (setresuid(-1, uid, suid) == -1) {
 +retval = -errno;
 +goto err_out;
 +}
 +if (setresgid(-1, gid, sgid) == -1) {
 +retval = -errno;
 +goto err_suid;
 +}


After changing the order of setresuid and setresgid this patch works as
expected. Please move setresgid before setresuid.

Tested-by: M. Mohan Kumar mo...@in.ibm.com




Re: [Qemu-devel] [PATCH] virtfs-proxy-helper: check return code of setfsgid/setfsuid

2012-10-11 Thread M. Mohan Kumar
Stefan Weil s...@weilnetz.de writes:

We need to change fsuid and fsgid in 9p server side when 9p client wants
to create a file with given uid and gid.

In my case setfsuid and setfsgid never return -1 even if a normal user tries to
change fsuid.

I am running F17 and glibc is 2.15-56.fc17

IMHO setfsuid/setfsgid need to return -1  set errno to EPERM when calling user
lacks CAP_SETUID capability. I can work on the kernel side to return
proper error values.

Also as per the man page:
   When glibc determines that the argument is not a valid user ID,
   it will return -1 and set errno  to  EINVAL
   without attempting the system call.

If it mean a nonexistent id by 'not a valid user ID' it may be a
problem in virtfs case. Client sends the user id details which may be
a nonexistent user id in host system. Ideally setfsuid setfsgid sets
whatever uid/gid passed if the caller is root as of now.   


 Am 10.10.2012 18:54, schrieb Stefan Weil:
 Am 10.10.2012 18:36, schrieb Paolo Bonzini:
 Il 10/10/2012 18:23, Stefan Weil ha scritto:
  0 would be wrong because it looks like both functions never
 return negative values.
 I just wrote a small test program (see
 below) and called it with different uids with and without root
 rights. This pattern should be fine:

 new_uid = setfsuid(uid);
 if (new_uid != 0  new_uid != uid) {
return -1;
 }
 I didn't really care about this case.  I assumed that the authors knew
 what they were doing...

 What I cared about is: When glibc determines that the argument is not a
   valid  group  ID,  it will  return  -1  and set errno to EINVAL 
 without
 attempting the system call.

 I was not able to get -1 with my test program: any value which I tried
 seemed to work when the program was called with sudo.


 I think this would also work:

 if (setfsuid(uid)  0 || setfsuid(uid) != uid) {
 return -1;
 }

 but it seems wasteful to do four syscalls instead of two.

 Paolo

 I added a local variable in my example to avoid those extra
 syscalls.

 Your last patch v2 does not handle missing rights (no root)
 because in that case the functions don't return a value  0
 but fail nevertheless.Calling a program which requires
 root privileges from a normal user account is usually a
 very common error. I don't know the use cases for virtfs -
 maybe that's no problem here.

 The functions have an additional problem: they don't set
 errno (see manpages). I tested this, and here the manpages
 are correct. The code in virtfs-proxy-helper expects that
 errno was set, so the patch must set errno = EPERM or
 something like that.

 Stefan

 Maybe the author of those code can tell us more on the
 use cases and which errors must be handled.

 Is it necessary to use those functions at all (they are very
 Linux specific), or can they be replaced by seteuid, setegid?

 Regards

 Stefan W.




[Qemu-devel] [PATCH] fsdev: Don't ignore setfsuid/setfsgid return values

2012-10-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

In current implementation of setfsuid/setfsgid there is no way to know
if it failed by checking the return value. This patch assumes
setfsuid/setfsgid returns -1 in case of error. Eventually kernel code
needs to be fixed.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index f9a8270..ed5eede 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -290,9 +290,12 @@ static int setfsugid(int uid, int gid)
 CAP_DAC_OVERRIDE,
 };
 
-setfsgid(gid);
-setfsuid(uid);
-
+if (setfsgid(gid)  0) {
+return -errno;
+}
+if (setfsuid(uid)  0) {
+return -errno;
+}
 if (uid != 0 || gid != 0) {
 return do_cap_set(cap_list, ARRAY_SIZE(cap_list), 0);
 }
-- 
1.7.11.4




[Qemu-devel] [Bug 1018530] Re: No write access in a 9p/virtfs shared folder

2012-07-11 Thread M. Mohan Kumar
Georg,

pass-through security model needs root privilege, if you want to run
qemu as non-root user either you have to use mapped security model or
proxy fs driver. But libvirt does not have support for proxy FS driver.
I posted a patch few months ago to libvirt for enabling the same. I will
do the followup with libvirt list to enable proxy FS in libvirt.

So could you please try mapped security model or run  qemu as root user
and update the results?

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1018530

Title:
  No write access in a 9p/virtfs shared folder

Status in QEMU:
  New
Status in “qemu-kvm” package in Ubuntu:
  Fix Released

Bug description:
  Ubuntu version:  Ubuntu 12.04 LTS
  Kernel: 3.2.0-25-generic
  Version of qemu-kvm: 1.0+noroms-0ubuntu13

  I have created an shared folder for an virtual machine which is
  managed by libvirt.

  filesystem type='mount' accessmode='passthrough'
  source dir='/storage/data'/
  target dir='data'/
  address type='pci' domain='0x' bus='0x00' slot='0x08' function='0x0'/
  /filesystem

  I mounted it in the virtual machine with this command:  mount -t 9p -o 
trans=virtio,version=9p2000.L data /data
  The filesystem permissions of all files an folders in the shared folder are 
set to 777. I expected that I have the full permissions also in the virtual 
machine.

  Regardless of the permissions on the filesystem I cannot write or create 
files and folders in the virtual machine. The original filesystem (/storage) is 
XFS.
  In another shared folder (similar config in libvirt) which is originally NTFS 
I have no problems.

  ProblemType: Bug
  DistroRelease: Ubuntu 12.04
  Package: qemu-kvm 1.0+noroms-0ubuntu13
  ProcVersionSignature: Ubuntu 3.2.0-25.40-generic 3.2.18
  Uname: Linux 3.2.0-25-generic x86_64
  ApportVersion: 2.0.1-0ubuntu8
  Architecture: amd64
  Date: Wed Jun 27 20:15:20 2012
  InstallationMedia: Ubuntu-Server 12.04 LTS Precise Pangolin - Beta amd64 
(20120409)
  MachineType: To be filled by O.E.M. To be filled by O.E.M.
  ProcEnviron:
   TERM=xterm
   LANG=de_DE.UTF-8
   SHELL=/bin/bash
  ProcKernelCmdLine: BOOT_IMAGE=/vmlinuz-3.2.0-25-generic 
root=/dev/mapper/system-root ro
  SourcePackage: qemu-kvm
  UpgradeStatus: No upgrade log present (probably fresh install)
  dmi.bios.date: 04/18/2012
  dmi.bios.vendor: American Megatrends Inc.
  dmi.bios.version: 1208
  dmi.board.asset.tag: To be filled by O.E.M.
  dmi.board.name: M5A99X EVO
  dmi.board.vendor: ASUSTeK COMPUTER INC.
  dmi.board.version: Rev 1.xx
  dmi.chassis.asset.tag: To Be Filled By O.E.M.
  dmi.chassis.type: 3
  dmi.chassis.vendor: To Be Filled By O.E.M.
  dmi.chassis.version: To Be Filled By O.E.M.
  dmi.modalias: 
dmi:bvnAmericanMegatrendsInc.:bvr1208:bd04/18/2012:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnASUSTeKCOMPUTERINC.:rnM5A99XEVO:rvrRev1.xx:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:
  dmi.product.name: To be filled by O.E.M.
  dmi.product.version: To be filled by O.E.M.
  dmi.sys.vendor: To be filled by O.E.M.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1018530/+subscriptions



[Qemu-devel] [Bug 1018530] Re: No write access in a 9p/virtfs shared folder

2012-07-09 Thread M. Mohan Kumar
No, commit  daf0b9aca9f67323266af1a92e8ea06f9d7bf408 added create
support proxy FS driver model. Local FS had support for creating files
much before.

Georg, is qemu running with root user privileges?

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/1018530

Title:
  No write access in a 9p/virtfs shared folder

Status in QEMU:
  New
Status in “qemu-kvm” package in Ubuntu:
  Fix Released

Bug description:
  Ubuntu version:  Ubuntu 12.04 LTS
  Kernel: 3.2.0-25-generic
  Version of qemu-kvm: 1.0+noroms-0ubuntu13

  I have created an shared folder for an virtual machine which is
  managed by libvirt.

  filesystem type='mount' accessmode='passthrough'
  source dir='/storage/data'/
  target dir='data'/
  address type='pci' domain='0x' bus='0x00' slot='0x08' function='0x0'/
  /filesystem

  I mounted it in the virtual machine with this command:  mount -t 9p -o 
trans=virtio,version=9p2000.L data /data
  The filesystem permissions of all files an folders in the shared folder are 
set to 777. I expected that I have the full permissions also in the virtual 
machine.

  Regardless of the permissions on the filesystem I cannot write or create 
files and folders in the virtual machine. The original filesystem (/storage) is 
XFS.
  In another shared folder (similar config in libvirt) which is originally NTFS 
I have no problems.

  ProblemType: Bug
  DistroRelease: Ubuntu 12.04
  Package: qemu-kvm 1.0+noroms-0ubuntu13
  ProcVersionSignature: Ubuntu 3.2.0-25.40-generic 3.2.18
  Uname: Linux 3.2.0-25-generic x86_64
  ApportVersion: 2.0.1-0ubuntu8
  Architecture: amd64
  Date: Wed Jun 27 20:15:20 2012
  InstallationMedia: Ubuntu-Server 12.04 LTS Precise Pangolin - Beta amd64 
(20120409)
  MachineType: To be filled by O.E.M. To be filled by O.E.M.
  ProcEnviron:
   TERM=xterm
   LANG=de_DE.UTF-8
   SHELL=/bin/bash
  ProcKernelCmdLine: BOOT_IMAGE=/vmlinuz-3.2.0-25-generic 
root=/dev/mapper/system-root ro
  SourcePackage: qemu-kvm
  UpgradeStatus: No upgrade log present (probably fresh install)
  dmi.bios.date: 04/18/2012
  dmi.bios.vendor: American Megatrends Inc.
  dmi.bios.version: 1208
  dmi.board.asset.tag: To be filled by O.E.M.
  dmi.board.name: M5A99X EVO
  dmi.board.vendor: ASUSTeK COMPUTER INC.
  dmi.board.version: Rev 1.xx
  dmi.chassis.asset.tag: To Be Filled By O.E.M.
  dmi.chassis.type: 3
  dmi.chassis.vendor: To Be Filled By O.E.M.
  dmi.chassis.version: To Be Filled By O.E.M.
  dmi.modalias: 
dmi:bvnAmericanMegatrendsInc.:bvr1208:bd04/18/2012:svnTobefilledbyO.E.M.:pnTobefilledbyO.E.M.:pvrTobefilledbyO.E.M.:rvnASUSTeKCOMPUTERINC.:rnM5A99XEVO:rvrRev1.xx:cvnToBeFilledByO.E.M.:ct3:cvrToBeFilledByO.E.M.:
  dmi.product.name: To be filled by O.E.M.
  dmi.product.version: To be filled by O.E.M.
  dmi.sys.vendor: To be filled by O.E.M.

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/1018530/+subscriptions



[Qemu-devel] [Bug 965867] Re: 9p virtual file system on qemu slow

2012-04-25 Thread M. Mohan Kumar
Hi Max,

Could you try passing msize=262144 for 9p mount point and post the
results?

Host:
[root@llm116 media]# ls -lhas file
1.1G -rw-r--r-- 1 root root 1.0G Apr 26 11:05 file

[root@llm116 media]# dd if=/dev/zero of=file bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 0.700828 s, 1.5 GB/s

[root@llm116 media]# time cp file file2

real0m6.353s
user0m0.007s
sys 0m1.520s

VM:

[root@qemu-img-64 pass]# time cp file 9p_file

real0m12.261s
user0m0.154s
sys 0m2.582s

[root@qemu-img-64 pass]# dd if=/dev/zero of=file.9 bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB) copied, 2.07335 s, 518 MB/s

[root@qemu-img-64 pass]# mount
[snip]
v_pass on /pass type 9p (rw,trans=virtio,version=9p2000.L,msize=262144)
[/snip]

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/965867

Title:
  9p virtual file system on qemu slow

Status in QEMU:
  New
Status in “qemu-kvm” package in Ubuntu:
  Confirmed

Bug description:
  Hi, 
  The 9p virtual file system is slow. Several examples below: 
  -
  Host for the first time: 
  $ time ls bam.unsorted/
  ...
  real0m0.084s
  user0m0.000s
  sys 0m0.028s
  --
  Host second and following: 

  real0m0.009s
  user0m0.000s
  sys 0m0.008s
  --
  VM for the first time: 
  $ time ls bam.unsorted/
  
  real0m23.141s
  user0m0.064s
  sys 0m2.156s
  --
  VM for the second time
  real0m3.643s
  user0m0.024s
  sys 0m0.424s
  

  Copy on host: 
  $ time cp 5173T.root.bak test.tmp
  real0m30.346s
  user0m0.004s
  sys 0m5.324s

  $ ls -lahs test.tmp
  2.7G -rw--- 1 oneadmin cloud 2.7G Mar 26 21:47 test.tmp

  ---
  $ copy on VM for the same file

  time cp 5173T.root.bak test.tmp

  real5m46.978s
  user0m0.352s
  sys 1m38.962s

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/965867/+subscriptions



Re: [Qemu-devel] VirtIO 9p mount_tag (bogus?) limit of 32 bytes

2012-03-07 Thread M. Mohan Kumar

Hi Anthony,

When I tried with ldconfig version 2.14.90, ldconfig successfully completed

QEMU version: 1.0.50
Kernel version: 3.3.0-rc6+

Could you please try with recent ldconfig?

On 02/22/2012 09:28 AM, C Anthony Risinger wrote:

On Sat, Feb 18, 2012 at 11:38 AM, Aneesh Kumar K.V
aneesh.ku...@linux.vnet.ibm.com  wrote:

On Thu, 16 Feb 2012 06:20:21 -0600, C Anthony Risingeranth...@xtfx.me  wrote:

a) mapped FS security policy (xattrs) causes `ldconfig` to abort()?
root or normal user ...

somehow `ldconfig` gets a duplicate inode while constructing the
cache, even though it already de-duped (confirmed via gdb and grep --
only a single abort() in the source)

b) unable to run `locale-gen` on *any* virtfs configuration? (strace)

[...]
mmap(NULL, 536870912, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) =
0x7fb3aac63000
mmap(0x7fb3aac63000, 103860, PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_FIXED, 3, 0) = -1 EINVAL (Invalid argument)
cannot map archive header: Invalid argument

c) package files containing device nodes fail (maybe this is expected
...); specifically `/lib/udev/devices/loop0`


Is this with 9p2000.L ?. What is the guest kernel version ?

(not sure if list will accept this ... too much traffic! had to remove myself)

yes this is with 9p2000.L, both host and guests run kernel 3.2.5.  i'm
happy to provide/try additional information/tests if useful.

... is there really no chance of upping the max path?  seems like
config space will be a big constraint, forever :-(

and i'm very much willing to do additional testing for the other
issues as well (i had to revert to qemu-as-root to get passthru
working 100% on rootfs ... ldconfig is kind of critical :-).  are
these known issues?






Re: [Qemu-devel] QEMU build errors with 'fdopendir'

2012-02-08 Thread M. Mohan Kumar

Hi,

I will give a fix to disable virtfs by providing a configure option 
--disable-virtfs.


But if you want use virtfs with your current setup, we can give the 
option to

disable handle and proxy FS driver. Still you can use local FS driver.

Meador Inge wrote:

Did these [1] builds errors ever get fixed?  I am running into one of them.  I
am building QEMU in an environment where 'fdopendir' is not present.
'fdopendir' was introduced in POSIX 2008 (and The Open Group Technical
Standard, 2006, Extended API Set Part 2.), so it may not be available in some
environments where QEMU is built.

[1] http://lists.nongnu.org/archive/html/qemu-devel/2011-12/msg00171.html

   





Re: [Qemu-devel] [PATCH] Remove O_NOATIME flag from 9pfs open() calls in readonly mode

2012-01-24 Thread M. Mohan Kumar
Acked-by: M. Mohan Kumar mo...@in.ibm.com

On Monday, January 16, 2012 11:41:40 PM Daniel P. Berrange wrote:
 From: Daniel P. Berrange berra...@redhat.com
 
 When 2c74c2cb4bedddbfa67628fbd5f9273b4e0e9903 added support for
 the 'readonly' flag against 9p filesystems, it also made QEMU
 add the O_NOATIME flag as a side-effect.
 
 The O_NOATIME flag, however, may only be set by the file owner,
 or a user with CAP_FOWNER capability.  QEMU cannot assume that
 this is the case for filesytems exported to QEMU.
 
 eg, run QEMU as non-root, and attempt to pass the host OS
 filesystem through to the guest OS with readonly enable.
 The result is that the guest OS cannot open any files at
 all.
 
 If O_NOATIME is really required, it should be optionally
 enabled via a separate QEMU command line flag.
 
  * hw/9pfs/virtio-9p.c: Remove O_NOATIME
 
 Signed-off-by: Daniel P. Berrange berra...@redhat.com
 ---
  hw/9pfs/virtio-9p.c |1 -
  1 files changed, 0 insertions(+), 1 deletions(-)
 
 diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
 index e6ba6ba..f8e2c07 100644
 --- a/hw/9pfs/virtio-9p.c
 +++ b/hw/9pfs/virtio-9p.c
 @@ -1391,7 +1391,6 @@ static void v9fs_open(void *opaque)
  err = -EROFS;
  goto out;
  }
 -flags |= O_NOATIME;
  }
  err = v9fs_co_open(pdu, fidp, flags);
  if (err  0) {




[Qemu-devel] [PATCH] fsdev: parameter parsing for proxy helper

2012-01-19 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |   10 --
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index baafee2..5aafc38 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -1040,7 +1040,13 @@ int main(int argc, char **argv)
 return -1;
 }
 
-if (*sock_name  (own_u == -1 || own_g == -1)) {
+if (sock_name  sock != -1) {
+fprintf(stderr, both named socket and socket descriptor specified\n);
+usage(argv[0]);
+exit(EXIT_FAILURE);
+}
+
+if (sock_name  (own_u == -1 || own_g == -1)) {
 fprintf(stderr, owner uid:gid not specified, );
 fprintf(stderr,
 owner uid:gid specifies who can access the socket file\n);
@@ -1068,7 +1074,7 @@ int main(int argc, char **argv)
 }
 
 do_log(LOG_INFO, Started\n);
-if (*sock_name) {
+if (sock_name) {
 sock = proxy_socket(sock_name, own_u, own_g);
 if (sock  0) {
 goto error;
-- 
1.7.6




[Qemu-devel] [PATCH] Preserve S_ISGID

2011-12-27 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

In passthrough security model in local fs driver, after a file creation
chown and chmod are done to set the file credentials and mode as requested
by 9p client. But if there was a request to create a file with S_ISGID
bit, doing chown on that file resets the S_ISGID bit. So first call
chown and then invoking chmod with proper mode bit retains the S_ISGID
(if present/requested)

This resulted in LTP mknod02, mknod03, mknod05, open10 test case
failures. This patch fixes this issue.

man 2 chown
When the owner or group of an executable file are changed by an unprivileged
user the S_ISUID  and  S_ISGID mode  bits are cleared.  POSIX does not specify
whether this also should happen when root does the chown(); the Linux behavior
depends on the kernel version.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 hw/9pfs/virtio-9p-local.c |7 ---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 3ae6ef2..3eb481d 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -115,9 +115,6 @@ static int local_post_create_passthrough(FsContext *fs_ctx, 
const char *path,
 {
 char buffer[PATH_MAX];
 
-if (chmod(rpath(fs_ctx, path, buffer), credp-fc_mode  0)  0) {
-return -1;
-}
 if (lchown(rpath(fs_ctx, path, buffer), credp-fc_uid,
 credp-fc_gid)  0) {
 /*
@@ -128,6 +125,10 @@ static int local_post_create_passthrough(FsContext 
*fs_ctx, const char *path,
 return -1;
 }
 }
+
+if (chmod(rpath(fs_ctx, path, buffer), credp-fc_mode  0)  0) {
+return -1;
+}
 return 0;
 }
 
-- 
1.7.6




[Qemu-devel] [PATCH V5 12/14] hw/9pfs: Documentation changes related to proxy fs

2011-12-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 qemu-options.hx |   25 -
 1 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index b3db10c..cfc999f 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -538,19 +538,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][,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][,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}
@@ -567,7 +567,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.
@@ -577,6 +577,10 @@ 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 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.
@@ -597,19 +601,19 @@ DEFHEADING(Virtual File system pass-through options:)
 
 DEF(virtfs, HAS_ARG, QEMU_OPTION_virtfs,
 -virtfs 
local,path=path,mount_tag=tag,security_model=[mapped|passthrough|none]\n
-[,writeout=immediate][,readonly]\n,
+[,writeout=immediate][,readonly][,sock_fd=sock_fd]\n,
 QEMU_ARCH_ALL)
 
 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][,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}
@@ -626,7 +630,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.
@@ -636,6 +640,9 @@ 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 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




[Qemu-devel] [PATCH V5 05/14] hw/9pfs: File system helper process for qemu 9p proxy FS

2011-12-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 -f|--fd socket descriptor -p|--path path-to-share

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 Makefile|3 +
 configure   |   19 +++
 fsdev/virtfs-proxy-helper.c |  300 +++
 hw/9pfs/virtio-9p-proxy.h   |9 ++
 4 files changed, 331 insertions(+), 0 deletions(-)
 create mode 100644 fsdev/virtfs-proxy-helper.c

diff --git a/Makefile b/Makefile
index 301c75e..1906c5e 100644
--- a/Makefile
+++ b/Makefile
@@ -154,6 +154,9 @@ qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
 qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
 qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
 
+fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o 
fsdev/virtio-9p-marshal.o
+fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
+
 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 5fbd812..8a22b17 100755
--- a/configure
+++ b/configure
@@ -1939,6 +1939,22 @@ 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
+  else
+cap=no
+  fi
+fi
+
+##
 # pthread probe
 PTHREADLIBS_LIST=-pthread -lpthread -lpthreadGC2
 
@@ -2736,6 +2752,9 @@ confdir=$sysconfdir$confsuffix
 tools=
 if test $softmmu = yes ; then
   tools=qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools
+  if [ $cap = yes -a $linux = yes ] ; then
+  tools=$tools fsdev/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
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
new file mode 100644
index 000..5fc2fc4
--- /dev/null
+++ b/fsdev/virtfs-proxy-helper.c
@@ -0,0 +1,300 @@
+/*
+ * Helper for QEMU Proxy FS Driver
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * M. Mohan Kumar mo...@in.ibm.com
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#include stdio.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/capability.h
+#include sys/fsuid.h
+#include stdarg.h
+#include stdbool.h
+#include qemu-common.h
+#include virtio-9p-marshal.h
+#include hw/9pfs/virtio-9p-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'},
+};
+
+static bool is_daemon;
+
+static void do_log(int loglevel, const char *format, ...)
+{
+va_list ap;
+
+va_start(ap, format);
+if (is_daemon) {
+vsyslog(LOG_CRIT, format, ap);
+} else {
+vfprintf(stderr, format, ap);
+}
+va_end(ap);
+}
+
+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 int do_cap_set(cap_value_t *cap_value, int size, int reset)
+{
+cap_t caps;
+if (reset) {
+/*
+ * Start with an empty set and set permitted and effective
+ */
+caps = cap_init();
+if (caps == NULL) {
+do_perror(cap_init);
+return -1;
+}
+if (cap_set_flag(caps, CAP_PERMITTED, size, cap_value, CAP_SET)  0) {
+do_perror(cap_set_flag);
+goto error;
+}
+} else {
+caps = cap_get_proc();
+if (!caps) {
+do_perror(cap_get_proc);
+return -1;
+}
+}
+if (cap_set_flag(caps, CAP_EFFECTIVE, size, cap_value, CAP_SET)  0) {
+do_perror(cap_set_flag);
+goto error;
+}
+if (cap_set_proc(caps)  0) {
+do_perror(cap_set_proc);
+goto error;
+}
+cap_free(caps);
+return 0;
+
+error:
+cap_free(caps);
+return -1;
+}
+
+static int init_capabilities(void)
+{
+/* helper needs following capbabilities only */
+cap_value_t cap_list[] = {
+CAP_CHOWN,
+CAP_DAC_OVERRIDE,
+CAP_FOWNER,
+CAP_FSETID,
+CAP_SETGID,
+CAP_MKNOD,
+CAP_SETUID,
+};
+return do_cap_set(cap_list, ARRAY_SIZE(cap_list), 1);
+}
+
+static int socket_read(int sockfd, void *buff, ssize_t size

[Qemu-devel] [PATCH V5 10/14] hw/9pfs: xattr interfaces in proxy filesystem driver

2011-12-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Add xattr support for proxy FS

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |   99 ++
 hw/9pfs/virtio-9p-proxy.c   |  124 ---
 hw/9pfs/virtio-9p-proxy.h   |4 ++
 3 files changed, 219 insertions(+), 8 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 2c1e2c7..10dd337 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -27,6 +27,7 @@
 #include stdbool.h
 #include sys/vfs.h
 #include sys/stat.h
+#include attr/xattr.h
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
@@ -329,6 +330,62 @@ static int send_response(int sock, struct iovec *iovec, 
int size)
 return 0;
 }
 
+static int do_getxattr(int type, struct iovec *iovec, struct iovec *out_iovec)
+{
+int size = 0, offset, retval;
+V9fsString path, name, xattr;
+
+v9fs_string_init(xattr);
+v9fs_string_init(path);
+retval = proxy_unmarshal(iovec, PROXY_HDR_SZ, ds, size, path);
+if (retval  0) {
+return retval;
+}
+offset = PROXY_HDR_SZ + retval;
+
+if (size) {
+xattr.data = g_malloc(size);
+xattr.size = size;
+}
+switch (type) {
+case T_LGETXATTR:
+v9fs_string_init(name);
+retval = proxy_unmarshal(iovec, offset, s, name);
+if (retval  0) {
+retval = lgetxattr(path.data, name.data, xattr.data, size);
+if (retval  0) {
+retval = -errno;
+} else {
+xattr.size = retval;
+}
+}
+v9fs_string_free(name);
+break;
+case T_LLISTXATTR:
+retval = llistxattr(path.data, xattr.data, size);
+if (retval  0) {
+retval = -errno;
+} else {
+xattr.size = retval;
+}
+break;
+}
+if (retval  0) {
+goto err_out;
+}
+
+if (!size) {
+proxy_marshal(out_iovec, PROXY_HDR_SZ, d, retval);
+retval = sizeof(retval);
+} else {
+retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, s, xattr);
+}
+err_out:
+v9fs_string_free(xattr);
+v9fs_string_free(path);
+return retval;
+}
+
 static void stat_to_prstat(ProxyStat *pr_stat, struct stat *stat)
 {
 memset(pr_stat, 0, sizeof(*pr_stat));
@@ -604,6 +661,8 @@ static int process_reply(int sock, int type,
 case T_UTIME:
 case T_RENAME:
 case T_REMOVE:
+case T_LSETXATTR:
+case T_LREMOVEXATTR:
 if (send_status(sock, out_iovec, retval)  0) {
 return -1;
 }
@@ -611,6 +670,8 @@ static int process_reply(int sock, int type,
 case T_LSTAT:
 case T_STATFS:
 case T_READLINK:
+case T_LGETXATTR:
+case T_LLISTXATTR:
 if (send_response(sock, out_iovec, retval)  0) {
 return -1;
 }
@@ -624,10 +685,13 @@ static int process_reply(int sock, int type,
 
 static int process_requests(int sock)
 {
+int flags;
+int size = 0;
 int retval = 0;
 uint64_t offset;
 ProxyHeader header;
 int mode, uid, gid;
+V9fsString name, value;
 struct timespec spec[2];
 V9fsString oldpath, path;
 struct iovec in_iovec, out_iovec;
@@ -755,6 +819,41 @@ static int process_requests(int sock)
 }
 v9fs_string_free(path);
 break;
+case T_LGETXATTR:
+case T_LLISTXATTR:
+retval = do_getxattr(header.type, in_iovec, out_iovec);
+break;
+case T_LSETXATTR:
+v9fs_string_init(path);
+v9fs_string_init(name);
+v9fs_string_init(value);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ, sssdd, path,
+ name, value, size, flags);
+if (retval  0) {
+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_string_init(path);
+v9fs_string_init(name);
+retval = proxy_unmarshal(in_iovec,
+ PROXY_HDR_SZ, ss, path, name);
+if (retval  0) {
+retval = lremovexattr(path.data, name.data);
+if (retval  0) {
+retval = -errno;
+}
+}
+v9fs_string_free(path);
+v9fs_string_free(name);
+break;
 default:
 goto err_out;
 break;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index cb6e4cd..983d319 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c

[Qemu-devel] [PATCH V5 08/14] hw/9pfs: Add stat/readlink/statfs for proxy FS

2011-12-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |  182 ++
 hw/9pfs/virtio-9p-proxy.c   |  206 +--
 hw/9pfs/virtio-9p-proxy.h   |   34 +++
 3 files changed, 414 insertions(+), 8 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index cdad310..5989b35 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -25,6 +25,8 @@
 #include sys/fsuid.h
 #include stdarg.h
 #include stdbool.h
+#include sys/vfs.h
+#include sys/stat.h
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
@@ -286,6 +288,172 @@ static int setfsugid(int uid, int gid)
 }
 
 /*
+ * send response in two parts
+ * 1) ProxyHeader
+ * 2) Response or error status
+ * This function should be called with marshaled response
+ * send_response constructs header part and error part only.
+ * send response sends {ProxyHeader,Response} if the request was success
+ * otherwise sends {ProxyHeader,error status}
+ */
+static int send_response(int sock, struct iovec *iovec, int size)
+{
+int retval;
+ProxyHeader header;
+
+/*
+ * If response size exceeds available iovec-iov_len,
+ * we return ENOBUFS
+ */
+if (size  PROXY_MAX_IO_SZ) {
+size = -ENOBUFS;
+}
+
+if (size  0) {
+/*
+ * In case of error we would not have got the error encoded
+ * already so encode the error here.
+ */
+header.type = T_ERROR;
+header.size = sizeof(size);
+proxy_marshal(iovec, PROXY_HDR_SZ, d, size);
+} else {
+header.type = T_SUCCESS;
+header.size = size;
+}
+proxy_marshal(iovec, 0, dd, header.type, header.size);
+retval = socket_write(sock, iovec-iov_base, header.size + PROXY_HDR_SZ);
+if (retval  0) {
+return retval;;
+}
+return 0;
+}
+
+static void stat_to_prstat(ProxyStat *pr_stat, struct stat *stat)
+{
+memset(pr_stat, 0, sizeof(*pr_stat));
+pr_stat-st_dev = stat-st_dev;
+pr_stat-st_ino = stat-st_ino;
+pr_stat-st_nlink = stat-st_nlink;
+pr_stat-st_mode = stat-st_mode;
+pr_stat-st_uid = stat-st_uid;
+pr_stat-st_gid = stat-st_gid;
+pr_stat-st_rdev = stat-st_rdev;
+pr_stat-st_size = stat-st_size;
+pr_stat-st_blksize = stat-st_blksize;
+pr_stat-st_blocks = stat-st_blocks;
+pr_stat-st_atim_sec = stat-st_atim.tv_sec;
+pr_stat-st_atim_nsec = stat-st_atim.tv_nsec;
+pr_stat-st_mtim_sec = stat-st_mtim.tv_sec;
+pr_stat-st_mtim_nsec = stat-st_mtim.tv_nsec;
+pr_stat-st_ctim_sec = stat-st_ctim.tv_sec;
+pr_stat-st_ctim_nsec = stat-st_ctim.tv_nsec;
+}
+
+static void statfs_to_prstatfs(ProxyStatFS *pr_stfs, struct statfs *stfs)
+{
+memset(pr_stfs, 0, sizeof(*pr_stfs));
+pr_stfs-f_type = stfs-f_type;
+pr_stfs-f_bsize = stfs-f_bsize;
+pr_stfs-f_blocks = stfs-f_blocks;
+pr_stfs-f_bfree = stfs-f_bfree;
+pr_stfs-f_bavail = stfs-f_bavail;
+pr_stfs-f_files = stfs-f_files;
+pr_stfs-f_ffree = stfs-f_ffree;
+pr_stfs-f_fsid[0] = stfs-f_fsid.__val[0];
+pr_stfs-f_fsid[1] = stfs-f_fsid.__val[1];
+pr_stfs-f_namelen = stfs-f_namelen;
+pr_stfs-f_frsize = stfs-f_frsize;
+}
+
+/*
+ * Gets stat/statfs information and packs in out_iovec structure
+ * on success returns number of bytes packed in out_iovec struture
+ * otherwise returns -errno
+ */
+static int do_stat(int type, struct iovec *iovec, struct iovec *out_iovec)
+{
+int retval;
+V9fsString path;
+ProxyStat pr_stat;
+ProxyStatFS pr_stfs;
+struct stat st_buf;
+struct statfs stfs_buf;
+
+v9fs_string_init(path);
+retval = proxy_unmarshal(iovec, PROXY_HDR_SZ, s, path);
+if (retval  0) {
+return retval;
+}
+
+switch (type) {
+case T_LSTAT:
+retval = lstat(path.data, st_buf);
+if (retval  0) {
+retval = -errno;
+} else {
+stat_to_prstat(pr_stat, st_buf);
+retval = proxy_marshal(out_iovec, PROXY_HDR_SZ,
+   qqqdddqq, pr_stat.st_dev,
+   pr_stat.st_ino, pr_stat.st_nlink,
+   pr_stat.st_mode, pr_stat.st_uid,
+   pr_stat.st_gid, pr_stat.st_rdev,
+   pr_stat.st_size, pr_stat.st_blksize,
+   pr_stat.st_blocks,
+   pr_stat.st_atim_sec, pr_stat.st_atim_nsec,
+   pr_stat.st_mtim_sec, pr_stat.st_mtim_nsec,
+   pr_stat.st_ctim_sec, pr_stat.st_ctim_nsec);
+}
+break;
+case T_STATFS:
+retval = statfs(path.data, stfs_buf);
+if (retval  0) {
+retval = -errno;
+} else {
+statfs_to_prstatfs(pr_stfs, stfs_buf

[Qemu-devel] [PATCH V5 06/14] hw/9pfs: Open and create files

2011-12-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Add interfaces to open and create files for proxy file system driver.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |  178 -
 hw/9pfs/virtio-9p-proxy.c   |  187 +--
 hw/9pfs/virtio-9p-proxy.h   |   11 +++
 3 files changed, 367 insertions(+), 9 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 5fc2fc4..c0935e3 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -9,6 +9,7 @@
  * the COPYING file in the top-level directory.
  */
 #include stdio.h
+#include sys/socket.h
 #include string.h
 #include sys/un.h
 #include limits.h
@@ -27,6 +28,7 @@
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
+#include fsdev/virtio-9p-marshal.h
 
 #define PROGNAME virtfs-proxy-helper
 
@@ -187,6 +189,139 @@ static int read_request(int sockfd, struct iovec *iovec, 
ProxyHeader *header)
 return 0;
 }
 
+static int send_fd(int sockfd, int fd)
+{
+struct msghdr msg;
+struct iovec iov;
+int retval, data;
+struct cmsghdr *cmsg;
+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  0) {
+/* fd is really negative errno if the request failed  */
+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 (fd = 0) {
+close(fd);
+}
+if (retval  0) {
+return retval;
+}
+return 0;
+}
+
+/*
+ * 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)
+{
+/*
+ * We still need DAC_OVERRIDE because  we don't change
+ * supplementary group ids, and hence may be subjected DAC rules
+ */
+cap_value_t cap_list[] = {
+CAP_DAC_OVERRIDE,
+};
+
+setfsgid(gid);
+setfsuid(uid);
+
+if (uid != 0 || gid != 0) {
+return do_cap_set(cap_list, ARRAY_SIZE(cap_list), 0);
+}
+return 0;
+}
+
+/*
+ * create a file and send fd on success
+ * return -errno on error
+ */
+static int do_create(struct iovec *iovec)
+{
+int ret;
+V9fsString path;
+int flags, mode, uid, gid, cur_uid, cur_gid;
+
+v9fs_string_init(path);
+ret = proxy_unmarshal(iovec, PROXY_HDR_SZ, s,
+  path, flags, mode, uid, gid);
+if (ret  0) {
+goto err_out;
+}
+cur_uid = geteuid();
+cur_gid = getegid();
+ret = setfsugid(uid, gid);
+if (ret  0) {
+/*
+ * On failure reset back to the
+ * old uid/gid
+ */
+ret = -errno;
+goto err_out;
+}
+ret = open(path.data, flags, mode);
+if (ret  0) {
+ret = -errno;
+}
+
+err_out:
+setfsugid(cur_uid, cur_gid);
+v9fs_string_free(path);
+return ret;
+}
+
+/*
+ * open a file and send fd on success
+ * return -errno on error
+ */
+static int do_open(struct iovec *iovec)
+{
+int flags, ret;
+V9fsString path;
+
+v9fs_string_init(path);
+ret = proxy_unmarshal(iovec, PROXY_HDR_SZ, sd, path, flags);
+if (ret  0) {
+goto err_out;
+}
+ret = open(path.data, flags);
+if (ret  0) {
+ret = -errno;
+}
+err_out:
+v9fs_string_free(path);
+return ret;
+}
+
 static void usage(char *prog)
 {
 fprintf(stderr, usage: %s\n
@@ -196,22 +331,59 @@ static void usage(char *prog)
 basename(prog));
 }
 
+static int process_reply(int sock, int type, int retval)
+{
+switch (type) {
+case T_OPEN:
+case T_CREATE:
+if (send_fd(sock, retval)  0) {
+return -1;
+}
+break;
+default:
+return -1;
+break;
+}
+return 0;
+}
+
 static int process_requests(int sock)
 {
-int retval;
+int retval = 0;
 ProxyHeader header;
 struct iovec in_iovec;
 
 in_iovec.iov_base

[Qemu-devel] [PATCH V5 11/14] hw/9pfs: Proxy getversion

2011-12-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Add proxy getversion to get generation number

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |   80 +++
 hw/9pfs/virtio-9p-proxy.c   |   32 +
 hw/9pfs/virtio-9p-proxy.h   |1 +
 3 files changed, 113 insertions(+), 0 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 10dd337..3beed25 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -28,6 +28,11 @@
 #include sys/vfs.h
 #include sys/stat.h
 #include attr/xattr.h
+#include sys/ioctl.h
+#include linux/fs.h
+#ifdef CONFIG_LINUX_MAGIC_H
+#include linux/magic.h
+#endif
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
@@ -35,6 +40,19 @@
 
 #define PROGNAME virtfs-proxy-helper
 
+#ifndef XFS_SUPER_MAGIC
+#define XFS_SUPER_MAGIC  0x58465342
+#endif
+#ifndef EXT2_SUPER_MAGIC
+#define EXT2_SUPER_MAGIC 0xEF53
+#endif
+#ifndef REISERFS_SUPER_MAGIC
+#define REISERFS_SUPER_MAGIC 0x52654973
+#endif
+#ifndef BTRFS_SUPER_MAGIC
+#define BTRFS_SUPER_MAGIC 0x9123683E
+#endif
+
 static struct option helper_opts[] = {
 {fd, required_argument, NULL, 'f'},
 {path, required_argument, NULL, 'p'},
@@ -42,6 +60,7 @@ static struct option helper_opts[] = {
 };
 
 static bool is_daemon;
+static bool get_version; /* IOC getversion IOCTL supported */
 
 static void do_log(int loglevel, const char *format, ...)
 {
@@ -330,6 +349,45 @@ static int send_response(int sock, struct iovec *iovec, 
int size)
 return 0;
 }
 
+/*
+ * gets generation number
+ * returns -errno on failure and sizeof(generation number) on success
+ */
+static int do_getversion(struct iovec *iovec, struct iovec *out_iovec)
+{
+V9fsString path;
+uint64_t version;
+int fd, retval = -ENOTTY;
+
+/* no need to issue ioctl */
+if (!get_version) {
+version = 0;
+retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, q, version);
+return retval;
+}
+#ifdef FS_IOC_GETVERSION
+retval = proxy_unmarshal(iovec, PROXY_HDR_SZ, s, path);
+if (retval  0) {
+return retval;
+}
+
+fd = open(path.data, O_RDONLY);
+if (fd  0) {
+retval = -errno;
+goto err_out;
+}
+if (ioctl(fd, FS_IOC_GETVERSION, version)  0) {
+retval = -errno;
+} else {
+retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, q, version);
+}
+close(fd);
+err_out:
+v9fs_string_free(path);
+#endif
+return retval;
+}
+
 static int do_getxattr(int type, struct iovec *iovec, struct iovec *out_iovec)
 {
 int size = 0, offset, retval;
@@ -672,6 +730,7 @@ static int process_reply(int sock, int type,
 case T_READLINK:
 case T_LGETXATTR:
 case T_LLISTXATTR:
+case T_GETVERSION:
 if (send_response(sock, out_iovec, retval)  0) {
 return -1;
 }
@@ -854,6 +913,9 @@ static int process_requests(int sock)
 v9fs_string_free(path);
 v9fs_string_free(name);
 break;
+case T_GETVERSION:
+retval = do_getversion(in_iovec, out_iovec);
+break;
 default:
 goto err_out;
 break;
@@ -875,6 +937,8 @@ int main(int argc, char **argv)
 char *rpath = NULL;
 struct stat stbuf;
 int c, option_index;
+int retval;
+struct statfs st_fs;
 
 is_daemon = true;
 sock = -1;
@@ -931,6 +995,22 @@ int main(int argc, char **argv)
 
 do_log(LOG_INFO, Started\n);
 
+get_version = false;
+#ifdef FS_IOC_GETVERSION
+/* check whether underlying FS support IOC_GETVERSION */
+retval = statfs(rpath, st_fs);
+if (!retval) {
+switch (st_fs.f_type) {
+case EXT2_SUPER_MAGIC:
+case BTRFS_SUPER_MAGIC:
+case REISERFS_SUPER_MAGIC:
+case XFS_SUPER_MAGIC:
+get_version = true;
+break;
+}
+}
+#endif
+
 if (chdir(/)  0) {
 do_perror(chdir);
 goto error;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 983d319..e782c4f 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -243,6 +243,9 @@ static int v9fs_receive_response(V9fsProxy *proxy, int type,
 v9fs_string_free(xattr);
 break;
 }
+case T_GETVERSION:
+proxy_unmarshal(reply, PROXY_HDR_SZ, q, response);
+break;
 default:
 return -1;
 }
@@ -509,6 +512,14 @@ static int v9fs_request(V9fsProxy *proxy, int type,
 header.type = T_LREMOVEXATTR;
 }
 break;
+case T_GETVERSION:
+path = va_arg(ap, V9fsString *);
+retval = proxy_marshal(iovec, PROXY_HDR_SZ, s, path);
+if (retval  0) {
+header.size = retval;
+header.type = T_GETVERSION;
+}
+break;
 default:
 error_report(Invalid type %d\n, type);
 retval = -EINVAL;
@@ -559,6 +570,7 @@ static

[Qemu-devel] [PATCH V5 04/14] hw/9pfs: Add new proxy filesystem driver

2011-12-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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,socket_fd=socket-fd

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 Makefile.objs |1 +
 fsdev/qemu-fsdev.c|1 +
 fsdev/qemu-fsdev.h|1 +
 hw/9pfs/virtio-9p-proxy.c |  388 +
 hw/9pfs/virtio-9p-proxy.h |   24 +++
 qemu-config.c |6 +
 vl.c  |6 +-
 7 files changed, 426 insertions(+), 1 deletions(-)
 create mode 100644 hw/9pfs/virtio-9p-proxy.c
 create mode 100644 hw/9pfs/virtio-9p-proxy.h

diff --git a/Makefile.objs b/Makefile.objs
index 1ca8369..1696675 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -312,6 +312,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-synth.o
 9pfs-nested-$(CONFIG_OPEN_BY_HANDLE) +=  virtio-9p-handle.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 00f48ab..e20202a 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -27,6 +27,7 @@ static FsDriverTable FsDrivers[] = {
 { .name = handle, .ops = handle_ops},
 #endif
 { .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/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
new file mode 100644
index 000..3e4dc68
--- /dev/null
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -0,0 +1,388 @@
+/*
+ * Virtio 9p Proxy callback
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * M. Mohan Kumar mo...@in.ibm.com
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+#include sys/socket.h
+#include sys/un.h
+#include hw/virtio.h
+#include virtio-9p.h
+#include fsdev/qemu-fsdev.h
+#include virtio-9p-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

[Qemu-devel] [PATCH V5 01/14] hw/9pfs: Move opt validation to FsDriver callback

2011-12-14 Thread M. Mohan Kumar
From: Aneesh Kumar K.V aneesh.ku...@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.ku...@linux.vnet.ibm.com
Signed-off-by: M. Mohan Kumar mo...@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 a85ecd3..73de79f 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   0x001C
 
 
+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 6684f7e..00f48ab 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -31,12 +31,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);
 
@@ -61,29 +59,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;
@@ -95,22 +73,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 cd343e1..642d5e2

[Qemu-devel] [PATCH V5 00/14] Proxy FS driver for VirtFS

2011-12-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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)

Changes from previous version V4:
* Handle the case request message  PROXY_MAX_IO_SZ as fatal, instead of
  recovering.
* Changed size data type to unsigned for both ProxyHeader and V9fsString
* Added chdir(/) before doing chroot()
* Code changes due to changing ProxyHeader size type to unsigned

Changes from previous version V3:
* Lots of code change involving
* Improve error handling in marshaling/unmarshaling code
* Return ENOBUFS when request/response size exceeds maximum buffer size

Changes from previous version V2:
* Added check to handle failures in marshaling/unmarshaling code. Also make
  sure that request/response will not exceed maximum buffer size (BUFF_SZ)
* Addressed Stefan's review comments

Changes from previous version:
*) Communication between qemu and helper process is similar to 9p way of packing
elements (pdu marshaling).

Aneesh Kumar K.V (1):
  hw/9pfs: Move opt validation to FsDriver callback

M. Mohan Kumar (13):
  hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file
  hw/9pfs: Add validation to {un}marshal code
  hw/9pfs: Add new proxy filesystem driver
  hw/9pfs: File system helper process for qemu 9p 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
  hw/9pfs: Add support to use named socket for proxy FS

 Makefile   |   15 +-
 Makefile.objs  |3 +-
 configure  |   19 +
 fsdev/file-op-9p.h |   17 +-
 fsdev/qemu-fsdev.c |   45 +--
 fsdev/qemu-fsdev.h |   11 +-
 fsdev/virtfs-proxy-helper.c| 1113 
 fsdev/virtfs-proxy-helper.texi |   63 +++
 fsdev/virtio-9p-marshal.c  |  360 
 fsdev/virtio-9p-marshal.h  |   90 +++
 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-proxy.c  | 1210 
 hw/9pfs/virtio-9p-proxy.h  |   95 
 hw/9pfs/virtio-9p.c|  756 --
 hw/9pfs/virtio-9p.h|   83 +---
 qemu-config.c  |   13 +
 qemu-options.hx|   32 +-
 vl.c   |   18 +-
 20 files changed, 3448 insertions(+), 562 deletions(-)
 create mode 100644 fsdev/virtfs-proxy-helper.c
 create mode 100644 fsdev/virtfs-proxy-helper.texi
 create mode 100644 fsdev/virtio-9p-marshal.c
 create mode 100644 fsdev/virtio-9p-marshal.h
 create mode 100644 hw/9pfs/virtio-9p-proxy.c
 create mode 100644 hw/9pfs/virtio-9p-proxy.h

-- 
1.7.6




[Qemu-devel] [PATCH V5 13/14] hw/9pfs: man page for proxy helper

2011-12-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 Makefile   |   12 +++-
 fsdev/virtfs-proxy-helper.texi |   59 
 2 files changed, 70 insertions(+), 1 deletions(-)
 create mode 100644 fsdev/virtfs-proxy-helper.texi

diff --git a/Makefile b/Makefile
index 0acad52..f5b3524 100644
--- a/Makefile
+++ b/Makefile
@@ -38,6 +38,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+=fsdev/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) fsdev/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
@@ -367,6 +371,12 @@ qemu-img.1: qemu-img.texi qemu-img-cmds.texi
  pod2man --section=1 --center=  --release=  qemu-img.pod  $@, \
GEN   $@)
 
+fsdev/virtfs-proxy-helper.1: fsdev/virtfs-proxy-helper.texi
+   $(call quiet-command, \
+ perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $ 
fsdev/virtfs-proxy-helper.pod  \
+ pod2man --section=1 --center=  --release=  
fsdev/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/fsdev/virtfs-proxy-helper.texi b/fsdev/virtfs-proxy-helper.texi
new file mode 100644
index 000..3816382
--- /dev/null
+++ b/fsdev/virtfs-proxy-helper.texi
@@ -0,0 +1,59 @@
+@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 -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




[Qemu-devel] [PATCH V5 03/14] hw/9pfs: Add validation to {un}marshal code

2011-12-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
Signed-off-by: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com
---
 fsdev/virtio-9p-marshal.c |  148 --
 fsdev/virtio-9p-marshal.h |   19 +-
 hw/9pfs/virtio-9p.c   |  467 +
 3 files changed, 438 insertions(+), 196 deletions(-)

diff --git a/fsdev/virtio-9p-marshal.c b/fsdev/virtio-9p-marshal.c
index 029c29e..198665d 100644
--- a/fsdev/virtio-9p-marshal.c
+++ b/fsdev/virtio-9p-marshal.c
@@ -20,17 +20,12 @@
 #include sys/uio.h
 #include string.h
 #include stdint.h
+#include errno.h
 
 #include compiler.h
 #include virtio-9p-marshal.h
 #include bswap.h
 
-void v9fs_string_init(V9fsString *str)
-{
-str-data = NULL;
-str-size = 0;
-}
-
 void v9fs_string_free(V9fsString *str)
 {
 g_free(str-data);
@@ -62,11 +57,13 @@ void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
 }
 
 
-static size_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count,
-  size_t offset, size_t size, int pack)
+static ssize_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;
+size_t req_size = size;
+
 
 for (i = 0; size  i  sg_count; i++) {
 size_t len;
@@ -90,18 +87,23 @@ static size_t v9fs_packunpack(void *addr, struct iovec *sg, 
int sg_count,
 }
 }
 }
-
+if (copied  req_size) {
+/*
+ * We copied less that requested size. error out
+ */
+return -ENOBUFS;
+}
 return copied;
 }
 
-static size_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num,
-  size_t offset, size_t size)
+static ssize_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)
+ssize_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);
 }
@@ -131,11 +133,12 @@ static int v9fs_copy_sg(struct iovec *src_sg, unsigned 
int num,
 return j;
 }
 
-size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
-  int bswap, const char *fmt, ...)
+ssize_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
+   int bswap, const char *fmt, ...)
 {
 int i;
 va_list ap;
+ssize_t copied;
 size_t old_offset = offset;
 
 va_start(ap, fmt);
@@ -143,13 +146,13 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, 
size_t offset,
 switch (fmt[i]) {
 case 'b': {
 uint8_t *valp = va_arg(ap, uint8_t *);
-offset += v9fs_unpack(valp, out_sg, out_num, offset, 
sizeof(*valp));
+copied = 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));
+copied = v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
 if (bswap) {
 *valp = le16_to_cpu(val);
 } else {
@@ -160,7 +163,7 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, 
size_t offset,
 case 'd': {
 uint32_t val, *valp;
 valp = va_arg(ap, uint32_t *);
-offset += v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
+copied = v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
 if (bswap) {
 *valp = le32_to_cpu(val);
 } else {
@@ -171,7 +174,7 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, 
size_t offset,
 case 'q': {
 uint64_t val, *valp;
 valp = va_arg(ap, uint64_t *);
-offset += v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
+copied = v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
 if (bswap) {
 *valp = le64_to_cpu(val);
 } else {
@@ -187,59 +190,70 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, 
size_t offset,
 }
 case 's': {
 V9fsString *str = va_arg(ap, V9fsString *);
-offset += v9fs_unmarshal(out_sg, out_num, offset, bswap,
-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;
+copied = v9fs_unmarshal(out_sg

[Qemu-devel] [PATCH V5 02/14] hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file

2011-12-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@in.ibm.com
---
 Makefile.objs |2 +-
 fsdev/virtio-9p-marshal.c |  338 +
 fsdev/virtio-9p-marshal.h |   87 
 hw/9pfs/virtio-9p.c   |  297 +---
 hw/9pfs/virtio-9p.h   |   83 +--
 5 files changed, 438 insertions(+), 369 deletions(-)
 create mode 100644 fsdev/virtio-9p-marshal.c
 create mode 100644 fsdev/virtio-9p-marshal.h

diff --git a/Makefile.objs b/Makefile.objs
index 3a699ee..1ca8369 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -61,7 +61,7 @@ ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
 # Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
 # only pull in the actual virtio-9p device if we also enabled virtio.
 CONFIG_REALLY_VIRTFS=y
-fsdev-nested-y = qemu-fsdev.o
+fsdev-nested-y = qemu-fsdev.o virtio-9p-marshal.o
 else
 fsdev-nested-y = qemu-fsdev-dummy.o
 endif
diff --git a/fsdev/virtio-9p-marshal.c b/fsdev/virtio-9p-marshal.c
new file mode 100644
index 000..029c29e
--- /dev/null
+++ b/fsdev/virtio-9p-marshal.c
@@ -0,0 +1,338 @@
+/*
+ * Virtio 9p backend
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   aligu...@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 glib.h
+#include glib/gprintf.h
+#include sys/types.h
+#include dirent.h
+#include sys/time.h
+#include utime.h
+#include sys/uio.h
+#include string.h
+#include stdint.h
+
+#include compiler.h
+#include virtio-9p-marshal.h
+#include bswap.h
+
+void v9fs_string_init(V9fsString *str)
+{
+str-data = NULL;
+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);
+}
+
+void GCC_FMT_ATTR(2, 3)
+v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
+{
+va_list ap;
+
+v9fs_string_free(str);
+
+va_start(ap, fmt);
+str-size = g_vasprintf(str-data, fmt, ap);
+va_end(ap);
+}
+
+void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
+{
+v9fs_string_free(lhs);
+v9fs_string_sprintf(lhs, %s, rhs-data);
+}
+
+
+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)
+{
+int i, j;
+size_t pos = 0;
+
+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,
+  int bswap, const char *fmt, ...)
+{
+int i;
+va_list ap;
+size_t old_offset = offset;
+
+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

[Qemu-devel] [PATCH V5 09/14] hw/9pfs: File ownership and others

2011-12-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@in.ibm.com
---
 Makefile|2 +-
 fsdev/virtfs-proxy-helper.c |   83 ++
 hw/9pfs/virtio-9p-proxy.c   |  136 +++
 hw/9pfs/virtio-9p-proxy.h   |6 ++
 4 files changed, 214 insertions(+), 13 deletions(-)

diff --git a/Makefile b/Makefile
index 1906c5e..0acad52 100644
--- a/Makefile
+++ b/Makefile
@@ -154,7 +154,7 @@ qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
 qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
 qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
 
-fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o 
fsdev/virtio-9p-marshal.o
+fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o 
fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y)
 fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
 
 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 5989b35..2c1e2c7 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -598,6 +598,12 @@ static int process_reply(int sock, int type,
 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:
 if (send_status(sock, out_iovec, retval)  0) {
 return -1;
 }
@@ -619,7 +625,10 @@ static int process_reply(int sock, int type,
 static int process_requests(int sock)
 {
 int retval = 0;
+uint64_t offset;
 ProxyHeader header;
+int mode, uid, gid;
+struct timespec spec[2];
 V9fsString oldpath, path;
 struct iovec in_iovec, out_iovec;
 
@@ -672,6 +681,80 @@ static int process_requests(int sock)
 case T_READLINK:
 retval = do_readlink(in_iovec, out_iovec);
 break;
+case T_CHMOD:
+v9fs_string_init(path);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ,
+ sd, path, mode);
+if (retval  0) {
+retval = chmod(path.data, mode);
+if (retval  0) {
+retval = -errno;
+}
+}
+v9fs_string_free(path);
+break;
+case T_CHOWN:
+v9fs_string_init(path);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ, sdd, path,
+ uid, gid);
+if (retval  0) {
+retval = lchown(path.data, uid, gid);
+if (retval  0) {
+retval = -errno;
+}
+}
+v9fs_string_free(path);
+break;
+case T_TRUNCATE:
+v9fs_string_init(path);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ, sq,
+ path, offset);
+if (retval  0) {
+retval = truncate(path.data, offset);
+if (retval  0) {
+retval = -errno;
+}
+}
+v9fs_string_free(path);
+break;
+case T_UTIME:
+v9fs_string_init(path);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ, s, path,
+ spec[0].tv_sec, spec[0].tv_nsec,
+ spec[1].tv_sec, spec[1].tv_nsec);
+if (retval  0) {
+retval = qemu_utimens(path.data, spec);
+if (retval  0) {
+retval = -errno;
+}
+}
+v9fs_string_free(path);
+break;
+case T_RENAME:
+v9fs_string_init(path);
+v9fs_string_init(oldpath);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ,
+ ss, oldpath, path);
+if (retval  0) {
+retval = rename(oldpath.data, path.data);
+if (retval  0) {
+retval = -errno;
+}
+}
+v9fs_string_free(oldpath);
+v9fs_string_free(path);
+break;
+case T_REMOVE:
+v9fs_string_init(path);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ, s, path);
+if (retval  0) {
+retval = remove(path.data);
+if (retval  0) {
+retval = -errno;
+}
+}
+v9fs_string_free(path);
+break;
 default:
 goto err_out;
 break;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 9fdcfd6..cb6e4cd 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -287,7 +287,9

[Qemu-devel] [PATCH V5 14/14] hw/9pfs: Add support to use named socket for proxy FS

2011-12-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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. We can achive the same using a shell script over
qemu and virtfs-proxy-helper using exec fdsocket-path, and then
passing that fd as argument to qemu and virtfs-proxy-helper. Also having
a server like virtfs-proxy-helper listening on a pathname without any
authentication is little bit scary. So we have to decide whether this
patch is really needed.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
Signed-off-by: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com
---
 fsdev/file-op-9p.h |2 +
 fsdev/virtfs-proxy-helper.c|   86 ++-
 fsdev/virtfs-proxy-helper.texi |4 ++
 hw/9pfs/virtio-9p-proxy.c  |   52 +---
 qemu-config.c  |7 +++
 qemu-options.hx|   15 +--
 vl.c   |6 ++-
 7 files changed, 157 insertions(+), 15 deletions(-)

diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 73de79f..4f76f9d 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -57,6 +57,8 @@ typedef struct extended_ops {
  */
 #define V9FS_SM_NONE0x0010
 #define V9FS_RDONLY 0x0020
+#define V9FS_PROXY_SOCK_FD  0x0040
+#define V9FS_PROXY_SOCK_NAME0x0080
 
 #define V9FS_SEC_MASK   0x001C
 
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 3beed25..baafee2 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -57,6 +57,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'},
 };
 
 static bool is_daemon;
@@ -690,11 +693,61 @@ err_out:
 return ret;
 }
 
+/* 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));
 }
@@ -935,16 +988,20 @@ int main(int argc, char **argv)
 {
 int sock;
 char *rpath = NULL;
+char *sock_name = NULL;
 struct stat stbuf;
 int c, option_index;
 int retval;
 struct statfs st_fs;
+uid_t own_u;
+gid_t own_g;
 
 is_daemon = true;
 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;
@@ -959,6 +1016,15 @@ int main(int argc, char **argv)
 case 'f':
 sock = atoi(optarg);
 break;
+case 's':
+sock_name = strdup(optarg);
+break;
+case 'u':
+own_u = atoi(optarg);
+break;
+case 'g':
+own_g = atoi(optarg);
+break;
 case '?':
 case 'h':
 default:
@@ -968,8 +1034,16 @@ int main(int argc, char **argv)
 }
 
 /* Parameter validation */
-if (sock == -1 || rpath == NULL) {
-fprintf(stderr, socket descriptor or path not specified\n);
+if ((sock_name == NULL  sock == -1) || rpath == NULL) {
+fprintf(stderr

[Qemu-devel] [PATCH V5 07/14] hw/9pfs: Create other filesystem objects

2011-12-14 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |  129 ++--
 hw/9pfs/virtio-9p-proxy.c   |  199 +++
 hw/9pfs/virtio-9p-proxy.h   |8 ++-
 3 files changed, 313 insertions(+), 23 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index c0935e3..cdad310 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -231,6 +231,30 @@ static int send_fd(int sockfd, int fd)
 return 0;
 }
 
+static int send_status(int sockfd, struct iovec *iovec, int status)
+{
+ProxyHeader header;
+int retval, msg_size;;
+
+if (status  0) {
+header.type = T_ERROR;
+} else {
+header.type = T_SUCCESS;
+}
+header.size = sizeof(status);
+/*
+ * marshal the return status. We don't check error.
+ * because we are sure we have enough space for the status
+ */
+msg_size = proxy_marshal(iovec, 0, ddd, header.type,
+ header.size, status);
+retval = socket_write(sockfd, iovec-iov_base, msg_size);
+if (retval  0) {
+return retval;
+}
+return 0;
+}
+
 /*
  * from man 7 capabilities, section
  * Effect of User ID Changes on Capabilities:
@@ -262,6 +286,67 @@ static int setfsugid(int uid, int gid)
 }
 
 /*
+ * create other filesystem objects and send 0 on success
+ * return -errno on error
+ */
+static int do_create_others(int type, struct iovec *iovec)
+{
+dev_t rdev;
+int retval = 0;
+int offset = PROXY_HDR_SZ;
+V9fsString oldpath, path;
+int mode, uid, gid, cur_uid, cur_gid;
+
+v9fs_string_init(path);
+v9fs_string_init(oldpath);
+cur_uid = geteuid();
+cur_gid = getegid();
+
+retval = proxy_unmarshal(iovec, offset, dd, uid, gid);
+if (retval  0) {
+return retval;
+}
+offset += retval;
+retval = setfsugid(uid, gid);
+if (retval  0) {
+retval = -errno;
+goto err_out;
+}
+switch (type) {
+case T_MKNOD:
+retval = proxy_unmarshal(iovec, offset, sdq, path, mode, rdev);
+if (retval  0) {
+goto err_out;
+}
+retval = mknod(path.data, mode, rdev);
+break;
+case T_MKDIR:
+retval = proxy_unmarshal(iovec, offset, sd, path, mode);
+if (retval  0) {
+goto err_out;
+}
+retval = mkdir(path.data, mode);
+break;
+case T_SYMLINK:
+retval = proxy_unmarshal(iovec, offset, ss, oldpath, path);
+if (retval  0) {
+goto err_out;
+}
+retval = symlink(oldpath.data, path.data);
+break;
+}
+if (retval  0) {
+retval = -errno;
+}
+
+err_out:
+v9fs_string_free(path);
+v9fs_string_free(oldpath);
+setfsugid(cur_uid, cur_gid);
+return retval;
+}
+
+/*
  * create a file and send fd on success
  * return -errno on error
  */
@@ -331,7 +416,8 @@ static void usage(char *prog)
 basename(prog));
 }
 
-static int process_reply(int sock, int type, int retval)
+static int process_reply(int sock, int type,
+ struct iovec *out_iovec, int retval)
 {
 switch (type) {
 case T_OPEN:
@@ -340,6 +426,14 @@ static int process_reply(int sock, int type, int retval)
 return -1;
 }
 break;
+case T_MKNOD:
+case T_MKDIR:
+case T_SYMLINK:
+case T_LINK:
+if (send_status(sock, out_iovec, retval)  0) {
+return -1;
+}
+break;
 default:
 return -1;
 break;
@@ -351,10 +445,14 @@ static int process_requests(int sock)
 {
 int retval = 0;
 ProxyHeader header;
-struct iovec in_iovec;
+V9fsString oldpath, path;
+struct iovec in_iovec, out_iovec;
+
+in_iovec.iov_base  = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
+in_iovec.iov_len   = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
+out_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
+out_iovec.iov_len  = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
 
-in_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
-in_iovec.iov_len  = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
 while (1) {
 /*
  * initialize the header type, so that we send
@@ -373,18 +471,37 @@ static int process_requests(int sock)
 case T_CREATE:
 retval = do_create(in_iovec);
 break;
+case T_MKNOD:
+case T_MKDIR:
+case T_SYMLINK:
+retval = do_create_others(header.type, in_iovec);
+break;
+case T_LINK:
+v9fs_string_init(path);
+v9fs_string_init(oldpath);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ,
+ ss, oldpath, path);
+if (retval  0

Re: [Qemu-devel] [PATCH V4 00/13] Proxy FS driver for VirtFS

2011-12-09 Thread M. Mohan Kumar
On Thursday, December 08, 2011 11:16:33 PM Stefan Hajnoczi wrote:
 On Mon, Dec 05, 2011 at 09:48:37PM +0530, M. Mohan Kumar wrote:
  From: M. Mohan Kumar mo...@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.
 
 Fails to build against qemu.git/master (217bfb4):
 
   CClibhw64/9pfs/virtio-9p-proxy.o
 hw/9pfs/virtio-9p-proxy.c:1195:5: error: unknown field ‘parse_opts’
 specified in initializer hw/9pfs/virtio-9p-proxy.c:1195:5: warning:
 initialization from incompatible pointer type [enabled by default]
 hw/9pfs/virtio-9p-proxy.c:1195:5: warning: (near initialization for
 ‘proxy_ops.init’) [enabled by default]
 
 Is this against another public tree?


Sorry, It depends on Aneesh's patch Move opt validation to FsDriver callback  
http://lists.gnu.org/archive/html/qemu-devel/2011-11/msg00275.html




Re: [Qemu-devel] [PATCH V4 04/13] hw/9pfs: File system helper process for qemu 9p proxy FS

2011-12-09 Thread M. Mohan Kumar
On Friday, December 09, 2011 12:01:14 AM Stefan Hajnoczi wrote:
 On Mon, Dec 05, 2011 at 09:48:41PM +0530, M. Mohan Kumar wrote:
  +static int read_request(int sockfd, struct iovec *iovec, ProxyHeader
  *header) +{
  +int retval;
  +
  +/*
  + * read the request header.
  + */
  +iovec-iov_len = 0;
  +retval = socket_read(sockfd, iovec-iov_base, PROXY_HDR_SZ);
  +if (retval  0) {
  +return retval;
  +}
  +iovec-iov_len = PROXY_HDR_SZ;
  +retval = proxy_unmarshal(iovec, 0, dd, header-type,
  header-size); +if (retval  0) {
  +return retval;
  +}
  +/*
  + * We can't process message.size  PROXY_MAX_IO_SZ, read the
  complete + * message from the socket and ignore it. This ensures
  that + * we can correctly handle the next request. We also return + 
 * ENOBUFS as error to indicate we ran out of buffer space. + */
  +if (header-size  PROXY_MAX_IO_SZ) {
  +int count, size;
  +size = header-size;
  +while (size  0) {
  +count = MIN(PROXY_MAX_IO_SZ, size);
  +count = socket_read(sockfd, iovec-iov_base + PROXY_HDR_SZ,
  count); +if (count  0) {
  +return count;
  +}
  +size -= count;
  +}
 
 I'm not sure recovery attempts are worthwhile here.  The client is
 buggy, perhaps just refuse further work.

But whats the issue in trying to recover in this case?
 
  +return -ENOBUFS;
  +}
 
 header-size is (signed) int and we didn't check for header-size  0.
 Please use an unsigned type.

I will fix in next version

 
  +if (chroot(rpath)  0) {
  +do_perror(chroot);
  +goto error;
  +}
  +umask(0);
 
 We haven't changed into the chroot yet, we need chdir(/).  Otherwise
 the current working directory is outside the chroot (and allows trivial
 escape).
I will fix in next version




[Qemu-devel] [PATCH V4 01/13] hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file

2011-12-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@in.ibm.com
---
 Makefile.objs |2 +-
 fsdev/virtio-9p-marshal.c |  338 +
 fsdev/virtio-9p-marshal.h |   87 
 hw/9pfs/virtio-9p.c   |  297 +---
 hw/9pfs/virtio-9p.h   |   83 +--
 5 files changed, 438 insertions(+), 369 deletions(-)
 create mode 100644 fsdev/virtio-9p-marshal.c
 create mode 100644 fsdev/virtio-9p-marshal.h

diff --git a/Makefile.objs b/Makefile.objs
index 3a699ee..1ca8369 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -61,7 +61,7 @@ ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
 # Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
 # only pull in the actual virtio-9p device if we also enabled virtio.
 CONFIG_REALLY_VIRTFS=y
-fsdev-nested-y = qemu-fsdev.o
+fsdev-nested-y = qemu-fsdev.o virtio-9p-marshal.o
 else
 fsdev-nested-y = qemu-fsdev-dummy.o
 endif
diff --git a/fsdev/virtio-9p-marshal.c b/fsdev/virtio-9p-marshal.c
new file mode 100644
index 000..029c29e
--- /dev/null
+++ b/fsdev/virtio-9p-marshal.c
@@ -0,0 +1,338 @@
+/*
+ * Virtio 9p backend
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   aligu...@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 glib.h
+#include glib/gprintf.h
+#include sys/types.h
+#include dirent.h
+#include sys/time.h
+#include utime.h
+#include sys/uio.h
+#include string.h
+#include stdint.h
+
+#include compiler.h
+#include virtio-9p-marshal.h
+#include bswap.h
+
+void v9fs_string_init(V9fsString *str)
+{
+str-data = NULL;
+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);
+}
+
+void GCC_FMT_ATTR(2, 3)
+v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
+{
+va_list ap;
+
+v9fs_string_free(str);
+
+va_start(ap, fmt);
+str-size = g_vasprintf(str-data, fmt, ap);
+va_end(ap);
+}
+
+void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
+{
+v9fs_string_free(lhs);
+v9fs_string_sprintf(lhs, %s, rhs-data);
+}
+
+
+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)
+{
+int i, j;
+size_t pos = 0;
+
+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,
+  int bswap, const char *fmt, ...)
+{
+int i;
+va_list ap;
+size_t old_offset = offset;
+
+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

[Qemu-devel] [PATCH V4 05/13] hw/9pfs: Open and create files

2011-12-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Add interfaces to open and create files for proxy file system driver.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |  191 ++-
 hw/9pfs/virtio-9p-proxy.c   |  189 +--
 hw/9pfs/virtio-9p-proxy.h   |   11 +++
 3 files changed, 382 insertions(+), 9 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 7670a0e..241fcff 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -9,6 +9,7 @@
  * the COPYING file in the top-level directory.
  */
 #include stdio.h
+#include sys/socket.h
 #include string.h
 #include sys/un.h
 #include limits.h
@@ -27,6 +28,7 @@
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
+#include fsdev/virtio-9p-marshal.h
 
 #define PROGNAME virtfs-proxy-helper
 
@@ -199,6 +201,139 @@ static int read_request(int sockfd, struct iovec *iovec, 
ProxyHeader *header)
 return 0;
 }
 
+static int send_fd(int sockfd, int fd)
+{
+struct msghdr msg;
+struct iovec iov;
+int retval, data;
+struct cmsghdr *cmsg;
+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  0) {
+/* fd is really negative errno if the request failed  */
+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 (fd = 0) {
+close(fd);
+}
+if (retval  0) {
+return retval;
+}
+return 0;
+}
+
+/*
+ * 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)
+{
+/*
+ * We still need DAC_OVERRIDE because  we don't change
+ * supplementary group ids, and hence may be subjected DAC rules
+ */
+cap_value_t cap_list[] = {
+CAP_DAC_OVERRIDE,
+};
+
+setfsgid(gid);
+setfsuid(uid);
+
+if (uid != 0 || gid != 0) {
+return do_cap_set(cap_list, ARRAY_SIZE(cap_list), 0);
+}
+return 0;
+}
+
+/*
+ * create a file and send fd on success
+ * return -errno on error
+ */
+static int do_create(struct iovec *iovec)
+{
+int ret;
+V9fsString path;
+int flags, mode, uid, gid, cur_uid, cur_gid;
+
+v9fs_string_init(path);
+ret = proxy_unmarshal(iovec, PROXY_HDR_SZ, s,
+  path, flags, mode, uid, gid);
+if (ret  0) {
+goto err_out;
+}
+cur_uid = geteuid();
+cur_gid = getegid();
+ret = setfsugid(uid, gid);
+if (ret  0) {
+/*
+ * On failure reset back to the
+ * old uid/gid
+ */
+ret = -errno;
+goto err_out;
+}
+ret = open(path.data, flags, mode);
+if (ret  0) {
+ret = -errno;
+}
+
+err_out:
+setfsugid(cur_uid, cur_gid);
+v9fs_string_free(path);
+return ret;
+}
+
+/*
+ * open a file and send fd on success
+ * return -errno on error
+ */
+static int do_open(struct iovec *iovec)
+{
+int flags, ret;
+V9fsString path;
+
+v9fs_string_init(path);
+ret = proxy_unmarshal(iovec, PROXY_HDR_SZ, sd, path, flags);
+if (ret  0) {
+goto err_out;
+}
+ret = open(path.data, flags);
+if (ret  0) {
+ret = -errno;
+}
+err_out:
+v9fs_string_free(path);
+return ret;
+}
+
 static void usage(char *prog)
 {
 fprintf(stderr, usage: %s\n
@@ -208,22 +343,72 @@ static void usage(char *prog)
 basename(prog));
 }
 
+static int process_reply(int sock, int type, int retval)
+{
+switch (type) {
+case T_OPEN:
+case T_CREATE:
+if (send_fd(sock, retval)  0) {
+return -1;
+}
+break;
+default:
+return -1;
+break;
+}
+return 0;
+}
+
 static int process_requests(int sock)
 {
-int retval;
+int retval = 0;
 ProxyHeader header;
 struct iovec in_iovec;
 
 in_iovec.iov_base

[Qemu-devel] [PATCH V4 03/13] hw/9pfs: Add new proxy filesystem driver

2011-12-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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,socket_fd=socket-fd

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 Makefile.objs |1 +
 fsdev/qemu-fsdev.c|1 +
 fsdev/qemu-fsdev.h|1 +
 hw/9pfs/virtio-9p-proxy.c |  388 +
 hw/9pfs/virtio-9p-proxy.h |   24 +++
 qemu-config.c |6 +
 vl.c  |6 +-
 7 files changed, 426 insertions(+), 1 deletions(-)
 create mode 100644 hw/9pfs/virtio-9p-proxy.c
 create mode 100644 hw/9pfs/virtio-9p-proxy.h

diff --git a/Makefile.objs b/Makefile.objs
index 1ca8369..1696675 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -312,6 +312,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-synth.o
 9pfs-nested-$(CONFIG_OPEN_BY_HANDLE) +=  virtio-9p-handle.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 00f48ab..e20202a 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -27,6 +27,7 @@ static FsDriverTable FsDrivers[] = {
 { .name = handle, .ops = handle_ops},
 #endif
 { .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/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
new file mode 100644
index 000..3e4dc68
--- /dev/null
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -0,0 +1,388 @@
+/*
+ * Virtio 9p Proxy callback
+ *
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * M. Mohan Kumar mo...@in.ibm.com
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+#include sys/socket.h
+#include sys/un.h
+#include hw/virtio.h
+#include virtio-9p.h
+#include fsdev/qemu-fsdev.h
+#include virtio-9p-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

[Qemu-devel] [PATCH V4 04/13] hw/9pfs: File system helper process for qemu 9p proxy FS

2011-12-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 -f|--fd socket descriptor -p|--path path-to-share

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 Makefile|3 +
 configure   |   19 +++
 fsdev/virtfs-proxy-helper.c |  308 +++
 hw/9pfs/virtio-9p-proxy.h   |9 ++
 4 files changed, 339 insertions(+), 0 deletions(-)
 create mode 100644 fsdev/virtfs-proxy-helper.c

diff --git a/Makefile b/Makefile
index 301c75e..1906c5e 100644
--- a/Makefile
+++ b/Makefile
@@ -154,6 +154,9 @@ qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
 qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
 qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
 
+fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o 
fsdev/virtio-9p-marshal.o
+fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
+
 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 ac4840d..4ecdb1c 100755
--- a/configure
+++ b/configure
@@ -1938,6 +1938,22 @@ 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
+  else
+cap=no
+  fi
+fi
+
+##
 # pthread probe
 PTHREADLIBS_LIST=-pthread -lpthread -lpthreadGC2
 
@@ -2735,6 +2751,9 @@ confdir=$sysconfdir$confsuffix
 tools=
 if test $softmmu = yes ; then
   tools=qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools
+  if [ $cap = yes -a $linux = yes ] ; then
+  tools=$tools fsdev/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
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
new file mode 100644
index 000..7670a0e
--- /dev/null
+++ b/fsdev/virtfs-proxy-helper.c
@@ -0,0 +1,308 @@
+/*
+ * Helper for QEMU Proxy FS Driver
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * M. Mohan Kumar mo...@in.ibm.com
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#include stdio.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/capability.h
+#include sys/fsuid.h
+#include stdarg.h
+#include stdbool.h
+#include qemu-common.h
+#include virtio-9p-marshal.h
+#include hw/9pfs/virtio-9p-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'},
+};
+
+static bool is_daemon;
+
+static void do_log(int loglevel, const char *format, ...)
+{
+va_list ap;
+
+va_start(ap, format);
+if (is_daemon) {
+vsyslog(LOG_CRIT, format, ap);
+} else {
+vfprintf(stderr, format, ap);
+}
+va_end(ap);
+}
+
+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 int do_cap_set(cap_value_t *cap_value, int size, int reset)
+{
+cap_t caps;
+if (reset) {
+/*
+ * Start with an empty set and set permitted and effective
+ */
+caps = cap_init();
+if (caps == NULL) {
+do_perror(cap_init);
+return -1;
+}
+if (cap_set_flag(caps, CAP_PERMITTED, size, cap_value, CAP_SET)  0) {
+do_perror(cap_set_flag);
+goto error;
+}
+} else {
+caps = cap_get_proc();
+if (!caps) {
+do_perror(cap_get_proc);
+return -1;
+}
+}
+if (cap_set_flag(caps, CAP_EFFECTIVE, size, cap_value, CAP_SET)  0) {
+do_perror(cap_set_flag);
+goto error;
+}
+if (cap_set_proc(caps)  0) {
+do_perror(cap_set_proc);
+goto error;
+}
+cap_free(caps);
+return 0;
+
+error:
+cap_free(caps);
+return -1;
+}
+
+static int init_capabilities(void)
+{
+/* helper needs following capbabilities only */
+cap_value_t cap_list[] = {
+CAP_CHOWN,
+CAP_DAC_OVERRIDE,
+CAP_FOWNER,
+CAP_FSETID,
+CAP_SETGID,
+CAP_MKNOD,
+CAP_SETUID,
+};
+return do_cap_set(cap_list, ARRAY_SIZE(cap_list), 1);
+}
+
+static int socket_read(int sockfd, void *buff, ssize_t size

[Qemu-devel] [PATCH V4 00/13] Proxy FS driver for VirtFS

2011-12-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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)

Changes from previous version V3:
* Improve error handling in marshaling/unmarshaling code
* Return ENOBUFS when request/response size exceeds maximum buffer size

Changes from previous version V2:
* Added check to handle failures in marshaling/unmarshaling code. Also make
  sure that request/response will not exceed maximum buffer size (BUFF_SZ)
* Addressed Stefan's review comments

Changes from previous version:
*) Communication between qemu and helper process is similar to 9p way of packing
elements (pdu marshaling).

M. Mohan Kumar (13):
  hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file
  hw/9pfs: Add validation to {un}marshal code
  hw/9pfs: Add new proxy filesystem driver
  hw/9pfs: File system helper process for qemu 9p 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
  hw/9pfs: Add support to use named socket for proxy FS

 Makefile   |   15 +-
 Makefile.objs  |3 +-
 configure  |   19 +
 fsdev/file-op-9p.h |2 +
 fsdev/qemu-fsdev.c |1 +
 fsdev/qemu-fsdev.h |1 +
 fsdev/virtfs-proxy-helper.c| 1134 
 fsdev/virtfs-proxy-helper.texi |   63 ++
 fsdev/virtio-9p-marshal.c  |  360 
 fsdev/virtio-9p-marshal.h  |   90 +++
 hw/9pfs/virtio-9p-proxy.c  | 1230 
 hw/9pfs/virtio-9p-proxy.h  |   95 +++
 hw/9pfs/virtio-9p.c|  756 +++--
 hw/9pfs/virtio-9p.h|   83 +---
 qemu-config.c  |   13 +
 qemu-options.hx|   32 +-
 vl.c   |   10 +-
 17 files changed, 3406 insertions(+), 501 deletions(-)
 create mode 100644 fsdev/virtfs-proxy-helper.c
 create mode 100644 fsdev/virtfs-proxy-helper.texi
 create mode 100644 fsdev/virtio-9p-marshal.c
 create mode 100644 fsdev/virtio-9p-marshal.h
 create mode 100644 hw/9pfs/virtio-9p-proxy.c
 create mode 100644 hw/9pfs/virtio-9p-proxy.h

-- 
1.7.6




[Qemu-devel] [PATCH V4 11/13] hw/9pfs: Documentation changes related to proxy fs

2011-12-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 qemu-options.hx |   25 -
 1 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index 681eaf1..cde17ed 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -530,19 +530,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][,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][,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}
@@ -559,7 +559,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.
@@ -569,6 +569,10 @@ 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 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.
@@ -589,19 +593,19 @@ DEFHEADING(Virtual File system pass-through options:)
 
 DEF(virtfs, HAS_ARG, QEMU_OPTION_virtfs,
 -virtfs 
local,path=path,mount_tag=tag,security_model=[mapped|passthrough|none]\n
-[,writeout=immediate][,readonly]\n,
+[,writeout=immediate][,readonly][,sock_fd=sock_fd]\n,
 QEMU_ARCH_ALL)
 
 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][,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}
@@ -618,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.
@@ -628,6 +632,9 @@ 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 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




[Qemu-devel] [PATCH V4 13/13] hw/9pfs: Add support to use named socket for proxy FS

2011-12-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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. We can achive the same using a shell script over
qemu and virtfs-proxy-helper using exec fdsocket-path, and then
passing that fd as argument to qemu and virtfs-proxy-helper. Also having
a server like virtfs-proxy-helper listening on a pathname without any
authentication is little bit scary. So we have to decide whether this
patch is really needed.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
Signed-off-by: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com
---
 fsdev/file-op-9p.h |2 +
 fsdev/virtfs-proxy-helper.c|   86 ++-
 fsdev/virtfs-proxy-helper.texi |4 ++
 hw/9pfs/virtio-9p-proxy.c  |   52 +---
 qemu-config.c  |7 +++
 qemu-options.hx|   15 +--
 vl.c   |6 ++-
 7 files changed, 157 insertions(+), 15 deletions(-)

diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 73de79f..4f76f9d 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -57,6 +57,8 @@ typedef struct extended_ops {
  */
 #define V9FS_SM_NONE0x0010
 #define V9FS_RDONLY 0x0020
+#define V9FS_PROXY_SOCK_FD  0x0040
+#define V9FS_PROXY_SOCK_NAME0x0080
 
 #define V9FS_SEC_MASK   0x001C
 
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index a6bd6dc..d526973 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -57,6 +57,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'},
 };
 
 static bool is_daemon;
@@ -702,11 +705,61 @@ err_out:
 return ret;
 }
 
+/* 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));
 }
@@ -960,16 +1013,20 @@ int main(int argc, char **argv)
 {
 int sock;
 char *rpath = NULL;
+char *sock_name = NULL;
 struct stat stbuf;
 int c, option_index;
 int retval;
 struct statfs st_fs;
+uid_t own_u;
+gid_t own_g;
 
 is_daemon = true;
 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;
@@ -984,6 +1041,15 @@ int main(int argc, char **argv)
 case 'f':
 sock = atoi(optarg);
 break;
+case 's':
+sock_name = strdup(optarg);
+break;
+case 'u':
+own_u = atoi(optarg);
+break;
+case 'g':
+own_g = atoi(optarg);
+break;
 case '?':
 case 'h':
 default:
@@ -993,8 +1059,16 @@ int main(int argc, char **argv)
 }
 
 /* Parameter validation */
-if (sock == -1 || rpath == NULL) {
-fprintf(stderr, socket descriptor or path not specified\n);
+if ((sock_name == NULL  sock == -1) || rpath == NULL) {
+fprintf(stderr

[Qemu-devel] [PATCH V4 08/13] hw/9pfs: File ownership and others

2011-12-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@in.ibm.com
---
 Makefile|2 +-
 fsdev/virtfs-proxy-helper.c |   83 +
 hw/9pfs/virtio-9p-proxy.c   |  142 +++
 hw/9pfs/virtio-9p-proxy.h   |6 ++
 4 files changed, 220 insertions(+), 13 deletions(-)

diff --git a/Makefile b/Makefile
index 1906c5e..0acad52 100644
--- a/Makefile
+++ b/Makefile
@@ -154,7 +154,7 @@ qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
 qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
 qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
 
-fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o 
fsdev/virtio-9p-marshal.o
+fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o 
fsdev/virtio-9p-marshal.o oslib-posix.o $(trace-obj-y)
 fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
 
 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 8bb1e06..871e3f4 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -610,6 +610,12 @@ static int process_reply(int sock, int type,
 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:
 if (send_status(sock, out_iovec, retval)  0) {
 return -1;
 }
@@ -631,7 +637,10 @@ static int process_reply(int sock, int type,
 static int process_requests(int sock)
 {
 int retval = 0;
+uint64_t offset;
 ProxyHeader header;
+int mode, uid, gid;
+struct timespec spec[2];
 V9fsString oldpath, path;
 struct iovec in_iovec, out_iovec;
 
@@ -697,6 +706,80 @@ static int process_requests(int sock)
 case T_READLINK:
 retval = do_readlink(in_iovec, out_iovec);
 break;
+case T_CHMOD:
+v9fs_string_init(path);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ,
+ sd, path, mode);
+if (retval  0) {
+retval = chmod(path.data, mode);
+if (retval  0) {
+retval = -errno;
+}
+}
+v9fs_string_free(path);
+break;
+case T_CHOWN:
+v9fs_string_init(path);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ, sdd, path,
+ uid, gid);
+if (retval  0) {
+retval = lchown(path.data, uid, gid);
+if (retval  0) {
+retval = -errno;
+}
+}
+v9fs_string_free(path);
+break;
+case T_TRUNCATE:
+v9fs_string_init(path);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ, sq,
+ path, offset);
+if (retval  0) {
+retval = truncate(path.data, offset);
+if (retval  0) {
+retval = -errno;
+}
+}
+v9fs_string_free(path);
+break;
+case T_UTIME:
+v9fs_string_init(path);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ, s, path,
+ spec[0].tv_sec, spec[0].tv_nsec,
+ spec[1].tv_sec, spec[1].tv_nsec);
+if (retval  0) {
+retval = qemu_utimens(path.data, spec);
+if (retval  0) {
+retval = -errno;
+}
+}
+v9fs_string_free(path);
+break;
+case T_RENAME:
+v9fs_string_init(path);
+v9fs_string_init(oldpath);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ,
+ ss, oldpath, path);
+if (retval  0) {
+retval = rename(oldpath.data, path.data);
+if (retval  0) {
+retval = -errno;
+}
+}
+v9fs_string_free(oldpath);
+v9fs_string_free(path);
+break;
+case T_REMOVE:
+v9fs_string_init(path);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ, s, path);
+if (retval  0) {
+retval = remove(path.data);
+if (retval  0) {
+retval = -errno;
+}
+}
+v9fs_string_free(path);
+break;
 default:
 goto err_out;
 break;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index bfbdcb5..588d806 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -287,7 +287,9

[Qemu-devel] [PATCH V4 07/13] hw/9pfs: Add stat/readlink/statfs for proxy FS

2011-12-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |  182 +
 hw/9pfs/virtio-9p-proxy.c   |  209 +--
 hw/9pfs/virtio-9p-proxy.h   |   34 +++
 3 files changed, 417 insertions(+), 8 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 729c79c..8bb1e06 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -25,6 +25,8 @@
 #include sys/fsuid.h
 #include stdarg.h
 #include stdbool.h
+#include sys/vfs.h
+#include sys/stat.h
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
@@ -298,6 +300,172 @@ static int setfsugid(int uid, int gid)
 }
 
 /*
+ * send response in two parts
+ * 1) ProxyHeader
+ * 2) Response or error status
+ * This function should be called with marshaled response
+ * send_response constructs header part and error part only.
+ * send response sends {ProxyHeader,Response} if the request was success
+ * otherwise sends {ProxyHeader,error status}
+ */
+static int send_response(int sock, struct iovec *iovec, int size)
+{
+int retval;
+ProxyHeader header;
+
+/*
+ * If response size exceeds available iovec-iov_len,
+ * we return ENOBUFS
+ */
+if (size  PROXY_MAX_IO_SZ) {
+size = -ENOBUFS;
+}
+
+if (size  0) {
+/*
+ * In case of error we would not have got the error encoded
+ * already so encode the error here.
+ */
+header.type = T_ERROR;
+header.size = sizeof(size);
+proxy_marshal(iovec, PROXY_HDR_SZ, d, size);
+} else {
+header.type = T_SUCCESS;
+header.size = size;
+}
+proxy_marshal(iovec, 0, dd, header.type, header.size);
+retval = socket_write(sock, iovec-iov_base, header.size + PROXY_HDR_SZ);
+if (retval  0) {
+return retval;;
+}
+return 0;
+}
+
+static void stat_to_prstat(ProxyStat *pr_stat, struct stat *stat)
+{
+memset(pr_stat, 0, sizeof(*pr_stat));
+pr_stat-st_dev = stat-st_dev;
+pr_stat-st_ino = stat-st_ino;
+pr_stat-st_nlink = stat-st_nlink;
+pr_stat-st_mode = stat-st_mode;
+pr_stat-st_uid = stat-st_uid;
+pr_stat-st_gid = stat-st_gid;
+pr_stat-st_rdev = stat-st_rdev;
+pr_stat-st_size = stat-st_size;
+pr_stat-st_blksize = stat-st_blksize;
+pr_stat-st_blocks = stat-st_blocks;
+pr_stat-st_atim_sec = stat-st_atim.tv_sec;
+pr_stat-st_atim_nsec = stat-st_atim.tv_nsec;
+pr_stat-st_mtim_sec = stat-st_mtim.tv_sec;
+pr_stat-st_mtim_nsec = stat-st_mtim.tv_nsec;
+pr_stat-st_ctim_sec = stat-st_ctim.tv_sec;
+pr_stat-st_ctim_nsec = stat-st_ctim.tv_nsec;
+}
+
+static void statfs_to_prstatfs(ProxyStatFS *pr_stfs, struct statfs *stfs)
+{
+memset(pr_stfs, 0, sizeof(*pr_stfs));
+pr_stfs-f_type = stfs-f_type;
+pr_stfs-f_bsize = stfs-f_bsize;
+pr_stfs-f_blocks = stfs-f_blocks;
+pr_stfs-f_bfree = stfs-f_bfree;
+pr_stfs-f_bavail = stfs-f_bavail;
+pr_stfs-f_files = stfs-f_files;
+pr_stfs-f_ffree = stfs-f_ffree;
+pr_stfs-f_fsid[0] = stfs-f_fsid.__val[0];
+pr_stfs-f_fsid[1] = stfs-f_fsid.__val[1];
+pr_stfs-f_namelen = stfs-f_namelen;
+pr_stfs-f_frsize = stfs-f_frsize;
+}
+
+/*
+ * Gets stat/statfs information and packs in out_iovec structure
+ * on success returns number of bytes packed in out_iovec struture
+ * otherwise returns -errno
+ */
+static int do_stat(int type, struct iovec *iovec, struct iovec *out_iovec)
+{
+int retval;
+V9fsString path;
+ProxyStat pr_stat;
+ProxyStatFS pr_stfs;
+struct stat st_buf;
+struct statfs stfs_buf;
+
+v9fs_string_init(path);
+retval = proxy_unmarshal(iovec, PROXY_HDR_SZ, s, path);
+if (retval  0) {
+return retval;
+}
+
+switch (type) {
+case T_LSTAT:
+retval = lstat(path.data, st_buf);
+if (retval  0) {
+retval = -errno;
+} else {
+stat_to_prstat(pr_stat, st_buf);
+retval = proxy_marshal(out_iovec, PROXY_HDR_SZ,
+   qqqdddqq, pr_stat.st_dev,
+   pr_stat.st_ino, pr_stat.st_nlink,
+   pr_stat.st_mode, pr_stat.st_uid,
+   pr_stat.st_gid, pr_stat.st_rdev,
+   pr_stat.st_size, pr_stat.st_blksize,
+   pr_stat.st_blocks,
+   pr_stat.st_atim_sec, pr_stat.st_atim_nsec,
+   pr_stat.st_mtim_sec, pr_stat.st_mtim_nsec,
+   pr_stat.st_ctim_sec, pr_stat.st_ctim_nsec);
+}
+break;
+case T_STATFS:
+retval = statfs(path.data, stfs_buf);
+if (retval  0) {
+retval = -errno;
+} else {
+statfs_to_prstatfs(pr_stfs, stfs_buf

[Qemu-devel] [PATCH V4 10/13] hw/9pfs: Proxy getversion

2011-12-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Add proxy getversion to get generation number

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |   80 +++
 hw/9pfs/virtio-9p-proxy.c   |   33 ++
 hw/9pfs/virtio-9p-proxy.h   |1 +
 3 files changed, 114 insertions(+), 0 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 2a2ea0b..a6bd6dc 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -28,6 +28,11 @@
 #include sys/vfs.h
 #include sys/stat.h
 #include attr/xattr.h
+#include sys/ioctl.h
+#include linux/fs.h
+#ifdef CONFIG_LINUX_MAGIC_H
+#include linux/magic.h
+#endif
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
@@ -35,6 +40,19 @@
 
 #define PROGNAME virtfs-proxy-helper
 
+#ifndef XFS_SUPER_MAGIC
+#define XFS_SUPER_MAGIC  0x58465342
+#endif
+#ifndef EXT2_SUPER_MAGIC
+#define EXT2_SUPER_MAGIC 0xEF53
+#endif
+#ifndef REISERFS_SUPER_MAGIC
+#define REISERFS_SUPER_MAGIC 0x52654973
+#endif
+#ifndef BTRFS_SUPER_MAGIC
+#define BTRFS_SUPER_MAGIC 0x9123683E
+#endif
+
 static struct option helper_opts[] = {
 {fd, required_argument, NULL, 'f'},
 {path, required_argument, NULL, 'p'},
@@ -42,6 +60,7 @@ static struct option helper_opts[] = {
 };
 
 static bool is_daemon;
+static bool get_version; /* IOC getversion IOCTL supported */
 
 static void do_log(int loglevel, const char *format, ...)
 {
@@ -342,6 +361,45 @@ static int send_response(int sock, struct iovec *iovec, 
int size)
 return 0;
 }
 
+/*
+ * gets generation number
+ * returns -errno on failure and sizeof(generation number) on success
+ */
+static int do_getversion(struct iovec *iovec, struct iovec *out_iovec)
+{
+V9fsString path;
+uint64_t version;
+int fd, retval = -ENOTTY;
+
+/* no need to issue ioctl */
+if (!get_version) {
+version = 0;
+retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, q, version);
+return retval;
+}
+#ifdef FS_IOC_GETVERSION
+retval = proxy_unmarshal(iovec, PROXY_HDR_SZ, s, path);
+if (retval  0) {
+return retval;
+}
+
+fd = open(path.data, O_RDONLY);
+if (fd  0) {
+retval = -errno;
+goto err_out;
+}
+if (ioctl(fd, FS_IOC_GETVERSION, version)  0) {
+retval = -errno;
+} else {
+retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, q, version);
+}
+close(fd);
+err_out:
+v9fs_string_free(path);
+#endif
+return retval;
+}
+
 static int do_getxattr(int type, struct iovec *iovec, struct iovec *out_iovec)
 {
 int size = 0, offset, retval;
@@ -684,6 +742,7 @@ static int process_reply(int sock, int type,
 case T_READLINK:
 case T_LGETXATTR:
 case T_LLISTXATTR:
+case T_GETVERSION:
 if (send_response(sock, out_iovec, retval)  0) {
 return -1;
 }
@@ -879,6 +938,9 @@ static int process_requests(int sock)
 v9fs_string_free(path);
 v9fs_string_free(name);
 break;
+case T_GETVERSION:
+retval = do_getversion(in_iovec, out_iovec);
+break;
 default:
 goto err_out;
 break;
@@ -900,6 +962,8 @@ int main(int argc, char **argv)
 char *rpath = NULL;
 struct stat stbuf;
 int c, option_index;
+int retval;
+struct statfs st_fs;
 
 is_daemon = true;
 sock = -1;
@@ -956,6 +1020,22 @@ int main(int argc, char **argv)
 
 do_log(LOG_INFO, Started\n);
 
+get_version = false;
+#ifdef FS_IOC_GETVERSION
+/* check whether underlying FS support IOC_GETVERSION */
+retval = statfs(rpath, st_fs);
+if (!retval) {
+switch (st_fs.f_type) {
+case EXT2_SUPER_MAGIC:
+case BTRFS_SUPER_MAGIC:
+case REISERFS_SUPER_MAGIC:
+case XFS_SUPER_MAGIC:
+get_version = true;
+break;
+}
+}
+#endif
+
 if (chroot(rpath)  0) {
 do_perror(chroot);
 goto error;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index ce1c411..65c17d6 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -243,6 +243,9 @@ static int v9fs_receive_response(V9fsProxy *proxy, int type,
 v9fs_string_free(xattr);
 break;
 }
+case T_GETVERSION:
+proxy_unmarshal(reply, PROXY_HDR_SZ, q, response);
+break;
 default:
 return -1;
 }
@@ -528,6 +531,15 @@ static int v9fs_request(V9fsProxy *proxy, int type,
 }
 header.type = T_LREMOVEXATTR;
 break;
+case T_GETVERSION:
+path = va_arg(ap, V9fsString *);
+header.size = proxy_marshal(iovec, PROXY_HDR_SZ, s, path);
+if (header.size  0) {
+retval = header.size;
+break;
+}
+header.type = T_GETVERSION;
+break;
 default:
 error_report(Invalid type %d\n, type);
 retval

[Qemu-devel] [PATCH V4 06/13] hw/9pfs: Create other filesystem objects

2011-12-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |  131 ++--
 hw/9pfs/virtio-9p-proxy.c   |  203 +++
 hw/9pfs/virtio-9p-proxy.h   |8 ++-
 3 files changed, 318 insertions(+), 24 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 241fcff..729c79c 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -243,6 +243,30 @@ static int send_fd(int sockfd, int fd)
 return 0;
 }
 
+static int send_status(int sockfd, struct iovec *iovec, int status)
+{
+ProxyHeader header;
+int retval, msg_size;;
+
+if (status  0) {
+header.type = T_ERROR;
+} else {
+header.type = T_SUCCESS;
+}
+header.size = sizeof(status);
+/*
+ * marshal the return status. We don't check error.
+ * because we are sure we have enough space for the status
+ */
+msg_size = proxy_marshal(iovec, 0, ddd, header.type,
+ header.size, status);
+retval = socket_write(sockfd, iovec-iov_base, msg_size);
+if (retval  0) {
+return retval;
+}
+return 0;
+}
+
 /*
  * from man 7 capabilities, section
  * Effect of User ID Changes on Capabilities:
@@ -274,6 +298,67 @@ static int setfsugid(int uid, int gid)
 }
 
 /*
+ * create other filesystem objects and send 0 on success
+ * return -errno on error
+ */
+static int do_create_others(int type, struct iovec *iovec)
+{
+dev_t rdev;
+int retval = 0;
+int offset = PROXY_HDR_SZ;
+V9fsString oldpath, path;
+int mode, uid, gid, cur_uid, cur_gid;
+
+v9fs_string_init(path);
+v9fs_string_init(oldpath);
+cur_uid = geteuid();
+cur_gid = getegid();
+
+retval = proxy_unmarshal(iovec, offset, dd, uid, gid);
+if (retval  0) {
+return retval;
+}
+offset += retval;
+retval = setfsugid(uid, gid);
+if (retval  0) {
+retval = -errno;
+goto err_out;
+}
+switch (type) {
+case T_MKNOD:
+retval = proxy_unmarshal(iovec, offset, sdq, path, mode, rdev);
+if (retval  0) {
+goto err_out;
+}
+retval = mknod(path.data, mode, rdev);
+break;
+case T_MKDIR:
+retval = proxy_unmarshal(iovec, offset, sd, path, mode);
+if (retval  0) {
+goto err_out;
+}
+retval = mkdir(path.data, mode);
+break;
+case T_SYMLINK:
+retval = proxy_unmarshal(iovec, offset, ss, oldpath, path);
+if (retval  0) {
+goto err_out;
+}
+retval = symlink(oldpath.data, path.data);
+break;
+}
+if (retval  0) {
+retval = -errno;
+}
+
+err_out:
+v9fs_string_free(path);
+v9fs_string_free(oldpath);
+setfsugid(cur_uid, cur_gid);
+return retval;
+}
+
+/*
  * create a file and send fd on success
  * return -errno on error
  */
@@ -343,7 +428,8 @@ static void usage(char *prog)
 basename(prog));
 }
 
-static int process_reply(int sock, int type, int retval)
+static int process_reply(int sock, int type,
+ struct iovec *out_iovec, int retval)
 {
 switch (type) {
 case T_OPEN:
@@ -352,6 +438,14 @@ static int process_reply(int sock, int type, int retval)
 return -1;
 }
 break;
+case T_MKNOD:
+case T_MKDIR:
+case T_SYMLINK:
+case T_LINK:
+if (send_status(sock, out_iovec, retval)  0) {
+return -1;
+}
+break;
 default:
 return -1;
 break;
@@ -363,10 +457,14 @@ static int process_requests(int sock)
 {
 int retval = 0;
 ProxyHeader header;
-struct iovec in_iovec;
+V9fsString oldpath, path;
+struct iovec in_iovec, out_iovec;
+
+in_iovec.iov_base  = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
+in_iovec.iov_len   = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
+out_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
+out_iovec.iov_len  = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
 
-in_iovec.iov_base = g_malloc(PROXY_MAX_IO_SZ + PROXY_HDR_SZ);
-in_iovec.iov_len  = PROXY_MAX_IO_SZ + PROXY_HDR_SZ;
 while (1) {
 /*
  * initialize the header type, so that we send
@@ -382,7 +480,7 @@ static int process_requests(int sock)
  * header.type update properly when we reach
  * here.
  */
-if (process_reply(sock, header.type, retval)  0) {
+if (process_reply(sock, header.type, out_iovec, retval)  0) {
 goto err_out;
 }
 continue;
@@ -398,18 +496,37 @@ static int process_requests(int sock)
 case T_CREATE:
 retval = do_create(in_iovec);
 break

[Qemu-devel] [PATCH V4 09/13] hw/9pfs: xattr interfaces in proxy filesystem driver

2011-12-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Add xattr support for proxy FS

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |   99 +
 hw/9pfs/virtio-9p-proxy.c   |  128 ---
 hw/9pfs/virtio-9p-proxy.h   |4 +
 3 files changed, 223 insertions(+), 8 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 871e3f4..2a2ea0b 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -27,6 +27,7 @@
 #include stdbool.h
 #include sys/vfs.h
 #include sys/stat.h
+#include attr/xattr.h
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
@@ -341,6 +342,62 @@ static int send_response(int sock, struct iovec *iovec, 
int size)
 return 0;
 }
 
+static int do_getxattr(int type, struct iovec *iovec, struct iovec *out_iovec)
+{
+int size = 0, offset, retval;
+V9fsString path, name, xattr;
+
+v9fs_string_init(xattr);
+v9fs_string_init(path);
+retval = proxy_unmarshal(iovec, PROXY_HDR_SZ, ds, size, path);
+if (retval  0) {
+return retval;
+}
+offset = PROXY_HDR_SZ + retval;
+
+if (size) {
+xattr.data = g_malloc(size);
+xattr.size = size;
+}
+switch (type) {
+case T_LGETXATTR:
+v9fs_string_init(name);
+retval = proxy_unmarshal(iovec, offset, s, name);
+if (retval  0) {
+retval = lgetxattr(path.data, name.data, xattr.data, size);
+if (retval  0) {
+retval = -errno;
+} else {
+xattr.size = retval;
+}
+}
+v9fs_string_free(name);
+break;
+case T_LLISTXATTR:
+retval = llistxattr(path.data, xattr.data, size);
+if (retval  0) {
+retval = -errno;
+} else {
+xattr.size = retval;
+}
+break;
+}
+if (retval  0) {
+goto err_out;
+}
+
+if (!size) {
+proxy_marshal(out_iovec, PROXY_HDR_SZ, d, retval);
+retval = sizeof(retval);
+} else {
+retval = proxy_marshal(out_iovec, PROXY_HDR_SZ, s, xattr);
+}
+err_out:
+v9fs_string_free(xattr);
+v9fs_string_free(path);
+return retval;
+}
+
 static void stat_to_prstat(ProxyStat *pr_stat, struct stat *stat)
 {
 memset(pr_stat, 0, sizeof(*pr_stat));
@@ -616,6 +673,8 @@ static int process_reply(int sock, int type,
 case T_UTIME:
 case T_RENAME:
 case T_REMOVE:
+case T_LSETXATTR:
+case T_LREMOVEXATTR:
 if (send_status(sock, out_iovec, retval)  0) {
 return -1;
 }
@@ -623,6 +682,8 @@ static int process_reply(int sock, int type,
 case T_LSTAT:
 case T_STATFS:
 case T_READLINK:
+case T_LGETXATTR:
+case T_LLISTXATTR:
 if (send_response(sock, out_iovec, retval)  0) {
 return -1;
 }
@@ -636,10 +697,13 @@ static int process_reply(int sock, int type,
 
 static int process_requests(int sock)
 {
+int flags;
+int size = 0;
 int retval = 0;
 uint64_t offset;
 ProxyHeader header;
 int mode, uid, gid;
+V9fsString name, value;
 struct timespec spec[2];
 V9fsString oldpath, path;
 struct iovec in_iovec, out_iovec;
@@ -780,6 +844,41 @@ static int process_requests(int sock)
 }
 v9fs_string_free(path);
 break;
+case T_LGETXATTR:
+case T_LLISTXATTR:
+retval = do_getxattr(header.type, in_iovec, out_iovec);
+break;
+case T_LSETXATTR:
+v9fs_string_init(path);
+v9fs_string_init(name);
+v9fs_string_init(value);
+retval = proxy_unmarshal(in_iovec, PROXY_HDR_SZ, sssdd, path,
+ name, value, size, flags);
+if (retval  0) {
+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_string_init(path);
+v9fs_string_init(name);
+retval = proxy_unmarshal(in_iovec,
+ PROXY_HDR_SZ, ss, path, name);
+if (retval  0) {
+retval = lremovexattr(path.data, name.data);
+if (retval  0) {
+retval = -errno;
+}
+}
+v9fs_string_free(path);
+v9fs_string_free(name);
+break;
 default:
 goto err_out;
 break;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 588d806..ce1c411 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c

[Qemu-devel] [PATCH V4 02/13] hw/9pfs: Add validation to {un}marshal code

2011-12-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
Signed-off-by: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com
---
 fsdev/virtio-9p-marshal.c |  148 --
 fsdev/virtio-9p-marshal.h |   19 +-
 hw/9pfs/virtio-9p.c   |  467 +
 3 files changed, 438 insertions(+), 196 deletions(-)

diff --git a/fsdev/virtio-9p-marshal.c b/fsdev/virtio-9p-marshal.c
index 029c29e..198665d 100644
--- a/fsdev/virtio-9p-marshal.c
+++ b/fsdev/virtio-9p-marshal.c
@@ -20,17 +20,12 @@
 #include sys/uio.h
 #include string.h
 #include stdint.h
+#include errno.h
 
 #include compiler.h
 #include virtio-9p-marshal.h
 #include bswap.h
 
-void v9fs_string_init(V9fsString *str)
-{
-str-data = NULL;
-str-size = 0;
-}
-
 void v9fs_string_free(V9fsString *str)
 {
 g_free(str-data);
@@ -62,11 +57,13 @@ void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
 }
 
 
-static size_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count,
-  size_t offset, size_t size, int pack)
+static ssize_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;
+size_t req_size = size;
+
 
 for (i = 0; size  i  sg_count; i++) {
 size_t len;
@@ -90,18 +87,23 @@ static size_t v9fs_packunpack(void *addr, struct iovec *sg, 
int sg_count,
 }
 }
 }
-
+if (copied  req_size) {
+/*
+ * We copied less that requested size. error out
+ */
+return -ENOBUFS;
+}
 return copied;
 }
 
-static size_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num,
-  size_t offset, size_t size)
+static ssize_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)
+ssize_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);
 }
@@ -131,11 +133,12 @@ static int v9fs_copy_sg(struct iovec *src_sg, unsigned 
int num,
 return j;
 }
 
-size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
-  int bswap, const char *fmt, ...)
+ssize_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
+   int bswap, const char *fmt, ...)
 {
 int i;
 va_list ap;
+ssize_t copied;
 size_t old_offset = offset;
 
 va_start(ap, fmt);
@@ -143,13 +146,13 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, 
size_t offset,
 switch (fmt[i]) {
 case 'b': {
 uint8_t *valp = va_arg(ap, uint8_t *);
-offset += v9fs_unpack(valp, out_sg, out_num, offset, 
sizeof(*valp));
+copied = 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));
+copied = v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
 if (bswap) {
 *valp = le16_to_cpu(val);
 } else {
@@ -160,7 +163,7 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, 
size_t offset,
 case 'd': {
 uint32_t val, *valp;
 valp = va_arg(ap, uint32_t *);
-offset += v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
+copied = v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
 if (bswap) {
 *valp = le32_to_cpu(val);
 } else {
@@ -171,7 +174,7 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, 
size_t offset,
 case 'q': {
 uint64_t val, *valp;
 valp = va_arg(ap, uint64_t *);
-offset += v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
+copied = v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
 if (bswap) {
 *valp = le64_to_cpu(val);
 } else {
@@ -187,59 +190,70 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, 
size_t offset,
 }
 case 's': {
 V9fsString *str = va_arg(ap, V9fsString *);
-offset += v9fs_unmarshal(out_sg, out_num, offset, bswap,
-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;
+copied = v9fs_unmarshal(out_sg

[Qemu-devel] [PATCH V4 12/13] hw/9pfs: man page for proxy helper

2011-12-05 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 Makefile   |   12 +++-
 fsdev/virtfs-proxy-helper.texi |   59 
 2 files changed, 70 insertions(+), 1 deletions(-)
 create mode 100644 fsdev/virtfs-proxy-helper.texi

diff --git a/Makefile b/Makefile
index 0acad52..f5b3524 100644
--- a/Makefile
+++ b/Makefile
@@ -38,6 +38,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+=fsdev/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) fsdev/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
@@ -367,6 +371,12 @@ qemu-img.1: qemu-img.texi qemu-img-cmds.texi
  pod2man --section=1 --center=  --release=  qemu-img.pod  $@, \
GEN   $@)
 
+fsdev/virtfs-proxy-helper.1: fsdev/virtfs-proxy-helper.texi
+   $(call quiet-command, \
+ perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $ 
fsdev/virtfs-proxy-helper.pod  \
+ pod2man --section=1 --center=  --release=  
fsdev/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/fsdev/virtfs-proxy-helper.texi b/fsdev/virtfs-proxy-helper.texi
new file mode 100644
index 000..3816382
--- /dev/null
+++ b/fsdev/virtfs-proxy-helper.texi
@@ -0,0 +1,59 @@
+@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 -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




[Qemu-devel] [Bug 897193] Re: virtfs: kernel compile fails

2011-11-29 Thread M. Mohan Kumar
Hi Avishay,

Are you running qemu as a normal user? In that case, could you please
check whether normal user has rw access to the kernel source?

Also could you please attach the output of strace scripts/kconfig/conf
--silentoldconfig Kconfig ?

-- 
You received this bug notification because you are a member of qemu-
devel-ml, which is subscribed to QEMU.
https://bugs.launchpad.net/bugs/897193

Title:
  virtfs: kernel compile fails

Status in QEMU:
  New

Bug description:
  I am trying to compile a kernel under virtfs, and am getting an error.
  The error does not occur when compiling outside of the virtfs mount.

  Both guest and host are running the 3.0.4 kernel.
  QEMU is latest from git: bc75c9e50d308b2ec6623a40179c5cdc84b63dae

  QEMU command line:
  /usr/local/bin/qemu-system-x86_64 -nographic -boot c -m 1024 -machine 
type=pc,accel=kvm -drive file=/root/hdd1.img,if=virtio -drive 
file=/root/test1.img,if=virtio -drive file=/root/test2.img,if=virtio -virtfs 
local,path=/mnt/virtfs,security_model=none,mount_tag=virtfs -net 
nic,model=virtio,macaddr=DE:AD:BE:EF:AA:BB -net tap,ifname=qtap0,script=no

  virtfs line in /etc/fstab:
  virtfs  /mnt/virtfs 9p  
defaults,noauto,trans=virtio0 0

  Steps to reproduce and output:

  [root@guest linux-3.0.4]# make mrproper
CLEAN   scripts/basic
CLEAN   scripts/kconfig
CLEAN   include/config include/generated
CLEAN   .config .config.old
  [root@guest linux-3.0.4]# make defconfig
HOSTCC  scripts/basic/fixdep
HOSTCC  scripts/kconfig/conf.o
SHIPPED scripts/kconfig/zconf.tab.c
SHIPPED scripts/kconfig/lex.zconf.c
SHIPPED scripts/kconfig/zconf.hash.c
HOSTCC  scripts/kconfig/zconf.tab.o
HOSTLD  scripts/kconfig/conf
  *** Default configuration is based on 'x86_64_defconfig'
  #
  # configuration written to .config
  #
  [root@guest linux-3.0.4]# make
  scripts/kconfig/conf --silentoldconfig Kconfig

  *** Error during update of the configuration.

  make[2]: *** [silentoldconfig] Error 1
  make[1]: *** [silentoldconfig] Error 2
  make: *** No rule to make target `include/config/auto.conf', needed by 
`include/config/kernel.release'.  Stop.

  
  Please let me know if you need any other information.  Thanks!

To manage notifications about this bug go to:
https://bugs.launchpad.net/qemu/+bug/897193/+subscriptions



Re: [Qemu-devel] virtio-9p compiling error

2011-11-29 Thread M. Mohan Kumar
Could you please give your host information? Such as gcc version, distro 
version etc?

I could compile in my Fedora 15 x86-64 system using gcc 4.6.0
-- 
Regards,
M. Mohan Kumar

On Tuesday, November 29, 2011 06:27:00 PM erik.r...@rdsoftware.de wrote:
 Hi all,
 
 when compiling the 1.0-rc4 I get the following error.
 0.14.0-kvm and 0.15.0-kvm were fine, I found no configure switch
 possibility to disable this code part. I really don't need it.
 
 Please help here:
 
   CClibhw64/9pfs/virtio-9p.o
   CClibhw64/9pfs/virtio-9p-local.o
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-local.c: In function
 'local_init': /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-local.c:721:
 warning: unused variable 'stbuf'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-local.c: At top level:
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-local.c:694: warning:
 'local_ioc_getversion' defined but not used
   CClibhw64/9pfs/virtio-9p-xattr.o
   CClibhw64/9pfs/virtio-9p-xattr-user.o
   CClibhw64/9pfs/virtio-9p-posix-acl.o
   CClibhw64/9pfs/virtio-9p-coth.o
   CClibhw64/9pfs/cofs.o
   CClibhw64/9pfs/codir.o
   CClibhw64/9pfs/cofile.o
   CClibhw64/9pfs/coxattr.o
   CClibhw64/9pfs/virtio-9p-handle.o
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c: In function
 'handle_update_file_cred':
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:95: warning: implicit
 declaration of function 'openat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:95: warning: nested
 extern declaration of 'openat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:103: warning: implicit
 declaration of function 'fchownat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:103: warning: nested
 extern declaration of 'fchownat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c: In function
 'handle_lstat': /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:120:
 warning: implicit declaration of function 'fstatat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:120: warning: nested
 extern declaration of 'fstatat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c: In function
 'handle_readlink':
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:135: warning: implicit
 declaration of function 'readlinkat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:135: warning: nested
 extern declaration of 'readlinkat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c: In function
 'handle_opendir':
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:167: warning: implicit
 declaration of function 'fdopendir'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:167: warning: nested
 extern declaration of 'fdopendir'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:167: warning: assignment
 makes pointer from integer without a cast
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c: In function
 'handle_mknod': /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:265:
 warning: implicit declaration of function 'mknodat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:265: warning: nested
 extern declaration of 'mknodat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c: In function
 'handle_mkdir': /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:283:
 warning: implicit declaration of function 'mkdirat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:283: warning: nested
 extern declaration of 'mkdirat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c: In function
 'handle_symlink':
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:333: warning: implicit
 declaration of function 'symlinkat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:333: warning: nested
 extern declaration of 'symlinkat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c: In function
 'handle_link': /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:363:
 warning: implicit declaration of function 'linkat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:363: warning: nested
 extern declaration of 'linkat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c: In function
 'handle_renameat':
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:570: warning: implicit
 declaration of function 'renameat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:570: warning: nested
 extern declaration of 'renameat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c: In function
 'handle_unlinkat':
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:593: warning: implicit
 declaration of function 'unlinkat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:593: warning: nested
 extern declaration of 'unlinkat'
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c: In function
 'handle_ioc_getversion':
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:616: error:
 'FS_IOC_GETVERSION' undeclared (first use in this function)
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:616: error: (Each
 undeclared identifier is reported only once
 /home/erik/qemu-1.0-rc4/hw/9pfs/virtio-9p-handle.c:616: error: for each
 function it appears

[Qemu-devel] [PATCH V3 10/13] hw/9pfs: Proxy getversion

2011-11-21 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Add proxy getversion to get generation number

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |   77 +++
 hw/9pfs/virtio-9p-proxy.c   |   34 +++
 hw/9pfs/virtio-9p-proxy.h   |1 +
 3 files changed, 112 insertions(+), 0 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 652fda6..08ea316 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -29,6 +29,11 @@
 #include sys/vfs.h
 #include sys/stat.h
 #include attr/xattr.h
+#include sys/ioctl.h
+#include linux/fs.h
+#ifdef CONFIG_LINUX_MAGIC_H
+#include linux/magic.h
+#endif
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
@@ -54,6 +59,19 @@
 } \
 } while (0)
 
+#ifndef XFS_SUPER_MAGIC
+#define XFS_SUPER_MAGIC  0x58465342
+#endif
+#ifndef EXT2_SUPER_MAGIC
+#define EXT2_SUPER_MAGIC 0xEF53
+#endif
+#ifndef REISERFS_SUPER_MAGIC
+#define REISERFS_SUPER_MAGIC 0x52654973
+#endif
+#ifndef BTRFS_SUPER_MAGIC
+#define BTRFS_SUPER_MAGIC 0x9123683E
+#endif
+
 static struct option helper_opts[] = {
 {fd, required_argument, NULL, 'f'},
 {path, required_argument, NULL, 'p'},
@@ -61,6 +79,7 @@ static struct option helper_opts[] = {
 };
 
 static bool is_daemon;
+static bool get_version; /* IOC getversion IOCTL supported */
 
 static int cap_set(void)
 {
@@ -298,6 +317,44 @@ static int send_response(int sock, struct iovec *iovec, 
int size)
 return 0;
 }
 
+/*
+ * gets generation number
+ * returns -errno on failure and sizeof(generation number) on success
+ */
+static int do_getversion(struct iovec *iovec, struct iovec *out_iovec)
+{
+int fd, retval;
+uint64_t version;
+V9fsString path;
+
+retval = sizeof(version);
+/* no need to issue ioctl */
+if (!get_version) {
+version = 0;
+proxy_marshal(out_iovec, 1, HDR_SZ, q, version);
+return retval;
+}
+
+if (proxy_unmarshal(iovec, 1, HDR_SZ, s, path)  0) {
+return -EOVERFLOW;
+}
+
+fd = open(path.data, O_RDONLY);
+if (fd  0) {
+retval = -errno;
+goto done;
+}
+if (ioctl(fd, FS_IOC_GETVERSION, version)  0) {
+retval = -errno;
+} else {
+proxy_marshal(out_iovec, 1, HDR_SZ, q, version);
+}
+close(fd);
+done:
+v9fs_string_free(path);
+return retval;
+}
+
 static int do_getxattr(int type, struct iovec *iovec, struct iovec *out_iovec)
 {
 int size = 0, offset, retval;
@@ -748,6 +805,9 @@ static int process_requests(int sock)
 v9fs_string_free(path);
 v9fs_string_free(name);
 break;
+case T_GETVERSION:
+size = do_getversion(in_iovec, out_iovec);
+break;
 default:
 goto error;
 break;
@@ -777,6 +837,7 @@ static int process_requests(int sock)
 case T_READLINK:
 case T_LGETXATTR:
 case T_LLISTXATTR:
+case T_GETVERSION:
 if (send_response(sock, out_iovec, size)  0) {
 goto error;
 }
@@ -798,6 +859,8 @@ int main(int argc, char **argv)
 char *rpath = NULL;
 struct stat stbuf;
 int c, option_index;
+int retval;
+struct statfs st_fs;
 
 is_daemon = true;
 sock = -1;
@@ -854,6 +917,20 @@ int main(int argc, char **argv)
 
 do_log(LOG_INFO, Started\n);
 
+get_version = false;
+/* check whether underlying FS support IOC_GETVERSION */
+retval = statfs(rpath, st_fs);
+if (!retval) {
+switch (st_fs.f_type) {
+case EXT2_SUPER_MAGIC:
+case BTRFS_SUPER_MAGIC:
+case REISERFS_SUPER_MAGIC:
+case XFS_SUPER_MAGIC:
+get_version = true;
+break;
+}
+}
+
 if (chroot(rpath)  0) {
 do_perror(chroot);
 goto error;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 0d6af6d..44d4860 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -213,6 +213,9 @@ static int v9fs_receive_response(V9fsProxy *proxy, int type,
 }
 break;
 }
+case T_GETVERSION:
+proxy_unmarshal(reply, 1, HDR_SZ, q, response);
+break;
 default:
 *sock_error = 1;
 return -1;
@@ -504,6 +507,16 @@ static int v9fs_request(V9fsProxy *proxy, int type,
 proxy_marshal(iovec, 1, 0, dd, header.type, header.size);
 header.size += HDR_SZ;
 break;
+case T_GETVERSION:
+path = va_arg(ap, V9fsString *);
+header.size = proxy_marshal(iovec, 1, HDR_SZ, s, path);
+if (header.size  0) {
+goto out_overflow;
+}
+header.type = T_GETVERSION;
+proxy_marshal(iovec, 1, 0, dd, header.type, header.size);
+header.size += HDR_SZ;
+break;
 default:
 error_report(Invalid type %d\n, type);
 va_end(ap);
@@ -551,6

[Qemu-devel] [PATCH V3 06/13] hw/9pfs: Create other filesystem objects

2011-11-21 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |  120 ++--
 hw/9pfs/virtio-9p-proxy.c   |  185 +++
 hw/9pfs/virtio-9p-proxy.h   |8 ++-
 3 files changed, 287 insertions(+), 26 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 867fdcc..246be77 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -216,6 +216,28 @@ static void send_fd(int sockfd, int fd)
 }
 }
 
+static int send_status(int sockfd, struct iovec *iovec, int status)
+{
+int retval, msg_size;;
+ProxyHeader header;
+
+if (status  0) {
+header.type = T_ERROR;
+} else {
+header.type = T_SUCCESS;
+}
+header.size = sizeof(status);
+
+/* marshal the return status */
+msg_size = proxy_marshal(iovec, 1, 0, ddd, header.type, header.size,
+status);
+retval = socket_write(sockfd, iovec-iov_base, msg_size);
+if (retval != msg_size) {
+return -EIO;
+}
+return 0;
+}
+
 /*
  * from man 7 capabilities, section
  * Effect of User ID Changes on Capabilities:
@@ -235,6 +257,59 @@ 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)
+{
+dev_t rdev;
+int retval = 0;
+V9fsString oldpath, path;
+int mode, uid, gid, cur_uid, cur_gid;
+int offset = HDR_SZ;
+
+cur_uid = geteuid();
+cur_gid = getegid();
+
+offset += proxy_unmarshal(iovec, 1, offset, dd, uid, gid);
+if (setfsugid(uid, gid)  0) {
+return -EPERM;
+}
+switch (type) {
+case T_MKNOD:
+if (proxy_unmarshal(iovec, 1, offset, sdq, path, mode, rdev)  0) 
{
+retval = -EOVERFLOW;
+goto out;
+}
+retval = mknod(path.data, mode, rdev);
+break;
+case T_MKDIR:
+if (proxy_unmarshal(iovec, 1, offset, sd, path, mode)  0) {
+retval = -EOVERFLOW;
+goto out;
+}
+retval = mkdir(path.data, mode);
+break;
+case T_SYMLINK:
+if (proxy_unmarshal(iovec, 1, offset, ss, oldpath, path)  0) {
+retval = -EOVERFLOW;
+goto out;
+}
+retval = symlink(oldpath.data, path.data);
+v9fs_string_free(oldpath);
+break;
+}
+
+if (retval  0) {
+retval = -errno;
+}
+v9fs_string_free(path);
+out:
+setfsugid(cur_uid, cur_gid);
+return retval;
+}
+
+/*
  * create a file and send fd on success
  * return -errno on error
  */
@@ -294,38 +369,65 @@ static void usage(char *prog)
 static int process_requests(int sock)
 {
 int type, retval = 0;
-struct iovec iovec;
+V9fsString oldpath, path;
+struct iovec in_iovec, out_iovec;
+
+in_iovec.iov_base = g_malloc(BUFF_SZ);
+in_iovec.iov_len = BUFF_SZ;
+out_iovec.iov_base = g_malloc(BUFF_SZ);
+out_iovec.iov_len = BUFF_SZ;
 
-iovec.iov_base = g_malloc(BUFF_SZ);
-iovec.iov_len = BUFF_SZ;
 while (1) {
-type = read_request(sock, iovec);
+type = read_request(sock, in_iovec);
 switch (type) {
 case T_OPEN:
-retval = do_open(iovec);
+retval = do_open(in_iovec);
 break;
 case T_CREATE:
-retval = do_create(iovec);
+retval = do_create(in_iovec);
+break;
+case T_MKNOD:
+case T_MKDIR:
+case T_SYMLINK:
+retval = do_create_others(type, in_iovec);
+break;
+case T_LINK:
+if (proxy_unmarshal(in_iovec, 1, HDR_SZ, ss,
+oldpath, path)  0) {
+retval = -EOVERFLOW;
+break;
+}
+retval = link(oldpath.data, path.data);
+if (retval  0) {
+retval = -errno;
+}
+v9fs_string_free(oldpath);
+v9fs_string_free(path);
 break;
 default:
 goto error;
 break;
 }
-
 /* Send response */
 switch (type) {
 case T_OPEN:
 case T_CREATE:
 send_fd(sock, retval);
 break;
+case T_MKNOD:
+case T_MKDIR:
+case T_SYMLINK:
+case T_LINK:
+send_status(sock, out_iovec, retval);
+break;
 default:
 goto error;
 break;
 }
 }
-(void)socket_write;
 error:
-g_free(iovec.iov_base);
+g_free(in_iovec.iov_base);
+g_free(out_iovec.iov_base);
 return -1;
 }
 
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 3472337..f116773 100644
--- a/hw

[Qemu-devel] [PATCH V3 02/13] hw/9pfs: Add validation to marshal code

2011-11-21 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Add validatio check to {un}marshal code.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtio-9p-marshal.c |   97 ---
 fsdev/virtio-9p-marshal.h |8 +-
 hw/9pfs/virtio-9p.c   |  231 +
 3 files changed, 236 insertions(+), 100 deletions(-)

diff --git a/fsdev/virtio-9p-marshal.c b/fsdev/virtio-9p-marshal.c
index 2da0a34..74161df 100644
--- a/fsdev/virtio-9p-marshal.c
+++ b/fsdev/virtio-9p-marshal.c
@@ -62,14 +62,14 @@ void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
 }
 
 
-static size_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count,
-  size_t offset, size_t size, int pack)
+static ssize_t v9fs_packunpack(void *addr, struct iovec *sg, int sg_count,
+  ssize_t offset, ssize_t size, int pack)
 {
 int i = 0;
-size_t copied = 0;
+ssize_t copied = 0;
 
 for (i = 0; size  i  sg_count; i++) {
-size_t len;
+ssize_t len;
 if (offset = sg[i].iov_len) {
 /* skip this sg */
 offset -= sg[i].iov_len;
@@ -91,25 +91,29 @@ static size_t v9fs_packunpack(void *addr, struct iovec *sg, 
int sg_count,
 }
 }
 
+/* could not copy requested 'size' */
+if (copied  0) {
+return -1;
+}
 return copied;
 }
 
-static size_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num,
-  size_t offset, size_t size)
+static ssize_t v9fs_unpack(void *dst, struct iovec *out_sg, int out_num,
+  ssize_t offset, ssize_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)
+ssize_t v9fs_pack(struct iovec *in_sg, int in_num, ssize_t offset,
+const void *src, ssize_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)
+ssize_t offset, struct iovec *sg)
 {
-size_t pos = 0;
+ssize_t pos = 0;
 int i, j;
 
 j = 0;
@@ -131,10 +135,10 @@ static int v9fs_copy_sg(struct iovec *src_sg, unsigned 
int num,
 return j;
 }
 
-size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, size_t offset,
-int convert, const char *fmt, ...)
+ssize_t v9fs_unmarshal(struct iovec *out_sg,
+int out_num, ssize_t offset, int convert, const char *fmt, ...)
 {
-size_t old_offset = offset;
+ssize_t old_offset = offset, copied;
 va_list ap;
 int i;
 
@@ -143,13 +147,13 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, 
size_t offset,
 switch (fmt[i]) {
 case 'b': {
 uint8_t *valp = va_arg(ap, uint8_t *);
-offset += v9fs_unpack(valp, out_sg, out_num, offset, 
sizeof(*valp));
+copied = 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));
+copied = v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
 if (convert) {
 *valp = le16_to_cpu(val);
 } else {
@@ -160,7 +164,7 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, 
size_t offset,
 case 'd': {
 uint32_t val, *valp;
 valp = va_arg(ap, uint32_t *);
-offset += v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
+copied = v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
 if (convert) {
 *valp = le32_to_cpu(val);
 } else {
@@ -171,7 +175,7 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, 
size_t offset,
 case 'q': {
 uint64_t val, *valp;
 valp = va_arg(ap, uint64_t *);
-offset += v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
+copied = v9fs_unpack(val, out_sg, out_num, offset, sizeof(val));
 if (convert) {
 *valp = le64_to_cpu(val);
 } else {
@@ -187,24 +191,31 @@ size_t v9fs_unmarshal(struct iovec *out_sg, int out_num, 
size_t offset,
 }
 case 's': {
 V9fsString *str = va_arg(ap, V9fsString *);
-offset += v9fs_unmarshal(out_sg, out_num, offset, convert,
+copied = v9fs_unmarshal(out_sg, out_num, offset, convert,
 w, str-size);
-/* FIXME: sanity check str-size */
+if (copied  0) {
+goto out;
+}
+offset += copied;
 str-data = g_malloc(str-size + 1);
-offset += v9fs_unpack(str-data

[Qemu-devel] [PATCH V3 13/13] hw/9pfs: Add support to use named socket for proxy FS

2011-11-21 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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. We can achive the same using a shell script over
qemu and virtfs-proxy-helper using exec fdsocket-path, and then
passing that fd as argument to qemu and virtfs-proxy-helper. Also having
a server like virtfs-proxy-helper listening on a pathname without any
authentication is little bit scary. So we have to decide whether this
patch is really needed.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
Signed-off-by: Aneesh Kumar K.V aneesh.ku...@linux.vnet.ibm.com
---
 fsdev/file-op-9p.h |2 +
 fsdev/virtfs-proxy-helper.c|   86 ++-
 fsdev/virtfs-proxy-helper.texi |4 ++
 hw/9pfs/virtio-9p-proxy.c  |   52 +---
 qemu-config.c  |7 +++
 qemu-options.hx|   15 +--
 vl.c   |6 ++-
 7 files changed, 157 insertions(+), 15 deletions(-)

diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 84e5375..ac98e10 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -57,6 +57,8 @@ typedef struct extended_ops {
  */
 #define V9FS_SM_NONE0x0010
 #define V9FS_RDONLY 0x0020
+#define V9FS_PROXY_SOCK_FD  0x0040
+#define V9FS_PROXY_SOCK_NAME0x0080
 
 #define V9FS_SEC_MASK   0x001C
 
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 08ea316..18ced26 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -76,6 +76,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'},
 };
 
 static bool is_daemon;
@@ -635,11 +638,61 @@ static int do_open(struct iovec *iovec)
 return fd;
 }
 
+/* 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));
 }
@@ -857,16 +910,20 @@ int main(int argc, char **argv)
 {
 int sock;
 char *rpath = NULL;
+char *sock_name = NULL;
 struct stat stbuf;
 int c, option_index;
 int retval;
 struct statfs st_fs;
+uid_t own_u;
+gid_t own_g;
 
 is_daemon = true;
 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;
@@ -881,6 +938,15 @@ int main(int argc, char **argv)
 case 'f':
 sock = atoi(optarg);
 break;
+case 's':
+sock_name = strdup(optarg);
+break;
+case 'u':
+own_u = atoi(optarg);
+break;
+case 'g':
+own_g = atoi(optarg);
+break;
 case '?':
 case 'h':
 default:
@@ -890,8 +956,16 @@ 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

[Qemu-devel] [PATCH V3 05/13] hw/9pfs: Open and create files

2011-11-21 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Add interfaces to open and create files for proxy file system driver.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |  133 ++-
 hw/9pfs/virtio-9p-proxy.c   |  187 +--
 hw/9pfs/virtio-9p-proxy.h   |   14 +++
 3 files changed, 326 insertions(+), 8 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index dc222d4..867fdcc 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -9,6 +9,7 @@
  * the COPYING file in the top-level directory.
  */
 #include stdio.h
+#include sys/socket.h
 #include string.h
 #include sys/un.h
 #include limits.h
@@ -28,6 +29,7 @@
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
+#include fsdev/virtio-9p-marshal.h
 
 #define PROGNAME virtfs-proxy-helper
 
@@ -172,6 +174,114 @@ static int read_request(int sockfd, struct iovec *iovec)
 return header.type;
 }
 
+static void send_fd(int sockfd, int fd)
+{
+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  0) {
+/* fd is really negative errno if the request failed  */
+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 = 0) {
+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;
+
+if (proxy_unmarshal(iovec, 1, HDR_SZ, s,
+   path, flags, mode, uid, gid)  0) {
+return -EOVERFLOW;
+}
+cur_uid = geteuid();
+cur_gid = getegid();
+if (setfsugid(uid, gid)  0) {
+v9fs_string_free(path);
+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;
+
+if (proxy_unmarshal(iovec, 1, HDR_SZ, sd, path, flags)  0) {
+return -EOVERFLOW;
+}
+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
@@ -183,15 +293,34 @@ static void usage(char *prog)
 
 static int process_requests(int sock)
 {
-int type;
+int type, retval = 0;
 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) {
+switch (type) {
+case T_OPEN:
+retval = do_open(iovec);
+break;
+case T_CREATE:
+retval = do_create(iovec);
+break;
+default:
 goto error;
+break;
+}
+
+/* Send response */
+switch (type) {
+case T_OPEN:
+case T_CREATE:
+send_fd(sock, retval);
+break;
+default:
+goto error;
+break;
 }
 }
 (void)socket_write;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 0e539e3..3472337 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -22,6 +22,153 @@ typedef struct V9fsProxy {
 struct iovec iovec

[Qemu-devel] [PATCH V3 08/13] hw/9pfs: File ownership and others

2011-11-21 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@in.ibm.com
---
 Makefile|2 +-
 fsdev/virtfs-proxy-helper.c |   88 +
 hw/9pfs/virtio-9p-proxy.c   |  148 +++
 hw/9pfs/virtio-9p-proxy.h   |6 ++
 4 files changed, 231 insertions(+), 13 deletions(-)

diff --git a/Makefile b/Makefile
index 19b481a..378ee4d 100644
--- a/Makefile
+++ b/Makefile
@@ -153,7 +153,7 @@ qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
 qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
 qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
 
-fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o 
fsdev/virtio-9p-marshal.o
+fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o 
fsdev/virtio-9p-marshal.o oslib-posix.o
 fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
 
 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 7510827..c11538c 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -535,6 +535,9 @@ static void usage(char *prog)
 
 static int process_requests(int sock)
 {
+uint64_t offset;
+int mode, uid, gid;
+struct timespec spec[2];
 int type, retval = 0;
 V9fsString oldpath, path;
 struct iovec in_iovec, out_iovec;
@@ -579,6 +582,85 @@ static int process_requests(int sock)
 case T_READLINK:
 size = do_readlink(in_iovec, out_iovec);
 break;
+case T_CHMOD:
+retval = proxy_unmarshal(in_iovec, 1, HDR_SZ, sd, path, mode);
+if (retval  0) {
+retval = -EOVERFLOW;
+break;
+}
+retval = chmod(path.data, mode);
+if (retval  0) {
+retval = -errno;
+}
+v9fs_string_free(path);
+break;
+case T_CHOWN:
+retval = proxy_unmarshal(in_iovec, 1, HDR_SZ, sdd, path,
+uid, gid);
+if (retval  0) {
+retval = -EOVERFLOW;
+break;
+}
+retval = lchown(path.data, uid, gid);
+if (retval  0) {
+retval = -errno;
+}
+v9fs_string_free(path);
+break;
+case T_TRUNCATE:
+retval = proxy_unmarshal(in_iovec, 1, HDR_SZ, sq,
+path, offset);
+if (retval  0) {
+retval = -EOVERFLOW;
+break;
+}
+retval = truncate(path.data, offset);
+if (retval  0) {
+retval = -errno;
+}
+v9fs_string_free(path);
+break;
+case T_UTIME:
+retval = proxy_unmarshal(in_iovec, 1, HDR_SZ, s, path,
+   spec[0].tv_sec, spec[0].tv_nsec,
+   spec[1].tv_sec, spec[1].tv_nsec);
+if (retval  0) {
+retval = -EOVERFLOW;
+break;
+}
+retval = qemu_utimensat(AT_FDCWD, path.data, spec,
+AT_SYMLINK_NOFOLLOW);
+if (retval  0) {
+retval = -errno;
+}
+v9fs_string_free(path);
+break;
+case T_RENAME:
+retval = proxy_unmarshal(in_iovec, 1,
+   HDR_SZ, ss, oldpath, path);
+if (retval  0) {
+retval = -EOVERFLOW;
+break;
+}
+retval = rename(oldpath.data, path.data);
+if (retval  0) {
+retval = -errno;
+}
+v9fs_string_free(oldpath);
+v9fs_string_free(path);
+break;
+case T_REMOVE:
+retval = proxy_unmarshal(in_iovec, 1, HDR_SZ, s, path);
+if (retval  0) {
+retval = -EOVERFLOW;
+break;
+}
+retval = remove(path.data);
+if (retval  0) {
+retval = -errno;
+}
+v9fs_string_free(path);
+break;
 default:
 goto error;
 break;
@@ -593,6 +675,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:
 send_status(sock, out_iovec, retval);
 break;
 case T_LSTAT:
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index aca799e..186d681 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -246,6 +246,8 @@ static int v9fs_request(V9fsProxy *proxy, int type

[Qemu-devel] [PATCH V3 04/13] hw/9pfs: File system helper process for qemu 9p proxy FS

2011-11-21 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 -f|--fd socket descriptor -p|--path path-to-share

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 Makefile|3 +
 configure   |   19 +++
 fsdev/virtfs-proxy-helper.c |  280 +++
 hw/9pfs/virtio-9p-proxy.h   |7 +-
 4 files changed, 308 insertions(+), 1 deletions(-)
 create mode 100644 fsdev/virtfs-proxy-helper.c

diff --git a/Makefile b/Makefile
index ba8d738..19b481a 100644
--- a/Makefile
+++ b/Makefile
@@ -153,6 +153,9 @@ qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
 qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
 qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
 
+fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o 
fsdev/virtio-9p-marshal.o
+fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
+
 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 a6cf6d6..a2b55e8 100755
--- a/configure
+++ b/configure
@@ -1873,6 +1873,22 @@ 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
+  else
+cap=no
+  fi
+fi
+
+##
 # pthread probe
 PTHREADLIBS_LIST=-pthread -lpthread -lpthreadGC2
 
@@ -2662,6 +2678,9 @@ confdir=$sysconfdir$confsuffix
 tools=
 if test $softmmu = yes ; then
   tools=qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools
+  if [ $cap = yes -a $linux = yes ] ; then
+  tools=$tools fsdev/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
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
new file mode 100644
index 000..dc222d4
--- /dev/null
+++ b/fsdev/virtfs-proxy-helper.c
@@ -0,0 +1,280 @@
+/*
+ * Helper for QEMU Proxy FS Driver
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * M. Mohan Kumar mo...@in.ibm.com
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#include stdio.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 stdbool.h
+#include qemu-common.h
+#include virtio-9p-marshal.h
+#include hw/9pfs/virtio-9p-proxy.h
+
+#define PROGNAME virtfs-proxy-helper
+
+#define do_log(loglevel, fmt, args...) \
+do { \
+if (is_daemon) {\
+syslog(loglevel, fmt, ##args); \
+} else { \
+fprintf(stderr, fmt, ##args); \
+} \
+} while (0)
+
+#define do_perror(string) \
+do { \
+if (is_daemon) {\
+syslog(LOG_CRIT, string :%s, strerror(errno)); \
+} else { \
+fprintf(stderr, string :%s\n, strerror(errno)); \
+} \
+} while (0)
+
+static struct option helper_opts[] = {
+{fd, required_argument, NULL, 'f'},
+{path, required_argument, NULL, 'p'},
+{nodaemon, no_argument, NULL, 'n'},
+};
+
+static bool is_daemon;
+
+static int cap_set(void)
+{
+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;
+}
+if (cap_set_flag(caps, CAP_PERMITTED, 8, cap_list, CAP_SET)  0) {
+do_perror(cap_set_flag);
+goto error;
+}
+if (cap_set_proc(caps)  0) {
+do_perror(cap_set_proc);
+goto error;
+}
+if (cap_set_flag(caps, CAP_EFFECTIVE, 8, cap_list, CAP_SET)) {
+do_perror(cap_set_flag);
+goto error;
+}
+if (cap_set_proc(caps)  0) {
+do_perror(cap_set_proc);
+goto error;
+}
+cap_free(caps);
+return 0;
+
+error:
+cap_free(caps);
+return -1;
+}
+
+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)
+{
+ssize_t retval

[Qemu-devel] [PATCH V3 07/13] hw/9pfs: Add stat/readlink/statfs for proxy FS

2011-11-21 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |  182 +
 hw/9pfs/virtio-9p-proxy.c   |  189 +--
 hw/9pfs/virtio-9p-proxy.h   |   34 
 3 files changed, 397 insertions(+), 8 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 246be77..7510827 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -26,6 +26,8 @@
 #include sys/fsuid.h
 #include stdarg.h
 #include stdbool.h
+#include sys/vfs.h
+#include sys/stat.h
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
@@ -257,6 +259,171 @@ static int setfsugid(int uid, int gid)
 }
 
 /*
+ * send response in two parts
+ * 1) ProxyHeader
+ * 2) Response or error status
+ * This function should be called with marshaling response
+ * send_response constructs header part and error part only.
+ * send response sends {ProxyHeader,Response} if the request was success
+ * otherwise sends {ProxyHeader,error status}
+ */
+static int send_response(int sock, struct iovec *iovec, int size)
+{
+int retval;
+ProxyHeader header;
+
+/*
+ * If response size exceeds available iovec-iov_len,
+ * we return EOVERFLOW
+ */
+if (size  (int)iovec-iov_len) {
+size = -EOVERFLOW;
+}
+
+if (size  0) {
+header.type = T_ERROR;
+header.size = sizeof(size);
+proxy_marshal(iovec, 1, HDR_SZ, d, size);
+} else {
+header.type = T_SUCCESS;
+header.size = size;
+}
+
+proxy_marshal(iovec, 1, 0, dd, header.type, header.size);
+retval = socket_write(sock, iovec-iov_base, header.size + HDR_SZ);
+if (retval != header.size + HDR_SZ) {
+return -EIO;
+}
+return 0;
+}
+
+static void stat_to_prstat(ProxyStat *pr_stat, struct stat *stat)
+{
+memset(pr_stat, 0, sizeof(*pr_stat));
+pr_stat-st_dev = stat-st_dev;
+pr_stat-st_ino = stat-st_ino;
+pr_stat-st_nlink = stat-st_nlink;
+pr_stat-st_mode = stat-st_mode;
+pr_stat-st_uid = stat-st_uid;
+pr_stat-st_gid = stat-st_gid;
+pr_stat-st_rdev = stat-st_rdev;
+pr_stat-st_size = stat-st_size;
+pr_stat-st_blksize = stat-st_blksize;
+pr_stat-st_blocks = stat-st_blocks;
+pr_stat-st_atim_sec = stat-st_atim.tv_sec;
+pr_stat-st_atim_nsec = stat-st_atim.tv_nsec;
+pr_stat-st_mtim_sec = stat-st_mtim.tv_sec;
+pr_stat-st_mtim_nsec = stat-st_mtim.tv_nsec;
+pr_stat-st_ctim_sec = stat-st_ctim.tv_sec;
+pr_stat-st_ctim_nsec = stat-st_ctim.tv_nsec;
+}
+
+static void statfs_to_prstatfs(ProxyStatFS *pr_stfs, struct statfs *stfs)
+{
+memset(pr_stfs, 0, sizeof(*pr_stfs));
+pr_stfs-f_type = stfs-f_type;
+pr_stfs-f_bsize = stfs-f_bsize;
+pr_stfs-f_blocks = stfs-f_blocks;
+pr_stfs-f_bfree = stfs-f_bfree;
+pr_stfs-f_bavail = stfs-f_bavail;
+pr_stfs-f_files = stfs-f_files;
+pr_stfs-f_ffree = stfs-f_ffree;
+pr_stfs-f_fsid[0] = stfs-f_fsid.__val[0];
+pr_stfs-f_fsid[1] = stfs-f_fsid.__val[1];
+pr_stfs-f_namelen = stfs-f_namelen;
+pr_stfs-f_frsize = stfs-f_frsize;
+}
+
+/*
+ * Gets stat/statfs information and packs in out_iovec structure
+ * on success returns number of bytes packed in out_iovec struture
+ * otherwise returns -errno
+ */
+static int do_stat(int type, struct iovec *iovec, struct iovec *out_iovec)
+{
+V9fsString path;
+struct stat st_buf;
+ProxyStat pr_stat;
+struct statfs stfs_buf;
+ProxyStatFS pr_stfs;
+int retval = 0;
+
+if (proxy_unmarshal(iovec, 1, HDR_SZ, s, path)  0) {
+return -EOVERFLOW;
+}
+
+switch (type) {
+case T_LSTAT:
+retval = lstat(path.data, st_buf);
+if (retval  0) {
+retval = -errno;
+} else {
+stat_to_prstat(pr_stat, st_buf);
+retval = proxy_marshal(out_iovec, 1, HDR_SZ,
+qqqdddqq, pr_stat.st_dev,
+pr_stat.st_ino, pr_stat.st_nlink,
+pr_stat.st_mode, pr_stat.st_uid,
+pr_stat.st_gid, pr_stat.st_rdev,
+pr_stat.st_size, pr_stat.st_blksize,
+pr_stat.st_blocks,
+pr_stat.st_atim_sec, pr_stat.st_atim_nsec,
+pr_stat.st_mtim_sec, pr_stat.st_mtim_nsec,
+pr_stat.st_ctim_sec, pr_stat.st_ctim_nsec);
+if (retval  0) {
+retval = -EOVERFLOW;
+}
+}
+break;
+case T_STATFS:
+retval = statfs(path.data, stfs_buf);
+if (retval  0) {
+retval = -errno;
+} else {
+statfs_to_prstatfs(pr_stfs, stfs_buf);
+retval = proxy_marshal(out_iovec, 1, HDR_SZ,
+qqq, pr_stfs.f_type, pr_stfs.f_bsize

[Qemu-devel] [PATCH V3 09/13] hw/9pfs: xattr interfaces in proxy filesystem driver

2011-11-21 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Add xattr support for proxy FS

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |   93 ++-
 hw/9pfs/virtio-9p-proxy.c   |  130 +++---
 hw/9pfs/virtio-9p-proxy.h   |4 +
 3 files changed, 216 insertions(+), 11 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index c11538c..652fda6 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -28,6 +28,7 @@
 #include stdbool.h
 #include sys/vfs.h
 #include sys/stat.h
+#include attr/xattr.h
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
@@ -297,6 +298,59 @@ static int send_response(int sock, struct iovec *iovec, 
int size)
 return 0;
 }
 
+static int do_getxattr(int type, struct iovec *iovec, struct iovec *out_iovec)
+{
+int size = 0, offset, retval;
+V9fsString path, name, xattr;
+
+v9fs_string_init(xattr);
+retval = proxy_unmarshal(iovec, 1, HDR_SZ, ds, size, path);
+if (retval  0) {
+return -EOVERFLOW;
+}
+offset = HDR_SZ + retval;
+
+if (size) {
+xattr.data = g_malloc(size);
+xattr.size = size;
+}
+switch (type) {
+case T_LGETXATTR:
+if (proxy_unmarshal(iovec, 1, offset, s, name)) {
+retval = -EOVERFLOW;
+goto error;
+}
+retval = lgetxattr(path.data, name.data, xattr.data, size);
+if (retval  0) {
+retval = -errno;
+v9fs_string_free(name);
+goto error;
+}
+v9fs_string_free(name);
+break;
+case T_LLISTXATTR:
+retval = llistxattr(path.data, xattr.data, size);
+if (retval  0) {
+retval = -errno;
+goto error;
+}
+break;
+}
+
+if (!size) {
+proxy_marshal(out_iovec, 1, HDR_SZ, d, retval);
+retval = sizeof(retval);
+} else {
+retval = proxy_marshal(out_iovec, 1, HDR_SZ, s, xattr);
+if (retval  0) {
+retval = -EOVERFLOW;
+}
+}
+error:
+v9fs_string_free(path);
+return retval;
+}
+
 static void stat_to_prstat(ProxyStat *pr_stat, struct stat *stat)
 {
 memset(pr_stat, 0, sizeof(*pr_stat));
@@ -539,9 +593,10 @@ static int process_requests(int sock)
 int mode, uid, gid;
 struct timespec spec[2];
 int type, retval = 0;
+V9fsString name, value;
 V9fsString oldpath, path;
 struct iovec in_iovec, out_iovec;
-int size = 0;
+int size = 0, flags;
 
 in_iovec.iov_base = g_malloc(BUFF_SZ);
 in_iovec.iov_len = BUFF_SZ;
@@ -661,6 +716,38 @@ static int process_requests(int sock)
 }
 v9fs_string_free(path);
 break;
+case T_LGETXATTR:
+case T_LLISTXATTR:
+size = do_getxattr(type, in_iovec, out_iovec);
+break;
+case T_LSETXATTR:
+retval = proxy_unmarshal(in_iovec, 1, HDR_SZ, sssdd, path,
+name, value, size, flags);
+if (retval  0) {
+retval = -EOVERFLOW;
+break;
+}
+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:
+retval = proxy_unmarshal(in_iovec, 1, HDR_SZ, ss, path, name);
+if (retval  0) {
+retval = -EOVERFLOW;
+break;
+}
+retval = lremovexattr(path.data, name.data);
+if (retval  0) {
+retval = -errno;
+}
+v9fs_string_free(path);
+v9fs_string_free(name);
+break;
 default:
 goto error;
 break;
@@ -681,11 +768,15 @@ static int process_requests(int sock)
 case T_UTIME:
 case T_RENAME:
 case T_REMOVE:
+case T_LSETXATTR:
+case T_LREMOVEXATTR:
 send_status(sock, out_iovec, retval);
 break;
 case T_LSTAT:
 case T_STATFS:
 case T_READLINK:
+case T_LGETXATTR:
+case T_LLISTXATTR:
 if (send_response(sock, out_iovec, size)  0) {
 goto error;
 }
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 186d681..0d6af6d 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -136,7 +136,7 @@ static void prstat_to_stat(struct stat *stbuf, ProxyStat 
*prstat)
  * size of errno/response is given by header.size
  */
 static int v9fs_receive_response(V9fsProxy *proxy, int type,
-int *sock_error, void *response)
+int *sock_error, int size, void *response)
 {
 int retval

[Qemu-devel] [PATCH V3 01/13] hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file

2011-11-21 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@in.ibm.com
---
 Makefile.objs |2 +-
 fsdev/virtio-9p-marshal.c |  338 +
 fsdev/virtio-9p-marshal.h |   87 
 hw/9pfs/virtio-9p.c   |  297 +---
 hw/9pfs/virtio-9p.h   |   83 +--
 5 files changed, 438 insertions(+), 369 deletions(-)
 create mode 100644 fsdev/virtio-9p-marshal.c
 create mode 100644 fsdev/virtio-9p-marshal.h

diff --git a/Makefile.objs b/Makefile.objs
index d7a6539..c256fdc 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -61,7 +61,7 @@ ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
 # Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
 # only pull in the actual virtio-9p device if we also enabled virtio.
 CONFIG_REALLY_VIRTFS=y
-fsdev-nested-y = qemu-fsdev.o
+fsdev-nested-y = qemu-fsdev.o virtio-9p-marshal.o
 else
 fsdev-nested-y = qemu-fsdev-dummy.o
 endif
diff --git a/fsdev/virtio-9p-marshal.c b/fsdev/virtio-9p-marshal.c
new file mode 100644
index 000..2da0a34
--- /dev/null
+++ b/fsdev/virtio-9p-marshal.c
@@ -0,0 +1,338 @@
+/*
+ * Virtio 9p backend
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   aligu...@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 glib.h
+#include glib/gprintf.h
+#include sys/types.h
+#include dirent.h
+#include sys/time.h
+#include utime.h
+#include sys/uio.h
+#include string.h
+#include stdint.h
+
+#include compiler.h
+#include virtio-9p-marshal.h
+#include bswap.h
+
+void v9fs_string_init(V9fsString *str)
+{
+str-data = NULL;
+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);
+}
+
+void GCC_FMT_ATTR(2, 3)
+v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
+{
+va_list ap;
+
+v9fs_string_free(str);
+
+va_start(ap, fmt);
+str-size = g_vasprintf(str-data, fmt, ap);
+va_end(ap);
+}
+
+void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
+{
+v9fs_string_free(lhs);
+v9fs_string_sprintf(lhs, %s, rhs-data);
+}
+
+
+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,
+int convert, 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

[Qemu-devel] [PATCH V3 12/13] hw/9pfs: man page for proxy helper

2011-11-21 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 Makefile   |   12 +++-
 fsdev/virtfs-proxy-helper.texi |   59 
 2 files changed, 70 insertions(+), 1 deletions(-)
 create mode 100644 fsdev/virtfs-proxy-helper.texi

diff --git a/Makefile b/Makefile
index 378ee4d..29ae332 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+=fsdev/virtfs-proxy-helper.1
 else
 DOCS=
 endif
@@ -280,7 +281,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) fsdev/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
@@ -358,6 +362,12 @@ qemu-img.1: qemu-img.texi qemu-img-cmds.texi
  pod2man --section=1 --center=  --release=  qemu-img.pod  $@, \
GEN   $@)
 
+fsdev/virtfs-proxy-helper.1: fsdev/virtfs-proxy-helper.texi
+   $(call quiet-command, \
+ perl -Ww -- $(SRC_PATH)/scripts/texi2pod.pl $ 
fsdev/virtfs-proxy-helper.pod  \
+ pod2man --section=1 --center=  --release=  
fsdev/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/fsdev/virtfs-proxy-helper.texi b/fsdev/virtfs-proxy-helper.texi
new file mode 100644
index 000..3816382
--- /dev/null
+++ b/fsdev/virtfs-proxy-helper.texi
@@ -0,0 +1,59 @@
+@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 -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




[Qemu-devel] [PATCH V3 00/13] Proxy FS driver for VirtFS

2011-11-21 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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)

Changes from previous version V2:
* Added check to handle failures in marshaling/unmarshaling code. Also make
  sure that request/response will not exceed maximum buffer size (BUFF_SZ)
* Addressed Stefan's review comments

Changes from previous version:
*) Communication between qemu and helper process is similar to 9p way of packing
elements (pdu marshaling).

Tested with fsstress.

M. Mohan Kumar (13):
  hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file
  hw/9pfs: Validating marshal code
  hw/9pfs: Add new proxy filesystem driver
  hw/9pfs: File system helper process for qemu 9p 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
  hw/9pfs: Add support to use named socket for proxy FS

 Makefile   |   15 +-
 Makefile.objs  |4 +-
 configure  |   19 +
 fsdev/file-op-9p.h |3 +-
 fsdev/qemu-fsdev.c |1 +
 fsdev/qemu-fsdev.h |1 +
 fsdev/virtfs-proxy-helper.c| 1029 ++
 fsdev/virtfs-proxy-helper.texi |   63 +++
 fsdev/virtio-9p-marshal.c  |  365 +
 fsdev/virtio-9p-marshal.h  |   87 +++
 hw/9pfs/virtio-9p-proxy.c  | 1181 
 hw/9pfs/virtio-9p-proxy.h  |   80 +++
 hw/9pfs/virtio-9p.c|  524 ++
 hw/9pfs/virtio-9p.h|   83 +---
 qemu-config.c  |   13 +
 qemu-options.hx|   32 +-
 vl.c   |   10 +-
 17 files changed, 3069 insertions(+), 441 deletions(-)
 create mode 100644 fsdev/virtfs-proxy-helper.c
 create mode 100644 fsdev/virtfs-proxy-helper.texi
 create mode 100644 fsdev/virtio-9p-marshal.c
 create mode 100644 fsdev/virtio-9p-marshal.h
 create mode 100644 hw/9pfs/virtio-9p-proxy.c
 create mode 100644 hw/9pfs/virtio-9p-proxy.h

-- 
1.7.6




[Qemu-devel] [PATCH V3 03/13] hw/9pfs: Add new proxy filesystem driver

2011-11-21 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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,socket_fd=socket-fd

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 Makefile.objs |2 +-
 fsdev/file-op-9p.h|1 -
 fsdev/qemu-fsdev.c|1 +
 fsdev/qemu-fsdev.h|1 +
 fsdev/virtio-9p-marshal.h |2 +-
 hw/9pfs/virtio-9p-proxy.c |  374 +
 hw/9pfs/virtio-9p-proxy.h |   10 ++
 qemu-config.c |6 +
 vl.c  |6 +-
 9 files changed, 399 insertions(+), 4 deletions(-)
 create mode 100644 hw/9pfs/virtio-9p-proxy.c
 create mode 100644 hw/9pfs/virtio-9p-proxy.h

diff --git a/Makefile.objs b/Makefile.objs
index c256fdc..8201202 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -311,7 +311,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-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/file-op-9p.h b/fsdev/file-op-9p.h
index 22849c9..84e5375 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -60,7 +60,6 @@ typedef struct extended_ops {
 
 #define V9FS_SEC_MASK   0x001C
 
-
 typedef struct FileOperations FileOperations;
 /*
  * Structure to store the various fsdev's passed through command line.
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/fsdev/virtio-9p-marshal.h b/fsdev/virtio-9p-marshal.h
index b268cbf..36302b7 100644
--- a/fsdev/virtio-9p-marshal.h
+++ b/fsdev/virtio-9p-marshal.h
@@ -30,7 +30,7 @@ typedef struct V9fsStat
 V9fsString muid;
 /* 9p2000.u */
 V9fsString extension;
-   int32_t n_uid;
+int32_t n_uid;
 int32_t n_gid;
 int32_t n_muid;
 } V9fsStat;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
new file mode 100644
index 000..0e539e3
--- /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 mo...@in.ibm.com
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+#include sys/socket.h
+#include sys/un.h
+#include hw/virtio.h
+#include virtio-9p.h
+#include fsdev/qemu-fsdev.h
+#include virtio-9p-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

[Qemu-devel] [PATCH V3 11/13] hw/9pfs: Documentation changes related to proxy fs

2011-11-21 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 qemu-options.hx |   25 -
 1 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index 681eaf1..cde17ed 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -530,19 +530,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][,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][,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}
@@ -559,7 +559,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.
@@ -569,6 +569,10 @@ 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 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.
@@ -589,19 +593,19 @@ DEFHEADING(Virtual File system pass-through options:)
 
 DEF(virtfs, HAS_ARG, QEMU_OPTION_virtfs,
 -virtfs 
local,path=path,mount_tag=tag,security_model=[mapped|passthrough|none]\n
-[,writeout=immediate][,readonly]\n,
+[,writeout=immediate][,readonly][,sock_fd=sock_fd]\n,
 QEMU_ARCH_ALL)
 
 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][,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}
@@ -618,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.
@@ -628,6 +632,9 @@ 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 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




Re: [Qemu-devel] [PATCH V2 03/12] hw/9pfs: File system helper process for qemu 9p proxy FS

2011-11-16 Thread M. Mohan Kumar

Stefan Hajnoczi wrote:

On Tue, Nov 15, 2011 at 11:57 AM, M. Mohan Kumarmo...@in.ibm.com  wrote:
   

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
new file mode 100644
index 000..69daf7c
--- /dev/null
+++ b/fsdev/virtfs-proxy-helper.c
@@ -0,0 +1,271 @@
+/*
+ * Helper for QEMU Proxy FS Driver
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * M. Mohan Kumarmo...@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.
+ */
+#includestdio.h
+#includesys/socket.h
+#includestring.h
+#includesys/un.h
+#includelimits.h
+#includesignal.h
+#includeerrno.h
+#includestdlib.h
+#includesys/resource.h
+#includesys/stat.h
+#includegetopt.h
+#includeunistd.h
+#includesyslog.h
+#includesys/prctl.h
+#includesys/capability.h
+#includesys/fsuid.h
+#includestdarg.h
+#include bswap.h
 

Where is bswap.h used and why abovesys/socket.h?
   

I will fix it
   

+#includesys/socket.h
+#include qemu-common.h
+#include virtio-9p-marshal.h
+#include hw/9pfs/virtio-9p-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?

Also, please use the bool type fromstdbool.h, it makes it easier
for readers who don't have to guess how the variable works (might be a
bitfield or reference count too).

   

I will fix it.

+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) {
+return -EIO;
+}
 

Shouldn't this loop until size bytes have been read?

   

Ok, I will fix this.

+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) {
+return -EIO;
 

We could pass the actual -errno here if retval  0.

   

Socket errors are treated fatal and the reason for failures are not used
by the code. When ever there is socket error, helper exits.



+}
+return retval;
+}
+
+static int read_request(int sockfd, struct iovec *iovec)
+{
+int retval;
+ProxyHeader header;
+
+/* read the header */
+retval = socket_read(sockfd, iovec-iov_base, sizeof(header));
+if (retval != sizeof(header)) {
+return -EIO;
+}
+/* unmarshal header */
+proxy_unmarshal(iovec, 1, 0, dd,header.type,header.size);
+/* read the request */
+retval = socket_read(sockfd, iovec-iov_base + sizeof(header), 
header.size);
+if (retval != header.size) {
+return -EIO;
+}
+return header.type;
+}
 

Size checks are missing and we're trusting what the client sends!
   

Could you please elaborate?
   

+
+static void usage(char *prog)
+{
+fprintf(stderr, usage: %s\n
+ -p|--pathpath  9p path to export\n
+ {-f|--fdsocket-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);
 

Buffer overflow.  The whole thing would be simpler like this:

const char *rpath = ;
[...]
 case 'p':
 rpath = optarg;
 break;

   

I will fix it

+break;
+case 'n':
+is_daemon = 0;
+break;
+case 'f':
+sock = atoi(optarg);
+break;
+case '?':
+case 'h':
+default:
+usage(argv[0]);
+return -1;
 

The convention is for programs to exit with 1 (EXIT_FAILURE) on error.

   

I will fix it.

+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);
 

sterror() would provide 

[Qemu-devel] [PATCH V2 00/12] Proxy FS driver for VirtFS

2011-11-15 Thread M. Mohan Kumar
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)

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: 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
  hw/9pfs: Add support to use named socket for proxy FS

 Makefile   |   15 +-
 Makefile.objs  |4 +-
 configure  |   19 +
 fsdev/file-op-9p.h |3 +-
 fsdev/qemu-fsdev.c |1 +
 fsdev/qemu-fsdev.h |1 +
 fsdev/virtfs-proxy-helper.c|  947 +
 fsdev/virtfs-proxy-helper.texi |   63 +++
 fsdev/virtio-9p-marshal.c  |  338 
 fsdev/virtio-9p-marshal.h  |   87 +++
 hw/9pfs/virtio-9p-proxy.c  | 1123 
 hw/9pfs/virtio-9p-proxy.h  |   80 +++
 hw/9pfs/virtio-9p.c|  297 +---
 hw/9pfs/virtio-9p.h|   85 +---
 qemu-config.c  |   13 +
 qemu-options.hx|   32 +-
 vl.c   |   10 +-
 17 files changed, 2736 insertions(+), 382 deletions(-)
 create mode 100644 fsdev/virtfs-proxy-helper.c
 create mode 100644 fsdev/virtfs-proxy-helper.texi
 create mode 100644 fsdev/virtio-9p-marshal.c
 create mode 100644 fsdev/virtio-9p-marshal.h
 create mode 100644 hw/9pfs/virtio-9p-proxy.c
 create mode 100644 hw/9pfs/virtio-9p-proxy.h

-- 
1.7.6




[Qemu-devel] [PATCH V2 07/12] hw/9pfs: File ownership and others

2011-11-15 Thread M. Mohan Kumar
Add file ownership interfaces like chmod/chown, utime update, rename,
remove and truncating files for proxy FS

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 Makefile|2 +-
 fsdev/virtfs-proxy-helper.c |   66 +
 hw/9pfs/virtio-9p-proxy.c   |  134 +++
 hw/9pfs/virtio-9p-proxy.h   |6 ++
 4 files changed, 195 insertions(+), 13 deletions(-)

diff --git a/Makefile b/Makefile
index 19b481a..378ee4d 100644
--- a/Makefile
+++ b/Makefile
@@ -153,7 +153,7 @@ qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
 qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
 qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
 
-fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o 
fsdev/virtio-9p-marshal.o
+fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o 
fsdev/virtio-9p-marshal.o oslib-posix.o
 fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
 
 qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index eb33504..ded0ead 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -495,6 +495,9 @@ static void usage(char *prog)
 
 static int process_requests(int sock)
 {
+uint64_t offset;
+int mode, uid, gid;
+struct timespec spec[2];
 int type, retval = 0;
 V9fsString oldpath, path;
 struct iovec in_iovec, out_iovec;
@@ -535,6 +538,63 @@ static int process_requests(int sock)
 case T_READLINK:
 size = do_readlink(in_iovec, out_iovec);
 break;
+case T_CHMOD:
+proxy_unmarshal(in_iovec, 1, HDR_SZ, sd,
+path, mode);
+retval = chmod(path.data, mode);
+if (retval  0) {
+retval = -errno;
+}
+v9fs_string_free(path);
+break;
+case T_CHOWN:
+proxy_unmarshal(in_iovec, 1, HDR_SZ, sdd, path,
+uid, gid);
+retval = lchown(path.data, uid, gid);
+if (retval  0) {
+retval = -errno;
+}
+v9fs_string_free(path);
+break;
+case T_TRUNCATE:
+proxy_unmarshal(in_iovec, 1, HDR_SZ, sq,
+path, offset);
+retval = truncate(path.data, offset);
+if (retval  0) {
+retval = -errno;
+}
+v9fs_string_free(path);
+break;
+case T_UTIME:
+proxy_unmarshal(in_iovec, 1,
+   HDR_SZ, s, path,
+   spec[0].tv_sec, spec[0].tv_nsec,
+   spec[1].tv_sec, spec[1].tv_nsec);
+retval = qemu_utimensat(AT_FDCWD, path.data, spec,
+AT_SYMLINK_NOFOLLOW);
+if (retval  0) {
+retval = -errno;
+}
+v9fs_string_free(path);
+break;
+case T_RENAME:
+proxy_unmarshal(in_iovec, 1,
+   HDR_SZ, 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:
+proxy_unmarshal(in_iovec, 1, HDR_SZ, s, path);
+retval = remove(path.data);
+if (retval  0) {
+retval = -errno;
+}
+v9fs_string_free(path);
+break;
 default:
 goto error;
 break;
@@ -550,6 +610,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:
 send_status(sock, out_iovec, retval);
 break;
 case T_LSTAT:
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 090db44..aefdc61 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -242,6 +242,8 @@ static int v9fs_request(V9fsProxy *proxy, int type,
 struct iovec *iovec = NULL, *reply = NULL;
 dev_t rdev;
 int size = 0;
+struct timespec spec[2];
+uint64_t offset;
 
 qemu_mutex_lock(proxy-mutex);
 
@@ -339,6 +341,63 @@ static int v9fs_request(V9fsProxy *proxy, int type,
 proxy_marshal(iovec, 1, 0, dd, header.type, header.size);
 header.size += HDR_SZ;
 break;
+case T_CHMOD:
+path = va_arg(ap, V9fsString *);
+mode = va_arg(ap, int);
+header.size = proxy_marshal(iovec, 1, HDR_SZ, sd,
+   path, mode);
+header.type = T_CHMOD;
+proxy_marshal(iovec, 1, 0, dd, header.type, header.size

[Qemu-devel] [PATCH V2 05/12] hw/9pfs: Create other filesystem objects

2011-11-15 Thread M. Mohan Kumar
Add interfaces to create filesystem objects like directory,
device nodes, symbolic links, links for proxy filesytem driver

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |  105 --
 hw/9pfs/virtio-9p-proxy.c   |  173 +++
 hw/9pfs/virtio-9p-proxy.h   |8 ++-
 3 files changed, 261 insertions(+), 25 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 68d27f1..377e91a 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -210,6 +210,28 @@ static void send_fd(int sockfd, int fd)
 }
 }
 
+static int send_status(int sockfd, struct iovec *iovec, int status)
+{
+int retval, msg_size;;
+ProxyHeader header;
+
+if (status  0) {
+header.type = T_ERROR;
+} else {
+header.type = T_SUCCESS;
+}
+header.size = sizeof(status);
+
+/* marshal the return status */
+msg_size = proxy_marshal(iovec, 1, 0, ddd, header.type, header.size,
+status);
+retval = socket_write(sockfd, iovec-iov_base, msg_size);
+if (retval != msg_size) {
+return -EIO;
+}
+return 0;
+}
+
 /*
  * from man 7 capabilities, section
  * Effect of User ID Changes on Capabilities:
@@ -229,6 +251,49 @@ 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)
+{
+dev_t rdev;
+int retval = 0;
+V9fsString oldpath, path;
+int mode, uid, gid, cur_uid, cur_gid;
+int offset = HDR_SZ;
+
+cur_uid = geteuid();
+cur_gid = getegid();
+
+offset += proxy_unmarshal(iovec, 1, offset, dd, uid, gid);
+if (setfsugid(uid, gid)  0) {
+return -EPERM;
+}
+switch (type) {
+case T_MKNOD:
+proxy_unmarshal(iovec, 1, offset, sdq, path, mode, rdev);
+retval = mknod(path.data, mode, rdev);
+break;
+case T_MKDIR:
+proxy_unmarshal(iovec, 1, offset, sd, path, mode);
+retval = mkdir(path.data, mode);
+break;
+case T_SYMLINK:
+proxy_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
  */
@@ -281,18 +346,36 @@ static void usage(char *prog)
 static int process_requests(int sock)
 {
 int type, retval = 0;
-struct iovec iovec;
+V9fsString oldpath, path;
+struct iovec in_iovec, out_iovec;
+
+in_iovec.iov_base = g_malloc(BUFF_SZ);
+in_iovec.iov_len = BUFF_SZ;
+out_iovec.iov_base = g_malloc(BUFF_SZ);
+out_iovec.iov_len = BUFF_SZ;
 
-iovec.iov_base = g_malloc(BUFF_SZ);
-iovec.iov_len = BUFF_SZ;
 while (1) {
-type = read_request(sock, iovec);
+type = read_request(sock, in_iovec);
 switch (type) {
 case T_OPEN:
-retval = do_open(iovec);
+retval = do_open(in_iovec);
 break;
 case T_CREATE:
-retval = do_create(iovec);
+retval = do_create(in_iovec);
+break;
+case T_MKNOD:
+case T_MKDIR:
+case T_SYMLINK:
+retval = do_create_others(type, in_iovec);
+break;
+case T_LINK:
+proxy_unmarshal(in_iovec, 1, HDR_SZ, 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;
@@ -305,14 +388,20 @@ static int process_requests(int sock)
 case T_CREATE:
 send_fd(sock, retval);
 break;
+case T_MKNOD:
+case T_MKDIR:
+case T_SYMLINK:
+case T_LINK:
+send_status(sock, out_iovec, retval);
+break;
 default:
 goto error;
 break;
 }
 }
-(void)socket_write;
 error:
-g_free(iovec.iov_base);
+g_free(in_iovec.iov_base);
+g_free(out_iovec.iov_base);
 return -1;
 }
 
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index 8cc55d6..683d762 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -19,7 +19,8 @@
 typedef struct V9fsProxy {
 int sockfd;
 QemuMutex mutex;
-struct iovec iovec;
+struct iovec in_iovec;
+struct iovec out_iovec;
 } V9fsProxy;
 
 /*
@@ -79,6 +80,38 @@ static int v9fs_receivefd(int sockfd, int *sock_error)
 return -ENFILE; /* Ancillary data sent but not received */
 }
 
+static ssize_t socket_read(int sockfd, void *buff, size_t size

[Qemu-devel] [PATCH V2 06/12] hw/9pfs: Add stat/readlink/statfs for proxy FS

2011-11-15 Thread M. Mohan Kumar
Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |  165 
 hw/9pfs/virtio-9p-proxy.c   |  174 +--
 hw/9pfs/virtio-9p-proxy.h   |   34 +
 3 files changed, 367 insertions(+), 6 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 377e91a..eb33504 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -27,6 +27,8 @@
 #include stdarg.h
 #include bswap.h
 #include sys/socket.h
+#include sys/vfs.h
+#include sys/stat.h
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
@@ -251,6 +253,154 @@ static int setfsugid(int uid, int gid)
 }
 
 /*
+ * send response in two parts
+ * 1) ProxyHeader
+ * 2) Response or error status
+ * This function should be called with marshaling response
+ * send_response constructs header part and error part only.
+ * send response sends {ProxyHeader,Response} if the request was success
+ * otherwise sends {ProxyHeader,error status}
+ */
+static int send_response(int sock, struct iovec *iovec, int size)
+{
+int retval;
+ProxyHeader header;
+
+if (size  0) {
+header.type = T_ERROR;
+header.size = sizeof(size);
+proxy_marshal(iovec, 1, HDR_SZ, d, size);
+} else {
+header.type = T_SUCCESS;
+header.size = size;
+}
+
+proxy_marshal(iovec, 1, 0, dd, header.type, header.size);
+retval = socket_write(sock, iovec-iov_base, header.size + HDR_SZ);
+if (retval != header.size + HDR_SZ) {
+return -EIO;
+}
+return 0;
+}
+
+static void stat_to_prstat(ProxyStat *pr_stat, struct stat *stat)
+{
+memset(pr_stat, 0, sizeof(*pr_stat));
+pr_stat-st_dev = stat-st_dev;
+pr_stat-st_ino = stat-st_ino;
+pr_stat-st_nlink = stat-st_nlink;
+pr_stat-st_mode = stat-st_mode;
+pr_stat-st_uid = stat-st_uid;
+pr_stat-st_gid = stat-st_gid;
+pr_stat-st_rdev = stat-st_rdev;
+pr_stat-st_size = stat-st_size;
+pr_stat-st_blksize = stat-st_blksize;
+pr_stat-st_blocks = stat-st_blocks;
+pr_stat-st_atim_sec = stat-st_atim.tv_sec;
+pr_stat-st_atim_nsec = stat-st_atim.tv_nsec;
+pr_stat-st_mtim_sec = stat-st_mtim.tv_sec;
+pr_stat-st_mtim_nsec = stat-st_mtim.tv_nsec;
+pr_stat-st_ctim_sec = stat-st_ctim.tv_sec;
+pr_stat-st_ctim_nsec = stat-st_ctim.tv_nsec;
+}
+
+static void statfs_to_prstatfs(ProxyStatFS *pr_stfs, struct statfs *stfs)
+{
+memset(pr_stfs, 0, sizeof(*pr_stfs));
+pr_stfs-f_type = stfs-f_type;
+pr_stfs-f_bsize = stfs-f_bsize;
+pr_stfs-f_blocks = stfs-f_blocks;
+pr_stfs-f_bfree = stfs-f_bfree;
+pr_stfs-f_bavail = stfs-f_bavail;
+pr_stfs-f_files = stfs-f_files;
+pr_stfs-f_ffree = stfs-f_ffree;
+pr_stfs-f_fsid[0] = stfs-f_fsid.__val[0];
+pr_stfs-f_fsid[1] = stfs-f_fsid.__val[1];
+pr_stfs-f_namelen = stfs-f_namelen;
+pr_stfs-f_frsize = stfs-f_frsize;
+}
+
+/*
+ * Gets stat/statfs information and packs in out_iovec structure
+ * on success returns number of bytes packed in out_iovec struture
+ * otherwise returns -errno
+ */
+static int do_stat(int type, struct iovec *iovec, struct iovec *out_iovec)
+{
+V9fsString path;
+int retval = 0;
+
+proxy_unmarshal(iovec, 1, HDR_SZ, s, path);
+
+switch (type) {
+case T_LSTAT: {
+struct stat st_buf;
+ProxyStat pr_stat;
+
+retval = lstat(path.data, st_buf);
+if (retval  0) {
+retval = -errno;
+} else {
+stat_to_prstat(pr_stat, st_buf);
+retval = proxy_marshal(out_iovec, 1, HDR_SZ,
+qqqdddqq, pr_stat.st_dev,
+pr_stat.st_ino, pr_stat.st_nlink,
+pr_stat.st_mode, pr_stat.st_uid,
+pr_stat.st_gid, pr_stat.st_rdev,
+pr_stat.st_size, pr_stat.st_blksize,
+pr_stat.st_blocks,
+pr_stat.st_atim_sec, pr_stat.st_atim_nsec,
+pr_stat.st_mtim_sec, pr_stat.st_mtim_nsec,
+pr_stat.st_ctim_sec, pr_stat.st_ctim_nsec);
+}
+break;
+}
+case T_STATFS: {
+struct statfs stfs_buf;
+ProxyStatFS pr_stfs;
+
+retval = statfs(path.data, stfs_buf);
+if (retval  0) {
+retval = -errno;
+} else {
+statfs_to_prstatfs(pr_stfs, stfs_buf);
+retval = proxy_marshal(out_iovec, 1, HDR_SZ,
+qqq, pr_stfs.f_type, pr_stfs.f_bsize,
+pr_stfs.f_blocks, pr_stfs.f_bfree, 
pr_stfs.f_bavail,
+pr_stfs.f_files, pr_stfs.f_ffree,
+pr_stfs.f_fsid[0], pr_stfs.f_fsid[1],
+pr_stfs.f_namelen, pr_stfs.f_frsize);
+}
+break

[Qemu-devel] [PATCH V2 02/12] hw/9pfs: Add new proxy filesystem driver

2011-11-15 Thread M. Mohan Kumar
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,socket_fd=socket-fd

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 Makefile.objs |2 +-
 fsdev/file-op-9p.h|1 -
 fsdev/qemu-fsdev.c|1 +
 fsdev/qemu-fsdev.h|1 +
 fsdev/virtio-9p-marshal.h |2 +-
 hw/9pfs/virtio-9p-proxy.c |  374 +
 hw/9pfs/virtio-9p-proxy.h |   10 ++
 qemu-config.c |6 +
 vl.c  |6 +-
 9 files changed, 399 insertions(+), 4 deletions(-)
 create mode 100644 hw/9pfs/virtio-9p-proxy.c
 create mode 100644 hw/9pfs/virtio-9p-proxy.h

diff --git a/Makefile.objs b/Makefile.objs
index c256fdc..8201202 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -311,7 +311,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-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/file-op-9p.h b/fsdev/file-op-9p.h
index 22849c9..84e5375 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -60,7 +60,6 @@ typedef struct extended_ops {
 
 #define V9FS_SEC_MASK   0x001C
 
-
 typedef struct FileOperations FileOperations;
 /*
  * Structure to store the various fsdev's passed through command line.
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/fsdev/virtio-9p-marshal.h b/fsdev/virtio-9p-marshal.h
index fe2d34b..45dba20 100644
--- a/fsdev/virtio-9p-marshal.h
+++ b/fsdev/virtio-9p-marshal.h
@@ -30,7 +30,7 @@ typedef struct V9fsStat
 V9fsString muid;
 /* 9p2000.u */
 V9fsString extension;
-   int32_t n_uid;
+int32_t n_uid;
 int32_t n_gid;
 int32_t n_muid;
 } V9fsStat;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
new file mode 100644
index 000..0e539e3
--- /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 mo...@in.ibm.com
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+#include sys/socket.h
+#include sys/un.h
+#include hw/virtio.h
+#include virtio-9p.h
+#include fsdev/qemu-fsdev.h
+#include virtio-9p-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

[Qemu-devel] [PATCH V2 01/12] hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file

2011-11-15 Thread M. Mohan Kumar
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 mo...@in.ibm.com
---
 Makefile.objs |2 +-
 fsdev/virtio-9p-marshal.c |  338 +
 fsdev/virtio-9p-marshal.h |   87 
 hw/9pfs/virtio-9p.c   |  297 +---
 hw/9pfs/virtio-9p.h   |   85 ++--
 5 files changed, 440 insertions(+), 369 deletions(-)
 create mode 100644 fsdev/virtio-9p-marshal.c
 create mode 100644 fsdev/virtio-9p-marshal.h

diff --git a/Makefile.objs b/Makefile.objs
index d7a6539..c256fdc 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -61,7 +61,7 @@ ifeq ($(CONFIG_VIRTIO)$(CONFIG_VIRTFS)$(CONFIG_PCI),yyy)
 # Lots of the fsdev/9pcode is pulled in by vl.c via qemu_fsdev_add.
 # only pull in the actual virtio-9p device if we also enabled virtio.
 CONFIG_REALLY_VIRTFS=y
-fsdev-nested-y = qemu-fsdev.o
+fsdev-nested-y = qemu-fsdev.o virtio-9p-marshal.o
 else
 fsdev-nested-y = qemu-fsdev-dummy.o
 endif
diff --git a/fsdev/virtio-9p-marshal.c b/fsdev/virtio-9p-marshal.c
new file mode 100644
index 000..2da0a34
--- /dev/null
+++ b/fsdev/virtio-9p-marshal.c
@@ -0,0 +1,338 @@
+/*
+ * Virtio 9p backend
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   aligu...@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 glib.h
+#include glib/gprintf.h
+#include sys/types.h
+#include dirent.h
+#include sys/time.h
+#include utime.h
+#include sys/uio.h
+#include string.h
+#include stdint.h
+
+#include compiler.h
+#include virtio-9p-marshal.h
+#include bswap.h
+
+void v9fs_string_init(V9fsString *str)
+{
+str-data = NULL;
+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);
+}
+
+void GCC_FMT_ATTR(2, 3)
+v9fs_string_sprintf(V9fsString *str, const char *fmt, ...)
+{
+va_list ap;
+
+v9fs_string_free(str);
+
+va_start(ap, fmt);
+str-size = g_vasprintf(str-data, fmt, ap);
+va_end(ap);
+}
+
+void v9fs_string_copy(V9fsString *lhs, V9fsString *rhs)
+{
+v9fs_string_free(lhs);
+v9fs_string_sprintf(lhs, %s, rhs-data);
+}
+
+
+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,
+int convert, 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

[Qemu-devel] [PATCH 00/12] Proxy FS driver for VirtFS

2011-11-15 Thread M. Mohan Kumar
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)

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: 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
  hw/9pfs: Add support to use named socket for proxy FS

 Makefile   |   15 +-
 Makefile.objs  |4 +-
 configure  |   19 +
 fsdev/file-op-9p.h |3 +-
 fsdev/qemu-fsdev.c |1 +
 fsdev/qemu-fsdev.h |1 +
 fsdev/virtfs-proxy-helper.c|  947 +
 fsdev/virtfs-proxy-helper.texi |   63 +++
 fsdev/virtio-9p-marshal.c  |  338 
 fsdev/virtio-9p-marshal.h  |   87 +++
 hw/9pfs/virtio-9p-proxy.c  | 1123 
 hw/9pfs/virtio-9p-proxy.h  |   80 +++
 hw/9pfs/virtio-9p.c|  297 +---
 hw/9pfs/virtio-9p.h|   85 +---
 qemu-config.c  |   13 +
 qemu-options.hx|   32 +-
 vl.c   |   10 +-
 17 files changed, 2736 insertions(+), 382 deletions(-)
 create mode 100644 fsdev/virtfs-proxy-helper.c
 create mode 100644 fsdev/virtfs-proxy-helper.texi
 create mode 100644 fsdev/virtio-9p-marshal.c
 create mode 100644 fsdev/virtio-9p-marshal.h
 create mode 100644 hw/9pfs/virtio-9p-proxy.c
 create mode 100644 hw/9pfs/virtio-9p-proxy.h

-- 
1.7.6




[Qemu-devel] [PATCH V2 08/12] hw/9pfs: xattr interfaces in proxy filesystem driver

2011-11-15 Thread M. Mohan Kumar
Add xattr support for proxy FS

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |   78 -
 hw/9pfs/virtio-9p-proxy.c   |  119 +++
 hw/9pfs/virtio-9p-proxy.h   |4 ++
 3 files changed, 190 insertions(+), 11 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index ded0ead..ccd7ed8 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -29,6 +29,7 @@
 #include sys/socket.h
 #include sys/vfs.h
 #include sys/stat.h
+#include attr/xattr.h
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
@@ -283,6 +284,50 @@ static int send_response(int sock, struct iovec *iovec, 
int size)
 return 0;
 }
 
+static int do_getxattr(int type, struct iovec *iovec, struct iovec *out_iovec)
+{
+int size = 0, offset, retval;
+V9fsString path, name, xattr;
+
+v9fs_string_init(xattr);
+
+offset = HDR_SZ;
+offset += proxy_unmarshal(iovec, 1, HDR_SZ, ds, size, path);
+if (size) {
+xattr.data = g_malloc(size);
+xattr.size = size;
+}
+switch (type) {
+case T_LGETXATTR:
+proxy_unmarshal(iovec, 1, offset, s, name);
+retval = lgetxattr(path.data, name.data, xattr.data, size);
+if (retval  0) {
+retval = -errno;
+v9fs_string_free(name);
+goto error;
+}
+   v9fs_string_free(name);
+break;
+case T_LLISTXATTR:
+retval = llistxattr(path.data, xattr.data, size);
+if (retval  0) {
+retval = -errno;
+goto error;
+}
+break;
+}
+
+if (!size) {
+proxy_marshal(out_iovec, 1, HDR_SZ, d, retval);
+retval = sizeof(retval);
+} else {
+retval = proxy_marshal(out_iovec, 1, HDR_SZ, s, xattr);
+}
+error:
+v9fs_string_free(path);
+return retval;
+}
+
 static void stat_to_prstat(ProxyStat *pr_stat, struct stat *stat)
 {
 memset(pr_stat, 0, sizeof(*pr_stat));
@@ -499,9 +544,10 @@ static int process_requests(int sock)
 int mode, uid, gid;
 struct timespec spec[2];
 int type, retval = 0;
+V9fsString name, value;
 V9fsString oldpath, path;
 struct iovec in_iovec, out_iovec;
-int size = 0;
+int size = 0, flags;
 
 in_iovec.iov_base = g_malloc(BUFF_SZ);
 in_iovec.iov_len = BUFF_SZ;
@@ -595,6 +641,32 @@ static int process_requests(int sock)
 }
 v9fs_string_free(path);
 break;
+case T_LGETXATTR:
+case T_LLISTXATTR:
+size = do_getxattr(type, in_iovec, out_iovec);
+break;
+case T_LSETXATTR:
+proxy_unmarshal(in_iovec, 1, HDR_SZ,
+   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:
+proxy_unmarshal(in_iovec, 1,
+   HDR_SZ, 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;
@@ -616,11 +688,15 @@ static int process_requests(int sock)
 case T_UTIME:
 case T_RENAME:
 case T_REMOVE:
+case T_LSETXATTR:
+case T_LREMOVEXATTR:
 send_status(sock, out_iovec, retval);
 break;
 case T_LSTAT:
 case T_STATFS:
 case T_READLINK:
+case T_LGETXATTR:
+case T_LLISTXATTR:
 if (send_response(sock, out_iovec, size)  0) {
 goto error;
 }
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index aefdc61..f672ac3 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -136,7 +136,7 @@ static void prstat_to_stat(struct stat *stbuf, ProxyStat 
*prstat)
  * size of errno/response is given by header.size
  */
 static int v9fs_receive_response(V9fsProxy *proxy, int type,
-int *sock_error, void *response)
+int *sock_error, int size, void *response)
 {
 int retval, error;
 ProxyHeader header;
@@ -196,6 +196,19 @@ static int v9fs_receive_response(V9fsProxy *proxy, int 
type,
 v9fs_string_free(target);
 break;
 }
+case T_LGETXATTR:
+case T_LLISTXATTR: {
+V9fsString xattr;
+if (!size) {
+proxy_unmarshal(reply, 1, HDR_SZ, d, size);
+return size;
+} else {
+proxy_unmarshal(reply, 1, HDR_SZ, s

[Qemu-devel] [PATCH V2 09/12] hw/9pfs: Proxy getversion

2011-11-15 Thread M. Mohan Kumar
Add proxy getversion to get generation number

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |   74 +++
 hw/9pfs/virtio-9p-proxy.c   |   31 ++
 hw/9pfs/virtio-9p-proxy.h   |1 +
 3 files changed, 106 insertions(+), 0 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index ccd7ed8..917bb26 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -30,6 +30,11 @@
 #include sys/vfs.h
 #include sys/stat.h
 #include attr/xattr.h
+#include sys/ioctl.h
+#include linux/fs.h
+#ifdef CONFIG_LINUX_MAGIC_H
+#include linux/magic.h
+#endif
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
@@ -38,6 +43,19 @@
 
 #define PROGNAME virtfs-proxy-helper
 
+#ifndef XFS_SUPER_MAGIC
+#define XFS_SUPER_MAGIC  0x58465342
+#endif
+#ifndef EXT2_SUPER_MAGIC
+#define EXT2_SUPER_MAGIC 0xEF53
+#endif
+#ifndef REISERFS_SUPER_MAGIC
+#define REISERFS_SUPER_MAGIC 0x52654973
+#endif
+#ifndef BTRFS_SUPER_MAGIC
+#define BTRFS_SUPER_MAGIC 0x9123683E
+#endif
+
 static struct option helper_opts[] = {
 {fd, required_argument, NULL, 'f'},
 {path, required_argument, NULL, 'p'},
@@ -45,6 +63,7 @@ static struct option helper_opts[] = {
 };
 
 int is_daemon;
+int get_version; /* IOC getversion IOCTL supported */
 
 static void do_perror(const char *string)
 {
@@ -284,6 +303,42 @@ static int send_response(int sock, struct iovec *iovec, 
int size)
 return 0;
 }
 
+/*
+ * gets generation number
+ * returns -errno on failure and sizeof(generation number) on success
+ */
+static int do_getversion(struct iovec *iovec, struct iovec *out_iovec)
+{
+int fd, retval;
+uint64_t version;
+V9fsString path;
+
+retval = sizeof(version);
+/* no need to issue ioctl */
+if (!get_version) {
+version = 0;
+proxy_marshal(out_iovec, 1, HDR_SZ, q, version);
+return retval;
+}
+
+proxy_unmarshal(iovec, 1, HDR_SZ, s, path);
+
+fd = open(path.data, O_RDONLY);
+if (fd  0) {
+retval = -errno;
+goto done;
+}
+if (ioctl(fd, FS_IOC_GETVERSION, version)  0) {
+retval = -errno;
+} else {
+proxy_marshal(out_iovec, 1, HDR_SZ, q, version);
+}
+close(fd);
+done:
+v9fs_string_free(path);
+return retval;
+}
+
 static int do_getxattr(int type, struct iovec *iovec, struct iovec *out_iovec)
 {
 int size = 0, offset, retval;
@@ -667,6 +722,9 @@ static int process_requests(int sock)
 v9fs_string_free(path);
 v9fs_string_free(name);
 break;
+case T_GETVERSION:
+size = do_getversion(in_iovec, out_iovec);
+break;
 default:
 goto error;
 break;
@@ -697,6 +755,7 @@ static int process_requests(int sock)
 case T_READLINK:
 case T_LGETXATTR:
 case T_LLISTXATTR:
+case T_GETVERSION:
 if (send_response(sock, out_iovec, size)  0) {
 goto error;
 }
@@ -718,6 +777,8 @@ int main(int argc, char **argv)
 char rpath[PATH_MAX];
 struct stat stbuf;
 int c, option_index;
+int retval;
+struct statfs st_fs;
 
 is_daemon = 1;
 rpath[0] = '\0';
@@ -775,6 +836,19 @@ int main(int argc, char **argv)
 
 do_log(LOG_INFO, Started);
 
+/* check whether underlying FS support IOC_GETVERSION */
+retval = statfs(rpath, st_fs);
+if (!retval) {
+switch (st_fs.f_type) {
+case EXT2_SUPER_MAGIC:
+case BTRFS_SUPER_MAGIC:
+case REISERFS_SUPER_MAGIC:
+case XFS_SUPER_MAGIC:
+get_version = 1;
+break;
+}
+}
+
 if (chroot(rpath)  0) {
 do_perror(chroot);
 goto error;
diff --git a/hw/9pfs/virtio-9p-proxy.c b/hw/9pfs/virtio-9p-proxy.c
index f672ac3..bc63835 100644
--- a/hw/9pfs/virtio-9p-proxy.c
+++ b/hw/9pfs/virtio-9p-proxy.c
@@ -209,6 +209,9 @@ static int v9fs_receive_response(V9fsProxy *proxy, int type,
 }
 break;
 }
+case T_GETVERSION:
+proxy_unmarshal(reply, 1, HDR_SZ, q, response);
+break;
 default:
 *sock_error = 1;
 return -1;
@@ -450,6 +453,13 @@ static int v9fs_request(V9fsProxy *proxy, int type,
 proxy_marshal(iovec, 1, 0, dd, header.type, header.size);
 header.size += HDR_SZ;
 break;
+case T_GETVERSION:
+path = va_arg(ap, V9fsString *);
+header.size = proxy_marshal(iovec, 1, HDR_SZ, s, path);
+header.type = T_GETVERSION;
+proxy_marshal(iovec, 1, 0, dd, header.type, header.size);
+header.size += HDR_SZ;
+break;
 default:
 error_report(Invalid type %d\n, type);
 va_end(ap);
@@ -497,6 +507,7 @@ static int v9fs_request(V9fsProxy *proxy, int type,
 case T_STATFS:
 case T_LGETXATTR:
 case T_LLISTXATTR:
+case T_GETVERSION:
 retval

[Qemu-devel] [PATCH V2 04/12] hw/9pfs: Open and create files

2011-11-15 Thread M. Mohan Kumar
Add interfaces to open and create files for proxy file system driver.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/virtfs-proxy-helper.c |  136 +++-
 hw/9pfs/virtio-9p-proxy.c   |  180 +--
 hw/9pfs/virtio-9p-proxy.h   |9 ++
 3 files changed, 314 insertions(+), 11 deletions(-)

diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
index 69daf7c..68d27f1 100644
--- a/fsdev/virtfs-proxy-helper.c
+++ b/fsdev/virtfs-proxy-helper.c
@@ -30,6 +30,8 @@
 #include qemu-common.h
 #include virtio-9p-marshal.h
 #include hw/9pfs/virtio-9p-proxy.h
+#include fsdev/virtio-9p-marshal.h
+
 
 #define PROGNAME virtfs-proxy-helper
 
@@ -148,20 +150,125 @@ static int read_request(int sockfd, struct iovec *iovec)
 ProxyHeader header;
 
 /* read the header */
-retval = socket_read(sockfd, iovec-iov_base, sizeof(header));
-if (retval != sizeof(header)) {
+retval = socket_read(sockfd, iovec-iov_base, HDR_SZ);
+if (retval != HDR_SZ) {
 return -EIO;
 }
 /* unmarshal header */
 proxy_unmarshal(iovec, 1, 0, dd, header.type, header.size);
 /* read the request */
-retval = socket_read(sockfd, iovec-iov_base + sizeof(header), 
header.size);
+retval = socket_read(sockfd, iovec-iov_base + HDR_SZ, header.size);
 if (retval != header.size) {
 return -EIO;
 }
 return header.type;
 }
 
+static void send_fd(int sockfd, int fd)
+{
+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  0) {
+/*
+ * 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 = 0) {
+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;
+proxy_unmarshal(iovec, 1, HDR_SZ, s,
+   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;
+proxy_unmarshal(iovec, 1, HDR_SZ, 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
@@ -173,15 +280,34 @@ static void usage(char *prog)
 
 static int process_requests(int sock)
 {
-int type;
+int type, retval = 0;
 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) {
+switch (type) {
+case T_OPEN:
+retval = do_open(iovec);
+break;
+case T_CREATE:
+retval = do_create(iovec);
+break;
+default:
+goto error;
+break;
+}
+
+/* Send response */
+switch (type) {
+case T_OPEN

[Qemu-devel] [PATCH V2 03/12] hw/9pfs: File system helper process for qemu 9p proxy FS

2011-11-15 Thread M. Mohan Kumar
Provide root privilege access to QEMU 9p proxy filesystem using socket
communication.

Proxy helper is started by root user as:
~ # virtfs-proxy-helper -f|--fd socket descriptor -p|--path path-to-share

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 Makefile|3 +
 configure   |   19 +++
 fsdev/virtfs-proxy-helper.c |  271 +++
 hw/9pfs/virtio-9p-proxy.h   |   10 ++
 4 files changed, 303 insertions(+), 0 deletions(-)
 create mode 100644 fsdev/virtfs-proxy-helper.c

diff --git a/Makefile b/Makefile
index ba8d738..19b481a 100644
--- a/Makefile
+++ b/Makefile
@@ -153,6 +153,9 @@ qemu-img$(EXESUF): qemu-img.o $(tools-obj-y) $(block-obj-y)
 qemu-nbd$(EXESUF): qemu-nbd.o $(tools-obj-y) $(block-obj-y)
 qemu-io$(EXESUF): qemu-io.o cmd.o $(tools-obj-y) $(block-obj-y)
 
+fsdev/virtfs-proxy-helper$(EXESUF): fsdev/virtfs-proxy-helper.o 
fsdev/virtio-9p-marshal.o
+fsdev/virtfs-proxy-helper$(EXESUF): LIBS += -lcap
+
 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 a6cf6d6..a2b55e8 100755
--- a/configure
+++ b/configure
@@ -1873,6 +1873,22 @@ 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
+  else
+cap=no
+  fi
+fi
+
+##
 # pthread probe
 PTHREADLIBS_LIST=-pthread -lpthread -lpthreadGC2
 
@@ -2662,6 +2678,9 @@ confdir=$sysconfdir$confsuffix
 tools=
 if test $softmmu = yes ; then
   tools=qemu-img\$(EXESUF) qemu-io\$(EXESUF) $tools
+  if [ $cap = yes -a $linux = yes ] ; then
+  tools=$tools fsdev/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
diff --git a/fsdev/virtfs-proxy-helper.c b/fsdev/virtfs-proxy-helper.c
new file mode 100644
index 000..69daf7c
--- /dev/null
+++ b/fsdev/virtfs-proxy-helper.c
@@ -0,0 +1,271 @@
+/*
+ * Helper for QEMU Proxy FS Driver
+ * Copyright IBM, Corp. 2011
+ *
+ * Authors:
+ * M. Mohan Kumar mo...@in.ibm.com
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ */
+#include 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 virtio-9p-marshal.h
+#include hw/9pfs/virtio-9p-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

[Qemu-devel] [PATCH 01/13] hw/9pfs: Move opt validation to FsDriver callback

2011-10-31 Thread M. Mohan Kumar
From: Aneesh Kumar K.V aneesh.ku...@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.ku...@linux.vnet.ibm.com
Signed-off-by: M. Mohan Kumar mo...@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   0x001C
 
 
+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

[Qemu-devel] [PATCH 04/13] hw/9pfs: File system helper process for qemu 9p proxy FS

2011-10-31 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@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 000..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

[Qemu-devel] [PATCH 05/13] hw/9pfs: Add support to use named socket for proxy FS

2011-10-31 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@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

[Qemu-devel] [PATCH 07/13] hw/9pfs: Create other filesystem objects

2011-10-31 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@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

[Qemu-devel] [PATCH 09/13] hw/9pfs: File ownership and others

2011-10-31 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@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, s, 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

[Qemu-devel] [PATCH 13/13] hw/9pfs: man page for proxy helper

2011-10-31 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com


Signed-off-by: M. Mohan Kumar mo...@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 000..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




[Qemu-devel] [PATCH 12/13] hw/9pfs: Documentation changes related to proxy fs

2011-10-31 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com


Signed-off-by: M. Mohan Kumar mo...@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




[Qemu-devel] [PATCH 08/13] hw/9pfs: Add stat/readlink/statfs for proxy FS

2011-10-31 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com


Signed-off-by: M. Mohan Kumar mo...@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

[Qemu-devel] [PATCH 03/13] hw/9pfs: Add new proxy filesystem driver

2011-10-31 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@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 000..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 000..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 mo...@in.ibm.com
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+#include sys/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

[Qemu-devel] [PATCH 02/13] hw/9pfs: Move pdu_marshal/unmarshal code to a seperate file

2011-10-31 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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 mo...@in.ibm.com
Signed-off-by: Aneesh Kumar K.V aneesh.ku...@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 000..1a21254
--- /dev/null
+++ b/hw/9pfs/virtio-9p-marshal.c
@@ -0,0 +1,257 @@
+/*
+ * Virtio 9p backend
+ *
+ * Copyright IBM, Corp. 2010
+ *
+ * Authors:
+ *  Anthony Liguori   aligu...@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

[Qemu-devel] [PATCH 00/13] Proxy FS driver for VirtFS

2011-10-31 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@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




[Qemu-devel] [PATCH 10/13] hw/9pfs: xattr interfaces in proxy filesystem driver

2011-10-31 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Add xattr support for proxy FS

Signed-off-by: M. Mohan Kumar mo...@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

[Qemu-devel] [PATCH 06/13] hw/9pfs: Open and create files

2011-10-31 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Add interfaces to open and create files for proxy file system driver.

Signed-off-by: M. Mohan Kumar mo...@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, s, 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

[Qemu-devel] [V3 PATCH 2/2] hw/9pfs: Read-only support for 9p export

2011-10-25 Thread M. Mohan Kumar
A new fsdev parameter readonly is introduced to control accessing 9p export.
readonly can be used to specify the access type. By default rw access
is given to 9p export.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/file-op-9p.h  |4 +++-
 fsdev/qemu-fsdev.c  |7 ++-
 hw/9pfs/virtio-9p.c |   50 ++
 qemu-config.c   |7 +++
 qemu-options.hx |   14 ++
 vl.c|2 ++
 6 files changed, 78 insertions(+), 6 deletions(-)

diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index 908e2a5..5788ff9 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -56,10 +56,12 @@ typedef struct extended_ops {
  * On failure ignore the error.
  */
 #define V9FS_SM_NONE0x0010
-
+#define V9FS_RDONLY 0x0020
 
 #define V9FS_SEC_MASK   0x001C
 
+
+
 typedef struct FsContext
 {
 uid_t uid;
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index 5977bcc..27d10cb 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -35,7 +35,7 @@ int qemu_fsdev_add(QemuOpts *opts)
 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);
 
 if (!fsdev_id) {
 fprintf(stderr, fsdev: No id specified\n);
@@ -86,6 +86,11 @@ int qemu_fsdev_add(QemuOpts *opts)
 fsle-fse.export_flags |= V9FS_IMMEDIATE_WRITEOUT;
 }
 }
+if (ro) {
+fsle-fse.export_flags |= V9FS_RDONLY;
+} else {
+fsle-fse.export_flags = ~V9FS_RDONLY;
+}
 
 if (strcmp(fsdriver, local)) {
 goto done;
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 8b6813f..e7618d7 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -1271,6 +1271,11 @@ static void v9fs_fix_path(V9fsPath *dst, V9fsPath *src, 
int len)
 dst-size++;
 }
 
+static inline bool is_ro_export(FsContext *ctx)
+{
+return ctx-export_flags  V9FS_RDONLY;
+}
+
 static void v9fs_version(void *opaque)
 {
 V9fsPDU *pdu = opaque;
@@ -1690,6 +1695,14 @@ static void v9fs_open(void *opaque)
 } else {
 flags = omode_to_uflags(mode);
 }
+if (is_ro_export(s-ctx)) {
+if (mode  O_WRONLY || mode  O_RDWR ||
+mode  O_APPEND || mode  O_TRUNC) {
+err = -EROFS;
+goto out;
+}
+flags |= O_NOATIME;
+}
 err = v9fs_co_open(pdu, fidp, flags);
 if (err  0) {
 goto out;
@@ -3309,6 +3322,39 @@ static void v9fs_op_not_supp(void *opaque)
 complete_pdu(pdu-s, pdu, -EOPNOTSUPP);
 }
 
+static void v9fs_fs_ro(void *opaque)
+{
+V9fsPDU *pdu = opaque;
+complete_pdu(pdu-s, pdu, -EROFS);
+}
+
+static inline bool is_read_only_op(V9fsPDU *pdu)
+{
+switch (pdu-id) {
+case P9_TREADDIR:
+case P9_TSTATFS:
+case P9_TGETATTR:
+case P9_TXATTRWALK:
+case P9_TLOCK:
+case P9_TGETLOCK:
+case P9_TREADLINK:
+case P9_TVERSION:
+case P9_TLOPEN:
+case P9_TATTACH:
+case P9_TSTAT:
+case P9_TWALK:
+case P9_TCLUNK:
+case P9_TFSYNC:
+case P9_TOPEN:
+case P9_TREAD:
+case P9_TAUTH:
+case P9_TFLUSH:
+return 1;
+default:
+return 0;
+}
+}
+
 static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
 {
 Coroutine *co;
@@ -3320,6 +3366,10 @@ static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
 } else {
 handler = pdu_co_handlers[pdu-id];
 }
+
+if (is_ro_export(s-ctx)  !is_read_only_op(pdu)) {
+handler = v9fs_fs_ro;
+}
 co = qemu_coroutine_create(handler);
 qemu_coroutine_enter(co, pdu);
 }
diff --git a/qemu-config.c b/qemu-config.c
index 90b6b3e..597d7e1 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -180,7 +180,11 @@ QemuOptsList qemu_fsdev_opts = {
 }, {
 .name = writeout,
 .type = QEMU_OPT_STRING,
+}, {
+.name = readonly,
+.type = QEMU_OPT_BOOL,
 },
+
 { /*End of list */ }
 },
 };
@@ -205,6 +209,9 @@ QemuOptsList qemu_virtfs_opts = {
 }, {
 .name = writeout,
 .type = QEMU_OPT_STRING,
+}, {
+.name = readonly,
+.type = QEMU_OPT_BOOL,
 },
 
 { /*End of list */ }
diff --git a/qemu-options.hx b/qemu-options.hx
index 5d2a776..1baa381 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -528,12 +528,12 @@ 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]\n,
+   [,writeout=immediate][,readonly]\n,
 QEMU_ARCH_ALL)
 
 STEXI
 
-@item -fsdev 
@var{fsdriver},id=@var{id},path=@var{path},[security_model=@var{security_model}][,writeout=@var{writeout

[Qemu-devel] [V3 PATCH 1/2] qemu: Add opt_set_bool functionality

2011-10-25 Thread M. Mohan Kumar
Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
Changes from previous version V2:
* qemu_opt_set_bool does not need to call qemu_opt_parse, because it
supports only setting boolean types

Changes from previous version:
* Changed qemu_opt_{get|set}_bool to use 'bool' data type

 qemu-option.c |   39 +++
 qemu-option.h |3 ++-
 2 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/qemu-option.c b/qemu-option.c
index 105d760..f97a758 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -168,7 +168,7 @@ QEMUOptionParameter 
*get_option_parameter(QEMUOptionParameter *list,
 return NULL;
 }
 
-static int parse_option_bool(const char *name, const char *value, int *ret)
+static int parse_option_bool(const char *name, const char *value, bool *ret)
 {
 if (value != NULL) {
 if (!strcmp(value, on)) {
@@ -258,7 +258,7 @@ static int parse_option_size(const char *name, const char 
*value, uint64_t *ret)
 int set_option_parameter(QEMUOptionParameter *list, const char *name,
 const char *value)
 {
-int flag;
+bool flag;
 
 // Find a matching parameter
 list = get_option_parameter(list, name);
@@ -508,7 +508,7 @@ struct QemuOpt {
 
 const QemuOptDesc *desc;
 union {
-int  boolean;
+bool boolean;
 uint64_t uint;
 } value;
 
@@ -542,7 +542,7 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name)
 return opt ? opt-str : NULL;
 }
 
-int qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval)
+bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
 {
 QemuOpt *opt = qemu_opt_find(opts, name);
 
@@ -636,6 +636,37 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const 
char *value)
 return 0;
 }
 
+int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
+{
+QemuOpt *opt;
+const QemuOptDesc *desc = opts-list-desc;
+int i;
+
+for (i = 0; desc[i].name != NULL; i++) {
+if (strcmp(desc[i].name, name) == 0) {
+break;
+}
+}
+if (desc[i].name == NULL) {
+if (i == 0) {
+/* empty list - allow any */;
+} else {
+qerror_report(QERR_INVALID_PARAMETER, name);
+return -1;
+}
+}
+
+opt = g_malloc0(sizeof(*opt));
+opt-name = g_strdup(name);
+opt-opts = opts;
+QTAILQ_INSERT_TAIL(opts-head, opt, next);
+if (desc[i].name != NULL) {
+opt-desc = desc+i;
+}
+opt-value.boolean = !!val;
+return 0;
+}
+
 int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
  int abort_on_failure)
 {
diff --git a/qemu-option.h b/qemu-option.h
index b515813..07958e4 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -105,10 +105,11 @@ struct QemuOptsList {
 };
 
 const char *qemu_opt_get(QemuOpts *opts, const char *name);
-int qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval);
+bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
 uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t 
defval);
 uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
 int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
+int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val);
 typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void 
*opaque);
 int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
  int abort_on_failure);
-- 
1.7.6




[Qemu-devel] [PATCH 1/2] qemu: Add opt_set_bool functionality

2011-10-19 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
Changes from previous version:
* Changed qemu_opt_{get|set}_bool to use 'bool' data type

 qemu-option.c |   43 +++
 qemu-option.h |3 ++-
 2 files changed, 41 insertions(+), 5 deletions(-)

diff --git a/qemu-option.c b/qemu-option.c
index 105d760..1fd2755 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -168,7 +168,7 @@ QEMUOptionParameter 
*get_option_parameter(QEMUOptionParameter *list,
 return NULL;
 }
 
-static int parse_option_bool(const char *name, const char *value, int *ret)
+static int parse_option_bool(const char *name, const char *value, bool *ret)
 {
 if (value != NULL) {
 if (!strcmp(value, on)) {
@@ -258,7 +258,7 @@ static int parse_option_size(const char *name, const char 
*value, uint64_t *ret)
 int set_option_parameter(QEMUOptionParameter *list, const char *name,
 const char *value)
 {
-int flag;
+bool flag;
 
 // Find a matching parameter
 list = get_option_parameter(list, name);
@@ -508,7 +508,7 @@ struct QemuOpt {
 
 const QemuOptDesc *desc;
 union {
-int  boolean;
+bool boolean;
 uint64_t uint;
 } value;
 
@@ -542,7 +542,7 @@ const char *qemu_opt_get(QemuOpts *opts, const char *name)
 return opt ? opt-str : NULL;
 }
 
-int qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval)
+bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval)
 {
 QemuOpt *opt = qemu_opt_find(opts, name);
 
@@ -636,6 +636,41 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const 
char *value)
 return 0;
 }
 
+int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
+{
+QemuOpt *opt;
+const QemuOptDesc *desc = opts-list-desc;
+int i;
+
+for (i = 0; desc[i].name != NULL; i++) {
+if (strcmp(desc[i].name, name) == 0) {
+break;
+}
+}
+if (desc[i].name == NULL) {
+if (i == 0) {
+/* empty list - allow any */;
+} else {
+qerror_report(QERR_INVALID_PARAMETER, name);
+return -1;
+}
+}
+
+opt = g_malloc0(sizeof(*opt));
+opt-name = g_strdup(name);
+opt-opts = opts;
+QTAILQ_INSERT_TAIL(opts-head, opt, next);
+if (desc[i].name != NULL) {
+opt-desc = desc+i;
+}
+opt-value.boolean = !!val;
+if (qemu_opt_parse(opt)  0) {
+qemu_opt_del(opt);
+return -1;
+}
+return 0;
+}
+
 int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
  int abort_on_failure)
 {
diff --git a/qemu-option.h b/qemu-option.h
index b515813..07958e4 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -105,10 +105,11 @@ struct QemuOptsList {
 };
 
 const char *qemu_opt_get(QemuOpts *opts, const char *name);
-int qemu_opt_get_bool(QemuOpts *opts, const char *name, int defval);
+bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
 uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t 
defval);
 uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
 int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
+int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val);
 typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void 
*opaque);
 int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
  int abort_on_failure);
-- 
1.7.6




[Qemu-devel] [PATCH 2/2] hw/9pfs: Read-only support for 9p export

2011-10-19 Thread M. Mohan Kumar
From: M. Mohan Kumar mo...@in.ibm.com

A new fsdev parameter readonly is introduced to control accessing 9p export.
readonly=on|off can be used to specify the access type. By default rw access
is given to 9p export.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com

---
Changes from previous version V4:
* Updated on top of current for-upstream branch

Changes from previous version V3:
* Use opt_set_bool function to set readonly option
* Change the flag from MS_READONLY to 9p specific

Change from previous version V2:
* QEMU_OPT_BOOL is used for readdonly parameter

Changes from previous version:
* Use readonly option instead of access
* Change function return type to boolean where its needed

 fsdev/file-op-9p.h  |2 ++
 fsdev/qemu-fsdev.c  |7 ++-
 hw/9pfs/virtio-9p.c |   51 +++
 qemu-config.c   |7 +++
 vl.c|2 ++
 5 files changed, 68 insertions(+), 1 deletions(-)

diff --git a/fsdev/file-op-9p.h b/fsdev/file-op-9p.h
index c7b4e38..ba564d4 100644
--- a/fsdev/file-op-9p.h
+++ b/fsdev/file-op-9p.h
@@ -60,6 +60,8 @@ typedef struct extended_ops {
 
 #define V9FS_SEC_MASK   0x001C
 
+#define V9FS_RDONLY 0x0020
+
 typedef struct FsContext
 {
 uid_t uid;
diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index e8dc0fd..7fd2aa7 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -36,7 +36,7 @@ int qemu_fsdev_add(QemuOpts *opts)
 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);
 
 if (!fsdev_id) {
 fprintf(stderr, fsdev: No id specified\n);
@@ -87,6 +87,11 @@ int qemu_fsdev_add(QemuOpts *opts)
 fsle-fse.export_flags |= V9FS_IMMEDIATE_WRITEOUT;
 }
 }
+if (ro) {
+fsle-fse.export_flags |= V9FS_RDONLY;
+} else {
+fsle-fse.export_flags = ~V9FS_RDONLY;
+}
 
 if (strcmp(fsdriver, local)) {
 goto done;
diff --git a/hw/9pfs/virtio-9p.c b/hw/9pfs/virtio-9p.c
index 1c67bfe..b6770e2 100644
--- a/hw/9pfs/virtio-9p.c
+++ b/hw/9pfs/virtio-9p.c
@@ -1271,6 +1271,11 @@ static void v9fs_fix_path(V9fsPath *dst, V9fsPath *src, 
int len)
 dst-size++;
 }
 
+static inline bool is_ro_export(int export_flags)
+{
+return export_flags  V9FS_RDONLY;
+}
+
 static void v9fs_version(void *opaque)
 {
 V9fsPDU *pdu = opaque;
@@ -1692,6 +1697,15 @@ static void v9fs_open(void *opaque)
 } else {
 flags = omode_to_uflags(mode);
 }
+if (is_ro_export(s-ctx.export_flags)) {
+if (mode  O_WRONLY || mode  O_RDWR ||
+mode  O_APPEND || mode  O_TRUNC) {
+err = -EROFS;
+goto out;
+} else {
+flags |= O_NOATIME;
+}
+}
 err = v9fs_co_open(pdu, fidp, flags);
 if (err  0) {
 goto out;
@@ -3311,6 +3325,39 @@ static void v9fs_op_not_supp(void *opaque)
 complete_pdu(pdu-s, pdu, -EOPNOTSUPP);
 }
 
+static void v9fs_fs_ro(void *opaque)
+{
+V9fsPDU *pdu = opaque;
+complete_pdu(pdu-s, pdu, -EROFS);
+}
+
+static inline bool is_read_only_op(int id)
+{
+switch (id) {
+case P9_TREADDIR:
+case P9_TSTATFS:
+case P9_TGETATTR:
+case P9_TXATTRWALK:
+case P9_TLOCK:
+case P9_TGETLOCK:
+case P9_TREADLINK:
+case P9_TVERSION:
+case P9_TLOPEN:
+case P9_TATTACH:
+case P9_TSTAT:
+case P9_TWALK:
+case P9_TCLUNK:
+case P9_TFSYNC:
+case P9_TOPEN:
+case P9_TREAD:
+case P9_TAUTH:
+case P9_TFLUSH:
+return 1;
+default:
+return 0;
+}
+}
+
 static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
 {
 Coroutine *co;
@@ -3322,6 +3369,10 @@ static void submit_pdu(V9fsState *s, V9fsPDU *pdu)
 } else {
 handler = pdu_co_handlers[pdu-id];
 }
+
+if (is_ro_export(s-ctx.export_flags)  !is_read_only_op(pdu-id)) {
+handler = v9fs_fs_ro;
+}
 co = qemu_coroutine_create(handler);
 qemu_coroutine_enter(co, pdu);
 }
diff --git a/qemu-config.c b/qemu-config.c
index 90b6b3e..597d7e1 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -180,7 +180,11 @@ QemuOptsList qemu_fsdev_opts = {
 }, {
 .name = writeout,
 .type = QEMU_OPT_STRING,
+}, {
+.name = readonly,
+.type = QEMU_OPT_BOOL,
 },
+
 { /*End of list */ }
 },
 };
@@ -205,6 +209,9 @@ QemuOptsList qemu_virtfs_opts = {
 }, {
 .name = writeout,
 .type = QEMU_OPT_STRING,
+}, {
+.name = readonly,
+.type = QEMU_OPT_BOOL,
 },
 
 { /*End of list */ }
diff --git a/vl.c b/vl.c
index c9de124..cf66ef9 100644
--- a/vl.c
+++ b/vl.c
@@ -2823,6 +2823,8 @@ int main(int argc, char **argv, char **envp

[Qemu-devel] [PATCH] hw/9pfs: Handle Security model parsing

2011-10-14 Thread M. Mohan Kumar
Except local fs driver other fs drivers (handle) don't need
security model. Update fsdev parameter parsing accordingly.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---
 fsdev/qemu-fsdev.c |   26 +-
 qemu-options.hx|   12 
 vl.c   |6 ++
 3 files changed, 27 insertions(+), 17 deletions(-)

diff --git a/fsdev/qemu-fsdev.c b/fsdev/qemu-fsdev.c
index ce920d6..5977bcc 100644
--- a/fsdev/qemu-fsdev.c
+++ b/fsdev/qemu-fsdev.c
@@ -58,8 +58,15 @@ int qemu_fsdev_add(QemuOpts *opts)
 return -1;
 }
 
-if (!sec_model) {
-fprintf(stderr, fsdev: No security_model specified.\n);
+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;
 }
 
@@ -80,6 +87,10 @@ int qemu_fsdev_add(QemuOpts *opts)
 }
 }
 
+if (strcmp(fsdriver, local)) {
+goto done;
+}
+
 if (!strcmp(sec_model, passthrough)) {
 fsle-fse.export_flags |= V9FS_SM_PASSTHROUGH;
 } else if (!strcmp(sec_model, mapped)) {
@@ -87,14 +98,11 @@ int qemu_fsdev_add(QemuOpts *opts)
 } else if (!strcmp(sec_model, none)) {
 fsle-fse.export_flags |= V9FS_SM_NONE;
 } else {
-fprintf(stderr, Default to security_model=none. You may want
- enable advanced security model using 
-security option:\n\t security_model=passthrough\n\t 
-security_model=mapped\n);
-
-fsle-fse.export_flags |= V9FS_SM_NONE;
+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/qemu-options.hx b/qemu-options.hx
index 518a1f1..f05be30 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -527,13 +527,13 @@ DEFHEADING()
 DEFHEADING(File system options:)
 
 DEF(fsdev, HAS_ARG, QEMU_OPTION_fsdev,
--fsdev 
fsdriver,id=id,path=path,security_model=[mapped|passthrough|none]\n
+-fsdev 
fsdriver,id=id,path=path,[security_model={mapped|passthrough|none}]\n
[,writeout=immediate]\n,
 QEMU_ARCH_ALL)
 
 STEXI
 
-@item -fsdev 
@var{fsdriver},id=@var{id},path=@var{path},security_model=@var{security_model}[,writeout=@var{writeout}]
+@item -fsdev 
@var{fsdriver},id=@var{id},path=@var{path},[security_model=@var{security_model}][,writeout=@var{writeout}]
 @findex -fsdev
 Define a new file system device. Valid options are:
 @table @option
@@ -555,7 +555,9 @@ attributes like uid, gid, mode bits and link target are 
stored as
 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.
+set file attributes like ownership. Security model is mandatory
+only for local fsdriver. Other fsdrivers (like handle) don't take
+security model as a parameter.
 @item writeout=@var{writeout}
 This is an optional argument. The only supported value is immediate.
 This means that host page cache will be used to read and write data but
@@ -609,7 +611,9 @@ attributes like uid, gid, mode bits and link target are 
stored as
 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.
+set file attributes like ownership. Security model is mandatory only
+for local fsdriver. Other fsdrivers (like handle) don't take security
+model as a parameter.
 @item writeout=@var{writeout}
 This is an optional argument. The only supported value is immediate.
 This means that host page cache will be used to read and write data but
diff --git a/vl.c b/vl.c
index 3b8199f..d672268 100644
--- a/vl.c
+++ b/vl.c
@@ -2800,14 +2800,12 @@ 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 ||
-qemu_opt_get(opts, security_model) == NULL) {
+qemu_opt_get(opts, path) == NULL) {
 fprintf(stderr, Usage: -virtfs 
fsdriver,path=/share_path/,
-security_model=[mapped|passthrough|none],
+[security_model={mapped|passthrough|none}],
 mount_tag=tag.\n);
 exit(1);
 }
-
 fsdev

Re: [Qemu-devel] [PATCH] hw/9pfs: Handle Security model parsing

2011-10-13 Thread M. Mohan Kumar
-- 
Regards,
M. Mohan Kumar
On Wednesday, October 12, 2011 09:37:23 PM Daniel P. Berrange wrote:
 On Wed, Oct 12, 2011 at 09:05:50PM +0530, M. Mohan Kumar wrote:
   On Wed, Oct 12, 2011 at 01:24:16PM +0530, M. Mohan Kumar wrote:
Security model is needed only for 'local' fs driver.

Signed-off-by: M. Mohan Kumar mo...@in.ibm.com
---

 fsdev/qemu-fsdev.c |6 +
 fsdev/qemu-fsdev.h |1 +
 hw/9pfs/virtio-9p-device.c |   47
 ++- vl.c
 
 |   20 +++--
 
 4 files changed, 43 insertions(+), 31 deletions(-)

--- a/fsdev/qemu-fsdev.h
+++ b/fsdev/qemu-fsdev.h
@@ -40,6 +40,7 @@ typedef struct FsTypeTable {

 typedef struct FsTypeEntry {
 
 char *fsdev_id;
 char *path;

+char *fsdriver;

 char *security_model;
 int cache_flags;
 FileOperations *ops;

diff --git a/hw/9pfs/virtio-9p-device.c b/hw/9pfs/virtio-9p-device.c
index aac58ad..1846e36 100644
--- a/hw/9pfs/virtio-9p-device.c
+++ b/hw/9pfs/virtio-9p-device.c
@@ -83,29 +83,30 @@ VirtIODevice *virtio_9p_init(DeviceState *dev,
V9fsConf *conf)

 exit(1);
 
 }

-if (!strcmp(fse-security_model, passthrough)) {
-/* Files on the Fileserver set to client user credentials */
-s-ctx.fs_sm = SM_PASSTHROUGH;
-s-ctx.xops = passthrough_xattr_ops;
-} else if (!strcmp(fse-security_model, mapped)) {
-/* Files on the fileserver are set to QEMU credentials.
- * Client user credentials are saved in extended attributes.
- */
-s-ctx.fs_sm = SM_MAPPED;
-s-ctx.xops = mapped_xattr_ops;
-} else if (!strcmp(fse-security_model, none)) {
-/*
- * Files on the fileserver are set to QEMU credentials.
- */
-s-ctx.fs_sm = SM_NONE;
-s-ctx.xops = none_xattr_ops;
-} else {
-fprintf(stderr, Default to security_model=none. You may
want - enable advanced security model using 
-security option:\n\t security_model=passthrough\n\t
 -security_model=mapped\n);
-s-ctx.fs_sm = SM_NONE;
-s-ctx.xops = none_xattr_ops;
+/* security models is needed only for local fs driver */
+if (!strcmp(fse-fsdriver, local)) {
+if (!strcmp(fse-security_model, passthrough)) {
+/* Files on the Fileserver set to client user
credentials */ +s-ctx.fs_sm = SM_PASSTHROUGH;
+s-ctx.xops = passthrough_xattr_ops;
+} else if (!strcmp(fse-security_model, mapped)) {
+/* Files on the fileserver are set to QEMU credentials.
+* Client user credentials are saved in extended
attributes. +*/
+s-ctx.fs_sm = SM_MAPPED;
+s-ctx.xops = mapped_xattr_ops;
+} else if (!strcmp(fse-security_model, none)) {
+/*
+* Files on the fileserver are set to QEMU credentials.
+*/
+s-ctx.fs_sm = SM_NONE;
+s-ctx.xops = none_xattr_ops;
+} else {
+fprintf(stderr, Invalid security_model %s specified.\n
+Available security models are:\t 
+passthrough,mapped or none\n,
fse-security_model); +exit(1);
+}
   
   Are you sure there aren't use cases where people would like to
   choose between  passthrough  mapped, even when using the 'proxy'
   or 'handle' security drivers.
  
  Proxy FS driver is added to overcome the limit imposed by local +
  passthrough security model combination that needs qemu to be started by
  root user. Mapped and none secuiry model can be used by non root user
  also.
  
  So Proxy FS driver does not need any security model(its pass-through
  only)
 
 The Proxy FS driver does not need the security model, but if so desired
 it would be possible to choose to implement the security models. It just
 happens that the driver is hardcoded to only operate in 'passthrough'
 mode.
 
 I think that disabling the parsing of the 'security' parameter for
 non-local drivers is dangerous, because an application might think that
 the 'mapped' model was supported, but its parameter would get silently
 ignored. If the requested value is not supported, then the application
 should always be told about that.
 
 So, IMHO, it would be better to have logic such as:
Daniel,
Code in virtio-9p-device.c does the validation of security model. Aneesh's 
recent patch moved the validation in fsdev/qemu-fsdev.c
 
 if (strcmp(security_mode, passthrough) == 0) {
  ...
 } else if (strcmp(security_model, mapped) == 0) {
  if (strcmp(fsdriver, local) != 0

  1   2   3   >