diff --git a/arch/amd64/binfmt_elf.c b/arch/amd64/binfmt_elf.c index e83cdb5..8fe9893 100644 --- a/arch/amd64/binfmt_elf.c +++ b/arch/amd64/binfmt_elf.c @@ -104,6 +104,39 @@ int binfmt_is_elf(const char *ident, size_t len) { return !strncmp(ident, "\x7F""ELF", 4); } +int elf_is_dynamic(struct vfs_ioctx *ioctx, struct ofile *fd, int *is_dynamic) { + Elf64_Ehdr ehdr; + Elf64_Phdr phdr; + int res; + + *is_dynamic = 0; + + if ((res = elf_read(ioctx, fd, 0, &ehdr, sizeof(Elf64_Ehdr))) != 0) { + return res; + } + + if (ehdr.e_ident[EI_CLASS] != ELFCLASS64) { + return -ENOEXEC; + } + + for (size_t i = 0; i < ehdr.e_phnum; ++i) { + if ((res = elf_read(ioctx, + fd, + ehdr.e_phoff + i * ehdr.e_phentsize, + &phdr, + ehdr.e_phentsize)) != 0) { + return res; + } + + if (phdr.p_type == PT_DYNAMIC) { + *is_dynamic = 1; + break; + } + } + + return 0; +} + int elf_load(struct process *proc, struct vfs_ioctx *ctx, struct ofile *fd, uintptr_t *entry) { int res; ssize_t bread; diff --git a/include/sys/binfmt_elf.h b/include/sys/binfmt_elf.h index 45c9aea..d4df4b2 100644 --- a/include/sys/binfmt_elf.h +++ b/include/sys/binfmt_elf.h @@ -6,3 +6,4 @@ struct ofile; int elf_load(struct process *proc, struct vfs_ioctx *ctx, struct ofile *fd, uintptr_t *entry); int binfmt_is_elf(const char *guess, size_t len); +int elf_is_dynamic(struct vfs_ioctx *ioctx, struct ofile *fd, int *is_dynamic); diff --git a/sys/execve.c b/sys/execve.c index 76b109e..0ea8138 100644 --- a/sys/execve.c +++ b/sys/execve.c @@ -171,12 +171,32 @@ int sys_execve(const char *path, const char **argv, const char **envp) { } argv_new[argc] = NULL; - for (int i = 0; i < argc; ++i) { - kdebug("[%d]: %s\n", i, argv_new[i]); - } - return sys_execve(shebang + 2, argv_new, envp); } + } else { + int is_dynamic = 0; + if ((res = elf_is_dynamic(&proc->ioctx, &fd, &is_dynamic)) != 0) { + kerror("%s: %s\n", path, kstrerror(res)); + vfs_close(&proc->ioctx, &fd); + return -EINVAL; + } + + if (is_dynamic) { + vfs_close(&proc->ioctx, &fd); + + int argc; + for (argc = 0; argv[argc]; ++argc); + + const char *argv_new[argc + 3]; + argv_new[0] = "/lib/ld"; + argv_new[1] = path; + for (int i = 0; i < argc; ++i) { + argv_new[i + 2] = argv[i]; + } + argv_new[argc + 2] = NULL; + + return sys_execve(argv_new[0], argv_new, envp); + } } const char *e = strrchr(path, '/');