blob: 6ab7ce277c6b6e762a6b20b968405e60737e5021 [file] [log] [blame]
Brad Bishop15ae2502019-06-18 21:44:24 -04001From baaec960e9e7be0b526eaf831b079ddfe5c15124 Mon Sep 17 00:00:00 2001
2From: Mimi Zohar <zohar@linux.vnet.ibm.com>
3Date: Thu, 10 Mar 2016 18:19:20 +0200
4Subject: [PATCH] ima: add support for creating files using the mknodat
5 syscall
6
7Commit 3034a14 "ima: pass 'opened' flag to identify newly created files"
8stopped identifying empty files as new files. However new empty files
9can be created using the mknodat syscall. On systems with IMA-appraisal
10enabled, these empty files are not labeled with security.ima extended
11attributes properly, preventing them from subsequently being opened in
12order to write the file data contents. This patch marks these empty
13files, created using mknodat, as new in order to allow the file data
14contents to be written.
15
16Files with security.ima xattrs containing a file signature are considered
17"immutable" and can not be modified. The file contents need to be
18written, before signing the file. This patch relaxes this requirement
19for new files, allowing the file signature to be written before the file
20contents.
21
22Upstream-Status: Accepted [https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/security/integrity/ima/ima_appraise.c?id=05d1a717ec0430c916a749b94eb90ab74bbfa356]
23
24Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
25---
26 fs/namei.c | 2 ++
27 include/linux/ima.h | 7 ++++++-
28 security/integrity/ima/ima_appraise.c | 3 +++
29 security/integrity/ima/ima_main.c | 32 +++++++++++++++++++++++++++++++-
30 4 files changed, 42 insertions(+), 2 deletions(-)
31
32diff --git a/fs/namei.c b/fs/namei.c
33index ccd7f98..19502da 100644
34--- a/fs/namei.c
35+++ b/fs/namei.c
36@@ -3526,6 +3526,8 @@ retry:
37 switch (mode & S_IFMT) {
38 case 0: case S_IFREG:
39 error = vfs_create(path.dentry->d_inode,dentry,mode,true);
40+ if (!error)
41+ ima_post_path_mknod(dentry);
42 break;
43 case S_IFCHR: case S_IFBLK:
44 error = vfs_mknod(path.dentry->d_inode,dentry,mode,
45diff --git a/include/linux/ima.h b/include/linux/ima.h
46index 120ccc5..7f51971 100644
47--- a/include/linux/ima.h
48+++ b/include/linux/ima.h
49@@ -20,7 +20,7 @@ extern void ima_file_free(struct file *file);
50 extern int ima_file_mmap(struct file *file, unsigned long prot);
51 extern int ima_module_check(struct file *file);
52 extern int ima_fw_from_file(struct file *file, char *buf, size_t size);
53-
54+extern void ima_post_path_mknod(struct dentry *dentry);
55 #else
56 static inline int ima_bprm_check(struct linux_binprm *bprm)
57 {
58@@ -52,6 +52,11 @@ static inline int ima_fw_from_file(struct file *file, char *buf, size_t size)
59 return 0;
60 }
61
62+static inline void ima_post_path_mknod(struct dentry *dentry)
63+{
64+ return;
65+}
66+
67 #endif /* CONFIG_IMA */
68
69 #ifdef CONFIG_IMA_APPRAISE
70diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
71index 4df493e..20806ea 100644
72--- a/security/integrity/ima/ima_appraise.c
73+++ b/security/integrity/ima/ima_appraise.c
74@@ -274,6 +274,11 @@ out:
75 xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
76 if (!ima_fix_xattr(dentry, iint))
77 status = INTEGRITY_PASS;
78+ } else if ((inode->i_size == 0) &&
79+ (iint->flags & IMA_NEW_FILE) &&
80+ (xattr_value &&
81+ xattr_value->type == EVM_IMA_XATTR_DIGSIG)) {
82+ status = INTEGRITY_PASS;
83 }
84 integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
85 op, cause, rc, 0);
86diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
87index eeee00dc..705bf78 100644
88--- a/security/integrity/ima/ima_main.c
89+++ b/security/integrity/ima/ima_main.c
90@@ -242,7 +242,8 @@ static int process_measurement(struct file *file, int mask, int function,
91 ima_audit_measurement(iint, pathname);
92
93 out_digsig:
94- if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG))
95+ if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG) &&
96+ !(iint->flags & IMA_NEW_FILE))
97 rc = -EACCES;
98 kfree(xattr_value);
99 out_free:
100@@ -310,6 +311,35 @@ int ima_file_check(struct file *file, int mask, int opened)
101 EXPORT_SYMBOL_GPL(ima_file_check);
102
103 /**
104+ * ima_post_path_mknod - mark as a new inode
105+ * @dentry: newly created dentry
106+ *
107+ * Mark files created via the mknodat syscall as new, so that the
108+ * file data can be written later.
109+ */
110+void ima_post_path_mknod(struct dentry *dentry)
111+{
112+ struct integrity_iint_cache *iint;
113+ struct inode *inode;
114+ int must_appraise;
115+
116+ if (!dentry || !dentry->d_inode)
117+ return;
118+
119+ inode = dentry->d_inode;
120+ if (inode->i_size != 0)
121+ return;
122+
123+ must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK);
124+ if (!must_appraise)
125+ return;
126+
127+ iint = integrity_inode_get(inode);
128+ if (iint)
129+ iint->flags |= IMA_NEW_FILE;
130+}
131+
132+/**
133 * ima_module_check - based on policy, collect/store/appraise measurement.
134 * @file: pointer to the file to be measured/appraised
135 *
136--
1372.5.0
138