scd: a race condition between scd_command_handler and handle_tick

Niibe Yutaka gniibe at fsij.org
Wed Apr 4 03:43:55 CEST 2012


This is a bug report for GnuPG 2.0.19 (or 2.0.18).  I have not yet
checked if there is this bug in the development version or not.

This bug was found at "make check" of building scute 1.4.0 for Debian.
I think that it is a bug of a race condition.

Here are failure logs:

https://buildd.debian.org/status/fetch.php?pkg=scute&arch=armel&ver=1.4.0-2&stamp=1333006067
https://buildd.debian.org/status/fetch.php?pkg=scute&arch=ia64&ver=1.4.0-3&stamp=1333361223

It surely occured on other non-exotic architectures.  In fact, I
encountered on my amd64 box too (sorry, I lost the log).


NORMAL CASE:
Since the build environment doesn't have libpcsclite.so.1, pcsc daemon
wrappers fails at start up, and it results "Card error".

In the log, it's like:
-----------------------
gpg-agent[27706]: can't create directory `/home/buildd/.gnupg': No such file or directory
scdaemon[27707]: error sending PC/SC OPEN request: Broken pipe
gpg-agent[27706]: command learn failed: Card error
Skipping test because no token is present.
PASS: t-opensession
-----------------------

BUG CASE:
It seemed that opening PC/SC driver somehow succeeded wrongly after an
failure, and it tried to send APDUs to a reader which failed.  In this
case, the error code is "Not supported", and it resulted failure of
scute's test.

In the log, it's like:
-----------------------
gpg-agent[27735]: can't create directory `/home/buildd/.gnupg': No such file or directory
scdaemon[27736]: error sending PC/SC OPEN request: Broken pipe
scdaemon[27736]: apdu_send_simple(0) failed: not supported
scdaemon[27736]: apdu_send_simple(0) failed: not supported
scdaemon[27736]: apdu_send_simple(0) failed: not supported
scdaemon[27736]: apdu_send_simple(0) failed: not supported
scdaemon[27736]: apdu_send_simple(0) failed: not supported
scdaemon[27736]: apdu_send_simple(0) failed: not supported
scdaemon[27736]: apdu_send_simple(0) failed: not supported
scdaemon[27736]: apdu_send_simple(0) failed: not supported
scdaemon[27736]: no supported card application found: Not supported
gpg-agent[27735]: command learn failed: Not supported
t-closeallsessions.c:48: Function failed
FAIL: t-closeallsessions
-----------------------

For NORMAL CASE, the function open_card failed correctly, as
apdu_connect failed because reader_table[slot].used == 0.

For the BUG CASE, there is a race condition between two threads, the
command handler thread and handle_tick thread.

COMMAND HANDLER THREAD's call-chain is like:
-> scd_command_handler
  -> cmd_serialno
    -> open_card
      ->apdu_connect

HANDLE_TICK THREAD's call-chain is like:
-> handle_tick
  -> scd_update_reader_status_file
    -> update_reader_status_file
      -> get_reader_slot
        -> apdu_open_reader
          -> open_pcsc_reader
            -> open_pcsc_reader_wrapper
              -> new_reader_slot
              Then, forking gnupg-pcsc-wrapper...

For the BUG CASE, it could be considered it goes like this: 

HANDLE_TICK_THREAD                  COMMAND HANDLER THREAD

                                    enter scd_command_handler
                                          ctrl->reader_slot = 0
enter handle_tick
...
enter new_reader_slot
      reader_table[slot].used = 1
forking gnupg-pcsc-wrapper and
thread switch occurs
                                    enter cmd_serialno
                                    enter open_card
                                    enter apdu_connect
                                    *** It succeeds,                    ***
                                    *** as reader_table[slot].used == 1 ***
                                    exit  apdu_connect with success
failure of gnupg-pcsc-wrapper...
                                    tries sending apdu... 


I think that we need mutual exclusion between threads as
there is a shared resource (the connection to gnupg-pcsc-wrapper).
-- 



More information about the Gnupg-devel mailing list