Pasar capacidades a través de ejecutivo

Pasar capacidades a través de ejecutivo

Estoy tratando de entender cómo se pasan las capacidades de Linux a un proceso que ha sido exec()controlado por otro. Por lo que he leído, para que una capacidad se mantenga después de la ejecución, debe estar en el conjunto heredable. Sin embargo, de lo que no estoy seguro es de cómo se completa ese conjunto.

Mi objetivo es poder ejecutar un programa como usuario normal que normalmente requeriría root. La capacidad que necesita es cap_dac_overridepoder leer un archivo privado. No quiero darle ninguna otra capacidad.

Aquí está mi envoltorio:

#include <unistd.h>

int main(int argc, char *argv[]) {
    return execl("/usr/bin/net", "net", "ads", "dns", "register", "-P", NULL);
}

Esto funciona cuando configuro el permiso setuid en el ejecutable resultante:

~ $ sudo chown root: ./registerdns
~ $ sudo chmod u+s ./registerdns
~ $ ./registerdns 
Successfully registered hostname with DNS

Sin embargo, me gustaría usar capacidades en lugar de setuid. Intenté configurar la cap_dac_overridecapacidad en el contenedor:

~ $ sudo setcap cap_dac_override=eip ./registerdns
~ $ ./registerdns 
Failed to open /var/lib/samba/private/secrets.tdb
ERROR: Unable to open secrets database

También intenté configurar el indicador heredable en la cap_dac_overridecapacidad del netejecutable en sí:

~ $ sudo setcap cap_dac_override=eip ./registerdns
~ $ sudo setcap cap_dac_override=i /usr/bin/net
~ $ ./registerdns 
Failed to open /var/lib/samba/private/secrets.tdb
ERROR: Unable to open secrets database

Necesito usar el contenedor para asegurarme de que la capacidad solo esté disponible cuando se usa ese conjunto exacto de argumentos; El netprograma hace varias otras cosas que podrían ser peligrosas si otorga a los usuarios permisos demasiado amplios.

Obviamente no entiendo bien cómo funciona la herencia. Parece que no puedo entender cómo configurar el contenedor para pasar sus capacidades al proceso de reemplazo para que pueda usarlas. He leído la página de manual y muchos otros documentos sobre cómodeberíatrabajo, y pensé que estaba haciendo lo que describe.

Respuesta1

Resulta que configurar +i en el contenedor nonoagregue la capacidad al CAP_INHERITABLEconjunto para el proceso contenedor, por lo que no se pasa exec. Por lo tanto, tuve que agregar manualmente CAP_DAC_OVERRIDEantes CAP_INHERITABLEde llamar execl:

#include <sys/capability.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv[]) {
    cap_t caps = cap_get_proc();
    printf("Capabilities: %s\n", cap_to_text(caps, NULL));
    cap_value_t newcaps[1] = { CAP_DAC_OVERRIDE, };
    cap_set_flag(caps, CAP_INHERITABLE, 1, newcaps, CAP_SET);
    cap_set_proc(caps);
    printf("Capabilities: %s\n", cap_to_text(caps, NULL));
    cap_free(caps);
    return execl("/usr/bin/net", "net", "ads", "dns", "register", "-P", NULL);
}

Además, tuve que agregar cap_dac_overridea las capacidades de archivo permitidas configuradas /usr/bin/nety configurar el bit efectivo:

~ $ sudo setcap cap_dac_override=p ./registerdns
~ $ sudo setcap cap_dac_override=ei /usr/bin/net
~ $ ./registerdns
Capabilities = cap_dac_override+p
Capabilities = cap_dac_override+ip
Successfully registered hostname with DNS

Creo que ahora entiendo completamente lo que está pasando:

  1. El contenedor necesita CAP_DAC_OVERRIDEsu conjunto permitido para poder agregarlo a su conjunto heredable.
  2. El conjunto heredable del proceso del contenedor es diferente al conjunto heredable del archivo, por lo que configurar +i en el archivo es inútil; el contenedor debe agregarse explícitamente CAP_DAC_OVERRIDEal CAP_INHERITABLEuso de cap_set_flag/ cap_set_proc.
  3. El netarchivo debe estar CAP_DAC_OVERRIDEen su conjunto heredable para que de hecho pueda heredar la capacidad del contenedor en su CAP_PERMITTEDconjunto. También es necesario configurar el bit efectivo para que se promocione automáticamente a CAP_EFFECTIVE.

Respuesta2

Creo que necesitas ambos:

setcap cap_dac_override+pe ./registerdns
setcap cap_dac_override+i /usr/bin/net

Las pebanderas encendidas registerdnsdicen que ejecutar el programa adquiere la capacidad. La ibandera encendida netdice que se le permite heredar la capacidad del programa que realiza la llamada.

información relacionada