Android sepolicy 구성 요소 파헤치기: 주요 파일의 역할과 의미
안드로이드 프레임워크나 HAL(Hardware Abstraction Layer)을 개발하다 보면 반드시 마주치게 되는 것이 바로 sepolicy입니다. 단순히 권한을 허용하는 것(allow)을 넘어, 안드로이드 시스템은 수십 개의 설정 파일이 얽혀 매우 세밀한 보안 그물망을 형성하고 있습니다.
어떤 파일이 파일 시스템의 라벨을 결정하는지, 어떤 파일이 앱의 도메인을 결정하는지 명확히 알아야만 'AVC Denied' 에러의 늪에서 빠르게 빠져나올 수 있습니다. 오늘은 안드로이드 소스 트리 내 sepolicy 디렉터리를 구성하는 주요 파일들의 역할과 그 중요성을 상세히 살펴보겠습니다.

📌 핵심 요약 3줄
- 자원별 라벨링: file, genfs, property, service 등 각 자원의 특성에 맞는 컨텍스트 파일이 개별적으로 존재합니다.
- 정책의 컴파일: 수많은 .te(Type Enforcement) 파일과 설정들이 결합되어 최종적으로 바이너리 형태인 sepolicy 파일로 빌드됩니다.
- 앱 보안의 핵심: seapp_contexts와 mac_permissions.xml은 서명 및 패키지 정보를 기반으로 앱의 보안 도메인을 결정하는 핵심 요소입니다.
1. Android sepolicy 주요 파일 및 역할 총정리
안드로이드 sepolicy는 그 역할에 따라 크게 라벨링(Contexts) 파일과 규칙(Rules) 파일로 나뉩니다.
| 파일명 | 역할 및 설명 | 주요 예시 |
| file_contexts | 물리적 파일 및 디렉터리의 보안 라벨 정의 | /dev/block/.* u:object_r:block_device:s0 |
| service_contexts | 바인더(Binder) 서비스 이름과 라벨 매핑 | activity u:r:activity_service:s0 |
| property_contexts | 시스템 속성(Property) 접근 권한 라벨링 | ro.telephony..* u:object_r:telephony_prop:s0 |
| genfs_contexts | 가상 파일 시스템(proc, sysfs 등) 라벨링 | genfscon sysfs / u:object_r:sysfs:s0 |
| seapp_contexts | 앱의 UID/패키지명에 따른 도메인 할당 | user=_app domain=untrusted_app |
| mac_permissions.xml | 앱 서명(Signature) 기반의 보안 태그 할당 | <signer signature="..."> <seinfo value="platform" /> |
| policy.conf | 컴파일 전 모든 TE 정책이 합쳐진 중간 단계 파일 | allow init shell_exec:file { read } |
| sepolicy (Binary) | 커널이 실제 로드하여 사용하는 바이너리 정책 | 최종 빌드 결과물 |
2. 주요 구성 요소 상세 분석
2.1 컨텍스트(Context) 관리 파일
안드로이드의 모든 자원에는 '이름표'가 붙어 있습니다. 이 이름표를 어디에 붙일지 결정하는 파일들입니다.
- file_contexts: 정규식을 사용하여 특정 경로에 라벨을 붙입니다.
- genfs_contexts: 경로가 고정되지 않거나 커널에서 동적으로 생성되는 가상 파일 시스템을 처리합니다.
- property_contexts: setprop, getprop 시 권한 검사의 기준이 됩니다.
2.2 애플리케이션 보안 관리
안드로이드 앱은 단순히 리눅스 사용자로만 구분되지 않습니다.
- mac_permissions.xml: 특정 인증서로 서명된 앱에 seinfo라는 태그를 붙입니다.
- seapp_contexts: 위에서 부여된 seinfo 태그나 user(UID) 정보를 조합하여 해당 앱이 실행될 Domain을 결정합니다.
2.3 역할 및 사용자 정의 (RBAC)
- roles / users / initial_sid_contexts: SELinux의 기본 아키텍처인 역할 기반 접근 제어(RBAC)를 위한 설정입니다. 안드로이드에서는 대부분 u:r:domain:s0 형태를 유지하며, system_r 역할이 주로 사용됩니다.
3. SELinux 정책 빌드 및 실무 디버깅
수정한 정책을 적용하려면 컴파일 과정을 거쳐야 하며, 적용 여부는 로그를 통해 확인합니다.
- 정책 빌드: m sepolicy 명령어를 통해 전체 정책을 컴파일할 수 있습니다.
- 동적 모드 변경: 개발 중에는 setenforce 0(Permissive)으로 차단 없이 로그만 확인할 수 있습니다.
- 로그 확인: adb shell dmesg | grep avc 또는 logcat | grep avc를 통해 거부된 권한을 실시간으로 분석합니다.
🛠️ 개발자를 위한 팁 & 흔히 하는 실수
✅ 개발 팁 (Best Practices)
- 정규식 최적화: file_contexts에서 지나치게 넓은 정규식(예: /data/.*)을 사용하면 시스템 전체 보안이 취약해집니다. 가급적 구체적인 경로를 지정하세요.
- Label 확인은 필수: 정책을 추가했는데도 동작하지 않는다면, 실제 파일의 라벨이 의도대로 붙었는지 ls -Z 명령어로 반드시 확인해야 합니다. (restorecon이 필요한 경우가 많습니다.)
❌ 흔히 하는 실수 (Common Mistakes)
- seapp_contexts 설정 오류: 신규 앱을 platform_app으로 동작시키려 할 때, mac_permissions.xml에 서명 정보를 추가하지 않고 seapp_contexts만 수정하면 적용되지 않습니다.
- neverallow 위반: 구글의 기본 정책에는 강력한 거부 규칙(neverallow)이 있습니다. 본인의 정책이 이를 위반하면 빌드 타임에 에러가 발생하며, 이때는 권한을 요청하기보다 시스템 설계를 변경하는 것이 맞습니다.
- 바이너리 직접 수정 시도: 커널에 로드된 sepolicy 바이너리를 직접 수정하는 것은 불가능합니다. 항상 소스 레벨(.te)에서 수정하고 다시 빌드해야 합니다.
4. 결론
Android sepolicy는 수많은 파일이 유기적으로 연결되어 거대한 보안 체계를 이룹니다. file_contexts가 파일의 이름표를 정하고, te 파일이 그 이름표 사이의 동작을 허용하는 원리를 이해한다면, 복잡한 보안 이슈도 논리적으로 해결할 수 있습니다.
오늘 정리한 파일 구조가 여러분의 안드로이드 시스템 개발에 든든한 가이드가 되길 바랍니다. 궁금한 점은 언제든 댓글로 남겨주세요!
'Android System & AOSP Engineering > Android Security & SELinux' 카테고리의 다른 글
| Android SELinux 정책 문법 완벽 정리: type, allow, neverallow 예제 가이드 (0) | 2025.04.30 |
|---|---|
| Android SELinux avc: denied 로그 분석 및 해결 완벽 가이드 (0) | 2025.04.29 |
| Android SELinux 정책 파일 구조 분석: public vs private 차이점 정리 (0) | 2025.04.27 |
| Android sepolicy 구조 완벽 분석: file_contexts부터 빌드 과정까지 (0) | 2025.04.26 |
| Android 보안의 핵심 SELinux: 역할과 필요성 완벽 정리 (Lollipop 이후 필수) (0) | 2025.04.25 |