Subject: RE: [nfsv4] re: ACL and Posix Mode bit interaction

From: "Yoder, Alan" <[email-masked]>
Date: Sat, 29 Jul 2006 14:36:51 -0700

> > First off, if this is explained/resolved in the current draft, 
> > just tell me to "piss off and read it":-) I've looked at the 
> > NFSv4<->POSIX ACL draft, but not the 4.1 draft. 
> 
> Actually I don't think it is.  Maybe I missed it but there doesn't 
> seem to be a section on synthesizing an ACL from a mode when 
> ACL hasn't
> been set.
> 
> > Everyone seems to be saying this, but it doesn't seem so easy to me.
> > For example, a file "test" owned by rick has hard links in 
> two directories:
> > drwxr-xr-x  2 andrew  wheel  512 Jul 29 13:41 bar
> > drwx------  2 rick    wheel  512 Jul 29 13:41 foo
> > 
> > Now, I can see that rick can delete foo/test and andrew can 
> delete bar/test.
> 
> > How does this get expressed in the ACL synthesized from the 
> Mode bits for 
> > "test"? (ie. What about ACEs for DELETE?)

   The directories and hard links each have separate ACLs.
In a directory, "w" == CREATE_CHILD + DELETE_CHILD + ....
There's no correspondent in the mode bits for DELETE on a
file that I can think of.  

   Possibly we need a table specifying this mapping.

Alan

===============================================================
Alan G. Yoder                                    [email-masked]
Technical Staff                           
Network Appliance, Inc.                            408-822-6919
===============================================================

> 
> The only conclusion I can draw is that the synthsized ACL 
> does not specify
> ACE's with delete.  If you did, then you would be able to 
> delete the file
> independent of the path used and you don't want to do that.
> 
> I think according to the algorithm in section 5.2.1, this 
> means that the
> deletion decision will be made according to permissions in 
> the directory
> as you want.
> 
> -----Original Message-----
> From: [email-masked] 
> [mailto:[email-masked]] 
> Sent: Saturday, July 29, 2006 2:46 PM
> To: [email-masked]
> Cc: [email-masked]; Yoder, Alan; [email-masked]; 
> [email-masked]
> Subject: [nfsv4] re: ACL and Posix Mode bit interaction
> 
> First off, if this is explained/resolved in the current 
> draft, just tell me to "piss off and read it":-) I've looked 
> at the NFSv4<->POSIX ACL draft, but not the 4.1 draft.
> But, in case it isn't covered in the draft...
> 
> >  * It's easy to synthesize an ACL given a mode, if you
> >    need to.  Next.
> 
> Everyone seems to be saying this, but it doesn't seem so easy to me.
> For example, a file "test" owned by rick has hard links in 
> two directories:
> drwxr-xr-x  2 andrew  wheel  512 Jul 29 13:41 bar
> drwx------  2 rick    wheel  512 Jul 29 13:41 foo
> 
> Now, I can see that rick can delete foo/test and andrew can 
> delete bar/test.
> How does this get expressed in the ACL synthesized from the 
> Mode bits for "test"? (ie. What about ACEs for DELETE?)
> 
> I suppose an ACL could have been synthesized when the file 
> was first created, with DELETE ACE(s) built from the 
> directory's Mode bits. But then, how does the server 
> "massage" this ACL when the second hard link is created?
> 
> Under RFC3530, if you didn't generate any ACEs with DELETE in 
> them, it would be "undefined", which could be construed to 
> mean "check the link's directory ACL". But, under 4.1 it 
> sounds like the answer is Deny instead of undefined, unless 
> ACEs for DELETE are in the ACL?
> 
> If the ACL synthesized from Mode bits doesn't handle this 
> case and is only approximate, the semantics of "deletion" 
> changes when the ACL is synthesized.
> 
> > In all cases, if a file has an ACL, that's what's used to actually 
> > check the permissions.  The mode is just for stat and display 
> > purposes.  If it doesn't have an ACL, then there's nothing to 
> > synchronize.
> 
> And what do you return when a v4 client does a Getattr/ACL 
> for files that don't have ACLs? Synthesize it at that point 
> and create subtly different permission semantics for the file 
> as a result?
> 
> Still Confused by ACLs, rick
> 
> _______________________________________________
> nfsv4 mailing list
> [email-masked]
> https://www1.ietf.org/mailman/listinfo/nfsv4
> 

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

---

From: "J. Bruce Fields" <[email-masked]>
Date: Mon, 31 Jul 2006 11:56:57 -0400

>    The directories and hard links each have separate ACLs.

I don't understand.  You're not suggesting returning different ACLs
depending on which way the file was looked up, are you?  I don't think
that's a good idea.

>    Possibly we need a table specifying this mapping.

See  the "ACE4_DELETE vs. ACE4_DELETE_CHILD" section of the 4.1 draft
for a discussion of the semantics of those bits.

If you're following the recommendations of that section, then you
probably want DELETE always to be cleared on mode-bit-derived ACLs.

I believe the mapping linux and solaris are currently using produces an
ACL like:

	OWNER@:ALLOW:owner bits
	OWNER@:DENY:~owner bits
	GROUP@:ALLOW:group bits
	GROUP@:DENY:~group bits
	EVERYONE@:ALLOW:other bits
	EVERYONE@:DENY:~other bits

where those bitmasks are determined by mapping the

	read mode bit to READ_DATA
	write mode bit to WRITE_DATA|APPEND_DATA (on files)
			  WRITE_DATA|APPEND_DATA|DELETE_CHILD (on directories)
	execute bit to EXECUTE

and also turning on READ_ACL, READ_ATTRIBUTES, and SYNCHRONIZE
unconditionally, and adding WRITE_ACL and WRITE_ATTRIBUTES to the owner
bits.

Note that in the case where the owner, group, and other bits are ordered
from least-to-most restrictive, the DENY's are unnecessary.  Some day
soon I intend to modify the Linux implementation to stop inserting those
unnecessary DENY's.

The documentation for Microsoft's "Services for UNIX" also gives an
example of Windows ACL->mode bit mapping which is pretty similar to the
above (with DENY's inserted only as necessary).

http://www.microsoft.com/technet/interopmigration/unix/sfu/sfu3perm.mspx#EFAA

--b.

---

From: Lisa Week <[email-masked]>
Date: Mon, 31 Jul 2006 15:32:14 -0600

>>   Possibly we need a table specifying this mapping.
Right, ACE4_DELETE would not be specified in a mapping for the ACL that 
gets synthesized from the mode.

>I believe the mapping linux and solaris are currently using produces an

Yes, this is what Solaris produces if the underlying file system on the 
server is UFS (which implemented POSIX-draft ACLs natively).  It is a 
little different for ZFS which implemented NFSv4 ACLs natively, but the 
same concepts are upheld.

Just to be clear, the following are true for Solaris/UFS *and* Solaris/ZFS:
1.) The mappings of read, write and execute mode bits are the same as 
you describe below
2.) ALLOW/DENY pairs must exist
3.) Everyone gets ALLOWed ACE4_READ_ATTRIBUTES, ACE4_READ_ACL, 
ACE4_SYNCHRONIZE
4.) Owner gets ALLOWed ACE4_WRITE_ATTRIBUTES, ACE4_WRITE_ACL

The following is only true for Solaris ZFS:
5.) Owner gets ALLOWed ACE4_WRITE_OWNER (*), ACE4_WRITE_NAMED_ATTRIBUTES
    (*) ACE4_WRITE_OWNER on Solaris means the ability to take ownership 
of the file.  Change the owner to yourself and the owning group to a 
group that you are a member of.
6.) Everyone gets ALLOWed ACE4_READ_NAMED_ATTRIBUTES
7.) Everyone gets DENYed ACE4_WRITE_NAMED_ATTRIBUTES

See below for snoop output...

----

In thinking about what mapping should/could be documented in 4.1...
To me, what seems to be the most important is that we can agree on the 
mappings from the read, write and execute mode bits to the access mask 
bits and that we can agree on the basic semantics that need to be upheld 
by the mode (this should be pretty easy).  For instance, mode 0644 means 
owner can read and write, owning group can read, everyone other than the 
owner and owning group can read.  Then however an implementation wants 
to uphold those semantics, whether it is with ALLOW/DENY ACE pairs, all 
ALLOW ACEs, etc. that should be left up to the implementation.

Also, it doesn't seem like the default values and behaviors that 
implementations may have regarding ACE4_READ_ATTRIBUTES, ACE4_READ_ACL, 
ACE4_SYNCHRONIZE, ACE4_WRITE_ATTRIBUTES, ACE4_WRITE_ACL, 
ACE4_READ_NAMED_ATTRIBUTES, ACE4_WRITE_NAMED_ATTRIBUTES should be 
limited.  For example, if an implementation wanted to DENY everyone 
ACE4_READ_ATTRIBUTES by default, that should be possible.

>unconditionally, and adding WRITE_ACL and WRITE_ATTRIBUTES to the owner
snoop output from Solaris/ZFS:

NFS:  ACL of 6 entries
NFS:  nfsace4[0]
NFS:    type = 1
NFS:       ACE4_ACCESS_DENIED_ACE_TYPE
NFS:    flags = 0
NFS:    mask = 20
NFS:         ACE4_EXECUTE
NFS:    who = OWNER@
NFS:  nfsace4[1]
NFS:    type = 0
NFS:       ACE4_ACCESS_ALLOWED_ACE_TYPE
NFS:    flags = 0
NFS:    mask = c0117
NFS:         ACE4_READ_DATA/ACE4_LIST_DIRECTORY  
ACE4_WRITE_DATA/ACE4_ADD_FILE
NFS:         ACE4_APPEND_DATA/ACE4_ADD_SUBDIRECTORY  ACE4_WRITE_NAMED_ATTRS
NFS:         ACE4_WRITE_ATTRIBUTES  ACE4_WRITE_ACL  ACE4_WRITE_OWNER
NFS:    who = OWNER@
NFS:  nfsace4[2]
NFS:    type = 1
NFS:       ACE4_ACCESS_DENIED_ACE_TYPE
NFS:    flags = 40
NFS:         ACE4_IDENTIFIER_GROUP
NFS:    mask = 26
NFS:         ACE4_WRITE_DATA/ACE4_ADD_FILE
NFS:         ACE4_APPEND_DATA/ACE4_ADD_SUBDIRECTORY  ACE4_EXECUTE
NFS:    who = GROUP@
NFS:  nfsace4[3]
NFS:    type = 0
NFS:       ACE4_ACCESS_ALLOWED_ACE_TYPE
NFS:    flags = 40
NFS:         ACE4_IDENTIFIER_GROUP
NFS:    mask = 1
NFS:         ACE4_READ_DATA/ACE4_LIST_DIRECTORY
NFS:    who = GROUP@
NFS:  nfsace4[4]
NFS:    type = 1
NFS:       ACE4_ACCESS_DENIED_ACE_TYPE
NFS:    flags = 0
NFS:    mask = c0136
NFS:         ACE4_WRITE_DATA/ACE4_ADD_FILE
NFS:         ACE4_APPEND_DATA/ACE4_ADD_SUBDIRECTORY  ACE4_WRITE_NAMED_ATTRS
NFS:         ACE4_EXECUTE  ACE4_WRITE_ATTRIBUTES  ACE4_WRITE_ACL
NFS:         ACE4_WRITE_OWNER
NFS:    who = EVERYONE@
NFS:  nfsace4[5]
NFS:    type = 0
NFS:       ACE4_ACCESS_ALLOWED_ACE_TYPE
NFS:    flags = 0
NFS:    mask = 120089
NFS:         ACE4_READ_DATA/ACE4_LIST_DIRECTORY  ACE4_READ_NAMED_ATTRS
NFS:         ACE4_READ_ATTRIBUTES  ACE4_READ_ACL  ACE4_SYNCHRONIZE
NFS:    who = EVERYONE@
NFS:  Mode = 0644

snoop output from Solaris/UFS:

NFS:  ACL of 7 entries
NFS:  nfsace4[0]
NFS:    type = 0
NFS:       ACE4_ACCESS_ALLOWED_ACE_TYPE
NFS:    flags = 0
NFS:    mask = 160187
NFS:         ACE4_READ_DATA/ACE4_LIST_DIRECTORY  
ACE4_WRITE_DATA/ACE4_ADD_FILE
NFS:         ACE4_APPEND_DATA/ACE4_ADD_SUBDIRECTORY  ACE4_READ_ATTRIBUTES
NFS:         ACE4_WRITE_ATTRIBUTES  ACE4_READ_ACL  ACE4_WRITE_ACL
NFS:         ACE4_SYNCHRONIZE
NFS:    who = OWNER@
NFS:  nfsace4[1]
NFS:    type = 1
NFS:       ACE4_ACCESS_DENIED_ACE_TYPE
NFS:    flags = 0
NFS:    mask = 20
NFS:         ACE4_EXECUTE
NFS:    who = OWNER@
NFS:  nfsace4[2]
NFS:    type = 1
NFS:       ACE4_ACCESS_DENIED_ACE_TYPE
NFS:    flags = 40
NFS:         ACE4_IDENTIFIER_GROUP
NFS:    mask = 40126
NFS:         ACE4_WRITE_DATA/ACE4_ADD_FILE
NFS:         ACE4_APPEND_DATA/ACE4_ADD_SUBDIRECTORY  ACE4_EXECUTE
NFS:         ACE4_WRITE_ATTRIBUTES  ACE4_WRITE_ACL
NFS:    who = GROUP@
NFS:  nfsace4[3]
NFS:    type = 0
NFS:       ACE4_ACCESS_ALLOWED_ACE_TYPE
NFS:    flags = 40
NFS:         ACE4_IDENTIFIER_GROUP
NFS:    mask = 120081
NFS:         ACE4_READ_DATA/ACE4_LIST_DIRECTORY  ACE4_READ_ATTRIBUTES
NFS:         ACE4_READ_ACL  ACE4_SYNCHRONIZE
NFS:    who = GROUP@
NFS:  nfsace4[4]
NFS:    type = 1
NFS:       ACE4_ACCESS_DENIED_ACE_TYPE
NFS:    flags = 40
NFS:         ACE4_IDENTIFIER_GROUP
NFS:    mask = 40126
NFS:         ACE4_WRITE_DATA/ACE4_ADD_FILE
NFS:         ACE4_APPEND_DATA/ACE4_ADD_SUBDIRECTORY  ACE4_EXECUTE
NFS:         ACE4_WRITE_ATTRIBUTES  ACE4_WRITE_ACL
NFS:    who = GROUP@
NFS:  nfsace4[5]
NFS:    type = 0
NFS:       ACE4_ACCESS_ALLOWED_ACE_TYPE
NFS:    flags = 0
NFS:    mask = 120081
NFS:         ACE4_READ_DATA/ACE4_LIST_DIRECTORY  ACE4_READ_ATTRIBUTES
NFS:         ACE4_READ_ACL  ACE4_SYNCHRONIZE
NFS:    who = EVERYONE@
NFS:  nfsace4[6]
NFS:    type = 1
NFS:       ACE4_ACCESS_DENIED_ACE_TYPE
NFS:    flags = 0
NFS:    mask = 40126
NFS:         ACE4_WRITE_DATA/ACE4_ADD_FILE
NFS:         ACE4_APPEND_DATA/ACE4_ADD_SUBDIRECTORY  ACE4_EXECUTE
NFS:         ACE4_WRITE_ATTRIBUTES  ACE4_WRITE_ACL
NFS:    who = EVERYONE@
NFS:  Mode = 0644