From patchwork Wed May 26 23:21:44 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: jvrao X-Patchwork-Id: 53669 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 7DADDB7D17 for ; Thu, 27 May 2010 09:24:32 +1000 (EST) Received: from localhost ([127.0.0.1]:45776 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OHPxd-0007eB-44 for incoming@patchwork.ozlabs.org; Wed, 26 May 2010 19:24:29 -0400 Received: from [140.186.70.92] (port=51721 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OHPrc-0003Q1-J8 for qemu-devel@nongnu.org; Wed, 26 May 2010 19:18:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OHPra-0006jU-Lc for qemu-devel@nongnu.org; Wed, 26 May 2010 19:18:16 -0400 Received: from e38.co.us.ibm.com ([32.97.110.159]:39392) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OHPra-0006j4-Dq for qemu-devel@nongnu.org; Wed, 26 May 2010 19:18:14 -0400 Received: from d03relay01.boulder.ibm.com (d03relay01.boulder.ibm.com [9.17.195.226]) by e38.co.us.ibm.com (8.14.3/8.13.1) with ESMTP id o4QNBiZ1002350 for ; Wed, 26 May 2010 17:11:44 -0600 Received: from d03av02.boulder.ibm.com (d03av02.boulder.ibm.com [9.17.195.168]) by d03relay01.boulder.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id o4QNIBrk175256 for ; Wed, 26 May 2010 17:18:11 -0600 Received: from d03av02.boulder.ibm.com (loopback [127.0.0.1]) by d03av02.boulder.ibm.com (8.14.3/8.13.1/NCO v10.0 AVout) with ESMTP id o4QNIBAq016914 for ; Wed, 26 May 2010 17:18:11 -0600 Received: from localhost.localdomain (elm9m80.beaverton.ibm.com [9.47.81.80]) by d03av02.boulder.ibm.com (8.14.3/8.13.1/NCO v10.0 AVin) with ESMTP id o4QNI067016065; Wed, 26 May 2010 17:18:10 -0600 From: "Venkateswararao Jujjuri (JV)" To: qemu-devel@nongnu.org Date: Wed, 26 May 2010 16:21:44 -0700 Message-Id: <1274916106-25616-6-git-send-email-jvrao@linux.vnet.ibm.com> X-Mailer: git-send-email 1.6.0.6 In-Reply-To: <1274916106-25616-1-git-send-email-jvrao@linux.vnet.ibm.com> References: <1274916106-25616-1-git-send-email-jvrao@linux.vnet.ibm.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Cc: aliguori@us.ibm.com, "Venkateswararao Jujjuri \(JV\)" Subject: [Qemu-devel] [PATCH -V4 5/7] virtio-9p: Implemented security model for symlink and link. X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Signed-off-by: Venkateswararao Jujjuri --- hw/file-op-9p.h | 4 +- hw/virtio-9p-local.c | 98 ++++++++++++++++++++++++++++++++++++++++--------- hw/virtio-9p.c | 24 +++++++++---- 3 files changed, 99 insertions(+), 27 deletions(-) diff --git a/hw/file-op-9p.h b/hw/file-op-9p.h index 144dd77..c1c08b4 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 bd8c1c7..395a33f 100644 --- a/hw/virtio-9p-local.c +++ b/hw/virtio-9p-local.c @@ -64,12 +64,27 @@ 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; + } + do { + tsize = read(fd, (void *)buf, bufsz); + } while (tsize == -1 && errno == EINTR); + 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) @@ -262,32 +277,79 @@ 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; + int serrno = 0; + /* 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; + do { + write_size = write(fd, (void *)oldpath, oldpath_size); + } while (write_size == -1 && errno == EINTR); + + if (write_size != oldpath_size) { + serrno = errno; + 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) { + serrno = errno; + 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 & 07777); + if (err == -1) { + serrno = errno; + goto err_end; + } + err = chown(rpath(fs_ctx, newpath), credp->fc_uid, credp->fc_gid); + if (err == -1) { + serrno = errno; + goto err_end; + } + } + return err; + +err_end: + remove(rpath(fs_ctx, newpath)); + errno = serrno; + 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 38c1d68..90620aa 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; + + return s->ops->symlink(&s->ctx, vs->extension.data, vs->fullname.data, + &cred); } -static int v9fs_do_link(V9fsState *s, V9fsString *oldpath, V9fsString *newpath) +static int v9fs_do_link(V9fsState *s, V9fsFidState *nfidp, V9fsCreateState *vs) { - return s->ops->link(&s->ctx, oldpath->data, newpath->data); + FsCred cred; + cred_init(&cred); + cred.fc_uid = nfidp->uid; + cred.fc_mode = vs->perm & 0777; + + return s->ops->link(&s->ctx, nfidp->path.data, vs->fullname.data, &cred); } static int v9fs_do_truncate(V9fsState *s, V9fsString *path, off_t size) @@ -1766,7 +1776,7 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err) err = v9fs_do_mkdir(s, vs); v9fs_create_post_mkdir(s, vs, err); } else if (vs->perm & P9_STAT_MODE_SYMLINK) { - err = v9fs_do_symlink(s, &vs->extension, &vs->fullname); + err = v9fs_do_symlink(s, vs); v9fs_create_post_perms(s, vs, err); } else if (vs->perm & P9_STAT_MODE_LINK) { int32_t nfid = atoi(vs->extension.data); @@ -1775,7 +1785,7 @@ static void v9fs_create_post_lstat(V9fsState *s, V9fsCreateState *vs, int err) err = -errno; v9fs_post_create(s, vs, err); } - err = v9fs_do_link(s, &nfidp->path, &vs->fullname); + err = v9fs_do_link(s, nfidp, vs); v9fs_create_post_perms(s, vs, err); } else if (vs->perm & P9_STAT_MODE_DEVICE) { char ctype;