summaryrefslogtreecommitdiffstats
path: root/bug69090.patch
blob: 270f05a0151d9e44b3aeeef5ac8bdd9d8ad9649d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
Backported from php 5.6 by Remi
Using 


From ecba563f2fa1e027ea91b9ee0d50611273852995 Mon Sep 17 00:00:00 2001
From: Dmitry Stogov <dmitry@zend.com>
Date: Wed, 16 Nov 2016 12:43:10 +0300
Subject: [PATCH] Fixed bug #69090 (check cached files permissions)

---
 NEWS                                  |  1 +
 ext/opcache/README                    | 10 ++++++++
 ext/opcache/ZendAccelerator.c         | 47 +++++++++++++++++++++++++++++++++++
 ext/opcache/ZendAccelerator.h         |  5 ++++
 ext/opcache/zend_accelerator_hash.c   | 12 +++++++++
 ext/opcache/zend_accelerator_module.c |  4 +++
 6 files changed, 79 insertions(+)

diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index 985a4ef..c8d2290 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -1559,6 +1559,28 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T
 		persistent_script = NULL;
 	}
 
+	/* 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) {
+#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
+			zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
+#else
+			zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename TSRMLS_CC);
+#endif
+			zend_bailout();
+		} else {
+#if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
+			zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
+#else
+			zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename TSRMLS_CC);
+#endif
+		}
+		return NULL;
+	}
+
 	SHM_UNPROTECT();
 
 	/* If script is found then validate_timestamps if option is enabled */
@@ -2071,6 +2093,31 @@ static void accel_activate(void)
 		return;
 	}
 
+#ifndef ZEND_WIN32
+	if (ZCG(accel_directives).validate_root) {
+		struct stat buf;
+
+		if (stat("/", &buf) != 0) {
+			ZCG(root_hash) = 0;
+		} else {
+			unsigned long x = buf.st_ino;
+
+#if SIZEOF_LONG == 4
+			x = ((x >> 16) ^ x) * 0x45d9f3b;
+			x = ((x >> 16) ^ x) * 0x45d9f3b;
+			x = (x >> 16) ^ x;
+#elif SIZEOF_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
+
 	SHM_UNPROTECT();
 	/* PHP-5.4 and above return "double", but we use 1 sec precision */
 	ZCG(request_time) = (time_t)sapi_get_request_time(TSRMLS_C);
diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h
index 11942f1..a711de7 100644
--- a/ext/opcache/ZendAccelerator.h
+++ b/ext/opcache/ZendAccelerator.h
@@ -229,6 +229,8 @@ typedef struct _zend_accel_directives {
 	zend_bool      file_override_enabled;
 	zend_bool      inherited_hack;
 	zend_bool      enable_cli;
+	zend_bool      validate_permission;
+	zend_bool      validate_root;
 	unsigned long  revalidate_freq;
 	unsigned long  file_update_protection;
 	char          *error_log;
@@ -263,6 +265,9 @@ typedef struct _zend_accel_globals {
 	int                     include_path_len; /* "include_path" string length */
 	int                     include_path_check;
 	time_t                  request_time;
+#ifndef ZEND_WIN32
+	unsigned long           root_hash;
+#endif
 	/* preallocated shared-memory block to save current script */
 	void                   *mem;
 	/* cache to save hash lookup on the same INCLUDE opcode */
diff --git a/ext/opcache/zend_accelerator_hash.c b/ext/opcache/zend_accelerator_hash.c
index 992885f..4b8b712 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 */
@@ -147,6 +150,9 @@ void* zend_accel_hash_find(zend_accel_hash *accel_hash, char *key, zend_uint key
 	zend_accel_hash_entry *entry;
 
 	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];
@@ -175,6 +181,9 @@ zend_accel_hash_entry* zend_accel_hash_find_entry(zend_accel_hash *accel_hash, c
 	zend_accel_hash_entry *entry;
 
 	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];
@@ -200,6 +209,9 @@ int zend_accel_hash_unlink(zend_accel_hash *accel_hash, char *key, zend_uint 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 5671f2f..0faa915 100644
--- a/ext/opcache/zend_accelerator_module.c
+++ b/ext/opcache/zend_accelerator_module.c
@@ -251,6 +251,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)
@@ -659,6 +661,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);
-- 
2.1.4

From a91f3d475ee9a59c38833c683c0bd355338f1564 Mon Sep 17 00:00:00 2001
From: Dmitry Stogov <dmitry@zend.com>
Date: Wed, 16 Nov 2016 16:43:57 +0300
Subject: [PATCH] Fixed ZTS build

---
 ext/opcache/zend_accelerator_hash.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/ext/opcache/zend_accelerator_hash.c b/ext/opcache/zend_accelerator_hash.c
index 4b8b712..4a16a93 100644
--- a/ext/opcache/zend_accelerator_hash.c
+++ b/ext/opcache/zend_accelerator_hash.c
@@ -77,6 +77,9 @@ zend_accel_hash_entry* zend_accel_hash_update(zend_accel_hash *accel_hash, char
 	zend_ulong index;
 	zend_accel_hash_entry *entry;
 	zend_accel_hash_entry *indirect_bucket = NULL;
+#ifndef ZEND_WIN32
+	TSRMLS_FETCH();
+#endif
 
 	if (indirect) {
 		indirect_bucket = (zend_accel_hash_entry*)data;
@@ -148,6 +151,9 @@ void* zend_accel_hash_find(zend_accel_hash *accel_hash, char *key, zend_uint key
 	zend_ulong hash_value;
 	zend_ulong index;
 	zend_accel_hash_entry *entry;
+#ifndef ZEND_WIN32
+	TSRMLS_FETCH();
+#endif
 
 	hash_value = zend_inline_hash_func(key, key_length);
 #ifndef ZEND_WIN32
@@ -179,6 +185,9 @@ zend_accel_hash_entry* zend_accel_hash_find_entry(zend_accel_hash *accel_hash, c
 	zend_ulong hash_value;
 	zend_ulong index;
 	zend_accel_hash_entry *entry;
+#ifndef ZEND_WIN32
+	TSRMLS_FETCH();
+#endif
 
 	hash_value = zend_inline_hash_func(key, key_length);
 #ifndef ZEND_WIN32
@@ -207,6 +216,9 @@ int zend_accel_hash_unlink(zend_accel_hash *accel_hash, char *key, zend_uint key
 	zend_ulong hash_value;
     zend_ulong index;
     zend_accel_hash_entry *entry, *last_entry=NULL;
+#ifndef ZEND_WIN32
+	TSRMLS_FETCH();
+#endif
 
 	hash_value = zend_inline_hash_func(key, key_length);
 #ifndef ZEND_WIN32
-- 
2.1.4

From 8202b970777b84d57c590b78f9b6572ef0e0c205 Mon Sep 17 00:00:00 2001
From: Dmitry Stogov <dmitry@zend.com>
Date: Wed, 16 Nov 2016 23:01:40 +0300
Subject: [PATCH] Use full path

---
 ext/opcache/ZendAccelerator.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index c8d2290..9d0d32e8 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -1563,7 +1563,7 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type T
 	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)) {
+	    UNEXPECTED(access(persistent_script->full_path, R_OK) != 0)) {
 		if (type == ZEND_REQUIRE) {
 #if ZEND_EXTENSION_API_NO < PHP_5_3_X_API_NO
 			zend_message_dispatcher(ZMSG_FAILED_REQUIRE_FOPEN, file_handle->filename);
-- 
2.1.4

From 9849c97b1bdfd7f0a7c499cad4cf601ebd68cc22 Mon Sep 17 00:00:00 2001
From: Dmitry Stogov <dmitry@zend.com>
Date: Thu, 17 Nov 2016 01:08:42 +0300
Subject: [PATCH] Accorate handling of too big inodes of chroot directories

---
 ext/opcache/ZendAccelerator.c | 20 ++++++++------------
 1 file changed, 8 insertions(+), 12 deletions(-)

diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index 9d0d32e8..7e8a444 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -2100,18 +2100,14 @@ static void accel_activate(void)
 		if (stat("/", &buf) != 0) {
 			ZCG(root_hash) = 0;
 		} else {
-			unsigned long x = buf.st_ino;
-
-#if SIZEOF_LONG == 4
-			x = ((x >> 16) ^ x) * 0x45d9f3b;
-			x = ((x >> 16) ^ x) * 0x45d9f3b;
-			x = (x >> 16) ^ x;
-#elif SIZEOF_LONG == 8
-			x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
-			x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
-			x = x ^ (x >> 31);
-#endif
-			ZCG(root_hash) = x;
+			ZCG(root_hash) = buf.st_ino;
+			if (sizeof(buf.st_ino) > sizeof(ZCG(root_hash))) {
+				if (ZCG(root_hash) != buf.st_ino) {
+					zend_alter_ini_entry("opcache.enable", sizeof("opcache.enable"), "0", 1, ZEND_INI_SYSTEM, ZEND_INI_STAGE_RUNTIME);
+					zend_accel_error(ACCEL_LOG_WARNING, "Can't cache files in chroot() directory with too big inode");
+					return;
+				}
+			}
 		}
 	} else {
 		ZCG(root_hash) = 0;
-- 
2.1.4