17

I would like to give a user permissions to create and read files in a particular directory, but not to modify or delete files. If the user can append to files that is ok, but I'd rather not. This is on Ubuntu Linux.

I think this is impossible with standard Unix file permissions, but perhaps this is possible using ACLs? The user will always be connecting using SFTP, so if there was some way to control this within SFTP (as opposed to OS permissions) that would be fine.

To be absolutely clear, I want the following:

  • echo hello > test # succeeds, because test doesn't exist, and creation is allowed
  • echo hello >> test # can succeed or fail, depending on whether appending is allowed
  • echo hello2 > test # fails, because test already exists, and modification is not allowed
  • cat test # succeeds, because reads are allowed
  • rm test # fails, because delete is not allowed

If you're wondering why I want to do this, it's to make a Duplicati backup system resistant to Ransomware.

Rui F Ribeiro
  • 55,929
  • 26
  • 146
  • 227
paj28
  • 273
  • 1
  • 2
  • 8
  • 1
    Files are always created empty. When you do `echo > test`, the shell does a `open("test", O_WRONLY|O_CREAT|O_TRUNC)` which creates the file and then invokes `echo` that writes the content so modifies it. Now you could allow only the first open(WR) to succeed. – Stéphane Chazelas Aug 12 '15 at 11:19
  • @StéphaneChazelas - edited to clarify that appending is allowed – paj28 Aug 12 '15 at 11:26

2 Answers2

19

You could use bindfs like:

$ ls -ld dir
drwxr-xr-t 2 stephane stephane 4096 Aug 12 12:28 dir/

That directory is owned by stephane, with group stephane (stephane being its only member). Also note the t that prevents users from renaming or removing entries that they don't own.

$ sudo bindfs -u root -p u=rwD,g=r,dg=rwx,o=rD dir dir

We bindfs dir over itself with fixed ownership and permissions for files and directories. All files appear owned by root (though underneath in the real directory they're still owned by stephane).

Directories get drwxrwxr-x root stephane permissions while other types of files get -rw-r--r-- root stephane ones.

$ ls -ld dir
drwxrwxr-t   2 root     stephane   4096 Aug 12 12:28 dir

Now creating a file works because the directory is writeable:

$ echo test > dir/file
$ ls -ld dir/file
-rw-r--r-- 1 root stephane 5 Aug 12 12:29 dir/file

However it's not possible to do a second write open() on that file as we don't have permission on it:

$ echo test > dir/file
zsh: permission denied: dir/file

(note that appending is not allowed there (as not part of your initial requirements)).

A limitation: while you can't remove or rename entries in dir because of the t bit, new directories that you create in there won't have that t bit, so you'll be able to rename or delete entries there.

Stéphane Chazelas
  • 522,931
  • 91
  • 1,010
  • 1,501
  • This is brilliant! Thank-you for taking the time to work out such an elegant solution. I had heard of bindfs before, but this is the first time I've actually used it. – paj28 Aug 12 '15 at 16:15
  • This is so insane! Thank you for having the brain you have!! – Stephan Møller Feb 03 '23 at 14:26
5

The chattr +a option will allow appending only. Files may be altered that way, but only by adding (i.e. appending lines) to them. You cannot delete existing files, but create new ones. This might fit your needs:

sudo chattr -R +a /dir/to/apply/to

from man chattr

A file with the `a' attribute set can only be open in append mode for writing. Only the superuser or a process possessing the CAP_LINUX_IMMUTABLE capability can set or clear this attribute.

(note that it applies to directories, too)

So your list would look like:

echo hello > test # succeeds, because test doesn't exist, and creation is allowed
echo hello2 > test # fails, because test already exists, and overwriting is not allowed
echo hello3 >> test # succeeds, because appending is allowed
cat test # succeeds, because reads are allowed
rm test # fails, because delete is not allowed
FelixJN
  • 12,616
  • 2
  • 27
  • 48
  • Ok, this sounds promising. It correctly prevents deletes, and if a file has the attribute, it prevents overwrites. However, when new files are created they do not automatically get the attribute. Is there some way to have this happen automatically? – paj28 Aug 12 '15 at 11:14
  • If the directory has the attribute, the files will behave accordingly despite not having the attribute explicitly set. The problem is files in new subdirs. E.g. dir1 is `chattr +a` then I can create a file, am not allowed to remove it, can append. If I create dir1/dir2 then I can do as I please IN dir2 – FelixJN Aug 12 '15 at 11:18
  • 1
    Unfortunately not: http://dpaste.com/042XQ7X – paj28 Aug 12 '15 at 11:20
  • Aahh, sorry - I did a wrong test earlier – FelixJN Aug 12 '15 at 11:24
  • @paj28 your link is broken :-( – mjaggard Mar 07 '17 at 09:10
  • @mjaggard - Sorry, the dpaste has expired. In any case, the accepted answer is a better solution. – paj28 Mar 07 '17 at 09:45
  • Is this enough to prevent ransomware from making the file useless? – Freedo Nov 19 '18 at 20:01
  • @Freedo The best way against ransomware attacks is always a good backup. Yet the files may not be rewritten here, which includes not allowing encryption. If your attacker gains root rights however ..... – FelixJN Dec 19 '18 at 20:31