SSD Nodes Learn 🎉 VPS ab $5.50/Monat
Anleitungen Matt ConnorVon Matt Connor

umask unter Linux: Standardrechte verstehen und prüfen

Die umask entfernt Rechte bei jeder neuen Datei. Prüfen Sie den Wert, erstellen Sie Datei und Verzeichnis und vergleichen Sie die Modi für root und Ihren Benutzer.

Was die umask unter Linux bewirkt

Die umask ist eine Zahl, die jeder Prozess unter Linux mitführt. Sie legt den Modus jeder Datei und jedes Verzeichnisses fest, die dieser Prozess erstellt. Ein Programm fordert beim Erstellen eine Gruppe von Berechtigungen vom Kernel an. Der Kernel löscht jedes Bit, das in der Maske angegeben ist, und wendet die verbleibenden Bits an. Eine umask gewährt niemals Zugriff. Sie entfernt nur Bits aus den Berechtigungen, die das erstellende Programm angefordert hat.

Der Wert ist keine Eigenschaft Ihrer Distribution. Er hängt davon ab, unter welchem Account Sie arbeiten und wie die Shell gestartet wurde. Diese beiden Werte können auf demselben Rechner zum selben Zeitpunkt bei einem unveränderten Image unterschiedlich sein. Der erste Schritt ist daher keine Suche im Handbuch. Messen Sie den Wert direkt auf dem System vor Ihnen.

Umask in der aktuellen Shell anzeigen

umask
umask -S

Die erste Form gibt die Maske oktal aus. Die zweite gibt dieselbe Maske als Berechtigungen aus, die sie zulässt, und verwendet dabei das von chmod akzeptierte symbolische Format. Lassen Sie beide Zeilen auf dem Bildschirm stehen. Alle folgenden Schritte vergleichen die Ausgabe mit dem, was Ihre Shell gerade ausgegeben hat.

umask ist ein Shell-Builtin und kein Programm auf dem Datenträger. Bestätigen Sie dies mit type umask. Das ist relevant, weil ein Builtin den Shell-Prozess selbst ändert. Ein separates Programm könnte nur seinen eigenen Prozess ändern, anschließend beendet es sich und nimmt die Änderung mit.

Datei und Verzeichnis erstellen und die Berechtigungsmodi anschließend auslesen

cd "$(mktemp -d)"
touch probe.file
mkdir probe.dir
stat -c '%a %A %n' probe.file probe.dir

%a gibt den Modus oktal aus, und %A gibt denselben Modus in der Form drwxr-xr-x aus, die ls -l verwendet. Vergleichen Sie beide Zeilen mit der zuvor ausgegebenen Maske. Jedes in der Maske gesetzte Bit fehlt in den Modi, weil eine Maske ausschließlich diese Bits löscht. Wenn sich die Spalte %A noch nicht intuitiv lesen lässt, sollten Sie zuerst die Berechtigungszeichenfolge drwxr-xr-x sicher verstehen.

Datei und Verzeichnis unterscheiden sich voneinander. Die Maske ist nicht der Grund für diesen Unterschied. touch fordert Lese- und Schreibrechte für Besitzer, Gruppe und andere an. mkdir fordert für alle drei Lese-, Schreib- und Ausführungsrechte an. Dieselbe Maske wird von zwei unterschiedlichen Anforderungen abgezogen. Eine mit touch erstellte Datei ist daher unabhängig vom Inhalt der Maske niemals ausführbar: Das Execute-Bit wurde nie angefordert, und eine Maske kann ein Bit nicht wieder hinzufügen.

( umask a=rwx; touch open.file; stat -c '%a %A %n' open.file )

Die Klammern führen die Befehle in einer Subshell aus. Die Änderung gilt daher nur innerhalb dieser Subshell. Die Maske fordert jetzt an, dass kein Bit gelöscht wird, und stat zeigt für die Datei weiterhin kein Execute-Bit an. Führen Sie anschließend erneut umask aus. Danach ist der ursprüngliche Wert wieder vorhanden. Das zeigt, dass die Einstellung innerhalb eines Prozesses gilt und an Kindprozesse vererbt wird, statt auf der Festplatte gespeichert zu werden.

Bei Verzeichnissen wirkt sich ein gelöschtes Execute-Bit aus.

( umask a=rw; mkdir noexec.dir; cd noexec.dir )

Als normaler Benutzer schlägt cd mit bash: cd: noexec.dir: Permission denied fehl, weil die Maske das von mkdir angeforderte Execute-Bit gelöscht hat. Ein Verzeichnis ohne Execute-Bit kann nicht betreten werden. root überspringt diese Prüfung. Daher zeigt sich dieses Verhalten nur bei einem normalen Benutzerkonto.

Warum root und Ihr eigener Benutzer eine unterschiedliche umask sehen

Führen Sie dieselbe Messung über ein anderes Konto und auf eine andere Weise gestartet aus. Lesen Sie anschließend beide Ausgaben direkt nebeneinander.

umask
sudo -i umask

sudo -i startet die Login-Shell von root und führt den integrierten Befehl darin aus. Damit handelt es sich um ein anderes Konto mit einem anderen Startpfad. Auf unveränderten Ubuntu- und Debian-Server-Images können die beiden Zeilen unterschiedliche Werte ausgeben. Beide Zeilen sind korrekt. Jede zeigt das Ergebnis ihres eigenen Startpfads. Im restlichen Beitrag geht es darum, welcher Teil des Systems dieses Ergebnis erzeugt hat.

Welche Datei in Ihrem Image den Wert festgelegt hat

grep -nE '^(UMASK|USERGROUPS_ENAB)' /etc/login.defs
grep -rn pam_umask /etc/pam.d/
grep -rn umask /etc/profile /etc/profile.d/ /etc/bash.bashrc ~/.profile ~/.bashrc 2>/dev/null || echo 'no umask line in the shell startup files'

Wenn der erste grep-Befehl keine Ausgabe liefert, führen Sie ihn erneut ohne den Anker ^ aus. Die Zeile ist möglicherweise auskommentiert. Eine auskommentierte Zeile dient als Dokumentation und ist keine Konfiguration. Der dritte grep-Befehl ist der Teil, der viele überrascht. Unter Debian und Ubuntu verweist die mitgelieferte /etc/profile meistens auf PAM, anstatt selbst eine Maske festzulegen. Die Datei, die Sie für zuständig hielten, ist es daher häufig nicht. grep beendet sich mit einem Fehlerstatus, wenn es keine Übereinstimmung findet. Deshalb endet diese Zeile mit || echo. Wenn in einer Image-Datei keine Startdatei eine Maske erwähnt, erhalten Sie die Meldung statt keiner Ausgabe. Diese Meldung ist das Ergebnis.

/etc/login.defs kündigt einen Wert an, PAM wendet jedoch einen anderen an

Die Zeile UMASK in /etc/login.defs enthält den Wert, den die meisten Anleitungen nennen. Weder der Kernel noch die Shell lesen diese Datei. Gelesen wird sie von pam_umask, einem PAM-Modul (Pluggable Authentication Modules), das beim Erstellen einer Sitzung ausgeführt wird. pam_umask verwendet den ersten gefundenen Wert: zuerst einen Eintrag umask= im GECOS-Feld des Benutzers, danach ein Argument umask=, das direkt in der Zeile pam_umask.so angegeben ist, und anschließend UMASK aus /etc/login.defs. Distributionen patchen dieses Modul. Führen Sie daher man pam_umask auf Ihrem eigenen Image aus und prüfen Sie die dort ausgegebene Reihenfolge.

So kann /etc/login.defs einen Wert ankündigen, während Ihre Sitzung ohne Warnung auf beiden Seiten mit einem anderen Wert endet. Die grep-Befehle zeigen, welcher Fall vorliegt. Wenn die Zeile pam_umask.so ein eigenes Argument umask= enthält, wird der Wert aus login.defs nicht verwendet.

USERGROUPS_ENAB und die Root-Ausnahme

id -un
id -gn

Wenn beide denselben Namen ausgeben, verwenden Sie eine private Benutzergruppe: Das Konto wurde mit einer eigenen Gruppe angelegt, die nach dem Konto benannt ist. pam_umask verfügt über ein Verhalten für private Benutzergruppen, das in USERGROUPS_ENAB in /etc/login.defs gesteuert wird. Wenn diese Option aktiviert ist, das Konto nicht root ist und der Name der primären Gruppe mit dem Benutzernamen übereinstimmt, übernimmt das Modul die Eigentümerziffer der Maske in die Gruppenziffer. Die Sitzung endet dann mit einer Maske, die die Gruppenbits für alles offen lässt, was dieses Konto erstellt. root wird vom Modul selbst ausgeschlossen. Diese Ausnahme ist der häufigste einzelne Grund dafür, dass zwei Shells auf demselben Server unterschiedliche Masken ausgeben.

Der Grund für diese Regel ist, dass eine private Gruppe genau ein Mitglied hat. Schreibbarkeit für die Gruppe entspricht dann ausschließlich der Schreibbarkeit für den Eigentümer. Das gilt nicht mehr, sobald jemand ein zweites Mitglied zur Gruppe hinzufügt. Ab diesem Zeitpunkt kann das neue Mitglied jede Datei schreiben, die das Konto jemals erstellt hat. Dazu musste kein Befehl für diese Dateien ausgeführt werden. Weisen Sie jedem Dienst ein eigenes Benutzerkonto mit den geringstmöglichen Berechtigungen zu. Dadurch bleibt diese Gruppe absichtlich eine Gruppe mit nur einem Mitglied.

Login-Shell, Nicht-Login-Shell und nicht interaktive Shell

umask
bash -lc 'umask'
bash -c 'umask'

PAM wird erstellt, wenn eine Sitzung gestartet wird: login auf der Konsole, sshd, su, sudo -i. Wenn eine Shell eine weitere Shell startet, wird PAM nicht ausgeführt. bash -l ist eine Login-Shell. Daher liest sie /etc/profile und ~/.profile, ruft pam_umask jedoch nie auf, weil keine Sitzung erstellt wurde. bash -c liest keine der beiden Dateien und übernimmt die Umask des Prozesses, der sie gestartet hat. Ein Cron-Job, ein Git-Hook und ein von einem Service-Manager gestartetes Programm fallen alle in diese letzte Kategorie. Ihre Umask entspricht daher der Umask des jeweiligen Elternprozesses.

Deshalb lautet eine häufige Meldung: „Ich habe die Einstellung in /etc/profile vorgenommen, aber der Dienst erstellt weiterhin Dateien mit den falschen Berechtigungen.“ Der Dienst hat diese Datei nie gelesen.

Wo die Einstellung dauerhaft greift

Setzen Sie die Maske dort, wo die Workload tatsächlich gestartet wird, da jeder Startpfad eine andere Datei liest.

  1. Für Konten, die sich anmelden: UMASK in /etc/login.defs, angewendet von pam_umask auf jede Sitzung des Systems. Die Einstellung gilt systemweit und ändert daher alle Konten gleichzeitig.
  2. Für ein einzelnes Konto: Das Argument umask= in der Zeile pam_umask.so gilt ebenfalls systemweit. Ein benutzerspezifischer Wert gehört daher in das GECOS-Feld des betreffenden Benutzers oder für Login-Shells in ~/.profile und für interaktive Shells in ~/.bashrc.
  3. Für einen Daemon unter systemd: UMask= im Abschnitt [Service] der Unit. Eine Unit wird vom Service-Manager gestartet. Daher wird /etc/profile nie gelesen, und pam_umask wird nie ausgeführt. Nur die Unit-Datei von diesen Optionen erreicht den Daemon.
  4. Für ein von cron oder einem Hook gestartetes Skript: ein explizites umask in der ersten Zeile, bevor das Skript Dateien oder Verzeichnisse anlegt.
[Service]
UMask=<the octal mask you chose>

Prüfen Sie die Einstellung anschließend nach einem frischen Start über denselben Pfad. Führen Sie die Prüfung nicht in der Shell aus, in der Sie die Datei bearbeitet haben. Ihre aktuelle Shell verwendet bereits ihre vorhandene Maske. Das Bearbeiten einer Konfigurationsdatei wirkt sich nicht rückwirkend auf einen laufenden Prozess aus.

bash -lc 'umask'
sudo -i umask

Warum chmod im Nachhinein nicht dieselbe Lösung ist

chmod repariert vorhandene Dateien. Die Maske legt den Modus von Dateien fest, die noch nicht existieren. Führen Sie chmod -R für ein Verzeichnis aus, erhält die nächste Datei, die der Dienst schreibt, wieder den alten Modus, weil dieser vom Prozess stammt, der die Datei erstellt. Am Verzeichnis selbst ändert sich dadurch nichts.

Außerdem gibt es ein Zeitfenster. Zwischen dem Erstellen der Datei und dem Ausführen von chmod liegt die Datei bereits mit dem weiteren Modus auf der Festplatte. Jeder Prozess, der das Verzeichnis lesen kann, kann sie in dieser Zeit öffnen. Bei einem privaten Schlüssel oder einem Backup-Archiv ist genau dieses Zeitfenster das Risiko, das Sie beseitigen wollten.

Legen Sie den Modus stattdessen beim Erstellen fest. install -m u=rw,go= newfile /etc/app/newfile schreibt das Ziel mit einem expliziten Modus. mkdir -m macht dasselbe für ein Verzeichnis. Beide verwenden den angegebenen Modus und ignorieren die Maske. ssh-keygen setzt den Modus des privaten Schlüssels, den es schreibt. Deshalb ist diese einzelne Datei auf einem System oft korrekt, während andere Dateien es nicht sind.

Am häufigsten ist SSH betroffen. Ein mit einfachem mkdir erstelltes ~/.ssh oder ein mit cat >> angehängtes authorized_keys übernimmt die Maske Ihrer Shell. Wenn StrictModes aktiviert ist, verweigert sshd das Lesen einer Schlüsseldatei aus einem für die Gruppe beschreibbaren Verzeichnis. Der Client meldet Permission denied (publickey). Das /var/log/auth.log des Servers protokolliert die tatsächliche Ursache:

Authentication refused: bad ownership or modes for directory /home/deploy/.ssh

Diese Prüfung ist beabsichtigt. Die Absicherung von SSH auf einem VPS hängt davon ab, dass sie greift. Prüfen Sie die Maske auf einem neuen Server, bevor Sie die Konten anlegen, die ihn verwenden. Führen Sie das zusammen mit den ersten zehn Minuten auf einem neuen VPS durch. Dann ist der Modus jeder Datei, die diese Konten schreiben, im Voraus festgelegt.

Kopier- und Archivierungsprogramme ignorieren die Maske

cp -p und rsync -a stellen die auf der Quelldatei gespeicherten Berechtigungen wieder her. Die Maske hat daher keinen Einfluss auf das Ergebnis. tar verhält sich genauso, wenn es als root oder als gewöhnlicher Benutzer mit -p extrahiert. Eine aus einem Backup wiederhergestellte Datei behält die Berechtigungen, die sie zum Zeitpunkt der Sicherung hatte. Prüfen Sie das, bevor Sie zu dem Schluss kommen, dass eine korrekte Maske ignoriert wird: Bei wiederhergestellten Daten wurde sie überhaupt nicht berücksichtigt.

FAQ

Warum erstellt mein Cronjob Dateien mit einem anderen Modus als meine SSH-Sitzung?

Ein Cronjob ist keine Login-Sitzung. Deshalb wird pam_umask nicht ausgeführt, und der Job liest weder /etc/profile noch ~/.profile. Er übernimmt die Maske des Prozesses, der ihn gestartet hat. Setzen Sie in der ersten Zeile des Skripts explizit umask, bevor das Skript Dateien erstellt. Geben Sie die Maske außerdem einmal innerhalb des Jobs aus. So sehen Sie, welche Maske der Job tatsächlich verwendet, statt nur die Maske Ihrer eigenen Shell.

Warum steht in /etc/login.defs etwas anderes, als meine Shell ausgibt?

UMASK in /etc/login.defs ist nur der letzte Fallback für pam_umask. Das Modul verwendet bevorzugt einen Eintrag umask= im GECOS-Feld des Benutzers. Danach berücksichtigt es ein Argument umask= in der Zeile pam_umask.so in /etc/pam.d/. Das durch USERGROUPS_ENAB aktivierte usergroups-Verhalten ändert anschließend die Gruppenziffer für jedes Nicht-root-Konto, dessen primäre Gruppe nach dem Konto benannt ist. Führen Sie grep -rn pam_umask /etc/pam.d/ und id -un; id -gn aus, um zu sehen, welche dieser Einstellungen für Ihr Konto gilt.

Kann eine umask eine Datei ausführbar machen?

Nein. Eine Maske kann nur Bits aus den Berechtigungen entfernen, die das erstellende Programm anfordert. touch fordert niemals das Ausführungsbit an. Daher erzeugt keine Maske eine ausführbare Datei. Prüfen Sie dies in einem temporären Verzeichnis mit ( umask a=rwx; touch f; stat -c '%a %A' f ). Für ein Ausführungsbit benötigen Sie chmod oder ein Programm wie install -m, das dieses Bit beim Erstellen anfordert.

Wo lege ich die umask für einen systemd-Dienst fest?

In der Unit mit UMask= im Abschnitt [Service]. Ein Dienst wird vom Service Manager und nicht durch einen Login gestartet. Deshalb werden die Startdateien der Shell nicht gelesen, und pam_umask wird für den Dienst nicht ausgeführt. Führen Sie anschließend systemctl daemon-reload aus und starten Sie die Unit neu. Prüfen Sie das Ergebnis von außerhalb: Lassen Sie den Dienst eine Datei erstellen, und lesen Sie das Ergebnis anschließend mit stat -c '%a %n' aus.

Ist eine standardmäßige Maske mit Schreibrechten für die Gruppe sicher?

Sie ist sicher, solange die Gruppe genau ein Mitglied hat. Das entspricht der Annahme des User-Private-Group-Schemas. Fügen Sie dieser Gruppe ein zweites Konto hinzu, können dessen Dateien sofort durch das neue Mitglied beschrieben werden. Dafür muss kein Befehl für diese Dateien ausgeführt werden. Führen Sie id -un und id -gn aus. Wenn dabei derselbe Name ausgegeben wird, verwenden Sie eine private Gruppe. Wenn Sie eine Gruppe für mehrere Konten freigeben, setzen Sie eine Maske, die das Gruppenschreibbit entfernt. Erstellen Sie anschließend eine Datei, und lesen Sie stat -c '%a %n' aus, um zu bestätigen, dass die Änderung wirksam ist.

#umask#permissions#pam#login-defs#linux