From patchwork Thu May 31 22:49:06 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 923659 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="b6KsWPso"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40xjMr61z3z9s4Y for ; Fri, 1 Jun 2018 08:50:00 +1000 (AEST) Received: from localhost ([::1]:46493 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fOWOM-000584-EP for incoming@patchwork.ozlabs.org; Thu, 31 May 2018 18:49:58 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38488) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fOWNi-00056J-EY for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fOWNg-0000k1-9P for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:18 -0400 Received: from mail-pg0-x22a.google.com ([2607:f8b0:400e:c05::22a]:38598) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fOWNg-0000jV-3I for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:16 -0400 Received: by mail-pg0-x22a.google.com with SMTP id c9-v6so7528196pgf.5 for ; Thu, 31 May 2018 15:49:15 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=dc9nmEC4EhhoiijrUSkV24PteoW8Hb15c4lSKrNTdhc=; b=b6KsWPsowirLWGQeC0h95k+bgZWIOQEvTdR8u+xI0abJeRV/CfMZ+Ld1NHMqfvNBAE WFvnsKO6pl3dnH5EffsboswTLoUPMBFGSU4TUZaGg1senGtg4W86DluiSCHgMdiPbxxB N7AVODxaUGxalSjlm1/l5B5hiPdxkAojB3mHc= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=dc9nmEC4EhhoiijrUSkV24PteoW8Hb15c4lSKrNTdhc=; b=AHAaZpE6NRo0TUSDCMKqNodNaTW/9xv2JT1iBZMvS7njHXBph5VUqUDkhlepInnrr7 V7lKbcC8EsyebDS+JxV1xMIzFZV4oPUOj1CT+QYMZAcf5PCUIy6qnHKv5kGIsJz8MTcy A1viHgycLUBXQNaie4gewRdfODSPMjOwV4HOymIQJ2eoMg2E17nSP8TWEM5hF326kseO onNYwKE/T+WYfqhPBgx4LFS72JOE0l6PUSGaux0lKlbHD/dz5kSYorit+W9gBwUyoKkm 8x3ZHrD05OghWHbAGe5lhinxA3cP9EBR/YBPshEZjfezXWuYlcU/qmQ5/vt1kAl4W9eK NCJQ== X-Gm-Message-State: ALKqPweIUiQ1Ym3qV8SSb+q5kewjAsh9wPYzufPR+P+9N7H5zWZGLpWT mTGiFqy8o1v2G1eTjahctmOmZGHvKb4= X-Google-Smtp-Source: ADUXVKIHDCaljDxn1jLi2jBzWKKVYHrgXnWWp8ljTRKsPgtwiUtcjmeC8mnBURjnDE8WTIO42+NjZg== X-Received: by 2002:a62:ed12:: with SMTP id u18-v6mr8488604pfh.127.1527806954743; Thu, 31 May 2018 15:49:14 -0700 (PDT) Received: from cloudburst.twiddle.net (97-126-112-211.tukw.qwest.net. [97.126.112.211]) by smtp.gmail.com with ESMTPSA id t3-v6sm33385584pgs.91.2018.05.31.15.49.13 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 31 May 2018 15:49:13 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 31 May 2018 15:49:06 -0700 Message-Id: <20180531224911.23725-2-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180531224911.23725-1-richard.henderson@linaro.org> References: <20180531224911.23725-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::22a Subject: [Qemu-devel] [PATCH 1/6] gdbstub: Return the fd from gdbserver_start X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, laurent@vivier.eu, evgreen@chromium.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This will allow us to protect gdbserver_fd from the guest. Signed-off-by: Richard Henderson Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Laurent Vivier --- gdbstub.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gdbstub.c b/gdbstub.c index 6081e719c5..057d0d65c5 100644 --- a/gdbstub.c +++ b/gdbstub.c @@ -1890,15 +1890,16 @@ static int gdbserver_open(int port) int gdbserver_start(int port) { gdbserver_fd = gdbserver_open(port); - if (gdbserver_fd < 0) + if (gdbserver_fd < 0) { return -1; + } /* accept connections */ if (!gdb_accept()) { close(gdbserver_fd); gdbserver_fd = -1; return -1; } - return 0; + return gdbserver_fd; } /* Disable gdb stub for child processes. */ From patchwork Thu May 31 22:49:07 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 923658 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="IHPHY/Pn"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40xjMq357Pz9s1B for ; Fri, 1 Jun 2018 08:49:59 +1000 (AEST) Received: from localhost ([::1]:46494 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fOWOK-000587-5s for incoming@patchwork.ozlabs.org; Thu, 31 May 2018 18:49:56 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38492) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fOWNi-00056K-O0 for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:19 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fOWNh-0000lA-O2 for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:18 -0400 Received: from mail-pf0-x243.google.com ([2607:f8b0:400e:c00::243]:37862) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fOWNh-0000ke-Hp for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:17 -0400 Received: by mail-pf0-x243.google.com with SMTP id e9-v6so11490070pfi.4 for ; Thu, 31 May 2018 15:49:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=4kx9iWqrZaAigsaP3mi/Tl0rT4kzKW4FmGtRPBRUajU=; b=IHPHY/PnNxiLGBmD/SOzbwnkkztdegq25rSlB7OPUunzCK6SbcTfqBBM66R4+/3pdY q2202u4GyvLsds4bLhwObFfgA0cHNBP8/xPjjp5fA+MsIfY6UlJfMhMHQqUSeDDaIN2b XkK/t3gK72wOX8Q72u3+o7CQoKNmBhZPvVPrk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=4kx9iWqrZaAigsaP3mi/Tl0rT4kzKW4FmGtRPBRUajU=; b=nui0YBdu4vQKIfJ4EYvRMqAV3S1DBIKEntiW9RRjzYoBGKTZG/SAZBmmDHhFCNfCUf jR4n/D9AW50yiFhg9MVRLJYyHKwTDS3m/rRmQARLYo9f3+t396Rf4ZdmaptyhpflYCy3 4eQC2Vi+qMTY6fHUHo7Acrecc14pGSfAYSn1yEsp7OwnTw56X1A5JFnKYuoZ1UXfz5Yj AhUnv0uJ7J3MAU49dHeGH+jE7FoaDyCOFSOLxPjABTfy7cP8lpEktCiCv5NQ+CNaJM+R t+Xn04VJ/01KOCwte3aes2SHrB+vFqNkOXRK6VPGQbfTlHPCtsWmo37AyIUEiJ7a8H9H Jnog== X-Gm-Message-State: ALKqPwfqq35wazyVInARj3bei/QR4W6GuwCLOTEvjLDRvNkkKUArVwpO zsXdIDm1ouMY0N882hhEgsPvWy4kM5c= X-Google-Smtp-Source: ADUXVKLC67cbojy9eXH/cRd5t/t+H7Uct5AFMTsE2WbFg5XvsIySNGJ/3AA6ClGwbm75AzB2Xzgthw== X-Received: by 2002:a62:1411:: with SMTP id 17-v6mr8512872pfu.3.1527806956101; Thu, 31 May 2018 15:49:16 -0700 (PDT) Received: from cloudburst.twiddle.net (97-126-112-211.tukw.qwest.net. [97.126.112.211]) by smtp.gmail.com with ESMTPSA id t3-v6sm33385584pgs.91.2018.05.31.15.49.14 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 31 May 2018 15:49:15 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 31 May 2018 15:49:07 -0700 Message-Id: <20180531224911.23725-3-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180531224911.23725-1-richard.henderson@linaro.org> References: <20180531224911.23725-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::243 Subject: [Qemu-devel] [PATCH 2/6] linux-user: Add host_fds and manipulators X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, laurent@vivier.eu, evgreen@chromium.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This allows emulation of guest syscalls to reject manipulations to fds used by the host. Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier --- linux-user/qemu.h | 30 ++++++++++++++++++++++++++++++ linux-user/main.c | 27 ++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index c55c8e294b..33dafbe0e4 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -155,6 +155,36 @@ void task_settid(TaskState *); void stop_all_tasks(void); extern const char *qemu_uname_release; extern unsigned long mmap_min_addr; +extern fd_set host_fds; + +/** + * is_hostfd: + * @fd: file descriptor to check + * + * Return true if @fd is being used by the host and therefore any + * guest system call referencing @fd should return EBADF. + */ +static inline bool is_hostfd(int fd) +{ + return fd >= 0 && fd < FD_SETSIZE && FD_ISSET(fd, &host_fds); +} + +/** + * contains_hostfd: + * @fds: fd_set of descriptors to check + * + * Return true if any descriptor in @fds are being used by the host + * and therefore the guest system call should return EBADF. + */ +bool contains_hostfd(const fd_set *fds); + +/** + * add_hostfd: + * @fd: file descriptor to reserve + * + * Add @fd to the set of file descriptors to reserve for the host. + */ +void add_hostfd(int fd); /* ??? See if we can avoid exposing so much of the loader internals. */ diff --git a/linux-user/main.c b/linux-user/main.c index 78d6d3e7eb..ee3f323c08 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -49,6 +49,7 @@ static const char *cpu_type; unsigned long mmap_min_addr; unsigned long guest_base; int have_guest_base; +fd_set host_fds; /* * When running 32-on-64 we should make sure we can fit all of the possible @@ -112,6 +113,23 @@ int cpu_get_pic_interrupt(CPUX86State *env) } #endif +bool contains_hostfd(const fd_set *fds) +{ + int i; + for (i = 0; i < ARRAY_SIZE(__FDS_BITS(fds)); ++i) { + if (__FDS_BITS(fds)[i] & __FDS_BITS(&host_fds)[i]) { + return true; + } + } + return true; +} + +void add_hostfd(int fd) +{ + g_assert(fd >= 0 && fd < FD_SETSIZE); + FD_SET(fd, &host_fds); +} + /***********************************************************/ /* Helper routines for implementing atomic operations. */ @@ -805,12 +823,19 @@ int main(int argc, char **argv, char **envp) target_cpu_copy_regs(env, regs); + /* Prevent the guest from closing the log file. */ + if (qemu_logfile && qemu_logfile != stderr) { + add_hostfd(fileno(qemu_logfile)); + } + if (gdbstub_port) { - if (gdbserver_start(gdbstub_port) < 0) { + int fd = gdbserver_start(gdbstub_port); + if (fd < 0) { fprintf(stderr, "qemu: could not open gdbserver on port %d\n", gdbstub_port); exit(EXIT_FAILURE); } + add_hostfd(fd); gdb_handlesig(cpu, 0); } cpu_loop(env); From patchwork Thu May 31 22:49:08 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 923665 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="j3xhvY59"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40xjV06njFz9s4Y for ; Fri, 1 Jun 2018 08:55:20 +1000 (AEST) Received: from localhost ([::1]:46526 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fOWTV-0001LS-PQ for incoming@patchwork.ozlabs.org; Thu, 31 May 2018 18:55:17 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38519) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fOWNm-00059y-Kz for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:25 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fOWNj-0000nN-Ml for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:22 -0400 Received: from mail-pf0-x243.google.com ([2607:f8b0:400e:c00::243]:35356) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fOWNj-0000mY-BU for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:19 -0400 Received: by mail-pf0-x243.google.com with SMTP id x9-v6so11494872pfm.2 for ; Thu, 31 May 2018 15:49:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=gmDyDf7PgQJa87IpvETmA8ipIStbcbJNh9qw/rzUD1s=; b=j3xhvY59XR9eALmO+eWoeFbq0DTBBO/R9cNIa55JBnfndx+7oY6/GW/P6v1MSLvcYG odS4KVgMDOyO/3U98hAmlgYgMMZ2IQiBkU9yignjsQYLvyJhoLh9IT198iFfqh5roeQ3 PcvxoHNLwsXPVyMrkpOxSD+cxYTzasnl4kF08= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=gmDyDf7PgQJa87IpvETmA8ipIStbcbJNh9qw/rzUD1s=; b=n7hrSeO+O/TKWtY3463nZSbsDxW4UYVzXkH9m7eRuHsNibyqo5mWnNg5uFX4gj0VuJ 6O0S/ny2i7L//2Orjoc8cKYlqg9anUxymN+aya9jOxlDipga4m4IAfU/FGkA+p9yyHPT ahh2aznCcC2Ec0aaPUsbnHOT3lSKBn0Jsq5MtFXUgizjQLuKEBI6hNtLIEw0ps5qSvfs krJNyS5Gfe98STXWJjoKbfuRVHRKzdgQDIcvr6ALgAMtBctoBadE+g4/sQKYeUZjApfD EWS8hKNBp/94rq1Fcp6ION3s4ViMbAqF/+mY8ZURgVrUEXNyzVUcSQw4S88/DpwGRRzm lCGA== X-Gm-Message-State: ALKqPwfSESppAXYbXXNX7Vc78M2GEATjC1CkvYHzKJ8NEHsfq9MHRVuT kR2ZrOPZs14pUYz1LSRuUR9Legd4ink= X-Google-Smtp-Source: ADUXVKIiJRQDxl75hda1CrxfmUebfDC3f/0qEQH0QR/972+YQYf66UOb/QFOgybniNfYC4FH6VXLew== X-Received: by 2002:a62:cd45:: with SMTP id o66-v6mr8464919pfg.250.1527806957628; Thu, 31 May 2018 15:49:17 -0700 (PDT) Received: from cloudburst.twiddle.net (97-126-112-211.tukw.qwest.net. [97.126.112.211]) by smtp.gmail.com with ESMTPSA id t3-v6sm33385584pgs.91.2018.05.31.15.49.16 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 31 May 2018 15:49:16 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 31 May 2018 15:49:08 -0700 Message-Id: <20180531224911.23725-4-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180531224911.23725-1-richard.henderson@linaro.org> References: <20180531224911.23725-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::243 Subject: [Qemu-devel] [PATCH 3/6] linux-user: Check is_hostfd in do_syscall X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, laurent@vivier.eu, evgreen@chromium.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" This is the vast majority of all fd inputs, but not all. Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier --- linux-user/syscall.c | 303 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 280 insertions(+), 23 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index d02c16bbc6..5339f0bc1c 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -8034,6 +8034,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, if (arg3 == 0) ret = 0; else { + if (is_hostfd(arg1)) { + goto ebadf; + } if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0))) goto efault; ret = get_errno(safe_read(arg1, p, arg3)); @@ -8045,6 +8048,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } break; case TARGET_NR_write: + if (is_hostfd(arg1)) { + goto ebadf; + } if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1))) goto efault; if (fd_trans_target_to_host_data(arg1)) { @@ -8072,6 +8078,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #endif case TARGET_NR_openat: + if (is_hostfd(arg1)) { + goto ebadf; + } if (!(p = lock_user_string(arg2))) goto efault; ret = get_errno(do_openat(cpu_env, arg1, p, @@ -8082,16 +8091,25 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE) case TARGET_NR_name_to_handle_at: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5); break; #endif #if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE) case TARGET_NR_open_by_handle_at: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_open_by_handle_at(arg1, arg2, arg3); fd_trans_unregister(ret); break; #endif case TARGET_NR_close: + if (is_hostfd(arg1)) { + goto ebadf; + } fd_trans_unregister(arg1); ret = get_errno(close(arg1)); break; @@ -8155,7 +8173,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if defined(TARGET_NR_linkat) case TARGET_NR_linkat: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { void * p2 = NULL; if (!arg2 || !arg4) goto efault; @@ -8180,6 +8200,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if defined(TARGET_NR_unlinkat) case TARGET_NR_unlinkat: + if (is_hostfd(arg1)) { + goto ebadf; + } if (!(p = lock_user_string(arg2))) goto efault; ret = get_errno(unlinkat(arg1, p, arg3)); @@ -8311,6 +8334,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if defined(TARGET_NR_mknodat) case TARGET_NR_mknodat: + if (is_hostfd(arg1)) { + goto ebadf; + } if (!(p = lock_user_string(arg2))) goto efault; ret = get_errno(mknodat(arg1, p, arg3, arg4)); @@ -8334,6 +8360,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, goto unimplemented; #endif case TARGET_NR_lseek: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(lseek(arg1, arg2, arg3)); break; #if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA) @@ -8484,7 +8513,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if defined(TARGET_NR_futimesat) case TARGET_NR_futimesat: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { struct timeval *tvp, tv[2]; if (arg3) { if (copy_from_user_timeval(&tv[0], arg3) @@ -8520,6 +8551,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if defined(TARGET_NR_faccessat) && defined(__NR_faccessat) case TARGET_NR_faccessat: + if (is_hostfd(arg1)) { + goto ebadf; + } if (!(p = lock_user_string(arg2))) goto efault; ret = get_errno(faccessat(arg1, p, arg3, 0)); @@ -8564,7 +8598,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if defined(TARGET_NR_renameat) case TARGET_NR_renameat: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { void *p2; p = lock_user_string(arg2); p2 = lock_user_string(arg4); @@ -8579,7 +8615,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if defined(TARGET_NR_renameat2) case TARGET_NR_renameat2: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { void *p2; p = lock_user_string(arg2); p2 = lock_user_string(arg4); @@ -8603,6 +8641,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if defined(TARGET_NR_mkdirat) case TARGET_NR_mkdirat: + if (is_hostfd(arg1)) { + goto ebadf; + } if (!(p = lock_user_string(arg2))) goto efault; ret = get_errno(mkdirat(arg1, p, arg3)); @@ -8618,6 +8659,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #endif case TARGET_NR_dup: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(dup(arg1)); if (ret >= 0) { fd_trans_dup(arg1, ret); @@ -8720,6 +8764,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_dup2 case TARGET_NR_dup2: + if (is_hostfd(arg1) || is_hostfd(arg2)) { + goto ebadf; + } ret = get_errno(dup2(arg1, arg2)); if (ret >= 0) { fd_trans_dup(arg1, arg2); @@ -8731,6 +8778,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, { int host_flags; + if (is_hostfd(arg1) || is_hostfd(arg2)) { + goto ebadf; + } if ((arg3 & ~TARGET_O_CLOEXEC) != 0) { return -EINVAL; } @@ -9424,7 +9474,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if defined(TARGET_NR_symlinkat) case TARGET_NR_symlinkat: - { + if (is_hostfd(arg2)) { + goto ebadf; + } else { void *p2; p = lock_user_string(arg1); p2 = lock_user_string(arg3); @@ -9475,7 +9527,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if defined(TARGET_NR_readlinkat) case TARGET_NR_readlinkat: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { void *p2; p = lock_user_string(arg2); p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0); @@ -9619,13 +9673,22 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, unlock_user(p, arg1, 0); break; case TARGET_NR_ftruncate: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(ftruncate(arg1, arg2)); break; case TARGET_NR_fchmod: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(fchmod(arg1, arg2)); break; #if defined(TARGET_NR_fchmodat) case TARGET_NR_fchmodat: + if (is_hostfd(arg1)) { + goto ebadf; + } if (!(p = lock_user_string(arg2))) goto efault; ret = get_errno(fchmodat(arg1, p, arg3, 0)); @@ -9688,6 +9751,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } break; case TARGET_NR_fstatfs: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(fstatfs(arg1, &stfs)); goto convert_statfs; #ifdef TARGET_NR_statfs64 @@ -9718,6 +9784,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } break; case TARGET_NR_fstatfs64: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(fstatfs(arg1, &stfs)); goto convert_statfs64; #endif @@ -9732,84 +9801,135 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_accept case TARGET_NR_accept: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_accept4(arg1, arg2, arg3, 0); break; #endif #ifdef TARGET_NR_accept4 case TARGET_NR_accept4: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_accept4(arg1, arg2, arg3, arg4); break; #endif #ifdef TARGET_NR_bind case TARGET_NR_bind: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_bind(arg1, arg2, arg3); break; #endif #ifdef TARGET_NR_connect case TARGET_NR_connect: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_connect(arg1, arg2, arg3); break; #endif #ifdef TARGET_NR_getpeername case TARGET_NR_getpeername: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_getpeername(arg1, arg2, arg3); break; #endif #ifdef TARGET_NR_getsockname case TARGET_NR_getsockname: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_getsockname(arg1, arg2, arg3); break; #endif #ifdef TARGET_NR_getsockopt case TARGET_NR_getsockopt: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5); break; #endif #ifdef TARGET_NR_listen case TARGET_NR_listen: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(listen(arg1, arg2)); break; #endif #ifdef TARGET_NR_recv case TARGET_NR_recv: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0); break; #endif #ifdef TARGET_NR_recvfrom case TARGET_NR_recvfrom: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6); break; #endif #ifdef TARGET_NR_recvmsg case TARGET_NR_recvmsg: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_sendrecvmsg(arg1, arg2, arg3, 0); break; #endif #ifdef TARGET_NR_send case TARGET_NR_send: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0); break; #endif #ifdef TARGET_NR_sendmsg case TARGET_NR_sendmsg: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_sendrecvmsg(arg1, arg2, arg3, 1); break; #endif #ifdef TARGET_NR_sendmmsg case TARGET_NR_sendmmsg: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1); break; case TARGET_NR_recvmmsg: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0); break; #endif #ifdef TARGET_NR_sendto case TARGET_NR_sendto: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6); break; #endif #ifdef TARGET_NR_shutdown case TARGET_NR_shutdown: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(shutdown(arg1, arg2)); break; #endif @@ -9835,6 +9955,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_setsockopt case TARGET_NR_setsockopt: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5); break; #endif @@ -9938,7 +10061,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, goto do_stat; #endif case TARGET_NR_fstat: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { ret = get_errno(fstat(arg1, &st)); #if defined(TARGET_NR_stat) || defined(TARGET_NR_lstat) do_stat: @@ -10110,6 +10235,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #endif case TARGET_NR_fsync: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(fsync(arg1)); break; case TARGET_NR_clone: @@ -10225,6 +10353,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = get_errno(getpgid(arg1)); break; case TARGET_NR_fchdir: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(fchdir(arg1)); break; #ifdef TARGET_NR_bdflush /* not on x86_64 */ @@ -10244,7 +10375,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR__llseek /* Not on alpha */ case TARGET_NR__llseek: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { int64_t res; #if !defined(__NR_llseek) res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, arg5); @@ -10264,6 +10397,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_getdents case TARGET_NR_getdents: + if (is_hostfd(arg1)) { + goto ebadf; + } #ifdef EMULATE_GETDENTS_WITH_GETDENTS #if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 { @@ -10396,7 +10532,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif /* TARGET_NR_getdents */ #if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) case TARGET_NR_getdents64: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { struct linux_dirent64 *dirp; abi_long count = arg3; if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) @@ -10454,10 +10592,19 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, goto efault; } + ret = 0; pfd = alloca(sizeof(struct pollfd) * nfds); for (i = 0; i < nfds; i++) { pfd[i].fd = tswap32(target_pfd[i].fd); pfd[i].events = tswap16(target_pfd[i].events); + if (is_hostfd(pfd[i].fd)) { + ret = -TARGET_EBADF; + } + } + if (ret < 0) { + unlock_user(target_pfd, arg1, + sizeof(struct target_pollfd) * nfds); + goto fail; } } @@ -10541,10 +10688,15 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_flock: /* NOTE: the flock constant seems to be the same for every Linux platform */ + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(safe_flock(arg1, arg2)); break; case TARGET_NR_readv: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); if (vec != NULL) { ret = get_errno(safe_readv(arg1, vec, arg3)); @@ -10555,7 +10707,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } break; case TARGET_NR_writev: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); if (vec != NULL) { ret = get_errno(safe_writev(arg1, vec, arg3)); @@ -10567,7 +10721,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #if defined(TARGET_NR_preadv) case TARGET_NR_preadv: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0); if (vec != NULL) { unsigned long low, high; @@ -10583,7 +10739,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if defined(TARGET_NR_pwritev) case TARGET_NR_pwritev: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); if (vec != NULL) { unsigned long low, high; @@ -10602,6 +10760,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */ case TARGET_NR_fdatasync: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(fdatasync(arg1)); break; #endif @@ -10866,6 +11027,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_pread64 case TARGET_NR_pread64: + if (is_hostfd(arg1)) { + goto ebadf; + } if (regpairs_aligned(cpu_env, num)) { arg4 = arg5; arg5 = arg6; @@ -10876,6 +11040,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, unlock_user(p, arg2, ret); break; case TARGET_NR_pwrite64: + if (is_hostfd(arg1)) { + goto ebadf; + } if (regpairs_aligned(cpu_env, num)) { arg4 = arg5; arg5 = arg6; @@ -10971,6 +11138,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, { off_t *offp = NULL; off_t off; + + if (is_hostfd(arg1) || is_hostfd(arg2)) { + goto ebadf; + } if (arg3) { ret = get_user_sal(off, arg3); if (is_error(ret)) { @@ -10992,6 +11163,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, { off_t *offp = NULL; off_t off; + + if (is_hostfd(arg1) || is_hostfd(arg2)) { + goto ebadf; + } if (arg3) { ret = get_user_s64(off, arg3); if (is_error(ret)) { @@ -11059,6 +11234,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_ftruncate64 case TARGET_NR_ftruncate64: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4); break; #endif @@ -11084,6 +11262,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_fstat64 case TARGET_NR_fstat64: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(fstat(arg1, &st)); if (!is_error(ret)) ret = host_to_target_stat64(cpu_env, arg2, &st); @@ -11096,6 +11277,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #ifdef TARGET_NR_newfstatat case TARGET_NR_newfstatat: #endif + if (is_hostfd(arg1)) { + goto ebadf; + } if (!(p = lock_user_string(arg2))) goto efault; ret = get_errno(fstatat(arg1, path(p), &st, arg4)); @@ -11184,6 +11368,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #if defined(TARGET_NR_fchownat) case TARGET_NR_fchownat: + if (is_hostfd(arg1)) { + goto ebadf; + } if (!(p = lock_user_string(arg2))) goto efault; ret = get_errno(fchownat(arg1, p, low2highuid(arg3), @@ -11525,6 +11712,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_fchown32 case TARGET_NR_fchown32: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(fchown(arg1, arg2, arg3)); break; #endif @@ -11626,6 +11816,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, * Note that offset and len are both 64-bit so appear as * pairs of 32-bit registers. */ + if (is_hostfd(arg1)) { + goto ebadf; + } ret = posix_fadvise(arg1, target_offset64(arg3, arg4), target_offset64(arg5, arg6), arg2); ret = -host_to_target_errno(ret); @@ -11636,6 +11829,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #ifdef TARGET_NR_fadvise64_64 case TARGET_NR_fadvise64_64: + if (is_hostfd(arg1)) { + goto ebadf; + } #if defined(TARGET_PPC) || defined(TARGET_XTENSA) /* 6 args: fd, advice, offset (high, low), len (high, low) */ ret = arg2; @@ -11664,6 +11860,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #ifdef TARGET_NR_fadvise64 case TARGET_NR_fadvise64: + if (is_hostfd(arg1)) { + goto ebadf; + } /* 5 args: fd, offset (high, low), len, advice */ if (regpairs_aligned(cpu_env, num)) { /* offset is in (3,4), len in 5 and advice in 6 */ @@ -11686,6 +11885,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #ifdef TARGET_NR_fadvise64 case TARGET_NR_fadvise64: #endif + if (is_hostfd(arg1)) { + goto ebadf; + } #ifdef TARGET_S390X switch (arg4) { case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */ @@ -11711,6 +11913,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if TARGET_ABI_BITS == 32 case TARGET_NR_fcntl64: + if (is_hostfd(arg1)) { + goto ebadf; + } { int cmd; struct flock64 fl; @@ -11858,7 +12063,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } break; case TARGET_NR_fsetxattr: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { void *n, *v = 0; if (arg3) { v = lock_user(VERIFY_READ, arg3, arg4, 1); @@ -11905,7 +12112,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } break; case TARGET_NR_fgetxattr: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { void *n, *v = 0; if (arg3) { v = lock_user(VERIFY_WRITE, arg3, arg4, 0); @@ -11944,7 +12153,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } break; case TARGET_NR_fremovexattr: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { void *n; n = lock_user_string(arg2); if (n) { @@ -12095,7 +12306,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #if defined(TARGET_NR_utimensat) case TARGET_NR_utimensat: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { struct timespec *tsp, ts[2]; if (!arg3) { tsp = NULL; @@ -12141,6 +12354,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch) case TARGET_NR_inotify_add_watch: + if (is_hostfd(arg1)) { + goto ebadf; + } p = lock_user_string(arg2); ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3)); unlock_user(p, arg2, 0); @@ -12148,6 +12364,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch) case TARGET_NR_inotify_rm_watch: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(sys_inotify_rm_watch(arg1, arg2)); break; #endif @@ -12248,14 +12467,18 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #ifdef CONFIG_SPLICE #ifdef TARGET_NR_tee case TARGET_NR_tee: - { + if (is_hostfd(arg1) || is_hostfd(arg2)) { + goto ebadf; + } else { ret = get_errno(tee(arg1,arg2,arg3,arg4)); } break; #endif #ifdef TARGET_NR_splice case TARGET_NR_splice: - { + if (is_hostfd(arg1) || is_hostfd(arg3)) { + goto ebadf; + } else { loff_t loff_in, loff_out; loff_t *ploff_in = NULL, *ploff_out = NULL; if (arg2) { @@ -12285,8 +12508,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #endif #ifdef TARGET_NR_vmsplice - case TARGET_NR_vmsplice: - { + case TARGET_NR_vmsplice: + if (is_hostfd(arg1)) { + goto ebadf; + } else { struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1); if (vec != NULL) { ret = get_errno(vmsplice(arg1, vec, arg3, arg4)); @@ -12327,6 +12552,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif /* CONFIG_EVENTFD */ #if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate) case TARGET_NR_fallocate: + if (is_hostfd(arg1)) { + goto ebadf; + } #if TARGET_ABI_BITS == 32 ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4), target_offset64(arg5, arg6))); @@ -12338,6 +12566,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #if defined(CONFIG_SYNC_FILE_RANGE) #if defined(TARGET_NR_sync_file_range) case TARGET_NR_sync_file_range: + if (is_hostfd(arg1)) { + goto ebadf; + } #if TARGET_ABI_BITS == 32 #if defined(TARGET_MIPS) ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4), @@ -12354,6 +12585,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #if defined(TARGET_NR_sync_file_range2) case TARGET_NR_sync_file_range2: /* This is like sync_file_range but the arguments are reordered */ + if (is_hostfd(arg1)) { + goto ebadf; + } #if TARGET_ABI_BITS == 32 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4), target_offset64(arg5, arg6), arg2)); @@ -12365,11 +12599,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #if defined(TARGET_NR_signalfd4) case TARGET_NR_signalfd4: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_signalfd4(arg1, arg2, arg4); break; #endif #if defined(TARGET_NR_signalfd) case TARGET_NR_signalfd: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = do_signalfd4(arg1, arg2, 0); break; #endif @@ -12389,6 +12629,10 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, { struct epoll_event ep; struct epoll_event *epp = 0; + + if (is_hostfd(arg1) || is_hostfd(arg3)) { + goto ebadf; + } if (arg4) { struct target_epoll_event *target_ep; if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) { @@ -12422,6 +12666,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, int maxevents = arg3; int timeout = arg4; + if (is_hostfd(arg1)) { + goto ebadf; + } if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) { ret = -TARGET_EINVAL; break; @@ -12698,7 +12945,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD) case TARGET_NR_timerfd_gettime: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { struct itimerspec its_curr; ret = get_errno(timerfd_gettime(arg1, &its_curr)); @@ -12712,7 +12961,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD) case TARGET_NR_timerfd_settime: - { + if (is_hostfd(arg1)) { + goto ebadf; + } else { struct itimerspec its_new, its_old, *p_new; if (arg3) { @@ -12747,6 +12998,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #if defined(TARGET_NR_setns) && defined(CONFIG_SETNS) case TARGET_NR_setns: + if (is_hostfd(arg1)) { + goto ebadf; + } ret = get_errno(setns(arg1, arg2)); break; #endif @@ -12781,4 +13035,7 @@ fail: efault: ret = -TARGET_EFAULT; goto fail; +ebadf: + ret = -TARGET_EBADF; + goto fail; } From patchwork Thu May 31 22:49:09 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 923663 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="jXBJAyoQ"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40xjQv342bz9s4Y for ; Fri, 1 Jun 2018 08:52:39 +1000 (AEST) Received: from localhost ([::1]:46511 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fOWQu-0007Xf-MI for incoming@patchwork.ozlabs.org; Thu, 31 May 2018 18:52:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38529) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fOWNn-0005AX-7a for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fOWNm-0000pQ-I9 for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:23 -0400 Received: from mail-pl0-x230.google.com ([2607:f8b0:400e:c01::230]:47027) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fOWNm-0000p0-CQ for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:22 -0400 Received: by mail-pl0-x230.google.com with SMTP id 30-v6so14074562pld.13 for ; Thu, 31 May 2018 15:49:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=vgByVcF4sTG4UIGoDfjdQmMRjmxXVfAO4cyzhWgy1pQ=; b=jXBJAyoQ5oIb2p6Nf95rL+iLe45Ui5dtDFJzssYth2sQVfoQ16lFJK2OYXEiKO4pyT c4b/U6jOD3xenRbibE15kfrhTmzP1i/irQjmuPN0EuDxW5kYydWGnpOLgN4n0jnDlpUm 4rZFwhllXSMWxyhPkHcY7UBReii4c5Y879IA4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=vgByVcF4sTG4UIGoDfjdQmMRjmxXVfAO4cyzhWgy1pQ=; b=eNVhdPkhQpJxlZu+li3Le76tDLMYIMGbPBkxYXYonIw+heyJCRNG9MPYnr8hILD/TS 3kIO2EQkNJ4o44PXzkKMNYHHZ1n2slKSiMKcwbjixPnBpodtLHBL+K88OJMoSHziYWg5 RtsAxaM1UxrqF4wCy046oruYIsz5XUqTGXUc3jqCjryjx8waK34Phz8OAxD7vCqajBna 97YUvOMJdwv518j55zCOjwnkvwbXXdCKi92q75jGWEA1YAKBkU2qzrvaT4T19xHPGMaA 7HI80Vrd7Ih18Y0rAjnSqFqBTpqTMGcnsFtuRaA0Az28uTz6iGCQfKqbhYbz7NIdadR6 vuvA== X-Gm-Message-State: ALKqPwfAif36pSMH98phD+alvRGheoeHlpt8NG6Ueb0tlsZHcCb6BRR3 1NRkMmEFpKKGExQaOCTgJ568dZlXKoQ= X-Google-Smtp-Source: ADUXVKJF2ARaz34/ei4KuVrFmnE9UeNrbmbHLISQ2Mdr77QbwgRjc7NQWnUN9LDEOS45QWA3xyeddw== X-Received: by 2002:a17:902:7e42:: with SMTP id a2-v6mr8654068pln.151.1527806959735; Thu, 31 May 2018 15:49:19 -0700 (PDT) Received: from cloudburst.twiddle.net (97-126-112-211.tukw.qwest.net. [97.126.112.211]) by smtp.gmail.com with ESMTPSA id t3-v6sm33385584pgs.91.2018.05.31.15.49.18 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 31 May 2018 15:49:18 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 31 May 2018 15:49:09 -0700 Message-Id: <20180531224911.23725-5-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180531224911.23725-1-richard.henderson@linaro.org> References: <20180531224911.23725-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c01::230 Subject: [Qemu-devel] [PATCH 4/6] linux-user: Check contains_hostfd in select syscalls X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, laurent@vivier.eu, evgreen@chromium.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier --- linux-user/syscall.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 5339f0bc1c..b98125829b 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1506,6 +1506,11 @@ static abi_long do_select(int n, if (ret) { return ret; } + if (contains_hostfd(&rfds) || + contains_hostfd(&wfds) || + contains_hostfd(&efds)) { + return -TARGET_EBADF; + } if (target_tv_addr) { if (copy_from_user_timeval(&tv, target_tv_addr)) @@ -9392,6 +9397,11 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, if (ret) { goto fail; } + if (contains_hostfd(&rfds) || + contains_hostfd(&wfds) || + contains_hostfd(&efds)) { + goto ebadf; + } /* * This takes a timespec, and not a timeval, so we cannot From patchwork Thu May 31 22:49:10 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 923661 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="ILKiSk7K"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40xjN20jqZz9s1B for ; Fri, 1 Jun 2018 08:50:10 +1000 (AEST) Received: from localhost ([::1]:46496 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fOWOV-0005F5-PA for incoming@patchwork.ozlabs.org; Thu, 31 May 2018 18:50:07 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38531) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fOWNn-0005Aj-Ev for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:24 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fOWNm-0000pe-MG for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:23 -0400 Received: from mail-pf0-x231.google.com ([2607:f8b0:400e:c00::231]:36718) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fOWNm-0000p5-Gv for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:22 -0400 Received: by mail-pf0-x231.google.com with SMTP id w129-v6so11499025pfd.3 for ; Thu, 31 May 2018 15:49:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Q1iNbE7b2UYUJKQIqBMPbPcIDxffIQfiNgT2DyF9Ne0=; b=ILKiSk7K5205eB5+ztRNKyiGmk3yhvOqgSnhlUOQQUzcEqe9PzD1Mx2ssOdYfbyYJT Zfkr8O3B3QChado6oJ7aYVsD7MKY2pPv2fBeZjEBYZc24RG7PYg7pXZrpOufuEQ380Pn 7keXPQ3Xr54Vga4E5rvj30X9Irnr5vz3qhN4s= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Q1iNbE7b2UYUJKQIqBMPbPcIDxffIQfiNgT2DyF9Ne0=; b=aWUPwQ8SSiq8RDcNQXfpSkc9IKdR3ckXswckr4svBKl6FWTF9Ykcs92zHfCAhyQZM+ lX5kHEItvn+MptCwYXToXe4aO2ZQiDE5Y57NCe3InHQhhow5QdgkXCJXX82e1/qJ/LZ7 yJ15MAu2i1KFzUYNJCsfictoqimpEahBh4Z8zmvJAlxPH78kP1sFHN3FwESMShGZ7k98 +qZShCe8mcVNPmllPRxZ8iaQKIrP2ft0y1hE93VluvpPfgi6rPtFRnMN7B7KiCkU4YcG aU8uXuFvd5+1BtuBFV2Rh3wlWrdmzt5Tso1lkJe2DuSQ35n4yLZHCk4nWl4G+msyX747 /ZZA== X-Gm-Message-State: ALKqPweLFAvlhOPQnbSI/d5MevdGHil4RaaG/PKpBUUszX82d3wTdO6P QLQzmoMhprhUq9IcFE6sMMqPWRirU3I= X-Google-Smtp-Source: ADUXVKJbaPZpbdsL0QSJEZ2CBTP+iqa+KqJuZOnkBkaJJzJrsIm5v2MXgajjlnimN8pRi9vhNcAtNA== X-Received: by 2002:a62:6c87:: with SMTP id h129-v6mr8371181pfc.179.1527806961171; Thu, 31 May 2018 15:49:21 -0700 (PDT) Received: from cloudburst.twiddle.net (97-126-112-211.tukw.qwest.net. [97.126.112.211]) by smtp.gmail.com with ESMTPSA id t3-v6sm33385584pgs.91.2018.05.31.15.49.19 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 31 May 2018 15:49:20 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 31 May 2018 15:49:10 -0700 Message-Id: <20180531224911.23725-6-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180531224911.23725-1-richard.henderson@linaro.org> References: <20180531224911.23725-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c00::231 Subject: [Qemu-devel] [PATCH 5/6] linux-user: Check is_hostfd in mmap syscalls X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, laurent@vivier.eu, evgreen@chromium.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Signed-off-by: Richard Henderson Reviewed-by: Laurent Vivier --- linux-user/syscall.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index b98125829b..d7513d5dac 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -9605,11 +9605,17 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, v5 = tswapal(v[4]); v6 = tswapal(v[5]); unlock_user(v, arg1, 0); + if (is_hostfd(v5)) { + goto ebadf; + } ret = get_errno(target_mmap(v1, v2, v3, target_to_host_bitmask(v4, mmap_flags_tbl), v5, v6)); } #else + if (is_hostfd(arg5)) { + goto ebadf; + } ret = get_errno(target_mmap(arg1, arg2, arg3, target_to_host_bitmask(arg4, mmap_flags_tbl), arg5, @@ -9622,6 +9628,9 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #ifndef MMAP_SHIFT #define MMAP_SHIFT 12 #endif + if (is_hostfd(arg5)) { + goto ebadf; + } ret = get_errno(target_mmap(arg1, arg2, arg3, target_to_host_bitmask(arg4, mmap_flags_tbl), arg5, From patchwork Thu May 31 22:49:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 923664 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=linaro.org Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=linaro.org header.i=@linaro.org header.b="kFcSyzrF"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 40xjQv341nz9s1B for ; Fri, 1 Jun 2018 08:52:38 +1000 (AEST) Received: from localhost ([::1]:46510 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fOWQu-0007Wo-DE for incoming@patchwork.ozlabs.org; Thu, 31 May 2018 18:52:36 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38559) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fOWNr-0005Gw-Uj for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fOWNo-0000rO-LU for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:27 -0400 Received: from mail-pg0-x244.google.com ([2607:f8b0:400e:c05::244]:44340) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fOWNo-0000qf-B4 for qemu-devel@nongnu.org; Thu, 31 May 2018 18:49:24 -0400 Received: by mail-pg0-x244.google.com with SMTP id p21-v6so10350839pgd.11 for ; Thu, 31 May 2018 15:49:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=7OSmq4hqL21PytEiWwZ62wkBZ8Vmh8b24upJeUdJdBg=; b=kFcSyzrF7C6LBF7LlbRzF78myjrbbahwkKM1+4VP1v24M+W2Fw6iOmEY5nsO/amv8m fIza4QHYBU1qKFX5tEOZmQj3auBXOtuH5aF68PRZhBOkrxfPvrAWBRhJ6IfynOEu80Fz xMT5d5+fWJoKFHetzVdNGV/y1n4d2a2v5xBSE= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=7OSmq4hqL21PytEiWwZ62wkBZ8Vmh8b24upJeUdJdBg=; b=Uy5ye6xpYPyKvoScUtMblN/d00wFL9YiEIgZMNRVAs8ldIalSqUAAc4mBA4HHfxPj8 HtrVUunksnvVoWYm+1/sU/FzEcgRh+0QyRQ7Bb+Z4A3wCsLTfrH7HP64BFYB+RHt3Tlz r6vmqcJlwW8AvT1If/3MOcazG3YHsTQ5XmZqDvNz5RZlymamUPE6GNMtenTf9J/KI/Eb ZiNaihZ56L4f/Rvdq64AX7wdgDgIog7PXHZfBfDXky31366tUypb8EO8qBfQvsP7V2KZ k3c9JYDXtnz7JYc4368BzWSa1TU1i8cYUI3ymQymqqQqFHy9/xCizuxo/rhIFLT+7RGN /qTw== X-Gm-Message-State: ALKqPwevhDMV6NvBn7EUrE+DH8G/DpGXpUBrMulhjajIcBcWlmH4Bzkp 2O0SMmd7E5sBpcE8fbaMlyTa7uUgJsg= X-Google-Smtp-Source: ADUXVKL29ReXwPINHFsrGS0gj4CswfWahx3IBHBxuMpxSOF7w8XojmbI0DAn7y1VzdPQPZZGLuUARw== X-Received: by 2002:a65:4b49:: with SMTP id k9-v6mr6772862pgt.369.1527806962785; Thu, 31 May 2018 15:49:22 -0700 (PDT) Received: from cloudburst.twiddle.net (97-126-112-211.tukw.qwest.net. [97.126.112.211]) by smtp.gmail.com with ESMTPSA id t3-v6sm33385584pgs.91.2018.05.31.15.49.21 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Thu, 31 May 2018 15:49:21 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Thu, 31 May 2018 15:49:11 -0700 Message-Id: <20180531224911.23725-7-richard.henderson@linaro.org> X-Mailer: git-send-email 2.17.0 In-Reply-To: <20180531224911.23725-1-richard.henderson@linaro.org> References: <20180531224911.23725-1-richard.henderson@linaro.org> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:400e:c05::244 Subject: [Qemu-devel] [PATCH 6/6] linux-user: Use *at functions to implement interp_prefix X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: peter.maydell@linaro.org, laurent@vivier.eu, evgreen@chromium.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" If the interp_prefix is a complete chroot, it may have a *lot* of files. Setting up the cache for this is quite expensive. For the most part, we can use the *at versions of various syscalls to attempt the operation in the prefix. For the few cases that remain, attempt the operation in the prefix via concatenation and then retry if that fails. Signed-off-by: Richard Henderson --- linux-user/qemu.h | 37 ++++++++++ linux-user/elfload.c | 5 +- linux-user/main.c | 26 ++++++- linux-user/syscall.c | 163 +++++++++++++++++++++++++++++-------------- 4 files changed, 174 insertions(+), 57 deletions(-) diff --git a/linux-user/qemu.h b/linux-user/qemu.h index 33dafbe0e4..05a82a3628 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -471,7 +471,44 @@ void mmap_fork_start(void); void mmap_fork_end(int child); /* main.c */ +extern int interp_dirfd; extern unsigned long guest_stack_size; +char *interp_prefix_path(const char *path); + +/* If PATH is absolute, attempt an operation first within interp_dirfd, + * using OPENAT_EXPR. If that fails with ENOENT, or if PATH is not + * absolute, only use NORMAL_EXPR. + */ +#define TRY_INTERP_FD(RET, PATH, OPENAT_EXPR, NORMAL_EXPR) \ + do { \ + if (interp_dirfd >= 0 && (PATH)[0] == '/') { \ + RET = OPENAT_EXPR; \ + if (RET != -1 || errno != ENOENT) { \ + break; \ + } \ + } \ + RET = NORMAL_EXPR; \ + } while (0) + +/* If PATH is absolute, attempt an operation first with interp_prefix + * prefixed. If that fails with ENOENT, or if PATH is not absolute, + * only attempt with PATH. + */ +#define TRY_INTERP_PATH(RET, PATH, EXPR) \ + do { \ + char *new_##PATH = interp_prefix_path(PATH); \ + if (new_##PATH) { \ + __typeof(PATH) save_##PATH = PATH; \ + PATH = new_##PATH; \ + RET = EXPR; \ + free(new_##PATH); \ + PATH = save_##PATH; \ + if (RET != -1 || errno != ENOENT) { \ + break; \ + } \ + } \ + RET = EXPR; \ + } while (0) /* user access */ diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 13bc78d0c8..abdf5bbf01 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -6,7 +6,6 @@ #include "qemu.h" #include "disas/disas.h" -#include "qemu/path.h" #ifdef _ARCH_PPC64 #undef ARCH_DLINFO @@ -2375,7 +2374,9 @@ static void load_elf_interp(const char *filename, struct image_info *info, { int fd, retval; - fd = open(path(filename), O_RDONLY); + TRY_INTERP_FD(fd, filename, + openat(interp_dirfd, filename + 1, O_RDONLY), + open(filename, O_RDONLY)); if (fd < 0) { goto exit_perror; } diff --git a/linux-user/main.c b/linux-user/main.c index ee3f323c08..4e956fc00c 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -23,7 +23,6 @@ #include "qapi/error.h" #include "qemu.h" -#include "qemu/path.h" #include "qemu/config-file.h" #include "qemu/cutils.h" #include "qemu/help_option.h" @@ -89,9 +88,27 @@ unsigned long reserved_va; static void usage(int exitcode); +int interp_dirfd; static const char *interp_prefix = CONFIG_QEMU_INTERP_PREFIX; const char *qemu_uname_release; +char *interp_prefix_path(const char *path) +{ + size_t i_len, p_len; + char *ret; + + if (interp_prefix == NULL || path[0] != '/') { + return NULL; + } + i_len = strlen(interp_prefix); + p_len = strlen(path) + 1; + ret = g_malloc(i_len + p_len); + + memcpy(ret, interp_prefix, i_len); + memcpy(ret + i_len, path, p_len); + return ret; +} + /* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so we allocate a bigger stack. Need a better solution, for example by remapping the process stack directly at the right place */ @@ -671,7 +688,12 @@ int main(int argc, char **argv, char **envp) memset(&bprm, 0, sizeof (bprm)); /* Scan interp_prefix dir for replacement files. */ - init_paths(interp_prefix); + interp_dirfd = open(interp_prefix, O_CLOEXEC | O_DIRECTORY | O_PATH); + if (interp_dirfd >= 0) { + add_hostfd(interp_dirfd); + } else { + interp_prefix = NULL; + } init_qemu_uname_release(); diff --git a/linux-user/syscall.c b/linux-user/syscall.c index d7513d5dac..b75dd9a5bc 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -19,7 +19,6 @@ #define _ATFILE_SOURCE #include "qemu/osdep.h" #include "qemu/cutils.h" -#include "qemu/path.h" #include #include #include @@ -7401,7 +7400,10 @@ static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname, fh = g_malloc0(total_size); fh->handle_bytes = size; - ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags)); + TRY_INTERP_FD(ret, name, + name_to_handle_at(interp_dirfd, name + 1, fh, &mid, flags), + name_to_handle_at(dirfd, name, fh, &mid, flags)); + ret = get_errno(ret); unlock_user(name, pathname, 0); /* man name_to_handle_at(2): @@ -7777,6 +7779,7 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, #endif { NULL, NULL, NULL } }; + int ret; if (is_proc_myself(pathname, "exe")) { int execfd = qemu_getauxval(AT_EXECFD); @@ -7816,7 +7819,10 @@ static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, return fd; } - return safe_openat(dirfd, path(pathname), flags, mode); + TRY_INTERP_FD(ret, pathname, + safe_openat(interp_dirfd, pathname + 1, flags, mode), + safe_openat(dirfd, pathname, flags, mode)); + return ret; } #define TIMER_MAGIC 0x0caf0000 @@ -7969,6 +7975,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, struct stat st; struct statfs stfs; void *p; + char *fn; #if defined(DEBUG_ERESTARTSYS) /* Debug-only code for exercising the syscall-restart code paths @@ -8531,10 +8538,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } else { tvp = NULL; } - if (!(p = lock_user_string(arg2))) + if (!(fn = lock_user_string(arg2))) { goto efault; - ret = get_errno(futimesat(arg1, path(p), tvp)); - unlock_user(p, arg2, 0); + } + TRY_INTERP_FD(ret, fn, + futimesat(interp_dirfd, fn + 1, tvp), + futimesat(arg1, fn, tvp)); + ret = get_errno(ret); + unlock_user(fn, arg2, 0); } break; #endif @@ -8548,10 +8559,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_access case TARGET_NR_access: - if (!(p = lock_user_string(arg1))) + if (!(fn = lock_user_string(arg1))) { goto efault; - ret = get_errno(access(path(p), arg2)); - unlock_user(p, arg1, 0); + } + TRY_INTERP_FD(ret, fn, + faccessat(interp_dirfd, fn + 1, arg2, 0), + access(fn, arg2)); + ret = get_errno(ret); + unlock_user(fn, arg1, 0); break; #endif #if defined(TARGET_NR_faccessat) && defined(__NR_faccessat) @@ -8559,10 +8574,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, if (is_hostfd(arg1)) { goto ebadf; } - if (!(p = lock_user_string(arg2))) + if (!(fn = lock_user_string(arg2))) { goto efault; - ret = get_errno(faccessat(arg1, p, arg3, 0)); - unlock_user(p, arg2, 0); + } + TRY_INTERP_FD(ret, fn, + faccessat(interp_dirfd, fn + 1, arg3, 0), + faccessat(arg1, fn, arg3, 0)); + ret = get_errno(ret); + unlock_user(fn, arg2, 0); break; #endif #ifdef TARGET_NR_nice /* not on alpha */ @@ -8713,10 +8732,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, if (arg1 == 0) { ret = get_errno(acct(NULL)); } else { - if (!(p = lock_user_string(arg1))) + if (!(fn = lock_user_string(arg1))) { goto efault; - ret = get_errno(acct(path(p))); - unlock_user(p, arg1, 0); + } + TRY_INTERP_PATH(ret, fn, acct(fn)); + ret = get_errno(ret); + unlock_user(fn, arg1, 0); } break; #ifdef TARGET_NR_umount2 @@ -9507,14 +9528,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, case TARGET_NR_readlink: { void *p2; - p = lock_user_string(arg1); + fn = lock_user_string(arg1); p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0); - if (!p || !p2) { + if (!fn || !p2) { ret = -TARGET_EFAULT; } else if (!arg3) { /* Short circuit this for the magic exe check. */ ret = -TARGET_EINVAL; - } else if (is_proc_myself((const char *)p, "exe")) { + } else if (is_proc_myself(fn, "exe")) { char real[PATH_MAX], *temp; temp = realpath(exec_path, real); /* Return value is # of bytes that we wrote to the buffer. */ @@ -9528,10 +9549,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, memcpy(p2, real, ret); } } else { - ret = get_errno(readlink(path(p), p2, arg3)); + TRY_INTERP_FD(ret, fn, + readlinkat(interp_dirfd, fn + 1, p2, arg3), + readlink(fn, p2, arg3)); + ret = get_errno(ret); } unlock_user(p2, arg2, ret); - unlock_user(p, arg1, 0); + unlock_user(fn, arg1, 0); } break; #endif @@ -9541,20 +9565,23 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, goto ebadf; } else { void *p2; - p = lock_user_string(arg2); + fn = lock_user_string(arg2); p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0); - if (!p || !p2) { + if (!fn || !p2) { ret = -TARGET_EFAULT; - } else if (is_proc_myself((const char *)p, "exe")) { + } else if (is_proc_myself(fn, "exe")) { char real[PATH_MAX], *temp; temp = realpath(exec_path, real); ret = temp == NULL ? get_errno(-1) : strlen(real) ; snprintf((char *)p2, arg4, "%s", real); } else { - ret = get_errno(readlinkat(arg1, path(p), p2, arg4)); + TRY_INTERP_FD(ret, fn, + readlinkat(interp_dirfd, fn + 1, p2, arg4), + readlinkat(arg1, fn, p2, arg4)); + ret = get_errno(ret); } unlock_user(p2, arg3, ret); - unlock_user(p, arg2, 0); + unlock_user(fn, arg2, 0); } break; #endif @@ -9739,10 +9766,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, goto unimplemented; #endif case TARGET_NR_statfs: - if (!(p = lock_user_string(arg1))) + if (!(fn = lock_user_string(arg1))) { goto efault; - ret = get_errno(statfs(path(p), &stfs)); - unlock_user(p, arg1, 0); + } + TRY_INTERP_PATH(ret, fn, statfs(fn, &stfs)); + ret = get_errno(ret); + unlock_user(fn, arg1, 0); convert_statfs: if (!is_error(ret)) { struct target_statfs *target_stfs; @@ -9777,10 +9806,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, goto convert_statfs; #ifdef TARGET_NR_statfs64 case TARGET_NR_statfs64: - if (!(p = lock_user_string(arg1))) + if (!(fn = lock_user_string(arg1))) { goto efault; - ret = get_errno(statfs(path(p), &stfs)); - unlock_user(p, arg1, 0); + } + TRY_INTERP_PATH(ret, fn, statfs(fn, &stfs)); + ret = get_errno(ret); + unlock_user(fn, arg1, 0); convert_statfs64: if (!is_error(ret)) { struct target_statfs64 *target_stfs; @@ -10065,18 +10096,26 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #ifdef TARGET_NR_stat case TARGET_NR_stat: - if (!(p = lock_user_string(arg1))) + if (!(fn = lock_user_string(arg1))) { goto efault; - ret = get_errno(stat(path(p), &st)); - unlock_user(p, arg1, 0); + } + TRY_INTERP_FD(ret, fn, + fstatat(interp_dirfd, fn + 1, &st, 0), + stat(fn, &st)); + ret = get_errno(ret); + unlock_user(fn, arg1, 0); goto do_stat; #endif #ifdef TARGET_NR_lstat case TARGET_NR_lstat: - if (!(p = lock_user_string(arg1))) + if (!(fn = lock_user_string(arg1))) { goto efault; - ret = get_errno(lstat(path(p), &st)); - unlock_user(p, arg1, 0); + } + TRY_INTERP_FD(ret, fn, + fstatat(interp_dirfd, fn + 1, &st, AT_SYMLINK_NOFOLLOW), + lstat(fn, &st)); + ret = get_errno(ret); + unlock_user(fn, arg1, 0); goto do_stat; #endif case TARGET_NR_fstat: @@ -11261,20 +11300,28 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #endif #ifdef TARGET_NR_stat64 case TARGET_NR_stat64: - if (!(p = lock_user_string(arg1))) + if (!(fn = lock_user_string(arg1))) { goto efault; - ret = get_errno(stat(path(p), &st)); - unlock_user(p, arg1, 0); + } + TRY_INTERP_FD(ret, fn, + fstatat(interp_dirfd, fn + 1, &st, 0), + stat(fn, &st)); + ret = get_errno(ret); + unlock_user(fn, arg1, 0); if (!is_error(ret)) ret = host_to_target_stat64(cpu_env, arg2, &st); break; #endif #ifdef TARGET_NR_lstat64 case TARGET_NR_lstat64: - if (!(p = lock_user_string(arg1))) + if (!(fn = lock_user_string(arg1))) { goto efault; - ret = get_errno(lstat(path(p), &st)); - unlock_user(p, arg1, 0); + } + TRY_INTERP_FD(ret, fn, + fstatat(interp_dirfd, fn + 1, &st, AT_SYMLINK_NOFOLLOW), + lstat(fn, &st)); + ret = get_errno(ret); + unlock_user(fn, arg1, 0); if (!is_error(ret)) ret = host_to_target_stat64(cpu_env, arg2, &st); break; @@ -11299,9 +11346,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, if (is_hostfd(arg1)) { goto ebadf; } - if (!(p = lock_user_string(arg2))) + if (!(fn = lock_user_string(arg2))) { goto efault; - ret = get_errno(fstatat(arg1, path(p), &st, arg4)); + } + TRY_INTERP_FD(ret, fn, + fstatat(interp_dirfd, fn + 1, &st, arg4), + fstatat(arg1, fn, &st, arg4)); + ret = get_errno(ret); + unlock_user(fn, arg2, 0); if (!is_error(ret)) ret = host_to_target_stat64(cpu_env, arg3, &st); break; @@ -12339,12 +12391,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, if (!arg2) ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4)); else { - if (!(p = lock_user_string(arg2))) { - ret = -TARGET_EFAULT; - goto fail; + if (!(fn = lock_user_string(arg2))) { + goto efault; } - ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4)); - unlock_user(p, arg2, 0); + TRY_INTERP_FD(ret, fn, + sys_utimensat(interp_dirfd, fn + 1, tsp, arg4), + sys_utimensat(arg1, fn, tsp, arg4)); + ret = get_errno(ret); + unlock_user(fn, arg2, 0); } } break; @@ -12376,9 +12430,12 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, if (is_hostfd(arg1)) { goto ebadf; } - p = lock_user_string(arg2); - ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3)); - unlock_user(p, arg2, 0); + if (!(fn = lock_user_string(arg2))) { + goto efault; + } + TRY_INTERP_PATH(ret, fn, sys_inotify_add_watch(arg1, fn, arg3)); + ret = get_errno(ret); + unlock_user(fn, arg2, 0); break; #endif #if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)