LabHub
배우기 러닝패스 코스

Linux基礎

権限はファイルではなく動作に付く

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

한 줄 요약

rwx 세 글자는 파일에 붙었을 때와 디렉터리에 붙었을 때 뜻이 다르다. 이 차이를 모르면 "읽기 전용 파일이 왜 지워지지" 같은 사고를 계속 만나게 된다.

概念マップ: 삭제는 파일에 대한 동작이 아니라 디렉터리에 대한 동작・디렉터리에 쓰기 권한・setuid(4)・setgid(2)

왜 이게 필요했나

공유 디렉터리를 하나 만들어 팀에서 같이 쓰기로 했다. 각자 파일을 올리고, 남의 파일은 건드리지 않기로 약속했다. 그런데 어느 날 누군가의 파일이 사라졌다. 파일 권한은 644, 소유자도 그대로였다.

여기서 "권한이 644 인데 어떻게 지워졌지"라고 물으면 답이 안 나온다. 삭제는 파일에 대한 동작이 아니라 디렉터리에 대한 동작이기 때문이다. 파일을 지운다는 것은 디렉터리에서 이름 하나를 떼어내는 일이고, 그러려면 그 디렉터리에 쓰기 권한이 있으면 된다. 파일 자체가 읽기 전용이든 남의 것이든 상관없다.

유닉스는 이 문제를 위해 별도의 비트를 하나 더 뒀다. 그게 sticky 비트다.

어떻게 동작하나

먼저 같은 글자가 대상에 따라 어떻게 달라지는지 정리한다.

비트 파일에서 디렉터리에서
r 내용을 읽을 수 있다 목록을 볼 수 있다(ls)
w 내용을 고칠 수 있다 항목을 만들고 지울 수 있다
x 실행할 수 있다 그 안으로 들어가고 경로를 통과할 수 있다

디렉터리에 r만 있고 x가 없으면 이름은 보이는데 그 안의 파일 정보는 못 읽는다. 반대로 x만 있고 r이 없으면 목록은 못 보지만 정확한 이름을 알면 접근할 수 있다.

여기에 특수 비트 세 개가 얹힌다. 8진수 네 자리 중 맨 앞자리다.

그래서 팀 공유 디렉터리의 표준 형태는 2770(그룹 상속 + 그룹 밖 차단)이고, 아무나 올리되 남의 것은 못 지우게 하려면 1777이다.

현장에서 만나는 모습

첫째, 그룹을 추가했는데 적용이 안 된다. usermod -aG devs alice를 실행해도 alice 가 이미 로그인해 있던 셸에는 반영되지 않는다. 그룹 목록은 프로세스가 만들어질 때 정해지기 때문이다. 새 로그인 세션이 필요하다. 여기서 -a(append)를 빼면 기존 보조 그룹이 전부 날아간다 - 운영 서버에서 자주 나오는 사고다.

둘째, 8진수와 기호 표기. chmod 750 run.sh처럼 절대값으로 주는 방식과 chmod g+x,o-rwx run.sh처럼 상대적으로 고치는 방식이 있다. 배포 스크립트에서는 현재 상태와 무관하게 결과가 같아야 하므로 절대값이 안전하다. 반대로 대량 파일을 손볼 때는 기호 표기가 실수를 줄인다.

셋째, 권한 확인은 눈이 아니라 명령으로. ls -l-rwxr-x---를 사람이 세는 것보다 stat -c %a가 정확하다. 채점 스크립트나 점검 스크립트를 쓸 때는 항상 stat을 쓴다.

새로 만든 파일의 권한은 누가 정하나

chmod 를 쳐 본 적은 있어도 파일이 처음 만들어질 때의 권한은 어디서 오는지 모르는 경우가 많다. 이것을 정하는 것이 umask 다.

프로그램이 파일을 만들 때 원하는 권한을 커널에 알려 주는데, 일반 파일은 대개 666, 디렉터리는 777 을 요청한다. 커널은 거기서 umask 에 켜진 비트를 빼고 만든다. umask 가 022 면 파일은 644, 디렉터리는 755 가 된다. 그래서 umask 는 "허용" 이 아니라 "금지" 목록이고, 값을 읽을 때 그 방향을 헷갈리면 계산이 반대로 나온다.

여기서 두 가지가 자주 문제가 된다. 첫째, 실행 비트는 umask 로 붙지 않는다. 요청이 666 이라 애초에 실행 비트가 없기 때문이고, 그래서 새로 만든 스크립트는 언제나 chmod +x 가 필요하다. 둘째, umask 는 프로세스마다 있고 자식이 물려받으므로, 서비스의 umask 는 그 서비스를 띄운 환경이 정한다. 사람이 셸에서 띄울 때와 시스템이 부팅 때 띄울 때 값이 달라서, 손으로 재시작한 서비스가 만든 파일만 권한이 다른 상황이 생긴다. 이런 서비스는 설정에 umask 를 명시해 두는 편이 안전하다.

권한이 이상할 때 확인하는 순서도 정해 두면 좋다. 누가 만들었나 → 그때 umask 가 무엇이었나 → 디렉터리에 setgid 가 걸려 있나 → 그 뒤에 누가 chmod 했나. 특히 세 번째는 앞에서 본 대로 그룹이 바뀌므로, 파일 소유 그룹이 만든 사람의 기본 그룹과 다르면 그 디렉터리를 먼저 본다.

마지막으로 접근 제어 목록(ACL)을 짚어 둔다. 소유자·그룹·기타 셋만으로는 "이 사람에게만 추가로 읽기를 준다" 를 표현할 수 없어서, 그럴 때 setfacl 로 개별 권한을 얹는다. 다만 ls -l 에는 끝에 + 하나만 붙어서 눈에 잘 안 띄므로, 권한이 설명되지 않을 때는 getfacl 로 확인해 보아야 한다.

다음 실습에서 할 것

사용자와 그룹을 직접 만들고, setgid 와 sticky 를 건 공유 디렉터리를 구성한 뒤, 마지막에는 "이 파일이 기대한 권한인지"를 검사해 종료 코드로 알려 주는 점검 스크립트를 작성한다.