23 de diciembre de 2012

Otra piedrecita en el zapato de la FSF

Aunque en este blog alguna vez se ha criticado a la FSF y a Stallman, en realidad mi opinión personal sobre el asunto está algo entre mezclada. Comparto sus objetivos de fomentar el software libre, valoro que Stallman dedique su vida a patear el mundo dando charlas, aplaudo el trabajo de asesoramiento legal, me arrodillo ante la lucha contra el incumplimiento de la GPL, y soy consciente de que su tendencia a pensar lo peor de las multinacionales acaba teniendo muchos aciertos (se empeñan en darle la razón). Pero por otra parte se trata de un tipo que mantiene opiniones extremas y a menudo toma decisiones que a mi me parecen francamente estúpidas y que muestran una relación con la realidad un tanto especial.

Esto viene a cuento porque el mantenedor de GNU sed ha renunciado a su puesto. En el anuncio de versión detalla sus razones. No se trata de una ruptura confrontada ni de odios personales, simplemente disconformidades con la forma de gestionar el proyecto GNU. Además, en el propio anuncio nos enteramos de que el mantenedor de GnuTLS está moviendo el proyecto fuera de GNU, por razones parecidas: creen en la causa del software libre, pero están de desacuerdo con la gestión y las decisiones que se toman.

A mi me parece que esto no hace más que confirmar y fomentar la deriva e irrelevancia de GNU tal y como se pretendía plantear originalmente, que era como un proyecto de sistema operativo, y no el repositorio de proyectos variados que es hoy. Por mucho que se empeñen en seguir fomentando el uso del palabro "GNU/Linux", como si las distribuciones Linux fuesen, en cuanto a proyectos, seguidoras en algo de GNU, lo cierto es que la porción de software GNU incluido en una distribución moderna es más bien pequeña.

Las noticias de conflictos entre la FSF y desarrolladores de proyectos GNU no son nuevas, y sospecho que no serán las últimas. En los conflictos de GNU suelen haber un patrón que se repite: los programadores y mantenedores que aportan la mayoría del código se encuentran un día con decisiones o prácticas con las que ellos no están del todo acuerdo. Solucionar esos problemas internos no parece imposible, claro. Pero no hay que esperar milagros, recordemos que el éxito de LLVM (que acaba de anunciar su versión 3.2) se debe en buena parte a la politización de las decisiones técnicas de GCC. GCC siempre fue la joya de la corona, pero ahora que la gente puede pasar olímpicamente de GCC (aunque la muerte de GCC está muy exagerada), su valor se reduce, y con él el de GNU como proyecto. Aunque el software libre sale ganando, claro.

17 de diciembre de 2012

Premio a la chapuza del año


En Samsung a algún genio se le ha ocurrido incluir un dispositivo en /dev que permite acceso a toda la memoria del sistema en sus dispositivos Android. ¿Permisos de dicho dispositivo? ¡Abierto para todo el mundo! ¡Lectura y escritura! Ha habido otros problemas de seguridad, pero el absurdo que supone algo así no puede describirse con palabras. Es como volver a los tiempos de MS-DOS, sin protección de memoria ni multiusuario ni nada.

Por si esto no fuese bastante, han tenido la magnífica idea de hacer que varias librerías utilicen este dispositivo directamente, tal y como hacía X.org hace años, cuando accedía directamente a memoria para leer el bus PCI, lo cual hace complicado solucionar el problema. Y como remate final, el dispositivo incluye ioctls para sincronizar las caches L1 y L2 de la CPU (¿por qué una aplicación requiere acceso a algo así? Ni idea). Ni tan siquiera se les ha ocurrido usar el /dev/mem que viene de serie en cualquier kernel, se han tomado la molestia de reimplementar la cosa a mano.

16 de diciembre de 2012

Btrfs y colisiones de hash

A estas alturas habrán leído titulares en muchos sitios de Internet sobre un fallo de seguridad/ataque de denegación en Btrfs, provocando colisiones de hash desvelado por este blog. Como suele ocurrir con las cosas técnicas, la información ha oscilado entre la ausencia y la confusión, de ahí esta entrada.

La mayor confusión es que al mencionar la palabra "hash" junto con "btrfs", mucha gente ha asociado esto con la capacidad de Btrfs o ZFS de hacer checksums de todos los datos del disco, pero no tiene nada que ver. De lo que trata el ataque es del hash de los nombres de los archivos. Organizar el contenido de los directorios con un hash puede sorprender, pero es un método estándar utilizado por todos los sistemas de archivo modernos: Ext3/4, XFS, Reiserfs v3, JFS, ZFS, etc. Los checksums para asegurar la integridad del sistema de archivos son otro asunto.

Para calcular el hash de los nombres de archivo, Btrfs utiliza el algoritmo crc-32c. Como ha demostrado el artículo del blog citado anteriormente, se trata de un algoritmo débil frente a ataques de colisiones; es decir, es relativamente fácil generar a propósito un nombre de archivo cuyo hash crc32c sea idéntico al de otro con un nombre diferente. No pueden existir dos nombres con el mismo hash, por lo tanto se puede imposibilitar la creación de un archivo determinado creando otro que tenga el mismo hash.

El principal problema de Btrfs es que no se gestionan correctamente esas colisiones de hash. Una colisión por si misma no es ningún problema: se detecta fácilmente, se prohíbe la creación del archivo con hash duplicado, se devuelve error, y punto. No poder crear el archivo por la colisión es una molestia pero que se puede gestionar sin problemas, sin embargo, Btrfs parece entrar en un loop infinito para el proceso que encuentra la colisión, y eso es un fallo. Sobre su solución, hace poco que Btrfs ha añadido verdadera gestión de errores (Linux 3.4), y parece que había algunos parches en SuSE relacionados con ello que solucionan el problema de la colisión que aun no están en mainline - o quizás algunos fallos que hacen que el sistema de archivos se remonte en modo de solo lectura (el asunto no está del todo claro aun). En breve se enviarán los parches para 3.8 y para -stable, y Btrfs gestionará el problema normalmente, sin entrar en loops infinitos ni sufrir errores extraños. Hasta aquí el problema en la gestión de colisiones.

El otro asunto es la discusión sobre si el algoritmo de hash utilizado por Btrfs es demasiado débil. Este asunto es un poco más sutil. Lo cierto es que, aunque es cierto que el algoritmo es débil frente a colisiones, no es nada nuevo. El autor de Btrfs ya ha dicho que nunca esperó que crc-32c fuese capaz de resistir ataques colisiones. Seguramente tampoco resistan los de reiserfs, ni Ext4, ni XFS, si se intenta. Incluso ZFS usa CRC-64, que es más fuerte, pero no inquebrantable.

Lo cierto es que los algoritmos de hash utilizados habitualmente para ordenar directorios no se escogen pensando en resistir ataques extremos - de ser así, de entrada no usarían algoritmos como CRC. Esos algoritmos no se escogen pensando en resistir pruebas extremas de seguridad sino más bien en evitar coincidencias casuales y asegurar la integridad de datos (por ejemplo, en archivos comprimidos). Al fin y al cabo, se asume que si alguien permite a cualquier persona crear archivos en un directorio de su propiedad, es su problema (podrían hacerse otra clase de ataques DoS, como simplemente crear el máximo número de archivos posible que permita el sistema de archivos en un directorio).

Además, en los sistemas de archivo se tiene muy en cuenta que el algoritmo sea de cálculo sencillo, para afectar lo menos posible al rendimiento. Una de las razones por las que Btrfs utiliza crc-32c es que las CPUs Intel modernas con soporte SSE4.2 tienen una instrucción crc32c que permite usar ese algoritmo prácticamente "gratis". No parece que el autor de Btrfs tenga intención de cambiar el algoritmo por defecto (aunque quizás acepte otros alternativos para quienes quieran usarlos), simplemente solucionará el problema de gestión correcta de colisiones. Aun así, Btrfs un tiene espacio de 64 bits para almacenar el hash de los elementos de un directorio, por lo que añadir soporte para otro (u otros cuantos) algoritmos no sería especialmente difícil.

11 de diciembre de 2012

Las novedades de Linux 3.7

Ya se ha anunciado la versión 3.7 del kernel Linux. Esta versión incluye soporte para la nueva arquitectura de 64 bits de ARM, soporte ARM para multiplataforma - la habilidad de arrancar diferentes sistemas ARM con un mismo kernel-, soporte para la firma criptográfica de módulos del kernel, fsync() más veloz en Btrfs y soporte en éste para desactivar copy-on-write para cada archivo utilizando la herramienta chattr, una nueva herramienta "perf trace" que intenta imitar a strace, soporte completo para la característica TCP Fast Open, soporte experimental del protocolo SMBv2 usado por sistemas Windows modernos, soporte estable de NFS 4.1 y pNFS, un protocolo de tunelación que permite transferir paquetes ethernet de la Capa 2 a través de UDP, y soporte para la característica de seguridad de procesadores Intel "SMAP". También se han incluido drivers nuevos y muchas otras mejoras y pequeños cambios. La lista completa de cambios, en inglés, puede encontrarse aquí, como siempre. 

· Soporte de ARM multiplataforma: Una distribución Linux típica puede arrancar y funcionar en cientos de modelos diferentes (diferentes CPUs, GPUs, placas madre, chipsets, etc) de un mismo CD. Esta capacidad de arrancar en diferentes configuraciones de hardware es algo habitual en el mundo PC, pero no existía en el  mundo ARM Linux. En esta versión, Linux ha añadido soporte para esta capacidad. Esto hará mucho más sencillo el soporte de sistemas ARM por parte de las distros 

· Soporte de la arquitectura de 64 bits de ARM: Los modelos más modernos de ARM, ARMv8, añaden por primera vez soporte de direccionamiento de memoria de 64 bits. Estas CPUs pueden ejecutar código de 32 bits, pero el conjunto de instrucciones de 64 bits es muy diferente, no tan solo una extensión de las de 32 bits, así que el soporte de Linux ha sido añadido como una arquitectura completamente nueva - arm64. 

· Módulos del kernel firmados criptográficamente: Esta versión añade soporte para firmar módulos del kernel. De ese modo, el kernel puede prohibir la carga de módulos que no estén firmados con la clave correcta - incluso si lo intenta el usuario root. Esta característica es útil para propósitos de seguridad, ya que un atacante que ganase privilegios de root no podría instalar un rootkit utilizando la carga de módulos.

· Mejoras en Btrfs:
   * Mejoras de rendimiento de fsync(): La llamada al sistema fsync() escribe los datos modificados de un archivo al disco. El rendimiento de fsync() es importante para software como dpkg/rpm, Firefox, qemu, etc. El rendimiento de fsync() ha sido bastante malo históricamente, pero en esta versión es varias veces más rápido.

   * Soporte para desactivar copy-on-write para cada archivo usando chattr: Btrfs puede desactivar copy-on-write para los datos de una archivo usando la opción de montaje "nodatacow". En esta versión es posible desactivar copy-on-write individualmente para cada archivo utilizando el comando "chattr +C archivo" (requiere un e2fsprogs reciente).

  Copy-on-write no es beneficios para todo el mundo, y algunas aplicaciones quieren desactivarlo para conseguir mejor rendimiento y menor fragmentación. Nota: Para desactivar copy-on-write es necesario usar chattr en un archivo vacío, no funcionará en uno que ya tenga datos (en ese caso se puede crear un archivo temporal vacío, desactivar copy-on-write en él, copiar los datos de uno a otro y renombrar el archivo). Nota2: Desactivar copy-on-write desactivará también los checksums. Nota 3: Es posible usar chattr +C en un directorio, de modo que los nuevos archivos creados dentro de ese directorio heredarán la desactivación de copy-on-write

  * Eliminación del límite de enlaces duros dentro de un sólo directorio: Btrfs no permitía la creación de más de 20 enlaces duros dentro de un mismo directorio. Se ha hecho una modificación del formato del disco para añadir un nuevo tipo de "referencias a inodo" que eleva el límite por directorio a 65K.

  * Hole punching: "Hole punching" es la habilidad para desasignar un rango de espacio dentro de un archivo (usando la llamada al sistema fallocate() con el modo FALLOC_FL_PUNCH_HOLE). Btrfs ha añadido soporte para esta característica

· perf trace, una alternativa a strace: El subsistema de trazado perf ha añadido una nueva herramienta: perf trace. Esta herramienta debería parecerse a la venerable herramienta strace, pero en lugar de usar la llamada de systema ptrace(), utiliza la infraestructura de trazado de Linux. Su propósito es hacer el uso de las características de trazado más sencillo a los usuarios. Esta herramienta está en sus primeras versiones, pero mejorará con el tiempo.

· TCP Fast Open (lado del servidor): Linux ya añadió soporte para TCP Fast Open ("apertura rápida") para clientes en Linux 3.6. En esta versión se ha añadido soporte para el lado del servidor, completando de ese modo el soporte.

"Fast Open" es una optimización al proceso de establecimiento de una conexión TCP que permite eliminar un round time trip (RTT) de ciertas conexiones. Fast Open puede mejorar la carga de páginas entre un 4 y un 41%.

· Soporte experimental del protocolo SMBv2: ¡Nota! La lista de cambios de la versión anterior del kernel, ya mencionó esta característica, pero fue un error. El soporte no estaba disponible en esa versión, fue desactivado a última hora y sólo ha sido completado en esta versión.

El sistema de red cifs ha añadido soporte para la versión 2 del protocolo SMB. El protocolo SMB2 es el sucesor de los populares CIFS y SMB, y es el protocolo de invercambio de archivos por defecto en sistemas Windows desde Windows Vista en 2006. SMB2 eventualmente permitirá mejor rendimiento y seguridad y características que no eran posible con anteriores versiones del protocolo.

· NFS v4.1 ya no se considera experimental: El soporte para NFS v4.1 ([http://tools.ietf.org/html/rfc5661 RFC 5661]) ha estado en desarrollo durante mucho tiempo, y en esta versión se ha librado por primera vez de la etiqueta "experimental". La principal característica de NFS v4.1 es pNFS, es decir, "parallel NFS". pNFS permite tomar ventaja de clusters de servidores, permitiendo promorcionar acceso en paralelo escalable a archivos individuales o sistemas de archivos distribuidos entre varios servidores. Un sólo sistema de archivos puede estar repartido entre varios servidores, tanto a nivel de archivo como a nivel de bloque.

· Protocolo de tunelización vxlan "Virtual extensible LAN": Linux ha añadido soporte para vxlan, un protocolo de tunelización que permite transmitir paquetes ethernet de la Capa 2 sobre UDP. vxlan es usado con frecuencia para tunelizar redes en entornos de virtualización. El protocolo vxlan en si mismo es un [http://tools.ietf.org/html/draft-mahalingam-dutt-dcops-vxlan-02 borrador de RFC] que está diseñado para solventar el problema de número límitado de VLANs (4096), con vxlan el identificador se expande a 24 bits. El protocolo se ejecuta sobre UDP usando un sólo puerto de destino. A diferencia de otros túneles, una vxlan es una red de 1 a N destinos, no sólo punto a punto. Hay una implementación de vxlan para Openvswitch.

· Soporte para la característica SMAP de Intel: El "Supervisor Mode Access Prevention (SMAP)" es una característica que estará disponible en futuras CPUs Intel. Prohíbe al kernel el acceso a páginas de memoria usadas por el espacio de usuario. Esto permite detener ciertos tipos de exploits.

Y eso es todo. La lista completa de cambios en inglés, aquí.