ima: support for kexec image and initramfs

Add IMA policy support for measuring/appraising the kexec image and
initramfs. Two new IMA policy identifiers KEXEC_KERNEL_CHECK and
KEXEC_INITRAMFS_CHECK are defined.

Example policy rules:
measure func=KEXEC_KERNEL_CHECK
appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig
measure func=KEXEC_INITRAMFS_CHECK
appraise func=KEXEC_INITRAMFS_CHECK appraise_type=imasig

Moving the enumeration to the vfs layer simplified the patches, allowing
the IMA changes, for the most part, to be separated from the other
changes.  Unfortunately, passing either a kernel_read_file_id or a
ima_hooks enumeration within IMA is messy.

Option 1: duplicate kernel_read_file enumeration in ima_hooks

enum kernel_read_file_id {
	...
        READING_KEXEC_IMAGE,
        READING_KEXEC_INITRAMFS,
        READING_MAX_ID

enum ima_hooks {
	...
	KEXEC_KERNEL_CHECK
	KEXEC_INITRAMFS_CHECK

Option 2: define ima_hooks as extension of kernel_read_file
eg: enum ima_hooks {
        FILE_CHECK = READING_MAX_ID,
        MMAP_CHECK,

In order to pass both kernel_read_file_id and ima_hooks values, we
would need to specify a struct containing a union.

struct caller_id {
        union {
                enum ima_hooks func_id;
                enum kernel_read_file_id read_id;
        };
};

Option 3: incorportate the ima_hooks enumeration into kernel_read_file_id,
perhaps changing the enumeration name.

For now, duplicate the new READING_KEXEC_IMAGE/INITRAMFS in the ima_hooks.

Changelog v4:
- replaced switch statement with a kernel_read_file_id to an ima_hooks
id mapping array - Dmitry
- renamed ima_hook tokens KEXEC_CHECK and INITRAMFS_CHECK to
KEXEC_KERNEL_CHECK and KEXEC_INITRAMFS_CHECK respectively - Dave Young

Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Acked-by: Petko Manolov <petkan@mip-labs.com>
Acked-by: Dmitry Kasatkin <dmitry.kasatkin@huawei.com>
Cc: Dave Young <dyoung@redhat.com>
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 5da0b9c..f764881 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -339,6 +339,13 @@
 	return 0;
 }
 
+static int read_idmap[READING_MAX_ID] = {
+	[READING_FIRMWARE] = FIRMWARE_CHECK,
+	[READING_MODULE] = MODULE_CHECK,
+	[READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK,
+	[READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK,
+};
+
 /**
  * ima_post_read_file - in memory collect/appraise/audit measurement
  * @file: pointer to the file to be measured/appraised/audit
@@ -355,7 +362,7 @@
 int ima_post_read_file(struct file *file, void *buf, loff_t size,
 		       enum kernel_read_file_id read_id)
 {
-	enum ima_hooks func = FILE_CHECK;
+	enum ima_hooks func;
 
 	if (!file && read_id == READING_FIRMWARE) {
 		if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
@@ -373,11 +380,7 @@
 		return 0;
 	}
 
-	if (read_id == READING_FIRMWARE)
-		func = FIRMWARE_CHECK;
-	else if (read_id == READING_MODULE)
-		func = MODULE_CHECK;
-
+	func = read_idmap[read_id] ?: FILE_CHECK;
 	return process_measurement(file, buf, size, MAY_READ, func, 0);
 }