SELinux 정책 빌드하기

이 문서에서는 SELinux 정책 빌드 방법을 설명합니다. SELinux 정책은 핵심 AOSP 정책(플랫폼)과 기기별 정책(공급업체)의 조합으로 빌드됩니다. Android 4.4에서 Android 7.0까지의 SELinux 정책 빌드 흐름은 모든 sepolicy 프래그먼트 병합 이후 루트 디렉터리에 모놀리식 파일을 생성했습니다. 즉, SoC 공급업체 및 ODM 제조업체는 정책이 수정될 때마다 boot.img(비 A/B 기기) 또는 system.img(A/B 기기)를 수정했습니다.

Android 8.0 이상에서는 플랫폼 및 공급업체 정책이 별도로 빌드됩니다. SOC 및 OEM은 정책의 일부를 업데이트하고 이미지(예: vendor.imgvendor.img 및 boot.img)를 빌드한 후 플랫폼 업데이트와 관계없이 이 이미지를 업데이트할 수 있습니다.

그러나 모듈화된 SELinux 정책 파일은 /vendor 파티션에 저장되므로 init 프로세스는 시스템 및 공급업체 파티션을 더 일찍 마운트해야 합니다. 그래야 이러한 파티션에서 SELinux 파일을 읽어 시스템 디렉터리의 핵심 SELinux 파일과 병합할 수 있습니다(커널에 로드하기 전에).

소스 파일

SELinux를 빌드하기 위한 로직은 다음 파일에 있습니다.

  • external/selinux: SELinux 정책 및 라벨을 컴파일하는 HOST 명령줄 유틸리티를 빌드하는 데 사용되는 외부 SELinux 프로젝트입니다.
    • external/selinux/libselinux: Android는 일부 Android 관련 맞춤설정과 함께 외부 libselinux 프로젝트의 하위 집합만 사용합니다. 자세한 내용은 external/selinux/README.android를 참조하세요.
    • external/selinux/libsepol:
      • chkcon: 지정된 바이너리 정책(호스트 실행 파일)에 보안 컨텍스트가 유효한지 확인합니다.
      • libsepol: 바이너리 보안 정책을 처리하기 위한 SELinux 라이브러리(호스트 정적/공유 라이브러리, 타겟 정적 라이브러리)입니다.
    • external/selinux/checkpolicy: SELinux 정책 컴파일러(호스트 실행 파일: checkpolicy, checkmoduledispol)입니다. libsepol에 종속됩니다.
  • system/sepolicy: 컨텍스트 및 정책 파일을 포함한 핵심 Android SELinux 정책 구성입니다. 주요 sepolicy 빌드 로직도 여기(system/sepolicy/Android.mk)에 있습니다.

system/sepolicy의 파일에 관한 자세한 내용은 SELinux 구현을 참조하세요.

Android 7.0 이하

이 섹션에서는 SELinux 정책이 Android 7.x 이하에서 빌드되는 방식에 관해 다룹니다.

SELinux 정책 빌드하기

SELinux 정책은 핵심 AOSP 정책을 기기별 맞춤설정과 결합하여 생성됩니다. 그런 다음, 결합된 정책은 정책 컴파일러 및 다양한 검사기로 전달됩니다. 기기별 맞춤설정은 기기별 Boardconfig.mk 파일에 정의된 BOARD_SEPOLICY_DIRS 변수를 통해 실행됩니다. 이 전역 빌드 변수에는 추가 정책 파일을 검색하는 순서를 지정하는 디렉터리 목록이 포함됩니다.

예를 들어 SoC 공급업체 및 ODM은 다음과 같이 SoC 관련 설정용 디렉터리 및 기기 관련 설정용 디렉터리를 각각 추가하여 지정된 기기의 최종 SELinux 구성을 생성할 수 있습니다.

  • BOARD_SEPOLICY_DIRS += device/SOC/common/sepolicy
  • BOARD_SEPOLICY_DIRS += device/SoC/DEVICE/sepolicy

다음과 같이 system/sepolicyBOARD_SEPOLICY_DIRS에 있는 file_contexts 파일의 콘텐츠를 연결하여 기기에 file_contexts.bin을 생성합니다.

이 이미지는 Android 7.x의 SELinux 빌드 로직을 보여줍니다.
그림 1. SELinux 빌드 로직

sepolicy 파일은 다음과 같이 여러 소스 파일로 구성됩니다.

  • 일반 텍스트 policy.confsecurity_classes, initial_sids, *.te 파일, genfs_contextsport_contexts를 순서대로 연결함으로써 생성됩니다.
  • 각 파일(예: security_classes)의 콘텐츠는 system/sepolicy/BOARDS_SEPOLICY_DIRS의 동일한 이름을 가진 파일을 연결한 것입니다.
  • policy.conf는 구문 검사를 위해 SELinux 컴파일러로 전송되고 기기에서 sepolicy로서 바이너리 형식으로 컴파일됩니다.
    이 이미지는 Android 7.x의 SELinux 정책 파일을 생성하는 파일을 보여줍니다.
    그림 2. SELinux 정책 파일

SELinux 파일

컴파일 이후 7.x 이하를 실행하는 Android 기기에는 일반적으로 다음과 같은 SELinux 관련 파일이 포함됩니다.

  • selinux_version
  • sepolicy: 정책 파일을 결합한 이후 바이너리 출력(예: security_classes, initial_sids*.te)
  • file_contexts
  • property_contexts
  • seapp_contexts
  • service_contexts
  • system/etc/mac_permissions.xml

자세한 내용은 SELinux 구현을 참조하세요.

SELinux 초기화

시스템이 부팅될 때 SELinux는 허용 모드에 있으며 강제 적용 모드에 있지 않습니다. init 프로세스는 다음 작업을 실행합니다.

  • /sys/fs/selinux/load를 통해 램디스크에서 커널로 sepolicy 파일을 로드합니다.
  • SELinux를 강제 적용 모드로 전환합니다.
  • re-exec()를 실행하여 SELinux 도메인 규칙을 자체에 적용합니다.

부팅 시간을 줄이려면 가능한 한 빨리 init 프로세스에서 re-exec()를 실행합니다.

Android 8.0 이상

Android 8.0에서 SELinux 정책은 플랫폼 및 공급업체 구성요소로 분할되어 독립적인 플랫폼/공급업체 정책 업데이트를 허용하는 동시에 호환성을 유지합니다.

플랫폼 sepolicy는 특정 유형 및 속성을 공급업체 정책 작성자에게 내보내기 위해 플랫폼 비공개 및 공개 부분으로 추가 분할됩니다. 플랫폼 공개 유형/속성은 지정된 플랫폼 버전의 안정적인 API로 유지됩니다. 이전 플랫폼 공개 유형/속성과의 호환성은 플랫폼 매핑 파일을 사용하는 여러 버전에서 보장될 수 있습니다.

플랫폼 공개 sepolicy

플랫폼 공개 sepolicy에는 system/sepolicy/public에 정의된 모든 항목이 포함됩니다. 플랫폼은 공개 정책에 정의된 유형 및 속성이 지정된 플랫폼 버전의 안정적인 API라고 가정할 수 있습니다. 이는 공급업체(예: 기기) 정책 개발자가 추가 기기별 정책을 작성할 수 있는 플랫폼에서 내보내는 sepolicy의 일부를 형성합니다.

유형은 공급업체 파일이 작성되는 정책의 버전(PLATFORM_SEPOLICY_VERSION 빌드 변수에 의해 정의됨)에 따라 버전이 지정됩니다. 그러면 버전이 지정된 공개 정책은 공급업체 정책과 함께 플랫폼 정책에 원래 형식으로 포함됩니다. 따라서 최종 정책에는 비공개 플랫폼 정책, 현재 플랫폼의 공개 sepolicy, 기기별 정책 및 기기 정책이 작성된 플랫폼 버전에 상응하는 버전 지정된 공개 정책이 포함됩니다.

플랫폼 비공개 sepolicy

플랫폼 비공개 sepolicy에는 /system/sepolicy/private에 정의된 모든 항목이 포함됩니다. 이 정책 부분은 플랫폼 기능에 필요한 플랫폼 전용 유형, 권한 및 속성을 형성합니다. 이러한 항목은 vendor/device 정책 작성자에게 내보내지지 않습니다. 비 플랫폼 정책 작성자는 플랫폼 비공개 sepolicy에 정의된 유형/속성/규칙을 기반으로 정책 확장을 작성해서는 안 됩니다. 또한 이러한 규칙은 프레임워크 전용 업데이트의 일부로 수정되거나 정리될 수 있습니다.

플랫폼 비공개 매핑

플랫폼 비공개 매핑에는 정책 구문이 포함되며 이 정책 구문은 이전 플랫폼 버전의 플랫폼 공개 정책에 노출된 속성을 현재 플랫폼 공개 sepolicy에 사용되는 구체적인 유형에 매핑합니다. 이렇게 하면 이전 플랫폼 공개 sepolicy 버전의 플랫폼 공개 속성을 기반으로 작성된 공급업체 정책이 계속 작동합니다. 버전 관리는 지정된 플랫폼 버전의 AOSP에 설정된 PLATFORM_SEPOLICY_VERSION 빌드 변수를 기반으로 합니다. 이 플랫폼이 공급업체 정책을 수락할 것으로 예상되는 각 이전 플랫폼 버전과 관련하여 별도의 매핑 파일이 있습니다. 자세한 내용은 호환성을 참조하세요.

SELinux 정책 빌드하기

Android 8.0의 SELinux 정책은 /system/vendor의 요소를 결합하여 만들 수 있습니다. 이 정책을 적절하게 설정하기 위한 로직은 /platform/system/sepolicy/Android.mk에 있습니다.

정책은 다음 위치에 있습니다.

위치 포함
system/sepolicy/public 플랫폼의 sepolicy API
system/sepolicy/private 플랫폼 구현 세부정보(공급업체는 무시할 수 있음)
system/sepolicy/vendor 공급업체가 사용할 수 있는 정책 및 컨텍스트 파일(원한다면 공급업체는 무시할 수 있음)
BOARD_SEPOLICY_DIRS 공급업체 sepolicy

빌드 시스템은 이 정책을 사용하여 시스템 파티션 및 공급업체 파티션에 각각 플랫폼 및 공급업체 정책 구성요소를 생성합니다. 다음 단계가 포함됩니다.

  1. 정책, 특히 다음과 같은 정책을 SELinux CIL(Common Intermediate Language) 형식으로 변환합니다.
    1. 공개 플랫폼 정책
    2. 비공개 정책 + 공개 정책의 조합
    3. 공개 + 공급업체 및 BOARD_SEPOLICY_DIRS 정책
  2. 공급업체 정책의 일부로 공개적으로 제공되는 정책을 버전 관리합니다. 생성된 공개 CIL 정책을 사용하여 플랫폼 정책에 연결될 속성으로 변환되어야 하는 부분에 관해 공개 + 공급업체 + BOARD_SEPOLICY_DIRS 정책 조합에 알리는 방식을 사용합니다.
  3. 플랫폼 부분과 공급업체 부분을 연결하는 매핑 파일을 생성합니다. 처음에는 공개 정책의 유형을 공급업체 정책의 상응하는 속성과 연결합니다. 또한 이후에는 향후 플랫폼 버전에서 유지 관리되는 파일의 기초를 제공하여 이 플랫폼 버전을 타겟팅하는 공급업체 정책과의 호환성을 구현합니다.
  4. 정책 파일을 결합합니다(온디바이스 솔루션과 사전 컴파일된 솔루션을 모두 설명).
    1. 매핑, 플랫폼 및 공급업체 정책 정책을 결합합니다.
    2. 출력 바이너리 정책 파일을 컴파일합니다.