[Pcsclite-muscle] Race condition during readerstate update
Ludovic Rousseau
ludovic.rousseau at gmail.com
Mon Sep 7 05:23:58 EDT 2020
Le ven. 28 août 2020 à 13:41, Marc Kewitz
<Marc.Kewitz.ext at rohde-schwarz.com> a écrit :
> Hi,
Hello,
> I need your advice/help on an issue. I will try to explain the general setup first and then the issue.
>
> We have a SOC running linux. This SOC is connected to another processor via usb. This processor is handling the smartcard ( and also other things ). Our software is running on the SOC using the pcsc-lite lib to communicate with the pcscd which communicates with the processor/smartcard. They are communicating via the ccid T1 protocol using the CCID driver lib on the SOC. We have 2 slots for this smartcard reader.
>
> Now to the issue. We are regularly sending requests ( PC_to_RDR_XfrBlock ) to the smartcard to get random data. If someone pulls the smartcard during those requests, the request obviously fails. If that happens, the processor checks if the smartcard is still available ( in this case not ) and sends RDR_to_PC_NotifySlotChange via the interrupt channel back to the pcscd. After that the processor sends the answer RDR_to_PC_DataBlock with an error code.
> This all works fine and we receive the notifyslotchange as well as the datablock answer.
> As soon as our software on the SOC realizes that the request failed, it sends an SCardStatus request to the pcscd to check if the card is still available. Now the issue is that the readerStates that the pcscd receives in getReaderStates ( ) have not been updated yet and we see that smartcard as available although it is not.
>
> It seems like the handling of interrupts in the ccid driver, Multi_PollingProc and Multi_InterruptRead, is too slow as I can see the reception of the RDR_to_PC_DataBlock answer and the following SCardStatus request before I see the InterruptRead return in the pcscd. The readerState update in EHStatusHandlerThread is consequently only happening after the SCardStatus request.
>
> Did anyone ever come across this issue? I really want to avoid touching pcscd-lite. My first idea was to get the smartcard status via IFDStatusICC ( )/GetSlotStatus in SCardStatus. This also works and solves the problem, but I'd like to not mess with the pcsc-lite code. I also don't see delaying the SCardStatus call in the software running on the SOC as a viable solution as a sleep or similar is only concealing the actual problem.
I fixed a problem in the CCID driver and PCSC-lite.
Now when a smart card is removed during a SCardTransmit() you will
(sometimes/often) receive the error SCARD_E_NO_SMARTCARD instead of
SCARD_E_NOT_TRANSACTED.
And the SCardStatus(), if it returns SCARD_S_SUCCESS, will indicate
SCARD_ABSENT in pdwState.
After "some time" SCardStatus() will return SCARD_W_REMOVED_CARD.
I wrote "sometimes/often" because depending on the CCID error reported
by the reader SCardTransmit() may still return SCARD_E_NOT_TRANSACTED.
For example the reader may return the CCID error "Procedure byte
conflict" instead of "Card absent or mute". In that case the driver
does not know yet if the card is still present or not.
You will have to build the current git versions of libccid and
pcsc-lite to get this fix.
Tell me if the fix works for you.
Remarks:
- on Windows I get SCARD_E_COMM_DATA_LOST for SCardTransmit() or a
non-PCSC error 0x57 "The parameter is incorrect"
- SCardStatus() returns SCARD_W_REMOVED_CARD immediately (as expected)
On macOS (Catalina) I have the same behavior as on GNU/Linux before my
changes. SCardTransmit() returns SCARD_E_NOT_TRANSACTED and
SCardStatus() may return SCARD_S_SUCCESS immediately and
SCARD_W_REMOVED_CARD after "some time".
Questions:
- maybe SCARD_W_REMOVED_CARD is even better than SCARD_E_NO_SMARTCARD
for SCardTransmit()
- SCardStatus() will return SCARD_S_SUCCESS (but with a correct
pdwState) until the card removal is really detected. Do you think that
is important to fix?
Bye
--
Dr. Ludovic Rousseau
More information about the pcsclite-muscle
mailing list