staging: unisys: visorbus: tolerate larger-than-expected controlvm channel
authorTim Sell <Timothy.Sell@unisys.com>
Wed, 2 Mar 2016 00:45:03 +0000 (19:45 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 2 Mar 2016 03:14:07 +0000 (19:14 -0800)
Use the dynamic size of the controlvm channel (struct channel_header.size)
instead of the statically computed sizeof(struct controlvm_channel) when
determining the valid bounds for visorchannel_read() and
visorchannel_write().

This prevents an observed problem where kdump was failing because
controlvm_channel.local_crash_msg_offset was pointing beyond the statically
computed size of the channel, even though the channel was physically large
enough.  This was causing visorchannel_read() to unecessarily fail, because
we thought we were attempting to access memory outside of the channel.

Signed-off-by: Timothy Sell <timothy.sell@unisys.com>
Signed-off-by: David Kershner <david.kershner@unisys.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/unisys/visorbus/visorchipset.c

index e1a5b672fe6d4a22504d02d7853df40eaf89a965..166a067e8bb4bcef74a681940a097eac6da5780f 100644 (file)
@@ -2251,7 +2251,6 @@ visorchipset_init(struct acpi_device *acpi_device)
 {
        int rc = 0;
        u64 addr;
-       int tmp_sz = sizeof(struct spar_controlvm_channel_protocol);
        uuid_le uuid = SPAR_CONTROLVM_CHANNEL_PROTOCOL_UUID;
 
        addr = controlvm_get_channel_address();
@@ -2261,8 +2260,10 @@ visorchipset_init(struct acpi_device *acpi_device)
        memset(&busdev_notifiers, 0, sizeof(busdev_notifiers));
        memset(&controlvm_payload_info, 0, sizeof(controlvm_payload_info));
 
-       controlvm_channel = visorchannel_create_with_lock(addr, tmp_sz,
+       controlvm_channel = visorchannel_create_with_lock(addr, 0,
                                                          GFP_KERNEL, uuid);
+       if (!controlvm_channel)
+               return -ENODEV;
        if (SPAR_CONTROLVM_CHANNEL_OK_CLIENT(
                    visorchannel_get_header(controlvm_channel))) {
                initialize_controlvm_payload();