Blame view

fs/fuse/acl.c 2.32 KB
60bcc88ad   Seth Forshee   fuse: Add posix A...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
  /*
   * FUSE: Filesystem in Userspace
   * Copyright (C) 2016 Canonical Ltd. <seth.forshee@canonical.com>
   *
   * This program can be distributed under the terms of the GNU GPL.
   * See the file COPYING.
   */
  
  #include "fuse_i.h"
  
  #include <linux/posix_acl.h>
  #include <linux/posix_acl_xattr.h>
  
  struct posix_acl *fuse_get_acl(struct inode *inode, int type)
  {
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	int size;
  	const char *name;
  	void *value = NULL;
  	struct posix_acl *acl;
36cf9ae54   Miklos Szeredi   fuse: fix bad inode
21
22
  	if (fuse_is_bad(inode))
  		return ERR_PTR(-EIO);
60bcc88ad   Seth Forshee   fuse: Add posix A...
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
  	if (!fc->posix_acl || 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)
8cb08329b   Eric W. Biederman   fuse: Support fus...
38
  		acl = posix_acl_from_xattr(fc->user_ns, value, size);
60bcc88ad   Seth Forshee   fuse: Add posix A...
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
  	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;
  }
  
  int fuse_set_acl(struct inode *inode, struct posix_acl *acl, int type)
  {
  	struct fuse_conn *fc = get_fuse_conn(inode);
  	const char *name;
  	int ret;
36cf9ae54   Miklos Szeredi   fuse: fix bad inode
56
57
  	if (fuse_is_bad(inode))
  		return -EIO;
60bcc88ad   Seth Forshee   fuse: Add posix A...
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
  	if (!fc->posix_acl || fc->no_setxattr)
  		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) {
  		/*
  		 * 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 = posix_acl_xattr_size(acl->a_count);
  		void *value;
  
  		if (size > PAGE_SIZE)
  			return -E2BIG;
  
  		value = kmalloc(size, GFP_KERNEL);
  		if (!value)
  			return -ENOMEM;
8cb08329b   Eric W. Biederman   fuse: Support fus...
85
  		ret = posix_acl_to_xattr(fc->user_ns, acl, value, size);
60bcc88ad   Seth Forshee   fuse: Add posix A...
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
  		if (ret < 0) {
  			kfree(value);
  			return ret;
  		}
  
  		ret = fuse_setxattr(inode, name, value, size, 0);
  		kfree(value);
  	} else {
  		ret = fuse_removexattr(inode, name);
  	}
  	forget_all_cached_acls(inode);
  	fuse_invalidate_attr(inode);
  
  	return ret;
  }