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: <20160204152235.GB5343@pd.tnic>
Date:	Thu, 4 Feb 2016 16:22:35 +0100
From:	Borislav Petkov <bp@...en8.de>
To:	Ingo Molnar <mingo@...nel.org>
Cc:	"Luck, Tony" <tony.luck@...el.com>,
	"H. Peter Anvin" <hpa@...or.com>,
	Thomas Gleixner <tglx@...utronix.de>,
	Andy Lutomirski <luto@...capital.net>,
	Peter Zijlstra <peterz@...radead.org>,
	Steven Rostedt <rostedt@...dmis.org>,
	Brian Gerst <brgerst@...il.com>,
	lkml <linux-kernel@...r.kernel.org>
Subject: [PATCH -v2] x86: Add an archinfo dumper module

Here's v2 with the stuff we talked about, implemented. I've added
'control_regs' file too so that you can do:

$ cat /sys/kernel/debug/x86/archinfo/control_regs
CR4: [-|-|SMEP|OSXSAVE|-|-|-|-|OSXMMEXCPT|OSFXSR|-|PGE|MCE|PAE|PSE|-|-|-|-]: 0x1406f0

for example. Yeah, only CR4 right now.

Off the top of my head, we would need "msrs" which dumps EFER and a
bunch of other interesting MSRs along with the names of the set bits.

---
From: Borislav Petkov <bp@...e.de>
Date: Mon, 30 Nov 2015 13:53:36 +0100
Subject: [PATCH -v2] x86: Add an archinfo dumper module

Dump interesting/valuable information related to the x86 architecture of
the current CPU and platform.

Signed-off-by: Borislav Petkov <bp@...e.de>
---
 arch/x86/Kconfig.debug     |   5 ++
 arch/x86/kernel/Makefile   |   1 +
 arch/x86/kernel/archinfo.c | 215 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 221 insertions(+)
 create mode 100644 arch/x86/kernel/archinfo.c

diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 9b18ed97a8a2..c757d1ee9a7a 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -383,4 +383,9 @@ config PUNIT_ATOM_DEBUG
 	  The current power state can be read from
 	  /sys/kernel/debug/punit_atom/dev_power_state
 
+config ARCHINFO
+	tristate "x86 archinfo dumper module"
+	---help---
+	  Dump interesting x86 arch stuff.
+
 endmenu
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index b1b78ffe01d0..89972c1b9de6 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -109,6 +109,7 @@ obj-$(CONFIG_EFI)			+= sysfb_efi.o
 
 obj-$(CONFIG_PERF_EVENTS)		+= perf_regs.o
 obj-$(CONFIG_TRACING)			+= tracepoint.o
+obj-$(CONFIG_ARCHINFO)			+= archinfo.o
 
 ###
 # 64 bit specific files
diff --git a/arch/x86/kernel/archinfo.c b/arch/x86/kernel/archinfo.c
new file mode 100644
index 000000000000..c04e98625565
--- /dev/null
+++ b/arch/x86/kernel/archinfo.c
@@ -0,0 +1,215 @@
+#include <linux/debugfs.h>
+#include <linux/module.h>
+#include <linux/cpu.h>
+
+#include <asm/desc.h>
+
+static const char * const system_desc_types[] = {
+	[0] = "Reserved (illegal)",
+	[1] = "Available 16-bit TSS",
+	[2] = "LDT",
+	[3] = "Busy 16-bit TSS",
+	[4] = "16-bit Call Gate",
+	[5] = "Task Gate",
+	[6] = "16-bit Interrupt Gate",
+	[7] = "16-bit Trap Gate",
+	[8] = "Reserved (illegal)",
+	[9] = "Available 32-bit TSS",
+	[10] = "Reserved (illegal)",
+	[11] = "Busy 32-bit TSS",
+	[12] = "32-bit Call Gate",
+	[13] = "Reserved (illegal)",
+	[14] = "32-bit Interrupt Gate",
+	[15] = "32-bit Trap Gate",
+};
+
+static const char * const user_desc_types[] = {
+	[0] = "Read-Only",
+	[1] = "Read-only - Accessed",
+	[2] = "Read/Write",
+	[3] = "Read/Write - Accessed",
+	[4] = "Expand-down, Read-Only",
+	[5] = "Expand-down, Read-Only - Accessed",
+	[6] = "Expand-down, Read-Write",
+	[7] = "Expand-down, Read-Write - Accessed",
+	[8] = "Execute-Only",
+	[9] = "Execute-Only - Accessed",
+	[10] = "Execute/Readable",
+	[11] = "Execute/Readable - Accessed",
+	[12] = "Conforming, Execute-Only",
+	[13] = "Conforming, Execute-Only - Accessed",
+	[14] = "Conforming, Execute/Readable",
+	[15] = "Conforming, Execute/Readable - Accessed",
+};
+
+static void print_seg_desc(struct seq_file *m, struct desc_struct *d, int num)
+{
+	seq_printf(m, "%02d:\n", num);
+	seq_printf(m, "[ base[31:24]:%02x G:%x D:%x L:%x AVL:%x lim[19:16]:%x |",
+		   d->base2, d->g, d->d, d->l, d->avl, d->limit);
+	seq_printf(m, " P:%x DPL:%x S:%x C:%x base[23:16]:%02x ]\n",
+		   d->p, d->dpl, d->s, !!(d->type & BIT(2)), d->base1);
+	seq_printf(m, "[ base[15:00]:%04x | lim[15:00]:%04x ]: ",
+		   d->base0, d->limit0);
+
+	if (d->s)
+		seq_printf(m, "User: (0x%x) %s, %s\n",
+			    d->type,
+			   (d->type > 7 ? "Code" : "Data"),
+			   (user_desc_types[d->type]));
+	else
+		seq_printf(m, "System: (0x%x) %s\n", d->type, system_desc_types[d->type]);
+
+	seq_printf(m, "\n");
+}
+
+static void dump_gdt(void *info)
+{
+	struct gdt_page *g = this_cpu_ptr(&gdt_page);
+	struct seq_file *m = (struct seq_file *)info;
+	int i;
+
+	seq_printf(m, "CPU%d, GDT %p:\n", smp_processor_id(), &g->gdt);
+
+	for (i = 0; i < GDT_ENTRIES; i++)
+		print_seg_desc(m, &g->gdt[i], i);
+
+	seq_printf(m, "----\n");
+
+}
+
+static int gdt_show(struct seq_file *m, void *v)
+{
+	int c;
+
+	/*
+	 * Using on_each_cpu() here fudges the output and we want it nicely
+	 * sorted by CPU.
+	 */
+	get_online_cpus();
+		for_each_online_cpu(c)
+			smp_call_function_single(c, dump_gdt, m, 1);
+	put_online_cpus();
+
+	seq_printf(m,
+		   "\nInfo:\n"
+		   "base,limit,A,G,R: ignored in 64-bit mode.\n"
+		   "G: granularity bit (23):\n"
+			"\t- 0b: segment limit is not scaled.\n"
+			"\t- 1b: segment limit scaled by 4K.\n"
+		   "D/B: CS default operand size bit (22):\n"
+			"\t- 0b: 16-bit.\n"
+			"\t- 1b: 32-bit.\n"
+			"\tD=0b is the only allowed setting in long mode (L=1b).\n"
+			"\tCalled B in stack segments.\n"
+		   "L: long mode bit (21):\n"
+			"\t- 0b: CPU in compat mode. Enables segmentation.\n"
+			"\t- 1b: CPU in long mode.\n"
+		   "AVL: bit available to software (20).\n"
+		   "P: present bit (15):\n"
+			"\t- 0b: seg. not present in mem => #NP.\n"
+			"\t- 1b: seg is present in memory.\n"
+		   "DPL: Descriptor Privilege Level [14:13]:\n"
+			"\t- 0b: highest privilege level.\n"
+			"    ...\n"
+			"\t- 3b: lowest privilege level.\n"
+		   "S+Type: decriptor types [12,11:8]:\n"
+			"\t Specify descriptor type and access characteristics.\n"
+		   " S:\n"
+			"\t- 0b: System descriptor.\n"
+			"\t- 1b: User descriptor.\n"
+		   " R: readable bit (9):\n"
+			"\t- 0b: code seg is executable, reads -> #GP\n"
+			"\t- 1b: code seg is both read/exec\n"
+		   " A: accessed bit (8): set by CPU when desc copied into %%cs; cleared only by sw.\n"
+			);
+
+	return 0;
+}
+
+static int gdt_open(struct inode *inode, struct file *filp)
+{
+	return single_open(filp, gdt_show, NULL);
+}
+
+static int cr_show(struct seq_file *m, void *v)
+{
+	unsigned long cr4 = __read_cr4();
+
+	seq_printf(m, "CR4: [%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s|%s]: 0x%lx\n",
+		      (cr4 & BIT(22) ? "PKE"		: "-"),
+		      (cr4 & BIT(21) ? "SMAP"		: "-"),
+		      (cr4 & BIT(20) ? "SMEP"		: "-"),
+		      (cr4 & BIT(18) ? "OSXSAVE"	: "-"),
+		      (cr4 & BIT(17) ? "PCIDE"		: "-"),
+		      (cr4 & BIT(16) ? "FSGSBASE"	: "-"),
+		      (cr4 & BIT(14) ? "SMXE"		: "-"),
+		      (cr4 & BIT(13) ? "VMXE"		: "-"),
+		      (cr4 & BIT(10) ? "OSXMMEXCPT"	: "-"),
+		      (cr4 & BIT(9)  ? "OSFXSR"		: "-"),
+		      (cr4 & BIT(8)  ? "PCE"		: "-"),
+		      (cr4 & BIT(7)  ? "PGE"		: "-"),
+		      (cr4 & BIT(6)  ? "MCE"		: "-"),
+		      (cr4 & BIT(5)  ? "PAE"		: "-"),
+		      (cr4 & BIT(4)  ? "PSE"		: "-"),
+		      (cr4 & BIT(3)  ? "DE"		: "-"),
+		      (cr4 & BIT(2)  ? "TSD"		: "-"),
+		      (cr4 & BIT(1)  ? "PVI"		: "-"),
+		      (cr4 & BIT(0)  ? "VME"		: "-"),
+		      cr4);
+
+	return 0;
+}
+
+static int cr_open(struct inode *inode, struct file *filp)
+{
+	return single_open(filp, cr_show, NULL);
+}
+
+static const struct file_operations cr_fops = {
+	.owner	 = THIS_MODULE,
+	.open	 = cr_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release,
+};
+
+static const struct file_operations gdt_fops = {
+	.owner	 = THIS_MODULE,
+	.open	 = gdt_open,
+	.read	 = seq_read,
+	.llseek	 = seq_lseek,
+	.release = single_release,
+};
+
+static struct dentry *dfs_entry;
+
+static int __init archinfo_init(void)
+{
+	dfs_entry = debugfs_create_dir("archinfo", arch_debugfs_dir);
+	if (IS_ERR_OR_NULL(dfs_entry))
+		return -EINVAL;
+
+	if (!debugfs_create_file("gdt", S_IRUSR, dfs_entry, NULL, &gdt_fops)) {
+		debugfs_remove_recursive(dfs_entry);
+		return -EINVAL;
+	}
+
+	if (!debugfs_create_file("control_regs", S_IRUSR, dfs_entry, NULL, &cr_fops)) {
+		debugfs_remove_recursive(dfs_entry);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static void __exit archinfo_exit(void)
+{
+	debugfs_remove_recursive(dfs_entry);
+}
+
+module_init(archinfo_init);
+module_exit(archinfo_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Borislav Petkov <bp@...en8.de>");
+MODULE_DESCRIPTION("x86 arch info dumper");
-- 
2.3.5


-- 
Regards/Gruss,
    Boris.

ECO tip #101: Trim your mails when you reply.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ