aboutsummaryrefslogtreecommitdiff
path: root/bin/chmod
diff options
context:
space:
mode:
authorEdward Tomasz Napierala <trasz@FreeBSD.org>2009-07-01 15:52:19 +0000
committerEdward Tomasz Napierala <trasz@FreeBSD.org>2009-07-01 15:52:19 +0000
commitdeda5987bc6e3a94f2ae3a854fa944b60ac5eca1 (patch)
tree9061a434c397b22d8c234fdf2d0ba619b111d22b /bin/chmod
parent422d78667687764f4f5f84e8e6b81ef8c79e9b18 (diff)
downloadsrc-deda5987bc6e3a94f2ae3a854fa944b60ac5eca1.tar.gz
src-deda5987bc6e3a94f2ae3a854fa944b60ac5eca1.zip
With NFSv4 ACLs, it is possible that applying a mode to an ACL which
is identical to the mode computed from that ACL will modify the ACL. For example, mode computed from the following ACL is 0600: user:kamila:rwx--------C--:------:allow owner@:--x-----------:------:deny owner@:rw-p---A-W-Co-:------:allow group@:rwxp----------:------:deny group@:--------------:------:allow everyone@:rwxp---A-W-Co-:------:deny everyone@:------a-R-c--s:------:allow However, applying that mode (chmod 0600) changes the ACL into this: user:kamila:rwx-----------:------:deny user:kamila:rwx--------C--:------:allow owner@:--x-----------:------:deny owner@:rw-p---A-W-Co-:------:allow group@:rwxp----------:------:deny group@:--------------:------:allow everyone@:rwxp---A-W-Co-:------:deny everyone@:------a-R-c--s:------:allow In chmod(1) utility, there is an optimisation, which makes it not call chmod(2) if the mode of the file is the same as the new mode. Disable that optimisation for files which may have NFSv4 ACLs. Reviewed by: rwatson Approved by: re (kib)
Notes
Notes: svn path=/head/; revision=195243
Diffstat (limited to 'bin/chmod')
-rw-r--r--bin/chmod/chmod.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/bin/chmod/chmod.c b/bin/chmod/chmod.c
index 6736032466cc..d003b5fbc86f 100644
--- a/bin/chmod/chmod.c
+++ b/bin/chmod/chmod.c
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include <unistd.h>
static void usage(void);
+static int may_have_nfs4acl(const FTSENT *ent);
int
main(int argc, char *argv[])
@@ -180,8 +181,14 @@ done: argv += optind;
break;
}
newmode = getmode(set, p->fts_statp->st_mode);
- if ((newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS))
- continue;
+ /*
+ * With NFSv4 ACLs, it is possible that applying a mode
+ * identical to the one computed from an ACL will change
+ * that ACL.
+ */
+ if (may_have_nfs4acl(p) == 0 &&
+ (newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS))
+ continue;
if ((*change_mode)(p->fts_accpath, newmode) && !fflag) {
warn("%s", p->fts_path);
rval = 1;
@@ -219,3 +226,24 @@ usage(void)
"usage: chmod [-fhv] [-R [-H | -L | -P]] mode file ...\n");
exit(1);
}
+
+static int
+may_have_nfs4acl(const FTSENT *ent)
+{
+ int ret;
+ static dev_t previous_dev = (dev_t)-1;
+ static int supports_acls = -1;
+
+ if (previous_dev != ent->fts_statp->st_dev) {
+ previous_dev = ent->fts_statp->st_dev;
+ supports_acls = 0;
+
+ ret = pathconf(ent->fts_accpath, _PC_ACL_NFS4);
+ if (ret > 0)
+ supports_acls = 1;
+ else if (ret < 0 && errno != EINVAL)
+ warn("%s", ent->fts_path);
+ }
+
+ return (supports_acls);
+}