Patchwork [-V3,23/32] vritio-9p: Fix chmod bug with directory

login
register
mail settings
Submitter Aneesh Kumar K.V
Date March 25, 2010, 4:43 p.m.
Message ID <1269535420-31206-24-git-send-email-aneesh.kumar@linux.vnet.ibm.com>
Download mbox | patch
Permalink /patch/48574/
State New
Headers show

Comments

Aneesh Kumar K.V - March 25, 2010, 4:43 p.m.
chmod 0777 <dir>  fails with EIO.
This is a result of wrong check in server code.
Server code is trying to check if the file type is not being changed by
making sure that fidp->dir is not NULL.
But the fidp->dir is set only on opendir/createdir.

This patch gives proper check to all special files.

Signed-off-by: Venkateswararao Jujjuri <jvrao@linux.vnet.ibm.com>
Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
---
 hw/virtio-9p.c |   56 +++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 41 insertions(+), 15 deletions(-)

Patch

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 9aa4b72..e519605 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -298,11 +298,12 @@  static int free_fid(V9fsState *s, int32_t fid)
 #define P9_STAT_MODE_SETGID	0x00040000
 #define P9_STAT_MODE_SETVTX	0x00010000
 
-#define P9_STAT_MODE_SPECIAL	(P9_STAT_MODE_NAMED_PIPE | \
-                                P9_STAT_MODE_SYMLINK | \
-                                P9_STAT_MODE_LINK | \
-                                P9_STAT_MODE_DEVICE)
-
+#define P9_STAT_MODE_TYPE_BITS (P9_STAT_MODE_DIR |		\
+				P9_STAT_MODE_SYMLINK |		\
+				P9_STAT_MODE_LINK |		\
+                                P9_STAT_MODE_DEVICE |		\
+                                P9_STAT_MODE_NAMED_PIPE |	\
+                                P9_STAT_MODE_SOCKET)
 
 /* This is the algorithm from ufs in spfs */
 static void stat_to_qid(const struct stat *stbuf, V9fsQID *qidp)
@@ -1842,6 +1843,7 @@  typedef struct V9fsWstatState
     int16_t unused;
     V9fsStat v9stat;
     V9fsFidState *fidp;
+    struct stat stbuf;
     V9fsString nname;
 } V9fsWstatState;
 
@@ -2034,6 +2036,37 @@  static int donttouch_stat(V9fsStat *stat)
 		return 0;
 }
 
+static void v9fs_wstat_post_lstat(V9fsState *s, V9fsWstatState *vs, int err)
+{
+    uint32_t v9_mode;
+
+    if (err == -1) {
+        err = -errno;
+        goto out;
+    }
+
+    v9_mode = stat_to_v9mode(&vs->stbuf);
+
+    if ((vs->v9stat.mode & P9_STAT_MODE_TYPE_BITS) !=
+        (v9_mode & P9_STAT_MODE_TYPE_BITS)) {
+            /* Attempting to change the type */
+            err = -EIO;
+            goto out;
+    }
+
+    if (posix_chmod(s, &vs->fidp->path, v9mode_to_mode(vs->v9stat.mode,
+                    &vs->v9stat.extension))) {
+            err = -errno;
+     }
+    v9fs_wstat_post_chmod(s, vs, err);
+    return;
+
+out:
+    v9fs_stat_free(&vs->v9stat);
+    complete_pdu(s, vs->pdu, err);
+    qemu_free(vs);
+}
+
 static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
 {
     int32_t fid;
@@ -2060,16 +2093,9 @@  static void v9fs_wstat(V9fsState *s, V9fsPDU *pdu)
     }
 
     if (vs->v9stat.mode != -1) {
-        if (vs->v9stat.mode & P9_STAT_MODE_DIR && vs->fidp->dir == NULL) {
-            err = -EIO;
-            goto out;
-        }
-
-        if (posix_chmod(s, &vs->fidp->path,
-                    v9mode_to_mode(vs->v9stat.mode,
-                        &vs->v9stat.extension))) {
-            err = -errno;
-        }
+        err = posix_lstat(s, &vs->fidp->path, &vs->stbuf);
+        v9fs_wstat_post_lstat(s, vs, err);
+        return;
     }
 
     v9fs_wstat_post_chmod(s, vs, err);