From owner-freebsd-stable@FreeBSD.ORG Tue Jun 10 17:17:27 2008 Return-Path: Delivered-To: freebsd-stable@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 999961065678 for ; Tue, 10 Jun 2008 17:17:27 +0000 (UTC) (envelope-from scf@FreeBSD.org) Received: from mail.farley.org (farley.org [67.64.95.201]) by mx1.freebsd.org (Postfix) with ESMTP id 66E3F8FC16 for ; Tue, 10 Jun 2008 17:17:27 +0000 (UTC) (envelope-from scf@FreeBSD.org) Received: from thor.farley.org (HPooka@thor.farley.org [192.168.1.5]) by mail.farley.org (8.14.3/8.14.3) with ESMTP id m5AHHOjn008584; Tue, 10 Jun 2008 12:17:24 -0500 (CDT) (envelope-from scf@FreeBSD.org) Date: Tue, 10 Jun 2008 12:17:24 -0500 (CDT) From: "Sean C. Farley" To: Timo Sirainen In-Reply-To: <1213071257.3904.991.camel@hurina> Message-ID: References: <1213036854.3904.967.camel@hurina> <1213071257.3904.991.camel@hurina> User-Agent: Alpine 1.10 (BSF 962 2008-03-14) MIME-Version: 1.0 Content-Type: TEXT/PLAIN; format=flowed; charset=US-ASCII X-Spam-Status: No, score=-4.4 required=3.0 tests=ALL_TRUSTED,AWL,BAYES_00 autolearn=ham version=3.2.4 X-Spam-Checker-Version: SpamAssassin 3.2.4 (2008-01-01) on mail.farley.org Cc: freebsd-stable@FreeBSD.org Subject: Re: Environment clearing broken in 7.0 X-BeenThere: freebsd-stable@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Production branch of FreeBSD source code List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 10 Jun 2008 17:17:27 -0000 On Tue, 10 Jun 2008, Timo Sirainen wrote: > On Mon, 2008-06-09 at 22:27 -0500, Sean C. Farley wrote: >> On Mon, 9 Jun 2008, Timo Sirainen wrote: >> >>> I think clearing environment using: >>> >>> environ[0] = NULL; >>> >>> has been kind of a semi-standard for a while now. At least Dovecot >>> and Postfix clears their environment this way. But this no longer >>> works in FreeBSD 7.0 (putenv(), environ[0]=NULL, putenv() -> >>> everything is visible again). Was this change intended, or will this >>> be fixed? >> >> It is more or less intended. When a program sets an environment >> variable, the environment is copied for faster/leaner usage. >> Changing individual values within environ is not checked else every >> pointer would need to be checked for consistency. What I did was to >> write the code to detect if environ is replaced (NULL or new array of >> variables). > > OK, so perhaps Sendmail's way of clearing environment would be the > best solution: > > static char *emptyenv[1] = { NULL }; > environ = emptyenv; That works too. >> I suggest reading the two paragraphs from Open Group's getenv()[1] >> documentation starting at "Conforming applications are required not >> to modify environ directly, ..." for the rationale in the new design. >> Obviously, applications are not required to conform, but the >> documentation talks about what an OS may be doing under the covers to >> environ. > > How about implementing clearenv()? I'm using it now if it's available. It is a thought. It is not part of SUSv3, but there are many API calls in our libc that are not part of that spec. Interestingly, clearenv() on Linux ends up setting environ=NULL. Also, from the Linux man page: The DG/UX and Tru64 manpages write: If environ has been modified by anything other than the putenv(), getenv(), or clearenv() functions, then clearenv() will return an error and the process environment will remain unchanged. Hopefully, no libraries on these systems are manipulating environ else clearenv() will not work. >> Out of curiosity, do Dovecot and Postfix check that environ is not >> NULL before setting environ[0]? environ may be set to NULL at the >> start but not by FreeBSD's /usr/bin/env -i. > > Yes, both check if it's NULL. (I think I originally copied my code's > logic from Postfix.) Good. I asked because I could see myself making that mistake awhile back before I truly understood how environ interacted with applications from start (exec()) to finish. >>> Looks like I could work around this by using: >>> >>> environ = NULL; >> >> That will work on the *BSD's, OpenSolaris and Linux. > > But not on OS X. It crashes there. Grrrr. >> Also, this will work: >> environ = calloc(1, sizeof(*environ)); > > Is this any better than using a static emptyenv[1]? Not exactly but see below about Haiku as an example. > BTW. I wonder if this change breaks any applications where not > clearing environment could result in a security hole. As far as I know > FreeBSD 7.0 is the only modern OS where environ[0]=NULL doesn't work. OpenSolaris also does not detect environ[0]=NULL. Haiku[1], like MacOS, does not handle environ=NULL. *sigh* To support the most OS's I recommend the environ replacement such as in the static environ above. IMHO, mixing direct usage of the internals of environ and calling *env() is not safe. I really wish that environ could not be touched directly by any application. To be safe with all implementations of environ, I recommend using a method that replaces environ with a NULL terminated array such as you have with emptyenv. This will work on all platforms. Oops! Actually, it may break on Haiku since it will realloc() environ if it has copied environ previously with a call to putenv(), setenv() or unsetenv(). No guarantees, but I will do some research about detecting a NULL at environ[0] as another means of clearing the environment and/or writing an implementation of clearenv(). Of course, you will still have problems on OpenSolaris. What are you planning to do there, or does it support cleanenv()? Does anyone know why clearenv() was rejected? There is hardly a peep on the OpenGroup web site. To consolidate the notes: environ = NULL does not work on: 1. MacOS/Darwin 2. Haiku environ[0] = NULL does not work on: 1. FreeBSD 7+ 2. OpenSolaris static char *emptyenv[1] = { NULL }; environ = emptyenv; does not work on: 1. Haiku 2. MacOS? environ = calloc(1, sizeof(*environ)); should work on all assuming NULL was not returned. cleanenv() works on all systems that support it with caveats concerning: 1. DG/UX and Tru64 Sean 1. http://dev.haiku-os.org/browser/haiku/trunk/src/system/libroot/posix/stdlib/env.c -- scf@FreeBSD.org