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

📄 keyring.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
 * find a keyring with the specified name * - all named keyrings are searched * - only find keyrings with search permission for the process * - only find keyrings with a serial number greater than the one specified */struct key *find_keyring_by_name(const char *name, key_serial_t bound){	struct key *keyring;	int bucket;	keyring = ERR_PTR(-EINVAL);	if (!name)		goto error;	bucket = keyring_hash(name);	read_lock(&keyring_name_lock);	if (keyring_name_hash[bucket].next) {		/* search this hash bucket for a keyring with a matching name		 * that's readable and that hasn't been revoked */		list_for_each_entry(keyring,				    &keyring_name_hash[bucket],				    type_data.link				    ) {			if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))				continue;			if (strcmp(keyring->description, name) != 0)				continue;			if (key_permission(make_key_ref(keyring, 0),					   KEY_SEARCH) < 0)				continue;			/* found a potential candidate, but we still need to			 * check the serial number */			if (keyring->serial <= bound)				continue;			/* we've got a match */			atomic_inc(&keyring->usage);			read_unlock(&keyring_name_lock);			goto error;		}	}	read_unlock(&keyring_name_lock);	keyring = ERR_PTR(-ENOKEY); error:	return keyring;} /* end find_keyring_by_name() *//*****************************************************************************//* * see if a cycle will will be created by inserting acyclic tree B in acyclic * tree A at the topmost level (ie: as a direct child of A) * - since we are adding B to A at the top level, checking for cycles should *   just be a matter of seeing if node A is somewhere in tree B */static int keyring_detect_cycle(struct key *A, struct key *B){	struct {		struct keyring_list *keylist;		int kix;	} stack[KEYRING_SEARCH_MAX_DEPTH];	struct keyring_list *keylist;	struct key *subtree, *key;	int sp, kix, ret;	rcu_read_lock();	ret = -EDEADLK;	if (A == B)		goto cycle_detected;	subtree = B;	sp = 0;	/* start processing a new keyring */ descend:	if (test_bit(KEY_FLAG_REVOKED, &subtree->flags))		goto not_this_keyring;	keylist = rcu_dereference(subtree->payload.subscriptions);	if (!keylist)		goto not_this_keyring;	kix = 0; ascend:	/* iterate through the remaining keys in this keyring */	for (; kix < keylist->nkeys; kix++) {		key = keylist->keys[kix];		if (key == A)			goto cycle_detected;		/* recursively check nested keyrings */		if (key->type == &key_type_keyring) {			if (sp >= KEYRING_SEARCH_MAX_DEPTH)				goto too_deep;			/* stack the current position */			stack[sp].keylist = keylist;			stack[sp].kix = kix;			sp++;			/* begin again with the new keyring */			subtree = key;			goto descend;		}	}	/* the keyring we're looking at was disqualified or didn't contain a	 * matching key */ not_this_keyring:	if (sp > 0) {		/* resume the checking of a keyring higher up in the tree */		sp--;		keylist = stack[sp].keylist;		kix = stack[sp].kix + 1;		goto ascend;	}	ret = 0; /* no cycles detected */ error:	rcu_read_unlock();	return ret; too_deep:	ret = -ELOOP;	goto error; cycle_detected:	ret = -EDEADLK;	goto error;} /* end keyring_detect_cycle() *//*****************************************************************************//* * dispose of a keyring list after the RCU grace period */static void keyring_link_rcu_disposal(struct rcu_head *rcu){	struct keyring_list *klist =		container_of(rcu, struct keyring_list, rcu);	kfree(klist);} /* end keyring_link_rcu_disposal() *//*****************************************************************************//* * dispose of a keyring list after the RCU grace period, freeing the unlinked * key */static void keyring_unlink_rcu_disposal(struct rcu_head *rcu){	struct keyring_list *klist =		container_of(rcu, struct keyring_list, rcu);	key_put(klist->keys[klist->delkey]);	kfree(klist);} /* end keyring_unlink_rcu_disposal() *//*****************************************************************************//* * link a key into to a keyring * - must be called with the keyring's semaphore write-locked * - discard already extant link to matching key if there is one */int __key_link(struct key *keyring, struct key *key){	struct keyring_list *klist, *nklist;	unsigned max;	size_t size;	int loop, ret;	ret = -EKEYREVOKED;	if (test_bit(KEY_FLAG_REVOKED, &keyring->flags))		goto error;	ret = -ENOTDIR;	if (keyring->type != &key_type_keyring)		goto error;	/* serialise link/link calls to prevent parallel calls causing a	 * cycle when applied to two keyring in opposite orders */	down_write(&keyring_serialise_link_sem);	/* check that we aren't going to create a cycle adding one keyring to	 * another */	if (key->type == &key_type_keyring) {		ret = keyring_detect_cycle(keyring, key);		if (ret < 0)			goto error2;	}	/* see if there's a matching key we can displace */	klist = keyring->payload.subscriptions;	if (klist && klist->nkeys > 0) {		struct key_type *type = key->type;		for (loop = klist->nkeys - 1; loop >= 0; loop--) {			if (klist->keys[loop]->type == type &&			    strcmp(klist->keys[loop]->description,				   key->description) == 0			    ) {				/* found a match - replace with new key */				size = sizeof(struct key *) * klist->maxkeys;				size += sizeof(*klist);				BUG_ON(size > PAGE_SIZE);				ret = -ENOMEM;				nklist = kmemdup(klist, size, GFP_KERNEL);				if (!nklist)					goto error2;				/* replace matched key */				atomic_inc(&key->usage);				nklist->keys[loop] = key;				rcu_assign_pointer(					keyring->payload.subscriptions,					nklist);				/* dispose of the old keyring list and the				 * displaced key */				klist->delkey = loop;				call_rcu(&klist->rcu,					 keyring_unlink_rcu_disposal);				goto done;			}		}	}	/* check that we aren't going to overrun the user's quota */	ret = key_payload_reserve(keyring,				  keyring->datalen + KEYQUOTA_LINK_BYTES);	if (ret < 0)		goto error2;	klist = keyring->payload.subscriptions;	if (klist && klist->nkeys < klist->maxkeys) {		/* there's sufficient slack space to add directly */		atomic_inc(&key->usage);		klist->keys[klist->nkeys] = key;		smp_wmb();		klist->nkeys++;		smp_wmb();	}	else {		/* grow the key list */		max = 4;		if (klist)			max += klist->maxkeys;		ret = -ENFILE;		if (max > 65535)			goto error3;		size = sizeof(*klist) + sizeof(struct key *) * max;		if (size > PAGE_SIZE)			goto error3;		ret = -ENOMEM;		nklist = kmalloc(size, GFP_KERNEL);		if (!nklist)			goto error3;		nklist->maxkeys = max;		nklist->nkeys = 0;		if (klist) {			nklist->nkeys = klist->nkeys;			memcpy(nklist->keys,			       klist->keys,			       sizeof(struct key *) * klist->nkeys);		}		/* add the key into the new space */		atomic_inc(&key->usage);		nklist->keys[nklist->nkeys++] = key;		rcu_assign_pointer(keyring->payload.subscriptions, nklist);		/* dispose of the old keyring list */		if (klist)			call_rcu(&klist->rcu, keyring_link_rcu_disposal);	}done:	ret = 0;error2:	up_write(&keyring_serialise_link_sem);error:	return ret;error3:	/* undo the quota changes */	key_payload_reserve(keyring,			    keyring->datalen - KEYQUOTA_LINK_BYTES);	goto error2;} /* end __key_link() *//*****************************************************************************//* * link a key to a keyring */int key_link(struct key *keyring, struct key *key){	int ret;	key_check(keyring);	key_check(key);	down_write(&keyring->sem);	ret = __key_link(keyring, key);	up_write(&keyring->sem);	return ret;} /* end key_link() */EXPORT_SYMBOL(key_link);/*****************************************************************************//* * unlink the first link to a key from a keyring */int key_unlink(struct key *keyring, struct key *key){	struct keyring_list *klist, *nklist;	int loop, ret;	key_check(keyring);	key_check(key);	ret = -ENOTDIR;	if (keyring->type != &key_type_keyring)		goto error;	down_write(&keyring->sem);	klist = keyring->payload.subscriptions;	if (klist) {		/* search the keyring for the key */		for (loop = 0; loop < klist->nkeys; loop++)			if (klist->keys[loop] == key)				goto key_is_present;	}	up_write(&keyring->sem);	ret = -ENOENT;	goto error;key_is_present:	/* we need to copy the key list for RCU purposes */	nklist = kmalloc(sizeof(*klist) +			 sizeof(struct key *) * klist->maxkeys,			 GFP_KERNEL);	if (!nklist)		goto nomem;	nklist->maxkeys = klist->maxkeys;	nklist->nkeys = klist->nkeys - 1;	if (loop > 0)		memcpy(&nklist->keys[0],		       &klist->keys[0],		       loop * sizeof(struct key *));	if (loop < nklist->nkeys)		memcpy(&nklist->keys[loop],		       &klist->keys[loop + 1],		       (nklist->nkeys - loop) * sizeof(struct key *));	/* adjust the user's quota */	key_payload_reserve(keyring,			    keyring->datalen - KEYQUOTA_LINK_BYTES);	rcu_assign_pointer(keyring->payload.subscriptions, nklist);	up_write(&keyring->sem);	/* schedule for later cleanup */	klist->delkey = loop;	call_rcu(&klist->rcu, keyring_unlink_rcu_disposal);	ret = 0;error:	return ret;nomem:	ret = -ENOMEM;	up_write(&keyring->sem);	goto error;} /* end key_unlink() */EXPORT_SYMBOL(key_unlink);/*****************************************************************************//* * dispose of a keyring list after the RCU grace period, releasing the keys it * links to */static void keyring_clear_rcu_disposal(struct rcu_head *rcu){	struct keyring_list *klist;	int loop;	klist = container_of(rcu, struct keyring_list, rcu);	for (loop = klist->nkeys - 1; loop >= 0; loop--)		key_put(klist->keys[loop]);	kfree(klist);} /* end keyring_clear_rcu_disposal() *//*****************************************************************************//* * clear the specified process keyring * - implements keyctl(KEYCTL_CLEAR) */int keyring_clear(struct key *keyring){	struct keyring_list *klist;	int ret;	ret = -ENOTDIR;	if (keyring->type == &key_type_keyring) {		/* detach the pointer block with the locks held */		down_write(&keyring->sem);		klist = keyring->payload.subscriptions;		if (klist) {			/* adjust the quota */			key_payload_reserve(keyring,					    sizeof(struct keyring_list));			rcu_assign_pointer(keyring->payload.subscriptions,					   NULL);		}		up_write(&keyring->sem);		/* free the keys after the locks have been dropped */		if (klist)			call_rcu(&klist->rcu, keyring_clear_rcu_disposal);		ret = 0;	}	return ret;} /* end keyring_clear() */EXPORT_SYMBOL(keyring_clear);/*****************************************************************************//* * dispose of the links from a revoked keyring * - called with the key sem write-locked */static void keyring_revoke(struct key *keyring){	struct keyring_list *klist = keyring->payload.subscriptions;	/* adjust the quota */	key_payload_reserve(keyring, 0);	if (klist) {		rcu_assign_pointer(keyring->payload.subscriptions, NULL);		call_rcu(&klist->rcu, keyring_clear_rcu_disposal);	}} /* end keyring_revoke() */

⌨️ 快捷键说明

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