La virtualización es un pilar fundamental en la computación moderna, permitiendo la consolidación de recursos y el aislamiento de entornos. Sin embargo, las plataformas propietarias a menudo imponen restricciones artificiales que limitan su utilidad en escenarios de desarrollo y pruebas a gran escala. Este artículo aborda un problema específico en macOS Apple Silicon: la limitación de dos máquinas virtuales (VMs) activas simultáneamente. Esta restricción, impuesta por la licencia de software de Apple, se traduce en una barrera técnica a nivel de kernel, desafiando la flexibilidad que los ingenieros esperan de una plataforma de desarrollo.

La investigación se centra en desentrañar cómo esta limitación es aplicada a nivel de sistema operativo, y cómo puede ser eludida para fines no comerciales y de investigación. El objetivo es proporcionar una comprensión profunda de los mecanismos internos del kernel XNU, revelando cómo las políticas de licencia pueden manifestarse en el código de bajo nivel y cómo, con el conocimiento adecuado, estas barreras pueden ser superadas, abriendo nuevas posibilidades para la experimentación y el desarrollo en entornos Apple Silicon.

Arquitectura del Sistema

La arquitectura de virtualización en macOS Apple Silicon se basa en el framework Virtualization.framework, que a su vez interactúa con el kernel XNU. Inicialmente, se sospechó que la limitación residía en el espacio de usuario, dentro de Virtualization.framework. Sin embargo, un análisis detallado con herramientas como Hopper Disassembler reveló que el framework solo genera el mensaje de error, pero la lógica de la restricción se encuentra en el kernel.

La clave de la limitación se descubrió en el código cerrado de XNU, específicamente en las funciones relacionadas con el stack de virtualización, identificadas bajo el prefijo hv_vm_*. La variable hv_apple_isa_vm_quota dentro del kernel es la encargada de mantener el conteo de VMs activas, siendo decrementada y incrementada por funciones como hv_vm_destroy_0 y hv_trap_vm_create. En los kernels de desarrollo, esta variable puede ser sobrescrita mediante el boot-arg hv_apple_isa_vm_quota y habilitada por el boot-arg hypervisor. Sin embargo, en los kernels de lanzamiento, el acceso a esta funcionalidad está protegido por una verificación AppleInternal ligada a System Integrity Protection (SIP), específicamente el flag CSR_ALLOW_APPLE_INTERNAL.

Para eludir esta restricción, se requiere arrancar con un Kernel Debug Kit (KDK) de Apple, que incluye un kernel de desarrollo. Este kernel se compila en una 'Kernel Collection' (.kc) utilizando kmutil create, incorporando extensiones de kernel (kexts) necesarias. Posteriormente, se desactiva SIP y las restricciones de boot-args mediante csrutil disable y bputil --disable-boot-args-restriction en el modo de recuperación. Finalmente, se configura el sistema para arrancar con la Kernel Collection personalizada y se establecen los boot-args kcsuffix=development, hypervisor=0x1 y hv_apple_isa_vm_quota=0xFF (para 255 VMs) utilizando nvram.

Proceso de Elusión del Límite de VM

  1. 1 Identificación de la Restricción Análisis de `Virtualization.framework` y XNU para localizar el código de limi...
  2. 2 Obtención de KDK Descarga del Kernel Debug Kit (KDK) correspondiente a la versión de macOS.
  3. 3 Construcción de Kernel Collection Uso de `kmutil create` para generar una `VirtualMachine.kc` con el kernel de ...
  4. 4 Acceso a RecoveryOS Reinicio del Mac en modo de recuperación.
  5. 5 Desactivación de Seguridad Ejecución de `csrutil disable` y `bputil --disable-boot-args-restriction`.
  6. 6 Configuración de Boot Uso de `kmutil configure-boot` para seleccionar la KC personalizada.
  7. 7 Establecimiento de Boot-Args Configuración de `nvram` con `kcsuffix=development`, `hypervisor=0x1`, `hv_ap...
  8. 8 Reinicio y Verificación Reinicio del sistema y confirmación de la configuración con `sysctl` y `nvram`.
CapaTecnologíaJustificación
orchestration Virtualization.framework API de alto nivel para la creación y gestión de máquinas virtuales macOS en Apple Silicon. vs UTM (utiliza Virtualization.framework), Parallels Desktop (implementación propietaria)
compute XNU Kernel Núcleo del sistema operativo macOS, donde reside la lógica de virtualización de bajo nivel y la implementación de la cuota de VMs. `hv_apple_isa_vm_quota` variable, `hypervisor` boot-arg, `AppleInternal` check.
security System Integrity Protection (SIP) Mecanismo de seguridad que protege partes del sistema operativo de modificaciones, incluyendo la restricción de ciertos boot-args y la verificación `AppleInternal`. `CSR_ALLOW_APPLE_INTERNAL` flag.

Trade-offs

Ganancias
  • ▲▲ Número de VMs macOS simultáneas
  • Flexibilidad para desarrollo y pruebas
Costes
  • Seguridad del sistema (SIP desactivado)
  • Actualizaciones de macOS simplificadas
  • Soporte oficial de Apple
sudo kmutil create \
--arch arm64e \
--no-authorization \
--variant-suffix development \
--new boot \
--boot-path VirtualMachine.kc \
--kernel /Library/Developer/KDKs/KDK_14.0_23A5301h.kdk/System/Library/Kernels/kernel.development.t6020 \
--repository /Library/Developer/KDKs/KDK_14.0_23A5301h.kdk/System/Library/Extensions \
--repository /System/Library/Extensions \
--repository /System/Library/DriverExtensions \
--explicit-only $(kmutil inspect -V release --no-header | grep -v "SEPHiber" | awk '{print " -b "$1; }')
Comando para construir una Kernel Collection personalizada a partir de un Kernel Debug Kit.
csrutil disable
bputil --disable-boot-args-restriction
kmutil configure-boot --volume /Volumes/Macintosh\ HD --custom-boot-object /Volumes/Macintosh\ HD/Users/*/VirtualMachine.kc
nvram 40A0DDD2-77F8-4392-B4A3-1E7304206516:boot-args='kcsuffix=development hypervisor=0x1 hv_apple_isa_vm_quota=0xFF'
Comandos para deshabilitar SIP, permitir boot-args personalizados, configurar el arranque con la KC y establecer los boot-args para la cuota de VM.

Fundamentos Teóricos

Este problema se conecta con los fundamentos de la seguridad de sistemas operativos y la gestión de recursos, temas explorados en la academia desde los inicios de la computación. La imposición de límites a nivel de kernel para hacer cumplir políticas de licencia es un ejemplo de cómo las restricciones no técnicas se traducen en mecanismos de bajo nivel. Conceptos como la 'Trusted Computing Base' (TCB) y la 'separación de privilegios' son directamente relevantes, ya que el kernel actúa como la TCB que impone estas políticas, y la elusión implica manipular los privilegios de arranque.

Aunque no hay un paper específico que prediga esta implementación exacta, el trabajo de Butler Lampson en 'Protection' (1971) y los principios de seguridad de Saltzer y Schroeder en 'The Protection of Information in Computer Systems' (1975) proporcionan el marco teórico para entender cómo los sistemas operativos controlan el acceso a recursos y cómo se diseñan los mecanismos de protección. La manipulación de boot-args y la desactivación de SIP son análogas a la explotación de configuraciones de seguridad para alterar el comportamiento previsto del sistema, un área de estudio constante en la seguridad informática.