diff options
-rw-r--r-- | include/keys/user-type.h | 47 | ||||
-rw-r--r-- | security/keys/user_defined.c | 49 |
2 files changed, 71 insertions, 25 deletions
diff --git a/include/keys/user-type.h b/include/keys/user-type.h new file mode 100644 index 000000000000..26f6ec38577a --- /dev/null +++ b/include/keys/user-type.h | |||
@@ -0,0 +1,47 @@ | |||
1 | /* user-type.h: User-defined key type | ||
2 | * | ||
3 | * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. | ||
4 | * Written by David Howells (dhowells@redhat.com) | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _KEYS_USER_TYPE_H | ||
13 | #define _KEYS_USER_TYPE_H | ||
14 | |||
15 | #include <linux/key.h> | ||
16 | #include <linux/rcupdate.h> | ||
17 | |||
18 | /*****************************************************************************/ | ||
19 | /* | ||
20 | * the payload for a key of type "user" | ||
21 | * - once filled in and attached to a key: | ||
22 | * - the payload struct is invariant may not be changed, only replaced | ||
23 | * - the payload must be read with RCU procedures or with the key semaphore | ||
24 | * held | ||
25 | * - the payload may only be replaced with the key semaphore write-locked | ||
26 | * - the key's data length is the size of the actual data, not including the | ||
27 | * payload wrapper | ||
28 | */ | ||
29 | struct user_key_payload { | ||
30 | struct rcu_head rcu; /* RCU destructor */ | ||
31 | unsigned short datalen; /* length of this data */ | ||
32 | char data[0]; /* actual data */ | ||
33 | }; | ||
34 | |||
35 | extern struct key_type key_type_user; | ||
36 | |||
37 | extern int user_instantiate(struct key *key, const void *data, size_t datalen); | ||
38 | extern int user_duplicate(struct key *key, const struct key *source); | ||
39 | extern int user_update(struct key *key, const void *data, size_t datalen); | ||
40 | extern int user_match(const struct key *key, const void *criterion); | ||
41 | extern void user_destroy(struct key *key); | ||
42 | extern void user_describe(const struct key *user, struct seq_file *m); | ||
43 | extern long user_read(const struct key *key, | ||
44 | char __user *buffer, size_t buflen); | ||
45 | |||
46 | |||
47 | #endif /* _KEYS_USER_TYPE_H */ | ||
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index e446acba73d3..cbda3b2780a1 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -15,18 +15,10 @@ | |||
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/seq_file.h> | 16 | #include <linux/seq_file.h> |
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <keys/user-type.h> | ||
18 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
19 | #include "internal.h" | 20 | #include "internal.h" |
20 | 21 | ||
21 | static int user_instantiate(struct key *key, const void *data, size_t datalen); | ||
22 | static int user_duplicate(struct key *key, const struct key *source); | ||
23 | static int user_update(struct key *key, const void *data, size_t datalen); | ||
24 | static int user_match(const struct key *key, const void *criterion); | ||
25 | static void user_destroy(struct key *key); | ||
26 | static void user_describe(const struct key *user, struct seq_file *m); | ||
27 | static long user_read(const struct key *key, | ||
28 | char __user *buffer, size_t buflen); | ||
29 | |||
30 | /* | 22 | /* |
31 | * user defined keys take an arbitrary string as the description and an | 23 | * user defined keys take an arbitrary string as the description and an |
32 | * arbitrary blob of data as the payload | 24 | * arbitrary blob of data as the payload |
@@ -42,19 +34,13 @@ struct key_type key_type_user = { | |||
42 | .read = user_read, | 34 | .read = user_read, |
43 | }; | 35 | }; |
44 | 36 | ||
45 | struct user_key_payload { | ||
46 | struct rcu_head rcu; /* RCU destructor */ | ||
47 | unsigned short datalen; /* length of this data */ | ||
48 | char data[0]; /* actual data */ | ||
49 | }; | ||
50 | |||
51 | EXPORT_SYMBOL_GPL(key_type_user); | 37 | EXPORT_SYMBOL_GPL(key_type_user); |
52 | 38 | ||
53 | /*****************************************************************************/ | 39 | /*****************************************************************************/ |
54 | /* | 40 | /* |
55 | * instantiate a user defined key | 41 | * instantiate a user defined key |
56 | */ | 42 | */ |
57 | static int user_instantiate(struct key *key, const void *data, size_t datalen) | 43 | int user_instantiate(struct key *key, const void *data, size_t datalen) |
58 | { | 44 | { |
59 | struct user_key_payload *upayload; | 45 | struct user_key_payload *upayload; |
60 | int ret; | 46 | int ret; |
@@ -78,18 +64,20 @@ static int user_instantiate(struct key *key, const void *data, size_t datalen) | |||
78 | rcu_assign_pointer(key->payload.data, upayload); | 64 | rcu_assign_pointer(key->payload.data, upayload); |
79 | ret = 0; | 65 | ret = 0; |
80 | 66 | ||
81 | error: | 67 | error: |
82 | return ret; | 68 | return ret; |
83 | 69 | ||
84 | } /* end user_instantiate() */ | 70 | } /* end user_instantiate() */ |
85 | 71 | ||
72 | EXPORT_SYMBOL_GPL(user_instantiate); | ||
73 | |||
86 | /*****************************************************************************/ | 74 | /*****************************************************************************/ |
87 | /* | 75 | /* |
88 | * duplicate a user defined key | 76 | * duplicate a user defined key |
89 | * - both keys' semaphores are locked against further modification | 77 | * - both keys' semaphores are locked against further modification |
90 | * - the new key cannot yet be accessed | 78 | * - the new key cannot yet be accessed |
91 | */ | 79 | */ |
92 | static int user_duplicate(struct key *key, const struct key *source) | 80 | int user_duplicate(struct key *key, const struct key *source) |
93 | { | 81 | { |
94 | struct user_key_payload *upayload, *spayload; | 82 | struct user_key_payload *upayload, *spayload; |
95 | int ret; | 83 | int ret; |
@@ -112,6 +100,8 @@ static int user_duplicate(struct key *key, const struct key *source) | |||
112 | 100 | ||
113 | } /* end user_duplicate() */ | 101 | } /* end user_duplicate() */ |
114 | 102 | ||
103 | EXPORT_SYMBOL_GPL(user_duplicate); | ||
104 | |||
115 | /*****************************************************************************/ | 105 | /*****************************************************************************/ |
116 | /* | 106 | /* |
117 | * dispose of the old data from an updated user defined key | 107 | * dispose of the old data from an updated user defined key |
@@ -131,7 +121,7 @@ static void user_update_rcu_disposal(struct rcu_head *rcu) | |||
131 | * update a user defined key | 121 | * update a user defined key |
132 | * - the key's semaphore is write-locked | 122 | * - the key's semaphore is write-locked |
133 | */ | 123 | */ |
134 | static int user_update(struct key *key, const void *data, size_t datalen) | 124 | int user_update(struct key *key, const void *data, size_t datalen) |
135 | { | 125 | { |
136 | struct user_key_payload *upayload, *zap; | 126 | struct user_key_payload *upayload, *zap; |
137 | int ret; | 127 | int ret; |
@@ -163,26 +153,30 @@ static int user_update(struct key *key, const void *data, size_t datalen) | |||
163 | 153 | ||
164 | call_rcu(&zap->rcu, user_update_rcu_disposal); | 154 | call_rcu(&zap->rcu, user_update_rcu_disposal); |
165 | 155 | ||
166 | error: | 156 | error: |
167 | return ret; | 157 | return ret; |
168 | 158 | ||
169 | } /* end user_update() */ | 159 | } /* end user_update() */ |
170 | 160 | ||
161 | EXPORT_SYMBOL_GPL(user_update); | ||
162 | |||
171 | /*****************************************************************************/ | 163 | /*****************************************************************************/ |
172 | /* | 164 | /* |
173 | * match users on their name | 165 | * match users on their name |
174 | */ | 166 | */ |
175 | static int user_match(const struct key *key, const void *description) | 167 | int user_match(const struct key *key, const void *description) |
176 | { | 168 | { |
177 | return strcmp(key->description, description) == 0; | 169 | return strcmp(key->description, description) == 0; |
178 | 170 | ||
179 | } /* end user_match() */ | 171 | } /* end user_match() */ |
180 | 172 | ||
173 | EXPORT_SYMBOL_GPL(user_match); | ||
174 | |||
181 | /*****************************************************************************/ | 175 | /*****************************************************************************/ |
182 | /* | 176 | /* |
183 | * dispose of the data dangling from the corpse of a user | 177 | * dispose of the data dangling from the corpse of a user |
184 | */ | 178 | */ |
185 | static void user_destroy(struct key *key) | 179 | void user_destroy(struct key *key) |
186 | { | 180 | { |
187 | struct user_key_payload *upayload = key->payload.data; | 181 | struct user_key_payload *upayload = key->payload.data; |
188 | 182 | ||
@@ -190,11 +184,13 @@ static void user_destroy(struct key *key) | |||
190 | 184 | ||
191 | } /* end user_destroy() */ | 185 | } /* end user_destroy() */ |
192 | 186 | ||
187 | EXPORT_SYMBOL_GPL(user_destroy); | ||
188 | |||
193 | /*****************************************************************************/ | 189 | /*****************************************************************************/ |
194 | /* | 190 | /* |
195 | * describe the user key | 191 | * describe the user key |
196 | */ | 192 | */ |
197 | static void user_describe(const struct key *key, struct seq_file *m) | 193 | void user_describe(const struct key *key, struct seq_file *m) |
198 | { | 194 | { |
199 | seq_puts(m, key->description); | 195 | seq_puts(m, key->description); |
200 | 196 | ||
@@ -202,13 +198,14 @@ static void user_describe(const struct key *key, struct seq_file *m) | |||
202 | 198 | ||
203 | } /* end user_describe() */ | 199 | } /* end user_describe() */ |
204 | 200 | ||
201 | EXPORT_SYMBOL_GPL(user_describe); | ||
202 | |||
205 | /*****************************************************************************/ | 203 | /*****************************************************************************/ |
206 | /* | 204 | /* |
207 | * read the key data | 205 | * read the key data |
208 | * - the key's semaphore is read-locked | 206 | * - the key's semaphore is read-locked |
209 | */ | 207 | */ |
210 | static long user_read(const struct key *key, | 208 | long user_read(const struct key *key, char __user *buffer, size_t buflen) |
211 | char __user *buffer, size_t buflen) | ||
212 | { | 209 | { |
213 | struct user_key_payload *upayload; | 210 | struct user_key_payload *upayload; |
214 | long ret; | 211 | long ret; |
@@ -228,3 +225,5 @@ static long user_read(const struct key *key, | |||
228 | return ret; | 225 | return ret; |
229 | 226 | ||
230 | } /* end user_read() */ | 227 | } /* end user_read() */ |
228 | |||
229 | EXPORT_SYMBOL_GPL(user_read); | ||