diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 05496622b4ef..6d184a94ba20 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1532,6 +1532,10 @@
 	                [IMA] Define a custom template format.
 			Format: { "field1|...|fieldN" }
 
+	ima_integrity_model=
+			[IMA] Select an integrity model.
+			Models: { "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 f2cdd528f8ff..b9fdf0264c9d 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_models { 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
@@ -58,6 +60,7 @@ extern int ima_used_chip;
 extern int ima_hash_algo;
 extern int ima_appraise;
 extern struct path ima_null;
+extern int ima_integrity_model;
 
 /* IMA event related data */
 struct ima_event_data {
@@ -249,6 +252,10 @@ 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_appraise_integrity_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,
@@ -291,6 +298,15 @@ static inline int ima_read_xattr(struct dentry *dentry,
 	return 0;
 }
 
+static inline bool ima_appraise_integrity_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 23e025e86aed..27bbf48596cb 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -18,6 +18,12 @@
 
 #include "ima.h"
 
+int ima_integrity_model;
+
+static char *ima_integrity_models_str[INTEGRITY_POLICY__LAST] = {
+	[BIBA_STRICT] = "biba-strict",
+};
+
 static int __init default_appraise_setup(char *str)
 {
 #ifdef CONFIG_IMA_APPRAISE_BOOTPARAM
@@ -33,6 +39,27 @@ static int __init default_appraise_setup(char *str)
 
 __setup("ima_appraise=", default_appraise_setup);
 
+static int __init integrity_model_setup(char *str)
+{
+	int i;
+
+	for (i = BIBA_STRICT; i < INTEGRITY_POLICY__LAST; i++) {
+		if (strcmp(str, ima_integrity_models_str[i]) == 0) {
+			ima_integrity_model = i;
+			break;
+		}
+	}
+
+	if (i == INTEGRITY_POLICY__LAST) {
+		pr_err("Invalid model %s, using %s\n", str,
+		       ima_integrity_models_str[BIBA_STRICT]);
+		ima_integrity_model = BIBA_STRICT;
+	}
+
+	return 1;
+}
+__setup("ima_integrity_model=", integrity_model_setup);
+
 /*
  * is_ima_appraise_enabled - return appraise status
  *
@@ -197,6 +224,80 @@ 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_integrity_check - detect violations of an integrity 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 enforces constraints of the selected integrity model.
+ *
+ * Conventions:
+ * - must_appraise: true (TCB subject), false (non-TCB subject)
+ * - iint status: INTEGRITY_PASS (TCB object), other values (non-TCB object)
+ *
+ * Constraints:
+ * - write down: TCB object can be written only by TCB subject
+ * - read up: TCB subject can read only TCB objects
+ *
+ * Integrity models:
+ * - biba-strict: write down, read up
+ *
+ * Return: true if constraints are violated, false otherwise
+ */
+bool ima_appraise_integrity_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_violation";
+	int expected_writecount = (mode & FMODE_WRITE) ? 1 : 0;
+
+	/* check write down violations */
+	if (!must_appraise && (mode & FMODE_WRITE)) {
+		if (IS_IMA(inode)) {
+			if (!iint)
+				iint = integrity_iint_find(inode);
+			if (iint->flags & IMA_APPRAISED)
+				goto out_violation;
+		} else if (ima_inode_is_appraised(file_dentry(file), inode)) {
+			goto out_violation;
+		}
+	/* concurrent write to non-TCB object by non-TCB subjects */
+	} else if (must_appraise && !(iint->flags & IMA_APPRAISED) &&
+		   atomic_read(&inode->i_writecount) > expected_writecount) {
+		/* updating security.ima will cause a write down violation */
+		if (mode & FMODE_WRITE) {
+			cause = "write_down_violation_tcb";
+			goto out_violation;
+		}
+
+		/* check read up violations */
+		if (mode & (FMODE_READ | FMODE_EXEC)) {
+			cause = "read_up_violation";
+			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_models_str[ima_integrity_model],
+			    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 a12f8a148e5e..ee9897c8d0cc 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -108,7 +108,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,
@@ -181,7 +182,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
 	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, model_violation = false;
 	enum hash_algo hash_algo;
 
 	if (!ima_policy_flag || !S_ISREG(inode->i_mode))
@@ -194,7 +195,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
 	action = ima_get_action(inode, cred, 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_model)
 		return 0;
 
 	must_appraise = action & IMA_APPRAISE;
@@ -211,13 +212,21 @@ static int process_measurement(struct file *file, const struct cred *cred,
 			goto out;
 	}
 
-	if (violation_check) {
+	if (ima_integrity_model) {
+		model_violation = ima_appraise_integrity_check(file, iint,
+							must_appraise, &pathbuf,
+							&pathname, filename);
+		/* access will be denied */
+		if (model_violation)
+			action &= ~IMA_APPRAISE;
+	}
+
+	if (violation_check)
 		ima_rdwr_violation_check(file, iint, action & IMA_MEASURE,
 					 &pathbuf, &pathname, filename);
-		if (!action) {
-			rc = 0;
-			goto out_free;
-		}
+	if (!action) {
+		rc = 0;
+		goto out_free;
 	}
 
 	/* Determine if already appraised/measured based on bitmask
@@ -275,7 +284,9 @@ static int process_measurement(struct file *file, const struct cred *cred,
 		__putname(pathbuf);
 out:
 	inode_unlock(inode);
-	if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE))
+	if (((rc && must_appraise) ||
+	    (ima_integrity_model && model_violation)) &&
+	    (ima_appraise & IMA_APPRAISE_ENFORCE))
 		return -EACCES;
 	return 0;
 }
