Come imposto SGID in PHP?

Oct 07 2020

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

DanielB Oct 08 2020 at 21:11

È 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?

Paolo Oct 09 2020 at 12:37

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.