Могу ли я запретить создание папки с определенным именем?

Могу ли я запретить создание папки с определенным именем?

Я работаю над веб-приложением LAMP, и где-то есть запланированный процесс, который постоянно создает папку, называемую shopв корне сайта. Каждый раз, когда это появляется, это вызывает конфликты с правилами перезаписи в приложении, что нехорошо.

Пока я не найду скрипт, вызывающий проблемы, есть ли способ предотвратить shopсоздание любой папки, которая называется в корне? Я знаю, что я могу изменить разрешения для папки, чтобы предотвратить изменение ее содержимого, но я не нашел способа предотвратить создание папки с определенным именем.

решение1

Это невозможно, поскольку пользователь, создавший каталог, имеет достаточные права на запись в родительский каталог.

Вместо этого вы можете использовать inotifyсемейство системных вызовов, предоставляемых ядром Linux, для отслеживания создания (и, при необходимости, mv-редактирования) каталога shopв указанном каталоге, если каталог создан (или, при необходимости, mv-редактирован) .rm

В этом случае вам понадобится следующая программа пользовательского пространства inotifywait(входит в комплект inotify-tools, при необходимости сначала установите ее).


Предполагая, что каталог shopбудет находиться в /foo/barкаталоге, давайте установим мониторинг для /foo/bar/shopего создания и rmнемедленно, если он создан:

inotifywait -qme create /foo/bar | \
             awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'
  • inotifywait -qme create /foo/barотслеживает /foo/barкаталог на предмет любого файла/каталога, который может быть создан, т.е. отслеживает любое createсобытие

  • Если файл создан, awk '/,ISDIR shop$/ { system("rm -r -- /foo/bar/shop") }'проверяет, является ли он каталогом и имеет ли его имя shop( /,ISDIR shop$/), если да, то rmкаталогом ( system("rm -r -- /foo/bar/shop"))

/foo/barДля удаления shopиз каталога команду необходимо выполнить от имени пользователя, имеющего разрешение на запись в каталог .


Если вы также хотите отслеживать mvоперации -ing, добавьте moved_toтакже наблюдение за событием:

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

Обратите внимание, если вы ищете файл, а не каталог, с именем 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") }'

решение2

Чтобы ответить буквально, основываясь на вопросе предотвращенияпапкаопределенного имени, которое будет создано.

touch shop

Вы не можете создать каталог, если файл с таким же именем уже существует.

mkdir: cannot create directory ‘shop’: File exists

решение3

А как насчет перехвата mkdirсистемного вызова с помощью 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

Обратите внимание, что внутри этого обработчика вы можете вместо этого регистрировать PID процесса, который хочет создать этот каталог:

$ 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

Вам необходимо поместить это в ~/.bashrcroot (или в тот, кто запускает ваше приложение), чтобы гарантировать, что это будет использоваться:

export LD_PRELOAD=/path/to/test.so

решение4

Создайте символическую ссылку, указывающую на несуществующее местоположение внутри несуществующего каталога. Это имеет некоторые забавные последствия:

$ 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 и другие завершатся ошибкой EEXIST(Файл существует).
  2. Попытка открыть путь для чтения, записи или добавления завершится ошибкой ENOENT(Нет такого файла или каталога)
  3. Использование stat(2) (а не lstat(2) или stat(1)) для определения местоположения также не даст результата ENOENT. lstat, конечно же, вернет информацию о символической ссылке.

Это имеет два преимущества по сравнению с некоторыми другими предлагаемыми здесь решениями: (а) вам не нужна запущенная служба, отслеживающая создание каталога, и (б) для большинства команд имя кажется несуществующим.

Вам придется попробовать, но я подозреваю, что какие бы правила перезаписи у вас ни были, они не используют lstat или другие команды, не допускающие разыменования, что приводит к их сбою.

Связанный контент