From owner-freebsd-hackers@FreeBSD.ORG Mon May 20 21:47:47 2013 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.FreeBSD.org [8.8.178.115]) by hub.freebsd.org (Postfix) with ESMTP id 7BA45F3D for ; Mon, 20 May 2013 21:47:47 +0000 (UTC) (envelope-from jilles@stack.nl) Received: from mx1.stack.nl (unknown [IPv6:2001:610:1108:5012::107]) by mx1.freebsd.org (Postfix) with ESMTP id 459371FA8 for ; Mon, 20 May 2013 21:47:47 +0000 (UTC) Received: from snail.stack.nl (snail.stack.nl [IPv6:2001:610:1108:5010::131]) by mx1.stack.nl (Postfix) with ESMTP id BF09D1203CF; Mon, 20 May 2013 23:47:31 +0200 (CEST) Received: by snail.stack.nl (Postfix, from userid 1677) id 959BB28493; Mon, 20 May 2013 23:47:31 +0200 (CEST) Date: Mon, 20 May 2013 23:47:31 +0200 From: Jilles Tjoelker To: Kurt Lidl Subject: Re: find -delete broken, or just used improperly? Message-ID: <20130520214731.GA43407@stack.nl> References: <20130520192316.GA32531@pix.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20130520192316.GA32531@pix.net> User-Agent: Mutt/1.5.21 (2010-09-15) Cc: freebsd-hackers@freebsd.org X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 20 May 2013 21:47:47 -0000 On Mon, May 20, 2013 at 03:23:16PM -0400, Kurt Lidl wrote: > OK, maybe I'm missing something obvious, but... > find(1) says: > -delete > Delete found files and/or directories. Always returns true. > This executes from the current working directory as find recurses > down the tree. It will not attempt to delete a filename with a > ``/'' character in its pathname relative to ``.'' for security > reasons. Depth-first traversal processing is implied by this > option. Following symlinks is incompatible with this option. > However, it fails even when the path is absolute: > bhyve9# mkdir /tmp/foo > bhyve9# find /tmp/foo -empty -delete > find: -delete: /tmp/foo: relative path potentially not safe > Shouldn't this work? The "relative path" refers to a pathname that contains a slash other than at the beginning or end and may therefore refer to somewhere else if a directory is concurrently replaced by a symlink. When -L is not specified and "." can be opened, the fts(3) code underlying find(1) is careful to avoid following symlinks or being dropped in different locations by moving the directory fts is currently traversing. If a problematic concurrent modification is detected, fts will not enter the directory or abort. Files found in the search are returned via the current working directory and a pathname not containing a slash. For paranoia, find(1) verifies this when -delete is used. However, it is too paranoid about the root of the traversal. It is already assumed that the initial pathname does not refer to directories or symlinks that might be replaced by untrusted users; otherwise, the whole traversal would be unsafe. Therefore, it is not necessary to do the check for fts_level == FTS_ROOTLEVEL. The below patch allows deleting the pathname given to find itself: Index: usr.bin/find/function.c =================================================================== --- usr.bin/find/function.c (revision 250661) +++ usr.bin/find/function.c (working copy) @@ -442,7 +442,8 @@ errx(1, "-delete: forbidden when symlinks are followed"); /* Potentially unsafe - do not accept relative paths whatsoever */ - if (strchr(entry->fts_accpath, '/') != NULL) + if (entry->fts_level > FTS_ROOTLEVEL && + strchr(entry->fts_accpath, '/') != NULL) errx(1, "-delete: %s: relative path potentially not safe", entry->fts_accpath); -- Jilles Tjoelker