Skip to content

Commit

Permalink
usb-ccid: better bulk_out error handling
Browse files Browse the repository at this point in the history
Add err goto label where we can jump to from all error conditions.
STALL request on all errors.  Reset position on all errors.

Normal request processing is not in a else branch any more, so this code
is reintended, there are no code changes in that part of the code
though.

Signed-off-by: Gerd Hoffmann <[email protected]>
Reviewed-by: Marc-André Lureau <[email protected]>
Message-id: [email protected]
  • Loading branch information
kraxel committed Feb 21, 2017
1 parent 558ff1b commit 0aeebc7
Showing 1 changed file with 61 additions and 55 deletions.
116 changes: 61 additions & 55 deletions hw/usb/dev-smartcard-reader.c
Original file line number Diff line number Diff line change
Expand Up @@ -1001,8 +1001,7 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
CCID_Header *ccid_header;

if (p->iov.size + s->bulk_out_pos > BULK_OUT_DATA_SIZE) {
p->status = USB_RET_STALL;
return;
goto err;
}
ccid_header = (CCID_Header *)s->bulk_out_data;
usb_packet_copy(p, s->bulk_out_data + s->bulk_out_pos, p->iov.size);
Expand All @@ -1017,64 +1016,71 @@ static void ccid_handle_bulk_out(USBCCIDState *s, USBPacket *p)
DPRINTF(s, 1,
"%s: bad USB_TOKEN_OUT length, should be at least 10 bytes\n",
__func__);
} else {
DPRINTF(s, D_MORE_INFO, "%s %x %s\n", __func__,
ccid_header->bMessageType,
ccid_message_type_to_str(ccid_header->bMessageType));
switch (ccid_header->bMessageType) {
case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
ccid_write_slot_status(s, ccid_header);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
DPRINTF(s, 1, "%s: PowerOn: %d\n", __func__,
goto err;
}

DPRINTF(s, D_MORE_INFO, "%s %x %s\n", __func__,
ccid_header->bMessageType,
ccid_message_type_to_str(ccid_header->bMessageType));
switch (ccid_header->bMessageType) {
case CCID_MESSAGE_TYPE_PC_to_RDR_GetSlotStatus:
ccid_write_slot_status(s, ccid_header);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOn:
DPRINTF(s, 1, "%s: PowerOn: %d\n", __func__,
((CCID_IccPowerOn *)(ccid_header))->bPowerSelect);
s->powered = true;
if (!ccid_card_inserted(s)) {
ccid_report_error_failed(s, ERROR_ICC_MUTE);
}
/* atr is written regardless of error. */
ccid_write_data_block_atr(s, ccid_header);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff:
ccid_reset_error_status(s);
s->powered = false;
ccid_write_slot_status(s, ccid_header);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock:
ccid_on_apdu_from_guest(s, (CCID_XferBlock *)s->bulk_out_data);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters:
ccid_reset_error_status(s);
ccid_set_parameters(s, ccid_header);
ccid_write_parameters(s, ccid_header);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters:
ccid_reset_error_status(s);
ccid_reset_parameters(s);
ccid_write_parameters(s, ccid_header);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters:
ccid_reset_error_status(s);
ccid_write_parameters(s, ccid_header);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical:
ccid_report_error_failed(s, 0);
ccid_write_slot_status(s, ccid_header);
break;
default:
DPRINTF(s, 1,
s->powered = true;
if (!ccid_card_inserted(s)) {
ccid_report_error_failed(s, ERROR_ICC_MUTE);
}
/* atr is written regardless of error. */
ccid_write_data_block_atr(s, ccid_header);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_IccPowerOff:
ccid_reset_error_status(s);
s->powered = false;
ccid_write_slot_status(s, ccid_header);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock:
ccid_on_apdu_from_guest(s, (CCID_XferBlock *)s->bulk_out_data);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_SetParameters:
ccid_reset_error_status(s);
ccid_set_parameters(s, ccid_header);
ccid_write_parameters(s, ccid_header);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_ResetParameters:
ccid_reset_error_status(s);
ccid_reset_parameters(s);
ccid_write_parameters(s, ccid_header);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_GetParameters:
ccid_reset_error_status(s);
ccid_write_parameters(s, ccid_header);
break;
case CCID_MESSAGE_TYPE_PC_to_RDR_Mechanical:
ccid_report_error_failed(s, 0);
ccid_write_slot_status(s, ccid_header);
break;
default:
DPRINTF(s, 1,
"handle_data: ERROR: unhandled message type %Xh\n",
ccid_header->bMessageType);
/*
* The caller is expecting the device to respond, tell it we
* don't support the operation.
*/
ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED);
ccid_write_slot_status(s, ccid_header);
break;
}
/*
* The caller is expecting the device to respond, tell it we
* don't support the operation.
*/
ccid_report_error_failed(s, ERROR_CMD_NOT_SUPPORTED);
ccid_write_slot_status(s, ccid_header);
break;
}
s->bulk_out_pos = 0;
return;

err:
p->status = USB_RET_STALL;
s->bulk_out_pos = 0;
return;
}

static void ccid_bulk_in_copy_to_guest(USBCCIDState *s, USBPacket *p)
Expand Down

0 comments on commit 0aeebc7

Please sign in to comment.