Чи існує файл, який завжди існує, і "звичайний" користувач не може його встановити?


14

Мені це потрібно для одиничного тесту. Існує функція, яка робить lstat на шляху файлу, переданого як його параметр. Я повинен запустити шлях коду там, де lstatне вдається (оскільки покриття коду має досягати 90%)

Тест може працювати лише під одним користувачем, тому мені було цікаво, чи є в Ubuntu файл, який існує завжди, але звичайні користувачі не мають доступу до його читання або до його папки. (Так lstatби не вдалося на ньому, якщо не виконано як root.)

Неіснуючий файл не є рішенням, оскільки для цього є окремий шлях коду, який я вже запускаю.

EDIT: Відсутність лише доступу для читання до файлу недостатньо. З цим lstatвсе ще можна виконати. Мені вдалося його запустити (на моїй локальній машині, де я маю доступ до кореня), створивши папку в / root та файл у ній. І встановлення дозволу 700 на папку. Тож я шукаю файл, який знаходиться у папці, доступній лише root.


6
ІМХО/etc/shadow
Ромео Нінов,

3
Ви не можете припустити існування будь-якого файлу, оскільки ваша програма може працювати в chroot або окремому просторі імен. Якщо припустити, що / proc встановлено нормально, а init - це нічого особливого, тоді /proc/1/fd/0слід робити.
mosvy

1
@mosvy Спасибі, що працює на моїй локальній машині. Хм, тоді я спробую це також у басейні QA та Staging.
Кошеня кошеня,

2
Чому ви прив'язуєте свій тестовий код до певного аромату ОС, коли ви могли просто створити викидний файл та видалити власний доступ для читання до нього?
Кіліан Фот

4
Я б стверджував, що це насправді не тестовий модуль, коли він починається залежно від реальної, а не знущається, файлової системи.
Toby Speight

Відповіді:


21

У сучасних системах Linux ви повинні мати можливість використовувати /proc/1/fdinfo/0(інформацію для дескриптора файлу 1 (stdout) процесу id 1 ( initу просторі імен кореневого підпису, який має працювати як root)).

Ви можете знайти список із (як звичайний користувач):

sudo find /etc /dev /sys /proc -type f -print0 |
  perl -l -0ne 'print unless lstat'

(видаліть, -type fякщо ви не хочете обмежуватись звичайними файлами).

/var/cache/ldconfig/aux-cacheє ще одним потенційним кандидатом, якщо вам потрібно розглянути лише системи Ubuntu. Він повинен працювати в більшості систем GNU, оскільки /var/cache/ldconfigстворено для читання + запису + пошуку, коріння може виконуватись тільки за допомогою ldconfigкоманди, що постачається з libc GNU.


1
Спасибі! Якщо/proc/1/fdinfo/0 працює на Ubuntu 16.04 та 18.04, цього більш ніж достатньо.
Кошеня кошеня,

1
Використання /proc/1/fdinfo/0не обов'язково працює в контейнері (наприклад, контейнер Docker), і часто одиничні тести проводяться в таких контейнерах в CI.
Філіп Вендлер

@PhilippWendler, я вже згадував простір імен кореневих під . ОП запитує не про контейнери, а про файли, які гарантовано будуть знаходитись у макеті файлової системи системи Ubuntu. Оскільки контейнери можуть містити будь-який макет файлів і каталогів, це питання не може відповідати там.
Стефан Шазелас

12

Переглядаючи сторінку чоловіка lstat (2), ви можете отримати натхнення на випадки, які можуть призвести до її помилки, якщо не помилки ENOENT (файл не існує.)

Найбільш очевидний:

У дозволі на пошук EACCES відмовлено в одному з каталогів у префіксі шляху .

Тому вам потрібен каталог, з якого ви не можете шукати.

Так, ви можете шукати той, який вже є у вашій системі (можливо, /var/lib/privateякщо він існує?), Але ви також можете створити його самостійно, з еквівалентом:

$ mkdir myprivatedir
$ touch myprivatedir/myunreachablefile
$ chmod 0 myprivatedir
$ ls -l myprivatedir/myunreachablefile

Операція lstat (2) завершиться невдачею з тут EACCES. (Видалення всіх дозволів із каталогу гарантує це. Можливо, вам навіть цього не потрібно, і chmod -xвидалення дозволів на виконання буде достатньо, оскільки для доступу до файлів під ним потрібні дозволи на виконання каталогу.)

Є ще один креативний спосіб збити lstat (2) з ладу, переглянувши його довідкову сторінку:

ENOTDIR - компонент префікса шляху шляху не є каталогом.

Отже, спроба отримати доступ до такого файлу, як /etc/passwd/nonexistentслід викликати цю помилку, яка знову-таки відрізняється від ENOENT ("Немає такого файлу чи каталогу") і може відповідати вашим потребам.

Ще один:

Шлях ENAMETOOLONG занадто довгий.

Але для цього вам може знадобитися дійсно довге ім’я (я вважаю, 4 096 байт є типовим обмеженням, але ваша система / файлова система може мати довший.)

Нарешті, це важко сказати , є чи який - небудь з них буде на самому справі корисно для вас. Ви кажете, що хочете чогось, що не викликає сценарій "файл не існує". Хоча зазвичай це означає помилку ENOENT, на практиці багато перевірок вищого рівня просто інтерпретують будь-які помилки lstat (2) як "не існує". Наприклад, test -eабо еквівалент [ -e ...]з оболонки може просто інтерпретувати все вищезазначене як "не існує", тим більше, що він не має хорошого способу повернути інше повідомлення про помилку, а не повернення помилки означало б, що файл існує, що, безумовно, не так.


@StephaneChazelas Чудова точка! Оновлено.
filbranden

6

Ти можеш find самі.

Використання /etc- каталог файлів конфігурації як відправна точка:

sudo find /etc -type f -perm 0400 -user root

У моїй системі це нічого не повертає.

Ви можете бути менш обмежувальним і дозволити групі root(лише користувач rootповинен бути членом групи root), і слідкуйте за дозволом 440:

sudo find /etc -perm 0440 -user root -group root

У моїй системі це повертається:

/etc/sudoers.d/README
/etc/sudoers

Редагувати:

Виходячи з редагування, ви шукаєте каталог, який не має достатнього дозволу для користувача, що викликає, щоб запобігти переліку списку каталогів:

sudo find / -perm o-rwx -type d -user root -group root 

тут я шукаю каталоги ( -type d), у яких відсутні біти пермі для читання-запису-виконання для інших ( o-rwx) і належатьroot:root .

З технічної точки зору, просто відсутність xбіта Execute ( ) заважатиме переліку каталогу (lstat(2) ) в каталозі.

У висновку, який я знайшов /run/systemd/inaccessible/у своїй системі на основі Systemd init.

Що стосується файлів /proc, /sys, /dev:

  • Ці файлові системи є віртуальними FS, тобто вони знаходяться в пам'яті, а не на диску

  • Якщо ви плануєте покластися /proc, використовуйте /proc/1/тобто покладайтеся на щось під PID 1, а не на пізніші PID, щоб мати надійність / послідовність, оскільки пізні PID (процеси) не гарантовано існують.


Дякую, я думаю, що моє питання неправильне. Я все ще можу lstat файли, не маючи доступу до них. Можливо, доступ до папки має бути обмежений? (Я змінив заголовок)
Crouching Kitten

Спасибі. Якщо find / -type d -perm 0400 -user rootя знайшов каталог /proc/20/map_files/, якщо я посилаюсь на складене ім’я файлу всередині цієї папки, як /proc/20/map_files/asdasd, то він завжди виходить з ладу. Чи завжди ця папка існує в Ubuntu?
Кошеня кошеня,

@CrouchingKitten, каталоги в них /proc/1/можуть бути безпечнішими, оскільки init завжди існує. Але це procне звичайна файлова система, якщо це важливо.
ilkkachu

Дякую, що я дав заяву, але прийняв іншу відповідь, тому що сказав, що це гарантовано, що це /proc/1/fdinfo/0працює на сучасному Убунтусі.
Кошеня кошеня,

-perm o-rwxяк би -perm 0, біти все починають з цього. Ось, ви хочете ! -perm -1.
Стефан Шазелас
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.