Quais são as implicações da macro __user do linux?

Eu estava esperando que alguém pudesse explicar as nuances da macro __user usada na fonte do kernel do Linux.

Primeiro de tudo, a macro:

# define __user __attribute__((noderef, address_space(1))) 

Agora, depois de algumas pesquisas, eu li que essa macro permite designar um ponteiro como pertencente ao espaço de endereço do usuário e que ele não deve ser desreferenciado.

Eu posso estar perdendo alguns fatos óbvios, mas alguém poderia explicar as implicações de tal macro? Por exemplo, qual é um bom exemplo de onde essa macro seria útil? Mais uma vez, perdoe-me se estiver faltando alguma coisa óbvia.

Para colocar isso em algum contexto, eu vi a macro enquanto examinava algum código USB (linux / usbdevice_fs.h). Eu estou apenas procurando por um entendimento geral de que essas macros (ou outras semelhantes) usam dentro do kernel.

Obrigado por olhar!

Ele permite que ferramentas como esparsas digam aos desenvolvedores do kernel que eles possivelmente estão usando um ponteiro não confiável (ou um ponteiro que pode ser inválido no atual mapeamento de endereço virtual) de forma incorreta.

Eu acho que o __user marca os pointers do espaço do usuário e diz ao desenvolvedor / sistema para não confiar nele. Se o usuário lhe der um ponteiro “inválido”, então o kernel tenta referenciá-lo (observe que o kernel pode referenciar em qualquer lugar) e pode corromper seu próprio espaço.

Por exemplo, em “read” (em você usbdevice_fs.h) deve fornecer um buffer (__user) para gravar o resultado. Então você tem que usar copy_to_user, mas não memcopy, strcpy ou algo assim.

Nota: Esta não é uma definição / descrição formal, mas a única parte que conheço.

A macro __user é definida com algumas outras macros como __force / __kernel etc no arquivo de header compilador.h. Eles na verdade não são de uso algum para compiladores tradicionais, incluindo GCC / ICC etc. Mas é útil para ferramentas de análise estática do kernel como esparsas (mais informações aqui: Sparse – Linux Kernel Newbies). Quando você menciona as macros como __user / __kernel / __force etc, ele mantém um significado especial para o escasso. Na lista de discussão do kernel do Linux, Linus Torvalds explica o uso dele assim:

Isso é importante lembrar: para o gcc, as annotations esparsas não têm sentido. Eles ainda podem ser úteis apenas para dizer ao programador que “ei, aquele ponteiro que você obteve não era um ponteiro normal” de uma maneira razoavelmente legível, mas no final, a menos que você use esparsos, eles na verdade não fazem nada.

CONTUDO. Quando você usa a análise, é outra questão inteiramente. Para “esparso”, esse “__iomem” tem muito significado:

 # define __iomem __attribute__((noderef, address_space(2))) 

ou seja, “iomem” significa duas coisas separadas: significa que esparsas devem reclamar

se o ponteiro é sempre desreferenciado (é um ponteiro “noderef”) diretamente, e está em “espaço de endereço 2” em oposição ao espaço de endereço normal (0).

Agora, isso significa que sparse irá reclamar se tal ponteiro é passado para uma function que quer um ponteiro regular (porque não é um ponteiro normal, e obviamente você não deve fazer coisas como “strcmp ()” etc.) e sparse também irá reclamar se você tentar convertê-lo em outro ponteiro em outro espaço de endereço.