Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Concurrency issue with SCardCancel and SCardGetStatusChange timeout #160

Closed
jjanku opened this issue Nov 2, 2023 · 1 comment
Closed

Comments

@jjanku
Copy link

jjanku commented Nov 2, 2023

Versions

  • smart card reader driver name and version: no reader
  • pcsc-lite version: 1.9.9-3.fc38
  • the output of the command /usr/sbin/pcscd --version:
pcsc-lite version 1.9.9.
Copyright (C) 1999-2002 by David Corcoran <corcoran@musclecard.com>.
Copyright (C) 2001-2022 by Ludovic Rousseau <ludovic.rousseau@free.fr>.
Copyright (C) 2003-2004 by Damien Sauveron <sauveron@labri.fr>.
Report bugs to <pcsclite-muscle@lists.infradead.org>.
Enabled features: Linux x86_64-redhat-linux-gnu libsystemd serial usb libudev usbdropdir=/usr/lib64/pcsc/drivers ipcdir=/run/pcscd filter configdir=/etc/reader.conf.d
MAX_READERNAME: 128, PCSCLITE_MAX_READERS_CONTEXTS: 16

Platform

  • Operating system or GNU/Linux distribution name and version: Fedora 38 (6.5.7-200.fc38.x86_64)
  • Smart card middleware name and version
  • Smart card reader manufacturer name and reader model name: no reader
  • Smart card name: no card

Issue

When SCardCancel is called around the time when SCardGetStatusChange times out, it returns SCARD_E_INVALID_HANDLE. I would expect SCardCancel to either cancel SCardGetStatusChange (if it runs before the timeout) or do nothing and succeed (if it runs after the timeout).

Python script to reproduce the issue (based on SCardCancel.py):

#! /usr/bin/env python3

#   SCardCancel.py : Unitary test for SCardCancel()
#   Copyright (C) 2008-2009  Ludovic Rousseau
#
#   This program is free software; you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation; either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License along
#   with this program; if not, see <http://www.gnu.org/licenses/>.


from smartcard.scard import *
from smartcard.pcsc.PCSCExceptions import *
import threading
import time


def cancel():
    time.sleep(1)
    print("cancel")
    hresult = SCardCancel(hcontext)
    if hresult != 0:
        print('Failed to SCardCancel: ' + SCardGetErrorMessage(hresult))

hresult, hcontext = SCardEstablishContext(SCARD_SCOPE_USER)
if hresult != SCARD_S_SUCCESS:
    raise EstablishContextException(hresult)

readers = [r'\\?PnP?\Notification']
print('PC/SC Readers:', readers)

readerstates = {}
for reader in readers:
    readerstates[reader] = (reader, SCARD_STATE_UNAWARE)

t = threading.Thread(target=cancel)
t.start()

# increasing or decreasing the timeout by about 50 ms solves the issue
hresult, newstates = SCardGetStatusChange(hcontext, 1000,
        list(readerstates.values()))
print("SCardGetStatusChange()", SCardGetErrorMessage(hresult))
if hresult != SCARD_S_SUCCESS and hresult != SCARD_E_TIMEOUT:
    if SCARD_E_CANCELLED == hresult:
        pass
    else:
        raise BaseSCardException(hresult)

t.join()

hresult = SCardReleaseContext(hcontext)
print("SCardReleaseContext()", SCardGetErrorMessage(hresult))
if hresult != SCARD_S_SUCCESS:
    raise ReleaseContextException(hresult)

Log

Output from the script above:

PC/SC Readers: ['\\\\?PnP?\\Notification']
cancel
SCardGetStatusChange() Command timeout.
Failed to SCardCancel: Invalid handle.
SCardReleaseContext() Command successful.

Output from pcscd:
log.txt

@LudovicRousseau
Copy link
Owner

Fixed.
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants