tools/testing/selftests/x86/nx_stack.c
Source file repositories/reference/linux-study-clean/tools/testing/selftests/x86/nx_stack.c
File Facts
- System
- Linux kernel
- Corpus path
tools/testing/selftests/x86/nx_stack.c- Extension
.c- Size
- 5482 bytes
- Lines
- 213
- Domain
- Support Tooling And Documentation
- Bucket
- tools
- Inferred role
- Support Tooling And Documentation: implementation source
- Status
- source implementation candidate
Why This File Exists
Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
assert.hsignal.hstdint.hstdio.hstdlib.hsys/mman.hsys/resource.hunistd.h
Detected Declarations
function sigsegvfunction sigtrapfunction main
Annotated Snippet
if (1) {
printf("stack min %lx\n", stack_min_addr);
}
uc->uc_mcontext.gregs[RIP] = (uintptr_t)&make_stack2;
test_state = 1;
} else if (test_state == 1) {
/* Stack has been cleared from top to bottom. */
unsigned long stack_max_addr = uc->uc_mcontext.gregs[RDI];
if (1) {
printf("stack max %lx\n", stack_max_addr);
}
/* Start faulting pages on stack and see what happens. */
uc->uc_mcontext.gregs[RIP] = stack_max_addr - PAGE_SIZE;
test_state = 2;
} else if (test_state == 2) {
/* Stack page is NX -- good, test next page. */
uc->uc_mcontext.gregs[RIP] -= PAGE_SIZE;
if (uc->uc_mcontext.gregs[RIP] == stack_min_addr) {
/* One more SIGSEGV and test ends. */
test_state = 3;
}
} else {
printf("PASS\tAll stack pages are NX\n");
_exit(EXIT_SUCCESS);
}
}
static void sigtrap(int _, siginfo_t *__, void *uc_)
{
const ucontext_t *uc = uc_;
unsigned long rip = uc->uc_mcontext.gregs[RIP];
printf("FAIL\texecutable page on the stack: " RIP_STRING " %lx\n", rip);
_exit(EXIT_FAILURE);
}
int main(void)
{
{
struct sigaction act = {};
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = &sigsegv;
int rv = sigaction(SIGSEGV, &act, NULL);
assert(rv == 0);
}
{
struct sigaction act = {};
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = &sigtrap;
int rv = sigaction(SIGTRAP, &act, NULL);
assert(rv == 0);
}
{
struct rlimit rlim;
int rv = getrlimit(RLIMIT_STACK, &rlim);
assert(rv == 0);
/* Cap stack at time-honored 8 MiB value. */
rlim.rlim_max = rlim.rlim_cur;
if (rlim.rlim_max > 8 * 1024 * 1024) {
rlim.rlim_max = 8 * 1024 * 1024;
}
rv = setrlimit(RLIMIT_STACK, &rlim);
assert(rv == 0);
}
{
/*
* We don't know now much stack SIGSEGV handler uses.
* Bump this by 1 page every time someone complains,
* or rewrite it in assembly.
*/
const size_t len = SIGSTKSZ;
void *p = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
assert(p != MAP_FAILED);
stack_t ss = {};
ss.ss_sp = p;
ss.ss_size = len;
int rv = sigaltstack(&ss, NULL);
assert(rv == 0);
}
make_stack1();
/*
* Unreachable, but if _this_ INT3 is ever reached, it's a bug somewhere.
* Fold it into main SIGTRAP pathway.
*/
__builtin_trap();
}
Annotation
- Immediate include surface: `assert.h`, `signal.h`, `stdint.h`, `stdio.h`, `stdlib.h`, `sys/mman.h`, `sys/resource.h`, `unistd.h`.
- Detected declarations: `function sigsegv`, `function sigtrap`, `function main`.
- Atlas domain: Support Tooling And Documentation / tools.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.