9ae3a8
From b71bd2f7f4a259183fa3d38e6e891cffb86683e2 Mon Sep 17 00:00:00 2001
9ae3a8
From: Gerd Hoffmann <kraxel@redhat.com>
9ae3a8
Date: Tue, 14 Mar 2017 08:52:54 +0100
9ae3a8
Subject: [PATCH 21/24] usb-ccid: better bulk_out error handling
9ae3a8
MIME-Version: 1.0
9ae3a8
Content-Type: text/plain; charset=UTF-8
9ae3a8
Content-Transfer-Encoding: 8bit
9ae3a8
9ae3a8
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
9ae3a8
Message-id: <1489481576-26911-3-git-send-email-kraxel@redhat.com>
9ae3a8
Patchwork-id: 74289
9ae3a8
O-Subject: [RHEL-7.4 qemu-kvm PATCH 2/4] usb-ccid: better bulk_out error handling
9ae3a8
Bugzilla: 1419818
9ae3a8
RH-Acked-by: Stefan Hajnoczi <stefanha@redhat.com>
9ae3a8
RH-Acked-by: Laurent Vivier <lvivier@redhat.com>
9ae3a8
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
9ae3a8
Add err goto label where we can jump to from all error conditions.
9ae3a8
STALL request on all errors.  Reset position on all errors.
9ae3a8
9ae3a8
Normal request processing is not in a else branch any more, so this code
9ae3a8
is reintended, there are no code changes in that part of the code
9ae3a8
though.
9ae3a8
9ae3a8
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
9ae3a8
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
9ae3a8
Message-id: 1487250819-23764-2-git-send-email-kraxel@redhat.com
9ae3a8
(cherry picked from commit 0aeebc73b7976bae5cb7e9768e3d9a0fd9d634e8)
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 hw/usb/dev-smartcard-reader.c | 116 ++++++++++++++++++++++--------------------
9ae3a8
 1 file changed, 61 insertions(+), 55 deletions(-)
9ae3a8
9ae3a8
diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c
9ae3a8
index 0e0b363..672a7bf 100644
9ae3a8
--- a/hw/usb/dev-smartcard-reader.c
9ae3a8
+++ b/hw/usb/dev-smartcard-reader.c
9ae3a8
@@ -999,8 +999,7 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
9ae3a8
     CCID_Header *ccid_header;
9ae3a8
 
9ae3a8
     if (p->iov.size + s->bulk_out_pos > BULK_OUT_DATA_SIZE) {
9ae3a8
-        p->status = USB_RET_STALL;
9ae3a8
-        return;
9ae3a8
+        goto err;
9ae3a8
     }
9ae3a8
     ccid_header = (CCID_Header *)s->bulk_out_data;
9ae3a8
     usb_packet_copy(p, s->bulk_out_data + s->bulk_out_pos, p->iov.size);
9ae3a8
@@ -1015,64 +1014,71 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
9ae3a8
         DPRINTF(s, 1,
9ae3a8
                 "%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n",
9ae3a8
                 __func__);
9ae3a8
-    } else {
9ae3a8
-        DPRINTF(s, D_MORE_INFO, "%s %x %s\n", __func__,
9ae3a8
-                ccid_header->bMessageType,
9ae3a8
-                ccid_message_type_to_str(ccid_header->bMessageType));
9ae3a8
-        switch (ccid_header->bMessageType) {
9ae3a8
-        case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
9ae3a8
-            ccid_write_slot_status(s, ccid_header);
9ae3a8
-            break;
9ae3a8
-        case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
9ae3a8
-            DPRINTF(s, 1, "%s: PowerOn: %d\n", __func__,
9ae3a8
+        goto err;
9ae3a8
+    }
9ae3a8
+
9ae3a8
+    DPRINTF(s, D_MORE_INFO, "%s %x %s\n", __func__,
9ae3a8
+            ccid_header->bMessageType,
9ae3a8
+            ccid_message_type_to_str(ccid_header->bMessageType));
9ae3a8
+    switch (ccid_header->bMessageType) {
9ae3a8
+    case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
9ae3a8
+        ccid_write_slot_status(s, ccid_header);
9ae3a8
+        break;
9ae3a8
+    case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
9ae3a8
+        DPRINTF(s, 1, "%s: PowerOn: %d\n", __func__,
9ae3a8
                 ((CCID_IccPowerOn *)(ccid_header))->bPowerSelect);
9ae3a8
-            s->powered = true;
9ae3a8
-            if (!ccid_card_inserted(s)) {
9ae3a8
-                ccid_report_error_failed(s, ERROR_ICC_MUTE);
9ae3a8
-            }
9ae3a8
-            /* atr is written regardless of error. */
9ae3a8
-            ccid_write_data_block_atr(s, ccid_header);
9ae3a8
-            break;
9ae3a8
-        case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff:
9ae3a8
-            ccid_reset_error_status(s);
9ae3a8
-            s->powered = false;
9ae3a8
-            ccid_write_slot_status(s, ccid_header);
9ae3a8
-            break;
9ae3a8
-        case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock:
9ae3a8
-            ccid_on_apdu_from_guest(s, (CCID_XferBlock *)s->bulk_out_data);
9ae3a8
-            break;
9ae3a8
-        case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters:
9ae3a8
-            ccid_reset_error_status(s);
9ae3a8
-            ccid_set_parameters(s, ccid_header);
9ae3a8
-            ccid_write_parameters(s, ccid_header);
9ae3a8
-            break;
9ae3a8
-        case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters:
9ae3a8
-            ccid_reset_error_status(s);
9ae3a8
-            ccid_reset_parameters(s);
9ae3a8
-            ccid_write_parameters(s, ccid_header);
9ae3a8
-            break;
9ae3a8
-        case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters:
9ae3a8
-            ccid_reset_error_status(s);
9ae3a8
-            ccid_write_parameters(s, ccid_header);
9ae3a8
-            break;
9ae3a8
-        case CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical:
9ae3a8
-            ccid_report_error_failed(s, 0);
9ae3a8
-            ccid_write_slot_status(s, ccid_header);
9ae3a8
-            break;
9ae3a8
-        default:
9ae3a8
-            DPRINTF(s, 1,
9ae3a8
+        s->powered = true;
9ae3a8
+        if (!ccid_card_inserted(s)) {
9ae3a8
+            ccid_report_error_failed(s, ERROR_ICC_MUTE);
9ae3a8
+        }
9ae3a8
+        /* atr is written regardless of error. */
9ae3a8
+        ccid_write_data_block_atr(s, ccid_header);
9ae3a8
+        break;
9ae3a8
+    case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff:
9ae3a8
+        ccid_reset_error_status(s);
9ae3a8
+        s->powered = false;
9ae3a8
+        ccid_write_slot_status(s, ccid_header);
9ae3a8
+        break;
9ae3a8
+    case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock:
9ae3a8
+        ccid_on_apdu_from_guest(s, (CCID_XferBlock *)s->bulk_out_data);
9ae3a8
+        break;
9ae3a8
+    case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters:
9ae3a8
+        ccid_reset_error_status(s);
9ae3a8
+        ccid_set_parameters(s, ccid_header);
9ae3a8
+        ccid_write_parameters(s, ccid_header);
9ae3a8
+        break;
9ae3a8
+    case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters:
9ae3a8
+        ccid_reset_error_status(s);
9ae3a8
+        ccid_reset_parameters(s);
9ae3a8
+        ccid_write_parameters(s, ccid_header);
9ae3a8
+        break;
9ae3a8
+    case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters:
9ae3a8
+        ccid_reset_error_status(s);
9ae3a8
+        ccid_write_parameters(s, ccid_header);
9ae3a8
+        break;
9ae3a8
+    case CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical:
9ae3a8
+        ccid_report_error_failed(s, 0);
9ae3a8
+        ccid_write_slot_status(s, ccid_header);
9ae3a8
+        break;
9ae3a8
+    default:
9ae3a8
+        DPRINTF(s, 1,
9ae3a8
                 "handle_data: ERROR: unhandled message type %Xh\n",
9ae3a8
                 ccid_header->bMessageType);
9ae3a8
-            /*
9ae3a8
-             * The caller is expecting the device to respond, tell it we
9ae3a8
-             * don't support the operation.
9ae3a8
-             */
9ae3a8
-            ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED);
9ae3a8
-            ccid_write_slot_status(s, ccid_header);
9ae3a8
-            break;
9ae3a8
-        }
9ae3a8
+        /*
9ae3a8
+         * The caller is expecting the device to respond, tell it we
9ae3a8
+         * don't support the operation.
9ae3a8
+         */
9ae3a8
+        ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED);
9ae3a8
+        ccid_write_slot_status(s, ccid_header);
9ae3a8
+        break;
9ae3a8
     }
9ae3a8
     s->bulk_out_pos = 0;
9ae3a8
+    return;
9ae3a8
+
9ae3a8
+err:
9ae3a8
+    p->status = USB_RET_STALL;
9ae3a8
+    s->bulk_out_pos = 0;
9ae3a8
+    return;
9ae3a8
 }
9ae3a8
 
9ae3a8
 static void ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p)
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8