SELinux 구현

SELinux는 기본 규칙 거부로 설정됩니다. 즉, 커널에 후크가 있는 모든 액세스가 정책에 의해 명시적으로 허용되어야 합니다. 이는 정책 파일이 규칙, 유형, 클래스, 권한 등과 관련된 방대한 정보로 구성되어 있음을 의미합니다. SELinux의 전체적인 고려사항은 이 문서의 범위에 포함되지 않습니다. 하지만 새로운 Android 기기를 불러올 때는 정책 규칙 작성 방법을 이해하는 것이 중요합니다. 이미 SELinux에 관한 많은 정보가 제공되고 있습니다. 제안된 리소스에 관한 자세한 정보는 지원 문서를 참조하세요.

키 파일

SELinux를 사용 설정하려면 최신 Android 커널을 통합한 후 system/sepolicy 디렉터리에 있는 파일을 통합합니다. 컴파일된 파일은 SELinux 커널 보안 정책을 구성하고 업스트림 Android 운영체제를 포함합니다.

일반적으로 system/sepolicy 파일은 직접 수정하면 안 됩니다. 대신 /device/manufacturer/device-name/sepolicy 디렉터리에 고유한 기기별 정책 파일을 추가하거나 수정해야 합니다. Android 8.0 이상 버전에서 기기별 정책 파일을 변경할 경우 vendor 디렉터리에 있는 정책에만 영향을 미쳐야 합니다. Android 8.0 이상에서 공개 sepolicy를 구분하는 법에 관한 자세한 내용은 Android 8.0 이상에서 SEPolicy 맞춤설정을 참조하세요. Android 버전에 관계없이 파일을 계속 수정할 수 있습니다.

정책 파일

*.te로 끝나는 파일은 도메인과 라벨을 정의하는 SELinux 정책 소스 파일입니다. 새 정책 파일을 /device/manufacturer/device-name/sepolicy에 만들어야 할 수도 있지만 가능한 경우 기존 파일을 업데이트해야 합니다.

컨텍스트 파일

컨텍스트 파일에는 객체의 라벨을 지정할 수 있습니다.

  • file_contexts는 파일에 라벨을 할당할 뿐만 아니라 다양한 사용자 공간 구성요소에서 사용됩니다. 새 정책을 만들 때 이 파일을 만들거나 업데이트하여 새 라벨을 파일에 할당하세요. 새 file_contexts를 적용하려면 파일 시스템 이미지를 다시 빌드하거나 파일의 restorecon을 실행하여 라벨을 다시 지정하세요. 업그레이드 시 file_contexts 변경사항은 업그레이드의 일부로서 시스템 및 사용자 데이터 파티션에 자동으로 적용됩니다. 또한 파티션이 읽기-쓰기로 마운트된 후 restorecon_recursive 호출을 init.board.rc 파일에 추가하면 다른 파티션으로 업그레이드 시 변경사항이 자동으로 적용됩니다.
  • genfs_contextsproc 또는 vfat 등 확장된 속성을 지원하지 않는 파일 시스템에 라벨을 할당합니다. 이 구성은 커널 정책의 일부로 로드되지만 파일 시스템을 재부팅 또는 마운트 해제 후 다시 마운트해야 변경사항이 완전히 적용되는 코어 내 inode에는 변경사항이 적용되지 않을 수 있습니다. context=mount 옵션을 사용하여 특정 라벨을 vfat와 같은 특정 마운트에 할당할 수도 있습니다.
  • property_contexts는 Android 시스템 속성에 라벨을 할당하여 속성을 설정할 수 있는 프로세스를 제어합니다. 시작 시 init 프로세스에서 이 구성을 읽습니다.
  • service_contexts는 Android 바인더 서비스에 라벨을 지정하여 서비스의 바인더 참조를 추가(등록) 및 검색(조회)할 수 있는 프로세스를 제어합니다. 시작 시 servicemanager 프로세스에서 이 구성을 읽습니다.
  • seapp_contexts는 앱 프로세스 및 /data/data 디렉터리에 라벨을 할당합니다. 각 앱 실행 시 zygote 프로세스에서, 시작 시 installd에서 이 구성을 읽습니다.
  • mac_permissions.xml은 서명 및 패키지 이름(선택사항)을 기준으로 앱에 seinfo 태그를 할당합니다. seinfo 태그를 seapp_contexts 파일의 키로 사용하면 seinfo 태그가 포함된 모든 앱에 특정 라벨을 할당할 수 있습니다. 시작 시 system_server에서 이 구성을 읽습니다.

BoardConfig.mk makefile

정책 및 컨텍스트 파일을 수정하거나 추가한 후 sepolicy 하위 디렉터리 및 각각의 새 정책 파일을 참조할 수 있도록 /device/manufacturer/device-name/BoardConfig.mk makefile을 업데이트하세요. BOARD_SEPOLICY 변수에 관한 자세한 내용은 system/sepolicy/README 파일을 참조하세요.

    BOARD_SEPOLICY_DIRS += \
            <root>/device/manufacturer/device-name/sepolicy

    BOARD_SEPOLICY_UNION += \
            genfs_contexts \
            file_contexts \
            sepolicy.te
    

다시 빌드한 후 SELinux에서 기기를 사용 설정할 수 있습니다. 이제 맞춤설정에서 설명한 대로 SELinux 정책을 맞춤설정하여 Android 운영체제에 추가한 사항을 수용하거나 유효성 검사에서 다룬 내용대로 기존 설정을 확인할 수 있습니다.

새 정책 파일과 BoardConfig.mk 업데이트가 있을 경우 새 정책 설정이 최종 커널 정책 파일에 자동으로 빌드됩니다. sepolicy를 기기에 빌드하는 방법에 관한 자세한 내용은 sepolicy 빌드를 참조하세요.

구현

SELinux를 시작하려면 다음 단계를 따르세요.

  1. 다음과 같이 커널에서 SELinux를 사용 설정합니다. CONFIG_SECURITY_SELINUX=y
  2. 다음과 같이 kernel_cmdline 매개변수를 변경합니다.
        BOARD_KERNEL_CMDLINE := androidboot.selinux=permissive
    기기의 초기 정책 개발에만 적용됩니다. 초기 부트스트랩 정책을 설정한 후에는 이 매개변수를 삭제하여 기기에서 CTS가 시행할 수 있도록 하세요. 그렇게 하지 않으면 CTS가 실패합니다.
  3. 시스템을 허용 모드로 부팅하고, 부팅 시 거부되는 사항을 확인합니다.
    Ubuntu 14.04 이상:
        adb shell su -c dmesg | grep denied | audit2allow -p out/target/product/BOARD/root/sepolicy
        
    Ubuntu 12.04:
        adb pull /sys/fs/selinux/policy
        adb logcat -b all | audit2allow -p policy
        
  4. init: Warning! Service name needs a SELinux domain defined; please fix!와 유사한 경고를 출력하는지 평가합니다. 안내와 도구에 관한 유효성 검사를 참조하세요.
  5. 라벨을 지정해야 하는 기기 및 기타 새 파일을 확인합니다.
  6. 객체의 기존 라벨 또는 새 라벨을 사용합니다. *_contexts 파일을 참조하여 이전에 라벨을 지정한 방식을 확인하고 라벨의 의미에 관한 지식을 사용하여 새 라벨을 할당합니다. 정책에 맞는 기존 라벨을 사용하는 것이 이상적이지만 새 라벨과 이 라벨에 액세스하기 위한 규칙이 필요한 경우도 있습니다. 적절한 컨텍스트 파일에 라벨을 추가합니다.
  7. 자체 보안 도메인이 있어야 하는 도메인/프로세스를 확인합니다. 각각 완전히 새로운 정책을 작성해야 할 수도 있습니다. 예를 들면 init에서 생성된 모든 서비스에는 자체 정책이 있어야 합니다. 다음 명령어를 사용하면 실행 중인 서비스를 표시할 수 있습니다. 하지만 모든 서비스에서 이 작업을 수행해야 합니다.
        adb shell su -c ps -Z | grep init
        
        adb shell su -c dmesg | grep 'avc: '
        
  8. init.device.rc를 검토하여 도메인 유형이 없는 도메인을 확인합니다. 개발 프로세스 초기에 도메인을 제공하면 init에 규칙을 추가하거나 init 액세스를 고유한 정책에 있는 액세스와 혼동하는 것을 피할 수 있습니다.
  9. BOARD_CONFIG.mk를 설정하면 BOARD_SEPOLICY_* 변수를 사용할 수 있습니다. 설정에 관한 자세한 내용은 system/sepolicy에 있는README를 참조하세요.
  10. init.device.rc 및 fstab.device 파일을 검사하여 mount가 라벨이 지정된 파일 시스템에 제대로 사용되고 있는지 또는 context= mount 옵션이 지정되었는지 확인합니다.
  11. 거부 사항을 각각 확인하고 이를 제대로 처리할 수 있도록 SELinux 정책을 만듭니다. 맞춤설정의 예를 참조하세요.

먼저 AOSP의 정책으로 시작한 다음 이 정책을 기반으로 빌드하여 맞춤설정해야 합니다. 정책 전략과 각 단계에 관한 자세한 내용은 SELinux 정책 작성을 참조하세요.

사용 사례

다음은 자체 소프트웨어 및 관련 SELinux 정책을 만들 때 고려해야 할 특정 악용 사례입니다.

심볼릭 링크 - 심볼릭 링크는 파일로 표시되기 때문에 대개 파일로 읽혀 악용될 수 있습니다. 예를 들어 init와 같이 일부 권한 있는 구성요소의 경우 특정 파일의 권한을 변경하여 그 파일을 과도하게 공개할 수도 있습니다.

그런 다음 공격자는 그 파일을 자신이 제어하는 코드와 연결된 심볼릭 링크로 바꿔 임의의 파일을 덮어쓸 수 있습니다. 하지만 애플리케이션이 심볼릭 링크를 순회하지 않는다는 것을 알고 있을 경우 SELinux에서 이를 금지할 수 있습니다.

시스템 파일 - 시스템 서버에서만 수정해야 하는 시스템 파일의 클래스를 고려합니다. 아직 netd, initvold가 루트로 실행되고 있기 때문에 시스템 파일에 액세스할 수 있습니다. 따라서 netd가 손상되면 파일뿐 아니라 잠재적으로 시스템 서버 자체도 손상될 수 있습니다.

SELinux를 사용하면 이러한 파일을 시스템 서버 데이터 파일로 식별할 수 있습니다. 따라서 이러한 파일에 대한 읽기/쓰기 액세스 권한이 있는 유일한 도메인은 시스템 서버입니다. netd가 손상된 경우에도 루트로 실행되지만 도메인을 시스템 서버 도메인으로 전환하여 시스템 파일에 액세스할 수 없습니다.

앱 데이터 - 다른 예로는 루트로 실행되어야 하지만 앱 데이터에 액세스하면 안 되는 함수 클래스가 있습니다. 애플리케이션 데이터와 관련이 없는 특정 도메인에서 인터넷에 액세스하는 것을 금지하는 등 다양한 어설션을 만들 수 있어 매우 유용합니다.

setattr - chmodchown과 같은 명령어의 경우 관련 도메인에서 setattr을 실행할 수 있는 파일 집합을 식별할 수 있습니다. 루트로도 그 이외의 모든 항목에 관한 변경을 금지할 수 있습니다. 그렇기 때문에 애플리케이션에서는 shell_data_files 또는 system_data_files가 아닌 app_data_files 라벨이 지정된 항목에 대해 chmodchown이 실행될 수도 있습니다.