From owner-p4-projects Sun Jul 28 20:31: 2 2002 Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id B091337B401; Sun, 28 Jul 2002 20:30:37 -0700 (PDT) Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 24D8237B400 for ; Sun, 28 Jul 2002 20:30:37 -0700 (PDT) Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id AC0B243E5E for ; Sun, 28 Jul 2002 20:30:36 -0700 (PDT) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: from freefall.freebsd.org (perforce@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.4/8.12.4) with ESMTP id g6T3UaJU051810 for ; Sun, 28 Jul 2002 20:30:36 -0700 (PDT) (envelope-from bb+lists.freebsd.perforce@cyrus.watson.org) Received: (from perforce@localhost) by freefall.freebsd.org (8.12.4/8.12.4/Submit) id g6T3UZev051796 for perforce@freebsd.org; Sun, 28 Jul 2002 20:30:35 -0700 (PDT) Date: Sun, 28 Jul 2002 20:30:35 -0700 (PDT) Message-Id: <200207290330.g6T3UZev051796@freefall.freebsd.org> X-Authentication-Warning: freefall.freebsd.org: perforce set sender to bb+lists.freebsd.perforce@cyrus.watson.org using -f From: Robert Watson Subject: PERFORCE change 15096 for review To: Perforce Change Reviews Sender: owner-p4-projects@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG http://people.freebsd.org/~peter/p4db/chv.cgi?CH=15096 Change 15096 by rwatson@rwatson_paprika on 2002/07/28 20:30:28 More cosmetic changes. Relocate the memory map sweep during revocation to just below the subject relabeling code where it is used, and away from the framework/module initialization at the top. Rename some functions to match new naming conventions. Affected files ... .. //depot/projects/trustedbsd/mac/sys/kern/kern_mac.c#214 edit Differences ... ==== //depot/projects/trustedbsd/mac/sys/kern/kern_mac.c#214 (text+ko) ==== @@ -188,9 +188,9 @@ static int mac_policy_unregister(struct mac_policy_conf *mpc); static int mac_stdcreatevnode_ea(struct vnode *vp); -static void mac_subject_mmapped_drop_perms(struct thread *td, +static void mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred); -static void mac_subject_mmapped_drop_perms_recurse(struct thread *td, +static void mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, struct vm_map *map); /* @@ -284,160 +284,6 @@ const size_t maxlabelsize = 65536; /* - * When relabeling a subject, call out to the policies for the maximum - * permission allowed for each object type we know about in its - * memory space, and revoke access (in the least surprising ways we - * know) when necessary. The process lock is not held here. - */ -static void -mac_subject_mmapped_drop_perms(struct thread *td, struct ucred *cred) -{ - - /* XXX freeze all other threads */ - mtx_lock(&Giant); - mac_subject_mmapped_drop_perms_recurse(td, cred, - &td->td_proc->p_vmspace->vm_map); - mtx_unlock(&Giant); - /* XXX allow other threads to continue */ -} - -static __inline const char * -prot2str(vm_prot_t prot) -{ - - switch (prot & VM_PROT_ALL) { - case VM_PROT_READ: - return ("r--"); - case VM_PROT_READ | VM_PROT_WRITE: - return ("rw-"); - case VM_PROT_READ | VM_PROT_EXECUTE: - return ("r-x"); - case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: - return ("rwx"); - case VM_PROT_WRITE: - return ("-w-"); - case VM_PROT_EXECUTE: - return ("--x"); - case VM_PROT_WRITE | VM_PROT_EXECUTE: - return ("-wx"); - default: - return ("---"); - } -} - -static void -mac_subject_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, - struct vm_map *map) -{ - struct vm_map_entry *vme; - vm_prot_t result, revokeperms; - vm_object_t object; - vm_ooffset_t offset; - struct vnode *vp; - - vm_map_lock_read(map); - for (vme = map->header.next; vme != &map->header; vme = vme->next) { - if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { - mac_subject_mmapped_drop_perms_recurse(td, cred, - vme->object.sub_map); - continue; - } - /* - * Skip over entries that obviously are not shared. - */ - if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || - !vme->max_protection) - continue; - /* - * Drill down to the deepest backing object. - */ - offset = vme->offset; - object = vme->object.vm_object; - if (object == NULL) - continue; - while (object->backing_object != NULL) { - object = object->backing_object; - offset += object->backing_object_offset; - } - /* - * At the moment, vm_maps and objects aren't considered - * by the MAC system, so only things with backing by a - * normal object (read: vnodes) are checked. - */ - if (object->type != OBJT_VNODE) - continue; - vp = (struct vnode *)object->handle; - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - result = mac_check_vnode_mmap_prot(cred, vp, 0); - VOP_UNLOCK(vp, 0, td); - /* - * Find out what maximum protection we may be allowing - * now but a policy needs to get removed. - */ - revokeperms = vme->max_protection & ~result; - if (!revokeperms) - continue; - printf("pid %d: revoking %s perms from %#lx:%d " - "(max %s/cur %s)\n", td->td_proc->p_pid, - prot2str(revokeperms), vme->start, vme->end - vme->start, - prot2str(vme->max_protection), prot2str(vme->protection)); - vm_map_lock_upgrade(map); - /* - * This is the really simple case: if a map has more - * max_protection than is allowed, but it's not being - * actually used (that is, the current protection is - * still allowed), we can just wipe it out and do - * nothing more. - */ - if ((vme->protection & revokeperms) == 0) { - vme->max_protection -= revokeperms; - } else { - if (revokeperms & VM_PROT_WRITE) { - /* - * In the more complicated case, flush out all - * pending changes to the object then turn it - * copy-on-write. - */ - vm_object_reference(object); - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); - vm_object_page_clean(object, - OFF_TO_IDX(offset), - OFF_TO_IDX(offset + vme->end - vme->start + - PAGE_MASK), - OBJPC_SYNC); - VOP_UNLOCK(vp, 0, td); - vm_object_deallocate(object); - /* - * Why bother if there's no read permissions - * anymore? For the rest, we need to leave - * the write permissions on for COW, or - * remove them entirely if configured to. - */ - if (!mac_mmap_revocation_via_cow) { - vme->max_protection &= ~VM_PROT_WRITE; - vme->protection &= ~VM_PROT_WRITE; - } if ((revokeperms & VM_PROT_READ) == 0) - vme->eflags |= MAP_ENTRY_COW | - MAP_ENTRY_NEEDS_COPY; - } - if (revokeperms & VM_PROT_EXECUTE) { - vme->max_protection &= ~VM_PROT_EXECUTE; - vme->protection &= ~VM_PROT_EXECUTE; - } - if (revokeperms & VM_PROT_READ) { - vme->max_protection = 0; - vme->protection = 0; - } - pmap_protect(map->pmap, vme->start, vme->end, - vme->protection & ~revokeperms); - vm_map_simplify_entry(map, vme); - } - vm_map_lock_downgrade(map); - } - vm_map_unlock_read(map); -} - -/* * Initialize the MAC subsystem, including appropriate SMP locks. */ static void @@ -2147,6 +1993,160 @@ } /* + * When relabeling a process, call out to the policies for the maximum + * permission allowed for each object type we know about in its + * memory space, and revoke access (in the least surprising ways we + * know) when necessary. The process lock is not held here. + */ +static void +mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred) +{ + + /* XXX freeze all other threads */ + mtx_lock(&Giant); + mac_cred_mmapped_drop_perms_recurse(td, cred, + &td->td_proc->p_vmspace->vm_map); + mtx_unlock(&Giant); + /* XXX allow other threads to continue */ +} + +static __inline const char * +prot2str(vm_prot_t prot) +{ + + switch (prot & VM_PROT_ALL) { + case VM_PROT_READ: + return ("r--"); + case VM_PROT_READ | VM_PROT_WRITE: + return ("rw-"); + case VM_PROT_READ | VM_PROT_EXECUTE: + return ("r-x"); + case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE: + return ("rwx"); + case VM_PROT_WRITE: + return ("-w-"); + case VM_PROT_EXECUTE: + return ("--x"); + case VM_PROT_WRITE | VM_PROT_EXECUTE: + return ("-wx"); + default: + return ("---"); + } +} + +static void +mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred, + struct vm_map *map) +{ + struct vm_map_entry *vme; + vm_prot_t result, revokeperms; + vm_object_t object; + vm_ooffset_t offset; + struct vnode *vp; + + vm_map_lock_read(map); + for (vme = map->header.next; vme != &map->header; vme = vme->next) { + if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) { + mac_cred_mmapped_drop_perms_recurse(td, cred, + vme->object.sub_map); + continue; + } + /* + * Skip over entries that obviously are not shared. + */ + if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) || + !vme->max_protection) + continue; + /* + * Drill down to the deepest backing object. + */ + offset = vme->offset; + object = vme->object.vm_object; + if (object == NULL) + continue; + while (object->backing_object != NULL) { + object = object->backing_object; + offset += object->backing_object_offset; + } + /* + * At the moment, vm_maps and objects aren't considered + * by the MAC system, so only things with backing by a + * normal object (read: vnodes) are checked. + */ + if (object->type != OBJT_VNODE) + continue; + vp = (struct vnode *)object->handle; + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + result = mac_check_vnode_mmap_prot(cred, vp, 0); + VOP_UNLOCK(vp, 0, td); + /* + * Find out what maximum protection we may be allowing + * now but a policy needs to get removed. + */ + revokeperms = vme->max_protection & ~result; + if (!revokeperms) + continue; + printf("pid %d: revoking %s perms from %#lx:%d " + "(max %s/cur %s)\n", td->td_proc->p_pid, + prot2str(revokeperms), vme->start, vme->end - vme->start, + prot2str(vme->max_protection), prot2str(vme->protection)); + vm_map_lock_upgrade(map); + /* + * This is the really simple case: if a map has more + * max_protection than is allowed, but it's not being + * actually used (that is, the current protection is + * still allowed), we can just wipe it out and do + * nothing more. + */ + if ((vme->protection & revokeperms) == 0) { + vme->max_protection -= revokeperms; + } else { + if (revokeperms & VM_PROT_WRITE) { + /* + * In the more complicated case, flush out all + * pending changes to the object then turn it + * copy-on-write. + */ + vm_object_reference(object); + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td); + vm_object_page_clean(object, + OFF_TO_IDX(offset), + OFF_TO_IDX(offset + vme->end - vme->start + + PAGE_MASK), + OBJPC_SYNC); + VOP_UNLOCK(vp, 0, td); + vm_object_deallocate(object); + /* + * Why bother if there's no read permissions + * anymore? For the rest, we need to leave + * the write permissions on for COW, or + * remove them entirely if configured to. + */ + if (!mac_mmap_revocation_via_cow) { + vme->max_protection &= ~VM_PROT_WRITE; + vme->protection &= ~VM_PROT_WRITE; + } if ((revokeperms & VM_PROT_READ) == 0) + vme->eflags |= MAP_ENTRY_COW | + MAP_ENTRY_NEEDS_COPY; + } + if (revokeperms & VM_PROT_EXECUTE) { + vme->max_protection &= ~VM_PROT_EXECUTE; + vme->protection &= ~VM_PROT_EXECUTE; + } + if (revokeperms & VM_PROT_READ) { + vme->max_protection = 0; + vme->protection = 0; + } + pmap_protect(map->pmap, vme->start, vme->end, + vme->protection & ~revokeperms); + vm_map_simplify_entry(map, vme); + } + vm_map_lock_downgrade(map); + } + vm_map_unlock_read(map); +} + +/* * When the subject's label changes, it may require revocation of privilege * to mapped objects. This can't be done on-the-fly later with a unified * buffer cache. @@ -2156,7 +2156,7 @@ { MAC_PERFORM(relabel_cred, cred, newlabel); - mac_subject_mmapped_drop_perms(curthread, cred); + mac_cred_mmapped_drop_perms(curthread, cred); } void To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe p4-projects" in the body of the message