Skip to content

Commit

Permalink
With NFSv4 ACLs, it is possible that applying a mode to an ACL which
Browse files Browse the repository at this point in the history
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)
  • Loading branch information
trasz committed Jul 1, 2009
1 parent f90eaa9 commit c51532a
Showing 1 changed file with 30 additions and 2 deletions.
32 changes: 30 additions & 2 deletions bin/chmod/chmod.c
Expand Up @@ -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[])
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

0 comments on commit c51532a

Please sign in to comment.