diff options
-rw-r--r-- | Documentation/keys-request-key.txt | 25 | ||||
-rw-r--r-- | Documentation/keys.txt | 93 | ||||
-rw-r--r-- | Documentation/networking/rxrpc.txt | 7 | ||||
-rw-r--r-- | fs/afs/cell.c | 17 | ||||
-rw-r--r-- | include/keys/rxrpc-type.h | 2 | ||||
-rw-r--r-- | include/linux/key-type.h | 112 | ||||
-rw-r--r-- | include/linux/key.h | 99 | ||||
-rw-r--r-- | net/rxrpc/af_rxrpc.c | 1 | ||||
-rw-r--r-- | net/rxrpc/ar-key.c | 32 | ||||
-rw-r--r-- | security/keys/internal.h | 35 | ||||
-rw-r--r-- | security/keys/key.c | 34 | ||||
-rw-r--r-- | security/keys/process_keys.c | 16 | ||||
-rw-r--r-- | security/keys/request_key.c | 556 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 11 |
14 files changed, 605 insertions, 435 deletions
diff --git a/Documentation/keys-request-key.txt b/Documentation/keys-request-key.txt index c1f64fdf84c..266955d23ee 100644 --- a/Documentation/keys-request-key.txt +++ b/Documentation/keys-request-key.txt | |||
@@ -20,6 +20,19 @@ or: | |||
20 | const char *callout_string, | 20 | const char *callout_string, |
21 | void *aux); | 21 | void *aux); |
22 | 22 | ||
23 | or: | ||
24 | |||
25 | struct key *request_key_async(const struct key_type *type, | ||
26 | const char *description, | ||
27 | const char *callout_string); | ||
28 | |||
29 | or: | ||
30 | |||
31 | struct key *request_key_async_with_auxdata(const struct key_type *type, | ||
32 | const char *description, | ||
33 | const char *callout_string, | ||
34 | void *aux); | ||
35 | |||
23 | Or by userspace invoking the request_key system call: | 36 | Or by userspace invoking the request_key system call: |
24 | 37 | ||
25 | key_serial_t request_key(const char *type, | 38 | key_serial_t request_key(const char *type, |
@@ -32,10 +45,14 @@ does not need to link the key to a keyring to prevent it from being immediately | |||
32 | destroyed. The kernel interface returns a pointer directly to the key, and | 45 | destroyed. The kernel interface returns a pointer directly to the key, and |
33 | it's up to the caller to destroy the key. | 46 | it's up to the caller to destroy the key. |
34 | 47 | ||
35 | The request_key_with_auxdata() call is like the in-kernel request_key() call, | 48 | The request_key*_with_auxdata() calls are like the in-kernel request_key*() |
36 | except that it permits auxiliary data to be passed to the upcaller (the default | 49 | calls, except that they permit auxiliary data to be passed to the upcaller (the |
37 | is NULL). This is only useful for those key types that define their own upcall | 50 | default is NULL). This is only useful for those key types that define their |
38 | mechanism rather than using /sbin/request-key. | 51 | own upcall mechanism rather than using /sbin/request-key. |
52 | |||
53 | The two async in-kernel calls may return keys that are still in the process of | ||
54 | being constructed. The two non-async ones will wait for construction to | ||
55 | complete first. | ||
39 | 56 | ||
40 | The userspace interface links the key to a keyring associated with the process | 57 | The userspace interface links the key to a keyring associated with the process |
41 | to prevent the key from going away, and returns the serial number of the key to | 58 | to prevent the key from going away, and returns the serial number of the key to |
diff --git a/Documentation/keys.txt b/Documentation/keys.txt index 947d57d5345..51652d39e61 100644 --- a/Documentation/keys.txt +++ b/Documentation/keys.txt | |||
@@ -4,7 +4,7 @@ | |||
4 | 4 | ||
5 | This service allows cryptographic keys, authentication tokens, cross-domain | 5 | This service allows cryptographic keys, authentication tokens, cross-domain |
6 | user mappings, and similar to be cached in the kernel for the use of | 6 | user mappings, and similar to be cached in the kernel for the use of |
7 | filesystems other kernel services. | 7 | filesystems and other kernel services. |
8 | 8 | ||
9 | Keyrings are permitted; these are a special type of key that can hold links to | 9 | Keyrings are permitted; these are a special type of key that can hold links to |
10 | other keys. Processes each have three standard keyring subscriptions that a | 10 | other keys. Processes each have three standard keyring subscriptions that a |
@@ -726,6 +726,15 @@ call, and the key released upon close. How to deal with conflicting keys due to | |||
726 | two different users opening the same file is left to the filesystem author to | 726 | two different users opening the same file is left to the filesystem author to |
727 | solve. | 727 | solve. |
728 | 728 | ||
729 | To access the key manager, the following header must be #included: | ||
730 | |||
731 | <linux/key.h> | ||
732 | |||
733 | Specific key types should have a header file under include/keys/ that should be | ||
734 | used to access that type. For keys of type "user", for example, that would be: | ||
735 | |||
736 | <keys/user-type.h> | ||
737 | |||
729 | Note that there are two different types of pointers to keys that may be | 738 | Note that there are two different types of pointers to keys that may be |
730 | encountered: | 739 | encountered: |
731 | 740 | ||
@@ -791,6 +800,36 @@ payload contents" for more information. | |||
791 | passed to the key_type->request_key() op if it exists. | 800 | passed to the key_type->request_key() op if it exists. |
792 | 801 | ||
793 | 802 | ||
803 | (*) A key can be requested asynchronously by calling one of: | ||
804 | |||
805 | struct key *request_key_async(const struct key_type *type, | ||
806 | const char *description, | ||
807 | const char *callout_string); | ||
808 | |||
809 | or: | ||
810 | |||
811 | struct key *request_key_async_with_auxdata(const struct key_type *type, | ||
812 | const char *description, | ||
813 | const char *callout_string, | ||
814 | void *aux); | ||
815 | |||
816 | which are asynchronous equivalents of request_key() and | ||
817 | request_key_with_auxdata() respectively. | ||
818 | |||
819 | These two functions return with the key potentially still under | ||
820 | construction. To wait for contruction completion, the following should be | ||
821 | called: | ||
822 | |||
823 | int wait_for_key_construction(struct key *key, bool intr); | ||
824 | |||
825 | The function will wait for the key to finish being constructed and then | ||
826 | invokes key_validate() to return an appropriate value to indicate the state | ||
827 | of the key (0 indicates the key is usable). | ||
828 | |||
829 | If intr is true, then the wait can be interrupted by a signal, in which | ||
830 | case error ERESTARTSYS will be returned. | ||
831 | |||
832 | |||
794 | (*) When it is no longer required, the key should be released using: | 833 | (*) When it is no longer required, the key should be released using: |
795 | 834 | ||
796 | void key_put(struct key *key); | 835 | void key_put(struct key *key); |
@@ -924,7 +963,11 @@ DEFINING A KEY TYPE | |||
924 | 963 | ||
925 | A kernel service may want to define its own key type. For instance, an AFS | 964 | A kernel service may want to define its own key type. For instance, an AFS |
926 | filesystem might want to define a Kerberos 5 ticket key type. To do this, it | 965 | filesystem might want to define a Kerberos 5 ticket key type. To do this, it |
927 | author fills in a struct key_type and registers it with the system. | 966 | author fills in a key_type struct and registers it with the system. |
967 | |||
968 | Source files that implement key types should include the following header file: | ||
969 | |||
970 | <linux/key-type.h> | ||
928 | 971 | ||
929 | The structure has a number of fields, some of which are mandatory: | 972 | The structure has a number of fields, some of which are mandatory: |
930 | 973 | ||
@@ -1053,22 +1096,44 @@ The structure has a number of fields, some of which are mandatory: | |||
1053 | as might happen when the userspace buffer is accessed. | 1096 | as might happen when the userspace buffer is accessed. |
1054 | 1097 | ||
1055 | 1098 | ||
1056 | (*) int (*request_key)(struct key *key, struct key *authkey, const char *op, | 1099 | (*) int (*request_key)(struct key_construction *cons, const char *op, |
1057 | void *aux); | 1100 | void *aux); |
1058 | 1101 | ||
1059 | This method is optional. If provided, request_key() and | 1102 | This method is optional. If provided, request_key() and friends will |
1060 | request_key_with_auxdata() will invoke this function rather than | 1103 | invoke this function rather than upcalling to /sbin/request-key to operate |
1061 | upcalling to /sbin/request-key to operate upon a key of this type. | 1104 | upon a key of this type. |
1105 | |||
1106 | The aux parameter is as passed to request_key_async_with_auxdata() and | ||
1107 | similar or is NULL otherwise. Also passed are the construction record for | ||
1108 | the key to be operated upon and the operation type (currently only | ||
1109 | "create"). | ||
1110 | |||
1111 | This method is permitted to return before the upcall is complete, but the | ||
1112 | following function must be called under all circumstances to complete the | ||
1113 | instantiation process, whether or not it succeeds, whether or not there's | ||
1114 | an error: | ||
1115 | |||
1116 | void complete_request_key(struct key_construction *cons, int error); | ||
1117 | |||
1118 | The error parameter should be 0 on success, -ve on error. The | ||
1119 | construction record is destroyed by this action and the authorisation key | ||
1120 | will be revoked. If an error is indicated, the key under construction | ||
1121 | will be negatively instantiated if it wasn't already instantiated. | ||
1122 | |||
1123 | If this method returns an error, that error will be returned to the | ||
1124 | caller of request_key*(). complete_request_key() must be called prior to | ||
1125 | returning. | ||
1126 | |||
1127 | The key under construction and the authorisation key can be found in the | ||
1128 | key_construction struct pointed to by cons: | ||
1129 | |||
1130 | (*) struct key *key; | ||
1131 | |||
1132 | The key under construction. | ||
1062 | 1133 | ||
1063 | The aux parameter is as passed to request_key_with_auxdata() or is NULL | 1134 | (*) struct key *authkey; |
1064 | otherwise. Also passed are the key to be operated upon, the | ||
1065 | authorisation key for this operation and the operation type (currently | ||
1066 | only "create"). | ||
1067 | 1135 | ||
1068 | This function should return only when the upcall is complete. Upon return | 1136 | The authorisation key. |
1069 | the authorisation key will be revoked, and the target key will be | ||
1070 | negatively instantiated if it is still uninstantiated. The error will be | ||
1071 | returned to the caller of request_key*(). | ||
1072 | 1137 | ||
1073 | 1138 | ||
1074 | ============================ | 1139 | ============================ |
diff --git a/Documentation/networking/rxrpc.txt b/Documentation/networking/rxrpc.txt index cae231b1c13..c36b64b0020 100644 --- a/Documentation/networking/rxrpc.txt +++ b/Documentation/networking/rxrpc.txt | |||
@@ -857,3 +857,10 @@ The kernel interface functions are as follows: | |||
857 | 857 | ||
858 | This is used to extract the error number from a message indicating either | 858 | This is used to extract the error number from a message indicating either |
859 | a local error occurred or a network error occurred. | 859 | a local error occurred or a network error occurred. |
860 | |||
861 | (*) Allocate a null key for doing anonymous security. | ||
862 | |||
863 | struct key *rxrpc_get_null_key(const char *keyname); | ||
864 | |||
865 | This is used to allocate a null RxRPC key that can be used to indicate | ||
866 | anonymous security for a particular domain. | ||
diff --git a/fs/afs/cell.c b/fs/afs/cell.c index ccfa89f3525..970d38f3056 100644 --- a/fs/afs/cell.c +++ b/fs/afs/cell.c | |||
@@ -33,6 +33,7 @@ static struct afs_cell *afs_cell_root; | |||
33 | static struct afs_cell *afs_cell_alloc(const char *name, char *vllist) | 33 | static struct afs_cell *afs_cell_alloc(const char *name, char *vllist) |
34 | { | 34 | { |
35 | struct afs_cell *cell; | 35 | struct afs_cell *cell; |
36 | struct key *key; | ||
36 | size_t namelen; | 37 | size_t namelen; |
37 | char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next; | 38 | char keyname[4 + AFS_MAXCELLNAME + 1], *cp, *dp, *next; |
38 | int ret; | 39 | int ret; |
@@ -89,20 +90,14 @@ static struct afs_cell *afs_cell_alloc(const char *name, char *vllist) | |||
89 | do { | 90 | do { |
90 | *dp++ = toupper(*cp); | 91 | *dp++ = toupper(*cp); |
91 | } while (*cp++); | 92 | } while (*cp++); |
92 | cell->anonymous_key = key_alloc(&key_type_rxrpc, keyname, 0, 0, current, | ||
93 | KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA); | ||
94 | if (IS_ERR(cell->anonymous_key)) { | ||
95 | _debug("no key"); | ||
96 | ret = PTR_ERR(cell->anonymous_key); | ||
97 | goto error; | ||
98 | } | ||
99 | 93 | ||
100 | ret = key_instantiate_and_link(cell->anonymous_key, NULL, 0, | 94 | key = rxrpc_get_null_key(keyname); |
101 | NULL, NULL); | 95 | if (IS_ERR(key)) { |
102 | if (ret < 0) { | 96 | _debug("no key"); |
103 | _debug("instantiate failed"); | 97 | ret = PTR_ERR(key); |
104 | goto error; | 98 | goto error; |
105 | } | 99 | } |
100 | cell->anonymous_key = key; | ||
106 | 101 | ||
107 | _debug("anon key %p{%x}", | 102 | _debug("anon key %p{%x}", |
108 | cell->anonymous_key, key_serial(cell->anonymous_key)); | 103 | cell->anonymous_key, key_serial(cell->anonymous_key)); |
diff --git a/include/keys/rxrpc-type.h b/include/keys/rxrpc-type.h index e2ee73aef0e..4ea429b1875 100644 --- a/include/keys/rxrpc-type.h +++ b/include/keys/rxrpc-type.h | |||
@@ -19,4 +19,6 @@ | |||
19 | */ | 19 | */ |
20 | extern struct key_type key_type_rxrpc; | 20 | extern struct key_type key_type_rxrpc; |
21 | 21 | ||
22 | extern struct key *rxrpc_get_null_key(const char *); | ||
23 | |||
22 | #endif /* _KEYS_USER_TYPE_H */ | 24 | #endif /* _KEYS_USER_TYPE_H */ |
diff --git a/include/linux/key-type.h b/include/linux/key-type.h new file mode 100644 index 00000000000..65833d4d599 --- /dev/null +++ b/include/linux/key-type.h | |||
@@ -0,0 +1,112 @@ | |||
1 | /* Definitions for key type implementations | ||
2 | * | ||
3 | * Copyright (C) 2007 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 Licence | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the Licence, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #ifndef _LINUX_KEY_TYPE_H | ||
13 | #define _LINUX_KEY_TYPE_H | ||
14 | |||
15 | #include <linux/key.h> | ||
16 | |||
17 | #ifdef CONFIG_KEYS | ||
18 | |||
19 | /* | ||
20 | * key under-construction record | ||
21 | * - passed to the request_key actor if supplied | ||
22 | */ | ||
23 | struct key_construction { | ||
24 | struct key *key; /* key being constructed */ | ||
25 | struct key *authkey;/* authorisation for key being constructed */ | ||
26 | }; | ||
27 | |||
28 | typedef int (*request_key_actor_t)(struct key_construction *key, | ||
29 | const char *op, void *aux); | ||
30 | |||
31 | /* | ||
32 | * kernel managed key type definition | ||
33 | */ | ||
34 | struct key_type { | ||
35 | /* name of the type */ | ||
36 | const char *name; | ||
37 | |||
38 | /* default payload length for quota precalculation (optional) | ||
39 | * - this can be used instead of calling key_payload_reserve(), that | ||
40 | * function only needs to be called if the real datalen is different | ||
41 | */ | ||
42 | size_t def_datalen; | ||
43 | |||
44 | /* instantiate a key of this type | ||
45 | * - this method should call key_payload_reserve() to determine if the | ||
46 | * user's quota will hold the payload | ||
47 | */ | ||
48 | int (*instantiate)(struct key *key, const void *data, size_t datalen); | ||
49 | |||
50 | /* update a key of this type (optional) | ||
51 | * - this method should call key_payload_reserve() to recalculate the | ||
52 | * quota consumption | ||
53 | * - the key must be locked against read when modifying | ||
54 | */ | ||
55 | int (*update)(struct key *key, const void *data, size_t datalen); | ||
56 | |||
57 | /* match a key against a description */ | ||
58 | int (*match)(const struct key *key, const void *desc); | ||
59 | |||
60 | /* clear some of the data from a key on revokation (optional) | ||
61 | * - the key's semaphore will be write-locked by the caller | ||
62 | */ | ||
63 | void (*revoke)(struct key *key); | ||
64 | |||
65 | /* clear the data from a key (optional) */ | ||
66 | void (*destroy)(struct key *key); | ||
67 | |||
68 | /* describe a key */ | ||
69 | void (*describe)(const struct key *key, struct seq_file *p); | ||
70 | |||
71 | /* read a key's data (optional) | ||
72 | * - permission checks will be done by the caller | ||
73 | * - the key's semaphore will be readlocked by the caller | ||
74 | * - should return the amount of data that could be read, no matter how | ||
75 | * much is copied into the buffer | ||
76 | * - shouldn't do the copy if the buffer is NULL | ||
77 | */ | ||
78 | long (*read)(const struct key *key, char __user *buffer, size_t buflen); | ||
79 | |||
80 | /* handle request_key() for this type instead of invoking | ||
81 | * /sbin/request-key (optional) | ||
82 | * - key is the key to instantiate | ||
83 | * - authkey is the authority to assume when instantiating this key | ||
84 | * - op is the operation to be done, usually "create" | ||
85 | * - the call must not return until the instantiation process has run | ||
86 | * its course | ||
87 | */ | ||
88 | request_key_actor_t request_key; | ||
89 | |||
90 | /* internal fields */ | ||
91 | struct list_head link; /* link in types list */ | ||
92 | }; | ||
93 | |||
94 | extern struct key_type key_type_keyring; | ||
95 | |||
96 | extern int register_key_type(struct key_type *ktype); | ||
97 | extern void unregister_key_type(struct key_type *ktype); | ||
98 | |||
99 | extern int key_payload_reserve(struct key *key, size_t datalen); | ||
100 | extern int key_instantiate_and_link(struct key *key, | ||
101 | const void *data, | ||
102 | size_t datalen, | ||
103 | struct key *keyring, | ||
104 | struct key *instkey); | ||
105 | extern int key_negate_and_link(struct key *key, | ||
106 | unsigned timeout, | ||
107 | struct key *keyring, | ||
108 | struct key *instkey); | ||
109 | extern void complete_request_key(struct key_construction *cons, int error); | ||
110 | |||
111 | #endif /* CONFIG_KEYS */ | ||
112 | #endif /* _LINUX_KEY_TYPE_H */ | ||
diff --git a/include/linux/key.h b/include/linux/key.h index a9220e75782..fcdbd5ed227 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* key.h: authentication token and access key management | 1 | /* Authentication token and access key management |
2 | * | 2 | * |
3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004, 2007 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -175,78 +175,6 @@ struct key { | |||
175 | } payload; | 175 | } payload; |
176 | }; | 176 | }; |
177 | 177 | ||
178 | /*****************************************************************************/ | ||
179 | /* | ||
180 | * kernel managed key type definition | ||
181 | */ | ||
182 | typedef int (*request_key_actor_t)(struct key *key, struct key *authkey, | ||
183 | const char *op, void *aux); | ||
184 | |||
185 | struct key_type { | ||
186 | /* name of the type */ | ||
187 | const char *name; | ||
188 | |||
189 | /* default payload length for quota precalculation (optional) | ||
190 | * - this can be used instead of calling key_payload_reserve(), that | ||
191 | * function only needs to be called if the real datalen is different | ||
192 | */ | ||
193 | size_t def_datalen; | ||
194 | |||
195 | /* instantiate a key of this type | ||
196 | * - this method should call key_payload_reserve() to determine if the | ||
197 | * user's quota will hold the payload | ||
198 | */ | ||
199 | int (*instantiate)(struct key *key, const void *data, size_t datalen); | ||
200 | |||
201 | /* update a key of this type (optional) | ||
202 | * - this method should call key_payload_reserve() to recalculate the | ||
203 | * quota consumption | ||
204 | * - the key must be locked against read when modifying | ||
205 | */ | ||
206 | int (*update)(struct key *key, const void *data, size_t datalen); | ||
207 | |||
208 | /* match a key against a description */ | ||
209 | int (*match)(const struct key *key, const void *desc); | ||
210 | |||
211 | /* clear some of the data from a key on revokation (optional) | ||
212 | * - the key's semaphore will be write-locked by the caller | ||
213 | */ | ||
214 | void (*revoke)(struct key *key); | ||
215 | |||
216 | /* clear the data from a key (optional) */ | ||
217 | void (*destroy)(struct key *key); | ||
218 | |||
219 | /* describe a key */ | ||
220 | void (*describe)(const struct key *key, struct seq_file *p); | ||
221 | |||
222 | /* read a key's data (optional) | ||
223 | * - permission checks will be done by the caller | ||
224 | * - the key's semaphore will be readlocked by the caller | ||
225 | * - should return the amount of data that could be read, no matter how | ||
226 | * much is copied into the buffer | ||
227 | * - shouldn't do the copy if the buffer is NULL | ||
228 | */ | ||
229 | long (*read)(const struct key *key, char __user *buffer, size_t buflen); | ||
230 | |||
231 | /* handle request_key() for this type instead of invoking | ||
232 | * /sbin/request-key (optional) | ||
233 | * - key is the key to instantiate | ||
234 | * - authkey is the authority to assume when instantiating this key | ||
235 | * - op is the operation to be done, usually "create" | ||
236 | * - the call must not return until the instantiation process has run | ||
237 | * its course | ||
238 | */ | ||
239 | request_key_actor_t request_key; | ||
240 | |||
241 | /* internal fields */ | ||
242 | struct list_head link; /* link in types list */ | ||
243 | }; | ||
244 | |||
245 | extern struct key_type key_type_keyring; | ||
246 | |||
247 | extern int register_key_type(struct key_type *ktype); | ||
248 | extern void unregister_key_type(struct key_type *ktype); | ||
249 | |||
250 | extern struct key *key_alloc(struct key_type *type, | 178 | extern struct key *key_alloc(struct key_type *type, |
251 | const char *desc, | 179 | const char *desc, |
252 | uid_t uid, gid_t gid, | 180 | uid_t uid, gid_t gid, |
@@ -259,16 +187,6 @@ extern struct key *key_alloc(struct key_type *type, | |||
259 | #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ | 187 | #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ |
260 | #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ | 188 | #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ |
261 | 189 | ||
262 | extern int key_payload_reserve(struct key *key, size_t datalen); | ||
263 | extern int key_instantiate_and_link(struct key *key, | ||
264 | const void *data, | ||
265 | size_t datalen, | ||
266 | struct key *keyring, | ||
267 | struct key *instkey); | ||
268 | extern int key_negate_and_link(struct key *key, | ||
269 | unsigned timeout, | ||
270 | struct key *keyring, | ||
271 | struct key *instkey); | ||
272 | extern void key_revoke(struct key *key); | 190 | extern void key_revoke(struct key *key); |
273 | extern void key_put(struct key *key); | 191 | extern void key_put(struct key *key); |
274 | 192 | ||
@@ -293,6 +211,17 @@ extern struct key *request_key_with_auxdata(struct key_type *type, | |||
293 | const char *callout_info, | 211 | const char *callout_info, |
294 | void *aux); | 212 | void *aux); |
295 | 213 | ||
214 | extern struct key *request_key_async(struct key_type *type, | ||
215 | const char *description, | ||
216 | const char *callout_info); | ||
217 | |||
218 | extern struct key *request_key_async_with_auxdata(struct key_type *type, | ||
219 | const char *description, | ||
220 | const char *callout_info, | ||
221 | void *aux); | ||
222 | |||
223 | extern int wait_for_key_construction(struct key *key, bool intr); | ||
224 | |||
296 | extern int key_validate(struct key *key); | 225 | extern int key_validate(struct key *key); |
297 | 226 | ||
298 | extern key_ref_t key_create_or_update(key_ref_t keyring, | 227 | extern key_ref_t key_create_or_update(key_ref_t keyring, |
@@ -328,8 +257,6 @@ extern int keyring_add_key(struct key *keyring, | |||
328 | 257 | ||
329 | extern struct key *key_lookup(key_serial_t id); | 258 | extern struct key *key_lookup(key_serial_t id); |
330 | 259 | ||
331 | extern void keyring_replace_payload(struct key *key, void *replacement); | ||
332 | |||
333 | #define key_serial(key) ((key) ? (key)->serial : 0) | 260 | #define key_serial(key) ((key) ? (key)->serial : 0) |
334 | 261 | ||
335 | /* | 262 | /* |
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index 0803f305ed0..c680017f5c8 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/poll.h> | 15 | #include <linux/poll.h> |
16 | #include <linux/proc_fs.h> | 16 | #include <linux/proc_fs.h> |
17 | #include <linux/key-type.h> | ||
17 | #include <net/net_namespace.h> | 18 | #include <net/net_namespace.h> |
18 | #include <net/sock.h> | 19 | #include <net/sock.h> |
19 | #include <net/af_rxrpc.h> | 20 | #include <net/af_rxrpc.h> |
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 7e049ff6ae6..9a8ff684da7 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/net.h> | 16 | #include <linux/net.h> |
17 | #include <linux/skbuff.h> | 17 | #include <linux/skbuff.h> |
18 | #include <linux/key.h> | 18 | #include <linux/key-type.h> |
19 | #include <linux/crypto.h> | 19 | #include <linux/crypto.h> |
20 | #include <net/sock.h> | 20 | #include <net/sock.h> |
21 | #include <net/af_rxrpc.h> | 21 | #include <net/af_rxrpc.h> |
@@ -40,7 +40,6 @@ struct key_type key_type_rxrpc = { | |||
40 | .destroy = rxrpc_destroy, | 40 | .destroy = rxrpc_destroy, |
41 | .describe = rxrpc_describe, | 41 | .describe = rxrpc_describe, |
42 | }; | 42 | }; |
43 | |||
44 | EXPORT_SYMBOL(key_type_rxrpc); | 43 | EXPORT_SYMBOL(key_type_rxrpc); |
45 | 44 | ||
46 | /* | 45 | /* |
@@ -330,5 +329,32 @@ error: | |||
330 | _leave(" = -ENOMEM [ins %d]", ret); | 329 | _leave(" = -ENOMEM [ins %d]", ret); |
331 | return -ENOMEM; | 330 | return -ENOMEM; |
332 | } | 331 | } |
333 | |||
334 | EXPORT_SYMBOL(rxrpc_get_server_data_key); | 332 | EXPORT_SYMBOL(rxrpc_get_server_data_key); |
333 | |||
334 | /** | ||
335 | * rxrpc_get_null_key - Generate a null RxRPC key | ||
336 | * @keyname: The name to give the key. | ||
337 | * | ||
338 | * Generate a null RxRPC key that can be used to indicate anonymous security is | ||
339 | * required for a particular domain. | ||
340 | */ | ||
341 | struct key *rxrpc_get_null_key(const char *keyname) | ||
342 | { | ||
343 | struct key *key; | ||
344 | int ret; | ||
345 | |||
346 | key = key_alloc(&key_type_rxrpc, keyname, 0, 0, current, | ||
347 | KEY_POS_SEARCH, KEY_ALLOC_NOT_IN_QUOTA); | ||
348 | if (IS_ERR(key)) | ||
349 | return key; | ||
350 | |||
351 | ret = key_instantiate_and_link(key, NULL, 0, NULL, NULL); | ||
352 | if (ret < 0) { | ||
353 | key_revoke(key); | ||
354 | key_put(key); | ||
355 | return ERR_PTR(ret); | ||
356 | } | ||
357 | |||
358 | return key; | ||
359 | } | ||
360 | EXPORT_SYMBOL(rxrpc_get_null_key); | ||
diff --git a/security/keys/internal.h b/security/keys/internal.h index 1bb416f4bbc..d36d6939335 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* internal.h: authentication token and access key management internal defs | 1 | /* internal.h: authentication token and access key management internal defs |
2 | * | 2 | * |
3 | * Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2003-5, 2007 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -12,17 +12,28 @@ | |||
12 | #ifndef _INTERNAL_H | 12 | #ifndef _INTERNAL_H |
13 | #define _INTERNAL_H | 13 | #define _INTERNAL_H |
14 | 14 | ||
15 | #include <linux/key.h> | 15 | #include <linux/key-type.h> |
16 | #include <linux/key-ui.h> | 16 | #include <linux/key-ui.h> |
17 | 17 | ||
18 | #if 0 | 18 | static inline __attribute__((format(printf, 1, 2))) |
19 | #define kenter(FMT, a...) printk("==> %s("FMT")\n",__FUNCTION__ , ## a) | 19 | void no_printk(const char *fmt, ...) |
20 | #define kleave(FMT, a...) printk("<== %s()"FMT"\n",__FUNCTION__ , ## a) | 20 | { |
21 | #define kdebug(FMT, a...) printk(FMT"\n" , ## a) | 21 | } |
22 | |||
23 | #ifdef __KDEBUG | ||
24 | #define kenter(FMT, ...) \ | ||
25 | printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__) | ||
26 | #define kleave(FMT, ...) \ | ||
27 | printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__) | ||
28 | #define kdebug(FMT, ...) \ | ||
29 | printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__) | ||
22 | #else | 30 | #else |
23 | #define kenter(FMT, a...) do {} while(0) | 31 | #define kenter(FMT, ...) \ |
24 | #define kleave(FMT, a...) do {} while(0) | 32 | no_printk(KERN_DEBUG "==> %s("FMT")\n", __FUNCTION__, ##__VA_ARGS__) |
25 | #define kdebug(FMT, a...) do {} while(0) | 33 | #define kleave(FMT, ...) \ |
34 | no_printk(KERN_DEBUG "<== %s()"FMT"\n", __FUNCTION__, ##__VA_ARGS__) | ||
35 | #define kdebug(FMT, ...) \ | ||
36 | no_printk(KERN_DEBUG FMT"\n", ##__VA_ARGS__) | ||
26 | #endif | 37 | #endif |
27 | 38 | ||
28 | extern struct key_type key_type_user; | 39 | extern struct key_type key_type_user; |
@@ -36,7 +47,7 @@ extern struct key_type key_type_user; | |||
36 | */ | 47 | */ |
37 | struct key_user { | 48 | struct key_user { |
38 | struct rb_node node; | 49 | struct rb_node node; |
39 | struct list_head consq; /* construction queue */ | 50 | struct mutex cons_lock; /* construction initiation lock */ |
40 | spinlock_t lock; | 51 | spinlock_t lock; |
41 | atomic_t usage; /* for accessing qnkeys & qnbytes */ | 52 | atomic_t usage; /* for accessing qnkeys & qnbytes */ |
42 | atomic_t nkeys; /* number of keys */ | 53 | atomic_t nkeys; /* number of keys */ |
@@ -62,7 +73,7 @@ extern void key_user_put(struct key_user *user); | |||
62 | extern struct rb_root key_serial_tree; | 73 | extern struct rb_root key_serial_tree; |
63 | extern spinlock_t key_serial_lock; | 74 | extern spinlock_t key_serial_lock; |
64 | extern struct semaphore key_alloc_sem; | 75 | extern struct semaphore key_alloc_sem; |
65 | extern struct rw_semaphore key_construction_sem; | 76 | extern struct mutex key_construction_mutex; |
66 | extern wait_queue_head_t request_key_conswq; | 77 | extern wait_queue_head_t request_key_conswq; |
67 | 78 | ||
68 | 79 | ||
@@ -109,7 +120,7 @@ extern struct key *request_key_and_link(struct key_type *type, | |||
109 | struct request_key_auth { | 120 | struct request_key_auth { |
110 | struct key *target_key; | 121 | struct key *target_key; |
111 | struct task_struct *context; | 122 | struct task_struct *context; |
112 | const char *callout_info; | 123 | char *callout_info; |
113 | pid_t pid; | 124 | pid_t pid; |
114 | }; | 125 | }; |
115 | 126 | ||
diff --git a/security/keys/key.c b/security/keys/key.c index 01bbc6d9d19..fdd5ca6d89f 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* key.c: basic authentication token and access key management | 1 | /* Basic authentication token and access key management |
2 | * | 2 | * |
3 | * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -34,7 +34,7 @@ static void key_cleanup(struct work_struct *work); | |||
34 | static DECLARE_WORK(key_cleanup_task, key_cleanup); | 34 | static DECLARE_WORK(key_cleanup_task, key_cleanup); |
35 | 35 | ||
36 | /* we serialise key instantiation and link */ | 36 | /* we serialise key instantiation and link */ |
37 | DECLARE_RWSEM(key_construction_sem); | 37 | DEFINE_MUTEX(key_construction_mutex); |
38 | 38 | ||
39 | /* any key who's type gets unegistered will be re-typed to this */ | 39 | /* any key who's type gets unegistered will be re-typed to this */ |
40 | static struct key_type key_type_dead = { | 40 | static struct key_type key_type_dead = { |
@@ -104,7 +104,7 @@ struct key_user *key_user_lookup(uid_t uid) | |||
104 | candidate->qnkeys = 0; | 104 | candidate->qnkeys = 0; |
105 | candidate->qnbytes = 0; | 105 | candidate->qnbytes = 0; |
106 | spin_lock_init(&candidate->lock); | 106 | spin_lock_init(&candidate->lock); |
107 | INIT_LIST_HEAD(&candidate->consq); | 107 | mutex_init(&candidate->cons_lock); |
108 | 108 | ||
109 | rb_link_node(&candidate->node, parent, p); | 109 | rb_link_node(&candidate->node, parent, p); |
110 | rb_insert_color(&candidate->node, &key_user_tree); | 110 | rb_insert_color(&candidate->node, &key_user_tree); |
@@ -418,7 +418,7 @@ static int __key_instantiate_and_link(struct key *key, | |||
418 | awaken = 0; | 418 | awaken = 0; |
419 | ret = -EBUSY; | 419 | ret = -EBUSY; |
420 | 420 | ||
421 | down_write(&key_construction_sem); | 421 | mutex_lock(&key_construction_mutex); |
422 | 422 | ||
423 | /* can't instantiate twice */ | 423 | /* can't instantiate twice */ |
424 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { | 424 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { |
@@ -443,11 +443,11 @@ static int __key_instantiate_and_link(struct key *key, | |||
443 | } | 443 | } |
444 | } | 444 | } |
445 | 445 | ||
446 | up_write(&key_construction_sem); | 446 | mutex_unlock(&key_construction_mutex); |
447 | 447 | ||
448 | /* wake up anyone waiting for a key to be constructed */ | 448 | /* wake up anyone waiting for a key to be constructed */ |
449 | if (awaken) | 449 | if (awaken) |
450 | wake_up_all(&request_key_conswq); | 450 | wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT); |
451 | 451 | ||
452 | return ret; | 452 | return ret; |
453 | 453 | ||
@@ -500,7 +500,7 @@ int key_negate_and_link(struct key *key, | |||
500 | if (keyring) | 500 | if (keyring) |
501 | down_write(&keyring->sem); | 501 | down_write(&keyring->sem); |
502 | 502 | ||
503 | down_write(&key_construction_sem); | 503 | mutex_lock(&key_construction_mutex); |
504 | 504 | ||
505 | /* can't instantiate twice */ | 505 | /* can't instantiate twice */ |
506 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { | 506 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { |
@@ -525,14 +525,14 @@ int key_negate_and_link(struct key *key, | |||
525 | key_revoke(instkey); | 525 | key_revoke(instkey); |
526 | } | 526 | } |
527 | 527 | ||
528 | up_write(&key_construction_sem); | 528 | mutex_unlock(&key_construction_mutex); |
529 | 529 | ||
530 | if (keyring) | 530 | if (keyring) |
531 | up_write(&keyring->sem); | 531 | up_write(&keyring->sem); |
532 | 532 | ||
533 | /* wake up anyone waiting for a key to be constructed */ | 533 | /* wake up anyone waiting for a key to be constructed */ |
534 | if (awaken) | 534 | if (awaken) |
535 | wake_up_all(&request_key_conswq); | 535 | wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT); |
536 | 536 | ||
537 | return ret; | 537 | return ret; |
538 | 538 | ||
@@ -899,12 +899,14 @@ void key_revoke(struct key *key) | |||
899 | { | 899 | { |
900 | key_check(key); | 900 | key_check(key); |
901 | 901 | ||
902 | /* make sure no one's trying to change or use the key when we mark | 902 | /* make sure no one's trying to change or use the key when we mark it |
903 | * it */ | 903 | * - we tell lockdep that we might nest because we might be revoking an |
904 | down_write(&key->sem); | 904 | * authorisation key whilst holding the sem on a key we've just |
905 | set_bit(KEY_FLAG_REVOKED, &key->flags); | 905 | * instantiated |
906 | 906 | */ | |
907 | if (key->type->revoke) | 907 | down_write_nested(&key->sem, 1); |
908 | if (!test_and_set_bit(KEY_FLAG_REVOKED, &key->flags) && | ||
909 | key->type->revoke) | ||
908 | key->type->revoke(key); | 910 | key->type->revoke(key); |
909 | 911 | ||
910 | up_write(&key->sem); | 912 | up_write(&key->sem); |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index b6f86808475..2a0eb946fc7 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -26,7 +26,7 @@ static DEFINE_MUTEX(key_session_mutex); | |||
26 | /* the root user's tracking struct */ | 26 | /* the root user's tracking struct */ |
27 | struct key_user root_key_user = { | 27 | struct key_user root_key_user = { |
28 | .usage = ATOMIC_INIT(3), | 28 | .usage = ATOMIC_INIT(3), |
29 | .consq = LIST_HEAD_INIT(root_key_user.consq), | 29 | .cons_lock = __MUTEX_INITIALIZER(root_key_user.cons_lock), |
30 | .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock), | 30 | .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock), |
31 | .nkeys = ATOMIC_INIT(2), | 31 | .nkeys = ATOMIC_INIT(2), |
32 | .nikeys = ATOMIC_INIT(2), | 32 | .nikeys = ATOMIC_INIT(2), |
@@ -679,8 +679,18 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, | |||
679 | break; | 679 | break; |
680 | } | 680 | } |
681 | 681 | ||
682 | /* check the status */ | 682 | if (!partial) { |
683 | if (perm) { | 683 | ret = wait_for_key_construction(key, true); |
684 | switch (ret) { | ||
685 | case -ERESTARTSYS: | ||
686 | goto invalid_key; | ||
687 | default: | ||
688 | if (perm) | ||
689 | goto invalid_key; | ||
690 | case 0: | ||
691 | break; | ||
692 | } | ||
693 | } else if (perm) { | ||
684 | ret = key_validate(key); | 694 | ret = key_validate(key); |
685 | if (ret < 0) | 695 | if (ret < 0) |
686 | goto invalid_key; | 696 | goto invalid_key; |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 557500110a1..6381e616c47 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* request_key.c: request a key from userspace | 1 | /* Request a key from userspace |
2 | * | 2 | * |
3 | * Copyright (C) 2004-6 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004-2007 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -18,27 +18,54 @@ | |||
18 | #include <linux/keyctl.h> | 18 | #include <linux/keyctl.h> |
19 | #include "internal.h" | 19 | #include "internal.h" |
20 | 20 | ||
21 | struct key_construction { | 21 | /* |
22 | struct list_head link; /* link in construction queue */ | 22 | * wait_on_bit() sleep function for uninterruptible waiting |
23 | struct key *key; /* key being constructed */ | 23 | */ |
24 | }; | 24 | static int key_wait_bit(void *flags) |
25 | { | ||
26 | schedule(); | ||
27 | return 0; | ||
28 | } | ||
29 | |||
30 | /* | ||
31 | * wait_on_bit() sleep function for interruptible waiting | ||
32 | */ | ||
33 | static int key_wait_bit_intr(void *flags) | ||
34 | { | ||
35 | schedule(); | ||
36 | return signal_pending(current) ? -ERESTARTSYS : 0; | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * call to complete the construction of a key | ||
41 | */ | ||
42 | void complete_request_key(struct key_construction *cons, int error) | ||
43 | { | ||
44 | kenter("{%d,%d},%d", cons->key->serial, cons->authkey->serial, error); | ||
25 | 45 | ||
26 | /* when waiting for someone else's keys, you get added to this */ | 46 | if (error < 0) |
27 | DECLARE_WAIT_QUEUE_HEAD(request_key_conswq); | 47 | key_negate_and_link(cons->key, key_negative_timeout, NULL, |
48 | cons->authkey); | ||
49 | else | ||
50 | key_revoke(cons->authkey); | ||
51 | |||
52 | key_put(cons->key); | ||
53 | key_put(cons->authkey); | ||
54 | kfree(cons); | ||
55 | } | ||
56 | EXPORT_SYMBOL(complete_request_key); | ||
28 | 57 | ||
29 | /*****************************************************************************/ | ||
30 | /* | 58 | /* |
31 | * request userspace finish the construction of a key | 59 | * request userspace finish the construction of a key |
32 | * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>" | 60 | * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>" |
33 | */ | 61 | */ |
34 | static int call_sbin_request_key(struct key *key, | 62 | static int call_sbin_request_key(struct key_construction *cons, |
35 | struct key *authkey, | ||
36 | const char *op, | 63 | const char *op, |
37 | void *aux) | 64 | void *aux) |
38 | { | 65 | { |
39 | struct task_struct *tsk = current; | 66 | struct task_struct *tsk = current; |
40 | key_serial_t prkey, sskey; | 67 | key_serial_t prkey, sskey; |
41 | struct key *keyring; | 68 | struct key *key = cons->key, *authkey = cons->authkey, *keyring; |
42 | char *argv[9], *envp[3], uid_str[12], gid_str[12]; | 69 | char *argv[9], *envp[3], uid_str[12], gid_str[12]; |
43 | char key_str[12], keyring_str[3][12]; | 70 | char key_str[12], keyring_str[3][12]; |
44 | char desc[20]; | 71 | char desc[20]; |
@@ -82,8 +109,7 @@ static int call_sbin_request_key(struct key *key, | |||
82 | rcu_read_lock(); | 109 | rcu_read_lock(); |
83 | sskey = rcu_dereference(tsk->signal->session_keyring)->serial; | 110 | sskey = rcu_dereference(tsk->signal->session_keyring)->serial; |
84 | rcu_read_unlock(); | 111 | rcu_read_unlock(); |
85 | } | 112 | } else { |
86 | else { | ||
87 | sskey = tsk->user->session_keyring->serial; | 113 | sskey = tsk->user->session_keyring->serial; |
88 | } | 114 | } |
89 | 115 | ||
@@ -110,228 +136,77 @@ static int call_sbin_request_key(struct key *key, | |||
110 | /* do it */ | 136 | /* do it */ |
111 | ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, | 137 | ret = call_usermodehelper_keys(argv[0], argv, envp, keyring, |
112 | UMH_WAIT_PROC); | 138 | UMH_WAIT_PROC); |
139 | kdebug("usermode -> 0x%x", ret); | ||
140 | if (ret >= 0) { | ||
141 | /* ret is the exit/wait code */ | ||
142 | if (test_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags) || | ||
143 | key_validate(key) < 0) | ||
144 | ret = -ENOKEY; | ||
145 | else | ||
146 | /* ignore any errors from userspace if the key was | ||
147 | * instantiated */ | ||
148 | ret = 0; | ||
149 | } | ||
113 | 150 | ||
114 | error_link: | 151 | error_link: |
115 | key_put(keyring); | 152 | key_put(keyring); |
116 | 153 | ||
117 | error_alloc: | 154 | error_alloc: |
118 | kleave(" = %d", ret); | 155 | kleave(" = %d", ret); |
156 | complete_request_key(cons, ret); | ||
119 | return ret; | 157 | return ret; |
158 | } | ||
120 | 159 | ||
121 | } /* end call_sbin_request_key() */ | ||
122 | |||
123 | /*****************************************************************************/ | ||
124 | /* | 160 | /* |
125 | * call out to userspace for the key | 161 | * call out to userspace for key construction |
126 | * - called with the construction sem held, but the sem is dropped here | ||
127 | * - we ignore program failure and go on key status instead | 162 | * - we ignore program failure and go on key status instead |
128 | */ | 163 | */ |
129 | static struct key *__request_key_construction(struct key_type *type, | 164 | static int construct_key(struct key *key, const char *callout_info, void *aux) |
130 | const char *description, | ||
131 | const char *callout_info, | ||
132 | void *aux, | ||
133 | unsigned long flags) | ||
134 | { | 165 | { |
166 | struct key_construction *cons; | ||
135 | request_key_actor_t actor; | 167 | request_key_actor_t actor; |
136 | struct key_construction cons; | 168 | struct key *authkey; |
137 | struct timespec now; | 169 | int ret; |
138 | struct key *key, *authkey; | ||
139 | int ret, negated; | ||
140 | 170 | ||
141 | kenter("%s,%s,%s,%lx", type->name, description, callout_info, flags); | 171 | kenter("%d,%s,%p", key->serial, callout_info, aux); |
142 | 172 | ||
143 | /* create a key and add it to the queue */ | 173 | cons = kmalloc(sizeof(*cons), GFP_KERNEL); |
144 | key = key_alloc(type, description, | 174 | if (!cons) |
145 | current->fsuid, current->fsgid, current, KEY_POS_ALL, | 175 | return -ENOMEM; |
146 | flags); | ||
147 | if (IS_ERR(key)) | ||
148 | goto alloc_failed; | ||
149 | |||
150 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); | ||
151 | |||
152 | cons.key = key; | ||
153 | list_add_tail(&cons.link, &key->user->consq); | ||
154 | |||
155 | /* we drop the construction sem here on behalf of the caller */ | ||
156 | up_write(&key_construction_sem); | ||
157 | 176 | ||
158 | /* allocate an authorisation key */ | 177 | /* allocate an authorisation key */ |
159 | authkey = request_key_auth_new(key, callout_info); | 178 | authkey = request_key_auth_new(key, callout_info); |
160 | if (IS_ERR(authkey)) { | 179 | if (IS_ERR(authkey)) { |
180 | kfree(cons); | ||
161 | ret = PTR_ERR(authkey); | 181 | ret = PTR_ERR(authkey); |
162 | authkey = NULL; | 182 | authkey = NULL; |
163 | goto alloc_authkey_failed; | 183 | } else { |
164 | } | 184 | cons->authkey = key_get(authkey); |
165 | 185 | cons->key = key_get(key); | |
166 | /* make the call */ | 186 | |
167 | actor = call_sbin_request_key; | 187 | /* make the call */ |
168 | if (type->request_key) | 188 | actor = call_sbin_request_key; |
169 | actor = type->request_key; | 189 | if (key->type->request_key) |
170 | ret = actor(key, authkey, "create", aux); | 190 | actor = key->type->request_key; |
171 | if (ret < 0) | 191 | |
172 | goto request_failed; | 192 | ret = actor(cons, "create", aux); |
173 | 193 | ||
174 | /* if the key wasn't instantiated, then we want to give an error */ | 194 | /* check that the actor called complete_request_key() prior to |
175 | ret = -ENOKEY; | 195 | * returning an error */ |
176 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) | 196 | WARN_ON(ret < 0 && |
177 | goto request_failed; | 197 | !test_bit(KEY_FLAG_REVOKED, &authkey->flags)); |
178 | 198 | key_put(authkey); | |
179 | key_revoke(authkey); | ||
180 | key_put(authkey); | ||
181 | |||
182 | down_write(&key_construction_sem); | ||
183 | list_del(&cons.link); | ||
184 | up_write(&key_construction_sem); | ||
185 | |||
186 | /* also give an error if the key was negatively instantiated */ | ||
187 | check_not_negative: | ||
188 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { | ||
189 | key_put(key); | ||
190 | key = ERR_PTR(-ENOKEY); | ||
191 | } | ||
192 | |||
193 | out: | ||
194 | kleave(" = %p", key); | ||
195 | return key; | ||
196 | |||
197 | request_failed: | ||
198 | key_revoke(authkey); | ||
199 | key_put(authkey); | ||
200 | |||
201 | alloc_authkey_failed: | ||
202 | /* it wasn't instantiated | ||
203 | * - remove from construction queue | ||
204 | * - mark the key as dead | ||
205 | */ | ||
206 | negated = 0; | ||
207 | down_write(&key_construction_sem); | ||
208 | |||
209 | list_del(&cons.link); | ||
210 | |||
211 | /* check it didn't get instantiated between the check and the down */ | ||
212 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { | ||
213 | set_bit(KEY_FLAG_NEGATIVE, &key->flags); | ||
214 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); | ||
215 | negated = 1; | ||
216 | } | ||
217 | |||
218 | clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); | ||
219 | |||
220 | up_write(&key_construction_sem); | ||
221 | |||
222 | if (!negated) | ||
223 | goto check_not_negative; /* surprisingly, the key got | ||
224 | * instantiated */ | ||
225 | |||
226 | /* set the timeout and store in the session keyring if we can */ | ||
227 | now = current_kernel_time(); | ||
228 | key->expiry = now.tv_sec + key_negative_timeout; | ||
229 | |||
230 | if (current->signal->session_keyring) { | ||
231 | struct key *keyring; | ||
232 | |||
233 | rcu_read_lock(); | ||
234 | keyring = rcu_dereference(current->signal->session_keyring); | ||
235 | atomic_inc(&keyring->usage); | ||
236 | rcu_read_unlock(); | ||
237 | |||
238 | key_link(keyring, key); | ||
239 | key_put(keyring); | ||
240 | } | ||
241 | |||
242 | key_put(key); | ||
243 | |||
244 | /* notify anyone who was waiting */ | ||
245 | wake_up_all(&request_key_conswq); | ||
246 | |||
247 | key = ERR_PTR(ret); | ||
248 | goto out; | ||
249 | |||
250 | alloc_failed: | ||
251 | up_write(&key_construction_sem); | ||
252 | goto out; | ||
253 | |||
254 | } /* end __request_key_construction() */ | ||
255 | |||
256 | /*****************************************************************************/ | ||
257 | /* | ||
258 | * call out to userspace to request the key | ||
259 | * - we check the construction queue first to see if an appropriate key is | ||
260 | * already being constructed by userspace | ||
261 | */ | ||
262 | static struct key *request_key_construction(struct key_type *type, | ||
263 | const char *description, | ||
264 | const char *callout_info, | ||
265 | void *aux, | ||
266 | struct key_user *user, | ||
267 | unsigned long flags) | ||
268 | { | ||
269 | struct key_construction *pcons; | ||
270 | struct key *key, *ckey; | ||
271 | |||
272 | DECLARE_WAITQUEUE(myself, current); | ||
273 | |||
274 | kenter("%s,%s,{%d},%s,%lx", | ||
275 | type->name, description, user->uid, callout_info, flags); | ||
276 | |||
277 | /* see if there's such a key under construction already */ | ||
278 | down_write(&key_construction_sem); | ||
279 | |||
280 | list_for_each_entry(pcons, &user->consq, link) { | ||
281 | ckey = pcons->key; | ||
282 | |||
283 | if (ckey->type != type) | ||
284 | continue; | ||
285 | |||
286 | if (type->match(ckey, description)) | ||
287 | goto found_key_under_construction; | ||
288 | } | 199 | } |
289 | 200 | ||
290 | /* see about getting userspace to construct the key */ | 201 | kleave(" = %d", ret); |
291 | key = __request_key_construction(type, description, callout_info, aux, | 202 | return ret; |
292 | flags); | 203 | } |
293 | error: | ||
294 | kleave(" = %p", key); | ||
295 | return key; | ||
296 | |||
297 | /* someone else has the same key under construction | ||
298 | * - we want to keep an eye on their key | ||
299 | */ | ||
300 | found_key_under_construction: | ||
301 | atomic_inc(&ckey->usage); | ||
302 | up_write(&key_construction_sem); | ||
303 | |||
304 | /* wait for the key to be completed one way or another */ | ||
305 | add_wait_queue(&request_key_conswq, &myself); | ||
306 | |||
307 | for (;;) { | ||
308 | set_current_state(TASK_INTERRUPTIBLE); | ||
309 | if (!test_bit(KEY_FLAG_USER_CONSTRUCT, &ckey->flags)) | ||
310 | break; | ||
311 | if (signal_pending(current)) | ||
312 | break; | ||
313 | schedule(); | ||
314 | } | ||
315 | |||
316 | set_current_state(TASK_RUNNING); | ||
317 | remove_wait_queue(&request_key_conswq, &myself); | ||
318 | |||
319 | /* we'll need to search this process's keyrings to see if the key is | ||
320 | * now there since we can't automatically assume it's also available | ||
321 | * there */ | ||
322 | key_put(ckey); | ||
323 | ckey = NULL; | ||
324 | |||
325 | key = NULL; /* request a retry */ | ||
326 | goto error; | ||
327 | |||
328 | } /* end request_key_construction() */ | ||
329 | 204 | ||
330 | /*****************************************************************************/ | ||
331 | /* | 205 | /* |
332 | * link a freshly minted key to an appropriate destination keyring | 206 | * link a key to the appropriate destination keyring |
207 | * - the caller must hold a write lock on the destination keyring | ||
333 | */ | 208 | */ |
334 | static void request_key_link(struct key *key, struct key *dest_keyring) | 209 | static void construct_key_make_link(struct key *key, struct key *dest_keyring) |
335 | { | 210 | { |
336 | struct task_struct *tsk = current; | 211 | struct task_struct *tsk = current; |
337 | struct key *drop = NULL; | 212 | struct key *drop = NULL; |
@@ -363,11 +238,11 @@ static void request_key_link(struct key *key, struct key *dest_keyring) | |||
363 | break; | 238 | break; |
364 | 239 | ||
365 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: | 240 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: |
366 | dest_keyring = current->user->session_keyring; | 241 | dest_keyring = tsk->user->session_keyring; |
367 | break; | 242 | break; |
368 | 243 | ||
369 | case KEY_REQKEY_DEFL_USER_KEYRING: | 244 | case KEY_REQKEY_DEFL_USER_KEYRING: |
370 | dest_keyring = current->user->uid_keyring; | 245 | dest_keyring = tsk->user->uid_keyring; |
371 | break; | 246 | break; |
372 | 247 | ||
373 | case KEY_REQKEY_DEFL_GROUP_KEYRING: | 248 | case KEY_REQKEY_DEFL_GROUP_KEYRING: |
@@ -377,15 +252,115 @@ static void request_key_link(struct key *key, struct key *dest_keyring) | |||
377 | } | 252 | } |
378 | 253 | ||
379 | /* and attach the key to it */ | 254 | /* and attach the key to it */ |
380 | key_link(dest_keyring, key); | 255 | __key_link(dest_keyring, key); |
381 | |||
382 | key_put(drop); | 256 | key_put(drop); |
383 | |||
384 | kleave(""); | 257 | kleave(""); |
258 | } | ||
385 | 259 | ||
386 | } /* end request_key_link() */ | 260 | /* |
261 | * allocate a new key in under-construction state and attempt to link it in to | ||
262 | * the requested place | ||
263 | * - may return a key that's already under construction instead | ||
264 | */ | ||
265 | static int construct_alloc_key(struct key_type *type, | ||
266 | const char *description, | ||
267 | struct key *dest_keyring, | ||
268 | unsigned long flags, | ||
269 | struct key_user *user, | ||
270 | struct key **_key) | ||
271 | { | ||
272 | struct key *key; | ||
273 | key_ref_t key_ref; | ||
274 | |||
275 | kenter("%s,%s,,,", type->name, description); | ||
276 | |||
277 | mutex_lock(&user->cons_lock); | ||
278 | |||
279 | key = key_alloc(type, description, | ||
280 | current->fsuid, current->fsgid, current, KEY_POS_ALL, | ||
281 | flags); | ||
282 | if (IS_ERR(key)) | ||
283 | goto alloc_failed; | ||
284 | |||
285 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); | ||
286 | |||
287 | if (dest_keyring) | ||
288 | down_write(&dest_keyring->sem); | ||
289 | |||
290 | /* attach the key to the destination keyring under lock, but we do need | ||
291 | * to do another check just in case someone beat us to it whilst we | ||
292 | * waited for locks */ | ||
293 | mutex_lock(&key_construction_mutex); | ||
294 | |||
295 | key_ref = search_process_keyrings(type, description, type->match, | ||
296 | current); | ||
297 | if (!IS_ERR(key_ref)) | ||
298 | goto key_already_present; | ||
299 | |||
300 | if (dest_keyring) | ||
301 | construct_key_make_link(key, dest_keyring); | ||
302 | |||
303 | mutex_unlock(&key_construction_mutex); | ||
304 | if (dest_keyring) | ||
305 | up_write(&dest_keyring->sem); | ||
306 | mutex_unlock(&user->cons_lock); | ||
307 | *_key = key; | ||
308 | kleave(" = 0 [%d]", key_serial(key)); | ||
309 | return 0; | ||
310 | |||
311 | key_already_present: | ||
312 | mutex_unlock(&key_construction_mutex); | ||
313 | if (dest_keyring) | ||
314 | up_write(&dest_keyring->sem); | ||
315 | mutex_unlock(&user->cons_lock); | ||
316 | key_put(key); | ||
317 | *_key = key = key_ref_to_ptr(key_ref); | ||
318 | kleave(" = -EINPROGRESS [%d]", key_serial(key)); | ||
319 | return -EINPROGRESS; | ||
320 | |||
321 | alloc_failed: | ||
322 | mutex_unlock(&user->cons_lock); | ||
323 | *_key = NULL; | ||
324 | kleave(" = %ld", PTR_ERR(key)); | ||
325 | return PTR_ERR(key); | ||
326 | } | ||
327 | |||
328 | /* | ||
329 | * commence key construction | ||
330 | */ | ||
331 | static struct key *construct_key_and_link(struct key_type *type, | ||
332 | const char *description, | ||
333 | const char *callout_info, | ||
334 | void *aux, | ||
335 | struct key *dest_keyring, | ||
336 | unsigned long flags) | ||
337 | { | ||
338 | struct key_user *user; | ||
339 | struct key *key; | ||
340 | int ret; | ||
341 | |||
342 | user = key_user_lookup(current->fsuid); | ||
343 | if (!user) | ||
344 | return ERR_PTR(-ENOMEM); | ||
345 | |||
346 | ret = construct_alloc_key(type, description, dest_keyring, flags, user, | ||
347 | &key); | ||
348 | key_user_put(user); | ||
349 | |||
350 | if (ret == 0) { | ||
351 | ret = construct_key(key, callout_info, aux); | ||
352 | if (ret < 0) | ||
353 | goto construction_failed; | ||
354 | } | ||
355 | |||
356 | return key; | ||
357 | |||
358 | construction_failed: | ||
359 | key_negate_and_link(key, key_negative_timeout, NULL, NULL); | ||
360 | key_put(key); | ||
361 | return ERR_PTR(ret); | ||
362 | } | ||
387 | 363 | ||
388 | /*****************************************************************************/ | ||
389 | /* | 364 | /* |
390 | * request a key | 365 | * request a key |
391 | * - search the process's keyrings | 366 | * - search the process's keyrings |
@@ -400,7 +375,6 @@ struct key *request_key_and_link(struct key_type *type, | |||
400 | struct key *dest_keyring, | 375 | struct key *dest_keyring, |
401 | unsigned long flags) | 376 | unsigned long flags) |
402 | { | 377 | { |
403 | struct key_user *user; | ||
404 | struct key *key; | 378 | struct key *key; |
405 | key_ref_t key_ref; | 379 | key_ref_t key_ref; |
406 | 380 | ||
@@ -412,112 +386,124 @@ struct key *request_key_and_link(struct key_type *type, | |||
412 | key_ref = search_process_keyrings(type, description, type->match, | 386 | key_ref = search_process_keyrings(type, description, type->match, |
413 | current); | 387 | current); |
414 | 388 | ||
415 | kdebug("search 1: %p", key_ref); | ||
416 | |||
417 | if (!IS_ERR(key_ref)) { | 389 | if (!IS_ERR(key_ref)) { |
418 | key = key_ref_to_ptr(key_ref); | 390 | key = key_ref_to_ptr(key_ref); |
419 | } | 391 | } else if (PTR_ERR(key_ref) != -EAGAIN) { |
420 | else if (PTR_ERR(key_ref) != -EAGAIN) { | ||
421 | key = ERR_PTR(PTR_ERR(key_ref)); | 392 | key = ERR_PTR(PTR_ERR(key_ref)); |
422 | } | 393 | } else { |
423 | else { | ||
424 | /* the search failed, but the keyrings were searchable, so we | 394 | /* the search failed, but the keyrings were searchable, so we |
425 | * should consult userspace if we can */ | 395 | * should consult userspace if we can */ |
426 | key = ERR_PTR(-ENOKEY); | 396 | key = ERR_PTR(-ENOKEY); |
427 | if (!callout_info) | 397 | if (!callout_info) |
428 | goto error; | 398 | goto error; |
429 | 399 | ||
430 | /* - get hold of the user's construction queue */ | 400 | key = construct_key_and_link(type, description, callout_info, |
431 | user = key_user_lookup(current->fsuid); | 401 | aux, dest_keyring, flags); |
432 | if (!user) | ||
433 | goto nomem; | ||
434 | |||
435 | for (;;) { | ||
436 | if (signal_pending(current)) | ||
437 | goto interrupted; | ||
438 | |||
439 | /* ask userspace (returns NULL if it waited on a key | ||
440 | * being constructed) */ | ||
441 | key = request_key_construction(type, description, | ||
442 | callout_info, aux, | ||
443 | user, flags); | ||
444 | if (key) | ||
445 | break; | ||
446 | |||
447 | /* someone else made the key we want, so we need to | ||
448 | * search again as it might now be available to us */ | ||
449 | key_ref = search_process_keyrings(type, description, | ||
450 | type->match, | ||
451 | current); | ||
452 | |||
453 | kdebug("search 2: %p", key_ref); | ||
454 | |||
455 | if (!IS_ERR(key_ref)) { | ||
456 | key = key_ref_to_ptr(key_ref); | ||
457 | break; | ||
458 | } | ||
459 | |||
460 | if (PTR_ERR(key_ref) != -EAGAIN) { | ||
461 | key = ERR_PTR(PTR_ERR(key_ref)); | ||
462 | break; | ||
463 | } | ||
464 | } | ||
465 | |||
466 | key_user_put(user); | ||
467 | |||
468 | /* link the new key into the appropriate keyring */ | ||
469 | if (!IS_ERR(key)) | ||
470 | request_key_link(key, dest_keyring); | ||
471 | } | 402 | } |
472 | 403 | ||
473 | error: | 404 | error: |
474 | kleave(" = %p", key); | 405 | kleave(" = %p", key); |
475 | return key; | 406 | return key; |
407 | } | ||
476 | 408 | ||
477 | nomem: | 409 | /* |
478 | key = ERR_PTR(-ENOMEM); | 410 | * wait for construction of a key to complete |
479 | goto error; | 411 | */ |
480 | 412 | int wait_for_key_construction(struct key *key, bool intr) | |
481 | interrupted: | 413 | { |
482 | key_user_put(user); | 414 | int ret; |
483 | key = ERR_PTR(-EINTR); | ||
484 | goto error; | ||
485 | 415 | ||
486 | } /* end request_key_and_link() */ | 416 | ret = wait_on_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT, |
417 | intr ? key_wait_bit_intr : key_wait_bit, | ||
418 | intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); | ||
419 | if (ret < 0) | ||
420 | return ret; | ||
421 | return key_validate(key); | ||
422 | } | ||
423 | EXPORT_SYMBOL(wait_for_key_construction); | ||
487 | 424 | ||
488 | /*****************************************************************************/ | ||
489 | /* | 425 | /* |
490 | * request a key | 426 | * request a key |
491 | * - search the process's keyrings | 427 | * - search the process's keyrings |
492 | * - check the list of keys being created or updated | 428 | * - check the list of keys being created or updated |
493 | * - call out to userspace for a key if supplementary info was provided | 429 | * - call out to userspace for a key if supplementary info was provided |
430 | * - waits uninterruptible for creation to complete | ||
494 | */ | 431 | */ |
495 | struct key *request_key(struct key_type *type, | 432 | struct key *request_key(struct key_type *type, |
496 | const char *description, | 433 | const char *description, |
497 | const char *callout_info) | 434 | const char *callout_info) |
498 | { | 435 | { |
499 | return request_key_and_link(type, description, callout_info, NULL, | 436 | struct key *key; |
500 | NULL, KEY_ALLOC_IN_QUOTA); | 437 | int ret; |
501 | 438 | ||
502 | } /* end request_key() */ | 439 | key = request_key_and_link(type, description, callout_info, NULL, |
503 | 440 | NULL, KEY_ALLOC_IN_QUOTA); | |
441 | if (!IS_ERR(key)) { | ||
442 | ret = wait_for_key_construction(key, false); | ||
443 | if (ret < 0) { | ||
444 | key_put(key); | ||
445 | return ERR_PTR(ret); | ||
446 | } | ||
447 | } | ||
448 | return key; | ||
449 | } | ||
504 | EXPORT_SYMBOL(request_key); | 450 | EXPORT_SYMBOL(request_key); |
505 | 451 | ||
506 | /*****************************************************************************/ | ||
507 | /* | 452 | /* |
508 | * request a key with auxiliary data for the upcaller | 453 | * request a key with auxiliary data for the upcaller |
509 | * - search the process's keyrings | 454 | * - search the process's keyrings |
510 | * - check the list of keys being created or updated | 455 | * - check the list of keys being created or updated |
511 | * - call out to userspace for a key if supplementary info was provided | 456 | * - call out to userspace for a key if supplementary info was provided |
457 | * - waits uninterruptible for creation to complete | ||
512 | */ | 458 | */ |
513 | struct key *request_key_with_auxdata(struct key_type *type, | 459 | struct key *request_key_with_auxdata(struct key_type *type, |
514 | const char *description, | 460 | const char *description, |
515 | const char *callout_info, | 461 | const char *callout_info, |
516 | void *aux) | 462 | void *aux) |
517 | { | 463 | { |
518 | return request_key_and_link(type, description, callout_info, aux, | 464 | struct key *key; |
519 | NULL, KEY_ALLOC_IN_QUOTA); | 465 | int ret; |
466 | |||
467 | key = request_key_and_link(type, description, callout_info, aux, | ||
468 | NULL, KEY_ALLOC_IN_QUOTA); | ||
469 | if (!IS_ERR(key)) { | ||
470 | ret = wait_for_key_construction(key, false); | ||
471 | if (ret < 0) { | ||
472 | key_put(key); | ||
473 | return ERR_PTR(ret); | ||
474 | } | ||
475 | } | ||
476 | return key; | ||
477 | } | ||
478 | EXPORT_SYMBOL(request_key_with_auxdata); | ||
520 | 479 | ||
521 | } /* end request_key_with_auxdata() */ | 480 | /* |
481 | * request a key (allow async construction) | ||
482 | * - search the process's keyrings | ||
483 | * - check the list of keys being created or updated | ||
484 | * - call out to userspace for a key if supplementary info was provided | ||
485 | */ | ||
486 | struct key *request_key_async(struct key_type *type, | ||
487 | const char *description, | ||
488 | const char *callout_info) | ||
489 | { | ||
490 | return request_key_and_link(type, description, callout_info, NULL, | ||
491 | NULL, KEY_ALLOC_IN_QUOTA); | ||
492 | } | ||
493 | EXPORT_SYMBOL(request_key_async); | ||
522 | 494 | ||
523 | EXPORT_SYMBOL(request_key_with_auxdata); | 495 | /* |
496 | * request a key with auxiliary data for the upcaller (allow async construction) | ||
497 | * - search the process's keyrings | ||
498 | * - check the list of keys being created or updated | ||
499 | * - call out to userspace for a key if supplementary info was provided | ||
500 | */ | ||
501 | struct key *request_key_async_with_auxdata(struct key_type *type, | ||
502 | const char *description, | ||
503 | const char *callout_info, | ||
504 | void *aux) | ||
505 | { | ||
506 | return request_key_and_link(type, description, callout_info, aux, | ||
507 | NULL, KEY_ALLOC_IN_QUOTA); | ||
508 | } | ||
509 | EXPORT_SYMBOL(request_key_async_with_auxdata); | ||
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index cbf58a91b00..510f7be73a2 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -127,6 +127,7 @@ static void request_key_auth_destroy(struct key *key) | |||
127 | } | 127 | } |
128 | 128 | ||
129 | key_put(rka->target_key); | 129 | key_put(rka->target_key); |
130 | kfree(rka->callout_info); | ||
130 | kfree(rka); | 131 | kfree(rka); |
131 | 132 | ||
132 | } /* end request_key_auth_destroy() */ | 133 | } /* end request_key_auth_destroy() */ |
@@ -151,6 +152,12 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) | |||
151 | kleave(" = -ENOMEM"); | 152 | kleave(" = -ENOMEM"); |
152 | return ERR_PTR(-ENOMEM); | 153 | return ERR_PTR(-ENOMEM); |
153 | } | 154 | } |
155 | rka->callout_info = kmalloc(strlen(callout_info) + 1, GFP_KERNEL); | ||
156 | if (!rka->callout_info) { | ||
157 | kleave(" = -ENOMEM"); | ||
158 | kfree(rka); | ||
159 | return ERR_PTR(-ENOMEM); | ||
160 | } | ||
154 | 161 | ||
155 | /* see if the calling process is already servicing the key request of | 162 | /* see if the calling process is already servicing the key request of |
156 | * another process */ | 163 | * another process */ |
@@ -179,7 +186,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) | |||
179 | } | 186 | } |
180 | 187 | ||
181 | rka->target_key = key_get(target); | 188 | rka->target_key = key_get(target); |
182 | rka->callout_info = callout_info; | 189 | strcpy(rka->callout_info, callout_info); |
183 | 190 | ||
184 | /* allocate the auth key */ | 191 | /* allocate the auth key */ |
185 | sprintf(desc, "%x", target->serial); | 192 | sprintf(desc, "%x", target->serial); |
@@ -203,6 +210,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) | |||
203 | 210 | ||
204 | auth_key_revoked: | 211 | auth_key_revoked: |
205 | up_read(¤t->request_key_auth->sem); | 212 | up_read(¤t->request_key_auth->sem); |
213 | kfree(rka->callout_info); | ||
206 | kfree(rka); | 214 | kfree(rka); |
207 | kleave("= -EKEYREVOKED"); | 215 | kleave("= -EKEYREVOKED"); |
208 | return ERR_PTR(-EKEYREVOKED); | 216 | return ERR_PTR(-EKEYREVOKED); |
@@ -212,6 +220,7 @@ error_inst: | |||
212 | key_put(authkey); | 220 | key_put(authkey); |
213 | error_alloc: | 221 | error_alloc: |
214 | key_put(rka->target_key); | 222 | key_put(rka->target_key); |
223 | kfree(rka->callout_info); | ||
215 | kfree(rka); | 224 | kfree(rka); |
216 | kleave("= %d", ret); | 225 | kleave("= %d", ret); |
217 | return ERR_PTR(ret); | 226 | return ERR_PTR(ret); |