diff options
| author | Stanislav Malyshev <stas@php.net> | 2014-04-13 20:31:20 -0700 |
|---|---|---|
| committer | Stanislav Malyshev <stas@php.net> | 2014-04-14 10:51:31 -0700 |
| commit | 41569b10290e31affb7d8a4e5623b051790fab05 (patch) | |
| tree | e1f322b7c57ed1415f49e8fc24affa3d192d07e2 | |
| parent | 9e76e87ca961b57737f8f9db68972c5a9ce9b1f7 (diff) | |
| download | php-git-41569b10290e31affb7d8a4e5623b051790fab05.tar.gz | |
Fix bug #66171: better handling of symlinks
| -rw-r--r-- | ext/session/mod_files.c | 37 |
1 files changed, 20 insertions, 17 deletions
diff --git a/ext/session/mod_files.c b/ext/session/mod_files.c index 47140436e7..76f5d4c7c6 100644 --- a/ext/session/mod_files.c +++ b/ext/session/mod_files.c @@ -115,6 +115,7 @@ static void ps_files_close(ps_files *data) static void ps_files_open(ps_files *data, const char *key TSRMLS_DC) { char buf[MAXPATHLEN]; + struct stat sbuf; if (data->fd < 0 || !data->lastkey || strcmp(key, data->lastkey)) { if (data->lastkey) { @@ -134,26 +135,28 @@ static void ps_files_open(ps_files *data, const char *key TSRMLS_DC) } data->lastkey = estrdup(key); - - data->fd = VCWD_OPEN_MODE(buf, O_CREAT | O_RDWR | O_BINARY, data->filemode); + + /* O_NOFOLLOW to prevent us from following evil symlinks */ +#ifdef O_NOFOLLOW + data->fd = VCWD_OPEN_MODE(buf, O_CREAT | O_RDWR | O_BINARY | O_NOFOLLOW, data->filemode); +#else + /* Check to make sure that the opened file is not outside of allowable dirs. + This is not 100% safe but it's hard to do something better without O_NOFOLLOW */ + if(PG(open_basedir) && lstat(buf, &sbuf) == 0 && S_ISLNK(sbuf.st_mode) && php_check_open_basedir(buf TSRMLS_CC)) { + return; + } + data->fd = VCWD_OPEN_MODE(buf, O_CREAT | O_RDWR | O_BINARY, data->filemode); +#endif if (data->fd != -1) { #ifndef PHP_WIN32 - /* check to make sure that the opened file is not a symlink, linking to data outside of allowable dirs */ - if (PG(open_basedir)) { - struct stat sbuf; - - if (fstat(data->fd, &sbuf)) { - close(data->fd); - data->fd = -1; - return; - } - if (S_ISLNK(sbuf.st_mode) && php_check_open_basedir(buf TSRMLS_CC)) { - close(data->fd); - data->fd = -1; - return; - } - } + /* check that this session file was created by us or root – we + don't want to end up accepting the sessions of another webapp */ + if (fstat(data->fd, &sbuf) || (sbuf.st_uid != 0 && sbuf.st_uid != getuid() && sbuf.st_uid != geteuid())) { + close(data->fd); + data->fd = -1; + return; + } #endif flock(data->fd, LOCK_EX); |
