4

I have SMB/CIFS file sharing set up on an OmniOS server with the Solaris kernel module which uses NFSv4 ACLs that should work correctly with Windows clients.

I want to create a shared directory with the following goals: a user (let's say alice) should be able to create and modify files, but not delete them. Also creation of subdirectories should be prevented. Read access should be permitted.

I've tried the following ACL, which basically works:

/usr/bin/chmod A=\
user:root:rwxpdDaARWcCos:fd-----:allow,\    # root has full access
user:alice:rwx---a-R-c--s:-------:allow,\   # dir: create files, read everything
user:alice:rwxp--aARWc--s:f-i----:allow \   # files: wpAW is needed for full file write access, everything is only inherited to files
/pool/share

But if alice views the Security tab of the newly added files in the Windows Explorer, she can grant herself full access rights and delete the file afterwards, even if she does not have Co rights.

How to explain this behavior? And how can I change it so that ACLs cannot be modified?


Edit: Output of ls seems to be normal:

# /usr/bin/ls -v
total 1
-rwx------+  1 alice staff          3 2016-03-21 test.txt
    0:user:root:read_data/write_data/append_data/read_xattr/write_xattr
        /execute/delete_child/read_attributes/write_attributes/delete
        /read_acl/write_acl/write_owner/synchronize:inherited:allow
    1:user:alice:read_data/write_data/append_data/read_xattr
        /write_xattr/execute/read_attributes/write_attributes/read_acl
        /synchronize:inherited:allow

# /usr/bin/ls -V
total 1
-rwx------+  1 alice staff          3 2016-03-21 test.txt
    user:root:rwxpdDaARWcCos:------I:allow
    user:alice:rwxp--aARWc--s:------I:allow

Output of ls for the directory itself:

# /usr/bin/ls -Vd
drwx------+  3 root     root           4 2016-03-21 .
 user:root:rwxpdDaARWcCos:fd-----:allow
user:alice:rwx---a-R-c--s:-------:allow
user:alice:rwxp--aARWc--s:f-i----:allow

# /usr/bin/ls -vd
drwx------+  3 root     root           4 2016-03-21 .
    0:user:root:list_directory/read_data/add_file/write_data
        /add_subdirectory/append_data/read_xattr/write_xattr/execute
        /delete_child/read_attributes/write_attributes/delete/read_acl
        /write_acl/write_owner/synchronize:file_inherit/dir_inherit:allow
    1:user:alice:list_directory/read_data/add_file/write_data
        /read_xattr/execute/read_attributes/read_acl/synchronize:allow
    2:user:alice:list_directory/read_data/add_file/write_data
        /add_subdirectory/append_data/read_xattr/write_xattr/execute
        /read_attributes/write_attributes/read_acl/synchronize
        :file_inherit/inherit_only:allow

The filesystem of the share is ZFS. The most interesting non-default properties are as follows:

NAME        PROPERTY        VALUE          SOURCE
pool/share  type            filesystem     -
pool/share  compression     lz4            inherited from pool
pool/share  atime           off            local
pool/share  aclmode         restricted     local
pool/share  aclinherit      passthrough    local
pool/share  version         5              -
pool/share  utf8only        on             -
pool/share  normalization   formD          -
pool/share  casesensitivity insensitive    -
pool/share  nbmand          on             local
pool/share  sharesmb        name=testshare local

CIFS share permissions are set to allow everyone full access, so only the file permission should apply.

Update:

This thread is very similar to my problem, although the solution with reducing the ACLs in /pool/share/.zfs/shares/testshare to modify_set for everyone (or denying users specific delete permissions) does not seem to work in my case and I don't know why.

user121391
  • 2,452
  • 12
  • 31
  • Post the output of `ls -v /pool/share` and/or `ls -V /pool/share`. – Andrew Henle Mar 21 '16 at 16:36
  • @AndrewHenle Thanks for the suggestion, I edited my question with the results of ls. – user121391 Mar 21 '16 at 17:05
  • Does the `alice` user actually own the directory? – Andrew Henle Mar 21 '16 at 18:18
  • No, root owns it. Although it shouldn't matter, should it? I have removed all owner/group/everyone permissions from it, so ownership should not matter much? – user121391 Mar 22 '16 at 08:42
  • If `alice` owns the directory, that user would definitely be able to delete files in it through normal Unix-style permissions. Could you post the output of `ls -vd /pool/share`? That should be the correct command to post the ACLs and permissions of the directory itself. And I assume the underlying file system is ZFS? – Andrew Henle Mar 22 '16 at 10:24
  • Yes, it is ZFS, i forgot to add this. I edited my post and also included the ZFS properties. – user121391 Mar 22 '16 at 12:25
  • Does `alice` need `write_data` on the *directory*? The ACLs already give the user the ability to create files and subdirectories. I'd think `write_data` on a directory would be the same as giving the user normal Unix-style `write` access to the directory itself, which does give the user the ability to delete files, although for once [the documentation](http://docs.oracle.com/cd/E23823_01/html/819-5461/gbacb.html) isn't clear as to how that ACL value applies to a directory: *write_data w Permission to modify or replace the contents of a file.* – Andrew Henle Mar 24 '16 at 10:13
  • w means ability to create a file: *add_file w Permission to add a new file to a directory.* I also tried to remove only the write_data in verbose format, but it is not accepted. I also noticed that `p` is needed on files in my case despite what the documentation says, otherwise the file is empty. It may depend on the ways different applications write their files. – user121391 Mar 24 '16 at 10:48
  • `w` also maps to `write_data`. so `add_file` and `write_data` seem tightly coupled if not actually identical then. Interesting that those aren't separated at all. What about explicitly denying `delete_child` and/or `delete` permissions? – Andrew Henle Mar 24 '16 at 11:27
  • Makes no difference, the user always seems to retain full control over owned files (embedded's answer explains it). – user121391 Mar 24 '16 at 12:07
  • OK, I'm reduced to these: deny `write_attribute` to the files, or set the sticky bit on the directory. If neither of those work, I'm pretty sure Samba is used under the hood to perform CIFS shares (I know it is in Solaris 11). The Samba config file is likely `/etc/samba/smb.conf` (if not, look in `/lib/svc/method/samba` to find the config file) and set `acl map full control = No` in the `[global]` section (I think it will work there). If you read the Samba [smb.conf documentation](https://www.samba.org/samba/docs/man/manpages/smb.conf.5.html), by default `rwx` is mapped to "full control". – Andrew Henle Mar 25 '16 at 13:02
  • And FWIW, I found it a lot easier to do CIFS shares from Solaris by setting up a zone specifically just to run Samba and share via CIFS. The driver behind that was the performance of ZFS SMB/CIFS shares using ZFS sharing to Android mobile devices was absolutely horrendous. Performance was great on other platforms, but it was unusable on Android. Interesting because it's just the OS-supplied Samba doing the sharing in both cases. But once I did that, I found administering Samba directly was a lot easier, and also provided much finer-grained control than the ZFS properties provide. – Andrew Henle Mar 25 '16 at 13:08
  • Denying `write_attributes` on the the files prevents them to be written correctly, unfortunately (they are empty). Would setting the sticky bit not be the opposite from what I want? See the last paragraph in http://unix.stackexchange.com/questions/79395/how-does-the-sticky-bit-work : *"For directories, it prevents unprivileged users from removing or renaming a file in the directory unless they own the file or the directory"* – user121391 Mar 30 '16 at 08:42
  • Regarding native samba: I've read in the napp-it documentation and several forum posts from its creator (gea) that the ZFS CIFS module should be preferred over native samba if you want to achieve highest compatibility with Windows operating systems. Also, I would prefer to not change everything just for this single problem case that affects one directory. – user121391 Mar 30 '16 at 08:45

2 Answers2

1

IMHO everything gets really confusing if you remove the trivial acls for user,group,everyone. Things to consider:

  • In cases of deny permissions or when an access permission for a file is missing, the privilege subsystem determines what access request is granted for the owner of the file or for superuser. This mechanism prevents owners of files from getting locked out of their files and enables superuser to modify files for recovery purposes.
  • POSIX-draft based ACLs use a single entry to define which permissions are allowed and which permissions are denied. The new ACL model has two types of ACEs that affect access checking: ALLOW and DENY
  • The owner of a file is granted the write_acl permission unconditionally, even if the permission is explicitly denied.
  • If you change the permissions of the file, a file's ACL is updated accordingly. In addition, if you remove a non-trivial ACL that granted a user access to a file or directory, that user could still have access to the file or directory because of the file or directory's permission bits that grant access to a group or to everyone

So my approach is to modify the trivial acls according to the needs (use deny mode) and than add non-trivial acls for all the special use cases. Keep this in mind as well:

  • After an allow permission has been granted, it cannot be denied by a subsequent ACL deny entry in the same ACL permission set.

If have no idea what OmniOS is, but these documents helped me understand NFS ACL. We use Solaris with ZFS https://docs.oracle.com/cd/E53394_01/html/E54801/ftyxi.html#scrolltoc

embedded
  • 456
  • 1
  • 6
  • 19
  • Thank you for your answer, I was not aware of this security fallback, I will test with additional users/non-owners. OmniOS is an illumos-based distribution, I think the ZFS and ACL behaviour should not differ much from Solaris 10. – user121391 Mar 23 '16 at 15:02
  • Could you please explain your approach a bit more? I tried to first deny deletion and acl change permissions and then allow user-based, but it is not different from before. Or is it still impossible to work around the owner-acl limitation you outlined earlier? – user121391 Mar 24 '16 at 10:00
  • I also updated my post with a link to a very similar problem, but that solution did not help in my case. – user121391 Mar 24 '16 at 10:07
1

After ignoring this problem for a week, it now suddenly works... I don't know what has caused it, but it works... I have tried the suggestion from this blog, but modified it to include AW as rights. Then I tested it again, this time only with my older deny rules (overwriting the new ones completely), that also worked. Finally I used the very first settings from my own question which never worked, but now they did.

After some more testing, I think it was because the SMB service was not restarted before and the share ACLs where not recognized correctly. Changing them was the only way I could restore the old (and wrong) behavior.

So, for future reference, the solution is to define the normal permissions on the files themselves, and not allow Co permissions on the share level:

  1. Apply the following ACL rules to the directory and (inherited) to all newly created files:

    /usr/bin/chmod A=\
    user:root:rwxpdDaARWcCos:fd-----:allow,\    # root has full access
    user:alice:rwx---a-R-c--s:-------:allow,\   # dir: create files, read everything
    user:alice:rwxp--aARWc--s:f-i----:allow \   # files: wpAW is needed for full file write access, everything is only inherited to files
    /pool/share
    
  2. Apply the following ACL rules to the ZFS dataset's hidden share directory (this is needed to prevent the owner from modifying ACLs, for details see @embedded's answer and the linked serverfault post):

    /usr/bin/chmod A=\
    user:root:full_set:-------:allow,\          # root has full access
    everyone@:modify_set:-------:allow \        # anyone else cannot modify permissions
    /pool/share/.zfs/shares/testshare
    
  3. Restart the SMB server (needed to update changed share ACLs, see this thread):

    svcadm restart svc:/network/smb/server:default # restart service
    svcs -xv svc:/network/smb/server:default       # check if the startup date has changed
    

Now new files can be created and written, but not deleted and also Windows users cannot give themselves additional rights. This solution works fine for my situation, but I can see two small downsides:

  • You have to remember/document that you changed the share level, if additional permissions should be set in the future.
  • It is possible that a user modifies the content of documents. For example, alice can overwrite chars or lines in a text document. I think this is because the application I use needs the append and write privileges and there is no ACL that checks for "initial write only" or similar.
user121391
  • 2,452
  • 12
  • 31