environment variable accessibility in Linux

Let's trace the flow of the confidential data. In this analysis, it is understood that anything Alice can do, root can also do. Also an external observer “one level up” (e.g. with physical access to snoop on the disk bus, or in the hypervisor if the code is running in the virtual machine) might be able to access the data.

First, the data is loaded from a file. Assuming that only Alice has read permission on the file and the file is not otherwise leaked, only Alice can call cat /home/alice/fav_food.txt successfully. The data is then in the memory of the cat process, where only that process can access it. The data is transmitted over a pipe from the cat command to the calling shell; only the two processes involved can see the data on the pipe. The data is then in the memory of the shell process, again private to that process.

At some point, the data will end up in the shell's environment. Depending on the shell, this may happen when the export statement is executed, or only when the shell executes an external program. At this point, the data will be an argument of an execve system call. After that call, the data will be in the environment of the child process.

The environment of a process is just as private as the rest of that process's memory (from mm->env_start to mm->env_end in the process's memory map). It's contiguous with the initial thread's stack. However, there is a special mechanism that allows other processes to view a copy of the environment: the environ file in the process's /proc directory (/proc/$pid/environ). This file is only readable by its owner, who is the user running the process (for a privileged process, that's the effective UID). (Note that the command line arguments in /proc/$pid/cmdline, on the other hand, are readable by all.) You can audit the kernel source to verify that this is the only way to leak the environment of a process.

There is another potential source for leaking the environment: during the execve call. The execve system call does not directly leak the environment. However, there is a generic audit mechanism that can log the arguments of every system call, including execve. So if auditing is enabled, the environment can be sent through the audit mechanism and end up in a log file. On a decently configured system, only the administrator has access to the log file (on my default Debian installation, it's /var/log/audit/audit.log, only readable by root, and written to by the auditd daemon running as root).

I lied above: I wrote that the memory of a process cannot be read by another process. This is in fact not true: like all unices, Linux implements the ptrace system call. This system call allows a process to inspect the memory and even execute code in the context of another process. It's what allows debuggers to exist. Only Alice can trace Alice's processes. Furthermore, if a process is privileged (setuid or setgid), only root can trace it.

Conclusion: the environment of a process is only available to the user (euid) running the process.

Note that I assume that there is no other process that might leak the data. There is no setuid root program on a normal Linux installation that might expose a process's environment. (On some older unices, ps was a setuid root program that parsed some kernel memory; some variants would happily display a process's environment to any and all. On Linux, ps is unprivileged and gets its data from /proc like everyone else.).

(Note that this applies to reasonably current versions of Linux. A very long time ago, I think in the 1.x kernel days, the environment was world-readable.)


I was initially going to say "no". Environment variable values are per user and no other user can read or write to another user's env. vars. However, there is an interesting tidbit over on SO that indicates that root is able to at least read this information via /proc/<pid>/environ. I was not aware of this Linux-specific interface until now.

https://stackoverflow.com/a/532284/643314

With that said, it looks like this interface is still unreadable to other users, even if they are in the same groups. The permissions are set to 400 for the environ file and /proc prevents chmod from affecting it. I suspect that the security domain for environment variable separation across users is still intact and cannot be bypassed through normal means.


Despite Gilles' theoretically correct answer: I would not put secrets into environment variables.

  • Environment variables are usually defined near the top of the process tree (e.g. through $HOME/.profile).
  • Users do not treat the contents of the environment as secrets.

It's sufficient that a single process logs the environment variables to a world-readable file: env >> env-traces.txt or similar. You cannot control it.

Tags:

Linux

Memory