vfs_xattr.c revision 1.22 1 /* $NetBSD: vfs_xattr.c,v 1.22 2010/06/24 13:03:12 hannken Exp $ */
2
3 /*-
4 * Copyright (c) 2005, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright (c) 1989, 1993
34 * The Regents of the University of California. All rights reserved.
35 * (c) UNIX System Laboratories, Inc.
36 * All or some portions of this file are derived from material licensed
37 * to the University of California by American Telephone and Telegraph
38 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
39 * the permission of UNIX System Laboratories, Inc.
40 *
41 * Redistribution and use in source and binary forms, with or without
42 * modification, are permitted provided that the following conditions
43 * are met:
44 * 1. Redistributions of source code must retain the above copyright
45 * notice, this list of conditions and the following disclaimer.
46 * 2. Redistributions in binary form must reproduce the above copyright
47 * notice, this list of conditions and the following disclaimer in the
48 * documentation and/or other materials provided with the distribution.
49 * 3. Neither the name of the University nor the names of its contributors
50 * may be used to endorse or promote products derived from this software
51 * without specific prior written permission.
52 *
53 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
54 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
57 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63 * SUCH DAMAGE.
64 */
65
66 /*
67 * VFS extended attribute support.
68 */
69
70 #include <sys/cdefs.h>
71 __KERNEL_RCSID(0, "$NetBSD: vfs_xattr.c,v 1.22 2010/06/24 13:03:12 hannken Exp $");
72
73 #include <sys/param.h>
74 #include <sys/systm.h>
75 #include <sys/namei.h>
76 #include <sys/filedesc.h>
77 #include <sys/kernel.h>
78 #include <sys/file.h>
79 #include <sys/vnode.h>
80 #include <sys/mount.h>
81 #include <sys/proc.h>
82 #include <sys/uio.h>
83 #include <sys/extattr.h>
84 #include <sys/xattr.h>
85 #include <sys/sysctl.h>
86 #include <sys/syscallargs.h>
87 #include <sys/kauth.h>
88
89 /*
90 * Credential check based on process requesting service, and per-attribute
91 * permissions.
92 *
93 * NOTE: Vnode must be locked.
94 */
95 int
96 extattr_check_cred(struct vnode *vp, int attrnamespace,
97 kauth_cred_t cred, struct lwp *l, int access)
98 {
99
100 if (cred == NOCRED)
101 return (0);
102
103 switch (attrnamespace) {
104 case EXTATTR_NAMESPACE_SYSTEM:
105 /*
106 * Do we really want to allow this, or just require that
107 * these requests come from kernel code (NOCRED case above)?
108 */
109 return (kauth_authorize_generic(cred, KAUTH_GENERIC_ISSUSER,
110 NULL));
111
112 case EXTATTR_NAMESPACE_USER:
113 return (VOP_ACCESS(vp, access, cred));
114
115 default:
116 return (EPERM);
117 }
118 }
119
120 /*
121 * Default vfs_extattrctl routine for file systems that do not support
122 * it.
123 */
124 /*ARGSUSED*/
125 int
126 vfs_stdextattrctl(struct mount *mp, int cmt, struct vnode *vp,
127 int attrnamespace, const char *attrname)
128 {
129
130 if (vp != NULL)
131 VOP_UNLOCK(vp);
132 return (EOPNOTSUPP);
133 }
134
135 /*
136 * Push extended attribute configuration information into the file
137 * system.
138 *
139 * NOTE: Not all file systems that support extended attributes will
140 * require the use of this system call.
141 */
142 int
143 sys_extattrctl(struct lwp *l, const struct sys_extattrctl_args *uap, register_t *retval)
144 {
145 /* {
146 syscallarg(const char *) path;
147 syscallarg(int) cmd;
148 syscallarg(const char *) filename;
149 syscallarg(int) attrnamespace;
150 syscallarg(const char *) attrname;
151 } */
152 struct vnode *path_vp, *file_vp;
153 struct nameidata file_nd;
154 char attrname[EXTATTR_MAXNAMELEN];
155 int error;
156
157 if (SCARG(uap, attrname) != NULL) {
158 error = copyinstr(SCARG(uap, attrname), attrname,
159 sizeof(attrname), NULL);
160 if (error)
161 return (error);
162 }
163
164 error = namei_simple_user(SCARG(uap, path),
165 NSM_FOLLOW_NOEMULROOT, &path_vp);
166 if (error) {
167 return (error);
168 }
169
170 file_vp = NULL;
171 if (SCARG(uap, filename) != NULL) {
172 NDINIT(&file_nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
173 SCARG(uap, filename));
174 error = namei(&file_nd);
175 if (error) {
176 vrele(path_vp);
177 return (error);
178 }
179 file_vp = file_nd.ni_vp;
180 }
181
182 error = VFS_EXTATTRCTL(path_vp->v_mount, SCARG(uap, cmd), file_vp,
183 SCARG(uap, attrnamespace),
184 SCARG(uap, attrname) != NULL ? attrname : NULL);
185
186 if (file_vp != NULL)
187 vrele(file_vp);
188 vrele(path_vp);
189
190 return (error);
191 }
192
193 /*****************************************************************************
194 * Internal routines to manipulate file system extended attributes:
195 * - set
196 * - get
197 * - delete
198 * - list
199 *****************************************************************************/
200
201 /*
202 * extattr_set_vp:
203 *
204 * Set a named extended attribute on a file or directory.
205 */
206 static int
207 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
208 const void *data, size_t nbytes, struct lwp *l, register_t *retval)
209 {
210 struct uio auio;
211 struct iovec aiov;
212 ssize_t cnt;
213 int error;
214
215 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
216
217 aiov.iov_base = __UNCONST(data); /* XXXUNCONST kills const */
218 aiov.iov_len = nbytes;
219 auio.uio_iov = &aiov;
220 auio.uio_iovcnt = 1;
221 auio.uio_offset = 0;
222 if (nbytes > INT_MAX) {
223 error = EINVAL;
224 goto done;
225 }
226 auio.uio_resid = nbytes;
227 auio.uio_rw = UIO_WRITE;
228 KASSERT(l == curlwp);
229 auio.uio_vmspace = l->l_proc->p_vmspace;
230 cnt = nbytes;
231
232 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, l->l_cred);
233 cnt -= auio.uio_resid;
234 retval[0] = cnt;
235
236 done:
237 VOP_UNLOCK(vp);
238 return (error);
239 }
240
241 /*
242 * extattr_get_vp:
243 *
244 * Get a named extended attribute on a file or directory.
245 */
246 static int
247 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
248 void *data, size_t nbytes, struct lwp *l, register_t *retval)
249 {
250 struct uio auio, *auiop;
251 struct iovec aiov;
252 ssize_t cnt;
253 size_t size, *sizep;
254 int error;
255
256 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
257
258 /*
259 * Slightly unusual semantics: if the user provides a NULL data
260 * pointer, they don't want to receive the data, just the maximum
261 * read length.
262 */
263 auiop = NULL;
264 sizep = NULL;
265 cnt = 0;
266 if (data != NULL) {
267 aiov.iov_base = data;
268 aiov.iov_len = nbytes;
269 auio.uio_iov = &aiov;
270 auio.uio_offset = 0;
271 if (nbytes > INT_MAX) {
272 error = EINVAL;
273 goto done;
274 }
275 auio.uio_resid = nbytes;
276 auio.uio_rw = UIO_READ;
277 KASSERT(l == curlwp);
278 auio.uio_vmspace = l->l_proc->p_vmspace;
279 auiop = &auio;
280 cnt = nbytes;
281 } else
282 sizep = &size;
283
284 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
285 l->l_cred);
286
287 if (auiop != NULL) {
288 cnt -= auio.uio_resid;
289 retval[0] = cnt;
290 } else
291 retval[0] = size;
292
293 done:
294 VOP_UNLOCK(vp);
295 return (error);
296 }
297
298 /*
299 * extattr_delete_vp:
300 *
301 * Delete a named extended attribute on a file or directory.
302 */
303 static int
304 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
305 struct lwp *l)
306 {
307 int error;
308
309 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
310
311 error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, l->l_cred);
312 if (error == EOPNOTSUPP)
313 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
314 l->l_cred);
315
316 VOP_UNLOCK(vp);
317 return (error);
318 }
319
320 /*
321 * extattr_list_vp:
322 *
323 * Retrieve a list of extended attributes on a file or directory.
324 */
325 static int
326 extattr_list_vp(struct vnode *vp, int attrnamespace, void *data, size_t nbytes,
327 struct lwp *l, register_t *retval)
328 {
329 struct uio auio, *auiop;
330 size_t size, *sizep;
331 struct iovec aiov;
332 ssize_t cnt;
333 int error;
334
335 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
336
337 auiop = NULL;
338 sizep = NULL;
339 cnt = 0;
340 if (data != NULL) {
341 aiov.iov_base = data;
342 aiov.iov_len = nbytes;
343 auio.uio_iov = &aiov;
344 auio.uio_offset = 0;
345 if (nbytes > INT_MAX) {
346 error = EINVAL;
347 goto done;
348 }
349 auio.uio_resid = nbytes;
350 auio.uio_rw = UIO_READ;
351 KASSERT(l == curlwp);
352 auio.uio_vmspace = l->l_proc->p_vmspace;
353 auiop = &auio;
354 cnt = nbytes;
355 } else
356 sizep = &size;
357
358 error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep, l->l_cred);
359
360 if (auiop != NULL) {
361 cnt -= auio.uio_resid;
362 retval[0] = cnt;
363 } else
364 retval[0] = size;
365
366 done:
367 VOP_UNLOCK(vp);
368 return (error);
369 }
370
371 /*****************************************************************************
372 * BSD <sys/extattr.h> API for file system extended attributes
373 *****************************************************************************/
374
375 int
376 sys_extattr_set_fd(struct lwp *l, const struct sys_extattr_set_fd_args *uap, register_t *retval)
377 {
378 /* {
379 syscallarg(int) fd;
380 syscallarg(int) attrnamespace;
381 syscallarg(const char *) attrname;
382 syscallarg(const void *) data;
383 syscallarg(size_t) nbytes;
384 } */
385 struct file *fp;
386 struct vnode *vp;
387 char attrname[EXTATTR_MAXNAMELEN];
388 int error;
389
390 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
391 NULL);
392 if (error)
393 return (error);
394
395 error = fd_getvnode(SCARG(uap, fd), &fp);
396 if (error)
397 return (error);
398 vp = (struct vnode *) fp->f_data;
399
400 error = extattr_set_vp(vp, SCARG(uap, attrnamespace), attrname,
401 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
402
403 fd_putfile(SCARG(uap, fd));
404 return (error);
405 }
406
407 int
408 sys_extattr_set_file(struct lwp *l, const struct sys_extattr_set_file_args *uap, register_t *retval)
409 {
410 /* {
411 syscallarg(const char *) path;
412 syscallarg(int) attrnamespace;
413 syscallarg(const char *) attrname;
414 syscallarg(const void *) data;
415 syscallarg(size_t) nbytes;
416 } */
417 struct vnode *vp;
418 char attrname[EXTATTR_MAXNAMELEN];
419 int error;
420
421 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
422 NULL);
423 if (error)
424 return (error);
425
426 error = namei_simple_user(SCARG(uap, path),
427 NSM_FOLLOW_NOEMULROOT, &vp);
428 if (error)
429 return (error);
430
431 error = extattr_set_vp(vp, SCARG(uap, attrnamespace), attrname,
432 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
433
434 vrele(vp);
435 return (error);
436 }
437
438 int
439 sys_extattr_set_link(struct lwp *l, const struct sys_extattr_set_link_args *uap, register_t *retval)
440 {
441 /* {
442 syscallarg(const char *) path;
443 syscallarg(int) attrnamespace;
444 syscallarg(const char *) attrname;
445 syscallarg(const void *) data;
446 syscallarg(size_t) nbytes;
447 } */
448 struct vnode *vp;
449 char attrname[EXTATTR_MAXNAMELEN];
450 int error;
451
452 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
453 NULL);
454 if (error)
455 return (error);
456
457 error = namei_simple_user(SCARG(uap, path),
458 NSM_NOFOLLOW_NOEMULROOT, &vp);
459 if (error)
460 return (error);
461
462 error = extattr_set_vp(vp, SCARG(uap, attrnamespace), attrname,
463 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
464
465 vrele(vp);
466 return (error);
467 }
468
469 int
470 sys_extattr_get_fd(struct lwp *l, const struct sys_extattr_get_fd_args *uap, register_t *retval)
471 {
472 /* {
473 syscallarg(int) fd;
474 syscallarg(int) attrnamespace;
475 syscallarg(const char *) attrname;
476 syscallarg(void *) data;
477 syscallarg(size_t) nbytes;
478 } */
479 struct file *fp;
480 struct vnode *vp;
481 char attrname[EXTATTR_MAXNAMELEN];
482 int error;
483
484 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
485 NULL);
486 if (error)
487 return (error);
488
489 error = fd_getvnode(SCARG(uap, fd), &fp);
490 if (error)
491 return (error);
492 vp = (struct vnode *) fp->f_data;
493
494 error = extattr_get_vp(vp, SCARG(uap, attrnamespace), attrname,
495 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
496
497 fd_putfile(SCARG(uap, fd));
498 return (error);
499 }
500
501 int
502 sys_extattr_get_file(struct lwp *l, const struct sys_extattr_get_file_args *uap, register_t *retval)
503 {
504 /* {
505 syscallarg(const char *) path;
506 syscallarg(int) attrnamespace;
507 syscallarg(const char *) attrname;
508 syscallarg(void *) data;
509 syscallarg(size_t) nbytes;
510 } */
511 struct vnode *vp;
512 char attrname[EXTATTR_MAXNAMELEN];
513 int error;
514
515 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
516 NULL);
517 if (error)
518 return (error);
519
520 error = namei_simple_user(SCARG(uap, path),
521 NSM_FOLLOW_NOEMULROOT, &vp);
522 if (error)
523 return (error);
524
525 error = extattr_get_vp(vp, SCARG(uap, attrnamespace), attrname,
526 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
527
528 vrele(vp);
529 return (error);
530 }
531
532 int
533 sys_extattr_get_link(struct lwp *l, const struct sys_extattr_get_link_args *uap, register_t *retval)
534 {
535 /* {
536 syscallarg(const char *) path;
537 syscallarg(int) attrnamespace;
538 syscallarg(const char *) attrname;
539 syscallarg(void *) data;
540 syscallarg(size_t) nbytes;
541 } */
542 struct vnode *vp;
543 char attrname[EXTATTR_MAXNAMELEN];
544 int error;
545
546 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
547 NULL);
548 if (error)
549 return (error);
550
551 error = namei_simple_user(SCARG(uap, path),
552 NSM_NOFOLLOW_NOEMULROOT, &vp);
553 if (error)
554 return (error);
555
556 error = extattr_get_vp(vp, SCARG(uap, attrnamespace), attrname,
557 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
558
559 vrele(vp);
560 return (error);
561 }
562
563 int
564 sys_extattr_delete_fd(struct lwp *l, const struct sys_extattr_delete_fd_args *uap, register_t *retval)
565 {
566 /* {
567 syscallarg(int) fd;
568 syscallarg(int) attrnamespace;
569 syscallarg(const char *) attrname;
570 } */
571 struct file *fp;
572 struct vnode *vp;
573 char attrname[EXTATTR_MAXNAMELEN];
574 int error;
575
576 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
577 NULL);
578 if (error)
579 return (error);
580
581 error = fd_getvnode(SCARG(uap, fd), &fp);
582 if (error)
583 return (error);
584 vp = (struct vnode *) fp->f_data;
585
586 error = extattr_delete_vp(vp, SCARG(uap, attrnamespace), attrname, l);
587
588 fd_putfile(SCARG(uap, fd));
589 return (error);
590 }
591
592 int
593 sys_extattr_delete_file(struct lwp *l, const struct sys_extattr_delete_file_args *uap, register_t *retval)
594 {
595 /* {
596 syscallarg(const char *) path;
597 syscallarg(int) attrnamespace;
598 syscallarg(const char *) attrname;
599 } */
600 struct vnode *vp;
601 char attrname[EXTATTR_MAXNAMELEN];
602 int error;
603
604 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
605 NULL);
606 if (error)
607 return (error);
608
609 error = namei_simple_user(SCARG(uap, path),
610 NSM_FOLLOW_NOEMULROOT, &vp);
611 if (error)
612 return (error);
613
614 error = extattr_delete_vp(vp, SCARG(uap, attrnamespace), attrname, l);
615
616 vrele(vp);
617 return (error);
618 }
619
620 int
621 sys_extattr_delete_link(struct lwp *l, const struct sys_extattr_delete_link_args *uap, register_t *retval)
622 {
623 /* {
624 syscallarg(const char *) path;
625 syscallarg(int) attrnamespace;
626 syscallarg(const char *) attrname;
627 } */
628 struct vnode *vp;
629 char attrname[EXTATTR_MAXNAMELEN];
630 int error;
631
632 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
633 NULL);
634 if (error)
635 return (error);
636
637 error = namei_simple_user(SCARG(uap, path),
638 NSM_NOFOLLOW_NOEMULROOT, &vp);
639 if (error)
640 return (error);
641
642 error = extattr_delete_vp(vp, SCARG(uap, attrnamespace), attrname, l);
643
644 vrele(vp);
645 return (error);
646 }
647
648 int
649 sys_extattr_list_fd(struct lwp *l, const struct sys_extattr_list_fd_args *uap, register_t *retval)
650 {
651 /* {
652 syscallarg(int) fd;
653 syscallarg(int) attrnamespace;
654 syscallarg(void *) data;
655 syscallarg(size_t) nbytes;
656 } */
657 struct file *fp;
658 struct vnode *vp;
659 int error;
660
661 error = fd_getvnode(SCARG(uap, fd), &fp);
662 if (error)
663 return (error);
664 vp = (struct vnode *) fp->f_data;
665
666 error = extattr_list_vp(vp, SCARG(uap, attrnamespace),
667 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
668
669 fd_putfile(SCARG(uap, fd));
670 return (error);
671 }
672
673 int
674 sys_extattr_list_file(struct lwp *l, const struct sys_extattr_list_file_args *uap, register_t *retval)
675 {
676 /* {
677 syscallarg(const char *) path;
678 syscallarg(int) attrnamespace;
679 syscallarg(void *) data;
680 syscallarg(size_t) nbytes;
681 } */
682 struct vnode *vp;
683 int error;
684
685 error = namei_simple_user(SCARG(uap, path),
686 NSM_FOLLOW_NOEMULROOT, &vp);
687 if (error)
688 return (error);
689
690 error = extattr_list_vp(vp, SCARG(uap, attrnamespace),
691 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
692
693 vrele(vp);
694 return (error);
695 }
696
697 int
698 sys_extattr_list_link(struct lwp *l, const struct sys_extattr_list_link_args *uap, register_t *retval)
699 {
700 /* {
701 syscallarg(const char *) path;
702 syscallarg(int) attrnamespace;
703 syscallarg(void *) data;
704 syscallarg(size_t) nbytes;
705 } */
706 struct vnode *vp;
707 int error;
708
709 error = namei_simple_user(SCARG(uap, path),
710 NSM_NOFOLLOW_NOEMULROOT, &vp);
711 if (error)
712 return (error);
713
714 error = extattr_list_vp(vp, SCARG(uap, attrnamespace),
715 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
716
717 vrele(vp);
718 return (error);
719 }
720
721 /*****************************************************************************
722 * Linux-compatible <sys/xattr.h> API for file system extended attributes
723 *****************************************************************************/
724
725 int
726 sys_setxattr(struct lwp *l, const struct sys_setxattr_args *uap, register_t *retval)
727 {
728 /* {
729 syscallarg(const char *) path;
730 syscallarg(const char *) name;
731 syscallarg(void *) value;
732 syscallarg(size_t) size;
733 syscallarg(int) flags;
734 } */
735 struct vnode *vp;
736 char attrname[XATTR_NAME_MAX];
737 int error;
738
739 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
740 NULL);
741 if (error)
742 return (error);
743
744 error = namei_simple_user(SCARG(uap, path),
745 NSM_FOLLOW_NOEMULROOT, &vp);
746 if (error)
747 return (error);
748
749 /* XXX flags */
750
751 error = extattr_set_vp(vp, EXTATTR_NAMESPACE_USER,
752 attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
753
754 vrele(vp);
755 return (error);
756 }
757
758 int
759 sys_lsetxattr(struct lwp *l, const struct sys_lsetxattr_args *uap, register_t *retval)
760 {
761 /* {
762 syscallarg(const char *) path;
763 syscallarg(const char *) name;
764 syscallarg(void *) value;
765 syscallarg(size_t) size;
766 syscallarg(int) flags;
767 } */
768 struct vnode *vp;
769 char attrname[XATTR_NAME_MAX];
770 int error;
771
772 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
773 NULL);
774 if (error)
775 return (error);
776
777 error = namei_simple_user(SCARG(uap, path),
778 NSM_NOFOLLOW_NOEMULROOT, &vp);
779 if (error)
780 return (error);
781
782 /* XXX flags */
783
784 error = extattr_set_vp(vp, EXTATTR_NAMESPACE_USER,
785 attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
786
787 vrele(vp);
788 return (error);
789 }
790
791 int
792 sys_fsetxattr(struct lwp *l, const struct sys_fsetxattr_args *uap, register_t *retval)
793 {
794 /* {
795 syscallarg(int) fd;
796 syscallarg(const char *) name;
797 syscallarg(void *) value;
798 syscallarg(size_t) size;
799 syscallarg(int) flags;
800 } */
801 struct file *fp;
802 struct vnode *vp;
803 char attrname[XATTR_NAME_MAX];
804 int error;
805
806 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
807 NULL);
808 if (error)
809 return (error);
810
811 error = fd_getvnode(SCARG(uap, fd), &fp);
812 if (error)
813 return (error);
814 vp = (struct vnode *) fp->f_data;
815
816 /* XXX flags */
817
818 error = extattr_set_vp(vp, EXTATTR_NAMESPACE_USER,
819 attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
820
821 fd_putfile(SCARG(uap, fd));
822 return (error);
823 }
824
825 int
826 sys_getxattr(struct lwp *l, const struct sys_getxattr_args *uap, register_t *retval)
827 {
828 /* {
829 syscallarg(const char *) path;
830 syscallarg(const char *) name;
831 syscallarg(void *) value;
832 syscallarg(size_t) size;
833 } */
834 struct vnode *vp;
835 char attrname[XATTR_NAME_MAX];
836 int error;
837
838 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
839 NULL);
840 if (error)
841 return (error);
842
843 error = namei_simple_user(SCARG(uap, path),
844 NSM_FOLLOW_NOEMULROOT, &vp);
845 if (error)
846 return (error);
847
848 error = extattr_get_vp(vp, EXTATTR_NAMESPACE_USER,
849 attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
850
851 vrele(vp);
852 return (error);
853 }
854
855 int
856 sys_lgetxattr(struct lwp *l, const struct sys_lgetxattr_args *uap, register_t *retval)
857 {
858 /* {
859 syscallarg(const char *) path;
860 syscallarg(const char *) name;
861 syscallarg(void *) value;
862 syscallarg(size_t) size;
863 } */
864 struct vnode *vp;
865 char attrname[XATTR_NAME_MAX];
866 int error;
867
868 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
869 NULL);
870 if (error)
871 return (error);
872
873 error = namei_simple_user(SCARG(uap, path),
874 NSM_NOFOLLOW_NOEMULROOT, &vp);
875 if (error)
876 return (error);
877
878 error = extattr_get_vp(vp, EXTATTR_NAMESPACE_USER,
879 attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
880
881 vrele(vp);
882 return (error);
883 }
884
885 int
886 sys_fgetxattr(struct lwp *l, const struct sys_fgetxattr_args *uap, register_t *retval)
887 {
888 /* {
889 syscallarg(int) fd;
890 syscallarg(const char *) name;
891 syscallarg(void *) value;
892 syscallarg(size_t) size;
893 } */
894 struct file *fp;
895 struct vnode *vp;
896 char attrname[XATTR_NAME_MAX];
897 int error;
898
899 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
900 NULL);
901 if (error)
902 return (error);
903
904 error = fd_getvnode(SCARG(uap, fd), &fp);
905 if (error)
906 return (error);
907 vp = (struct vnode *) fp->f_data;
908
909 error = extattr_get_vp(vp, EXTATTR_NAMESPACE_USER,
910 attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
911
912 fd_putfile(SCARG(uap, fd));
913 return (error);
914 }
915
916 int
917 sys_listxattr(struct lwp *l, const struct sys_listxattr_args *uap, register_t *retval)
918 {
919 /* {
920 syscallarg(const char *) path;
921 syscallarg(char *) list;
922 syscallarg(size_t) size;
923 } */
924 struct vnode *vp;
925 int error;
926
927 error = namei_simple_user(SCARG(uap, path),
928 NSM_FOLLOW_NOEMULROOT, &vp);
929 if (error)
930 return (error);
931
932 error = extattr_list_vp(vp, EXTATTR_NAMESPACE_USER,
933 SCARG(uap, list), SCARG(uap, size), l, retval);
934
935 vrele(vp);
936 return (error);
937 }
938
939 int
940 sys_llistxattr(struct lwp *l, const struct sys_llistxattr_args *uap, register_t *retval)
941 {
942 /* {
943 syscallarg(const char *) path;
944 syscallarg(char *) list;
945 syscallarg(size_t) size;
946 } */
947 struct vnode *vp;
948 int error;
949
950 error = namei_simple_user(SCARG(uap, path),
951 NSM_NOFOLLOW_NOEMULROOT, &vp);
952 if (error)
953 return (error);
954
955 error = extattr_list_vp(vp, EXTATTR_NAMESPACE_USER,
956 SCARG(uap, list), SCARG(uap, size), l, retval);
957
958 vrele(vp);
959 return (error);
960 }
961
962 int
963 sys_flistxattr(struct lwp *l, const struct sys_flistxattr_args *uap, register_t *retval)
964 {
965 /* {
966 syscallarg(int) fd;
967 syscallarg(char *) list;
968 syscallarg(size_t) size;
969 } */
970 struct file *fp;
971 struct vnode *vp;
972 int error;
973
974 error = fd_getvnode(SCARG(uap, fd), &fp);
975 if (error)
976 return (error);
977 vp = (struct vnode *) fp->f_data;
978
979 error = extattr_list_vp(vp, EXTATTR_NAMESPACE_USER,
980 SCARG(uap, list), SCARG(uap, size), l, retval);
981
982 fd_putfile(SCARG(uap, fd));
983 return (error);
984 }
985
986 int
987 sys_removexattr(struct lwp *l, const struct sys_removexattr_args *uap, register_t *retval)
988 {
989 /* {
990 syscallarg(const char *) path;
991 syscallarg(const char *) name;
992 } */
993 struct vnode *vp;
994 char attrname[XATTR_NAME_MAX];
995 int error;
996
997 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
998 NULL);
999 if (error)
1000 return (error);
1001
1002 error = namei_simple_user(SCARG(uap, path),
1003 NSM_FOLLOW_NOEMULROOT, &vp);
1004 if (error)
1005 return (error);
1006
1007 error = extattr_delete_vp(vp, EXTATTR_NAMESPACE_USER,
1008 attrname, l);
1009
1010 vrele(vp);
1011 return (error);
1012 }
1013
1014 int
1015 sys_lremovexattr(struct lwp *l, const struct sys_lremovexattr_args *uap, register_t *retval)
1016 {
1017 /* {
1018 syscallarg(const char *) path;
1019 syscallarg(const char *) name;
1020 } */
1021 struct vnode *vp;
1022 char attrname[XATTR_NAME_MAX];
1023 int error;
1024
1025 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
1026 NULL);
1027 if (error)
1028 return (error);
1029
1030 error = namei_simple_user(SCARG(uap, path),
1031 NSM_NOFOLLOW_NOEMULROOT, &vp);
1032 if (error)
1033 return (error);
1034
1035 error = extattr_delete_vp(vp, EXTATTR_NAMESPACE_USER,
1036 attrname, l);
1037
1038 vrele(vp);
1039 return (error);
1040 }
1041
1042 int
1043 sys_fremovexattr(struct lwp *l, const struct sys_fremovexattr_args *uap, register_t *retval)
1044 {
1045 /* {
1046 syscallarg(int) fd;
1047 syscallarg(const char *) name;
1048 } */
1049 struct file *fp;
1050 struct vnode *vp;
1051 char attrname[XATTR_NAME_MAX];
1052 int error;
1053
1054 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
1055 NULL);
1056 if (error)
1057 return (error);
1058
1059 error = fd_getvnode(SCARG(uap, fd), &fp);
1060 if (error)
1061 return (error);
1062 vp = (struct vnode *) fp->f_data;
1063
1064 error = extattr_delete_vp(vp, EXTATTR_NAMESPACE_USER,
1065 attrname, l);
1066
1067 fd_putfile(SCARG(uap, fd));
1068 return (error);
1069 }
1070