Skip to content

Commit

Permalink
9pfs: fix integer overflow issue in xattr read/write
Browse files Browse the repository at this point in the history
The v9fs_xattr_read() and v9fs_xattr_write() are passed a guest
originated offset: they must ensure this offset does not go beyond
the size of the extended attribute that was set in v9fs_xattrcreate().
Unfortunately, the current code implement these checks with unsafe
calculations on 32 and 64 bit values, which may allow a malicious
guest to cause OOB access anyway.

Fix this by comparing the offset and the xattr size, which are
both uint64_t, before trying to compute the effective number of bytes
to read or write.

Suggested-by: Greg Kurz <groug@kaod.org>
Signed-off-by: Li Qiang <liqiang6-s@360.cn>
Reviewed-by: Greg Kurz <groug@kaod.org>
Reviewed-By: Guido Günther <agx@sigxcpu.org>
Signed-off-by: Greg Kurz <groug@kaod.org>
  • Loading branch information
Li Qiang authored and gkurz committed Nov 1, 2016
1 parent 8495f9a commit 7e55d65
Showing 1 changed file with 12 additions and 20 deletions.
32 changes: 12 additions & 20 deletions hw/9pfs/9p.c
Expand Up @@ -1637,20 +1637,17 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
{
ssize_t err;
size_t offset = 7;
int read_count;
int64_t xattr_len;
uint64_t read_count;
V9fsVirtioState *v = container_of(s, V9fsVirtioState, state);
VirtQueueElement *elem = v->elems[pdu->idx];

xattr_len = fidp->fs.xattr.len;
read_count = xattr_len - off;
if (fidp->fs.xattr.len < off) {
read_count = 0;
} else {
read_count = fidp->fs.xattr.len - off;
}
if (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);
if (err < 0) {
Expand Down Expand Up @@ -1979,23 +1976,18 @@ static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp,
{
int i, to_copy;
ssize_t err = 0;
int write_count;
int64_t xattr_len;
uint64_t write_count;
size_t offset = 7;


xattr_len = fidp->fs.xattr.len;
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
*/
if (fidp->fs.xattr.len < off) {
err = -ENOSPC;
goto out;
}
write_count = fidp->fs.xattr.len - off;
if (write_count > count) {
write_count = count;
}
err = pdu_marshal(pdu, offset, "d", write_count);
if (err < 0) {
return err;
Expand Down

0 comments on commit 7e55d65

Please sign in to comment.