]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
plugin-loader: Check version of loaded plugins 2835-plugin-versions
authorTobias Brunner <tobias@strongswan.org>
Mon, 11 Aug 2025 14:28:46 +0000 (16:28 +0200)
committerTobias Brunner <tobias@strongswan.org>
Mon, 11 Aug 2025 14:56:04 +0000 (16:56 +0200)
This prevents loading plugins from older builds that can cause all sorts
of issues as they might access struct members in different locations.

We don't check the version for statically linked plugins.

src/libstrongswan/plugins/plugin_loader.c

index 0d4659f127c99192f74f859cd0f73e394d4715ad..65e73e468aeb682d21489d997efde327c4e9be19 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010-2014 Tobias Brunner
+ * Copyright (C) 2010-2025 Tobias Brunner
  * Copyright (C) 2007 Martin Willi
  *
  * Copyright (C) secunet Security Networks AG
@@ -46,7 +46,6 @@ typedef struct plugin_entry_t plugin_entry_t;
  * Statically registered constructors
  */
 static hashtable_t *plugin_constructors = NULL;
-
 #elif !defined(HAVE_DLADDR)
 #error Neither dynamic linking nor static plugin constructors are supported!
 #endif
@@ -413,6 +412,39 @@ static status_t create_plugin(private_plugin_loader_t *this, void *handle,
        return SUCCESS;
 }
 
+#ifdef HAVE_DLADDR
+/**
+ * Verify that the plugin version matches that of the daemon
+ */
+static bool verify_plugin_version(void *handle, char *name)
+{
+       char field[128];
+       char **version;
+
+       if (snprintf(field, sizeof(field), "%s_plugin_version",
+                                name) >= sizeof(field))
+       {
+               return FALSE;
+       }
+       translate(field, "-", "_");
+
+       version = dlsym(handle, field);
+       if (!version)
+       {
+               DBG1(DBG_LIB, "plugin '%s': failed to load - version field %s missing",
+                        name, field);
+               return FALSE;
+       }
+       if (strcmp(*version, VERSION))
+       {
+               DBG1(DBG_LIB, "plugin '%s': failed to load - plugin version %s doesn't "
+                        "match version %s", name, *version, VERSION);
+               return FALSE;
+       }
+       return TRUE;
+}
+#endif /* HAVE_DLADDR */
+
 /**
  * load a single plugin
  */
@@ -479,6 +511,11 @@ static plugin_entry_t *load_plugin(private_plugin_loader_t *this, char *name,
                DBG1(DBG_LIB, "plugin '%s' failed to load: %s", name, dlerror());
                return NULL;
        }
+       if (!verify_plugin_version(handle, name))
+       {
+               dlclose(handle);
+               return NULL;
+       }
        switch (create_plugin(this, handle, name, create, TRUE, critical, &entry))
        {
                case SUCCESS: