/* Exec preprocessor: * (previously known as "sb_execve_mod") */ int sb_execve_preprocess(char **file, char ***argv, char ***envp) { struct lua_instance *luaif = get_lua(); int res, new_argc, new_envc; if (!luaif) return(0); if (!argv || !envp) { SB_LOG(SB_LOGLEVEL_ERROR, "ERROR: sb_argvenvp: (argv || envp) == NULL"); release_lua(luaif); return -1; } if (getenv("SBOX_DISABLE_ARGVENVP")) { SB_LOG(SB_LOGLEVEL_DEBUG, "sb_argvenvp disabled(E):"); release_lua(luaif); return 0; } SB_LOG(SB_LOGLEVEL_NOISE, "sb_execve_preprocess: gettop=%d", lua_gettop(luaif->lua)); lua_getfield(luaif->lua, LUA_GLOBALSINDEX, "sbox_execve_preprocess"); lua_pushstring(luaif->lua, *file); free(*file); strvec_to_lua_table(luaif, *argv); strvec_free(*argv); strvec_to_lua_table(luaif, *envp); strvec_free(*envp); /* args: binaryname, argv, envp * returns: err, file, argc, argv, envc, envp */ lua_call(luaif->lua, 3, 6); res = lua_tointeger(luaif->lua, -6); *file = strdup(lua_tostring(luaif->lua, -5)); new_argc = lua_tointeger(luaif->lua, -4); new_envc = lua_tointeger(luaif->lua, -2); lua_string_table_to_strvec(luaif, -3, argv, new_argc); lua_string_table_to_strvec(luaif, -1, envp, new_envc); /* remove sbox_execve_preprocess' return values from the stack. */ lua_pop(luaif->lua, 6); SB_LOG(SB_LOGLEVEL_NOISE, "sb_execve_preprocess: at exit, gettop=%d", lua_gettop(luaif->lua)); release_lua(luaif); return res; }
static void js_model_destroy(js_model_t *jm) { assert(TAILQ_FIRST(&jm->jm_items) == NULL); if(jm->jm_args) strvec_free(jm->jm_args); prop_unsubscribe(jm->jm_eventsub); if(jm->jm_root) prop_ref_dec(jm->jm_root); if(jm->jm_loading) prop_ref_dec(jm->jm_loading); if(jm->jm_nodes) prop_ref_dec(jm->jm_nodes); if(jm->jm_actions) prop_ref_dec(jm->jm_actions); if(jm->jm_type) prop_ref_dec(jm->jm_type); if(jm->jm_error) prop_ref_dec(jm->jm_error); if(jm->jm_contents) prop_ref_dec(jm->jm_contents); if(jm->jm_entries) prop_ref_dec(jm->jm_entries); if(jm->jm_source) prop_ref_dec(jm->jm_source); if(jm->jm_metadata) prop_ref_dec(jm->jm_metadata); if(jm->jm_options) prop_ref_dec(jm->jm_options); if(jm->jm_eventsink) prop_ref_dec(jm->jm_eventsink); if(jm->jm_pc != NULL) prop_courier_destroy(jm->jm_pc); free(jm->jm_url); hts_mutex_lock(&js_model_mutex); LIST_REMOVE(jm, jm_link); hts_mutex_unlock(&js_model_mutex); free(jm); }
/* Make preparations for an union directory: * (FIXME. This is not very efficient) * (FIXME. Does not remove removed entries) * (FIXME. add description) * * Parameters: * 1. Path to the directory, which is presented as * union of more than one real directories * 2. Number of real directory paths * 3. Array of real directory paths * Returns: * 1. Status (boolean): false if error, true if ok * 2. Path to the created union directory. */ static int lua_lb_prep_union_dir(lua_State *l) { char *dst_path = NULL; int num_real_dir_entries; char **src_paths = NULL; char *result_path = NULL; int n = lua_gettop(l); if (n == 3) { dst_path = strdup(lua_tostring(l, 1)); num_real_dir_entries = lua_tointeger(l, 2); if (dst_path && (num_real_dir_entries > 0)) { lua_string_table_to_strvec(l, 3, &src_paths, num_real_dir_entries); result_path = prep_union_dir(dst_path, (const char **)src_paths, num_real_dir_entries); strvec_free(src_paths); } } lua_pushboolean(l, result_path ? 1 : 0); lua_pushstring(l, result_path); free(dst_path); if (result_path) free(result_path); return 2; }
static void js_model_destroy(js_model_t *jm) { if(jm->jm_args) strvec_free(jm->jm_args); prop_unsubscribe(jm->jm_eventsub); if(jm->jm_root) prop_ref_dec(jm->jm_root); if(jm->jm_loading) prop_ref_dec(jm->jm_loading); if(jm->jm_nodes) prop_ref_dec(jm->jm_nodes); if(jm->jm_actions) prop_ref_dec(jm->jm_actions); if(jm->jm_type) prop_ref_dec(jm->jm_type); if(jm->jm_error) prop_ref_dec(jm->jm_error); if(jm->jm_contents) prop_ref_dec(jm->jm_contents); if(jm->jm_entries) prop_ref_dec(jm->jm_entries); if(jm->jm_source) prop_ref_dec(jm->jm_source); if(jm->jm_metadata) prop_ref_dec(jm->jm_metadata); if(jm->jm_options) prop_ref_dec(jm->jm_options); if(jm->jm_eventsink) prop_ref_dec(jm->jm_eventsink); if(jm->jm_pc != NULL) prop_courier_destroy(jm->jm_pc); free(jm->jm_url); free(jm); }
static void es_gumbo_find_by_class_r(GumboNode *node, char **classes, duk_context *ctx, int *idxp, es_gumbo_output_t *ego) { if(node->type != GUMBO_NODE_ELEMENT && node->type != GUMBO_NODE_TEMPLATE) return; const GumboElement *e = &node->v.element; GumboAttribute *a = gumbo_get_attribute(&e->attributes, "class"); if(a != NULL) { char **list = strvec_split(a->value, ' '); for(int i = 0; classes[i] != NULL; i++) { int found = 0; for(int j = 0; list[j] != NULL; j++) { if(!strcmp(list[j], classes[i])) { found = 1; break; } } if(!found) goto notfound; } push_gumbo_node(ctx, node, ego); duk_put_prop_index(ctx, -2, (*idxp)++); notfound: strvec_free(list); } for(int i = 0; i < e->children.length; i++) es_gumbo_find_by_class_r(e->children.data[i], classes, ctx, idxp, ego); }
static prop_t * prop_from_path(const char *path) { char **n = strvec_split(path, '/'); prop_t *p = prop_get_by_name((const char **)n, 1, NULL); strvec_free(n); return p; }
static int es_gumbo_find_by_class(duk_context *ctx) { es_gumbo_node_t *egn = es_get_native_obj(ctx, 0, &es_native_gumbo_node); const char *cls = duk_to_string(ctx, 1); int idx = 0; duk_push_array(ctx); char **classlist = strvec_split(cls, ' '); es_gumbo_find_by_class_r(egn->node, classlist, ctx, &idx, egn->output); strvec_free(classlist); return 1; }
/* Map script interpreter: * Called with "rule" and "exec_policy" already in lua's stack, * leaves (possibly modified) "rule" and "exec_policy" to lua's stack. */ char *sb_execve_map_script_interpreter( const char *interpreter, const char *interp_arg, const char *mapped_script_filename, const char *orig_script_filename, char ***argv, char ***envp) { struct lua_instance *luaif; char *mapped_interpreter; int new_argc, new_envc; int res; luaif = get_lua(); if (!luaif) return(0); if (!argv || !envp) { SB_LOG(SB_LOGLEVEL_ERROR, "ERROR: sb_execve_map_script_interpreter: " "(argv || envp) == NULL"); release_lua(luaif); return NULL; } SB_LOG(SB_LOGLEVEL_NOISE, "sb_execve_map_script_interpreter: gettop=%d" " interpreter=%s interp_arg=%s " "mapped_script_filename=%s orig_script_filename=%s", lua_gettop(luaif->lua), interpreter, interp_arg, mapped_script_filename, orig_script_filename); lua_getfield(luaif->lua, LUA_GLOBALSINDEX, "sb_execve_map_script_interpreter"); /* stack now contains "rule", "exec_policy" and * "sb_execve_map_script_interpreter". * move "sb_execve_map_script_interpreter" to the bottom : */ lua_insert(luaif->lua, -3); lua_pushstring(luaif->lua, interpreter); if (interp_arg) lua_pushstring(luaif->lua, interp_arg); else lua_pushnil(luaif->lua); lua_pushstring(luaif->lua, mapped_script_filename); lua_pushstring(luaif->lua, orig_script_filename); strvec_to_lua_table(luaif, *argv); strvec_to_lua_table(luaif, *envp); /* args: rule, exec_policy, interpreter, interp_arg, * mapped_script_filename, orig_script_filename, * argv, envp * returns: rule, policy, result, mapped_interpreter, #argv, argv, * #envp, envp * "result" is one of: * 0: argv / envp were modified; mapped_interpreter was set * 1: argv / envp were not modified; mapped_interpreter was set * -1: deny exec. */ if(SB_LOG_IS_ACTIVE(SB_LOGLEVEL_NOISE3)) { dump_lua_stack("sb_execve_map_script_interpreter M1", luaif->lua); } SB_LOG(SB_LOGLEVEL_NOISE, "sb_execve_map_script_interpreter: call lua, gettop=%d", lua_gettop(luaif->lua)); lua_call(luaif->lua, 8, 8); SB_LOG(SB_LOGLEVEL_NOISE, "sb_execve_map_script_interpreter: return from lua, gettop=%d", lua_gettop(luaif->lua)); if(SB_LOG_IS_ACTIVE(SB_LOGLEVEL_NOISE3)) { dump_lua_stack("sb_execve_map_script_interpreter M2", luaif->lua); } mapped_interpreter = (char *)lua_tostring(luaif->lua, -5); if (mapped_interpreter) mapped_interpreter = strdup(mapped_interpreter); res = lua_tointeger(luaif->lua, -6); switch (res) { case 0: /* exec arguments were modified, replace contents of * argv and envp vectors */ SB_LOG(SB_LOGLEVEL_DEBUG, "sb_execve_map_script_interpreter: Updated argv&envp"); strvec_free(*argv); new_argc = lua_tointeger(luaif->lua, -4); lua_string_table_to_strvec(luaif, -3, argv, new_argc); new_envc = lua_tointeger(luaif->lua, -2); strvec_free(*envp); lua_string_table_to_strvec(luaif, -1, envp, new_envc); /* remove return values from the stack, leave rule & policy. */ lua_pop(luaif->lua, 6); break; case 1: SB_LOG(SB_LOGLEVEL_DEBUG, "sb_execve_map_script_interpreter: argv&envp were not modified"); /* remove return values from the stack, leave rule & policy. */ lua_pop(luaif->lua, 6); break; case 2: SB_LOG(SB_LOGLEVEL_DEBUG, "sb_execve_map_script_interpreter: use sbox_map_path_for_exec"); /* remove all return values from the stack. */ lua_pop(luaif->lua, 8); if (mapped_interpreter) free(mapped_interpreter); mapped_interpreter = NULL; { mapping_results_t mapping_result; clear_mapping_results_struct(&mapping_result); sbox_map_path_for_exec("script_interp", interpreter, &mapping_result); if (mapping_result.mres_result_buf) { mapped_interpreter = strdup(mapping_result.mres_result_buf); } free_mapping_results(&mapping_result); } SB_LOG(SB_LOGLEVEL_DEBUG, "sb_execve_map_script_interpreter: " "interpreter=%s mapped_interpreter=%s", interpreter, mapped_interpreter); break; case -1: SB_LOG(SB_LOGLEVEL_DEBUG, "sb_execve_map_script_interpreter: exec denied"); /* remove return values from the stack, leave rule & policy. */ lua_pop(luaif->lua, 6); if (mapped_interpreter) free(mapped_interpreter); mapped_interpreter = NULL; break; default: SB_LOG(SB_LOGLEVEL_ERROR, "sb_execve_map_script_interpreter: Unsupported result %d", res); /* remove return values from the stack, leave rule & policy. */ lua_pop(luaif->lua, 6); break; } if(SB_LOG_IS_ACTIVE(SB_LOGLEVEL_NOISE3)) { dump_lua_stack("sb_execve_map_script_interpreter E2", luaif->lua); } SB_LOG(SB_LOGLEVEL_NOISE, "sb_execve_map_script_interpreter: at exit, gettop=%d", lua_gettop(luaif->lua)); release_lua(luaif); return mapped_interpreter; }
/* Exec Postprocessing: * Called with "rule" and "exec_policy" already in lua's stack. */ int sb_execve_postprocess(char *exec_type, char **mapped_file, char **filename, const char *binary_name, char ***argv, char ***envp) { struct lua_instance *luaif; int res, new_argc; int replace_environment = 0; luaif = get_lua(); if (!luaif) return(0); if(SB_LOG_IS_ACTIVE(SB_LOGLEVEL_NOISE3)) { dump_lua_stack("sb_execve_postprocess entry", luaif->lua); } if (!argv || !envp) { SB_LOG(SB_LOGLEVEL_ERROR, "ERROR: sb_argvenvp: (argv || envp) == NULL"); release_lua(luaif); return -1; } SB_LOG(SB_LOGLEVEL_NOISE, "sb_execve_postprocess: gettop=%d", lua_gettop(luaif->lua)); lua_getfield(luaif->lua, LUA_GLOBALSINDEX, "sb_execve_postprocess"); /* stack now contains "rule", "exec_policy" and "sb_execve_postprocess". * move "sb_execve_postprocess" to the bottom : */ lua_insert(luaif->lua, -3); lua_pushstring(luaif->lua, exec_type); lua_pushstring(luaif->lua, *mapped_file); lua_pushstring(luaif->lua, *filename); lua_pushstring(luaif->lua, binary_name); strvec_to_lua_table(luaif, *argv); strvec_to_lua_table(luaif, *envp); /* args: rule, exec_policy, exec_type, mapped_file, filename, * binaryname, argv, envp * returns: res, mapped_file, filename, argc, argv, envc, envp */ lua_call(luaif->lua, 8, 7); res = lua_tointeger(luaif->lua, -7); switch (res) { case 0: /* exec arguments were modified, replace contents of * argv vector */ SB_LOG(SB_LOGLEVEL_DEBUG, "sb_execve_postprocess: Updated argv&envp"); free(*mapped_file); *mapped_file = strdup(lua_tostring(luaif->lua, -6)); free(*filename); *filename = strdup(lua_tostring(luaif->lua, -5)); strvec_free(*argv); new_argc = lua_tointeger(luaif->lua, -4); lua_string_table_to_strvec(luaif, -3, argv, new_argc); replace_environment = 1; break; case 1: SB_LOG(SB_LOGLEVEL_DEBUG, "sb_execve_postprocess: argv was not modified"); /* always update environment when we are going to exec */ replace_environment = 1; break; case -1: SB_LOG(SB_LOGLEVEL_DEBUG, "sb_execve_postprocess: exec denied"); break; default: SB_LOG(SB_LOGLEVEL_ERROR, "sb_execve_postprocess: Unsupported result %d", res); break; } if (replace_environment) { int new_envc; new_envc = lua_tointeger(luaif->lua, -2); strvec_free(*envp); lua_string_table_to_strvec(luaif, -1, envp, new_envc); } /* remove sb_execve_postprocess return values from the stack. */ lua_pop(luaif->lua, 7); SB_LOG(SB_LOGLEVEL_NOISE, "sb_execve_postprocess: at exit, gettop=%d", lua_gettop(luaif->lua)); release_lua(luaif); return res; }
static JSBool js_createMultiOpt(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { js_setting_group_t *jsg = JS_GetPrivate(cx, obj); const char *id; const char *title; JSObject *func; JSObject *optlist; JSBool persistent = JS_FALSE; if(!JS_ConvertArguments(cx, argc, argv, "ssoo/b", &id, &title, &optlist, &func, &persistent)) return JS_FALSE; js_setting_t *jss = jss_create(cx, obj, id, rval, func, jsg, persistent); if(jss == NULL) return JS_FALSE; char **options = NULL; JSIdArray *opts, *opt; int i; char *defvalue = NULL; if((opts = JS_Enumerate(cx, optlist)) != NULL) { for(i = 0; i < opts->length; i++) { jsval name, value, id, title, def; if(!JS_IdToValue(cx, opts->vector[i], &name) || !JSVAL_IS_INT(name) || !JS_GetElement(cx, optlist, JSVAL_TO_INT(name), &value) || !JSVAL_IS_OBJECT(value) || (opt = JS_Enumerate(cx, JSVAL_TO_OBJECT(value))) == NULL) continue; if(opt->length >= 2 && JS_GetElement(cx, JSVAL_TO_OBJECT(value), 0, &id) && JS_GetElement(cx, JSVAL_TO_OBJECT(value), 1, &title)) { if(opt->length < 3 || !JS_GetElement(cx, JSVAL_TO_OBJECT(value), 2, &def)) def = JSVAL_FALSE; const char *k = JS_GetStringBytes(JS_ValueToString(cx, id)); if(def == JSVAL_TRUE) mystrset(&defvalue, k); strvec_addp(&options, k); strvec_addp(&options, JS_GetStringBytes(JS_ValueToString(cx, title))); } JS_DestroyIdArray(cx, opt); } JS_DestroyIdArray(cx, opts); } rstr_t *r = NULL; if(persistent && jsg->jsg_kv_url) r = kv_url_opt_get_rstr(jsg->jsg_kv_url, KVSTORE_DOMAIN_PLUGIN, id); jss->jss_s = setting_create(SETTING_MULTIOPT, jsg->jsg_root, SETTINGS_INITIAL_UPDATE | jsg->jsg_settings_flags, SETTING_TITLE_CSTR(title), SETTING_COURIER(js_global_pc), SETTING_CALLBACK(js_store_update_string, jss), SETTING_VALUE(r ? rstr_get(r) : defvalue), SETTING_OPTION_LIST(options), SETTING_HTSMSG_CUSTOM_SAVER(id, jsg->jsg_store, js_setting_group_save, jsg), NULL); strvec_free(options); rstr_release(r); jss->jss_cx = NULL; return JS_TRUE; }
/* Exec Postprocessing: */ int lb_execve_postprocess(const char *exec_type, const char *exec_policy_name, char **mapped_file, char **filename, const char *binary_name, char ***argv, char ***envp) { struct lbcontext *lbctx; int res, new_argc; int replace_environment = 0; PROCESSCLOCK(clk1) START_PROCESSCLOCK(LB_LOGLEVEL_INFO, &clk1, "lb_execve_postprocess"); lbctx = get_lbcontext_lua(); if (!lbctx) return(0); if(LB_LOG_IS_ACTIVE(LB_LOGLEVEL_NOISE3)) { dump_lua_stack("lb_execve_postprocess entry", lbctx->lua); } if (!argv || !envp) { LB_LOG(LB_LOGLEVEL_ERROR, "ERROR: lb_argvenvp: (argv || envp) == NULL"); release_lbcontext(lbctx); return -1; } LB_LOG(LB_LOGLEVEL_NOISE, "lb_execve_postprocess: gettop=%d", lua_gettop(lbctx->lua)); lua_getfield(lbctx->lua, LUA_GLOBALSINDEX, "lb_execve_postprocess"); lua_pushstring(lbctx->lua, exec_policy_name); lua_pushstring(lbctx->lua, exec_type); lua_pushstring(lbctx->lua, *mapped_file); lua_pushstring(lbctx->lua, *filename); lua_pushstring(lbctx->lua, binary_name); strvec_to_lua_table(lbctx, *argv); strvec_to_lua_table(lbctx, *envp); /* args: exec_policy_name, exec_type, mapped_file, filename, * binaryname, argv, envp * returns: res, mapped_file, filename, argc, argv, envc, envp */ lua_call(lbctx->lua, 7, 7); res = lua_tointeger(lbctx->lua, -7); switch (res) { case 0: /* exec arguments were modified, replace contents of * argv vector */ LB_LOG(LB_LOGLEVEL_DEBUG, "lb_execve_postprocess: Updated argv&envp"); free(*mapped_file); *mapped_file = strdup(lua_tostring(lbctx->lua, -6)); free(*filename); *filename = strdup(lua_tostring(lbctx->lua, -5)); strvec_free(*argv); new_argc = lua_tointeger(lbctx->lua, -4); lua_string_table_to_strvec(lbctx->lua, -3, argv, new_argc); replace_environment = 1; break; case 1: LB_LOG(LB_LOGLEVEL_DEBUG, "lb_execve_postprocess: argv was not modified"); /* always update environment when we are going to exec */ replace_environment = 1; break; case -1: LB_LOG(LB_LOGLEVEL_DEBUG, "lb_execve_postprocess: exec denied"); break; default: LB_LOG(LB_LOGLEVEL_ERROR, "lb_execve_postprocess: Unsupported result %d", res); break; } if (replace_environment) { int new_envc; new_envc = lua_tointeger(lbctx->lua, -2); strvec_free(*envp); lua_string_table_to_strvec(lbctx->lua, -1, envp, new_envc); } /* remove lb_execve_postprocess return values from the stack. */ lua_pop(lbctx->lua, 7); STOP_AND_REPORT_PROCESSCLOCK(LB_LOGLEVEL_INFO, &clk1, mapped_file); LB_LOG(LB_LOGLEVEL_NOISE, "lb_execve_postprocess: at exit, gettop=%d", lua_gettop(lbctx->lua)); release_lbcontext(lbctx); return res; }