Rosetta 2 en una Mac con Apple Chip
Las computadoras Mac con Apple Chip son capaces de ejecutar código compilado para el conjunto de instrucciones x86_64 mediante un mecanismo de traducción llamado Rosetta 2. Se ofrecen dos tipos de traducción: en tiempo de ejecución y anticipada.
Traducción en tiempo de ejecución
En la segmentación de traducción en tiempo de ejecución (JIT), un objeto Mach x86_64 se identifica al principio de la ruta de ejecución de la imagen. Cuando se encuentran estas imágenes, el kernel transfiere el control a un código auxiliar de traducción especial de Rosetta en lugar de al editor de enlace dinámico dyld(1)
. El código auxiliar de traducción luego traduce las páginas x86_64 durante la ejecución de la imagen. Esta traducción se lleva a cabo completamente dentro del proceso, y el kernel sigue verificando los hashes de código de cada página x86_64 mediante la firma de código adjunta al binario cuando la página tiene fallas. En caso de que el hash no coincida, el kernel aplica la política de corrección correspondiente para ese proceso.
Traducción anticipada
En la ruta de traducción anticipada (AOT), los binarios x86_64 se leen desde almacenamiento en los momentos que el sistema considera óptimos para la capacidad de respuesta de ese código. Los artefactos traducidos se escriben en el almacenamiento como un tipo especial de archivo de objeto Mach. Ese archivo es similar a una imagen ejecutable, pero está marcado para indicar que es el producto traducido de otra imagen.
En este modelo, el artefacto AOT deriva toda su información de identidad de la imagen ejecutable x86_64 original. Para aplicar esta vinculación, una entidad del espacio del usuario con privilegios firma el artefacto de traducción utilizando una clave específica del dispositivo que administra el Secure Enclave. Esta clave se entrega exclusivamente a la entidad del espacio del usuario con privilegios, que se identifica como tal mediante una autorización restringida. El directorio de códigos creado para el artefacto de traducción incluye el hash del directorio de códigos de la imagen ejecutable x86_64 original. La firma del artefacto de traducción en sí se conoce como firma complementaria.
La segmentación AOT comienza de manera similar a la de JIT, con la transferencia del control del kernel a la ejecución de Rosetta en lugar de al editor de enlace dinámico dyld(1)
. Pero la ejecución de Rosetta envía después una consulta de comunicación entre procesos (IPC) al servicio del sistema de Rosetta, que pregunta si hay una traducción AOT disponible para la imagen ejecutable actual. Si se encuentra, el servicio de Rosetta ofrece un manejo para esa traducción, y se asigna al proceso y se ejecuta. Durante la ejecución, el kernel aplica los hash del directorio de códigos del artefacto de traducción que se autentican mediante la firma arraigada en la clave de firma específica del dispositivo. Los hash del directorio de códigos de la imagen x86_64 original no están involucrados en este proceso.
Los artefactos traducidos se almacenan en una bóveda de datos a la que ninguna entidad puede acceder durante la ejecución, excepto el servicio de Rosetta. El servicio de Rosetta administra el acceso a su caché mediante la distribución de descriptores de archivos de sólo lectura a artefactos de traducción individuales; esto limita el acceso a la caché de artefactos AOT. La comunicación entre procesos de este servicio y la huella dependiente se mantienen de manera intencional muy estrechas para limitar su superficie de ataque.
Si el hash del directorio de códigos de la imagen x86_64 original no coincide con el codificado en la firma del artefacto de traducción AOT, este resultado se considera el equivalente a una firma de código no válida y se toman las medidas de aplicación apropiadas.
Si un proceso remoto consulta el kernel para obtener las autorizaciones u otras propiedades de identidad del código de un ejecutable traducido a AOT, se devuelven las propiedades de identidad de la imagen x86_64 original.
Contenido de caché de confianza estática
macOS 11 o versiones posteriores cuentan con archivos binarios “fat” o multiarquitectura de Mach que contienen fragmentos de código de computadora x86_64 y arm64. En las computadoras Mac con Apple Chip, el usuario puede decidir ejecutar el fragmento x86_64 de un binario del sistema a través de la segmentación de Rosetta; por ejemplo, para cargar un módulo que no tiene una variante nativa arm64. Para admitir este enfoque, la caché de confianza estática que se envía con macOS, en términos generales, contiene tres hashes de directorio de códigos por cada archivo de objeto Mach:
Un hash del directorio de códigos del fragmento arm64
Un hash del directorio de códigos del fragmento x86_64
Un hash del directorio de códigos de la traducción AOT del fragmento x86_64
El procedimiento de traducción AOT de Rosetta es determinante en el sentido de que produce una salida idéntica para cualquier entrada proporcionada, independientemente de cuándo se realizó la traducción o en qué dispositivo se realizó.
Durante la compilación de macOS, cada archivo de objeto Mach se ejecuta a través de la segmentación de la traducción AOT de Rosetta asociada con la versión de macOS que se está compilando, y el hash del directorio de códigos resultante se registra en la caché de confianza. Por razones de eficacia, los productos traducidos reales no se envían con el sistema operativo y se reconstituyen por solicitud cuando el usuario los solicita.
Cuando se está ejecutando una imagen x86_64 en una computadora Mac con Apple Chip, si el hash del directorio de códigos de esa imagen está en la caché de confianza estática, se espera que el hash del directorio de códigos del artefacto AOT resultante también esté en la caché de confianza estática. Dichos productos no están firmados por la clave específica del dispositivo, ya que la autoridad de firma está arraigada en la cadena de arranque seguro de Apple.
Código x86_64 sin firmar
Una computadora Mac con Apple Chip no permite la ejecución del código arm64 nativo a menos que se adjunte una firma válida. Esta firma puede ser tan simple como una firma de código ad hoc (véase codesign(1)
) que no tiene ninguna identidad real de la mitad secreta de un par de claves asimétricas (es simplemente una medida no autenticada del binario).
Para la compatibilidad binaria, el código x86_64 traducido puede ejecutarse a través de Rosetta sin ninguna información de firma. No se transmite una identidad específica a este código a través del procedimiento de firma del Secure Enclave específico del dispositivo, y se ejecuta exactamente con las mismas limitaciones que el código nativo sin firmar que se ejecuta en computadoras Mac basadas en Intel.