diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2016-08-15 11:10:28 +0200 |
---|---|---|
committer | Michael Roth <mdroth@linux.vnet.ibm.com> | 2016-09-28 15:39:49 -0500 |
commit | 1b5520a3fd6d7416bb7dff9b69c58fb83e23ed05 (patch) | |
tree | f0d4e48c6c80d9e752ecf2ff8701c00319afe1fb | |
parent | 9ea7a46e2674edc84f056fc66c6f642d88b0c9ee (diff) |
s390x/css: handle cssid 255 correctly
The cssid 255 is reserved but still valid from an architectural
point of view. However, feeding a bogus schid of 0xffffffff into
the virtio hypercall will lead to a crash:
Stack trace of thread 138363:
#0 0x00000000100d168c css_find_subch (qemu-system-s390x)
#1 0x00000000100d3290 virtio_ccw_hcall_notify
#2 0x00000000100cbf60 s390_virtio_hypercall
#3 0x000000001010ff7a handle_hypercall
#4 0x0000000010079ed4 kvm_cpu_exec (qemu-system-s390x)
#5 0x00000000100609b4 qemu_kvm_cpu_thread_fn
#6 0x000003ff8b887bb4 start_thread (libpthread.so.0)
#7 0x000003ff8b78df0a thread_start (libc.so.6)
This is because the css array was only allocated for 0..254
instead of 0..255.
Let's fix this by bumping MAX_CSSID to 255 and fencing off the
reserved cssid of 255 during css image allocation.
Reported-by: Christian Borntraeger <borntraeger@de.ibm.com>
Tested-by: Christian Borntraeger <borntraeger@de.ibm.com>
Cc: qemu-stable@nongnu.org
Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com>
(cherry picked from commit 882b3b97697affb36ca3d174f42f846232008979)
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
-rw-r--r-- | hw/s390x/css.c | 8 | ||||
-rw-r--r-- | hw/s390x/css.h | 2 |
2 files changed, 4 insertions, 6 deletions
diff --git a/hw/s390x/css.c b/hw/s390x/css.c index 3a1d919580..0eb53f9a6b 100644 --- a/hw/s390x/css.c +++ b/hw/s390x/css.c @@ -139,7 +139,8 @@ out_err: int css_create_css_image(uint8_t cssid, bool default_image) { trace_css_new_image(cssid, default_image ? "(default)" : ""); - if (cssid > MAX_CSSID) { + /* 255 is reserved */ + if (cssid == 255) { return -EINVAL; } if (channel_subsys.css[cssid]) { @@ -1226,7 +1227,7 @@ bool css_schid_final(int m, uint8_t cssid, uint8_t ssid, uint16_t schid) uint8_t real_cssid; real_cssid = (!m && (cssid == 0)) ? channel_subsys.default_cssid : cssid; - if (real_cssid > MAX_CSSID || ssid > MAX_SSID || + if (ssid > MAX_SSID || !channel_subsys.css[real_cssid] || !channel_subsys.css[real_cssid]->sch_set[ssid]) { return true; @@ -1241,9 +1242,6 @@ static int css_add_virtual_chpid(uint8_t cssid, uint8_t chpid, uint8_t type) CssImage *css; trace_css_chpid_add(cssid, chpid, type); - if (cssid > MAX_CSSID) { - return -EINVAL; - } css = channel_subsys.css[cssid]; if (!css) { return -EINVAL; diff --git a/hw/s390x/css.h b/hw/s390x/css.h index a320eea59c..fdcfa3a783 100644 --- a/hw/s390x/css.h +++ b/hw/s390x/css.h @@ -19,7 +19,7 @@ /* Channel subsystem constants. */ #define MAX_SCHID 65535 #define MAX_SSID 3 -#define MAX_CSSID 254 /* 255 is reserved */ +#define MAX_CSSID 255 #define MAX_CHPID 255 #define MAX_CIWS 62 |