[llvm-bugs] [Bug 48035] New: LLD may incorrect mark dynamic executable as PT_EXEC (static executable) in some situations.

via llvm-bugs llvm-bugs at lists.llvm.org
Sat Oct 31 06:01:20 PDT 2020


https://bugs.llvm.org/show_bug.cgi?id=48035

            Bug ID: 48035
           Summary: LLD may incorrect mark dynamic executable as PT_EXEC
                    (static executable) in some situations.
           Product: lld
           Version: unspecified
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: ELF
          Assignee: unassignedbugs at nondot.org
          Reporter: harley.paterson at postgrad.otago.ac.nz
                CC: llvm-bugs at lists.llvm.org, smithp352 at googlemail.com

# Description

LLVM marks the ELF header of outputs all executable files with program type
executable `PT_EXEC` (executable object), including dynamically linked programs
and relocatable executable. My understanding is `PT_EXEC` is reserved for
statically linked, non-relocatable executable.

"PT_DYN" (dynamic object) is used for any code which requires the loader to
manipulate the address space after segments are loaded - including relocatable
executables, executables with dynamically loaded dependencies, and actual
dynamic libraries - Even if these "dynamic objects" are actually executable
programs with entry points.

Several GNU libc utilities, `ld-linux.so`, and the `dlfcn.h` functions assume
this scheme.

LLVM's scheme has at lease two observable problems:

- The loader, at least on Linux, will not apply address space layout
randomization. I've not tested this on other platforms.
- Glibc `dlopen` will refuse to open any object marked as `PT_EXEC`, even if
the object contains dynamic symbols and is relocatable.

I believe both the issues reported in the following test cases would be fixed
by the LLVM linker using the `PT_DYN` type for any executable which is position
independent, requires relocation, or requires dynamic linking.

# Test case

test.c
```c
#include <stdlib.h>
#include <stdio.h>

void alpha()
{
    printf("Alpha function at 0x%p\n", &alpha);
}

int main(void)
{
    alpha();
    return(EXIT_SUCCESS);
}
```

## Test 1: ALSR not applied:
```sh
# LLVM's behavior
$ clang -fPIE test.c -o test
$ readelf -h test | grep "Type"
Type:                              EXEC (Executable file)
$ ./test
Alpha function at 0x4004d0    # ASLR not applied.
$ ./test
Alpha function at 0x4004d0    # ASLR not applied.

# Expected behavior (GCC)
$ gcc -fPIE test.c -o test
$ readelf -h test | grep "Type"
Type:                              DYN (Shared object file)
$ ./test
Alpha function at 0x0x7f877820064a    # ASLR applied.
$ ./test
Alpha function at 0x0x7f0b32e0064a    # ASLR applied.
```

## Test 2: dlopen refuses to load objects.

```sh
$ cat load.c
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
    if (argc < 2) {
        printf("Usage: ./load <object>\n");
        exit(EXIT_FAILURE);
    }   
    void* test_handle = dlopen(argv[1], RTLD_LAZY);
    if (test_handle == NULL) {
        printf("Dlopen Could not open '%s' object.\n", argv[1]);
    }
    void* alpha_ptr = dlsym(test_handle, "alpha");
    if (alpha_ptr == NULL) {
        printf("Dlopen could not locate the 'alpha' symbol.\n");
    }
    printf("Dlopen found alpha at 0x%p\n", alpha_ptr);
    exit(EXIT_SUCCESS);
}

$ clang -ldl load.c -o load

# LLVM's behavior.
$ clang test.c -o test -rdynamic
$ readelf -h test | grep "Type"
Type:                              EXEC (Executable file)
# Dynamic symbols are present, but dlopen gives up at `PT_EXEC`.
$ readelf --dyn-syms test | grep "alpha"
5: 00000000004006c0    36 FUNC    GLOBAL DEFAULT   12 alpha
$ ./load ~/test
Dlopen Could not open '/home/hpaterson/test' object.
Dlopen could not locate the 'alpha' symbol.
Dlopen found alpha at 0x(nil)

# Expected behavour (GCC)
$ gcc -rdynamic test.c -o test
$ readelf -h test | grep "Type"
Type:                              DYN (Shared object file)
$ readelf --dyn-syms test | grep "alpha"
8: 000000000000082a    31 FUNC    GLOBAL DEFAULT   14 alpha
$ ./load ~/test
Dlopen found alpha at 0x0x7f5b225e082a
```

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20201031/1dd54308/attachment.html>


More information about the llvm-bugs mailing list