void procd_coldplug(void) { char *argv[] = { "udevtrigger", NULL }; umount2("/dev/pts", MNT_DETACH); umount2("/dev/", MNT_DETACH); mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755,size=512K"); mkdir("/dev/shm", 0755); mkdir("/dev/pts", 0755); mount("devpts", "/dev/pts", "devpts", 0, 0); udevtrigger.cb = udevtrigger_complete; udevtrigger.pid = fork(); if (!udevtrigger.pid) { execvp(argv[0], argv); ERROR("Failed to start coldplug\n"); exit(-1); } if (udevtrigger.pid <= 0) { ERROR("Failed to start new coldplug instance\n"); return; } uloop_process_add(&udevtrigger); DEBUG(4, "Launched coldplug instance, pid=%d\n", (int) udevtrigger.pid); }
static void fork_worker(struct init_action *a) { int fd; pid_t p; a->proc.pid = fork(); if (!a->proc.pid) { p = setsid(); fd = dev_open(a->id); if (fd != -1) { dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); if (fd > STDERR_FILENO) close(fd); } ioctl(STDIN_FILENO, TIOCSCTTY, 1); tcsetpgrp(STDIN_FILENO, p); execvp(a->argv[0], a->argv); ERROR("Failed to execute %s\n", a->argv[0]); exit(-1); } if (a->proc.pid > 0) { DEBUG(4, "Launched new %s action, pid=%d\n", a->handler->name, (int) a->proc.pid); uloop_process_add(&a->proc); } }
void preinit(void) { char *init[] = { "/bin/sh", "/etc/preinit", NULL }; char *plug[] = { "/sbin/procd", "-h", "/etc/hotplug-preinit.json", NULL }; int fd; LOG("- preinit -\n"); plugd_proc.cb = plugd_proc_cb; plugd_proc.pid = fork(); if (!plugd_proc.pid) { execvp(plug[0], plug); ERROR("Failed to start plugd\n"); exit(-1); } if (plugd_proc.pid <= 0) { ERROR("Failed to start new plugd instance\n"); return; } uloop_process_add(&plugd_proc); setenv("PREINIT", "1", 1); fd = creat("/tmp/.preinit", 0600); if (fd < 0) ERROR("Failed to create sentinel file\n"); else close(fd); preinit_proc.cb = spawn_procd; preinit_proc.pid = fork(); if (!preinit_proc.pid) { execvp(init[0], init); ERROR("Failed to start preinit\n"); exit(-1); } if (preinit_proc.pid <= 0) { ERROR("Failed to start new preinit instance\n"); return; } uloop_process_add(&preinit_proc); DEBUG(4, "Launched preinit instance, pid=%d\n", (int) preinit_proc.pid); }
void runqueue_process_add(struct runqueue *q, struct runqueue_process *p, pid_t pid) { if (p->proc.pending) return; p->proc.pid = pid; p->proc.cb = __runqueue_proc_cb; if (!p->task.type) p->task.type = &runqueue_proc_type; uloop_process_add(&p->proc); if (!p->task.running) runqueue_task_add(q, &p->task, true); }
static void tracer_cb(struct uloop_process *c, int ret) { if (WIFSTOPPED(ret) && WSTOPSIG(ret) & 0x80) { if (!in_syscall) { int syscall = ptrace(PTRACE_PEEKUSER, c->pid, reg_syscall_nr); if (syscall < syscall_max) { syscall_count[syscall]++; if (debug) fprintf(stderr, "%s()\n", syscall_names[syscall]); } else if (debug) { fprintf(stderr, "syscal(%d)\n", syscall); } } in_syscall = !in_syscall; } else if (WIFEXITED(ret)) { uloop_end(); return; } ptrace(PTRACE_SYSCALL, c->pid, 0, 0); uloop_process_add(&tracer); }
static void http_new_client(struct uloop_fd *ufd, unsigned events) { int status; struct timeval t; t.tv_sec = 60; t.tv_usec = 0; for (;;) { int client = accept(ufd->fd, NULL, NULL); /* set one minute timeout */ if (setsockopt(ufd->fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&t, sizeof t)) { DD("setsockopt() failed\n"); } if (client == -1) break; struct uloop_process *uproc = calloc(1, sizeof(*uproc)); if (!uproc || (uproc->pid = fork()) == -1) { FREE(uproc); close(client); } if (uproc->pid != 0) { /* parent */ /* register an event handler for when the child terminates */ uproc->cb = http_del_client; uloop_process_add(uproc); close(client); } else { /* child */ FILE *fp; char buffer[BUFSIZ]; char *auth_digest; int8_t auth_status = 0; fp = fdopen(client, "r+"); DDF("+++ RECEIVED HTTP REQUEST +++\n"); while (fgets(buffer, sizeof(buffer), fp)) { char *username = config->local->username; char *password = config->local->password; if (!username || !password) { // if we dont have username or password configured proceed with connecting to ACS auth_status = 1; } else if (auth_digest = strstr(buffer, "Authorization: Digest ")) { if (http_digest_auth_check("GET", "/", auth_digest + strlen("Authorization: Digest "), REALM, username, password, 300) == MHD_YES) auth_status = 1; else { auth_status = 0; log_message(NAME, L_NOTICE, "Connection Request authorization failed\n"); } } if (buffer[0] == '\r' || buffer[0] == '\n') { /* end of http request (empty line) */ goto http_end_child; } } error_child: /* here we are because of an error, e.g. timeout */ status = ETIMEDOUT|ENOMEM; goto done_child; http_end_child: fflush(fp); if (auth_status) { status = 0; fputs("HTTP/1.1 200 OK\r\n", fp); fputs("Content-Length: 0\r\n", fp); } else { status = EACCES; fputs("HTTP/1.1 401 Unauthorized\r\n", fp); fputs("Content-Length: 0\r\n", fp); fputs("Connection: close\r\n", fp); http_digest_auth_fail_response(fp, "GET", "/", REALM, OPAQUE); fputs("\r\n", fp); } fputs("\r\n", fp); goto done_child; done_child: fclose(fp); DDF("--- RECEIVED HTTP REQUEST ---\n"); exit(status); } } }
int netifd_start_process(const char **argv, char **env, struct netifd_process *proc) { int pfds[2]; int pid; netifd_kill_process(proc); if (pipe(pfds) < 0) return -1; if ((pid = fork()) < 0) goto error; if (!pid) { int i; if (env) { while (*env) { putenv(*env); env++; } } if (proc->dir_fd >= 0) if (fchdir(proc->dir_fd)) {} close(pfds[0]); for (i = 0; i <= 2; i++) { if (pfds[1] == i) continue; dup2(pfds[1], i); } if (pfds[1] > 2) close(pfds[1]); execvp(argv[0], (char **) argv); exit(127); } if (pid < 0) goto error; close(pfds[1]); proc->uloop.cb = netifd_process_cb; proc->uloop.pid = pid; uloop_process_add(&proc->uloop); list_add_tail(&proc->list, &process_list); system_fd_set_cloexec(pfds[0]); proc->log.stream.string_data = true; proc->log.stream.notify_read = netifd_process_log_read_cb; ustream_fd_init(&proc->log, pfds[0]); return 0; error: close(pfds[0]); close(pfds[1]); return -1; }
int main(int argc, char **argv, char **envp) { char *json = NULL; int status, ch, policy = EPERM; pid_t child; while ((ch = getopt(argc, argv, "f:p:")) != -1) { switch (ch) { case 'f': json = optarg; break; case 'p': policy = atoi(optarg); break; } } argc -= optind; argv += optind; if (!argc) return -1; if (getenv("TRACE_DEBUG")) debug = 1; unsetenv("TRACE_DEBUG"); child = fork(); if (child == 0) { char **_argv = calloc(argc + 1, sizeof(char *)); char **_envp; char preload[] = "LD_PRELOAD=/lib/libpreload-trace.so"; int envc = 1; int ret; memcpy(_argv, argv, argc * sizeof(char *)); while (envp[envc++]) ; _envp = calloc(envc, sizeof(char *)); memcpy(&_envp[1], _envp, envc * sizeof(char *)); *envp = preload; ret = execve(_argv[0], _argv, envp); ERROR("failed to exec %s: %s\n", _argv[0], strerror(errno)); return ret; } if (child < 0) return -1; syscall_max = ARRAY_SIZE(syscall_names); syscall_count = calloc(syscall_max, sizeof(int)); waitpid(child, &status, 0); if (!WIFSTOPPED(status)) { ERROR("failed to start %s\n", *argv); return -1; } ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACESYSGOOD); ptrace(PTRACE_SYSCALL, child, 0, 0); uloop_init(); tracer.pid = child; tracer.cb = tracer_cb; uloop_process_add(&tracer); uloop_run(); uloop_done(); if (!json) if (asprintf(&json, "/tmp/%s.%u.json", basename(*argv), child) < 0) ERROR("failed to allocate output path: %s\n", strerror(errno)); print_syscalls(policy, json); return 0; }