diff options
| author | Ben Fuhrmannek | 2021-08-06 20:17:38 +0200 |
|---|---|---|
| committer | Ben Fuhrmannek | 2021-08-06 20:17:38 +0200 |
| commit | 260f17f112e2d081783c6dc102f81666ac2435d9 (patch) | |
| tree | 959d5e83c91b77b52017d809656a8655fd017fa4 | |
| parent | 2b6086486be69533d0077585c7726b3efa175fe6 (diff) | |
restructured function hooks, implemented unhook
| -rw-r--r-- | src/sp_utils.c | 71 | ||||
| -rw-r--r-- | src/sp_utils.h | 1 |
2 files changed, 43 insertions, 29 deletions
diff --git a/src/sp_utils.c b/src/sp_utils.c index 5483618..af78d20 100644 --- a/src/sp_utils.c +++ b/src/sp_utils.c | |||
| @@ -391,41 +391,43 @@ bool sp_match_array_value(const zval* arr, const zend_string* to_match, | |||
| 391 | return false; | 391 | return false; |
| 392 | } | 392 | } |
| 393 | 393 | ||
| 394 | bool /* success */ _hook_function(const char* original_name, HashTable* hook_table, | ||
| 395 | zif_handler new_function) { | ||
| 396 | zend_function* func; | ||
| 397 | if ((func = zend_hash_str_find_ptr(CG(function_table), VAR_AND_LEN(original_name)))) { | ||
| 398 | if (func->type != ZEND_INTERNAL_FUNCTION) { | ||
| 399 | return false; | ||
| 400 | } | ||
| 401 | if (zend_hash_str_add_new_ptr((hook_table), VAR_AND_LEN(original_name), | ||
| 402 | func->internal_function.handler) == NULL) { | ||
| 403 | // LCOV_EXCL_START | ||
| 404 | sp_log_err("function_pointer_saving", | ||
| 405 | "Could not save function pointer for %s", original_name); | ||
| 406 | return false; | ||
| 407 | // LCOV_EXCL_STOP | ||
| 408 | } | ||
| 409 | func->internal_function.handler = new_function; | ||
| 410 | return true; | ||
| 411 | } | ||
| 412 | return false; | ||
| 413 | } | ||
| 414 | |||
| 394 | bool hook_function(const char* original_name, HashTable* hook_table, | 415 | bool hook_function(const char* original_name, HashTable* hook_table, |
| 395 | zif_handler new_function) { | 416 | zif_handler new_function) { |
| 396 | zend_internal_function* func; | 417 | zend_function* func; |
| 397 | bool ret = false; | ||
| 398 | 418 | ||
| 399 | /* The `mb` module likes to hook functions, like strlen->mb_strlen, | ||
| 400 | * so we have to hook both of them. */ | ||
| 401 | 419 | ||
| 402 | if ((func = zend_hash_str_find_ptr(CG(function_table), | 420 | bool ret = _hook_function(original_name, hook_table, new_function); |
| 403 | VAR_AND_LEN(original_name)))) { | ||
| 404 | if (func->handler == new_function) { | ||
| 405 | return SUCCESS; // the function is already hooked | ||
| 406 | } else { | ||
| 407 | if (zend_hash_str_add_new_ptr((hook_table), VAR_AND_LEN(original_name), | ||
| 408 | func->handler) == NULL) { | ||
| 409 | // LCOV_EXCL_START | ||
| 410 | sp_log_err("function_pointer_saving", | ||
| 411 | "Could not save function pointer for %s", original_name); | ||
| 412 | return FAILURE; | ||
| 413 | // LCOV_EXCL_STOP | ||
| 414 | } | ||
| 415 | func->handler = new_function; | ||
| 416 | ret = true; | ||
| 417 | } | ||
| 418 | } | ||
| 419 | 421 | ||
| 420 | #if PHP_VERSION_ID < 80000 | 422 | #if PHP_VERSION_ID < 80000 |
| 421 | CG(compiler_options) |= ZEND_COMPILE_NO_BUILTIN_STRLEN; | 423 | CG(compiler_options) |= ZEND_COMPILE_NO_BUILTIN_STRLEN; |
| 422 | #endif | 424 | #endif |
| 423 | 425 | ||
| 424 | if (0 == strncmp(original_name, "mb_", 3) && !CG(multibyte)) { | 426 | /* The `mb` module likes to hook functions, like strlen->mb_strlen, |
| 425 | if (zend_hash_str_find(CG(function_table), | 427 | * so we have to hook both of them. */ |
| 426 | VAR_AND_LEN(original_name + 3))) { | 428 | |
| 427 | return hook_function(original_name + 3, hook_table, new_function); | 429 | if (!CG(multibyte) && 0 == strncmp(original_name, "mb_", 3)) { |
| 428 | } | 430 | _hook_function(original_name + 3, hook_table, new_function); |
| 429 | } else if (CG(multibyte)) { | 431 | } else if (CG(multibyte)) { |
| 430 | // LCOV_EXCL_START | 432 | // LCOV_EXCL_START |
| 431 | char* mb_name = ecalloc(strlen(original_name) + 3 + 1, 1); | 433 | char* mb_name = ecalloc(strlen(original_name) + 3 + 1, 1); |
| @@ -434,9 +436,7 @@ bool hook_function(const char* original_name, HashTable* hook_table, | |||
| 434 | } | 436 | } |
| 435 | memcpy(mb_name, "mb_", sizeof("mb_") - 1); | 437 | memcpy(mb_name, "mb_", sizeof("mb_") - 1); |
| 436 | memcpy(mb_name + 3, VAR_AND_LEN(original_name)); | 438 | memcpy(mb_name + 3, VAR_AND_LEN(original_name)); |
| 437 | if (zend_hash_str_find(CG(function_table), VAR_AND_LEN(mb_name))) { | 439 | _hook_function(mb_name, hook_table, new_function); |
| 438 | return hook_function(mb_name, hook_table, new_function); | ||
| 439 | } | ||
| 440 | efree(mb_name); | 440 | efree(mb_name); |
| 441 | // LCOV_EXCL_STOP | 441 | // LCOV_EXCL_STOP |
| 442 | } | 442 | } |
| @@ -459,6 +459,19 @@ int hook_regexp(const sp_pcre* regexp, HashTable* hook_table, | |||
| 459 | return SUCCESS; | 459 | return SUCCESS; |
| 460 | } | 460 | } |
| 461 | 461 | ||
| 462 | void unhook_functions(HashTable *ht) { | ||
| 463 | zend_string *fname; | ||
| 464 | zif_handler orig_handler; | ||
| 465 | zend_ulong idx; | ||
| 466 | |||
| 467 | ZEND_HASH_REVERSE_FOREACH_KEY_PTR(ht, idx, fname, orig_handler) | ||
| 468 | zend_function *func = zend_hash_find_ptr(CG(function_table), fname); | ||
| 469 | if (func && func->type == ZEND_INTERNAL_FUNCTION && orig_handler) { | ||
| 470 | func->internal_function.handler = orig_handler; | ||
| 471 | } | ||
| 472 | ZEND_HASH_FOREACH_END_DEL(); | ||
| 473 | } | ||
| 474 | |||
| 462 | bool check_is_in_eval_whitelist(const zend_string* const function_name) { | 475 | bool check_is_in_eval_whitelist(const zend_string* const function_name) { |
| 463 | const sp_list_node* it = SNUFFLEUPAGUS_G(config).config_eval->whitelist; | 476 | const sp_list_node* it = SNUFFLEUPAGUS_G(config).config_eval->whitelist; |
| 464 | 477 | ||
diff --git a/src/sp_utils.h b/src/sp_utils.h index 5537a34..ec79e8b 100644 --- a/src/sp_utils.h +++ b/src/sp_utils.h | |||
| @@ -82,6 +82,7 @@ void sp_log_disable(const char *restrict, const char *restrict, | |||
| 82 | void sp_log_disable_ret(const char *restrict, const zend_string *restrict, | 82 | void sp_log_disable_ret(const char *restrict, const zend_string *restrict, |
| 83 | const sp_disabled_function *); | 83 | const sp_disabled_function *); |
| 84 | bool hook_function(const char *, HashTable *, zif_handler); | 84 | bool hook_function(const char *, HashTable *, zif_handler); |
| 85 | void unhook_functions(HashTable *ht); | ||
| 85 | int hook_regexp(const sp_pcre *, HashTable *, zif_handler); | 86 | int hook_regexp(const sp_pcre *, HashTable *, zif_handler); |
| 86 | bool check_is_in_eval_whitelist(const zend_string *const function_name); | 87 | bool check_is_in_eval_whitelist(const zend_string *const function_name); |
| 87 | int sp_log_request(const zend_string *restrict folder, | 88 | int sp_log_request(const zend_string *restrict folder, |
