Skip to content

Commit ecba563

Browse files
committed
Fixed bug #69090 (check cached files permissions)
1 parent e922d89 commit ecba563

File tree

6 files changed

+79
-0
lines changed

6 files changed

+79
-0
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ PHP NEWS
55
- Opcache:
66
. Fixed bug #73402 (Opcache segfault when using class constant to call a
77
method). (Laruence)
8+
. Fixed bug #69090 (check cached files permissions)
89

910
- OpenSSL
1011
. Fixed bug #72776 (Invalid parameter in memcpy function trough

ext/opcache/README

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,16 @@ opcache.validate_timestamps (default "1")
102102
The frequency of the check is controlled by the directive
103103
"opcache.revalidate_freq".
104104

105+
opcache.validate_permission (default "0")
106+
Leads OPcache to check file readability on each access to cached file.
107+
This directive should be enabled in shared hosting environment, when few
108+
users (PHP-FPM pools) reuse the common OPcache shared memory.
109+
110+
opcache.validate_root (default "0")
111+
This directive prevents file name collisions in different "chroot"
112+
environments. It should be enabled for sites that may serve requests in
113+
different "chroot" environments.
114+
105115
opcache.revalidate_freq (default "2")
106116
How often (in seconds) to check file timestamps for changes to the shared
107117
memory storage allocation. ("1" means validate once per second, but only

ext/opcache/ZendAccelerator.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1592,6 +1592,28 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T
15921592
persistent_script = NULL;
15931593
}
15941594

1595+
/* Revalidate acessibility of cached file */
1596+
if (EXPECTED(persistent_script != NULL) &&
1597+
UNEXPECTED(ZCG(accel_directives).validate_permission) &&
1598+
file_handle->type == ZEND_HANDLE_FILENAME &&
1599+
UNEXPECTED(access(file_handle->filename, R_OK) != 0)) {
1600+
if (type == ZEND_REQUIRE) {
1601+
#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
1602+
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
1603+
#else
1604+
zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
1605+
#endif
1606+
zend_bailout();
1607+
} else {
1608+
#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
1609+
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
1610+
#else
1611+
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC);
1612+
#endif
1613+
}
1614+
return NULL;
1615+
}
1616+
15951617
SHM_UNPROTECT();
15961618

15971619
/* If script is found then validate_timestamps if option is enabled */
@@ -2126,6 +2148,31 @@ static void accel_activate(void)
21262148
return;
21272149
}
21282150

2151+
#ifndef ZEND_WIN32
2152+
if (ZCG(accel_directives).validate_root) {
2153+
struct stat buf;
2154+
2155+
if (stat("/", &buf) != 0) {
2156+
ZCG(root_hash) = 0;
2157+
} else {
2158+
unsigned long x = buf.st_ino;
2159+
2160+
#if SIZEOF_LONG == 4
2161+
x = ((x >> 16) ^ x) * 0x45d9f3b;
2162+
x = ((x >> 16) ^ x) * 0x45d9f3b;
2163+
x = (x >> 16) ^ x;
2164+
#elif SIZEOF_LONG == 8
2165+
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
2166+
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
2167+
x = x ^ (x >> 31);
2168+
#endif
2169+
ZCG(root_hash) = x;
2170+
}
2171+
} else {
2172+
ZCG(root_hash) = 0;
2173+
}
2174+
#endif
2175+
21292176
SHM_UNPROTECT();
21302177
/* PHP-5.4 and above return "double", but we use 1 sec precision */
21312178
ZCG(request_time) = (time_t)sapi_get_request_time(TSRMLS_C);

ext/opcache/ZendAccelerator.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,8 @@ typedef struct _zend_accel_directives {
230230
zend_bool file_override_enabled;
231231
zend_bool inherited_hack;
232232
zend_bool enable_cli;
233+
zend_bool validate_permission;
234+
zend_bool validate_root;
233235
unsigned long revalidate_freq;
234236
unsigned long file_update_protection;
235237
char *error_log;
@@ -264,6 +266,9 @@ typedef struct _zend_accel_globals {
264266
int include_path_len; /* "include_path" string length */
265267
int include_path_check;
266268
time_t request_time;
269+
#ifndef ZEND_WIN32
270+
unsigned long root_hash;
271+
#endif
267272
/* preallocated shared-memory block to save current script */
268273
void *mem;
269274
/* cache to save hash lookup on the same INCLUDE opcode */

ext/opcache/zend_accelerator_hash.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ zend_accel_hash_entry* zend_accel_hash_update(zend_accel_hash *accel_hash, char
8686
}
8787

8888
hash_value = zend_inline_hash_func(key, key_length);
89+
#ifndef ZEND_WIN32
90+
hash_value ^= ZCG(root_hash);
91+
#endif
8992
index = hash_value % accel_hash->max_num_entries;
9093

9194
/* try to see if the element already exists in the hash */
@@ -147,6 +150,9 @@ void* zend_accel_hash_find(zend_accel_hash *accel_hash, char *key, zend_uint key
147150
zend_accel_hash_entry *entry;
148151

149152
hash_value = zend_inline_hash_func(key, key_length);
153+
#ifndef ZEND_WIN32
154+
hash_value ^= ZCG(root_hash);
155+
#endif
150156
index = hash_value % accel_hash->max_num_entries;
151157

152158
entry = accel_hash->hash_table[index];
@@ -175,6 +181,9 @@ zend_accel_hash_entry* zend_accel_hash_find_entry(zend_accel_hash *accel_hash, c
175181
zend_accel_hash_entry *entry;
176182

177183
hash_value = zend_inline_hash_func(key, key_length);
184+
#ifndef ZEND_WIN32
185+
hash_value ^= ZCG(root_hash);
186+
#endif
178187
index = hash_value % accel_hash->max_num_entries;
179188

180189
entry = accel_hash->hash_table[index];
@@ -200,6 +209,9 @@ int zend_accel_hash_unlink(zend_accel_hash *accel_hash, char *key, zend_uint key
200209
zend_accel_hash_entry *entry, *last_entry=NULL;
201210

202211
hash_value = zend_inline_hash_func(key, key_length);
212+
#ifndef ZEND_WIN32
213+
hash_value ^= ZCG(root_hash);
214+
#endif
203215
index = hash_value % accel_hash->max_num_entries;
204216

205217
entry = accel_hash->hash_table[index];

ext/opcache/zend_accelerator_module.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,8 @@ ZEND_INI_BEGIN()
255255
STD_PHP_INI_BOOLEAN("opcache.enable" , "1", PHP_INI_ALL, OnEnable, enabled , zend_accel_globals, accel_globals)
256256
STD_PHP_INI_BOOLEAN("opcache.use_cwd" , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.use_cwd , zend_accel_globals, accel_globals)
257257
STD_PHP_INI_BOOLEAN("opcache.validate_timestamps", "1", PHP_INI_ALL , OnUpdateBool, accel_directives.validate_timestamps, zend_accel_globals, accel_globals)
258+
STD_PHP_INI_BOOLEAN("opcache.validate_permission", "0", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.validate_permission, zend_accel_globals, accel_globals)
259+
STD_PHP_INI_BOOLEAN("opcache.validate_root" , "0", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.validate_root , zend_accel_globals, accel_globals)
258260
STD_PHP_INI_BOOLEAN("opcache.inherited_hack" , "1", PHP_INI_SYSTEM, OnUpdateBool, accel_directives.inherited_hack , zend_accel_globals, accel_globals)
259261
STD_PHP_INI_BOOLEAN("opcache.dups_fix" , "0", PHP_INI_ALL , OnUpdateBool, accel_directives.ignore_dups , zend_accel_globals, accel_globals)
260262
STD_PHP_INI_BOOLEAN("opcache.revalidate_path" , "0", PHP_INI_ALL , OnUpdateBool, accel_directives.revalidate_path , zend_accel_globals, accel_globals)
@@ -663,6 +665,8 @@ static ZEND_FUNCTION(opcache_get_configuration)
663665
add_assoc_bool(directives, "opcache.enable_cli", ZCG(accel_directives).enable_cli);
664666
add_assoc_bool(directives, "opcache.use_cwd", ZCG(accel_directives).use_cwd);
665667
add_assoc_bool(directives, "opcache.validate_timestamps", ZCG(accel_directives).validate_timestamps);
668+
add_assoc_bool(directives, "opcache.validate_permission", ZCG(accel_directives).validate_permission);
669+
add_assoc_bool(directives, "opcache.validate_root", ZCG(accel_directives).validate_root);
666670
add_assoc_bool(directives, "opcache.inherited_hack", ZCG(accel_directives).inherited_hack);
667671
add_assoc_bool(directives, "opcache.dups_fix", ZCG(accel_directives).ignore_dups);
668672
add_assoc_bool(directives, "opcache.revalidate_path", ZCG(accel_directives).revalidate_path);

0 commit comments

Comments
 (0)