Answers:
鉴于创建目录的用户具有足够的权限可以在父目录上进行写入,因此您不能这样做。
相反,您可以利用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操作,请同时添加监视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") }'
inotifywait
做到这一点的也有可能是触发也许还能赶上过程用ps -ef
从字面上回答是基于防止创建特定名称的文件夹的问题。
touch shop
如果存在具有相同名称的文件,则无法创建目录
mkdir: cannot create directory ‘shop’: File exists
chattr +i shop
使其不可变。在删除不可变标志之前,它甚至无法重命名/删除。
rename(2)
它仍然可以工作,因为名称不是inode的一部分,但事实并非如此。快速的互联网搜索无法揭示原因。有什么提示吗?
rename
工作。
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
root用户(或运行应用程序的任何人)中,以确保将其使用:
export LD_PRELOAD=/path/to/test.so
LD_PRELOAD
这样的黑客基本上总是错误的,除非您知道自己在做什么,否则它们会破坏您要替换的函数的异步信号安全性之类的属性,从而严重破坏您加载程序的程序。
fopen
应该有"a"
代替"w"
,因此它可以保持以前的日志
(会对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
创建指向不存在目录内不存在位置的符号链接。这具有一些有趣的含义:
$ 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
EEXIST
(文件存在)。ENOENT
(没有此类文件或目录)ENOENT
。lstat当然会返回有关符号链接的信息。与这里提出的其他一些解决方案相比,这具有两个优点:(a)您不需要运行可跟踪目录创建的服务,并且(b)大多数命令似乎都没有该名称。
您将不得不尝试一下,但是我怀疑无论您拥有什么重写规则,它们都不会使用lstat或其他非取消引用命令,从而使它们失败。