From owner-freebsd-hackers@FreeBSD.ORG Tue May 21 18:04:57 2013 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 2DB5CE63; Tue, 21 May 2013 18:04:57 +0000 (UTC) (envelope-from lidl@pix.net) Received: from hydra.pix.net (hydra.pix.net [IPv6:2001:470:e254::3c]) by mx1.freebsd.org (Postfix) with ESMTP id 41AE9226; Tue, 21 May 2013 18:04:56 +0000 (UTC) Received: from torb.pix.net (torb.pix.net [IPv6:2001:470:e254:10:12dd:b1ff:febf:eca9]) (authenticated bits=0) by hydra.pix.net (8.14.5/8.14.5) with ESMTP id r4LI4tWL042392; Tue, 21 May 2013 14:04:55 -0400 (EDT) (envelope-from lidl@pix.net) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.97.8 at mail.pix.net Message-ID: <519BB747.8030107@pix.net> Date: Tue, 21 May 2013 14:04:55 -0400 From: Kurt Lidl User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.8; rv:17.0) Gecko/20130509 Thunderbird/17.0.6 MIME-Version: 1.0 To: John Baldwin Subject: Re: find -delete broken, or just used improperly? References: <20130520192316.GA32531@pix.net> <20130520214731.GA43407@stack.nl> <201305211106.39313.jhb@freebsd.org> In-Reply-To: <201305211106.39313.jhb@freebsd.org> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Cc: freebsd-hackers@freebsd.org, Jilles Tjoelker 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: Tue, 21 May 2013 18:04:57 -0000 On 5/21/13 11:06 AM, John Baldwin wrote: > On Monday, May 20, 2013 5:47:31 pm Jilles Tjoelker wrote: >> 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); > > I'm curious, how would you instruct a patched find to avoid deleteing the > /tmp/foo directory (e.g. if you wanted this to be a job that pruned empty > dirs from /tmp/foo but never pruned the directory itself). Would -mindepth 1 > do it? (Just asking. I have also found this message annoying but most of > the jobs I have seen it on probably don't want to delete the root path, > just descendants.) Using "-mindepth 1" does indeed preserve the target directory. Without it, the target directory is removed if all the children files/directories are empty. I've just finished a complete build of a recent stable/9: make buildworld && make buildkernel && cd release && make release With WITHOUT_SHAREDOCS= set in my src.conf, and Jilles' patch to find, and the following patch to Makefile.inc1, it now builds a release properly. bhyve9# hg diff Makefile.inc1 diff -r ca8ef48b4ba6 Makefile.inc1 --- a/Makefile.inc1 Thu May 16 10:21:04 2013 -0400 +++ b/Makefile.inc1 Tue May 21 13:58:13 2013 -0400 @@ -754,7 +754,7 @@ ${IMAKEENV} rm -rf ${INSTALLTMP} .if make(distributeworld) .for dist in ${EXTRA_DISTRIBUTIONS} - find ${DESTDIR}/${DISTDIR}/${dist} -empty -delete + find ${DESTDIR}/${DISTDIR}/${dist} -mindepth 1 -empty -delete .endfor .if defined(NO_ROOT) .for dist in base ${EXTRA_DISTRIBUTIONS} If one doesn't have the "-mindepth 1" in the find command, it will remove the usr/share/doc directory entirely, which will cause a failure later in the 'make release' target code... -Kurt