VM protection, code writes, and target cache traversal

osfmk/vm/vm_map.c · 25631 lines · browse source

VM map implementations behind protection changes and data overwrites. The MATTR_CACHE path walks target mappings, follows submaps and VM objects, and invokes pmap_attribute_cache_sync for resident physical pages.

vm_map_protect source
vm_map_protect: Sets the protection of the specified address region in the target map. If "set_max" is specified, the maximum protection is to be set; otherwise, only the current protection is affected.
kern_return_t
vm_map_protect(
	vm_map_t                map,
	vm_map_offset_ut        start_u,
	vm_map_offset_ut        end_u,
	boolean_t               set_max,
	vm_prot_ut              new_prot_u)
{
	vm_map_entry_t                  current;
	vm_map_offset_t                 prev;
	vm_map_entry_t                  entry;
	vm_prot_t                       new_prot;
	vm_prot_t                       new_max;
	int                             pmap_options = 0;
	kern_return_t                   kr;
	vm_map_offset_t                 start, original_start;
	vm_map_offset_t                 end;

	vmlp_api_start(VM_MAP_PROTECT);

	kr = vm_map_protect_sanitize(map,
	    start_u,
	    end_u,
	    new_prot_u,
	    &start,
	    &end,
	    &new_prot);
	if (__improbable(kr != KERN_SUCCESS)) {
		kr = vm_sanitize_get_kr(kr);
		vmlp_api_end(VM_MAP_PROTECT, kr);
… more in source
vm_map_copy_overwrite source
kern_return_t
vm_map_copy_overwrite(
	vm_map_t                dst_map,
	vm_map_offset_ut        dst_addr_u,
	vm_map_copy_t           copy,
	vm_map_size_ut          copy_size_u,
	boolean_t               interruptible)
{
	vm_map_offset_t dst_addr, dst_end;
	vm_map_size_t   copy_size;
	vm_map_size_t   head_size, tail_size;
	vm_map_copy_t   head_copy, tail_copy;
	vm_map_offset_t head_addr, tail_addr;
	vm_map_entry_t  entry;
	kern_return_t   kr;
	vm_map_offset_t effective_page_mask, effective_page_size;
	uint16_t        copy_page_shift;

	vmlp_api_start(VM_MAP_COPY_OVERWRITE);

	head_size = 0;
	tail_size = 0;
	head_copy = NULL;
	tail_copy = NULL;
	head_addr = 0;
	tail_addr = 0;

	/*
	 *	Check for null copy object.
	 */
… more in source
vm_map_machine_attribute source
Routine: vm_map_machine_attribute Purpose: Provide machine-specific attributes to mappings, such as cachability etc. for machines that provide them. NUMA architectures and machines with big/strange caches will use this. Note: Responsibilities for locking and checking are handled here, everything else in the pmap module. If any non-volatile information must be kept, the pmap module should handle it itself. [This assumes that attributes do not need to be inherited, which seems ok to me]
kern_return_t
vm_map_machine_attribute(
	vm_map_t                map,
	vm_map_offset_ut        start_u,
	vm_map_offset_ut        end_u,
	vm_machine_attribute_t  attribute,
	vm_machine_attribute_val_t *value) /* IN/OUT */
{
	mach_vm_offset_t start, end;
	vm_map_size_t    sync_size;
	kern_return_t    ret;
	vm_map_entry_t   entry;

	vmlp_api_start(VM_MAP_MACHINE_ATTRIBUTE);

	ret = vm_map_machine_attribute_sanitize(map,
	    start_u,
	    end_u,
	    &start,
	    &end,
	    &sync_size);
	if (__improbable(ret != KERN_SUCCESS)) {
		ret = vm_sanitize_get_kr(ret);
		vmlp_api_end(VM_MAP_MACHINE_ATTRIBUTE, ret);
		return ret;
	}

	if (start < vm_map_min(map) || end > vm_map_max(map)) {
		vmlp_api_end(VM_MAP_MACHINE_ATTRIBUTE, KERN_INVALID_ADDRESS);
		return KERN_INVALID_ADDRESS;
… more in source