我正在开发一个 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 或其他非取消引用命令,从而导致它们失败。