find -delete broken, or just used improperly?
John Baldwin
jhb at freebsd.org
Tue May 21 16:17:28 UTC 2013
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
More information about the freebsd-hackers
mailing list