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