O Dopamina A ferramenta de jailbreak para dispositivos A12-A15 executando iOS e iPadOS 15.0-15.4.1 é o único jailbreak mais recente disponível para qualquer dispositivo mais recente que o iPhone X neste momento. Dito isto, não é surpresa que seja uma escolha popular para jailbreakers hoje.
Mas se você usa Dopamina ou acompanha o projeto desde o seu início, provavelmente já ouviu uma certa palavra usada algumas vezes pelo desenvolvedor líder do projeto, Lars Fröder ( @opa334dev ) e usuários: Spinlock.
Na verdade, há um problema conhecido que afeta o jailbreak da Dopamine, chamado Spinlock Timeout Panic, e, em última análise, faz com que o dispositivo do usuário mostre uma tela rosa e, em seguida, reinicie de uma forma aparentemente não provocada. O problema foi descrito em termos técnicos da seguinte forma:
O mapeamento na parte superior das páginas executáveis dyld_shared_cache parece desencadear um comportamento extremo no PPL que às vezes causa um tempo limite no spinlock de uma página de memória, resultando em um kernel panic.
Quanto mais ajustes as funções do gancho C são instaladas e quanto mais processos elas injetam, mais frequentemente esse comportamento parece ser acionado.
Parece que esse problema pode ser corrigido conectando todas as páginas que foram conectadas, mas o espaço do usuário não pode aceitar esse bloqueio e encontrar o objeto vm_page na memória do kernel para inverter o bit conectado diretamente está se mostrando difícil.
Como nunca experimentei pessoalmente um desses problemas no meu dispositivo de dopamina, tem sido difícil explicar como isso se parece ou quando acontece, mas conversei com Fröder para perguntar o que eles acham que poderia estar causando isso para saber mais sobre como eles estão tentando resolver isso.
A resposta de Fröder foi esclarecedora para pessoas não técnicas como eu e provavelmente para muitos outros na comunidade do jailbreak e desde então tem sido publicado em uma página de problemas do GitHub para o público ver. A resposta completa, citada abaixo, revela a compreensão de Fröder sobre o problema do Spinlock Timeout Panic:
Aqui está uma tentativa de uma explicação mais aprofundada do problema, de acordo com minha melhor compreensão atual. Tenha em mente que se baseia em suposições que são basicamente impossíveis de verificar.
Portanto, em um sistema multithread, “bloqueios” são usados para evitar que dois threads interfiram um no outro. Através desse thread pode adquirir um bloqueio, fazer a modificação e desbloqueá-lo. Enquanto estiver bloqueado, outro thread que tentar adquirir o bloqueio aguardará até que o objeto seja desbloqueado novamente.
Um spinlock é essencialmente a mesma coisa, usado apenas para coisas relevantes ao desempenho e a principal diferença é que um spinlock pode expirar se algo demorar muito no bloqueio enquanto outro thread está tentando adquiri-lo. Portanto, ao adquirir um bloqueio e o objeto já estiver bloqueado, ele esperaria alguns tiques e se o objeto não fosse desbloqueado nesse período, o tempo expiraria.
Este mecanismo por si só não é a questão, a questão tem a ver com memória Páginas. Cada página de memória (que descreve uma área de 16kB de RAM) possui um spinlock para que não haja problemas quando vários processos tentam adquirir a mesma página ao mesmo tempo.
Páginas específicas podem ser mapeadas em vários processos (por exemplo, se ambos carregarem a mesma biblioteca), elas reutilizarão a mesma página para economizar memória. Os ajustes desejam sobrescrever essa memória por processo, portanto, eles precisam primeiro fazer uma cópia específica do processo do mapeamento existente e mapeá-la sobre ela, para que, por exemplo, uma página pode ser modificada em um processo enquanto permanece em estoque nos outros processos. O problema parece acontecer especificamente ao mapear na parte superior de uma página que reside dentro de dyld_shared_cache.
O problema agora é que a Apple provavelmente nunca testou esse tipo de conexão e, aparentemente, quando você faz isso em muitos processos, pode fazer com que a página original (a do mapeamento compartilhado) seja paginada, porque não está sendo usada ativamente . Paginar uma página essencialmente a remove da RAM e quando ela for acessada novamente, ela será carregada novamente. Num sistema de estoque isso não acontecerá porque nada foi fisgado.
Agora, a causa raiz parece ser algo tentando paginar uma página compartilhada/executável previamente paginada de volta, isso desencadeia um problema de preempção onde um thread pega o spinlock e enquanto tem isso, ele é antecipado para um contexto diferente que também leva o mesmo spinlock (a preempção é essencialmente um mecanismo que permite que um thread seja usado para outra coisa, mesmo que esteja ocupado no momento, o código deve desativá-lo e reativá-lo explicitamente se houver um trecho de código que sempre deve ser executado de uma só vez) . Portanto, parece haver um caminho de código que só é invocado a partir desse comportamento específico em que a Apple não desativa corretamente a preempção, fazendo com que um thread execute o mesmo spinlock duas vezes, o que faz com que o tempo limite seja atingido porque o contexto antigo não está mais sendo executado e não é possível desbloquear o spinlock novamente.
Quanto a mitigar isso, tentei mexer nas variáveis relacionadas ao spinlock para aumentar o limite necessário para o tempo limite, infelizmente a Apple nos ferrou porque tudo relacionado a isso é protegido por KTRR, para o qual não temos um bypass. Eu acho que a solução adequada seria “desconectar” (conectar uma página evita que ela seja paginada) todas as páginas a serem conectadas antes de serem sobrescritas para garantir que a saída da página nunca aconteça e, portanto, o caminho do código envolvido no o problema não é acionado, eu tentei um monte de coisas até agora, mas parece que é impossível adquirir tal fiação do espaço do usuário, então isso tem que ser feito dentro do kernel. Infelizmente, as estruturas envolvidas nesse mapeamento compartilhado específico que causa o problema são muito complicadas e ainda não encontrei uma maneira de obter o objeto de página correto ao qual aplicar a fiação.
O problema do Spinlock Timeout Panic existe desde que a dopamina foi disponibilizada pela primeira vez e continua a persistir até hoje apesar de muitas tentativas para corrigir o problema. Dito isto, abrir o diálogo para que mais pessoas vejam e contribuam é o passo certo em frente, pois torna mais fácil para mais mentes debater a questão e uma possível solução.
Fröder explica sua próxima ideia para tentar frustrar o problema em um comentário de acompanhamento:
Portanto, o próximo passo para tentar consertar seria encontrar a estrutura vm_page de uma página DSC na memória do kernel, até agora todas as minhas tentativas de encontrar tal estrutura falharam.
Embora ainda não tenha me afetado diretamente, será realmente interessante ver se Fröder é capaz de resolver o problema do Spinlock Timeout Panic. Parece ser mais prevalente para usuários que instalam mais ajustes de jailbreak que conectam funções C. Pode ser que meu dispositivo de teste não tenha muitos ajustes instalados para desencadear o problema, mas sei que existem muitos jailbreakers por aí que instalam toneladas de ajustes de jailbreak – mais do que eu jamais faria.
Veja também: Como fazer jailbreak de dispositivos A12-A15 executando iOS e iPadOS 15.0-15.4.1 com Dopamina
Você já foi afetado por um Spinlock Timeout Panic descrito como uma tela rosa antes de uma reinicialização repentina enquanto usava o jailbreak do Dopamine? Deixe-nos saber na seção de comentários abaixo.