scd: Fix "Conflicting usage" bug.

* 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.

(backport of commit f42c50dbf0)
This commit is contained in:
NIIBE Yutaka 2015-12-03 11:26:24 +09:00
parent 01fa4c7b8b
commit 9934889415
3 changed files with 13 additions and 27 deletions

View File

@ -3136,7 +3136,13 @@ apdu_close_reader (int slot)
return SW_HOST_NO_DRIVER;
sw = apdu_disconnect (slot);
if (sw)
return 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.
*/
log_debug ("apdu_close_reader => 0x%x (apdu_disconnect)\n", sw);
}
if (reader_table[slot].close_reader)
return reader_table[slot].close_reader (slot);
return SW_HOST_NOT_SUPPORTED;

View File

@ -44,11 +44,6 @@ struct app_ctx_s {
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;

View File

@ -190,9 +190,12 @@ application_notify_card_reset (int slot)
/* 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)
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
@ -265,16 +268,6 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
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
@ -506,15 +499,7 @@ release_application (app_t 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);
}