1.. include:: ../disclaimer-ita.rst 2 3:Original: :ref:`Documentation/process/adding-syscalls.rst <addsyscalls>` 4:Translator: Federico Vaga <federico.vaga@vaga.pv.it> 5 6.. _it_addsyscalls: 7 8Aggiungere una nuova chiamata di sistema 9======================================== 10 11Questo documento descrive quello che è necessario sapere per aggiungere 12nuove chiamate di sistema al kernel Linux; questo è da considerarsi come 13un'aggiunta ai soliti consigli su come proporre nuove modifiche 14:ref:`Documentation/translations/it_IT/process/submitting-patches.rst <it_submittingpatches>`. 15 16 17Alternative alle chiamate di sistema 18------------------------------------ 19 20La prima considerazione da fare quando si aggiunge una nuova chiamata di 21sistema è quella di valutare le alternative. Nonostante le chiamate di sistema 22siano il punto di interazione fra spazio utente e kernel più tradizionale ed 23ovvio, esistono altre possibilità - scegliete quella che meglio si adatta alle 24vostra interfaccia. 25 26 - Se le operazioni coinvolte possono rassomigliare a quelle di un filesystem, 27 allora potrebbe avere molto più senso la creazione di un nuovo filesystem o 28 dispositivo. Inoltre, questo rende più facile incapsulare la nuova 29 funzionalità in un modulo kernel piuttosto che essere sviluppata nel cuore 30 del kernel. 31 32 - Se la nuova funzionalità prevede operazioni dove il kernel notifica 33 lo spazio utente su un avvenimento, allora restituire un descrittore 34 di file all'oggetto corrispondente permette allo spazio utente di 35 utilizzare ``poll``/``select``/``epoll`` per ricevere quelle notifiche. 36 - Tuttavia, le operazioni che non si sposano bene con operazioni tipo 37 :manpage:`read(2)`/:manpage:`write(2)` dovrebbero essere implementate 38 come chiamate :manpage:`ioctl(2)`, il che potrebbe portare ad un'API in 39 un qualche modo opaca. 40 41 - Se dovete esporre solo delle informazioni sul sistema, un nuovo nodo in 42 sysfs (vedere ``Documentation/filesystems/sysfs.rst``) o 43 in procfs potrebbe essere sufficiente. Tuttavia, l'accesso a questi 44 meccanismi richiede che il filesystem sia montato, il che potrebbe non 45 essere sempre vero (per esempio, in ambienti come namespace/sandbox/chroot). 46 Evitate d'aggiungere nuove API in debugfs perché questo non viene 47 considerata un'interfaccia di 'produzione' verso lo spazio utente. 48 - Se l'operazione è specifica ad un particolare file o descrittore, allora 49 potrebbe essere appropriata l'aggiunta di un comando :manpage:`fcntl(2)`. 50 Tuttavia, :manpage:`fcntl(2)` è una chiamata di sistema multiplatrice che 51 nasconde una notevole complessità, quindi è ottima solo quando la nuova 52 funzione assomiglia a quelle già esistenti in :manpage:`fcntl(2)`, oppure 53 la nuova funzionalità è veramente semplice (per esempio, leggere/scrivere 54 un semplice flag associato ad un descrittore di file). 55 - Se l'operazione è specifica ad un particolare processo, allora 56 potrebbe essere appropriata l'aggiunta di un comando :manpage:`prctl(2)`. 57 Come per :manpage:`fcntl(2)`, questa chiamata di sistema è un complesso 58 multiplatore quindi è meglio usarlo per cose molto simili a quelle esistenti 59 nel comando ``prctl`` oppure per leggere/scrivere un semplice flag relativo 60 al processo. 61 62 63Progettare l'API: pianificare le estensioni 64------------------------------------------- 65 66Una nuova chiamata di sistema diventerà parte dell'API del kernel, e 67dev'essere supportata per un periodo indefinito. Per questo, è davvero 68un'ottima idea quella di discutere apertamente l'interfaccia sulla lista 69di discussione del kernel, ed è altrettanto importante pianificarne eventuali 70estensioni future. 71 72(Nella tabella delle chiamate di sistema sono disseminati esempi dove questo 73non fu fatto, assieme ai corrispondenti aggiornamenti - 74``eventfd``/``eventfd2``, ``dup2``/``dup3``, ``inotify_init``/``inotify_init1``, 75``pipe``/``pipe2``, ``renameat``/``renameat2`` --quindi imparate dalla storia 76del kernel e pianificate le estensioni fin dall'inizio) 77 78Per semplici chiamate di sistema che accettano solo un paio di argomenti, 79il modo migliore di permettere l'estensibilità è quello di includere un 80argomento *flags* alla chiamata di sistema. Per assicurarsi che i programmi 81dello spazio utente possano usare in sicurezza *flags* con diverse versioni 82del kernel, verificate se *flags* contiene un qualsiasi valore sconosciuto, 83in qual caso rifiutate la chiamata di sistema (con ``EINVAL``):: 84 85 if (flags & ~(THING_FLAG1 | THING_FLAG2 | THING_FLAG3)) 86 return -EINVAL; 87 88(Se *flags* non viene ancora utilizzato, verificate che l'argomento sia zero) 89 90Per chiamate di sistema più sofisticate che coinvolgono un numero più grande di 91argomenti, il modo migliore è quello di incapsularne la maggior parte in una 92struttura dati che verrà passata per puntatore. Questa struttura potrà 93funzionare con future estensioni includendo un campo *size*:: 94 95 struct xyzzy_params { 96 u32 size; /* userspace sets p->size = sizeof(struct xyzzy_params) */ 97 u32 param_1; 98 u64 param_2; 99 u64 param_3; 100 }; 101 102Fintanto che un qualsiasi campo nuovo, diciamo ``param_4``, è progettato per 103offrire il comportamento precedente quando vale zero, allora questo permetterà 104di gestire un conflitto di versione in entrambe le direzioni: 105 106 - un vecchio kernel può gestire l'accesso di una versione moderna di un 107 programma in spazio utente verificando che la memoria oltre la dimensione 108 della struttura dati attesa sia zero (in pratica verificare che 109 ``param_4 == 0``). 110 - un nuovo kernel può gestire l'accesso di una versione vecchia di un 111 programma in spazio utente estendendo la struttura dati con zeri (in pratica 112 ``param_4 = 0``). 113 114Vedere :manpage:`perf_event_open(2)` e la funzione ``perf_copy_attr()`` (in 115``kernel/events/core.c``) per un esempio pratico di questo approccio. 116 117 118Progettare l'API: altre considerazioni 119-------------------------------------- 120 121Se la vostra nuova chiamata di sistema permette allo spazio utente di fare 122riferimento ad un oggetto del kernel, allora questa dovrebbe usare un 123descrittore di file per accesso all'oggetto - non inventatevi nuovi tipi di 124accesso da spazio utente quando il kernel ha già dei meccanismi e una semantica 125ben definita per utilizzare i descrittori di file. 126 127Se la vostra nuova chiamata di sistema xyzzy(2) ritorna un nuovo 128descrittore di file, allora l'argomento *flags* dovrebbe includere un valore 129equivalente a ``O_CLOEXEC`` per i nuovi descrittori. Questo rende possibile, 130nello spazio utente, la chiusura della finestra temporale fra le chiamate a 131``xyzzy()`` e ``fcntl(fd, F_SETFD, FD_CLOEXEC)``, dove un inaspettato 132``fork()`` o ``execve()`` potrebbe trasferire il descrittore al programma 133eseguito (Comunque, resistete alla tentazione di riutilizzare il valore di 134``O_CLOEXEC`` dato che è specifico dell'architettura e fa parte di una 135enumerazione di flag ``O_*`` che è abbastanza ricca). 136 137Se la vostra nuova chiamata di sistema ritorna un nuovo descrittore di file, 138dovreste considerare che significato avrà l'uso delle chiamate di sistema 139della famiglia di :manpage:`poll(2)`. Rendere un descrittore di file pronto 140per la lettura o la scrittura è il tipico modo del kernel per notificare lo 141spazio utente circa un evento associato all'oggetto del kernel. 142 143Se la vostra nuova chiamata di sistema xyzzy(2) ha un argomento 144che è il percorso ad un file:: 145 146 int sys_xyzzy(const char __user *path, ..., unsigned int flags); 147 148dovreste anche considerare se non sia più appropriata una versione 149`xyzzyat(2)`:: 150 151 int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags); 152 153Questo permette più flessibilità su come lo spazio utente specificherà il file 154in questione; in particolare, permette allo spazio utente di richiedere la 155funzionalità su un descrittore di file già aperto utilizzando il *flag* 156``AT_EMPTY_PATH``, in pratica otterremmo gratuitamente l'operazione 157fxyzzy(3):: 158 159 - xyzzyat(AT_FDCWD, path, ..., 0) is equivalent to xyzzy(path,...) 160 - xyzzyat(fd, "", ..., AT_EMPTY_PATH) is equivalent to fxyzzy(fd, ...) 161 162(Per maggiori dettagli sulla logica delle chiamate \*at(), leggete la pagina 163man :manpage:`openat(2)`; per un esempio di AT_EMPTY_PATH, leggere la pagina 164man :manpage:`fstatat(2)`). 165 166Se la vostra nuova chiamata di sistema xyzzy(2) prevede un parametro 167per descrivere uno scostamento all'interno di un file, usate ``loff_t`` come 168tipo cosicché scostamenti a 64-bit potranno essere supportati anche su 169architetture a 32-bit. 170 171Se la vostra nuova chiamata di sistema xyzzy(2) prevede l'uso di 172funzioni riservate, allora dev'essere gestita da un opportuno bit di privilegio 173(verificato con una chiamata a ``capable()``), come descritto nella pagina man 174:manpage:`capabilities(7)`. Scegliete un bit di privilegio già esistente per 175gestire la funzionalità associata, ma evitate la combinazione di diverse 176funzionalità vagamente collegate dietro lo stesso bit, in quanto va contro il 177principio di *capabilities* di separare i poteri di root. In particolare, 178evitate di aggiungere nuovi usi al fin-troppo-generico privilegio 179``CAP_SYS_ADMIN``. 180 181Se la vostra nuova chiamata di sistema xyzzy(2) manipola altri 182processi oltre a quello chiamato, allora dovrebbe essere limitata (usando 183la chiamata ``ptrace_may_access()``) di modo che solo un processo chiamante 184con gli stessi permessi del processo in oggetto, o con i necessari privilegi, 185possa manipolarlo. 186 187Infine, state attenti che in alcune architetture non-x86 la vita delle chiamate 188di sistema con argomenti a 64-bit viene semplificata se questi argomenti 189ricadono in posizioni dispari (pratica, i parametri 1, 3, 5); questo permette 190l'uso di coppie contigue di registri a 32-bit. (Questo non conta se gli 191argomenti sono parte di una struttura dati che viene passata per puntatore). 192 193 194Proporre l'API 195-------------- 196 197Al fine di rendere le nuove chiamate di sistema di facile revisione, è meglio 198che dividiate le modifiche i pezzi separati. Questi dovrebbero includere 199almeno le seguenti voci in *commit* distinti (ognuno dei quali sarà descritto 200più avanti): 201 202 - l'essenza dell'implementazione della chiamata di sistema, con i prototipi, 203 i numeri generici, le modifiche al Kconfig e l'implementazione *stub* di 204 ripiego. 205 - preparare la nuova chiamata di sistema per un'architettura specifica, 206 solitamente x86 (ovvero tutti: x86_64, x86_32 e x32). 207 - un programma di auto-verifica da mettere in ``tools/testing/selftests/`` 208 che mostri l'uso della chiamata di sistema. 209 - una bozza di pagina man per la nuova chiamata di sistema. Può essere 210 scritta nell'email di presentazione, oppure come modifica vera e propria 211 al repositorio delle pagine man. 212 213Le proposte di nuove chiamate di sistema, come ogni altro modifica all'API del 214kernel, deve essere sottomessa alla lista di discussione 215linux-api@vger.kernel.org. 216 217 218Implementazione di chiamate di sistema generiche 219------------------------------------------------ 220 221Il principale punto d'accesso alla vostra nuova chiamata di sistema 222`xyzzy(2)` verrà chiamato ``sys_xyzzy()``; ma, piuttosto che in modo 223esplicito, lo aggiungerete tramite la macro ``SYSCALL_DEFINEn``. La 'n' 224indica il numero di argomenti della chiamata di sistema; la macro ha come 225argomento il nome della chiamata di sistema, seguito dalle coppie (tipo, nome) 226per definire i suoi parametri. L'uso di questa macro permette di avere 227i metadati della nuova chiamata di sistema disponibili anche per altri 228strumenti. 229 230Il nuovo punto d'accesso necessita anche del suo prototipo di funzione in 231``include/linux/syscalls.h``, marcato come asmlinkage di modo da abbinargli 232il modo in cui quelle chiamate di sistema verranno invocate:: 233 234 asmlinkage long sys_xyzzy(...); 235 236Alcune architetture (per esempio x86) hanno le loro specifiche tabelle di 237chiamate di sistema (syscall), ma molte altre architetture condividono una 238tabella comune di syscall. Aggiungete alla lista generica la vostra nuova 239chiamata di sistema aggiungendo un nuovo elemento alla lista in 240``include/uapi/asm-generic/unistd.h``:: 241 242 #define __NR_xyzzy 292 243 __SYSCALL(__NR_xyzzy, sys_xyzzy) 244 245Aggiornate anche il contatore __NR_syscalls di modo che sia coerente con 246l'aggiunta della nuove chiamate di sistema; va notato che se più di una nuova 247chiamata di sistema viene aggiunga nella stessa finestra di sviluppo, il numero 248della vostra nuova syscall potrebbe essere aggiustato al fine di risolvere i 249conflitti. 250 251Il file ``kernel/sys_ni.c`` fornisce le implementazioni *stub* di ripiego che 252ritornano ``-ENOSYS``. Aggiungete la vostra nuova chiamata di sistema anche 253qui:: 254 255 COND_SYSCALL(xyzzy); 256 257La vostra nuova funzionalità del kernel, e la chiamata di sistema che la 258controlla, dovrebbero essere opzionali. Quindi, aggiungete un'opzione 259``CONFIG`` (solitamente in ``init/Kconfig``). Come al solito per le nuove 260opzioni ``CONFIG``: 261 262 - Includete una descrizione della nuova funzionalità e della chiamata di 263 sistema che la controlla. 264 - Rendete l'opzione dipendente da EXPERT se dev'essere nascosta agli utenti 265 normali. 266 - Nel Makefile, rendere tutti i nuovi file sorgenti, che implementano la 267 nuova funzionalità, dipendenti dall'opzione CONFIG (per esempio 268 ``obj-$(CONFIG_XYZZY_SYSCALL) += xyzzy.o``). 269 - Controllate due volte che sia possibile generare il kernel con la nuova 270 opzione CONFIG disabilitata. 271 272Per riassumere, vi serve un *commit* che includa: 273 274 - un'opzione ``CONFIG``per la nuova funzione, normalmente in ``init/Kconfig`` 275 - ``SYSCALL_DEFINEn(xyzzy, ...)`` per il punto d'accesso 276 - il corrispondente prototipo in ``include/linux/syscalls.h`` 277 - un elemento nella tabella generica in ``include/uapi/asm-generic/unistd.h`` 278 - *stub* di ripiego in ``kernel/sys_ni.c`` 279 280 281.. _it_syscall_generic_6_11: 282 283Dalla versione 6.11 284~~~~~~~~~~~~~~~~~~~~ 285 286A partire dalla versione 6.11 del kernel, l'implementazione generica delle 287chiamate di sistema per le seguenti architetture non richiede più modifiche 288a ``include/uapi/asm-generic/unistd.h``: 289 290 - arc 291 - arm64 292 - csky 293 - hexagon 294 - loongarch 295 - nios2 296 - openrisc 297 - riscv 298 299Al suo posto, dovete aggiornare ``scripts/syscall.tbl`` e, se necessario, 300modificare ``arch/*/kernel/Makefile.syscalls``. 301 302Dato che ``scripts/syscall.tbl`` funge da tabella comune delle chiamate di 303sistema condivisa fra più architetture, in questa tabella è richiesto un 304nuovo elemento:: 305 306 468 common xyzzy sys_xyzzy 307 308Da notare che l'aggiunta di un elemento a ``scripts/syscall.tbl`` con l'ABI 309"common" influisce anche su tutte le architetture che condividono questa 310tabella. Per modifiche più limitate o specifiche di un'architettura, 311considerate l'uso di un'ABI specifica per l'architettura, o la definizione 312di una nuova. 313 314Se viene introdotta una nuova ABI, per esempio ``xyz``, andranno fatti i 315corrispondenti aggiornamenti anche in ``arch/*/kernel/Makefile.syscalls``:: 316 317 syscall_abis_{32,64} += xyz (...) 318 319Per riassumere, vi serve un *commit* che includa: 320 321 - un'opzione ``CONFIG`` per la nuova funzione, normalmente in 322 ``init/Kconfig`` 323 - ``SYSCALL_DEFINEn(xyzzy, ...)`` per il punto d'accesso 324 - il corrispondente prototipo in ``include/linux/syscalls.h`` 325 - un nuovo elemento in ``scripts/syscall.tbl`` 326 - (se necessario) aggiornamenti al Makefile in 327 ``arch/*/kernel/Makefile.syscalls`` 328 - *stub* di ripiego in ``kernel/sys_ni.c`` 329 330 331Implementazione delle chiamate di sistema x86 332--------------------------------------------- 333 334Per collegare la vostra nuova chiamate di sistema alle piattaforme x86, 335dovete aggiornate la tabella principale di syscall. Assumendo che la vostra 336nuova chiamata di sistema non sia particolarmente speciale (vedere sotto), 337dovete aggiungere un elemento *common* (per x86_64 e x32) in 338arch/x86/entry/syscalls/syscall_64.tbl:: 339 340 333 common xyzzy sys_xyzzy 341 342e un elemento per *i386* ``arch/x86/entry/syscalls/syscall_32.tbl``:: 343 344 380 i386 xyzzy sys_xyzzy 345 346Ancora una volta, questi numeri potrebbero essere cambiati se generano 347conflitti durante la finestra di integrazione. 348 349 350Chiamate di sistema compatibili (generico) 351------------------------------------------ 352 353Per molte chiamate di sistema, la stessa implementazione a 64-bit può essere 354invocata anche quando il programma in spazio utente è a 32-bit; anche se la 355chiamata di sistema include esplicitamente un puntatore, questo viene gestito 356in modo trasparente. 357 358Tuttavia, ci sono un paio di situazione dove diventa necessario avere un 359livello di gestione della compatibilità per risolvere le differenze di 360dimensioni fra 32-bit e 64-bit. 361 362Il primo caso è quando un kernel a 64-bit supporta anche programmi in spazio 363utente a 32-bit, perciò dovrà ispezionare aree della memoria (``__user``) che 364potrebbero contenere valori a 32-bit o a 64-bit. In particolar modo, questo 365è necessario quando un argomento di una chiamata di sistema è: 366 367 - un puntatore ad un puntatore 368 - un puntatore ad una struttura dati contenente a sua volta un puntatore 369 ( ad esempio ``struct iovec __user *``) 370 - un puntatore ad un tipo intero di dimensione variabile (``time_t``, 371 ``off_t``, ``long``, ...) 372 - un puntatore ad una struttura dati contenente un tipo intero di dimensione 373 variabile. 374 375Il secondo caso che richiede un livello di gestione della compatibilità è 376quando uno degli argomenti di una chiamata a sistema è esplicitamente un tipo 377a 64-bit anche su architetture a 32-bit, per esempio ``loff_t`` o ``__u64``. 378In questo caso, un valore che arriva ad un kernel a 64-bit da un'applicazione 379a 32-bit verrà diviso in due valori a 32-bit che dovranno essere riassemblati 380in questo livello di compatibilità. 381 382(Da notare che non serve questo livello di compatibilità per argomenti che 383sono puntatori ad un tipo esplicitamente a 64-bit; per esempio, in 384:manpage:`splice(2)` l'argomento di tipo ``loff_t __user *`` non necessita 385di una chiamata di sistema ``compat_``) 386 387La versione compatibile della nostra chiamata di sistema si chiamerà 388``compat_sys_xyzzy()``, e viene aggiunta utilizzando la macro 389``COMPAT_SYSCALL_DEFINEn()`` (simile a SYSCALL_DEFINEn). Questa versione 390dell'implementazione è parte del kernel a 64-bit ma accetta parametri a 32-bit 391che trasformerà secondo le necessità (tipicamente, la versione 392``compat_sys_`` converte questi valori nello loro corrispondente a 64-bit e 393può chiamare la versione ``sys_`` oppure invocare una funzione che implementa 394le parti comuni). 395 396Il punto d'accesso *compat* deve avere il corrispondente prototipo di funzione 397in ``include/linux/compat.h``, marcato come asmlinkage di modo da abbinargli 398il modo in cui quelle chiamate di sistema verranno invocate:: 399 400 asmlinkage long compat_sys_xyzzy(...); 401 402Se la chiamata di sistema prevede una struttura dati organizzata in modo 403diverso per sistemi a 32-bit e per quelli a 64-bit, diciamo 404``struct xyzzy_args``, allora il file d'intestazione 405``then the include/linux/compat.h`` deve includere la sua versione 406*compatibile* (``struct compat_xyzzy_args``); ogni variabile con 407dimensione variabile deve avere il proprio tipo ``compat_`` corrispondente 408a quello in ``struct xyzzy_args``. La funzione ``compat_sys_xyzzy()`` 409può usare la struttura ``compat_`` per analizzare gli argomenti ricevuti 410da una chiamata a 32-bit. 411 412Per esempio, se avete i seguenti campi:: 413 414 struct xyzzy_args { 415 const char __user *ptr; 416 __kernel_long_t varying_val; 417 u64 fixed_val; 418 /* ... */ 419 }; 420 421nella struttura ``struct xyzzy_args``, allora la struttura 422``struct compat_xyzzy_args`` dovrebbe avere:: 423 424 struct compat_xyzzy_args { 425 compat_uptr_t ptr; 426 compat_long_t varying_val; 427 u64 fixed_val; 428 /* ... */ 429 }; 430 431La lista generica delle chiamate di sistema ha bisogno di essere 432aggiustata al fine di permettere l'uso della versione *compatibile*; 433la voce in ``include/uapi/asm-generic/unistd.h`` dovrebbero usare 434``__SC_COMP`` piuttosto di ``__SYSCALL``:: 435 436 #define __NR_xyzzy 292 437 __SC_COMP(__NR_xyzzy, sys_xyzzy, compat_sys_xyzzy) 438 439Riassumendo, vi serve: 440 441 - un ``COMPAT_SYSCALL_DEFINEn(xyzzy, ...)`` per il punto d'accesso 442 *compatibile* 443 - un prototipo in ``include/linux/compat.h`` 444 - (se necessario) una struttura di compatibilità a 32-bit in 445 ``include/linux/compat.h`` 446 - una voce ``__SC_COMP``, e non ``__SYSCALL``, in 447 ``include/uapi/asm-generic/unistd.h`` 448 449 450Dalla versione 6.11 451~~~~~~~~~~~~~~~~~~~~ 452 453Questo si applica a tutte le architetture elencate in 454:ref:`Dalla versione 6.11<it_syscall_generic_6_11>` sotto "Implementazione 455di chiamate di sistema generiche", eccetto arm64. Vedere 456:ref:`Chiamate di sistema compatibili (arm64)<it_compat_arm64>` per maggiori 457informazioni. 458 459Dovete estendere la voce in ``scripts/syscall.tbl`` con una colonna 460aggiuntiva per indicare che un programma in spazio utente a 32-bit in 461esecuzione su un kernel a 64-bit deve invocare il punto d'accesso 462*compatibile*:: 463 464 468 common xyzzy sys_xyzzy compat_sys_xyzzy 465 466Riassumendo, vi serve: 467 468 - un ``COMPAT_SYSCALL_DEFINEn(xyzzy, ...)`` per il punto d'accesso 469 *compatibile* 470 - il corrispondente prototipo in ``include/linux/compat.h`` 471 - la modifica della voce in ``scripts/syscall.tbl`` per includere una 472 colonna "compat" aggiuntiva 473 - (se necessario) una struttura di mappatura a 32-bit in 474 ``include/linux/compat.h`` 475 476 477.. _it_compat_arm64: 478 479Chiamate di sistema compatibili (arm64) 480^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 481 482Su arm64 esiste una tabella delle chiamate di sistema dedicata per le 483chiamate di sistema compatibili rivolte allo spazio utente a 32-bit 484(AArch32): ``arch/arm64/tools/syscall_32.tbl``. Dovete aggiungere una riga 485aggiuntiva a questa tabella specificando il punto d'accesso *compatibile*:: 486 487 468 common xyzzy sys_xyzzy compat_sys_xyzzy 488 489 490Compatibilità delle chiamate di sistema (x86) 491--------------------------------------------- 492 493Per collegare una chiamata di sistema, su un'architettura x86, con la sua 494versione *compatibile*, è necessario aggiustare la voce nella tabella 495delle syscall. 496 497Per prima cosa, la voce in ``arch/x86/entry/syscalls/syscall_32.tbl`` prende 498un argomento aggiuntivo per indicare che un programma in spazio utente 499a 32-bit, eseguito su un kernel a 64-bit, dovrebbe accedere tramite il punto 500d'accesso compatibile:: 501 502 380 i386 xyzzy sys_xyzzy __ia32_compat_sys_xyzzy 503 504Secondo, dovete capire cosa dovrebbe succedere alla nuova chiamata di sistema 505per la versione dell'ABI x32. Qui C'è una scelta da fare: gli argomenti 506possono corrisponde alla versione a 64-bit o a quella a 32-bit. 507 508Se c'è un puntatore ad un puntatore, la decisione è semplice: x32 è ILP32, 509quindi gli argomenti dovrebbero corrispondere a quelli a 32-bit, e la voce in 510``arch/x86/entry/syscalls/syscall_64.tbl`` sarà divisa cosicché i programmi 511x32 eseguano la chiamata *compatibile*:: 512 513 333 64 xyzzy sys_xyzzy 514 ... 515 555 x32 xyzzy __x32_compat_sys_xyzzy 516 517Se non ci sono puntatori, allora è preferibile riutilizzare la chiamata di 518sistema a 64-bit per l'ABI x32 (e di conseguenza la voce in 519arch/x86/entry/syscalls/syscall_64.tbl rimane immutata). 520 521In ambo i casi, dovreste verificare che i tipi usati dagli argomenti 522abbiano un'esatta corrispondenza da x32 (-mx32) al loro equivalente a 52332-bit (-m32) o 64-bit (-m64). 524 525 526Chiamate di sistema che ritornano altrove 527----------------------------------------- 528 529Nella maggior parte delle chiamate di sistema, al termine della loro 530esecuzione, i programmi in spazio utente riprendono esattamente dal punto 531in cui si erano interrotti -- quindi dall'istruzione successiva, con lo 532stesso *stack* e con la maggior parte del registri com'erano stati 533lasciati prima della chiamata di sistema, e anche con la stessa memoria 534virtuale. 535 536Tuttavia, alcune chiamata di sistema fanno le cose in modo differente. 537Potrebbero ritornare ad un punto diverso (``rt_sigreturn``) o cambiare 538la memoria in spazio utente (``fork``/``vfork``/``clone``) o perfino 539l'architettura del programma (``execve``/``execveat``). 540 541Per permettere tutto ciò, l'implementazione nel kernel di questo tipo di 542chiamate di sistema potrebbero dover salvare e ripristinare registri 543aggiuntivi nello *stack* del kernel, permettendo così un controllo completo 544su dove e come l'esecuzione dovrà continuare dopo l'esecuzione della 545chiamata di sistema. 546 547Queste saranno specifiche per ogni architettura, ma tipicamente si definiscono 548dei punti d'accesso in *assembly* per salvare/ripristinare i registri 549aggiuntivi e quindi chiamare il vero punto d'accesso per la chiamata di 550sistema. 551 552Per l'architettura x86_64, questo è implementato come un punto d'accesso 553``stub_xyzzy`` in ``arch/x86/entry/entry_64.S``, e la voce nella tabella 554di syscall (``arch/x86/entry/syscalls/syscall_64.tbl``) verrà corretta di 555conseguenza:: 556 557 333 common xyzzy stub_xyzzy 558 559L'equivalente per programmi a 32-bit eseguiti su un kernel a 64-bit viene 560normalmente chiamato ``stub32_xyzzy`` e implementato in 561``arch/x86/entry/entry_64_compat.S`` con la corrispondente voce nella tabella 562di syscall ``arch/x86/entry/syscalls/syscall_32.tbl`` corretta nel 563seguente modo:: 564 565 380 i386 xyzzy sys_xyzzy stub32_xyzzy 566 567Se una chiamata di sistema necessita di un livello di compatibilità (come 568nella sezione precedente), allora la versione ``stub32_`` deve invocare 569la versione ``compat_sys_`` piuttosto che quella nativa a 64-bit. In aggiunta, 570se l'implementazione dell'ABI x32 è diversa da quella x86_64, allora la sua 571voce nella tabella di syscall dovrà chiamare uno *stub* che invoca la versione 572``compat_sys_``, 573 574Per completezza, sarebbe carino impostare una mappatura cosicché 575*user-mode* Linux (UML) continui a funzionare -- la sua tabella di syscall 576farà riferimento a stub_xyzzy, ma UML non include l'implementazione 577in ``arch/x86/entry/entry_64.S`` (perché UML simula i registri eccetera). 578Correggerlo è semplice, basta aggiungere una #define in 579``arch/x86/um/sys_call_table_64.c``:: 580 581 #define stub_xyzzy sys_xyzzy 582 583 584Altri dettagli 585-------------- 586 587La maggior parte dei kernel tratta le chiamate di sistema allo stesso modo, 588ma possono esserci rare eccezioni per le quali potrebbe essere necessario 589l'aggiornamento della vostra chiamata di sistema. 590 591Il sotto-sistema di controllo (*audit subsystem*) è uno di questi casi 592speciali; esso include (per architettura) funzioni che classificano alcuni 593tipi di chiamate di sistema -- in particolare apertura dei file 594(``open``/``openat``), esecuzione dei programmi (``execve``/``exeveat``) 595oppure multiplatori di socket (``socketcall``). Se la vostra nuova chiamata 596di sistema è simile ad una di queste, allora il sistema di controllo dovrebbe 597essere aggiornato. 598 599Più in generale, se esiste una chiamata di sistema che è simile alla vostra, 600vale la pena fare una ricerca con ``grep`` su tutto il kernel per la chiamata 601di sistema esistente per verificare che non ci siano altri casi speciali. 602 603 604Verifica 605-------- 606 607Una nuova chiamata di sistema dev'essere, ovviamente, provata; è utile fornire 608ai revisori un programma in spazio utente che mostri l'uso della chiamata di 609sistema. Un buon modo per combinare queste cose è quello di aggiungere un 610semplice programma di auto-verifica in una nuova cartella in 611``tools/testing/selftests/``. 612 613Per una nuova chiamata di sistema, ovviamente, non ci sarà alcuna funzione 614in libc e quindi il programma di verifica dovrà invocarla usando ``syscall()``; 615inoltre, se la nuova chiamata di sistema prevede un nuova struttura dati 616visibile in spazio utente, il file d'intestazione necessario dev'essere 617installato al fine di compilare il programma. 618 619Assicuratevi che il programma di auto-verifica possa essere eseguito 620correttamente su tutte le architetture supportate. Per esempio, verificate che 621funzioni quando viene compilato per x86_64 (-m64), x86_32 (-m32) e x32 (-mx32). 622 623Al fine di una più meticolosa ed estesa verifica della nuova funzionalità, 624dovreste considerare l'aggiunta di nuove verifica al progetto 'Linux Test', 625oppure al progetto xfstests per cambiamenti relativi al filesystem. 626 627 - https://linux-test-project.github.io/ 628 - git://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git 629 630 631Pagine man 632---------- 633 634Tutte le nuove chiamate di sistema dovrebbero avere una pagina man completa, 635idealmente usando i marcatori groff, ma anche il puro testo può andare. Se 636state usando groff, è utile che includiate nella email di presentazione una 637versione già convertita in formato ASCII: semplificherà la vita dei revisori. 638 639Le pagine man dovrebbero essere in copia-conoscenza verso 640linux-man@vger.kernel.org 641Per maggiori dettagli, leggere 642https://www.kernel.org/doc/man-pages/patches.html 643 644 645Non invocate chiamate di sistema dal kernel 646------------------------------------------- 647 648Le chiamate di sistema sono, come già detto prima, punti di interazione fra 649lo spazio utente e il kernel. Perciò, le chiamate di sistema come 650``sys_xyzzy()`` o ``compat_sys_xyzzy()`` dovrebbero essere chiamate solo dallo 651spazio utente attraverso la tabella syscall, ma non da nessun altro punto nel 652kernel. Se la nuova funzionalità è utile all'interno del kernel, per esempio 653dev'essere condivisa fra una vecchia e una nuova chiamata di sistema o 654dev'essere utilizzata da una chiamata di sistema e la sua variante compatibile, 655allora dev'essere implementata come una funzione di supporto 656(*helper function*) (per esempio ``ksys_xyzzy()``). Questa funzione potrà 657essere chiamata dallo *stub* (``sys_xyzzy()``), dalla variante compatibile 658(``compat_sys_xyzzy()``), e/o da altri parti del kernel. 659 660Sui sistemi x86 a 64-bit, a partire dalla versione v4.17 è un requisito 661fondamentale quello di non invocare chiamate di sistema all'interno del kernel. 662Esso usa una diversa convenzione per l'invocazione di chiamate di sistema dove 663``struct pt_regs`` viene decodificata al volo in una funzione che racchiude 664la chiamata di sistema la quale verrà eseguita successivamente. 665Questo significa che verranno passati solo i parametri che sono davvero 666necessari ad una specifica chiamata di sistema, invece che riempire ogni volta 6676 registri del processore con contenuti presi dallo spazio utente (potrebbe 668causare seri problemi nella sequenza di chiamate). 669 670Inoltre, le regole su come i dati possano essere usati potrebbero differire 671fra il kernel e l'utente. Questo è un altro motivo per cui invocare 672``sys_xyzzy()`` è generalmente una brutta idea. 673 674Eccezioni a questa regola vengono accettate solo per funzioni d'architetture 675che surclassano quelle generiche, per funzioni d'architettura di compatibilità, 676o per altro codice in arch/ 677 678 679Riferimenti e fonti 680------------------- 681 682 - Articolo di Michael Kerris su LWN sull'uso dell'argomento flags nelle 683 chiamate di sistema: https://lwn.net/Articles/585415/ 684 - Articolo di Michael Kerris su LWN su come gestire flag sconosciuti in 685 una chiamata di sistema: https://lwn.net/Articles/588444/ 686 - Articolo di Jake Edge su LWN che descrive i limiti degli argomenti a 64-bit 687 delle chiamate di sistema: https://lwn.net/Articles/311630/ 688 - Una coppia di articoli di David Drysdale che descrivono i dettagli del 689 percorso implementativo di una chiamata di sistema per la versione v3.14: 690 691 - https://lwn.net/Articles/604287/ 692 - https://lwn.net/Articles/604515/ 693 694 - Requisiti specifici alle architetture sono discussi nella pagina man 695 :manpage:`syscall(2)` : 696 http://man7.org/linux/man-pages/man2/syscall.2.html#NOTES 697 - Collezione di email di Linux Torvalds sui problemi relativi a ``ioctl()``: 698 http://yarchive.net/comp/linux/ioctl.html 699 - "Come non inventare interfacce del kernel", Arnd Bergmann, 700 http://www.ukuug.org/events/linux2007/2007/papers/Bergmann.pdf 701 - Articolo di Michael Kerris su LWN sull'evitare nuovi usi di CAP_SYS_ADMIN: 702 https://lwn.net/Articles/486306/ 703 - Raccomandazioni da Andrew Morton circa il fatto che tutte le informazioni 704 su una nuova chiamata di sistema dovrebbero essere contenute nello stesso 705 filone di discussione di email: https://lore.kernel.org/r/20140724144747.3041b208832bbdf9fbce5d96@linux-foundation.org 706 - Raccomandazioni da Michael Kerrisk circa il fatto che le nuove chiamate di 707 sistema dovrebbero avere una pagina man: https://lore.kernel.org/r/CAKgNAkgMA39AfoSoA5Pe1r9N+ZzfYQNvNPvcRN7tOvRb8+v06Q@mail.gmail.com 708 - Consigli da Thomas Gleixner sul fatto che il collegamento all'architettura 709 x86 dovrebbe avvenire in un *commit* differente: 710 https://lore.kernel.org/r/alpine.DEB.2.11.1411191249560.3909@nanos 711 - Consigli da Greg Kroah-Hartman circa la bontà d'avere una pagina man e un 712 programma di auto-verifica per le nuove chiamate di sistema: 713 https://lore.kernel.org/r/20140320025530.GA25469@kroah.com 714 - Discussione di Michael Kerrisk sulle nuove chiamate di sistema contro 715 le estensioni :manpage:`prctl(2)`: https://lore.kernel.org/r/CAHO5Pa3F2MjfTtfNxa8LbnkeeU8=YJ+9tDqxZpw7Gz59E-4AUg@mail.gmail.com 716 - Consigli da Ingo Molnar che le chiamate di sistema con più argomenti 717 dovrebbero incapsularli in una struttura che includa un argomento 718 *size* per garantire l'estensibilità futura: 719 https://lore.kernel.org/r/20150730083831.GA22182@gmail.com 720 - Un certo numero di casi strani emersi dall'uso (riuso) dei flag O_*: 721 722 - commit 75069f2b5bfb ("vfs: renumber FMODE_NONOTIFY and add to uniqueness 723 check") 724 - commit 12ed2e36c98a ("fanotify: FMODE_NONOTIFY and __O_SYNC in sparc 725 conflict") 726 - commit bb458c644a59 ("Safer ABI for O_TMPFILE") 727 728 - Discussion from Matthew Wilcox about restrictions on 64-bit arguments: 729 https://lore.kernel.org/r/20081212152929.GM26095@parisc-linux.org 730 - Raccomandazioni da Greg Kroah-Hartman sul fatto che i flag sconosciuti dovrebbero 731 essere controllati: https://lore.kernel.org/r/20140717193330.GB4703@kroah.com 732 - Raccomandazioni da Linus Torvalds che le chiamate di sistema x32 dovrebbero 733 favorire la compatibilità con le versioni a 64-bit piuttosto che quelle a 32-bit: 734 https://lore.kernel.org/r/CA+55aFxfmwfB7jbbrXxa=K7VBYPfAvmu3XOkGrLbB1UFjX1+Ew@mail.gmail.com 735 - Serie di patch che revisiona l'infrastruttura della tabella delle chiamate 736 di sistema per usare scripts/syscall.tbl su più architetture: 737 https://lore.kernel.org/lkml/20240704143611.2979589-1-arnd@kernel.org 738