cp nadpisuje vs rm, a następnie cp

18

Kiedy próbuję zastąpić plik binarny, który jest aktualnie uruchomiony, cpnie nadpisać, ale jest to możliwe, aby rmgo potem cp. Na przykład:

user@poste:~$ cp binaryFile /tmp
user@poste:~$ sudo cp /tmp/binaryFile binaryFile 
[sudo] password for user:
cp: cannot create regular file `binaryFile`: Text file busy
user@poste:~$ sudo rm binaryFile 
user@poste:~$ sudo cp /tmp/binaryFile  binaryFile 
user@poste:~$ file binaryFile 
binaryFile : ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x7ce005d9eb50e2574246b6a881e625802f7e49f2, not stripped

Wiesz, dlaczego?

M4rty
źródło
2
Ciekawy mały wątek, ale powinien być na UNO / Linux.SE IMO.
underscore_d

Odpowiedzi:

41

W pierwszym przypadku próbujesz zastąpić zawartość pliku, który jest obecnie uruchomiony jako program. Linux nie pozwala na to - gdyby to zrobił, nadpisałeś kod tak, jak działał go system operacyjny; pierwsza różnica spowodowałaby awarię programu lub spowodowała jego awarię.

Ale w drugim przypadku tak naprawdę nie zmieniasz zawartości starego pliku - tworzysz nowy plik na jego miejscu, podczas gdy stary po prostu traci nazwę pliku, ale zachowuje jego zawartość nietkniętą.

(Pamiętaj, że technicznierm nie usuwa plików, po prostu usuwa linki do katalogów - podobnie jak w przypadku dodawania większej liczby linków do tego samego pliku. Tylko wtedy, gdy plik nie ma linków i nie ma otwartych odwołań do plików, jest automatycznie usuwany).ln

System odwołuje się do używanych plików przez ich i-węzeł, więc nie ma znaczenia, że ​​mają tę samą nazwę pliku - nadal jest to stary plik, który pozostaje otwarty przez system i chociaż nie ma już żadnych łączy, zostanie jedynie usunięty gdy wszystkie programy go zamkną.

użytkownik1686
źródło
7
Inna sztuczka, która jest często używana przy użyciu tej samej logiki: Otwórz (tymczasowy) plik w swoim oprogramowaniu i usuń go natychmiast, bez uprzedniego zamykania pliku. Twój program nadal może go używać w dowolny sposób, a kiedy program go zamknie (kontroluje) lub zapomni go zamknąć (np. Program uległ awarii bez czyszczenia), zostanie on automatycznie usunięty przez system operacyjny. (Koniec programu, bez względu na to, jak to się stało, uwalnia wszystkie odniesienia do programu, które miał do pliku.)
Tonny,
2
Dlatego też po usunięciu pliku dziennika uruchomionego procesu komenda df nie zwraca poprawionego rozmiaru, dopóki proces nie zostanie zatrzymany
M4rty,
Czy jest jakiś sposób, aby zewnętrzny program (z uprawnieniami roota) mógł znaleźć i utworzyć nowy uchwyt dla tego wiszącego i-węzła? Wyobrażam sobie, że istnieją programy, które używają tego jako „funkcji bezpieczeństwa”, dlatego warto poznać całą historię.
BenPen
3
@BenPen: Tak w systemie Linux - użyj, /proc/*/fdaby uzyskać do niego dostęp, i opcjonalnie linkat (), aby dodać nowe łącze do systemu plików.
user1686,
3
@BenPen i grawity: W rzeczywistości nie można połączyć i-węzła z powrotem do struktury katalogów, jeśli ma zero łączy, nawet ze linkat()względów bezpieczeństwa . (Wyjątek od tej reguły: jeśli nie został utworzony, open(O_TMPFILE)więc zaczął się od zerowych łączy). Jeśli spróbujesz, linkat()zwraca ENOENT, nawet jako root. Zobacz moją odpowiedź na to pytanie, aby skrypt perla mógł się uruchomić linkati udowodnić, że nie działa, nawet jako root: /
Peter Cordes