Search code examples
phpfile-permissions

PHP: file write permissions


I have been banging my head for quite a while now because of this...

I'm trying to install a MyBB forum on my virtual server (CentOS 7, apache http server, php 5.4.3) and I ran into troubles with file permissions. MyBB needs two files to be writable, one of them is config.php and the second one is settings.php, both of them in directory inc.

I set the permissions on both files to 666. I wrote a simple testing php page which mimics the way MyBB tests for the ability to write:

<?php
echo('config: ');
$configwritable = @fopen('forum/inc/config.php', 'w');
if ($configwritable) {
        echo('yes');
} else {
        echo('no');
}
echo('<br/>');
echo('settings: ');
$configwritable = @fopen('forum/inc/settings.php', 'w');
if ($configwritable) {
    echo('yes');
} else {
    echo('no');
}
?>

The page output is

config: no
settings: yes

but if I list the files, they show up like this

root@localhost# ls -l forum/inc/config.php forum/inc/settings.php 
-rw-rw-rw-. 1 krkavec krkavec 0  2. říj 22.49 forum/inc/config.php
-rw-rw-rw-. 1 krkavec krkavec 0  2. říj 22.51 forum/inc/settings.php

How is it possible? Both the files belong to the same user, to the same group, have the same size (zero), are in the same directory, have the same permissions, have almost the same modification time (differing by two minutes) and virtually everything else except their name is identical.

To make things even more weird, I tried to play around with deleting and creating the files again, watch:

1: deleting both files

root@localhost# rm -f forum/inc/config.php forum/inc/settings.php

and the page output:

config: no
settings: no

which is ok since the inc directory isn't supposed to be writable.

2: create settings.php

root@localhost# F=forum/inc/settings.php ; touch $F ; chown krkavec:krkavec $F ; chmod 666 $F
root@localhost# ls -l forum/inc/settings.php forum/inc/config.php
ls: cannot access forum/inc/config.php: No such file or directory
-rw-rw-rw-. 1 krkavec krkavec 0  2. říj 23.15 forum/inc/settings.php

and the page output:

config: no
settings: yes

which is totally ok and expected - the file is there and has writable permissions.

3: create config.php

root@localhost# F=forum/inc/config.php ; touch $F ; chown krkavec:krkavec $F ; chmod 666 $F
root@localhost# ls -l forum/inc/settings.php forum/inc/config.php
-rw-rw-rw-. 1 krkavec krkavec 0  2. říj 23.23 forum/inc/config.php
-rw-rw-rw-. 1 krkavec krkavec 0  2. říj 23.15 forum/inc/settings.php

and the page output:

config: no
settings: yes

BAM! I would totally expect the config to be writable.

Any help is greatly appreciated.

EDIT: I modified the testing page according to Marc B's and drew010's suggestions

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

echo('config var_dump: ');
var_dump(stat('forum/inc/config.php'));
echo('<br/>config: ');
$configwritable = fopen('forum/inc/config.php', 'w');
if ($configwritable) {
    echo('yes');
} else {
    echo('no');
}
echo('<br/>');
echo('settings var_dump: ');
var_dump(stat('forum/inc/settings.php'));
echo('<br/>settings: ');
$configwritable2 = fopen('forum/inc/settings.php', 'w');
if ($configwritable2) {
    echo('yes');
} else {
    echo('no');
}
?>

and the page's output (with both files present) is:

config var_dump: array(26) { [0]=> int(64768) [1]=> int(19155212) [2]=> int(33206) [3]=> int(1) [4]=> int(1000) [5]=> int(1000) [6]=> int(0) [7]=> int(0) [8]=> int(1443821772) [9]=> int(1443821772) [10]=> int(1443821772) [11]=> int(4096) [12]=> int(0) ["dev"]=> int(64768) ["ino"]=> int(19155212) ["mode"]=> int(33206) ["nlink"]=> int(1) ["uid"]=> int(1000) ["gid"]=> int(1000) ["rdev"]=> int(0) ["size"]=> int(0) ["atime"]=> int(1443821772) ["mtime"]=> int(1443821772) ["ctime"]=> int(1443821772) ["blksize"]=> int(4096) ["blocks"]=> int(0) } 
config: 
Warning: fopen(forum/inc/config.php): failed to open stream: Permission denied in /var/www/html/test.php on line 8
no
settings var_dump: array(26) { [0]=> int(64768) [1]=> int(19155069) [2]=> int(33206) [3]=> int(1) [4]=> int(1000) [5]=> int(1000) [6]=> int(0) [7]=> int(0) [8]=> int(1443821763) [9]=> int(1443823158) [10]=> int(1443823158) [11]=> int(4096) [12]=> int(0) ["dev"]=> int(64768) ["ino"]=> int(19155069) ["mode"]=> int(33206) ["nlink"]=> int(1) ["uid"]=> int(1000) ["gid"]=> int(1000) ["rdev"]=> int(0) ["size"]=> int(0) ["atime"]=> int(1443821763) ["mtime"]=> int(1443823158) ["ctime"]=> int(1443823158) ["blksize"]=> int(4096) ["blocks"]=> int(0) } 
settings: yes

Solution

  • For some magical, unknown reason, when I renamed settings.php to config.php and then created new settings.php and set the rights appropriately, both files are writable.

    However, I have no idea whatsoever why the file had to be renamed. The result is the same as after the step 3 described in the question except that it works.

    Any suggestion why this hat to be done and the reason behind it is greatly welcome.

    EDIT: It was caused by SELinux security context which prevented apache to write to the file. Running chcon -t httpd_sys_rw_content_t config.php solved the problem.