
Я пытаюсь понять, почему у sudo нет здесь разрешения.
touch fred.txt
/tmp$ ls -la fred.txt
-rw-rw-r-- 1 me me 0 Dec 12 15:40 fred.txt
/tmp$ sudo -i
~# cd /tmp
/tmp# echo hi >> fred.txt
-bash: fred.txt: Permission denied
/tmp# chmod 666 fred.txt
/tmp# ls -la fred.txt
-rw-rw-rw- 1 me me 0 Dec 12 15:40 fred.txt
/tmp# echo hi >> fred.txt
-bash: fred.txt: Permission denied
id
uid=0(root) gid=0(root) groups=0(root)
Насколько я понимаю, разрешение 666 должно давать владельцу, группе и другим разрешение на чтение/запись файла. Surly sudo, который действует как root, как видно из команды id, имеет доступ к файлу под разрешением «другие».
Что я здесь не понимаю?
решение1
Это как-то связано сэто совершитьв ядре Linux. Часто /tmp
является «доступным для записи всем» («world» здесь означает «другие») и «прилипающим»:
$ stat /tmp/
...
Access: (1777/drwxrwxrwt) Uid: ( 0/ root) Gid: ( 0/ root)
...
chmod(2)
:
...
S_ISVTX (01000) sticky bit (restricted deletion flag, as described in unlink(2))
...
S_IWOTH (00002) write by others
...
Как упоминалось в сообщении о коммите, это не запрещает вам записывать данные в затронутый файл, но запрещает открывать такой файл с помощью O_CREAT
, что является флагом дляopen()
который обычно устанавливается для запуска создания файла, если цель еще не существует. Таким образом, вы все равно можете записать в затронутый файл с неустановленным флагом (что можно сделать с помощью dd
):
# ls -l /tmp/meh
-rwxrwxrwx 1 tom tom 0 Dec 12 17:33 /tmp/meh
# id
uid=0(root) gid=0(root) groups=0(root)
# echo test | dd of=/tmp/meh oflag=append conv=notrunc
dd: failed to open '/tmp/meh': Permission denied
# echo test | dd of=/tmp/meh oflag=append conv=notrunc,nocreat
0+1 records in
0+1 records out
5 bytes copied, 9.4981e-05 s, 52.6 kB/s
#
Обратите внимание, что речь идет исключительно о том, установлен ли флаг, а не о том, нужно ли создавать файл, поскольку в рассматриваемом случае файл всегда существует.
Также обратите внимание, что, как указано в сообщении о коммите, файл не может быть открыт O_CREAT
безтолькопотому что он не принадлежал пользователю, который пытался его открыть ( root
), но также потому что его владелец ( tom
) отличается от владельца ( root
) каталога ( /tmp
). Если бы /tmp/
он принадлежал tom
как /tmp/meh
был, root
был быспособныйчтобы открыть его с помощью O_CREAT
.
Также смэто совершитьв systemd, который включает «защиту» на дистрибутивах, которые ее приняли:
# sysctl fs.protected_regular
fs.protected_regular = 1
Обратите внимание, что соответствующие sysctlsтакже может быть установлено 2
(или 0
).