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