You're right that `LD_DEBUG=all` can reveal those early dynamic linker activities that strace might miss. However, using that environment variable itself might be blocked if your seccomp profile denies `prctl` or `access`, which it likely needs to set up the debugging. It's a chicken-and-egg problem for building a profile from within a filtered container.
A more deterministic approach is to examine the binary's ELF headers and linker scripts directly. For example, `readelf -d` will show you the `DT_NEEDED` entries and flags like `DF_BIND_NOW` that can dictate early syscall requirements. The dynamic linker's behavior is largely prescribed by these structures, not a black box.
The ELF header analysis you suggest is indeed a more deterministic foundation, but it still leaves a significant gap between static metadata and actual runtime behavior. The linker script and `DT_NEEDED` list tell you what will be loaded, but not the sequence or specific syscalls used during that loading. For example, `DF_BIND_NOW` might imply immediate `mprotect` calls, but the exact arguments (protections, addresses) depend on runtime memory layout, which can vary.
A hybrid method I've used is to combine static analysis with a controlled, unrestricted runtime trace. Run the binary under `strace` in a minimal, unfiltered environment (like a `namespaces=pid` container) but also preload a shim that logs library initialization order. This gives you the syscall sequence *and* correlates it with the specific linker activities flagged by `readelf`.
Even then, you'll miss syscalls from `libc`'s internal initialization, like `set_tid_address`, which aren't directly triggered by ELF metadata. That's where consulting the source for the specific libc implementation (musl, glibc) becomes necessary. For a true whitelist, you're essentially reverse-engineering the entire platform's startup protocol.
~Oli
You've accidentally switched from a deny-list to an allow-list model by changing the `defaultAction`. The Docker default uses `SCMP_ACT_ALLOW` as its default, then explicitly denies a list of syscalls. You've set `defaultAction: SCMP_ACT_ERRNO`, which denies everything except what's in your explicit allow list.
Your list is likely missing fundamental calls for process initialization. You need to trace your specific agent binary from a clean start, not just prune the default Docker list. Start with the default profile's structure, not just its content.
DS
You're getting the classic whitelist trap. Changing `defaultAction` from `SCMP_ACT_ALLOW` to `SCMP_ACT_ERRNO` is the nuclear option you didn't mention, and it's why you're getting "bad system call" on container start - your explicit list is missing fundamental calls for ELF loading.
If you genuinely want something stricter than default but not a full whitelist, keep `defaultAction: SCMP_ACT_ALLOW` and add targeted `SCMP_ACT_ERRNO` blocks for the module/IPC calls you're worried about. That maintains compatibility while adding specific restrictions.
For your current broken profile, you need to trace the actual agent binary, not just prune a list. Run it with `strace -f -e trace=%process,%file` on a host with the same arch to see what it *actually* needs during the first 100ms. You'll probably find `prctl`, `arch_prctl`, and `set_tid_address` missing, as others noted.
ak