/* * If we fork with active superpages * - the parent should still be able to access the superpages * - the child should not be able to access the superpages */ boolean_t test_fork() { mach_vm_address_t addr = 0; mach_vm_size_t size = SUPERPAGE_SIZE; int kr, ret; pid_t pid; kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB); if (!(ret = check_kr(kr, "mach_vm_allocate"))) return ret; fflush(stdout); if ((pid=fork())) { /* parent */ if (!(ret = check_rw(addr, size))) return ret; waitpid(pid, &ret, 0); if (!ret) { sprintf(error, "child could access superpage"); return ret; } } else { /* child */ if (!(ret = check_nr(addr, size, NULL))) exit(ret); exit(TRUE); } kr = mach_vm_deallocate(mach_task_self(), addr, size); if (!(ret = check_kr(kr, "mach_vm_deallocate"))) return ret; return TRUE; }
/* * Tests one allocation/deallocaton cycle; used in a loop this tests for leaks */ boolean_t test_alloc_dealloc() { mach_vm_address_t addr = 0; mach_vm_size_t size = SUPERPAGE_SIZE; int kr, ret; kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB); if (!(ret = check_kr(kr, "mach_vm_allocate"))) return ret; if (!(ret = check_addr0(addr, "mach_vm_allocate"))) return ret; if (!(ret = check_align(addr))) return ret; if (!(ret = check_rw(addr, size))) return ret; kr = mach_vm_deallocate(mach_task_self(), addr, size); if (!(ret = check_kr(kr, "mach_vm_deallocate"))) return ret; return TRUE; }
/* * If we allocate a 2 MB superpage read-write without specifying an address, * - the call should succeed * - not return 0 * - return a 2 MB aligned address * - the memory should be readable and writable */ boolean_t test_allocate() { int kr, ret; global_addr = 0; global_size = SUPERPAGE_SIZE; kr = mach_vm_allocate(mach_task_self(), &global_addr, global_size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB); if (!(ret = check_kr(kr, "mach_vm_allocate"))) return ret; if (!(ret = check_addr0(global_addr, "mach_vm_allocate"))) return ret; if (!(ret = check_align(global_addr))) return ret; if (!(ret = check_rw(global_addr, global_size))) return ret; return TRUE; }
/* * If we allocate a 2 MB superpage read-write at a 2 MB aligned address, * - the call should succeed * - return the address we wished for * - the memory should be readable and writable * If we deallocate it, * - the call should succeed * - make the memory inaccessible */ boolean_t test_allocatefixed() { int kr; int ret; mach_vm_address_t addr = FIXED_ADDRESS1; mach_vm_size_t size = SUPERPAGE_SIZE; kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_SUPERPAGE_SIZE_2MB); if (!(ret = check_kr(kr, "mach_vm_allocate"))) return ret; if (!(ret = check_addr(addr, FIXED_ADDRESS1, "mach_vm_allocate"))) return ret; if (!(ret = check_rw(addr, size))) return ret; kr = mach_vm_deallocate(mach_task_self(), addr, size); if (!(ret = check_kr(kr, "mach_vm_deallocate"))) return ret; if (!(ret = check_nr(addr, size, NULL))) return ret; return TRUE; }
/* * If we allocate a superpage of any size read-write without specifying an address * - the call should succeed * - not return 0 * - the memory should be readable and writable * If we deallocate it, * - the call should succeed * - make the memory inaccessible */ boolean_t test_allocate_size_any() { int kr; int ret; mach_vm_address_t addr = 0; mach_vm_size_t size = 2*PAGE_SIZE; /* will be rounded up to some superpage size */ kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_ANY); if (!(ret = check_kr(kr, "mach_vm_allocate"))) return ret; if (!(ret = check_addr0(addr, "mach_vm_allocate"))) return ret; if (!(ret = check_rw(addr, size))) return ret; kr = mach_vm_deallocate(mach_task_self(), addr, size); if (!(ret = check_kr(kr, "mach_vm_deallocate"))) return ret; if (!(ret = check_nr(addr, size, NULL))) return ret; return TRUE; }
/* * If we try to wire superpages * - the call should succeed * - the memory should remain readable and writable */ boolean_t test_wire() { int kr; int ret; mach_vm_address_t addr = 0; mach_vm_size_t size = SUPERPAGE_SIZE; kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB); if (!(ret = check_kr(kr, "mach_vm_allocate"))) return ret; kr = mach_vm_wire(mach_host_self(), mach_task_self(), addr, size, VM_PROT_WRITE | VM_PROT_READ); if (!geteuid()) /* may fail as user */ if (!(ret = check_kr(kr, "mach_vm_wire"))) return ret; if (!(ret = check_rw(addr, size))) return ret; kr = mach_vm_deallocate(mach_task_self(), addr, size); if (!(ret = check_kr(kr, "mach_vm_deallocate"))) return ret; return TRUE; }
/* * Implement sequence assignment item sub-script for the type. */ static int sipVoidPtr_ass_item(PyObject *self, int idx, PyObject *value) { int value_size; void *value_ptr; if (check_rw(self) < 0 || check_size(self) < 0 || check_index(self, idx) < 0) return -1; if ((value_size = get_value_data(value, &value_ptr)) < 0) return -1; if (value_size != 1) { PyErr_SetString(PyExc_TypeError, "right operand must be a single byte"); return -1; } ((char *)((sipVoidPtrObject *)self)->voidptr)[idx] = *(char *)value_ptr; return 0; }
/* * If we try to wire superpages * - the call should fail * - the memory should remain readable and writable * Currently, superpages are always wired. */ boolean_t test_unwire() { int kr; int ret; mach_vm_address_t addr = 0; mach_vm_size_t size = SUPERPAGE_SIZE; kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB); if (!(ret = check_kr(kr, "mach_vm_allocate"))) return ret; kr = mach_vm_wire(mach_host_self(), mach_task_self(), addr, size, VM_PROT_NONE); if ((ret = check_kr(kr, "mach_vm_wire"))) { sprintf(error, "could unwire"); return FALSE; } if (!(ret = check_rw(addr, size))) return ret; kr = mach_vm_deallocate(mach_task_self(), addr, size); if (!(ret = check_kr(kr, "mach_vm_deallocate"))) return ret; return TRUE; }
/* * Implement sequence assignment slice sub-script for the type. */ static int sipVoidPtr_ass_slice(PyObject *self, int left, int right, PyObject *value) { sipVoidPtrObject *v; int value_size; void *value_ptr; if (check_rw(self) < 0 || check_size(self) < 0) return -1; if ((value_size = get_value_data(value, &value_ptr)) < 0) return -1; v = (sipVoidPtrObject *)self; fix_bounds(v->size, &left, &right); if (check_slice_size(right - left, value_size) < 0) return -1; memmove((char *)(v->voidptr) + left, value_ptr, right - left); return 0; }
/* * Implement mapping assignment sub-script for the type. */ static int sipVoidPtr_ass_subscript(PyObject *self, PyObject *key, PyObject *value) { sipVoidPtrObject *v; Py_ssize_t start, size; #if PY_VERSION_HEX >= 0x02060000 Py_buffer value_view; #else Py_ssize_t value_size; void *value_ptr; #endif if (check_rw(self) < 0 || check_size(self) < 0) return -1; v = (sipVoidPtrObject *)self; if (PyIndex_Check(key)) { start = PyNumber_AsSsize_t(key, PyExc_IndexError); if (start == -1 && PyErr_Occurred()) return -1; if (start < 0) start += v->size; if (check_index(self, start) < 0) return -1; size = 1; } else if (PySlice_Check(key)) { Py_ssize_t stop, step; if (sipConvertFromSliceObject(key, v->size, &start, &stop, &step, &size) < 0) return -1; if (step != 1) { PyErr_SetNone(PyExc_NotImplementedError); return -1; } } else { bad_key(key); return -1; } #if PY_VERSION_HEX >= 0x02060000 if (PyObject_GetBuffer(value, &value_view, PyBUF_CONTIG_RO) < 0) return -1; /* We could allow any item size... */ if (value_view.itemsize != 1) { PyErr_Format(PyExc_TypeError, "'%s' must have an item size of 1", Py_TYPE(value_view.obj)->tp_name); PyBuffer_Release(&value_view); return -1; } if (check_slice_size(size, value_view.len) < 0) { PyBuffer_Release(&value_view); return -1; } memmove((char *)v->voidptr + start, value_view.buf, size); PyBuffer_Release(&value_view); #else if ((value_size = get_value_data(value, &value_ptr)) < 0) return -1; if (check_slice_size(size, value_size) < 0) return -1; memmove((char *)v->voidptr + start, value_ptr, size); #endif return 0; }