Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 Jul 2009 15:52:19 +0000 (UTC)
From:      Edward Tomasz Napierala <trasz@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r195243 - head/bin/chmod
Message-ID:  <200907011552.n61FqJL5016996@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: trasz
Date: Wed Jul  1 15:52:19 2009
New Revision: 195243
URL: http://svn.freebsd.org/changeset/base/195243

Log:
  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)

Modified:
  head/bin/chmod/chmod.c

Modified: head/bin/chmod/chmod.c
==============================================================================
--- head/bin/chmod/chmod.c	Wed Jul  1 15:37:23 2009	(r195242)
+++ head/bin/chmod/chmod.c	Wed Jul  1 15:52:19 2009	(r195243)
@@ -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);
+}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200907011552.n61FqJL5016996>