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