Path: blob/master/security/keys/request_key_auth.c
10814 views
/* Request key authorisation token key definition.1*2* Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.3* Written by David Howells ([email protected])4*5* This program is free software; you can redistribute it and/or6* modify it under the terms of the GNU General Public License7* as published by the Free Software Foundation; either version8* 2 of the License, or (at your option) any later version.9*10* See Documentation/security/keys-request-key.txt11*/1213#include <linux/module.h>14#include <linux/sched.h>15#include <linux/err.h>16#include <linux/seq_file.h>17#include <linux/slab.h>18#include <asm/uaccess.h>19#include "internal.h"2021static int request_key_auth_instantiate(struct key *, const void *, size_t);22static void request_key_auth_describe(const struct key *, struct seq_file *);23static void request_key_auth_revoke(struct key *);24static void request_key_auth_destroy(struct key *);25static long request_key_auth_read(const struct key *, char __user *, size_t);2627/*28* The request-key authorisation key type definition.29*/30struct key_type key_type_request_key_auth = {31.name = ".request_key_auth",32.def_datalen = sizeof(struct request_key_auth),33.instantiate = request_key_auth_instantiate,34.describe = request_key_auth_describe,35.revoke = request_key_auth_revoke,36.destroy = request_key_auth_destroy,37.read = request_key_auth_read,38};3940/*41* Instantiate a request-key authorisation key.42*/43static int request_key_auth_instantiate(struct key *key,44const void *data,45size_t datalen)46{47key->payload.data = (struct request_key_auth *) data;48return 0;49}5051/*52* Describe an authorisation token.53*/54static void request_key_auth_describe(const struct key *key,55struct seq_file *m)56{57struct request_key_auth *rka = key->payload.data;5859seq_puts(m, "key:");60seq_puts(m, key->description);61if (key_is_instantiated(key))62seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len);63}6465/*66* Read the callout_info data (retrieves the callout information).67* - the key's semaphore is read-locked68*/69static long request_key_auth_read(const struct key *key,70char __user *buffer, size_t buflen)71{72struct request_key_auth *rka = key->payload.data;73size_t datalen;74long ret;7576datalen = rka->callout_len;77ret = datalen;7879/* we can return the data as is */80if (buffer && buflen > 0) {81if (buflen > datalen)82buflen = datalen;8384if (copy_to_user(buffer, rka->callout_info, buflen) != 0)85ret = -EFAULT;86}8788return ret;89}9091/*92* Handle revocation of an authorisation token key.93*94* Called with the key sem write-locked.95*/96static void request_key_auth_revoke(struct key *key)97{98struct request_key_auth *rka = key->payload.data;99100kenter("{%d}", key->serial);101102if (rka->cred) {103put_cred(rka->cred);104rka->cred = NULL;105}106}107108/*109* Destroy an instantiation authorisation token key.110*/111static void request_key_auth_destroy(struct key *key)112{113struct request_key_auth *rka = key->payload.data;114115kenter("{%d}", key->serial);116117if (rka->cred) {118put_cred(rka->cred);119rka->cred = NULL;120}121122key_put(rka->target_key);123key_put(rka->dest_keyring);124kfree(rka->callout_info);125kfree(rka);126}127128/*129* Create an authorisation token for /sbin/request-key or whoever to gain130* access to the caller's security data.131*/132struct key *request_key_auth_new(struct key *target, const void *callout_info,133size_t callout_len, struct key *dest_keyring)134{135struct request_key_auth *rka, *irka;136const struct cred *cred = current->cred;137struct key *authkey = NULL;138char desc[20];139int ret;140141kenter("%d,", target->serial);142143/* allocate a auth record */144rka = kmalloc(sizeof(*rka), GFP_KERNEL);145if (!rka) {146kleave(" = -ENOMEM");147return ERR_PTR(-ENOMEM);148}149rka->callout_info = kmalloc(callout_len, GFP_KERNEL);150if (!rka->callout_info) {151kleave(" = -ENOMEM");152kfree(rka);153return ERR_PTR(-ENOMEM);154}155156/* see if the calling process is already servicing the key request of157* another process */158if (cred->request_key_auth) {159/* it is - use that instantiation context here too */160down_read(&cred->request_key_auth->sem);161162/* if the auth key has been revoked, then the key we're163* servicing is already instantiated */164if (test_bit(KEY_FLAG_REVOKED, &cred->request_key_auth->flags))165goto auth_key_revoked;166167irka = cred->request_key_auth->payload.data;168rka->cred = get_cred(irka->cred);169rka->pid = irka->pid;170171up_read(&cred->request_key_auth->sem);172}173else {174/* it isn't - use this process as the context */175rka->cred = get_cred(cred);176rka->pid = current->pid;177}178179rka->target_key = key_get(target);180rka->dest_keyring = key_get(dest_keyring);181memcpy(rka->callout_info, callout_info, callout_len);182rka->callout_len = callout_len;183184/* allocate the auth key */185sprintf(desc, "%x", target->serial);186187authkey = key_alloc(&key_type_request_key_auth, desc,188cred->fsuid, cred->fsgid, cred,189KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |190KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA);191if (IS_ERR(authkey)) {192ret = PTR_ERR(authkey);193goto error_alloc;194}195196/* construct the auth key */197ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL);198if (ret < 0)199goto error_inst;200201kleave(" = {%d,%d}", authkey->serial, atomic_read(&authkey->usage));202return authkey;203204auth_key_revoked:205up_read(&cred->request_key_auth->sem);206kfree(rka->callout_info);207kfree(rka);208kleave("= -EKEYREVOKED");209return ERR_PTR(-EKEYREVOKED);210211error_inst:212key_revoke(authkey);213key_put(authkey);214error_alloc:215key_put(rka->target_key);216key_put(rka->dest_keyring);217kfree(rka->callout_info);218kfree(rka);219kleave("= %d", ret);220return ERR_PTR(ret);221}222223/*224* See if an authorisation key is associated with a particular key.225*/226static int key_get_instantiation_authkey_match(const struct key *key,227const void *_id)228{229struct request_key_auth *rka = key->payload.data;230key_serial_t id = (key_serial_t)(unsigned long) _id;231232return rka->target_key->serial == id;233}234235/*236* Search the current process's keyrings for the authorisation key for237* instantiation of a key.238*/239struct key *key_get_instantiation_authkey(key_serial_t target_id)240{241const struct cred *cred = current_cred();242struct key *authkey;243key_ref_t authkey_ref;244245authkey_ref = search_process_keyrings(246&key_type_request_key_auth,247(void *) (unsigned long) target_id,248key_get_instantiation_authkey_match,249cred);250251if (IS_ERR(authkey_ref)) {252authkey = ERR_CAST(authkey_ref);253goto error;254}255256authkey = key_ref_to_ptr(authkey_ref);257if (test_bit(KEY_FLAG_REVOKED, &authkey->flags)) {258key_put(authkey);259authkey = ERR_PTR(-EKEYREVOKED);260}261262error:263return authkey;264}265266267