SELinux 맞춤설정

기본 수준의 SELinux 기능을 통합하고 결과를 철저하게 분석했다면 맞춤설정에 적용할 자체 정책 설정을 Android 운영체제에 추가할 수 있습니다. 정책은 반드시 Android 호환성 프로그램의 요구사항을 따라야 하며 SELinux의 기본 설정을 삭제하면 안 됩니다.

제조업체는 기존 SELinux 정책을 삭제하면 안 됩니다. 기존 정책을 삭제하면 Android SELinux 구현과 이 구현에서 관리하는 애플리케이션이 손상될 수 있습니다. 규정에 맞게 실행되도록 개선해야 할 타사 애플리케이션의 경우도 마찬가지입니다. 애플리케이션이 SELinux 지원 기기에서 계속 작동하기 위해 어떠한 수정도 필요해서는 안 됩니다.

SELinux 맞춤설정을 시작할 때 해야 할 작업은 다음과 같습니다.

  • 모든 새 데몬에 관한 SELinux 정책 작성
  • 적합한 경우 항상 사전 정의된 도메인 사용
  • init 서비스로 생성된 프로세스에 도메인 할당
  • 정책을 작성하기 전에 관련 매크로 숙지
  • 핵심 정책 중 변경된 사항을 AOSP에 제출

또한 해서는 안 되는 일은 다음과 같습니다.

  • 호환되지 않는 정책 만들기
  • 최종 사용자 정책의 맞춤설정 허용
  • MDM 정책의 맞춤설정 허용
  • 정책 위반으로 사용자를 불안하게 만들기
  • 백도어 추가

구체적인 요구사항은 Android 호환성 정의 문서커널 보안 기능 섹션을 참조하세요.

SELinux는 허용 목록 접근방식을 사용합니다. 즉, 정책에서 명시적으로 허용된 액세스 권한만 부여됩니다. Android의 기본 SELinux 정책은 이미 Android 오픈소스 프로젝트를 지원하므로 SELinux 설정 수정이 필요하지 않습니다. SELinux 설정을 맞춤설정할 때 기존 애플리케이션이 손상되지 않도록 주의하세요. 시작하려면 다음 단계를 따르세요.

  1. 최신 Android 커널을 사용합니다.
  2. 최소 권한의 원칙을 적용합니다.
  3. Android에 직접 추가한 항목만 제출합니다. 기본 정책은 Android 오픈소스 프로젝트 코드베이스에 자동으로 적용됩니다.
  4. 소프트웨어 구성요소는 단일 작업을 실행하는 모듈로 분류합니다.
  5. 이 작업 및 관련 없는 기능을 분리하는 SELinux 정책을 생성합니다.
  6. /device/manufacturer/device-name/sepolicy 디렉터리 내의 *.te 파일(SELinux 정책 소스 파일의 확장자)에 정책을 넣고 BOARD_SEPOLICY 변수를 사용하여 빌드에 포함합니다.
  7. 처음에는 신규 도메인을 허용 가능한 상태로 만듭니다. 도메인의 .te 파일에서 허용 선언을 이용하면 됩니다.
  8. 결과를 분석하고 도메인 정의를 조정합니다.
  9. userdebug 빌드에서 추가적인 거부가 표시되지 않으면 허용 선언을 삭제합니다.

SELinux 정책 변경사항을 통합한 후, 앞으로 SELinux 호환성을 보장하기 위한 단계를 개발 워크플로에 추가합니다. 이상적인 소프트웨어 개발 프로세스에서는 소프트웨어 모델이 수정된 경우에만 SELinux 정책이 변경되고 실제 구현이 수정된 경우에는 변경되지 않습니다.

SELinux 맞춤설정을 시작하려면 먼저 Android에 추가한 사항에 대한 감사를 수행합니다. 새로운 기능을 실행하는 구성요소를 추가한 경우 시행 모드를 켜기 전에 구성요소가 Android의 보안 정책과 OEM의 관련 정책을 준수하는지 확인합니다.

지나치게 제한적이며 호환성이 낮으면 기기 기능이 손상됩니다. 불필요한 문제를 방지하기 위해서는 더 일반적이고 호환성이 높은 편이 낫습니다. 반대로 다른 사용자들에게 도움이 될 수 있는 변경사항이라면 수정사항을 기본 SELinux 정책에 패치로 제출합니다. 패치가 기본 보안 정책에 적용되면 새로운 Android 버전이 출시될 때마다 매번 변경할 필요가 없습니다.

정책 구문 예시

SELinux는 M4 컴퓨터 언어를 기반으로 하므로 시간을 절약할 수 있는 다양한 매크로를 지원합니다.

다음 예에서는 모든 도메인에 /dev/null에서 읽기 또는 쓰기 권한과 /dev/zero에서 읽기 권한을 부여합니다.

# Allow read / write access to /dev/null
allow domain null_device:chr_file { getattr open read ioctl lock append write};

# Allow read-only access to /dev/zero
allow domain zero_device:chr_file { getattr open read ioctl lock };

SELinux의 *_file_perms 매크로(약식)를 이용해 같은 구문을 작성할 수도 있습니다.

# Allow read / write access to /dev/null
allow domain null_device:chr_file rw_file_perms;

# Allow read-only access to /dev/zero
allow domain zero_device:chr_file r_file_perms;

정책 예시

다음은 DHCP를 위한 완전한 예시 정책입니다.

type dhcp, domain;
permissive dhcp;
type dhcp_exec, exec_type, file_type;
type dhcp_data_file, file_type, data_file_type;

init_daemon_domain(dhcp)
net_domain(dhcp)

allow dhcp self:capability { setgid setuid net_admin net_raw net_bind_service
};
allow dhcp self:packet_socket create_socket_perms;
allow dhcp self:netlink_route_socket { create_socket_perms nlmsg_write };
allow dhcp shell_exec:file rx_file_perms;
allow dhcp system_file:file rx_file_perms;
# For /proc/sys/net/ipv4/conf/*/promote_secondaries
allow dhcp proc_net:file write;
allow dhcp system_prop:property_service set ;
unix_socket_connect(dhcp, property, init)

type_transition dhcp system_data_file:{ dir file } dhcp_data_file;
allow dhcp dhcp_data_file:dir create_dir_perms;
allow dhcp dhcp_data_file:file create_file_perms;

allow dhcp netd:fd use;
allow dhcp netd:fifo_file rw_file_perms;
allow dhcp netd:{ dgram_socket_class_set unix_stream_socket } { read write };
allow dhcp netd:{ netlink_kobject_uevent_socket netlink_route_socket
netlink_nflog_socket } { read write };

예시를 분석해 보겠습니다.

첫 번째 줄의 유형 선언은 DHCP 데몬이 기본 보안 정책(domain)을 상속한다는 뜻입니다. 앞서 예를 든 구문을 통해 DHCP는 /dev/null에서 읽거나 쓸 수 있습니다.

두 번째 줄에서는 DHCP를 허용 도메인으로 식별합니다.

init_daemon_domain(dhcp) 줄의 정책은 DHCP가 init으로부터 생성되고 서로 통신할 수 있음을 명시합니다.

net_domain(dhcp) 줄의 정책은 DHCP가 net 도메인의 일반 네트워크 기능(TCP 패킷 읽고 쓰기, 소켓 통신, DNS 요청 실행 등)을 사용할 수 있도록 합니다.

allow dhcp proc_net:file write; 줄의 정책은 DHCP가 /proc에 있는 특정 파일에 쓸 수 있게 합니다. 이는 SELinux에서 세세한 수준으로 파일에 라벨을 지정하는 것을 보여 줍니다. /proc/sys/net 하위의 파일에만 쓸 수 있도록 proc_net 라벨을 사용합니다.

allow dhcp netd:fd use;로 시작되는 예시의 마지막 부분은 애플리케이션이 상호작용하도록 허용하는 방법을 보여 줍니다. DHCP와 netd는 파일 설명자, FIFO 파일, 데이터그램 소켓, UNIX 스트림 소켓을 통해 서로 통신할 수 있습니다. DHCP는 데이터그램 소켓과 UNIX 스트림 소켓에서만 읽고 쓸 수 있으며 새로 만들거나 열 수는 없습니다.

제어 가능한 항목

클래스 권한
파일

ioctl read write create getattr setattr lock relabelfrom relabelto append
unlink link rename execute swapon quotaon mounton
디렉터리

add_name remove_name reparent search rmdir open audit_access execmod
소켓

ioctl read write create getattr setattr lock relabelfrom relabelto append bind
connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg
name_bind
파일 시스템

mount remount unmount getattr relabelfrom relabelto transition associate
quotamod quotaget
절차

fork transition sigchld sigkill sigstop signull signal ptrace getsched setsched
getsession getpgid setpgid getcap setcap share getattr setexec setfscreate
noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem
execstack execheap setkeycreate setsockcreate
보안

compute_av compute_create compute_member check_context load_policy
compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot
read_policy
기능

chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap
linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock
ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin
sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write
audit_control setfcap

더보기

더보기

neverallow 규칙

SELinux의 neverallow 규칙은 절대 발생해서는 안 되는 동작을 금지합니다. 호환성 테스트를 사용하여 SELinux neverallow 규칙이 여러 기기에 걸쳐 시행됩니다.

다음 가이드라인을 준수하는 제조업체는 맞춤설정 시 neverallow 규칙과 관련한 오류를 방지할 수 있습니다. 다음에서 사용된 규칙 번호는 Android 5.1을 따르며 출시 버전에 따라 변경될 수 있습니다.

규칙 48: neverallow { domain -debuggerd -vold -dumpstate -system_server } self:capability sys_ptrace;
ptrace man 페이지를 참조하세요. sys_ptrace 기능은 모든 프로세스를 ptrace하는 기능을 부여합니다. 이 기능을 통해 다른 프로세스를 상당 부분 제어할 수 있으며 이 기능은 규칙에 설명된 대로 지정된 시스템 구성요소에만 속해야 합니다. 사용자용 빌드가 아니거나 불필요한 기능이 존재한다는 것을 나타내기 위해 이 기능이 필요할 때가 많습니다. 불필요한 구성요소를 삭제합니다.

규칙 76: neverallow { domain -appdomain -dumpstate -shell -system_server -zygote } { file_type -system_file -exec_type }:file execute;
시스템상에서 임의 코드의 실행을 방지하는 규칙입니다. 구체적으로는 자체 검사 부팅과 같은 메커니즘 덕분에 보안이 보장되는 /system의 코드만 실행되도록 합니다. 보통 neverallow 규칙에 문제가 발생했을 때 가장 좋은 해결책은 문제의 코드를 /system 파티션으로 옮기는 것입니다.

Android 8.0 이상에서 SEPolicy 맞춤설정

이 섹션에서는 Android 오픈소스 프로젝트(AOSP) SEPolicy 및 SEPolicy 확장 프로그램 관련 세부정보를 포함하여 Android 8.0 이상의 공급업체 SELinux 정책에 관한 가이드라인을 제시합니다. SELinux 정책이 파티션과 Android 버전에 걸쳐 호환되는 방법에 관한 자세한 내용은 호환성 문서를 참조하세요.

정책 위치

Android 7.0 및 이전 버전에서는 기기 제조업체가 BOARD_SEPOLICY_DIRS에 정책을 추가할 수 있었습니다(여러 기기 유형에 걸쳐 AOSP 정책을 강화하기 위한 정책 포함). Android 8.0 이상 버전에서 BOARD_SEPOLICY_DIRS에 정책을 추가하면 공급업체 이미지에만 정책이 삽입됩니다.

Android 8.0 이상에서는 AOSP의 다음 위치에 정책이 존재합니다.

  • system/sepolicy/public. 공급업체별 정책에 사용하기 위해 내보낸 정책을 포함합니다. 모두 Android 8.0 호환성 인프라를 따라야 합니다. 공개 정책은 여러 버전에 걸쳐 지속되므로 맞춤 정책에 어떤 /public이라도 포함할 수 있습니다. 그러므로 /public에 배치할 수 있는 정책의 유형은 좀 더 제한됩니다. 이를 플랫폼의 내보낸 정책 API라고 생각해 보세요. /system/vendor 간의 인터페이스를 처리하기 위한 모든 것이 여기에 속합니다.
  • system/sepolicy/private. 시스템 이미지의 작동에 필요하며 공급업체 이미지 정책에 언급되지 않은 정책을 포함합니다.
  • system/sepolicy/vendor. /vendor에 위치하지만 기기별 디렉터리가 아닌 핵심 플랫폼 경로에 존재하는 구성요소의 정책을 포함합니다. 이 위치는 기기와 전역 구성요소 간 빌드 시스템의 차이로 인한 아티팩트입니다. 즉, 개념적으로는 아래에 설명된 기기별 정책의 일부입니다.
  • device/manufacturer/device-name/sepolicy. 기기별 정책을 포함합니다. Android 8.0 이상 버전에서는 공급업체 이미지의 구성요소 정책에 부합하는 정책의 기기 맞춤설정도 포함됩니다.

Android 11 이상에서는 system_ext 및 제품 파티션에도 파티션별 정책이 포함될 수 있습니다. system_ext 및 제품 정책도 공개 및 비공개로 분할되며, 공급업체는 system_ext와 제품의 공개 정책(예: 시스템 정책)을 사용할 수 있습니다.

  • SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS. 공급업체별 정책에 사용하기 위해 내보낸 정책을 포함합니다. system_ext 파티션에 설치됩니다.
  • SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS: system_ext 이미지의 작동에 필요하며 공급업체 이미지 정책에 언급되지 않은 정책을 포함합니다. system_ext 파티션에 설치됩니다.
  • PRODUCT_PUBLIC_SEPOLICY_DIRS. 공급업체별 정책에 사용하기 위해 내보낸 정책을 포함합니다. 제품 파티션에 설치됩니다.
  • PRODUCT_PRIVATE_SEPOLICY_DIRS. 제품 이미지의 작동에 필요하며 공급업체 이미지 정책에 언급되지 않은 정책을 포함합니다. 제품 파티션에 설치됩니다.
참고: GSI가 사용되는 경우 OEM의 system_ext 및 제품 파티션은 마운트되지 않습니다. OEM별 유형 정의가 누락되어 OEM의 system_ext 및 제품 공개 정책을 사용하는 공급업체 sepolicy 규칙이 NOP가 됩니다.
참고: system_ext 및 제품 공개 정책을 사용할 때는 특히 주의하시기 바랍니다. 공개 정책은 system_ext/product와 공급업체 간에 내보낸 API 역할을 합니다. 파트너는 자체적으로 호환성 문제를 관리해야 합니다.

지원되는 정책 시나리오

Android 8.0 이상 버전을 실행하는 기기의 경우, 공급업체 이미지는 OEM 시스템 이미지 및 Google에서 제공한 참조 AOSP 시스템 이미지와 호환되어야 합니다. 또한 참조 이미지상에서 CTS를 통과해야 합니다. 이는 프레임워크와 공급업체 코드 간의 명확한 구분을 보장하기 위함입니다. 이러한 기기는 다음 시나리오를 지원합니다.

공급업체 이미지 전용 확장 프로그램

: 공급업체 이미지의 프로세스를 지원하는 새 서비스를 공급업체 이미지의 vndservicemanager에 추가하는 경우

이전 Android 버전을 실행하는 기기와 마찬가지로 기기별 맞춤설정을 device/manufacturer/device-name/sepolicy에 추가합니다. 공급업체 구성요소가 다른 공급업체 구성요소와(만) 상호작용하는 방식을 제어하는 새 정책은 device/manufacturer/device-name/sepolicy에만 존재하는 유형을 포함해야 합니다. 여기에 작성된 정책은 공급업체 코드가 작동하도록 허용하고, 프레임워크 전용 OTA의 일부로 업데이트되지 않으며, 참조 AOSP 시스템 이미지가 있는 기기의 통합 정책에 포함됩니다.

AOSP에서 작동하기 위한 공급업체 이미지 지원

: AOSP가 정의한 HAL을 구현하는 (공급업체 이미지에서 hwservicemanager로 등록된) 새 프로세스 추가

이전 Android 버전을 실행하는 기기와 마찬가지로 기기별 맞춤설정을 device/manufacturer/device-name/sepolicy에서 실행합니다. system/sepolicy/public/의 일부로 내보낸 정책은 사용 가능하며 공급업체 정책의 한 부분으로 제공됩니다. 공개 정책의 유형과 속성은 제공된 neverallow 제약에 따라 신규 공급업체별 부분과의 상호작용에 영향을 주는 새 규칙에 사용될 수 있습니다. 공급업체 전용과 마찬가지로 새 정책은 프레임워크 전용 OTA의 일부로 업데이트되지 않으며, 참조 AOSP 시스템 이미지가 있는 기기의 통합 정책에 포함됩니다.

시스템 이미지 전용 확장 프로그램

: 시스템 이미지로부터 다른 프로세스에서만 액세스하며 servicemanager에 등록된 신규 서비스 추가

이 정책을 system/sepolicy/private에 추가하세요. 새 부분이 공급업체 이미지의 새 구성요소와 상호작용할 필요가 없는 경우, 파트너 시스템 이미지의 기능을 사용하기 위해 추가 프로세스나 객체를 추가할 수 있습니다. 구체적으로 이러한 프로세스나 객체는 공급업체 이미지의 정책 없이도 정상적으로 작동해야 합니다. system/sepolicy/public에서 내보낸 정책은 공급업체 이미지 전용 확장 프로그램과 마찬가지로 여기에서 사용할 수 있습니다. 이 정책은 시스템 이미지의 일부이며 프레임워크 전용 OTA에서 업데이트될 수 있지만, 참조 AOSP 시스템 이미지를 사용할 때는 포함되지 않습니다.

확장 AOSP 구성요소를 제공하는 공급업체 이미지 확장 프로그램

: AOSP 시스템 이미지에도 존재하는 확장 클라이언트가 사용하는 신규 비 AOSP HAL(예: 확장 system_server)

시스템과 공급업체 간의 상호작용 정책은 공급업체 파티션에 있는 device/manufacturer/device-name/sepolicy 디렉터리에 포함되어야 합니다. 참조 AOSP 이미지와 호환되도록 공급업체 이미지를 추가로 지원하는 위 시나리오와 유사합니다. 단, 수정된 AOSP 구성요소가 시스템 파티션의 나머지 부분과 함께 제대로 작동하려면 추가 정책이 필요할 수도 있습니다. 이는 공개 AOSP 유형 라벨이 있는 한 상관없습니다.

공개 AOSP 구성요소와 시스템 이미지 전용 확장 프로그램의 상호작용 정책은 system/sepolicy/private에 있어야 합니다.

AOSP 인터페이스만 액세스하는 시스템 이미지 확장 프로그램

: 새로운 비 AOSP 시스템 프로세스에서 AOSP가 의존하는 HAL에 액세스해야 하는 경우

시스템 이미지 전용 확장 프로그램 예시와 유사하지만, 새로운 시스템 구성요소가 system/vendor 인터페이스 전반에서 상호작용할 수도 있다는 점이 다릅니다. 새 시스템 구성요소 정책은 system/sepolicy/private에 위치해야 합니다. 이는 system/sepolicy/public에 있는 AOSP에 의해 이미 설정된 인터페이스를 통하는 경우(즉, 기능에 필요한 유형과 속성이 있는 경우) 허용됩니다. 정책은 기기별 정책에 포함될 수 있지만, 다른 system/sepolicy/private 유형을 사용하거나 프레임워크 전용 업데이트의 결과에 따라 (정책에 영향을 미치는 어떠한 방식으로도) 변경하는 것은 불가능합니다. 정책은 프레임워크 전용 OTA에서 변경될 수 있지만 AOSP 시스템 이미지를 사용하는 경우에는 존재하지 않습니다. 또한 새 시스템 구성요소도 가지지 않습니다.

새로운 시스템 구성요소를 제공하는 공급업체 이미지 확장 프로그램

: AOSP 유사체가 없는(따라서 자체 도메인이 필요한) 클라이언트 프로세스가 사용할 새로운 비 AOSP HAL 추가

AOSP 확장 예시와 유사하게, 시스템과 공급업체 간의 상호작용 정책은 공급업체 파티션에 위치한 device/manufacturer/device-name/sepolicy 디렉터리에 있어야 합니다. 이는 시스템 정책이 공급업체별 세부정보를 알 수 없도록 하기 위함입니다. system/sepolicy/public에서 정책을 확장하는 공개 유형을 새로 추가할 수 있습니다. 이는 기존 AOSP 정책에 추가하는 방식으로만 가능하며, AOSP 공개 정책을 삭제해서는 안 됩니다. 이렇게 하면 새 공개 유형을 system/sepolicy/privatedevice/manufacturer/device-name/sepolicy의 정책에 사용할 수 있습니다.

system/sepolicy/public에 추가할 때마다 복잡성이 증가한다는 점에 유의하시기 바랍니다. 매핑 파일에 기록되어야 하고 다른 제한사항이 적용되는 새로운 호환성을 보장해야 하기 때문입니다. 새 유형과 이에 상응하는 허용 규칙만 system/sepolicy/public에 추가할 수 있으며 속성 및 다른 정책 구문은 지원되지 않습니다. 또한 새 공개 유형은 /vendor 정책에 있는 객체에 라벨을 지정하는 데 직접적으로 사용될 수 없습니다.

지원되지 않는 정책 시나리오

Android 8.0 이상을 실행 중인 기기는 다음 정책 시나리오와 예시를 지원하지 않습니다.

프레임워크 전용 OTA 후에 새 공급업체 이미지 구성요소에 대한 권한이 필요한 시스템 이미지의 추가 확장 프로그램

: 자체 도메인이 필요한 새로운 비 AOSP 시스템 프로세스가 다음 Android 버전에 추가되어 새로운 비 AOSP HAL에 액세스해야 하는 경우

새 시스템 유형이 프레임워크 전용 OTA에 도입되었다는 것을 제외하면 새로운 (비 AOSP) 시스템 및 공급업체 구성요소 상호작용과 비슷합니다. 새 유형이 system/sepolicy/public의 정책에 추가되더라도 기존 공급업체 정책은 Android 8.0 시스템 공개 정책만 추적하므로 새 유형에 관해 알 수 없습니다. AOSP는 속성(예: hal_foo 속성)을 통해 공급업체 제공 리소스를 노출하여 이를 처리합니다. 그러나 이 방법은 속성 파트너 확장 프로그램이 system/sepolicy/public에서 지원되지 않으므로 공급업체 정책에 사용할 수 없습니다. 기존의 공개 유형에서 액세스 권한을 제공해야 합니다.

: 시스템 프로세스(AOSP 또는 비 AOSP)를 변경하면 새로운 비 AOSP 공급업체 구성요소와 상호작용하는 방식이 변경되어야 합니다.

시스템 이미지의 정책은 특정 공급업체 맞춤설정에 관해 모르는 상태에서 작성되어야 합니다. 따라서 AOSP의 특정 인터페이스 관련 정책은 system/sepolicy/public의 속성을 통해 노출되므로 공급업체 정책은 이러한 속성을 사용하는 향후 시스템 정책을 선택할 수 있습니다. 하지만 system/sepolicy/public의 속성 확장 프로그램이 지원되지 않으므로 시스템 구성요소가 새로운 공급업체 구성요소와 어떻게 상호작용하는지, 그리고 AOSP system/sepolicy/public에 이미 존재하는 속성에 의해 처리되지 않는 구성요소는 무엇인지 결정하는 모든 정책이 device/manufacturer/device-name/sepolicy에 있어야 합니다. 즉, 시스템 유형은 프레임워크 전용 OTA의 일부로 공급업체 유형에 부여된 액세스 권한을 변경할 수 없습니다.