If dynamically-loadable ENGINEs are linked against a shared-library version
authorGeoff Thorpe <geoff@openssl.org>
Fri, 18 Oct 2002 20:45:38 +0000 (20:45 +0000)
committerGeoff Thorpe <geoff@openssl.org>
Fri, 18 Oct 2002 20:45:38 +0000 (20:45 +0000)
of libcrypto, then it is possible that when they are loaded they will share
the same static data as the loading application/library. This means it will
be too late to set memory/ERR/ex_data/[etc] callbacks, but entirely
unnecessary to try. This change puts a static variable in the core ENGINE
code (contained in libcrypto) and a function returning a pointer to it. If
the loaded ENGINE's return value from this function matches the loading
application/library's return value - they share static data. If they don't
match, the loaded ENGINE has its own copy of libcrypto's static data and so
the callbacks need to be set.

Also, although 0.9.7 hasn't been released yet, it's clear this will
introduce a binary incompatibility between dynamic ENGINEs built for 0.9.7
and 0.9.8 (though others probably exist already from EC_*** hooks and
what-not) - so the version control values are correspondingly bumped.

crypto/engine/eng_dyn.c
crypto/engine/eng_lib.c
crypto/engine/engine.h

index 5803c0123a0a22637a6fd6c685c24ec3ce2f503e..61ae230570dcc49ea7e6ae6d7ce3900af2c1cea7 100644 (file)
@@ -500,6 +500,7 @@ static int dynamic_load(ENGINE *e, dynamic_data_ctx *ctx)
         * engine.h, much of this would be simplified if each area of code
         * provided its own "summary" structure of all related callbacks. It
         * would also increase opaqueness. */
+       fns.static_state = ENGINE_get_static_state();
        fns.err_fns = ERR_get_implementation();
        fns.ex_data_fns = CRYPTO_get_ex_data_implementation();
        CRYPTO_get_mem_functions(&fns.mem_fns.malloc_cb,
index a66d0f08af26d8293aa768897138fb0a2f2ff365..999061a8ed828c2a763505462e15522cee122b7f 100644 (file)
@@ -319,3 +319,13 @@ const ENGINE_CMD_DEFN *ENGINE_get_cmd_defns(const ENGINE *e)
        {
        return e->cmd_defns;
        }
+
+/* eng_lib.o is pretty much linked into anything that touches ENGINE already, so
+ * put the "static_state" hack here. */
+
+static int internal_static_hack = 0;
+
+void *ENGINE_get_static_state(void)
+       {
+       return &internal_static_hack;
+       }
index 0d35b0152dca6cf5552176b259a1c4bcf6f36733..77663742aaf84075a34d42c74cdb4c36ef6ec3ac 100644 (file)
@@ -567,17 +567,20 @@ void ENGINE_add_conf_module(void);
 /**************************/
 
 /* Binary/behaviour compatibility levels */
-#define OSSL_DYNAMIC_VERSION           (unsigned long)0x00010100
+#define OSSL_DYNAMIC_VERSION           (unsigned long)0x00010200
 /* Binary versions older than this are too old for us (whether we're a loader or
  * a loadee) */
-#define OSSL_DYNAMIC_OLDEST            (unsigned long)0x00010100
+#define OSSL_DYNAMIC_OLDEST            (unsigned long)0x00010200
 
 /* When compiling an ENGINE entirely as an external shared library, loadable by
  * the "dynamic" ENGINE, these types are needed. The 'dynamic_fns' structure
  * type provides the calling application's (or library's) error functionality
  * and memory management function pointers to the loaded library. These should
  * be used/set in the loaded library code so that the loading application's
- * 'state' will be used/changed in all operations. */
+ * 'state' will be used/changed in all operations. The 'static_state' pointer
+ * allows the loaded library to know if it shares the same static data as the
+ * calling application (or library), and thus whether these callbacks need to be
+ * set or not. */
 typedef void *(*dyn_MEM_malloc_cb)(size_t);
 typedef void *(*dyn_MEM_realloc_cb)(void *, size_t);
 typedef void (*dyn_MEM_free_cb)(void *);
@@ -605,6 +608,7 @@ typedef struct st_dynamic_LOCK_fns {
        } dynamic_LOCK_fns;
 /* The top-level structure */
 typedef struct st_dynamic_fns {
+       void                                    *static_state;
        const ERR_FNS                           *err_fns;
        const CRYPTO_EX_DATA_IMPL               *ex_data_fns;
        dynamic_MEM_fns                         mem_fns;
@@ -645,6 +649,7 @@ typedef int (*dynamic_bind_engine)(ENGINE *e, const char *id,
                                const dynamic_fns *fns);
 #define IMPLEMENT_DYNAMIC_BIND_FN(fn) \
        int bind_engine(ENGINE *e, const char *id, const dynamic_fns *fns) { \
+               if(ENGINE_get_static_state() == fns->static_state) goto skip_cbs; \
                if(!CRYPTO_set_mem_functions(fns->mem_fns.malloc_cb, \
                        fns->mem_fns.realloc_cb, fns->mem_fns.free_cb)) \
                        return 0; \
@@ -656,9 +661,22 @@ typedef int (*dynamic_bind_engine)(ENGINE *e, const char *id,
                if(!CRYPTO_set_ex_data_implementation(fns->ex_data_fns)) \
                        return 0; \
                if(!ERR_set_implementation(fns->err_fns)) return 0; \
+       skip_cbs: \
                if(!fn(e,id)) return 0; \
                return 1; }
 
+/* If the loading application (or library) and the loaded ENGINE library share
+ * the same static data (eg. they're both dynamically linked to the same
+ * libcrypto.so) we need a way to avoid trying to set system callbacks - this
+ * would fail, and for the same reason that it's unnecessary to try. If the
+ * loaded ENGINE has (or gets from through the loader) its own copy of the
+ * libcrypto static data, we will need to set the callbacks. The easiest way to
+ * detect this is to have a function that returns a pointer to some static data
+ * and let the loading application and loaded ENGINE compare their respective
+ * values. */
+void *ENGINE_get_static_state(void);
+
+
 /* BEGIN ERROR CODES */
 /* The following lines are auto generated by the script mkerr.pl. Any changes
  * made after this point may be overwritten when the script is next run.