¿Qué hace la bandera FD_CLOEXEC fcntl ()?

82

Al igual que:

if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
...

Aunque he leído man fcntl, no puedo entender qué hace.

compilar fan
fuente

Respuestas:

74

Establece el indicador close-on-exec para el descriptor de archivo, lo que hace que el descriptor de archivo se cierre automáticamente (y atómicamente) cuando cualquiera de las execfunciones -family tiene éxito.

También prueba el valor de retorno para ver si la operación falló, lo cual es bastante inútil si el descriptor de archivo es válido, ya que no existe ninguna condición bajo la cual esta operación deba fallar en un descriptor de archivo válido.

R .. GitHub DEJA DE AYUDAR A ICE
fuente
4
Tenga en cuenta que no hace nada acerca de vaciar cualquier flujo de archivo ( FILE *) asociado con el descriptor de archivo. Un uso válido de FD_CLOEXEC es cerrar un archivo de registro que el proceso principal tiene abierto al ejecutar un proceso de shell. Tenga en cuenta que POSIX 2008 tiene una opción open(2)para O_CLOEXEC, por lo que puede establecer esta propiedad cuando abra el archivo, lo que será muy útil una vez que esté ampliamente disponible.
Jonathan Leffler
Establecer la bandera de forma atómica cuando se abre el archivo es bastante esencial para cualquier programa con subprocesos que pueda estar abriendo archivos mientras que otro subproceso podría estar ejecutando programas externos. Por desgracia, sólo está disponible para los openno accept, socket, pipe, etc ...
R .. GitHub dejar de ayudar a ICE
Sí, hay problemas de diseño al agregar O_CLOEXEC o equivalente a las otras funciones de creación de descriptores de archivos (aunque dup()y dup2()no se ven afectados, por supuesto). Probablemente tendría que tener nuevas funciones con un parámetro adicional de 'modo' o 'banderas', que es presumiblemente la razón por la que no sucedió. Si pudiera usar O_CLOEXEC en socket, entonces podría suponer que clonaría accept()esa bandera en el descriptor que devuelve. Pero socket()y pipe()son más complicados.
Jonathan Leffler
3
dupy dup2se ven afectados. La marca close-on-exec se aplica a los descriptores de archivos, no a las descripciones de archivos abiertos, por lo que no se comparte entre descriptores de archivos duplicados. Eso es una cosa muy buena.
R .. GitHub DEJA DE AYUDAR A ICE
3
El seguimiento de la conversación en los comentarios, POSIX ha adoptado para su inclusión en el próximo número de nuevas interfaces que fijan las deficiencias: dup3, pipe2, y accept4. Además, sockettiene la SOCK_CLOEXECbandera que puedes combinar con el tipo de enchufe solicitado.
R .. GitHub DEJA DE AYUDAR A ICE
33

Marca el descriptor de archivo para que se close()d automáticamente cuando el proceso o cualquier hijo fork()llame a una de las exec*()funciones de la familia. Esto es útil para evitar filtrar sus descriptores de archivos a programas aleatorios ejecutados por ej system().

geekosaurio
fuente
¿Es esto un problema de seguridad?
zach
1
@zach, podrías decirlo; pero en realidad, cualquier refactorización que realice, como encapsular una lógica dispersa en una sola entidad, puede denominarse un "problema de seguridad", porque reduce la probabilidad de errores debido al uso incorrecto de esa entidad, y "un error" es algo abstracto que incluye segfaults y filtraciones de información en particular.
Hi-Angel
Así que estoy refactorizando un código de socket, y entre obtener el socket y conectarse al servidor remoto, usan F_SETFD para agregar la bandera FD_CLOEXEC al FD del socket. Luego, después de una conexión exitosa, se elimina FD_CLOEXEC. No puedo encontrar ninguna llamada de exec () involucrada en esta área de código y me pregunto si son restos de código antiguo que deberían haber sido eliminados pero no lo fueron. No estoy seguro de qué buscar para averiguar el propósito de todo.
JoeManiaci