Чи можу я запобігти створенню папки певного імені?


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операції з відстеженням , додайте також слідкувати за 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
Крім того, якщо ви використовуєте inotifywaitдля цього, можливо також, що тригер також зможе впіймати процесps -ef
roaima

30

Відповісти буквально на підставі запитання про запобігання створенню папки певного імені.

touch shop

Ви не можете створити каталог, якщо існує файл з ідентичним іменем

mkdir: cannot create directory ‘shop’: File exists


6
Цього * може не вистачити *. mkdir може цього не робити, але це можна зробити. Хоча перша спроба, хоча.
coteyr

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

1
Це розумна маленька хитрість, не зовсім підходяща для моєї ситуації, але розумна ідея для певних обставин 👍
Андрій

1
@R .. цікаво. Я очікував, rename(2)що все ще працювати, оскільки ім'я не є частиною inode, але це не так. Швидкий пошук в Інтернеті не виявляє, чому. Якісь підказки?
domen

@domen: Тому що це частина мети атрибута "непорушний". Я підозрюю, що для запобігання renameроботі потрібна нетривіальна додаткова робота на рівні реалізації .
R .. GitHub СТОП ДОПОМОГАТИ ICE

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подібні хаки в основному завжди помиляються, і якщо ви не знаєте, чим займаєтесь, вони можуть погано порушити програму, яку ви завантажуєте, порушивши такі властивості, як безпека сигналу асинхроніки функції, яку ви замінюєте.
R .. GitHub СТОП ДОПОМОГАЙТЕ

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

2
Це також не буде працювати, якщо поганий код викликає syscall безпосередньо, а не через libc. Або якщо поганий код статично пов'язаний.
domen

3

(Прокоментував би відповідь Міаті, але не можу запам’ятати свій старий обліковий запис і не маю достатньої репутації в цьому новому ...)

Ви можете заблокувати створення, створивши файл, а потім змінивши його атрибути.

$ 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. lstat, звичайно, поверне інформацію про симпосилання.

Це має дві переваги перед іншими запропонованими тут рішеннями: (a) вам не потрібна служба, що відстежує створення каталогу, і (b) ім'я, як видається, не існує в більшості команд.

Вам доведеться зняти це, але я підозрюю, що які б правила перезапису у вас не були, вони не використовують lstat або інші команди, що не перенаправляють, що робить їх помилковими.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.