linux-integrity.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] integrity: make 'sync' update the inode integrity state
@ 2019-04-10 14:56 Janne Karhunen
  2019-04-11 13:03 ` Mimi Zohar
  0 siblings, 1 reply; 10+ messages in thread
From: Janne Karhunen @ 2019-04-10 14:56 UTC (permalink / raw)
  To: zohar, linux-integrity; +Cc: Janne Karhunen, Janne Karhunen

From: Janne Karhunen <Janne.Karhunen@gmail.com>

When a file is open for writing, kernel crash or power outage
is guaranteed to corrupt inode integrity state leading to file
appraisal failure on the subsequent boot. Allow applications
to be designed with integrity measurements in mind by making
sure the integrity state is recomputed when sync(fd) is
intentionally called for the open file.

Signed-off-by: Janne Karhunen <janne.karhunen@gmail.com>
---
 fs/sync.c                         |  3 +++
 include/linux/ima.h               |  1 +
 include/linux/lsm_hooks.h         |  5 +++++
 include/linux/security.h          |  6 ++++++
 security/integrity/ima/ima_main.c | 31 ++++++++++++++++++++++++++++++-
 security/security.c               |  5 +++++
 6 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/fs/sync.c b/fs/sync.c
index b54e0541ad89..6c01f1970eac 100644
--- a/fs/sync.c
+++ b/fs/sync.c
@@ -16,6 +16,7 @@
 #include <linux/pagemap.h>
 #include <linux/quotaops.h>
 #include <linux/backing-dev.h>
+#include <linux/security.h>
 #include "internal.h"
 
 #define VALID_FLAGS (SYNC_FILE_RANGE_WAIT_BEFORE|SYNC_FILE_RANGE_WRITE| \
@@ -194,6 +195,8 @@ int vfs_fsync_range(struct file *file, loff_t start, loff_t end, int datasync)
 		return -EINVAL;
 	if (!datasync && (inode->i_state & I_DIRTY_TIME))
 		mark_inode_dirty_sync(inode);
+	security_file_sync(file);
+
 	return file->f_op->fsync(file, start, end, datasync);
 }
 EXPORT_SYMBOL(vfs_fsync_range);
diff --git a/include/linux/ima.h b/include/linux/ima.h
index dc12fbcf484c..dbd6c56ae7e1 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -20,6 +20,7 @@ extern int ima_bprm_check(struct linux_binprm *bprm);
 extern int ima_file_check(struct file *file, int mask);
 extern void ima_post_create_tmpfile(struct inode *inode);
 extern void ima_file_free(struct file *file);
+extern void ima_file_update(struct file *file);
 extern int ima_file_mmap(struct file *file, unsigned long prot);
 extern int ima_load_data(enum kernel_load_data_id id);
 extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index a9b8ff578b6b..196a04d06fb6 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -541,6 +541,9 @@
  *	Save open-time permission checking state for later use upon
  *	file_permission, and recheck access if anything has changed
  *	since inode_permission.
+ * @file_sync:
+ *	Called when sync is being requested for file. Primary use is to make
+ *	sure integrity measurement of the file is kept in sync with the data.
  *
  * Security hooks for task operations.
  *
@@ -1596,6 +1599,7 @@ union security_list_options {
 					struct fown_struct *fown, int sig);
 	int (*file_receive)(struct file *file);
 	int (*file_open)(struct file *file);
+	void (*file_sync)(struct file *file);
 
 	int (*task_alloc)(struct task_struct *task, unsigned long clone_flags);
 	void (*task_free)(struct task_struct *task);
@@ -1892,6 +1896,7 @@ struct security_hook_heads {
 	struct hlist_head file_send_sigiotask;
 	struct hlist_head file_receive;
 	struct hlist_head file_open;
+	struct hlist_head file_sync;
 	struct hlist_head task_alloc;
 	struct hlist_head task_free;
 	struct hlist_head cred_alloc_blank;
diff --git a/include/linux/security.h b/include/linux/security.h
index 49f2685324b0..467cfa02f9f6 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -315,6 +315,7 @@ int security_file_send_sigiotask(struct task_struct *tsk,
 				 struct fown_struct *fown, int sig);
 int security_file_receive(struct file *file);
 int security_file_open(struct file *file);
+void security_file_sync(struct file *file);
 int security_task_alloc(struct task_struct *task, unsigned long clone_flags);
 void security_task_free(struct task_struct *task);
 int security_cred_alloc_blank(struct cred *cred, gfp_t gfp);
@@ -876,6 +877,11 @@ static inline int security_file_open(struct file *file)
 	return 0;
 }
 
+static inline void security_file_sync(struct file *file)
+{
+	return;
+}
+
 static inline int security_task_alloc(struct task_struct *task,
 				      unsigned long clone_flags)
 {
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 357edd140c09..e60b878d8356 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -16,7 +16,7 @@
  *
  * File: ima_main.c
  *	implements the IMA hooks: ima_bprm_check, ima_file_mmap,
- *	and ima_file_check.
+ *	ima_file_update and ima_file_check.
  */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -375,6 +375,35 @@ int ima_bprm_check(struct linux_binprm *bprm)
 				   MAY_EXEC, CREDS_CHECK);
 }
 
+/**
+ * ima_file_update - called from sync to update xattrs
+ * @file: pointer to file structure being updated
+ */
+void ima_file_update(struct file *file)
+{
+	struct inode *inode = file_inode(file);
+	struct integrity_iint_cache *iint;
+
+	if (!ima_policy_flag || !S_ISREG(inode->i_mode))
+		return;
+
+	iint = integrity_iint_find(inode);
+	if (!iint)
+		return;
+
+	mutex_lock(&iint->mutex);
+	if (atomic_read(&inode->i_writecount) == 1) {
+		clear_bit(IMA_UPDATE_XATTR, &iint->atomic_flags);
+		if (!IS_I_VERSION(inode) ||
+		    !inode_eq_iversion(inode, iint->version)) {
+			iint->flags &= ~IMA_COLLECTED;
+			ima_update_xattr(iint, file);
+		}
+	}
+	mutex_unlock(&iint->mutex);
+}
+EXPORT_SYMBOL_GPL(ima_file_update);
+
 /**
  * ima_path_check - based on policy, collect/store measurement.
  * @file: pointer to the file to be measured
diff --git a/security/security.c b/security/security.c
index 23cbb1a295a3..6a0980a1df22 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1451,6 +1451,11 @@ int security_file_open(struct file *file)
 	return fsnotify_perm(file, MAY_OPEN);
 }
 
+void security_file_sync(struct file *file)
+{
+	ima_file_update(file);
+}
+
 int security_task_alloc(struct task_struct *task, unsigned long clone_flags)
 {
 	int rc = lsm_task_alloc(task);
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2019-05-07 12:43 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-10 14:56 [PATCH] integrity: make 'sync' update the inode integrity state Janne Karhunen
2019-04-11 13:03 ` Mimi Zohar
2019-04-11 14:10   ` Janne Karhunen
     [not found]     ` <CAE=NcraxAJum=Uk77BoPXVkBDk3rwmXh80mLxy6pxrtUW_hpQg@mail.gmail.com>
     [not found]       ` <1556805843.4134.15.camel@linux.ibm.com>
     [not found]         ` <CAE=Ncrb4unTxeU=2jLb-KTqKXpK98vGFbrOxdcnjdfD_Ddk8ug@mail.gmail.com>
     [not found]           ` <1556884105.4754.18.camel@linux.ibm.com>
2019-05-06 13:17             ` Janne Karhunen
2019-05-07 12:42               ` Janne Karhunen
2019-04-12 12:40   ` Janne Karhunen
2019-04-25 10:05     ` Janne Karhunen
2019-04-25 12:14       ` Mimi Zohar
2019-04-25 12:46         ` Janne Karhunen
2019-05-03 11:48   ` Mimi Zohar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).