static script_info *create_script(char const *file) { int base; char *filename_fs; lua_State *L; script_info *info = g_new0(script_info, 1); info->hooks = g_ptr_array_new_with_free_func((GDestroyNotify)free_hook); info->unload_hooks = g_ptr_array_new_with_free_func((GDestroyNotify)free_hook); info->filename = g_strdup(expand_path(file)); L = luaL_newstate(); info->state = L; if(!L) { hexchat_print(ph, "\00304Could not allocate memory for the script"); destroy_script(info); return NULL; } prepare_state(L, info); lua_rawgeti(L, LUA_REGISTRYINDEX, info->traceback); base = lua_gettop(L); filename_fs = g_filename_from_utf8(info->filename, -1, NULL, NULL, NULL); if(!filename_fs) { hexchat_printf(ph, "Invalid filename: %s", info->filename); destroy_script(info); return NULL; } if(luaL_loadfile(L, filename_fs)) { g_free(filename_fs); hexchat_printf(ph, "Lua syntax error: %s", luaL_optstring(L, -1, "")); destroy_script(info); return NULL; } g_free(filename_fs); info->status |= STATUS_ACTIVE; if(lua_pcall(L, 0, 0, base)) { char const *error = lua_tostring(L, -1); hexchat_printf(ph, "Lua error: %s", error ? error : "(non-string error)"); destroy_script(info); return NULL; } lua_pop(L, 1); if(!info->name) { hexchat_printf(ph, "Lua script didn't register with hexchat.register"); destroy_script(info); return NULL; } return info; }
static uint8_t winner_from (PPosition_type pos, PState_DFS state, int f) { prepare_state (state, f); int mi = (pos->player == L) ? X(f) : Y(f); int ma = (pos->player == L) ? X(f) : Y(f); while (not_done (state)) { int const px = pop (state); int const py = pop (state); #define DO(dx, dy) \ if ( (px + dx) >= 0 && (px + dx) <= SIZE \ && (py + dy) >= 0 && (py + dy) <= SIZE \ && pos->taken[LIN ((px + dx), (py + dy))] == pos->player \ ) \ { \ if (not_seen (state, px + dx, py + dy)) \ { \ mi = MIN (mi, (pos->player == L) ? (px + dx) : (py + dy)); \ ma = MAX (ma, (pos->player == L) ? (px + dx) : (py + dy)); \ \ if (mi == 0 && ma == SIZE) \ { \ return pos->player; \ } \ \ push (state, px + dx, py + dy); \ } \ } \ DO ( 0, 1); DO ( 1, 1); DO ( 1, 0); DO ( 0,-1); DO (-1,-1); DO (-1, 0); #undef DO } return N; }
static void create_interpreter(void) { lua_State *L; interp = g_new0(script_info, 1); interp->hooks = g_ptr_array_new_with_free_func((GDestroyNotify)free_hook); interp->unload_hooks = g_ptr_array_new_with_free_func((GDestroyNotify)free_hook); interp->name = "lua interpreter"; interp->description = ""; interp->version = ""; interp->handle = ph; interp->filename = ""; L = luaL_newstate(); interp->state = L; if(!L) { hexchat_print(ph, "\00304Could not allocate memory for the interpreter"); g_free(interp); interp = NULL; return; } prepare_state(L, interp); }
int crux(int argc, char *argv[]) { if (argc <= 1) { syntax(); return -1; } /* * First, parse the command line. */ Params params; int program_args = 1; int rc = parse_command_line(params, argc, argv, program_args); if (rc < 0) { return rc; } /* * Next, get the original IDs of the user executing this setuid program. */ uid_t ruid, euid, suid; gid_t rgid, egid, sgid; ASSERT(getresgid(&rgid, &egid, &sgid) >= 0); ASSERT(getresuid(&ruid, &euid, &suid) >= 0); ASSERT(unshare(CLONE_NEWNS) >= 0); /* The following is needed for MS_MOVE to work */ ASSERT(mount(NULL, "/", "none", MS_PRIVATE | MS_REC, NULL) == 0); State state; prepare_state(params, state, ruid, rgid); int sockets[2]; pid_t discard_pid = -1; if (params.discard_after_exec) { /* Fork a subprocess for the umount */ ASSERT(socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets) == 0); discard_pid = fork(); if (discard_pid == 0) { close(sockets[1]); char q[1]; ASSERT(0 <= read(sockets[0], q, 1)); lazy_unmount(params); ASSERT(0 <= write(sockets[0], q, 1)); exit(-1); return 0; } close(sockets[0]); } /* Drop back to regular user */ ASSERT(setgid(rgid) >= 0); ASSERT(setuid(ruid) >= 0); /* * Operate on the files. */ for (auto &dirstate : state.dirs) { auto &dir = dirstate.dir; for (auto &replacement_state : dirstate.replacements) { auto &replacement = replacement_state.replacement; auto target_fullpath = dir.path + "/" + replacement.target; unlink(target_fullpath.c_str()); std::ofstream dst(target_fullpath, std::ios::binary); dst << replacement_state.input_file->rdbuf(); ASSERT(chmod(target_fullpath.c_str(), replacement_state.st.st_mode & ~0170000) >= 0); } } /* * Execute the program in our crafted environment. */ pid_t pid = vfork(); if (pid == 0) { if (params.discard_after_exec) { static char str_1[0x100]; snprintf(str_1, sizeof(str_1), "%s=%s", "LD_PRELOAD", // TODO: Find a better way to locate the shared library PREFIX_PATH "/share/with-overlayfs/hook.so"); ASSERT(putenv(str_1) == 0); static char str_2[0x100]; snprintf(str_2, sizeof(str_2), "%s=%d", AFTER_LOAD_ENV, sockets[1]); ASSERT(putenv(str_2) == 0); } int r = execvp(argv[program_args], &argv[program_args]); exit(-1); return r; } if (params.discard_after_exec) { close(sockets[1]); } if (discard_pid != -1) { int status = 0; waitpid(pid, &status, 0); } int status = 0; waitpid(pid, &status, 0); if (WIFEXITED(status)) { return WEXITSTATUS(status); } return -1; }