5

I am using the following in openssh/telnet code, which sets the user environment.

setenv("TEST_ENV", "testing", 1);

But this can be modified by the user, is there anyway to make it readonly env variable?

Ram
  • 170
  • 1
  • 2
  • 5

3 Answers3

7

There's nothing in the conventional process environment to make a variable read only, only shells have that concept for their own environment/variables (the two overlap in ways, but they must be understood as distinct). The same applies for type properties like integer, array, function etc.

Have you considered using a restricted shell, like rbash? You could set rbash up to run readonly TEST_ENV) in its startup script. rbash may be too restrictive though, but it addresses to a good extent the issues raise in the comments.

The environment is a read/write part of each process (see here and here for details), not only can a process write directly to the data part (via environ[]), it can change the pointers to it. You might be able to do something with this (i.e. relocate to a read-only page) if you are proficient in assembly and can find your way around the crt startup code, but I don't recommend it ;-)

If there are specific commands that users run that must have a certain environment you may be able to set only group-execute and use sudo to set the correct variables (e.g. via /etc/environment or env_file directive) and run the command as the specific group (preserving uid). Recent versions support noexec on most platforms which can be used to prevent running a new shell (though can can break programs which legitimately fork() and exec()).

As a last option you may be able to use LD_PRELOAD and your own library to set a controlled environment for some/all user processes by wrapping the relevant libc functions (getenv() putenv() etc.). libfaketime does exactly this for time related libc functions. There's a less well known tool called timetravel that does similar, but also hooks setenv() and getenv() so as to keep control of LD_PRELOAD in the face of adversity.

The most robust approach is to filter the setenv() unsetenv() putenv() (and possibly clearnv()) calls to prevent modification, and filter getenv() so that it always returns the required value (possibly from a file). This approach won't prevent direct manipulation of the environment memory via environ[], but as long as you are in control of getenv() any process which relies on the libc API should see your value. bash uses environ[] directly when it initialises, but also calls getenv().

mr.spuratic
  • 9,901
6

Readonly variables can be set in POSIX compliant shells using the readonly command.

readonly VAR=foo   # POSIX
declare -r VAR=foo # bash
export VAR

This is in no way a security feature to prevent the user from changing it. The user can always spawn a new shell and change the variable.

jordanm
  • 42,678
  • yeah, that is a thing to worry about :( – Ram Mar 02 '13 at 06:33
  • 1
    Note that zsh allows typeset +r VAR to turn the readonly attribute off. – Stéphane Chazelas Mar 02 '13 at 07:48
  • 5
    Also note that AT&T implementations of ksh export the readonly attribute of exported variables to the environment via the A__z special variable, so in a newly started ksh, the variable will still be read-only (though if you have access to env, or perl or any other shell or tool that can modify an environment variable, that won't stop you from doing things like env VAR=new-value ksh – Stéphane Chazelas Mar 02 '13 at 08:20
0

You can set /etc/skel/.bashrc or every users's ~/.bashrc

readonly TEST_ENV
wcc526
  • 101