inotifywait에 대한 잠재적 해결 방법이 NUL로 구분된 출력을 생성하지 못합니다.

inotifywait에 대한 잠재적 해결 방법이 NUL로 구분된 출력을 생성하지 못합니다.

현재 다음을 사용하는 bash 스크립트를 작성 중입니다.inotifywait사용자가 제공한 파일 및 디렉터리 목록에 대해 특정 작업을 수행합니다.

그게 내 관심을 끌었어많은 쉘 도구와 달리 inotifywait사용할 수 없습니다 \0.주입 공격 가능성특별히 고안된 법적 파일 이름(줄바꿈 포함)을 갖습니다.

내 스크립트가 불필요한 취약점을 유발하지 않도록 이 문제를 해결하고 싶습니다. 내가하는 방법은 다음과 같습니다.

  • inotifywaitwatch에 전달된 모든 파일/경로 의 후행 백슬래시가 제거되었는지 확인하세요 .
  • 다음과 같이 출력을 생성 inotifywait하도록 출력 형식을 지정합니다 .--format "%e %w%f//"
    • <EVENT LIST> <FILE PATH>//
  • 줄 끝에서 발견된 inotifywait모든 항목을 sed로 파이프 출력합니다.//\0
  • Bash while read루프를 사용하여 \0구분된 레코드 읽기
  • 이는 첫 번째 레코드 이후의 모든 후속 레코드에 추가 선행 개행 문자가 있음을 의미합니다. 이건 벗겨진거네
  • 그런 다음 각 레코드는 첫 번째 공백에서 분할될 수 있습니다. 공백이 이벤트 목록(inotifywait에 따라 쉼표로 구분됨)이 되기 전, 공백이 이벤트와 연결된 전체 경로 이름 이후
#!/bin/bash

shopt -s extglob
watchlist=("${@}")

# Remove trailing slashes from any watchlist elements
watchlist=("${watchlist[@]%%+(/)}")

# Reduce multiple consecutive slashes to singles as per @meuh
watchlist=("${watchlist[@]//+(\/)/\/}")

printf -vnewline "\n"

inotifywait -qrm "${watchlist[@]}" --format "%e %w%f//" | \
    sed -u 's%//$%\x00%' | \
    while IFS= read -r -d '' line; do
        line="${line#${newline}}"
        events="${line%% *}"
        filepath="${line#* }"
        printf "events=%s\nfilepath=%q\n" "$events" "$filepath"
    done

내가 아는 한, 이것은 공백, 개행, 따옴표 등 흥미로운 문자가 포함된 파일/경로 이름을 처리합니다. 그러나 이것은 다소 촌스러운 패치워크처럼 보입니다.

이 질문의 목적에 따라 ${watchlist[]}배열은 명령줄 인수에서 복사되었지만 배열은 다른 방식으로 구성될 수 있으며 "흥미로운" 문자가 포함될 수 있습니다.

  1. 이를 깨뜨릴 수 있는 악의적인 경로가 있나요? 특정 이벤트에 대해 $events및 변수의 내용이 올바르지 않은 경우에도 마찬가지입니까 ?$filepath

  2. 이것이 방수라면 더 깨끗한 방법이 있습니까?

나는 쉽게 글을 쓸 수 있다는 것을 알고 있습니다.inotify_add_watch()이 문제를 해결하려면 Friend 프로그램을 호출하세요 . 하지만 지금은 다른 종속성으로 인해 bash에서 작업하고 있습니다.


나는 이것을 여기에 게시할지, codereview.SE 또는 심지어 메인 so.SE에 게시할지에 대해 갈등을 겪었습니다.

답변1

가지다십자가NUL로 구분된 출력이 지원되며 다음과 같이 사용할 수 있습니다.

#!/bin/bash

shopt -s extglob
watchlist=("${@}")

# Remove trailing slashes from any watchlist elements
watchlist=("${watchlist[@]%%+(/)}")

printf -vnewline "\n"

inotifywait -qrm "${watchlist[@]}" --format "%e %w%f%0" | \
while IFS= read -r -d '' line; do
    events="${line%% *}"
    filepath="${line#* }"
    printf "events=%s\nfilepath=%q\n" "$events" "$filepath"
done

--format이 사용될 때 이 버전은 기본적으로 줄바꿈을 추가하지 않습니다.

답변2

watchlist교체하려면 정리가 필요합니다 . 다음과 같은 이름의 디렉토리를 고려하십시오 ( 여기서 개행 문자는 어디에 있습니까).///\nabc\n

$ mkdir t
$ mkdir t/$'\nabc'
$ touch t/$'\nabc'/x

디렉터리를 살펴보면 t//$'\nabc'줄 끝에 가짜 출력이 표시됩니다.//

$ inotifywait -m -r t//$'\nabc' --format "%e %w%f//" 
Setting up watches.  Beware: since -r was given, this may take a while!
Watches established.
OPEN t//
abc/x//
ATTRIB t//
abc/x//
CLOSE_WRITE,CLOSE t//
abc/x//

얻는 -c대신에 참고하세요.--format데이터 세트스타일 출력은 파일 이름을 줄 바꿈으로 큰따옴표로 묶었지만 구문 분석하기가 더 어렵습니다. 제 경우에는 위 예의 코어 덤프입니다.

-c합계 출력 예 touch t/$'new\nfile':

t/,CREATE,"new
file"

관련 정보