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