void brp_parse_config() { /* * Free memory associated with previous config parsing */ free_config(); /* * Ensure we're using a root-modifiable-only configuration file, just in case. */ if (!check_config_secure(CONFIG)) { fprintf(stderr, "brp: config file at "CONFIG" is not secure, refusing to continue.\n"); exit(1); } int nsec; struct section *sec = parse_config(CONFIG, &nsec), *sec_curr = sec; if (sec == NULL) exit(1); size_t arrsz = 0; while(sec_curr) { if (strcmp(sec_curr->name, "stratum-order")) out_item_count += sec_curr->nent; else { arrsz = sec_curr->nent+1; stratum = calloc(sec_curr->nent+1, sizeof(void *)); struct entry *e = sec_curr->e; while(e) { _add_stratum(&stratum, &arrsz, e->lhs); e = e->next; } } sec_curr = sec_curr->next; } struct dirent *dent; DIR *d = opendir("/bedrock/run/enabled_strata/"); if (!d) { perror("Failed to list enabled strata"); exit(1); } if (!arrsz) { arrsz = 1; stratum = calloc(1, sizeof(void *)); } while((dent = readdir(d))) if (strncmp(dent->d_name, ".", 1) && strncmp(dent->d_name, "..", 2)) _add_stratum(&stratum, &arrsz, dent->d_name); closedir(d); char **tmp_s = stratum; nstratum = 0; while(*tmp_s) { nstratum++; tmp_s++; } stratum_len = malloc(sizeof(size_t)*nstratum); for(int st = 0; st < nstratum; st++) stratum_len[st] = strlen(stratum[st]); out_items = malloc(out_item_count*sizeof(struct out_item)); sec_curr = sec; int i = 0; int curr_filter = 0; while(sec_curr) { struct entry *e = sec_curr->e; if (strcmp(sec_curr->name, "pass") == 0) { curr_filter = FILTER_PASS; } else if (strcmp(sec_curr->name, "brc-wrap") == 0) { curr_filter = FILTER_BRC_WRAP; } else if (strcmp(sec_curr->name, "exec-filter") == 0) { curr_filter = FILTER_EXEC; } else if (strcmp(sec_curr->name, "stratum-order") == 0){ sec_curr = sec_curr->next; continue; } else { fprintf(stderr, "brp: Failed to parse config\n"); exit(1); } while(e) { /* get path */ out_items[i].path = strdup(e->lhs); out_items[i].path_len = e->lhs_len; if (out_items[i].path[out_items[i].path_len-1] == '/') { out_items[i].file_type = FILE_TYPE_DIRECTORY; out_items[i].path[--out_items[i].path_len] = '\0'; } else out_items[i].file_type = FILE_TYPE_NORMAL; out_items[i].filter = curr_filter; out_items[i].in_items = malloc(e->nrhs*sizeof(struct in_item)); struct rhs *r = e->r; struct in_item *in_items = out_items[i].in_items; int j = 0; while(r) { in_items[j].stratum_id = -1; if (r->str[0] != '/') { // The in_path might start with a stratum // specification char *colon = strchr(r->str, ':'); if (!colon || colon[1] != '/') { // Invalid path, just ignore r = r->next; continue; } in_items[j].path = strdup(colon+1); for (int st = 0; st < nstratum; st++) if (strncmp(r->str, stratum[st], colon-r->str) == 0) { in_items[j].stratum_id = st; break; } if (in_items[j].stratum_id == -1) { r = r->next; continue; } } else in_items[j].path = strdup(r->str); in_items[j].path_len = strlen(in_items[j].path); j++; r = r->next; } out_items[i].in_item_count = j; i++; e = e->next; } sec_curr = sec_curr->next; } free_sections(sec); }
void elf_mod_symload(int strtablen) { Elf_Ehdr ehdr; char *shstrtab; struct elf_section *head, *s; char *symbuf, *strbuf; /* * Seek to the text offset to start loading... */ if (lseek(modfd, 0, SEEK_SET) == -1) err(12, "lseek"); if (read_elf_header(modfd, &ehdr) < 0) return; shstrtab = read_shstring_table(modfd, &ehdr); read_sections(modfd, &ehdr, shstrtab, &head); for (s = head; s; s = s->next) { struct elf_section *p = s; if ((p->type == SHT_SYMTAB) || (p->type == SHT_DYNSYM)) { if (debug) fprintf(stderr, "loading `%s': addr = %p, " "size = %#lx\n", s->name, s->addr, (u_long)s->size); /* * Seek to the file offset to start loading it... */ if (lseek(modfd, p->offset, SEEK_SET) == -1) err(12, "lseek"); symbuf = malloc(p->size); if (symbuf == 0) err(13, "malloc"); if (read(modfd, symbuf, p->size) != p->size) err(14, "read"); loadsym(symbuf, p->size); free(symbuf); } } for (s = head; s; s = s->next) { struct elf_section *p = s; if ((p->type == SHT_STRTAB) && (strcmp(p->name, ".strtab") == 0 )) { if (debug) fprintf(stderr, "loading `%s': addr = %p, " "size = %#lx\n", s->name, s->addr, (u_long)s->size); /* * Seek to the file offset to start loading it... */ if (lseek(modfd, p->offset, SEEK_SET) == -1) err(12, "lseek"); strbuf = malloc(p->size); if (strbuf == 0) err(13, "malloc"); if (read(modfd, strbuf, p->size) != p->size) err(14, "read"); loadsym(strbuf, p->size); free(strbuf); } } free(shstrtab); free_sections(head); return; }
/* return size needed by the module */ int elf_mod_sizes(int fd, size_t *modsize, int *strtablen, struct lmc_resrv *resrvp, struct stat *sp) { Elf_Ehdr ehdr; ssize_t off = 0; size_t data_hole = 0; char *shstrtab, *strtab; struct elf_section *head, *s, *stab; if (read_elf_header(fd, &ehdr) < 0) return -1; shstrtab = read_shstring_table(fd, &ehdr); read_sections(fd, &ehdr, shstrtab, &head); for (s = head; s; s = s->next) { /* XXX impossible! */ if (s->type == SHT_STRTAB && s->type == SHT_SYMTAB && s->type == SHT_DYNSYM) continue; if (debug) fprintf(stderr, "%s: addr = %p size = %#lx align = %#lx\n", s->name, s->addr, (u_long)s->size, (u_long)s->align); /* * XXX try to get rid of the hole before the data * section that GNU-ld likes to put there */ if (strcmp(s->name, ".data") == 0 && s->addr > (void *)off) { data_offset = roundup(off, s->align); if (debug) fprintf(stderr, ".data section forced to " "offset %p (was %p)\n", (void *)data_offset, s->addr); /* later remove size of compressed hole from off */ data_hole = (ssize_t)s->addr - data_offset; } off = (ssize_t)s->addr + s->size; } off -= data_hole; /* XXX round to pagesize? */ *modsize = roundup(off, sysconf(_SC_PAGESIZE)); /* get string table length */ strtab = read_string_table(fd, head, strtablen); free(shstrtab); free(strtab); /* get symbol table sections */ get_symtab(&head); stab = head; resrvp->sym_symsize = 0; while (stab) { resrvp->sym_symsize += stab->size; stab = stab->next; } resrvp->sym_size = resrvp->sym_symsize + *strtablen; free_sections(head); return (0); }
/* load a prelinked module; returns entry point */ void * elf_mod_load(int fd) { Elf_Ehdr ehdr; size_t zero_size = 0; size_t b; ssize_t n; char *shstrtab; struct elf_section *head, *s; char buf[10 * BUFSIZ]; void *addr = NULL; if (read_elf_header(fd, &ehdr) < 0) return NULL; shstrtab = read_shstring_table(fd, &ehdr); read_sections(fd, &ehdr, shstrtab, &head); for (s = head; s; s = s->next) { if (s->type != SHT_STRTAB && s->type != SHT_SYMTAB && s->type != SHT_DYNSYM) { if (debug) fprintf(stderr, "loading `%s': addr = %p, " "size = %#lx\n", s->name, s->addr, (u_long)s->size); if (s->type == SHT_NOBITS) { /* skip some space */ zero_size += s->size; } else { if (addr != NULL) { /* * if there is a gap in the prelinked * module, transfer some empty space. */ zero_size += (char*)s->addr - (char*)addr; } if (zero_size) { loadspace(zero_size); zero_size = 0; } b = s->size; if (lseek(fd, s->offset, SEEK_SET) == -1) err(1, "lseek"); while (b) { n = read(fd, buf, MIN(b, sizeof(buf))); if (n == 0) errx(1, "unexpected EOF"); if (n < 0) err(1, "read"); loadbuf(buf, n); b -= n; } addr = (char*)s->addr + s->size; } } } if (zero_size) loadspace(zero_size); free_sections(head); free(shstrtab); return (void *)ehdr.e_entry; }
int main(int argc, char **argv) { struct option long_options[] = { {"wordy", no_argument, NULL, 'w'}, {"help", no_argument, NULL, 'h'}, }; struct epoll_event events[10]; int epoll_fd = -1; struct itimerspec it; int ret; int status = EXIT_SUCCESS; if (argc > 0) progname = argv[0]; for (;;) { int c; c = getopt_long(argc, argv, "wh", long_options, NULL); if (c == -1) break; switch (c) { case 'w': wordy = true; break; case 'h': usage(false); default: usage(true); } } if (optind != argc) usage(true); dpy = XOpenDisplay(NULL); if (!dpy) { fprintf(stderr, "unable to open display '%s'\n", XDisplayName(NULL)); status = EXIT_FAILURE; goto out; } root = DefaultRootWindow(dpy); epoll_fd = epoll_create1(EPOLL_CLOEXEC); if (epoll_fd == -1) { perror("epoll_create1"); status = EXIT_FAILURE; goto out; } ret = signal_fd_init(epoll_fd); if (ret == -1) { status = EXIT_FAILURE; goto out; } ret = timer_fd_init(epoll_fd); if (ret == -1) { status = EXIT_FAILURE; goto out; } ret = ctl_fd_init(epoll_fd); if (ret == -1) { status = EXIT_FAILURE; goto out; } if (init_plugins()) { status = EXIT_FAILURE; goto out; } if (init_sections(epoll_fd, config, sizeof(config) / sizeof(*config))) { status = EXIT_FAILURE; goto out; } if (update_timer_sections()) { status = EXIT_FAILURE; goto out; } it.it_interval.tv_sec = 1; it.it_interval.tv_nsec = 0; it.it_value.tv_sec = 1; it.it_value.tv_nsec = 0; ret = timerfd_settime(timer_cb.fd, 0, &it, NULL); if (ret == -1) { perror("timerfd_settime"); status = EXIT_FAILURE; goto out; } while (!quit) { int i; update = false; ret = epoll_wait(epoll_fd, events, sizeof(events) / sizeof(events[0]), -1); if (ret == -1) { if (errno == EINTR) continue; perror("epoll_wait"); status = EXIT_FAILURE; goto out; } for (i = 0; i < ret; i++) { struct epoll_callback *cb = events[i].data.ptr; ret = cb->callback(cb->fd, cb->data, events[i].events); if (ret) { status = EXIT_FAILURE; goto out; } } if (update) { ret = update_statusbar(); if (ret) { status = EXIT_FAILURE; goto out; } } } status = EXIT_SUCCESS; out: if (epoll_fd != -1) close(epoll_fd); free_sections(); if (ctl_cb.fd != -1) { close(ctl_cb.fd); unlink(ctl_addr.sun_path); } if (timer_cb.fd != -1) close(timer_cb.fd); if (signal_cb.fd != -1) close(signal_cb.fd); str_free(&status_str); if (dpy) { XStoreName(dpy, root, ""); XFlush(dpy); XCloseDisplay(dpy); } return status; }