공급업체 초기화

init 프로세스의 권한은 제한이 거의 없을 뿐만 아니라 시스템 및 공급업체 파티션의 입력 스크립트를 모두 사용하여 부팅 프로세스 중 시스템을 초기화합니다. 이 액세스로 인해 Treble 시스템/공급업체 분할에 큰 허점이 생깁니다. 공급업체 스크립트가 안정적인 시스템-공급업체 ABI(Application Binary Interface)의 일부가 아닌 파일, 속성 등에 액세스하도록 init에 지시할 수 있기 때문입니다.

공급업체 초기화는 별도의 SELinux(보안이 강화된 Linux) 도메인 vendor_init를 사용하여 공급업체별 권한으로 /vendor 명령어를 실행함으로써 이러한 허점을 채울 수 있도록 설계되었습니다.

메커니즘

공급업체 초기화에서는 SELinux 컨텍스트 u:r:vendor_init:s0을 사용하여 부팅 프로세스 초기에 init의 하위 프로세스를 포크합니다. 이 SELinux 컨텍스트는 기본 init 컨텍스트보다 권한이 훨씬 적으며 공급업체별 또는 안정적 시스템-공급업체 ABI의 일부인 파일, 속성 등에만 액세스할 수 있습니다.

Init는 로드되는 각 스크립트를 검사하여 경로가 /vendor로 시작하는지 확인하고 그럴 경우 명령어를 공급업체 초기화 컨텍스트에서 실행해야 한다는 표시로 태그를 지정합니다. 각 init 빌트인은 공급업체 초기화 하위 프로세스에서 명령어를 실행해야 하는지 여부를 지정하는 부울로 주석 처리됩니다.

  • 파일 시스템에 액세스하는 대부분의 명령어는 공급업체 초기화 하위 프로세스에서 실행되도록 주석 처리되며 공급업체 초기화 SEPolicy가 적용됩니다.
  • 내부 init 상태에 영향을 주는 대부분의 명령어(예: 서비스 시작 및 중지)는 일반 init 프로세스 내에서 실행됩니다. 이러한 명령어는 공급업체 스크립트가 SELinux가 아닌 자체 권한 처리를 위해 호출하고 있음을 알립니다.

init의 기본 처리 루프에서는 명령어가 공급업체 하위 프로세스에서 실행되도록 주석 처리되고 공급업체 스크립트에서 생성된 경우 명령어가 프로세스 간 통신(IPC)을 통해 공급업체 초기화 하위 프로세스로 전송되어 실행되는지 확인하며 결과는 다시 init로 보냅니다.

공급업체 초기화 사용

공급 업체 초기화는 기본적으로 사용 설정되며 제한사항은 /vendor 파티션에 있는 모든 init 스크립트에 적용됩니다. 공급업체 초기화는 스크립트가 이미 시스템 전용 파일, 속성 등에 액세스하지 않는 공급업체에 투명해야 합니다.

하지만 지정된 공급업체의 스크립트에 있는 명령어가 공급업체 초기화 제한사항을 위반하면 그 명령어는 실패하게 됩니다. 실패한 명령어에는 init의 커널 로그(dmesg로 표시)에 실패를 나타내는 줄이 있습니다. SELinux 감사에는 SELinux 정책으로 인해 실패한 명령어가 함께 표시됩니다. SELinux 감사가 포함된 실패 사례는 다음과 같습니다.

type=1400 audit(1511821362.996:9): avc: denied { search } for pid=540 comm="init" name="nfc" dev="sda45" ino=1310721 scontext=u:r:vendor_init:s0 tcontext=u:object_r:nfc_data_file:s0 tclass=dir permissive=0
init: Command 'write /data/nfc/bad_file_access 1234' action=boot (/vendor/etc/init/hw/init.walleye.rc:422) took 2ms and failed: Unable to write to file '/data/nfc/bad_file_access': open() failed: Permission denied

명령어가 실패할 경우 선택할 수 있는 옵션에는 두 가지가 있습니다.

  • 명령어가 의도된 제한(예: 명령어가 시스템 파일 또는 속성에 액세스할 경우)으로 인해 실패할 경우 안적정인 인터페이스로만 진행하여 Treble에 적합한 방식으로 명령어를 다시 구현해야 합니다. Neverallow 규칙은 안정적인 시스템-공급업체 ABI의 일부가 아닌 시스템 파일에 액세스하기 위해 권한을 추가하는 것을 방지합니다.
  • SELinux 라벨이 새로 지정되어 아직 시스템 vendor_init.te의 권한이 부여되지 않았거나 neverallow 규칙을 통해 권한이 제외된 경우 기기별 vendor_init.te의 권한이 새 라벨에 부여될 수 있습니다.

Android 9 이전에 출시되는 기기의 경우 data_between_core_and_vendor_violators 유형 속성을 기기별 vendor_init.te 파일에 추가하면 neverallow 규칙을 우회할 수 있습니다.

코드 위치

공급업체 초기화 IPC 로직의 대부분은 system/core/init/subcontext.cpp에 있습니다.

명령어 표는 system/core/init/builtins.cppBuiltinFunctionMap 클래스에 있으며 명령어가 공급업체 초기화 하위 프로세스에서 실행되어야 하는지 여부를 나타내는 주석을 포함합니다.

공급업체 초기화용 SEPolicy는 system/sepolicy의 비공개(system/sepolicy/private/vendor_init.te) 디렉터리와 공개(system/sepolicy/public/vendor_init.te) 디렉터리로 분할됩니다.