Löscht "rm. *" Jemals das übergeordnete Verzeichnis?

53

Der Ausdruck .*wird durch Bash erweitert, um das aktuelle und das übergeordnete Verzeichnis einzuschließen:

$ ls -la
total 2600
drwxrwxrwx   2 terdon terdon 2162688 Sep 10 16:22 .
drwxr-xr-x 142 terdon terdon  491520 Sep 10 15:34 ..
-rw-r--r--   1 terdon terdon       0 Sep 10 16:22 foo
$ echo .*
. ..

Wenn ich rm -rf .*auf meinem Debian mit GNU-Bash version 4.2.36(1)-releaseund rmvon laufe rm (GNU coreutils) 8.13, erhalte ich folgende Meldung:

$ rm -rf .*
rm: cannot remove directory: `.'
rm: cannot remove directory: `..'

Ist das eine GNU-Sache oder ist es POSIX? Gibt es * nix-Systeme, auf denen der obige Befehl unbemerkt löscht .und ..?

Ist dies auch ein Sicherheitsmerkmal der Shell oder des rmBefehls selbst?

terdon
quelle
4
Ich weiß , diese Frage ist im Rahmen rm, aber ich dachte , es wert war , zu erwähnen , dass Sie immer noch zu unerwarteten Ergebnissen mit haben kann chmod, chownusw. , wenn passend .*.
Aaron Copley

Antworten:

59

Die neueste (Stand 2017) Version der POSIX-Spezifikation für das rmDienstprogramm ist hier (und die vorherige dort ) und verbietet das Löschen von .und ...

Wenn eine der Dateien dot oder dot-dot als Basisname eines Operanden angegeben wird (d. H. Als endgültige Pfadnamenskomponente) oder wenn ein Operand in das Stammverzeichnis aufgelöst wird, schreibt rm eine Diagnosemeldung in den Standardfehler und unternimmt nichts mehr mit solchen Operanden.

Wie von @jlliagre angemerkt, handelt es sich bei dem Teil about /um eine Ergänzung in SUSv4.

Die älteste öffentlich verfügbare Unix-Spezifikation, die ich finden konnte ( XPF4 CAE rev2 (1994)), hat dies bereits spezifiziert .und ..kann nicht entfernt werden, obwohl Kommentare im Änderungsprotokoll von GNU fileutils darauf hindeuten, dass dies bereits in älteren POSIX-Spezifikationen der Fall war.

Beachten Sie, dass dies auch für dir/..und gilt ../, aber einige Implementierungen (einschließlich UNIX-zertifizierter Implementierungen wie Solaris 11 und macOS) weiterhin nicht vor rm -rf ../oder schützen rm -rf .*/.

Geschichte

Frühe Unikate

Die -rOption zu rmwurde in Unix V3 (1973) hinzugefügt, obwohl nur der Inhalt der Verzeichnisse gelöscht wurde. Sie müssten sie dennoch rmdirzum Entfernen von Verzeichnissen verwenden.

Dies änderte sich in Unix V7 (1979, der Veröffentlichung, die auch die Bourne-Shell einführte und von der die meisten Unices abstammen). rm -rjetzt entfernte auch Verzeichnisse und würde den ..Verzeichnisbaum nicht löschen . In der Manpage heißt es:

Es ist verboten, die Datei ..nur zu entfernen , um die unsozialen Folgen einer versehentlichen Handlung wie zu vermeiden rm -r .*.

(obwohl man argumentieren könnte, dass rm -r .*es immer noch unsozial ist, da es alles löscht, weil .es enthalten ist).

Das Entfernen wurde dennoch akzeptiert, .ohne dass die Verknüpfung zu den Einträgen .oder ..aufgehoben wurde. Es rm -r .war also eine effektive Möglichkeit, das aktuelle Verzeichnis zu leeren.

Beachten Sie auch, dass die Schutzmaßnahme nur für ein wörtliches ..Argument und nicht für dir/..oder gedacht war ./... Also, rm -rf ./.*würde immer noch alles in dem übergeordneten Verzeichnis entfernen rekursiv.

Es ist interessant zu sehen , dass das war schon die Wanze / misfeature zu umgehen , mit denen Klackse umfassen könnten .und ..bei ihrer Expansion. Das wurde in der Forsyth-Shell (die Basis für die ursprüngliche Minix-Shell und pdksh) in den späten 80ern zsh(1990) und fish(2005) behoben, aber nicht in anderen Shells und insbesondere nicht in der POSIX- shSprache, deren Erweiterung es erfordert .*, .und ..wenn Sie werden von zurückgegeben readdir()( behebt bashdas Problem teilweise nur, shopt -s dotglobwenn Globs (mit Ausnahme .xxxderjenigen) nicht enthalten sind, .oder ..und wenn Sie dies tun ksh, können Sie es beheben FIGNORE='@(.|..)').

Wann genau auch das Verbieten .hinzugefügt wurde, ist nicht immer klar und variiert mit jedem Unix. Ein paar Erkenntnisse weiter unten.

BSDs

Das Verbot von .wurde irgendwann zwischen 2.9BSD (1983) und 2.10BSD (1987) sowie zwischen 4.2BSD (1983) und 4.3BSD (1986) hinzugefügt (siehe diese Änderung mit dem Zeitstempel 1985 im Unix-History-Repo ).

$ wget -qO- http://www.tuhs.org/Archive/PDP-11/Distributions/ucb/2.9BSD/root.tar.gz |
    zgrep -ao 'rm: canno[[:print:]]*'
rm: cannot remove `..'
$ wget -qO- http://www.tuhs.org/Archive/PDP-11/Distributions/ucb/2.10bsd.tar.gz |
    zgrep -ao 'rm: canno[[:print:]]*'
rm: cannot remove `.' or `..'
rm: cannot remove `.' or `..'\n");

Für dir/.und dir/..siehe diese Änderung im Jahr 1988 (BSD 4.3 Net / 1).

Bis rmheute leert die von FreeBSD (und Derivaten wie macOS) immer noch das aktuelle oder übergeordnete Verzeichnis auf rm -rf ./oder rm -rf ../obwohl (wichtig für rm -rf .*/).

System V

Ich habe nicht viele Informationen, da weder Quelle noch Binärdatei für die AT & T-Unix-Derivate nach V7 öffentlich verfügbar sind. In seinem Online-Handbuch erwähnt HPUX (basierend auf System III) immer noch, dass es nur verbietet, ..während es effektiv beides verbietet. Dies ist ein Hinweis darauf, dass zumindest SysIII das Löschen von .( edit : Betrachtet man nun den SysIII- rmQuellcode , so ist es praktisch unverändert seit Unix V7).

Alle anderen Online-Handbücher, die ich überprüft habe, erwähnen das Löschen .oder ..sind verboten, was zu erwarten ist, dass sie POSIX-konform sind.

Solaris rmleert weiterhin das aktuelle oder übergeordnete Verzeichnis auf rm -rf ./oder rm -rf ../.

GNU

Das frühe Änderungsprotokoll für die GNU-Dateien enthält alle historischen Informationen.

Während ursprünglich weder Löschen .noch ..Verboten war, ..war erst und dann beides (einschließlich dir/.) verboten , alles zwischen 1990 und 1991.

andere

Wie wir gesehen haben zsh, beinhaltet die Erweiterung von .*(oder einem beliebigen Glob) niemals .oder ..(sogar im shEmulationsmodus). Das rmeingebaute (was Sie bekommen, wenn Sie zmodload zsh/files) behandelt daher nicht .oder ..speziell. Also, mit diesem zshbuiltin, Sie können rm -rf .oder rm -rf ..zu leeren .oder ..aber rm -rf .*nicht entfernen .oder ...

In busybox rmwurde das Verbot des Löschens von .und ..in 0.52 (2001) hinzugefügt

Stéphane Chazelas
quelle
Seltsam, das scheint zu spezifizieren, dass rm -rf . /(beachte das Leerzeichen) zwei Warnungen (für .und /) ausgegeben und beendet werden sollen, aber wir scheinen alle paar Monate eine Frage zu bekommen, wie man sich davon erholt.
Kevin
6
@ Kevin Nicht alle Systeme sind POSIX-kompatibel, und die Root-Verzeichniseinschränkung wurde erst in der neuesten POSIX-Version explizit hinzugefügt.
Juli
@ jlliagre Ich verstehe. GNU versucht im Allgemeinen, POSIX zu implementieren (+ Erweiterungen natürlich), und ich würde mir vorstellen, dass sie dieses einfügen möchten, aber wenn es ziemlich neu ist, würde das es erklären.
Kevin
2
@Stephane: Du hast recht, aber ich würde trotzdem ein großes "Ja, es könnte passieren! Aber ..." am Anfang deiner Antwort einfügen, so dass die Leute das zweifellos in der Tat wissen, bei einigen (älteren oder einfach nicht -POSIX-kompatiblen) Systemen können sie übergeordnete Verzeichnisse löschen. Ich versuche immer, auf diese Möglichkeit hinzuweisen (dh ich versuche, auf der sicheren Seite zu bleiben, auch wenn die Antwort manchmal schwerer zu lesen / zu merken ist) ^^
Olivier Dulac
1
@ MartinSchröder, Auf BSDs wurde es irgendwo zwischen 2.8BSD und 2.10BSD hinzugefügt (vorher war nur ".." wie in UnixV7 verboten) und zwischen 3BSD und 4.3RENO. Auf SysV-Systemen ist dies weniger klar. Das HPUX-Handbuch behauptet beispielsweise, es verbiete nur "..", aber tatsächlich verbiete es beides "." und "..", es ist nur das Handbuch, das nicht aktuell ist.
Stéphane Chazelas