+ Policies: { "biba-strict" }
+
ima.ahash_minsize= [IMA] Minimum file size for asynchronous hash usage
Format: <min_file_size>
Set the minimal file size for using asynchronous hash.
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index d52b487ad259..377e1d8c2afb 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -36,6 +36,8 @@ enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN,
IMA_SHOW_BINARY_OLD_STRING_FMT, IMA_SHOW_ASCII };
enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 };
+enum integrity_policies { BIBA_STRICT = 1, INTEGRITY_POLICY__LAST };
+
/* digest size for IMA, fits SHA1 or MD5 */
#define IMA_DIGEST_SIZE SHA1_DIGEST_SIZE
#define IMA_EVENT_NAME_LEN_MAX 255
@@ -57,6 +59,7 @@ extern int ima_initialized;
extern int ima_used_chip;
extern int ima_hash_algo;
extern int ima_appraise;
+extern int ima_integrity_policy;
/* IMA event related data */
struct ima_event_data {
@@ -247,6 +250,11 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
int xattr_len);
int ima_read_xattr(struct dentry *dentry,
struct evm_ima_xattr_data **xattr_value);
+bool ima_inode_is_appraised(struct dentry *dentry, struct inode *inode);
+bool ima_appraise_biba_check(struct file *file,
+ struct integrity_iint_cache *iint,
+ int must_appraise, char **pathbuf,
+ const char **pathname, char *namebuf);
#else
static inline int ima_appraise_measurement(enum ima_hooks func,
@@ -289,6 +297,21 @@ static inline int ima_read_xattr(struct dentry *dentry,
return 0;
}
+static inline bool ima_inode_is_appraised(struct dentry *dentry,
+ struct inode *inode);
+{
+ return false;
+}
+
+static inline bool ima_appraise_biba_check(struct file *file,
+ struct integrity_iint_cache *iint,
+ int must_appraise, char **pathbuf,
+ const char **pathname,
+ char *namebuf)
+{
+ return false;
+}
+
#endif /* CONFIG_IMA_APPRAISE */
/* LSM based policy rules require audit */
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 809ba70fbbbf..c24824ef64c4 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -18,6 +18,10 @@
#include "ima.h"
+static char *ima_integrity_policies_str[INTEGRITY_POLICY__LAST] = {
+ [BIBA_STRICT] = "biba-strict",
+};
+
static int __init default_appraise_setup(char *str)
{
#ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
@@ -33,6 +37,15 @@ static int __init default_appraise_setup(char *str)
__setup("ima_appraise=", default_appraise_setup);
+static int __init integrity_policy_setup(char *str)
+{
+ if (strcmp(str, ima_integrity_policies_str[BIBA_STRICT]) == 0)
+ ima_integrity_policy = BIBA_STRICT;
+
+ return 1;
+}
+__setup("ima_integrity_policy=", integrity_policy_setup);
+
/*
* is_ima_appraise_enabled - return appraise status
*
@@ -189,6 +202,54 @@ int ima_read_xattr(struct dentry *dentry,
return ret;
}
+bool ima_inode_is_appraised(struct dentry *dentry, struct inode *inode)
+{
+ ssize_t len;
+
+ len = __vfs_getxattr(dentry, inode, XATTR_NAME_IMA, NULL, 0);
+
+ return (len > 0 && len >= sizeof(struct evm_ima_xattr_data));
+}
+
+/*
+ * ima_appraise_biba_check - detect violations of a Biba policy
+ *
+ * The appraisal policy identifies which subjects belong to the TCB. Files
+ * with a valid digital signature or HMAC are also part of the TCB. This
+ * function detects attempts to write appraised files by subjects outside
+ * the TCB. The Biba strict policy denies this operation.
+ *
+ * Return: true if current operation violates a Biba policy, false otherwise
+ */
+bool ima_appraise_biba_check(struct file *file,
+ struct integrity_iint_cache *iint,
+ int must_appraise, char **pathbuf,
+ const char **pathname, char *namebuf)
+{
+ struct inode *inode = file_inode(file);
+ fmode_t mode = file->f_mode;
+ char *cause = "write_down";
+
+ /* check write up, ima_appraise_measurement() checks read down */
+ if (!must_appraise && (mode & FMODE_WRITE)) {
+ if (IS_IMA(inode)) {
+ if (!iint)
+ iint = integrity_iint_find(inode);
+ if (iint->flags & IMA_APPRAISE)
+ goto out_violation;
+ } else if (ima_inode_is_appraised(file_dentry(file), inode)) {
+ goto out_violation;
+ }
+ }
+ return false;
+out_violation:
+ *pathname = ima_d_path(&file->f_path, pathbuf, namebuf);
+ integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, *pathname,
+ ima_integrity_policies_str[ima_integrity_policy],
+ cause, 0, 0);
+ return true;
+}
+
/*
* ima_appraise_measurement - appraise file measurement
*
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index bb7e36e90c79..6e85ea8e2373 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -31,6 +31,7 @@ int ima_initialized;
#ifdef CONFIG_IMA_APPRAISE
int ima_appraise = IMA_APPRAISE_ENFORCE;
+int ima_integrity_policy;
#else
int ima_appraise;
#endif
@@ -103,7 +104,8 @@ static void ima_rdwr_violation_check(struct file *file,
if (!send_tomtou && !send_writers)
return;
- *pathname = ima_d_path(&file->f_path, pathbuf, filename);
+ if (!*pathname)
+ *pathname = ima_d_path(&file->f_path, pathbuf, filename);
if (send_tomtou)
ima_add_violation(file, *pathname, iint,
@@ -168,7 +170,7 @@ static int process_measurement(struct file *file, char *buf, loff_t size,
int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
struct evm_ima_xattr_data *xattr_value = NULL;
int xattr_len = 0;
- bool violation_check;
+ bool violation_check, policy_violation = false;
enum hash_algo hash_algo;
if (!ima_policy_flag || !S_ISREG(inode->i_mode))
@@ -181,7 +183,7 @@ static int process_measurement(struct file *file, char *buf, loff_t size,
action = ima_get_action(inode, mask, func, &pcr);
violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
(ima_policy_flag & IMA_MEASURE));
- if (!action && !violation_check)
+ if (!action && !violation_check && !ima_integrity_policy)
return 0;
must_appraise = action & IMA_APPRAISE;
@@ -198,13 +200,16 @@ static int process_measurement(struct file *file, char *buf, loff_t size,
goto out;
}
- if (violation_check) {
+ if (ima_integrity_policy)
+ policy_violation = ima_appraise_biba_check(file, iint,
+ must_appraise, &pathbuf,
+ &pathname, filename);
+ if (violation_check)
ima_rdwr_violation_check(file, iint, action & IMA_MEASURE,
&pathbuf, &pathname);
- if (!action) {
- rc = 0;
- goto out_free;
- }
+ if (!action) {
+ rc = 0;
+ goto out_free;
}
/* Determine if already appraised/measured based on bitmask
@@ -260,7 +265,9 @@ static int process_measurement(struct file *file, char *buf, loff_t size,
__putname(pathbuf);
out:
inode_unlock(inode);
- if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE))
+ if (((rc && must_appraise) ||
+ (ima_integrity_policy && policy_violation)) &&
+ (ima_appraise & IMA_APPRAISE_ENFORCE))
return -EACCES;
return 0;
}