[hjl@gnu-6 relro-9]$ cat x.c int const p1[1] = { -1 }; [hjl@gnu-6 relro-9]$ cat foo.c #include <stdlib.h> extern int const p1[1]; void foo (void) { if (p1[0] != -1) abort (); } [hjl@gnu-6 relro-9]$ cat m.c #include <stdio.h> extern void foo (void); extern int p1[1]; int main () { foo (); printf ("%d\n", p1[0]); p1[0] = 0; foo (); return 0; } [hjl@gnu-6 relro-9]$ make gcc -O2 -g -c -o m.o m.c gcc -O2 -g -fPIC -c -o x.o x.c gcc -O2 -g -fPIC -c -o foo.o foo.c ld -shared --gc-sections -z relro -o libx.so x.o foo.o gcc -o x -O2 -g m.o libx.so -Wl,-R,. ./x -1 Makefile:10: recipe for target 'all' failed make: *** [all] Aborted [hjl@gnu-6 relro-9]$
And how is that a bug? The program invokes undefined behavior.
(In reply to Andreas Schwab from comment #1) > And how is that a bug? The program invokes undefined behavior. Linker should generate copy relocation against read-only symbol in .data.rel.ro section, instead of .bss section, so that the copy of read-only symbol is also read-only after relocation at run-time.
Here's a testcase that I think does not invoke any undefined behaviour, and shows various inconsistencies with protected variables and copy relocs. Depending on the version of gcc (and glibc!) you may see &x != x or no segfault. Compile protmain with -fPIC to see correct behaviour. cat > prot.h <<\EOF extern void *x; extern void aprint (void); extern void boom (void); EOF cat > prota.c <<\EOF #include "prot.h" void __attribute__ ((visibility ("protected"), section(".data.rel.ro"))) *x = &x; void aprint (void) { __builtin_printf ("A: &x = %p, x = %p\n", &x, x); } EOF cat > protb.c <<\EOF #include "prot.h" void boom (void) { x = 0; } EOF cat > protmain.c <<\EOF #include "prot.h" int main (void) { __builtin_printf ("main: &x = %p, x = %p\n", &x, x); aprint (); boom (); return 0; } EOF gcc -O2 -fPIC -shared -o liba.so prota.c protb.c -Wl,-z,relro gcc -O2 -o protmain protmain.c -L. -la -Wl,-rpath,. ./protmain
BTW, the testcase in comment #3 (and yours too!) show just how difficult it is to fix this problem. When the main program is *not* relro you don't have anywhere to put the new .dynbss.ro or whatever you want to call the internal linker generated section for read-only .dynbss variables. You don't have a .data.rel.ro in the main executable and can't tack them on to .rodata, because then ld.so will segfault when applying the copy relocation..
Dup. *** This bug has been marked as a duplicate of bug 20995 ***