Memory location of environment variable (Linux)

Page content

Check that each envirnment variables are assigned to processes

you can see /pro/{{ process_id }}/environ holds all environment variable which is used for the process.

https://man7.org/linux/man-pages/man5/proc.5.html

/proc/[pid]/environ
      This file contains the initial environment that was set
      when the currently executing program was started via
      execve(2).  The entries are separated by null bytes
      ('\0'), and there may be a null byte at the end.  Thus, to
      print out the environment of process 1, you would do:

          $ cat /proc/1/environ | tr '\000' '\n'

      If, after an execve(2), the process modifies its
      environment (e.g., by calling functions such as putenv(3)
      or modifying the environ(7) variable directly), this file
      will not reflect those changes.

      Furthermore, a process may change the memory location that
      this file refers via prctl(2) operations such as
      PR_SET_MM_ENV_START.

getenv() and setenv() are not systemcall!

In which memory segment are environment variables stored?

The content of this video was wrong… He said

  • Actual data are stored in heap,
  • Pointers to the environment variable are stored in data segment.

But we really need to check the Blackmesh’s comment:

The environment is actually stored entirely on the stack and is a part of the initial process stack that is set up before the program starts running. The first value on the stack is the argument count followed by an array of the addresses of the different arguments, then address 0 marking the end of the argument array. Right after that there is a second array of addresses which each point to a zero-terminated string which would be the environment variables, this array is also terminated by having address 0 at the end. There is actually a third array of auxiliary vectors but after that there is an unspecified amount of bytes before the information block starts. It’s generally inside this block the command line arguments and environment variables are stored, as in the actual string values.

You can confirm this by dumping the stack of pretty much any program and you typically find all the environment variables at the very end (highest memory address). If you are on Linux you can do this by first reading the /proc/<pid>/maps file for any process, just replace <pid> with that process’ PID. This file contains the ranges of memory mapped to the process and what they are mapped to. Near the bottom you’ll see one line with the range mapped to [stack]. Take note of the start address and calculate how big it is in bytes. Then run sudo xxd -s <start-address> -l <size-in-bytes> /dev/<pid>/mem, example sudo xxd -s 0x7fff182bd000 -l 0x22000 /dev/14950/mem. And the environment variables should get printed out together with their hex values and address location.