161 lines · 3.9 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * FUSE: Filesystem in Userspace * Copyright (C) 2016 Canonical Ltd. <seth.forshee@canonical.com> */ #include "fuse_i.h" #include <linux/posix_acl.h>#include <linux/posix_acl_xattr.h> static struct posix_acl *__fuse_get_acl(struct fuse_conn *fc,					struct inode *inode, int type, bool rcu){	int size;	const char *name;	void *value = NULL;	struct posix_acl *acl; 	if (rcu)		return ERR_PTR(-ECHILD); 	if (fuse_is_bad(inode))		return ERR_PTR(-EIO); 	if (fc->no_getxattr)		return NULL; 	if (type == ACL_TYPE_ACCESS)		name = XATTR_NAME_POSIX_ACL_ACCESS;	else if (type == ACL_TYPE_DEFAULT)		name = XATTR_NAME_POSIX_ACL_DEFAULT;	else		return ERR_PTR(-EOPNOTSUPP); 	value = kmalloc(PAGE_SIZE, GFP_KERNEL);	if (!value)		return ERR_PTR(-ENOMEM);	size = fuse_getxattr(inode, name, value, PAGE_SIZE);	if (size > 0)		acl = posix_acl_from_xattr(fc->user_ns, value, size);	else if ((size == 0) || (size == -ENODATA) ||		 (size == -EOPNOTSUPP && fc->no_getxattr))		acl = NULL;	else if (size == -ERANGE)		acl = ERR_PTR(-E2BIG);	else		acl = ERR_PTR(size); 	kfree(value);	return acl;} static inline bool fuse_no_acl(const struct fuse_conn *fc,			       const struct inode *inode){	/*	 * Refuse interacting with POSIX ACLs for daemons that	 * don't support FUSE_POSIX_ACL and are not mounted on	 * the host to retain backwards compatibility.	 */	return !fc->posix_acl && (i_user_ns(inode) != &init_user_ns);} struct posix_acl *fuse_get_acl(struct mnt_idmap *idmap,			       struct dentry *dentry, int type){	struct inode *inode = d_inode(dentry);	struct fuse_conn *fc = get_fuse_conn(inode); 	if (fuse_no_acl(fc, inode))		return ERR_PTR(-EOPNOTSUPP); 	return __fuse_get_acl(fc, inode, type, false);} struct posix_acl *fuse_get_inode_acl(struct inode *inode, int type, bool rcu){	struct fuse_conn *fc = get_fuse_conn(inode); 	/*	 * FUSE daemons before FUSE_POSIX_ACL was introduced could get and set	 * POSIX ACLs without them being used for permission checking by the	 * vfs. Retain that behavior for backwards compatibility as there are	 * filesystems that do all permission checking for acls in the daemon	 * and not in the kernel.	 */	if (!fc->posix_acl)		return NULL;	return __fuse_get_acl(fc,  inode, type, rcu);} int fuse_set_acl(struct mnt_idmap *idmap, struct dentry *dentry,		 struct posix_acl *acl, int type){	struct inode *inode = d_inode(dentry);	struct fuse_conn *fc = get_fuse_conn(inode);	const char *name;	int ret; 	if (fuse_is_bad(inode))		return -EIO; 	if (fc->no_setxattr || fuse_no_acl(fc, inode))		return -EOPNOTSUPP; 	if (type == ACL_TYPE_ACCESS)		name = XATTR_NAME_POSIX_ACL_ACCESS;	else if (type == ACL_TYPE_DEFAULT)		name = XATTR_NAME_POSIX_ACL_DEFAULT;	else		return -EINVAL; 	if (acl) {		unsigned int extra_flags = 0;		/*		 * Fuse userspace is responsible for updating access		 * permissions in the inode, if needed. fuse_setxattr		 * invalidates the inode attributes, which will force		 * them to be refreshed the next time they are used,		 * and it also updates i_ctime.		 */		size_t size;		void *value; 		value = posix_acl_to_xattr(fc->user_ns, acl, &size, GFP_KERNEL);		if (!value)			return -ENOMEM; 		if (size > PAGE_SIZE) {			kfree(value);			return -E2BIG;		} 		/*		 * Fuse daemons without FUSE_POSIX_ACL never changed the passed		 * through POSIX ACLs. Such daemons don't expect setgid bits to		 * be stripped.		 */		if (fc->posix_acl &&		    !in_group_or_capable(idmap, inode,					 i_gid_into_vfsgid(idmap, inode)))			extra_flags |= FUSE_SETXATTR_ACL_KILL_SGID; 		ret = fuse_setxattr(inode, name, value, size, 0, extra_flags);		kfree(value);	} else {		ret = fuse_removexattr(inode, name);	} 	if (fc->posix_acl) {		/*		 * Fuse daemons without FUSE_POSIX_ACL never cached POSIX ACLs		 * and didn't invalidate attributes. Retain that behavior.		 */		forget_all_cached_acls(inode);		fuse_invalidate_attr(inode);	} 	return ret;}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t