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