Search code examples
linuxpermissionsgzip

Why don't Linux file permissions stop gzip overwriting the original file?


I just noticed that gzip seems to be able to overwrite a file with its zipped counterpart despite the file permissions being set to read only. I was under the impression that chmod 400 would prevent a file from being altered, and yet it seems that this is not the case. Does overwriting a file not count as a "write"? Or am I misunderstanding how permissions work?

For example, if I create a file full of zeros, remove write permissions, and then gzip it, the file is replaced by a smaller gzipped file. I do not understand why the OS allows this. This works with both SUSE Linux Enterprise Server 15 SP2 and Linux Mint 20.2:

`

ng@bonobo:~/sandbox$ dd if=/dev/zero of=zeros bs=1 count=100
100+0 records in
100+0 records out
100 bytes copied, 0.000693556 s, 144 kB/s
ng@bonobo:~/sandbox$ chmod 400 zeros 
ng@bonobo:~/sandbox$ ls -l
total 4
-r-------- 1 ng ng 100 Feb 10 23:58 zeros
ng@bonobo:~/sandbox$ gzip zeros 
ng@bonobo:~/sandbox$ ls -l
total 4
-r-------- 1 ng ng 30 Feb 10 23:58 zeros.gz

If I try to rm the file, I at least get a warning that it is write-protected, but I am allowed to proceed after typing y. Similarly, I can edit a read-only file in vim and save it using ! to override the warning about it being read-only.

Does this mean that programs like rm and vim are making a system call to change the file permissions (which my account has authority to do), then changing the file, and then setting the permissions back to read-only? And maybe gzip also does this but doesn't warn me first?

This is not really a big problem for me, but it makes me worry that I don't understand permissions and maybe files that I thought were somewhat safe from careless actions might not be so safe.


Solution

  • You need to understand what gzip does and how it does it.

    What it does is to compress the file in place. How it does is to read the original file and then write a compressed version as a new file with a ".gzip" suffix. If that succeeds, it delete the original.

    The file system operations are:

    • open and read the old file - that is permitted by the permissions on the file and parent directory
    • create and write the new file - that is permitted by the permissions on the parent directory
    • delete the old file - that is an operation on the parent directory, and it is permitted provided you have read and write permission for the directory.

    OK ... why doesn't gzip explicitly check that the file is writeable before compressing it? I don't know, but I probably would have implemented gzip like this too, considering that:

    • it is convenient to be able to gzip a tree of files in place without jumping through hoops to deal with read-only files, and
    • gzip compression is reversible and the actions of gzip are mostly (almost) reversible too.