我可以防止创建具有特定名称的文件夹吗?


16

我正在使用LAMP Web应用程序,并且某个地方有一个计划的过程,该过程一直shop在网站的根目录中创建一个文件夹。每次出现这种情况都会导致与应用程序中的重写规则发生冲突,这不是很好。

在找到令人讨厌的脚本之前,是否有办法防止shop在根目录中创建任何名为文件夹的文件夹?我知道我可以更改文件夹的权限以防止更改其内容,但是我还没有找到一种方法来防止创建具有特定名称的文件夹。


4
要查明创建过程,可以启用auditing
安德鲁·亨利

Answers:


30

鉴于创建目录的用户具有足够的权限可以在父目录上进行写入,因此您不能这样做。

相反,您可以利用inotifyLinux内核提供的系统调用系列来监视给定目录中目录的创建(或可选地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") }'

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停止帮助ICE

1
这是一个聪明的小动作,不是很适合我的情况,但在某些情况下👍一个聪明的想法
安德鲁

1
@R ..有趣。我希望rename(2)它仍然可以工作,因为名称不是inode的一部分,但事实并非如此。快速的互联网搜索无法揭示原因。有什么提示吗?
domen

@domen:因为那是“不变”属性目的的一部分。我怀疑在实现级别上需要进行一些琐碎的额外工作才能阻止rename工作。
R .. GitHub停止帮助ICE

4

mkdirLD_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
这不应该让人失望,这是一个解决方案,也是一个不错的选择
2016年

4
它使用手提箱核弹打开一罐豆子。但是,至少他们会被煮熟……
与莫妮卡(Monica)

2
@cat:我不同意。LD_PRELOAD这样的黑客基本上总是错误的,除非您知道自己在做什么,否则它们会破坏您要替换的函数的异步信号安全性之类的属性,从而严重破坏您加载程序的程序。
R .. GitHub停止帮助ICE,2013年

1
另外,我觉得fopen应该有"a"代替"w",因此它可以保持以前的日志

2
如果错误的代码而不是通过libc直接调用syscall,这也将不起作用。或者,如果错误代码是静态链接的。
domen

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 '16

另外,为什么不告诉我们这与其他答案有何关系,而不是为什么决定发布?
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或其他非取消引用命令,从而使它们失败。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.