static int lua_set_acllist(lua_State *L, void *wl, lua_cmd_t *cmd, char *buf) { struct maclist *maclist = (struct maclist *) buf; struct ether_addr *ea; uint max = (WLC_IOCTL_MAXLEN - sizeof(int)) / ETHER_ADDR_LEN; char *nargv[128]; char **argv; uint len; cmd_split(buf, (char **)nargv, 128); argv = (char **)nargv; /* Clear list */ maclist->count = htod32(0); ea = maclist->ea; while (*argv && maclist->count < max) { if (!wl_ether_atoe(*argv, ea)) { return -1; } maclist->count++; ea++; argv++; } /* Set new list */ len = sizeof(maclist->count) + maclist->count * sizeof(maclist->ea); maclist->count = htod32(maclist->count); return wlu_set(wl, WLC_SET_MACLIST, maclist, len); }
static int start_child_process(const char* cmd) { int pid, in[2], out[2], err[2]; char** params = cmd_split(cmd); pipe(in); pipe(out); pipe(err); signal(SIGCHLD, SIG_DFL); pid = fork(); switch(pid) { case 0: /* child process */ close(0); dup(in[0]); close(in[0]); close(in[1]); close(1); dup(out[1]); close(out[0]); close(out[1]); close(2); dup(err[1]); close(err[0]); close(err[1]); errno = 0; /* start it */ execvp(params[0], params); /* some programs use value 2 (tar) */ if(errno == 2) _exit(199); else _exit(errno); break; case -1: E_WARNING(E_STRLOC ": fork() failed\n"); /* close the pipes */ close(in[0]); close(in[1]); close(out[0]); close(out[1]); close(err[0]); close(err[1]); break; default: /* parent */ close(in[0]); close(out[1]); close(err[1]); break; } /* cleanup when returns from the child */ for(int i = 0; params[i]; i++) free(params[i]); free(params); int status = 0, ret = 1; errno = 0; if(waitpid(pid, &status, 0) < 0) { E_WARNING(E_STRLOC ": waitpid() failed with '%s'\n", strerror(errno)); return 1; } if(WIFEXITED(status)) { ret = WEXITSTATUS(status); } else if(WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV) { start_crasher(cmd, SIGSEGV); } else { E_WARNING(E_STRLOC ": child '%s' killed\n", cmd); } return ret; }
static void exec_cmd(const char* cmd, int child_err_report_fd) { /* let it be closed on exec */ if(child_err_report_fd != -1) fcntl(child_err_report_fd, F_SETFD, FD_CLOEXEC); int errnosv, count = 0; char** args = cmd_split(cmd, &count); if(!args) { errnosv = ENOMEM; if(child_err_report_fd != -1) { /* report it to the pipe if it was used*/ write_int(child_err_report_fd, RUN_EXECVE_FAILED); write_int(child_err_report_fd, errnosv); _exit(1); } else { /* or directly if wasn't */ _exit(errnosv); } } /* see if it has a path component in itself */ if(strchr(args[0], '/') != NULL) { execv(args[0], args); /* execute it then via shell if failed */ if(errno == ENOEXEC) exec_cmd_via_shell(args[0], args, count); } else { /* * search PATH then; here will not be used file_path() or similar checker * but execve() will be directly called on each path component and if failed, * it will go to the next available */ char name[PATH_MAX], *path, *path_copy; path = getenv("PATH"); if(!path) { /* in glib was stated that '.' is put last for security so I'm using that here too */ path = (char*)"/bin:/usr/bin:."; } path_copy = strdup(path); if(path_copy) { for(char* t = strtok(path_copy, ":"); t; t = strtok(NULL, ":")) { snprintf(name, sizeof(name), "%s/%s", t, args[0]); /* execute it */ execv(name, args); /* or try with shell instead */ if(errno == ENOEXEC) exec_cmd_via_shell(name, args, count); /* these indicates that current entry wasn't found; go to the next */ if(errno == EACCES || errno == ENOENT || errno == ENOTDIR) continue; /* if we got here, it means it is bad; break it and let errno be reported via pipe */ errnosv = errno; break; } free(path_copy); } } /* quickly save it before any further stdlib calls */ errnosv = errno; /* got here; everything failed so report it then */ for(int i = 0; args[i]; i++) free(args[i]); free(args); if(child_err_report_fd != -1) { /* report for async code */ write_int(child_err_report_fd, RUN_EXECVE_FAILED); write_int(child_err_report_fd, errnosv); _exit(1); } else { /* report for sync code */ _exit(errnosv); } }