변경할 수 없는 속성 집합이 있는 파일을 검색하는 방법은 무엇입니까?

변경할 수 없는 속성 집합이 있는 파일을 검색하는 방법은 무엇입니까?

구성 감사 이유로 저는 ext3 파일 시스템에서 불변 속성 세트(pass chattr +i)가 있는 파일을 검색할 수 있기를 원합니다. find이 작업이나 이와 유사한 옵션을 찾을 수 없습니다 . 이제 lsattr각 디렉터리의 출력을 구문 분석하는 스크립트를 직접 작성해야 할 것 같습니다. 더 나은 접근 방식을 제공하는 표준 유틸리티가 있습니까?

답변1

이는 명령 파이프라인을 통해 lsattr명령을 파이프하여 부분적으로 수행할 수 있습니다 grep.

lsattr -R | grep +i

그러나 전체 ext3파일 시스템을 언급할 때 검색에는 과 다른 일부 디렉터리가 포함될 수 /proc있으며 /dev무시하고 싶은 일부 오류가 보고될 수도 있습니다. 아마도 명령을 실행할 수 있을 것입니다.

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

grepPCRE 도구를 사용하여 grep"-i-"를 보다 엄격하게 일치시킬 수 있습니다 .

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

이는 다음 상황에 적용됩니다.

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

그러나 그것은 완벽하지 않습니다. immutable 플래그 주위에 다른 속성이 활성화되어 있으면 해당 속성을 일치시키지 않으며 이름이 위 패턴과 일치하는 파일에 속게 됩니다. 예를 들면 다음과 같습니다.

$ 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

하지만 여전히 취약하기 때문에 파일 시스템의 파일을 기반으로 추가 조정이 필요합니다. 말할 것도 없이@Stephenchazelles파일 이름에 개행 문자를 포함하면 위의 패턴을 상당히 쉽게 조작할 수 있다는 것이 주석에서 언급되었습니다 grep.

인용하다

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

답변2

이 스크립트의 목적이 감사인 경우 임의의 파일 이름(예: 줄바꿈이 포함된 이름)을 올바르게 처리하는 것이 특히 중요합니다. 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 {} +

lsattrPerl, Python 또는 Ruby와 같은 덜 특이한 언어를 사용하고 작업을 직접 수행하는 것이 좋습니다. ioctl 시스템 호출을 lsattr발행 FS_IOC_GETFLAGS하고 파일의인덱스 노드 플래그. 이것은 Python 개념 증명입니다.

#!/usr/bin/env python2
import array, fcntl, os, sys
S_IFMT =  0o170000
S_IFDIR = 0o040000
S_IFREG = 0o100000
FS_IOC_GETFLAGS = 0x80086601
EXT3_IMMUTABLE_FL = 0x00000010
count = 0
def check(filename):
    mode = os.lstat(filename).st_mode
    if mode & S_IFMT not in [S_IFREG, S_IFDIR]:
        return
    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)

답변3

나에게 올바른 방향(제가 놓친 스위치 -R) 을 알려준 Ramesh, slm 및 Stéphane에게 감사드립니다 lsattr. 불행하게도 지금까지는 어떤 대답도 정답이 아닌 것 같습니다.

나는 다음을 생각해 냈습니다.

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

이렇게 하면 파일이 변경 불가능한 것처럼 보이도록 개행을 사용하는 것을 방지할 수 있습니다. 물론아니요파일을 변경할 수 없게 만들고 파일 이름에 줄 바꿈을 포함하는 것을 방지합니다. 그러나 그러한 파일은 루트에서 이런 방식으로 생성되어야 하기 때문에 내 사용 사례에서는 그러한 파일이 내 파일 시스템에 존재하지 않는다고 확신할 수 있습니다. (이 접근 방식은 루트 사용자가 손상될 수 있는 침입 감지에는 적합하지 않지만 lsattr동일한 루트 사용자에게 속한 동일한 시스템 유틸리티를 사용하는 데에도 적합하지 않습니다 .)

답변4

사용하기에는 너무 느리고 find -exec구문 분석 출력 lsattr은 다음과 같습니다.마찬가지로 신뢰할 수 없는ls, Python을 다음과 같이 사용하십시오.자일스의 대답ioctlPython 인터프리터가 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;
    }
}

관련 정보