Extend plugin infrastructure to catch Bro version mismatches at link

time.

People keep running into the problem that they upgrade Bro but forget
to recompile their plugins--which can lead to crashes. While the
plugins' API version was supposed to catch this, it's not reliable as
that check may come too late. This change takes a different tack: We
compile a C function into the Bro binary that has Bro's version number
encoded into its name. A plugin can then reference that function. If
the Bro version changes, the function goes away and the plugin won't
load anymore.

I've integrated that function reference into the plugin skeleton code
so that new plugins get it automatically (unless explicitly removed).
I couldn't see a way to do it transparently for already existing
plugins unfortunately.

The version number used for the function name is slightly normalized
to skip any git revision postfixes (i.e., "2.5-xxx" is always treated
as "2.5-git") so that one doesn't need to recompile all plugins after
every master commit. That seems good enough, usually people run into
this when upgrading to a new release.

If one loads an old plugin into a new Bro, the error message looks
like this:

    $ bro -NN Demo::Foo
    fatal error in /home/robin/bro/master/scripts/base/init-bare.bro, line 1:
    cannot load plugin library /home/robin/tmp/p/build//lib/Demo-Foo.linux-x86_64.so:
    /home/robin/tmp/p/build//lib/Demo-Foo.linux-x86_64.so: undefined symbol: bro_version_2_5_git_debug

Not the prettiest, but better than a crash!

TODO: I'm still unsure if we should remove the plugin API version
altogetger now. This link-time check should catch everything the API
version does, except for master commits.
This commit is contained in:
Robin Sommer 2017-07-07 15:44:53 -07:00
parent ffa7480ce4
commit 8ae30d8aac
5 changed files with 42 additions and 1 deletions

View file

@ -18,6 +18,8 @@
#define BRO_PLUGIN_API_VERSION 5
#endif
#define BRO_PLUGIN_BRO_VERSION BRO_VERSION_FUNCTION
class ODesc;
class Func;
class Event;
@ -93,6 +95,12 @@ public:
// strong hint.). The attribute seems generally available.
inline Configuration() __attribute__((always_inline));
/**
* One can assign BRO_PLUGIN_BRO_VERSION to this to catch
* version mismatches at link(!) time.
*/
const char* (*bro_version)();
private:
friend class Plugin;
int api_version; // Current BRO_PLUGIN_API_VERSION. Automatically set.
@ -103,6 +111,7 @@ inline Configuration::Configuration()
name = "";
description = "";
api_version = BRO_PLUGIN_API_VERSION;
bro_version = 0;
}
/**