From a79a0a618d2b0219307b77ecd721cba34edaf117 Mon Sep 17 00:00:00 2001 From: NAKAMURA Gou Date: Thu, 7 Aug 2014 16:16:13 +0900 Subject: [PATCH 01/15] drop VM_IO because it's not MMIO --- executer/kernel/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executer/kernel/syscall.c b/executer/kernel/syscall.c index 946f4827..3ce5f454 100644 --- a/executer/kernel/syscall.c +++ b/executer/kernel/syscall.c @@ -429,7 +429,7 @@ static struct vm_operations_struct rus_vmops = { static int rus_mmap(struct file *file, struct vm_area_struct *vma) { - vma->vm_flags |= VM_IO | VM_RESERVED | VM_DONTEXPAND | VM_PFNMAP; + vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND | VM_PFNMAP; vma->vm_ops = &rus_vmops; return 0; } From fe39d56554677740ce4aec51d49dd39da57e8060 Mon Sep 17 00:00:00 2001 From: NAKAMURA Gou Date: Thu, 7 Aug 2014 16:36:33 +0900 Subject: [PATCH 02/15] use mixed mapping instead of PFN mapping --- executer/kernel/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executer/kernel/syscall.c b/executer/kernel/syscall.c index 3ce5f454..c2257d02 100644 --- a/executer/kernel/syscall.c +++ b/executer/kernel/syscall.c @@ -429,7 +429,7 @@ static struct vm_operations_struct rus_vmops = { static int rus_mmap(struct file *file, struct vm_area_struct *vma) { - vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND | VM_PFNMAP; + vma->vm_flags |= VM_RESERVED | VM_DONTEXPAND | VM_MIXEDMAP; vma->vm_ops = &rus_vmops; return 0; } From b4910ec33f0786b15e461ee3f0848604f5d1439d Mon Sep 17 00:00:00 2001 From: NAKAMURA Gou Date: Thu, 7 Aug 2014 16:03:36 +0900 Subject: [PATCH 03/15] use vm_insert_page() if 'struct page' exists --- executer/kernel/syscall.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/executer/kernel/syscall.c b/executer/kernel/syscall.c index c2257d02..f41f993d 100644 --- a/executer/kernel/syscall.c +++ b/executer/kernel/syscall.c @@ -405,6 +405,19 @@ static int rus_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) pfn = phys >> PAGE_SHIFT; #if USE_VM_INSERT_PFN for (pix = 0; pix < (pgsize / PAGE_SIZE); ++pix) { + struct page *page; + + if (pfn_valid(pfn+pix)) { + page = pfn_to_page(pfn+pix); + if (!page_count(page)) { + get_page(page); + } + error = vm_insert_page(vma, rva+(pix*PAGE_SIZE), page); + if (error) { + printk("vm_insert_page: %d\n", error); + } + } + else error = vm_insert_pfn(vma, rva+(pix*PAGE_SIZE), pfn+pix); if (error) { break; From 8c1c8a40d1a681fdcfd8d536a824d4eeae2bfac8 Mon Sep 17 00:00:00 2001 From: NAKAMURA Gou Date: Thu, 7 Aug 2014 12:31:48 +0900 Subject: [PATCH 04/15] use madvise() when zap_vma_ptes() fails --- executer/kernel/syscall.c | 21 ++++++++++++++------- executer/user/mcexec.c | 6 +++++- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/executer/kernel/syscall.c b/executer/kernel/syscall.c index f41f993d..fb7d4bc9 100644 --- a/executer/kernel/syscall.c +++ b/executer/kernel/syscall.c @@ -1138,13 +1138,16 @@ out: return (IS_ERR_VALUE(map))? (int)map: 0; } -static void clear_pte_range(uintptr_t start, uintptr_t len) +static int clear_pte_range(uintptr_t start, uintptr_t len) { struct mm_struct *mm = current->mm; struct vm_area_struct *vma; uintptr_t addr; uintptr_t end; + int error; + int ret; + ret = 0; down_read(&mm->mmap_sem); addr = start; while (addr < (start + len)) { @@ -1161,14 +1164,15 @@ static void clear_pte_range(uintptr_t start, uintptr_t len) end = vma->vm_end; } if (addr < end) { - zap_vma_ptes(vma, addr, end-addr); - dprintk("clear_pte_range() 0x%lx - 0x%lx OK\n", - vma->vm_start, vma->vm_end); + error = zap_vma_ptes(vma, addr, end-addr); + if (ret == 0) { + ret = error; + } } addr = end; } up_read(&mm->mmap_sem); - return; + return ret; } /** @@ -1306,8 +1310,11 @@ int __do_in_kernel_syscall(ihk_os_t os, struct mcctrl_channel *c, struct syscall ppd->pid, ppd->rpgtable); } - clear_pte_range(sc->args[0], sc->args[1]); - ret = 0; + error = clear_pte_range(sc->args[0], sc->args[1]); + if (error) { + error = -ENOSYS; + goto out; + } break; case __NR_mprotect: diff --git a/executer/user/mcexec.c b/executer/user/mcexec.c index a8f08d89..d3661911 100644 --- a/executer/user/mcexec.c +++ b/executer/user/mcexec.c @@ -1157,12 +1157,16 @@ int main_loop(int fd, int cpu, pthread_mutex_t *lock) return w.sr.args[0]; case __NR_mmap: - case __NR_munmap: case __NR_mprotect: /* reserved for internal use */ do_syscall_return(fd, cpu, -ENOSYS, 0, 0, 0, 0); break; + case __NR_munmap: + ret = madvise((void *)w.sr.args[0], w.sr.args[1], MADV_DONTNEED); + do_syscall_return(fd, cpu, ret, 0, 0, 0, 0); + break; + #ifdef USE_SYSCALL_MOD_CALL case 303:{ __dprintf("mcexec.c,mod_cal,mod=%ld,cmd=%ld\n", w.sr.args[0], w.sr.args[1]); From 34854d3c93e108d43b98b0bdb781a81b0ef5453c Mon Sep 17 00:00:00 2001 From: Tomoki Shirasawa Date: Mon, 1 Sep 2014 14:27:31 +0900 Subject: [PATCH 05/15] ltp times03 --- executer/user/mcexec.c | 44 ++++++++++++++++++------------------------ 1 file changed, 19 insertions(+), 25 deletions(-) diff --git a/executer/user/mcexec.c b/executer/user/mcexec.c index c13890f9..15c19e96 100644 --- a/executer/user/mcexec.c +++ b/executer/user/mcexec.c @@ -608,33 +608,27 @@ sendsig(int sig, siginfo_t *siginfo, void *context) siginfo->si_signo == SIGINT) return; - if(tid == master_tid){ - cpu = 0; - remote_tid = -1; + for(i = 0; i < ncpu; i++){ + if(siginfo->si_pid == pid && + thread_data[i].tid == tid){ + if(thread_data[i].terminate) + return; + break; + } + if(siginfo->si_pid != pid && + thread_data[i].remote_tid == tid){ + if(thread_data[i].terminate) + return; + break; + } + } + if(i != ncpu){ + remote_tid = thread_data[i].remote_tid; + cpu = thread_data[i].cpu; } else{ - for(i = 1; i < ncpu; i++){ - if(siginfo->si_pid == pid && - thread_data[i].tid == tid){ - if(thread_data[i].terminate) - return; - break; - } - if(siginfo->si_pid != pid && - thread_data[i].remote_tid == tid){ - if(thread_data[i].terminate) - return; - break; - } - } - if(i != ncpu){ - remote_tid = thread_data[i].remote_tid; - cpu = thread_data[i].cpu; - } - else{ - cpu = 0; - remote_tid = -1; - } + cpu = 0; + remote_tid = -1; } sigdesc.cpu = cpu; From 431adf7e7c293bbb908576289bff3a444eaad4fd Mon Sep 17 00:00:00 2001 From: NAKAMURA Gou Date: Fri, 29 Aug 2014 16:02:52 +0900 Subject: [PATCH 06/15] mcctrl: report success when __NR_munmap succeeds --- executer/kernel/syscall.c | 1 + 1 file changed, 1 insertion(+) diff --git a/executer/kernel/syscall.c b/executer/kernel/syscall.c index fb7d4bc9..0d6b1fd6 100644 --- a/executer/kernel/syscall.c +++ b/executer/kernel/syscall.c @@ -1315,6 +1315,7 @@ int __do_in_kernel_syscall(ihk_os_t os, struct mcctrl_channel *c, struct syscall error = -ENOSYS; goto out; } + ret = 0; break; case __NR_mprotect: From f2e0e42ba4a51a247270a2291da6ffcd3238ccb8 Mon Sep 17 00:00:00 2001 From: NAKAMURA Gou Date: Fri, 29 Aug 2014 16:03:07 +0900 Subject: [PATCH 07/15] mcexec: report proper error when __NR_munmap fails --- executer/user/mcexec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/executer/user/mcexec.c b/executer/user/mcexec.c index d3661911..6d03b28b 100644 --- a/executer/user/mcexec.c +++ b/executer/user/mcexec.c @@ -1164,6 +1164,7 @@ int main_loop(int fd, int cpu, pthread_mutex_t *lock) case __NR_munmap: ret = madvise((void *)w.sr.args[0], w.sr.args[1], MADV_DONTNEED); + SET_ERR(ret); do_syscall_return(fd, cpu, ret, 0, 0, 0, 0); break; From 4177f1c9cd4ce2e9338ce7b935ca95f00687a3dd Mon Sep 17 00:00:00 2001 From: NAKAMURA Gou Date: Fri, 29 Aug 2014 20:28:33 +0900 Subject: [PATCH 08/15] TODO: get_page()ed pages have to be put_page()ed The pages which get_page() has been called with should be recorded. Because these pages have to be passed to put_page() before they are freed. --- executer/kernel/syscall.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/executer/kernel/syscall.c b/executer/kernel/syscall.c index 0d6b1fd6..ddc03f57 100644 --- a/executer/kernel/syscall.c +++ b/executer/kernel/syscall.c @@ -411,6 +411,12 @@ static int rus_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) page = pfn_to_page(pfn+pix); if (!page_count(page)) { get_page(page); + /* + * TODO: + * The pages which get_page() has been called with + * should be recorded. Because these pages have to + * be passed to put_page() before they are freed. + */ } error = vm_insert_page(vma, rva+(pix*PAGE_SIZE), page); if (error) { From 7b825c0a65827e77033ccc2a6fbdc433fc0cbcda Mon Sep 17 00:00:00 2001 From: Tomoki Shirasawa Date: Wed, 3 Sep 2014 10:56:41 +0900 Subject: [PATCH 09/15] fix coredump (ltp abort01) --- arch/x86/kernel/syscall.c | 27 +++++++++++++++++++++++---- kernel/mem.c | 14 +++++++------- kernel/syscall.c | 4 ++-- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index 6a3b99ea..281620c6 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -189,6 +189,8 @@ do_setpgid(int pid, int pgid) } } +extern void coredump(struct process *proc, void *regs); + void do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pending *pending) { @@ -260,11 +262,26 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate); } else{ + int coredumped = 0; kfree(pending); ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate); - if(sig == SIGCHLD || sig == SIGURG) + switch(sig){ + case SIGCHLD: + case SIGURG: return; - terminate(0, sig, (ihk_mc_user_context_t *)regs->rsp); + case SIGQUIT: + case SIGILL: + case SIGTRAP: + case SIGABRT: + case SIGBUS: + case SIGFPE: + case SIGUSR1: + case SIGSEGV: + case SIGUSR2: + coredump(proc, regs); + coredumped = 0x80; + } + terminate(0, sig | coredumped, (ihk_mc_user_context_t *)regs->rsp); } } @@ -561,8 +578,10 @@ set_signal(int sig, void *regs0) return; if((__sigmask(sig) & proc->sigmask.__val[0]) || - (regs->rsp & 0x8000000000000000)) - terminate(0, sig, (ihk_mc_user_context_t *)regs->rsp); + (regs->rsp & 0x8000000000000000)){ + coredump(proc, regs0); + terminate(0, sig | 0x80, (ihk_mc_user_context_t *)regs->rsp); + } else do_kill(proc->pid, proc->tid, sig); } diff --git a/kernel/mem.c b/kernel/mem.c index a931cc6f..8db8f27c 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -180,7 +180,7 @@ void freecore(struct coretable **); * \param regs A pointer to a x86_regs structure. */ -static void coredump(struct process *proc, void *regs) +void coredump(struct process *proc, void *regs) { struct syscall_request request IHK_DMA_ALIGN; int ret; @@ -216,9 +216,9 @@ static void unhandled_page_fault(struct process *proc, void *fault_addr, void *r unsigned long error = ((struct x86_regs *)regs)->error; irqflags = kprintf_lock(); - __kprintf("[%d] Page fault for 0x%lX\n", + dkprintf("[%d] Page fault for 0x%lX\n", ihk_mc_get_processor_id(), address); - __kprintf("%s for %s access in %s mode (reserved bit %s set), " + dkprintf("%s for %s access in %s mode (reserved bit %s set), " "it %s an instruction fetch\n", (error & PF_PROT ? "protection fault" : "no page found"), (error & PF_WRITE ? "write" : "read"), @@ -230,14 +230,14 @@ static void unhandled_page_fault(struct process *proc, void *fault_addr, void *r list_for_each_entry(range, &vm->vm_range_list, list) { if (range->start <= address && range->end > address) { found = 1; - __kprintf("address is in range, flag: 0x%X! \n", + dkprintf("address is in range, flag: 0x%X! \n", range->flag); ihk_mc_pt_print_pte(vm->page_table, (void*)address); break; } } if (!found) { - __kprintf("address is out of range! \n"); + dkprintf("address is out of range! \n"); } kprintf_unlock(irqflags); @@ -246,8 +246,8 @@ static void unhandled_page_fault(struct process *proc, void *fault_addr, void *r ihk_mc_debug_show_interrupt_context(regs); - dkprintf("now dump a core file\n"); - coredump(proc, regs); + //dkprintf("now dump a core file\n"); + //coredump(proc, regs); #ifdef DEBUG_PRINT_MEM { diff --git a/kernel/syscall.c b/kernel/syscall.c index 41f33f78..5cdf9234 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -400,7 +400,7 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx) struct fork_tree_node *child, *next; request.number = __NR_exit_group; - request.args[0] = ((rc & 0x00ff) << 8) | (sig & 0x7f); + request.args[0] = ((rc & 0x00ff) << 8) | (sig & 0xff); #ifdef DCFA_KMOD do_mod_exit(rc); @@ -430,7 +430,7 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx) ihk_mc_spinlock_lock_noirq(&ftn->lock); ftn->pid = proc->pid; - ftn->exit_status = ((rc & 0x00ff) << 8) | (sig & 0x7f); + ftn->exit_status = ((rc & 0x00ff) << 8) | (sig & 0xff); ftn->status = PS_ZOMBIE; ihk_mc_spinlock_unlock_noirq(&ftn->lock); From 308987c1eef671a691620a2b08ddc0acb4e03a4f Mon Sep 17 00:00:00 2001 From: Tomoki Shirasawa Date: Wed, 3 Sep 2014 15:17:44 +0900 Subject: [PATCH 10/15] infrequent fail LTP pipe02 --- executer/kernel/control.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executer/kernel/control.c b/executer/kernel/control.c index e6c5fb92..80603ba5 100644 --- a/executer/kernel/control.c +++ b/executer/kernel/control.c @@ -284,7 +284,7 @@ static long mcexec_send_signal(ihk_os_t os, struct signal_desc *sigparam) isp.pid = sig.pid; isp.arg = (long)sig.tid << 32 | (sig.sig & 0x00000000ffffffffL); - mcctrl_ikc_send(os, 0, &isp); + mcctrl_ikc_send(os, sig.cpu, &isp); return 0; } From cd366de09728dff24a12b7846f4b29455df4bfa2 Mon Sep 17 00:00:00 2001 From: "Balazs Gerofi bgerofi@riken.jp" Date: Wed, 3 Sep 2014 18:15:43 +0900 Subject: [PATCH 11/15] execve(): - COKERNEL_PATH and COKERNEL_EXEC_ROOT support for co-kernels with different architecture than the host (i.e., Xeon Phi). - fix various error codes: ENAMETOOLONG, ENOENT, ENOTDIR, EACCES, ENOEXEC, EFAULT. - support for shell code execution. --- executer/include/uprotocol.h | 3 + executer/user/mcexec.c | 278 ++++++++++++++++++++++++----------- kernel/include/syscall.h | 3 + kernel/syscall.c | 9 +- lib/include/string.h | 2 +- lib/string.c | 21 ++- 6 files changed, 224 insertions(+), 92 deletions(-) diff --git a/executer/include/uprotocol.h b/executer/include/uprotocol.h index cb2e95c7..8f9ae88e 100644 --- a/executer/include/uprotocol.h +++ b/executer/include/uprotocol.h @@ -63,6 +63,8 @@ struct program_image_section { void *fp; }; +#define SHELL_PATH_MAX_LEN 1024 + struct program_load_desc { int num_sections; int status; @@ -88,6 +90,7 @@ struct program_load_desc { unsigned long rlimit_stack_cur; unsigned long rlimit_stack_max; unsigned long interp_align; + char shell_path[SHELL_PATH_MAX_LEN]; struct program_image_section sections[0]; }; diff --git a/executer/user/mcexec.c b/executer/user/mcexec.c index 2bcbd2e3..1721cc7b 100644 --- a/executer/user/mcexec.c +++ b/executer/user/mcexec.c @@ -338,14 +338,109 @@ struct program_load_desc *load_interp(struct program_load_desc *desc0, FILE *fp) unsigned char *dma_buf; -int load_elf_desc(char *filename, struct program_load_desc **desc_p) +int lookup_exec_path(char *filename, char *path, int max_len) +{ + int found = 0; + int error; + + /* Is file not absolute path? */ + if (strncmp(filename, "/", 1)) { + + /* Is filename a single component without path? */ + if (strncmp(filename, ".", 1) && !strchr(filename, '/')) { + + char *token, *string, *tofree; + char *PATH = getenv("COKERNEL_PATH"); + if (!PATH) { + PATH = getenv("PATH"); + } + + if (strlen(filename) >= 255) { + return ENAMETOOLONG; + } + + __dprintf("PATH: %s\n", PATH); + + /* strsep() modifies string! */ + tofree = string = strdup(PATH); + if (string == NULL) { + printf("lookup_exec_path(): copying PATH, not enough memory?\n"); + return ENOMEM; + } + + while ((token = strsep(&string, ":")) != NULL) { + + error = snprintf(path, max_len, + "%s/%s", token, filename); + if (error < 0 || error >= max_len) { + fprintf(stderr, "lookup_exec_path(): array too small?\n"); + continue; + } + + error = access(path, X_OK); + if (error == 0) { + found = 1; + break; + } + } + + free(tofree); + } + + /* Not in path, file to be open from the working directory */ + if (!found) { + error = snprintf(path, max_len, "%s", filename); + + if (error < 0 || error >= max_len) { + fprintf(stderr, "lookup_exec_path(): array too small?\n"); + return ENOMEM; + } + + found = 1; + } + } + /* Absolute path */ + else if (!strncmp(filename, "/", 1)) { + char *root = getenv("COKERNEL_EXEC_ROOT"); + + if (root) { + error = snprintf(path, max_len, "%s/%s", root, filename); + } + else { + error = snprintf(path, max_len, "%s", filename); + } + + if (error < 0 || error >= max_len) { + fprintf(stderr, "lookup_exec_path(): array too small?\n"); + return ENOMEM; + } + + found = 1; + } + + if (!found) { + fprintf(stderr, + "lookup_exec_path(): error finding file %s\n", filename); + return ENOENT; + } + + __dprintf("lookup_exec_path(): %s\n", path); + + return 0; +} + +int load_elf_desc(char *filename, struct program_load_desc **desc_p, + char **shell_p) { FILE *fp; FILE *interp = NULL; char *interp_path; + char *shell = NULL; + size_t shell_len = 0; struct program_load_desc *desc; int ret = 0; struct stat sb; + char header[1024]; if ((ret = access(filename, X_OK)) != 0) { fprintf(stderr, "Error: %s is not an executable?, errno: %d\n", @@ -369,6 +464,27 @@ int load_elf_desc(char *filename, struct program_load_desc **desc_p) return errno; } + if (fread(&header, 1, 2, fp) != 2) { + fprintf(stderr, "Error: Failed to read header from %s\n", filename); + return errno; + } + + if (!strncmp(header, "#!", 2)) { + + if (getline(&shell, &shell_len, fp) == -1) { + fprintf(stderr, "Error: reading shell path %s\n", filename); + } + + fclose(fp); + + /* Delete new line character */ + shell[strlen(shell) - 1] = 0; + *shell_p = shell; + return 0; + } + + rewind(fp); + desc = load_elf(fp, &interp_path); if (!desc) { fclose(fp); @@ -519,7 +635,7 @@ void print_flat(char *flat) * returns the total length of the flat string and updates flat to * point to the beginning. */ -int flatten_strings(int nr_strings, char **strings, char **flat) +int flatten_strings(int nr_strings, char *first, char **strings, char **flat) { int full_len, string_i; unsigned long flat_offset; @@ -532,6 +648,10 @@ int flatten_strings(int nr_strings, char **strings, char **flat) /* Count full length */ full_len = sizeof(int) + sizeof(char *); // Counter and terminating NULL + if (first) { + full_len += sizeof(char *) + strlen(first) + 1; + } + for (string_i = 0; string_i < nr_strings; ++string_i) { // Pointer + actual value full_len += sizeof(char *) + strlen(strings[string_i]) + 1; @@ -545,18 +665,25 @@ int flatten_strings(int nr_strings, char **strings, char **flat) memset(_flat, 0, full_len); /* Number of strings */ - *((int*)_flat) = nr_strings; + *((int*)_flat) = nr_strings + (first ? 1 : 0); // Actual offset - flat_offset = sizeof(int) + sizeof(char *) * (nr_strings + 1); + flat_offset = sizeof(int) + sizeof(char *) * (nr_strings + 1 + + (first ? 1 : 0)); + + if (first) { + *((char **)(_flat + sizeof(int))) = (void *)flat_offset; + memcpy(_flat + flat_offset, first, strlen(first) + 1); + flat_offset += strlen(first) + 1; + } for (string_i = 0; string_i < nr_strings; ++string_i) { /* Fabricate the string */ - *((char **)(_flat + sizeof(int) + string_i * sizeof(char *))) = (void *)flat_offset; + *((char **)(_flat + sizeof(int) + (string_i + (first ? 1 : 0)) + * sizeof(char *))) = (void *)flat_offset; memcpy(_flat + flat_offset, strings[string_i], strlen(strings[string_i]) + 1); flat_offset += strlen(strings[string_i]) + 1; - } *flat = _flat; @@ -756,6 +883,9 @@ int main(int argc, char **argv) int target_core = 0; int mcosid = 0; int opt; + char path[1024]; + char *shell = NULL; + char shell_path[1024]; #ifdef USE_SYSCALL_MOD_CALL __glob_argc = argc; @@ -768,7 +898,7 @@ int main(int argc, char **argv) } /* Collect environment variables */ - envs_len = flatten_strings(-1, environ, &envs); + envs_len = flatten_strings(-1, NULL, environ, &envs); envs = envs; error = getrlimit(RLIMIT_STACK, &rlim_stack); @@ -820,18 +950,40 @@ int main(int argc, char **argv) for (i = optind; i < argc; ++i) { __dprintf("%s ", argv[i]); } - __dprintf("\n"); + __dprintf("%s", "\n"); - if (load_elf_desc(argv[optind], &desc) != 0) { + if (lookup_exec_path(argv[optind], path, sizeof(path)) != 0) { + fprintf(stderr, "error: finding file: %s\n", argv[optind]); + return 1; + } + + if (load_elf_desc(path, &desc, &shell) != 0) { fprintf(stderr, "error: loading file: %s\n", argv[optind]); return 1; } + + /* Check whether shell script */ + if (shell) { + if (lookup_exec_path(shell, shell_path, sizeof(shell_path)) != 0) { + fprintf(stderr, "error: finding file: %s\n", shell); + return 1; + } + + if (load_elf_desc(shell_path, &desc, &shell) != 0) { + fprintf(stderr, "error: loading file: %s\n", shell); + return 1; + } + } + + if (shell) { + argv[optind] = path; + } desc->envs_len = envs_len; desc->envs = envs; //print_flat(envs); - desc->args_len = flatten_strings(-1, argv + optind, &args); + desc->args_len = flatten_strings(-1, shell, argv + optind, &args); desc->args = args; //print_flat(args); @@ -1269,93 +1421,51 @@ int main_loop(int fd, int cpu, pthread_mutex_t *lock) switch (w.sr.args[0]) { struct program_load_desc *desc; struct remote_transfer trans; - int error; - int found; - char path[2048]; + char path[1024]; char *filename; int ret; + char *shell = NULL; + char shell_path[1024]; /* Load descriptor phase */ case 1: - ret = -1; - found = 0; filename = (char *)w.sr.args[1]; - - /* Is filename a single component without path? */ - if (strncmp(filename, "/", 1) - && !strchr(filename, '/')) { - - char *token, *string, *tofree; - char *PATH = getenv("COKERNEL_PATH"); - if (!PATH) { - PATH = getenv("PATH"); - } - - if (strlen(filename) >= 255) { - ret = ENAMETOOLONG; - goto return_execve1; - } - - __dprintf("PATH: %s\n", PATH); - - /* strsep() modifies string! */ - tofree = string = strdup(PATH); - if (string == NULL) { - printf("error: copying PATH, not enough memory?\n"); - goto return_execve1; - } - - while ((token = strsep(&string, ":")) != NULL) { - - error = snprintf(path, sizeof(path), - "%s/%s", token, filename); - if (error < 0 || error >= sizeof(path)) { - fprintf(stderr, "execve(): array too small?\n"); - continue; - } - - error = access(path, X_OK); - if (error == 0) { - found = 1; - break; - } - } - - free(tofree); - } - else { - char *root = getenv("COKERNEL_EXEC_ROOT"); - - if (root) { - error = snprintf(path, sizeof(path), "%s/%s", root, filename); - } - else { - error = snprintf(path, sizeof(path), "%s", filename); - } - - if (error < 0 || error >= sizeof(path)) { - fprintf(stderr, "execve(): array too small?\n"); - goto return_execve1; - } - - found = 1; - } - if (!found) { - fprintf(stderr, - "execve(): error finding file %s\n", filename); - ret = ENOENT; + if ((ret = lookup_exec_path(filename, path, sizeof(path))) + != 0) { goto return_execve1; } - __dprintf("execve(): path to binary: %s\n", path); - - if ((ret = load_elf_desc(path, &desc)) != 0) { + if ((ret = load_elf_desc(path, &desc, &shell)) != 0) { fprintf(stderr, "execve(): error loading ELF for file %s\n", path); goto return_execve1; } + + /* Check whether shell script */ + if (shell) { + if ((ret = lookup_exec_path(shell, shell_path, + sizeof(shell_path))) != 0) { + fprintf(stderr, "execve(): error: finding file: %s\n", shell); + goto return_execve1; + } + + if ((ret = load_elf_desc(shell_path, &desc, &shell)) + != 0) { + fprintf(stderr, "execve(): error: loading file: %s\n", shell); + goto return_execve1; + } + + if (strlen(shell_path) >= SHELL_PATH_MAX_LEN) { + fprintf(stderr, "execve(): error: shell path too long: %s\n", shell_path); + ret = ENAMETOOLONG; + goto return_execve1; + } + + /* Let the LWK know the shell interpreter */ + strcpy(desc->shell_path, shell_path); + } __dprintf("execve(): load_elf_desc() for %s OK, num sections: %d\n", path, desc->num_sections); @@ -1410,10 +1520,10 @@ return_execve1: goto return_execve1; } - __dprintf("execve(): transfer ELF desc OK\n"); + __dprintf("%s", "execve(): transfer ELF desc OK\n"); transfer_image(fd, desc); - __dprintf("execve(): image transferred\n"); + __dprintf("%s", "execve(): image transferred\n"); ret = 0; return_execve2: diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h index d04d9a90..e2d8dab9 100644 --- a/kernel/include/syscall.h +++ b/kernel/include/syscall.h @@ -103,6 +103,8 @@ struct program_image_section { void *fp; }; +#define SHELL_PATH_MAX_LEN 1024 + struct program_load_desc { int num_sections; int status; @@ -128,6 +130,7 @@ struct program_load_desc { unsigned long rlimit_stack_cur; unsigned long rlimit_stack_max; unsigned long interp_align; + char shell_path[SHELL_PATH_MAX_LEN]; struct program_image_section sections[0]; }; diff --git a/kernel/syscall.c b/kernel/syscall.c index 5cdf9234..b34277ce 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -1245,15 +1245,20 @@ SYSCALL_DECLARE(execve) dkprintf("execve(): ELF desc received, num sections: %d\n", desc->num_sections); + + if (desc->shell_path[0]) { + dkprintf("execve(): shell interpreter: %s\n", desc->shell_path); + } /* Flatten argv and envp into kernel-space buffers */ - argv_flat_len = flatten_strings(-1, argv, &argv_flat); + argv_flat_len = flatten_strings(-1, (desc->shell_path[0] ? + desc->shell_path : NULL), argv, &argv_flat); if (argv_flat_len == 0) { kprintf("ERROR: no argv for executable: %s?\n", filename); return -EINVAL; } - envp_flat_len = flatten_strings(-1, envp, &envp_flat); + envp_flat_len = flatten_strings(-1, NULL, envp, &envp_flat); if (envp_flat_len == 0) { kprintf("ERROR: no envp for executable: %s?\n", filename); return -EINVAL; diff --git a/lib/include/string.h b/lib/include/string.h index e34afe58..3c9c8e99 100644 --- a/lib/include/string.h +++ b/lib/include/string.h @@ -28,6 +28,6 @@ int memcmp(const void *s1, const void *s2, size_t n); void *memset(void *s, int n, size_t l); unsigned long strtol(const char *cp, char **endp, unsigned int base); -int flatten_strings(int nr_strings, char **strings, char **flat); +int flatten_strings(int nr_strings, char *first, char **strings, char **flat); #endif diff --git a/lib/string.c b/lib/string.c index 41f58a40..3af7d372 100644 --- a/lib/string.c +++ b/lib/string.c @@ -181,7 +181,7 @@ int memcmp(const void *s1, const void *s2, size_t n) * returns the total length of the flat string and updates flat to * point to the beginning. */ -int flatten_strings(int nr_strings, char **strings, char **flat) +int flatten_strings(int nr_strings, char *first, char **strings, char **flat) { int full_len, string_i; unsigned long flat_offset; @@ -194,6 +194,10 @@ int flatten_strings(int nr_strings, char **strings, char **flat) /* Count full length */ full_len = sizeof(int) + sizeof(char *); // Counter and terminating NULL + if (first) { + full_len += sizeof(char *) + strlen(first) + 1; + } + for (string_i = 0; string_i < nr_strings; ++string_i) { // Pointer + actual value full_len += sizeof(char *) + strlen(strings[string_i]) + 1; @@ -207,18 +211,25 @@ int flatten_strings(int nr_strings, char **strings, char **flat) memset(_flat, 0, full_len); /* Number of strings */ - *((int*)_flat) = nr_strings; + *((int*)_flat) = nr_strings + (first ? 1 : 0); // Actual offset - flat_offset = sizeof(int) + sizeof(char *) * (nr_strings + 1); + flat_offset = sizeof(int) + sizeof(char *) * (nr_strings + 1 + + (first ? 1 : 0)); + + if (first) { + *((char **)(_flat + sizeof(int))) = (void *)flat_offset; + memcpy(_flat + flat_offset, first, strlen(first) + 1); + flat_offset += strlen(first) + 1; + } for (string_i = 0; string_i < nr_strings; ++string_i) { /* Fabricate the string */ - *((char **)(_flat + sizeof(int) + string_i * sizeof(char *))) = (void *)flat_offset; + *((char **)(_flat + sizeof(int) + (string_i + (first ? 1 : 0)) + * sizeof(char *))) = (void *)flat_offset; memcpy(_flat + flat_offset, strings[string_i], strlen(strings[string_i]) + 1); flat_offset += strlen(strings[string_i]) + 1; - } *flat = _flat; From 7da4b8b8dc6fc219af5abad1cd4bf0f91c3eb9b3 Mon Sep 17 00:00:00 2001 From: Tomoki Shirasawa Date: Wed, 3 Sep 2014 18:22:27 +0900 Subject: [PATCH 12/15] fix sched_[sg]etaffinity(tid==0, ...) (LTP sched_getaffinity01) --- kernel/syscall.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/kernel/syscall.c b/kernel/syscall.c index 5cdf9234..29b0a5d5 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -2009,6 +2009,7 @@ SYSCALL_DECLARE(sched_setaffinity) struct process *thread; int cpu_id; unsigned long irqstate; + extern int num_processors; if (sizeof(k_cpu_set) > len) { kprintf("%s:%d\n Too small buffer.", __FILE__, __LINE__); @@ -2023,11 +2024,13 @@ SYSCALL_DECLARE(sched_setaffinity) // XXX: We should build something like cpu_available_mask in advance CPU_ZERO(&cpu_set); - extern int num_processors; for (cpu_id = 0; cpu_id < num_processors; cpu_id++) if (CPU_ISSET(cpu_id, &k_cpu_set)) CPU_SET(cpu_id, &cpu_set); + if(tid == 0) + tid = cpu_local_var(current)->tid; + for (cpu_id = 0; cpu_id < num_processors; cpu_id++) { irqstate = ihk_mc_spinlock_lock(&get_cpu_local_var(cpu_id)->runq_lock); list_for_each_entry(thread, &get_cpu_local_var(cpu_id)->runq, sched_list) @@ -2064,6 +2067,7 @@ SYSCALL_DECLARE(sched_getaffinity) int found = 0; int i; unsigned long irqstate; + extern int num_processors; if (sizeof(k_cpu_set) > len) { kprintf("%s:%d Too small buffer.\n", __FILE__, __LINE__); @@ -2071,7 +2075,9 @@ SYSCALL_DECLARE(sched_getaffinity) } len = MIN2(len, sizeof(k_cpu_set)); - extern int num_processors; + if(tid == 0) + tid = cpu_local_var(current)->tid; + for (i = 0; i < num_processors && !found; i++) { struct process *thread; irqstate = ihk_mc_spinlock_lock(&get_cpu_local_var(i)->runq_lock); From a16c3170ef1248b388d4e41467ca004e3ab80e4d Mon Sep 17 00:00:00 2001 From: Masamichi Takagi Date: Thu, 4 Sep 2014 17:07:27 +0900 Subject: [PATCH 13/15] Correct wait4 when the child is not found Make wait4 return -ECHILD when pid is specified and it's not found. --- kernel/syscall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/syscall.c b/kernel/syscall.c index f8a910be..b61c74a4 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -333,7 +333,7 @@ rescan: ihk_mc_spinlock_unlock_noirq(&child_iter->lock); } - if (empty) { + if (empty || (!child && pid != -1)) { ihk_mc_spinlock_unlock_noirq(&proc->ftn->lock); return -ECHILD; } From e45632c9f8bbd8980c53503a767a68766489cba0 Mon Sep 17 00:00:00 2001 From: Masamichi Takagi Date: Thu, 4 Sep 2014 17:28:14 +0900 Subject: [PATCH 14/15] Check "options" argument in wait4 Make wait4 return -EINVAL when not supported options are requested. --- kernel/syscall.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/syscall.c b/kernel/syscall.c index b61c74a4..77cecc81 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -311,6 +311,9 @@ SYSCALL_DECLARE(wait4) struct waitq_entry waitpid_wqe; int empty = 1; + if (options & ~(WNOHANG | WUNTRACED | WCONTINUED)) { + return -EINVAL; + } rescan: child = NULL; pid = (int)ihk_mc_syscall_arg0(ctx); From 15c9ae4c8d746289ead519a30986932ea8bf0d58 Mon Sep 17 00:00:00 2001 From: "Balazs Gerofi bgerofi@riken.jp" Date: Thu, 4 Sep 2014 18:11:41 +0900 Subject: [PATCH 15/15] execve(): lookup_exec_path() support for symlinks based on COKERNEL_EXEC_ROOT --- executer/user/mcexec.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/executer/user/mcexec.c b/executer/user/mcexec.c index 1721cc7b..a044b264 100644 --- a/executer/user/mcexec.c +++ b/executer/user/mcexec.c @@ -340,8 +340,13 @@ unsigned char *dma_buf; int lookup_exec_path(char *filename, char *path, int max_len) { - int found = 0; + int found; int error; + struct stat sb; + char *link_path = NULL; + +retry: + found = 0; /* Is file not absolute path? */ if (strncmp(filename, "/", 1)) { @@ -418,6 +423,36 @@ int lookup_exec_path(char *filename, char *path, int max_len) found = 1; } + if (link_path) { + free(link_path); + link_path = NULL; + } + + /* Check whether the resolved path is a symlink */ + if (lstat(path, &sb) == -1) { + fprintf(stderr, "lookup_exec_path(): error stat\n"); + return errno; + } + + if ((sb.st_mode & S_IFMT) == S_IFLNK) { + char *link_path = malloc(max_len); + if (!link_path) { + fprintf(stderr, "lookup_exec_path(): error allocating\n"); + return ENOMEM; + } + + error = readlink(path, link_path, max_len); + if (error == -1 || error == max_len) { + fprintf(stderr, "lookup_exec_path(): error readlink\n"); + return EINVAL; + } + + __dprintf("lookup_exec_path(): %s is link -> %s\n", path, link_path); + + filename = link_path; + goto retry; + } + if (!found) { fprintf(stderr, "lookup_exec_path(): error finding file %s\n", filename);