[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
bug#27200: sed happily modifies read-only files.
From: |
Assaf Gordon |
Subject: |
bug#27200: sed happily modifies read-only files. |
Date: |
Wed, 7 Jun 2017 17:39:45 +0000 |
User-agent: |
Mutt/1.5.23 (2014-03-12) |
Hello,
On Wed, Jun 07, 2017 at 04:37:49PM +0200, Péter wrote:
(We are discussing about these bits:
https://www.gnu.org/software/coreutils/manual/html_node/Mode-Structure.html)
Yes, exactly those bits.
However - there is a difference between those bits on a file,
and these bits on the directory containing that file.
That difference is the source of the confusion.
$ ls -la
-r--r--r-- 1 pp pp 10 jún 7 15:02 foo
Are you stating that in this case the file is (should be treated)
writable?
The file is not writable (you can not change the content of the existing
file). But it can be replaced with another file,
which is exactly what sed (and VI) are doing - that is the way
unix file/directory permissions have been for decades.
Sorry, I can not believe that.
There's no need to believe, just to try it ;)
Some *facts*:
$ vi foo
When trying to insert something: "W10: Warning: Changing a readonly file"
When trying to save the file: "[RED] E45: 'readonly' option is set (add ! to
override)"
Exactly! "add ! to override" means VI can replace that file.
When you use "w!" in VI,
VI *can not* replace the content of the existing file (the kernel
prevents it). But it can create a new temporary file,
then replace the source file with it.
$ nano foo
When trying to save (after some insertion): "[ Error writing foo: Permission denied
]"
$ echo FFFFF >foo
bash: foo: Permission denied
$ python3 -c 'with open("foo", "w") as f: f.write("FFFFFFFF\n")'
Traceback (most recent call last):
File "<string>", line 1, in <module>
PermissionError: [Errno 13] Permission denied: 'foo'
In all these examples, you are attempting to modify the file directly.
They are prevented by the kernel.
This is not what sed (and VI) are doing - they are replacing the
file with another - which is perfectly permissable because
the directory is writable.
I know that this protection is not hyper-strong. Can be
"circumvented". If a (bad) guy wants to modify the foo file, (s)he can
accomplish it (with the trick of using unlink instead of mv ...):
There is no such thing as strong/hyper-strong/not-so-string protection.
Either something is protected, or it is not.
The *content* of the existing file can not be modified
(i.e. the kernel will reject write attempts, and no user-program
can modify it).
But because the directory containing that file is not write-protected,
a user can rename the file, delete the file, and replace the file
with another file (which gives the impression that the file was
modified).
(I remain unconvinced, unless will state otherwise.)
I'll try to demonstrate what happens in two ways.
First, using inode:
A 'file' in unix is just a link to an inode (which represents
the file's content and metadata on the file system).
Multiple filenames can point to the same content on the file system,
thus having the same inode (these are 'hard-links').
Same inode means the same content, different inode means different
"files".
More info here: https://en.wikipedia.org/wiki/Inode
Create a file:
$ echo hello > 1.txt
Its inode number is 8051885:
$ ls -li
total 4
8051885 -rw-rw-r-- 1 gordon gordon 6 Jun 7 12:15 1.txt
Modify the file's content:
$ echo world >> 1.txt
It is still the same 'file' on the file system (same inode number):
$ ls -li
total 4
8051885 -rw-rw-r-- 1 gordon gordon 12 Jun 7 12:15 1.txt
Remove write-permissions from the file's content,
this prevents writing (as expected):
$ chmod a-w 1.txt
$ echo foobar >> 1.txt
bash: 1.txt: Permission denied
If you now open the file in 'vi',
modify it, and do "w!" and "q" (to force-override the file),
you'll see it is a *different* file (different inode value):
$ ls -li
total 4
8052811 -r--r--r-- 1 gordon gordon 19 Jun 7 12:18 1.txt
VI *replaced* the file, it did not (and could not) modify
the file directly.
Another way: since you've mentioned python,
observe the difference between these two scripts:
$ echo hello > 1.txt
$ chmod a-w 1.txt
$ ls -li 1.txt
8051885 -r--r--r-- 1 gordon gordon 6 Jun 7 13:21 1.txt
This script tries to modify the file's content directly,
and will fail with "permission denied":
$ cat 1.py
f=open("1.txt","w")
f.write("world")
$ python 1.py
Traceback (most recent call last):
File "1.py", line 1, in <module>
f=open("1.txt","w")
IOError: [Errno 13] Permission denied: '1.txt'
But this script replaces the file with a new file,
and that is working just fine (just like 'sed' and 'vim'):
$ cat 2.py
import os
inf=open("1.txt","r")
outf=open("1.tmp","w")
for i in inf:
outf.write(i)
outf.write("world\n")
inf.close()
outf.close()
os.rename("1.tmp","1.txt")
$ python 2.py
[[ no error ]]
$ cat 1.txt
hello
world
When programs like mv/rm/vi ask you about the file being
"write protected", they do the equivalent of this python script:
import os, sys, stat
if not os.access("1.txt",os.W_OK):
a = input("The file is write-protected, replace it (y/n)? ")
if a != "y":
sys.exit("aborting")
inf=open("1.txt","r")
outf=open("1.tmp","w")
for i in inf:
outf.write(i)
outf.write("hello\n")
inf.close()
outf.close()
os.rename("1.tmp","1.txt")
That is, they check the file permission mode,
and if the write-bits are off, *as a courtesy*, they
ask if you are sure about replacing it.
But there is *nothing* technical (in the OS/kernel) that
protects the file from being replaced.
-----
I hope that the above at least convinces you that
from a pure technical POV, a file without write-permission
bits can be replaced (but not modified) - thus this is
not a bug in sed.
You can still argue that 'sed' should be friendlier to
(and more protective of) the user,
and warn about such cases (and optionally add a "--force" parameter).
That is certainly a valid request,
however, due to backwards compatiblity, this behaviour is not likely
to change without a lot more discussion and preparations.
Hope this helps,
regards,
- assaf
- bug#27200: sed happily modifies read-only files., Péter, 2017/06/02
- bug#27200: sed happily modifies read-only files., Assaf Gordon, 2017/06/02
- bug#27200: sed happily modifies read-only files., Péter, 2017/06/06
- bug#27200: sed happily modifies read-only files., Bob Proulx, 2017/06/06
- bug#27200: sed happily modifies read-only files., Péter, 2017/06/07
- bug#27200: sed happily modifies read-only files.,
Assaf Gordon <=
- bug#27200: sed happily modifies read-only files., Davide Brini, 2017/06/07
- bug#27200: sed happily modifies read-only files., Péter, 2017/06/08
- bug#27200: sed happily modifies read-only files., Bob Proulx, 2017/06/11