|
|
@@ -24,7 +24,6 @@
|
|
|
#include <linux/slab.h>
|
|
|
#include <linux/xattr.h>
|
|
|
#include <linux/ima.h>
|
|
|
-#include <crypto/hash_info.h>
|
|
|
|
|
|
#include "ima.h"
|
|
|
|
|
|
@@ -154,8 +153,8 @@ void ima_file_free(struct file *file)
|
|
|
ima_check_last_writer(iint, inode, file);
|
|
|
}
|
|
|
|
|
|
-static int process_measurement(struct file *file, int mask, int function,
|
|
|
- int opened)
|
|
|
+static int process_measurement(struct file *file, char *buf, loff_t size,
|
|
|
+ int mask, enum ima_hooks func, int opened)
|
|
|
{
|
|
|
struct inode *inode = file_inode(file);
|
|
|
struct integrity_iint_cache *iint = NULL;
|
|
|
@@ -163,9 +162,10 @@ static int process_measurement(struct file *file, int mask, int function,
|
|
|
char *pathbuf = NULL;
|
|
|
const char *pathname = NULL;
|
|
|
int rc = -ENOMEM, action, must_appraise;
|
|
|
- struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL;
|
|
|
+ struct evm_ima_xattr_data *xattr_value = NULL;
|
|
|
int xattr_len = 0;
|
|
|
bool violation_check;
|
|
|
+ enum hash_algo hash_algo;
|
|
|
|
|
|
if (!ima_policy_flag || !S_ISREG(inode->i_mode))
|
|
|
return 0;
|
|
|
@@ -174,8 +174,8 @@ static int process_measurement(struct file *file, int mask, int function,
|
|
|
* bitmask based on the appraise/audit/measurement policy.
|
|
|
* Included is the appraise submask.
|
|
|
*/
|
|
|
- action = ima_get_action(inode, mask, function);
|
|
|
- violation_check = ((function == FILE_CHECK || function == MMAP_CHECK) &&
|
|
|
+ action = ima_get_action(inode, mask, func);
|
|
|
+ violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
|
|
|
(ima_policy_flag & IMA_MEASURE));
|
|
|
if (!action && !violation_check)
|
|
|
return 0;
|
|
|
@@ -184,7 +184,7 @@ static int process_measurement(struct file *file, int mask, int function,
|
|
|
|
|
|
/* Is the appraise rule hook specific? */
|
|
|
if (action & IMA_FILE_APPRAISE)
|
|
|
- function = FILE_CHECK;
|
|
|
+ func = FILE_CHECK;
|
|
|
|
|
|
inode_lock(inode);
|
|
|
|
|
|
@@ -214,16 +214,19 @@ static int process_measurement(struct file *file, int mask, int function,
|
|
|
/* Nothing to do, just return existing appraised status */
|
|
|
if (!action) {
|
|
|
if (must_appraise)
|
|
|
- rc = ima_get_cache_status(iint, function);
|
|
|
+ rc = ima_get_cache_status(iint, func);
|
|
|
goto out_digsig;
|
|
|
}
|
|
|
|
|
|
template_desc = ima_template_desc_current();
|
|
|
if ((action & IMA_APPRAISE_SUBMASK) ||
|
|
|
strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0)
|
|
|
- xattr_ptr = &xattr_value;
|
|
|
+ /* read 'security.ima' */
|
|
|
+ xattr_len = ima_read_xattr(file->f_path.dentry, &xattr_value);
|
|
|
|
|
|
- rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len);
|
|
|
+ hash_algo = ima_get_hash_algo(xattr_value, xattr_len);
|
|
|
+
|
|
|
+ rc = ima_collect_measurement(iint, file, buf, size, hash_algo);
|
|
|
if (rc != 0) {
|
|
|
if (file->f_flags & O_DIRECT)
|
|
|
rc = (iint->flags & IMA_PERMIT_DIRECTIO) ? 0 : -EACCES;
|
|
|
@@ -237,7 +240,7 @@ static int process_measurement(struct file *file, int mask, int function,
|
|
|
ima_store_measurement(iint, file, pathname,
|
|
|
xattr_value, xattr_len);
|
|
|
if (action & IMA_APPRAISE_SUBMASK)
|
|
|
- rc = ima_appraise_measurement(function, iint, file, pathname,
|
|
|
+ rc = ima_appraise_measurement(func, iint, file, pathname,
|
|
|
xattr_value, xattr_len, opened);
|
|
|
if (action & IMA_AUDIT)
|
|
|
ima_audit_measurement(iint, pathname);
|
|
|
@@ -270,7 +273,8 @@ out:
|
|
|
int ima_file_mmap(struct file *file, unsigned long prot)
|
|
|
{
|
|
|
if (file && (prot & PROT_EXEC))
|
|
|
- return process_measurement(file, MAY_EXEC, MMAP_CHECK, 0);
|
|
|
+ return process_measurement(file, NULL, 0, MAY_EXEC,
|
|
|
+ MMAP_CHECK, 0);
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
@@ -289,7 +293,8 @@ int ima_file_mmap(struct file *file, unsigned long prot)
|
|
|
*/
|
|
|
int ima_bprm_check(struct linux_binprm *bprm)
|
|
|
{
|
|
|
- return process_measurement(bprm->file, MAY_EXEC, BPRM_CHECK, 0);
|
|
|
+ return process_measurement(bprm->file, NULL, 0, MAY_EXEC,
|
|
|
+ BPRM_CHECK, 0);
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -304,24 +309,26 @@ int ima_bprm_check(struct linux_binprm *bprm)
|
|
|
*/
|
|
|
int ima_file_check(struct file *file, int mask, int opened)
|
|
|
{
|
|
|
- return process_measurement(file,
|
|
|
+ return process_measurement(file, NULL, 0,
|
|
|
mask & (MAY_READ | MAY_WRITE | MAY_EXEC),
|
|
|
FILE_CHECK, opened);
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(ima_file_check);
|
|
|
|
|
|
/**
|
|
|
- * ima_module_check - based on policy, collect/store/appraise measurement.
|
|
|
- * @file: pointer to the file to be measured/appraised
|
|
|
+ * ima_read_file - pre-measure/appraise hook decision based on policy
|
|
|
+ * @file: pointer to the file to be measured/appraised/audit
|
|
|
+ * @read_id: caller identifier
|
|
|
*
|
|
|
- * Measure/appraise kernel modules based on policy.
|
|
|
+ * Permit reading a file based on policy. The policy rules are written
|
|
|
+ * in terms of the policy identifier. Appraising the integrity of
|
|
|
+ * a file requires a file descriptor.
|
|
|
*
|
|
|
- * On success return 0. On integrity appraisal error, assuming the file
|
|
|
- * is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
|
|
|
+ * For permission return 0, otherwise return -EACCES.
|
|
|
*/
|
|
|
-int ima_module_check(struct file *file)
|
|
|
+int ima_read_file(struct file *file, enum kernel_read_file_id read_id)
|
|
|
{
|
|
|
- if (!file) {
|
|
|
+ if (!file && read_id == READING_MODULE) {
|
|
|
#ifndef CONFIG_MODULE_SIG_FORCE
|
|
|
if ((ima_appraise & IMA_APPRAISE_MODULES) &&
|
|
|
(ima_appraise & IMA_APPRAISE_ENFORCE))
|
|
|
@@ -329,18 +336,53 @@ int ima_module_check(struct file *file)
|
|
|
#endif
|
|
|
return 0; /* We rely on module signature checking */
|
|
|
}
|
|
|
- return process_measurement(file, MAY_EXEC, MODULE_CHECK, 0);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
-int ima_fw_from_file(struct file *file, char *buf, size_t size)
|
|
|
+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,
|
|
|
+ [READING_POLICY] = POLICY_CHECK
|
|
|
+};
|
|
|
+
|
|
|
+/**
|
|
|
+ * ima_post_read_file - in memory collect/appraise/audit measurement
|
|
|
+ * @file: pointer to the file to be measured/appraised/audit
|
|
|
+ * @buf: pointer to in memory file contents
|
|
|
+ * @size: size of in memory file contents
|
|
|
+ * @read_id: caller identifier
|
|
|
+ *
|
|
|
+ * Measure/appraise/audit in memory file based on policy. Policy rules
|
|
|
+ * are written in terms of a policy identifier.
|
|
|
+ *
|
|
|
+ * On success return 0. On integrity appraisal error, assuming the file
|
|
|
+ * is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
|
|
|
+ */
|
|
|
+int ima_post_read_file(struct file *file, void *buf, loff_t size,
|
|
|
+ enum kernel_read_file_id read_id)
|
|
|
{
|
|
|
- if (!file) {
|
|
|
+ enum ima_hooks func;
|
|
|
+
|
|
|
+ if (!file && read_id == READING_FIRMWARE) {
|
|
|
if ((ima_appraise & IMA_APPRAISE_FIRMWARE) &&
|
|
|
(ima_appraise & IMA_APPRAISE_ENFORCE))
|
|
|
return -EACCES; /* INTEGRITY_UNKNOWN */
|
|
|
return 0;
|
|
|
}
|
|
|
- return process_measurement(file, MAY_EXEC, FIRMWARE_CHECK, 0);
|
|
|
+
|
|
|
+ if (!file && read_id == READING_MODULE) /* MODULE_SIG_FORCE enabled */
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (!file || !buf || size == 0) { /* should never happen */
|
|
|
+ if (ima_appraise & IMA_APPRAISE_ENFORCE)
|
|
|
+ return -EACCES;
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ func = read_idmap[read_id] ?: FILE_CHECK;
|
|
|
+ return process_measurement(file, buf, size, MAY_READ, func, 0);
|
|
|
}
|
|
|
|
|
|
static int __init init_ima(void)
|