Symbol conflicts between JSON libraries
When mod_dav_tpc is loaded along with mod_oauth2, at some point during authentication processing durch request handling, a segmentation fault occurs in mod_oauth2 for a json_
method.
The jansson
library triggers this segfault when accessing a value of one of its struct types.
The problem is caused because the value was actually constructed by json-c
, which was inadvertently called because one (or more) of its functions have the same name as functions in jansson
.
Both libraries are loaded because of transitive dependencies by the runtime linker:
- mod_oauth2 loads
- liboauth2 loads
- cjose loads
- jansson
- jansson
- cjose loads
- liboauth2 loads
- mod_dav_tpc loads
- gfal2 loads dynamically
- gfal_plugin_http loads
- json-c
- gfal_plugin_http loads
- gfal_transfer loads
- json-c
- gfal2 loads dynamically
The C-style symbol space is flat and does not distinguish (except through symbol versioning, see below) between different libraries. Each ELF specifies which sonames it wants loaded and independently which symbols it requires from the "external world". The loader will attempt to resolve these symbols but decide arbitrarily between multiple symbols with the same name.
Root Cause
Several JSON libraries export their function with names ("symbols") starting with json_
and there are function with exactly the same name in multiple libraries.
A process may load two of the JSON libraries into memory - usually because of transitive dependencies between libraries.
In such a situation, it is not clear which of the conflicting symbol name is referred to and a call to a function may result in the wrong code to be invoked.
Often, the result are strange errors such as validation errors or eventually segmentation faults.
Symbol versioning (a, b) solves this problem by adding another piece of information - the version - to each symbol at link time.
The version conventionally contains the name of the project, thereby eliminating conflicts between the same function being exported in different projects, as well as the a release version indicator.
Function calls look the same in C code, but symbols written into object files by the linker also contain the version.
This happen both for libraries exporting symbols and depending libraries which use these symbols.
Hence, the shared object (.so
file) of a library must be available at link time of depending libraries, so that the correct symbol information can be extracted.
Symbol versioning has been introduced to several JSON libraries. However, not all distributions contain these later releases with version information yet.
The issue of conflicting symbol names is also known in EL, but has been fixed only for EL8.