Standard C usage of getenv and safe practices
Asked Answered
W

4

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?

Windermere answered 22/2, 2013 at 23:8 Comment(4)
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.Barbitone
"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.Eller
I revised the questionWindermere
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.Inguinal
W
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.

Wildman answered 22/2, 2013 at 23:25 Comment(7)
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).Hagan
@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.Wildman
@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().Wildman
It could be worthwhile to suggest setenv in your answer. :)Hagan
@zneak: That's irrelevant to the question. The question is about reading environment variables. Quote: "Could reading variables (for example getenv()) cause buffer overflow?"Wildman
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.Hagan
@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.Wildman
D
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
Dogie answered 23/2, 2013 at 7:24 Comment(3)
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 <stdio.h>; 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.Inguinal
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 understandDogie
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) ? "<undefined>" : env)); to ensure there is no crash. Printing a null pointer as a string is undefined behaviour, to be avoided at all costs.Inguinal
F
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.

Freshet answered 22/2, 2013 at 23:53 Comment(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'.Inguinal
S
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.

Spavin answered 23/2, 2013 at 4:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.