yugr
yugr

Reputation: 21878

Crash when dlopening shared library which accesses global variable in constructor

This simple library

$ cat foo.c
int glob;

int foo() {
  return 0;
}

__attribute__((constructor))
void init() {
  glob = foo();
}

$ gcc -g -O0 -shared -fPIC foo.c -o libfoo.so

loads fine when I link it normally:

$ cat prog1.c
extern int foo();

int main() {
  return foo();
}

$ gcc -g -O0 prog1.c libfoo.so
$ LD_LIBRARY_PATH=. ./a.out

but crashes if I load it via dlopen:

$ cat prog2.c
#include <dlfcn.h>

int main() {
  dlopen("./libfoo.so", RTLD_LAZY | RTLD_GLOBAL);
  return 0;
}

$ gcc -g -O0 prog2.c -ldl
$ ./a.out
Segmentation fault

When I inspect it in gdb it looks like it crashes in init trying to store to address which does not match glob. I tested in Ubuntu 24.04 (Glibc 2.39) and Debian 11.11 (Glibc 2.31).

Upvotes: 1

Views: 101

Answers (1)

yugr
yugr

Reputation: 21878

Answered by Mike Kashkarov

glob is also a name of Glibc function, exported from libc.so. So in dlopen case glob is resolved to address in Glibc's read-only memory segment and we get a crash when writing to it.

Upvotes: 1

Related Questions