From 69905421581c1c90476a79e2bb65a927a19604d0 Mon Sep 17 00:00:00 2001 From: liuchang Date: Mon, 25 Nov 2024 01:53:48 +0000 Subject: [PATCH] add api maat_state_need_compile --- include/maat.h | 1 + src/inc_internal/maat_rule.h | 4 +- src/maat_api.c | 21 ++++++++- src/maat_rule.c | 89 ++++++++++++++++++++++++++++------- test/maat_framework_gtest.cpp | 30 +++++++----- 5 files changed, 114 insertions(+), 31 deletions(-) diff --git a/include/maat.h b/include/maat.h index 43b1296..2ab1b83 100644 --- a/include/maat.h +++ b/include/maat.h @@ -297,6 +297,7 @@ struct maat_state *maat_state_new(struct maat *instance, int thread_id); * @param n_result: the size of rule_array and ex_data_array */ size_t maat_state_compile(struct maat_state *state, const char *table_name, uuid_t rule_array[], size_t n_result); +int maat_state_need_compile(struct maat_state *state, const char *table_name); void maat_state_reset(struct maat_state *state); diff --git a/src/inc_internal/maat_rule.h b/src/inc_internal/maat_rule.h index d3952ca..0486c42 100644 --- a/src/inc_internal/maat_rule.h +++ b/src/inc_internal/maat_rule.h @@ -51,9 +51,11 @@ long long rule_runtime_rule_count(void *rule_runtime); long long rule_runtime_update_err_count(void *rule_runtime); -int rule_runtime_match(struct rule_runtime *rule_rt, uuid_t *rule_uuids, +int rule_runtime_match(int table_id, struct rule_runtime *rule_rt, uuid_t *rule_uuids, size_t rule_ids_size, struct maat_state *state); +int rule_runtime_need_compile(int table_id, struct rule_runtime *rule_rt, struct rule_compile_state *rule_compile_state); + size_t rule_runtime_get_hit_paths(struct rule_runtime *rule_rt, int thread_id, struct rule_compile_state *rule_compile_state, struct maat_hit_path *hit_path_array, diff --git a/src/maat_api.c b/src/maat_api.c index b4b30d1..abe40d1 100644 --- a/src/maat_api.c +++ b/src/maat_api.c @@ -1182,7 +1182,7 @@ size_t maat_state_compile(struct maat_state *state, const char *table_name, uuid return 0; } - int rule_num = rule_runtime_match((struct rule_runtime *)rule_rt, rule_array, n_result, state); + int rule_num = rule_runtime_match(table_id, (struct rule_runtime *)rule_rt, rule_array, n_result, state); if (rule_num > 0) { alignment_int64_array_add(state->maat_inst->stat->hit_rule_cnt, state->thread_id, rule_num); } @@ -1190,6 +1190,25 @@ size_t maat_state_compile(struct maat_state *state, const char *table_name, uuid return rule_num; } +int maat_state_need_compile(struct maat_state *state, const char *table_name) +{ + if (state == NULL || state->maat_inst == NULL) { + return 0; + } + + int table_id = maat_get_table_id(state->maat_inst, table_name); + if (table_id < 0) { + return 0; + } + + void *rule_rt = table_manager_get_runtime(state->maat_inst->tbl_mgr, table_id); + if (NULL == rule_rt) { + return 0; + } + + return rule_runtime_need_compile(table_id, (struct rule_runtime *)rule_rt, state->rule_compile_state); +} + int maat_scan_flag(struct maat *maat_inst, const char *table_name, const char *attribute_name, long long flag, struct maat_state *state) { diff --git a/src/maat_rule.c b/src/maat_rule.c index 4f51e86..14394b2 100644 --- a/src/maat_rule.c +++ b/src/maat_rule.c @@ -80,6 +80,14 @@ struct attribute_hit_object_collection { UT_hash_handle hh; }; +struct rule_compile_runtime_state { + int table_id;//key + time_t rule_rt_version; + int hit_object_changed; + int need_scan_not_logic; + UT_hash_handle hh; +}; + /* rule_runtime and object2rule_runtime share rule_hash_map */ struct rule_runtime { struct bool_matcher *bm; @@ -136,12 +144,12 @@ struct internal_hit_path { struct rule_compile_state { int Nth_scan; - time_t rule_rt_version; UT_array *internal_hit_paths; UT_array *all_hit_conditions; UT_array *exclude_not_conditions; struct attribute_hit_object_collection *attr_hit_objects_hashtbl; + struct rule_compile_runtime_state *rule_runtime_state_hash; }; static UT_icd ut_condition_id_icd = {sizeof(long long), NULL, NULL, NULL}; @@ -761,13 +769,8 @@ maat_rule_bool_matcher_match(struct rule_runtime *rule_rt, (thread_id * MAX_HIT_RULE_NUM); assert(thread_id >= 0); - if (0 == rule_compile_state->rule_rt_version) { - rule_compile_state->rule_rt_version = rule_rt->version; - } - if (NULL == rule_rt->bm || - 0 == utarray_len(rule_compile_state->all_hit_conditions) || - rule_compile_state->rule_rt_version != rule_rt->version) { + 0 == utarray_len(rule_compile_state->all_hit_conditions)) { return 0; } @@ -812,7 +815,6 @@ void rule_compile_state_reset(struct rule_compile_state *rule_compile_state) } rule_compile_state->Nth_scan = 0; - rule_compile_state->rule_rt_version = 0; utarray_clear(rule_compile_state->internal_hit_paths); utarray_clear(rule_compile_state->all_hit_conditions); @@ -836,6 +838,13 @@ void rule_compile_state_reset(struct rule_compile_state *rule_compile_state) attr_hit_obj->need_scan_not_object = 0; attr_hit_obj->Nth_scan = 0; } + + struct rule_compile_runtime_state *rule_runtime_state = NULL, *tmp_rule_runtime_state = NULL; + HASH_ITER(hh, rule_compile_state->rule_runtime_state_hash, rule_runtime_state, tmp_rule_runtime_state) { + rule_runtime_state->rule_rt_version = 0; + rule_runtime_state->hit_object_changed = 0; + rule_runtime_state->need_scan_not_logic = 0; + } } void rule_compile_state_free(struct rule_compile_state *rule_compile_state, @@ -892,6 +901,13 @@ void rule_compile_state_free(struct rule_compile_state *rule_compile_state, FREE(attr_hit_obj); } + struct rule_compile_runtime_state *rule_runtime_state = NULL, *tmp_rule_runtime_state = NULL; + HASH_ITER(hh, rule_compile_state->rule_runtime_state_hash, rule_runtime_state, tmp_rule_runtime_state) { + HASH_DEL(rule_compile_state->rule_runtime_state_hash, rule_runtime_state); + free_bytes += sizeof(struct rule_compile_runtime_state); + FREE(rule_runtime_state); + } + FREE(rule_compile_state); free_bytes += sizeof(struct rule_compile_state); @@ -1070,10 +1086,6 @@ size_t rule_runtime_get_hit_paths(struct rule_runtime *rule_rt, int thread_id, (thread_id * MAX_HIT_RULE_NUM); assert(thread_id >= 0); - if (rule_compile_state->rule_rt_version != rule_rt->version) { - return 0; - } - int bool_match_ret = bool_matcher_match(rule_rt->bm, (unsigned long long *)utarray_eltptr(rule_compile_state->all_hit_conditions, 0), @@ -1497,7 +1509,7 @@ static int compare_rule_item(const void *a, const void *b) return rule_sort_para_compare(&sa, &sb); } -int rule_runtime_match(struct rule_runtime *rule_rt, uuid_t *rule_uuids, +int rule_runtime_match(int table_id, struct rule_runtime *rule_rt, uuid_t *rule_uuids, size_t rule_ids_size, struct maat_state *state) { struct rule_compile_state *rule_compile_state = state->rule_compile_state; @@ -1506,6 +1518,21 @@ int rule_runtime_match(struct rule_runtime *rule_rt, uuid_t *rule_uuids, utarray_clear(rule_compile_state->all_hit_conditions); utarray_clear(rule_compile_state->exclude_not_conditions); + + struct rule_compile_runtime_state *rule_compile_rt_state = NULL; + HASH_FIND_INT(rule_compile_state->rule_runtime_state_hash, &table_id, rule_compile_rt_state); + if (rule_compile_rt_state == NULL) { + rule_compile_rt_state = ALLOC(struct rule_compile_runtime_state, 1); + rule_compile_rt_state->table_id = table_id; + HASH_ADD_INT(rule_compile_state->rule_runtime_state_hash, table_id, rule_compile_rt_state); + } + + rule_compile_rt_state->hit_object_changed = 0; + rule_compile_rt_state->need_scan_not_logic = 0; + + if (rule_compile_rt_state->rule_rt_version != rule_rt->version) { + rule_compile_rt_state->rule_rt_version = rule_rt->version; + } struct attribute_hit_object_collection *attr_hit_obj_coll = NULL, *tmp = NULL; HASH_ITER(hh, rule_compile_state->attr_hit_objects_hashtbl, attr_hit_obj_coll, tmp) { @@ -1588,6 +1615,26 @@ int rule_runtime_match(struct rule_runtime *rule_rt, uuid_t *rule_uuids, return MIN(bool_match_ret, rule_ids_size); } +int rule_runtime_need_compile(int table_id, struct rule_runtime *rule_rt, struct rule_compile_state *rule_compile_state) +{ + struct rule_compile_runtime_state *rule_compile_rt_state = NULL; + + HASH_FIND_INT(rule_compile_state->rule_runtime_state_hash, &table_id, rule_compile_rt_state); + if (rule_compile_rt_state == NULL || rule_compile_rt_state->rule_rt_version == 0) {//haven't compiled yet, need compile + return 1; + } + + if (rule_compile_rt_state->rule_rt_version != rule_rt->version) { + return 0; + } + + if (rule_compile_rt_state->hit_object_changed || rule_compile_rt_state->need_scan_not_logic) { + return 1; + } + + return 0; +} + static struct attribute_hit_object_collection * rule_compile_state_get_attr_hit_obj_coll(struct maat *maat_inst, struct rule_compile_state *rule_compile_state, const char *attribute_name) { @@ -1608,7 +1655,7 @@ static struct attribute_hit_object_collection * rule_compile_state_get_attr_hit_ return attr_hit_obj_coll; } -static void rule_compile_state_add_hit_objects(struct rule_compile_state *rule_compile_state, +static int rule_compile_state_add_hit_objects(struct rule_compile_state *rule_compile_state, struct attribute_hit_object_collection * attr_hit_obj_coll, uuid_t object_uuids[], size_t n_object_uuids) { @@ -1635,7 +1682,7 @@ static void rule_compile_state_add_hit_objects(struct rule_compile_state *rule_c utarray_sort(attr_hit_obj_coll->all_object_uuids, compare_object_uuid); } - return; + return object_uuid_idx_array_len; } int rule_compile_state_update(struct rule_compile_state *rule_compile_state, struct maat *maat_inst, @@ -1680,7 +1727,12 @@ int rule_compile_state_update(struct rule_compile_state *rule_compile_state, str uuid_copy(hit_object_uuids[hit_cnt++], super_object_uuids[j]); } - rule_compile_state_add_hit_objects(rule_compile_state, attr_hit_obj_coll, hit_object_uuids, hit_cnt); + if (rule_compile_state_add_hit_objects(rule_compile_state, attr_hit_obj_coll, hit_object_uuids, hit_cnt) > 0) { + struct rule_compile_runtime_state *rule_compile_rt_state = NULL, *tmp = NULL; + HASH_ITER(hh, rule_compile_state->rule_runtime_state_hash, rule_compile_rt_state, tmp) { + rule_compile_rt_state->hit_object_changed = 1; + } + } return hit_cnt; } @@ -1698,6 +1750,11 @@ void rule_compile_state_not_logic_update(struct maat *maat_inst, struct rule_com attr_hit_obj_coll->need_scan_not_object = 1; attr_hit_obj_coll->Nth_scan = Nth_scan; + struct rule_compile_runtime_state *rule_compile_rt_state = NULL, *tmp = NULL; + HASH_ITER(hh, rule_compile_state->rule_runtime_state_hash, rule_compile_rt_state, tmp) { + rule_compile_rt_state->need_scan_not_logic = 1; + } + return; } diff --git a/test/maat_framework_gtest.cpp b/test/maat_framework_gtest.cpp index 1883adb..41c879d 100644 --- a/test/maat_framework_gtest.cpp +++ b/test/maat_framework_gtest.cpp @@ -9610,14 +9610,18 @@ TEST_F(MaatCmd, UpdateDeadLockDetection) { memset(results, 0, sizeof(results)); ret = maat_scan_string(maat_inst, table_http_url, attribute_http_url, scan_data2, strlen(scan_data2), state); - //After full update, condition ids are re-orgnized, therefore mid are not compatible to the new scanner (hierarchy). + EXPECT_EQ(ret, MAAT_SCAN_HIT); ret = maat_scan_not_logic(maat_inst, table_http_url, attribute_http_url, state); EXPECT_EQ(ret, MAAT_SCAN_OK); n_hit_result = maat_state_compile(state, default_rule_table_name, results, ARRAY_SIZE); - EXPECT_EQ(n_hit_result, 0); + EXPECT_EQ(n_hit_result, 2); + uuid_unparse(results[0], uuid_str); + EXPECT_STREQ(uuid_str, rule2_uuid_str); + uuid_unparse(results[1], uuid_str); + EXPECT_STREQ(uuid_str, rule1_uuid_str); maat_state_free(state); state = NULL; @@ -9973,10 +9977,6 @@ TEST_F(MaatCmd, IPAndStreamScanWhenFullUpdate) { ret = maat_scan_not_logic(maat_inst, expr_table_name, expr_attribute_name, state); EXPECT_EQ(ret, MAAT_SCAN_OK); - /* maat_state keep the rule_rt version when maat_state_new(). - After full updating, new rule_rt version is different from that of maat_state, - so MAAT_SCAN_HIT will never happen. - */ ret = maat_scan_ipv4(maat_inst, ip_table_name, ip_attribute_name, ip_addr, state); EXPECT_EQ(ret, MAAT_SCAN_HIT); @@ -9984,7 +9984,10 @@ TEST_F(MaatCmd, IPAndStreamScanWhenFullUpdate) { EXPECT_EQ(ret, MAAT_SCAN_OK); n_hit_result = maat_state_compile(state, default_rule_table_name, results, ARRAY_SIZE); - EXPECT_EQ(n_hit_result, 0); + EXPECT_EQ(n_hit_result, 1); + char uuid_str[UUID_STR_LEN] = {0}; + uuid_unparse(results[0], uuid_str); + EXPECT_STREQ(uuid_str, rule1_uuid_str); maat_stream_free(stream); maat_state_free(state); @@ -10185,12 +10188,11 @@ TEST_F(MaatCmd, IPAndStringScanWhenFullupdate) { EXPECT_EQ(ret, MAAT_SCAN_OK); n_hit_result = maat_state_compile(state, default_rule_table_name, results, ARRAY_SIZE); - EXPECT_EQ(n_hit_result, 0); + EXPECT_EQ(n_hit_result, 1); + char uuid_str[UUID_STR_LEN] = {0}; + uuid_unparse(results[0], uuid_str); + EXPECT_STREQ(uuid_str, rule1_uuid_str); - /* maat_state keep the rule_rt version when maat_state_new(). - After full updating, new rule_rt version is different from that of maat_state, - so MAAT_SCAN_HIT will never happen. - */ ret = maat_scan_ipv4(maat_inst, ip_table_name, ip_attribute_name, ip_addr, state); EXPECT_EQ(ret, MAAT_SCAN_HIT); @@ -10198,7 +10200,9 @@ TEST_F(MaatCmd, IPAndStringScanWhenFullupdate) { EXPECT_EQ(ret, MAAT_SCAN_OK); n_hit_result = maat_state_compile(state, default_rule_table_name, results, ARRAY_SIZE); - EXPECT_EQ(n_hit_result, 0); + EXPECT_EQ(n_hit_result, 1); + uuid_unparse(results[0], uuid_str); + EXPECT_STREQ(uuid_str, rule1_uuid_str); maat_state_free(state); state = NULL;