summaryrefslogtreecommitdiff
path: root/doio.c
diff options
context:
space:
mode:
authorEvan Zacks <zackse@cpan.org>2013-11-26 09:56:11 -0500
committerCraig A. Berry <craigberry@mac.com>2013-12-02 22:45:36 -0600
commit1dcae8b8dd1e2aa373ab045fee3d4f95d34f0b3c (patch)
treebe70583afa6fd8bdb89c3e26763f7148652961ab /doio.c
parent448f81ea464c80a9a14d972e68f7649d1ed12d8a (diff)
downloadperl-1dcae8b8dd1e2aa373ab045fee3d4f95d34f0b3c.tar.gz
Make unlink on directory as root set errno.
If unlink is called on an existing directory while running as root without -U (PL_unsafe), the unlink call fails but does not set $!, because unlink(2) is not actually called in this case. If unlink is called as a user (or as root with -U), unlink(2) is invoked, so attempting to remove a directory would set errno to EISDIR as expected. If running as root without -U (PL_unsafe is false), lstat and S_ISDIR are called instead. If the lstat succeeds and S_ISDIR returns true, the argument is skipped without warning and without setting $!, meaning Perl's unlink can return failure while leaving the previous value of errno in place. This commit sets errno to EISDIR for this case.
Diffstat (limited to 'doio.c')
-rw-r--r--doio.c6
1 files changed, 5 insertions, 1 deletions
diff --git a/doio.c b/doio.c
index 4c929b1c31..56d33b2c62 100644
--- a/doio.c
+++ b/doio.c
@@ -1821,8 +1821,12 @@ nothing in the core.
tot--;
}
else { /* don't let root wipe out directories without -U */
- if (PerlLIO_lstat(s,&PL_statbuf) < 0 || S_ISDIR(PL_statbuf.st_mode))
+ if (PerlLIO_lstat(s,&PL_statbuf) < 0)
tot--;
+ else if (S_ISDIR(PL_statbuf.st_mode)) {
+ tot--;
+ SETERRNO(EISDIR, SS$_NOPRIV);
+ }
else {
if (UNLINK(s))
tot--;