summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2020-02-07 20:36:06 -0800
committerKaz Kylheku <kaz@kylheku.com>2020-02-07 20:36:06 -0800
commit6d6bb0cae29be50cb3e69d85df6cc0b6fee1ab9d (patch)
tree5a27a7e5b9d66ba03ea55ba31a70717a177d3a76
parent9dddf656328b2bcd76292aabc44112e99ad1b25a (diff)
downloadtxr-6d6bb0cae29be50cb3e69d85df6cc0b6fee1ab9d.tar.gz
txr-6d6bb0cae29be50cb3e69d85df6cc0b6fee1ab9d.tar.bz2
txr-6d6bb0cae29be50cb3e69d85df6cc0b6fee1ab9d.zip
chmod: fix broken umask application for implicit all.
* sysif.c (chmod_wrap): The umask logic is not activating after the first iteration through the loop, because when who is zero, we clobber it by adding the bits for u, g, and o. Then on subsequent iterations, who is no longer zero. Instead, let us leave the value of who alone, and in all the relevant places, check for it being zero.
-rw-r--r--sysif.c15
1 files changed, 6 insertions, 9 deletions
diff --git a/sysif.c b/sysif.c
index 11c07ce5..286dcca6 100644
--- a/sysif.c
+++ b/sysif.c
@@ -637,34 +637,31 @@ static val chmod_wrap(val target, val mode)
{
mode_t bits = 0;
mode_t mask = 0;
- int do_um = (who == 0);
-
- if (do_um)
- who = CHM_U | CHM_G | CHM_O;
+ int implicit_all = (who == 0);
if ((srcm & 020))
bits |= S_ISVTX;
- if ((who & CHM_U) != 0) {
+ if (implicit_all || (who & CHM_U) != 0) {
mask |= 0700;
if ((srcm & 010))
bits |= S_ISUID;
bits |= (srcm & 7) << 6;
}
- if ((who & CHM_G) != 0) {
+ if (implicit_all || (who & CHM_G) != 0) {
mask |= 0070;
if ((srcm & 010))
bits |= S_ISGID;
bits |= (srcm & 7) << 3;
}
- if ((who & CHM_O) != 0) {
+ if (implicit_all || (who & CHM_O) != 0) {
mask |= 0007;
bits |= (srcm & 7);
}
- if (do_um) {
+ if (implicit_all) {
mode_t um = umask(0777);
umask(um);
bits &= ~um;
@@ -675,7 +672,7 @@ static val chmod_wrap(val target, val mode)
case chm_sub: cmode &= ~bits; break;
case chm_set:
cmode &= ~mask;
- if ((who & CHM_O) != 0)
+ if (implicit_all || (who & CHM_O) != 0)
cmode &= ~S_ISVTX; /* GNU Coreutils 8.28 chmod behavior */
if (!S_ISDIR(cmode))
cmode &= ~(S_ISUID | S_ISGID);