From owner-p4-projects@FreeBSD.ORG Sun Jul 6 08:57:57 2008 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 3C0C41065683; Sun, 6 Jul 2008 08:57:57 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 021161065681 for ; Sun, 6 Jul 2008 08:57:57 +0000 (UTC) (envelope-from trasz@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id DF8808FC12 for ; Sun, 6 Jul 2008 08:57:56 +0000 (UTC) (envelope-from trasz@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id m668vukA090287 for ; Sun, 6 Jul 2008 08:57:56 GMT (envelope-from trasz@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.2/8.14.1/Submit) id m668vue2090285 for perforce@freebsd.org; Sun, 6 Jul 2008 08:57:56 GMT (envelope-from trasz@freebsd.org) Date: Sun, 6 Jul 2008 08:57:56 GMT Message-Id: <200807060857.m668vue2090285@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to trasz@freebsd.org using -f From: Edward Tomasz Napierala To: Perforce Change Reviews Cc: Subject: PERFORCE change 144766 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 06 Jul 2008 08:57:57 -0000 http://perforce.freebsd.org/chv.cgi?CH=144766 Change 144766 by trasz@trasz_traszkan on 2008/07/06 08:57:32 With NFS4 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 NFS4 ACLs. Affected files ... .. //depot/projects/soc2008/trasz_nfs4acl/TODO#5 edit .. //depot/projects/soc2008/trasz_nfs4acl/bin/chmod/chmod.c#2 edit Differences ... ==== //depot/projects/soc2008/trasz_nfs4acl/TODO#5 (text+ko) ==== @@ -6,10 +6,6 @@ - Add error checking to acl_to_text_nfs4.c. -- Find out what to do with chmod(1). Right now, "chmod 600" on file - which already has mode 0600 does not call chmod(2) at all - and it - should, as it might cause ACL recomputation. - - Make access control more granular. - Attach ZFS to the framework. ==== //depot/projects/soc2008/trasz_nfs4acl/bin/chmod/chmod.c#2 (text+ko) ==== @@ -54,6 +54,7 @@ #include void usage(void); +int may_have_nfs4acl(const FTSENT *ent); int main(int argc, char *argv[]) @@ -180,8 +181,15 @@ break; } newmode = getmode(set, p->fts_statp->st_mode); - if ((newmode & ALLPERMS) == (p->fts_statp->st_mode & ALLPERMS)) - continue; + /* + * With NFS4 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) { + if ((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 +227,25 @@ "usage: chmod [-fhv] [-R [-H | -L | -P]] mode file ...\n"); exit(1); } + +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_EXTENDED_SECURITY_NP); + if (ret > 0) + supports_acls = 1; + else if (ret < 0 && errno != EINVAL) + warn("%s", ent->fts_path); + } + + return (supports_acls); +} +