NFSv4 ACL's not being respected by BSD

I have posted this as part of the thread found at http://forums.freebsd.org/showthread.php?p=227701#post227701 also.

I am using a FreeBSD (9.0 - or possibly 9.1) system derived from the ZFSguru distribution. I have a ZFS (pool v15 fs v4) pool set up.

aclinherit and aclmode are both set to 'passthrough' on all the filesystems in the pool, and the pool root itself also. The correct 'NFSv4' ACL data is being shown by getfacl.

Code:
bx83@myhost: ~ $ getfacl ./
# file: ./
# owner: bx83
# group: bx83
          user:somedude:-wx-----------:------:allow
            owner@:rwxp--aARWcCos:------:allow
            group@:r-x---a-R-c--s:------:allow
         everyone@:------a-R-c--s:------:allow

There's no indication that POSIX.1e ACL's are being used, and in fact trying to set 'default' ACL entries gets me an error message about these being redundant for NFSv4 - clearly, NFSv4 ACL's are in effect, and working.

BUT: FreeBSD will only respect the Unix 9-bit mode when checking file permissions.

This is *completely broken* as far as having ACL's in use in your filesystem, because FreeBSD is basically circumventing whatever's in them (besides the rwx permission bits). The whole point of ACL's is to be able to set permissions more finely grained than rwx, and to not have to rely on silly conventions (e.g. needing 'x' to read a directory, instead of just 'r').

In the NFSv4 ACL's used in ZFS, you can set these permissions bits in the ACL for owner@ (the owner of a file/directory at the time) or a specific user (e.g. user:somedude); FreeBSD will at least interpret these entries, as far as taking notice that you've assigned permissions to different entities.

For example, stripping all permissions for everyone@, but adding 'wx' for a specific user, as above, will give somedude wx permissions and everyone else outside of group/owner no permissions; user somedude can make files and edit them in the directory where these ACE's are included, while any other (non-owner, non-group) users won't have any permissions. somedude can also delete the files they create; but somedude can't list the directory contents of the directory they're in (because they lack the 'r' permission).

BUT - no other permissions in the ACL (like p/append, d/delete child, R/read xattribs, etc.) will be respected. They also won't be interpreted as meaning anything - having p/append without 'w' write won't let you append to files, it will just prevent you from writing anything; having p and w will let you write to any part of the file, not just append.

So, continuing with the previous example, if I set somedude's ACE on the current directory to something equivalent to the Unix 'wx', like this:
Code:
user:somedude:-w-p-dD-------:------:allow
(write files, append data to a file, create sub-directories, delete child files/directories)

I can't do *anything* in this directory, because I no longer have the 'x' execute permission - which in an ACL should only grant the permission to execute files (scripts and binaries) -- but to Unix, is necessary to read directory contents (and apparently, do anything in a directory, even if you have write permission to it).

So what the hell, FreeBSD? :p Why can I use a ZFS filesystem, employ it's NFSv4 ACL's, set and read them correctly, but not have them respected? Are only clients on NFS (v4) going to respect these ACL's? Only people mounting my pool via Solaris 10/11?

Is this the fault of FreeBSD, or Bash, or ZFS, or some setting in rc.conf or the kernel, or what?

If anyone could shed light on this I would eternally grateful, it's driving me insane so far.
 
[SOLVED] NFSv4 ACL's not being respected by BSD

Well golly - it only took about three hours of ad-hoc tests (during which I would have preferred to be watching Game of Thrones series 3, but such is the need of a Unix enthusiast to solve problems annoying them, before anything else in life can be enjoyed ;P) -- but I finally cracked it.

I hope this helps anyone else who's been searching for definitive answers like me -- and not for Solaris, or Samba mounts over Linux (ugh...).

Below is a list of the NFSv4 ACL entries, and what they actually mean on a BSD system (i.e. not Solaris 11).

The main quirks I notice are:
  • ownership means you can always edit or restore the ACL, regardless if you've removed the c and C perms for owner@;
  • r and x are required to view a directory's contents. Leaving one out will cause problems (see notes at end);
  • p/append, o/change owner, and s/synchronise mean effectively nothing. p seems to allow creating subdirectories; nobody but root can change owner (still), and sync is redundant on ZFS it would seem -- and for a filesystem famed for having guaranteed data integrity on a write transaction, let's not **** around with 's' in case it jeopardises that :p

Questions I still have (if anyone has answers to these, I'd love to know them!):
  • In what order are ACEs read? Does it even matter?
  • Do "user:" ACEs trump the big three @ (owner@, group@, everyone@) ACEs? It *seems* like they do...?
  • Does Deny trump Allow? It seems as though the effective permissions of a user (and reflected in the usual rwx bits on an ls -la command) is the combination of all the Deny's plus Allows on top -- in other words, Allow trumps Deny. I've read some Solaris documentation which says the same (for Solaris, of course) -- but historically, as with Windows and CISCO network ACL's, a Deny trumps all, and the most restrictive permission set is used. So who knows :/

NOTE: the below applies to my testing on FreeBSD (9-RELEASE), with ZFS support, nfs4acl turned on for all volumes in /etc/fstab, on ZFS filesystems (v4, on pool v15), and with aclinherit and aclmode both set to 'passthrough'. I have to yet to make these ACL's useful or respected mounted over NFSv4 on to my Mac (should keep me occupied in the remaining winter...).

ALSO NOTE: a subject is a user or a group; an object is a file or a directory.

BSD NFSv4 ACL's, and their application on the actual BSD commandline:
  • r = read file, view directory contents;
  • w = create/edit/append/delete files;
  • x = execute file, view directory contents;
  • p = create sub-directory;
  • d = allows deleting a file or directory, even if (you) don't possess ownership or write permission to it;
  • D = allows deletion of a child file or child directory (subdirectory), when D is set on its parent directory; regardless of whether subject possesses ownership or write permission to the directory (on which D is set), or a child object of it; can ONLY be set on a directory object;
  • a = read attributes (e.g. atime);
  • A = change attributes (e.g. update a time);
  • R = read xattribs;
  • W = change/add xattribs;
  • c = read ACL with getfacl;
  • C = change/add ACL with setfacl;
  • o = change owner of file (seems redundant, only root can change a file's owner);
  • s = sync (also seems redundant);

If you have D set for you (your username), a group you belong to, or you're the owner -- you can delete any and all child objects (file or subduers) in that directory, regardless of your write/ownership permissions to the directory (where D is set), or write/ownership permissions on any of the child objects.

If you have d set for you (your username), a group you belong to, or you're the owner -- you can delete an object (file or directory) regardless of your write/ownership permissions to that object.

Further explanation on 'r' and 'x': In a logical world, 'r' would allow you to read files or directory contents; 'x' would allow (binary, file) execution. Not so in the Unix world :/
  • r+x set ON - You can read the directory contents, all files and sub-directory names, sizes, etc.
  • r+x set OFF - Attempt to read directory contents returns Permission Denied and 'total 0'.
  • r OFF x ON - Attempt to read directory contents returns Permission Denied and 'total 0'.
  • r ON x OFF - Returns directory contents (lists files and sub-directories), but with 'Permission Denied' for all of them, and 'total 0' -- weird.

r must be ON to see the actual content/sub-directories listing at all. x must be ON to get information about contents -- r on with x off will read contents/subdirectories, but return no information for each, just permission denied.

Inheritance permissions (only inheritable to directories, of course - files can't reproduce :p ):
  • d = Inherit this ACE on all subdirectories - their ACL will contain this ACE.
  • f = inherit this ACE on all the files created in this directory - their ACL will contain this ACE.
  • i = This ACE doesn't apply to this file, or directory -- it is only inheritable, and will only be copied into the ACLs of subdirectories or child files. If you set owner@, group@ and everyone@ to have 'i' set here, your file/directory will have NO PERMISSIONS (mode 000), unless you've added other ACE's (e.g. for a user or group). Inheritable ACEs are just there for children, they don't affect the object they're actually written into.
  • n = no propagation - I haven't tested this. It appears to means that only child objects will inherit this ACE into their ACLs -- but *their* children won't. You can effectively set ACEs for objects in a directory, but when users create subdirectories, these won't have the ACEs attached.

Hope this helps somebody :)
 
n00balert said:
your last post did help me with 10-Current. Cheers.
10-CURRENT doesn't exist anymore. It's either 10.0-RELEASE, 10-STABLE or 11-CURRENT.
 
some of us are too lazy to upgrade?

Code:
 $ uname -a
FreeBSD myhost.xx.com 10.0-CURRENT FreeBSD 10.0-CURRENT #0 r253489: Sat Jul 20 04:04:52 PDT 2013     root@myhost.xx.com:/usr/obj/usr/src/sys/GENERIC  amd64
 
When it comes to NFSv4 ACLs, FreeBSD works (or at least is supposed to work) exactly the same way as Solaris. Same semantics, including the quirks above. (BTW, it's impressive you figured this out without looking at the source code.) Basically, the Windows semantics, without the parts that don't make sense (synchronize permission), the ones that no longer make sense (read_xattr/write_xattr permissions), and ones that would be a security hole (write_owner permission). Just like in Solaris, the append permission is ignored for regular files (means "create subdirectory" for directories), and read_acl/write_acl are always granted to the owner, to prevent footshooting.

Now, regarding questions: differently from POSIX.1e ACLs, where order doesn't matter, NFSv4 ACLs are evaluated entry by entry, i.e. the order does matter. Think about it this way: for every operation you need to have some permissions. ACL is evaluated rule by rule; every "allow" rule that applies to you (i.e. user:xxx, and you're that user) gives you some permissions. If you get all the permissions you need - you are allowed to proceed. If you hit a "deny" rule before that happens - the access is denied.
 
Hello Trasz@,

and read_acl/write_acl are always granted to the owner, to prevent footshooting.

this mean's, that there is no way to mark a file as read-only on NFSv4? I ask, because i have an kerberized NFSv4 mount and all files which have the permissions 0400 can be overwritten by the owner.

Or is there a way to prevent "overwriting" on NFSv4 for the owner?
 
No, it means there is no way to prevent the file owner from changing the permissions. Marking the file read-only - ie preventing the owner from changing the contents - should still work as expected.

The files in question, do they have ACLs? What does "getfacl" say?
 
serverside: (FreeBSD 11, nfsd)
touch testfile && chmod 0400 testfile && getfacl testfile
Code:
# file: testfile
# owner: rm
# group: rm
            owner@:r-----aARWcCos:-------:allow
            group@:------a-R-c--s:-------:allow
         everyone@:------a-R-c--s:-------:allow

clientside: (Debian, NFSv4.1, sec=krb5p)
ls -l testfile
Code:
-r-------- 1 rm rm 0 Feb 21 07:23 testfile
getfacl testfile
Code:
# file: testfile
# owner: rm
# group: rm
user::r--
group::---
other::---
nfs4_getfacl testfile
Code:
A::OWNER@:rtTnNcCoy
A:g:GROUP@:tncy
A::EVERYONE@:tncy
echo 23 >> testfile

cat testfile
Code:
23

Why is "23" appended although the file is readonly? :)
 
Last edited:
I have no idea; looks like it should be. Could you file a PR?

Also - could you test it on the server side? I mean, verify whether the user that should have local read-only access to that file cannot write to it?
 
server-side test (login as file owner):

getfacl testfile
Code:
# file: testfile
# owner: rm
# group: rm
            owner@:r-----aARWcCos:-------:allow
            group@:------a-R-c--s:-------:allow
         everyone@:------a-R-c--s:-------:allow
echo '23' >> testfile
Code:
-bash: testfile: Permission denied
...on the server the permissions work correct.

same settings, same user, but connected from the client via kerberized NFSv4 mount:

nfs4_getfacl testfile
Code:
A::OWNER@:rtTnNcCoy
A:g:GROUP@:tncy
A::EVERYONE@:tncy
echo '23' >> testfile
cat testfile
Code:
23
...and this is an error. It must be impossible to edit the file from the client, when it is marked as readonly on the server. It seem's that the file permission check isn't working correctly when accessed via NFS.
 
Back
Top