From 5876fb659bca3bd47efb3bc717125dd3560dac1c Mon Sep 17 00:00:00 2001 From: Wolfgang Bumiller Date: Wed, 7 Sep 2016 11:58:00 +0200 Subject: [PATCH] various CVE fixes CVE-2016-7116: 9pfs: forbid illegal path names 9pfs: forbid . and .. in file names 9pfs: handle walk of ".." in the root directory CVE-2016-7155: scsi: check page count while initialising descriptor rings CVE-2016-7156: scsi: pvscsi: avoid infinite loop while building SG list CVE-2016-7157: scsi: mptconfig: fix an assert expression --- .../0001-9pfs-forbid-illegal-path-names.patch | 178 +++++++++++++++++++++ .../0002-9pfs-forbid-.-and-.-in-file-names.patch | 159 ++++++++++++++++++ ...fs-handle-walk-of-.-in-the-root-directory.patch | 126 +++++++++++++++ ...page-count-while-initialising-descriptor-.patch | 83 ++++++++++ ...-avoid-infinite-loop-while-building-SG-li.patch | 63 ++++++++ ...7-scsi-mptconfig-fix-an-assert-expression.patch | 35 ++++ debian/patches/series | 6 + 7 files changed, 650 insertions(+) create mode 100644 debian/patches/extra/0001-9pfs-forbid-illegal-path-names.patch create mode 100644 debian/patches/extra/0002-9pfs-forbid-.-and-.-in-file-names.patch create mode 100644 debian/patches/extra/0003-9pfs-handle-walk-of-.-in-the-root-directory.patch create mode 100644 debian/patches/extra/CVE-2016-7155-scsi-check-page-count-while-initialising-descriptor-.patch create mode 100644 debian/patches/extra/CVE-2016-7156-scsi-pvscsi-avoid-infinite-loop-while-building-SG-li.patch create mode 100644 debian/patches/extra/CVE-2016-7157-scsi-mptconfig-fix-an-assert-expression.patch diff --git a/debian/patches/extra/0001-9pfs-forbid-illegal-path-names.patch b/debian/patches/extra/0001-9pfs-forbid-illegal-path-names.patch new file mode 100644 index 0000000..15d3119 --- /dev/null +++ b/debian/patches/extra/0001-9pfs-forbid-illegal-path-names.patch @@ -0,0 +1,178 @@ +From 21289fc663198d96ae2ca145a425f2e21ed4637a Mon Sep 17 00:00:00 2001 +From: Greg Kurz +Date: Tue, 30 Aug 2016 19:11:05 +0200 +Subject: [PATCH 1/6] 9pfs: forbid illegal path names + +Empty path components don't make sense for most commands and may cause +undefined behavior, depending on the backend. + +Also, the walk request described in the 9P spec [1] clearly shows that +the client is supposed to send individual path components: the official +linux client never sends portions of path containing the / character for +example. + +Moreover, the 9P spec [2] also states that a system can decide to restrict +the set of supported characters used in path components, with an explicit +mention "to remove slashes from name components". + +This patch introduces a new name_is_illegal() helper that checks the +names sent by the client are not empty and don't contain unwanted chars. +Since 9pfs is only supported on linux hosts, only the / character is +checked at the moment. When support for other hosts (AKA. win32) is added, +other chars may need to be blacklisted as well. + +If a client sends an illegal path component, the request will fail and +ENOENT is returned to the client. + +[1] http://man.cat-v.org/plan_9/5/walk +[2] http://man.cat-v.org/plan_9/5/intro + +Suggested-by: Peter Maydell +Signed-off-by: Greg Kurz +Reviewed-by: Eric Blake +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Peter Maydell +--- + hw/9pfs/9p.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 56 insertions(+) + +diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c +index f5e3012..53c466b 100644 +--- a/hw/9pfs/9p.c ++++ b/hw/9pfs/9p.c +@@ -1254,6 +1254,11 @@ static int v9fs_walk_marshal(V9fsPDU *pdu, uint16_t nwnames, V9fsQID *qids) + return offset; + } + ++static bool name_is_illegal(const char *name) ++{ ++ return !*name || strchr(name, '/') != NULL; ++} ++ + static void v9fs_walk(void *opaque) + { + int name_idx; +@@ -1287,6 +1292,10 @@ static void v9fs_walk(void *opaque) + if (err < 0) { + goto out_nofid; + } ++ if (name_is_illegal(wnames[i].data)) { ++ err = -ENOENT; ++ goto out_nofid; ++ } + offset += err; + } + } else if (nwnames > P9_MAXWELEM) { +@@ -1481,6 +1490,11 @@ static void v9fs_lcreate(void *opaque) + } + trace_v9fs_lcreate(pdu->tag, pdu->id, dfid, flags, mode, gid); + ++ if (name_is_illegal(name.data)) { ++ err = -ENOENT; ++ goto out_nofid; ++ } ++ + fidp = get_fid(pdu, dfid); + if (fidp == NULL) { + err = -ENOENT; +@@ -2066,6 +2080,11 @@ static void v9fs_create(void *opaque) + } + trace_v9fs_create(pdu->tag, pdu->id, fid, name.data, perm, mode); + ++ if (name_is_illegal(name.data)) { ++ err = -ENOENT; ++ goto out_nofid; ++ } ++ + fidp = get_fid(pdu, fid); + if (fidp == NULL) { + err = -EINVAL; +@@ -2231,6 +2250,11 @@ static void v9fs_symlink(void *opaque) + } + trace_v9fs_symlink(pdu->tag, pdu->id, dfid, name.data, symname.data, gid); + ++ if (name_is_illegal(name.data)) { ++ err = -ENOENT; ++ goto out_nofid; ++ } ++ + dfidp = get_fid(pdu, dfid); + if (dfidp == NULL) { + err = -EINVAL; +@@ -2305,6 +2329,11 @@ static void v9fs_link(void *opaque) + } + trace_v9fs_link(pdu->tag, pdu->id, dfid, oldfid, name.data); + ++ if (name_is_illegal(name.data)) { ++ err = -ENOENT; ++ goto out_nofid; ++ } ++ + dfidp = get_fid(pdu, dfid); + if (dfidp == NULL) { + err = -ENOENT; +@@ -2387,6 +2416,12 @@ static void v9fs_unlinkat(void *opaque) + if (err < 0) { + goto out_nofid; + } ++ ++ if (name_is_illegal(name.data)) { ++ err = -ENOENT; ++ goto out_nofid; ++ } ++ + dfidp = get_fid(pdu, dfid); + if (dfidp == NULL) { + err = -EINVAL; +@@ -2493,6 +2528,12 @@ static void v9fs_rename(void *opaque) + if (err < 0) { + goto out_nofid; + } ++ ++ if (name_is_illegal(name.data)) { ++ err = -ENOENT; ++ goto out_nofid; ++ } ++ + fidp = get_fid(pdu, fid); + if (fidp == NULL) { + err = -ENOENT; +@@ -2605,6 +2646,11 @@ static void v9fs_renameat(void *opaque) + goto out_err; + } + ++ if (name_is_illegal(old_name.data) || name_is_illegal(new_name.data)) { ++ err = -ENOENT; ++ goto out_err; ++ } ++ + v9fs_path_write_lock(s); + err = v9fs_complete_renameat(pdu, olddirfid, + &old_name, newdirfid, &new_name); +@@ -2815,6 +2861,11 @@ static void v9fs_mknod(void *opaque) + } + trace_v9fs_mknod(pdu->tag, pdu->id, fid, mode, major, minor); + ++ if (name_is_illegal(name.data)) { ++ err = -ENOENT; ++ goto out_nofid; ++ } ++ + fidp = get_fid(pdu, fid); + if (fidp == NULL) { + err = -ENOENT; +@@ -2966,6 +3017,11 @@ static void v9fs_mkdir(void *opaque) + } + trace_v9fs_mkdir(pdu->tag, pdu->id, fid, name.data, mode, gid); + ++ if (name_is_illegal(name.data)) { ++ err = -ENOENT; ++ goto out_nofid; ++ } ++ + fidp = get_fid(pdu, fid); + if (fidp == NULL) { + err = -ENOENT; +-- +2.1.4 + diff --git a/debian/patches/extra/0002-9pfs-forbid-.-and-.-in-file-names.patch b/debian/patches/extra/0002-9pfs-forbid-.-and-.-in-file-names.patch new file mode 100644 index 0000000..c2c0500 --- /dev/null +++ b/debian/patches/extra/0002-9pfs-forbid-.-and-.-in-file-names.patch @@ -0,0 +1,159 @@ +From 3ae00feb459657766ec623de7eae8f014a660ab4 Mon Sep 17 00:00:00 2001 +From: Greg Kurz +Date: Tue, 30 Aug 2016 19:13:11 +0200 +Subject: [PATCH 2/6] 9pfs: forbid . and .. in file names + +According to the 9P spec http://man.cat-v.org/plan_9/5/open about the +create request: + +The names . and .. are special; it is illegal to create files with these +names. + +This patch causes the create and lcreate requests to fail with EINVAL if +the file name is either "." or "..". + +Even if it isn't explicitly written in the spec, this patch extends the +checking to all requests that may cause a directory entry to be created: + + - mknod + - rename + - renameat + - mkdir + - link + - symlink + +The unlinkat request also gets patched for consistency (even if +rmdir("foo/..") is expected to fail according to POSIX.1-2001). + +The various error values come from the linux manual pages. + +Suggested-by: Peter Maydell +Signed-off-by: Greg Kurz +Reviewed-by: Eric Blake +Reviewed-by: Michael S. Tsirkin +Signed-off-by: Peter Maydell +--- + hw/9pfs/9p.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 51 insertions(+) + +diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c +index 53c466b..1e96427 100644 +--- a/hw/9pfs/9p.c ++++ b/hw/9pfs/9p.c +@@ -1495,6 +1495,11 @@ static void v9fs_lcreate(void *opaque) + goto out_nofid; + } + ++ if (!strcmp(".", name.data) || !strcmp("..", name.data)) { ++ err = -EEXIST; ++ goto out_nofid; ++ } ++ + fidp = get_fid(pdu, dfid); + if (fidp == NULL) { + err = -ENOENT; +@@ -2085,6 +2090,11 @@ static void v9fs_create(void *opaque) + goto out_nofid; + } + ++ if (!strcmp(".", name.data) || !strcmp("..", name.data)) { ++ err = -EEXIST; ++ goto out_nofid; ++ } ++ + fidp = get_fid(pdu, fid); + if (fidp == NULL) { + err = -EINVAL; +@@ -2255,6 +2265,11 @@ static void v9fs_symlink(void *opaque) + goto out_nofid; + } + ++ if (!strcmp(".", name.data) || !strcmp("..", name.data)) { ++ err = -EEXIST; ++ goto out_nofid; ++ } ++ + dfidp = get_fid(pdu, dfid); + if (dfidp == NULL) { + err = -EINVAL; +@@ -2334,6 +2349,11 @@ static void v9fs_link(void *opaque) + goto out_nofid; + } + ++ if (!strcmp(".", name.data) || !strcmp("..", name.data)) { ++ err = -EEXIST; ++ goto out_nofid; ++ } ++ + dfidp = get_fid(pdu, dfid); + if (dfidp == NULL) { + err = -ENOENT; +@@ -2422,6 +2442,16 @@ static void v9fs_unlinkat(void *opaque) + goto out_nofid; + } + ++ if (!strcmp(".", name.data)) { ++ err = -EINVAL; ++ goto out_nofid; ++ } ++ ++ if (!strcmp("..", name.data)) { ++ err = -ENOTEMPTY; ++ goto out_nofid; ++ } ++ + dfidp = get_fid(pdu, dfid); + if (dfidp == NULL) { + err = -EINVAL; +@@ -2534,6 +2564,11 @@ static void v9fs_rename(void *opaque) + goto out_nofid; + } + ++ if (!strcmp(".", name.data) || !strcmp("..", name.data)) { ++ err = -EISDIR; ++ goto out_nofid; ++ } ++ + fidp = get_fid(pdu, fid); + if (fidp == NULL) { + err = -ENOENT; +@@ -2651,6 +2686,12 @@ static void v9fs_renameat(void *opaque) + goto out_err; + } + ++ if (!strcmp(".", old_name.data) || !strcmp("..", old_name.data) || ++ !strcmp(".", new_name.data) || !strcmp("..", new_name.data)) { ++ err = -EISDIR; ++ goto out_err; ++ } ++ + v9fs_path_write_lock(s); + err = v9fs_complete_renameat(pdu, olddirfid, + &old_name, newdirfid, &new_name); +@@ -2866,6 +2907,11 @@ static void v9fs_mknod(void *opaque) + goto out_nofid; + } + ++ if (!strcmp(".", name.data) || !strcmp("..", name.data)) { ++ err = -EEXIST; ++ goto out_nofid; ++ } ++ + fidp = get_fid(pdu, fid); + if (fidp == NULL) { + err = -ENOENT; +@@ -3022,6 +3068,11 @@ static void v9fs_mkdir(void *opaque) + goto out_nofid; + } + ++ if (!strcmp(".", name.data) || !strcmp("..", name.data)) { ++ err = -EEXIST; ++ goto out_nofid; ++ } ++ + fidp = get_fid(pdu, fid); + if (fidp == NULL) { + err = -ENOENT; +-- +2.1.4 + diff --git a/debian/patches/extra/0003-9pfs-handle-walk-of-.-in-the-root-directory.patch b/debian/patches/extra/0003-9pfs-handle-walk-of-.-in-the-root-directory.patch new file mode 100644 index 0000000..d4f22c2 --- /dev/null +++ b/debian/patches/extra/0003-9pfs-handle-walk-of-.-in-the-root-directory.patch @@ -0,0 +1,126 @@ +From 348503ea115b336343166b87271208ffc0bdeb0a Mon Sep 17 00:00:00 2001 +From: Greg Kurz +Date: Tue, 30 Aug 2016 17:02:27 +0200 +Subject: [PATCH 3/6] 9pfs: handle walk of ".." in the root directory + +The 9P spec at http://man.cat-v.org/plan_9/5/intro says: + +All directories must support walks to the directory .. (dot-dot) meaning +parent directory, although by convention directories contain no explicit +entry for .. or . (dot). The parent of the root directory of a server's +tree is itself. + +This means that a client cannot walk further than the root directory +exported by the server. In other words, if the client wants to walk +"/.." or "/foo/../..", the server should answer like the request was +to walk "/". + +This patch just does that: +- we cache the QID of the root directory at attach time +- during the walk we compare the QID of each path component with the root + QID to detect if we're in a "/.." situation +- if so, we skip the current component and go to the next one + +Signed-off-by: Greg Kurz +Reviewed-by: Eric Blake +Signed-off-by: Peter Maydell +--- + hw/9pfs/9p.c | 40 +++++++++++++++++++++++++++++++--------- + hw/9pfs/9p.h | 1 + + 2 files changed, 32 insertions(+), 9 deletions(-) + +diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c +index 1e96427..1ac05b2 100644 +--- a/hw/9pfs/9p.c ++++ b/hw/9pfs/9p.c +@@ -1008,6 +1008,7 @@ static void v9fs_attach(void *opaque) + goto out; + } + err += offset; ++ memcpy(&s->root_qid, &qid, sizeof(qid)); + trace_v9fs_attach_return(pdu->tag, pdu->id, + qid.type, qid.version, qid.path); + /* +@@ -1259,6 +1260,14 @@ static bool name_is_illegal(const char *name) + return !*name || strchr(name, '/') != NULL; + } + ++static bool not_same_qid(const V9fsQID *qid1, const V9fsQID *qid2) ++{ ++ return ++ qid1->type != qid2->type || ++ qid1->version != qid2->version || ++ qid1->path != qid2->path; ++} ++ + static void v9fs_walk(void *opaque) + { + int name_idx; +@@ -1274,6 +1283,7 @@ static void v9fs_walk(void *opaque) + V9fsFidState *newfidp = NULL; + V9fsPDU *pdu = opaque; + V9fsState *s = pdu->s; ++ V9fsQID qid; + + err = pdu_unmarshal(pdu, offset, "ddw", &fid, &newfid, &nwnames); + if (err < 0) { +@@ -1307,6 +1317,12 @@ static void v9fs_walk(void *opaque) + err = -ENOENT; + goto out_nofid; + } ++ ++ err = fid_to_qid(pdu, fidp, &qid); ++ if (err < 0) { ++ goto out; ++ } ++ + v9fs_path_init(&dpath); + v9fs_path_init(&path); + /* +@@ -1316,16 +1332,22 @@ static void v9fs_walk(void *opaque) + v9fs_path_copy(&dpath, &fidp->path); + v9fs_path_copy(&path, &fidp->path); + for (name_idx = 0; name_idx < nwnames; name_idx++) { +- err = v9fs_co_name_to_path(pdu, &dpath, wnames[name_idx].data, &path); +- if (err < 0) { +- goto out; +- } +- err = v9fs_co_lstat(pdu, &path, &stbuf); +- if (err < 0) { +- goto out; ++ if (not_same_qid(&pdu->s->root_qid, &qid) || ++ strcmp("..", wnames[name_idx].data)) { ++ err = v9fs_co_name_to_path(pdu, &dpath, wnames[name_idx].data, ++ &path); ++ if (err < 0) { ++ goto out; ++ } ++ ++ err = v9fs_co_lstat(pdu, &path, &stbuf); ++ if (err < 0) { ++ goto out; ++ } ++ stat_to_qid(&stbuf, &qid); ++ v9fs_path_copy(&dpath, &path); + } +- stat_to_qid(&stbuf, &qids[name_idx]); +- v9fs_path_copy(&dpath, &path); ++ memcpy(&qids[name_idx], &qid, sizeof(qid)); + } + if (fid == newfid) { + BUG_ON(fidp->fid_type != P9_FID_NONE); +diff --git a/hw/9pfs/9p.h b/hw/9pfs/9p.h +index 1a19418..589b3a5 100644 +--- a/hw/9pfs/9p.h ++++ b/hw/9pfs/9p.h +@@ -219,6 +219,7 @@ typedef struct V9fsState + int32_t root_fid; + Error *migration_blocker; + V9fsConf fsconf; ++ V9fsQID root_qid; + } V9fsState; + + /* 9p2000.L open flags */ +-- +2.1.4 + diff --git a/debian/patches/extra/CVE-2016-7155-scsi-check-page-count-while-initialising-descriptor-.patch b/debian/patches/extra/CVE-2016-7155-scsi-check-page-count-while-initialising-descriptor-.patch new file mode 100644 index 0000000..54df061 --- /dev/null +++ b/debian/patches/extra/CVE-2016-7155-scsi-check-page-count-while-initialising-descriptor-.patch @@ -0,0 +1,83 @@ +From 7c7e45d2bd1a77fbe89dff83fabf89a46479111f Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit +Date: Thu, 1 Sep 2016 16:30:51 +0530 +Subject: [PATCH 4/6] scsi: check page count while initialising descriptor + rings + +Vmware Paravirtual SCSI emulation uses command descriptors to +process SCSI commands. These descriptors come with their ring +buffers. A guest could set the page count for these rings to +an arbitrary value, leading to infinite loop or OOB access. +Add check to avoid it. + +Reported-by: Tom Victor +Reported-by: Li Qiang +Signed-off-by: Prasad J Pandit +--- + hw/scsi/vmw_pvscsi.c | 19 +++++++++---------- + 1 file changed, 9 insertions(+), 10 deletions(-) + +diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c +index 2d7528d..22f872c 100644 +--- a/hw/scsi/vmw_pvscsi.c ++++ b/hw/scsi/vmw_pvscsi.c +@@ -153,7 +153,7 @@ pvscsi_log2(uint32_t input) + return log; + } + +-static int ++static void + pvscsi_ring_init_data(PVSCSIRingInfo *m, PVSCSICmdDescSetupRings *ri) + { + int i; +@@ -161,10 +161,6 @@ pvscsi_ring_init_data(PVSCSIRingInfo *m, PVSCSICmdDescSetupRings *ri) + uint32_t req_ring_size, cmp_ring_size; + m->rs_pa = ri->ringsStatePPN << VMW_PAGE_SHIFT; + +- if ((ri->reqRingNumPages > PVSCSI_SETUP_RINGS_MAX_NUM_PAGES) +- || (ri->cmpRingNumPages > PVSCSI_SETUP_RINGS_MAX_NUM_PAGES)) { +- return -1; +- } + req_ring_size = ri->reqRingNumPages * PVSCSI_MAX_NUM_REQ_ENTRIES_PER_PAGE; + cmp_ring_size = ri->cmpRingNumPages * PVSCSI_MAX_NUM_CMP_ENTRIES_PER_PAGE; + txr_len_log2 = pvscsi_log2(req_ring_size - 1); +@@ -196,8 +192,6 @@ pvscsi_ring_init_data(PVSCSIRingInfo *m, PVSCSICmdDescSetupRings *ri) + + /* Flush ring state page changes */ + smp_wmb(); +- +- return 0; + } + + static int +@@ -747,7 +741,7 @@ pvscsi_dbg_dump_tx_rings_config(PVSCSICmdDescSetupRings *rc) + + trace_pvscsi_tx_rings_num_pages("Confirm Ring", rc->cmpRingNumPages); + for (i = 0; i < rc->cmpRingNumPages; i++) { +- trace_pvscsi_tx_rings_ppn("Confirm Ring", rc->reqRingPPNs[i]); ++ trace_pvscsi_tx_rings_ppn("Confirm Ring", rc->cmpRingPPNs[i]); + } + } + +@@ -780,11 +774,16 @@ pvscsi_on_cmd_setup_rings(PVSCSIState *s) + + trace_pvscsi_on_cmd_arrived("PVSCSI_CMD_SETUP_RINGS"); + +- pvscsi_dbg_dump_tx_rings_config(rc); +- if (pvscsi_ring_init_data(&s->rings, rc) < 0) { ++ if (!rc->reqRingNumPages ++ || rc->reqRingNumPages > PVSCSI_SETUP_RINGS_MAX_NUM_PAGES ++ || !rc->cmpRingNumPages ++ || rc->cmpRingNumPages > PVSCSI_SETUP_RINGS_MAX_NUM_PAGES) { + return PVSCSI_COMMAND_PROCESSING_FAILED; + } + ++ pvscsi_dbg_dump_tx_rings_config(rc); ++ pvscsi_ring_init_data(&s->rings, rc); ++ + s->rings_info_valid = TRUE; + return PVSCSI_COMMAND_PROCESSING_SUCCEEDED; + } +-- +2.1.4 + diff --git a/debian/patches/extra/CVE-2016-7156-scsi-pvscsi-avoid-infinite-loop-while-building-SG-li.patch b/debian/patches/extra/CVE-2016-7156-scsi-pvscsi-avoid-infinite-loop-while-building-SG-li.patch new file mode 100644 index 0000000..d4a133a --- /dev/null +++ b/debian/patches/extra/CVE-2016-7156-scsi-pvscsi-avoid-infinite-loop-while-building-SG-li.patch @@ -0,0 +1,63 @@ +From a8ceb006190b9072b0b9866ec5a07bd6de4eca6d Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit +Date: Tue, 6 Sep 2016 23:23:17 +0530 +Subject: [PATCH 5/6] scsi: pvscsi: avoid infinite loop while building SG list + +In PVSCSI paravirtual SCSI bus, pvscsi_convert_sglist can take a very +long time or go into an infinite loop due to two different bugs: + +1) the request descriptor data length is defined to be 64 bit. While +building SG list from a request descriptor, it gets truncated to 32bit +in routine 'pvscsi_convert_sglist'. This could lead to an infinite loop +situation for large 'dataLen' values, when data_length is cast to uint32_t +and chunk_size becomes always zero. Fix this by removing the incorrect +cast. + +2) pvscsi_get_next_sg_elem can be called arbitrarily many times if the +element has a zero length. Get out of the loop early when this happens, +by introducing an upper limit on the number of SG list elements. + +Reported-by: Li Qiang +Signed-off-by: Prasad J Pandit +--- + hw/scsi/vmw_pvscsi.c | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/hw/scsi/vmw_pvscsi.c b/hw/scsi/vmw_pvscsi.c +index 22f872c..e43e0a4 100644 +--- a/hw/scsi/vmw_pvscsi.c ++++ b/hw/scsi/vmw_pvscsi.c +@@ -40,6 +40,8 @@ + #define PVSCSI_MAX_DEVS (64) + #define PVSCSI_MSIX_NUM_VECTORS (1) + ++#define PVSCSI_MAX_SG_ELEM 2048 ++ + #define PVSCSI_MAX_CMD_DATA_WORDS \ + (sizeof(PVSCSICmdDescSetupRings)/sizeof(uint32_t)) + +@@ -629,17 +631,16 @@ pvscsi_queue_pending_descriptor(PVSCSIState *s, SCSIDevice **d, + static void + pvscsi_convert_sglist(PVSCSIRequest *r) + { +- int chunk_size; ++ uint32_t chunk_size, elmcnt = 0; + uint64_t data_length = r->req.dataLen; + PVSCSISGState sg = r->sg; +- while (data_length) { +- while (!sg.resid) { ++ while (data_length && elmcnt < PVSCSI_MAX_SG_ELEM) { ++ while (!sg.resid && elmcnt++ < PVSCSI_MAX_SG_ELEM) { + pvscsi_get_next_sg_elem(&sg); + trace_pvscsi_convert_sglist(r->req.context, r->sg.dataAddr, + r->sg.resid); + } +- assert(data_length > 0); +- chunk_size = MIN((unsigned) data_length, sg.resid); ++ chunk_size = MIN(data_length, sg.resid); + if (chunk_size) { + qemu_sglist_add(&r->sgl, sg.dataAddr, chunk_size); + } +-- +2.1.4 + diff --git a/debian/patches/extra/CVE-2016-7157-scsi-mptconfig-fix-an-assert-expression.patch b/debian/patches/extra/CVE-2016-7157-scsi-mptconfig-fix-an-assert-expression.patch new file mode 100644 index 0000000..f74c99b --- /dev/null +++ b/debian/patches/extra/CVE-2016-7157-scsi-mptconfig-fix-an-assert-expression.patch @@ -0,0 +1,35 @@ +From a0e2a28c08472ad3468c2f75d20fe1ca02ef8c0b Mon Sep 17 00:00:00 2001 +From: Prasad J Pandit +Date: Wed, 31 Aug 2016 17:36:07 +0530 +Subject: [PATCH 6/6] scsi: mptconfig: fix an assert expression + +When LSI SAS1068 Host Bus emulator builds configuration page +headers, mptsas_config_pack() should assert that the size +fits in a byte. However, the size is expressed in 32-bit +units, so up to 1020 bytes fit. The assertion was only +allowing replies up to 252 bytes, so fix it. + +Suggested-by: Paolo Bonzini +Signed-off-by: Prasad J Pandit +Message-Id: <1472645167-30765-2-git-send-email-ppandit@redhat.com> +Signed-off-by: Paolo Bonzini +--- + hw/scsi/mptconfig.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/hw/scsi/mptconfig.c b/hw/scsi/mptconfig.c +index 7071854..3e4f400 100644 +--- a/hw/scsi/mptconfig.c ++++ b/hw/scsi/mptconfig.c +@@ -158,7 +158,7 @@ static size_t mptsas_config_pack(uint8_t **data, const char *fmt, ...) + va_end(ap); + + if (data) { +- assert(ret < 256 && (ret % 4) == 0); ++ assert(ret / 4 < 256 && (ret % 4) == 0); + stb_p(*data + 1, ret / 4); + } + return ret; +-- +2.1.4 + diff --git a/debian/patches/series b/debian/patches/series index 972f109..5ad7435 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -67,3 +67,9 @@ extra/0007-virtio-decrement-vq-inuse-in-virtqueue_discard.patch extra/0008-iscsi-pass-SCSI-status-back-for-SG_IO.patch extra/0009-net-limit-allocation-in-nc_sendv_compat.patch extra/0010-ui-fix-refresh-of-VNC-server-surface.patch +extra/0001-9pfs-forbid-illegal-path-names.patch +extra/0002-9pfs-forbid-.-and-.-in-file-names.patch +extra/0003-9pfs-handle-walk-of-.-in-the-root-directory.patch +extra/CVE-2016-7155-scsi-check-page-count-while-initialising-descriptor-.patch +extra/CVE-2016-7156-scsi-pvscsi-avoid-infinite-loop-while-building-SG-li.patch +extra/CVE-2016-7157-scsi-mptconfig-fix-an-assert-expression.patch -- 2.11.4.GIT