Inspect Linux Process Security Attributes Safely
You will finish with a read-only way to inspect the security attributes exposed for a Linux process, understand which attribute applies to which later operation, and recognise when a missing file is a kernel or security-module detail rather than a shell problem. The examples use Linux man-pages 6.7, installed here as package version 6.7-2.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need a shell and a process you are allowed to inspect. The main examples read your own process, so they need no elevated privileges. Do not write a security context merely to make an example produce different output: writes can alter a process's security state and can affect files, keys or sockets created afterwards.
1. Confirm the installed contract
Start with the local manual page. This is an ordinary, read-only command and does not need sudo:
$ man proc_pid_attr
$ dpkg-query -W -f='${Package} ${Version}\n' manpages
manpages 6.7-2
The interface is a directory below /proc/<pid>/attr/. The directory is present only when the kernel was built with CONFIG_SECURITY. The manual uses SELinux to explain the files, but the interface is intended to be shared by security modules.
Checkpoint: if man proc_pid_attr cannot find the page, the package version above is not installed on your host. Continue only after checking the manual page supplied by that host.
2. Read the current attribute
Use self to refer to the shell process running the command:
$ cat /proc/self/attr/current
unconfined
The value is host-specific. On an SELinux system it is the process security context. On this machine the result is unconfined, which is a real observation about the current process, not a result every Linux host should show.
To inspect another process, replace PID with a numeric process ID that you are permitted to read:
$ PID=1234
$ test -r "/proc/$PID/attr/current" && cat "/proc/$PID/attr/current"
system_u:system_r:sshd_t:s0
The context in that second example is illustrative, not a promised default. If the test fails, check that the process still exists and that its security policy allows the read. Do not fix a permission error by writing to the file.
3. List the interface your kernel exposes
List the directory before assuming that every documented node exists:
$ ls -la /proc/self/attr
dr-xr-xr-x 2 ... apparmor
-rw-rw-rw- 1 ... current
-rw-rw-rw- 1 ... exec
-rw-rw-rw- 1 ... fscreate
-rw-rw-rw- 1 ... keycreate
-r--r--r-- 1 ... prev
dr-xr-xr-x 2 ... smack
-rw-rw-rw- 1 ... sockcreate
Ownership, timestamps and the exact set of entries vary. The installed proc_pid_attr(5) page documents current, exec, fscreate, keycreate, prev and socketcreate. This machine exposes sockcreate instead of a file named socketcreate. That is a useful warning: discover the local directory and do not build a script that assumes every security module uses the same spelling or supports every attribute.
Subdirectories such as apparmor and smack belong to particular security modules. They are not evidence that SELinux is active, and their presence does not mean that an application is confined.
4. Understand the attribute names before touching them
These files describe different points in a process lifecycle:
currentrepresents the process's current security attributes. The manual says that SELinux may permit authorised writes, but a successful write is a policy-controlled security transition.execis the attribute to use for a subsequentexecve(2)transition. In SELinux, it is reset by that exec, and a process can set only its own node.fscreatesupplies attributes for files created by lateropen(2),mkdir(2),symlink(2)andmknod(2)calls. In SELinux it persists across several creations until reset, but is reset by exec.keycreatesupplies the context for keys subsequently created withadd_key(2).prevreports the process security context before its last exec.socketcreate, or the module-specific spelling exposed locally, supplies the context for subsequently created sockets when that security module supports it.
Read a node without assuming that its contents are text you can safely reuse:
for name in current exec fscreate keycreate prev sockcreate; do
path="/proc/self/attr/$name"
if [ -r "$path" ]; then
printf '%s: ' "$name"
if ! IFS= read -r value <"$path"; then
printf '%s\n' 'read failed'
else
printf '%s\n' "$value"
fi
else
printf '%s: unavailable\n' "$name"
fi
done
Some nodes are write-oriented or can reject a normal read. That is expected. A read failure is not permission to try a write; it may be a deliberate interface restriction.
5. Keep writes out of routine diagnostics
Writing a value to an attribute is not a harmless configuration test. For example, a write to fscreate can change the labels assigned to later files created by the same process, while a write to keycreate or a socket-creation attribute can affect later kernel objects. A write to exec is intended to influence the next program image. These effects can outlive the command that performed the write.
Do not run a command such as this on a production process unless you have verified the security policy, the exact context, the process identity and a recovery plan:
$ printf '%s\n' 'CONTEXT_VALUE' > /proc/self/attr/exec
Warning
The placeholder above is deliberately not a runnable context. Substituting an arbitrary value can fail, trigger a policy transition or alter what the process can do after exec. The installed manual also limits some SELinux writes to the process itself and to contexts authorised by policy. Elevated privileges do not make an invalid context safe.
There is no universal undo command. If a write changes a process attribute, the safest recovery is usually to stop that process and start a fresh one under its normal policy. For service work, prepare the service rollback before testing and use a maintenance window. Do not delete files or restart a service as part of a read-only inspection.
6. Diagnose the common traps
If /proc/self/attr is absent, check the mounted proc filesystem and the kernel configuration or security-module setup with your platform documentation. The manual only promises the directory when CONFIG_SECURITY is enabled; it does not promise that SELinux, AppArmor, Smack or another module is loaded.
If current reads successfully but a specialised node is missing, use the local listing as the source of truth. A security module can expose its own subdirectory and semantics. Do not infer that a missing keycreate or socket attribute means the whole security interface is broken.
If a process disappears between checking its PID and reading its file, the path can fail or refer to a newly reused PID later. For monitoring, open and read the relevant path promptly and treat failures as a state change rather than retrying writes. Reading /proc/self/attr/current avoids PID reuse for the process doing the check.
Finally, a readable context does not prove that every operation is permitted. It identifies the current or requested security attributes; the active module and its policy decide what those attributes mean.
Done means
- You confirmed the installed man-pages version and read the local
proc_pid_attr(5)contract. - You read
/proc/self/attr/currentwithout elevated privileges. - You listed the local attribute names instead of assuming the manual's complete list is mounted unchanged.
- You know the difference between current, exec, file-creation, key-creation, previous and socket-creation attributes.
- You treated writes as security-sensitive process changes and did not use an arbitrary context value.
- You can distinguish a missing interface, a module-specific node and a policy-controlled read or write failure.