[Qemu-devel] [PATCH -V3 5/7] virtio-9p: Implemented security model for symlink and link.

2010-05-21 Thread Venkateswararao Jujjuri (JV)
Signed-off-by: Venkateswararao Jujjuri 
---
 hw/file-op-9p.h  |4 +-
 hw/virtio-9p-local.c |   87 +++--
 hw/virtio-9p.c   |   24 ++
 3 files changed, 88 insertions(+), 27 deletions(-)

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 752fbad..0a9c10a 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -54,8 +54,8 @@ typedef struct FileOperations
 int (*mknod)(FsContext *, const char *, FsCred *);
 int (*utime)(FsContext *, const char *, const struct utimbuf *);
 int (*remove)(FsContext *, const char *);
-int (*symlink)(FsContext *, const char *, const char *);
-int (*link)(FsContext *, const char *, const char *);
+int (*symlink)(FsContext *, const char *, const char *, FsCred *);
+int (*link)(FsContext *, const char *, const char *, FsCred *);
 int (*setuid)(FsContext *, uid_t);
 int (*close)(FsContext *, int);
 int (*closedir)(FsContext *, DIR *);
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index bfcd695..ca0f065 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -64,12 +64,25 @@ static int local_set_xattr(const char *path, FsCred *credp)
 }
 }
  return 0;
- }
+}
 
-static ssize_t local_readlink(FsContext *ctx, const char *path,
-char *buf, size_t bufsz)
+static ssize_t local_readlink(FsContext *fs_ctx, const char *path,
+char *buf, size_t bufsz)
 {
-return readlink(rpath(ctx, path), buf, bufsz);
+ssize_t tsize = -1;
+if (fs_ctx->fs_sm == sm_mapped) {
+int fd;
+fd = open(rpath(fs_ctx, path), O_RDONLY);
+if (fd == -1) {
+return -1;
+}
+tsize = read(fd, (void *)buf, bufsz);
+close(fd);
+return tsize;
+} else if (fs_ctx->fs_sm == sm_passthrough) {
+tsize = readlink(rpath(fs_ctx, path), buf, bufsz);
+}
+return tsize;
 }
 
 static int local_close(FsContext *ctx, int fd)
@@ -247,32 +260,70 @@ err_end:
 return err;
 }
 
-static int local_symlink(FsContext *ctx, const char *oldpath,
-const char *newpath)
+
+static int local_symlink(FsContext *fs_ctx, const char *oldpath,
+const char *newpath, FsCred *credp)
 {
-return symlink(oldpath, rpath(ctx, newpath));
+int err = -1;
+/* Determine the security model */
+if (fs_ctx->fs_sm == sm_mapped) {
+int fd;
+ssize_t oldpath_size, write_size;
+fd = open(rpath(fs_ctx, newpath), O_CREAT|O_EXCL|O_RDWR,
+SM_LOCAL_MODE_BITS);
+if (fd == -1) {
+return fd;
+}
+/* Write the oldpath (target) to the file. */
+oldpath_size = strlen(oldpath) + 1;
+write_size = write(fd, (void *)oldpath, oldpath_size);
+if (write_size != oldpath_size) {
+close(fd);
+err = -1;
+goto err_end;
+}
+close(fd);
+/* Set cleint credentials in symlink's xattr */
+credp->fc_mode = credp->fc_mode|S_IFLNK;
+err = local_set_xattr(rpath(fs_ctx, newpath), credp);
+if (err == -1) {
+goto err_end;
+}
+} else if (fs_ctx->fs_sm == sm_passthrough) {
+err = symlink(oldpath, rpath(fs_ctx, newpath));
+if (err) {
+return err;
+}
+err = chmod(rpath(fs_ctx, newpath), credp->fc_mode & 0);
+if (err == -1) {
+goto err_end;
+}
+err = chown(rpath(fs_ctx, newpath), credp->fc_uid, credp->fc_gid);
+if (err == -1) {
+goto err_end;
+}
+}
+return err;
+
+err_end:
+remove(rpath(fs_ctx, newpath));
+return err;
 }
 
-static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
+static int local_link(FsContext *fs_ctx, const char *oldpath,
+const char *newpath, FsCred *credp)
 {
-char *tmp = qemu_strdup(rpath(ctx, oldpath));
-int err, serrno = 0;
+char *tmp = qemu_strdup(rpath(fs_ctx, oldpath));
+int err;
 
 if (tmp == NULL) {
 return -ENOMEM;
 }
 
-err = link(tmp, rpath(ctx, newpath));
-if (err == -1) {
-serrno = errno;
-}
+err = link(tmp, rpath(fs_ctx, newpath));
 
 qemu_free(tmp);
 
-if (err == -1) {
-errno = serrno;
-}
-
 return err;
 }
 
diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 30f649d..fbc846b 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -197,15 +197,25 @@ static int v9fs_do_open2(V9fsState *s, V9fsCreateState 
*vs)
 return s->ops->open2(&s->ctx, vs->fullname.data, flags, &cred);
 }
 
-static int v9fs_do_symlink(V9fsState *s, V9fsString *oldpath,
-V9fsString *newpath)
+static int v9fs_do_symlink(V9fsState *s, V9fsCreateState *vs)
 {
-return s->ops->symlink(&s->ctx, oldpath->data, newpath->data);
+FsCred cred;
+cred_init(&cred);
+cred.fc_uid = vs->fidp->uid;
+cred.fc_mode = vs->perm | 0777

Re: [Qemu-devel] [PATCH -V3 5/7] virtio-9p: Implemented security model for symlink and link.

2010-05-24 Thread Anthony Liguori

On 05/21/2010 04:26 PM, Venkateswararao Jujjuri (JV) wrote:

Signed-off-by: Venkateswararao Jujjuri
---
  hw/file-op-9p.h  |4 +-
  hw/virtio-9p-local.c |   87 +++--
  hw/virtio-9p.c   |   24 ++
  3 files changed, 88 insertions(+), 27 deletions(-)

diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h
index 752fbad..0a9c10a 100644
--- a/hw/file-op-9p.h
+++ b/hw/file-op-9p.h
@@ -54,8 +54,8 @@ typedef struct FileOperations
  int (*mknod)(FsContext *, const char *, FsCred *);
  int (*utime)(FsContext *, const char *, const struct utimbuf *);
  int (*remove)(FsContext *, const char *);
-int (*symlink)(FsContext *, const char *, const char *);
-int (*link)(FsContext *, const char *, const char *);
+int (*symlink)(FsContext *, const char *, const char *, FsCred *);
+int (*link)(FsContext *, const char *, const char *, FsCred *);
  int (*setuid)(FsContext *, uid_t);
  int (*close)(FsContext *, int);
  int (*closedir)(FsContext *, DIR *);
diff --git a/hw/virtio-9p-local.c b/hw/virtio-9p-local.c
index bfcd695..ca0f065 100644
--- a/hw/virtio-9p-local.c
+++ b/hw/virtio-9p-local.c
@@ -64,12 +64,25 @@ static int local_set_xattr(const char *path, FsCred *credp)
  }
  }
   return 0;
- }
+}

-static ssize_t local_readlink(FsContext *ctx, const char *path,
-char *buf, size_t bufsz)
+static ssize_t local_readlink(FsContext *fs_ctx, const char *path,
+char *buf, size_t bufsz)
  {
-return readlink(rpath(ctx, path), buf, bufsz);
+ssize_t tsize = -1;
+if (fs_ctx->fs_sm == sm_mapped) {
+int fd;
+fd = open(rpath(fs_ctx, path), O_RDONLY);
+if (fd == -1) {
+return -1;
+}
+tsize = read(fd, (void *)buf, bufsz);
+close(fd);
+return tsize;
+} else if (fs_ctx->fs_sm == sm_passthrough) {
+tsize = readlink(rpath(fs_ctx, path), buf, bufsz);
+}
+return tsize;
  }

  static int local_close(FsContext *ctx, int fd)
@@ -247,32 +260,70 @@ err_end:
  return err;
  }

-static int local_symlink(FsContext *ctx, const char *oldpath,
-const char *newpath)
+
+static int local_symlink(FsContext *fs_ctx, const char *oldpath,
+const char *newpath, FsCred *credp)
  {
-return symlink(oldpath, rpath(ctx, newpath));
+int err = -1;
+/* Determine the security model */
+if (fs_ctx->fs_sm == sm_mapped) {
+int fd;
+ssize_t oldpath_size, write_size;
+fd = open(rpath(fs_ctx, newpath), O_CREAT|O_EXCL|O_RDWR,
+SM_LOCAL_MODE_BITS);
+if (fd == -1) {
+return fd;
+}
+/* Write the oldpath (target) to the file. */
+oldpath_size = strlen(oldpath) + 1;
+write_size = write(fd, (void *)oldpath, oldpath_size);
   


Signals are pretty frequent in qemu so not handling EINTR is asking for 
trouble.


Regards,

Anthony Liguori


+if (write_size != oldpath_size) {
+close(fd);
+err = -1;
+goto err_end;
+}
+close(fd);
+/* Set cleint credentials in symlink's xattr */
+credp->fc_mode = credp->fc_mode|S_IFLNK;
+err = local_set_xattr(rpath(fs_ctx, newpath), credp);
+if (err == -1) {
+goto err_end;
+}
+} else if (fs_ctx->fs_sm == sm_passthrough) {
+err = symlink(oldpath, rpath(fs_ctx, newpath));
+if (err) {
+return err;
+}
+err = chmod(rpath(fs_ctx, newpath), credp->fc_mode&  0);
+if (err == -1) {
+goto err_end;
+}
+err = chown(rpath(fs_ctx, newpath), credp->fc_uid, credp->fc_gid);
+if (err == -1) {
+goto err_end;
+}
+}
+return err;
+
+err_end:
+remove(rpath(fs_ctx, newpath));
+return err;
  }

-static int local_link(FsContext *ctx, const char *oldpath, const char *newpath)
+static int local_link(FsContext *fs_ctx, const char *oldpath,
+const char *newpath, FsCred *credp)
  {
-char *tmp = qemu_strdup(rpath(ctx, oldpath));
-int err, serrno = 0;
+char *tmp = qemu_strdup(rpath(fs_ctx, oldpath));
+int err;

  if (tmp == NULL) {
  return -ENOMEM;
  }

-err = link(tmp, rpath(ctx, newpath));
-if (err == -1) {
-serrno = errno;
-}
+err = link(tmp, rpath(fs_ctx, newpath));

  qemu_free(tmp);

-if (err == -1) {
-errno = serrno;
-}
-
  return err;
  }

diff --git a/hw/virtio-9p.c b/hw/virtio-9p.c
index 30f649d..fbc846b 100644
--- a/hw/virtio-9p.c
+++ b/hw/virtio-9p.c
@@ -197,15 +197,25 @@ static int v9fs_do_open2(V9fsState *s, V9fsCreateState 
*vs)
  return s->ops->open2(&s->ctx, vs->fullname.data, flags,&cred);
  }

-static int v9fs_do_symlink(V9fsState *s, V9fsString *oldpath,
-V9fsString *newpath)
+static int v9fs_do_symlink(V9fsState *s, V9fsC