int osi_UFSTruncate(struct osi_file *afile, afs_int32 asize) { afs_ucred_t *oldCred; struct vattr tvattr; afs_int32 code; struct osi_stat tstat; AFS_STATCNT(osi_Truncate); /* This routine only shrinks files, and most systems * have very slow truncates, even when the file is already * small enough. Check now and save some time. */ code = afs_osi_Stat(afile, &tstat); if (code || tstat.size <= asize) return code; ObtainWriteLock(&afs_xosi, 321); tvattr.va_mask = AT_SIZE; tvattr.va_size = asize; /* * The only time a flag is used (ATTR_UTIME) is when we're changing the time */ AFS_GUNLOCK(); #ifdef AFS_SUN510_ENV code = VOP_SETATTR(afile->vnode, &tvattr, 0, afs_osi_credp, NULL); #else code = VOP_SETATTR(afile->vnode, &tvattr, 0, afs_osi_credp); #endif AFS_GLOCK(); ReleaseWriteLock(&afs_xosi); return code; }
int osi_UFSTruncate(register struct osi_file *afile, afs_int32 asize) { struct vattr tvattr; struct vnode *vp; register afs_int32 code, glocked; AFS_STATCNT(osi_Truncate); ObtainWriteLock(&afs_xosi, 321); vp = afile->vnode; /* * This routine only shrinks files, and most systems * have very slow truncates, even when the file is already * small enough. Check now and save some time. */ glocked = ISAFS_GLOCK(); if (glocked) AFS_GUNLOCK(); #if defined(AFS_FBSD80_ENV) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp); #elif defined(AFS_FBSD50_ENV) vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curthread); code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curthread); #else vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, curproc); code = VOP_GETATTR(afile->vnode, &tvattr, afs_osi_credp, curproc); #endif if (code != 0 || tvattr.va_size <= asize) goto out; VATTR_NULL(&tvattr); tvattr.va_size = asize; #if defined(AFS_FBSD80_ENV) code = VOP_SETATTR(vp, &tvattr, afs_osi_credp); #elif defined(AFS_FBSD50_ENV) code = VOP_SETATTR(vp, &tvattr, afs_osi_credp, curthread); #else code = VOP_SETATTR(vp, &tvattr, afs_osi_credp, curproc); #endif out: #if defined(AFS_FBSD80_ENV) VOP_UNLOCK(vp, 0); #elif defined(AFS_FBSD50_ENV) VOP_UNLOCK(vp, LK_EXCLUSIVE, curthread); #else VOP_UNLOCK(vp, LK_EXCLUSIVE, curproc); #endif if (glocked) AFS_GLOCK(); ReleaseWriteLock(&afs_xosi); return code; }
/* * smb_vop_setattr() * * smb_fsop_setattr()/smb_vop_setattr() should always be used instead of * VOP_SETATTR() when calling from the CIFS service, due to special processing * for streams files. * * Streams have a size but otherwise do not have separate attributes from * the (unnamed stream) file, i.e., the security and ownership of the file * applies to the stream. In contrast, extended attribute files, which are * used to implement streams, are independent objects with their own * attributes. * * For compatibility with streams, we set the size on the extended attribute * file and apply other attributes to the (unnamed stream) file. The one * exception is that the UID and GID can be set on the stream by passing a * NULL unnamed_vp, which allows callers to synchronize stream ownership * with the (unnamed stream) file. */ int smb_vop_setattr(vnode_t *vp, vnode_t *unnamed_vp, smb_attr_t *attr, int flags, cred_t *cr) { int error = 0; int at_size = 0; vnode_t *use_vp; xvattr_t xvattr; vattr_t *vap; if (attr->sa_mask & SMB_AT_DOSATTR) { attr->sa_dosattr &= (FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM); } if (unnamed_vp) { use_vp = unnamed_vp; if (attr->sa_mask & SMB_AT_SIZE) { at_size = 1; attr->sa_mask &= ~SMB_AT_SIZE; } } else { use_vp = vp; } /* * The caller should not be setting sa_vattr.va_mask, * but rather sa_mask. */ attr->sa_vattr.va_mask = 0; if (vfs_has_feature(use_vp->v_vfsp, VFSFT_XVATTR)) { smb_vop_setup_xvattr(attr, &xvattr); vap = &xvattr.xva_vattr; } else { smb_sa_to_va_mask(attr->sa_mask, &attr->sa_vattr.va_mask); vap = &attr->sa_vattr; } if ((error = VOP_SETATTR(use_vp, vap, flags, cr, &smb_ct)) != 0) return (error); if (at_size) { attr->sa_vattr.va_mask = AT_SIZE; error = VOP_SETATTR(vp, &attr->sa_vattr, flags, kcred, &smb_ct); } return (error); }
STATIC int linvfs_file_mmap( struct file *filp, struct vm_area_struct *vma) { struct inode *ip = filp->f_dentry->d_inode; vnode_t *vp = LINVFS_GET_VP(ip); vattr_t va = { .va_mask = XFS_AT_UPDATIME }; int error; if (vp->v_vfsp->vfs_flag & VFS_DMI) { xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); error = -XFS_SEND_MMAP(mp, vma, 0); if (error) return error; } vma->vm_ops = &linvfs_file_vm_ops; VOP_SETATTR(vp, &va, XFS_AT_UPDATIME, NULL, error); if (!error) vn_revalidate(vp); /* update Linux inode flags */ return 0; }
int osi_UFSTruncate(struct osi_file *afile, afs_int32 asize) { struct vattr tvattr; afs_int32 code; struct osi_stat tstat; AFS_STATCNT(osi_Truncate); /* * This routine only shrinks files, and most systems * have very slow truncates, even when the file is already * small enough. Check now and save some time. */ code = afs_osi_Stat(afile, &tstat); if (code || tstat.size <= asize) return code; ObtainWriteLock(&afs_xosi, 321); VATTR_NULL(&tvattr); tvattr.va_size = asize; AFS_GUNLOCK(); VOP_LOCK(afile->vnode, LK_EXCLUSIVE | LK_RETRY, curproc); code = VOP_SETATTR(afile->vnode, &tvattr, afs_osi_credp, curproc); VOP_UNLOCK(afile->vnode, 0, curproc); AFS_GLOCK(); if (code == 0) afile->size = asize; ReleaseWriteLock(&afs_xosi); return code; }
int osi_UFSTruncate(struct osi_file *afile, afs_int32 asize) { afs_ucred_t *oldCred; struct vattr tvattr; afs_int32 code; struct osi_stat tstat; AFS_STATCNT(osi_Truncate); /* This routine only shrinks files, and most systems * have very slow truncates, even when the file is already * small enough. Check now and save some time. */ code = afs_osi_Stat(afile, &tstat); if (code || tstat.size <= asize) return code; ObtainWriteLock(&afs_xosi, 321); VATTR_NULL(&tvattr); /* note that this credential swapping stuff is only necessary because * of ufs's references directly to u.u_cred instead of to * credentials parameter. Probably should fix ufs some day. */ oldCred = p_cred(u.u_procp); set_p_cred(u.u_procp, &afs_osi_cred); tvattr.va_size = asize; AFS_GUNLOCK(); code = VOP_SETATTR(afile->vnode, &tvattr, &afs_osi_cred, 0); AFS_GLOCK(); set_p_cred(u.u_procp, oldCred); /* restore */ ReleaseWriteLock(&afs_xosi); return code; }
int osi_UFSTruncate(struct osi_file *afile, afs_int32 asize) { afs_ucred_t *oldCred; struct vattr tvattr; afs_int32 code; struct osi_stat tstat; AFS_STATCNT(osi_Truncate); /* This routine only shrinks files, and most systems * have very slow truncates, even when the file is already * small enough. Check now and save some time. */ code = afs_osi_Stat(afile, &tstat); if (code || tstat.size <= asize) return code; ObtainWriteLock(&afs_xosi, 321); AFS_GUNLOCK(); #ifdef AFS_DARWIN80_ENV VATTR_INIT(&tvattr); VATTR_SET(&tvattr, va_size, asize); code = vnode_setattr(afile->vnode, &tvattr, afs_osi_ctxtp); #else VATTR_NULL(&tvattr); tvattr.va_size = asize; code = VOP_SETATTR(afile->vnode, &tvattr, &afs_osi_cred, current_proc()); #endif AFS_GLOCK(); ReleaseWriteLock(&afs_xosi); return code; }
/*ARGSUSED4*/ static int auto_setattr( vnode_t *vp, struct vattr *vap, int flags, cred_t *cred, caller_context_t *ct) { vnode_t *newvp; int error; AUTOFS_DPRINT((4, "auto_setattr vp %p\n", (void *)vp)); if (error = auto_trigger_mount(vp, cred, &newvp)) goto done; if (newvp != NULL) { /* * Node is mounted on. */ if (vn_is_readonly(newvp)) error = EROFS; else error = VOP_SETATTR(newvp, vap, flags, cred, ct); VN_RELE(newvp); } else error = ENOSYS; done: AUTOFS_DPRINT((5, "auto_setattr: error=%d\n", error)); return (error); }
/* * Drops reference to the log file. */ void cachefs_dlog_teardown(fscache_t *fscp) { vattr_t va; /*LINTED: set but not used */ int error; mutex_enter(&fscp->fs_dlock); /* clean up the log file */ if (fscp->fs_dlogfile) { VN_RELE(fscp->fs_dlogfile); fscp->fs_dlogfile = NULL; } /* clean up the map file */ if (fscp->fs_dmapfile) { /* set the map file to the actual size needed */ va.va_mask = AT_SIZE; va.va_size = fscp->fs_dmapoff; error = VOP_SETATTR(fscp->fs_dmapfile, &va, 0, kcred, NULL); #ifdef CFSDEBUG if (error) { cmn_err(CE_WARN, "cachefs: map setattr failed %d", error); } #endif VN_RELE(fscp->fs_dmapfile); fscp->fs_dmapfile = NULL; } mutex_exit(&fscp->fs_dlock); }
int sc_chmod(thread_t *t, syscall_result_t *r, chmod_args_t *args) { int res=0; proc_t *p = t->thr_proc; vnode_t *node; char pname[PATH_MAX]; if((res = copyinstr(pname, args->fname, PATH_MAX))) return res; res = vfs_lookup(p->p_curdir, &node, pname, t, LKP_NORMAL); if(res) return res; vattr_t va; va.va_mask=VATTR_ALL; if((res = VOP_GETATTR(node, &va))) goto err; res = -EPERM; if(p->p_cred->p_euid != 0 && p->p_cred->p_euid != va.va_uid) goto err; mode_t mode = args->mode & 07777; if(ISSET(mode, S_ISGID) && p->p_cred->p_euid!=0 && va.va_gid!=p->p_cred->p_egid) UNSET(mode, S_ISGID); //mamy prawo kasować bit suid/sgid? va.va_mask = VATTR_MODE; va.va_mode = mode; if((res = VOP_SETATTR(node, &va))) goto err; vrele(node); return 0; err: vrele(node); return res; }
static int zfs_replay_setattr(zfsvfs_t *zfsvfs, lr_setattr_t *lr, boolean_t byteswap) { znode_t *zp; xvattr_t xva; vattr_t *vap = &xva.xva_vattr; int error; void *start; xva_init(&xva); if (byteswap) { byteswap_uint64_array(lr, sizeof (*lr)); if ((lr->lr_mask & AT_XVATTR) && zfsvfs->z_version >= ZPL_VERSION_INITIAL) zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); } if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) { /* * As we can log setattrs out of order, it's possible the * file has been removed. In this case just drop the setattr * and return success. */ if (error == ENOENT) error = 0; return (error); } zfs_init_vattr(vap, lr->lr_mask, lr->lr_mode, lr->lr_uid, lr->lr_gid, 0, lr->lr_foid); vap->va_size = lr->lr_size; ZFS_TIME_DECODE(&vap->va_atime, lr->lr_atime); ZFS_TIME_DECODE(&vap->va_mtime, lr->lr_mtime); /* * Fill in xvattr_t portions if necessary. */ start = (lr_setattr_t *)(lr + 1); if (vap->va_mask & AT_XVATTR) { zfs_replay_xvattr((lr_attr_t *)start, &xva); start = (caddr_t)start + ZIL_XVAT_SIZE(((lr_attr_t *)start)->lr_attr_masksize); } else xva.xva_vattr.va_mask &= ~AT_XVATTR; zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, lr->lr_uid, lr->lr_gid); error = VOP_SETATTR(ZTOV(zp), vap, 0, kcred, NULL); zfs_fuid_info_free(zfsvfs->z_fuid_replay); zfsvfs->z_fuid_replay = NULL; VN_RELE(ZTOV(zp)); return (error); }
STATIC int linvfs_setattr( struct dentry *dentry, struct iattr *attr) { struct inode *inode = dentry->d_inode; unsigned int ia_valid = attr->ia_valid; vnode_t *vp = LINVFS_GET_VP(inode); vattr_t vattr; int flags = 0; int error; memset(&vattr, 0, sizeof(vattr_t)); if (ia_valid & ATTR_UID) { vattr.va_mask |= XFS_AT_UID; vattr.va_uid = attr->ia_uid; } if (ia_valid & ATTR_GID) { vattr.va_mask |= XFS_AT_GID; vattr.va_gid = attr->ia_gid; } if (ia_valid & ATTR_SIZE) { vattr.va_mask |= XFS_AT_SIZE; vattr.va_size = attr->ia_size; } if (ia_valid & ATTR_ATIME) { vattr.va_mask |= XFS_AT_ATIME; vattr.va_atime = attr->ia_atime; inode->i_atime = attr->ia_atime; } if (ia_valid & ATTR_MTIME) { vattr.va_mask |= XFS_AT_MTIME; vattr.va_mtime = attr->ia_mtime; } if (ia_valid & ATTR_CTIME) { vattr.va_mask |= XFS_AT_CTIME; vattr.va_ctime = attr->ia_ctime; } if (ia_valid & ATTR_MODE) { vattr.va_mask |= XFS_AT_MODE; vattr.va_mode = attr->ia_mode; if (!in_group_p(inode->i_gid) && !capable(CAP_FSETID)) inode->i_mode &= ~S_ISGID; } if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) flags |= ATTR_UTIME; #ifdef ATTR_NO_BLOCK if ((ia_valid & ATTR_NO_BLOCK)) flags |= ATTR_NONBLOCK; #endif VOP_SETATTR(vp, &vattr, flags, NULL, error); if (error) return -error; vn_revalidate(vp); return error; }
/* * Set up the correct mode on the file based on the supplied ACL. This * makes sure that the mode on the file reflects the state of the * u::,g::[m::], and o:: entries in the ACL. Since the mode is where * the ACL is going to get the permissions for these entries, we must * synchronize the mode whenever we set the ACL on a file. */ STATIC int xfs_acl_setmode( vnode_t *vp, xfs_acl_t *acl, int *basicperms) { vattr_t va; xfs_acl_entry_t *ap; xfs_acl_entry_t *gap = NULL; int i, error, nomask = 1; *basicperms = 1; if (acl->acl_cnt == XFS_ACL_NOT_PRESENT) return 0; /* * Copy the u::, g::, o::, and m:: bits from the ACL into the * mode. The m:: bits take precedence over the g:: bits. */ va.va_mask = XFS_AT_MODE; VOP_GETATTR(vp, &va, 0, sys_cred, error); if (error) return error; va.va_mask = XFS_AT_MODE; va.va_mode &= ~(S_IRWXU|S_IRWXG|S_IRWXO); ap = acl->acl_entry; for (i = 0; i < acl->acl_cnt; ++i) { switch (ap->ae_tag) { case ACL_USER_OBJ: va.va_mode |= ap->ae_perm << 6; break; case ACL_GROUP_OBJ: gap = ap; break; case ACL_MASK: /* more than just standard modes */ nomask = 0; va.va_mode |= ap->ae_perm << 3; *basicperms = 0; break; case ACL_OTHER: va.va_mode |= ap->ae_perm; break; default: /* more than just standard modes */ *basicperms = 0; break; } ap++; } /* Set the group bits from ACL_GROUP_OBJ if there's no ACL_MASK */ if (gap && nomask) va.va_mode |= gap->ae_perm << 3; VOP_SETATTR(vp, &va, 0, sys_cred, error); return error; }
static int zfs_replay_setattr(void *arg1, void *arg2, boolean_t byteswap) { zfsvfs_t *zfsvfs = arg1; lr_setattr_t *lr = arg2; znode_t *zp; xvattr_t xva; vattr_t *vap = &xva.xva_vattr; vnode_t *vp; int error; void *start; xva_init(&xva); if (byteswap) { byteswap_uint64_array(lr, sizeof (*lr)); if ((lr->lr_mask & AT_XVATTR) && zfsvfs->z_version >= ZPL_VERSION_INITIAL) zfs_replay_swap_attrs((lr_attr_t *)(lr + 1)); } if ((error = zfs_zget(zfsvfs, lr->lr_foid, &zp)) != 0) return (error); zfs_init_vattr(vap, lr->lr_mask, lr->lr_mode, lr->lr_uid, lr->lr_gid, 0, lr->lr_foid); vap->va_size = lr->lr_size; ZFS_TIME_DECODE(&vap->va_atime, lr->lr_atime); ZFS_TIME_DECODE(&vap->va_mtime, lr->lr_mtime); /* * Fill in xvattr_t portions if necessary. */ start = (lr_setattr_t *)(lr + 1); if (vap->va_mask & AT_XVATTR) { zfs_replay_xvattr((lr_attr_t *)start, &xva); start = (caddr_t)start + ZIL_XVAT_SIZE(((lr_attr_t *)start)->lr_attr_masksize); } else xva.xva_vattr.va_mask &= ~AT_XVATTR; zfsvfs->z_fuid_replay = zfs_replay_fuid_domain(start, &start, lr->lr_uid, lr->lr_gid); vp = ZTOV(zp); vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); error = VOP_SETATTR(vp, vap, kcred); VOP_UNLOCK(vp, 0); zfs_fuid_info_free(zfsvfs->z_fuid_replay); zfsvfs->z_fuid_replay = NULL; VN_RELE(vp); return (error); }
/* * exacct_vn_write() is a vn_rdwr wrapper that protects us from corrupting the * accounting file in case of an I/O or filesystem error. acctctl() prevents * the two accounting vnodes from being equal, and the appropriate ac_lock is * held across the call, so we're single threaded through this code for each * file. */ static int exacct_vn_write(ac_info_t *info, void *buf, ssize_t bufsize) { int error = 0; ssize_t resid; struct vattr va; if (info == NULL) return (0); mutex_enter(&info->ac_lock); /* * Don't do anything unless accounting file is set. */ if (info->ac_vnode == NULL) { mutex_exit(&info->ac_lock); return (0); } /* * Save the size. If vn_rdwr fails, reset the size to avoid corrupting * the present accounting file. */ va.va_mask = AT_SIZE; error = VOP_GETATTR(info->ac_vnode, &va, 0, kcred, NULL); if (error == 0) { error = vn_rdwr(UIO_WRITE, info->ac_vnode, (caddr_t)buf, bufsize, 0LL, UIO_SYSSPACE, FAPPEND, (rlim64_t)MAXOFFSET_T, kcred, &resid); if (error) { (void) VOP_SETATTR(info->ac_vnode, &va, 0, kcred, NULL); } else if (resid != 0) { (void) VOP_SETATTR(info->ac_vnode, &va, 0, kcred, NULL); error = ENOSPC; } } mutex_exit(&info->ac_lock); return (error); }
int RUMP_VOP_SETATTR(struct vnode *vp, struct vattr *vap, struct kauth_cred *cred) { int error; rump_schedule(); error = VOP_SETATTR(vp, vap, cred); rump_unschedule(); return error; }
static int fdesc_setattr(struct vop_setattr_args *ap) { struct vattr *vap = ap->a_vap; struct vnode *vp; struct mount *mp; struct file *fp; struct thread *td = curthread; cap_rights_t rights; unsigned fd; int error; /* * Can't mess with the root vnode */ if (VTOFDESC(ap->a_vp)->fd_type == Froot) return (EACCES); fd = VTOFDESC(ap->a_vp)->fd_fd; /* * Allow setattr where there is an underlying vnode. */ error = getvnode(td, fd, cap_rights_init(&rights, CAP_EXTATTR_SET), &fp); if (error) { /* * getvnode() returns EINVAL if the file descriptor is not * backed by a vnode. Silently drop all changes except * chflags(2) in this case. */ if (error == EINVAL) { if (vap->va_flags != VNOVAL) error = EOPNOTSUPP; else error = 0; } return (error); } vp = fp->f_vnode; if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) == 0) { vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); error = VOP_SETATTR(vp, ap->a_vap, ap->a_cred); VOP_UNLOCK(vp, 0); vn_finished_write(mp); } fdrop(fp, td); return (error); }
int spec_setattr(void *v) { struct vop_getattr_args *ap = v; struct vnode *vp = ap->a_vp; int error; if (!(vp->v_flag & VCLONE)) return (EBADF); vn_lock(vp->v_specparent, LK_EXCLUSIVE|LK_RETRY, curproc); error = VOP_SETATTR(vp->v_specparent, ap->a_vap, ap->a_cred); VOP_UNLOCK(vp, 0); return (error); }
/* * union_setattr(struct vnode *a_vp, struct vattr *a_vap, * struct ucred *a_cred, struct thread *a_td) */ static int union_setattr(struct vop_setattr_args *ap) { struct union_node *un = VTOUNION(ap->a_vp); struct thread *td = ap->a_td; struct vattr *vap = ap->a_vap; struct vnode *uppervp; int error; /* * Disallow write attempts on filesystems mounted read-only. */ if ((ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) && (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)) { return (EROFS); } /* * Handle case of truncating lower object to zero size, * by creating a zero length upper object. This is to * handle the case of open with O_TRUNC and O_CREAT. */ if (un->un_uppervp == NULLVP && (un->un_lowervp->v_type == VREG)) { error = union_copyup(un, (ap->a_vap->va_size != 0), ap->a_cred, ap->a_td); if (error) return (error); } /* * Try to set attributes in upper layer, * otherwise return read-only filesystem error. */ error = EROFS; if ((uppervp = union_lock_upper(un, td)) != NULLVP) { error = VOP_SETATTR(un->un_uppervp, ap->a_vap, ap->a_cred); if ((error == 0) && (ap->a_vap->va_size != VNOVAL)) union_newsize(ap->a_vp, ap->a_vap->va_size, VNOVAL); union_unlock_upper(uppervp, td); } return (error); }
/* * Hacked up version of vn_open. We _only_ handle ptys and only open * them with FREAD|FWRITE and never deal with creat or stuff like that. * * We need it because we have to fake up root credentials to open the pty. */ static int ptm_vn_open(struct nameidata *ndp) { struct proc *p = ndp->ni_cnd.cn_proc; struct ucred *cred; struct vattr vattr; struct vnode *vp; int error; if ((error = namei(ndp)) != 0) return (error); vp = ndp->ni_vp; if (vp->v_type != VCHR) { error = EINVAL; goto bad; } /* * Get us a fresh cred with root privileges. */ cred = crget(); error = VOP_OPEN(vp, FREAD|FWRITE, cred, p); if (!error) { /* update atime/mtime */ VATTR_NULL(&vattr); getnanotime(&vattr.va_atime); vattr.va_mtime = vattr.va_atime; vattr.va_vaflags |= VA_UTIMES_NULL; (void)VOP_SETATTR(vp, &vattr, p->p_ucred, p); } crfree(cred); if (error) goto bad; vp->v_writecount++; return (0); bad: vput(vp); return (error); }
int pty_grant_slave(struct lwp *l, dev_t dev, struct mount *mp) { int error; struct vnode *vp; /* * Open the slave. * namei -> setattr -> unlock -> revoke -> vrele -> * namei -> open -> unlock * Three stage rocket: * 1. Change the owner and permissions on the slave. * 2. Revoke all the users of the slave. * 3. open the slave. */ if (ptm == NULL) return EOPNOTSUPP; if ((error = (*ptm->allocvp)(mp, l, &vp, dev, 't')) != 0) return error; if ((vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { struct vattr vattr; (*ptm->getvattr)(mp, l, &vattr); /* Do the VOP_SETATTR() as root. */ error = VOP_SETATTR(vp, &vattr, lwp0.l_cred); if (error) { DPRINTF(("setattr %d\n", error)); VOP_UNLOCK(vp); vrele(vp); return error; } } VOP_UNLOCK(vp); VOP_REVOKE(vp, REVOKEALL); /* * The vnode is useless after the revoke, we need to get it again. */ vrele(vp); return 0; }
static int xattr_dir_setattr(vnode_t *vp, vattr_t *vap, int flags, cred_t *cr, caller_context_t *ct) { vnode_t *realvp; int error; /* * If there is a real xattr directory, do the setattr there. * Otherwise, just return success. The GFS directory is transient, * and any setattr changes can disappear anyway. */ error = xattr_dir_realdir(vp, &realvp, LOOKUP_XATTR, cr, ct); if (error == 0) { error = VOP_SETATTR(realvp, vap, flags, cr, ct); } if (error == ENOENT) { error = 0; } return (error); }
int linvfs_generic_file_mmap(struct file *filp, struct vm_area_struct *vma) { vnode_t *vp; int ret; /* this will return a (-) error so flip */ ret = -generic_file_mmap(filp, vma); if (!ret) { vattr_t va, *vap; vap = &va; vap->va_mask = AT_UPDATIME; vp = LINVFS_GET_VP(filp->f_dentry->d_inode); ASSERT(vp); VOP_SETATTR(vp, vap, AT_UPDATIME, NULL, ret); } return(-ret); }
static int xattr_copy(vnode_t *sdvp, char *snm, vnode_t *tdvp, char *tnm, cred_t *cr, caller_context_t *ct) { xvattr_t xvattr; vnode_t *pdvp; int error; /* * Only copy system attrs if the views are the same */ if (strcmp(snm, tnm) != 0) return (EINVAL); xva_init(&xvattr); XVA_SET_REQ(&xvattr, XAT_SYSTEM); XVA_SET_REQ(&xvattr, XAT_READONLY); XVA_SET_REQ(&xvattr, XAT_HIDDEN); XVA_SET_REQ(&xvattr, XAT_ARCHIVE); XVA_SET_REQ(&xvattr, XAT_APPENDONLY); XVA_SET_REQ(&xvattr, XAT_NOUNLINK); XVA_SET_REQ(&xvattr, XAT_IMMUTABLE); XVA_SET_REQ(&xvattr, XAT_NODUMP); XVA_SET_REQ(&xvattr, XAT_AV_MODIFIED); XVA_SET_REQ(&xvattr, XAT_AV_QUARANTINED); XVA_SET_REQ(&xvattr, XAT_CREATETIME); XVA_SET_REQ(&xvattr, XAT_REPARSE); XVA_SET_REQ(&xvattr, XAT_OFFLINE); XVA_SET_REQ(&xvattr, XAT_SPARSE); pdvp = gfs_file_parent(sdvp); error = VOP_GETATTR(pdvp, &xvattr.xva_vattr, 0, cr, ct); if (error) return (error); pdvp = gfs_file_parent(tdvp); error = VOP_SETATTR(pdvp, &xvattr.xva_vattr, 0, cr, ct); return (error); }
static int unionfs_setattr(void *v) { struct vop_setattr_args *ap = v; int error; struct unionfs_node *unp; struct vnode *uvp; struct vnode *lvp; struct vattr *vap; UNIONFS_INTERNAL_DEBUG("unionfs_setattr: enter\n"); error = EROFS; unp = VTOUNIONFS(ap->a_vp); uvp = unp->un_uppervp; lvp = unp->un_lowervp; vap = ap->a_vap; if ((ap->a_vp->v_mount->mnt_flag & MNT_RDONLY) && (vap->va_flags != VNOVAL || vap->va_uid != (uid_t)VNOVAL || vap->va_gid != (gid_t)VNOVAL || vap->va_atime.tv_sec != VNOVAL || vap->va_mtime.tv_sec != VNOVAL || vap->va_mode != (mode_t)VNOVAL)) return (EROFS); if (uvp == NULLVP && lvp->v_type == VREG) { error = unionfs_copyfile(unp, (vap->va_size != 0), ap->a_cred); if (error != 0) return (error); uvp = unp->un_uppervp; } if (uvp != NULLVP) error = VOP_SETATTR(uvp, vap, ap->a_cred); UNIONFS_INTERNAL_DEBUG("unionfs_setattr: leave (%d)\n", error); return (error); }
int sc_chown(thread_t *t, syscall_result_t *r, chown_args_t *args) { int res=0; proc_t *p = t->thr_proc; vnode_t *node; char pname[PATH_MAX]; if((res = copyinstr(pname, args->fname, PATH_MAX))) return res; res = vfs_lookup(p->p_curdir, &node, pname, t, LKP_NORMAL); if(res) return res; vattr_t va; va.va_mask=VATTR_ALL; if((res = VOP_GETATTR(node, &va))) goto err; res = -EPERM; if(p->p_cred->p_euid != 0 && p->p_cred->p_euid != va.va_uid) goto err; if(p->p_cred->p_euid != 0) //tak... póki co nie ma zmian dla nie roota goto err; va.va_mask = VATTR_UID | VATTR_GID | VATTR_MODE; if(args->uid!=-1) va.va_uid = args->uid; if(args->gid!=-1) va.va_gid = args->gid; if(p->p_cred->p_euid!=0) //tymczasowo niemożliwe UNSET(va.va_mode, S_ISUID | S_ISGID); if((res = VOP_SETATTR(node, &va))) goto err; vrele(node); return 0; err: vrele(node); return res; }
STATIC int xfs_file_mmap( struct file *filp, struct vm_area_struct *vma) { struct inode *ip = filp->f_dentry->d_inode; vnode_t *vp = vn_from_inode(ip); vattr_t vattr; int error; vma->vm_ops = &xfs_file_vm_ops; #ifdef CONFIG_XFS_DMAPI if (vp->v_vfsp->vfs_flag & VFS_DMI) { vma->vm_ops = &xfs_dmapi_file_vm_ops; } #endif /* CONFIG_XFS_DMAPI */ vattr.va_mask = XFS_AT_UPDATIME; VOP_SETATTR(vp, &vattr, XFS_AT_UPDATIME, NULL, error); if (likely(!error)) __vn_revalidate(vp, &vattr); /* update flags */ return 0; }
/* * Common code for vnode open operations. * Check permissions, and call the VOP_OPEN or VOP_CREATE routine. */ int vn_open(struct nameidata *ndp, int fmode, int cmode) { struct vnode *vp; struct proc *p = ndp->ni_cnd.cn_proc; struct ucred *cred = p->p_ucred; struct vattr va; int error; if ((fmode & (FREAD|FWRITE)) == 0) return (EINVAL); if ((fmode & (O_TRUNC | FWRITE)) == O_TRUNC) return (EINVAL); if (fmode & O_CREAT) { ndp->ni_cnd.cn_nameiop = CREATE; ndp->ni_cnd.cn_flags = LOCKPARENT | LOCKLEAF; if ((fmode & O_EXCL) == 0 && (fmode & O_NOFOLLOW) == 0) ndp->ni_cnd.cn_flags |= FOLLOW; if ((error = namei(ndp)) != 0) return (error); if (ndp->ni_vp == NULL) { VATTR_NULL(&va); va.va_type = VREG; va.va_mode = cmode; error = VOP_CREATE(ndp->ni_dvp, &ndp->ni_vp, &ndp->ni_cnd, &va); if (error) return (error); fmode &= ~O_TRUNC; vp = ndp->ni_vp; } else { VOP_ABORTOP(ndp->ni_dvp, &ndp->ni_cnd); if (ndp->ni_dvp == ndp->ni_vp) vrele(ndp->ni_dvp); else vput(ndp->ni_dvp); ndp->ni_dvp = NULL; vp = ndp->ni_vp; if (fmode & O_EXCL) { error = EEXIST; goto bad; } fmode &= ~O_CREAT; } } else { ndp->ni_cnd.cn_nameiop = LOOKUP; ndp->ni_cnd.cn_flags = ((fmode & O_NOFOLLOW) ? NOFOLLOW : FOLLOW) | LOCKLEAF; if ((error = namei(ndp)) != 0) return (error); vp = ndp->ni_vp; } if (vp->v_type == VSOCK) { error = EOPNOTSUPP; goto bad; } if (vp->v_type == VLNK) { error = EMLINK; goto bad; } if ((fmode & O_CREAT) == 0) { if (fmode & FREAD) { if ((error = VOP_ACCESS(vp, VREAD, cred, p)) != 0) goto bad; } if (fmode & FWRITE) { if (vp->v_type == VDIR) { error = EISDIR; goto bad; } if ((error = vn_writechk(vp)) != 0 || (error = VOP_ACCESS(vp, VWRITE, cred, p)) != 0) goto bad; } } if ((fmode & O_TRUNC) && vp->v_type == VREG) { VATTR_NULL(&va); va.va_size = 0; if ((error = VOP_SETATTR(vp, &va, cred, p)) != 0) goto bad; } if ((error = VOP_OPEN(vp, fmode, cred, p)) != 0) goto bad; if (vp->v_flag & VCLONED) { struct cloneinfo *cip = (struct cloneinfo *) vp->v_data; vp->v_flag &= ~VCLONED; ndp->ni_vp = cip->ci_vp; /* return cloned vnode */ vp->v_data = cip->ci_data; /* restore v_data */ VOP_UNLOCK(vp, 0, p); /* keep a reference */ vp = ndp->ni_vp; /* for the increment below */ free(cip, M_TEMP); } if (fmode & FWRITE) vp->v_writecount++; return (0); bad: vput(vp); return (error); }
STATIC int xfs_ioc_xattr( vnode_t *vp, xfs_inode_t *ip, struct file *filp, unsigned int cmd, unsigned long arg) { struct fsxattr fa; vattr_t va; int error; int attr_flags; unsigned int flags; switch (cmd) { case XFS_IOC_FSGETXATTR: { va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_NEXTENTS; VOP_GETATTR(vp, &va, 0, NULL, error); if (error) return -error; fa.fsx_xflags = va.va_xflags; fa.fsx_extsize = va.va_extsize; fa.fsx_nextents = va.va_nextents; if (copy_to_user((struct fsxattr *)arg, &fa, sizeof(fa))) return -XFS_ERROR(EFAULT); return 0; } case XFS_IOC_FSSETXATTR: { if (copy_from_user(&fa, (struct fsxattr *)arg, sizeof(fa))) return -XFS_ERROR(EFAULT); attr_flags = 0; if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) attr_flags |= ATTR_NONBLOCK; va.va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE; va.va_xflags = fa.fsx_xflags; va.va_extsize = fa.fsx_extsize; VOP_SETATTR(vp, &va, attr_flags, NULL, error); if (!error) vn_revalidate(vp); /* update Linux inode flags */ return -error; } case XFS_IOC_FSGETXATTRA: { va.va_mask = XFS_AT_XFLAGS|XFS_AT_EXTSIZE|XFS_AT_ANEXTENTS; VOP_GETATTR(vp, &va, 0, NULL, error); if (error) return -error; fa.fsx_xflags = va.va_xflags; fa.fsx_extsize = va.va_extsize; fa.fsx_nextents = va.va_anextents; if (copy_to_user((struct fsxattr *)arg, &fa, sizeof(fa))) return -XFS_ERROR(EFAULT); return 0; } case XFS_IOC_GETXFLAGS: { flags = xfs_di2lxflags(ip->i_d.di_flags); if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags))) return -XFS_ERROR(EFAULT); return 0; } case XFS_IOC_SETXFLAGS: { if (copy_from_user(&flags, (unsigned int *)arg, sizeof(flags))) return -XFS_ERROR(EFAULT); if (flags & ~(LINUX_XFLAG_IMMUTABLE | LINUX_XFLAG_APPEND | \ LINUX_XFLAG_NOATIME | LINUX_XFLAG_NODUMP | \ LINUX_XFLAG_SYNC)) return -XFS_ERROR(EOPNOTSUPP); attr_flags = 0; if (filp->f_flags & (O_NDELAY|O_NONBLOCK)) attr_flags |= ATTR_NONBLOCK; va.va_mask = XFS_AT_XFLAGS; va.va_xflags = xfs_merge_ioc_xflags(flags, xfs_dic2xflags(&ip->i_d, ARCH_NOCONVERT)); VOP_SETATTR(vp, &va, attr_flags, NULL, error); if (!error) vn_revalidate(vp); /* update Linux inode flags */ return -error; } case XFS_IOC_GETVERSION: { flags = LINVFS_GET_IP(vp)->i_generation; if (copy_to_user((unsigned int *)arg, &flags, sizeof(flags))) return -XFS_ERROR(EFAULT); return 0; } default: return -ENOTTY; } }
int ptmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { dev_t newdev, error; struct pt_softc * pti; struct nameidata cnd, snd; struct filedesc *fdp = p->p_fd; struct file *cfp = NULL, *sfp = NULL; int cindx, sindx; uid_t uid; gid_t gid; struct vattr vattr; struct ucred *cred; struct ptmget *ptm = (struct ptmget *)data; error = 0; switch (cmd) { case PTMGET: fdplock(fdp); /* Grab two filedescriptors. */ if ((error = falloc(p, &cfp, &cindx)) != 0) { fdpunlock(fdp); break; } if ((error = falloc(p, &sfp, &sindx)) != 0) { fdremove(fdp, cindx); closef(cfp, p); fdpunlock(fdp); break; } retry: /* Find and open a free master pty. */ newdev = pty_getfree(); if ((error = check_pty(minor(newdev)))) goto bad; pti = pt_softc[minor(newdev)]; NDINIT(&cnd, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE, pti->pty_pn, p); if ((error = ptm_vn_open(&cnd)) != 0) { /* * Check if the master open failed because we lost * the race to grab it. */ if (error == EIO && !pty_isfree(minor(newdev))) goto retry; goto bad; } cfp->f_flag = FREAD|FWRITE; cfp->f_type = DTYPE_VNODE; cfp->f_ops = &vnops; cfp->f_data = (caddr_t) cnd.ni_vp; VOP_UNLOCK(cnd.ni_vp, 0, p); /* * Open the slave. * namei -> setattr -> unlock -> revoke -> vrele -> * namei -> open -> unlock * Three stage rocket: * 1. Change the owner and permissions on the slave. * 2. Revoke all the users of the slave. * 3. open the slave. */ NDINIT(&snd, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE, pti->pty_sn, p); if ((error = namei(&snd)) != 0) goto bad; if ((snd.ni_vp->v_mount->mnt_flag & MNT_RDONLY) == 0) { gid = tty_gid; /* get real uid */ uid = p->p_cred->p_ruid; VATTR_NULL(&vattr); vattr.va_uid = uid; vattr.va_gid = gid; vattr.va_mode = (S_IRUSR|S_IWUSR|S_IWGRP) & ALLPERMS; /* Get a fake cred to pretend we're root. */ cred = crget(); error = VOP_SETATTR(snd.ni_vp, &vattr, cred, p); crfree(cred); if (error) { vput(snd.ni_vp); goto bad; } } VOP_UNLOCK(snd.ni_vp, 0, p); if (snd.ni_vp->v_usecount > 1 || (snd.ni_vp->v_flag & (VALIASED))) VOP_REVOKE(snd.ni_vp, REVOKEALL); /* * The vnode is useless after the revoke, we need to * namei again. */ vrele(snd.ni_vp); NDINIT(&snd, LOOKUP, NOFOLLOW|LOCKLEAF, UIO_SYSSPACE, pti->pty_sn, p); /* now open it */ if ((error = ptm_vn_open(&snd)) != 0) goto bad; sfp->f_flag = FREAD|FWRITE; sfp->f_type = DTYPE_VNODE; sfp->f_ops = &vnops; sfp->f_data = (caddr_t) snd.ni_vp; VOP_UNLOCK(snd.ni_vp, 0, p); /* now, put the indexen and names into struct ptmget */ ptm->cfd = cindx; ptm->sfd = sindx; memcpy(ptm->cn, pti->pty_pn, sizeof(pti->pty_pn)); memcpy(ptm->sn, pti->pty_sn, sizeof(pti->pty_sn)); /* mark the files mature now that we've passed all errors */ FILE_SET_MATURE(cfp); FILE_SET_MATURE(sfp); fdpunlock(fdp); break; default: error = EINVAL; break; } return (error); bad: fdremove(fdp, cindx); closef(cfp, p); fdremove(fdp, sindx); closef(sfp, p); fdpunlock(fdp); return (error); }