Kiedy próbuję zastąpić plik binarny, który jest aktualnie uruchomiony, cp
nie nadpisać, ale jest to możliwe, aby rm
go 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?
Odpowiedzi:
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 technicznie
rm
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ą.
źródło
/proc/*/fd
aby uzyskać do niego dostęp, i opcjonalnie linkat (), aby dodać nowe łącze do systemu plików.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ćlinkat
i udowodnić, że nie działa, nawet jako root: /