Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

289
Views
Evite que el proceso abra un nuevo descriptor de archivo en Linux, pero permita recibir descriptores de archivo a través de sockets

Actualmente estoy trabajando en un proyecto en el que tengo un proceso principal que configura un par de sockets, se bifurca y luego usa este par de sockets para comunicarse. El hijo, si quiere abrir un archivo (o cualquier otro recurso basado en un descriptor de archivo) siempre debe ir al padre, solicitar el recurso y obtener el fd enviado a través del par de sockets. Además, quiero evitar que el niño abra cualquier descriptor de archivo por sí mismo.

Tropecé con setrlimit que evita con éxito que el niño abra nuevos descriptores de archivo, pero también parece invalidar cualquier descriptor de archivo enviado a través de la conexión de socket inicial. ¿Hay algún método en Linux que permita que un solo proceso abra cualquier archivo, envíe su descriptor de archivo a otros procesos y les permita usarlos sin permitir que estos otros procesos abran cualquier descriptor de archivo por sí mismos?

Para mi caso de uso, puede ser cualquier configuración del kernel, llamada al sistema, etc. siempre que se pueda aplicar después de la bifurcación y siempre que se aplique a todos los descriptores de archivos (no solo archivos sino también sockets, pares de sockets, etc.).

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Lo que tienes aquí es exactamente el caso de uso de seccomp .

Usando seccomp, puede filtrar las llamadas al sistema de diferentes maneras. Lo que desea hacer en esta situación es, justo después de fork() , instalar un filtro seccomp que no permita el uso de open(2) , openat(2) , socket(2) (y más). Para lograr esto, puede hacer lo siguiente:

  1. Primero, cree un contexto seccomp usando seccomp_init(3) con el comportamiento predeterminado de SCMP_ACT_ALLOW .
  2. Luego agregue una regla al contexto usando seccomp_rule_add(3) para cada llamada al sistema que desee denegar. Puede usar SCMP_ACT_KILL para finalizar el proceso si se intenta la llamada al sistema, SCMP_ACT_ERRNO(val) para hacer que la llamada al sistema falle y devuelva el valor errno especificado o cualquier otro valor de action definido en la página del manual.
  3. Cargue el contexto usando seccomp_load(3) para hacerlo efectivo.

Antes de continuar, TENGA EN CUENTA que un enfoque de lista negra como este es, en general, más débil que un enfoque de lista blanca. Permite cualquier llamada al sistema que no esté explícitamente desautorizada y podría resultar en una omisión del filtro . Si cree que el proceso secundario que desea ejecutar podría estar tratando maliciosamente de evitar el filtro, o si ya sabe qué llamadas al sistema necesitarán los elementos secundarios, un enfoque de lista blanca es mejor y debe hacer lo contrario de lo anterior: cree un filtro con la acción predeterminada de SCMP_ACT_KILL y permita las llamadas al sistema necesarias con SCMP_ACT_ALLOW . En términos de código, la diferencia es mínima (la lista blanca probablemente sea más larga, pero los pasos son los mismos).

Aquí hay un ejemplo de lo anterior (estoy haciendo exit(-1) en caso de error solo por simplicidad):

 #include <stdlib.h> #include <seccomp.h> static void secure(void) { int err; scmp_filter_ctx ctx; int blacklist[] = { SCMP_SYS(open), SCMP_SYS(openat), SCMP_SYS(creat), SCMP_SYS(socket), SCMP_SYS(open_by_handle_at), // ... possibly more ... }; // Create a new seccomp context, allowing every syscall by default. ctx = seccomp_init(SCMP_ACT_ALLOW); if (ctx == NULL) exit(-1); /* Now add a filter for each syscall that you want to disallow. In this case, we'll use SCMP_ACT_KILL to kill the process if it attempts to execute the specified syscall. */ for (unsigned i = 0; i < sizeof(blacklist) / sizeof(blacklist[0]); i++) { err = seccomp_rule_add(ctx, SCMP_ACT_KILL, blacklist[i], 0); if (err) exit(-1); } // Load the context making it effective. err = seccomp_load(ctx); if (err) exit(-1); }

Ahora, en su programa, puede llamar a la función anterior para aplicar el filtro seccomp justo después de fork() , así:

 child_pid = fork(); if (child_pid == -1) exit(-1); if (child_pid == 0) { secure(); // Child code here... exit(0); } else { // Parent code here... }

Algunas notas importantes sobre seccomp:

  • Un filtro seccomp, una vez aplicado, no puede ser eliminado o alterado por el proceso.
  • Si el filtro permite fork(2) o clone(2) , todos los procesos secundarios estarán restringidos por el mismo filtro.
  • Si se permite execve(2) , el filtro existente se conservará en una llamada a execve(2) .
  • Si se permite la llamada al sistema prctl(2) , el proceso puede aplicar más filtros.
over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!