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