¿Cómo configuro SGID en PHP?
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
¿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?
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.