Jak ustawić SGID w PHP?
Nie mogę ustawić bitu SGID z PHP.
Mam ten katalog:
4 drwxrwsr-x 12 www-data mygroup 4096 Oct 7 16:05 mydir
Zwróć uwagę na bit SGID. Tak więc, jeśli po prostu utworzę w nim katalog z powłoki za pomocą mkdir test, otrzymam
4 drwxr-sr-x 2 myuser mygroup 4096 Oct 7 16:22 test
Zauważ, że bit SGID jest dziedziczony. Ale chciałbym, żeby grupa była zapisywalna (na co moja umask 22nie pozwala), więc mogę po prostu chmod 02775 testi jestem całkowicie szczęśliwy:
4 drwxrwsr-x 2 myuser mygroup 4096 Oct 7 16:22 test
Teraz chciałbym zrobić to samo ze skryptu PHP. Oczywiście spodziewałbym się, że to zadziała:
mkdir("/mydir/test2");
chmod("/mydir/test2", 02775);
Ale tak się nie dzieje i zamiast tego otrzymuję to (SGID jest resetowany):
4 drwxrwxr-x 2 www-data mygroup 4096 Oct 7 16:30 test2
Oto kilka innych przydatnych eksperymentów:
mkdir("/mydir/test3");
mkdir("/mydir/test4");
passthru("chmod 02775 '/mydir/test4'");
mkdir("/mydir/test5");
passthru("chmod g+w '/mydir/test5'");
Wyniki są
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
Co ciekawe, mkdir()sam zachował SGID, ale chmod()resetuje go, nawet przez passthru().
Wiem, że podręcznik PHP mówi, chmodże polecenie oczekuje tylko trzech cyfr ósemkowych, ale czytałem również to pytanie o przepływie stosu i wygląda na to, że podręcznik zawiera przestarzałe informacje, a inne mogą wpływać na SGID. Poza tym nie powinno to wpływać na passthru()wersje, prawda? To samo pytanie o chmod()przepełnienie stosu wspomina o konieczności bycia „ostatnim, do którego można zadzwonić” po chown()i chgrp(), ale nie używam żadnego z nich.
Co ja robię źle?
Odpowiedzi
Czy to działa na serwerze internetowym, czy po prostu jako skrypt CLI? Jeśli CLI, użytkownik czy root?
Poza tym, dlaczego katalogi? SGID jest używany w plikach programów, aby umożliwić użytkownikowi uruchomienie programu / skryptu jako inny użytkownik, np. „Sudo”. Czy próbowałeś przetestować to na plikach, a nie katalogach?
Ostatecznie jedynym sposobem, w jaki mogłem znaleźć potrzebne uprawnienia, jest skorzystanie z prawidłowego zachowania mkdir()i uniknięcie wywołania, chmod()które wydaje się resetować bit SGID bez względu na wszystko. Jedyny sposób, w jaki mogę o tym pomyśleć, to zmienić umask za pomocą umask():
$myumask = umask(2); mkdir("/mydir/test6"); umask($myumask);
Wygląda na to, że działa dobrze:
4 drwxrwsr-x 2 www-data mygroup 4096 Oct 9 14:22 test6
Pozostaje mi kwestia poruszona w nocie https://www.php.net/manual/en/function.umask.php: że wszystkie wątki wielowątkowego serwera WWW mają tę samą umaskę , co oczywiście prowadzi do niepożądanego i nieprzewidywalnego zachowania. Na szczęście w moim przypadku mogłem się upewnić, że wszystkie tworzenie katalogów są wykonywane w kontekście jednowątkowym (zasadniczo przy pierwszym testowym uruchomieniu skryptu) i dzięki temu czuję się bezpiecznie. Dlatego jest to przydatne obejście, ale nie jest to ogólne rozwiązanie.