1.. SPDX-License-Identifier: GPL-2.0 2 3======================================================================== 4Interfaces, recursos de linguagem, atributos e convenções obsoletos 5======================================================================== 6 7Em um mundo perfeito, seria possível converter todas as instâncias de alguma 8API obsoleta para a nova API e remover completamente a API antiga em um único 9ciclo de desenvolvimento. No entanto, devido ao tamanho do kernel, à hierarquia 10de manutenção e ao cronograma, nem sempre é viável realizar esse tipo de 11conversão de uma só vez. Isso significa que novas instâncias podem acabar 12entrando no kernel enquanto as antigas estão sendo removidas, apenas aumentando 13o volume de trabalho para remover a API. A fim de instruir os desenvolvedores 14sobre o que se tornou obsoleto e o porquê, esta lista foi criada para servir de 15referência quando o uso de elementos obsoletos for proposto para inclusão no 16kernel. 17 18__deprecated 19------------ 20Embora este atributo marque visualmente uma interface como obsoleta, ele `não 21gera mais avisos durante as compilações 22<https://git.kernel.org/linus/771c035372a036f83353eef46dbb829780330234>`_ porque 23um dos objetivos permanentes do kernel é compilar sem avisos (*warnings*), e 24ninguém estava de fato agindo para remover essas interfaces obsoletas. Embora o 25uso de `__deprecated` seja útil para sinalizar uma API antiga em um arquivo de 26cabeçalho (*header file*), não é a solução completa. Tais interfaces devem ser 27totalmente removidas do kernel ou adicionadas a este arquivo para desestimular 28outros desenvolvedores de usá-las no futuro. 29 30BBUG() e BUG_ON() 31----------------- 32Em vez disso, use WARN() e WARN_ON() e trate a condição de erro "impossível" 33da forma mais amigável possível. Embora a família de APIs BUG() tenha sido 34originalmente projetada para agir como uma asserção de "situação impossível" e 35eliminar uma thread do kernel de forma "segura", ela se mostrou arriscada 36demais. (Por exemplo: "Em que ordem os bloqueios precisam ser liberados? Os 37diversos estados foram restaurados?") Muito frequentemente, o uso de BUG() vai 38desestabilizar o sistema ou travá-lo por completo, o que torna impossível 39depurar ou até mesmo obter relatórios de travamento (*crash reports*) viáveis. 40Linus tem opiniões `muito fortes 41<https://lore.kernel.org/lkml/CA+55aFy6jNLsywVYdGp83AMrXBo_P-pkjkphPGrO=82SPKCpLQ@mail.gmail.com/>`_ 42`sobre isso 43<https://lore.kernel.org/lkml/CAHk-=whDHsbK3HTOpTF=ue_o04onRwTEaK_ZoJp_fjbqq4+=Jw@mail.gmail.com/>`_. 44 45Note que a família WARN() só deve ser usada para situações que "espera-se que 46sejam inacessíveis". Se você quiser alertar sobre situações que são 47"acessíveis, mas indesejáveis", use a família de funções pr_warn(). Os 48administradores do sistema podem ter configurado o sysctl *panic_on_warn* para 49garantir que seus sistemas não continuem executando diante de condições 50"inacessíveis". (Para exemplos, veja commits como `este aqui 51<https://git.kernel.org/linus/d4689846881d160a4d12a514e991a740bcb5d65a>`_.) 52 53Aritmética explícita em argumentos do alocador 54---------------------------------------------- 55Cálculos dinâmicos de tamanho (especialmente multiplicação) não devem ser 56realizados em argumentos de funções de alocação de memória (ou similares) 57devido ao risco de estouro de capacidade (*overflow*). Isso poderia fazer com 58que os valores dessem a volta (*wrap around*), resultando em uma alocação menor 59do que o esperado pelo chamador. O uso dessas alocações pode levar a estouros 60lineares na memória heap e a outros comportamentos incorretos. (Uma exceção a 61isso são valores literais onde o compilador pode emitir um aviso se houver 62risco de estouro. No entanto, a maneira preferível nesses casos é refatorar o 63código conforme sugerido abaixo para evitar a aritmética explícita.) 64 65Por exemplo, não use ``count * size`` como argumento, como em:: 66 67 foo = kmalloc(count * size, GFP_KERNEL); 68 69Em vez disso, a forma de dois fatores do alocador deve ser utilizada:: 70 71 foo = kmalloc_array(count, size, GFP_KERNEL); 72 73Especificamente, kmalloc() pode ser substituído por kmalloc_array(), e 74kzalloc() pode ser substituído por kcalloc(). 75 76Se nenhuma forma de dois fatores estiver disponível, os auxiliares de 77saturação em estouro (*saturate-on-overflow*) devem ser usados:: 78 79 bar = dma_alloc_coherent(dev, array_size(count, size), &dma, GFP_KERNEL); 80 81Outro caso comum a ser evitado é calcular o tamanho de uma estrutura com uma 82matriz final de outras estruturas, como em:: 83 84 header = kzalloc(sizeof(*header) + count * sizeof(*header->item), 85 GFP_KERNEL); 86 87Em vez disso, use o auxiliar:: 88 89 header = kzalloc(struct_size(header, item, count), GFP_KERNEL); 90 91.. note:: Se você estiver usando struct_size() em uma estrutura que contém uma 92 matriz de comprimento zero ou de um único elemento como membro final, 93 refatore o uso dessa matriz e mude para um `membro de matriz flexível 94 <#zero-length-and-one-element-arrays>`_ em seu lugar. 95 96Para outros cálculos, faça a composição usando os auxiliares size_mul(), 97size_add() e size_sub(). Por exemplo, no caso de:: 98 99 foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL); 100 101Em vez disso, use os auxiliares:: 102 103 foo = krealloc(size_add(current_size, 104 size_mul(chunk_size, 105 size_sub(count, 3))), GFP_KERNEL); 106 107Para mais detalhes, veja também array3_size() e flex_array_size(), bem como as 108funções relacionadas das famílias check_mul_overflow(), check_add_overflow(), 109check_sub_overflow() e check_shl_overflow().\ 110 111simple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull() 112---------------------------------------------------------------------- 113As funções simple_strtol(), simple_strtoll(), simple_strtoul() e 114simple_strtoull() ignoram explicitamente estouros de capacidade (*overflows*), 115o que pode levar a resultados inesperados nos chamadores. As respectivas 116funções kstrtol(), kstrtoll(), kstrtoul() e kstrtoull() tendem a ser as 117substitutas corretas, embora se deva notar que estas exigem que a string seja 118terminada em NUL ou em nova linha (*newline*). 119 120strcpy() 121-------- 122A função strcpy() não realiza verificação de limites no buffer de destino. 123Isso pode resultar em estouros lineares além do final do buffer, levando a todo 124tipo de comportamentos incorretos. Embora ``CONFIG_FORTIFY_SOURCE=y`` e várias 125opções do compilador ajudem a reduzir o risco de usar esta função, não há uma 126boa razão para adicionar novos usos dela. A substituta segura é strscpy(), 127embora se deva ter cuidado nos casos em que o valor de retorno de strcpy() era 128utilizado, já que strscpy() não retorna um ponteiro para o destino, mas sim a 129quantidade de bytes não-NUL copiados (ou um código de erro errno negativo quando 130ocorre truncamento). 131 132strncpy() 133--------- 134A função strncpy() foi removida do kernel. Todos os chamadores antigos foram 135migrados para alternativas mais seguras. 136 137A função strncpy() não garantia a terminação em NUL do buffer de destino, 138levando a estouros de leitura linear e outros comportamentos incorretos. Ela 139também preenchia incondicionalmente o destino com NUL, o que representava uma 140penalidade de desempenho desnecessária para chamadores que usavam apenas 141strings terminadas em NUL. Devido aos seus diversos comportamentos, ela era uma 142API ambígua para determinar qual era a real intenção do autor ao realizar a 143cópia. 144 145As substitutas para strncpy() são: 146 147- strscpy() quando o destino deve ser terminado em NUL. 148- strscpy_pad() quando o destino deve ser terminado em NUL e preenchido com 149 zeros (por exemplo, estruturas que cruzam fronteiras de privilégio). 150- memtostr() para destinos terminados em NUL a partir de origens de largura 151 fixa não terminadas em NUL (com o atributo ``__nonstring`` na origem). 152- memtostr_pad() para o mesmo caso anterior, mas com preenchimento de zeros. 153- strtomem() para destinos de largura fixa não terminados em NUL, com o 154 atributo ``__nonstring`` no destino. 155- strtomem_pad() para destinos não terminados em NUL que também precisam de 156 preenchimento com zeros. 157- memcpy_and_pad() para cópias limitadas a partir de origens potencialmente não 158 terminadas, onde o tamanho do destino é um valor definido em tempo de 159 execução (*runtime*). 160 161strlcpy() 162--------- 163A função strlcpy() lê primeiro todo o buffer de origem (já que o valor de 164retorno deve corresponder ao de strlen()). Essa leitura pode exceder o limite 165de tamanho do destino. Isso é ineficiente e pode levar a estouros de leitura 166linear se a string de origem não for terminada em NUL. A substituta segura é 167strscpy(), embora se deva ter cuidado nos casos em que o valor de retorno de 168strlcpy() é utilizado, já que strscpy() retornará valores negativos de errno 169quando houver truncamento. 170 171Especificador de formato %p 172---------------------------- 173Tradicionalmente, o uso de "%p" em strings de formatação causava falhas de 174exposição de endereços reais no dmesg, proc, sysfs, etc. Em vez de deixar esses 175endereços expostos a explorações, todos os usos de "%p" no kernel agora são 176exibidos como um valor hash, tornando-os inúteis para fins de endereçamento. 177Novos usos de "%p" não devem ser adicionados ao kernel. Para endereços de texto, 178usar "%pS" costuma ser melhor, pois exibe o nome do símbolo, que é muito mais 179útil. Para quase todo o restante, simplesmente não adicione "%p" de forma 180alguma. 181 182Parafraseando as diretrizes atuais do Linus `guidance 183<https://lore.kernel.org/lkml/CA+55aFwQEd_d40g4mUCSsVRZzrFPUJt74vc6PPpb675hYNXcKw@mail.gmail.com/>`_: 184 185- Se o valor hash de "%p" é inútil, pergunte a si mesmo se o ponteiro em si é 186 importante. Talvez ele deva ser removido por completo? 187- Se você realmente acredita que o valor real do ponteiro é importante, por que 188 algum estado do sistema ou nível de privilégio do usuário seria considerado 189 "especial"? Se você acha que pode justificar isso (em comentários e no log de 190 commit) de forma sólida o suficiente para resistir ao escrutínio do Linus, 191 talvez possa usar "%px", certificando-se de aplicar permissões adequadas. 192 193Se você estiver depurando algo em que a geração de hash de "%p" esteja causando 194problemas, é possível inicializar o sistema temporariamente com a opção de 195depuração "`no_hash_pointers 196<https://git.kernel.org/linus/5ead723a20e0447bc7db33dc3070b420e5f80aa6>`_". 197 198Matrizes de Tamanho Variável (VLAs) 199----------------------------------- 200O uso de VLAs (Variable Length Arrays) na pilha de execução gera um código de 201máquina muito pior do que matrizes de tamanho estático na pilha. Embora esses 202problemas significativos de `desempenho 203<https://git.kernel.org/linus/02361bc77888>`_ sejam motivo suficiente para 204eliminar as VLAs, elas também representam um risco de segurança. O crescimento 205dinâmico de uma matriz na pilha pode exceder a memória restante no segmento da 206pilha. Isso pode levar a um travamento, à possível sobrescrita de dados 207sensíveis no final da pilha (quando compilado sem ``CONFIG_THREAD_INFO_IN_TASK=y``) 208ou à sobrescrita de posições de memória adjacentes à pilha (quando compilado sem 209``CONFIG_VMAP_STACK=y``). 210 211Passagem direta implícita no switch case (fall-through) 212------------------------------------------------------- 213A linguagem C permite que o fluxo de execução de um bloco switch passe 214diretamente para o próximo caso (fall-through) quando uma instrução "break" 215está ausente ao final de um caso. No entanto, isso introduz ambiguidade no 216código, pois nem sempre fica claro se o "break" ausente é intencional ou um bug. 217Por exemplo, não é óbvio apenas olhando para o código se o ``STATE_ONE`` foi 218intencionalmente projetado para passar diretamente para o ``STATE_TWO``:: 219 220 switch (value) { 221 case STATE_ONE: 222 do_something(); 223 case STATE_TWO: 224 do_other(); 225 break; 226 default: 227 WARN("unknown state"); 228 } 229 230Como há uma longa lista de falhas `causadas pela ausência de instruções "break" 231<https://cwe.mitre.org/data/definitions/484.html>`_, não permitimos mais a 232passagem direta implícita. Para identificar os casos de passagem direta 233intencionais, adotamos a macro pseudo-palavra-chave "fallthrough", que se 234expande para a extensão do gcc `__attribute__((__fallthrough__)) 235<https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html>`_. (Quando a 236sintaxe ``[[fallthrough]]`` do C17/C18 for suportada de forma mais ampla por 237compiladores C, analisadores estáticos e IDEs, poderemos mudar para o uso dessa 238sintaxe para a pseudo-palavra-chave da macro.) 239 240Todos os blocos de switch/case devem terminar com um dos seguintes elementos: 241 242* break; 243* fallthrough; 244* continue; 245* goto <rótulo>; 246* return [expressão]; 247 248Matrizes de comprimento zero e de um único elemento 249---------------------------------------------------- 250Há uma necessidade frequente no kernel de fornecer uma maneira de declarar uma 251estrutura com um conjunto de elementos finais de tamanho dinâmico. O código do 252kernel deve sempre usar `"membros de matriz flexível" 253<https://en.wikipedia.org/wiki/Flexible_array_member>`_ para esses casos. O 254estilo antigo de matrizes de um único elemento ou de comprimento zero não deve 255mais ser utilizado. 256 257No código C mais antigo, elementos finais de tamanho dinâmico eram declarados 258especificando uma matriz de um elemento ao final de uma estrutura:: 259 260 struct something { 261 size_t count; 262 struct foo items[1]; 263 }; 264 265Isso levava a cálculos de tamanho frágeis via sizeof() (que exigiam a subtração 266do tamanho do elemento final único para obter o tamanho correto do "cabeçalho"). 267Uma `extensão GNU C <https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_ foi 268introduzida para permitir matrizes de comprimento zero, a fim de evitar esses 269problemas de cálculo de tamanho:: 270 271 struct something { 272 size_t count; 273 struct foo items[0]; 274 }; 275 276No entanto, isso trouxe outros problemas e não resolveu algumas limitações de 277ambos os estilos, como a incapacidade de detectar quando tal matriz é usada 278acidentalmente *fora* do final de uma estrutura (o que poderia ocorrer 279diretamente, ou quando tal estrutura estava contida em unions, estruturas de 280estruturas, etc.). 281 282O padrão C99 introduziu os "membros de matriz flexível", nos quais a declaração 283da matriz simplesmente não possui um tamanho numérico:: 284 285 struct something { 286 size_t count; 287 struct foo items[]; 288 }; 289 290Esta é a maneira como o kernel espera que elementos finais de tamanho dinâmico 291sejam declarados. Isso permite que o compilador gere erros quando a matriz 292flexível não for o último elemento da estrutura, o que ajuda a evitar que bugs 293de `comportamento indefinido 294<https://git.kernel.org/linus/76497732932f15e7323dc805e8ea8dc11bb587cf>`_ sejam 295introduzidos inadvertidamente na base de código. Também permite que o 296compilador analise corretamente os tamanhos das matrizes (via sizeof(), 297``CONFIG_FORTIFY_SOURCE`` e ``CONFIG_UBSAN_BOUNDS``). Por exemplo, não existe um 298mecanismo que nos alerte de que a seguinte aplicação do operador sizeof() a uma 299matriz de comprimento zero sempre resulta em zero:: 300 301 struct something { 302 size_t count; 303 struct foo items[0]; 304 }; 305 306 struct something *instance; 307 308 instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL); 309 instance->count = count; 310 311 size = sizeof(instance->items) * instance->count; 312 memcpy(instance->items, source, size); 313 314Na última linha do código acima, ``size`` acaba sendo ``zero``, quando se 315poderia pensar que ele representaria o tamanho total em bytes da memória 316dinâmica recentemente alocada para a matriz final ``items``. Aqui estão alguns 317exemplos deste problema: `link 1 318<https://git.kernel.org/linus/f2cd32a443da694ac4e28fbf4ac6f9d5cc63a539>`_, 319`link 2 320<https://git.kernel.org/linus/ab91c2a89f86be2898cee208d492816ec238b2cf>`_. 321Em vez disso, `membros de matriz flexível têm tipo incompleto e, portanto, o 322operador sizeof() não pode ser aplicado 323<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_, de modo que qualquer 324uso incorreto de tais operadores será imediatamente percebido em tempo de 325compilação. 326 327Em relação às matrizes de um único elemento, é preciso estar muito ciente de que 328`tais matrizes ocupam pelo menos o mesmo espaço que um único objeto daquele tipo 329<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_ e, portanto, contribuem 330para o tamanho da estrutura que as contém. Isso é propício a erros sempre que se 331deseja calcular o tamanho total da memória dinâmica a ser alocada para uma 332estrutura que contém uma matriz desse tipo como membro:: 333 334 struct something { 335 size_t count; 336 struct foo items[1]; 337 }; 338 339 struct something *instance; 340 341 instance = kmalloc(struct_size(instance, items, count - 1), GFP_KERNEL); 342 instance->count = count; 343 344 size = sizeof(instance->items) * instance->count; 345 memcpy(instance->items, source, size); 346 347No exemplo acima, foi necessário lembrar de calcular ``count - 1`` ao usar o 348auxiliar struct_size(); caso contrário, teríamos alocado memória --de forma não 349intencional-- para um objeto ``items`` a mais. A maneira mais limpa e menos 350sujeita a erros de implementar isso é através do uso de um `membro de matriz 351flexível`, em conjunto com os auxiliares struct_size() e flex_array_size():: 352 353 struct something { 354 size_t count; 355 struct foo items[]; 356 }; 357 358 struct something *instance; 359 360 instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL); 361 instance->count = count; 362 363 memcpy(instance->items, source, flex_array_size(instance, items, instance->count)); 364 365Existem dois casos especiais de substituição nos quais o auxiliar 366DECLARE_FLEX_ARRAY() precisa ser utilizado. (Note que ele é nomeado 367__DECLARE_FLEX_ARRAY() para uso em cabeçalhos de UAPI.) Esses casos ocorrem 368quando a matriz flexível está sozinha em uma estrutura ou faz parte de uma 369union. Isso não é permitido pela especificação C99, mas sem justificativa 370técnica (como pode ser visto tanto pelo uso existente de tais matrizes nesses 371locais quanto pela solução alternativa que DECLARE_FLEX_ARRAY() adota). Por 372exemplo, para converter isto:: 373 374 struct something { 375 ... 376 union { 377 struct type1 one[0]; 378 struct type2 two[0]; 379 }; 380 }; 381 382O auxiliar deve ser utilizado:: 383 384 struct something { 385 ... 386 union { 387 DECLARE_FLEX_ARRAY(struct type1, one); 388 DECLARE_FLEX_ARRAY(struct type2, two); 389 }; 390 }; 391 392Atribuições diretas de kmalloc para objetos struct 393-------------------------------------------------- 394Realizar atribuições diretas (*open-coded*) de alocações da família kmalloc() 395impede que o kernel (e o compilador) consigam examinar o tipo da variável que 396está recebendo a atribuição, o que limita qualquer introspecção relacionada que 397possa ajudar com alinhamento, estouros de capacidade (*wrap-around*) ou 398proteções adicionais (*hardening*). A família de macros kmalloc_obj() fornece 399essa introspecção, que pode ser usada para os padrões de código comuns de 400alocações de objetos únicos, de matrizes ou de objetos flexíveis. Por exemplo, 401estas atribuições diretas:: 402 403 ptr = kmalloc(sizeof(*ptr), gfp); 404 ptr = kzalloc(sizeof(*ptr), gfp); 405 ptr = kmalloc_array(count, sizeof(*ptr), gfp); 406 ptr = kcalloc(count, sizeof(*ptr), gfp); 407 ptr = kmalloc(struct_size(ptr, flex_member, count), gfp); 408 ptr = kmalloc(sizeof(struct foo), gfp); 409 410tornam-se, respectivamente:: 411 412 ptr = kmalloc_obj(*ptr [, gfp] ); 413 ptr = kzalloc_obj(*ptr [, gfp] ); 414 ptr = kmalloc_objs(*ptr, count [, gfp] ); 415 ptr = kzalloc_objs(*ptr, count [, gfp] ); 416 ptr = kmalloc_flex(*ptr, flex_member, count [, gfp] ); 417 __auto_type ptr = kmalloc_obj(struct foo [, gfp] ); 418 419O argumento gfp é opcional, sendo o valor padrão GFP_KERNEL. Se 420``ptr->flex_member`` estiver anotado com __counted_by(), a alocação falhará 421automaticamente caso ``count`` seja maior do que o valor máximo representável 422que pode ser armazenado no membro contador associado a ``flex_member``. 423