diff mbox series

[RFC,v1,2/3] ima: ascii_vpcr pseudo-file for sysadmins

Message ID 20230127081953.7534-3-ilya.hanov@huawei-partners.com (mailing list archive)
State New, archived
Headers show
Series ima: vPCR debug/security | expand

Commit Message

Ilya Hanov Jan. 27, 2023, 8:19 a.m. UTC
Dump cPCR values in human-readable format. This may add some flexibility for
debugging. ima/vpcr also was renamed to ima/binary_vpcr. When something went wrong
System Administrator is able to see cPCR values without
doing PCR_Extend operations (for PCR12), this invokes only PCR_Read. ascii_vpcr
has the same format as binary_vpcr, but can be read by humans:

$ sudo cat /sys/kernel/security/ima/ascii_vpcr
cPCR: c57f9efc-7149-4df5-a1b3-66fb03db4006 8780724757d796e21b242f9bc8912c0905d24dfb2011a74fd1e91134b247bf80
(output truncated)

Signed-off-by: Ilya Hanov <ilya.hanov@huawei-partners.com>
---
 security/integrity/ima/ima_fs.c | 129 ++++++++++++++++++++++++++++----
 1 file changed, 113 insertions(+), 16 deletions(-)
diff mbox series

Patch

diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index cf9164d31599..2ebbdfa708df 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -572,7 +572,7 @@  static void *vpcr_next(struct seq_file *m, void *v, loff_t *pos)
 	return seq_list_next(v, &vpcr_list, pos);
 }
 
-static void vpcr_stop(struct seq_file *m, void *v)
+static void binary_vpcr_stop(struct seq_file *m, void *v)
 {
 	int j;
 	int ret;
@@ -585,8 +585,10 @@  static void vpcr_stop(struct seq_file *m, void *v)
 		return;
 
 	tpm_chip = curr_ns->ima_tpm_chip;
-	pcr12_digest.alg_id = TPM_ALG_SHA256;
+	if (!tpm_chip)
+		goto ex;
 
+	pcr12_digest.alg_id = TPM_ALG_SHA256;
 	temp_tpm = kcalloc(tpm_chip->nr_allocated_banks,
 			   sizeof(*curr_ns->digests), GFP_NOFS);
 	if (!temp_tpm)
@@ -626,7 +628,7 @@  static void vpcr_stop(struct seq_file *m, void *v)
 	mutex_unlock(&vpcr_list_mutex);
 }
 
-static int vpcr_show(struct seq_file *m, void *v)
+static int binary_vpcr_show(struct seq_file *m, void *v)
 {
 	int ret = 0;
 	u8 buf[IMA_MAX_DIGEST_SIZE * 2] = {0};
@@ -647,14 +649,96 @@  static int vpcr_show(struct seq_file *m, void *v)
 	return ret;
 }
 
-const struct seq_operations vpcr_seq_ops = {
+const struct seq_operations binary_vpcr_seq_ops = {
+	.start = vpcr_start,
+	.next  = vpcr_next,
+	.stop  = binary_vpcr_stop,
+	.show  = binary_vpcr_show,
+};
+
+static int ima_binary_vpcr_open(struct inode *inode, struct file *filp)
+{
+	struct user_namespace *user_ns = ima_user_ns_from_file(filp);
+	struct ima_namespace *ns = ima_ns_from_file(filp);
+
+	if (!ns->ima_tpm_chip)
+		return -ENODEV;
+
+	if (!ns_is_active(ns) || !mac_admin_ns_capable(user_ns))
+		return -EACCES;
+
+	return seq_open(filp, &binary_vpcr_seq_ops);
+}
+
+static const struct file_operations ima_binary_vpcr_fops = {
+	.open = ima_binary_vpcr_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = seq_release,
+};
+
+static void ascii_vpcr_stop(struct seq_file *m, void *v)
+{
+	int ret;
+	struct tpm_chip *tpm_chip;
+	struct tpm_digest pcr12_digest;
+	struct ima_namespace *curr_ns = ima_ns_from_file(m->file);
+
+	if (!vpcr_mutex_acquired)
+		return;
+
+	tpm_chip = curr_ns->ima_tpm_chip;
+	if (!tpm_chip)
+		goto ex;
+
+	pcr12_digest.alg_id = TPM_ALG_SHA256;
+	ret = tpm_pcr_read(tpm_chip, TPM_PCR12, &pcr12_digest);
+	if (ret != 0) {
+		seq_puts(m, "TPM read error\n");
+		goto ex;
+	}
+
+	/* 1st: PCR12 Prefix */
+	seq_printf(m, "\nPCR12: ");
+
+	/* 2nd: PCR12 Hash */
+	seq_printf(m, "%*phN", SHA256_DIGEST_SIZE, pcr12_digest.digest);
+	seq_printf(m, "\n");
+ex:
+	WRITE_ONCE(vpcr_mutex_acquired, false);
+	mutex_unlock(&vpcr_list_mutex);
+}
+
+static int ascii_vpcr_show(struct seq_file *m, void *v)
+{
+	struct vpcr_entry *vpcr = list_entry(v, struct vpcr_entry, list);
+	struct ima_namespace *curr_ns = container_of(vpcr, struct ima_namespace,
+						     vpcr);
+
+	if (!vpcr)
+		return -ENOENT;
+
+	/* 1st: cPCR Prefix */
+	seq_printf(m, "cPCR: ");
+
+	/* 2nd: cPCR UUID Value */
+	seq_printf(m, "%pUb ", &curr_ns->uuid);
+
+	/* 3rd: cPCR.Value XOR cPCR.Secret */
+	seq_printf(m, "%*phN", SHA256_DIGEST_SIZE, vpcr->vpcr_tmp);
+	seq_printf(m, "\n");
+
+	return 0;
+}
+
+const struct seq_operations ascii_vpcr_seq_ops = {
 	.start = vpcr_start,
 	.next  = vpcr_next,
-	.stop  = vpcr_stop,
-	.show  = vpcr_show,
+	.stop  = ascii_vpcr_stop,
+	.show  = ascii_vpcr_show,
 };
 
-static int ima_vpcr_open(struct inode *inode, struct file *filp)
+static int ima_ascii_vpcr_open(struct inode *inode, struct file *filp)
 {
 	struct user_namespace *user_ns = ima_user_ns_from_file(filp);
 	struct ima_namespace *ns = ima_ns_from_file(filp);
@@ -665,11 +749,11 @@  static int ima_vpcr_open(struct inode *inode, struct file *filp)
 	if (!ns_is_active(ns) || !mac_admin_ns_capable(user_ns))
 		return -EACCES;
 
-	return seq_open(filp, &vpcr_seq_ops);
+	return seq_open(filp, &ascii_vpcr_seq_ops);
 }
 
-static const struct file_operations ima_vpcr_fops = {
-	.open = ima_vpcr_open,
+static const struct file_operations ima_ascii_vpcr_fops = {
+	.open = ima_ascii_vpcr_open,
 	.read = seq_read,
 	.llseek = seq_lseek,
 	.release = seq_release,
@@ -686,7 +770,8 @@  int ima_fs_ns_init(struct user_namespace *user_ns, struct dentry *root)
 	struct dentry *runtime_measurements_count = NULL;
 	struct dentry *violations = NULL;
 	struct dentry *active = NULL;
-	struct dentry *vpcr = NULL;
+	struct dentry *binary_vpcr = NULL;
+	struct dentry *ascii_vpcr = NULL;
 	int ret;
 
 	/*
@@ -764,10 +849,21 @@  int ima_fs_ns_init(struct user_namespace *user_ns, struct dentry *root)
 	}
 
 	if (ns == &init_ima_ns) {
-		vpcr = securityfs_create_file("vpcr", S_IRUSR | S_IRGRP,
-					      ima_dir, NULL, &ima_vpcr_fops);
-		if (IS_ERR(vpcr)) {
-			ret = PTR_ERR(vpcr);
+		binary_vpcr =
+		    securityfs_create_file("binary_vpcr",
+					    S_IRUSR | S_IRGRP, ima_dir, NULL,
+					    &ima_binary_vpcr_fops);
+		if (IS_ERR(binary_vpcr)) {
+			ret = PTR_ERR(binary_vpcr);
+			goto out;
+		}
+
+		ascii_vpcr =
+		    securityfs_create_file("ascii_vpcr",
+					    S_IRUSR | S_IRGRP, ima_dir, NULL,
+					    &ima_ascii_vpcr_fops);
+		if (IS_ERR(ascii_vpcr)) {
+			ret = PTR_ERR(ascii_vpcr);
 			goto out;
 		}
 	}
@@ -799,7 +895,8 @@  int ima_fs_ns_init(struct user_namespace *user_ns, struct dentry *root)
 
 	return 0;
 out:
-	securityfs_remove(vpcr);
+	securityfs_remove(ascii_vpcr);
+	securityfs_remove(binary_vpcr);
 	securityfs_remove(active);
 	securityfs_remove(ns->ima_policy);
 	securityfs_remove(violations);