1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-02 08:42:48 +00:00

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
This commit is contained in:
Mark Johnston 2021-09-07 14:03:52 -04:00
parent a40c4ae866
commit 686aa9287c
2 changed files with 6 additions and 4 deletions

View File

@ -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);

View File

@ -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);