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