Dateiberechtigungen in Linux: chmod, chown und umask
1. Übersicht
Der Fehler Permission denied ist einer der häufigsten Fehler beim Deployment von Anwendungen auf Linux. Die Anwendung kann Logs nicht schreiben, kann Konfigurationsdateien nicht lesen, oder vertrauliche Dateien können von allen Benutzern gelesen werden.
Dieser Artikel erklärt das Berechtigungsmodell von Linux und zeigt die Verwendung von drei Hauptwerkzeugen: chmod zum Ändern von Berechtigungen, chown zum Wechsel des Besitzers und umask zur Kontrolle der Standardberechtigungen neuer Dateien. Am Ende des Artikels kannst du die Berechtigungen jeder Datei lesen, die richtigen Berechtigungen vergeben und POSIX-Berechtigungen von Java aus verwalten.
2. Dateiberechtigungen mit ls -l lesen
Beginnen wir mit einem Beispielverzeichnis:
mkdir -p shop && cd shop
echo "id,total" > order.csv
mkdir reports
ls -l
-rw-r--r-- 1 an dev 9 Oct 13 09:00 order.csv
drwxr-xr-x 2 an dev 4096 Oct 13 09:00 reports
Die erste Spalte hat 10 Zeichen:
- Das erste Zeichen ist der Dateityp:
-ist eine reguläre Datei,dist ein Verzeichnis,list ein symbolischer Link. - Die restlichen 9 Zeichen sind in drei Gruppen à 3 Zeichen unterteilt: user (Besitzer), group (Gruppe), other (alle anderen).
- Jede Gruppe besteht aus
r(read),w(write),x(execute). Ein-bedeutet, dass diese Berechtigung nicht vorhanden ist.
Die dritte und vierte Spalte sind der Besitzer (an) und die Gruppe (dev). Bei order.csv kann an also lesen und schreiben, Mitglieder der Gruppe dev können nur lesen, und alle anderen Benutzer können nur lesen.
Um Berechtigungen in Zahlenform zu sehen, nutze stat:
stat -c '%a %A %U:%G %n' order.csv reports
644 -rw-r--r-- an:dev order.csv
755 drwxr-xr-x an:dev reports
Der Kernel prüft die Berechtigungen in dieser Reihenfolge. Wenn du der Besitzer bist, wird nur die Berechtigungsgruppe des Benutzers angewendet. Wenn du nicht der Besitzer bist, aber zur Gruppe gehörst, wird nur die Berechtigungsgruppe der Gruppe angewendet. Ansonsten wird die “other”-Gruppe verwendet. Die Gruppen addieren sich nicht. Daher wird eine Datei mit Berechtigung ---r--r-- den Besitzer selbst am Lesen hindern, obwohl alle anderen lesen können.
3. Berechtigungen mit chmod ändern
3.1. Symbolische Form
Die symbolische Form hat die Syntax [ugoa][+-=][rwxX]. Dabei bedeutet u user, g group, o other, a all (alle).
chmod g+w order.csv # Schreibberechtigung für Gruppe hinzufügen
chmod o-r order.csv # Leseberechtigung für andere entfernen
chmod u=rw,go= order.csv # user: rw, group und other: keine
stat -c '%a %A' order.csv
600 -rw-------
Die Operatoren + und - fügen nur die angegebenen Berechtigungen hinzu oder entfernen sie; andere Berechtigungen bleiben erhalten. Der Operator = setzt die gesamte Gruppe neu. Die symbolische Form ist sicher, wenn du nur einen Teil ändern möchtest, ohne den aktuellen Zustand kennen zu müssen.
3.2. Oktalzahlenform
Jede Berechtigung hat einen Wert: r = 4, w = 2, x = 1. Addiert man diese Werte, erhält man eine Ziffer für jede Gruppe.
| Zahl | Berechtigung | Verwendung |
|---|---|---|
| 7 | rwx |
Besitzer von Verzeichnissen oder Skripten |
| 6 | rw- |
Besitzer von Datendateien |
| 5 | r-x |
Lesen und Verzeichnis betreten, Skript ausführen |
| 4 | r-- |
Nur lesen |
| 0 | --- |
Keine Berechtigung |
Beispiel, ein Skript und eine Datei mit Geheimnissen erstellen:
printf '#!/bin/bash\necho "Backup orders..."\n' > backup.sh
echo "db.password=s3cret" > secret.properties
chmod 755 backup.sh
chmod 600 secret.properties
./backup.sh
stat -c '%a %n' backup.sh secret.properties
Backup orders...
755 backup.sh
600 secret.properties
755 ermöglicht es jedem, das Skript auszuführen, aber nur der Besitzer kann es ändern. 600 ermöglicht nur dem Besitzer, die geheime Datei zu lesen und zu schreiben. Die Oktalform setzt alle Berechtigungen auf einmal, daher ist sie geeignet, wenn du den exakten gewünschten Zustand kennst.
3.3. Rekursive Berechtigungsänderung und Großbuchstabe X
Ein klassischer Fehler ist die Ausführung dieses Befehls:
chmod -R 755 shop/
Dieser Befehl macht alle Dateien ausführbar, einschließlich order.csv. Der richtige Weg ist, den Großbuchstaben X zu verwenden. Dieses Symbol fügt x nur zu Verzeichnissen hinzu, oder zu Dateien, die bereits x in einer Gruppe haben:
chmod -R u=rwX,go=rX shop/
Das Ergebnis ist, dass Verzeichnisse die Berechtigung 755 haben, normale Dateien die Berechtigung 644, und backup.sh behält die Berechtigung 755. Wenn du mehr Kontrolle brauchst, kannst du mit find trennen:
find shop -type d -exec chmod 750 {} +
find shop -type f -exec chmod 640 {} +
4. Berechtigungen von Verzeichnissen unterscheiden sich von Dateien
Bei Verzeichnissen bedeuten rwx etwas anderes:
r: Inhalte des Verzeichnisses auflisten (ls).w: Elemente im Verzeichnis erstellen, löschen oder umbenennen. Diese Berechtigung muss zusammen mitxverwendet werden, um wirksam zu sein.x: In das Verzeichnis wechseln (cd) und auf Inhalte zugreifen, wenn du den Namen kennst.
Eine überraschende Folge: Das Löschen einer Datei hängt von den Berechtigungen des Verzeichnisses ab, nicht von den Berechtigungen der Datei selbst.
mkdir inbox && echo "data" > inbox/invoice.txt
chmod 444 inbox/invoice.txt # Datei ist schreibgeschützt
rm -f inbox/invoice.txt # Kann trotzdem gelöscht werden, weil inbox w-Berechtigung hat
ls inbox # Leer
Umgekehrt: Wenn du die x-Berechtigung auf dem Verzeichnis entfernst, kannst du die Datei nicht lesen, auch wenn die Datei die Berechtigung 644 hat:
echo "data" > inbox/invoice.txt
chmod 644 inbox/invoice.txt
chmod u-x inbox
cat inbox/invoice.txt
cat: inbox/invoice.txt: Permission denied
Wenn eine Anwendung Permission denied meldet, aber die Dateiberechtigungen richtig aussehen, überprüfe alle übergeordneten Verzeichnisse im Pfad. Der Befehl namei -l /path/to/file zeigt die Berechtigungen jeder Ebene. Bevor du fortfährst, gibst du dem Verzeichnis die Berechtigung zurück mit chmod u+x inbox.
5. Besitzer mit chown und chgrp wechseln
chown ändert den Besitzer, die Gruppe oder beide:
sudo chown appuser order.csv # Nur Besitzer ändern
sudo chown appuser:dev order.csv # Besitzer und Gruppe ändern
sudo chown :dev order.csv # Nur Gruppe ändern
sudo chown -R appuser:appuser /opt/shop
Ein paar wichtige Punkte:
- Nur
rootkann den Besitzer ändern. Ein normaler Benutzer kann seine Dateien nicht an jemand anderen “übergeben”. - Ein normaler Benutzer kann die Gruppe seiner eigenen Dateien ändern, aber nur zu einer Gruppe, der er angehört. Der Befehl ist
chgrp dev order.csv. chown -Rtraversiert den Verzeichnisbaum. Bei symbolischen Links ändert es standardmäßig den Besitzer der Datei, auf die der Link verweist. Verwende-h, wenn du den Besitzer des Links selbst ändern möchtest.
Ein häufiges Muster beim Deployment ist, den Service als separaten Benutzer auszuführen und die Betriebsgruppe gemeinsam zu nutzen:
sudo chown -R appuser:ops /var/log/shop
sudo chmod -R u=rwX,g=rX,o= /var/log/shop
Mit diesem Setup kann der Service Logs schreiben, die ops-Gruppe kann Logs lesen, und andere Benutzer können nicht zugreifen.
6. Standardberechtigungen mit umask
Wenn neue Dateien erstellt werden, fordert das Programm normalerweise die Berechtigung 666 für Dateien und 777 für Verzeichnisse an. Der Kernel deaktiviert dann die Bits, die in umask enthalten sind. Das Ergebnis ist:
tatsächliche Berechtigung = angeforderte Berechtigung AND (NOT umask)
umask # aktuellen Wert anzeigen
umask 027 # für die aktuelle Shell ändern
touch customer.csv && mkdir archive
stat -c '%a %n' customer.csv archive
0022
640 customer.csv
750 archive
Mit umask 027: Die Datei erhält 666 minus die Bits in 027, also 640. Das Verzeichnis erhält 777 minus 027, also 750. Andere verlieren alle Berechtigungen, die Gruppe verliert die Schreibberechtigung.
Hinweis:
umaskist eine Bitmaske-Operation, nicht arithmetische Subtraktion. Mitumask 033haben neue Dateien die Berechtigung644, nicht633. Der Grund ist, dass das Bitxnicht in666vorhanden ist, daher gibt es nichts zu deaktivieren.
Ein paar häufig verwendete Werte:
| umask | Datei | Verzeichnis | Wann verwenden |
|---|---|---|---|
022 |
644 | 755 | Standard auf den meisten Distros |
027 |
640 | 750 | Server, nur Sharing innerhalb der Gruppe |
077 |
600 | 700 | sensible Daten |
Der Befehl umask hat nur Auswirkungen auf den aktuellen Prozess und seine Kinder. Um es für einen systemd-Service permanent zu setzen, deklariere es in der Unit-Datei:
[Service]
User=appuser
UMask=0027
7. Drei spezielle Bits: setuid, setgid, sticky
Neben den 9 grundlegenden Bits hat Linux noch drei spezielle Bits. Sie werden als vierte Ziffer am Anfang der Oktalform geschrieben:
- setuid (4): Das Programm läuft mit den Berechtigungen des Besitzers. Beispiel:
/usr/bin/passwdwird als-rwsr-xr-xangezeigt. - setgid (2): Wenn auf einem Verzeichnis gesetzt, erben neue Dateien im Verzeichnis die Gruppe des Verzeichnisses. Dieses Bit ist sehr nützlich für gemeinsam genutzte Arbeitsverzeichnisse.
- sticky (1): Wenn auf einem Verzeichnis gesetzt, kann nur der Besitzer einer Datei diese Datei löschen.
/tmpnutzt dieses Bit und wird alsdrwxrwxrwtangezeigt.
Beispiel: Ein gemeinsames Verzeichnis für die Gruppe dev erstellen:
sudo mkdir /srv/shared && sudo chown :dev /srv/shared
sudo chmod 2770 /srv/shared
stat -c '%a %A' /srv/shared
2770 drwxrws---
Warnung: Weise setuid nicht Skripten oder selbst geschriebenen Dateien zu, es sei denn, du verstehst wirklich die Risiken. Ein Programm mit setuid root und einem Fehler ist ein klassischer Weg zu Privilege Escalation.
8. POSIX-Berechtigungen von Java aus verwalten
Java NIO unterstützt POSIX-Berechtigungen über PosixFilePermissions. Diese Klasse schreibt eine geheime Datei und stellt sicher, dass nur der Besitzer sie lesen kann:
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.PosixFilePermissions;
public class SecretWriter {
public Path writeSecret(Path dir, String content) throws IOException {
Path file = dir.resolve("secret.properties");
Files.writeString(file, content);
Files.setPosixFilePermissions(file, PosixFilePermissions.fromString("rw-------"));
return file;
}
}
fromString("rw-------") konvertiert eine symbolische Zeichenkette in ein Set<PosixFilePermission>. Dann funktioniert setPosixFilePermissions wie der Befehl chmod 600.
Du könntest versuchen, PosixFilePermissions.asFileAttribute(...) an Files.createFile zu übergeben. Diese Methode wird immer noch durch umask beeinflusst, genau wie der Systemaufruf open(). Für vertrauliche Dateien solltest du setPosixFilePermissions nach der Erstellung aufrufen, um das Ergebnis sicherzustellen. Ein noch sicherer Weg ist, die Datei mit strikten Berechtigungen direkt bei der Erstellung zu erstellen, um zu verhindern, dass die Datei in der Zwischenzeit von anderen gelesen wird.
Test mit JUnit 5 und AssertJ:
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.nio.file.*;
import java.nio.file.attribute.PosixFilePermissions;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assumptions.assumeTrue;
class SecretWriterTest {
@TempDir
Path tempDir;
@Test
void givenSecret_whenWritten_thenOnlyOwnerCanReadAndWrite() throws Exception {
assumeTrue(FileSystems.getDefault().supportedFileAttributeViews().contains("posix"));
Path file = new SecretWriter().writeSecret(tempDir, "db.password=s3cret");
String perms = PosixFilePermissions.toString(Files.getPosixFilePermissions(file));
assertThat(perms).isEqualTo("rw-------");
assertThat(Files.readString(file)).contains("db.password");
}
}
assumeTrue wird den Test auf Windows überspringen, wo die posix Attribute View nicht vorhanden ist. Ohne diese Zeile würde der Test eine UnsupportedOperationException werfen.
9. Häufige Fehler
chmod 777zur schnellen Fehlerbehebung verwenden. Dies öffnet die Schreibberechtigung für alle Benutzer auf der Maschine. Bestimme stattdessen, welcher Benutzer den Prozess ausführt (ps -o user= -p <pid>), und gebe die Berechtigung nur diesem Benutzer oder dieser Gruppe.chmod -R 755auf einen Verzeichnisbaum anwenden. Dies macht alle Dateien ausführbar. Verwende stattdessenXin Großbuchstaben oderfindwie in Abschnitt 3.3.- Nur die Berechtigungen der Datei prüfen. Du musst auch alle übergeordneten Verzeichnisse mit
namei -lprüfen. sudoausführen und dann vergessen, den Besitzer zu wechseln. Dateien, die vonsudoerstellt werden, gehörenroot, daher können sie von Benutzern mit normalen Berechtigungen nicht geschrieben werden. Führechowndanach sofort aus.- Volume in Docker mounten. Die UID im Container kann sich von der UID auf dem Host unterscheiden. Berechtigungen werden vom Kernel nach Nummer-UID geprüft, nicht nach Benutzername.
- SSH lehnt den Schlüssel ab. SSH ignoriert
~/.ssh/authorized_keysoder den privaten Schlüssel, wenn die Berechtigungen zu großzügig sind. Das Verzeichnis~/.sshbenötigt die Berechtigung700, der private Schlüssel benötigt600.
10. Fazit
Das Berechtigungsmodell von Linux besteht aus drei Gruppen (user, group, other) und drei Berechtigungen (r, w, x). Diese Berechtigungen haben unterschiedliche Bedeutungen für Dateien und Verzeichnisse.
Verwende chmod, um Berechtigungen zu ändern: symbolische Form, wenn du nur einen Teil ändern musst, Oktalform, wenn du alles auf einmal setzen möchtest. Verwende chown und chgrp, um Dateien dem richtigen Benutzer und der richtigen Gruppe zuzuweisen. Verwende umask, damit neue Dateien von Anfang an mit sicheren Berechtigungen erstellt werden.
Das durchgehende Prinzip ist, so wenig Berechtigungen wie möglich zu gewähren. Führe Services als separaten Benutzer aus, teile über Gruppen und setze other auf 0 für alles Vertrauliche.