vfs_xattr.c revision 1.23 1 /* $NetBSD: vfs_xattr.c,v 1.23 2010/11/19 06:44:45 dholland 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.23 2010/11/19 06:44:45 dholland 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 pathbuf *file_pb;
154 struct nameidata file_nd;
155 char attrname[EXTATTR_MAXNAMELEN];
156 int error;
157
158 if (SCARG(uap, attrname) != NULL) {
159 error = copyinstr(SCARG(uap, attrname), attrname,
160 sizeof(attrname), NULL);
161 if (error)
162 return (error);
163 }
164
165 error = namei_simple_user(SCARG(uap, path),
166 NSM_FOLLOW_NOEMULROOT, &path_vp);
167 if (error) {
168 return (error);
169 }
170
171 file_vp = NULL;
172 if (SCARG(uap, filename) != NULL) {
173 error = pathbuf_copyin(SCARG(uap, filename), &file_pb);
174 if (error) {
175 vrele(path_vp);
176 return (error);
177 }
178 NDINIT(&file_nd, LOOKUP, FOLLOW | LOCKLEAF, file_pb);
179 error = namei(&file_nd);
180 if (error) {
181 pathbuf_destroy(file_pb);
182 vrele(path_vp);
183 return (error);
184 }
185 file_vp = file_nd.ni_vp;
186 pathbuf_destroy(file_pb);
187 }
188
189 error = VFS_EXTATTRCTL(path_vp->v_mount, SCARG(uap, cmd), file_vp,
190 SCARG(uap, attrnamespace),
191 SCARG(uap, attrname) != NULL ? attrname : NULL);
192
193 if (file_vp != NULL)
194 vrele(file_vp);
195 vrele(path_vp);
196
197 return (error);
198 }
199
200 /*****************************************************************************
201 * Internal routines to manipulate file system extended attributes:
202 * - set
203 * - get
204 * - delete
205 * - list
206 *****************************************************************************/
207
208 /*
209 * extattr_set_vp:
210 *
211 * Set a named extended attribute on a file or directory.
212 */
213 static int
214 extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname,
215 const void *data, size_t nbytes, struct lwp *l, register_t *retval)
216 {
217 struct uio auio;
218 struct iovec aiov;
219 ssize_t cnt;
220 int error;
221
222 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
223
224 aiov.iov_base = __UNCONST(data); /* XXXUNCONST kills const */
225 aiov.iov_len = nbytes;
226 auio.uio_iov = &aiov;
227 auio.uio_iovcnt = 1;
228 auio.uio_offset = 0;
229 if (nbytes > INT_MAX) {
230 error = EINVAL;
231 goto done;
232 }
233 auio.uio_resid = nbytes;
234 auio.uio_rw = UIO_WRITE;
235 KASSERT(l == curlwp);
236 auio.uio_vmspace = l->l_proc->p_vmspace;
237 cnt = nbytes;
238
239 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, &auio, l->l_cred);
240 cnt -= auio.uio_resid;
241 retval[0] = cnt;
242
243 done:
244 VOP_UNLOCK(vp);
245 return (error);
246 }
247
248 /*
249 * extattr_get_vp:
250 *
251 * Get a named extended attribute on a file or directory.
252 */
253 static int
254 extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname,
255 void *data, size_t nbytes, struct lwp *l, register_t *retval)
256 {
257 struct uio auio, *auiop;
258 struct iovec aiov;
259 ssize_t cnt;
260 size_t size, *sizep;
261 int error;
262
263 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
264
265 /*
266 * Slightly unusual semantics: if the user provides a NULL data
267 * pointer, they don't want to receive the data, just the maximum
268 * read length.
269 */
270 auiop = NULL;
271 sizep = NULL;
272 cnt = 0;
273 if (data != NULL) {
274 aiov.iov_base = data;
275 aiov.iov_len = nbytes;
276 auio.uio_iov = &aiov;
277 auio.uio_offset = 0;
278 if (nbytes > INT_MAX) {
279 error = EINVAL;
280 goto done;
281 }
282 auio.uio_resid = nbytes;
283 auio.uio_rw = UIO_READ;
284 KASSERT(l == curlwp);
285 auio.uio_vmspace = l->l_proc->p_vmspace;
286 auiop = &auio;
287 cnt = nbytes;
288 } else
289 sizep = &size;
290
291 error = VOP_GETEXTATTR(vp, attrnamespace, attrname, auiop, sizep,
292 l->l_cred);
293
294 if (auiop != NULL) {
295 cnt -= auio.uio_resid;
296 retval[0] = cnt;
297 } else
298 retval[0] = size;
299
300 done:
301 VOP_UNLOCK(vp);
302 return (error);
303 }
304
305 /*
306 * extattr_delete_vp:
307 *
308 * Delete a named extended attribute on a file or directory.
309 */
310 static int
311 extattr_delete_vp(struct vnode *vp, int attrnamespace, const char *attrname,
312 struct lwp *l)
313 {
314 int error;
315
316 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
317
318 error = VOP_DELETEEXTATTR(vp, attrnamespace, attrname, l->l_cred);
319 if (error == EOPNOTSUPP)
320 error = VOP_SETEXTATTR(vp, attrnamespace, attrname, NULL,
321 l->l_cred);
322
323 VOP_UNLOCK(vp);
324 return (error);
325 }
326
327 /*
328 * extattr_list_vp:
329 *
330 * Retrieve a list of extended attributes on a file or directory.
331 */
332 static int
333 extattr_list_vp(struct vnode *vp, int attrnamespace, void *data, size_t nbytes,
334 struct lwp *l, register_t *retval)
335 {
336 struct uio auio, *auiop;
337 size_t size, *sizep;
338 struct iovec aiov;
339 ssize_t cnt;
340 int error;
341
342 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
343
344 auiop = NULL;
345 sizep = NULL;
346 cnt = 0;
347 if (data != NULL) {
348 aiov.iov_base = data;
349 aiov.iov_len = nbytes;
350 auio.uio_iov = &aiov;
351 auio.uio_offset = 0;
352 if (nbytes > INT_MAX) {
353 error = EINVAL;
354 goto done;
355 }
356 auio.uio_resid = nbytes;
357 auio.uio_rw = UIO_READ;
358 KASSERT(l == curlwp);
359 auio.uio_vmspace = l->l_proc->p_vmspace;
360 auiop = &auio;
361 cnt = nbytes;
362 } else
363 sizep = &size;
364
365 error = VOP_LISTEXTATTR(vp, attrnamespace, auiop, sizep, l->l_cred);
366
367 if (auiop != NULL) {
368 cnt -= auio.uio_resid;
369 retval[0] = cnt;
370 } else
371 retval[0] = size;
372
373 done:
374 VOP_UNLOCK(vp);
375 return (error);
376 }
377
378 /*****************************************************************************
379 * BSD <sys/extattr.h> API for file system extended attributes
380 *****************************************************************************/
381
382 int
383 sys_extattr_set_fd(struct lwp *l, const struct sys_extattr_set_fd_args *uap, register_t *retval)
384 {
385 /* {
386 syscallarg(int) fd;
387 syscallarg(int) attrnamespace;
388 syscallarg(const char *) attrname;
389 syscallarg(const void *) data;
390 syscallarg(size_t) nbytes;
391 } */
392 struct file *fp;
393 struct vnode *vp;
394 char attrname[EXTATTR_MAXNAMELEN];
395 int error;
396
397 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
398 NULL);
399 if (error)
400 return (error);
401
402 error = fd_getvnode(SCARG(uap, fd), &fp);
403 if (error)
404 return (error);
405 vp = (struct vnode *) fp->f_data;
406
407 error = extattr_set_vp(vp, SCARG(uap, attrnamespace), attrname,
408 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
409
410 fd_putfile(SCARG(uap, fd));
411 return (error);
412 }
413
414 int
415 sys_extattr_set_file(struct lwp *l, const struct sys_extattr_set_file_args *uap, register_t *retval)
416 {
417 /* {
418 syscallarg(const char *) path;
419 syscallarg(int) attrnamespace;
420 syscallarg(const char *) attrname;
421 syscallarg(const void *) data;
422 syscallarg(size_t) nbytes;
423 } */
424 struct vnode *vp;
425 char attrname[EXTATTR_MAXNAMELEN];
426 int error;
427
428 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
429 NULL);
430 if (error)
431 return (error);
432
433 error = namei_simple_user(SCARG(uap, path),
434 NSM_FOLLOW_NOEMULROOT, &vp);
435 if (error)
436 return (error);
437
438 error = extattr_set_vp(vp, SCARG(uap, attrnamespace), attrname,
439 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
440
441 vrele(vp);
442 return (error);
443 }
444
445 int
446 sys_extattr_set_link(struct lwp *l, const struct sys_extattr_set_link_args *uap, register_t *retval)
447 {
448 /* {
449 syscallarg(const char *) path;
450 syscallarg(int) attrnamespace;
451 syscallarg(const char *) attrname;
452 syscallarg(const void *) data;
453 syscallarg(size_t) nbytes;
454 } */
455 struct vnode *vp;
456 char attrname[EXTATTR_MAXNAMELEN];
457 int error;
458
459 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
460 NULL);
461 if (error)
462 return (error);
463
464 error = namei_simple_user(SCARG(uap, path),
465 NSM_NOFOLLOW_NOEMULROOT, &vp);
466 if (error)
467 return (error);
468
469 error = extattr_set_vp(vp, SCARG(uap, attrnamespace), attrname,
470 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
471
472 vrele(vp);
473 return (error);
474 }
475
476 int
477 sys_extattr_get_fd(struct lwp *l, const struct sys_extattr_get_fd_args *uap, register_t *retval)
478 {
479 /* {
480 syscallarg(int) fd;
481 syscallarg(int) attrnamespace;
482 syscallarg(const char *) attrname;
483 syscallarg(void *) data;
484 syscallarg(size_t) nbytes;
485 } */
486 struct file *fp;
487 struct vnode *vp;
488 char attrname[EXTATTR_MAXNAMELEN];
489 int error;
490
491 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
492 NULL);
493 if (error)
494 return (error);
495
496 error = fd_getvnode(SCARG(uap, fd), &fp);
497 if (error)
498 return (error);
499 vp = (struct vnode *) fp->f_data;
500
501 error = extattr_get_vp(vp, SCARG(uap, attrnamespace), attrname,
502 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
503
504 fd_putfile(SCARG(uap, fd));
505 return (error);
506 }
507
508 int
509 sys_extattr_get_file(struct lwp *l, const struct sys_extattr_get_file_args *uap, register_t *retval)
510 {
511 /* {
512 syscallarg(const char *) path;
513 syscallarg(int) attrnamespace;
514 syscallarg(const char *) attrname;
515 syscallarg(void *) data;
516 syscallarg(size_t) nbytes;
517 } */
518 struct vnode *vp;
519 char attrname[EXTATTR_MAXNAMELEN];
520 int error;
521
522 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
523 NULL);
524 if (error)
525 return (error);
526
527 error = namei_simple_user(SCARG(uap, path),
528 NSM_FOLLOW_NOEMULROOT, &vp);
529 if (error)
530 return (error);
531
532 error = extattr_get_vp(vp, SCARG(uap, attrnamespace), attrname,
533 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
534
535 vrele(vp);
536 return (error);
537 }
538
539 int
540 sys_extattr_get_link(struct lwp *l, const struct sys_extattr_get_link_args *uap, register_t *retval)
541 {
542 /* {
543 syscallarg(const char *) path;
544 syscallarg(int) attrnamespace;
545 syscallarg(const char *) attrname;
546 syscallarg(void *) data;
547 syscallarg(size_t) nbytes;
548 } */
549 struct vnode *vp;
550 char attrname[EXTATTR_MAXNAMELEN];
551 int error;
552
553 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
554 NULL);
555 if (error)
556 return (error);
557
558 error = namei_simple_user(SCARG(uap, path),
559 NSM_NOFOLLOW_NOEMULROOT, &vp);
560 if (error)
561 return (error);
562
563 error = extattr_get_vp(vp, SCARG(uap, attrnamespace), attrname,
564 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
565
566 vrele(vp);
567 return (error);
568 }
569
570 int
571 sys_extattr_delete_fd(struct lwp *l, const struct sys_extattr_delete_fd_args *uap, register_t *retval)
572 {
573 /* {
574 syscallarg(int) fd;
575 syscallarg(int) attrnamespace;
576 syscallarg(const char *) attrname;
577 } */
578 struct file *fp;
579 struct vnode *vp;
580 char attrname[EXTATTR_MAXNAMELEN];
581 int error;
582
583 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
584 NULL);
585 if (error)
586 return (error);
587
588 error = fd_getvnode(SCARG(uap, fd), &fp);
589 if (error)
590 return (error);
591 vp = (struct vnode *) fp->f_data;
592
593 error = extattr_delete_vp(vp, SCARG(uap, attrnamespace), attrname, l);
594
595 fd_putfile(SCARG(uap, fd));
596 return (error);
597 }
598
599 int
600 sys_extattr_delete_file(struct lwp *l, const struct sys_extattr_delete_file_args *uap, register_t *retval)
601 {
602 /* {
603 syscallarg(const char *) path;
604 syscallarg(int) attrnamespace;
605 syscallarg(const char *) attrname;
606 } */
607 struct vnode *vp;
608 char attrname[EXTATTR_MAXNAMELEN];
609 int error;
610
611 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
612 NULL);
613 if (error)
614 return (error);
615
616 error = namei_simple_user(SCARG(uap, path),
617 NSM_FOLLOW_NOEMULROOT, &vp);
618 if (error)
619 return (error);
620
621 error = extattr_delete_vp(vp, SCARG(uap, attrnamespace), attrname, l);
622
623 vrele(vp);
624 return (error);
625 }
626
627 int
628 sys_extattr_delete_link(struct lwp *l, const struct sys_extattr_delete_link_args *uap, register_t *retval)
629 {
630 /* {
631 syscallarg(const char *) path;
632 syscallarg(int) attrnamespace;
633 syscallarg(const char *) attrname;
634 } */
635 struct vnode *vp;
636 char attrname[EXTATTR_MAXNAMELEN];
637 int error;
638
639 error = copyinstr(SCARG(uap, attrname), attrname, sizeof(attrname),
640 NULL);
641 if (error)
642 return (error);
643
644 error = namei_simple_user(SCARG(uap, path),
645 NSM_NOFOLLOW_NOEMULROOT, &vp);
646 if (error)
647 return (error);
648
649 error = extattr_delete_vp(vp, SCARG(uap, attrnamespace), attrname, l);
650
651 vrele(vp);
652 return (error);
653 }
654
655 int
656 sys_extattr_list_fd(struct lwp *l, const struct sys_extattr_list_fd_args *uap, register_t *retval)
657 {
658 /* {
659 syscallarg(int) fd;
660 syscallarg(int) attrnamespace;
661 syscallarg(void *) data;
662 syscallarg(size_t) nbytes;
663 } */
664 struct file *fp;
665 struct vnode *vp;
666 int error;
667
668 error = fd_getvnode(SCARG(uap, fd), &fp);
669 if (error)
670 return (error);
671 vp = (struct vnode *) fp->f_data;
672
673 error = extattr_list_vp(vp, SCARG(uap, attrnamespace),
674 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
675
676 fd_putfile(SCARG(uap, fd));
677 return (error);
678 }
679
680 int
681 sys_extattr_list_file(struct lwp *l, const struct sys_extattr_list_file_args *uap, register_t *retval)
682 {
683 /* {
684 syscallarg(const char *) path;
685 syscallarg(int) attrnamespace;
686 syscallarg(void *) data;
687 syscallarg(size_t) nbytes;
688 } */
689 struct vnode *vp;
690 int error;
691
692 error = namei_simple_user(SCARG(uap, path),
693 NSM_FOLLOW_NOEMULROOT, &vp);
694 if (error)
695 return (error);
696
697 error = extattr_list_vp(vp, SCARG(uap, attrnamespace),
698 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
699
700 vrele(vp);
701 return (error);
702 }
703
704 int
705 sys_extattr_list_link(struct lwp *l, const struct sys_extattr_list_link_args *uap, register_t *retval)
706 {
707 /* {
708 syscallarg(const char *) path;
709 syscallarg(int) attrnamespace;
710 syscallarg(void *) data;
711 syscallarg(size_t) nbytes;
712 } */
713 struct vnode *vp;
714 int error;
715
716 error = namei_simple_user(SCARG(uap, path),
717 NSM_NOFOLLOW_NOEMULROOT, &vp);
718 if (error)
719 return (error);
720
721 error = extattr_list_vp(vp, SCARG(uap, attrnamespace),
722 SCARG(uap, data), SCARG(uap, nbytes), l, retval);
723
724 vrele(vp);
725 return (error);
726 }
727
728 /*****************************************************************************
729 * Linux-compatible <sys/xattr.h> API for file system extended attributes
730 *****************************************************************************/
731
732 int
733 sys_setxattr(struct lwp *l, const struct sys_setxattr_args *uap, register_t *retval)
734 {
735 /* {
736 syscallarg(const char *) path;
737 syscallarg(const char *) name;
738 syscallarg(void *) value;
739 syscallarg(size_t) size;
740 syscallarg(int) flags;
741 } */
742 struct vnode *vp;
743 char attrname[XATTR_NAME_MAX];
744 int error;
745
746 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
747 NULL);
748 if (error)
749 return (error);
750
751 error = namei_simple_user(SCARG(uap, path),
752 NSM_FOLLOW_NOEMULROOT, &vp);
753 if (error)
754 return (error);
755
756 /* XXX flags */
757
758 error = extattr_set_vp(vp, EXTATTR_NAMESPACE_USER,
759 attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
760
761 vrele(vp);
762 return (error);
763 }
764
765 int
766 sys_lsetxattr(struct lwp *l, const struct sys_lsetxattr_args *uap, register_t *retval)
767 {
768 /* {
769 syscallarg(const char *) path;
770 syscallarg(const char *) name;
771 syscallarg(void *) value;
772 syscallarg(size_t) size;
773 syscallarg(int) flags;
774 } */
775 struct vnode *vp;
776 char attrname[XATTR_NAME_MAX];
777 int error;
778
779 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
780 NULL);
781 if (error)
782 return (error);
783
784 error = namei_simple_user(SCARG(uap, path),
785 NSM_NOFOLLOW_NOEMULROOT, &vp);
786 if (error)
787 return (error);
788
789 /* XXX flags */
790
791 error = extattr_set_vp(vp, EXTATTR_NAMESPACE_USER,
792 attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
793
794 vrele(vp);
795 return (error);
796 }
797
798 int
799 sys_fsetxattr(struct lwp *l, const struct sys_fsetxattr_args *uap, register_t *retval)
800 {
801 /* {
802 syscallarg(int) fd;
803 syscallarg(const char *) name;
804 syscallarg(void *) value;
805 syscallarg(size_t) size;
806 syscallarg(int) flags;
807 } */
808 struct file *fp;
809 struct vnode *vp;
810 char attrname[XATTR_NAME_MAX];
811 int error;
812
813 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
814 NULL);
815 if (error)
816 return (error);
817
818 error = fd_getvnode(SCARG(uap, fd), &fp);
819 if (error)
820 return (error);
821 vp = (struct vnode *) fp->f_data;
822
823 /* XXX flags */
824
825 error = extattr_set_vp(vp, EXTATTR_NAMESPACE_USER,
826 attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
827
828 fd_putfile(SCARG(uap, fd));
829 return (error);
830 }
831
832 int
833 sys_getxattr(struct lwp *l, const struct sys_getxattr_args *uap, register_t *retval)
834 {
835 /* {
836 syscallarg(const char *) path;
837 syscallarg(const char *) name;
838 syscallarg(void *) value;
839 syscallarg(size_t) size;
840 } */
841 struct vnode *vp;
842 char attrname[XATTR_NAME_MAX];
843 int error;
844
845 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
846 NULL);
847 if (error)
848 return (error);
849
850 error = namei_simple_user(SCARG(uap, path),
851 NSM_FOLLOW_NOEMULROOT, &vp);
852 if (error)
853 return (error);
854
855 error = extattr_get_vp(vp, EXTATTR_NAMESPACE_USER,
856 attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
857
858 vrele(vp);
859 return (error);
860 }
861
862 int
863 sys_lgetxattr(struct lwp *l, const struct sys_lgetxattr_args *uap, register_t *retval)
864 {
865 /* {
866 syscallarg(const char *) path;
867 syscallarg(const char *) name;
868 syscallarg(void *) value;
869 syscallarg(size_t) size;
870 } */
871 struct vnode *vp;
872 char attrname[XATTR_NAME_MAX];
873 int error;
874
875 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
876 NULL);
877 if (error)
878 return (error);
879
880 error = namei_simple_user(SCARG(uap, path),
881 NSM_NOFOLLOW_NOEMULROOT, &vp);
882 if (error)
883 return (error);
884
885 error = extattr_get_vp(vp, EXTATTR_NAMESPACE_USER,
886 attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
887
888 vrele(vp);
889 return (error);
890 }
891
892 int
893 sys_fgetxattr(struct lwp *l, const struct sys_fgetxattr_args *uap, register_t *retval)
894 {
895 /* {
896 syscallarg(int) fd;
897 syscallarg(const char *) name;
898 syscallarg(void *) value;
899 syscallarg(size_t) size;
900 } */
901 struct file *fp;
902 struct vnode *vp;
903 char attrname[XATTR_NAME_MAX];
904 int error;
905
906 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
907 NULL);
908 if (error)
909 return (error);
910
911 error = fd_getvnode(SCARG(uap, fd), &fp);
912 if (error)
913 return (error);
914 vp = (struct vnode *) fp->f_data;
915
916 error = extattr_get_vp(vp, EXTATTR_NAMESPACE_USER,
917 attrname, SCARG(uap, value), SCARG(uap, size), l, retval);
918
919 fd_putfile(SCARG(uap, fd));
920 return (error);
921 }
922
923 int
924 sys_listxattr(struct lwp *l, const struct sys_listxattr_args *uap, register_t *retval)
925 {
926 /* {
927 syscallarg(const char *) path;
928 syscallarg(char *) list;
929 syscallarg(size_t) size;
930 } */
931 struct vnode *vp;
932 int error;
933
934 error = namei_simple_user(SCARG(uap, path),
935 NSM_FOLLOW_NOEMULROOT, &vp);
936 if (error)
937 return (error);
938
939 error = extattr_list_vp(vp, EXTATTR_NAMESPACE_USER,
940 SCARG(uap, list), SCARG(uap, size), l, retval);
941
942 vrele(vp);
943 return (error);
944 }
945
946 int
947 sys_llistxattr(struct lwp *l, const struct sys_llistxattr_args *uap, register_t *retval)
948 {
949 /* {
950 syscallarg(const char *) path;
951 syscallarg(char *) list;
952 syscallarg(size_t) size;
953 } */
954 struct vnode *vp;
955 int error;
956
957 error = namei_simple_user(SCARG(uap, path),
958 NSM_NOFOLLOW_NOEMULROOT, &vp);
959 if (error)
960 return (error);
961
962 error = extattr_list_vp(vp, EXTATTR_NAMESPACE_USER,
963 SCARG(uap, list), SCARG(uap, size), l, retval);
964
965 vrele(vp);
966 return (error);
967 }
968
969 int
970 sys_flistxattr(struct lwp *l, const struct sys_flistxattr_args *uap, register_t *retval)
971 {
972 /* {
973 syscallarg(int) fd;
974 syscallarg(char *) list;
975 syscallarg(size_t) size;
976 } */
977 struct file *fp;
978 struct vnode *vp;
979 int error;
980
981 error = fd_getvnode(SCARG(uap, fd), &fp);
982 if (error)
983 return (error);
984 vp = (struct vnode *) fp->f_data;
985
986 error = extattr_list_vp(vp, EXTATTR_NAMESPACE_USER,
987 SCARG(uap, list), SCARG(uap, size), l, retval);
988
989 fd_putfile(SCARG(uap, fd));
990 return (error);
991 }
992
993 int
994 sys_removexattr(struct lwp *l, const struct sys_removexattr_args *uap, register_t *retval)
995 {
996 /* {
997 syscallarg(const char *) path;
998 syscallarg(const char *) name;
999 } */
1000 struct vnode *vp;
1001 char attrname[XATTR_NAME_MAX];
1002 int error;
1003
1004 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
1005 NULL);
1006 if (error)
1007 return (error);
1008
1009 error = namei_simple_user(SCARG(uap, path),
1010 NSM_FOLLOW_NOEMULROOT, &vp);
1011 if (error)
1012 return (error);
1013
1014 error = extattr_delete_vp(vp, EXTATTR_NAMESPACE_USER,
1015 attrname, l);
1016
1017 vrele(vp);
1018 return (error);
1019 }
1020
1021 int
1022 sys_lremovexattr(struct lwp *l, const struct sys_lremovexattr_args *uap, register_t *retval)
1023 {
1024 /* {
1025 syscallarg(const char *) path;
1026 syscallarg(const char *) name;
1027 } */
1028 struct vnode *vp;
1029 char attrname[XATTR_NAME_MAX];
1030 int error;
1031
1032 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
1033 NULL);
1034 if (error)
1035 return (error);
1036
1037 error = namei_simple_user(SCARG(uap, path),
1038 NSM_NOFOLLOW_NOEMULROOT, &vp);
1039 if (error)
1040 return (error);
1041
1042 error = extattr_delete_vp(vp, EXTATTR_NAMESPACE_USER,
1043 attrname, l);
1044
1045 vrele(vp);
1046 return (error);
1047 }
1048
1049 int
1050 sys_fremovexattr(struct lwp *l, const struct sys_fremovexattr_args *uap, register_t *retval)
1051 {
1052 /* {
1053 syscallarg(int) fd;
1054 syscallarg(const char *) name;
1055 } */
1056 struct file *fp;
1057 struct vnode *vp;
1058 char attrname[XATTR_NAME_MAX];
1059 int error;
1060
1061 error = copyinstr(SCARG(uap, name), attrname, sizeof(attrname),
1062 NULL);
1063 if (error)
1064 return (error);
1065
1066 error = fd_getvnode(SCARG(uap, fd), &fp);
1067 if (error)
1068 return (error);
1069 vp = (struct vnode *) fp->f_data;
1070
1071 error = extattr_delete_vp(vp, EXTATTR_NAMESPACE_USER,
1072 attrname, l);
1073
1074 fd_putfile(SCARG(uap, fd));
1075 return (error);
1076 }
1077