Rosetta 2 sui Mac dotati di chip Apple
I Mac dotati di chip Apple sono in grado di eseguire il codice compilato per il set di istruzioni x86_64 utilizzando un meccanismo di traduzione chiamato Rosetta 2. I tipi di traduzione offerti sono due: JIT (Just In Time) e AOT (Ahead OF Time).
Traduzione JIT (Just In Time)
Nel flusso di traduzione JIT, un oggetto Mach x86_64 viene identificato in precedenza nel percorso di esecuzione dell’immagine. Quando tali immagini vengono incontrate, il kernel trasferisce il controllo a una speciale porzione di Rosetta responsabile della traduzione piuttosto che all’editor dei link dinamici dyld(1)
. La porzione responsabile della traduzione traduce le pagine x86_64 durante l’esecuzione dell’immagine. La traduzione avviene interamente all’interno del processo. Il kernel verifica comunque gli hash del codice di ciascuna pagina x86_64 tramite la firma allegata al binario. Nel caso di una mancata corrispondenza tra gli hash, il kernel implementa le politiche di rimedio appropriate per tale processo.
Traduzione AOT (Ahead OF Time)
Nella procedura di traduzione AOT, i binari x86_64 vengono letti dallo spazio di archiviazione in momenti che il sistema ritiene ottimali per la reattività di tale codice. Gli artefatti tradotti vengono scritti sullo spazio di archiviazione come un tipo speciale di file di oggetto Mach. Tale file è simile a un’immagine eseguibile, ma è contrassegnato in modo da indicare che si tratta della traduzione di un’altra immagine.
In questo modello, l’artefatto AOT prende tutte le informazioni della sua identità dall’immagine eseguibile x86_64 originale. Per implementare questo legame, un’entità dello spazio utente privilegiata firma l’artefatto tradotto tramite una chiave specifica per il dispositivo che è gestita da Secure Enclave. Questa chiave viene rilasciata solo all’entità dello spazio utente privilegiata, che è identificata come tale tramite un permesso limitato. La directory di codice creata per l’artefatto tradotto include l’hash della directory di codice dell’immagine eseguibile x86_64 originale. La firma dell’artefatto tradotto stesso è conosciuta come firma supplementare.
Il flusso di traduzione AOT inizia in modo simile a quello JIT, con il kernel che trasferisce il controllo a Rosetta piuttosto che all’editor dei link dinamici dyld(1)
. Ma in questo caso, successivamente Rosetta invia una richiesta di comunicazione tra processi al servizio di sistema di Rosetta, il quale controlla se è disponibile una traduzione AOT per l’attuale immagine eseguibile. Se viene trovata, il servizio di Rosetta fornisce un collegamento a tale traduzione e questa viene mappata nel processo ed eseguita. Durante l’esecuzione, il kernel implementa gli hash della directory di codice dell’artefatto tradotto, che sono autenticati dalla firma che ha la propria radice nella chiave specifica per il dispositivo. Gli hash della directory di codice dell’immagine x86_64 originale non sono coinvolti in questo processo.
Gli artefatti tradotti sono archiviati in un data vault non accessibile in runtime da nessuna entità, tranne che dal servizio di Rosetta. Il servizio di Rosetta gestisce l’accesso alla propria cache distribuendo descrittori di file di sola lettura ad artefatti tradotti individuali; ciò limita l’accesso alla cache degli artefatti AOT. La comunicazione tra processi del servizio e gli elementi dipendenti sono intenzionalmente ristretti per limitare le possibilità di attacco.
Se l’hash della directory di codice dell’immagine x86_64 originale non corrisponde a quello codificato nella firma dell’artefatto tradotto AOT, il risultato viene considerato equivalente a una firma del codice non valida e vengono implementate le misure appropriate.
Se un processo remoto richiede al kernel dei permessi o altre proprietà di identità del codice di un eseguibile tradotto in modalità AOT, vengono restituite le proprietà dell’identità dell’immagine x86_64 originale.
Contenuti della cache di attendibilità statica
macOS 11 o versioni successive viene fornito con binari Mach “multiarchitettura”, che contengono porzioni di codice macchina sia x86_64 che arm64. Sui Mac dotati di chip Apple, l’utente potrebbe scegliere di eseguire il codice x86_64 di un binario di sistema tramite il flusso di Rosetta, ad esempio per caricare un plugin che non ha una variante arm64 nativa. Per supportare questa opzione, la cache di attendibilità statica fornita con macOS, in linea generale, contiene tre hash di directory di codice per file di oggetto Mach.
Un hash della directory di codice della porzione arm64
Un hash della directory di codice della porzione x86_64
Un hash della directory di codice della traduzione AOT della porzione x86_64
La procedura di traduzione di Rosetta è deterministica, nel senso che riproduce un output identico per ciascun input dato, a prescindere dal momento in cui la traduzione è stata effettuata o su quale dispositivo.
Durante il processo di build di macOS, ogni file di oggetto Mach viene tradotto tramite il flusso di Rosetta associato alla versione di macOS in fase di build e l’hash della directory del codice risultante viene registrato nella cache di attendibilità. Per ragioni di efficienza, i prodotti tradotti non vengono forniti con il sistema operativo e vengono realizzati su richiesta dell’utente.
Quando un’immagine x86_64 è in esecuzione su un Mac dotato di chip Apple, se l’hash della directory di tale codice si trova nella cache di attendibilità statica, è previsto che anche l’hash della directory del codice dell’artefatto AOT risultante si trovi nella cache di attendibilità statica. Tali prodotti non sono firmati dalla chiave specifica per il dispositivo, perché l’autorità per la firma ha la propria radice nella catena di avvio protetto di Apple.
Codice x86_64 non firmato
I Mac dotati di chip Apple non consentono l’esecuzione di codice nativo arm64 se non vi è allegata una firma valida. Questa può essere anche una semplice firma “ad hoc” (vedi codesign(1)
) che non contiene nessuna informazione di identità dalla metà segreta della coppia di chiavi asimmetrica (è semplicemente una misurazione autenticata del binario).
Per questioni di compatibilità dei binari, il codice x86_64 tradotto può essere eseguito tramite Rosetta senza alcuna informazione riguardante la firma. La procedura di firma di Secure Enclave specifica per il dispositivo non fornisce alcuna identità a tale codice, che viene eseguito esattamente con le stesse limitazioni del codice nativo non firmato in esecuzione sui Mac dotati di processore Intel.