1. 서론: 왜 지금 SELinux를 다시 봐야 하는가?
Android 생태계가 파편화에서 통합으로, 그리고 다시 모듈화(Project Treble)로 진화함에 따라 보안 모델의 핵심인 SELinux(Security-Enhanced Linux) 역시 매 버전마다 정교해지고 있습니다. 과거에는 단순히 실행 권한을 허용하는 수준이었다면, 최신 Android에서는 시스템과 벤더 영역 간의 엄격한 분리(Isolation)가 핵심입니다. 이 글에서는 최신 Android 버전에서 변경된 정책 체계와 실무에서 바로 활용할 수 있는 디버깅 팁을 정리해 보겠습니다.

2. 핵심 요약 (3줄)
- 영역 분리 강화: System과 Vendor 도메인 간의 결합도를 낮추기 위해 attributes와 신규 도메인 정의가 더욱 세밀해졌습니다.
- 정책 관리 체계화: BOARD_SEPOLICY_DIRS와 PRODUCT_PRIVATE_SEPOLICY_DIRS의 명확한 구분을 통한 제품별 맞춤형 보안 적용이 강조됩니다.
- 실무형 디버깅: avc: denied 로그 분석을 통한 신속한 정책 반영과 CIL 문법의 이해가 필수적입니다.
3. SELinux 정책의 주요 변경 사항
3.1 새로운 도메인 및 속성(Attribute) 추가
최신 Android는 특정 프로세스가 너무 많은 권한을 가지지 않도록 Least Privilege(최소 권한) 원칙에 따라 도메인을 쪼개고 있습니다.
| 구분 | 주요 변경 사항 | 목적 |
| Micro-segmentation | 시스템 서비스를 기능별 세부 도메인으로 분리 | 특정 서비스 탈취 시 피해 최소화 |
| Property Contexts | vendor_internal_prop 등 신규 속성 추가 | 벤더 속성에 대한 시스템 접근 제어 |
| HAL Isolation | Passthrough HAL에서 Binderized HAL로의 완전 전환 | 하드웨어 접근 권한의 엄격한 격리 |
3.2 정책 코드 예시 (CIL 및 Type Definition)
최신 정책에서는 기존 .te 파일 외에도 컴파일된 .cil 형태의 이해가 필요할 때가 있습니다.
# 새로운 서비스 도메인 정의 예시 (CIL 형태)
(type my_new_service)
(typeattribute my_new_service_server)
# system_server가 해당 서비스를 실행하고 시그널을 보낼 수 있도록 허용
(allow system_server my_new_service (process (transition sigchld)))
4. Vendor 및 Product 영역의 정책 분리
Android 10 이상부터는 시스템과 벤더 정책의 혼합을 방지하기 위해 디렉터리 구조를 엄격히 구분합니다.
4.1 정책 정의 디렉터리 비교
| 변수명 | 위치 | 용도 |
| BOARD_SEPOLICY_DIRS | device/ 또는 vendor/ | SoC 및 하드웨어 보드 관련 공통 정책 |
| PRODUCT_PRIVATE_SEPOLICY_DIRS | product/ | 특정 제품(모델)에만 국한된 비공개 정책 |
| SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS | system_ext/ | 시스템 확장 기능을 위한 정책 |
5. 실전 디버깅: AVC Denied 해결 프로세스
정책 변경 후 실제 하드웨어에서 발생하는 거부 로그를 분석하고 반영하는 과정입니다.
5.1 로그 확인 명령어
# 실시간 로그 모니터링
adb logcat -b all | grep "avc: denied"
# Audit2allow를 활용한 정책 자동 생성 (참고용)
adb logcat -d | audit2allow -p out/target/product/<device>/root/sepolicy
5.2 권한 수정 프로세스
로그에 scontext=u:r:my_service:s0와 tcontext=u:object_r:vendor_data_file:s0이 나타난다면 아래와 같이 대응합니다.
| 단계 | 작업 내용 | 적용 코드 |
| 1단계 | 문제 원인 식별 | my_service가 vendor_data_file 디렉터리를 읽으려다 거부됨 |
| 2단계 | TE 파일 수정 | allow my_service vendor_data_file:dir { read open getattr }; 추가 |
| 3단계 | 빌드 및 반영 | make selinux_policy 또는 전체 빌드 후 이미지 플래싱 |
💡 개발을 위한 팁 (Tips)
- Neverallow를 주의하세요: AOSP 상위 레벨에서 정의된 neverallow 규칙은 벤더 영역에서 강제로 allow 할 수 없습니다. 이 경우 정책을 우회하기보다 아키텍처 자체를 검토해야 합니다.
- Permissive 모드 활용: 개발 초기 단계에서는 setenforce 0 명령어로 Permissive 모드로 전환하여 필요한 모든 로그를 한 번에 수집한 뒤 정책을 한꺼번에 작성하는 것이 효율적입니다.
⚠️ 흔히 하는 실수 (Common Mistakes)
- _tmp 속성 남용: 테스트를 위해 임시로 넓은 권한(예: domain 속성 부여)을 주었다가 출시 시점에 보안 취약점으로 지적받는 경우가 많습니다.
- Context 불일치: 파일 시스템에 file_contexts를 정의했더라도, 실제 파일이 생성될 때 restorecon이 수행되지 않으면 정책이 적용되지 않을 수 있습니다.
- Labeling 누락: 새로운 sysfs나 debugfs 노드를 추가하고도 별도의 Label을 지정하지 않아 sysfs:file 전체에 권한을 요청하는 실수는 지양해야 합니다.
6. 결론
최신 Android의 SELinux 정책은 더 이상 단순한 "관문"이 아니라, 시스템 아키텍처의 일부로 자리 잡았습니다. 특히 BOARD와 PRODUCT 간의 정책 분리를 명확히 이해하는 것은 유지보수가 용이한 코드를 작성하는 첫걸음입니다. 위에서 살펴본 변경 사항과 디버깅 절차를 숙지하여, 보안과 성능을 모두 잡는 안드로이드 시스템 개발을 진행하시기 바랍니다.
'Android System & AOSP Engineering > Android Security & SELinux' 카테고리의 다른 글
| Android SELinux 보안 트렌드: Zero Trust와 eBPF가 가져올 미래 (0) | 2025.05.19 |
|---|---|
| Android 10부터 14까지: 버전별 SELinux 정책 변화 및 보안 강화 총정리 (0) | 2025.05.16 |
| AOSP 보안 가이드라인을 준수하는 SELinux 정책 검토 및 분석 방법 (0) | 2025.05.15 |
| SELinux 정책 최적화 가이드: 성능과 보안을 모두 잡는 5가지 기법 (0) | 2025.05.14 |
| 안드로이드 SELinux 보안의 핵심: neverallow 정책 개념 및 활용 가이드 (0) | 2025.05.13 |