Velvet Star Monitor

Standout celebrity highlights with iconic style.

general

Vim can break file permissions?

Writer Matthew Harrington

I was using Vim the other day as usual, when I noticed something strange. Here's what I did:

~$ touch testfile
~$ ls -l | grep testfile
-rw-r--r-- 1 username groupname 0 Jul 23 10:00 testfile
~$ vim testfile

Then I made a change, and saved and quit with :wq. Pretty normal. Then, however:

~$ sudo chown root:root testfile
~$ sudo chmod 644 testfile
~$ sudo -k
~$ ls -l | grep testfile
-rw-r--r-- root root 0 Jul 23 10:02 testfile
~$ vim testfile

So root should have r/w access and everyone else should have only read. Edit the file, try to save - you can't. Awesome, working as intended. However, if you save with :w!, vim somehow changes the file ownership back to username:usergroup and the file is saved. Even if you do this:

~$ sudo chmod 444 testfile
~$ sudo -k
~$ ls -l | grep testfile
-r--r--r-- 1 root root 0 Jul 23 10:06 testfile
~$ vim testfile

You can still overwrite with :w!! What is happening? How can vim break the laws of file ownership and permission like this? I looked at the help page in vim by saying :help :w and found this:

:w[rite]! [++opt] Like ":write", but forcefully write when 'readonly' is set or there is another reason why writing was refused. Note: This may change the permission and ownership of the file and break (symbolic) links. Add the 'W' flage to 'cpoptions' to avoid this.

I've been unable to write to a file in vim previously when I shouldn't, so I guess the real heart of my question is, how can I make a file unedit-able by vim and why isn't it based on file system permissions, like I'd expect, and what mechanism is vim using to edit the file that other editors (gedit, nano) can't use?

EDIT: The computer I tried this on is using Linux kernel 3.15.5-2-ARCH. Vim's version number is 7.4.373-1, and it's the one installed by pacman - I didn't compile it from scratch with any special options.

3

1 Answer

I can see that your current path is ~, your user's home directory. You should have write permissions to that directory.

Think of it another way - if you have read and write permissions to the directory, what's stopping you from copying the file, deleting the old one and renaming the new one with different permissions?

This is exactly what vim does!


If you run vim under strace, for example:

open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0644) = -1 EACCES (Permission denied)
lstat("testfile", {st_mode=S_IFREG|0644, st_size=10, ...}) = 0
getuid() = 1000
unlink("testfile") = 0
open("testfile", O_WRONLY|O_CREAT|O_TRUNC, 0644) = 3
write(3, "ffjidfjds\n", 10) = 10
fsync(3) = 0
close(3) = 0
chmod("testfile", 0644) = 0

Based on this log, I can guess at the following process:

Some earlier permission checks (and chown attempts, etc.) are omitted for brevity.

  1. open Attempt to open the file for writing (fail: permission denied)
  2. lstat Check the owner of the file
  3. getuuid Check the current user ID, to see if they match the file owner
  4. unlink Delete the file (this is allowed because write permission on the directory)
  5. open Create a new file with the same name
  6. write The file contents (read earlier, I typed in some gibberish)
  7. fsync Flush the file to disk (not really important)
  8. close
  9. chmod Change the new file's permissions to look like the old one - it just happens to have a new owner now.
4

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy