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

xattr.c (6331B)


      1/*
      2 * FUSE: Filesystem in Userspace
      3 * Copyright (C) 2001-2016  Miklos Szeredi <miklos@szeredi.hu>
      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/xattr.h>
     12#include <linux/posix_acl_xattr.h>
     13
     14int fuse_setxattr(struct inode *inode, const char *name, const void *value,
     15		  size_t size, int flags, unsigned int extra_flags)
     16{
     17	struct fuse_mount *fm = get_fuse_mount(inode);
     18	FUSE_ARGS(args);
     19	struct fuse_setxattr_in inarg;
     20	int err;
     21
     22	if (fm->fc->no_setxattr)
     23		return -EOPNOTSUPP;
     24
     25	memset(&inarg, 0, sizeof(inarg));
     26	inarg.size = size;
     27	inarg.flags = flags;
     28	inarg.setxattr_flags = extra_flags;
     29
     30	args.opcode = FUSE_SETXATTR;
     31	args.nodeid = get_node_id(inode);
     32	args.in_numargs = 3;
     33	args.in_args[0].size = fm->fc->setxattr_ext ?
     34		sizeof(inarg) : FUSE_COMPAT_SETXATTR_IN_SIZE;
     35	args.in_args[0].value = &inarg;
     36	args.in_args[1].size = strlen(name) + 1;
     37	args.in_args[1].value = name;
     38	args.in_args[2].size = size;
     39	args.in_args[2].value = value;
     40	err = fuse_simple_request(fm, &args);
     41	if (err == -ENOSYS) {
     42		fm->fc->no_setxattr = 1;
     43		err = -EOPNOTSUPP;
     44	}
     45	if (!err)
     46		fuse_update_ctime(inode);
     47
     48	return err;
     49}
     50
     51ssize_t fuse_getxattr(struct inode *inode, const char *name, void *value,
     52		      size_t size)
     53{
     54	struct fuse_mount *fm = get_fuse_mount(inode);
     55	FUSE_ARGS(args);
     56	struct fuse_getxattr_in inarg;
     57	struct fuse_getxattr_out outarg;
     58	ssize_t ret;
     59
     60	if (fm->fc->no_getxattr)
     61		return -EOPNOTSUPP;
     62
     63	memset(&inarg, 0, sizeof(inarg));
     64	inarg.size = size;
     65	args.opcode = FUSE_GETXATTR;
     66	args.nodeid = get_node_id(inode);
     67	args.in_numargs = 2;
     68	args.in_args[0].size = sizeof(inarg);
     69	args.in_args[0].value = &inarg;
     70	args.in_args[1].size = strlen(name) + 1;
     71	args.in_args[1].value = name;
     72	/* This is really two different operations rolled into one */
     73	args.out_numargs = 1;
     74	if (size) {
     75		args.out_argvar = true;
     76		args.out_args[0].size = size;
     77		args.out_args[0].value = value;
     78	} else {
     79		args.out_args[0].size = sizeof(outarg);
     80		args.out_args[0].value = &outarg;
     81	}
     82	ret = fuse_simple_request(fm, &args);
     83	if (!ret && !size)
     84		ret = min_t(ssize_t, outarg.size, XATTR_SIZE_MAX);
     85	if (ret == -ENOSYS) {
     86		fm->fc->no_getxattr = 1;
     87		ret = -EOPNOTSUPP;
     88	}
     89	return ret;
     90}
     91
     92static int fuse_verify_xattr_list(char *list, size_t size)
     93{
     94	size_t origsize = size;
     95
     96	while (size) {
     97		size_t thislen = strnlen(list, size);
     98
     99		if (!thislen || thislen == size)
    100			return -EIO;
    101
    102		size -= thislen + 1;
    103		list += thislen + 1;
    104	}
    105
    106	return origsize;
    107}
    108
    109ssize_t fuse_listxattr(struct dentry *entry, char *list, size_t size)
    110{
    111	struct inode *inode = d_inode(entry);
    112	struct fuse_mount *fm = get_fuse_mount(inode);
    113	FUSE_ARGS(args);
    114	struct fuse_getxattr_in inarg;
    115	struct fuse_getxattr_out outarg;
    116	ssize_t ret;
    117
    118	if (fuse_is_bad(inode))
    119		return -EIO;
    120
    121	if (!fuse_allow_current_process(fm->fc))
    122		return -EACCES;
    123
    124	if (fm->fc->no_listxattr)
    125		return -EOPNOTSUPP;
    126
    127	memset(&inarg, 0, sizeof(inarg));
    128	inarg.size = size;
    129	args.opcode = FUSE_LISTXATTR;
    130	args.nodeid = get_node_id(inode);
    131	args.in_numargs = 1;
    132	args.in_args[0].size = sizeof(inarg);
    133	args.in_args[0].value = &inarg;
    134	/* This is really two different operations rolled into one */
    135	args.out_numargs = 1;
    136	if (size) {
    137		args.out_argvar = true;
    138		args.out_args[0].size = size;
    139		args.out_args[0].value = list;
    140	} else {
    141		args.out_args[0].size = sizeof(outarg);
    142		args.out_args[0].value = &outarg;
    143	}
    144	ret = fuse_simple_request(fm, &args);
    145	if (!ret && !size)
    146		ret = min_t(ssize_t, outarg.size, XATTR_LIST_MAX);
    147	if (ret > 0 && size)
    148		ret = fuse_verify_xattr_list(list, ret);
    149	if (ret == -ENOSYS) {
    150		fm->fc->no_listxattr = 1;
    151		ret = -EOPNOTSUPP;
    152	}
    153	return ret;
    154}
    155
    156int fuse_removexattr(struct inode *inode, const char *name)
    157{
    158	struct fuse_mount *fm = get_fuse_mount(inode);
    159	FUSE_ARGS(args);
    160	int err;
    161
    162	if (fm->fc->no_removexattr)
    163		return -EOPNOTSUPP;
    164
    165	args.opcode = FUSE_REMOVEXATTR;
    166	args.nodeid = get_node_id(inode);
    167	args.in_numargs = 1;
    168	args.in_args[0].size = strlen(name) + 1;
    169	args.in_args[0].value = name;
    170	err = fuse_simple_request(fm, &args);
    171	if (err == -ENOSYS) {
    172		fm->fc->no_removexattr = 1;
    173		err = -EOPNOTSUPP;
    174	}
    175	if (!err)
    176		fuse_update_ctime(inode);
    177
    178	return err;
    179}
    180
    181static int fuse_xattr_get(const struct xattr_handler *handler,
    182			 struct dentry *dentry, struct inode *inode,
    183			 const char *name, void *value, size_t size)
    184{
    185	if (fuse_is_bad(inode))
    186		return -EIO;
    187
    188	return fuse_getxattr(inode, name, value, size);
    189}
    190
    191static int fuse_xattr_set(const struct xattr_handler *handler,
    192			  struct user_namespace *mnt_userns,
    193			  struct dentry *dentry, struct inode *inode,
    194			  const char *name, const void *value, size_t size,
    195			  int flags)
    196{
    197	if (fuse_is_bad(inode))
    198		return -EIO;
    199
    200	if (!value)
    201		return fuse_removexattr(inode, name);
    202
    203	return fuse_setxattr(inode, name, value, size, flags, 0);
    204}
    205
    206static bool no_xattr_list(struct dentry *dentry)
    207{
    208	return false;
    209}
    210
    211static int no_xattr_get(const struct xattr_handler *handler,
    212			struct dentry *dentry, struct inode *inode,
    213			const char *name, void *value, size_t size)
    214{
    215	return -EOPNOTSUPP;
    216}
    217
    218static int no_xattr_set(const struct xattr_handler *handler,
    219			struct user_namespace *mnt_userns,
    220			struct dentry *dentry, struct inode *nodee,
    221			const char *name, const void *value,
    222			size_t size, int flags)
    223{
    224	return -EOPNOTSUPP;
    225}
    226
    227static const struct xattr_handler fuse_xattr_handler = {
    228	.prefix = "",
    229	.get    = fuse_xattr_get,
    230	.set    = fuse_xattr_set,
    231};
    232
    233const struct xattr_handler *fuse_xattr_handlers[] = {
    234	&fuse_xattr_handler,
    235	NULL
    236};
    237
    238const struct xattr_handler *fuse_acl_xattr_handlers[] = {
    239	&posix_acl_access_xattr_handler,
    240	&posix_acl_default_xattr_handler,
    241	&fuse_xattr_handler,
    242	NULL
    243};
    244
    245static const struct xattr_handler fuse_no_acl_access_xattr_handler = {
    246	.name  = XATTR_NAME_POSIX_ACL_ACCESS,
    247	.flags = ACL_TYPE_ACCESS,
    248	.list  = no_xattr_list,
    249	.get   = no_xattr_get,
    250	.set   = no_xattr_set,
    251};
    252
    253static const struct xattr_handler fuse_no_acl_default_xattr_handler = {
    254	.name  = XATTR_NAME_POSIX_ACL_DEFAULT,
    255	.flags = ACL_TYPE_ACCESS,
    256	.list  = no_xattr_list,
    257	.get   = no_xattr_get,
    258	.set   = no_xattr_set,
    259};
    260
    261const struct xattr_handler *fuse_no_acl_xattr_handlers[] = {
    262	&fuse_no_acl_access_xattr_handler,
    263	&fuse_no_acl_default_xattr_handler,
    264	&fuse_xattr_handler,
    265	NULL
    266};