/* * instantiate a request-key authorisation record */ static int request_key_auth_instantiate(struct key *key, const void *data, size_t datalen) { struct request_key_auth *rka, *irka; struct key *instkey; int ret; ret = -ENOMEM; rka = kmalloc(sizeof(*rka), GFP_KERNEL); if (rka) { /* see if the calling process is already servicing the key * request of another process */ instkey = key_get_instantiation_authkey(0); if (!IS_ERR(instkey)) { /* it is - use that instantiation context here too */ irka = instkey->payload.data; rka->context = irka->context; rka->pid = irka->pid; key_put(instkey); } else { /* it isn't - use this process as the context */ rka->context = current; rka->pid = current->pid; } rka->target_key = key_get((struct key *) data); key->payload.data = rka; ret = 0; } return ret; } /* end request_key_auth_instantiate() */
/* * 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() */
/* * instantiate the key with the specified payload, and, if one is given, link * the key into the keyring */ long keyctl_instantiate_key(key_serial_t id, const void __user *_payload, size_t plen, key_serial_t ringid) { struct request_key_auth *rka; struct key *instkey; key_ref_t keyring_ref; void *payload; long ret; ret = -EINVAL; if (plen > 32767) goto error; /* pull the payload in if one was supplied */ payload = NULL; if (_payload) { ret = -ENOMEM; payload = kmalloc(plen, GFP_KERNEL); if (!payload) goto error; ret = -EFAULT; if (copy_from_user(payload, _payload, plen) != 0) goto error2; } /* find the instantiation authorisation key */ instkey = key_get_instantiation_authkey(id); if (IS_ERR(instkey)) { ret = PTR_ERR(instkey); goto error2; } rka = instkey->payload.data; /* find the destination keyring amongst those belonging to the * requesting task */ keyring_ref = NULL; if (ringid) { keyring_ref = lookup_user_key(rka->context, ringid, 1, 0, KEY_WRITE); if (IS_ERR(keyring_ref)) { ret = PTR_ERR(keyring_ref); goto error3; } } /* instantiate the key and link it into a keyring */ ret = key_instantiate_and_link(rka->target_key, payload, plen, key_ref_to_ptr(keyring_ref), instkey); key_ref_put(keyring_ref); error3: key_put(instkey); error2: kfree(payload); error: return ret; } /* end keyctl_instantiate_key() */
/* * describe a user key * - the key must have view permission * - if there's a buffer, we place up to buflen bytes of data into it * - unless there's an error, we return the amount of description available, * irrespective of how much we may have copied * - the description is formatted thus: * type;uid;gid;perm;description<NUL> * - implements keyctl(KEYCTL_DESCRIBE) */ long keyctl_describe_key(key_serial_t keyid, char __user *buffer, size_t buflen) { struct key *key, *instkey; key_ref_t key_ref; char *tmpbuf; long ret; key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW); if (IS_ERR(key_ref)) { /* viewing a key under construction is permitted if we have the * authorisation token handy */ if (PTR_ERR(key_ref) == -EACCES) { instkey = key_get_instantiation_authkey(keyid); if (!IS_ERR(instkey)) { key_put(instkey); key_ref = lookup_user_key(NULL, keyid, 0, 1, 0); if (!IS_ERR(key_ref)) goto okay; } } ret = PTR_ERR(key_ref); goto error; } okay: /* calculate how much description we're going to return */ ret = -ENOMEM; tmpbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); if (!tmpbuf) goto error2; key = key_ref_to_ptr(key_ref); ret = snprintf(tmpbuf, PAGE_SIZE - 1, "%s;%d;%d;%08x;%s", key_ref_to_ptr(key_ref)->type->name, key_ref_to_ptr(key_ref)->uid, key_ref_to_ptr(key_ref)->gid, key_ref_to_ptr(key_ref)->perm, key_ref_to_ptr(key_ref)->description ? key_ref_to_ptr(key_ref)->description : "" ); /* include a NUL char at the end of the data */ if (ret > PAGE_SIZE - 1) ret = PAGE_SIZE - 1; tmpbuf[ret] = 0; ret++; /* consider returning the data */ if (buffer && buflen > 0) { if (buflen > ret) buflen = ret; if (copy_to_user(buffer, tmpbuf, buflen) != 0) ret = -EFAULT; } kfree(tmpbuf); error2: key_ref_put(key_ref); error: return ret; } /* end keyctl_describe_key() */