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