diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-25 16:22:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-25 16:22:23 -0400 |
commit | 57ce66d39f10fb01efabd72b14eb033deddb226b (patch) | |
tree | aea270718c7b82df9cfcb10794d4b69cfaf61f38 /security | |
parent | 4ba9628fe5bf90e0125dbec847a0cf4f5553de14 (diff) | |
parent | 34bccd61b139dbb452421aebf480e7af5f7a12ed (diff) |
Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull integrity updates from James Morris:
"From Mimi: This contains a couple of bug fixes, including one for a
recent problem with calculating file hashes on overlayfs, and some
code cleanup"
* 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
MAINTAINERS: add Jarkko as maintainer for trusted keys
ima: open a new file instance if no read permissions
ima: fix showing large 'violations' or 'runtime_measurements_count'
security/integrity: remove unnecessary 'init_keyring' variable
security/integrity: constify some read-only data
vfs: require i_size <= SIZE_MAX in kernel_read_file()
Diffstat (limited to 'security')
-rw-r--r-- | security/integrity/digsig.c | 10 | ||||
-rw-r--r-- | security/integrity/evm/evm_crypto.c | 4 | ||||
-rw-r--r-- | security/integrity/ima/ima.h | 2 | ||||
-rw-r--r-- | security/integrity/ima/ima_api.c | 3 | ||||
-rw-r--r-- | security/integrity/ima/ima_crypto.c | 54 | ||||
-rw-r--r-- | security/integrity/ima/ima_fs.c | 9 | ||||
-rw-r--r-- | security/integrity/ima/ima_init.c | 2 | ||||
-rw-r--r-- | security/integrity/ima/ima_main.c | 2 | ||||
-rw-r--r-- | security/integrity/ima/ima_template.c | 11 |
9 files changed, 54 insertions, 43 deletions
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 9bb0a7f2863e..5eacba858e4b 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c | |||
@@ -26,7 +26,7 @@ | |||
26 | 26 | ||
27 | static struct key *keyring[INTEGRITY_KEYRING_MAX]; | 27 | static struct key *keyring[INTEGRITY_KEYRING_MAX]; |
28 | 28 | ||
29 | static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { | 29 | static const char * const keyring_name[INTEGRITY_KEYRING_MAX] = { |
30 | #ifndef CONFIG_INTEGRITY_TRUSTED_KEYRING | 30 | #ifndef CONFIG_INTEGRITY_TRUSTED_KEYRING |
31 | "_evm", | 31 | "_evm", |
32 | "_ima", | 32 | "_ima", |
@@ -37,12 +37,6 @@ static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { | |||
37 | "_module", | 37 | "_module", |
38 | }; | 38 | }; |
39 | 39 | ||
40 | #ifdef CONFIG_INTEGRITY_TRUSTED_KEYRING | ||
41 | static bool init_keyring __initdata = true; | ||
42 | #else | ||
43 | static bool init_keyring __initdata; | ||
44 | #endif | ||
45 | |||
46 | #ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY | 40 | #ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY |
47 | #define restrict_link_to_ima restrict_link_by_builtin_and_secondary_trusted | 41 | #define restrict_link_to_ima restrict_link_by_builtin_and_secondary_trusted |
48 | #else | 42 | #else |
@@ -85,7 +79,7 @@ int __init integrity_init_keyring(const unsigned int id) | |||
85 | struct key_restriction *restriction; | 79 | struct key_restriction *restriction; |
86 | int err = 0; | 80 | int err = 0; |
87 | 81 | ||
88 | if (!init_keyring) | 82 | if (!IS_ENABLED(CONFIG_INTEGRITY_TRUSTED_KEYRING)) |
89 | return 0; | 83 | return 0; |
90 | 84 | ||
91 | restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL); | 85 | restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL); |
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index 8a3905bb02c7..8c25f949ebdb 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c | |||
@@ -27,7 +27,7 @@ | |||
27 | #define EVMKEY "evm-key" | 27 | #define EVMKEY "evm-key" |
28 | #define MAX_KEY_SIZE 128 | 28 | #define MAX_KEY_SIZE 128 |
29 | static unsigned char evmkey[MAX_KEY_SIZE]; | 29 | static unsigned char evmkey[MAX_KEY_SIZE]; |
30 | static int evmkey_len = MAX_KEY_SIZE; | 30 | static const int evmkey_len = MAX_KEY_SIZE; |
31 | 31 | ||
32 | struct crypto_shash *hmac_tfm; | 32 | struct crypto_shash *hmac_tfm; |
33 | static struct crypto_shash *evm_tfm[HASH_ALGO__LAST]; | 33 | static struct crypto_shash *evm_tfm[HASH_ALGO__LAST]; |
@@ -38,7 +38,7 @@ static DEFINE_MUTEX(mutex); | |||
38 | 38 | ||
39 | static unsigned long evm_set_key_flags; | 39 | static unsigned long evm_set_key_flags; |
40 | 40 | ||
41 | static char * const evm_hmac = "hmac(sha1)"; | 41 | static const char evm_hmac[] = "hmac(sha1)"; |
42 | 42 | ||
43 | /** | 43 | /** |
44 | * evm_set_key() - set EVM HMAC key from the kernel | 44 | * evm_set_key() - set EVM HMAC key from the kernel |
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 67db9d9454ca..cc12f3449a72 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h | |||
@@ -88,7 +88,7 @@ struct ima_template_desc { | |||
88 | char *name; | 88 | char *name; |
89 | char *fmt; | 89 | char *fmt; |
90 | int num_fields; | 90 | int num_fields; |
91 | struct ima_template_field **fields; | 91 | const struct ima_template_field **fields; |
92 | }; | 92 | }; |
93 | 93 | ||
94 | struct ima_template_entry { | 94 | struct ima_template_entry { |
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index a02c5acfd403..99dd1d53fc35 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c | |||
@@ -51,7 +51,8 @@ int ima_alloc_init_template(struct ima_event_data *event_data, | |||
51 | 51 | ||
52 | (*entry)->template_desc = template_desc; | 52 | (*entry)->template_desc = template_desc; |
53 | for (i = 0; i < template_desc->num_fields; i++) { | 53 | for (i = 0; i < template_desc->num_fields; i++) { |
54 | struct ima_template_field *field = template_desc->fields[i]; | 54 | const struct ima_template_field *field = |
55 | template_desc->fields[i]; | ||
55 | u32 len; | 56 | u32 len; |
56 | 57 | ||
57 | result = field->field_init(event_data, | 58 | result = field->field_init(event_data, |
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 7e7e7e7c250a..d9e7728027c6 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c | |||
@@ -210,7 +210,7 @@ static int ima_calc_file_hash_atfm(struct file *file, | |||
210 | { | 210 | { |
211 | loff_t i_size, offset; | 211 | loff_t i_size, offset; |
212 | char *rbuf[2] = { NULL, }; | 212 | char *rbuf[2] = { NULL, }; |
213 | int rc, read = 0, rbuf_len, active = 0, ahash_rc = 0; | 213 | int rc, rbuf_len, active = 0, ahash_rc = 0; |
214 | struct ahash_request *req; | 214 | struct ahash_request *req; |
215 | struct scatterlist sg[1]; | 215 | struct scatterlist sg[1]; |
216 | struct crypto_wait wait; | 216 | struct crypto_wait wait; |
@@ -257,11 +257,6 @@ static int ima_calc_file_hash_atfm(struct file *file, | |||
257 | &rbuf_size[1], 0); | 257 | &rbuf_size[1], 0); |
258 | } | 258 | } |
259 | 259 | ||
260 | if (!(file->f_mode & FMODE_READ)) { | ||
261 | file->f_mode |= FMODE_READ; | ||
262 | read = 1; | ||
263 | } | ||
264 | |||
265 | for (offset = 0; offset < i_size; offset += rbuf_len) { | 260 | for (offset = 0; offset < i_size; offset += rbuf_len) { |
266 | if (!rbuf[1] && offset) { | 261 | if (!rbuf[1] && offset) { |
267 | /* Not using two buffers, and it is not the first | 262 | /* Not using two buffers, and it is not the first |
@@ -300,8 +295,6 @@ static int ima_calc_file_hash_atfm(struct file *file, | |||
300 | /* wait for the last update request to complete */ | 295 | /* wait for the last update request to complete */ |
301 | rc = ahash_wait(ahash_rc, &wait); | 296 | rc = ahash_wait(ahash_rc, &wait); |
302 | out3: | 297 | out3: |
303 | if (read) | ||
304 | file->f_mode &= ~FMODE_READ; | ||
305 | ima_free_pages(rbuf[0], rbuf_size[0]); | 298 | ima_free_pages(rbuf[0], rbuf_size[0]); |
306 | ima_free_pages(rbuf[1], rbuf_size[1]); | 299 | ima_free_pages(rbuf[1], rbuf_size[1]); |
307 | out2: | 300 | out2: |
@@ -336,7 +329,7 @@ static int ima_calc_file_hash_tfm(struct file *file, | |||
336 | { | 329 | { |
337 | loff_t i_size, offset = 0; | 330 | loff_t i_size, offset = 0; |
338 | char *rbuf; | 331 | char *rbuf; |
339 | int rc, read = 0; | 332 | int rc; |
340 | SHASH_DESC_ON_STACK(shash, tfm); | 333 | SHASH_DESC_ON_STACK(shash, tfm); |
341 | 334 | ||
342 | shash->tfm = tfm; | 335 | shash->tfm = tfm; |
@@ -357,11 +350,6 @@ static int ima_calc_file_hash_tfm(struct file *file, | |||
357 | if (!rbuf) | 350 | if (!rbuf) |
358 | return -ENOMEM; | 351 | return -ENOMEM; |
359 | 352 | ||
360 | if (!(file->f_mode & FMODE_READ)) { | ||
361 | file->f_mode |= FMODE_READ; | ||
362 | read = 1; | ||
363 | } | ||
364 | |||
365 | while (offset < i_size) { | 353 | while (offset < i_size) { |
366 | int rbuf_len; | 354 | int rbuf_len; |
367 | 355 | ||
@@ -378,8 +366,6 @@ static int ima_calc_file_hash_tfm(struct file *file, | |||
378 | if (rc) | 366 | if (rc) |
379 | break; | 367 | break; |
380 | } | 368 | } |
381 | if (read) | ||
382 | file->f_mode &= ~FMODE_READ; | ||
383 | kfree(rbuf); | 369 | kfree(rbuf); |
384 | out: | 370 | out: |
385 | if (!rc) | 371 | if (!rc) |
@@ -420,6 +406,8 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) | |||
420 | { | 406 | { |
421 | loff_t i_size; | 407 | loff_t i_size; |
422 | int rc; | 408 | int rc; |
409 | struct file *f = file; | ||
410 | bool new_file_instance = false, modified_flags = false; | ||
423 | 411 | ||
424 | /* | 412 | /* |
425 | * For consistency, fail file's opened with the O_DIRECT flag on | 413 | * For consistency, fail file's opened with the O_DIRECT flag on |
@@ -431,15 +419,41 @@ int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash) | |||
431 | return -EINVAL; | 419 | return -EINVAL; |
432 | } | 420 | } |
433 | 421 | ||
434 | i_size = i_size_read(file_inode(file)); | 422 | /* Open a new file instance in O_RDONLY if we cannot read */ |
423 | if (!(file->f_mode & FMODE_READ)) { | ||
424 | int flags = file->f_flags & ~(O_WRONLY | O_APPEND | | ||
425 | O_TRUNC | O_CREAT | O_NOCTTY | O_EXCL); | ||
426 | flags |= O_RDONLY; | ||
427 | f = dentry_open(&file->f_path, flags, file->f_cred); | ||
428 | if (IS_ERR(f)) { | ||
429 | /* | ||
430 | * Cannot open the file again, lets modify f_flags | ||
431 | * of original and continue | ||
432 | */ | ||
433 | pr_info_ratelimited("Unable to reopen file for reading.\n"); | ||
434 | f = file; | ||
435 | f->f_flags |= FMODE_READ; | ||
436 | modified_flags = true; | ||
437 | } else { | ||
438 | new_file_instance = true; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | i_size = i_size_read(file_inode(f)); | ||
435 | 443 | ||
436 | if (ima_ahash_minsize && i_size >= ima_ahash_minsize) { | 444 | if (ima_ahash_minsize && i_size >= ima_ahash_minsize) { |
437 | rc = ima_calc_file_ahash(file, hash); | 445 | rc = ima_calc_file_ahash(f, hash); |
438 | if (!rc) | 446 | if (!rc) |
439 | return 0; | 447 | goto out; |
440 | } | 448 | } |
441 | 449 | ||
442 | return ima_calc_file_shash(file, hash); | 450 | rc = ima_calc_file_shash(f, hash); |
451 | out: | ||
452 | if (new_file_instance) | ||
453 | fput(f); | ||
454 | else if (modified_flags) | ||
455 | f->f_flags &= ~FMODE_READ; | ||
456 | return rc; | ||
443 | } | 457 | } |
444 | 458 | ||
445 | /* | 459 | /* |
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index ae9d5c766a3c..3183cc23d0f8 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c | |||
@@ -42,14 +42,14 @@ static int __init default_canonical_fmt_setup(char *str) | |||
42 | __setup("ima_canonical_fmt", default_canonical_fmt_setup); | 42 | __setup("ima_canonical_fmt", default_canonical_fmt_setup); |
43 | 43 | ||
44 | static int valid_policy = 1; | 44 | static int valid_policy = 1; |
45 | #define TMPBUFLEN 12 | 45 | |
46 | static ssize_t ima_show_htable_value(char __user *buf, size_t count, | 46 | static ssize_t ima_show_htable_value(char __user *buf, size_t count, |
47 | loff_t *ppos, atomic_long_t *val) | 47 | loff_t *ppos, atomic_long_t *val) |
48 | { | 48 | { |
49 | char tmpbuf[TMPBUFLEN]; | 49 | char tmpbuf[32]; /* greater than largest 'long' string value */ |
50 | ssize_t len; | 50 | ssize_t len; |
51 | 51 | ||
52 | len = scnprintf(tmpbuf, TMPBUFLEN, "%li\n", atomic_long_read(val)); | 52 | len = scnprintf(tmpbuf, sizeof(tmpbuf), "%li\n", atomic_long_read(val)); |
53 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, len); | 53 | return simple_read_from_buffer(buf, count, ppos, tmpbuf, len); |
54 | } | 54 | } |
55 | 55 | ||
@@ -179,7 +179,8 @@ int ima_measurements_show(struct seq_file *m, void *v) | |||
179 | /* 6th: template specific data */ | 179 | /* 6th: template specific data */ |
180 | for (i = 0; i < e->template_desc->num_fields; i++) { | 180 | for (i = 0; i < e->template_desc->num_fields; i++) { |
181 | enum ima_show_type show = IMA_SHOW_BINARY; | 181 | enum ima_show_type show = IMA_SHOW_BINARY; |
182 | struct ima_template_field *field = e->template_desc->fields[i]; | 182 | const struct ima_template_field *field = |
183 | e->template_desc->fields[i]; | ||
183 | 184 | ||
184 | if (is_ima_template && strcmp(field->field_id, "d") == 0) | 185 | if (is_ima_template && strcmp(field->field_id, "d") == 0) |
185 | show = IMA_SHOW_BINARY_NO_FIELD_LEN; | 186 | show = IMA_SHOW_BINARY_NO_FIELD_LEN; |
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index faac9ecaa0ae..59d834219cd6 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include "ima.h" | 25 | #include "ima.h" |
26 | 26 | ||
27 | /* name for boot aggregate entry */ | 27 | /* name for boot aggregate entry */ |
28 | static const char *boot_aggregate_name = "boot_aggregate"; | 28 | static const char boot_aggregate_name[] = "boot_aggregate"; |
29 | struct tpm_chip *ima_tpm_chip; | 29 | struct tpm_chip *ima_tpm_chip; |
30 | 30 | ||
31 | /* Add the boot aggregate to the IMA measurement list and extend | 31 | /* Add the boot aggregate to the IMA measurement list and extend |
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 2d31921fbda4..1b88d58e1325 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c | |||
@@ -440,7 +440,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id) | |||
440 | return 0; | 440 | return 0; |
441 | } | 441 | } |
442 | 442 | ||
443 | static int read_idmap[READING_MAX_ID] = { | 443 | static const int read_idmap[READING_MAX_ID] = { |
444 | [READING_FIRMWARE] = FIRMWARE_CHECK, | 444 | [READING_FIRMWARE] = FIRMWARE_CHECK, |
445 | [READING_FIRMWARE_PREALLOC_BUFFER] = FIRMWARE_CHECK, | 445 | [READING_FIRMWARE_PREALLOC_BUFFER] = FIRMWARE_CHECK, |
446 | [READING_MODULE] = MODULE_CHECK, | 446 | [READING_MODULE] = MODULE_CHECK, |
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index 30db39b23804..b631b8bc7624 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c | |||
@@ -32,7 +32,7 @@ static struct ima_template_desc builtin_templates[] = { | |||
32 | static LIST_HEAD(defined_templates); | 32 | static LIST_HEAD(defined_templates); |
33 | static DEFINE_SPINLOCK(template_list); | 33 | static DEFINE_SPINLOCK(template_list); |
34 | 34 | ||
35 | static struct ima_template_field supported_fields[] = { | 35 | static const struct ima_template_field supported_fields[] = { |
36 | {.field_id = "d", .field_init = ima_eventdigest_init, | 36 | {.field_id = "d", .field_init = ima_eventdigest_init, |
37 | .field_show = ima_show_template_digest}, | 37 | .field_show = ima_show_template_digest}, |
38 | {.field_id = "n", .field_init = ima_eventname_init, | 38 | {.field_id = "n", .field_init = ima_eventname_init, |
@@ -49,7 +49,7 @@ static struct ima_template_field supported_fields[] = { | |||
49 | static struct ima_template_desc *ima_template; | 49 | static struct ima_template_desc *ima_template; |
50 | static struct ima_template_desc *lookup_template_desc(const char *name); | 50 | static struct ima_template_desc *lookup_template_desc(const char *name); |
51 | static int template_desc_init_fields(const char *template_fmt, | 51 | static int template_desc_init_fields(const char *template_fmt, |
52 | struct ima_template_field ***fields, | 52 | const struct ima_template_field ***fields, |
53 | int *num_fields); | 53 | int *num_fields); |
54 | 54 | ||
55 | static int __init ima_template_setup(char *str) | 55 | static int __init ima_template_setup(char *str) |
@@ -125,7 +125,8 @@ static struct ima_template_desc *lookup_template_desc(const char *name) | |||
125 | return found ? template_desc : NULL; | 125 | return found ? template_desc : NULL; |
126 | } | 126 | } |
127 | 127 | ||
128 | static struct ima_template_field *lookup_template_field(const char *field_id) | 128 | static const struct ima_template_field * |
129 | lookup_template_field(const char *field_id) | ||
129 | { | 130 | { |
130 | int i; | 131 | int i; |
131 | 132 | ||
@@ -153,11 +154,11 @@ static int template_fmt_size(const char *template_fmt) | |||
153 | } | 154 | } |
154 | 155 | ||
155 | static int template_desc_init_fields(const char *template_fmt, | 156 | static int template_desc_init_fields(const char *template_fmt, |
156 | struct ima_template_field ***fields, | 157 | const struct ima_template_field ***fields, |
157 | int *num_fields) | 158 | int *num_fields) |
158 | { | 159 | { |
159 | const char *template_fmt_ptr; | 160 | const char *template_fmt_ptr; |
160 | struct ima_template_field *found_fields[IMA_TEMPLATE_NUM_FIELDS_MAX]; | 161 | const struct ima_template_field *found_fields[IMA_TEMPLATE_NUM_FIELDS_MAX]; |
161 | int template_num_fields; | 162 | int template_num_fields; |
162 | int i, len; | 163 | int i, len; |
163 | 164 | ||