summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2016-11-16 12:58:30 +0300
committerDmitry Stogov <dmitry@zend.com>2016-11-16 12:58:30 +0300
commit35e7927736d98bf418084f1d8168bd45497e213a (patch)
treed2361f92972655d86ef9bfc111b17b98baa9fbe5
parentca6091471c6aefce07319488edebcfb254944e4c (diff)
parent86460af56c520b7210d5e21afb7368d4a4d01e1d (diff)
downloadphp-git-35e7927736d98bf418084f1d8168bd45497e213a.tar.gz
Merge branch 'PHP-7.1'
* PHP-7.1: Fixed bug #69090 (check cached files permissions)
-rw-r--r--ext/opcache/README10
-rw-r--r--ext/opcache/ZendAccelerator.c39
-rw-r--r--ext/opcache/ZendAccelerator.h9
-rw-r--r--ext/opcache/zend_accelerator_hash.c16
-rw-r--r--ext/opcache/zend_accelerator_module.c4
5 files changed, 74 insertions, 4 deletions
diff --git a/ext/opcache/README b/ext/opcache/README
index e4d36ba51a..cf305ad9d1 100644
--- a/ext/opcache/README
+++ b/ext/opcache/README
@@ -102,6 +102,16 @@ opcache.validate_timestamps (default "1")
The frequency of the check is controlled by the directive
"opcache.revalidate_freq".
+opcache.validate_permission (default "0")
+ Leads OPcache to check file readability on each access to cached file.
+ This directive should be enabled in shared hosting environment, when few
+ users (PHP-FPM pools) reuse the common OPcache shared memory.
+
+opcache.validate_root (default "0")
+ This directive prevents file name collisions in different "chroot"
+ environments. It should be enabled for sites that may serve requests in
+ different "chroot" environments.
+
opcache.revalidate_freq (default "2")
How often (in seconds) to check file timestamps for changes to the shared
memory storage allocation. ("1" means validate once per second, but only
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index 2f549cc011..9b6734fb49 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -1771,6 +1771,20 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
ZCG(counted) = 1;
}
+ /* Revalidate acessibility of cached file */
+ if (EXPECTED(persistent_script != NULL) &&
+ UNEXPECTED(ZCG(accel_directives).validate_permission) &&
+ file_handle->type == ZEND_HANDLE_FILENAME &&
+ UNEXPECTED(access(file_handle->filename, R_OK) != 0)) {
+ if (type == ZEND_REQUIRE) {
+ zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
+ zend_bailout();
+ } else {
+ zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC);
+ }
+ return NULL;
+ }
+
HANDLE_BLOCK_INTERRUPTIONS();
SHM_UNPROTECT();
@@ -2084,6 +2098,31 @@ static void accel_activate(void)
}
#endif
+#ifndef ZEND_WIN32
+ if (ZCG(accel_directives).validate_root) {
+ struct stat buf;
+
+ if (stat("/", &buf) != 0) {
+ ZCG(root_hash) = 0;
+ } else {
+ zend_ulong x = buf.st_ino;
+
+#if SIZEOF_ZEND_LONG == 4
+ x = ((x >> 16) ^ x) * 0x45d9f3b;
+ x = ((x >> 16) ^ x) * 0x45d9f3b;
+ x = (x >> 16) ^ x;
+#elif SIZEOF_ZEND_LONG == 8
+ x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
+ x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
+ x = x ^ (x >> 31);
+#endif
+ ZCG(root_hash) = x;
+ }
+ } else {
+ ZCG(root_hash) = 0;
+ }
+#endif
+
HANDLE_BLOCK_INTERRUPTIONS();
SHM_UNPROTECT();
diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h
index d45be56279..40e162926e 100644
--- a/ext/opcache/ZendAccelerator.h
+++ b/ext/opcache/ZendAccelerator.h
@@ -180,8 +180,10 @@ typedef struct _zend_accel_directives {
zend_bool file_override_enabled;
zend_bool inherited_hack;
zend_bool enable_cli;
- zend_ulong revalidate_freq;
- zend_ulong file_update_protection;
+ zend_bool validate_permission;
+ zend_bool validate_root;
+ zend_ulong revalidate_freq;
+ zend_ulong file_update_protection;
char *error_log;
#ifdef ZEND_WIN32
char *mmap_base;
@@ -233,6 +235,9 @@ typedef struct _zend_accel_globals {
time_t last_restart_time; /* used to synchronize SHM and in-process caches */
char system_id[32];
HashTable xlat_table;
+#ifndef ZEND_WIN32
+ zend_ulong root_hash;
+#endif
/* preallocated shared-memory block to save current script */
void *mem;
void *arena_mem;
diff --git a/ext/opcache/zend_accelerator_hash.c b/ext/opcache/zend_accelerator_hash.c
index a533d06120..7ec64cec1f 100644
--- a/ext/opcache/zend_accelerator_hash.c
+++ b/ext/opcache/zend_accelerator_hash.c
@@ -86,6 +86,9 @@ zend_accel_hash_entry* zend_accel_hash_update(zend_accel_hash *accel_hash, char
}
hash_value = zend_inline_hash_func(key, key_length);
+#ifndef ZEND_WIN32
+ hash_value ^= ZCG(root_hash);
+#endif
index = hash_value % accel_hash->max_num_entries;
/* try to see if the element already exists in the hash */
@@ -139,9 +142,15 @@ zend_accel_hash_entry* zend_accel_hash_update(zend_accel_hash *accel_hash, char
static zend_always_inline void* zend_accel_hash_find_ex(zend_accel_hash *accel_hash, char *key, uint32_t key_length, zend_ulong hash_value, int data)
{
- zend_ulong index = hash_value % accel_hash->max_num_entries;
- zend_accel_hash_entry *entry = accel_hash->hash_table[index];
+ zend_ulong index;
+ zend_accel_hash_entry *entry;
+#ifndef ZEND_WIN32
+ hash_value ^= ZCG(root_hash);
+#endif
+ index = hash_value % accel_hash->max_num_entries;
+
+ entry = accel_hash->hash_table[index];
while (entry) {
if (entry->hash_value == hash_value
&& entry->key_length == key_length
@@ -224,6 +233,9 @@ int zend_accel_hash_unlink(zend_accel_hash *accel_hash, char *key, uint32_t key_
zend_accel_hash_entry *entry, *last_entry=NULL;
hash_value = zend_inline_hash_func(key, key_length);
+#ifndef ZEND_WIN32
+ hash_value ^= ZCG(root_hash);
+#endif
index = hash_value % accel_hash->max_num_entries;
entry = accel_hash->hash_table[index];
diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c
index b8a3410895..7feaaf6584 100644
--- a/ext/opcache/zend_accelerator_module.c
+++ b/ext/opcache/zend_accelerator_module.c
@@ -272,6 +272,8 @@ ZEND_INI_BEGIN()
STD_PHP_INI_BOOLEAN("opcache.enable" , "1", PHP_INI_ALL, OnEnable, enabled , zend_accel_globals, accel_globals)
STD_PHP_INI_BOOLEAN("opcache.use_cwd" , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.use_cwd , zend_accel_globals, accel_globals)
STD_PHP_INI_BOOLEAN("opcache.validate_timestamps", "1", PHP_INI_ALL , OnUpdateBool, accel_directives.validate_timestamps, zend_accel_globals, accel_globals)
+ STD_PHP_INI_BOOLEAN("opcache.validate_permission", "0", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.validate_permission, zend_accel_globals, accel_globals)
+ STD_PHP_INI_BOOLEAN("opcache.validate_root" , "0", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.validate_root , zend_accel_globals, accel_globals)
STD_PHP_INI_BOOLEAN("opcache.inherited_hack" , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.inherited_hack , zend_accel_globals, accel_globals)
STD_PHP_INI_BOOLEAN("opcache.dups_fix" , "0", PHP_INI_ALL , OnUpdateBool, accel_directives.ignore_dups , zend_accel_globals, accel_globals)
STD_PHP_INI_BOOLEAN("opcache.revalidate_path" , "0", PHP_INI_ALL , OnUpdateBool, accel_directives.revalidate_path , zend_accel_globals, accel_globals)
@@ -691,6 +693,8 @@ static ZEND_FUNCTION(opcache_get_configuration)
add_assoc_bool(&directives, "opcache.enable_cli", ZCG(accel_directives).enable_cli);
add_assoc_bool(&directives, "opcache.use_cwd", ZCG(accel_directives).use_cwd);
add_assoc_bool(&directives, "opcache.validate_timestamps", ZCG(accel_directives).validate_timestamps);
+ add_assoc_bool(&directives, "opcache.validate_permission", ZCG(accel_directives).validate_permission);
+ add_assoc_bool(&directives, "opcache.validate_root", ZCG(accel_directives).validate_root);
add_assoc_bool(&directives, "opcache.inherited_hack", ZCG(accel_directives).inherited_hack);
add_assoc_bool(&directives, "opcache.dups_fix", ZCG(accel_directives).ignore_dups);
add_assoc_bool(&directives, "opcache.revalidate_path", ZCG(accel_directives).revalidate_path);