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
commit02ca39fdf8b42ff58f603707b55dfa997767efac (patch)
tree5a27a7e5b9d66ba03ea55ba31a70717a177d3a76
parent152a12592d3c5ee2794e938ed18c4939cac5cace (diff)
downloadtxr-02ca39fdf8b42ff58f603707b55dfa997767efac.tar.gz
txr-02ca39fdf8b42ff58f603707b55dfa997767efac.tar.bz2
txr-02ca39fdf8b42ff58f603707b55dfa997767efac.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);