<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - LLD may incorrect mark dynamic executable as PT_EXEC (static executable) in some situations."
href="https://bugs.llvm.org/show_bug.cgi?id=48035">48035</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>LLD may incorrect mark dynamic executable as PT_EXEC (static executable) in some situations.
</td>
</tr>
<tr>
<th>Product</th>
<td>lld
</td>
</tr>
<tr>
<th>Version</th>
<td>unspecified
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>Linux
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>ELF
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>harley.paterson@postgrad.otago.ac.nz
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org, smithp352@googlemail.com
</td>
</tr></table>
<p>
<div>
<pre># 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
```</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>