Come imposto SGID in PHP?
Non riesco a impostare il bit SGID da PHP.
Ho questa directory:
4 drwxrwsr-x 12 www-data mygroup 4096 Oct 7 16:05 mydir
Notare il bit SGID. Quindi, se creo semplicemente una directory dalla shell con mkdir test, ottengo
4 drwxr-sr-x 2 myuser mygroup 4096 Oct 7 16:22 test
Notare che il bit SGID viene ereditato. Ma lo vorrei scrivibile in gruppo (cosa che il mio umask 22non consente) così posso semplicemente chmod 02775 teste sono perfettamente felice:
4 drwxrwsr-x 2 myuser mygroup 4096 Oct 7 16:22 test
Ora vorrei fare lo stesso da uno script PHP. Naturalmente, mi aspetto che funzioni:
mkdir("/mydir/test2");
chmod("/mydir/test2", 02775);
Ma non lo fa e ottengo questo invece (l'SGID viene ripristinato):
4 drwxrwxr-x 2 www-data mygroup 4096 Oct 7 16:30 test2
Ecco un paio di altri esperimenti utili:
mkdir("/mydir/test3");
mkdir("/mydir/test4");
passthru("chmod 02775 '/mydir/test4'");
mkdir("/mydir/test5");
passthru("chmod g+w '/mydir/test5'");
I risultati sono
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
È interessante notare che da mkdir()solo ha conservato l'SGID, ma lo chmod()ripristina, anche attraverso passthru().
So che il manuale PHP dice chmodche il comando prevede solo tre cifre ottali, ma ho letto anche questa domanda sullo stackoverflow e sembra che il manuale contenga informazioni obsolete e altri possono influenzare lo SGID. Inoltre, non dovrebbe influire sulle passthru()versioni, vero? La stessa domanda di stackoverflow menziona qualcosa sulla chmod()necessità di essere "l'ultimo a essere chiamato" dopo chown()e chgrp(), ma non sto usando nessuno di questi.
Che cosa sto facendo di sbagliato?
Risposte
È in esecuzione su un server Web o semplicemente come uno script CLI? Se CLI, utente o root?
Inoltre, perché le directory? SGID viene utilizzato sui file di programma, per consentire a un utente di eseguire un programma / script come un altro utente, come "sudo". Hai provato a testarlo sui file piuttosto che sulle directory?
Alla fine, l'unico modo che ho potuto trovare per ottenere i permessi di cui ho bisogno è trarre profitto dal comportamento corretto mkdir()ed evitare di chiamare chmod()che sembra ripristinare il bit SGID, non importa quale. L'unico modo in cui posso pensare di farlo è cambiare l' umask con umask():
$myumask = umask(2); mkdir("/mydir/test6"); umask($myumask);
Questo sembra funzionare bene:
4 drwxrwsr-x 2 www-data mygroup 4096 Oct 9 14:22 test6
Ciò mi lascia con la questione sollevata nella nota di https://www.php.net/manual/en/function.umask.php: che tutti i thread di un webserver multithread condividono la stessa umask , portando ovviamente a comportamenti indesiderati e imprevedibili. Fortunatamente, nel mio caso, ho potuto accertare che tutte le creazioni di directory vengono eseguite in un contesto monofiletto (essenzialmente, alla prima esecuzione di test di uno script) e quindi mi sento al sicuro. Quindi, questa è una soluzione utile ma non una soluzione generale.