Processo de Inicialização do Init no Android: Análise do Código Fonte

main.cpp: Entrada do Processo Init

int principal(int argc, char** argv) {
#if __has_feature(address_sanitizer)
    __asan_set_callback_relatorio(AsanCallbackRelatorio);
#endif
    definir_prioridade(PRIO_PROCESS, 0, -20);
    
    if (!strcmp(basename(argv[0]), "ueventd")) {
        return ueventd_principal(argc, argv);
    }

    if (argc > 1) {
        const char* parametro = argv[1];
        if (!strcmp(parametro, "subcontexto")) {
            return SubcontextoPrincipal(argc, argv);
        }
        if (!strcmp(parametro, "config_selinux")) {
            return ConfigurarSelinux(argv);
        }
        if (!strcmp(parametro, "segunda_etapa")) {
            return SegundaEtapaPrincipal(argc, argv);
        }
    }
    return PrimeiraEtapaPrincipal(argc, argv);
}

O ponto de entrada principal analisa argumentos para determinar a fase de inicialização:

  1. Sem argumentos: Executa PrimeiraEtapaPrincipal()
  2. config_selinux: Chama ConfigurarSelinux()
  3. segunda_etapa: Executa SegundaEtapaPrincipal()
  4. Casos especiais (ueventd/subcontxeto) não abordados

first_stage_init.cpp: Primeira Fase

int PrimeiraEtapaPrincipal(int argc, char** argv) {
    std::vector<std::pair<std::string, int>> erros;
    tempo_inicio = boot_clock::now();
    
    // Configuração básica do sistema
    umask(0);
    clearenv();
    setenv("PATH", _PATH_PADRAO, 1);
    
    // Montagem de sistemas de arquivos essenciais
    montar("tmpfs", "/dev", "tmpfs", MS_NOSUID, "modo=0755");
    montar("proc", "/proc", "proc", 0, "hidepid=2");
    montar("sysfs", "/sys", "sysfs", 0, NULL);
    
    // Criação de dispositivos críticos
    criar_dispositivo("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
    criar_dispositivo("/dev/random", S_IFCHR | 0666, makedev(1, 8));
    
    // Preparação para segunda etapa
    montar("tmpfs", kRecursosSegundaEtapa, "tmpfs", MS_NOEXEC, "modo=0755");
    
    // Carregamento de módulos do kernel
    if (!CarregarModulosKernel()) {
        LOG(ERRO) << "Falha ao carregar módulos";
    }
    
    // Transição para configuração SELinux
    const char* argumentos[] = {"/sistema/bin/init", "config_selinux", nullptr};
    execv(argumentos[0], const_cast<char**>(argumentos));
    return 1;
}

Principais operações:

  1. Montagem de sistemas de arquivos temporários (/dev, /proc, /sys)
  2. Criação de dispositivos essenciais (/dev/kmsg, /dev/random)
  3. Configuração de permissões e ambiente básico
  4. Carregamento de módulos do kernel
  5. Preparação para transição de fase

selinux.cpp: Configuração do SELinux

int ConfigurarSelinux(char** argv) {
    IniciarRegistroKernel();
    std::string politica;
    
    // Carregar política de segurança
    LerPolitica(&politica);
    auto auxiliar = SnapuserdSelinuxHelper::CriarSeNecessario();
    
    if (auxiliar) {
        auxiliar->IniciarTransicao();
    }
    
    CarregarPoliticaSelinux(politica);
    
    if (auxiliar) {
        auxiliar->FinalizarTransicao();
    }
    
    // Aplicar contextos SELinux
    selinux_android_restorecon("/dev/selinux/", SELINUX_ANDROID_RESTORECON_RECURSE);
    SelinuxAtivarCumprimento();
    
    // Transição para segunda etapa
    const char* argumentos[] = {"/sistema/bin/init", "segunda_etapa", nullptr};
    execv(argumentos[0], const_cast<char**>(argumentos));
    return 1;
}

Fluxo principal:

  1. Carregamento da política de segurança
  2. Coordenação com snapuserd para partições dinâmicas
  3. Aplicação de contextos SELinux
  4. Ativação do modo de cumprimento

second_stage_main: Segunda Fase

int SegundaEtapaPrincipal(int argc, char** argv) {
    IniciarRegistroKernel();
    LOG(INFO) << "Segunda etapa iniciada";
    
    // Inicialização de subsistemas
    InicializarPropriedades();
    MontarSistemasArquivosExtras();
    
    // Configuração SELinux final
    InicializarRotulosSelinux();
    RestaurarContextoSelinux();
    
    // Configuração de eventos
    Epoll epoll;
    epoll.AdicionarCallback(ReapProcessos);
    InstalarManipuladorSinais(&epoll);
    
    // Serviços essenciais
    IniciarServicoPropriedades();
    ManipuladorMontagem manipulador(&epoll);
    
    // Carregamento de scripts de inicialização
    Analisador analisador = CriarAnalisador();
    analisador.AnalisarConfig("/sistema/etc/init/hw/init.rc");
    analisador.AnalisarConfig("/vendor/etc/init");
    
    // Loop principal de eventos
    while (true) {
        auto tempo_acao = CalcularProximaAcao();
        auto resultado = epoll.Esperar(tempo_acao);
        ManipularMensagensControle();
    }
    return 0;
}

Componentes críticos:

  1. Inicialização do sistema de propriedades
  2. Carregamento de scripts init.rc
  3. Configuração do epoll para gerenciamento de eventos
  4. Loop principal para processamento de ações
  5. Inicialização de serviços essenciais

Inicialização do Zygote

O script init.rc dispara o início do Zygote:

start zygote

O comando start é processado pelo gerenciador de ações, executando o binário definido para o serviço zygote.

Tags: Android-Init SELinux AOSP Boot-Process linux-kernel

Publicado em 7-8 19:33