1485 lines · 43.0 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0-or-later/* Common capabilities, needed by capability.o. */ #include <linux/capability.h>#include <linux/audit.h>#include <linux/init.h>#include <linux/kernel.h>#include <linux/lsm_hooks.h>#include <linux/file.h>#include <linux/mm.h>#include <linux/mman.h>#include <linux/pagemap.h>#include <linux/swap.h>#include <linux/skbuff.h>#include <linux/netlink.h>#include <linux/ptrace.h>#include <linux/xattr.h>#include <linux/hugetlb.h>#include <linux/mount.h>#include <linux/sched.h>#include <linux/prctl.h>#include <linux/securebits.h>#include <linux/user_namespace.h>#include <linux/binfmts.h>#include <linux/personality.h>#include <linux/mnt_idmapping.h> /* * If a non-root user executes a setuid-root binary in * !secure(SECURE_NOROOT) mode, then we raise capabilities. * However if fE is also set, then the intent is for only * the file capabilities to be applied, and the setuid-root * bit is left on either to change the uid (plausible) or * to get full privilege on a kernel without file capabilities * support.  So in that case we do not raise capabilities. * * Warn if that happens, once per boot. */static void warn_setuid_and_fcaps_mixed(const char *fname){	static int warned;	if (!warned) {		printk(KERN_INFO "warning: `%s' has both setuid-root and"			" effective capabilities. Therefore not raising all"			" capabilities.\n", fname);		warned = 1;	}} /** * cap_capable - Determine whether a task has a particular effective capability * @cred: The credentials to use * @targ_ns:  The user namespace in which we need the capability * @cap: The capability to check for * @opts: Bitmask of options defined in include/linux/security.h * * Determine whether the nominated task has the specified capability amongst * its effective set, returning 0 if it does, -ve if it does not. * * NOTE WELL: cap_has_capability() cannot be used like the kernel's capable() * and has_capability() functions.  That is, it has the reverse semantics: * cap_has_capability() returns 0 when a task has a capability, but the * kernel's capable() and has_capability() returns 1 for this case. */int cap_capable(const struct cred *cred, struct user_namespace *targ_ns,		int cap, unsigned int opts){	struct user_namespace *ns = targ_ns; 	/* See if cred has the capability in the target user namespace	 * by examining the target user namespace and all of the target	 * user namespace's parents.	 */	for (;;) {		/* Do we have the necessary capabilities? */		if (ns == cred->user_ns)			return cap_raised(cred->cap_effective, cap) ? 0 : -EPERM; 		/*		 * If we're already at a lower level than we're looking for,		 * we're done searching.		 */		if (ns->level <= cred->user_ns->level)			return -EPERM; 		/* 		 * The owner of the user namespace in the parent of the		 * user namespace has all caps.		 */		if ((ns->parent == cred->user_ns) && uid_eq(ns->owner, cred->euid))			return 0; 		/*		 * If you have a capability in a parent user ns, then you have		 * it over all children user namespaces as well.		 */		ns = ns->parent;	} 	/* We never get here */} /** * cap_settime - Determine whether the current process may set the system clock * @ts: The time to set * @tz: The timezone to set * * Determine whether the current process may set the system clock and timezone * information, returning 0 if permission granted, -ve if denied. */int cap_settime(const struct timespec64 *ts, const struct timezone *tz){	if (!capable(CAP_SYS_TIME))		return -EPERM;	return 0;} /** * cap_ptrace_access_check - Determine whether the current process may access *			   another * @child: The process to be accessed * @mode: The mode of attachment. * * If we are in the same or an ancestor user_ns and have all the target * task's capabilities, then ptrace access is allowed. * If we have the ptrace capability to the target user_ns, then ptrace * access is allowed. * Else denied. * * Determine whether a process may access another, returning 0 if permission * granted, -ve if denied. */int cap_ptrace_access_check(struct task_struct *child, unsigned int mode){	int ret = 0;	const struct cred *cred, *child_cred;	const kernel_cap_t *caller_caps; 	rcu_read_lock();	cred = current_cred();	child_cred = __task_cred(child);	if (mode & PTRACE_MODE_FSCREDS)		caller_caps = &cred->cap_effective;	else		caller_caps = &cred->cap_permitted;	if (cred->user_ns == child_cred->user_ns &&	    cap_issubset(child_cred->cap_permitted, *caller_caps))		goto out;	if (ns_capable(child_cred->user_ns, CAP_SYS_PTRACE))		goto out;	ret = -EPERM;out:	rcu_read_unlock();	return ret;} /** * cap_ptrace_traceme - Determine whether another process may trace the current * @parent: The task proposed to be the tracer * * If parent is in the same or an ancestor user_ns and has all current's * capabilities, then ptrace access is allowed. * If parent has the ptrace capability to current's user_ns, then ptrace * access is allowed. * Else denied. * * Determine whether the nominated task is permitted to trace the current * process, returning 0 if permission is granted, -ve if denied. */int cap_ptrace_traceme(struct task_struct *parent){	int ret = 0;	const struct cred *cred, *child_cred; 	rcu_read_lock();	cred = __task_cred(parent);	child_cred = current_cred();	if (cred->user_ns == child_cred->user_ns &&	    cap_issubset(child_cred->cap_permitted, cred->cap_permitted))		goto out;	if (has_ns_capability(parent, child_cred->user_ns, CAP_SYS_PTRACE))		goto out;	ret = -EPERM;out:	rcu_read_unlock();	return ret;} /** * cap_capget - Retrieve a task's capability sets * @target: The task from which to retrieve the capability sets * @effective: The place to record the effective set * @inheritable: The place to record the inheritable set * @permitted: The place to record the permitted set * * This function retrieves the capabilities of the nominated task and returns * them to the caller. */int cap_capget(struct task_struct *target, kernel_cap_t *effective,	       kernel_cap_t *inheritable, kernel_cap_t *permitted){	const struct cred *cred; 	/* Derived from kernel/capability.c:sys_capget. */	rcu_read_lock();	cred = __task_cred(target);	*effective   = cred->cap_effective;	*inheritable = cred->cap_inheritable;	*permitted   = cred->cap_permitted;	rcu_read_unlock();	return 0;} /* * Determine whether the inheritable capabilities are limited to the old * permitted set.  Returns 1 if they are limited, 0 if they are not. */static inline int cap_inh_is_capped(void){	/* they are so limited unless the current task has the CAP_SETPCAP	 * capability	 */	if (cap_capable(current_cred(), current_cred()->user_ns,			CAP_SETPCAP, CAP_OPT_NONE) == 0)		return 0;	return 1;} /** * cap_capset - Validate and apply proposed changes to current's capabilities * @new: The proposed new credentials; alterations should be made here * @old: The current task's current credentials * @effective: A pointer to the proposed new effective capabilities set * @inheritable: A pointer to the proposed new inheritable capabilities set * @permitted: A pointer to the proposed new permitted capabilities set * * This function validates and applies a proposed mass change to the current * process's capability sets.  The changes are made to the proposed new * credentials, and assuming no error, will be committed by the caller of LSM. */int cap_capset(struct cred *new,	       const struct cred *old,	       const kernel_cap_t *effective,	       const kernel_cap_t *inheritable,	       const kernel_cap_t *permitted){	if (cap_inh_is_capped() &&	    !cap_issubset(*inheritable,			  cap_combine(old->cap_inheritable,				      old->cap_permitted)))		/* incapable of using this inheritable set */		return -EPERM; 	if (!cap_issubset(*inheritable,			  cap_combine(old->cap_inheritable,				      old->cap_bset)))		/* no new pI capabilities outside bounding set */		return -EPERM; 	/* verify restrictions on target's new Permitted set */	if (!cap_issubset(*permitted, old->cap_permitted))		return -EPERM; 	/* verify the _new_Effective_ is a subset of the _new_Permitted_ */	if (!cap_issubset(*effective, *permitted))		return -EPERM; 	new->cap_effective   = *effective;	new->cap_inheritable = *inheritable;	new->cap_permitted   = *permitted; 	/*	 * Mask off ambient bits that are no longer both permitted and	 * inheritable.	 */	new->cap_ambient = cap_intersect(new->cap_ambient,					 cap_intersect(*permitted,						       *inheritable));	if (WARN_ON(!cap_ambient_invariant_ok(new)))		return -EINVAL;	return 0;} /** * cap_inode_need_killpriv - Determine if inode change affects privileges * @dentry: The inode/dentry in being changed with change marked ATTR_KILL_PRIV * * Determine if an inode having a change applied that's marked ATTR_KILL_PRIV * affects the security markings on that inode, and if it is, should * inode_killpriv() be invoked or the change rejected. * * Return: 1 if security.capability has a value, meaning inode_killpriv() * is required, 0 otherwise, meaning inode_killpriv() is not required. */int cap_inode_need_killpriv(struct dentry *dentry){	struct inode *inode = d_backing_inode(dentry);	int error; 	error = __vfs_getxattr(dentry, inode, XATTR_NAME_CAPS, NULL, 0);	return error > 0;} /** * cap_inode_killpriv - Erase the security markings on an inode * * @mnt_userns:	user namespace of the mount the inode was found from * @dentry:	The inode/dentry to alter * * Erase the privilege-enhancing security markings on an inode. * * If the inode has been found through an idmapped mount the user namespace of * the vfsmount must be passed through @mnt_userns. This function will then * take care to map the inode according to @mnt_userns before checking * permissions. On non-idmapped mounts or if permission checking is to be * performed on the raw inode simply passs init_user_ns. * * Return: 0 if successful, -ve on error. */int cap_inode_killpriv(struct user_namespace *mnt_userns, struct dentry *dentry){	int error; 	error = __vfs_removexattr(mnt_userns, dentry, XATTR_NAME_CAPS);	if (error == -EOPNOTSUPP)		error = 0;	return error;} static bool rootid_owns_currentns(kuid_t kroot){	struct user_namespace *ns; 	if (!uid_valid(kroot))		return false; 	for (ns = current_user_ns(); ; ns = ns->parent) {		if (from_kuid(ns, kroot) == 0)			return true;		if (ns == &init_user_ns)			break;	} 	return false;} static __u32 sansflags(__u32 m){	return m & ~VFS_CAP_FLAGS_EFFECTIVE;} static bool is_v2header(size_t size, const struct vfs_cap_data *cap){	if (size != XATTR_CAPS_SZ_2)		return false;	return sansflags(le32_to_cpu(cap->magic_etc)) == VFS_CAP_REVISION_2;} static bool is_v3header(size_t size, const struct vfs_cap_data *cap){	if (size != XATTR_CAPS_SZ_3)		return false;	return sansflags(le32_to_cpu(cap->magic_etc)) == VFS_CAP_REVISION_3;} /* * getsecurity: We are called for security.* before any attempt to read the * xattr from the inode itself. * * This gives us a chance to read the on-disk value and convert it.  If we * return -EOPNOTSUPP, then vfs_getxattr() will call the i_op handler. * * Note we are not called by vfs_getxattr_alloc(), but that is only called * by the integrity subsystem, which really wants the unconverted values - * so that's good. */int cap_inode_getsecurity(struct user_namespace *mnt_userns,			  struct inode *inode, const char *name, void **buffer,			  bool alloc){	int size, ret;	kuid_t kroot;	u32 nsmagic, magic;	uid_t root, mappedroot;	char *tmpbuf = NULL;	struct vfs_cap_data *cap;	struct vfs_ns_cap_data *nscap = NULL;	struct dentry *dentry;	struct user_namespace *fs_ns; 	if (strcmp(name, "capability") != 0)		return -EOPNOTSUPP; 	dentry = d_find_any_alias(inode);	if (!dentry)		return -EINVAL; 	size = sizeof(struct vfs_ns_cap_data);	ret = (int)vfs_getxattr_alloc(mnt_userns, dentry, XATTR_NAME_CAPS,				      &tmpbuf, size, GFP_NOFS);	dput(dentry); 	if (ret < 0 || !tmpbuf) {		size = ret;		goto out_free;	} 	fs_ns = inode->i_sb->s_user_ns;	cap = (struct vfs_cap_data *) tmpbuf;	if (is_v2header((size_t) ret, cap)) {		root = 0;	} else if (is_v3header((size_t) ret, cap)) {		nscap = (struct vfs_ns_cap_data *) tmpbuf;		root = le32_to_cpu(nscap->rootid);	} else {		size = -EINVAL;		goto out_free;	} 	kroot = make_kuid(fs_ns, root); 	/* If this is an idmapped mount shift the kuid. */	kroot = mapped_kuid_fs(mnt_userns, fs_ns, kroot); 	/* If the root kuid maps to a valid uid in current ns, then return	 * this as a nscap. */	mappedroot = from_kuid(current_user_ns(), kroot);	if (mappedroot != (uid_t)-1 && mappedroot != (uid_t)0) {		size = sizeof(struct vfs_ns_cap_data);		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 (!rootid_owns_currentns(kroot)) {		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 * @mnt_userns:	user namespace of the mount the inode was found from * @fs_userns:	user namespace of the filesystem * * If the inode has been found through an idmapped mount the user namespace of * the vfsmount must be passed through @mnt_userns. This function will then * take care to map the inode according to @mnt_userns before checking * permissions. On non-idmapped mounts or if permission checking is to be * performed on the raw inode simply passs init_user_ns.

Lines 1–500 of 1485.