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