
我正在開發一個 LAMP Web 應用程序,並且在某個地方有一個預定的進程,該進程會不斷創建一個shop
在站點根目錄中調用的資料夾。每次出現這種情況都會導致與應用程式中的重寫規則發生衝突,這不好。
在找到有問題的腳本之前,有沒有辦法阻止shop
在根目錄中建立任何名為的資料夾?我知道我可以更改資料夾的權限以防止其內容被更改,但我還沒有找到一種方法來防止建立特定名稱的資料夾。
答案1
你不能,因為建立目錄的使用者有足夠的權限在父目錄上寫入。
相反,您可以利用inotify
Linux 核心提供的系統呼叫系列來監視給定目錄中mv
目錄的建立(以及可選的 -ing) ,如果已建立(或可選的-ed)目錄。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
您需要將其放置在~/.bashrc
根目錄(或運行您的應用程式的任何人)中,以確保使用它:
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
- mkdir、連結和其他文件將失敗並顯示
EEXIST
(文件存在)。 - 嘗試開啟路徑進行讀取、寫入或追加將失敗
ENOENT
(沒有此類檔案或目錄) - 在該位置上使用 stat(2)(不是 lstat(2) 或 stat(1))也會失敗,並顯示
ENOENT
. lstat 當然會傳回有關符號連結的資訊。
與此處提出的其他一些解決方案相比,這有兩個優點:(a) 您不需要執行追蹤目錄建立的服務;(b) 對於大多數命令來說,該名稱似乎不存在。
您必須嘗試一下,但我懷疑無論您有什麼重寫規則,它們都不使用 lstat 或其他非取消引用命令,從而導致它們失敗。