Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
973c9f4f | 2 | /* Manage a process's keyrings |
1da177e4 | 3 | * |
69664cf1 | 4 | * Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved. |
1da177e4 | 5 | * Written by David Howells (dhowells@redhat.com) |
1da177e4 LT |
6 | */ |
7 | ||
1da177e4 LT |
8 | #include <linux/init.h> |
9 | #include <linux/sched.h> | |
8703e8a4 | 10 | #include <linux/sched/user.h> |
1da177e4 LT |
11 | #include <linux/keyctl.h> |
12 | #include <linux/fs.h> | |
13 | #include <linux/err.h> | |
bb003079 | 14 | #include <linux/mutex.h> |
ee18d64c | 15 | #include <linux/security.h> |
1d1e9756 | 16 | #include <linux/user_namespace.h> |
7c0f6ba6 | 17 | #include <linux/uaccess.h> |
0f44e4d9 | 18 | #include <linux/init_task.h> |
822ad64d | 19 | #include <keys/request_key_auth-type.h> |
1da177e4 LT |
20 | #include "internal.h" |
21 | ||
973c9f4f | 22 | /* Session keyring create vs join semaphore */ |
bb003079 | 23 | static DEFINE_MUTEX(key_session_mutex); |
1da177e4 | 24 | |
973c9f4f | 25 | /* The root user's tracking struct */ |
1da177e4 | 26 | struct key_user root_key_user = { |
ddb99e11 | 27 | .usage = REFCOUNT_INIT(3), |
76181c13 | 28 | .cons_lock = __MUTEX_INITIALIZER(root_key_user.cons_lock), |
6cfd76a2 | 29 | .lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock), |
1da177e4 LT |
30 | .nkeys = ATOMIC_INIT(2), |
31 | .nikeys = ATOMIC_INIT(2), | |
9a56c2db | 32 | .uid = GLOBAL_ROOT_UID, |
1da177e4 LT |
33 | }; |
34 | ||
1da177e4 | 35 | /* |
0f44e4d9 DH |
36 | * Get or create a user register keyring. |
37 | */ | |
38 | static struct key *get_user_register(struct user_namespace *user_ns) | |
39 | { | |
40 | struct key *reg_keyring = READ_ONCE(user_ns->user_keyring_register); | |
41 | ||
42 | if (reg_keyring) | |
43 | return reg_keyring; | |
44 | ||
45 | down_write(&user_ns->keyring_sem); | |
46 | ||
47 | /* Make sure there's a register keyring. It gets owned by the | |
48 | * user_namespace's owner. | |
49 | */ | |
50 | reg_keyring = user_ns->user_keyring_register; | |
51 | if (!reg_keyring) { | |
52 | reg_keyring = keyring_alloc(".user_reg", | |
53 | user_ns->owner, INVALID_GID, | |
028db3e2 LT |
54 | &init_cred, |
55 | KEY_POS_WRITE | KEY_POS_SEARCH | | |
56 | KEY_USR_VIEW | KEY_USR_READ, | |
57 | 0, | |
58 | NULL, NULL); | |
0f44e4d9 DH |
59 | if (!IS_ERR(reg_keyring)) |
60 | smp_store_release(&user_ns->user_keyring_register, | |
61 | reg_keyring); | |
62 | } | |
63 | ||
64 | up_write(&user_ns->keyring_sem); | |
65 | ||
66 | /* We don't return a ref since the keyring is pinned by the user_ns */ | |
67 | return reg_keyring; | |
68 | } | |
69 | ||
70 | /* | |
71 | * Look up the user and user session keyrings for the current process's UID, | |
72 | * creating them if they don't exist. | |
1da177e4 | 73 | */ |
0f44e4d9 DH |
74 | int look_up_user_keyrings(struct key **_user_keyring, |
75 | struct key **_user_session_keyring) | |
1da177e4 | 76 | { |
0f44e4d9 DH |
77 | const struct cred *cred = current_cred(); |
78 | struct user_namespace *user_ns = current_user_ns(); | |
79 | struct key *reg_keyring, *uid_keyring, *session_keyring; | |
028db3e2 | 80 | key_perm_t user_keyring_perm; |
0f44e4d9 DH |
81 | key_ref_t uid_keyring_r, session_keyring_r; |
82 | uid_t uid = from_kuid(user_ns, cred->user->uid); | |
1da177e4 LT |
83 | char buf[20]; |
84 | int ret; | |
85 | ||
028db3e2 LT |
86 | user_keyring_perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL; |
87 | ||
0f44e4d9 | 88 | kenter("%u", uid); |
1da177e4 | 89 | |
0f44e4d9 DH |
90 | reg_keyring = get_user_register(user_ns); |
91 | if (IS_ERR(reg_keyring)) | |
92 | return PTR_ERR(reg_keyring); | |
1da177e4 | 93 | |
0f44e4d9 | 94 | down_write(&user_ns->keyring_sem); |
69664cf1 | 95 | ret = 0; |
1da177e4 | 96 | |
0f44e4d9 DH |
97 | /* Get the user keyring. Note that there may be one in existence |
98 | * already as it may have been pinned by a session, but the user_struct | |
99 | * pointing to it may have been destroyed by setuid. | |
100 | */ | |
101 | snprintf(buf, sizeof(buf), "_uid.%u", uid); | |
102 | uid_keyring_r = keyring_search(make_key_ref(reg_keyring, true), | |
103 | &key_type_keyring, buf, false); | |
104 | kdebug("_uid %p", uid_keyring_r); | |
105 | if (uid_keyring_r == ERR_PTR(-EAGAIN)) { | |
106 | uid_keyring = keyring_alloc(buf, cred->user->uid, INVALID_GID, | |
028db3e2 | 107 | cred, user_keyring_perm, |
0f44e4d9 DH |
108 | KEY_ALLOC_UID_KEYRING | |
109 | KEY_ALLOC_IN_QUOTA, | |
110 | NULL, reg_keyring); | |
69664cf1 | 111 | if (IS_ERR(uid_keyring)) { |
0f44e4d9 DH |
112 | ret = PTR_ERR(uid_keyring); |
113 | goto error; | |
69664cf1 | 114 | } |
0f44e4d9 DH |
115 | } else if (IS_ERR(uid_keyring_r)) { |
116 | ret = PTR_ERR(uid_keyring_r); | |
117 | goto error; | |
118 | } else { | |
119 | uid_keyring = key_ref_to_ptr(uid_keyring_r); | |
120 | } | |
69664cf1 | 121 | |
0f44e4d9 DH |
122 | /* Get a default session keyring (which might also exist already) */ |
123 | snprintf(buf, sizeof(buf), "_uid_ses.%u", uid); | |
124 | session_keyring_r = keyring_search(make_key_ref(reg_keyring, true), | |
125 | &key_type_keyring, buf, false); | |
126 | kdebug("_uid_ses %p", session_keyring_r); | |
127 | if (session_keyring_r == ERR_PTR(-EAGAIN)) { | |
128 | session_keyring = keyring_alloc(buf, cred->user->uid, INVALID_GID, | |
028db3e2 | 129 | cred, user_keyring_perm, |
0f44e4d9 DH |
130 | KEY_ALLOC_UID_KEYRING | |
131 | KEY_ALLOC_IN_QUOTA, | |
132 | NULL, NULL); | |
69664cf1 | 133 | if (IS_ERR(session_keyring)) { |
0f44e4d9 DH |
134 | ret = PTR_ERR(session_keyring); |
135 | goto error_release; | |
69664cf1 DH |
136 | } |
137 | ||
0f44e4d9 DH |
138 | /* We install a link from the user session keyring to |
139 | * the user keyring. | |
140 | */ | |
141 | ret = key_link(session_keyring, uid_keyring); | |
142 | if (ret < 0) | |
143 | goto error_release_session; | |
144 | ||
145 | /* And only then link the user-session keyring to the | |
146 | * register. | |
147 | */ | |
148 | ret = key_link(reg_keyring, session_keyring); | |
149 | if (ret < 0) | |
150 | goto error_release_session; | |
151 | } else if (IS_ERR(session_keyring_r)) { | |
152 | ret = PTR_ERR(session_keyring_r); | |
153 | goto error_release; | |
154 | } else { | |
155 | session_keyring = key_ref_to_ptr(session_keyring_r); | |
1da177e4 LT |
156 | } |
157 | ||
0f44e4d9 DH |
158 | up_write(&user_ns->keyring_sem); |
159 | ||
160 | if (_user_session_keyring) | |
161 | *_user_session_keyring = session_keyring; | |
162 | else | |
163 | key_put(session_keyring); | |
164 | if (_user_keyring) | |
165 | *_user_keyring = uid_keyring; | |
166 | else | |
167 | key_put(uid_keyring); | |
69664cf1 DH |
168 | kleave(" = 0"); |
169 | return 0; | |
1da177e4 | 170 | |
0f44e4d9 | 171 | error_release_session: |
69664cf1 DH |
172 | key_put(session_keyring); |
173 | error_release: | |
174 | key_put(uid_keyring); | |
664cceb0 | 175 | error: |
0f44e4d9 | 176 | up_write(&user_ns->keyring_sem); |
69664cf1 | 177 | kleave(" = %d", ret); |
1da177e4 | 178 | return ret; |
69664cf1 | 179 | } |
1da177e4 | 180 | |
0f44e4d9 DH |
181 | /* |
182 | * Get the user session keyring if it exists, but don't create it if it | |
183 | * doesn't. | |
184 | */ | |
185 | struct key *get_user_session_keyring_rcu(const struct cred *cred) | |
186 | { | |
187 | struct key *reg_keyring = READ_ONCE(cred->user_ns->user_keyring_register); | |
188 | key_ref_t session_keyring_r; | |
189 | char buf[20]; | |
190 | ||
191 | struct keyring_search_context ctx = { | |
192 | .index_key.type = &key_type_keyring, | |
193 | .index_key.description = buf, | |
194 | .cred = cred, | |
195 | .match_data.cmp = key_default_cmp, | |
196 | .match_data.raw_data = buf, | |
197 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | |
198 | .flags = KEYRING_SEARCH_DO_STATE_CHECK, | |
199 | }; | |
200 | ||
201 | if (!reg_keyring) | |
202 | return NULL; | |
203 | ||
204 | ctx.index_key.desc_len = snprintf(buf, sizeof(buf), "_uid_ses.%u", | |
205 | from_kuid(cred->user_ns, | |
206 | cred->user->uid)); | |
207 | ||
208 | session_keyring_r = keyring_search_rcu(make_key_ref(reg_keyring, true), | |
209 | &ctx); | |
210 | if (IS_ERR(session_keyring_r)) | |
211 | return NULL; | |
212 | return key_ref_to_ptr(session_keyring_r); | |
213 | } | |
214 | ||
1da177e4 | 215 | /* |
c9f838d1 EB |
216 | * Install a thread keyring to the given credentials struct if it didn't have |
217 | * one already. This is allowed to overrun the quota. | |
218 | * | |
219 | * Return: 0 if a thread keyring is now present; -errno on failure. | |
1da177e4 | 220 | */ |
d84f4f99 | 221 | int install_thread_keyring_to_cred(struct cred *new) |
1da177e4 | 222 | { |
d84f4f99 | 223 | struct key *keyring; |
1da177e4 | 224 | |
c9f838d1 EB |
225 | if (new->thread_keyring) |
226 | return 0; | |
227 | ||
d84f4f99 | 228 | keyring = keyring_alloc("_tid", new->uid, new->gid, new, |
028db3e2 | 229 | KEY_POS_ALL | KEY_USR_VIEW, |
5ac7eace DH |
230 | KEY_ALLOC_QUOTA_OVERRUN, |
231 | NULL, NULL); | |
d84f4f99 DH |
232 | if (IS_ERR(keyring)) |
233 | return PTR_ERR(keyring); | |
1da177e4 | 234 | |
d84f4f99 DH |
235 | new->thread_keyring = keyring; |
236 | return 0; | |
237 | } | |
1da177e4 | 238 | |
1da177e4 | 239 | /* |
c9f838d1 EB |
240 | * Install a thread keyring to the current task if it didn't have one already. |
241 | * | |
242 | * Return: 0 if a thread keyring is now present; -errno on failure. | |
1da177e4 | 243 | */ |
d84f4f99 | 244 | static int install_thread_keyring(void) |
1da177e4 | 245 | { |
d84f4f99 | 246 | struct cred *new; |
1da177e4 LT |
247 | int ret; |
248 | ||
d84f4f99 DH |
249 | new = prepare_creds(); |
250 | if (!new) | |
251 | return -ENOMEM; | |
1da177e4 | 252 | |
d84f4f99 DH |
253 | ret = install_thread_keyring_to_cred(new); |
254 | if (ret < 0) { | |
255 | abort_creds(new); | |
256 | return ret; | |
1da177e4 LT |
257 | } |
258 | ||
d84f4f99 DH |
259 | return commit_creds(new); |
260 | } | |
1da177e4 | 261 | |
d84f4f99 | 262 | /* |
c9f838d1 EB |
263 | * Install a process keyring to the given credentials struct if it didn't have |
264 | * one already. This is allowed to overrun the quota. | |
973c9f4f | 265 | * |
c9f838d1 | 266 | * Return: 0 if a process keyring is now present; -errno on failure. |
d84f4f99 DH |
267 | */ |
268 | int install_process_keyring_to_cred(struct cred *new) | |
269 | { | |
270 | struct key *keyring; | |
1da177e4 | 271 | |
3a50597d | 272 | if (new->process_keyring) |
c9f838d1 | 273 | return 0; |
d84f4f99 | 274 | |
96b5c8fe | 275 | keyring = keyring_alloc("_pid", new->uid, new->gid, new, |
028db3e2 | 276 | KEY_POS_ALL | KEY_USR_VIEW, |
5ac7eace DH |
277 | KEY_ALLOC_QUOTA_OVERRUN, |
278 | NULL, NULL); | |
d84f4f99 DH |
279 | if (IS_ERR(keyring)) |
280 | return PTR_ERR(keyring); | |
281 | ||
3a50597d DH |
282 | new->process_keyring = keyring; |
283 | return 0; | |
d84f4f99 | 284 | } |
1da177e4 | 285 | |
1da177e4 | 286 | /* |
c9f838d1 | 287 | * Install a process keyring to the current task if it didn't have one already. |
973c9f4f | 288 | * |
c9f838d1 | 289 | * Return: 0 if a process keyring is now present; -errno on failure. |
1da177e4 | 290 | */ |
d84f4f99 | 291 | static int install_process_keyring(void) |
1da177e4 | 292 | { |
d84f4f99 | 293 | struct cred *new; |
1da177e4 LT |
294 | int ret; |
295 | ||
d84f4f99 DH |
296 | new = prepare_creds(); |
297 | if (!new) | |
298 | return -ENOMEM; | |
1da177e4 | 299 | |
d84f4f99 DH |
300 | ret = install_process_keyring_to_cred(new); |
301 | if (ret < 0) { | |
302 | abort_creds(new); | |
c9f838d1 | 303 | return ret; |
1da177e4 LT |
304 | } |
305 | ||
d84f4f99 DH |
306 | return commit_creds(new); |
307 | } | |
1da177e4 | 308 | |
1da177e4 | 309 | /* |
c9f838d1 EB |
310 | * Install the given keyring as the session keyring of the given credentials |
311 | * struct, replacing the existing one if any. If the given keyring is NULL, | |
312 | * then install a new anonymous session keyring. | |
5c7e372c | 313 | * @cred can not be in use by any task yet. |
c9f838d1 EB |
314 | * |
315 | * Return: 0 on success; -errno on failure. | |
1da177e4 | 316 | */ |
685bfd2c | 317 | int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) |
1da177e4 | 318 | { |
7e047ef5 | 319 | unsigned long flags; |
1da177e4 | 320 | struct key *old; |
1a26feb9 DH |
321 | |
322 | might_sleep(); | |
1da177e4 LT |
323 | |
324 | /* create an empty session keyring */ | |
325 | if (!keyring) { | |
7e047ef5 | 326 | flags = KEY_ALLOC_QUOTA_OVERRUN; |
3a50597d | 327 | if (cred->session_keyring) |
7e047ef5 DH |
328 | flags = KEY_ALLOC_IN_QUOTA; |
329 | ||
96b5c8fe | 330 | keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred, |
028db3e2 LT |
331 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ, |
332 | flags, NULL, NULL); | |
1a26feb9 DH |
333 | if (IS_ERR(keyring)) |
334 | return PTR_ERR(keyring); | |
d84f4f99 | 335 | } else { |
ccc3e6d9 | 336 | __key_get(keyring); |
1da177e4 LT |
337 | } |
338 | ||
339 | /* install the keyring */ | |
3a50597d | 340 | old = cred->session_keyring; |
5c7e372c | 341 | cred->session_keyring = keyring; |
3a50597d DH |
342 | |
343 | if (old) | |
1a26feb9 | 344 | key_put(old); |
1da177e4 | 345 | |
1a26feb9 | 346 | return 0; |
d84f4f99 | 347 | } |
1da177e4 | 348 | |
1da177e4 | 349 | /* |
c9f838d1 EB |
350 | * Install the given keyring as the session keyring of the current task, |
351 | * replacing the existing one if any. If the given keyring is NULL, then | |
352 | * install a new anonymous session keyring. | |
353 | * | |
354 | * Return: 0 on success; -errno on failure. | |
1da177e4 | 355 | */ |
d84f4f99 | 356 | static int install_session_keyring(struct key *keyring) |
1da177e4 | 357 | { |
d84f4f99 DH |
358 | struct cred *new; |
359 | int ret; | |
1da177e4 | 360 | |
d84f4f99 DH |
361 | new = prepare_creds(); |
362 | if (!new) | |
363 | return -ENOMEM; | |
1da177e4 | 364 | |
99599537 | 365 | ret = install_session_keyring_to_cred(new, keyring); |
d84f4f99 DH |
366 | if (ret < 0) { |
367 | abort_creds(new); | |
368 | return ret; | |
369 | } | |
1da177e4 | 370 | |
d84f4f99 DH |
371 | return commit_creds(new); |
372 | } | |
1da177e4 | 373 | |
1da177e4 | 374 | /* |
973c9f4f | 375 | * Handle the fsuid changing. |
1da177e4 | 376 | */ |
2e21865f | 377 | void key_fsuid_changed(struct cred *new_cred) |
1da177e4 LT |
378 | { |
379 | /* update the ownership of the thread keyring */ | |
2e21865f DH |
380 | if (new_cred->thread_keyring) { |
381 | down_write(&new_cred->thread_keyring->sem); | |
382 | new_cred->thread_keyring->uid = new_cred->fsuid; | |
383 | up_write(&new_cred->thread_keyring->sem); | |
1da177e4 | 384 | } |
a8b17ed0 | 385 | } |
1da177e4 | 386 | |
1da177e4 | 387 | /* |
973c9f4f | 388 | * Handle the fsgid changing. |
1da177e4 | 389 | */ |
2e21865f | 390 | void key_fsgid_changed(struct cred *new_cred) |
1da177e4 LT |
391 | { |
392 | /* update the ownership of the thread keyring */ | |
2e21865f DH |
393 | if (new_cred->thread_keyring) { |
394 | down_write(&new_cred->thread_keyring->sem); | |
395 | new_cred->thread_keyring->gid = new_cred->fsgid; | |
396 | up_write(&new_cred->thread_keyring->sem); | |
1da177e4 | 397 | } |
a8b17ed0 | 398 | } |
1da177e4 | 399 | |
1da177e4 | 400 | /* |
973c9f4f | 401 | * Search the process keyrings attached to the supplied cred for the first |
e59428f7 DH |
402 | * matching key under RCU conditions (the caller must be holding the RCU read |
403 | * lock). | |
973c9f4f DH |
404 | * |
405 | * The search criteria are the type and the match function. The description is | |
406 | * given to the match function as a parameter, but doesn't otherwise influence | |
407 | * the search. Typically the match function will compare the description | |
408 | * parameter to the key's description. | |
409 | * | |
410 | * This can only search keyrings that grant Search permission to the supplied | |
411 | * credentials. Keyrings linked to searched keyrings will also be searched if | |
412 | * they grant Search permission too. Keys can only be found if they grant | |
413 | * Search permission to the credentials. | |
414 | * | |
415 | * Returns a pointer to the key with the key usage count incremented if | |
416 | * successful, -EAGAIN if we didn't find any matching key or -ENOKEY if we only | |
417 | * matched negative keys. | |
418 | * | |
419 | * In the case of a successful return, the possession attribute is set on the | |
420 | * returned key reference. | |
1da177e4 | 421 | */ |
e59428f7 | 422 | key_ref_t search_cred_keyrings_rcu(struct keyring_search_context *ctx) |
1da177e4 | 423 | { |
0f44e4d9 | 424 | struct key *user_session; |
b5f545c8 | 425 | key_ref_t key_ref, ret, err; |
0b9dc6c9 | 426 | const struct cred *cred = ctx->cred; |
1da177e4 LT |
427 | |
428 | /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were | |
429 | * searchable, but we failed to find a key or we found a negative key; | |
430 | * otherwise we want to return a sample error (probably -EACCES) if | |
431 | * none of the keyrings were searchable | |
432 | * | |
433 | * in terms of priority: success > -ENOKEY > -EAGAIN > other error | |
434 | */ | |
664cceb0 | 435 | key_ref = NULL; |
1da177e4 LT |
436 | ret = NULL; |
437 | err = ERR_PTR(-EAGAIN); | |
438 | ||
439 | /* search the thread keyring first */ | |
0b9dc6c9 | 440 | if (cred->thread_keyring) { |
e59428f7 | 441 | key_ref = keyring_search_rcu( |
0b9dc6c9 | 442 | make_key_ref(cred->thread_keyring, 1), ctx); |
664cceb0 | 443 | if (!IS_ERR(key_ref)) |
1da177e4 LT |
444 | goto found; |
445 | ||
664cceb0 | 446 | switch (PTR_ERR(key_ref)) { |
1da177e4 | 447 | case -EAGAIN: /* no key */ |
1da177e4 | 448 | case -ENOKEY: /* negative key */ |
664cceb0 | 449 | ret = key_ref; |
1da177e4 LT |
450 | break; |
451 | default: | |
664cceb0 | 452 | err = key_ref; |
1da177e4 LT |
453 | break; |
454 | } | |
455 | } | |
456 | ||
457 | /* search the process keyring second */ | |
0b9dc6c9 | 458 | if (cred->process_keyring) { |
e59428f7 | 459 | key_ref = keyring_search_rcu( |
0b9dc6c9 | 460 | make_key_ref(cred->process_keyring, 1), ctx); |
664cceb0 | 461 | if (!IS_ERR(key_ref)) |
1da177e4 LT |
462 | goto found; |
463 | ||
664cceb0 | 464 | switch (PTR_ERR(key_ref)) { |
1da177e4 | 465 | case -EAGAIN: /* no key */ |
fe9453a1 DH |
466 | if (ret) |
467 | break; | |
df561f66 | 468 | fallthrough; |
1da177e4 | 469 | case -ENOKEY: /* negative key */ |
664cceb0 | 470 | ret = key_ref; |
1da177e4 LT |
471 | break; |
472 | default: | |
664cceb0 | 473 | err = key_ref; |
1da177e4 LT |
474 | break; |
475 | } | |
476 | } | |
477 | ||
3e30148c | 478 | /* search the session keyring */ |
0b9dc6c9 | 479 | if (cred->session_keyring) { |
e59428f7 | 480 | key_ref = keyring_search_rcu( |
0b9dc6c9 | 481 | make_key_ref(cred->session_keyring, 1), ctx); |
3e30148c | 482 | |
664cceb0 | 483 | if (!IS_ERR(key_ref)) |
3e30148c DH |
484 | goto found; |
485 | ||
664cceb0 | 486 | switch (PTR_ERR(key_ref)) { |
3e30148c DH |
487 | case -EAGAIN: /* no key */ |
488 | if (ret) | |
489 | break; | |
df561f66 | 490 | fallthrough; |
3e30148c | 491 | case -ENOKEY: /* negative key */ |
664cceb0 | 492 | ret = key_ref; |
3e30148c DH |
493 | break; |
494 | default: | |
664cceb0 | 495 | err = key_ref; |
3e30148c DH |
496 | break; |
497 | } | |
b5f545c8 DH |
498 | } |
499 | /* or search the user-session keyring */ | |
0f44e4d9 DH |
500 | else if ((user_session = get_user_session_keyring_rcu(cred))) { |
501 | key_ref = keyring_search_rcu(make_key_ref(user_session, 1), | |
502 | ctx); | |
503 | key_put(user_session); | |
504 | ||
664cceb0 | 505 | if (!IS_ERR(key_ref)) |
3e30148c DH |
506 | goto found; |
507 | ||
664cceb0 | 508 | switch (PTR_ERR(key_ref)) { |
3e30148c DH |
509 | case -EAGAIN: /* no key */ |
510 | if (ret) | |
511 | break; | |
df561f66 | 512 | fallthrough; |
3e30148c | 513 | case -ENOKEY: /* negative key */ |
664cceb0 | 514 | ret = key_ref; |
3e30148c DH |
515 | break; |
516 | default: | |
664cceb0 | 517 | err = key_ref; |
3e30148c DH |
518 | break; |
519 | } | |
8589b4e0 | 520 | } |
b5f545c8 | 521 | |
927942aa DH |
522 | /* no key - decide on the error we're going to go for */ |
523 | key_ref = ret ? ret : err; | |
524 | ||
525 | found: | |
526 | return key_ref; | |
527 | } | |
528 | ||
927942aa | 529 | /* |
973c9f4f DH |
530 | * Search the process keyrings attached to the supplied cred for the first |
531 | * matching key in the manner of search_my_process_keyrings(), but also search | |
532 | * the keys attached to the assumed authorisation key using its credentials if | |
533 | * one is available. | |
534 | * | |
e59428f7 DH |
535 | * The caller must be holding the RCU read lock. |
536 | * | |
537 | * Return same as search_cred_keyrings_rcu(). | |
927942aa | 538 | */ |
e59428f7 | 539 | key_ref_t search_process_keyrings_rcu(struct keyring_search_context *ctx) |
927942aa DH |
540 | { |
541 | struct request_key_auth *rka; | |
542 | key_ref_t key_ref, ret = ERR_PTR(-EACCES), err; | |
543 | ||
e59428f7 | 544 | key_ref = search_cred_keyrings_rcu(ctx); |
927942aa DH |
545 | if (!IS_ERR(key_ref)) |
546 | goto found; | |
547 | err = key_ref; | |
548 | ||
b5f545c8 DH |
549 | /* if this process has an instantiation authorisation key, then we also |
550 | * search the keyrings of the process mentioned there | |
551 | * - we don't permit access to request_key auth keys via this method | |
552 | */ | |
4bdf0bc3 DH |
553 | if (ctx->cred->request_key_auth && |
554 | ctx->cred == current_cred() && | |
555 | ctx->index_key.type != &key_type_request_key_auth | |
b5f545c8 | 556 | ) { |
4bdf0bc3 DH |
557 | const struct cred *cred = ctx->cred; |
558 | ||
e59428f7 | 559 | if (key_validate(cred->request_key_auth) == 0) { |
146aa8b1 | 560 | rka = ctx->cred->request_key_auth->payload.data[0]; |
b5f545c8 | 561 | |
e59428f7 | 562 | //// was search_process_keyrings() [ie. recursive] |
4bdf0bc3 | 563 | ctx->cred = rka->cred; |
e59428f7 | 564 | key_ref = search_cred_keyrings_rcu(ctx); |
4bdf0bc3 | 565 | ctx->cred = cred; |
1da177e4 | 566 | |
04c567d9 DH |
567 | if (!IS_ERR(key_ref)) |
568 | goto found; | |
927942aa | 569 | ret = key_ref; |
3e30148c | 570 | } |
1da177e4 LT |
571 | } |
572 | ||
573 | /* no key - decide on the error we're going to go for */ | |
927942aa DH |
574 | if (err == ERR_PTR(-ENOKEY) || ret == ERR_PTR(-ENOKEY)) |
575 | key_ref = ERR_PTR(-ENOKEY); | |
576 | else if (err == ERR_PTR(-EACCES)) | |
577 | key_ref = ret; | |
578 | else | |
579 | key_ref = err; | |
1da177e4 | 580 | |
3e30148c | 581 | found: |
664cceb0 | 582 | return key_ref; |
a8b17ed0 | 583 | } |
664cceb0 | 584 | /* |
973c9f4f | 585 | * See if the key we're looking at is the target key. |
664cceb0 | 586 | */ |
0c903ab6 DH |
587 | bool lookup_user_key_possessed(const struct key *key, |
588 | const struct key_match_data *match_data) | |
664cceb0 | 589 | { |
46291959 | 590 | return key == match_data->raw_data; |
a8b17ed0 | 591 | } |
664cceb0 | 592 | |
1da177e4 | 593 | /* |
973c9f4f DH |
594 | * Look up a key ID given us by userspace with a given permissions mask to get |
595 | * the key it refers to. | |
596 | * | |
597 | * Flags can be passed to request that special keyrings be created if referred | |
598 | * to directly, to permit partially constructed keys to be found and to skip | |
599 | * validity and permission checks on the found key. | |
600 | * | |
601 | * Returns a pointer to the key with an incremented usage count if successful; | |
602 | * -EINVAL if the key ID is invalid; -ENOKEY if the key ID does not correspond | |
603 | * to a key or the best found key was a negative key; -EKEYREVOKED or | |
604 | * -EKEYEXPIRED if the best found key was revoked or expired; -EACCES if the | |
605 | * found key doesn't grant the requested permit or the LSM denied access to it; | |
606 | * or -ENOMEM if a special keyring couldn't be created. | |
607 | * | |
608 | * In the case of a successful return, the possession attribute is set on the | |
609 | * returned key reference. | |
1da177e4 | 610 | */ |
5593122e | 611 | key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, |
8c0637e9 | 612 | enum key_need_perm need_perm) |
1da177e4 | 613 | { |
4bdf0bc3 | 614 | struct keyring_search_context ctx = { |
46291959 DH |
615 | .match_data.cmp = lookup_user_key_possessed, |
616 | .match_data.lookup_type = KEYRING_SEARCH_LOOKUP_DIRECT, | |
dcf49dbc DH |
617 | .flags = (KEYRING_SEARCH_NO_STATE_CHECK | |
618 | KEYRING_SEARCH_RECURSE), | |
4bdf0bc3 | 619 | }; |
8bbf4976 | 620 | struct request_key_auth *rka; |
0f44e4d9 | 621 | struct key *key, *user_session; |
b6dff3ec | 622 | key_ref_t key_ref, skey_ref; |
1da177e4 LT |
623 | int ret; |
624 | ||
bb952bb9 | 625 | try_again: |
4bdf0bc3 | 626 | ctx.cred = get_current_cred(); |
664cceb0 | 627 | key_ref = ERR_PTR(-ENOKEY); |
1da177e4 LT |
628 | |
629 | switch (id) { | |
630 | case KEY_SPEC_THREAD_KEYRING: | |
4bdf0bc3 | 631 | if (!ctx.cred->thread_keyring) { |
5593122e | 632 | if (!(lflags & KEY_LOOKUP_CREATE)) |
1da177e4 LT |
633 | goto error; |
634 | ||
8bbf4976 | 635 | ret = install_thread_keyring(); |
1da177e4 | 636 | if (ret < 0) { |
4d09ec0f | 637 | key_ref = ERR_PTR(ret); |
1da177e4 LT |
638 | goto error; |
639 | } | |
bb952bb9 | 640 | goto reget_creds; |
1da177e4 LT |
641 | } |
642 | ||
4bdf0bc3 | 643 | key = ctx.cred->thread_keyring; |
ccc3e6d9 | 644 | __key_get(key); |
664cceb0 | 645 | key_ref = make_key_ref(key, 1); |
1da177e4 LT |
646 | break; |
647 | ||
648 | case KEY_SPEC_PROCESS_KEYRING: | |
4bdf0bc3 | 649 | if (!ctx.cred->process_keyring) { |
5593122e | 650 | if (!(lflags & KEY_LOOKUP_CREATE)) |
1da177e4 LT |
651 | goto error; |
652 | ||
8bbf4976 | 653 | ret = install_process_keyring(); |
1da177e4 | 654 | if (ret < 0) { |
4d09ec0f | 655 | key_ref = ERR_PTR(ret); |
1da177e4 LT |
656 | goto error; |
657 | } | |
bb952bb9 | 658 | goto reget_creds; |
1da177e4 LT |
659 | } |
660 | ||
4bdf0bc3 | 661 | key = ctx.cred->process_keyring; |
ccc3e6d9 | 662 | __key_get(key); |
664cceb0 | 663 | key_ref = make_key_ref(key, 1); |
1da177e4 LT |
664 | break; |
665 | ||
666 | case KEY_SPEC_SESSION_KEYRING: | |
4bdf0bc3 | 667 | if (!ctx.cred->session_keyring) { |
1da177e4 LT |
668 | /* always install a session keyring upon access if one |
669 | * doesn't exist yet */ | |
0f44e4d9 | 670 | ret = look_up_user_keyrings(NULL, &user_session); |
69664cf1 DH |
671 | if (ret < 0) |
672 | goto error; | |
3ecf1b4f DH |
673 | if (lflags & KEY_LOOKUP_CREATE) |
674 | ret = join_session_keyring(NULL); | |
675 | else | |
0f44e4d9 | 676 | ret = install_session_keyring(user_session); |
d84f4f99 | 677 | |
0f44e4d9 | 678 | key_put(user_session); |
1da177e4 LT |
679 | if (ret < 0) |
680 | goto error; | |
bb952bb9 | 681 | goto reget_creds; |
0f44e4d9 DH |
682 | } else if (test_bit(KEY_FLAG_UID_KEYRING, |
683 | &ctx.cred->session_keyring->flags) && | |
3ecf1b4f DH |
684 | lflags & KEY_LOOKUP_CREATE) { |
685 | ret = join_session_keyring(NULL); | |
686 | if (ret < 0) | |
687 | goto error; | |
688 | goto reget_creds; | |
1da177e4 LT |
689 | } |
690 | ||
5c7e372c | 691 | key = ctx.cred->session_keyring; |
ccc3e6d9 | 692 | __key_get(key); |
664cceb0 | 693 | key_ref = make_key_ref(key, 1); |
1da177e4 LT |
694 | break; |
695 | ||
696 | case KEY_SPEC_USER_KEYRING: | |
0f44e4d9 DH |
697 | ret = look_up_user_keyrings(&key, NULL); |
698 | if (ret < 0) | |
699 | goto error; | |
664cceb0 | 700 | key_ref = make_key_ref(key, 1); |
1da177e4 LT |
701 | break; |
702 | ||
703 | case KEY_SPEC_USER_SESSION_KEYRING: | |
0f44e4d9 DH |
704 | ret = look_up_user_keyrings(NULL, &key); |
705 | if (ret < 0) | |
706 | goto error; | |
664cceb0 | 707 | key_ref = make_key_ref(key, 1); |
1da177e4 LT |
708 | break; |
709 | ||
710 | case KEY_SPEC_GROUP_KEYRING: | |
711 | /* group keyrings are not yet supported */ | |
4d09ec0f | 712 | key_ref = ERR_PTR(-EINVAL); |
1da177e4 LT |
713 | goto error; |
714 | ||
b5f545c8 | 715 | case KEY_SPEC_REQKEY_AUTH_KEY: |
4bdf0bc3 | 716 | key = ctx.cred->request_key_auth; |
b5f545c8 DH |
717 | if (!key) |
718 | goto error; | |
719 | ||
ccc3e6d9 | 720 | __key_get(key); |
b5f545c8 DH |
721 | key_ref = make_key_ref(key, 1); |
722 | break; | |
723 | ||
8bbf4976 | 724 | case KEY_SPEC_REQUESTOR_KEYRING: |
4bdf0bc3 | 725 | if (!ctx.cred->request_key_auth) |
8bbf4976 DH |
726 | goto error; |
727 | ||
4bdf0bc3 | 728 | down_read(&ctx.cred->request_key_auth->sem); |
f67dabbd | 729 | if (test_bit(KEY_FLAG_REVOKED, |
4bdf0bc3 | 730 | &ctx.cred->request_key_auth->flags)) { |
8bbf4976 DH |
731 | key_ref = ERR_PTR(-EKEYREVOKED); |
732 | key = NULL; | |
733 | } else { | |
146aa8b1 | 734 | rka = ctx.cred->request_key_auth->payload.data[0]; |
8bbf4976 | 735 | key = rka->dest_keyring; |
ccc3e6d9 | 736 | __key_get(key); |
8bbf4976 | 737 | } |
4bdf0bc3 | 738 | up_read(&ctx.cred->request_key_auth->sem); |
8bbf4976 DH |
739 | if (!key) |
740 | goto error; | |
741 | key_ref = make_key_ref(key, 1); | |
742 | break; | |
743 | ||
1da177e4 | 744 | default: |
664cceb0 | 745 | key_ref = ERR_PTR(-EINVAL); |
1da177e4 LT |
746 | if (id < 1) |
747 | goto error; | |
748 | ||
749 | key = key_lookup(id); | |
664cceb0 | 750 | if (IS_ERR(key)) { |
e231c2ee | 751 | key_ref = ERR_CAST(key); |
1da177e4 | 752 | goto error; |
664cceb0 DH |
753 | } |
754 | ||
755 | key_ref = make_key_ref(key, 0); | |
756 | ||
757 | /* check to see if we possess the key */ | |
47546208 | 758 | ctx.index_key = key->index_key; |
46291959 | 759 | ctx.match_data.raw_data = key; |
4bdf0bc3 | 760 | kdebug("check possessed"); |
e59428f7 DH |
761 | rcu_read_lock(); |
762 | skey_ref = search_process_keyrings_rcu(&ctx); | |
763 | rcu_read_unlock(); | |
4bdf0bc3 | 764 | kdebug("possessed=%p", skey_ref); |
664cceb0 DH |
765 | |
766 | if (!IS_ERR(skey_ref)) { | |
767 | key_put(key); | |
768 | key_ref = skey_ref; | |
769 | } | |
770 | ||
1da177e4 LT |
771 | break; |
772 | } | |
773 | ||
5593122e DH |
774 | /* unlink does not use the nominated key in any way, so can skip all |
775 | * the permission checks as it is only concerned with the keyring */ | |
8c0637e9 DH |
776 | if (need_perm != KEY_NEED_UNLINK) { |
777 | if (!(lflags & KEY_LOOKUP_PARTIAL)) { | |
778 | ret = wait_for_key_construction(key, true); | |
779 | switch (ret) { | |
780 | case -ERESTARTSYS: | |
781 | goto invalid_key; | |
782 | default: | |
783 | if (need_perm != KEY_AUTHTOKEN_OVERRIDE && | |
784 | need_perm != KEY_DEFER_PERM_CHECK) | |
785 | goto invalid_key; | |
786 | case 0: | |
787 | break; | |
788 | } | |
789 | } else if (need_perm != KEY_DEFER_PERM_CHECK) { | |
790 | ret = key_validate(key); | |
791 | if (ret < 0) | |
76181c13 | 792 | goto invalid_key; |
76181c13 | 793 | } |
8c0637e9 DH |
794 | |
795 | ret = -EIO; | |
796 | if (!(lflags & KEY_LOOKUP_PARTIAL) && | |
797 | key_read_state(key) == KEY_IS_UNINSTANTIATED) | |
1da177e4 LT |
798 | goto invalid_key; |
799 | } | |
800 | ||
3e30148c | 801 | /* check the permissions */ |
8c0637e9 | 802 | ret = key_task_permission(key_ref, ctx.cred, need_perm); |
028db3e2 LT |
803 | if (ret < 0) |
804 | goto invalid_key; | |
1da177e4 | 805 | |
074d5898 | 806 | key->last_used_at = ktime_get_real_seconds(); |
31d5a79d | 807 | |
664cceb0 | 808 | error: |
4bdf0bc3 | 809 | put_cred(ctx.cred); |
664cceb0 | 810 | return key_ref; |
1da177e4 | 811 | |
664cceb0 DH |
812 | invalid_key: |
813 | key_ref_put(key_ref); | |
814 | key_ref = ERR_PTR(ret); | |
1da177e4 LT |
815 | goto error; |
816 | ||
bb952bb9 DH |
817 | /* if we attempted to install a keyring, then it may have caused new |
818 | * creds to be installed */ | |
819 | reget_creds: | |
4bdf0bc3 | 820 | put_cred(ctx.cred); |
bb952bb9 | 821 | goto try_again; |
a8b17ed0 | 822 | } |
76ef5e17 | 823 | EXPORT_SYMBOL(lookup_user_key); |
bb952bb9 | 824 | |
1da177e4 | 825 | /* |
973c9f4f DH |
826 | * Join the named keyring as the session keyring if possible else attempt to |
827 | * create a new one of that name and join that. | |
828 | * | |
829 | * If the name is NULL, an empty anonymous keyring will be installed as the | |
830 | * session keyring. | |
831 | * | |
832 | * Named session keyrings are joined with a semaphore held to prevent the | |
833 | * keyrings from going away whilst the attempt is made to going them and also | |
834 | * to prevent a race in creating compatible session keyrings. | |
1da177e4 LT |
835 | */ |
836 | long join_session_keyring(const char *name) | |
837 | { | |
d84f4f99 DH |
838 | const struct cred *old; |
839 | struct cred *new; | |
1da177e4 | 840 | struct key *keyring; |
d84f4f99 DH |
841 | long ret, serial; |
842 | ||
d84f4f99 DH |
843 | new = prepare_creds(); |
844 | if (!new) | |
845 | return -ENOMEM; | |
846 | old = current_cred(); | |
1da177e4 LT |
847 | |
848 | /* if no name is provided, install an anonymous keyring */ | |
849 | if (!name) { | |
d84f4f99 | 850 | ret = install_session_keyring_to_cred(new, NULL); |
1da177e4 LT |
851 | if (ret < 0) |
852 | goto error; | |
853 | ||
3a50597d | 854 | serial = new->session_keyring->serial; |
d84f4f99 DH |
855 | ret = commit_creds(new); |
856 | if (ret == 0) | |
857 | ret = serial; | |
858 | goto okay; | |
1da177e4 LT |
859 | } |
860 | ||
861 | /* allow the user to join or create a named keyring */ | |
bb003079 | 862 | mutex_lock(&key_session_mutex); |
1da177e4 LT |
863 | |
864 | /* look for an existing keyring of this name */ | |
69664cf1 | 865 | keyring = find_keyring_by_name(name, false); |
1da177e4 LT |
866 | if (PTR_ERR(keyring) == -ENOKEY) { |
867 | /* not found - try and create a new one */ | |
96b5c8fe | 868 | keyring = keyring_alloc( |
028db3e2 LT |
869 | name, old->uid, old->gid, old, |
870 | KEY_POS_ALL | KEY_USR_VIEW | KEY_USR_READ | KEY_USR_LINK, | |
5ac7eace | 871 | KEY_ALLOC_IN_QUOTA, NULL, NULL); |
1da177e4 LT |
872 | if (IS_ERR(keyring)) { |
873 | ret = PTR_ERR(keyring); | |
bcf945d3 | 874 | goto error2; |
1da177e4 | 875 | } |
d84f4f99 | 876 | } else if (IS_ERR(keyring)) { |
1da177e4 LT |
877 | ret = PTR_ERR(keyring); |
878 | goto error2; | |
3a50597d DH |
879 | } else if (keyring == new->session_keyring) { |
880 | ret = 0; | |
d636bd9f | 881 | goto error3; |
1da177e4 LT |
882 | } |
883 | ||
884 | /* we've got a keyring - now to install it */ | |
d84f4f99 | 885 | ret = install_session_keyring_to_cred(new, keyring); |
1da177e4 | 886 | if (ret < 0) |
d636bd9f | 887 | goto error3; |
1da177e4 | 888 | |
d84f4f99 DH |
889 | commit_creds(new); |
890 | mutex_unlock(&key_session_mutex); | |
891 | ||
1da177e4 LT |
892 | ret = keyring->serial; |
893 | key_put(keyring); | |
d84f4f99 DH |
894 | okay: |
895 | return ret; | |
1da177e4 | 896 | |
d636bd9f EB |
897 | error3: |
898 | key_put(keyring); | |
664cceb0 | 899 | error2: |
bb003079 | 900 | mutex_unlock(&key_session_mutex); |
664cceb0 | 901 | error: |
d84f4f99 | 902 | abort_creds(new); |
1da177e4 | 903 | return ret; |
d84f4f99 | 904 | } |
ee18d64c DH |
905 | |
906 | /* | |
973c9f4f DH |
907 | * Replace a process's session keyring on behalf of one of its children when |
908 | * the target process is about to resume userspace execution. | |
ee18d64c | 909 | */ |
67d12145 | 910 | void key_change_session_keyring(struct callback_head *twork) |
ee18d64c | 911 | { |
413cd3d9 | 912 | const struct cred *old = current_cred(); |
67d12145 | 913 | struct cred *new = container_of(twork, struct cred, rcu); |
ee18d64c | 914 | |
413cd3d9 ON |
915 | if (unlikely(current->flags & PF_EXITING)) { |
916 | put_cred(new); | |
ee18d64c | 917 | return; |
413cd3d9 | 918 | } |
ee18d64c | 919 | |
ee18d64c DH |
920 | new-> uid = old-> uid; |
921 | new-> euid = old-> euid; | |
922 | new-> suid = old-> suid; | |
923 | new->fsuid = old->fsuid; | |
924 | new-> gid = old-> gid; | |
925 | new-> egid = old-> egid; | |
926 | new-> sgid = old-> sgid; | |
927 | new->fsgid = old->fsgid; | |
928 | new->user = get_uid(old->user); | |
ba0e3427 | 929 | new->user_ns = get_user_ns(old->user_ns); |
ee18d64c DH |
930 | new->group_info = get_group_info(old->group_info); |
931 | ||
932 | new->securebits = old->securebits; | |
933 | new->cap_inheritable = old->cap_inheritable; | |
934 | new->cap_permitted = old->cap_permitted; | |
935 | new->cap_effective = old->cap_effective; | |
58319057 | 936 | new->cap_ambient = old->cap_ambient; |
ee18d64c DH |
937 | new->cap_bset = old->cap_bset; |
938 | ||
939 | new->jit_keyring = old->jit_keyring; | |
940 | new->thread_keyring = key_get(old->thread_keyring); | |
3a50597d | 941 | new->process_keyring = key_get(old->process_keyring); |
ee18d64c DH |
942 | |
943 | security_transfer_creds(new, old); | |
944 | ||
945 | commit_creds(new); | |
946 | } | |
c124bde2 MZ |
947 | |
948 | /* | |
949 | * Make sure that root's user and user-session keyrings exist. | |
950 | */ | |
951 | static int __init init_root_keyring(void) | |
952 | { | |
0f44e4d9 | 953 | return look_up_user_keyrings(NULL, NULL); |
c124bde2 MZ |
954 | } |
955 | ||
956 | late_initcall(init_root_keyring); |