
Ich arbeite an einer LAMP-Web-App und irgendwo gibt es einen geplanten Prozess, der ständig einen Ordner namens shop
im Stammverzeichnis der Site erstellt. Jedes Mal, wenn dies auftritt, kommt es zu Konflikten mit den Umschreiberegeln in der App, was nicht gut ist.
Gibt es eine Möglichkeit, die Erstellung von Ordnern mit diesem Namen im Stammverzeichnis zu verhindern, bis ich das fehlerhafte Skript gefunden habe shop
? Ich weiß, dass ich die Berechtigungen für einen Ordner ändern kann, um zu verhindern, dass sein Inhalt geändert wird, aber ich habe keine Möglichkeit gefunden, die Erstellung eines Ordners mit einem bestimmten Namen zu verhindern.
Antwort1
Dies ist nicht möglich, da der Benutzer, der das Verzeichnis erstellt, über ausreichende Schreibberechtigungen für das übergeordnete Verzeichnis verfügt.
inotify
Sie können stattdessen die Familie der Systemaufrufe nutzen , die vom Linux-Kernel bereitgestellt werden, um die Erstellung (und optional mv
-ing) des Verzeichnisses shop
im angegebenen Verzeichnis zu überwachen, falls das Verzeichnis erstellt (oder optional mv
-ed) wird.rm
Das Userspace-Programm, das Sie in diesem Fall benötigen, ist inotifywait
(wird mitgeliefert inotify-tools
, installieren Sie es bei Bedarf zuerst).
Angenommen, das Verzeichnis shop
würde sich im /foo/bar
Verzeichnis befinden, richten wir eine Überwachung für /foo/bar/shop
die Erstellung ein und rm
führen bei Erstellung sofort Folgendes aus:
inotifywait -qme create /foo/bar | \
awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'
inotifywait -qme create /foo/bar
überwacht/foo/bar
das Verzeichnis auf alle Dateien/Verzeichnisse, die erstellt werden könnten, d. h. auf allecreate
EreignisseWenn erstellt,
awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'
wird geprüft, ob die Datei zufällig ein Verzeichnis ist und der Nameshop
(/,ISDIR shop$/
) ist, wenn ja,rm
das Verzeichnis (system("rm -r -- /foo/bar/shop")
)
Sie müssen den Befehl als Benutzer ausführen, der über Schreibberechtigung für das Verzeichnis verfügt, /foo/bar
um Daten shop
aus dem Verzeichnis zu entfernen.
Wenn Sie auch -ing-Vorgänge überwachen möchten mv
, fügen Sie moved_to
auch „watch for event“ hinzu:
inotifywait -qme create,moved_to /foo/bar | \
awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'
Nur zur Kenntnis: Wenn Sie nach einer Datei und nicht einem Verzeichnis mit dem Namen suchen shop
:
inotifywait -qme create /foo/bar | \
awk '$NF == "shop" { system("rm -- /foo/bar/shop") }'
inotifywait -qme create,moved_to /foo/bar | \
awk '$NF == "shop" { system("rm -- /foo/bar/shop") }'
Antwort2
Um wörtlich auf die Frage zu antworten, ob man verhindern könne,Ordnereines bestimmten Namens, der erstellt werden soll.
touch shop
Sie können kein Verzeichnis erstellen, wenn eine Datei mit identischem Namen vorhanden ist
mkdir: cannot create directory ‘shop’: File exists
Antwort3
Wie wäre es mit der Entführung mkdir
eines Systemaufrufs mit LD_PRELOAD
...?
$ ls
test.c
$ cat test.c
#define _GNU_SOURCE
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dlfcn.h>
typedef int (*orig_mkdir_func_type)(const char *path, mode_t mode);
int mkdir(const char *path, mode_t mode) {
if(!strcmp(path, "shop")) return 1;
orig_mkdir_func_type orig_func;
orig_func = (orig_mkdir_func_type)dlsym(RTLD_NEXT, "mkdir");
return orig_func(path, mode);
}
$ gcc -shared -fPIC test.c -o test.so
$ LD_PRELOAD='./test.so' mkdir test
$ LD_PRELOAD='./test.so' mkdir shop
mkdir: cannot create directory ‘shop’: No such file or directory
$ ls
test test.c test.so
Beachten Sie, dass Sie in diesem Handler stattdessen die PID des Prozesses protokollieren können, der dieses Verzeichnis erstellen möchte:
$ cat test.c
#define _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dlfcn.h>
typedef int (*orig_mkdir_func_type)(const char *path, mode_t mode);
int mkdir(const char *path, mode_t mode) {
if(!strcmp(path, "shop")) {
FILE* fp = fopen("/tmp/log.txt", "w");
fprintf(fp, "PID of evil script: %d\n", (int)getpid());
fclose(fp);
}
orig_mkdir_func_type orig_func;
orig_func = (orig_mkdir_func_type)dlsym(RTLD_NEXT, "mkdir");
return orig_func(path, mode);
}
$ gcc -shared -fPIC test.c -o test.so
$ LD_PRELOAD='./test.so' mkdir shop
$ cat /tmp/log.txt
PID of evil script: 8706
Sie müssen dies im ~/.bashrc
Stammverzeichnis (oder bei demjenigen, der Ihre App ausführt) platzieren, um sicherzustellen, dass es verwendet wird:
export LD_PRELOAD=/path/to/test.so
Antwort4
Erstellen Sie einen symbolischen Link, der auf einen nicht vorhandenen Ort innerhalb eines nicht vorhandenen Verzeichnisses verweist. Dies hat einige interessante Auswirkungen:
$ ln -s non-existent/foobar foo
$ ls -ln
total 0
lrwxrwxrwx 1 1000 1000 19 Okt 4 17:17 foo -> non-existent/foobar
$ mkdir foo
mkdir: cannot create directory ‘foo’: File exists
$ cat foo
cat: foo: No such file or directory
$ echo foo > foo
zsh: no such file or directory: foo
- mkdir, link und andere schlagen mit
EEXIST
(Datei existiert) fehl. - Der Versuch, den Pfad zum Lesen, Schreiben oder Anhängen zu öffnen, schlägt mit der Meldung
ENOENT
„(Keine solche Datei oder kein solches Verzeichnis)“ fehl. - Die Verwendung von stat(2) (nicht lstat(2) oder stat(1)) auf den Standort schlägt ebenfalls fehl
ENOENT
. lstat gibt selbstverständlich die Informationen über den symbolischen Link zurück.
Dies hat gegenüber einigen anderen hier vorgeschlagenen Lösungen zwei Vorteile: (a) Sie müssen keinen Dienst ausführen, der die Erstellung des Verzeichnisses verfolgt, und (b) der Name scheint für die meisten Befehle nicht zu existieren.
Sie müssen es versuchen, aber ich vermute, dass Ihre Umschreiberegeln, egal welche, nicht lstat oder andere nicht dereferenzierende Befehle verwenden und deshalb fehlschlagen.