특정 이름의 폴더가 생성되는 것을 막을 수 있습니까?


16

LAMP 웹 앱에서 작업 중이며 shop사이트의 루트에 있는 폴더를 계속 만드는 예약 프로세스 가 있습니다. 이것이 나타날 때마다 앱의 다시 쓰기 규칙과 충돌이 발생하지만 좋지 않습니다.

문제가있는 스크립트를 찾을 때까지 shop루트에 폴더 가 만들어 지지 않도록하는 방법이 있습니까? 폴더의 내용이 변경되지 않도록 폴더에 대한 권한을 변경할 수 있지만 특정 이름의 폴더가 생성되는 것을 방지하는 방법을 찾지 못했습니다.


4
작성중인 작업을 찾으려면 감사사용 가능하게 할 수 있습니다 .
Andrew Henle

답변:


30

디렉토리를 작성하는 사용자에게 상위 디렉토리에 쓸 수있는 충분한 권한이 있으면 부여 할 수 없습니다.

대신 inotifyLinux 커널이 제공하는 시스템 호출 제품군을 활용하여 디렉토리가 작성되거나 선택적으로 -ed 인 경우 지정된 디렉토리에서 mv디렉토리 의 작성 (및 선택적으로 -ing) 을 감시 할 수 있습니다.shopmvrm

이 경우 필요한 사용자 공간 프로그램은 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 중지 지원 얼음

1
이것은 현명한 작은 트릭입니다. 내 상황에는 맞지 않지만 특정 상황에 대한 영리한 아이디어 👍
Andrew

1
@R .. 흥미로운. rename(2)name은 inode의 일부가 아니기 때문에 여전히 작동 할 것으로 예상 했지만 그렇지 않습니다. 빠른 인터넷 검색은 이유를 밝히지 않습니다. 힌트가 있습니까?
domen

@domen : "불변"속성의 목적의 일부이기 때문입니다. 작동하지 않도록 구현 수준에서 사소한 추가 작업이 필요하다고 생각합니다 rename.
R .. GitHub 중지 지원 얼음

4

mkdirsyscall을 하이재킹하는 것은 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

2
이것은 downvote를 가져서는 안되며, 해결책이자 좋은 것입니다.
cat

4
콩가루를 열기 위해 여행 가방 핵무기를 사용하고 있습니다. 하지만, 이봐 적어도 그들은 ... 요리됩니다
모니카와 밝기 경주

2
@cat : 동의하지 않습니다. LD_PRELOAD이와 같은 해킹은 기본적으로 항상 잘못이며, 수행중인 작업을 알지 못하면 대체하는 함수의 비동기 신호 안전과 같은 속성을 차단하여로드하는 프로그램을 심하게 손상 시킬 수 있습니다 .
R .. GitHub 중지 지원 얼음

1
또한, 나는 생각 fopen해야한다 "a"대신 "w"이 이전 로그를 보존 할 수 있도록,
고양이

2
잘못된 코드가 libc를 통하지 않고 syscall을 직접 호출하는 경우에도 작동하지 않습니다. 또는 잘못된 코드가 정적으로 링크 된 경우.
domen

3

(Miati의 답변에 대해 언급했지만 내 오래된 계정을 기억할 수 없으며이 새로운 계정에 대한 명성이 충분하지 않습니다 ...)

파일을 작성한 다음 파일 속성을 변경하여 작성을 차단할 수 있습니다.

$ sudo touch shop
$ sudo chattr +i shop

그런 다음 사용자가 루트가 되더라도 해당 파일로 작업을 시도하면 차단됩니다.

$ 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 나 다른 비 참조 명령을 사용하지 않아서 실패한다고 생각합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.