PHP fopen eșuează întotdeauna cu permisiunea refuzată (Administrarea sistemului, Apache 2.2, Php, Suexec)

Kevin Loney a intrebat.

Sunt în procesul de migrare a câtorva bloguri WordPress pe AWS și am dat peste o problemă cu permisiunile fișierelor care m-a zădărnicit cu succes în ultimele câteva ore.

Cel mai simplu apel fopen posibil eșuează întotdeauna cu „failed to open stream: Permission denied”:

<?php $handle = fopen('test.txt', 'w') or die('Can't open file'); ?>

Am încercat/verificat următoarele

  • Directorul în care scriu are permisiunile de fișier corecte (755) și proprietatea corectă. Acest lucru este valabil pe toată calea până la /home.
  • Scriu în directorul corect, așa cum este confirmat de getcwd()
  • Scriptul PHP de test are același proprietar ca și calea în care încerc să scriu și permisiuni corecte (644).
  • Rulez mod_suexec pentru a mă asigura că scriptul este executat cu același utilizator și grup ca și calea în care scriu. Funcțiile getmyuid() și getmygid() returnează ID-urile de utilizator și de grup corecte (Editare: Acest lucru este greșit, vezi mai jos).
  • Modul de siguranță PHP este dezactivat în php.ini.
  • fopen nu este o funcție PHP nepermisă.
  • Utilizarea funcției open_basedir este dezactivată.

Este ceva ce mi-a scăpat și care ar putea cauza acest lucru? Suspectez că m-am uitat atât de mult la asta încât îmi scapă ceva evident.

Actualizare: După ce am aplicat sugestiile lui womble, încep să cred că această problemă este mai nefastă decât niște permisiuni proaste sau o configurație greșită a PHP. Am reușit să fac codul de mai sus să scrie un fișier, însă chiar dacă scriptul PHP a fost executat cu utilizatorul și grupul corect, proprietatea și grupul fișierelor rezultate au fost setate pe cele ale lui apache. Dacă execut același script de test din linia de comandă, fișierul emis are permisiunile corecte. Acest lucru mă face să cred că este o problemă cu utilizarea mea a mod_suexec.

Editați: Utilizarea mea de către getmyuid() și getmygid() sunt incorecte, deoarece acestea returnează doar utilizatorul și grupul fișierului de script, nu și permisiunile cu care acesta rulează. O abordare mai corectă ar fi să folosiți ceva de genul următor:

<?php echo exec('ps -up '.getmypid()); ?>

4 răspunsuri
womble

Bună întrebare – arată că ți-ai făcut temele.

Nu mă pot gândi la nimic „evident” pe care nu l-ai verificat, așa că nu pot decât să-ți dau câteva sfaturi mai avansate de depanare.

  • Porniți strace pe procesul PHP și vedeți exact ce face sub capotă.
  • Scrieți o bucată de cod care să facă un fopen(..., 'r') pentru a verifica de trei ori dacă permisiunile arborelui de directoare sunt, de fapt, în regulă.
  • su la utilizatorul în cauză și încercați să faceți niște lucruri în linia de comandă. Dacă funcționează, atunci știți că scriptul dvs. nu rulează cu permisiunile pe care le credeți.
  • Verificați dacă nu există ACL-uri extinse pe componentele fișierului, directorului sau ale căii de acces principale (getfacl este instrumentul pe care trebuie să-l utilizați). Este neobișnuit, dar din când în când sar și îți smulg fața. În cazul în care aveți ACL-uri, utilizați setfacl -x pentru a scăpa de ele după ce ați verificat că nu sunt necesare.

Comentarii

  • Fișierul nu are ACL-uri extinse, fopen(…, ‘r’) funcționează corect și scrie cu succes fișierele atunci când execut php în linia de comandă ca și atunci când sunt su’d in ca utilizator. Am reușit să fac să scrie un fișier atunci când este executat de apache și am actualizat întrebarea cu rezultatele mele. –  > Por Kevin Loney.
  • În cazul în care fișierul a fost creat de către apache, atunci scriptul este executat ca apache, indiferent dacă celelalte teste sugerează contrariul. Aș spune că suexec configurația este stricată. Ar trebui să întrebați despre asta pe Server Fault. <grin> –  > Por womble.
user101119

Verificați care este folderul home al lui apache (în mod normal este /var/www) și puneți fișierele în acest folder, în final apoi dați permisiunile necesare. Schimbați folderul temp upload php în acest folder. Acest lucru funcționează pentru mine.

Vitalijus

încercați /usr/sbin/apachectl -t -D DUMP_MODULES

verificați dacă toate modulele sunt activate

Dacă primiți

Warning: SuexecUserGroup directive requires SUEXEC wrapper.

Rezoluție

Un astfel de avertisment este de obicei cauzat de permisiuni invalide pe suexec wrapper, ar trebui să fie:

# ls -la /usr/sbin/suexec
-rwsr-xr-x 1 root root 12064 2008-04-17 01:15 /usr/sbin/suexec

Dacă permisiunile sau proprietatea sunt diferite de cele din exemplul de mai sus, utilizați următoarele comenzi pentru a le corecta:

# chown root:root  /usr/sbin/suexec
# chmod 4755 /usr/sbin/suexec

după această corecție, totul a fost în regulă.

Daniel Baker

2 lucruri.

  1. Trebuie să scăpați apostroful din declarația die.
  2. 5 este r-x, 6 este rw-. Aș seta permisiunile la 0766 pentru -rwxrw-rw-.

Comentarii

  • Documentele pentru WordPress indică faptul că 755 este permisiunile corecte pentru fișierele de director. Oricum, nici acest lucru nu ar trebui să conteze, deoarece scriptul php se execută cu același utilizator și grup ca și directorul în care se scrie. –  > Por Kevin Loney.
  • Wordpress se preocupă mai puțin de permisiunile fișierelor sale. Apache este cel care va servi paginile, cu condiția ca sistemul de fișiere să permită acest lucru. Același lucru este valabil și pentru scrierea într-un fișier. Worpress se aplică la Apache pentru a scrie. Dacă Apache este configurat pentru a permite, Apache se aplică la sistemul de fișiere pentru scriere, dacă fișierul nu are permisiunea de scriere setată, atunci cererea este respinsă. setați 0777 pentru folderul de scriere, precum și pentru fișier. Vedeți ce se întâmplă. –  > Por Daniel Baker.
  • Un lucru în plus. Fișierul care efectuează scrierea nu are nevoie de permisiuni de scriere. Doar fișierul și directorul în care se scrie. linux.com/learn/tutorials/… –  > Por Daniel Baker.
  • fopen încă nu reușește cu permisiune refuzată după ce am setat 0777 pe folderul și fișierul de scriere –  > Por Kevin Loney.
  • 0766? Serios? Mi-ar plăcea să știu un motiv legitim pentru a folosi vreodată acest set de permisiuni. –  > Por womble.