Blame view
security/keys/process_keys.c
20.6 KB
973c9f4f4 KEYS: Fix up comm... |
1 |
/* Manage a process's keyrings |
1da177e4c Linux-2.6.12-rc2 |
2 |
* |
69664cf16 keys: don't gener... |
3 |
* Copyright (C) 2004-2005, 2008 Red Hat, Inc. All Rights Reserved. |
1da177e4c Linux-2.6.12-rc2 |
4 5 6 7 8 9 10 11 12 13 14 |
* Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include <linux/module.h> #include <linux/init.h> #include <linux/sched.h> |
1da177e4c Linux-2.6.12-rc2 |
15 16 17 |
#include <linux/keyctl.h> #include <linux/fs.h> #include <linux/err.h> |
bb0030797 [PATCH] sem2mutex... |
18 |
#include <linux/mutex.h> |
ee18d64c1 KEYS: Add a keyct... |
19 |
#include <linux/security.h> |
1d1e97562 keys: distinguish... |
20 |
#include <linux/user_namespace.h> |
1da177e4c Linux-2.6.12-rc2 |
21 22 |
#include <asm/uaccess.h> #include "internal.h" |
973c9f4f4 KEYS: Fix up comm... |
23 |
/* Session keyring create vs join semaphore */ |
bb0030797 [PATCH] sem2mutex... |
24 |
static DEFINE_MUTEX(key_session_mutex); |
1da177e4c Linux-2.6.12-rc2 |
25 |
|
973c9f4f4 KEYS: Fix up comm... |
26 |
/* User keyring creation semaphore */ |
69664cf16 keys: don't gener... |
27 |
static DEFINE_MUTEX(key_user_keyring_mutex); |
973c9f4f4 KEYS: Fix up comm... |
28 |
/* The root user's tracking struct */ |
1da177e4c Linux-2.6.12-rc2 |
29 30 |
struct key_user root_key_user = { .usage = ATOMIC_INIT(3), |
76181c134 KEYS: Make reques... |
31 |
.cons_lock = __MUTEX_INITIALIZER(root_key_user.cons_lock), |
6cfd76a26 [PATCH] lockdep: ... |
32 |
.lock = __SPIN_LOCK_UNLOCKED(root_key_user.lock), |
1da177e4c Linux-2.6.12-rc2 |
33 34 35 |
.nkeys = ATOMIC_INIT(2), .nikeys = ATOMIC_INIT(2), .uid = 0, |
1d1e97562 keys: distinguish... |
36 |
.user_ns = &init_user_ns, |
1da177e4c Linux-2.6.12-rc2 |
37 |
}; |
1da177e4c Linux-2.6.12-rc2 |
38 |
/* |
973c9f4f4 KEYS: Fix up comm... |
39 |
* Install the user and user session keyrings for the current process's UID. |
1da177e4c Linux-2.6.12-rc2 |
40 |
*/ |
8bbf4976b KEYS: Alter use o... |
41 |
int install_user_keyrings(void) |
1da177e4c Linux-2.6.12-rc2 |
42 |
{ |
d84f4f992 CRED: Inaugurate ... |
43 44 |
struct user_struct *user; const struct cred *cred; |
1da177e4c Linux-2.6.12-rc2 |
45 46 47 |
struct key *uid_keyring, *session_keyring; char buf[20]; int ret; |
d84f4f992 CRED: Inaugurate ... |
48 49 |
cred = current_cred(); user = cred->user; |
69664cf16 keys: don't gener... |
50 |
kenter("%p{%u}", user, user->uid); |
1da177e4c Linux-2.6.12-rc2 |
51 |
|
69664cf16 keys: don't gener... |
52 53 54 |
if (user->uid_keyring) { kleave(" = 0 [exist]"); return 0; |
1da177e4c Linux-2.6.12-rc2 |
55 |
} |
69664cf16 keys: don't gener... |
56 57 |
mutex_lock(&key_user_keyring_mutex); ret = 0; |
1da177e4c Linux-2.6.12-rc2 |
58 |
|
69664cf16 keys: don't gener... |
59 60 61 62 63 64 65 66 67 68 |
if (!user->uid_keyring) { /* get the UID-specific keyring * - there may be one in existence already as it may have been * pinned by a session, but the user_struct pointing to it * may have been destroyed by setuid */ sprintf(buf, "_uid.%u", user->uid); uid_keyring = find_keyring_by_name(buf, true); if (IS_ERR(uid_keyring)) { uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, |
d84f4f992 CRED: Inaugurate ... |
69 |
cred, KEY_ALLOC_IN_QUOTA, |
69664cf16 keys: don't gener... |
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
NULL); if (IS_ERR(uid_keyring)) { ret = PTR_ERR(uid_keyring); goto error; } } /* get a default session keyring (which might also exist * already) */ sprintf(buf, "_uid_ses.%u", user->uid); session_keyring = find_keyring_by_name(buf, true); if (IS_ERR(session_keyring)) { session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, |
d84f4f992 CRED: Inaugurate ... |
85 |
cred, KEY_ALLOC_IN_QUOTA, NULL); |
69664cf16 keys: don't gener... |
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
if (IS_ERR(session_keyring)) { ret = PTR_ERR(session_keyring); goto error_release; } /* we install a link from the user session keyring to * the user keyring */ ret = key_link(session_keyring, uid_keyring); if (ret < 0) goto error_release_both; } /* install the keyrings */ user->uid_keyring = uid_keyring; user->session_keyring = session_keyring; |
1da177e4c Linux-2.6.12-rc2 |
101 |
} |
69664cf16 keys: don't gener... |
102 103 104 |
mutex_unlock(&key_user_keyring_mutex); kleave(" = 0"); return 0; |
1da177e4c Linux-2.6.12-rc2 |
105 |
|
69664cf16 keys: don't gener... |
106 107 108 109 |
error_release_both: key_put(session_keyring); error_release: key_put(uid_keyring); |
664cceb00 [PATCH] Keys: Add... |
110 |
error: |
69664cf16 keys: don't gener... |
111 112 |
mutex_unlock(&key_user_keyring_mutex); kleave(" = %d", ret); |
1da177e4c Linux-2.6.12-rc2 |
113 |
return ret; |
69664cf16 keys: don't gener... |
114 |
} |
1da177e4c Linux-2.6.12-rc2 |
115 |
|
1da177e4c Linux-2.6.12-rc2 |
116 |
/* |
973c9f4f4 KEYS: Fix up comm... |
117 118 |
* Install a fresh thread keyring directly to new credentials. This keyring is * allowed to overrun the quota. |
1da177e4c Linux-2.6.12-rc2 |
119 |
*/ |
d84f4f992 CRED: Inaugurate ... |
120 |
int install_thread_keyring_to_cred(struct cred *new) |
1da177e4c Linux-2.6.12-rc2 |
121 |
{ |
d84f4f992 CRED: Inaugurate ... |
122 |
struct key *keyring; |
1da177e4c Linux-2.6.12-rc2 |
123 |
|
d84f4f992 CRED: Inaugurate ... |
124 125 126 127 |
keyring = keyring_alloc("_tid", new->uid, new->gid, new, KEY_ALLOC_QUOTA_OVERRUN, NULL); if (IS_ERR(keyring)) return PTR_ERR(keyring); |
1da177e4c Linux-2.6.12-rc2 |
128 |
|
d84f4f992 CRED: Inaugurate ... |
129 130 131 |
new->thread_keyring = keyring; return 0; } |
1da177e4c Linux-2.6.12-rc2 |
132 |
|
1da177e4c Linux-2.6.12-rc2 |
133 |
/* |
973c9f4f4 KEYS: Fix up comm... |
134 |
* Install a fresh thread keyring, discarding the old one. |
1da177e4c Linux-2.6.12-rc2 |
135 |
*/ |
d84f4f992 CRED: Inaugurate ... |
136 |
static int install_thread_keyring(void) |
1da177e4c Linux-2.6.12-rc2 |
137 |
{ |
d84f4f992 CRED: Inaugurate ... |
138 |
struct cred *new; |
1da177e4c Linux-2.6.12-rc2 |
139 |
int ret; |
d84f4f992 CRED: Inaugurate ... |
140 141 142 |
new = prepare_creds(); if (!new) return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
143 |
|
d84f4f992 CRED: Inaugurate ... |
144 145 146 147 148 149 |
BUG_ON(new->thread_keyring); ret = install_thread_keyring_to_cred(new); if (ret < 0) { abort_creds(new); return ret; |
1da177e4c Linux-2.6.12-rc2 |
150 |
} |
d84f4f992 CRED: Inaugurate ... |
151 152 |
return commit_creds(new); } |
1da177e4c Linux-2.6.12-rc2 |
153 |
|
d84f4f992 CRED: Inaugurate ... |
154 |
/* |
973c9f4f4 KEYS: Fix up comm... |
155 156 157 158 |
* Install a process keyring directly to a credentials struct. * * Returns -EEXIST if there was already a process keyring, 0 if one installed, * and other value on any other error |
d84f4f992 CRED: Inaugurate ... |
159 160 161 162 163 |
*/ int install_process_keyring_to_cred(struct cred *new) { struct key *keyring; int ret; |
1da177e4c Linux-2.6.12-rc2 |
164 |
|
d84f4f992 CRED: Inaugurate ... |
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
if (new->tgcred->process_keyring) return -EEXIST; keyring = keyring_alloc("_pid", new->uid, new->gid, new, KEY_ALLOC_QUOTA_OVERRUN, NULL); if (IS_ERR(keyring)) return PTR_ERR(keyring); spin_lock_irq(&new->tgcred->lock); if (!new->tgcred->process_keyring) { new->tgcred->process_keyring = keyring; keyring = NULL; ret = 0; } else { ret = -EEXIST; } spin_unlock_irq(&new->tgcred->lock); key_put(keyring); |
1da177e4c Linux-2.6.12-rc2 |
183 |
return ret; |
d84f4f992 CRED: Inaugurate ... |
184 |
} |
1da177e4c Linux-2.6.12-rc2 |
185 |
|
1da177e4c Linux-2.6.12-rc2 |
186 |
/* |
973c9f4f4 KEYS: Fix up comm... |
187 188 189 190 191 |
* Make sure a process keyring is installed for the current process. The * existing process keyring is not replaced. * * Returns 0 if there is a process keyring by the end of this function, some * error otherwise. |
1da177e4c Linux-2.6.12-rc2 |
192 |
*/ |
d84f4f992 CRED: Inaugurate ... |
193 |
static int install_process_keyring(void) |
1da177e4c Linux-2.6.12-rc2 |
194 |
{ |
d84f4f992 CRED: Inaugurate ... |
195 |
struct cred *new; |
1da177e4c Linux-2.6.12-rc2 |
196 |
int ret; |
d84f4f992 CRED: Inaugurate ... |
197 198 199 |
new = prepare_creds(); if (!new) return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
200 |
|
d84f4f992 CRED: Inaugurate ... |
201 202 203 |
ret = install_process_keyring_to_cred(new); if (ret < 0) { abort_creds(new); |
27d637989 Fix install_proce... |
204 |
return ret != -EEXIST ? ret : 0; |
1da177e4c Linux-2.6.12-rc2 |
205 |
} |
d84f4f992 CRED: Inaugurate ... |
206 207 |
return commit_creds(new); } |
1da177e4c Linux-2.6.12-rc2 |
208 |
|
1da177e4c Linux-2.6.12-rc2 |
209 |
/* |
973c9f4f4 KEYS: Fix up comm... |
210 |
* Install a session keyring directly to a credentials struct. |
1da177e4c Linux-2.6.12-rc2 |
211 |
*/ |
685bfd2c4 umh: creds: conve... |
212 |
int install_session_keyring_to_cred(struct cred *cred, struct key *keyring) |
1da177e4c Linux-2.6.12-rc2 |
213 |
{ |
7e047ef5f [PATCH] keys: sor... |
214 |
unsigned long flags; |
1da177e4c Linux-2.6.12-rc2 |
215 |
struct key *old; |
1a26feb96 [PATCH] Keys: Imp... |
216 217 |
might_sleep(); |
1da177e4c Linux-2.6.12-rc2 |
218 219 220 |
/* create an empty session keyring */ if (!keyring) { |
7e047ef5f [PATCH] keys: sor... |
221 |
flags = KEY_ALLOC_QUOTA_OVERRUN; |
d84f4f992 CRED: Inaugurate ... |
222 |
if (cred->tgcred->session_keyring) |
7e047ef5f [PATCH] keys: sor... |
223 |
flags = KEY_ALLOC_IN_QUOTA; |
d84f4f992 CRED: Inaugurate ... |
224 225 |
keyring = keyring_alloc("_ses", cred->uid, cred->gid, cred, flags, NULL); |
1a26feb96 [PATCH] Keys: Imp... |
226 227 |
if (IS_ERR(keyring)) return PTR_ERR(keyring); |
d84f4f992 CRED: Inaugurate ... |
228 |
} else { |
1da177e4c Linux-2.6.12-rc2 |
229 230 231 232 |
atomic_inc(&keyring->usage); } /* install the keyring */ |
d84f4f992 CRED: Inaugurate ... |
233 234 235 236 |
spin_lock_irq(&cred->tgcred->lock); old = cred->tgcred->session_keyring; rcu_assign_pointer(cred->tgcred->session_keyring, keyring); spin_unlock_irq(&cred->tgcred->lock); |
1da177e4c Linux-2.6.12-rc2 |
237 |
|
1a26feb96 [PATCH] Keys: Imp... |
238 239 240 241 242 243 |
/* we're using RCU on the pointer, but there's no point synchronising * on it if it didn't previously point to anything */ if (old) { synchronize_rcu(); key_put(old); } |
1da177e4c Linux-2.6.12-rc2 |
244 |
|
1a26feb96 [PATCH] Keys: Imp... |
245 |
return 0; |
d84f4f992 CRED: Inaugurate ... |
246 |
} |
1da177e4c Linux-2.6.12-rc2 |
247 |
|
1da177e4c Linux-2.6.12-rc2 |
248 |
/* |
973c9f4f4 KEYS: Fix up comm... |
249 250 |
* Install a session keyring, discarding the old one. If a keyring is not * supplied, an empty one is invented. |
1da177e4c Linux-2.6.12-rc2 |
251 |
*/ |
d84f4f992 CRED: Inaugurate ... |
252 |
static int install_session_keyring(struct key *keyring) |
1da177e4c Linux-2.6.12-rc2 |
253 |
{ |
d84f4f992 CRED: Inaugurate ... |
254 255 |
struct cred *new; int ret; |
1da177e4c Linux-2.6.12-rc2 |
256 |
|
d84f4f992 CRED: Inaugurate ... |
257 258 259 |
new = prepare_creds(); if (!new) return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
260 |
|
995995378 KEYS: If install_... |
261 |
ret = install_session_keyring_to_cred(new, keyring); |
d84f4f992 CRED: Inaugurate ... |
262 263 264 265 |
if (ret < 0) { abort_creds(new); return ret; } |
1da177e4c Linux-2.6.12-rc2 |
266 |
|
d84f4f992 CRED: Inaugurate ... |
267 268 |
return commit_creds(new); } |
1da177e4c Linux-2.6.12-rc2 |
269 |
|
1da177e4c Linux-2.6.12-rc2 |
270 |
/* |
973c9f4f4 KEYS: Fix up comm... |
271 |
* Handle the fsuid changing. |
1da177e4c Linux-2.6.12-rc2 |
272 273 274 275 |
*/ void key_fsuid_changed(struct task_struct *tsk) { /* update the ownership of the thread keyring */ |
b6dff3ec5 CRED: Separate ta... |
276 277 278 279 280 |
BUG_ON(!tsk->cred); if (tsk->cred->thread_keyring) { down_write(&tsk->cred->thread_keyring->sem); tsk->cred->thread_keyring->uid = tsk->cred->fsuid; up_write(&tsk->cred->thread_keyring->sem); |
1da177e4c Linux-2.6.12-rc2 |
281 |
} |
a8b17ed01 KEYS: Do some sty... |
282 |
} |
1da177e4c Linux-2.6.12-rc2 |
283 |
|
1da177e4c Linux-2.6.12-rc2 |
284 |
/* |
973c9f4f4 KEYS: Fix up comm... |
285 |
* Handle the fsgid changing. |
1da177e4c Linux-2.6.12-rc2 |
286 287 288 289 |
*/ void key_fsgid_changed(struct task_struct *tsk) { /* update the ownership of the thread keyring */ |
b6dff3ec5 CRED: Separate ta... |
290 291 292 293 294 |
BUG_ON(!tsk->cred); if (tsk->cred->thread_keyring) { down_write(&tsk->cred->thread_keyring->sem); tsk->cred->thread_keyring->gid = tsk->cred->fsgid; up_write(&tsk->cred->thread_keyring->sem); |
1da177e4c Linux-2.6.12-rc2 |
295 |
} |
a8b17ed01 KEYS: Do some sty... |
296 |
} |
1da177e4c Linux-2.6.12-rc2 |
297 |
|
1da177e4c Linux-2.6.12-rc2 |
298 |
/* |
973c9f4f4 KEYS: Fix up comm... |
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 |
* Search the process keyrings attached to the supplied cred for the first * matching key. * * The search criteria are the type and the match function. The description is * given to the match function as a parameter, but doesn't otherwise influence * the search. Typically the match function will compare the description * parameter to the key's description. * * This can only search keyrings that grant Search permission to the supplied * credentials. Keyrings linked to searched keyrings will also be searched if * they grant Search permission too. Keys can only be found if they grant * Search permission to the credentials. * * Returns a pointer to the key with the key usage count incremented if * successful, -EAGAIN if we didn't find any matching key or -ENOKEY if we only * matched negative keys. * * In the case of a successful return, the possession attribute is set on the * returned key reference. |
1da177e4c Linux-2.6.12-rc2 |
318 |
*/ |
927942aab KEYS: Make /proc/... |
319 320 321 |
key_ref_t search_my_process_keyrings(struct key_type *type, const void *description, key_match_func_t match, |
78b7280cc KEYS: Improve /pr... |
322 |
bool no_state_check, |
927942aab KEYS: Make /proc/... |
323 |
const struct cred *cred) |
1da177e4c Linux-2.6.12-rc2 |
324 |
{ |
b5f545c88 [PATCH] keys: Per... |
325 |
key_ref_t key_ref, ret, err; |
1da177e4c Linux-2.6.12-rc2 |
326 327 328 329 330 331 332 333 |
/* we want to return -EAGAIN or -ENOKEY if any of the keyrings were * searchable, but we failed to find a key or we found a negative key; * otherwise we want to return a sample error (probably -EACCES) if * none of the keyrings were searchable * * in terms of priority: success > -ENOKEY > -EAGAIN > other error */ |
664cceb00 [PATCH] Keys: Add... |
334 |
key_ref = NULL; |
1da177e4c Linux-2.6.12-rc2 |
335 336 337 338 |
ret = NULL; err = ERR_PTR(-EAGAIN); /* search the thread keyring first */ |
c69e8d9c0 CRED: Use RCU to ... |
339 |
if (cred->thread_keyring) { |
664cceb00 [PATCH] Keys: Add... |
340 |
key_ref = keyring_search_aux( |
c69e8d9c0 CRED: Use RCU to ... |
341 |
make_key_ref(cred->thread_keyring, 1), |
78b7280cc KEYS: Improve /pr... |
342 |
cred, type, description, match, no_state_check); |
664cceb00 [PATCH] Keys: Add... |
343 |
if (!IS_ERR(key_ref)) |
1da177e4c Linux-2.6.12-rc2 |
344 |
goto found; |
664cceb00 [PATCH] Keys: Add... |
345 |
switch (PTR_ERR(key_ref)) { |
1da177e4c Linux-2.6.12-rc2 |
346 347 348 349 |
case -EAGAIN: /* no key */ if (ret) break; case -ENOKEY: /* negative key */ |
664cceb00 [PATCH] Keys: Add... |
350 |
ret = key_ref; |
1da177e4c Linux-2.6.12-rc2 |
351 352 |
break; default: |
664cceb00 [PATCH] Keys: Add... |
353 |
err = key_ref; |
1da177e4c Linux-2.6.12-rc2 |
354 355 356 357 358 |
break; } } /* search the process keyring second */ |
bb952bb98 CRED: Separate pe... |
359 |
if (cred->tgcred->process_keyring) { |
664cceb00 [PATCH] Keys: Add... |
360 |
key_ref = keyring_search_aux( |
bb952bb98 CRED: Separate pe... |
361 |
make_key_ref(cred->tgcred->process_keyring, 1), |
78b7280cc KEYS: Improve /pr... |
362 |
cred, type, description, match, no_state_check); |
664cceb00 [PATCH] Keys: Add... |
363 |
if (!IS_ERR(key_ref)) |
1da177e4c Linux-2.6.12-rc2 |
364 |
goto found; |
664cceb00 [PATCH] Keys: Add... |
365 |
switch (PTR_ERR(key_ref)) { |
1da177e4c Linux-2.6.12-rc2 |
366 367 368 369 |
case -EAGAIN: /* no key */ if (ret) break; case -ENOKEY: /* negative key */ |
664cceb00 [PATCH] Keys: Add... |
370 |
ret = key_ref; |
1da177e4c Linux-2.6.12-rc2 |
371 372 |
break; default: |
664cceb00 [PATCH] Keys: Add... |
373 |
err = key_ref; |
1da177e4c Linux-2.6.12-rc2 |
374 375 376 |
break; } } |
3e30148c3 [PATCH] Keys: Mak... |
377 |
/* search the session keyring */ |
bb952bb98 CRED: Separate pe... |
378 |
if (cred->tgcred->session_keyring) { |
8589b4e00 [PATCH] Keys: Use... |
379 |
rcu_read_lock(); |
664cceb00 [PATCH] Keys: Add... |
380 381 |
key_ref = keyring_search_aux( make_key_ref(rcu_dereference( |
bb952bb98 CRED: Separate pe... |
382 |
cred->tgcred->session_keyring), |
664cceb00 [PATCH] Keys: Add... |
383 |
1), |
78b7280cc KEYS: Improve /pr... |
384 |
cred, type, description, match, no_state_check); |
8589b4e00 [PATCH] Keys: Use... |
385 |
rcu_read_unlock(); |
3e30148c3 [PATCH] Keys: Mak... |
386 |
|
664cceb00 [PATCH] Keys: Add... |
387 |
if (!IS_ERR(key_ref)) |
3e30148c3 [PATCH] Keys: Mak... |
388 |
goto found; |
664cceb00 [PATCH] Keys: Add... |
389 |
switch (PTR_ERR(key_ref)) { |
3e30148c3 [PATCH] Keys: Mak... |
390 391 392 393 |
case -EAGAIN: /* no key */ if (ret) break; case -ENOKEY: /* negative key */ |
664cceb00 [PATCH] Keys: Add... |
394 |
ret = key_ref; |
3e30148c3 [PATCH] Keys: Mak... |
395 396 |
break; default: |
664cceb00 [PATCH] Keys: Add... |
397 |
err = key_ref; |
3e30148c3 [PATCH] Keys: Mak... |
398 399 |
break; } |
b5f545c88 [PATCH] keys: Per... |
400 401 |
} /* or search the user-session keyring */ |
c69e8d9c0 CRED: Use RCU to ... |
402 |
else if (cred->user->session_keyring) { |
b5f545c88 [PATCH] keys: Per... |
403 |
key_ref = keyring_search_aux( |
c69e8d9c0 CRED: Use RCU to ... |
404 |
make_key_ref(cred->user->session_keyring, 1), |
78b7280cc KEYS: Improve /pr... |
405 |
cred, type, description, match, no_state_check); |
664cceb00 [PATCH] Keys: Add... |
406 |
if (!IS_ERR(key_ref)) |
3e30148c3 [PATCH] Keys: Mak... |
407 |
goto found; |
664cceb00 [PATCH] Keys: Add... |
408 |
switch (PTR_ERR(key_ref)) { |
3e30148c3 [PATCH] Keys: Mak... |
409 410 411 412 |
case -EAGAIN: /* no key */ if (ret) break; case -ENOKEY: /* negative key */ |
664cceb00 [PATCH] Keys: Add... |
413 |
ret = key_ref; |
3e30148c3 [PATCH] Keys: Mak... |
414 415 |
break; default: |
664cceb00 [PATCH] Keys: Add... |
416 |
err = key_ref; |
3e30148c3 [PATCH] Keys: Mak... |
417 418 |
break; } |
8589b4e00 [PATCH] Keys: Use... |
419 |
} |
b5f545c88 [PATCH] keys: Per... |
420 |
|
927942aab KEYS: Make /proc/... |
421 422 423 424 425 426 |
/* no key - decide on the error we're going to go for */ key_ref = ret ? ret : err; found: return key_ref; } |
927942aab KEYS: Make /proc/... |
427 |
/* |
973c9f4f4 KEYS: Fix up comm... |
428 429 430 431 432 433 |
* Search the process keyrings attached to the supplied cred for the first * matching key in the manner of search_my_process_keyrings(), but also search * the keys attached to the assumed authorisation key using its credentials if * one is available. * * Return same as search_my_process_keyrings(). |
927942aab KEYS: Make /proc/... |
434 435 436 437 438 439 440 441 442 443 |
*/ key_ref_t search_process_keyrings(struct key_type *type, const void *description, key_match_func_t match, const struct cred *cred) { struct request_key_auth *rka; key_ref_t key_ref, ret = ERR_PTR(-EACCES), err; might_sleep(); |
78b7280cc KEYS: Improve /pr... |
444 445 |
key_ref = search_my_process_keyrings(type, description, match, false, cred); |
927942aab KEYS: Make /proc/... |
446 447 448 |
if (!IS_ERR(key_ref)) goto found; err = key_ref; |
b5f545c88 [PATCH] keys: Per... |
449 450 451 452 |
/* if this process has an instantiation authorisation key, then we also * search the keyrings of the process mentioned there * - we don't permit access to request_key auth keys via this method */ |
c69e8d9c0 CRED: Use RCU to ... |
453 |
if (cred->request_key_auth && |
d84f4f992 CRED: Inaugurate ... |
454 |
cred == current_cred() && |
04c567d93 [PATCH] Keys: Fix... |
455 |
type != &key_type_request_key_auth |
b5f545c88 [PATCH] keys: Per... |
456 |
) { |
04c567d93 [PATCH] Keys: Fix... |
457 |
/* defend against the auth key being revoked */ |
c69e8d9c0 CRED: Use RCU to ... |
458 |
down_read(&cred->request_key_auth->sem); |
b5f545c88 [PATCH] keys: Per... |
459 |
|
c69e8d9c0 CRED: Use RCU to ... |
460 461 |
if (key_validate(cred->request_key_auth) == 0) { rka = cred->request_key_auth->payload.data; |
b5f545c88 [PATCH] keys: Per... |
462 |
|
04c567d93 [PATCH] Keys: Fix... |
463 |
key_ref = search_process_keyrings(type, description, |
d84f4f992 CRED: Inaugurate ... |
464 |
match, rka->cred); |
1da177e4c Linux-2.6.12-rc2 |
465 |
|
c69e8d9c0 CRED: Use RCU to ... |
466 |
up_read(&cred->request_key_auth->sem); |
04c567d93 [PATCH] Keys: Fix... |
467 468 469 |
if (!IS_ERR(key_ref)) goto found; |
927942aab KEYS: Make /proc/... |
470 |
ret = key_ref; |
04c567d93 [PATCH] Keys: Fix... |
471 |
} else { |
c69e8d9c0 CRED: Use RCU to ... |
472 |
up_read(&cred->request_key_auth->sem); |
3e30148c3 [PATCH] Keys: Mak... |
473 |
} |
1da177e4c Linux-2.6.12-rc2 |
474 475 476 |
} /* no key - decide on the error we're going to go for */ |
927942aab KEYS: Make /proc/... |
477 478 479 480 481 482 |
if (err == ERR_PTR(-ENOKEY) || ret == ERR_PTR(-ENOKEY)) key_ref = ERR_PTR(-ENOKEY); else if (err == ERR_PTR(-EACCES)) key_ref = ret; else key_ref = err; |
1da177e4c Linux-2.6.12-rc2 |
483 |
|
3e30148c3 [PATCH] Keys: Mak... |
484 |
found: |
664cceb00 [PATCH] Keys: Add... |
485 |
return key_ref; |
a8b17ed01 KEYS: Do some sty... |
486 |
} |
1da177e4c Linux-2.6.12-rc2 |
487 |
|
1da177e4c Linux-2.6.12-rc2 |
488 |
/* |
973c9f4f4 KEYS: Fix up comm... |
489 |
* See if the key we're looking at is the target key. |
664cceb00 [PATCH] Keys: Add... |
490 |
*/ |
927942aab KEYS: Make /proc/... |
491 |
int lookup_user_key_possessed(const struct key *key, const void *target) |
664cceb00 [PATCH] Keys: Add... |
492 493 |
{ return key == target; |
a8b17ed01 KEYS: Do some sty... |
494 |
} |
664cceb00 [PATCH] Keys: Add... |
495 |
|
664cceb00 [PATCH] Keys: Add... |
496 |
/* |
973c9f4f4 KEYS: Fix up comm... |
497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 |
* Look up a key ID given us by userspace with a given permissions mask to get * the key it refers to. * * Flags can be passed to request that special keyrings be created if referred * to directly, to permit partially constructed keys to be found and to skip * validity and permission checks on the found key. * * Returns a pointer to the key with an incremented usage count if successful; * -EINVAL if the key ID is invalid; -ENOKEY if the key ID does not correspond * to a key or the best found key was a negative key; -EKEYREVOKED or * -EKEYEXPIRED if the best found key was revoked or expired; -EACCES if the * found key doesn't grant the requested permit or the LSM denied access to it; * or -ENOMEM if a special keyring couldn't be created. * * In the case of a successful return, the possession attribute is set on the * returned key reference. |
1da177e4c Linux-2.6.12-rc2 |
513 |
*/ |
5593122ee KEYS: Deal with d... |
514 |
key_ref_t lookup_user_key(key_serial_t id, unsigned long lflags, |
8bbf4976b KEYS: Alter use o... |
515 |
key_perm_t perm) |
1da177e4c Linux-2.6.12-rc2 |
516 |
{ |
8bbf4976b KEYS: Alter use o... |
517 |
struct request_key_auth *rka; |
d84f4f992 CRED: Inaugurate ... |
518 |
const struct cred *cred; |
1da177e4c Linux-2.6.12-rc2 |
519 |
struct key *key; |
b6dff3ec5 CRED: Separate ta... |
520 |
key_ref_t key_ref, skey_ref; |
1da177e4c Linux-2.6.12-rc2 |
521 |
int ret; |
bb952bb98 CRED: Separate pe... |
522 523 |
try_again: cred = get_current_cred(); |
664cceb00 [PATCH] Keys: Add... |
524 |
key_ref = ERR_PTR(-ENOKEY); |
1da177e4c Linux-2.6.12-rc2 |
525 526 527 |
switch (id) { case KEY_SPEC_THREAD_KEYRING: |
b6dff3ec5 CRED: Separate ta... |
528 |
if (!cred->thread_keyring) { |
5593122ee KEYS: Deal with d... |
529 |
if (!(lflags & KEY_LOOKUP_CREATE)) |
1da177e4c Linux-2.6.12-rc2 |
530 |
goto error; |
8bbf4976b KEYS: Alter use o... |
531 |
ret = install_thread_keyring(); |
1da177e4c Linux-2.6.12-rc2 |
532 |
if (ret < 0) { |
4d09ec0f7 KEYS: Return more... |
533 |
key_ref = ERR_PTR(ret); |
1da177e4c Linux-2.6.12-rc2 |
534 535 |
goto error; } |
bb952bb98 CRED: Separate pe... |
536 |
goto reget_creds; |
1da177e4c Linux-2.6.12-rc2 |
537 |
} |
b6dff3ec5 CRED: Separate ta... |
538 |
key = cred->thread_keyring; |
1da177e4c Linux-2.6.12-rc2 |
539 |
atomic_inc(&key->usage); |
664cceb00 [PATCH] Keys: Add... |
540 |
key_ref = make_key_ref(key, 1); |
1da177e4c Linux-2.6.12-rc2 |
541 542 543 |
break; case KEY_SPEC_PROCESS_KEYRING: |
bb952bb98 CRED: Separate pe... |
544 |
if (!cred->tgcred->process_keyring) { |
5593122ee KEYS: Deal with d... |
545 |
if (!(lflags & KEY_LOOKUP_CREATE)) |
1da177e4c Linux-2.6.12-rc2 |
546 |
goto error; |
8bbf4976b KEYS: Alter use o... |
547 |
ret = install_process_keyring(); |
1da177e4c Linux-2.6.12-rc2 |
548 |
if (ret < 0) { |
4d09ec0f7 KEYS: Return more... |
549 |
key_ref = ERR_PTR(ret); |
1da177e4c Linux-2.6.12-rc2 |
550 551 |
goto error; } |
bb952bb98 CRED: Separate pe... |
552 |
goto reget_creds; |
1da177e4c Linux-2.6.12-rc2 |
553 |
} |
bb952bb98 CRED: Separate pe... |
554 |
key = cred->tgcred->process_keyring; |
1da177e4c Linux-2.6.12-rc2 |
555 |
atomic_inc(&key->usage); |
664cceb00 [PATCH] Keys: Add... |
556 |
key_ref = make_key_ref(key, 1); |
1da177e4c Linux-2.6.12-rc2 |
557 558 559 |
break; case KEY_SPEC_SESSION_KEYRING: |
bb952bb98 CRED: Separate pe... |
560 |
if (!cred->tgcred->session_keyring) { |
1da177e4c Linux-2.6.12-rc2 |
561 562 |
/* always install a session keyring upon access if one * doesn't exist yet */ |
8bbf4976b KEYS: Alter use o... |
563 |
ret = install_user_keyrings(); |
69664cf16 keys: don't gener... |
564 565 |
if (ret < 0) goto error; |
3ecf1b4f3 KEYS: keyctl_get_... |
566 567 568 569 570 |
if (lflags & KEY_LOOKUP_CREATE) ret = join_session_keyring(NULL); else ret = install_session_keyring( cred->user->session_keyring); |
d84f4f992 CRED: Inaugurate ... |
571 |
|
1da177e4c Linux-2.6.12-rc2 |
572 573 |
if (ret < 0) goto error; |
bb952bb98 CRED: Separate pe... |
574 |
goto reget_creds; |
3ecf1b4f3 KEYS: keyctl_get_... |
575 576 577 578 579 580 581 |
} else if (cred->tgcred->session_keyring == cred->user->session_keyring && lflags & KEY_LOOKUP_CREATE) { ret = join_session_keyring(NULL); if (ret < 0) goto error; goto reget_creds; |
1da177e4c Linux-2.6.12-rc2 |
582 |
} |
3e30148c3 [PATCH] Keys: Mak... |
583 |
rcu_read_lock(); |
bb952bb98 CRED: Separate pe... |
584 |
key = rcu_dereference(cred->tgcred->session_keyring); |
1da177e4c Linux-2.6.12-rc2 |
585 |
atomic_inc(&key->usage); |
3e30148c3 [PATCH] Keys: Mak... |
586 |
rcu_read_unlock(); |
664cceb00 [PATCH] Keys: Add... |
587 |
key_ref = make_key_ref(key, 1); |
1da177e4c Linux-2.6.12-rc2 |
588 589 590 |
break; case KEY_SPEC_USER_KEYRING: |
b6dff3ec5 CRED: Separate ta... |
591 |
if (!cred->user->uid_keyring) { |
8bbf4976b KEYS: Alter use o... |
592 |
ret = install_user_keyrings(); |
69664cf16 keys: don't gener... |
593 594 595 |
if (ret < 0) goto error; } |
b6dff3ec5 CRED: Separate ta... |
596 |
key = cred->user->uid_keyring; |
1da177e4c Linux-2.6.12-rc2 |
597 |
atomic_inc(&key->usage); |
664cceb00 [PATCH] Keys: Add... |
598 |
key_ref = make_key_ref(key, 1); |
1da177e4c Linux-2.6.12-rc2 |
599 600 601 |
break; case KEY_SPEC_USER_SESSION_KEYRING: |
b6dff3ec5 CRED: Separate ta... |
602 |
if (!cred->user->session_keyring) { |
8bbf4976b KEYS: Alter use o... |
603 |
ret = install_user_keyrings(); |
69664cf16 keys: don't gener... |
604 605 606 |
if (ret < 0) goto error; } |
b6dff3ec5 CRED: Separate ta... |
607 |
key = cred->user->session_keyring; |
1da177e4c Linux-2.6.12-rc2 |
608 |
atomic_inc(&key->usage); |
664cceb00 [PATCH] Keys: Add... |
609 |
key_ref = make_key_ref(key, 1); |
1da177e4c Linux-2.6.12-rc2 |
610 611 612 613 |
break; case KEY_SPEC_GROUP_KEYRING: /* group keyrings are not yet supported */ |
4d09ec0f7 KEYS: Return more... |
614 |
key_ref = ERR_PTR(-EINVAL); |
1da177e4c Linux-2.6.12-rc2 |
615 |
goto error; |
b5f545c88 [PATCH] keys: Per... |
616 |
case KEY_SPEC_REQKEY_AUTH_KEY: |
b6dff3ec5 CRED: Separate ta... |
617 |
key = cred->request_key_auth; |
b5f545c88 [PATCH] keys: Per... |
618 619 620 621 622 623 |
if (!key) goto error; atomic_inc(&key->usage); key_ref = make_key_ref(key, 1); break; |
8bbf4976b KEYS: Alter use o... |
624 |
case KEY_SPEC_REQUESTOR_KEYRING: |
b6dff3ec5 CRED: Separate ta... |
625 |
if (!cred->request_key_auth) |
8bbf4976b KEYS: Alter use o... |
626 |
goto error; |
b6dff3ec5 CRED: Separate ta... |
627 628 |
down_read(&cred->request_key_auth->sem); if (cred->request_key_auth->flags & KEY_FLAG_REVOKED) { |
8bbf4976b KEYS: Alter use o... |
629 630 631 |
key_ref = ERR_PTR(-EKEYREVOKED); key = NULL; } else { |
b6dff3ec5 CRED: Separate ta... |
632 |
rka = cred->request_key_auth->payload.data; |
8bbf4976b KEYS: Alter use o... |
633 634 635 |
key = rka->dest_keyring; atomic_inc(&key->usage); } |
b6dff3ec5 CRED: Separate ta... |
636 |
up_read(&cred->request_key_auth->sem); |
8bbf4976b KEYS: Alter use o... |
637 638 639 640 |
if (!key) goto error; key_ref = make_key_ref(key, 1); break; |
1da177e4c Linux-2.6.12-rc2 |
641 |
default: |
664cceb00 [PATCH] Keys: Add... |
642 |
key_ref = ERR_PTR(-EINVAL); |
1da177e4c Linux-2.6.12-rc2 |
643 644 645 646 |
if (id < 1) goto error; key = key_lookup(id); |
664cceb00 [PATCH] Keys: Add... |
647 |
if (IS_ERR(key)) { |
e231c2ee6 Convert ERR_PTR(P... |
648 |
key_ref = ERR_CAST(key); |
1da177e4c Linux-2.6.12-rc2 |
649 |
goto error; |
664cceb00 [PATCH] Keys: Add... |
650 651 652 653 654 655 656 |
} key_ref = make_key_ref(key, 0); /* check to see if we possess the key */ skey_ref = search_process_keyrings(key->type, key, lookup_user_key_possessed, |
d84f4f992 CRED: Inaugurate ... |
657 |
cred); |
664cceb00 [PATCH] Keys: Add... |
658 659 660 661 662 |
if (!IS_ERR(skey_ref)) { key_put(key); key_ref = skey_ref; } |
1da177e4c Linux-2.6.12-rc2 |
663 664 |
break; } |
5593122ee KEYS: Deal with d... |
665 666 667 668 669 670 671 672 |
/* unlink does not use the nominated key in any way, so can skip all * the permission checks as it is only concerned with the keyring */ if (lflags & KEY_LOOKUP_FOR_UNLINK) { ret = 0; goto error; } if (!(lflags & KEY_LOOKUP_PARTIAL)) { |
76181c134 KEYS: Make reques... |
673 674 675 676 677 678 679 680 681 682 683 |
ret = wait_for_key_construction(key, true); switch (ret) { case -ERESTARTSYS: goto invalid_key; default: if (perm) goto invalid_key; case 0: break; } } else if (perm) { |
1da177e4c Linux-2.6.12-rc2 |
684 685 686 687 688 689 |
ret = key_validate(key); if (ret < 0) goto invalid_key; } ret = -EIO; |
5593122ee KEYS: Deal with d... |
690 691 |
if (!(lflags & KEY_LOOKUP_PARTIAL) && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) |
1da177e4c Linux-2.6.12-rc2 |
692 |
goto invalid_key; |
3e30148c3 [PATCH] Keys: Mak... |
693 |
/* check the permissions */ |
d84f4f992 CRED: Inaugurate ... |
694 |
ret = key_task_permission(key_ref, cred, perm); |
29db91906 [PATCH] Keys: Add... |
695 |
if (ret < 0) |
1da177e4c Linux-2.6.12-rc2 |
696 |
goto invalid_key; |
664cceb00 [PATCH] Keys: Add... |
697 |
error: |
bb952bb98 CRED: Separate pe... |
698 |
put_cred(cred); |
664cceb00 [PATCH] Keys: Add... |
699 |
return key_ref; |
1da177e4c Linux-2.6.12-rc2 |
700 |
|
664cceb00 [PATCH] Keys: Add... |
701 702 703 |
invalid_key: key_ref_put(key_ref); key_ref = ERR_PTR(ret); |
1da177e4c Linux-2.6.12-rc2 |
704 |
goto error; |
bb952bb98 CRED: Separate pe... |
705 706 707 708 709 |
/* if we attempted to install a keyring, then it may have caused new * creds to be installed */ reget_creds: put_cred(cred); goto try_again; |
a8b17ed01 KEYS: Do some sty... |
710 |
} |
bb952bb98 CRED: Separate pe... |
711 |
|
1da177e4c Linux-2.6.12-rc2 |
712 |
/* |
973c9f4f4 KEYS: Fix up comm... |
713 714 715 716 717 718 719 720 721 |
* Join the named keyring as the session keyring if possible else attempt to * create a new one of that name and join that. * * If the name is NULL, an empty anonymous keyring will be installed as the * session keyring. * * Named session keyrings are joined with a semaphore held to prevent the * keyrings from going away whilst the attempt is made to going them and also * to prevent a race in creating compatible session keyrings. |
1da177e4c Linux-2.6.12-rc2 |
722 723 724 |
*/ long join_session_keyring(const char *name) { |
d84f4f992 CRED: Inaugurate ... |
725 726 |
const struct cred *old; struct cred *new; |
1da177e4c Linux-2.6.12-rc2 |
727 |
struct key *keyring; |
d84f4f992 CRED: Inaugurate ... |
728 729 730 731 732 |
long ret, serial; /* only permit this if there's a single thread in the thread group - * this avoids us having to adjust the creds on all threads and risking * ENOMEM */ |
5bb459bb4 kernel: rename is... |
733 |
if (!current_is_single_threaded()) |
d84f4f992 CRED: Inaugurate ... |
734 735 736 737 738 739 |
return -EMLINK; new = prepare_creds(); if (!new) return -ENOMEM; old = current_cred(); |
1da177e4c Linux-2.6.12-rc2 |
740 741 742 |
/* if no name is provided, install an anonymous keyring */ if (!name) { |
d84f4f992 CRED: Inaugurate ... |
743 |
ret = install_session_keyring_to_cred(new, NULL); |
1da177e4c Linux-2.6.12-rc2 |
744 745 |
if (ret < 0) goto error; |
d84f4f992 CRED: Inaugurate ... |
746 747 748 749 750 |
serial = new->tgcred->session_keyring->serial; ret = commit_creds(new); if (ret == 0) ret = serial; goto okay; |
1da177e4c Linux-2.6.12-rc2 |
751 752 753 |
} /* allow the user to join or create a named keyring */ |
bb0030797 [PATCH] sem2mutex... |
754 |
mutex_lock(&key_session_mutex); |
1da177e4c Linux-2.6.12-rc2 |
755 756 |
/* look for an existing keyring of this name */ |
69664cf16 keys: don't gener... |
757 |
keyring = find_keyring_by_name(name, false); |
1da177e4c Linux-2.6.12-rc2 |
758 759 |
if (PTR_ERR(keyring) == -ENOKEY) { /* not found - try and create a new one */ |
d84f4f992 CRED: Inaugurate ... |
760 |
keyring = keyring_alloc(name, old->uid, old->gid, old, |
7e047ef5f [PATCH] keys: sor... |
761 |
KEY_ALLOC_IN_QUOTA, NULL); |
1da177e4c Linux-2.6.12-rc2 |
762 763 |
if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); |
bcf945d36 [PATCH] Error dur... |
764 |
goto error2; |
1da177e4c Linux-2.6.12-rc2 |
765 |
} |
d84f4f992 CRED: Inaugurate ... |
766 |
} else if (IS_ERR(keyring)) { |
1da177e4c Linux-2.6.12-rc2 |
767 768 769 770 771 |
ret = PTR_ERR(keyring); goto error2; } /* we've got a keyring - now to install it */ |
d84f4f992 CRED: Inaugurate ... |
772 |
ret = install_session_keyring_to_cred(new, keyring); |
1da177e4c Linux-2.6.12-rc2 |
773 774 |
if (ret < 0) goto error2; |
d84f4f992 CRED: Inaugurate ... |
775 776 |
commit_creds(new); mutex_unlock(&key_session_mutex); |
1da177e4c Linux-2.6.12-rc2 |
777 778 |
ret = keyring->serial; key_put(keyring); |
d84f4f992 CRED: Inaugurate ... |
779 780 |
okay: return ret; |
1da177e4c Linux-2.6.12-rc2 |
781 |
|
664cceb00 [PATCH] Keys: Add... |
782 |
error2: |
bb0030797 [PATCH] sem2mutex... |
783 |
mutex_unlock(&key_session_mutex); |
664cceb00 [PATCH] Keys: Add... |
784 |
error: |
d84f4f992 CRED: Inaugurate ... |
785 |
abort_creds(new); |
1da177e4c Linux-2.6.12-rc2 |
786 |
return ret; |
d84f4f992 CRED: Inaugurate ... |
787 |
} |
ee18d64c1 KEYS: Add a keyct... |
788 789 |
/* |
973c9f4f4 KEYS: Fix up comm... |
790 791 |
* Replace a process's session keyring on behalf of one of its children when * the target process is about to resume userspace execution. |
ee18d64c1 KEYS: Add a keyct... |
792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 |
*/ void key_replace_session_keyring(void) { const struct cred *old; struct cred *new; if (!current->replacement_session_keyring) return; write_lock_irq(&tasklist_lock); new = current->replacement_session_keyring; current->replacement_session_keyring = NULL; write_unlock_irq(&tasklist_lock); if (!new) return; old = current_cred(); new-> uid = old-> uid; new-> euid = old-> euid; new-> suid = old-> suid; new->fsuid = old->fsuid; new-> gid = old-> gid; new-> egid = old-> egid; new-> sgid = old-> sgid; new->fsgid = old->fsgid; new->user = get_uid(old->user); |
f7285b5d6 Set cred->user_ns... |
819 |
new->user_ns = new->user->user_ns; |
ee18d64c1 KEYS: Add a keyct... |
820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 |
new->group_info = get_group_info(old->group_info); new->securebits = old->securebits; new->cap_inheritable = old->cap_inheritable; new->cap_permitted = old->cap_permitted; new->cap_effective = old->cap_effective; new->cap_bset = old->cap_bset; new->jit_keyring = old->jit_keyring; new->thread_keyring = key_get(old->thread_keyring); new->tgcred->tgid = old->tgcred->tgid; new->tgcred->process_keyring = key_get(old->tgcred->process_keyring); security_transfer_creds(new, old); commit_creds(new); } |