Linux compat 2.6.39: mount_nodev()
[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))
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 = CRED();
114         int error;
115         xattr_filldir_t xf = { buffer_size, 0, buffer, ip };
116
117         crhold(cr);
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         crfree(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 = CRED();
149         int error;
150
151         crhold(cr);
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         crfree(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 = CRED();
192         ssize_t wrote;
193         int error;
194         const int xattr_mode = S_IFREG | 0644;
195
196         crhold(cr);
197
198         /* Lookup the xattr directory and create it if required. */
199         error = -zfs_lookup(ip, NULL, &dxip, LOOKUP_XATTR | CREATE_XATTR_DIR,
200             cr, NULL, NULL);
201         if (error)
202                 goto out;
203
204         /*
205          * Lookup a specific xattr name in the directory, two failure modes:
206          *   XATTR_CREATE: fail if xattr already exists
207          *   XATTR_REMOVE: fail if xattr does not exist
208          */
209         error = -zfs_lookup(dxip, (char *)name, &xip, 0, cr, NULL, NULL);
210         if (error) {
211                 if (error != -ENOENT)
212                         goto out;
213
214                 if ((error == -ENOENT) && (flags & XATTR_REPLACE))
215                         goto out;
216         } else {
217                 error = -EEXIST;
218                 if (flags & XATTR_CREATE)
219                         goto out;
220         }
221         error = 0;
222
223         /* Remove a specific name xattr when value is set to NULL. */
224         if (value == NULL) {
225                 if (xip)
226                         error = -zfs_remove(dxip, (char *)name, cr);
227
228                 goto out;
229         }
230
231         /* Lookup failed create a new xattr. */
232         if (xip == NULL) {
233                 vap = kmem_zalloc(sizeof(vattr_t), KM_SLEEP);
234                 vap->va_mode = xattr_mode;
235                 vap->va_mask = ATTR_MODE;
236                 vap->va_uid = crgetfsuid(cr);
237                 vap->va_gid = crgetfsgid(cr);
238
239                 error = -zfs_create(dxip, (char *)name, vap, 0, 0644, &xip,
240                     cr, 0, NULL);
241                 if (error)
242                         goto out;
243         }
244
245         ASSERT(xip != NULL);
246
247         error = -zfs_freesp(ITOZ(xip), 0, 0, xattr_mode, TRUE);
248         if (error)
249                 goto out;
250
251         wrote = zpl_write_common(xip, value, size, 0, UIO_SYSSPACE, 0, cr);
252         if (wrote < 0)
253                 error = wrote;
254
255 out:
256         if (vap)
257                 kmem_free(vap, sizeof(vattr_t));
258
259         if (xip)
260                 iput(xip);
261
262         if (dxip)
263                 iput(dxip);
264
265         crfree(cr);
266         if (error == -ENOENT)
267                 error = -ENODATA;
268
269         ASSERT3S(error, <=, 0);
270
271         return (error);
272 }
273
274 static int
275 __zpl_xattr_user_get(struct inode *ip, const char *name,
276     void *buffer, size_t size)
277 {
278         char *xattr_name;
279         int error;
280
281         if (strcmp(name, "") == 0)
282                 return -EINVAL;
283
284         if (!(ITOZSB(ip)->z_flags & ZSB_XATTR))
285                 return -EOPNOTSUPP;
286
287         xattr_name = kmem_asprintf("%s%s", XATTR_USER_PREFIX, name);
288         error = zpl_xattr_get(ip, xattr_name, buffer, size);
289         strfree(xattr_name);
290
291         return (error);
292 }
293 ZPL_XATTR_GET_WRAPPER(zpl_xattr_user_get);
294
295 static int
296 __zpl_xattr_user_set(struct inode *ip, const char *name,
297     const void *value, size_t size, int flags)
298 {
299         char *xattr_name;
300         int error;
301
302         if (strcmp(name, "") == 0)
303                 return -EINVAL;
304
305         if (!(ITOZSB(ip)->z_flags & ZSB_XATTR))
306                 return -EOPNOTSUPP;
307
308         xattr_name = kmem_asprintf("%s%s", XATTR_USER_PREFIX, name);
309         error = zpl_xattr_set(ip, xattr_name, value, size, flags);
310         strfree(xattr_name);
311
312         return (error);
313 }
314 ZPL_XATTR_SET_WRAPPER(zpl_xattr_user_set);
315
316 xattr_handler_t zpl_xattr_user_handler = {
317         .prefix = XATTR_USER_PREFIX,
318         .get    = zpl_xattr_user_get,
319         .set    = zpl_xattr_user_set,
320 };
321
322 static int
323 __zpl_xattr_trusted_get(struct inode *ip, const char *name,
324     void *buffer, size_t size)
325 {
326         char *xattr_name;
327         int error;
328
329         if (!capable(CAP_SYS_ADMIN))
330                 return -EACCES;
331
332         if (strcmp(name, "") == 0)
333                 return -EINVAL;
334
335         xattr_name = kmem_asprintf("%s%s", XATTR_TRUSTED_PREFIX, name);
336         error = zpl_xattr_get(ip, xattr_name, buffer, size);
337         strfree(xattr_name);
338
339         return (error);
340 }
341 ZPL_XATTR_GET_WRAPPER(zpl_xattr_trusted_get);
342
343 static int
344 __zpl_xattr_trusted_set(struct inode *ip, const char *name,
345     const void *value, size_t size, int flags)
346 {
347         char *xattr_name;
348         int error;
349
350         if (!capable(CAP_SYS_ADMIN))
351                 return -EACCES;
352
353         if (strcmp(name, "") == 0)
354                 return -EINVAL;
355
356         xattr_name = kmem_asprintf("%s%s", XATTR_TRUSTED_PREFIX, name);
357         error = zpl_xattr_set(ip, xattr_name, value, size, flags);
358         strfree(xattr_name);
359
360         return (error);
361 }
362 ZPL_XATTR_SET_WRAPPER(zpl_xattr_trusted_set);
363
364 xattr_handler_t zpl_xattr_trusted_handler = {
365         .prefix = XATTR_TRUSTED_PREFIX,
366         .get    = zpl_xattr_trusted_get,
367         .set    = zpl_xattr_trusted_set,
368 };
369
370 static int
371 __zpl_xattr_security_get(struct inode *ip, const char *name,
372     void *buffer, size_t size)
373 {
374         char *xattr_name;
375         int error;
376
377         if (strcmp(name, "") == 0)
378                 return -EINVAL;
379
380         xattr_name = kmem_asprintf("%s%s", XATTR_SECURITY_PREFIX, name);
381         error = zpl_xattr_get(ip, xattr_name, buffer, size);
382         strfree(xattr_name);
383
384         return (error);
385 }
386 ZPL_XATTR_GET_WRAPPER(zpl_xattr_security_get);
387
388 static int
389 __zpl_xattr_security_set(struct inode *ip, const char *name,
390     const void *value, size_t size, int flags)
391 {
392         char *xattr_name;
393         int error;
394
395         if (strcmp(name, "") == 0)
396                 return -EINVAL;
397
398         xattr_name = kmem_asprintf("%s%s", XATTR_SECURITY_PREFIX, name);
399         error = zpl_xattr_set(ip, xattr_name, value, size, flags);
400         strfree(xattr_name);
401
402         return (error);
403 }
404 ZPL_XATTR_SET_WRAPPER(zpl_xattr_security_set);
405
406 int
407 zpl_xattr_security_init(struct inode *ip, struct inode *dip,
408     const struct qstr *qstr)
409 {
410         int error;
411         size_t len;
412         void *value;
413         char *name;
414
415         error = zpl_security_inode_init_security(ip, dip, qstr,
416             &name, &value, &len);
417         if (error) {
418                 if (error == -EOPNOTSUPP)
419                         return 0;
420
421                 return (error);
422         }
423
424         error = __zpl_xattr_security_set(ip, name, value, len, 0);
425
426         kfree(name);
427         kfree(value);
428
429         return (error);
430 }
431
432 xattr_handler_t zpl_xattr_security_handler = {
433         .prefix = XATTR_SECURITY_PREFIX,
434         .get    = zpl_xattr_security_get,
435         .set    = zpl_xattr_security_set,
436 };
437
438 xattr_handler_t *zpl_xattr_handlers[] = {
439         &zpl_xattr_security_handler,
440         &zpl_xattr_trusted_handler,
441         &zpl_xattr_user_handler,
442 #ifdef HAVE_POSIX_ACLS
443         &zpl_xattr_acl_access_handler,
444         &zpl_xattr_acl_default_handler,
445 #endif /* HAVE_POSIX_ACLS */
446 };