Quali sono le implicazioni della macro linux __user?

Speravo che qualcuno potesse spiegare le sfumature della macro __user usata nel sorgente del kernel linux.

Prima di tutto, la macro:

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

Ora, dopo alcuni googling, ho letto che questa macro consente di designare un puntatore come appartenente allo spazio degli indirizzi utente e che non dovrebbe essere dereferenziato.

Potrei mancare alcuni fatti ovvi, ma qualcuno potrebbe spiegare le implicazioni di una simile macro? Ad esempio, qual è un buon esempio di dove questa macro sarebbe utile? Di nuovo, perdonami se mi manca qualcosa di ovvio.

Per mettere questo in un certo contesto, sono arrivato attraverso la macro mentre esaminavo un codice USB (linux / usbdevice_fs.h). Sto solo cercando una comprensione generale di questa macro (o di altri simili) all’interno del kernel.

Grazie per aver guardato!

Permette a strumenti come sparse di dire agli sviluppatori del kernel che probabilmente stanno usando un puntatore non sicuro (o un puntatore che potrebbe non essere valido nella mapping dell’indirizzo virtuale corrente) in modo improprio.

Penso che __user segni i puntatori dello spazio degli utenti e dice allo sviluppatore / sistema di non fidarsi di esso. Se l’utente fornisce un puntatore “non valido”, il kernel prova a farvi riferimento (si noti che il kernel può fare riferimento ovunque) e può danneggiare il proprio spazio.

Ad esempio in “read” (in you usbdevice_fs.h) dovresti fornire un buffer (__user) per scrivere il risultato. Quindi devi usare copy_to_user, ma non memcopy, strcpy o qualcosa del genere.

Nota: questa non è una definizione / descrizione formale, ma l’unica parte di cui sono a conoscenza.

La macro __user è definita con alcune altre macro come __force / __kernel ecc nel file di intestazione compiler.h. In realtà non sono di alcuna utilità per i compilatori tradizionali, inclusi GCC / ICC ecc. Ma è utile per gli strumenti di analisi statica del kernel come sparse (maggiori informazioni qui: Sparse – Linux Kernel Newbies). Quando si menzionano macro come __user / __kernel / __force ecc, mantiene un significato speciale per sparse. Nella mailing list del kernel Linux, Linus Torvalds spiega l’uso di questo in questo modo:

Questo è importante da ricordare: per gcc, le annotazioni sparse sono prive di significato. Possono ancora essere utili solo per dire al programmatore che “hey, quel puntatore che hai ottenuto non era un normale puntatore” in un modo abbastanza leggibile, ma alla fine, a meno che tu non usi sparse, in realtà non fanno nulla.

PERÒ. Quando usi l’analisi, è tutta un’altra questione. Per “sparse”, quel “__iomem” ha un sacco di significato:

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

cioè “iomem” significa due cose separate: significa che sparse dovrebbe lamentarsi

se il puntatore è mai dereferenziato (è un puntatore “noderef”) direttamente, e si trova nello “spazio indirizzo 2” in opposizione al normale spazio indirizzo (0).

Ora, ciò significa che sparse si lamenterà se un tale puntatore viene mai passato in una funzione che vuole un puntatore regolare (perché non è un puntatore normale, e ovviamente non dovrebbe fare cose come “strcmp ()” ecc.) e sparse si lamenterà anche se proverai a lanciarlo su un altro puntatore in un altro spazio indirizzo.