Linux 2.6.35 compat, const struct xattr_handler
[zfs.git] / module / zfs / zpl_xattr.c
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright (c) 2011, Lawrence Livermore National Security, LLC.
23  *
24  * Extended attributes (xattr) on Solaris are implemented as files
25  * which exist in a hidden xattr directory.  These extended attributes
26  * can be accessed using the attropen() system call which opens
27  * the extended attribute.  It can then be manipulated just like
28  * a standard file descriptor.  This has a couple advantages such
29  * as practically no size limit on the file, and the extended
30  * attributes permissions may differ from those of the parent file.
31  * This interface is really quite clever, but it's also completely
32  * different than what is supported on Linux.
33  *
34  * Under Linux extended attributes are manipulated by the system
35  * calls getxattr(2), setxattr(2), and listxattr(2).  They consider
36  * extended attributes to be name/value pairs where the name is a
37  * NULL terminated string.  The name must also include one of the
38  * following name space prefixes:
39  *
40  *   user     - No restrictions and is available to user applications.
41  *   trusted  - Restricted to kernel and root (CAP_SYS_ADMIN) use.
42  *   system   - Used for access control lists (system.nfs4_acl, etc).
43  *   security - Used by SELinux to store a files security context.
44  *
45  * This Linux interface is implemented internally using the more
46  * flexible Solaris style extended attributes.  Every extended
47  * attribute is store as a file in a hidden directory associated
48  * with the parent file.  This ensures on disk compatibility with
49  * zfs implementations on other platforms (Solaris, FreeBSD, MacOS).
50  *
51  * One consequence of this implementation is that when an extended
52  * attribute is manipulated an inode is created.  This inode will
53  * exist in the Linux inode cache but there will be no associated
54  * entry in the dentry cache which references it.  This is safe
55  * but it may result in some confusion.
56  *
57  * Longer term I would like to see the 'security.selinux' extended
58  * attribute moved to a SA.  This should significantly improve
59  * performance on a SELinux enabled system by minimizing the
60  * number of seeks required to access a file.  However, for now
61  * this xattr is still stored in a file because I'm pretty sure
62  * adding a new SA will break on-disk compatibility.
63  */
64
65
66 #include <sys/zfs_vfsops.h>
67 #include <sys/zfs_vnops.h>
68 #include <sys/zfs_znode.h>
69 #include <sys/vfs.h>
70 #include <sys/zpl.h>
71
72 typedef struct xattr_filldir {
73         size_t size;
74         size_t offset;
75         char *buf;
76         struct inode *inode;
77 } xattr_filldir_t;
78
79 static int
80 zpl_xattr_filldir(void *arg, const char *name, int name_len,
81     loff_t offset, uint64_t objnum, unsigned int d_type)
82 {
83         xattr_filldir_t *xf = arg;
84
85         if (!strncmp(name, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN))
86                 if (!(ITOZSB(xf->inode)->z_flags & ZSB_XATTR_USER))
87                         return (0);
88
89         if (!strncmp(name, XATTR_TRUSTED_PREFIX, XATTR_TRUSTED_PREFIX_LEN))
90                 if (!capable(CAP_SYS_ADMIN))
91                         return (0);
92
93         /* When xf->buf is NULL only calculate the required size. */
94         if (xf->buf) {
95                 if (xf->offset + name_len + 1 > xf->size)
96                         return (-ERANGE);
97
98                 memcpy(xf->buf + xf->offset, name, name_len);
99                 xf->buf[xf->offset + name_len] = '\0';
100         }
101
102         xf->offset += (name_len + 1);
103
104         return (0);
105 }
106
107 ssize_t
108 zpl_xattr_list(struct dentry *dentry, char *buffer, size_t buffer_size)
109 {
110         struct inode *ip = dentry->d_inode;
111         struct inode *dxip = NULL;
112         loff_t pos = 3;  /* skip '.', '..', and '.zfs' entries. */
113         cred_t *cr;
114         int error;
115         xattr_filldir_t xf = { buffer_size, 0, buffer, ip };
116
117         cr = (cred_t *)get_current_cred();
118
119         /* Lookup the xattr directory */
120         error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR, cr, NULL, NULL);
121         if (error) {
122                 if (error == -ENOENT)
123                         error = 0;
124
125                 goto out;
126         }
127
128         /* Fill provided buffer via zpl_zattr_filldir helper */
129         error = -zfs_readdir(dxip, (void *)&xf, zpl_xattr_filldir, &pos, cr);
130         if (error)
131                 goto out;
132
133         error = xf.offset;
134 out:
135         if (dxip)
136                 iput(dxip);
137
138         put_cred(cr);
139
140         return (error);
141 }
142
143 static int
144 zpl_xattr_get(struct inode *ip, const char *name, void *buf, size_t size)
145 {
146         struct inode *dxip = NULL;
147         struct inode *xip = NULL;
148         cred_t *cr;
149         int error;
150
151         cr = (cred_t *)get_current_cred();
152
153         /* Lookup the xattr directory */
154         error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR, cr, NULL, NULL);
155         if (error)
156                 goto out;
157
158         /* Lookup a specific xattr name in the directory */
159         error = -zfs_lookup(dxip, (char *)name, &xip, 0, cr, NULL, NULL);
160         if (error)
161                 goto out;
162
163         if (!size) {
164                 error = i_size_read(xip);
165                 goto out;
166         }
167
168         error = zpl_read_common(xip, buf, size, 0, UIO_SYSSPACE, 0, cr);
169 out:
170         if (xip)
171                 iput(xip);
172
173         if (dxip)
174                 iput(dxip);
175
176         put_cred(cr);
177
178         if (error == -ENOENT)
179                 error = -ENODATA;
180
181         return (error);
182 }
183
184 static int
185 zpl_xattr_set(struct inode *ip, const char *name, const void *value,
186     size_t size, int flags)
187 {
188         struct inode *dxip = NULL;
189         struct inode *xip = NULL;
190         vattr_t *vap = NULL;
191         cred_t *cr;
192         ssize_t wrote;
193         int error;
194
195         cr = (cred_t *)get_current_cred();
196
197         /* Lookup the xattr directory and create it if required. */
198         error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR | CREATE_XATTR_DIR,
199             cr, NULL, NULL);
200         if (error)
201                 goto out;
202
203         /*
204          * Lookup a specific xattr name in the directory, two failure modes:
205          *   XATTR_CREATE: fail if xattr already exists
206          *   XATTR_REMOVE: fail if xattr does not exist
207          */
208         error = -zfs_lookup(dxip, (char *)name, &xip, 0, cr, NULL, NULL);
209         if (error) {
210                 if (error != -ENOENT)
211                         goto out;
212
213                 if ((error == -ENOENT) && (flags & XATTR_REPLACE))
214                         goto out;
215         } else {
216                 error = -EEXIST;
217                 if (flags & XATTR_CREATE)
218                         goto out;
219         }
220         error = 0;
221
222         /* Remove a specific name xattr when value is set to NULL. */
223         if (value == NULL) {
224                 if (xip)
225                         error = -zfs_remove(dxip, (char *)name, cr);
226
227                 goto out;
228         }
229
230         /* Lookup failed create a new xattr. */
231         if (xip == NULL) {
232                 vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
233                 vap->va_mode = S_IFREG | 0644;
234                 vap->va_mask = ATTR_MODE;
235                 vap->va_uid = current_fsuid();
236                 vap->va_gid = current_fsgid();
237
238                 error = -zfs_create(dxip, (char *)name, vap, 0, 0644, &xip,
239                     cr, 0, NULL);
240                 if (error)
241                         goto out;
242         }
243
244         ASSERT(xip != NULL);
245         wrote = zpl_write_common(xip, value, size, 0, UIO_SYSSPACE, 0, cr);
246         if (wrote < 0)
247                 error = wrote;
248
249 out:
250         if (vap)
251                 kmem_free(vap, sizeof(vattr_t));
252
253         if (xip)
254                 iput(xip);
255
256         if (dxip)
257                 iput(dxip);
258
259         put_cred(cr);
260         if (error == -ENOENT)
261                 error = -ENODATA;
262
263         ASSERT3S(error, <=, 0);
264
265         return (error);
266 }
267
268 static int
269 zpl_xattr_user_get(struct inode *ip, const char *name,
270     void *buffer, size_t size)
271 {
272         char *xattr_name;
273         int error;
274
275         if (strcmp(name, "") == 0)
276                 return -EINVAL;
277
278         if (!(ITOZSB(ip)->z_flags & ZSB_XATTR_USER))
279                 return -EOPNOTSUPP;
280
281         xattr_name = kmem_asprintf("%s%s", XATTR_USER_PREFIX, name);
282         error = zpl_xattr_get(ip, xattr_name, buffer, size);
283         strfree(xattr_name);
284
285         return (error);
286 }
287
288 static int
289 zpl_xattr_user_set(struct inode *ip, const char *name,
290     const void *value, size_t size, int flags)
291 {
292         char *xattr_name;
293         int error;
294
295         if (strcmp(name, "") == 0)
296                 return -EINVAL;
297
298         if (!(ITOZSB(ip)->z_flags & ZSB_XATTR_USER))
299                 return -EOPNOTSUPP;
300
301         xattr_name = kmem_asprintf("%s%s", XATTR_USER_PREFIX, name);
302         error = zpl_xattr_set(ip, xattr_name, value, size, flags);
303         strfree(xattr_name);
304
305         return (error);
306 }
307
308 xattr_handler_t zpl_xattr_user_handler = {
309         .prefix = XATTR_USER_PREFIX,
310         .get    = zpl_xattr_user_get,
311         .set    = zpl_xattr_user_set,
312 };
313
314 static int
315 zpl_xattr_trusted_get(struct inode *ip, const char *name,
316     void *buffer, size_t size)
317 {
318         char *xattr_name;
319         int error;
320
321         if (!capable(CAP_SYS_ADMIN))
322                 return -EACCES;
323
324         if (strcmp(name, "") == 0)
325                 return -EINVAL;
326
327         xattr_name = kmem_asprintf("%s%s", XATTR_TRUSTED_PREFIX, name);
328         error = zpl_xattr_get(ip, xattr_name, buffer, size);
329         strfree(xattr_name);
330
331         return (error);
332 }
333
334 static int
335 zpl_xattr_trusted_set(struct inode *ip, const char *name,
336     const void *value, size_t size, int flags)
337 {
338         char *xattr_name;
339         int error;
340
341         if (!capable(CAP_SYS_ADMIN))
342                 return -EACCES;
343
344         if (strcmp(name, "") == 0)
345                 return -EINVAL;
346
347         xattr_name = kmem_asprintf("%s%s", XATTR_TRUSTED_PREFIX, name);
348         error = zpl_xattr_set(ip, xattr_name, value, size, flags);
349         strfree(xattr_name);
350
351         return (error);
352 }
353
354 xattr_handler_t zpl_xattr_trusted_handler = {
355         .prefix = XATTR_TRUSTED_PREFIX,
356         .get    = zpl_xattr_trusted_get,
357         .set    = zpl_xattr_trusted_set,
358 };
359
360 static int
361 zpl_xattr_security_get(struct inode *ip, const char *name,
362     void *buffer, size_t size)
363 {
364         char *xattr_name;
365         int error;
366
367         if (strcmp(name, "") == 0)
368                 return -EINVAL;
369
370         xattr_name = kmem_asprintf("%s%s", XATTR_SECURITY_PREFIX, name);
371         error = zpl_xattr_get(ip, xattr_name, buffer, size);
372         strfree(xattr_name);
373
374         return (error);
375 }
376
377 static int
378 zpl_xattr_security_set(struct inode *ip, const char *name,
379     const void *value, size_t size, int flags)
380 {
381         char *xattr_name;
382         int error;
383
384         if (strcmp(name, "") == 0)
385                 return -EINVAL;
386
387         xattr_name = kmem_asprintf("%s%s", XATTR_SECURITY_PREFIX, name);
388         error = zpl_xattr_set(ip, xattr_name, value, size, flags);
389         strfree(xattr_name);
390
391         return (error);
392 }
393
394 int
395 zpl_xattr_security_init(struct inode *ip, struct inode *dip)
396 {
397         int error;
398         size_t len;
399         void *value;
400         char *name;
401
402         error = security_inode_init_security(ip, dip, &name, &value, &len);
403         if (error) {
404                 if (error == -EOPNOTSUPP)
405                         return 0;
406
407                 return (error);
408         }
409
410         error = zpl_xattr_security_set(ip, name, value, len, 0);
411
412         kfree(name);
413         kfree(value);
414
415         return (error);
416 }
417
418 xattr_handler_t zpl_xattr_security_handler = {
419         .prefix = XATTR_SECURITY_PREFIX,
420         .get    = zpl_xattr_security_get,
421         .set    = zpl_xattr_security_set,
422 };
423
424 xattr_handler_t *zpl_xattr_handlers[] = {
425         &zpl_xattr_security_handler,
426         &zpl_xattr_trusted_handler,
427         &zpl_xattr_user_handler,
428 #ifdef HAVE_POSIX_ACLS
429         &zpl_xattr_acl_access_handler,
430         &zpl_xattr_acl_default_handler,
431 #endif /* HAVE_POSIX_ACLS */
432 };