¿Cómo configuro SGID en PHP?

Oct 07 2020

No puedo configurar el bit SGID desde PHP.

Tengo este directorio:

  4 drwxrwsr-x 12 www-data mygroup  4096 Oct  7 16:05 mydir

Tenga en cuenta el bit SGID. Entonces, si simplemente creo un directorio en él desde el shell con mkdir test, obtengo

  4 drwxr-sr-x  2 myuser   mygroup   4096 Oct  7 16:22 test

Tenga en cuenta que el bit SGID se hereda. Pero me gustaría que se pueda escribir en grupo (lo que mi umask 22no permite) para poder simplemente chmod 02775 testy estoy perfectamente feliz:

  4 drwxrwsr-x  2 myuser   mygroup   4096 Oct  7 16:22 test

Ahora me gustaría hacer lo mismo desde un script PHP. Naturalmente, esperaría que esto funcione:

mkdir("/mydir/test2");
chmod("/mydir/test2", 02775);

Pero no es así y obtengo esto en su lugar (el SGID se restablece):

  4 drwxrwxr-x  2 www-data mygroup   4096 Oct  7 16:30 test2

Aquí hay un par de otros experimentos útiles:

mkdir("/mydir/test3");
mkdir("/mydir/test4");
passthru("chmod 02775 '/mydir/test4'");
mkdir("/mydir/test5");
passthru("chmod g+w '/mydir/test5'");

Los resultados son

  4 drwxr-sr-x  2 www-data mygroup   4096 Oct  7 16:39 test3
  4 drwxrwxr-x  2 www-data mygroup   4096 Oct  7 16:39 test4
  4 drwxrwxr-x  2 www-data mygroup   4096 Oct  7 17:06 test5

Curiosamente, mkdir()solo ha conservado el SGID, pero lo chmod()restablece, incluso a través passthru().

Sé que el manual de PHP dice chmodque el comando espera solo tres dígitos octales, pero leí también esta pregunta sobre el flujo de pila y parece que el manual contiene información obsoleta y otros pueden afectar el SGID. Además, no debería afectar a las passthru()versiones, ¿verdad? La misma pregunta de stackoverflow menciona algo sobre la chmod()necesidad de ser "el último en ser llamado" después de chown()y chgrp(), pero no estoy usando ninguno de esos.

¿Qué estoy haciendo mal?

Respuestas

DanielB Oct 08 2020 at 21:11

¿Se ejecuta en un servidor web o simplemente como un script CLI? Si es CLI, ¿usuario o root?

Además, ¿por qué directorios? SGID se utiliza en archivos de programa para permitir que un usuario ejecute un programa / script como otro usuario, como "sudo". ¿Ha intentado probar esto en archivos en lugar de directorios?

Paolo Oct 09 2020 at 12:37

Al final, la única forma que pude encontrar para obtener los permisos que necesito es aprovechar el comportamiento correcto mkdir()y evitar llamadas chmod()que parecen restablecer el bit SGID sin importar qué. La única forma en que puedo pensar en hacer esto es cambiar la máscara de usuario con umask():

$myumask = umask(2); mkdir("/mydir/test6"); umask($myumask);

Esto parece funcionar bien:

  4 drwxrwsr-x  2 www-data mygroup   4096 Oct  9 14:22 test6

Esto me deja con el problema planteado en la nota de https://www.php.net/manual/en/function.umask.php: que todos los hilos de un servidor web multiproceso comparten la misma umask , lo que obviamente conduce a un comportamiento no deseado e impredecible. Afortunadamente, en mi caso, pude determinar que todas las creaciones de directorios se realizan en un contexto de subprocesos múltiples (esencialmente, en la primera ejecución de prueba de un script) y, por lo tanto, me siento seguro. Por lo tanto, esta es una solución alternativa útil, pero no una solución general.