diff options
author | James Morris <james.l.morris@oracle.com> | 2014-01-06 06:23:01 -0500 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2014-01-06 06:23:01 -0500 |
commit | 38fd2c202a3d82bc12430bce5789fa2c2a406f71 (patch) | |
tree | a73513dbb015155f5236b391709b9083916b3136 /security | |
parent | dcf4e392867bf98d50ad108ed7c2bfb941e8c33d (diff) | |
parent | d6e0a2dd12f4067a5bcefb8bbd8ddbeff800afbc (diff) |
Merge to v3.13-rc7 for prerequisite changes in the Xen code for TPM
Diffstat (limited to 'security')
29 files changed, 361 insertions, 326 deletions
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c index 95c2b2689a03..7db9954f1af2 100644 --- a/security/apparmor/apparmorfs.c +++ b/security/apparmor/apparmorfs.c | |||
@@ -580,15 +580,13 @@ static struct aa_namespace *__next_namespace(struct aa_namespace *root, | |||
580 | 580 | ||
581 | /* check if the next ns is a sibling, parent, gp, .. */ | 581 | /* check if the next ns is a sibling, parent, gp, .. */ |
582 | parent = ns->parent; | 582 | parent = ns->parent; |
583 | while (parent) { | 583 | while (ns != root) { |
584 | mutex_unlock(&ns->lock); | 584 | mutex_unlock(&ns->lock); |
585 | next = list_entry_next(ns, base.list); | 585 | next = list_entry_next(ns, base.list); |
586 | if (!list_entry_is_head(next, &parent->sub_ns, base.list)) { | 586 | if (!list_entry_is_head(next, &parent->sub_ns, base.list)) { |
587 | mutex_lock(&next->lock); | 587 | mutex_lock(&next->lock); |
588 | return next; | 588 | return next; |
589 | } | 589 | } |
590 | if (parent == root) | ||
591 | return NULL; | ||
592 | ns = parent; | 590 | ns = parent; |
593 | parent = parent->parent; | 591 | parent = parent->parent; |
594 | } | 592 | } |
diff --git a/security/apparmor/crypto.c b/security/apparmor/crypto.c index d6222ba4e919..532471d0b3a0 100644 --- a/security/apparmor/crypto.c +++ b/security/apparmor/crypto.c | |||
@@ -15,14 +15,14 @@ | |||
15 | * it should be. | 15 | * it should be. |
16 | */ | 16 | */ |
17 | 17 | ||
18 | #include <linux/crypto.h> | 18 | #include <crypto/hash.h> |
19 | 19 | ||
20 | #include "include/apparmor.h" | 20 | #include "include/apparmor.h" |
21 | #include "include/crypto.h" | 21 | #include "include/crypto.h" |
22 | 22 | ||
23 | static unsigned int apparmor_hash_size; | 23 | static unsigned int apparmor_hash_size; |
24 | 24 | ||
25 | static struct crypto_hash *apparmor_tfm; | 25 | static struct crypto_shash *apparmor_tfm; |
26 | 26 | ||
27 | unsigned int aa_hash_size(void) | 27 | unsigned int aa_hash_size(void) |
28 | { | 28 | { |
@@ -32,35 +32,33 @@ unsigned int aa_hash_size(void) | |||
32 | int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start, | 32 | int aa_calc_profile_hash(struct aa_profile *profile, u32 version, void *start, |
33 | size_t len) | 33 | size_t len) |
34 | { | 34 | { |
35 | struct scatterlist sg[2]; | 35 | struct { |
36 | struct hash_desc desc = { | 36 | struct shash_desc shash; |
37 | .tfm = apparmor_tfm, | 37 | char ctx[crypto_shash_descsize(apparmor_tfm)]; |
38 | .flags = 0 | 38 | } desc; |
39 | }; | ||
40 | int error = -ENOMEM; | 39 | int error = -ENOMEM; |
41 | u32 le32_version = cpu_to_le32(version); | 40 | u32 le32_version = cpu_to_le32(version); |
42 | 41 | ||
43 | if (!apparmor_tfm) | 42 | if (!apparmor_tfm) |
44 | return 0; | 43 | return 0; |
45 | 44 | ||
46 | sg_init_table(sg, 2); | ||
47 | sg_set_buf(&sg[0], &le32_version, 4); | ||
48 | sg_set_buf(&sg[1], (u8 *) start, len); | ||
49 | |||
50 | profile->hash = kzalloc(apparmor_hash_size, GFP_KERNEL); | 45 | profile->hash = kzalloc(apparmor_hash_size, GFP_KERNEL); |
51 | if (!profile->hash) | 46 | if (!profile->hash) |
52 | goto fail; | 47 | goto fail; |
53 | 48 | ||
54 | error = crypto_hash_init(&desc); | 49 | desc.shash.tfm = apparmor_tfm; |
50 | desc.shash.flags = 0; | ||
51 | |||
52 | error = crypto_shash_init(&desc.shash); | ||
55 | if (error) | 53 | if (error) |
56 | goto fail; | 54 | goto fail; |
57 | error = crypto_hash_update(&desc, &sg[0], 4); | 55 | error = crypto_shash_update(&desc.shash, (u8 *) &le32_version, 4); |
58 | if (error) | 56 | if (error) |
59 | goto fail; | 57 | goto fail; |
60 | error = crypto_hash_update(&desc, &sg[1], len); | 58 | error = crypto_shash_update(&desc.shash, (u8 *) start, len); |
61 | if (error) | 59 | if (error) |
62 | goto fail; | 60 | goto fail; |
63 | error = crypto_hash_final(&desc, profile->hash); | 61 | error = crypto_shash_final(&desc.shash, profile->hash); |
64 | if (error) | 62 | if (error) |
65 | goto fail; | 63 | goto fail; |
66 | 64 | ||
@@ -75,19 +73,19 @@ fail: | |||
75 | 73 | ||
76 | static int __init init_profile_hash(void) | 74 | static int __init init_profile_hash(void) |
77 | { | 75 | { |
78 | struct crypto_hash *tfm; | 76 | struct crypto_shash *tfm; |
79 | 77 | ||
80 | if (!apparmor_initialized) | 78 | if (!apparmor_initialized) |
81 | return 0; | 79 | return 0; |
82 | 80 | ||
83 | tfm = crypto_alloc_hash("sha1", 0, CRYPTO_ALG_ASYNC); | 81 | tfm = crypto_alloc_shash("sha1", 0, CRYPTO_ALG_ASYNC); |
84 | if (IS_ERR(tfm)) { | 82 | if (IS_ERR(tfm)) { |
85 | int error = PTR_ERR(tfm); | 83 | int error = PTR_ERR(tfm); |
86 | AA_ERROR("failed to setup profile sha1 hashing: %d\n", error); | 84 | AA_ERROR("failed to setup profile sha1 hashing: %d\n", error); |
87 | return error; | 85 | return error; |
88 | } | 86 | } |
89 | apparmor_tfm = tfm; | 87 | apparmor_tfm = tfm; |
90 | apparmor_hash_size = crypto_hash_digestsize(apparmor_tfm); | 88 | apparmor_hash_size = crypto_shash_digestsize(apparmor_tfm); |
91 | 89 | ||
92 | aa_info_message("AppArmor sha1 policy hashing enabled"); | 90 | aa_info_message("AppArmor sha1 policy hashing enabled"); |
93 | 91 | ||
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h index f2d4b6348cbc..c28b0f20ab53 100644 --- a/security/apparmor/include/policy.h +++ b/security/apparmor/include/policy.h | |||
@@ -360,7 +360,9 @@ static inline void aa_put_replacedby(struct aa_replacedby *p) | |||
360 | static inline void __aa_update_replacedby(struct aa_profile *orig, | 360 | static inline void __aa_update_replacedby(struct aa_profile *orig, |
361 | struct aa_profile *new) | 361 | struct aa_profile *new) |
362 | { | 362 | { |
363 | struct aa_profile *tmp = rcu_dereference(orig->replacedby->profile); | 363 | struct aa_profile *tmp; |
364 | tmp = rcu_dereference_protected(orig->replacedby->profile, | ||
365 | mutex_is_locked(&orig->ns->lock)); | ||
364 | rcu_assign_pointer(orig->replacedby->profile, aa_get_profile(new)); | 366 | rcu_assign_pointer(orig->replacedby->profile, aa_get_profile(new)); |
365 | orig->flags |= PFLAG_INVALID; | 367 | orig->flags |= PFLAG_INVALID; |
366 | aa_put_profile(tmp); | 368 | aa_put_profile(tmp); |
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c index 6172509fa2b7..705c2879d3a9 100644 --- a/security/apparmor/policy.c +++ b/security/apparmor/policy.c | |||
@@ -563,7 +563,8 @@ void __init aa_free_root_ns(void) | |||
563 | static void free_replacedby(struct aa_replacedby *r) | 563 | static void free_replacedby(struct aa_replacedby *r) |
564 | { | 564 | { |
565 | if (r) { | 565 | if (r) { |
566 | aa_put_profile(rcu_dereference(r->profile)); | 566 | /* r->profile will not be updated any more as r is dead */ |
567 | aa_put_profile(rcu_dereference_protected(r->profile, true)); | ||
567 | kzfree(r); | 568 | kzfree(r); |
568 | } | 569 | } |
569 | } | 570 | } |
@@ -609,6 +610,7 @@ void aa_free_profile(struct aa_profile *profile) | |||
609 | aa_put_dfa(profile->policy.dfa); | 610 | aa_put_dfa(profile->policy.dfa); |
610 | aa_put_replacedby(profile->replacedby); | 611 | aa_put_replacedby(profile->replacedby); |
611 | 612 | ||
613 | kzfree(profile->hash); | ||
612 | kzfree(profile); | 614 | kzfree(profile); |
613 | } | 615 | } |
614 | 616 | ||
diff --git a/security/device_cgroup.c b/security/device_cgroup.c index c123628d3f84..7c2a0a71049e 100644 --- a/security/device_cgroup.c +++ b/security/device_cgroup.c | |||
@@ -63,16 +63,6 @@ static inline struct dev_cgroup *task_devcgroup(struct task_struct *task) | |||
63 | 63 | ||
64 | struct cgroup_subsys devices_subsys; | 64 | struct cgroup_subsys devices_subsys; |
65 | 65 | ||
66 | static int devcgroup_can_attach(struct cgroup_subsys_state *new_css, | ||
67 | struct cgroup_taskset *set) | ||
68 | { | ||
69 | struct task_struct *task = cgroup_taskset_first(set); | ||
70 | |||
71 | if (current != task && !capable(CAP_SYS_ADMIN)) | ||
72 | return -EPERM; | ||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | /* | 66 | /* |
77 | * called under devcgroup_mutex | 67 | * called under devcgroup_mutex |
78 | */ | 68 | */ |
@@ -697,7 +687,6 @@ static struct cftype dev_cgroup_files[] = { | |||
697 | 687 | ||
698 | struct cgroup_subsys devices_subsys = { | 688 | struct cgroup_subsys devices_subsys = { |
699 | .name = "devices", | 689 | .name = "devices", |
700 | .can_attach = devcgroup_can_attach, | ||
701 | .css_alloc = devcgroup_css_alloc, | 690 | .css_alloc = devcgroup_css_alloc, |
702 | .css_free = devcgroup_css_free, | 691 | .css_free = devcgroup_css_free, |
703 | .css_online = devcgroup_online, | 692 | .css_online = devcgroup_online, |
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c index 77ca965ab684..b4af4ebc5be2 100644 --- a/security/integrity/digsig.c +++ b/security/integrity/digsig.c | |||
@@ -13,9 +13,7 @@ | |||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
14 | 14 | ||
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/sched.h> | ||
17 | #include <linux/rbtree.h> | 16 | #include <linux/rbtree.h> |
18 | #include <linux/cred.h> | ||
19 | #include <linux/key-type.h> | 17 | #include <linux/key-type.h> |
20 | #include <linux/digsig.h> | 18 | #include <linux/digsig.h> |
21 | 19 | ||
@@ -23,19 +21,11 @@ | |||
23 | 21 | ||
24 | static struct key *keyring[INTEGRITY_KEYRING_MAX]; | 22 | static struct key *keyring[INTEGRITY_KEYRING_MAX]; |
25 | 23 | ||
26 | #ifdef CONFIG_IMA_TRUSTED_KEYRING | ||
27 | static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { | ||
28 | ".evm", | ||
29 | ".module", | ||
30 | ".ima", | ||
31 | }; | ||
32 | #else | ||
33 | static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { | 24 | static const char *keyring_name[INTEGRITY_KEYRING_MAX] = { |
34 | "_evm", | 25 | "_evm", |
35 | "_module", | 26 | "_module", |
36 | "_ima", | 27 | "_ima", |
37 | }; | 28 | }; |
38 | #endif | ||
39 | 29 | ||
40 | int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, | 30 | int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, |
41 | const char *digest, int digestlen) | 31 | const char *digest, int digestlen) |
@@ -45,7 +35,7 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, | |||
45 | 35 | ||
46 | if (!keyring[id]) { | 36 | if (!keyring[id]) { |
47 | keyring[id] = | 37 | keyring[id] = |
48 | request_key(&key_type_keyring, keyring_name[id], NULL); | 38 | request_key(&key_type_keyring, keyring_name[id], NULL); |
49 | if (IS_ERR(keyring[id])) { | 39 | if (IS_ERR(keyring[id])) { |
50 | int err = PTR_ERR(keyring[id]); | 40 | int err = PTR_ERR(keyring[id]); |
51 | pr_err("no %s keyring: %d\n", keyring_name[id], err); | 41 | pr_err("no %s keyring: %d\n", keyring_name[id], err); |
@@ -66,21 +56,3 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, | |||
66 | 56 | ||
67 | return -EOPNOTSUPP; | 57 | return -EOPNOTSUPP; |
68 | } | 58 | } |
69 | |||
70 | int integrity_init_keyring(const unsigned int id) | ||
71 | { | ||
72 | const struct cred *cred = current_cred(); | ||
73 | const struct user_struct *user = cred->user; | ||
74 | |||
75 | keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0), | ||
76 | KGIDT_INIT(0), cred, | ||
77 | ((KEY_POS_ALL & ~KEY_POS_SETATTR) | | ||
78 | KEY_USR_VIEW | KEY_USR_READ), | ||
79 | KEY_ALLOC_NOT_IN_QUOTA, user->uid_keyring); | ||
80 | if (!IS_ERR(keyring[id])) | ||
81 | set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags); | ||
82 | else | ||
83 | pr_info("Can't allocate %s keyring (%ld)\n", | ||
84 | keyring_name[id], PTR_ERR(keyring[id])); | ||
85 | return 0; | ||
86 | } | ||
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index dad8d4ca2437..81a27971d884 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig | |||
@@ -123,11 +123,3 @@ config IMA_APPRAISE | |||
123 | For more information on integrity appraisal refer to: | 123 | For more information on integrity appraisal refer to: |
124 | <http://linux-ima.sourceforge.net> | 124 | <http://linux-ima.sourceforge.net> |
125 | If unsure, say N. | 125 | If unsure, say N. |
126 | |||
127 | config IMA_TRUSTED_KEYRING | ||
128 | bool "Require all keys on the _ima keyring be signed" | ||
129 | depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING | ||
130 | default y | ||
131 | help | ||
132 | This option requires that all keys added to the _ima | ||
133 | keyring be signed by a key on the system trusted keyring. | ||
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_appraise.c b/security/integrity/ima/ima_appraise.c index 46353ee517f6..734e9468aca0 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c | |||
@@ -381,14 +381,3 @@ int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name) | |||
381 | } | 381 | } |
382 | return result; | 382 | return result; |
383 | } | 383 | } |
384 | |||
385 | #ifdef CONFIG_IMA_TRUSTED_KEYRING | ||
386 | static int __init init_ima_keyring(void) | ||
387 | { | ||
388 | int ret; | ||
389 | |||
390 | ret = integrity_init_keyring(INTEGRITY_KEYRING_IMA); | ||
391 | return 0; | ||
392 | } | ||
393 | late_initcall(init_ima_keyring); | ||
394 | #endif | ||
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 6d01c694a32c..1683bbf289a4 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: |
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index b9e7c133734a..2fb5e53e927f 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h | |||
@@ -137,19 +137,12 @@ static inline int integrity_digsig_verify(const unsigned int id, | |||
137 | #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS | 137 | #ifdef CONFIG_INTEGRITY_ASYMMETRIC_KEYS |
138 | int asymmetric_verify(struct key *keyring, const char *sig, | 138 | int asymmetric_verify(struct key *keyring, const char *sig, |
139 | int siglen, const char *data, int datalen); | 139 | int siglen, const char *data, int datalen); |
140 | |||
141 | int integrity_init_keyring(const unsigned int id); | ||
142 | #else | 140 | #else |
143 | static inline int asymmetric_verify(struct key *keyring, const char *sig, | 141 | static inline int asymmetric_verify(struct key *keyring, const char *sig, |
144 | int siglen, const char *data, int datalen) | 142 | int siglen, const char *data, int datalen) |
145 | { | 143 | { |
146 | return -EOPNOTSUPP; | 144 | return -EOPNOTSUPP; |
147 | } | 145 | } |
148 | |||
149 | static int integrity_init_keyring(const unsigned int id) | ||
150 | { | ||
151 | return 0; | ||
152 | } | ||
153 | #endif | 146 | #endif |
154 | 147 | ||
155 | #ifdef CONFIG_INTEGRITY_AUDIT | 148 | #ifdef CONFIG_INTEGRITY_AUDIT |
diff --git a/security/keys/big_key.c b/security/keys/big_key.c index 2cf5e62d67af..8137b27d641d 100644 --- a/security/keys/big_key.c +++ b/security/keys/big_key.c | |||
@@ -70,7 +70,7 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | |||
70 | * | 70 | * |
71 | * TODO: Encrypt the stored data with a temporary key. | 71 | * TODO: Encrypt the stored data with a temporary key. |
72 | */ | 72 | */ |
73 | file = shmem_file_setup("", datalen, 0); | 73 | file = shmem_kernel_file_setup("", datalen, 0); |
74 | if (IS_ERR(file)) { | 74 | if (IS_ERR(file)) { |
75 | ret = PTR_ERR(file); | 75 | ret = PTR_ERR(file); |
76 | goto err_quota; | 76 | goto err_quota; |
@@ -78,6 +78,7 @@ int big_key_instantiate(struct key *key, struct key_preparsed_payload *prep) | |||
78 | 78 | ||
79 | written = kernel_write(file, prep->data, prep->datalen, 0); | 79 | written = kernel_write(file, prep->data, prep->datalen, 0); |
80 | if (written != datalen) { | 80 | if (written != datalen) { |
81 | ret = written; | ||
81 | if (written >= 0) | 82 | if (written >= 0) |
82 | ret = -ENOMEM; | 83 | ret = -ENOMEM; |
83 | goto err_fput; | 84 | goto err_fput; |
diff --git a/security/keys/gc.c b/security/keys/gc.c index cce621c33dce..d3222b6d7d59 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c | |||
@@ -130,46 +130,6 @@ void key_gc_keytype(struct key_type *ktype) | |||
130 | kleave(""); | 130 | kleave(""); |
131 | } | 131 | } |
132 | 132 | ||
133 | static int key_gc_keyring_func(const void *object, void *iterator_data) | ||
134 | { | ||
135 | const struct key *key = object; | ||
136 | time_t *limit = iterator_data; | ||
137 | return key_is_dead(key, *limit); | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * Garbage collect pointers from a keyring. | ||
142 | * | ||
143 | * Not called with any locks held. The keyring's key struct will not be | ||
144 | * deallocated under us as only our caller may deallocate it. | ||
145 | */ | ||
146 | static void key_gc_keyring(struct key *keyring, time_t limit) | ||
147 | { | ||
148 | int result; | ||
149 | |||
150 | kenter("%x{%s}", keyring->serial, keyring->description ?: ""); | ||
151 | |||
152 | if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) | | ||
153 | (1 << KEY_FLAG_REVOKED))) | ||
154 | goto dont_gc; | ||
155 | |||
156 | /* scan the keyring looking for dead keys */ | ||
157 | rcu_read_lock(); | ||
158 | result = assoc_array_iterate(&keyring->keys, | ||
159 | key_gc_keyring_func, &limit); | ||
160 | rcu_read_unlock(); | ||
161 | if (result == true) | ||
162 | goto do_gc; | ||
163 | |||
164 | dont_gc: | ||
165 | kleave(" [no gc]"); | ||
166 | return; | ||
167 | |||
168 | do_gc: | ||
169 | keyring_gc(keyring, limit); | ||
170 | kleave(" [gc]"); | ||
171 | } | ||
172 | |||
173 | /* | 133 | /* |
174 | * Garbage collect a list of unreferenced, detached keys | 134 | * Garbage collect a list of unreferenced, detached keys |
175 | */ | 135 | */ |
@@ -388,7 +348,7 @@ found_unreferenced_key: | |||
388 | */ | 348 | */ |
389 | found_keyring: | 349 | found_keyring: |
390 | spin_unlock(&key_serial_lock); | 350 | spin_unlock(&key_serial_lock); |
391 | key_gc_keyring(key, limit); | 351 | keyring_gc(key, limit); |
392 | goto maybe_resched; | 352 | goto maybe_resched; |
393 | 353 | ||
394 | /* We found a dead key that is still referenced. Reset its type and | 354 | /* We found a dead key that is still referenced. Reset its type and |
diff --git a/security/keys/key.c b/security/keys/key.c index 55d110f0aced..6e21c11e48bc 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -272,7 +272,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
272 | } | 272 | } |
273 | 273 | ||
274 | /* allocate and initialise the key and its description */ | 274 | /* allocate and initialise the key and its description */ |
275 | key = kmem_cache_alloc(key_jar, GFP_KERNEL); | 275 | key = kmem_cache_zalloc(key_jar, GFP_KERNEL); |
276 | if (!key) | 276 | if (!key) |
277 | goto no_memory_2; | 277 | goto no_memory_2; |
278 | 278 | ||
@@ -293,18 +293,12 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
293 | key->uid = uid; | 293 | key->uid = uid; |
294 | key->gid = gid; | 294 | key->gid = gid; |
295 | key->perm = perm; | 295 | key->perm = perm; |
296 | key->flags = 0; | ||
297 | key->expiry = 0; | ||
298 | key->payload.data = NULL; | ||
299 | key->security = NULL; | ||
300 | 296 | ||
301 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) | 297 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) |
302 | key->flags |= 1 << KEY_FLAG_IN_QUOTA; | 298 | key->flags |= 1 << KEY_FLAG_IN_QUOTA; |
303 | if (flags & KEY_ALLOC_TRUSTED) | 299 | if (flags & KEY_ALLOC_TRUSTED) |
304 | key->flags |= 1 << KEY_FLAG_TRUSTED; | 300 | key->flags |= 1 << KEY_FLAG_TRUSTED; |
305 | 301 | ||
306 | memset(&key->type_data, 0, sizeof(key->type_data)); | ||
307 | |||
308 | #ifdef KEY_DEBUGGING | 302 | #ifdef KEY_DEBUGGING |
309 | key->magic = KEY_DEBUG_MAGIC; | 303 | key->magic = KEY_DEBUG_MAGIC; |
310 | #endif | 304 | #endif |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index d80311e571c3..d46cbc5e335e 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -160,7 +160,7 @@ static u64 mult_64x32_and_fold(u64 x, u32 y) | |||
160 | static unsigned long hash_key_type_and_desc(const struct keyring_index_key *index_key) | 160 | static unsigned long hash_key_type_and_desc(const struct keyring_index_key *index_key) |
161 | { | 161 | { |
162 | const unsigned level_shift = ASSOC_ARRAY_LEVEL_STEP; | 162 | const unsigned level_shift = ASSOC_ARRAY_LEVEL_STEP; |
163 | const unsigned long level_mask = ASSOC_ARRAY_LEVEL_STEP_MASK; | 163 | const unsigned long fan_mask = ASSOC_ARRAY_FAN_MASK; |
164 | const char *description = index_key->description; | 164 | const char *description = index_key->description; |
165 | unsigned long hash, type; | 165 | unsigned long hash, type; |
166 | u32 piece; | 166 | u32 piece; |
@@ -194,10 +194,10 @@ static unsigned long hash_key_type_and_desc(const struct keyring_index_key *inde | |||
194 | * ordinary keys by making sure the lowest level segment in the hash is | 194 | * ordinary keys by making sure the lowest level segment in the hash is |
195 | * zero for keyrings and non-zero otherwise. | 195 | * zero for keyrings and non-zero otherwise. |
196 | */ | 196 | */ |
197 | if (index_key->type != &key_type_keyring && (hash & level_mask) == 0) | 197 | if (index_key->type != &key_type_keyring && (hash & fan_mask) == 0) |
198 | return hash | (hash >> (ASSOC_ARRAY_KEY_CHUNK_SIZE - level_shift)) | 1; | 198 | return hash | (hash >> (ASSOC_ARRAY_KEY_CHUNK_SIZE - level_shift)) | 1; |
199 | if (index_key->type == &key_type_keyring && (hash & level_mask) != 0) | 199 | if (index_key->type == &key_type_keyring && (hash & fan_mask) != 0) |
200 | return (hash + (hash << level_shift)) & ~level_mask; | 200 | return (hash + (hash << level_shift)) & ~fan_mask; |
201 | return hash; | 201 | return hash; |
202 | } | 202 | } |
203 | 203 | ||
@@ -279,12 +279,11 @@ static bool keyring_compare_object(const void *object, const void *data) | |||
279 | * Compare the index keys of a pair of objects and determine the bit position | 279 | * Compare the index keys of a pair of objects and determine the bit position |
280 | * at which they differ - if they differ. | 280 | * at which they differ - if they differ. |
281 | */ | 281 | */ |
282 | static int keyring_diff_objects(const void *_a, const void *_b) | 282 | static int keyring_diff_objects(const void *object, const void *data) |
283 | { | 283 | { |
284 | const struct key *key_a = keyring_ptr_to_key(_a); | 284 | const struct key *key_a = keyring_ptr_to_key(object); |
285 | const struct key *key_b = keyring_ptr_to_key(_b); | ||
286 | const struct keyring_index_key *a = &key_a->index_key; | 285 | const struct keyring_index_key *a = &key_a->index_key; |
287 | const struct keyring_index_key *b = &key_b->index_key; | 286 | const struct keyring_index_key *b = data; |
288 | unsigned long seg_a, seg_b; | 287 | unsigned long seg_a, seg_b; |
289 | int level, i; | 288 | int level, i; |
290 | 289 | ||
@@ -691,8 +690,8 @@ descend_to_node: | |||
691 | smp_read_barrier_depends(); | 690 | smp_read_barrier_depends(); |
692 | ptr = ACCESS_ONCE(shortcut->next_node); | 691 | ptr = ACCESS_ONCE(shortcut->next_node); |
693 | BUG_ON(!assoc_array_ptr_is_node(ptr)); | 692 | BUG_ON(!assoc_array_ptr_is_node(ptr)); |
694 | node = assoc_array_ptr_to_node(ptr); | ||
695 | } | 693 | } |
694 | node = assoc_array_ptr_to_node(ptr); | ||
696 | 695 | ||
697 | begin_node: | 696 | begin_node: |
698 | kdebug("begin_node"); | 697 | kdebug("begin_node"); |
@@ -1304,7 +1303,7 @@ static void keyring_revoke(struct key *keyring) | |||
1304 | } | 1303 | } |
1305 | } | 1304 | } |
1306 | 1305 | ||
1307 | static bool gc_iterator(void *object, void *iterator_data) | 1306 | static bool keyring_gc_select_iterator(void *object, void *iterator_data) |
1308 | { | 1307 | { |
1309 | struct key *key = keyring_ptr_to_key(object); | 1308 | struct key *key = keyring_ptr_to_key(object); |
1310 | time_t *limit = iterator_data; | 1309 | time_t *limit = iterator_data; |
@@ -1315,22 +1314,47 @@ static bool gc_iterator(void *object, void *iterator_data) | |||
1315 | return true; | 1314 | return true; |
1316 | } | 1315 | } |
1317 | 1316 | ||
1317 | static int keyring_gc_check_iterator(const void *object, void *iterator_data) | ||
1318 | { | ||
1319 | const struct key *key = keyring_ptr_to_key(object); | ||
1320 | time_t *limit = iterator_data; | ||
1321 | |||
1322 | key_check(key); | ||
1323 | return key_is_dead(key, *limit); | ||
1324 | } | ||
1325 | |||
1318 | /* | 1326 | /* |
1319 | * Collect garbage from the contents of a keyring, replacing the old list with | 1327 | * Garbage collect pointers from a keyring. |
1320 | * a new one with the pointers all shuffled down. | ||
1321 | * | 1328 | * |
1322 | * Dead keys are classed as oned that are flagged as being dead or are revoked, | 1329 | * Not called with any locks held. The keyring's key struct will not be |
1323 | * expired or negative keys that were revoked or expired before the specified | 1330 | * deallocated under us as only our caller may deallocate it. |
1324 | * limit. | ||
1325 | */ | 1331 | */ |
1326 | void keyring_gc(struct key *keyring, time_t limit) | 1332 | void keyring_gc(struct key *keyring, time_t limit) |
1327 | { | 1333 | { |
1328 | kenter("{%x,%s}", key_serial(keyring), keyring->description); | 1334 | int result; |
1329 | 1335 | ||
1336 | kenter("%x{%s}", keyring->serial, keyring->description ?: ""); | ||
1337 | |||
1338 | if (keyring->flags & ((1 << KEY_FLAG_INVALIDATED) | | ||
1339 | (1 << KEY_FLAG_REVOKED))) | ||
1340 | goto dont_gc; | ||
1341 | |||
1342 | /* scan the keyring looking for dead keys */ | ||
1343 | rcu_read_lock(); | ||
1344 | result = assoc_array_iterate(&keyring->keys, | ||
1345 | keyring_gc_check_iterator, &limit); | ||
1346 | rcu_read_unlock(); | ||
1347 | if (result == true) | ||
1348 | goto do_gc; | ||
1349 | |||
1350 | dont_gc: | ||
1351 | kleave(" [no gc]"); | ||
1352 | return; | ||
1353 | |||
1354 | do_gc: | ||
1330 | down_write(&keyring->sem); | 1355 | down_write(&keyring->sem); |
1331 | assoc_array_gc(&keyring->keys, &keyring_assoc_array_ops, | 1356 | assoc_array_gc(&keyring->keys, &keyring_assoc_array_ops, |
1332 | gc_iterator, &limit); | 1357 | keyring_gc_select_iterator, &limit); |
1333 | up_write(&keyring->sem); | 1358 | up_write(&keyring->sem); |
1334 | 1359 | kleave(" [gc]"); | |
1335 | kleave(""); | ||
1336 | } | 1360 | } |
diff --git a/security/keys/persistent.c b/security/keys/persistent.c index 82f4957a7acf..0ad3ee283781 100644 --- a/security/keys/persistent.c +++ b/security/keys/persistent.c | |||
@@ -144,10 +144,8 @@ long keyctl_get_persistent(uid_t _uid, key_serial_t destid) | |||
144 | /* You can only see your own persistent cache if you're not | 144 | /* You can only see your own persistent cache if you're not |
145 | * sufficiently privileged. | 145 | * sufficiently privileged. |
146 | */ | 146 | */ |
147 | if (uid_eq(uid, current_uid()) && | 147 | if (!uid_eq(uid, current_uid()) && |
148 | uid_eq(uid, current_suid()) && | 148 | !uid_eq(uid, current_euid()) && |
149 | uid_eq(uid, current_euid()) && | ||
150 | uid_eq(uid, current_fsuid()) && | ||
151 | !ns_capable(ns, CAP_SETUID)) | 149 | !ns_capable(ns, CAP_SETUID)) |
152 | return -EPERM; | 150 | return -EPERM; |
153 | } | 151 | } |
diff --git a/security/lsm_audit.c b/security/lsm_audit.c index 8d8d97dbb389..9a62045e6282 100644 --- a/security/lsm_audit.c +++ b/security/lsm_audit.c | |||
@@ -302,18 +302,19 @@ static void dump_common_audit_data(struct audit_buffer *ab, | |||
302 | "faddr", "fport"); | 302 | "faddr", "fport"); |
303 | break; | 303 | break; |
304 | } | 304 | } |
305 | #if IS_ENABLED(CONFIG_IPV6) | ||
305 | case AF_INET6: { | 306 | case AF_INET6: { |
306 | struct inet_sock *inet = inet_sk(sk); | 307 | struct inet_sock *inet = inet_sk(sk); |
307 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | ||
308 | 308 | ||
309 | print_ipv6_addr(ab, &inet6->rcv_saddr, | 309 | print_ipv6_addr(ab, &sk->sk_v6_rcv_saddr, |
310 | inet->inet_sport, | 310 | inet->inet_sport, |
311 | "laddr", "lport"); | 311 | "laddr", "lport"); |
312 | print_ipv6_addr(ab, &inet6->daddr, | 312 | print_ipv6_addr(ab, &sk->sk_v6_daddr, |
313 | inet->inet_dport, | 313 | inet->inet_dport, |
314 | "faddr", "fport"); | 314 | "faddr", "fport"); |
315 | break; | 315 | break; |
316 | } | 316 | } |
317 | #endif | ||
317 | case AF_UNIX: | 318 | case AF_UNIX: |
318 | u = unix_sk(sk); | 319 | u = unix_sk(sk); |
319 | if (u->path.dentry) { | 320 | if (u->path.dentry) { |
@@ -396,7 +397,8 @@ void common_lsm_audit(struct common_audit_data *a, | |||
396 | if (a == NULL) | 397 | if (a == NULL) |
397 | return; | 398 | return; |
398 | /* we use GFP_ATOMIC so we won't sleep */ | 399 | /* we use GFP_ATOMIC so we won't sleep */ |
399 | ab = audit_log_start(current->audit_context, GFP_ATOMIC, AUDIT_AVC); | 400 | ab = audit_log_start(current->audit_context, GFP_ATOMIC | __GFP_NOWARN, |
401 | AUDIT_AVC); | ||
400 | 402 | ||
401 | if (ab == NULL) | 403 | if (ab == NULL) |
402 | return; | 404 | return; |
diff --git a/security/selinux/avc.c b/security/selinux/avc.c index dad36a6ab45f..fc3e6628a864 100644 --- a/security/selinux/avc.c +++ b/security/selinux/avc.c | |||
@@ -746,7 +746,6 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
746 | * @tclass: target security class | 746 | * @tclass: target security class |
747 | * @requested: requested permissions, interpreted based on @tclass | 747 | * @requested: requested permissions, interpreted based on @tclass |
748 | * @auditdata: auxiliary audit data | 748 | * @auditdata: auxiliary audit data |
749 | * @flags: VFS walk flags | ||
750 | * | 749 | * |
751 | * Check the AVC to determine whether the @requested permissions are granted | 750 | * Check the AVC to determine whether the @requested permissions are granted |
752 | * for the SID pair (@ssid, @tsid), interpreting the permissions | 751 | * for the SID pair (@ssid, @tsid), interpreting the permissions |
@@ -756,17 +755,15 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
756 | * permissions are granted, -%EACCES if any permissions are denied, or | 755 | * permissions are granted, -%EACCES if any permissions are denied, or |
757 | * another -errno upon other errors. | 756 | * another -errno upon other errors. |
758 | */ | 757 | */ |
759 | int avc_has_perm_flags(u32 ssid, u32 tsid, u16 tclass, | 758 | int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, |
760 | u32 requested, struct common_audit_data *auditdata, | 759 | u32 requested, struct common_audit_data *auditdata) |
761 | unsigned flags) | ||
762 | { | 760 | { |
763 | struct av_decision avd; | 761 | struct av_decision avd; |
764 | int rc, rc2; | 762 | int rc, rc2; |
765 | 763 | ||
766 | rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd); | 764 | rc = avc_has_perm_noaudit(ssid, tsid, tclass, requested, 0, &avd); |
767 | 765 | ||
768 | rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata, | 766 | rc2 = avc_audit(ssid, tsid, tclass, requested, &avd, rc, auditdata); |
769 | flags); | ||
770 | if (rc2) | 767 | if (rc2) |
771 | return rc2; | 768 | return rc2; |
772 | return rc; | 769 | return rc; |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 6d0bf5c0c832..6625699f497c 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -53,6 +53,7 @@ | |||
53 | #include <net/ip.h> /* for local_port_range[] */ | 53 | #include <net/ip.h> /* for local_port_range[] */ |
54 | #include <net/sock.h> | 54 | #include <net/sock.h> |
55 | #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ | 55 | #include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */ |
56 | #include <net/inet_connection_sock.h> | ||
56 | #include <net/net_namespace.h> | 57 | #include <net/net_namespace.h> |
57 | #include <net/netlabel.h> | 58 | #include <net/netlabel.h> |
58 | #include <linux/uaccess.h> | 59 | #include <linux/uaccess.h> |
@@ -95,10 +96,6 @@ | |||
95 | #include "audit.h" | 96 | #include "audit.h" |
96 | #include "avc_ss.h" | 97 | #include "avc_ss.h" |
97 | 98 | ||
98 | #define SB_TYPE_FMT "%s%s%s" | ||
99 | #define SB_SUBTYPE(sb) (sb->s_subtype && sb->s_subtype[0]) | ||
100 | #define SB_TYPE_ARGS(sb) sb->s_type->name, SB_SUBTYPE(sb) ? "." : "", SB_SUBTYPE(sb) ? sb->s_subtype : "" | ||
101 | |||
102 | extern struct security_operations *security_ops; | 99 | extern struct security_operations *security_ops; |
103 | 100 | ||
104 | /* SECMARK reference count */ | 101 | /* SECMARK reference count */ |
@@ -413,8 +410,8 @@ static int sb_finish_set_opts(struct super_block *sb) | |||
413 | the first boot of the SELinux kernel before we have | 410 | the first boot of the SELinux kernel before we have |
414 | assigned xattr values to the filesystem. */ | 411 | assigned xattr values to the filesystem. */ |
415 | if (!root_inode->i_op->getxattr) { | 412 | if (!root_inode->i_op->getxattr) { |
416 | printk(KERN_WARNING "SELinux: (dev %s, type "SB_TYPE_FMT") has no " | 413 | printk(KERN_WARNING "SELinux: (dev %s, type %s) has no " |
417 | "xattr support\n", sb->s_id, SB_TYPE_ARGS(sb)); | 414 | "xattr support\n", sb->s_id, sb->s_type->name); |
418 | rc = -EOPNOTSUPP; | 415 | rc = -EOPNOTSUPP; |
419 | goto out; | 416 | goto out; |
420 | } | 417 | } |
@@ -422,22 +419,22 @@ static int sb_finish_set_opts(struct super_block *sb) | |||
422 | if (rc < 0 && rc != -ENODATA) { | 419 | if (rc < 0 && rc != -ENODATA) { |
423 | if (rc == -EOPNOTSUPP) | 420 | if (rc == -EOPNOTSUPP) |
424 | printk(KERN_WARNING "SELinux: (dev %s, type " | 421 | printk(KERN_WARNING "SELinux: (dev %s, type " |
425 | SB_TYPE_FMT") has no security xattr handler\n", | 422 | "%s) has no security xattr handler\n", |
426 | sb->s_id, SB_TYPE_ARGS(sb)); | 423 | sb->s_id, sb->s_type->name); |
427 | else | 424 | else |
428 | printk(KERN_WARNING "SELinux: (dev %s, type " | 425 | printk(KERN_WARNING "SELinux: (dev %s, type " |
429 | SB_TYPE_FMT") getxattr errno %d\n", sb->s_id, | 426 | "%s) getxattr errno %d\n", sb->s_id, |
430 | SB_TYPE_ARGS(sb), -rc); | 427 | sb->s_type->name, -rc); |
431 | goto out; | 428 | goto out; |
432 | } | 429 | } |
433 | } | 430 | } |
434 | 431 | ||
435 | if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) | 432 | if (sbsec->behavior > ARRAY_SIZE(labeling_behaviors)) |
436 | printk(KERN_ERR "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), unknown behavior\n", | 433 | printk(KERN_ERR "SELinux: initialized (dev %s, type %s), unknown behavior\n", |
437 | sb->s_id, SB_TYPE_ARGS(sb)); | 434 | sb->s_id, sb->s_type->name); |
438 | else | 435 | else |
439 | printk(KERN_DEBUG "SELinux: initialized (dev %s, type "SB_TYPE_FMT"), %s\n", | 436 | printk(KERN_DEBUG "SELinux: initialized (dev %s, type %s), %s\n", |
440 | sb->s_id, SB_TYPE_ARGS(sb), | 437 | sb->s_id, sb->s_type->name, |
441 | labeling_behaviors[sbsec->behavior-1]); | 438 | labeling_behaviors[sbsec->behavior-1]); |
442 | 439 | ||
443 | sbsec->flags |= SE_SBINITIALIZED; | 440 | sbsec->flags |= SE_SBINITIALIZED; |
@@ -600,6 +597,7 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
600 | const struct cred *cred = current_cred(); | 597 | const struct cred *cred = current_cred(); |
601 | int rc = 0, i; | 598 | int rc = 0, i; |
602 | struct superblock_security_struct *sbsec = sb->s_security; | 599 | struct superblock_security_struct *sbsec = sb->s_security; |
600 | const char *name = sb->s_type->name; | ||
603 | struct inode *inode = sbsec->sb->s_root->d_inode; | 601 | struct inode *inode = sbsec->sb->s_root->d_inode; |
604 | struct inode_security_struct *root_isec = inode->i_security; | 602 | struct inode_security_struct *root_isec = inode->i_security; |
605 | u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; | 603 | u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0; |
@@ -658,8 +656,8 @@ static int selinux_set_mnt_opts(struct super_block *sb, | |||
658 | strlen(mount_options[i]), &sid); | 656 | strlen(mount_options[i]), &sid); |
659 | if (rc) { | 657 | if (rc) { |
660 | printk(KERN_WARNING "SELinux: security_context_to_sid" | 658 | printk(KERN_WARNING "SELinux: security_context_to_sid" |
661 | "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n", | 659 | "(%s) failed for (dev %s, type %s) errno=%d\n", |
662 | mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc); | 660 | mount_options[i], sb->s_id, name, rc); |
663 | goto out; | 661 | goto out; |
664 | } | 662 | } |
665 | switch (flags[i]) { | 663 | switch (flags[i]) { |
@@ -806,8 +804,7 @@ out: | |||
806 | out_double_mount: | 804 | out_double_mount: |
807 | rc = -EINVAL; | 805 | rc = -EINVAL; |
808 | printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different " | 806 | printk(KERN_WARNING "SELinux: mount invalid. Same superblock, different " |
809 | "security settings for (dev %s, type "SB_TYPE_FMT")\n", sb->s_id, | 807 | "security settings for (dev %s, type %s)\n", sb->s_id, name); |
810 | SB_TYPE_ARGS(sb)); | ||
811 | goto out; | 808 | goto out; |
812 | } | 809 | } |
813 | 810 | ||
@@ -1539,7 +1536,7 @@ static int cred_has_capability(const struct cred *cred, | |||
1539 | 1536 | ||
1540 | rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); | 1537 | rc = avc_has_perm_noaudit(sid, sid, sclass, av, 0, &avd); |
1541 | if (audit == SECURITY_CAP_AUDIT) { | 1538 | if (audit == SECURITY_CAP_AUDIT) { |
1542 | int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad, 0); | 1539 | int rc2 = avc_audit(sid, sid, sclass, av, &avd, rc, &ad); |
1543 | if (rc2) | 1540 | if (rc2) |
1544 | return rc2; | 1541 | return rc2; |
1545 | } | 1542 | } |
@@ -1562,8 +1559,7 @@ static int task_has_system(struct task_struct *tsk, | |||
1562 | static int inode_has_perm(const struct cred *cred, | 1559 | static int inode_has_perm(const struct cred *cred, |
1563 | struct inode *inode, | 1560 | struct inode *inode, |
1564 | u32 perms, | 1561 | u32 perms, |
1565 | struct common_audit_data *adp, | 1562 | struct common_audit_data *adp) |
1566 | unsigned flags) | ||
1567 | { | 1563 | { |
1568 | struct inode_security_struct *isec; | 1564 | struct inode_security_struct *isec; |
1569 | u32 sid; | 1565 | u32 sid; |
@@ -1576,7 +1572,7 @@ static int inode_has_perm(const struct cred *cred, | |||
1576 | sid = cred_sid(cred); | 1572 | sid = cred_sid(cred); |
1577 | isec = inode->i_security; | 1573 | isec = inode->i_security; |
1578 | 1574 | ||
1579 | return avc_has_perm_flags(sid, isec->sid, isec->sclass, perms, adp, flags); | 1575 | return avc_has_perm(sid, isec->sid, isec->sclass, perms, adp); |
1580 | } | 1576 | } |
1581 | 1577 | ||
1582 | /* Same as inode_has_perm, but pass explicit audit data containing | 1578 | /* Same as inode_has_perm, but pass explicit audit data containing |
@@ -1591,7 +1587,7 @@ static inline int dentry_has_perm(const struct cred *cred, | |||
1591 | 1587 | ||
1592 | ad.type = LSM_AUDIT_DATA_DENTRY; | 1588 | ad.type = LSM_AUDIT_DATA_DENTRY; |
1593 | ad.u.dentry = dentry; | 1589 | ad.u.dentry = dentry; |
1594 | return inode_has_perm(cred, inode, av, &ad, 0); | 1590 | return inode_has_perm(cred, inode, av, &ad); |
1595 | } | 1591 | } |
1596 | 1592 | ||
1597 | /* Same as inode_has_perm, but pass explicit audit data containing | 1593 | /* Same as inode_has_perm, but pass explicit audit data containing |
@@ -1606,7 +1602,7 @@ static inline int path_has_perm(const struct cred *cred, | |||
1606 | 1602 | ||
1607 | ad.type = LSM_AUDIT_DATA_PATH; | 1603 | ad.type = LSM_AUDIT_DATA_PATH; |
1608 | ad.u.path = *path; | 1604 | ad.u.path = *path; |
1609 | return inode_has_perm(cred, inode, av, &ad, 0); | 1605 | return inode_has_perm(cred, inode, av, &ad); |
1610 | } | 1606 | } |
1611 | 1607 | ||
1612 | /* Same as path_has_perm, but uses the inode from the file struct. */ | 1608 | /* Same as path_has_perm, but uses the inode from the file struct. */ |
@@ -1618,7 +1614,7 @@ static inline int file_path_has_perm(const struct cred *cred, | |||
1618 | 1614 | ||
1619 | ad.type = LSM_AUDIT_DATA_PATH; | 1615 | ad.type = LSM_AUDIT_DATA_PATH; |
1620 | ad.u.path = file->f_path; | 1616 | ad.u.path = file->f_path; |
1621 | return inode_has_perm(cred, file_inode(file), av, &ad, 0); | 1617 | return inode_has_perm(cred, file_inode(file), av, &ad); |
1622 | } | 1618 | } |
1623 | 1619 | ||
1624 | /* Check whether a task can use an open file descriptor to | 1620 | /* Check whether a task can use an open file descriptor to |
@@ -1654,7 +1650,7 @@ static int file_has_perm(const struct cred *cred, | |||
1654 | /* av is zero if only checking access to the descriptor. */ | 1650 | /* av is zero if only checking access to the descriptor. */ |
1655 | rc = 0; | 1651 | rc = 0; |
1656 | if (av) | 1652 | if (av) |
1657 | rc = inode_has_perm(cred, inode, av, &ad, 0); | 1653 | rc = inode_has_perm(cred, inode, av, &ad); |
1658 | 1654 | ||
1659 | out: | 1655 | out: |
1660 | return rc; | 1656 | return rc; |
@@ -2481,8 +2477,8 @@ static int selinux_sb_remount(struct super_block *sb, void *data) | |||
2481 | rc = security_context_to_sid(mount_options[i], len, &sid); | 2477 | rc = security_context_to_sid(mount_options[i], len, &sid); |
2482 | if (rc) { | 2478 | if (rc) { |
2483 | printk(KERN_WARNING "SELinux: security_context_to_sid" | 2479 | printk(KERN_WARNING "SELinux: security_context_to_sid" |
2484 | "(%s) failed for (dev %s, type "SB_TYPE_FMT") errno=%d\n", | 2480 | "(%s) failed for (dev %s, type %s) errno=%d\n", |
2485 | mount_options[i], sb->s_id, SB_TYPE_ARGS(sb), rc); | 2481 | mount_options[i], sb->s_id, sb->s_type->name, rc); |
2486 | goto out_free_opts; | 2482 | goto out_free_opts; |
2487 | } | 2483 | } |
2488 | rc = -EINVAL; | 2484 | rc = -EINVAL; |
@@ -2520,8 +2516,8 @@ out_free_secdata: | |||
2520 | return rc; | 2516 | return rc; |
2521 | out_bad_option: | 2517 | out_bad_option: |
2522 | printk(KERN_WARNING "SELinux: unable to change security options " | 2518 | printk(KERN_WARNING "SELinux: unable to change security options " |
2523 | "during remount (dev %s, type "SB_TYPE_FMT")\n", sb->s_id, | 2519 | "during remount (dev %s, type=%s)\n", sb->s_id, |
2524 | SB_TYPE_ARGS(sb)); | 2520 | sb->s_type->name); |
2525 | goto out_free_opts; | 2521 | goto out_free_opts; |
2526 | } | 2522 | } |
2527 | 2523 | ||
@@ -3829,7 +3825,7 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) | |||
3829 | u32 nlbl_sid; | 3825 | u32 nlbl_sid; |
3830 | u32 nlbl_type; | 3826 | u32 nlbl_type; |
3831 | 3827 | ||
3832 | err = selinux_skb_xfrm_sid(skb, &xfrm_sid); | 3828 | err = selinux_xfrm_skb_sid(skb, &xfrm_sid); |
3833 | if (unlikely(err)) | 3829 | if (unlikely(err)) |
3834 | return -EACCES; | 3830 | return -EACCES; |
3835 | err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); | 3831 | err = selinux_netlbl_skbuff_getsid(skb, family, &nlbl_type, &nlbl_sid); |
@@ -3847,6 +3843,30 @@ static int selinux_skb_peerlbl_sid(struct sk_buff *skb, u16 family, u32 *sid) | |||
3847 | return 0; | 3843 | return 0; |
3848 | } | 3844 | } |
3849 | 3845 | ||
3846 | /** | ||
3847 | * selinux_conn_sid - Determine the child socket label for a connection | ||
3848 | * @sk_sid: the parent socket's SID | ||
3849 | * @skb_sid: the packet's SID | ||
3850 | * @conn_sid: the resulting connection SID | ||
3851 | * | ||
3852 | * If @skb_sid is valid then the user:role:type information from @sk_sid is | ||
3853 | * combined with the MLS information from @skb_sid in order to create | ||
3854 | * @conn_sid. If @skb_sid is not valid then then @conn_sid is simply a copy | ||
3855 | * of @sk_sid. Returns zero on success, negative values on failure. | ||
3856 | * | ||
3857 | */ | ||
3858 | static int selinux_conn_sid(u32 sk_sid, u32 skb_sid, u32 *conn_sid) | ||
3859 | { | ||
3860 | int err = 0; | ||
3861 | |||
3862 | if (skb_sid != SECSID_NULL) | ||
3863 | err = security_sid_mls_copy(sk_sid, skb_sid, conn_sid); | ||
3864 | else | ||
3865 | *conn_sid = sk_sid; | ||
3866 | |||
3867 | return err; | ||
3868 | } | ||
3869 | |||
3850 | /* socket security operations */ | 3870 | /* socket security operations */ |
3851 | 3871 | ||
3852 | static int socket_sockcreate_sid(const struct task_security_struct *tsec, | 3872 | static int socket_sockcreate_sid(const struct task_security_struct *tsec, |
@@ -3970,7 +3990,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in | |||
3970 | if (snum) { | 3990 | if (snum) { |
3971 | int low, high; | 3991 | int low, high; |
3972 | 3992 | ||
3973 | inet_get_local_port_range(&low, &high); | 3993 | inet_get_local_port_range(sock_net(sk), &low, &high); |
3974 | 3994 | ||
3975 | if (snum < max(PROT_SOCK, low) || snum > high) { | 3995 | if (snum < max(PROT_SOCK, low) || snum > high) { |
3976 | err = sel_netport_sid(sk->sk_protocol, | 3996 | err = sel_netport_sid(sk->sk_protocol, |
@@ -4314,8 +4334,10 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
4314 | } | 4334 | } |
4315 | err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, | 4335 | err = avc_has_perm(sk_sid, peer_sid, SECCLASS_PEER, |
4316 | PEER__RECV, &ad); | 4336 | PEER__RECV, &ad); |
4317 | if (err) | 4337 | if (err) { |
4318 | selinux_netlbl_err(skb, err, 0); | 4338 | selinux_netlbl_err(skb, err, 0); |
4339 | return err; | ||
4340 | } | ||
4319 | } | 4341 | } |
4320 | 4342 | ||
4321 | if (secmark_active) { | 4343 | if (secmark_active) { |
@@ -4453,7 +4475,7 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
4453 | struct sk_security_struct *sksec = sk->sk_security; | 4475 | struct sk_security_struct *sksec = sk->sk_security; |
4454 | int err; | 4476 | int err; |
4455 | u16 family = sk->sk_family; | 4477 | u16 family = sk->sk_family; |
4456 | u32 newsid; | 4478 | u32 connsid; |
4457 | u32 peersid; | 4479 | u32 peersid; |
4458 | 4480 | ||
4459 | /* handle mapped IPv4 packets arriving via IPv6 sockets */ | 4481 | /* handle mapped IPv4 packets arriving via IPv6 sockets */ |
@@ -4463,16 +4485,11 @@ static int selinux_inet_conn_request(struct sock *sk, struct sk_buff *skb, | |||
4463 | err = selinux_skb_peerlbl_sid(skb, family, &peersid); | 4485 | err = selinux_skb_peerlbl_sid(skb, family, &peersid); |
4464 | if (err) | 4486 | if (err) |
4465 | return err; | 4487 | return err; |
4466 | if (peersid == SECSID_NULL) { | 4488 | err = selinux_conn_sid(sksec->sid, peersid, &connsid); |
4467 | req->secid = sksec->sid; | 4489 | if (err) |
4468 | req->peer_secid = SECSID_NULL; | 4490 | return err; |
4469 | } else { | 4491 | req->secid = connsid; |
4470 | err = security_sid_mls_copy(sksec->sid, peersid, &newsid); | 4492 | req->peer_secid = peersid; |
4471 | if (err) | ||
4472 | return err; | ||
4473 | req->secid = newsid; | ||
4474 | req->peer_secid = peersid; | ||
4475 | } | ||
4476 | 4493 | ||
4477 | return selinux_netlbl_inet_conn_request(req, family); | 4494 | return selinux_netlbl_inet_conn_request(req, family); |
4478 | } | 4495 | } |
@@ -4709,7 +4726,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex, | |||
4709 | return NF_ACCEPT; | 4726 | return NF_ACCEPT; |
4710 | } | 4727 | } |
4711 | 4728 | ||
4712 | static unsigned int selinux_ipv4_forward(unsigned int hooknum, | 4729 | static unsigned int selinux_ipv4_forward(const struct nf_hook_ops *ops, |
4713 | struct sk_buff *skb, | 4730 | struct sk_buff *skb, |
4714 | const struct net_device *in, | 4731 | const struct net_device *in, |
4715 | const struct net_device *out, | 4732 | const struct net_device *out, |
@@ -4719,7 +4736,7 @@ static unsigned int selinux_ipv4_forward(unsigned int hooknum, | |||
4719 | } | 4736 | } |
4720 | 4737 | ||
4721 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 4738 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
4722 | static unsigned int selinux_ipv6_forward(unsigned int hooknum, | 4739 | static unsigned int selinux_ipv6_forward(const struct nf_hook_ops *ops, |
4723 | struct sk_buff *skb, | 4740 | struct sk_buff *skb, |
4724 | const struct net_device *in, | 4741 | const struct net_device *in, |
4725 | const struct net_device *out, | 4742 | const struct net_device *out, |
@@ -4732,6 +4749,7 @@ static unsigned int selinux_ipv6_forward(unsigned int hooknum, | |||
4732 | static unsigned int selinux_ip_output(struct sk_buff *skb, | 4749 | static unsigned int selinux_ip_output(struct sk_buff *skb, |
4733 | u16 family) | 4750 | u16 family) |
4734 | { | 4751 | { |
4752 | struct sock *sk; | ||
4735 | u32 sid; | 4753 | u32 sid; |
4736 | 4754 | ||
4737 | if (!netlbl_enabled()) | 4755 | if (!netlbl_enabled()) |
@@ -4740,8 +4758,27 @@ static unsigned int selinux_ip_output(struct sk_buff *skb, | |||
4740 | /* we do this in the LOCAL_OUT path and not the POST_ROUTING path | 4758 | /* we do this in the LOCAL_OUT path and not the POST_ROUTING path |
4741 | * because we want to make sure we apply the necessary labeling | 4759 | * because we want to make sure we apply the necessary labeling |
4742 | * before IPsec is applied so we can leverage AH protection */ | 4760 | * before IPsec is applied so we can leverage AH protection */ |
4743 | if (skb->sk) { | 4761 | sk = skb->sk; |
4744 | struct sk_security_struct *sksec = skb->sk->sk_security; | 4762 | if (sk) { |
4763 | struct sk_security_struct *sksec; | ||
4764 | |||
4765 | if (sk->sk_state == TCP_LISTEN) | ||
4766 | /* if the socket is the listening state then this | ||
4767 | * packet is a SYN-ACK packet which means it needs to | ||
4768 | * be labeled based on the connection/request_sock and | ||
4769 | * not the parent socket. unfortunately, we can't | ||
4770 | * lookup the request_sock yet as it isn't queued on | ||
4771 | * the parent socket until after the SYN-ACK is sent. | ||
4772 | * the "solution" is to simply pass the packet as-is | ||
4773 | * as any IP option based labeling should be copied | ||
4774 | * from the initial connection request (in the IP | ||
4775 | * layer). it is far from ideal, but until we get a | ||
4776 | * security label in the packet itself this is the | ||
4777 | * best we can do. */ | ||
4778 | return NF_ACCEPT; | ||
4779 | |||
4780 | /* standard practice, label using the parent socket */ | ||
4781 | sksec = sk->sk_security; | ||
4745 | sid = sksec->sid; | 4782 | sid = sksec->sid; |
4746 | } else | 4783 | } else |
4747 | sid = SECINITSID_KERNEL; | 4784 | sid = SECINITSID_KERNEL; |
@@ -4751,7 +4788,7 @@ static unsigned int selinux_ip_output(struct sk_buff *skb, | |||
4751 | return NF_ACCEPT; | 4788 | return NF_ACCEPT; |
4752 | } | 4789 | } |
4753 | 4790 | ||
4754 | static unsigned int selinux_ipv4_output(unsigned int hooknum, | 4791 | static unsigned int selinux_ipv4_output(const struct nf_hook_ops *ops, |
4755 | struct sk_buff *skb, | 4792 | struct sk_buff *skb, |
4756 | const struct net_device *in, | 4793 | const struct net_device *in, |
4757 | const struct net_device *out, | 4794 | const struct net_device *out, |
@@ -4811,27 +4848,36 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4811 | * as fast and as clean as possible. */ | 4848 | * as fast and as clean as possible. */ |
4812 | if (!selinux_policycap_netpeer) | 4849 | if (!selinux_policycap_netpeer) |
4813 | return selinux_ip_postroute_compat(skb, ifindex, family); | 4850 | return selinux_ip_postroute_compat(skb, ifindex, family); |
4851 | |||
4852 | secmark_active = selinux_secmark_enabled(); | ||
4853 | peerlbl_active = selinux_peerlbl_enabled(); | ||
4854 | if (!secmark_active && !peerlbl_active) | ||
4855 | return NF_ACCEPT; | ||
4856 | |||
4857 | sk = skb->sk; | ||
4858 | |||
4814 | #ifdef CONFIG_XFRM | 4859 | #ifdef CONFIG_XFRM |
4815 | /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec | 4860 | /* If skb->dst->xfrm is non-NULL then the packet is undergoing an IPsec |
4816 | * packet transformation so allow the packet to pass without any checks | 4861 | * packet transformation so allow the packet to pass without any checks |
4817 | * since we'll have another chance to perform access control checks | 4862 | * since we'll have another chance to perform access control checks |
4818 | * when the packet is on it's final way out. | 4863 | * when the packet is on it's final way out. |
4819 | * NOTE: there appear to be some IPv6 multicast cases where skb->dst | 4864 | * NOTE: there appear to be some IPv6 multicast cases where skb->dst |
4820 | * is NULL, in this case go ahead and apply access control. */ | 4865 | * is NULL, in this case go ahead and apply access control. |
4821 | if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL) | 4866 | * NOTE: if this is a local socket (skb->sk != NULL) that is in the |
4867 | * TCP listening state we cannot wait until the XFRM processing | ||
4868 | * is done as we will miss out on the SA label if we do; | ||
4869 | * unfortunately, this means more work, but it is only once per | ||
4870 | * connection. */ | ||
4871 | if (skb_dst(skb) != NULL && skb_dst(skb)->xfrm != NULL && | ||
4872 | !(sk != NULL && sk->sk_state == TCP_LISTEN)) | ||
4822 | return NF_ACCEPT; | 4873 | return NF_ACCEPT; |
4823 | #endif | 4874 | #endif |
4824 | secmark_active = selinux_secmark_enabled(); | ||
4825 | peerlbl_active = selinux_peerlbl_enabled(); | ||
4826 | if (!secmark_active && !peerlbl_active) | ||
4827 | return NF_ACCEPT; | ||
4828 | 4875 | ||
4829 | /* if the packet is being forwarded then get the peer label from the | ||
4830 | * packet itself; otherwise check to see if it is from a local | ||
4831 | * application or the kernel, if from an application get the peer label | ||
4832 | * from the sending socket, otherwise use the kernel's sid */ | ||
4833 | sk = skb->sk; | ||
4834 | if (sk == NULL) { | 4876 | if (sk == NULL) { |
4877 | /* Without an associated socket the packet is either coming | ||
4878 | * from the kernel or it is being forwarded; check the packet | ||
4879 | * to determine which and if the packet is being forwarded | ||
4880 | * query the packet directly to determine the security label. */ | ||
4835 | if (skb->skb_iif) { | 4881 | if (skb->skb_iif) { |
4836 | secmark_perm = PACKET__FORWARD_OUT; | 4882 | secmark_perm = PACKET__FORWARD_OUT; |
4837 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) | 4883 | if (selinux_skb_peerlbl_sid(skb, family, &peer_sid)) |
@@ -4840,7 +4886,45 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4840 | secmark_perm = PACKET__SEND; | 4886 | secmark_perm = PACKET__SEND; |
4841 | peer_sid = SECINITSID_KERNEL; | 4887 | peer_sid = SECINITSID_KERNEL; |
4842 | } | 4888 | } |
4889 | } else if (sk->sk_state == TCP_LISTEN) { | ||
4890 | /* Locally generated packet but the associated socket is in the | ||
4891 | * listening state which means this is a SYN-ACK packet. In | ||
4892 | * this particular case the correct security label is assigned | ||
4893 | * to the connection/request_sock but unfortunately we can't | ||
4894 | * query the request_sock as it isn't queued on the parent | ||
4895 | * socket until after the SYN-ACK packet is sent; the only | ||
4896 | * viable choice is to regenerate the label like we do in | ||
4897 | * selinux_inet_conn_request(). See also selinux_ip_output() | ||
4898 | * for similar problems. */ | ||
4899 | u32 skb_sid; | ||
4900 | struct sk_security_struct *sksec = sk->sk_security; | ||
4901 | if (selinux_skb_peerlbl_sid(skb, family, &skb_sid)) | ||
4902 | return NF_DROP; | ||
4903 | /* At this point, if the returned skb peerlbl is SECSID_NULL | ||
4904 | * and the packet has been through at least one XFRM | ||
4905 | * transformation then we must be dealing with the "final" | ||
4906 | * form of labeled IPsec packet; since we've already applied | ||
4907 | * all of our access controls on this packet we can safely | ||
4908 | * pass the packet. */ | ||
4909 | if (skb_sid == SECSID_NULL) { | ||
4910 | switch (family) { | ||
4911 | case PF_INET: | ||
4912 | if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) | ||
4913 | return NF_ACCEPT; | ||
4914 | break; | ||
4915 | case PF_INET6: | ||
4916 | if (IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) | ||
4917 | return NF_ACCEPT; | ||
4918 | default: | ||
4919 | return NF_DROP_ERR(-ECONNREFUSED); | ||
4920 | } | ||
4921 | } | ||
4922 | if (selinux_conn_sid(sksec->sid, skb_sid, &peer_sid)) | ||
4923 | return NF_DROP; | ||
4924 | secmark_perm = PACKET__SEND; | ||
4843 | } else { | 4925 | } else { |
4926 | /* Locally generated packet, fetch the security label from the | ||
4927 | * associated socket. */ | ||
4844 | struct sk_security_struct *sksec = sk->sk_security; | 4928 | struct sk_security_struct *sksec = sk->sk_security; |
4845 | peer_sid = sksec->sid; | 4929 | peer_sid = sksec->sid; |
4846 | secmark_perm = PACKET__SEND; | 4930 | secmark_perm = PACKET__SEND; |
@@ -4878,7 +4962,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex, | |||
4878 | return NF_ACCEPT; | 4962 | return NF_ACCEPT; |
4879 | } | 4963 | } |
4880 | 4964 | ||
4881 | static unsigned int selinux_ipv4_postroute(unsigned int hooknum, | 4965 | static unsigned int selinux_ipv4_postroute(const struct nf_hook_ops *ops, |
4882 | struct sk_buff *skb, | 4966 | struct sk_buff *skb, |
4883 | const struct net_device *in, | 4967 | const struct net_device *in, |
4884 | const struct net_device *out, | 4968 | const struct net_device *out, |
@@ -4888,7 +4972,7 @@ static unsigned int selinux_ipv4_postroute(unsigned int hooknum, | |||
4888 | } | 4972 | } |
4889 | 4973 | ||
4890 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 4974 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
4891 | static unsigned int selinux_ipv6_postroute(unsigned int hooknum, | 4975 | static unsigned int selinux_ipv6_postroute(const struct nf_hook_ops *ops, |
4892 | struct sk_buff *skb, | 4976 | struct sk_buff *skb, |
4893 | const struct net_device *in, | 4977 | const struct net_device *in, |
4894 | const struct net_device *out, | 4978 | const struct net_device *out, |
@@ -5504,11 +5588,11 @@ static int selinux_setprocattr(struct task_struct *p, | |||
5504 | /* Check for ptracing, and update the task SID if ok. | 5588 | /* Check for ptracing, and update the task SID if ok. |
5505 | Otherwise, leave SID unchanged and fail. */ | 5589 | Otherwise, leave SID unchanged and fail. */ |
5506 | ptsid = 0; | 5590 | ptsid = 0; |
5507 | task_lock(p); | 5591 | rcu_read_lock(); |
5508 | tracer = ptrace_parent(p); | 5592 | tracer = ptrace_parent(p); |
5509 | if (tracer) | 5593 | if (tracer) |
5510 | ptsid = task_sid(tracer); | 5594 | ptsid = task_sid(tracer); |
5511 | task_unlock(p); | 5595 | rcu_read_unlock(); |
5512 | 5596 | ||
5513 | if (tracer) { | 5597 | if (tracer) { |
5514 | error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, | 5598 | error = avc_has_perm(ptsid, sid, SECCLASS_PROCESS, |
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h index 92d0ab561db8..f53ee3c58d0f 100644 --- a/security/selinux/include/avc.h +++ b/security/selinux/include/avc.h | |||
@@ -130,7 +130,7 @@ static inline int avc_audit(u32 ssid, u32 tsid, | |||
130 | u16 tclass, u32 requested, | 130 | u16 tclass, u32 requested, |
131 | struct av_decision *avd, | 131 | struct av_decision *avd, |
132 | int result, | 132 | int result, |
133 | struct common_audit_data *a, unsigned flags) | 133 | struct common_audit_data *a) |
134 | { | 134 | { |
135 | u32 audited, denied; | 135 | u32 audited, denied; |
136 | audited = avc_audit_required(requested, avd, result, 0, &denied); | 136 | audited = avc_audit_required(requested, avd, result, 0, &denied); |
@@ -138,7 +138,7 @@ static inline int avc_audit(u32 ssid, u32 tsid, | |||
138 | return 0; | 138 | return 0; |
139 | return slow_avc_audit(ssid, tsid, tclass, | 139 | return slow_avc_audit(ssid, tsid, tclass, |
140 | requested, audited, denied, | 140 | requested, audited, denied, |
141 | a, flags); | 141 | a, 0); |
142 | } | 142 | } |
143 | 143 | ||
144 | #define AVC_STRICT 1 /* Ignore permissive mode. */ | 144 | #define AVC_STRICT 1 /* Ignore permissive mode. */ |
@@ -147,17 +147,9 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, | |||
147 | unsigned flags, | 147 | unsigned flags, |
148 | struct av_decision *avd); | 148 | struct av_decision *avd); |
149 | 149 | ||
150 | int avc_has_perm_flags(u32 ssid, u32 tsid, | 150 | int avc_has_perm(u32 ssid, u32 tsid, |
151 | u16 tclass, u32 requested, | 151 | u16 tclass, u32 requested, |
152 | struct common_audit_data *auditdata, | 152 | struct common_audit_data *auditdata); |
153 | unsigned); | ||
154 | |||
155 | static inline int avc_has_perm(u32 ssid, u32 tsid, | ||
156 | u16 tclass, u32 requested, | ||
157 | struct common_audit_data *auditdata) | ||
158 | { | ||
159 | return avc_has_perm_flags(ssid, tsid, tclass, requested, auditdata, 0); | ||
160 | } | ||
161 | 153 | ||
162 | u32 avc_policy_seqno(void); | 154 | u32 avc_policy_seqno(void); |
163 | 155 | ||
diff --git a/security/selinux/include/xfrm.h b/security/selinux/include/xfrm.h index 0dec76c64cf5..48c3cc94c168 100644 --- a/security/selinux/include/xfrm.h +++ b/security/selinux/include/xfrm.h | |||
@@ -39,6 +39,7 @@ int selinux_xfrm_sock_rcv_skb(u32 sk_sid, struct sk_buff *skb, | |||
39 | int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb, | 39 | int selinux_xfrm_postroute_last(u32 sk_sid, struct sk_buff *skb, |
40 | struct common_audit_data *ad, u8 proto); | 40 | struct common_audit_data *ad, u8 proto); |
41 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); | 41 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall); |
42 | int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid); | ||
42 | 43 | ||
43 | static inline void selinux_xfrm_notify_policyload(void) | 44 | static inline void selinux_xfrm_notify_policyload(void) |
44 | { | 45 | { |
@@ -79,11 +80,12 @@ static inline int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, | |||
79 | static inline void selinux_xfrm_notify_policyload(void) | 80 | static inline void selinux_xfrm_notify_policyload(void) |
80 | { | 81 | { |
81 | } | 82 | } |
82 | #endif | ||
83 | 83 | ||
84 | static inline int selinux_skb_xfrm_sid(struct sk_buff *skb, u32 *sid) | 84 | static inline int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid) |
85 | { | 85 | { |
86 | return selinux_xfrm_decode_session(skb, sid, 0); | 86 | *sid = SECSID_NULL; |
87 | return 0; | ||
87 | } | 88 | } |
89 | #endif | ||
88 | 90 | ||
89 | #endif /* _SELINUX_XFRM_H_ */ | 91 | #endif /* _SELINUX_XFRM_H_ */ |
diff --git a/security/selinux/nlmsgtab.c b/security/selinux/nlmsgtab.c index 855e464e92ef..332ac8a80cf5 100644 --- a/security/selinux/nlmsgtab.c +++ b/security/selinux/nlmsgtab.c | |||
@@ -116,6 +116,8 @@ static struct nlmsg_perm nlmsg_audit_perms[] = | |||
116 | { AUDIT_MAKE_EQUIV, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, | 116 | { AUDIT_MAKE_EQUIV, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, |
117 | { AUDIT_TTY_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ }, | 117 | { AUDIT_TTY_GET, NETLINK_AUDIT_SOCKET__NLMSG_READ }, |
118 | { AUDIT_TTY_SET, NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT }, | 118 | { AUDIT_TTY_SET, NETLINK_AUDIT_SOCKET__NLMSG_TTY_AUDIT }, |
119 | { AUDIT_GET_FEATURE, NETLINK_AUDIT_SOCKET__NLMSG_READ }, | ||
120 | { AUDIT_SET_FEATURE, NETLINK_AUDIT_SOCKET__NLMSG_WRITE }, | ||
119 | }; | 121 | }; |
120 | 122 | ||
121 | 123 | ||
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index ee470a0b5c27..d106733ad987 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c | |||
@@ -2334,50 +2334,16 @@ int security_fs_use(struct super_block *sb) | |||
2334 | struct ocontext *c; | 2334 | struct ocontext *c; |
2335 | struct superblock_security_struct *sbsec = sb->s_security; | 2335 | struct superblock_security_struct *sbsec = sb->s_security; |
2336 | const char *fstype = sb->s_type->name; | 2336 | const char *fstype = sb->s_type->name; |
2337 | const char *subtype = (sb->s_subtype && sb->s_subtype[0]) ? sb->s_subtype : NULL; | ||
2338 | struct ocontext *base = NULL; | ||
2339 | 2337 | ||
2340 | read_lock(&policy_rwlock); | 2338 | read_lock(&policy_rwlock); |
2341 | 2339 | ||
2342 | for (c = policydb.ocontexts[OCON_FSUSE]; c; c = c->next) { | 2340 | c = policydb.ocontexts[OCON_FSUSE]; |
2343 | char *sub; | 2341 | while (c) { |
2344 | int baselen; | 2342 | if (strcmp(fstype, c->u.name) == 0) |
2345 | |||
2346 | baselen = strlen(fstype); | ||
2347 | |||
2348 | /* if base does not match, this is not the one */ | ||
2349 | if (strncmp(fstype, c->u.name, baselen)) | ||
2350 | continue; | ||
2351 | |||
2352 | /* if there is no subtype, this is the one! */ | ||
2353 | if (!subtype) | ||
2354 | break; | ||
2355 | |||
2356 | /* skip past the base in this entry */ | ||
2357 | sub = c->u.name + baselen; | ||
2358 | |||
2359 | /* entry is only a base. save it. keep looking for subtype */ | ||
2360 | if (sub[0] == '\0') { | ||
2361 | base = c; | ||
2362 | continue; | ||
2363 | } | ||
2364 | |||
2365 | /* entry is not followed by a subtype, so it is not a match */ | ||
2366 | if (sub[0] != '.') | ||
2367 | continue; | ||
2368 | |||
2369 | /* whew, we found a subtype of this fstype */ | ||
2370 | sub++; /* move past '.' */ | ||
2371 | |||
2372 | /* exact match of fstype AND subtype */ | ||
2373 | if (!strcmp(subtype, sub)) | ||
2374 | break; | 2343 | break; |
2344 | c = c->next; | ||
2375 | } | 2345 | } |
2376 | 2346 | ||
2377 | /* in case we had found an fstype match but no subtype match */ | ||
2378 | if (!c) | ||
2379 | c = base; | ||
2380 | |||
2381 | if (c) { | 2347 | if (c) { |
2382 | sbsec->behavior = c->v.behavior; | 2348 | sbsec->behavior = c->v.behavior; |
2383 | if (!c->sid[0]) { | 2349 | if (!c->sid[0]) { |
diff --git a/security/selinux/xfrm.c b/security/selinux/xfrm.c index a91d205ec0c6..0462cb3ff0a7 100644 --- a/security/selinux/xfrm.c +++ b/security/selinux/xfrm.c | |||
@@ -209,19 +209,26 @@ int selinux_xfrm_state_pol_flow_match(struct xfrm_state *x, | |||
209 | NULL) ? 0 : 1); | 209 | NULL) ? 0 : 1); |
210 | } | 210 | } |
211 | 211 | ||
212 | /* | 212 | static u32 selinux_xfrm_skb_sid_egress(struct sk_buff *skb) |
213 | * LSM hook implementation that checks and/or returns the xfrm sid for the | ||
214 | * incoming packet. | ||
215 | */ | ||
216 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) | ||
217 | { | 213 | { |
218 | u32 sid_session = SECSID_NULL; | 214 | struct dst_entry *dst = skb_dst(skb); |
219 | struct sec_path *sp; | 215 | struct xfrm_state *x; |
220 | 216 | ||
221 | if (skb == NULL) | 217 | if (dst == NULL) |
222 | goto out; | 218 | return SECSID_NULL; |
219 | x = dst->xfrm; | ||
220 | if (x == NULL || !selinux_authorizable_xfrm(x)) | ||
221 | return SECSID_NULL; | ||
222 | |||
223 | return x->security->ctx_sid; | ||
224 | } | ||
225 | |||
226 | static int selinux_xfrm_skb_sid_ingress(struct sk_buff *skb, | ||
227 | u32 *sid, int ckall) | ||
228 | { | ||
229 | u32 sid_session = SECSID_NULL; | ||
230 | struct sec_path *sp = skb->sp; | ||
223 | 231 | ||
224 | sp = skb->sp; | ||
225 | if (sp) { | 232 | if (sp) { |
226 | int i; | 233 | int i; |
227 | 234 | ||
@@ -248,6 +255,30 @@ out: | |||
248 | } | 255 | } |
249 | 256 | ||
250 | /* | 257 | /* |
258 | * LSM hook implementation that checks and/or returns the xfrm sid for the | ||
259 | * incoming packet. | ||
260 | */ | ||
261 | int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall) | ||
262 | { | ||
263 | if (skb == NULL) { | ||
264 | *sid = SECSID_NULL; | ||
265 | return 0; | ||
266 | } | ||
267 | return selinux_xfrm_skb_sid_ingress(skb, sid, ckall); | ||
268 | } | ||
269 | |||
270 | int selinux_xfrm_skb_sid(struct sk_buff *skb, u32 *sid) | ||
271 | { | ||
272 | int rc; | ||
273 | |||
274 | rc = selinux_xfrm_skb_sid_ingress(skb, sid, 0); | ||
275 | if (rc == 0 && *sid == SECSID_NULL) | ||
276 | *sid = selinux_xfrm_skb_sid_egress(skb); | ||
277 | |||
278 | return rc; | ||
279 | } | ||
280 | |||
281 | /* | ||
251 | * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy. | 282 | * LSM hook implementation that allocs and transfers uctx spec to xfrm_policy. |
252 | */ | 283 | */ |
253 | int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, | 284 | int selinux_xfrm_policy_alloc(struct xfrm_sec_ctx **ctxp, |
@@ -327,19 +358,22 @@ int selinux_xfrm_state_alloc_acquire(struct xfrm_state *x, | |||
327 | return rc; | 358 | return rc; |
328 | 359 | ||
329 | ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC); | 360 | ctx = kmalloc(sizeof(*ctx) + str_len, GFP_ATOMIC); |
330 | if (!ctx) | 361 | if (!ctx) { |
331 | return -ENOMEM; | 362 | rc = -ENOMEM; |
363 | goto out; | ||
364 | } | ||
332 | 365 | ||
333 | ctx->ctx_doi = XFRM_SC_DOI_LSM; | 366 | ctx->ctx_doi = XFRM_SC_DOI_LSM; |
334 | ctx->ctx_alg = XFRM_SC_ALG_SELINUX; | 367 | ctx->ctx_alg = XFRM_SC_ALG_SELINUX; |
335 | ctx->ctx_sid = secid; | 368 | ctx->ctx_sid = secid; |
336 | ctx->ctx_len = str_len; | 369 | ctx->ctx_len = str_len; |
337 | memcpy(ctx->ctx_str, ctx_str, str_len); | 370 | memcpy(ctx->ctx_str, ctx_str, str_len); |
338 | kfree(ctx_str); | ||
339 | 371 | ||
340 | x->security = ctx; | 372 | x->security = ctx; |
341 | atomic_inc(&selinux_xfrm_refcount); | 373 | atomic_inc(&selinux_xfrm_refcount); |
342 | return 0; | 374 | out: |
375 | kfree(ctx_str); | ||
376 | return rc; | ||
343 | } | 377 | } |
344 | 378 | ||
345 | /* | 379 | /* |