From owner-freebsd-bugs@FreeBSD.ORG Mon Dec 7 22:50:06 2009 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 9B9601065679 for ; Mon, 7 Dec 2009 22:50:06 +0000 (UTC) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (freefall.freebsd.org [IPv6:2001:4f8:fff6::28]) by mx1.freebsd.org (Postfix) with ESMTP id 781958FC1F for ; Mon, 7 Dec 2009 22:50:06 +0000 (UTC) Received: from freefall.freebsd.org (localhost [127.0.0.1]) by freefall.freebsd.org (8.14.3/8.14.3) with ESMTP id nB7Mo6r4078480 for ; Mon, 7 Dec 2009 22:50:06 GMT (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.14.3/8.14.3/Submit) id nB7Mo6Ys078479; Mon, 7 Dec 2009 22:50:06 GMT (envelope-from gnats) Resent-Date: Mon, 7 Dec 2009 22:50:06 GMT Resent-Message-Id: <200912072250.nB7Mo6Ys078479@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Jon Passki Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 42D71106568B for ; 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 ; 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 ; 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 To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-3.1 Cc: Subject: conf/141258: /etc/rc.d/tmp may act incorrectly based on unprivleged local user actions X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 07 Dec 2009 22:50:06 -0000 >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: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Mon Dec 07 22:50:06 UTC 2009 >Closed-Date: >Last-Modified: >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: >Unformatted: