diff options
author | James Morris <james.l.morris@oracle.com> | 2012-10-02 23:00:17 -0400 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2012-10-02 23:00:17 -0400 |
commit | 61d335dd27c67d656f114c091a46cf95cbeeb77c (patch) | |
tree | 1e96f07fe903f992e1e2095f1a03b61243da59f0 | |
parent | 87b526d349b04c31d7b3a40b434eb3f825d22305 (diff) | |
parent | 4442d7704c7311d1c42383d365e0b883e0075975 (diff) |
Merge branch 'security-next-keys' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/security-keys into next-queue
As requested by David.
-rw-r--r-- | Documentation/security/keys.txt | 67 | ||||
-rw-r--r-- | fs/cifs/cifs_spnego.c | 6 | ||||
-rw-r--r-- | fs/cifs/cifsacl.c | 20 | ||||
-rw-r--r-- | fs/nfs/idmap.c | 12 | ||||
-rw-r--r-- | include/keys/user-type.h | 6 | ||||
-rw-r--r-- | include/linux/cred.h | 17 | ||||
-rw-r--r-- | include/linux/key-type.h | 35 | ||||
-rw-r--r-- | include/linux/key.h | 1 | ||||
-rw-r--r-- | kernel/cred.c | 127 | ||||
-rw-r--r-- | net/ceph/crypto.c | 9 | ||||
-rw-r--r-- | net/dns_resolver/dns_key.c | 19 | ||||
-rw-r--r-- | net/rxrpc/ar-key.c | 40 | ||||
-rw-r--r-- | security/keys/encrypted-keys/encrypted.c | 16 | ||||
-rw-r--r-- | security/keys/key.c | 120 | ||||
-rw-r--r-- | security/keys/keyctl.c | 33 | ||||
-rw-r--r-- | security/keys/keyring.c | 16 | ||||
-rw-r--r-- | security/keys/process_keys.c | 94 | ||||
-rw-r--r-- | security/keys/request_key.c | 21 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 8 | ||||
-rw-r--r-- | security/keys/trusted.c | 16 | ||||
-rw-r--r-- | security/keys/user_defined.c | 14 |
21 files changed, 367 insertions, 330 deletions
diff --git a/Documentation/security/keys.txt b/Documentation/security/keys.txt index aa0dbd74b71b..7b4145d00452 100644 --- a/Documentation/security/keys.txt +++ b/Documentation/security/keys.txt | |||
@@ -412,6 +412,10 @@ The main syscalls are: | |||
412 | to the keyring. In this case, an error will be generated if the process | 412 | to the keyring. In this case, an error will be generated if the process |
413 | does not have permission to write to the keyring. | 413 | does not have permission to write to the keyring. |
414 | 414 | ||
415 | If the key type supports it, if the description is NULL or an empty | ||
416 | string, the key type will try and generate a description from the content | ||
417 | of the payload. | ||
418 | |||
415 | The payload is optional, and the pointer can be NULL if not required by | 419 | The payload is optional, and the pointer can be NULL if not required by |
416 | the type. The payload is plen in size, and plen can be zero for an empty | 420 | the type. The payload is plen in size, and plen can be zero for an empty |
417 | payload. | 421 | payload. |
@@ -990,6 +994,23 @@ payload contents" for more information. | |||
990 | reference pointer if successful. | 994 | reference pointer if successful. |
991 | 995 | ||
992 | 996 | ||
997 | (*) A keyring can be created by: | ||
998 | |||
999 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | ||
1000 | const struct cred *cred, | ||
1001 | key_perm_t perm, | ||
1002 | unsigned long flags, | ||
1003 | struct key *dest); | ||
1004 | |||
1005 | This creates a keyring with the given attributes and returns it. If dest | ||
1006 | is not NULL, the new keyring will be linked into the keyring to which it | ||
1007 | points. No permission checks are made upon the destination keyring. | ||
1008 | |||
1009 | Error EDQUOT can be returned if the keyring would overload the quota (pass | ||
1010 | KEY_ALLOC_NOT_IN_QUOTA in flags if the keyring shouldn't be accounted | ||
1011 | towards the user's quota). Error ENOMEM can also be returned. | ||
1012 | |||
1013 | |||
993 | (*) To check the validity of a key, this function can be called: | 1014 | (*) To check the validity of a key, this function can be called: |
994 | 1015 | ||
995 | int validate_key(struct key *key); | 1016 | int validate_key(struct key *key); |
@@ -1114,12 +1135,53 @@ The structure has a number of fields, some of which are mandatory: | |||
1114 | it should return 0. | 1135 | it should return 0. |
1115 | 1136 | ||
1116 | 1137 | ||
1117 | (*) int (*instantiate)(struct key *key, const void *data, size_t datalen); | 1138 | (*) int (*preparse)(struct key_preparsed_payload *prep); |
1139 | |||
1140 | This optional method permits the key type to attempt to parse payload | ||
1141 | before a key is created (add key) or the key semaphore is taken (update or | ||
1142 | instantiate key). The structure pointed to by prep looks like: | ||
1143 | |||
1144 | struct key_preparsed_payload { | ||
1145 | char *description; | ||
1146 | void *type_data[2]; | ||
1147 | void *payload; | ||
1148 | const void *data; | ||
1149 | size_t datalen; | ||
1150 | size_t quotalen; | ||
1151 | }; | ||
1152 | |||
1153 | Before calling the method, the caller will fill in data and datalen with | ||
1154 | the payload blob parameters; quotalen will be filled in with the default | ||
1155 | quota size from the key type and the rest will be cleared. | ||
1156 | |||
1157 | If a description can be proposed from the payload contents, that should be | ||
1158 | attached as a string to the description field. This will be used for the | ||
1159 | key description if the caller of add_key() passes NULL or "". | ||
1160 | |||
1161 | The method can attach anything it likes to type_data[] and payload. These | ||
1162 | are merely passed along to the instantiate() or update() operations. | ||
1163 | |||
1164 | The method should return 0 if success ful or a negative error code | ||
1165 | otherwise. | ||
1166 | |||
1167 | |||
1168 | (*) void (*free_preparse)(struct key_preparsed_payload *prep); | ||
1169 | |||
1170 | This method is only required if the preparse() method is provided, | ||
1171 | otherwise it is unused. It cleans up anything attached to the | ||
1172 | description, type_data and payload fields of the key_preparsed_payload | ||
1173 | struct as filled in by the preparse() method. | ||
1174 | |||
1175 | |||
1176 | (*) int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); | ||
1118 | 1177 | ||
1119 | This method is called to attach a payload to a key during construction. | 1178 | This method is called to attach a payload to a key during construction. |
1120 | The payload attached need not bear any relation to the data passed to this | 1179 | The payload attached need not bear any relation to the data passed to this |
1121 | function. | 1180 | function. |
1122 | 1181 | ||
1182 | The prep->data and prep->datalen fields will define the original payload | ||
1183 | blob. If preparse() was supplied then other fields may be filled in also. | ||
1184 | |||
1123 | If the amount of data attached to the key differs from the size in | 1185 | If the amount of data attached to the key differs from the size in |
1124 | keytype->def_datalen, then key_payload_reserve() should be called. | 1186 | keytype->def_datalen, then key_payload_reserve() should be called. |
1125 | 1187 | ||
@@ -1135,6 +1197,9 @@ The structure has a number of fields, some of which are mandatory: | |||
1135 | If this type of key can be updated, then this method should be provided. | 1197 | If this type of key can be updated, then this method should be provided. |
1136 | It is called to update a key's payload from the blob of data provided. | 1198 | It is called to update a key's payload from the blob of data provided. |
1137 | 1199 | ||
1200 | The prep->data and prep->datalen fields will define the original payload | ||
1201 | blob. If preparse() was supplied then other fields may be filled in also. | ||
1202 | |||
1138 | key_payload_reserve() should be called if the data length might change | 1203 | key_payload_reserve() should be called if the data length might change |
1139 | before any changes are actually made. Note that if this succeeds, the type | 1204 | before any changes are actually made. Note that if this succeeds, the type |
1140 | is committed to changing the key because it's already been altered, so all | 1205 | is committed to changing the key because it's already been altered, so all |
diff --git a/fs/cifs/cifs_spnego.c b/fs/cifs/cifs_spnego.c index e622863b292f..086f381d6489 100644 --- a/fs/cifs/cifs_spnego.c +++ b/fs/cifs/cifs_spnego.c | |||
@@ -31,18 +31,18 @@ | |||
31 | 31 | ||
32 | /* create a new cifs key */ | 32 | /* create a new cifs key */ |
33 | static int | 33 | static int |
34 | cifs_spnego_key_instantiate(struct key *key, const void *data, size_t datalen) | 34 | cifs_spnego_key_instantiate(struct key *key, struct key_preparsed_payload *prep) |
35 | { | 35 | { |
36 | char *payload; | 36 | char *payload; |
37 | int ret; | 37 | int ret; |
38 | 38 | ||
39 | ret = -ENOMEM; | 39 | ret = -ENOMEM; |
40 | payload = kmalloc(datalen, GFP_KERNEL); | 40 | payload = kmalloc(prep->datalen, GFP_KERNEL); |
41 | if (!payload) | 41 | if (!payload) |
42 | goto error; | 42 | goto error; |
43 | 43 | ||
44 | /* attach the data */ | 44 | /* attach the data */ |
45 | memcpy(payload, data, datalen); | 45 | memcpy(payload, prep->data, prep->datalen); |
46 | key->payload.data = payload; | 46 | key->payload.data = payload; |
47 | ret = 0; | 47 | ret = 0; |
48 | 48 | ||
diff --git a/fs/cifs/cifsacl.c b/fs/cifs/cifsacl.c index 05f4dc263a23..3151a264988e 100644 --- a/fs/cifs/cifsacl.c +++ b/fs/cifs/cifsacl.c | |||
@@ -167,17 +167,17 @@ static struct shrinker cifs_shrinker = { | |||
167 | }; | 167 | }; |
168 | 168 | ||
169 | static int | 169 | static int |
170 | cifs_idmap_key_instantiate(struct key *key, const void *data, size_t datalen) | 170 | cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep) |
171 | { | 171 | { |
172 | char *payload; | 172 | char *payload; |
173 | 173 | ||
174 | payload = kmalloc(datalen, GFP_KERNEL); | 174 | payload = kmalloc(prep->datalen, GFP_KERNEL); |
175 | if (!payload) | 175 | if (!payload) |
176 | return -ENOMEM; | 176 | return -ENOMEM; |
177 | 177 | ||
178 | memcpy(payload, data, datalen); | 178 | memcpy(payload, prep->data, prep->datalen); |
179 | key->payload.data = payload; | 179 | key->payload.data = payload; |
180 | key->datalen = datalen; | 180 | key->datalen = prep->datalen; |
181 | return 0; | 181 | return 0; |
182 | } | 182 | } |
183 | 183 | ||
@@ -537,19 +537,15 @@ init_cifs_idmap(void) | |||
537 | if (!cred) | 537 | if (!cred) |
538 | return -ENOMEM; | 538 | return -ENOMEM; |
539 | 539 | ||
540 | keyring = key_alloc(&key_type_keyring, ".cifs_idmap", 0, 0, cred, | 540 | keyring = keyring_alloc(".cifs_idmap", 0, 0, cred, |
541 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | 541 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | |
542 | KEY_USR_VIEW | KEY_USR_READ, | 542 | KEY_USR_VIEW | KEY_USR_READ, |
543 | KEY_ALLOC_NOT_IN_QUOTA); | 543 | KEY_ALLOC_NOT_IN_QUOTA, NULL); |
544 | if (IS_ERR(keyring)) { | 544 | if (IS_ERR(keyring)) { |
545 | ret = PTR_ERR(keyring); | 545 | ret = PTR_ERR(keyring); |
546 | goto failed_put_cred; | 546 | goto failed_put_cred; |
547 | } | 547 | } |
548 | 548 | ||
549 | ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL); | ||
550 | if (ret < 0) | ||
551 | goto failed_put_key; | ||
552 | |||
553 | ret = register_key_type(&cifs_idmap_key_type); | 549 | ret = register_key_type(&cifs_idmap_key_type); |
554 | if (ret < 0) | 550 | if (ret < 0) |
555 | goto failed_put_key; | 551 | goto failed_put_key; |
diff --git a/fs/nfs/idmap.c b/fs/nfs/idmap.c index a850079467d8..957134b4c0fd 100644 --- a/fs/nfs/idmap.c +++ b/fs/nfs/idmap.c | |||
@@ -192,19 +192,15 @@ static int nfs_idmap_init_keyring(void) | |||
192 | if (!cred) | 192 | if (!cred) |
193 | return -ENOMEM; | 193 | return -ENOMEM; |
194 | 194 | ||
195 | keyring = key_alloc(&key_type_keyring, ".id_resolver", 0, 0, cred, | 195 | keyring = keyring_alloc(".id_resolver", 0, 0, cred, |
196 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | 196 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | |
197 | KEY_USR_VIEW | KEY_USR_READ, | 197 | KEY_USR_VIEW | KEY_USR_READ, |
198 | KEY_ALLOC_NOT_IN_QUOTA); | 198 | KEY_ALLOC_NOT_IN_QUOTA, NULL); |
199 | if (IS_ERR(keyring)) { | 199 | if (IS_ERR(keyring)) { |
200 | ret = PTR_ERR(keyring); | 200 | ret = PTR_ERR(keyring); |
201 | goto failed_put_cred; | 201 | goto failed_put_cred; |
202 | } | 202 | } |
203 | 203 | ||
204 | ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL); | ||
205 | if (ret < 0) | ||
206 | goto failed_put_key; | ||
207 | |||
208 | ret = register_key_type(&key_type_id_resolver); | 204 | ret = register_key_type(&key_type_id_resolver); |
209 | if (ret < 0) | 205 | if (ret < 0) |
210 | goto failed_put_key; | 206 | goto failed_put_key; |
diff --git a/include/keys/user-type.h b/include/keys/user-type.h index bc9ec1d7698c..5e452c84f1e6 100644 --- a/include/keys/user-type.h +++ b/include/keys/user-type.h | |||
@@ -35,8 +35,10 @@ struct user_key_payload { | |||
35 | extern struct key_type key_type_user; | 35 | extern struct key_type key_type_user; |
36 | extern struct key_type key_type_logon; | 36 | extern struct key_type key_type_logon; |
37 | 37 | ||
38 | extern int user_instantiate(struct key *key, const void *data, size_t datalen); | 38 | struct key_preparsed_payload; |
39 | extern int user_update(struct key *key, const void *data, size_t datalen); | 39 | |
40 | extern int user_instantiate(struct key *key, struct key_preparsed_payload *prep); | ||
41 | extern int user_update(struct key *key, struct key_preparsed_payload *prep); | ||
40 | extern int user_match(const struct key *key, const void *criterion); | 42 | extern int user_match(const struct key *key, const void *criterion); |
41 | extern void user_revoke(struct key *key); | 43 | extern void user_revoke(struct key *key); |
42 | extern void user_destroy(struct key *key); | 44 | extern void user_destroy(struct key *key); |
diff --git a/include/linux/cred.h b/include/linux/cred.h index ebbed2ce6637..0142aacb70b7 100644 --- a/include/linux/cred.h +++ b/include/linux/cred.h | |||
@@ -77,21 +77,6 @@ extern int in_group_p(kgid_t); | |||
77 | extern int in_egroup_p(kgid_t); | 77 | extern int in_egroup_p(kgid_t); |
78 | 78 | ||
79 | /* | 79 | /* |
80 | * The common credentials for a thread group | ||
81 | * - shared by CLONE_THREAD | ||
82 | */ | ||
83 | #ifdef CONFIG_KEYS | ||
84 | struct thread_group_cred { | ||
85 | atomic_t usage; | ||
86 | pid_t tgid; /* thread group process ID */ | ||
87 | spinlock_t lock; | ||
88 | struct key __rcu *session_keyring; /* keyring inherited over fork */ | ||
89 | struct key *process_keyring; /* keyring private to this process */ | ||
90 | struct rcu_head rcu; /* RCU deletion hook */ | ||
91 | }; | ||
92 | #endif | ||
93 | |||
94 | /* | ||
95 | * The security context of a task | 80 | * The security context of a task |
96 | * | 81 | * |
97 | * The parts of the context break down into two categories: | 82 | * The parts of the context break down into two categories: |
@@ -139,6 +124,8 @@ struct cred { | |||
139 | #ifdef CONFIG_KEYS | 124 | #ifdef CONFIG_KEYS |
140 | unsigned char jit_keyring; /* default keyring to attach requested | 125 | unsigned char jit_keyring; /* default keyring to attach requested |
141 | * keys to */ | 126 | * keys to */ |
127 | struct key __rcu *session_keyring; /* keyring inherited over fork */ | ||
128 | struct key *process_keyring; /* keyring private to this process */ | ||
142 | struct key *thread_keyring; /* keyring private to this thread */ | 129 | struct key *thread_keyring; /* keyring private to this thread */ |
143 | struct key *request_key_auth; /* assumed request_key authority */ | 130 | struct key *request_key_auth; /* assumed request_key authority */ |
144 | struct thread_group_cred *tgcred; /* thread-group shared credentials */ | 131 | struct thread_group_cred *tgcred; /* thread-group shared credentials */ |
diff --git a/include/linux/key-type.h b/include/linux/key-type.h index f0c651cda7b0..518a53afb9ea 100644 --- a/include/linux/key-type.h +++ b/include/linux/key-type.h | |||
@@ -26,6 +26,27 @@ struct key_construction { | |||
26 | struct key *authkey;/* authorisation for key being constructed */ | 26 | struct key *authkey;/* authorisation for key being constructed */ |
27 | }; | 27 | }; |
28 | 28 | ||
29 | /* | ||
30 | * Pre-parsed payload, used by key add, update and instantiate. | ||
31 | * | ||
32 | * This struct will be cleared and data and datalen will be set with the data | ||
33 | * and length parameters from the caller and quotalen will be set from | ||
34 | * def_datalen from the key type. Then if the preparse() op is provided by the | ||
35 | * key type, that will be called. Then the struct will be passed to the | ||
36 | * instantiate() or the update() op. | ||
37 | * | ||
38 | * If the preparse() op is given, the free_preparse() op will be called to | ||
39 | * clear the contents. | ||
40 | */ | ||
41 | struct key_preparsed_payload { | ||
42 | char *description; /* Proposed key description (or NULL) */ | ||
43 | void *type_data[2]; /* Private key-type data */ | ||
44 | void *payload; /* Proposed payload */ | ||
45 | const void *data; /* Raw data */ | ||
46 | size_t datalen; /* Raw datalen */ | ||
47 | size_t quotalen; /* Quota length for proposed payload */ | ||
48 | }; | ||
49 | |||
29 | typedef int (*request_key_actor_t)(struct key_construction *key, | 50 | typedef int (*request_key_actor_t)(struct key_construction *key, |
30 | const char *op, void *aux); | 51 | const char *op, void *aux); |
31 | 52 | ||
@@ -45,18 +66,28 @@ struct key_type { | |||
45 | /* vet a description */ | 66 | /* vet a description */ |
46 | int (*vet_description)(const char *description); | 67 | int (*vet_description)(const char *description); |
47 | 68 | ||
69 | /* Preparse the data blob from userspace that is to be the payload, | ||
70 | * generating a proposed description and payload that will be handed to | ||
71 | * the instantiate() and update() ops. | ||
72 | */ | ||
73 | int (*preparse)(struct key_preparsed_payload *prep); | ||
74 | |||
75 | /* Free a preparse data structure. | ||
76 | */ | ||
77 | void (*free_preparse)(struct key_preparsed_payload *prep); | ||
78 | |||
48 | /* instantiate a key of this type | 79 | /* instantiate a key of this type |
49 | * - this method should call key_payload_reserve() to determine if the | 80 | * - this method should call key_payload_reserve() to determine if the |
50 | * user's quota will hold the payload | 81 | * user's quota will hold the payload |
51 | */ | 82 | */ |
52 | int (*instantiate)(struct key *key, const void *data, size_t datalen); | 83 | int (*instantiate)(struct key *key, struct key_preparsed_payload *prep); |
53 | 84 | ||
54 | /* update a key of this type (optional) | 85 | /* update a key of this type (optional) |
55 | * - this method should call key_payload_reserve() to recalculate the | 86 | * - this method should call key_payload_reserve() to recalculate the |
56 | * quota consumption | 87 | * quota consumption |
57 | * - the key must be locked against read when modifying | 88 | * - the key must be locked against read when modifying |
58 | */ | 89 | */ |
59 | int (*update)(struct key *key, const void *data, size_t datalen); | 90 | int (*update)(struct key *key, struct key_preparsed_payload *prep); |
60 | 91 | ||
61 | /* match a key against a description */ | 92 | /* match a key against a description */ |
62 | int (*match)(const struct key *key, const void *desc); | 93 | int (*match)(const struct key *key, const void *desc); |
diff --git a/include/linux/key.h b/include/linux/key.h index cef3b315ba7c..890699815212 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -264,6 +264,7 @@ extern int key_unlink(struct key *keyring, | |||
264 | 264 | ||
265 | extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | 265 | extern struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, |
266 | const struct cred *cred, | 266 | const struct cred *cred, |
267 | key_perm_t perm, | ||
267 | unsigned long flags, | 268 | unsigned long flags, |
268 | struct key *dest); | 269 | struct key *dest); |
269 | 270 | ||
diff --git a/kernel/cred.c b/kernel/cred.c index de728ac50d82..3f7ad1ec2ae4 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
@@ -30,17 +30,6 @@ | |||
30 | static struct kmem_cache *cred_jar; | 30 | static struct kmem_cache *cred_jar; |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * The common credentials for the initial task's thread group | ||
34 | */ | ||
35 | #ifdef CONFIG_KEYS | ||
36 | static struct thread_group_cred init_tgcred = { | ||
37 | .usage = ATOMIC_INIT(2), | ||
38 | .tgid = 0, | ||
39 | .lock = __SPIN_LOCK_UNLOCKED(init_cred.tgcred.lock), | ||
40 | }; | ||
41 | #endif | ||
42 | |||
43 | /* | ||
44 | * The initial credentials for the initial task | 33 | * The initial credentials for the initial task |
45 | */ | 34 | */ |
46 | struct cred init_cred = { | 35 | struct cred init_cred = { |
@@ -65,9 +54,6 @@ struct cred init_cred = { | |||
65 | .user = INIT_USER, | 54 | .user = INIT_USER, |
66 | .user_ns = &init_user_ns, | 55 | .user_ns = &init_user_ns, |
67 | .group_info = &init_groups, | 56 | .group_info = &init_groups, |
68 | #ifdef CONFIG_KEYS | ||
69 | .tgcred = &init_tgcred, | ||
70 | #endif | ||
71 | }; | 57 | }; |
72 | 58 | ||
73 | static inline void set_cred_subscribers(struct cred *cred, int n) | 59 | static inline void set_cred_subscribers(struct cred *cred, int n) |
@@ -96,36 +82,6 @@ static inline void alter_cred_subscribers(const struct cred *_cred, int n) | |||
96 | } | 82 | } |
97 | 83 | ||
98 | /* | 84 | /* |
99 | * Dispose of the shared task group credentials | ||
100 | */ | ||
101 | #ifdef CONFIG_KEYS | ||
102 | static void release_tgcred_rcu(struct rcu_head *rcu) | ||
103 | { | ||
104 | struct thread_group_cred *tgcred = | ||
105 | container_of(rcu, struct thread_group_cred, rcu); | ||
106 | |||
107 | BUG_ON(atomic_read(&tgcred->usage) != 0); | ||
108 | |||
109 | key_put(tgcred->session_keyring); | ||
110 | key_put(tgcred->process_keyring); | ||
111 | kfree(tgcred); | ||
112 | } | ||
113 | #endif | ||
114 | |||
115 | /* | ||
116 | * Release a set of thread group credentials. | ||
117 | */ | ||
118 | static void release_tgcred(struct cred *cred) | ||
119 | { | ||
120 | #ifdef CONFIG_KEYS | ||
121 | struct thread_group_cred *tgcred = cred->tgcred; | ||
122 | |||
123 | if (atomic_dec_and_test(&tgcred->usage)) | ||
124 | call_rcu(&tgcred->rcu, release_tgcred_rcu); | ||
125 | #endif | ||
126 | } | ||
127 | |||
128 | /* | ||
129 | * The RCU callback to actually dispose of a set of credentials | 85 | * The RCU callback to actually dispose of a set of credentials |
130 | */ | 86 | */ |
131 | static void put_cred_rcu(struct rcu_head *rcu) | 87 | static void put_cred_rcu(struct rcu_head *rcu) |
@@ -150,9 +106,10 @@ static void put_cred_rcu(struct rcu_head *rcu) | |||
150 | #endif | 106 | #endif |
151 | 107 | ||
152 | security_cred_free(cred); | 108 | security_cred_free(cred); |
109 | key_put(cred->session_keyring); | ||
110 | key_put(cred->process_keyring); | ||
153 | key_put(cred->thread_keyring); | 111 | key_put(cred->thread_keyring); |
154 | key_put(cred->request_key_auth); | 112 | key_put(cred->request_key_auth); |
155 | release_tgcred(cred); | ||
156 | if (cred->group_info) | 113 | if (cred->group_info) |
157 | put_group_info(cred->group_info); | 114 | put_group_info(cred->group_info); |
158 | free_uid(cred->user); | 115 | free_uid(cred->user); |
@@ -246,15 +203,6 @@ struct cred *cred_alloc_blank(void) | |||
246 | if (!new) | 203 | if (!new) |
247 | return NULL; | 204 | return NULL; |
248 | 205 | ||
249 | #ifdef CONFIG_KEYS | ||
250 | new->tgcred = kzalloc(sizeof(*new->tgcred), GFP_KERNEL); | ||
251 | if (!new->tgcred) { | ||
252 | kmem_cache_free(cred_jar, new); | ||
253 | return NULL; | ||
254 | } | ||
255 | atomic_set(&new->tgcred->usage, 1); | ||
256 | #endif | ||
257 | |||
258 | atomic_set(&new->usage, 1); | 206 | atomic_set(&new->usage, 1); |
259 | #ifdef CONFIG_DEBUG_CREDENTIALS | 207 | #ifdef CONFIG_DEBUG_CREDENTIALS |
260 | new->magic = CRED_MAGIC; | 208 | new->magic = CRED_MAGIC; |
@@ -308,9 +256,10 @@ struct cred *prepare_creds(void) | |||
308 | get_user_ns(new->user_ns); | 256 | get_user_ns(new->user_ns); |
309 | 257 | ||
310 | #ifdef CONFIG_KEYS | 258 | #ifdef CONFIG_KEYS |
259 | key_get(new->session_keyring); | ||
260 | key_get(new->process_keyring); | ||
311 | key_get(new->thread_keyring); | 261 | key_get(new->thread_keyring); |
312 | key_get(new->request_key_auth); | 262 | key_get(new->request_key_auth); |
313 | atomic_inc(&new->tgcred->usage); | ||
314 | #endif | 263 | #endif |
315 | 264 | ||
316 | #ifdef CONFIG_SECURITY | 265 | #ifdef CONFIG_SECURITY |
@@ -334,39 +283,20 @@ EXPORT_SYMBOL(prepare_creds); | |||
334 | */ | 283 | */ |
335 | struct cred *prepare_exec_creds(void) | 284 | struct cred *prepare_exec_creds(void) |
336 | { | 285 | { |
337 | struct thread_group_cred *tgcred = NULL; | ||
338 | struct cred *new; | 286 | struct cred *new; |
339 | 287 | ||
340 | #ifdef CONFIG_KEYS | ||
341 | tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL); | ||
342 | if (!tgcred) | ||
343 | return NULL; | ||
344 | #endif | ||
345 | |||
346 | new = prepare_creds(); | 288 | new = prepare_creds(); |
347 | if (!new) { | 289 | if (!new) |
348 | kfree(tgcred); | ||
349 | return new; | 290 | return new; |
350 | } | ||
351 | 291 | ||
352 | #ifdef CONFIG_KEYS | 292 | #ifdef CONFIG_KEYS |
353 | /* newly exec'd tasks don't get a thread keyring */ | 293 | /* newly exec'd tasks don't get a thread keyring */ |
354 | key_put(new->thread_keyring); | 294 | key_put(new->thread_keyring); |
355 | new->thread_keyring = NULL; | 295 | new->thread_keyring = NULL; |
356 | 296 | ||
357 | /* create a new per-thread-group creds for all this set of threads to | ||
358 | * share */ | ||
359 | memcpy(tgcred, new->tgcred, sizeof(struct thread_group_cred)); | ||
360 | |||
361 | atomic_set(&tgcred->usage, 1); | ||
362 | spin_lock_init(&tgcred->lock); | ||
363 | |||
364 | /* inherit the session keyring; new process keyring */ | 297 | /* inherit the session keyring; new process keyring */ |
365 | key_get(tgcred->session_keyring); | 298 | key_put(new->process_keyring); |
366 | tgcred->process_keyring = NULL; | 299 | new->process_keyring = NULL; |
367 | |||
368 | release_tgcred(new); | ||
369 | new->tgcred = tgcred; | ||
370 | #endif | 300 | #endif |
371 | 301 | ||
372 | return new; | 302 | return new; |
@@ -383,9 +313,6 @@ struct cred *prepare_exec_creds(void) | |||
383 | */ | 313 | */ |
384 | int copy_creds(struct task_struct *p, unsigned long clone_flags) | 314 | int copy_creds(struct task_struct *p, unsigned long clone_flags) |
385 | { | 315 | { |
386 | #ifdef CONFIG_KEYS | ||
387 | struct thread_group_cred *tgcred; | ||
388 | #endif | ||
389 | struct cred *new; | 316 | struct cred *new; |
390 | int ret; | 317 | int ret; |
391 | 318 | ||
@@ -425,22 +352,12 @@ int copy_creds(struct task_struct *p, unsigned long clone_flags) | |||
425 | install_thread_keyring_to_cred(new); | 352 | install_thread_keyring_to_cred(new); |
426 | } | 353 | } |
427 | 354 | ||
428 | /* we share the process and session keyrings between all the threads in | 355 | /* The process keyring is only shared between the threads in a process; |
429 | * a process - this is slightly icky as we violate COW credentials a | 356 | * anything outside of those threads doesn't inherit. |
430 | * bit */ | 357 | */ |
431 | if (!(clone_flags & CLONE_THREAD)) { | 358 | if (!(clone_flags & CLONE_THREAD)) { |
432 | tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL); | 359 | key_put(new->process_keyring); |
433 | if (!tgcred) { | 360 | new->process_keyring = NULL; |
434 | ret = -ENOMEM; | ||
435 | goto error_put; | ||
436 | } | ||
437 | atomic_set(&tgcred->usage, 1); | ||
438 | spin_lock_init(&tgcred->lock); | ||
439 | tgcred->process_keyring = NULL; | ||
440 | tgcred->session_keyring = key_get(new->tgcred->session_keyring); | ||
441 | |||
442 | release_tgcred(new); | ||
443 | new->tgcred = tgcred; | ||
444 | } | 361 | } |
445 | #endif | 362 | #endif |
446 | 363 | ||
@@ -643,9 +560,6 @@ void __init cred_init(void) | |||
643 | */ | 560 | */ |
644 | struct cred *prepare_kernel_cred(struct task_struct *daemon) | 561 | struct cred *prepare_kernel_cred(struct task_struct *daemon) |
645 | { | 562 | { |
646 | #ifdef CONFIG_KEYS | ||
647 | struct thread_group_cred *tgcred; | ||
648 | #endif | ||
649 | const struct cred *old; | 563 | const struct cred *old; |
650 | struct cred *new; | 564 | struct cred *new; |
651 | 565 | ||
@@ -653,14 +567,6 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) | |||
653 | if (!new) | 567 | if (!new) |
654 | return NULL; | 568 | return NULL; |
655 | 569 | ||
656 | #ifdef CONFIG_KEYS | ||
657 | tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL); | ||
658 | if (!tgcred) { | ||
659 | kmem_cache_free(cred_jar, new); | ||
660 | return NULL; | ||
661 | } | ||
662 | #endif | ||
663 | |||
664 | kdebug("prepare_kernel_cred() alloc %p", new); | 570 | kdebug("prepare_kernel_cred() alloc %p", new); |
665 | 571 | ||
666 | if (daemon) | 572 | if (daemon) |
@@ -678,13 +584,10 @@ struct cred *prepare_kernel_cred(struct task_struct *daemon) | |||
678 | get_group_info(new->group_info); | 584 | get_group_info(new->group_info); |
679 | 585 | ||
680 | #ifdef CONFIG_KEYS | 586 | #ifdef CONFIG_KEYS |
681 | atomic_set(&tgcred->usage, 1); | 587 | new->session_keyring = NULL; |
682 | spin_lock_init(&tgcred->lock); | 588 | new->process_keyring = NULL; |
683 | tgcred->process_keyring = NULL; | ||
684 | tgcred->session_keyring = NULL; | ||
685 | new->tgcred = tgcred; | ||
686 | new->request_key_auth = NULL; | ||
687 | new->thread_keyring = NULL; | 589 | new->thread_keyring = NULL; |
590 | new->request_key_auth = NULL; | ||
688 | new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; | 591 | new->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; |
689 | #endif | 592 | #endif |
690 | 593 | ||
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index 9da7fdd3cd8a..af14cb425164 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c | |||
@@ -423,14 +423,15 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, | |||
423 | } | 423 | } |
424 | } | 424 | } |
425 | 425 | ||
426 | int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) | 426 | int ceph_key_instantiate(struct key *key, struct key_preparsed_payload *prep) |
427 | { | 427 | { |
428 | struct ceph_crypto_key *ckey; | 428 | struct ceph_crypto_key *ckey; |
429 | size_t datalen = prep->datalen; | ||
429 | int ret; | 430 | int ret; |
430 | void *p; | 431 | void *p; |
431 | 432 | ||
432 | ret = -EINVAL; | 433 | ret = -EINVAL; |
433 | if (datalen <= 0 || datalen > 32767 || !data) | 434 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
434 | goto err; | 435 | goto err; |
435 | 436 | ||
436 | ret = key_payload_reserve(key, datalen); | 437 | ret = key_payload_reserve(key, datalen); |
@@ -443,8 +444,8 @@ int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) | |||
443 | goto err; | 444 | goto err; |
444 | 445 | ||
445 | /* TODO ceph_crypto_key_decode should really take const input */ | 446 | /* TODO ceph_crypto_key_decode should really take const input */ |
446 | p = (void *)data; | 447 | p = (void *)prep->data; |
447 | ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen); | 448 | ret = ceph_crypto_key_decode(ckey, &p, (char*)prep->data+datalen); |
448 | if (ret < 0) | 449 | if (ret < 0) |
449 | goto err_ckey; | 450 | goto err_ckey; |
450 | 451 | ||
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index d9507dd05818..b53bb4a41daa 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c | |||
@@ -59,13 +59,13 @@ const struct cred *dns_resolver_cache; | |||
59 | * "ip1,ip2,...#foo=bar" | 59 | * "ip1,ip2,...#foo=bar" |
60 | */ | 60 | */ |
61 | static int | 61 | static int |
62 | dns_resolver_instantiate(struct key *key, const void *_data, size_t datalen) | 62 | dns_resolver_instantiate(struct key *key, struct key_preparsed_payload *prep) |
63 | { | 63 | { |
64 | struct user_key_payload *upayload; | 64 | struct user_key_payload *upayload; |
65 | unsigned long derrno; | 65 | unsigned long derrno; |
66 | int ret; | 66 | int ret; |
67 | size_t result_len = 0; | 67 | size_t datalen = prep->datalen, result_len = 0; |
68 | const char *data = _data, *end, *opt; | 68 | const char *data = prep->data, *end, *opt; |
69 | 69 | ||
70 | kenter("%%%d,%s,'%*.*s',%zu", | 70 | kenter("%%%d,%s,'%*.*s',%zu", |
71 | key->serial, key->description, | 71 | key->serial, key->description, |
@@ -259,19 +259,15 @@ static int __init init_dns_resolver(void) | |||
259 | if (!cred) | 259 | if (!cred) |
260 | return -ENOMEM; | 260 | return -ENOMEM; |
261 | 261 | ||
262 | keyring = key_alloc(&key_type_keyring, ".dns_resolver", 0, 0, cred, | 262 | keyring = keyring_alloc(".dns_resolver", 0, 0, cred, |
263 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | | 263 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | |
264 | KEY_USR_VIEW | KEY_USR_READ, | 264 | KEY_USR_VIEW | KEY_USR_READ, |
265 | KEY_ALLOC_NOT_IN_QUOTA); | 265 | KEY_ALLOC_NOT_IN_QUOTA, NULL); |
266 | if (IS_ERR(keyring)) { | 266 | if (IS_ERR(keyring)) { |
267 | ret = PTR_ERR(keyring); | 267 | ret = PTR_ERR(keyring); |
268 | goto failed_put_cred; | 268 | goto failed_put_cred; |
269 | } | 269 | } |
270 | 270 | ||
271 | ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL); | ||
272 | if (ret < 0) | ||
273 | goto failed_put_key; | ||
274 | |||
275 | ret = register_key_type(&key_type_dns_resolver); | 271 | ret = register_key_type(&key_type_dns_resolver); |
276 | if (ret < 0) | 272 | if (ret < 0) |
277 | goto failed_put_key; | 273 | goto failed_put_key; |
@@ -303,3 +299,4 @@ static void __exit exit_dns_resolver(void) | |||
303 | module_init(init_dns_resolver) | 299 | module_init(init_dns_resolver) |
304 | module_exit(exit_dns_resolver) | 300 | module_exit(exit_dns_resolver) |
305 | MODULE_LICENSE("GPL"); | 301 | MODULE_LICENSE("GPL"); |
302 | |||
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 8b1f9f49960f..106c5a6b1ab2 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c | |||
@@ -26,8 +26,8 @@ | |||
26 | #include "ar-internal.h" | 26 | #include "ar-internal.h" |
27 | 27 | ||
28 | static int rxrpc_vet_description_s(const char *); | 28 | static int rxrpc_vet_description_s(const char *); |
29 | static int rxrpc_instantiate(struct key *, const void *, size_t); | 29 | static int rxrpc_instantiate(struct key *, struct key_preparsed_payload *); |
30 | static int rxrpc_instantiate_s(struct key *, const void *, size_t); | 30 | static int rxrpc_instantiate_s(struct key *, struct key_preparsed_payload *); |
31 | static void rxrpc_destroy(struct key *); | 31 | static void rxrpc_destroy(struct key *); |
32 | static void rxrpc_destroy_s(struct key *); | 32 | static void rxrpc_destroy_s(struct key *); |
33 | static void rxrpc_describe(const struct key *, struct seq_file *); | 33 | static void rxrpc_describe(const struct key *, struct seq_file *); |
@@ -678,7 +678,7 @@ error: | |||
678 | * | 678 | * |
679 | * if no data is provided, then a no-security key is made | 679 | * if no data is provided, then a no-security key is made |
680 | */ | 680 | */ |
681 | static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) | 681 | static int rxrpc_instantiate(struct key *key, struct key_preparsed_payload *prep) |
682 | { | 682 | { |
683 | const struct rxrpc_key_data_v1 *v1; | 683 | const struct rxrpc_key_data_v1 *v1; |
684 | struct rxrpc_key_token *token, **pp; | 684 | struct rxrpc_key_token *token, **pp; |
@@ -686,26 +686,26 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) | |||
686 | u32 kver; | 686 | u32 kver; |
687 | int ret; | 687 | int ret; |
688 | 688 | ||
689 | _enter("{%x},,%zu", key_serial(key), datalen); | 689 | _enter("{%x},,%zu", key_serial(key), prep->datalen); |
690 | 690 | ||
691 | /* handle a no-security key */ | 691 | /* handle a no-security key */ |
692 | if (!data && datalen == 0) | 692 | if (!prep->data && prep->datalen == 0) |
693 | return 0; | 693 | return 0; |
694 | 694 | ||
695 | /* determine if the XDR payload format is being used */ | 695 | /* determine if the XDR payload format is being used */ |
696 | if (datalen > 7 * 4) { | 696 | if (prep->datalen > 7 * 4) { |
697 | ret = rxrpc_instantiate_xdr(key, data, datalen); | 697 | ret = rxrpc_instantiate_xdr(key, prep->data, prep->datalen); |
698 | if (ret != -EPROTO) | 698 | if (ret != -EPROTO) |
699 | return ret; | 699 | return ret; |
700 | } | 700 | } |
701 | 701 | ||
702 | /* get the key interface version number */ | 702 | /* get the key interface version number */ |
703 | ret = -EINVAL; | 703 | ret = -EINVAL; |
704 | if (datalen <= 4 || !data) | 704 | if (prep->datalen <= 4 || !prep->data) |
705 | goto error; | 705 | goto error; |
706 | memcpy(&kver, data, sizeof(kver)); | 706 | memcpy(&kver, prep->data, sizeof(kver)); |
707 | data += sizeof(kver); | 707 | prep->data += sizeof(kver); |
708 | datalen -= sizeof(kver); | 708 | prep->datalen -= sizeof(kver); |
709 | 709 | ||
710 | _debug("KEY I/F VERSION: %u", kver); | 710 | _debug("KEY I/F VERSION: %u", kver); |
711 | 711 | ||
@@ -715,11 +715,11 @@ static int rxrpc_instantiate(struct key *key, const void *data, size_t datalen) | |||
715 | 715 | ||
716 | /* deal with a version 1 key */ | 716 | /* deal with a version 1 key */ |
717 | ret = -EINVAL; | 717 | ret = -EINVAL; |
718 | if (datalen < sizeof(*v1)) | 718 | if (prep->datalen < sizeof(*v1)) |
719 | goto error; | 719 | goto error; |
720 | 720 | ||
721 | v1 = data; | 721 | v1 = prep->data; |
722 | if (datalen != sizeof(*v1) + v1->ticket_length) | 722 | if (prep->datalen != sizeof(*v1) + v1->ticket_length) |
723 | goto error; | 723 | goto error; |
724 | 724 | ||
725 | _debug("SCIX: %u", v1->security_index); | 725 | _debug("SCIX: %u", v1->security_index); |
@@ -784,17 +784,17 @@ error: | |||
784 | * instantiate a server secret key | 784 | * instantiate a server secret key |
785 | * data should be a pointer to the 8-byte secret key | 785 | * data should be a pointer to the 8-byte secret key |
786 | */ | 786 | */ |
787 | static int rxrpc_instantiate_s(struct key *key, const void *data, | 787 | static int rxrpc_instantiate_s(struct key *key, |
788 | size_t datalen) | 788 | struct key_preparsed_payload *prep) |
789 | { | 789 | { |
790 | struct crypto_blkcipher *ci; | 790 | struct crypto_blkcipher *ci; |
791 | 791 | ||
792 | _enter("{%x},,%zu", key_serial(key), datalen); | 792 | _enter("{%x},,%zu", key_serial(key), prep->datalen); |
793 | 793 | ||
794 | if (datalen != 8) | 794 | if (prep->datalen != 8) |
795 | return -EINVAL; | 795 | return -EINVAL; |
796 | 796 | ||
797 | memcpy(&key->type_data, data, 8); | 797 | memcpy(&key->type_data, prep->data, 8); |
798 | 798 | ||
799 | ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); | 799 | ci = crypto_alloc_blkcipher("pcbc(des)", 0, CRYPTO_ALG_ASYNC); |
800 | if (IS_ERR(ci)) { | 800 | if (IS_ERR(ci)) { |
@@ -802,7 +802,7 @@ static int rxrpc_instantiate_s(struct key *key, const void *data, | |||
802 | return PTR_ERR(ci); | 802 | return PTR_ERR(ci); |
803 | } | 803 | } |
804 | 804 | ||
805 | if (crypto_blkcipher_setkey(ci, data, 8) < 0) | 805 | if (crypto_blkcipher_setkey(ci, prep->data, 8) < 0) |
806 | BUG(); | 806 | BUG(); |
807 | 807 | ||
808 | key->payload.data = ci; | 808 | key->payload.data = ci; |
diff --git a/security/keys/encrypted-keys/encrypted.c b/security/keys/encrypted-keys/encrypted.c index 2d1bb8af7696..9e1e005c7596 100644 --- a/security/keys/encrypted-keys/encrypted.c +++ b/security/keys/encrypted-keys/encrypted.c | |||
@@ -773,8 +773,8 @@ static int encrypted_init(struct encrypted_key_payload *epayload, | |||
773 | * | 773 | * |
774 | * On success, return 0. Otherwise return errno. | 774 | * On success, return 0. Otherwise return errno. |
775 | */ | 775 | */ |
776 | static int encrypted_instantiate(struct key *key, const void *data, | 776 | static int encrypted_instantiate(struct key *key, |
777 | size_t datalen) | 777 | struct key_preparsed_payload *prep) |
778 | { | 778 | { |
779 | struct encrypted_key_payload *epayload = NULL; | 779 | struct encrypted_key_payload *epayload = NULL; |
780 | char *datablob = NULL; | 780 | char *datablob = NULL; |
@@ -782,16 +782,17 @@ static int encrypted_instantiate(struct key *key, const void *data, | |||
782 | char *master_desc = NULL; | 782 | char *master_desc = NULL; |
783 | char *decrypted_datalen = NULL; | 783 | char *decrypted_datalen = NULL; |
784 | char *hex_encoded_iv = NULL; | 784 | char *hex_encoded_iv = NULL; |
785 | size_t datalen = prep->datalen; | ||
785 | int ret; | 786 | int ret; |
786 | 787 | ||
787 | if (datalen <= 0 || datalen > 32767 || !data) | 788 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
788 | return -EINVAL; | 789 | return -EINVAL; |
789 | 790 | ||
790 | datablob = kmalloc(datalen + 1, GFP_KERNEL); | 791 | datablob = kmalloc(datalen + 1, GFP_KERNEL); |
791 | if (!datablob) | 792 | if (!datablob) |
792 | return -ENOMEM; | 793 | return -ENOMEM; |
793 | datablob[datalen] = 0; | 794 | datablob[datalen] = 0; |
794 | memcpy(datablob, data, datalen); | 795 | memcpy(datablob, prep->data, datalen); |
795 | ret = datablob_parse(datablob, &format, &master_desc, | 796 | ret = datablob_parse(datablob, &format, &master_desc, |
796 | &decrypted_datalen, &hex_encoded_iv); | 797 | &decrypted_datalen, &hex_encoded_iv); |
797 | if (ret < 0) | 798 | if (ret < 0) |
@@ -834,16 +835,17 @@ static void encrypted_rcu_free(struct rcu_head *rcu) | |||
834 | * | 835 | * |
835 | * On success, return 0. Otherwise return errno. | 836 | * On success, return 0. Otherwise return errno. |
836 | */ | 837 | */ |
837 | static int encrypted_update(struct key *key, const void *data, size_t datalen) | 838 | static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) |
838 | { | 839 | { |
839 | struct encrypted_key_payload *epayload = key->payload.data; | 840 | struct encrypted_key_payload *epayload = key->payload.data; |
840 | struct encrypted_key_payload *new_epayload; | 841 | struct encrypted_key_payload *new_epayload; |
841 | char *buf; | 842 | char *buf; |
842 | char *new_master_desc = NULL; | 843 | char *new_master_desc = NULL; |
843 | const char *format = NULL; | 844 | const char *format = NULL; |
845 | size_t datalen = prep->datalen; | ||
844 | int ret = 0; | 846 | int ret = 0; |
845 | 847 | ||
846 | if (datalen <= 0 || datalen > 32767 || !data) | 848 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
847 | return -EINVAL; | 849 | return -EINVAL; |
848 | 850 | ||
849 | buf = kmalloc(datalen + 1, GFP_KERNEL); | 851 | buf = kmalloc(datalen + 1, GFP_KERNEL); |
@@ -851,7 +853,7 @@ static int encrypted_update(struct key *key, const void *data, size_t datalen) | |||
851 | return -ENOMEM; | 853 | return -ENOMEM; |
852 | 854 | ||
853 | buf[datalen] = 0; | 855 | buf[datalen] = 0; |
854 | memcpy(buf, data, datalen); | 856 | memcpy(buf, prep->data, datalen); |
855 | ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); | 857 | ret = datablob_parse(buf, &format, &new_master_desc, NULL, NULL); |
856 | if (ret < 0) | 858 | if (ret < 0) |
857 | goto out; | 859 | goto out; |
diff --git a/security/keys/key.c b/security/keys/key.c index 50d96d4e06f2..da63a659db75 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -412,8 +412,7 @@ EXPORT_SYMBOL(key_payload_reserve); | |||
412 | * key_construction_mutex. | 412 | * key_construction_mutex. |
413 | */ | 413 | */ |
414 | static int __key_instantiate_and_link(struct key *key, | 414 | static int __key_instantiate_and_link(struct key *key, |
415 | const void *data, | 415 | struct key_preparsed_payload *prep, |
416 | size_t datalen, | ||
417 | struct key *keyring, | 416 | struct key *keyring, |
418 | struct key *authkey, | 417 | struct key *authkey, |
419 | unsigned long *_prealloc) | 418 | unsigned long *_prealloc) |
@@ -431,7 +430,7 @@ static int __key_instantiate_and_link(struct key *key, | |||
431 | /* can't instantiate twice */ | 430 | /* can't instantiate twice */ |
432 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { | 431 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { |
433 | /* instantiate the key */ | 432 | /* instantiate the key */ |
434 | ret = key->type->instantiate(key, data, datalen); | 433 | ret = key->type->instantiate(key, prep); |
435 | 434 | ||
436 | if (ret == 0) { | 435 | if (ret == 0) { |
437 | /* mark the key as being instantiated */ | 436 | /* mark the key as being instantiated */ |
@@ -482,22 +481,37 @@ int key_instantiate_and_link(struct key *key, | |||
482 | struct key *keyring, | 481 | struct key *keyring, |
483 | struct key *authkey) | 482 | struct key *authkey) |
484 | { | 483 | { |
484 | struct key_preparsed_payload prep; | ||
485 | unsigned long prealloc; | 485 | unsigned long prealloc; |
486 | int ret; | 486 | int ret; |
487 | 487 | ||
488 | memset(&prep, 0, sizeof(prep)); | ||
489 | prep.data = data; | ||
490 | prep.datalen = datalen; | ||
491 | prep.quotalen = key->type->def_datalen; | ||
492 | if (key->type->preparse) { | ||
493 | ret = key->type->preparse(&prep); | ||
494 | if (ret < 0) | ||
495 | goto error; | ||
496 | } | ||
497 | |||
488 | if (keyring) { | 498 | if (keyring) { |
489 | ret = __key_link_begin(keyring, key->type, key->description, | 499 | ret = __key_link_begin(keyring, key->type, key->description, |
490 | &prealloc); | 500 | &prealloc); |
491 | if (ret < 0) | 501 | if (ret < 0) |
492 | return ret; | 502 | goto error_free_preparse; |
493 | } | 503 | } |
494 | 504 | ||
495 | ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey, | 505 | ret = __key_instantiate_and_link(key, &prep, keyring, authkey, |
496 | &prealloc); | 506 | &prealloc); |
497 | 507 | ||
498 | if (keyring) | 508 | if (keyring) |
499 | __key_link_end(keyring, key->type, prealloc); | 509 | __key_link_end(keyring, key->type, prealloc); |
500 | 510 | ||
511 | error_free_preparse: | ||
512 | if (key->type->preparse) | ||
513 | key->type->free_preparse(&prep); | ||
514 | error: | ||
501 | return ret; | 515 | return ret; |
502 | } | 516 | } |
503 | 517 | ||
@@ -706,7 +720,7 @@ void key_type_put(struct key_type *ktype) | |||
706 | * if we get an error. | 720 | * if we get an error. |
707 | */ | 721 | */ |
708 | static inline key_ref_t __key_update(key_ref_t key_ref, | 722 | static inline key_ref_t __key_update(key_ref_t key_ref, |
709 | const void *payload, size_t plen) | 723 | struct key_preparsed_payload *prep) |
710 | { | 724 | { |
711 | struct key *key = key_ref_to_ptr(key_ref); | 725 | struct key *key = key_ref_to_ptr(key_ref); |
712 | int ret; | 726 | int ret; |
@@ -722,7 +736,7 @@ static inline key_ref_t __key_update(key_ref_t key_ref, | |||
722 | 736 | ||
723 | down_write(&key->sem); | 737 | down_write(&key->sem); |
724 | 738 | ||
725 | ret = key->type->update(key, payload, plen); | 739 | ret = key->type->update(key, prep); |
726 | if (ret == 0) | 740 | if (ret == 0) |
727 | /* updating a negative key instantiates it */ | 741 | /* updating a negative key instantiates it */ |
728 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | 742 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); |
@@ -774,6 +788,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
774 | unsigned long flags) | 788 | unsigned long flags) |
775 | { | 789 | { |
776 | unsigned long prealloc; | 790 | unsigned long prealloc; |
791 | struct key_preparsed_payload prep; | ||
777 | const struct cred *cred = current_cred(); | 792 | const struct cred *cred = current_cred(); |
778 | struct key_type *ktype; | 793 | struct key_type *ktype; |
779 | struct key *keyring, *key = NULL; | 794 | struct key *keyring, *key = NULL; |
@@ -789,8 +804,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
789 | } | 804 | } |
790 | 805 | ||
791 | key_ref = ERR_PTR(-EINVAL); | 806 | key_ref = ERR_PTR(-EINVAL); |
792 | if (!ktype->match || !ktype->instantiate) | 807 | if (!ktype->match || !ktype->instantiate || |
793 | goto error_2; | 808 | (!description && !ktype->preparse)) |
809 | goto error_put_type; | ||
794 | 810 | ||
795 | keyring = key_ref_to_ptr(keyring_ref); | 811 | keyring = key_ref_to_ptr(keyring_ref); |
796 | 812 | ||
@@ -798,18 +814,37 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
798 | 814 | ||
799 | key_ref = ERR_PTR(-ENOTDIR); | 815 | key_ref = ERR_PTR(-ENOTDIR); |
800 | if (keyring->type != &key_type_keyring) | 816 | if (keyring->type != &key_type_keyring) |
801 | goto error_2; | 817 | goto error_put_type; |
818 | |||
819 | memset(&prep, 0, sizeof(prep)); | ||
820 | prep.data = payload; | ||
821 | prep.datalen = plen; | ||
822 | prep.quotalen = ktype->def_datalen; | ||
823 | if (ktype->preparse) { | ||
824 | ret = ktype->preparse(&prep); | ||
825 | if (ret < 0) { | ||
826 | key_ref = ERR_PTR(ret); | ||
827 | goto error_put_type; | ||
828 | } | ||
829 | if (!description) | ||
830 | description = prep.description; | ||
831 | key_ref = ERR_PTR(-EINVAL); | ||
832 | if (!description) | ||
833 | goto error_free_prep; | ||
834 | } | ||
802 | 835 | ||
803 | ret = __key_link_begin(keyring, ktype, description, &prealloc); | 836 | ret = __key_link_begin(keyring, ktype, description, &prealloc); |
804 | if (ret < 0) | 837 | if (ret < 0) { |
805 | goto error_2; | 838 | key_ref = ERR_PTR(ret); |
839 | goto error_free_prep; | ||
840 | } | ||
806 | 841 | ||
807 | /* if we're going to allocate a new key, we're going to have | 842 | /* if we're going to allocate a new key, we're going to have |
808 | * to modify the keyring */ | 843 | * to modify the keyring */ |
809 | ret = key_permission(keyring_ref, KEY_WRITE); | 844 | ret = key_permission(keyring_ref, KEY_WRITE); |
810 | if (ret < 0) { | 845 | if (ret < 0) { |
811 | key_ref = ERR_PTR(ret); | 846 | key_ref = ERR_PTR(ret); |
812 | goto error_3; | 847 | goto error_link_end; |
813 | } | 848 | } |
814 | 849 | ||
815 | /* if it's possible to update this type of key, search for an existing | 850 | /* if it's possible to update this type of key, search for an existing |
@@ -826,13 +861,13 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
826 | /* if the client doesn't provide, decide on the permissions we want */ | 861 | /* if the client doesn't provide, decide on the permissions we want */ |
827 | if (perm == KEY_PERM_UNDEF) { | 862 | if (perm == KEY_PERM_UNDEF) { |
828 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; | 863 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; |
829 | perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR; | 864 | perm |= KEY_USR_VIEW; |
830 | 865 | ||
831 | if (ktype->read) | 866 | if (ktype->read) |
832 | perm |= KEY_POS_READ | KEY_USR_READ; | 867 | perm |= KEY_POS_READ; |
833 | 868 | ||
834 | if (ktype == &key_type_keyring || ktype->update) | 869 | if (ktype == &key_type_keyring || ktype->update) |
835 | perm |= KEY_USR_WRITE; | 870 | perm |= KEY_POS_WRITE; |
836 | } | 871 | } |
837 | 872 | ||
838 | /* allocate a new key */ | 873 | /* allocate a new key */ |
@@ -840,25 +875,27 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
840 | perm, flags); | 875 | perm, flags); |
841 | if (IS_ERR(key)) { | 876 | if (IS_ERR(key)) { |
842 | key_ref = ERR_CAST(key); | 877 | key_ref = ERR_CAST(key); |
843 | goto error_3; | 878 | goto error_link_end; |
844 | } | 879 | } |
845 | 880 | ||
846 | /* instantiate it and link it into the target keyring */ | 881 | /* instantiate it and link it into the target keyring */ |
847 | ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL, | 882 | ret = __key_instantiate_and_link(key, &prep, keyring, NULL, &prealloc); |
848 | &prealloc); | ||
849 | if (ret < 0) { | 883 | if (ret < 0) { |
850 | key_put(key); | 884 | key_put(key); |
851 | key_ref = ERR_PTR(ret); | 885 | key_ref = ERR_PTR(ret); |
852 | goto error_3; | 886 | goto error_link_end; |
853 | } | 887 | } |
854 | 888 | ||
855 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); | 889 | key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); |
856 | 890 | ||
857 | error_3: | 891 | error_link_end: |
858 | __key_link_end(keyring, ktype, prealloc); | 892 | __key_link_end(keyring, ktype, prealloc); |
859 | error_2: | 893 | error_free_prep: |
894 | if (ktype->preparse) | ||
895 | ktype->free_preparse(&prep); | ||
896 | error_put_type: | ||
860 | key_type_put(ktype); | 897 | key_type_put(ktype); |
861 | error: | 898 | error: |
862 | return key_ref; | 899 | return key_ref; |
863 | 900 | ||
864 | found_matching_key: | 901 | found_matching_key: |
@@ -866,10 +903,9 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
866 | * - we can drop the locks first as we have the key pinned | 903 | * - we can drop the locks first as we have the key pinned |
867 | */ | 904 | */ |
868 | __key_link_end(keyring, ktype, prealloc); | 905 | __key_link_end(keyring, ktype, prealloc); |
869 | key_type_put(ktype); | ||
870 | 906 | ||
871 | key_ref = __key_update(key_ref, payload, plen); | 907 | key_ref = __key_update(key_ref, &prep); |
872 | goto error; | 908 | goto error_free_prep; |
873 | } | 909 | } |
874 | EXPORT_SYMBOL(key_create_or_update); | 910 | EXPORT_SYMBOL(key_create_or_update); |
875 | 911 | ||
@@ -888,6 +924,7 @@ EXPORT_SYMBOL(key_create_or_update); | |||
888 | */ | 924 | */ |
889 | int key_update(key_ref_t key_ref, const void *payload, size_t plen) | 925 | int key_update(key_ref_t key_ref, const void *payload, size_t plen) |
890 | { | 926 | { |
927 | struct key_preparsed_payload prep; | ||
891 | struct key *key = key_ref_to_ptr(key_ref); | 928 | struct key *key = key_ref_to_ptr(key_ref); |
892 | int ret; | 929 | int ret; |
893 | 930 | ||
@@ -900,18 +937,31 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) | |||
900 | 937 | ||
901 | /* attempt to update it if supported */ | 938 | /* attempt to update it if supported */ |
902 | ret = -EOPNOTSUPP; | 939 | ret = -EOPNOTSUPP; |
903 | if (key->type->update) { | 940 | if (!key->type->update) |
904 | down_write(&key->sem); | 941 | goto error; |
905 | |||
906 | ret = key->type->update(key, payload, plen); | ||
907 | if (ret == 0) | ||
908 | /* updating a negative key instantiates it */ | ||
909 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | ||
910 | 942 | ||
911 | up_write(&key->sem); | 943 | memset(&prep, 0, sizeof(prep)); |
944 | prep.data = payload; | ||
945 | prep.datalen = plen; | ||
946 | prep.quotalen = key->type->def_datalen; | ||
947 | if (key->type->preparse) { | ||
948 | ret = key->type->preparse(&prep); | ||
949 | if (ret < 0) | ||
950 | goto error; | ||
912 | } | 951 | } |
913 | 952 | ||
914 | error: | 953 | down_write(&key->sem); |
954 | |||
955 | ret = key->type->update(key, &prep); | ||
956 | if (ret == 0) | ||
957 | /* updating a negative key instantiates it */ | ||
958 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | ||
959 | |||
960 | up_write(&key->sem); | ||
961 | |||
962 | if (key->type->preparse) | ||
963 | key->type->free_preparse(&prep); | ||
964 | error: | ||
915 | return ret; | 965 | return ret; |
916 | } | 966 | } |
917 | EXPORT_SYMBOL(key_update); | 967 | EXPORT_SYMBOL(key_update); |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 3364fbf46807..6d9d0c747525 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -46,6 +46,9 @@ static int key_get_type_from_user(char *type, | |||
46 | * Extract the description of a new key from userspace and either add it as a | 46 | * Extract the description of a new key from userspace and either add it as a |
47 | * new key to the specified keyring or update a matching key in that keyring. | 47 | * new key to the specified keyring or update a matching key in that keyring. |
48 | * | 48 | * |
49 | * If the description is NULL or an empty string, the key type is asked to | ||
50 | * generate one from the payload. | ||
51 | * | ||
49 | * The keyring must be writable so that we can attach the key to it. | 52 | * The keyring must be writable so that we can attach the key to it. |
50 | * | 53 | * |
51 | * If successful, the new key's serial number is returned, otherwise an error | 54 | * If successful, the new key's serial number is returned, otherwise an error |
@@ -72,10 +75,17 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type, | |||
72 | if (ret < 0) | 75 | if (ret < 0) |
73 | goto error; | 76 | goto error; |
74 | 77 | ||
75 | description = strndup_user(_description, PAGE_SIZE); | 78 | description = NULL; |
76 | if (IS_ERR(description)) { | 79 | if (_description) { |
77 | ret = PTR_ERR(description); | 80 | description = strndup_user(_description, PAGE_SIZE); |
78 | goto error; | 81 | if (IS_ERR(description)) { |
82 | ret = PTR_ERR(description); | ||
83 | goto error; | ||
84 | } | ||
85 | if (!*description) { | ||
86 | kfree(description); | ||
87 | description = NULL; | ||
88 | } | ||
79 | } | 89 | } |
80 | 90 | ||
81 | /* pull the payload in if one was supplied */ | 91 | /* pull the payload in if one was supplied */ |
@@ -1112,12 +1122,12 @@ long keyctl_instantiate_key_iov(key_serial_t id, | |||
1112 | ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, | 1122 | ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc, |
1113 | ARRAY_SIZE(iovstack), iovstack, &iov); | 1123 | ARRAY_SIZE(iovstack), iovstack, &iov); |
1114 | if (ret < 0) | 1124 | if (ret < 0) |
1115 | return ret; | 1125 | goto err; |
1116 | if (ret == 0) | 1126 | if (ret == 0) |
1117 | goto no_payload_free; | 1127 | goto no_payload_free; |
1118 | 1128 | ||
1119 | ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); | 1129 | ret = keyctl_instantiate_key_common(id, iov, ioc, ret, ringid); |
1120 | 1130 | err: | |
1121 | if (iov != iovstack) | 1131 | if (iov != iovstack) |
1122 | kfree(iov); | 1132 | kfree(iov); |
1123 | return ret; | 1133 | return ret; |
@@ -1475,7 +1485,8 @@ long keyctl_session_to_parent(void) | |||
1475 | goto error_keyring; | 1485 | goto error_keyring; |
1476 | newwork = &cred->rcu; | 1486 | newwork = &cred->rcu; |
1477 | 1487 | ||
1478 | cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r); | 1488 | cred->session_keyring = key_ref_to_ptr(keyring_r); |
1489 | keyring_r = NULL; | ||
1479 | init_task_work(newwork, key_change_session_keyring); | 1490 | init_task_work(newwork, key_change_session_keyring); |
1480 | 1491 | ||
1481 | me = current; | 1492 | me = current; |
@@ -1500,7 +1511,7 @@ long keyctl_session_to_parent(void) | |||
1500 | mycred = current_cred(); | 1511 | mycred = current_cred(); |
1501 | pcred = __task_cred(parent); | 1512 | pcred = __task_cred(parent); |
1502 | if (mycred == pcred || | 1513 | if (mycred == pcred || |
1503 | mycred->tgcred->session_keyring == pcred->tgcred->session_keyring) { | 1514 | mycred->session_keyring == pcred->session_keyring) { |
1504 | ret = 0; | 1515 | ret = 0; |
1505 | goto unlock; | 1516 | goto unlock; |
1506 | } | 1517 | } |
@@ -1516,9 +1527,9 @@ long keyctl_session_to_parent(void) | |||
1516 | goto unlock; | 1527 | goto unlock; |
1517 | 1528 | ||
1518 | /* the keyrings must have the same UID */ | 1529 | /* the keyrings must have the same UID */ |
1519 | if ((pcred->tgcred->session_keyring && | 1530 | if ((pcred->session_keyring && |
1520 | pcred->tgcred->session_keyring->uid != mycred->euid) || | 1531 | pcred->session_keyring->uid != mycred->euid) || |
1521 | mycred->tgcred->session_keyring->uid != mycred->euid) | 1532 | mycred->session_keyring->uid != mycred->euid) |
1522 | goto unlock; | 1533 | goto unlock; |
1523 | 1534 | ||
1524 | /* cancel an already pending keyring replacement */ | 1535 | /* cancel an already pending keyring replacement */ |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 81e7852d281d..9270ba054a1e 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -66,7 +66,7 @@ static inline unsigned keyring_hash(const char *desc) | |||
66 | * operations. | 66 | * operations. |
67 | */ | 67 | */ |
68 | static int keyring_instantiate(struct key *keyring, | 68 | static int keyring_instantiate(struct key *keyring, |
69 | const void *data, size_t datalen); | 69 | struct key_preparsed_payload *prep); |
70 | static int keyring_match(const struct key *keyring, const void *criterion); | 70 | static int keyring_match(const struct key *keyring, const void *criterion); |
71 | static void keyring_revoke(struct key *keyring); | 71 | static void keyring_revoke(struct key *keyring); |
72 | static void keyring_destroy(struct key *keyring); | 72 | static void keyring_destroy(struct key *keyring); |
@@ -121,12 +121,12 @@ static void keyring_publish_name(struct key *keyring) | |||
121 | * Returns 0 on success, -EINVAL if given any data. | 121 | * Returns 0 on success, -EINVAL if given any data. |
122 | */ | 122 | */ |
123 | static int keyring_instantiate(struct key *keyring, | 123 | static int keyring_instantiate(struct key *keyring, |
124 | const void *data, size_t datalen) | 124 | struct key_preparsed_payload *prep) |
125 | { | 125 | { |
126 | int ret; | 126 | int ret; |
127 | 127 | ||
128 | ret = -EINVAL; | 128 | ret = -EINVAL; |
129 | if (datalen == 0) { | 129 | if (prep->datalen == 0) { |
130 | /* make the keyring available by name if it has one */ | 130 | /* make the keyring available by name if it has one */ |
131 | keyring_publish_name(keyring); | 131 | keyring_publish_name(keyring); |
132 | ret = 0; | 132 | ret = 0; |
@@ -257,17 +257,14 @@ error: | |||
257 | * Allocate a keyring and link into the destination keyring. | 257 | * Allocate a keyring and link into the destination keyring. |
258 | */ | 258 | */ |
259 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | 259 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, |
260 | const struct cred *cred, unsigned long flags, | 260 | const struct cred *cred, key_perm_t perm, |
261 | struct key *dest) | 261 | unsigned long flags, struct key *dest) |
262 | { | 262 | { |
263 | struct key *keyring; | 263 | struct key *keyring; |
264 | int ret; | 264 | int ret; |
265 | 265 | ||
266 | keyring = key_alloc(&key_type_keyring, description, | 266 | keyring = key_alloc(&key_type_keyring, description, |
267 | uid, gid, cred, | 267 | uid, gid, cred, perm, flags); |
268 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, | ||
269 | flags); | ||
270 | |||
271 | if (!IS_ERR(keyring)) { | 268 | if (!IS_ERR(keyring)) { |
272 | ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); | 269 | ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); |
273 | if (ret < 0) { | 270 | if (ret < 0) { |
@@ -278,6 +275,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | |||
278 | 275 | ||
279 | return keyring; | 276 | return keyring; |
280 | } | 277 | } |
278 | EXPORT_SYMBOL(keyring_alloc); | ||
281 | 279 | ||
282 | /** | 280 | /** |
283 | * keyring_search_aux - Search a keyring tree for a key matching some criteria | 281 | * keyring_search_aux - Search a keyring tree for a key matching some criteria |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 54339cfd6734..b58d93892740 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -46,9 +46,11 @@ int install_user_keyrings(void) | |||
46 | struct user_struct *user; | 46 | struct user_struct *user; |
47 | const struct cred *cred; | 47 | const struct cred *cred; |
48 | struct key *uid_keyring, *session_keyring; | 48 | struct key *uid_keyring, *session_keyring; |
49 | key_perm_t user_keyring_perm; | ||
49 | char buf[20]; | 50 | char buf[20]; |
50 | int ret; | 51 | int ret; |
51 | 52 | ||
53 | user_keyring_perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL; | ||
52 | cred = current_cred(); | 54 | cred = current_cred(); |
53 | user = cred->user; | 55 | user = cred->user; |
54 | 56 | ||
@@ -72,8 +74,8 @@ int install_user_keyrings(void) | |||
72 | uid_keyring = find_keyring_by_name(buf, true); | 74 | uid_keyring = find_keyring_by_name(buf, true); |
73 | if (IS_ERR(uid_keyring)) { | 75 | if (IS_ERR(uid_keyring)) { |
74 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, | 76 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, |
75 | cred, KEY_ALLOC_IN_QUOTA, | 77 | cred, user_keyring_perm, |
76 | NULL); | 78 | KEY_ALLOC_IN_QUOTA, NULL); |
77 | if (IS_ERR(uid_keyring)) { | 79 | if (IS_ERR(uid_keyring)) { |
78 | ret = PTR_ERR(uid_keyring); | 80 | ret = PTR_ERR(uid_keyring); |
79 | goto error; | 81 | goto error; |
@@ -88,7 +90,8 @@ int install_user_keyrings(void) | |||
88 | if (IS_ERR(session_keyring)) { | 90 | if (IS_ERR(session_keyring)) { |
89 | session_keyring = | 91 | session_keyring = |
90 | keyring_alloc(buf, user->uid, (gid_t) -1, | 92 | keyring_alloc(buf, user->uid, (gid_t) -1, |
91 | cred, KEY_ALLOC_IN_QUOTA, NULL); | 93 | cred, user_keyring_perm, |
94 | KEY_ALLOC_IN_QUOTA, NULL); | ||
92 | if (IS_ERR(session_keyring)) { | 95 | if (IS_ERR(session_keyring)) { |
93 | ret = PTR_ERR(session_keyring); | 96 | ret = PTR_ERR(session_keyring); |
94 | goto error_release; | 97 | goto error_release; |
@@ -129,6 +132,7 @@ int install_thread_keyring_to_cred(struct cred *new) | |||
129 | struct key *keyring; | 132 | struct key *keyring; |
130 | 133 | ||
131 | keyring = keyring_alloc("_tid", new->uid, new->gid, new, | 134 | keyring = keyring_alloc("_tid", new->uid, new->gid, new, |
135 | KEY_POS_ALL | KEY_USR_VIEW, | ||
132 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | 136 | KEY_ALLOC_QUOTA_OVERRUN, NULL); |
133 | if (IS_ERR(keyring)) | 137 | if (IS_ERR(keyring)) |
134 | return PTR_ERR(keyring); | 138 | return PTR_ERR(keyring); |
@@ -169,27 +173,18 @@ static int install_thread_keyring(void) | |||
169 | int install_process_keyring_to_cred(struct cred *new) | 173 | int install_process_keyring_to_cred(struct cred *new) |
170 | { | 174 | { |
171 | struct key *keyring; | 175 | struct key *keyring; |
172 | int ret; | ||
173 | 176 | ||
174 | if (new->tgcred->process_keyring) | 177 | if (new->process_keyring) |
175 | return -EEXIST; | 178 | return -EEXIST; |
176 | 179 | ||
177 | keyring = keyring_alloc("_pid", new->uid, new->gid, | 180 | keyring = keyring_alloc("_pid", new->uid, new->gid, new, |
178 | new, KEY_ALLOC_QUOTA_OVERRUN, NULL); | 181 | KEY_POS_ALL | KEY_USR_VIEW, |
182 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | ||
179 | if (IS_ERR(keyring)) | 183 | if (IS_ERR(keyring)) |
180 | return PTR_ERR(keyring); | 184 | return PTR_ERR(keyring); |
181 | 185 | ||
182 | spin_lock_irq(&new->tgcred->lock); | 186 | new->process_keyring = keyring; |
183 | if (!new->tgcred->process_keyring) { | 187 | return 0; |
184 | new->tgcred->process_keyring = keyring; | ||
185 | keyring = NULL; | ||
186 | ret = 0; | ||
187 | } else { | ||
188 | ret = -EEXIST; | ||
189 | } | ||
190 | spin_unlock_irq(&new->tgcred->lock); | ||
191 | key_put(keyring); | ||
192 | return ret; | ||
193 | } | 188 | } |
194 | 189 | ||
195 | /* | 190 | /* |
@@ -230,11 +225,12 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) | |||
230 | /* create an empty session keyring */ | 225 | /* create an empty session keyring */ |
231 | if (!keyring) { | 226 | if (!keyring) { |
232 | flags = KEY_ALLOC_QUOTA_OVERRUN; | 227 | flags = KEY_ALLOC_QUOTA_OVERRUN; |
233 | if (cred->tgcred->session_keyring) | 228 | if (cred->session_keyring) |
234 | flags = KEY_ALLOC_IN_QUOTA; | 229 | flags = KEY_ALLOC_IN_QUOTA; |
235 | 230 | ||
236 | keyring = keyring_alloc("_ses", cred->uid, cred->gid, | 231 | keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred, |
237 | cred, flags, NULL); | 232 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ, |
233 | flags, NULL); | ||
238 | if (IS_ERR(keyring)) | 234 | if (IS_ERR(keyring)) |
239 | return PTR_ERR(keyring); | 235 | return PTR_ERR(keyring); |
240 | } else { | 236 | } else { |
@@ -242,17 +238,11 @@ int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) | |||
242 | } | 238 | } |
243 | 239 | ||
244 | /* install the keyring */ | 240 | /* install the keyring */ |
245 | spin_lock_irq(&cred->tgcred->lock); | 241 | old = cred->session_keyring; |
246 | old = cred->tgcred->session_keyring; | 242 | rcu_assign_pointer(cred->session_keyring, keyring); |
247 | rcu_assign_pointer(cred->tgcred->session_keyring, keyring); | 243 | |
248 | spin_unlock_irq(&cred->tgcred->lock); | 244 | if (old) |
249 | |||
250 | /* we're using RCU on the pointer, but there's no point synchronising | ||
251 | * on it if it didn't previously point to anything */ | ||
252 | if (old) { | ||
253 | synchronize_rcu(); | ||
254 | key_put(old); | 245 | key_put(old); |
255 | } | ||
256 | 246 | ||
257 | return 0; | 247 | return 0; |
258 | } | 248 | } |
@@ -357,8 +347,6 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
357 | 347 | ||
358 | switch (PTR_ERR(key_ref)) { | 348 | switch (PTR_ERR(key_ref)) { |
359 | case -EAGAIN: /* no key */ | 349 | case -EAGAIN: /* no key */ |
360 | if (ret) | ||
361 | break; | ||
362 | case -ENOKEY: /* negative key */ | 350 | case -ENOKEY: /* negative key */ |
363 | ret = key_ref; | 351 | ret = key_ref; |
364 | break; | 352 | break; |
@@ -369,9 +357,9 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
369 | } | 357 | } |
370 | 358 | ||
371 | /* search the process keyring second */ | 359 | /* search the process keyring second */ |
372 | if (cred->tgcred->process_keyring) { | 360 | if (cred->process_keyring) { |
373 | key_ref = keyring_search_aux( | 361 | key_ref = keyring_search_aux( |
374 | make_key_ref(cred->tgcred->process_keyring, 1), | 362 | make_key_ref(cred->process_keyring, 1), |
375 | cred, type, description, match, no_state_check); | 363 | cred, type, description, match, no_state_check); |
376 | if (!IS_ERR(key_ref)) | 364 | if (!IS_ERR(key_ref)) |
377 | goto found; | 365 | goto found; |
@@ -390,12 +378,10 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
390 | } | 378 | } |
391 | 379 | ||
392 | /* search the session keyring */ | 380 | /* search the session keyring */ |
393 | if (cred->tgcred->session_keyring) { | 381 | if (cred->session_keyring) { |
394 | rcu_read_lock(); | 382 | rcu_read_lock(); |
395 | key_ref = keyring_search_aux( | 383 | key_ref = keyring_search_aux( |
396 | make_key_ref(rcu_dereference( | 384 | make_key_ref(rcu_dereference(cred->session_keyring), 1), |
397 | cred->tgcred->session_keyring), | ||
398 | 1), | ||
399 | cred, type, description, match, no_state_check); | 385 | cred, type, description, match, no_state_check); |
400 | rcu_read_unlock(); | 386 | rcu_read_unlock(); |
401 | 387 | ||
@@ -565,7 +551,7 @@ try_again: | |||
565 | break; | 551 | break; |
566 | 552 | ||
567 | case KEY_SPEC_PROCESS_KEYRING: | 553 | case KEY_SPEC_PROCESS_KEYRING: |
568 | if (!cred->tgcred->process_keyring) { | 554 | if (!cred->process_keyring) { |
569 | if (!(lflags & KEY_LOOKUP_CREATE)) | 555 | if (!(lflags & KEY_LOOKUP_CREATE)) |
570 | goto error; | 556 | goto error; |
571 | 557 | ||
@@ -577,13 +563,13 @@ try_again: | |||
577 | goto reget_creds; | 563 | goto reget_creds; |
578 | } | 564 | } |
579 | 565 | ||
580 | key = cred->tgcred->process_keyring; | 566 | key = cred->process_keyring; |
581 | atomic_inc(&key->usage); | 567 | atomic_inc(&key->usage); |
582 | key_ref = make_key_ref(key, 1); | 568 | key_ref = make_key_ref(key, 1); |
583 | break; | 569 | break; |
584 | 570 | ||
585 | case KEY_SPEC_SESSION_KEYRING: | 571 | case KEY_SPEC_SESSION_KEYRING: |
586 | if (!cred->tgcred->session_keyring) { | 572 | if (!cred->session_keyring) { |
587 | /* always install a session keyring upon access if one | 573 | /* always install a session keyring upon access if one |
588 | * doesn't exist yet */ | 574 | * doesn't exist yet */ |
589 | ret = install_user_keyrings(); | 575 | ret = install_user_keyrings(); |
@@ -598,7 +584,7 @@ try_again: | |||
598 | if (ret < 0) | 584 | if (ret < 0) |
599 | goto error; | 585 | goto error; |
600 | goto reget_creds; | 586 | goto reget_creds; |
601 | } else if (cred->tgcred->session_keyring == | 587 | } else if (cred->session_keyring == |
602 | cred->user->session_keyring && | 588 | cred->user->session_keyring && |
603 | lflags & KEY_LOOKUP_CREATE) { | 589 | lflags & KEY_LOOKUP_CREATE) { |
604 | ret = join_session_keyring(NULL); | 590 | ret = join_session_keyring(NULL); |
@@ -608,7 +594,7 @@ try_again: | |||
608 | } | 594 | } |
609 | 595 | ||
610 | rcu_read_lock(); | 596 | rcu_read_lock(); |
611 | key = rcu_dereference(cred->tgcred->session_keyring); | 597 | key = rcu_dereference(cred->session_keyring); |
612 | atomic_inc(&key->usage); | 598 | atomic_inc(&key->usage); |
613 | rcu_read_unlock(); | 599 | rcu_read_unlock(); |
614 | key_ref = make_key_ref(key, 1); | 600 | key_ref = make_key_ref(key, 1); |
@@ -768,12 +754,6 @@ long join_session_keyring(const char *name) | |||
768 | struct key *keyring; | 754 | struct key *keyring; |
769 | long ret, serial; | 755 | long ret, serial; |
770 | 756 | ||
771 | /* only permit this if there's a single thread in the thread group - | ||
772 | * this avoids us having to adjust the creds on all threads and risking | ||
773 | * ENOMEM */ | ||
774 | if (!current_is_single_threaded()) | ||
775 | return -EMLINK; | ||
776 | |||
777 | new = prepare_creds(); | 757 | new = prepare_creds(); |
778 | if (!new) | 758 | if (!new) |
779 | return -ENOMEM; | 759 | return -ENOMEM; |
@@ -785,7 +765,7 @@ long join_session_keyring(const char *name) | |||
785 | if (ret < 0) | 765 | if (ret < 0) |
786 | goto error; | 766 | goto error; |
787 | 767 | ||
788 | serial = new->tgcred->session_keyring->serial; | 768 | serial = new->session_keyring->serial; |
789 | ret = commit_creds(new); | 769 | ret = commit_creds(new); |
790 | if (ret == 0) | 770 | if (ret == 0) |
791 | ret = serial; | 771 | ret = serial; |
@@ -799,8 +779,10 @@ long join_session_keyring(const char *name) | |||
799 | keyring = find_keyring_by_name(name, false); | 779 | keyring = find_keyring_by_name(name, false); |
800 | if (PTR_ERR(keyring) == -ENOKEY) { | 780 | if (PTR_ERR(keyring) == -ENOKEY) { |
801 | /* not found - try and create a new one */ | 781 | /* not found - try and create a new one */ |
802 | keyring = keyring_alloc(name, old->uid, old->gid, old, | 782 | keyring = keyring_alloc( |
803 | KEY_ALLOC_IN_QUOTA, NULL); | 783 | name, old->uid, old->gid, old, |
784 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_LINK, | ||
785 | KEY_ALLOC_IN_QUOTA, NULL); | ||
804 | if (IS_ERR(keyring)) { | 786 | if (IS_ERR(keyring)) { |
805 | ret = PTR_ERR(keyring); | 787 | ret = PTR_ERR(keyring); |
806 | goto error2; | 788 | goto error2; |
@@ -808,6 +790,9 @@ long join_session_keyring(const char *name) | |||
808 | } else if (IS_ERR(keyring)) { | 790 | } else if (IS_ERR(keyring)) { |
809 | ret = PTR_ERR(keyring); | 791 | ret = PTR_ERR(keyring); |
810 | goto error2; | 792 | goto error2; |
793 | } else if (keyring == new->session_keyring) { | ||
794 | ret = 0; | ||
795 | goto error2; | ||
811 | } | 796 | } |
812 | 797 | ||
813 | /* we've got a keyring - now to install it */ | 798 | /* we've got a keyring - now to install it */ |
@@ -864,8 +849,7 @@ void key_change_session_keyring(struct callback_head *twork) | |||
864 | 849 | ||
865 | new->jit_keyring = old->jit_keyring; | 850 | new->jit_keyring = old->jit_keyring; |
866 | new->thread_keyring = key_get(old->thread_keyring); | 851 | new->thread_keyring = key_get(old->thread_keyring); |
867 | new->tgcred->tgid = old->tgcred->tgid; | 852 | new->process_keyring = key_get(old->process_keyring); |
868 | new->tgcred->process_keyring = key_get(old->tgcred->process_keyring); | ||
869 | 853 | ||
870 | security_transfer_creds(new, old); | 854 | security_transfer_creds(new, old); |
871 | 855 | ||
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index 000e75017520..0ae3a2202771 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -126,6 +126,7 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
126 | 126 | ||
127 | cred = get_current_cred(); | 127 | cred = get_current_cred(); |
128 | keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, | 128 | keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, |
129 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ, | ||
129 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | 130 | KEY_ALLOC_QUOTA_OVERRUN, NULL); |
130 | put_cred(cred); | 131 | put_cred(cred); |
131 | if (IS_ERR(keyring)) { | 132 | if (IS_ERR(keyring)) { |
@@ -150,12 +151,12 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
150 | cred->thread_keyring ? cred->thread_keyring->serial : 0); | 151 | cred->thread_keyring ? cred->thread_keyring->serial : 0); |
151 | 152 | ||
152 | prkey = 0; | 153 | prkey = 0; |
153 | if (cred->tgcred->process_keyring) | 154 | if (cred->process_keyring) |
154 | prkey = cred->tgcred->process_keyring->serial; | 155 | prkey = cred->process_keyring->serial; |
155 | sprintf(keyring_str[1], "%d", prkey); | 156 | sprintf(keyring_str[1], "%d", prkey); |
156 | 157 | ||
157 | rcu_read_lock(); | 158 | rcu_read_lock(); |
158 | session = rcu_dereference(cred->tgcred->session_keyring); | 159 | session = rcu_dereference(cred->session_keyring); |
159 | if (!session) | 160 | if (!session) |
160 | session = cred->user->session_keyring; | 161 | session = cred->user->session_keyring; |
161 | sskey = session->serial; | 162 | sskey = session->serial; |
@@ -297,14 +298,14 @@ static void construct_get_dest_keyring(struct key **_dest_keyring) | |||
297 | break; | 298 | break; |
298 | 299 | ||
299 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: | 300 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: |
300 | dest_keyring = key_get(cred->tgcred->process_keyring); | 301 | dest_keyring = key_get(cred->process_keyring); |
301 | if (dest_keyring) | 302 | if (dest_keyring) |
302 | break; | 303 | break; |
303 | 304 | ||
304 | case KEY_REQKEY_DEFL_SESSION_KEYRING: | 305 | case KEY_REQKEY_DEFL_SESSION_KEYRING: |
305 | rcu_read_lock(); | 306 | rcu_read_lock(); |
306 | dest_keyring = key_get( | 307 | dest_keyring = key_get( |
307 | rcu_dereference(cred->tgcred->session_keyring)); | 308 | rcu_dereference(cred->session_keyring)); |
308 | rcu_read_unlock(); | 309 | rcu_read_unlock(); |
309 | 310 | ||
310 | if (dest_keyring) | 311 | if (dest_keyring) |
@@ -347,6 +348,7 @@ static int construct_alloc_key(struct key_type *type, | |||
347 | const struct cred *cred = current_cred(); | 348 | const struct cred *cred = current_cred(); |
348 | unsigned long prealloc; | 349 | unsigned long prealloc; |
349 | struct key *key; | 350 | struct key *key; |
351 | key_perm_t perm; | ||
350 | key_ref_t key_ref; | 352 | key_ref_t key_ref; |
351 | int ret; | 353 | int ret; |
352 | 354 | ||
@@ -355,8 +357,15 @@ static int construct_alloc_key(struct key_type *type, | |||
355 | *_key = NULL; | 357 | *_key = NULL; |
356 | mutex_lock(&user->cons_lock); | 358 | mutex_lock(&user->cons_lock); |
357 | 359 | ||
360 | perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR; | ||
361 | perm |= KEY_USR_VIEW; | ||
362 | if (type->read) | ||
363 | perm |= KEY_POS_READ; | ||
364 | if (type == &key_type_keyring || type->update) | ||
365 | perm |= KEY_POS_WRITE; | ||
366 | |||
358 | key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, | 367 | key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, |
359 | KEY_POS_ALL, flags); | 368 | perm, flags); |
360 | if (IS_ERR(key)) | 369 | if (IS_ERR(key)) |
361 | goto alloc_failed; | 370 | goto alloc_failed; |
362 | 371 | ||
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 60d4e3f5e4bb..85730d5a5a59 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -19,7 +19,8 @@ | |||
19 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
20 | #include "internal.h" | 20 | #include "internal.h" |
21 | 21 | ||
22 | static int request_key_auth_instantiate(struct key *, const void *, size_t); | 22 | static int request_key_auth_instantiate(struct key *, |
23 | struct key_preparsed_payload *); | ||
23 | static void request_key_auth_describe(const struct key *, struct seq_file *); | 24 | static void request_key_auth_describe(const struct key *, struct seq_file *); |
24 | static void request_key_auth_revoke(struct key *); | 25 | static void request_key_auth_revoke(struct key *); |
25 | static void request_key_auth_destroy(struct key *); | 26 | static void request_key_auth_destroy(struct key *); |
@@ -42,10 +43,9 @@ struct key_type key_type_request_key_auth = { | |||
42 | * Instantiate a request-key authorisation key. | 43 | * Instantiate a request-key authorisation key. |
43 | */ | 44 | */ |
44 | static int request_key_auth_instantiate(struct key *key, | 45 | static int request_key_auth_instantiate(struct key *key, |
45 | const void *data, | 46 | struct key_preparsed_payload *prep) |
46 | size_t datalen) | ||
47 | { | 47 | { |
48 | key->payload.data = (struct request_key_auth *) data; | 48 | key->payload.data = (struct request_key_auth *)prep->data; |
49 | return 0; | 49 | return 0; |
50 | } | 50 | } |
51 | 51 | ||
diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 3f163d0489ad..e13fcf7636f7 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c | |||
@@ -895,23 +895,24 @@ static struct trusted_key_payload *trusted_payload_alloc(struct key *key) | |||
895 | * | 895 | * |
896 | * On success, return 0. Otherwise return errno. | 896 | * On success, return 0. Otherwise return errno. |
897 | */ | 897 | */ |
898 | static int trusted_instantiate(struct key *key, const void *data, | 898 | static int trusted_instantiate(struct key *key, |
899 | size_t datalen) | 899 | struct key_preparsed_payload *prep) |
900 | { | 900 | { |
901 | struct trusted_key_payload *payload = NULL; | 901 | struct trusted_key_payload *payload = NULL; |
902 | struct trusted_key_options *options = NULL; | 902 | struct trusted_key_options *options = NULL; |
903 | size_t datalen = prep->datalen; | ||
903 | char *datablob; | 904 | char *datablob; |
904 | int ret = 0; | 905 | int ret = 0; |
905 | int key_cmd; | 906 | int key_cmd; |
906 | size_t key_len; | 907 | size_t key_len; |
907 | 908 | ||
908 | if (datalen <= 0 || datalen > 32767 || !data) | 909 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
909 | return -EINVAL; | 910 | return -EINVAL; |
910 | 911 | ||
911 | datablob = kmalloc(datalen + 1, GFP_KERNEL); | 912 | datablob = kmalloc(datalen + 1, GFP_KERNEL); |
912 | if (!datablob) | 913 | if (!datablob) |
913 | return -ENOMEM; | 914 | return -ENOMEM; |
914 | memcpy(datablob, data, datalen); | 915 | memcpy(datablob, prep->data, datalen); |
915 | datablob[datalen] = '\0'; | 916 | datablob[datalen] = '\0'; |
916 | 917 | ||
917 | options = trusted_options_alloc(); | 918 | options = trusted_options_alloc(); |
@@ -981,17 +982,18 @@ static void trusted_rcu_free(struct rcu_head *rcu) | |||
981 | /* | 982 | /* |
982 | * trusted_update - reseal an existing key with new PCR values | 983 | * trusted_update - reseal an existing key with new PCR values |
983 | */ | 984 | */ |
984 | static int trusted_update(struct key *key, const void *data, size_t datalen) | 985 | static int trusted_update(struct key *key, struct key_preparsed_payload *prep) |
985 | { | 986 | { |
986 | struct trusted_key_payload *p = key->payload.data; | 987 | struct trusted_key_payload *p = key->payload.data; |
987 | struct trusted_key_payload *new_p; | 988 | struct trusted_key_payload *new_p; |
988 | struct trusted_key_options *new_o; | 989 | struct trusted_key_options *new_o; |
990 | size_t datalen = prep->datalen; | ||
989 | char *datablob; | 991 | char *datablob; |
990 | int ret = 0; | 992 | int ret = 0; |
991 | 993 | ||
992 | if (!p->migratable) | 994 | if (!p->migratable) |
993 | return -EPERM; | 995 | return -EPERM; |
994 | if (datalen <= 0 || datalen > 32767 || !data) | 996 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
995 | return -EINVAL; | 997 | return -EINVAL; |
996 | 998 | ||
997 | datablob = kmalloc(datalen + 1, GFP_KERNEL); | 999 | datablob = kmalloc(datalen + 1, GFP_KERNEL); |
@@ -1008,7 +1010,7 @@ static int trusted_update(struct key *key, const void *data, size_t datalen) | |||
1008 | goto out; | 1010 | goto out; |
1009 | } | 1011 | } |
1010 | 1012 | ||
1011 | memcpy(datablob, data, datalen); | 1013 | memcpy(datablob, prep->data, datalen); |
1012 | datablob[datalen] = '\0'; | 1014 | datablob[datalen] = '\0'; |
1013 | ret = datablob_parse(datablob, new_p, new_o); | 1015 | ret = datablob_parse(datablob, new_p, new_o); |
1014 | if (ret != Opt_update) { | 1016 | if (ret != Opt_update) { |
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index c7660a25a3e4..55dc88939185 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -58,13 +58,14 @@ EXPORT_SYMBOL_GPL(key_type_logon); | |||
58 | /* | 58 | /* |
59 | * instantiate a user defined key | 59 | * instantiate a user defined key |
60 | */ | 60 | */ |
61 | int user_instantiate(struct key *key, const void *data, size_t datalen) | 61 | int user_instantiate(struct key *key, struct key_preparsed_payload *prep) |
62 | { | 62 | { |
63 | struct user_key_payload *upayload; | 63 | struct user_key_payload *upayload; |
64 | size_t datalen = prep->datalen; | ||
64 | int ret; | 65 | int ret; |
65 | 66 | ||
66 | ret = -EINVAL; | 67 | ret = -EINVAL; |
67 | if (datalen <= 0 || datalen > 32767 || !data) | 68 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
68 | goto error; | 69 | goto error; |
69 | 70 | ||
70 | ret = key_payload_reserve(key, datalen); | 71 | ret = key_payload_reserve(key, datalen); |
@@ -78,7 +79,7 @@ int user_instantiate(struct key *key, const void *data, size_t datalen) | |||
78 | 79 | ||
79 | /* attach the data */ | 80 | /* attach the data */ |
80 | upayload->datalen = datalen; | 81 | upayload->datalen = datalen; |
81 | memcpy(upayload->data, data, datalen); | 82 | memcpy(upayload->data, prep->data, datalen); |
82 | rcu_assign_keypointer(key, upayload); | 83 | rcu_assign_keypointer(key, upayload); |
83 | ret = 0; | 84 | ret = 0; |
84 | 85 | ||
@@ -92,13 +93,14 @@ EXPORT_SYMBOL_GPL(user_instantiate); | |||
92 | * update a user defined key | 93 | * update a user defined key |
93 | * - the key's semaphore is write-locked | 94 | * - the key's semaphore is write-locked |
94 | */ | 95 | */ |
95 | int user_update(struct key *key, const void *data, size_t datalen) | 96 | int user_update(struct key *key, struct key_preparsed_payload *prep) |
96 | { | 97 | { |
97 | struct user_key_payload *upayload, *zap; | 98 | struct user_key_payload *upayload, *zap; |
99 | size_t datalen = prep->datalen; | ||
98 | int ret; | 100 | int ret; |
99 | 101 | ||
100 | ret = -EINVAL; | 102 | ret = -EINVAL; |
101 | if (datalen <= 0 || datalen > 32767 || !data) | 103 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
102 | goto error; | 104 | goto error; |
103 | 105 | ||
104 | /* construct a replacement payload */ | 106 | /* construct a replacement payload */ |
@@ -108,7 +110,7 @@ int user_update(struct key *key, const void *data, size_t datalen) | |||
108 | goto error; | 110 | goto error; |
109 | 111 | ||
110 | upayload->datalen = datalen; | 112 | upayload->datalen = datalen; |
111 | memcpy(upayload->data, data, datalen); | 113 | memcpy(upayload->data, prep->data, datalen); |
112 | 114 | ||
113 | /* check the quota and attach the new data */ | 115 | /* check the quota and attach the new data */ |
114 | zap = upayload; | 116 | zap = upayload; |