git: 686aa9287c6b - main - swap_pager: Handle large swap_pager_reserve() requests

Mark Johnston markj at FreeBSD.org
Tue Sep 7 18:05:46 UTC 2021


The branch main has been updated by markj:

URL: https://cgit.FreeBSD.org/src/commit/?id=686aa9287c6b3658daa2ca0ef1917f2e70a6c07e

commit 686aa9287c6b3658daa2ca0ef1917f2e70a6c07e
Author:     Mark Johnston <markj at FreeBSD.org>
AuthorDate: 2021-09-07 18:03:52 +0000
Commit:     Mark Johnston <markj at FreeBSD.org>
CommitDate: 2021-09-07 18:04:50 +0000

    swap_pager: Handle large swap_pager_reserve() requests
    
    This interface is used solely by md(4) when the MD_RESERVE flag is
    specified, as in `mdconfig -a -t swap -s 1G -o reserve`.  It
    pre-allocates swap blocks for the entire object.
    
    The number of blocks to be reserved is specified as a vm_size_t, but
    swp_pager_getswapspace() can allocate at most INT_MAX blocks.  vm_size_t
    also seems like the incorrect type to use here it refers only to the
    size of the VM object, not the size of a mapping.  So:
    - change the type of "size" in swap_pager_reserve() to vm_pindex_t, and
    - clamp the requested number of blocks for a single
      swp_pager_getswapspace() call to INT_MAX.
    
    Reported by:    syzkaller
    Reviewed by:    dougm, alc, kib
    MFC after:      2 weeks
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D31875
---
 sys/vm/swap_pager.c | 8 +++++---
 sys/vm/swap_pager.h | 2 +-
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/sys/vm/swap_pager.c b/sys/vm/swap_pager.c
index 63f0d22ed705..6d64ff883966 100644
--- a/sys/vm/swap_pager.c
+++ b/sys/vm/swap_pager.c
@@ -82,6 +82,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/disklabel.h>
 #include <sys/eventhandler.h>
 #include <sys/fcntl.h>
+#include <sys/limits.h>
 #include <sys/lock.h>
 #include <sys/kernel.h>
 #include <sys/mount.h>
@@ -977,15 +978,16 @@ swap_pager_freespace(vm_object_t object, vm_pindex_t start, vm_size_t size)
  *	Returns 0 on success, -1 on failure.
  */
 int
-swap_pager_reserve(vm_object_t object, vm_pindex_t start, vm_size_t size)
+swap_pager_reserve(vm_object_t object, vm_pindex_t start, vm_pindex_t size)
 {
 	daddr_t addr, blk, n_free, s_free;
-	int i, j, n;
+	vm_pindex_t i, j;
+	int n;
 
 	swp_pager_init_freerange(&s_free, &n_free);
 	VM_OBJECT_WLOCK(object);
 	for (i = 0; i < size; i += n) {
-		n = size - i;
+		n = MIN(size - i, INT_MAX);
 		blk = swp_pager_getswapspace(&n);
 		if (blk == SWAPBLK_NONE) {
 			swp_pager_meta_free(object, start, i);
diff --git a/sys/vm/swap_pager.h b/sys/vm/swap_pager.h
index 20ff70acc3d8..6761d4f99ee4 100644
--- a/sys/vm/swap_pager.h
+++ b/sys/vm/swap_pager.h
@@ -78,7 +78,7 @@ void swap_pager_copy(vm_object_t, vm_object_t, vm_pindex_t, int);
 vm_pindex_t swap_pager_find_least(vm_object_t object, vm_pindex_t pindex);
 void swap_pager_swap_init(void);
 int swap_pager_nswapdev(void);
-int swap_pager_reserve(vm_object_t, vm_pindex_t, vm_size_t);
+int swap_pager_reserve(vm_object_t, vm_pindex_t, vm_pindex_t);
 void swap_pager_status(int *total, int *used);
 u_long swap_pager_swapped_pages(vm_object_t object);
 void swapoff_all(void);


More information about the dev-commits-src-all mailing list