2009-02-25 13 views
7

La definición del UNIX abierta() función cuando se utiliza con la bandera O_CREAT es que requiere un tercer argumento con nombre modo con el fin de establecer los privilegios de los archivos.bandera Unix O_CREAT sin el modo especificado

¿Qué pasa si ese modo no está especificado?

int file; 
static const char filename[] = "test.test"; 

if ((file = open(filename, O_RDWR | O_CREAT | O_TRUNC)) == 1) 
{ 
    perror("Error opening file."); 
    exit(EXIT_FAILURE); 
} 

close(file); 

¿Qué ocurre con el archivo que se crea con esas banderas? En mi sistema me sale:

-r--r-s--- 1 hyperboreean hyperboreean  0 2009-02-25 01:40 test.test 

Una teoría es que la función de apertura se ve en la pila y cheques para el parámetro mode y termina usando un entero aleatorio que encuentra.

¿Qué dice la norma sobre esto?

+0

Es por esto que se inventaron los prototipos de funciones. – womble

+1

Tu comentario no tiene sentido. – SoapBox

+0

No, de hecho. Y tampoco lo hizo el voto en baja. – cdonner

Respuesta

1

hyperboreean, su sospecha puede ser no tan lejos de la realidad. Esperaba encontrar la respuesta en Kernighan Ritchie. Lamentablemente, no lo hice. Creo que se requiere el parámetro de permisos con el indicador O_CREAT, y si no lo proporciona, open() extraerá un valor aleatorio de la pila, que por supuesto pasa desapercibido en C.

Editar: por " al azar "Quiero decir no predecible. Probablemente esté recogiendo parte de la dirección de retorno, que se encuentra en la parte superior de los parámetros en la pila.

2

Buena pregunta. El valor mode será modificado por el umask del proceso. Así que si usted no pasa un mode explícitamente a open en una operación O_CREAT, y si esto se traduce en bits aleatorios que se utiliza para el modo, esos bits aleatorios serán modificados por el umask.

Ojalá pudiera ser más definitivo y preciso, pero estoy de acuerdo con cdonner que se están utilizando los valores "aleatorios", junto con el umask.

Editar: Una cosa que podría intentar es usar dtruss o truss o alguna otra función para rastrear llamadas al sistema, y ​​mirar el valor de mode en tiempo de ejecución para ver si se usa algo sensible, o si es aleatorio bits modificados por umask, por ejemplo.

+0

En mi prueba con ptrace() , Es solo algo aparentemente aleatorio, aunque en mi caso siempre es un número de 11 bits (12 bits con el 0 inicial indicando octal) que comienza con 2777. –

+0

El valor 02777 es interesante porque implica escritura mundial con el set-gid poco. Bueno, solo otra razón por la cual crear un archivo sin el modo es peligroso. –

8

El estándar POSIX (IEEE 1003.1: 2008) open() prototipos como:

int open(const char *path, int oflag, ...); 

La sección que describe el comportamiento de O_CREAT no dice lo que sucederá si se omite el tercer argumento es necesario, lo que significa que el comportamiento no está definido, todo es posible.

En la práctica, el uso de parte de la pila que estaba destinada a ser marco de pila o dirección de retorno o algo similar es bastante probable, hasta una aproximación razonable, que se puede considerar como un entero aleatorio.

El estándar POSIX 2008 tiene algunas banderas nuevas (y útiles) interesantes para open(), incluyendo:

  • O_FDCLOEXEC para especificar close-on-exec al abierto.
  • O_DIRECTORY para especificar que el archivo debe ser un directorio.
  • O_NOFOLLOW para especificar que no se busquen enlaces simbólicos.
0

Para el registro, en la mayoría de los sistemas de libc, es probable que estar en manos de va_arg, which states in it's man page:

If there is no next argument, or if type is not compatible with the 
    type of the actual next argument (as promoted according to the 
    default argument promotions), **random errors will occur**. 
int 
__libc_open64 (const char *file, int oflag, ...) 
{ 
    int mode = 0; 

    if (oflag & O_CREAT) 
    { 
     va_list arg; 
     va_start (arg, oflag); 
     mode = va_arg (arg, int); 
     va_end (arg); 
    } 

    if (SINGLE_THREAD_P) 
     return INLINE_SYSCALL (open, 3, file, oflag | O_LARGEFILE, mode); 

    int oldtype = LIBC_CANCEL_ASYNC(); 

    int result = INLINE_SYSCALL (open, 3, file, oflag | O_LARGEFILE, mode); 

    LIBC_CANCEL_RESET (oldtype); 

    return result; 
} 
Cuestiones relacionadas