Subject: [nfsv4] NFSv4 <-> POSIX-draft ACL interoperability

From: Sam Falkner <[email-masked]>
Date: Wed, 01 Dec 2004 13:34:00 -0700

The following is a summary of the issues found at the October Bakeathon. 

The issues stem from various vendor's need to translate to and from
NFSv4 and POSIX-draft ACL models.  Many of these points are being
re-iterated from an email thread started earlier by Bruce Fields.

We are also attaching a document that describes current Solaris server
behaviors.

- Sam Falkner
  Lisa Week

Building on the previous thread, in order to most correctly resolve
these issues there are a couple of different angles of the problems to
think about.

The issues can be divided up into client and server problems.
These being:

1.) What should a server accept upon a client setting an ACL.
2.) What should a server respond as being the base ACL on a file upon 
    its creation.
3.) What should a client accept upon getting an ACL.
4.) What should a client attempt to set.

Issues

0. Motivation for current Solaris behavior

In any situation where the existing Solaris filesystem (UFS) could not
enforce the semantics of an NFSv4 ACL, it was decided to reject the ACL,
rather than inaccurately representing the NFSv4 ACL on the server
filesystem.

We still feel that being strict with what ACLs are accepted is the most
correct approach, but we are considering making changes in order to
improve interoperability.

1. ACE4_DELETE

1.1 Solaris

Currently, Solaris does not set the ACE4_DELETE mask on any ACEs.  If a
Solaris client or server receives an ACL with ACE4_DELETE on any ACEs,
it fails; server returns NFS4ERR_ATTRNOTSUPP, client gives ENOTSUP and
it fabricates an ACL from the mode bits of the file.

Rationale: with current Solaris filesystems, the ability to delete a
file cannot be allowed or denied on a per-file basis via an ACL.
Instead, this is determined via the permissions on the parent
directory.

1.1.1 Changes we could make to allow for better interoperability

Server

Solaris would ignore ACE4_DELETE on any ACEs in any ACL it receives.
It would continue to produce ACLs without ACE4_DELETE set on any of its
ACEs.  This would allow Solaris to be less strict on the ACLs it
accepts; the drawback is that a client could set an ACL with
ACE4_DELETE on some of its ACEs, but a subsequent get would not receive
the same ACL that was set.

Client

Solaris client would continue to produce ACLs without ACE4_DELETE set
on any ACEs.  When the Solaris client receives an ACL, it would ignore
the ACE4_DELETE mask on any ACEs.  The drawback for this would be that
"setfacl -m ...", which is a command line utility to modify an existing
POSIX-draft ACL, would silently lose any ACE4_DELETE masks that were
present in the original ACL.

1.2 IBM

An AIX server requires that both ACE4_DELETE be ALLOWED on a file, and
ACE4_DELETE_CHILD be ALLOWED on the parent directory, in order to
delete a file.

1.3 NetApp

A NetApp server requires that either ACE4_DELETE be ALLOWED on a file,
or ACE4_DELETE_CHILD be ALLOWED on a directory, in order to delete a
file.

1.4 Linux/CITI

???

2. ACE4_SYNCHRONIZE

2.1 Solaris

Currently, Solaris does not set the ACE4_SYNCHRONIZE on any ACEs.  If a
Solaris client or server receives an ACL with ACE4_SYNCHRONIZE on any
ACEs, it fails; server returns NFS4ERR_ATTRNOTSUPP, client gives
ENOTSUP and it fabricates an ACL from the mode bits of the file.

Rationale: ACE4_SYNCHRONIZE has no meaning on a POSIX system.

2.1.1 Changes we could make to allow for better interoperability

Server

Solaris would set ACE4_SYNCHRONIZE on all ALLOW ACEs.  Server would
accept an ACL with ACE4_SYNCHRONIZE on any ALLOW ACEs, but return
NFS4ERR_ATTRNOTSUPP if ACE4_SYNCHRONIZE is on any DENY ACEs.

Client

Solaris client would ignore ACE4_SYNCHRONIZE on any ACEs upon getting
an ACL.  Client would set ACE4_SYNCHRONIZE on any ALLOW ACEs on setting
an ACL.

2.2 IBM

An IBM server sets ACE4_SYNCHRONIZE on all ALLOW ACEs.  Presumably it
accepts ACLs with ACE4_SYNCHRONIZE on ALLOW ACEs; what is the behavior
if it receives an ACL with ACE4_SYNCHRONIZE on a DENY ACE?

2.3 NetApp

A NetApp server sets ACE4_SYNCHRONIZE on all ALLOW ACEs.  Presumably it
accepts ACLs with ACE4_SYNCHRONIZE on ALLOW ACEs; what is the behavior
if it receives an ACL with ACE4_SYNCHRONIZE on a DENY ACE?

2.4 Linux/CITI

A Linux server sets ACE4_SYNCHRONIZE on all ALLOW ACEs.  Presumably it
accepts ACLs with ACE4_SYNCHRONIZE on ALLOW ACEs; what is the behavior
if it receives an ACL with ACE4_SYNCHRONIZE on a DENY ACE?

3. ACE4_WRITE_OWNER

3.1 Solaris

Currently, a Solaris server does not set ACE4_WRITE_OWNER on any ACEs.
If it receives an ACL with ACE4_WRITE_OWNER on any ACEs, it will return
NFS4ERR_ATTRNOTSUPP.  If a Solaris client receives an ACL with
ACE4_WRITE_OWNER set on any ACEs, it will fail with ENOTSUP and may
fabricate an ACL based on the file's mode bits.

Rationale: with the current Solaris filesystems, the ability to write
the owner (i.e. "chown") cannot be allowed or denied on a per-file
basis via an ACL.

3.1.1 Changes we could make to allow for better interoperability

Server

Solaris would set ACE4_WRITE_OWNER on all DENY ACEs it produces.  It
would also ignore ACE4_WRITE_OWNER on any DENY ACEs in any ACL it
receives, but would error with NFS4ERR_ATTRNOTSUPP if ACE4_WRITE_OWNER
is set on any ALLOW ACEs.

Client

Solaris would ignore ACE4_WRITE_OWNER on any ACEs in any ACL it
receives.  It would continue its policy of never setting
ACE4_WRITE_OWNER on any ACEs in ACLs that it produces.  The drawback
for this would be that "setfacl -m ...", which is a command line
utility to modify an existing POSIX-draft ACL, would silently lose any
ACE4_WRITE_OWNER masks that were present in the original ACL.

3.2 IBM

???

3.3 NetApp

???

3.4 Linux/CITI

A Linux server sets ACE4_WRITE_OWNER on all DENY ACEs.  Presumably it
accepts ACLs with ACE4_WRITE_OWNER on DENY ACEs, and fails when
receiving ACLs with ACE4_WRITE_OWNER on ALLOW ACEs.

4. ACE ordering on Solaris

Solaris Beta 7 had a bug where NFSv4 ACLs were translated from
POSIX-draft incorrectly with regards to the ordering of the group
ACEs.

This has been fixed as of November 22, 2004, and the fix will be
available in the final release of Solaris 10.
_______________________________________________
nfsv4 mailing list
[email-masked]
https://www1.ietf.org/mailman/listinfo/nfsv4

---

From: "J. Bruce Fields" <[email-masked]>
Date: Wed, 8 Dec 2004 17:10:49 -0500

> it fabricates an ACL from the mode bits of the file.

I don't understand the description of the client's behaviour.  If an
application asks for an ACL, surely the client can't both return
ENOTSUP and return the fabricated ACL at the same time?

> the same ACL that was set.

In the case of ACE4_DELETE set in a DENY ace, this would be a violation of
"the guiding principle is that the file not appear to be more secure
than it really is." (5.11.3).  Does this scare anybody, or does nobody
care?

> 1.4 Linux/CITI

Our server returns -EINVAL if you send an ACE with DELETE set.
Permissions to unlink are determined in the traditional way (by
consulting write permissions on the directory).  The posix getfacl
utility on our client will return an error if the DELETE bit is set in
any ACL, and the posix setfacl will never send an ACE with DELETE set.

> if it receives an ACL with ACE4_SYNCHRONIZE on a DENY ACE?

It returns EINVAL.  It also returns EINVAL if you don't set
SYNCHRONIZE in an ALLOW ace.  This should probably be relaxed; I can't
see any harm to silently turning on SYNCHRONIZE in an ACL that didn't
explicitly deny SYNCHRONIZE.

> is set on any ALLOW ACEs.
....
> receiving ACLs with ACE4_WRITE_OWNER on ALLOW ACEs.

Yes.  The Solaris behaviour sounds reasonable, though.

> available in the final release of Solaris 10.

Some reorderings of the group ACEs don't change the meaning of the ACE,
and a smart implementation might allow for this.  But agreeing on an
order allows a simpler implementation.

Content-Description: Current Solaris behavior
> Current Solaris behavior is modeled after the internet draft
> http://www.ietf.org/internet-drafts/draft-ietf-nfsv4-acl-mapping-02.txt
> by Marius Aamodt Eriksen and J. Bruce Fields.  There may be some changes
> made before Solaris 10 is shipped, to allow for better interoperability
> between Solaris and other vendors.
> 
> This document describes what the Solaris NFSv4 Server will accept for
> ACLs when it must map to POSIX-draft ACLs for a UFS filesystem.

Thanks for the thorough description; I hope to take a closer look at it
in the next couple days.  We also have a python script that tests some
of the mapping behaviour.

--b.

---

From: Lisa Week <[email-masked]>
Date: Thu, 09 Dec 2004 13:23:03 -0700

Hi Bruce and others.

Comments inline...

Thanks,
Lisa Week
Sam Falkner

> ENOTSUP and return the fabricated ACL at the same time?

Yes, this is a bit odd, but right now in Solaris, we have a requirement 
that the calls to get an acl must not fail.  The ENOTSUP is never seen 
by the user when using the Solaris system call (acl/facl) to get an acl.

> than it really is." (5.11.3).  Does this scare anybody, or does nobody

To be honest, we'd prefer to keep Solaris' current behavior, but as you 
know, this really causes problems for IBM since they must have 
ACE4_DELETE and ACE4_DELETE_CHILD ALLOWed in order to delete a file. 
Right now, on a brand new file, an IBM server sends ACLs with 
ACE4_DELETE in the ALLOW ACE's.  Because of this our client is unable to 
even get an ACL from an IBM server.  Seems pretty serious...

Question for IBM:  By default, does your client place ACE4_DELETE in any 
ACE's upon setting an ACL?  If yes, with the current Solaris behavior, 
an IBM client would not be able to set an acl on a Solaris/UFS server.

> any ACL, and the posix setfacl will never send an ACE with DELETE set.

This is the same as Solaris' current behavior except for the fact that 
our server will return NFS4ERR_ATTRNOTSUPP if you send an ACE with 
ACE4_DELETE set. (That may be what you meant anyway...?)

> explicitly deny SYNCHRONIZE.

This is similar to our proposed changes.  The only subtle difference is 
that we wouldn't require ACE4_SYNCHRONIZE to be there in all cases (it 
can be completely missing), but we will return NFS4ERR_ATTRNOTSUPP if 
ACE4_SYNCHRONIZE is in a DENY ACE.

Might have to think about it a bit more, but I don't think we would mind 
requiring ACE4_SYNCHRONIZE to be on the ALLOW ACE's...I guess this would 
be the least suprising to the user.

> Yes.  The Solaris behaviour sounds reasonable, though.

Just to clarify, which Solaris behavior sounds resonable.  The current 
or the proposed?

I think you meant the current behavior so:
We believe it would be a good goal to have our behaviors be the 
same...If you believe the current Solaris behavior is resonable, should 
we go with that?

> order allows a simpler implementation.

Yup.

> of the mapping behaviour.

Feel free to contact us with any questions (this goes to all of you)! 
The whole idea of that description is to get other vendors aware of what 
they have to do to interoperate with us.

We will continue to post updates to this doc with any future changes.

---

From: "J. Bruce Fields" <[email-masked]>
Date: Fri, 10 Dec 2004 15:59:24 -0500

> ACE4_DELETE set. (That may be what you meant anyway...?)

You're just complaining about the choice of error?  What we're returning
now is NFS4ERR_INVAL, and I agree that that's a bug, and that
NFS4ERR_ATTRNOTSUPP would make more sense.

> same...If you believe the current Solaris behavior is resonable, should 

Yes.  Having thought about it some more, I like the idea of leaving bits unset
whenever we can, for a couple reasons:
	1. By leaving it unset, it's clearer that we're not making a
	   commitment to enforce it.  (By rfc3530, the access check
	   algorithm's behaviour is undefined when we fall off the end of
	   the acl without encountering a requested bit in an ALLOW or
	   DENY bit.)
	2. It seems simpler to just say "we don't support that bit" and
	   leave it unset.  It might make it a bit easier for non-posix
	   clients to figure out what's going on too.
	3. It will also make the ACLs that users see by default simpler.
	   Currently, from a Linux client to a Linux server, if I touch
	   a file (with no default ACL on the parent directory), I get
	   something like this:
		$ touch /mnt/puzzle/test1/FOO
		$ nfs4_getfacl /mnt/puzzle/test1/FOO
		1: A::OWNER@:rwanNtTcCy
		2: D::OWNER@:xo
		3: A:g:GROUP@:rntcy
		4: D:g:GROUP@:waNxTCo
		5: A::EVERYONE@:rntcy
		6: D::EVERYONE@:waNxTCo
	   I mean, good grief, who wants to have to figure out what
	   "rwanNtTcCy" means.  It would be nice to pare these down a bit.

And as long as we're going to be breaking Linux's compatibility with
itself, we may as well do the same thing with SYNCHRONIZE (with the
exception that if someone only lists SYNCHRONIZE in an ALLOW ace, then
it's probably safe for us just to ignore it).

--b.

---

From: Lisa Week <[email-masked]>
Date: Fri, 10 Dec 2004 14:27:32 -0700

> NFS4ERR_ATTRNOTSUPP would make more sense.

Not complaining, just pointing out a difference. ;)

> it's probably safe for us just to ignore it).

So...SYNCHRONIZE, eh?

Well, we are perfectly fine (already have changes in hand) for always 
ALLOWing ACE4_SYNCHRONIZE.  It is our perception that all other vendors 
have decided to ALLOW ACE4_SYNCHRONIZE so maybe we should stick with 
that decision and not stir the pot there???