static int nfs_statvfs(struct mount *mp, struct statvfs *sbp, struct ucred *cred) { struct vnode *vp; struct nfs_statfs *sfp; struct nfsmount *nmp = VFSTONFS(mp); thread_t td = curthread; int error = 0, retattr; struct nfsnode *np; struct nfsm_info info; info.mrep = NULL; info.v3 = (nmp->nm_flag & NFSMNT_NFSV3); lwkt_gettoken(&nmp->nm_token); #ifndef nolint sfp = NULL; #endif error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, NULL); if (error) { lwkt_reltoken(&nmp->nm_token); return (error); } vp = NFSTOV(np); /* ignore the passed cred */ cred = crget(); cred->cr_ngroups = 1; if (info.v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) (void)nfs_fsinfo(nmp, vp, td); nfsstats.rpccnt[NFSPROC_FSSTAT]++; nfsm_reqhead(&info, vp, NFSPROC_FSSTAT, NFSX_FH(info.v3)); ERROROUT(nfsm_fhtom(&info, vp)); NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_FSSTAT, td, cred, &error)); if (info.v3) { ERROROUT(nfsm_postop_attr(&info, vp, &retattr, NFS_LATTR_NOSHRINK)); } if (error) { if (info.mrep != NULL) m_freem(info.mrep); goto nfsmout; } NULLOUT(sfp = nfsm_dissect(&info, NFSX_STATFS(info.v3))); sbp->f_flag = nmp->nm_flag; sbp->f_owner = nmp->nm_cred->cr_ruid; if (info.v3) { sbp->f_bsize = NFS_FABLKSIZE; sbp->f_frsize = NFS_FABLKSIZE; sbp->f_blocks = (fxdr_hyper(&sfp->sf_tbytes) / ((u_quad_t)NFS_FABLKSIZE)); sbp->f_bfree = (fxdr_hyper(&sfp->sf_fbytes) / ((u_quad_t)NFS_FABLKSIZE)); sbp->f_bavail = (fxdr_hyper(&sfp->sf_abytes) / ((u_quad_t)NFS_FABLKSIZE)); sbp->f_files = fxdr_hyper(&sfp->sf_tfiles); sbp->f_ffree = fxdr_hyper(&sfp->sf_ffiles); sbp->f_favail = fxdr_hyper(&sfp->sf_afiles); } else { sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize); sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks); sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree); sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail); sbp->f_files = 0; sbp->f_ffree = 0; sbp->f_favail = 0; } sbp->f_syncreads = 0; sbp->f_syncwrites = 0; sbp->f_asyncreads = 0; sbp->f_asyncwrites = 0; sbp->f_type = mp->mnt_vfc->vfc_typenum; m_freem(info.mrep); info.mrep = NULL; nfsmout: vput(vp); crfree(cred); lwkt_reltoken(&nmp->nm_token); return (error); }
/* * nfs statfs call */ int nfs_statfs(struct mount *mp, struct statfs *sbp, struct ucred *cred) { struct vnode *vp; struct nfs_statfs *sfp; struct nfsmount *nmp = VFSTONFS(mp); thread_t td = curthread; int error = 0, retattr; struct nfsnode *np; u_quad_t tquad; struct nfsm_info info; info.mrep = NULL; info.v3 = (nmp->nm_flag & NFSMNT_NFSV3); lwkt_gettoken(&nmp->nm_token); #ifndef nolint sfp = NULL; #endif error = nfs_nget(mp, (nfsfh_t *)nmp->nm_fh, nmp->nm_fhsize, &np, NULL); if (error) { lwkt_reltoken(&nmp->nm_token); return (error); } vp = NFSTOV(np); /* ignore the passed cred */ cred = crget(); cred->cr_ngroups = 1; if (info.v3 && (nmp->nm_state & NFSSTA_GOTFSINFO) == 0) (void)nfs_fsinfo(nmp, vp, td); nfsstats.rpccnt[NFSPROC_FSSTAT]++; nfsm_reqhead(&info, vp, NFSPROC_FSSTAT, NFSX_FH(info.v3)); ERROROUT(nfsm_fhtom(&info, vp)); NEGKEEPOUT(nfsm_request(&info, vp, NFSPROC_FSSTAT, td, cred, &error)); if (info.v3) { ERROROUT(nfsm_postop_attr(&info, vp, &retattr, NFS_LATTR_NOSHRINK)); } if (error) { if (info.mrep != NULL) m_freem(info.mrep); goto nfsmout; } NULLOUT(sfp = nfsm_dissect(&info, NFSX_STATFS(info.v3))); sbp->f_flags = nmp->nm_flag; if (info.v3) { sbp->f_bsize = NFS_FABLKSIZE; tquad = fxdr_hyper(&sfp->sf_tbytes); sbp->f_blocks = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); tquad = fxdr_hyper(&sfp->sf_fbytes); sbp->f_bfree = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); tquad = fxdr_hyper(&sfp->sf_abytes); sbp->f_bavail = (long)(tquad / ((u_quad_t)NFS_FABLKSIZE)); sbp->f_files = (fxdr_unsigned(int32_t, sfp->sf_tfiles.nfsuquad[1]) & 0x7fffffff); sbp->f_ffree = (fxdr_unsigned(int32_t, sfp->sf_ffiles.nfsuquad[1]) & 0x7fffffff); } else { sbp->f_bsize = fxdr_unsigned(int32_t, sfp->sf_bsize); sbp->f_blocks = fxdr_unsigned(int32_t, sfp->sf_blocks); sbp->f_bfree = fxdr_unsigned(int32_t, sfp->sf_bfree); sbp->f_bavail = fxdr_unsigned(int32_t, sfp->sf_bavail); sbp->f_files = 0; sbp->f_ffree = 0; } /* * Some values are pre-set in mnt_stat. Note in particular f_iosize * cannot be changed once the filesystem is mounted as it is used * as the basis for BIOs. */ if (sbp != &mp->mnt_stat) { sbp->f_type = mp->mnt_vfc->vfc_typenum; bcopy(mp->mnt_stat.f_mntfromname, sbp->f_mntfromname, MNAMELEN); sbp->f_iosize = mp->mnt_stat.f_iosize; } m_freem(info.mrep); info.mrep = NULL; nfsmout: vput(vp); crfree(cred); lwkt_reltoken(&nmp->nm_token); return (error); }
int sys_setgid(struct setgid_args *uap) { struct proc *p = curproc; struct ucred *cr; gid_t gid; int error; lwkt_gettoken(&p->p_token); cr = p->p_ucred; /* * See if we have "permission" by POSIX 1003.1 rules. * * Note that setgid(getegid()) is a special case of * "appropriate privileges" in appendix B.4.2.2. We need * to use this clause to be compatible with traditional BSD * semantics. Basically, it means that "setgid(xx)" sets all * three id's (assuming you have privs). * * For notes on the logic here, see setuid() above. */ gid = uap->gid; if (gid != cr->cr_rgid && /* allow setgid(getgid()) */ #ifdef _POSIX_SAVED_IDS gid != cr->cr_svgid && /* allow setgid(saved gid) */ #endif #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ gid != cr->cr_groups[0] && /* allow setgid(getegid()) */ #endif (error = priv_check_cred(cr, PRIV_CRED_SETGID, 0))) { goto done; } #ifdef _POSIX_SAVED_IDS /* * Do we have "appropriate privileges" (are we root or gid == egid) * If so, we are changing the real uid and saved gid. */ if ( #ifdef POSIX_APPENDIX_B_4_2_2 /* use the clause from B.4.2.2 */ gid == cr->cr_groups[0] || #endif priv_check_cred(cr, PRIV_CRED_SETGID, 0) == 0) /* we are using privs */ #endif { /* * Set real gid */ if (cr->cr_rgid != gid) { cr = cratom_proc(p); cr->cr_rgid = gid; setsugid(); } /* * Set saved gid * * XXX always set saved gid even if not _POSIX_SAVED_IDS, as * the security of setegid() depends on it. B.4.2.2 says it * is important that we should do this. */ if (cr->cr_svgid != gid) { cr = cratom_proc(p); cr->cr_svgid = gid; setsugid(); } } /* * In all cases permitted cases, we are changing the egid. * Copy credentials so other references do not see our changes. */ if (cr->cr_groups[0] != gid) { cr = cratom_proc(p); cr->cr_groups[0] = gid; setsugid(); } error = 0; done: lwkt_reltoken(&p->p_token); return (error); }
int sys_setuid(struct setuid_args *uap) { struct proc *p = curproc; struct ucred *cr; uid_t uid; int error; lwkt_gettoken(&p->p_token); cr = p->p_ucred; /* * See if we have "permission" by POSIX 1003.1 rules. * * Note that setuid(geteuid()) is a special case of * "appropriate privileges" in appendix B.4.2.2. We need * to use this clause to be compatible with traditional BSD * semantics. Basically, it means that "setuid(xx)" sets all * three id's (assuming you have privs). * * Notes on the logic. We do things in three steps. * 1: We determine if the euid is going to change, and do EPERM * right away. We unconditionally change the euid later if this * test is satisfied, simplifying that part of the logic. * 2: We determine if the real and/or saved uid's are going to * change. Determined by compile options. * 3: Change euid last. (after tests in #2 for "appropriate privs") */ uid = uap->uid; if (uid != cr->cr_ruid && /* allow setuid(getuid()) */ #ifdef _POSIX_SAVED_IDS uid != crc->cr_svuid && /* allow setuid(saved gid) */ #endif #ifdef POSIX_APPENDIX_B_4_2_2 /* Use BSD-compat clause from B.4.2.2 */ uid != cr->cr_uid && /* allow setuid(geteuid()) */ #endif (error = priv_check_cred(cr, PRIV_CRED_SETUID, 0))) goto done; #ifdef _POSIX_SAVED_IDS /* * Do we have "appropriate privileges" (are we root or uid == euid) * If so, we are changing the real uid and/or saved uid. */ if ( #ifdef POSIX_APPENDIX_B_4_2_2 /* Use the clause from B.4.2.2 */ uid == cr->cr_uid || #endif priv_check_cred(cr, PRIV_CRED_SETUID, 0) == 0) /* we are using privs */ #endif { /* * Set the real uid and transfer proc count to new user. */ if (uid != cr->cr_ruid) { cr = change_ruid(uid); setsugid(); } /* * Set saved uid * * XXX always set saved uid even if not _POSIX_SAVED_IDS, as * the security of seteuid() depends on it. B.4.2.2 says it * is important that we should do this. */ if (cr->cr_svuid != uid) { cr = cratom_proc(p); cr->cr_svuid = uid; setsugid(); } } /* * In all permitted cases, we are changing the euid. * Copy credentials so other references do not see our changes. */ if (cr->cr_uid != uid) { change_euid(uid); setsugid(); } error = 0; done: lwkt_reltoken(&p->p_token); return (error); }
/* * No requirements. */ static int do_vmtotal(SYSCTL_HANDLER_ARGS) { struct vmtotal total; struct vmtotal *totalp; vm_object_t object; bzero(&total, sizeof(total)); totalp = &total; /* * Mark all objects as inactive. */ lwkt_gettoken(&vmobj_token); for (object = TAILQ_FIRST(&vm_object_list); object != NULL; object = TAILQ_NEXT(object,object_list)) { if (object->type == OBJT_MARKER) continue; vm_object_clear_flag(object, OBJ_ACTIVE); } lwkt_reltoken(&vmobj_token); /* * Calculate process statistics. */ allproc_scan(do_vmtotal_callback, totalp); /* * Calculate object memory usage statistics. */ lwkt_gettoken(&vmobj_token); for (object = TAILQ_FIRST(&vm_object_list); object != NULL; object = TAILQ_NEXT(object, object_list)) { /* * devices, like /dev/mem, will badly skew our totals. * markers aren't real objects. */ if (object->type == OBJT_MARKER) continue; if (object->type == OBJT_DEVICE) continue; if (object->size >= 0x7FFFFFFF) { /* * Probably unbounded anonymous memory (really * bounded by related vm_map_entry structures which * we do not have access to in this loop). */ totalp->t_vm += object->resident_page_count; } else { /* * It's questionable how useful this is but... */ totalp->t_vm += object->size; } totalp->t_rm += object->resident_page_count; if (object->flags & OBJ_ACTIVE) { totalp->t_avm += object->size; totalp->t_arm += object->resident_page_count; } if (object->shadow_count > 1) { /* shared object */ totalp->t_vmshr += object->size; totalp->t_rmshr += object->resident_page_count; if (object->flags & OBJ_ACTIVE) { totalp->t_avmshr += object->size; totalp->t_armshr += object->resident_page_count; } } } lwkt_reltoken(&vmobj_token); totalp->t_free = vmstats.v_free_count + vmstats.v_cache_count; return (sysctl_handle_opaque(oidp, totalp, sizeof total, req)); }
/* * The caller must hold proc_token. */ static int do_vmtotal_callback(struct proc *p, void *data) { struct vmtotal *totalp = data; struct lwp *lp; vm_map_entry_t entry; vm_map_t map; int paging; if (p->p_flag & P_SYSTEM) return(0); FOREACH_LWP_IN_PROC(lp, p) { switch (lp->lwp_stat) { case LSSTOP: case LSSLEEP: if ((p->p_flag & P_SWAPPEDOUT) == 0) { if ((lp->lwp_flag & LWP_SINTR) == 0) totalp->t_dw++; else if (lp->lwp_slptime < maxslp) totalp->t_sl++; } else if (lp->lwp_slptime < maxslp) { totalp->t_sw++; } if (lp->lwp_slptime >= maxslp) return(0); break; case LSRUN: if (p->p_flag & P_SWAPPEDOUT) totalp->t_sw++; else totalp->t_rq++; if (p->p_stat == SIDL) return(0); break; default: return (0); } } /* * Note active objects. */ paging = 0; lwkt_gettoken(&vm_token); if (p->p_vmspace) { map = &p->p_vmspace->vm_map; vm_map_lock_read(map); for (entry = map->header.next; entry != &map->header; entry = entry->next) { if (entry->maptype != VM_MAPTYPE_NORMAL && entry->maptype != VM_MAPTYPE_VPAGETABLE) { continue; } if (entry->object.vm_object == NULL) continue; vm_object_set_flag(entry->object.vm_object, OBJ_ACTIVE); paging |= entry->object.vm_object->paging_in_progress; } vm_map_unlock_read(map); } lwkt_reltoken(&vm_token); if (paging) totalp->t_pw++; return(0); }