안드로이드 프레임워크나 드라이버를 개발하다 보면 코드는 완벽한데 기능이 동작하지 않는 당혹스러운 상황을 자주 마주하게 됩니다. 대부분의 경우 원인은 안드로이드의 강력한 보안 엔진인 SELinux에 있습니다. SELinux는 정책에 정의되지 않은 모든 접근을 차단하며, 이때 남기는 기록이 바로 'avc: denied' 로그입니다.
본 포스팅에서는 adb logcat과 dmesg를 활용하여 SELinux 거부 로그를 정밀하게 분석하고, audit2allow 도구 및 .te 파일 수정을 통해 문제를 해결하는 실무 프로세스를 상세히 다룹니다.

📌 핵심 요약 3줄
- 로그 구조 파악: scontext(주체), tcontext(대상), tclass(유형), denied(작업)를 통해 차단 원인을 정확히 진단합니다.
- 해결 전략: audit2allow 도구로 정책을 자동 생성하거나, .te 파일을 수동 수정하여 최소 권한을 부여합니다.
- 검증 프로세스: Permissive 모드에서 동작을 먼저 확인한 뒤, Enforcing 모드에서 정책이 정상 반영되었는지 최종 검토합니다.
1. SELinux avc: denied 로그 구조 분석
SELinux 거부 로그는 한 줄에 매우 많은 정보를 담고 있습니다. 각 필드의 의미를 아는 것이 디버깅의 시작입니다.
[avc: denied 로그 주요 필드 해설]
| 필드명 | 의미 | 예시 |
| denied { action } | 허용되지 않은 접근 유형 | read, write, open, execute, call |
| scontext (Source) | 접근을 시도한 프로세스의 보안 도메인 | u:r:untrusted_app:s0 |
| tcontext (Target) | 접근 대상 리소스의 보안 타입 | u:object_r:system_data_file:s0 |
| tclass | 문제의 대상이 되는 객체의 클래스 | file, dir, unix_stream_socket, binder |
| permissive | 차단 여부 (0: 강제 차단, 1: 로그만 기록) | permissive=0 |
2. 실전 로그 분석 사례
실제 개발 중 자주 발생하는 로그를 통해 분석 방법을 살펴보겠습니다.
예제 로그:
avc: denied { write } for pid=5678 comm="custom_daemon" path="/data/log.txt" scontext=u:r:custom_daemon:s0 tcontext=u:object_r:system_data_file:s0 tclass=file permissive=0
분석 결과:
- 주체(scontext): custom_daemon이라는 프로세스가
- 대상(tcontext): system_data_file 타입의 파일에 대해
- 행위(action): 쓰기(write)를 시도했으나
- 결과: 정책에 허용 규칙이 없어 실제로 차단됨(permissive=0).
3. 단계별 해결 방법
3.1. audit2allow 도구를 이용한 자동 정책 생성
로그가 방대하거나 복잡할 때는 audit2allow 도구를 사용하는 것이 가장 효율적입니다.
[audit2allow 작업 순서]
| 단계 | 작업 내용 | 실행 명령어 |
| 1. 로그 수집 | dmesg에서 거부 로그만 추출하여 파일로 저장 | adb shell dmesg |
| 2. 정책 추출 | 로그를 분석해 필요한 allow 규칙 생성 | audit2allow -i avc_log.txt -p [policy_path] |
| 3. 규칙 검토 | 생성된 구문이 보안상 적절한지 확인 | 출력된 "allow scontext tcontext:tclass action;" 확인 |
3.2. 수동 정책 수정 (.te 파일)
보안성을 높이기 위해 직접 .te 파일을 수정하는 방법입니다. 해당 도메인의 정책 파일에 아래 형식을 추가합니다.
(작성 예시)
allow custom_daemon system_data_file:file { write open getattr };
💡 개발을 위한 팁
- Permissive 모드 활용: "adb shell setenforce 0"을 실행하면 시스템 전체를 허용 모드로 바꿀 수 있습니다. 기능이 동작하지 않는 원인이 '코드 문제'인지 'SELinux 문제'인지 판별할 때 유용합니다.
- 속성(Attribute) 활용: 특정 타입에 일일이 권한을 주기보다 domain, file_type 같은 속성을 적절히 활용하면 정책 관리가 훨씬 수월해집니다.
- 컴파일 환경 확인: sepolicy 수정 후에는 반드시 "mmm system/sepolicy" 등을 통해 정책을 다시 빌드하고 이미지를 플래싱해야 적용됩니다.
⚠️ 흔히 하는 실수
[트러블슈팅 및 주의사항]
| 구분 | 내용 |
| 과도한 권한 부여 | 귀찮다는 이유로 dac_override 같은 강력한 권한을 주면 보안 체계가 무너집니다. 반드시 필요한 최소 권한만 허용하세요. |
| Neverallow 위반 | 구글이 금지한 'neverallow' 규칙을 어기면 빌드 타임에 에러가 발생합니다. 이 경우 설계 자체를 변경해야 할 수도 있습니다. |
| 도메인 전이 누락 | 새로운 바이너리를 실행할 때 적절한 도메인 전이(Transition) 규칙을 넣지 않으면, 실행 파일이 권한이 부족한 부모 도메인에 머물게 됩니다. |
4. 결론
SELinux 정책 대응은 안드로이드 임베디드 개발자의 숙명과도 같습니다. 단순히 차단 로그를 없애는 것에 그치지 않고, 왜 이 접근이 차단되었으며 보안상 허용해도 괜찮은지 판단하는 능력이 중요합니다.
본 가이드에서 소개한 분석법과 정책 수정 프로세스를 활용하여 안정적이고 보안이 강화된 안드로이드 시스템을 구축하시기 바랍니다. 해결되지 않는 까다로운 avc: denied 로그가 있다면 댓글로 남겨주세요! 함께 고민해 보겠습니다.
'Android System & AOSP Engineering > Android Security & SELinux' 카테고리의 다른 글
| 안드로이드 SELinux 디버깅 완벽 가이드: dmesg와 logcat 활용법 (0) | 2025.05.12 |
|---|---|
| 안드로이드 SELinux 정책 생성 가이드: audit2allow 활용법 및 검증 정리 (0) | 2025.05.11 |
| Android Third-party 앱 SELinux 정책 가이드: untrusted_app과 isolated_app 차이점 (0) | 2025.05.09 |
| 안드로이드 Vendor 바이너리 SELinux 정책 적용 가이드: sepolicy 설정부터 디버깅까지 (0) | 2025.05.08 |
| 안드로이드 시스템 서비스 추가 가이드: SELinux 정책(sepolicy) 완벽 설정법 (0) | 2025.05.08 |