Limpieza de desbordamiento de enteros

Los desbordamientos de enteros no deseados pueden causar daños en la memoria o vulnerabilidades de divulgación de información en las variables asociadas con los accesos a la memoria o las asignaciones de memoria. Para combatir esto, agregamos UndefinedBehaviorSanitizer (UBSan) de Clang, desinfectantes de desbordamiento de enteros firmados y sin firmar para fortalecer el marco de medios en Android 7.0. En Android 9, ampliamos UBSan para cubrir más componentes y mejoramos la compatibilidad del sistema de compilación.

Esto está diseñado para agregar comprobaciones en torno a operaciones/instrucciones aritméticas, que podrían desbordarse, para abortar de manera segura un proceso si ocurre un desbordamiento. Estos desinfectantes pueden mitigar toda una clase de corrupción de la memoria y vulnerabilidades de divulgación de información donde la causa raíz es un desbordamiento de enteros, como la vulnerabilidad Stagefright original.

Ejemplos y fuente

El compilador proporciona desinfección de desbordamiento de enteros (IntSan) y agrega instrumentación al binario durante el tiempo de compilación para detectar desbordamientos aritméticos. Está habilitado de forma predeterminada en varios componentes de la plataforma, por ejemplo, /platform/external/libnl/Android.bp .

Implementación

IntSan utiliza los desinfectantes de desbordamiento de enteros con y sin signo de UBSan. Esta mitigación está habilitada a nivel de módulo. Ayuda a mantener seguros los componentes críticos de Android y no debe desactivarse.

Le recomendamos encarecidamente que habilite la desinfección de desbordamiento de enteros para componentes adicionales. Los candidatos ideales son el código nativo privilegiado o el código nativo que analiza la entrada del usuario que no es de confianza. Hay una pequeña sobrecarga de rendimiento asociada con el desinfectante que depende del uso del código y la prevalencia de las operaciones aritméticas. Espere un pequeño porcentaje de gastos generales y pruebe si el rendimiento es una preocupación.

Compatibilidad con IntSan en makefiles

Para habilitar IntSan en un archivo MAKE, agregue:

LOCAL_SANITIZE := integer_overflow
# Optional features
LOCAL_SANITIZE_DIAG := integer_overflow
LOCAL_SANITIZE_BLACKLIST := modulename_blacklist.txt
  • LOCAL_SANITIZE toma una lista separada por comas de desinfectantes, con integer_overflow como un conjunto preempaquetado de opciones para los desinfectantes de desbordamiento de enteros individuales firmados y sin firmar con una lista negra predeterminada .
  • LOCAL_SANITIZE_DIAG activa el modo de diagnóstico para los desinfectantes. Utilice el modo de diagnóstico solo durante las pruebas, ya que esto no anulará los desbordamientos, anulando por completo la ventaja de seguridad de la mitigación. Consulte Solución de problemas para obtener detalles adicionales.
  • LOCAL_SANITIZE_BLACKLIST le permite especificar un archivo de lista negra para evitar que se desinfecten las funciones y los archivos de origen. Consulte Solución de problemas para obtener detalles adicionales.

Si desea un control más granular, habilite los desinfectantes individualmente usando una o ambas banderas:

LOCAL_SANITIZE := signed-integer-overflow, unsigned-integer-overflow
LOCAL_SANITIZE_DIAG := signed-integer-overflow, unsigned-integer-overflow

Compatibilidad con IntSan en archivos blueprint

Para habilitar la desinfección de desbordamiento de enteros en un archivo blueprint, como /platform/external/libnl/Android.bp , agregue:

   sanitize: {
      integer_overflow: true,
      diag: {
          integer_overflow: true,
      },
      blacklist: "modulename_blacklist.txt",
   },

Al igual que con los archivos make, la propiedad integer_overflow es un conjunto preempaquetado de opciones para los desinfectantes individuales de desbordamiento de enteros firmados y sin firmar con una lista negra predeterminada .

El conjunto de propiedades diag habilita el modo de diagnóstico para los desinfectantes. Use el modo de diagnóstico solo durante la prueba. El modo de diagnóstico no aborta en los desbordamientos, lo que anula por completo la ventaja de seguridad de la mitigación en las compilaciones de usuarios. Consulte Solución de problemas para obtener detalles adicionales.

La propiedad de la blacklist permite la especificación de un archivo de lista negra que permite a los desarrolladores evitar que las funciones y los archivos de origen se desinfecten. Consulte Solución de problemas para obtener detalles adicionales.

Para habilitar los desinfectantes individualmente, use:

   sanitize: {
      misc_undefined: ["signed-integer-overflow", "unsigned-integer-overflow"],
      diag: {
          misc_undefined: ["signed-integer-overflow",
                           "unsigned-integer-overflow",],
      },
      blacklist: "modulename_blacklist.txt",
   },

Solución de problemas

Si está habilitando la desinfección de desbordamiento de enteros en componentes nuevos, o confía en bibliotecas de plataforma que han tenido desinfección de desbordamiento de enteros, es posible que tenga algunos problemas con desbordamientos de enteros benignos que causan abortos. Debe probar los componentes con la desinfección habilitada para asegurarse de que puedan surgir desbordamientos benignos.

Para encontrar cancelaciones causadas por la desinfección en las compilaciones de los usuarios, busque bloqueos de SIGABRT con mensajes de cancelación que indiquen un desbordamiento detectado por UBSan, como:

pid: ###, tid: ###, name: Binder:###  >>> /system/bin/surfaceflinger <<<
signal 6 (SIGABRT), code -6 (SI_TKILL), fault addr --------
Abort message: 'ubsan: sub-overflow'

El seguimiento de la pila debe incluir la función que causa el aborto; sin embargo, los desbordamientos que ocurren en las funciones en línea pueden no ser evidentes en el seguimiento de la pila.

Para determinar más fácilmente la causa raíz, habilite los diagnósticos en la biblioteca que activan la cancelación e intente reproducir el error. Con los diagnósticos habilitados, el proceso no se cancelará y, en su lugar, continuará ejecutándose. No abortar ayuda a maximizar la cantidad de desbordamientos benignos en una ruta de ejecución particular sin tener que volver a compilar después de corregir cada error. Diagnostics genera un mensaje de error que incluye el número de línea y el archivo de origen que provoca la cancelación:

frameworks/native/services/surfaceflinger/SurfaceFlinger.cpp:2188:32: runtime error: unsigned integer overflow: 0 - 1 cannot be represented in type 'size_t' (aka 'unsigned long')

Una vez que se encuentra la operación aritmética problemática, asegúrese de que el desbordamiento sea benigno y intencionado (por ejemplo, no tiene implicaciones de seguridad). Puede abordar el aborto del desinfectante de la siguiente manera:

  • Refactorización del código para evitar el desbordamiento ( ejemplo )
  • Desbordamiento explícito a través de las funciones __builtin_*_overflow de Clang ( ejemplo )
  • Deshabilitar la desinfección en la función especificando el atributo no_sanitize ( ejemplo )
  • Deshabilitar el saneamiento de una función o archivo fuente a través de un archivo de lista negra ( ejemplo )

Debe utilizar la solución más granular posible. Por ejemplo, una función grande con muchas operaciones aritméticas y una sola operación de desbordamiento debe tener la operación única refactorizada en lugar de la función completa en la lista negra.

Los patrones comunes que pueden resultar en desbordamientos benignos incluyen:

  • Conversiones implícitas en las que se produce un desbordamiento sin firmar antes de convertirse en un tipo firmado ( ejemplo )
  • Eliminaciones de listas vinculadas que disminuyen el índice de bucle en la eliminación ( ejemplo )
  • Asignar un tipo sin firmar a -1 en lugar de especificar el valor máximo real ( ejemplo )
  • Bucles que decrementan un entero sin signo en la condición ( ejemplo , ejemplo )

Se recomienda que los desarrolladores se aseguren de que, en los casos en los que el sanitizer detecte un desbordamiento, sea realmente benigno, sin efectos secundarios no deseados ni implicaciones de seguridad antes de desactivar el sanitizer.

Deshabilitar IntSan

Puede deshabilitar IntSan con listas negras o atributos de funciones. Desactive con moderación y solo cuando la refactorización del código no sea razonable o si hay una sobrecarga de rendimiento problemática.

Consulte la documentación de Clang upstream para obtener más información sobre cómo deshabilitar IntSan con atributos de función y formato de archivo de lista negra . La lista negra debe limitarse al desinfectante en particular mediante el uso de nombres de sección que especifiquen el desinfectante de destino para evitar afectar a otros desinfectantes.

Validación

Actualmente, no existe una prueba CTS específica para la desinfección de desbordamiento de enteros. En su lugar, asegúrese de que las pruebas de CTS pasen con o sin IntSan habilitado para verificar que no esté afectando el dispositivo.