From jhein@timing.com  Fri Dec 16 20:47:28 2005
Return-Path: <jhein@timing.com>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 4B05716A41F;
	Fri, 16 Dec 2005 20:47:28 +0000 (GMT)
	(envelope-from jhein@timing.com)
Received: from Daffy.timing.com (mail.timing.com [206.168.13.218])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 1D3C343D8B;
	Fri, 16 Dec 2005 20:47:04 +0000 (GMT)
	(envelope-from jhein@timing.com)
Received: from Elmer.timing.com (elmer.timing.com [206.168.13.187])
	by Daffy.timing.com (8.13.1/8.12.8) with ESMTP id jBGKkx2I075029;
	Fri, 16 Dec 2005 13:46:59 -0700 (MST)
	(envelope-from jhein@timing.com)
Received: from Elmer.timing.com (localhost.timing.com [127.0.0.1])
	by Elmer.timing.com (8.12.8p1/8.11.6) with ESMTP id jBGKkxMW001131;
	Fri, 16 Dec 2005 13:46:59 -0700 (MST)
	(envelope-from jhein@Elmer.timing.com)
Received: (from jhein@localhost)
	by Elmer.timing.com (8.12.8p1/8.12.8/Submit) id jBGKkxn7001129;
	Fri, 16 Dec 2005 13:46:59 -0700 (MST)
Message-Id: <200512162046.jBGKkxn7001129@Elmer.timing.com>
Date: Fri, 16 Dec 2005 13:46:59 -0700 (MST)
From: "John E. Hein" <jhein@timing.com>
Reply-To: "John E. Hein" <jhein@timing.com>
To: FreeBSD-gnats-submit@freebsd.org
Cc: brooks@freebsd.org
Subject: dhclient-script problems with symlink'd resolv.conf when /etc is read-only
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         90518
>Category:       bin
>Synopsis:       [patch] dhclient(8): dhclient-script problems with symlink'd resolv.conf when /etc is read-only
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    brooks
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Fri Dec 16 20:50:03 GMT 2005
>Closed-Date:    Sat May 13 03:25:51 GMT 2006
>Last-Modified:  Sat May 13 03:25:51 GMT 2006
>Originator:     John E. Hein
>Release:        FreeBSD 4.8-RELEASE i386
>Organization:
Timing Solutions
>Environment:
System: noticed on 4.x; still appears to be a problem on -current


>Description:
    Some situations - embedded products, for instance - call
    for a read-only root (& /etc) file system.  In such cases,
    we sym-link /etc/resolv.conf to a writable file system
    (e.g., /some/where/etc/resolv.conf).

    In 4.x, the 'rm /etc/resolv.conf.std' in dhclient-script fails
    and lines are appended to the actual resolv.conf file.  Over
    time, it can get quite large (in the case where new_domain_name
    is empty and thus the rm /etc/resolv.conf is attempted)).  In
    this case the easy fix is 'cp /dev/null /etc/resolv.conf' rather
    than using 'rm'.

    In -current, the problem is similar but the effect can be
    different.  The way dhclient-script works there, a temporary
    /etc/resolv.conf.std file is written to, then its contents is
    cat'd to the real resolv.conf.

    If /etc/resolv.conf.std does not exist on a read-only /etc,
    resolv.conf will never populate.

    If /etc/resolv.conf.std is a sym link (because the someone using
    a read-only /etc has looked into dhclient-script and seen what
    files it writes to), then you will hit the 'growing' resolv.conf
    issue described above.

    NB: I have not actually tried it on -current yet.  I have just
    looked at the add_new_resolv_conf() function.  If I did not dig
    deep enough, I apologize.  I'll try to verify it on -current
    when I get a chance.

>How-To-Repeat:
    mount -ur /

    Then run dhclient for your interface (using a dhcp server that
    supplies DNS server info).

    Observe the effects (or lack thereof) on resolv.conf

>Fix:

	Here's a patch for -current.  The choice of using TMPDIR
	may be wrong.  There could be a possible security issue,
	but I'm not clear about all the ways dhclient-script can
	be invoked.  Writing to a less accessible directory might
	be prudent.  And using an env var here may allow a malicious
	user could point TMPDIR somewhere undesirable.

    Somewhere under /var/run might be a better place.

    OpenBSD's version has the same problem.

Index: dhclient-script
===================================================================
RCS file: /base/FreeBSD-CVS/src/sbin/dhclient/dhclient-script,v
retrieving revision 1.10
diff -u -p -r1.10 dhclient-script
--- dhclient-script	8 Sep 2005 22:49:17 -0000	1.10
+++ dhclient-script	16 Dec 2005 20:31:52 -0000
@@ -134,21 +134,22 @@ add_new_resolv_conf() {
 	# thus broke the script. This code creates the resolv.conf if either
 	# are provided.
 
-	rm -f /etc/resolv.conf.std
+	local tmpres=${TMPDIR:-/tmp}/resolv.conf.std
+	rm -f $tmpres
 
 	if [ -n "$new_domain_name" ]; then
-		echo "search $new_domain_name" >>/etc/resolv.conf.std
+		echo "search $new_domain_name" >>$tmpres
 	fi
 
 	if [ -n "$new_domain_name_servers" ]; then
 		for nameserver in $new_domain_name_servers; do
-			echo "nameserver $nameserver" >>/etc/resolv.conf.std
+			echo "nameserver $nameserver" >>$tmpres
 		done
 	fi
 
-	if [ -f /etc/resolv.conf.std ]; then
+	if [ -f $tmpres ]; then
 		if [ -f /etc/resolv.conf.tail ]; then
-			cat /etc/resolv.conf.tail >>/etc/resolv.conf.std
+			cat /etc/resolv.conf.tail >>$tmpres
 		fi
 
 		# When resolv.conf is not changed actually, we don't
@@ -156,8 +157,8 @@ add_new_resolv_conf() {
 		# If /usr is not mounted yet, we cannot use cmp, then
 		# the following test fails.  In such case, we simply
 		# ignore an error and do update resolv.conf.
-		if cmp -s /etc/resolv.conf.std /etc/resolv.conf; then
-			rm -f /etc/resolv.conf.std
+		if cmp -s $tmpres /etc/resolv.conf; then
+			rm -f $tmpres
 			return 0
 		fi 2>/dev/null
 
@@ -168,8 +169,8 @@ add_new_resolv_conf() {
 		if [ -f /etc/resolv.conf ]; then
 			cat /etc/resolv.conf > /etc/resolv.conf.save
 		fi
-		cat /etc/resolv.conf.std > /etc/resolv.conf
-		rm -f /etc/resolv.conf.std
+		cat $tmpres > /etc/resolv.conf
+		rm -f $tmpres
 
 		# Try to ensure correct ownership and permissions.
 		chown -RL root:wheel /etc/resolv.conf
>Release-Note:
>Audit-Trail:

From: "John E. Hein" <jhein@timing.com>
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: bin/90518: dhclient-script problems with symlink'd resolv.conf
 when /etc is read-only
Date: Fri, 16 Dec 2005 14:09:17 -0700

 Sorry about the bizarre formatting in the text above.
Responsible-Changed-From-To: freebsd-bugs->wes 
Responsible-Changed-By: wes 
Responsible-Changed-When: Mon Jan 23 05:49:11 UTC 2006 
Responsible-Changed-Why:  
I'll shepherd this one along. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=90518 
State-Changed-From-To: open->patched 
State-Changed-By: brooks 
State-Changed-When: Sun May 7 23:53:44 UTC 2006 
State-Changed-Why:  
The patch was commited in rev 1.12 and fixed to use /var/run to 
avoid symlike overwrite attacks in rev 1.14. Should be MFC'd after 
6.1-RELEASE. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=90518 
State-Changed-From-To: patched->closed 
State-Changed-By: brooks 
State-Changed-When: Sat May 13 03:24:18 UTC 2006 
State-Changed-Why:  
Merged corrected patch into 6.x.  No plan to merge to earlier versions. 


Responsible-Changed-From-To: wes->brooks 
Responsible-Changed-By: brooks 
Responsible-Changed-When: Sat May 13 03:24:18 UTC 2006 
Responsible-Changed-Why:  
Merged corrected patch into 6.x.  No plan to merge to earlier versions. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=90518 
>Unformatted:

I tried your solution and it worked OK.  I don't see any obvious
exploit of TMPDIR unless dhclient is run insecurely, which would
be problematic itself.  I'll MFC this to 6.x and 5.x in 3 days
unless there are problems noted by users.  I need my test bed at
work to fully test all of these variants as well.
