scd: Fix RESET command handling (more).
authorNIIBE Yutaka <gniibe@fsij.org>
Fri, 17 Feb 2017 02:50:40 +0000 (11:50 +0900)
committerNIIBE Yutaka <gniibe@fsij.org>
Fri, 17 Feb 2017 02:50:40 +0000 (11:50 +0900)
* scd/app-common.h (struct app_ctx_s): Add reset_requested.
* scd/app.c (app_reset): Locking APP, set reset_requested.
(deallocate_app): Release the lock.
(release_application): Add LOCKED_ALREADY argument.
(scd_update_reader_status_file): Hold the lock when accessing APP.
When reset_requested is set, close the reader and deallocate APP.
* scd/command.c (open_card_with_request, cmd_restart): Follow the
change of release_application.
(send_client_notifications): Here it calls release_application holding
the lock.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
scd/app-common.h
scd/app.c
scd/command.c

index c79e36b..38e6cc6 100644 (file)
@@ -54,6 +54,7 @@ struct app_ctx_s {
   const char *apptype;
   unsigned int card_version;
   unsigned int card_status;
+  unsigned int reset_requested:1;
   unsigned int periodical_check_needed:1;
   unsigned int did_chv1:1;
   unsigned int force_chv1:1;   /* True if the card does not cache CHV1. */
@@ -132,7 +133,7 @@ gpg_error_t select_application (ctrl_t ctrl, const char *name, app_t *r_app,
                                 int scan, const unsigned char *serialno_bin,
                                 size_t serialno_bin_len);
 char *get_supported_applications (void);
-void release_application (app_t app);
+void release_application (app_t app, int locked_already);
 gpg_error_t app_munge_serialno (app_t app);
 gpg_error_t app_write_learn_status (app_t app, ctrl_t ctrl,
                                     unsigned int flags);
index b6f3a05..1d81631 100644 (file)
--- a/scd/app.c
+++ b/scd/app.c
@@ -143,19 +143,23 @@ app_reset (app_t app, ctrl_t ctrl, int send_reset)
 
   if (send_reset)
     {
-      int sw = apdu_reset (app->slot);
+      int sw;
+
+      lock_app (app, ctrl);
+      sw = apdu_reset (app->slot);
       if (sw)
         err = gpg_error (GPG_ERR_CARD_RESET);
 
-      /* Release the same application which is used by all sessions.  */
-      send_client_notifications (app, 1);
+      app->reset_requested = 1;
+      unlock_app (app);
+
       scd_kick_the_loop ();
       gnupg_sleep (1);
     }
   else
     {
       ctrl->app_ctx = NULL;
-      release_application (app);
+      release_application (app, 0);
     }
 
   return err;
@@ -454,6 +458,8 @@ deallocate_app (app_t app)
     }
 
   xfree (app->serialno);
+
+  unlock_app (app);
   xfree (app);
 }
 
@@ -463,7 +469,7 @@ deallocate_app (app_t app)
    actually deferring the deallocation to allow for a later reuse by
    a new connection. */
 void
-release_application (app_t app)
+release_application (app_t app, int locked_already)
 {
   if (!app)
     return;
@@ -473,12 +479,15 @@ release_application (app_t app)
      is using the card - this way the PIN cache and other cached data
      are preserved.  */
 
-  lock_app (app, NULL);
+  if (!locked_already)
+    lock_app (app, NULL);
+
   if (!app->ref_count)
     log_bug ("trying to release an already released context\n");
 
   --app->ref_count;
-  unlock_app (app);
+  if (!locked_already)
+    unlock_app (app);
 }
 
 
@@ -1019,9 +1028,10 @@ scd_update_reader_status_file (void)
       int sw;
       unsigned int status;
 
+      lock_app (a, NULL);
       app_next = a->next;
 
-      if (a->ref_count == 0)
+      if (a->reset_requested)
         status = 0;
       else
         {
@@ -1036,6 +1046,7 @@ scd_update_reader_status_file (void)
               /* Get status failed.  Ignore that.  */
               if (a->periodical_check_needed)
                 periodical_check_needed = 1;
+              unlock_app (a);
               continue;
             }
         }
@@ -1056,12 +1067,14 @@ scd_update_reader_status_file (void)
               a->card_status = status;
               if (a->periodical_check_needed)
                 periodical_check_needed = 1;
+              unlock_app (a);
             }
         }
       else
         {
           if (a->periodical_check_needed)
             periodical_check_needed = 1;
+          unlock_app (a);
         }
     }
   npth_mutex_unlock (&app_list_lock);
index bd7e803..5b7ddc8 100644 (file)
@@ -227,7 +227,7 @@ open_card_with_request (ctrl_t ctrl, const char *apptype, const char *serialno)
 
   /* Re-scan USB devices.  Release APP, before the scan.  */
   ctrl->app_ctx = NULL;
-  release_application (app);
+  release_application (app, 0);
 
   if (serialno)
     serialno_bin = hex_to_buffer (serialno, &serialno_bin_len);
@@ -1495,7 +1495,7 @@ cmd_restart (assuan_context_t ctx, char *line)
   if (app)
     {
       ctrl->app_ctx = NULL;
-      release_application (app);
+      release_application (app, 0);
     }
   if (locked_session && ctrl->server_local == locked_session)
     {
@@ -1922,7 +1922,7 @@ send_client_notifications (app_t app, int removal)
           {
             sl->ctrl_backlink->app_ctx = NULL;
             sl->card_removed = 1;
-            release_application (app);
+            release_application (app, 1);
           }
 
         if (!sl->event_signal || !sl->assuan_ctx)