summaryrefslogtreecommitdiff
path: root/src/sp_execute.c
diff options
context:
space:
mode:
authorBen Fuhrmannek2022-04-19 19:01:52 +0200
committerjvoisin2022-07-12 22:50:28 +0200
commitcd9031935ef2306f7ba2097856b20bf116f341ee (patch)
treebe425fa8af11f41a2679ba9eae9f0a3e969d4da0 /src/sp_execute.c
parent077e96b6319aaf26414d1d0eeb30eb4f144f0019 (diff)
extended checks for readonly_exec, enabled by default
introduced config options: readonly_exec.extended_checks() or xchecks() readonly_exec.no_extended_checks() or noxchecks()
Diffstat (limited to 'src/sp_execute.c')
-rw-r--r--src/sp_execute.c77
1 files changed, 64 insertions, 13 deletions
diff --git a/src/sp_execute.c b/src/sp_execute.c
index cc401aa..56d25c5 100644
--- a/src/sp_execute.c
+++ b/src/sp_execute.c
@@ -1,4 +1,5 @@
1#include "php_snuffleupagus.h" 1#include "php_snuffleupagus.h"
2#include "ext/standard/php_string.h"
2 3
3static void (*orig_execute_ex)(zend_execute_data *execute_data) = NULL; 4static void (*orig_execute_ex)(zend_execute_data *execute_data) = NULL;
4static void (*orig_zend_execute_internal)(zend_execute_data *execute_data, 5static void (*orig_zend_execute_internal)(zend_execute_data *execute_data,
@@ -12,22 +13,72 @@ static zend_result (*orig_zend_stream_open)(zend_file_handle *handle) = NULL;
12// FIXME handle symlink 13// FIXME handle symlink
13ZEND_COLD static inline void terminate_if_writable(const char *filename) { 14ZEND_COLD static inline void terminate_if_writable(const char *filename) {
14 const sp_config_readonly_exec *config_ro_exec = &(SPCFG(readonly_exec)); 15 const sp_config_readonly_exec *config_ro_exec = &(SPCFG(readonly_exec));
16 char *errmsg = "unknown access problem";
17
18 // check write access
15 if (0 == access(filename, W_OK)) { 19 if (0 == access(filename, W_OK)) {
16 if (config_ro_exec->dump) { 20 errmsg = "Attempted execution of a writable file";
17 sp_log_request(config_ro_exec->dump, config_ro_exec->textual_representation); 21 goto violation;
18 } 22 }
19 if (true == config_ro_exec->simulation) { 23 if (errno != EACCES) {
20 sp_log_simulation("readonly_exec", "Attempted execution of a writable file (%s)", filename); 24 goto err;
21 } else { 25 }
22 sp_log_drop("readonly_exec", "Attempted execution of a writable file (%s)", filename); 26
23 } 27 // other checks are 'extended checks' that can be enabled/disabled via config
28 if (!config_ro_exec->extended_checks) {
29 return;
30 }
31
32 // check effective uid
33 struct stat buf;
34 if (0 != stat(filename, &buf)) {
35 goto err;
36 }
37 if (buf.st_uid == geteuid()) {
38 errmsg = "Attempted execution of file owned by process";
39 goto violation;
40 }
41
42 // check write access on directory
43 char *dirname = estrndup(filename, strlen(filename));
44 php_dirname(dirname, strlen(dirname));
45 if (0 == access(dirname, W_OK)) {
46 errmsg = "Attempted execution of file in writable directory";
47 efree(dirname);
48 goto violation;
49 }
50 if (errno != EACCES) {
51 efree(dirname);
52 goto err;
53 }
54
55 // check effecite uid of directory
56 if (0 != stat(dirname, &buf)) {
57 efree(dirname);
58 goto err;
59 }
60 efree(dirname);
61 if (buf.st_uid == geteuid()) {
62 errmsg = "Attempted execution of file in directory owned by process";
63 goto violation;
64 }
65
66 // we would actually need to check all parent directories as well, but that task is left for other tools
67 return;
68
69violation:
70 if (config_ro_exec->dump) {
71 sp_log_request(config_ro_exec->dump, config_ro_exec->textual_representation);
72 }
73 if (config_ro_exec->simulation) {
74 sp_log_simulation("readonly_exec", "%s (%s)", errmsg, filename);
24 } else { 75 } else {
25 if (EACCES != errno) { 76 sp_log_drop("readonly_exec", "%s (%s)", errmsg, filename);
26 // LCOV_EXCL_START
27 sp_log_err("Writable execution", "Error while accessing %s: %s", filename, strerror(errno));
28 // LCOV_EXCL_STOP
29 }
30 } 77 }
78 return;
79
80err:
81 sp_log_err("readonly_exec", "Error while accessing %s: %s", filename, strerror(errno));
31} 82}
32 83
33inline static void is_builtin_matching( 84inline static void is_builtin_matching(