File 0215-9p-introduce-the-V9fsDir-type.patch of Package qemu.10254
From 33f4672846312ce2d403e56a1184b7fe426e5724 Mon Sep 17 00:00:00 2001
From: Greg Kurz <gkurz@linux.vnet.ibm.com>
Date: Mon, 6 Jun 2016 11:52:34 +0200
Subject: [PATCH] 9p: introduce the V9fsDir type
If we are to switch back to readdir(), we need a more complex type than
DIR * to be able to serialize concurrent accesses to the directory stream.
This patch introduces a placeholder type and fixes all users.
Reviewed-by: Eric Blake <eblake@redhat.com>
Signed-off-by: Greg Kurz <gkurz@linux.vnet.ibm.com>
(cherry picked from commit f314ea4e30a1ef87bf8845da952c6dd0bac20b95)
[BR: Fix and/or infrastructure for BSC#1020427 CVE-2016-9602]
Signed-off-by: Bruce Rogers <brogers@suse.com>
---
hw/9pfs/9p-handle.c | 18 +++++++++---------
hw/9pfs/9p-local.c | 18 +++++++++---------
hw/9pfs/9p-proxy.c | 20 ++++++++++----------
hw/9pfs/9p.c | 12 ++++++------
hw/9pfs/9p.h | 6 +++++-
5 files changed, 39 insertions(+), 35 deletions(-)
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c
index 58b77b4c94..3537c8a7f0 100644
--- a/hw/9pfs/9p-handle.c
+++ b/hw/9pfs/9p-handle.c
@@ -110,7 +110,7 @@ static int handle_close(FsContext *ctx, V9fsFidOpenState *fs)
static int handle_closedir(FsContext *ctx, V9fsFidOpenState *fs)
{
- return closedir(fs->dir);
+ return closedir(fs->dir.stream);
}
static int handle_open(FsContext *ctx, V9fsPath *fs_path,
@@ -130,8 +130,8 @@ static int handle_opendir(FsContext *ctx,
if (ret < 0) {
return -1;
}
- fs->dir = fdopendir(ret);
- if (!fs->dir) {
+ fs->dir.stream = fdopendir(ret);
+ if (!fs->dir.stream) {
return -1;
}
return 0;
@@ -139,24 +139,24 @@ static int handle_opendir(FsContext *ctx,
static void handle_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
{
- rewinddir(fs->dir);
+ rewinddir(fs->dir.stream);
}
static off_t handle_telldir(FsContext *ctx, V9fsFidOpenState *fs)
{
- return telldir(fs->dir);
+ return telldir(fs->dir.stream);
}
static int handle_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
struct dirent *entry,
struct dirent **result)
{
- return readdir_r(fs->dir, entry, result);
+ return readdir_r(fs->dir.stream, entry, result);
}
static void handle_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
{
- seekdir(fs->dir, off);
+ seekdir(fs->dir.stream, off);
}
static ssize_t handle_preadv(FsContext *ctx, V9fsFidOpenState *fs,
@@ -260,7 +260,7 @@ static int handle_fstat(FsContext *fs_ctx, int fid_type,
int fd;
if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir);
+ fd = dirfd(fs->dir.stream);
} else {
fd = fs->fd;
}
@@ -407,7 +407,7 @@ static int handle_fsync(FsContext *ctx, int fid_type,
int fd;
if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir);
+ fd = dirfd(fs->dir.stream);
} else {
fd = fs->fd;
}
diff --git a/hw/9pfs/9p-local.c b/hw/9pfs/9p-local.c
index 5bc25756f3..1f9558dfdc 100644
--- a/hw/9pfs/9p-local.c
+++ b/hw/9pfs/9p-local.c
@@ -345,7 +345,7 @@ static int local_close(FsContext *ctx, V9fsFidOpenState *fs)
static int local_closedir(FsContext *ctx, V9fsFidOpenState *fs)
{
- return closedir(fs->dir);
+ return closedir(fs->dir.stream);
}
static int local_open(FsContext *ctx, V9fsPath *fs_path,
@@ -367,9 +367,9 @@ static int local_opendir(FsContext *ctx,
char *path = fs_path->data;
buffer = rpath(ctx, path);
- fs->dir = opendir(buffer);
+ fs->dir.stream = opendir(buffer);
g_free(buffer);
- if (!fs->dir) {
+ if (!fs->dir.stream) {
return -1;
}
return 0;
@@ -377,12 +377,12 @@ static int local_opendir(FsContext *ctx,
static void local_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
{
- rewinddir(fs->dir);
+ rewinddir(fs->dir.stream);
}
static off_t local_telldir(FsContext *ctx, V9fsFidOpenState *fs)
{
- return telldir(fs->dir);
+ return telldir(fs->dir.stream);
}
static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
@@ -392,7 +392,7 @@ static int local_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
int ret;
again:
- ret = readdir_r(fs->dir, entry, result);
+ ret = readdir_r(fs->dir.stream, entry, result);
if (ctx->export_flags & V9FS_SM_MAPPED) {
entry->d_type = DT_UNKNOWN;
} else if (ctx->export_flags & V9FS_SM_MAPPED_FILE) {
@@ -408,7 +408,7 @@ again:
static void local_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
{
- seekdir(fs->dir, off);
+ seekdir(fs->dir.stream, off);
}
static ssize_t local_preadv(FsContext *ctx, V9fsFidOpenState *fs,
@@ -607,7 +607,7 @@ static int local_fstat(FsContext *fs_ctx, int fid_type,
int err, fd;
if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir);
+ fd = dirfd(fs->dir.stream);
} else {
fd = fs->fd;
}
@@ -995,7 +995,7 @@ static int local_fsync(FsContext *ctx, int fid_type,
int fd;
if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir);
+ fd = dirfd(fs->dir.stream);
} else {
fd = fs->fd;
}
diff --git a/hw/9pfs/9p-proxy.c b/hw/9pfs/9p-proxy.c
index 73d00dd74d..dfd3ca2300 100644
--- a/hw/9pfs/9p-proxy.c
+++ b/hw/9pfs/9p-proxy.c
@@ -631,7 +631,7 @@ static int proxy_close(FsContext *ctx, V9fsFidOpenState *fs)
static int proxy_closedir(FsContext *ctx, V9fsFidOpenState *fs)
{
- return closedir(fs->dir);
+ return closedir(fs->dir.stream);
}
static int proxy_open(FsContext *ctx, V9fsPath *fs_path,
@@ -650,14 +650,14 @@ static int proxy_opendir(FsContext *ctx,
{
int serrno, fd;
- fs->dir = NULL;
+ fs->dir.stream = NULL;
fd = v9fs_request(ctx->private, T_OPEN, NULL, "sd", fs_path, O_DIRECTORY);
if (fd < 0) {
errno = -fd;
return -1;
}
- fs->dir = fdopendir(fd);
- if (!fs->dir) {
+ fs->dir.stream = fdopendir(fd);
+ if (!fs->dir.stream) {
serrno = errno;
close(fd);
errno = serrno;
@@ -668,24 +668,24 @@ static int proxy_opendir(FsContext *ctx,
static void proxy_rewinddir(FsContext *ctx, V9fsFidOpenState *fs)
{
- rewinddir(fs->dir);
+ rewinddir(fs->dir.stream);
}
static off_t proxy_telldir(FsContext *ctx, V9fsFidOpenState *fs)
{
- return telldir(fs->dir);
+ return telldir(fs->dir.stream);
}
static int proxy_readdir_r(FsContext *ctx, V9fsFidOpenState *fs,
struct dirent *entry,
struct dirent **result)
{
- return readdir_r(fs->dir, entry, result);
+ return readdir_r(fs->dir.stream, entry, result);
}
static void proxy_seekdir(FsContext *ctx, V9fsFidOpenState *fs, off_t off)
{
- seekdir(fs->dir, off);
+ seekdir(fs->dir.stream, off);
}
static ssize_t proxy_preadv(FsContext *ctx, V9fsFidOpenState *fs,
@@ -789,7 +789,7 @@ static int proxy_fstat(FsContext *fs_ctx, int fid_type,
int fd;
if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir);
+ fd = dirfd(fs->dir.stream);
} else {
fd = fs->fd;
}
@@ -934,7 +934,7 @@ static int proxy_fsync(FsContext *ctx, int fid_type,
int fd;
if (fid_type == P9_FID_DIR) {
- fd = dirfd(fs->dir);
+ fd = dirfd(fs->dir.stream);
} else {
fd = fs->fd;
}
diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c
index 7350ce3020..53c8bdc67c 100644
--- a/hw/9pfs/9p.c
+++ b/hw/9pfs/9p.c
@@ -228,7 +228,7 @@ static int v9fs_reopen_fid(V9fsPDU *pdu, V9fsFidState *f)
} while (err == -EINTR && !pdu->cancelled);
}
} else if (f->fid_type == P9_FID_DIR) {
- if (f->fs.dir == NULL) {
+ if (f->fs.dir.stream == NULL) {
do {
err = v9fs_co_opendir(pdu, f);
} while (err == -EINTR && !pdu->cancelled);
@@ -342,7 +342,7 @@ static int free_fid(V9fsPDU *pdu, V9fsFidState *fidp)
retval = v9fs_co_close(pdu, &fidp->fs);
}
} else if (fidp->fid_type == P9_FID_DIR) {
- if (fidp->fs.dir != NULL) {
+ if (fidp->fs.dir.stream != NULL) {
retval = v9fs_co_closedir(pdu, &fidp->fs);
}
} else if (fidp->fid_type == P9_FID_XATTR) {
@@ -440,7 +440,7 @@ void v9fs_reclaim_fd(V9fsPDU *pdu)
reclaim_count++;
}
} else if (f->fid_type == P9_FID_DIR) {
- if (f->fs.dir != NULL) {
+ if (f->fs.dir.stream != NULL) {
/*
* Up the reference count so that
* a clunk request won't free this fid
@@ -448,8 +448,8 @@ void v9fs_reclaim_fd(V9fsPDU *pdu)
f->ref++;
f->rclm_lst = reclaim_list;
reclaim_list = f;
- f->fs_reclaim.dir = f->fs.dir;
- f->fs.dir = NULL;
+ f->fs_reclaim.dir.stream = f->fs.dir.stream;
+ f->fs.dir.stream = NULL;
reclaim_count++;
}
}
@@ -1889,7 +1889,7 @@ static void v9fs_readdir(void *opaque)
retval = -EINVAL;
goto out_nofid;
}
- if (!fidp->fs.dir) {
+ if (!fidp->fs.dir.stream) {
retval = -EINVAL;
goto out;
}
diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h
index f5a7387798..c0ce0e33c2 100644
--- a/hw/9pfs/9p.h
+++ b/hw/9pfs/9p.h
@@ -171,13 +171,17 @@ typedef struct V9fsXattr
int flags;
} V9fsXattr;
+typedef struct V9fsDir {
+ DIR *stream;
+} V9fsDir;
+
/*
* Filled by fs driver on open and other
* calls.
*/
union V9fsFidOpenState {
int fd;
- DIR *dir;
+ V9fsDir dir;
V9fsXattr xattr;
/*
* private pointer for fs drivers, that