/* * deal with execve() */ int exec_keys(struct task_struct *tsk) { struct key *old; /* newly exec'd tasks don't get a thread keyring */ task_lock(tsk); old = tsk->thread_keyring; tsk->thread_keyring = NULL; task_unlock(tsk); key_put(old); /* discard the process keyring from a newly exec'd task */ spin_lock_irq(&tsk->sighand->siglock); old = tsk->signal->process_keyring; tsk->signal->process_keyring = NULL; spin_unlock_irq(&tsk->sighand->siglock); key_put(old); return 0; } /* end exec_keys() */
/* * set the attributes of an inode */ int afs_setattr(struct dentry *dentry, struct iattr *attr) { struct afs_fs_cursor fc; struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry)); struct key *key; int ret; _enter("{%x:%u},{n=%pd},%x", vnode->fid.vid, vnode->fid.vnode, dentry, attr->ia_valid); if (!(attr->ia_valid & (ATTR_SIZE | ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME))) { _leave(" = 0 [unsupported]"); return 0; } /* flush any dirty data outstanding on a regular file */ if (S_ISREG(vnode->vfs_inode.i_mode)) filemap_write_and_wait(vnode->vfs_inode.i_mapping); if (attr->ia_valid & ATTR_FILE) { key = afs_file_key(attr->ia_file); } else { key = afs_request_key(vnode->volume->cell); if (IS_ERR(key)) { ret = PTR_ERR(key); goto error; } } ret = -ERESTARTSYS; if (afs_begin_vnode_operation(&fc, vnode, key)) { while (afs_select_fileserver(&fc)) { fc.cb_break = vnode->cb_break + vnode->cb_s_break; afs_fs_setattr(&fc, attr); } afs_check_for_remote_deletion(&fc, fc.vnode); afs_vnode_commit_status(&fc, vnode, fc.cb_break); ret = afs_end_vnode_operation(&fc); } if (!(attr->ia_valid & ATTR_FILE)) key_put(key); error: _leave(" = %d", ret); return ret; }
int init_cifs_idmap(void) { struct cred *cred; struct key *keyring; int ret; cifs_dbg(FYI, "Registering the %s key type\n", cifs_idmap_key_type.name); /* create an override credential set with a special thread keyring in * which requests are cached * * this is used to prevent malicious redirections from being installed * with add_key(). */ cred = prepare_kernel_cred(NULL); if (!cred) return -ENOMEM; keyring = keyring_alloc(".cifs_idmap", GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ, KEY_ALLOC_NOT_IN_QUOTA, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto failed_put_cred; } ret = register_key_type(&cifs_idmap_key_type); if (ret < 0) goto failed_put_key; /* instruct request_key() to use this special keyring as a cache for * the results it looks up */ set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; root_cred = cred; cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring)); return 0; failed_put_key: key_put(keyring); failed_put_cred: put_cred(cred); return ret; }
/* * return information about an AFS volume */ static int afs_statfs(struct dentry *dentry, struct kstatfs *buf) { struct afs_super_info *as = AFS_FS_S(dentry->d_sb); struct afs_fs_cursor fc; struct afs_volume_status vs; struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry)); struct key *key; int ret; buf->f_type = dentry->d_sb->s_magic; buf->f_bsize = AFS_BLOCK_SIZE; buf->f_namelen = AFSNAMEMAX - 1; if (as->dyn_root) { buf->f_blocks = 1; buf->f_bavail = 0; buf->f_bfree = 0; return 0; } key = afs_request_key(vnode->volume->cell); if (IS_ERR(key)) return PTR_ERR(key); ret = -ERESTARTSYS; if (afs_begin_vnode_operation(&fc, vnode, key)) { fc.flags |= AFS_FS_CURSOR_NO_VSLEEP; while (afs_select_fileserver(&fc)) { fc.cb_break = afs_calc_vnode_cb_break(vnode); afs_fs_get_volume_status(&fc, &vs); } afs_check_for_remote_deletion(&fc, fc.vnode); afs_vnode_commit_status(&fc, vnode, fc.cb_break); ret = afs_end_vnode_operation(&fc); } key_put(key); if (ret == 0) { if (vs.max_quota == 0) buf->f_blocks = vs.part_max_blocks; else buf->f_blocks = vs.max_quota; buf->f_bavail = buf->f_bfree = buf->f_blocks - vs.blocks_in_use; } return ret; }
int __init cifs_init_dns_resolver(void) { struct cred *cred; struct key *keyring; int ret; printk(KERN_NOTICE "Registering the %s key type\n", key_type_dns_resolver.name); /* create an override credential set with a special thread keyring in * which DNS requests are cached * * this is used to prevent malicious redirections from being installed * with add_key(). */ cred = prepare_kernel_cred(NULL); if (!cred) return -ENOMEM; keyring = key_alloc(&key_type_keyring, ".dns_resolver", 0, 0, cred, (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ, KEY_ALLOC_NOT_IN_QUOTA); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto failed_put_cred; } ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL); if (ret < 0) goto failed_put_key; ret = register_key_type(&key_type_dns_resolver); if (ret < 0) goto failed_put_key; /* instruct request_key() to use this special keyring as a cache for * the results it looks up */ cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; dns_resolver_cache = cred; return 0; failed_put_key: key_put(keyring); failed_put_cred: put_cred(cred); return ret; }
/* * destroy an instantiation authorisation token key */ static void request_key_auth_destroy(struct key *key) { struct request_key_auth *rka = key->payload.data; kenter("{%d}", key->serial); if (rka->context) { put_task_struct(rka->context); rka->context = NULL; } key_put(rka->target_key); kfree(rka); } /* end request_key_auth_destroy() */
/* * release a bundle */ void rxrpc_put_bundle(struct rxrpc_transport *trans, struct rxrpc_conn_bundle *bundle) { _enter("%p,%p{%d}",trans, bundle, atomic_read(&bundle->usage)); if (atomic_dec_and_lock(&bundle->usage, &trans->client_lock)) { _debug("Destroy bundle"); rb_erase(&bundle->node, &trans->bundles); spin_unlock(&trans->client_lock); ASSERT(list_empty(&bundle->unused_conns)); ASSERT(list_empty(&bundle->avail_conns)); ASSERT(list_empty(&bundle->busy_conns)); ASSERTCMP(bundle->num_conns, ==, 0); key_put(bundle->key); kfree(bundle); }
static ssize_t nfs_idmap_request_key(const char *name, size_t namelen, const char *type, void *data, size_t data_size) { const struct cred *saved_cred; struct key *rkey; char *desc; struct user_key_payload *payload; ssize_t ret; ret = nfs_idmap_get_desc(name, namelen, type, strlen(type), &desc); if (ret <= 0) goto out; saved_cred = override_creds(id_resolver_cache); rkey = request_key(&key_type_id_resolver, desc, ""); revert_creds(saved_cred); kfree(desc); if (IS_ERR(rkey)) { ret = PTR_ERR(rkey); goto out; } rcu_read_lock(); rkey->perm |= KEY_USR_VIEW; ret = key_validate(rkey); if (ret < 0) goto out_up; payload = rcu_dereference(rkey->payload.data); if (IS_ERR_OR_NULL(payload)) { ret = PTR_ERR(payload); goto out_up; } ret = payload->datalen; if (ret > 0 && ret <= data_size) memcpy(data, payload->data, ret); else ret = -EINVAL; out_up: rcu_read_unlock(); key_put(rkey); out: return ret; }
static void set_cred_user_ns(struct cred *cred, struct user_namespace *user_ns) { /* Start with the same capabilities as init but useless for doing * anything as the capabilities are bound to the new user namespace. */ cred->securebits = SECUREBITS_DEFAULT; cred->cap_inheritable = CAP_EMPTY_SET; cred->cap_permitted = CAP_FULL_SET; cred->cap_effective = CAP_FULL_SET; cred->cap_bset = CAP_FULL_SET; #ifdef CONFIG_KEYS key_put(cred->request_key_auth); cred->request_key_auth = NULL; #endif /* tgcred will be cleared in our caller bc CLONE_THREAD won't be set */ cred->user_ns = user_ns; }
/* * unbind a key and a ctx. * caller must hold write lock, as well as a ref of the key. */ static void unbind_key_ctx(struct key *key, struct ptlrpc_cli_ctx *ctx) { LASSERT(key->payload.data == ctx); LASSERT(test_bit(PTLRPC_CTX_CACHED_BIT, &ctx->cc_flags) == 0); /* must revoke the key, or others may treat it as newly created */ key_revoke_locked(key); key->payload.data = NULL; ctx2gctx_keyring(ctx)->gck_key = NULL; /* once ctx get split from key, the timer is meaningless */ ctx_clear_timer_kr(ctx); ctx_put_kr(ctx, 1); key_put(key); }
static int nfs_idmap_init_keyring(void) { struct cred *cred; struct key *keyring; int ret = 0; printk(KERN_NOTICE "NFS: Registering the %s key type\n", key_type_id_resolver.name); cred = prepare_kernel_cred(NULL); if (!cred) return -ENOMEM; keyring = keyring_alloc(".id_resolver", GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred, (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ, KEY_ALLOC_NOT_IN_QUOTA, NULL); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto failed_put_cred; } ret = register_key_type(&key_type_id_resolver); if (ret < 0) goto failed_put_key; ret = register_key_type(&key_type_id_resolver_legacy); if (ret < 0) goto failed_reg_legacy; set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags); cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; id_resolver_cache = cred; return 0; failed_reg_legacy: unregister_key_type(&key_type_id_resolver); failed_put_key: key_put(keyring); failed_put_cred: put_cred(cred); return ret; }
/* * request a key * - search the process's keyrings * - check the list of keys being created or updated * - call out to userspace for a key if supplementary info was provided * - waits uninterruptible for creation to complete */ struct key *request_key(struct key_type *type, const char *description, const char *callout_info) { struct key *key; int ret; key = request_key_and_link(type, description, callout_info, NULL, NULL, KEY_ALLOC_IN_QUOTA); if (!IS_ERR(key)) { ret = wait_for_key_construction(key, false); if (ret < 0) { key_put(key); return ERR_PTR(ret); } } return key; }
/** * request_key_and_link - Request a key and cache it in a keyring. * @type: The type of key we want. * @description: The searchable description of the key. * @callout_info: The data to pass to the instantiation upcall (or NULL). * @callout_len: The length of callout_info. * @aux: Auxiliary data for the upcall. * @dest_keyring: Where to cache the key. * @flags: Flags to key_alloc(). * * A key matching the specified criteria is searched for in the process's * keyrings and returned with its usage count incremented if found. Otherwise, * if callout_info is not NULL, a key will be allocated and some service * (probably in userspace) will be asked to instantiate it. * * If successfully found or created, the key will be linked to the destination * keyring if one is provided. * * Returns a pointer to the key if successful; -EACCES, -ENOKEY, -EKEYREVOKED * or -EKEYEXPIRED if an inaccessible, negative, revoked or expired key was * found; -ENOKEY if no key was found and no @callout_info was given; -EDQUOT * if insufficient key quota was available to create a new key; or -ENOMEM if * insufficient memory was available. * * If the returned key was created, then it may still be under construction, * and wait_for_key_construction() should be used to wait for that to complete. */ struct key *request_key_and_link(struct key_type *type, const char *description, const void *callout_info, size_t callout_len, void *aux, struct key *dest_keyring, unsigned long flags) { const struct cred *cred = current_cred(); struct key *key; key_ref_t key_ref; kenter("%s,%s,%p,%zu,%p,%p,%lx", type->name, description, callout_info, callout_len, aux, dest_keyring, flags); /* search all the process keyrings for a key */ key_ref = search_process_keyrings(type, description, type->match, cred); if (!IS_ERR(key_ref)) { key = key_ref_to_ptr(key_ref); if (dest_keyring) { construct_get_dest_keyring(&dest_keyring); key_link(dest_keyring, key); key_put(dest_keyring); } } else if (PTR_ERR(key_ref) != -EAGAIN) { key = ERR_CAST(key_ref); } else { /* the search failed, but the keyrings were searchable, so we * should consult userspace if we can */ key = ERR_PTR(-ENOKEY); if (!callout_info) goto error; key = construct_key_and_link(type, description, callout_info, callout_len, aux, dest_keyring, flags); } error: kleave(" = %p", key); return key; }
/* get secret from key store */ static int get_secret(struct ceph_crypto_key *dst, const char *name) { struct key *ukey; int key_err; int err = 0; struct ceph_crypto_key *ckey; ukey = request_key(&key_type_ceph, name, NULL); if (!ukey || IS_ERR(ukey)) { /* request_key errors don't map nicely to mount(2) errors; don't even try, but still printk */ key_err = PTR_ERR(ukey); switch (key_err) { case -ENOKEY: pr_warn("ceph: Mount failed due to key not found: %s\n", name); break; case -EKEYEXPIRED: pr_warn("ceph: Mount failed due to expired key: %s\n", name); break; case -EKEYREVOKED: pr_warn("ceph: Mount failed due to revoked key: %s\n", name); break; default: pr_warn("ceph: Mount failed due to unknown key error %d: %s\n", key_err, name); } err = -EPERM; goto out; } ckey = ukey->payload.data[0]; err = ceph_crypto_key_clone(dst, ckey); if (err) goto out_key; /* pass through, err is 0 */ out_key: key_put(ukey); out: return err; }
/* * Call out to userspace for key construction. * * Program failure is ignored in favour of key status. */ static int construct_key(struct key *key, const void *callout_info, size_t callout_len, void *aux, struct key *dest_keyring) { struct key_construction *cons; request_key_actor_t actor; struct key *authkey; int ret; kenter("%d,%p,%zu,%p", key->serial, callout_info, callout_len, aux); cons = kmalloc(sizeof(*cons), GFP_KERNEL); if (!cons) return -ENOMEM; /* allocate an authorisation key */ authkey = request_key_auth_new(key, callout_info, callout_len, dest_keyring); if (IS_ERR(authkey)) { kfree(cons); ret = PTR_ERR(authkey); authkey = NULL; } else { cons->authkey = key_get(authkey); cons->key = key_get(key); /* make the call */ actor = call_sbin_request_key; if (key->type->request_key) actor = key->type->request_key; ret = actor(cons, "create", aux); /* check that the actor called complete_request_key() prior to * returning an error */ WARN_ON(ret < 0 && !test_bit(KEY_FLAG_REVOKED, &authkey->flags)); key_put(authkey); } kleave(" = %d", ret); return ret; }
/* * install a session keyring, discarding the old one * - if a keyring is not supplied, an empty one is invented */ static int install_session_keyring(struct task_struct *tsk, struct key *keyring) { unsigned long flags; struct key *old; char buf[20]; might_sleep(); /* create an empty session keyring */ if (!keyring) { sprintf(buf, "_ses.%u", tsk->tgid); flags = KEY_ALLOC_QUOTA_OVERRUN; if (tsk->signal->session_keyring) flags = KEY_ALLOC_IN_QUOTA; keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, flags, NULL); if (IS_ERR(keyring)) return PTR_ERR(keyring); } else { atomic_inc(&keyring->usage); } /* install the keyring */ spin_lock_irq(&tsk->sighand->siglock); old = tsk->signal->session_keyring; rcu_assign_pointer(tsk->signal->session_keyring, keyring); spin_unlock_irq(&tsk->sighand->siglock); /* 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); } return 0; } /* end install_session_keyring() */
/** * request_key_with_auxdata - Request a key with auxiliary data for the upcaller * @type: The type of key we want. * @description: The searchable description of the key. * @callout_info: The data to pass to the instantiation upcall (or NULL). * @callout_len: The length of callout_info. * @aux: Auxiliary data for the upcall. * * As for request_key_and_link() except that it does not add the returned key * to a keyring if found and new keys are always allocated in the user's quota. * * Furthermore, it then works as wait_for_key_construction() to wait for the * completion of keys undergoing construction with a non-interruptible wait. */ struct key *request_key_with_auxdata(struct key_type *type, const char *description, const void *callout_info, size_t callout_len, void *aux) { struct key *key; int ret; key = request_key_and_link(type, description, callout_info, callout_len, aux, NULL, KEY_ALLOC_IN_QUOTA); if (!IS_ERR(key)) { ret = wait_for_key_construction(key, false); if (ret < 0) { key_put(key); return ERR_PTR(ret); } } return key; }
static ssize_t dh_data_from_key(key_serial_t keyid, void **data) { struct key *key; key_ref_t key_ref; long status; ssize_t ret; key_ref = lookup_user_key(keyid, 0, KEY_NEED_READ); if (IS_ERR(key_ref)) { ret = -ENOKEY; goto error; } key = key_ref_to_ptr(key_ref); ret = -EOPNOTSUPP; if (key->type == &key_type_user) { down_read(&key->sem); status = key_validate(key); if (status == 0) { const struct user_key_payload *payload; uint8_t *duplicate; payload = user_key_payload_locked(key); duplicate = kmemdup(payload->data, payload->datalen, GFP_KERNEL); if (duplicate) { *data = duplicate; ret = payload->datalen; } else { ret = -ENOMEM; } } up_read(&key->sem); } key_put(key); error: return ret; }
static int afs_readpage(struct file *file, struct page *page) { struct key *key; int ret; if (file) { key = file->private_data; ASSERT(key != NULL); ret = afs_page_filler(key, page); } else { struct inode *inode = page->mapping->host; key = afs_request_key(AFS_FS_S(inode->i_sb)->volume->cell); if (IS_ERR(key)) { ret = PTR_ERR(key); } else { ret = afs_page_filler(key, page); key_put(key); } } return ret; }
/* * set the attributes of an inode */ int afs_setattr(struct dentry *dentry, struct iattr *attr) { struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry)); struct key *key; int ret; _enter("{%x:%u},{n=%pd},%x", vnode->fid.vid, vnode->fid.vnode, dentry, attr->ia_valid); if (!(attr->ia_valid & (ATTR_SIZE | ATTR_MODE | ATTR_UID | ATTR_GID | ATTR_MTIME))) { _leave(" = 0 [unsupported]"); return 0; } /* flush any dirty data outstanding on a regular file */ if (S_ISREG(vnode->vfs_inode.i_mode)) { filemap_write_and_wait(vnode->vfs_inode.i_mapping); afs_writeback_all(vnode); } if (attr->ia_valid & ATTR_FILE) { key = attr->ia_file->private_data; } else { key = afs_request_key(vnode->volume->cell); if (IS_ERR(key)) { ret = PTR_ERR(key); goto error; } } ret = afs_vnode_setattr(vnode, key, attr); if (!(attr->ia_valid & ATTR_FILE)) key_put(key); error: _leave(" = %d", ret); return ret; }
int nfs_idmap_init(void) { struct cred *cred; struct key *keyring; int ret = 0; ; cred = prepare_kernel_cred(NULL); if (!cred) return -ENOMEM; keyring = key_alloc(&key_type_keyring, ".id_resolver", 0, 0, cred, (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ, KEY_ALLOC_NOT_IN_QUOTA); if (IS_ERR(keyring)) { ret = PTR_ERR(keyring); goto failed_put_cred; } ret = key_instantiate_and_link(keyring, NULL, 0, NULL, NULL); if (ret < 0) goto failed_put_key; ret = register_key_type(&key_type_id_resolver); if (ret < 0) goto failed_put_key; cred->thread_keyring = keyring; cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING; id_resolver_cache = cred; return 0; failed_put_key: key_put(keyring); failed_put_cred: put_cred(cred); return ret; }
int asymmetric_verify(struct key *keyring, const char *sig, int siglen, const char *data, int datalen) { struct public_key_signature pks; struct signature_v2_hdr *hdr = (struct signature_v2_hdr *)sig; struct key *key; int ret = -ENOMEM; if (siglen <= sizeof(*hdr)) return -EBADMSG; siglen -= sizeof(*hdr); if (siglen != __be16_to_cpu(hdr->sig_size)) return -EBADMSG; if (hdr->hash_algo >= PKEY_HASH__LAST) return -ENOPKG; key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid)); if (IS_ERR(key)) return PTR_ERR(key); memset(&pks, 0, sizeof(pks)); pks.pkey_hash_algo = hdr->hash_algo; pks.digest = (u8 *)data; pks.digest_size = datalen; pks.nr_mpi = 1; pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen); if (pks.rsa.s) ret = verify_signature(key, &pks); mpi_free(pks.rsa.s); key_put(key); pr_debug("%s() = %d\n", __func__, ret); return ret; }
/* * deal with the UID changing */ void switch_uid_keyring(struct user_struct *new_user) { #if 0 /* do nothing for now */ struct key *old; /* switch to the new user's session keyring if we were running under * root's default session keyring */ if (new_user->uid != 0 && current->session_keyring == &root_session_keyring ) { atomic_inc(&new_user->session_keyring->usage); task_lock(current); old = current->session_keyring; current->session_keyring = new_user->session_keyring; task_unlock(current); key_put(old); } #endif } /* end switch_uid_keyring() */
/* * Check the new certificate against the ones in the trust keyring. If one of * those is the signing key and validates the new certificate, then mark the * new certificate as being trusted. * * Return 0 if the new certificate was successfully validated, 1 if we couldn't * find a matching parent certificate in the trusted list and an error if there * is a matching certificate but the signature check fails. */ static int x509_validate_trust(struct x509_certificate *cert, struct key *trust_keyring) { struct key *key; int ret = 1; if (!trust_keyring) return -EOPNOTSUPP; if (ca_keyid && !asymmetric_key_id_partial(cert->akid_skid, ca_keyid)) return -EPERM; key = x509_request_asymmetric_key(trust_keyring, cert->akid_skid, false); if (!IS_ERR(key)) { if (!use_builtin_keys || test_bit(KEY_FLAG_BUILTIN, &key->flags)) ret = x509_check_signature(key->payload.data, cert); key_put(key); } return ret; }
/* * allocate the keyrings to be associated with a UID */ int alloc_uid_keyring(struct user_struct *user, struct task_struct *ctx) { struct key *uid_keyring, *session_keyring; char buf[20]; int ret; /* concoct a default session keyring */ sprintf(buf, "_uid_ses.%u", user->uid); session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, KEY_ALLOC_IN_QUOTA, NULL); if (IS_ERR(session_keyring)) { ret = PTR_ERR(session_keyring); goto error; } /* and a UID specific keyring, pointed to by the default session * keyring */ sprintf(buf, "_uid.%u", user->uid); uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, KEY_ALLOC_IN_QUOTA, session_keyring); if (IS_ERR(uid_keyring)) { key_put(session_keyring); ret = PTR_ERR(uid_keyring); goto error; } /* install the keyrings */ user->uid_keyring = uid_keyring; user->session_keyring = session_keyring; ret = 0; error: return ret; } /* end alloc_uid_keyring() */
/* * negatively instantiate the key with the given timeout (in seconds), and, if * one is given, link the key into the keyring */ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) { struct request_key_auth *rka; struct key *instkey; key_ref_t keyring_ref; long ret; /* find the instantiation authorisation key */ instkey = key_get_instantiation_authkey(id); if (IS_ERR(instkey)) { ret = PTR_ERR(instkey); goto error; } rka = instkey->payload.data; /* find the destination keyring if present (which must also be * writable) */ keyring_ref = NULL; if (ringid) { keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); if (IS_ERR(keyring_ref)) { ret = PTR_ERR(keyring_ref); goto error2; } } /* instantiate the key and link it into a keyring */ ret = key_negate_and_link(rka->target_key, timeout, key_ref_to_ptr(keyring_ref), instkey); key_ref_put(keyring_ref); error2: key_put(instkey); error: return ret; } /* end keyctl_negate_key() */
/** * restrict_link_by_signature - Restrict additions to a ring of public keys * @trust_keyring: A ring of keys that can be used to vouch for the new cert. * @type: The type of key being added. * @payload: The payload of the new key. * * Check the new certificate against the ones in the trust keyring. If one of * those is the signing key and validates the new certificate, then mark the * new certificate as being trusted. * * Returns 0 if the new certificate was accepted, -ENOKEY if we couldn't find a * matching parent certificate in the trusted list, -EKEYREJECTED if the * signature check fails or the key is blacklisted and some other error if * there is a matching certificate but the signature check cannot be performed. */ int restrict_link_by_signature(struct key *trust_keyring, const struct key_type *type, const union key_payload *payload) { const struct public_key_signature *sig; struct key *key; int ret; pr_devel("==>%s()\n", __func__); if (!trust_keyring) return -ENOKEY; if (type != &key_type_asymmetric) return -EOPNOTSUPP; sig = payload->data[asym_auth]; if (!sig->auth_ids[0] && !sig->auth_ids[1]) return -ENOKEY; if (ca_keyid && !asymmetric_key_id_partial(sig->auth_ids[1], ca_keyid)) return -EPERM; /* See if we have a key that signed this one. */ key = find_asymmetric_key(trust_keyring, sig->auth_ids[0], sig->auth_ids[1], false); if (IS_ERR(key)) return -ENOKEY; if (use_builtin_keys && !test_bit(KEY_FLAG_BUILTIN, &key->flags)) ret = -ENOKEY; else ret = verify_signature(key, sig); key_put(key); return ret; }
/* * Get the key from the TPM for the SHA1-HMAC */ int evm_init_key(void) { struct key *evm_key; struct encrypted_key_payload *ekp; int rc = 0; evm_key = request_key(&key_type_encrypted, EVMKEY, NULL); if (IS_ERR(evm_key)) return -ENOENT; down_read(&evm_key->sem); ekp = evm_key->payload.data; if (ekp->decrypted_datalen > MAX_KEY_SIZE) { rc = -EINVAL; goto out; } memcpy(evmkey, ekp->decrypted_data, ekp->decrypted_datalen); out: /* burn the original key contents */ memset(ekp->decrypted_data, 0, ekp->decrypted_datalen); up_read(&evm_key->sem); key_put(evm_key); return rc; }
/* * This is the task which runs the usermode application */ int __exec_usermodehelper(char *path, char **argv, char **envp, struct key *ring) { struct key *new_session, *old_session; int retval; /* Unblock all signals and set the session keyring. */ new_session = key_get(ring); flush_signals(current); spin_lock_irq(¤t->sighand->siglock); old_session = __install_session_keyring(current, new_session); flush_signal_handlers(current, 1); sigemptyset(¤t->blocked); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); key_put(old_session); retval = -EPERM; if (current->fs->root) retval = execve(path, argv, envp); return retval; }
/* Resolves server name to ip address. * input: * unc - server UNC * output: * *ip_addr - pointer to server ip, caller responcible for freeing it. * return 0 on success */ int dns_resolve_server_name_to_ip(const char *unc, char **ip_addr) { const struct cred *saved_cred; int rc = -EAGAIN; struct key *rkey = ERR_PTR(-EAGAIN); char *name; char *data = NULL; int len; if (!ip_addr || !unc) return -EINVAL; /* search for server name delimiter */ len = strlen(unc); if (len < 3) { cFYI(1, ("%s: unc is too short: %s", __func__, unc)); return -EINVAL; } len -= 2; name = memchr(unc+2, '\\', len); if (!name) { cFYI(1, ("%s: probably server name is whole unc: %s", __func__, unc)); } else { len = (name - unc) - 2/* leading // */; } name = kmalloc(len+1, GFP_KERNEL); if (!name) { rc = -ENOMEM; return rc; } memcpy(name, unc+2, len); name[len] = 0; if (is_ip(name)) { cFYI(1, ("%s: it is IP, skipping dns upcall: %s", __func__, name)); data = name; goto skip_upcall; } saved_cred = override_creds(dns_resolver_cache); rkey = request_key(&key_type_dns_resolver, name, ""); revert_creds(saved_cred); if (!IS_ERR(rkey)) { if (!(rkey->perm & KEY_USR_VIEW)) { down_read(&rkey->sem); rkey->perm |= KEY_USR_VIEW; up_read(&rkey->sem); } len = rkey->type_data.x[0]; data = rkey->payload.data; } else { cERROR(1, ("%s: unable to resolve: %s", __func__, name)); goto out; } skip_upcall: if (data) { *ip_addr = kmalloc(len + 1, GFP_KERNEL); if (*ip_addr) { memcpy(*ip_addr, data, len + 1); if (!IS_ERR(rkey)) cFYI(1, ("%s: resolved: %s to %s", __func__, name, *ip_addr )); rc = 0; } else { rc = -ENOMEM; } if (!IS_ERR(rkey)) key_put(rkey); } out: kfree(name); return rc; }