115317Swosch.. SPDX-License-Identifier: GPL-2.0
215317Swosch
315317Swosch.. include:: ../disclaimer-ita.rst
415317Swosch
515317Swosch:Original: :ref:`Documentation/process/deprecated.rst <deprecated>`
615317Swosch:Translator: Federico Vaga <federico.vaga@vaga.pv.it>
715317Swosch
815317Swosch.. _it_deprecated:
915317Swosch
1015317Swosch==============================================================================
1115317SwoschInterfacce deprecate, caratteristiche del linguaggio, attributi, e convenzioni
1215317Swosch==============================================================================
1315317Swosch
1415317SwoschIn un mondo perfetto, sarebbe possibile prendere tutti gli usi di
1515317Swoschun'interfaccia deprecata e convertirli in quella nuova, e cos�� sarebbe
1615317Swoschpossibile rimuovere la vecchia interfaccia in un singolo ciclo di sviluppo.
1715317SwoschTuttavia, per via delle dimensioni del kernel, la gerarchia dei manutentori e
1815317Swoschle tempistiche, non �� sempre possibile fare questo tipo di conversione tutta
1915317Swoschin una volta. Questo significa che nuove istanze di una vecchia interfaccia
2015317Swoschpotrebbero aggiungersi al kernel proprio quando si sta cercando di rimuoverle,
2115317Swoschaumentando cos�� il carico di lavoro. Al fine di istruire gli sviluppatori su
2215317Swoschcosa �� considerato deprecato (e perch��), �� stata create la seguente lista a cui
2315317Swoschfare riferimento quando qualcuno propone modifiche che usano cose deprecate.
2450476Speter
2515317Swosch__deprecated
2615317Swosch------------
2715317SwoschNonostante questo attributo marchi visibilmente un interfaccia come deprecata,
2815317Swosch`non produce pi�� alcun avviso durante la compilazione
29146661Seivind<https://git.kernel.org/linus/771c035372a036f83353eef46dbb829780330234>`_
3015317Swoschperch�� uno degli obiettivi del kernel �� quello di compilare senza avvisi;
31146661Seivindinoltre, nessuno stava agendo per rimuovere queste interfacce. Nonostante l'uso
32146661Seivinddi `__deprecated` in un file d'intestazione sia opportuno per segnare una
33146661Seivindinterfaccia come 'vecchia', questa non �� una soluzione completa. L'interfaccia
34146661Seivinddeve essere rimossa dal kernel, o aggiunta a questo documento per scoraggiarne
35146661Seivindl'uso.
36146661Seivind
3715317SwoschBUG() e BUG_ON()
3815317Swosch----------------
3915317SwoschAl loro posto usate WARN() e WARN_ON() per gestire le
4069341Srucondizioni "impossibili" e gestitele come se fosse possibile farlo.
4167662SnikNonostante le funzioni della famiglia BUG() siano state progettate
4267662Snikper asserire "situazioni impossibili" e interrompere in sicurezza un
4367662Snikthread del kernel, queste si sono rivelate essere troppo rischiose
4467662Snik(per esempio, in quale ordine rilasciare i *lock*? Ci sono stati che
4515317Swoschsono stati ripristinati?). Molto spesso l'uso di BUG()
4615317Swoschdestabilizza il sistema o lo corrompe del tutto, il che rende
4715317Swoschimpossibile un'attivit�� di debug o anche solo leggere un rapporto
4815317Swoschcirca l'errore.  Linus ha un'opinione molto critica al riguardo:
4915317Swosch`email 1
5067662Snik<https://lore.kernel.org/lkml/CA+55aFy6jNLsywVYdGp83AMrXBo_P-pkjkphPGrO=82SPKCpLQ@mail.gmail.com/>`_,
5115317Swosch`email 2
5215317Swosch<https://lore.kernel.org/lkml/CAHk-=whDHsbK3HTOpTF=ue_o04onRwTEaK_ZoJp_fjbqq4+=Jw@mail.gmail.com/>`_
5367662Snik
5415317SwoschTenete presente che la famiglia di funzioni WARN() dovrebbe essere
5567662Snikusato solo per situazioni che si suppone siano "impossibili".  Se
5615317Swoschvolete avvisare gli utenti riguardo a qualcosa di possibile anche se
5715317Swoschindesiderato, usare le funzioni della famiglia pr_warn().  Chi
5867662Snikamministra il sistema potrebbe aver attivato l'opzione sysctl
5915317Swosch*panic_on_warn* per essere sicuri che il sistema smetta di funzionare
6015317Swoschin caso si verifichino delle condizioni "inaspettate". (per esempio,
6167662Snikdate un'occhiata al questo `commit
6267662Snik<https://git.kernel.org/linus/d4689846881d160a4d12a514e991a740bcb5d65a>`_)
6367662Snik
6467662SnikCalcoli codificati negli argomenti di un allocatore
6515317Swosch----------------------------------------------------
6615317SwoschIl calcolo dinamico delle dimensioni (specialmente le moltiplicazioni) non
6715317Swoschdovrebbero essere fatto negli argomenti di funzioni di allocazione di memoria
6867662Snik(o simili) per via del rischio di overflow. Questo pu�� portare a valori pi��
6915317Swoschpiccoli di quelli che il chiamante si aspettava. L'uso di questo modo di
7067662Snikallocare pu�� portare ad un overflow della memoria di heap e altri
7115317Swoschmalfunzionamenti. (Si fa eccezione per valori numerici per i quali il
7215317Swoschcompilatore pu�� generare avvisi circa un potenziale overflow. Tuttavia, anche in
7367662Snikquesti casi �� preferibile riscrivere il codice come suggerito di seguito).
7415317Swosch
7515317SwoschPer esempio, non usate ``count * size`` come argomento::
7667662Snik
7767662Snik	foo = kmalloc(count * size, GFP_KERNEL);
7867662Snik
7967662SnikAl suo posto, si dovrebbe usare l'allocatore a due argomenti::
8015317Swosch
8115317Swosch	foo = kmalloc_array(count, size, GFP_KERNEL);
8267662Snik
8315317SwoschNello specifico, kmalloc() pu�� essere sostituta da kmalloc_array(), e kzalloc()
8467662Snikda kcalloc().
8515317Swosch
8615317SwoschSe questo tipo di allocatore non �� disponibile, allora dovrebbero essere usate
8767662Snikle funzioni del tipo *saturate-on-overflow*::
8815317Swosch
8915317Swosch	bar = dma_alloc_coherent(dev, array_size(count, size), &dma, GFP_KERNEL);
9067662Snik
9167662SnikUn altro tipico caso da evitare �� quello di calcolare la dimensione di una
9267662Snikstruttura seguita da un vettore di altre strutture, come nel seguente caso::
9367662Snik
9415317Swosch	header = kzalloc(sizeof(*header) + count * sizeof(*header->item),
9515317Swosch			 GFP_KERNEL);
9667662Snik
9715317SwoschInvece, usate la seguente funzione::
9867662Snik
9915317Swosch	header = kzalloc(struct_size(header, item, count), GFP_KERNEL);
10015317Swosch
10167662Snik.. note:: Se per caso state usando struct_size() su una struttura dati che
10215317Swosch	  in coda contiene un array di lunghezza zero o uno, allora siete
10315317Swosch	  invitati a riorganizzare il vostro codice usando il
10467662Snik	  `flexible array member <#zero-length-and-one-element-arrays>`_.
10567662Snik
10667662SnikPer altri calcoli, usate le funzioni size_mul(), size_add(), e size_sub(). Per
10767662Snikesempio, al posto di::
10815317Swosch
10915317Swosch       foo = krealloc(current_size + chunk_size * (count - 3), GFP_KERNEL);
11067662Snik
11115317Swoschdovreste scrivere:
11267662Snik
11315317Swosch       foo = krealloc(size_add(current_size,
11415317Swosch                               size_mul(chunk_size,
11515317Swosch                                        size_sub(count, 3))), GFP_KERNEL);
11615317Swosch
11767662SnikPer maggiori dettagli fate riferimento a array3_size() e flex_array_size(), ma
11815317Swoschanche le funzioni della famiglia check_mul_overflow(), check_add_overflow(),
11915317Swoschcheck_sub_overflow(), e check_shl_overflow().
12067662Snik
12167662Sniksimple_strtol(), simple_strtoll(), simple_strtoul(), simple_strtoull()
12267662Snik----------------------------------------------------------------------
12367662SnikLe funzioni simple_strtol(), simple_strtoll(),
12415317Swoschsimple_strtoul(), e simple_strtoull() ignorano volutamente
12515317Swoschi possibili overflow, e questo pu�� portare il chiamante a generare risultati
12667662Snikinaspettati. Le rispettive funzioni kstrtol(), kstrtoll(),
12715317Swoschkstrtoul(), e kstrtoull() sono da considerarsi le corrette
12867662Sniksostitute; tuttavia va notato che queste richiedono che la stringa sia
12915317Swoschterminata con il carattere NUL o quello di nuova riga.
13015317Swosch
13167662Snikstrcpy()
13215317Swosch--------
13315317SwoschLa funzione strcpy() non fa controlli agli estremi del buffer
13467662Snikdi destinazione. Questo pu�� portare ad un overflow oltre i limiti del
13567662Snikbuffer e generare svariati tipi di malfunzionamenti. Nonostante l'opzione
13667662Snik`CONFIG_FORTIFY_SOURCE=y` e svariate opzioni del compilatore aiutano
13767662Snika ridurne il rischio, non c'�� alcuna buona ragione per continuare ad usare
13815317Swoschquesta funzione. La versione sicura da usare �� strscpy(), tuttavia va
13915317Swoschprestata attenzione a tutti quei casi dove viene usato il valore di
14067662Snikritorno di strcpy().  La funzione strscpy() non ritorna un puntatore
14115317Swoschalla destinazione, ma un contatore dei byte non NUL copiati (oppure
14215317Swoschun errno negativo se la stringa �� stata troncata).
14367662Snik
14415317Swoschstrncpy() su stringe terminate con NUL
14515317Swosch--------------------------------------
14667662SnikL'utilizzo di strncpy() non fornisce alcuna garanzia sul fatto che
14715317Swoschil buffer di destinazione verr�� terminato con il carattere NUL. Questo
14815317Swoschpotrebbe portare a diversi overflow di lettura o altri malfunzionamenti
14967662Snikcausati, appunto, dalla mancanza del terminatore. Questa estende la
15067662Snikterminazione nel buffer di destinazione quando la stringa d'origine �� pi��
15167662Snikcorta; questo potrebbe portare ad una penalizzazione delle prestazioni per
15267662Snikchi usa solo stringe terminate. La versione sicura da usare ��
15315317Swoschstrscpy(), tuttavia va prestata attenzione a tutti quei casi dove
15415317Swoschviene usato il valore di ritorno di strncpy().  La funzione strscpy()
15567662Sniknon ritorna un puntatore alla destinazione, ma un contatore dei byte
15615317Swoschnon NUL copiati (oppure un errno negativo se la stringa �� stata
15767662Sniktroncata). Tutti i casi che necessitano di estendere la
15815317Swoschterminazione con NUL dovrebbero usare strscpy_pad().
15915317Swosch
16015317SwoschSe il chiamate no usa stringhe terminate con NUL, allore strncpy()
16167662Snikpu�� continuare ad essere usata, ma i buffer di destinazione devono essere
16215317Swoschmarchiati con l'attributo `__nonstring <https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html>`_
16315317Swoschper evitare avvisi durante la compilazione.
16467662Snik
16567662Snikstrlcpy()
16667662Snik---------
16767662SnikLa funzione strlcpy(), per prima cosa, legge interamente il buffer di
16815317Swoschorigine, magari leggendo pi�� di quanto verr�� effettivamente copiato. Questo
16915317Swosch�� inefficiente e pu�� portare a overflow di lettura quando la stringa non ��
17067662Snikterminata con NUL. La versione sicura da usare �� strscpy(), tuttavia
17115317Swoschva prestata attenzione a tutti quei casi dove viene usato il valore di
17267662Snikritorno di strlcpy(), dato che strscpy() ritorna un valore di errno
17315317Swoschnegativo quanto la stringa viene troncata.
17415317Swosch
17567662SnikSegnaposto %p nella stringa di formato
17615317Swosch--------------------------------------
17715317Swosch
17867662SnikTradizionalmente, l'uso del segnaposto "%p" nella stringa di formato
17967662Snikesponne un indirizzo di memoria in dmesg, proc, sysfs, eccetera.  Per
18067662Snikevitare che questi indirizzi vengano sfruttati da malintenzionati,
18167662Sniktutto gli usi di "%p" nel kernel rappresentano l'hash dell'indirizzo,
18215317Swoschrendendolo di fatto inutilizzabile.  Nuovi usi di "%p" non dovrebbero
18315317Swoschessere aggiunti al kernel.  Per una rappresentazione testuale di un
18467662Snikindirizzo usate "%pS", l'output �� migliore perch�� mostrer�� il nome del
18515317Swoschsimbolo.  Per tutto il resto, semplicemente non usate "%p".
18667662Snik
18715317SwoschParafrasando la `guida
18815317Swosch<https://lore.kernel.org/lkml/CA+55aFwQEd_d40g4mUCSsVRZzrFPUJt74vc6PPpb675hYNXcKw@mail.gmail.com/>`_
18915317Swoschdi Linus:
19067662Snik
19115317Swosch- Se il valore hash di "%p" �� inutile, chiediti se il puntatore stesso
19215317Swosch  �� importante. Forse dovrebbe essere rimosso del tutto?
19367662Snik- Se credi davvero che il vero valore del puntatore sia importante,
19467662Snik  perch�� alcuni stati del sistema o i livelli di privilegi di un
19567662Snik  utente sono considerati "special"? Se pensi di poterlo giustificare
19667662Snik  (in un commento e nel messaggio del commit) abbastanza bene da
19715317Swosch  affrontare il giudizio di Linus, allora forse potrai usare "%px",
19815317Swosch  assicurandosi anche di averne il permesso.
19967662Snik
20015317SwoschPotete disabilitare temporaneamente l'hashing di "%p" nel caso in cui questa
20167662Snikfunzionalit�� vi sia d'ostacolo durante una sessione di debug. Per farlo
20267662Snikaggiungete l'opzione di debug "`no_hash_pointers
20315317Swosch<https://git.kernel.org/linus/5ead723a20e0447bc7db33dc3070b420e5f80aa6>`_" alla
20467662Snikriga di comando del kernel.
20567662Snik
20667662SnikVettori a dimensione variabile (VLA)
20767662Snik------------------------------------
20867662Snik
20967662SnikUsare VLA sullo stack produce codice molto peggiore rispetto a quando si usano
21067662Snikvettori a dimensione fissa. Questi `problemi di prestazioni <https://git.kernel.org/linus/02361bc77888>`_,
21167662Sniktutt'altro che banali, sono gi�� un motivo valido per eliminare i VLA; in
21267662Snikaggiunta sono anche un problema per la sicurezza. La crescita dinamica di un
21367662Snikvettore nello stack potrebbe eccedere la memoria rimanente in tale segmento.
21467662SnikQuesto pu�� portare a dei malfunzionamenti, potrebbe sovrascrivere
21567662Snikdati importanti alla fine dello stack (quando il kernel �� compilato senza
21667662Snik`CONFIG_THREAD_INFO_IN_TASK=y`), o sovrascrivere un pezzo di memoria adiacente
21767662Snikallo stack (quando il kernel �� compilato senza `CONFIG_VMAP_STACK=y`).
21867662Snik
219Salto implicito nell'istruzione switch-case
220-------------------------------------------
221
222Il linguaggio C permette ai casi di un'istruzione `switch` di saltare al
223prossimo caso quando l'istruzione "break" viene omessa alla fine del caso
224corrente. Tuttavia questo rende il codice ambiguo perch�� non �� sempre ovvio se
225l'istruzione "break" viene omessa intenzionalmente o �� un baco. Per esempio,
226osservando il seguente pezzo di codice non �� chiaro se lo stato
227`STATE_ONE` �� stato progettato apposta per eseguire anche `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
239Dato che c'�� stata una lunga lista di problemi `dovuti alla mancanza dell'istruzione
240"break" <https://cwe.mitre.org/data/definitions/484.html>`_, oggigiorno non
241permettiamo pi�� che vi sia un "salto implicito" (*fall-through*). Per
242identificare un salto implicito intenzionale abbiamo adottato la pseudo
243parola chiave 'fallthrough' che viene espansa nell'estensione di gcc
244`__attribute__((fallthrough))` `Statement Attributes
245<https://gcc.gnu.org/onlinedocs/gcc/Statement-Attributes.html>`_.
246(Quando la sintassi C17/C18 `[[fallthrough]]` sar�� pi�� comunemente
247supportata dai compilatori C, analizzatori statici, e dagli IDE,
248allora potremo usare quella sintassi per la pseudo parola chiave)
249
250Quando la sintassi [[fallthrough]] sar�� pi�� comunemente supportata dai
251compilatori, analizzatori statici, e ambienti di sviluppo IDE,
252allora potremo usarla anche noi.
253
254Ne consegue che tutti i blocchi switch/case devono finire in uno dei seguenti
255modi:
256
257* ``break;``
258* `fallthrough;``
259* ``continue;``
260* ``goto <label>;``
261* ``return [expression];``
262
263Array di lunghezza zero o con un solo elemento
264----------------------------------------------
265All'interno del kernel ricorre spesso la necessita di avere membri
266di dimensione variabile all'interno di una struttura dati. In questi
267casi il codice del kernel dovrebbe usare sempre i `"flexible array
268member" <https://en.wikipedia.org/wiki/Flexible_array_member>`_. La
269tecnica degli array a lunghezza nulla o di un solo elemento non
270dovrebbe essere pi�� usata.
271
272Nel codice C pi�� vecchio, la dichiarazione di un membro di dimensione
273variabile in coda ad una struttura dati veniva fatto dichiarando un
274array di un solo elemento posizionato alla fine della struttura dati::
275
276        struct something {
277                size_t count;
278                struct foo items[1];
279        };
280
281Questo ha portato ad un calcolo di sizeof() traballante (dovrebbe
282rimuovere la dimensione del singolo elemento in coda per calcolare la
283dimensione esatta dell' "intestazione"). Per evitare questi problemi ��
284stata introdotta un' `estensione a GNU C
285<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_ che
286permettesse la dichiarazione di array a lungezza zero::
287
288        struct something {
289                size_t count;
290                struct foo items[0];
291        };
292
293Ma questo ha portato nuovi problemi, e non ha risolto alcuni dei
294problemi che affliggono entrambe le tecniche: per esempio
295l'impossibilit�� di riconoscere se un array di quel tipo viene usato
296nel mezzo di una struttura dati e _non_ alla fine (potrebbe accadere
297sia direttamente, sia indirettamente quando si usano le unioni o le
298strutture di strutture).
299
300Lo standard C99 introduce i "flexible array members". Questi array non
301hanno una dimensione nella loro dichiarazione::
302
303        struct something {
304                size_t count;
305                struct foo items[];
306        };
307
308Questo �� il modo con cui ci si aspetta che vengano dichiarati gli
309elementi di lunghezza variabile in coda alle strutture dati.  Permette
310al compilatore di produrre errori quando gli array flessibili non si
311trovano alla fine della struttura dati, il che permette di prevenire
312alcuni tipi di bachi dovuti a `comportamenti inaspettati
313<https://git.kernel.org/linus/76497732932f15e7323dc805e8ea8dc11bb587cf>`_.
314Inoltre, permette al compilatore di analizzare correttamente le
315dimensioni degli array (attraverso sizeof(), `CONFIG_FORTIFY_SOURCE`,
316e `CONFIG_UBSAN_BOUNDS`). Per esempio, non esiste alcun meccanismo in
317grado di avvisarci che il seguente uso di sizeof() dia sempre come
318zero come risultato::
319
320        struct something {
321                size_t count;
322                struct foo items[0];
323        };
324
325        struct something *instance;
326
327        instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL);
328        instance->count = count;
329
330        size = sizeof(instance->items) * instance->count;
331        memcpy(instance->items, source, size);
332
333Il valore di ``size`` nell'ultima riga sar�� ``zero``, quando uno
334invece si aspetterebbe che il suo valore sia la dimensione totale in
335byte dell'allocazione dinamica che abbiamo appena fatto per l'array
336``items``. Qui un paio di esempi reali del problema: `collegamento 1
337<https://git.kernel.org/linus/f2cd32a443da694ac4e28fbf4ac6f9d5cc63a539>`_,
338`collegamento 2
339<https://git.kernel.org/linus/ab91c2a89f86be2898cee208d492816ec238b2cf>`_.
340Invece, `i flexible array members hanno un tipo incompleto, e quindi
341sizeof() non pu�� essere applicato
342<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_; dunque ogni
343uso scorretto di questo operatore verr�� identificato immediatamente
344durante la compilazione.
345
346Per quanto riguarda gli array di un solo elemento, bisogna essere
347consapevoli che `questi array occupano almeno quanto lo spazio di un
348singolo oggetti dello stesso tipo
349<https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html>`_, e quindi
350contribuiscono al calcolo della dimensione della struttura che li
351contiene. In questo caso �� facile commettere errori quando si vuole
352calcolare la dimensione totale della memoria totale da allocare per
353una struttura dati::
354
355        struct something {
356                size_t count;
357                struct foo items[1];
358        };
359
360        struct something *instance;
361
362        instance = kmalloc(struct_size(instance, items, count - 1), GFP_KERNEL);
363        instance->count = count;
364
365        size = sizeof(instance->items) * instance->count;
366        memcpy(instance->items, source, size);
367
368In questo esempio ci siamo dovuti ricordare di usare ``count - 1`` in
369struct_size(), altrimenti avremmo --inavvertitamente-- allocato
370memoria per un oggetti ``items`` in pi��. Il modo pi�� pulito e meno
371propenso agli errori �� quello di usare i `flexible array member`, in
372combinazione con struct_size() e flex_array_size()::
373
374        struct something {
375                size_t count;
376                struct foo items[];
377        };
378
379        struct something *instance;
380
381        instance = kmalloc(struct_size(instance, items, count), GFP_KERNEL);
382        instance->count = count;
383
384        memcpy(instance->items, source, flex_array_size(instance, items, instance->count));
385
386Ci sono due casi speciali dove �� necessario usare la macro DECLARE_FLEX_ARRAY()
387(da notare che la stessa macro �� chiamata __DECLARE_FLEX_ARRAY() nei file di
388intestazione UAPI). Uno �� quando l'array flessibile �� l'unico elemento di una
389struttura, e l'altro quando �� parte di un unione. Per motivi non tecnici, entrambi
390i casi d'uso non sono permessi dalla specifica C99. Per esempio, per
391convertire il seguente codice::
392
393    struct something {
394        ...
395        union {
396            struct type1 one[0];
397            struct type2 two[0];
398        };
399    };
400
401La macro di supporto dev'essere usata::
402
403    struct something {
404        ...
405        union {
406            DECLARE_FLEX_ARRAY(struct type1, one);
407            DECLARE_FLEX_ARRAY(struct type2, two);
408        };
409    };
410