diff options
Diffstat (limited to 'security/integrity/ima')
-rw-r--r-- | security/integrity/ima/ima.h | 7 | ||||
-rw-r--r-- | security/integrity/ima/ima_api.c | 22 | ||||
-rw-r--r-- | security/integrity/ima/ima_crypto.c | 17 | ||||
-rw-r--r-- | security/integrity/ima/ima_fs.c | 14 | ||||
-rw-r--r-- | security/integrity/ima/ima_init.c | 3 | ||||
-rw-r--r-- | security/integrity/ima/ima_template.c | 21 | ||||
-rw-r--r-- | security/integrity/ima/ima_template_lib.c | 6 |
7 files changed, 67 insertions, 23 deletions
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index bf03c6a16cc8..0356e1d437ca 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -26,7 +26,8 @@ | |||
26 | 26 | ||
27 | #include "../integrity.h" | 27 | #include "../integrity.h" |
28 | 28 | ||
29 | enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_ASCII }; | 29 | enum ima_show_type { IMA_SHOW_BINARY, IMA_SHOW_BINARY_NO_FIELD_LEN, |
30 | IMA_SHOW_ASCII }; | ||
30 | enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; | 31 | enum tpm_pcrs { TPM_PCR0 = 0, TPM_PCR8 = 8 }; |
31 | 32 | ||
32 | /* digest size for IMA, fits SHA1 or MD5 */ | 33 | /* digest size for IMA, fits SHA1 or MD5 */ |
@@ -97,7 +98,8 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, | |||
97 | const char *op, struct inode *inode, | 98 | const char *op, struct inode *inode, |
98 | const unsigned char *filename); | 99 | const unsigned char *filename); |
99 | int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash); | 100 | int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash); |
100 | int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields, | 101 | int ima_calc_field_array_hash(struct ima_field_data *field_data, |
102 | struct ima_template_desc *desc, int num_fields, | ||
101 | struct ima_digest_data *hash); | 103 | struct ima_digest_data *hash); |
102 | int __init ima_calc_boot_aggregate(struct ima_digest_data *hash); | 104 | int __init ima_calc_boot_aggregate(struct ima_digest_data *hash); |
103 | void ima_add_violation(struct file *file, const unsigned char *filename, | 105 | void ima_add_violation(struct file *file, const unsigned char *filename, |
@@ -146,6 +148,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint, | |||
146 | int xattr_len, struct ima_template_entry **entry); | 148 | int xattr_len, struct ima_template_entry **entry); |
147 | int ima_store_template(struct ima_template_entry *entry, int violation, | 149 | int ima_store_template(struct ima_template_entry *entry, int violation, |
148 | struct inode *inode, const unsigned char *filename); | 150 | struct inode *inode, const unsigned char *filename); |
151 | void ima_free_template_entry(struct ima_template_entry *entry); | ||
149 | const char *ima_d_path(struct path *path, char **pathbuf); | 152 | const char *ima_d_path(struct path *path, char **pathbuf); |
150 | 153 | ||
151 | /* rbtree tree calls to lookup, insert, delete | 154 | /* rbtree tree calls to lookup, insert, delete |
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 0e7540863fc2..c38bbce8c6a6 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c | |||
@@ -22,6 +22,19 @@ | |||
22 | #include "ima.h" | 22 | #include "ima.h" |
23 | 23 | ||
24 | /* | 24 | /* |
25 | * ima_free_template_entry - free an existing template entry | ||
26 | */ | ||
27 | void ima_free_template_entry(struct ima_template_entry *entry) | ||
28 | { | ||
29 | int i; | ||
30 | |||
31 | for (i = 0; i < entry->template_desc->num_fields; i++) | ||
32 | kfree(entry->template_data[i].data); | ||
33 | |||
34 | kfree(entry); | ||
35 | } | ||
36 | |||
37 | /* | ||
25 | * ima_alloc_init_template - create and initialize a new template entry | 38 | * ima_alloc_init_template - create and initialize a new template entry |
26 | */ | 39 | */ |
27 | int ima_alloc_init_template(struct integrity_iint_cache *iint, | 40 | int ima_alloc_init_template(struct integrity_iint_cache *iint, |
@@ -37,6 +50,7 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint, | |||
37 | if (!*entry) | 50 | if (!*entry) |
38 | return -ENOMEM; | 51 | return -ENOMEM; |
39 | 52 | ||
53 | (*entry)->template_desc = template_desc; | ||
40 | for (i = 0; i < template_desc->num_fields; i++) { | 54 | for (i = 0; i < template_desc->num_fields; i++) { |
41 | struct ima_template_field *field = template_desc->fields[i]; | 55 | struct ima_template_field *field = template_desc->fields[i]; |
42 | u32 len; | 56 | u32 len; |
@@ -51,10 +65,9 @@ int ima_alloc_init_template(struct integrity_iint_cache *iint, | |||
51 | (*entry)->template_data_len += sizeof(len); | 65 | (*entry)->template_data_len += sizeof(len); |
52 | (*entry)->template_data_len += len; | 66 | (*entry)->template_data_len += len; |
53 | } | 67 | } |
54 | (*entry)->template_desc = template_desc; | ||
55 | return 0; | 68 | return 0; |
56 | out: | 69 | out: |
57 | kfree(*entry); | 70 | ima_free_template_entry(*entry); |
58 | *entry = NULL; | 71 | *entry = NULL; |
59 | return result; | 72 | return result; |
60 | } | 73 | } |
@@ -94,6 +107,7 @@ int ima_store_template(struct ima_template_entry *entry, | |||
94 | /* this function uses default algo */ | 107 | /* this function uses default algo */ |
95 | hash.hdr.algo = HASH_ALGO_SHA1; | 108 | hash.hdr.algo = HASH_ALGO_SHA1; |
96 | result = ima_calc_field_array_hash(&entry->template_data[0], | 109 | result = ima_calc_field_array_hash(&entry->template_data[0], |
110 | entry->template_desc, | ||
97 | num_fields, &hash.hdr); | 111 | num_fields, &hash.hdr); |
98 | if (result < 0) { | 112 | if (result < 0) { |
99 | integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, | 113 | integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, |
@@ -133,7 +147,7 @@ void ima_add_violation(struct file *file, const unsigned char *filename, | |||
133 | } | 147 | } |
134 | result = ima_store_template(entry, violation, inode, filename); | 148 | result = ima_store_template(entry, violation, inode, filename); |
135 | if (result < 0) | 149 | if (result < 0) |
136 | kfree(entry); | 150 | ima_free_template_entry(entry); |
137 | err_out: | 151 | err_out: |
138 | integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, | 152 | integrity_audit_msg(AUDIT_INTEGRITY_PCR, inode, filename, |
139 | op, cause, result, 0); | 153 | op, cause, result, 0); |
@@ -268,7 +282,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, | |||
268 | if (!result || result == -EEXIST) | 282 | if (!result || result == -EEXIST) |
269 | iint->flags |= IMA_MEASURED; | 283 | iint->flags |= IMA_MEASURED; |
270 | if (result < 0) | 284 | if (result < 0) |
271 | kfree(entry); | 285 | ima_free_template_entry(entry); |
272 | } | 286 | } |
273 | 287 | ||
274 | void ima_audit_measurement(struct integrity_iint_cache *iint, | 288 | void ima_audit_measurement(struct integrity_iint_cache *iint, |
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 676e0292dfec..fdf60def52e9 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c | |||
@@ -140,6 +140,7 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) | |||
140 | * Calculate the hash of template data | 140 | * Calculate the hash of template data |
141 | */ | 141 | */ |
142 | static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, | 142 | static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, |
143 | struct ima_template_desc *td, | ||
143 | int num_fields, | 144 | int num_fields, |
144 | struct ima_digest_data *hash, | 145 | struct ima_digest_data *hash, |
145 | struct crypto_shash *tfm) | 146 | struct crypto_shash *tfm) |
@@ -160,9 +161,13 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, | |||
160 | return rc; | 161 | return rc; |
161 | 162 | ||
162 | for (i = 0; i < num_fields; i++) { | 163 | for (i = 0; i < num_fields; i++) { |
163 | rc = crypto_shash_update(&desc.shash, | 164 | if (strcmp(td->name, IMA_TEMPLATE_IMA_NAME) != 0) { |
164 | (const u8 *) &field_data[i].len, | 165 | rc = crypto_shash_update(&desc.shash, |
165 | sizeof(field_data[i].len)); | 166 | (const u8 *) &field_data[i].len, |
167 | sizeof(field_data[i].len)); | ||
168 | if (rc) | ||
169 | break; | ||
170 | } | ||
166 | rc = crypto_shash_update(&desc.shash, field_data[i].data, | 171 | rc = crypto_shash_update(&desc.shash, field_data[i].data, |
167 | field_data[i].len); | 172 | field_data[i].len); |
168 | if (rc) | 173 | if (rc) |
@@ -175,7 +180,8 @@ static int ima_calc_field_array_hash_tfm(struct ima_field_data *field_data, | |||
175 | return rc; | 180 | return rc; |
176 | } | 181 | } |
177 | 182 | ||
178 | int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields, | 183 | int ima_calc_field_array_hash(struct ima_field_data *field_data, |
184 | struct ima_template_desc *desc, int num_fields, | ||
179 | struct ima_digest_data *hash) | 185 | struct ima_digest_data *hash) |
180 | { | 186 | { |
181 | struct crypto_shash *tfm; | 187 | struct crypto_shash *tfm; |
@@ -185,7 +191,8 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, int num_fields, | |||
185 | if (IS_ERR(tfm)) | 191 | if (IS_ERR(tfm)) |
186 | return PTR_ERR(tfm); | 192 | return PTR_ERR(tfm); |
187 | 193 | ||
188 | rc = ima_calc_field_array_hash_tfm(field_data, num_fields, hash, tfm); | 194 | rc = ima_calc_field_array_hash_tfm(field_data, desc, num_fields, |
195 | hash, tfm); | ||
189 | 196 | ||
190 | ima_free_tfm(tfm); | 197 | ima_free_tfm(tfm); |
191 | 198 | ||
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index d47a7c86a21d..db01125926bd 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c | |||
@@ -120,6 +120,7 @@ static int ima_measurements_show(struct seq_file *m, void *v) | |||
120 | struct ima_template_entry *e; | 120 | struct ima_template_entry *e; |
121 | int namelen; | 121 | int namelen; |
122 | u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX; | 122 | u32 pcr = CONFIG_IMA_MEASURE_PCR_IDX; |
123 | bool is_ima_template = false; | ||
123 | int i; | 124 | int i; |
124 | 125 | ||
125 | /* get entry */ | 126 | /* get entry */ |
@@ -145,14 +146,21 @@ static int ima_measurements_show(struct seq_file *m, void *v) | |||
145 | ima_putc(m, e->template_desc->name, namelen); | 146 | ima_putc(m, e->template_desc->name, namelen); |
146 | 147 | ||
147 | /* 5th: template length (except for 'ima' template) */ | 148 | /* 5th: template length (except for 'ima' template) */ |
148 | if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) | 149 | if (strcmp(e->template_desc->name, IMA_TEMPLATE_IMA_NAME) == 0) |
150 | is_ima_template = true; | ||
151 | |||
152 | if (!is_ima_template) | ||
149 | ima_putc(m, &e->template_data_len, | 153 | ima_putc(m, &e->template_data_len, |
150 | sizeof(e->template_data_len)); | 154 | sizeof(e->template_data_len)); |
151 | 155 | ||
152 | /* 6th: template specific data */ | 156 | /* 6th: template specific data */ |
153 | for (i = 0; i < e->template_desc->num_fields; i++) { | 157 | for (i = 0; i < e->template_desc->num_fields; i++) { |
154 | e->template_desc->fields[i]->field_show(m, IMA_SHOW_BINARY, | 158 | enum ima_show_type show = IMA_SHOW_BINARY; |
155 | &e->template_data[i]); | 159 | struct ima_template_field *field = e->template_desc->fields[i]; |
160 | |||
161 | if (is_ima_template && strcmp(field->field_id, "d") == 0) | ||
162 | show = IMA_SHOW_BINARY_NO_FIELD_LEN; | ||
163 | field->field_show(m, show, &e->template_data[i]); | ||
156 | } | 164 | } |
157 | return 0; | 165 | return 0; |
158 | } | 166 | } |
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 15f34bd40abe..37122768554a 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c | |||
@@ -63,7 +63,6 @@ static void __init ima_add_boot_aggregate(void) | |||
63 | result = ima_calc_boot_aggregate(&hash.hdr); | 63 | result = ima_calc_boot_aggregate(&hash.hdr); |
64 | if (result < 0) { | 64 | if (result < 0) { |
65 | audit_cause = "hashing_error"; | 65 | audit_cause = "hashing_error"; |
66 | kfree(entry); | ||
67 | goto err_out; | 66 | goto err_out; |
68 | } | 67 | } |
69 | } | 68 | } |
@@ -76,7 +75,7 @@ static void __init ima_add_boot_aggregate(void) | |||
76 | result = ima_store_template(entry, violation, NULL, | 75 | result = ima_store_template(entry, violation, NULL, |
77 | boot_aggregate_name); | 76 | boot_aggregate_name); |
78 | if (result < 0) | 77 | if (result < 0) |
79 | kfree(entry); | 78 | ima_free_template_entry(entry); |
80 | return; | 79 | return; |
81 | err_out: | 80 | err_out: |
82 | integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op, | 81 | integrity_audit_msg(AUDIT_INTEGRITY_PCR, NULL, boot_aggregate_name, op, |
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index 4e5da990630b..635695f6a185 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c | |||
@@ -90,7 +90,7 @@ static struct ima_template_field *lookup_template_field(const char *field_id) | |||
90 | return NULL; | 90 | return NULL; |
91 | } | 91 | } |
92 | 92 | ||
93 | static int template_fmt_size(char *template_fmt) | 93 | static int template_fmt_size(const char *template_fmt) |
94 | { | 94 | { |
95 | char c; | 95 | char c; |
96 | int template_fmt_len = strlen(template_fmt); | 96 | int template_fmt_len = strlen(template_fmt); |
@@ -106,22 +106,29 @@ static int template_fmt_size(char *template_fmt) | |||
106 | return j + 1; | 106 | return j + 1; |
107 | } | 107 | } |
108 | 108 | ||
109 | static int template_desc_init_fields(char *template_fmt, | 109 | static int template_desc_init_fields(const char *template_fmt, |
110 | struct ima_template_field ***fields, | 110 | struct ima_template_field ***fields, |
111 | int *num_fields) | 111 | int *num_fields) |
112 | { | 112 | { |
113 | char *c, *template_fmt_ptr = template_fmt; | 113 | char *c, *template_fmt_copy, *template_fmt_ptr; |
114 | int template_num_fields = template_fmt_size(template_fmt); | 114 | int template_num_fields = template_fmt_size(template_fmt); |
115 | int i, result = 0; | 115 | int i, result = 0; |
116 | 116 | ||
117 | if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) | 117 | if (template_num_fields > IMA_TEMPLATE_NUM_FIELDS_MAX) |
118 | return -EINVAL; | 118 | return -EINVAL; |
119 | 119 | ||
120 | /* copying is needed as strsep() modifies the original buffer */ | ||
121 | template_fmt_copy = kstrdup(template_fmt, GFP_KERNEL); | ||
122 | if (template_fmt_copy == NULL) | ||
123 | return -ENOMEM; | ||
124 | |||
120 | *fields = kzalloc(template_num_fields * sizeof(*fields), GFP_KERNEL); | 125 | *fields = kzalloc(template_num_fields * sizeof(*fields), GFP_KERNEL); |
121 | if (*fields == NULL) { | 126 | if (*fields == NULL) { |
122 | result = -ENOMEM; | 127 | result = -ENOMEM; |
123 | goto out; | 128 | goto out; |
124 | } | 129 | } |
130 | |||
131 | template_fmt_ptr = template_fmt_copy; | ||
125 | for (i = 0; (c = strsep(&template_fmt_ptr, "|")) != NULL && | 132 | for (i = 0; (c = strsep(&template_fmt_ptr, "|")) != NULL && |
126 | i < template_num_fields; i++) { | 133 | i < template_num_fields; i++) { |
127 | struct ima_template_field *f = lookup_template_field(c); | 134 | struct ima_template_field *f = lookup_template_field(c); |
@@ -133,10 +140,12 @@ static int template_desc_init_fields(char *template_fmt, | |||
133 | (*fields)[i] = f; | 140 | (*fields)[i] = f; |
134 | } | 141 | } |
135 | *num_fields = i; | 142 | *num_fields = i; |
136 | return 0; | ||
137 | out: | 143 | out: |
138 | kfree(*fields); | 144 | if (result < 0) { |
139 | *fields = NULL; | 145 | kfree(*fields); |
146 | *fields = NULL; | ||
147 | } | ||
148 | kfree(template_fmt_copy); | ||
140 | return result; | 149 | return result; |
141 | } | 150 | } |
142 | 151 | ||
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c index 6d66ad6ed265..c38adcc910fb 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c | |||
@@ -109,9 +109,12 @@ static void ima_show_template_data_binary(struct seq_file *m, | |||
109 | enum data_formats datafmt, | 109 | enum data_formats datafmt, |
110 | struct ima_field_data *field_data) | 110 | struct ima_field_data *field_data) |
111 | { | 111 | { |
112 | ima_putc(m, &field_data->len, sizeof(u32)); | 112 | if (show != IMA_SHOW_BINARY_NO_FIELD_LEN) |
113 | ima_putc(m, &field_data->len, sizeof(u32)); | ||
114 | |||
113 | if (!field_data->len) | 115 | if (!field_data->len) |
114 | return; | 116 | return; |
117 | |||
115 | ima_putc(m, field_data->data, field_data->len); | 118 | ima_putc(m, field_data->data, field_data->len); |
116 | } | 119 | } |
117 | 120 | ||
@@ -125,6 +128,7 @@ static void ima_show_template_field_data(struct seq_file *m, | |||
125 | ima_show_template_data_ascii(m, show, datafmt, field_data); | 128 | ima_show_template_data_ascii(m, show, datafmt, field_data); |
126 | break; | 129 | break; |
127 | case IMA_SHOW_BINARY: | 130 | case IMA_SHOW_BINARY: |
131 | case IMA_SHOW_BINARY_NO_FIELD_LEN: | ||
128 | ima_show_template_data_binary(m, show, datafmt, field_data); | 132 | ima_show_template_data_binary(m, show, datafmt, field_data); |
129 | break; | 133 | break; |
130 | default: | 134 | default: |