+static inline bool
+is_kernel_to_kernel_copy()
+{
+ return current_thread()->map->pmap == kernel_pmap;
+}
+
+static int
+copy_validate_user(const user_addr_t user_addr, vm_size_t nbytes, bool kern_to_kern_allowed)
+{
+ user_addr_t user_addr_last = user_addr + nbytes;
+ thread_t self = current_thread();
+
+ if (__improbable(!kern_to_kern_allowed && is_kernel_to_kernel_copy())) {
+ return EFAULT;
+ }
+
+ if (__improbable((user_addr_last < user_addr) ||
+ ((user_addr + nbytes) > vm_map_max(self->map)) ||
+ (user_addr < vm_map_min(self->map)))) {
+ return EFAULT;
+ }
+
+ if (__improbable(nbytes > copysize_limit_panic)) {
+ panic("%s(%p, ..., %u) - transfer too large", __func__,
+ (void *)user_addr, nbytes);
+ }
+
+ return 0;
+}
+