From patchwork Sun Jan 27 02:03:21 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Laurent Vivier X-Patchwork-Id: 215941 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 9BEFB2C008C for ; Sun, 27 Jan 2013 13:03:51 +1100 (EST) Received: from localhost ([::1]:35183 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TzHb0-0002qZ-Kx for incoming@patchwork.ozlabs.org; Sat, 26 Jan 2013 21:03:46 -0500 Received: from eggs.gnu.org ([208.118.235.92]:47201) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TzHaq-0002qR-1U for qemu-devel@nongnu.org; Sat, 26 Jan 2013 21:03:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1TzHan-0000cg-7d for qemu-devel@nongnu.org; Sat, 26 Jan 2013 21:03:35 -0500 Received: from smtp6-g21.free.fr ([2a01:e0c:1:1599::15]:47215) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1TzHam-0000cC-Ka for qemu-devel@nongnu.org; Sat, 26 Jan 2013 21:03:33 -0500 Received: from localhost.localdomain (unknown [78.238.229.36]) by smtp6-g21.free.fr (Postfix) with ESMTP id 661EF82253; Sun, 27 Jan 2013 03:03:25 +0100 (CET) From: Laurent Vivier To: qemu-devel@nongnu.org Date: Sun, 27 Jan 2013 03:03:21 +0100 Message-Id: <1359252201-8647-1-git-send-email-laurent@vivier.eu> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1356037019-19426-1-git-send-email-laurent@vivier.eu> References: <1356037019-19426-1-git-send-email-laurent@vivier.eu> X-detected-operating-system: by eggs.gnu.org: Error: Malformed IPv6 address (bad octet value). X-Received-From: 2a01:e0c:1:1599::15 Cc: Peter Maydell , Riku Voipio , Laurent Vivier Subject: [Qemu-devel] [PATCH] linux-user: add support of binfmt_misc 'O' flag X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org The binfmt_misc module can calculate the credentials and security token according to the binary instead of to the interpreter if the 'C' flag is enabled. To be able to execute non-readable binaries, this flag implies 'O' flag. When 'O' flag is enabled, bintfmt_misc opens the file for reading and pass the file descriptor to the interpreter. References: linux/Documentation/binfmt_misc.txt ['O' and 'C' description] linux/fs/binfmt_misc.c linux/fs/binfmt_elf.c [ AT_EXECFD usage ] Signed-off-by: Laurent Vivier --- linux-user/linuxload.c | 8 ++------ linux-user/main.c | 32 +++++++++++++++++++++++++++++++- linux-user/qemu.h | 2 +- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c index 381ab89..2c3ec58 100644 --- a/linux-user/linuxload.c +++ b/linux-user/linuxload.c @@ -130,7 +130,7 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, return sp; } -int loader_exec(const char * filename, char ** argv, char ** envp, +int loader_exec(int fdexec, const char *filename, char **argv, char **envp, struct target_pt_regs * regs, struct image_info *infop, struct linux_binprm *bprm) { @@ -139,11 +139,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp, bprm->p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int); memset(bprm->page, 0, sizeof(bprm->page)); - retval = open(filename, O_RDONLY); - if (retval < 0) { - return -errno; - } - bprm->fd = retval; + bprm->fd = fdexec; bprm->filename = (char *)filename; bprm->argc = count(argv); bprm->argv = argv; diff --git a/linux-user/main.c b/linux-user/main.c index fcbeaca..e2ed210 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -3385,6 +3385,26 @@ static int parse_args(int argc, char **argv) return optind; } +static int get_execfd(char **envp) +{ + typedef struct { + long a_type; + long a_val; + } auxv_t; + auxv_t *auxv; + + while (*envp++ != NULL) { + ; + } + + for (auxv = (auxv_t *)envp; auxv->a_type != AT_NULL; auxv++) { + if (auxv->a_type == AT_EXECFD) { + return auxv->a_val; + } + } + return -1; +} + int main(int argc, char **argv, char **envp) { const char *log_file = DEBUG_LOGFILE; @@ -3399,6 +3419,7 @@ int main(int argc, char **argv, char **envp) int target_argc; int i; int ret; + int execfd; module_call_init(MODULE_INIT_QOM); @@ -3543,7 +3564,16 @@ int main(int argc, char **argv, char **envp) env->opaque = ts; task_settid(ts); - ret = loader_exec(filename, target_argv, target_environ, regs, + execfd = get_execfd(envp); + if (execfd < 0) { + execfd = open(filename, O_RDONLY); + } + if (execfd < 0) { + printf("Error while loading %s: %s\n", filename, strerror(-execfd)); + _exit(1); + } + + ret = loader_exec(execfd, filename, target_argv, target_environ, regs, info, &bprm); if (ret != 0) { printf("Error while loading %s: %s\n", filename, strerror(-ret)); diff --git a/linux-user/qemu.h b/linux-user/qemu.h index eb5ca6d..981ef2c 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -179,7 +179,7 @@ struct linux_binprm { void do_init_thread(struct target_pt_regs *regs, struct image_info *infop); abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, abi_ulong stringp, int push_ptr); -int loader_exec(const char * filename, char ** argv, char ** envp, +int loader_exec(int fdexec, const char *filename, char **argv, char **envp, struct target_pt_regs * regs, struct image_info *infop, struct linux_binprm *);