← Documents Documentation/translations/it_IT/process/adding-syscalls.rst GitHub 원문 ↗

Linux 6.18.37 · Translations

새 system call 추가하기

새 system call의 대안과 확장 가능한 ABI, generic·x86·compat 구현, selftest·man page와 내부 helper 원칙을 설명합니다.

Source pathDocumentation/translations/it_IT/process/adding-syscalls.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

adding-syscalls.rst:1-643

영구 userspace ABI인 새 system call이 정말 필요한지부터 검토하고 flags·size field, file descriptor와 capability를 사용해 미래 확장과 보안을 설계하는 방법을 다룹니다.

Generic·x86·32-bit compat wiring, 특수 return path, audit와 selftest, man page, kernel 내부 helper 분리까지 제출에 필요한 구현·검증 절차를 정리합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
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
8 Aggiungere una nuova chiamata di sistema
9 ========================================
10
11 Questo documento descrive quello che è necessario sapere per aggiungere
12 nuove chiamate di sistema al kernel Linux; questo è da considerarsi come
13 un'aggiunta ai soliti consigli su come proporre nuove modifiche
14 :ref:`Documentation/translations/it_IT/process/submitting-patches.rst <it_submittingpatches>`.
15
16
17 Alternative alle chiamate di sistema
18 ------------------------------------
19
20 La prima considerazione da fare quando si aggiunge una nuova chiamata di
21 sistema è quella di valutare le alternative. Nonostante le chiamate di sistema
22 siano il punto di interazione fra spazio utente e kernel più tradizionale ed
23 ovvio, esistono altre possibilità - scegliete quella che meglio si adatta alle
24 vostra 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
63 Progettare l'API: pianificare le estensioni
64 -------------------------------------------
65
66 Una nuova chiamata di sistema diventerà parte dell'API del kernel, e
67 dev'essere supportata per un periodo indefinito. Per questo, è davvero
68 un'ottima idea quella di discutere apertamente l'interfaccia sulla lista
69 di discussione del kernel, ed è altrettanto importante pianificarne eventuali
70 estensioni future.
71
72 (Nella tabella delle chiamate di sistema sono disseminati esempi dove questo
73 non fu fatto, assieme ai corrispondenti aggiornamenti -
74 ``eventfd``/``eventfd2``, ``dup2``/``dup3``, ``inotify_init``/``inotify_init1``,
75 ``pipe``/``pipe2``, ``renameat``/``renameat2`` --quindi imparate dalla storia
76 del kernel e pianificate le estensioni fin dall'inizio)
77
78 Per semplici chiamate di sistema che accettano solo un paio di argomenti,
79 il modo migliore di permettere l'estensibilità è quello di includere un
80 argomento *flags* alla chiamata di sistema. Per assicurarsi che i programmi
81 dello spazio utente possano usare in sicurezza *flags* con diverse versioni
82 del kernel, verificate se *flags* contiene un qualsiasi valore sconosciuto,
83 in 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
90 Per chiamate di sistema più sofisticate che coinvolgono un numero più grande di
91 argomenti, il modo migliore è quello di incapsularne la maggior parte in una
92 struttura dati che verrà passata per puntatore. Questa struttura potrà
93 funzionare 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
102 Fintanto che un qualsiasi campo nuovo, diciamo ``param_4``, è progettato per
103 offrire il comportamento precedente quando vale zero, allora questo permetterà
104 di 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
114 Vedere :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
118 Progettare l'API: altre considerazioni
119 --------------------------------------
120
121 Se la vostra nuova chiamata di sistema permette allo spazio utente di fare
122 riferimento ad un oggetto del kernel, allora questa dovrebbe usare un
123 descrittore di file per accesso all'oggetto - non inventatevi nuovi tipi di
124 accesso da spazio utente quando il kernel ha già dei meccanismi e una semantica
125 ben definita per utilizzare i descrittori di file.
126
127 Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` ritorna un nuovo
128 descrittore di file, allora l'argomento *flags* dovrebbe includere un valore
129 equivalente a ``O_CLOEXEC`` per i nuovi descrittori. Questo rende possibile,
130 nello 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
133 eseguito (Comunque, resistete alla tentazione di riutilizzare il valore di
134 ``O_CLOEXEC`` dato che è specifico dell'architettura e fa parte di una
135 enumerazione di flag ``O_*`` che è abbastanza ricca).
136
137 Se la vostra nuova chiamata di sistema ritorna un nuovo descrittore di file,
138 dovreste considerare che significato avrà l'uso delle chiamate di sistema
139 della famiglia di :manpage:`poll(2)`. Rendere un descrittore di file pronto
140 per la lettura o la scrittura è il tipico modo del kernel per notificare lo
141 spazio utente circa un evento associato all'oggetto del kernel.
142
143 Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` ha un argomento
144 che è il percorso ad un file::
145
146 int sys_xyzzy(const char __user *path, ..., unsigned int flags);
147
148 dovreste anche considerare se non sia più appropriata una versione
149 :manpage:`xyzzyat(2)`::
150
151 int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags);
152
153 Questo permette più flessibilità su come lo spazio utente specificherà il file
154 in questione; in particolare, permette allo spazio utente di richiedere la
155 funzionalità su un descrittore di file già aperto utilizzando il *flag*
156 ``AT_EMPTY_PATH``, in pratica otterremmo gratuitamente l'operazione
157 :manpage:`fxyzzy(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
163 man :manpage:`openat(2)`; per un esempio di AT_EMPTY_PATH, leggere la pagina
164 man :manpage:`fstatat(2)`).
165
166 Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` prevede un parametro
167 per descrivere uno scostamento all'interno di un file, usate ``loff_t`` come
168 tipo cosicché scostamenti a 64-bit potranno essere supportati anche su
169 architetture a 32-bit.
170
171 Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` prevede l'uso di
172 funzioni 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
175 gestire la funzionalità associata, ma evitate la combinazione di diverse
176 funzionalità vagamente collegate dietro lo stesso bit, in quanto va contro il
177 principio di *capabilities* di separare i poteri di root. In particolare,
178 evitate di aggiungere nuovi usi al fin-troppo-generico privilegio
179 ``CAP_SYS_ADMIN``.
180
181 Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` manipola altri
182 processi oltre a quello chiamato, allora dovrebbe essere limitata (usando
183 la chiamata ``ptrace_may_access()``) di modo che solo un processo chiamante
184 con gli stessi permessi del processo in oggetto, o con i necessari privilegi,
185 possa manipolarlo.
186
187 Infine, state attenti che in alcune architetture non-x86 la vita delle chiamate
188 di sistema con argomenti a 64-bit viene semplificata se questi argomenti
189 ricadono in posizioni dispari (pratica, i parametri 1, 3, 5); questo permette
190 l'uso di coppie contigue di registri a 32-bit. (Questo non conta se gli
191 argomenti sono parte di una struttura dati che viene passata per puntatore).
192
193
194 Proporre l'API
195 --------------
196
197 Al fine di rendere le nuove chiamate di sistema di facile revisione, è meglio
198 che dividiate le modifiche i pezzi separati. Questi dovrebbero includere
199 almeno le seguenti voci in *commit* distinti (ognuno dei quali sarà descritto
200 più 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
213 Le proposte di nuove chiamate di sistema, come ogni altro modifica all'API del
214 kernel, deve essere sottomessa alla lista di discussione
215 linux-api@vger.kernel.org.
216
217
218 Implementazione di chiamate di sistema generiche
219 ------------------------------------------------
220
221 Il principale punto d'accesso alla vostra nuova chiamata di sistema
222 :manpage:`xyzzy(2)` verrà chiamato ``sys_xyzzy()``; ma, piuttosto che in modo
223 esplicito, lo aggiungerete tramite la macro ``SYSCALL_DEFINEn``. La 'n'
224 indica il numero di argomenti della chiamata di sistema; la macro ha come
225 argomento il nome della chiamata di sistema, seguito dalle coppie (tipo, nome)
226 per definire i suoi parametri. L'uso di questa macro permette di avere
227 i metadati della nuova chiamata di sistema disponibili anche per altri
228 strumenti.
229
230 Il nuovo punto d'accesso necessita anche del suo prototipo di funzione in
231 ``include/linux/syscalls.h``, marcato come asmlinkage di modo da abbinargli
232 il modo in cui quelle chiamate di sistema verranno invocate::
233
234 asmlinkage long sys_xyzzy(...);
235
236 Alcune architetture (per esempio x86) hanno le loro specifiche tabelle di
237 chiamate di sistema (syscall), ma molte altre architetture condividono una
238 tabella comune di syscall. Aggiungete alla lista generica la vostra nuova
239 chiamata 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
245 Aggiornate anche il contatore __NR_syscalls di modo che sia coerente con
246 l'aggiunta della nuove chiamate di sistema; va notato che se più di una nuova
247 chiamata di sistema viene aggiunga nella stessa finestra di sviluppo, il numero
248 della vostra nuova syscall potrebbe essere aggiustato al fine di risolvere i
249 conflitti.
250
251 Il file ``kernel/sys_ni.c`` fornisce le implementazioni *stub* di ripiego che
252 ritornano ``-ENOSYS``. Aggiungete la vostra nuova chiamata di sistema anche
253 qui::
254
255 COND_SYSCALL(xyzzy);
256
257 La vostra nuova funzionalità del kernel, e la chiamata di sistema che la
258 controlla, dovrebbero essere opzionali. Quindi, aggiungete un'opzione
259 ``CONFIG`` (solitamente in ``init/Kconfig``). Come al solito per le nuove
260 opzioni ``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
272 Per 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 Implementazione delle chiamate di sistema x86
282 ---------------------------------------------
283
284 Per collegare la vostra nuova chiamate di sistema alle piattaforme x86,
285 dovete aggiornate la tabella principale di syscall. Assumendo che la vostra
286 nuova chiamata di sistema non sia particolarmente speciale (vedere sotto),
287 dovete aggiungere un elemento *common* (per x86_64 e x32) in
288 arch/x86/entry/syscalls/syscall_64.tbl::
289
290 333 common xyzzy sys_xyzzy
291
292 e un elemento per *i386* ``arch/x86/entry/syscalls/syscall_32.tbl``::
293
294 380 i386 xyzzy sys_xyzzy
295
296 Ancora una volta, questi numeri potrebbero essere cambiati se generano
297 conflitti durante la finestra di integrazione.
298
299
300 Chiamate di sistema compatibili (generico)
301 ------------------------------------------
302
303 Per molte chiamate di sistema, la stessa implementazione a 64-bit può essere
304 invocata anche quando il programma in spazio utente è a 32-bit; anche se la
305 chiamata di sistema include esplicitamente un puntatore, questo viene gestito
306 in modo trasparente.
307
308 Tuttavia, ci sono un paio di situazione dove diventa necessario avere un
309 livello di gestione della compatibilità per risolvere le differenze di
310 dimensioni fra 32-bit e 64-bit.
311
312 Il primo caso è quando un kernel a 64-bit supporta anche programmi in spazio
313 utente a 32-bit, perciò dovrà ispezionare aree della memoria (``__user``) che
314 potrebbero contenere valori a 32-bit o a 64-bit. In particolar modo, questo
315 è necessario quando un argomento di una chiamata di sistema è:
316
317 - un puntatore ad un puntatore
318 - un puntatore ad una struttura dati contenente a sua volta un puntatore
319 ( ad esempio ``struct iovec __user *``)
320 - un puntatore ad un tipo intero di dimensione variabile (``time_t``,
321 ``off_t``, ``long``, ...)
322 - un puntatore ad una struttura dati contenente un tipo intero di dimensione
323 variabile.
324
325 Il secondo caso che richiede un livello di gestione della compatibilità è
326 quando uno degli argomenti di una chiamata a sistema è esplicitamente un tipo
327 a 64-bit anche su architetture a 32-bit, per esempio ``loff_t`` o ``__u64``.
328 In questo caso, un valore che arriva ad un kernel a 64-bit da un'applicazione
329 a 32-bit verrà diviso in due valori a 32-bit che dovranno essere riassemblati
330 in questo livello di compatibilità.
331
332 (Da notare che non serve questo livello di compatibilità per argomenti che
333 sono puntatori ad un tipo esplicitamente a 64-bit; per esempio, in
334 :manpage:`splice(2)` l'argomento di tipo ``loff_t __user *`` non necessita
335 di una chiamata di sistema ``compat_``)
336
337 La versione compatibile della nostra chiamata di sistema si chiamerà
338 ``compat_sys_xyzzy()``, e viene aggiunta utilizzando la macro
339 ``COMPAT_SYSCALL_DEFINEn()`` (simile a SYSCALL_DEFINEn). Questa versione
340 dell'implementazione è parte del kernel a 64-bit ma accetta parametri a 32-bit
341 che trasformerà secondo le necessità (tipicamente, la versione
342 ``compat_sys_`` converte questi valori nello loro corrispondente a 64-bit e
343 può chiamare la versione ``sys_`` oppure invocare una funzione che implementa
344 le parti comuni).
345
346 Il punto d'accesso *compat* deve avere il corrispondente prototipo di funzione
347 in ``include/linux/compat.h``, marcato come asmlinkage di modo da abbinargli
348 il modo in cui quelle chiamate di sistema verranno invocate::
349
350 asmlinkage long compat_sys_xyzzy(...);
351
352 Se la chiamata di sistema prevede una struttura dati organizzata in modo
353 diverso per sistemi a 32-bit e per quelli a 64-bit, diciamo
354 ``struct xyzzy_args``, allora il file d'intestazione
355 ``then the include/linux/compat.h`` deve includere la sua versione
356 *compatibile* (``struct compat_xyzzy_args``); ogni variabile con
357 dimensione variabile deve avere il proprio tipo ``compat_`` corrispondente
358 a quello in ``struct xyzzy_args``. La funzione ``compat_sys_xyzzy()``
359 può usare la struttura ``compat_`` per analizzare gli argomenti ricevuti
360 da una chiamata a 32-bit.
361
362 Per esempio, se avete i seguenti campi::
363
364 struct xyzzy_args {
365 const char __user *ptr;
366 __kernel_long_t varying_val;
367 u64 fixed_val;
368 /* ... */
369 };
370
371 nella struttura ``struct xyzzy_args``, allora la struttura
372 ``struct compat_xyzzy_args`` dovrebbe avere::
373
374 struct compat_xyzzy_args {
375 compat_uptr_t ptr;
376 compat_long_t varying_val;
377 u64 fixed_val;
378 /* ... */
379 };
380
381 La lista generica delle chiamate di sistema ha bisogno di essere
382 aggiustata al fine di permettere l'uso della versione *compatibile*;
383 la voce in ``include/uapi/asm-generic/unistd.h`` dovrebbero usare
384 ``__SC_COMP`` piuttosto di ``__SYSCALL``::
385
386 #define __NR_xyzzy 292
387 __SC_COMP(__NR_xyzzy, sys_xyzzy, compat_sys_xyzzy)
388
389 Riassumendo, vi serve:
390
391 - un ``COMPAT_SYSCALL_DEFINEn(xyzzy, ...)`` per il punto d'accesso
392 *compatibile*
393 - un prototipo in ``include/linux/compat.h``
394 - (se necessario) una struttura di compatibilità a 32-bit in
395 ``include/linux/compat.h``
396 - una voce ``__SC_COMP``, e non ``__SYSCALL``, in
397 ``include/uapi/asm-generic/unistd.h``
398
399 Compatibilità delle chiamate di sistema (x86)
400 ---------------------------------------------
401
402 Per collegare una chiamata di sistema, su un'architettura x86, con la sua
403 versione *compatibile*, è necessario aggiustare la voce nella tabella
404 delle syscall.
405
406 Per prima cosa, la voce in ``arch/x86/entry/syscalls/syscall_32.tbl`` prende
407 un argomento aggiuntivo per indicare che un programma in spazio utente
408 a 32-bit, eseguito su un kernel a 64-bit, dovrebbe accedere tramite il punto
409 d'accesso compatibile::
410
411 380 i386 xyzzy sys_xyzzy __ia32_compat_sys_xyzzy
412
413 Secondo, dovete capire cosa dovrebbe succedere alla nuova chiamata di sistema
414 per la versione dell'ABI x32. Qui C'è una scelta da fare: gli argomenti
415 possono corrisponde alla versione a 64-bit o a quella a 32-bit.
416
417 Se c'è un puntatore ad un puntatore, la decisione è semplice: x32 è ILP32,
418 quindi gli argomenti dovrebbero corrispondere a quelli a 32-bit, e la voce in
419 ``arch/x86/entry/syscalls/syscall_64.tbl`` sarà divisa cosicché i programmi
420 x32 eseguano la chiamata *compatibile*::
421
422 333 64 xyzzy sys_xyzzy
423 ...
424 555 x32 xyzzy __x32_compat_sys_xyzzy
425
426 Se non ci sono puntatori, allora è preferibile riutilizzare la chiamata di
427 sistema a 64-bit per l'ABI x32 (e di conseguenza la voce in
428 arch/x86/entry/syscalls/syscall_64.tbl rimane immutata).
429
430 In ambo i casi, dovreste verificare che i tipi usati dagli argomenti
431 abbiano un'esatta corrispondenza da x32 (-mx32) al loro equivalente a
432 32-bit (-m32) o 64-bit (-m64).
433
434
435 Chiamate di sistema che ritornano altrove
436 -----------------------------------------
437
438 Nella maggior parte delle chiamate di sistema, al termine della loro
439 esecuzione, i programmi in spazio utente riprendono esattamente dal punto
440 in cui si erano interrotti -- quindi dall'istruzione successiva, con lo
441 stesso *stack* e con la maggior parte del registri com'erano stati
442 lasciati prima della chiamata di sistema, e anche con la stessa memoria
443 virtuale.
444
445 Tuttavia, alcune chiamata di sistema fanno le cose in modo differente.
446 Potrebbero ritornare ad un punto diverso (``rt_sigreturn``) o cambiare
447 la memoria in spazio utente (``fork``/``vfork``/``clone``) o perfino
448 l'architettura del programma (``execve``/``execveat``).
449
450 Per permettere tutto ciò, l'implementazione nel kernel di questo tipo di
451 chiamate di sistema potrebbero dover salvare e ripristinare registri
452 aggiuntivi nello *stack* del kernel, permettendo così un controllo completo
453 su dove e come l'esecuzione dovrà continuare dopo l'esecuzione della
454 chiamata di sistema.
455
456 Queste saranno specifiche per ogni architettura, ma tipicamente si definiscono
457 dei punti d'accesso in *assembly* per salvare/ripristinare i registri
458 aggiuntivi e quindi chiamare il vero punto d'accesso per la chiamata di
459 sistema.
460
461 Per l'architettura x86_64, questo è implementato come un punto d'accesso
462 ``stub_xyzzy`` in ``arch/x86/entry/entry_64.S``, e la voce nella tabella
463 di syscall (``arch/x86/entry/syscalls/syscall_64.tbl``) verrà corretta di
464 conseguenza::
465
466 333 common xyzzy stub_xyzzy
467
468 L'equivalente per programmi a 32-bit eseguiti su un kernel a 64-bit viene
469 normalmente chiamato ``stub32_xyzzy`` e implementato in
470 ``arch/x86/entry/entry_64_compat.S`` con la corrispondente voce nella tabella
471 di syscall ``arch/x86/entry/syscalls/syscall_32.tbl`` corretta nel
472 seguente modo::
473
474 380 i386 xyzzy sys_xyzzy stub32_xyzzy
475
476 Se una chiamata di sistema necessita di un livello di compatibilità (come
477 nella sezione precedente), allora la versione ``stub32_`` deve invocare
478 la versione ``compat_sys_`` piuttosto che quella nativa a 64-bit. In aggiunta,
479 se l'implementazione dell'ABI x32 è diversa da quella x86_64, allora la sua
480 voce nella tabella di syscall dovrà chiamare uno *stub* che invoca la versione
481 ``compat_sys_``,
482
483 Per completezza, sarebbe carino impostare una mappatura cosicché
484 *user-mode* Linux (UML) continui a funzionare -- la sua tabella di syscall
485 farà riferimento a stub_xyzzy, ma UML non include l'implementazione
486 in ``arch/x86/entry/entry_64.S`` (perché UML simula i registri eccetera).
487 Correggerlo è semplice, basta aggiungere una #define in
488 ``arch/x86/um/sys_call_table_64.c``::
489
490 #define stub_xyzzy sys_xyzzy
491
492
493 Altri dettagli
494 --------------
495
496 La maggior parte dei kernel tratta le chiamate di sistema allo stesso modo,
497 ma possono esserci rare eccezioni per le quali potrebbe essere necessario
498 l'aggiornamento della vostra chiamata di sistema.
499
500 Il sotto-sistema di controllo (*audit subsystem*) è uno di questi casi
501 speciali; esso include (per architettura) funzioni che classificano alcuni
502 tipi di chiamate di sistema -- in particolare apertura dei file
503 (``open``/``openat``), esecuzione dei programmi (``execve``/``exeveat``)
504 oppure multiplatori di socket (``socketcall``). Se la vostra nuova chiamata
505 di sistema è simile ad una di queste, allora il sistema di controllo dovrebbe
506 essere aggiornato.
507
508 Più in generale, se esiste una chiamata di sistema che è simile alla vostra,
509 vale la pena fare una ricerca con ``grep`` su tutto il kernel per la chiamata
510 di sistema esistente per verificare che non ci siano altri casi speciali.
511
512
513 Verifica
514 --------
515
516 Una nuova chiamata di sistema dev'essere, ovviamente, provata; è utile fornire
517 ai revisori un programma in spazio utente che mostri l'uso della chiamata di
518 sistema. Un buon modo per combinare queste cose è quello di aggiungere un
519 semplice programma di auto-verifica in una nuova cartella in
520 ``tools/testing/selftests/``.
521
522 Per una nuova chiamata di sistema, ovviamente, non ci sarà alcuna funzione
523 in libc e quindi il programma di verifica dovrà invocarla usando ``syscall()``;
524 inoltre, se la nuova chiamata di sistema prevede un nuova struttura dati
525 visibile in spazio utente, il file d'intestazione necessario dev'essere
526 installato al fine di compilare il programma.
527
528 Assicuratevi che il programma di auto-verifica possa essere eseguito
529 correttamente su tutte le architetture supportate. Per esempio, verificate che
530 funzioni quando viene compilato per x86_64 (-m64), x86_32 (-m32) e x32 (-mx32).
531
532 Al fine di una più meticolosa ed estesa verifica della nuova funzionalità,
533 dovreste considerare l'aggiunta di nuove verifica al progetto 'Linux Test',
534 oppure al progetto xfstests per cambiamenti relativi al filesystem.
535
536 - https://linux-test-project.github.io/
537 - git://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git
538
539
540 Pagine man
541 ----------
542
543 Tutte le nuove chiamate di sistema dovrebbero avere una pagina man completa,
544 idealmente usando i marcatori groff, ma anche il puro testo può andare. Se
545 state usando groff, è utile che includiate nella email di presentazione una
546 versione già convertita in formato ASCII: semplificherà la vita dei revisori.
547
548 Le pagine man dovrebbero essere in copia-conoscenza verso
549 linux-man@vger.kernel.org
550 Per maggiori dettagli, leggere
551 https://www.kernel.org/doc/man-pages/patches.html
552
553
554 Non invocate chiamate di sistema dal kernel
555 -------------------------------------------
556
557 Le chiamate di sistema sono, come già detto prima, punti di interazione fra
558 lo spazio utente e il kernel. Perciò, le chiamate di sistema come
559 ``sys_xyzzy()`` o ``compat_sys_xyzzy()`` dovrebbero essere chiamate solo dallo
560 spazio utente attraverso la tabella syscall, ma non da nessun altro punto nel
561 kernel. Se la nuova funzionalità è utile all'interno del kernel, per esempio
562 dev'essere condivisa fra una vecchia e una nuova chiamata di sistema o
563 dev'essere utilizzata da una chiamata di sistema e la sua variante compatibile,
564 allora dev'essere implementata come una funzione di supporto
565 (*helper function*) (per esempio ``ksys_xyzzy()``). Questa funzione potrà
566 essere chiamata dallo *stub* (``sys_xyzzy()``), dalla variante compatibile
567 (``compat_sys_xyzzy()``), e/o da altri parti del kernel.
568
569 Sui sistemi x86 a 64-bit, a partire dalla versione v4.17 è un requisito
570 fondamentale quello di non invocare chiamate di sistema all'interno del kernel.
571 Esso usa una diversa convenzione per l'invocazione di chiamate di sistema dove
572 ``struct pt_regs`` viene decodificata al volo in una funzione che racchiude
573 la chiamata di sistema la quale verrà eseguita successivamente.
574 Questo significa che verranno passati solo i parametri che sono davvero
575 necessari ad una specifica chiamata di sistema, invece che riempire ogni volta
576 6 registri del processore con contenuti presi dallo spazio utente (potrebbe
577 causare seri problemi nella sequenza di chiamate).
578
579 Inoltre, le regole su come i dati possano essere usati potrebbero differire
580 fra il kernel e l'utente. Questo è un altro motivo per cui invocare
581 ``sys_xyzzy()`` è generalmente una brutta idea.
582
583 Eccezioni a questa regola vengono accettate solo per funzioni d'architetture
584 che surclassano quelle generiche, per funzioni d'architettura di compatibilità,
585 o per altro codice in arch/
586
587
588 Riferimenti e fonti
589 -------------------
590
591 - Articolo di Michael Kerris su LWN sull'uso dell'argomento flags nelle
592 chiamate di sistema: https://lwn.net/Articles/585415/
593 - Articolo di Michael Kerris su LWN su come gestire flag sconosciuti in
594 una chiamata di sistema: https://lwn.net/Articles/588444/
595 - Articolo di Jake Edge su LWN che descrive i limiti degli argomenti a 64-bit
596 delle chiamate di sistema: https://lwn.net/Articles/311630/
597 - Una coppia di articoli di David Drysdale che descrivono i dettagli del
598 percorso implementativo di una chiamata di sistema per la versione v3.14:
599
600 - https://lwn.net/Articles/604287/
601 - https://lwn.net/Articles/604515/
602
603 - Requisiti specifici alle architetture sono discussi nella pagina man
604 :manpage:`syscall(2)` :
605 http://man7.org/linux/man-pages/man2/syscall.2.html#NOTES
606 - Collezione di email di Linux Torvalds sui problemi relativi a ``ioctl()``:
607 http://yarchive.net/comp/linux/ioctl.html
608 - "Come non inventare interfacce del kernel", Arnd Bergmann,
609 http://www.ukuug.org/events/linux2007/2007/papers/Bergmann.pdf
610 - Articolo di Michael Kerris su LWN sull'evitare nuovi usi di CAP_SYS_ADMIN:
611 https://lwn.net/Articles/486306/
612 - Raccomandazioni da Andrew Morton circa il fatto che tutte le informazioni
613 su una nuova chiamata di sistema dovrebbero essere contenute nello stesso
614 filone di discussione di email: https://lore.kernel.org/r/20140724144747.3041b208832bbdf9fbce5d96@linux-foundation.org
615 - Raccomandazioni da Michael Kerrisk circa il fatto che le nuove chiamate di
616 sistema dovrebbero avere una pagina man: https://lore.kernel.org/r/CAKgNAkgMA39AfoSoA5Pe1r9N+ZzfYQNvNPvcRN7tOvRb8+v06Q@mail.gmail.com
617 - Consigli da Thomas Gleixner sul fatto che il collegamento all'architettura
618 x86 dovrebbe avvenire in un *commit* differente:
619 https://lore.kernel.org/r/alpine.DEB.2.11.1411191249560.3909@nanos
620 - Consigli da Greg Kroah-Hartman circa la bontà d'avere una pagina man e un
621 programma di auto-verifica per le nuove chiamate di sistema:
622 https://lore.kernel.org/r/20140320025530.GA25469@kroah.com
623 - Discussione di Michael Kerrisk sulle nuove chiamate di sistema contro
624 le estensioni :manpage:`prctl(2)`: https://lore.kernel.org/r/CAHO5Pa3F2MjfTtfNxa8LbnkeeU8=YJ+9tDqxZpw7Gz59E-4AUg@mail.gmail.com
625 - Consigli da Ingo Molnar che le chiamate di sistema con più argomenti
626 dovrebbero incapsularli in una struttura che includa un argomento
627 *size* per garantire l'estensibilità futura:
628 https://lore.kernel.org/r/20150730083831.GA22182@gmail.com
629 - Un certo numero di casi strani emersi dall'uso (riuso) dei flag O_*:
630
631 - commit 75069f2b5bfb ("vfs: renumber FMODE_NONOTIFY and add to uniqueness
632 check")
633 - commit 12ed2e36c98a ("fanotify: FMODE_NONOTIFY and __O_SYNC in sparc
634 conflict")
635 - commit bb458c644a59 ("Safer ABI for O_TMPFILE")
636
637 - Discussion from Matthew Wilcox about restrictions on 64-bit arguments:
638 https://lore.kernel.org/r/20081212152929.GM26095@parisc-linux.org
639 - Raccomandazioni da Greg Kroah-Hartman sul fatto che i flag sconosciuti dovrebbero
640 essere controllati: https://lore.kernel.org/r/20140717193330.GB4703@kroah.com
641 - Raccomandazioni da Linus Torvalds che le chiamate di sistema x32 dovrebbero
642 favorire la compatibilità con le versioni a 64-bit piuttosto che quelle a 32-bit:
643 https://lore.kernel.org/r/CA+55aFxfmwfB7jbbrXxa=K7VBYPfAvmu3XOkGrLbB1UFjX1+Ew@mail.gmail.com
644

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

system call 대신 쓸 수 있는 interface

1-62

이 문서는 Documentation/process/submitting-patches.rst의 일반적인 제출 지침에 더해 Linux kernel에 새 system call을 추가할 때 필요한 사항을 설명한다.

가장 먼저 검토할 것은 system call이 아닌 다른 interface가 더 적합한지다. System call은 userspace와 kernel이 상호 작용하는 가장 전통적이고 분명한 지점이지만 유일한 방법은 아니므로 interface 성격에 가장 잘 맞는 방식을 선택해야 한다.

Filesystem 또는 device

관련 operation을 filesystem-like object로 표현할 수 있다면 새 filesystem이나 device를 만드는 편이 더 적절할 수 있다. 이 방식은 기능을 main kernel에 built-in으로 넣지 않고 kernel module로 캡슐화하기도 쉽다.

Kernel이 어떤 사건의 발생을 userspace에 알리는 기능이라면 관련 object의 새 file descriptor를 반환하게 만들 수 있다. 그러면 userspace는 poll/select/epoll로 notification을 받을 수 있다. 반면 read(2)나 write(2) 형태로 대응되지 않는 operation은 ioctl(2) request로 구현해야 하므로 API가 다소 불투명해질 수 있다.

sysfs, /proc, fcntl(2), prctl(2)

Runtime system information을 노출하기만 한다면 Documentation/filesystems/sysfs.rst가 설명하는 sysfs의 새 node나 /proc filesystem이 더 적절할 수 있다. 다만 이 mechanism에 접근하려면 해당 filesystem이 mount되어 있어야 하며 namespaced, sandboxed, chrooted environment에서는 그렇지 않을 수 있다. Debugfs는 production userspace interface로 간주되지 않으므로 API를 추가해서는 안 된다.

특정 file이나 file descriptor에만 적용되는 operation이면 fcntl(2) command option을 추가하는 방안이 더 적절할 수 있다. 그러나 fcntl(2)은 많은 복잡성을 감추는 multiplexing system call이므로 기존 fcntl(2) 기능과 매우 유사하거나 file descriptor 관련 단순 flag를 얻고 설정하는 정도의 기능에 가장 알맞다.

특정 task나 process에 적용되는 operation이면 prctl(2) command option을 추가할 수 있다. prctl(2) 역시 복잡한 multiplexor이므로 기존 prctl() command와 거의 같은 기능이나 process 관련 단순 flag의 get/set에 한정하는 편이 좋다.

새 system call은 영구 user-space ABI가 되므로 먼저 filesystem·device, sysfs나 `/proc`, `fcntl(2)`, `prctl(2)` 같은 기존 interface가 더 자연스러운지 검토합니다. Event notification은 file descriptor를 반환해 `poll`·`select`·`epoll`과 결합할 수 있습니다.

Production interface를 debugfs에 두지 않으며, namespace·sandbox·chroot 환경에서 sysfs나 `/proc`가 항상 mount된다고 가정해서도 안 됩니다. Multiplexor인 `fcntl`과 `prctl`은 기존 operation과 밀접하거나 단순 flag를 다룰 때만 확장하는 편이 좋습니다.

.. include:: ../disclaimer-ita.rst

:Original: :ref:`Documentation/process/adding-syscalls.rst <addsyscalls>`
:Translator: Federico Vaga <federico.vaga@vaga.pv.it>

.. _it_addsyscalls:

Aggiungere una nuova chiamata di sistema
========================================

Questo documento descrive quello che è necessario sapere per aggiungere
nuove chiamate di sistema al kernel Linux; questo è da considerarsi come
un'aggiunta ai soliti consigli su come proporre nuove modifiche
:ref:`Documentation/translations/it_IT/process/submitting-patches.rst <it_submittingpatches>`.


Alternative alle chiamate di sistema
------------------------------------

La prima considerazione da fare quando si aggiunge una nuova chiamata di
sistema è quella di valutare le alternative.  Nonostante le chiamate di sistema
siano il punto di interazione fra spazio utente e kernel più tradizionale ed
ovvio, esistono altre possibilità - scegliete quella che meglio si adatta alle
vostra interfaccia.

 - Se le operazioni coinvolte possono rassomigliare a quelle di un filesystem,
   allora potrebbe avere molto più senso la creazione di un nuovo filesystem o
   dispositivo.  Inoltre, questo rende più facile incapsulare la nuova
   funzionalità in un modulo kernel piuttosto che essere sviluppata nel cuore
   del kernel.

     - Se la nuova funzionalità prevede operazioni dove il kernel notifica
       lo spazio utente su un avvenimento, allora restituire un descrittore
       di file all'oggetto corrispondente permette allo spazio utente di
       utilizzare ``poll``/``select``/``epoll`` per ricevere quelle notifiche.
     - Tuttavia, le operazioni che non si sposano bene con operazioni tipo
       :manpage:`read(2)`/:manpage:`write(2)` dovrebbero essere implementate
       come chiamate :manpage:`ioctl(2)`, il che potrebbe portare ad un'API in
       un qualche modo opaca.

 - Se dovete esporre solo delle informazioni sul sistema, un nuovo nodo in
   sysfs (vedere ``Documentation/filesystems/sysfs.rst``) o
   in procfs potrebbe essere sufficiente.  Tuttavia, l'accesso a questi
   meccanismi richiede che il filesystem sia montato, il che potrebbe non
   essere sempre vero (per esempio, in ambienti come namespace/sandbox/chroot).
   Evitate d'aggiungere nuove API in debugfs perché questo non viene
   considerata un'interfaccia di 'produzione' verso lo spazio utente.
 - Se l'operazione è specifica ad un particolare file o descrittore, allora
   potrebbe essere appropriata l'aggiunta di un comando :manpage:`fcntl(2)`.
   Tuttavia, :manpage:`fcntl(2)` è una chiamata di sistema multiplatrice che
   nasconde una notevole complessità, quindi è ottima solo quando la nuova
   funzione assomiglia a quelle già esistenti in :manpage:`fcntl(2)`, oppure
   la nuova funzionalità è veramente semplice (per esempio, leggere/scrivere
   un semplice flag associato ad un descrittore di file).
 - Se l'operazione è specifica ad un particolare processo, allora
   potrebbe essere appropriata l'aggiunta di un comando :manpage:`prctl(2)`.
   Come per :manpage:`fcntl(2)`, questa chiamata di sistema è un complesso
   multiplatore quindi è meglio usarlo per cose molto simili a quelle esistenti
   nel comando ``prctl`` oppure per leggere/scrivere un semplice flag relativo
   al processo.

flags와 size field로 미래 확장 설계

63-117

새 system call은 kernel API의 일부가 되며 사실상 무기한 지원해야 한다. 따라서 interface를 kernel mailing list에서 명시적으로 논의하고 처음부터 향후 확장을 계획하는 것이 중요하다.

Syscall table에는 확장을 미리 고려하지 않아 후속 system call이 생긴 역사적 사례가 많다. eventfd/eventfd2, dup2/dup3, inotify_init/inotify_init1, pipe/pipe2, renameat/renameat2가 그 예다. Kernel의 역사를 보고 처음부터 확장 지점을 설계해야 한다.

Argument가 적으면 flags를 둔다

Argument가 두어 개뿐인 단순한 system call은 향후 확장을 위해 flags argument를 두는 방식이 선호된다. 서로 다른 kernel version에서 userspace program이 flag를 안전하게 쓰게 하려면 알려지지 않은 bit가 있는지 검사하고, 있으면 EINVAL로 system call을 거부한다.

if (flags & ~(THING_FLAG1 | THING_FLAG2 | THING_FLAG3))
    return -EINVAL;

아직 정의된 flag가 하나도 없다면 flags argument가 0인지 검사한다.

Argument가 많으면 size field가 있는 struct를 쓴다

Argument가 많은 복잡한 system call은 대부분의 argument를 structure에 넣고 pointer로 전달하는 방식이 선호된다. Structure 안에 size argument를 두면 미래의 field 추가를 처리할 수 있다.

struct xyzzy_params {
    u32 size; /* userspace sets p->size = sizeof(struct xyzzy_params) */
    u32 param_1;
    u64 param_2;
    u64 param_3;
};

나중에 추가하는 param_4 같은 field의 0 값이 과거 동작을 뜻하도록 설계하면 양방향 version mismatch를 모두 처리할 수 있다.

  • 새 userspace program이 오래된 kernel을 호출할 때: kernel이 알고 있는 structure 크기 너머의 memory가 모두 0인지 검사한다. 사실상 param_4 == 0을 확인하는 셈이다.
  • 오래된 userspace program이 새 kernel을 호출할 때: kernel은 작은 structure instance를 0으로 확장해 사실상 param_4 = 0으로 만든다.

이 pattern의 실제 예는 perf_event_open(2)과 kernel/events/core.c의 perf_copy_attr()에서 볼 수 있다.

Argument가 적은 call에는 `flags`를 두고 알려지지 않은 bit가 하나라도 있으면 `EINVAL`로 거부합니다. 아직 정의된 flag가 없어도 0인지 검사하면 미래 kernel과 과거 userspace의 의미 충돌을 막을 수 있습니다.

Argument가 많으면 `size` field를 첫 부분에 둔 structure를 pointer로 전달합니다. 새 field의 0 값이 과거 동작을 뜻하게 만들면 새 program이 오래된 kernel을 호출하거나 오래된 program이 새 kernel을 호출하는 양방향 version mismatch를 안전하게 처리할 수 있습니다.

확장 가능한 ABI 선택
형태확장 규칙
작은 argument 집합flags를 두고 unknown bit를 EINVAL로 거부
큰 argument 집합size가 있는 struct를 pointer로 전달
새 struct field0일 때 이전 version과 같은 동작

Argument 수와 향후 확장 방식에 따른 권장 pattern입니다.

Progettare l'API: pianificare le estensioni
-------------------------------------------

Una nuova chiamata di sistema diventerà parte dell'API del kernel, e
dev'essere supportata per un periodo indefinito.  Per questo, è davvero
un'ottima idea quella di discutere apertamente l'interfaccia sulla lista
di discussione del kernel, ed è altrettanto importante pianificarne eventuali
estensioni future.

(Nella tabella delle chiamate di sistema sono disseminati esempi dove questo
non fu fatto, assieme ai corrispondenti aggiornamenti -
``eventfd``/``eventfd2``, ``dup2``/``dup3``, ``inotify_init``/``inotify_init1``,
``pipe``/``pipe2``, ``renameat``/``renameat2`` --quindi imparate dalla storia
del kernel e pianificate le estensioni fin dall'inizio)

Per semplici chiamate di sistema che accettano solo un paio di argomenti,
il modo migliore di permettere l'estensibilità è quello di includere un
argomento *flags* alla chiamata di sistema.  Per assicurarsi che i programmi
dello spazio utente possano usare in sicurezza *flags* con diverse versioni
del kernel, verificate se *flags* contiene un qualsiasi valore sconosciuto,
in qual caso rifiutate la chiamata di sistema (con ``EINVAL``)::

    if (flags & ~(THING_FLAG1 | THING_FLAG2 | THING_FLAG3))
        return -EINVAL;

(Se *flags* non viene ancora utilizzato, verificate che l'argomento sia zero)

Per chiamate di sistema più sofisticate che coinvolgono un numero più grande di
argomenti, il modo migliore è quello di incapsularne la maggior parte in una
struttura dati che verrà passata per puntatore.  Questa struttura potrà
funzionare con future estensioni includendo un campo *size*::

    struct xyzzy_params {
        u32 size; /* userspace sets p->size = sizeof(struct xyzzy_params) */
        u32 param_1;
        u64 param_2;
        u64 param_3;
    };

Fintanto che un qualsiasi campo nuovo, diciamo ``param_4``, è progettato per
offrire il comportamento precedente quando vale zero, allora questo permetterà
di gestire un conflitto di versione in entrambe le direzioni:

 - un vecchio kernel può gestire l'accesso di una versione moderna di un
   programma in spazio utente verificando che la memoria oltre la dimensione
   della struttura dati attesa sia zero (in pratica verificare che
   ``param_4 == 0``).
 - un nuovo kernel può gestire l'accesso di una versione vecchia di un
   programma in spazio utente estendendo la struttura dati con zeri (in pratica
   ``param_4 = 0``).

Vedere :manpage:`perf_event_open(2)` e la funzione ``perf_copy_attr()`` (in
``kernel/events/core.c``) per un esempio pratico di questo approccio.

file descriptor·pathname·권한과 proposal 구성

118-217

새 system call이 userspace에서 kernel object를 가리키게 한다면 그 object handle로 file descriptor를 사용해야 한다. Kernel에 file descriptor를 위한 mechanism과 잘 정의된 semantics가 이미 있으므로 새로운 userspace object handle type을 만들지 않는다.

새 FD와 close-on-exec

새 xyzzy(2)가 file descriptor를 반환한다면 flags argument에는 새 FD에 O_CLOEXEC를 설정한 것과 같은 값을 포함해야 한다. 그래야 xyzzy() 반환 뒤 fcntl(fd, F_SETFD, FD_CLOEXEC)를 호출하기 전의 timing window를 없앨 수 있다. 이 window에서 다른 thread가 예기치 않게 fork()와 execve()를 수행하면 descriptor가 exec된 program으로 새어 나갈 수 있다.

실제 O_CLOEXEC 상수 값을 그대로 재사용하려는 유혹은 피한다. 이 값은 architecture-specific이고 이미 상당히 가득 찬 O_* flag numbering space의 일부다.

새 FD를 반환한다면 그 descriptor에 poll(2) 계열 system call을 적용했을 때의 의미도 설계해야 한다. FD를 read-ready 또는 write-ready로 만드는 것은 해당 kernel object에서 event가 발생했음을 kernel이 userspace에 알리는 일반적인 방법이다.

Pathname API는 *at 형태를 검토한다

xyzzy(2)가 filename argument를 받는다면 xyzzyat(2) 형태가 더 적절한지 검토한다.

int sys_xyzzy(const char __user *path, ..., unsigned int flags);
int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags);

xyzzyat(2)는 userspace가 대상 file을 지정하는 방법을 더 유연하게 만든다. 특히 AT_EMPTY_PATH를 사용하면 이미 open한 file descriptor에 기능을 적용할 수 있어 사실상 fxyzzy(3) operation까지 별도 system call 없이 얻는다.

xyzzyat(AT_FDCWD, path, ..., 0) == xyzzy(path, ...)
xyzzyat(fd, "", ..., AT_EMPTY_PATH) == fxyzzy(fd, ...)

*at() call의 근거는 openat(2), AT_EMPTY_PATH 예는 fstatat(2) man page에서 확인할 수 있다.

Offset, privilege와 target process

File 내부 offset을 나타내는 parameter는 32-bit architecture에서도 64-bit offset을 지원하도록 loff_t를 사용한다.

Privileged functionality는 capabilities(7)에 설명된 적절한 Linux capability bit로 통제하고 capable()로 검사한다. 관련 기능을 다스리는 기존 capability bit를 선택하되, root 권한을 나누려는 capability의 목적을 해치지 않도록 느슨하게 관련된 기능을 하나의 bit에 지나치게 묶지 않는다. 특히 이미 지나치게 일반적인 CAP_SYS_ADMIN의 새 사용은 피한다.

호출 process가 아닌 다른 process를 조작하는 system call은 ptrace_may_access()로 제한한다. Target process와 같은 permission을 가진 caller 또는 필요한 capability가 있는 caller만 target을 조작할 수 있어야 한다.

일부 non-x86 architecture는 명시적인 64-bit parameter가 홀수 번째 argument, 즉 1·3·5번에 있을 때 연속된 32-bit register 두 개를 사용하기 쉽다. Argument가 pointer로 전달되는 structure 안에 있다면 이 고려 사항은 적용되지 않는다.

새 system call을 쉽게 review할 수 있도록 patchset을 독립된 묶음으로 나누는 것이 좋다. 최소한 다음 항목은 서로 다른 commit이어야 한다.

  • System call core implementation, prototype, generic numbering, Kconfig 변경, fallback stub implementation
  • 특정 architecture의 wiring. 보통 x86이며 x86_64, x86_32, x32를 모두 포함한다.
  • tools/testing/selftests/ 아래 selftest로 작성한 userspace 사용 예
  • Cover letter에 plain text로 넣거나 별도 man-pages repository patch로 제출하는 새 system call의 draft man page

Kernel API의 다른 변경과 마찬가지로 새 system call proposal은 항상 linux-api@vger.kernel.org를 CC해야 한다.

새 system call patchset의 검토 단위
Core implementation + generic ABIArchitecture wiringUserspace selftestDraft man pagelinux-api@vger.kernel.org review

Core API와 architecture wiring, userspace 검증, 문서를 분리하면 각 책임과 review 범위가 분명해진다.

Kernel object handle에는 새 종류를 만들지 말고 file descriptor를 사용합니다. 새 FD를 반환한다면 atomic close-on-exec flag와 `poll(2)` 의미를 설계하고 실제 architecture-specific `O_CLOEXEC` 값은 임의로 재사용하지 않습니다.

Path를 받는 call은 `*at` 형태와 `AT_EMPTY_PATH`를 검토하고 file offset에는 `loff_t`를 씁니다. Privileged operation은 적절한 capability와 `capable()`로 제한하되 `CAP_SYS_ADMIN`에 무관한 권한을 계속 추가하지 않으며, 다른 process 조작은 `ptrace_may_access()`로 검사합니다.

Patchset은 core implementation·generic ABI, x86 wiring, `tools/testing/selftests/` selftest, draft man page를 독립 commit으로 나눕니다. 새 kernel API 제안은 `linux-api@vger.kernel.org`에 보내 관련 설계와 userspace 영향을 한 thread에서 review받습니다.

Progettare l'API: altre considerazioni
--------------------------------------

Se la vostra nuova chiamata di sistema permette allo spazio utente di fare
riferimento ad un oggetto del kernel, allora questa dovrebbe usare un
descrittore di file per accesso all'oggetto - non inventatevi nuovi tipi di
accesso da spazio utente quando il kernel ha già dei meccanismi e una semantica
ben definita per utilizzare i descrittori di file.

Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` ritorna un nuovo
descrittore di file, allora l'argomento *flags* dovrebbe includere un valore
equivalente a ``O_CLOEXEC`` per i nuovi descrittori.  Questo rende possibile,
nello spazio utente, la chiusura della finestra temporale fra le chiamate a
``xyzzy()`` e ``fcntl(fd, F_SETFD, FD_CLOEXEC)``, dove un inaspettato
``fork()`` o ``execve()`` potrebbe trasferire il descrittore al programma
eseguito (Comunque, resistete alla tentazione di riutilizzare il valore di
``O_CLOEXEC`` dato che è specifico dell'architettura e fa parte di una
enumerazione di flag ``O_*`` che è abbastanza ricca).

Se la vostra nuova chiamata di sistema ritorna un nuovo descrittore di file,
dovreste considerare che significato avrà l'uso delle chiamate di sistema
della famiglia di :manpage:`poll(2)`. Rendere un descrittore di file pronto
per la lettura o la scrittura è il tipico modo del kernel per notificare lo
spazio utente circa un evento associato all'oggetto del kernel.

Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` ha un argomento
che è il percorso ad un file::

    int sys_xyzzy(const char __user *path, ..., unsigned int flags);

dovreste anche considerare se non sia più appropriata una versione
:manpage:`xyzzyat(2)`::

    int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags);

Questo permette più flessibilità su come lo spazio utente specificherà il file
in questione; in particolare, permette allo spazio utente di richiedere la
funzionalità su un descrittore di file già aperto utilizzando il *flag*
``AT_EMPTY_PATH``, in pratica otterremmo gratuitamente l'operazione
:manpage:`fxyzzy(3)`::

 - xyzzyat(AT_FDCWD, path, ..., 0) is equivalent to xyzzy(path,...)
 - xyzzyat(fd, "", ..., AT_EMPTY_PATH) is equivalent to fxyzzy(fd, ...)

(Per maggiori dettagli sulla logica delle chiamate \*at(), leggete la pagina
man :manpage:`openat(2)`; per un esempio di AT_EMPTY_PATH, leggere la pagina
man :manpage:`fstatat(2)`).

Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` prevede un parametro
per descrivere uno scostamento all'interno di un file, usate ``loff_t`` come
tipo cosicché scostamenti a 64-bit potranno essere supportati anche su
architetture a 32-bit.

Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` prevede l'uso di
funzioni riservate, allora dev'essere gestita da un opportuno bit di privilegio
(verificato con una chiamata a ``capable()``), come descritto nella pagina man
:manpage:`capabilities(7)`.  Scegliete un bit di privilegio già esistente per
gestire la funzionalità associata, ma evitate la combinazione di diverse
funzionalità vagamente collegate dietro lo stesso bit, in quanto va contro il
principio di *capabilities* di separare i poteri di root.  In particolare,
evitate di aggiungere nuovi usi al fin-troppo-generico privilegio
``CAP_SYS_ADMIN``.

Se la vostra nuova chiamata di sistema :manpage:`xyzzy(2)` manipola altri
processi oltre a quello chiamato, allora dovrebbe essere limitata (usando
la chiamata ``ptrace_may_access()``) di modo che solo un processo chiamante
con gli stessi permessi del processo in oggetto, o con i necessari privilegi,
possa manipolarlo.

Infine, state attenti che in alcune architetture non-x86 la vita delle chiamate
di sistema con argomenti a 64-bit viene semplificata se questi argomenti
ricadono in posizioni dispari (pratica, i parametri 1, 3, 5); questo permette
l'uso di coppie contigue di registri a 32-bit.  (Questo non conta se gli
argomenti sono parte di una struttura dati che viene passata per puntatore).


Proporre l'API
--------------

Al fine di rendere le nuove chiamate di sistema di facile revisione, è meglio
che dividiate le modifiche i pezzi separati.  Questi dovrebbero includere
almeno le seguenti voci in *commit* distinti (ognuno dei quali sarà descritto
più avanti):

 - l'essenza dell'implementazione della chiamata di sistema, con i prototipi,
   i numeri generici, le modifiche al Kconfig e l'implementazione *stub* di
   ripiego.
 - preparare la nuova chiamata di sistema per un'architettura specifica,
   solitamente x86 (ovvero tutti: x86_64, x86_32 e x32).
 - un programma di auto-verifica da mettere in ``tools/testing/selftests/``
   che mostri l'uso della chiamata di sistema.
 - una bozza di pagina man per la nuova chiamata di sistema. Può essere
   scritta nell'email di presentazione, oppure come modifica vera e propria
   al repositorio delle pagine man.

Le proposte di nuove chiamate di sistema, come ogni altro modifica all'API del
kernel, deve essere sottomessa alla lista di discussione
linux-api@vger.kernel.org.

generic implementation과 fallback

218-280

새 xyzzy(2)의 주 entry point 이름은 sys_xyzzy()지만 function을 직접 선언해 정의하지 않고 적절한 SYSCALL_DEFINEn() macro로 추가한다. n은 system call argument 수다. Macro에는 system call 이름 뒤에 각 parameter의 (type, name) pair를 전달한다. 이 macro를 쓰면 새 system call의 metadata를 다른 tool이 이용할 수 있다.

System call 호출 방식과 맞추기 위해 include/linux/syscalls.h에 asmlinkage로 표시한 대응 prototype도 필요하다.

asmlinkage long sys_xyzzy(...);

x86 같은 architecture는 자체 syscall table을 가지지만 여러 architecture는 generic table을 공유한다. Generic 목록에 추가할 때는 include/uapi/asm-generic/unistd.h에 entry를 넣는다.

#define __NR_xyzzy 292
__SYSCALL(__NR_xyzzy, sys_xyzzy)

추가된 system call을 반영해 __NR_syscalls count도 갱신한다. 같은 merge window에 새 system call이 여러 개 들어오면 conflict를 해결하기 위해 syscall number가 바뀔 수 있다.

kernel/sys_ni.c는 각 system call이 구현되지 않았을 때 -ENOSYS를 반환하는 fallback stub를 제공한다. 새 system call도 여기에 추가한다.

COND_SYSCALL(xyzzy);

새 kernel 기능과 이를 제어하는 system call은 보통 optional이어야 하므로 CONFIG option을 추가한다. 일반적으로 init/Kconfig에 넣는다. 새 기능과 system call을 설명하고, 일반 사용자에게 숨겨야 한다면 EXPERT에 depend하게 한다. 새 source file은 Makefile에서 CONFIG option에 종속시킨다.

obj-$(CONFIG_XYZZY_SYSCALL) += xyzzy.o

새 CONFIG option을 끈 상태에서도 kernel이 build되는지 반드시 다시 확인한다.

Generic core commit의 필수 항목

  • 보통 init/Kconfig에 두는 새 기능의 CONFIG option
  • Entry point를 정의하는 SYSCALL_DEFINEn(xyzzy, ...)
  • include/linux/syscalls.h의 대응 prototype
  • include/uapi/asm-generic/unistd.h의 generic table entry
  • kernel/sys_ni.c의 fallback stub

Entry point는 `sys_xyzzy()`를 직접 선언해 정의하는 대신 `SYSCALL_DEFINEn()`으로 만들고 `include/linux/syscalls.h`에 `asmlinkage` prototype을 둡니다. Generic table의 `__NR_xyzzy`와 `__NR_syscalls`를 갱신하며 merge window 충돌로 번호가 바뀔 수 있음을 감안합니다.

`kernel/sys_ni.c`에는 `COND_SYSCALL(xyzzy)` fallback을 추가해 미구현 configuration에서 `-ENOSYS`를 반환하게 합니다. 기능은 `CONFIG_XYZZY_SYSCALL`로 optional하게 만들고 Makefile object도 해당 option에 종속시키며 option을 끈 build까지 검사합니다.

generic syscall commit 점검
위치필수 변경
implementationSYSCALL_DEFINEn(xyzzy, ...) entry point
include/linux/syscalls.hasmlinkage prototype
asm-generic/unistd.hnumber, __SYSCALL entry와 count
kernel/sys_ni.cCOND_SYSCALL fallback
Kconfig / Makefileoptional feature와 object 연결

로컬 이탈리아어 원문이 요구하는 core wiring 항목입니다.

Implementazione di chiamate di sistema generiche
------------------------------------------------

Il principale punto d'accesso alla vostra nuova chiamata di sistema
:manpage:`xyzzy(2)` verrà chiamato ``sys_xyzzy()``; ma, piuttosto che in modo
esplicito, lo aggiungerete tramite la macro ``SYSCALL_DEFINEn``. La 'n'
indica il numero di argomenti della chiamata di sistema; la macro ha come
argomento il nome della chiamata di sistema, seguito dalle coppie (tipo, nome)
per definire i suoi parametri.  L'uso di questa macro permette di avere
i metadati della nuova chiamata di sistema disponibili anche per altri
strumenti.

Il nuovo punto d'accesso necessita anche del suo prototipo di funzione in
``include/linux/syscalls.h``, marcato come asmlinkage di modo da abbinargli
il modo in cui quelle chiamate di sistema verranno invocate::

    asmlinkage long sys_xyzzy(...);

Alcune architetture (per esempio x86) hanno le loro specifiche tabelle di
chiamate di sistema (syscall), ma molte altre architetture condividono una
tabella comune di syscall. Aggiungete alla lista generica la vostra nuova
chiamata di sistema aggiungendo un nuovo elemento alla lista in
``include/uapi/asm-generic/unistd.h``::

    #define __NR_xyzzy 292
    __SYSCALL(__NR_xyzzy, sys_xyzzy)

Aggiornate anche il contatore __NR_syscalls di modo che sia coerente con
l'aggiunta della nuove chiamate di sistema; va notato che se più di una nuova
chiamata di sistema viene aggiunga nella stessa finestra di sviluppo, il numero
della vostra nuova syscall potrebbe essere aggiustato al fine di risolvere i
conflitti.

Il file ``kernel/sys_ni.c`` fornisce le implementazioni *stub* di ripiego che
ritornano ``-ENOSYS``.  Aggiungete la vostra nuova chiamata di sistema anche
qui::

    COND_SYSCALL(xyzzy);

La vostra nuova funzionalità del kernel, e la chiamata di sistema che la
controlla, dovrebbero essere opzionali. Quindi, aggiungete un'opzione
``CONFIG`` (solitamente in ``init/Kconfig``).  Come al solito per le nuove
opzioni ``CONFIG``:

 - Includete una descrizione della nuova funzionalità e della chiamata di
   sistema che la controlla.
 - Rendete l'opzione dipendente da EXPERT se dev'essere nascosta agli utenti
   normali.
 - Nel Makefile, rendere tutti i nuovi file sorgenti, che implementano la
   nuova funzionalità, dipendenti dall'opzione CONFIG (per esempio
   ``obj-$(CONFIG_XYZZY_SYSCALL) += xyzzy.o``).
 - Controllate due volte che sia possibile generare il kernel con la nuova
   opzione CONFIG disabilitata.

Per riassumere, vi serve un *commit* che includa:

 - un'opzione ``CONFIG``per la nuova funzione, normalmente in ``init/Kconfig``
 - ``SYSCALL_DEFINEn(xyzzy, ...)`` per il punto d'accesso
 - il corrispondente prototipo in ``include/linux/syscalls.h``
 - un elemento nella tabella generica in ``include/uapi/asm-generic/unistd.h``
 - *stub* di ripiego in ``kernel/sys_ni.c``

x86_64·x32·i386 syscall table

281-299

새 system call을 x86 platform에 연결하려면 master syscall table을 갱신한다. 특별한 system call이 아니라면 arch/x86/entry/syscalls/syscall_64.tbl에 x86_64와 x32용 common entry를 넣는다.

333   common   xyzzy     sys_xyzzy

arch/x86/entry/syscalls/syscall_32.tbl에는 i386 entry를 넣는다.

380   i386     xyzzy     sys_xyzzy

여기 적은 number도 해당 merge window의 conflict에 따라 바뀔 수 있다.

일반적인 새 call은 `arch/x86/entry/syscalls/syscall_64.tbl`에 x86_64와 x32용 `common` entry를, `syscall_32.tbl`에는 i386 entry를 추가합니다. 예시 번호 333과 380은 고정값이 아니며 같은 merge window의 다른 syscall과 충돌하면 조정됩니다.

Implementazione delle chiamate di sistema x86
---------------------------------------------

Per collegare la vostra nuova chiamate di sistema alle piattaforme x86,
dovete aggiornate la tabella principale di syscall.  Assumendo che la vostra
nuova chiamata di sistema non sia particolarmente speciale (vedere sotto),
dovete aggiungere un elemento *common* (per x86_64 e x32) in
arch/x86/entry/syscalls/syscall_64.tbl::

    333   common   xyzzy     sys_xyzzy

e un elemento per *i386* ``arch/x86/entry/syscalls/syscall_32.tbl``::

    380   i386     xyzzy     sys_xyzzy

Ancora una volta, questi numeri potrebbero essere cambiati se generano
conflitti durante la finestra di integrazione.

32-bit userspace용 generic compat layer

300-398

System call 대부분은 userspace program이 32-bit여도 같은 64-bit implementation을 호출할 수 있다. Argument에 명시적인 pointer가 있어도 보통 투명하게 처리된다. 그러나 32-bit와 64-bit의 크기 차이를 다루는 compatibility layer가 필요한 경우가 있다.

Compat layer가 필요한 첫 번째 경우

64-bit kernel이 32-bit userspace program도 지원하면서 32-bit 또는 64-bit 값이 들어 있을 수 있는 __user memory를 parse해야 하는 경우다. 다음 형태의 system call argument가 해당한다.

  • Pointer를 가리키는 pointer
  • Pointer를 포함한 struct를 가리키는 pointer. 예: struct iovec __user *
  • 크기가 달라지는 integral type을 가리키는 pointer. 예: time_t, off_t, long
  • 크기가 달라지는 integral type을 포함한 struct를 가리키는 pointer

Compat layer가 필요한 두 번째 경우

loff_t나 __u64처럼 32-bit architecture에서도 명시적으로 64-bit인 argument가 있는 경우다. 32-bit application에서 64-bit kernel로 들어오는 값은 32-bit 값 두 개로 분할되므로 compatibility layer에서 다시 조립해야 한다.

명시적인 64-bit type을 가리키는 pointer argument 자체는 compatibility layer가 필요하지 않다. 예를 들어 splice(2)의 loff_t __user * argument 때문에 compat_ system call이 필요해지지는 않는다.

compat_sys_xyzzy() 구현

Compatibility version 이름은 compat_sys_xyzzy()이며 SYSCALL_DEFINEn과 같은 방식의 COMPAT_SYSCALL_DEFINEn() macro로 추가한다. 이 implementation은 64-bit kernel의 일부로 실행되지만 32-bit parameter value가 들어온다고 가정하고 필요한 변환을 수행한다.

일반적으로 compat_sys_ version이 값을 64-bit 형태로 변환한 뒤 sys_ version을 호출하거나, native와 compat entry가 공통 inner implementation function을 호출한다.

include/linux/compat.h에는 system call 호출 방식과 맞도록 asmlinkage로 표시한 compat entry prototype도 넣는다.

asmlinkage long compat_sys_xyzzy(...);

System call이 32-bit와 64-bit에서 layout이 다른 struct xyzzy_args를 사용한다면 include/linux/compat.h에 struct compat_xyzzy_args도 정의한다. 원래 struct에서 크기가 달라지는 각 field를 대응 compat_ type으로 바꾼다. compat_sys_xyzzy()는 이 compat structure로 32-bit invocation의 argument를 parse한다.

struct xyzzy_args {
    const char __user *ptr;
    __kernel_long_t varying_val;
    u64 fixed_val;
    /* ... */
};

struct compat_xyzzy_args {
    compat_uptr_t ptr;
    compat_long_t varying_val;
    u64 fixed_val;
    /* ... */
};

Generic syscall list도 compat version을 가리키도록 바꿔야 한다. include/uapi/asm-generic/unistd.h에서 __SYSCALL 대신 __SC_COMP를 쓴다.

#define __NR_xyzzy 292
__SC_COMP(__NR_xyzzy, sys_xyzzy, compat_sys_xyzzy)

Generic compat 구현의 필수 항목

  • Compat entry point의 COMPAT_SYSCALL_DEFINEn(xyzzy, ...)
  • include/linux/compat.h의 대응 prototype
  • 필요한 경우 include/linux/compat.h의 32-bit mapping struct
  • include/uapi/asm-generic/unistd.h에서 __SYSCALL 대신 __SC_COMP 사용
32-bit process가 64-bit kernel의 compat entry를 호출하는 경로
32-bit userspaceSyscall tablecompat_sys_xyzzy()Common implementation
01 32-bit layout로 argument 구성compat entry 선택compat type으로 copy·decode
02 64-bit/native 형태로 변환검증과 실제 operation 수행
03 Return value 수신ABI에 맞춰 반환결과 변환결과 반환

Compat wrapper가 pointer와 가변 폭 field를 native representation으로 변환한 뒤 공통 구현으로 넘긴다.

64-bit kernel이 32-bit userspace memory에서 pointer-to-pointer, pointer를 포함한 struct, `time_t`·`off_t`·`long`처럼 폭이 달라지는 값을 읽거나 명시적 64-bit argument를 두 조각에서 재조립해야 하면 compat layer가 필요합니다. 단, `loff_t __user *`처럼 고정 64-bit type을 가리키는 pointer만으로는 별도 compat call이 필요하지 않습니다.

`COMPAT_SYSCALL_DEFINEn()`으로 `compat_sys_xyzzy()`를 만들고 `include/linux/compat.h`에 prototype과 필요한 `compat_xyzzy_args`를 정의합니다. Pointer는 `compat_uptr_t`, 폭이 달라지는 long은 `compat_long_t`처럼 대응 type으로 변환하고 generic table은 `__SYSCALL` 대신 `__SC_COMP`를 사용합니다.

Chiamate di sistema compatibili (generico)
------------------------------------------

Per molte chiamate di sistema, la stessa implementazione a 64-bit può essere
invocata anche quando il programma in spazio utente è a 32-bit; anche se la
chiamata di sistema include esplicitamente un puntatore, questo viene gestito
in modo trasparente.

Tuttavia, ci sono un paio di situazione dove diventa necessario avere un
livello di gestione della compatibilità per risolvere le differenze di
dimensioni fra 32-bit e 64-bit.

Il primo caso è quando un kernel a 64-bit supporta anche programmi in spazio
utente a 32-bit, perciò dovrà ispezionare aree della memoria (``__user``) che
potrebbero contenere valori a 32-bit o a 64-bit.  In particolar modo, questo
è necessario quando un argomento di una chiamata di sistema è:

 - un puntatore ad un puntatore
 - un puntatore ad una struttura dati contenente a sua volta un puntatore
   ( ad esempio ``struct iovec __user *``)
 - un puntatore ad un tipo intero di dimensione variabile (``time_t``,
   ``off_t``, ``long``, ...)
 - un puntatore ad una struttura dati contenente un tipo intero di dimensione
   variabile.

Il secondo caso che richiede un livello di gestione della compatibilità è
quando uno degli argomenti di una chiamata a sistema è esplicitamente un tipo
a 64-bit anche su architetture a 32-bit, per esempio ``loff_t`` o ``__u64``.
In questo caso, un valore che arriva ad un kernel a 64-bit da un'applicazione
a 32-bit verrà diviso in due valori a 32-bit che dovranno essere riassemblati
in questo livello di compatibilità.

(Da notare che non serve questo livello di compatibilità per argomenti che
sono puntatori ad un tipo esplicitamente a 64-bit; per esempio, in
:manpage:`splice(2)` l'argomento di tipo ``loff_t __user *`` non necessita
di una chiamata di sistema ``compat_``)

La versione compatibile della nostra chiamata di sistema si chiamerà
``compat_sys_xyzzy()``, e viene aggiunta utilizzando la macro
``COMPAT_SYSCALL_DEFINEn()`` (simile a SYSCALL_DEFINEn).  Questa versione
dell'implementazione è parte del kernel a 64-bit ma accetta parametri a 32-bit
che trasformerà secondo le necessità (tipicamente, la versione
``compat_sys_`` converte questi valori nello loro corrispondente a 64-bit e
può chiamare la versione ``sys_`` oppure invocare una funzione che implementa
le parti comuni).

Il punto d'accesso *compat* deve avere il corrispondente prototipo di funzione
in ``include/linux/compat.h``, marcato come asmlinkage di modo da abbinargli
il modo in cui quelle chiamate di sistema verranno invocate::

    asmlinkage long compat_sys_xyzzy(...);

Se la chiamata di sistema prevede una struttura dati organizzata in modo
diverso per sistemi a 32-bit e per quelli a 64-bit, diciamo
``struct xyzzy_args``, allora il file d'intestazione
``then the include/linux/compat.h`` deve includere la sua versione
*compatibile* (``struct compat_xyzzy_args``); ogni variabile con
dimensione variabile deve avere il proprio tipo ``compat_`` corrispondente
a quello in ``struct xyzzy_args``.  La funzione ``compat_sys_xyzzy()``
può usare la struttura ``compat_`` per analizzare gli argomenti ricevuti
da una chiamata a 32-bit.

Per esempio, se avete i seguenti campi::

    struct xyzzy_args {
        const char __user *ptr;
        __kernel_long_t varying_val;
        u64 fixed_val;
        /* ... */
    };

nella struttura ``struct xyzzy_args``, allora la struttura
``struct compat_xyzzy_args`` dovrebbe avere::

    struct compat_xyzzy_args {
        compat_uptr_t ptr;
        compat_long_t varying_val;
        u64 fixed_val;
        /* ... */
    };

La lista generica delle chiamate di sistema ha bisogno di essere
aggiustata al fine di permettere l'uso della versione *compatibile*;
la voce in ``include/uapi/asm-generic/unistd.h`` dovrebbero usare
``__SC_COMP`` piuttosto di ``__SYSCALL``::

    #define __NR_xyzzy 292
    __SC_COMP(__NR_xyzzy, sys_xyzzy, compat_sys_xyzzy)

Riassumendo, vi serve:

 - un ``COMPAT_SYSCALL_DEFINEn(xyzzy, ...)`` per il punto d'accesso
   *compatibile*
 - un prototipo in ``include/linux/compat.h``
 - (se necessario) una struttura di compatibilità a 32-bit in
   ``include/linux/compat.h``
 - una voce ``__SC_COMP``, e non ``__SYSCALL``, in
   ``include/uapi/asm-generic/unistd.h``

x86 compat entry와 x32 ABI

399-434

Compat version이 있는 system call을 x86에 연결하려면 syscall table entry를 조정한다. 먼저 arch/x86/entry/syscalls/syscall_32.tbl에 열을 하나 더 두어 64-bit kernel에서 실행되는 32-bit userspace program이 compat entry로 들어가게 한다.

380   i386     xyzzy     sys_xyzzy    __ia32_compat_sys_xyzzy

다음으로 새 system call의 x32 ABI가 어떤 argument layout을 사용할지 결정한다. 64-bit version 또는 32-bit version 중 하나와 일치해야 한다.

Pointer-to-pointer가 있다면 결정은 명확하다. x32는 ILP32이므로 layout은 32-bit version과 같아야 한다. arch/x86/entry/syscalls/syscall_64.tbl entry를 나눠 x32 program이 compatibility wrapper로 들어가게 한다.

333   64       xyzzy     sys_xyzzy
...
555   x32      xyzzy     __x32_compat_sys_xyzzy

Pointer가 없다면 x32 ABI에서 64-bit system call을 재사용하는 편이 좋다. 이 경우 arch/x86/entry/syscalls/syscall_64.tbl entry는 바꾸지 않는다.

어느 경우든 argument layout에 쓰인 type이 x32(-mx32)에서 선택한 32-bit(-m32) 또는 64-bit(-m64) equivalent와 정확히 mapping되는지 확인해야 한다.

`syscall_32.tbl`에는 64-bit kernel에서 실행되는 32-bit program이 `__ia32_compat_sys_xyzzy`로 들어가도록 compat 열을 추가합니다. x32 ABI는 pointer-to-pointer가 있으면 ILP32 layout을 따라 `__x32_compat_sys_xyzzy`를 쓰고 pointer가 없으면 가능한 한 64-bit implementation을 재사용합니다.

선택한 layout은 `-mx32` build의 argument type이 `-m32` 또는 `-m64` equivalent와 정확히 일치하는지 확인해야 합니다.

Compatibilità delle chiamate di sistema (x86)
---------------------------------------------

Per collegare una chiamata di sistema, su un'architettura x86, con la sua
versione *compatibile*, è necessario aggiustare la voce nella tabella
delle syscall.

Per prima cosa, la voce in ``arch/x86/entry/syscalls/syscall_32.tbl`` prende
un argomento aggiuntivo per indicare che un programma in spazio utente
a 32-bit, eseguito su un kernel a 64-bit, dovrebbe accedere tramite il punto
d'accesso compatibile::

    380   i386     xyzzy     sys_xyzzy    __ia32_compat_sys_xyzzy

Secondo, dovete capire cosa dovrebbe succedere alla nuova chiamata di sistema
per la versione dell'ABI x32.  Qui C'è una scelta da fare: gli argomenti
possono corrisponde alla versione a 64-bit o a quella a 32-bit.

Se c'è un puntatore ad un puntatore, la decisione è semplice: x32 è ILP32,
quindi gli argomenti dovrebbero corrispondere a quelli a 32-bit, e la voce in
``arch/x86/entry/syscalls/syscall_64.tbl`` sarà divisa cosicché i programmi
x32 eseguano la chiamata *compatibile*::

    333   64       xyzzy     sys_xyzzy
    ...
    555   x32      xyzzy     __x32_compat_sys_xyzzy

Se non ci sono puntatori, allora è preferibile riutilizzare la chiamata di
sistema a 64-bit per l'ABI x32 (e di conseguenza la voce in
arch/x86/entry/syscalls/syscall_64.tbl rimane immutata).

In ambo i casi, dovreste verificare che i tipi usati dagli argomenti
abbiano un'esatta corrispondenza da x32 (-mx32) al loro equivalente a
32-bit (-m32) o 64-bit (-m64).

다른 위치나 상태로 복귀하는 syscall

435-492

System call 대부분은 완료 뒤 user program이 중단한 바로 다음 instruction에서 계속 실행된다. Stack과 register 대부분은 호출 전과 같고 virtual memory space도 같다.

그러나 rt_sigreturn은 다른 위치로 복귀할 수 있고, fork/vfork/clone은 memory space를 바꾸며, execve/execveat는 program의 architecture까지 바꿀 수 있다.

이런 동작을 허용하려면 system call kernel implementation이 추가 register를 kernel stack에 save하고 restore해야 할 수 있다. 그래야 system call 뒤 execution을 어디서 어떤 상태로 계속할지 완전히 제어할 수 있다.

구현은 architecture-specific이지만 보통 추가 register를 save/restore하고 실제 system call entry point를 호출하는 assembly entry point를 정의한다.

x86_64에서는 arch/x86/entry/entry_64.S에 stub_xyzzy entry point를 구현하고 arch/x86/entry/syscalls/syscall_64.tbl을 그 entry에 맞춘다.

333   common   xyzzy     stub_xyzzy

64-bit kernel에서 실행되는 32-bit program용 equivalent는 보통 stub32_xyzzy라고 하며 arch/x86/entry/entry_64_compat.S에 구현한다. arch/x86/entry/syscalls/syscall_32.tbl도 대응되게 조정한다.

380   i386     xyzzy     sys_xyzzy    stub32_xyzzy

앞 절처럼 compatibility layer가 필요하면 stub32_ version은 native 64-bit version이 아니라 compat_sys_ version을 호출해야 한다. x32 ABI implementation이 x86_64 version과 공통이 아니라면 x32 syscall table도 compat_sys_ version을 부르는 stub를 호출해야 한다.

User-mode Linux도 계속 동작하도록 mapping을 추가하는 것이 좋다. UML syscall table은 stub_xyzzy를 참조하지만 register 등을 simulation하므로 UML build에는 arch/x86/entry/entry_64.S implementation이 들어가지 않는다. arch/x86/um/sys_call_table_64.c에 다음 define을 추가하면 해결된다.

#define stub_xyzzy sys_xyzzy

`rt_sigreturn`, `fork`·`vfork`·`clone`, `execve`·`execveat`처럼 일반 return path를 따르지 않는 call은 추가 register save·restore와 architecture-specific assembly entry가 필요할 수 있습니다.

x86_64의 `stub_xyzzy`, 32-bit compat의 `stub32_xyzzy`, 필요 시 `compat_sys_` 호출과 x32 stub을 table에 연결합니다. User-mode Linux는 실제 x86 assembly entry를 포함하지 않으므로 `arch/x86/um/sys_call_table_64.c`에서 `stub_xyzzy`를 `sys_xyzzy`로 mapping합니다.

Chiamate di sistema che ritornano altrove
-----------------------------------------

Nella maggior parte delle chiamate di sistema, al termine della loro
esecuzione, i programmi in spazio utente riprendono esattamente dal punto
in cui si erano interrotti -- quindi dall'istruzione successiva, con lo
stesso *stack* e con la maggior parte del registri com'erano stati
lasciati prima della chiamata di sistema, e anche con la stessa memoria
virtuale.

Tuttavia, alcune chiamata di sistema fanno le cose in modo differente.
Potrebbero ritornare ad un punto diverso (``rt_sigreturn``) o cambiare
la memoria in spazio utente (``fork``/``vfork``/``clone``) o perfino
l'architettura del programma (``execve``/``execveat``).

Per permettere tutto ciò, l'implementazione nel kernel di questo tipo di
chiamate di sistema potrebbero dover salvare e ripristinare registri
aggiuntivi nello *stack* del kernel, permettendo così un controllo completo
su dove e come l'esecuzione dovrà continuare dopo l'esecuzione della
chiamata di sistema.

Queste saranno specifiche per ogni architettura, ma tipicamente si definiscono
dei punti d'accesso in *assembly* per salvare/ripristinare i registri
aggiuntivi e quindi chiamare il vero punto d'accesso per la chiamata di
sistema.

Per l'architettura x86_64, questo è implementato come un punto d'accesso
``stub_xyzzy`` in ``arch/x86/entry/entry_64.S``, e la voce nella tabella
di syscall (``arch/x86/entry/syscalls/syscall_64.tbl``) verrà corretta di
conseguenza::

    333   common   xyzzy     stub_xyzzy

L'equivalente per programmi a 32-bit eseguiti su un kernel a 64-bit viene
normalmente chiamato ``stub32_xyzzy`` e implementato in
``arch/x86/entry/entry_64_compat.S`` con la corrispondente voce nella tabella
di syscall ``arch/x86/entry/syscalls/syscall_32.tbl`` corretta nel
seguente modo::

    380   i386     xyzzy     sys_xyzzy    stub32_xyzzy

Se una chiamata di sistema necessita di un livello di compatibilità (come
nella sezione precedente), allora la versione ``stub32_`` deve invocare
la versione ``compat_sys_`` piuttosto che quella nativa a 64-bit.  In aggiunta,
se l'implementazione dell'ABI x32 è diversa da quella x86_64, allora la sua
voce nella tabella di syscall dovrà chiamare uno *stub* che invoca la versione
``compat_sys_``,

Per completezza, sarebbe carino impostare una mappatura cosicché
*user-mode* Linux (UML) continui a funzionare -- la sua tabella di syscall
farà riferimento a stub_xyzzy, ma UML non include l'implementazione
in ``arch/x86/entry/entry_64.S`` (perché UML simula i registri eccetera).
Correggerlo è semplice, basta aggiungere una #define in
``arch/x86/um/sys_call_table_64.c``::

    #define stub_xyzzy sys_xyzzy

audit 특수 처리, selftest와 man page

493-553

Kernel 전체의 특수 처리 확인

Kernel 대부분은 system call을 generic하게 다루지만 특정 system call에 맞춰 갱신해야 하는 예외가 가끔 있다.

Audit subsystem이 한 예다. Architecture-specific function으로 file open(open/openat), program execution(execve/exeveat), socket multiplexor(socketcall) 같은 특수 system call type을 분류한다. 새 system call이 이들 중 하나와 유사하다면 audit system도 갱신해야 한다.

일반적으로 새 system call과 비슷한 기존 system call이 있다면 kernel 전체에서 그 이름을 grep해 다른 special case가 없는지 확인할 가치가 있다.

Selftest와 외부 test suite

새 system call은 당연히 test해야 하며 reviewer에게 userspace program의 사용법을 보여 주는 것도 유용하다. 두 목적을 함께 달성하는 좋은 방법은 tools/testing/selftests/ 아래 새 directory에 단순한 self-test program을 넣는 것이다.

새 system call에는 libc wrapper function이 없으므로 test는 syscall()로 직접 호출해야 한다. Userspace-visible structure를 새로 만들었다면 test를 compile할 수 있도록 대응 header도 install해야 한다.

Selftest가 지원하는 모든 architecture에서 성공하는지 확인한다. 예를 들어 x86_64(-m64), x86_32(-m32), x32(-mx32) ABI program으로 각각 compile해 동작을 검사한다.

새 기능을 더 넓고 철저하게 test하려면 Linux Test Project에 test를 추가하거나 filesystem 변경이면 xfstests project에 test를 추가하는 방안도 검토한다.

Man page

모든 새 system call에는 완전한 man page가 따라와야 한다. Groff markup이 이상적이지만 plain text도 가능하다. Groff를 썼다면 reviewer 편의를 위해 patchset cover email에 미리 render한 ASCII version도 넣는 것이 좋다.

Man page는 linux-man@vger.kernel.org를 CC해야 한다. 자세한 제출 방법은 kernel.org의 man-pages patch 안내를 참고한다.

`open`·`openat`, `execve`·`execveat`, `socketcall`처럼 audit subsystem이 특별히 분류하는 기존 syscall과 유사하다면 architecture별 audit code도 갱신합니다. Kernel 전체에서 유사 call 이름을 검색해 다른 special case가 없는지 확인합니다.

`tools/testing/selftests/`에 `syscall()`로 직접 호출하는 userspace test를 넣고 새 userspace-visible header를 install합니다. x86_64 `-m64`, x86_32 `-m32`, x32 `-mx32`에서 실행하며 필요하면 Linux Test Project나 filesystem용 xfstests에도 coverage를 추가합니다.

모든 새 syscall에는 완전한 man page를 제공하고 groff source를 보낼 때는 reviewer가 읽기 쉬운 ASCII render도 함께 보냅니다. Man page patch에는 `linux-man@vger.kernel.org`를 Cc합니다.

Altri dettagli
--------------

La maggior parte dei kernel tratta le chiamate di sistema allo stesso modo,
ma possono esserci rare eccezioni per le quali potrebbe essere necessario
l'aggiornamento della vostra chiamata di sistema.

Il sotto-sistema di controllo (*audit subsystem*) è uno di questi casi
speciali; esso include (per architettura) funzioni che classificano alcuni
tipi di chiamate di sistema -- in particolare apertura dei file
(``open``/``openat``), esecuzione dei programmi (``execve``/``exeveat``)
oppure multiplatori di socket (``socketcall``). Se la vostra nuova chiamata
di sistema è simile ad una di queste, allora il sistema di controllo dovrebbe
essere aggiornato.

Più in generale, se esiste una chiamata di sistema che è simile alla vostra,
vale la pena fare una ricerca con ``grep`` su tutto il kernel per la chiamata
di sistema esistente per verificare che non ci siano altri casi speciali.


Verifica
--------

Una nuova chiamata di sistema dev'essere, ovviamente, provata; è utile fornire
ai revisori un programma in spazio utente che mostri l'uso della chiamata di
sistema.  Un buon modo per combinare queste cose è quello di aggiungere un
semplice programma di auto-verifica in una nuova cartella in
``tools/testing/selftests/``.

Per una nuova chiamata di sistema, ovviamente, non ci sarà alcuna funzione
in libc e quindi il programma di verifica dovrà invocarla usando ``syscall()``;
inoltre, se la nuova chiamata di sistema prevede un nuova struttura dati
visibile in spazio utente, il file d'intestazione necessario dev'essere
installato al fine di compilare il programma.

Assicuratevi che il programma di auto-verifica possa essere eseguito
correttamente su tutte le architetture supportate.  Per esempio, verificate che
funzioni quando viene compilato per x86_64 (-m64), x86_32 (-m32) e x32 (-mx32).

Al fine di una più meticolosa ed estesa verifica della nuova funzionalità,
dovreste considerare l'aggiunta di nuove verifica al progetto 'Linux Test',
oppure al progetto xfstests per cambiamenti relativi al filesystem.

 - https://linux-test-project.github.io/
 - git://git.kernel.org/pub/scm/fs/xfs/xfstests-dev.git


Pagine man
----------

Tutte le nuove chiamate di sistema dovrebbero avere una pagina man completa,
idealmente usando i marcatori groff, ma anche il puro testo può andare.  Se
state usando groff, è utile che includiate nella email di presentazione una
versione già convertita in formato ASCII: semplificherà la vita dei revisori.

Le pagine man dovrebbero essere in copia-conoscenza verso
linux-man@vger.kernel.org
Per maggiori dettagli, leggere
https://www.kernel.org/doc/man-pages/patches.html

kernel 내부에서 syscall entry를 직접 호출하지 않기

554-587

System call은 userspace와 kernel 사이의 상호 작용 지점이다. 따라서 sys_xyzzy()나 compat_sys_xyzzy() 같은 system call function은 userspace가 syscall table을 통해서만 호출해야 하며 kernel의 다른 code가 직접 호출해서는 안 된다.

System call 기능을 kernel 내부에서도 사용해야 하거나 old syscall과 new syscall이 공유해야 하거나 native syscall과 compatibility variant가 공유해야 한다면 ksys_xyzzy() 같은 helper function으로 구현한다. 그러면 syscall stub인 sys_xyzzy(), compatibility syscall stub인 compat_sys_xyzzy(), 다른 kernel code가 helper를 호출할 수 있다.

적어도 64-bit x86에서는 v4.17부터 kernel 내부에서 system call function을 호출하지 않는 것이 엄격한 요구 사항이다. 이 architecture는 system call에 다른 calling convention을 쓴다. Syscall wrapper가 struct pt_regs를 즉시 decode한 다음 실제 syscall function으로 처리를 넘긴다.

그 결과 syscall entry에서 CPU register 여섯 개를 매번 임의의 userspace content로 채우는 대신 특정 syscall에 실제로 필요한 parameter만 전달한다. 임의의 userspace 값이 call chain 아래로 흘러가면 심각한 문제를 만들 수 있다.

또한 kernel data와 user data는 접근 규칙이 다를 수 있다. 이것도 sys_xyzzy()를 직접 호출하는 것이 일반적으로 나쁜 이유다.

이 규칙의 예외는 architecture-specific override, architecture-specific compatibility wrapper 또는 arch/ 아래의 다른 code에서만 허용된다.

`sys_xyzzy()`와 `compat_sys_xyzzy()`는 userspace가 syscall table을 통해 들어오는 ABI entry이므로 다른 kernel code가 직접 호출해서는 안 됩니다. 공통 기능은 `ksys_xyzzy()` 같은 helper로 분리해 native·compat stub과 내부 caller가 공유합니다.

64-bit x86은 v4.17부터 `struct pt_regs`를 wrapper에서 decode하는 별도 calling convention을 사용하므로 직접 호출 금지가 특히 중요합니다. Kernel pointer와 user pointer의 접근 규칙도 다르며 예외는 architecture override·compat wrapper 등 `arch/`의 제한된 code뿐입니다.

Non invocate chiamate di sistema dal kernel
-------------------------------------------

Le chiamate di sistema sono, come già detto prima, punti di interazione fra
lo spazio utente e il kernel.  Perciò, le chiamate di sistema come
``sys_xyzzy()`` o ``compat_sys_xyzzy()`` dovrebbero essere chiamate solo dallo
spazio utente attraverso la tabella syscall, ma non da nessun altro punto nel
kernel.  Se la nuova funzionalità è utile all'interno del kernel, per esempio
dev'essere condivisa fra una vecchia e una nuova chiamata di sistema o
dev'essere utilizzata da una chiamata di sistema e la sua variante compatibile,
allora dev'essere implementata come una funzione di supporto
(*helper function*) (per esempio ``ksys_xyzzy()``).  Questa funzione potrà
essere chiamata dallo *stub* (``sys_xyzzy()``), dalla variante compatibile
(``compat_sys_xyzzy()``), e/o da altri parti del kernel.

Sui sistemi x86 a 64-bit, a partire dalla versione v4.17 è un requisito
fondamentale quello di non invocare chiamate di sistema all'interno del kernel.
Esso usa una diversa convenzione per l'invocazione di chiamate di sistema dove
``struct pt_regs`` viene decodificata al volo in una funzione che racchiude
la chiamata di sistema la quale verrà eseguita successivamente.
Questo significa che verranno passati solo i parametri che sono davvero
necessari ad una specifica chiamata di sistema, invece che riempire ogni volta
6 registri del processore con contenuti presi dallo spazio utente (potrebbe
causare seri problemi nella sequenza di chiamate).

Inoltre, le regole su come i dati possano essere usati potrebbero differire
fra il kernel e l'utente.  Questo è un altro motivo per cui invocare
``sys_xyzzy()`` è generalmente una brutta idea.

Eccezioni a questa regola vengono accettate solo per funzioni d'architetture
che surclassano quelle generiche, per funzioni d'architettura di compatibilità,
o per altro codice in arch/

설계 근거와 참고 자료

588-643

System call의 flags argument 사용과 unknown flag 처리에 관한 Michael Kerrisk의 LWN 글, 64-bit system call argument 제약을 설명한 Jake Edge의 LWN 글, Linux v3.14의 system call implementation path를 자세히 설명한 David Drysdale의 LWN 글 두 편이 참고 자료로 제시된다.

Architecture-specific system call 요구 사항은 syscall(2) man page에서 확인할 수 있다. Linus Torvalds가 ioctl()의 문제를 논의한 email 모음과 Arnd Bergmann의 “How to not invent kernel interfaces”도 interface 설계 배경을 제공한다.

Michael Kerrisk의 CAP_SYS_ADMIN 새 사용을 피하는 방법, 새 system call의 관련 정보를 같은 email thread에 모두 담으라는 Andrew Morton의 권고, 새 system call에 man page를 붙이라는 Michael Kerrisk의 권고가 이어진다.

x86 wiring을 별도 commit으로 만들라는 Thomas Gleixner의 제안, 새 system call에 man page와 selftest를 함께 제공하라는 Greg Kroah-Hartman의 제안, 새 system call과 prctl(2) extension 선택을 논의한 Michael Kerrisk의 글도 참고할 수 있다.

Argument가 많은 system call은 future extension을 위한 size field가 있는 struct에 argument를 넣으라는 Ingo Molnar의 제안도 제시된다.

O_* numbering space flag의 재사용으로 생긴 numbering 문제는 commit 75069f2b5bfb("vfs: renumber FMODE_NONOTIFY and add to uniqueness check"), 12ed2e36c98a("fanotify: FMODE_NONOTIFY and __O_SYNC in sparc conflict"), bb458c644a59("Safer ABI for O_TMPFILE")에서 확인할 수 있다.

Matthew Wilcox의 64-bit argument 제약 논의, unknown flag를 엄격히 검사하라는 Greg Kroah-Hartman의 권고, x32 system call은 32-bit보다 64-bit version과의 호환을 선호해야 한다는 Linus Torvalds의 권고도 포함된다. 마지막 자료는 여러 architecture에서 scripts/syscall.tbl을 사용하도록 syscall table infrastructure를 개정한 patch series다.

참고 링크는 unknown flag 처리, 64-bit argument 배치, v3.14 syscall 구현 경로, architecture별 `syscall(2)` 규칙, `ioctl()`의 문제, `CAP_SYS_ADMIN` 남용 방지, man page·selftest·x86 분리 commit 권고의 근거를 제공합니다.

또한 많은 argument를 `size`가 있는 struct로 묶는 방법, `O_*` flag 번호 충돌 사례, x32가 32-bit보다 64-bit ABI 호환을 우선해야 한다는 논의를 포함합니다. 원문 링크와 commit ID는 아래 보존된 588~643줄에서 그대로 확인할 수 있습니다.

Riferimenti e fonti
-------------------

 - Articolo di Michael Kerris su LWN sull'uso dell'argomento flags nelle
   chiamate di sistema: https://lwn.net/Articles/585415/
 - Articolo di Michael Kerris su LWN su come gestire flag sconosciuti in
   una chiamata di sistema: https://lwn.net/Articles/588444/
 - Articolo di Jake Edge su LWN che descrive i limiti degli argomenti a 64-bit
   delle chiamate di sistema: https://lwn.net/Articles/311630/
 - Una coppia di articoli di David Drysdale che descrivono i dettagli del
   percorso implementativo di una chiamata di sistema per la versione v3.14:

    - https://lwn.net/Articles/604287/
    - https://lwn.net/Articles/604515/

 - Requisiti specifici alle architetture sono discussi nella pagina man
   :manpage:`syscall(2)` :
   http://man7.org/linux/man-pages/man2/syscall.2.html#NOTES
 - Collezione di email di Linux Torvalds sui problemi relativi a ``ioctl()``:
   http://yarchive.net/comp/linux/ioctl.html
 - "Come non inventare interfacce del kernel", Arnd Bergmann,
   http://www.ukuug.org/events/linux2007/2007/papers/Bergmann.pdf
 - Articolo di Michael Kerris su LWN sull'evitare nuovi usi di CAP_SYS_ADMIN:
   https://lwn.net/Articles/486306/
 - Raccomandazioni da Andrew Morton circa il fatto che tutte le informazioni
   su una nuova chiamata di sistema dovrebbero essere contenute nello stesso
   filone di discussione di email: https://lore.kernel.org/r/20140724144747.3041b208832bbdf9fbce5d96@linux-foundation.org
 - Raccomandazioni da Michael Kerrisk circa il fatto che le nuove chiamate di
   sistema dovrebbero avere una pagina man: https://lore.kernel.org/r/CAKgNAkgMA39AfoSoA5Pe1r9N+ZzfYQNvNPvcRN7tOvRb8+v06Q@mail.gmail.com
 - Consigli da Thomas Gleixner sul fatto che il collegamento all'architettura
   x86 dovrebbe avvenire in un *commit* differente:
   https://lore.kernel.org/r/alpine.DEB.2.11.1411191249560.3909@nanos
 - Consigli da Greg Kroah-Hartman circa la bontà d'avere una pagina man e un
   programma di auto-verifica per le nuove chiamate di sistema:
   https://lore.kernel.org/r/20140320025530.GA25469@kroah.com
 - Discussione di Michael Kerrisk sulle nuove chiamate di sistema contro
   le estensioni :manpage:`prctl(2)`: https://lore.kernel.org/r/CAHO5Pa3F2MjfTtfNxa8LbnkeeU8=YJ+9tDqxZpw7Gz59E-4AUg@mail.gmail.com
 - Consigli da Ingo Molnar che le chiamate di sistema con più argomenti
   dovrebbero incapsularli in una struttura che includa un argomento
   *size* per garantire l'estensibilità futura:
   https://lore.kernel.org/r/20150730083831.GA22182@gmail.com
 - Un certo numero di casi strani emersi dall'uso (riuso) dei flag O_*:

    - commit 75069f2b5bfb ("vfs: renumber FMODE_NONOTIFY and add to uniqueness
      check")
    - commit 12ed2e36c98a ("fanotify: FMODE_NONOTIFY and __O_SYNC in sparc
      conflict")
    - commit bb458c644a59 ("Safer ABI for O_TMPFILE")

 - Discussion from Matthew Wilcox about restrictions on 64-bit arguments:
   https://lore.kernel.org/r/20081212152929.GM26095@parisc-linux.org
 - Raccomandazioni da Greg Kroah-Hartman sul fatto che i flag sconosciuti dovrebbero
   essere controllati: https://lore.kernel.org/r/20140717193330.GB4703@kroah.com
 - Raccomandazioni da Linus Torvalds che le chiamate di sistema x32 dovrebbero
   favorire la compatibilità con le versioni a 64-bit piuttosto che quelle a 32-bit:
   https://lore.kernel.org/r/CA+55aFxfmwfB7jbbrXxa=K7VBYPfAvmu3XOkGrLbB1UFjX1+Ew@mail.gmail.com