1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-13 00:09:51 +02:00

scd: Fix RESET command handling (more).

* 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>
This commit is contained in:
NIIBE Yutaka 2017-02-17 11:50:40 +09:00
parent 7006352da7
commit 99d4dfe836
3 changed files with 26 additions and 12 deletions

View File

@ -54,6 +54,7 @@ struct app_ctx_s {
const char *apptype; const char *apptype;
unsigned int card_version; unsigned int card_version;
unsigned int card_status; unsigned int card_status;
unsigned int reset_requested:1;
unsigned int periodical_check_needed:1; unsigned int periodical_check_needed:1;
unsigned int did_chv1:1; unsigned int did_chv1:1;
unsigned int force_chv1:1; /* True if the card does not cache CHV1. */ 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, int scan, const unsigned char *serialno_bin,
size_t serialno_bin_len); size_t serialno_bin_len);
char *get_supported_applications (void); 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_munge_serialno (app_t app);
gpg_error_t app_write_learn_status (app_t app, ctrl_t ctrl, gpg_error_t app_write_learn_status (app_t app, ctrl_t ctrl,
unsigned int flags); unsigned int flags);

View File

@ -143,19 +143,23 @@ app_reset (app_t app, ctrl_t ctrl, int send_reset)
if (send_reset) if (send_reset)
{ {
int sw = apdu_reset (app->slot); int sw;
lock_app (app, ctrl);
sw = apdu_reset (app->slot);
if (sw) if (sw)
err = gpg_error (GPG_ERR_CARD_RESET); err = gpg_error (GPG_ERR_CARD_RESET);
/* Release the same application which is used by all sessions. */ app->reset_requested = 1;
send_client_notifications (app, 1); unlock_app (app);
scd_kick_the_loop (); scd_kick_the_loop ();
gnupg_sleep (1); gnupg_sleep (1);
} }
else else
{ {
ctrl->app_ctx = NULL; ctrl->app_ctx = NULL;
release_application (app); release_application (app, 0);
} }
return err; return err;
@ -454,6 +458,8 @@ deallocate_app (app_t app)
} }
xfree (app->serialno); xfree (app->serialno);
unlock_app (app);
xfree (app); xfree (app);
} }
@ -463,7 +469,7 @@ deallocate_app (app_t app)
actually deferring the deallocation to allow for a later reuse by actually deferring the deallocation to allow for a later reuse by
a new connection. */ a new connection. */
void void
release_application (app_t app) release_application (app_t app, int locked_already)
{ {
if (!app) if (!app)
return; return;
@ -473,12 +479,15 @@ release_application (app_t app)
is using the card - this way the PIN cache and other cached data is using the card - this way the PIN cache and other cached data
are preserved. */ are preserved. */
lock_app (app, NULL); if (!locked_already)
lock_app (app, NULL);
if (!app->ref_count) if (!app->ref_count)
log_bug ("trying to release an already released context\n"); log_bug ("trying to release an already released context\n");
--app->ref_count; --app->ref_count;
unlock_app (app); if (!locked_already)
unlock_app (app);
} }
@ -1019,9 +1028,10 @@ scd_update_reader_status_file (void)
int sw; int sw;
unsigned int status; unsigned int status;
lock_app (a, NULL);
app_next = a->next; app_next = a->next;
if (a->ref_count == 0) if (a->reset_requested)
status = 0; status = 0;
else else
{ {
@ -1036,6 +1046,7 @@ scd_update_reader_status_file (void)
/* Get status failed. Ignore that. */ /* Get status failed. Ignore that. */
if (a->periodical_check_needed) if (a->periodical_check_needed)
periodical_check_needed = 1; periodical_check_needed = 1;
unlock_app (a);
continue; continue;
} }
} }
@ -1056,12 +1067,14 @@ scd_update_reader_status_file (void)
a->card_status = status; a->card_status = status;
if (a->periodical_check_needed) if (a->periodical_check_needed)
periodical_check_needed = 1; periodical_check_needed = 1;
unlock_app (a);
} }
} }
else else
{ {
if (a->periodical_check_needed) if (a->periodical_check_needed)
periodical_check_needed = 1; periodical_check_needed = 1;
unlock_app (a);
} }
} }
npth_mutex_unlock (&app_list_lock); npth_mutex_unlock (&app_list_lock);

View 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. */ /* Re-scan USB devices. Release APP, before the scan. */
ctrl->app_ctx = NULL; ctrl->app_ctx = NULL;
release_application (app); release_application (app, 0);
if (serialno) if (serialno)
serialno_bin = hex_to_buffer (serialno, &serialno_bin_len); serialno_bin = hex_to_buffer (serialno, &serialno_bin_len);
@ -1495,7 +1495,7 @@ cmd_restart (assuan_context_t ctx, char *line)
if (app) if (app)
{ {
ctrl->app_ctx = NULL; ctrl->app_ctx = NULL;
release_application (app); release_application (app, 0);
} }
if (locked_session && ctrl->server_local == locked_session) 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->ctrl_backlink->app_ctx = NULL;
sl->card_removed = 1; sl->card_removed = 1;
release_application (app); release_application (app, 1);
} }
if (!sl->event_signal || !sl->assuan_ctx) if (!sl->event_signal || !sl->assuan_ctx)