1
0
mirror of git://git.gnupg.org/gnupg.git synced 2025-05-19 09:02:22 +02:00

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 <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2016-07-20 11:35:05 +09:00
parent 270f7f7b8b
commit 1598a44764
2 changed files with 48 additions and 42 deletions

View File

@ -168,8 +168,12 @@ application_notify_card_reset (int slot)
/* Release the APP, as it's not reusable any more. */ /* Release the APP, as it's not reusable any more. */
if (lock_table[slot].app) 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); deallocate_app (lock_table[slot].app);
lock_table[slot].app = NULL; lock_table[slot].app = NULL;
log_debug ("application has been released\n");
} }
unlock_reader (slot); unlock_reader (slot);

View File

@ -129,10 +129,6 @@ struct server_local_s
continue operation. */ continue operation. */
int card_removed; 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. */ /* A disconnect command has been sent. */
int disconnect_allowed; int disconnect_allowed;
@ -209,14 +205,28 @@ update_card_removed (int vrdr, int value)
return; return;
for (sl=session_list; sl; sl = sl->next_session) for (sl=session_list; sl; sl = sl->next_session)
if (sl->ctrl_backlink {
&& sl->ctrl_backlink->server_local->vreader_idx == vrdr) ctrl_t ctrl = sl->ctrl_backlink;
if (ctrl && ctrl->server_local->vreader_idx == vrdr)
{ {
sl->card_removed = value; 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. */ /* Let the card application layer know about the removal. */
if (value) if (value)
{
log_debug ("Removal of a card: %d\n", vrdr);
application_notify_card_reset (vreader_slot (vrdr)); application_notify_card_reset (vreader_slot (vrdr));
vreader_table[vrdr].slot = -1;
}
} }
@ -266,22 +276,30 @@ do_reset (ctrl_t ctrl, int send_reset)
if (!(vrdr == -1 || (vrdr >= 0 && vrdr < DIM(vreader_table)))) if (!(vrdr == -1 || (vrdr >= 0 && vrdr < DIM(vreader_table))))
BUG (); BUG ();
/* If there is an active application, release it. Tell all other /* If there is an active application, release it. */
sessions using the same application to release the
application. */
if (app) if (app)
{ {
ctrl->app_ctx = NULL; ctrl->app_ctx = NULL;
release_application (app); release_application (app);
}
/* Release the same application which is used by other sessions. */
if (send_reset) if (send_reset)
{ {
struct server_local_s *sl; struct server_local_s *sl;
for (sl=session_list; sl; sl = sl->next_session) 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; ctrl_t c = sl->ctrl_backlink;
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);
}
} }
} }
} }
@ -301,7 +319,7 @@ do_reset (ctrl_t ctrl, int send_reset)
break; break;
default: default:
apdu_close_reader (slot); apdu_close_reader (slot);
vreader_table[vrdr].slot = slot = -1; vreader_table[vrdr].slot = -1;
break; break;
} }
} }
@ -427,16 +445,6 @@ open_card (ctrl_t ctrl, const char *apptype)
if ( IS_LOCKED (ctrl) ) if ( IS_LOCKED (ctrl) )
return gpg_error (GPG_ERR_LOCKED); 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 /* If we are already initialized for one specific application we
need to check that the client didn't requested a specific need to check that the client didn't requested a specific
application different from the one in use before we continue. */ 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; session_list = ctrl->server_local;
ctrl->server_local->ctrl_backlink = ctrl; ctrl->server_local->ctrl_backlink = ctrl;
ctrl->server_local->assuan_ctx = ctx; 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 /* We open the reader right at startup so that the ticker is able to
update the status file. */ 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. */ /* Command processing loop. */
for (;;) for (;;)
@ -2256,9 +2260,7 @@ update_reader_status_file (int set_card_removed_flag)
if (sw_apdu == SW_HOST_NO_READER) if (sw_apdu == SW_HOST_NO_READER)
{ {
/* Most likely the _reader_ has been unplugged. */ /* Most likely the _reader_ has been unplugged. */
application_notify_card_reset (vr->slot);
apdu_close_reader (vr->slot); apdu_close_reader (vr->slot);
vr->slot = -1;
status = 0; status = 0;
changed = vr->changed; changed = vr->changed;
} }