fs/afs/security.c

Source file repositories/reference/linux-study-clean/fs/afs/security.c

File Facts

System
Linux kernel
Corpus path
fs/afs/security.c
Extension
.c
Size
12518 bytes
Lines
521
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (PTR_ERR(key) != -ENOKEY) {
			_leave(" = %ld", PTR_ERR(key));
			return key;
		}

		if (!cell->anonymous_key) {
			ret = afs_alloc_anon_key(cell);
			if (ret < 0)
				return ERR_PTR(ret);
		}

		/* act as anonymous user */
		_leave(" = {%x} [anon]", key_serial(cell->anonymous_key));
		return key_get(cell->anonymous_key);
	} else {
		/* act as authorised user */
		_leave(" = {%x} [auth]", key_serial(key));
		return key;
	}
}

/*
 * Get a key when pathwalk is in rcuwalk mode.
 */
struct key *afs_request_key_rcu(struct afs_cell *cell)
{
	struct key *key;

	_enter("{%s}", cell->key_desc);

	_debug("key %s", cell->key_desc);
	key = request_key_net_rcu(&key_type_rxrpc, cell->key_desc,
				  cell->net->net);
	if (IS_ERR(key)) {
		if (PTR_ERR(key) != -ENOKEY) {
			_leave(" = %ld", PTR_ERR(key));
			return key;
		}

		/* act as anonymous user */
		if (!cell->anonymous_key)
			return NULL; /* Need to allocate */
		_leave(" = {%x} [anon]", key_serial(cell->anonymous_key));
		return key_get(cell->anonymous_key);
	} else {
		/* act as authorised user */
		_leave(" = {%x} [auth]", key_serial(key));
		return key;
	}
}

/*
 * Dispose of a list of permits.
 */
static void afs_permits_rcu(struct rcu_head *rcu)
{
	struct afs_permits *permits =
		container_of(rcu, struct afs_permits, rcu);
	int i;

	for (i = 0; i < permits->nr_permits; i++)
		key_put(permits->permits[i].key);
	kfree(permits);
}

/*
 * Discard a permission cache.
 */
void afs_put_permits(struct afs_permits *permits)
{
	if (permits && refcount_dec_and_test(&permits->usage)) {
		spin_lock(&afs_permits_lock);
		hash_del_rcu(&permits->hash_node);
		spin_unlock(&afs_permits_lock);
		call_rcu(&permits->rcu, afs_permits_rcu);
	}
}

/*
 * Clear a permit cache on callback break.
 */
void afs_clear_permits(struct afs_vnode *vnode)
{
	struct afs_permits *permits;

	spin_lock(&vnode->lock);
	permits = rcu_dereference_protected(vnode->permit_cache,
					    lockdep_is_held(&vnode->lock));
	RCU_INIT_POINTER(vnode->permit_cache, NULL);
	spin_unlock(&vnode->lock);

Annotation

Implementation Notes