1 .. include:: ../disclaimer-sp.rst 2 3 :Original: :ref:`Documentation/process/deprecated.rst <deprecated>` 4 :Translator: Sergio Gonzalez <sergio.collado@gmail.com> 5 6 .. _sp_deprecated: 7 8 ============================================================================ 9 Interfaces obsoletos, Características del lenguaje, Atributos y Convenciones 10 ============================================================================ 11 12 En un mundo perfecto, sería posible convertir todas las instancias de 13 alguna API obsoleta en una nueva API y quitar la API anterior en un 14 único ciclo de desarrollo. Desafortunadamente, debido al tamaño del kernel, 15 la jerarquía de mantenimiento, y el tiempo, no siempre es posible hacer 16 estos cambios de una única vez. Esto significa que las nuevas instancias 17 han de ir creándose en el kernel, mientras que las antiguas se quitan, 18 haciendo que la cantidad de trabajo para limpiar las APIs crezca. Para 19 informar a los desarrolladores sobre qué ha sido declarado obsoleto y por 20 qué, ha sido creada esta lista como un lugar donde indicar cuando los usos 21 obsoletos son propuestos para incluir en el kernel. 22 23 __deprecated 24 ------------ 25 Mientras que este atributo señala visualmente que un interface ha sido 26 declarado obsoleto, este `no produce más avisos durante las compilaciones 27 <https://git.kernel.org/linus/771c035372a036f83353eef46dbb829780330234>`_ 28 porque uno de los objetivos del kernel es que compile sin avisos, y 29 nadie ha hecho nada para quitar estos interfaces obsoletos. Mientras 30 que usar `__deprecated` es sencillo para anotar una API obsoleta en 31 un archivo de cabecera, no es la solución completa. Dichos interfaces 32 deben o bien ser quitados por completo, o añadidos a este archivo para 33 desanimar a otros a usarla en el futuro. 34 35 BUG() y BUG_ON() 36 ---------------- 37 Use WARN() y WARN_ON() en su lugar, y gestione las condiciones de error 38 "imposibles" tan elegantemente como se pueda. Mientras que la familia de 39 funciones BUG() fueron originalmente diseñadas para actuar como una 40 "situación imposible", confirmar y disponer de un hilo del kernel de forma 41 "segura", estas funciones han resultado ser demasiado arriesgadas. (e.g. 42 "¿en qué orden se necesitan liberar los locks? ¿Se han restaurado sus 43 estados?). La popular función BUG() desestabilizará el sistema o lo romperá 44 totalmente, lo cual hace imposible depurarlo o incluso generar reportes de 45 crash. Linus tiene una `opinión muy fuerte 46 <https://lore.kernel.org/lkml/CA+55aFy6jNLsywVYdGp83AMrXBo_P-pkjkphPGrO=82SPKCpLQ@mail.gmail.com/">https://lore.kernel.org/lkml/CA+55aFy6jNLsywVYdGp83AMrXBo_P-pkjkphPGrO=82SPKCpLQ@mail.gmail.com/>`_ 47 y sentimientos `sobre esto 48 <https://lore.kernel.org/lkml/CAHk-=whDHsbK3HTOpTF=ue_o04onRwTEaK_ZoJp_fjbqq4+=Jw@mail.gmail.com/">https://lore.kernel.org/lkml/CAHk-=whDHsbK3HTOpTF=ue_o04onRwTEaK_ZoJp_fjbqq4+=Jw@mail.gmail.com/>`_. 49 50 Nótese que la familia de funciones WARN() únicamente debería ser usada 51 en situaciones que se "esperan no sean alcanzables". Si se quiere 52 avisar sobre situaciones "alcanzables pero no deseadas", úsese la familia 53 de funciones pr_warn(). Los responsables del sistema pueden haber definido 54 *panic_on_warn* sysctl para asegurarse que sus sistemas no continúan 55 ejecutándose en presencia del condiciones "no alcanzables". (Por ejemplo, 56 véase commits como `este 57 <https://git.kernel.org/linus/d4689846881d160a4d12a514e991a740bcb5d65a>`_.) 58 59 Operaciones aritméticas en los argumentos de reserva de memoria 60 --------------------------------------------------------------- 61 Los cálculos dinámicos de tamaño (especialmente multiplicaciones) no 62 deberían realizarse en los argumentos de reserva de memoria (o similares) 63 debido al riesgo de desbordamiento. Esto puede llevar a valores rotando y 64 que se realicen reservas de memoria menores que las que se esperaban. El 65 uso de esas reservas puede llevar a desbordamientos en el 'heap' de memoria 66 y otros funcionamientos incorrectos. (Una excepción a esto son los valores 67 literales donde el compilador si puede avisar si estos puede desbordarse. 68 De todos modos, el método recomendado en estos caso es reescribir el código 69 como se sugiere a continuación para evitar las operaciones aritméticas en 70 la reserva de memoria.) 71 72 Por ejemplo, no utilice `count * size`` como argumento, como en:: 73 74 foo = kmalloc(count * size, GFP_KERNEL); 75 76 En vez de eso, utilice la reserva con dos argumentos:: 77 78 foo = kmalloc_array(count, size, GFP_KERNEL); 79 80 Específicamente, kmalloc() puede ser sustituido con kmalloc_array(), 81 kzalloc() puede ser sustituido con kcalloc(). 82 83 Si no existen funciones con dos argumentos, utilice las funciones que se 84 saturan, en caso de desbordamiento:: 85 86 bar = vmalloc(array_size(count, size)); 87 88 Otro caso común a evitar es calcular el tamaño de una estructura com 89 la suma de otras estructuras, como en:: 90 91 header = kzalloc(sizeof(*header) + count * sizeof(*header->item), 92 GFP_KERNEL); 93 94 En vez de eso emplee:: 95 96 header = kzalloc(struct_size(header, item, count), GFP_KERNEL); 97 98 .. note:: Si se usa struct_size() en una estructura que contiene un elemento 99 de longitud cero o un array de un único elemento como un array miembro, 100 por favor reescribir ese uso y cambiar a un `miembro array flexible 101 <#zero-length-and-one-element-arrays>`_ 102 103 104 Para otros cálculos, por favor use las funciones de ayuda: size_mul(), 105 size_add(), and size_sub(). Por ejemplo, en el caso de:: 106 107 foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL); 108 109 Re-escríbase, como:: 110 111 foo = krealloc(size_add(current_size, 112 size_mul(chunk_size, 113 size_sub(count, 3))), GFP_KERNEL); 114 115 Para más detalles, mire también array3_size() y flex_array_size(), 116 como también la familia de funciones relacionadas check_mul_overflow(), 117 check_add_overflow(), check_sub_overflow(), y check_shl_overflow(). 118 119 120 simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull() 121 ---------------------------------------------------------------------- 122 Las funciones: simple_strtol(), simple_strtoll(), simple_strtoul(), y 123 simple_strtoull() explícitamente ignoran los desbordamientos, lo que puede 124 llevar a resultados inesperados por las funciones que las llaman. Las 125 funciones respectivas kstrtol(), kstrtoll(), kstrtoul(), y kstrtoull() 126 tienden a ser reemplazos correctos, aunque nótese que necesitarán que la 127 cadena de caracteres termine en NUL o en el carácter de línea nueva. 128 129 130 strcpy() 131 -------- 132 strcpy() no realiza verificaciones de los límites del buffer de destino. 133 Esto puede resultar en desbordamientos lineals más allá del fin del buffer, 134 causando todo tipo de errores. Mientras `CONFIG_FORTIFY_SOURCE=y` otras 135 varias opciones de compilación reducen el riesgo de usar esta función, no 136 hay ninguna buena razón para añadir nuevos usos de esta. El remplazo seguro 137 es la función strscpy(), aunque se ha de tener cuidado con cualquier caso 138 en el el valor retornado por strcpy() sea usado, ya que strscpy() no 139 devuelve un puntero a el destino, sino el número de caracteres no nulos 140 compilados (o el valor negativo de errno cuando se trunca la cadena de 141 caracteres). 142 143 strncpy() en cadenas de caracteres terminadas en NUL 144 ---------------------------------------------------- 145 El uso de strncpy() no garantiza que el buffer de destino esté terminado en 146 NUL. Esto puede causar varios errores de desbordamiento en lectura y otros 147 tipos de funcionamiento erróneo debido a que falta la terminación en NUL. 148 Esta función también termina la cadena de caracteres en NUL en el buffer de 149 destino si la cadena de origen es más corta que el buffer de destino, lo 150 cual puede ser una penalización innecesaria para funciones usen esta 151 función con cadenas de caracteres que sí están terminadas en NUL. 152 153 Cuando se necesita que la cadena de destino sea terminada en NUL, 154 el mejor reemplazo es usar la función strscpy(), aunque se ha de tener 155 cuidado en los casos en los que el valor de strncpy() fuera usado, ya que 156 strscpy() no devuelve un puntero al destino, sino el número de 157 caracteres no nulos copiados (o el valor negativo de errno cuando se trunca 158 la cadena de caracteres). Cualquier caso restante que necesitase todavía 159 ser terminado en el caracter nulo, debería usar strscpy_pad(). 160 161 Si una función usa cadenas de caracteres que no necesitan terminar en NUL, 162 debería usarse strtomem(), y el destino debería señalarse con el atributo 163 `__nonstring 164 <https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html>`_ 165 para evitar avisos futuros en el compilador. Para casos que todavía 166 necesitan cadenas de caracteres que se rellenen al final con el 167 caracter NUL, usar strtomem_pad(). 168 169 strlcpy() 170 --------- 171 strlcpy() primero lee por completo el buffer de origen (ya que el valor 172 devuelto intenta ser el mismo que el de strlen()). Esta lectura puede 173 sobrepasar el límite de tamaño del destino. Esto ineficiente y puede causar 174 desbordamientos de lectura si la cadena de origen no está terminada en el 175 carácter NUL. El reemplazo seguro de esta función es strscpy(), pero se ha 176 de tener cuidado que en los casos en lso que se usase el valor devuelto de 177 strlcpy(), ya que strscpy() devolverá valores negativos de erno cuando se 178 produzcan truncados. 179 180 Especificación de formato %p 181 ---------------------------- 182 Tradicionalmente,el uso de "%p" en el formato de cadenas de caracteres 183 resultaría en exponer esas direcciones en dmesg, proc, sysfs, etc. En vez 184 de dejar que sean una vulnerabilidad, todos los "%p" que se usan en el 185 kernel se imprimen como un hash, haciéndolos efectivamente inutilizables 186 para usarlos como direcciones de memoria. Nuevos usos de "%p" no deberían 187 ser añadidos al kernel. Para textos de direcciones, usar "%pS" es 188 mejor, ya que resulta en el nombre del símbolo. Para prácticamente el 189 resto de casos, mejor no usar "%p" en absoluto. 190 191 Parafraseando las actuales `direcciones de Linus <https://lore.kernel.org/lkml/CA+55aFwQEd_d40g4mUCSsVRZzrFPUJt74vc6PPpb675hYNXcKw@mail.gmail.com/">https://lore.kernel.org/lkml/CA+55aFwQEd_d40g4mUCSsVRZzrFPUJt74vc6PPpb675hYNXcKw@mail.gmail.com/>`_: 192 193 - Si el valor "hasheado" "%p" no tienen ninguna finalidad, preguntarse si el 194 puntero es realmente importante. ¿Quizás se podría quitar totalmente? 195 - Si realmente se piensa que el valor del puntero es importante, ¿porqué 196 algún estado del sistema o nivel de privilegio de usuario es considerado 197 "especial"? Si piensa que puede justificarse (en comentarios y mensajes 198 del commit), de forma suficiente como para pasar el escrutinio de Linux, 199 quizás pueda usar el "%p", a la vez que se asegura que tiene los permisos 200 correspondientes. 201 202 Si está depurando algo donde el "%p" hasheado está causando problemas, 203 se puede arrancar temporalmente con la opción de depuración "`no_hash_pointers 204 <https://git.kernel.org/linus/5ead723a20e0447bc7db33dc3070b420e5f80aa6>`_". 205 206 207 Arrays de longitud variable (VLAs) 208 ---------------------------------- 209 Usando VLA en la pila (stack) produce un código mucho peor que los arrays 210 de tamaño estático. Mientras que estos errores no triviales de `rendimiento 211 <https://git.kernel.org/linus/02361bc77888>`_ son razón suficiente 212 para no usar VLAs, esto además son un riesgo de seguridad. El crecimiento 213 dinámico del array en la pila, puede exceder la memoria restante en 214 el segmento de la pila. Esto podría llevara a un fallo, posible sobre-escritura 215 de contenido al final de la pila (cuando se construye sin 216 `CONFIG_THREAD_INFO_IN_TASK=y`), o sobre-escritura de la memoria adyacente 217 a la pila (cuando se construye sin `CONFIG_VMAP_STACK=y`). 218 219 220 Switch case fall-through implícito 221 ---------------------------------- 222 El lenguaje C permite a las sentencias 'switch' saltar de un caso al 223 siguiente caso cuando la sentencia de ruptura "break" no aparece al final 224 del caso. Esto, introduce ambigüedad en el código, ya que no siempre está 225 claro si el 'break' que falta es intencionado o un olvido. Por ejemplo, no 226 es obvio solamente mirando al código si `STATE_ONE` está escrito para 227 intencionadamente saltar en `STATE_TWO`:: 228 229 switch (value) { 230 case STATE_ONE: 231 do_something(); 232 case STATE_TWO: 233 do_other(); 234 break; 235 default: 236 WARN("unknown state"); 237 } 238 239 Ya que ha habido una larga lista de defectos `debidos a declaraciones de "break" 240 que faltan <https://cwe.mitre.org/data/definitions/484.html>`_, no se 241 permiten 'fall-through' implícitos. Para identificar 'fall-through' 242 intencionados, se ha adoptado la pseudo-palabra-clave macro "falltrhrough", 243 que expande las extensiones de gcc `__attribute__((__fallthrough__)) 244 <https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html>`_. 245 (Cuando la sintaxis de C17/c18 `[[fallthrough]]` sea más comúnmente 246 soportadas por los compiladores de C, analizadores estáticos, e IDEs, 247 se puede cambiar a usar esa sintaxis para esa pseudo-palabra-clave. 248 249 Todos los bloques switch/case deben acabar en uno de: 250 251 * break; 252 * fallthrough; 253 * continue; 254 * goto <label>; 255 * return [expression]; 256 257 258 Arrays de longitud cero y un elemento 259 ------------------------------------- 260 Hay una necesidad habitual en el kernel de proveer una forma para declarar 261 un grupo de elementos consecutivos de tamaño dinámico en una estructura. 262 El código del kernel debería usar siempre `"miembros array flexible" <https://en.wikipedia.org/wiki/Flexible_array_member>`_ 263 en estos casos. El estilo anterior de arrays de un elemento o de longitud 264 cero, no deben usarse más. 265 266 En el código C más antiguo, los elementos finales de tamaño dinámico se 267 obtenían especificando un array de un elemento al final de una estructura:: 268 269 struct something { 270 size_t count; 271 struct foo items[1]; 272 }; 273 274 En código C más antiguo, elementos seguidos de tamaño dinámico eran creados 275 especificando una array de un único elemento al final de una estructura:: 276 277 struct something { 278 size_t count; 279 struct foo items[1]; 280 }; 281 282 Esto llevó a resultados incorrectos en los cálculos de tamaño mediante 283 sizeof() (el cual hubiera necesitado eliminar el tamaño del último elemento 284 para tener un tamaño correcto de la "cabecera"). Una `extensión de GNU C 285 <https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_ se empezó a usar 286 para permitir los arrays de longitud cero, para evitar estos tipos de 287 problemas de tamaño:: 288 289 struct something { 290 size_t count; 291 struct foo items[0]; 292 }; 293 294 Pero esto llevó a otros problemas, y no solucionó algunos otros problemas 295 compartidos por ambos estilos, como no ser capaz de detectar cuando ese array 296 accidentalmente _no_ es usado al final de la estructura (lo que podía pasar 297 directamente, o cuando dicha estructura era usada en uniones, estructuras 298 de estructuras, etc). 299 300 C99 introdujo "los arrays miembros flexibles", los cuales carecen de un 301 tamaño numérico en su declaración del array:: 302 303 struct something { 304 size_t count; 305 struct foo items[]; 306 }; 307 308 Esta es la forma en la que el kernel espera que se declaren los elementos 309 de tamaño dinámico concatenados. Esto permite al compilador generar 310 errores, cuando el array flexible no es declarado en el último lugar de la 311 estructura, lo que ayuda a prevenir errores en él código del tipo 312 `comportamiento indefinido <https://git.kernel.org/linus/76497732932f15e7323dc805e8ea8dc11bb587cf>`_. 313 Esto también permite al compilador analizar correctamente los tamaños de 314 los arrays (via sizeof(), `CONFIG_FORTIFY_SOURCE`, y `CONFIG_UBSAN_BOUNDS`). 315 Por ejemplo, si no hay un mecanismo que avise que el siguiente uso de 316 sizeof() en un array de longitud cero, siempre resulta en cero:: 317 318 struct something { 319 size_t count; 320 struct foo items[0]; 321 }; 322 323 struct something *instance; 324 325 instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL); 326 instance->count = count; 327 328 size = sizeof(instance->items) * instance->count; 329 memcpy(instance->items, source, size); 330 331 En la última línea del código anterior, ``zero`` vale ``cero``, cuando uno 332 podría esperar que representa el tamaño total en bytes de la memoria dinámica 333 reservada para el array consecutivo ``items``. Aquí hay un par de ejemplos 334 más sobre este tema: `link 1 335 <https://git.kernel.org/linus/f2cd32a443da694ac4e28fbf4ac6f9d5cc63a539>`_, 336 `link 2 337 <https://git.kernel.org/linus/ab91c2a89f86be2898cee208d492816ec238b2cf>`_. 338 Sin embargo, los array de miembros flexibles tienen un type incompleto, y 339 no se ha de aplicar el operador sizeof()<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_, 340 así cualquier mal uso de dichos operadores será detectado inmediatamente en 341 el momento de compilación. 342 343 Con respecto a los arrays de un único elemento, se ha de ser consciente de 344 que dichos arrays ocupan al menos tanto espacio como un único objeto del 345 tipo https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_, de ahí que 346 estos contribuyan al tamaño de la estructura que los contiene. Esto es 347 proclive a errores cada vez que se quiere calcular el tamaño total de la 348 memoria dinámica para reservar una estructura que contenga un array de este 349 tipo como su miembro:: 350 351 struct something { 352 size_t count; 353 struct foo items[1]; 354 }; 355 356 struct something *instance; 357 358 instance = kmalloc(struct_size(instance, items, count - 1), GFP_KERNEL); 359 instance->count = count; 360 361 size = sizeof(instance->items) * instance->count; 362 memcpy(instance->items, source, size); 363 364 En el ejemplo anterior, hemos de recordar calcular ``count - 1``, cuando se 365 usa la función de ayuda struct_size(), de otro modo estaríamos 366 --desintencionadamente--reservando memoria para un ``items`` de más. La 367 forma más clara y menos proclive a errores es implementar esto mediante el 368 uso de `array miembro flexible`, junto con las funciones de ayuda: 369 struct_size() y flex_array_size():: 370 371 struct something { 372 size_t count; 373 struct foo items[]; 374 }; 375 376 struct something *instance; 377 378 instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL); 379 instance->count = count; 380 381 memcpy(instance->items, source, flex_array_size(instance, items, instance->count));
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.