Example #1
0
/*
 * unlink the first attachment of a key from a keyring
 * - the keyring must be writable
 * - we don't need any permissions on the key
 * - implements keyctl(KEYCTL_UNLINK)
 */
long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid)
{
	key_ref_t keyring_ref, key_ref;
	long ret;

	keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE);
	if (IS_ERR(keyring_ref)) {
		ret = PTR_ERR(keyring_ref);
		goto error;
	}

	key_ref = lookup_user_key(NULL, id, 0, 0, 0);
	if (IS_ERR(key_ref)) {
		ret = PTR_ERR(key_ref);
		goto error2;
	}

	ret = key_unlink(key_ref_to_ptr(keyring_ref), key_ref_to_ptr(key_ref));

	key_ref_put(key_ref);
 error2:
	key_ref_put(keyring_ref);
 error:
	return ret;

} /* end keyctl_keyring_unlink() */
Example #2
0
/*
 * Load the compiled-in list of X.509 certificates.
 */
static __init int load_system_certificate_list(void)
{
    key_ref_t key;
    const u8 *p, *end;
    size_t plen;

    pr_notice("Loading compiled-in X.509 certificates\n");

    p = system_certificate_list;
    end = p + system_certificate_list_size;
    while (p < end) {
        /* Each cert begins with an ASN.1 SEQUENCE tag and must be more
         * than 256 bytes in size.
         */
        if (end - p < 4)
            goto dodgy_cert;
        if (p[0] != 0x30 &&
                p[1] != 0x82)
            goto dodgy_cert;
        plen = (p[2] << 8) | p[3];
        plen += 4;
        if (plen > end - p)
            goto dodgy_cert;

        key = key_create_or_update(make_key_ref(system_trusted_keyring, 1),
                                   "asymmetric",
                                   NULL,
                                   p,
                                   plen,
                                   ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
                                    KEY_USR_VIEW | KEY_USR_READ),
                                   KEY_ALLOC_NOT_IN_QUOTA |
                                   KEY_ALLOC_TRUSTED);
        if (IS_ERR(key)) {
            pr_err("Problem loading in-kernel X.509 certificate (%ld)\n",
                   PTR_ERR(key));
        } else {
            set_bit(KEY_FLAG_BUILTIN, &key_ref_to_ptr(key)->flags);
            pr_notice("Loaded X.509 cert '%s'\n",
                      key_ref_to_ptr(key)->description);
            key_ref_put(key);
        }
        p += plen;
    }

    return 0;

dodgy_cert:
    pr_err("Problem parsing in-kernel X.509 certificate list\n");
    return 0;
}
Example #3
0
/*
 * Get the persistent keyring for a specific UID and link it to the nominated
 * keyring.
 */
static long key_get_persistent(struct user_namespace *ns, kuid_t uid,
			       key_ref_t dest_ref)
{
	struct keyring_index_key index_key;
	struct key *persistent;
	key_ref_t reg_ref, persistent_ref;
	char buf[32];
	long ret;

	/* Look in the register if it exists */
	index_key.type = &key_type_keyring;
	index_key.description = buf;
	index_key.desc_len = sprintf(buf, "_persistent.%u", from_kuid(ns, uid));

	if (ns->persistent_keyring_register) {
		reg_ref = make_key_ref(ns->persistent_keyring_register, true);
		down_read(&ns->persistent_keyring_register_sem);
		persistent_ref = find_key_to_update(reg_ref, &index_key);
		up_read(&ns->persistent_keyring_register_sem);

		if (persistent_ref)
			goto found;
	}

	/* It wasn't in the register, so we'll need to create it.  We might
	 * also need to create the register.
	 */
	down_write(&ns->persistent_keyring_register_sem);
	persistent_ref = key_create_persistent(ns, uid, &index_key);
	up_write(&ns->persistent_keyring_register_sem);
	if (!IS_ERR(persistent_ref))
		goto found;

	return PTR_ERR(persistent_ref);

found:
	ret = key_task_permission(persistent_ref, current_cred(), KEY_NEED_LINK);
	if (ret == 0) {
		persistent = key_ref_to_ptr(persistent_ref);
		ret = key_link(key_ref_to_ptr(dest_ref), persistent);
		if (ret == 0) {
			key_set_timeout(persistent, persistent_keyring_expiry);
			ret = persistent->serial;
		}
	}

	key_ref_put(persistent_ref);
	return ret;
}
Example #4
0
/*
 * get the ID of the specified process keyring
 * - the keyring must have search permission to be found
 * - implements keyctl(KEYCTL_GET_KEYRING_ID)
 */
long keyctl_get_keyring_ID(key_serial_t id, int create)
{
	key_ref_t key_ref;
	long ret;

	key_ref = lookup_user_key(NULL, id, create, 0, KEY_SEARCH);
	if (IS_ERR(key_ref)) {
		ret = PTR_ERR(key_ref);
		goto error;
	}

	ret = key_ref_to_ptr(key_ref)->serial;
	key_ref_put(key_ref);
 error:
	return ret;

} /* end keyctl_get_keyring_ID() */
Example #5
0
/*
 * Get the ID of the specified process keyring.
 *
 * The requested keyring must have search permission to be found.
 *
 * If successful, the ID of the requested keyring will be returned.
 */
long keyctl_get_keyring_ID(key_serial_t id, int create)
{
	key_ref_t key_ref;
	unsigned long lflags;
	long ret;

	lflags = create ? KEY_LOOKUP_CREATE : 0;
	key_ref = lookup_user_key(id, lflags, KEY_SEARCH);
	if (IS_ERR(key_ref)) {
		ret = PTR_ERR(key_ref);
		goto error;
	}

	ret = key_ref_to_ptr(key_ref)->serial;
	key_ref_put(key_ref);
error:
	return ret;
}
Example #6
0
/*
 * clear the specified process keyring
 * - the keyring must be writable
 * - implements keyctl(KEYCTL_CLEAR)
 */
long keyctl_keyring_clear(key_serial_t ringid)
{
	key_ref_t keyring_ref;
	long ret;

	keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
	if (IS_ERR(keyring_ref)) {
		ret = PTR_ERR(keyring_ref);
		goto error;
	}

	ret = keyring_clear(key_ref_to_ptr(keyring_ref));

	key_ref_put(keyring_ref);
 error:
	return ret;

} /* end keyctl_keyring_clear() */
Example #7
0
/*
 * revoke a key
 * - the key must be writable
 * - implements keyctl(KEYCTL_REVOKE)
 */
long keyctl_revoke_key(key_serial_t id)
{
	key_ref_t key_ref;
	long ret;

	key_ref = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
	if (IS_ERR(key_ref)) {
		ret = PTR_ERR(key_ref);
		goto error;
	}

	key_revoke(key_ref_to_ptr(key_ref));
	ret = 0;

	key_ref_put(key_ref);
 error:
	return ret;

} /* end keyctl_revoke_key() */
Example #8
0
/*
 * update a key's data payload
 * - the key must be writable
 * - implements keyctl(KEYCTL_UPDATE)
 */
long keyctl_update_key(key_serial_t id,
		       const void __user *_payload,
		       size_t plen)
{
	key_ref_t key_ref;
	void *payload;
	long ret;

	ret = -EINVAL;
	if (plen > PAGE_SIZE)
		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 target key (which must be writable) */
	key_ref = lookup_user_key(NULL, id, 0, 0, KEY_WRITE);
	if (IS_ERR(key_ref)) {
		ret = PTR_ERR(key_ref);
		goto error2;
	}

	/* update the key */
	ret = key_update(key_ref, payload, plen);

	key_ref_put(key_ref);
 error2:
	kfree(payload);
 error:
	return ret;

} /* end keyctl_update_key() */
Example #9
0
/*
 * Get the persistent keyring for a specific UID and link it to the nominated
 * keyring.
 */
long keyctl_get_persistent(uid_t _uid, key_serial_t destid)
{
	struct user_namespace *ns = current_user_ns();
	key_ref_t dest_ref;
	kuid_t uid;
	long ret;

	/* -1 indicates the current user */
	if (_uid == (uid_t)-1) {
		uid = current_uid();
	} else {
		uid = make_kuid(ns, _uid);
		if (!uid_valid(uid))
			return -EINVAL;

		/* You can only see your own persistent cache if you're not
		 * sufficiently privileged.
		 */
		if (!uid_eq(uid, current_uid()) &&
		    !uid_eq(uid, current_euid()) &&
		    !ns_capable(ns, CAP_SETUID))
			return -EPERM;
	}

	/* There must be a destination keyring */
	dest_ref = lookup_user_key(destid, KEY_LOOKUP_CREATE, KEY_NEED_WRITE);
	if (IS_ERR(dest_ref))
		return PTR_ERR(dest_ref);
	if (key_ref_to_ptr(dest_ref)->type != &key_type_keyring) {
		ret = -ENOTDIR;
		goto out_put_dest;
	}

	ret = key_get_persistent(ns, uid, dest_ref);

out_put_dest:
	key_ref_put(dest_ref);
	return ret;
}
Example #10
0
/*
 * 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() */
Example #11
0
int __init integrity_add_key(const unsigned int id, const void *data,
			     off_t size, key_perm_t perm)
{
	key_ref_t key;
	int rc = 0;

	if (!keyring[id])
		return -EINVAL;

	key = key_create_or_update(make_key_ref(keyring[id], 1), "asymmetric",
				   NULL, data, size, perm,
				   KEY_ALLOC_NOT_IN_QUOTA);
	if (IS_ERR(key)) {
		rc = PTR_ERR(key);
		pr_err("Problem loading X.509 certificate %d\n", rc);
	} else {
		pr_notice("Loaded X.509 cert '%s'\n",
			  key_ref_to_ptr(key)->description);
		key_ref_put(key);
	}

	return rc;

}
Example #12
0
/*
 * 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() */
Example #13
0
/*
 * extract the description of a new key from userspace and either add it as a
 * new key to the specified keyring or update a matching key in that keyring
 * - the keyring must be writable
 * - returns the new key's serial number
 * - implements add_key()
 */
asmlinkage long sys_add_key(const char __user *_type,
			    const char __user *_description,
			    const void __user *_payload,
			    size_t plen,
			    key_serial_t ringid)
{
	key_ref_t keyring_ref, key_ref;
	char type[32], *description;
	void *payload;
	long dlen, ret;

	ret = -EINVAL;
	if (plen > 32767)
		goto error;

	/* draw all the data into kernel space */
	ret = strncpy_from_user(type, _type, sizeof(type) - 1);
	if (ret < 0)
		goto error;
	type[31] = '\0';

	ret = -EPERM;
	if (type[0] == '.')
		goto error;

	ret = -EFAULT;
	dlen = strnlen_user(_description, PAGE_SIZE - 1);
	if (dlen <= 0)
		goto error;

	ret = -EINVAL;
	if (dlen > PAGE_SIZE - 1)
		goto error;

	ret = -ENOMEM;
	description = kmalloc(dlen + 1, GFP_KERNEL);
	if (!description)
		goto error;

	ret = -EFAULT;
	if (copy_from_user(description, _description, dlen + 1) != 0)
		goto error2;

	/* pull the payload in if one was supplied */
	payload = NULL;

	if (_payload) {
		ret = -ENOMEM;
		payload = kmalloc(plen, GFP_KERNEL);
		if (!payload)
			goto error2;

		ret = -EFAULT;
		if (copy_from_user(payload, _payload, plen) != 0)
			goto error3;
	}

	/* find the target keyring (which must be writable) */
	keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE);
	if (IS_ERR(keyring_ref)) {
		ret = PTR_ERR(keyring_ref);
		goto error3;
	}

	/* create or update the requested key and add it to the target
	 * keyring */
	key_ref = key_create_or_update(keyring_ref, type, description,
				       payload, plen, 0);
	if (!IS_ERR(key_ref)) {
		ret = key_ref_to_ptr(key_ref)->serial;
		key_ref_put(key_ref);
	}
	else {
		ret = PTR_ERR(key_ref);
	}

	key_ref_put(keyring_ref);
 error3:
	kfree(payload);
 error2:
	kfree(description);
 error:
	return ret;

} /* end sys_add_key() */
Example #14
0
/*
 * Extract the description of a new key from userspace and either add it as a
 * new key to the specified keyring or update a matching key in that keyring.
 *
 * If the description is NULL or an empty string, the key type is asked to
 * generate one from the payload.
 *
 * The keyring must be writable so that we can attach the key to it.
 *
 * If successful, the new key's serial number is returned, otherwise an error
 * code is returned.
 */
SYSCALL_DEFINE5(add_key, const char __user *, _type,
		const char __user *, _description,
		const void __user *, _payload,
		size_t, plen,
		key_serial_t, ringid)
{
	key_ref_t keyring_ref, key_ref;
	char type[32], *description;
	void *payload;
	long ret;
	bool vm;

	ret = -EINVAL;
	if (plen > 1024 * 1024 - 1)
		goto error;

	/* draw all the data into kernel space */
	ret = key_get_type_from_user(type, _type, sizeof(type));
	if (ret < 0)
		goto error;

	description = NULL;
	if (_description) {
		description = strndup_user(_description, PAGE_SIZE);
		if (IS_ERR(description)) {
			ret = PTR_ERR(description);
			goto error;
		}
		if (!*description) {
			kfree(description);
			description = NULL;
		}
	}

	/* pull the payload in if one was supplied */
	payload = NULL;

	vm = false;
	if (_payload) {
		ret = -ENOMEM;
		payload = kmalloc(plen, GFP_KERNEL | __GFP_NOWARN);
		if (!payload) {
			if (plen <= PAGE_SIZE)
				goto error2;
			vm = true;
			payload = vmalloc(plen);
			if (!payload)
				goto error2;
		}

		ret = -EFAULT;
		if (copy_from_user(payload, _payload, plen) != 0)
			goto error3;
	}

	/* find the target keyring (which must be writable) */
	keyring_ref = lookup_user_key(ringid, KEY_LOOKUP_CREATE, KEY_WRITE);
	if (IS_ERR(keyring_ref)) {
		ret = PTR_ERR(keyring_ref);
		goto error3;
	}

	/* create or update the requested key and add it to the target
	 * keyring */
	key_ref = key_create_or_update(keyring_ref, type, description,
				       payload, plen, KEY_PERM_UNDEF,
				       KEY_ALLOC_IN_QUOTA);
	if (!IS_ERR(key_ref)) {
		ret = key_ref_to_ptr(key_ref)->serial;
		key_ref_put(key_ref);
	}
	else {
		ret = PTR_ERR(key_ref);
	}

	key_ref_put(keyring_ref);
 error3:
	if (!vm)
		kfree(payload);
	else
		vfree(payload);
 error2:
	kfree(description);
 error:
	return ret;
}
Example #15
0
static int proc_keys_show(struct seq_file *m, void *v)
{
	const struct cred *cred = current_cred();
	struct rb_node *_p = v;
	struct key *key = rb_entry(_p, struct key, serial_node);
	struct timespec now;
	unsigned long timo;
	key_ref_t key_ref, skey_ref;
	char xbuf[12];
	int rc;

	key_ref = make_key_ref(key, 0);

	/*                                                                 
                                                               
  */
	if (key->perm & KEY_POS_VIEW) {
		skey_ref = search_my_process_keyrings(key->type, key,
						      lookup_user_key_possessed,
						      true, cred);
		if (!IS_ERR(skey_ref)) {
			key_ref_put(skey_ref);
			key_ref = make_key_ref(key, 1);
		}
	}

	/*                                                                    
                   
                                                                         
                                     
  */
	rc = key_task_permission(key_ref, cred, KEY_VIEW);
	if (rc < 0)
		return 0;

	now = current_kernel_time();

	rcu_read_lock();

	/*                                       */
	if (key->expiry == 0) {
		memcpy(xbuf, "perm", 5);
	} else if (now.tv_sec >= key->expiry) {
		memcpy(xbuf, "expd", 5);
	} else {
		timo = key->expiry - now.tv_sec;

		if (timo < 60)
			sprintf(xbuf, "%lus", timo);
		else if (timo < 60*60)
			sprintf(xbuf, "%lum", timo / 60);
		else if (timo < 60*60*24)
			sprintf(xbuf, "%luh", timo / (60*60));
		else if (timo < 60*60*24*7)
			sprintf(xbuf, "%lud", timo / (60*60*24));
		else
			sprintf(xbuf, "%luw", timo / (60*60*24*7));
	}

#define showflag(KEY, LETTER, FLAG) \
	(test_bit(FLAG,	&(KEY)->flags) ? LETTER : '-')

	seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ",
		   key->serial,
		   showflag(key, 'I', KEY_FLAG_INSTANTIATED),
		   showflag(key, 'R', KEY_FLAG_REVOKED),
		   showflag(key, 'D', KEY_FLAG_DEAD),
		   showflag(key, 'Q', KEY_FLAG_IN_QUOTA),
		   showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT),
		   showflag(key, 'N', KEY_FLAG_NEGATIVE),
		   atomic_read(&key->usage),
		   xbuf,
		   key->perm,
		   key->uid,
		   key->gid,
		   key->type->name);

#undef showflag

	if (key->type->describe)
		key->type->describe(key, m);
	seq_putc(m, '\n');

	rcu_read_unlock();
	return 0;
}
Example #16
0
/*
 * 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() */
Example #17
0
/*
 * Search the process keyrings and keyring trees linked from those for a
 * matching key.  Keyrings must have appropriate Search permission to be
 * searched.
 *
 * If a key is found, it will be attached to the destination keyring if there's
 * one specified and the serial number of the key will be returned.
 *
 * If no key is found, /sbin/request-key will be invoked if _callout_info is
 * non-NULL in an attempt to create a key.  The _callout_info string will be
 * passed to /sbin/request-key to aid with completing the request.  If the
 * _callout_info string is "" then it will be changed to "-".
 */
SYSCALL_DEFINE4(request_key, const char __user *, _type,
		const char __user *, _description,
		const char __user *, _callout_info,
		key_serial_t, destringid)
{
	struct key_type *ktype;
	struct key *key;
	key_ref_t dest_ref;
	size_t callout_len;
	char type[32], *description, *callout_info;
	long ret;

	/* pull the type into kernel space */
	ret = key_get_type_from_user(type, _type, sizeof(type));
	if (ret < 0)
		goto error;

	/* pull the description into kernel space */
	description = strndup_user(_description, PAGE_SIZE);
	if (IS_ERR(description)) {
		ret = PTR_ERR(description);
		goto error;
	}

	/* pull the callout info into kernel space */
	callout_info = NULL;
	callout_len = 0;
	if (_callout_info) {
		callout_info = strndup_user(_callout_info, PAGE_SIZE);
		if (IS_ERR(callout_info)) {
			ret = PTR_ERR(callout_info);
			goto error2;
		}
		callout_len = strlen(callout_info);
	}

	/* get the destination keyring if specified */
	dest_ref = NULL;
	if (destringid) {
		dest_ref = lookup_user_key(destringid, KEY_LOOKUP_CREATE,
					   KEY_WRITE);
		if (IS_ERR(dest_ref)) {
			ret = PTR_ERR(dest_ref);
			goto error3;
		}
	}

	/* find the key type */
	ktype = key_type_lookup(type);
	if (IS_ERR(ktype)) {
		ret = PTR_ERR(ktype);
		goto error4;
	}

	/* do the search */
	key = request_key_and_link(ktype, description, callout_info,
				   callout_len, NULL, key_ref_to_ptr(dest_ref),
				   KEY_ALLOC_IN_QUOTA);
	if (IS_ERR(key)) {
		ret = PTR_ERR(key);
		goto error5;
	}

	/* wait for the key to finish being constructed */
	ret = wait_for_key_construction(key, 1);
	if (ret < 0)
		goto error6;

	ret = key->serial;

error6:
 	key_put(key);
error5:
	key_type_put(ktype);
error4:
	key_ref_put(dest_ref);
error3:
	kfree(callout_info);
error2:
	kfree(description);
error:
	return ret;
}
Example #18
0
/*
 * search the specified keyring for a matching key
 * - the start keyring must be searchable
 * - nested keyrings may also be searched if they are searchable
 * - only keys with search permission may be found
 * - if a key is found, it will be attached to the destination keyring if
 *   there's one specified
 * - implements keyctl(KEYCTL_SEARCH)
 */
long keyctl_keyring_search(key_serial_t ringid,
			   const char __user *_type,
			   const char __user *_description,
			   key_serial_t destringid)
{
	struct key_type *ktype;
	key_ref_t keyring_ref, key_ref, dest_ref;
	char type[32], *description;
	long dlen, ret;

	/* pull the type and description into kernel space */
	ret = strncpy_from_user(type, _type, sizeof(type) - 1);
	if (ret < 0)
		goto error;
	type[31] = '\0';

	ret = -EFAULT;
	dlen = strnlen_user(_description, PAGE_SIZE - 1);
	if (dlen <= 0)
		goto error;

	ret = -EINVAL;
	if (dlen > PAGE_SIZE - 1)
		goto error;

	ret = -ENOMEM;
	description = kmalloc(dlen + 1, GFP_KERNEL);
	if (!description)
		goto error;

	ret = -EFAULT;
	if (copy_from_user(description, _description, dlen + 1) != 0)
		goto error2;

	/* get the keyring at which to begin the search */
	keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH);
	if (IS_ERR(keyring_ref)) {
		ret = PTR_ERR(keyring_ref);
		goto error2;
	}

	/* get the destination keyring if specified */
	dest_ref = NULL;
	if (destringid) {
		dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
		if (IS_ERR(dest_ref)) {
			ret = PTR_ERR(dest_ref);
			goto error3;
		}
	}

	/* find the key type */
	ktype = key_type_lookup(type);
	if (IS_ERR(ktype)) {
		ret = PTR_ERR(ktype);
		goto error4;
	}

	/* do the search */
	key_ref = keyring_search(keyring_ref, ktype, description);
	if (IS_ERR(key_ref)) {
		ret = PTR_ERR(key_ref);

		/* treat lack or presence of a negative key the same */
		if (ret == -EAGAIN)
			ret = -ENOKEY;
		goto error5;
	}

	/* link the resulting key to the destination keyring if we can */
	if (dest_ref) {
		ret = key_permission(key_ref, KEY_LINK);
		if (ret < 0)
			goto error6;

		ret = key_link(key_ref_to_ptr(dest_ref), key_ref_to_ptr(key_ref));
		if (ret < 0)
			goto error6;
	}

	ret = key_ref_to_ptr(key_ref)->serial;

 error6:
	key_ref_put(key_ref);
 error5:
	key_type_put(ktype);
 error4:
	key_ref_put(dest_ref);
 error3:
	key_ref_put(keyring_ref);
 error2:
	kfree(description);
 error:
	return ret;

} /* end keyctl_keyring_search() */
Example #19
0
/*
 * search the process keyrings for a matching key
 * - nested keyrings may also be searched if they have Search permission
 * - if a key is found, it will be attached to the destination keyring if
 *   there's one specified
 * - /sbin/request-key will be invoked if _callout_info is non-NULL
 *   - the _callout_info string will be passed to /sbin/request-key
 *   - if the _callout_info string is empty, it will be rendered as "-"
 * - implements request_key()
 */
asmlinkage long sys_request_key(const char __user *_type,
				const char __user *_description,
				const char __user *_callout_info,
				key_serial_t destringid)
{
	struct key_type *ktype;
	struct key *key;
	key_ref_t dest_ref;
	char type[32], *description, *callout_info;
	long dlen, ret;

	/* pull the type into kernel space */
	ret = strncpy_from_user(type, _type, sizeof(type) - 1);
	if (ret < 0)
		goto error;
	type[31] = '\0';

	ret = -EPERM;
	if (type[0] == '.')
		goto error;

	/* pull the description into kernel space */
	ret = -EFAULT;
	dlen = strnlen_user(_description, PAGE_SIZE - 1);
	if (dlen <= 0)
		goto error;

	ret = -EINVAL;
	if (dlen > PAGE_SIZE - 1)
		goto error;

	ret = -ENOMEM;
	description = kmalloc(dlen + 1, GFP_KERNEL);
	if (!description)
		goto error;

	ret = -EFAULT;
	if (copy_from_user(description, _description, dlen + 1) != 0)
		goto error2;

	/* pull the callout info into kernel space */
	callout_info = NULL;
	if (_callout_info) {
		ret = -EFAULT;
		dlen = strnlen_user(_callout_info, PAGE_SIZE - 1);
		if (dlen <= 0)
			goto error2;

		ret = -EINVAL;
		if (dlen > PAGE_SIZE - 1)
			goto error2;

		ret = -ENOMEM;
		callout_info = kmalloc(dlen + 1, GFP_KERNEL);
		if (!callout_info)
			goto error2;

		ret = -EFAULT;
		if (copy_from_user(callout_info, _callout_info, dlen + 1) != 0)
			goto error3;
	}

	/* get the destination keyring if specified */
	dest_ref = NULL;
	if (destringid) {
		dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE);
		if (IS_ERR(dest_ref)) {
			ret = PTR_ERR(dest_ref);
			goto error3;
		}
	}

	/* find the key type */
	ktype = key_type_lookup(type);
	if (IS_ERR(ktype)) {
		ret = PTR_ERR(ktype);
		goto error4;
	}

	/* do the search */
	key = request_key_and_link(ktype, description, callout_info,
				   key_ref_to_ptr(dest_ref));
	if (IS_ERR(key)) {
		ret = PTR_ERR(key);
		goto error5;
	}

	ret = key->serial;

 	key_put(key);
 error5:
	key_type_put(ktype);
 error4:
	key_ref_put(dest_ref);
 error3:
	kfree(callout_info);
 error2:
	kfree(description);
 error:
	return ret;

} /* end sys_request_key() */
Example #20
0
/*
 * Request an asymmetric key.
 */
static struct key *request_asymmetric_key(const char *signer, size_t signer_len,
					  const u8 *key_id, size_t key_id_len)
{
	key_ref_t key;
	size_t i;
	char *id, *q;

	pr_devel("==>%s(,%zu,,%zu)\n", __func__, signer_len, key_id_len);

	/* Construct an identifier. */
	id = kmalloc(signer_len + 2 + key_id_len * 2 + 1, GFP_KERNEL);
	if (!id)
		return ERR_PTR(-ENOKEY);

	memcpy(id, signer, signer_len);

	q = id + signer_len;
	*q++ = ':';
	*q++ = ' ';
	for (i = 0; i < key_id_len; i++) {
		*q++ = hex_asc[*key_id >> 4];
		*q++ = hex_asc[*key_id++ & 0x0f];
	}

	*q = 0;

	pr_debug("Look up: \"%s\"\n", id);

#ifdef CONFIG_MODULE_SIG_BLACKLIST
	key = keyring_search(make_key_ref(modsign_blacklist, 1),
				   &key_type_asymmetric, id);
	if (!IS_ERR(key)) {
		/* module is signed with a cert in the blacklist.  reject */
		pr_err("Module key '%s' is in blacklist\n", id);
		key_ref_put(key);
		kfree(id);
		return ERR_PTR(-EKEYREJECTED);
	}
#endif

	key = keyring_search(make_key_ref(modsign_keyring, 1),
			     &key_type_asymmetric, id);
	if (IS_ERR(key))
		pr_warn("Request for unknown module key '%s' err %ld\n",
			id, PTR_ERR(key));
	kfree(id);

	if (IS_ERR(key)) {
		switch (PTR_ERR(key)) {
			/* Hide some search errors */
		case -EACCES:
		case -ENOTDIR:
		case -EAGAIN:
			return ERR_PTR(-ENOKEY);
		default:
			return ERR_CAST(key);
		}
	}

	pr_devel("<==%s() = 0 [%x]\n", __func__, key_serial(key_ref_to_ptr(key)));
	return key_ref_to_ptr(key);
}
Example #21
0
static int proc_keys_show(struct seq_file *m, void *v)
{
	const struct cred *cred = current_cred();
	struct rb_node *_p = v;
	struct key *key = rb_entry(_p, struct key, serial_node);
	struct timespec now;
	unsigned long timo;
	key_ref_t key_ref, skey_ref;
	char xbuf[12];
	int rc;

	key_ref = make_key_ref(key, 0);

	/* determine if the key is possessed by this process (a test we can
	 * skip if the key does not indicate the possessor can view it
	 */
	if (key->perm & KEY_POS_VIEW) {
		skey_ref = search_my_process_keyrings(key->type, key,
						      lookup_user_key_possessed,
						      true, cred);
		if (!IS_ERR(skey_ref)) {
			key_ref_put(skey_ref);
			key_ref = make_key_ref(key, 1);
		}
	}

	/* check whether the current task is allowed to view the key (assuming
	 * non-possession)
	 * - the caller holds a spinlock, and thus the RCU read lock, making our
	 *   access to __current_cred() safe
	 */
	rc = key_task_permission(key_ref, cred, KEY_VIEW);
	if (rc < 0)
		return 0;

	now = current_kernel_time();

	rcu_read_lock();

	/* come up with a suitable timeout value */
	if (key->expiry == 0) {
		memcpy(xbuf, "perm", 5);
	} else if (now.tv_sec >= key->expiry) {
		memcpy(xbuf, "expd", 5);
	} else {
		timo = key->expiry - now.tv_sec;

		if (timo < 60)
			sprintf(xbuf, "%lus", timo);
		else if (timo < 60*60)
			sprintf(xbuf, "%lum", timo / 60);
		else if (timo < 60*60*24)
			sprintf(xbuf, "%luh", timo / (60*60));
		else if (timo < 60*60*24*7)
			sprintf(xbuf, "%lud", timo / (60*60*24));
		else
			sprintf(xbuf, "%luw", timo / (60*60*24*7));
	}

#define showflag(KEY, LETTER, FLAG) \
	(test_bit(FLAG,	&(KEY)->flags) ? LETTER : '-')

	seq_printf(m, "%08x %c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ",
		   key->serial,
		   showflag(key, 'I', KEY_FLAG_INSTANTIATED),
		   showflag(key, 'R', KEY_FLAG_REVOKED),
		   showflag(key, 'D', KEY_FLAG_DEAD),
		   showflag(key, 'Q', KEY_FLAG_IN_QUOTA),
		   showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT),
		   showflag(key, 'N', KEY_FLAG_NEGATIVE),
		   atomic_read(&key->usage),
		   xbuf,
		   key->perm,
		   key->uid,
		   key->gid,
		   key->type->name);

#undef showflag

	if (key->type->describe)
		key->type->describe(key, m);
	seq_putc(m, '\n');

	rcu_read_unlock();
	return 0;
}
Example #22
0
/*
 * 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() */