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

4 minutos de lectura

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 buscar en Google, leí que esta macro permite designar un puntero como perteneciente al espacio de direcciones del usuario, y que no se debe quitar la referencia.

Es posible que me falten algunos hechos obvios, pero ¿alguien podría explicar las implicaciones de tal macro? Por ejemplo, ¿cuál es un buen ejemplo de dónde sería útil esta macro? Nuevamente, perdóname si me estoy perdiendo algo obvio.

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

¡Gracias por mirar!

  • Vea la fuente do_execve() para un buen ejemplo. Vea cómo se usa argv en count(). Si simplemente quitaras la referencia (*argv[0]) o algo así, sparse(1) lo advertirá. address_space dice que no todos los punteros son iguales, lo que requiere reglas diferentes (desreferencia) y no se deben mezclar.

    – adobriyan

    24 de diciembre de 2010 a las 17:12


  • @adobriyan, ¿en qué encabezado o archivo fuente puedo encontrar esta función? No quiero grep mientras que el sistema de archivos para encontrarlo. Un camino será suficiente

    – Pastor

    9 de mayo de 2020 a las 21:04

Permite herramientas como escaso para decirles 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 el mapeo de direcciones virtuales actual) de manera incorrecta.

  • Entonces __attribute__() puede usar cualquier texto arbitrario como un “atributo”? ¿No está limitado a un conjunto fijo que sea significativo para el propio GCC?

    – Alex D.

    23/03/2015 a las 20:10

  • @AlexD Desde el Manual de sintaxis de atributos GCC: An attribute specifier is of the form __attribute__ ((attribute-list)). An attribute list is a possibly empty comma-separated sequence of attributes, where each attribute is one of the following: 1. Empty. Empty attributes are ignored. **2. An attribute name (which may be an identifier such as unused, or a reserved word such as const).** (...). Parece que podría ser cualquier identificador que desee (usando convenciones de nomenclatura de identificadores).

    – Enzo Ferber

    30 de diciembre de 2015 a las 18:45

Creo que __user marca 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 su dispositivo usb_fs.h) debería proporcionarle un búfer (__usuario) para escribir el resultado. Por lo tanto, debe usar copy_to_user, pero no memcopy, strcpy ni nada por el estilo.

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

  • sí, eso permite que copy_to_user tenga sentido

    – hukeping

    9 de julio de 2014 a las 4:12

avatar de usuario
Chintan Shah

los __user macro se define con algunas otras macros como __force/__kernel etc. en el archivo de cabecera compiler.h. En realidad, no son útiles para los compiladores tradicionales, incluidos GCC/ICC, etc. Pero son útiles 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., mantiene un significado especial para escaso. En la lista de correo del kernel de Linux, Linus Torvalds explica su uso de la siguiente manera:

Es importante recordar esto: para gcc, las anotaciones escasas no tienen sentido. Todavía 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 sparse, en realidad no hacer cualquier cosa.

SIN EMBARGO. Cuando usted hacer use parse, es otra cuestión completamente diferente. Para “escaso”, ese “__iomem” tiene mucho significado:

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

es decir, “iomem” significa dos cosas separadas: significa que escaso debe quejarse

si el puntero alguna vez se desreferencia (es un puntero “noderef”) directamente, y está en el “espacio de direcciones 2” en lugar del espacio de direcciones normal (0).

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

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad