scd: Fix "Conflicting usage" bug.
authorNIIBE Yutaka <gniibe@fsij.org>
Thu, 3 Dec 2015 02:26:24 +0000 (11:26 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Thu, 3 Dec 2015 02:26:24 +0000 (11:26 +0900)
* scd/apdu.c (apdu_close_reader): Call CLOSE_READER method even if we
  got an error from apdu_disconnect.
* scd/app-common.h (no_reuse): Remove.
* scd/app.c (application_notify_card_reset): Deallocate APP here.
(select_application, release_application): Don't use NO_REUSE.

--

Reproducible scenario: Invoke gpg --card-edit session from a terminal.
Invoke another gpg --card-edit session from another.  Remove a token.
Insert a token again.  Type RET on both terminals.  One of terminal
answers "Conflicting usage".

Perhaps, having NO_REUSE field was to avoid race conditions.  Now,
APP can be safely deallocated by application_notify_card_reset.

Thanks to the2nd.

scd/apdu.c
scd/app-common.h
scd/app.c

index eb3d4b6..95a2561 100644 (file)
@@ -3215,9 +3215,12 @@ apdu_close_reader (int slot)
   sw = apdu_disconnect (slot);
   if (sw)
     {
   sw = apdu_disconnect (slot);
   if (sw)
     {
+      /*
+       * When the reader/token was removed it might come here.
+       * It should go through to call CLOSE_READER even if we got an error.
+       */
       if (DBG_READER)
       if (DBG_READER)
-        log_debug ("leave: apdu_close_reader => 0x%x (apdu_disconnect)\n", sw);
-      return sw;
+        log_debug ("apdu_close_reader => 0x%x (apdu_disconnect)\n", sw);
     }
   if (reader_table[slot].close_reader)
     {
     }
   if (reader_table[slot].close_reader)
     {
index 379bcd1..b4bb55b 100644 (file)
@@ -47,11 +47,6 @@ struct app_ctx_s {
      operations the particular function pointer is set to NULL */
   unsigned int ref_count;
 
      operations the particular function pointer is set to NULL */
   unsigned int ref_count;
 
-  /* Flag indicating that a reset has been done for that application
-     and that this context is merely lingering and just should not be
-     reused.  */
-  int no_reuse;
-
   /* Used reader slot. */
   int slot;
 
   /* Used reader slot. */
   int slot;
 
index 49e08e6..5e6751e 100644 (file)
--- a/scd/app.c
+++ b/scd/app.c
@@ -175,9 +175,12 @@ application_notify_card_reset (int slot)
   /* FIXME: We are ignoring any error value here.  */
   lock_reader (slot, NULL);
 
   /* FIXME: We are ignoring any error value here.  */
   lock_reader (slot, NULL);
 
-  /* Mark application as non-reusable.  */
+  /* Release the APP, as it's not reusable any more.  */
   if (lock_table[slot].app)
   if (lock_table[slot].app)
-    lock_table[slot].app->no_reuse = 1;
+    {
+      deallocate_app (lock_table[slot].app);
+      lock_table[slot].app = NULL;
+    }
 
   /* Deallocate a saved application for that slot, so that we won't
      try to reuse it.  If there is no saved application, set a flag so
 
   /* Deallocate a saved application for that slot, so that we won't
      try to reuse it.  If there is no saved application, set a flag so
@@ -251,16 +254,6 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
         return gpg_error (GPG_ERR_CONFLICT);
       }
 
         return gpg_error (GPG_ERR_CONFLICT);
       }
 
-  /* Don't use a non-reusable marked application.  */
-  if (app && app->no_reuse)
-    {
-      unlock_reader (slot);
-      log_info ("lingering application '%s' in use by reader %d"
-                " - can't switch\n",
-                app->apptype? app->apptype:"?", slot);
-      return gpg_error (GPG_ERR_CONFLICT);
-    }
-
   /* If we don't have an app, check whether we have a saved
      application for that slot.  This is useful so that a card does
      not get reset even if only one session is using the card - this
   /* If we don't have an app, check whether we have a saved
      application for that slot.  This is useful so that a card does
      not get reset even if only one session is using the card - this
@@ -495,15 +488,7 @@ release_application (app_t app)
 
   if (lock_table[slot].last_app)
     deallocate_app (lock_table[slot].last_app);
 
   if (lock_table[slot].last_app)
     deallocate_app (lock_table[slot].last_app);
-  if (app->no_reuse)
-    {
-      /* If we shall not re-use the application we can't save it for
-         later use. */
-      deallocate_app (app);
-      lock_table[slot].last_app = NULL;
-    }
-  else
-    lock_table[slot].last_app = lock_table[slot].app;
+  lock_table[slot].last_app = lock_table[slot].app;
   lock_table[slot].app = NULL;
   unlock_reader (slot);
 }
   lock_table[slot].app = NULL;
   unlock_reader (slot);
 }