Fix bug #66171: better handling of symlinks

This commit is contained in:
Stanislav Malyshev 2014-04-13 20:31:20 -07:00
parent 9e76e87ca9
commit 41569b1029

View File

@ -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);