From owner-svn-src-all@freebsd.org Fri Jun 19 03:32:06 2020 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 51C5433CD87; Fri, 19 Jun 2020 03:32:06 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 49p49f1X6xz4Rcl; Fri, 19 Jun 2020 03:32:06 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 2FCD014B50; Fri, 19 Jun 2020 03:32:06 +0000 (UTC) (envelope-from markj@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 05J3W6u8006448; Fri, 19 Jun 2020 03:32:06 GMT (envelope-from markj@FreeBSD.org) Received: (from markj@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 05J3W53u006443; Fri, 19 Jun 2020 03:32:05 GMT (envelope-from markj@FreeBSD.org) Message-Id: <202006190332.05J3W53u006443@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: markj set sender to markj@FreeBSD.org using -f From: Mark Johnston Date: Fri, 19 Jun 2020 03:32:05 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r362361 - in head/sys: compat/linuxkpi/common/src vm X-SVN-Group: head X-SVN-Commit-Author: markj X-SVN-Commit-Paths: in head/sys: compat/linuxkpi/common/src vm X-SVN-Commit-Revision: 362361 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 19 Jun 2020 03:32:06 -0000 Author: markj Date: Fri Jun 19 03:32:04 2020 New Revision: 362361 URL: https://svnweb.freebsd.org/changeset/base/362361 Log: Add a helper function for validating VA ranges. Functions which take untrusted user ranges must validate against the bounds of the map, and also check for wraparound. Instead of having the same logic duplicated in a number of places, add a function to check. Reviewed by: dougm, kib Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential Revision: https://reviews.freebsd.org/D25328 Modified: head/sys/compat/linuxkpi/common/src/linux_page.c head/sys/vm/vm_fault.c head/sys/vm/vm_map.c head/sys/vm/vm_map.h head/sys/vm/vm_mmap.c Modified: head/sys/compat/linuxkpi/common/src/linux_page.c ============================================================================== --- head/sys/compat/linuxkpi/common/src/linux_page.c Fri Jun 19 03:31:46 2020 (r362360) +++ head/sys/compat/linuxkpi/common/src/linux_page.c Fri Jun 19 03:32:04 2020 (r362361) @@ -222,7 +222,7 @@ __get_user_pages_fast(unsigned long start, int nr_page va = start; map = &curthread->td_proc->p_vmspace->vm_map; end = start + (((size_t)nr_pages) << PAGE_SHIFT); - if (start < vm_map_min(map) || end > vm_map_max(map)) + if (!vm_map_range_valid(map, start, end)) return (-EINVAL); prot = write ? (VM_PROT_READ | VM_PROT_WRITE) : VM_PROT_READ; for (count = 0, mp = pages, va = start; va < end; Modified: head/sys/vm/vm_fault.c ============================================================================== --- head/sys/vm/vm_fault.c Fri Jun 19 03:31:46 2020 (r362360) +++ head/sys/vm/vm_fault.c Fri Jun 19 03:32:04 2020 (r362361) @@ -1713,10 +1713,7 @@ vm_fault_quick_hold_pages(vm_map_t map, vm_offset_t ad end = round_page(addr + len); addr = trunc_page(addr); - /* - * Check for illegal addresses. - */ - if (addr < vm_map_min(map) || addr > end || end > vm_map_max(map)) + if (!vm_map_range_valid(map, addr, end)) return (-1); if (atop(end - addr) > max_count) Modified: head/sys/vm/vm_map.c ============================================================================== --- head/sys/vm/vm_map.c Fri Jun 19 03:31:46 2020 (r362360) +++ head/sys/vm/vm_map.c Fri Jun 19 03:32:04 2020 (r362361) @@ -1616,8 +1616,7 @@ vm_map_insert(vm_map_t map, vm_object_t object, vm_oof /* * Check that the start and end points are not bogus. */ - if (start < vm_map_min(map) || end > vm_map_max(map) || - start >= end) + if (!vm_map_range_valid(map, start, end)) return (KERN_INVALID_ADDRESS); /* @@ -2161,9 +2160,7 @@ again: goto done; } } else if ((cow & MAP_REMAP) != 0) { - if (*addr < vm_map_min(map) || - *addr + length > vm_map_max(map) || - *addr + length <= length) { + if (!vm_map_range_valid(map, *addr, *addr + length)) { rv = KERN_INVALID_ADDRESS; goto done; } @@ -4324,9 +4321,8 @@ vm_map_stack_locked(vm_map_t map, vm_offset_t addrbos, KASSERT(orient != (MAP_STACK_GROWS_DOWN | MAP_STACK_GROWS_UP), ("bi-dir stack")); - if (addrbos < vm_map_min(map) || - addrbos + max_ssize > vm_map_max(map) || - addrbos + max_ssize <= addrbos) + if (max_ssize == 0 || + !vm_map_range_valid(map, addrbos, addrbos + max_ssize)) return (KERN_INVALID_ADDRESS); sgp = ((curproc->p_flag2 & P2_STKGAP_DISABLE) != 0 || (curproc->p_fctl0 & NT_FREEBSD_FCTL_STKGAP_DISABLE) != 0) ? 0 : Modified: head/sys/vm/vm_map.h ============================================================================== --- head/sys/vm/vm_map.h Fri Jun 19 03:31:46 2020 (r362360) +++ head/sys/vm/vm_map.h Fri Jun 19 03:32:04 2020 (r362361) @@ -255,6 +255,17 @@ vm_map_modflags(vm_map_t map, vm_flags_t set, vm_flags { map->flags = (map->flags | set) & ~clear; } + +static inline bool +vm_map_range_valid(vm_map_t map, vm_offset_t start, vm_offset_t end) +{ + if (end < start) + return (false); + if (start < vm_map_min(map) || end > vm_map_max(map)) + return (false); + return (true); +} + #endif /* KLD_MODULE */ #endif /* _KERNEL */ Modified: head/sys/vm/vm_mmap.c ============================================================================== --- head/sys/vm/vm_mmap.c Fri Jun 19 03:31:46 2020 (r362360) +++ head/sys/vm/vm_mmap.c Fri Jun 19 03:32:04 2020 (r362361) @@ -342,11 +342,8 @@ kern_mmap_req(struct thread *td, const struct mmap_req return (EINVAL); /* Address range must be all in user VM space. */ - if (addr < vm_map_min(&vms->vm_map) || - addr + size > vm_map_max(&vms->vm_map)) + if (!vm_map_range_valid(&vms->vm_map, addr, addr + size)) return (EINVAL); - if (addr + size < addr) - return (EINVAL); #ifdef MAP_32BIT if (flags & MAP_32BIT && addr + size > MAP_32BIT_MAX_ADDR) return (EINVAL); @@ -577,7 +574,7 @@ kern_munmap(struct thread *td, uintptr_t addr0, size_t vm_map_entry_t entry; bool pmc_handled; #endif - vm_offset_t addr; + vm_offset_t addr, end; vm_size_t pageoff; vm_map_t map; @@ -589,15 +586,11 @@ kern_munmap(struct thread *td, uintptr_t addr0, size_t addr -= pageoff; size += pageoff; size = (vm_size_t) round_page(size); - if (addr + size < addr) - return (EINVAL); - - /* - * Check for illegal addresses. Watch out for address wrap... - */ + end = addr + size; map = &td->td_proc->p_vmspace->vm_map; - if (addr < vm_map_min(map) || addr + size > vm_map_max(map)) + if (!vm_map_range_valid(map, addr, end)) return (EINVAL); + vm_map_lock(map); #ifdef HWPMC_HOOKS pmc_handled = false; @@ -609,7 +602,7 @@ kern_munmap(struct thread *td, uintptr_t addr0, size_t */ pkm.pm_address = (uintptr_t) NULL; if (vm_map_lookup_entry(map, addr, &entry)) { - for (; entry->start < addr + size; + for (; entry->start < end; entry = vm_map_entry_succ(entry)) { if (vm_map_check_protection(map, entry->start, entry->end, VM_PROT_EXECUTE) == TRUE) { @@ -621,7 +614,7 @@ kern_munmap(struct thread *td, uintptr_t addr0, size_t } } #endif - vm_map_delete(map, addr, addr + size); + vm_map_delete(map, addr, end); #ifdef HWPMC_HOOKS if (__predict_false(pmc_handled)) { @@ -772,9 +765,7 @@ kern_madvise(struct thread *td, uintptr_t addr0, size_ */ map = &td->td_proc->p_vmspace->vm_map; addr = addr0; - if (addr < vm_map_min(map) || addr + len > vm_map_max(map)) - return (EINVAL); - if ((addr + len) < addr) + if (!vm_map_range_valid(map, addr, addr + len)) return (EINVAL); /*