11

I am trying to write C code which makes use of some ENV variables in a UNIX environment. The question is: Could reading variables (for example getenv()) cause buffer overflow? Moreover, how can I find the limit of the env variable size for my platform ? For example which header file?

Finally, what are the safest code practices in reading environment supplied variables?

user1944224
  • 143
  • 1
  • 1
  • 5
  • One of the safest is not assuming that you'll always find the variable you'r looking for, as the env variables can be setted/unsetted by the shell user. – SeedmanJ Feb 22 '13 at 23:14
  • *"is using getenv() safe not to get overflowed"* Not to overflow what? You have not supplied a buffer, so `getenv` must take care of that itself. – dmckee --- ex-moderator kitten Feb 22 '13 at 23:16
  • I revised the question – user1944224 Feb 22 '13 at 23:23
  • 3
    Note that the C standard says _The string pointed to may be overwritten by a subsequent call to `getenv()`_, which is not what most people expect (nor is it common practice in Unix systems for that to be a problem). So, strictly, you need to make a copy of any environment variable returned by `getenv()` before calling `getenv()` again. There isn't a header that directly defines a limit on the size of env var names or values. On POSIX, the `ARG_MAX` limit (which is often 256 KiB) is the total size of 'environment plus arguments', but that's pretty big and not always a firm limit. – Jonathan Leffler Feb 23 '13 at 07:47

4 Answers4

7

Reading an environment variable with getenv() will not cause a buffer overflow.

On Linux, inherited environment variables and their values are stored in the process address space by the kernel during exec(). The getenv() function just returns a pointer to this existing data. Since it does not copy any data, there is no buffer, and there can be no buffer overflow.

If you try to pass too many environment variables to a new process, exec() will signal the E2BIG error.

Security concerns

There aren't really any buffer overflow concerns with environment variables.

The security concerns center around the fact that you shouldn't trust the contents of the environment. If your program is run setuid (or setgid, etc.) then the environment is an attack vector. The user can set PATH or LD_PRELOAD or other variables in malicious ways.

However, it's rare to write setuid programs. This is a good thing, since there are so many reasons why it's difficult to make setuid programs secure.

Dietrich Epp
  • 205,541
  • 37
  • 345
  • 415
  • `getenv` returns a `char*` and not a `const char*`. This means that it should be possible to write to the returned address (and hence there could be a buffer overflow). – zneak Feb 22 '13 at 23:28
  • @zneak: You're not supposed to write to it. It would be `const char *` but it's an old API and making it `const` now would break programs. – Dietrich Epp Feb 22 '13 at 23:29
  • @zneak: Of course, you can write to it if you really want to change the environment that way. But the buffer overflow would be in your code, not in `getenv()`. – Dietrich Epp Feb 22 '13 at 23:30
  • It could be worthwhile to suggest `setenv` in your answer. :) – zneak Feb 22 '13 at 23:32
  • @zneak: That's irrelevant to the question. The question is about *reading* environment variables. Quote: "Could reading variables (for example getenv()) cause buffer overflow?" – Dietrich Epp Feb 22 '13 at 23:33
  • I'm pointing this out because I don't think the question reflects what the asker had in mind. You very obviously don't need to know if there's a fixed size for environment variable values _unless_ you want to write to them. – zneak Feb 22 '13 at 23:54
  • @zneak: If you want to second-guess the question, then comment on the question. If you have your own answer, write it up as an answer. Trying to convince me that I'm not reading the question right is just a waste of both of our time. You're better than that. – Dietrich Epp Feb 23 '13 at 00:18
1
#include <stdio.h>
#include <stdlib.h>

int main()
{
    char *hai;
    printf("The current User name is\n");
    hai="USER";
    printf("%s\n",getenv(hai));
    printf("The current User Directory is\n");
    char *hai1="PWD";
    printf("%s\n",getenv(hai1));
    exit(0);
}

This program is passing the argument of the getenv() function its valid means get the output

Output:
    The current User name is

    loganaayahee

    The current User Directory is

    /home/loganaayahee/AdvanceUnix/
(or)

This is not the Environment variable means getenv() function return NULL.

    hai="HELLO";
    if(getenv(hai)==NULL)
        printf("This is not Env\n");
    else
        printf("%s\n",getenv(hai));

Output:
    This is Not Env
Israphel
  • 21
  • 1
  • 5
loganaayahee
  • 809
  • 2
  • 8
  • 13
  • Since you're using C99 variable definitions, you should also use C99 function definitions. That means you need an explicit return type on `main()`, as in `int main(void)`. On the whole, avoid global variables such as `buf`; doubly avoid unused global variables (such as `buf`). I recommend using `return(0);` at the end of `main()`. Sort the indentation out. Use a space between `#include` and ``; that's the way the standard writes such lines. Strictly, you could end up with a null pointer from `getenv()`, in which case printing it is not reliable. All in all, a tad messy and careless. – Jonathan Leffler Feb 23 '13 at 07:53
  • The getenv() function is argument is one pointer and that pointer is pointed to one string and if wrong means getenv() function return NULL.so what is wrong method? i cannot understand – loganaayahee Feb 23 '13 at 09:18
  • I'm not sure what you're asking, but if you do: `printf("NONEXISTENT=%s\n", getenv("NONEXISTENT"));` and the environment variable `$NONEXISTENT` does not exist, you may get a core dump. Some versions of `printf()` are spot a null pointer and print something like `(null)` (that's from Mac OS X 10.7.5), but it could crash instead. For safety, you need to use something like: `char *env = getenv("NONEXISTENT"); printf("NONEXISTENT=%s\n", var, (env == 0) ? "" : env));` to ensure there is no crash. Printing a null pointer as a string is undefined behaviour, to be avoided at all costs. – Jonathan Leffler Feb 23 '13 at 14:03
0

Depends on what you mean by "reading". Just calling getenv won't cause any problems. However, if you try to copy the returned string to a buffer of some kind and you don't check the limit of the buffer, you could get a buffer overflow. The string returned by getenv may be large, with no upper bound other than available memory that your system decides to allocate to the environment.

This is no different than any other string input you may get -- beware of using strcpy and sprintf as they don't check for the size of your output buffer.

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226
  • 1
    Sometimes, ARG_MAX is the limit (strictly on command line arguments plus environment), but that is often very substantial (256 KiB), which is big enough that most people will consider it 'unbounded'. – Jonathan Leffler Feb 23 '13 at 07:43
0

You have to be careful with the environment, particularly if you want to pass it to child processes. For example, the environment is supposed to contain only one value for each variable, but it is easy to create one that contains several, if you delete the first one and pass the result on, another one will be exposed. If you want to sanitize the environment for children, create it from scratch and not by deleting values from the one you've got. David Wheeler has a guide for secure programming in Unix/Linux at his website.

vonbrand
  • 11,412
  • 8
  • 32
  • 52