/* * set the default keyring in which request_key() will cache keys * - return the old setting */ long keyctl_set_reqkey_keyring(int reqkey_defl) { int ret; switch (reqkey_defl) { case KEY_REQKEY_DEFL_THREAD_KEYRING: ret = install_thread_keyring(current); if (ret < 0) return ret; goto set; case KEY_REQKEY_DEFL_PROCESS_KEYRING: ret = install_process_keyring(current); if (ret < 0) return ret; case KEY_REQKEY_DEFL_DEFAULT: case KEY_REQKEY_DEFL_SESSION_KEYRING: case KEY_REQKEY_DEFL_USER_KEYRING: case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: set: current->jit_keyring = reqkey_defl; case KEY_REQKEY_DEFL_NO_CHANGE: return current->jit_keyring; case KEY_REQKEY_DEFL_GROUP_KEYRING: default: return -EINVAL; } } /* end keyctl_set_reqkey_keyring() */
/* * lookup a key given a key ID from userspace with a given permissions mask * - don't create special keyrings unless so requested * - partially constructed keys aren't found unless requested */ struct key *lookup_user_key(key_serial_t id, int create, int partial, key_perm_t perm) { struct task_struct *tsk = current; unsigned long flags; struct key *key; int ret; key = ERR_PTR(-ENOKEY); switch (id) { case KEY_SPEC_THREAD_KEYRING: if (!tsk->thread_keyring) { if (!create) goto error; ret = install_thread_keyring(tsk); if (ret < 0) { key = ERR_PTR(ret); goto error; } } key = tsk->thread_keyring; atomic_inc(&key->usage); break; case KEY_SPEC_PROCESS_KEYRING: if (!tsk->signal->process_keyring) { if (!create) goto error; ret = install_process_keyring(tsk); if (ret < 0) { key = ERR_PTR(ret); goto error; } } key = tsk->signal->process_keyring; atomic_inc(&key->usage); break; case KEY_SPEC_SESSION_KEYRING: if (!tsk->signal->session_keyring) { /* always install a session keyring upon access if one * doesn't exist yet */ ret = install_session_keyring( tsk, tsk->user->session_keyring); if (ret < 0) goto error; } spin_lock_irqsave(&tsk->sighand->siglock, flags); key = tsk->signal->session_keyring; atomic_inc(&key->usage); spin_unlock_irqrestore(&tsk->sighand->siglock, flags); break; case KEY_SPEC_USER_KEYRING: key = tsk->user->uid_keyring; atomic_inc(&key->usage); break; case KEY_SPEC_USER_SESSION_KEYRING: key = tsk->user->session_keyring; atomic_inc(&key->usage); break; case KEY_SPEC_GROUP_KEYRING: /* group keyrings are not yet supported */ key = ERR_PTR(-EINVAL); goto error; default: key = ERR_PTR(-EINVAL); if (id < 1) goto error; key = key_lookup(id); if (IS_ERR(key)) goto error; break; } /* check the status and permissions */ if (perm) { ret = key_validate(key); if (ret < 0) goto invalid_key; } ret = -EIO; if (!partial && !(key->flags & KEY_FLAG_INSTANTIATED)) goto invalid_key; ret = -EACCES; if (!key_permission(key, perm)) goto invalid_key; error: return key; invalid_key: key_put(key); key = ERR_PTR(ret); goto error; } /* end lookup_user_key() */
/* * lookup a key given a key ID from userspace with a given permissions mask * - don't create special keyrings unless so requested * - partially constructed keys aren't found unless requested */ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, int create, int partial, key_perm_t perm) { key_ref_t key_ref, skey_ref; struct key *key; int ret; if (!context) context = current; key_ref = ERR_PTR(-ENOKEY); switch (id) { case KEY_SPEC_THREAD_KEYRING: if (!context->thread_keyring) { if (!create) goto error; ret = install_thread_keyring(context); if (ret < 0) { key = ERR_PTR(ret); goto error; } } key = context->thread_keyring; atomic_inc(&key->usage); key_ref = make_key_ref(key, 1); break; case KEY_SPEC_PROCESS_KEYRING: if (!context->signal->process_keyring) { if (!create) goto error; ret = install_process_keyring(context); if (ret < 0) { key = ERR_PTR(ret); goto error; } } key = context->signal->process_keyring; atomic_inc(&key->usage); key_ref = make_key_ref(key, 1); break; case KEY_SPEC_SESSION_KEYRING: if (!context->signal->session_keyring) { /* always install a session keyring upon access if one * doesn't exist yet */ ret = install_session_keyring( context, context->user->session_keyring); if (ret < 0) goto error; } rcu_read_lock(); key = rcu_dereference(context->signal->session_keyring); atomic_inc(&key->usage); rcu_read_unlock(); key_ref = make_key_ref(key, 1); break; case KEY_SPEC_USER_KEYRING: key = context->user->uid_keyring; atomic_inc(&key->usage); key_ref = make_key_ref(key, 1); break; case KEY_SPEC_USER_SESSION_KEYRING: key = context->user->session_keyring; atomic_inc(&key->usage); key_ref = make_key_ref(key, 1); break; case KEY_SPEC_GROUP_KEYRING: /* group keyrings are not yet supported */ key = ERR_PTR(-EINVAL); goto error; case KEY_SPEC_REQKEY_AUTH_KEY: key = context->request_key_auth; if (!key) goto error; atomic_inc(&key->usage); key_ref = make_key_ref(key, 1); break; default: key_ref = ERR_PTR(-EINVAL); if (id < 1) goto error; key = key_lookup(id); if (IS_ERR(key)) { key_ref = ERR_PTR(PTR_ERR(key)); goto error; } 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, current); if (!IS_ERR(skey_ref)) { key_put(key); key_ref = skey_ref; } break; } /* check the status */ if (perm) { ret = key_validate(key); if (ret < 0) goto invalid_key; } ret = -EIO; if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) goto invalid_key; /* check the permissions */ ret = key_task_permission(key_ref, context, perm); if (ret < 0) goto invalid_key; error: return key_ref; invalid_key: key_ref_put(key_ref); key_ref = ERR_PTR(ret); goto error; } /* end lookup_user_key() */