Hello Martin,
I think I fixed the pattern A crash in revision 6388. Can you try
again with an up-to-date subversion version of pcsc-lite?
I also got the patern B endless loop. I suspect a bug in libudev so
the pcscd do not receive the device remove event. But maybe it is a
bug in pcscd. I don't know how to reproduce the bug.
Bye
2012/5/28 Ludovic Rousseau <[email protected]>:
> 2012/5/27 Martin Vogt <[email protected]>:
>> On Sun, May 27, 2012 at 3:50 PM, Ludovic Rousseau
>> <[email protected]> wrote:
>
>>> I have not yet fixed this bug.
>>> And yes. It is a bit more complex to fix. I don't know yet how I will fix
>>> it.
>>
>> I looked at the code and added a few printfs.
>> The sequence seems to be:
>> HOTPLUG UDEV calls RFRemoveReader -s
>> [....]
>> 00000010 readerfactory.c:1009:RFUnInitializeReader() Attempting
>> shutdown of Aladdin eToken PRO USB 72K Java [Main Interface] 00 00.
>> 00000013 ifdhandler.c:244:IFDHCloseChannel()
>> usb:0529/0620:libudev:0:/dev/bus/usb/002/018 (lun: 0)
>> 00000021 ccid_usb.c:649:WriteUSB() write failed (2/18): -4 No such device
>> RFUnInitializeReader-1
>> 00000026 readerfactory.c:880:RFUnloadReader() Unloading reader driver.
>>
>> In between this call starts a new ContexThread:
>>
>> 00000105 winscard_svc.c:315:ContextThread() Received command:
>> DISCONNECT from client 9
>>
>> HOTPLU UDEV ends call RFRemoveReader -e
>>
>> Then I have:
>>
>> 00073910 winscard.c:796:SCardDisconnect() Lock released
>> 00000010 winscard.c:820:SCardDisconnect() Active Contexts: 0
>> 00000006 winscard.c:821:SCardDisconnect() dwDisposition: 2
>> Segmentation fault
>>
>> Maybe the hotplug thread can deliver Add/Remove over the SVCServiceRunLoop?
>> (As far as I understand it, the hotplug mechanism works independently,
>> and this may be the problem?)
>
> You can considerably reduce the time before the crash by adding a
> sleep(1) in ifdwrapper.c at line 269, just before the call to
> IFDStatusICC();
>
> The problem is that the reader is removed while another function using
> the reader is running and after this another function has checked the
> reader is present.
>
> It is a classic TOCTTOU bug [1].
>
> Bye
>
> [1] http://en.wikipedia.org/wiki/Time_of_check_to_time_of_use
--
Dr. Ludovic Rousseau
Index: src/winscard.c
===================================================================
--- src/winscard.c (révision 6387)
+++ src/winscard.c (copie de travail)
@@ -487,6 +487,8 @@ LONG SCardConnect(/*@unused@*/ SCARDCONT
rContext->readerState->readerSharing = rContext->contexts;
exit:
+ UNREF_READER(rContext)
+
PROFILE_END
return rv;
@@ -789,6 +791,8 @@ LONG SCardReconnect(SCARDHANDLE hCard, D
rv = SCARD_S_SUCCESS;
exit:
+ UNREF_READER(rContext)
+
return rv;
}
@@ -1037,6 +1041,8 @@ LONG SCardDisconnect(SCARDHANDLE hCard,
rv = SCARD_S_SUCCESS;
exit:
+ UNREF_READER(rContext)
+
return rv;
}
@@ -1077,6 +1083,8 @@ LONG SCardBeginTransaction(SCARDHANDLE h
Log2(PCSC_LOG_DEBUG, "Status: 0x%08lX", rv);
exit:
+ UNREF_READER(rContext)
+
return rv;
}
@@ -1211,6 +1219,8 @@ LONG SCardEndTransaction(SCARDHANDLE hCa
Log2(PCSC_LOG_DEBUG, "Status: 0x%08lX", rv);
exit:
+ UNREF_READER(rContext)
+
return rv;
}
@@ -1272,6 +1282,8 @@ LONG SCardStatus(SCARDHANDLE hCard, LPST
goto exit;
exit:
+ UNREF_READER(rContext)
+
return rv;
}
@@ -1329,6 +1341,8 @@ LONG SCardControl(SCARDHANDLE hCard, DWO
rv = SCARD_E_UNSUPPORTED_FEATURE;
exit:
+ UNREF_READER(rContext)
+
return rv;
}
@@ -1403,6 +1417,8 @@ LONG SCardGetAttrib(SCARDHANDLE hCard, D
}
exit:
+ UNREF_READER(rContext)
+
return rv;
}
@@ -1451,6 +1467,8 @@ LONG SCardSetAttrib(SCARDHANDLE hCard, D
rv = SCARD_E_NOT_TRANSACTED;
exit:
+ UNREF_READER(rContext)
+
return rv;
}
@@ -1605,6 +1623,8 @@ LONG SCardTransmit(SCARDHANDLE hCard, co
*pcbRecvLength = dwRxLength;
exit:
+ UNREF_READER(rContext)
+
return rv;
}
Index: src/readerfactory.c
===================================================================
--- src/readerfactory.c (révision 6387)
+++ src/readerfactory.c (copie de travail)
@@ -58,6 +58,7 @@ static int ConfigFileCRC = 0;
static pthread_mutex_t LockMutex = PTHREAD_MUTEX_INITIALIZER;
#define IDENTITY_SHIFT 16
+static LONG removeReader(READER_CONTEXT * sReader);
static int RDR_CLIHANDLES_seeker(const void *el, const void *key)
{
@@ -78,6 +79,33 @@ static int RDR_CLIHANDLES_seeker(const v
}
+LONG _RefReader(READER_CONTEXT * sReader)
+{
+ if (0 == sReader->reference)
+ return SCARD_E_READER_UNAVAILABLE;
+
+ pthread_mutex_lock(&sReader->reference_lock);
+ sReader->reference += 1;
+ pthread_mutex_unlock(&sReader->reference_lock);
+
+ return SCARD_S_SUCCESS;
+}
+
+LONG _UnrefReader(READER_CONTEXT * sReader)
+{
+ if (0 == sReader->reference)
+ return SCARD_E_READER_UNAVAILABLE;
+
+ pthread_mutex_lock(&sReader->reference_lock);
+ sReader->reference -= 1;
+ pthread_mutex_unlock(&sReader->reference_lock);
+
+ if (0 == sReader->reference)
+ removeReader(sReader);
+
+ return SCARD_S_SUCCESS;
+}
+
LONG RFAllocateReaderSpace(unsigned int customMaxReaderHandles)
{
int i; /* Counter */
@@ -218,6 +246,11 @@ LONG RFAddReader(const char *readerNameL
NULL);
sReadersContexts[dwContext]->powerState = POWER_STATE_UNPOWERED;
+ /* reference count */
+ (void)pthread_mutex_init(&sReadersContexts[dwContext]->reference_lock,
+ NULL);
+ sReadersContexts[dwContext]->reference = 1;
+
/* If a clone to this reader exists take some values from that clone */
if (parentNode >= 0 && parentNode < PCSCLITE_MAX_READERS_CONTEXTS)
{
@@ -411,6 +444,11 @@ LONG RFAddReader(const char *readerNameL
NULL);
sReadersContexts[dwContextB]->powerState =
POWER_STATE_UNPOWERED;
+ /* reference count */
+
(void)pthread_mutex_init(&sReadersContexts[dwContextB]->reference_lock,
+ NULL);
+ sReadersContexts[dwContextB]->reference = 1;
+
/* Call on the parent driver to see if the slots are thread
safe */
dwGetSize = sizeof(ucThread);
rv = IFDGetCapabilities((sReadersContexts[dwContext]),
@@ -477,6 +515,21 @@ LONG RFRemoveReader(const char *readerNa
rv = RFReaderInfoNamePort(port, readerName, &sContext);
if (SCARD_S_SUCCESS == rv)
{
+ /* first to derefence RFReaderInfoNamePort() */
+ UNREF_READER(sContext)
+
+ /* second to remove the reader */
+ UNREF_READER(sContext)
+ }
+
+ return SCARD_S_SUCCESS;
+}
+
+LONG removeReader(READER_CONTEXT * sContext)
+{
+ LONG rv;
+
+ {
/* Try to destroy the thread */
if (sContext -> pthThread)
(void)EHDestroyEventHandler(sContext);
@@ -673,6 +726,9 @@ LONG RFReaderInfo(const char *readerName
if (strcmp(readerName,
sReadersContexts[i]->readerState->readerName)
== 0)
{
+ /* Increase reference count */
+ REF_READER(sReadersContexts[i])
+
*sReader = sReadersContexts[i];
return SCARD_S_SUCCESS;
}
@@ -704,6 +760,10 @@ LONG RFReaderInfoNamePort(int port, cons
if ((strncmp(readerName, lpcStripReader, MAX_READERNAME
- sizeof(" 00 00")) == 0)
&& (port == sReadersContexts[i]->port))
{
+ Log3(PCSC_LOG_DEBUG, "name: %s, port: %d",
readerName, port);
+ /* Increase reference count */
+ REF_READER(sReadersContexts[i])
+
*sReader = sReadersContexts[i];
return SCARD_S_SUCCESS;
}
@@ -728,6 +788,9 @@ LONG RFReaderInfoById(SCARDHANDLE hCard,
(void)pthread_mutex_unlock(&sReadersContexts[i]->handlesList_lock);
if (currentHandle != NULL)
{
+ /* Increase reference count */
+ REF_READER(sReadersContexts[i])
+
*sReader = sReadersContexts[i];
return SCARD_S_SUCCESS;
}
Index: src/readerfactory.h
===================================================================
--- src/readerfactory.h (révision 6387)
+++ src/readerfactory.h (copie de travail)
@@ -109,6 +109,8 @@
int * pMutex; /**< Number of client to mutex
*/
int powerState; /**< auto power off state */
pthread_mutex_t powerState_lock; /**< powerState mutex */
+ int reference; /**< number of users of the
structure */
+ pthread_mutex_t reference_lock; /**< reference mutex */
struct pubReaderStatesList *readerState; /**< link to the
reader state */
/* we can't use READER_STATE * here since eventhandler.h can't
be
@@ -117,6 +119,12 @@
typedef struct ReaderContext READER_CONTEXT;
+ LONG _RefReader(READER_CONTEXT * sReader);
+ LONG _UnrefReader(READER_CONTEXT * sReader);
+
+#define REF_READER(reader) { LONG rv; Log2(PCSC_LOG_CRITICAL, "RefReader()
count was: %d", reader->reference); rv = _RefReader(reader); if (rv !=
SCARD_S_SUCCESS) return rv; }
+#define UNREF_READER(reader) {Log2(PCSC_LOG_CRITICAL, "UnrefReader() count
was: %d", reader->reference); _UnrefReader(reader);}
+
LONG RFAllocateReaderSpace(unsigned int);
LONG RFAddReader(const char *, int, const char *, const char *);
LONG RFRemoveReader(const char *, int);
_______________________________________________
Muscle mailing list
[email protected]
http://lists.drizzle.com/mailman/listinfo/muscle