불변 속성 세트가있는 파일을 검색하는 방법은 무엇입니까? 이나 유사한 옵션을 찾을 수 없습니다 .

구성 감사의 이유로 변경 불가능한 속성이 설정된 파일을 통해 ext3 파일 시스템을 검색 할 수 있기를 원합니다 (via chattr +i). find이 작업을 수행 하는 데 필요한 옵션 이나 유사한 옵션을 찾을 수 없습니다 . 이 시점에서 lsattr각 디렉토리의 출력 을 구문 분석 하기 위해 자체 스크립트를 작성해야합니다 . 더 나은 방법을 제공하는 표준 유틸리티가 있습니까?



답변

grep명령을 lsattr명령 으로 파이핑하여 부분적으로 수행 할 수 있습니다 .

lsattr -R | grep +i

그러나, 나는 당신이 전체 말할 때 믿는 ext3검색을 포함 할 수 파일 시스템 /proc, /dev및보고하면 그냥 원하는 몇 가지 오류가 무시하는 다른 디렉토리를. 다음과 같이 명령을 실행할 수 있습니다.

lsattr -R 2>/dev/null | grep -- "-i-"

의 PCRE 기능을 grep사용 grep하여 “-i-“와보다 명확하게 일치시켜 조금 더 엄격하게 만들 수 있습니다 .

lsattr -R 2>/dev/null | grep -P "(?<=-)i(?=-)"

그러면 다음과 같은 상황에서 작동합니다.

$ lsattr -R 2>/dev/null afile | grep -P "(?<=-)i(?=-)"
----i--------e-- afile

그러나 불완전하다. 불변 플래그 주위에 추가 속성이 활성화되어 있으면 일치하지 않으며, 위와 같은 패턴과 이름이 일치하는 파일에 속합니다.

$ lsattr -R 2>/dev/null afile* | grep -P "(?<=-)i(?=-)"
----i--------e-- afile
-------------e-- afile-i-am

다음과 같이 패턴을 조금 더 강화할 수 있습니다.

$ lsattr -a -R 2>/dev/null afile* | grep -P "(?<=-)i(?=-).* "
----i--------e-- afile

그러나 여전히 약간 깨지기 쉽고 파일 시스템 내의 파일에 따라 추가 조정이 필요합니다. 하지 언급에 관해서는 @StephaneChazeles은 이 위의 패턴을 우회하는 파일 이름으로 줄 바꿈을 포함하여 비교적 쉽게 gamed 될 수 있다는 의견에 언급했다 grep.

참고 문헌

https://groups.google.com/forum/#!topic/alt.os.linux/LkatROg2SlM


답변

스크립트의 목적이 감사라는 점을 고려하면 임의의 파일 이름 (예 : 줄 바꾸기 포함 이름)을 올바르게 처리하는 것이 특히 중요합니다. 이 lsattr경우 출력 lsattr이 모호 할 수 있으므로 여러 파일에서 동시에 사용할 수 없습니다.

한 번에 하나의 파일로 반복해서 find호출 할 수 있습니다 lsattr. 그래도 꽤 느릴 것입니다.

find / -xdev -exec sh -c '
  for i do
     attrs=$(lsattr -d "$i"); attrs=${attrs%% *}
     case $attrs in
       *i*) printf "%s\0" "$i";;
     esac
  done' sh {} +

Perl, Python 또는 Ruby와 같이 덜 까다로운 언어를 사용하고 lsattr직접 작업하는 것이 좋습니다 . ioctl syscall lsattr을 발행 FS_IOC_GETFLAGS하고 파일의 inode 플래그를 검색하여 작동합니다 . 다음은 Python 개념 증명입니다.

#!/usr/bin/env python2
import array, fcntl, os, sys
FS_IOC_GETFLAGS = 0x80086601
EXT3_IMMUTABLE_FL = 0x00000010
count = 0
def check(filename):
    fd = os.open(filename, os.O_RDONLY)
    a = array.array('L', [0])
    fcntl.ioctl(fd, FS_IOC_GETFLAGS, a, True)
    if a[0] & EXT3_IMMUTABLE_FL:
        sys.stdout.write(filename + '\0')
        global count
        count += 1
    os.close(fd)
for x in sys.argv[1:]:
    for (dirpath, dirnames, filenames) in os.walk(x):
        for name in dirnames + filenames:
            check(os.path.join(dirpath, name))
if count != 0: exit(1)


답변

임의의 파일 이름 (줄 바꾸기 문자가 포함 된 파일 이름 포함)을 처리하기 위해 일반적인 속임수 는에서 .//.대신 파일을 찾는 것입니다 .. 때문에 //디렉토리 트리를 통과하는 동안 일반적으로 발생할 수 없습니다, 당신이 확신하는 //것을 알리는에서 새 파일 이름의 시작 find(또는 여기 lsattr -R) 출력.

lsattr -R .//. | awk '
  function process() {
    i = index(record, " ")
    if (i && index(substr(record,1,i), "i"))
      print substr(record, i+4)
  }
  {
    if (/\/\//) {
      process()
      record=$0
    } else {
      record = record "\n" $0
    }
  }
  END{process()}'

출력은 여전히 ​​줄 바꿈으로 구분됩니다. 사후 처리가 필요한 경우이를 조정해야합니다. 예를 들어, -v ORS='\0'GNU를에 공급할 수 있도록를 추가 할 수 있습니다 xargs -r0.

또한 lsattr -R(적어도 1.42.13) 경로가 PATH_MAX (보통 4096) 보다 큰 파일의 플래그를보고 할 수 없으므로 누군가 부모 디렉토리 (또는 경로 구성 요소로 이동하는 경로 구성 요소)를 이동하여 변경 불가능한 파일을 숨길 수 있습니다 그것은 매우 깊은 디렉토리에 있습니다.

해결 방법은 다음 find과 함께 사용하는 것 입니다 -execdir.

find . -execdir sh -c '
  a=$(lsattr -d "$1") &&
    case ${a%% *} in
      (*i*) ;;
      (*) false
    esac' sh {} \; -print0

이제와 -print0, 후 처리 가능한, 그러나 당신이 그 경로가 무엇보다 큰 파일 경로에있는 모든 시스템 호출주의 할하려는 경우 PATH_MAX가 여전히 실패 및 디렉토리 구성 요소가 간격으로 이름이 변경 될 수도 있습니다.

다른 사람이 쓸 수있는 디렉토리 트리에 대한 신뢰할 수있는 보고서를 얻으려면 lsattr언급해야 할 명령 자체에 몇 가지 문제가 더 있습니다 .

  • 이 방법 lsattr -R .은 디렉토리 트리를 통과하며 경쟁 조건에 따라 달라질 수 있습니다. .적절한 시점에 일부 디렉토리를 심볼릭 링크로 교체하여 라우팅 된 디렉토리 트리 외부의 디렉토리로 내려갈 수 있습니다 .
  • 심지어 lsattr -d file경쟁 조건이 있습니다. 이러한 속성은 일반 파일 또는 디렉토리에만 적용됩니다. 그래서 lsattr않는 lstat()파일이 올바른 유형이며 다음 않는다는 것을 확인하기 위해 먼저 open()다음 ioctl()속성을 검색 할 수 있습니다. 그러나 (또는 O_NOCTTY) open()없이 호출합니다 O_NOFOLLOW. 예를 들어 및 사이에 file있는 심볼릭 링크로 대체 되어 시스템이 재부팅 될 수 있습니다. 그것은 어떻게해야 그 다음 , 그리고 여기에 경쟁 조건을 피하기 위해./dev/watchdoglstat()open()open(O_PATH|O_NOFOLLOW)fstat()openat()ioctl()

답변

Ramesh, slm 및 Stéphane에게 올바른 방향으로 나를 가리켜 주셔서 감사합니다 (에 대한 -R스위치 가 누락되었습니다 lsattr). 불행히도, 지금까지 답변 중 어느 것도 나를 위해 올바르게 작동하지 않았습니다.

나는 다음을 생각해 냈다.

lsattr -aR .//. | sed -rn '/i.+\.\/\/\./s/\.\/\///p'

이렇게하면 파일이 변경되지 않은 경우 파일을 변경할 수없는 것처럼 보이게하는 데 사용되는 줄 바꿈을 방지 할 수 있습니다. 변경 불가능으로 설정되고 파일 이름에 줄 바꿈이있는 파일은 보호 하지 않습니다 . 그러나 그러한 파일은 루트로 그렇게 만들어야하므로, 해당 파일이 내 사용 사례를 위해 파일 시스템에 존재하지 않는다고 확신 할 수 있습니다. (이 방법은 루트 사용자가 손상된 경우 침입 탐지에 적합하지 않지만 lsattr동일한 루트 사용자가 소유 한 동일한 시스템 유틸리티를 사용하지 않습니다 .)


답변

사용 find -exec의 출력을 구문 분석, 너무 느린 것은 lsattr입니다 유사의에 신뢰할 수없는ls 에서 파이썬을 사용하여, 질 의해 답변 에 대한 상수를 선택하는 데 필요한 ioctl파이썬 인터프리터는 32 비트 또는 64 비트인지에 따라 …

C ++은 스크립팅 언어만큼 나쁘지는 않습니다. 보너스로 C 프리 프로세서의 모든 기능을 갖춘 시스템 C 헤더에 액세스 할 수 있습니다.

다음 프로그램은 하나의 파일 시스템 내에있는 불변 파일을 검색합니다. 즉, 마운트 지점을 절대로 넘지 않습니다. 필요에 따라 마운트 포인트를 건너는 겉보기 트리를 검색하려면 호출 FTW_MOUNT에서 플래그를 제거 nftw하십시오. 또한 심볼릭 링크를 따르지 않습니다. 이를 따르려면 FTW_PHYS플래그를 제거하십시오 .

#define _FILE_OFFSET_BITS 64
#include <iostream>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/fs.h>
#include <sys/stat.h>
#include <ftw.h>

bool isImmutable(const char* path)
{
    static const int EXT3_IMMUTABLE_FLAG=0x10;

    const int fd=open(path,O_RDONLY|O_NONBLOCK|O_LARGEFILE);
    if(fd<=0)
    {
        perror(("Failed to open file \""+std::string(path)+"\"").c_str());
        return false;
    }
    unsigned long attrs;
    if(ioctl(fd,FS_IOC_GETFLAGS,&attrs)==-1)
    {
        perror(("Failed to get flags for file \""+std::string(path)+"\"").c_str());
        close(fd);
        return false;
    }
    close(fd);
    return attrs & EXT3_IMMUTABLE_FLAG;
}

int processPath(const char* path, const struct stat* info, int type, FTW* ftwbuf)
{
    switch(type)
    {
    case FTW_DNR:
        std::cerr << "Failed to read directory: " << path << "\n";
        return 0;
    case FTW_F:
        if(isImmutable(path))
            std::cout << path << '\n';
        return 0;
    }
    return 0;
}

int main(int argc, char** argv)
{
    if(argc!=2)
    {
        std::cerr << "Usage: " << argv[0] << " dir\n";
        return 1;
    }
    static const int maxOpenFDs=15;
    if(nftw(argv[1],processPath,maxOpenFDs,FTW_PHYS|FTW_MOUNT))
    {
        perror("nftw failed");
        return 1;
    }
}


답변

출력을 grep에 파이핑하는 대신 awk를 사용하여 출력의 첫 번째 필드에서 ‘i’만 일치시키는 이유는 무엇입니까?

lsattr -Ra 2>/dev/null /|awk '$1 ~ /i/ && $1 !~ /^\// {print}'

실제로 매일 cron을 통해 수백 대의 서버에서 / etc 디렉토리를 스캔하고 출력을 syslog로 보냅니다. 그런 다음 Splunk를 통해 일일 보고서를 생성 할 수 있습니다.

lsattr -Ra 2>/dev/null /etc|awk '$1 ~ /i/ && $1 !~ /^\// {print "Immutable_file="$2}'|logger -p local0.notice -t find_immutable


답변

매우 간단합니다. 용의자 폴더로 이동하여 다음 명령을 실행하십시오.

lsattr -laR | grep *immutable