1.. SPDX-License-Identifier: GPL-2.0 2 3======================================= 4Adicionando uma Nova Chamada de Sistema 5======================================= 6 7Este documento descreve o que está envolvido na adição de uma nova chamada de 8sistema (system call) ao kernel Linux, indo além dos conselhos normais de 9submissão em 10:ref:`Documentation/process/submitting-patches.rst <submittingpatches>`. 11 12 13Alternativas às Chamadas de Sistema 14----------------------------------- 15 16A primeira coisa a se considerar ao adicionar uma nova chamada de sistema é se 17uma das alternativas poderia ser mais adequada. Embora as chamadas de sistema 18sejam os pontos de interação mais tradicionais e óbvios entre o espaço do 19usuário (userspace) e o kernel, existem outras possibilidades -- escolha o que 20melhor se adapta à sua interface. 21 22 - Se as operações envolvidas puderem ser moldadas para se parecerem com um 23 objeto do tipo arquivo, pode fazer mais sentido criar um novo sistema de 24 arquivos ou dispositivo. Isso também torna mais fácil encapsular a nova 25 funcionalidade em um módulo de kernel, em vez de exigir que ela seja 26 incorporada ao kernel principal. 27 28 - Se a nova funcionalidade envolver operações em que o kernel notifica o 29 espaço do usuário de que algo aconteceu, retornar um novo descritor de 30 arquivo (file descriptor) para o objeto relevante permite que o espaço 31 do usuário use ``poll``/``select``/``epoll`` para receber essa 32 notificação. 33 - No entanto, as operações que não se mapeiam para operações do tipo 34 :manpage:`read(2)`/:manpage:`write(2)` precisam ser implementadas como 35 requisições :manpage:`ioctl(2)`, o que pode levar a uma API um tanto 36 quanto opaca. 37 38 - Se você estiver apenas expondo informações do sistema em tempo de execução, 39 um novo nó no sysfs (veja ``Documentation/filesystems/sysfs.rst``) ou no 40 sistema de arquivos ``/proc`` pode ser mais apropriado. No entanto, o acesso 41 a esses mecanismos exige que o sistema de arquivos relevante esteja montado, 42 o que pode não ser sempre o caso (por exemplo, em um ambiente com namespaces, 43 sandboxed ou chrooted). Evite adicionar qualquer API ao debugfs, pois este 44 não é considerado uma interface de "produção" para o espaço do usuário. 45 - Se a operação for específica para um arquivo ou descritor de arquivo de um 46 determinado objeto, então uma opção de comando adicional para :manpage:`fcntl(2)` 47 pode ser mais adequada. Contudo, o :manpage:`fcntl(2)` é uma chamada de sistema 48 de multiplexação que oculta muita complexidade, portanto, esta opção é melhor 49 para quando a nova função for intimamente análoga à funcionalidade existente 50 do :manpage:`fcntl(2)`, ou se a nova funcionalidade for muito simples (por 51 exemplo, obter/definir uma flag simples relacionada a um descritor de arquivo). 52 - Se a operação for específica para uma tarefa (task) ou processo específico, 53 então uma opção de comando adicional para :manpage:`prctl(2)` pode ser mais 54 apropriada. Assim como no caso do :manpage:`fcntl(2)`, esta chamada de sistema 55 é um multiplexador complicado, sendo melhor reservá-la para análogos próximos 56 de comandos ``prctl()`` existentes ou para obter/definir uma flag simples 57 relacionada a um processo. 58 59 60Projetando a API: Planejando a Extensibilidade 61---------------------------------------------- 62 63Uma nova chamada de sistema faz parte da API do kernel e deve ser suportada 64indefinidamente. Sendo assim, é uma excelente ideia discutir explicitamente a 65interface na lista de discussão do kernel (LKML), e é crucial planejar extensões 66futuras para essa interface. 67 68(A tabela de chamadas de sistema está repleta de exemplos históricos onde isso 69não foi feito, juntamente com as respectivas chamadas de sistema de acompanhamento 70-- ``eventfd``/``eventfd2``, ``dup2``/``dup3``, ``inotify_init``/``inotify_init1``, 71``pipe``/``pipe2``, ``renameat``/``renameat2`` -- portanto, aprenda com a história 72do kernel e planeje as extensões desde o início.) 73 74Para chamadas de sistema mais simples que recebem apenas alguns argumentos, a 75maneira preferencial de permitir extensibilidade futura é incluir um argumento de 76flags na chamada de sistema. Para garantir que os programas do espaço do usuário 77possam usar flags de forma segura entre diferentes versões do kernel, verifique 78se o valor de flags contém qualquer flag desconhecida e rejeite a chamada de 79sistema (com ``EINVAL``) se contiver:: 80 81 if (flags & ~(THING_FLAG1 | THING_FLAG2 | THING_FLAG3)) 82 return -EINVAL; 83 84(Se nenhum valor de flag for utilizado ainda, verifique se o argumento de flags 85é zero.) 86 87Para chamadas de sistema mais sofisticadas que envolvem um número maior de 88argumentos, prefere-se encapsular a maioria dos argumentos em uma estrutura 89(struct) que é passada por meio de um ponteiro. Esse tipo de estrutura pode 90lidar com extensões futuras incluindo um argumento de tamanho (size) na própria 91estrutura:: 92 93 struct xyzzy_params { 94 u32 size; /* o espaço do usuário define p->size = sizeof(struct xyzzy_params) */ 95 u32 param_1; 96 u64 param_2; 97 u64 param_3; 98 }; 99 100Desde que qualquer campo adicionado subsequentemente, digamos ``param_4``, seja 101projetado de forma que um valor zero mantenha o comportamento anterior, isso 102permitirá lidar com a divergência de versões em ambas as direções: 103 104 - Para lidar com um programa de espaço do usuário mais novo chamando um kernel 105 mais antigo, o código do kernel deve verificar se qualquer memória além do 106 tamanho da estrutura que ele espera está zerada (efetivamente verificando 107 se ``param_4 == 0``). 108 - Para lidar com um programa de espaço do usuário mais antigo chamando um kernel 109 mais novo, o código do kernel pode preencher com zero (zero-extend) a 110 instância menor da estrutura (efetivamente definindo ``param_4 = 0``). 111 112Veja :manpage:`perf_event_open(2)` e a função ``perf_copy_attr()`` (em 113``kernel/events/core.c``) para um exemplo desta abordagem. 114 115 116Projetando a API: Outras Considerações 117-------------------------------------- 118 119Se a sua nova chamada de sistema permitir que o espaço do usuário se refira a 120um objeto do kernel, ela deve usar um descritor de arquivo (file descriptor) 121como o handle (identificador) para esse objeto -- não invente um novo tipo de 122handle de objeto para o espaço do usuário quando o kernel já possui mecanismos 123e semânticas bem definidas para o uso de descritores de arquivo. 124 125Se a sua nova chamada de sistema (2) de fato retornar un novo descritor de 126arquivo, então o argumento de flags deve incluir um valor que seja equivalente 127a definir ``O_CLOEXEC`` no novo FD. Isso torna possível para o espaço do usuário 128fechar a janela de tempo entre a chamada ``()`` e a execução de 129``fcntl(fd, F_SETFD, FD_CLOEXEC)``, onde um ``fork()`` e ``execve()`` inesperados 130em outra thread poderiam vazar um descritor para o programa executado. (Contudo, 131resista à tentação de reutilizar o valor real da constante ``O_CLOEXEC``, pois 132ela é específica de cada arquitetura e faz parte de um espaço de numeração de 133flags ``O_*`` que está bastante cheio.) 134 135Se a sua chamada de sistema retornar um novo descritor de arquivo, você também 136deve considerar o que significa usar a família de chamadas de sistema 137:manpage:`poll(2)` nesse descritor de arquivo. Tornar um descritor de arquivo 138pronto para leitura ou escrita é a maneira normal de o kernel indicar ao espaço 139do usuário que um evento ocorreu no objeto correspondente do kernel. 140 141Se a sua nova chamada de sistema (2) envolver um argumento de nome de arquivo 142(filename):: 143 144 int sys_xyzzy(const char __user *path, ..., unsigned int flags); 145 146você também deve considerar se uma versão xyzzyat(2) seria mais apropriada:: 147 148 int sys_xyzzyat(int dfd, const char __user *path, ..., unsigned int flags); 149 150Isso permite maior flexibilidade para a forma como o espaço do usuário especifica 151o arquivo em questão; em particular, permite que o espaço do usuário solicite a 152funcionalidade para um descritor de arquivo já aberto usando a flag 153``AT_EMPTY_PATH``, fornecendo efetivamente uma operação fxyzzy(3) de graça:: 154 155 - xyzzyat(AT_FDCWD, path, ..., 0) é equivalente a (path,...) 156 - xyzzyat(fd, "", ..., AT_EMPTY_PATH) é equivalente a fxyzzy(fd, ...) 157 158(Para mais detalhes sobre a justificativa das chamadas \*at(), veja a página de 159manual :manpage:`openat(2)`; para um exemplo de AT_EMPTY_PATH, veja a página de 160manual :manpage:`fstatat(2)`.) 161 162Se a sua nova chamada de sistema (2) envolver um parâmetro que descreve um 163deslocamento (offset) dentro de um arquivo, mude o seu tipo para ``loff_t`` para 164que offsets de 64 bits possam ser suportados mesmo em arquiteturas de 32 bits. 165 166Se a sua nova chamada de sistema (2) envolver funcionalidades privilegiadas, 167ela precisa ser governada pelo bit de capacidade (capability) do Linux apropriado 168(verificado com uma chamada a ``capable()``), conforme descrito na página de 169manual :manpage:`capabilities(7)`. Escolha um bit de capacidade existente que governe 170funcionalidades relacionadas, mas tente evitar combinar muitas funções que tenham 171apenas uma vaga relação sob o mesmo bit, pois isso vai contra o propósito das 172capabilities de dividir o poder do root. Em particular, evite adicionar novos 173usos para a capacidade ``CAP_SYS_ADMIN``, que já é excessivamente generalista. 174 175Se a sua nova chamada de sistema (2) manipular um processo diferente do 176processo que a chamou, ela deve ser restrita (usando uma chamada a 177``ptrace_may_access()``) para que apenas um processo chamador com as mesmas 178permissões do processo alvo, ou com as capacidades necessárias, possa manipular 179o processo alvo. 180 181Finalmente, esteja ciente de que algumas arquiteturas não-x86 lidam melhor se os 182parâmetros da chamada de sistema que são explicitamente de 64 bits caírem em 183argumentos de numeração ímpar (ou seja, parâmetro 1, 3, 5), para permitir o uso 184de pares contíguos de registradores de 32 bits. (Esta preocupação não se aplica 185se os argumentos fizerem parte de uma estrutura que é passada por meio de um 186ponteiro.) 187 188 189Propondo a API 190-------------- 191 192Para tornar as novas chamadas de sistema fáceis de revisar, é melhor dividir o 193conjunto de patches (patchset) em blocos separados. Estes devem incluir, pelo 194menos, os seguintes itens como commits distintos (cada um dos quais é descrito 195mais adiante): 196 197 - A implementação central da chamada de sistema, juntamente com protótipos, 198 numeração genérica, alterações no Kconfig e a implementação de stub de realinhamento (fallback stub). 199 - A fiação (wiring up) da nova chamada de sistema para uma arquitetura em 200 particular, geralmente x86 (incluindo todas as variantes x86_64, x86_32 e x32). 201 - Uma demonstração do uso da nova chamada de sistema no espaço do usuário por 202 meio de um selftest em ``tools/testing/selftests/``. 203 - Um rascunho da página de manual (man-page) para a nova chamada de sistema, 204 seja como texto simples na carta de apresentação (cover letter) ou como um 205 patch para o repositório (separado) de man-pages. 206 207Novas propostas de chamadas de sistema, como qualquer alteração na API do 208kernel, devem sempre ser enviadas com cópia (cc'ed) para linux-api@vger.kernel.org. 209 210 211Implementação Genérica de Chamadas de Sistema 212--------------------------------------------- 213 214O ponto de entrada principal para a sua nova chamada de sistema (2) será chamado 215de ``sys_xyzzy()``, mas você deve adicionar esse ponto de entrada com a macro 216``SYSCALL_DEFINEn()`` apropriada, em vez de fazer isso explicitamente. O 'n' 217indica o número de argumentos da chamada de sistema, e a macro recebe o nome da 218chamada de sistema seguido pelos pares (tipo, nome) para os parâmetros como 219argumentos. O uso dessa macro permite que os metadados sobre a nova chamada de 220sistema fiquem disponíveis para outras ferramentas. 221 222O novo ponto de entrada também precisa de um protótipo de função correspondente 223em ``include/linux/syscalls.h``, marcado como asmlinkage para corresponder à 224maneira como as chamadas de sistema são invocadas:: 225 226 asmlinkage long sys_xyzzy(...); 227 228Algumas arquiteturas (por exemplo, x86) possuem suas próprias tabelas de syscall 229específicas da arquitetura, mas várias outras arquiteturas compartilham uma tabela 230de syscall genérica. Adicione a sua nova chamada de sistema à lista genérica 231adicionando uma entrada na lista em ``include/uapi/asm-generic/unistd.h``:: 232 233 #define __NR_xyzzy 292 234 __SYSCALL(__NR_xyzzy, sys_xyzzy) 235 236Atualize também a contagem de __NR_syscalls para refletir a chamada de sistema 237adicional, e observe que se múltiplas novas chamadas de sistema forem adicionadas 238na mesma janela de mesclagem (merge window), o número da sua nova syscall poderá 239ser ajustado para resolver conflitos. 240 241O arquivo ``kernel/sys_ni.c`` fornece uma implementação de stub de fallback para 242cada chamada de sistema, retornando ``-ENOSYS``. Adicione a sua nova chamada de 243sistema aqui também:: 244 245 COND_SYSCALL(sys_xyzzy); 246 247A sua nova funcionalidade de kernel, e a chamada de sistema que a controla, deve 248normalmente ser opcional, portanto adicione uma opção ``CONFIG`` (tipicamente em 249``init/Kconfig``) para ela. Como de costume para novas opções ``CONFIG``: 250 251 - Inclua uma descrição da nova funcionalidade e da chamada de sistema controlada 252 pela opção. 253 - Faça a opção depender de EXPERT se ela deve ser ocultada dos usuários normais. 254 - Faça com que quaisquer novos arquivos de código-fonte que implementem a função 255 sejam dependentes da opção CONFIG no Makefile (por exemplo, 256 ``obj-$(CONFIG_XYZZY_SYSCALL) += xyzzy.o``). 257 - Verifique duas vezes se o kernel ainda compila com a nova opção CONFIG desativada. 258 259Para resumir, você precisa de um commit que inclua: 260 261 - Opção ``CONFIG`` para a nova função, normalmente em ``init/Kconfig`` 262 - ``SYSCALL_DEFINEn(, ...)`` para o ponto de entrada 263 - Protótipo correspondente em ``include/linux/syscalls.h`` 264 - Entrada na tabela genérica em ``include/uapi/asm-generic/unistd.h`` 265 - Stub de fallback em ``kernel/sys_ni.c`` 266 267 268.. _pt_BR_syscall_generic_6_11: 269 270Desde a versão 6.11 271~~~~~~~~~~~~~~~~~~~ 272 273A partir da versão 6.11 do kernel, a implementação de chamadas de sistema 274genéricas para as seguintes arquiteturas não requer mais modificações em 275``include/uapi/asm-generic/unistd.h``: 276 277 - arc 278 - arm64 279 - csky 280 - hexagon 281 - loongarch 282 - nios2 283 - openrisc 284 - riscv 285 286Em vez disso, você precisa atualizar ``scripts/syscall.tbl`` e, se aplicável, 287ajustar ``arch/*/kernel/Makefile.syscalls``. 288 289Como o ``scripts/syscall.tbl`` serve como uma tabela de syscall comum para 290múltiplas arquiteturas, uma nova entrada é necessária nesta tabela:: 291 292 468 common sys_xyzzy 293 294Note que adicionar uma entrada ao ``scripts/syscall.tbl`` com a ABI "common" 295também afeta todas as arquiteturas que compartilham essa tabela. Para alterações 296mais limitadas ou específicas de uma arquitetura, considere usar uma ABI 297específica da arquitetura ou definir uma nova. 298 299Se uma nova ABI, digamos ``xyz``, for introduzida, as atualizações 300correspondentes também devem ser feitas em ``arch/*/kernel/Makefile.syscalls``:: 301 302 syscall_abis_{32,64} += xyz (...) 303 304Para resumir, você precisa de um commit que inclua: 305 306 - Opção ``CONFIG`` para a nova função, normalmente em ``init/Kconfig`` 307 - ``SYSCALL_DEFINEn(, ...)`` para o ponto de entrada 308 - Protótipo correspondente em ``include/linux/syscalls.h`` 309 - Nova entrada em ``scripts/syscall.tbl`` 310 - (Se necessário) Atualizações de Makefile em ``arch/*/kernel/Makefile.syscalls`` 311 - Stub de fallback em ``kernel/sys_ni.c`` 312 313 314Implementação de Chamadas de Sistema em x86 315------------------------------------------- 316 317Para interligar (wire up) a sua nova chamada de sistema nas plataformas x86, você 318precisa atualizar as tabelas mestras de syscall. Assumindo que a sua nova chamada 319de sistema não seja especial de alguma forma (veja abaixo), isso envolve uma 320entrada "common" (para x86_64 e x32) em 321``arch/x86/entry/syscalls/syscall_64.tbl``:: 322 323 333 common sys_xyzzy 324 325e uma entrada "i386" em ``arch/x86/entry/syscalls/syscall_32.tbl``:: 326 327 380 i386 sys_xyzzy 328 329Novamente, esses números estão sujeitos a alterações caso ocorram conflitos na 330janela de mesclagem (merge window) relevante. 331 332Chamadas de Sistema de Compatibilidade (Genéricas) 333-------------------------------------------------- 334 335Para a maioria das chamadas de sistema, a mesma implementação de 64 bits pode 336ser invocada mesmo quando o programa do espaço do usuário é, ele próprio, de 32 337bits; mesmo se os parâmetros da chamada de sistema incluírem um ponteiro 338explícito, isso é tratado de forma transparente. 339 340No entanto, existem algumas situações em que uma camada de compatibilidade 341(compatibility layer) é necessária para lidar com as diferenças de tamanho entre 34232 bits e 64 bits. 343 344A primeira é se o kernel de 64 bits também suportar programas de espaço do 345usuário de 32 bits e, portanto, precisar analisar áreas de memória 346(``__user``) que poderiam conter valores de 32 bits ou 64 bits. Em particular, 347isso é necessário sempre que um argumento de chamada de sistema for: 348 349 - um ponteiro para um ponteiro 350 - um ponteiro para uma struct que contém um ponteiro (por exemplo, 351 ``struct iovec __user *``) 352 - um ponteiro para um tipo integral de tamanho variável (``time_t``, 353 ``off_t``, ``long``, ...) 354 - um ponteiro para uma struct que contém um tipo integral de tamanho variável. 355 356A segunda situação que requer uma camada de compatibilidade é se um dos 357argumentos da chamada de sistema tiver um tipo que é explicitamente de 64 bits, 358mesmo em uma arquitetura de 32 bits, por exemplo, ``loff_t`` ou ``__u64``. Neste 359caso, um valor que chega ao kernel de 64 bits vindo de uma aplicação de 32 bits 360será dividido em dois valores de 32 bits, que precisarão ser remontados na 361camada de compatibilidade. 362 363(Note que um argumento de chamada de sistema que seja um ponteiro para um tipo 364explícito de 64 bits **não** precisa de uma camada de compatibilidade; por 365exemplo, os argumentos do :manpage:`splice(2)` do tipo ``loff_t __user *`` não 366disparam a necessidade de uma chamada de sistema ``compat_``.) 367 368A versão de compatibilidade da chamada de sistema é chamada de 369``compat_sys_xyzzy()`` e é adicionada com a macro ``COMPAT_SYSCALL_DEFINEn()``, 370de forma análoga à macro SYSCALL_DEFINEn. Esta versão da implementação roda como 371parte de um kernel de 64 bits, mas espera receber valores de parâmetros de 32 372bits e faz o que for necessário para lidar com eles. (Tipicamente, a versão 373``compat_sys_`` converte os valores para versões de 64 bits e chama a versão 374``sys_``, ou ambas chamam uma função interna comum de implementação). 375 376O ponto de entrada compat também precisa de um protótipo de função 377correspondente em ``include/linux/compat.h``, marcado como asmlinkage para 378corresponder à maneira como as chamadas de sistema são invocadas:: 379 380 asmlinkage long compat_sys_xyzzy(...); 381 382Se a chamada de sistema envolver uma estrutura cujo layout seja diferente em 383sistemas de 32 bits e 64 bits, digamos ``struct xyzzy_args``, então o arquivo de 384cabeçalho ``include/linux/compat.h`` também deve incluir uma versão compat da 385estrutura (``struct compat_xyzzy_args``), onde cada campo de tamanho variável 386tenha o tipo ``compat_`` correspondente ao tipo na ``struct xyzzy_args``. A 387rotina ``compat_sys_xyzzy()`` pode então usar essa estrutura ``compat_`` para 388analisar os argumentos vindos de uma invocação de 32 bits. 389 390Por exemplo, se existirem os campos:: 391 392 struct xyzzy_args { 393 const char __user *ptr; 394 __kernel_long_t varying_val; 395 u64 fixed_val; 396 /* ... */ 397 }; 398 399na struct xyzzy_args, então a struct compat_xyzzy_args teria:: 400 401 struct compat_xyzzy_args { 402 compat_uptr_t ptr; 403 compat_long_t varying_val; 404 u64 fixed_val; 405 /* ... */ 406 }; 407 408A lista genérica de chamadas de sistema também precisa de ajustes para permitir 409a versão compat; a entrada em ``include/uapi/asm-generic/unistd.h`` deve usar 410``__SC_COMP`` em vez de ``__SYSCALL``:: 411 412 #define __NR_xyzzy 292 413 __SC_COMP(__NR_xyzzy, sys_xyzzy, compat_sys_xyzzy) 414 415Para resumir, você precisa de: 416 417 - uma macro ``COMPAT_SYSCALL_DEFINEn(, ...)`` para o ponto de entrada compat 418 - protótipo correspondente em ``include/linux/compat.h`` 419 - (se necessário) struct de mapeamento de 32 bits em ``include/linux/compat.h`` 420 - instância de ``__SC_COMP``, e não de ``__SYSCALL``, em 421 ``include/uapi/asm-generic/unistd.h`` 422 423Desde a versão 6.11 424~~~~~~~~~~~~~~~~~~~ 425 426Isso se aplica a todas as arquiteturas listadas em 427:ref:`Desde a versão 6.11<pt_BR_syscall_generic_6_11>` sob "Implementação Genérica de 428Chamadas de Sistema", exceto arm64. Veja 429:ref:`Chamadas de Sistema de Compatibilidade (arm64)<pt_BR_compat_arm64>` para mais 430informações. 431 432Você precisa estender a entrada em ``scripts/syscall.tbl`` com uma coluna extra 433para indicar que um programa de espaço do usuário de 32 bits rodando em um 434kernel de 64 bits deve atingir o ponto de entrada compat:: 435 436 468 common sys_xyzzy compat_sys_xyzzy 437 438Para resumir, você precisa de: 439 440 - ``COMPAT_SYSCALL_DEFINEn(, ...)`` para o ponto de entrada compat 441 - Protótipo correspondente em ``include/linux/compat.h`` 442 - Modificação da entrada em ``scripts/syscall.tbl`` para incluir uma coluna 443 "compat" extra 444 - (Se necessário) Struct de mapeamento de 32 bits em ``include/linux/compat.h`` 445 446 447.. _pt_BR_compat_arm64: 448 449Chamadas de Sistema de Compatibilidade (arm64) 450^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 451 452No arm64, existe uma tabela de syscall dedicada para chamadas de sistema de 453compatibilidade voltadas para o espaço do usuário de 32 bits (AArch32): 454``arch/arm64/tools/syscall_32.tbl``. Você precisa adicionar uma linha adicional 455a esta tabela especificando o ponto de entrada compat:: 456 457 468 common sys_xyzzy compat_sys_xyzzy 458 459 460Chamadas de Sistema de Compatibilidade (x86) 461-------------------------------------------- 462 463Para interligar a arquitetura x86 de uma chamada de sistema com uma versão de 464compatibilidade, as entradas nas tabelas de syscall precisam ser ajustadas. 465 466Primeiro, a entrada em ``arch/x86/entry/syscalls/syscall_32.tbl`` ganha uma 467coluna extra para indicar que um programa de espaço do usuário de 32 bits rodando 468em um kernel de 64 bits deve atingir o ponto de entrada compat:: 469 470 380 i386 sys_xyzzy __ia32_compat_sys_xyzzy 471 472Segundo, você precisa definir o que deve acontecer para a versão da ABI x32 da 473nova chamada de sistema. Há uma escolha aqui: o layout dos argumentos deve 474corresponder à versão de 64 bits ou à versão de 32 bits. 475 476Se houver um ponteiro para um ponteiro envolvido, a decisão é fácil: x32 é 477ILP32 (inteiro, long e ponteiro possuem 32 bits), portanto o layout deve 478corresponder à versão de 32 bits, e a entrada em 479``arch/x86/entry/syscalls/syscall_64.tbl`` é dividida para que os programas x32 480atinjam o wrapper de compatibilidade:: 481 482 333 64 sys_xyzzy 483 ... 484 555 x32 __x32_compat_sys_xyzzy 485 486Se não houver ponteiros envolvidos, então é preferível reutilizar a chamada de 487sistema de 64 bits para a ABI x32 (e, consequentemente, a entrada em 488``arch/x86/entry/syscalls/syscall_64.tbl`` permanece inalterada). 489 490Em qualquer um dos casos, você deve verificar se os tipos envolvidos no layout 491dos seus argumentos de fato se mapeiam exatamente do x32 (-mx32) para os seus 492equivalentes de 32 bits (-m32) ou 64 bits (-m64). 493 494 495Chamadas de Sistema com Retorno para Outro Local 496------------------------------------------------ 497 498Para a maioria das chamadas de sistema (syscalls), assim que a execução é 499concluída, o programa do usuário continua exatamente de onde parou -- na 500próxima instrução, com a pilha idêntica e a maior parte dos registradores no 501mesmo estado de antes da chamada, além do mesmo espaço de memória virtual. 502 503No entanto, algumas poucas chamadas de sistema agem de forma diferente. Elas 504podem retornar para um local distinto (``rt_sigreturn``), alterar o espaço de 505memória (``fork``/``vfork``/``clone``) ou até mesmo modificar a arquitetura 506(``execve``/``execveat``) do programa. 507 508Para permitir isso, a implementação da chamada de sistema no kernel pode 509precisar salvar e restaurar registradores adicionais na pilha do kernel, 510garantindo controle total de onde e como a execução continuará após a syscall. 511 512Isso é específico de cada arquitetura (arch-specific), mas tipicamente envolve 513a definição de pontos de entrada em assembly que salvam/restauram esses 514registradores adicionais e invocam o ponto de entrada real da chamada de 515sistema. 516 517Para x86_64, isso é implementado como um ponto de entrada ``stub_xyzzy`` em 518``arch/x86/entry/entry_64.S``, e a entrada correspondente na tabela de syscalls 519(``arch/x86/entry/syscalls/syscall_64.tbl``) é ajustada para refletir:: 520 521 333 common stub_xyzzy 522 523O equivalente para programas de 32 bits executados em um kernel de 64 bits é 524normalmente chamado de ``stub32_xyzzy`` e implementado em 525``arch/x86/entry/entry_64_compat.S``, com o respectivo ajuste na tabela de 526syscalls em ``arch/x86/entry/syscalls/syscall_32.tbl``:: 527 528 380 i386 sys_xyzzy stub32_xyzzy 529 530Se a chamada de sistema precisar de uma camada de compatibilidade (como na 531seção anterior), a versão ``stub32_`` precisará chamar a versão 532``compat_sys_`` da chamada de sistema em vez da versão nativa de 64 bits. Além 533disso, se a implementação da ABI x32 não for compartilhada com a versão 534x86_64, sua tabela de syscalls também precisará invocar um stub que direcione 535para a versão ``compat_sys_``. 536 537Por questões de integridade, também é recomendado configurar um mapeamento para 538que o User-Mode Linux (UML) continue funcionando -- sua tabela de syscalls fará 539referência a ``stub_xyzzy``, mas o build do UML não inclui a implementação de 540``arch/x86/entry/entry_64.S`` (já que o UML simula registradores, etc.). Corrigir 541isso é tão simples quanto adicionar um #define em 542``arch/x86/um/sys_call_table_64.c``:: 543 544 #define stub_xyzzy sys_xyzzy 545 546 547Outros Detalhes 548--------------- 549 550A maior parte do kernel trata as chamadas de sistema de maneira genérica, mas 551há exceções ocasionais que podem precisar de atualização para a sua chamada 552de sistema específica. 553 554O subsistema de auditoria (audit) é um desses casos especiais; ele inclui 555funções (específicas de cada arquitetura) que classificam alguns tipos 556especiais de chamada de sistema -- especificamente operações de abertura de 557arquivo (``open``/``openat``), execução de programa (``execve``/``exeveat``) ou 558multiplexador de socket (``socketcall``). Se a sua nova chamada de sistema for 559análoga a uma dessas, o sistema de auditoria deverá ser atualizado. 560 561De forma mais geral, se existir uma chamada de sistema atual que seja análoga 562à sua nova chamada de sistema, vale a pena fazer um grep em todo o kernel pela 563chamada existente para verificar se não há outros casos especiais. 564 565 566Testes 567------ 568 569Uma nova chamada de sistema deve, obviamente, ser testada; também é útil 570fornecer aos revisores uma demonstração de como os programas do espaço do 571usuário (user space) usarão a chamada de sistema. Uma boa maneira de combinar 572esses objetivos é incluir um programa simples de autoteste em um novo diretório 573sob ``tools/testing/selftests/``. 574 575Para uma nova chamada de sistema, obviamente não haverá uma função de wrapper 576na libc e, portanto, o teste precisará invocá-la usando ``syscall()``; além 577disso, se a chamada de sistema envolver uma nova estrutura visível para o 578espaço do usuário, o cabeçalho correspondente precisará ser instalado para 579compilar o teste. 580 581Certifique-se de que o autoteste seja executado com sucesso em todas as 582arquiteturas suportadas. Por exemplo, verifique se ele funciona quando compitado 583como um programa ABI x86_64 (-m64), x86_32 (-m32) e x32 (-mx32). 584 585Para testes mais extensos e minuciosos de novas funcionalidades, você também 586deve considerar a adição de testes ao Linux Test Project ou ao projeto 587xfstests para alterações relacionadas 588 589Página de Manual (Man Page) 590--------------------------- 591 592Todas as novas chamadas de sistema devem vir acompanhadas de uma página de 593manual completa, idealmente usando a marcação groff, mas texto simples também 594é aceitável. Se o groff for utilizado, é útil incluir uma versão ASCII pré- 595renderizada da página de manual no e-mail de apresentação (cover letter) do 596conjunto de patches (patchset), para a conveniência dos revisores. 597 598A página de manual deve ser enviada com cópia (cc) para 599linux-man@vger.kernel.org. Para mais detalhes, consulte 600https://www.kernel.org/doc/man-pages/patches.html 601 602 603Não invoque Chamadas de Sistema dentro do Kernel 604------------------------------------------------ 605 606As chamadas de sistema são, como mencionado acima, pontos de interação entre o 607espaço do usuário (userspace) e o kernel. Portanto, funções de chamada de 608sistema como ``sys_xyzzy()`` ou ``compat_sys_xyzzy()`` só devem ser chamadas a 609partir do espaço do usuário por meio da tabela de syscalls, e não de outros 610lugares do kernel. Se a funcionalidade da syscall for útil para ser utilizada 611dentro do kernel, precisar ser compartilhada entre uma syscall antiga e uma 612nova, ou precisar ser compartilhada entre uma syscall e sua variante de 613compatibilidade, ela deve ser implementada por meio de uma função auxiliadora 614("helper", como ``ksys_xyzzy()``). Essa função do kernel poderá então ser 615chamada dentro do stub da syscall (``sys_xyzzy()``), do stub da syscall de 616compatibilidade (``compat_sys_xyzzy()``) e/ou de outro código do kernel. 617 618Pelo menos em x86 de 64 bits, será um requisito rígido a partir da versão v4.17 619em diante não chamar funções de chamadas de sistema no kernel. Essa arquitetura 620utiliza uma convenção de chamada diferente para chamadas de sistema na qual a 621``struct pt_regs`` é decodificada dinamicamente em um wrapper de syscall, que 622então repassa o processamento para a função real da syscall. Isso significa que 623apenas os parâmetros realmente necessários para uma syscall específica são 624passados durante a entrada da syscall, em vez de preencher seis registradores da 625CPU com conteúdos aleatórios do espaço do usuário o tempo todo (o que poderia 626causar problemas sérios no decorrer da cadeia de chamadas). 627 628Além disso, as regras sobre como os dados podem ser acessados diferem entre os 629dados do kernel e os dados do usuário. Essa é outra razão pela qual chamar 630``sys_xyzzy()`` geralmente é uma má ideia. 631 632Exceções a essa regra são permitidas apenas em substituições (overrides) 633específicas de cada arquitetura, wrappers de compatibilidade específicos de cada 634arquitetura ou outros códigos dentro do diretório arch/. 635 636Referências e Fontes 637-------------------- 638 639 - Artigo da LWN por Michael Kerrisk sobre o uso do argumento flags em chamadas 640 de sistema: 641 https://lwn.net/Articles/585415/ 642 - Artigo da LWN por Michael Kerrisk sobre como lidar com flags desconhecidas 643 em uma chamada de sistema: https://lwn.net/Articles/588444/ 644 - Artigo da LWN por Jake Edge descrevendo restrições em argumentos de chamadas 645 de sistema de 64 bits: https://lwn.net/Articles/311630/ 646 - Par de artigos da LWN por David Drysdale que descrevem detalhadamente os 647 caminhos de implementação de chamadas de sistema para a v3.14: 648 649 - https://lwn.net/Articles/604287/ 650 - https://lwn.net/Articles/604515/ 651 652 - Os requisitos específicos de arquitetura para chamadas de sistema são 653 discutidos na página de manual :manpage:`syscall(2)`: 654 http://man7.org/linux/man-pages/man2/syscall.2.html#NOTES 655 - E-mails compilados de Linus Torvalds discutindo os problemas com ``ioctl()``: 656 https://yarchive.net/comp/linux/ioctl.html 657 - "How to not invent kernel interfaces", Arnd Bergmann, 658 https://www.ukuug.org/events/linux2007/2007/papers/Bergmann.pdf 659 - Artigo da LWN por Michael Kerrisk sobre evitar novos usos de CAP_SYS_ADMIN: 660 https://lwn.net/Articles/486306/ 661 - Recomendação de Andrew Morton para que todas as informações relacionadas a 662 uma nova chamada de sistema venham na mesma thread de e-mail: 663 https://lore.kernel.org/r/20140724144747.3041b208832bbdf9fbce5d96@linux-foundation.org 664 - Recomendação de Michael Kerrisk para que uma nova chamada de sistema venha 665 acompanhada de uma página de manual: 666 https://lore.kernel.org/r/CAKgNAkgMA39AfoSoA5Pe1r9N+ZzfYQNvNPvcRN7tOvRb8+v06Q@mail.gmail.com 667 - Sugestão de Thomas Gleixner para que a vinculação (wire-up) do x86 esteja em 668 um commit separado: 669 https://lore.kernel.org/r/alpine.DEB.2.11.1411191249560.3909@nanos 670 - Sugestão de Greg Kroah-Hartman de que é bom que novas chamadas de sistema 671 venham acompanhadas de uma página de manual e um autoteste: 672 https://lore.kernel.org/r/20140320025530.GA25469@kroah.com 673 - Discussão de Michael Kerrisk sobre uma nova chamada de sistema versus a 674 extensão de :manpage:`prctl(2)`: 675 https://lore.kernel.org/r/CAHO5Pa3F2MjfTtfNxa8LbnkeeU8=YJ+9tDqxZpw7Gz59E-4AUg@mail.gmail.com 676 - Sugestão de Ingo Molnar de que as chamadas de sistema que envolvem múltiplos 677 argumentos devem encapsular esses argumentos em uma struct, a qual inclua um 678 campo de tamanho (size) para fins de extensibilidade futura: 679 https://lore.kernel.org/r/20150730083831.GA22182@gmail.com 680 - Excentricidades de numeração decorrentes do uso (e reuso) de flags do espaço 681 de numeração O_*: 682 683 - commit 75069f2b5bfb ("vfs: renumber FMODE_NONOTIFY and add to uniqueness 684 check") 685 - commit 12ed2e36c98a ("fanotify: FMODE_NONOTIFY and __O_SYNC in sparc 686 conflict") 687 - commit bb458c644a59 ("Safer ABI for O_TMPFILE") 688 689 - Discussão de Matthew Wilcox sobre restrições em argumentos de 64 bits: 690 https://lore.kernel.org/r/20081212152929.GM26095@parisc-linux.org 691 - Recomendação de Greg Kroah-Hartman de que flags desconhecidas devem ser 692 fiscalizadas/policiadas: 693 https://lore.kernel.org/r/20140717193330.GB4703@kroah.com 694 - Recomendação de Linus Torvalds de que as chamadas de sistema x32 devem 695 preferir a compatibilidade com as versões de 64 bits em vez das versões de 696 32 bits: 697 https://lore.kernel.org/r/CA+55aFxfmwfB7jbbrXxa=K7VBYPfAvmu3XOkGrLbB1UFjX1+Ew@mail.gmail.com 698 - Série de patches revisando a infraestrutura da tabela de chamadas de sistema 699 para utilizar scripts/syscall.tbl em múltiplas arquiteturas: 700 https://lore.kernel.org/lkml/20240704143611.2979589-1-arnd@kernel.org 701