Date: Tue, 21 May 2013 11:06:39 -0400 From: John Baldwin <jhb@freebsd.org> To: freebsd-hackers@freebsd.org Cc: Kurt Lidl <lidl@pix.net>, Jilles Tjoelker <jilles@stack.nl> Subject: Re: find -delete broken, or just used improperly? Message-ID: <201305211106.39313.jhb@freebsd.org> In-Reply-To: <20130520214731.GA43407@stack.nl> References: <20130520192316.GA32531@pix.net> <20130520214731.GA43407@stack.nl>
next in thread | previous in thread | raw e-mail | index | archive | help
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.) -- John Baldwin
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201305211106.39313.jhb>