vfs_extattr.c (762e6b856c64ee48f286a7f0b45d0067e556b252) vfs_extattr.c (91f37dcba1648b1f24e2913c3ab78fc4eae35991)
1/*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.

--- 46 unchanged lines hidden (view full) ---

55#include <sys/fcntl.h>
56#include <sys/file.h>
57#include <sys/linker.h>
58#include <sys/stat.h>
59#include <sys/unistd.h>
60#include <sys/vnode.h>
61#include <sys/proc.h>
62#include <sys/dirent.h>
1/*
2 * Copyright (c) 1989, 1993
3 * The Regents of the University of California. All rights reserved.
4 * (c) UNIX System Laboratories, Inc.
5 * All or some portions of this file are derived from material licensed
6 * to the University of California by American Telephone and Telegraph
7 * Co. or Unix System Laboratories, Inc. and are reproduced herein with
8 * the permission of UNIX System Laboratories, Inc.

--- 46 unchanged lines hidden (view full) ---

55#include <sys/fcntl.h>
56#include <sys/file.h>
57#include <sys/linker.h>
58#include <sys/stat.h>
59#include <sys/unistd.h>
60#include <sys/vnode.h>
61#include <sys/proc.h>
62#include <sys/dirent.h>
63#include <sys/extattr.h>
63
64
65#include <machine/limits.h>
64#include <miscfs/union/union.h>
66#include <miscfs/union/union.h>
65
67#include <sys/sysctl.h>
66#include <vm/vm.h>
67#include <vm/vm_object.h>
68#include <vm/vm_zone.h>
68#include <vm/vm.h>
69#include <vm/vm_object.h>
70#include <vm/vm_zone.h>
69#include <sys/sysctl.h>
70
71static int change_dir __P((struct nameidata *ndp, struct proc *p));
72static void checkdirs __P((struct vnode *olddp));
73static int chroot_refuse_vdir_fds __P((struct filedesc *fdp));
74static int getutimes __P((const struct timeval *, struct timespec *));
75static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t));
76static int setfmode __P((struct proc *, struct vnode *, int));
77static int setfflags __P((struct proc *, struct vnode *, int));

--- 3279 unchanged lines hidden (view full) ---

3357 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
3358 if (suser_xxx(p->p_ucred, 0, 0)) {
3359 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
3360 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
3361 sp = &sb;
3362 }
3363 return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
3364}
71
72static int change_dir __P((struct nameidata *ndp, struct proc *p));
73static void checkdirs __P((struct vnode *olddp));
74static int chroot_refuse_vdir_fds __P((struct filedesc *fdp));
75static int getutimes __P((const struct timeval *, struct timespec *));
76static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t));
77static int setfmode __P((struct proc *, struct vnode *, int));
78static int setfflags __P((struct proc *, struct vnode *, int));

--- 3279 unchanged lines hidden (view full) ---

3358 sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
3359 if (suser_xxx(p->p_ucred, 0, 0)) {
3360 bcopy((caddr_t)sp, (caddr_t)&sb, sizeof(sb));
3361 sb.f_fsid.val[0] = sb.f_fsid.val[1] = 0;
3362 sp = &sb;
3363 }
3364 return (copyout(sp, SCARG(uap, buf), sizeof(*sp)));
3365}
3366
3367/*
3368 * Syscall to push extended attribute configuration information into the
3369 * VFS. Accepts a path, which it converts to a mountpoint, as well as
3370 * a command (int cmd), and attribute name and misc data. For now, the
3371 * attribute name is left in userspace for consumption by the VFS_op.
3372 * It will probably be changed to be copied into sysspace by the
3373 * syscall in the future, once issues with various consumers of the
3374 * attribute code have raised their hands.
3375 *
3376 * Currently this is used only by UFS Extended Attributes.
3377 */
3378int
3379extattrctl(p, uap)
3380 struct proc *p;
3381 struct extattrctl_args *uap;
3382{
3383 struct nameidata nd;
3384 struct mount *mp;
3385 int error;
3386
3387 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
3388 if ((error = namei(&nd)) != 0)
3389 return (error);
3390 mp = nd.ni_vp->v_mount;
3391 NDFREE(&nd, 0);
3392 return (VFS_EXTATTRCTL(mp, SCARG(uap, cmd), SCARG(uap, attrname),
3393 SCARG(uap, arg), p));
3394}
3395
3396/*
3397 * Syscall to set a named extended attribute on a file or directory.
3398 * Accepts attribute name, and a uio structure pointing to the data to set.
3399 * The uio is consumed in the style of writev(). The real work happens
3400 * in VOP_SETEXTATTR().
3401 */
3402int
3403extattr_set_file(p, uap)
3404 struct proc *p;
3405 struct extattr_set_file_args *uap;
3406{
3407 struct nameidata nd;
3408 struct uio auio;
3409 struct iovec *iov, *needfree = NULL, aiov[UIO_SMALLIOV];
3410 char attrname[EXTATTR_MAXNAMELEN];
3411 u_int iovlen, cnt;
3412 int error, i;
3413
3414 error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
3415 if (error)
3416 return (error);
3417 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, SCARG(uap, path),
3418 p);
3419 if ((error = namei(&nd)) != 0)
3420 return(error);
3421 iovlen = uap->iovcnt * sizeof(struct iovec);
3422 if (uap->iovcnt > UIO_SMALLIOV) {
3423 if (uap->iovcnt > UIO_MAXIOV) {
3424 error = EINVAL;
3425 goto done;
3426 }
3427 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
3428 needfree = iov;
3429 } else
3430 iov = aiov;
3431 auio.uio_iov = iov;
3432 auio.uio_iovcnt = uap->iovcnt;
3433 auio.uio_rw = UIO_WRITE;
3434 auio.uio_segflg = UIO_USERSPACE;
3435 auio.uio_procp = p;
3436 auio.uio_offset = 0;
3437 if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
3438 goto done;
3439 auio.uio_resid = 0;
3440 for (i = 0; i < uap->iovcnt; i++) {
3441 if (iov->iov_len > INT_MAX - auio.uio_resid) {
3442 error = EINVAL;
3443 goto done;
3444 }
3445 auio.uio_resid += iov->iov_len;
3446 iov++;
3447 }
3448 cnt = auio.uio_resid;
3449 error = VOP_SETEXTATTR(nd.ni_vp, attrname, &auio, p->p_cred->pc_ucred,
3450 p);
3451 if (auio.uio_resid != cnt && (error == ERESTART ||
3452 error == EINTR || error == EWOULDBLOCK))
3453 error = 0;
3454 cnt -= auio.uio_resid;
3455 p->p_retval[0] = cnt;
3456done:
3457 if (needfree)
3458 FREE(needfree, M_IOV);
3459 NDFREE(&nd, 0);
3460 return (error);
3461}
3462
3463/*
3464 * Syscall to get a named extended attribute on a file or directory.
3465 * Accepts attribute name, and a uio structure pointing to a buffer for the
3466 * data. The uio is consumed in the style of readv(). The real work
3467 * happens in VOP_GETEXTATTR();
3468 */
3469int
3470extattr_get_file(p, uap)
3471 struct proc *p;
3472 struct extattr_get_file_args *uap;
3473{
3474 struct nameidata nd;
3475 struct uio auio;
3476 struct iovec *iov, *needfree, aiov[UIO_SMALLIOV];
3477 char attrname[EXTATTR_MAXNAMELEN];
3478 u_int iovlen, cnt;
3479 int error, i;
3480
3481 error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
3482 if (error)
3483 return (error);
3484 NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, SCARG(uap, path), p);
3485 if ((error = namei(&nd)) != 0)
3486 return (error);
3487 iovlen = uap->iovcnt * sizeof (struct iovec);
3488 if (uap->iovcnt > UIO_SMALLIOV) {
3489 if (uap->iovcnt > UIO_MAXIOV) {
3490 NDFREE(&nd, 0);
3491 return (EINVAL);
3492 }
3493 MALLOC(iov, struct iovec *, iovlen, M_IOV, M_WAITOK);
3494 needfree = iov;
3495 } else {
3496 iov = aiov;
3497 needfree = NULL;
3498 }
3499 auio.uio_iov = iov;
3500 auio.uio_iovcnt = uap->iovcnt;
3501 auio.uio_rw = UIO_READ;
3502 auio.uio_segflg = UIO_USERSPACE;
3503 auio.uio_procp = p;
3504 auio.uio_offset = 0;
3505 if ((error = copyin((caddr_t)uap->iovp, (caddr_t)iov, iovlen)))
3506 goto done;
3507 auio.uio_resid = 0;
3508 for (i = 0; i < uap->iovcnt; i++) {
3509 if (iov->iov_len > INT_MAX - auio.uio_resid) {
3510 error = EINVAL;
3511 goto done;
3512 }
3513 auio.uio_resid += iov->iov_len;
3514 iov++;
3515 }
3516 cnt = auio.uio_resid;
3517 error = VOP_GETEXTATTR(nd.ni_vp, attrname, &auio, p->p_cred->pc_ucred,
3518 p);
3519 if (auio.uio_resid != cnt && (error == ERESTART ||
3520 error == EINTR || error == EWOULDBLOCK))
3521 error = 0;
3522 cnt -= auio.uio_resid;
3523 p->p_retval[0] = cnt;
3524done:
3525 if (needfree)
3526 FREE(needfree, M_IOV);
3527 NDFREE(&nd, 0);
3528 return(error);
3529}
3530
3531/*
3532 * Syscall to delete a named extended attribute from a file or directory.
3533 * Accepts attribute name. The real work happens in VOP_SETEXTATTR().
3534 */
3535int
3536extattr_delete_file(p, uap)
3537 struct proc *p;
3538 struct extattr_delete_file_args *uap;
3539{
3540 struct nameidata nd;
3541 char attrname[EXTATTR_MAXNAMELEN];
3542 int error;
3543
3544 error = copyin(SCARG(uap, attrname), attrname, EXTATTR_MAXNAMELEN);
3545 if (error)
3546 return(error);
3547 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, SCARG(uap, path),
3548 p);
3549 if ((error = namei(&nd)) != 0)
3550 return(error);
3551 error = VOP_SETEXTATTR(nd.ni_vp, attrname, NULL, p->p_cred->pc_ucred,
3552 p);
3553 NDFREE(&nd, 0);
3554 return(error);
3555}