diff options
author | kevlo <kevlo@FreeBSD.org> | 2012-06-20 02:21:53 +0000 |
---|---|---|
committer | kevlo <kevlo@FreeBSD.org> | 2012-06-20 02:21:53 +0000 |
commit | 592e847dfeee3afbd0174cd2a749345b1d68a951 (patch) | |
tree | 6bbf4ac92d1bfee774d598f2e638ffb95b10493e /bin | |
parent | 5c7e44656e584946db7a32059adb6ebc4ef211e2 (diff) | |
download | FreeBSD-src-592e847dfeee3afbd0174cd2a749345b1d68a951.zip FreeBSD-src-592e847dfeee3afbd0174cd2a749345b1d68a951.tar.gz |
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
Diffstat (limited to 'bin')
-rw-r--r-- | bin/rm/rm.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/bin/rm/rm.c b/bin/rm/rm.c index 3c2ba61..1f81885 100644 --- a/bin/rm/rm.c +++ b/bin/rm/rm.c @@ -408,7 +408,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; @@ -427,8 +427,15 @@ rm_overwrite(char *file, struct stat *sbp) 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); |