Read a Linux Process Kernel Stack Through /proc
You will read the symbolic kernel call trace for a Linux process from /proc/PID/stack, check why access is denied, and retry with the least privilege that works. Allow about ten minutes. The examples are read-only and do not stop, signal or reconfigure a process.
The route
Jump straight to the step you need, or tick off Done means at the end.
This guide follows the installed proc_pid_stack(5) manual from the Linux man-pages 6.7 package. The file has existed since Linux 2.6.29, but it is available only when the running kernel was built with CONFIG_STACKTRACE. The exact functions in a trace depend on what the process is doing at the instant you read it.
1. Check the running kernel and target process
Choose a real target PID that you are allowed to inspect. For a harmless first check, use the shell's own PID. Run this as an ordinary user:
$ printf 'kernel: %s\n' "$(uname -r)"
kernel: 6.8.0-139-generic
$ pid=$$
$ printf 'target PID: %s\n' "$pid"
target PID: 12345
$ test -r "/proc/$pid/stack" && echo readable || echo 'not readable'
not readable
The PID in your output will differ. The test command checks the file permission presented by procfs; it does not prove that the subsequent read will pass the kernel's ptrace access check.
Checkpoint: keep the PID in a shell variable only while it identifies the process you intend to inspect. PIDs can be reused after a process exits, so do not save a PID in a long-lived script without checking that the process is still the intended one.
2. Read the stack file
Read the file with cat. This is an ordinary command and normally needs no elevated privilege when the target and reader have a permitted relationship:
$ cat "/proc/$pid/stack"
[<0>] example_kernel_function+0x2a/0x80
[<0>] another_kernel_function+0x54/0xa0
$ status=$?
$ printf 'cat status: %s\n' "$status"
cat status: 0
The angle-bracketed addresses and offsets are part of a symbolic kernel trace. This is not a copy of the process's user-space backtrace, and it is not a promise that every frame can be resolved to a source line. A sleeping process may show a wait path; a busy process can produce a different trace a moment later.
Do not treat a successful read as proof that the process is healthy. The file answers a narrow diagnostic question: which kernel functions are on the process's kernel stack at the time of the read?
3. Diagnose a permission failure
On this machine, an unprivileged read of both the shell's stack and PID 1's stack fails with Permission denied. That is consistent with the manual: access is governed by the PTRACE_MODE_ATTACH_FSCREDS ptrace check. The file mode alone is not the complete permission decision.
$ cat "/proc/$pid/stack"
cat: /proc/12345/stack: Permission denied
$ printf 'cat status: %s\n' "$?"
cat status: 1
Keep the diagnostic separate from an absent file. If the path does not exist, the PID may have exited or the kernel may not expose this proc entry. If the path exists but the read is denied, check the target identity and the host's ptrace policy before changing anything.
The kernel's ptrace policy can make even a same-user read fail. On systems using Yama, inspect the policy without changing it:
$ cat /proc/sys/kernel/yama/ptrace_scope
1
The value and the policy modules present vary by distribution. Do not write a new value merely to make a diagnostic command work. Changing ptrace policy weakens a security boundary and can affect other processes.
4. Retry with elevated privilege only when authorised
If you administer the host and your operational policy permits it, retry the read with sudo. This reads potentially sensitive kernel and process information, so treat the output as restricted diagnostic data. It does not change the process:
$ sudo -n head -5 /proc/1/stack
[<0>] ep_poll+0x342/0x390
[<0>] do_epoll_wait+0xdb/0x100
[<0>] __x64_sys_epoll_wait+0x6f/0x110
[<0>] x64_sys_call+0x1576/0x25a0
[<0>] do_syscall_64+0x87/0x180
$ printf 'head status: %s\n' "$?"
head status: 0
sudo -n refuses to prompt for a password. If it reports that a password is required, stop and use your normal approved administrative procedure rather than embedding credentials in a script. A successful privileged read confirms that the earlier failure was an access decision, not necessarily a missing stack trace feature.
5. Check whether the kernel supports the file
When the file is absent for every suitable PID, check the running kernel configuration if your distribution installs it:
$ config="/boot/config-$(uname -r)"
$ grep '^CONFIG_STACKTRACE=' "$config"
CONFIG_STACKTRACE=y
CONFIG_STACKTRACE=y is the configuration required by the manual. A missing configuration file is not proof that the feature is disabled. Some distributions expose kernel configuration through another path, and some restrict it. Check the distribution's kernel package documentation before drawing a conclusion.
If the option is not enabled, there is no procfs command that can turn it on in the running kernel. Use a kernel built with the feature, following your normal deployment and rollback process. Do not replace a production kernel as an ad hoc debugging step.
6. Use a stable capture in a diagnostic script
For a short capture, record the PID, command name and read result together. This avoids confusing a reused PID with the original target:
pid='12345'
if test -r "/proc/$pid/comm"; then
name=$(cat "/proc/$pid/comm") || exit 1
printf 'PID %s (%s) kernel stack:\n' "$pid" "$name"
if ! cat "/proc/$pid/stack"; then
printf 'cannot read /proc/%s/stack\n' "$pid" >&2
exit 1
fi
else
printf 'PID %s no longer exists or is not visible\n' "$pid" >&2
exit 1
fi
The script does not use sudo automatically. That keeps its privilege boundary visible and prevents a monitoring job from silently gaining access to process internals. If an administrative collector needs this data, grant it through the host's existing service account and audit process.
Done means
- You selected a live PID and understood that PIDs can be reused.
- You read
/proc/PID/stackor recorded a specific ptrace permission failure. - You know the result is a symbolic kernel trace, not a user-space backtrace or health verdict.
- You checked
CONFIG_STACKTRACEbefore blaming procfs when the file is absent. - Any privileged read was authorised, kept as restricted diagnostic data, and made no persistent system change.