From patchwork Mon Jul 11 14:57:58 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: David Vrabel X-Patchwork-Id: 9223731 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id DFF0360572 for ; Mon, 11 Jul 2016 15:00:27 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id CEBA727D13 for ; Mon, 11 Jul 2016 15:00:27 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C0F6927D85; Mon, 11 Jul 2016 15:00:27 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00, RCVD_IN_DNSWL_MED autolearn=ham version=3.3.1 Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 984D827D13 for ; Mon, 11 Jul 2016 15:00:26 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bMcet-0001sx-Rw; Mon, 11 Jul 2016 14:58:07 +0000 Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bMces-0001sr-Hr for xen-devel@lists.xenproject.org; Mon, 11 Jul 2016 14:58:06 +0000 Received: from [85.158.137.68] by server-9.bemta-3.messagelabs.com id 04/CA-16470-DF3B3875; Mon, 11 Jul 2016 14:58:05 +0000 X-Brightmail-Tracker: H4sIAAAAAAAAA+NgFvrBLMWRWlGSWpSXmKPExsXitHRDpO7fzc3 hBsuP8lt83zKZyYHR4/CHKywBjFGsmXlJ+RUJrBkTbq9gLvguW3Hl0FuWBsa/El2MnBwSAv4S c97vZgOx2QR0JB4vmcHexcjBISKgInF7r0EXIxcHs8AVRokd91rZQWqEBSwkzvYtZgWxWQRUJ SYvucUIYvMKuEkc/H+HGWKmnMT54z/BbCGgOR/XrmKFqBGUODnzCQuIzSwgIXHwxQuoem6J26 enMk9g5JmFpGwWkrIFjEyrGNWLU4vKUot0LfSSijLTM0pyEzNzdA0NjPVyU4uLE9NTcxKTivW S83M3MQJDhAEIdjBeaHc+xCjJwaQkyru0vzlciC8pP6UyI7E4I76oNCe1+BCjDAeHkgQvOzDk hASLUtNTK9Iyc4DBCpOW4OBREuHlA0nzFhck5hZnpkOkTjEqSonzXtgElBAASWSU5sG1wSLkE qOslDAvI9AhQjwFqUW5mSWo8q8YxTkYlYR5+UHG82TmlcBNfwW0mAloca0D2OKSRISUVAPj8Y wrRw69UT6Z/UJLPNrt6PPNL/vdLy9Q3b5u4hTHmSw6U8ymFv592ph47laoiMoytXoW+bKu/Q1 RhdNzt145Y+Ii3LXw05PyfKVrZjoXNq6stujuYH6am5A04//btKcv1673lVrwbPU0ceO2Lwka r8tPWq1RcGaNtNh08XjXs5m9xoYnD/nPU2Ipzkg01GIuKk4EAGC8f+eLAgAA X-Env-Sender: prvs=9936ea03f=david.vrabel@citrix.com X-Msg-Ref: server-2.tower-31.messagelabs.com!1468249083!49878491!1 X-Originating-IP: [66.165.176.89] X-SpamReason: No, hits=0.0 required=7.0 tests=sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni44OSA9PiAyMDMwMDc=\n, received_headers: No Received headers X-StarScan-Received: X-StarScan-Version: 8.46; banners=-,-,- X-VirusChecked: Checked Received: (qmail 61808 invoked from network); 11 Jul 2016 14:58:04 -0000 Received: from smtp.citrix.com (HELO SMTP.CITRIX.COM) (66.165.176.89) by server-2.tower-31.messagelabs.com with RC4-SHA encrypted SMTP; 11 Jul 2016 14:58:04 -0000 X-IronPort-AV: E=Sophos;i="5.28,346,1464652800"; d="scan'208";a="365497950" From: David Vrabel To: Date: Mon, 11 Jul 2016 15:57:58 +0100 Message-ID: <1468249078-6949-1-git-send-email-david.vrabel@citrix.com> X-Mailer: git-send-email 2.1.4 MIME-Version: 1.0 X-DLP: MIA2 Cc: Juergen Gross , Jennifer Herbert , Boris Ostrovsky , Ian Jackson , David Vrabel Subject: [Xen-devel] [PATCHv1] xen/evtchn: add IOCTL_EVTCHN_RESTRICT X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" X-Virus-Scanned: ClamAV using ClamSMTP IOCTL_EVTCHN_RESTRICT limits the file descriptor to being able to bind to interdomain event channels from a specific domain. Event channels that are already bound continue to work for sending and receiving notifications. This is useful as part of deprivileging a user space PV backend or device model (QEMU). e.g., Once the device model as bound to the ioreq server event channels it can restrict the file handle so an exploited DM cannot use it to create or bind to arbitrary event channels. Signed-off-by: David Vrabel Reviewed-by: Boris Ostrovsky --- drivers/xen/evtchn.c | 40 ++++++++++++++++++++++++++++++++++++++++ include/uapi/xen/evtchn.h | 15 +++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c index f4edd6d..7efd1cb 100644 --- a/drivers/xen/evtchn.c +++ b/drivers/xen/evtchn.c @@ -73,8 +73,12 @@ struct per_user_data { wait_queue_head_t evtchn_wait; struct fasync_struct *evtchn_async_queue; const char *name; + + domid_t restrict_domid; }; +#define UNRESTRICTED_DOMID ((domid_t)-1) + struct user_evtchn { struct rb_node node; struct per_user_data *user; @@ -443,6 +447,10 @@ static long evtchn_ioctl(struct file *file, struct ioctl_evtchn_bind_virq bind; struct evtchn_bind_virq bind_virq; + rc = -EACCES; + if (u->restrict_domid != UNRESTRICTED_DOMID) + break; + rc = -EFAULT; if (copy_from_user(&bind, uarg, sizeof(bind))) break; @@ -468,6 +476,11 @@ static long evtchn_ioctl(struct file *file, if (copy_from_user(&bind, uarg, sizeof(bind))) break; + rc = -EACCES; + if (u->restrict_domid != UNRESTRICTED_DOMID && + u->restrict_domid != bind.remote_domain) + break; + bind_interdomain.remote_dom = bind.remote_domain; bind_interdomain.remote_port = bind.remote_port; rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, @@ -485,6 +498,10 @@ static long evtchn_ioctl(struct file *file, struct ioctl_evtchn_bind_unbound_port bind; struct evtchn_alloc_unbound alloc_unbound; + rc = -EACCES; + if (u->restrict_domid != UNRESTRICTED_DOMID) + break; + rc = -EFAULT; if (copy_from_user(&bind, uarg, sizeof(bind))) break; @@ -553,6 +570,27 @@ static long evtchn_ioctl(struct file *file, break; } + case IOCTL_EVTCHN_RESTRICT_DOMID: { + struct ioctl_evtchn_restrict_domid ierd; + + rc = -EACCES; + if (u->restrict_domid != UNRESTRICTED_DOMID) + break; + + rc = -EFAULT; + if (copy_from_user(&ierd, uarg, sizeof(ierd))) + break; + + rc = -EINVAL; + if (ierd.domid == 0 || ierd.domid >= DOMID_FIRST_RESERVED) + break; + + u->restrict_domid = ierd.domid; + rc = 0; + + break; + } + default: rc = -ENOSYS; break; @@ -601,6 +639,8 @@ static int evtchn_open(struct inode *inode, struct file *filp) mutex_init(&u->ring_cons_mutex); spin_lock_init(&u->ring_prod_lock); + u->restrict_domid = UNRESTRICTED_DOMID; + filp->private_data = u; return nonseekable_open(inode, filp); diff --git a/include/uapi/xen/evtchn.h b/include/uapi/xen/evtchn.h index 14e833ee4..f057b53 100644 --- a/include/uapi/xen/evtchn.h +++ b/include/uapi/xen/evtchn.h @@ -85,4 +85,19 @@ struct ioctl_evtchn_notify { #define IOCTL_EVTCHN_RESET \ _IOC(_IOC_NONE, 'E', 5, 0) +/* + * Restrict this file descriptor so that it can only be used to bind + * new interdomain events from one domain. + * + * Once a file descriptor has been restricted it cannot be + * de-restricted, and must be closed and re-opened. Event channels + * which were bound before restricting remain bound afterwards, and + * can be notified as usual. + */ +#define IOCTL_EVTCHN_RESTRICT_DOMID \ + _IOC(_IOC_NONE, 'E', 100, sizeof(struct ioctl_evtchn_restrict_domid)) +struct ioctl_evtchn_restrict_domid { + domid_t domid; +}; + #endif /* __LINUX_PUBLIC_EVTCHN_H__ */