⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 key.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
		/* and link it into the destination keyring */		if (keyring)			ret = __key_link(keyring, key);		/* disable the authorisation key */		if (instkey)			key_revoke(instkey);	}	mutex_unlock(&key_construction_mutex);	if (keyring)		up_write(&keyring->sem);	/* wake up anyone waiting for a key to be constructed */	if (awaken)		wake_up_bit(&key->flags, KEY_FLAG_USER_CONSTRUCT);	return ret;} /* end key_negate_and_link() */EXPORT_SYMBOL(key_negate_and_link);/*****************************************************************************//* * do cleaning up in process context so that we don't have to disable * interrupts all over the place */static void key_cleanup(struct work_struct *work){	struct rb_node *_n;	struct key *key; go_again:	/* look for a dead key in the tree */	spin_lock(&key_serial_lock);	for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {		key = rb_entry(_n, struct key, serial_node);		if (atomic_read(&key->usage) == 0)			goto found_dead_key;	}	spin_unlock(&key_serial_lock);	return; found_dead_key:	/* we found a dead key - once we've removed it from the tree, we can	 * drop the lock */	rb_erase(&key->serial_node, &key_serial_tree);	spin_unlock(&key_serial_lock);	key_check(key);	security_key_free(key);	/* deal with the user's key tracking and quota */	if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {		spin_lock(&key->user->lock);		key->user->qnkeys--;		key->user->qnbytes -= key->quotalen;		spin_unlock(&key->user->lock);	}	atomic_dec(&key->user->nkeys);	if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags))		atomic_dec(&key->user->nikeys);	key_user_put(key->user);	/* now throw away the key memory */	if (key->type->destroy)		key->type->destroy(key);	kfree(key->description);#ifdef KEY_DEBUGGING	key->magic = KEY_DEBUG_MAGIC_X;#endif	kmem_cache_free(key_jar, key);	/* there may, of course, be more than one key to destroy */	goto go_again;} /* end key_cleanup() *//*****************************************************************************//* * dispose of a reference to a key * - when all the references are gone, we schedule the cleanup task to come and *   pull it out of the tree in definite process context */void key_put(struct key *key){	if (key) {		key_check(key);		if (atomic_dec_and_test(&key->usage))			schedule_work(&key_cleanup_task);	}} /* end key_put() */EXPORT_SYMBOL(key_put);/*****************************************************************************//* * find a key by its serial number */struct key *key_lookup(key_serial_t id){	struct rb_node *n;	struct key *key;	spin_lock(&key_serial_lock);	/* search the tree for the specified key */	n = key_serial_tree.rb_node;	while (n) {		key = rb_entry(n, struct key, serial_node);		if (id < key->serial)			n = n->rb_left;		else if (id > key->serial)			n = n->rb_right;		else			goto found;	} not_found:	key = ERR_PTR(-ENOKEY);	goto error; found:	/* pretend it doesn't exist if it's dead */	if (atomic_read(&key->usage) == 0 ||	    test_bit(KEY_FLAG_DEAD, &key->flags) ||	    key->type == &key_type_dead)		goto not_found;	/* this races with key_put(), but that doesn't matter since key_put()	 * doesn't actually change the key	 */	atomic_inc(&key->usage); error:	spin_unlock(&key_serial_lock);	return key;} /* end key_lookup() *//*****************************************************************************//* * find and lock the specified key type against removal * - we return with the sem readlocked */struct key_type *key_type_lookup(const char *type){	struct key_type *ktype;	down_read(&key_types_sem);	/* look up the key type to see if it's one of the registered kernel	 * types */	list_for_each_entry(ktype, &key_types_list, link) {		if (strcmp(ktype->name, type) == 0)			goto found_kernel_type;	}	up_read(&key_types_sem);	ktype = ERR_PTR(-ENOKEY); found_kernel_type:	return ktype;} /* end key_type_lookup() *//*****************************************************************************//* * unlock a key type */void key_type_put(struct key_type *ktype){	up_read(&key_types_sem);} /* end key_type_put() *//*****************************************************************************//* * attempt to update an existing key * - the key has an incremented refcount * - we need to put the key if we get an error */static inline key_ref_t __key_update(key_ref_t key_ref,				     const void *payload, size_t plen){	struct key *key = key_ref_to_ptr(key_ref);	int ret;	/* need write permission on the key to update it */	ret = key_permission(key_ref, KEY_WRITE);	if (ret < 0)		goto error;	ret = -EEXIST;	if (!key->type->update)		goto error;	down_write(&key->sem);	ret = key->type->update(key, payload, plen);	if (ret == 0)		/* updating a negative key instantiates it */		clear_bit(KEY_FLAG_NEGATIVE, &key->flags);	up_write(&key->sem);	if (ret < 0)		goto error;out:	return key_ref;error:	key_put(key);	key_ref = ERR_PTR(ret);	goto out;} /* end __key_update() *//*****************************************************************************//* * search the specified keyring for a key of the same description; if one is * found, update it, otherwise add a new one */key_ref_t key_create_or_update(key_ref_t keyring_ref,			       const char *type,			       const char *description,			       const void *payload,			       size_t plen,			       unsigned long flags){	struct key_type *ktype;	struct key *keyring, *key = NULL;	key_perm_t perm;	key_ref_t key_ref;	int ret;	/* look up the key type to see if it's one of the registered kernel	 * types */	ktype = key_type_lookup(type);	if (IS_ERR(ktype)) {		key_ref = ERR_PTR(-ENODEV);		goto error;	}	key_ref = ERR_PTR(-EINVAL);	if (!ktype->match || !ktype->instantiate)		goto error_2;	keyring = key_ref_to_ptr(keyring_ref);	key_check(keyring);	key_ref = ERR_PTR(-ENOTDIR);	if (keyring->type != &key_type_keyring)		goto error_2;	down_write(&keyring->sem);	/* if we're going to allocate a new key, we're going to have	 * to modify the keyring */	ret = key_permission(keyring_ref, KEY_WRITE);	if (ret < 0) {		key_ref = ERR_PTR(ret);		goto error_3;	}	/* if it's possible to update this type of key, search for an existing	 * key of the same type and description in the destination keyring and	 * update that instead if possible	 */	if (ktype->update) {		key_ref = __keyring_search_one(keyring_ref, ktype, description,					       0);		if (!IS_ERR(key_ref))			goto found_matching_key;	}	/* decide on the permissions we want */	perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;	perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR;	if (ktype->read)		perm |= KEY_POS_READ | KEY_USR_READ;	if (ktype == &key_type_keyring || ktype->update)		perm |= KEY_USR_WRITE;	/* allocate a new key */	key = key_alloc(ktype, description, current->fsuid, current->fsgid,			current, perm, flags);	if (IS_ERR(key)) {		key_ref = ERR_PTR(PTR_ERR(key));		goto error_3;	}	/* instantiate it and link it into the target keyring */	ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL);	if (ret < 0) {		key_put(key);		key_ref = ERR_PTR(ret);		goto error_3;	}	key_ref = make_key_ref(key, is_key_possessed(keyring_ref)); error_3:	up_write(&keyring->sem); error_2:	key_type_put(ktype); error:	return key_ref; found_matching_key:	/* we found a matching key, so we're going to try to update it	 * - we can drop the locks first as we have the key pinned	 */	up_write(&keyring->sem);	key_type_put(ktype);	key_ref = __key_update(key_ref, payload, plen);	goto error;} /* end key_create_or_update() */EXPORT_SYMBOL(key_create_or_update);/*****************************************************************************//* * update a key */int key_update(key_ref_t key_ref, const void *payload, size_t plen){	struct key *key = key_ref_to_ptr(key_ref);	int ret;	key_check(key);	/* the key must be writable */	ret = key_permission(key_ref, KEY_WRITE);	if (ret < 0)		goto error;	/* attempt to update it if supported */	ret = -EOPNOTSUPP;	if (key->type->update) {		down_write(&key->sem);		ret = key->type->update(key, payload, plen);		if (ret == 0)			/* updating a negative key instantiates it */			clear_bit(KEY_FLAG_NEGATIVE, &key->flags);		up_write(&key->sem);	} error:	return ret;} /* end key_update() */EXPORT_SYMBOL(key_update);/*****************************************************************************//* * revoke a key */void key_revoke(struct key *key){	key_check(key);	/* make sure no one's trying to change or use the key when we mark it	 * - we tell lockdep that we might nest because we might be revoking an	 *   authorisation key whilst holding the sem on a key we've just	 *   instantiated	 */	down_write_nested(&key->sem, 1);	if (!test_and_set_bit(KEY_FLAG_REVOKED, &key->flags) &&	    key->type->revoke)		key->type->revoke(key);	up_write(&key->sem);} /* end key_revoke() */EXPORT_SYMBOL(key_revoke);/*****************************************************************************//* * register a type of key */int register_key_type(struct key_type *ktype){	struct key_type *p;	int ret;	ret = -EEXIST;	down_write(&key_types_sem);	/* disallow key types with the same name */	list_for_each_entry(p, &key_types_list, link) {		if (strcmp(p->name, ktype->name) == 0)			goto out;	}	/* store the type */	list_add(&ktype->link, &key_types_list);	ret = 0; out:	up_write(&key_types_sem);	return ret;} /* end register_key_type() */EXPORT_SYMBOL(register_key_type);/*****************************************************************************//* * unregister a type of key */void unregister_key_type(struct key_type *ktype){	struct rb_node *_n;	struct key *key;	down_write(&key_types_sem);	/* withdraw the key type */	list_del_init(&ktype->link);	/* mark all the keys of this type dead */	spin_lock(&key_serial_lock);	for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {		key = rb_entry(_n, struct key, serial_node);		if (key->type == ktype)			key->type = &key_type_dead;	}	spin_unlock(&key_serial_lock);	/* make sure everyone revalidates their keys */	synchronize_rcu();	/* we should now be able to destroy the payloads of all the keys of	 * this type with impunity */	spin_lock(&key_serial_lock);	for (_n = rb_first(&key_serial_tree); _n; _n = rb_next(_n)) {		key = rb_entry(_n, struct key, serial_node);		if (key->type == ktype) {			if (ktype->destroy)				ktype->destroy(key);			memset(&key->payload, KEY_DESTROY, sizeof(key->payload));		}	}	spin_unlock(&key_serial_lock);	up_write(&key_types_sem);} /* end unregister_key_type() */EXPORT_SYMBOL(unregister_key_type);/*****************************************************************************//* * initialise the key management stuff */void __init key_init(void){	/* allocate a slab in which we can store keys */	key_jar = kmem_cache_create("key_jar", sizeof(struct key),			0, SLAB_HWCACHE_ALIGN|SLAB_PANIC, NULL);	/* add the special key types */	list_add_tail(&key_type_keyring.link, &key_types_list);	list_add_tail(&key_type_dead.link, &key_types_list);	list_add_tail(&key_type_user.link, &key_types_list);	/* record the root user tracking */	rb_link_node(&root_key_user.node,		     NULL,		     &key_user_tree.rb_node);	rb_insert_color(&root_key_user.node,			&key_user_tree);	/* record root's user standard keyrings */	key_check(&root_user_keyring);	key_check(&root_session_keyring);	__key_insert_serial(&root_user_keyring);	__key_insert_serial(&root_session_keyring);	keyring_publish_name(&root_user_keyring);	keyring_publish_name(&root_session_keyring);	/* link the two root keyrings together */	key_link(&root_session_keyring, &root_user_keyring);} /* end key_init() */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -