Home | History | Annotate | Line # | Download | only in kern
vfs_xattr.c revision 1.20.4.3
      1 /*	$NetBSD: vfs_xattr.c,v 1.20.4.3 2011/03/05 20:55:27 rmind 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.20.4.3 2011/03/05 20:55:27 rmind 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