[PATCH 19/27] hw/usb/dev-smartcard-reader: reject commands for invalid slots
Marc-André Lureau <[email protected]> Wed, 05 Aug 2026 15:51:09 +0400
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
The descriptor advertises bMaxSlotIndex = 0 (single slot), but ccid_handle_bulk_out() never validated bSlot. Commands addressed to non-existent slots were silently processed against slot 0 state. Reject them with bError = 5 (slot does not exist) per CCID Rev 1.1 section 6.2.7. Signed-off-by: Marc-André Lureau <[email protected]> --- hw/usb/dev-smartcard-reader.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/hw/usb/dev-smartcard-reader.c b/hw/usb/dev-smartcard-reader.c index e7bc5f6d4ae0..cc7356c77413 100644 --- a/hw/usb/dev-smartcard-reader.c +++ b/hw/usb/dev-smartcard-reader.c @@ -167,6 +167,7 @@ enum { ERROR_XFR_OVERRUN = -4, ERROR_HW_ERROR = -5, ERROR_CMD_SLOT_BUSY = -32, + ERROR_SLOT_NOT_EXIST = 5, }; /* 6.2.6 RDR_to_PC_SlotStatus definitions */ @@ -1087,6 +1088,35 @@ static const char *ccid_message_type_to_str(uint8_t type) return "unknown"; } +/* + * Send the spec-mandated response type for the given command with the + * error already staged via ccid_report_error_failed(). + */ +static void ccid_write_error_response(USBCCIDState *s, CCID_Header *recv) +{ + switch (recv->bMessageType) { + case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn: + case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock: + case CCID_MESSAGE_TYPE_PC_to_RDR_Secure: + ccid_write_data_block_error(s, recv->bSlot, recv->bSeq); + break; + case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters: + case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters: + case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters: + ccid_write_parameters(s, recv); + break; + case CCID_MESSAGE_TYPE_PC_to_RDR_Escape: + ccid_write_escape(s, recv); + break; + case CCID_MESSAGE_TYPE_PC_to_RDR_SetDataRateAndClockFrequency: + ccid_write_data_rate_and_clock(s, recv); + break; + default: + ccid_write_slot_status(s, recv); + break; + } +} + static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p) { CCID_Header *ccid_header; @@ -1130,6 +1160,14 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p) goto err; } + if (ccid_header->bSlot != 0) { + DPRINTF(s, 1, "usb-ccid: bad slot %d\n", ccid_header->bSlot); + ccid_report_error_failed(s, ERROR_SLOT_NOT_EXIST); + ccid_write_error_response(s, ccid_header); + s->bulk_out_pos = 0; + return; + } + DPRINTF(s, D_MORE_INFO, "%s %x %s\n", __func__, ccid_header->bMessageType, ccid_message_type_to_str(ccid_header->bMessageType)); -- 2.55.0