diff --git a/configure b/configure index d9d8c5ad..aae709e1 100755 --- a/configure +++ b/configure @@ -3816,7 +3816,7 @@ TARGET="$WITH_TARGET" -ac_config_files="$ac_config_files Makefile executer/user/Makefile executer/kernel/Makefile kernel/Makefile kernel/Makefile.build arch/x86/tools/mcreboot-attached-mic.sh arch/x86/tools/mcshutdown-attached-mic.sh arch/x86/tools/mcreboot-builtin-x86.sh arch/x86/tools/mcreboot-smp-x86.sh arch/x86/tools/mcshutdown-builtin-x86.sh arch/x86/tools/mcreboot.1:arch/x86/tools/mcreboot.1in" +ac_config_files="$ac_config_files Makefile executer/user/Makefile executer/kernel/Makefile executer/kernel/mcctrl.h kernel/Makefile kernel/Makefile.build arch/x86/tools/mcreboot-attached-mic.sh arch/x86/tools/mcshutdown-attached-mic.sh arch/x86/tools/mcreboot-builtin-x86.sh arch/x86/tools/mcreboot-smp-x86.sh arch/x86/tools/mcshutdown-builtin-x86.sh arch/x86/tools/mcreboot.1:arch/x86/tools/mcreboot.1in" if test "x$enable_dcfa" = xyes; then : @@ -4533,6 +4533,7 @@ do "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; "executer/user/Makefile") CONFIG_FILES="$CONFIG_FILES executer/user/Makefile" ;; "executer/kernel/Makefile") CONFIG_FILES="$CONFIG_FILES executer/kernel/Makefile" ;; + "executer/kernel/mcctrl.h") CONFIG_FILES="$CONFIG_FILES executer/kernel/mcctrl.h" ;; "kernel/Makefile") CONFIG_FILES="$CONFIG_FILES kernel/Makefile" ;; "kernel/Makefile.build") CONFIG_FILES="$CONFIG_FILES kernel/Makefile.build" ;; "arch/x86/tools/mcreboot-attached-mic.sh") CONFIG_FILES="$CONFIG_FILES arch/x86/tools/mcreboot-attached-mic.sh" ;; diff --git a/configure.ac b/configure.ac index fab17194..eab1a355 100644 --- a/configure.ac +++ b/configure.ac @@ -161,6 +161,7 @@ AC_CONFIG_FILES([ Makefile executer/user/Makefile executer/kernel/Makefile + executer/kernel/mcctrl.h kernel/Makefile kernel/Makefile.build arch/x86/tools/mcreboot-attached-mic.sh diff --git a/executer/kernel/Makefile.in b/executer/kernel/Makefile.in index 7149d849..51f04bc8 100644 --- a/executer/kernel/Makefile.in +++ b/executer/kernel/Makefile.in @@ -8,7 +8,7 @@ obj-m += mcctrl.o ccflags-y := -I$(IHK_BASE)/linux/include -I$(IHK_BASE)/ikc/include -I$(IHK_BASE)/include -I$(src)/../include -mcmodel=kernel -mno-red-zone -mcctrl-y := driver.o control.o ikc.o syscall.o procfs.o +mcctrl-y := driver.o control.o ikc.o syscall.o procfs.o binfmt_mcexec.o KBUILD_EXTRA_SYMBOLS = @abs_builddir@/../../../ihk/linux/core/Module.symvers diff --git a/executer/kernel/binfmt_mcexec.c b/executer/kernel/binfmt_mcexec.c new file mode 100644 index 00000000..b1b038d4 --- /dev/null +++ b/executer/kernel/binfmt_mcexec.c @@ -0,0 +1,256 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mcctrl.h" + +static int pathcheck(const char *file, const char *list) +{ + const char *p; + const char *q; + const char *r; + int l; + + if(!*list) + return 1; + p = list; + do{ + q = strchr(p, ':'); + if(!q) + q = strchr(p, '\0'); + for(r = q - 1; r >= p && *r == '/'; r--); + l = r - p + 1; + + if(!strncmp(file, p, l) && + file[l] == '/') + return 1; + + p = q + 1; + } while(*q); + return 0; +} + +static int load_elf(struct linux_binprm *bprm) +{ + const char *i_name; + char *cp; + struct file *file; + char interp[BINPRM_BUF_SIZE]; + int retval; + struct elfhdr *elf_ex = (struct elfhdr *)bprm->buf; + typedef struct { + char *name; + char *val; + int l; + } envdata; + envdata env[] = { + {.name = "MCEXEC"}, +#define env_mcexec (env[0].val) + {.name = "MCEXEC_WL"}, +#define env_mcexec_wl (env[1].val) + {.name = "MCEXEC_BL"}, +#define env_mcexec_bl (env[2].val) + {.name = NULL} + }; + envdata *ep; + unsigned long off = 0; + struct page *page; + char *addr = NULL; + int i; + unsigned long p; + int st; + int mode; + int cnt[2]; + char buf[32]; + int l; + int pass; + + if(memcmp(elf_ex->e_ident, ELFMAG, SELFMAG) != 0) + return -ENOEXEC; + if(elf_ex->e_type != ET_EXEC && elf_ex->e_type != ET_DYN) + return -ENOEXEC; + + if(elf_ex->e_ident[EI_CLASS] != ELFCLASS64) + return -ENOEXEC; + + cp = strrchr(bprm->interp, '/'); + if(!cp || + !strcmp(cp, "/mcexec") || + !strcmp(cp, "/ihkosctl") || + !strcmp(cp, "/ihkconfig")) + return -ENOEXEC; + + cnt[0] = bprm->argc; + cnt[1] = bprm->envc; + for(pass = 0; pass < 2; pass++){ + p = bprm->p; + mode = cnt[0] == 0? (cnt[1] == 0? 2: 1): 0; + if(pass == 1){ + for(ep = env; ep->name; ep++){ + if(ep->l) + ep->val = kmalloc(ep->l, GFP_KERNEL); + } + } + ep = NULL; + l = 0; + for(i = 0, st = 0; mode != 2;){ + if(st == 0){ + off = p & ~PAGE_MASK; + retval = get_user_pages(current, bprm->mm, + bprm->p, 1, 0, 1, + &page, NULL); + if(retval <= 0) + return -EFAULT; + addr = kmap_atomic(page); + st = 1; + } + if(addr[off]){ + if(mode == 1){ + if(ep){ + if(pass == 1) + ep->val[l] = addr[off]; + l++; + } + else if(addr[off] == '='){ + if(l < 32) + buf[l] = '\0'; + buf[31] = '\0'; + for(ep = env; ep->name; ep++) + if(!strcmp(ep->name, buf)) + break; + if(ep->name) + l = 0; + else + ep = NULL; + } + else{ + if(l < 32) + buf[l] = addr[off]; + l++; + } + + } + } + else{ + if(mode == 1 && ep){ + if(pass == 0){ + ep->l = l + 1; + } + else{ + ep->val[l] = '\0'; + } + } + ep = NULL; + l = 0; + i++; + if(i == cnt[mode]){ + i = 0; + mode++; + } + } + off++; + p++; + if(off == PAGE_SIZE || mode == 2){ + kunmap_atomic(addr); + put_page(page); + st = 0; + } + } + } + + if(!env_mcexec || !strcmp(env_mcexec, "0") || !strcmp(env_mcexec, "off")) + retval = 1; + else{ + retval = 0; + if(strchr(env_mcexec, '/') && strlen(env_mcexec) < BINPRM_BUF_SIZE) + strcpy(interp, env_mcexec); + else + strcpy(interp, MCEXEC_PATH); + } + + if(retval); + else if(env_mcexec_wl) + retval = !pathcheck(bprm->interp, env_mcexec_wl); + else if(env_mcexec_bl) + retval = pathcheck(bprm->interp, env_mcexec_bl); + else + retval = pathcheck(bprm->interp, "/usr:/bin:/sbin:/opt"); + + for(ep = env; ep->name; ep++) + if(ep->val) + kfree(ep->val); + if(retval) + return -ENOEXEC; + + file = open_exec(interp); + if (IS_ERR(file)) + return -ENOEXEC; + + retval = remove_arg_zero(bprm); + if (retval){ + fput(file); + return retval; + } + retval = copy_strings_kernel(1, &bprm->interp, bprm); + if (retval < 0){ + fput(file); + return retval; + } + bprm->argc++; + i_name = interp; + retval = copy_strings_kernel(1, &i_name, bprm); + if (retval){ + fput(file); + return retval; + } + bprm->argc++; +#if 1 + retval = bprm_change_interp(interp, bprm); + if (retval < 0){ + fput(file); + return retval; + } +#else + if(brpm->interp != bprm->filename) + kfree(brpm->interp); + kfree(brpm->filename); + bprm->filename = bprm->interp = kstrdup(interp, GFP_KERNEL); + if(!bprm->interp){ + fput(file); + return -ENOMEM; + } +#endif + + allow_write_access(bprm->file); + fput(bprm->file); + bprm->file = file; + + retval = prepare_binprm(bprm); + if (retval < 0){ + return retval; + } + return search_binary_handler(bprm); +} + +static struct linux_binfmt mcexec_format = { + .module = THIS_MODULE, + .load_binary = load_elf, +}; + +void __init binfmt_mcexec_init(void) +{ + insert_binfmt(&mcexec_format); +} + +void __exit binfmt_mcexec_exit(void) +{ + unregister_binfmt(&mcexec_format); +} diff --git a/executer/kernel/driver.c b/executer/kernel/driver.c index 0e03d5fe..bcdb72c5 100644 --- a/executer/kernel/driver.c +++ b/executer/kernel/driver.c @@ -41,6 +41,8 @@ extern void procfs_exit(int); extern void rus_page_hash_init(void); extern void rus_page_hash_put_pages(void); +extern void binfmt_mcexec_init(void); +extern void binfmt_mcexec_exit(void); static long mcctrl_ioctl(ihk_os_t os, unsigned int request, void *priv, unsigned long arg, struct file *file) @@ -120,6 +122,8 @@ static int __init mcctrl_init(void) } } + binfmt_mcexec_init(); + return 0; } @@ -127,6 +131,7 @@ static void __exit mcctrl_exit(void) { int i; + binfmt_mcexec_exit(); printk("mcctrl: unregistered.\n"); for(i = 0; i < OS_MAX_MINOR; i++){ if(os[i]){ diff --git a/executer/kernel/mcctrl.h b/executer/kernel/mcctrl.h.in similarity index 99% rename from executer/kernel/mcctrl.h rename to executer/kernel/mcctrl.h.in index 35e52a1b..a7ac0d26 100644 --- a/executer/kernel/mcctrl.h +++ b/executer/kernel/mcctrl.h.in @@ -38,6 +38,8 @@ #include #include +#define MCEXEC_PATH "@BINDIR@/mcexec" + #define SCD_MSG_PREPARE_PROCESS 0x1 #define SCD_MSG_PREPARE_PROCESS_ACKED 0x2 #define SCD_MSG_PREPARE_PROCESS_NACKED 0x7