[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [V4 PATCH 8/8] Chroot environment for other functions
From: |
M. Mohan Kumar |
Subject: |
[Qemu-devel] [V4 PATCH 8/8] Chroot environment for other functions |
Date: |
Tue, 1 Feb 2011 10:57:56 +0530 |
Add chroot functionality for systemcalls that can operate on a file
using relative directory file descriptor.
Signed-off-by: M. Mohan Kumar <address@hidden>
---
hw/9pfs/virtio-9p-local.c | 221 +++++++++++++++++++++++++++++++++++++++------
1 files changed, 191 insertions(+), 30 deletions(-)
diff --git a/hw/9pfs/virtio-9p-local.c b/hw/9pfs/virtio-9p-local.c
index 37a2510..b6471dd 100644
--- a/hw/9pfs/virtio-9p-local.c
+++ b/hw/9pfs/virtio-9p-local.c
@@ -20,6 +20,7 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <attr/xattr.h>
+#include <libgen.h>
/* Helper routine to fill V9fsFileObjectRequest structure */
static void fill_request(V9fsFileObjectRequest *request, const char *path,
@@ -141,14 +142,36 @@ static int passthrough_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((void *)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,141 @@ 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 = passthrough_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)) {
+ if (fs_ctx->fs_sm == SM_NONE ||
+ (credp->fc_uid == -1 && credp->fc_gid == -1)) {
return lchown(rpath(fs_ctx, path), credp->fc_uid, credp->fc_gid);
} else 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)) {
- 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 = passthrough_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)
--
1.7.3.4
- Re: [Qemu-devel] [V4 PATCH 2/8] Provide chroot environment server side interfaces, (continued)
- [Qemu-devel] [V4 PATCH 3/8] Add client side interfaces for chroot environment, M. Mohan Kumar, 2011/02/01
- [Qemu-devel] [V4 PATCH 4/8] Add support to open a file in chroot environment, M. Mohan Kumar, 2011/02/01
- [Qemu-devel] [V4 PATCH 5/8] Create support in chroot environment, M. Mohan Kumar, 2011/02/01
- [Qemu-devel] [V4 PATCH 6/8] Support for creating special files, M. Mohan Kumar, 2011/02/01
- [Qemu-devel] [V4 PATCH 7/8] Move file post creation changes to none security model, M. Mohan Kumar, 2011/02/01
- [Qemu-devel] [V4 PATCH 8/8] Chroot environment for other functions,
M. Mohan Kumar <=