Android System & AOSP Engineering/Android Security & SELinux

Android SELinux 정책 문법 완벽 정리: type, allow, neverallow 예제 가이드

임베디드 친구 2025. 4. 30. 19:41
반응형

안드로이드 시스템 개발자나 커스텀 ROM 제작자에게 SELinux는 '넘어야 할 거대한 벽'과 같습니다. 기능을 추가할 때마다 발생하는 권한 거부(AVC Denied) 이슈를 해결하기 위해서는 단순한 로그 분석을 넘어, SELinux 정책 파일(.te)을 구성하는 문법을 정확히 이해하고 직접 수정할 수 있어야 합니다.

SELinux는 강제 접근 제어(MAC) 모델을 사용하며, 모든 프로세스와 자원에 라벨을 붙여 통제합니다. 오늘은 정책 정의의 기초가 되는 주요 문법과 규칙들을 예제와 함께 상세히 파헤쳐 보겠습니다.

Generated by Gemini AI.


📌 핵심 요약 3줄

  1. 객체 라벨링: type과 attribute를 통해 시스템 내 모든 프로세스와 파일에 보안 레이블을 부여하고 그룹화합니다.
  2. 권한 정의: allow 규칙을 사용하여 특정 주체(Source)가 대상(Target)에 수행할 수 있는 동작을 명시합니다.
  3. 강력한 통제: neverallow는 보안상 절대 허용되지 않는 동작을 규정하며, 위반 시 시스템 빌드 자체가 불가능해집니다.

1. 객체의 정의: type과 attribute

SELinux 정책의 시작은 모든 사물에 '이름표(Label)'를 붙이는 것입니다.

문법 용도 핵심 특징
type 개별 객체에 부여되는 고유 라벨 프로세스, 파일, 소켓 등에 직접 할당됨
attribute 여러 타입을 묶는 그룹(속성) 정책 관리를 효율화하고 중복 코드를 방지함

1.1 type 및 attribute 선언 예제

코드 스니펫
 
# 속성 정의: 모든 앱 실행 파일을 묶기 위한 그룹
attribute app_exec_type;

# 타입 정의: 특정 앱 전용 실행 파일 라벨
type my_app_exec, app_exec_type, exec_type, file_type;

위 코드에서 my_app_exec은 app_exec_type이라는 속성을 상속받습니다. 나중에 app_exec_type에 권한을 주면, 이를 상속받은 모든 타입에 동일한 권한이 적용됩니다.


2. 접근 허용 규칙: allow

allow는 가장 많이 사용하는 규칙으로, "누가, 누구에게, 무엇을 할 수 있는가"를 정의합니다.

2.1 allow 문법 구조

형식: allow [소스 타입] [대상 타입] : [객체 클래스] { [허용 권한] };

항목 설명 예시
소스 타입 동작을 수행하는 주체 (Domain) my_app
대상 타입 동작의 대상이 되는 리소스 my_app_data
객체 클래스 리소스의 종류 file, dir, unix_stream_socket
허용 권한 수행 가능한 동작 read, write, open, getattr

2.2 실무 예제

코드 스니펫
 
# my_app 도메인이 my_app_data 라벨이 붙은 파일을 읽고 쓸 수 있게 허용
allow my_app my_app_data : file { read write open getattr };

# 디렉토리 검색 권한 허용
allow my_app my_app_data_dir : dir { search read };

3. 강력한 금지 규칙: neverallow

neverallow는 시스템의 보안 무결성을 지키기 위한 '최후의 보루'입니다.

  • 컴파일 타임 검사: 정책 빌드 시 allow 규칙이 neverallow를 위반하면 빌드가 즉시 중단됩니다.
  • 용도: 주로 일반 앱이 시스템 핵심 파일(커널, 보안 설정 등)에 접근하는 것을 원천 차단하는 데 사용됩니다.

3.1 neverallow 예제

코드 스니펫
 
# 보안 사고 예방: 일반 앱 도메인은 시스템 설정 파일을 쓸 수 없음
neverallow { appdomain -shell } system_file : file { write append };

# 특정 도메인 간의 데이터 유출 차단
neverallow my_app another_app_data : file { read };

🛠️ 개발자를 위한 팁 & 흔히 하는 실수

✅ 개발 팁 (Best Practices)

  • 매크로 활용: Android 소스 트리(system/sepolicy/public/te_macros)에는 자주 쓰이는 권한 묶음이 매크로로 정의되어 있습니다. r_file_perms (읽기 권한 묶음)나 rw_file_perms (읽기/쓰기 묶음)를 사용하여 가독성을 높이세요.
  • 최소 권한 부여: allow 규칙에 { read write }를 줄 때, 정말 write가 필요한지 다시 확인하세요. 불필요한 권한 부여는 보안 취약점이 됩니다.

❌ 흔히 하는 실수 (Common Mistakes)

  • neverallow 위반 무시: 빌드 에러가 났을 때 neverallow를 지워버리는 경우가 있습니다. 이는 구글의 CTS/VTS 인증 실패로 이어집니다. 정책을 지우기보다 아키텍처(데이터 전달 방식 등)를 수정해야 합니다.
  • 세미콜론 누락: 정책 파일은 각 문장 끝에 반드시 세미콜론(;)이 있어야 합니다. 누락 시 컴파일 에러 메시지가 매우 난해할 수 있으니 주의하세요.
  • 도메인 전환(Domain Transition) 누락: 새로운 프로세스를 띄울 때 type_transition을 설정하지 않으면 의도한 도메인으로 실행되지 않아 권한 오류가 발생합니다.

4. 정책 적용 및 확인 방법

수정한 정책을 시스템에 반영하려면 빌드가 필요합니다.

  1. 정책 컴파일: m sepolicy 명령어로 정책의 문법 오류와 neverallow 위반 여부를 검사합니다.
  2. 동작 확인: adb shell getenforce로 Enforcing 모드임을 확인하고, 로그를 모니터링합니다.
  3. 자동 생성 활용: audit2allow 도구를 사용하면 발생한 로그를 기반으로 권장되는 allow 문법을 자동으로 생성해 주어 편리합니다.

5. 마무리

SELinux 정책 문법은 안드로이드 보안 아키텍처의 언어와 같습니다. type으로 정의하고, attribute로 관리하며, allow로 소통하고, neverallow로 경계를 지키는 이 네 가지 원칙만 기억한다면 복잡한 보안 이슈도 논리적으로 풀어갈 수 있습니다.

이번 포스팅이 여러분의 안전하고 견고한 안드로이드 개발에 도움이 되었기를 바랍니다. 궁금한 점은 언제든 댓글로 남겨주세요!

반응형