Duplicación de procesos cruzados en Linux

Duplicación de procesos cruzados en Linux

Me gustaría duplicar un descriptor de archivo que se ejecuta en un proceso no relacionado en Linux. Se acerca deenviar mensaje(2)y SCM_RIGHTS(por ejemplohttps://stackoverflow.com/questions/4489433/sending-file-descriptor-over-unix-domain-socket-and-select), pero eso funciona sólo si el otro proceso está cooperando. Necesito una solución que no requiera la cooperación activa del otro proceso. También sé que podría crear primero el descriptor de archivo, conservar una copia y luego crear el otro proceso, pero necesito una solución en la que el otro proceso cree su propio descriptor de archivo.

Puedo ver el descriptor del archivo:

$ ls -l /proc/13115/fd/3
lrwx------ 1 pts pts 64 2013-05-04 13:15 /proc/13115/fd/3 -> socket:[19445454]

Sin embargo, open("/proc/13115/fd/3", O_RDWR)ejecutado en otro proceso devuelve el error.No existe tal dispositivo o dirección. ¿Hay algo más que funcione? Probablemente contrazo?

Respuesta1

Esto es por diseño: compartir descriptores de archivos con otros procesos es explícito. De forma predeterminada, los descriptores de archivos son tan privados como la propia memoria del proceso.

Como siempre, si tienes derecho atrazoDurante el proceso, puedes hacer lo que quieras, incluso llamarlo sendmsg. Tradicionalmente, llamar ptracerequiere ejecutarse con el mismo ID de usuario; Las restricciones de seguridad como SELinux, capacidades, cárceles, etc. pueden volverse ptracemás restrictivas. Por ejemplo, bajo la configuración predeterminada de Ubuntu, un proceso no raíz solo puede llamar ptracea sus propios descendientes (a través de AppArmor).

Usarlo ptracede manera robusta es un poco complicado: debes inyectar los datos correctos, asegurarte de no sobrescribir nada y limpiarlo tú mismo. Entonces, mi recomendación es inyectar el código de manera indirecta y activar ese código con una herramienta existente.

Escriba una pequeña biblioteca compartida que contenga el sendmsgcódigo y LD_PRELOADenvíelo al otro proceso. aquí hay algunosno probadoFalta el código esqueleto al que le falta la comprobación de errores.

int pts_gift_fd (char *path, int fd) {
    int sock;
    struct sockaddr_un addr = {0};
    struct msghdr msg = {0};
    struct iovec iov = {0};
    addr.sun_family = AF_UNIX;
    strlcpy(addr.sun_path, path, sizeof(addr.sun_path));
    /* Populate msg, iov as in the code you've already found */
    sock = socket(AF_UNIX, SOCK_STREAM, 0);
    connect(sock, (struct sockaddr*)&addr, sizeof(addr));
    sendmsg(sock, &msg, 0);
    close(sock);
}

Luego, para activar el código, ejecútelo gdb -n -pid 13115 -batch -x /dev/stdiny popenaliméntelo con esta entrada (dónde %destá el fd que desea obtener y %ses una ruta a un socket Unix que creó previamente y en el que está escuchando):

call pts_gift_fd("%s", %d)
detach
quit

Respuesta2

No puedes hacer esto por la misma razón que no puedes acceder a la memoria de un proceso no relacionado, porque un descriptor de archivoesparte de la memoria de otro proceso. La única razón por la que hay información sobre cosas como esta /proces porque el kernel la proporciona allí y es de sólo lectura (por lo tanto, existen medios para examinarla).una copiade la memoria de proceso).

Si se relaciona con un archivo, por supuesto, puede intentar acceder al archivo. Si es un enchufe, puedes espiarlo usandolibcapo algo derivado de él.

La situación es básicamente la siguiente: un descriptor de archivo es (nuevamente) parte de la memoria de un proceso. El descriptor tiene un búfer subyacente que existe en el espacio del núcleo; cuando el proceso lee o escribe en/desde el descriptor, está escribiendo en y desde este búfer. Para la salida de datos, el kernel vacía el búfer (al hardware) de forma adecuada; para los datos que entran, rellena el búfer (desde el hardware) cuando el proceso lo vacía. Esos buffers no son, AFAIK, accesibles para otros procesos, aunque existen algunos medios (por ejemplo, libpcap) delecturalos datos en alguna forma determinada por la interfaz del kernel particular, del mismo modo que la interfaz proc puede proporcionar algunos datos de la memoria del espacio de usuario del proceso.

información relacionada