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