aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
Diffstat (limited to 'security')
-rw-r--r--security/integrity/digsig_asymmetric.c11
-rw-r--r--security/integrity/ima/ima.h29
-rw-r--r--security/integrity/ima/ima_api.c12
-rw-r--r--security/integrity/ima/ima_appraise.c45
-rw-r--r--security/integrity/ima/ima_main.c11
-rw-r--r--security/integrity/integrity.h11
6 files changed, 94 insertions, 25 deletions
diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c
index b4754667659d..9eae4809006b 100644
--- a/security/integrity/digsig_asymmetric.c
+++ b/security/integrity/digsig_asymmetric.c
@@ -20,17 +20,6 @@
20#include "integrity.h" 20#include "integrity.h"
21 21
22/* 22/*
23 * signature format v2 - for using with asymmetric keys
24 */
25struct signature_v2_hdr {
26 uint8_t version; /* signature format version */
27 uint8_t hash_algo; /* Digest algorithm [enum pkey_hash_algo] */
28 uint32_t keyid; /* IMA key identifier - not X509/PGP specific*/
29 uint16_t sig_size; /* signature size */
30 uint8_t sig[0]; /* signature payload */
31} __packed;
32
33/*
34 * Request an asymmetric key. 23 * Request an asymmetric key.
35 */ 24 */
36static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid) 25static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index eb86032f4f1e..efcdef2bf1bc 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -99,7 +99,9 @@ static inline unsigned long ima_hash_key(u8 *digest)
99int ima_get_action(struct inode *inode, int mask, int function); 99int ima_get_action(struct inode *inode, int mask, int function);
100int ima_must_measure(struct inode *inode, int mask, int function); 100int ima_must_measure(struct inode *inode, int mask, int function);
101int ima_collect_measurement(struct integrity_iint_cache *iint, 101int ima_collect_measurement(struct integrity_iint_cache *iint,
102 struct file *file); 102 struct file *file,
103 struct evm_ima_xattr_data **xattr_value,
104 int *xattr_len);
103void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, 105void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
104 const unsigned char *filename); 106 const unsigned char *filename);
105void ima_audit_measurement(struct integrity_iint_cache *iint, 107void ima_audit_measurement(struct integrity_iint_cache *iint,
@@ -132,17 +134,25 @@ void ima_delete_rules(void);
132 134
133#ifdef CONFIG_IMA_APPRAISE 135#ifdef CONFIG_IMA_APPRAISE
134int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, 136int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
135 struct file *file, const unsigned char *filename); 137 struct file *file, const unsigned char *filename,
138 struct evm_ima_xattr_data *xattr_value,
139 int xattr_len);
136int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); 140int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func);
137void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); 141void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
138enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, 142enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
139 int func); 143 int func);
144void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len,
145 struct ima_digest_data *hash);
146int ima_read_xattr(struct dentry *dentry,
147 struct evm_ima_xattr_data **xattr_value);
140 148
141#else 149#else
142static inline int ima_appraise_measurement(int func, 150static inline int ima_appraise_measurement(int func,
143 struct integrity_iint_cache *iint, 151 struct integrity_iint_cache *iint,
144 struct file *file, 152 struct file *file,
145 const unsigned char *filename) 153 const unsigned char *filename,
154 struct evm_ima_xattr_data *xattr_value,
155 int xattr_len)
146{ 156{
147 return INTEGRITY_UNKNOWN; 157 return INTEGRITY_UNKNOWN;
148} 158}
@@ -163,6 +173,19 @@ static inline enum integrity_status ima_get_cache_status(struct integrity_iint_c
163{ 173{
164 return INTEGRITY_UNKNOWN; 174 return INTEGRITY_UNKNOWN;
165} 175}
176
177static inline void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
178 int xattr_len,
179 struct ima_digest_data *hash)
180{
181}
182
183static inline int ima_read_xattr(struct dentry *dentry,
184 struct evm_ima_xattr_data **xattr_value)
185{
186 return 0;
187}
188
166#endif 189#endif
167 190
168/* LSM based policy rules require audit */ 191/* LSM based policy rules require audit */
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index e531fe22e582..1dba98e2d7e9 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -139,17 +139,27 @@ int ima_must_measure(struct inode *inode, int mask, int function)
139 * Return 0 on success, error code otherwise 139 * Return 0 on success, error code otherwise
140 */ 140 */
141int ima_collect_measurement(struct integrity_iint_cache *iint, 141int ima_collect_measurement(struct integrity_iint_cache *iint,
142 struct file *file) 142 struct file *file,
143 struct evm_ima_xattr_data **xattr_value,
144 int *xattr_len)
143{ 145{
144 struct inode *inode = file_inode(file); 146 struct inode *inode = file_inode(file);
145 const char *filename = file->f_dentry->d_name.name; 147 const char *filename = file->f_dentry->d_name.name;
146 int result = 0; 148 int result = 0;
147 149
150 if (xattr_value)
151 *xattr_len = ima_read_xattr(file->f_dentry, xattr_value);
152
148 if (!(iint->flags & IMA_COLLECTED)) { 153 if (!(iint->flags & IMA_COLLECTED)) {
149 u64 i_version = file_inode(file)->i_version; 154 u64 i_version = file_inode(file)->i_version;
150 155
151 /* use default hash algorithm */ 156 /* use default hash algorithm */
152 iint->ima_hash.algo = ima_hash_algo; 157 iint->ima_hash.algo = ima_hash_algo;
158
159 if (xattr_value)
160 ima_get_hash_algo(*xattr_value, *xattr_len,
161 &iint->ima_hash);
162
153 result = ima_calc_file_hash(file, &iint->ima_hash); 163 result = ima_calc_file_hash(file, &iint->ima_hash);
154 if (!result) { 164 if (!result) {
155 iint->version = i_version; 165 iint->version = i_version;
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 3833b0fa7108..00708a3052cc 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -107,6 +107,34 @@ static void ima_cache_flags(struct integrity_iint_cache *iint, int func)
107 } 107 }
108} 108}
109 109
110void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len,
111 struct ima_digest_data *hash)
112{
113 struct signature_v2_hdr *sig;
114
115 if (!xattr_value || xattr_len < 0 || xattr_len <= 1 + sizeof(*sig))
116 return;
117
118 sig = (typeof(sig)) xattr_value->digest;
119
120 if (xattr_value->type != EVM_IMA_XATTR_DIGSIG || sig->version != 2)
121 return;
122
123 hash->algo = sig->hash_algo;
124}
125
126int ima_read_xattr(struct dentry *dentry,
127 struct evm_ima_xattr_data **xattr_value)
128{
129 struct inode *inode = dentry->d_inode;
130
131 if (!inode->i_op->getxattr)
132 return 0;
133
134 return vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
135 0, GFP_NOFS);
136}
137
110/* 138/*
111 * ima_appraise_measurement - appraise file measurement 139 * ima_appraise_measurement - appraise file measurement
112 * 140 *
@@ -116,23 +144,22 @@ static void ima_cache_flags(struct integrity_iint_cache *iint, int func)
116 * Return 0 on success, error code otherwise 144 * Return 0 on success, error code otherwise
117 */ 145 */
118int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, 146int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
119 struct file *file, const unsigned char *filename) 147 struct file *file, const unsigned char *filename,
148 struct evm_ima_xattr_data *xattr_value,
149 int xattr_len)
120{ 150{
121 struct dentry *dentry = file->f_dentry; 151 struct dentry *dentry = file->f_dentry;
122 struct inode *inode = dentry->d_inode; 152 struct inode *inode = dentry->d_inode;
123 struct evm_ima_xattr_data *xattr_value = NULL;
124 enum integrity_status status = INTEGRITY_UNKNOWN; 153 enum integrity_status status = INTEGRITY_UNKNOWN;
125 const char *op = "appraise_data"; 154 const char *op = "appraise_data";
126 char *cause = "unknown"; 155 char *cause = "unknown";
127 int rc; 156 int rc = xattr_len;
128 157
129 if (!ima_appraise) 158 if (!ima_appraise)
130 return 0; 159 return 0;
131 if (!inode->i_op->getxattr) 160 if (!inode->i_op->getxattr)
132 return INTEGRITY_UNKNOWN; 161 return INTEGRITY_UNKNOWN;
133 162
134 rc = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)&xattr_value,
135 0, GFP_NOFS);
136 if (rc <= 0) { 163 if (rc <= 0) {
137 if (rc && rc != -ENODATA) 164 if (rc && rc != -ENODATA)
138 goto out; 165 goto out;
@@ -159,7 +186,10 @@ int ima_appraise_measurement(int func, struct integrity_iint_cache *iint,
159 status = INTEGRITY_FAIL; 186 status = INTEGRITY_FAIL;
160 break; 187 break;
161 } 188 }
162 if (rc - 1 == iint->ima_hash.length) 189 if (xattr_len - 1 >= iint->ima_hash.length)
190 /* xattr length may be longer. md5 hash in previous
191 version occupied 20 bytes in xattr, instead of 16
192 */
163 rc = memcmp(xattr_value->digest, 193 rc = memcmp(xattr_value->digest,
164 iint->ima_hash.digest, 194 iint->ima_hash.digest,
165 iint->ima_hash.length); 195 iint->ima_hash.length);
@@ -207,7 +237,6 @@ out:
207 ima_cache_flags(iint, func); 237 ima_cache_flags(iint, func);
208 } 238 }
209 ima_set_cache_status(iint, func, status); 239 ima_set_cache_status(iint, func, status);
210 kfree(xattr_value);
211 return status; 240 return status;
212} 241}
213 242
@@ -223,7 +252,7 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
223 if (iint->flags & IMA_DIGSIG) 252 if (iint->flags & IMA_DIGSIG)
224 return; 253 return;
225 254
226 rc = ima_collect_measurement(iint, file); 255 rc = ima_collect_measurement(iint, file, NULL, NULL);
227 if (rc < 0) 256 if (rc < 0)
228 return; 257 return;
229 258
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 7708c2120d9c..95b5df2c6501 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -149,6 +149,8 @@ static int process_measurement(struct file *file, const char *filename,
149 char *pathbuf = NULL; 149 char *pathbuf = NULL;
150 const char *pathname = NULL; 150 const char *pathname = NULL;
151 int rc = -ENOMEM, action, must_appraise, _func; 151 int rc = -ENOMEM, action, must_appraise, _func;
152 struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL;
153 int xattr_len = 0;
152 154
153 if (!ima_initialized || !S_ISREG(inode->i_mode)) 155 if (!ima_initialized || !S_ISREG(inode->i_mode))
154 return 0; 156 return 0;
@@ -187,7 +189,10 @@ static int process_measurement(struct file *file, const char *filename,
187 goto out_digsig; 189 goto out_digsig;
188 } 190 }
189 191
190 rc = ima_collect_measurement(iint, file); 192 if (action & IMA_APPRAISE_SUBMASK)
193 xattr_ptr = &xattr_value;
194
195 rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len);
191 if (rc != 0) 196 if (rc != 0)
192 goto out_digsig; 197 goto out_digsig;
193 198
@@ -198,7 +203,8 @@ static int process_measurement(struct file *file, const char *filename,
198 if (action & IMA_MEASURE) 203 if (action & IMA_MEASURE)
199 ima_store_measurement(iint, file, pathname); 204 ima_store_measurement(iint, file, pathname);
200 if (action & IMA_APPRAISE_SUBMASK) 205 if (action & IMA_APPRAISE_SUBMASK)
201 rc = ima_appraise_measurement(_func, iint, file, pathname); 206 rc = ima_appraise_measurement(_func, iint, file, pathname,
207 xattr_value, xattr_len);
202 if (action & IMA_AUDIT) 208 if (action & IMA_AUDIT)
203 ima_audit_measurement(iint, pathname); 209 ima_audit_measurement(iint, pathname);
204 kfree(pathbuf); 210 kfree(pathbuf);
@@ -207,6 +213,7 @@ out_digsig:
207 rc = -EACCES; 213 rc = -EACCES;
208out: 214out:
209 mutex_unlock(&inode->i_mutex); 215 mutex_unlock(&inode->i_mutex);
216 kfree(xattr_value);
210 if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE)) 217 if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE))
211 return -EACCES; 218 return -EACCES;
212 return 0; 219 return 0;
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 0b02ea868e30..ea2318983d97 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -70,6 +70,17 @@ struct ima_digest_data {
70 u8 digest[IMA_MAX_DIGEST_SIZE]; 70 u8 digest[IMA_MAX_DIGEST_SIZE];
71} __packed; 71} __packed;
72 72
73/*
74 * signature format v2 - for using with asymmetric keys
75 */
76struct signature_v2_hdr {
77 uint8_t version; /* signature format version */
78 uint8_t hash_algo; /* Digest algorithm [enum pkey_hash_algo] */
79 uint32_t keyid; /* IMA key identifier - not X509/PGP specific */
80 uint16_t sig_size; /* signature size */
81 uint8_t sig[0]; /* signature payload */
82} __packed;
83
73/* integrity data associated with an inode */ 84/* integrity data associated with an inode */
74struct integrity_iint_cache { 85struct integrity_iint_cache {
75 struct rb_node rb_node; /* rooted in integrity_iint_tree */ 86 struct rb_node rb_node; /* rooted in integrity_iint_tree */