Chapter 24 Quiz: Dynamic Linking in Depth
Question 1
What is the primary purpose of the PLT (Procedure Linkage Table)?
A) To list all the procedures (functions) in a shared library for documentation B) To provide a fixed address that code can call, which then indirects through the GOT to reach the actual function — enabling lazy binding and position-independent function calls C) To link the program's symbol table with the library's symbol table at link time D) To store the addresses of all locally-defined functions for faster dispatch
Question 2
Before the first call to malloc (with lazy binding enabled), the GOT entry for malloc contains:
A) The actual address of malloc in libc
B) The address of instruction 2 (push index) in the malloc@plt PLT stub — pointing back into the PLT itself
C) Zero (null pointer) — the dynamic linker has not initialized it yet
D) The address of _dl_runtime_resolve directly
Question 3
Why is the GOT placed in a writable memory segment?
A) The GOT contains function code that may be modified by the JIT compiler at runtime
B) The dynamic linker must be able to write actual symbol addresses into GOT entries at runtime during lazy binding resolution
C) GOT entries are initialized by the program at startup and require write access
D) The GOT is writable because it is in the .bss segment, which is always writable
Question 4
LD_PRELOAD achieves function interposition because:
A) It directly patches the function addresses in the target binary's .text section
B) Libraries listed in LD_PRELOAD are loaded before all others; since symbol resolution uses the first matching definition, the preloaded library's functions shadow the real library functions
C) LD_PRELOAD modifies the GOT directly, redirecting all function calls
D) The kernel intercepts system calls from the preloaded library and routes them to the target binary
Question 5
dlsym(RTLD_NEXT, "malloc") inside an LD_PRELOAD library returns:
A) The address of malloc in the current (preloaded) library
B) The address of malloc in the next library in the search order after the calling library — typically the real malloc in libc
C) NULL if malloc has not yet been called (lazy binding not complete)
D) The PLT stub address for malloc
Question 6
Full RELRO (-Wl,-z,relro,-z,now) prevents GOT overwrite attacks by:
A) Randomizing the GOT addresses on each program run
B) Disabling lazy binding (resolving all symbols at startup) and then marking the entire GOT (including .got.plt) as read-only with mprotect
C) Encrypting GOT entries so attackers cannot read the function addresses
D) Moving the GOT to kernel address space where user code cannot write to it
Question 7
What does the R_X86_64_JUMP_SLOT relocation type instruct the dynamic linker to do?
A) Jump to the specified symbol address unconditionally B) Write the resolved symbol's runtime address into the GOT slot at the specified offset C) Insert a PLT stub for the specified symbol D) Redirect a call instruction to use the PLT instead of a direct call
Question 8
A shared library function that is marked __attribute__((visibility("hidden"))):
A) Cannot be called by any code, even within the same library B) Is not exported in the library's dynamic symbol table; calls within the library bypass the PLT and GOT, using direct calls instead C) Is available but requires dlsym to access D) Is compiled into the .bss section rather than .text
Question 9
DT_INIT_ARRAY in the .dynamic section contains:
A) The ELF file version and architecture information
B) An array of function pointers that are called (in order) before main — used for C++ global constructors and __attribute__((constructor)) functions
C) The initialization code for the dynamic linker itself
D) A list of shared libraries that must be initialized before this library
Question 10
Symbol versioning (e.g., printf@@GLIBC_2.2.5) allows:
A) Multiple programs to call different versions of printf simultaneously B) The same library file to export multiple versions of the same function with different ABIs, ensuring programs linked against old versions continue to work when the library is updated C) The linker to choose the most optimized version of a function based on CPU capabilities D) Weak symbol resolution when printf is not available on the system
Question 11
The difference between DT_RPATH and DT_RUNPATH is:
A) RPATH is for runtime libraries; RUNPATH is for compile-time libraries
B) RPATH takes precedence over LD_LIBRARY_PATH and cannot be overridden; RUNPATH has lower priority than LD_LIBRARY_PATH
C) RPATH is deprecated and treated as RUNPATH by modern dynamic linkers
D) RPATH is searched recursively; RUNPATH is searched only in the specified directory
Question 12
When dlopen is called with RTLD_GLOBAL:
A) The library is loaded into global memory (kernel address space)
B) Symbols from the loaded library are made available for symbol resolution by subsequently loaded libraries (they can see each other's symbols)
C) The library is loaded with global file permissions (world-readable)
D) All symbols in the library are resolved immediately, regardless of whether RTLD_NOW or RTLD_LAZY is specified
Question 13
LD_PRELOAD is silently ignored for setuid/setgid programs because:
A) Setuid programs use a different dynamic linker that does not support LD_PRELOAD
B) If honored, a non-privileged user could use LD_PRELOAD to inject code that runs with elevated privileges — a security vulnerability
C) Setuid programs statically link all their libraries, so LD_PRELOAD has nothing to intercept
D) Setuid programs explicitly unset LD_PRELOAD at startup before loading any libraries
Question 14
The $ORIGIN token in an RPATH or RUNPATH:
A) Is the virtual address of the program's origin (entry point) B) Expands at runtime to the directory containing the executable (or library) that has the embedded RPATH — enabling relocatable installations C) Is the hostname where the library was originally compiled D) Is a security token verified by the dynamic linker to prevent path injection
Question 15
What does ltrace do that strace does not?
A) ltrace shows CPU registers at each function call; strace shows only syscall arguments
B) ltrace intercepts and logs shared library function calls (e.g., printf, malloc); strace intercepts only kernel system calls
C) ltrace shows the complete call tree including inline functions; strace shows only top-level calls
D) ltrace requires root privileges; strace can run as a normal user
Question 16
__attribute__((constructor(200))) and __attribute__((constructor(300))) — which runs first?
A) 300 (higher priority number = higher priority = runs first) B) 200 (lower priority number = runs first; priorities work like scheduling priorities where lower number = earlier) C) They run in parallel if the system has multiple CPU cores D) The order is unspecified for priorities in the range 200-300
Question 17
In the PLT, the first entry (PLT[0]) is special. What is its purpose?
A) It contains the address of main for use by the C runtime startup
B) It is the resolver stub: it pushes the link_map pointer and jumps to _dl_runtime_resolve — used by all other PLT entries when their symbol is not yet resolved
C) It is a padding entry that is never executed
D) It contains the number of PLT entries for the dynamic linker's reference
Question 18
When a GOT overwrite attack replaces GOT[exit] with the address of shellcode, what happens when the program calls exit(0)?
A) Nothing — exit is a system call and cannot be intercepted via the GOT
B) The PLT stub for exit reads the GOT entry, which now contains the shellcode address, and the jmp in the PLT stub redirects execution to the shellcode
C) The shellcode runs but immediately crashes because it is not at a valid PLT entry address
D) The dynamic linker detects the modified GOT entry and re-resolves it correctly
Question 19
checksec --file=program reports "Partial RELRO." This means:
A) The GOT is completely read-only; PLT entries remain writable
B) .got (non-lazy relocations) is read-only after startup, but .got.plt (lazy-binding entries) remains writable
C) Only 50% of the GOT entries have been protected; the rest are writable
D) Full RELRO was attempted but failed due to missing library support
Question 20
dlclose(handle) decrements the reference count of the loaded library. The library is actually unloaded (unmapped) when:
A) dlclose is called exactly once for each dlopen
B) The reference count reaches zero — which happens only when all dlopen calls (including transitive dependencies) have been matched by dlclose calls
C) The calling program calls exit()
D) The garbage collector in ld-linux.so determines the library is no longer referenced
Answer Key
- B
- B
- B
- B
- B
- B
- B
- B
- B
- B
- B
- B
- B
- B
- B
- B
- B
- B
- B
- B