Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 15 Feb 2002 05:56:15 -0800
From:      Terry Lambert <tlambert2@mindspring.com>
To:        Sansonetti Laurent <pinux@arrakis.atlantys.net>
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: Reading userland environnement from the kernel
Message-ID:  <3C6D137F.87FB3DC5@mindspring.com>
References:  <1013782534.2860.5.camel@freebsd.datatest.test.datarescue.be>

next in thread | previous in thread | raw e-mail | index | archive | help
Sansonetti Laurent wrote:
> Hi hackers,
> 
> Is there a way to read user-land environ(7) table from the kernel for a
> given process ?

Yes and no, or we'd already have implemented variant
symbolic links.

The problem is manifold:

1)	The environment is pointed to by the environ **
	pointer in the user process.  The location of
	the environ ** pointer is not well known.

2)	The environ ** value may be overridden by the user
	program entirely, so the pages where the data lives
	aren't where the are expected, so a saved pointer
	to envp *[] at execve time is not a workaround

3)	The envrion ** is require by POSUCKS (sometimes
	spelled "POSIX"), so getting rid of it and making
	the getenv/setenv/putenv/unsetenv functions use
	a multiplex system call is not an option that
	maintains POSIX compliance.

4)	It's hard to satisfy #2 and #3 and maintain binary
	compatability; the gross way you could do this is
	to save two copies of environ **, the real one at
	startup, and the shadow one called "environ **",
	and then if the shadow does not match the real,
	fall back to the historical behaviour.  Synchornizing
	means that you would need to know when the change
	happens (not possible, unless you catch a write fault
	and implicitly fix it up, like SVR4 does with page
	zero pointer dereferences, unless you specifically
	tune the kernel to fault fatally on them), or you
	would have to reflect all kernel level changes into
	the user space area shadow (expensive, but doable).

5)	The execve() envp *[] passing is tricky, at best,
	for a modified implementation, since you have to
	read it back to pass it down.  One option, which
	fails POSIX again, is to pass the default in if
	there is a NULL passed here, for an in kernel
	implementation (actually, you don't have to pass
	anything for the user environment, if the system
	and group contain everything you care about).

6)	You can also put the environ ** into user pages
	(read only) that are also mapped into a pointer off
	the proc structure (read/write), so that the kernel
	changes are visible to user space.  This makes it
	so that environ ** is not writable, but it is OK
	to read it, so a minimum number of changes are
	required for system/group/user logical names.

I run with a variant of #6 on one of my machines; I use the
same page I use for the environ ** for the pid, gid, and
other data to make them zero kernel overhead for getpid,
getppid, getgid, etc. -- basically, any system call that
only reads a small fixed sized data value.

This still means that the environment is stored in the user
space process, but the current environ ** is always known
to the kernel, and if it needs to be modified, it takes a
system call.

It's pretty cool: it lets me set the environment variables
for processes from other processes, and everyone inherits
from init's environment (system logical name table), the
process group leader's (if they aren't the leader themselves:
group logical name table) and then themselves, in increasing
priority, on getenv().

But of course, it violates the writability of **environ,
which POSUCKS wants, but I don't care (on that machine,
signals default to restarting system calls so that my
user space threads library is incredibly light weight, and
getting the one-close-destroys-all-locks-even-for-other-opens
behaviour is non-default, too... you have to fcntl(F_POSIX)).

-- Terry

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?3C6D137F.87FB3DC5>