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