Philip Withnall philip.withnall@collabora.co.uk 2015 파일 시스템에 접근하기 조성호 shcho@gnome.org 2016, 2017. 파일 시스템 접근 요약

파일 시스템에 접근해야 할 때 피해야 할 몇가지 방식이 있습니다. 이 내용은 GFile, GInputStream, GOutputStream 표준 API를 알고 있음을 가졍합니다.

파일 접근시 비동기 입출력을 활용하십시오().

파일 이름 및 경로를 만들 때마다 적당한 함수를 활용하십시오().

파일 경로를 활용하기 전 예상 디렉터리에 있는지 검증하십시오().

파일 접근을 통제하는 필수 접근 통제 프로파일을 사용하십시오().

비동기 입출력

대부분의 모든 입출력 과정은 비동기 방식으로 처리해야합니다. 무슨 이야기냐면 GLib 메인 컨텍스트의 동작을 방해하면 안된다는 의미입니다. 각 입출력 함수의 *_async()*_finish() 변형 함수를 활용하여 언제든 수행 가능합니다.

예를 들어 g_input_stream_read() 함수 대신 g_input_stream_read_async() 함수를 사용하십시오.

동기 입출력은 메인 루프의 실행을 가로 막는데, 사용자 입력, 네트워크 패킷 수신, 콜백 시간 초과 및 대기 같은 상황의 경우 프로그램의 동작 흐름을 가로막은 함수에서 반환 값이 나오기 전에는 처리할 수 없다는 의미입니다.

동기 입출력은 리눅스에서 로컬 동기 입출력 보다 비동기 처리 스케줄의 처리 시간/용량이 비교적 좋지 않은 일부 상황에서 용납 가능합니다. 예를 들어 로컬 파일 또는 /proc 같은 가상 파일 시스템에서 작은 데이터를 읽어들이는 경우가 있습니다. 이 때, GIO 대신 g_open(), read(), g_close() 저수준 함수를 사용해야합니다.

로컬에 없다고 간주하는 사용자 개인 디렉터리에 있는 파일은, 네트워크 파일 시스템에 있을 수 있습니다.

개별 스레드의 동기 입출력 처리 같은 대안책은 가급적 피하시는게 좋습니다. 자세한 내용은 스레드 처리 지침서를 참고하십시오.

파일 경로 만들기

파일 이름 및 경로는 일반 문자열이 아닙니다. GLib에서는 일반 문자열에 항상 UTF-8을 사용한다고 간주하지만, 일부 시스템에서는 UTF-8이 아닌 다른 문자 인코딩을 사용할 수 있습니다. 이 이유로, 파일 이름 및 경로를 만들고 처리할 때 특별한 함수를 사용해야합니다(최신 리눅스 시스템에서는 대부분 보편적으로 파일 이름 인코딩에 UTF-8을 사용하여 실제로는 문제되지 않지만, UTF-16 파일 이름을 사용하는 윈도우 같은 시스템의 호환성을 확보하려면 파일 경로 함수를 활용해야합니다).

예를 들어 파일 경로는 g_strconcat() 함수보다 g_build_filename() 함수를 사용하여 만들어야합니다.

이렇게 하면 코드가 무슨 일을 하는지 의미를 좀 더 분명하게 하며, (필연적으로 절대적이진 않지만)디렉터리 구분 문자 중복을 방지하여 올바른 경로를 반환합니다.

다른 예를 들어보자면, g_strrstr() 함수 및 다른 직접적인 검색 함수를 활용하기보다는, g_path_get_basename() 함수와 g_path_get_dirname() 함수를 활용하여 경로를 분해해야합니다.

경로 검증 및 샌드박싱

웹 페이지 또는 사용자 입력 등의 외부 입력으로 파일 이름 또는 경로를 받는다면, 파일 경로로 둔 경로의 임의 경로 여부를 확인하여 검증해야합니다.예를 들어 ~/ 상수 문자열에 일부 사용자 입력을 받아 파일 이름을 만들고, 여기서 사용자 입력이 ../../etc/passwd라면, 사용자가 프로그램을 어떻게 실행하며, 만든 경로에서 어떤 데이터를 불러오냐에 따라 민감한 계정 정보로 접근하는데 접근할 수 있는 권한을(잠재적으로) 얻을 수 있습니다.

이 기능을 사용하기 전, g_file_resolve_relative_path() 함수로 상대 경로를 절대 경로로 변환하고 처리에 적당한 루트 샌드박싱 디렉터리에 있는 경로인지 검증하는 방식으로 작성한 경로를 검증하여 (악의적 접근을) 막을 수 있습니다. 이를테면, 코드로 파일을 다운로드할 때, g_file_has_parent() 함수를 사용하면 모든 경로가 ~/Downloads 디렉터리에 있는지 검증할 수 있습니다.

방어 차선책으로, 파일 시스템에 접근하는 모든 프로젝트는 디렉터리 및 파일의 읽기/쓰기 동작을 제한하는 AppArmor 또는 SELinux 같은 시스템을 활용하는 필수 접근 제어 프로파일 제공을 고려해야합니다.