Kann ich verhindern, dass ein Ordner mit einem bestimmten Namen erstellt wird?

16

Ich arbeite an einer LAMP-Web-App und es gibt irgendwo einen geplanten Prozess, bei dem ständig ein Ordner erstellt wird, der shopim Stammverzeichnis der Site aufgerufen wird . 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 eines Ordners shopim Stammverzeichnis zu verhindern, bis ich das fehlerhafte Skript gefunden habe ? Ich weiß, dass ich die Berechtigungen für einen Ordner ändern kann, um zu verhindern, dass der Inhalt geändert wird, aber ich habe keine Möglichkeit gefunden, die Erstellung eines Ordners mit einem bestimmten Namen zu verhindern.

Andrew
quelle
4
Um herauszufinden, was beim Erstellen geschieht, können Sie die Überwachung aktivieren .
Andrew Henle

Antworten:

30

Dies ist nicht möglich, da der Benutzer, der das Verzeichnis erstellt, über ausreichende Schreibrechte für das übergeordnete Verzeichnis verfügt.

Sie können stattdessen die inotifyFamilie der vom Linux-Kernel bereitgestellten Systemaufrufe nutzen, um nach der Erstellung (und optionalen mvAngabe) eines Verzeichnisses shopin dem angegebenen Verzeichnis zu mvsuchen , sofern das Verzeichnis erstellt wurde (oder optional -ed ist) rm.

Das Userspace-Programm, das Sie in diesem Fall benötigen, ist inotifywait(im Lieferumfang enthalten inotify-tools, installieren Sie es bei Bedarf zuerst).


Angenommen, das Verzeichnis shopbefindet sich im /foo/barVerzeichnis, legen wir eine Überwachung für die /foo/bar/shopErstellung fest, und zwar rmsofort, wenn sie erstellt wird:

inotifywait -qme create /foo/bar | \
             awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'
  • inotifywait -qme create /foo/barÜberwachungsverzeichnis /foo/barfür jede Datei / jedes Verzeichnis, das erstellt werden könnte, dh Überwachung für jedes createEreignis

  • Wenn erstellt, awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'überprüft , ob die Datei ein Verzeichnis sein geschieht und der Name ist shop( /,ISDIR shop$/), wenn so rmdas Verzeichnis ( system("rm -r -- /foo/bar/shop"))

Sie müssen den Befehl als Benutzer ausführen, der über die Schreibberechtigung /foo/barfür shopdas Verzeichnis verfügt, um ihn aus dem Verzeichnis zu entfernen .


Wenn Sie auch mv-ing-Vorgänge überwachen möchten , fügen Sie auch watch for moved_toevent hinzu:

inotifywait -qme create,moved_to /foo/bar | \
             awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'

Beachten Sie, wenn Sie nach einer Datei suchen, nicht nach einem Verzeichnis mit dem Namen 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") }'
heemayl
quelle
2
Wenn Sie inotifywaitdies verwenden, ist es außerdem möglich, dass der Auslöser den Prozess auch mitps -ef
roaima
30

Um buchstäblich auf die Frage zu antworten, ob ein Ordner mit einem bestimmten Namen nicht erstellt werden soll.

touch shop

Sie können kein Verzeichnis erstellen, wenn eine Datei mit demselben Namen vorhanden ist

mkdir: cannot create directory ‘shop’: File exists

Miati
quelle
6
Dies kann nicht genug sein. mkdir tut es vielleicht nicht, aber es kann getan werden. Es ist jedoch ein guter erster Versuch.
Coteyr
9
Verwenden Sie chattr +i shopauf Linux-Systemen, um es unveränderlich zu machen. Bis das unveränderliche Flag entfernt wird, kann es nicht einmal umbenannt / gelöscht werden.
R ..
1
Dies ist ein kluger kleiner Trick, nicht ganz richtig für meine Situation, aber eine kluge Idee für bestimmte Umstände 👍
Andrew
1
@ R .. interessant. Ich habe erwartet rename(2), dass es immer noch funktioniert, da name kein Teil von inode ist, aber es ist nicht so. Schnelle Internetsuche verrät nicht warum. Irgendwelche Hinweise?
Domen
@domen: Weil das Teil des Zwecks des Attributs "unveränderlich" ist. Ich vermute, dass es nicht trivialer zusätzlicher Arbeit auf der Implementierungsebene bedarf, um das Funktionieren zu verhindern rename.
R ..
4

Was ist mit der Entführung von mkdirsyscall 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 die PID des Prozesses protokollieren können, der stattdessen 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 in ~/.bashrcroot platzieren (oder wer auch immer Ihre App ausführt), um sicherzustellen, dass dies verwendet wird:

export LD_PRELOAD=/path/to/test.so
Nykakin
quelle
2
dies kein Downvote haben sollte, ist es eine Lösung und eine gute
Katze
4
Es benutzt eine Koffernuke, um eine Dose Bohnen zu öffnen. Aber hey, zumindest werden sie gekocht ...
Leichtigkeit Rennen mit Monica
2
@cat: Ich stimme nicht zu. LD_PRELOADHacks wie diese sind im Grunde immer falsch, und wenn Sie wissen , was Sie tun, können sie schlecht das Programm , das Sie sie in laden , indem Sie Eigenschaften wie der Asynchron-Signal-Sicherheit der Funktion brechen Sie ersetzen brechen.
R ..
1
Außerdem glaube ich , fopensollte "a"statt "w", so dass es frühere Protokolle bewahren kann
Katze
2
Dies funktioniert auch nicht, wenn fehlerhafter Code den Syscall direkt aufruft, nicht über libc. Oder wenn der fehlerhafte Code statisch verknüpft ist.
Domen
3

(Hätte die Antwort von Miati kommentiert, kann mich aber nicht an meinen alten Account erinnern und habe in diesem neuen nicht genug Ansehen ...)

Sie können die Erstellung blockieren, indem Sie eine Datei erstellen und anschließend die Dateiattribute ändern.

$ sudo touch shop
$ sudo chattr +i shop

Jeder Versuch, irgendetwas mit dieser Datei zu tun, wird blockiert - auch wenn der Benutzer root wird.

$ rm shop
rm: remove write-protected regular empty file ‘shop’? y
rm: cannot remove ‘shop’: Operation not permitted
$ sudo rm shop
rm: cannot remove ‘shop’: Operation not permitted
N. Clements
quelle
2
Wenn Sie den Namen / die E-Mail-Adresse Ihres alten Kontos kennen, können Sie über das Kontaktformular, das unten auf jeder Seite verlinkt ist, einen Konto-Zusammenschluss anfordern .
wizzwizz4
Sagen Sie uns auch, warum dies nicht mit der anderen Antwort zusammenhängt, anstatt warum Sie sich entschieden haben, etwas zu posten.
Jpaugh
2

Erstellen Sie einen Symlink, der auf einen nicht vorhandenen Speicherort in einem nicht vorhandenen Verzeichnis verweist. Dies hat einige spaßige 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
  1. mkdir, link und andere schlagen fehl mit EEXIST(Datei existiert).
  2. Der Versuch, den Pfad zum Lesen, Schreiben oder Anhängen zu öffnen, schlägt mit ENOENT(Keine solche Datei oder kein solches Verzeichnis) fehl.
  3. Die Verwendung von stat (2) (nicht lstat (2) oder stat (1)) an der Position schlägt ebenfalls mit fehl ENOENT. lstat wird selbstverständlich die Informationen über den Symlink zurücksenden.

Dies hat zwei Vorteile gegenüber einigen anderen hier vorgeschlagenen Lösungen: (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 werden es versuchen müssen, aber ich vermute, dass die Umschreiberegeln, die Sie haben, weder lstat noch andere nicht dereferenzierende Befehle verwenden, was dazu führt, dass sie fehlschlagen.

Jonas Schäfer
quelle