2

Ubuntu 20.04, the disk partition format is EXT4. normal user with sudo privilege, in a tmp dir, e.g: ~/tmp/

$ sudo touch c.txt
// this will create a root-root(user-group) file with mode 644, as expected.
$ rm c.txt
$ rm: remove write-protected regular empty file `c.txt'?     // sys prompt
if I selected 'y', then c.txt will be removed ! // NOT as expected.

I even tried rm not-empty file, still can remove !

I tried two computers both with Ubutnu 20.04, same.

why normal user can remove root file without sudo ?

Thanks!

P.s: After check doc on https://help.ubuntu.com/community/FilePermissions yes, normal user can delete any files in a full controlled directory(rwx=7), regardless file owner, modes. however, it seems that it should not apply with modfication operation. e.g:

// TC2
sudo vim d.txt     // this will create a root-root(user-group) with 644 mode

vim d.txt   
// edit by normal user, use w! to save in vim, 
// after exit vim, the file content changed and the user-group 
// chagned to current user group, not root-root anymore.

This is as expected ?

2
  • is that because I am the owner of dir ~/tmp/, so I can manage all files underneath no matter whose owner the file is ? I will check this with offical doc...
    – chenzero
    Oct 31, 2021 at 6:13
  • It's likely some inconsitent in file permission control. If I can use TC2 steps to change a file content, owner, and group, why I can not directly change the file by chown command ? I tried, If run $ chown chenzero d.txt in the terminal, chown will output: operation not permitted.
    – chenzero
    Oct 31, 2021 at 15:39

2 Answers 2

5

To delete a file from a directory all you is permission on directory itself the permissions on that file are irrelevant. In your case Normal user is having full permission on the directory that contains file in it. you can change it to immutable to prevent from deleting it: sudo chattr +i file

OR:

sudo chmod o-w /path_to_directory

11
  • 5
    The way I think of this is that the permissions on a file apply to its contents. Deleting, moving, or renaming a file does not touch its contents, so the permissions on it are irrelevant; these operations change the contents of the directory (and, for moving, the directory it's moving to), so write permission to the dir(s) is required. When you "delete" a file, you're really just removing ("unlinking") it from the directory, and if there are no remaining directory entries ("links") for it, it just sort of pops out of existence. Oct 31, 2021 at 6:41
  • 4
    @chenzero That's not true. A normal user can't modify a file owned by root, but a normal user can replace a file owned by root by a new file owned by that user, as long as it happens in a directory writable for the user.
    – TooTea
    Oct 31, 2021 at 14:29
  • 2
    @GordonDavisson: That's actually how directories work in real-life, too, and is in fact, why Unix calls them directories and not "folders" as some other OSs do. If I want to delete you from my phone's contact directory, I don't have to murder you, after all. If I want to remove a file from a folder, I have to have physical access to both the folder and the file inside it. If I want to remove a file from a directory, all I need is access to the directory, and then I can erase or strike through the entry. Oct 31, 2021 at 15:15
  • 2
    @chenzero The problem is that permissions are defined in terms of operations at the filesystem level, not what effect those operations have. Replacing vs changing a file have similar results, but they're very different in terms of what filesystem operations are involved, so permissions apply differently between them. IMO the problem is that unix permissions were designed by a filesystem expert, not a security expert, so they make sense in terms of filesystem operations but not in terms of defining a sane security policy. Oct 31, 2021 at 17:13
  • 3
    @raj vim can actually save either way -- it normally rewrites the existing file, but if it can't it switches to delete-and-replace mode. Many other programs do this to get more-nearly-atomic saves: they save under a temp name, then delete the original and rename the temp into its place; this avoids leaving a corrupted file if anything goes wrong while writing out the new version. Oct 31, 2021 at 18:02
1

A directory is a list of files and subdirectories (more precisely, for each entry: a filename or subdirectory name, owning user, owning group, permission bits, extended permissions, a pointer to the location on disk of the file/subdirectory, and additional esoteric metadata). A directory has an owner and a group. The permissions of the directory control which users and read, write, and cd into that directory. If you wish to create a file in a directory, you must have permission to write to the directory. If you wish to remove a file from a directory, you must have permission to write to the directory. If you wish to rename a file, you must have permission to write to the directory. If you wish to alter the permissions of a file, you must have permission to write to the directory. All of these are modifications of the directory, so use the directory's permissions. (There are exceptions related to extended permissions, which I set aside here.)

In the following, I will keep writing "the directory entry you use to access it" because there may be multiple directory entries, thus potentially different names, for a file in the filesystem. In fact, several entries in a single directory (necessarily having different names) may point to the same file on disk, and the various entries can have different owning user, owning group, and permissions.

A file entry in a directory has owning user, owning group, and permissions. If you wish to read the contents of a file, the directory entry you use to access it must permit read access to you. If you wish to write the contents of a file, the directory entry you use to access it must permit write access to you. If you wish to execute the contents of a file, the directory entry you use to access it must permit execute access to you.

So let's work through your example.

  • The current working directory is ~/tmp/, so the current user is the owning user, owning group, and has read+write+execute permissions to the directory.
  • sudo touch c.txt This creates a file with owning user root having read+write permissions, group root having write permissions, and write permissions to other users. (4 = read, 2 = write, 1 = execute; 6 = 4+2 = read+write)
  • rm c.txt has the warning/prompt "rm: remove write-protected regular empty file 'c.txt'?" This warning means: the current user has write permissions to the current directory, so can delete this file, but the current user only has read permissions to the contents of this file, which suggests that the current user wishes to preserve this file against changes. These two intentions are incompatible, so further guidance is requested.
  • Select y and c.txt is removed. Yes. You have permissions to delete the entry from the directory, so when you respond y, the entry is deleted from the directory. At no time are the contents of the file written or executed (which is what the file entry permissions would disallow).

Your second scenario also works, but not for the reason you expect. vim and many, many other editors (including, as a random example, Microsoft Word), do not edit the original file. They copy the file, then edit the copy. If edits are not saved, the copy can be deleted. If the edits are saved, the original file is deleted from the directory and the copy is renamed to the original's name. So let's see what happens.

mkdir test
cd test
ls -laF

total 8
drwxrwxr-x  2 fuzzy fuzzy 4096 Oct 31 11:40 ./
drwxr-xr-x 78 fuzzy fuzzy 4096 Oct 31 11:40 ../

We see that my user, fuzzy, and my group, fuzzy own the current directory, ., and 775 permissions are set (user fuzzy: rwx, group fuzzy: rwx, other: rx).

sudo vim d.txt
[supply password]
[vim session starts]
[insert mode]Hi.

Now let's move to another shell and see what's going on in the directory.

[another shell, not sudo...]
cd test
ls -laF

total 20
drwxrwxr-x  2 fuzzy fuzzy  4096 Oct 31 11:44 ./
drwxr-xr-x 78 fuzzy fuzzy  4096 Oct 31 11:44 ../
-rw-------  1 root  root  12288 Oct 31 11:44 .d.txt.swp

We see that the sudo vim has created a temporary file named .d.txt.swp with owners root.root and mode 600. Now go back and save the file in the sudo vim session and check again.

ls -laF

total 12
drwxrwxr-x  2 fuzzy fuzzy 4096 Oct 31 11:48 ./
drwxr-xr-x 78 fuzzy fuzzy 4096 Oct 31 11:48 ../
-rw-r--r--  1 root  root     4 Oct 31 11:48 d.txt

We see the temporary file's directory entry has been modified to have a new name and new permissions. The current user here is fuzzy, who only has read permissions to d.txt, but that's all fuzzy needs to open the file in an editor.

[first session, notice not sudo...]
vim d.txt
[go to end of first line]
[append.  warned: "W10: Warning: Changing a readonly file"]
[type a single space after "Hi."]

As soon as we appended the after the Hi. the vim temporary file appeared in the directory.

[second session]
ls -laF

total 16
drwxrwxr-x  2 fuzzy fuzzy 4096 Oct 31 11:53 ./
drwxr-xr-x 78 fuzzy fuzzy 4096 Oct 31 11:52 ../
-rw-r--r--  1 root  root     4 Oct 31 11:48 d.txt
-rw-------  1 fuzzy fuzzy 4096 Oct 31 11:53 .d.txt.swp

This directory has rwx permissions for user fuzzy, so creating this entry is permitted. As per normal, vim keeps the permissions of temporary files very strict.

[first session]
[exit insert mode]
[Esc]:w
[obtain error: "E45: 'readonly' option is set (add ! to override)"]

This means that the original directory entry does not have write permissions for the current user, fuzzy. This normally has the semantics that the file is not to be modified, so vim can respect those semantics or override them (because the directory permissions allow fuzzy to remove the d.txt entry and rename the .d.txt.swp to d.txt). Which do you want?

[first session]
[Esc]:w!

You choose to overwrite.

Let's see what's going on in the directory now.

[second session]
ls -laF

total 28
drwxrwxr-x  2 fuzzy fuzzy  4096 Oct 31 12:01 ./
drwxr-xr-x 78 fuzzy fuzzy  4096 Oct 31 12:00 ../
-rw-r--r--  1 fuzzy fuzzy     5 Oct 31 12:01 d.txt
-rw-r--r--  1 fuzzy fuzzy     4 Oct 31 11:48 d.txt~
-rw-------  1 fuzzy fuzzy 12288 Oct 31 12:01 .d.txt.swp

It's possible you don't see the d.txt~ file. I may have turned on a vim option to always save a backup copy of the original file. I don't recall what the default behaviour of vim is with respect to this option.

Now there are three files:

  • d.txt -- the modified version we just saved. It contains "Hi. ". Subsequent saves will replace this file.
  • d.txt~-- a backup copy of the original file. It contains "Hi." This directory entry was created by a process running as fuzzy, so has fuzzy's default ownerships and permissions.
  • .d.txt.swp -- the current working file. Subsequent edits will be periodically auto-saved to this file.

Now let's end that vim session.

[first session]
[Esc]:q

and again see what's going on in the filesystem.

[second session]
ls -laF

total 16
drwxrwxr-x  2 fuzzy fuzzy 4096 Oct 31 12:05 ./
drwxr-xr-x 78 fuzzy fuzzy 4096 Oct 31 12:05 ../
-rw-r--r--  1 fuzzy fuzzy    5 Oct 31 12:01 d.txt
-rw-r--r--  1 fuzzy fuzzy    4 Oct 31 11:48 d.txt~

Both files were created by unprivileged fuzzy, so have fuzzy's default ownerships and permissions. fuzzy was able to create and delete these directory entries because fuzzy has write permissions to the current directory, ..

1
  • Thanks for the great detailed explanations! I see the point, vim works because it deletes file first and rename the backup, not directly modify the original file. Thank you all and have a nice day!
    – chenzero
    Oct 31, 2021 at 18:03

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .