Address issue with C_Initialize after fork()

Resolves: rhbz#1218797
This commit is contained in:
Nikos Mavrogiannopoulos 2015-07-14 11:12:12 +02:00
parent 798fb5ed71
commit c7c9618926
2 changed files with 233 additions and 0 deletions

View File

@ -0,0 +1,228 @@
diff --git a/src/libopensc/ctx.c b/src/libopensc/ctx.c
index 4670008..26f8bf5 100644
--- a/src/libopensc/ctx.c
+++ b/src/libopensc/ctx.c
@@ -791,19 +791,21 @@ int sc_wait_for_event(sc_context_t *ctx, unsigned int event_mask, sc_reader_t **
}
-int sc_release_context(sc_context_t *ctx)
+static
+int __sc_release_context(sc_context_t *ctx, unsigned after_fork)
{
unsigned int i;
assert(ctx != NULL);
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
+
while (list_size(&ctx->readers)) {
sc_reader_t *rdr = (sc_reader_t *) list_get_at(&ctx->readers, 0);
_sc_delete_reader(ctx, rdr);
}
if (ctx->reader_driver->ops->finish != NULL)
- ctx->reader_driver->ops->finish(ctx);
+ ctx->reader_driver->ops->finish(ctx, after_fork);
for (i = 0; ctx->card_drivers[i]; i++) {
struct sc_card_driver *drv = ctx->card_drivers[i];
@@ -836,6 +838,16 @@ int sc_release_context(sc_context_t *ctx)
return SC_SUCCESS;
}
+int sc_release_context(sc_context_t *ctx)
+{
+ return __sc_release_context(ctx, 0);
+}
+
+int sc_terminate_context(sc_context_t *ctx)
+{
+ return __sc_release_context(ctx, 1);
+}
+
int sc_set_card_driver(sc_context_t *ctx, const char *short_name)
{
int i = 0, match = 0;
diff --git a/src/libopensc/libopensc.exports b/src/libopensc/libopensc.exports
index cea8d42..ed84ffe 100644
--- a/src/libopensc/libopensc.exports
+++ b/src/libopensc/libopensc.exports
@@ -244,6 +244,7 @@ sc_put_data
sc_read_binary
sc_read_record
sc_release_context
+sc_terminate_context
sc_reset
sc_reset_retry_counter
sc_restore_security_env
diff --git a/src/libopensc/opensc.h b/src/libopensc/opensc.h
index ad5405d..437a14d 100644
--- a/src/libopensc/opensc.h
+++ b/src/libopensc/opensc.h
@@ -374,7 +374,7 @@ struct sc_reader_operations {
int (*init)(struct sc_context *ctx);
/* Called when the driver is being unloaded. finish() has to
* release any resources. */
- int (*finish)(struct sc_context *ctx);
+ int (*finish)(struct sc_context *ctx, unsigned after_fork);
/* Called when library wish to detect new readers
* should add only new readers. */
int (*detect_readers)(struct sc_context *ctx);
@@ -752,6 +752,12 @@ int sc_context_create(sc_context_t **ctx, const sc_context_param_t *parm);
int sc_release_context(sc_context_t *ctx);
/**
+ * Releases an established OpenSC context without releasing any state that is shared with parent process
+ * @param ctx A pointer to the context structure to be released
+ */
+int sc_terminate_context(sc_context_t *ctx);
+
+/**
* Detect new readers available on system.
* @param ctx OpenSC context
* @return SC_SUCCESS on success and an error code otherwise.
diff --git a/src/libopensc/reader-ctapi.c b/src/libopensc/reader-ctapi.c
index 919c3f0..e252a42 100644
--- a/src/libopensc/reader-ctapi.c
+++ b/src/libopensc/reader-ctapi.c
@@ -514,7 +514,7 @@ static int ctapi_init(sc_context_t *ctx)
return 0;
}
-static int ctapi_finish(sc_context_t *ctx)
+static int ctapi_finish(sc_context_t *ctx, unsigned after_fork)
{
struct ctapi_global_private_data *priv = (struct ctapi_global_private_data *) ctx->reader_drv_data;
diff --git a/src/libopensc/reader-openct.c b/src/libopensc/reader-openct.c
index a276d52..32871d0 100644
--- a/src/libopensc/reader-openct.c
+++ b/src/libopensc/reader-openct.c
@@ -29,7 +29,7 @@
/* function declarations */
static int openct_reader_init(sc_context_t *ctx);
static int openct_add_reader(sc_context_t *ctx, unsigned int num, ct_info_t *info);
-static int openct_reader_finish(sc_context_t *ctx);
+static int openct_reader_finish(sc_context_t *ctx, unsigned after_fork);
static int openct_reader_release(sc_reader_t *reader);
static int openct_reader_detect_card_presence(sc_reader_t *reader);
static int openct_reader_connect(sc_reader_t *reader);
@@ -137,7 +137,7 @@ openct_add_reader(sc_context_t *ctx, unsigned int num, ct_info_t *info)
* Called when the driver is being unloaded. finish() has to
* deallocate the private data and any resources.
*/
-static int openct_reader_finish(sc_context_t *ctx)
+static int openct_reader_finish(sc_context_t *ctx, unsigned after_fork)
{
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_VERBOSE);
return SC_SUCCESS;
diff --git a/src/libopensc/reader-pcsc.c b/src/libopensc/reader-pcsc.c
index 7382452..cf5890d 100644
--- a/src/libopensc/reader-pcsc.c
+++ b/src/libopensc/reader-pcsc.c
@@ -740,14 +740,14 @@ out:
return ret;
}
-static int pcsc_finish(sc_context_t *ctx)
+static int pcsc_finish(sc_context_t *ctx, unsigned after_fork)
{
struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) ctx->reader_drv_data;
SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_NORMAL);
if (gpriv) {
- if (gpriv->pcsc_ctx != -1)
+ if (!after_fork && gpriv->pcsc_ctx != -1)
gpriv->SCardReleaseContext(gpriv->pcsc_ctx);
if (gpriv->dlhandle != NULL)
sc_dlclose(gpriv->dlhandle);
@@ -2096,7 +2096,7 @@ out:
return ret;
}
-static int cardmod_finish(sc_context_t *ctx)
+static int cardmod_finish(sc_context_t *ctx, unsigned after_fork)
{
struct pcsc_global_private_data *gpriv = (struct pcsc_global_private_data *) ctx->reader_drv_data;
diff --git a/src/pkcs11/pkcs11-global.c b/src/pkcs11/pkcs11-global.c
index ee6cf7c..886476e 100644
--- a/src/pkcs11/pkcs11-global.c
+++ b/src/pkcs11/pkcs11-global.c
@@ -40,6 +40,7 @@ list_t virtual_slots;
pid_t initialized_pid = (pid_t)-1;
#endif
static int in_finalize = 0;
+static CK_RV __sc_pkcs11_finalize(CK_VOID_PTR pReserved, unsigned after_fork);
extern CK_FUNCTION_LIST pkcs11_function_list;
#if defined(HAVE_PTHREAD) && defined(PKCS11_THREAD_LOCKING)
@@ -205,7 +206,7 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
/* Handle fork() exception */
#if !defined(_WIN32)
if (current_pid != initialized_pid) {
- C_Finalize(NULL_PTR);
+ __sc_pkcs11_finalize(NULL_PTR, 1);
}
initialized_pid = current_pid;
in_finalize = 0;
@@ -271,7 +272,8 @@ out:
return rv;
}
-CK_RV C_Finalize(CK_VOID_PTR pReserved)
+static
+CK_RV __sc_pkcs11_finalize(CK_VOID_PTR pReserved, unsigned after_fork)
{
int i;
void *p;
@@ -292,10 +294,14 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved)
/* cancel pending calls */
in_finalize = 1;
- sc_cancel(context);
- /* remove all cards from readers */
- for (i=0; i < (int)sc_ctx_get_reader_count(context); i++)
- card_removed(sc_ctx_get_reader(context, i));
+
+ if (!after_fork) {
+ sc_cancel(context);
+
+ /* remove all cards from readers */
+ for (i=0; i < (int)sc_ctx_get_reader_count(context); i++)
+ card_removed(sc_ctx_get_reader(context, i));
+ }
while ((p = list_fetch(&sessions)))
free(p);
@@ -307,7 +313,10 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved)
}
list_destroy(&virtual_slots);
- sc_release_context(context);
+ if (after_fork)
+ sc_terminate_context(context);
+ else
+ sc_release_context(context);
context = NULL;
/* Release and destroy the mutex */
@@ -316,6 +325,17 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved)
return rv;
}
+CK_RV C_Finalize(CK_VOID_PTR pReserved)
+{
+#if !defined(_WIN32)
+ pid_t current_pid = getpid();
+ if (current_pid != initialized_pid) {
+ return __sc_pkcs11_finalize(NULL_PTR, 1);
+ }
+#endif
+ return __sc_pkcs11_finalize(pReserved, 0);
+}
+
CK_RV C_GetInfo(CK_INFO_PTR pInfo)
{
CK_RV rv = CKR_OK;

View File

@ -20,6 +20,8 @@ Requires: pcsc-lite
Obsoletes: mozilla-opensc-signer < 0.12.0 Obsoletes: mozilla-opensc-signer < 0.12.0
Obsoletes: opensc-devel < 0.12.0 Obsoletes: opensc-devel < 0.12.0
Patch0: opensc-0.15.0-fork-issue.patch
%description %description
OpenSC provides a set of libraries and utilities to work with smart cards. Its OpenSC provides a set of libraries and utilities to work with smart cards. Its
main focus is on cards that support cryptographic operations, and facilitate main focus is on cards that support cryptographic operations, and facilitate
@ -33,6 +35,8 @@ every software/card that does so, too.
%prep %prep
%setup -q -n OpenSC-%{version} %setup -q -n OpenSC-%{version}
%patch0 -p1 -b .fork-issue
cp -p src/pkcs15init/README ./README.pkcs15init cp -p src/pkcs15init/README ./README.pkcs15init
cp -p src/scconf/README.scconf . cp -p src/scconf/README.scconf .
# No {_libdir} here to avoid multilib conflicts; it's just an example # No {_libdir} here to avoid multilib conflicts; it's just an example
@ -135,6 +139,7 @@ rm -rf %{buildroot}%{_sysconfdir}/bash_completion.d/
%changelog %changelog
* Tue Jul 14 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> - 0.15.0-1 * Tue Jul 14 2015 Nikos Mavrogiannopoulos <nmav@redhat.com> - 0.15.0-1
- Update to 0.15.0 (#1209682) - Update to 0.15.0 (#1209682)
- Solve issue with C_Initialize after fork() (#1218797)
* Thu Jun 18 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.14.0-3 * Thu Jun 18 2015 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 0.14.0-3
- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild - Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild