The Wanderer wrote:
> Bob Proulx wrote:
> > jimmy wrote:
> 
> >>    // --- remove (delete) a file owned by root, should not be
> >> allowed, but is allowed.  Here, it says the file is 'read-only'
> >> so it warns about it, but of course "rm -f " would work, too:
> > 
> > Why do you think it should not be allowed?  It is allowed.
> > 
> > If you don't want a user to modify the directory then change the
> > permissions of the directory.
> 
> In this case, however, the user isn't just modifying the directory; the
> user is modifying a file in the directory, by deleting that file.

Deleting a file does not modify the file contents.  Really!  :-)

Try this:

  mkdir /tmp/testdir1 /tmp/testdir2
  date -R >/tmp/testdir1/testfile1
  ln /tmp/testdir1/testfile1 /tmp/testdir2/testfile2
  md5sum /tmp/testdir1/testfile1 /tmp/testdir2/testfile2
    16dccbc3809d0e5051f1b73bf9ca5687  /tmp/testdir1/testfile1

Obviously at that time there will appear to be two files with the same
contents.  I say appear to be two files because it is one file that is
linked in two places.  But there is really only one file.

Now remove one file.  We would say "unlink" that file.

  man 2 unlink

The reason you "unlink" a file to remove it is due to the above
situation.  Removing a file simply unlinks it from a directory.

  rm /tmp/testdir1/testfile1

Okay.  It is gone.  It is removed from /tmp/testdir1.  Was the file
modified?  Let's check the file.

  md5sum /tmp/testdir2/testfile2
    16dccbc3809d0e5051f1b73bf9ca5687  /tmp/testdir2/testfile2

No modification was made to the file by removing it from the directory.

And then as others pointed out the file system is reference counted.
When the reference count to a file is reduced to zero then the space
is actually freed.  As long as the reference count is non-zero the
file is not modified by removing it (unlinking it) from a directory.

Therefore you do not need write permission to a file to remove it.
You need write permission to the directory holding it.

> >>    $ rm -v /tmp/testing/newjunk1.txt
> >> rm: remove write-protected regular file ‘/tmp/testing/newjunk1.txt’? y
> >> removed ‘/tmp/testing/newjunk1.txt’
> > 
> > Sure.  Because tst1 owns /tmp/testing.
> 
> I'm confused as to why that's enough.

I mis-wrote the above when I said it was because tst1 owns
/tmp/testing.  I had tried to be careful about talking about
permissions elsewhere.  But I had originally written my response
saying owns.  I went back and edited my response and changed most of
those to write permission but missed that one.  You caught me there on
the one I missed editing.  I should have said because tst1 has write
permission to the directory.

> Yes, moving a file affects only data stored in the directory node which
> contains the file (and the directory node where the file is being moved
> to, which may be the same one).
> 
> But deleting a file does not affect only data stored in the directory
> node which contains the file; it affects data stored in the file itself.
> (Assuming that there is only one hardlink to the file and the file is
> not presently open in any currently running process, which is often a
> reasonable assumption - and even when it is not, I don't think the
> permissions behavior of 'rm' should be different depending on the number
> of hardlinks to the file.)

Think of the case I presented above.  Let's change it slightly.

  mkdir /tmp/testdir1 /tmp/testdir2
  date -R >/tmp/testdir1/testfile1
  ln /tmp/testdir1/testfile1 /tmp/testdir2/testfile2
  md5sum /tmp/testdir1/testfile1 /tmp/testdir2/testfile2
    16dccbc3809d0e5051f1b73bf9ca5687  /tmp/testdir1/testfile1
    16dccbc3809d0e5051f1b73bf9ca5687  /tmp/testdir2/testfile2
  ls -ldog /tmp/testdir1/testfile1 /tmp/testdir2/testfile2
    -rw-rw-r-- 2 32 Jun  8 18:32 /tmp/testdir1/testfile1
    -rw-rw-r-- 2 32 Jun  8 18:32 /tmp/testdir2/testfile2
  chmod a-w /tmp/testdir2/testfile2
  ls -ldog /tmp/testdir1/testfile1 /tmp/testdir2/testfile2
    -r--r--r-- 2 32 Jun  8 18:32 /tmp/testdir1/testfile1
    -r--r--r-- 2 32 Jun  8 18:32 /tmp/testdir2/testfile2

Only one chmod needed because there really is only one file.  There
are two links.  Now how should it be handled if you remove one?

  rm -f /tmp/testdir1/testfile1

That must work.  Right?  Because we have not actually deleted the
file.  Not yet anyway.  The file is still there.  The file hasn't been
modified at all.

  ls -ldog /tmp/testdir2/testfile2
    -r--r--r-- 1 32 Jun  8 18:32 /tmp/testdir2/testfile2
  md5sum /tmp/testdir2/testfile2
    16dccbc3809d0e5051f1b73bf9ca5687  /tmp/testdir2/testfile2

So if the paradigm you are exploring existed the above would be
allowed.  But now unlinking the testfile2 case would not be allowed.

  rm -f /tmp/testdir2/testfile2

In the case you are exploring the above would fail because it was the
last reference to the file.  It is only at that time that the file
would actually be freed.  There just isn't any reasonable way to make
the behavior consistent between the case where the file has additional
links to it and the case when they don't.  And the whole purpose of
links is to be transparent.  Causing different behavior would defeat
much of the purpose of hard links.

Also the reference count applies to open file descriptors inside
programs too.  Open file descriptors are part of the reference count
too.  The file is not actually freed up until the last open file
descriptor is closed.

That would mean that there would be yet again a difference between
that last "rm -f /tmp/testdir2/testfile2" where it frees up the file
and having:

  sleep 300 < /tmp/testdir2/testfile2 &
  rm -f /tmp/testdir2/testfile2

In this case the reference count is non-zero due to the sleep 300
having an open file descriptor to the file.  In the paradigm case you
are exploring rm would not be the last unlink of the file due to the
open file descriptor being at least one more.  Only when the sleep
exits does the last reference to the file to go zero and the file
freed.  What would happen in that case?  Would the file exist forever
taking up space because it is marked read-only even though it is not
referenced from anywhere in the file system?  And so things are not
done that way.

> As such, it seems as if deleting a file *should* require write
> permission to that file.

I agree that it *feels* like a read-only file should never be possible
to be freed.  But there isn't any practical way to make that happen.

And it is worse for root.  Root always has write permission even if
the file does not have write bits.  The superuser has super user
permissions.

> Is there something I'm missing here?

Hopefully the discussion above makes sense and explains some of the
issues.

Bob

Attachment: signature.asc
Description: Digital signature

Reply via email to