¿Cuáles son las implicaciones de la macro linux __user?

Esperaba que alguien pudiera explicar los matices de la macro __user usada en la fuente del kernel de Linux.

Primero que nada, la macro:

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

Ahora, después de buscar en Google, leí que esta macro permite designar un puntero como perteneciente al espacio de direcciones del usuario, y que no debe ser desreferenciado.

Me pueden estar perdiendo algunos hechos obvios, pero ¿podría alguien explicar las implicaciones de tal macro? Por ejemplo, ¿cuál es un buen ejemplo de dónde esta macro sería útil? Nuevamente, perdónenme si me falta algo obvio.

Para poner esto en contexto, crucé la macro mientras examinaba un código USB (linux / usbdevice_fs.h). Solo estoy buscando una comprensión general de estas macros (u otras similares) en el kernel.

¡Gracias por mirar!

Permite que herramientas como scatter digan incorrectamente a los desarrolladores del kernel que posiblemente estén utilizando un puntero no confiable (o un puntero que puede no ser válido en la asignación de la dirección virtual actual).

Creo que __user marca los punteros del espacio del usuario y le dice al desarrollador / sistema que no confíe en él. Si el usuario le da un puntero “inválido”, entonces kernel intenta hacer referencia a él (tenga en cuenta que el kernel puede hacer referencia en todas partes) y puede corromper su propio espacio.

Por ejemplo, en “leer” (en usbdevice_fs.h) debe proporcionarle un búfer (__user) para escribir el resultado. Entonces debes usar copy_to_user, pero no memcopy, strcpy o algo como esto.

Nota: Esta no es definición / descripción formal, sino la única parte que conozco.

La macro __user se define con algunas otras macros como __force / __kernel etc. en el archivo de encabezado compiler.h. En realidad, no son de ninguna utilidad para los comstackdores tradicionales, como GCC / ICC, etc. Pero es útil para las herramientas de análisis estático del kernel, como Sparse (más información aquí: Sparse – Linux Kernel Newbies). Cuando mencionas las macros como __user / __kernel / __force etc, guarda un significado especial para sparse. En la lista de distribución del kernel de Linux, Linus Torvalds explica el uso de esta manera:

Es importante recordar esto: para gcc, las anotaciones dispersas no tienen sentido. Todavía pueden ser útiles simplemente para decirle al progtwigdor que “hey, ese puntero que obtuviste no era un puntero normal” de una manera bastante legible, pero al final, a menos que uses escaso, en realidad no hacen nada.

SIN EMBARGO. Cuando usas parse, es otra cosa completamente distinta. Para “escaso”, ese “__iomem” tiene mucho significado:

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

es decir, “iomem” significa dos cosas separadas: significa que disperso debería quejarse

si el puntero es alguna vez desreferenciado (es un puntero “noderef”) directamente, y está en “espacio de direcciones 2” en oposición al espacio de direcciones normal (0).

Ahora, eso significa que Sparse se quejará si ese puntero alguna vez pasa a una función que quiere un puntero regular (porque no es un puntero normal, y obviamente no deberías hacer cosas como “strcmp ()”, etc.) , y disperso también se quejará si intenta convertirlo a otro puntero en otro espacio de direcciones.