diff options
Diffstat (limited to 'security/keys/user_defined.c')
-rw-r--r-- | security/keys/user_defined.c | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 69ff52c08e97..c7660a25a3e4 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <asm/uaccess.h> | 18 | #include <asm/uaccess.h> |
19 | #include "internal.h" | 19 | #include "internal.h" |
20 | 20 | ||
21 | static int logon_vet_description(const char *desc); | ||
22 | |||
21 | /* | 23 | /* |
22 | * user defined keys take an arbitrary string as the description and an | 24 | * user defined keys take an arbitrary string as the description and an |
23 | * arbitrary blob of data as the payload | 25 | * arbitrary blob of data as the payload |
@@ -36,6 +38,24 @@ struct key_type key_type_user = { | |||
36 | EXPORT_SYMBOL_GPL(key_type_user); | 38 | EXPORT_SYMBOL_GPL(key_type_user); |
37 | 39 | ||
38 | /* | 40 | /* |
41 | * This key type is essentially the same as key_type_user, but it does | ||
42 | * not define a .read op. This is suitable for storing username and | ||
43 | * password pairs in the keyring that you do not want to be readable | ||
44 | * from userspace. | ||
45 | */ | ||
46 | struct key_type key_type_logon = { | ||
47 | .name = "logon", | ||
48 | .instantiate = user_instantiate, | ||
49 | .update = user_update, | ||
50 | .match = user_match, | ||
51 | .revoke = user_revoke, | ||
52 | .destroy = user_destroy, | ||
53 | .describe = user_describe, | ||
54 | .vet_description = logon_vet_description, | ||
55 | }; | ||
56 | EXPORT_SYMBOL_GPL(key_type_logon); | ||
57 | |||
58 | /* | ||
39 | * instantiate a user defined key | 59 | * instantiate a user defined key |
40 | */ | 60 | */ |
41 | int user_instantiate(struct key *key, const void *data, size_t datalen) | 61 | int user_instantiate(struct key *key, const void *data, size_t datalen) |
@@ -59,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen) | |||
59 | /* attach the data */ | 79 | /* attach the data */ |
60 | upayload->datalen = datalen; | 80 | upayload->datalen = datalen; |
61 | memcpy(upayload->data, data, datalen); | 81 | memcpy(upayload->data, data, datalen); |
62 | rcu_assign_pointer(key->payload.data, upayload); | 82 | rcu_assign_keypointer(key, upayload); |
63 | ret = 0; | 83 | ret = 0; |
64 | 84 | ||
65 | error: | 85 | error: |
@@ -98,7 +118,7 @@ int user_update(struct key *key, const void *data, size_t datalen) | |||
98 | if (ret == 0) { | 118 | if (ret == 0) { |
99 | /* attach the new data, displacing the old */ | 119 | /* attach the new data, displacing the old */ |
100 | zap = key->payload.data; | 120 | zap = key->payload.data; |
101 | rcu_assign_pointer(key->payload.data, upayload); | 121 | rcu_assign_keypointer(key, upayload); |
102 | key->expiry = 0; | 122 | key->expiry = 0; |
103 | } | 123 | } |
104 | 124 | ||
@@ -133,7 +153,7 @@ void user_revoke(struct key *key) | |||
133 | key_payload_reserve(key, 0); | 153 | key_payload_reserve(key, 0); |
134 | 154 | ||
135 | if (upayload) { | 155 | if (upayload) { |
136 | rcu_assign_pointer(key->payload.data, NULL); | 156 | rcu_assign_keypointer(key, NULL); |
137 | kfree_rcu(upayload, rcu); | 157 | kfree_rcu(upayload, rcu); |
138 | } | 158 | } |
139 | } | 159 | } |
@@ -189,3 +209,20 @@ long user_read(const struct key *key, char __user *buffer, size_t buflen) | |||
189 | } | 209 | } |
190 | 210 | ||
191 | EXPORT_SYMBOL_GPL(user_read); | 211 | EXPORT_SYMBOL_GPL(user_read); |
212 | |||
213 | /* Vet the description for a "logon" key */ | ||
214 | static int logon_vet_description(const char *desc) | ||
215 | { | ||
216 | char *p; | ||
217 | |||
218 | /* require a "qualified" description string */ | ||
219 | p = strchr(desc, ':'); | ||
220 | if (!p) | ||
221 | return -EINVAL; | ||
222 | |||
223 | /* also reject description with ':' as first char */ | ||
224 | if (p == desc) | ||
225 | return -EINVAL; | ||
226 | |||
227 | return 0; | ||
228 | } | ||