This pull request mostly contains some more fixes to prevent buggy guests from
breaking QEMU. -----BEGIN PGP SIGNATURE----- iEYEABECAAYFAlgYe/IACgkQAvw66wEB28KKBwCfQqbDrsJrP321utoF1F5C7dWl ENsAoKOVLRq8VEv3fI50dPx2JsMiqlBx =M7GK -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/gkurz/tags/for-upstream' into staging This pull request mostly contains some more fixes to prevent buggy guests from breaking QEMU. # gpg: Signature made Tue 01 Nov 2016 11:26:42 GMT # gpg: using DSA key 0x02FC3AEB0101DBC2 # gpg: Good signature from "Greg Kurz <groug@kaod.org>" # gpg: aka "Greg Kurz <groug@free.fr>" # gpg: aka "Greg Kurz <gkurz@fr.ibm.com>" # gpg: aka "Greg Kurz <gkurz@linux.vnet.ibm.com>" # gpg: aka "Gregory Kurz (Groug) <groug@free.fr>" # gpg: aka "Gregory Kurz (Cimai Technology) <gkurz@cimai.com>" # gpg: aka "Gregory Kurz (Meiosys Technology) <gkurz@meiosys.com>" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 2BD4 3B44 535E C0A7 9894 DBA2 02FC 3AEB 0101 DBC2 * remotes/gkurz/tags/for-upstream: 9pfs: drop excessive error message from virtfs_reset() 9pfs: don't BUG_ON() if fid is already opened 9pfs: xattrcreate requires non-opened fids 9pfs: limit xattr size in xattrcreate 9pfs: fix integer overflow issue in xattr read/write 9pfs: convert 'len/copied_len' field in V9fsXattr to the type of uint64_t 9pfs: add xattrwalk_fid field in V9fsXattr struct Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
39542105bb
80
hw/9pfs/9p.c
80
hw/9pfs/9p.c
@ -325,7 +325,7 @@ static int coroutine_fn v9fs_xattr_fid_clunk(V9fsPDU *pdu, V9fsFidState *fidp)
|
|||||||
{
|
{
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
if (fidp->fs.xattr.copied_len == -1) {
|
if (fidp->fs.xattr.xattrwalk_fid) {
|
||||||
/* getxattr/listxattr fid */
|
/* getxattr/listxattr fid */
|
||||||
goto free_value;
|
goto free_value;
|
||||||
}
|
}
|
||||||
@ -535,7 +535,7 @@ static int coroutine_fn v9fs_mark_fids_unreclaim(V9fsPDU *pdu, V9fsPath *path)
|
|||||||
static void coroutine_fn virtfs_reset(V9fsPDU *pdu)
|
static void coroutine_fn virtfs_reset(V9fsPDU *pdu)
|
||||||
{
|
{
|
||||||
V9fsState *s = pdu->s;
|
V9fsState *s = pdu->s;
|
||||||
V9fsFidState *fidp = NULL;
|
V9fsFidState *fidp;
|
||||||
|
|
||||||
/* Free all fids */
|
/* Free all fids */
|
||||||
while (s->fid_list) {
|
while (s->fid_list) {
|
||||||
@ -548,11 +548,6 @@ static void coroutine_fn virtfs_reset(V9fsPDU *pdu)
|
|||||||
free_fid(pdu, fidp);
|
free_fid(pdu, fidp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (fidp) {
|
|
||||||
/* One or more unclunked fids found... */
|
|
||||||
error_report("9pfs:%s: One or more uncluncked fids "
|
|
||||||
"found during reset", __func__);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define P9_QID_TYPE_DIR 0x80
|
#define P9_QID_TYPE_DIR 0x80
|
||||||
@ -1361,7 +1356,10 @@ static void coroutine_fn v9fs_walk(void *opaque)
|
|||||||
memcpy(&qids[name_idx], &qid, sizeof(qid));
|
memcpy(&qids[name_idx], &qid, sizeof(qid));
|
||||||
}
|
}
|
||||||
if (fid == newfid) {
|
if (fid == newfid) {
|
||||||
BUG_ON(fidp->fid_type != P9_FID_NONE);
|
if (fidp->fid_type != P9_FID_NONE) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
v9fs_path_copy(&fidp->path, &path);
|
v9fs_path_copy(&fidp->path, &path);
|
||||||
} else {
|
} else {
|
||||||
newfidp = alloc_fid(s, newfid);
|
newfidp = alloc_fid(s, newfid);
|
||||||
@ -1443,7 +1441,10 @@ static void coroutine_fn v9fs_open(void *opaque)
|
|||||||
err = -ENOENT;
|
err = -ENOENT;
|
||||||
goto out_nofid;
|
goto out_nofid;
|
||||||
}
|
}
|
||||||
BUG_ON(fidp->fid_type != P9_FID_NONE);
|
if (fidp->fid_type != P9_FID_NONE) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
err = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
|
err = v9fs_co_lstat(pdu, &fidp->path, &stbuf);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
@ -1637,20 +1638,17 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
|
|||||||
{
|
{
|
||||||
ssize_t err;
|
ssize_t err;
|
||||||
size_t offset = 7;
|
size_t offset = 7;
|
||||||
int read_count;
|
uint64_t read_count;
|
||||||
int64_t xattr_len;
|
|
||||||
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
|
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
|
||||||
VirtQueueElement *elem = v->elems[pdu->idx];
|
VirtQueueElement *elem = v->elems[pdu->idx];
|
||||||
|
|
||||||
xattr_len = fidp->fs.xattr.len;
|
if (fidp->fs.xattr.len < off) {
|
||||||
read_count = xattr_len - off;
|
read_count = 0;
|
||||||
|
} else {
|
||||||
|
read_count = fidp->fs.xattr.len - off;
|
||||||
|
}
|
||||||
if (read_count > max_count) {
|
if (read_count > max_count) {
|
||||||
read_count = max_count;
|
read_count = max_count;
|
||||||
} else if (read_count < 0) {
|
|
||||||
/*
|
|
||||||
* read beyond XATTR value
|
|
||||||
*/
|
|
||||||
read_count = 0;
|
|
||||||
}
|
}
|
||||||
err = pdu_marshal(pdu, offset, "d", read_count);
|
err = pdu_marshal(pdu, offset, "d", read_count);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
@ -1979,23 +1977,18 @@ static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
|
|||||||
{
|
{
|
||||||
int i, to_copy;
|
int i, to_copy;
|
||||||
ssize_t err = 0;
|
ssize_t err = 0;
|
||||||
int write_count;
|
uint64_t write_count;
|
||||||
int64_t xattr_len;
|
|
||||||
size_t offset = 7;
|
size_t offset = 7;
|
||||||
|
|
||||||
|
|
||||||
xattr_len = fidp->fs.xattr.len;
|
if (fidp->fs.xattr.len < off) {
|
||||||
write_count = xattr_len - off;
|
|
||||||
if (write_count > count) {
|
|
||||||
write_count = count;
|
|
||||||
} else if (write_count < 0) {
|
|
||||||
/*
|
|
||||||
* write beyond XATTR value len specified in
|
|
||||||
* xattrcreate
|
|
||||||
*/
|
|
||||||
err = -ENOSPC;
|
err = -ENOSPC;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
write_count = fidp->fs.xattr.len - off;
|
||||||
|
if (write_count > count) {
|
||||||
|
write_count = count;
|
||||||
|
}
|
||||||
err = pdu_marshal(pdu, offset, "d", write_count);
|
err = pdu_marshal(pdu, offset, "d", write_count);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
return err;
|
return err;
|
||||||
@ -2548,7 +2541,10 @@ static int coroutine_fn v9fs_complete_rename(V9fsPDU *pdu, V9fsFidState *fidp,
|
|||||||
err = -ENOENT;
|
err = -ENOENT;
|
||||||
goto out_nofid;
|
goto out_nofid;
|
||||||
}
|
}
|
||||||
BUG_ON(dirfidp->fid_type != P9_FID_NONE);
|
if (fidp->fid_type != P9_FID_NONE) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
v9fs_co_name_to_path(pdu, &dirfidp->path, name->data, &new_path);
|
v9fs_co_name_to_path(pdu, &dirfidp->path, name->data, &new_path);
|
||||||
} else {
|
} else {
|
||||||
old_name = fidp->path.data;
|
old_name = fidp->path.data;
|
||||||
@ -2620,7 +2616,10 @@ static void coroutine_fn v9fs_rename(void *opaque)
|
|||||||
err = -ENOENT;
|
err = -ENOENT;
|
||||||
goto out_nofid;
|
goto out_nofid;
|
||||||
}
|
}
|
||||||
BUG_ON(fidp->fid_type != P9_FID_NONE);
|
if (fidp->fid_type != P9_FID_NONE) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
/* if fs driver is not path based, return EOPNOTSUPP */
|
/* if fs driver is not path based, return EOPNOTSUPP */
|
||||||
if (!(pdu->s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT)) {
|
if (!(pdu->s->ctx.export_flags & V9FS_PATHNAME_FSCONTEXT)) {
|
||||||
err = -EOPNOTSUPP;
|
err = -EOPNOTSUPP;
|
||||||
@ -3190,7 +3189,7 @@ static void coroutine_fn v9fs_xattrwalk(void *opaque)
|
|||||||
*/
|
*/
|
||||||
xattr_fidp->fs.xattr.len = size;
|
xattr_fidp->fs.xattr.len = size;
|
||||||
xattr_fidp->fid_type = P9_FID_XATTR;
|
xattr_fidp->fid_type = P9_FID_XATTR;
|
||||||
xattr_fidp->fs.xattr.copied_len = -1;
|
xattr_fidp->fs.xattr.xattrwalk_fid = true;
|
||||||
if (size) {
|
if (size) {
|
||||||
xattr_fidp->fs.xattr.value = g_malloc(size);
|
xattr_fidp->fs.xattr.value = g_malloc(size);
|
||||||
err = v9fs_co_llistxattr(pdu, &xattr_fidp->path,
|
err = v9fs_co_llistxattr(pdu, &xattr_fidp->path,
|
||||||
@ -3223,7 +3222,7 @@ static void coroutine_fn v9fs_xattrwalk(void *opaque)
|
|||||||
*/
|
*/
|
||||||
xattr_fidp->fs.xattr.len = size;
|
xattr_fidp->fs.xattr.len = size;
|
||||||
xattr_fidp->fid_type = P9_FID_XATTR;
|
xattr_fidp->fid_type = P9_FID_XATTR;
|
||||||
xattr_fidp->fs.xattr.copied_len = -1;
|
xattr_fidp->fs.xattr.xattrwalk_fid = true;
|
||||||
if (size) {
|
if (size) {
|
||||||
xattr_fidp->fs.xattr.value = g_malloc(size);
|
xattr_fidp->fs.xattr.value = g_malloc(size);
|
||||||
err = v9fs_co_lgetxattr(pdu, &xattr_fidp->path,
|
err = v9fs_co_lgetxattr(pdu, &xattr_fidp->path,
|
||||||
@ -3255,7 +3254,7 @@ static void coroutine_fn v9fs_xattrcreate(void *opaque)
|
|||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
int32_t fid;
|
int32_t fid;
|
||||||
int64_t size;
|
uint64_t size;
|
||||||
ssize_t err = 0;
|
ssize_t err = 0;
|
||||||
V9fsString name;
|
V9fsString name;
|
||||||
size_t offset = 7;
|
size_t offset = 7;
|
||||||
@ -3270,22 +3269,33 @@ static void coroutine_fn v9fs_xattrcreate(void *opaque)
|
|||||||
}
|
}
|
||||||
trace_v9fs_xattrcreate(pdu->tag, pdu->id, fid, name.data, size, flags);
|
trace_v9fs_xattrcreate(pdu->tag, pdu->id, fid, name.data, size, flags);
|
||||||
|
|
||||||
|
if (size > XATTR_SIZE_MAX) {
|
||||||
|
err = -E2BIG;
|
||||||
|
goto out_nofid;
|
||||||
|
}
|
||||||
|
|
||||||
file_fidp = get_fid(pdu, fid);
|
file_fidp = get_fid(pdu, fid);
|
||||||
if (file_fidp == NULL) {
|
if (file_fidp == NULL) {
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
goto out_nofid;
|
goto out_nofid;
|
||||||
}
|
}
|
||||||
|
if (file_fidp->fid_type != P9_FID_NONE) {
|
||||||
|
err = -EINVAL;
|
||||||
|
goto out_put_fid;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make the file fid point to xattr */
|
/* Make the file fid point to xattr */
|
||||||
xattr_fidp = file_fidp;
|
xattr_fidp = file_fidp;
|
||||||
xattr_fidp->fid_type = P9_FID_XATTR;
|
xattr_fidp->fid_type = P9_FID_XATTR;
|
||||||
xattr_fidp->fs.xattr.copied_len = 0;
|
xattr_fidp->fs.xattr.copied_len = 0;
|
||||||
|
xattr_fidp->fs.xattr.xattrwalk_fid = false;
|
||||||
xattr_fidp->fs.xattr.len = size;
|
xattr_fidp->fs.xattr.len = size;
|
||||||
xattr_fidp->fs.xattr.flags = flags;
|
xattr_fidp->fs.xattr.flags = flags;
|
||||||
v9fs_string_init(&xattr_fidp->fs.xattr.name);
|
v9fs_string_init(&xattr_fidp->fs.xattr.name);
|
||||||
v9fs_string_copy(&xattr_fidp->fs.xattr.name, &name);
|
v9fs_string_copy(&xattr_fidp->fs.xattr.name, &name);
|
||||||
g_free(xattr_fidp->fs.xattr.value);
|
|
||||||
xattr_fidp->fs.xattr.value = g_malloc0(size);
|
xattr_fidp->fs.xattr.value = g_malloc0(size);
|
||||||
err = offset;
|
err = offset;
|
||||||
|
out_put_fid:
|
||||||
put_fid(pdu, file_fidp);
|
put_fid(pdu, file_fidp);
|
||||||
out_nofid:
|
out_nofid:
|
||||||
pdu_complete(pdu, err);
|
pdu_complete(pdu, err);
|
||||||
|
@ -159,11 +159,12 @@ typedef struct V9fsConf
|
|||||||
|
|
||||||
typedef struct V9fsXattr
|
typedef struct V9fsXattr
|
||||||
{
|
{
|
||||||
int64_t copied_len;
|
uint64_t copied_len;
|
||||||
int64_t len;
|
uint64_t len;
|
||||||
void *value;
|
void *value;
|
||||||
V9fsString name;
|
V9fsString name;
|
||||||
int flags;
|
int flags;
|
||||||
|
bool xattrwalk_fid;
|
||||||
} V9fsXattr;
|
} V9fsXattr;
|
||||||
|
|
||||||
typedef struct V9fsDir {
|
typedef struct V9fsDir {
|
||||||
|
@ -42,6 +42,6 @@ v9fs_mkdir(uint16_t tag, uint8_t id, int32_t fid, char* name, int mode, uint32_t
|
|||||||
v9fs_mkdir_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int err) "tag %u id %u qid={type %d version %d path %"PRId64"} err %d"
|
v9fs_mkdir_return(uint16_t tag, uint8_t id, int8_t type, int32_t version, int64_t path, int err) "tag %u id %u qid={type %d version %d path %"PRId64"} err %d"
|
||||||
v9fs_xattrwalk(uint16_t tag, uint8_t id, int32_t fid, int32_t newfid, char* name) "tag %d id %d fid %d newfid %d name %s"
|
v9fs_xattrwalk(uint16_t tag, uint8_t id, int32_t fid, int32_t newfid, char* name) "tag %d id %d fid %d newfid %d name %s"
|
||||||
v9fs_xattrwalk_return(uint16_t tag, uint8_t id, int64_t size) "tag %d id %d size %"PRId64
|
v9fs_xattrwalk_return(uint16_t tag, uint8_t id, int64_t size) "tag %d id %d size %"PRId64
|
||||||
v9fs_xattrcreate(uint16_t tag, uint8_t id, int32_t fid, char* name, int64_t size, int flags) "tag %d id %d fid %d name %s size %"PRId64" flags %d"
|
v9fs_xattrcreate(uint16_t tag, uint8_t id, int32_t fid, char* name, uint64_t size, int flags) "tag %d id %d fid %d name %s size %"PRIu64" flags %d"
|
||||||
v9fs_readlink(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
|
v9fs_readlink(uint16_t tag, uint8_t id, int32_t fid) "tag %d id %d fid %d"
|
||||||
v9fs_readlink_return(uint16_t tag, uint8_t id, char* target) "tag %d id %d name %s"
|
v9fs_readlink_return(uint16_t tag, uint8_t id, char* target) "tag %d id %d name %s"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user