Patch opcache_bug69090_user_id_keys for opcache Bug #69090
Patch version 2016-11-04 10:35 UTC
Return to Bug #69090 |
Download this patch
Patch Revisions:
Developer: php-dev@coydogsoftware.net
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index 985a4ef..3522861 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -52,6 +52,8 @@
typedef int uid_t;
typedef int gid_t;
#include <io.h>
+#include <Windows.h>
+#include <Lmcons.h> /* username max len */
#endif
#ifndef ZEND_WIN32
@@ -949,8 +951,36 @@ static unsigned int zend_accel_script_checksum(zend_persistent_script *persisten
char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_length, int *key_len TSRMLS_DC)
{
int key_length;
+ int key_offset = 0;
+ char *user_id_str = NULL;
+ int user_id_len = 0;
- /* CWD and include_path don't matter for absolute file names and streams */
+#ifdef ZEND_WIN32
+ /* Windows has no direct equivalent of EUID. SID and RID are roughly
+ * analagous, but for now simply using the username seems most
+ * straightforward since we can get max len from UNLEN in Lmcons.h
+ */
+ int username_len = UNLEN + 1;
+ char username_str[UNLEN + 1]; /* not wide-character compatible */
+ if (GetUserName(username_str, &username_len) == 0) {
+ zend_accel_error(ACCEL_LOG_WARNING, "GetUserName for opcache key user_id_str failed!");
+ return NULL;
+ } else {
+ user_id_len = username_len - 1; /* subtract terminating zero */
+ user_id_str = username_str;
+ }
+#else
+ #define EUID_BUFFSIZE 40 /* hope we never see >128-bit uid_t's */
+ uid_t euid = geteuid();
+ char euid_str[EUID_BUFFSIZE];
+ if (user_id_len = snprintf(euid_str, EUID_BUFFSIZE - 1, "%d", euid) >= EUID_BUFFSIZE) {
+ return NULL;
+ } else {
+ user_id_str = euid_str;
+ }
+#endif
+
+ /* CWD and include_path don't matter for absolute file names and streams */
if (ZCG(accel_directives).use_cwd &&
!IS_ABSOLUTE_PATH(file_handle->filename, path_length) &&
!is_stream_path(file_handle->filename)) {
@@ -958,7 +988,6 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt
int include_path_len = 0;
const char *parent_script = NULL;
int parent_script_len = 0;
- int cur_len = 0;
int cwd_len;
char *cwd;
@@ -1027,7 +1056,7 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt
}
/* Calculate key length */
- key_length = cwd_len + path_length + include_path_len + 2;
+ key_length = user_id_len + cwd_len + path_length + include_path_len + 3; /* +3 for delimiter colons */
if (parent_script_len) {
key_length += parent_script_len + 1;
}
@@ -1036,39 +1065,57 @@ char *accel_make_persistent_key_ex(zend_file_handle *file_handle, int path_lengt
* Note - the include_path must be the last element in the key,
* since in itself, it may include colons (which we use to separate
* different components of the key)
- */
+ */
if ((size_t)key_length >= sizeof(ZCG(key))) {
ZCG(key_len) = 0;
return NULL;
}
- memcpy(ZCG(key), cwd, cwd_len);
- ZCG(key)[cwd_len] = ':';
-
- memcpy(ZCG(key) + cwd_len + 1, file_handle->filename, path_length);
-
- ZCG(key)[cwd_len + 1 + path_length] = ':';
- cur_len = cwd_len + 1 + path_length + 1;
-
- if (parent_script_len) {
- memcpy(ZCG(key) + cur_len, parent_script, parent_script_len);
- cur_len += parent_script_len;
- ZCG(key)[cur_len] = ':';
- cur_len++;
+ /* Key on euid to prevent cross-user cache access bypassing file
+ * permissions. Prevents filename collision in chroots IFF each
+ * chroot environment has a different user.
+ */
+ memcpy(ZCG(key), user_id_str, user_id_len);
+ key_offset += user_id_len;
+ ZCG(key)[key_offset] = ':';
+ key_offset++;
+
+ memcpy(ZCG(key + key_offset), cwd, cwd_len);
+ key_offset += cwd_len;
+ ZCG(key)[key_offset] = ':';
+ key_offset++;
+
+ memcpy(ZCG(key) + key_offset, file_handle->filename, path_length);
+ key_offset += path_length;
+ ZCG(key)[key_offset] = ':';
+ key_offset++;
+
+ if (parent_script_len) {
+ memcpy(ZCG(key) + key_offset, parent_script, parent_script_len);
+ key_offset += parent_script_len;
+ ZCG(key)[key_offset] = ':';
+ key_offset++;
}
- memcpy(ZCG(key) + cur_len, include_path, include_path_len);
+ memcpy(ZCG(key) + key_offset, include_path, include_path_len);
ZCG(key)[key_length] = '\0';
} else {
- /* not use_cwd */
- key_length = path_length;
+ /* not use_cwd and use_cwd cases where filename is absolute */
+ key_length = user_id_len + 1 + path_length; /* <EUID>:<path> */
if ((size_t)key_length >= sizeof(ZCG(key))) {
ZCG(key_len) = 0;
return NULL;
}
- memcpy(ZCG(key), file_handle->filename, key_length + 1);
+
+ memcpy(ZCG(key), user_id_str, user_id_len);
+ key_offset = user_id_len;
+ ZCG(key)[key_offset] = ':';
+ key_offset++;
+
+ memcpy(ZCG(key + key_offset), file_handle->filename, key_length + 1);
}
*key_len = ZCG(key_len) = key_length;
+ zend_accel_error(ACCEL_LOG_DEBUG, "make_persistent_key_ex() returning key: %s", ZCG(key));
return ZCG(key);
}
|