summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibELF
AgeCommit message (Collapse)Author
2021-02-26LibELF: Consolidate main executable loading a bitAndreas Kling
Merge the load_elf() and commit_elf() functions into a single load_main_executable() function that takes care of both things. Also split "stage 3" into two separate stages, keeping the lazy relocations in stage 3, and adding a stage 4 for calling library initialization functions. We also make sure to map the main executable before dealing with any of its dependencies, to ensure that non-PIE executables get loaded at their desired address.
2021-02-24LibC+DynamicLoader: Move "transactional memory" GCC stubs to LibCAndreas Kling
Instead of having a special case in the dynamic loader where we ignore TM-related GCC symbols, just stub them out in LibC like we already do for various other things we don't support.
2021-02-24LibELF: Convert more string literals to StringView literals.Brian Gianforcaro
Most of these won't have perf impact, but the optimization is practically free, so no harm in fixing these up.
2021-02-24LibELF: Use StringView literal syntax to build section names.Brian Gianforcaro
2021-02-23Everywhere: Rename ASSERT => VERIFYAndreas Kling
(...and ASSERT_NOT_REACHED => VERIFY_NOT_REACHED) Since all of these checks are done in release builds as well, let's rename them to VERIFY to prevent confusion, as everyone is used to assertions being compiled out in release. We can introduce a new ASSERT macro that is specifically for debug checks, but I'm doing this wholesale conversion first since we've accumulated thousands of these already, and it's not immediately obvious which ones are suitable for ASSERT.
2021-02-23LibELF: Inline DynamicObject::hash_section()Andreas Kling
This was high up in profiles and gets almost entirely optimized out when inlined, so let's do that.
2021-02-23LibELF: Don't build barely-used section lookup table in ELF::ImageAndreas Kling
The name-to-section lookup table was only used in a handful of places, and none of them were calling it nearly enough to justify building a cache for it in the first place. So let's get rid of it and reduce startup time by a little bit. :^)
2021-02-23LibELF: Avoid doing strlen() on everything while iterating GNU hashAndreas Kling
It's a lot faster to iterate the GNU hash tables if we don't have to compute the length of every symbol name before rejecting it anyway while comparing the first character. :^)
2021-02-23LibELF: Rename lookup_elf_symbol() => lookup_sysv_symbol()Andreas Kling
We have two kinds of lookup, SYSV and GNU hash. Both are ELF lookups.
2021-02-23LibELF: Avoid calling strlen() in DynamicObject::hash_section()Andreas Kling
The long-term fix here is to make StringView recognize compile-time string literals and do the right thing automatically.
2021-02-23LibELF: Don't recompute the same ELF hashes over and overAndreas Kling
When performing a global symbol lookup, we were recomputing the symbol hashes once for every dynamic object searched. The hash function was at the very top of a profile (15%) of program startup. With this change, the hash function is no longer visible among the top stacks in the profile. :^)
2021-02-23LibELF: Remove an ungodly amount of DYNAMIC_LOAD_DEBUG loggingAndreas Kling
This logging mode was unusable anyway since it spams way too much. The dynamic loader is in a pretty good place now anyway, so I think it's okay for us to drop some of the bring-up debug logging. :^) Also, we have to be careful with dbgln_if(FOO_DEBUG, "{}", foo()) where foo() is something expensive, since it might get evaluated even if !FOO_DEBUG.
2021-02-23LibELF: Move ELF hash functions to their own file (and make constexpr)Andreas Kling
2021-02-21LibELF: Fix build with ELF_IMAGE_DEBUGAndreas Kling
2021-02-21LibELF: Move DynamicObject::lookup_symbol() to DynamicLoaderAndreas Kling
Also simplify it by removing an unreachable code path.
2021-02-21LibELF: Make SymbolLookupResult::address a VirtualAddressAndreas Kling
Let's use a stronger type than void* for this since we're talking specifically about a virtual address and not necessarily a pointer to something actually in memory (yet).
2021-02-21LibELF: Simplify DynamicObject::Symbol class a bitAndreas Kling
We no longer need the create_undefined() helper function. Also we don't need a member field for is_undefined().
2021-02-21LibELF: Make symbol lookup functions return Optional<Symbol>Andreas Kling
It was very confusing how these functions used the "undefined" state of Symbol to signal lookup failure. Let's use Optional<T> to make things a bit more understandable.
2021-02-21LibELF: Remove "always bind now" global flagAndreas Kling
This looked like someone's forgotten debug mechanism.
2021-02-21LibELF+DynamicLoader: Rename DynamicObject::construct() => create()Andreas Kling
2021-02-21LibELF: Fix various clang-tidy warningsAndreas Kling
Remove a bunch of unused code, unnecessary const, and make some non-object-specific member functions static.
2021-02-20LibELF: Use StringView instead of "const char*" in dynamic linker codeAndreas Kling
There's no reason to use C strings more than absolutely necessary.
2021-02-20DynamicLoader: Always make .data segment read+writeAndreas Kling
Let's just ignore the program header and always go with read+write. Nothing else makes sense anyway.
2021-02-19LibC: Remove text relocationAndreas Kling
Tweak the PLT trampoline to avoid generating textrels in LibC. This allows us to share all the LibC mappings, reducing per-process memory consumption by ~200 KB. :^) Patch originally by @nico.
2021-02-19DynamicLoader+Userland: Enable RELRO for shared libraries as well :^)Andreas Kling
To support this, I had to reorganize the "load_elf" function into two passes. First we map all the dynamic objects, to get their symbols into the global lookup table. Then we link all the dynamic objects. So many read-only GOT's! :^)
2021-02-18LibELF+Userland: Enable RELRO for all userland executables :^)Andreas Kling
The dynamic loader will now mark RELRO segments read-only after performing relocations. This is pretty cool! Note that this only applies to main executables so far,. RELRO support for shared libraries will require some reorganizing of the dynamic loader.
2021-02-18DynamicLoader: Some ELF data segments were allocated too smallAndreas Kling
For a data segment that starts at a non-zero offset into a 4KB page and crosses a 4KB page boundary, we were failing to pad the VM allocation, which would cause the memcpy() to fail. Make sure we round the segment bases down, and segment ends up, and the issue goes away.
2021-02-13LibELF: Unmap and close the main executable after dynamic loadAndreas Kling
We don't need to keep the whole main executable in memory after completing the dynamic loading process. We can also close the fd.
2021-02-08Everywhere: Replace dbgln<flag>(...) with dbgln_if(flag, ...)AnotherTest
Replacement made by `find Kernel Userland -name '*.h' -o -name '*.cpp' | sed -i -Ee 's/dbgln\b<(\w+)>\(/dbgln_if(\1, /g'`
2021-02-08Everywhere: Fix obvious dbgln() bugsAnotherTest
This will allow compiletime dbgln() checks to pass
2021-02-05Userland: Add LibSystem and funnel all syscalls through itAndreas Kling
This achieves two things: - Programs can now intentionally perform arbitrary syscalls by calling syscall(). This allows us to work on things like syscall fuzzing. - It restricts the ability of userspace to make syscalls to a single 4KB page of code. In order to call the kernel directly, an attacker must now locate this page and call through it.
2021-02-05LibELF: Only set up PLT trampoline for objects with a PLTAndreas Kling
2021-02-04LibELF: Randomize the VM reservation (so we don't break ASLR)Andreas Kling
2021-02-03LibELF: Make a dummy VM reservation before mapping dynamic objectsAndreas Kling
Using the text segment for the VM reservation ran into trouble when there was a discrepancy between the p_filesz and p_memsz. Simplify this mechanism and avoid trouble by making the reservation as a MAP_PRIVATE | MAP_NORESERVE throwaway mapping instead. Fixes #5225.
2021-02-03LibELF: Remove dynamic loader syscall exception for libkeyboard.soAndreas Kling
LibKeyboard no longer needs to make syscalls so remove the exception we were making for it. :^)
2021-02-03LibC+LibELF: Run clang-formatAndreas Kling
2021-02-02LibELF: Make syscall region exceptions for UE and libkeyboard.soAndreas Kling
These two are currently making some syscalls so we'll have to make exceptions for them until we can clean them up.
2021-02-02LibELF: Mark libc.so and libpthread.so as syscall regionsAndreas Kling
Also, before calling the main program entry function, inform the kernel that no more syscall regions can be registered. This effectively bans syscalls from everywhere except LibC and LibPthread. Pretty neat! :^)
2021-02-01LibELF: Close dynamic objects after mapping and linking themAndreas Kling
Oops, we were leaving the file descriptors open.
2021-01-31LibELF: Split the DynamicLoader's loading mechanism into two stepsAndreas Kling
load_from_image() becomes map() and link(). This allows us to map an object before mapping its dependencies. This solves an issue where fixed-position executables (like GCC) would clash with the ASLR placement of their own shared libraries.
2021-01-31LibELF: Assert on multiple calls to DynamicLoader::load_from_image()Andreas Kling
It would be a mistake to recreate the cached DynamicObject.
2021-01-31LibELF: Don't validate ELF twice in DynamicLoaderAndreas Kling
Validation was happening in two steps, some in the constructor, and then some later on, in load_from_image(). This made no sense so just move all the validation to the constructor.
2021-01-31LibELF: Call mmap() before constructing the DynamicLoader objectAndreas Kling
Refactor DynamicLoader construction with a try_create() helper so that we can call mmap() before making a loader. This way the loader doesn't need to have an "mmap failed" state. This patch also takes care of determining the ELF file size in try_create() instead of expecting callers to provide it.
2021-01-30LibELF: Add a bunch of overflow checks in ELF validationAndreas Kling
2021-01-30LibELF: Avoid quadratic memory usage weaknessBen Wiederhake
Section names are referred to by offset and length. We do not check (and probably should not check) whether these names overlap in any way. This opened the door to many sections (in this example: about 2700) forcing ELF::Image::m_sections to contain endless copies of the same huge string (in this case: 882K). Fix this by loading only the first PAGE_SIZE bytes of each name. Since section names are only relevant for relocations and debug information and most section names are hard-coded (and far below 4096 bytes) anyway, this should be no restriction at all for 'normal' executables. Found by OSS-Fuzz: https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=29187
2021-01-30DynamicLoader: load_program_headers use variables to store regions (#5173)Jorropo
Previously regions were stored in a vector and then a pointer to regions in this vector were taken and stored. The problem is the vector were still appended after pointers were taken, if enough regions were present the vector would grow so large that it needed a resize, this cause his memory to moved and now the previous pointers are now pointing to old memory we just freed. Fixes #5160
2021-01-29LibELF: Map text segments read-only at firstAndreas Kling
To support upcoming W^X changes in the kernel, the dynamic loader needs to be careful about the order in which permissions are added to shared library text segments. We now start by mapping text segments read-only (no-write, no-exec). If relocations are needed, we make them writable, and then finally, for all text segments, we finish by making them read+exec.
2021-01-29LibELF: Tidy up DynamicLoader::load_program_headers() a bitAndreas Kling
Remove a confusing temporary, rename some things and add assertions.
2021-01-29LibELF: perror on failed mmap in load_program_headers (#5159)Jorropo
2021-01-28LibELF: Implement ASLR for shared libraries :^)Andreas Kling
Use mmap() with the new MAP_RANDOMIZED flag to load shared libraries at random addresses in each process. To avoid address space collisions, we start by doing a large chunk mmap that covers enough VM for both text and data, then we unmap and remap the data segment separately, once we know everything will fit. This is pretty cool! :^)