From: Timo Sirainen Date: Wed, 7 Jul 2010 14:18:46 +0000 (+0100) Subject: module_dir_load(): Added support for checking binary name dependency. X-Git-Tag: 2.0.rc2~20 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=9cb5240b14923b5e64f32027eb46ee97d1a56f97;p=thirdparty%2Fdovecot%2Fcore.git module_dir_load(): Added support for checking binary name dependency. --HG-- branch : HEAD --- diff --git a/src/lib/module-dir.c b/src/lib/module-dir.c index b55f8909d9..f004a8eb7c 100644 --- a/src/lib/module-dir.c +++ b/src/lib/module-dir.c @@ -67,8 +67,29 @@ static void module_free(struct module *module) } static bool -module_check_missing_dependencies(struct module *module, - struct module *all_modules) +module_check_wrong_binary_dependency(const struct module_dir_load_settings *set, + struct module *module) +{ + const char *symbol_name, *binary_dep; + + symbol_name = t_strconcat(module->name, "_binary_dependency", NULL); + binary_dep = dlsym(module->handle, symbol_name); + if (binary_dep == NULL) + return TRUE; + + if (set->binary_name == NULL || + strcmp(binary_dep, set->binary_name) == 0) + return TRUE; + + i_error("Can't load plugin %s: " + "Plugin is intended to be used only by %s binary (we're %s)", + module->name, binary_dep, set->binary_name); + return FALSE; +} + +static bool +module_check_missing_plugin_dependencies(struct module *module, + struct module *all_modules) { const char **deps; struct module *m; @@ -134,6 +155,7 @@ module_load(const char *path, const char *name, void *handle; struct module *module; const char *const *module_version; + bool failed = FALSE; if (set->ignore_dlopen_errors) { handle = quiet_dlopen(path, RTLD_GLOBAL | RTLD_NOW); @@ -143,7 +165,16 @@ module_load(const char *path, const char *name, handle = dlopen(path, RTLD_GLOBAL | RTLD_NOW); if (handle == NULL) { i_error("dlopen(%s) failed: %s", path, dlerror()); +#ifdef RTLD_LAZY + failed = TRUE; + /* try to give a better error message by lazily loading + the plugin and checking its dependencies */ + handle = dlopen(path, RTLD_LAZY); + if (handle == NULL) + return NULL; +#else return NULL; +#endif } } @@ -174,12 +205,12 @@ module_load(const char *path, const char *name, set->require_init_funcs) { i_error("Module doesn't have %s function: %s", module->init == NULL ? "init" : "deinit", path); - module->deinit = NULL; - module_free(module); - return NULL; - } + failed = TRUE; + } else if (!module_check_wrong_binary_dependency(set, module) || + !module_check_missing_plugin_dependencies(module, all_modules)) + failed = TRUE; - if (!module_check_missing_dependencies(module, all_modules)) { + if (failed) { module->deinit = NULL; module_free(module); return NULL; diff --git a/src/lib/module-dir.h b/src/lib/module-dir.h index 4a55530921..1569417828 100644 --- a/src/lib/module-dir.h +++ b/src/lib/module-dir.h @@ -5,6 +5,9 @@ struct module_dir_load_settings { /* If version is non-NULL and the module contains a version symbol, fail the load if they're different. */ const char *version; + /* Binary name used for checking if plugin is tried to be loaded for + wrong binary. */ + const char *binary_name; /* Require all plugins to have _init() function */ unsigned int require_init_funcs:1;