[Qemu-devel] [PATCH -V3 5/7] virtio-9p: Implemented security model for symlink and link.
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.
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