]> git.proxmox.com Git - pve-qemu-kvm.git/commitdiff
various CVE fixes
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 7 Sep 2016 09:58:00 +0000 (11:58 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Wed, 7 Sep 2016 10:12:21 +0000 (12:12 +0200)
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

debian/patches/extra/0001-9pfs-forbid-illegal-path-names.patch [new file with mode: 0644]
debian/patches/extra/0002-9pfs-forbid-.-and-.-in-file-names.patch [new file with mode: 0644]
debian/patches/extra/0003-9pfs-handle-walk-of-.-in-the-root-directory.patch [new file with mode: 0644]
debian/patches/extra/CVE-2016-7155-scsi-check-page-count-while-initialising-descriptor-.patch [new file with mode: 0644]
debian/patches/extra/CVE-2016-7156-scsi-pvscsi-avoid-infinite-loop-while-building-SG-li.patch [new file with mode: 0644]
debian/patches/extra/CVE-2016-7157-scsi-mptconfig-fix-an-assert-expression.patch [new file with mode: 0644]
debian/patches/series

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 (file)
index 0000000..15d3119
--- /dev/null
@@ -0,0 +1,178 @@
+From 21289fc663198d96ae2ca145a425f2e21ed4637a Mon Sep 17 00:00:00 2001
+From: Greg Kurz <groug@kaod.org>
+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 <peter.maydell@linaro.org>
+Signed-off-by: Greg Kurz <groug@kaod.org>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
+---
+ 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 (file)
index 0000000..c2c0500
--- /dev/null
@@ -0,0 +1,159 @@
+From 3ae00feb459657766ec623de7eae8f014a660ab4 Mon Sep 17 00:00:00 2001
+From: Greg Kurz <groug@kaod.org>
+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 <peter.maydell@linaro.org>
+Signed-off-by: Greg Kurz <groug@kaod.org>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
+Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
+---
+ 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 (file)
index 0000000..d4f22c2
--- /dev/null
@@ -0,0 +1,126 @@
+From 348503ea115b336343166b87271208ffc0bdeb0a Mon Sep 17 00:00:00 2001
+From: Greg Kurz <groug@kaod.org>
+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 <groug@kaod.org>
+Reviewed-by: Eric Blake <eblake@redhat.com>
+Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
+---
+ 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 (file)
index 0000000..54df061
--- /dev/null
@@ -0,0 +1,83 @@
+From 7c7e45d2bd1a77fbe89dff83fabf89a46479111f Mon Sep 17 00:00:00 2001
+From: Prasad J Pandit <pjp@fedoraproject.org>
+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 <vv474172261@gmail.com>
+Reported-by: Li Qiang <liqiang6-s@360.cn>
+Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
+---
+ 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 (file)
index 0000000..d4a133a
--- /dev/null
@@ -0,0 +1,63 @@
+From a8ceb006190b9072b0b9866ec5a07bd6de4eca6d Mon Sep 17 00:00:00 2001
+From: Prasad J Pandit <pjp@fedoraproject.org>
+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 <liqiang6-s@360.cn>
+Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
+---
+ 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 (file)
index 0000000..f74c99b
--- /dev/null
@@ -0,0 +1,35 @@
+From a0e2a28c08472ad3468c2f75d20fe1ca02ef8c0b Mon Sep 17 00:00:00 2001
+From: Prasad J Pandit <pjp@fedoraproject.org>
+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 <pbonzini@redhat.com>
+Signed-off-by: Prasad J Pandit <pjp@fedoraproject.org>
+Message-Id: <1472645167-30765-2-git-send-email-ppandit@redhat.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+---
+ 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
+
index 972f1091eef4506aa7bb9f7e837758773a297343..5ad7435bd4747f7aab0d1ee5733df9d898d4e628 100644 (file)
@@ -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