lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20230530053724.232765-12-baolu.lu@linux.intel.com>
Date:   Tue, 30 May 2023 13:37:18 +0800
From:   Lu Baolu <baolu.lu@...ux.intel.com>
To:     Jason Gunthorpe <jgg@...pe.ca>, Kevin Tian <kevin.tian@...el.com>,
        Joerg Roedel <joro@...tes.org>, Will Deacon <will@...nel.org>,
        Robin Murphy <robin.murphy@....com>,
        Jean-Philippe Brucker <jean-philippe@...aro.org>,
        Nicolin Chen <nicolinc@...dia.com>,
        Yi Liu <yi.l.liu@...el.com>,
        Jacob Pan <jacob.jun.pan@...ux.intel.com>
Cc:     iommu@...ts.linux.dev, linux-kselftest@...r.kernel.org,
        virtualization@...ts.linux-foundation.org,
        linux-kernel@...r.kernel.org, Lu Baolu <baolu.lu@...ux.intel.com>
Subject: [RFC PATCHES 11/17] iommufd: Deliver fault messages to user space

Provide a read-only file interface that allows user space to obtain fault
messages by sequentially reading the file. User space can determine whether
all fault messages have been read by comparing the provided read buffer
with the actually returned data length. Once a fault is read by the user,
it will be moved from the pending list to the waiting-for-response list.

Signed-off-by: Yi Liu <yi.l.liu@...el.com>
Signed-off-by: Lu Baolu <baolu.lu@...ux.intel.com>
---
 drivers/iommu/iommufd/iommufd_private.h |  2 +
 drivers/iommu/iommufd/hw_pagetable.c    | 66 +++++++++++++++++++++++++
 2 files changed, 68 insertions(+)

diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h
index 67e5aa0f996e..6da0ba9421d0 100644
--- a/drivers/iommu/iommufd/iommufd_private.h
+++ b/drivers/iommu/iommufd/iommufd_private.h
@@ -242,6 +242,8 @@ struct hw_pgtable_fault {
 	struct list_head response;
 	struct eventfd_ctx *trigger;
 	bool user_pasid_table;
+	struct file *fault_file;
+	int fault_fd;
 };
 
 struct iommufd_fault {
diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c
index ca3e4d92f2aa..09377a98069b 100644
--- a/drivers/iommu/iommufd/hw_pagetable.c
+++ b/drivers/iommu/iommufd/hw_pagetable.c
@@ -4,6 +4,8 @@
  */
 #include <linux/iommu.h>
 #include <linux/eventfd.h>
+#include <linux/file.h>
+#include <linux/anon_inodes.h>
 #include <uapi/linux/iommufd.h>
 
 #include "../iommu-priv.h"
@@ -310,6 +312,8 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
 		iommu_domain_set_iopf_handler(hwpt->domain,
 					      iommufd_hw_pagetable_iopf_handler,
 					      hwpt);
+
+		cmd->out_fault_fd = hwpt->fault->fault_fd;
 	}
 
 	cmd->out_hwpt_id = hwpt->obj.id;
@@ -421,6 +425,62 @@ iommufd_hw_pagetable_iopf_handler(struct iommu_fault *fault,
 	return IOMMU_PAGE_RESP_ASYNC;
 }
 
+static ssize_t hwpt_fault_fops_read(struct file *filep, char __user *buf,
+				    size_t count, loff_t *ppos)
+{
+	struct hw_pgtable_fault *fault = filep->private_data;
+	size_t fault_size = sizeof(struct iommu_fault);
+	struct iommufd_fault *ifault;
+	size_t done = 0;
+
+	if (ppos || count % fault_size)
+		return -ESPIPE;
+
+	mutex_lock(&fault->mutex);
+	while (!list_empty(&fault->deliver) && count > done) {
+		ifault = list_first_entry(&fault->deliver, struct iommufd_fault, item);
+		if (copy_to_user(buf + done, &ifault->fault, fault_size))
+			break;
+		done += fault_size;
+		list_del_init(&ifault->item);
+		if (ifault->fault.flags & IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE)
+			list_add_tail(&ifault->item, &fault->response);
+		else
+			kfree(ifault);
+	}
+	mutex_unlock(&fault->mutex);
+
+	return done;
+}
+
+static const struct file_operations hwpt_fault_fops = {
+	.owner		= THIS_MODULE,
+	.read		= hwpt_fault_fops_read,
+};
+
+static int hw_pagetable_get_fault_fd(struct hw_pgtable_fault *fault)
+{
+	struct file *filep;
+	int fdno;
+
+	fdno = get_unused_fd_flags(O_CLOEXEC);
+	if (fdno < 0)
+		return fdno;
+
+	filep = anon_inode_getfile("[iommufd-pgfault]", &hwpt_fault_fops,
+				   fault, O_RDONLY);
+	if (IS_ERR(filep)) {
+		put_unused_fd(fdno);
+		return PTR_ERR(filep);
+	}
+
+	fd_install(fdno, filep);
+	fault->fault_file = filep;
+	fault->fault_fd = fdno;
+
+	return 0;
+}
+
 static struct hw_pgtable_fault *hw_pagetable_fault_alloc(int eventfd)
 {
 	struct hw_pgtable_fault *fault;
@@ -440,8 +500,14 @@ static struct hw_pgtable_fault *hw_pagetable_fault_alloc(int eventfd)
 		goto out_free;
 	}
 
+	rc = hw_pagetable_get_fault_fd(fault);
+	if (rc)
+		goto out_put_eventfd;
+
 	return fault;
 
+out_put_eventfd:
+	eventfd_ctx_put(fault->trigger);
 out_free:
 	kfree(fault);
 	return ERR_PTR(rc);
-- 
2.34.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ