Czy plik może zostać pobrany przez jego i-węzeł?


27

Uruchomiłem następujące polecenia w podanej kolejności:

$ln a b
$ls -i a b
523669 a 523669 b
$rm -f a
$ls -i b
523669 b

Doszedłem do wniosku, że polecenie rmfaktycznie usuwa tylko nazwę pliku ( aw tym teście) zamiast pliku, ponieważ i-węzeł nadal istnieje i można go pobrać za pomocą innej nazwy pliku ( b).

Moje pytanie brzmi: czy plik jest na stałe połączony tylko z jedną nazwą pliku, kiedy rmjest wykonywany, czy prawdziwy plik (tj. I-węzeł) jest całkowicie usuwany? A jeśli nie, czy i-węzeł pliku można pobrać bez nazwy pliku i tylko za pośrednictwem i-węzła?


Brzmi dla mnie specyficznie dla systemu operacyjnego.
Ignacio Vazquez-Abrams

@Ignacio Vazquez-Abrams. Masz na myśli, że to zależy od wersji?
user43312,

Nie, to znaczy, że zależy to od systemu operacyjnego. Każdy z nich ma inne (jeśli w ogóle ) sposoby korzystania z VFS.
Ignacio Vazquez-Abrams

@Ignacio Vazquez-Abrams Czy masz pojęcie o RHL lub RHEL?
user43312,

1
@BruceEdiger Os X sort-of robi to. Dostęp do obiektu systemu plików można uzyskać za pomocą „referencyjnego adresu URL pliku”, który jest zasadniczo zbudowany z numeru systemu plików i numeru węzła. Jednak ich samodzielne tworzenie nie jest oficjalnie obsługiwane. Zamiast tego otrzymujesz „referencyjny adres URL pliku” dla pliku, a następnie używasz go zamiast ścieżki do kolejnych dostępów w tej samej sesji środowiska wykonawczego, dzięki czemu Twoja aplikacja staje się nieświadoma przeniesienia pliku w inne miejsce na tym samym woluminie.
Plik analogowy

Odpowiedzi:


29

Jeśli spróbujesz otworzyć plik za pomocą jego i-węzła, pomija to przechodzenie przez katalog. Przejście do katalogu jest niezbędne do określenia uprawnień do pliku i katalogów do niego prowadzących. Bez przejścia do katalogu jądro nie ma możliwości ustalenia, czy proces wywołujący może uzyskać dostęp do pliku.

Nie było proponowane łata na jądro Linux, aby umożliwić stworzenie link do pliku z deskryptora pliku . Zostało odrzucone, ponieważ bezpieczne wdrożenie tego byłoby niezwykle trudne .

W systemie Linux (i prawdopodobnie w innych wariantach uniksowych z tego samego powodu) nie można utworzyć łącza do usuniętego pliku, więc jeśli plik nie ma już nazwy, nie można go ponownie dodać .¹ Możesz otworzyć usunięty plik plik, otwierając magiczne linki pod /proc/$pid/fd/.

Jeśli plik nie ma już żadnego łącza i nie jest już otwarty, to już nie istnieje, a przestrzeń poprzednio wykorzystywana przez jego dane można w dowolnym momencie odzyskać.

¹ Możesz to zrobić, zmieniając bajty bezpośrednio w systemie plików w sposób zależny od systemu plików, na przykład w debugfsprzypadku ext2 / ext3 / ext4. Wymaga to dostępu do urządzenia, na którym zamontowany jest system plików (tzn. Zazwyczaj tylko root może to zrobić). Chociaż debugfs może uzyskać dostęp do pliku za pomocą i-węzła, nie pomaga to, jeśli plik zostanie usunięty: plik zostanie naprawdę usunięty, jeśli aplikacja go zamknie, a uruchomienie debugfs w trybie odczytu-zapisu na zamontowanym systemie plików jest receptą na nieszczęście.


11

W systemie Linux debugfsinteraktywny debuger systemu plików ext2 / ext3 / ext4 udostępnia lnpolecenie, które może przyjąć numer filespeci- węzła jako i utworzyć nowe twarde łącze do odpowiedniego pliku. W praktyce wymaga to jednak, aby niepowiązany plik był otwarty przez proces , utrzymując w nim otwarty deskryptor pliku /proc/[pid]/fd/[n]. Podjęcie próby usunięcia pliku najprawdopodobniej doprowadzi do uszkodzenia systemu plików.

Jest tak, ponieważ aby zapewnić, że ext3 (i rozszerzenie ext4) może bezpiecznie wznowić rozłączenie po awarii, faktycznie zeruje wskaźniki bloków w i-węzle , podczas gdy ext2 tylko zaznacza te bloki jako nieużywane w bitmapach bloków i oznacza i-węzeł jako „usunięty” i pozostawia wskaźniki bloków same. Mimo to, ponieważ system plików musi zostać zamontowany do odczytu i zapisu, aby utworzyć łącze twarde, bloki zarezerwowane dla usuniętego pliku mogły już zostać ponownie przydzielone.

Przed wersją jądra 2.6.39 było tak, że opcja wprowadzona w GNU coreutils v8.0 mogła być wykorzystana do odzyskania niepowiązanego pliku poprzez otwarty deskryptor pliku, jeśli zarówno niepowiązany plik, jak i nowy hardlink znajdowały się w systemie plików tmpfs . Ta funkcja została odtąd wyłączona , ponieważ, jak zauważył Gilles , względy bezpieczeństwa związane z umożliwieniem tworzenia twardego łącza bezpośrednio z deskryptora pliku.ln -L|--logical/proc/[pid]/fd/[n]


Właśnie próbowałem ln -Lodzyskać usunięty plik z / proc i dostałem błąd: „Brak takiego pliku lub katalogu”, więc nie sądzę, że to faktycznie obsługuje. Mam coreutils 8.21.
wingedsubmariner

1
ln -Lnie robi tego, co mówisz, robi. Mówi, lnże jeśli źródło jest dowiązaniem symbolicznym, powinno na stałe powiązać cel. Linki symboliczne w /proc/$pid/fdsą specjalne, a linkowanie na (deleted)stałe nie działa.
Gilles „SO- przestań być zły”

Również debugfsnie pomoże, jeśli plik został usunięty - chyba że chcesz ryzykować uruchomienie go w trybie odczytu i zapisu na system plików zamontowany, co jest prawdopodobne, aby całkowicie magiel cały system plików.
Gilles „SO- przestań być zły”

Zaktualizowano odpowiedź w odniesieniu do ln -L. Kiedyś można było tworzyć twarde linki /proc/[pid]/fd/[n]przy użyciu go w pewnych szczególnych okolicznościach, ale od tego czasu zostało to naprawione.
Thomas Nyman

1
debugfs„s lnjest bardzo niska, a jedynie tworzy nazwy, nie aktualizuje liczby ani usuwanie znacznika bloki jako nieużywane, więc jest to bardzo niebezpieczne . Wolę debugfs, undelktóre des tego wszystkiego. Uwaga: debugfsto nie może być prowadzony na zamontowanym systemie plików, chyba że chcesz mieć szansę na spalenie swoich FS na popiół.
Lloeki,

9

Komendy „ln” i „rm” działały dokładnie tak w każdym systemie plików UNIX od wczesnych lat siedemdziesiątych. Mac OSX, BSD i Linux dziedziczą ten oryginalny projekt.

Sam plik UNIX nie ma nazwy, tylko numer i- węzła . Ale możesz uzyskać do niego dostęp tylko poprzez wpis w specjalnym pliku „katalogu”, który wiąże nazwę z danym inum; nie możesz bezpośrednio określić inum.

Katalog sam w sobie jest plikiem, więc musisz również uzyskać do niego dostęp za pośrednictwem (innego) katalogu itd., Poprzez serię nazw katalogów ograniczonych ukośnikami (/) zwanymi „nazwą ścieżki”. Ścieżka rozpoczyna się w „bieżącym katalogu roboczym” procesu, chyba że nazwa zaczyna się od „/”, w którym to przypadku zaczyna się od katalogu głównego systemu plików. Na przykład, jeśli nazwa ścieżki nie zawiera znaków „/”, to oczekuje się, że będzie to wpis w bieżącym katalogu.

Plik inny niż katalog może mieć dowolną liczbę nazw ścieżek, zwanych „twardymi łączami”, i będzie istniał do momentu usunięcia wszystkich nazw ścieżek i zamknięcia pliku przez ostatni proces. Następnie plik jest faktycznie usuwany, a jego miejsce oznaczone jako dostępne do ponownego użycia. Oznacza to, że możesz utworzyć () lub otworzyć () pojedynczo połączony plik, a następnie odłączyć (), aby nie pojawiał się już w przestrzeni nazw systemu plików, ale plik będzie istniał do momentu jego zamknięcia. Jest to przydatne w przypadku tymczasowych plików scratch, które nie zostaną odczytane przez żaden inny program.

Chociaż katalogi mają numery i-węzłów, większość systemów plików nie zezwala na twarde łącza do nich; mogą pojawić się tylko w jednym innym katalogu. (Jednym niezwykłym wyjątkiem jest system plików Mac OSX HFS +; pozwala to na tworzenie kopii zapasowych Time Machine). Nadal możesz tworzyć „miękkie linki” do katalogów (lub dowolnego innego pliku). Miękki link przypomina pozycję katalogu, tyle że zawiera inną nazwę ścieżki niż inum.

Każdy plik UNIX ma właściciela, grupę i uprawnienia dostępu. Jest to konieczne, ale niewystarczające, aby pozwoliły Ci otworzyć plik; musisz także mieć uprawnienia do wykonywania przynajmniej każdego katalogu w nazwie ścieżki, do której się odwołujesz. Dlatego nie ma standardowego sposobu otwierania pliku UNIX według jego numeru i-węzła; ominąłoby to ważny, szeroko stosowany mechanizm bezpieczeństwa.

Ale to nie wyjaśnia, dlaczego nie może istnieć standardowy sposób, w jaki użytkownik root (uprzywilejowany) może otworzyć plik według numeru i-węzła, skoro i tak sprawdzanie uprawnień jest pomijane. Byłoby to bardzo przydatne w przypadku niektórych funkcji zarządzania systemem, takich jak kopie zapasowe. Według mojej wiedzy takie mechanizmy istnieją, ale wszystkie są specyficzne dla systemu plików; nie ma ogólnego sposobu, aby to zrobić dla dowolnego systemu plików UNIX.


1
Naprzód w /jest cichy, więc wymawia się „ukośnik”.
ctrl-alt-delor

4

Pytanie można podjąć teoretycznie (co można osiągnąć debugfs) lub pragmatycznie (sytuacja nadzwyczajna). W tym drugim przypadku zakładam, że celem jest uratowanie dnia i przywrócenie zawartości pliku, być może w trybie pilnym (w taki sposób wylądowałem na tym pytaniu, więc myślę, że jest ono nadal aktualne i przydatne).

Ponieważ nie ma interfejsu API jądra, debugfsnie należy go uruchamiać w systemie plików na żywo, ponieważ bezpośrednio manipuluje on strukturą FS. Dlatego, aby zrobić to na żywo, musisz zdobyć inną nazwę pliku. Zakładając, że plik jest nadal otwarty przez jakiś proces (dowolny proces), można sięgnąć po zawsze wygodne deskryptory plików w /proc:

$ lsof -F pf "$PWD/a" | sed 's/^p//' # find pid and file descriptor number of any process having the file open
$ pid=1234
$ ls -l /proc/$pid/fd/* | grep "$PWD/a" # find file descriptor number
$ fd=42
$ cat /proc/$pid/fd/$fd > "$PWD/a.restored" # read contents to a new filename

Wskazówki:

  • jeśli masz wątpliwości co do właściwego fd, możesz uruchomić polecenia takie jak filena nim
  • jeśli do pliku zapisuje się proces, koniecznie zatrzymaj go jak najszybciej, w przeciwnym razie nie otrzymasz najnowszych danych. (Nie przetestowaną) sztuczką może być otwarcie pliku tylko do odczytu przez fd z innym procesem (spróbuj tail -f < /proc/$pid/fd/$fd > /dev/nullwyjść z procesu zapisu, aby wyjść bez problemu i użyć fd nowego procesu.

2
To powinno być tail -f < /proc/...w drugiej wskazówce.
Murray Jensen

Lub użyj go, tail -c +0 -f aby skopiować go zamiast cat, jeśli proces pisania jest tylko dołączany (nie szuka wstecz i przepisuje). Wyjdź wcześniej z innego procesu tail, a następnie poczekaj, tailaż dojdziesz do końca pliku.
Peter Cordes
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.