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