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]
Date:   Mon,  4 May 2020 17:02:30 +0200
From:   Alexandre Chartre <alexandre.chartre@...cle.com>
To:     tglx@...utronix.de, mingo@...hat.com, bp@...en8.de, hpa@...or.com,
        dave.hansen@...ux.intel.com, luto@...nel.org, peterz@...radead.org,
        x86@...nel.org, linux-mm@...ck.org, linux-kernel@...r.kernel.org
Cc:     pbonzini@...hat.com, konrad.wilk@...cle.com,
        jan.setjeeilers@...cle.com, liran.alon@...cle.com,
        junaids@...gle.com, graf@...zon.de, rppt@...ux.vnet.ibm.com,
        kuzuno@...il.com, mgross@...ux.intel.com,
        alexandre.chartre@...cle.com
Subject: [RFC v4][PATCH part-3 09/14] asidrv: Add ioctls to manage ASI page faults

Add ioctls to list and clear ASI page faults. Also add an ioctl to display
or not stack trace on ASI page fault.

Signed-off-by: Alexandre Chartre <alexandre.chartre@...cle.com>
---
 drivers/staging/asi/asidrv.c | 88 ++++++++++++++++++++++++++++++++++++
 drivers/staging/asi/asidrv.h | 32 +++++++++++++
 2 files changed, 120 insertions(+)

diff --git a/drivers/staging/asi/asidrv.c b/drivers/staging/asi/asidrv.c
index 9ca17e0b654e..e6edfbe5acea 100644
--- a/drivers/staging/asi/asidrv.c
+++ b/drivers/staging/asi/asidrv.c
@@ -4,6 +4,7 @@
  */
 
 #include <linux/fs.h>
+#include <linux/kallsyms.h>
 #include <linux/kthread.h>
 #include <linux/miscdevice.h>
 #include <linux/module.h>
@@ -790,12 +791,99 @@ static int asidrv_ioctl_run_sequence(struct asidrv_test *test,
 	return 0;
 }
 
+/*
+ * ASI fault ioctls
+ */
+
+static int asidrv_ioctl_list_fault(struct asi *asi, unsigned long arg)
+{
+	struct asidrv_fault_list __user *uflist;
+	struct asidrv_fault_list *flist;
+	size_t flist_size;
+	__u32 uflist_len;
+	int i;
+
+	uflist = (struct asidrv_fault_list __user *)arg;
+	if (copy_from_user(&uflist_len, &uflist->length, sizeof(uflist_len)))
+		return -EFAULT;
+
+	uflist_len = min_t(unsigned int, uflist_len, ASI_FAULT_LOG_SIZE);
+
+	flist_size = sizeof(*flist) + sizeof(struct asidrv_fault) * uflist_len;
+	flist = kzalloc(flist_size, GFP_KERNEL);
+	if (!flist)
+		return -ENOMEM;
+
+	for (i = 0; i < ASI_FAULT_LOG_SIZE; i++) {
+		if (!asi->fault_log[i].address)
+			break;
+		if (i < uflist_len) {
+			flist->fault[i].addr = asi->fault_log[i].address;
+			flist->fault[i].count = asi->fault_log[i].count;
+			sprint_symbol(flist->fault[i].symbol,
+				      asi->fault_log[i].address);
+		}
+	}
+	flist->length = i;
+
+	if (copy_to_user(uflist, flist, flist_size)) {
+		kfree(flist);
+		return -EFAULT;
+	}
+
+	if (i >= ASI_FAULT_LOG_SIZE)
+		pr_warn("ASI %p: fault log buffer is full [%d]\n", asi, i);
+
+	kfree(flist);
+
+	return 0;
+}
+
+static int asidrv_ioctl_clear_fault(struct asi *asi)
+{
+	int i;
+
+	for (i = 0; i < ASI_FAULT_LOG_SIZE; i++) {
+		if (!asi->fault_log[i].address)
+			break;
+		asi->fault_log[i].address = 0;
+	}
+
+	pr_debug("ASI %p: faults cleared\n", asi);
+	return 0;
+}
+
+static int asidrv_ioctl_log_fault_stack(struct asi *asi, bool log_stack)
+{
+	if (log_stack) {
+		asi->fault_log_policy |= ASI_FAULT_LOG_STACK;
+		pr_debug("ASI %p: setting fault stack\n", asi);
+	} else {
+		asi->fault_log_policy &= ~ASI_FAULT_LOG_STACK;
+		pr_debug("ASI %p: clearing fault stack\n", asi);
+	}
+
+	return 0;
+}
+
 static long asidrv_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
 {
 	struct asidrv_test *test = asidrv_test;
+	struct asi *asi = test->asi;
 
 	switch (cmd) {
 
+	/* ASI fault ioctls */
+
+	case ASIDRV_IOCTL_LIST_FAULT:
+		return asidrv_ioctl_list_fault(asi, arg);
+
+	case ASIDRV_IOCTL_CLEAR_FAULT:
+		return asidrv_ioctl_clear_fault(asi);
+
+	case ASIDRV_IOCTL_LOG_FAULT_STACK:
+		return asidrv_ioctl_log_fault_stack(asi, arg);
+
 	/* Test ioctls */
 
 	case ASIDRV_IOCTL_RUN_SEQUENCE:
diff --git a/drivers/staging/asi/asidrv.h b/drivers/staging/asi/asidrv.h
index 9f540b119883..99ab9843e36b 100644
--- a/drivers/staging/asi/asidrv.h
+++ b/drivers/staging/asi/asidrv.h
@@ -36,9 +36,41 @@ enum asidrv_run_error {
 
 #define ASIDRV_IOCTL_RUN_SEQUENCE	_IOWR('a', 1, struct asidrv_run_param)
 
+/*
+ * ASIDRV_IOCTL_LIST_FAULT: return the list of ASI faults.
+ *
+ * User should set 'length' with the number of entries available in the
+ * 'fault' array. On return, 'length' is set to the number of ASI faults
+ * (which can be larger than the original 'length' value), and the 'fault'
+ * array is filled with the ASI faults.
+ */
+#define ASIDRV_IOCTL_LIST_FAULT		_IOWR('a', 2, struct asidrv_fault_list)
+#define ASIDRV_IOCTL_CLEAR_FAULT	_IO('a', 3)
+#define ASIDRV_IOCTL_LOG_FAULT_STACK	_IO('a', 4)
+
+#define ASIDRV_KSYM_NAME_LEN	128
+/*
+ * We need KSYM_SYMBOL_LEN to lookup symbol. However it's not part of
+ * userland include. So we use a reasonably large value (KSYM_SYMBOL_LEN
+ * is around 310).
+ */
+#define ASIDRV_KSYM_SYMBOL_LEN	512
+
 struct asidrv_run_param {
 	__u32 sequence;		/* sequence to run */
 	__u32 run_error;	/* result error after run */
 	__u32 asi_active;	/* ASI is active after run? */
 };
+
+struct asidrv_fault {
+	__u64 addr;
+	char  symbol[ASIDRV_KSYM_SYMBOL_LEN];
+	__u32 count;
+};
+
+struct asidrv_fault_list {
+	__u32 length;
+	struct asidrv_fault fault[0];
+};
+
 #endif
-- 
2.18.2

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ