Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to preserve ownership and permissions when doing an atomic file replace?

So, the normal POSIX way to safely, atomically replace the contents of a file is:

  • fopen(3) a temporary file on the same volume
  • fwrite(3) the new contents to the temporary file
  • fflush(3)/fsync(2) to ensure the contents are written to disk
  • fclose(3) the temporary file
  • rename(2) the temporary file to replace the target file

However, on my Linux system (Ubuntu 16.04 LTS), one consequence of this process is that the ownership and permissions of the target file change to the ownership and permissions of the temporary file, which default to uid/gid and current umask.

I thought I would add code to stat(2) the target file before overwriting, and fchown(2)/fchmod(2) the temporary file before calling rename, but that can fail due to EPERM.

Is the only solution to ensure that the uid/gid of the file matches the current user and group of the process overwriting the file? Is there a safe way to fall back in this case, or do we necessarily lose the atomic guarantee?

like image 559
Daniel Pryden Avatar asked Feb 28 '18 14:02

Daniel Pryden


2 Answers

Is the only solution to ensure that the uid/gid of the file matches the current user and group of the process overwriting the file?

No.

In Linux, a process with the CAP_LEASE capability can obtain an exclusive lease on the file, which blocks other processes from opening the file for up to /proc/sys/fs/lease-break-time seconds. This means that technically, you can take the exclusive lease, replace the file contents, and release the lease, to modify the file atomically (from the perspective of other processes).

Also, a process with the CAP_CHOWN capability can change the file ownership (user and group) arbitrarily.

Is there a safe way to [handle the case where the uid or gid does not match the current process], or do we necessarily lose the atomic guarantee?

Considering that in general, files may have ACLs and xattrs, it might be useful to create a helper program, that clones the ownership including ACLs, and extended attributes, from an existing file to a new file in the same directory (perhaps with a fixed name pattern, say .new-################, where # indicate random alphanumeric characters), if the real user (getuid(), getgid(), getgroups()) is allowed to modify the original file. This helper program would have at least the CAP_CHOWN capability, and would have to consider the various security aspects (especially the ways it could be exploited). (However, if the caller can overwrite the contents, and create new files in the target directory -- the caller must have write access to the target directory, so that they can do the rename/hardlink replacement --, creating a clone file on their behalf with empty contents ought to be safe. I would personally exclude target files owned by root user or group, though.)

Essentially, the helper program would behave much like the mktemp command, except it would take the path to the existing target file as a parameter. It would then be relatively straightforward to wrap it into a library function, using e.g. fork()/exec() and pipes or sockets.

I personally avoid this problem by using group-based access controls: dedicated (local) group for each set. The file owner field is basically just an informational field then, indicating the user that last recreated (or was in charge of) said file, with access control entirely based on the group. This means that changing the mode and the group id to match the original file suffices. (Copying ACLs would be even better, though.) If the user is a member of the target group, they can do the fchown() to change the group of any file they own, as well as the fchmod() to set the mode, too.

like image 193
Nominal Animal Avatar answered Sep 20 '22 19:09

Nominal Animal


I am by no means an expert in this area, but I don't think it's possible. This answer seems to back this up. There has to be a compromise.

Here are some possible solutions. Every one has advantages and disadvantages and weighted and chosen depending on the use case and scenario.

  • Use atomic rename.

    Advantage: atomic operation

    Disadvantage: possible to not keep owner/permissions

  • Create a backup. Write file in place

    This is what some text editor do.

    Advantage: will keep owner/permissions

    Disadvantage: no atomicity. Can corrupt file. Other application might get a "draft" version of the file.

  • Set up permissions to the folder such that creating a new file is possible with the original owner & attributes.

    Advantages: atomicity & owner/permissions are kept

    Disadvantages: Can be used only in certain specific scenarios (knowledge at the time of creation of the files that would be edited, the security model must allow and permit this). Can decrease security.

  • Create a daemon/service responsible for editing the files. This process would have the necessary permissions to create files with the respective owner & permissions. It would accept requests to edit files.

    Advantages: atomicity & owner/permissions are kept. Higher and granular control to what and how can be edited.

    Disadvantages. Possible in only specific scenarios. More complex to implement. Might require deployment and installation. Adding an attack surface. Adding another source of possible (security) bugs. Possible performance impact due to the added intermediate layer.

like image 37
bolov Avatar answered Sep 21 '22 19:09

bolov