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