Summary: chmod는 파일 모드 비트를 바꿔 사용자별 접근 범위를 정하고, chown은 그 권한을 적용받는 소유자와 그룹을 바꾼다. chroot는 이 둘과 달리 프로세스가 절대 경로를 해석하는 루트를 변경하며, 별도의 실행 환경을 구성할 수 있지만 완전한 보안 격리를 제공하지는 않는다.
chmod
chmod(Change Mode)는 파일과 디렉터리의 접근 권한을 변경한다. 파일에는 소유자, 그룹, 그 외 사용자라는 세 범주가 있고, 각 범주에는 읽기·쓰기·실행 권한을 서로 다르게 줄 수 있다. chmod를 사용하는 이유는 이 접근 범위를 실제 용도에 맞게 나누기 위해서다. 일반 파일에서는 내용을 읽고 수정하고 실행할 수 있는지를 정하고, 디렉터리에서는 목록 조회, 내부 파일 생성·삭제, 경로 탐색 가능 여부를 조정한다.
기본 구문은 다음과 같다.
chmod [OPTION]... {MODE | --reference=REF_FILE} FILE...
MODE를 직접 지정하거나 --reference로 다른 파일의 모드를 가져올 수 있다. 권한은 기호 모드와 8진수 모드 중 하나로 표현한다. 파일 모드 비트를 바꿀 수 있는 프로세스는 유효 사용자 ID가 파일 소유자의 사용자 ID와 일치하거나, 해당 작업에 필요한 권한을 가지고 있어야 한다. 명령이 성공하면 종료 상태는 0, 실패하면 0이 아닌 값이다.
파일 모드 비트
파일 모드 비트는 일반 접근을 제어하는 권한 비트와 일부 파일에만 영향을 주는 특수 모드 비트로 구성된다. 일반 권한을 해석할 때는 먼저 권한의 대상이 누구인지 확인해야 한다.
| 기호 | 범주 | 의미 |
| u | user | 파일 소유자 |
| g | group | 파일 그룹에 속한 사용자 |
| o | others | 그 외 사용자 |
| a | all | 모든 사용자, ugo와 동일 |
rwx의 의미는 일반 파일과 디렉터리에서 다르다.
| 권한 | 값 | 일반 파일 | 디렉터리 |
| r | 4 | 내용 읽기 | 항목 목록 조회 |
| w | 2 | 내용 변경 | 내부 파일 생성·삭제 |
| x | 1 | 프로그램으로 실행 | 내부 파일 접근·경로 탐색 |
특히 디렉터리의 w와 x를 일반 파일의 쓰기·실행과 같은 의미로 읽으면 권한을 잘못 판단하기 쉽다. 디렉터리에서 w는 내부 항목을 만들거나 지우는 동작에 관여하고, x는 그 디렉터리를 경로의 일부로 사용해 내부 파일에 접근하는 권한이다.
기호 모드
기호 모드는 현재 권한을 기준으로 일부 비트만 추가하거나 제거할 때 적합하다. 표현은 사용자, 연산자, 권한 순서이며 내부에 공백을 넣지 않는다.
[ugoa][+-=][rwxXst]
연산자는 기존 권한을 어떻게 다룰지 결정한다.
| 연산자 | 의미 |
| + | 기존 권한에 지정 권한 추가 |
| - | 기존 권한에서 지정 권한 제거 |
| = | 기존 권한을 지정 권한으로 교체 |
r, w, x는 읽기, 쓰기, 실행·탐색을 뜻한다. 대문자 X는 디렉터리이거나 이미 실행 권한이 하나라도 있는 파일에만 실행·탐색 권한을 적용한다. s는 u와 결합하면 set-user-ID, g와 결합하면 set-group-ID를 가리키고, t는 sticky bit를 가리킨다. 서로 다른 변경을 한 번에 적용할 때는 쉼표로 구분한다.
chmod a=rw foo
chmod go-w foo
chmod u=rwx,g=rx,o= foo
chmod a+X dir
첫 번째 명령은 모든 사용자에게 읽기·쓰기만 허용한다. 두 번째는 소유자를 제외한 그룹과 그 외 사용자에게서 쓰기 권한만 제거하므로, 나머지 권한에는 영향을 주지 않는다. 세 번째처럼 =를 사용하면 각 사용자 범주의 권한을 명시한 값으로 교체한다. 마지막 명령의 X는 디렉터리와 기존 실행 파일만 선별한다는 점에서 소문자 x와 구분된다.
8진수 모드
8진수 모드는 소유자, 그룹, 그 외 사용자의 rwx 조합을 각각 하나의 숫자로 나타낸다. 각 자리는 읽기 4, 쓰기 2, 실행·탐색 1을 더해 계산한다.
| 값 | 권한 | 계산 |
| 0 | --- | 권한 없음 |
| 1 | --x | 1 |
| 2 | -w- | 2 |
| 3 | -wx | 2 + 1 |
| 4 | r-- | 4 |
| 5 | r-x | 4 + 1 |
| 6 | rw- | 4 + 2 |
| 7 | rwx | 4 + 2 + 1 |
세 자리 앞에는 특수 권한을 나타내는 자리가 올 수 있다.
[특수 권한][소유자][그룹][그 외 사용자]
숫자 모드는 항상 8진수로 해석되므로 선행 0은 필요하지 않다. 기호 모드보다 짧지만, 일반적으로 기존 권한의 일부를 조정하기보다 전체 권한을 절대값으로 설정한다는 차이가 있다.
| 모드 | 기호 | 표현 의미 |
| 644 | u=rw,g=r,o=r | 소유자 읽기·쓰기, 나머지 읽기 |
| 664 | ug=rw,o=r | 소유자·그룹 읽기·쓰기, 나머지 읽기 |
| 751 | u=rwx,g=rx,o=x | 소유자 전체, 그룹 읽기·실행, 나머지 실행 |
| 4751 | u=srwx,g=rx,o=x | 751 + set-user-ID |
chmod 644 foo
chmod ug+x file
chmod 644 foo는 세 사용자 범주의 권한을 한 번에 확정한다. 반면 chmod ug+x file은 소유자와 그룹에 실행 권한만 추가한다. 최종 상태를 명확히 지정할 때는 숫자 모드가 짧고, 현재 설정을 유지하면서 특정 권한만 바꿀 때는 기호 모드가 변경 범위를 더 직접적으로 드러낸다.
특수 권한
특수 권한은 일반적인 읽기·쓰기·실행과 별도로 실행 프로세스의 유효 ID나 디렉터리의 파일 관리 방식에 영향을 준다.
| 8진수 값 | 기호 | 명칭 | 효과 |
| 4000 | u+s | set-user-ID | 실행 시 프로세스의 유효 사용자 ID를 파일 소유자로 설정 |
| 2000 | g+s | set-group-ID | 실행 시 프로세스의 유효 그룹 ID를 파일 그룹으로 설정, 디렉터리에서는 새 항목이 디렉터리 그룹을 상속 |
| 1000 | +t | sticky bit | 디렉터리에서 권한 없는 사용자의 파일 삭제·이름 변경을 파일 또는 디렉터리 소유자로 제한 |
chmod u+s program
chmod a-s program
chmod +t shared_dir
chmod 6755 shared_dir
디렉터리에 set-group-ID가 설정되어 있으면 그 안에 생긴 새 파일은 디렉터리의 그룹을 상속하고, 새 하위 디렉터리는 set-group-ID까지 상속한다. 여러 사용자가 같은 그룹을 기준으로 파일을 다루는 디렉터리에서는 소유 그룹이 이어지는 방식 자체가 권한 관리의 일부가 된다.
GNU chmod에서 디렉터리의 set-user-ID와 set-group-ID를 제거할 때는 제거 의도를 명시해야 한다. chmod a-s DIR, chmod =755 DIR, chmod 00755 DIR이 이에 해당한다. 일반 권한 세 자리만 보고 특수 비트도 항상 함께 지워질 것이라고 가정해서는 안 된다.
주요 옵션
chmod의 옵션은 재귀 처리, 출력 범위, 참조 파일 사용, 심볼릭 링크 처리 방식에 집중되어 있다.
| 옵션 | 의미 |
| -R, --recursive | 디렉터리와 내부 항목의 권한을 재귀적으로 변경 |
| -c, --changes | 실제 변경된 파일만 출력 |
| -f, --silent, --quiet | 변경 실패 오류 메시지 생략 |
| -v, --verbose | 처리한 모든 파일의 동작·비동작 출력 |
| --reference=REF_FILE | 참조 파일과 동일한 모드로 변경 |
| --preserve-root | /에 대한 재귀 변경 거부 |
| --dereference | 심볼릭 링크 자체가 아닌 대상에 적용 |
| -h, --no-dereference | 지원 시스템에서 심볼릭 링크 자체에 적용 |
| -H | -R 사용 시 명령행 인수인 디렉터리 심볼릭 링크만 탐색 |
| -L | -R 사용 시 발견한 모든 디렉터리 심볼릭 링크 탐색 |
| -P | 심볼릭 링크 탐색 안 함 |
심볼릭 링크를 명령행 인수로 직접 지정하면 기본적으로 링크가 가리키는 파일의 권한을 바꾼다. 반면 재귀 탐색 과정에서 발견한 심볼릭 링크는 기본적으로 무시한다. 같은 링크라도 명령행에서 직접 받은 경우와 디렉터리 아래에서 발견한 경우의 처리가 다르다.
-R과 -L 또는 역참조 옵션을 결합하면 범위가 더 넓어진다. 재귀 순회 중 공격자가 심볼릭 링크의 대상을 바꿀 수 있다면 원래 의도하지 않은 파일까지 권한 변경 대상이 될 수 있다. 루트 디렉터리를 재귀적으로 건드리지 않도록 하는 --preserve-root도 변경 범위를 통제하는 옵션이다.
chown
chown(Change Owner)은 파일과 디렉터리의 사용자 소유권 또는 그룹 소유권을 변경한다. chmod가 소유자·그룹·그 외 사용자에게 어떤 권한을 줄지 정한다면, chown은 그중 소유자와 그룹 자리에 누가 들어갈지를 바꾼다. 파일을 관리할 사용자나 그룹이 달라졌거나 여러 파일의 소유권을 기준 파일에 맞춰야 할 때 이 명령을 사용한다.
chown [OPTION]... {NEW_OWNER | --reference=REF_FILE} FILE...
소유자와 그룹은 공백 없이 다음 형식으로 지정한다.
[OWNER][:[GROUP]]
| 형식 | 사용자 소유자 | 그룹 소유자 |
| OWNER | OWNER로 변경 | 유지 |
| OWNER:GROUP | OWNER로 변경 | GROUP으로 변경 |
| OWNER: | OWNER로 변경 | OWNER의 로그인 그룹으로 변경 |
| :GROUP | 유지 | GROUP으로 변경, chgrp와 같은 기능 |
| : | 유지 | 유지 |
OWNER와 GROUP에는 이름 또는 숫자 ID를 넣을 수 있다. 숫자 ID가 같은 문자열의 이름과 혼동될 가능성을 피하려면 앞에 +를 붙일 수 있다. 사용자와 그룹의 구분자는 :를 사용한다. 오래된 스크립트에서 보이는 . 표기는 이식성이 없고 GNU에서도 경고가 발생하며 지원이 제거될 수 있다.
Linux에서는 사용자 소유자를 바꾸는 작업을 CAP_CHOWN을 가진 특권 프로세스만 수행할 수 있다. 파일 소유자는 그룹을 자신이 속한 그룹 중 하나로 바꿀 수 있고, CAP_CHOWN을 가진 프로세스는 임의의 그룹으로 변경할 수 있다. 따라서 다음 세 명령은 문법만 다른 것이 아니라 변경 범위와 필요한 권한도 다르다.
chown root /u
chown root:staff /u
chown -hR root /u
첫 번째 명령은 사용자 소유자만 root로 바꾸고 그룹은 유지한다. 두 번째는 사용자 소유자와 그룹을 함께 바꾼다. 세 번째는 /u와 그 아래 항목의 소유자를 재귀적으로 바꾸되, 심볼릭 링크에서는 링크 자체를 대상으로 삼는다. 성공 시 종료 상태는 0, 실패 시 0이 아닌 값이다.
주요 옵션
| 옵션 | 의미 |
| -R, --recursive | 디렉터리와 내부 항목의 소유권을 재귀적으로 변경 |
| -c, --changes | 실제 변경된 파일만 출력 |
| -f, --silent, --quiet | 변경 실패 오류 메시지 생략 |
| -v, --verbose | 처리한 모든 파일 출력 |
| --from=OLD_OWNER | 현재 소유권이 지정값과 일치할 때만 변경 |
| --reference=REF_FILE | 참조 파일과 동일한 사용자·그룹으로 변경 |
| --dereference | 심볼릭 링크 자체가 아닌 대상에 적용, 비재귀 작업의 기본값 |
| -h, --no-dereference | 심볼릭 링크 대상 대신 링크 자체에 적용 |
| --preserve-root | /에 대한 재귀 변경 거부 |
| -H | -R 사용 시 명령행 인수인 디렉터리 심볼릭 링크만 탐색 |
| -L | -R 사용 시 발견한 모든 디렉터리 심볼릭 링크 탐색 |
| -P | 심볼릭 링크 탐색 안 함, 재귀 작업의 기본값 |
--from=OLD_OWNER는 파일의 현재 소유권이 예상한 값과 일치할 때만 변경한다. 소유권을 확인한 뒤 별도의 명령으로 바꾸는 방식보다 확인과 변경 사이의 간격이 짧고, 예상과 다른 소유권의 파일이 함께 바뀔 가능성도 줄어든다.
심볼릭 링크 처리는 비재귀 작업과 재귀 작업을 나눠 봐야 한다. 비재귀 작업에서는 링크 대상을 따라가는 --dereference가 기본이고, 재귀 작업에서는 링크를 탐색하지 않는 -P가 기본이다. -R과 -L 또는 역참조를 함께 사용하면 chmod와 마찬가지로 순회 중 바뀐 링크가 의도하지 않은 파일을 가리킬 수 있다.
소유권 변경은 권한 비트와 완전히 독립적인 작업도 아니다. 처리 결과 set-user-ID 또는 set-group-ID가 제거될 수 있으며, 실제 동작은 시스템 정책과 시스템 호출에 따라 달라진다. 소유자만 바꾼 뒤 기존 특수 권한이 그대로 남아 있다고 전제해서는 안 되는 이유다.
chroot
chroot(Change Root)는 명령을 실행하기 전에 프로세스의 루트 디렉터리를 지정한 디렉터리로 바꾼다. 이후 절대 경로는 원래 시스템의 /가 아니라 NEWROOT를 시작점으로 해석된다. 새 루트 안에 실행 파일, 라이브러리, 데이터 파일을 별도로 배치하고 그 구성을 기준으로 명령을 실행할 때 사용한다.
chroot [OPTION]... NEWROOT [COMMAND [ARGS]...]
동작 순서는 세 단계다.
- 존재하는 NEWROOT를 새 루트 디렉터리로 변경한다.
- 작업 디렉터리를 새 루트 내부의 /로 변경한다.
- COMMAND와 ARGS를 실행한다.
일반적인 절대 경로는 기존 /부터 탐색하지만, chroot 이후에는 같은 / 표기가 NEWROOT를 가리킨다. COMMAND를 생략하면 $SHELL을 사용하고, 이 환경 변수가 설정되어 있지 않으면 /bin/sh를 -i 옵션으로 실행한다. 별도 옵션이 없다면 명령의 실행 자격 증명은 호출 프로세스와 같다.
많은 시스템에서 이 명령은 슈퍼유저만 실행할 수 있다. Linux에서는 사용자 네임스페이스 안에서 CAP_SYS_CHROOT가 필요하다. chroot는 경로의 출발점을 바꾸는 작업이므로 새 디렉터리를 준비하는 것만으로 끝나지 않고, 그 안에서 실행할 명령이 실제로 사용할 파일까지 함께 구성해야 한다.
주요 옵션
| 옵션 | 의미 |
| --userspec=USER[:GROUP] | 다른 사용자와 기본 그룹으로 명령 실행 |
| --groups=GROUPS | 쉼표로 구분한 보조 그룹 지정 |
| --groups='' | --userspec에 따른 보조 그룹 조회 비활성화 |
| --skip-chdir | 새 루트 변경 후 작업 디렉터리를 /로 바꾸지 않음, NEWROOT가 기존 /일 때만 허용 |
--userspec은 새 루트에서 명령을 실행할 사용자와 기본 그룹을 지정하고, --groups는 보조 그룹 목록을 덮어쓴다. 사용자와 그룹 이름은 chroot 외부와 내부에서 모두 조회하며, 내부 조회가 성공하면 그 결과가 우선한다. 이름이 아니라 숫자 ID임을 분명히 할 때는 chown과 마찬가지로 앞에 +를 붙인다.
--skip-chdir는 이름 그대로 루트 변경 뒤의 작업 디렉터리 이동을 생략한다. 다만 NEWROOT가 기존 /일 때만 허용되므로, 일반적인 새 루트 구성에서 외부 작업 디렉터리를 그대로 유지하기 위한 옵션은 아니다.
실행 환경 구성
새 루트에서 명령을 찾더라도 실행에 필요한 파일이 그 안에 없다면 명령은 동작하지 않는다. 실행 파일의 링크 방식에 따라 준비 범위가 달라진다.
- 정적 링크 실행 파일은 실행 파일 자체를 새 루트 내부에 배치한다.
- 동적 링크 실행 파일은 실행 파일과 필요한 공유 라이브러리를 새 루트 내부의 올바른 경로에 함께 배치한다.
- 실행 파일이 데이터, 상태 파일, 장치 파일을 요구하면 이 파일들도 필요한 위치에 준비한다.
동적 실행 파일의 공유 라이브러리는 ldd COMMAND로 확인한다. 예를 들어 정적으로 링크한 ls를 /tmp/empty/ls에 배치했다면 다음처럼 실행할 수 있다.
chroot /tmp/empty /ls -Rl /
여기서 명령에 적힌 /ls와 마지막 인수 /는 모두 원래 파일 시스템이 아니라 /tmp/empty를 루트로 해석한다. 새 루트 디렉터리 안의 구조가 실행 환경의 가시 범위를 결정하는 방식이다.
보안 특성
chroot는 경로 해석의 한 요소를 변경할 뿐, 완전한 샌드박스나 보안 격리 수단은 아니다. 명령 이름에 포함된 root가 관리자 계정을 뜻하는 것이 아니라 경로 탐색의 루트 디렉터리를 뜻한다는 점도 함께 구분할 필요가 있다.
chroot(2) 시스템 호출은 현재 작업 디렉터리를 바꾸지 않으며 열린 파일 디스크립터도 닫지 않는다. 현재 작업 디렉터리가 새 루트 밖에 있거나, 이미 열린 파일 디스크립터가 외부 파일을 가리키고 있다면 새 루트 바깥에 접근할 가능성이 남는다. GNU chroot 명령이 루트 변경 후 작업 디렉터리를 새 루트의 /로 옮기는 이유는 이 시스템 호출의 동작과 구분해서 봐야 한다. --skip-chdir를 지정하면 이 이동은 생략된다.
따라서 chroot가 보여 주는 파일 트리의 시작점이 바뀌었다는 사실과 프로세스가 완전히 격리됐다는 판단은 같지 않다. 이 명령으로 구성한 실행 환경을 보안 경계 자체로 해석할 수 없는 근거가 열린 파일 디스크립터와 현재 작업 디렉터리의 처리에 있다.
종료 상태
chroot는 자체 실패와 실행할 명령의 탐색·호출 실패를 서로 다른 종료 상태로 구분한다.
| 상태 | 의미 |
| 125 | chroot 자체 실패 |
| 126 | 명령을 찾았으나 실행할 수 없음 |
| 127 | 명령을 찾을 수 없음 |
| 그 외 | 실행한 명령의 종료 상태 |
새 루트 안에 명령이 없으면 127, 파일은 있지만 필요한 조건을 갖추지 못해 호출할 수 없으면 126으로 구분된다. 실행까지 성공한 경우에는 chroot가 별도의 성공 값을 덮어쓰지 않고 실행한 명령의 종료 상태를 그대로 반환한다.











