PERFORCE change 15096 for review

Robert Watson rwatson at freebsd.org
Mon Jul 29 03:30:35 GMT 2002


http://people.freebsd.org/~peter/p4db/chv.cgi?CH=15096

Change 15096 by rwatson at 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 at trustedbsd.org
with "unsubscribe trustedbsd-cvs" in the body of the message



More information about the trustedbsd-cvs mailing list