diff options
author | Evan Zacks <zackse@cpan.org> | 2013-11-26 09:56:11 -0500 |
---|---|---|
committer | Craig A. Berry <craigberry@mac.com> | 2013-12-02 22:45:36 -0600 |
commit | 1dcae8b8dd1e2aa373ab045fee3d4f95d34f0b3c (patch) | |
tree | be70583afa6fd8bdb89c3e26763f7148652961ab /doio.c | |
parent | 448f81ea464c80a9a14d972e68f7649d1ed12d8a (diff) | |
download | perl-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.c | 6 |
1 files changed, 5 insertions, 1 deletions
@@ -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--; |