aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNIIBE Yutaka <[email protected]>2016-07-20 02:35:05 +0000
committerNIIBE Yutaka <[email protected]>2016-07-20 02:35:05 +0000
commit1598a4476466822e7e9c757ac471089d3db4b545 (patch)
tree652f01c9efcd99562933e223d3d0b6121e85ec6b
parentagent: Add known keys to sshcontrol. (diff)
downloadgnupg-1598a4476466822e7e9c757ac471089d3db4b545.tar.gz
gnupg-1598a4476466822e7e9c757ac471089d3db4b545.zip
scd: Fix card removal/reset on multiple contexts.
* scd/app.c (application_notify_card_reset): Add message for debug. *scd/command.c (update_card_removed): Call release_application and set SLOT -1 here. (struct server_local_s): Remove app_ctx_marked_for_release. (do_reset): Don't mark release but call release_application here. (open_card): Remove app_ctx_marked_for_release handling. (update_reader_status_file): Don't set SLOT here, so that it can be released the APP by application_notify_card_reset in update_card_removed. -- Signed-off-by: NIIBE Yutaka <[email protected]>
Diffstat (limited to '')
-rw-r--r--scd/app.c4
-rw-r--r--scd/command.c84
2 files changed, 47 insertions, 41 deletions
diff --git a/scd/app.c b/scd/app.c
index 51464a2d8..55b8edd12 100644
--- a/scd/app.c
+++ b/scd/app.c
@@ -168,8 +168,12 @@ application_notify_card_reset (int slot)
/* Release the APP, as it's not reusable any more. */
if (lock_table[slot].app)
{
+ if (lock_table[slot].app->ref_count)
+ log_bug ("trying to release active context\n");
+
deallocate_app (lock_table[slot].app);
lock_table[slot].app = NULL;
+ log_debug ("application has been released\n");
}
unlock_reader (slot);
diff --git a/scd/command.c b/scd/command.c
index 5842ee752..d90c32042 100644
--- a/scd/command.c
+++ b/scd/command.c
@@ -129,10 +129,6 @@ struct server_local_s
continue operation. */
int card_removed;
- /* Flag indicating that the application context needs to be released
- at the next opportunity. */
- int app_ctx_marked_for_release;
-
/* A disconnect command has been sent. */
int disconnect_allowed;
@@ -209,14 +205,28 @@ update_card_removed (int vrdr, int value)
return;
for (sl=session_list; sl; sl = sl->next_session)
- if (sl->ctrl_backlink
- && sl->ctrl_backlink->server_local->vreader_idx == vrdr)
- {
- sl->card_removed = value;
- }
+ {
+ ctrl_t ctrl = sl->ctrl_backlink;
+
+ if (ctrl && ctrl->server_local->vreader_idx == vrdr)
+ {
+ sl->card_removed = value;
+ if (value)
+ {
+ struct app_ctx_s *app = ctrl->app_ctx;
+ ctrl->app_ctx = NULL;
+ release_application (app);
+ }
+ }
+ }
+
/* Let the card application layer know about the removal. */
if (value)
- application_notify_card_reset (vreader_slot (vrdr));
+ {
+ log_debug ("Removal of a card: %d\n", vrdr);
+ application_notify_card_reset (vreader_slot (vrdr));
+ vreader_table[vrdr].slot = -1;
+ }
}
@@ -266,23 +276,31 @@ do_reset (ctrl_t ctrl, int send_reset)
if (!(vrdr == -1 || (vrdr >= 0 && vrdr < DIM(vreader_table))))
BUG ();
- /* If there is an active application, release it. Tell all other
- sessions using the same application to release the
- application. */
+ /* If there is an active application, release it. */
if (app)
{
ctrl->app_ctx = NULL;
release_application (app);
- if (send_reset)
+ }
+
+ /* Release the same application which is used by other sessions. */
+ if (send_reset)
+ {
+ struct server_local_s *sl;
+
+ for (sl=session_list; sl; sl = sl->next_session)
{
- struct server_local_s *sl;
+ ctrl_t c = sl->ctrl_backlink;
- for (sl=session_list; sl; sl = sl->next_session)
- if (sl->ctrl_backlink
- && sl->ctrl_backlink->server_local->vreader_idx == vrdr)
- {
- sl->app_ctx_marked_for_release = 1;
- }
+ if (c && c != ctrl && c->server_local->vreader_idx == vrdr)
+ {
+ struct app_ctx_s *app0 = c->app_ctx;
+ if (app0)
+ {
+ c->app_ctx = NULL;
+ release_application (app0);
+ }
+ }
}
}
@@ -300,8 +318,8 @@ do_reset (ctrl_t ctrl, int send_reset)
case SW_HOST_CARD_INACTIVE:
break;
default:
- apdu_close_reader (slot);
- vreader_table[vrdr].slot = slot = -1;
+ apdu_close_reader (slot);
+ vreader_table[vrdr].slot = -1;
break;
}
}
@@ -427,16 +445,6 @@ open_card (ctrl_t ctrl, const char *apptype)
if ( IS_LOCKED (ctrl) )
return gpg_error (GPG_ERR_LOCKED);
- /* If the application has been marked for release do it now. We
- can't do it immediately in do_reset because the application may
- still be in use. */
- if (ctrl->server_local->app_ctx_marked_for_release)
- {
- ctrl->server_local->app_ctx_marked_for_release = 0;
- release_application (ctrl->app_ctx);
- ctrl->app_ctx = NULL;
- }
-
/* If we are already initialized for one specific application we
need to check that the client didn't requested a specific
application different from the one in use before we continue. */
@@ -2031,14 +2039,10 @@ scd_command_handler (ctrl_t ctrl, int fd)
session_list = ctrl->server_local;
ctrl->server_local->ctrl_backlink = ctrl;
ctrl->server_local->assuan_ctx = ctx;
- ctrl->server_local->vreader_idx = -1;
/* We open the reader right at startup so that the ticker is able to
update the status file. */
- if (ctrl->server_local->vreader_idx == -1)
- {
- ctrl->server_local->vreader_idx = get_current_reader ();
- }
+ ctrl->server_local->vreader_idx = get_current_reader ();
/* Command processing loop. */
for (;;)
@@ -2256,9 +2260,7 @@ update_reader_status_file (int set_card_removed_flag)
if (sw_apdu == SW_HOST_NO_READER)
{
/* Most likely the _reader_ has been unplugged. */
- application_notify_card_reset (vr->slot);
- apdu_close_reader (vr->slot);
- vr->slot = -1;
+ apdu_close_reader (vr->slot);
status = 0;
changed = vr->changed;
}