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


16

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

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


4
Чтобы узнать, что делает создание, вы можете включить аудит .
Эндрю Хенле

Ответы:


30

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

Вместо этого вы можете использовать inotifyсемейство системных вызовов, предоставляемых ядром Linux, для наблюдения за созданием (и необязательно mv-ing) каталога shopв данном каталоге, если он создан (или необязательно mv-ed), 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, добавьте watch for moved_toevent:

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
Более того, если вы используете inotifywaitэто, возможно, что триггер также сможет перехватить процесс с помощьюps -ef
roaima

30

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

touch shop

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

mkdir: cannot create directory ‘shop’: File exists


6
Это * может * не быть достаточно. Mkdir может не делать этого, но это может быть сделано. Хотя это хорошая первая попытка.
Котейр

9
В системах Linux используйте его, chattr +i shopчтобы сделать его неизменным. Пока неизменный флаг не будет удален, его даже нельзя переименовать / удалить.
R .. GitHub ОСТАНОВИТЬСЯ, ПОМОГАЯ ЛЬДУ

1
Это умная маленькая хитрость, не совсем подходящая для моей ситуации, но умная идея для определенных обстоятельств 👍
Эндрю

1
@R .. интересно. Я ожидал, rename(2)что все еще будет работать, поскольку name не является частью inode, но это не так. Быстрый поиск в интернете не показывает, почему. Есть намеки?
Домен

@domen: Потому что это является частью цели атрибута «неизменный». Я подозреваю, что для предотвращения renameработы требуется нетривиальная дополнительная работа на уровне реализации .
R .. GitHub ОСТАНОВИТЬ ЛЬДА

4

Как насчет угона 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

2
у этого не должно быть отрицательного голоса, это - решение и хорошее
кошка

4
Он использует ядерный чемоданчик, чтобы открыть банку бобов. Но, по крайней мере, они будут приготовлены ...
Легкость Гонки с Моникой

2
@cat: я не согласен. LD_PRELOADподобные хаки, в основном, всегда неправильны, и если вы не знаете, что делаете, они могут сильно сломать программу, в которую вы их загружаете, нарушив свойства, такие как async-signal-safety заменяемой функции.
R .. GitHub ОСТАНОВИТЬ ЛЬДА

1
Кроме того, я думаю, что fopenдолжен иметь "a"вместо "w", чтобы он мог сохранить предыдущие журналы
кошка

2
Это также не будет работать, если плохой код вызывает системный вызов напрямую, а не через libc. Или если плохой код статически связан.
Домен

3

(Я бы прокомментировал ответ Miati, но не могу вспомнить мой старый аккаунт и у меня недостаточно репутации на этом новом ...)

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

$ sudo touch shop
$ sudo chattr +i shop

Тогда любая попытка что-либо сделать с этим файлом будет заблокирована, даже если пользователь станет пользователем root.

$ 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

2
Если вам известно имя / адрес электронной почты вашей старой учетной записи, вы можете запросить слияние учетной записи из контактной формы, расположенной внизу каждой страницы .
wizzwizz4

Кроме того, почему бы не рассказать нам, как это связано с другим ответом, а не почему вы решили опубликовать?
jpaugh

2

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

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

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.