From owner-svn-src-all@freebsd.org Mon Jun 17 15:14:28 2019 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id DE0FA15BCAB9; Mon, 17 Jun 2019 15:14:27 +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) server-signature RSA-PSS (4096 bits) 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 84FA86DEAD; Mon, 17 Jun 2019 15:14:27 +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 5D84A27614; Mon, 17 Jun 2019 15:14:27 +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 x5HFERav051258; Mon, 17 Jun 2019 15:14:27 GMT (envelope-from markj@FreeBSD.org) Received: (from markj@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id x5HFERum051257; Mon, 17 Jun 2019 15:14:27 GMT (envelope-from markj@FreeBSD.org) Message-Id: <201906171514.x5HFERum051257@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: markj set sender to markj@FreeBSD.org using -f From: Mark Johnston Date: Mon, 17 Jun 2019 15:14:27 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org Subject: svn commit: r349142 - stable/12/sys/vm X-SVN-Group: stable-12 X-SVN-Commit-Author: markj X-SVN-Commit-Paths: stable/12/sys/vm X-SVN-Commit-Revision: 349142 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 84FA86DEAD X-Spamd-Bar: -- Authentication-Results: mx1.freebsd.org X-Spamd-Result: default: False [-2.98 / 15.00]; local_wl_from(0.00)[FreeBSD.org]; NEURAL_HAM_MEDIUM(-1.00)[-0.999,0]; NEURAL_HAM_SHORT(-0.98)[-0.978,0]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; ASN(0.00)[asn:11403, ipnet:2610:1c1:1::/48, country:US] X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.29 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: Mon, 17 Jun 2019 15:14:28 -0000 Author: markj Date: Mon Jun 17 15:14:26 2019 New Revision: 349142 URL: https://svnweb.freebsd.org/changeset/base/349142 Log: MFC r347950: Use M_NEXTFIT in memguard(9). Modified: stable/12/sys/vm/memguard.c Directory Properties: stable/12/ (props changed) Modified: stable/12/sys/vm/memguard.c ============================================================================== --- stable/12/sys/vm/memguard.c Mon Jun 17 15:13:15 2019 (r349141) +++ stable/12/sys/vm/memguard.c Mon Jun 17 15:14:26 2019 (r349142) @@ -102,26 +102,29 @@ SYSCTL_PROC(_vm_memguard, OID_AUTO, desc, CTLTYPE_STRING | CTLFLAG_RW | CTLFLAG_MPSAFE, 0, 0, memguard_sysctl_desc, "A", "Short description of memory type to monitor"); -static vm_offset_t memguard_cursor; +static int +memguard_sysctl_mapused(SYSCTL_HANDLER_ARGS) +{ + vmem_size_t size; + + size = vmem_size(memguard_arena, VMEM_ALLOC); + return (sysctl_handle_long(oidp, &size, sizeof(size), req)); +} + static vm_offset_t memguard_base; static vm_size_t memguard_mapsize; static vm_size_t memguard_physlimit; static u_long memguard_wasted; -static u_long memguard_wrap; static u_long memguard_succ; static u_long memguard_fail_kva; static u_long memguard_fail_pgs; -SYSCTL_ULONG(_vm_memguard, OID_AUTO, cursor, CTLFLAG_RD, - &memguard_cursor, 0, "MemGuard cursor"); SYSCTL_ULONG(_vm_memguard, OID_AUTO, mapsize, CTLFLAG_RD, &memguard_mapsize, 0, "MemGuard private arena size"); SYSCTL_ULONG(_vm_memguard, OID_AUTO, phys_limit, CTLFLAG_RD, &memguard_physlimit, 0, "Limit on MemGuard memory consumption"); SYSCTL_ULONG(_vm_memguard, OID_AUTO, wasted, CTLFLAG_RD, &memguard_wasted, 0, "Excess memory used through page promotion"); -SYSCTL_ULONG(_vm_memguard, OID_AUTO, wrapcnt, CTLFLAG_RD, - &memguard_wrap, 0, "MemGuard cursor wrap count"); SYSCTL_ULONG(_vm_memguard, OID_AUTO, numalloc, CTLFLAG_RD, &memguard_succ, 0, "Count of successful MemGuard allocations"); SYSCTL_ULONG(_vm_memguard, OID_AUTO, fail_kva, CTLFLAG_RD, @@ -157,7 +160,7 @@ SYSCTL_ULONG(_vm_memguard, OID_AUTO, frequency_hits, C /* * Return a fudged value to be used for vm_kmem_size for allocating - * the kernel_arena. The memguard memory will be a submap. + * the kernel_arena. */ unsigned long memguard_fudge(unsigned long km_size, const struct vm_map *parent_map) @@ -199,7 +202,8 @@ memguard_fudge(unsigned long km_size, const struct vm_ /* * Initialize the MemGuard mock allocator. All objects from MemGuard come - * out of a single VM map (contiguous chunk of address space). + * out of a single contiguous chunk of kernel address space that is managed + * by a vmem arena. */ void memguard_init(vmem_t *parent) @@ -209,7 +213,6 @@ memguard_init(vmem_t *parent) vmem_alloc(parent, memguard_mapsize, M_BESTFIT | M_WAITOK, &base); vmem_init(memguard_arena, "memguard arena", base, memguard_mapsize, PAGE_SIZE, 0, M_WAITOK); - memguard_cursor = base; memguard_base = base; printf("MEMGUARD DEBUGGING ALLOCATOR INITIALIZED:\n"); @@ -227,15 +230,15 @@ memguard_sysinit(void) struct sysctl_oid_list *parent; parent = SYSCTL_STATIC_CHILDREN(_vm_memguard); - - SYSCTL_ADD_UAUTO(NULL, parent, OID_AUTO, "mapstart", CTLFLAG_RD, - &memguard_base, "MemGuard KVA base"); - SYSCTL_ADD_UAUTO(NULL, parent, OID_AUTO, "maplimit", CTLFLAG_RD, - &memguard_mapsize, "MemGuard KVA size"); -#if 0 - SYSCTL_ADD_ULONG(NULL, parent, OID_AUTO, "mapused", CTLFLAG_RD, - &memguard_map->size, "MemGuard KVA used"); -#endif + SYSCTL_ADD_UAUTO(NULL, parent, OID_AUTO, "mapstart", + CTLFLAG_RD, &memguard_base, + "MemGuard KVA base"); + SYSCTL_ADD_UAUTO(NULL, parent, OID_AUTO, "maplimit", + CTLFLAG_RD, &memguard_mapsize, + "MemGuard KVA size"); + SYSCTL_ADD_PROC(NULL, parent, OID_AUTO, "mapused", + CTLFLAG_RD | CTLTYPE_ULONG, NULL, 0, memguard_sysctl_mapused, "LU", + "MemGuard KVA used"); } SYSINIT(memguard, SI_SUB_KLD, SI_ORDER_ANY, memguard_sysinit, NULL); @@ -288,17 +291,16 @@ memguard_alloc(unsigned long req_size, int flags) { vm_offset_t addr, origaddr; u_long size_p, size_v; - int do_guard, rv; + int do_guard, error, rv; size_p = round_page(req_size); if (size_p == 0) return (NULL); + /* * To ensure there are holes on both sides of the allocation, - * request 2 extra pages of KVA. We will only actually add a - * vm_map_entry and get pages for the original request. Save - * the value of memguard_options so we have a consistent - * value. + * request 2 extra pages of KVA. Save the value of memguard_options + * so that we use a consistent value throughout this function. */ size_v = size_p; do_guard = (memguard_options & MG_GUARD_AROUND) != 0; @@ -317,33 +319,17 @@ memguard_alloc(unsigned long req_size, int flags) memguard_fail_pgs++; goto out; } + /* - * Keep a moving cursor so we don't recycle KVA as long as - * possible. It's not perfect, since we don't know in what - * order previous allocations will be free'd, but it's simple - * and fast, and requires O(1) additional storage if guard - * pages are not used. - * - * XXX This scheme will lead to greater fragmentation of the - * map, unless vm_map_findspace() is tweaked. + * Attempt to avoid address reuse for as long as possible, to increase + * the likelihood of catching a use-after-free. */ - for (;;) { - if (vmem_xalloc(memguard_arena, size_v, 0, 0, 0, - memguard_cursor, VMEM_ADDR_MAX, - M_BESTFIT | M_NOWAIT, &origaddr) == 0) - break; - /* - * The map has no space. This may be due to - * fragmentation, or because the cursor is near the - * end of the map. - */ - if (memguard_cursor == memguard_base) { - memguard_fail_kva++; - addr = (vm_offset_t)NULL; - goto out; - } - memguard_wrap++; - memguard_cursor = memguard_base; + error = vmem_alloc(memguard_arena, size_v, M_NEXTFIT | M_NOWAIT, + &origaddr); + if (error != 0) { + memguard_fail_kva++; + addr = (vm_offset_t)NULL; + goto out; } addr = origaddr; if (do_guard) @@ -355,7 +341,6 @@ memguard_alloc(unsigned long req_size, int flags) addr = (vm_offset_t)NULL; goto out; } - memguard_cursor = addr + size_v; *v2sizep(trunc_page(addr)) = req_size; *v2sizev(trunc_page(addr)) = size_v; memguard_succ++;