Skip to content

Commit

Permalink
Adapt suhosin to lots of changes in PHP 5.5 executor
Browse files Browse the repository at this point in the history
  • Loading branch information
Stefan Esser committed Feb 11, 2014
1 parent 65c1c61 commit 3142dc0
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 25 deletions.
117 changes: 95 additions & 22 deletions execute.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@

#include "sha256.h"

#if PHP_VERSION_ID >= 50500
static void (*old_execute_ex)(zend_execute_data *execute_data TSRMLS_DC);
static void suhosin_execute_ex(zend_execute_data *execute_data TSRMLS_DC);
#endif

static void (*old_execute)(zend_op_array *op_array TSRMLS_DC);
static void suhosin_execute(zend_op_array *op_array TSRMLS_DC);
Expand All @@ -48,8 +52,13 @@ static void *(*zo_set_oe_ex)(void *ptr) = NULL;
/*STATIC zend_op_array* (*old_compile_file)(zend_file_handle* file_handle, int type TSRMLS_DC);
STATIC zend_op_array* suhosin_compile_file(zend_file_handle*, int TSRMLS_DC);*/

#if PHP_VERSION_ID >= 50500
static void suhosin_execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC);
static void (*old_execute_internal)(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC);
#else
static void suhosin_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
static void (*old_execute_internal)(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC);
#endif

extern zend_extension suhosin_zend_extension_entry;

Expand Down Expand Up @@ -355,8 +364,14 @@ static int suhosin_detect_codetype(zend_op_array *op_array TSRMLS_DC)

/* {{{ void suhosin_execute_ex(zend_op_array *op_array TSRMLS_DC)
* This function provides a hook for execution */
#if PHP_VERSION_ID > 50500
static void suhosin_execute_ex(zend_execute_data *execute_data TSRMLS_DC)
{
zend_op_array *op_array = execute_data->op_array;
#else
static void suhosin_execute_ex(zend_op_array *op_array, int zo, long dummy TSRMLS_DC)
{
#endif
zend_op_array *new_op_array;
int op_array_type, len;
char *fn;
Expand Down Expand Up @@ -462,7 +477,7 @@ static void suhosin_execute_ex(zend_op_array *op_array, int zo, long dummy TSRML
SUHOSIN_G(execution_depth)++;

if (SUHOSIN_G(max_execution_depth) && SUHOSIN_G(execution_depth) > SUHOSIN_G(max_execution_depth)) {
suhosin_log(S_EXECUTOR, "maximum execution depth reached - script terminated");
suhosin_log(S_EXECUTOR|S_GETCALLER, "maximum execution depth reached - script terminated");
suhosin_bailout(TSRMLS_C);
}

Expand Down Expand Up @@ -509,7 +524,7 @@ static void suhosin_execute_ex(zend_op_array *op_array, int zo, long dummy TSRML
switch (op_array_type) {
case SUHOSIN_CODE_TYPE_EVAL:
if (SUHOSIN_G(executor_disable_eval)) {
suhosin_log(S_EXECUTOR, "use of eval is forbidden by configuration");
suhosin_log(S_EXECUTOR|S_GETCALLER, "use of eval is forbidden by configuration");
if (!SUHOSIN_G(simulation)) {
zend_error(E_ERROR, "SUHOSIN - Use of eval is forbidden by configuration");
}
Expand All @@ -518,7 +533,7 @@ static void suhosin_execute_ex(zend_op_array *op_array, int zo, long dummy TSRML

case SUHOSIN_CODE_TYPE_REGEXP:
if (SUHOSIN_G(executor_disable_emod)) {
suhosin_log(S_EXECUTOR, "use of preg_replace() with /e modifier is forbidden by configuration");
suhosin_log(S_EXECUTOR|S_GETCALLER, "use of preg_replace() with /e modifier is forbidden by configuration");
if (!SUHOSIN_G(simulation)) {
zend_error(E_ERROR, "SUHOSIN - Use of preg_replace() with /e modifier is forbidden by configuration");
}
Expand All @@ -532,37 +547,37 @@ static void suhosin_execute_ex(zend_op_array *op_array, int zo, long dummy TSRML
break;

case SUHOSIN_CODE_TYPE_LONGNAME:
suhosin_log(S_INCLUDE, "Include filename ('%s') is too long", op_array->filename);
suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') is too long", op_array->filename);
suhosin_bailout(TSRMLS_C);
break;

case SUHOSIN_CODE_TYPE_MANYDOTS:
suhosin_log(S_INCLUDE, "Include filename ('%s') contains too many '../'", op_array->filename);
suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') contains too many '../'", op_array->filename);
suhosin_bailout(TSRMLS_C);
break;

case SUHOSIN_CODE_TYPE_UPLOADED:
suhosin_log(S_INCLUDE, "Include filename is an uploaded file");
suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename is an uploaded file");
suhosin_bailout(TSRMLS_C);
break;

case SUHOSIN_CODE_TYPE_0FILE:
suhosin_log(S_INCLUDE, "Include filename contains an ASCIIZ character");
suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename contains an ASCIIZ character");
suhosin_bailout(TSRMLS_C);
break;

case SUHOSIN_CODE_TYPE_WRITABLE:
suhosin_log(S_INCLUDE, "Include filename ('%s') is writable by PHP process", op_array->filename);
suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') is writable by PHP process", op_array->filename);
suhosin_bailout(TSRMLS_C);
break;

case SUHOSIN_CODE_TYPE_BLACKURL:
suhosin_log(S_INCLUDE, "Include filename ('%s') is an URL that is forbidden by the blacklist", op_array->filename);
suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') is an URL that is forbidden by the blacklist", op_array->filename);
suhosin_bailout(TSRMLS_C);
break;

case SUHOSIN_CODE_TYPE_BADURL:
suhosin_log(S_INCLUDE, "Include filename ('%s') is an URL that is not allowed", op_array->filename);
suhosin_log(S_INCLUDE|S_GETCALLER, "Include filename ('%s') is an URL that is not allowed", op_array->filename);
suhosin_bailout(TSRMLS_C);
break;

Expand All @@ -588,17 +603,22 @@ static void suhosin_execute_ex(zend_op_array *op_array, int zo, long dummy TSRML
}

continue_execution:
#if PHP_VERSION_ID >= 50500
old_execute_ex (execute_data TSRMLS_CC);
#else
if (zo) {
old_execute_ZO (op_array, dummy TSRMLS_CC);
} else {
old_execute (op_array TSRMLS_CC);
}
#endif
/* nothing to do */
SUHOSIN_G(in_code_type) = orig_code_type;
SUHOSIN_G(execution_depth)--;
}
/* }}} */

#if PHP_VERSION_ID < 50500
/* {{{ void suhosin_execute(zend_op_array *op_array TSRMLS_DC)
* This function provides a hook for execution */
static void suhosin_execute(zend_op_array *op_array TSRMLS_DC)
Expand All @@ -613,11 +633,17 @@ static void suhosin_execute_ZO(zend_op_array *op_array, long dummy TSRMLS_DC)
suhosin_execute_ex(op_array, 1, dummy TSRMLS_CC);
}
/* }}} */
#endif


#if PHP_VERSION_ID >= 50500
#define IH_HANDLER_PARAMS_REST int ht, zval *return_value, zval **return_value_ptr, zval *this_ptr, int return_value_used TSRMLS_DC
#define IH_HANDLER_PARAMS internal_function_handler *ih, IH_HANDLER_PARAMS_REST
#define IH_HANDLER_PARAM_PASSTHRU ih, ht, return_value, return_value_ptr, this_ptr, return_value_used TSRMLS_CC
#else
#define IH_HANDLER_PARAMS_REST zend_execute_data *execute_data_ptr, int return_value_used, int ht, zval *return_value TSRMLS_DC
#define IH_HANDLER_PARAMS internal_function_handler *ih, IH_HANDLER_PARAMS_REST
#define IH_HANDLER_PARAM_PASSTHRU ih, execute_data_ptr, return_value_used, ht, return_value TSRMLS_CC
#endif

HashTable ihandler_table;

Expand Down Expand Up @@ -1541,13 +1567,38 @@ internal_function_handler ihandlers[] = {

/* {{{ void suhosin_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC)
* This function provides a hook for internal execution */
#if PHP_VERSION_ID >= 50500
#define EX_T(offset) (*EX_TMP_VAR(execute_data_ptr, offset))

static void suhosin_execute_internal(zend_execute_data *execute_data_ptr, zend_fcall_info *fci, int return_value_used TSRMLS_DC)
{
zval *return_value;
zval **return_value_ptr;
zval *this_ptr;
int ht;

if (fci) {
return_value = *fci->retval_ptr_ptr;
return_value_ptr = fci->retval_ptr_ptr;
this_ptr = fci->object_ptr;
ht = fci->param_count;
} else {
temp_variable *ret = &EX_T(execute_data_ptr->opline->result.var);
zend_function *fbc = execute_data_ptr->function_state.function;
return_value = ret->var.ptr;
return_value_ptr = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) ? &ret->var.ptr : NULL;
this_ptr = execute_data_ptr->object;
ht = execute_data_ptr->opline->extended_value;
}
#else
static void suhosin_execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC)
{
zval *return_value;
int ht = execute_data_ptr->opline->extended_value;
#endif
char *lcname;
int function_name_strlen, free_lcname = 0;
zval *return_value;
zend_class_entry *ce = NULL;
int ht;
internal_function_handler *ih;

#ifdef ZEND_ENGINE_2
Expand All @@ -1568,7 +1619,8 @@ static void suhosin_execute_internal(zend_execute_data *execute_data_ptr, int re
lcname[function_name_strlen] = 0;
zend_str_tolower(lcname, function_name_strlen);
}


#if PHP_VERSION_ID < 50500
#ifdef ZEND_ENGINE_2
# if PHP_VERSION_ID < 50400
return_value = (*(temp_variable *)((char *) execute_data_ptr->Ts + execute_data_ptr->opline->result.u.var)).var.ptr;
Expand All @@ -1578,15 +1630,15 @@ static void suhosin_execute_internal(zend_execute_data *execute_data_ptr, int re
#else
return_value = execute_data_ptr->Ts[execute_data_ptr->opline->result.u.var].var.ptr;
#endif
ht = execute_data_ptr->opline->extended_value;
#endif

SDEBUG("function: %s", lcname);

if (SUHOSIN_G(in_code_type) == SUHOSIN_EVAL) {

if (SUHOSIN_G(eval_whitelist) != NULL) {
if (!zend_hash_exists(SUHOSIN_G(eval_whitelist), lcname, function_name_strlen+1)) {
suhosin_log(S_EXECUTOR, "function outside of eval whitelist called: %s()", lcname);
suhosin_log(S_EXECUTOR|S_GETCALLER, "function outside of eval whitelist called: %s()", lcname);
if (!SUHOSIN_G(simulation)) {
goto execute_internal_bailout;
} else {
Expand All @@ -1595,7 +1647,7 @@ static void suhosin_execute_internal(zend_execute_data *execute_data_ptr, int re
}
} else if (SUHOSIN_G(eval_blacklist) != NULL) {
if (zend_hash_exists(SUHOSIN_G(eval_blacklist), lcname, function_name_strlen+1)) {
suhosin_log(S_EXECUTOR, "function within eval blacklist called: %s()", lcname);
suhosin_log(S_EXECUTOR|S_GETCALLER, "function within eval blacklist called: %s()", lcname);
if (!SUHOSIN_G(simulation)) {
goto execute_internal_bailout;
} else {
Expand All @@ -1607,7 +1659,7 @@ static void suhosin_execute_internal(zend_execute_data *execute_data_ptr, int re

if (SUHOSIN_G(func_whitelist) != NULL) {
if (!zend_hash_exists(SUHOSIN_G(func_whitelist), lcname, function_name_strlen+1)) {
suhosin_log(S_EXECUTOR, "function outside of whitelist called: %s()", lcname);
suhosin_log(S_EXECUTOR|S_GETCALLER, "function outside of whitelist called: %s()", lcname);
if (!SUHOSIN_G(simulation)) {
goto execute_internal_bailout;
} else {
Expand All @@ -1616,7 +1668,7 @@ static void suhosin_execute_internal(zend_execute_data *execute_data_ptr, int re
}
} else if (SUHOSIN_G(func_blacklist) != NULL) {
if (zend_hash_exists(SUHOSIN_G(func_blacklist), lcname, function_name_strlen+1)) {
suhosin_log(S_EXECUTOR, "function within blacklist called: %s()", lcname);
suhosin_log(S_EXECUTOR|S_GETCALLER, "function within blacklist called: %s()", lcname);
if (!SUHOSIN_G(simulation)) {
goto execute_internal_bailout;
} else {
Expand All @@ -1635,10 +1687,18 @@ static void suhosin_execute_internal(zend_execute_data *execute_data_ptr, int re
}

if (retval == 0) {
#if PHP_VERSION_ID >= 50500
old_execute_internal(execute_data_ptr, fci, return_value_used TSRMLS_CC);
#else
old_execute_internal(execute_data_ptr, return_value_used TSRMLS_CC);
#endif
}
} else {
#if PHP_VERSION_ID >= 50500
old_execute_internal(execute_data_ptr, fci, return_value_used TSRMLS_CC);
#else
old_execute_internal(execute_data_ptr, return_value_used TSRMLS_CC);
#endif
}
if (free_lcname == 1) {
efree(lcname);
Expand Down Expand Up @@ -1678,13 +1738,19 @@ static int function_lookup(zend_extension *extension)
void suhosin_hook_execute(TSRMLS_D)
{
internal_function_handler *ih;


#if PHP_VERSION_ID >= 50500
old_execute_ex = zend_execute_ex;
zend_execute_ex = suhosin_execute_ex;
#else
old_execute = zend_execute;
zend_execute = suhosin_execute;
#endif

/* old_compile_file = zend_compile_file;
zend_compile_file = suhosin_compile_file; */

#if ZO_COMPATIBILITY_HACK_TEMPORARY_DISABLED
if (zo_set_oe_ex == NULL) {
zo_set_oe_ex = (void *)DL_FETCH_SYMBOL(NULL, "zend_optimizer_set_oe_ex");
}
Expand All @@ -1695,6 +1761,7 @@ void suhosin_hook_execute(TSRMLS_D)
if (zo_set_oe_ex != NULL) {
old_execute_ZO = zo_set_oe_ex(suhosin_execute_ZO);
}
#endif

old_execute_internal = zend_execute_internal;
if (old_execute_internal == NULL) {
Expand Down Expand Up @@ -1729,12 +1796,18 @@ void suhosin_hook_execute(TSRMLS_D)
*/
void suhosin_unhook_execute()
{
#if ZO_COMPATIBILITY_HACK_TEMPORARY_DISABLED
if (zo_set_oe_ex) {
zo_set_oe_ex(old_execute_ZO);
}

#endif

#if PHP_VERSION_ID >= 50500
zend_execute_ex = old_execute_ex;
#else
zend_execute = old_execute;

#endif

/* zend_compile_file = old_compile_file; */

if (old_execute_internal == execute_internal) {
Expand Down
19 changes: 16 additions & 3 deletions log.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ PHP_SUHOSIN_API void suhosin_log(int loglevel, char *fmt, ...)
{
int s, r, i=0, fd;
long written, towrite;
int getcaller=0;
char *wbuf;
struct timeval tv;
time_t now;
Expand All @@ -115,6 +116,12 @@ PHP_SUHOSIN_API void suhosin_log(int loglevel, char *fmt, ...)
va_list ap;
TSRMLS_FETCH();

#if PHP_VERSION_ID >= 50500
getcaller = (loglevel & S_GETCALLER) == S_GETCALLER;
#endif
/* remove the S_GETCALLER flag */
loglevel = loglevel & ~S_GETCALLER;

SDEBUG("(suhosin_log) loglevel: %d log_syslog: %u - log_sapi: %u - log_script: %u", loglevel, SUHOSIN_G(log_syslog), SUHOSIN_G(log_sapi), SUHOSIN_G(log_script));

/* dump core if wanted */
Expand Down Expand Up @@ -151,9 +158,15 @@ PHP_SUHOSIN_API void suhosin_log(int loglevel, char *fmt, ...)
}

if (zend_is_executing(TSRMLS_C)) {
if (EG(current_execute_data)) {
lineno = EG(current_execute_data)->opline->lineno;
fname = EG(current_execute_data)->op_array->filename;
zend_execute_data *exdata = EG(current_execute_data);
if (exdata) {
if (getcaller && exdata->prev_execute_data) {
lineno = exdata->prev_execute_data->opline->lineno;
fname = exdata->prev_execute_data->op_array->filename;
} else {
lineno = exdata->opline->lineno;
fname = exdata->op_array->filename;
}
} else {
lineno = zend_get_executed_lineno(TSRMLS_C);
fname = zend_get_executed_filename(TSRMLS_C);
Expand Down
1 change: 1 addition & 0 deletions php_suhosin.h
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,7 @@ ZEND_END_MODULE_GLOBALS(suhosin)
#define S_MAIL (1<<7L)
#define S_SESSION (1<<8L)
#define S_INTERNAL (1<<29L)
#define S_GETCALLER (1<<30L)
#define S_ALL (S_MEMORY | S_VARS | S_INCLUDE | S_FILES | S_MAIL | S_SESSION | S_MISC | S_SQL | S_EXECUTOR)
#endif

Expand Down

0 comments on commit 3142dc0

Please sign in to comment.