[Pcsclite-git-commit] [PCSC] 03/03: Threading: lock the card context in a safe way

Ludovic Rousseau rousseau at moszumanska.debian.org
Tue Jun 23 15:39:16 UTC 2015


This is an automated email from the git hooks/post-receive script.

rousseau pushed a commit to branch master
in repository PCSC.

commit 85d8dea93679c98b9673e71dd0d1b9cf793b6db0
Author: Ludovic Rousseau <ludovic.rousseau at gmail.com>
Date:   Tue Jun 23 14:50:22 2015 +0200

    Threading: lock the card context in a safe way
    
    Functions working on hCard now acquire the context lock while the
    global thread lock is held.
    
    This will avoid the context to be released between the context retrieval
    and context lock. The code was ugly with a new call to
    SCardGetContextAndChannelFromHandle() to check that the context was
    still valid.
    
    This patch similar than the one in
    9681246742b812ba1b8acbe8892d8aa755215059 for hContext.
    
    Thanks to Luc Mazardo for the bug report.
    http://lists.alioth.debian.org/pipermail/pcsclite-muscle/Week-of-Mon-20150608/000395.html
---
 src/winscard_clnt.c | 187 ++++++++--------------------------------------------
 1 file changed, 27 insertions(+), 160 deletions(-)

diff --git a/src/winscard_clnt.c b/src/winscard_clnt.c
index 589d14f..951434f 100644
--- a/src/winscard_clnt.c
+++ b/src/winscard_clnt.c
@@ -374,7 +374,7 @@ static LONG SCardRemoveContext(SCARDCONTEXT);
 static LONG SCardCleanContext(SCONTEXTMAP *);
 
 static LONG SCardAddHandle(SCARDHANDLE, SCONTEXTMAP *, LPCSTR);
-static LONG SCardGetContextAndChannelFromHandle(SCARDHANDLE,
+static LONG SCardGetContextChannelAndLockFromHandle(SCARDHANDLE,
 	/*@out@*/ SCONTEXTMAP * *, /*@out@*/ CHANNEL_MAP * *);
 static LONG SCardGetContextAndChannelFromHandleTH(SCARDHANDLE,
 	/*@out@*/ SCONTEXTMAP * *, /*@out@*/ CHANNEL_MAP * *);
@@ -931,34 +931,17 @@ LONG SCardReconnect(SCARDHANDLE hCard, DWORD dwShareMode,
 	if (pdwActiveProtocol == NULL)
 		return SCARD_E_INVALID_PARAMETER;
 
+	/* Retry loop for blocking behaviour */
+retry:
+
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+	rv = SCardGetContextChannelAndLockFromHandle(hCard, &currentContextMap,
 		&pChannelMap);
 	if (rv == -1)
 		return SCARD_E_INVALID_HANDLE;
 
-	/* Retry loop for blocking behaviour */
-retry:
-
-	(void)pthread_mutex_lock(&currentContextMap->mMutex);
-
-	/* check the handle is still valid */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
-		&pChannelMap);
-	if (rv == -1)
-	{
-		/* the hCard handle is now invalid
-		 * -> another thread may have called SCardReleaseContext
-		 *    so the mMutex has been unlocked (and is now invalid)
-		 * -> another thread may have called SCardDisconnect
-		 *    so the mMutex is STILL locked
-		 * since we don't know just unlock the mutex */
-		(void)pthread_mutex_unlock(&currentContextMap->mMutex);
-		return SCARD_E_INVALID_HANDLE;
-	}
-
 	scReconnectStruct.hCard = hCard;
 	scReconnectStruct.dwShareMode = dwShareMode;
 	scReconnectStruct.dwPreferredProtocols = dwPreferredProtocols;
@@ -1045,7 +1028,7 @@ LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+	rv = SCardGetContextChannelAndLockFromHandle(hCard, &currentContextMap,
 		&pChannelMap);
 	if (rv == -1)
 	{
@@ -1053,24 +1036,6 @@ LONG SCardDisconnect(SCARDHANDLE hCard, DWORD dwDisposition)
 		goto error;
 	}
 
-	(void)pthread_mutex_lock(&currentContextMap->mMutex);
-
-	/* check the handle is still valid */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
-		&pChannelMap);
-	if (rv == -1)
-		/* the hCard handle is now invalid
-		 * -> another thread may have called SCardReleaseContext
-		 *    so the mMutex has been unlocked (and is now invalid)
-		 * -> another thread may have called SCardDisconnect
-		 *    so the mMutex is STILL locked
-		 * since we don't know just unlock the mutex */
-	{
-		(void)pthread_mutex_unlock(&currentContextMap->mMutex);
-		rv = SCARD_E_INVALID_HANDLE;
-		goto error;
-	}
-
 	scDisconnectStruct.hCard = hCard;
 	scDisconnectStruct.dwDisposition = dwDisposition;
 	scDisconnectStruct.rv = SCARD_S_SUCCESS;
@@ -1151,36 +1116,19 @@ LONG SCardBeginTransaction(SCARDHANDLE hCard)
 	API_TRACE_IN("%ld", hCard)
 
 	/*
-	 * Make sure this handle has been opened
-	 */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
-		&pChannelMap);
-	if (rv == -1)
-		return SCARD_E_INVALID_HANDLE;
-
-	/*
 	 * Query the server every so often until the sharing violation ends
 	 * and then hold the lock for yourself.
 	 */
 
 	for(;;)
 	{
-		(void)pthread_mutex_lock(&currentContextMap->mMutex);
-
-		/* check the handle is still valid */
-		rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+		/*
+		 * Make sure this handle has been opened
+		 */
+		rv = SCardGetContextChannelAndLockFromHandle(hCard, &currentContextMap,
 			&pChannelMap);
 		if (rv == -1)
-		{
-			/* the hCard handle is now invalid
-			 * -> another thread may have called SCardReleaseContext
-			 *    so the mMutex has been unlocked (and is now invalid)
-			 * -> another thread may have called SCardDisconnect
-			 *    so the mMutex is STILL locked
-			 * since we don't know just unlock the mutex */
-			(void)pthread_mutex_unlock(&currentContextMap->mMutex);
 			return SCARD_E_INVALID_HANDLE;
-		}
 
 		scBeginStruct.hCard = hCard;
 		scBeginStruct.rv = SCARD_S_SUCCESS;
@@ -1271,28 +1219,11 @@ LONG SCardEndTransaction(SCARDHANDLE hCard, DWORD dwDisposition)
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+	rv = SCardGetContextChannelAndLockFromHandle(hCard, &currentContextMap,
 		&pChannelMap);
 	if (rv == -1)
 		return SCARD_E_INVALID_HANDLE;
 
-	(void)pthread_mutex_lock(&currentContextMap->mMutex);
-
-	/* check the handle is still valid */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
-		&pChannelMap);
-	if (rv == -1)
-	{
-		/* the hCard handle is now invalid
-		 * -> another thread may have called SCardReleaseContext
-		 *    so the mMutex has been unlocked (and is now invalid)
-		 * -> another thread may have called SCardDisconnect
-		 *    so the mMutex is STILL locked
-		 * since we don't know just unlock the mutex */
-		(void)pthread_mutex_unlock(&currentContextMap->mMutex);
-		return SCARD_E_INVALID_HANDLE;
-	}
-
 	scEndStruct.hCard = hCard;
 	scEndStruct.dwDisposition = dwDisposition;
 	scEndStruct.rv = SCARD_S_SUCCESS;
@@ -1462,33 +1393,16 @@ LONG SCardStatus(SCARDHANDLE hCard, LPSTR mszReaderName,
 	*pcchReaderLen = 0;
 	*pcbAtrLen = 0;
 
-	/*
-	 * Make sure this handle has been opened
-	 */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
-		&pChannelMap);
-	if (rv == -1)
-		return SCARD_E_INVALID_HANDLE;
-
 	/* Retry loop for blocking behaviour */
 retry:
 
-	(void)pthread_mutex_lock(&currentContextMap->mMutex);
-
-	/* check the handle is still valid */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+	/*
+	 * Make sure this handle has been opened
+	 */
+	rv = SCardGetContextChannelAndLockFromHandle(hCard, &currentContextMap,
 		&pChannelMap);
 	if (rv == -1)
-	{
-		/* the hCard handle is now invalid
-		 * -> another thread may have called SCardReleaseContext
-		 *    so the mMutex has been unlocked (and is now invalid)
-		 * -> another thread may have called SCardDisconnect
-		 *    so the mMutex is STILL locked
-		 * since we don't know just unlock the mutex */
-		(void)pthread_mutex_unlock(&currentContextMap->mMutex);
 		return SCARD_E_INVALID_HANDLE;
-	}
 
 	/* synchronize reader states with daemon */
 	rv = getReaderStates(currentContextMap);
@@ -2277,7 +2191,7 @@ LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+	rv = SCardGetContextChannelAndLockFromHandle(hCard, &currentContextMap,
 		&pChannelMap);
 	if (rv == -1)
 	{
@@ -2285,23 +2199,6 @@ LONG SCardControl(SCARDHANDLE hCard, DWORD dwControlCode, LPCVOID pbSendBuffer,
 		return SCARD_E_INVALID_HANDLE;
 	}
 
-	(void)pthread_mutex_lock(&currentContextMap->mMutex);
-
-	/* check the handle is still valid */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
-		&pChannelMap);
-	if (rv == -1)
-	{
-		/* the hCard handle is now invalid
-		 * -> another thread may have called SCardReleaseContext
-		 *    so the mMutex has been unlocked (and is now invalid)
-		 * -> another thread may have called SCardDisconnect
-		 *    so the mMutex is STILL locked
-		 * since we don't know just unlock the mutex */
-		(void)pthread_mutex_unlock(&currentContextMap->mMutex);
-		return SCARD_E_INVALID_HANDLE;
-	}
-
 	if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
 		|| (cbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
 	{
@@ -2578,28 +2475,11 @@ static LONG SCardGetSetAttrib(SCARDHANDLE hCard, int command, DWORD dwAttrId,
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+	rv = SCardGetContextChannelAndLockFromHandle(hCard, &currentContextMap,
 		&pChannelMap);
 	if (rv == -1)
 		return SCARD_E_INVALID_HANDLE;
 
-	(void)pthread_mutex_lock(&currentContextMap->mMutex);
-
-	/* check the handle is still valid */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
-		&pChannelMap);
-	if (rv == -1)
-	{
-		/* the hCard handle is now invalid
-		 * -> another thread may have called SCardReleaseContext
-		 *    so the mMutex has been unlocked (and is now invalid)
-		 * -> another thread may have called SCardDisconnect
-		 *    so the mMutex is STILL locked
-		 * since we don't know just unlock the mutex */
-		(void)pthread_mutex_unlock(&currentContextMap->mMutex);
-		return SCARD_E_INVALID_HANDLE;
-	}
-
 	if (*pcbAttrLen > MAX_BUFFER_SIZE)
 	{
 		rv = SCARD_E_INSUFFICIENT_BUFFER;
@@ -2729,10 +2609,13 @@ LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
 			pcbRecvLength == NULL || pioSendPci == NULL)
 		return SCARD_E_INVALID_PARAMETER;
 
+	/* Retry loop for blocking behaviour */
+retry:
+
 	/*
 	 * Make sure this handle has been opened
 	 */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+	rv = SCardGetContextChannelAndLockFromHandle(hCard, &currentContextMap,
 		&pChannelMap);
 	if (rv == -1)
 	{
@@ -2741,26 +2624,6 @@ LONG SCardTransmit(SCARDHANDLE hCard, const SCARD_IO_REQUEST *pioSendPci,
 		return SCARD_E_INVALID_HANDLE;
 	}
 
-	/* Retry loop for blocking behaviour */
-retry:
-
-	(void)pthread_mutex_lock(&currentContextMap->mMutex);
-
-	/* check the handle is still valid */
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
-		&pChannelMap);
-	if (rv == -1)
-	{
-		/* the hCard handle is now invalid
-		 * -> another thread may have called SCardReleaseContext
-		 *    so the mMutex has been unlocked (and is now invalid)
-		 * -> another thread may have called SCardDisconnect
-		 *    so the mMutex is STILL locked
-		 * since we don't know just unlock the mutex */
-		(void)pthread_mutex_unlock(&currentContextMap->mMutex);
-		return SCARD_E_INVALID_HANDLE;
-	}
-
 	if ((cbSendLength > MAX_BUFFER_SIZE_EXTENDED)
 		|| (*pcbRecvLength > MAX_BUFFER_SIZE_EXTENDED))
 	{
@@ -3492,7 +3355,7 @@ static LONG SCardRemoveHandle(SCARDHANDLE hCard)
 	int lrv;
 	LONG rv;
 
-	rv = SCardGetContextAndChannelFromHandle(hCard, &currentContextMap,
+	rv = SCardGetContextAndChannelFromHandleTH(hCard, &currentContextMap,
 		&currentChannelMap);
 	if (rv == -1)
 		return SCARD_E_INVALID_HANDLE;
@@ -3511,7 +3374,7 @@ static LONG SCardRemoveHandle(SCARDHANDLE hCard)
 	return SCARD_S_SUCCESS;
 }
 
-static LONG SCardGetContextAndChannelFromHandle(SCARDHANDLE hCard,
+static LONG SCardGetContextChannelAndLockFromHandle(SCARDHANDLE hCard,
 	SCONTEXTMAP **targetContextMap, CHANNEL_MAP ** targetChannelMap)
 {
 	LONG rv;
@@ -3522,6 +3385,10 @@ static LONG SCardGetContextAndChannelFromHandle(SCARDHANDLE hCard,
 	(void)SCardLockThread();
 	rv = SCardGetContextAndChannelFromHandleTH(hCard, targetContextMap,
 		targetChannelMap);
+
+	if (SCARD_S_SUCCESS == rv)
+		(void)pthread_mutex_lock(&(*targetContextMap)->mMutex);
+
 	(void)SCardUnlockThread();
 
 	return rv;

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pcsclite/PCSC.git



More information about the Pcsclite-cvs-commit mailing list