2010-12-23 9 views
45

Esperaba que alguien pudiera explicar los matices de la macro __user utilizada en la fuente del kernel de Linux.¿Cuáles son las implicaciones de la macro linux __user?

En primer lugar, la macro:

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

Ahora, después de algunas google leí que esta macro le permite a uno para designar a un puntero como pertenecientes al espacio de direcciones del usuario, y que no se deben dereferenciar.

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!

+2

Consulte la fuente do_execve() para ver un buen ejemplo. Vea cómo se usa argv en count(). Si simplemente desreferencia (* argv [0]) o algo así, escaso (1) lo advertirá. address_space dice que no todos los punteros son iguales, requieren reglas diferentes (deferencia) y no deben mezclarse. – adobriyan

Respuesta

33

Permite que las herramientas como sparse digan 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) incorrectamente.

+0

Entonces '__attribute __()' ¿puede usar cualquier texto arbitrario como un "atributo"? No se limita a un conjunto fijo que sea significativo para GCC. –

+0

@AlexD del [Manual de sintaxis de atributos de GCC] (https://gcc.gnu.org/onlinedocs/gcc/Attribute-Syntax.html): 'Un especificador de atributo tiene la forma __attribute__ ((attribute-list)). Una lista de atributos es una secuencia de atributos separada por comas, posiblemente vacía, donde cada atributo es uno de los siguientes: 1. Vacío. Los atributos vacíos son ignorados. ** 2. Un nombre de atributo (que puede ser un identificador como no utilizado, o una palabra reservada como const). ** (...) '. Parece que podría ser cualquier identificador que desee (utilizando las convenciones de nomenclatura de identificadores). –

27

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 la definición/descripción formal, pero la única parte que conozco.

+2

esperando los comentarios, por qué mi respuesta es downvoted. –

+2

lol ... la gente ama el voto abajo aquí; P – Junaid

+0

sí, que deja que el copy_to_user tenga sentido – David

2

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, 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 menciona las macros como __user/__kernel/__force etc., guarda un significado especial para disperso. En la lista de correo del kernel de Linux, Linus Torvalds explica el uso de esta manera:

Esto es importante recordar: para gcc, las anotaciones dispersas no tienen sentido. Todavía pueden ser útiles solo para decirle al programador 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 lo hacen cualquier cosa.

SIN EMBARGO. Cuando hace uso parse, es otra cosa completamente distinta. Por "escasa", que "__iomem" tiene un montón de significado:

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

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

si el puntero está siempre eliminan las referencias (que es un " noderef "puntero" directamente, y está en "espacio de direcciones 2" en lugar del espacio de direcciones normal (0).

Ahora, eso significa que escasa se quejará si un puntero tal vez se pasa a una función que quiere un puntero normal (porque es no un puntero normal, y es obvio que no debe hacer cosas como " strcmp() "etc. en él) y disperso también se quejará si intentas convertirlo a otro puntero en otro espacio de direcciones.

Cuestiones relacionadas