NetBSD-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Silly shell question



On Tue, 22 Mar 2016, Eric Haszlakiewicz wrote:
The special OS glue/magic that happens is that the kernel takes the list of environment variables passed to the execve() system call, and copies them to the stack of the newly executing binary (kern_exec.c if you want to go look).

Thank you, Eric. Your information is spot-on. Similar to what Manuel and Johnny gave me. I read quite a bit of source code, yesterday. The key for me was looking at the args to execve() just like you suggest. However, there were bits in the bourne shell source that also helped me to understand how and when the list was unrolled and used by the child shell.

Then, the code that runs before main() (which comes from crt0.o and automatically gets included in your program when you link)

Ahh, this is low-level and also interesting. I like learning about things we all take for granted sometimes. I've been coding in C for a while, and I never even knew about how the linker creates this and that it runs before main() etc... In the wikipedia page it says 'crt0' stands for "C runtime" and the zero means "very first!". Neat.

If your program (/bin/sh in this case) calls one of the exec* functions that don't take an explicit environ pointer, the implementation in libc (e.g. execl.c) actually calls execve() and passes along the current environment for you (which is available as the global variable "environ").

I noticed that in the shell source (var.c and others) that the shell takes some pretty strict measures on how to unpack all the data that it gets from the array of character pointers it gets passed as "envp". I'm now understanding how you could get yourself into a real mess by not taking great care with sanity checking what you get. It appears to be a bit of a pain in the butt.

Shell local variables aren't stored in environ at all and aren't passed along to the execve() call when the shell forks+execs some new process, they're just arbitrary data that the shell process keeps in its memory

Just for fun I was hunting around in the bourne shell code for what kind of data structure it uses to store the fact that "hey, this variable has been exported". I'm guessing it's a linked list of pointer addresses somewhere signifying "These are special. If you fork() or execve() something, pass this stuff along." Since they are pointers, the data changes appropriately as needed without any copies being involved (I'm guessing).

Actually, there's no reason that the shell needs to store even exported variables in its own environ global variable either, it just needs to make sure that it generates an appropriate array of variables when it starts a new process and calls execve().

Yes, I believe you and from what I'm seeing in the source, that's exactly what happens. I remember that there used to be some security problems with 'sudo' (and also others with telnet) because it didn't properly sanitize some of the environment that it accepted from the parent process. Now, I believe I understand more of the why.

Thanks to everyone who was gracious enough to explain what is probably really elementary stuff to most of you. I just wanted a "lower level" understanding of what was going on. Now I have it (or at least enough hubris to believe I do)!

-Swift


Home | Main Index | Thread Index | Old Index