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 (4901B)


      1// SPDX-License-Identifier: GPL-2.0
      2/*
      3 * (C) 2001 Clemson University and The University of Chicago
      4 *
      5 * See COPYING in top-level directory.
      6 */
      7
      8#include "protocol.h"
      9#include "orangefs-kernel.h"
     10#include "orangefs-bufmap.h"
     11#include <linux/posix_acl_xattr.h>
     12
     13struct posix_acl *orangefs_get_acl(struct inode *inode, int type, bool rcu)
     14{
     15	struct posix_acl *acl;
     16	int ret;
     17	char *key = NULL, *value = NULL;
     18
     19	if (rcu)
     20		return ERR_PTR(-ECHILD);
     21
     22	switch (type) {
     23	case ACL_TYPE_ACCESS:
     24		key = XATTR_NAME_POSIX_ACL_ACCESS;
     25		break;
     26	case ACL_TYPE_DEFAULT:
     27		key = XATTR_NAME_POSIX_ACL_DEFAULT;
     28		break;
     29	default:
     30		gossip_err("orangefs_get_acl: bogus value of type %d\n", type);
     31		return ERR_PTR(-EINVAL);
     32	}
     33	/*
     34	 * Rather than incurring a network call just to determine the exact
     35	 * length of the attribute, I just allocate a max length to save on
     36	 * the network call. Conceivably, we could pass NULL to
     37	 * orangefs_inode_getxattr() to probe the length of the value, but
     38	 * I don't do that for now.
     39	 */
     40	value = kmalloc(ORANGEFS_MAX_XATTR_VALUELEN, GFP_KERNEL);
     41	if (!value)
     42		return ERR_PTR(-ENOMEM);
     43
     44	gossip_debug(GOSSIP_ACL_DEBUG,
     45		     "inode %pU, key %s, type %d\n",
     46		     get_khandle_from_ino(inode),
     47		     key,
     48		     type);
     49	ret = orangefs_inode_getxattr(inode, key, value,
     50				      ORANGEFS_MAX_XATTR_VALUELEN);
     51	/* if the key exists, convert it to an in-memory rep */
     52	if (ret > 0) {
     53		acl = posix_acl_from_xattr(&init_user_ns, value, ret);
     54	} else if (ret == -ENODATA || ret == -ENOSYS) {
     55		acl = NULL;
     56	} else {
     57		gossip_err("inode %pU retrieving acl's failed with error %d\n",
     58			   get_khandle_from_ino(inode),
     59			   ret);
     60		acl = ERR_PTR(ret);
     61	}
     62	/* kfree(NULL) is safe, so don't worry if value ever got used */
     63	kfree(value);
     64	return acl;
     65}
     66
     67static int __orangefs_set_acl(struct inode *inode, struct posix_acl *acl,
     68			      int type)
     69{
     70	int error = 0;
     71	void *value = NULL;
     72	size_t size = 0;
     73	const char *name = NULL;
     74
     75	switch (type) {
     76	case ACL_TYPE_ACCESS:
     77		name = XATTR_NAME_POSIX_ACL_ACCESS;
     78		break;
     79	case ACL_TYPE_DEFAULT:
     80		name = XATTR_NAME_POSIX_ACL_DEFAULT;
     81		break;
     82	default:
     83		gossip_err("%s: invalid type %d!\n", __func__, type);
     84		return -EINVAL;
     85	}
     86
     87	gossip_debug(GOSSIP_ACL_DEBUG,
     88		     "%s: inode %pU, key %s type %d\n",
     89		     __func__, get_khandle_from_ino(inode),
     90		     name,
     91		     type);
     92
     93	if (acl) {
     94		size = posix_acl_xattr_size(acl->a_count);
     95		value = kmalloc(size, GFP_KERNEL);
     96		if (!value)
     97			return -ENOMEM;
     98
     99		error = posix_acl_to_xattr(&init_user_ns, acl, value, size);
    100		if (error < 0)
    101			goto out;
    102	}
    103
    104	gossip_debug(GOSSIP_ACL_DEBUG,
    105		     "%s: name %s, value %p, size %zd, acl %p\n",
    106		     __func__, name, value, size, acl);
    107	/*
    108	 * Go ahead and set the extended attribute now. NOTE: Suppose acl
    109	 * was NULL, then value will be NULL and size will be 0 and that
    110	 * will xlate to a removexattr. However, we don't want removexattr
    111	 * complain if attributes does not exist.
    112	 */
    113	error = orangefs_inode_setxattr(inode, name, value, size, 0);
    114
    115out:
    116	kfree(value);
    117	if (!error)
    118		set_cached_acl(inode, type, acl);
    119	return error;
    120}
    121
    122int orangefs_set_acl(struct user_namespace *mnt_userns, struct inode *inode,
    123		     struct posix_acl *acl, int type)
    124{
    125	int error;
    126	struct iattr iattr;
    127	int rc;
    128
    129	memset(&iattr, 0, sizeof iattr);
    130
    131	if (type == ACL_TYPE_ACCESS && acl) {
    132		/*
    133		 * posix_acl_update_mode checks to see if the permissions
    134		 * described by the ACL can be encoded into the
    135		 * object's mode. If so, it sets "acl" to NULL
    136		 * and "mode" to the new desired value. It is up to
    137		 * us to propagate the new mode back to the server...
    138		 */
    139		error = posix_acl_update_mode(&init_user_ns, inode,
    140					      &iattr.ia_mode, &acl);
    141		if (error) {
    142			gossip_err("%s: posix_acl_update_mode err: %d\n",
    143				   __func__,
    144				   error);
    145			return error;
    146		}
    147
    148		if (inode->i_mode != iattr.ia_mode)
    149			iattr.ia_valid = ATTR_MODE;
    150
    151	}
    152
    153	rc = __orangefs_set_acl(inode, acl, type);
    154
    155	if (!rc && (iattr.ia_valid == ATTR_MODE))
    156		rc = __orangefs_setattr(inode, &iattr);
    157
    158	return rc;
    159}
    160
    161int orangefs_init_acl(struct inode *inode, struct inode *dir)
    162{
    163	struct posix_acl *default_acl, *acl;
    164	umode_t mode = inode->i_mode;
    165	struct iattr iattr;
    166	int error = 0;
    167
    168	error = posix_acl_create(dir, &mode, &default_acl, &acl);
    169	if (error)
    170		return error;
    171
    172	if (default_acl) {
    173		error = __orangefs_set_acl(inode, default_acl,
    174					   ACL_TYPE_DEFAULT);
    175		posix_acl_release(default_acl);
    176	} else {
    177		inode->i_default_acl = NULL;
    178	}
    179
    180	if (acl) {
    181		if (!error)
    182			error = __orangefs_set_acl(inode, acl, ACL_TYPE_ACCESS);
    183		posix_acl_release(acl);
    184	} else {
    185		inode->i_acl = NULL;
    186	}
    187
    188	/* If mode of the inode was changed, then do a forcible ->setattr */
    189	if (mode != inode->i_mode) {
    190		memset(&iattr, 0, sizeof iattr);
    191		inode->i_mode = mode;
    192		iattr.ia_mode = mode;
    193		iattr.ia_valid |= ATTR_MODE;
    194		__orangefs_setattr(inode, &iattr);
    195	}
    196
    197	return error;
    198}