wandres.dev
LA FRONTERA CON EL USUARIO · copy_*_user, capabilities

Permisos, capabilities y el contexto

En la frontera, el kernel decide quién puede hacer qué. Las capabilities granulares, la comprobación de permisos, y la macro current que identifica quién te llama.

⏱ 10 min

Cruzar datos con seguridad (nivel 12.1) es la mitad; la otra es decidir si quien pide algo tiene derecho. El kernel tiene un sistema de permisos granular más allá del clásico root, y una forma de saber siempre quién está al otro lado de la syscall.

🎯 Al terminar esta lección sabrás
  • La macro current: quién te llama.
  • Comprobar permisos con capable.
  • Capabilities granulares vs root.
  • Contexto de proceso vs interrupción.

current: quién está llamando

En contexto de proceso, la macro current te da un puntero al task_struct (nivel 25) del proceso que ejecutó la syscall — quién te está llamando:

printk(KERN_INFO "me llama el proceso %s (PID %d)\n",
       current->comm, current->pid);

Es tu identidad del llamador: su PID, su nombre, sus credenciales, su usuario. La base para decidir permisos.

Comprobar permisos: capable

Antes de una operación privilegiada, el kernel comprueba si el llamador tiene el permiso adecuado:

if (!capable(CAP_NET_ADMIN))
	return -EPERM;        /* no tiene el permiso de administrar red */

Capabilities: root, dividido en piezas

Capabilities: el principio de mínimo privilegio en el kernel

El modelo clásico de Unix era binario: o eres root (todopoderoso) o no (limitado). Eso es peligroso — un programa que solo necesita, digamos, abrir puertos bajos no debería tener también permiso para reformatear discos. Las capabilities de Linux parten el poder de root en piezas granulares: CAP_NET_ADMIN (red), CAP_SYS_ADMIN (admin del sistema), CAP_SYS_MODULE (cargar módulos), CAP_DAC_OVERRIDE (saltarse permisos de archivos), y decenas más. Así un servicio recibe solo las capabilities que necesita, y un fallo suyo compromete mucho menos. Cuando escribas un driver con operaciones privilegiadas, comprueba la capability específica y mínima que corresponda —no CAP_SYS_ADMIN por pereza, que es casi como pedir root entero—. Este es el principio de mínimo privilegio (nivel 26 de C23) aplicado dentro del kernel: da y exige el poder justo, ni más ni menos. Reduce la superficie de ataque de todo el sistema.

Contexto de proceso vs interrupción

Un detalle crucial: current solo tiene sentido en contexto de proceso (cuando ejecutas en nombre de una syscall). En contexto de interrupción (nivel 22), no hay un proceso “llamante” — la interrupción llegó de forma asíncrona. Usar current o dormir ahí es un bug grave.

💡
¿En qué contexto estoy?

Antes de usar current, comprobar permisos o dormir, pregúntate: ¿estoy en contexto de proceso o de interrupción? En contexto de proceso (una syscall, tu char device read/write) puedes usar current, comprobar capabilities y dormir. En contexto de interrupción no. Saber en qué contexto corre tu código es una de las distinciones que más importan en el kernel, y la verás una y otra vez (concurrencia, memoria, interrupciones). Cada API del kernel documenta desde qué contexto se puede llamar.

⚔️ Controla el acceso
  1. En tu módulo, imprime quién te llama con current->comm y current->pid.
  2. Añade una comprobación capable(CAP_SYS_ADMIN) que devuelva -EPERM a los no privilegiados.
  3. Investiga la lista de capabilities en include/uapi/linux/capability.h.
  4. Explica por qué current no vale en contexto de interrupción.