From owner-dev-commits-src-all@freebsd.org Mon Jan 11 15:36:16 2021 Return-Path: Delivered-To: dev-commits-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id EC85F4DC6FE; Mon, 11 Jan 2021 15:36:16 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4DDyV36vCnz3rP2; Mon, 11 Jan 2021 15:36:11 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 7B4321CFC6; Mon, 11 Jan 2021 15:36:11 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 10BFaBcx026689; Mon, 11 Jan 2021 15:36:11 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 10BFaBtH026688; Mon, 11 Jan 2021 15:36:11 GMT (envelope-from git) Date: Mon, 11 Jan 2021 15:36:11 GMT Message-Id: <202101111536.10BFaBtH026688@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Roger Pau Monné Subject: git: a7650787905d - main - xen/privcmd: implement the restrict ioctl MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: royger X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: a7650787905d36ac01297aa699d3009da6cfaaa9 Auto-Submitted: auto-generated X-BeenThere: dev-commits-src-all@freebsd.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Commit messages for all branches of the src repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 11 Jan 2021 15:36:17 -0000 The branch main has been updated by royger: URL: https://cgit.FreeBSD.org/src/commit/?id=a7650787905d36ac01297aa699d3009da6cfaaa9 commit a7650787905d36ac01297aa699d3009da6cfaaa9 Author: Roger Pau Monne AuthorDate: 2020-06-25 17:16:04 +0000 Commit: Roger Pau Monné CommitDate: 2021-01-11 15:33:27 +0000 xen/privcmd: implement the restrict ioctl Use an interface compatible with the Linux one so that the user-space libraries already using the Linux interface can be used without much modifications. This allows an open privcmd instance to limit against which domains it can act upon. Sponsored by: Citrix Systems R&D --- sys/dev/xen/privcmd/privcmd.c | 82 +++++++++++++++++++++++++++++++++++++++++++ sys/xen/privcmd.h | 2 ++ 2 files changed, 84 insertions(+) diff --git a/sys/dev/xen/privcmd/privcmd.c b/sys/dev/xen/privcmd/privcmd.c index d9f11aa0fe7a..0ef6737df64f 100644 --- a/sys/dev/xen/privcmd/privcmd.c +++ b/sys/dev/xen/privcmd/privcmd.c @@ -78,12 +78,14 @@ struct privcmd_map { }; static d_ioctl_t privcmd_ioctl; +static d_open_t privcmd_open; static d_mmap_single_t privcmd_mmap_single; static struct cdevsw privcmd_devsw = { .d_version = D_VERSION, .d_ioctl = privcmd_ioctl, .d_mmap_single = privcmd_mmap_single, + .d_open = privcmd_open, .d_name = "privcmd", }; @@ -99,6 +101,10 @@ static struct cdev_pager_ops privcmd_pg_ops = { .cdev_pg_dtor = privcmd_pg_dtor, }; +struct per_user_data { + domid_t dom; +}; + static device_t privcmd_dev = NULL; /*------------------------- Privcmd Pager functions --------------------------*/ @@ -259,12 +265,30 @@ privcmd_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg, { int error; unsigned int i; + void *data; + const struct per_user_data *u; + + error = devfs_get_cdevpriv(&data); + if (error != 0) + return (EINVAL); + /* + * Constify user-data to prevent unintended changes to the restriction + * limits. + */ + u = data; switch (cmd) { case IOCTL_PRIVCMD_HYPERCALL: { struct ioctl_privcmd_hypercall *hcall; hcall = (struct ioctl_privcmd_hypercall *)arg; + + /* Forbid hypercalls if restricted. */ + if (u->dom != DOMID_INVALID) { + error = EPERM; + break; + } + #ifdef __amd64__ /* * The hypervisor page table walker will refuse to access @@ -301,6 +325,11 @@ privcmd_ioctl(struct cdev *dev, unsigned long cmd, caddr_t arg, mmap = (struct ioctl_privcmd_mmapbatch *)arg; + if (u->dom != DOMID_INVALID && u->dom != mmap->dom) { + error = EPERM; + break; + } + umap = setup_virtual_area(td, mmap->addr, mmap->num); if (umap == NULL) { error = EINVAL; @@ -382,6 +411,11 @@ mmap_out: mmap = (struct ioctl_privcmd_mmapresource *)arg; + if (u->dom != DOMID_INVALID && u->dom != mmap->dom) { + error = EPERM; + break; + } + bzero(&adq, sizeof(adq)); adq.domid = mmap->dom; @@ -434,6 +468,11 @@ mmap_out: dmop = (struct ioctl_privcmd_dmop *)arg; + if (u->dom != DOMID_INVALID && u->dom != dmop->dom) { + error = EPERM; + break; + } + if (dmop->num == 0) break; @@ -472,6 +511,24 @@ mmap_out: free(hbufs, M_PRIVCMD); + break; + } + case IOCTL_PRIVCMD_RESTRICT: { + struct per_user_data *u; + domid_t dom; + + dom = *(domid_t *)arg; + + error = devfs_get_cdevpriv((void **)&u); + if (error != 0) + break; + + if (u->dom != DOMID_INVALID && u->dom != dom) { + error = -EINVAL; + break; + } + u->dom = dom; + break; } default: @@ -482,6 +539,31 @@ mmap_out: return (error); } +static void +user_release(void *arg) +{ + + free(arg, M_PRIVCMD); +} + +static int +privcmd_open(struct cdev *dev, int flag, int otyp, struct thread *td) +{ + struct per_user_data *u; + int error; + + u = malloc(sizeof(*u), M_PRIVCMD, M_WAITOK); + u->dom = DOMID_INVALID; + + /* Assign the allocated per_user_data to this open instance. */ + error = devfs_set_cdevpriv(u, user_release); + if (error != 0) { + free(u, M_PRIVCMD); + } + + return (error); +} + /*------------------ Private Device Attachment Functions --------------------*/ static void privcmd_identify(driver_t *driver, device_t parent) diff --git a/sys/xen/privcmd.h b/sys/xen/privcmd.h index cd0bc7d550d9..55a1cdc86471 100644 --- a/sys/xen/privcmd.h +++ b/sys/xen/privcmd.h @@ -82,5 +82,7 @@ struct ioctl_privcmd_dmop { _IOW('E', 2, struct ioctl_privcmd_mmapresource) #define IOCTL_PRIVCMD_DM_OP \ _IOW('E', 3, struct ioctl_privcmd_dmop) +#define IOCTL_PRIVCMD_RESTRICT \ + _IOW('E', 4, domid_t) #endif /* !__XEN_PRIVCMD_H__ */