Чому джерелу Баша не потрібен біт виконання?


57

За допомогою Bash sourceможна виконати сценарій без набору бітів виконання. Це задокументоване та очікуване поведінка, але чи не проти використання біта виконання?

Я знаю, sourceце не створює підзаголовок.


2
Той факт, що chmodможе дозволити вам встановлювати дозволи (включаючи `x) з восьмеричним числом, дає певну підказку до того, з якої епохи він походить. Я не був би здивований, якби він розпочався як швидкий і брудний "це показник бінарного файлу, який ви можете виконати", від днів до того, як вона була винайдена, але я не маю доказів тому
зафіксовано

9
Потім знову, коли SUID вступає в гру, різні рівні захисту для різних категорій користувачів стають більш важливими. Ідіть і читайте мою програму SUID, якщо хочете. Але якщо ви виконаєте його просто прочитавши, повноваження SUID не поєднуються з ним
зафіксовано

@infixed Завантажувач програм Linux навіть не дивиться на шебанг, якщо не встановлено біт виконання. (Щоб трохи зубнути власний ріг: дивіться тут .)
Кайл Странд

Ви також можете мати + xr, але це трохи дивно, тому що зазвичай можна прочитати двійковий код, ввівши код у запущений процес
Niklas B.

@KyleStrand: "якщо ти виконаєш це за допомогою простого читання, сили SUID не поєднуються з ним". Я передбачав щось по лініїcp /sbin/suidexecutable /tmp/mycopy; /tmp/mycopy
інфікований

Відповіді:


36

Баш - перекладач; він приймає вклад і робить все, що хоче. Тут не потрібно прислухатися до виконуваного біта. Фактично, Bash є портативним і може працювати в операційних системах і файлових системах, які не мають жодної концепції виконуваного біта.

Що стосується виконавчого біта - це ядро ​​операційної системи. execНаприклад, коли ядро ​​Linux виконує , наприклад, перевіряє, чи не встановлена ​​файлова система з noexecопцією, вона перевіряє виконуваний біт програмного файлу та виконує будь-які вимоги, що пред'являються модулями безпеки (наприклад, SELinux або AppArmor).

Зауважте, що виконуваний біт є досить дискреційним видом контролю. Наприклад, у системі Linux x86-64, ви можете обійти верифікацію ядра виконуваного біта шляхом явного виклику /lib/x86_64-linux-gnu/ld-linux-x86-64.so.2в якості інтерпретатора :

cp /bin/ls /tmp/
chmod -x /tmp/ls
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /tmp/ls

Це дещо аналогічно пошуку вихідного коду Bash у Bash, за винятком того, що ld.soце інтерпретатор, а код, який він виконує, є машинним кодом у форматі ELF.


3
Використання завантажувача в якості "інтерпретатора" "байт-коду", який просто виявляється справжнім двійковим файлом, що виконується ..... приголомшливо. Дякую тобі за це.
Кайл Странд

@KyleStrand може бути декілька рівнів непрямості (різниця між збереженою програмою та завантаженим процесом і способом відображення пам'яті, різними наглядачами, віртуальними машинами тощо), але в принципі машинний код може виконуватися безпосередньо процесором (немає мікрокоду, і т. д.), тому машинний код не інтерпретується: апаратне забезпечення розуміє його так, як є - це рідна мова - жодних перекладачів не потрібно.
jfs

2
@JFSebastian Так, ми знаємо, що це нативний код, отже, "перекладач" є в лапках. Завдання полягає в ld.soтому, щоб робити динамічні зв'язки.
200_успіх

@JFSebastian Що сказав 200_success. Крім того, це те, що я мав на увазі під "реальним виконуваним двійковим кодом", і я також ставлю "байт-код" у лапки (оскільки "байт-код" AFAIK, як правило, не використовується для позначення фактично скомпільованого власного двійкового коду). Також приємне ім’я користувача.
Кайл Странд

@JFSebastian Я вважаю, що сучасні процесори, схожі на x86, насправді є RISC внутрішньо, при цьому стара інструкція CISC встановлює в основному виконання мікрокоду відповідних інструкцій RISC, де одна інструкція CISC може спричинити виконання багатьох інструкцій RISC. Тож у певному сенсі називати те, що процесор робить з машинним кодом RISC "інтерпретацією", якщо не зовсім коректно з технічної точки зору, то принаймні валідна ментальна модель. AES-NI - це, мабуть, один із найбільш екстремальних прикладів: одна інструкція CISC на раунд AES!
CVn

57

sourceабо еквівалентна, але стандартна крапка. не виконує скрипт, а читає команди з файлу сценарію, а потім виконує їх, рядок за рядком, у поточному середовищі оболонки.

Там немає нічого проти використання виконання біта, тому що оболонка тільки потрібно прочитати дозвіл на читання вмісту файлу.

Біт виконання потрібен лише під час запуску сценарію. Тут оболонка буде fork()переробляти новий процес, використовуючи execve()функцію для створення нового зображення процесу із сценарію, який повинен бути звичайним виконуваним файлом.


5
@alexis: Я не впевнений, що насправді дотримуюся. Якщо це зробити bash < script, ви отримуєте по суті такий же результат, як і source script. Який захист забезпечує перевірка бітів виконання?
Помітний укладач

27
@alexis, це не робота перекладача, щоб перевірити дозволи скриптів, які він інтерпретує. Нічого цього не робить - не Python, не Ruby, не віртуальна машина Java, не інші випадкові оболонки. Біт виконання контролює, чи execvможна використовувати сімейство системних викликів OS * з виконуваним файлом, а не чи буде запускати його інтерпретатор. Навіщо плутати людей (і порушувати здатність оцінювати код, потік з нефайлових джерел), порушуючи умовні умови?
Чарльз Даффі

14
@alexis, ... крім того, є цінне значення, що має бібліотеку оболонок, яку не можна виконати: в ній написано: "Я бібліотека, а не команда - джерело, не виконайте мене". Інакше вам потрібно буде написати код для виявлення та негайного використання коду, призначеного лише для отримання, але, не маючи дозволу + x, ви можете переконатися, що користувачі не зможуть (не) зловживають бібліотекою таким чином.
Чарльз Даффі

6
@alexis "це було рішення авторів" Тільки в тому сенсі, що кожен інший можливий біт коду, який не був включений, був рішенням. Оболонка відкриває файл для читання, щоб прочитати команди з нього. Я б не очікував, що він перевірить дозвіл на читання, він просто намагається відкрити файл і не може, якщо не може. Так само він не перевіряє наявність дозволу на запис чи виконання, оскільки ці перевірки не мають значення для читання файлу.
Ренді Оррісон

2
@alexis Це використовується на практиці, хоча, наприклад, з virtuolenv python, сценарій для його активації призначений для отримання, а не виконання, і, таким чином bin/activate, не має виконуваного біта. Сценарії можуть бути повністю бібліотеками або іншими подібними предметами. Я думаю, що .sh також може бути сигналом, але добре мати пістолети - це добре, що ./bin/activateзамість нього не можна бігати. bin/activate
daboross

20

Виконаний біт (на відміну від решти) для нечистових та нечутливих файлів не є надто механізмом захисту. Все, що ви можете прочитати, ви можете запустити побічно, і Linux дозволить вам побічно читати все, що ви можете запустити, але не безпосередньо прочитати (цього має бути достатньо, щоб пробити дірку в концепції не встановленого (g) uid x-біта, який є a захід безпеки).

Це більше зручності: дозвольте системі запустити його безпосередньо для мене, якщо біт встановлений, інакше мені потрібно це зробити побічно ( bash the_script;або деякий злом, щоб отримати зображення пам'яті виконуваного дозволу без читання ).

Ви можете встановити це для зручності, якщо ви маєте намір як вводити, так і виконувати ваш ресурс.

Мабуть, однак, багато реалізаторів спільної бібліотеки поділяють ваше мислення, і, отже, багато систем вимагають, щоб спільні бібліотеки, які по суті є нативним еквівалентом оборотних ресурсів оболонок, були позначені виконуваними, щоб бути корисними. Див. Чому спільні бібліотеки виконують? .


3
@ Motte001 Вони можуть виконати ці вкладення, якщо дуже хочуть. Це зручність.
PSkocik

2
Виконаний біт не для безпеки: Якщо я володію файлом, я вільний до chmodнього і роблю його виконуваним. Це для сортування даних за програмами, тому питання ОП є розумним.
alexis

1
@ Motte001 Це більше захисна функція браузера / поштового додатка GUI - вона може легко вирішити, що двічі клацнути будь-який файл, ім'я якого закінчується ".sh", виконуватись у терміналі (у стилі Windows), або навпаки, що подвійний- натискання будь-якого файлу в каталозі "завантажених вкладених файлів" викликає вбудований додаток для попереднього перегляду. xБіт просто додаткове місце він може читати / писати натяк на те , що робити.
IMSoP

3
Однією з причин, що нам потрібен виконуваний біт, є запуск встановлених програм, особливо тих, що належать root. Хоча ви, звичайно, можете їх виконати самостійно, вам потрібна ОС, щоб запустити їх, щоб вони мали необхідні дозволи. В деяких інших випадках це дійсно просто зручність.
Уелід Хан

2
"Linux дозволить вам прочитати все, що можна запустити через / proc" - Ну, мій запас ядра Debian не: /tmp$ cp /bin/cat ./cat ; chmod a-rw ./cat ; ./cat & cp /proc/$!/exe /tmp/cat2->cp: cannot stat ‘/proc/16260/exe’: Permission denied
ilkkachu

9

Це гарне запитання! Unix використовує виконуваний біт для розмежування програм і даних. ОС не вимагає біт виконання, оскільки джерело джерела не передається в ОС для виконання як новий процес. Але оболонка розглядає джерело джерела як програму і шукатиме $PATHфайл, який ви хочете отримати. Отже, сама оболонка могла вимагати виконання дозволу на джерела файлів; але це не сталося

Питання, мабуть, виникло давно. Дизайн оболонки Борна став результатом "тривалої послідовності модифікацій, діалогу, обговорення" серед мешканців Bell Labs, і багато дизайнерських рішень протягом багатьох років обговорювали С. Р. Борн та інші. На жаль, мій швидкий погляд не знайшов дискусії щодо функції джерела (на мою захист важко це гугл). Я знайшов, що "". Команда не з'являється в цьому ранньому вступі до оболонки самим Борном, але вона присутня у більш зрілій версії версії 7 .

Відсутня влада, ось моя власна інтерпретація:

  1. .Команди, він же source, в текстології включенні ефекту (як #includeв препроцесорів C) в вихідному код виконуючого сценарію або інтерактивної сесії. Як такий, включений файл, мабуть, не "виконується".

  2. Філософія Unix завжди полягала в тому, щоб дати програмістам достатньо мотузки, щоб повіситися. Занадто велика кількість рук і довільних обмежень просто заважають. Лише зовсім недавно деякі розповсюдження rm -r /відмовляються робити те, що ви просите. (Ця команда говорить , rmщоб видалити всі на своєму комп'ютері. Не намагайтеся як корінь! Або ще краще, не зовсім.) Так що , можливо , Борн в співавт. щойно вирішив, що, намагаючись створити файл, ти вважатимеш, що ти робиш. Це також дозволяє уникнути зайвої роботи, і цикли мали багато часу.


Але однозначно не слід робити те, що сказав @cat.
TOOGAM

Я здивований, що він не був позначений і видалений @TOOGAM, але я поставив / і!
кіт

Там я не знаю, що написав @cat, але відповідь я ще більше підтвердив. (Але давай, це було досить зрозуміло вже з контексту.)
alexis

4

Що стосується ОС, то файл, що містить скрипт оболонки, - це лише дані. Якщо ви передаєте ім'я такого файлу даних в sourceкоманду або передаєте його в командному рядку для виклику оболонки bash, все, що бачить ОС, - це рядок, який збігається з іменем файлу, що містить дані.

Як би біт виконання був би взагалі доречним у такому випадку?


3

Відмінність важлива, оскільки у вас може бути файл команд оболонки, який не є корисним як виконуваний файл, а корисний лише під час пошуку. Для цього файлу ви можете вимкнути біт виконання, і тоді він ніколи не буде доступний, якщо явно не буде вказано команду-джерело. Причиною такої речі є побічні ефекти на оболонці, з якої вона запущена. Для конкретного прикладу, у мене є сценарій під назвою fix_path, який переглядає та змінює шлях.


1

На всякий випадок, коли когось цікавлять подальші дослідження та / або уточнення: У майже сумісній з POSIX оболонці, впровадженій деякий час тому, внутрішня робота функцій 'exec_program ()' та 'buildin_source ()' є дуже зразковими. У цих функціях ви точно бачите, в чому різниця між ними:

https://github.com/rsenn/shish/blob/master/src/builtin/builtin_source.c

https://github.com/rsenn/shish/blob/master/src/exec/exec_program.c

в основному джерело пошуку може розглядатися як оболонка тимчасово перенаправляє свій внутрішній дескриптор файлу, звідки вона аналізує скрипт оболонки (термінал в інтерактивному режимі). так що це дуже схоже на переадресації , як <input_file.txtі >>append_to_something.listі їх просто потрібно відкривати і закривати файли.

тому виконання виконується execve()системним викликом, для якого біт виконання є обов'язковим.

Пригадую, я бачив деякі системи, які дозволяють виконувати бінарні файли ELF / a.out, але за допомогою виконання "/lib/ld-dynamic-linker.so" та з бінарною програмою (без файлу exec) в якості першого аргументу. Я вважаю, що це було на деяких машинах DEC Alpha або VAX (Можливо, це був SCO Unix?)


-2

Інша точка зору:

Заданий скрипт в основному складається з вбудованих оболонок та програмних дзвінків. Вбудовані оболонки (з- sourceпоміж них) є частинами оболонки, і оболонка повинна бути виконана в першу чергу. Кожна названа програма (що це за ELF, інший скрипт із шебангом, що завгодно) має мати встановлений біт виконання, інакше вона не запуститься.

Тож це не проти використання біта виконання, оскільки нічого без біта виконання не буде працювати. Перевірка не відбувається для скрипта, який розміщено в цілому; воно виконується для кожної частини окремо, але це так.


Оболонки оболонки не походять із сценарію оболонки. Зазвичай вони є частиною виконуваної оболонки. У ksh93, zsh та декількох інших оболонках вони можуть бути розширеннями оболонок.
fpmurphy

@ fpmurphy1 Чи не це моє речення "вбудована оболонка (...) - це частини оболонки"?
Каміль Маціоровський
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.