strange file security on Ubuntu 20.04

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 ?


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


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, ..