security/commoncap.c

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

File Facts

System
Linux kernel
Corpus path
security/commoncap.c
Extension
.c
Size
45073 bytes
Lines
1528
Domain
Core OS
Bucket
Security And Isolation
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 (alloc) {
			if (!nscap) {
				/* v2 -> v3 conversion */
				nscap = kzalloc(size, GFP_ATOMIC);
				if (!nscap) {
					size = -ENOMEM;
					goto out_free;
				}
				nsmagic = VFS_CAP_REVISION_3;
				magic = le32_to_cpu(cap->magic_etc);
				if (magic & VFS_CAP_FLAGS_EFFECTIVE)
					nsmagic |= VFS_CAP_FLAGS_EFFECTIVE;
				memcpy(&nscap->data, &cap->data, sizeof(__le32) * 2 * VFS_CAP_U32);
				nscap->magic_etc = cpu_to_le32(nsmagic);
			} else {
				/* use allocated v3 buffer */
				tmpbuf = NULL;
			}
			nscap->rootid = cpu_to_le32(mappedroot);
			*buffer = nscap;
		}
		goto out_free;
	}

	if (!vfsuid_root_in_currentns(vfsroot)) {
		size = -EOVERFLOW;
		goto out_free;
	}

	/* This comes from a parent namespace.  Return as a v2 capability */
	size = sizeof(struct vfs_cap_data);
	if (alloc) {
		if (nscap) {
			/* v3 -> v2 conversion */
			cap = kzalloc(size, GFP_ATOMIC);
			if (!cap) {
				size = -ENOMEM;
				goto out_free;
			}
			magic = VFS_CAP_REVISION_2;
			nsmagic = le32_to_cpu(nscap->magic_etc);
			if (nsmagic & VFS_CAP_FLAGS_EFFECTIVE)
				magic |= VFS_CAP_FLAGS_EFFECTIVE;
			memcpy(&cap->data, &nscap->data, sizeof(__le32) * 2 * VFS_CAP_U32);
			cap->magic_etc = cpu_to_le32(magic);
		} else {
			/* use unconverted v2 */
			tmpbuf = NULL;
		}
		*buffer = cap;
	}
out_free:
	kfree(tmpbuf);
	return size;
}

/**
 * rootid_from_xattr - translate root uid of vfs caps
 *
 * @value:	vfs caps value which may be modified by this function
 * @size:	size of @ivalue
 * @task_ns:	user namespace of the caller
 */
static vfsuid_t rootid_from_xattr(const void *value, size_t size,
				  struct user_namespace *task_ns)
{
	const struct vfs_ns_cap_data *nscap = value;
	uid_t rootid = 0;

	if (size == XATTR_CAPS_SZ_3)
		rootid = le32_to_cpu(nscap->rootid);

	return VFSUIDT_INIT(make_kuid(task_ns, rootid));
}

static bool validheader(size_t size, const struct vfs_cap_data *cap)
{
	return is_v2header(size, cap) || is_v3header(size, cap);
}

/**
 * cap_convert_nscap - check vfs caps
 *
 * @idmap:	idmap of the mount the inode was found from
 * @dentry:	used to retrieve inode to check permissions on
 * @ivalue:	vfs caps value which may be modified by this function
 * @size:	size of @ivalue
 *
 * User requested a write of security.capability.  If needed, update the
 * xattr to change from v2 to v3, or to fixup the v3 rootid.

Annotation

Implementation Notes