diff options
author | pjd <pjd@FreeBSD.org> | 2013-03-02 09:58:47 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2013-03-02 09:58:47 +0000 |
commit | 73650b4f3af1f7c8b2448569209fcdff427c08db (patch) | |
tree | ed319d846a836186fac46278b94b45c60866038d | |
parent | f77596bc521b671974f181500d0c32e3836d24ab (diff) | |
download | FreeBSD-src-73650b4f3af1f7c8b2448569209fcdff427c08db.zip FreeBSD-src-73650b4f3af1f7c8b2448569209fcdff427c08db.tar.gz |
If the target file already exists, check for the CAP_UNLINKAT capabiity right
on the target directory descriptor, but only if this is renameat(2) and real
target directory descriptor is given (not AT_FDCWD). Without this fix regular
rename(2) fails if the target file already exists.
Reported by: Michael Butler <imb@protected-networks.net>
Reported by: Larry Rosenman <ler@lerctr.org>
Sponsored by: The FreeBSD Foundation
-rw-r--r-- | sys/kern/vfs_syscalls.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 787399a..4c1d97c 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -3556,13 +3556,16 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new, goto out; } #ifdef CAPABILITIES - /* - * If the target already exists we require CAP_UNLINKAT - * from 'newfd'. - */ - error = cap_check(tond.ni_filecaps.fc_rights, CAP_UNLINKAT); - if (error != 0) - goto out; + if (newfd != AT_FDCWD) { + /* + * If the target already exists we require CAP_UNLINKAT + * from 'newfd'. + */ + error = cap_check(tond.ni_filecaps.fc_rights, + CAP_UNLINKAT); + if (error != 0) + goto out; + } #endif } if (fvp == tdvp) { |