domingo, febrero 08, 2009

strlcpy y strlcat: Funciones en C para copia y concatenación de cadenas

Hace algún tiempo, vía Reddit.proggraming di con el artículo de Todd C. Miller y Theo de Raadt,strlcpy and strlcat - consistent, safe, string copy and concatenation., donde hablan las decisiones que les llevaron a diseñar estas dos funciones para mitigar los problemas de buffer overflow o desbordamiento de búfer tan habituales en los programas en escritos en C. El artículo definitivo para entender las consecuencias de seguridad de estos errores de programación es el Smashing The Stack For Fun And Profit que Aleph One publicó en el número 49 de la Phrack Magazine

El típico programa de un buffer overflow en C se da en la siguiente función:

int mi_funcion(char *input){
    char buf[256];
    ....
    ....
    strcat("CADENA",buf);
    ....
    ....
    return 0;
}
Si la cadena a la que apunta input es controlada por el usuario y no existe ningún límite en el número de caracteres (ya sea porque estamos leyendo de un fichero en disco, de la red o entrada del usuario vía teclado), al usar la función strcat acabaremos sobrepansando el tamaño de buf, y escribiendo en direcciones de memoria que no se debe. Si el programa donde se da este fallo se ejecuta con privilegios, puede aprovecharse para hacer una escalada desde un usuario normal a otro privilegiado.

Lo primero es usar las funciones de la librería estándar de C:strncpy y strncat.

char* strncpy(char *restrict s1, const char *restrict s2, size_t n);
char* strncat(char *restrict s1, const char *restrict s2, size_t n);
El cambio fundamental es es el parámetro n, que especifica el número de bytes del búfer apuntado por s1. Así cualquiera de esas dos funciones copiará como máximo n bytes o bien si encuentra en la cadena que esté copiando, el carácter que manda el fin de cadena en C, el \0.

Sin embargo estas dos funciones tienen dos problemas:

  • strncpy no termina con el \0 la cadena si se utiliza todo el búfer.
  • strncat rellena de ceros todo el búfer de destino hasta el tamaño que se especifica
Para evitar estos problemas Todd C. Miller y Theo de Raadt propusieron las funciones strlcat y strlcpy:
size_t strlcpy(char *dst, const char *src, size_t size);
size_t strlcat(char *dst, const char *src, size_t size);
Estas dos funciones garantizan que las cadenas están terminada con un \0 y permite detectar de manera sencilla en el caso de strlcat la existencia de que una cadena se trunque, como puede verse en este ejemplo sacado de la página de manual de MacOS X:
if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname))
    goto toolong;
if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname))
    goto toolong;
Las decisiones de diseño que llevaron a estas funciones están descritas en el artículo enlazado al principio. Aunque hace mucho tiempo del artículo, en el año 1999, es una lectura interesante para comprender la evolución de las API para evitar los problemas de seguridad.

Actualización

Me comenta mig21 que estas funciones no siempre le han gustado a otros desarrolladores. Por ejemplo, Ulrich Drepper, mantenedor de la GNU libc:
This is horribly inefficient BSD crap. Using these function only leads to other errors. Correct string handling means that you always know how long your strings are and therefore you can you memcpy (instead of strcpy).
Y es interesante el enlace a la entrada en la wikipedia de strlcpy.

Technorati Tags: ,

jueves, febrero 05, 2009

Manejo de la memoria y anotomia del uso de la memoria de un proceso en Linux

(vía reddit.programming Gustavo Duarte vuelve a la carga con dos excelentes y detalladas entradas que explica el mapa de memoria de un proceso en Linux y como el kernel utiliza la memoria. Entradas muy detalladas, con excelentes gráficos y referencias al código fuente de la implementación en Linux.

El blog de Gustavo Duarte tiene información muy interesante para cualquiera que le interese la programción a bajo nivel y como funciona los microprocesadores Intel. A tener en el agregador RSS, sin duda.

Technorati Tags: ,

miércoles, febrero 04, 2009

Proteccionismo económico, deuda pública

Una de las peores consecuencias de esta crisis económica que estamos sufriendo es la vuelta a las medidas proteccionistas. Los planes de rescate que se están estudiando en EEUU incluyen cláusulas para que sólo se beneficien aquellos proyectos que usen hierro y acero fabricano en EEUU, en Inglaterra hay huelgas pidiendo que se contraten a trabajadores británicos frente a extranjeros o se corta la inmigración de universitarios de fuera de la UE, o el ministro de industria español, Miguel Sebastián, pidiendo que se cumpre producto español. Es interesante repasar la lista de medidas proteccionistas que se está fraguando. Los franceses tampoco se libran de este club.

Una de las leyes que se aprobaron en EEUU durante el New Deal tras el crack de 1929 fue la Hawley_Tariff_Act que elevó los aranceles de importación para más de veinte mil productos, lo que acabó causando que otros países aumentaran los aranceles a los productos fabricados en EEUU e importados por ellos, con la correspondiente caída del comercio internacional y que según algunos economistas fue una de las causas que hizo más profunda la Gran Depresión (podéis ver El despeñadero proteccionista, un artículo de opinión sobre este tema)

En el caso de España, no está mal recordar que somos en tanto por ciento, el país más endeudado del mundo. Las exportaciones españolas vienen a ser aproximadamente un 20% del PIB español. Si de buenas a primeras, empezaran a aparecer aranceles,España sería un país muy perjudicado, con una deuda bestial a la que hacer frente y las dificultades para exportar.

Para acabar, me ha llamado la atención de la emisión de deuda pública de 67000 millones de dólares por parte del Tesoro americano. De esta emisión, aproximandamente 36300 millones se utilizará para, ¡pagar los vencimientos de otras emisiones de deuda anteriores!. Es decir, la pescadilla que se muerde la cola, ojo con este tipo de cosas, porque con la cantidad de dinero que están inyectando en diversas empresas americanas que son zombies, cuando tengan que hacer frente a los costes de estos planes - se habla de 800000 millones de dólares -, tendrán que recaudar vía fiscalidad ese dinero, porque si lo que piensan es ir emitiendo deuda para pagar la que va venciendo, el dólar puede empezar a cavar su tumba, porque como los compradores de deuda pública pierdan la confianza....

Technorati Tags: ,

martes, febrero 03, 2009

Novedades de Python 3.x en Developer Works

La gente de IBM ha publicado un par de artículos sobre las próximas novedades de Python 3.x. En el primero de ellos, Python 3 primer, Part 1: What's new en Python 3 primer, Part 2: Advanced topics se habla sobre:
  • La nueva función print()
  • El cambio de raw_input() a input()
  • Un nuevo tipo, bytes para almacenar enteros entre 0 y 127, es decir, caracteres ASCII no extendidos.
  • Permite identificadores que sean cadenas Unicode y evitar la conversión a ASCII de la función repr()
  • Aparece una nueva manera de utilizar cadenas formateadas, aparte del operador %. Los objetos tienen ahora un o format
  • Cambios en los diccionarios. Desaparecen algunos métodos.
  • Nuevo modelo de entrada y salida
  • Class decorators
  • Metaclasses
  • Abstract base classes
  • Cambio en la sintaxis de las excepciones.
  • Se añade la represantación binaria a los posibles literales numéricos y se modifica el octal
  • Anotación de funciones
Puede verse en los dos artículos de Developer Works pueden verse varios ejemplos de lo anterior. Espero poco a poco, ir viéndolas y experimentando con ellas, aunque la versión 3.0 tardará en estar generalizada y convivirá mucho tiempo con la 2.x, es interesante ver las novedades, es especial porque poco a recibido alguna de las características de la versión 3.x para que se pueda ir adaptando el código.

Technorati Tags:

domingo, febrero 01, 2009

¿El que se parecen un UltraSparc y un Z80A?

Leyendo un documento sobre el microprocesador de Sun UltraSPARC, me llamó la atención la existencia de cuatro juegos de registros globales, cuyo uso se controla a través de una serie de campos en el registro PSTATE. Esta técnica no es nueva en el mundo de los microprocesadores, porque existía algo similar en el antiguo Z80A de Zilog: tenía duplicados los registros principales y se podía aprovechar la velocidad de cambio a este juego de registros alternativos para evitar en el tratamiento de interrupciones almacenar todos el banco de registros en la pila. En el caso de la UltraSparc, tiene cuatro juegos de registros globales. Si alguien tiene curiosidad de ver como se selecciona cada juego, puede mirar cif.S, en el código fuente de Linux, aunque este código sólo lo puede ejecutar la CPU en modo privilegiado.

Referencias

  1. UltraSPARC III Cu User's manual
  2. STP1031, UltraSPARCTM-II
  3. OpenSPARC T1 Microarchitecture Specification

Technorati Tags: ,