Blame view

fs/xfs/xfs_xattr.c 6.13 KB
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
  /*
   * Copyright (C) 2008 Christoph Hellwig.
   * Portions Copyright (C) 2000-2008 Silicon Graphics, Inc.
   *
   * This program is free software; you can redistribute it and/or
   * modify it under the terms of the GNU General Public License as
   * published by the Free Software Foundation.
   *
   * This program is distributed in the hope that it would be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write the Free Software Foundation,
   * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
   */
  
  #include "xfs.h"
a4fbe6ab1   Dave Chinner   xfs: decouple ino...
20
  #include "xfs_format.h"
69432832f   Dave Chinner   xfs: split out in...
21
  #include "xfs_log_format.h"
239880ef6   Dave Chinner   xfs: decouple log...
22
  #include "xfs_trans_resv.h"
570627875   Dave Chinner   xfs: unify direct...
23
24
  #include "xfs_mount.h"
  #include "xfs_da_format.h"
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
25
26
27
28
  #include "xfs_inode.h"
  #include "xfs_attr.h"
  #include "xfs_attr_leaf.h"
  #include "xfs_acl.h"
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
29
30
31
  
  #include <linux/posix_acl_xattr.h>
  #include <linux/xattr.h>
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
32
  static int
b296821a7   Al Viro   xattr_handler: pa...
33
34
  xfs_xattr_get(const struct xattr_handler *handler, struct dentry *unused,
  		struct inode *inode, const char *name, void *value, size_t size)
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
35
  {
d9a82a040   Andreas Gruenbacher   xattr handlers: P...
36
  	int xflags = handler->flags;
b296821a7   Al Viro   xattr_handler: pa...
37
  	struct xfs_inode *ip = XFS_I(inode);
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
38
  	int error, asize = size;
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
39
40
41
42
43
  	/* Convert Linux syscall to XFS internal ATTR flags */
  	if (!size) {
  		xflags |= ATTR_KERNOVAL;
  		value = NULL;
  	}
2451337dd   Dave Chinner   xfs: global error...
44
  	error = xfs_attr_get(ip, (unsigned char *)name, value, &asize, xflags);
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
45
46
47
48
  	if (error)
  		return error;
  	return asize;
  }
47e1bf640   Andreas Gruenbacher   xfs: invalidate c...
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  void
  xfs_forget_acl(
  	struct inode		*inode,
  	const char		*name,
  	int			xflags)
  {
  	/*
  	 * Invalidate any cached ACLs if the user has bypassed the ACL
  	 * interface. We don't validate the content whatsoever so it is caller
  	 * responsibility to provide data in valid format and ensure i_mode is
  	 * consistent.
  	 */
  	if (xflags & ATTR_ROOT) {
  #ifdef CONFIG_XFS_POSIX_ACL
  		if (!strcmp(name, SGI_ACL_FILE))
  			forget_cached_acl(inode, ACL_TYPE_ACCESS);
  		else if (!strcmp(name, SGI_ACL_DEFAULT))
  			forget_cached_acl(inode, ACL_TYPE_DEFAULT);
  #endif
  	}
  }
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
70
  static int
593012268   Al Viro   switch xattr_hand...
71
72
73
  xfs_xattr_set(const struct xattr_handler *handler, struct dentry *unused,
  		struct inode *inode, const char *name, const void *value,
  		size_t size, int flags)
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
74
  {
5d2eb548b   Linus Torvalds   Merge branch 'for...
75
  	int			xflags = handler->flags;
593012268   Al Viro   switch xattr_hand...
76
  	struct xfs_inode	*ip = XFS_I(inode);
67d8e04e3   Brian Foster   xfs: invalidate c...
77
  	int			error;
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
78

f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
79
80
81
82
83
84
85
  	/* Convert Linux syscall to XFS internal ATTR flags */
  	if (flags & XATTR_CREATE)
  		xflags |= ATTR_CREATE;
  	if (flags & XATTR_REPLACE)
  		xflags |= ATTR_REPLACE;
  
  	if (!value)
2451337dd   Dave Chinner   xfs: global error...
86
  		return xfs_attr_remove(ip, (unsigned char *)name, xflags);
67d8e04e3   Brian Foster   xfs: invalidate c...
87
  	error = xfs_attr_set(ip, (unsigned char *)name,
a9273ca5c   Dave Chinner   xfs: convert attr...
88
  				(void *)value, size, xflags);
47e1bf640   Andreas Gruenbacher   xfs: invalidate c...
89
  	if (!error)
593012268   Al Viro   switch xattr_hand...
90
  		xfs_forget_acl(inode, name, xflags);
67d8e04e3   Brian Foster   xfs: invalidate c...
91
92
  
  	return error;
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
93
  }
46e58764f   Stephen Hemminger   xfs: constify xat...
94
  static const struct xattr_handler xfs_xattr_user_handler = {
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
95
  	.prefix	= XATTR_USER_PREFIX,
431547b3c   Christoph Hellwig   sanitize xattr ha...
96
97
98
  	.flags	= 0, /* no flags implies user namespace */
  	.get	= xfs_xattr_get,
  	.set	= xfs_xattr_set,
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
99
  };
46e58764f   Stephen Hemminger   xfs: constify xat...
100
  static const struct xattr_handler xfs_xattr_trusted_handler = {
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
101
  	.prefix	= XATTR_TRUSTED_PREFIX,
431547b3c   Christoph Hellwig   sanitize xattr ha...
102
103
104
  	.flags	= ATTR_ROOT,
  	.get	= xfs_xattr_get,
  	.set	= xfs_xattr_set,
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
105
  };
46e58764f   Stephen Hemminger   xfs: constify xat...
106
  static const struct xattr_handler xfs_xattr_security_handler = {
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
107
  	.prefix	= XATTR_SECURITY_PREFIX,
431547b3c   Christoph Hellwig   sanitize xattr ha...
108
109
110
  	.flags	= ATTR_SECURE,
  	.get	= xfs_xattr_get,
  	.set	= xfs_xattr_set,
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
111
  };
46e58764f   Stephen Hemminger   xfs: constify xat...
112
  const struct xattr_handler *xfs_xattr_handlers[] = {
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
113
114
115
  	&xfs_xattr_user_handler,
  	&xfs_xattr_trusted_handler,
  	&xfs_xattr_security_handler,
ef14f0c15   Christoph Hellwig   xfs: use generic ...
116
  #ifdef CONFIG_XFS_POSIX_ACL
2401dc297   Christoph Hellwig   xfs: use generic ...
117
118
  	&posix_acl_access_xattr_handler,
  	&posix_acl_default_xattr_handler,
ef14f0c15   Christoph Hellwig   xfs: use generic ...
119
  #endif
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
120
121
  	NULL
  };
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
122
  static int
5d92b75c7   Andreas Gruenbacher   xfs: Change how l...
123
  __xfs_xattr_put_listent(
a9273ca5c   Dave Chinner   xfs: convert attr...
124
  	struct xfs_attr_list_context *context,
5d92b75c7   Andreas Gruenbacher   xfs: Change how l...
125
126
127
128
  	char *prefix,
  	int prefix_len,
  	unsigned char *name,
  	int namelen)
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
129
  {
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
130
131
  	char *offset;
  	int arraytop;
5d92b75c7   Andreas Gruenbacher   xfs: Change how l...
132
133
  	if (!context->alist)
  		goto compute_size;
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
134
135
136
137
  
  	arraytop = context->count + prefix_len + namelen + 1;
  	if (arraytop > context->firstu) {
  		context->count = -1;	/* insufficient space */
791cc43b3   Artem Savkov   Make __xfs_xattr_...
138
  		context->seen_enough = 1;
2a6fba6d2   Eric Sandeen   xfs: only return ...
139
  		return 0;
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
140
141
  	}
  	offset = (char *)context->alist + context->count;
5d92b75c7   Andreas Gruenbacher   xfs: Change how l...
142
  	strncpy(offset, prefix, prefix_len);
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
143
  	offset += prefix_len;
a9273ca5c   Dave Chinner   xfs: convert attr...
144
  	strncpy(offset, (char *)name, namelen);			/* real name */
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
145
146
  	offset += namelen;
  	*offset = '\0';
5d92b75c7   Andreas Gruenbacher   xfs: Change how l...
147
148
  
  compute_size:
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
149
150
151
152
153
  	context->count += prefix_len + namelen + 1;
  	return 0;
  }
  
  static int
5d92b75c7   Andreas Gruenbacher   xfs: Change how l...
154
  xfs_xattr_put_listent(
a9273ca5c   Dave Chinner   xfs: convert attr...
155
156
157
158
  	struct xfs_attr_list_context *context,
  	int		flags,
  	unsigned char	*name,
  	int		namelen,
e5bd12bfe   Eric Sandeen   xfs: don't pass v...
159
  	int		valuelen)
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
160
  {
5d92b75c7   Andreas Gruenbacher   xfs: Change how l...
161
162
  	char *prefix;
  	int prefix_len;
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
163

5d92b75c7   Andreas Gruenbacher   xfs: Change how l...
164
  	ASSERT(context->count >= 0);
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
165

5d92b75c7   Andreas Gruenbacher   xfs: Change how l...
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
  	if (flags & XFS_ATTR_ROOT) {
  #ifdef CONFIG_XFS_POSIX_ACL
  		if (namelen == SGI_ACL_FILE_SIZE &&
  		    strncmp(name, SGI_ACL_FILE,
  			    SGI_ACL_FILE_SIZE) == 0) {
  			int ret = __xfs_xattr_put_listent(
  					context, XATTR_SYSTEM_PREFIX,
  					XATTR_SYSTEM_PREFIX_LEN,
  					XATTR_POSIX_ACL_ACCESS,
  					strlen(XATTR_POSIX_ACL_ACCESS));
  			if (ret)
  				return ret;
  		} else if (namelen == SGI_ACL_DEFAULT_SIZE &&
  			 strncmp(name, SGI_ACL_DEFAULT,
  				 SGI_ACL_DEFAULT_SIZE) == 0) {
  			int ret = __xfs_xattr_put_listent(
  					context, XATTR_SYSTEM_PREFIX,
  					XATTR_SYSTEM_PREFIX_LEN,
  					XATTR_POSIX_ACL_DEFAULT,
  					strlen(XATTR_POSIX_ACL_DEFAULT));
  			if (ret)
  				return ret;
  		}
  #endif
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
190

5d92b75c7   Andreas Gruenbacher   xfs: Change how l...
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
  		/*
  		 * Only show root namespace entries if we are actually allowed to
  		 * see them.
  		 */
  		if (!capable(CAP_SYS_ADMIN))
  			return 0;
  
  		prefix = XATTR_TRUSTED_PREFIX;
  		prefix_len = XATTR_TRUSTED_PREFIX_LEN;
  	} else if (flags & XFS_ATTR_SECURE) {
  		prefix = XATTR_SECURITY_PREFIX;
  		prefix_len = XATTR_SECURITY_PREFIX_LEN;
  	} else {
  		prefix = XATTR_USER_PREFIX;
  		prefix_len = XATTR_USER_PREFIX_LEN;
  	}
  
  	return __xfs_xattr_put_listent(context, prefix, prefix_len, name,
  				       namelen);
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
210
211
212
  }
  
  ssize_t
2a6fba6d2   Eric Sandeen   xfs: only return ...
213
214
215
216
  xfs_vn_listxattr(
  	struct dentry	*dentry,
  	char		*data,
  	size_t		size)
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
217
218
219
  {
  	struct xfs_attr_list_context context;
  	struct attrlist_cursor_kern cursor = { 0 };
2a6fba6d2   Eric Sandeen   xfs: only return ...
220
221
  	struct inode	*inode = d_inode(dentry);
  	int		error;
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
222
223
224
225
226
227
228
229
  
  	/*
  	 * First read the regular on-disk attributes.
  	 */
  	memset(&context, 0, sizeof(context));
  	context.dp = XFS_I(inode);
  	context.cursor = &cursor;
  	context.resynch = 1;
5d92b75c7   Andreas Gruenbacher   xfs: Change how l...
230
  	context.alist = size ? data : NULL;
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
231
232
  	context.bufsize = size;
  	context.firstu = context.bufsize;
5d92b75c7   Andreas Gruenbacher   xfs: Change how l...
233
  	context.put_listent = xfs_xattr_put_listent;
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
234

2a6fba6d2   Eric Sandeen   xfs: only return ...
235
236
237
  	error = xfs_attr_list_int(&context);
  	if (error)
  		return error;
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
238
239
  	if (context.count < 0)
  		return -ERANGE;
f9e09f095   Lachlan McIlroy   [XFS] Use the gen...
240
241
  	return context.count;
  }