Subject: [nfsv4] NFSv4 ACL and POSIX interaction / mask

From: Andreas Gruenbacher <[email-masked]>
Date: Mon, 3 Jul 2006 23:10:14 +0200

Hello,

I have been thinking about the problems of interaction between NFSv4 ACLs and 
POSIX, and particularly about the issue of masking permissions through chmod 
and after creating files or directories.

On a UNIX system that supports NFSv4 ACLs natively, I think we should try to 
accept as wide a range of NFSv4 ACLs as possible, but we must make sure that 
we can preserve POSIX semantics. In particular, this means that ACLs may 
contain ACEs for users other than OWNER@, GROUP@, and EVERYONE@, and that 
chmod(2) must continue to provide the same kinds of guarantees as without 
NFSv4 ACLs.

I am assuming here that NFSv4 ACLs shall be an additional rather than an 
alternate file access control mechanism in the POSIX sense: Alternate file 
access control mechanisms must ``be enabled only by explicit user action, on 
a per-file basis by the file owner or a user with the appropriate 
privilege'', and must ``be disabled for a file after the file permission bits 
are changed for that file with chmod( )'' according to POSIX. In other words, 
newly created files or directories would have alternate file access control 
mechanisms disabled. This would render NFSv4 ACLs essentially useless for 
UNIX processes, because they would almost always be disabled, and would only 
work for remote processes until a POSIX process chmods a file or creates a 
directory, which wouldn't get us very far.

Let's look at chmod(2): the mode specified in chmod(2) defines the permissions 
of three classes of users: owner, group, and other. Each class is assigned a 
set of the READ, WRITE, and EXECUTE permissions. This defines the maximum set 
of permissions that this class has at any moment.

In an NFSv4 ACL, each entry must be in exactly one of the three classes of 
users: OWNER@ is in the owner class, GROUP@ and additional users and groups 
listed in the ACL are in the group class, and EVERYONE@ is in the other 
class.

No ACL entry shall granted permissions that exceed the permissions of its 
class. (Additional permissions in a class could be enabled explicitly, which 
would amount to an alternate file access mechanism, though.)

Note that we must not allow an ACE to be in no class, either: if we did, a 
chmod call with mode 0 would not disable all access, which would conflict 
with POSIX.

Note that this definition is in line with POSIX 1003.1e draft 17 [2], while it 
conflicts with the IETF NFS Version 4 ACLs draft [1], which associates only 
GROUP@ entries with the group file mode permission bits in section 5.1. The 
relevant text of IETF NFS Version 4 ACLs draft [1] is also found in NFSv4 
Minor Version 1 [4].

We want chmod(2) to be non-destructive, so that a chmod to a more restrictive 
mode and back to the original mode will leave the file with the same 
permissions as before the changes.

According to NFS Version 4 ACLs [1], it has been tried to replace the entire 
ACL with an ACL that only grants the permissions specified by the new mode. 
This approach has two drawbacks: first, it is destructive, and additional 
permissions granted are lost in the first chmod. Second, additional 
restrictions (DENY entries) may be lost as well. This is not acceptable, and 
unsurprisingly, users did not favor this approach.

POSIX ACLs have solved the non-destructiveness problem by introducing a mask 
ACL entry: the mask entry applies to all group class entries, and defines an 
upper bound to the permissions those entries may grant. POSIX ACLs only have 
ACL entries that allow permissions, and only specify READ, WRITE, and EXECUTE 
permissions. Therefore, the owner class and other class permissions are the 
permissions granted to the owner and to others, respectively. (Note the 
difference between these others and NFSv4's EVERYONE@ special identifier).

The mask concept is not part of NFSv4 ACLs. Marius A. Eriksen and others have 
proposed to emulate the POSIX ACL mask entry by prepending (with exception of 
OWNER@ and EVERYONE@ ACEs) each ALLOW ACE with a DENY ACE for the same user, 
group, or special identifier as in the ALLOW ACE. The permissions in the DENY 
ACE are set so that the entry denies the permissions not granted by the mask.

Unless we accept a very specific form of NFSv4 ACLs only (which would 
contradict the goal stated at the top of this message, and which would mean 
that interoperability with anything but POSIX ACLs would become difficult), 
there is no easy way to tell DENY entries introduced to emulate the mask from 
DENY entries added by hand. This has two potential consequences:

 - First, if we fail to identify such a mask-emulation DENY entry, we may end 
up inserting another such entry. We might end up doing so repeatedly.

 - Second, we may take a user-provided DENY entry for a mask-emulation DENY 
entry, and clear mask bits from that entry. This would contradict the user's 
intention. So the approach of inserting mask-emulation DENY entries is not 
good enough in general. (Mapping between NFSv4 and POSIX ACLs does not have 
this problem, because POSIX ACLs don't have DENY ACEs.)

In my opinion, there are two possible solutions for this problem: we can (1) 
devise a special kind of NFSv4 ACL entry that we will recognize as mask 
entry, or (2) give the owner/group/other class permission bits higher 
priority than the ACL entries, and only allow permissions that are allowed by 
both the ACEs and their associated classes.

In case (1), we could either keep prepending (almost) each ALLOW entry with an 
associated DENY entry and set a special flag in the DENY entry, or we could 
introduce something like a MASK@ special identifier, add MASK@ entries to the 
ACL in the appropriate places, and add the mask logic to the permission check 
algorithm.

We would need at most three MASK@ entries per ACL, one for each class of 
users: it should be obvious that we need a mask for the group class, which 
contains the GROUP@ entries and all entries for explicitly named users and 
groups. We want to avoid destroying permissions set explicitly for USER@ and 
EVERYONE@ entries after a chmod as well though. We could then use the mask 
mechanism to selectively turn on additional permissions not covered by READ, 
WRITE, and EXECUTE, as a kind of alternate file access control mechanism.

We could keep such extensions local to the server and not expose them over the 
protocol, with the obvious interoperability problems when copying files 
around, or we could make whichever extensions we need part of the NFSv4 
protocol.

Case (2) would be pretty simple to implement, but all permissions that are not 
covered by READ, WRITE, EXECUTE would always be masked (for correctness, even 
for remote clients), and there would be no controlled way to un-mask them.

Thoughts anyone?

Thanks,
Andreas

REFERENCES

[1] Sam Falkner et al.: NFS Version 4 ACLs, draft-ietf-nfsv4-acls-00.txt

[2] POSIX 1003.1e/2c draft 17 (withdrawn), 
http://wt.xpilot.org/publications/posix.1e

[3] Marius Aamodt Eriksen et al.: Mapping Between NFSv4 and Posix Draft ACLs, 
draft-ietf-nfsv4-acl-mapping-04.txt

[4] Spencer Shepler (editor): NFSv4 Minor Version 1, 
draft-ietf-nfsv4-minorversion1-03.txt

-- 
Andreas Gruenbacher <[email-masked]>
Novell / SUSE Labs

_______________________________________________
nfsv4 mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/nfsv4

---

From: Andreas Gruenbacher <[email-masked]>
Date: Fri, 7 Jul 2006 13:55:30 +0200

On Monday, 3. July 2006 23:10, Andreas Gruenbacher wrote:
> Hello,
>
> I have been thinking about the problems of interaction between NFSv4 ACLs
> and POSIX, and particularly about the issue of masking permissions through
> chmod and after creating files or directories.

Here is a follow-up after some personal feedback from Sam. I believe that 
draft-ietf-nfsv4-acls-00 is not ready to become part of the NFSv4 Minor 
Version 1 RFC: some assumptions are not correct from a POSIX point of view, 
and the way how chmod and file create modes are applied to NFSv4 ACLs is weak
and not guaranteed to be correct.

I will first try to clarify some of the points I tried to make in the previous 
posting and point out deficiencies in draft-ietf-nfsv4-acls-00. Then I will 
propose an alternative design which is more correct than introducing DENY 
entries to mask permissions. (As a bonus, it is easier to implement. too.)

> On a UNIX system that supports NFSv4 ACLs natively, I think we should try
> to accept as wide a range of NFSv4 ACLs as possible, but we must make sure
> that we can preserve POSIX semantics. In particular, this means that ACLs
> may contain ACEs for users other than OWNER@, GROUP@, and EVERYONE@, and
> that chmod(2) must continue to provide the same kinds of guarantees as
> without NFSv4 ACLs.
>
> access control mechanisms must ``be enabled only by explicit user action,
> on a per-file basis by the file owner or a user with the appropriate
> privilege'', and must ``be disabled for a file after the file permission
> bits are changed for that file with chmod( )'' according to POSIX. In other
> words, newly created files or directories would have alternate file access
> control mechanisms disabled. This would render NFSv4 ACLs essentially
> useless for UNIX processes, because they would almost always be disabled,
> and would only work for remote processes until a POSIX process chmods a
> file or creates a directory, which wouldn't get us very far.

As Sam pointed out, a subset of NFSv4 ACLs maps to an additional file access 
control mechanism, while the rest goes beyond that, and therefore is an 
alternate file access control mechanism.

It is important to understand how POSIX defines additional file access control 
mechanisms:

[] 3.4 Additional File Access Control Mechanism
[] An implementation-defined mechanism that is layered upon the access control
[]  mechanisms defined here, but which do not grant permissions beyond those
[]  defined herein, although they may further restrict them.

In other words, when a file has just been created and after chmod, the file 
mode permission bits define an upper bound to the permissions granted to 
anyone on the system, and nobody has additional permissions. Additional 
permissions (as an alternate file access control mechanism) may be 
enabled explicitly, but the next chmod must disable them again.

We can classify the permissions that NFSv4 ACLs grant into additional and 
alternate mechanisms as follows: everything covered by the POSIX 
read/write/execute permissions (such as ACE4_READ_DATA, but also 
ACE4_APPEND_DATA) is additional, while everything beyond that (such as 
ACE4_WRITE_OWNER) is alternate. Under this definition, all NFSv4 ACLs that 
grant no more than ACE4_READ_DATA, ACE4_LIST_DIRECTORY, ACE4_WRITE_DATA, 
ACE4_ADD_FILE, ACE4_APPEND_DATA, ACE4_ADD_SUBDIRECTORY, 
ACE4_READ_NAMED_ATTRS, ACE4_WRITE_NAMED_ATTRS, ACE4_EXECUTE, 
ACE4_READ_ATTRIBUTES, ACE4_WRITE_ATTRIBUTES, ACE4_READ_ACL, and 
ACE4_SYNCHRONIZE would count as additional access control mechanisms. All 
others with ACE4_WRITE_ACL, ACE4_WRITE_OWNER, ACE4_DELETE_CHILD, and 
ACE4_DELETE are alternate.

As said already, the POSIX file mode permission bits define the permissions of 
three classes: owner, group, and other. An additional file access control 
mechanism may only further restrict the permissions granted to those classes.

To map NFSv4 ACLs to an additional file access control mechanism,

 - we must map each NFSv4 ACL entry to exactly one of the three classes.

 - we must ensure that the ACL does not grant any permissions that go beyond
   the class permissions after a chmod or create.

 - in particular, we must ensure that the ACL grants no "alternate"
   permissions after a chmod or create.

We are free to provide mechanisms by which more permissions may be enabled by 
explicit user action, on a per-file basis by the file owner or a user with 
the appropriate privilege, according to POSIX.

The POSIX definitions of the three file permission classes are:

[] 3.173 File Owner Class
[] The property of a file indicating access permissions for a process related
[] to the user identification of a process. A process is in the file owner
[] class of a file if the effective user ID of the process matches the user ID
[] of the file.

[] 3.166 File Group Class
[] The property of a file indicating access permissions for a process
[] related to the group identification of a process. A process is in
[] the file group class of a file if the process is not in the file owner
[] class and if the effective group ID or one of the supplementary group
[] IDs of the process matches the group ID associated with the file. Other
[] members of the class may be implementation-defined.

[] 3.172 File Other Class
[] The property of a file indicating access permissions for a process related
[] to the user and group identification of a process. A process is in the file
[] other class of a file if the process is not in the file owner class or file
[] group class.

The key fact in these definitions is that an implementation may define 
additional members of the File Group Class, while the other classes are not 
extensible.

Under this definition, we end up with the following mapping:

 - OWNER@ entries are in the File Owner Class,
 - EVERYONE@ entries are in the File Other Class,
 - every other entry is in the File Group Class(*).

 (*) User entries for the user who is the current file owner are a special
     case: due to how the NFSv4 ACL permission check algorithm is specified,
     I believe that they should be put in the OWNER@ class.

> Note that this definition is in line with POSIX 1003.1e draft 17 [2], while
> it conflicts with the IETF NFS Version 4 ACLs draft [1], which associates
> only GROUP@ entries with the group file mode permission bits in section
> 5.1. The relevant text of IETF NFS Version 4 ACLs draft [1] is also found
> in NFSv4 Minor Version 1 [4].

Section 5.1 of [1] needs to be fixed: we must set the permission bits so that 
they are a superset of the permissions of all the entries in the respective 
class. (We cannot represent permissions that are not supersets of 
POSIX read, write, execute in the class, but that is not a problem, as we will 
see later.)

Non-monotonic permissions
=========================

Note that with arbitrary NFSV4 ACLs, the permissions granted to a process from 
multiple ACL entries will accumulate. This means that permissions across 
multiple classes may accumulate as well. This can be prevented with DENY 
entries in the ACL, e.g.,

	OWNER@:mask1::ALLOW
	OWNER@:^mask1::DENY
	user@domain:mask2::ALLOW
	group@domain:mask3:ACE4_IDENTIFIER_GROUP:ALLOW
	user@domain:^mask2::DENY
	group@domain:^mask3:ACE4_IDENTIFIER_GROUP:DENY
	EVERYONE:mask4::ALLOW

This means that we will not have to deal with this special case when computing 
the file mode permission bits, and we can achieve consistency by forcing ACLs 
to be "well structured".

We could also leave this as an implementation consideration: ACLs which are 
not "well structured" in the above sense will grant permissions that go 
beyond what an additional access control mechanism may grant *only* for 
non-monotonic file mode permission bits. With non-monotonic I mean file mode 
permission bits which grant more permissions to the group class than to the 
owner class, or more permissions to the other class than to the group class. 

> We want chmod(2) to be non-destructive, so that a chmod to a more
> restrictive mode and back to the original mode will leave the file with the
> same permissions as before the changes.
>
>[...]
>
> POSIX ACLs have solved the non-destructiveness problem by introducing a
> mask ACL entry: the mask entry applies to all group class entries, and
> defines an upper bound to the permissions those entries may grant. POSIX
> ACLs only have ACL entries that allow permissions, and only specify READ,
> WRITE, and EXECUTE permissions. Therefore, the owner class and other class
> permissions are the permissions granted to the owner and to others,
> respectively. (Note the difference between these others and NFSv4's
> EVERYONE@ special identifier).
>
> The mask concept is not part of NFSv4 ACLs. Marius A. Eriksen and others
> have proposed to emulate the POSIX ACL mask entry by prepending (with
> exception of OWNER@ and EVERYONE@ ACEs) each ALLOW ACE with a DENY ACE for
> the same user, group, or special identifier as in the ALLOW ACE. The
> permissions in the DENY ACE are set so that the entry denies the
> permissions not granted by the mask.

Internet draft-ietf-nfsv4-acls-00.txt [1] uses the same mechanism to implement 
masking.

> there is no easy way to tell DENY entries introduced to emulate the mask
> from DENY entries added by hand. This has two potential consequences:
>
>  - First, if we fail to identify such a mask-emulation DENY entry, we may
> end up inserting another such entry. We might end up doing so repeatedly.
>
> entry, and clear mask bits from that entry. This would contradict the
> user's intention. So the approach of inserting mask-emulation DENY entries
> is not good enough in general. (Mapping between NFSv4 and POSIX ACLs does
> not have this problem, because POSIX ACLs don't have DENY ACEs.)

Therefore, the mechanism described in section 5.3 is not suitable for our 
purposes, and we need to replace it with something better.

> In my opinion, there are two possible solutions for this problem: we can
> (1) devise a special kind of NFSv4 ACL entry that we will recognize as mask
> priority than the ACL entries, and only allow permissions that are allowed
> by both the ACEs and their associated classes.

A third option exists as well which fits in very well with POSIX and can be 
implemented in NFSv4 in a backward compatible way.

Alternative Proposal
====================

Instead of adding DENY entries to the ACL for the purpose of masking, attach 
three optional attributes to each file: owner_class_mask, group_class_mask, 
and other_class_mask. When those attributes are present, they define which 
permissions in an ACE are effective.

Each ACE is is restricted by one of these mask attributes in each access 
check:

 - OWNER@ entries and entries for the user@domain that currently owns the file
   are restricted by owner_class_mask.

 - EVERYONE@ entries are restricted by other_class_mask.

 - All other entries are restricted by group_class_mask.

The effective permissions are computed as the bitwise and (&) of the ACE mask 
and the associated class_mask attribute.

When doing a chmod(2) or when applying a create mask, the owner_class_mask, 
group_class_mask, and other_class_mask attributes are modified according to 
the owner class, group class, and other class permissions of the mode 
parameter as follows:

 - The POSIX read permission implies the ACE4_READ_DATA, ACE4_READ_ATTRIBUTES, 
ACE4_READ_ACL, and ACE4_SYNCHRONIZE bitmask flags.

 - The POSIX write permission implies the ACE4_WRITE_DATA, ACE4_APPEND_DATA, 
ACE4_WRITE_ATTRIBUTES, ACE4_DELETE_CHILD, and ACE4_SYNCHRONIZE bitmask flags.

 - The POSIX execute permission implies the ACE4_EXECUTE mask.

This saves us from bloating ACLs with DENY entries, is more efficient when 
doing a chmod, and also saves us from destroying permissions in user provided 
DENY entries.

When an ACL is set, then set all mask attributes to the values provided in the 
same SETATTR operation, and set the remaining mask attributes to the union of 
all ALLOW ACL entries in the ACL that the class applies to.

Without any further changes, NFSv4 clients not aware of the three optional 
attributes would not be aware of the restrictions imposed by those masks when 
querying for the ACL. This would create an interoperability problem, and 
possible security holes. To solve this problem, we can extend the GETATTR 
operation as follows:

When a client requests the ACL attribute, check if it also requests one or 
more of the three optional owner_class_mask, group_class_mask, or 
other_class_mask attributes. If it does, then send the requested attributes 
as they are. If the client requests only the ACL without any of the masks, 
return an ACL with only effective mask flags set, and with all other flags 
removed.

Alternate permissions in the ACL can be enabled by either setting an ACL 
without providing full mask entries, or by setting the appropriate bit(s) in 
the corresponding mask entry or entries.

When comparing POSIX ACLs and the NFSv4 ACL + mask attributes as proposed 
here, one obvious difference is that POSIX ACLs have only one mask entry, 
while I propose three mask entries here. The reason for this is that POSIX 
ACLs can at most grant read, write, and execute permissions, and so with 
POSIX ACLs, the File Owner Class permissions are always identical to the 
permissions granted to the owner, and the File Other Class permissions are 
always identical to the permissions granted to others. With NFSv4 ACLs, 
OWNER@ and EVERYONE@ entries may grant additional permissions that go beyond 
what POSIX read, write, and execute can grant, and we need a mechanism so 
that those alternate permissions can be turned off by chmod and during file 
create without destroying the permissions.

I would appreciate if you could take this alternative proposal into 
consideration when deciding how to proceed with NFSv4 Minor 
Version 1 at next week's IETF 66 meeting.

Thanks and best regards,
Andreas

> [3] Marius Aamodt Eriksen et al.: Mapping Between NFSv4 and Posix Draft
> ACLs, draft-ietf-nfsv4-acl-mapping-04.txt
>

---

From: Sam Falkner <[email-masked]>
Date: Fri, 07 Jul 2006 21:45:38 -0600

> and not guaranteed to be correct.

I disagree -- see below.

> alternate file access control mechanism.

Yes -- ALLOW ACEs are alternate file access control, and DENY ACEs  
are additional file access control.

> enabled explicitly, but the next chmod must disable them again.

The use of the word "Additional" is confusing in the above  
sentence.  :-)  I think you mean "more", or similar, but "Additional"  
has a very specific meaning which (I think) isn't what you mean.

> ACE4_WRITE_OWNER) is alternate.

Note well: this is quite different from draft-ietf-nfsv4- 
minorversion1-03.txt, i.e. this is an alternate proposal.

> Under this definition, all NFSv4 ACLs that

I don't understand what is gained by this designation of additional  
access control mechanisms.  If you really say that this ACL:

OWNER@:read_data:allow
[email-masked]:read_data:allow

is additional file access control, then what is the mode on such a  
file?  Unless the mode says "group can read", then [email-masked]  
wouldn't be able to read, if the ACL is additional file access  
control.  What if you want [email-masked] to be able to read, but  
you don't want the file's owning group to read?

>    the class permissions after a chmod or create.

Additional File Access Control must not grant beyond the class  
permissions *ever*, not just after create or chmod.

>    permissions after a chmod or create.

I don't understand this; you began this section with "To map NFSv4  
ACLs to an additional...", but here, you seem to be describing ACLs  
as an alternate file access control mechanism.

>  - EVERYONE@ entries are in the File Other Class,

No, I don't think EVERYONE@ is in the File Other Class.  Given this ACL:

EVERYONE@:read_data:deny
OWNER@:read_data:allow

the owner would NOT be able to read.  In other words, file owner  
class and file group class are also affected by EVERYONE@ ACEs.

>  - every other entry is in the File Group Class(*).

including EVERYONE@.  ;-)

>      I believe that they should be put in the OWNER@ class.

The current minorversion1 draft has a similar design constraint.

> POSIX read, write, execute in the class, but that is not a problem,  

We must do so carefully.  I'm not convinced that a superset is the  
best way to go, but we should talk about this later.

> Non-monotonic permissions

Yuck!  I'm glad you're not proposing this as a general NFSv4 ACL  
model.  :-)

> owner class, or more permissions to the other class than to the  

I'm sorry, I just don't follow that paragraph.

>> from DENY entries added by hand.

I would refute this; see below.

>> This has two potential consequences:
>>

But we will not ever fail to identify such a mask-emulation DENY  
entry, when it is one that was created by a previous chmod.  Only in  
a degenerate case of modify-acl-carefully, chmod, modify-acl- 
carefully, chmod, etc., would you get a growing ACL problem.

>> is not good enough in general.

A user-provided DENY entry would have to fit into a very specific and  
somewhat nonsensical form in order to be misidentified.  Here's an  
example:

[email-masked]:read_data:deny
[email-masked]:read_data:allow

If a "chmod 444" were done, the deny ACE above would be modified.   
Any other cases of chmod modifying a user-provided ACE would have to  
be essentially the same as the above example.  I think that that's an  
acceptable situation.

>> (Mapping between NFSv4 and POSIX ACLs does

> purposes, and we need to replace it with something better.

I don't agree that 5.3 is not suitable, but I would love to see  
something better.

>> by both the ACEs and their associated classes.

Yikes -- I don't like either of the above solutions; let's look at  
the third...

> implemented in NFSv4 in a backward compatible way.

I take it you mean that "the effective access mask bits for ACEs of  
type ALLOW"?

> ACE4_WRITE_ATTRIBUTES, ACE4_DELETE_CHILD, and ACE4_SYNCHRONIZE  

I'm not sure I agree about ACE4_WRITE_ATTRIBUTES, but that's a minor  
detail.

> doing a chmod, and also saves us from destroying permissions in  

Yes, but at the cost of adding new file attributes...  Don't get me  
wrong, I do see merit in this proposal, but I don't know if it'll be  
acceptable.

> all ALLOW ACL entries in the ACL that the class applies to.

This doesn't take the ordering of the ACL into account; is this your  
intention?  So

GROUP@:read_data/write_data:DENY
GROUP@:read_data/write_data:ALLOW

would result in a group_class_mask of read_data|write_data, right?   
(I'm not saying it's wrong, I'm just making sure I understand.)

> return an ACL with only effective mask flags set, and with all  

I assume you mean in the ALLOW ACEs only, right?

> the corresponding mask entry or entries.

Yes, I think I understand.

> create without destroying the permissions.

Given that EVERYONE@ is not equivalent to the POSIX "other" class, it  
could be trimmed down to two.

> Version 1 at next week's IETF 66 meeting.

This proposal certainly has its merits.  I have doubts about the  
feasibility of adding two or three new file attributes, and new as- 
yet-unimplemented semantics, into the minorversion1 draft.  I have  
doubts about how this would be implemented on a Windows-based server.

The current design specified in draft-ietf-nfsv4-minorversion1-03.txt  
has implementation experience -- it's released in Solaris 10 update  
3, a shipping product.  It meets strict POSIX requirements for those  
implementations that choose to conform to POSIX.  I believe it's  
fully implementable on a Windows-based server.

I too hope that this can be discussed at IETF 66.

- Sam

---

From: Sam Falkner <[email-masked]>
Date: Sat, 08 Jul 2006 08:32:06 -0600

On Jul 7, 2006, at 9:45 PM, Sam Falkner wrote:

> I'm not sure I agree about ACE4_WRITE_ATTRIBUTES, but that's a  
> minor detail.
>
> wrong, I do see merit in this proposal, but I don't know if it'll  
> be acceptable.
>
> This doesn't take the ordering of the ACL into account; is this  
> your intention?  So
>

More thoughts on this model and getattr.  Giving different versions  
of the ACL depending on how it's requested leads to problems.  To  
recap, if NFSv4.0 client asks for the post-chmod ACL, it'll get the  
inhibited version of the ACL.  Tools for modifying an ACL invariably  
do read/modify/write.  So NFSv4.0 client reads the stripped down ACL,  
modifies it, and writes it back.  At this point, information is lost  
-- the stripped down ACL is now the only ACL we have.  This leads to  
future environments where some classes of clients inadvertently do  
bad things, while others behave more correctly.

The ACL model in draft-ietf-nfsv4-minorversion1-03.txt always shows  
every client the entire, correct ACL, every time.

- Sam

> Given that EVERYONE@ is not equivalent to the POSIX "other" class,  
> it could be trimmed down to two.
>
> The current design specified in draft-ietf-nfsv4- 
> minorversion1-03.txt has implementation experience -- it's released  
> in Solaris 10 update 3, a shipping product.  It meets strict POSIX  
> requirements for those implementations that choose to conform to  
> POSIX.  I believe it's fully implementable on a Windows-based server.
>

---

From: Andreas Gruenbacher <[email-masked]>
Date: Sun, 9 Jul 2006 18:22:43 +0200

On Saturday, 8. July 2006 05:45, Sam Falkner wrote:
> >> I have been thinking about the problems of interaction between
> >> NFSv4 ACLs and POSIX, and particularly about the issue of masking
> >> permissions through chmod and after creating files or directories.
> >
> > Here is a follow-up after some personal feedback from Sam. I
> > believe that draft-ietf-nfsv4-acls-00 is not ready to become part of the
> > NFSv4 Minor Version 1 RFC: some assumptions are not correct from a POSIX
> > point of view, and the way how chmod and file create modes are applied to
> > NFSv4 ACLs is weak and not guaranteed to be correct.
>
> I disagree -- see below.

Here are some facts to back my points: Let's assume that a file inherits the 
following ACL when being created (I am using ^(...) here with the meaning of 
"all bitflags except ..."):

	OWNER@:READ_DATA/WRITE_DATA::ALLOW
	OWNER@:^(READ_DATA/WRITE_DATA)::DENY
	GROUP@:READ_DATA::ALLOW
	user@domain:READ_DATA/WRITE_DATA::ALLOW
	GROUP@:^READ_DATA::DENY
	user@domain:^(READ_DATA/WRITE_DATA)::DENY
	EVERYONE@:READ_DATA::ALLOW

This acl is "well structured" in the POSIX sense: OWNER@ will only get the 
owner permissions and none of the other permissions, user@domain and GROUP@ 
will only get the permissions intended for them, and only others (neither 
OWNER@ nor user@domain nor GROUP@) will get EVERYONE@ permissions; in other 
words, the acl is even correct for non-monotonic permissions.

According to section 5.1 of draft-ietf-nfsv4-acls [1], the resulting file mode 
permission bits for this acl shall be rw-r--r--. After a chmod or a file 
create, alternate file access control mechanisms must be disabled and only 
additional file access control mechanisms may remain active. According to 
POSIX, additional file access control mechanisms require that no user may be 
granted more permissions than the respective file classes permit. In this 
case, user@domain clearly is not in the File Owner Class. (According to 
POSIX, user@domain must be in the File Group Class.) The user@domain user is 
granted WRITE_DATA though, which is *incorrect* from a POSIX point of view.

Next, let's assume than an ACL contains the following pair of user-provided 
entries:

	GROUP@:WRITE_DATA::DENY
	GROUP@:READ_DATA::ALLOW

Clearly the user's intention is to deny WRITE_DATA access to GROUP@. The 
algorithm to apply a mode to an existing ACL will remove the WRITE_DATA bit 
from the GROUP@:WRITE_DATA::DENY entry when a chmod(..., 0770) is done 
though. This is counter to the user's intention, so I would call that *wrong* 
as well. It also violates the principle of least surprise. There really is no 
safe way to tell user-provided ACL entries from artificially made up ACL 
entries.

draft-ietf-nfsv4-acls is missing a clear classification of ACL entries into 
the File Owner, File Group, and File Other classes. Every ACL entry must be 
in one of the three classes in order to compute appropriate file mode 
permission bits when setting an ACL, and after inheriting permissions. This 
classification also determines which effect chmod will have on an ACL.

So draft-ietf-nfsv4-acls is *incorrect* and *wrong* from a POSIX point of 
view, while my alternative proposal is correct, apart from being simpler to 
implement. I hope that my emails and some background reading (like the file 
access related parts of the POSIX definitions volume [5], a paper that 
explains POSIX ACLs and how they are implemented on Linux [6], and perhaps 
1003.1e draft 17) will convince you about that.

Note that in traditional POSIX, permissions from multiple file classes will 
never accumulate: each user always is either granted the File Owner 
permission bits, the File Group permission bits, or the File Other permission 
bits. (Additional file access control mechanisms may further limit the 
permissions granted, and alternative file access control mechanisms may 
further limit or extend the permissions granted.) Permissions from multiple 
acl entries accumulate in the NFSv4 ACL model though, and so unless an acl is 
"well structured" in the above sense, permissions from multiple classes may 
accumulate.

> > I will first try to clarify some of the points I tried to make in
> > the previous posting and point out deficiencies in
> > draft-ietf-nfsv4-acls-00. Then I will propose an alternative design which
> > is more correct than introducing DENY entries to mask permissions. (As a
> > bonus, it is easier to implement. too.)
> >
> >> On a UNIX system that supports NFSv4 ACLs natively, I think we
> >> should try to accept as wide a range of NFSv4 ACLs as possible, but we
> >> must make sure that we can preserve POSIX semantics. In particular, this
> >> means that ACLs may contain ACEs for users other than OWNER@, GROUP@, and
> >> EVERYONE@, and that chmod(2) must continue to provide the same kinds of
> >> guarantees as without NFSv4 ACLs.
> >>
> >> alternate file access control mechanism in the POSIX sense: Alternate
> >> file access control mechanisms must ``be enabled only by explicit user
> >> action, on a per-file basis by the file owner or a user with the
> >> appropriate privilege'', and must ``be disabled for a file after the file
> >> permission bits are changed for that file with chmod( )'' according to
> >> POSIX. In other words, newly created files or directories would have
> >> alternate file access control mechanisms disabled. This would render
> >> NFSv4 ACLs essentially useless for UNIX processes, because they would
> >> almost always be disabled, and would only work for remote processes until
> >> a POSIX process chmods a file or creates a directory, which wouldn't get
> >> us very far. 
> >
> > As Sam pointed out, a subset of NFSv4 ACLs maps to an additional file
> > access control mechanism, while the rest goes beyond that, and therefore
> > is an alternate file access control mechanism.
>

This classification makes no sense, and it also does not match what you 
propose in section 5.3 of draft-ietf-nfsv4-acls, either: there are acls that 
contain ALLOW entries which are still only an additional file access control 
mechanism, so we really need to classify them as an additional file access 
control mechanism in order to avoid having to disable them during chmod or 
when inheriting permissions. If ALLOW ACEs were alternate in general, then we 
would have to disable them all after a chmod, and I think we agree that this 
would make ACLs practically useless in combination with POSIX.

The only classification that makes sense is by the permissions that an ACL 
grants. You have given an example of an ACL that clearly is an additional 
file access control mechanism only. With this kind of classification, a 
significant subset of NFSv4 ACLs can be treated as an additional file access 
control mechanism, which makes them actually useful even when POSIX systems 
and Windows (or other systems with NFSv4 ACLs or similar) interact and both 
change ACLs.

> > It is important to understand how POSIX defines additional file
> > access control mechanisms:
> >
> > [] An implementation-defined mechanism that is layered upon the
> > [] access control mechanisms defined here, but which do not grant
> > [] permissions beyond those defined herein, although they may further
> > [] restrict them. 
> >
> > In other words, when a file has just been created and after chmod,
> > the file mode permission bits define an upper bound to the permissions
> > granted to anyone on the system, and nobody has additional permissions.
> > Additional permissions (as an alternate file access control mechanism) may
> > be enabled explicitly, but the next chmod must disable them again.
>

I indeed meant more permissions as in additional mask bits granted, as opposed 
to an additional file access control mechanism in the sense how POSIX defines 
this term.

> minorversion1-03.txt, i.e. this is an alternate proposal.

Yes, this is a different approach of classifying NFSv4 ACLs into additional 
and alternate file access control mechanisms, which complies to POSIX as well 
as to the current NFSv4 RFC. It conflicts with draft-ietf-nfsv4-acls, and by 
implication with draft-ietf-nfsv4-minorversion1-03 [4], which includes the 
same text.

Note that draft-ietf-nfsv4-acls is inconsistent in itself: the algorithm in 
section 5.3 restricts which permissions an ACL grants by masking permissions 
(which implies that you are classifying by permission as opposed to turning 
off all ALLOW entries), while section 14.4 says that "the ALLOW type of ACE 
is considered to be an alternate file access control mechanism because it can 
further extend the permissions of a user".

> > Under this definition, all NFSv4 ACLs that grant no more than
> > ACE4_READ_DATA, ACE4_LIST_DIRECTORY, ACE4_WRITE_DATA, 
> > ACE4_SYNCHRONIZE would count as additional access control
> > mechanisms. All others with ACE4_WRITE_ACL, ACE4_WRITE_OWNER,
> > ACE4_DELETE_CHILD, and ACE4_DELETE are alternate.

> I'm not sure I agree about ACE4_WRITE_ATTRIBUTES, but that's a minor

I stand corrected that ACE4_WRITE_ATTRIBUTES is an alternate permission rather 
than an additional one: the POSIX read/write/execute permissions do not allow 
to write to inode attributes.

> access control mechanisms.

The benefit is that a more reasonable set of permissions can remain active 
across chmod and permission inheritance: if we assume that ALLOW ACEs are 
alternative, all ALLOW ACEs will have to be disabled when a chmod is done, or 
in the permissions that a file inherits. A chmod form one mode to another and 
back will disable all alternative file access control mechanisms; there is no 
way around that.

If we assume that certain permissions are in the additional class and others 
are in the alternative class, then we can disable only those additional 
permissions which exceed what the associated file class permits (remember 
that the file classes define the maximum permissions that a member of that 
class may have. We will always disable all alternative permissions upon 
chmod, because those are the entries which exceed what the file class may 
permit by definition, but we will leave as much of the additional 
permissions intact as possible.

Consider this ACL (I have used the same example above already):

	OWNER@:READ_DATA/WRITE_DATA::ALLOW
	OWNER@:^(READ_DATA/WRITE_DATA)::DENY
	GROUP@:READ_DATA::ALLOW
	user@domain:READ_DATA/WRITE_DATA::ALLOW
	GROUP@:^READ_DATA::DENY
	user@domain:^(READ_DATA/WRITE_DATA)::DENY
	EVERYONE@:READ_DATA::ALLOW

With the ALLOW = alternative classification, all allow entries would get 
disabled, and so this ACL would not grant any permissions to anybody no 
matter which chmod mode is used. With the classification I am proposing, this 
file would have rw-rw-r-- file mode permission bits. A chmod to rw-r----- 
would disable the user@domain:WRITE_DATA and EVERYONE@:READ_DATA permissions, 
but the other permissions would still remain effective.

Note that this is actually the behavior you are describing in section 5.3 of 
draft-ietf-nfsv4-acls-00, the draft is only missing a clear classification of 
ACEs into the File Owner, File Group, and File  Other classes.

One essential difference between draft-ietf-nfsv4-acls-00 and my proposal is 
the mechanism used to restrict the permissions that an ACL grants: 
draft-ietf-nfsv4-acls-00 inserts DENY entries in the acl at the appropriate 
places and updates them later as appropriate, while my proposal introduces 
optional mask attributes and only updates those attributes.

While draft-ietf-nfsv4-acls-00 style ACLs can be sent to all NFSv4 clients 
unmodified, we need to be careful when sending ACLs to clients in the 
presence of mask attributes: if a client is aware of the mask attributes, we 
can send the ACL directly. If the client is unaware of the mask attributes, 
we can choose to either send an ACL that only contains all the effective 
permissions and with the masked permissions removed, or we could first insert 
DENY entries in the ACL we send similar to section 5.3 of 
draft-ietf-nfsv4-acls-00 (but with the classification of ACEs into the file 
classes cleaned up).

> If you really say that this ACL: 
>
> OWNER@:read_data:allow
> is additional file access control,

Yes.

> then what is the mode on such a file?

The mode is r--r-----, which does *not* imply that the owning group has read 
access.

> Unless the mode says "group can read", then [email-masked] 
> control.

That's correct.

> What if you want [email-masked] to be able to read, but you don't want the
> file's owning group to read? 

POSIX does not require that r--r----- file mode permission bits give the 
owning group write access. The owning group permissions depend on which 
entries are in the acl: with File Group Class permissions of r--, if the acl 
contains a GROUP@:READ_DATA::ALLOW entry, the owning group is granted 
READ_DATA access. With no GROUP@ entry, a GROUP@:WRITE_DATA::ALLOW entry, or 
a GROUP@:READ_DATA::DENY entry before other entries that would give GROUP@ 
read access, GROUP@ would not be granted READ_DATA access.

There is one other case to look at though: while a chmod will disable all 
alternate permissions and no alternate permissions will be effective for 
newly created files, the mask attributes can be set explicitly, and alternate 
permissions may be enabled. Depending on which permissions the ACL grants, 
this may cause alternate permissions to become effective (alternate file 
access control mechanism), and in this case, more permissions may be granted 
than the file mode permission bits imply.

Setting the mask attributes should cause the file mode permission bits to be 
set to the value that most closely matches the mask attributes. (For example, 
setting the READ_DATA bitmask in group_class_mask should also set the read 
File Group Class permission).

I proposed that when a SETATTR of ACL is done without also setting the three 
*_class_mask attributes, then those*_class_mask attributes that are not 
specified should be computed as the union of the mask bits of the entries in 
the respective class. This means that a SETATTR of ACL may or may not amount 
to an alternate file access control operation.

I highly recommend to read POSIX Access Control Lists on Linux [6].

> > As said already, the POSIX file mode permission bits define the
> > permissions of three classes: owner, group, and other. An additional
> > file access control mechanism may only further restrict the permissions
> > granted to those classes.
> >
> >  - we must ensure that the ACL does not grant any permissions that
> > go beyond the class permissions after a chmod or create.
>

I am saying that permissions classified as alternate can never become 
effective as part of an additional file access control mechanism. This means 
that the ACL may still contain such alternate permissions, but we must ensure 
that these permissions will not become effective implicitly.

> > We are free to provide mechanisms by which more permissions may be
> > enabled by explicit user action, on a per-file basis by the file owner or
> > a user with the appropriate privilege, according to POSIX.

... and this would count as an alternate access control mechanism then.

> > [] The property of a file indicating access permissions for a
> > [] process related to the user identification of a process. A process
> > [] is in the file owner class of a file if the effective user ID of the
> > [] process matches the user ID of the file.
> >
> > [] the file group class of a file if the process is not in the file
> > [] owner class and if the effective group ID or one of the supplementary
> > [] group IDs of the process matches the group ID associated with the
> > [] file. Other members of the class may be implementation-defined.
> >
> > [] The property of a file indicating access permissions for a
> > [] process related to the user and group identification of a process.
> > [] A process is in the file other class of a file if the process is not
> > [] in the file owner class or file group class.
> >
> > additional members of the File Group Class, while the other classes
> > are not extensible.
> >

I strongly disagree. Please reconsider what I said about non-monotonic 
permissions and "well structured" acls (well-formed would have been a better 
term for it):

 - with well-formed ACLs, permissions from multiple classes cannot
   accumulate.

 - with arbitrary ACLs, permissions from multiple classes can
   accumulate. 

The well-formedness property of an ACL determines whether or not permissions 
may accumulate across classes. This does not invalidate the classification 
itself.

While being a perfectly fine NFSv4 ACL, the above ACL definitely is not 
well-formed.

Other than the fact that permissions may accumulate across classes (which only 
becomes a problem with non-monotonic file mode permission bits), "ill-formed" 
ACLs are not a problem.

For strict POSIX compliance, we must ensure that ACLs are well-formed after 
chmod, and that inherited ACLs will be well-formed as well. We could achieve 
this either by rejecting "ill-formed" ACLs during SETATTR of ACL (so that 
chmod and inherited permissions will always operate on well-formed acls), or 
we could try to convert arbitrary ACLs into well-formed ACLs during chmod and 
during permission inheritance (*). I am sure that there are some forms of 
NFSv4 ACLs which cannot be converted into well-formed ACLs without loss of 
information, so we would have to fail some chmods and file creates. This is 
ugly of course, and chmod errors in particular would most likely badly trap 
up some POSIX applications. I am undecided whether checking for well-formed 
ACLs in SETATTR or masageing ACLs in CHMOD and during creates is the lesser 
evil.

(*) Ill-formed ACLs are only an issue with a non-monotonic chmod or file 
create mode. This means that acl inheritance and chmod is POSIX compliant 
even with ill-formed ACLs as long as the mode is monotonic, and we actually 
only need to be careful in the (almost unrealistically) rare case where the 
mode is non-monotonic.

Because of the ramifications of trying to enforce well-formed ACLs or trying 
to constructing them after the fact, we may want to offer users a choice to 
violate this particular aspect of POSIX in certain installations: according 
to my experience, non-monotonic permissions do not actually occur in real 
life, so I am convinced that this is much less evil on users than totally 
strict POSIX compliance.

(The rules how well-formed ACLs must be structured are pretty simple. I don't 
want to detail them here at this point, but they can be distilled from 
Marius's draft-ietf-nfsv4-acl-mapping-04 [3].)

> >  (*) User entries for the user who is the current file owner are a
> >      special case: due to how the NFSv4 ACL permission check algorithm
> >      is specified, I believe that they should be put in the OWNER@
> >      class. 
>

... which comes entirely from draft-ietf-nfsv4-acls, if I am not mistaken.

> >> Note that this definition is in line with POSIX 1003.1e draft 17
> >> [2], while it conflicts with the IETF NFS Version 4 ACLs draft [1],
> >> which associates only GROUP@ entries with the group file mode
> >> permission bits in section 5.1. The relevant text of IETF NFS
> >> Version 4 ACLs draft [1] is also found in NFSv4 Minor Version 1 [4].
> >
> > Section 5.1 of [1] needs to be fixed: we must set the permission
> > bits so that they are a superset of the permissions of all the
> > entries in the respective class. (We cannot represent permissions that
> > are not supersets of POSIX read, write, execute in the class, but that
> > is not a problem, as we will
> > see later.)
>
> We must do so carefully.

No doubt about it.

> I'm not convinced that a superset is the best way to go, but we should talk
> about this later.  

Nothing else makes any sense at all IMO, and nothing else would be compatible 
with POSIX (as far as the additional file access control part goes), or in 
the spirit of POSIX (for the alternate file access control part). I think I 
have given sufficient arguments why this is so.

> > Note that with arbitrary NFSV4 ACLs, the permissions granted to a
> > process from multiple ACL entries will accumulate. This means that
> > permissions across multiple classes may accumulate as well. This can be
> > prevented with DENY entries in the ACL, e.g.,
> >
> > 	OWNER@:mask1::ALLOW
> > 	OWNER@:^mask1::DENY
> > 	user@domain:mask2::ALLOW
> > This means that we will not have to deal with this special case
> > when computing the file mode permission bits, and we can achieve
> > consistency by forcing ACLs to be "well structured".
>

Note that this is exactly how the proposed six-entry ACL on page 15 of 
draft-ietf-nfsv4-acls is structured, and how draft-ietf-nfsv4-acl-mapping-04 
ACLs are structured, and not by coincidence. I agree it's a bit ugly, but the 
accumulative semantics of NFSv4 ACLs don't leave us any other options.

> > We could also leave this as an implementation consideration: ACLs
> > which are not "well structured" in the above sense will grant permissions
> > that go beyond what an additional access control mechanism may grant
> > *only* for non-monotonic file mode permission bits. With non-monotonic I
> > mean  file mode permission bits which grant more permissions to the group
> > class than to the owner class, or more permissions to the other class than
> > to the group class.
>

I have already tried to reiterate this point further up in this reply. Still 
unclear?

> >> restrictive mode and back to the original mode will leave the file
> >> with the same permissions as before the changes.
> >>
> >> [...]
> >>
> >> WRITE, and EXECUTE permissions. Therefore, the owner class and other
> >> class permissions are the permissions granted to the owner and to others,
> >> exception of OWNER@ and EVERYONE@ ACEs) each ALLOW ACE with a DENY
> >> ACE for the same user, group, or special identifier as in the ALLOW ACE.
> >> The permissions in the DENY ACE are set so that the entry denies the
> > Internet draft-ietf-nfsv4-acls-00.txt [1] uses the same mechanism
> > to implement masking.
> >
> >> contradict the goal stated at the top of this message, and which
> >> would mean that interoperability with anything but POSIX ACLs would
> >> become difficult), there is no easy way to tell DENY entries introduced
> >> to emulate the mask from DENY entries added by hand.
>
> >>  - First, if we fail to identify such a mask-emulation DENY entry,
> >>    we may end up inserting another such entry. We might end up doing
> >>    so repeatedly.
>

Yes. And guess what will happen when POSIX and Windows applications will 
modify the permissions of the same file in turn? Note that even a chmod from 
one mode to another and back is enough to mess things up quite badly.

As far as I remember, Win2K always reorders ACL entries so that all DENY 
entries come before all ALLOW entries.

> >>  - Second, we may take a user-provided DENY entry for a mask-
> >> emulation DENY entry, and clear mask bits from that entry. This would
> >> contradict the user's intention. So the approach of inserting
> >> mask-emulation DENY entries is not good enough in general.
>

I already gave a more realistic example above:

	GROUP@:WRITE_DATA::DENY
	GROUP@:READ_DATA::ALLOW

> > Therefore, the mechanism described in section 5.3 is not suitable
> > for our purposes, and we need to replace it with something better.
>

Well, I did propose something *much* better.

> >> In my opinion, there are two possible solutions for this problem:
> >> we can (1) devise a special kind of NFSv4 ACL entry that we will
> >> recognize as mask entry, or (2) give the owner/group/other class
> >> permission bits higher priority than the ACL entries, and only allow
> >> permissions that are allowed by both the ACEs and their associated
> >> classes. 
>
> > A third option exists as well which fits in very well with POSIX
> > and can be implemented in NFSv4 in a backward compatible way.
> >
> > Alternative Proposal
> > ====================
> >
> > Instead of adding DENY entries to the ACL for the purpose of masking,
> > attach three optional attributes to each file: owner_class_mask,
> > group_class_mask, and other_class_mask. When those attributes are present,
> > they define which permissions in an ACE are effective.
> >
> > Each ACE is is restricted by one of these mask attributes in each
> > access check:
> >
> >  - OWNER@ entries and entries for the user@domain that currently
> >    owns the file are restricted by owner_class_mask.
> >
> > The effective permissions are computed as the bitwise and (&) of
> > the ACE mask and the associated class_mask attribute.
>

When determining access, it is irrelevant whether we mask only ALLOW entries, 
or ALLOW and DENY entries. When computing the mask attributes, we must only 
consider ALLOW entries though.

> > When doing a chmod(2) or when applying a create mask, the
> > owner_class_mask, group_class_mask, and other_class_mask attributes are
> > modified according to the owner class, group class, and other class
> > permissions of the mode parameter as follows:
> >
> >  - The POSIX read permission implies the ACE4_READ_DATA,
> >    ACE4_READ_ATTRIBUTES, ACE4_READ_ACL, and ACE4_SYNCHRONIZE bitmask
> >    flags. 
> >
> >  - The POSIX write permission implies the ACE4_WRITE_DATA,
> >    ACE4_APPEND_DATA, ACE4_WRITE_ATTRIBUTES, ACE4_DELETE_CHILD, and
> >    ACE4_SYNCHRONIZE bitmask flags.
>

I agree that POSIX write does not imply ACE4_WRITE_ATTRIBUTES.

> > This saves us from bloating ACLs with DENY entries, is more
> > efficient when doing a chmod, and also saves us from destroying
> > permissions in user provided DENY entries.
>

If the number of attributes is a concern, we could equally well store all 
three masks in a single three-entry array.

> > When an ACL is set, then set all mask attributes to the values
> > provided in the same SETATTR operation, and set the remaining mask
> > attributes to the union of all ALLOW ACL entries in the ACL that the
> > class applies to. 
>

Yes, order is irrelevant. Note that we must only consider the ALLOW entries 
when computing one of the mask attributes though.

> > Without any further changes, NFSv4 clients not aware of the three
> > optional attributes would not be aware of the restrictions imposed
> > by those masks when querying for the ACL. This would create an
> > interoperability problem, and possible security holes. To solve this
> > problem, we can extend the GETATTR
> > operation as follows:
> >
> > When a client requests the ACL attribute, check if it also requests
> > one or more of the three optional owner_class_mask, group_class_mask,
> > or other_class_mask attributes. If it does, then send the requested
> > attributes as they are. If the client requests only the ACL without
> > any of the masks, return an ACL with only effective mask flags set,
> > and with all other flags removed.
>

Probably not: the resulting ACL will grant exactly the same permissions either 
way. The whole ACL will become easier to understand if we also remove masked 
permissions from DENY ACL entries, so thais is why I would prefer this 
approach.

> > Alternate permissions in the ACL can be enabled by either setting
> > an ACL without providing full mask entries, or by setting the
> > appropriate bit(s) in the corresponding mask entry or entries.
>
> > When comparing POSIX ACLs and the NFSv4 ACL + mask attributes as
> > proposed here, one obvious difference is that POSIX ACLs have only
> > one mask entry, while I propose three mask entries here. The reason
> > for this is that POSIX ACLs can at most grant read, write, and
> > execute permissions, and so with POSIX ACLs, the File Owner Class
> > permissions are always identical to the permissions granted to the
> > owner, and the File Other Class permissions are always identical to
> > the permissions granted to others. With NFSv4 ACLs, OWNER@ and
> > EVERYONE@ entries may grant additional permissions that go beyond
> > what POSIX read, write, and execute can grant, and we need a
> > mechanism so that those alternate permissions can be turned off by
> > chmod and during file create without destroying the permissions.
>

See the well-formed ACL discussion above why EVERYONE@ should be in the File 
Other Class. But even if you totally object to this line of argumentation, 
the File Other Class would still need to restrict EVERYONE@ entries: all 
users other than the owner, owning group, or other users explicitly mentioned 
in the ACL will be granted EVERYONE@ permissions, and we must make sure that 
no user in the File Other Class will obtain any permissions beyond the File 
Other Class permissions after a chmod to be POSIX compliant. (Alternatively, 
we could remove permissions directly from all EVERYONE@ entries, but that 
would be destructive, which is exactly what we are trying to avoid.

> yet-unimplemented semantics,

Come on, it's not fair to pull the "as-yet-unimplemented" card. I am doing my 
best to argue my points as exhaustively as possible. I also have this 
proposal implemented, and I will start shaking out bugs tomorrow. I can make 
the prototype available publicly immediately in case you doubt me. My plan 
was to do so later this week, after some more debugging, though. I will 
definitely do everything I can to release an initial version within the next 
days.

> into the minorversion1 draft.  I have doubts about how this would be
> implemented on a Windows-based server. 

Not at all.  Windows server simply won't implement the mask attributes, and so 
they would see a perfect NFSv4 ACL world. Some permissions will get knocked 
out if the ACL contains some alternative permissions and the UNIX side later 
disables them, or if the ACL contains some permissions that the UNIX side 
decides to mask. This is *only* an issue when a Windows system modifies the 
permissions of a file after some permissions have been masked by a POSIX 
system (which means that the POSIX system must have modified the permissions 
of the same file as well). In particular, it is not an issue when only 
Windows systems access a file, or when only POSIX systems access a file.

> implementations that choose to conform to POSIX.  

It is *not* POSIX compliant unless it implements a few things other than 
described in draft-ietf-nfsv4-acls-00. I have argued why in the first part of 
my reply.

> I believe it's fully implementable on a Windows-based server.

Why should Microsoft spend time on draft-ietf-nfsv4-acls-00 other than for 
computing reasonable file modes(**)? NFSv4 ACLs are NTFS/CIFS ACLs minus 
Automatic Inheritance (see 
http://www1.ietf.org/mail-archive/web/nfsv4/current/msg03135.html)

(**) I already argue why the algorithm in section 5.1 of 
draft-ietf-nfsv4-acls-00 is wrong and not POSIX compliant. This can easily be 
fixed, but how it should be fixed depends on which approach is chosen.

Thanks,
Andreas

> >> draft-ietf-nfsv4-minorversion1-03.txt

[5] Standard for Information Technology — Portable Operating System Interface 
(POSIX®), http://www.opengroup.org/austin/

[6] Andreas Gruenbacher: POSIX Access Control Lists on Linux, 
http://www.suse.de/~agruen/acl/linux-acls/

[7] POSIX 1003.1e/2c draft 17, http://wt.xpilot.org/publications/posix.1e/

---

From: Lisa Week <[email-masked]>
Date: Sat, 08 Jul 2006 00:51:42 -0600

Hi Andreas,

I have a couple additional questions and comments.  See those inline...

Thanks,
Lisa

On Jul 7, 2006, at 9:45 PM, Sam Falkner wrote:

>>> NFSv4 ACLs
>> believe that
>> the previous
>>> should try
>> access control
>> the file
> sentence.  :-)  I think you mean "more", or similar, but  
> "Additional" has a very specific meaning which (I think) isn't what  
> you mean.
>
>> mechanisms. All

1.) If ACEs with ACE4_WRITE_ACL, ACE4_WRITE_OWNER, ACE4_DELETE_CHILD  
and ACE4_DELETE are alternate access control mechanisms, what will  
happen to ACEs with these access mask bits set upon chmod of the file?

For example, if we have the following ACL:
     [email-masked]:ACE4_WRITE_ACL:deny

		or even

     [email-masked]:ACE4_WRITE_OWNER:allow

Upon chmod we would have to disable them (however an implementation  
chooses to) and effectively remove it.

The thing that I have a problem with here is the fact that the  
changing of the file permission bits will affect what access has been  
defined in the ACL for things such as ACE4_WRITE_OWNER,  
ACE4_WRITE_ACL, etc.  A user setting the file permission bits is not  
saying anything about what they want to be done with any ACEs that  
include the ACE4_WRITE_OWNER mask bit.  Why would we want to mess  
with them?

2.) So, what if an ACE contained a mixture of the access mask bits  
that are alternate and additional?

Would we allow having ACE4_READ_DATA and ACE4_WRITE_ACL in the same  
ACE?  What would happen to an ACE such as this upon chmod?

>> permissions of
>> go beyond
>> enabled by
>> process related
>> process related

I'll restate it because it is important: EVERYONE@ is not equivalent  
to the File Other Class.  I believe the original intention was to  
have it be equivalent to one the Windows "well known sid":   http:// 
msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/ 
security/well_known_sid_type.asp

Really with NFSv4 ACLs, the only way we have the equivalent of a File  
Other Class is if the EVERYONE@ entries come at the end of the ACL.   
Such as this:

      owner@:execute:deny
      owner@:read_data/write_data/append_data/write_xattr/ 
write_attributes
          /write_acl/write_owner:allow
      group@:write_data/append_data/execute:deny
      group@:read_data:allow
      everyone@:write_data/append_data/write_xattr/execute/ 
write_attributes
          /write_acl/write_owner:deny
      everyone@:read_data/read_xattr/read_attributes/read_acl/ 
synchronize
          :allow

>> special
>>> [2], while
>> bits so that
>> process from
>> when computing
>> which are
>> to implement
>>> would mean
> entry, when it is one that was created by a previous chmod.  Only  
> in a degenerate case of modify-acl-carefully, chmod, modify-acl- 
>>> emulation DENY
> A user-provided DENY entry would have to fit into a very specific  
> and somewhat nonsensical form in order to be misidentified.  Here's  
> an example:
>
> Any other cases of chmod modifying a user-provided ACE would have  
> to be essentially the same as the above example.  I think that  
> that's an acceptable situation.
>
>> for our
>>> we can
>> and can be
>> access

Again, EVERYONE@ is not equivalent to the File Other Class.   
Depending on where an ACE pertaining to EVERYONE@ is in the ACL, it  
could even refer to the owner and the owning group.

>> owner_class_mask,
>> ACE4_READ_ATTRIBUTES,
>> ACE4_APPEND_DATA,

Yes, as [4] says, ACE4_WRITE_ATTRIBUTES is the "Permission to change  
the times associated with a file or directory to an arbitrary  
value."  Having that included in the POSIX write permission would not  
be correct, but as Sam said, that is minor.

>> efficient when
>> provided in the
>> optional
>> an ACL

Sorry, but I don't think I understand.  Andreas, what do you mean by  
"Alternate" permissions in that sentence?  It is unclear to me as to  
what happens to the access mask bits outside of the following:   
(collectively, these are the access mask bits that make up the POSIX  
read, write and execute permissions)
ACE4_READ_DATA, ACE4_READ_ATTRIBUTES, ACE4_READ_ACL, ACE4_SYNCHRONIZE  
ACE4_WRITE_DATA, ACE4_APPEND_DATA, ACE4_WRITE_ATTRIBUTES,  
ACE4_DELETE_CHILD and ACE4_EXECUTE

The remaining ones are:
ACE4_WRITE_ACL, ACE4_WRITE_OWNER, ACE4_DELETE, ACE4_READ_NAMED_ATTRS  
and ACE4_WRITE_NAMED_ATTRS

Are these "remaining ones" also given representation in the masks?   
Right away I assumed not, but now I am not sure.

Actually, I think what is confusing me is that before, when talking  
about Additional and Alternate file access control mechanisms, you  
said that: " All others with ACE4_WRITE_ACL, ACE4_WRITE_OWNER,  
ACE4_DELETE_CHILD, and ACE4_DELETE are alternate."

I just wonder how that statement  relates to the statement that  
"Alternate permissions in the ACL can be enabled by either setting an  
ACL without providing full mask entries, or by setting the  
appropriate bit(s) in the corresponding mask entry or entries."

>> proposed
>> mechanism so

---

From: Sam Falkner <[email-masked]>
Date: Mon, 10 Jul 2006 07:29:56 -0600

On Jul 9, 2006, at 10:22 AM, Andreas Gruenbacher wrote:

> permission bits for this acl shall be rw-r--r--.

Your proposal would give this mode: rw-rw-r--.  I think we should  
consider this more carefully.

> After a chmod or a file

No, it is not granted WRITE_DATA after a chmod().  After a chmod 644,  
there will be a "user@domain:WRITE_DATA::DENY" prepended.  This is  
well defined in the current minorversion1.  So it is not "incorrect  
from a POSIX point of view."

If your problem is with the computation of the mode, then we can  
discuss this some more.  But following create or chmod, user@domain  
is not granted WRITE_DATA.

> Clearly the user's intention is to deny WRITE_DATA access to GROUP@.

Yes, that *was* the user's intention, at the time the user set the ACL.

> The
> as well.

You would call it wrong that a chmod 770 would allow WRITE_DATA to  
members of the file's owning group?!  The  user did a chmod -- the  
user changed the permissions on the file!

This is not a POSIX flaw, and this is not a design flaw of any kind.   
"chmod 770" grants the owning group permission to write the file,  
period.

> It also violates the principle of least surprise.

Are you kidding?  Consider a directory with this ACE in its ACL:

GROUP@:READ_DATA/WRITE_DATA:FILE_INHERIT:DENY

With your proposal, open("foo", O_CREAT | O_RDWR, 0666) in this  
directory creates a file that the owning group is denied read and  
write permission.  Then:

% chmod 664 foo

Oops, owning group *still* cannot read or write the file!  Linux/*NIX  
has a long history of files having a mode attribute, and users using  
chmod to set permissions -- but not much history with NFSv4 ACLs.   
Your proposal more or less requires that Linux/*NIX users immediately  
start using ACLs, or face the "chmod doesn't fix my file" problem.

I've spent quite some time over the last few days looking for flaws  
in your proposal, but I'll admit that I missed this one, and it's a  
big one.

> There really is no

The semantics in draft-ietf-nfsv4-acls are well defined, predictable,  
consistent, and reasonable.

> classification also determines which effect chmod will have on an ACL.

I assume you mean "every ACE", not "every ACL".  As I mentioned  
above, I'm not sure whether or not this is a requirement, but it can  
be discussed further.  However, if it turns out that draft-ietf-nfsv4- 
acls is wrong in this regard, then the only consequence is a minor  
change to 5.1.

> 1003.1e draft 17) will convince you about that.

I am absolutely not convinced.

This email is getting *way* too long, so I will stop at this point,  
and perhaps will reply to other pieces in the future.

- Sam

---

From: "J. Bruce Fields" <[email-masked]>
Date: Mon, 10 Jul 2006 10:15:41 -0400

> consider this more carefully.

As Andreas says, this is what the posix draft would have you do.  It's
also what Linux (and, I assume, Solaris) do in the case of posix ACLs.

If the goals was compatibility with that posix draft, RFC3530 should
have specified that owner, other, and group bits be kept in sync with
(respectively) OWNER@, EVERYONE@, and the *maximum* of permissions given
to any other entity, rather than with OWNER@, EVERYONE@, and GROUP@.

> user changed the permissions on the file!

That is how posix acl's work; again, the group mode bit really
corresponds to the mask, not to the group acl entry:

	bfields@pickle:~$ getfacl foo
	# file: foo
	# owner: bfields
	# group: bfields
	user::rw-
	user:bfields:r--
	group::r--
	mask::r--
	other::---

	bfields@pickle:~$ chmod 770 foo
	bfields@pickle:~$ getfacl foo
	# file: foo
	# owner: bfields
	# group: bfields
	user::rwx
	user:bfields:r--
	group::r--
	mask::rwx
	other::---

Of course, "posix" acls aren't really posix, and we could do something
else if seems simpler.  Neither behavior seems intuitive to me in all
situations.

--b.

---

From: Sam Falkner <[email-masked]>
Date: Mon, 10 Jul 2006 09:32:28 -0600

> also what Linux (and, I assume, Solaris) do in the case of posix ACLs.

Not on Solaris.  With POSIX-draft ACLs, adding user:friend:rw- to a  
mode rw-r--r-- file still gives you rw-r--r--.  (And as you point out  
later, these ACLs ain't POSIX.)

> 	bfields@pickle:~$ getfacl foo

Again, not so on Solaris.  I wasn't aware that it was on Linux.  Sigh.

> else if seems simpler.  Neither behavior seems intuitive to me in all

I think having chmod be functional, i.e. chmod 770 gives write  
permission to the owning group, and an "ls -l" shows "rwxrwx---",  
would be best by far.

- Sam

---

From: "J. Bruce Fields" <[email-masked]>
Date: Mon, 10 Jul 2006 14:57:42 -0400

> later, these ACLs ain't POSIX.)
...
> > corresponds to the mask, not to the group acl entry:
...
> Again, not so on Solaris.  I wasn't aware that it was on Linux.  Sigh.

Ugh, sorry, OK, I didn't understand that we had that difference.

Personally, after seeing how complicated this can get, I almost think
I'd rather translate mode bits to NFSv4 ACLs by translating them to the
obvious ACL with 3 ALLOW ACEs.  And I'd rather translate the mask by
just masking out the bits in the obvious way, rather than adding DENY
aces.

At the very least, I'd rather not *forbid* such an implementation.  Yes,
it makes chmod irreversible, and it's wrong in a few rare corner cases,
but there are advantages to being wrong in a way that's simple and easy
to document.

If we're committed to getting the mask ace right, though, I would prefer
to adopt one of Andreas's solutions; they'd allow us to generate much
simpler ACLs.  I actually prefer the first proposal (letting the server
use the mode bits to mask out permissions).  But if we're going to add
explicit mask aces, then please, let's add only one.  I understand the
theoretical advantage to masking out all three classes, but that's
adding too much complexity for a few corner cases, and I don't think
it's going to be easy for users to understand.

We could add a new ACE type (in addition to ALLOW, DENY, AUDIT, ALARM),
and then a client could query the server's ability to represent the mask
with the aclsupport attribute and decide whether it wants to add DENY's
to represent the mask, or just give up on chmod reversibility.

--b.

---

From: Andreas Gruenbacher <[email-masked]>
Date: Mon, 10 Jul 2006 23:09:31 +0200

Lisa,

> chooses to) and effectively remove it.

In my proposal with the owner_class_mask, group_class_mask, and 
other_class_mask attributes, the chmod does not remove any mask bits from the 
ACEs, it sets the mask attributes to reflect the chmod mode parameter. The 
permission check algorithm only considers the effective permissions. So the 
mask attributes define which permissions are enabled and which are disabled.

> include the ACE4_WRITE_OWNER mask bit.  Why would we want to mess

It's quite simple: ACE4_WRITE_OWNER is an alternate access control mechanism 
under POSIX, no matter how we look at it. POSIX says that a chmod must disable 
alternate access control mechanisms, and it says that additional access 
control mechanisms may only introduce further restrictions. So a chmod will 
disable ACE4_WRITE_ACL and ACE4_WRITE_OWNER access, in both proposals.

> ACE?  What would happen to an ACE such as this upon chmod?

Of course we allow such ACEs. In fact, any NFSv4 ACL is allowed(*). Chmod does 
not touch the ACL, it adjusts the mask attributes so that only bits allowed 
by the respective class (File Owner Class, File Group Class, File Other 
Class) will be set in the mask attributes. Because only bits set both in an 
ACE and in the associated mask attribute are effective, all other permissions 
will automatically be disabled. Your proposal achieves the same effect by 
prepending ALLOW entries with DENY entries that deny masked permissions.

(*) See the well-formed ACLs and non-monotonic permissions discussion in the 
previous mails for why we may want to enforce a specific form of ACLs for 
full POSIX compliance, and in which conditions this matters.

> security/well_known_sid_type.asp

EVERYONE@ in NFSv4 ACLs indeed matches EVERYONE@ in Windows ACLs.

> Other Class is if the EVERYONE@ entries come at the end of the ACL.

Again, that's what I discussed as part of well-formed ACLs and non-monotonic 
permissions. Think of it this way:

We classify ACEs as follows:

  - OWNER@ entries and user@domain entries for the user who currently owns
    a file are in the File Owner Class,

  - all other entries are in the File Group Class.

Well-formed NFSv4 ACLs include DENY entries which make sure that the 
permissions granted to each class (File Owner Class, File Group Class, File 
Other Class) are isolated, and permissions granted to one class will not 
"swap over" to another class. In particular, this means that nobody in the 
File Owner and File Group classes will be granted any permissions from an 
EVERYONE@ ACE.

Arbitrary NFSv4 ACLs are not "well-formed" in this sense. They do not isolate 
the classes, and permissions from several classes may accumulate.

So, for strict POSIX compliance, we much make sure that ACLs are well-formed 
if both is true:

 - they are inherited or chmod'ed

 - and the mask applied to the ACL is non-monotonic

In all other cases (when an ACL is set, or when the permissions are monotonic) 
we will still be within the bounds of POSIX, and so we don't need to care.

So I'll restate that EVERYONE@ entries *are* in the File Other Class. Whether 
or not permissions may "swap over" from one class to another is determined by 
whether or not an ACL is "well-formed". This is an aspect orthogonal to the 
classification, to be dealt with separately. No other classification can fix 
the well-formedness aspect.

> could even refer to the owner and the owning group.

Wrong in my opinion: with an ACL that simply consists of a single EVERYONE@ 
ACE, the other permissions will apply to all classes, but that's because the 
ACL is not well-formed, not because EVERYONE@ is classified wrong.

> "Alternate" permissions in that sentence?

Here is a table of NFSv4 ACL mask bits and their classification. Mask bits are 
classified as Additional if they are either always permitted under POSIX 
(indicated as None in the table), or if they are equivalent to or a subset of 
a POSIX permission (indicated as Read, Write, Execute in the table). Mask 
bits are classified as Alternate if POSIX permissions cannot grant this 
permission (e.g., the equvalent of WRITE_ACL is implicitly granted to the 
owner, but there is no way to grant WRITE_ACL to an arbitrary other user).

READ_DATA               Additional (Read)
LIST_DIRECTORY          Additional (Read)
WRITE_DATA              Additional (Write)
ADD_FILE                Additional (Write)
APPEND_DATA             Additional (Write)
ADD_SUBDIRECTORY        Additional (Write)
READ_NAMED_ATTRS        Additional (Read) (**)
WRITE_NAMED_ATTRS       Additional (Write) (**)
EXECUTE                 Additional (Execute)
DELETE_CHILD            Additional (Write)
READ_ATTRIBUTES         Additional (None)
WRITE_ATTRIBUTES        Alternate
DELETE                  Alternate
READ_ACL                Additional (None)
WRITE_ACL               Alternate
WRITE_OWNER             Alternate
SYNCHRONIZE             Additional (None)

> It is unclear to me as to 

(**) I think that Read and Write imply ACE4_READ_NAMED_ATTRS and 
ACE4_WRITE_NAMED_ATTRS on Solaris, respectively, but I'm not sure. In case 
they are not, they would indeed count as Alternate.

> Are these "remaining ones" also given representation in the masks?

Yes. Alternate permissions must be subject to the mask attributes, because we 
must be able to disable them upon chmod and ACL inheritance. We can turn them 
back on later by setting the corresponding bitflags in the mask attributes 
(explicitly, or implicitly by setting a new ACL without also providing mask 
attributes, see further below).

POSIX does not require that alternate file access mechanisms be either on or 
off completely (i.e., an on/off switch); we are free to turn alternate 
permissions on or off individually. (We must turn them all off upon chmod and 
permission inheritance, but that should be clear by now.)

> appropriate bit(s) in the corresponding mask entry or entries."

My proposal was that a SETATTR of ACL that does not also set the mask 
attributes should automatically set all unspecified mask attributes to the 
union of all the ALLOW ACEs in the respective class. In other words, when a 
NFSv4.0 client executes an ACL SETATTR, all the ALLOW permissions in the ACL 
will automatically get set in the respective mask attributes as well, and 
will be effective. POSIX allows this behavior.

Andreas

---

From: Sam Falkner <[email-masked]>
Date: Mon, 10 Jul 2006 17:26:32 -0500

> it's going to be easy for users to understand.

How would a scheme that uses one and only one mask ACE work?  Are you  
thinking of catching mode 077 via a

OWNER@:READ_DATA/WRITE_DATA/EXECUTE:DENY

but having no way to catch mode 707 (because GROUP@:READ_DATA/ 
WRITE_DATA/EXECUTE:DENY might catch the owner)?

> to represent the mask, or just give up on chmod reversibility.

Please explain this further.  What would the fifth ACE type do?  What  
would it give you that DENY wouldn't?

- Sam

---

From: "J. Bruce Fields" <[email-masked]>
Date: Mon, 10 Jul 2006 18:39:39 -0400

On Mon, Jul 10, 2006 at 05:26:32PM -0500, Sam Falkner wrote:
> >If we're committed to getting the mask ace right, though, I would
> >prefer to adopt one of Andreas's solutions; they'd allow us to
> >generate much simpler ACLs.  I actually prefer the first proposal
> >(letting the  server use the mode bits to mask out permissions).  But
> >if we're going to add explicit mask aces, then please, let's add only
> >one.  I understand the theoretical advantage to masking out all three
> >classes, but that's adding too much complexity for a few corner
> >cases, and I don't think it's going to be easy for users to
> >understand.
> 

Andreas's proposal was actually to add something new to the protocol
(either a new attribute, or a new special entity (like "MASK@")) to
transfer the mask.  One of the advantages of doing that is that you'd no
longer have to use a bunch of DENY ACEs scattered through the ACL, all
carrying the same information.  E.g. you'd the client to include an ACE
like

	MASK@:READ_DATA:DENY

and modify the NFSv4 acl-permission-checking algorithm to mask out any
bitmasks anywhere other than OWNER@ or DENY@.

But Andreas was proposing that we actually add 3 different types of
masks, one for the OWNER@, one for EVERYONE@, and one for the others,
and I think that's overkill.  So that's what I'm arguing against.

> >We could add a new ACE type (in addition to ALLOW, DENY, AUDIT,
> >ALARM), and then a client could query the server's ability to
> >represent the  mask with the aclsupport attribute and decide whether
> >it wants to add  DENY's to represent the mask, or just give up on
> >chmod reversibility.
> 

It's just a way to pass the mask inside the ACL, but using a new ACE
type instead of a new special entity.

The advantage is that a client can actually probe to see if the server
supports it, so we wouldn't have to make it mandatory for a server to
support it.  But a separate attribute would also have that property.

--b.

---

From: "J. Bruce Fields" <[email-masked]>
Date: Mon, 10 Jul 2006 18:43:11 -0400

> bitmasks anywhere other than OWNER@ or DENY@.

(Err, I meant to say "OWNER@ or EVERYONE@", sorry....)

--b.

---

From: Andreas Gruenbacher <[email-masked]>
Date: Tue, 11 Jul 2006 00:50:57 +0200

> from a POSIX point of view."

Now that I look at the example again, I realize that I didn't define the 
create mode. With create mode 640 or less permissive, everything is fine. 
Let's assume create mode 664 though: then the file mode permission bits will 
still come out as rw-r--r--, but the ACL will grant WRITE_DATA to 
user@domain. That's the case I meant, and this case is not POSIX compliant.

> is not granted WRITE_DATA.

My problems are these:

* the algorithm in 5.3 is based on an ACE classification closer to the one
  I proposed, while the algorithm in 5.1 is based on a different
  classsification. We need to straighten this out, and I have argued
  repeatedly now why the classification I proposed leads to consistent
  and correct results. Most of the little inconsistencies in
  draft-ietf-nfsv4-acls-00 will stick out quite clearly once we agree on
  the right classification, and they will be easy to fix.

* the DENY entries introduced to mask permissions bloat the ACL, and make
  the ACL look strange to non-POSIX systems. The algorithm in section 5.3
  may remove permissions from user-provided DENY entries in some cases,
  and it may introduce duplicate DENY entries in some situations such as
  when another system reorders ACEs.Some versions of Windows do that.

The alternative approach I am proposing has a clear classification of ACEs, 
separates the orthogonal aspects of classification vs. well-formed acls, and 
has none of the weaknesses that the mask DENY ACEs cause.

> > Next, let's assume than an ACL contains the following pair of user-
> > provided entries:
> >
> > 	GROUP@:WRITE_DATA::DENY
> > 	GROUP@:READ_DATA::ALLOW
> >

Hm... not the best example because GROUP@ is the owning group, which 
corresponds to the group file mode permission bits in traditional POSIX. The 
problem is more difficult to see in this case, but I argue that the owhning 
group permissions and the group file mode permission bits are not the same
with ACLs: the file group mode permission bits restrict GROUP@ entries, and 
all user@domain and group@domain entries in the acl. For the sake of this 
example, substitute GROUP@ with user@domain though, and you'll see the 
problem more clearly: a user adds an explicit user@domain:WRITE_DATA::DENY 
entry to an acl which is followed by a user@domain:READ_DATA::ALLOW entry. 
After a chmod to 664 for example, this user suddenly has write access. The 
user clearly did not intend this to happen.

> > The algorithm to apply a mode to an existing ACL will remove the
> > WRITE_DATA bit

Yes. The user set the group file mode permission bits to rwx, in other words, 
ACEs in the File Group Class are limited to rwx after that. This does not 
imply that GROUP@ ACEs automatically have the equivalent of rwx though: the 
File Group Class contains several ACL entries, and you want to control the 
group file mode permission bits independently from the permissions of the 
owning group: otherwise, it wouldn't be possible to give the owning group 
fewer permissions than any user@domain or group@domain entry.

Let's look at this ACL:

	OWNER@:READ_DATA/WRITE_DATA::ALLOW
	GROUP@:READ_DATA::ALLOW
	user@domain:READ_DATA/WRITE_DATA::ALLOW
	EVERYONE@:READ_DATE::ALLOW

The GROUP@ and user@domain entries are in the File Group Class. After a chmod 
to 664, the ACL changes to this in Sam's proposal (some unnecessary 
permissions left out):

	OWNER@:EXECUTE::DENY
	OWNER@:READ_DATA/WRITE_DATA::ALLOW
	GROUP@:EXECUTE::DENY
	GROUP@:READ_DATA::ALLOW
	user@domain:EXECUTE::DENY
	user@domain:READ_DATA/WRITE_DATA::ALLOW
	EVERYONE@:WRITE_DATA/EXECUTE::DENY
	EVERYONE@:READ_DATE::ALLOW

In my proposal, the ACL would remain the same as before the chmod, but the 
owner_class_mask would become READ_DATA/WRITE_DATA, the group_class_mask 
would become READ_DATA/WRITE_DATA, and the other_class_mask would become 
READ_DATA. Note that the ACL does *not* grant write access to GROUP@ in 
either case.

> "chmod 770" grants the owning group permission to write the file,

No, see above. chmod 770 grants the File Group Class rwx, but ACLs act as an 
additional file access control mechanism here, and further limit the 
permissions granted to the owning group, which is a member of the File Group 
Class.

> Are you kidding?

I did not mean to.

> Consider a directory with this ACE in its ACL: 

To counter that argument, UNIX systems, including and foremost Solaris, but 
also others like Linux, have had POSIX ACLs for quite some time, and there 
the same "chmod doesn't fix my file" case exists, and it hasn't been a 
problem at all.

The GROUP@:READ_DATA/WRITE_DATA:FILE_INHERIT:DENY ace is a clear case of 
"doctor it hurts when I do this". As is an EVERYONE@:*::DENY ACL entry.

> start using ACLs, or face the "chmod doesn't fix my file" problem.

Chmod by definition *cannot* fix all permission problems in the presence of 
ACLs unless it completely replaces the ACL with something like the six-entry 
acl pattern in draft-ietf-nfsv4-acls-00. We already know that it's not a good 
idea to have chmod destroy acls.

> in your proposal, but I'll admit that I missed this one, and it's a

May I ask you to come back to this issue in case you still feel the same way 
after this reply?

> > There really is no safe way to tell user-provided ACL entries from
> > artificially made up ACL entries.
>

"Well defined": for one thing, draft-ietf-nfsv4-acls-00 is not explicit or 
clear about the ACE classification it is based on.

"Predictable": probably yes.

"Consistent": it uses different classifications in sections 5.1 and 5.3. 

"Reasonable": I don't like the DENY ACEs at all but that's a matter of taste. 
The problems which the DENY ACEs cause are no matter of taste though, and I 
would call the design unreasonable for that reason. Enforcing the DENY ACEs 
on thers when an alternative design exists that avoids the known problems 
that they have does not seem very reasonable to me, either.

The two proposals have two fundamental differences:

* My proposal tries to be clear in semantics, and separates orthogonal
  aspects from each other. draft-ietf-nfsv4-acls-00 has a number of
  weaknesses when it comes to clarity of semantics. I am positive that
  we will manage to clarify all these areas in draft-ietf-nfsv4-acls-00.
  At that point, the *only* essential difference that will remain between
  the two proposals will be that

* draft-ietf-nfsv4-acls-00 uses DENY ACL entries for masking permissions,
  while my proposal uses explicit mask attributes.

> > draft-ietf-nfsv4-acls is missing a clear classification of ACL
> > entries into the File Owner, File Group, and File Other classes. Every
> > ACL entry must be in one of the three classes in order to compute
> > appropriate file mode permission bits when setting an ACL, and after
> > inheriting permissions. This classification also determines which effect
> > chmod will have on an ACL. 
>
> I assume you mean "every ACE", not "every ACL".

	every ACL entry == every ACE

> As I mentioned above, I'm not sure whether or not this is a requirement,
> but it can be discussed further.

How else can a chmod 700 disable all but the owner permissions, a chmod 770 
disable all "others" to have access, and a chmod 000 disable all permissions 
if you don't know which ACEs each class applies to?

> However, if it turns out that draft-ietf-nfsv4-acls is wrong in this regard,
> then the only consequence is a minor change to 5.1.

I hope I can also convince you that the DENY entries to mask permissions are a 
really bad idea.

> I am absolutely not convinced.

I would still recommend that you read [6] at least.

Andreas

---

From: Andreas Gruenbacher <[email-masked]>
Date: Tue, 11 Jul 2006 02:01:42 +0200

> also what Linux (and, I assume, Solaris) do in the case of posix ACLs.

We are not talking about the POSIX 1003.1e draft here, we are talking about 
the real POSIX standard.

> to any other entity, rather than with OWNER@, EVERYONE@, and GROUP@.

I argued why I think this is a misbelief, please scan for well-formed ACLs and 
non-monotonic permissions.

> else if seems simpler.  Neither behavior seems intuitive to me in all

The issue is that you sometimes want to give the owning group fewer perissions 
than say, user:bfields in the above example. You can only do that by 
separating the owning group and mask permissions.

For this aspect of the problem (actually for all aspects except for those that 
the DENY entries cause because they are sometimes difficult or impossible to 
uniquely tell from other "ordinary" entries) it is totally irrelevant whether 
the mask is represented as a mask:: acl entry as in POSIX ACLs, as a series 
of DENY ACL entries, or as NFSv4 attributes.

(POSIX ACLs only need one mask entry because they can never grant more than 
rwx permissions anyway, and so the owner and other permissions are always 
identical to the owner and other file mode permission bits. That's no longer 
true with POSIX ACLs, and so there we also need mask entries for the owner 
and for others.)

Andreas

---

From: Andreas Gruenbacher <[email-masked]>
Date: Tue, 11 Jul 2006 02:15:53 +0200

> later, these ACLs ain't POSIX.)

Indeed, they are only pretty close. One other difference is that Solaris POSIX 
ACLs are always four-entry on some (all?) file systems, while Draft 17 ACLs 
as implemented on Irix, FreeBSD, Linux, and possibly others support 
three-entry ACLs as well (they are equivalent to the file mode permission 
bits.)

It would be bad to repeat the mistake of breaking POSIX assumptions.

> permission to the owning group, and an "ls -l" shows "rwxrwx---",

It screws you when you want to give the owning group fewer permissions than 
other users in the File Group Class. This can be worked around by creating a 
dummy group with no members, or one group that only contains a single user 
for each user, and changing the owning group of files, but the owning group 
already has other defined uses in POSIX (think of SETGID for files and 
directories), and so it's not desirable and not always possible to change the 
owning group to such a dummy group.

Andreas

---

From: "J. Bruce Fields" <[email-masked]>
Date: Mon, 10 Jul 2006 20:28:26 -0400

> true with POSIX ACLs, and so there we also need mask entries for the owner 

So you need this if and only if you want to be able to set OWNER@
permissions other than read, write, or execute, *and* want to be able to
recover from a chmod?

The argument for the reversibility of chmod seems a lot stronger when
the information that could be lost is a long list of users and
permissions than when it's just a few bits for the owner.

--b.

---

From: Andreas Gruenbacher <[email-masked]>
Date: Tue, 11 Jul 2006 02:48:37 +0200

On Tuesday, 11. July 2006 02:28, J. Bruce Fields wrote:
> > The issue is that you sometimes want to give the owning group fewer
> > perissions than say, user:bfields in the above example. You can only do
> > that by separating the owning group and mask permissions.
> >
> > For this aspect of the problem (actually for all aspects except for those
> > that the DENY entries cause because they are sometimes difficult or
> > impossible to uniquely tell from other "ordinary" entries) it is totally
> > irrelevant whether the mask is represented as a mask:: acl entry as in
> > POSIX ACLs, as a series of DENY ACL entries, or as NFSv4 attributes.
> >
> > (POSIX ACLs only need one mask entry because they can never grant more
> > than rwx permissions anyway, and so the owner and other permissions are
> > always identical to the owner and other file mode permission bits. That's
> > no longer true with POSIX ACLs, and so there we also need mask entries
> > for the owner and for others.)
>

I think I have answered this exhaustively in:

Subject: Re: [NFS] [nfsv4] Re: NFSv4 ACL and POSIX interaction / mask,
         draft-ietf-nfsv4-acls-00 not ready
Date: Tue, 11 Jul 2006 02:44:30 +0200
Message-Id: <[email-masked]>

Andreas

---

From: Sam Falkner <[email-masked]>
Date: Tue, 11 Jul 2006 00:42:05 -0500

> owning group to such a dummy group.

No -- if you want owning group to have fewer permissions than other  
users, you're using an ACL.  You use tools that manipulate ACLs.

Solaris' POSIX-draft ACLs have the property that chmod works (i.e.  
you can set group permissions), and you use setfacl if you want to  
change other entries.  It's perfectly easy to have owning group have  
fewer permissions than supplimental users.

The bottom line is that chmod must set the mode, rather than "set the  
mode, unless there's some sort of ACL thingy, in which case the group  
bits aren't the group bits but are instead the mask bits".

- Sam

---

From: Sam Falkner <[email-masked]>
Date: Tue, 11 Jul 2006 01:17:43 -0500

> user@domain. That's the case I meant, and this case is not POSIX  

Wrong.  The file mode permission bits will be rw-rw-r--.  There is no  
problem with POSIX compliance.

> user clearly did not intend this to happen.

No -- after the chmod, the DENY still stands, unaltered.

- Sam

---

From: Lisa Week <[email-masked]>
Date: Tue, 11 Jul 2006 02:50:20 -0400

On Jul 9, 2006, at 10:22 AM, Andreas Gruenbacher wrote:

> provided
> entries into

Yes, permissions may accumulate, but in the design in the minor  
version doc, after a chmod, any permissions that go beyond the mode  
bits being set will be disabled.  This is done via the algorithm in  
section 3.16.6.3 -  "Applying a Mode to an Existing ACL".  This makes  
sure that the permissions (ACE4_READ_DATA/ACE4_LIST_DIRECTORY,
ACE4_WRITE_DATA/ACE4_WRITE_DATA, ACE4_APPEND_DATA/ 
ACE4_ADD_SUBDIRECTORY and ACE4_EXECUTE... which is what the mode  
defines) that accumulate will NOT go beyond the mode bits being set.

> when inheriting permissions.

We clearly have a disagreement what "additional" and "alternate" file  
access control mechanisms mean to NFSv4 ACLs.

Without these fundamental things, we will never be able to reach  
consensus.  So lets try to up-level the discussion and see if we can  
get agreement on what the meanings of these two access control  
mechanisms are in the context of NFSv4...

I know this has been iterated over and over again, but bear with  
me...  hopefully this will give you a better idea of where we're  
coming from.

POSIX defines Additional Access Control Mechanism as follows:
"An implementation-defined mechanism that is layered upon the access  
control mechanisms defined here, but which do not grant permissions  
beyond those defined herein, although they may further restrict them."

POSIX defines Alternate Access Control Mechanisms are as follows:
"An implementation-defined mechanism that is independent of the  
access control mechanisms defined herein, and which if enabled on a  
file may either restrict or extend the permissions of a given user.  
IEEE Std 1003.1-2001 defines when such mechanisms can be enabled and  
when they are disabled."

So, the question that comes to my mind when reading that text is:  
What does it mean when they say "access mechanisms defined herein" in  
both of those definitions?  Well, the access mechanisms defined in  
the POSIX spec are the "File Access Permissions", right?  So, can we  
agree that "access mechanisms defined herein" would be the "File  
Access Permissions"?

Okay, the description of "File Access Permissions" says that "The  
standard file access control mechanism uses the file permission bits..."

So, what are the file permission bits?  They are read, write, execute/ 
search for the File Owner Class, File Group Class and File Other Class.

So, to put this together, Additional access control mechanisms are   
the ability to further restrict the read, write, execute/search  
permissions for the File Owner Class, File Group Class and File Other  
Class.  And, Alternate access control mechanisms are the ability to  
either restrict or extend the read, write, execute/search permissions  
for the File Owner, Group and Other Class.

Now, to classify NFSv4 ACLs into Additional and Alternate access  
control mechanisms...
Since we are only controlling the read, write, execute/search  
permissions, the only permissions we should classify in NFSv4 ACLs  
are the access mask bits that intersect with the file permission bits  
as defined by POSIX.  And for NFSv4 that means the following access  
mask bits are of interest:
ACE4_READ_DATA/ACE4_LIST_DIRECTORY
ACE4_WRITE_DATA/ACE4_WRITE_DATA, ACE4_APPEND_DATA/ACE4_ADD_SUBDIRECTORY
ACE4_EXECUTE.

(Actually, this is where the existing draft-ietf-acl-00 proposal is  
confusing.  It doesn't come right out and say this.  In the write up  
we had the assumptions that this was clear, but I know that it needs  
to be further specified.)

So, now in the NFSv4 ACL sense, Alternate access control mechanisms  
are used to further extend and Additional access control mechanisms  
are used to further restrict the following access mask bits:
ACE4_READ_DATA/ACE4_LIST_DIRECTORY
ACE4_WRITE_DATA/ACE4_WRITE_DATA, ACE4_APPEND_DATA/ACE4_ADD_SUBDIRECTORY
ACE4_EXECUTE.

How would one extend those access mask bits (Alternate)?  By putting  
them in an ALLOW ACE.
How would one restrict those access mask bits (Additional)?  By  
putting them in a DENY ACE.

As far as the other access mask bits...they aren't covered by the  
POSIX File Access Permissions so do they need a classification?  No,  
not really.  (More on this below...)

> If ALLOW ACEs were alternate in general, then we
> grants.

I would agree with that, but don't go putting further restrictions on  
us than POSIX defined in the first place.  As said before POSIX only  
defines what should happen with regard to the access control  
mechanisms that layer on top of or extend the *file permission  
bits*.  See more below.

> You have given an example of an ACL that clearly is an additional

The thing that is still out there is that if you classify ACEs with  
ACE4_READ_DATA, for example, as an additional access control  
mechanism, you will never be able to give a arbitrary user or group  
the ACE4_READ_DATA permission without having the File Class that it  
belongs to also have at least those permissions.  That seems broken  
to me.

> off all ALLOW entries),

I give you this.  The wording about the classification of ACEs in  
draft-ietf-nfsv4-acls is not quite sufficient.  As I've said before,  
It makes some important assumptions, but isn't clear as to what those  
are.  It doesn't map to what the algorithm specifies.  With that  
said, it was not meant to be misleading in any way.

As documented in the algorithm definition in section 3.16.6.3 -  
"Applying a Mode to an Existing ACL" of the minor version doc, the  
following is a clarification of the classification:

ALLOW ACEs with ACE4_READ_DATA/ACE4_LIST_DIRECTORY, ACE4_WRITE_DATA/ 
ACE4_ADD_FILE, ACE4_APPEND_DATA/ACE4_ADD_SUBDIRECTORY, and  
ACE4_EXECUTE access mask bits are Alternate security mechanisms.   
These access mask bits will be disabled upon chmod.

DENY ACEs with those access mask bits are Additional access control  
mechanisms.  These access mask bits will be left unchanged  after a  
chmod, unless, as described in 3.16.6.3 it is one of the special  
identifiers, OWNER@, GROUP@, EVERYONE@.

All other access mask bits listed below are outside of the access  
control mechanisms specified by POSIX and are therefore unclassified  
and unrestricted:
ACE4_READ_NAMED_ATTRS
ACE4_WRITE_NAMED_ATTRS
ACE4_DELETE_CHILD
ACE4_READ_ATTRIBUTES
ACE4_WRITE_ATTRIBUTES
ACE4_DELETE
ACE4_READ_ACL
ACE4_WRITE_ACL
ACE4_WRITE_OWNER
ACE4_SYNCHRONIZE

This means that if an ACE defines one of those access mask bits, the  
access granted or denied will remain unchanged after a chmod.

> while section 14.4 says that "the ALLOW type of ACE

Thoughts?

Thanks,
Lisa

---

From: Andreas Gruenbacher <[email-masked]>
Date: Tue, 11 Jul 2006 02:44:30 +0200

> bitmasks anywhere other than OWNER@ or DENY@.

Another benefit would be that we can tell what are MASK entries and which 
entries are not. That's not always possible with the DENY entries.

> and I think that's overkill.  So that's what I'm arguing against.

The reason for adding owner and other masks was this: we want to be able to 
turn off alternate permissions upon chmod and acl inheritance. We can already 
easily do that for the File Group Class by cleaning the alternate mask bits 
there; it's the same mechanism we also use for turning off additional mask 
bits for chmod, for example. We need to be able to turn off alternate and 
additional mode bits for the owner and for others as well in cases like 
chmod. Now we could devise a different mechanism for turning off alternate 
permissions for the owner and for others (like a bit somewhere), but that 
would still leave us with the problem of how to turn off additional mask 
bits. The NFSv4 ACL mask bits are more fine-grained that the POSIX mask bits, 
and we don't want to destroy the granularity of the NFSv4 ACL mask bits when 
masking permissions. Therefore, we need mask entries for the owner and for 
others as well.

Consider this ACL:

	OWNER@:READ_DATA/WRITE_DATA::ALLOW
	GROUP@:APPEND_DATA::DENY
	GROUP@:READ_DATA::ALLOW
	EVERYONE@:APPEND_DATA::ALLOW

The corresponding mode is 0642 (rw-r---w-). POSIX applications will know 
nothing about the fact that others are only allowed to append data to that 
file. Now consider that a user does a chmod(file, 0) followed by a 
chmod(file, 0642). Which permissions should others have after the chmod? Not 
full write access I assume; POSIX applications should not remove restrictions 
they are not even aware of by accident.

Using the same masking mechanism across all three classes and being able to 
selectively turn alternate mask bits on and off for all classes can only be a 
benefit.

> type instead of a new special entity.

Yes, that was one of the possible designs.

> support it.  But a separate attribute would also have that property.

Advantages of attributes are that clients will never be bothered with ACE 
types they don't know. We can directly access attibutes, rather than scanning 
for the right ACEs, inserting ACEs in case they are missing, etc. There will 
be exactly three masks (or so I hope), and I don't see why we should need to 
add more classes later. We can store all three classes as a single attribute 
though; that may be more acceptable that three separate attributes.

Andreas

---

From: Andreas Gruenbacher <[email-masked]>
Date: Tue, 11 Jul 2006 10:05:21 +0200

On Tuesday, 11. July 2006 07:42, Sam Falkner wrote:
> > It screws you when you want to give the owning group fewer permissions
> > than other users in the File Group Class. This can be worked around by
> > creating a dummy group with no members, or one group that only contains
> > a single user for each user, and changing the owning group of files, but
> > the owning group already has other defined uses in POSIX (think of SETGID
> > for files and directories), and so it's not desirable and not always
> > possible to change the owning group to such a dummy group.
>

Sorry, but while this may look like a good idea at first, it doesn't work very 
well. Let's look at an example:

	OWNER@:READ_DATA/WRITE_DATA::ALLOW
	GROUP@:READ_DATA/WRITE_DATA::ALLOW
	user@domain:READ_DATA/WRITE_DATA::ALLOW
	EVERYONE:READ_DATA::ALLOW

The mode is rw-rw-r--. Now we use ACL tools to change the ACL to give the 
owning group fewer permissions than user@domain as you say:

	OWNER@:READ_DATA/WRITE_DATA::ALLOW
	GROUP@:READ_DATA::ALLOW
	user@domain:READ_DATA/WRITE_DATA::ALLOW
	EVERYONE:READ_DATA::ALLOW

The mode must still be rw-rw-r-- because otherwise, user@domain wouldn't have 
WRITE_DATA access. Now a nasty, evil POSIX application that doesn't know 
anything about ACLs comes along and does a chmod(file, 0600), chmod(file, 
0664). What should be the appropriate result? If changing the group file mode 
permission bits writes through to the GROUP@ entry as you say, then we would 
end up with the following *effective* permissions:

	OWNER@:READ_DATA/WRITE_DATA::ALLOW
	GROUP@:READ_DATA/WRITE_DATA::ALLOW
	user@domain:READ_DATA/WRITE_DATA::ALLOW
	EVERYONE:READ_DATA::ALLOW

(The effective permissions are the same no matter how permissions are masked 
in the ACL, be it via DENY ACEs or via masks. In the case of DENY ACEs, the 
ACL would contain DENY entries, but those wouldn't mask any permissions in 
this case. The example is slightly more difficult to think through with DENY 
ACEs because they contain some redudancy and potential for inconsistencies, 
but the result is the same.)

From the POSIX application's point of view, the file has the same permissions 
before and after the chmod. The POSIX application cannot be held guilty; 
after all it doesn't know about ACLs by definition. Yet the acl actually 
grants more permissions after the chmods, and the change we did to give the 
owning group fewer permissions with ACL tools is lost. This can be quite 
serious.

We can play the same example with MAY_WRITE vs. MAY_APPEND: if the group file 
mode permission bits write through to the owning group permissions, a POSIX 
chmod may convert a MAY_APPEND owning group ACE into a MAY_WRITE owning group 
ACE.

> fewer permissions than supplimental users.

That's a bug, and draft 17 of POSIX 1003.1e (withdrawn) has this bug fixed.

> bits aren't the group bits but are instead the mask bits".

We may be misunderstanding here: I agree that chmod must set the file mode 
(permission bits as well as special bits). The point is that the group file 
mode permission bits can no longer be the same as the owning group 
permissions with ACLs, or else innocent POSIX applications may cause 
unintended side effects as in the example.

Andreas

---

From: Andreas Gruenbacher <[email-masked]>
Date: Tue, 11 Jul 2006 10:45:43 +0200

On Tuesday, 11. July 2006 08:17, Sam Falkner wrote:
> >>> Here are some facts to back my points: Let's assume that a file inherits
> >>> the following ACL when being created (I am using ^(...) here with the
> >>> meaning of "all bitflags except ..."):
> >>>
> >>> This acl is "well structured" in the POSIX sense: OWNER@ will only get
> >>> the owner permissions and none of the other permissions, user@domain
> >>> and GROUP@ will only get the permissions intended for them, and only
> >>> others (neither OWNER@ nor user@domain nor GROUP@) will get EVERYONE@
> >>> permissions; in other words, the acl is even correct for non-monotonic
> >>> permissions. 
> >>>
> >>> According to section 5.1 of draft-ietf-nfsv4-acls [1], the resulting
> >>> file mode permission bits for this acl shall be rw-r--r--.
> >>
> >>> After a chmod or a file create, alternate file access control mechanisms
> >>> must be disabled and only additional file access control mechanisms may
> >>> remain active. According to POSIX, additional file access control
> >>> mechanisms require that no user may be granted more permissions than the
> >>> respective file classes permit. In this case, user@domain clearly is not
> >>> in the File Owner Class. (According to POSIX, user@domain must be in the
> >>> File Group Class.) The user@domain user is granted WRITE_DATA though,
> >>> which is *incorrect* from a POSIX point of view.
> >>
> > Now that I look at the example again, I realize that I didn't
> > define the create mode. With create mode 640 or less permissive,
> > everything is fine. Let's assume create mode 664 though: then the file
> > mode permission bits will still come out as rw-r--r--, but the ACL will
> > grant WRITE_DATA to user@domain. That's the case I meant, and this case is
> > not POSIX compliant.
>

Ah. And why should that be according to draft-ietf-nfsv4-acls-00? Because the 
group file mode permission bits write through to GROUP@ entries, and so the 
rw- group permissions in the create mask elevate the permissions given to the 
owning group in the ACL?

I hope that my reply from Tue, 11 Jul 2006 10:05:21 +0200 made it clear that 
writing through to the GROUP@ entries causes POSIX applications to 
accidentally remove restrictions from an ACL, and so we really must not do 
that. The same argument applies to writing through to OWNER@ and EVERYONE@ 
entries, by the way. The "The final six ACEs are adjusted according to the 
incoming mode" section of the algorithm described in 5.3 is a really bad 
idea.

> > corresponds to the group file mode permission bits in traditional
> > POSIX. The problem is more difficult to see in this case, but I argue
> > that the owhning group permissions and the group file mode permission
> > bits are not the same with ACLs: the file group mode permission bits
> > restrict GROUP@ entries, and all user@domain and group@domain entries
> > in the acl. For the sake of this example, substitute GROUP@ with
> > user@domain though, and you'll see the problem more clearly: a user
> > adds an explicit user@domain:WRITE_DATA::DENY entry to an acl which
> > is followed by a user@domain:READ_DATA::ALLOW entry. After a chmod to
> > 664 for example, this user suddenly has write access. The

Great Sam, you have trapped me with another special case that is there only 
because of those pesky mask DENY entries: "the mask bits are a subset of the 
mask bits of the current ACE" [1].

My point still holds, just that the following ALLOW ACE must have the denied 
WRITE_DATA permission set as well:

	user@domain:WRITE_DATA::DENY
	user@domain:READ_DATA/WRITE_DATA::ALLOW

Do you *still* disagree?

Andreas

---

From: Andreas Gruenbacher <[email-masked]>
Date: Tue, 11 Jul 2006 10:55:55 +0200

On Tuesday, 11. July 2006 08:50, Lisa Week wrote:
> > Note that in traditional POSIX, permissions from multiple file
> > classes will never accumulate: each user always is either granted the
> > File Owner permission bits, the File Group permission bits, or the File
> > Other permission bits. (Additional file access control mechanisms may
> > further limit the permissions granted, and alternative file access
> > control mechanisms may further limit or extend the permissions granted.)
> > Permissions from multiple acl entries accumulate in the NFSv4 ACL model
> > though, and so unless an acl is "well structured" in the above sense,
> > permissions from multiple classes may accumulate.
>

Ack.

Andreas

---

From: Sam Falkner <[email-masked]>
Date: Tue, 11 Jul 2006 08:29:21 -0400

> 	EVERYONE:READ_DATA::ALLOW

That's not how Solaris works either.  Sorry, I should have explained  
it better.  In Solaris using POSIX-draft ACLs, chmod() changes both  
the group permissions and the mask, simultaneously.  I now understand  
why you were hesitant to have chmod affect the group permissions, but  
having it affect both mask and group solves both problems.

I realize that I'm talking about POSIX-draft ACLs, but the same  
design principles work for NFSv4 ACLs.  chmod() affects the GROUP@  
permissions directly, and also affects the mask, no matter how the  
mask is implemented.

- Sam

---

From: Sam Falkner <[email-masked]>
Date: Tue, 11 Jul 2006 08:44:42 -0400

> mask bits of the current ACE" [1].

I trapped you, but not out of malice.  The fact that you fell into  
the trap proves a point.  You tried to give an example as a  
reasonable pair of ACEs that a user would set, and fell into the trap  
of having the design deal with your ACEs correctly.  The design is to  
only manipulate DENY entries if the follow a very specific pattern, a  
pattern that an end-user is unlikely to set.  In other words, the  
design avoids manipulating DENYs unless the DENYs are redundant.

> 	user@domain:READ_DATA/WRITE_DATA::ALLOW

Yes, there, the chmod would change the DENY ACE.  So if an end-user  
really did say WRITE_DATA:DENY, WRITE_DATA:ALLOW, albeit with other  
bits, then yes, the ACL can change as a result of the chmod.

> Do you *still* disagree?

I don't disagree that the DENY would be changed by a chmod(), but I  
do disagree that it's a major flaw.

I would rather live with the flaw of having redundant user-supplied  
ACEs manipulated upon chmod than to add new file attributes that  
NFSv4.0 clients and servers won't know about.

- Sam

---

From: "J. Bruce Fields" <[email-masked]>
Date: Tue, 11 Jul 2006 09:46:35 -0400

> having it affect both mask and group solves both problems.

I think you're missing the point of his example.  The point is that a
chmod-using application may expect the sequence chmod(600) chmod(664) on
a file with mode 664 to be a no-op.

But if chmod() changes both group and mask bits ("owning group" and
"group file class" bits) then this sequence isn't a no-op any more in
his example.  It gives GROUP@ write permissions.

So Andreas is trying to ensure the property that any sequence of chmod's
that leaves the mode bits the same also leaves the ACL the same.  I
agree that that's a nice property.

What I'm not convinced of yet is that this is really worth caring about
much.  Is this common application behavior?  Have there been complaints
about this from people using Solaris's ACLs?

--b.

---

From: "J. Bruce Fields" <[email-masked]>
Date: Fri, 14 Jul 2006 13:59:30 -0400

> > chmod and after creating files or directories.

So, omitting the details, the idea is to add 3 optional attributes
(owner_class_mask, group_class_mask, and other_class_mask) which limit
the permissions that an ACL can grant to different classes of entities.

For a client that doesn't support the new attributes, a server can apply
the mask attributes to the ACL before returning it.  I suppose a
multi-protocol server would do the same for CIFS clients.

For a server that doesn't support the new attributes, the client still
has available any of the current options: give up on non-destructive
chmod, or fall back on representing mask bits with DENIES.

When client and server support the new mask bits, we get a completely
non-destructive chmod without all the complicated DENY heuristics.

I agree that that would be an improvement.

--b.

---

From: "J. Bruce Fields" <[email-masked]>
Date: Fri, 14 Jul 2006 14:22:45 -0400

> multi-protocol server would do the same for CIFS clients.

By the way, the proposed protocol behavior here is odd:  the server
returns a different ACL depending on whether the client requested any of
the new mask attributes in the same GETATTR.

But I suppose there are other cases (rdattr_error, maybe some migration
cases??) where what we return can depend in strange ways on which
attributes were requested, so maybe it's not totally without precedent?

--b.

---

From: "J. Bruce Fields" <[email-masked]>
Date: Fri, 14 Jul 2006 14:44:07 -0400

On Fri, Jul 14, 2006 at 02:38:41PM -0400, [email-masked] wrote:
> >> -----Original Message-----
> >> From: J. Bruce Fields [mailto:[email-masked]] 
> >> Sent: Friday, July 14, 2006 14:00
> >> To: [email-masked]
> >> Cc: Sam Falkner; [email-masked]; Spencer Shepler; 
> >> Brian Pawlowski
> >> Subject: [nfsv4] Re: [NFS] NFSv4 ACL and POSIX interaction / 
> >> mask,draft-ietf-nfsv4-acls-00 not ready
> >> 
> >> 
> Since CIFS does not understand the semantics of permission mask, does
> the server enforce the mask when the access for the data comes from
> a CIFS client ?

Yes, it does.  But it also only ever shows CIFS clients a version of the
ACL with the mask already applied, so CIFS clients see no inconcistency.
(In other words, if there's an "ALLOW bfields READ+WRITE" ACE, but the
relevant mask only allows READ, then the CIFS client will see a version
of the ACL where that ACE only allows READ.)

See any reason why that won't work?

--b.

---

From: [email-masked]
Date: Fri, 14 Jul 2006 14:38:41 -0400

---

From: Andreas Gruenbacher <[email-masked]>
Date: Fri, 14 Jul 2006 20:50:19 +0200

On Friday, 14. July 2006 20:44, J. Bruce Fields wrote:
> Yes, it does.

Definitely, yes. Not enforcing the mask that would be a security hole.

Andreas

---

From: Andreas Gruenbacher <[email-masked]>
Date: Fri, 14 Jul 2006 21:02:44 +0200

> chmod, or fall back on representing mask bits with DENIES.

Maybe not what you meant, but shouldn't the client rely on the server to do 
"the right thing" when it sees a mode SETATTR? I think it would be a bad idea 
for the client to guess such details as which exact file security model a 
server implements. Instead, the server should be responsible for doing what 
the client is asking for (and erring towards more restrictive permissions if 
necessary).

Andreas

---

From: "J. Bruce Fields" <[email-masked]>
Date: Fri, 14 Jul 2006 15:13:57 -0400

On Fri, Jul 14, 2006 at 09:02:44PM +0200, Andreas Gruenbacher wrote:
> "the right thing" when it sees a mode SETATTR?

RFC 3530 allows a server to leave named users and groups with
permissions greater than the permissions in the group mode bit, so if a
client wants posix-like behavior it can't count on the server for that.

That said...

> I think it would be a bad idea for the client to guess such details as
> which exact file security model a server implements. Instead, the
> server should be responsible for doing what the client is asking for
> (and erring towards more restrictive permissions if necessary).

... I'm all for declaring 3530 wrong here and insisting that the mode bits
act like a mask, or just not worrying about it and telling users to
check their server's manual very carefully if they depend on the posix
behavior.

--b.

---

From: Sam Falkner <[email-masked]>
Date: Sat, 15 Jul 2006 07:56:23 -0600

> his example.  It gives GROUP@ write permissions.

Okay, understood.

> agree that that's a nice property.

Perhaps, but I think having chmod unable to set the mode to be a much  
more undesirable property, to put it mildly.

> about this from people using Solaris's ACLs?

I did some more research, and found that the Solaris chmod() system  
call does pretty much what Linux does -- the group permissions of  
chmod() affect the mask, not the group permission bits.  Originally,  
the chmod command did the chmod() system call, and not much else.

There were many complaints about this.  So many that the chmod  
command line was changed to do the chmod() system call, and then, in  
the presence of an ACL, fix the permission bits.  In other words, the  
bug was fixed.

I have found no complaints about the current Solaris behavior, where  
chmod affects group permissions.

- Sam

---

From: Andreas Gruenbacher <[email-masked]>
Date: Thu, 27 Jul 2006 02:59:04 +0200

Lisa,

> agree that "access mechanisms defined herein" would be the "File

the "access mechanisms defined herein" refer to all file access control 
mechanisms that POSIX defines. This includes permissions always granted to 
the owner such as chmod, but also mechanisms such as the restricted deletion 
flag bit (S_ISVTX) for directories, etc.

Trust me, POSIX is very careful about wording, and if "access mechanisms 
defined herein" did indeed refer to the file access permissions, then POSIX 
would say exactly that.

> said, it was not meant to be misleading in any way.

I never meant to imply bad intentions ;-)

> identifiers, OWNER@, GROUP@, EVERYONE@.

No, that's still messed up. We don't care about permissions that are not 
granted, so we *could* only look at ALLOW ACEs, but this distinction is not 
at all relevant.

What counts is which access mask flags are equivalent to the POSIX Read, 
Write, and Execute permissions, and which are not: those are the access mask 
flags which may (sometimes) be used as additional access control mechanisms.

The other issue is which POSIX file class each ACE maps to. Let's assume for 
now that we only know that OWNER@ maps to the File Owner Class to keep this 
example short.

Together with these two classifications, we can determine whether an ACE is 
within the bounds of an additional file access control mechanism. Let's look 
at the following ACE, and a file which has a file mode of 0740 (rwxr-----):

  OWNER@:READ_DATA/APPEND_DATA/EXECUTE::ALLOW

The OWNER@ ACE maps to the File Owner Class. This means that as an additional 
access control mechanism, the ACE may not grant more than Read, Write, and 
Execute. The READ_DATA access mask flag is equivalent to POSIX Read, the 
APPEND_DATA access mask flag is a subset of POSIX Write, and the EXECUTE 
access mask flag is equivalent to POSIX Execute, so we are fine.

Now, let's assume that the user does a chmod to mode 0640 (rw-r-----). The 
permissions of the File Owner Class now no longer cover the EXECUTE 
permission. There are two options to fix this problem:

 1. either accept that the ACE cannot be part of an additional file
    access control mechanism, or

 2. disable the EXECUTE access mask flag, either temporarily or
    permanently, which gets us back into the bounds of additional file
    access control mechanisms.

In case 1, the only choice that remains is that the ACE must be part of an 
alternate file access control mechanism (see more on that below). POSIX 
states that we must disable alternate file access control mechanisms upon 
chmod and for new files, and they must only be re-enabled per explicit user 
action. So the EXECUTE permission would be just gone until the user 
explicitly re-enables it (with something other than a chmod). This would 
render ACLs practically useless under POSIX.

In case 2, the ACE still remains within the bounds of additional file access 
control mechanisms. If we disable EXECUTE only temporarily, then a future 
chmod back to mode 0740 can simply re-enable EXECUTE, and we will not have 
lost anything. (Remember, chmod does not disable additional file access 
control mechanisms.) 

There are several possibilities how we can disable access mode flags 
temporarily:

 1. we could add an explicit DENY ACE before the ALLOW ACE that has
    the affected access mask flags disabled (this is the
    draft-ietf-nfsv4-acls-00 approach),

 2. we could declare that all access mask flags which go beyond
    the corresponding File Class are automatically disabled, or

 3. we could introduce file masks as I am proposing.

The file masks have the advantage that the user can easily manually enable 
more access mask flags in them. This would construe an explicit user action 
as per POSIX. So depending on which flags the user enables, that may amount 
to an additional or alternate file access control mechanism. POSIX is 
perfectly fine with that, even for enabling flags such as WRITE_OWNER. The 
only thing we must ensure is that alternate flags are disabled upon chmod as 
well as for new files.

> access granted or denied will remain unchanged after a chmod.

I am afraid this is impossible: there is no such thing as being outside the 
file access control mechanisms defined by POSIX. The reason is simple: POSIX 
applications absolutely *must* be able to rely on POSIX semantics in order to 
be able to keep the system secure.

Let's assume that ACE4_WRITE_OWNER was indeed outside of the access control 
mechanisms defined by POSIX as a counter example. A POSIX application does a 
chmod to mode 0600 (rw-------) in order to restrict access to the file owner. 
After that, the application can perfectly well write information that is 
confidential to the owner into the file -- after all, only the owner will 
have access, right?

Well, not quite, because an ACL might still grant ACE4_WRITE_OWNER to some 
other user on the system. That other user could simply take over ownership of 
the file, and do whatever he wants with it. Here we have it, a perfect 
security hole; all POSIX applications potentially broken!

Therefore, there cannot be any file access control mechanisms which are 
neither defined by POSIX, nor additional or alternate.

By definition, pure POSIX applications have no idea which additional or 
alternate file access control mechanisms a particular POSIX implementation 
may define, so they cannot know about such sideband mechanisms, and they also 
have no way of disabling them.

Andreas

---

From: Andreas Gruenbacher <[email-masked]>
Date: Thu, 27 Jul 2006 04:57:39 +0200

Lisa,

On Thursday, 27. July 2006 02:59, Andreas Gruenbacher wrote:
> mechanisms defined by POSIX as a counter example. A POSIX application does
> a chmod to mode 0600 (rw-------) in order to restrict access to the file
> owner. After that, the application can perfectly well write information
> that is confidential to the owner into the file -- after all, only the
> owner will have access, right?
>
> other user on the system. That other user could simply take over ownership
> of the file, and do whatever he wants with it. Here we have it, a perfect

I forgot to mention that an analogous case can be made for additional file 
access control mechanisms as well: POSIX applications cannot know which 
additional file access control mechanisms a particular implementation may 
support; they are free to rely on invariants under POSIX, such as a chmod 
from one mode to another, which should be a no-op. Additional file access 
control mechanisms must make sure that POSIX invariants will not change the 
permissions granted.

This contradicts with having a chmod write through to OWNER@, GROUP@, and 
EVERYONE@ ACEs: consider the same ACE we had before with a file mode of 0740 
(rwxr-----):

If a chmod to 0640 and back to 0740 writes through to the OWNER@ ACE, the 
entry will change to:

  OWNER@:READ_DATA/WRITE_DATA/APPEND_DATA/EXECUTE::ALLOW

So a POSIX application has added mask flags in a supposed invariant. That's 
also a security hole, but not one as severe as the first because the only 
mask flag affected is APPEND_DATA (I believe).

I have pointed this out before in Section 4.7. "Mode Changes and the OWNER@, 
GROUP@, and EVERYONE@ ACEs".

Andreas

---

From: Lisa Week <[email-masked]>
Date: Fri, 28 Jul 2006 00:32:59 -0600

Hi Andreas,

Some initial comments inline...

Thanks,
Lisa

>granted, so we *could* only look at ALLOW ACEs, but this distinction is not 
What?  I don't understand how you can say that "we don't care about 
permissions that are not granted".  We definitely care about permissions 
that are explicitly not granted. 

Also, I believe it is relevant to make a distinction between ALLOW and 
DENY ACEs.  Here's why:

The reasoning behind classifying those DENY ACEs as additional access 
control mechanisms are 1.) because they further restrict the permissions 
of users and groups (which is what additional does by definition) and 
2.) we don't want them to have to be disabled upon chmod.  Try to think 
about it in a way that you have just set an explicit entry to deny 
certain permissions to a supplemental user or group.  It is important 
that those users or groups don't have their permissions elevated after 
chmod.

For example, if you have an ACL such as this:

fred:READ_DATA/WRITE_DATA/APPEND_DATA/EXECUTE::DENY
OWNER@:READ_DATA/WRITE_DATA/APPEND_DATA/EXECUTE::ALLOW
GROUP@:READ_DATA/WRITE_DATA/APPEND_DATA/EXECUTE::ALLOW
EVERYONE@:READ_DATA/WRITE_DATA/APPEND_DATA/EXECUTE::ALLOW

The mode would be 777.  User fred is denied the ability to read, write 
and execute because of the explicit deny ACE.  After chmod, fred should 
still not be able to read, write and execute.  That is the goal that we 
were trying to meet.

I realize that the mapping that you describe in section 4.4 of 
http://www.suse.de/~agruen/nfs4acl/mapping-nfsv4-acls-to-posix-00.html 
would also give us the capabilities that  I have described above.

With that said, I will go on to describe the capabilities that I feel 
the mapping in section 4.4 lacks.  The capabilities that it lacks is 
where the relevance of having those ALLOW ACEs that I described before 
be considered Alternate access control mechanisms comes in.

The mapping in section 4.4 makes it impossible to do the following by 
*only* modifying the ACL.

The mode of the file is 644 and you want to give fred the ability to 
read, write and execute.

fred:READ_DATA/WRITE_DATA/APPEND_DATA/EXECUTE::ALLOW
OWNER@:READ_DATA/WRITE_DATA/APPEND_DATA::ALLOW
OWNER@:EXECUTE::DENY
GROUP@:READ_DATA::ALLOW
GROUP@:WRITE_DATA/APPEND_DATA/EXECUTE::DENY
EVERYONE@:READ_DATA::ALLOW
EVERYONE@:WRITE_DATA/APPEND_DATA/EXECUTE::DENY

With the classification in 4.4, you can set that ACL, but it won't take 
effect until you also explicitly modify the file group class permissions 
(via a mask or whatever).

The capability to set the type of ACL that is above was the goal when 
classifying ALLOW ACEs as Alternate security access control mechanisms.  
We can do this because as Alternate is defined, it can extend the 
permissions of a user.  Therefore, setting the ACL attribute is all that 
is needed for this to take effect.

---

I am trying to figure out why there has been such a disagreement here 
and perhaps this is another thing that needs to be cleared up.  What 
does the disabling of an alternate access control mechanism mean?  
Certainly it is not that we have to get rid of everything that is in an 
ALLOW ACE every time a chmod is done.

If you had the following ACL:

fred:READ_DATA/WRITE_DATA/APPEND_DATA/EXECUTE::ALLOW
OWNER@:READ_DATA/WRITE_DATA/APPEND_DATA/EXECUTE::ALLOW
GROUP@:READ_DATA/WRITE_DATA/APPEND_DATA/EXECUTE::ALLOW
EVERYONE@:READ_DATA/WRITE_DATA/APPEND_DATA/EXECUTE::ALLOW

The mode would be 777.  Disabling can be meant that after the chmod, the 
user "fred" should not have more permissions that his respective class.  
So, after a chmod to 770, fred should still be allowed the ability to 
read, write and execute.  This is in how the permissions for fred are 
disabled.  They are being masked down to what the permissions of the 
file group class are.

>flags which may (sometimes) be used as additional access control mechanisms.

What do you mean by sometimes.

>render ACLs practically useless under POSIX.

Why wouldn't the EXECUTE permission be able to be re-enabled with 
chmod?  Of course, it can.  If you are setting a mode of 740, that says 
that the owner can execute.  That is an explicit action and EXECUTE 
permission should be granted to the owner.

>security hole; all POSIX applications potentially broken!
The owner of the file had taken *explicit* action to grant 
ACE4_WRITE_OWNER to another user on the system.  You say that it is a 
security hole if the user that was explicitly granted the ability to 
write owner is now able to do what they were told they could do?

>may define,

> so they cannot know about such sideband mechanisms, and they also