From 13590ca98ac2fd4939b683adbfdd63392b559f3f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 28 Nov 2015 14:58:01 +0100 Subject: Strip down procd to the necessary code, update copyright --- CMakeLists.txt | 89 +------ early.c | 84 +++++++ initd/early.c | 106 --------- initd/init.c | 121 ---------- initd/init.h | 32 --- initd/mkdev.c | 125 ---------- initd/preinit.c | 122 ---------- initd/zram.c | 128 ---------- inittab.c | 1 + jail/capabilities.c | 116 --------- jail/capabilities.h | 14 -- jail/elf.c | 355 ---------------------------- jail/elf.h | 38 --- jail/jail.c | 459 ------------------------------------ jail/log.h | 27 --- jail/preload.c | 80 ------- jail/seccomp-bpf.h | 89 ------- jail/seccomp.c | 142 ----------- jail/seccomp.h | 19 -- libc-compat.h | 10 - log.h | 1 + make_capabilities_h.sh | 10 - make_syscall_h.sh | 18 -- plug/coldplug.c | 69 ------ plug/hotplug.c | 610 ------------------------------------------------ plug/hotplug.h | 25 -- plug/udevtrigger.c | 264 --------------------- preload.h | 56 ----- procd.c | 24 +- procd.h | 3 + rcS.c | 1 + rcS.h | 1 + service/instance.c | 1 + service/instance.h | 1 + service/service.c | 57 +---- service/service.h | 17 +- service/setlbf.c | 6 - service/trigger.c | 1 + service/validate.c | 163 ------------- service/watch.c | 1 + signal.c | 1 + state.c | 17 +- system.c | 1 + trace/preload.c | 80 ------- trace/trace.c | 225 ------------------ ubus.c | 1 + upgraded/CMakeLists.txt | 17 -- upgraded/upgraded.c | 80 ------- utils/askfirst.c | 1 + utils/utils.c | 1 + utils/utils.h | 1 + watchdog.c | 1 + watchdog.h | 1 + 53 files changed, 121 insertions(+), 3792 deletions(-) create mode 100644 early.c delete mode 100644 initd/early.c delete mode 100644 initd/init.c delete mode 100644 initd/init.h delete mode 100644 initd/mkdev.c delete mode 100644 initd/preinit.c delete mode 100644 initd/zram.c delete mode 100644 jail/capabilities.c delete mode 100644 jail/capabilities.h delete mode 100644 jail/elf.c delete mode 100644 jail/elf.h delete mode 100644 jail/jail.c delete mode 100644 jail/log.h delete mode 100644 jail/preload.c delete mode 100644 jail/seccomp-bpf.h delete mode 100644 jail/seccomp.c delete mode 100644 jail/seccomp.h delete mode 100644 libc-compat.h delete mode 100755 make_capabilities_h.sh delete mode 100755 make_syscall_h.sh delete mode 100644 plug/coldplug.c delete mode 100644 plug/hotplug.c delete mode 100644 plug/hotplug.h delete mode 100644 plug/udevtrigger.c delete mode 100644 preload.h delete mode 100644 service/setlbf.c delete mode 100644 service/validate.c delete mode 100644 trace/preload.c delete mode 100644 trace/trace.c delete mode 100644 upgraded/CMakeLists.txt delete mode 100644 upgraded/upgraded.c diff --git a/CMakeLists.txt b/CMakeLists.txt index d749c25..30b1410 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,21 +6,10 @@ ADD_DEFINITIONS(-Os -ggdb -Wall -Werror --std=gnu99 -Wmissing-declarations) SET(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "") -IF(APPLE) - INCLUDE_DIRECTORIES(/opt/local/include) - LINK_DIRECTORIES(/opt/local/lib) -ENDIF() - - -ADD_LIBRARY(setlbf SHARED service/setlbf.c) -INSTALL(TARGETS setlbf - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} -) - -SET(SOURCES procd.c signal.c watchdog.c state.c inittab.c rcS.c ubus.c system.c - service/service.c service/instance.c service/validate.c service/trigger.c service/watch.c - plug/coldplug.c plug/hotplug.c utils/utils.c) +SET(SOURCES procd.c signal.c watchdog.c state.c inittab.c rcS.c ubus.c system.c early.c + service/service.c service/instance.c service/trigger.c service/watch.c + utils/utils.c) SET(LIBS ubox ubus json-c blobmsg_json json_script) @@ -28,84 +17,14 @@ IF(DEBUG) ADD_DEFINITIONS(-DDEBUG -g3) ENDIF() -IF(ZRAM_TMPFS) - ADD_DEFINITIONS(-DZRAM_TMPFS) - SET(SOURCES_ZRAM initd/zram.c) -ENDIF() - -IF(BUILD_UPGRADED) - add_subdirectory(upgraded) -ENDIF() - -ADD_EXECUTABLE(procd ${SOURCES}) -TARGET_LINK_LIBRARIES(procd ${LIBS}) -INSTALL(TARGETS procd - RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR} -) - - -ADD_EXECUTABLE(init initd/init.c initd/early.c initd/preinit.c initd/mkdev.c watchdog.c - utils/utils.c ${SOURCES_ZRAM}) +ADD_EXECUTABLE(init ${SOURCES}) TARGET_LINK_LIBRARIES(init ${LIBS}) INSTALL(TARGETS init RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR} ) -ADD_EXECUTABLE(udevtrigger plug/udevtrigger.c) -INSTALL(TARGETS udevtrigger - RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR} -) - - ADD_EXECUTABLE(askfirst utils/askfirst.c) INSTALL(TARGETS askfirst RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR} ) - -ADD_CUSTOM_COMMAND( - OUTPUT syscall-names.h - COMMAND ./make_syscall_h.sh ${CMAKE_C_COMPILER} > ./syscall-names.h - DEPENDS ./make_syscall_h.sh -) -ADD_CUSTOM_TARGET(syscall-names-h DEPENDS syscall-names.h) - -ADD_CUSTOM_COMMAND( - OUTPUT capabilities-names.h - COMMAND ./make_capabilities_h.sh ${CMAKE_C_COMPILER} > ./capabilities-names.h - DEPENDS ./make_capabilities_h.sh -) -ADD_CUSTOM_TARGET(capabilities-names-h DEPENDS capabilities-names.h) - -IF(SECCOMP_SUPPORT) -ADD_LIBRARY(preload-seccomp SHARED jail/preload.c jail/seccomp.c) -TARGET_LINK_LIBRARIES(preload-seccomp dl ubox blobmsg_json) -INSTALL(TARGETS preload-seccomp - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} -) -ADD_DEPENDENCIES(preload-seccomp syscall-names-h) -endif() - -IF(JAIL_SUPPORT) -ADD_EXECUTABLE(ujail jail/jail.c jail/elf.c jail/capabilities.c) -TARGET_LINK_LIBRARIES(ujail ubox blobmsg_json) -INSTALL(TARGETS ujail - RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR} -) -ADD_DEPENDENCIES(ujail capabilities-names-h) -endif() - -IF(UTRACE_SUPPORT) -ADD_EXECUTABLE(utrace trace/trace.c) -TARGET_LINK_LIBRARIES(utrace ubox ${json} blobmsg_json) -INSTALL(TARGETS utrace - RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR} -) -ADD_DEPENDENCIES(utrace syscall-names-h) - -ADD_LIBRARY(preload-trace SHARED trace/preload.c) -TARGET_LINK_LIBRARIES(preload-trace dl) -INSTALL(TARGETS preload-trace - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} -) -endif() diff --git a/early.c b/early.c new file mode 100644 index 0000000..92ec6bd --- /dev/null +++ b/early.c @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2013 Felix Fietkau + * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "procd.h" + +static void +early_console(const char *dev) +{ + struct stat s; + int dd; + + if (stat(dev, &s)) { + ERROR("Failed to stat %s\n", dev); + return; + } + + dd = open(dev, O_RDWR); + if (dd < 0) + dd = open("/dev/null", O_RDWR); + + dup2(dd, STDIN_FILENO); + dup2(dd, STDOUT_FILENO); + dup2(dd, STDERR_FILENO); + + if (dd != STDIN_FILENO && + dd != STDOUT_FILENO && + dd != STDERR_FILENO) + close(dd); + + fcntl(STDERR_FILENO, F_SETFL, fcntl(STDERR_FILENO, F_GETFL) | O_NONBLOCK); +} + +static void +early_mounts(void) +{ + unsigned int oldumask = umask(0); + + mount("proc", "/proc", "proc", MS_NOATIME | MS_NODEV | MS_NOEXEC | MS_NOSUID, 0); + mount("sys", "/sys", "sysfs", MS_NOATIME | MS_NODEV | MS_NOEXEC | MS_NOSUID, 0); + mount("cgroup", "/sys/fs/cgroup", "cgroup", MS_NODEV | MS_NOEXEC | MS_NOSUID, "none"); + mount("dev", "/dev", "devtmpfs", MS_NOATIME | MS_NOSUID, "mode=0755,size=512K"); + mkdir("/dev/pts", 0755); + mount("devpts", "/dev/pts", "devpts", MS_NOATIME | MS_NOEXEC | MS_NOSUID, "mode=600"); + mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOATIME, 0); + + umask(oldumask); +} + +static void +early_env(void) +{ + setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin", 1); +} + +void +procd_early(void) +{ + early_mounts(); + early_console("/dev/console"); + early_env(); + + LOG("Console is alive\n"); +} diff --git a/initd/early.c b/initd/early.c deleted file mode 100644 index e87774f..0000000 --- a/initd/early.c +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright (C) 2013 Felix Fietkau - * Copyright (C) 2013 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include - -#include -#include -#include -#include - -#include "init.h" -#include "../libc-compat.h" - -static void -early_dev(void) -{ - mkdev("*", 0600); - mknod("/dev/null", 0666, makedev(1, 3)); -} - -static void -early_console(const char *dev) -{ - struct stat s; - int dd; - - if (stat(dev, &s)) { - ERROR("Failed to stat %s\n", dev); - return; - } - - dd = open(dev, O_RDWR); - if (dd < 0) - dd = open("/dev/null", O_RDWR); - - dup2(dd, STDIN_FILENO); - dup2(dd, STDOUT_FILENO); - dup2(dd, STDERR_FILENO); - - if (dd != STDIN_FILENO && - dd != STDOUT_FILENO && - dd != STDERR_FILENO) - close(dd); - - fcntl(STDERR_FILENO, F_SETFL, fcntl(STDERR_FILENO, F_GETFL) | O_NONBLOCK); -} - -static void -early_mounts(void) -{ - unsigned int oldumask = umask(0); - - mount("proc", "/proc", "proc", MS_NOATIME | MS_NODEV | MS_NOEXEC | MS_NOSUID, 0); - mount("sysfs", "/sys", "sysfs", MS_NOATIME | MS_NODEV | MS_NOEXEC | MS_NOSUID, 0); - mount("cgroup", "/sys/fs/cgroup", "cgroup", MS_NODEV | MS_NOEXEC | MS_NOSUID, 0); - mount("tmpfs", "/dev", "tmpfs", MS_NOATIME | MS_NOSUID, "mode=0755,size=512K"); - ignore(symlink("/tmp/shm", "/dev/shm")); - mkdir("/dev/pts", 0755); - mount("devpts", "/dev/pts", "devpts", MS_NOATIME | MS_NOEXEC | MS_NOSUID, "mode=600"); - early_dev(); - - early_console("/dev/console"); - if (mount_zram_on_tmp()) { - mount("tmpfs", "/tmp", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOATIME, 0); - mkdir("/tmp/shm", 01777); - } else { - mkdir("/tmp/shm", 01777); - mount("tmpfs", "/tmp/shm", "tmpfs", MS_NOSUID | MS_NODEV | MS_NOATIME, - "mode=01777"); - } - mkdir("/tmp/run", 0777); - mkdir("/tmp/lock", 0777); - mkdir("/tmp/state", 0777); - umask(oldumask); -} - -static void -early_env(void) -{ - setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin", 1); -} - -void -early(void) -{ - if (getpid() != 1) - return; - - early_mounts(); - early_env(); - - LOG("Console is alive\n"); -} diff --git a/initd/init.c b/initd/init.c deleted file mode 100644 index 9818c4f..0000000 --- a/initd/init.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (C) 2013 Felix Fietkau - * Copyright (C) 2013 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../utils/utils.h" -#include "init.h" -#include "../watchdog.h" - -unsigned int debug = 0; - -static void -signal_shutdown(int signal, siginfo_t *siginfo, void *data) -{ - fprintf(stderr, "reboot\n"); - fflush(stderr); - sync(); - sleep(2); - reboot(RB_AUTOBOOT); - while (1) - ; -} - -static struct sigaction sa_shutdown = { - .sa_sigaction = signal_shutdown, - .sa_flags = SA_SIGINFO -}; - -static void -cmdline(void) -{ - char line[20]; - char* res; - long r; - - res = get_cmdline_val("init_debug", line, sizeof(line)); - if (res != NULL) { - r = strtol(line, NULL, 10); - if ((r != LONG_MIN) && (r != LONG_MAX)) - debug = (int) r; - } -} - -int -main(int argc, char **argv) -{ - pid_t pid; - - ulog_open(ULOG_KMSG, LOG_DAEMON, "init"); - - sigaction(SIGTERM, &sa_shutdown, NULL); - sigaction(SIGUSR1, &sa_shutdown, NULL); - sigaction(SIGUSR2, &sa_shutdown, NULL); - - early(); - cmdline(); - watchdog_init(1); - - pid = fork(); - if (!pid) { - char *kmod[] = { "/sbin/kmodloader", "/etc/modules-boot.d/", NULL }; - - if (debug < 3) { - int fd = open("/dev/null", O_RDWR); - - if (fd > -1) { - dup2(fd, STDIN_FILENO); - dup2(fd, STDOUT_FILENO); - dup2(fd, STDERR_FILENO); - if (fd > STDERR_FILENO) - close(fd); - } - } - execvp(kmod[0], kmod); - ERROR("Failed to start kmodloader\n"); - exit(-1); - } - if (pid <= 0) { - ERROR("Failed to start kmodloader instance\n"); - } else { - int i; - - for (i = 0; i < 120; i++) { - if (waitpid(pid, NULL, WNOHANG) > 0) - break; - sleep(1); - watchdog_ping(); - } - } - uloop_init(); - preinit(); - uloop_run(); - - return 0; -} diff --git a/initd/init.h b/initd/init.h deleted file mode 100644 index 274645b..0000000 --- a/initd/init.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2013 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _INIT_H__ -#define _INIT_H__ - -#include - -#include "../log.h" - -void preinit(void); -void early(void); -int mkdev(const char *progname, int progmode); - -#ifdef ZRAM_TMPFS -int mount_zram_on_tmp(void); -#else -static inline int mount_zram_on_tmp(void) { - return -ENOSYS; -} -#endif -#endif diff --git a/initd/mkdev.c b/initd/mkdev.c deleted file mode 100644 index e6d3d0c..0000000 --- a/initd/mkdev.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2013 Felix Fietkau - * Copyright (C) 2013 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define _DEFAULT_SOURCE - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "init.h" - -static char **patterns; -static int n_patterns; -static char buf[PATH_MAX]; -static char buf2[PATH_MAX]; -static unsigned int mode = 0600; - -static bool find_pattern(const char *name) -{ - int i; - - for (i = 0; i < n_patterns; i++) - if (!fnmatch(patterns[i], name, 0)) - return true; - - return false; -} - -static void make_dev(const char *path, bool block, int major, int minor) -{ - unsigned int oldumask = umask(0); - unsigned int _mode = mode | (block ? S_IFBLK : S_IFCHR); - - DEBUG(4, "Creating %s device %s(%d,%d)\n", - block ? "block" : "character", - path, major, minor); - - mknod(path, _mode, makedev(major, minor)); - umask(oldumask); -} - -static void find_devs(bool block) -{ - char *path = block ? "/sys/dev/block" : "/sys/dev/char"; - struct dirent *dp; - DIR *dir; - - dir = opendir(path); - if (!dir) - return; - - path = buf2 + sprintf(buf2, "%s/", path); - while ((dp = readdir(dir)) != NULL) { - char *c; - int major = 0, minor = 0; - int len; - - if (dp->d_type != DT_LNK) - continue; - - if (sscanf(dp->d_name, "%d:%d", &major, &minor) != 2) - continue; - - strcpy(path, dp->d_name); - len = readlink(buf2, buf, sizeof(buf)); - if (len <= 0) - continue; - - buf[len] = 0; - if (!find_pattern(buf)) - continue; - - c = strrchr(buf, '/'); - if (!c) - continue; - - c++; - make_dev(c, block, major, minor); - } - closedir(dir); -} - -static char *add_pattern(const char *name) -{ - char *str = malloc(strlen(name) + 2); - - str[0] = '*'; - strcpy(str + 1, name); - return str; -} - -int mkdev(const char *name, int _mode) -{ - char *pattern; - - if (chdir("/dev")) - return 1; - - pattern = add_pattern(name); - patterns = &pattern; - mode = _mode; - n_patterns = 1; - find_devs(true); - find_devs(false); - return chdir("/"); -} diff --git a/initd/preinit.c b/initd/preinit.c deleted file mode 100644 index f38d8ef..0000000 --- a/initd/preinit.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (C) 2013 Felix Fietkau - * Copyright (C) 2013 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include - -#include -#include -#include - -#include - -#include - -#include "init.h" -#include "../watchdog.h" - -static struct uloop_process preinit_proc; -static struct uloop_process plugd_proc; - -static void -check_dbglvl(void) -{ - FILE *fp = fopen("/tmp/debug_level", "r"); - int lvl = 0; - - if (!fp) - return; - if (fscanf(fp, "%d", &lvl) == EOF) - ERROR("failed to read debug level\n"); - fclose(fp); - unlink("/tmp/debug_level"); - - if (lvl > 0 && lvl < 5) - debug = lvl; -} - -static void -spawn_procd(struct uloop_process *proc, int ret) -{ - char *wdt_fd = watchdog_fd(); - char *argv[] = { "/sbin/procd", NULL}; - struct stat s; - char dbg[2]; - - if (plugd_proc.pid > 0) - kill(plugd_proc.pid, SIGKILL); - - if (!stat("/tmp/sysupgrade", &s)) - while (true) - sleep(1); - - unsetenv("INITRAMFS"); - unsetenv("PREINIT"); - DEBUG(2, "Exec to real procd now\n"); - if (wdt_fd) - setenv("WDTFD", wdt_fd, 1); - check_dbglvl(); - if (debug > 0) { - snprintf(dbg, 2, "%d", debug); - setenv("DBGLVL", dbg, 1); - } - - execvp(argv[0], argv); -} - -static void -plugd_proc_cb(struct uloop_process *proc, int ret) -{ - proc->pid = 0; -} - -void -preinit(void) -{ - char *init[] = { "/bin/sh", "/etc/preinit", NULL }; - char *plug[] = { "/sbin/procd", "-h", "/etc/hotplug-preinit.json", NULL }; - - 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); - - 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); -} diff --git a/initd/zram.c b/initd/zram.c deleted file mode 100644 index 49480af..0000000 --- a/initd/zram.c +++ /dev/null @@ -1,128 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "../log.h" - -#include "init.h" - -#define KB(x) (x * 1024) - -#define ZRAM_MOD_PATH "/lib/modules/%s/zram.ko" -#define EXT4_MOD_PATH "/lib/modules/%s/ext4.ko" - -static long -proc_meminfo(void) -{ - FILE *fp; - char line[256]; - char *key; - long val = KB(16); - - fp = fopen("/proc/meminfo", "r"); - if (fp == NULL) { - ERROR("Can't open /proc/meminfo: %s\n", strerror(errno)); - return errno; - } - - while (fgets(line, sizeof(line), fp)) { - key = strtok(line, ":"); - if (strcasecmp(key, "MemTotal")) - continue; - val = atol(strtok(NULL, " kB\n")); - break; - } - fclose(fp); - - if (val > KB(32)) - val = KB(32); - - return val; -} - -static int -early_insmod(char *module) -{ - pid_t pid = fork(); - - if (!pid) { - char *modprobe[] = { "/usr/sbin/modprobe", NULL, NULL }; - char *path; - struct utsname ver; - - uname(&ver); - path = alloca(sizeof(module) + strlen(ver.release) + 1); - sprintf(path, module, ver.release); - modprobe[1] = path; - execvp(modprobe[0], modprobe); - ERROR("Can't exec /usr/sbin/modprobe\n"); - exit(-1); - } - - if (pid <= 0) { - ERROR("Can't exec /usr/sbin/modprobe\n"); - return -1; - } else { - waitpid(pid, NULL, 0); - } - - return 0; -} - - -int -mount_zram_on_tmp(void) -{ - char *mkfs[] = { "/usr/sbin/mkfs.ext4", "-b", "4096", "-F", "-L", "TEMP", "-m", "0", "/dev/zram0", NULL }; - FILE *fp; - long zramsize; - pid_t pid; - int ret; - - if (early_insmod(ZRAM_MOD_PATH) || early_insmod(EXT4_MOD_PATH)) { - ERROR("failed to insmod zram support\n"); - return -1; - } - - mkdev("*", 0600); - - zramsize = proc_meminfo() / 2; - fp = fopen("/sys/block/zram0/disksize", "r+"); - if (fp == NULL) { - ERROR("Can't open /sys/block/zram0/disksize: %s\n", strerror(errno)); - return errno; - } - fprintf(fp, "%ld", KB(zramsize)); - fclose(fp); - - pid = fork(); - if (!pid) { - execvp(mkfs[0], mkfs); - ERROR("Can't exec /sbin/mkfs.ext4\n"); - exit(-1); - } else if (pid <= 0) { - ERROR("Can't exec /sbin/mkfs.ext4\n"); - return -1; - } else { - waitpid(pid, NULL, 0); - } - - ret = mount("/dev/zram0", "/tmp", "ext4", MS_NOSUID | MS_NODEV | MS_NOATIME, "errors=continue,noquota"); - if (ret < 0) { - ERROR("Can't mount /dev/zram0 on /tmp: %s\n", strerror(errno)); - return errno; - } - - LOG("Using up to %ld kB of RAM as ZRAM storage on /mnt\n", zramsize); - - return 0; -} diff --git a/inittab.c b/inittab.c index f8f0218..4675aca 100644 --- a/inittab.c +++ b/inittab.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/jail/capabilities.c b/jail/capabilities.c deleted file mode 100644 index b5ea965..0000000 --- a/jail/capabilities.c +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (C) 2015 Etienne CHAMPETIER - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define _GNU_SOURCE 1 -#include -#include - -#include -#include - -#include "log.h" -#include "../capabilities-names.h" -#include "capabilities.h" - -static int find_capabilities(const char *name) -{ - int i; - - for (i = 0; i <= CAP_LAST_CAP; i++) - if (capabilities_names[i] && !strcmp(capabilities_names[i], name)) - return i; - - return -1; -} - -int drop_capabilities(const char *file) -{ - enum { - CAP_KEEP, - CAP_DROP, - __CAP_MAX - }; - static const struct blobmsg_policy policy[__CAP_MAX] = { - [CAP_KEEP] = { .name = "cap.keep", .type = BLOBMSG_TYPE_ARRAY }, - [CAP_DROP] = { .name = "cap.drop", .type = BLOBMSG_TYPE_ARRAY }, - }; - struct blob_buf b = { 0 }; - struct blob_attr *tb[__CAP_MAX]; - struct blob_attr *cur; - int rem, cap; - char *name; - uint64_t capdrop = 0LLU; - - DEBUG("dropping capabilities\n"); - - blob_buf_init(&b, 0); - if (!blobmsg_add_json_from_file(&b, file)) { - ERROR("failed to load %s\n", file); - return -1; - } - - blobmsg_parse(policy, __CAP_MAX, tb, blob_data(b.head), blob_len(b.head)); - if (!tb[CAP_KEEP] && !tb[CAP_DROP]) { - ERROR("failed to parse %s\n", file); - return -1; - } - - blobmsg_for_each_attr(cur, tb[CAP_KEEP], rem) { - name = blobmsg_get_string(cur); - if (!name) { - ERROR("invalid capability name in cap.keep\n"); - return -1; - } - cap = find_capabilities(name); - if (cap == -1) { - ERROR("unknown capability %s in cap.keep\n", name); - return -1; - } - capdrop |= (1LLU << cap); - } - - if (capdrop == 0LLU) { - DEBUG("cap.keep empty -> only dropping capabilities from cap.drop (blacklist)\n"); - capdrop = 0xffffffffffffffffLLU; - } else { - DEBUG("cap.keep has at least one capability -> dropping every capabilities not in cap.keep (whitelist)\n"); - } - - blobmsg_for_each_attr(cur, tb[CAP_DROP], rem) { - name = blobmsg_get_string(cur); - if (!name) { - ERROR("invalid capability name in cap.drop\n"); - return -1; - } - cap = find_capabilities(name); - if (cap == -1) { - ERROR("unknown capability %s in cap.drop\n", name); - return -1; - } - capdrop &= ~(1LLU << cap); - } - - for (cap = 0; cap <= CAP_LAST_CAP; cap++) { - if ( (capdrop & (1LLU << cap)) == 0) { - DEBUG("dropping capability %s (%d)\n", capabilities_names[cap], cap); - if (prctl(PR_CAPBSET_DROP, cap, 0, 0, 0)) { - ERROR("prctl(PR_CAPBSET_DROP, %d) failed: %s\n", cap, strerror(errno)); - return errno; - } - } else { - DEBUG("keeping capability %s (%d)\n", capabilities_names[cap], cap); - } - } - - return 0; -} diff --git a/jail/capabilities.h b/jail/capabilities.h deleted file mode 100644 index e6699e9..0000000 --- a/jail/capabilities.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (C) 2015 Etienne CHAMPETIER - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -int drop_capabilities(const char *file); diff --git a/jail/elf.c b/jail/elf.c deleted file mode 100644 index cbb3051..0000000 --- a/jail/elf.c +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (C) 2015 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define _GNU_SOURCE -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "elf.h" - -struct avl_tree libraries; -static LIST_HEAD(library_paths); - -void alloc_library_path(const char *path) -{ - struct library_path *p; - char *_path; - - p = calloc_a(sizeof(*p), - &_path, strlen(path) + 1); - if (!p) - return; - - p->path = strcpy(_path, path); - - list_add_tail(&p->list, &library_paths); - DEBUG("adding ld.so path %s\n", path); -} - -static void alloc_library(const char *path, const char *name) -{ - struct library *l; - char *_name, *_path; - - l = calloc_a(sizeof(*l), - &_path, strlen(path) + 1, - &_name, strlen(name) + 1); - if (!l) - return; - - l->avl.key = l->name = strcpy(_name, name); - l->path = strcpy(_path, path); - - avl_insert(&libraries, &l->avl); - DEBUG("adding library %s/%s\n", path, name); -} - -static int elf_open(char **dir, char *file) -{ - struct library_path *p; - char path[256]; - int fd = -1; - - *dir = NULL; - - list_for_each_entry(p, &library_paths, list) { - if (strlen(p->path)) - snprintf(path, sizeof(path), "%s/%s", p->path, file); - else - strncpy(path, file, sizeof(path)); - fd = open(path, O_RDONLY); - if (fd >= 0) { - *dir = p->path; - break; - } - } - - if (fd == -1) - fd = open(file, O_RDONLY); - - return fd; -} - -char* find_lib(char *file) -{ - struct library *l; - static char path[256]; - const char *p; - - l = avl_find_element(&libraries, file, l, avl); - if (!l) - return NULL; - - p = l->path; - if (strstr(p, "local")) - p = "/lib"; - - snprintf(path, sizeof(path), "%s/%s", p, file); - - return path; -} - -static int elf64_find_section(char *map, unsigned int type, unsigned int *offset, unsigned int *size, unsigned int *vaddr) -{ - Elf64_Ehdr *e; - Elf64_Phdr *ph; - int i; - - e = (Elf64_Ehdr *) map; - ph = (Elf64_Phdr *) (map + e->e_phoff); - - for (i = 0; i < e->e_phnum; i++) { - if (ph[i].p_type == type) { - *offset = ph[i].p_offset; - if (size) - *size = ph[i].p_filesz; - if (vaddr) - *vaddr = ph[i].p_vaddr; - return 0; - } - } - - return -1; -} - -static int elf32_find_section(char *map, unsigned int type, unsigned int *offset, unsigned int *size, unsigned int *vaddr) -{ - Elf32_Ehdr *e; - Elf32_Phdr *ph; - int i; - - e = (Elf32_Ehdr *) map; - ph = (Elf32_Phdr *) (map + e->e_phoff); - - for (i = 0; i < e->e_phnum; i++) { - if (ph[i].p_type == type) { - *offset = ph[i].p_offset; - if (size) - *size = ph[i].p_filesz; - if (vaddr) - *vaddr = ph[i].p_vaddr; - return 0; - } - } - - return -1; -} - -static int elf_find_section(char *map, unsigned int type, unsigned int *offset, unsigned int *size, unsigned int *vaddr) -{ - int clazz = map[EI_CLASS]; - - if (clazz == ELFCLASS32) - return elf32_find_section(map, type, offset, size, vaddr); - else if (clazz == ELFCLASS64) - return elf64_find_section(map, type, offset, size, vaddr); - - ERROR("unknown elf format %d\n", clazz); - - return -1; -} - -static int elf32_scan_dynamic(char *map, int dyn_offset, int dyn_size, int load_offset) -{ - Elf32_Dyn *dynamic = (Elf32_Dyn *) (map + dyn_offset); - char *strtab = NULL; - - while ((void *) dynamic < (void *) (map + dyn_offset + dyn_size)) { - Elf32_Dyn *curr = dynamic; - - dynamic++; - if (curr->d_tag != DT_STRTAB) - continue; - - strtab = map + (curr->d_un.d_val - load_offset); - break; - } - - if (!strtab) - return -1; - - dynamic = (Elf32_Dyn *) (map + dyn_offset); - while ((void *) dynamic < (void *) (map + dyn_offset + dyn_size)) { - Elf32_Dyn *curr = dynamic; - - dynamic++; - if (curr->d_tag != DT_NEEDED) - continue; - - if (elf_load_deps(&strtab[curr->d_un.d_val])) - return -1; - } - - return 0; -} - -static int elf64_scan_dynamic(char *map, int dyn_offset, int dyn_size, int load_offset) -{ - Elf64_Dyn *dynamic = (Elf64_Dyn *) (map + dyn_offset); - char *strtab = NULL; - - while ((void *) dynamic < (void *) (map + dyn_offset + dyn_size)) { - Elf64_Dyn *curr = dynamic; - - dynamic++; - if (curr->d_tag != DT_STRTAB) - continue; - - strtab = map + (curr->d_un.d_val - load_offset); - break; - } - - if (!strtab) - return -1; - - dynamic = (Elf64_Dyn *) (map + dyn_offset); - while ((void *) dynamic < (void *) (map + dyn_offset + dyn_size)) { - Elf64_Dyn *curr = dynamic; - - dynamic++; - if (curr->d_tag != DT_NEEDED) - continue; - - if (elf_load_deps(&strtab[curr->d_un.d_val])) - return -1; - } - - return 0; -} - -int elf_load_deps(char *library) -{ - unsigned int dyn_offset, dyn_size; - unsigned int load_offset, load_vaddr; - struct stat s; - char *map = NULL, *dir = NULL; - int clazz, fd, ret = -1; - - if (avl_find(&libraries, library)) - return 0; - - fd = elf_open(&dir, library); - - if (fd < 0) { - ERROR("failed to open %s\n", library); - return -1; - } - - if (fstat(fd, &s) == -1) { - ERROR("failed to stat %s\n", library); - ret = -1; - goto err_out; - } - - map = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (map == MAP_FAILED) { - ERROR("failed to mmap %s\n", library); - ret = -1; - goto err_out; - } - - if (elf_find_section(map, PT_LOAD, &load_offset, NULL, &load_vaddr)) { - ERROR("failed to load the .load section from %s\n", library); - ret = -1; - goto err_out; - } - - if (elf_find_section(map, PT_DYNAMIC, &dyn_offset, &dyn_size, NULL)) { - ERROR("failed to load the .dynamic section from %s\n", library); - ret = -1; - goto err_out; - } - - if (dir) { - alloc_library(dir, library); - } else { - char *elf = strdup(library); - - alloc_library(dirname(elf), basename(library)); - free(elf); - } - clazz = map[EI_CLASS]; - - if (clazz == ELFCLASS32) - ret = elf32_scan_dynamic(map, dyn_offset, dyn_size, load_vaddr - load_offset); - else if (clazz == ELFCLASS64) - ret = elf64_scan_dynamic(map, dyn_offset, dyn_size, load_vaddr - load_offset); - -err_out: - if (map) - munmap(map, s.st_size); - close(fd); - - return ret; -} - -void load_ldso_conf(const char *conf) -{ - FILE* fp = fopen(conf, "r"); - char line[256]; - - if (!fp) { - DEBUG("failed to open %s\n", conf); - return; - } - - while (!feof(fp)) { - int len; - - if (!fgets(line, 256, fp)) - break; - len = strlen(line); - if (len < 2) - continue; - if (*line == '#') - continue; - if (line[len - 1] == '\n') - line[len - 1] = '\0'; - if (!strncmp(line, "include ", 8)) { - char *sep = strstr(line, " "); - glob_t gl; - int i; - - if (!sep) - continue;; - while (*sep == ' ') - sep++; - if (glob(sep, GLOB_NOESCAPE | GLOB_MARK, NULL, &gl)) { - ERROR("glob failed on %s\n", sep); - continue; - } - for (i = 0; i < gl.gl_pathc; i++) - load_ldso_conf(gl.gl_pathv[i]); - globfree(&gl); - } else { - struct stat s; - - if (stat(line, &s)) - continue; - alloc_library_path(line); - } - } - - fclose(fp); -} diff --git a/jail/elf.h b/jail/elf.h deleted file mode 100644 index 3ae311e..0000000 --- a/jail/elf.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2015 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef _ELF_H__ -#include -#include - -#include "log.h" - -struct library { - struct avl_node avl; - char *name; - char *path; -}; - -struct library_path { - struct list_head list; - char *path; -}; - -extern struct avl_tree libraries; - -extern void alloc_library_path(const char *path); -extern char* find_lib(char *file); -extern int elf_load_deps(char *library); -extern void load_ldso_conf(const char *conf); - -#endif diff --git a/jail/jail.c b/jail/jail.c deleted file mode 100644 index 56dc9ca..0000000 --- a/jail/jail.c +++ /dev/null @@ -1,459 +0,0 @@ -/* - * Copyright (C) 2015 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define _GNU_SOURCE -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "elf.h" -#include "capabilities.h" - -#include -#include - -#define STACK_SIZE (1024 * 1024) -#define OPT_ARGS "P:S:C:n:r:w:d:psulo" - -static struct { - char *path; - char *name; - char **jail_argv; - char *seccomp; - char *capabilities; - int namespace; - int procfs; - int ronly; - int sysfs; -} opts; - -struct extra { - struct list_head list; - - const char *path; - const char *name; - int readonly; -}; - -static LIST_HEAD(extras); - -extern int pivot_root(const char *new_root, const char *put_old); - -int debug = 0; - -static char child_stack[STACK_SIZE]; - -static int mkdir_p(char *dir, mode_t mask) -{ - char *l = strrchr(dir, '/'); - int ret; - - if (!l) - return 0; - - *l = '\0'; - - if (mkdir_p(dir, mask)) - return -1; - - *l = '/'; - - ret = mkdir(dir, mask); - if (ret && errno == EEXIST) - return 0; - - if (ret) - ERROR("mkdir failed on %s: %s\n", dir, strerror(errno)); - - return ret; -} - -static int mount_bind(const char *root, const char *path, const char *name, int readonly, int error) -{ - const char *p = path; - struct stat s; - char old[256]; - char new[256]; - int fd; - - if (strstr(p, "local")) - p = "/lib"; - - snprintf(old, sizeof(old), "%s/%s", path, name); - snprintf(new, sizeof(new), "%s%s", root, p); - - mkdir_p(new, 0755); - - snprintf(new, sizeof(new), "%s%s/%s", root, p, name); - - if (stat(old, &s)) { - ERROR("%s does not exist\n", old); - return error; - } - - if (S_ISDIR(s.st_mode)) { - mkdir_p(new, 0755); - } else { - fd = creat(new, 0644); - if (fd == -1) { - ERROR("failed to create %s: %s\n", new, strerror(errno)); - return -1; - } - close(fd); - } - - if (mount(old, new, NULL, MS_BIND, NULL)) { - ERROR("failed to mount -B %s %s: %s\n", old, new, strerror(errno)); - return -1; - } - - if (readonly && mount(NULL, new, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL)) { - ERROR("failed to remount ro %s: %s\n", new, strerror(errno)); - return -1; - } - - DEBUG("mount -B %s %s\n", old, new); - - return 0; -} - -static int build_jail_fs() -{ - struct library *l; - struct extra *m; - - if (mount("tmpfs", opts.path, "tmpfs", MS_NOATIME, "mode=0755")) { - ERROR("tmpfs mount failed %s\n", strerror(errno)); - return -1; - } - - if (chdir(opts.path)) { - ERROR("failed to chdir() in the jail root\n"); - return -1; - } - - avl_init(&libraries, avl_strcmp, false, NULL); - alloc_library_path("/lib64"); - alloc_library_path("/lib"); - alloc_library_path("/usr/lib"); - load_ldso_conf("/etc/ld.so.conf"); - - if (elf_load_deps(*opts.jail_argv)) { - ERROR("failed to load dependencies\n"); - return -1; - } - - if (opts.seccomp && elf_load_deps("libpreload-seccomp.so")) { - ERROR("failed to load libpreload-seccomp.so\n"); - return -1; - } - - avl_for_each_element(&libraries, l, avl) - if (mount_bind(opts.path, l->path, l->name, 1, -1)) - return -1; - - list_for_each_entry(m, &extras, list) - if (mount_bind(opts.path, m->path, m->name, m->readonly, 0)) - return -1; - - char *mpoint; - if (asprintf(&mpoint, "%s/old", opts.path) < 0) { - ERROR("failed to alloc pivot path: %s\n", strerror(errno)); - return -1; - } - mkdir_p(mpoint, 0755); - if (pivot_root(opts.path, mpoint) == -1) { - ERROR("pivot_root failed:%s\n", strerror(errno)); - free(mpoint); - return -1; - } - free(mpoint); - umount2("/old", MNT_DETACH); - rmdir("/old"); - if (opts.procfs) { - mkdir("/proc", 0755); - mount("proc", "/proc", "proc", MS_NOATIME | MS_NODEV | MS_NOEXEC | MS_NOSUID, 0); - } - if (opts.sysfs) { - mkdir("/sys", 0755); - mount("sysfs", "/sys", "sysfs", MS_NOATIME | MS_NODEV | MS_NOEXEC | MS_NOSUID, 0); - } - if (opts.ronly) - mount(NULL, "/", NULL, MS_RDONLY | MS_REMOUNT, 0); - - return 0; -} - -#define MAX_ENVP 8 -static char** build_envp(const char *seccomp) -{ - static char *envp[MAX_ENVP]; - static char preload_var[64]; - static char seccomp_var[64]; - static char debug_var[] = "LD_DEBUG=all"; - char *preload_lib = find_lib("libpreload-seccomp.so"); - int count = 0; - - if (seccomp && !preload_lib) { - ERROR("failed to add preload-lib to env\n"); - return NULL; - } - if (seccomp) { - snprintf(seccomp_var, sizeof(seccomp_var), "SECCOMP_FILE=%s", seccomp); - envp[count++] = seccomp_var; - snprintf(preload_var, sizeof(preload_var), "LD_PRELOAD=%s", preload_lib); - envp[count++] = preload_var; - } - if (debug > 1) - envp[count++] = debug_var; - - return envp; -} - -static void usage(void) -{ - fprintf(stderr, "ujail -- \n"); - fprintf(stderr, " -d \tshow debug log (increase num to increase verbosity)\n"); - fprintf(stderr, " -S \tseccomp filter config\n"); - fprintf(stderr, " -C \tcapabilities drop config\n"); - fprintf(stderr, " -n \tthe name of the jail\n"); - fprintf(stderr, "namespace jail options:\n"); - fprintf(stderr, " -P \tpath where the jail will be staged\n"); - fprintf(stderr, " -r \treadonly files that should be staged\n"); - fprintf(stderr, " -w \twriteable files that should be staged\n"); - fprintf(stderr, " -p\t\tjail has /proc\n"); - fprintf(stderr, " -s\t\tjail has /sys\n"); - fprintf(stderr, " -l\t\tjail has /dev/log\n"); - fprintf(stderr, " -u\t\tjail has a ubus socket\n"); - fprintf(stderr, " -o\t\tremont jail root (/) read only\n"); - fprintf(stderr, "\nWarning: by default root inside the jail is the same\n\ -and he has the same powers as root outside the jail,\n\ -thus he can escape the jail and/or break stuff.\n\ -Please use seccomp/capabilities (-S/-C) to restrict his powers\n\n\ -If you use none of the namespace jail options,\n\ -ujail will not use namespace/build a jail,\n\ -and will only drop capabilities/apply seccomp filter.\n\n"); -} - -static int exec_jail() -{ - char **envp = build_envp(opts.seccomp); - if (!envp) - exit(EXIT_FAILURE); - - if (opts.capabilities && drop_capabilities(opts.capabilities)) - exit(EXIT_FAILURE); - - INFO("exec-ing %s\n", *opts.jail_argv); - execve(*opts.jail_argv, opts.jail_argv, envp); - //we get there only if execve fails - ERROR("failed to execve %s: %s\n", *opts.jail_argv, strerror(errno)); - exit(EXIT_FAILURE); -} - -static int spawn_jail(void *arg) -{ - if (opts.name && sethostname(opts.name, strlen(opts.name))) { - ERROR("failed to sethostname: %s\n", strerror(errno)); - } - - if (build_jail_fs()) { - ERROR("failed to build jail fs"); - exit(EXIT_FAILURE); - } - - return exec_jail(); -} - -static int jail_running = 1; -static int jail_return_code = 0; - -static void jail_process_handler(struct uloop_process *c, int ret) -{ - if (WIFEXITED(ret)) { - jail_return_code = WEXITSTATUS(ret); - INFO("jail (%d) exited with exit: %d\n", c->pid, jail_return_code); - } else { - jail_return_code = WTERMSIG(ret); - INFO("jail (%d) exited with signal: %d\n", c->pid, jail_return_code); - } - jail_running = 0; - uloop_end(); -} - -static struct uloop_process jail_process = { - .cb = jail_process_handler, -}; - -static void add_extra(char *name, int readonly) -{ - struct extra *f; - - if (*name != '/') { - ERROR("%s is not an absolute path\n", name); - return; - } - - f = calloc(1, sizeof(struct extra)); - - f->name = basename(name); - f->path = dirname(strdup(name)); - f->readonly = readonly; - - list_add_tail(&f->list, &extras); -} - -int main(int argc, char **argv) -{ - uid_t uid = getuid(); - char log[] = "/dev/log"; - char ubus[] = "/var/run/ubus.sock"; - int ret = EXIT_SUCCESS; - int ch; - - if (uid) { - ERROR("not root, aborting: %s\n", strerror(errno)); - return EXIT_FAILURE; - } - - umask(022); - - while ((ch = getopt(argc, argv, OPT_ARGS)) != -1) { - switch (ch) { - case 'd': - debug = atoi(optarg); - break; - case 'p': - opts.namespace = 1; - opts.procfs = 1; - break; - case 'o': - opts.namespace = 1; - opts.ronly = 1; - break; - case 's': - opts.namespace = 1; - opts.sysfs = 1; - break; - case 'S': - opts.seccomp = optarg; - add_extra(optarg, 1); - break; - case 'C': - opts.capabilities = optarg; - add_extra(optarg, 1); - break; - case 'P': - opts.namespace = 1; - opts.path = optarg; - break; - case 'n': - opts.name = optarg; - break; - case 'r': - opts.namespace = 1; - add_extra(optarg, 1); - break; - case 'w': - opts.namespace = 1; - add_extra(optarg, 0); - break; - case 'u': - opts.namespace = 1; - add_extra(ubus, 0); - break; - case 'l': - opts.namespace = 1; - add_extra(log, 0); - break; - } - } - - //no param found - if (argc - optind < 1) { - usage(); - return EXIT_FAILURE; - } - if (!(opts.namespace||opts.capabilities||opts.seccomp)) { - ERROR("Not using namespaces, capabilities or seccomp !!!\n\n"); - usage(); - return EXIT_FAILURE; - } - DEBUG("Using namespaces(%d), capabilities(%d), seccomp(%d)\n", - opts.namespace, - opts.capabilities != 0, - opts.seccomp != 0); - - opts.jail_argv = &argv[optind]; - - if (opts.name) - prctl(PR_SET_NAME, opts.name, NULL, NULL, NULL); - - if (opts.namespace && !opts.path && asprintf(&opts.path, "/tmp/%s", basename(*opts.jail_argv)) == -1) { - ERROR("failed to asprintf root path: %s\n", strerror(errno)); - return EXIT_FAILURE; - } - - if (opts.namespace && mkdir(opts.path, 0755)) { - ERROR("unable to create root path: %s (%s)\n", opts.path, strerror(errno)); - return EXIT_FAILURE; - } - - uloop_init(); - if (opts.namespace) { - jail_process.pid = clone(spawn_jail, - child_stack + STACK_SIZE, - CLONE_NEWUTS | CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | SIGCHLD, argv); - } else { - jail_process.pid = fork(); - } - - if (jail_process.pid > 0) { - //parent process - uloop_process_add(&jail_process); - uloop_run(); - uloop_done(); - if (jail_running) { - DEBUG("uloop interrupted, killing jail process\n"); - kill(jail_process.pid, SIGTERM); - waitpid(jail_process.pid, NULL, 0); - } - } else if (jail_process.pid == 0) { - //fork child process - return exec_jail(); - } else { - ERROR("failed to clone/fork: %s\n", strerror(errno)); - ret = EXIT_FAILURE; - } - - if (opts.namespace && rmdir(opts.path)) { - ERROR("Unable to remove root path: %s (%s)\n", opts.path, strerror(errno)); - ret = EXIT_FAILURE; - } - - if (ret) - return ret; - - return jail_return_code; -} diff --git a/jail/log.h b/jail/log.h deleted file mode 100644 index b1d201e..0000000 --- a/jail/log.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (C) 2015 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -extern int debug; -#include - -#define INFO(fmt, ...) do { \ - printf("jail: "fmt, ## __VA_ARGS__); \ - } while (0) -#define ERROR(fmt, ...) do { \ - syslog(LOG_ERR, "jail: "fmt, ## __VA_ARGS__); \ - fprintf(stderr,"jail: "fmt, ## __VA_ARGS__); \ - } while (0) -#define DEBUG(fmt, ...) do { \ - if (debug) printf("jail: "fmt, ## __VA_ARGS__); \ - } while (0) - diff --git a/jail/preload.c b/jail/preload.c deleted file mode 100644 index a1cc0b6..0000000 --- a/jail/preload.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2015 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include - -#include "seccomp.h" -#include "../preload.h" - -static main_t __main__; - -static int __preload_main__(int argc, char **argv, char **envp) -{ - char *env_file = getenv("SECCOMP_FILE"); - - if (install_syscall_filter(*argv, env_file)) - return -1; - - unsetenv("LD_PRELOAD"); - unsetenv("SECCOMP_FILE"); - - return (*__main__)(argc, argv, envp); -} - -int __libc_start_main(main_t main, - int argc, - char **argv, - ElfW(auxv_t) *auxvec, - __typeof (main) init, - void (*fini) (void), - void (*rtld_fini) (void), - void *stack_end) -{ - start_main_t __start_main__; - - __start_main__ = dlsym(RTLD_NEXT, "__libc_start_main"); - if (!__start_main__) - INFO("failed to find __libc_start_main %s\n", dlerror()); - - __main__ = main; - - return (*__start_main__)(__preload_main__, argc, argv, auxvec, - init, fini, rtld_fini, stack_end); -} - -void __uClibc_main(main_t main, - int argc, - char **argv, - void (*app_init)(void), - void (*app_fini)(void), - void (*rtld_fini)(void), - void *stack_end attribute_unused) -{ - uClibc_main __start_main__; - - __start_main__ = dlsym(RTLD_NEXT, "__uClibc_main"); - if (!__start_main__) - INFO("failed to find __uClibc_main %s\n", dlerror()); - - __main__ = main; - - return (*__start_main__)(__preload_main__, argc, argv, - app_init, app_fini, rtld_fini, stack_end); -} diff --git a/jail/seccomp-bpf.h b/jail/seccomp-bpf.h deleted file mode 100644 index 82c0669..0000000 --- a/jail/seccomp-bpf.h +++ /dev/null @@ -1,89 +0,0 @@ -/* - * seccomp example for x86 (32-bit and 64-bit) with BPF macros - * - * Copyright (c) 2012 The Chromium OS Authors - * Authors: - * Will Drewry - * Kees Cook - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#ifndef _SECCOMP_BPF_H_ -#define _SECCOMP_BPF_H_ - -#define _GNU_SOURCE 1 -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#ifndef PR_SET_NO_NEW_PRIVS -# define PR_SET_NO_NEW_PRIVS 38 -#endif - -#include -#include -#include - -#ifdef HAVE_LINUX_SECCOMP_H -# include -#endif - -#ifndef SECCOMP_MODE_FILTER -#define SECCOMP_MODE_FILTER 2 /* uses user-supplied filter. */ -#define SECCOMP_RET_KILL 0x00000000U /* kill the task immediately */ -#define SECCOMP_RET_TRAP 0x00030000U /* disallow and force a SIGSYS */ -#define SECCOMP_RET_ERRNO 0x00050000U /* returns an errno */ -#define SECCOMP_RET_LOG 0x00070000U -#define SECCOMP_RET_ALLOW 0x7fff0000U /* allow */ -#define SECCOMP_RET_ERROR(x) (SECCOMP_RET_ERRNO | ((x) & 0x0000ffffU)) -#define SECCOMP_RET_LOGGER(x) (SECCOMP_RET_LOG | ((x) & 0x0000ffffU)) - -struct seccomp_data { - int nr; - __u32 arch; - __u64 instruction_pointer; - __u64 args[6]; -}; -#endif - -#ifndef SYS_SECCOMP -# define SYS_SECCOMP 1 -#endif - -#define syscall_nr (offsetof(struct seccomp_data, nr)) -#define arch_nr (offsetof(struct seccomp_data, arch)) - -#if defined(__i386__) -# define REG_SYSCALL REG_EAX -# define ARCH_NR AUDIT_ARCH_I386 -#elif defined(__x86_64__) -# define REG_SYSCALL REG_RAX -# define ARCH_NR AUDIT_ARCH_X86_64 -#elif defined(__mips__) -# define REG_SYSCALL regs[2] -# if __BYTE_ORDER == __LITTLE_ENDIAN -# define ARCH_NR AUDIT_ARCH_MIPSEL -# else -# define ARCH_NR AUDIT_ARCH_MIPS -# endif -#elif defined(__arm__) && (defined(__ARM_EABI__) || defined(__thumb__)) -# define REG_SYSCALL regs.uregs[7] -# if __BYTE_ORDER == __LITTLE_ENDIAN -# define ARCH_NR AUDIT_ARCH_ARM -# else -# define ARCH_NR AUDIT_ARCH_ARMEB -# endif -#else -# warning "Platform does not support seccomp filter yet" -# define REG_SYSCALL 0 -# define ARCH_NR 0 -#endif - -#endif /* _SECCOMP_BPF_H_ */ diff --git a/jail/seccomp.c b/jail/seccomp.c deleted file mode 100644 index de01fc6..0000000 --- a/jail/seccomp.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * seccomp example with syscall reporting - * - * Copyright (c) 2012 The Chromium OS Authors - * Authors: - * Kees Cook - * Will Drewry - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#define _GNU_SOURCE 1 -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "seccomp-bpf.h" -#include "seccomp.h" -#include "../syscall-names.h" - -static int max_syscall = ARRAY_SIZE(syscall_names); - -static int find_syscall(const char *name) -{ - int i; - - for (i = 0; i < max_syscall; i++) - if (syscall_names[i] && !strcmp(syscall_names[i], name)) - return i; - - return -1; -} - -static void set_filter(struct sock_filter *filter, __u16 code, __u8 jt, __u8 jf, __u32 k) -{ - filter->code = code; - filter->jt = jt; - filter->jf = jf; - filter->k = k; -} - -int install_syscall_filter(const char *argv, const char *file) -{ - enum { - SECCOMP_WHITELIST, - SECCOMP_POLICY, - __SECCOMP_MAX - }; - static const struct blobmsg_policy policy[__SECCOMP_MAX] = { - [SECCOMP_WHITELIST] = { .name = "whitelist", .type = BLOBMSG_TYPE_ARRAY }, - [SECCOMP_POLICY] = { .name = "policy", .type = BLOBMSG_TYPE_INT32 }, - }; - struct blob_buf b = { 0 }; - struct blob_attr *tb[__SECCOMP_MAX]; - struct blob_attr *cur; - int rem; - - struct sock_filter *filter; - struct sock_fprog prog = { 0 }; - int sz = 5, idx = 0, default_policy = 0; - - INFO("%s: setting up syscall filter\n", argv); - - blob_buf_init(&b, 0); - if (!blobmsg_add_json_from_file(&b, file)) { - INFO("%s: failed to load %s\n", argv, file); - return -1; - } - - blobmsg_parse(policy, __SECCOMP_MAX, tb, blob_data(b.head), blob_len(b.head)); - if (!tb[SECCOMP_WHITELIST]) { - INFO("%s: %s is missing the syscall table\n", argv, file); - return -1; - } - - if (tb[SECCOMP_POLICY]) - default_policy = blobmsg_get_u32(tb[SECCOMP_POLICY]); - - blobmsg_for_each_attr(cur, tb[SECCOMP_WHITELIST], rem) - sz += 2; - - filter = calloc(sz, sizeof(struct sock_filter)); - if (!filter) { - INFO("failed to allocate filter memory\n"); - return -1; - } - - /* validate arch */ - set_filter(&filter[idx++], BPF_LD + BPF_W + BPF_ABS, 0, 0, arch_nr); - set_filter(&filter[idx++], BPF_JMP + BPF_JEQ + BPF_K, 1, 0, ARCH_NR); - set_filter(&filter[idx++], BPF_RET + BPF_K, 0, 0, SECCOMP_RET_KILL); - - /* get syscall */ - set_filter(&filter[idx++], BPF_LD + BPF_W + BPF_ABS, 0, 0, syscall_nr); - - blobmsg_for_each_attr(cur, tb[SECCOMP_WHITELIST], rem) { - char *name = blobmsg_get_string(cur); - int nr; - - if (!name) { - INFO("%s: invalid syscall name\n", argv); - continue; - } - - nr = find_syscall(name); - if (nr == -1) { - INFO("%s: unknown syscall %s\n", argv, name); - continue; - } - - /* add whitelist */ - set_filter(&filter[idx++], BPF_JMP + BPF_JEQ + BPF_K, 0, 1, nr); - set_filter(&filter[idx++], BPF_RET + BPF_K, 0, 0, SECCOMP_RET_ALLOW); - } - - if (default_policy) - /* return -1 and set errno */ - set_filter(&filter[idx], BPF_RET + BPF_K, 0, 0, SECCOMP_RET_LOGGER(default_policy)); - else - /* kill the process */ - set_filter(&filter[idx], BPF_RET + BPF_K, 0, 0, SECCOMP_RET_KILL); - - if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) { - INFO("%s: prctl(PR_SET_NO_NEW_PRIVS) failed: %s\n", argv, strerror(errno)); - return errno; - } - - prog.len = (unsigned short) idx + 1; - prog.filter = filter; - - if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) { - INFO("%s: prctl(PR_SET_SECCOMP) failed: %s\n", argv, strerror(errno)); - return errno; - } - return 0; -} diff --git a/jail/seccomp.h b/jail/seccomp.h deleted file mode 100644 index 45eede7..0000000 --- a/jail/seccomp.h +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2015 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define INFO(fmt, ...) do { \ - syslog(LOG_INFO,"preload-seccomp: "fmt, ## __VA_ARGS__); \ - fprintf(stderr,"preload-seccomp: "fmt, ## __VA_ARGS__); \ - } while (0) - -int install_syscall_filter(const char *argv, const char *file); diff --git a/libc-compat.h b/libc-compat.h deleted file mode 100644 index 9435346..0000000 --- a/libc-compat.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __PROCD_LIBC_COMPAT_H -#define __PROCD_LIBC_COMPAT_H - -#if defined(__GLIBC__) && !defined(__UCLIBC__) -static inline int ignore(int x) {return x;} -#else -#define ignore(x) x -#endif - -#endif diff --git a/log.h b/log.h index bf86f1e..c8c3929 100644 --- a/log.h +++ b/log.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/make_capabilities_h.sh b/make_capabilities_h.sh deleted file mode 100755 index 635e740..0000000 --- a/make_capabilities_h.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh - -CC=$1 -[ -n "$TARGET_CC_NOCACHE" ] && CC=$TARGET_CC_NOCACHE - -echo "#include " -echo "static const char *capabilities_names[] = {" -echo "#include " | ${CC} -E -dM - | grep '#define CAP' | grep -vE '(CAP_TO|CAP_LAST_CAP)' | \ - awk '{print $3" "$2}' | sort -n | awk '{print " ["$1"]\t= \""tolower($2)"\","}' -echo "};" diff --git a/make_syscall_h.sh b/make_syscall_h.sh deleted file mode 100755 index 3363bc7..0000000 --- a/make_syscall_h.sh +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh -# syscall reporting example for seccomp -# -# Copyright (c) 2012 The Chromium OS Authors -# Authors: -# Kees Cook -# -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -CC=$1 -[ -n "$TARGET_CC_NOCACHE" ] && CC=$TARGET_CC_NOCACHE - -echo "#include " -echo "static const char *syscall_names[] = {" -echo "#include " | ${CC} -E -dM - | grep '^#define __NR_' | \ - LC_ALL=C sed -r -n -e 's/^\#define[ \t]+__NR_([a-z0-9_]+)[ \t]+([ ()+0-9a-zNR_Linux]+)(.*)/ [\2] = "\1",/p' -echo "};" diff --git a/plug/coldplug.c b/plug/coldplug.c deleted file mode 100644 index 5fcb9a3..0000000 --- a/plug/coldplug.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2013 Felix Fietkau - * Copyright (C) 2013 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include - -#include - -#include "../procd.h" -#include "../libc-compat.h" - -#include "hotplug.h" - -static struct uloop_process udevtrigger; - -static void coldplug_complete(struct uloop_timeout *t) -{ - DEBUG(4, "Coldplug complete\n"); - hotplug_last_event(NULL); - procd_state_next(); -} - -static void udevtrigger_complete(struct uloop_process *proc, int ret) -{ - DEBUG(4, "Finished udevtrigger\n"); - hotplug_last_event(coldplug_complete); -} - -void procd_coldplug(void) -{ - char *argv[] = { "udevtrigger", NULL }; - unsigned int oldumask = umask(0); - - umount2("/dev/pts", MNT_DETACH); - umount2("/dev/", MNT_DETACH); - mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755,size=512K"); - ignore(symlink("/tmp/shm", "/dev/shm")); - mkdir("/dev/pts", 0755); - umask(oldumask); - mount("devpts", "/dev/pts", "devpts", MS_NOEXEC | MS_NOSUID, 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); -} diff --git a/plug/hotplug.c b/plug/hotplug.c deleted file mode 100644 index b5ebd07..0000000 --- a/plug/hotplug.c +++ /dev/null @@ -1,610 +0,0 @@ -/* - * Copyright (C) 2013 Felix Fietkau - * Copyright (C) 2013 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "../procd.h" - -#include "hotplug.h" - -#define HOTPLUG_WAIT 500 - -struct cmd_handler; -struct cmd_queue { - struct list_head list; - - struct blob_attr *msg; - struct blob_attr *data; - int timeout; - - void (*handler)(struct blob_attr *msg, struct blob_attr *data); - void (*start)(struct blob_attr *msg, struct blob_attr *data); - void (*complete)(struct blob_attr *msg, struct blob_attr *data, int ret); -}; - -struct button_timeout { - struct list_head list; - struct uloop_timeout timeout; - char *name; - int seen; - struct blob_attr *data; -}; - -static LIST_HEAD(cmd_queue); -static LIST_HEAD(button_timer); -static struct uloop_process queue_proc; -static struct uloop_timeout last_event; -static struct blob_buf b, button_buf; -static char *rule_file; -static struct blob_buf script; -static struct cmd_queue *current; - -static void queue_add(struct cmd_handler *h, struct blob_attr *msg, struct blob_attr *data); -static void handle_button_complete(struct blob_attr *msg, struct blob_attr *data, int ret); - -static void button_free(struct button_timeout *b) -{ - uloop_timeout_cancel(&b->timeout); - list_del(&b->list); - free(b->data); - free(b->name); - free(b); -} - -static void button_timeout_remove(char *button) -{ - struct button_timeout *b, *c; - - if (!list_empty(&button_timer)) list_for_each_entry_safe(b, c, &button_timer, list) { - if (!strcmp(b->name, button)) - button_free(b); - } -} - -static char *hotplug_msg_find_var(struct blob_attr *msg, const char *name) -{ - struct blob_attr *cur; - int rem; - - blobmsg_for_each_attr(cur, msg, rem) { - if (blobmsg_type(cur) != BLOBMSG_TYPE_STRING) - continue; - - if (strcmp(blobmsg_name(cur), name) != 0) - continue; - - return blobmsg_data(cur); - } - - return NULL; -} - -static void mkdir_p(char *dir) -{ - char *l = strrchr(dir, '/'); - - if (l) { - *l = '\0'; - mkdir_p(dir); - *l = '/'; - mkdir(dir, 0755); - } -} - -static void handle_makedev(struct blob_attr *msg, struct blob_attr *data) -{ - unsigned int oldumask = umask(0); - static struct blobmsg_policy mkdev_policy[2] = { - { .type = BLOBMSG_TYPE_STRING }, - { .type = BLOBMSG_TYPE_STRING }, - }; - struct blob_attr *tb[2]; - char *minor = hotplug_msg_find_var(msg, "MINOR"); - char *major = hotplug_msg_find_var(msg, "MAJOR"); - char *subsystem = hotplug_msg_find_var(msg, "SUBSYSTEM"); - - blobmsg_parse_array(mkdev_policy, 2, tb, blobmsg_data(data), blobmsg_data_len(data)); - if (tb[0] && tb[1] && minor && major && subsystem) { - mode_t m = S_IFCHR; - char *d = strdup(blobmsg_get_string(tb[0])); - - d = dirname(d); - mkdir_p(d); - free(d); - - if (!strcmp(subsystem, "block")) - m = S_IFBLK; - mknod(blobmsg_get_string(tb[0]), - m | strtoul(blobmsg_data(tb[1]), NULL, 8), - makedev(atoi(major), atoi(minor))); - } - umask(oldumask); -} - -static void handle_rm(struct blob_attr *msg, struct blob_attr *data) -{ - static struct blobmsg_policy rm_policy = { - .type = BLOBMSG_TYPE_STRING, - }; - struct blob_attr *tb; - - blobmsg_parse_array(&rm_policy, 1, &tb, blobmsg_data(data), blobmsg_data_len(data)); - if (tb) - unlink(blobmsg_data(tb)); -} - -static void handle_exec(struct blob_attr *msg, struct blob_attr *data) -{ - char *argv[8]; - struct blob_attr *cur; - int rem, fd; - int i = 0; - - blobmsg_for_each_attr(cur, msg, rem) - setenv(blobmsg_name(cur), blobmsg_data(cur), 1); - - blobmsg_for_each_attr(cur, data, rem) { - argv[i] = blobmsg_data(cur); - i++; - if (i == 7) - break; - } - - if (debug < 3) { - fd = open("/dev/null", O_RDWR); - if (fd > -1) { - dup2(fd, STDIN_FILENO); - dup2(fd, STDOUT_FILENO); - dup2(fd, STDERR_FILENO); - if (fd > STDERR_FILENO) - close(fd); - } - } - - if (i > 0) { - argv[i] = NULL; - execvp(argv[0], &argv[0]); - } - exit(-1); -} - -static void handle_button_start(struct blob_attr *msg, struct blob_attr *data) -{ - char *button = hotplug_msg_find_var(msg, "BUTTON"); - - if (button) - button_timeout_remove(button); -} - -static void handle_firmware(struct blob_attr *msg, struct blob_attr *data) -{ - char *dir = blobmsg_get_string(blobmsg_data(data)); - char *file = hotplug_msg_find_var(msg, "FIRMWARE"); - char *dev = hotplug_msg_find_var(msg, "DEVPATH"); - struct stat s = { 0 }; - char *path, loadpath[256], syspath[256]; - int fw, src, load, len; - static char buf[4096]; - - DEBUG(2, "Firmware request for %s/%s\n", dir, file); - - if (!file || !dir || !dev) { - ERROR("Request for unknown firmware %s/%s\n", dir, file); - exit(-1); - } - - path = alloca(strlen(dir) + strlen(file) + 2); - sprintf(path, "%s/%s", dir, file); - - if (stat(path, &s)) { - ERROR("Could not find firmware %s\n", path); - src = -1; - s.st_size = 0; - goto send_to_kernel; - } - - src = open(path, O_RDONLY); - if (src < 0) { - ERROR("Failed to open %s\n", path); - s.st_size = 0; - goto send_to_kernel; - } - -send_to_kernel: - snprintf(loadpath, sizeof(loadpath), "/sys/%s/loading", dev); - load = open(loadpath, O_WRONLY); - if (!load) { - ERROR("Failed to open %s\n", loadpath); - exit(-1); - } - if (write(load, "1", 1) == -1) { - ERROR("Failed to write to %s\n", loadpath); - exit(-1); - } - close(load); - - snprintf(syspath, sizeof(syspath), "/sys/%s/data", dev); - fw = open(syspath, O_WRONLY); - if (fw < 0) { - ERROR("Failed to open %s\n", syspath); - exit(-1); - } - - len = s.st_size; - while (len) { - len = read(src, buf, sizeof(buf)); - if (len <= 0) - break; - - if (write(fw, buf, len) == -1) { - ERROR("failed to write firmware file %s/%s to %s\n", dir, file, dev); - break; - } - } - - if (src >= 0) - close(src); - close(fw); - - load = open(loadpath, O_WRONLY); - if (write(load, "0", 1) == -1) - ERROR("failed to write to %s\n", loadpath); - close(load); - - DEBUG(2, "Done loading %s\n", path); - - exit(-1); -} - -enum { - HANDLER_MKDEV = 0, - HANDLER_RM, - HANDLER_EXEC, - HANDLER_BUTTON, - HANDLER_FW, -}; - -static struct cmd_handler { - char *name; - int atomic; - void (*handler)(struct blob_attr *msg, struct blob_attr *data); - void (*start)(struct blob_attr *msg, struct blob_attr *data); - void (*complete)(struct blob_attr *msg, struct blob_attr *data, int ret); -} handlers[] = { - [HANDLER_MKDEV] = { - .name = "makedev", - .atomic = 1, - .handler = handle_makedev, - }, - [HANDLER_RM] = { - .name = "rm", - .atomic = 1, - .handler = handle_rm, - }, - [HANDLER_EXEC] = { - .name = "exec", - .handler = handle_exec, - }, - [HANDLER_BUTTON] = { - .name = "button", - .handler = handle_exec, - .start = handle_button_start, - .complete = handle_button_complete, - }, - [HANDLER_FW] = { - .name = "load-firmware", - .handler = handle_firmware, - }, -}; - -static void queue_next(void) -{ - struct cmd_queue *c; - - if (queue_proc.pending || list_empty(&cmd_queue)) - return; - - c = list_first_entry(&cmd_queue, struct cmd_queue, list); - - queue_proc.pid = fork(); - if (!queue_proc.pid) { - uloop_done(); - c->handler(c->msg, c->data); - exit(0); - } - if (c->start) - c->start(c->msg, c->data); - list_del(&c->list); - if (c->complete) - current = c; - else - free(c); - if (queue_proc.pid <= 0) { - queue_next(); - return; - } - - uloop_process_add(&queue_proc); - - DEBUG(4, "Launched hotplug exec instance, pid=%d\n", (int) queue_proc.pid); -} - -static void queue_proc_cb(struct uloop_process *c, int ret) -{ - DEBUG(4, "Finished hotplug exec instance, pid=%d\n", (int) c->pid); - - if (current) { - current->complete(current->msg, current->data, ret); - free(current); - current = NULL; - } - queue_next(); -} - -static void queue_add(struct cmd_handler *h, struct blob_attr *msg, struct blob_attr *data) -{ - struct cmd_queue *c = NULL; - struct blob_attr *_msg, *_data; - - c = calloc_a(sizeof(struct cmd_queue), - &_msg, blob_pad_len(msg), - &_data, blob_pad_len(data), - NULL); - - c->msg = _msg; - c->data = _data; - - if (!c) - return; - - memcpy(c->msg, msg, blob_pad_len(msg)); - memcpy(c->data, data, blob_pad_len(data)); - c->handler = h->handler; - c->complete = h->complete; - c->start = h->start; - list_add_tail(&c->list, &cmd_queue); - queue_next(); -} - -static void handle_button_timeout(struct uloop_timeout *t) -{ - struct button_timeout *b; - char seen[16]; - - b = container_of(t, struct button_timeout, timeout); - blob_buf_init(&button_buf, 0); - blobmsg_add_string(&button_buf, "BUTTON", b->name); - blobmsg_add_string(&button_buf, "ACTION", "timeout"); - snprintf(seen, sizeof(seen), "%d", b->seen); - blobmsg_add_string(&button_buf, "SEEN", seen); - queue_add(&handlers[HANDLER_EXEC], button_buf.head, b->data); - button_free(b); -} - -static void handle_button_complete(struct blob_attr *msg, struct blob_attr *data, int ret) -{ - char *name = hotplug_msg_find_var(msg, "BUTTON"); - struct button_timeout *b; - int timeout = ret >> 8; - - if (!timeout) - return; - - b = malloc(sizeof(*b)); - if (!b || !name) - return; - - memset(b, 0, sizeof(*b)); - - b->data = malloc(blob_pad_len(data)); - b->name = strdup(name); - b->seen = timeout; - - memcpy(b->data, data, blob_pad_len(data)); - b->timeout.cb = handle_button_timeout; - - uloop_timeout_set(&b->timeout, timeout * 1000); - list_add(&b->list, &button_timer); -} - -static const char* rule_handle_var(struct json_script_ctx *ctx, const char *name, struct blob_attr *vars) -{ - const char *str, *sep; - - if (!strcmp(name, "DEVICENAME") || !strcmp(name, "DEVNAME")) { - str = json_script_find_var(ctx, vars, "DEVPATH"); - if (!str) - return NULL; - - sep = strrchr(str, '/'); - if (sep) - return sep + 1; - - return str; - } - - return NULL; -} - -static struct json_script_file * -rule_handle_file(struct json_script_ctx *ctx, const char *name) -{ - json_object *obj; - - obj = json_object_from_file((char*)name); - if (!obj) - return NULL; - - blob_buf_init(&script, 0); - blobmsg_add_json_element(&script, "", obj); - - return json_script_file_from_blobmsg(name, blob_data(script.head), blob_len(script.head)); -} - -static void rule_handle_command(struct json_script_ctx *ctx, const char *name, - struct blob_attr *data, struct blob_attr *vars) -{ - struct blob_attr *cur; - int rem, i; - - if (debug > 3) { - DEBUG(4, "Command: %s", name); - blobmsg_for_each_attr(cur, data, rem) - DEBUG(4, " %s", (char *) blobmsg_data(cur)); - DEBUG(4, "\n"); - - DEBUG(4, "Message:"); - blobmsg_for_each_attr(cur, vars, rem) - DEBUG(4, " %s=%s", blobmsg_name(cur), (char *) blobmsg_data(cur)); - DEBUG(4, "\n"); - } - - for (i = 0; i < ARRAY_SIZE(handlers); i++) - if (!strcmp(handlers[i].name, name)) { - if (handlers[i].atomic) - handlers[i].handler(vars, data); - else - queue_add(&handlers[i], vars, data); - break; - } - - if (last_event.cb) - uloop_timeout_set(&last_event, HOTPLUG_WAIT); -} - -static void rule_handle_error(struct json_script_ctx *ctx, const char *msg, - struct blob_attr *context) -{ - char *s; - - s = blobmsg_format_json(context, false); - ERROR("ERROR: %s in block: %s\n", msg, s); - free(s); -} - -static struct json_script_ctx jctx = { - .handle_var = rule_handle_var, - .handle_error = rule_handle_error, - .handle_command = rule_handle_command, - .handle_file = rule_handle_file, -}; - -static void hotplug_handler_debug(struct blob_attr *data) -{ - char *str; - - if (debug < 3) - return; - - str = blobmsg_format_json(data, true); - DEBUG(3, "%s\n", str); - free(str); -} - -static void hotplug_handler(struct uloop_fd *u, unsigned int ev) -{ - int i = 0; - static char buf[4096]; - int len = recv(u->fd, buf, sizeof(buf), MSG_DONTWAIT); - void *index; - if (len < 1) - return; - - blob_buf_init(&b, 0); - index = blobmsg_open_table(&b, NULL); - while (i < len) { - int l = strlen(buf + i) + 1; - char *e = strstr(&buf[i], "="); - - if (e) { - *e = '\0'; - blobmsg_add_string(&b, &buf[i], &e[1]); - } - i += l; - } - blobmsg_close_table(&b, index); - hotplug_handler_debug(b.head); - json_script_run(&jctx, rule_file, blob_data(b.head)); -} - -static struct uloop_fd hotplug_fd = { - .cb = hotplug_handler, -}; - -void hotplug_last_event(uloop_timeout_handler handler) -{ - last_event.cb = handler; - if (handler) - uloop_timeout_set(&last_event, HOTPLUG_WAIT); - else - uloop_timeout_cancel(&last_event); -} - -void hotplug(char *rules) -{ - struct sockaddr_nl nls; - int nlbufsize = 512 * 1024; - - rule_file = strdup(rules); - memset(&nls,0,sizeof(struct sockaddr_nl)); - nls.nl_family = AF_NETLINK; - nls.nl_pid = getpid(); - nls.nl_groups = -1; - - if ((hotplug_fd.fd = socket(PF_NETLINK, SOCK_DGRAM | SOCK_CLOEXEC, NETLINK_KOBJECT_UEVENT)) == -1) { - ERROR("Failed to open hotplug socket: %s\n", strerror(errno)); - exit(1); - } - if (bind(hotplug_fd.fd, (void *)&nls, sizeof(struct sockaddr_nl))) { - ERROR("Failed to bind hotplug socket: %s\n", strerror(errno)); - exit(1); - } - - if (setsockopt(hotplug_fd.fd, SOL_SOCKET, SO_RCVBUFFORCE, &nlbufsize, sizeof(nlbufsize))) - ERROR("Failed to resize receive buffer: %s\n", strerror(errno)); - - json_script_init(&jctx); - queue_proc.cb = queue_proc_cb; - uloop_fd_add(&hotplug_fd, ULOOP_READ); -} - -int hotplug_run(char *rules) -{ - uloop_init(); - hotplug(rules); - uloop_run(); - - return 0; -} - -void hotplug_shutdown(void) -{ - uloop_fd_delete(&hotplug_fd); - close(hotplug_fd.fd); -} diff --git a/plug/hotplug.h b/plug/hotplug.h deleted file mode 100644 index 2a44442..0000000 --- a/plug/hotplug.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (C) 2013 Felix Fietkau - * Copyright (C) 2013 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#ifndef __PROCD_HOTPLUG_H -#define __PROCD_HOTPLUG_H - -#include - -void hotplug(char *rules); -int hotplug_run(char *rules); -void hotplug_shutdown(void); -void hotplug_last_event(uloop_timeout_handler handler); - -#endif diff --git a/plug/udevtrigger.c b/plug/udevtrigger.c deleted file mode 100644 index 5013189..0000000 --- a/plug/udevtrigger.c +++ /dev/null @@ -1,264 +0,0 @@ -/* - * Copyright (C) 2004-2006 Kay Sievers - * Copyright (C) 2006 Hannes Reinecke - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation version 2 of the License. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PATH_SIZE 512 - -#ifndef strlcpy -#define strlcpy(d,s,l) (strncpy(d,s,l), (d)[(l)-1] = '\0') -#endif - -#ifndef strlcat -#define strlcat(d,s,l) strncat(d,s,(l)-strlen(d)-1) -#endif - -static int verbose; -static int dry_run; - -static void log_message(int priority, const char *format, ...) -{ - va_list args; - - va_start(args, format); - vsyslog(priority, format, args); - va_end(args); -} - -#undef err -#define err(format, arg...) \ - do { \ - log_message(LOG_ERR ,"%s: " format ,__FUNCTION__ ,## arg); \ - } while (0) - -#undef info -#define info(format, arg...) \ - do { \ - log_message(LOG_INFO ,"%s: " format ,__FUNCTION__ ,## arg); \ - } while (0) - -#ifdef DEBUG -#undef dbg -#define dbg(format, arg...) \ - do { \ - log_message(LOG_DEBUG ,"%s: " format ,__FUNCTION__ ,## arg); \ - } while (0) -#else -#define dbg(...) do {} while(0) -#endif - - -static void trigger_uevent(const char *devpath) -{ - char filename[PATH_SIZE]; - int fd; - - strlcpy(filename, "/sys", sizeof(filename)); - strlcat(filename, devpath, sizeof(filename)); - strlcat(filename, "/uevent", sizeof(filename)); - - if (verbose) - printf("%s\n", devpath); - - if (dry_run) - return; - - fd = open(filename, O_WRONLY); - if (fd < 0) { - dbg("error on opening %s: %s\n", filename, strerror(errno)); - return; - } - - if (write(fd, "add", 3) < 0) - info("error on triggering %s: %s\n", filename, strerror(errno)); - - close(fd); -} - -static int sysfs_resolve_link(char *devpath, size_t size) -{ - char link_path[PATH_SIZE]; - char link_target[PATH_SIZE]; - int len; - int i; - int back; - - strlcpy(link_path, "/sys", sizeof(link_path)); - strlcat(link_path, devpath, sizeof(link_path)); - len = readlink(link_path, link_target, sizeof(link_target)); - if (len <= 0) - return -1; - link_target[len] = '\0'; - dbg("path link '%s' points to '%s'", devpath, link_target); - - for (back = 0; strncmp(&link_target[back * 3], "../", 3) == 0; back++) - ; - dbg("base '%s', tail '%s', back %i", devpath, &link_target[back * 3], back); - for (i = 0; i <= back; i++) { - char *pos = strrchr(devpath, '/'); - - if (pos == NULL) - return -1; - pos[0] = '\0'; - } - dbg("after moving back '%s'", devpath); - strlcat(devpath, "/", size); - strlcat(devpath, &link_target[back * 3], size); - return 0; -} - -static bool device_has_attribute(const char *path, const char *attr, - mode_t mode) -{ - char filename[PATH_SIZE]; - struct stat statbuf; - - strlcpy(filename, path, sizeof(filename)); - strlcat(filename, attr, sizeof(filename)); - - if (stat(filename, &statbuf) < 0) - return false; - - if (!(statbuf.st_mode & mode)) - return false; - - return true; -} - -static int device_list_insert(const char *path) -{ - char devpath[PATH_SIZE]; - struct stat statbuf; - - dbg("add '%s'" , path); - - /* we only have a device, if we have a dev and an uevent file */ - if (!device_has_attribute(path, "/dev", S_IRUSR) || - !device_has_attribute(path, "/uevent", S_IWUSR)) - return -1; - - strlcpy(devpath, &path[4], sizeof(devpath)); - - /* resolve possible link to real target */ - if (lstat(path, &statbuf) < 0) - return -1; - if (S_ISLNK(statbuf.st_mode)) - if (sysfs_resolve_link(devpath, sizeof(devpath)) != 0) - return -1; - - trigger_uevent(devpath); - return 0; -} - -static void scan_subdir(const char *base, const char *subdir, - bool insert, int depth) -{ - DIR *dir; - struct dirent *dent; - - dir = opendir(base); - if (dir == NULL) - return; - - for (dent = readdir(dir); dent != NULL; dent = readdir(dir)) { - char dirname[PATH_SIZE]; - - if (dent->d_name[0] == '.') - continue; - - strlcpy(dirname, base, sizeof(dirname)); - strlcat(dirname, "/", sizeof(dirname)); - strlcat(dirname, dent->d_name, sizeof(dirname)); - - if (insert) { - int err; - - err = device_list_insert(dirname); - if (err) - continue; - } - - if (subdir) - strlcat(dirname, subdir, sizeof(base)); - - if (depth) - scan_subdir(dirname, NULL, true, depth - 1); - } - - closedir(dir); -} - -int main(int argc, char *argv[], char *envp[]) -{ - struct stat statbuf; - int option; - - openlog("udevtrigger", LOG_PID | LOG_CONS, LOG_DAEMON); - - while (1) { - option = getopt(argc, argv, "vnh"); - if (option == -1) - break; - - switch (option) { - case 'v': - verbose = 1; - break; - case 'n': - dry_run = 1; - break; - case 'h': - printf("Usage: udevtrigger OPTIONS\n" - " -v print the list of devices while running\n" - " -n do not actually trigger the events\n" - " -h print this text\n" - "\n"); - goto exit; - default: - goto exit; - } - } - - - /* if we have /sys/subsystem, forget all the old stuff */ - scan_subdir("/sys/bus", "/devices", false, 1); - scan_subdir("/sys/class", NULL, false, 1); - - /* scan "block" if it isn't a "class" */ - if (stat("/sys/class/block", &statbuf) != 0) - scan_subdir("/sys/block", NULL, true, 1); - -exit: - - closelog(); - return 0; -} diff --git a/preload.h b/preload.h deleted file mode 100644 index 5e663ac..0000000 --- a/preload.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2015 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include - -#ifndef __unbounded -#define __unbounded -#endif - -#ifndef attribute_unused -#define attribute_unused __attribute__ ((unused)) -#endif -typedef int (*main_t)(int, char **, char **); - -typedef int (*start_main_t)(main_t main, int, char *__unbounded *__unbounded, - ElfW(auxv_t) *, - __typeof (main), - void (*fini) (void), - void (*rtld_fini) (void), - void *__unbounded stack_end); - -int __libc_start_main(main_t main, - int argc, - char **argv, - ElfW(auxv_t) *auxvec, - __typeof (main) init, - void (*fini) (void), - void (*rtld_fini) (void), - void *stack_end); - - -typedef void (*uClibc_main)(main_t main, - int argc, - char **argv, - void (*app_init)(void), - void (*app_fini)(void), - void (*rtld_fini)(void), - void *stack_end attribute_unused); - -void __uClibc_main(main_t main, - int argc, - char **argv, - void (*app_init)(void), - void (*app_fini)(void), - void (*rtld_fini)(void), - void *stack_end attribute_unused); diff --git a/procd.c b/procd.c index e41d98a..a82d9a5 100644 --- a/procd.c +++ b/procd.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 @@ -23,16 +24,14 @@ #include "procd.h" #include "watchdog.h" -#include "plug/hotplug.h" -unsigned int debug; +unsigned int debug = 4; static int usage(const char *prog) { ERROR("Usage: %s [options]\n" "Options:\n" "\t-s \tPath to ubus socket\n" - "\t-h \trun as hotplug daemon\n" "\t-d \tEnable debug messages\n" "\n", prog); return 1; @@ -41,19 +40,15 @@ static int usage(const char *prog) int main(int argc, char **argv) { int ch; - char *dbglvl = getenv("DBGLVL"); + if (getpid() != 1) { + fprintf(stderr, "error: must run as PID 1\n"); + return 1; + } ulog_open(ULOG_KMSG, LOG_DAEMON, "procd"); - if (dbglvl) { - debug = atoi(dbglvl); - unsetenv("DBGLVL"); - } - - while ((ch = getopt(argc, argv, "d:s:h:")) != -1) { + while ((ch = getopt(argc, argv, "d:s:")) != -1) { switch (ch) { - case 'h': - return hotplug_run(optarg); case 's': ubus_socket = optarg; break; @@ -68,10 +63,7 @@ int main(int argc, char **argv) uloop_init(); procd_signal(); trigger_init(); - if (getpid() != 1) - procd_connect_ubus(); - else - procd_state_next(); + procd_state_next(); uloop_run(); uloop_done(); diff --git a/procd.h b/procd.h index 66d183c..eeb2889 100644 --- a/procd.h +++ b/procd.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 @@ -29,6 +30,8 @@ extern char *ubus_socket; extern int upgrade_running; +void procd_early(void); + void procd_connect_ubus(void); void procd_reconnect_ubus(int reconnect); void ubus_init_service(struct ubus_context *ctx); diff --git a/rcS.c b/rcS.c index 1e38d39..fae30c7 100644 --- a/rcS.c +++ b/rcS.c @@ -2,6 +2,7 @@ * runqueue-example.c * * Copyright (C) 2013 Felix Fietkau + * Copyright (C) 2015 Matthias Schiffer * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/rcS.h b/rcS.h index 91d37d1..a5be019 100644 --- a/rcS.h +++ b/rcS.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/service/instance.c b/service/instance.c index 40ff021..3c98ff7 100644 --- a/service/instance.c +++ b/service/instance.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/service/instance.h b/service/instance.h index 3fb33e9..cdf0bf7 100644 --- a/service/instance.h +++ b/service/instance.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/service/service.c b/service/service.c index 2702dc3..90f4d7c 100644 --- a/service/service.c +++ b/service/service.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 @@ -83,7 +84,6 @@ service_alloc(const char *name) s->instances.keep_old = true; s->name = new_name; s->avl.key = s->name; - INIT_LIST_HEAD(&s->validators); return s; } @@ -93,7 +93,6 @@ enum { SERVICE_SET_SCRIPT, SERVICE_SET_INSTANCES, SERVICE_SET_TRIGGER, - SERVICE_SET_VALIDATE, __SERVICE_SET_MAX }; @@ -102,7 +101,6 @@ static const struct blobmsg_policy service_set_attrs[__SERVICE_SET_MAX] = { [SERVICE_SET_SCRIPT] = { "script", BLOBMSG_TYPE_STRING }, [SERVICE_SET_INSTANCES] = { "instances", BLOBMSG_TYPE_TABLE }, [SERVICE_SET_TRIGGER] = { "triggers", BLOBMSG_TYPE_ARRAY }, - [SERVICE_SET_VALIDATE] = { "validate", BLOBMSG_TYPE_ARRAY }, }; static int @@ -117,8 +115,6 @@ service_update(struct service *s, struct blob_attr **tb, bool add) s->trigger = NULL; } - service_validate_del(s); - if (tb[SERVICE_SET_TRIGGER] && blobmsg_data_len(tb[SERVICE_SET_TRIGGER])) { s->trigger = blob_memdup(tb[SERVICE_SET_TRIGGER]); if (!s->trigger) @@ -126,11 +122,6 @@ service_update(struct service *s, struct blob_attr **tb, bool add) trigger_add(s->trigger, s); } - if (tb[SERVICE_SET_VALIDATE] && blobmsg_data_len(tb[SERVICE_SET_VALIDATE])) { - blobmsg_for_each_attr(cur, tb[SERVICE_SET_VALIDATE], rem) - service_validate_add(s, cur); - } - if (tb[SERVICE_SET_INSTANCES]) { if (!add) vlist_update(&s->instances); @@ -155,7 +146,6 @@ service_delete(struct service *s) trigger_del(s); free(s->trigger); free(s); - service_validate_del(s); } enum { @@ -200,19 +190,6 @@ static const struct blobmsg_policy event_policy[__EVENT_MAX] = { [EVENT_DATA] = { .name = "data", .type = BLOBMSG_TYPE_TABLE }, }; -enum { - VALIDATE_PACKAGE, - VALIDATE_TYPE, - VALIDATE_SERVICE, - __VALIDATE_MAX -}; - -static const struct blobmsg_policy validate_policy[__VALIDATE_MAX] = { - [VALIDATE_PACKAGE] = { .name = "package", .type = BLOBMSG_TYPE_STRING }, - [VALIDATE_TYPE] = { .name = "type", .type = BLOBMSG_TYPE_STRING }, - [VALIDATE_SERVICE] = { .name = "service", .type = BLOBMSG_TYPE_STRING }, -}; - enum { DATA_NAME, DATA_INSTANCE, @@ -282,8 +259,6 @@ service_dump(struct service *s, bool verbose) } if (verbose && s->trigger) blobmsg_add_blob(&b, s->trigger); - if (verbose && !list_empty(&s->validators)) - service_validate_dump(&b, s); blobmsg_close_table(&b, c); } @@ -398,34 +373,6 @@ service_handle_event(struct ubus_context *ctx, struct ubus_object *obj, return 0; } -static int -service_handle_validate(struct ubus_context *ctx, struct ubus_object *obj, - struct ubus_request_data *req, const char *method, - struct blob_attr *msg) -{ - struct blob_attr *tb[__VALIDATE_MAX]; - char *p = NULL, *t = NULL; - - if (!msg) - return UBUS_STATUS_INVALID_ARGUMENT; - - blobmsg_parse(validate_policy, __VALIDATE_MAX, tb, blob_data(msg), blob_len(msg)); - if (tb[VALIDATE_SERVICE]) { - return 0; - } - if (tb[VALIDATE_PACKAGE]) - p = blobmsg_get_string(tb[VALIDATE_PACKAGE]); - - if (tb[VALIDATE_TYPE]) - t = blobmsg_get_string(tb[VALIDATE_TYPE]); - - blob_buf_init(&b, 0); - service_validate_dump_all(&b, p, t); - ubus_send_reply(ctx, req, b.head); - - return 0; -} - static int service_get_data(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, @@ -493,7 +440,6 @@ static struct ubus_method main_object_methods[] = { UBUS_METHOD("update_start", service_handle_update, service_attrs), UBUS_METHOD("update_complete", service_handle_update, service_attrs), UBUS_METHOD("event", service_handle_event, event_policy), - UBUS_METHOD("validate", service_handle_validate, validate_policy), UBUS_METHOD("get_data", service_get_data, get_data_policy), }; @@ -557,6 +503,5 @@ void service_init(void) { avl_init(&services, avl_strcmp, false, NULL); - service_validate_init(); } diff --git a/service/service.h b/service/service.h index 892a147..e346058 100644 --- a/service/service.h +++ b/service/service.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 @@ -27,31 +28,15 @@ struct vrule { char *rule; }; -struct validate { - struct avl_node avl; - struct list_head list; - - char *package; - char *type; - - struct avl_tree rules; -}; - struct service { struct avl_node avl; const char *name; struct blob_attr *trigger; struct vlist_tree instances; - struct list_head validators; }; -void service_validate_add(struct service *s, struct blob_attr *attr); -void service_validate_dump(struct blob_buf *b, struct service *s); -void service_validate_dump_all(struct blob_buf *b, char *p, char *s); int service_start_early(char *name, char *cmdline); -void service_validate_del(struct service *s); -void service_validate_init(void); void service_init(void); void service_event(const char *type, const char *service, const char *instance); diff --git a/service/setlbf.c b/service/setlbf.c deleted file mode 100644 index 94c251e..0000000 --- a/service/setlbf.c +++ /dev/null @@ -1,6 +0,0 @@ -#include - -static void __attribute__((constructor)) setlbf(void) -{ - setbuf(stdout, NULL); -} diff --git a/service/trigger.c b/service/trigger.c index 97a06bb..9c7115c 100644 --- a/service/trigger.c +++ b/service/trigger.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/service/validate.c b/service/validate.c deleted file mode 100644 index 6a449f4..0000000 --- a/service/validate.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2013 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include -#include -#include - -#include "../procd.h" - -#include "service.h" - -enum { - SERVICE_VAL_PACKAGE, - SERVICE_VAL_TYPE, - SERVICE_VAL_DATA, - __SERVICE_VAL_MAX -}; - -static const struct blobmsg_policy service_validate_attrs[__SERVICE_VAL_MAX] = { - [SERVICE_VAL_PACKAGE] = { "package", BLOBMSG_TYPE_STRING }, - [SERVICE_VAL_TYPE] = { "type", BLOBMSG_TYPE_STRING }, - [SERVICE_VAL_DATA] = { "data", BLOBMSG_TYPE_TABLE }, -}; - -static struct avl_tree validators; - -void -service_validate_dump_all(struct blob_buf *b, char *p, char *s) -{ - struct json_object *r = json_object_new_object(); - struct validate *v; - - if (!r) - return; - - avl_for_each_element(&validators, v, avl) { - struct json_object *o, *t; - struct vrule *vr; - - if (p && strcmp(p, v->package)) - continue; - - if (s && strcmp(s, v->type)) - continue; - - json_object_object_get_ex(r, v->package, &o); - if (!o) { - o = json_object_new_object(); - json_object_object_add(r, v->package, o); - } - json_object_object_get_ex(o, v->type, &t); - if (!t) { - t = json_object_new_object(); - json_object_object_add(o, v->type, t); - } - avl_for_each_element(&v->rules, vr, avl) - json_object_object_add(t, vr->option, json_object_new_string(vr->rule)); - } - blobmsg_add_object(b, r); - json_object_put(r); -} - -void -service_validate_dump(struct blob_buf *b, struct service *s) -{ - struct validate *v; - void *i = blobmsg_open_array(b, "validate"); - - list_for_each_entry(v, &s->validators, list) { - struct vrule *vr; - void *k, *j = blobmsg_open_table(b, "validate"); - - blobmsg_add_string(b, "package", v->package); - blobmsg_add_string(b, "type", v->type); - k = blobmsg_open_table(b, "rules"); - avl_for_each_element(&v->rules, vr, avl) - blobmsg_add_string(b, vr->option, vr->rule); - blobmsg_close_table(b, k); - blobmsg_close_table(b, j); - } - blobmsg_close_array(b, i); -} - -void -service_validate_del(struct service *s) -{ - struct validate *v, *n; - - if (list_empty(&s->validators)) - return; - - list_for_each_entry_safe(v, n, &s->validators, list) { - struct vrule *vr, *a; - - avl_remove_all_elements(&v->rules, vr, avl, a) - free(vr); - - avl_delete(&validators, &v->avl); - list_del(&v->list); - free(v); - } -} - -void -service_validate_add(struct service *s, struct blob_attr *msg) -{ - struct blob_attr *tb[__SERVICE_VAL_MAX]; - struct validate *v; - char *type, *package; - struct blob_attr *cur; - int rem; - - blobmsg_parse(service_validate_attrs, __SERVICE_VAL_MAX, tb, blobmsg_data(msg), blobmsg_data_len(msg)); - if (!tb[SERVICE_VAL_PACKAGE] || !tb[SERVICE_VAL_TYPE] || !tb[SERVICE_VAL_DATA]) - return; - - v = calloc_a(sizeof(*v), &package, blobmsg_data_len(tb[SERVICE_VAL_PACKAGE]) + 1, - &type, blobmsg_data_len(tb[SERVICE_VAL_TYPE]) + 1); - if (!v) - return; - - v->type = type; - v->avl.key = v->package = package; - strcpy(v->package, blobmsg_get_string(tb[SERVICE_VAL_PACKAGE])); - strcpy(v->type, blobmsg_get_string(tb[SERVICE_VAL_TYPE])); - - list_add(&v->list, &s->validators); - if (avl_insert(&validators, &v->avl)) { - free(v); - return; - } - avl_init(&v->rules, avl_strcmp, false, NULL); - - blobmsg_for_each_attr(cur, tb[SERVICE_VAL_DATA], rem) { - char *option; - char *rule; - struct vrule *vr = calloc_a(sizeof(*vr), &option, strlen(blobmsg_name(cur)) + 1, - &rule, strlen(blobmsg_get_string(cur)) + 1); - - vr->avl.key = vr->option = option; - vr->rule = rule; - strcpy(vr->option, blobmsg_name(cur)); - strcpy(vr->rule, blobmsg_get_string(cur)); - if (avl_insert(&v->rules, &vr->avl)) - free(vr); - } -} - -void -service_validate_init(void) -{ - avl_init(&validators, avl_strcmp, true, NULL); -} diff --git a/service/watch.c b/service/watch.c index 349b484..cc0b2ee 100644 --- a/service/watch.c +++ b/service/watch.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/signal.c b/signal.c index 16824f7..60b8f82 100644 --- a/signal.c +++ b/signal.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/state.c b/state.c index 1ed70f5..1faa7a0 100644 --- a/state.c +++ b/state.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 @@ -22,7 +23,6 @@ #include "procd.h" #include "syslog.h" -#include "plug/hotplug.h" #include "watchdog.h" #include "service/service.h" #include "utils/utils.h" @@ -30,7 +30,6 @@ enum { STATE_NONE = 0, STATE_EARLY, - STATE_UBUS, STATE_INIT, STATE_RUNNING, STATE_SHUTDOWN, @@ -99,17 +98,9 @@ static void state_enter(void) switch (state) { case STATE_EARLY: - LOG("- early -\n"); watchdog_init(0); - hotplug("/etc/hotplug.json"); - procd_coldplug(); - break; - - case STATE_UBUS: - // try to reopen incase the wdt was not available before coldplug - watchdog_init(0); - set_stdio("console"); - LOG("- ubus -\n"); + LOG("- early -\n"); + procd_early(); procd_connect_ubus(); service_init(); service_start_early("ubus", ubus_cmd); @@ -185,7 +176,7 @@ void procd_state_next(void) void procd_state_ubus_connect(void) { - if (state == STATE_UBUS) + if (state == STATE_EARLY) procd_state_next(); } diff --git a/system.c b/system.c index fb7fbe4..5f0b9bb 100644 --- a/system.c +++ b/system.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/trace/preload.c b/trace/preload.c deleted file mode 100644 index 99dd906..0000000 --- a/trace/preload.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2015 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../preload.h" - -#define ERROR(fmt, ...) do { \ - fprintf(stderr,"perload-jail: "fmt, ## __VA_ARGS__); \ - } while (0) - -static main_t __main__; - -static int __preload_main__(int argc, char **argv, char **envp) -{ - unsetenv("LD_PRELOAD"); - ptrace(PTRACE_TRACEME); - kill(getpid(), SIGSTOP); - - return (*__main__)(argc, argv, envp); -} - -int __libc_start_main(main_t main, - int argc, - char **argv, - ElfW(auxv_t) *auxvec, - __typeof (main) init, - void (*fini) (void), - void (*rtld_fini) (void), - void *stack_end) -{ - start_main_t __start_main__; - - __start_main__ = dlsym(RTLD_NEXT, "__libc_start_main"); - if (!__start_main__) - ERROR("failed to find __libc_start_main %s\n", dlerror()); - - __main__ = main; - - return (*__start_main__)(__preload_main__, argc, argv, auxvec, - init, fini, rtld_fini, stack_end); -} - -void __uClibc_main(main_t main, - int argc, - char **argv, - void (*app_init)(void), - void (*app_fini)(void), - void (*rtld_fini)(void), - void *stack_end attribute_unused) -{ - uClibc_main __start_main__; - - __start_main__ = dlsym(RTLD_NEXT, "__uClibc_main"); - if (!__start_main__) - ERROR("failed to find __uClibc_main %s\n", dlerror()); - - __main__ = main; - - return (*__start_main__)(__preload_main__, argc, argv, - app_init, app_fini, rtld_fini, stack_end); -} diff --git a/trace/trace.c b/trace/trace.c deleted file mode 100644 index b0005b8..0000000 --- a/trace/trace.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2015 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "../syscall-names.h" - -#define _offsetof(a, b) __builtin_offsetof(a,b) -#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) - -#ifdef __amd64__ -#define reg_syscall_nr _offsetof(struct user, regs.orig_rax) -#elif defined(__i386__) -#define reg_syscall_nr _offsetof(struct user, regs.orig_eax) -#elif defined(__mips) -# ifndef EF_REG2 -# define EF_REG2 8 -# endif -#define reg_syscall_nr (EF_REG2 / 4) -#elif defined(__arm__) -#define reg_syscall_nr _offsetof(struct user, regs.uregs[7]) -#else -#error tracing is not supported on this architecture -#endif - -#define INFO(fmt, ...) do { \ - fprintf(stderr, "utrace: "fmt, ## __VA_ARGS__); \ -} while (0) - -#define ERROR(fmt, ...) do { \ - syslog(LOG_ERR, "utrace: "fmt, ## __VA_ARGS__); \ - fprintf(stderr, "utrace: "fmt, ## __VA_ARGS__); \ -} while (0) - -static struct uloop_process tracer; -static int *syscall_count; -static struct blob_buf b; -static int syscall_max; -static int in_syscall; -static int debug; - -static int max_syscall = ARRAY_SIZE(syscall_names); - -static void set_syscall(const char *name, int val) -{ - int i; - - for (i = 0; i < max_syscall; i++) - if (syscall_names[i] && !strcmp(syscall_names[i], name)) { - syscall_count[i] = val; - return; - } -} - -static void print_syscalls(int policy, const char *json) -{ - void *c; - int i; - - set_syscall("rt_sigaction", 1); - set_syscall("sigreturn", 1); - set_syscall("rt_sigreturn", 1); - set_syscall("exit_group", 1); - set_syscall("exit", 1); - - blob_buf_init(&b, 0); - c = blobmsg_open_array(&b, "whitelist"); - - for (i = 0; i < ARRAY_SIZE(syscall_names); i++) { - if (!syscall_count[i]) - continue; - if (syscall_names[i]) { - if (debug) - printf("syscall %d (%s) was called %d times\n", - i, syscall_names[i], syscall_count[i]); - blobmsg_add_string(&b, NULL, syscall_names[i]); - } else { - ERROR("no name found for syscall(%d)\n", i); - } - } - blobmsg_close_array(&b, c); - blobmsg_add_u32(&b, "policy", policy); - if (json) { - FILE *fp = fopen(json, "w"); - if (fp) { - fprintf(fp, "%s", blobmsg_format_json_indent(b.head, true, 0)); - fclose(fp); - INFO("saving syscall trace to %s\n", json); - } else { - ERROR("failed to open %s\n", json); - } - } else { - printf("%s\n", - blobmsg_format_json_indent(b.head, true, 0)); - } - -} - -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); -} - -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; -} diff --git a/ubus.c b/ubus.c index 211a1ec..386a7d4 100644 --- a/ubus.c +++ b/ubus.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/upgraded/CMakeLists.txt b/upgraded/CMakeLists.txt deleted file mode 100644 index 093dba2..0000000 --- a/upgraded/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -cmake_minimum_required(VERSION 2.6) - -PROJECT(upgraded C) -ADD_DEFINITIONS(-Os -ggdb -Wall -Werror --std=gnu99 -Wmissing-declarations) -set(CMAKE_EXE_LINKER_FLAGS "-static -fPIC") -set(CMAKE_FIND_LIBRARY_SUFFIXES .a) -set(CMAKE_EXE_LINK_DYNAMIC_C_FLAGS) -set(CMAKE_EXE_LINK_DYNAMIC_CXX_FLAGS) -set(CMAKE_SHARED_LIBRARY_C_FLAGS) -set(CMAKE_SHARED_LIBRARY_CXX_FLAGS) -set(CMAKE_SHARED_LIBRARY_LINK_C_FLAGS) -set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS) -ADD_EXECUTABLE(upgraded upgraded.c ../watchdog.c) -TARGET_LINK_LIBRARIES(upgraded ubox rt -lc -lgcc_pic) -INSTALL(TARGETS upgraded - RUNTIME DESTINATION sbin -) diff --git a/upgraded/upgraded.c b/upgraded/upgraded.c deleted file mode 100644 index d7433e7..0000000 --- a/upgraded/upgraded.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (C) 2013 Felix Fietkau - * Copyright (C) 2013 John Crispin - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 2.1 - * as published by the Free Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - */ - -#include - -#include -#include -#include -#include -#include - -#include - -#include "../watchdog.h" - -static struct uloop_process upgrade_proc; -unsigned int debug = 2; - -static void upgrade_proc_cb(struct uloop_process *proc, int ret) -{ - if (ret) - fprintf(stderr, "sysupgrade aborted with return code: %d\n", ret); - uloop_end(); -} - -static void sysupgarde(char *folder) -{ - char *args[] = { "/sbin/sysupgrade", "nand", NULL, NULL }; - - args[2] = folder; - upgrade_proc.cb = upgrade_proc_cb; - upgrade_proc.pid = fork(); - if (!upgrade_proc.pid) { - execvp(args[0], args); - fprintf(stderr, "Failed to fork sysupgrade\n"); - exit(-1); - } - if (upgrade_proc.pid <= 0) { - fprintf(stderr, "Failed to start sysupgarde\n"); - uloop_end(); - } -} - -int main(int argc, char **argv) -{ - pid_t p = getpid(); - - if (p != 1) { - fprintf(stderr, "this tool needs to run as pid 1\n"); - return -1; - } - if (chdir("/tmp") == -1) { - fprintf(stderr, "failed to chdir to /tmp: %s\n", strerror(errno)); - return -1; - } - if (argc != 2) { - fprintf(stderr, "sysupgrade stage 2 failed, no folder specified\n"); - return -1; - } - - uloop_init(); - watchdog_init(0); - sysupgarde(argv[1]); - uloop_run(); - - reboot(RB_AUTOBOOT); - - return 0; -} diff --git a/utils/askfirst.c b/utils/askfirst.c index 69de76f..cdd2883 100644 --- a/utils/askfirst.c +++ b/utils/askfirst.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/utils/utils.c b/utils/utils.c index c0d1cd5..8dbbbd2 100644 --- a/utils/utils.c +++ b/utils/utils.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/utils/utils.h b/utils/utils.h index 8b384fc..c371678 100644 --- a/utils/utils.h +++ b/utils/utils.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/watchdog.c b/watchdog.c index 592ae7e..0eae9c8 100644 --- a/watchdog.c +++ b/watchdog.c @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 diff --git a/watchdog.h b/watchdog.h index 015fa93..8d64895 100644 --- a/watchdog.h +++ b/watchdog.h @@ -1,6 +1,7 @@ /* * Copyright (C) 2013 Felix Fietkau * Copyright (C) 2013 John Crispin + * Copyright (C) 2015 Matthias Schiffer * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License version 2.1 -- cgit v1.2.3