aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity
diff options
context:
space:
mode:
authorDmitry Kasatkin <d.kasatkin@samsung.com>2013-04-25 03:44:04 -0400
committerMimi Zohar <zohar@linux.vnet.ibm.com>2013-10-25 17:16:59 -0400
commitd3634d0f426bdeb433cb288bdbb0a5e16cf3dbbf (patch)
tree2197b45ddbdfcc81ecdc6b5acaa9292eead795b7 /security/integrity
parentc7c8bb237fdbff932b5e431aebee5ce862ea07d1 (diff)
ima: read and use signature hash algorithm
All files on the filesystem, currently, are hashed using the same hash algorithm. In preparation for files from different packages being signed using different hash algorithms, this patch adds support for reading the signature hash algorithm from the 'security.ima' extended attribute and calculates the appropriate file data hash based on it. Changelog: - fix scripts Lindent and checkpatch msgs - Mimi - fix md5 support for older version, which occupied 20 bytes in the xattr, not the expected 16 bytes. Fix the comparison to compare only the first 16 bytes. Signed-off-by: Dmitry Kasatkin <d.kasatkin@samsung.com> Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
Diffstat (limited to 'security/integrity')
-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 */