Czy istnieje plik, który zawsze istnieje, a „normalny” użytkownik nie może go zapisać?

14

Potrzebuję tego do testu jednostkowego. Istnieje funkcja, która wykonuje lstat na ścieżce pliku przekazanej jako parametr. Muszę wyzwolić ścieżkę kodu w przypadku lstatniepowodzenia (ponieważ pokrycie kodu musi osiągnąć 90%)

Test można uruchomić tylko dla jednego użytkownika, dlatego zastanawiałem się, czy w Ubuntu istnieje plik, który zawsze istnieje, ale normalni użytkownicy nie mają dostępu do odczytu ani do niego. (Więc lstatnie powiedzie się, chyba że zostanie wykonany jako root.)

Nieistniejący plik nie jest rozwiązaniem, ponieważ istnieje osobna ścieżka do niego, którą już uruchamiam.

EDYCJA: Brak dostępu tylko do odczytu do pliku nie wystarczy. Dzięki temu lstatnadal można wykonać. Udało mi się go uruchomić (na moim komputerze lokalnym, na którym mam dostęp do konta root), tworząc folder w katalogu / root i plik w nim. I ustawienie uprawnień 700 na folder. Więc szukam pliku, który znajduje się w folderze, który jest dostępny tylko przez root.

Przyczajony kotek
źródło
6
IMHO/etc/shadow
Romeo Ninov
3
Nie możesz założyć istnienia żadnego pliku, ponieważ twój program może działać w chroot lub w oddzielnej przestrzeni nazw. Jeśli założenie, że / proc jest zamontowane jest w porządku, a init nie jest niczym specjalnym, to /proc/1/fd/0powinno zrobić.
mosvy
1
@mosvy Dzięki, że działa na mojej lokalnej maszynie. Hmm, więc wypróbuję to również w QA i puli etapowej.
Przyczajony kociak
2
Dlaczego przywiązujesz kod testowy do określonego systemu operacyjnego, skoro możesz po prostu utworzyć plik umożliwiający usunięcie go i usunąć do niego własny dostęp do odczytu?
Kilian Foth,
4
Twierdziłbym, że tak naprawdę nie jest to test jednostkowy, gdy zaczyna się w zależności od prawdziwego, a nie wyśmiewanego systemu plików.
Toby Speight

Odpowiedzi:

21

W nowoczesnych systemach Linux powinieneś być w stanie korzystać /proc/1/fdinfo/0(informacje o deskryptorze pliku 1 (stdout) procesu o id 1 ( initw głównej przestrzeni nazw pid, która powinna działać jako root)).

Możesz znaleźć listę z (jako zwykły użytkownik):

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

(usuń, -type fjeśli nie chcesz ograniczać się do zwykłych plików).

/var/cache/ldconfig/aux-cachejest kolejnym potencjalnym kandydatem, jeśli potrzebujesz tylko rozważyć systemy Ubuntu. Powinien działać na większości systemów GNU, ponieważ /var/cache/ldconfigjest tworzony odczyt + zapis + przeszukiwalny do rootowania tylko za pomocą ldconfigpolecenia dostarczonego z GNU libc.

Stéphane Chazelas
źródło
1
Dzięki! Jeśli /proc/1/fdinfo/0działa na Ubuntu 16.04 i 18.04, to więcej niż wystarcza.
Przyczajony kotek
1
Korzystanie /proc/1/fdinfo/0niekoniecznie działa w kontenerze (np. Kontenerze Docker) i często testy jednostkowe są przeprowadzane w takich kontenerach w CI.
Philipp Wendler
@PhilippWendler, wspomniałem już o przestrzeni nazw root pid . OP nie pyta o kontenery, ale o pliki, które mają się znaleźć w układzie systemu plików systemu Ubuntu. Ponieważ kontenery mogą zawierać dowolny układ plików i katalogów, na to pytanie nie można było odpowiedzieć.
Stéphane Chazelas
12

Patrząc na stronę podręcznika lstat (2) , możesz czerpać inspirację w przypadkach, które mogą sprawić, że zawiedzie z błędami innymi niż ENOENT (plik nie istnieje).

Najbardziej oczywistym z nich jest:

EACCES Brak uprawnień do wyszukiwania dla jednego z katalogów w prefiksie ścieżki .

Potrzebujesz katalogu, z którego nie możesz wyszukiwać.

Tak, możesz poszukać takiego, który jest już w twoim systemie (być może, /var/lib/privatejeśli istnieje?) Ale równie dobrze możesz sam go stworzyć, z odpowiednikiem:

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

Operacja lstat (2) zakończy się tutaj niepowodzeniem z EACCES. (Usunięcie wszystkich uprawnień z katalogu to zapewnia. Może nawet nie potrzebujesz tak dużo ichmod -x usunięcie uprawnień do wykonania byłoby wystarczające, ponieważ uprawnienia dostępu do katalogu są potrzebne, aby uzyskać dostęp do plików w nim zawartych).

Istnieje inny twórczy sposób, aby spowodować niepowodzenie lstat (2), patrząc na jego stronę podręcznika:

ENOTDIR Składnik prefiksu ścieżki nie jest katalogiem.

Próbuję uzyskać dostęp do pliku takiego jak /etc/passwd/nonexistent powinien wywołać ten błąd, który różni się od ENOENT („Brak takiego pliku lub katalogu”) i może odpowiadać Twoim potrzebom.

Kolejny to:

Ścieżka ENAMETOOLONG jest za długa.

Ale możesz potrzebować naprawdę długiej nazwy dla tego (uważam, że 4096 bajtów jest typowym limitem, ale twój system / system plików może mieć dłuższy).

Wreszcie, to trudno powiedzieć, czy któryś z nich będzie rzeczywiście przydatne dla Ciebie. Mówisz, że chcesz czegoś, co nie uruchamia scenariusza „plik nie istnieje”. Chociaż zazwyczaj oznacza to błąd ENOENT, w praktyce wiele kontroli wyższego poziomu po prostu interpretuje wszelkie błędy z lstat (2) jako „nieistniejące”. Na przykład test -elub odpowiednik [ -e ...]powłoki może po prostu zinterpretować wszystkie powyższe jako „nie istnieje”, zwłaszcza że nie ma dobrego sposobu na zwrócenie innego komunikatu o błędzie, a brak zwrócenia błędu oznaczałby, że plik istnieje, co z pewnością nie jest prawdą.

filbranden
źródło
@StephaneChazelas Świetny punkt! Zaktualizowano
filbranden
6

Możesz find zrobić sam.

Korzystanie /etc- katalog plików konfiguracyjnych jako punkt wyjścia:

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

W moim systemie nic to nie zwraca.

Możesz być mniej restrykcyjny i zezwalać na grupę root(tylko użytkownik rootpowinien być członkiem grupy root) i zwracać uwagę na pozwolenie 440:

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

W moim systemie zwraca to:

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

Edytować:

Na podstawie dokonanej edycji szukasz katalogu, który nie ma wystarczających uprawnień dla wywołującego użytkownika, aby zapobiec wyświetleniu katalogu:

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

tutaj szukam katalogów ( -type d), które nie mają bitów perm read-write-execute dla innych ( o-rwx) i są własnością root:root.

Technicznie, tylko brak xbitu execute ( ) uniemożliwiłby listowanie katalogów ( lstat(2)) w katalogu.

W danych wyjściowych znalazłem /run/systemd/inaccessible/w moim systemie opartym na inicjowaniu Systemd.

Jeśli chodzi o pliki /proc, /sys, /dev:

  • Te systemy plików to wirtualny FS, tzn. Rezydują w pamięci, a nie na dysku

  • Jeśli planujesz polegać /proc, użyj /proc/1/np. Polegaj na czymś w ramach PID 1, a nie późniejszych PID, aby mieć niezawodność / spójność, ponieważ późniejsze PID (procesy) nie są gwarantowane.

heemayl
źródło
Dzięki, myślę, że moje pytanie jest złe. Nadal mogę lstat plików bez dostępu do nich odczytu. Może dostęp do folderu musi być ograniczony? (Zmieniłem tytuł)
Crouching Kitten
Dzięki. Po find / -type d -perm 0400 -user rootznalezieniu katalogu /proc/20/map_files/, jeśli odwołuję się do gotowej nazwy pliku w tym folderze, na przykład /proc/20/map_files/asdasd, to zawsze kończy się niepowodzeniem. Czy ten folder zawsze istnieje w systemie Ubuntu?
Przyczajony kotek
@CrouchingKitten, katalogi w /proc/1/mogą być bezpieczniejsze, ponieważ init zawsze istnieje. Ale to procnie jest zwykły system plików, na wypadek, gdyby to miało znaczenie.
ilkkachu
Dziękuję, oddałem głos, ale zaakceptowałem inną odpowiedź, ponieważ powiedział, że jest gwarantowane, że /proc/1/fdinfo/0działa na nowoczesnym Ubuntusie.
Przyczajony kociak
-perm o-rwxjest jak -perm 0, bity są na początek. Tutaj byś chciał ! -perm -1.
Stéphane Chazelas,