Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 27 Jun 2012 00:37:22 +0000 (UTC)
From:      Xin LI <delphij@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org
Subject:   svn commit: r237617 - stable/7/bin/rm
Message-ID:  <201206270037.q5R0bMCm071413@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: delphij
Date: Wed Jun 27 00:37:22 2012
New Revision: 237617
URL: http://svn.freebsd.org/changeset/base/237617

Log:
  MFC r237339:
  
  Polish previous revision: if the fts_* routines have lstat()'ed the
  directory entry then use the struct stat from that instead of doing
  it again, and skip the rm_overwrite() call if fts_read() indicated
  that the entry couldn't be a regular file.
  
  Obtained from:	OpenBSD
  
  MFC r237284 (kevlo):
  
  Fix potential symlink race condition in "rm -P" by adding a check
  that the file we have opened is the one we expected.  Also open in
  non-blocking mode to avoid a potential hang with FIFOs.
  
  Obtained from:	NetBSD via OpenBSD

Modified:
  stable/7/bin/rm/rm.c
Directory Properties:
  stable/7/bin/rm/   (props changed)

Modified: stable/7/bin/rm/rm.c
==============================================================================
--- stable/7/bin/rm/rm.c	Wed Jun 27 00:34:06 2012	(r237616)
+++ stable/7/bin/rm/rm.c	Wed Jun 27 00:37:22 2012	(r237617)
@@ -288,10 +288,16 @@ rm_tree(char **argv)
 				if (fflag)
 					continue;
 				/* FALLTHROUGH */
-			default:
+
+			case FTS_F:
+			case FTS_NSOK:
 				if (Pflag)
-					if (!rm_overwrite(p->fts_accpath, NULL))
+					if (!rm_overwrite(p->fts_accpath, p->fts_info ==
+					    FTS_NSOK ? NULL : p->fts_statp))
 						continue;
+				/* FALLTHROUGH */
+
+			default:
 				rval = unlink(p->fts_accpath);
 				if (rval == 0 || (fflag && errno == ENOENT)) {
 					if (rval == 0 && vflag)
@@ -386,7 +392,7 @@ rm_file(char **argv)
 int
 rm_overwrite(char *file, struct stat *sbp)
 {
-	struct stat sb;
+	struct stat sb, sb2;
 	struct statfs fsb;
 	off_t len;
 	int bsize, fd, wlen;
@@ -405,8 +411,15 @@ rm_overwrite(char *file, struct stat *sb
 		    file, sbp->st_ino);
 		return (0);
 	}
-	if ((fd = open(file, O_WRONLY, 0)) == -1)
+	if ((fd = open(file, O_WRONLY|O_NONBLOCK|O_NOFOLLOW, 0)) == -1)
+		goto err;
+	if (fstat(fd, &sb2))
 		goto err;
+	if (sb2.st_dev != sbp->st_dev || sb2.st_ino != sbp->st_ino ||
+	    !S_ISREG(sb2.st_mode)) {
+		errno = EPERM;
+		goto err;
+	}
 	if (fstatfs(fd, &fsb) == -1)
 		goto err;
 	bsize = MAX(fsb.f_iosize, 1024);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201206270037.q5R0bMCm071413>