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