From patchwork Tue Jan 18 06:26:26 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mohan Kumar M X-Patchwork-Id: 79262 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 9CDD5B7126 for ; Tue, 18 Jan 2011 17:38:15 +1100 (EST) Received: from localhost ([127.0.0.1]:60447 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Pf5Cm-0006Jd-CC for incoming@patchwork.ozlabs.org; Tue, 18 Jan 2011 01:38:12 -0500 Received: from [140.186.70.92] (port=36648 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Pf51T-0002G3-TK for qemu-devel@nongnu.org; Tue, 18 Jan 2011 01:26:33 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Pf51S-00032M-5a for qemu-devel@nongnu.org; Tue, 18 Jan 2011 01:26:31 -0500 Received: from e28smtp03.in.ibm.com ([122.248.162.3]:39535) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Pf51R-00031r-2U for qemu-devel@nongnu.org; Tue, 18 Jan 2011 01:26:30 -0500 Received: from d28relay01.in.ibm.com (d28relay01.in.ibm.com [9.184.220.58]) by e28smtp03.in.ibm.com (8.14.4/8.13.1) with ESMTP id p0I6QROR000718 for ; Tue, 18 Jan 2011 11:56:27 +0530 Received: from d28av03.in.ibm.com (d28av03.in.ibm.com [9.184.220.65]) by d28relay01.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p0I6QRrq3354792 for ; Tue, 18 Jan 2011 11:56:27 +0530 Received: from d28av03.in.ibm.com (loopback [127.0.0.1]) by d28av03.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p0I6QR9M022916 for ; Tue, 18 Jan 2011 17:26:27 +1100 Received: from explorer.in.ibm.com ([9.124.35.46]) by d28av03.in.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p0I6QRfD022913 for ; Tue, 18 Jan 2011 17:26:27 +1100 From: "M. Mohan Kumar" To: qemu-devel@nongnu.org Date: Tue, 18 Jan 2011 11:56:26 +0530 Message-Id: <1295331986-24232-1-git-send-email-mohan@in.ibm.com> X-Mailer: git-send-email 1.7.3.4 In-Reply-To: <1295331799-23856-1-git-send-email-mohan@in.ibm.com> References: <1295331799-23856-1-git-send-email-mohan@in.ibm.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6, seldom 2.4 (older, 4) Subject: [Qemu-devel] [V3 PATCH 8/8] virtio-9p: Chroot environment for other functions 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 Add chroot functionality for systemcalls that can operate on a file using relative directory file descriptor. Signed-off-by: M. Mohan Kumar --- hw/9pfs/virtio-9p-local.c | 222 ++++++++++++++++++++++++++++++++++++++------ 1 files changed, 191 insertions(+), 31 deletions(-) diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c index d2e32e2..9586190 100644 --- a/hw/9pfs/virtio-9p-local.c +++ b/hw/9pfs/virtio-9p-local.c @@ -20,6 +20,7 @@ #include #include #include +#include /* Helper routine to fill V9fsFileObjectRequest structure */ static void fill_request(V9fsFileObjectRequest *request, const char *path, @@ -141,14 +142,36 @@ static int __link(FsContext *fs_ctx, const char *oldpath, return retval; } +/* + * Returns file descriptor of dirname(path) + * This fd can be used by *at functions + */ +static int get_dirfd(FsContext *fs_ctx, const char *path) +{ + V9fsFileObjectRequest request; + int fd, error = 0; + char *dpath = qemu_strdup(path); + + fill_request(&request, dirname(dpath), NULL); + request.data.type = T_OPEN; + fd = v9fs_request(fs_ctx, &request, &error); + if (fd < 0) { + errno = error; + } + qemu_free(dpath); + qemu_free(request.path.path); + return fd; +} + static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf) { int err; - err = lstat(rpath(fs_ctx, path), stbuf); - if (err) { - return err; - } + if (fs_ctx->fs_sm == SM_MAPPED) { + err = lstat(rpath(fs_ctx, path), stbuf); + if (err) { + return err; + } /* Actual credentials are part of extended attrs */ uid_t tmp_uid; gid_t tmp_gid; @@ -170,6 +193,27 @@ static int local_lstat(FsContext *fs_ctx, const char *path, struct stat *stbuf) sizeof(dev_t)) > 0) { stbuf->st_rdev = tmp_dev; } + } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) { + int pfd, serrno = 0; + char *tmp_path; + + pfd = get_dirfd(fs_ctx, path); + if (pfd < 0) { + return -1; + } + tmp_path = qemu_strdup(path); + err = fstatat(pfd, basename(tmp_path), stbuf, AT_SYMLINK_NOFOLLOW); + if (err < 0) { + serrno = errno; + } + close(pfd); + qemu_free(tmp_path); + errno = serrno; + } else { + err = lstat(rpath(fs_ctx, path), stbuf); + if (err) { + return err; + } } return err; } @@ -234,9 +278,23 @@ static ssize_t local_readlink(FsContext *fs_ctx, const char *path, } while (tsize == -1 && errno == EINTR); close(fd); return tsize; - } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) || - (fs_ctx->fs_sm == SM_NONE)) { + } else if (fs_ctx->fs_sm == SM_NONE) { tsize = readlink(rpath(fs_ctx, path), buf, bufsz); + } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) { + int pfd, serrno = 0; + char *tmp_path; + pfd = get_dirfd(fs_ctx, path); + if (pfd < 0) { + return -1; + } + tmp_path = qemu_strdup(path); + tsize = readlinkat(pfd, basename(tmp_path), buf, bufsz); + if (tsize < 0) { + serrno = 0; + } + close(pfd); + qemu_free(tmp_path); + errno = serrno; } return tsize; } @@ -328,8 +386,23 @@ static int local_chmod(FsContext *fs_ctx, const char *path, FsCred *credp) { if (fs_ctx->fs_sm == SM_MAPPED) { return local_set_xattr(rpath(fs_ctx, path), credp); - } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) || - (fs_ctx->fs_sm == SM_NONE)) { + } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) { + int pfd, err, serrno = 0; + char *tmp_path; + pfd = get_dirfd(fs_ctx, path); + if (pfd < 0) { + return -1; + } + tmp_path = qemu_strdup(path); + err = fchmodat(pfd, basename(tmp_path), credp->fc_mode, 0); + if (err == -1) { + serrno = errno; + } + qemu_free(tmp_path); + close(pfd); + errno = serrno; + return err; + } else if (fs_ctx->fs_sm == SM_NONE) { return chmod(rpath(fs_ctx, path), credp->fc_mode); } return -1; @@ -575,53 +648,140 @@ static int local_link(FsContext *fs_ctx, const char *oldpath, static int local_truncate(FsContext *ctx, const char *path, off_t size) { - return truncate(rpath(ctx, path), size); + if (ctx->fs_sm == SM_PASSTHROUGH) { + int fd, retval; + fd = __open(ctx, path, O_RDWR); + if (fd < 0) { + return fd; + } + retval = ftruncate(fd, size); + close(fd); + return retval; + } else { + return truncate(rpath(ctx, path), size); + } } static int local_rename(FsContext *ctx, const char *oldpath, const char *newpath) { - char *tmp; - int err; - - tmp = qemu_strdup(rpath(ctx, oldpath)); + int err, serrno = 0; - err = rename(tmp, rpath(ctx, newpath)); - if (err == -1) { - int serrno = errno; - qemu_free(tmp); + if (ctx->fs_sm == SM_PASSTHROUGH) { + int opfd, npfd; + char *old_tmppath, *new_tmppath; + opfd = get_dirfd(ctx, oldpath); + if (opfd < 0) { + return -1; + } + npfd = get_dirfd(ctx, newpath); + if (npfd < 0) { + close(opfd); + return -1; + } + old_tmppath = qemu_strdup(oldpath); + new_tmppath = qemu_strdup(newpath); + err = renameat(opfd, basename(old_tmppath), + npfd, basename(new_tmppath)); + if (err == -1) { + serrno = errno; + } + close(npfd); + close(opfd); + qemu_free(old_tmppath); + qemu_free(new_tmppath); errno = serrno; } else { - qemu_free(tmp); + char *tmp; + tmp = qemu_strdup(rpath(ctx, oldpath)); + + err = rename(tmp, rpath(ctx, newpath)); + if (err == -1) { + int serrno = errno; + qemu_free(tmp); + errno = serrno; + } else { + qemu_free(tmp); + } } return err; - } static int local_chown(FsContext *fs_ctx, const char *path, FsCred *credp) { - if ((credp->fc_uid == -1 && credp->fc_gid == -1) || - (fs_ctx->fs_sm == SM_PASSTHROUGH)) { - return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid); - } else if (fs_ctx->fs_sm == SM_MAPPED) { + if (fs_ctx->fs_sm == SM_MAPPED) { return local_set_xattr(rpath(fs_ctx, path), credp); - } else if ((fs_ctx->fs_sm == SM_PASSTHROUGH) || - (fs_ctx->fs_sm == SM_NONE)) { + } else if (fs_ctx->fs_sm == SM_NONE) { return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid); + } else if (fs_ctx->fs_sm == SM_PASSTHROUGH) { + int pfd, err, serrno = 0; + char *old_path; + pfd = get_dirfd(fs_ctx, path); + if (pfd < 0) { + return -1; + } + old_path = qemu_strdup(path); + err = fchownat(pfd, basename(old_path), credp->fc_uid, credp->fc_gid, + AT_SYMLINK_NOFOLLOW); + if (err == -1) { + serrno = errno; + } + qemu_free(old_path); + close(pfd); + errno = serrno; + return err; } return -1; } -static int local_utimensat(FsContext *s, const char *path, - const struct timespec *buf) +static int local_utimensat(FsContext *fs_ctx, const char *path, + const struct timespec *buf) { - return qemu_utimensat(AT_FDCWD, rpath(s, path), buf, AT_SYMLINK_NOFOLLOW); + if (fs_ctx->fs_sm == SM_PASSTHROUGH) { + int fd, retval; + fd = __open(fs_ctx, path, O_RDONLY); + retval = futimens(fd, buf); + close(fd); + return retval; + } else { + return utimensat(AT_FDCWD, rpath(fs_ctx, path), buf, + AT_SYMLINK_NOFOLLOW); + } } -static int local_remove(FsContext *ctx, const char *path) -{ - return remove(rpath(ctx, path)); +static int local_remove(FsContext *fs_ctx, const char *path) + { + if (fs_ctx->fs_sm == SM_PASSTHROUGH) { + int pfd, err, serrno, flags; + char *old_path; + struct stat stbuf; + pfd = get_dirfd(fs_ctx, path); + if (pfd < 0) { + return -1; + } + old_path = qemu_strdup(path); + err = fstatat(pfd, basename(old_path), &stbuf, AT_SYMLINK_NOFOLLOW); + if (err < 0) { + return -1; + } + serrno = flags = 0; + if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { + flags = AT_REMOVEDIR; + } else { + flags = 0; + } + err = unlinkat(pfd, basename(old_path), flags); + if (err == -1) { + serrno = errno; + } + qemu_free(old_path); + close(pfd); + errno = serrno; + return err; + } else { + return remove(rpath(fs_ctx, path)); + } } static int local_fsync(FsContext *ctx, int fd, int datasync)