GCC Code Coverage Report


Directory: ../replacer/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 64.9% 1125 / 0 / 1733
Functions: 92.5% 123 / 0 / 133
Branches: 44.2% 600 / 0 / 1357

queue.c
Line Branch Exec Source
1 /*
2 * queue.h
3 *
4 * Created on: Sep 3, 2018
5 * Author: alexey
6 */
7 #define _POSIX_C_SOURCE 200809L
8
9 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__clang__)
10 #define GCC_DIAGNOSTIC_AWARE 1
11 #else
12 #define GCC_DIAGNOSTIC_AWARE 0
13 #endif
14
15 #ifdef __GNUC__
16 #define SUPPRESS_NOT_USED_WARN __attribute__((unused))
17 #else
18 #define SUPPRESS_NOT_USED_WARN
19 #endif
20
21 #include <alloca.h>
22 #include <ctype.h>
23 #include <fcntl.h>
24 #include <libgen.h>
25 #include <linux/limits.h>
26 #include <pthread.h>
27 #include <stdarg.h>
28 #include <stdbool.h>
29 #include <stdint.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/stat.h>
34 #include <sys/time.h>
35 #include <time.h>
36 #include <unistd.h>
37 #include <dlfcn.h>
38 #include <sys/mman.h>
39
40 #include "pcre/pcre.h"
41 #if defined(PA_RULES_VERSION)
42 #include "php_version.h" // PHP_MAJOR_VERSION definition is now available
43 #endif
44
45 #ifdef UNIT_TESTING
46 #define QUEUE_NOINLINE
47 #endif
48
49 #include "../shared-storage/bayrepodump.h"
50 #include "../shared-storage/bayrepomalloc.h"
51 #include "global_data.h"
52 #include "map/map.h"
53 #include "queue.h"
54 #include "queue_buffer.h"
55 #include "reversed_ordered_set/reversed_ordered_set.h"
56 #include "stringfunc.h"
57 #include "counters-saver.h"
58
59 #include "unit_test_common.h"
60
61 #define G_MIN_HANDLE_STRING_SIZE 4
62 #define G_MIN_HANDLE_STRING_SIZE_RCE 1
63 #define G_MAX_PARAM_LENGTH 1024
64
65 #define G_MAX_RESULT_LEN 256
66
67 #define G_NON_LOG_RULE_ID 120000
68
69 #define SIZE_OF_ELEM 1
70 #define OK 0
71 #define PHP_IMUNITY_MIN_ID 80000
72 #define PHP_IMUNITY_MAX_ID 119999
73
74 static map_str_t config_data = map_static_init(0);
75 static params_global_data *parms_data_g_ptr = NULL;
76
77 static char *v2_database_paths[2] = {BIN_F_V2_AGENT, BIN_V2_F};
78 static map_int_t *urls_list = NULL;
79 static reversed_ordered_set_t *files_list = NULL;
80 static map_str_t *funcs = NULL;
81 static map_int_t *func_id = NULL;
82 static map_str_t *func_old_conv = NULL;
83 static map_int_t *writeloggers = NULL;
84 static exclude_rules_list *fp_list_g = NULL;
85 static char *malware_directory_config = NULL;
86 static int malware_directory_config_fd = -1;
87 static reversed_ordered_set_t *exclude_files_list = NULL;
88
89 static params_global_data parms_data_g_ptr_v2 = {NULL,
90 map_static_init(NULL),
91 map_static_init(0),
92 {NULL, 0, 0, NULL},
93 NULL,
94 NULL,
95 map_static_init(NULL),
96 map_static_init(NULL),
97 map_static_init(0),
98 map_static_init(NULL),
99 map_static_init(0),
100 {{NULL, 0, 0, NULL}, NULL, 0},
101 {NULL},
102 0,
103 {NULL, 0, 0, NULL}};
104
105 static params_list server_array = {NULL, NULL, 0, 0};
106 extern char **environ;
107
108 static void *storage = NULL;
109 static void (*storage_free_cb)(void *storage_ptr) = &free;
110 typedef void (*storage_free_cb_ptr)(void *storage_ptr);
111
112 static map_str_t *script_rules_list_map = NULL;
113 static void *script_rules_list_storage = NULL;
114 static void (*script_rules_list_storage_free_cb)(void *storage_ptr) = &free;
115
116 typedef struct __script_rules {
117 rules_list *rules;
118 void *storage;
119 void (*storage_free_cb)(void *storage_ptr);
120 } script_rules_t;
121
122 static map_void_t scripts_rules_map = map_static_init(0);
123
124 #define FAKE_SCRIPT_RULES ((script_rules_t *)(intptr_t)-1)
125
126 static intptr_t current_script_rules_uid = 0;
127 static script_rules_t *current_script_rules = NULL;
128 static intptr_t common_script_rules_uid = 0;
129 static script_rules_t *common_script_rules = NULL;
130 #define I360_PATH_BUFF 4096
131
132 static char current_db_path[I360_PATH_BUFF];
133
134 1 char *i360_get_current_db_path() {
135 1 return current_db_path;
136 }
137
138 #ifndef UNIT_TESTING
139 static
140 #endif
141 58 void i360_load_script_rules() {
142 58 script_rules_list_storage = brp_restore_mmap_dump(LIST_DUMP_F, &script_rules_list_storage_free_cb);
143
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 58 times.
58 if (script_rules_list_storage)
144 script_rules_list_map = (map_str_t *)brp_get_pointer_with_number(script_rules_list_storage, 0);
145
146
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 58 times.
58 if (script_rules_list_map)
147 return;
148
149
1/4
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 11 taken 58 times.
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 11 not taken.
58 if (script_rules_list_storage && script_rules_list_storage_free_cb)
150 script_rules_list_storage_free_cb(script_rules_list_storage);
151
152 58 script_rules_list_storage = brp_restore_dump(LIST_BIN_F, SECURITY_BYTE);
153 58 script_rules_list_storage_free_cb = &free;
154
155
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 15 taken 58 times.
58 if (script_rules_list_storage)
156 script_rules_list_map = (map_str_t *)brp_get_pointer_with_number(script_rules_list_storage, 0);
157
158
1/2
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 17 taken 58 times.
58 if (script_rules_list_map)
159 return;
160
161
1/4
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 20 taken 58 times.
✗ Branch 18 → 19 not taken.
✗ Branch 18 → 20 not taken.
58 if (script_rules_list_storage && script_rules_list_storage_free_cb)
162 script_rules_list_storage_free_cb(script_rules_list_storage);
163 }
164
165 #ifndef UNIT_TESTING
166 static
167 #endif
168 104 void i360_reset_script_rules() {
169 104 map_iter_t iter = map_iter(&scripts_rules_map);
170 const char *key;
171
1/2
✗ Branch 13 → 4 not taken.
✓ Branch 13 → 14 taken 104 times.
104 while ((key = map_next(&scripts_rules_map, &iter))) {
172 script_rules_t *sr = *map_value(&scripts_rules_map, &iter);
173 if (sr == FAKE_SCRIPT_RULES)
174 continue;
175
176 if (sr->storage && sr->storage_free_cb)
177 sr->storage_free_cb(sr->storage);
178
179 free(sr);
180 }
181 104 map_deinit(&scripts_rules_map);
182 104 current_script_rules_uid = 0;
183 104 current_script_rules = NULL;
184 104 common_script_rules_uid = 0;
185 104 common_script_rules = NULL;
186 104 }
187
188 #ifndef UNIT_TESTING
189 static
190 #endif
191 59 void i360_free_script_rules() {
192 59 i360_reset_script_rules();
193
194
1/4
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 6 taken 59 times.
✗ Branch 4 → 5 not taken.
✗ Branch 4 → 6 not taken.
59 if (script_rules_list_storage && script_rules_list_storage_free_cb)
195 script_rules_list_storage_free_cb(script_rules_list_storage);
196
197 59 script_rules_list_storage = NULL;
198 59 script_rules_list_storage_free_cb = NULL;
199 59 script_rules_list_map = NULL;
200 59 }
201
202 #ifndef UNIT_TESTING
203 static
204 #endif
205 40 void *i360_get_script_rules(const char *file_name, intptr_t uid) {
206 40 int common = 0;
207
208
1/4
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 40 times.
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
40 if (!script_rules_list_map || !uid)
209 40 return NULL;
210
211 if (file_name && *file_name == '*' && file_name[1] == 0) {
212 common = 1;
213 if (common_script_rules_uid == uid)
214 return (common_script_rules == FAKE_SCRIPT_RULES) ? NULL : common_script_rules;
215 }
216 else {
217 // Fast path
218 if (current_script_rules_uid && current_script_rules_uid == uid)
219 return (current_script_rules == FAKE_SCRIPT_RULES) ? NULL : current_script_rules;
220 }
221
222 intptr_t *script_rules_uid = common ? &common_script_rules_uid : &current_script_rules_uid;
223 script_rules_t **script_current_rules = common ? &common_script_rules : &current_script_rules;
224
225 *script_rules_uid = uid;
226 script_rules_t **script_rules_ptr = (script_rules_t **)map_get(&scripts_rules_map, file_name);
227 *script_current_rules = script_rules_ptr ? *script_rules_ptr : NULL;
228
229 if (*script_current_rules)
230 return (*script_current_rules == FAKE_SCRIPT_RULES) ? NULL : *script_current_rules;
231
232 char **script_rule_file = (char **)map_get(script_rules_list_map, file_name);
233
234 if (!script_rule_file || !*script_rule_file) {
235 map_set(&scripts_rules_map, file_name, (*script_current_rules = FAKE_SCRIPT_RULES));
236 return NULL;
237 }
238
239 char script_rule_file_buffer[PATH_MAX];
240 script_rules_t script_rules = {NULL, NULL, NULL};
241
242 memset(script_rule_file_buffer, 0, PATH_MAX);
243 size_t buf_left = PATH_MAX;
244 i360_strnadd(script_rule_file_buffer, LIST_CONF_PATH, strlen(LIST_CONF_PATH), PATH_MAX, &buf_left);
245 i360_strnadd(script_rule_file_buffer, *script_rule_file, strlen(*script_rule_file), PATH_MAX, &buf_left);
246 i360_strnadd(script_rule_file_buffer, ".sruledump", strlen(".sruledump"), PATH_MAX, &buf_left);
247 script_rules.storage = brp_restore_mmap_dump(script_rule_file_buffer, &script_rules.storage_free_cb);
248
249 if (script_rules.storage)
250 script_rules.rules = (rules_list *)brp_get_pointer_with_number(script_rules.storage, 0);
251
252 if (script_rules.rules) {
253 script_rules_t *sr = malloc(sizeof(script_rules_t));
254 if (sr) {
255 *sr = script_rules;
256 map_set(&scripts_rules_map, file_name, sr);
257 return (*script_current_rules = sr);
258 }
259 }
260
261 if (script_rules.storage && script_rules.storage_free_cb)
262 script_rules.storage_free_cb(script_rules.storage);
263
264 memset(script_rule_file_buffer, 0, PATH_MAX);
265 buf_left = PATH_MAX;
266 i360_strnadd(script_rule_file_buffer, LIST_CONF_PATH, strlen(LIST_CONF_PATH), PATH_MAX, &buf_left);
267 i360_strnadd(script_rule_file_buffer, *script_rule_file, strlen(*script_rule_file), PATH_MAX, &buf_left);
268 i360_strnadd(script_rule_file_buffer, ".srule", strlen(".srule"), PATH_MAX, &buf_left);
269 script_rules.storage = brp_restore_dump(script_rule_file_buffer, SECURITY_BYTE);
270 script_rules.storage_free_cb = &free;
271
272 if (script_rules.storage)
273 script_rules.rules = (rules_list *)brp_get_pointer_with_number(script_rules.storage, 0);
274
275 if (script_rules.rules) {
276 script_rules_t *sr = malloc(sizeof(script_rules_t));
277 if (sr) {
278 *sr = script_rules;
279 map_set(&scripts_rules_map, file_name, sr);
280 return (*script_current_rules = sr);
281 }
282 }
283
284 if (script_rules.storage)
285 script_rules.storage_free_cb(script_rules.storage);
286
287 map_set(&scripts_rules_map, file_name, (*script_current_rules = FAKE_SCRIPT_RULES));
288 return NULL;
289 }
290
291 #define G_MAX_TEST_RECOGNIZER_SUB_ID 10
292 #ifndef DEEP_PHP_TESTS
293 #define G_TEST_FLAG "/usr/share/i360-php-opts/test_enabled"
294 #else
295 #define G_TEST_FLAG "test_enabled"
296 #endif
297 static int test_env_enabled = 0;
298
299 #define RGX_MAX_DOCROOT_LEN 4096
300
301 struct timespec stat_rgx_time = {0, 0};
302 static pcre *re_stat_rgx = NULL;
303 static char current_doc_root_rgx[RGX_MAX_DOCROOT_LEN + 1] = {0};
304 static int doc_root_len = 0;
305 static int exclude_list_opt = 1;
306
307 1 void i360_set_exclude_list_opt(int value) {
308 1 exclude_list_opt = value;
309 1 }
310
311 static int i360_compare_timespec_queue(struct timespec *t1, struct timespec *t2) {
312 long int v1, v2;
313 v1 = t1->tv_nsec + t1->tv_sec * 1000000000;
314 v2 = t2->tv_nsec + t2->tv_sec * 1000000000;
315 if (v1 > v2)
316 return 1;
317 else if (v1 < v2)
318 return -1;
319 else
320 return 0;
321 }
322
323 1 void i360_load_exclude_list(char *document_root) {
324 struct stat st;
325
1/2
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 4 not taken.
1 if (document_root) {
326 1 strncpy(current_doc_root_rgx, document_root, RGX_MAX_DOCROOT_LEN);
327 }
328 else {
329 strncpy(current_doc_root_rgx, "/", RGX_MAX_DOCROOT_LEN);
330 }
331 1 doc_root_len = strlen(current_doc_root_rgx);
332
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 24 taken 1 time.
1 if (stat(ABS_PATH_RGX, &st) == 0) {
333 if (st.st_size > 0) {
334 if (i360_compare_timespec_queue(&st.st_mtim, &stat_rgx_time) > 0) {
335 stat_rgx_time = st.st_mtim;
336 if (re_stat_rgx) {
337 free(re_stat_rgx);
338 re_stat_rgx = NULL;
339 }
340 re_stat_rgx = calloc(st.st_size, 1);
341 if (re_stat_rgx) {
342 FILE *fp = fopen(ABS_PATH_RGX, "rb");
343 if (fp) {
344 if (!fread(re_stat_rgx, st.st_size, 1, fp)) {
345 free(re_stat_rgx);
346 re_stat_rgx = NULL;
347 }
348 fclose(fp);
349 }
350 else {
351 free(re_stat_rgx);
352 re_stat_rgx = NULL;
353 }
354 }
355 }
356 }
357 }
358 1 }
359
360 1 void i360_free_exclude_list() {
361
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 1 time.
1 if (re_stat_rgx) {
362 free(re_stat_rgx);
363 re_stat_rgx = NULL;
364 }
365 1 }
366
367 3 void i360_set_malware_directory_config(char *path) {
368 3 malware_directory_config = path;
369
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 3 times.
3 if (malware_directory_config_fd >= 0) {
370 close(malware_directory_config_fd);
371 }
372
2/2
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 2 times.
3 if (!path) {
373 1 malware_directory_config_fd = -1;
374 1 return;
375 }
376
1/2
✓ Branch 6 → 7 taken 2 times.
✗ Branch 6 → 9 not taken.
2 if (path[0]) {
377 2 malware_directory_config_fd = open(path, O_DIRECTORY);
378 //#ifndef NDEBUG
379 // if (malware_directory_config_fd < 0) {
380 // perror("malware_dir_path error");
381 // }
382 //#endif
383 }
384 }
385
386 1 void i360_check_test_enabled() {
387 #ifndef UNIT_TESTING
388 test_env_enabled = 0;
389 #else
390 1 test_env_enabled = 1;
391 #endif
392 1 }
393
394 1 int i360_is_test_env_enabled() {
395 1 return test_env_enabled;
396 }
397
398 #define TMPBUFF 15000
399
400 /* When reading whitelist rules information from file, it's going to be
401 ** one-fread operation. File content will be read directly to either
402 ** static_wl_buffer (fsize < WL_STATIC_BUFFER_SIZE) or dynamically
403 ** allocated buffer (fsize >= WL_STATIC_BUFFER_SIZE).
404 **
405 ** NOTE: it makes sense to have WL_STATIC_BUFFER_SIZE equal to
406 *4+sizeof(wl_item)*N
407 */
408 #define WL_STATIC_BUFFER_SIZE (size_t)100000
409
410 const char *const STR_WL_INCOMPATIBLE = "error: incompatible rules whitelist file %lu\n";
411 const char *const STR_WL_CORRUPTED = "warning: rules whitelist file might be corrupted\n";
412
413 static unsigned char static_wl_buffer[WL_STATIC_BUFFER_SIZE];
414 static unsigned char *wl_buffer = static_wl_buffer;
415 static unsigned int wl_buffer_size = WL_STATIC_BUFFER_SIZE;
416
417 /* When php file being processed is changed (cur_php_fname), we also
418 ** update whitelist rules files which are associated (see set_cur_php_fname)
419 */
420 static char cur_php_fname[PATH_MAX] = "";
421 static size_t cur_php_fname_len = 0;
422 static intptr_t cur_php_uid = 0;
423 static char *cur_wl_rules = NULL;
424
425 /* How whitelist rules data is being stored in memory may depend
426 ** on whitelist format version
427 */
428 static unsigned int wl_version = WHITELIST_FILE_VER3;
429
430 /* If in whitelist, there is an item with no file name is
431 ** specified (empty string), all the appropriate rules are in
432 ** power for all the files.
433 */
434 static char *super_wl_rules = NULL;
435
436 4 static inline int i360_isset_cur_php_fname() {
437 4 return cur_php_fname[0];
438 }
439 6 static inline void i360_reset_cur_php_fname() {
440 6 cur_php_fname[0] = (char)0;
441 6 cur_php_fname_len = 0;
442 6 cur_php_uid = 0;
443 6 }
444
445 35 void i360_extract_correct_php_script_name(char *cur_php_fname) {
446 35 char *dot = strchr(cur_php_fname, ':');
447
448
2/2
✓ Branch 2 → 3 taken 10 times.
✓ Branch 2 → 15 taken 25 times.
35 if (dot) {
449 10 *dot = 0;
450 10 int string_len = strlen(cur_php_fname) + 1;
451 10 int i = string_len - 2, j = i;
452 10 char *ptr = cur_php_fname;
453 10 dot = ptr + i;
454
2/2
✓ Branch 14 → 4 taken 62 times.
✓ Branch 14 → 15 taken 2 times.
64 while (i >= 0) {
455
10/10
✓ Branch 4 → 5 taken 53 times.
✓ Branch 4 → 13 taken 9 times.
✓ Branch 5 → 6 taken 44 times.
✓ Branch 5 → 13 taken 9 times.
✓ Branch 6 → 7 taken 30 times.
✓ Branch 6 → 8 taken 14 times.
✓ Branch 7 → 8 taken 8 times.
✓ Branch 7 → 13 taken 22 times.
✓ Branch 8 → 9 taken 8 times.
✓ Branch 8 → 13 taken 14 times.
62 if (!(ptr[i] == '(' || ptr[i] == ')' || (ptr[i] >= '0' && ptr[i] <= '9') || ptr[i] == ' ')) {
456
1/2
✓ Branch 9 → 10 taken 8 times.
✗ Branch 9 → 12 not taken.
8 if ((i + 1) <= j) {
457
1/2
✓ Branch 10 → 11 taken 8 times.
✗ Branch 10 → 12 not taken.
8 if (ptr[i + 1] == '(') {
458 8 ptr[i + 1] = 0;
459 }
460 }
461 8 break;
462 }
463 54 i--;
464 }
465 }
466 35 }
467
468 26 void i360_set_cur_php_fname(char *fname, map_void_t *whitelist_map, int compile) {
469
4/4
✓ Branch 2 → 3 taken 24 times.
✓ Branch 2 → 10 taken 2 times.
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 10 taken 23 times.
26 if (fname && fname[0] == '[') {
470
2/4
✓ Branch 4 → 5 taken 1 time.
✗ Branch 4 → 9 not taken.
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 9 not taken.
1 if (compile && i360_isset_cur_php_fname()) {
471 1 i360_reset_cur_php_fname();
472 1 cur_wl_rules = NULL;
473 }
474 1 return;
475 }
476
477
4/4
✓ Branch 10 → 11 taken 2 times.
✓ Branch 10 → 16 taken 23 times.
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 16 taken 1 time.
25 if (!compile && i360_isset_cur_php_fname()) {
478
2/4
✓ Branch 13 → 14 taken 1 time.
✗ Branch 13 → 16 not taken.
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 1 time.
1 if (fname && !strcmp(cur_php_fname, fname)) {
479 return;
480 }
481 }
482
483
2/2
✓ Branch 16 → 17 taken 23 times.
✓ Branch 16 → 28 taken 2 times.
25 if (fname) {
484 23 cur_php_uid = (intptr_t)fname;
485 /* using strncpy safely to avoid -Wstringop-truncation (GCC 8) */
486 23 memcpy(cur_php_fname, fname, strlen(fname) + 1);
487
488 23 i360_extract_correct_php_script_name(cur_php_fname);
489
490 23 cur_php_fname_len = strnlen(cur_php_fname, PATH_MAX);
491
4/4
✓ Branch 18 → 19 taken 3 times.
✓ Branch 18 → 20 taken 20 times.
✓ Branch 21 → 22 taken 3 times.
✓ Branch 21 → 23 taken 20 times.
23 void **ptr = map_get((whitelist_map ? whitelist_map : &parms_data_g_ptr->whitelist_map), cur_php_fname);
492
2/2
✓ Branch 25 → 26 taken 10 times.
✓ Branch 25 → 27 taken 13 times.
23 if (ptr) {
493 10 cur_wl_rules = *ptr;
494 }
495 else {
496 13 cur_wl_rules = NULL;
497 }
498 }
499 else {
500 2 i360_reset_cur_php_fname();
501 2 cur_wl_rules = NULL;
502 }
503 }
504
505 3 void i360_free_cur_php_fname() {
506 3 i360_reset_cur_php_fname();
507 3 }
508
509 1 char *i360_get_cur_php_fname() {
510 1 return cur_php_fname;
511 }
512
513 192889 static int i360_wl_item_comp(const void *elem1, const void *elem2) {
514 192889 const unsigned int f = *((unsigned int *)elem1);
515 192889 const unsigned int s = *((unsigned int *)elem2);
516
2/2
✓ Branch 2 → 3 taken 179224 times.
✓ Branch 2 → 4 taken 13665 times.
192889 if (f < s)
517 179224 return 1;
518
2/2
✓ Branch 4 → 5 taken 5889 times.
✓ Branch 4 → 6 taken 7776 times.
13665 if (f > s)
519 5889 return -1;
520 7776 return 0;
521 }
522
523 45 void i360_free_queue() {
524 45 i360_reset_script_rules();
525 45 }
526
527 59 void i360_read_internal_config(char *path_to_config) {
528 59 map_init(&config_data);
529 59 FILE *cfg = fopen(path_to_config, "r");
530
1/2
✓ Branch 3 → 4 taken 59 times.
✗ Branch 3 → 30 not taken.
59 if (cfg) {
531 59 char buffer[TMPBUFF * 2] = {0};
532
2/2
✓ Branch 27 → 5 taken 265 times.
✓ Branch 27 → 28 taken 59 times.
324 while (fgets(buffer, sizeof(buffer), cfg) != NULL) {
533 265 char *key = buffer;
534 265 char *value = buffer;
535 265 int max_length = TMPBUFF * 2;
536
6/8
✓ Branch 7 → 8 taken 3080 times.
✓ Branch 7 → 11 taken 261 times.
✓ Branch 8 → 9 taken 3080 times.
✗ Branch 8 → 11 not taken.
✓ Branch 9 → 10 taken 3080 times.
✗ Branch 9 → 11 not taken.
✓ Branch 10 → 6 taken 3076 times.
✓ Branch 10 → 11 taken 4 times.
3341 while (*value != '=' && (max_length > 1) && *value != 0 && *value != '\n') {
537 3076 value++;
538 3076 max_length--;
539 }
540
2/2
✓ Branch 11 → 12 taken 261 times.
✓ Branch 11 → 25 taken 4 times.
265 if (*value == '=') {
541 261 *value = '\0';
542 261 value++;
543
1/2
✓ Branch 12 → 13 taken 261 times.
✗ Branch 12 → 25 not taken.
261 if (max_length > 0) {
544 261 char *trim_key = i360_my_strtrim(key);
545 261 char *trim_value = i360_my_strtrim(value);
546
2/4
✓ Branch 15 → 16 taken 261 times.
✗ Branch 15 → 21 not taken.
✓ Branch 16 → 17 taken 261 times.
✗ Branch 16 → 21 not taken.
261 if (trim_key && trim_value) {
547 261 char *check_exists = (char *)map_get(&config_data, trim_key);
548
2/2
✓ Branch 18 → 19 taken 6 times.
✓ Branch 18 → 20 taken 255 times.
261 if (check_exists) {
549 6 map_remove(&config_data, trim_key);
550 }
551 261 map_set_(&(config_data).base, trim_key, trim_value, strlen(trim_value) + 1);
552 }
553
1/2
✓ Branch 21 → 22 taken 261 times.
✗ Branch 21 → 23 not taken.
261 if (trim_key)
554 261 free(trim_key);
555
1/2
✓ Branch 23 → 24 taken 261 times.
✗ Branch 23 → 25 not taken.
261 if (trim_value)
556 261 free(trim_value);
557 }
558 }
559 265 memset(buffer, 0, TMPBUFF * 2);
560 }
561 59 fclose(cfg);
562 }
563 59 }
564
565 60 void i360_free_internal_config() {
566 60 map_str_t map_null = map_static_init(0);
567
2/2
✓ Branch 2 → 3 taken 59 times.
✓ Branch 2 → 5 taken 1 time.
60 if (memcmp(&config_data, &map_null, sizeof(config_data))) {
568 59 map_deinit(&config_data);
569 59 memset(&config_data, 0, sizeof(config_data));
570 }
571 60 }
572
573 27 char *i360_get_config_key(char *key_name) {
574 27 return (char *)map_get(&config_data, key_name);
575 }
576
577 char *i360_getenv(const char *name, const char *default_value) {
578 if (!name || !*name)
579 return NULL;
580 char *ret = getenv(name);
581 // we expect ret to be alphanumeric or _- and end up with a null byte
582 if (ret && *ret) {
583 int is_valid = 1;
584 const char *p;
585 for (p = ret; *p; p++) {
586 if (!isalnum((unsigned char)*p) && *p != '_' && *p != '-') {
587 is_valid = 0;
588 break;
589 }
590 }
591 if (is_valid) {
592 return i360_inner_strdup(ret);
593 }
594 }
595 if (!default_value || !*default_value) {
596 return NULL;
597 }
598 return i360_inner_strdup((char *)default_value);
599 }
600
601 // params
602
603 10 int i360_add_func_param_value_add(params_list *parms, char *param, char *value, int length,
604 __attribute__((unused)) int add_param) {
605 10 int need_length = (length > G_MAX_PARAM_LENGTH ? G_MAX_PARAM_LENGTH : length);
606 10 params_item *new = calloc(1, sizeof(params_item));
607
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 10 times.
10 if (!new) {
608 parms->err = 1;
609 return -1;
610 }
611
1/2
✓ Branch 5 → 6 taken 10 times.
✗ Branch 5 → 7 not taken.
10 new->param = i360_inner_strndup(param ? param : "", need_length);
612 10 new->param_len = need_length;
613
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 12 taken 10 times.
10 if (!new->param) {
614 free(new);
615 parms->err = 1;
616 return -1;
617 }
618
1/2
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 17 taken 10 times.
10 if (value) {
619 new->value = i360_inner_strdup(value);
620 if (!new->value) {
621 free(new);
622 parms->err = 1;
623 return -1;
624 }
625 }
626
2/2
✓ Branch 17 → 18 taken 3 times.
✓ Branch 17 → 19 taken 7 times.
10 if (parms->head) {
627 3 parms->tail->next = new;
628 3 new->number = parms->tail->number + 1;
629 3 parms->length++;
630 3 parms->tail = new;
631 }
632 else {
633 7 parms->head = new;
634 7 parms->tail = new;
635 7 parms->length = 1;
636 7 new->number = 1;
637 }
638 10 return 0;
639 }
640
641 10 int i360_add_func_param_value(params_list *parms, char *param, __attribute__((unused)) char *value, int length) {
642 10 return i360_add_func_param_value_add(parms, param, NULL, length, 0);
643 }
644
645 9 int i360_add_func_param(params_list *parms, char *param, int length) {
646 9 return i360_add_func_param_value(parms, param, NULL, length);
647 }
648
649 25 void i360_free_func_params(params_list *parms) {
650
2/2
✓ Branch 2 → 3 taken 7 times.
✓ Branch 2 → 11 taken 18 times.
25 if (parms->head) {
651 7 params_item *item = parms->head;
652
2/2
✓ Branch 9 → 4 taken 10 times.
✓ Branch 9 → 10 taken 7 times.
17 while (item) {
653 10 params_item *item_del = item;
654 10 item = item->next;
655
1/2
✓ Branch 4 → 5 taken 10 times.
✗ Branch 4 → 6 not taken.
10 if (item_del->param)
656 10 free(item_del->param);
657
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 10 times.
10 if (item_del->value) {
658 free(item_del->value);
659 }
660 10 free(item_del);
661 }
662 7 parms->head = NULL;
663 7 parms->tail = NULL;
664 7 parms->length = 0;
665 }
666 25 }
667
668 // New params
669
670 static int i360_params_numb = 0;
671
672 #define PROACTIVE_MAX_PARAMS_TO_SAVE 10
673 #define PROACTIVE_MAX_PARAMS_FUNC_NAME PROACTIVE_MAX_PARAMS_TO_SAVE + 1
674 #define PROACTIVE_MAX_PARAMS_PARAM_PRE 8
675 #define PROACTIVE_MAX_PARAMS_FUNC_PRE 10
676
677 static char i360_params_static[PROACTIVE_MAX_PARAMS_FUNC_NAME][G_MAX_PARAM_LENGTH + PROACTIVE_MAX_PARAMS_FUNC_PRE + 1] =
678 {"PHPFP_A=", "PHPFP_B=", "PHPFP_C=", "PHPFP_D=", "PHPFP_E=", "PHPFP_F=",
679 "PHPFP_G=", "PHPFP_H=", "PHPFP_I=", "PHPFP_J=", "PHPFP_NAM="};
680
681 static int i360_params_static_length[PROACTIVE_MAX_PARAMS_FUNC_NAME] = {0};
682
683 47 int i360_add_func_param_value_add_new(const char *param, size_t length) {
684
2/2
✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 4 taken 45 times.
47 if (i360_params_numb == PROACTIVE_MAX_PARAMS_TO_SAVE)
685 2 return -1;
686
2/2
✓ Branch 4 → 5 taken 44 times.
✓ Branch 4 → 6 taken 1 time.
45 size_t need_length = (length > G_MAX_PARAM_LENGTH ? (G_MAX_PARAM_LENGTH - 1) : length);
687 45 char *str_ptr = i360_params_static[i360_params_numb];
688 45 str_ptr += PROACTIVE_MAX_PARAMS_PARAM_PRE;
689 45 strncpy(str_ptr, param, need_length + 1);
690 45 i360_params_static_length[i360_params_numb] = need_length;
691 45 i360_params_numb++;
692 45 return 0;
693 }
694
695 33 int i360_add_func_param_value_new(const char *param, size_t length) {
696 33 return i360_add_func_param_value_add_new(param, length);
697 }
698
699 33 int i360_add_func_param_new(const char *param, size_t length) {
700 33 return i360_add_func_param_value_new(param, length);
701 }
702
703 29 void i360_free_func_params_new() {
704 // When we add a parameter, we don't append it, but rather strncpy it fresh
705 // so we don't need to clean up anything except the current number of parameters
706 // This is one of the hottest functions, so it must make sense to optimize it
707 29 i360_params_numb = 0;
708 29 }
709
710 27 char *i360_get_params_new(int *index, int *len) {
711 27 char *ptr = i360_get_params_index_new(index, len);
712
2/2
✓ Branch 3 → 4 taken 20 times.
✓ Branch 3 → 5 taken 7 times.
27 if (*index != -1) {
713 20 *index = *index + 1;
714 }
715 27 return ptr;
716 }
717
718 42 char *i360_get_params_index_new(int *index, int *len) {
719
2/2
✓ Branch 2 → 3 taken 8 times.
✓ Branch 2 → 4 taken 34 times.
42 if (*index >= i360_params_numb) {
720 8 *index = -1;
721 8 *len = 0;
722 8 return NULL;
723 }
724
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 34 times.
34 if (*index >= PROACTIVE_MAX_PARAMS_TO_SAVE) {
725 *index = -1;
726 *len = 0;
727 return NULL;
728 }
729 34 *len = i360_params_static_length[*index];
730 34 char *ptr = i360_params_static[*index];
731 34 ptr += PROACTIVE_MAX_PARAMS_PARAM_PRE;
732 34 return ptr;
733 }
734
735 36 int i360_get_params_new_numb() {
736 36 return i360_params_numb;
737 }
738
739 2 char *i360_get_params_new_raw(int index) {
740
3/4
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 1 time.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 1 time.
2 if (index >= PROACTIVE_MAX_PARAMS_TO_SAVE || index >= i360_params_numb) {
741 1 return NULL;
742 }
743 1 return i360_params_static[index];
744 }
745
746 18 char *i360_is_function_hooked(const char *name, char *buffer) {
747 18 char *res = (char *)map_get(funcs, name);
748
2/2
✓ Branch 3 → 4 taken 17 times.
✓ Branch 3 → 5 taken 1 time.
18 if (res) {
749 17 buffer[0] = res[0];
750 17 buffer[1] = res[1];
751 17 buffer[2] = res[2];
752 17 return buffer;
753 }
754 1 return NULL;
755 }
756
757 14 int i360_get_params_flags(char *func_info) {
758 14 return (int)(func_info[2] - '0');
759 }
760
761 2 static int i360_fast_bad_syscall_detection_files(__attribute__((unused)) params_list *params, file_value *values) {
762
3/4
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1 time.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 1 time.
2 if (!i360_get_params_new_numb() || !values)
763 1 return 0;
764 1 int index = 0;
765 1 int len = 0;
766 1 char *prm = i360_get_params_new(&index, &len);
767
1/2
✓ Branch 20 → 8 taken 2 times.
✗ Branch 20 → 21 not taken.
2 while (index != -1) {
768
1/2
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 19 not taken.
2 if (len > G_MIN_HANDLE_STRING_SIZE_RCE) {
769 2 file_value *values_dup = values;
770
2/2
✓ Branch 18 → 10 taken 8 times.
✓ Branch 18 → 19 taken 1 time.
9 while (values_dup) {
771
1/2
✓ Branch 10 → 11 taken 8 times.
✗ Branch 10 → 17 not taken.
8 if (values_dup->status > 0) {
772 int pcreExecRet;
773 int subStrVec[30];
774
775 8 pcreExecRet = pcre_exec(values_dup->re, values_dup->reE, prm, len, 0, PCRE_ANCHORED | PCRE_NO_START_OPTIMIZE,
776 subStrVec, 30);
777
778
2/2
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 16 taken 7 times.
8 if (pcreExecRet > 0) {
779
1/2
✗ Branch 13 → 14 not taken.
✓ Branch 13 → 15 taken 1 time.
1 if (values_dup->type == 1) {
780 i360_set_logger_rce();
781 }
782 1 return 1;
783 }
784 }
785 7 values_dup = values_dup->next;
786 }
787 }
788 1 prm = i360_get_params_new(&index, &len);
789 }
790 return 0;
791 }
792
793 #define MAX_DOMAIN_NAME 256
794
795 9 static void i360_extract_domain_name(char *param, char *buffer, int buffer_len) {
796 9 buffer_len = buffer_len - 1;
797 9 int p_len = strlen(param);
798
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 9 times.
9 if (!p_len) {
799 strncpy(buffer, "", buffer_len);
800 return;
801 }
802 9 char *ptr = param;
803
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 9 times.
9 if (p_len < 4) {
804 strncpy(buffer, param, buffer_len);
805 }
806 else {
807 9 ptr = strstr(param, "://");
808
2/2
✓ Branch 6 → 7 taken 6 times.
✓ Branch 6 → 8 taken 3 times.
9 if (!ptr) { //(ptr && param[0] == 'h' && param[1] == 't' && param[2] == 't' && param[3] == 'p')) {
809 6 ptr = param;
810 }
811 else {
812 3 ptr += 3;
813 }
814 9 int www_len = p_len - (ptr - param);
815
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 9 times.
9 if (www_len < 4) {
816 strncpy(buffer, ptr, buffer_len);
817 }
818 else {
819
5/8
✓ Branch 11 → 12 taken 2 times.
✓ Branch 11 → 16 taken 7 times.
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 16 not taken.
✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 16 not taken.
✓ Branch 14 → 15 taken 2 times.
✗ Branch 14 → 16 not taken.
9 if (ptr[0] == 'w' && ptr[1] == 'w' && ptr[2] == 'w' && ptr[3] == '.') {
820 2 ptr += 4;
821 }
822 9 int copy_len = strcspn(ptr, ":/");
823 9 copy_len = copy_len > buffer_len ? buffer_len : copy_len;
824 9 memcpy(buffer, ptr, copy_len);
825 9 buffer[copy_len] = 0;
826 }
827 }
828 9 return;
829 }
830
831 11 static int i360_fast_bad_syscall_detection_by_map_domain(__attribute__((unused)) params_list *params, map_int_t *m) {
832 11 char domain[MAX_DOMAIN_NAME] = {0};
833
3/4
✓ Branch 3 → 4 taken 9 times.
✓ Branch 3 → 5 taken 2 times.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 9 times.
11 if (!i360_get_params_new_numb() || !m)
834 2 return 0;
835 9 int index = 0;
836 9 int len = 0;
837 9 char *prm = i360_get_params_new(&index, &len);
838
2/2
✓ Branch 14 → 8 taken 13 times.
✓ Branch 14 → 15 taken 6 times.
19 while (index != -1) {
839
2/2
✓ Branch 8 → 9 taken 9 times.
✓ Branch 8 → 13 taken 4 times.
13 if (len > G_MIN_HANDLE_STRING_SIZE) {
840 9 i360_extract_domain_name(prm, domain, MAX_DOMAIN_NAME);
841 9 int *val = map_get(m, domain);
842
2/2
✓ Branch 11 → 12 taken 3 times.
✓ Branch 11 → 13 taken 6 times.
9 if (val) {
843 3 return 1;
844 }
845 }
846 10 prm = i360_get_params_new(&index, &len);
847 }
848 6 return 0;
849 }
850
851 static int i360_fast_bad_syscall_detection_by_map_reverse(struct reversed_ordered_set_t *m) {
852 if (!i360_get_params_new_numb() || !m)
853 return 0;
854 int index = 0;
855 int len = 0;
856 char *prm = i360_get_params_new(&index, &len);
857 while (index != -1) {
858 if (len > G_MIN_HANDLE_STRING_SIZE) {
859 int val = i360_rev_ordered_find_partial(m, prm, len);
860 if (val >= 0) {
861 return 1;
862 }
863 }
864 prm = i360_get_params_new(&index, &len);
865 }
866 return 0;
867 }
868
869 13 void i360_param_check(char *func_info, params_list *params, int flags) {
870
1/2
✓ Branch 2 → 3 taken 13 times.
✗ Branch 2 → 11 not taken.
13 if (flags) {
871
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 7 taken 11 times.
13 if (flags & rce_patterns_list_mask) {
872
2/2
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 7 taken 1 time.
2 if (i360_fast_bad_syscall_detection_files(params, parms_data_g_ptr->rce_patterns_list)) {
873 1 func_info[0] = (char)toupper((unsigned char)func_info[0]);
874 1 return;
875 }
876 }
877
2/2
✓ Branch 7 → 8 taken 11 times.
✓ Branch 7 → 11 taken 1 time.
12 if (flags & black_urls_list_mask) {
878
2/2
✓ Branch 9 → 10 taken 3 times.
✓ Branch 9 → 11 taken 8 times.
11 if (i360_fast_bad_syscall_detection_by_map_domain(params, urls_list)) {
879 3 func_info[0] = (char)toupper((unsigned char)func_info[0]);
880 3 return;
881 }
882 }
883 }
884 }
885
886 59 void i360_free_global_copy() {
887
2/2
✓ Branch 2 → 3 taken 58 times.
✓ Branch 2 → 7 taken 1 time.
59 if (parms_data_g_ptr) {
888 58 i360_free_rules_whitelist(&parms_data_g_ptr->whitelist_map);
889 58 map_void_t null_map = map_static_init(0);
890
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 58 times.
58 if (memcmp(&parms_data_g_ptr->whitelist_map, &null_map, sizeof(map_void_t))) {
891 map_deinit(&parms_data_g_ptr->whitelist_map);
892 }
893
894 58 memset(parms_data_g_ptr, 0, sizeof(*parms_data_g_ptr));
895 58 parms_data_g_ptr = NULL;
896 }
897
898
2/2
✓ Branch 7 → 8 taken 53 times.
✓ Branch 7 → 10 taken 6 times.
59 if (storage) {
899 53 storage_free_cb(storage);
900 53 storage = NULL;
901 }
902
903 59 i360_free_script_rules();
904 59 i360_pd_database_deinit();
905 59 }
906
907 6227 static void i360_dump_rules(int dump_fd, int is_empty_rulelist, const char *fname, unsigned int rules[], int len,
908 int dump_zero_ruleid) {
909 #ifndef UNIT_TESTING
910 if (dump_fd < 0)
911 return;
912
913 if (is_empty_rulelist) {
914 dprintf(dump_fd, "\"%s\": []\n", fname);
915 }
916 else {
917 dprintf(dump_fd, "\"%s\":\n", fname);
918
919 size_t rules_ptr = (size_t)rules;
920 if (rules_ptr % sizeof(rules[0]))
921 dprintf(dump_fd, "# rules bad padding warning [%p]\n", rules);
922 else
923 dprintf(dump_fd, "# rules padding ok [%p]\n", rules);
924
925 int i;
926 for (i = 0; i < len; i++)
927 if (rules[i] || dump_zero_ruleid)
928 dprintf(dump_fd, "- %u\n", rules[i]);
929 }
930 #else
931 (void)dump_fd;
932 (void)is_empty_rulelist;
933 (void)fname;
934 (void)rules;
935 (void)len;
936 (void)dump_zero_ruleid;
937 #endif
938 6227 }
939
940 #define WL_FILE_PREFIX_LEN 4
941 #define WHITELIST_SUPER_RULE ""
942
943 7 static void i360_parse_whitelist_data_ver3(unsigned char *buffer, unsigned int buffer_size, map_void_t *map,
944 int dump_fd) {
945 7 unsigned int num_wl_item = (buffer_size - sizeof(unsigned int)) / sizeof(whitelist_file_item);
946
947
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 7 times.
7 if ((buffer_size - sizeof(unsigned int)) % sizeof(whitelist_file_item)) {
948 return;
949 }
950
951 7 whitelist_file_item *wl_item = (whitelist_file_item *)(((unsigned char *)buffer) + sizeof(unsigned int));
952
953
2/2
✓ Branch 19 → 5 taken 212 times.
✓ Branch 19 → 20 taken 7 times.
219 while (num_wl_item--) {
954 // If no rules are listed, we whitelist all of them
955 212 unsigned char is_whitelist_rule = 0, is_empty_rulelist = !0;
956 212 int i = 0;
957
2/2
✓ Branch 9 → 6 taken 6784 times.
✓ Branch 9 → 10 taken 212 times.
6996 for (; i < MAX_WHITELIST_RULES; ++i) {
958
2/2
✓ Branch 6 → 7 taken 2874 times.
✓ Branch 6 → 8 taken 3910 times.
6784 if (wl_item->rules[i]) {
959 2874 is_whitelist_rule = 1;
960 2874 is_empty_rulelist = 0;
961 }
962 }
963
964 212 i360_dump_rules(dump_fd, is_empty_rulelist, wl_item->fname, wl_item->rules, MAX_WHITELIST_RULES,
965 /*dump_zero_ruleid*/ 0);
966
967
4/6
✓ Branch 11 → 12 taken 5 times.
✓ Branch 11 → 15 taken 207 times.
✓ Branch 12 → 13 taken 5 times.
✗ Branch 12 → 15 not taken.
✓ Branch 13 → 14 taken 5 times.
✗ Branch 13 → 15 not taken.
212 if (!strcmp(wl_item->fname, WHITELIST_SUPER_RULE) && !super_wl_rules && is_whitelist_rule) {
968 5 super_wl_rules = (char *)wl_item->rules;
969 5 qsort(super_wl_rules, MAX_WHITELIST_RULES, sizeof(unsigned int), i360_wl_item_comp);
970 }
971 else {
972
1/2
✓ Branch 15 → 16 taken 207 times.
✗ Branch 15 → 17 not taken.
207 if (is_whitelist_rule) {
973 207 qsort(wl_item->rules, MAX_WHITELIST_RULES, sizeof(wl_item->rules[0]), i360_wl_item_comp);
974 }
975
976 207 map_set(map, wl_item->fname, wl_item->rules);
977 }
978
979 212 wl_item = (whitelist_file_item *)(((unsigned char *)wl_item) + sizeof(whitelist_file_item));
980 }
981 }
982
983 9 static void i360_parse_whitelist_data_ver4(unsigned char *buffer, unsigned int buffer_size, map_void_t *map,
984 int dump_fd) {
985 9 unsigned char *buffer_end = buffer + buffer_size, *buf = buffer + sizeof(int), *ptr, *wl_fname;
986 unsigned int fname_len, rules_num;
987 unsigned int *rules;
988 unsigned char is_whitelist_rule;
989
990 6006 while (1) {
991 6015 ptr = buf;
992
993 6015 buf += sizeof(unsigned short int);
994
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 6015 times.
6015 if (buf >= buffer_end)
995 goto fmt_broken;
996
997 6015 fname_len = *(unsigned short int *)ptr;
998 6015 ptr = buf;
999
1000 6015 buf += fname_len;
1001
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 6015 times.
6015 if (buf >= buffer_end)
1002 goto fmt_broken;
1003
1004 6015 wl_fname = ptr;
1005 6015 ptr = buf;
1006
1007 6015 buf += sizeof(unsigned char);
1008
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 9 taken 6015 times.
6015 if (buf >= buffer_end)
1009 goto fmt_broken;
1010
1011 6015 rules_num = *(unsigned char *)ptr;
1012 6015 rules = (unsigned int *)buf;
1013 6015 buf += sizeof(int) * rules_num;
1014
1015
1/2
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 6015 times.
6015 if (buf > buffer_end)
1016 goto fmt_broken;
1017
1018 6015 is_whitelist_rule = 0;
1019 6015 unsigned int i = 0;
1020
2/2
✓ Branch 15 → 12 taken 84039 times.
✓ Branch 15 → 16 taken 6015 times.
90054 for (; i < rules_num; ++i) {
1021
1/2
✓ Branch 12 → 13 taken 84039 times.
✗ Branch 12 → 14 not taken.
84039 if (rules[i])
1022 84039 is_whitelist_rule = 1;
1023 }
1024
1025 6015 i360_dump_rules(dump_fd, /*is_empty_rulelist*/ (rules_num == 0), (const char *)wl_fname, rules, rules_num,
1026 /*dump_zero_ruleid*/ !0);
1027
1028
5/6
✓ Branch 17 → 18 taken 6 times.
✓ Branch 17 → 21 taken 6009 times.
✓ Branch 18 → 19 taken 5 times.
✓ Branch 18 → 21 taken 1 time.
✓ Branch 19 → 20 taken 5 times.
✗ Branch 19 → 21 not taken.
6015 if (!strcmp((const char *)wl_fname, WHITELIST_SUPER_RULE) && !super_wl_rules && is_whitelist_rule) {
1029 5 super_wl_rules = (char *)ptr;
1030 5 qsort(rules, rules_num, sizeof(unsigned int), i360_wl_item_comp);
1031 }
1032 else {
1033
1/2
✓ Branch 21 → 22 taken 6010 times.
✗ Branch 21 → 23 not taken.
6010 if (is_whitelist_rule) {
1034 6010 qsort(rules, rules_num, sizeof(unsigned int), i360_wl_item_comp);
1035 }
1036
1037 6010 map_set(map, (const char *)wl_fname, ptr);
1038 }
1039
1040
2/2
✓ Branch 24 → 25 taken 9 times.
✓ Branch 24 → 26 taken 6006 times.
6015 if (buf == buffer_end)
1041 9 break;
1042 }
1043 9 return;
1044
1045 fmt_broken:
1046 return;
1047 }
1048
1049 76 void i360_read_whitelist_from_file(map_void_t *map, char *filename) {
1050 76 i360_read_whitelist_from_file2(map, filename, /*dump_fd*/ -1);
1051 76 }
1052
1053 76 void i360_read_whitelist_from_file2(map_void_t *map, char *filename, int dump_fd) {
1054 76 FILE *file = fopen(filename, "rb");
1055
2/2
✓ Branch 3 → 4 taken 16 times.
✓ Branch 3 → 27 taken 60 times.
76 if (file) {
1056
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 16 times.
16 if (!(dump_fd < 0))
1057 dprintf(dump_fd, "---\n");
1058 struct stat statbuf;
1059
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 10 taken 16 times.
16 if (stat(filename, &statbuf) == -1) {
1060 fclose(file);
1061 return;
1062 }
1063
1064 // wl_buffer is assumed to be NULL
1065
2/2
✓ Branch 10 → 11 taken 8 times.
✓ Branch 10 → 15 taken 8 times.
16 if (statbuf.st_size >= wl_buffer_size) {
1066
2/2
✓ Branch 11 → 12 taken 1 time.
✓ Branch 11 → 13 taken 7 times.
8 if (wl_buffer != static_wl_buffer)
1067 1 free(wl_buffer);
1068
1069 8 wl_buffer = malloc(statbuf.st_size);
1070 8 wl_buffer_size = statbuf.st_size;
1071 }
1072
1073 // WL_STATIC_BUFFER_SIZE
1074
1/2
✓ Branch 16 → 17 taken 16 times.
✗ Branch 16 → 23 not taken.
16 if (fread(wl_buffer, 1, statbuf.st_size, file)) {
1075 16 wl_version = *(unsigned int *)wl_buffer;
1076
1/2
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 16 times.
16 if (!(dump_fd < 0))
1077 dprintf(dump_fd, "# API_VER: %u\n", wl_version);
1078
2/2
✓ Branch 19 → 20 taken 7 times.
✓ Branch 19 → 21 taken 9 times.
16 if (wl_version == WHITELIST_FILE_VER3) {
1079 7 i360_parse_whitelist_data_ver3(wl_buffer, statbuf.st_size, map, dump_fd);
1080 }
1081
1/2
✓ Branch 21 → 22 taken 9 times.
✗ Branch 21 → 23 not taken.
9 else if (wl_version == WHITELIST_FILE_VER4) {
1082 9 i360_parse_whitelist_data_ver4(wl_buffer, statbuf.st_size, map, dump_fd);
1083 }
1084 }
1085
1086
1/2
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 16 times.
16 if (!(dump_fd < 0))
1087 dprintf(dump_fd, "...\n");
1088 16 fclose(file);
1089 }
1090 }
1091
1092 78 void i360_free_rules_whitelist(map_void_t *map) {
1093 78 map_void_t null_map = map_static_init(0);
1094
5/6
✓ Branch 2 → 3 taken 77 times.
✓ Branch 2 → 5 taken 1 time.
✓ Branch 3 → 4 taken 77 times.
✗ Branch 3 → 6 not taken.
✓ Branch 4 → 5 taken 62 times.
✓ Branch 4 → 6 taken 15 times.
78 if (!map || (map && !memcmp(map, &null_map, sizeof(map_void_t)))) {
1095 63 return;
1096 }
1097 15 char *key = NULL;
1098 15 map_iter_t iter = map_iter(map);
1099
1100
2/2
✓ Branch 11 → 8 taken 4216 times.
✓ Branch 11 → 12 taken 15 times.
4231 while ((key = (char *)map_next(map, &iter))) {
1101 4216 map_remove(map, key);
1102 4216 iter = map_iter(map);
1103 }
1104
1105 15 map_deinit(map);
1106
1107 15 super_wl_rules = NULL;
1108 15 memset(map, 0, sizeof(*map));
1109 }
1110
1111 18 void i360_free_wl_buffer() {
1112
3/4
✓ Branch 2 → 3 taken 7 times.
✓ Branch 2 → 6 taken 11 times.
✓ Branch 3 → 4 taken 7 times.
✗ Branch 3 → 6 not taken.
18 if (static_wl_buffer != wl_buffer && wl_buffer) {
1113 7 free(wl_buffer);
1114 7 wl_buffer = static_wl_buffer;
1115 7 wl_buffer_size = WL_STATIC_BUFFER_SIZE;
1116 }
1117 18 }
1118
1119 #define GET_DATA_FROM_STORAGE(x) \
1120 x = &parms_data_g_ptr->x; \
1121 if (!x) { \
1122 i360_free_global_copy(); \
1123 return 1; \
1124 }
1125
1126 #define GET_DATA_FROM_STORAGE_TYPE(x, y) \
1127 x = (y)&parms_data_g_ptr->x; \
1128 if (!x) { \
1129 i360_free_global_copy(); \
1130 return 1; \
1131 }
1132
1133 53 static int i360_restore_dump(const char *fname, __attribute__((unused)) char sipher) {
1134 #ifndef UNIT_TESTING
1135 struct flock lock;
1136 memset(&lock, 0, sizeof(struct flock));
1137
1138 int fd = open(LOCK_F, O_RDONLY);
1139 if (fd == -1) {
1140 return 1;
1141 }
1142
1143 lock.l_type = F_RDLCK;
1144
1145 if (fcntl(fd, F_SETLKW, &lock) == -1) {
1146 close(fd);
1147 return 4;
1148 }
1149 #endif
1150
1151 53 storage = brp_restore_dump(fname, SECURITY_BYTE);
1152 53 storage_free_cb = &free;
1153
1154 #ifndef UNIT_TESTING
1155 fcntl(fd, F_UNLCK, &lock);
1156 close(fd);
1157 #endif
1158
1159 /* success */
1160 53 return 0;
1161 }
1162
1163 // Transformate in two items array only
1164 static const char *i360_restore_from_options(__attribute__((unused)) void (**free_cb)(void *ptr)) {
1165 char *result = NULL;
1166 struct {
1167 const char *bin_f, *dump_f;
1168 } options[] = {{BIN_F_AGENT, DUMP_F_AGENT}, {BIN_F, DUMP_F}},
1169 *next = &options[1]; // by default set /usr/share/i360-php-opt/.rules
1170 // Check for .rules time modification
1171 struct stat rules_vers_st, rules_pack_st;
1172 int rules_ver_rc = stat(options[0].bin_f, &rules_vers_st);
1173 int rules_pack_rc = stat(options[1].bin_f, &rules_pack_st);
1174 if ((rules_pack_rc == -1) && (rules_ver_rc == -1)) { // no files at all
1175 return result;
1176 }
1177 else if ((!rules_ver_rc) && (rules_pack_rc == -1)) { // no global rule only agent
1178 next = &options[0];
1179 }
1180 else if ((!rules_ver_rc) && (rules_vers_st.st_mtime >= rules_pack_st.st_mtime)) { // global present by agents more new
1181 // or equal
1182 next = &options[0];
1183 } // by default use global. erlier set
1184
1185 /* using strncpy safely to avoid -Wstringop-truncation (GCC 8) */
1186 size_t bin_f_len = strlen(next->bin_f);
1187 memcpy(current_db_path, next->bin_f, bin_f_len + 1);
1188
1189 struct stat dump_st, bin_st;
1190 int dump_rc = stat(next->dump_f, &dump_st);
1191 int bin_rc = stat(next->bin_f, &bin_st);
1192 if (dump_rc == OK && bin_rc == OK && dump_st.st_mtime >= bin_st.st_mtime) {
1193 result = brp_restore_mmap_dump(next->dump_f, &storage_free_cb);
1194 if (result)
1195 return result;
1196 }
1197 if (bin_rc == OK) {
1198 int rc = i360_restore_dump(next->bin_f, SECURITY_BYTE);
1199 if (rc == OK) {
1200 result = storage;
1201 storage_free_cb = &free;
1202 }
1203 }
1204
1205 return result;
1206 }
1207
1208 58 int i360_make_global_copy(i360_make_global_copy_params *params) {
1209 58 int index = 0;
1210 58 i360_set_database_version(SET_OLD_DBTYPE);
1211
1212
3/4
✓ Branch 3 → 4 taken 53 times.
✓ Branch 3 → 9 taken 5 times.
✓ Branch 4 → 5 taken 53 times.
✗ Branch 4 → 9 not taken.
58 if (params && params->rules_file) {
1213 53 int rc = i360_restore_dump(params->rules_file, SECURITY_BYTE);
1214
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 53 times.
53 if (rc)
1215 return rc;
1216 //#ifdef UNIT_TESTING
1217 //#pragma GCC diagnostic push
1218 //#pragma GCC diagnostic ignored "-Wextra"
1219 /* https://debarshiray.wordpress.com/2019/04/01/about-wextra-and-wcast-function-type */
1220 // storage_free_cb = (storage_free_cb_ptr)&_test_free_internal;
1221 //#pragma GCC diagnostic pop
1222 //#else
1223 // storage_free_cb = &free;
1224 //#endif
1225 53 storage_free_cb = &free;
1226 }
1227
1/2
✓ Branch 10 → 11 taken 5 times.
✗ Branch 10 → 20 not taken.
5 else if (i360_pd_database_init()) {
1228 5 i360_set_database_version(SET_HYPERSCAN_DBTYPE);
1229 5 parms_data_g_ptr = &parms_data_g_ptr_v2;
1230 5 funcs = NULL;
1231 5 func_id = NULL;
1232 5 func_old_conv = NULL;
1233 5 writeloggers = NULL;
1234 5 exclude_files_list = NULL;
1235
1236 5 map_init(&parms_data_g_ptr->whitelist_map);
1237
1/6
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 17 taken 5 times.
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 17 not taken.
✗ Branch 14 → 15 not taken.
✗ Branch 14 → 17 not taken.
5 if (params && params->application_id && strncmp(params->application_id, "-1", 2) != 0) {
1238 char whitelist_path[PATH_MAX];
1239 snprintf(whitelist_path, PATH_MAX, "%s%s_rules_whitelist", WHITELIST_APP_PATH, params->application_id);
1240 i360_read_whitelist_from_file(&parms_data_g_ptr->whitelist_map, whitelist_path);
1241 } else {
1242 5 i360_read_whitelist_from_file(&parms_data_g_ptr->whitelist_map, WHITELIST_FILE);
1243 }
1244
1245 5 i360_load_script_rules();
1246 5 return 0;
1247 }
1248 else {
1249 storage = (void *)i360_restore_from_options(&storage_free_cb);
1250 }
1251
1252
1/2
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 25 taken 53 times.
53 if (!storage) {
1253 i360_free_global_copy();
1254 return 2;
1255 }
1256
1257 53 parms_data_g_ptr = brp_get_pointer_with_number(storage, 0);
1258
1/2
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 29 taken 53 times.
53 if (!parms_data_g_ptr) {
1259 i360_free_global_copy();
1260 return 3;
1261 }
1262
1263
1/2
✗ Branch 29 → 30 not taken.
✓ Branch 29 → 32 taken 53 times.
53 GET_DATA_FROM_STORAGE(urls_list);
1264
1/2
✗ Branch 32 → 33 not taken.
✓ Branch 32 → 35 taken 53 times.
53 GET_DATA_FROM_STORAGE(files_list);
1265
1/2
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 38 taken 53 times.
53 GET_DATA_FROM_STORAGE(funcs);
1266
1/2
✗ Branch 38 → 39 not taken.
✓ Branch 38 → 41 taken 53 times.
53 GET_DATA_FROM_STORAGE(func_id);
1267
1/2
✗ Branch 41 → 42 not taken.
✓ Branch 41 → 44 taken 53 times.
53 GET_DATA_FROM_STORAGE(func_old_conv);
1268
1/2
✗ Branch 44 → 45 not taken.
✓ Branch 44 → 47 taken 53 times.
53 GET_DATA_FROM_STORAGE(writeloggers);
1269
1/2
✗ Branch 47 → 48 not taken.
✓ Branch 47 → 50 taken 53 times.
53 GET_DATA_FROM_STORAGE(exclude_files_list);
1270
1271 53 map_init(&parms_data_g_ptr->whitelist_map);
1272
5/6
✓ Branch 50 → 51 taken 53 times.
✗ Branch 50 → 55 not taken.
✓ Branch 51 → 52 taken 2 times.
✓ Branch 51 → 55 taken 51 times.
✓ Branch 52 → 53 taken 1 time.
✓ Branch 52 → 55 taken 1 time.
54 if (params && params->application_id && strncmp(params->application_id, "-1", 2) != 0) {
1273 char whitelist_path[PATH_MAX];
1274 1 snprintf(whitelist_path, PATH_MAX, "%s%s_rules_whitelist", WHITELIST_APP_PATH, params->application_id);
1275 1 i360_read_whitelist_from_file(&parms_data_g_ptr->whitelist_map, whitelist_path);
1276 } else {
1277 52 i360_read_whitelist_from_file(&parms_data_g_ptr->whitelist_map, WHITELIST_FILE);
1278 }
1279
1280 53 fp_list_g = &parms_data_g_ptr->fp_list;
1281
1282 53 file_value *ptr = parms_data_g_ptr->rce_patterns_list;
1283
2/2
✓ Branch 60 → 57 taken 356 times.
✓ Branch 60 → 61 taken 53 times.
409 while (ptr) {
1284
1/2
✓ Branch 57 → 58 taken 356 times.
✗ Branch 57 → 59 not taken.
356 if (ptr->status > 0)
1285 356 pcre_pattern_to_host_byte_order(ptr->re, ptr->reE, NULL);
1286 356 ptr = ptr->next;
1287 }
1288
1289 53 rules_list *rules = parms_data_g_ptr->detector;
1290
2/2
✓ Branch 83 → 62 taken 268 times.
✓ Branch 83 → 84 taken 53 times.
321 while (rules) {
1291
1/2
✓ Branch 62 → 63 taken 268 times.
✗ Branch 62 → 64 not taken.
268 if (rules->status > 0)
1292 268 pcre_pattern_to_host_byte_order(rules->re, rules->reE, NULL);
1293
1294
3/4
✓ Branch 64 → 65 taken 15 times.
✓ Branch 64 → 67 taken 253 times.
✓ Branch 65 → 66 taken 15 times.
✗ Branch 65 → 67 not taken.
268 if ((rules->precheck.param == 2) && (rules->precheck.status > 0)) {
1295 15 pcre_pattern_to_host_byte_order(rules->precheck.re, rules->precheck.reE, NULL);
1296 }
1297
1/4
✗ Branch 67 → 68 not taken.
✓ Branch 67 → 70 taken 268 times.
✗ Branch 68 → 69 not taken.
✗ Branch 68 → 70 not taken.
268 if ((rules->fop_pfirst_chk.param == 2) && (rules->fop_pfirst_chk.status > 0)) {
1298 pcre_pattern_to_host_byte_order(rules->fop_pfirst_chk.re, rules->fop_pfirst_chk.reE, NULL);
1299 }
1300
1/4
✗ Branch 70 → 71 not taken.
✓ Branch 70 → 73 taken 268 times.
✗ Branch 71 → 72 not taken.
✗ Branch 71 → 73 not taken.
268 if ((rules->fop_psecond_chk.param == 2) && (rules->fop_psecond_chk.status > 0)) {
1301 pcre_pattern_to_host_byte_order(rules->fop_psecond_chk.re, rules->fop_psecond_chk.reE, NULL);
1302 }
1303
1304
1/2
✗ Branch 73 → 74 not taken.
✓ Branch 73 → 82 taken 268 times.
268 if (rules->private_fp_list.count) {
1305 int rule_index = 0;
1306 for (rule_index = 0; rule_index < rules->private_fp_list.count; rule_index++) {
1307 rules_list *item = rules->private_fp_list.rules[rule_index];
1308 while (item) {
1309 if (item->status > 0) {
1310 pcre_pattern_to_host_byte_order(item->re, item->reE, NULL);
1311 }
1312 item = item->next;
1313 }
1314 }
1315 }
1316 268 rules = rules->next;
1317 }
1318
1319 53 index = 0;
1320
2/2
✓ Branch 92 → 85 taken 535 times.
✓ Branch 92 → 93 taken 53 times.
588 for (index = 0; index < fp_list_g->count; index++) {
1321
2/2
✓ Branch 85 → 86 taken 470 times.
✓ Branch 85 → 91 taken 65 times.
535 if (fp_list_g->rules[index]) {
1322 470 rules_list *rl = fp_list_g->rules[index];
1323
2/2
✓ Branch 90 → 87 taken 535 times.
✓ Branch 90 → 91 taken 470 times.
1005 while (rl) {
1324
1/2
✓ Branch 87 → 88 taken 535 times.
✗ Branch 87 → 89 not taken.
535 if (rl->status > 0)
1325 535 pcre_pattern_to_host_byte_order(rl->re, rl->reE, NULL);
1326 535 rl = rl->next;
1327 }
1328 }
1329 }
1330
1331 53 i360_load_script_rules();
1332 53 return 0;
1333 }
1334
1335 9 static int i360_check_fp_inner(const char *queue, size_t queue_len, int check_empty, exclude_rules_list *find_list) {
1336
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 9 times.
9 if (find_list == NULL)
1337 return 0;
1338
1339 9 int val = i360_rev_ordered_find_partial(&find_list->files_list, cur_php_fname, strlen(cur_php_fname));
1340
4/6
✓ Branch 5 → 6 taken 1 time.
✓ Branch 5 → 24 taken 8 times.
✓ Branch 6 → 7 taken 1 time.
✗ Branch 6 → 24 not taken.
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 24 not taken.
9 if (val >= 0 && find_list->rules && find_list->rules[val]) {
1341 1 rules_list *rl = find_list->rules[val];
1342
1/2
✓ Branch 22 → 9 taken 1 time.
✗ Branch 22 → 23 not taken.
1 while (rl) {
1343 // Only for rinit rules checker
1344 // no execution flow, that fp_rules should be marked as A in execution flow
1345 // A (big leter A) never faces in normal execution flow
1346
3/6
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 16 not taken.
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 16 not taken.
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 16 taken 1 time.
1 if (rl->status > 0 && rl->raw_regexp && rl->raw_regexp[0] != 'A') {
1347 int pcreExecRet;
1348 int subStrVec[30];
1349
1350 pcreExecRet =
1351 pcre_exec(rl->re, rl->reE, queue, (int)queue_len, 0, PCRE_ANCHORED | PCRE_NO_START_OPTIMIZE, subStrVec, 30);
1352
1353 if (pcreExecRet > 0) {
1354 return 1;
1355 }
1356 }
1357 else {
1358
4/8
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 21 not taken.
✓ Branch 17 → 18 taken 1 time.
✗ Branch 17 → 21 not taken.
✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 21 not taken.
✓ Branch 19 → 20 taken 1 time.
✗ Branch 19 → 21 not taken.
1 if (rl->raw_regexp && rl->raw_regexp[0] == 'A' && queue && !queue[0]) {
1359 // rule for i360_check_chain_rinit is in fp_list we shoukd to skip it
1360 1 return 1;
1361 }
1362 }
1363 rl = rl->next;
1364 }
1365 }
1366 else {
1367
1/2
✗ Branch 24 → 25 not taken.
✓ Branch 24 → 37 taken 8 times.
8 if (check_empty) {
1368 val = i360_rev_ordered_find_partial(&find_list->files_list, "***", 3);
1369 if (val >= 0) {
1370 rules_list *rl = find_list->rules[val];
1371 while (rl) {
1372 if (rl->status > 0 && rl->raw_regexp && rl->raw_regexp[0] != 'A') {
1373 int pcreExecRet;
1374 int subStrVec[30];
1375
1376 pcreExecRet = pcre_exec(rl->re, rl->reE, queue, (int)queue_len, 0, PCRE_ANCHORED | PCRE_NO_START_OPTIMIZE,
1377 subStrVec, 30);
1378
1379 if (pcreExecRet > 0) {
1380 return 1;
1381 }
1382 }
1383 rl = rl->next;
1384 }
1385 }
1386 }
1387 }
1388 8 return 0;
1389 }
1390
1391 9 int i360_check_fp(const char *queue, size_t queue_len, int check_empty) {
1392 9 return i360_check_fp_inner(queue, queue_len, check_empty, fp_list_g);
1393 }
1394
1395 8 static int i360_precheck_params_ext(rules_list *rule) {
1396
1/2
✓ Branch 2 → 3 taken 8 times.
✗ Branch 2 → 4 not taken.
8 if (!rule->check_ext)
1397 8 return 1;
1398 if ((rule->check_ext_len <= 0))
1399 return 1;
1400
1401 if (i360_get_params_new_numb()) {
1402 int index = 0;
1403 int len = 0;
1404 char *prm = i360_get_params_new(&index, &len);
1405 while (index != -1) {
1406 if (((size_t)len >= rule->check_ext_len) &&
1407 (!strncmp(prm + len - rule->check_ext_len, rule->check_ext, rule->check_ext_len))) {
1408 return 1;
1409 }
1410 prm = i360_get_params_new(&index, &len);
1411 }
1412 }
1413 return 0;
1414 }
1415
1416 10 static int i360_precheck_script_ext(rules_list *rule) {
1417
2/2
✓ Branch 2 → 3 taken 8 times.
✓ Branch 2 → 4 taken 2 times.
10 if (!rule->script_ext_param)
1418 8 return 1;
1419
2/4
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 6 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 2 times.
2 if ((rule->script_ext_param > 2 || rule->script_ext_param < 0))
1420 return 1;
1421 2 char *ptr = cur_php_fname;
1422
1423
1/2
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 17 taken 2 times.
2 if (rule->script_ext_param == 1) {
1424 if (!i360_isset_cur_php_fname() || rule->script_ext_len < 1 || !rule->script_ext) {
1425 return 0;
1426 }
1427
1428 char *ptr = cur_php_fname;
1429
1430 if ((cur_php_fname_len >= rule->script_ext_len) &&
1431 (!strncmp(ptr + cur_php_fname_len - rule->script_ext_len, rule->script_ext, rule->script_ext_len))) {
1432 return 1;
1433 }
1434
1435 return 0;
1436 }
1437 else {
1438
1/2
✓ Branch 17 → 18 taken 2 times.
✗ Branch 17 → 22 not taken.
2 if (rule->script_ext_status > 0) {
1439 int pcreExecRet;
1440 int subStrVec[30];
1441
1442 2 pcreExecRet = pcre_exec(rule->script_ext_re,
1443 NULL, // rule->script_ext_reE,
1444 2 ptr, strlen(ptr), 0, PCRE_NO_START_OPTIMIZE, subStrVec, 30);
1445
1446
1/2
✓ Branch 19 → 20 taken 2 times.
✗ Branch 19 → 21 not taken.
2 if (pcreExecRet > 0) {
1447 2 return 1;
1448 }
1449 }
1450 }
1451 return 0;
1452 }
1453
1454 8 static int i360_check_mail_heuristic(const char *func_name) {
1455 8 char max_param_len[G_MAX_ALT_NAME_LEN] = {0};
1456 8 int index = 0;
1457 8 int len = 0;
1458 8 char *prm = NULL;
1459
2/2
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 7 times.
8 if (!strncmp(func_name, "mail", G_MAX_ALT_NAME_LEN)) {
1460 1 return 1;
1461 }
1462
2/2
✓ Branch 4 → 5 taken 5 times.
✓ Branch 4 → 6 taken 2 times.
7 else if (!strncmp(func_name, "fsockopen", G_MAX_ALT_NAME_LEN) ||
1463
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 16 taken 5 times.
5 !strncmp(func_name, "pfsockopen", G_MAX_ALT_NAME_LEN)) {
1464
2/2
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 15 taken 1 time.
2 if (i360_get_params_new_numb() > 1) {
1465 1 index = 1;
1466 1 len = 0;
1467 1 prm = i360_get_params_index_new(&index, &len);
1468
2/4
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 15 not taken.
✓ Branch 10 → 11 taken 1 time.
✗ Branch 10 → 15 not taken.
1 if (len > 0 && prm) {
1469 1 int port = atoi(prm);
1470
1/6
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 14 taken 1 time.
✗ Branch 12 → 13 not taken.
✗ Branch 12 → 14 not taken.
✗ Branch 13 → 14 not taken.
✗ Branch 13 → 15 not taken.
1 if (port == 25 || port == 587 || port == 465) {
1471 1 return 1;
1472 }
1473 }
1474 }
1475 }
1476
2/2
✓ Branch 16 → 17 taken 2 times.
✓ Branch 16 → 27 taken 3 times.
5 else if (!strncmp(func_name, "stream_socket_client", G_MAX_ALT_NAME_LEN)) {
1477
2/2
✓ Branch 18 → 19 taken 1 time.
✓ Branch 18 → 37 taken 1 time.
2 if (i360_get_params_new_numb()) {
1478 1 index = 0;
1479 1 len = 0;
1480 1 prm = i360_get_params_index_new(&index, &len);
1481
2/4
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 37 not taken.
✓ Branch 21 → 22 taken 1 time.
✗ Branch 21 → 37 not taken.
1 if (prm && len > 0) {
1482 1 memcpy(max_param_len, prm, strnlen(prm, G_MAX_ALT_NAME_LEN - 1));
1483 1 char *str = strchr(max_param_len, ':');
1484
1/2
✓ Branch 22 → 23 taken 1 time.
✗ Branch 22 → 37 not taken.
1 if (str) {
1485 1 str++;
1486 1 int port = atoi(str);
1487
1/6
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 26 taken 1 time.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 26 not taken.
✗ Branch 25 → 26 not taken.
✗ Branch 25 → 37 not taken.
1 if (port == 25 || port == 587 || port == 465) {
1488 1 return 1;
1489 }
1490 }
1491 }
1492 }
1493 }
1494
2/2
✓ Branch 27 → 28 taken 2 times.
✓ Branch 27 → 37 taken 1 time.
3 else if (!strncmp(func_name, "socket_connect", G_MAX_ALT_NAME_LEN)) {
1495
2/2
✓ Branch 29 → 30 taken 1 time.
✓ Branch 29 → 37 taken 1 time.
2 if (i360_get_params_new_numb() > 2) {
1496 1 index = 2;
1497 1 len = 0;
1498 1 prm = i360_get_params_index_new(&index, &len);
1499
2/4
✓ Branch 31 → 32 taken 1 time.
✗ Branch 31 → 37 not taken.
✓ Branch 32 → 33 taken 1 time.
✗ Branch 32 → 37 not taken.
1 if (prm && len > 0) {
1500 1 int port = atoi(prm);
1501
1/6
✗ Branch 33 → 34 not taken.
✓ Branch 33 → 36 taken 1 time.
✗ Branch 34 → 35 not taken.
✗ Branch 34 → 36 not taken.
✗ Branch 35 → 36 not taken.
✗ Branch 35 → 37 not taken.
1 if (port == 25 || port == 587 || port == 465) {
1502 1 return 1;
1503 }
1504 }
1505 }
1506 }
1507 4 return 0;
1508 }
1509
1510 14 static int i360_precheck_param_fop(rules_re_t *rule, int index) {
1511
2/4
✓ Branch 2 → 3 taken 14 times.
✗ Branch 2 → 4 not taken.
✓ Branch 3 → 4 taken 14 times.
✗ Branch 3 → 5 not taken.
14 if ((rule->param > 2 || rule->param <= 0))
1512 14 return 1;
1513 if (i360_get_params_new_numb() < index)
1514 return 0;
1515
1516 int len = 0;
1517 char *prm = i360_get_params_new(&index, &len);
1518 if (index == -1)
1519 return 0;
1520
1521 switch (rule->param) {
1522 case 1:
1523 if (len >= rule->string_len) {
1524 if (!strncmp(prm, rule->string_raw, rule->string_len)) {
1525 return 1;
1526 }
1527 }
1528 break;
1529 case 2:
1530 if (rule->status > 0) {
1531 int pcreExecRet;
1532 int subStrVec[30];
1533 pcreExecRet = pcre_exec(rule->re,
1534 NULL, // rule->reE,
1535 prm, len, 0, PCRE_NO_START_OPTIMIZE, subStrVec, 30);
1536 if (pcreExecRet > 0) {
1537 return 1;
1538 }
1539 }
1540 break;
1541 default:
1542 abort();
1543 }
1544 return 0;
1545 }
1546
1547 8 static int i360_precheck_params(int target, rules_re_t *rule) {
1548
2/2
✓ Branch 2 → 3 taken 5 times.
✓ Branch 2 → 4 taken 3 times.
8 if (!rule->param)
1549 5 return 1;
1550
2/4
✓ Branch 4 → 5 taken 3 times.
✗ Branch 4 → 6 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 3 times.
3 if ((rule->param > 2 || rule->param < 0))
1551 return 1;
1552
1/2
✓ Branch 8 → 9 taken 3 times.
✗ Branch 8 → 27 not taken.
3 if (i360_get_params_new_numb()) {
1553 3 int index = 0;
1554 3 int len = 0;
1555 3 char *prm = i360_get_params_new(&index, &len);
1556
1/2
✓ Branch 24 → 11 taken 3 times.
✗ Branch 24 → 25 not taken.
3 while (index != -1) {
1557
1/2
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 15 taken 3 times.
3 if (rule->param == 1) {
1558 if (len >= rule->string_len) {
1559 if (!strncmp(prm, rule->string_raw, rule->string_len)) {
1560 2 return 1;
1561 }
1562 }
1563 }
1564
1/2
✓ Branch 15 → 16 taken 3 times.
✗ Branch 15 → 21 not taken.
3 else if (rule->param == 2) {
1565
1/2
✓ Branch 16 → 17 taken 3 times.
✗ Branch 16 → 21 not taken.
3 if (rule->status > 0) {
1566 int pcreExecRet;
1567 int subStrVec[30];
1568
1569 3 pcreExecRet = pcre_exec(rule->re,
1570 NULL, // rule->reE,
1571 prm, len, 0, PCRE_NO_START_OPTIMIZE, subStrVec, 30);
1572
1573
2/2
✓ Branch 18 → 19 taken 2 times.
✓ Branch 18 → 20 taken 1 time.
3 if (pcreExecRet > 0) {
1574 2 return 1;
1575 }
1576 }
1577 }
1578
1/2
✓ Branch 21 → 22 taken 1 time.
✗ Branch 21 → 23 not taken.
1 if (target > 0)
1579 1 break; // for wp core should check only 1 parameter;
1580 prm = i360_get_params_new(&index, &len);
1581 }
1582 }
1583 1 return 0;
1584 }
1585
1586 35 static int i360_is_group_enabled(groups_rules_list *g_rules, unsigned int app_id, size_t enabled_group) {
1587
1/4
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 35 times.
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
35 if ((g_rules->group_id == enabled_group) && (enabled_group))
1588 return 1;
1589
2/2
✓ Branch 5 → 6 taken 30 times.
✓ Branch 5 → 10 taken 5 times.
35 if (g_rules->enabled) {
1590
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 9 taken 30 times.
30 if (app_id) {
1591 if (g_rules->app_id == app_id) {
1592 return 1;
1593 }
1594 }
1595 else {
1596 30 return 1;
1597 }
1598 }
1599 5 return 0;
1600 }
1601
1602 11 static int i360_precheck_function_name(rules_list *rule, const char *function_name) {
1603
2/2
✓ Branch 2 → 3 taken 6 times.
✓ Branch 2 → 10 taken 5 times.
11 if (rule->has_func_list) {
1604
2/4
✓ Branch 3 → 4 taken 6 times.
✗ Branch 3 → 5 not taken.
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 6 taken 6 times.
6 if (!function_name || !rule->func_list)
1605 return 0;
1606 6 int *res = map_get(rule->func_list, function_name);
1607
1/2
✓ Branch 7 → 8 taken 6 times.
✗ Branch 7 → 9 not taken.
6 if (res)
1608 6 return 1;
1609 return 0;
1610 }
1611 else
1612 5 return 1;
1613 }
1614
1615 2 static int i360_check_exclude_list() {
1616 2 char php_fname[RGX_MAX_DOCROOT_LEN + 1] = "";
1617 2 char cur_php_fname_dir[PATH_MAX] = "";
1618
1/2
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 4 not taken.
2 if (!exclude_list_opt)
1619 2 return 0;
1620 if (re_stat_rgx) {
1621 if (i360_get_params_new_numb()) {
1622 strncpy(cur_php_fname_dir, cur_php_fname, PATH_MAX);
1623 char *last_slash = strrchr(cur_php_fname_dir, '/');
1624 if (last_slash)
1625 *last_slash = 0;
1626 else
1627 strncpy(cur_php_fname_dir, "/", PATH_MAX);
1628 int index = 0;
1629 int len = 0;
1630 char *prm = i360_get_params_new(&index, &len);
1631 while (index != -1) {
1632 if (len > 0) {
1633 if (i360_translate_to_real_path(prm, cur_php_fname_dir, php_fname, RGX_MAX_DOCROOT_LEN)) {
1634 memcpy(php_fname, prm, strlen(prm));
1635 }
1636 int pcreExecRet;
1637 int subStrVec[30];
1638 pcreExecRet =
1639 pcre_exec(re_stat_rgx, NULL, php_fname, strlen(php_fname), 0, PCRE_NO_START_OPTIMIZE, subStrVec, 30);
1640 if (pcreExecRet > 0) {
1641 return 1;
1642 }
1643 }
1644 prm = i360_get_params_new(&index, &len);
1645 }
1646 }
1647 }
1648 return 0;
1649 }
1650
1651 4 static int i360_precheck_params_for_inclusion() {
1652
1/2
✓ Branch 2 → 3 taken 4 times.
✗ Branch 2 → 4 not taken.
4 if (!malware_directory_config)
1653 4 return 0;
1654
1655 if (!i360_isset_cur_php_fname()) {
1656 return 0;
1657 }
1658
1659 if (i360_get_params_new_numb()) {
1660 int index = 0;
1661 int len = 0;
1662 char *prm = i360_get_params_new(&index, &len);
1663 while (index != -1) {
1664 if ((len > 0) && i360_check_if_file_marked_as_danger(prm, cur_php_fname, malware_directory_config_fd)) {
1665 return 1;
1666 }
1667 prm = i360_get_params_new(&index, &len);
1668 }
1669 }
1670
1671 return 0;
1672 }
1673
1674 1 int i360_precheck_params_for_inclusion_rinit(char *current_script_name) {
1675
1/4
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1 time.
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
1 if (!malware_directory_config || !current_script_name)
1676 1 return 0;
1677 if (strstr(current_script_name, "index.php"))
1678 return 0;
1679
1680 if (i360_check_if_file_marked_as_danger(current_script_name, current_script_name, malware_directory_config_fd)) {
1681 return 1;
1682 }
1683
1684 return 0;
1685 }
1686
1687 7 static int i360_precheck_susp_file_list(rules_list *rule) {
1688
1/2
✓ Branch 2 → 3 taken 7 times.
✗ Branch 2 → 4 not taken.
7 if (!rule->is_list)
1689 7 return 1;
1690 return i360_fast_bad_syscall_detection_by_map_reverse(&rule->files_list);
1691 }
1692
1693 1 int i360_is_file_white_listed(int rule_id) {
1694 // Those files which names are whitelisted, we exclude
1695 // exclude them from regex search. Bitmask is used
1696
1/4
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 8 taken 1 time.
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 8 not taken.
1 if (cur_wl_rules && (WHITELIST_FILE_VER3 == wl_version) &&
1697 (!((unsigned int *)cur_wl_rules)[0] ||
1698 bsearch(&rule_id, cur_wl_rules, MAX_WHITELIST_RULES, sizeof(int), i360_wl_item_comp)))
1699 return 1;
1700
1701
1/6
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 15 taken 1 time.
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 15 not taken.
✗ Branch 10 → 11 not taken.
✗ Branch 10 → 15 not taken.
1 if (cur_wl_rules && (WHITELIST_FILE_VER4 == wl_version) && *(unsigned char *)cur_wl_rules &&
1702 (!((unsigned int *)(cur_wl_rules + 1))[0] ||
1703 bsearch(&rule_id, cur_wl_rules + 1, *(unsigned char *)cur_wl_rules, sizeof(int), i360_wl_item_comp)))
1704 return 1;
1705
1706 // Apply super-rules to every whitelist item
1707
3/6
✓ Branch 15 → 16 taken 1 time.
✗ Branch 15 → 20 not taken.
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 20 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 1 time.
2 if (super_wl_rules && (WHITELIST_FILE_VER3 == wl_version) &&
1708 1 bsearch(&rule_id, super_wl_rules, MAX_WHITELIST_RULES, sizeof(int), i360_wl_item_comp))
1709 return 1;
1710
1711
2/8
✓ Branch 20 → 21 taken 1 time.
✗ Branch 20 → 26 not taken.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 26 taken 1 time.
✗ Branch 22 → 23 not taken.
✗ Branch 22 → 26 not taken.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 26 not taken.
1 if (super_wl_rules && (WHITELIST_FILE_VER4 == wl_version) && super_wl_rules[0] &&
1712 bsearch(&rule_id, super_wl_rules + 1, *(unsigned char *)super_wl_rules, sizeof(int), i360_wl_item_comp))
1713 return 1;
1714
1715 1 return 0;
1716 }
1717
1718 5 static int i360_target_detection_by_map_reverse(char *file_name, struct reversed_ordered_set_t *m) {
1719 5 char php_fname[RGX_MAX_DOCROOT_LEN] = {0};
1720 5 char cur_php_fname_dir[PATH_MAX] = {0};
1721
2/4
✓ Branch 2 → 3 taken 5 times.
✗ Branch 2 → 4 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 5 times.
5 if (!file_name || !m)
1722 return 0;
1723 /* using strncpy safely to avoid -Wstringop-truncation (GCC 8) */
1724 5 size_t cur_php_fname_len = strlen(cur_php_fname);
1725 5 memcpy(cur_php_fname_dir, cur_php_fname, cur_php_fname_len + 1);
1726 5 char *last_slash = strrchr(cur_php_fname_dir, '/');
1727
1/2
✓ Branch 5 → 6 taken 5 times.
✗ Branch 5 → 7 not taken.
5 if (last_slash)
1728 5 *last_slash = 0;
1729 else
1730 strncpy(cur_php_fname_dir, "/", PATH_MAX);
1731
1/2
✓ Branch 9 → 10 taken 5 times.
✗ Branch 9 → 11 not taken.
5 if (i360_translate_to_real_path(file_name, cur_php_fname_dir, php_fname, RGX_MAX_DOCROOT_LEN)) {
1732 5 memcpy(php_fname, file_name, strlen(file_name) + 1);
1733 }
1734 5 char file_name_copy[PATH_MAX] = {0};
1735 5 int val = i360_rev_ordered_find_partial(m, php_fname, strlen(php_fname));
1736
2/2
✓ Branch 12 → 13 taken 1 time.
✓ Branch 12 → 14 taken 4 times.
5 if (val >= 0) {
1737 1 return 1;
1738 }
1739 else {
1740 /* using strncpy safely to avoid -Wstringop-truncation (GCC 8) */
1741 4 size_t php_fname_len = strlen(php_fname);
1742 4 memcpy(file_name_copy, php_fname, php_fname_len + 1);
1743 4 char *ptr = strrchr(file_name_copy, '/');
1744
1/2
✓ Branch 14 → 15 taken 4 times.
✗ Branch 14 → 18 not taken.
4 if (ptr) {
1745 4 *ptr = 0;
1746 4 val = i360_rev_ordered_find_partial(m, file_name_copy, strlen(file_name_copy));
1747
1/2
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 4 times.
4 if (val >= 0) {
1748 return 1;
1749 }
1750 }
1751 }
1752 4 return 0;
1753 }
1754
1755 2 static int i360_target_fpa_positive(rules_list *rule, char *file_name) {
1756
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2 times.
2 if (!i360_precheck_script_ext(rule))
1757 return 0;
1758
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 2 times.
2 if (i360_target_detection_by_map_reverse(file_name, exclude_files_list))
1759 return 0;
1760 2 return 1;
1761 }
1762
1763 2 static int i360_target_fpa_postivie_detection_by_map_reverse() {
1764
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 2 times.
2 if (!exclude_files_list)
1765 return 0;
1766
1/2
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 15 not taken.
2 if (i360_get_params_new_numb()) {
1767 2 int index = 0;
1768 2 int len = 0;
1769 2 char *prm = i360_get_params_new(&index, &len);
1770
2/2
✓ Branch 13 → 8 taken 2 times.
✓ Branch 13 → 14 taken 1 time.
3 while (index != -1) {
1771
1/2
✓ Branch 8 → 9 taken 2 times.
✗ Branch 8 → 12 not taken.
2 if (len > G_MIN_HANDLE_STRING_SIZE) {
1772
2/2
✓ Branch 10 → 11 taken 1 time.
✓ Branch 10 → 12 taken 1 time.
2 if (i360_target_detection_by_map_reverse(prm, exclude_files_list)) {
1773 1 return 1;
1774 }
1775 }
1776 1 prm = i360_get_params_new(&index, &len);
1777 }
1778 }
1779 1 return 0;
1780 }
1781
1782 1 static int i360_target_wp_core_check_fopen(const char *function_name) {
1783
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 12 taken 1 time.
1 if (!strncmp(function_name, "fopen", 5)) {
1784 if (i360_get_params_new_numb() > 1) {
1785 int index = 1;
1786 int len = 0;
1787 char *prm = i360_get_params_new(&index, &len);
1788 if (((len == 1) && !strncmp(prm, "r", 1)) || ((len == 2) && !strncmp(prm, "rb", 2))) {
1789 return 1;
1790 }
1791 }
1792 }
1793 1 return 0;
1794 }
1795
1796 7 static int i360_target_wp_core_protect(rules_list *rule, const char *function_name) {
1797
2/2
✓ Branch 2 → 3 taken 5 times.
✓ Branch 2 → 4 taken 2 times.
7 if (rule->target <= 0)
1798 5 return 1;
1799
2/2
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 9 taken 1 time.
2 if (rule->target & TARGET_fpa_negative) {
1800
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 1 time.
1 if (i360_target_fpa_postivie_detection_by_map_reverse())
1801 return 0;
1802 1 return 1;
1803 }
1804
1/2
✓ Branch 9 → 10 taken 1 time.
✗ Branch 9 → 23 not taken.
1 else if (rule->target & TARGET_fpa_notblock_postitive_script_negative) {
1805
1/2
✗ Branch 11 → 12 not taken.
✓ Branch 11 → 13 taken 1 time.
1 if (i360_target_wp_core_check_fopen(function_name))
1806 return 0;
1807
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 1 time.
1 if (!i360_target_fpa_postivie_detection_by_map_reverse())
1808 return 1;
1809
1/2
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 19 taken 1 time.
1 if (!i360_isset_cur_php_fname())
1810 return 0;
1811 1 char *script = cur_php_fname;
1812
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 1 time.
1 if (i360_target_detection_by_map_reverse(script, exclude_files_list))
1813 return 0;
1814 1 return 1;
1815 }
1816 else if (rule->target & TARGET_fpa_negative_only) {
1817 if (i360_target_wp_core_check_fopen(function_name))
1818 return 0;
1819 if (i360_target_fpa_postivie_detection_by_map_reverse())
1820 return 0;
1821 return 1;
1822 }
1823 return 0;
1824 }
1825
1826 117 static int i360_default_recognizer_rule_match(rules_list *rule, const char *queue, size_t queue_len,
1827 const char *function_name) {
1828
1/4
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 5 taken 117 times.
✗ Branch 3 → 4 not taken.
✗ Branch 3 → 5 not taken.
117 if (rule->status <= 0 && !rule->detection_type)
1829 return 0;
1830
1831 // Those files which names are whitelisted, we exclude
1832 // exclude them from regex search. Bitmask is used
1833
4/4
✓ Branch 5 → 6 taken 35 times.
✓ Branch 5 → 11 taken 82 times.
✓ Branch 6 → 7 taken 10 times.
✓ Branch 6 → 11 taken 25 times.
117 if (cur_wl_rules && (WHITELIST_FILE_VER3 == wl_version) &&
1834
3/4
✓ Branch 7 → 8 taken 10 times.
✗ Branch 7 → 10 not taken.
✓ Branch 9 → 10 taken 6 times.
✓ Branch 9 → 11 taken 4 times.
20 (!((unsigned int *)cur_wl_rules)[0] ||
1835 10 bsearch(&(rule->id), cur_wl_rules, MAX_WHITELIST_RULES, sizeof(int), i360_wl_item_comp)))
1836 6 return 0;
1837
1838
5/6
✓ Branch 11 → 12 taken 29 times.
✓ Branch 11 → 18 taken 82 times.
✓ Branch 12 → 13 taken 25 times.
✓ Branch 12 → 18 taken 4 times.
✓ Branch 13 → 14 taken 25 times.
✗ Branch 13 → 18 not taken.
111 if (cur_wl_rules && (WHITELIST_FILE_VER4 == wl_version) && *(unsigned char *)cur_wl_rules &&
1839
3/4
✓ Branch 14 → 15 taken 25 times.
✗ Branch 14 → 17 not taken.
✓ Branch 16 → 17 taken 14 times.
✓ Branch 16 → 18 taken 11 times.
50 (!((unsigned int *)(cur_wl_rules + 1))[0] ||
1840 25 bsearch(&(rule->id), cur_wl_rules + 1, *(unsigned char *)cur_wl_rules, sizeof(int), i360_wl_item_comp)))
1841 14 return 0;
1842
1843 // Apply super-rules to every whitelist item
1844
6/6
✓ Branch 18 → 19 taken 44 times.
✓ Branch 18 → 23 taken 53 times.
✓ Branch 19 → 20 taken 26 times.
✓ Branch 19 → 23 taken 18 times.
✓ Branch 21 → 22 taken 3 times.
✓ Branch 21 → 23 taken 23 times.
123 if (super_wl_rules && (WHITELIST_FILE_VER3 == wl_version) &&
1845 26 bsearch(&(rule->id), super_wl_rules, MAX_WHITELIST_RULES, sizeof(int), i360_wl_item_comp))
1846 3 return 0;
1847
1848
7/8
✓ Branch 23 → 24 taken 41 times.
✓ Branch 23 → 29 taken 53 times.
✓ Branch 24 → 25 taken 18 times.
✓ Branch 24 → 29 taken 23 times.
✓ Branch 25 → 26 taken 18 times.
✗ Branch 25 → 29 not taken.
✓ Branch 27 → 28 taken 3 times.
✓ Branch 27 → 29 taken 15 times.
112 if (super_wl_rules && (WHITELIST_FILE_VER4 == wl_version) && super_wl_rules[0] &&
1849 18 bsearch(&(rule->id), super_wl_rules + 1, *(unsigned char *)super_wl_rules, sizeof(int), i360_wl_item_comp))
1850 3 return 0;
1851
1852 int pcreExecRet;
1853 int subStrVec[30];
1854
1855
1/2
✓ Branch 29 → 30 taken 91 times.
✗ Branch 29 → 31 not taken.
91 if (rule->detection_type == 0) {
1856 pcreExecRet =
1857 91 pcre_exec(rule->re, rule->reE, queue, (int)queue_len, 0, PCRE_ANCHORED | PCRE_NO_START_OPTIMIZE, subStrVec, 30);
1858 }
1859 else if (rule->detection_type == 1) {
1860 if (!rule->rule_string || !rule->rule_string_len)
1861 return 0;
1862 if (rule->rule_string_len > queue_len)
1863 return 0;
1864 pcreExecRet = strncmp(rule->rule_string, queue, rule->rule_string_len) ? -1 : 1;
1865 }
1866 else {
1867 pcreExecRet = queue[0] == rule->rule_char ? 1 : -1;
1868 }
1869
1870
2/2
✓ Branch 45 → 46 taken 71 times.
✓ Branch 45 → 47 taken 20 times.
91 if (pcreExecRet < 1)
1871 71 return 0;
1872
1873
2/2
✓ Branch 47 → 48 taken 2 times.
✓ Branch 47 → 59 taken 18 times.
20 if (rule->check_blocked == 2) {
1874
1/2
✓ Branch 51 → 52 taken 2 times.
✗ Branch 51 → 54 not taken.
4 return (i360_precheck_function_name(rule, function_name) &&
1875
2/6
✓ Branch 49 → 50 taken 2 times.
✗ Branch 49 → 57 not taken.
✗ Branch 53 → 54 not taken.
✓ Branch 53 → 57 taken 2 times.
✗ Branch 55 → 56 not taken.
✗ Branch 55 → 57 not taken.
4 (i360_precheck_params_for_inclusion() || i360_check_exclude_list()) && i360_precheck_susp_file_list(rule));
1876 }
1877
1878
2/2
✓ Branch 59 → 60 taken 2 times.
✓ Branch 59 → 69 taken 16 times.
18 if (rule->check_blocked == 1)
1879
2/6
✓ Branch 61 → 62 taken 2 times.
✗ Branch 61 → 67 not taken.
✗ Branch 63 → 64 not taken.
✓ Branch 63 → 67 taken 2 times.
✗ Branch 65 → 66 not taken.
✗ Branch 65 → 67 not taken.
2 return (i360_precheck_function_name(rule, function_name) && i360_precheck_params_for_inclusion() &&
1880 i360_precheck_susp_file_list(rule));
1881
1882
2/2
✓ Branch 69 → 70 taken 8 times.
✓ Branch 69 → 72 taken 8 times.
16 if (rule->check_mail == 1)
1883 8 return i360_check_mail_heuristic(function_name);
1884
1885
4/6
✓ Branch 73 → 74 taken 8 times.
✗ Branch 73 → 100 not taken.
✓ Branch 75 → 76 taken 8 times.
✗ Branch 75 → 100 not taken.
✓ Branch 77 → 78 taken 7 times.
✓ Branch 77 → 100 taken 1 time.
16 if (i360_precheck_script_ext(rule) && i360_precheck_params_ext(rule) &&
1886
2/4
✓ Branch 79 → 80 taken 7 times.
✗ Branch 79 → 100 not taken.
✓ Branch 81 → 82 taken 7 times.
✗ Branch 81 → 100 not taken.
22 i360_precheck_params(rule->target, &rule->precheck) && i360_precheck_param_fop(&rule->fop_pfirst_chk, 0) &&
1887
2/4
✓ Branch 83 → 84 taken 7 times.
✗ Branch 83 → 100 not taken.
✓ Branch 85 → 86 taken 7 times.
✗ Branch 85 → 100 not taken.
21 i360_precheck_param_fop(&rule->fop_psecond_chk, 1) && i360_precheck_function_name(rule, function_name) &&
1888
1/2
✓ Branch 87 → 88 taken 7 times.
✗ Branch 87 → 100 not taken.
14 i360_precheck_susp_file_list(rule) && i360_target_wp_core_protect(rule, function_name)) {
1889
2/4
✓ Branch 88 → 89 taken 7 times.
✗ Branch 88 → 90 not taken.
✗ Branch 89 → 90 not taken.
✓ Branch 89 → 91 taken 7 times.
7 if (rule->is_list || rule->check_fp) {
1890 ((unsigned char*)queue)[0] = (char)toupper((unsigned char)queue[0]);
1891 }
1892 7 return (rule->check_fp != 1)
1893 7 ? ((rule->private_fp_list.count > 0)
1894 ? (!i360_check_fp_inner(queue, queue_len, 0, (exclude_rules_list *)&rule->private_fp_list))
1895
1/2
✗ Branch 92 → 93 not taken.
✓ Branch 92 → 95 taken 7 times.
7 : (!i360_check_fp(queue, queue_len, 0)))
1896
1/2
✓ Branch 91 → 92 taken 7 times.
✗ Branch 91 → 98 not taken.
14 : 1; // fp exclude list
1897 }
1898
1899 1 return 0;
1900 }
1901
1902 #define FNAME_LEN 16
1903
1904 3 int i360_check_null_file_size(const char *fname) {
1905 3 char php_fname[RGX_MAX_DOCROOT_LEN + 1] = "";
1906 3 char cur_php_fname_dir[PATH_MAX] = "";
1907 struct stat st;
1908
1909
2/4
✓ Branch 2 → 3 taken 3 times.
✗ Branch 2 → 4 not taken.
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 3 times.
3 if (!fname || *fname == 0)
1910 return 1;
1911
1912 3 strncpy(cur_php_fname_dir, cur_php_fname, PATH_MAX);
1913 3 char *last_slash = strrchr(cur_php_fname_dir, '/');
1914
2/2
✓ Branch 5 → 6 taken 2 times.
✓ Branch 5 → 7 taken 1 time.
3 if (last_slash)
1915 2 *last_slash = 0;
1916 else
1917 1 cur_php_fname_dir[0] = '\0';
1918 //strncpy(cur_php_fname_dir, "/", PATH_MAX);
1919
2/2
✓ Branch 9 → 10 taken 1 time.
✓ Branch 9 → 11 taken 2 times.
3 if (i360_translate_to_real_path(fname, cur_php_fname_dir, php_fname, RGX_MAX_DOCROOT_LEN))
1920 1 memcpy(php_fname, fname, strlen(fname));
1921
3/4
✓ Branch 12 → 13 taken 2 times.
✓ Branch 12 → 15 taken 1 time.
✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 15 not taken.
3 if (!stat(php_fname, &st) && st.st_size)
1922 2 return 0;
1923
1924 1 return 1;
1925 }
1926
1927 20 static rules_list *i360_script_default_recognizer(const char *function_name, const char *queue, size_t queue_len) {
1928 20 const char *names[] = {cur_php_fname, "*"};
1929 size_t i;
1930
2/2
✓ Branch 15 → 3 taken 40 times.
✓ Branch 15 → 16 taken 20 times.
60 for (i = 0; i < sizeof(names)/sizeof(names[0]); ++ i) {
1931 40 script_rules_t *script_rules = i360_get_script_rules(names[i], cur_php_uid);
1932
1/2
✗ Branch 4 → 5 not taken.
✓ Branch 4 → 14 taken 40 times.
40 if (script_rules) {
1933 rules_list *rule = script_rules->rules;
1934 while (rule) {
1935 i360_ull rule_timer = 0;
1936 i360_counter_saver_savetimer(&rule_timer);
1937 if (i360_default_recognizer_rule_match(rule, queue, queue_len, function_name)) {
1938 i360_counter_saver_add_rule(rule->id, rule_timer);
1939 return rule;
1940 }
1941 i360_counter_saver_add_rule(rule->id, rule_timer);
1942
1943 rule = rule->next;
1944 }
1945 }
1946 }
1947
1948 20 return NULL;
1949 }
1950
1951 28 static rules_list *i360_default_recognizer(const char *function_name, const char *queue, size_t queue_len, int level,
1952 unsigned int app_id, int enabled_group) {
1953 28 groups_rules_list *g_rules = parms_data_g_ptr->grp_detector;
1954
2/2
✓ Branch 21 → 3 taken 31 times.
✓ Branch 21 → 22 taken 17 times.
48 while (g_rules) {
1955
2/2
✓ Branch 4 → 5 taken 28 times.
✓ Branch 4 → 20 taken 3 times.
31 if (i360_is_group_enabled(g_rules, app_id, enabled_group)) {
1956 28 rules_list_ptr *rules_ptr = g_rules->head;
1957
2/2
✓ Branch 19 → 6 taken 120 times.
✓ Branch 19 → 20 taken 17 times.
137 while (rules_ptr) {
1958 120 rules_list *rule = rules_ptr->rule_ptr;
1959
1960
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 120 times.
120 if (rule->level < level) {
1961 rules_ptr = rules_ptr->next;
1962 3 continue;
1963 }
1964
2/2
✓ Branch 8 → 9 taken 3 times.
✓ Branch 8 → 10 taken 117 times.
120 if (rule->target & TARGET_before_execution_negative) {
1965 3 rules_ptr = rules_ptr->next;
1966 3 continue;
1967 }
1968
1969 117 i360_ull rule_timer = 0;
1970 117 i360_counter_saver_savetimer(&rule_timer);
1971
1972
2/2
✓ Branch 12 → 13 taken 11 times.
✓ Branch 12 → 15 taken 106 times.
117 if (i360_default_recognizer_rule_match(rule, queue, queue_len, function_name)) {
1973 11 i360_counter_saver_add_rule(rule->id, rule_timer);
1974 11 return rule;
1975 }
1976
1977 106 i360_counter_saver_add_rule(rule->id, rule_timer);
1978
1979 106 rules_ptr = rules_ptr->next;
1980 }
1981 }
1982 20 g_rules = g_rules->next;
1983 }
1984
1985 17 return i360_script_default_recognizer(function_name, queue, queue_len);
1986 }
1987
1988 33 static int i360_get_app_id() {
1989 33 return 0;
1990 }
1991
1992 28 void i360_check_chain(__attribute__((unused)) params_list *params, chain_result *result, int logger,
1993 const char *function_name, const char *queue, size_t queue_len, int level, int enabled_group) {
1994 28 memset(result, 0, sizeof(chain_result));
1995 28 result->danger_type = NODANGER;
1996 28 result->recognizer_id = I360_RECOGNIZER_ID_NONE;
1997
1998 28 rules_list *rules = i360_default_recognizer(function_name, queue, queue_len, level, i360_get_app_id(), enabled_group);
1999
2/2
✓ Branch 4 → 5 taken 11 times.
✓ Branch 4 → 13 taken 17 times.
28 if (rules) {
2000
3/6
✓ Branch 5 → 6 taken 9 times.
✓ Branch 5 → 8 taken 2 times.
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 9 taken 9 times.
✗ Branch 7 → 8 not taken.
✗ Branch 7 → 9 not taken.
11 if ((rules->action == BLOCK_FUNC) || (rules->id >= PHP_IMUNITY_MIN_ID && rules->id <= PHP_IMUNITY_MAX_ID)) {
2001 2 result->block = 1;
2002 }
2003
3/4
✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 12 taken 9 times.
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 2 times.
11 if (rules->action != NO_ACTION && rules->check_blocked == 2) {
2004 result->block = 2;
2005 }
2006 11 result->recognizer_id = I360_RECOGNIZER_ID_COMMON;
2007 11 result->chain_id = rules->id;
2008 11 result->danger_type = DANGER;
2009 11 result->recognizer_desr = I360_RECOGNIZER_ID_COMMON_DESC;
2010 11 result->ruldescr = rules->description;
2011 }
2012
2013
3/6
✓ Branch 13 → 14 taken 26 times.
✓ Branch 13 → 17 taken 2 times.
✗ Branch 15 → 16 not taken.
✓ Branch 15 → 18 taken 26 times.
✗ Branch 16 → 17 not taken.
✗ Branch 16 → 18 not taken.
28 if ((result->chain_id >= G_NON_LOG_RULE_ID) || (i360_is_rce_logger_log_mode() && (result->danger_type == DANGER))) {
2014 2 result->recognizer_id = I360_RECOGNIZER_ID_INTERNAL;
2015 2 result->recognizer_desr = I360_RECOGNIZER_ID_INTERNAL_DESC;
2016 }
2017
2018
2/2
✓ Branch 18 → 19 taken 2 times.
✓ Branch 18 → 22 taken 26 times.
28 if (logger) {
2019
2/2
✓ Branch 19 → 20 taken 1 time.
✓ Branch 19 → 21 taken 1 time.
2 if (result->danger_type) {
2020 1 result->action = LOG_ONLY;
2021 }
2022 else {
2023 1 result->recognizer_desr = I360_RECOGNIZER_ID_LOG_DESC;
2024 1 result->action = LOG_ONLY;
2025 1 result->recognizer_id = I360_RECOGNIZER_ID_LOG;
2026 1 result->chain_id = 0;
2027 1 result->danger_type = DANGER;
2028 }
2029 }
2030 28 }
2031
2032 2 static int i360_target_before_execution_negative(rules_list *rule, char *file_name) {
2033 2 return i360_target_fpa_positive(rule, file_name);
2034 }
2035
2036 2 static rules_list *i360_default_recognizer_rinit(int level, unsigned int app_id, size_t enabled_group,
2037 char *file_name) {
2038 2 groups_rules_list *g_rules = parms_data_g_ptr->grp_detector;
2039
2/2
✓ Branch 32 → 3 taken 4 times.
✓ Branch 32 → 33 taken 1 time.
5 while (g_rules) {
2040
2/2
✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 31 taken 2 times.
4 if (i360_is_group_enabled(g_rules, app_id, enabled_group)) {
2041 2 rules_list_ptr *rules_ptr = g_rules->head;
2042
2/2
✓ Branch 30 → 6 taken 7 times.
✓ Branch 30 → 31 taken 1 time.
8 while (rules_ptr) {
2043 7 rules_list *rule = rules_ptr->rule_ptr;
2044
2045
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 8 taken 7 times.
7 if (rule->level < level) {
2046 rules_ptr = rules_ptr->next;
2047 5 continue;
2048 }
2049
2/2
✓ Branch 8 → 9 taken 5 times.
✓ Branch 8 → 10 taken 2 times.
7 if (!(rule->target & TARGET_before_execution_negative)) {
2050 5 rules_ptr = rules_ptr->next;
2051 5 continue;
2052 }
2053
2054 2 i360_ull rule_timer = 0;
2055 2 i360_counter_saver_savetimer(&rule_timer);
2056
1/2
✓ Branch 12 → 13 taken 2 times.
✗ Branch 12 → 25 not taken.
2 if (i360_target_before_execution_negative(rule, file_name)) {
2057 // Check for fp_rules without execution flow
2058
1/2
✓ Branch 13 → 14 taken 2 times.
✗ Branch 13 → 23 not taken.
2 if (rule->check_fp != 1) {
2059
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 19 taken 2 times.
2 if (rule->private_fp_list.count > 0) {
2060 if (!i360_check_fp_inner("", 0, 0, (exclude_rules_list *)&rule->private_fp_list)) {
2061 i360_counter_saver_add_rule(rule->id, rule_timer);
2062 1 return rule;
2063 }
2064 }
2065 else {
2066
2/2
✓ Branch 20 → 21 taken 1 time.
✓ Branch 20 → 25 taken 1 time.
2 if (!i360_check_fp("", 0, 0)) {
2067 1 i360_counter_saver_add_rule(rule->id, rule_timer);
2068 1 return rule;
2069 }
2070 }
2071 }
2072 else {
2073 i360_counter_saver_add_rule(rule->id, rule_timer);
2074 return rule;
2075 }
2076 }
2077 1 i360_counter_saver_add_rule(rule->id, rule_timer);
2078
2079 1 rules_ptr = rules_ptr->next;
2080 }
2081 }
2082 3 g_rules = g_rules->next;
2083 }
2084
2085 1 return NULL;
2086 }
2087
2088 2 void i360_check_chain_rinit(chain_result *result, int logger, int level, int enabled_group, char *file_name) {
2089 2 memset(result, 0, sizeof(chain_result));
2090 2 result->danger_type = NODANGER;
2091 2 result->recognizer_id = I360_RECOGNIZER_ID_NONE;
2092
2093
1/2
✓ Branch 3 → 4 taken 2 times.
✗ Branch 3 → 15 not taken.
2 if (!i360_pd_database_check_rinit(result, level, enabled_group, "", 0)) {
2094 2 rules_list *rules = i360_default_recognizer_rinit(level, i360_get_app_id(), enabled_group, file_name);
2095
2/2
✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 15 taken 1 time.
2 if (rules) {
2096
3/6
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 10 not taken.
✓ Branch 8 → 9 taken 1 time.
✗ Branch 8 → 11 not taken.
✗ Branch 9 → 10 not taken.
✓ Branch 9 → 11 taken 1 time.
1 if ((rules->action == BLOCK_FUNC) || (rules->id >= PHP_IMUNITY_MIN_ID && rules->id <= PHP_IMUNITY_MAX_ID)) {
2097 result->block = 1;
2098 }
2099
2/4
✓ Branch 11 → 12 taken 1 time.
✗ Branch 11 → 14 not taken.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 1 time.
1 if (rules->action != NO_ACTION && rules->check_blocked == 2) {
2100 result->block = 2;
2101 }
2102 1 result->recognizer_id = I360_RECOGNIZER_ID_COMMON;
2103 1 result->chain_id = rules->id;
2104 1 result->danger_type = DANGER;
2105 1 result->recognizer_desr = I360_RECOGNIZER_ID_COMMON_DESC;
2106 1 result->ruldescr = rules->description;
2107 }
2108 }
2109
2110
3/6
✓ Branch 15 → 16 taken 1 time.
✓ Branch 15 → 19 taken 1 time.
✗ Branch 17 → 18 not taken.
✓ Branch 17 → 20 taken 1 time.
✗ Branch 18 → 19 not taken.
✗ Branch 18 → 20 not taken.
2 if ((result->chain_id >= G_NON_LOG_RULE_ID) || (i360_is_rce_logger_log_mode() && (result->danger_type == DANGER))) {
2111 1 result->recognizer_id = I360_RECOGNIZER_ID_INTERNAL;
2112 1 result->recognizer_desr = I360_RECOGNIZER_ID_INTERNAL_DESC;
2113 }
2114
2115
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 24 taken 2 times.
2 if (logger) {
2116 if (result->danger_type) {
2117 result->action = LOG_ONLY;
2118 }
2119 else {
2120 result->recognizer_desr = I360_RECOGNIZER_ID_LOG_DESC;
2121 result->action = LOG_ONLY;
2122 result->recognizer_id = I360_RECOGNIZER_ID_LOG;
2123 result->chain_id = 0;
2124 result->danger_type = DANGER;
2125 }
2126 }
2127 2 }
2128
2129 9 int i360_result_action(chain_result *chains, int user_action) {
2130
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 9 times.
9 if (chains->recognizer_id == I360_RECOGNIZER_ID_INTERNAL) {
2131 return LOG_ONLY;
2132 }
2133 9 return user_action;
2134 }
2135
2136 4 void i360_func_foreach(void (*f)(const char *key, const char *val, int is_danger, int is_openwrite,
2137 const void *dbfunc)) {
2138
1/2
✓ Branch 3 → 4 taken 4 times.
✗ Branch 3 → 5 not taken.
4 if (i360_pd_database_func_foreach(f))
2139 4 return;
2140
2141 const char *key = NULL;
2142 map_iter_t iter = map_iter(funcs);
2143 while ((key = map_next(funcs, &iter))) {
2144 char *res = (char *)map_value(funcs, &iter);
2145 if (map_get(writeloggers, key)) {
2146 f(key, res, 1, 1, 0);
2147 }
2148 else {
2149 f(key, res, 1, 0, 0);
2150 }
2151 }
2152
2153 iter = map_iter(writeloggers);
2154 while ((key = map_next(writeloggers, &iter))) {
2155 if (!map_get(funcs, key)) {
2156 f(key, NULL, 0, 1, 0);
2157 }
2158 }
2159 }
2160
2161 #ifndef UNIT_TESTING
2162 void i360_print_params(params_list *params, const char *fname, const char *dbgfile_name) {
2163 if (!params)
2164 return;
2165 if (dbgfile_name) {
2166 i360_write_debug_log(dbgfile_name, 2, "FUNC PARAMS %s:", fname);
2167 }
2168 if (params->head) {
2169 params_item *item = params->head;
2170 while (item) {
2171 if (dbgfile_name) {
2172 i360_write_debug_log(dbgfile_name, 0, "%s,", item->param);
2173 }
2174 item = item->next;
2175 }
2176 }
2177 if (dbgfile_name) {
2178 i360_write_debug_log(dbgfile_name, 3, "");
2179 }
2180 return;
2181 }
2182
2183 void i360_print_params_new(const char *fname, const char *dbgfile_name) {
2184 if (!i360_params_numb)
2185 return;
2186 if (dbgfile_name) {
2187 i360_write_debug_log(dbgfile_name, 2, "FUNC PARAMS %s:", fname);
2188 }
2189 if (i360_params_numb) {
2190 int index = 0;
2191 int len = 0;
2192 char *prm = i360_get_params_new(&index, &len);
2193 while (index != -1) {
2194 if (dbgfile_name) {
2195 i360_write_debug_log(dbgfile_name, 0, "%s,", prm);
2196 }
2197 prm = i360_get_params_new(&index, &len);
2198 }
2199 }
2200 if (dbgfile_name) {
2201 i360_write_debug_log(dbgfile_name, 3, "");
2202 }
2203 return;
2204 }
2205
2206 void i360_print_func_dict_letter() {
2207 const char *key = NULL;
2208 map_iter_t iter = map_iter(funcs);
2209 while ((key = map_next(funcs, &iter))) {
2210 char *res = (char *)map_get(funcs, key);
2211 char letter_buf[2] = {0};
2212 snprintf(letter_buf, 2, "%c", res[0]);
2213 printf("%c\t%s\n", res[0], key);
2214 }
2215 iter = map_iter(&parms_data_g_ptr->groups);
2216 while ((key = map_next(&parms_data_g_ptr->groups, &iter))) {
2217 char *res = (char *)map_get(&parms_data_g_ptr->groups, key);
2218 char *name = (char *)map_get(funcs, res);
2219 if (!name) {
2220 printf("%c\t%s\n", key[0], res);
2221 }
2222 }
2223 }
2224
2225 void i360_print_func_dict() {
2226 char letter_shown[256] = {0};
2227 const char *key = NULL;
2228 map_iter_t iter = map_iter(funcs);
2229 while ((key = map_next(funcs, &iter))) {
2230 char *res = (char *)map_get(funcs, key);
2231 uint8_t index = (uint8_t)res[0];
2232 if (!letter_shown[index]) {
2233 char letter_buf[2] = {0};
2234 snprintf(letter_buf, 2, "%c", res[0]);
2235 char *name = (char *)map_get(&parms_data_g_ptr->groups, letter_buf);
2236 printf("%c\t%s\n", res[0], name ? name : key);
2237 letter_shown[index] = 1;
2238 }
2239 }
2240 }
2241
2242 void i360_print_groups_dict() {
2243 groups_rules_list *g_rules = parms_data_g_ptr->grp_detector;
2244 while (g_rules) {
2245 if (i360_is_group_enabled(g_rules, 0, 0)) {
2246 printf("%d\t%s\n", g_rules->group_id, g_rules->group_description);
2247 }
2248 g_rules = g_rules->next;
2249 }
2250 }
2251 #endif
2252
2253 1 params_global_data *i360_get_global_data() {
2254 1 return parms_data_g_ptr;
2255 }
2256
2257 1 identifier i360_make_anyop_old(uint8_t glb, uint8_t uniq) {
2258 1 identifier tmp = {0};
2259 1 tmp.split.syscall_name = ANYOP;
2260 1 tmp.split.reserved = PHP1_RESERVED;
2261 1 tmp.split.anyop_calls = glb;
2262 1 tmp.split.anyop_dif_modif = uniq;
2263 1 return tmp;
2264 }
2265
2266 1 int i360_is_eval_in_func_list() {
2267 char buffer[G_MAX_RESULT_LEN];
2268
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 1 time.
1 if (!funcs)
2269 return 1;
2270 1 memset(buffer, 0, G_MAX_RESULT_LEN);
2271
1/2
✓ Branch 5 → 6 taken 1 time.
✗ Branch 5 → 7 not taken.
1 if (i360_is_function_hooked("eval", buffer)) {
2272 1 return 1;
2273 }
2274 return 0;
2275 }
2276
2277 #define FILE_DEBUG_LEN 4096
2278
2279 3 int i360_write_debug_log(const char *file_name, int new_line, const char *format, ...) {
2280 char file_name_new[FILE_DEBUG_LEN];
2281 char buffer[16000];
2282 3 snprintf(file_name_new, FILE_DEBUG_LEN, "%s.%d", file_name, getpid());
2283 3 FILE *fp = fopen(file_name_new, "a");
2284
1/2
✓ Branch 4 → 5 taken 3 times.
✗ Branch 4 → 16 not taken.
3 if (fp) {
2285 struct timeval tv;
2286 3 gettimeofday(&tv, NULL);
2287 va_list args;
2288 3 va_start(args, format);
2289 3 vsnprintf(buffer, 16000, format, args);
2290 3 va_end(args);
2291
2/2
✓ Branch 6 → 7 taken 1 time.
✓ Branch 6 → 8 taken 2 times.
3 if (new_line == 1) {
2292 1 fprintf(fp, "[%lld.%lld] %s\n", (long long)(tv.tv_sec), (long long)(tv.tv_usec) / 1000, buffer);
2293 }
2294
2/2
✓ Branch 8 → 9 taken 1 time.
✓ Branch 8 → 10 taken 1 time.
2 else if (new_line == 2) {
2295 1 fprintf(fp, "[%lld.%lld] %s", (long long)(tv.tv_sec), (long long)(tv.tv_usec) / 1000, buffer);
2296 }
2297 else {
2298
1/2
✗ Branch 10 → 11 not taken.
✓ Branch 10 → 12 taken 1 time.
1 fprintf(fp, "%s%s", buffer, (new_line ? "\n" : ""));
2299 }
2300 3 fclose(fp);
2301 }
2302 3 return 0;
2303 }
2304
2305 static __thread int rce_logger = 0;
2306
2307 1 void i360_reset_logger_rce() {
2308 1 rce_logger = 0; // block mode
2309 1 }
2310
2311 1 void i360_set_logger_rce() {
2312 1 rce_logger = 1; // log mode
2313 1 }
2314
2315 30 int i360_is_rce_logger_log_mode() {
2316 30 return rce_logger == 1;
2317 }
2318
2319 typedef void (*iter_environ_cb)(char *s, size_t ln, void *data);
2320
2321 /**
2322 * Slurp file content into memory buffer on heap.
2323 * File size is not checked, thus slurp_file() is Ok
2324 * to be used for procfs items or pipes.
2325 *
2326 * @param path
2327 * @param buf_heapptr placeholder for heap buffer pointer.
2328 * That is slurp_file() caller responsibility to free heap buffer
2329 * when the things are done.
2330 * @Return number of bytes read or -1 on error
2331 */
2332 2 static ssize_t slurp_file(const char *path, char **buf_heapptr) {
2333 2 FILE *fp = fopen(path, "rb");
2334
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2 times.
2 if (!fp)
2335 return -1;
2336
2337 2 size_t buf_len = 4096;
2338
2339
1/2
✗ Branch 6 → 7 not taken.
✓ Branch 6 → 9 taken 2 times.
2 if (!(*buf_heapptr = malloc(buf_len))) {
2340 fclose(fp);
2341 return -1;
2342 }
2343
2344 2 size_t buf_free_capacity = buf_len;
2345 2 size_t buf_next_chunk_offset = 0;
2346 2 ssize_t retval = 0;
2347
2348 2 while (true) {
2349 4 size_t bytes_read = fread(*buf_heapptr + buf_next_chunk_offset, 1, buf_free_capacity, fp);
2350 4 retval += bytes_read;
2351 4 buf_free_capacity -= bytes_read;
2352
2/2
✓ Branch 11 → 12 taken 2 times.
✓ Branch 11 → 13 taken 2 times.
4 if (buf_free_capacity)
2353 2 break;
2354
2355 2 buf_next_chunk_offset += bytes_read;
2356 2 size_t grow_by = buf_len; // grow buf exponentially (x2)
2357 2 void *newptr = realloc(*buf_heapptr, buf_len + grow_by); // Mind possible memory leak
2358
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 18 taken 2 times.
2 if (!(newptr)) {
2359 fclose(fp);
2360 free(*buf_heapptr);
2361 *buf_heapptr = NULL;
2362 return -1;
2363 }
2364 2 *buf_heapptr = newptr;
2365 2 buf_len += grow_by;
2366 2 buf_free_capacity += grow_by;
2367 }
2368
2369 2 fclose(fp);
2370 2 return retval;
2371 }
2372
2373 /**
2374 * Iterate over /proc/self/environ strings
2375 *
2376 * @param cb callback to be called for each environ string
2377 * @Return zero on success or -1 on error
2378 */
2379 #ifndef UNIT_TESTING
2380 static
2381 #endif
2382 2 int iter_proc_self_environ(iter_environ_cb cb, char *path, void *data) {
2383 char *environ_buf;
2384 2 ssize_t read = slurp_file(path, &environ_buf);
2385
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 2 times.
2 if (read < 0)
2386 return -1;
2387
2388 size_t ln;
2389 2 char *p = environ_buf, *q = p + read;
2390
2/2
✓ Branch 8 → 6 taken 108 times.
✓ Branch 8 → 9 taken 2 times.
110 for (; q != p; p += ln + 1) {
2391 108 ln = strlen(p);
2392 108 cb(p, ln, data);
2393 }
2394 2 free(environ_buf);
2395 2 return 0;
2396 }
2397
2398 2 static void iter_environ(iter_environ_cb cb) {
2399 2 char **s = environ;
2400
2/2
✓ Branch 5 → 3 taken 110 times.
✓ Branch 5 → 6 taken 2 times.
112 for (; *s; ++s) {
2401 110 int ln = strlen(*s);
2402 110 cb(*s, ln, NULL);
2403 }
2404 2 }
2405
2406 #include "envfilter.c"
2407
2408 110 static void i360_init_global_server_cb(char *s, size_t ln, __attribute__((unused)) void *data) {
2409
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 5 taken 108 times.
110 if (i360_need_save_env_variable(s, ln) == 1) {
2410 2 i360_add_func_param(&server_array, s, ln);
2411 }
2412 110 }
2413
2414 2 void i360_init_global_server() {
2415
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 2 times.
2 if (server_array.head) {
2416 i360_free_func_params(&server_array);
2417 }
2418
1/2
✓ Branch 4 → 5 taken 2 times.
✗ Branch 4 → 6 not taken.
2 if (environ)
2419 {
2420 2 iter_environ(i360_init_global_server_cb);
2421 }
2422 else {
2423 iter_proc_self_environ(i360_init_global_server_cb, "/proc/self/environ", NULL);
2424 }
2425 2 }
2426
2427 1 void i360_init_global_server_no_env() {
2428
1/2
✓ Branch 2 → 3 taken 1 time.
✗ Branch 2 → 4 not taken.
1 if (server_array.head) {
2429 1 i360_free_func_params(&server_array);
2430 }
2431 1 }
2432
2433 1 void i360_add_value_to_global_server(char *key, int len) {
2434 1 i360_add_func_param(&server_array, key, len);
2435 1 }
2436
2437 1 void i360_clean_global_server() {
2438 1 i360_free_func_params(&server_array);
2439 1 }
2440
2441 1 params_list *i360_get_global_server() {
2442 1 return (params_list *)&server_array;
2443 }
2444
2445 #define I360_PARAM_BUF_LEN_QUEUE 15
2446
2447 38 int i360_check_open_read(const char *fname, __attribute__((unused)) char short_name, int recognizer_id, int chain_id) {
2448
2/2
✓ Branch 2 → 3 taken 7 times.
✓ Branch 2 → 4 taken 31 times.
38 if (recognizer_id != I360_RECOGNIZER_ID_COMMON)
2449 7 return 0;
2450
4/4
✓ Branch 4 → 5 taken 24 times.
✓ Branch 4 → 6 taken 7 times.
✓ Branch 5 → 6 taken 7 times.
✓ Branch 5 → 7 taken 17 times.
31 if ((chain_id < PHP_IMUNITY_MIN_ID) || (chain_id > PHP_IMUNITY_MAX_ID))
2451 14 return 0;
2452
2/2
✓ Branch 7 → 8 taken 1 time.
✓ Branch 7 → 9 taken 16 times.
17 if (!fname)
2453 1 return 0;
2454
2455
2/2
✓ Branch 9 → 10 taken 2 times.
✓ Branch 9 → 11 taken 14 times.
16 if (!strcmp(fname, "file_get_contents"))
2456 2 return 1;
2457
2458
2/2
✓ Branch 11 → 12 taken 2 times.
✓ Branch 11 → 13 taken 12 times.
14 if (strcmp(fname, "fopen"))
2459 2 return 0;
2460
2/2
✓ Branch 14 → 15 taken 2 times.
✓ Branch 14 → 16 taken 10 times.
12 if (i360_get_params_new_numb() < 2)
2461 2 return 0;
2462 10 int index = 1;
2463 10 int len = 0;
2464 10 char *prm = i360_get_params_index_new(&index, &len);
2465
3/6
✓ Branch 17 → 18 taken 10 times.
✗ Branch 17 → 20 not taken.
✓ Branch 18 → 19 taken 10 times.
✗ Branch 18 → 20 not taken.
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 21 taken 10 times.
10 if (!prm || len == 0 || len > 2)
2466 return 0;
2467
2468 // check is read
2469 10 char sym0 = prm[0];
2470 10 char sym1 = 0;
2471
2/2
✓ Branch 21 → 22 taken 6 times.
✓ Branch 21 → 23 taken 4 times.
10 if (len > 1)
2472 6 sym1 = prm[1];
2473 10 sym0 = (char)tolower((unsigned char)sym0);
2474
4/4
✓ Branch 23 → 24 taken 6 times.
✓ Branch 23 → 26 taken 4 times.
✓ Branch 24 → 25 taken 4 times.
✓ Branch 24 → 26 taken 2 times.
10 if (sym0 == 'r' && sym1 != '+')
2475 4 return 1;
2476 6 return 0;
2477 }
2478
2479 #define MAX_PEPARED_BUFER_LEN 4096
2480 #define MAX_PREPARED_ARRAY_LEN 100
2481 #define MIN_NEEDED_DATA 20
2482
2483 static char prepared_data_buffer[MAX_PREPARED_ARRAY_LEN][MAX_PEPARED_BUFER_LEN] = {{0}};
2484 static int last_free_in_prepared_buffer = 0;
2485 static int prepared_data_buffer_done = 0;
2486
2487 1 void i360_clear_prepared_buffer() {
2488 1 memset(prepared_data_buffer, 0, sizeof(prepared_data_buffer));
2489 1 last_free_in_prepared_buffer = 0;
2490 1 prepared_data_buffer_done = 0;
2491 1 }
2492
2493 1 void i360_fix_prepared_buffer() {
2494 1 prepared_data_buffer_done = last_free_in_prepared_buffer;
2495 1 }
2496
2497 // 1 - data added successfully
2498 // -1 - no place for new static data
2499 // 0 - no data added, data is empty
2500 83 int i360_add_prepared_buffer_req_data(char *data) {
2501
2/2
✓ Branch 2 → 3 taken 82 times.
✓ Branch 2 → 6 taken 1 time.
83 if (data) {
2502
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 5 taken 80 times.
82 if (last_free_in_prepared_buffer >= (MAX_PREPARED_ARRAY_LEN - MIN_NEEDED_DATA)) {
2503 2 return -1;
2504 }
2505 80 strncpy(prepared_data_buffer[last_free_in_prepared_buffer], data, MAX_PEPARED_BUFER_LEN - 1);
2506 80 last_free_in_prepared_buffer++;
2507 #if MIN_NEEDED_DATA == 0
2508 if (last_free_in_prepared_buffer >= MAX_PREPARED_ARRAY_LEN)
2509 last_free_in_prepared_buffer = MAX_PREPARED_ARRAY_LEN - 1;
2510 #endif
2511 80 return 1;
2512 }
2513 else {
2514 1 return 0;
2515 }
2516 return 0;
2517 }
2518
2519 1 void i360_restore_buffer_for_dynamic() {
2520 1 last_free_in_prepared_buffer = prepared_data_buffer_done;
2521 1 }
2522
2523 // 1 - data added successfully
2524 // -1 - no place for new dyn data
2525 // 0 - no data added, data is empty
2526 24 int i360_add_prepared_buffer_dyn_data(char *data) {
2527
2/2
✓ Branch 2 → 3 taken 23 times.
✓ Branch 2 → 6 taken 1 time.
24 if (data) {
2528
2/2
✓ Branch 3 → 4 taken 2 times.
✓ Branch 3 → 5 taken 21 times.
23 if (last_free_in_prepared_buffer >= MAX_PREPARED_ARRAY_LEN) {
2529 2 return -1;
2530 };
2531 21 strncpy(prepared_data_buffer[last_free_in_prepared_buffer], data, MAX_PEPARED_BUFER_LEN - 1);
2532 21 last_free_in_prepared_buffer++;
2533 21 return 1;
2534 }
2535 else {
2536 1 return 0;
2537 }
2538 return 0;
2539 }
2540
2541 2 int i360_is_prepared_buffer_fixed() {
2542 2 return prepared_data_buffer_done;
2543 }
2544
2545 6 int i360_prepared_buffer_length() {
2546 6 return last_free_in_prepared_buffer;
2547 }
2548
2549 2 char *i360_prepared_buffer_get(int index) {
2550
3/4
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 4 not taken.
✓ Branch 3 → 4 taken 1 time.
✓ Branch 3 → 5 taken 1 time.
2 if (index < 0 || index >= last_free_in_prepared_buffer)
2551 1 return NULL;
2552 1 return (char *)prepared_data_buffer[index];
2553 }
2554
2555 #include "hs_runtime.h"
2556 #include "database.h"
2557
2558 static int database_fd = -1;
2559 static size_t database_size = 0;
2560 static const i360_pd_database_t *database = NULL;
2561 static hs_scratch_t *scratch = NULL;
2562
2563 4 long i360_get_current_db_sig() {
2564
2/2
✓ Branch 2 → 3 taken 1 time.
✓ Branch 2 → 4 taken 3 times.
4 if (database)
2565 1 return (long)database->id;
2566
2/2
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 2 times.
3 if (parms_data_g_ptr)
2567 1 return parms_data_g_ptr->signs;
2568 2 return 0;
2569 }
2570
2571 static inline
2572 412 const void *i360_pd_database_ptr(i360_pd_database_offset_t offset) {
2573
4/4
✓ Branch 2 → 3 taken 402 times.
✓ Branch 2 → 5 taken 10 times.
✓ Branch 3 → 4 taken 397 times.
✓ Branch 3 → 5 taken 5 times.
412 return (const void *)(offset != 0 && offset != UINT64_MAX ? &((const char*)database)[offset] : NULL);
2574 }
2575
2576 5 static hs_scratch_t *scratch_alloc() {
2577 const void *hs;
2578 5 hs_scratch_t *scratch = NULL;
2579 5 const i360_pd_database_offset_t *hss = i360_pd_database_ptr(database->hs);
2580
2/2
✓ Branch 10 → 4 taken 25 times.
✓ Branch 10 → 11 taken 5 times.
30 while ((hs = i360_pd_database_ptr(*(hss++))) != NULL) {
2581
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 8 taken 25 times.
25 if (hs_alloc_scratch((const hs_database_t *)hs, &scratch) != HS_SUCCESS) {
2582 hs_free_scratch(scratch);
2583 return NULL;
2584 }
2585 }
2586 5 return scratch;
2587 }
2588
2589 6 void i360_pd_set_v2_database_paths(char *global_path, char *agent_path) {
2590
1/2
✓ Branch 2 → 3 taken 6 times.
✗ Branch 2 → 4 not taken.
6 if (global_path) {
2591 6 v2_database_paths[0] = global_path;
2592 }
2593
2/2
✓ Branch 4 → 5 taken 1 time.
✓ Branch 4 → 6 taken 5 times.
6 if (agent_path) {
2594 1 v2_database_paths[1] = agent_path;
2595 }
2596 6 }
2597
2598 5 int i360_pd_database_init() {
2599 struct {
2600 const char *bin_f;
2601 5 } options[] = {{v2_database_paths[0]}, {v2_database_paths[1]}}, *next = &options[1];
2602 struct stat rules_vers_st, rules_pack_st;
2603 5 int rules_ver_rc = stat(options[0].bin_f, &rules_vers_st);
2604 5 int rules_pack_rc = stat(options[1].bin_f, &rules_pack_st);
2605
2/4
✓ Branch 4 → 5 taken 5 times.
✗ Branch 4 → 7 not taken.
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 7 taken 5 times.
5 if ((rules_pack_rc == -1) && (rules_ver_rc == -1)) { // no files at all
2606 return 0;
2607 }
2608
2/4
✓ Branch 7 → 8 taken 5 times.
✗ Branch 7 → 10 not taken.
✓ Branch 8 → 9 taken 5 times.
✗ Branch 8 → 10 not taken.
5 else if ((!rules_ver_rc) && (rules_pack_rc == -1)) { // no global rule only agent
2609 5 next = &options[0];
2610 }
2611 else if ((!rules_ver_rc) && (rules_vers_st.st_mtime >= rules_pack_st.st_mtime)) { // global present by agents more new
2612 // or equal
2613 next = &options[0];
2614 } // by default use global. erlier set
2615 5 strncpy(current_db_path, next->bin_f, I360_PATH_BUFF-1);
2616
2617
1/2
✗ Branch 14 → 15 not taken.
✓ Branch 14 → 16 taken 5 times.
5 if (hs_valid_platform() != HS_SUCCESS)
2618 return 0;
2619
2620
1/2
✗ Branch 16 → 17 not taken.
✓ Branch 16 → 18 taken 5 times.
5 if (scratch) {
2621 hs_free_scratch(scratch);
2622 }
2623
2624
1/2
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 5 times.
5 if (database) {
2625 munmap((void *)database, database_size);
2626 }
2627
2628
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 22 taken 5 times.
5 if (database_fd >= 0) {
2629 close(database_fd);
2630 }
2631
2632 struct stat sb;
2633 5 int fd = open(next->bin_f, O_RDONLY);
2634
1/2
✗ Branch 23 → 24 not taken.
✓ Branch 23 → 25 taken 5 times.
5 if (fd == -1)
2635 return 0;
2636
1/2
✗ Branch 26 → 27 not taken.
✓ Branch 26 → 29 taken 5 times.
5 if (fstat(fd, &sb) == -1) {
2637 close(fd);
2638 return 0;
2639 }
2640 5 void *ptr = mmap((void *)database, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
2641
1/2
✗ Branch 30 → 31 not taken.
✓ Branch 30 → 33 taken 5 times.
5 if (ptr == MAP_FAILED) {
2642 close(fd);
2643 return 0;
2644 }
2645 5 database = (const i360_pd_database_t *)ptr;
2646
2/4
✓ Branch 33 → 34 taken 5 times.
✗ Branch 33 → 35 not taken.
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 38 taken 5 times.
5 if (database->sign != I360_PD_DATABASE_SIGN || database->ver != I360_PD_DATABASE_VER) {
2647 munmap(ptr, sb.st_size);
2648 close(fd);
2649 database = NULL;
2650 return 0;
2651 }
2652 5 database_fd = fd;
2653 5 database_size = sb.st_size;
2654 5 scratch = scratch_alloc();
2655 5 return 1;
2656 }
2657
2658 59 void i360_pd_database_deinit() {
2659
2/2
✓ Branch 2 → 3 taken 5 times.
✓ Branch 2 → 4 taken 54 times.
59 if (scratch)
2660 5 hs_free_scratch(scratch);
2661
2/2
✓ Branch 4 → 5 taken 5 times.
✓ Branch 4 → 6 taken 54 times.
59 if (database != NULL)
2662 5 munmap((void *)database, database_size);
2663
2/2
✓ Branch 6 → 7 taken 5 times.
✓ Branch 6 → 8 taken 54 times.
59 if (database_fd != -1)
2664 5 close(database_fd);
2665 59 scratch = NULL;
2666 59 database = NULL;
2667 59 database_fd = -1;
2668 59 database_size = 0;
2669 59 }
2670
2671 3 static int is_group_enabled(const i360_pd_database_rule_group_t *group, int app_id, int enabled_group) {
2672
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 3 times.
3 if (!group)
2673 return 0;
2674
3/4
✓ Branch 4 → 5 taken 2 times.
✓ Branch 4 → 7 taken 1 time.
✓ Branch 5 → 6 taken 2 times.
✗ Branch 5 → 7 not taken.
3 if ((group->id == enabled_group) && (enabled_group))
2675 2 return 1;
2676
1/2
✓ Branch 7 → 8 taken 1 time.
✗ Branch 7 → 12 not taken.
1 if (group->enabled) {
2677
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 11 taken 1 time.
1 if (app_id) {
2678 if (group->app_id == app_id) {
2679 return 1;
2680 }
2681 }
2682 else {
2683 1 return 1;
2684 }
2685 }
2686 return 0;
2687 }
2688
2689 struct _match_context {
2690 uint64_t *bitmap;
2691 const char *val;
2692 size_t len;
2693 };
2694
2695 static const i360_pd_database_pcre_t *database_pcre(unsigned int offset) {
2696 const i360_pd_database_offset_t *list = i360_pd_database_ptr(database->pcre);
2697 return (const i360_pd_database_pcre_t *)i360_pd_database_ptr(list[offset]);
2698 }
2699
2700 static int match_set_index(unsigned int id, __attribute__((unused)) unsigned long long from,
2701 __attribute__((unused)) unsigned long long to, __attribute__((unused)) unsigned int flags,
2702 void *context) {
2703 struct _match_context *mctx = (struct _match_context *)context;
2704 uint64_t *bitmap = mctx->bitmap;
2705 if (id >= (unsigned int)database->index_pcre) {
2706 unsigned int offset = id - (unsigned int)database->index_pcre;
2707 const i360_pd_database_pcre_t *p = database_pcre(offset);
2708 int subStrVec[30];
2709 int pcreExecRet = pcre_exec((const pcre *)p->pcre, (const pcre_extra *)i360_pd_database_ptr(p->pcre_extra),
2710 mctx->val, mctx->len, 0, PCRE_ANCHORED | PCRE_NO_START_OPTIMIZE, subStrVec, 30);
2711 id = p->index;
2712 if (pcreExecRet <= 0)
2713 return HS_SUCCESS;
2714 }
2715 I360_BITMAP_BIT_SET(bitmap, id);
2716 return HS_SUCCESS;
2717 }
2718
2719 static int match_set_index_exclude_list_args(unsigned int id, __attribute__((unused)) unsigned long long from,
2720 __attribute__((unused)) unsigned long long to,
2721 __attribute__((unused)) unsigned int flags, void *context) {
2722 struct _match_context *mctx = (struct _match_context *)context;
2723 uint64_t *bitmap = mctx->bitmap;
2724 if (id >= (unsigned int)database->index_pcre) {
2725 unsigned int offset = id - (unsigned int)database->index_pcre;
2726 const i360_pd_database_pcre_t *p = database_pcre(offset);
2727 int subStrVec[30];
2728 int pcreExecRet = pcre_exec((const pcre *)p->pcre, (const pcre_extra *)i360_pd_database_ptr(p->pcre_extra),
2729 mctx->val, mctx->len, 0, PCRE_ANCHORED | PCRE_NO_START_OPTIMIZE, subStrVec, 30);
2730 if (pcreExecRet <= 0)
2731 return HS_SUCCESS;
2732 }
2733 I360_BITMAP_BIT_SET(bitmap, I360_PD_DATABASE_EXCLUDE_LIST_ARGS_BIT);
2734 I360_BITMAP_BIT_RESET(bitmap, I360_PD_DATABASE_EXCLUDE_LIST_ARGS_NEGATIVE_BIT);
2735 return HS_SCAN_TERMINATED;
2736 }
2737
2738 static int match_set_index_exclude_list_script(unsigned int id, __attribute__((unused)) unsigned long long from,
2739 __attribute__((unused)) unsigned long long to,
2740 __attribute__((unused)) unsigned int flags, void *context) {
2741 struct _match_context *mctx = (struct _match_context *)context;
2742 uint64_t *bitmap = mctx->bitmap;
2743 if (id >= (unsigned int)database->index_pcre) {
2744 unsigned int offset = id - (unsigned int)database->index_pcre;
2745 const i360_pd_database_pcre_t *p = database_pcre(offset);
2746 int subStrVec[30];
2747 int pcreExecRet = pcre_exec((const pcre *)p->pcre, (const pcre_extra *)i360_pd_database_ptr(p->pcre_extra),
2748 mctx->val, mctx->len, 0, PCRE_ANCHORED | PCRE_NO_START_OPTIMIZE, subStrVec, 30);
2749 if (pcreExecRet <= 0)
2750 return HS_SUCCESS;
2751 }
2752 I360_BITMAP_BIT_RESET(bitmap, I360_PD_DATABASE_EXCLUDE_LIST_SCRIPT_NEGATIVE_BIT);
2753 return HS_SUCCESS;
2754 }
2755
2756 static int match_set_index_domain_blak_list_args(unsigned int id, __attribute__((unused)) unsigned long long from,
2757 __attribute__((unused)) unsigned long long to,
2758 __attribute__((unused)) unsigned int flags, void *context) {
2759 struct _match_context *mctx = (struct _match_context *)context;
2760 uint64_t *bitmap = mctx->bitmap;
2761 if (id >= (unsigned int)database->index_pcre) {
2762 unsigned int offset = id - (unsigned int)database->index_pcre;
2763 const i360_pd_database_pcre_t *p = database_pcre(offset);
2764 int subStrVec[30];
2765 int pcreExecRet = pcre_exec((const pcre *)p->pcre, (const pcre_extra *)i360_pd_database_ptr(p->pcre_extra),
2766 mctx->val, mctx->len, 0, PCRE_ANCHORED | PCRE_NO_START_OPTIMIZE, subStrVec, 30);
2767 if (pcreExecRet <= 0)
2768 return HS_SUCCESS;
2769 }
2770 I360_BITMAP_BIT_SET(bitmap, I360_PD_DATABASE_BLACK_LIST_BIT);
2771 return HS_SCAN_TERMINATED;
2772 }
2773
2774 3 static hs_error_t match_scan(i360_pd_database_offset_t offset, const char *data, unsigned int length,
2775 match_event_handler onEvent, uint64_t *bitmap) {
2776 3 const void *db = i360_pd_database_ptr(offset);
2777
1/2
✗ Branch 3 → 4 not taken.
✓ Branch 3 → 5 taken 3 times.
3 if (db == NULL)
2778 return HS_INVALID;
2779 3 struct _match_context mctx = {.bitmap = bitmap, .val = data, .len = length};
2780 3 return hs_scan((const hs_database_t *)db, mctx.val, mctx.len, 0, scratch, onEvent, &mctx);
2781 }
2782
2783 3 static const i360_pd_database_rule_t *match_rules(const i360_pd_database_func_t *func, const char *queue,
2784 size_t queue_len, int level, int enabled_group,
2785 3 uint64_t *conditions) {
2786 3 int app_id = i360_get_app_id();
2787 3 const char *script = cur_php_fname;
2788 3 size_t script_len = 0;
2789
2790 // Rules match bitmap: 1 means rule triggered, 0 rule did not trigger
2791 3 uint64_t bitmap[database->index_size];
2792 3 memcpy(bitmap, i360_pd_database_ptr(database->index_init), database->index_size * 8);
2793
2794 3 bitmap[0] |= func->conditions & (I360_PD_DATABASE_DETECT | I360_PD_DATABASE_ARG | I360_PD_DATABASE_SCRIPT);
2795
2796
1/2
✓ Branch 4 → 5 taken 3 times.
✗ Branch 4 → 6 not taken.
3 if (script)
2797 3 script_len = strlen(script);
2798
2799
1/2
✓ Branch 6 → 7 taken 3 times.
✗ Branch 6 → 8 not taken.
3 if (I360_CONDITION_BIT_ISSET(func->conditions, I360_PD_DATABASE_DETECT_BIT)) {
2800 3 match_scan(func->hs_detect_re, queue, queue_len, match_set_index, bitmap);
2801 }
2802
1/2
✗ Branch 8 → 9 not taken.
✓ Branch 8 → 19 taken 3 times.
3 if (I360_CONDITION_BIT_ISSET(func->conditions, I360_PD_DATABASE_ARG_BIT)) {
2803 if (i360_get_params_new_numb()) {
2804 int index = 0;
2805 int len = 0;
2806 char *prm = i360_get_params_new(&index, &len);
2807 while (index != -1) {
2808 hs_error_t rv = match_scan(func->hs_args_re, prm, len, match_set_index, bitmap);
2809 if (rv != HS_SUCCESS)
2810 break;
2811 prm = i360_get_params_new(&index, &len);
2812 }
2813 }
2814 }
2815
1/4
✗ Branch 19 → 20 not taken.
✓ Branch 19 → 22 taken 3 times.
✗ Branch 20 → 21 not taken.
✗ Branch 20 → 22 not taken.
3 if (I360_CONDITION_BIT_ISSET(func->conditions, I360_PD_DATABASE_SCRIPT_BIT) && script_len) {
2816 match_scan(func->hs_script_re, script, script_len, match_set_index, bitmap);
2817 }
2818
1/4
✗ Branch 22 → 23 not taken.
✓ Branch 22 → 28 taken 3 times.
✗ Branch 24 → 25 not taken.
✗ Branch 24 → 28 not taken.
3 if (I360_CONDITION_BIT_ISSET(func->conditions, I360_PD_DATABASE_FILE_OP_NAME_BIT) && i360_get_params_new_numb()) {
2819 int index = 0;
2820 int len = 0;
2821 char *prm = i360_get_params_new(&index, &len);
2822 match_scan(func->hs_file_op_name_re, prm, len, match_set_index, bitmap);
2823 }
2824
1/4
✗ Branch 28 → 29 not taken.
✓ Branch 28 → 34 taken 3 times.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 34 not taken.
3 if (I360_CONDITION_BIT_ISSET(func->conditions, I360_PD_DATABASE_FILE_OP_CONTENT_BIT) && i360_get_params_new_numb() > 1) {
2825 int index = 1;
2826 int len = 0;
2827 char *prm = i360_get_params_new(&index, &len);
2828 match_scan(func->hs_file_op_content_re, prm, len, match_set_index, bitmap);
2829 }
2830
1/4
✗ Branch 34 → 35 not taken.
✓ Branch 34 → 46 taken 3 times.
✗ Branch 36 → 37 not taken.
✗ Branch 36 → 46 not taken.
3 if (I360_PD_CONDITION_INCLUDES(func->conditions, I360_PD_DATABASE_EXCLUDE_LIST_ARGS | I360_PD_DATABASE_EXCLUDE_LIST_ARGS_NEGATIVE) &&
2831 i360_get_params_new_numb()) {
2832 int index = 0;
2833 int len = 0;
2834 char *prm = i360_get_params_new(&index, &len);
2835 while (index != -1) {
2836 if (len > G_MIN_HANDLE_STRING_SIZE) {
2837 hs_error_t rv = match_scan(database->hs_exclude_list, prm, len, match_set_index_exclude_list_args, bitmap);
2838 if (rv != HS_SUCCESS) {
2839 break;
2840 }
2841 }
2842 prm = i360_get_params_new(&index, &len);
2843 }
2844 }
2845
1/6
✗ Branch 46 → 47 not taken.
✓ Branch 46 → 50 taken 3 times.
✗ Branch 47 → 48 not taken.
✗ Branch 47 → 50 not taken.
✗ Branch 48 → 49 not taken.
✗ Branch 48 → 50 not taken.
3 if (I360_CONDITION_BIT_ISSET(func->conditions, I360_PD_DATABASE_EXCLUDE_LIST_SCRIPT_NEGATIVE_BIT) && script &&
2846 script_len > G_MIN_HANDLE_STRING_SIZE) {
2847 match_scan(database->hs_exclude_list, script, script_len, match_set_index_exclude_list_script, bitmap);
2848 }
2849
1/4
✗ Branch 50 → 51 not taken.
✓ Branch 50 → 63 taken 3 times.
✗ Branch 52 → 53 not taken.
✗ Branch 52 → 63 not taken.
3 if (I360_CONDITION_BIT_ISSET(func->conditions, I360_PD_DATABASE_BLACK_LIST_BIT) && i360_get_params_new_numb()) {
2850 char domain[MAX_DOMAIN_NAME] = {0};
2851 int index = 0;
2852 int len = 0;
2853 char *prm = i360_get_params_new(&index, &len);
2854 while (index != -1) {
2855 if (len > G_MIN_HANDLE_STRING_SIZE) {
2856 i360_extract_domain_name(prm, domain, MAX_DOMAIN_NAME);
2857 hs_error_t rv =
2858 match_scan(database->hs_black_list, domain, strlen(domain), match_set_index_domain_blak_list_args, bitmap);
2859 if (rv != HS_SUCCESS) {
2860 break;
2861 }
2862 }
2863 prm = i360_get_params_new(&index, &len);
2864 }
2865 }
2866
1/2
✗ Branch 63 → 64 not taken.
✓ Branch 63 → 68 taken 3 times.
3 if (I360_CONDITION_BIT_ISSET(func->conditions, I360_PD_DATABASE_MAIL_BIT)) {
2867 if (i360_check_mail_heuristic(i360_pd_database_ptr(func->name)))
2868 I360_BITMAP_BIT_SET(bitmap, I360_PD_DATABASE_MAIL_BIT);
2869 }
2870
1/2
✗ Branch 68 → 69 not taken.
✓ Branch 68 → 81 taken 3 times.
3 if (I360_CONDITION_BIT_ISSET(func->conditions, I360_PD_DATABASE_FOPEN_READ_NEGATIVE_BIT)) {
2871 const void *fopen = i360_pd_database_ptr(database->fopen);
2872 if (fopen && fopen == (const void *)func) {
2873 if (i360_get_params_new_numb() > 1) {
2874 int index = 1;
2875 int len = 0;
2876 char *prm = i360_get_params_new(&index, &len);
2877 if (((len == 1) && !strncmp(prm, "r", 1)) || ((len == 2) && !strncmp(prm, "rb", 2))) {
2878 I360_BITMAP_BIT_RESET(bitmap, I360_PD_DATABASE_FOPEN_READ_NEGATIVE_BIT);
2879 }
2880 }
2881 }
2882 }
2883
1/2
✗ Branch 81 → 82 not taken.
✓ Branch 81 → 85 taken 3 times.
3 if (I360_PD_CONDITION_INCLUDES(func->conditions, I360_PD_DATABASE_BLOCK | I360_PD_DATABASE_BLOCK_EXCLUDE)) {
2884 if (i360_precheck_params_for_inclusion())
2885 I360_BITMAP_BIT_SET(bitmap, I360_PD_DATABASE_BLOCK_BIT);
2886 }
2887
1/2
✗ Branch 85 → 86 not taken.
✓ Branch 85 → 90 taken 3 times.
3 if (I360_CONDITION_BIT_ISSET(func->conditions, I360_PD_DATABASE_BLOCK_EXCLUDE_BIT)) {
2888 if (I360_BITMAP_BIT_ISSET(bitmap, I360_PD_DATABASE_BLOCK_BIT) || i360_check_exclude_list())
2889 I360_BITMAP_BIT_SET(bitmap, I360_PD_DATABASE_BLOCK_EXCLUDE_BIT);
2890 }
2891
2892 3 const i360_pd_database_offset_t *rules = func->rules;
2893 3 const i360_pd_database_fp_rule_t *fp = (const i360_pd_database_fp_rule_t *)i360_pd_database_ptr(*rules);
2894 // False positive rules
2895
1/2
✗ Branch 100 → 92 not taken.
✓ Branch 100 → 101 taken 3 times.
3 while (fp) {
2896 int i;
2897 int match = 1;
2898 for (i = 0; i < database->index_size; i++) {
2899 if ((bitmap[i] & fp->bitmap[i]) != fp->bitmap[i]) {
2900 match = 0;
2901 break;
2902 }
2903 }
2904 if (match) {
2905 I360_BITMAP_BIT_RESET(bitmap, I360_PD_DATABASE_FALSE_POSITIVE_BIT);
2906 I360_BITMAP_BIT_RESET(bitmap, fp->index);
2907 }
2908
2909 fp = (const i360_pd_database_fp_rule_t *)i360_pd_database_ptr(*(++rules));
2910 }
2911
2912 // Rules
2913 const i360_pd_database_rule_t *rule;
2914
2/2
✓ Branch 139 → 102 taken 3 times.
✓ Branch 139 → 140 taken 3 times.
6 while ((rule = (const i360_pd_database_rule_t *)i360_pd_database_ptr(*(++rules))) != NULL) {
2915
2/4
✓ Branch 104 → 105 taken 3 times.
✗ Branch 104 → 137 not taken.
✗ Branch 105 → 106 not taken.
✓ Branch 105 → 137 taken 3 times.
3 if (is_group_enabled(i360_pd_database_ptr(rule->group), app_id, enabled_group) && (rule->level >= level)) {
2916 int i;
2917 int match = 1;
2918 for (i = 0; i < database->index_size; i++) {
2919 if ((bitmap[i] & rule->bitmap[i]) != rule->bitmap[i]) {
2920 match = 0;
2921 break;
2922 }
2923 }
2924
2925 // Those files which names are whitelisted, we exclude
2926 // exclude them from regex search. Bitmask is used
2927 if (cur_wl_rules && (WHITELIST_FILE_VER3 == wl_version) &&
2928 (!((unsigned int *)cur_wl_rules)[0] ||
2929 bsearch(&(rule->id), cur_wl_rules, MAX_WHITELIST_RULES, sizeof(int), i360_wl_item_comp)))
2930 continue;
2931
2932 if (cur_wl_rules && (WHITELIST_FILE_VER4 == wl_version) && *(unsigned char *)cur_wl_rules &&
2933 (!((unsigned int *)(cur_wl_rules + 1))[0] ||
2934 bsearch(&(rule->id), cur_wl_rules + 1, *(unsigned char *)cur_wl_rules, sizeof(int), i360_wl_item_comp)))
2935 continue;
2936
2937 // Apply super-rules to every whitelist item
2938 if (super_wl_rules && (WHITELIST_FILE_VER3 == wl_version) &&
2939 bsearch(&(rule->id), super_wl_rules, MAX_WHITELIST_RULES, sizeof(int), i360_wl_item_comp))
2940 continue;
2941
2942 if (super_wl_rules && (WHITELIST_FILE_VER4 == wl_version) && super_wl_rules[0] &&
2943 bsearch(&(rule->id), super_wl_rules + 1, *(unsigned char *)super_wl_rules, sizeof(int), i360_wl_item_comp))
2944 continue;
2945
2946 if (match) {
2947 return rule;
2948 }
2949 }
2950 }
2951
2952
1/2
✓ Branch 140 → 141 taken 3 times.
✗ Branch 140 → 142 not taken.
3 if (conditions)
2953 3 *conditions = bitmap[0];
2954
2955 3 return NULL;
2956 }
2957
2958 #ifndef UNIT_TESTING
2959 static inline
2960 #endif
2961 3 int i360_pd_database_is_args_requirde(const void *dbfunc) {
2962 3 const i360_pd_database_func_t *func = (const i360_pd_database_func_t *)dbfunc;
2963 3 return I360_PD_CONDITION_INCLUDES(func->conditions, I360_PD_DATABASE_ARG_BITS) ? 1 : 0;
2964 }
2965
2966 #ifndef UNIT_TESTING
2967 static inline
2968 #endif
2969 4 int i360_pd_database_is_write_log(const void *dbfunc) {
2970 4 const i360_pd_database_func_t *func = (const i360_pd_database_func_t *)dbfunc;
2971 4 return I360_CONDITION_BIT_ISSET(func->conditions, I360_PD_DATABASE_WRITE_LOG_BIT) ? 1 : 0;
2972 }
2973
2974 3 void i360_pd_database_make_info(const void *dbfunc, char *info) {
2975 3 const i360_pd_database_func_t *func = (const i360_pd_database_func_t *)dbfunc;
2976 3 info[0] = func->letter;
2977
2/2
✓ Branch 2 → 3 taken 2 times.
✓ Branch 2 → 4 taken 1 time.
3 info[1] = func->conditions != 0 ? 'd' : '0';
2978 3 info[2] = '0' + 16 * i360_pd_database_is_args_requirde(dbfunc) +
2979 3 16 * i360_pd_database_is_write_log(dbfunc);
2980 //if (i360_pd_database_is_args_requirde(dbfunc)) {
2981 //info[2] += 16;
2982 //}
2983 3 }
2984
2985 3 void i360_pd_database_check(chain_result *result, const void *dbfunc, const char *queue, size_t queue_len, int logger,
2986 int level, int enabled_group) {
2987 3 uint64_t conditions = 0;
2988 3 const i360_pd_database_func_t *func = (const i360_pd_database_func_t *)dbfunc;
2989 3 memset(result, 0, sizeof(chain_result));
2990 3 result->danger_type = NODANGER;
2991 3 result->recognizer_id = I360_RECOGNIZER_ID_NONE;
2992
2993 /*
2994 * rule stats from 0 to 255 shows how long rules applies to function, where function detects as number by ascii letter
2995 */
2996 3 i360_ull rule_timer = 0;
2997 3 i360_counter_saver_savetimer(&rule_timer);
2998 3 const i360_pd_database_rule_t *rule = match_rules(func, queue, queue_len, level, enabled_group, &conditions);
2999 3 i360_counter_saver_add_rule((unsigned int)((unsigned int)func->letter + STAT_SHIFTER_FUNC), rule_timer);
3000
1/2
✗ Branch 5 → 6 not taken.
✓ Branch 5 → 17 taken 3 times.
3 if (rule) {
3001 if (I360_PD_CONDITION_INCLUDES(rule->bitmap[0], I360_PD_DATABASE_ARG_BITS)) {
3002 // Database V1 code uppercase the letters with matching arguments. We have to do the same
3003 // to enable more sophisticated rules after a function was blocked by args
3004 i360_queue_buffer_uppercase_last();
3005 }
3006 if ((rule->action == BLOCK_FUNC) || (rule->id >= PHP_IMUNITY_MIN_ID && rule->id <= PHP_IMUNITY_MAX_ID)) {
3007 result->block = 1;
3008 }
3009 if (rule->action != NO_ACTION && I360_BITMAP_BIT_ISSET(rule->bitmap, I360_PD_DATABASE_BLOCK_EXCLUDE_BIT)) {
3010 result->block = 2;
3011 }
3012 result->recognizer_id = I360_RECOGNIZER_ID_COMMON;
3013 result->chain_id = rule->id;
3014 result->danger_type = DANGER;
3015 result->recognizer_desr = I360_RECOGNIZER_ID_COMMON_DESC;
3016 result->ruldescr = (char *)i360_pd_database_ptr(rule->description);
3017 }
3018
1/2
✓ Branch 17 → 18 taken 3 times.
✗ Branch 17 → 29 not taken.
3 else if (I360_CONDITION_BIT_ISSET(conditions, I360_PD_DATABASE_FALSE_POSITIVE_BIT)) {
3019 3 rules_list *rules = i360_script_default_recognizer(i360_pd_database_ptr(func->name), queue, queue_len);
3020
1/2
✗ Branch 20 → 21 not taken.
✓ Branch 20 → 29 taken 3 times.
3 if (rules) {
3021 if ((rules->action == BLOCK_FUNC) || (rules->id >= PHP_IMUNITY_MIN_ID && rules->id <= PHP_IMUNITY_MAX_ID)) {
3022 result->block = 1;
3023 }
3024 if (rules->action != NO_ACTION && rules->check_blocked == 2) {
3025 result->block = 2;
3026 }
3027 result->recognizer_id = I360_RECOGNIZER_ID_COMMON;
3028 result->chain_id = rules->id;
3029 result->danger_type = DANGER;
3030 result->recognizer_desr = I360_RECOGNIZER_ID_COMMON_DESC;
3031 result->ruldescr = rules->description;
3032 }
3033 }
3034
3035
2/6
✓ Branch 29 → 30 taken 3 times.
✗ Branch 29 → 33 not taken.
✗ Branch 31 → 32 not taken.
✓ Branch 31 → 34 taken 3 times.
✗ Branch 32 → 33 not taken.
✗ Branch 32 → 34 not taken.
3 if ((result->chain_id >= G_NON_LOG_RULE_ID) || (i360_is_rce_logger_log_mode() && (result->danger_type == DANGER))) {
3036 result->recognizer_id = I360_RECOGNIZER_ID_INTERNAL;
3037 result->recognizer_desr = I360_RECOGNIZER_ID_INTERNAL_DESC;
3038 }
3039
3040
1/2
✓ Branch 34 → 35 taken 3 times.
✗ Branch 34 → 38 not taken.
3 if (logger) {
3041
1/2
✗ Branch 35 → 36 not taken.
✓ Branch 35 → 37 taken 3 times.
3 if (result->danger_type) {
3042 result->action = LOG_ONLY;
3043 }
3044 else {
3045 3 result->recognizer_desr = I360_RECOGNIZER_ID_LOG_DESC;
3046 3 result->action = LOG_ONLY;
3047 3 result->recognizer_id = I360_RECOGNIZER_ID_LOG;
3048 3 result->chain_id = 0;
3049 3 result->danger_type = DANGER;
3050 }
3051 }
3052 3 }
3053
3054 2 int i360_pd_database_check_rinit(chain_result *result, int level, int enabled_group, const char *queue,
3055 size_t queue_len) {
3056
1/2
✓ Branch 2 → 3 taken 2 times.
✗ Branch 2 → 4 not taken.
2 if (!database)
3057 2 return 0;
3058
3059 const i360_pd_database_func_t *rinit = i360_pd_database_ptr(database->rinit);
3060
3061 if (!rinit)
3062 return 1;
3063
3064 i360_ull rule_timer = 0;
3065 i360_counter_saver_savetimer(&rule_timer);
3066 const i360_pd_database_rule_t *rule = match_rules(rinit, queue, queue_len, level, enabled_group, NULL);
3067 i360_counter_saver_add_rule((unsigned int)STAT_RINIT_RULESCHECK_TIME, rule_timer);
3068 if (rule) {
3069 if ((rule->action == BLOCK_FUNC) || (rule->id >= PHP_IMUNITY_MIN_ID && rule->id <= PHP_IMUNITY_MAX_ID)) {
3070 result->block = 1;
3071 }
3072 if (rule->action != NO_ACTION && I360_BITMAP_BIT_ISSET(rule->bitmap, I360_PD_DATABASE_BLOCK_EXCLUDE_BIT)) {
3073 result->block = 2;
3074 }
3075 result->recognizer_id = I360_RECOGNIZER_ID_COMMON;
3076 result->chain_id = rule->id;
3077 result->danger_type = DANGER;
3078 result->recognizer_desr = I360_RECOGNIZER_ID_COMMON_DESC;
3079 result->ruldescr = (char *)i360_pd_database_ptr(rule->description);
3080 }
3081
3082 return 1;
3083 }
3084
3085 4 int i360_pd_database_func_foreach(void (*f)(const char *key, const char *val, int is_danger, int is_openwrite,
3086 const void *dbfunc)) {
3087
1/2
✗ Branch 2 → 3 not taken.
✓ Branch 2 → 4 taken 4 times.
4 if (!database)
3088 return 0;
3089
3090 4 const i360_pd_database_func_t *func = i360_pd_database_ptr(database->fopen);
3091
1/2
✓ Branch 5 → 6 taken 4 times.
✗ Branch 5 → 8 not taken.
4 if (func != NULL)
3092 4 f(i360_pd_database_ptr(func->name), NULL, (int)(func->letter != 0),
3093 4 I360_CONDITION_BIT_ISSET(func->conditions, I360_PD_DATABASE_WRITE_LOG_BIT), func);
3094 4 const i360_pd_database_offset_t *funcs = database->list;
3095
2/2
✓ Branch 12 → 9 taken 172 times.
✓ Branch 12 → 13 taken 4 times.
176 while ((func = i360_pd_database_ptr(*(funcs++))) != NULL)
3096 172 f(i360_pd_database_ptr(func->name), NULL, (int)(func->letter != 0),
3097 172 I360_CONDITION_BIT_ISSET(func->conditions, I360_PD_DATABASE_WRITE_LOG_BIT), func);
3098
3099 4 return 1;
3100 }
3101
3102 uint8_t i360_env_gencrc(uint8_t *data) {
3103 uint8_t crc = 0xff;
3104 size_t i, j;
3105 i = 0;
3106 while (data[i]) {
3107 crc ^= data[i];
3108 for (j = 0; j < 8; j++) {
3109 if ((crc & 0x80) != 0)
3110 crc = (uint8_t)((crc << 1) ^ 0x31);
3111 else
3112 crc <<= 1;
3113 }
3114 i++;
3115 }
3116 return crc;
3117 }
3118
3119 130 int i360_need_save_env_variable(char *variable_name, int var_len) {
3120 130 int len = var_len;
3121 130 char *fnd_eq = strchr(variable_name, '=');
3122 130 int result = 0;
3123
2/2
✓ Branch 2 → 3 taken 124 times.
✓ Branch 2 → 5 taken 6 times.
130 if (fnd_eq) {
3124 124 len = fnd_eq - variable_name;
3125
1/2
✓ Branch 3 → 4 taken 124 times.
✗ Branch 3 → 5 not taken.
124 if (len < var_len) {
3126 124 var_len = len;
3127 }
3128 }
3129 130 result = (i360_env_filter_check(variable_name, var_len) != NULL);
3130 130 return result;
3131 }
3132
3133 static int database_version = 0;
3134 /*
3135 * 0 - old database
3136 * 1 - new hyperscan database
3137 */
3138 63 void i360_set_database_version(int db_version) {
3139 63 database_version = db_version;
3140 63 }
3141
3142 2 int i360_get_database_version() {
3143 2 return database_version;
3144 }
3145