chmod кто-то убрал x бит:-rw-r--r-- 1 root root 63864 Jun 14 11:00 /bin/chmod
Пытаешься вернуть как было:
~$ chmod +x /bin/chmod
-bash: /bin/chmod: Permission denied
🥲 А
chmod больше не запускается — ведь у него самого теперь нет права на выполнение.И как починить
chmod, если chmod сломан? 🤔На самом деле есть довольно красивый способ, но сначала разберёмся, как Linux вообще запускает программы.
Большинство привычных программ в Linux — динамически слинкованные. Это значит, что они используют внешние библиотеки (
.so), которые не лежат внутри самого бинарника.Проще говоря, динамическая линковка — это когда программа говорит: «мне нужна вот эта книга, она лежит в общей библиотеке». А при статической линковке всё необходимое уже находится внутри самого бинарника.
Поэтому одна и та же
libc, например, может использоваться сразу множеством программ, а не храниться отдельной копией внутри каждой.Когда вы запускаете динамически слинкованную программу, ядро Linux запускает динамический загрузчик для неё.
Он загружает необходимые библиотеки в память, связывает их с программой и только после этого передаёт управление самой программе.
Посмотреть, какой загрузчик нужен бинарнику, можно через
ldd:~$ ldd /bin/chmod
linux-vdso.so.1 (0x00007fff16ff5000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f776111d000)
/lib64/ld-linux-x86-64.so.2 (0x00007f7761327000)
Вот он:
/lib64/ld-linux-x86-64.so.2. И самое интересное — его можно вызвать вручную.А значит, можно попросить загрузчик запустить наш
chmod:/lib64/ld-linux-x86-64.so.2 /bin/chmod +x /bin/chmod
Готово. Мы только что запустили
chmod, у которого не было x бита, и с его помощью вернули этот самый x бит.Проверяем:
~$ ls -l $(which chmod)
-rwxr-xr-x 1 root root 63864 Jun 14 11:00 /bin/chmod
Но почему это вообще сработало?
Ядро проверяет
x бит у того файла, который запускают. А запустили мы ld-linux — у него с правами всё в порядке.Дальше сам
ld-linux открывает /bin/chmod и загружает его код в память. Поэтому x у самого chmod здесь уже не требуется.И это работает не только с
chmod — если случайно убрать x у другого динамически слинкованного бинарника, его тоже можно запустить через ld-linux.Кстати, восстановить права можно и без этого трюка.
Например, если в системе есть Python:
python3 -c 'import os; os.chmod("/bin/chmod", 0o755)'Или командой
install — она умеет выставлять права при копировании:install -m 755 /bin/chmod ./chmod
mv ./chmod /bin/chmod
Но мы сделали чуть интереснее: починили
chmod с помощью самого chmod, который не был исполняемым. 😎👨💻 Код в Прод