[PATCH] elf: Remove ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA

Szabolcs Nagy szabolcs.nagy@arm.com
Tue May 31 08:12:11 GMT 2022


The 05/30/2022 23:48, Fangrui Song wrote:
> On 2022-05-30, Szabolcs Nagy wrote:
> > The 05/27/2022 21:42, Fangrui Song via Libc-alpha wrote:
> > > Say both a.so and b.so define protected var and the executable copy
> > > relocates var.  ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA has strange
> > > semantics: a.so accesses the copy in the executable while b.so accesses
> > > its own.  This behavior requires that (a) the compiler emits
> > > GOT-generating relocations (b) the linker produces GLOB_DAT instead of
> > > RELATIVE.  The behavior change is from commit
> > > 62da1e3b00b51383ffa7efc89d8addda0502e107 (x86) and then copied to nios2
> > > (ae5eae7cfc9c4a8297ff82ec6b794faca1976ecc) and arc
> > > (0e7d930c4c11de896fe807f67fa1eb756c9c1e05).
> > > 
> > > Without the ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA code, b.so's GLOB_DAT
> > > will bind to the executable (normal behavior).
> > 
> > i think this should be reworded so all of this is under
> > assumptions (a) and (b).
> 
> How should I reword this, concretely? :)

how about:

If an executable has copy relocations for extern protected data, that
can only work if the library containing the definition is built with
assumptions (a) ... (b) ... .  Otherwise the library uses its own
definition directly and the executable accesses a stale copy. Note:
the GOT relocations defeat the purpose of protected visibility as an
optimization, but allow the dynamic linker to make the executable and
library use the same copy when copy relocations are present, but it
turns out this never worked perfectly.

ELF_RTYPE_... has strange semantics when both a.so and b.so define
protected var and the executable copy relocates var: a.so accesses the
copy in ...
The behaviour change is from commit ...

Without the ELF_RTYPE_...

There is no change when copy relocations are not present or when only
one library has definition for a protected variable.  It's extremely
unlikely that anyone relies on ...

> I think the tests currently XPASS on x86 with GNU ld and XFAIL on a
> bunch of architectures. I do have a plan (after this
> is accepted) to remove the `if (&protected3 == protected3b_p ())` part
> and remove `test-xfail-tst-protected1a = yes`)

sounds good. (this can be a separate patch)

> > (although if we reject copy relocs for
> > protected symbols in ld then the test may not work at all)
> 
> Right. libc_cv_protected_data in configure.ac should be changed
> to test whether copy relocations on protected data works,
> instead of testing just whether protected data compiles and links.
> 
> For aarch64, I plan to make GCC and GNU ld behaviors match clang and gold/ld.lld, the IMO ideal semantics.  The full roadmap is
> https://maskray.me/blog/2021-01-09-copy-relocations-canonical-plt-entries-and-protected#summary

this makes sense to me.

> > i think the exe now can interpose a protected symbol in a dso
> > if that uses GOT relocs. (there is no interposition if the
> > linker binds the protected symbol locally of course). i think
> > the commit should mention this change too.
> 
> This case (one dso definition copy relocated by exe) does not change.
> Even with the ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA code, the definition in
> the first dso can be interposed if it uses GOT relocs.
> 
> The ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA code affects the (multiple dso
> definitions, with the first one copy relocated by exe) case.

either this should be fixed or documented:

on aarch64 this patch vs the extern protected change reverted:

$ elf/ld.so-old --library-path . ./a.out
var in dso: 0xffffa6d50020 2
var in exe: 0x420038 1
$ elf/ld.so-new --library-path . ./a.out
var in dso: 0x420038 1
var in exe: 0x420038 1

$ cat a.c
#include <stdio.h>
void dso_call(void);
int foobar = 1;
int main()
{
  dso_call();
  printf("var in exe: %p %d\n", &foobar, foobar);
}

$ cat dso.c
#include <stdio.h>
__attribute__((visibility("protected"))) int foobar = 2;
void dso_call(void)
{
  printf("var in dso: %p %d\n", &foobar, foobar);
}

$ aarch64-none-linux-gnu-readelf -aW dso.so |grep foobar
000000000001ffd0  0000000800000401 R_AARCH64_GLOB_DAT     0000000000020020 foobar + 0
     8: 0000000000020020     4 OBJECT  GLOBAL PROTECTED   22 foobar
    74: 0000000000020020     4 OBJECT  GLOBAL PROTECTED   22 foobar

$ aarch64-none-linux-gnu-readelf -aW a.out |grep foobar
     8: 0000000000420038     4 OBJECT  GLOBAL DEFAULT   24 foobar
    90: 0000000000420038     4 OBJECT  GLOBAL DEFAULT   24 foobar



More information about the Libc-alpha mailing list