Is it possible to prevent files created being world-readable

filespermissions

Assume a user uid=1000 and guids=1000,33,277 is allowed to create a file in the folder /files/. Is there any way I can prevent that the this user allows others to read the file (which are not at least in the groups 1000, 33 or 277)?

Let the file created be /files/user1000.file then the question can be specific:

Is there a way to prevent this outcome of ls /files/user1000.file -al

-rw-rw-r-- 1 1000 1000 6 May 15 17:21 user1000.file

and have this instead:

-rw-rw---- 1 1000 1000 6 May 15 17:21 user1000.file

Maybe using umask? I know that there are things like setgid drw-rws---, so I'm optimistic there might be a way.

Yet I would imagine it is up to the user to decide to do a chmod o+rw user1000.file?

Best Answer

There are two possible solutions to your problem, which both address slightly different scenarios.

The first one would be using umask. The umask is a value which tells the kernel, which access-bits to clear on newly created files (this primarily affects the open(2) and creat(2) system calls — you would still be able to set access bits »forbidden« through the umask value by explicitly calling chmod(2) on the freshly created file). Thus, if you set umask to 0, all access bits requested by the program creating the file are set. If you set it to 04777, all bits are cleared.

Most of the times, the default umask value would be 022, meaning that write permissions are cleared for group and others.

So to solve your problem, you could have the umask value set to 027, which would result in every created file having write access removed for group and all bits cleared for others:

$ umask
022
$ touch testfile.022
$ ls -l testfile.022
-rw-r--r-- 1 user user 0 May 15 18:56 testfile.022
$ umask 027
$ touch testfile.027
$ ls -l testfile.027
-rw-r----- 1 user user 0 May 15 18:57 testfile.027

To set this in every shell you start, put the appropriate umask call into one of the startup-files of your shell (~/.profile or ~/.bashrc being a good place to start).

Another approach would be using a default Access Control Lists (ACLs) on the directory you want to have those bits cleared in. This approach has two advantages compared to using umask. First, it adds more granularity, namely on directory level, and second, it works for everyone (you won't have to alter the global umask value):

$ umask
022
$ mkdir acldir
$ cd acldir
$ getfacl .
# file .
# owner: user
# group: user
user::rwx
group::r-x
other::r-x
$ ls -la
total 12
drwxr-xr-x  2 user user    6 May 15 19:11 .
drwxr-xr-x 83 user user 8192 May 15:19:08 ..
$ touch testfile.noacl
$ ls -l testfile.noacl
-rw-r--r-- 1 user user 0 May 15 19:14 testfile.noacl
$ setfacl    -m 'user::rwx,group::r-x,other::---' .
$ setfacl -d -m 'user::rwx,group::r-x,other::---' .
# file: .
# owner: user
# group: user
user::rwx
group::r-x
other::---
default:user::rwx
default:group::r-x
default:other::---
$ touch testfile.acl
$ ls -l testfile.acl
-rw-r----- 1 user user 0 May 15 19:16 testfile.acl

As you could see, with the default ACL in place, testfile.acl has access bits for others cleared, even with the umask value set to 022.

For a deeper understanding of ACLs, have a look at the acl(5) man page.

Edit: If you want to prevent the file's owner from doing an explicit chown(2) on the file, you would have to bring out the heavy artillery; I think it's not possible in a standards compliant way (in terms of POSIX). There are several security frameworks out there which might allow you to intercept and filter system calls, but which need additional configuration afford. Some of them are:

  • SELinux (hadn't worked with this, yet, but it's fairly generally available; used by RedHat per default, e.g.)
  • RSBAC (heavy configuration afford, but you'll have really fine grained control over what specific users may do and what not)
  • AppArmor (I think Ubuntu uses this)
Related Question