static void dump_exec_selection_rules(ruletree_object_offset_t offs, int indent) { ruletree_exec_policy_selection_rule_t *rule = offset_to_ruletree_object_ptr( offs, SB2_RULETREE_OBJECT_TYPE_EXEC_SEL_RULE); if (rule_dumped[offs]) { print_indent(indent + 1); printf("[ => @ %u]\n", offs); return; } rule_dumped[offs] = 1; print_indent(indent); printf("{ Exec policy selection rule[%u]:\n", (unsigned)offs); print_indent(indent+1); printf("type = 0x%X\n", rule->rtree_xps_type); if (rule->rtree_xps_selector_offs) { print_indent(indent+1); printf("selector = '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_xps_selector_offs, NULL)); } if (rule->rtree_xps_exec_policy_name_offs) { print_indent(indent+1); printf("exec_policy_name = '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_xps_exec_policy_name_offs, NULL)); } print_indent(indent+1); printf("flags = 0x%X\n", rule->rtree_xps_flags); print_indent(indent); printf("}\n"); }
static int if_exists_in(ruletree_fsrule_t *action, const char *abs_clean_virtual_path) { const char *map_to_target; char *test_path = NULL; map_to_target = offset_to_ruletree_string_ptr(action->rtree_fsr_action_offs, NULL); if (!strcmp(map_to_target, "/")) { test_path = strdup(abs_clean_virtual_path); } else { if (asprintf(&test_path, "%s%s", map_to_target, abs_clean_virtual_path) < 0) { LB_LOG(LB_LOGLEVEL_ERROR, "asprintf failed"); return(0); } } if (lb_path_exists(test_path)) { LB_LOG(LB_LOGLEVEL_DEBUG, "if_exists_in: True '%s' -> proceed to then_actions", test_path); free(test_path); return (1); } LB_LOG(LB_LOGLEVEL_DEBUG, "if_exists_in: False '%s'", test_path); free(test_path); return(0); }
static int if_exists_then_replace_by( ruletree_fsrule_t *action, ruletree_fsrule_t *rule_selector, const char *abs_clean_virtual_path, char **resultp) { char *test_path; const char *replacement = NULL; *resultp = NULL; replacement = offset_to_ruletree_string_ptr(action->rtree_fsr_action_offs, NULL); test_path = ruletree_execute_replace_rule(abs_clean_virtual_path, replacement, rule_selector); if (!test_path) return(0); if (lb_path_exists(test_path)) { LB_LOG(LB_LOGLEVEL_DEBUG, "if_exists_then_replace_by: True '%s'", test_path); *resultp = test_path; return(1); } LB_LOG(LB_LOGLEVEL_DEBUG, "if_exists_then_replace_by: False '%s'", test_path); free(test_path); return(0); }
static int if_exists_then_map_to(ruletree_fsrule_t *action, const char *abs_clean_virtual_path, char **resultp) { const char *map_to_target; char *test_path = NULL; *resultp = NULL; map_to_target = offset_to_ruletree_string_ptr(action->rtree_fsr_action_offs, NULL); if (!strcmp(map_to_target, "/")) { test_path = strdup(abs_clean_virtual_path); } else { if (asprintf(&test_path, "%s%s", map_to_target, abs_clean_virtual_path) < 0) { SB_LOG(SB_LOGLEVEL_ERROR, "asprintf failed"); return(0); } } if (sb_path_exists(test_path)) { SB_LOG(SB_LOGLEVEL_DEBUG, "if_exists_then_map_to: True '%s'", test_path); *resultp = test_path; return(1); } SB_LOG(SB_LOGLEVEL_DEBUG, "if_exists_then_map_to: False '%s'", test_path); free(test_path); return(0); }
static void dump_exec_pp_rules(ruletree_object_offset_t offs, int indent) { ruletree_exec_preprocessing_rule_t *rule = offset_to_exec_preprocessing_rule_ptr(offs); if (rule_dumped[offs]) { print_indent(indent + 1); printf("[ => @ %u]\n", offs); return; } rule_dumped[offs] = 1; print_indent(indent); printf("{ Exec preprocessing rule[%u]:\n", (unsigned)offs); if (rule->rtree_xpr_binary_name_offs) { print_indent(indent+1); printf("binary_name = '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_xpr_binary_name_offs, NULL)); } #define EXECPP_PRINT_LIST(name, field) \ if (rule->field) { \ print_indent(indent+1); \ printf(name " = {\n"); \ dump_objectlist(rule->field, indent + 2); \ print_indent(indent+1); \ printf("}\n"); \ } EXECPP_PRINT_LIST("path_prefixes", rtree_xpr_path_prefixes_table_offs) EXECPP_PRINT_LIST("add_head", rtree_xpr_add_head_table_offs) EXECPP_PRINT_LIST("add_options", rtree_xpr_add_options_table_offs) EXECPP_PRINT_LIST("add_tail", rtree_xpr_add_tail_table_offs) EXECPP_PRINT_LIST("remove", rtree_xpr_remove_table_offs) if (rule->rtree_xpr_new_filename_offs) { print_indent(indent+1); printf("new_filename = '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_xpr_new_filename_offs, NULL)); } if (rule->rtree_xpr_disable_mapping) { print_indent(indent+1); printf("disable_mapping = true\n"); } print_indent(indent); printf("}\n"); }
static void dump_objectlist(ruletree_object_offset_t list_offs, int indent) { uint32_t list_size = ruletree_objectlist_get_list_size(list_offs); uint32_t i; const char *cp; print_indent(indent); printf("{ list[%u], size=%u:\n", (unsigned)list_offs, list_size); for (i = 0; i < list_size; i++) { ruletree_object_offset_t item_offs; item_offs = ruletree_objectlist_get_item(list_offs, i); print_indent(indent); printf("#%d:\n", i); if (item_offs) { ruletree_object_hdr_t *hdr = offset_to_ruletree_object_ptr( item_offs, 0/*any type is ok*/); if (hdr) { switch (hdr->rtree_obj_type) { case SB2_RULETREE_OBJECT_TYPE_OBJECTLIST: print_indent(indent+1); printf("List:\n"); dump_objectlist(item_offs, indent+2); break; case SB2_RULETREE_OBJECT_TYPE_FSRULE: print_indent(indent+1); printf("FS rule:\n"); dump_rules(item_offs, indent+2); break; case SB2_RULETREE_OBJECT_TYPE_EXEC_PP_RULE: dump_exec_pp_rules(item_offs, indent+1); break; case SB2_RULETREE_OBJECT_TYPE_EXEC_SEL_RULE: dump_exec_selection_rules(item_offs, indent+1); break; case SB2_RULETREE_OBJECT_TYPE_NET_RULE: dump_net_rules(item_offs, indent+1); break; case SB2_RULETREE_OBJECT_TYPE_STRING: print_indent(indent+1); printf("STRING "); cp = offset_to_ruletree_string_ptr(item_offs, NULL); if (cp) printf("'%s'\n", cp); else printf("NULL\n"); break; default: print_indent(indent+1); printf("Unsupported type\n"); break; } } } } print_indent(indent); printf("}\n"); }
/* returns an allocated buffer */ static char *ruletree_execute_replace_rule( const char *full_path, const char *replacement, ruletree_fsrule_t *rule) { char *new_path = NULL; uint32_t selector_len; const char *selector = offset_to_ruletree_string_ptr(rule->rtree_fsr_selector_offs, &selector_len); LB_LOG(LB_LOGLEVEL_DEBUG, "ruletree_execute_replace_rule: orig='%s',replacement='%s',selector='%s'", full_path, replacement,selector); switch (rule->rtree_fsr_selector_type) { case LB_RULETREE_FSRULE_SELECTOR_PREFIX: case LB_RULETREE_FSRULE_SELECTOR_DIR: if (asprintf(&new_path, "%s%s", replacement, full_path + selector_len) < 0) { LB_LOG(LB_LOGLEVEL_ERROR, "asprintf failed"); return(NULL); } return(new_path); case LB_RULETREE_FSRULE_SELECTOR_PATH: /* "path" may be shorter than prefix during path resolution */ if (!strcmp(full_path, selector)) { return(strdup(replacement)); } LB_LOG(LB_LOGLEVEL_DEBUG, "replacement failed"); return(NULL); default: LB_LOG(LB_LOGLEVEL_ERROR, "ruletree_execute_replace_rule: Unknown selector type %d", rule->rtree_fsr_selector_type); } return(NULL); }
static void print_ruletree_object_type(ruletree_object_offset_t obj_offs) { ruletree_object_hdr_t *hdr; hdr = offset_to_ruletree_object_ptr(obj_offs, 0/*any type is ok*/); if (hdr) { const char *cp; uint32_t *uip; switch (hdr->rtree_obj_type) { case SB2_RULETREE_OBJECT_TYPE_FILEHDR: printf("FILEHDR"); break; case SB2_RULETREE_OBJECT_TYPE_CATALOG: printf("CATALOG @%u", obj_offs); break; case SB2_RULETREE_OBJECT_TYPE_FSRULE: printf("FSRULE @%u", obj_offs); break; case SB2_RULETREE_OBJECT_TYPE_STRING: printf("STRING\t"); cp = offset_to_ruletree_string_ptr(obj_offs, NULL); if (cp) printf("'%s'", cp); else printf("NULL"); break; case SB2_RULETREE_OBJECT_TYPE_OBJECTLIST: printf("LIST @%u", obj_offs); break; case SB2_RULETREE_OBJECT_TYPE_BINTREE: printf("BINTREE @%u", obj_offs); break; case SB2_RULETREE_OBJECT_TYPE_INODESTAT: { ruletree_inodestat_t *fsp; fsp = (ruletree_inodestat_t*)hdr; if (fsp) { int a = fsp->rtree_inode_simu.inodesimu_active_fields; printf("INODESTAT: dev=%lld ino=%lld act=0x%X", (long long)fsp->rtree_inode_simu.inodesimu_dev, (long long)fsp->rtree_inode_simu.inodesimu_ino, a); if (a & RULETREE_INODESTAT_SIM_UID) printf(" uid=%d", (int)fsp->rtree_inode_simu.inodesimu_uid); if (a & RULETREE_INODESTAT_SIM_GID) printf(" gid=%d", (int)fsp->rtree_inode_simu.inodesimu_gid); if (a & RULETREE_INODESTAT_SIM_MODE) printf(" mode=0%o", (int)fsp->rtree_inode_simu.inodesimu_mode); if (a & RULETREE_INODESTAT_SIM_SUIDSGID) printf(" suid_sgid=0%o", (int)fsp->rtree_inode_simu.inodesimu_suidsgid); if (a & RULETREE_INODESTAT_SIM_DEVNODE) printf(" device_type=0%o rdev=0x%llX", (int)fsp->rtree_inode_simu.inodesimu_devmode, (long long)fsp->rtree_inode_simu.inodesimu_rdev); } else { printf("INODESTAT: <NULL>"); } } break; case SB2_RULETREE_OBJECT_TYPE_UINT32: uip = ruletree_get_pointer_to_uint32(obj_offs); if (uip) printf("UINT32 %u (0x%X)", *uip, *uip); else printf("UINT32 <none; got NULL pointer>"); break; case SB2_RULETREE_OBJECT_TYPE_BOOLEAN: uip = ruletree_get_pointer_to_boolean(obj_offs); if (uip) printf("BOOLEAN %s", *uip ? "true" : "false"); else printf("BOOLEAN <none; got NULL pointer>"); break; default: printf("<unknown type %d>", hdr->rtree_obj_type); break; } } else { printf("<invalid value offset>"); } }
static void dump_net_rules(ruletree_object_offset_t offs, int indent) { ruletree_net_rule_t *rule = offset_to_ruletree_object_ptr(offs, SB2_RULETREE_OBJECT_TYPE_NET_RULE); if (rule_dumped[offs]) { print_indent(indent + 1); printf("[ => @ %u]\n", offs); return; } rule_dumped[offs] = 1; print_indent(indent); printf("{ net rule[%u]:\n", (unsigned)offs); print_indent(indent + 1); switch(rule->rtree_net_ruletype) { case SB2_RULETREE_NET_RULETYPE_DENY: printf("ruletype = deny\n"); break; case SB2_RULETREE_NET_RULETYPE_ALLOW: printf("ruletype = allow\n"); break; case SB2_RULETREE_NET_RULETYPE_RULES: printf("ruletype = rules\n"); break; default: printf("ruletype = %d (UNKNOWN)\n", rule->rtree_net_ruletype); break; } if (rule->rtree_net_func_name) { print_indent(indent + 1); printf("func_name = '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_net_func_name, NULL)); } if (rule->rtree_net_binary_name) { print_indent(indent + 1); printf("binary_name = '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_net_binary_name, NULL)); } if (rule->rtree_net_address) { print_indent(indent + 1); printf("address = '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_net_address, NULL)); } if (rule->rtree_net_port) { print_indent(indent + 1); printf("port = %d\n", rule->rtree_net_port); } if (rule->rtree_net_new_address) { print_indent(indent + 1); printf("new_address = '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_net_new_address, NULL)); } if (rule->rtree_net_new_port) { print_indent(indent + 1); printf("new_port = %d\n", rule->rtree_net_new_port); } if (rule->rtree_net_log_msg) { print_indent(indent + 1); if (rule->rtree_net_log_level) { printf("log_level = %d, ", rule->rtree_net_log_level); } printf("log_msg = '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_net_log_msg, NULL)); } if (rule->rtree_net_errno) { print_indent(indent + 1); printf("errno = %d '%s'\n", rule->rtree_net_errno, strerror(rule->rtree_net_errno)); } if (rule->rtree_net_rules) { dump_objectlist(rule->rtree_net_rules, indent+1); } print_indent(indent); printf("}\n"); }
static int prepare_exec(const char *exec_fn_name, const char *exec_policy_name, const char *orig_file, int file_has_been_mapped, char *const *orig_argv, char *const *orig_envp, enum binary_type *typep, char **new_file, /* return value */ char ***new_argv, char ***new_envp) /* *new_envp must be filled by the caller */ { char **my_envp = *new_envp; /* FIXME */ const char **my_new_envp = NULL; const char **my_new_argv = NULL; char **my_argv = NULL, *my_file = NULL; char *binaryname, *tmp, *mapped_file; int err = 0; enum binary_type type; int postprocess_result = 0; int ret = 0; /* 0: ok to exec, ret<0: exec fails */ int file_mode; uid_t file_uid; gid_t file_gid; PROCESSCLOCK(clk1) PROCESSCLOCK(clk4) START_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk1, "prepare_exec"); (void)exec_fn_name; /* not yet used */ (void)orig_envp; /* not used */ SB_LOG(SB_LOGLEVEL_DEBUG, "prepare_exec(): orig_file='%s'", orig_file); SB_LOG(SB_LOGLEVEL_NOISE, "%s: exec_policy_name='%s'", __func__, exec_policy_name); tmp = strdup(orig_file); binaryname = strdup(basename(tmp)); /* basename may modify *tmp */ free(tmp); my_file = strdup(orig_file); my_argv = duplicate_argv(orig_argv); if (!file_has_been_mapped) { PROCESSCLOCK(clk2) START_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk2, "execve_preprocess"); if ((err = apply_exec_preprocessing_rules(&my_file, &my_argv, &my_envp)) != 0) { SB_LOG(SB_LOGLEVEL_ERROR, "argvenvp processing error %i", err); } STOP_AND_REPORT_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk2, my_file); } /* test if mapping is enabled during the exec().. * (host-* tools disable it) */ if (file_has_been_mapped) { /* (e.g. we came back from run_hashbang()) */ SB_LOG(SB_LOGLEVEL_DEBUG, "prepare_exec(): no double mapping, my_file = %s", my_file); mapped_file = strdup(my_file); } else if (strvec_contains_prefix(my_envp, "SBOX_DISABLE_MAPPING=1", NULL)) { SB_LOG(SB_LOGLEVEL_DEBUG, "do_exec(): mapping disabled, my_file = %s", my_file); mapped_file = strdup(my_file); /* we won't call sbox_map_path_for_exec() because mapping * is disabled. */ } else { /* now we have to do path mapping for my_file to find exactly * what is the path we're supposed to deal with */ mapping_results_t mapping_result; PROCESSCLOCK(clk3) clear_mapping_results_struct(&mapping_result); START_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk3, "map_path_for_exec"); sbox_map_path_for_exec("do_exec", my_file, &mapping_result); mapped_file = (mapping_result.mres_result_buf ? strdup(mapping_result.mres_result_buf) : NULL); exec_policy_name = (mapping_result.mres_exec_policy_name ? strdup(mapping_result.mres_exec_policy_name) : NULL); STOP_AND_REPORT_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk3, mapped_file); free_mapping_results(&mapping_result); SB_LOG(SB_LOGLEVEL_DEBUG, "do_exec(): my_file = %s, mapped_file = %s", my_file, mapped_file); } /* * prepare_envp_for_do_exec() left us placeholder in envp array * that we will fill now with fully mangled binary name. */ change_environment_variable(my_envp, "__SB2_REAL_BINARYNAME=", mapped_file); /* inspect the completely mangled filename */ type = inspect_binary(mapped_file, 1/*check_x_permission*/, &file_mode, &file_uid, &file_gid); if (typep) *typep = type; if (!exec_policy_name) { if ((type != BIN_INVALID) && (type != BIN_NONE)) { exec_policy_name = find_exec_policy_name(mapped_file, my_file); if (!exec_policy_name) { errno = ENOEXEC; ret = -1; SB_LOG(SB_LOGLEVEL_ERROR, "No exec policy (%s,%s) => ENOEXEC", my_file, mapped_file); goto out; } } } SB_LOG(SB_LOGLEVEL_DEBUG, "%s: exec_policy_name=%s", __func__, exec_policy_name); START_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk4, "exec/typeswitch"); switch (type) { case BIN_HASHBANG: SB_LOG(SB_LOGLEVEL_DEBUG, "Exec/hashbang %s", mapped_file); /* prepare_hashbang() will call prepare_exec() * recursively */ ret = prepare_hashbang(&mapped_file, my_file, &my_argv, &my_envp, exec_policy_name); break; case BIN_HOST_DYNAMIC: SB_LOG(SB_LOGLEVEL_DEBUG, "Exec/host-dynamic %s", mapped_file); #if 0 postprocess_result = sb_execve_postprocess("native", exec_policy_name, &mapped_file, &my_file, binaryname, &my_argv, &my_envp); #else postprocess_result = exec_postprocess_native_executable( exec_policy_name, &mapped_file, &my_file, binaryname, (const char **)my_argv, &my_new_argv, (const char **)*new_envp, &my_new_envp); my_envp = (char**)my_new_envp; /* FIXME */ my_argv = (char**)my_new_argv; /* FIXME */ #endif if (postprocess_result < 0) { errno = EINVAL; ret = -1; } else { simulate_suid_and_sgid_if_needed(mapped_file, my_envp, file_mode, file_uid, file_gid, 1/*host_compatible_binary*/); } break; case BIN_HOST_STATIC: #if 0 postprocess_result = sb_execve_postprocess("static", exec_policy_name, &mapped_file, &my_file, binaryname, &my_argv, &my_envp); #else { const char *namev_in_ruletree[4]; const char *cputransp_cmd = NULL; ruletree_object_offset_t cmd_offs; namev_in_ruletree[0] = "cputransparency"; namev_in_ruletree[1] = "native"; namev_in_ruletree[2] = "cmd"; namev_in_ruletree[3] = NULL; cmd_offs = ruletree_catalog_vget(namev_in_ruletree); if (cmd_offs) { cputransp_cmd = offset_to_ruletree_string_ptr(cmd_offs, NULL); } if (cputransp_cmd && (cputransp_cmd[0] != '\0')) { postprocess_result = exec_postprocess_cpu_transparency_executable( exec_policy_name, &mapped_file, &my_file, binaryname, (const char **)my_argv, &my_new_argv, (const char **)*new_envp, &my_new_envp, "native"); my_envp = (char**)my_new_envp; /* FIXME */ my_argv = (char**)my_new_argv; /* FIXME */ } else { const char *allow_static_bin = NULL; /* don't print warning, if this static binary * has been allowed (see the wrapper for * ldconfig - we don't want to see warnings * every time when someone executes that) */ allow_static_bin = getenv("SBOX_ALLOW_STATIC_BINARY"); if (allow_static_bin && !strcmp(allow_static_bin, mapped_file)) { /* no warnning, just debug */ SB_LOG(SB_LOGLEVEL_DEBUG, "statically linked " "native binary %s (allowed)", mapped_file); } else { SB_LOG(SB_LOGLEVEL_WARNING, "Executing statically " "linked native binary %s", mapped_file); } /* Add LD_LIBRARY_PATH and LD_PRELOAD. * the static binary itself does not need * these, but if it executes another * program, then there is at least some * hope of getting back to SB2. It won't * be able to start anything that runs * under CPU transparency, but host-compatible * binaries may be able to get back.. */ postprocess_result = exec_postprocess_host_static_executable( exec_policy_name, &mapped_file, &my_file, binaryname, (const char **)my_argv, &my_new_argv, (const char **)*new_envp, &my_new_envp); my_envp = (char**)my_new_envp; /* FIXME */ my_argv = (char**)my_new_argv; /* FIXME */ } } #endif if (postprocess_result < 0) { errno = EINVAL; ret = -1; } else { /* the static binary won't get SUID simulation, * but if it executes something else.. */ simulate_suid_and_sgid_if_needed(mapped_file, my_envp, file_mode, file_uid, file_gid, 1/*host_compatible_binary*/); } break; case BIN_TARGET: SB_LOG(SB_LOGLEVEL_DEBUG, "Exec/target %s", mapped_file); #if 0 postprocess_result = sb_execve_postprocess( "cpu_transparency", exec_policy_name, &mapped_file, &my_file, binaryname, &my_argv, &my_envp); #else postprocess_result = exec_postprocess_cpu_transparency_executable( exec_policy_name, &mapped_file, &my_file, binaryname, (const char **)my_argv, &my_new_argv, (const char **)*new_envp, &my_new_envp, "target"); my_envp = (char**)my_new_envp; /* FIXME */ my_argv = (char**)my_new_argv; /* FIXME */ #endif if (postprocess_result < 0) { errno = EINVAL; ret = -1; } else { simulate_suid_and_sgid_if_needed(mapped_file, my_envp, file_mode, file_uid, file_gid, 0/*not host_compatible_binary*/); } break; case BIN_INVALID: /* = can't be executed, no X permission */ /* don't even try to exec, errno has been set.*/ ret = -1; break; case BIN_NONE: /* file does not exist. errno has been set. */ ret = -1; break; case BIN_UNKNOWN: errno = ENOEXEC; ret = -1; SB_LOG(SB_LOGLEVEL_DEBUG, "Unidentified executable detected (%s) => ENOEXEC", mapped_file); break; } STOP_AND_REPORT_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk4, my_file); out: *new_file = mapped_file; *new_argv = my_argv; *new_envp = my_envp; STOP_AND_REPORT_PROCESSCLOCK(SB_LOGLEVEL_INFO, &clk1, orig_file); return(ret); }
static ruletree_object_offset_t ruletree_find_rule( const path_mapping_context_t *ctx, ruletree_object_offset_t rule_list_offs, const char *virtual_path, size_t virtual_path_len, int *min_path_lenp, uint32_t fn_class, ruletree_fsrule_t **rule_p) { uint32_t rule_list_size; uint32_t i; PROCESSCLOCK(clk1) START_PROCESSCLOCK(LB_LOGLEVEL_INFO, &clk1, "ruletree_find_rule"); LB_LOG(LB_LOGLEVEL_NOISE, "ruletree_find_rule for (%s)", virtual_path); rule_list_size = ruletree_objectlist_get_list_size(rule_list_offs); if (min_path_lenp) *min_path_lenp = 0; if (rule_p) *rule_p = NULL; if (rule_list_size == 0) return(0); for (i = 0; i < rule_list_size; i++) { ruletree_fsrule_t *rp; ruletree_object_offset_t rule_offs; rule_offs = ruletree_objectlist_get_item(rule_list_offs, i); if (!rule_offs) continue; rp = offset_to_ruletree_fsrule_ptr(rule_offs); if (rp) { int min_path_len; if (rp->rtree_fsr_condition_type != 0) { LB_LOG(LB_LOGLEVEL_DEBUG, "ruletree_find_rule: can't handle rules with conditions, fail. @%d", rule_offs); return(0); } if (rp->rtree_fsr_selector_type == 0) { LB_LOG(LB_LOGLEVEL_NOISE, "ruletree_find_rule skipping defunct rule @%d", rule_offs); continue; } min_path_len = ruletree_test_path_match(virtual_path, virtual_path_len, rp); if (min_path_len >= 0) { LB_LOG(LB_LOGLEVEL_NOISE, "ruletree_find_rule found rule @ %d", rule_offs); if (rp->rtree_fsr_func_class) { if ((rp->rtree_fsr_func_class & fn_class) == 0) { /* Function class does not match.. */ continue; } } if (rp->rtree_fsr_binary_name) { const char *bin_name_in_rule = offset_to_ruletree_string_ptr(rp->rtree_fsr_binary_name, NULL); if (strcmp(ctx->pmc_binary_name, bin_name_in_rule)) { /* binary name does not match, not this rule... */ continue; } } if (min_path_lenp) *min_path_lenp = min_path_len; if (rp->rtree_fsr_action_type == LB_RULETREE_FSRULE_ACTION_SUBTREE) { /* if rule can be found from the subtree, return it, * otherwise continue looping here */ if (rp->rtree_fsr_rule_list_link) { ruletree_object_offset_t subtree_offs; LB_LOG(LB_LOGLEVEL_NOISE, "ruletree_find_rule: continue @ %d", rp->rtree_fsr_rule_list_link); subtree_offs = ruletree_find_rule(ctx, rp->rtree_fsr_rule_list_link, virtual_path, virtual_path_len, min_path_lenp, fn_class, rule_p); if (subtree_offs) { STOP_AND_REPORT_PROCESSCLOCK( LB_LOGLEVEL_INFO, &clk1, "found/subtree"); return(subtree_offs); } } else { LB_LOG(LB_LOGLEVEL_NOISE, "ruletree_find_rule: no link"); } continue; } /* found it! */ if (rule_p) *rule_p = rp; STOP_AND_REPORT_PROCESSCLOCK( LB_LOGLEVEL_INFO, &clk1, "found"); return(rule_offs); } } } STOP_AND_REPORT_PROCESSCLOCK(LB_LOGLEVEL_INFO, &clk1, "not found"); return (0); /* failed to find it */ }
static char *ruletree_execute_conditional_actions( const path_mapping_context_t *ctx, int result_log_level, const char *abs_clean_virtual_path, int *flagsp, const char **exec_policy_name_ptr, const char **errormsgp, ruletree_fsrule_t *rule_selector) { uint32_t actions_list_size; uint32_t i; ruletree_object_offset_t action_list_offs = rule_selector->rtree_fsr_rule_list_link; /* FIXME: these are not yet used. */ (void)ctx; (void)result_log_level; (void)exec_policy_name_ptr; LB_LOG(LB_LOGLEVEL_NOISE, "ruletree_execute_conditional_actions for (%s)", abs_clean_virtual_path); actions_list_size = ruletree_objectlist_get_list_size(action_list_offs); if (actions_list_size == 0) { LB_LOG(LB_LOGLEVEL_DEBUG, "ruletree_execute_conditional_actions: action list not found or empty."); *errormsgp = "action list not found or empty."; return (NULL); } for (i = 0; i < actions_list_size; i++) { ruletree_fsrule_t *action_cand_p; ruletree_object_offset_t action_offs; action_offs = ruletree_objectlist_get_item(action_list_offs, i); if (!action_offs) continue; /* "rule_selector" is the rule which matched, and * brought us here (so it contains "dir","prefix" * or "path"). * Each member in the "actions" array is a * candidate for the rule which will be applied, * i.e. a suitable member from that array gives * instructions about what to do next */ action_cand_p = offset_to_ruletree_fsrule_ptr(action_offs); if (action_cand_p) { char *mapping_result; if (action_cand_p->rtree_fsr_condition_type != 0) { const char *cond_str; const char *evp; cond_str = offset_to_ruletree_string_ptr(action_cand_p->rtree_fsr_condition_offs, NULL); LB_LOG(LB_LOGLEVEL_NOISE, "Condition test '%s'", cond_str); switch (action_cand_p->rtree_fsr_condition_type) { case LB_RULETREE_FSRULE_CONDITION_IF_ENV_VAR_IS_NOT_EMPTY: if (!cond_str) continue; /* continue if no env.var.name */ evp = getenv(cond_str); if (!evp || !*evp) continue; /* continue if empty */ LB_LOG(LB_LOGLEVEL_NOISE, "Condition test: env.var was not empty"); break; /* else test passed. */ case LB_RULETREE_FSRULE_CONDITION_IF_ENV_VAR_IS_EMPTY: if (!cond_str) continue; /* continue if no env.var.name */ evp = getenv(cond_str); if (evp && *evp) continue; /* continue if not empty */ LB_LOG(LB_LOGLEVEL_NOISE, "Condition test: env.var was empty"); break; /* else test passed. */ case LB_RULETREE_FSRULE_CONDITION_IF_ACTIVE_EXEC_POLICY_IS: if (!cond_str || !ldbox_active_exec_policy_name || strcmp(cond_str, ldbox_active_exec_policy_name)) { /* exec policy name did not match */ continue; } LB_LOG(LB_LOGLEVEL_NOISE, "Condition test: exec policy name matched"); break; case LB_RULETREE_FSRULE_CONDITION_IF_REDIRECT_IGNORE_IS_ACTIVE: if (!cond_str) continue; /* continue if no path */ if (test_if_str_in_colon_separated_list_from_env( cond_str, "LDBOX_REDIRECT_IGNORE")) { LB_LOG(LB_LOGLEVEL_NOISE, "Condition test: redirect-ignore is active (%s)", cond_str); } else { LB_LOG(LB_LOGLEVEL_NOISE, "Condition test: redirect-ignore is NOT active (%s)", cond_str); continue; } break; case LB_RULETREE_FSRULE_CONDITION_IF_REDIRECT_FORCE_IS_ACTIVE: if (!cond_str) continue; /* continue if no path */ if (test_if_str_in_colon_separated_list_from_env( cond_str, "LDBOX_REDIRECT_FORCE")) { LB_LOG(LB_LOGLEVEL_NOISE, "Condition test: redirect-force is active (%s)", cond_str); } else { LB_LOG(LB_LOGLEVEL_NOISE, "Condition test: redirect-force is NOT active (%s)", cond_str); continue; } break; case LB_RULETREE_FSRULE_CONDITION_IF_EXISTS_IN: if (if_exists_in(action_cand_p, abs_clean_virtual_path)) { /* found, jump to the new rule tree branch */ ruletree_object_offset_t then_actions_offset = action_cand_p->rtree_fsr_rule_list_link; if (!then_actions_offset) { LB_LOG(LB_LOGLEVEL_DEBUG, "if_exists_in: no then_actions found"); /* continue with normal rule tree */ continue; } else { LB_LOG(LB_LOGLEVEL_DEBUG, "if_exists_in: then_actions found (%d)", then_actions_offset); ruletree_fsrule_t new_rules = *rule_selector; new_rules.rtree_fsr_rule_list_link = then_actions_offset; return ruletree_execute_conditional_actions(ctx, result_log_level, abs_clean_virtual_path, flagsp, exec_policy_name_ptr, errormsgp, &new_rules); } } /* not found, continue with normal rule tree */ continue; break; default: LB_LOG(LB_LOGLEVEL_ERROR, "ruletree_execute_conditional_actions: " " unknown condition %d @%d", action_cand_p->rtree_fsr_condition_type, action_offs); goto unimplemented_action_error; } } switch (action_cand_p->rtree_fsr_action_type) { case LB_RULETREE_FSRULE_ACTION_IF_EXISTS_THEN_MAP_TO: if (if_exists_then_map_to(action_cand_p, abs_clean_virtual_path, &mapping_result)) { return(mapping_result); } break; case LB_RULETREE_FSRULE_ACTION_IF_EXISTS_THEN_REPLACE_BY: if (if_exists_then_replace_by(action_cand_p, rule_selector, abs_clean_virtual_path, &mapping_result)) { return(mapping_result); } break; case LB_RULETREE_FSRULE_ACTION_USE_ORIG_PATH: case LB_RULETREE_FSRULE_ACTION_FORCE_ORIG_PATH: case LB_RULETREE_FSRULE_ACTION_FORCE_ORIG_PATH_UNLESS_CHROOT: case LB_RULETREE_FSRULE_ACTION_MAP_TO: case LB_RULETREE_FSRULE_ACTION_REPLACE_BY: case LB_RULETREE_FSRULE_ACTION_SET_PATH: case LB_RULETREE_FSRULE_ACTION_MAP_TO_VALUE_OF_ENV_VAR: case LB_RULETREE_FSRULE_ACTION_REPLACE_BY_VALUE_OF_ENV_VAR: case LB_RULETREE_FSRULE_ACTION_PROCFS: case LB_RULETREE_FSRULE_ACTION_UNION_DIR: return(execute_std_action(rule_selector, action_cand_p, abs_clean_virtual_path, flagsp)); default: /* FIXME */ goto unimplemented_action_error; } } } /* end of list is most probably a fatal error in the rule file. */ LB_LOG(LB_LOGLEVEL_ERROR, "ruletree_execute_conditional_actions: End of conditional action list, " "probably caused by an error in the rule file."); /* FIXME. This should probably return the original path (compare with * Lua code) */ *errormsgp = "End of conditional action list"; return (NULL); unimplemented_action_error: LB_LOG(LB_LOGLEVEL_ERROR, "Internal error: ruletree_execute_conditional_actions: Encountered " "an unknown conditional action."); *errormsgp = "unknown conditional action (internal error)"; return (NULL); }
/* Returns min.path length if a match is found, otherwise returns -1 */ static int ruletree_test_path_match(const char *full_path, size_t full_path_len, ruletree_fsrule_t *rp) { const char *selector = NULL; const char *match_type = "no match"; int result = -1; uint32_t selector_len; if (!rp || !full_path) { LB_LOG(LB_LOGLEVEL_NOISE, "ruletree_test_path_match fails"); return(-1); } LB_LOG(LB_LOGLEVEL_NOISE, "ruletree_test_path_match (%s), type=%d", full_path, rp->rtree_fsr_selector_type); selector = offset_to_ruletree_string_ptr(rp->rtree_fsr_selector_offs, &selector_len); switch (rp->rtree_fsr_selector_type) { case LB_RULETREE_FSRULE_SELECTOR_PATH: if (selector) { if ((selector_len == full_path_len) && !strcmp(full_path, selector)) { result = selector_len; match_type = "path"; } } break; case LB_RULETREE_FSRULE_SELECTOR_PREFIX: if (selector && (*selector != '\0')) { if ((full_path_len >= selector_len) && (full_path[selector_len-1] == selector[selector_len-1]) && !strncmp(full_path, selector, selector_len)) { result = selector_len; match_type = "prefix"; } } break; case LB_RULETREE_FSRULE_SELECTOR_DIR: if (selector && (*selector != '\0')) { /* test a directory prefix: the next char after the * prefix must be '\0' or '/', unless we are accessing * the root directory */ if ((full_path_len >= selector_len) && ((full_path[selector_len] == '/') || (full_path[selector_len] == '\0') || ((selector_len == 1) && (*full_path=='/'))) ) { if (!strncmp(full_path, selector, selector_len)) { result = selector_len; match_type = "dir"; } } } break; default: LB_LOG(LB_LOGLEVEL_ERROR, "ruletree_test_path_match: " "Unsupported selector type (rule='%s')", offset_to_ruletree_string_ptr(rp->rtree_fsr_name_offs, NULL)); return(-1); } LB_LOG(LB_LOGLEVEL_NOISE, "ruletree_test_path_match '%s' (%u), '%s' (%u) => %d (%s)", full_path, full_path_len, selector, selector_len, result, match_type); return(result); }
/* "standard actions" = use_orig_path, force_orig_path, map_to, replace_by */ static char *execute_std_action( ruletree_fsrule_t *rule_selector, ruletree_fsrule_t *action, const char *abs_clean_virtual_path, int *flagsp) { const char *cp; char *procfs_result; char *union_dir_result = NULL; char *new_path = NULL; switch (action->rtree_fsr_action_type) { case LB_RULETREE_FSRULE_ACTION_USE_ORIG_PATH: return(strdup(abs_clean_virtual_path)); case LB_RULETREE_FSRULE_ACTION_FORCE_ORIG_PATH: /* flags should already contain LB_MAPPING_RULE_FLAGS_FORCE_ORIG_PATH, * but forcing it here won't hurt anyone. */ *flagsp |= LB_MAPPING_RULE_FLAGS_FORCE_ORIG_PATH; return(strdup(abs_clean_virtual_path)); case LB_RULETREE_FSRULE_ACTION_FORCE_ORIG_PATH_UNLESS_CHROOT: /* flags should already contain it, * but forcing it here won't hurt anyone. */ *flagsp |= LB_MAPPING_RULE_FLAGS_FORCE_ORIG_PATH_UNLESS_CHROOT; return(strdup(abs_clean_virtual_path)); case LB_RULETREE_FSRULE_ACTION_MAP_TO: cp = offset_to_ruletree_string_ptr(action->rtree_fsr_action_offs, NULL); return(execute_map_to(abs_clean_virtual_path, "map_to", cp)); case LB_RULETREE_FSRULE_ACTION_REPLACE_BY: cp = offset_to_ruletree_string_ptr(action->rtree_fsr_action_offs, NULL); LB_LOG(LB_LOGLEVEL_DEBUG, "execute_std_action: replace by '%s'", cp); new_path = ruletree_execute_replace_rule(abs_clean_virtual_path, cp/*replacement*/, rule_selector); LB_LOG(LB_LOGLEVEL_DEBUG, "execute_std_action: replaced: '%s'", cp); return(new_path); case LB_RULETREE_FSRULE_ACTION_SET_PATH: cp = offset_to_ruletree_string_ptr(action->rtree_fsr_action_offs, NULL); LB_LOG(LB_LOGLEVEL_DEBUG, "execute_std_action: set path to '%s'", cp); new_path = strdup(cp); return(new_path); case LB_RULETREE_FSRULE_ACTION_MAP_TO_VALUE_OF_ENV_VAR: cp = offset_to_ruletree_string_ptr(action->rtree_fsr_action_offs, NULL); cp = getenv(cp); return(execute_map_to(abs_clean_virtual_path, "map_to_value_of_env_var", cp)); case LB_RULETREE_FSRULE_ACTION_REPLACE_BY_VALUE_OF_ENV_VAR: cp = offset_to_ruletree_string_ptr(action->rtree_fsr_action_offs, NULL); cp = getenv(cp); LB_LOG(LB_LOGLEVEL_DEBUG, "execute_std_action: replace by env.var.value '%s'", cp); new_path = ruletree_execute_replace_rule(abs_clean_virtual_path, cp/*replacement*/, rule_selector); LB_LOG(LB_LOGLEVEL_DEBUG, "execute_std_action: replaced/2: '%s'", cp); return(new_path); case LB_RULETREE_FSRULE_ACTION_PROCFS: LB_LOG(LB_LOGLEVEL_DEBUG, "execute_std_action: /proc: %s", abs_clean_virtual_path); procfs_result = procfs_mapping_request(abs_clean_virtual_path); if (procfs_result) { /* mapped to somewhere else */ return(procfs_result); } /* no need to map this path */ return(strdup(abs_clean_virtual_path)); case LB_RULETREE_FSRULE_ACTION_UNION_DIR: LB_LOG(LB_LOGLEVEL_DEBUG, "execute_std_action: union_dir: %s", abs_clean_virtual_path); { ruletree_object_offset_t union_dir_list_offs = rule_selector->rtree_fsr_rule_list_link; int num_real_dir_entries; const char **src_paths = NULL; int i; num_real_dir_entries = ruletree_objectlist_get_list_size(union_dir_list_offs); if (num_real_dir_entries > 0) { src_paths = calloc(num_real_dir_entries, sizeof(char*)); for (i = 0; i < num_real_dir_entries; i++) { ruletree_object_offset_t str_offs; str_offs = ruletree_objectlist_get_item(union_dir_list_offs, i); src_paths[i] = offset_to_ruletree_string_ptr(str_offs, NULL); LB_LOG(LB_LOGLEVEL_DEBUG, "execute_std_action: union_dir src_path[%d]: %s", i, src_paths[i]); } union_dir_result = prep_union_dir(abs_clean_virtual_path, src_paths, num_real_dir_entries); } if (src_paths) free(src_paths); } LB_LOG(LB_LOGLEVEL_DEBUG, "union_dir result = '%s'", union_dir_result); return(union_dir_result); default: LB_LOG(LB_LOGLEVEL_ERROR, "Internal error: execute_std_action: action code is %d", action->rtree_fsr_action_type); } return(NULL); }
static void dump_catalog(ruletree_object_offset_t catalog_offs, const char *catalog_name, int indent) { ruletree_catalog_entry_t *catalog; ruletree_catalog_entry_t *catp; if (!catalog_offs) { ruletree_hdr_t *treehdr = (ruletree_hdr_t*)offset_to_ruletree_object_ptr(0, SB2_RULETREE_OBJECT_TYPE_FILEHDR); catalog_offs = treehdr->rtree_hdr_root_catalog; } if (rule_dumped[catalog_offs]) { print_indent(indent); printf("[ => Catalog @ %u '%s']\n", catalog_offs, catalog_name); return; } rule_dumped[catalog_offs] = 1; print_indent(indent); printf("Catalog @ %u '%s':\n", catalog_offs, catalog_name); catalog = offset_to_ruletree_object_ptr(catalog_offs, SB2_RULETREE_OBJECT_TYPE_CATALOG); if (!catalog) { print_indent(indent+1); printf("[empty]\n"); return; } /* first, print contents of the catalog itself */ for (catp = catalog; catp; catp = catp->rtree_cat_next_entry_offs ? offset_to_ruletree_object_ptr(catp->rtree_cat_next_entry_offs, SB2_RULETREE_OBJECT_TYPE_CATALOG) : NULL) { const char *name = "??"; print_indent(indent+1); if (catp->rtree_cat_name_offs) { name = offset_to_ruletree_string_ptr(catp->rtree_cat_name_offs, NULL); if (name) { printf("'%s'\t", name); } else { printf("<invalid name offset>\t"); } } else { printf("<no name>\t"); } if (catp->rtree_cat_value_offs) { print_ruletree_object_type(catp->rtree_cat_value_offs); } else { printf("<no value>"); } printf("\n"); } /* next, process again all entries that need recursive processing */ for (catp = catalog; catp; catp = catp->rtree_cat_next_entry_offs ? offset_to_ruletree_object_ptr(catp->rtree_cat_next_entry_offs, SB2_RULETREE_OBJECT_TYPE_CATALOG) : NULL) { const char *name = "??"; if (catp->rtree_cat_name_offs) { name = offset_to_ruletree_string_ptr(catp->rtree_cat_name_offs, NULL); } if (catp->rtree_cat_value_offs) { print_ruletree_object_recurse(indent+1, name, catp->rtree_cat_value_offs); } } print_indent(indent); printf("End of Catalog @ %u '%s'.\n", catalog_offs, catalog_name); }
static void dump_rules(ruletree_object_offset_t offs, int indent) { ruletree_fsrule_t *rule = offset_to_ruletree_fsrule_ptr(offs); const char *rule_list_link_label = "??"; if (rule_dumped[offs]) { print_indent(indent + 1); printf("[ => @ %u]\n", offs); return; } rule_dumped[offs] = 1; print_indent(indent); printf("{ Rule[%u]:\n", (unsigned)offs); if (rule->rtree_fsr_name_offs) { print_indent(indent+1); printf("name = '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_fsr_name_offs, NULL)); } if (rule->rtree_fsr_selector_type) { print_indent(indent+1); printf("IF: "); switch (rule->rtree_fsr_selector_type) { case SB2_RULETREE_FSRULE_SELECTOR_PREFIX: printf("prefix '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_fsr_selector_offs, NULL)); break; case SB2_RULETREE_FSRULE_SELECTOR_DIR: printf("dir '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_fsr_selector_offs, NULL)); break; case SB2_RULETREE_FSRULE_SELECTOR_PATH: printf("path '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_fsr_selector_offs, NULL)); break; default: printf("ERROR: Unknown selector type %d\n", rule->rtree_fsr_selector_type); break; } } if (rule->rtree_fsr_condition_type) { const char *condstr = offset_to_ruletree_string_ptr(rule->rtree_fsr_condition_offs, NULL); print_indent(indent+1); printf("CONDITIONAL: "); switch (rule->rtree_fsr_condition_type) { case SB2_RULETREE_FSRULE_CONDITION_IF_ACTIVE_EXEC_POLICY_IS: printf("if_active_exec_policy_is '%s'\n", condstr); break; case SB2_RULETREE_FSRULE_CONDITION_IF_REDIRECT_IGNORE_IS_ACTIVE: printf("if_redirect_ignore_is_active '%s'\n", condstr); break; case SB2_RULETREE_FSRULE_CONDITION_IF_REDIRECT_FORCE_IS_ACTIVE: printf("if_redirect_force_is_active '%s'\n", condstr); break; case SB2_RULETREE_FSRULE_CONDITION_IF_ENV_VAR_IS_NOT_EMPTY: printf("if_env_var_is_not_empty '%s'\n", condstr); break; case SB2_RULETREE_FSRULE_CONDITION_IF_ENV_VAR_IS_EMPTY: printf("if_env_var_is_empty '%s'\n", condstr); break; default: printf("ERROR: Unknown condition type %d\n", rule->rtree_fsr_condition_type); break; } } if (rule->rtree_fsr_func_class) { print_indent(indent+1); printf("IF_CLASS: 0x%X ( ", rule->rtree_fsr_func_class); if (rule->rtree_fsr_func_class & SB2_INTERFACE_CLASS_OPEN) printf("open "); if (rule->rtree_fsr_func_class & SB2_INTERFACE_CLASS_STAT) printf("stat "); if (rule->rtree_fsr_func_class & SB2_INTERFACE_CLASS_EXEC) printf("exec "); if (rule->rtree_fsr_func_class & SB2_INTERFACE_CLASS_SOCKADDR) printf("sockaddr "); if (rule->rtree_fsr_func_class & SB2_INTERFACE_CLASS_FTSOPEN) printf("ftsopen "); if (rule->rtree_fsr_func_class & SB2_INTERFACE_CLASS_GLOB) printf("glob "); if (rule->rtree_fsr_func_class & SB2_INTERFACE_CLASS_GETCWD) printf("getcwd "); if (rule->rtree_fsr_func_class & SB2_INTERFACE_CLASS_REALPATH) printf("realpath "); if (rule->rtree_fsr_func_class & SB2_INTERFACE_CLASS_L10N) printf("l10n "); if (rule->rtree_fsr_func_class & SB2_INTERFACE_CLASS_MKNOD) printf("mknod "); if (rule->rtree_fsr_func_class & SB2_INTERFACE_CLASS_RENAME) printf("rename "); if (rule->rtree_fsr_func_class & SB2_INTERFACE_CLASS_SYMLINK) printf("symlink "); if (rule->rtree_fsr_func_class & SB2_INTERFACE_CLASS_CREAT) printf("creat "); if (rule->rtree_fsr_func_class & SB2_INTERFACE_CLASS_PROC_FS_OP) printf("proc_fs_op "); printf(")\n"); } if (rule->rtree_fsr_binary_name) { const char *bin_name = offset_to_ruletree_string_ptr(rule->rtree_fsr_binary_name, NULL); print_indent(indent+1); printf("BINARY_NAME: '%s'\n", bin_name); } if (rule->rtree_fsr_exec_policy_name) { const char *ep_name = offset_to_ruletree_string_ptr(rule->rtree_fsr_exec_policy_name, NULL); print_indent(indent+1); printf("EXEC_POLICY_NAME: '%s'\n", ep_name); } print_indent(indent+1); printf("ACTION: "); switch (rule->rtree_fsr_action_type) { case SB2_RULETREE_FSRULE_ACTION_FALLBACK_TO_OLD_MAPPING_ENGINE: printf("FALLBACK_TO_OLD_MAPPING_ENGINE\n"); break; case SB2_RULETREE_FSRULE_ACTION_PROCFS: printf("sb2_procfs_mapper\n"); break; case SB2_RULETREE_FSRULE_ACTION_UNION_DIR: printf("union_dir => rule->rtree_fsr_rule_list_link\n"); rule_list_link_label = "union_dir"; break; case SB2_RULETREE_FSRULE_ACTION_USE_ORIG_PATH: printf("use_orig_path\n"); break; case SB2_RULETREE_FSRULE_ACTION_FORCE_ORIG_PATH: printf("force_orig_path\n"); break; case SB2_RULETREE_FSRULE_ACTION_REPLACE_BY: printf("replace_by '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_fsr_action_offs, NULL)); break; case SB2_RULETREE_FSRULE_ACTION_SET_PATH: printf("set_path '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_fsr_action_offs, NULL)); break; case SB2_RULETREE_FSRULE_ACTION_MAP_TO: printf("map_to '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_fsr_action_offs, NULL)); break; case SB2_RULETREE_FSRULE_ACTION_REPLACE_BY_VALUE_OF_ENV_VAR: printf("replace_by_value_of_env_var '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_fsr_action_offs, NULL)); break; case SB2_RULETREE_FSRULE_ACTION_MAP_TO_VALUE_OF_ENV_VAR: printf("map_to_value_of_env_var '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_fsr_action_offs, NULL)); break; case SB2_RULETREE_FSRULE_ACTION_CONDITIONAL_ACTIONS: printf("actions => %d\n", rule->rtree_fsr_rule_list_link); rule_list_link_label = "actions"; break; case SB2_RULETREE_FSRULE_ACTION_SUBTREE: printf("subtree => %d\n", rule->rtree_fsr_rule_list_link); rule_list_link_label = "rules"; break; case SB2_RULETREE_FSRULE_ACTION_IF_EXISTS_THEN_MAP_TO: printf("if_exists_then_map_to '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_fsr_action_offs, NULL)); break; case SB2_RULETREE_FSRULE_ACTION_IF_EXISTS_THEN_REPLACE_BY: printf("if_exists_then_replace_by '%s'\n", offset_to_ruletree_string_ptr(rule->rtree_fsr_action_offs, NULL)); break; default: printf("ERROR: Unknown action type %d\n", rule->rtree_fsr_action_type); break; } if (rule->rtree_fsr_rule_list_link) { print_indent(indent+1); printf("%s = {\n", rule_list_link_label); dump_objectlist(rule->rtree_fsr_rule_list_link, indent + 2); print_indent(indent+1); printf("}\n"); } print_indent(indent); printf("}\n"); }
char *ruletree_translate_path( const path_mapping_context_t *ctx, int result_log_level, const char *abs_clean_virtual_path, int *flagsp, const char **exec_policy_name_ptr, const char **errormsgp) { char *host_path = NULL; ruletree_fsrule_t *rule; PROCESSCLOCK(clk1) START_PROCESSCLOCK(LB_LOGLEVEL_INFO, &clk1, "ruletree_translate_path"); *errormsgp = NULL; if (!ctx->pmc_ruletree_offset) { /* This might happen during initialization phase, * when rule tree is not yet available */ LB_LOG(LB_LOGLEVEL_DEBUG, "ruletree_translate_path: No rule tree"); *errormsgp = "No rule tree"; return(NULL); } rule = offset_to_ruletree_fsrule_ptr(ctx->pmc_ruletree_offset); LB_LOG(LB_LOGLEVEL_DEBUG, "ruletree_translate_path(%s)", abs_clean_virtual_path); /* execute rule */ /* FIXME: should care about the R/O flag... */ if (flagsp) *flagsp = rule->rtree_fsr_flags; if (exec_policy_name_ptr) { if (rule->rtree_fsr_exec_policy_name) { *exec_policy_name_ptr = offset_to_ruletree_string_ptr(rule->rtree_fsr_exec_policy_name, NULL); } else { *exec_policy_name_ptr = NULL; } } switch (rule->rtree_fsr_action_type) { case LB_RULETREE_FSRULE_ACTION_FALLBACK_TO_OLD_MAPPING_ENGINE: LB_LOG(LB_LOGLEVEL_WARNING, "ruletree_translate_path: Forced fallback. This should never happen nowadays."); host_path = NULL; break; case LB_RULETREE_FSRULE_ACTION_USE_ORIG_PATH: case LB_RULETREE_FSRULE_ACTION_FORCE_ORIG_PATH: case LB_RULETREE_FSRULE_ACTION_FORCE_ORIG_PATH_UNLESS_CHROOT: case LB_RULETREE_FSRULE_ACTION_MAP_TO: case LB_RULETREE_FSRULE_ACTION_REPLACE_BY: case LB_RULETREE_FSRULE_ACTION_SET_PATH: case LB_RULETREE_FSRULE_ACTION_MAP_TO_VALUE_OF_ENV_VAR: case LB_RULETREE_FSRULE_ACTION_REPLACE_BY_VALUE_OF_ENV_VAR: case LB_RULETREE_FSRULE_ACTION_PROCFS: case LB_RULETREE_FSRULE_ACTION_UNION_DIR: host_path = execute_std_action(rule, rule, abs_clean_virtual_path, flagsp); break; case LB_RULETREE_FSRULE_ACTION_CONDITIONAL_ACTIONS: host_path = ruletree_execute_conditional_actions( ctx, result_log_level, abs_clean_virtual_path, flagsp, exec_policy_name_ptr, errormsgp, rule); break; default: LB_LOG(LB_LOGLEVEL_ERROR, "ruletree_translate_path: Unknown action code %d", rule->rtree_fsr_action_type); host_path = NULL; break; } if (host_path) { if (*host_path != '/') { LB_LOG(LB_LOGLEVEL_ERROR, "Mapping failed: Result is not absolute ('%s'->'%s')", abs_clean_virtual_path, host_path); host_path = NULL; } else { char *new_host_path = clean_and_log_fs_mapping_result(ctx, abs_clean_virtual_path, result_log_level, host_path, *flagsp); if (new_host_path == NULL) { LB_LOG(result_log_level, "Mapping failed ('%s')", abs_clean_virtual_path); *errormsgp = "Mapping failed"; } free(host_path); host_path = new_host_path; } } else { LB_LOG(result_log_level, "Mapping failed: Fallback to Lua mapping ('%s')", abs_clean_virtual_path); *errormsgp = "No result from C mapping"; } STOP_AND_REPORT_PROCESSCLOCK(LB_LOGLEVEL_INFO, &clk1, host_path); return(host_path); }