c macros linux-kernel kernel

¿Cuáles son las implicaciones de la macro linux__user?



macros linux-kernel (3)

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

Por ejemplo, en "leer" (en usted usbdevice_fs.h) debería proporcionarle un búfer (__user) en el que escribir el resultado. Así que tienes que usar copy_to_user, pero no memcopy, strcpy o algo así.

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

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

En primer lugar, la macro:

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

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

Puede que me falten algunos datos obvios, pero ¿podría alguien explicar las implicaciones de tal macro? Por ejemplo, ¿cuál es un buen ejemplo de dónde sería útil esta macro? De nuevo, perdóname si me falta algo obvio.

Para poner esto en un contexto, me encontré con la macro mientras examinaba un código USB (linux / usbdevice_fs.h). Solo busco una comprensión general de este uso de macros (u otros similares) dentro del kernel.

¡Gracias por mirar!


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 compiladores tradicionales, incluidos GCC / ICC, etc. Pero es útil para las herramientas de análisis estático del kernel como escasos (más información aquí: Sparse - Linux Kernel Newbies). Cuando mencionas las macros como __user / __kernel / __force etc, se mantiene un significado especial para dispersos. En la lista de correo del kernel de Linux, Linus Torvalds explica el uso de esta manera:

Es importante recordar esto: para gcc, las anotaciones dispersas no tienen sentido. Aún pueden ser útiles solo para decirle al programador que "oye, ese puntero que obtuviste no era un puntero normal" de una manera bastante legible, pero al final, a menos que uses poca, no hacen nada.

SIN EMBARGO. Cuando usas el análisis, es otra cuestión completamente. Para "sparse", ese "__iomem" tiene mucho significado:

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

es decir, "iomem" significa dos cosas separadas: significa que sparse debería quejarse

si el puntero es referenciado directamente (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 Spark se quejará si ese puntero se pasa a una función que quiere un puntero normal (porque no es un puntero normal, y obviamente no debería hacer cosas como "strcmp ()", etc.) , y sparse también se quejará si intentas lanzarlo a otro puntero en otro espacio de direcciones.


Permite que herramientas como sparse digan a los desarrolladores del kernel que posiblemente están usando un puntero que no es de confianza (o un puntero que puede no ser válido en la asignación de direcciones virtuales actual) de manera incorrecta.