cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

acl.c (2684B)


      1/*
      2 * FUSE: Filesystem in Userspace
      3 * Copyright (C) 2016 Canonical Ltd. <seth.forshee@canonical.com>
      4 *
      5 * This program can be distributed under the terms of the GNU GPL.
      6 * See the file COPYING.
      7 */
      8
      9#include "fuse_i.h"
     10
     11#include <linux/posix_acl.h>
     12#include <linux/posix_acl_xattr.h>
     13
     14struct posix_acl *fuse_get_acl(struct inode *inode, int type, bool rcu)
     15{
     16	struct fuse_conn *fc = get_fuse_conn(inode);
     17	int size;
     18	const char *name;
     19	void *value = NULL;
     20	struct posix_acl *acl;
     21
     22	if (rcu)
     23		return ERR_PTR(-ECHILD);
     24
     25	if (fuse_is_bad(inode))
     26		return ERR_PTR(-EIO);
     27
     28	if (!fc->posix_acl || fc->no_getxattr)
     29		return NULL;
     30
     31	if (type == ACL_TYPE_ACCESS)
     32		name = XATTR_NAME_POSIX_ACL_ACCESS;
     33	else if (type == ACL_TYPE_DEFAULT)
     34		name = XATTR_NAME_POSIX_ACL_DEFAULT;
     35	else
     36		return ERR_PTR(-EOPNOTSUPP);
     37
     38	value = kmalloc(PAGE_SIZE, GFP_KERNEL);
     39	if (!value)
     40		return ERR_PTR(-ENOMEM);
     41	size = fuse_getxattr(inode, name, value, PAGE_SIZE);
     42	if (size > 0)
     43		acl = posix_acl_from_xattr(fc->user_ns, value, size);
     44	else if ((size == 0) || (size == -ENODATA) ||
     45		 (size == -EOPNOTSUPP && fc->no_getxattr))
     46		acl = NULL;
     47	else if (size == -ERANGE)
     48		acl = ERR_PTR(-E2BIG);
     49	else
     50		acl = ERR_PTR(size);
     51
     52	kfree(value);
     53	return acl;
     54}
     55
     56int fuse_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
     57		 struct posix_acl *acl, int type)
     58{
     59	struct fuse_conn *fc = get_fuse_conn(inode);
     60	const char *name;
     61	int ret;
     62
     63	if (fuse_is_bad(inode))
     64		return -EIO;
     65
     66	if (!fc->posix_acl || fc->no_setxattr)
     67		return -EOPNOTSUPP;
     68
     69	if (type == ACL_TYPE_ACCESS)
     70		name = XATTR_NAME_POSIX_ACL_ACCESS;
     71	else if (type == ACL_TYPE_DEFAULT)
     72		name = XATTR_NAME_POSIX_ACL_DEFAULT;
     73	else
     74		return -EINVAL;
     75
     76	if (acl) {
     77		unsigned int extra_flags = 0;
     78		/*
     79		 * Fuse userspace is responsible for updating access
     80		 * permissions in the inode, if needed. fuse_setxattr
     81		 * invalidates the inode attributes, which will force
     82		 * them to be refreshed the next time they are used,
     83		 * and it also updates i_ctime.
     84		 */
     85		size_t size = posix_acl_xattr_size(acl->a_count);
     86		void *value;
     87
     88		if (size > PAGE_SIZE)
     89			return -E2BIG;
     90
     91		value = kmalloc(size, GFP_KERNEL);
     92		if (!value)
     93			return -ENOMEM;
     94
     95		ret = posix_acl_to_xattr(fc->user_ns, acl, value, size);
     96		if (ret < 0) {
     97			kfree(value);
     98			return ret;
     99		}
    100
    101		if (!in_group_p(i_gid_into_mnt(&init_user_ns, inode)) &&
    102		    !capable_wrt_inode_uidgid(&init_user_ns, inode, CAP_FSETID))
    103			extra_flags |= FUSE_SETXATTR_ACL_KILL_SGID;
    104
    105		ret = fuse_setxattr(inode, name, value, size, 0, extra_flags);
    106		kfree(value);
    107	} else {
    108		ret = fuse_removexattr(inode, name);
    109	}
    110	forget_all_cached_acls(inode);
    111	fuse_invalidate_attr(inode);
    112
    113	return ret;
    114}