diff options
Diffstat (limited to 'Documentation/translations/sp_SP/process/deprecated.rst')
-rw-r--r-- | Documentation/translations/sp_SP/process/deprecated.rst | 381 |
1 files changed, 381 insertions, 0 deletions
diff --git a/Documentation/translations/sp_SP/process/deprecated.rst b/Documentation/translations/sp_SP/process/deprecated.rst new file mode 100644 index 000000000000..d52120e0d753 --- /dev/null +++ b/Documentation/translations/sp_SP/process/deprecated.rst @@ -0,0 +1,381 @@ +.. include:: ../disclaimer-sp.rst + +:Original: :ref:`Documentation/process/deprecated.rst <deprecated>` +:Translator: Sergio Gonzalez <sergio.collado@gmail.com> + +.. _sp_deprecated: + +============================================================================ +Interfaces obsoletos, Características del lenguaje, Atributos y Convenciones +============================================================================ + +En un mundo perfecto, sería posible convertir todas las instancias de +alguna API obsoleta en una nueva API y quitar la API anterior en un +único ciclo de desarrollo. Desafortunadamente, debido al tamaño del kernel, +la jerarquía de mantenimiento, y el tiempo, no siempre es posible hacer +estos cambios de una única vez. Esto significa que las nuevas instancias +han de ir creándose en el kernel, mientras que las antiguas se quitan, +haciendo que la cantidad de trabajo para limpiar las APIs crezca. Para +informar a los desarrolladores sobre qué ha sido declarado obsoleto y por +qué, ha sido creada esta lista como un lugar donde indicar cuando los usos +obsoletos son propuestos para incluir en el kernel. + +__deprecated +------------ +Mientras que este atributo señala visualmente que un interface ha sido +declarado obsoleto, este `no produce más avisos durante las compilaciones +<https://git.kernel.org/linus/771c035372a036f83353eef46dbb829780330234>`_ +porque uno de los objetivos del kernel es que compile sin avisos, y +nadie ha hecho nada para quitar estos interfaces obsoletos. Mientras +que usar `__deprecated` es sencillo para anotar una API obsoleta en +un archivo de cabecera, no es la solución completa. Dichos interfaces +deben o bien ser quitados por completo, o añadidos a este archivo para +desanimar a otros a usarla en el futuro. + +BUG() y BUG_ON() +---------------- +Use WARN() y WARN_ON() en su lugar, y gestione las condiciones de error +"imposibles" tan elegantemente como se pueda. Mientras que la familia de +funciones BUG() fueron originalmente diseñadas para actuar como una +"situación imposible", confirmar y disponer de un hilo del kernel de forma +"segura", estas funciones han resultado ser demasiado arriesgadas. (e.g. +"¿en qué orden se necesitan liberar los locks? ¿Se han restaurado sus +estados?). La popular función BUG() desestabilizará el sistema o lo romperá +totalmente, lo cual hace imposible depurarlo o incluso generar reportes de +crash. Linus tiene una `opinión muy fuerte +<https://lore.kernel.org/lkml/CA+55aFy6jNLsywVYdGp83AMrXBo_P-pkjkphPGrO=82SPKCpLQ@mail.gmail.com/>`_ +y sentimientos `sobre esto +<https://lore.kernel.org/lkml/CAHk-=whDHsbK3HTOpTF=ue_o04onRwTEaK_ZoJp_fjbqq4+=Jw@mail.gmail.com/>`_. + +Nótese que la familia de funciones WARN() únicamente debería ser usada +en situaciones que se "esperan no sean alcanzables". Si se quiere +avisar sobre situaciones "alcanzables pero no deseadas", úsese la familia +de funciones pr_warn(). Los responsables del sistema pueden haber definido +*panic_on_warn* sysctl para asegurarse que sus sistemas no continúan +ejecutándose en presencia del condiciones "no alcanzables". (Por ejemplo, +véase commits como `este +<https://git.kernel.org/linus/d4689846881d160a4d12a514e991a740bcb5d65a>`_.) + +Operaciones aritméticas en los argumentos de reserva de memoria +--------------------------------------------------------------- +Los cálculos dinámicos de tamaño (especialmente multiplicaciones) no +deberían realizarse en los argumentos de reserva de memoria (o similares) +debido al riesgo de desbordamiento. Esto puede llevar a valores rotando y +que se realicen reservas de memoria menores que las que se esperaban. El +uso de esas reservas puede llevar a desbordamientos en el 'heap' de memoria +y otros funcionamientos incorrectos. (Una excepción a esto son los valores +literales donde el compilador si puede avisar si estos puede desbordarse. +De todos modos, el método recomendado en estos caso es reescribir el código +como se sugiere a continuación para evitar las operaciones aritméticas en +la reserva de memoria.) + +Por ejemplo, no utilice `count * size`` como argumento, como en:: + + foo = kmalloc(count * size, GFP_KERNEL); + +En vez de eso, utilice la reserva con dos argumentos:: + + foo = kmalloc_array(count, size, GFP_KERNEL); + +Específicamente, kmalloc() puede ser sustituido con kmalloc_array(), +kzalloc() puede ser sustituido con kcalloc(). + +Si no existen funciones con dos argumentos, utilice las funciones que se +saturan, en caso de desbordamiento:: + + bar = vmalloc(array_size(count, size)); + +Otro caso común a evitar es calcular el tamaño de una estructura com +la suma de otras estructuras, como en:: + + header = kzalloc(sizeof(*header) + count * sizeof(*header->item), + GFP_KERNEL); + +En vez de eso emplee:: + + header = kzalloc(struct_size(header, item, count), GFP_KERNEL); + +.. note:: Si se usa struct_size() en una estructura que contiene un elemento + de longitud cero o un array de un único elemento como un array miembro, + por favor reescribir ese uso y cambiar a un `miembro array flexible + <#zero-length-and-one-element-arrays>`_ + + +Para otros cálculos, por favor use las funciones de ayuda: size_mul(), +size_add(), and size_sub(). Por ejemplo, en el caso de:: + + foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL); + +Re-escríbase, como:: + + foo = krealloc(size_add(current_size, + size_mul(chunk_size, + size_sub(count, 3))), GFP_KERNEL); + +Para más detalles, mire también array3_size() y flex_array_size(), +como también la familia de funciones relacionadas check_mul_overflow(), +check_add_overflow(), check_sub_overflow(), y check_shl_overflow(). + + +simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull() +---------------------------------------------------------------------- +Las funciones: simple_strtol(), simple_strtoll(), simple_strtoul(), y +simple_strtoull() explícitamente ignoran los desbordamientos, lo que puede +llevar a resultados inesperados por las funciones que las llaman. Las +funciones respectivas kstrtol(), kstrtoll(), kstrtoul(), y kstrtoull() +tienden a ser reemplazos correctos, aunque nótese que necesitarán que la +cadena de caracteres termine en NUL o en el carácter de línea nueva. + + +strcpy() +-------- +strcpy() no realiza verificaciones de los límites del buffer de destino. +Esto puede resultar en desbordamientos lineals más allá del fin del buffer, +causando todo tipo de errores. Mientras `CONFIG_FORTIFY_SOURCE=y` otras +varias opciones de compilación reducen el riesgo de usar esta función, no +hay ninguna buena razón para añadir nuevos usos de esta. El remplazo seguro +es la función strscpy(), aunque se ha de tener cuidado con cualquier caso +en el el valor retornado por strcpy() sea usado, ya que strscpy() no +devuelve un puntero a el destino, sino el número de caracteres no nulos +compilados (o el valor negativo de errno cuando se trunca la cadena de +caracteres). + +strncpy() en cadenas de caracteres terminadas en NUL +---------------------------------------------------- +El uso de strncpy() no garantiza que el buffer de destino esté terminado en +NUL. Esto puede causar varios errores de desbordamiento en lectura y otros +tipos de funcionamiento erróneo debido a que falta la terminación en NUL. +Esta función también termina la cadena de caracteres en NUL en el buffer de +destino si la cadena de origen es más corta que el buffer de destino, lo +cual puede ser una penalización innecesaria para funciones usen esta +función con cadenas de caracteres que sí están terminadas en NUL. + +Cuando se necesita que la cadena de destino sea terminada en NUL, +el mejor reemplazo es usar la función strscpy(), aunque se ha de tener +cuidado en los casos en los que el valor de strncpy() fuera usado, ya que +strscpy() no devuelve un puntero al destino, sino el número de +caracteres no nulos copiados (o el valor negativo de errno cuando se trunca +la cadena de caracteres). Cualquier caso restante que necesitase todavía +ser terminado en el caracter nulo, debería usar strscpy_pad(). + +Si una función usa cadenas de caracteres que no necesitan terminar en NUL, +debería usarse strtomem(), y el destino debería señalarse con el atributo +`__nonstring +<https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html>`_ +para evitar avisos futuros en el compilador. Para casos que todavía +necesitan cadenas de caracteres que se rellenen al final con el +caracter NUL, usar strtomem_pad(). + +strlcpy() +--------- +strlcpy() primero lee por completo el buffer de origen (ya que el valor +devuelto intenta ser el mismo que el de strlen()). Esta lectura puede +sobrepasar el límite de tamaño del destino. Esto ineficiente y puede causar +desbordamientos de lectura si la cadena de origen no está terminada en el +carácter NUL. El reemplazo seguro de esta función es strscpy(), pero se ha +de tener cuidado que en los casos en lso que se usase el valor devuelto de +strlcpy(), ya que strscpy() devolverá valores negativos de erno cuando se +produzcan truncados. + +Especificación de formato %p +---------------------------- +Tradicionalmente,el uso de "%p" en el formato de cadenas de caracteres +resultaría en exponer esas direcciones en dmesg, proc, sysfs, etc. En vez +de dejar que sean una vulnerabilidad, todos los "%p" que se usan en el +kernel se imprimen como un hash, haciéndolos efectivamente inutilizables +para usarlos como direcciones de memoria. Nuevos usos de "%p" no deberían +ser añadidos al kernel. Para textos de direcciones, usar "%pS" es +mejor, ya que resulta en el nombre del símbolo. Para prácticamente el +resto de casos, mejor no usar "%p" en absoluto. + +Parafraseando las actuales `direcciones de Linus <https://lore.kernel.org/lkml/CA+55aFwQEd_d40g4mUCSsVRZzrFPUJt74vc6PPpb675hYNXcKw@mail.gmail.com/>`_: + +- Si el valor "hasheado" "%p" no tienen ninguna finalidad, preguntarse si el + puntero es realmente importante. ¿Quizás se podría quitar totalmente? +- Si realmente se piensa que el valor del puntero es importante, ¿porqué + algún estado del sistema o nivel de privilegio de usuario es considerado + "especial"? Si piensa que puede justificarse (en comentarios y mensajes + del commit), de forma suficiente como para pasar el escrutinio de Linux, + quizás pueda usar el "%p", a la vez que se asegura que tiene los permisos + correspondientes. + +Si está depurando algo donde el "%p" hasheado está causando problemas, +se puede arrancar temporalmente con la opción de depuración "`no_hash_pointers +<https://git.kernel.org/linus/5ead723a20e0447bc7db33dc3070b420e5f80aa6>`_". + + +Arrays de longitud variable (VLAs) +---------------------------------- +Usando VLA en la pila (stack) produce un código mucho peor que los arrays +de tamaño estático. Mientras que estos errores no triviales de `rendimiento +<https://git.kernel.org/linus/02361bc77888>`_ son razón suficiente +para no usar VLAs, esto además son un riesgo de seguridad. El crecimiento +dinámico del array en la pila, puede exceder la memoria restante en +el segmento de la pila. Esto podría llevara a un fallo, posible sobre-escritura +de contenido al final de la pila (cuando se construye sin +`CONFIG_THREAD_INFO_IN_TASK=y`), o sobre-escritura de la memoria adyacente +a la pila (cuando se construye sin `CONFIG_VMAP_STACK=y`). + + +Switch case fall-through implícito +---------------------------------- +El lenguaje C permite a las sentencias 'switch' saltar de un caso al +siguiente caso cuando la sentencia de ruptura "break" no aparece al final +del caso. Esto, introduce ambigüedad en el código, ya que no siempre está +claro si el 'break' que falta es intencionado o un olvido. Por ejemplo, no +es obvio solamente mirando al código si `STATE_ONE` está escrito para +intencionadamente saltar en `STATE_TWO`:: + + switch (value) { + case STATE_ONE: + do_something(); + case STATE_TWO: + do_other(); + break; + default: + WARN("unknown state"); + } + +Ya que ha habido una larga lista de defectos `debidos a declaraciones de "break" +que faltan <https://cwe.mitre.org/data/definitions/484.html>`_, no se +permiten 'fall-through' implícitos. Para identificar 'fall-through' +intencionados, se ha adoptado la pseudo-palabra-clave macro "falltrhrough", +que expande las extensiones de gcc `__attribute__((__fallthrough__)) +<https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html>`_. +(Cuando la sintaxis de C17/c18 `[[fallthrough]]` sea más comúnmente +soportadas por los compiladores de C, analizadores estáticos, e IDEs, +se puede cambiar a usar esa sintaxis para esa pseudo-palabra-clave. + +Todos los bloques switch/case deben acabar en uno de: + +* break; +* fallthrough; +* continue; +* goto <label>; +* return [expression]; + + +Arrays de longitud cero y un elemento +------------------------------------- +Hay una necesidad habitual en el kernel de proveer una forma para declarar +un grupo de elementos consecutivos de tamaño dinámico en una estructura. +El código del kernel debería usar siempre `"miembros array flexible" <https://en.wikipedia.org/wiki/Flexible_array_member>`_ +en estos casos. El estilo anterior de arrays de un elemento o de longitud +cero, no deben usarse más. + +En el código C más antiguo, los elementos finales de tamaño dinámico se +obtenían especificando un array de un elemento al final de una estructura:: + + struct something { + size_t count; + struct foo items[1]; + }; + +En código C más antiguo, elementos seguidos de tamaño dinámico eran creados +especificando una array de un único elemento al final de una estructura:: + + struct something { + size_t count; + struct foo items[1]; + }; + +Esto llevó a resultados incorrectos en los cálculos de tamaño mediante +sizeof() (el cual hubiera necesitado eliminar el tamaño del último elemento +para tener un tamaño correcto de la "cabecera"). Una `extensión de GNU C +<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_ se empezó a usar +para permitir los arrays de longitud cero, para evitar estos tipos de +problemas de tamaño:: + + struct something { + size_t count; + struct foo items[0]; + }; + +Pero esto llevó a otros problemas, y no solucionó algunos otros problemas +compartidos por ambos estilos, como no ser capaz de detectar cuando ese array +accidentalmente _no_ es usado al final de la estructura (lo que podía pasar +directamente, o cuando dicha estructura era usada en uniones, estructuras +de estructuras, etc). + +C99 introdujo "los arrays miembros flexibles", los cuales carecen de un +tamaño numérico en su declaración del array:: + + struct something { + size_t count; + struct foo items[]; + }; + +Esta es la forma en la que el kernel espera que se declaren los elementos +de tamaño dinámico concatenados. Esto permite al compilador generar +errores, cuando el array flexible no es declarado en el último lugar de la +estructura, lo que ayuda a prevenir errores en él código del tipo +`comportamiento indefinido <https://git.kernel.org/linus/76497732932f15e7323dc805e8ea8dc11bb587cf>`_. +Esto también permite al compilador analizar correctamente los tamaños de +los arrays (via sizeof(), `CONFIG_FORTIFY_SOURCE`, y `CONFIG_UBSAN_BOUNDS`). +Por ejemplo, si no hay un mecanismo que avise que el siguiente uso de +sizeof() en un array de longitud cero, siempre resulta en cero:: + + struct something { + size_t count; + struct foo items[0]; + }; + + struct something *instance; + + instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL); + instance->count = count; + + size = sizeof(instance->items) * instance->count; + memcpy(instance->items, source, size); + +En la última línea del código anterior, ``zero`` vale ``cero``, cuando uno +podría esperar que representa el tamaño total en bytes de la memoria dinámica +reservada para el array consecutivo ``items``. Aquí hay un par de ejemplos +más sobre este tema: `link 1 +<https://git.kernel.org/linus/f2cd32a443da694ac4e28fbf4ac6f9d5cc63a539>`_, +`link 2 +<https://git.kernel.org/linus/ab91c2a89f86be2898cee208d492816ec238b2cf>`_. +Sin embargo, los array de miembros flexibles tienen un type incompleto, y +no se ha de aplicar el operador sizeof()<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_, +así cualquier mal uso de dichos operadores será detectado inmediatamente en +el momento de compilación. + +Con respecto a los arrays de un único elemento, se ha de ser consciente de +que dichos arrays ocupan al menos tanto espacio como un único objeto del +tipo https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_, de ahí que +estos contribuyan al tamaño de la estructura que los contiene. Esto es +proclive a errores cada vez que se quiere calcular el tamaño total de la +memoria dinámica para reservar una estructura que contenga un array de este +tipo como su miembro:: + + struct something { + size_t count; + struct foo items[1]; + }; + + struct something *instance; + + instance = kmalloc(struct_size(instance, items, count - 1), GFP_KERNEL); + instance->count = count; + + size = sizeof(instance->items) * instance->count; + memcpy(instance->items, source, size); + +En el ejemplo anterior, hemos de recordar calcular ``count - 1``, cuando se +usa la función de ayuda struct_size(), de otro modo estaríamos +--desintencionadamente--reservando memoria para un ``items`` de más. La +forma más clara y menos proclive a errores es implementar esto mediante el +uso de `array miembro flexible`, junto con las funciones de ayuda: +struct_size() y flex_array_size():: + + struct something { + size_t count; + struct foo items[]; + }; + + struct something *instance; + + instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL); + instance->count = count; + + memcpy(instance->items, source, flex_array_size(instance, items, instance->count)); |