]>
Commit | Line | Data |
---|---|---|
95259824 WB |
1 | From 86a37b0a0ed8f32db819782ca4a367712ece1453 Mon Sep 17 00:00:00 2001 |
2 | From: Li Qiang <liqiang6-s@360.cn> | |
3 | Date: Tue, 1 Nov 2016 12:00:40 +0100 | |
4 | Subject: [PATCH 8/8] 9pfs: fix integer overflow issue in xattr read/write | |
5 | MIME-Version: 1.0 | |
6 | Content-Type: text/plain; charset=UTF-8 | |
7 | Content-Transfer-Encoding: 8bit | |
8 | ||
9 | The v9fs_xattr_read() and v9fs_xattr_write() are passed a guest | |
10 | originated offset: they must ensure this offset does not go beyond | |
11 | the size of the extended attribute that was set in v9fs_xattrcreate(). | |
12 | Unfortunately, the current code implement these checks with unsafe | |
13 | calculations on 32 and 64 bit values, which may allow a malicious | |
14 | guest to cause OOB access anyway. | |
15 | ||
16 | Fix this by comparing the offset and the xattr size, which are | |
17 | both uint64_t, before trying to compute the effective number of bytes | |
18 | to read or write. | |
19 | ||
20 | Suggested-by: Greg Kurz <groug@kaod.org> | |
21 | Signed-off-by: Li Qiang <liqiang6-s@360.cn> | |
22 | Reviewed-by: Greg Kurz <groug@kaod.org> | |
23 | Reviewed-By: Guido Günther <agx@sigxcpu.org> | |
24 | Signed-off-by: Greg Kurz <groug@kaod.org> | |
25 | --- | |
26 | hw/9pfs/9p.c | 32 ++++++++++++-------------------- | |
27 | 1 file changed, 12 insertions(+), 20 deletions(-) | |
28 | ||
29 | diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c | |
30 | index af07846..fc4f2cd 100644 | |
31 | --- a/hw/9pfs/9p.c | |
32 | +++ b/hw/9pfs/9p.c | |
33 | @@ -1628,20 +1628,17 @@ static int v9fs_xattr_read(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, | |
34 | { | |
35 | ssize_t err; | |
36 | size_t offset = 7; | |
37 | - int read_count; | |
38 | - int64_t xattr_len; | |
39 | + uint64_t read_count; | |
40 | V9fsVirtioState *v = container_of(s, V9fsVirtioState, state); | |
41 | VirtQueueElement *elem = v->elems[pdu->idx]; | |
42 | ||
43 | - xattr_len = fidp->fs.xattr.len; | |
44 | - read_count = xattr_len - off; | |
45 | + if (fidp->fs.xattr.len < off) { | |
46 | + read_count = 0; | |
47 | + } else { | |
48 | + read_count = fidp->fs.xattr.len - off; | |
49 | + } | |
50 | if (read_count > max_count) { | |
51 | read_count = max_count; | |
52 | - } else if (read_count < 0) { | |
53 | - /* | |
54 | - * read beyond XATTR value | |
55 | - */ | |
56 | - read_count = 0; | |
57 | } | |
58 | err = pdu_marshal(pdu, offset, "d", read_count); | |
59 | if (err < 0) { | |
60 | @@ -1969,23 +1966,18 @@ static int v9fs_xattr_write(V9fsState *s, V9fsPDU *pdu, V9fsFidState *fidp, | |
61 | { | |
62 | int i, to_copy; | |
63 | ssize_t err = 0; | |
64 | - int write_count; | |
65 | - int64_t xattr_len; | |
66 | + uint64_t write_count; | |
67 | size_t offset = 7; | |
68 | ||
69 | ||
70 | - xattr_len = fidp->fs.xattr.len; | |
71 | - write_count = xattr_len - off; | |
72 | - if (write_count > count) { | |
73 | - write_count = count; | |
74 | - } else if (write_count < 0) { | |
75 | - /* | |
76 | - * write beyond XATTR value len specified in | |
77 | - * xattrcreate | |
78 | - */ | |
79 | + if (fidp->fs.xattr.len < off) { | |
80 | err = -ENOSPC; | |
81 | goto out; | |
82 | } | |
83 | + write_count = fidp->fs.xattr.len - off; | |
84 | + if (write_count > count) { | |
85 | + write_count = count; | |
86 | + } | |
87 | err = pdu_marshal(pdu, offset, "d", write_count); | |
88 | if (err < 0) { | |
89 | return err; | |
90 | -- | |
91 | 2.1.4 | |
92 |