-
[시스템 프로그래밍] Files and Directories / 권한에 관해개발 이야기/운영체제(OS)&시스템프로그래밍 2024. 10. 21. 03:10
본 내용은 한양대학교 조인휘 교수님의 시스템 프로그래밍 강의 내용을 바탕으로 정리하였습니다
stat, f stat, and lstat
#include <sys/stat.h> int stat(const char *pathname, struct stat *buf); int fstat(int filedes, struct stat *buf); int lstat(const char *pathname, struct stat *buf);
파일의 속성 정보, 즉 메타데이터를 가져오는 system call이다(from inode).
stat(): 지정한 파일 경로에 대한 파일 정보를 가져옴, 심볼릭 링크가 있는 경우 그 링크가 가리키는 실제 파일의 정보 반환
fstat(): 열려있는 파일 디스크립터로부터 파일 정보를 가져옴
lstat(): 심볼릭 링크 자체에 대한 정보를 가져옴, 즉 링크파일 자체의 속성정보를 가져옴
File & Directory 권한
리눅스는 앞서 말한 것처럼 여러 사용자가 사용하는 멀티 유즈 시스템을 제공한다. 따라서 권한을 엄격히 관리한다. 사용자들은 자신한테 권한이 부여된 파일만 읽고 쓰고 실행 가능하다.
- 권한 확인: ls -l
ls -l /path/to/directory
권한을 확인하면 다음과 같은 결과가 나오게 된다.
drwxr-xr-x 2 user group 4096 FEB 12 14:00 directory
하나씩 확인해보자.
첫번째 문자 d는 디렉토리임을 나타내고, 그 뒤에 나오는 문자는 rwxr-xr-x는 권한을 나타낸다.
파일의 유형은 d: 디렉토리, b: 블록 디바이스 파일(블록 단위의 데이터 처리), c: 문자 디바이스 파일(바이트의 열로 데이터를 처리), l: symoblic link 파일, p: 명명된 pipe. s: Socket, -:일반파일 로 구분된다.
권한은 아래와 같이 구분된다.
r,w,x는 각각 read wirte execute로 읽기(read), 쓰기(write), 실행(execute) 권한을 의미한다.
권한의 경우 십진수를 이진수로 바꾸어 해석하면 된다.
예를 들어 예를 들어 '777'의 경우 이진수로 111 111 111이고 rwxrwxrwx라는 의미를 가지므로 파일 소유자, 소유 그룹, 일반 사용자에게 읽기, 쓰기, 실행의 모든 권한을 주는 설정이다.
Q: To create a new file in a directory, which permission(s) do we need to have?
Q: To delete an existing file in a dir, which permission(s)?
두개 모두다 W와 X 권한이 필요하다.
이때 그럼 특수 권한은 무엇을 의미하는가?
SUID, SGID : Set-User-ID and Set-Group-ID
파일의 실행 권한에 영향을 미치는 특수한 권한 비트로, 사용자의 권한 대신 파일의 소유자나 그룹의 권한으로 실행할 수 있게끔 일시적으로 권한을 제공해준다.
SUID는 실행 파일에 적용되며, 해당 파일이 실행될 때 파일의 소유자 권한으로 프로그램이 실행한다.
$ ls -l /usr/bin/passwd -rwsr-xr-x 1 root root 54256 Jan 14 2024 /usr/bin/passwd
rwsr-xr-x에서 s는 소유자 권한의 실행 비트를 나타내며, 이 비트가 SUID가 설정되었음을 의미한다.
# SUID 설정 chmod u+s filename # SUID 해제 chmod u-s filename # 4755: SUID + 소유자 읽기/쓰기/실행, 그룹 읽기/실행, 기타 읽기/실행 권한 설정 chmod 4755 filename
SGID는 실행 파일 및 디렉터리에 모두 적용되며, 두 가지 방식으로 동작한다. 만일 실행파일에 설정되면 파일의 소유 그룹의 권한으로 프로그램을 실행하고, 디렉토리에 설정되면 해당 리렉토리 내에서 새로 생성되는 모든 파일과 하위 디렉토리는 디렉토리의 소유 그룹을 상속받는다. 즉 기본적으로 파일을 생성하면 그 파일은 생성자의 기본 그룹 소유가 되지만, SGID 비트가 설정된 디렉터리 안에서는 디렉터리의 그룹 소유권을 따르게된다.$ ls -ld /shared_directory drwxrwsr-x 2 user staff 4096 Jan 14 2024 /shared_directory
위 예시에서 drwxrwsr-x는 SGID 비트가 설정된 디렉터리를 나타낸다.
# SGID 설정 chmod g+s filename # SGID 해제 chmod g-s filename # 2755: SGID + 소유자 읽기/쓰기/실행, 그룹 읽기/실행, 기타 읽기/실행 권한 설정 chmod 2755 directory_name
Sticky Bit는 주로 디렉터리에 설정되며, 디렉터리 내에서 파일을 삭제하거나 이름을 변경할 수 있는 권한을 제어한다. Sticky Bit가 설정된 디렉터리에서는 해당 파일의 소유자나 루트 사용자만 그 디렉터리 내 파일을 삭제하거나 이름을 변경할 수 있다. 즉 공동 작업 공간에서 파일을 실수로 삭제하지 않도록 보호하는 데 유용하다.
$ ls -ld /tmp drwxrwxrwt 9 root root 4096 Jan 14 2024 /tmp
위 예시에서 drwxrwxrwt에서 마지막 **t**가 Sticky Bit가 설정된 것을 나타낸다.
# Sticky Bit 설정 chmod +t directory_name # Sticky Bit 해제 chmod -t directory_name # 1755: Sticky Bit + 소유자 읽기/쓰기/실행, 그룹 읽기/실행, 기타 읽기/실행 권한 설정 chmod 1755 directory_name
acess()
파일의 권한을 가지고 있는지 확인하는 system call
#include <unistd.h> int access(const char *pathname, int mode);
real user ID/Group에 기반하여 권한을 확인한다. 이때 real user id와 effective user id는 시스템에 로크인 시 부여받는 ID인지 혹은 파일 시스템에 접근할 때 사용하는 사용자 권한인지의 차이이다(후자는 Set uid u+s인 경우 변경된다)
예를 들어, Set-User-ID(SUID) 비트가 설정된 프로그램에서 access()를 호출하면, 실제 사용자 ID를 기반으로 권한을 확인하므로 유효 사용자 ID로 실행되는 권한이 반영되지 않을 수 있다.
umask()
include <sys/stat.h> mode_t umask(mode_t cmask);
umask란 파일이나 디렉토리를 생성할 때 기본 권한을 제어하는 값이다. 즉, 제한하는 권한을 설정하는 데 사용한다.
어떻게 값이 유도되는지 보자
파일과 디렉터리의 기본 권한은 다음과 같다:
- 파일: 666 (읽기 및 쓰기 권한만 부여됨)
- 디렉터리: 777 (읽기, 쓰기, 실행 권한 모두 부여됨)
umask 값이 022인 경우:
- 022는 그룹과 그 외 사용자에게서 쓰기 권한을 제거한다.
- 기본 파일 권한인 666에서 022를 XOR연산을 하면 644가 됩니다. 즉, 새 파일의 기본 권한은 rw-r--r--.
- 기본 디렉터리 권한인 777에서 022를 빼면 755가 됩니다. 즉, 새 디렉터리의 기본 권한은 rwxr-xr-x가 된다.
아래와 같이 계산해도 된다. 002에 관해서 XOR연산(같으면 1 아니면 0)
110 110 110 = 666 : 파일비교기본값
000 000 010 = 002 : umask
110 110 100 = 664 : 파일 퍼미션
111 111 111 = 777 : 디렉토리비교기본값
000 000 010 = 002 : umask
111 111 101 = 775 = 디렉토리 퍼미션
chmod, fchmod
#include <sys/stat.h> int chmod(const char *pathname, mode_t mode); int fchmod(int filedes, mode_t mode);
chmod와 fchmod는 모두 권한을 변경하는 systemcall이다(change mode)
이때 둘 모두 기능은 같으나 chmod는 파일의 path를 기반으로 fchmod는 file discripter를 기반으로 찾는(standard IO개념)다.
두 system call 모두 파일의 소유자 혹은 root 사용자만 사용할 수 있다(당연히 권한을 막 바꾸면 큰일 나기에)
chown, fchown, and lchown
int chown(const char *pathname, uid_t owner, gid_t group); int fchown(int filedes, uid_t owner, gid_t group); int lchown(const char *pathname, uid_t owner, gid_t group);
3 systm call 모두 파일이나 디렉토리의 소유자를 변경한다(change owner)
chown은 파일의 경로를 이용하여 변경하다
fchown은 파일 디스크립터를 이용한다.
(위의 chown과 fchown 모두 심볼릭 링크가 주어지면 대상 파일의 소유자를 변경)
마지막으로 l이 붙은 lchown은 심볼릭 링크 자체의 소유자를 변경한다.
file truncation
#include <unistd.h> int truncate(const char *pathname, off_t length); int ftruncate(int filedes, off_t length);
truncate과 ftruncate 모두 파일의 크기를 줄이거나 비우는 작업이다. 이는 파일을 비우거나 특정 크기로 줄일 때 사용한다.
remove(), rename()
int remove(const char *pathname); int rename(const char *oldpath, const char *newpath);
remove()는 파일이나 디렉토리를 삭제하는 함수. 파일의 경우 추후 후술할 unlink()와 동일한 동작을 한다.
rename은 파일 또는 디렉토리의 이름을 변경하거나 파일을 다른 경로로 이동시키는 데 가능. 서로 다른 파일 시스템간의 이동은 불가
Symbolic link & Hard link
Hard link는 원본파일과 동일한 inode를 직접적으로 가리키며, 원본 파일이 사라지더라도 데이터만 살아있으면 원본 파일에 접근이 가능하다.
다만, hardlink는 서로 다른 파일 시스템에서는 불가능하고, 디렉토리에 관한 하드링크는 일반적으로(super user가 아니면) 제한된다.
Symbolic link는 또 다른 inode를 생성해서 이를 바라보는 링크를 가르킨다. 이는 원본파일이나 디렉토리가 삭제되면 더 이상 유효하지 않은 접근을 가지게 된다.
link, unlink: 하드링크용
int link(const char *oldpath, const char *newpath); int unlink(const char *pathname);
link()는 파일에 대한 하드링크를 생성한다. 즉 두 파일은 동일한 i-node를 공유하며 link count를 증가시킨다(파일이 존재하면 기본 1, 즉 link()하면 2가 된다)
unlink()는 파일에 대한 하드링크를 삭제하고, 파일에 연결된 모든 링크가 삭제되면 파일의 데이터와 i-node도 제거된다.
symlink() readlink(): 심볼릭 링크 용
int symlink(const char *target, const char *linkpath);
symlink()는 심볼릭 링크를 생성한다. 즉, 새로운 i-node를 생성한다.
include <unistd.h> ssize_t readlink(const char *pathname, char *buf, size_t bufsize);
readlink는 심볼릭 링크가 가리키는 원본파일의 경로를 읽어온다. 심볼릭 링크는 파일 경로를 가리키기 때문에, 이 함수는 심볼릭 링크 자체를 따라가지 않고, 링크가 가리키는 경로를 읽어온다.
삭제는 unlink()로 가능하다.
utime()
#include <sys/types.h> #include <utime.h> int utime(const char *pathname, const struct utimbuf *times);
파일의 acces/modification 시간을 변경
mkdir / rmdir: 디렉토리 생성 / 삭제
int mkdir(const char *pathname, mode_t mode); int rmdir(const char *pathname);
chdir, fchdir, getcwd: 현재 작업 디렉토리 변경, 경로 얻기
#include <unistd.h> int chdir(const char *pathname); int fchdir(int filedes); char *getcwd(char *buf, size_t size);
chdir() 함수는 현재 작업 디렉터리(Current Working Directory, CWD)를 지정된 경로로 변경
fchdir() 함수는 파일 디스크립터를 통해 현재 작업 디렉터리를 변경
getcwd() 함수는 현재 작업 디렉터리의 절대 경로를 반환
'개발 이야기 > 운영체제(OS)&시스템프로그래밍' 카테고리의 다른 글
[시스템프로그래밍] Standard I/O Library (0) 2024.10.21 [시스템 프로그래밍] File I/O (0) 2024.10.21 [시스템프로그래밍] UNIX System Overview (1) 2024.10.20