Linux seccomp行为不一致求助:LD_PRELOAD防护模块异常
Hey there, let's break down this seccomp + LD_PRELOAD issue you're facing. It's super common to hit unexpected behavior when trying to block syscalls via preloaded modules—let's walk through the most likely culprits and fixes.
First, Let's Rule Out Common Pitfalls
1. You're Only Hooking the Libc Wrapper, Not All Call Paths
Most folks start by hooking the exposed libc function set_robust_list, but that only catches calls that go through the libc wrapper. If the target process uses a direct syscall() invocation or even raw syscall/sysenter instructions, your hook will completely miss it.
For example, this incomplete hook won't work for direct syscall calls:
#include <dlfcn.h> #include <stdlib.h> static int (*orig_set_robust_list)(const struct robust_list_head *head, size_t len); int set_robust_list(const struct robust_list_head *head, size_t len) { exit(1); // Expected to kill the process } __attribute__((constructor)) void init() { orig_set_robust_list = dlsym(RTLD_NEXT, "set_robust_list"); }
2. Verify the Syscall Is Actually Being Triggered
Before debugging your module, confirm the target process is even calling set_robust_list using strace:
strace -e set_robust_list ./your_target_program
If strace doesn't show the syscall, your expectation might be off. If it does show up but your module doesn't react, your hook is missing the call path.
Fixes to Block set_robust_list Reliably
Option 1: Hook Both the Libc Wrapper and syscall() Function
To cover all user-space call paths, you need to intercept both the libc function and the generic syscall() helper. Here's a corrected module:
#include <dlfcn.h> #include <stdlib.h> #include <sys/syscall.h> // Store original function pointers static int (*orig_set_robust_list)(const struct robust_list_head *head, size_t len); static long (*orig_syscall)(long number, ...); // Hook the libc wrapper int set_robust_list(const struct robust_list_head *head, size_t len) { exit(EXIT_FAILURE); } // Hook the generic syscall function to check for SYS_set_robust_list long syscall(long number, ...) { if (number == SYS_set_robust_list) { exit(EXIT_FAILURE); } return orig_syscall(number, ...); } // Initialize hooks when the module is loaded __attribute__((constructor)) void init_hooks() { orig_set_robust_list = dlsym(RTLD_NEXT, "set_robust_list"); orig_syscall = dlsym(RTLD_NEXT, "syscall"); }
Compile it with:
gcc -shared -fPIC -o block_set_robust_list.so block_set_robust_list.c -ldl
Then inject it:
LD_PRELOAD=./block_set_robust_list.so ./your_target_program
Option 2: Use Seccomp Directly (More Reliable)
LD_PRELOAD can't block raw syscall instructions, so if you need absolute enforcement, use seccomp directly. Here's a module that sets up a seccomp rule to kill any process calling set_robust_list:
#include <stdio.h> #include <stdlib.h> #include <seccomp.h> void setup_seccomp_rules() { scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_ALLOW); // Allow all syscalls by default if (!ctx) { perror("seccomp_init failed"); exit(EXIT_FAILURE); } // Add rule to kill process on set_robust_list call if (seccomp_rule_add(ctx, SCMP_ACT_KILL, SCMP_SYS(set_robust_list), 0) < 0) { perror("Failed to add seccomp rule"); seccomp_release(ctx); exit(EXIT_FAILURE); } // Load the filter into the kernel if (seccomp_load(ctx) < 0) { perror("Failed to load seccomp filter"); seccomp_release(ctx); exit(EXIT_FAILURE); } seccomp_release(ctx); } // Initialize seccomp when the module loads __attribute__((constructor)) void init_seccomp() { setup_seccomp_rules(); }
Compile and inject the same way as the LD_PRELOAD hook—this will catch every possible invocation of the syscall, no matter how it's triggered.
Other Edge Cases to Check
- Static Linked Programs: LD_PRELOAD doesn't work on statically linked binaries. If your target is static, you'll need to use seccomp or statically inject your code.
- Libc Version Differences: Some older libc versions handle
set_robust_listvia internal functions instead of the exposed wrapper. Thesyscall()hook will catch these cases. - Root Permissions: Seccomp rules still apply to root users, so that's not the issue here.
If you share your exact module code, we can pinpoint even more specific issues—but these steps should cover most of the common reasons your current setup isn't working.
内容的提问来源于stack exchange,提问作者Ben Hirschberg

