Add kern_mmap_racct_check(), a helper to verify limits in vm_mmap*().

Reviewed by:	markj
Tested by:	pho
Sponsored by:	The FreeBSD Foundation
MFC after:	1 week
Differential revision:	https://reviews.freebsd.org/D24652
This commit is contained in:
Konstantin Belousov 2020-09-08 23:48:19 +00:00
parent fbf2a77876
commit 67a659d282
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=365486
2 changed files with 41 additions and 29 deletions

View File

@ -62,6 +62,7 @@ struct sockaddr;
struct stat;
struct thr_param;
struct uio;
struct vm_map;
typedef int (*mmap_check_fp_fn)(struct file *, int, int, int);
@ -197,8 +198,10 @@ int kern_mlock(struct proc *proc, struct ucred *cred, uintptr_t addr,
size_t len);
int kern_mmap(struct thread *td, uintptr_t addr, size_t len, int prot,
int flags, int fd, off_t pos);
int kern_mmap_req(struct thread *td, const struct mmap_req *mrp);
int kern_mmap_racct_check(struct thread *td, struct vm_map *map,
vm_size_t size);
int kern_mmap_maxprot(struct proc *p, int prot);
int kern_mmap_req(struct thread *td, const struct mmap_req *mrp);
int kern_mprotect(struct thread *td, uintptr_t addr, size_t size, int prot);
int kern_msgctl(struct thread *, int, int, struct msqid_ds *);
int kern_msgrcv(struct thread *, int, void *, size_t, long, int, long *);

View File

@ -1509,6 +1509,39 @@ vm_mmap(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
return (error);
}
int
kern_mmap_racct_check(struct thread *td, vm_map_t map, vm_size_t size)
{
int error;
RACCT_PROC_LOCK(td->td_proc);
if (map->size + size > lim_cur(td, RLIMIT_VMEM)) {
RACCT_PROC_UNLOCK(td->td_proc);
return (ENOMEM);
}
if (racct_set(td->td_proc, RACCT_VMEM, map->size + size)) {
RACCT_PROC_UNLOCK(td->td_proc);
return (ENOMEM);
}
if (!old_mlock && map->flags & MAP_WIREFUTURE) {
if (ptoa(pmap_wired_count(map->pmap)) + size >
lim_cur(td, RLIMIT_MEMLOCK)) {
racct_set_force(td->td_proc, RACCT_VMEM, map->size);
RACCT_PROC_UNLOCK(td->td_proc);
return (ENOMEM);
}
error = racct_set(td->td_proc, RACCT_MEMLOCK,
ptoa(pmap_wired_count(map->pmap)) + size);
if (error != 0) {
racct_set_force(td->td_proc, RACCT_VMEM, map->size);
RACCT_PROC_UNLOCK(td->td_proc);
return (error);
}
}
RACCT_PROC_UNLOCK(td->td_proc);
return (0);
}
/*
* Internal version of mmap that maps a specific VM object into an
* map. Called by mmap for MAP_ANON, vm_mmap, shm_mmap, and vn_mmap.
@ -1518,39 +1551,15 @@ vm_mmap_object(vm_map_t map, vm_offset_t *addr, vm_size_t size, vm_prot_t prot,
vm_prot_t maxprot, int flags, vm_object_t object, vm_ooffset_t foff,
boolean_t writecounted, struct thread *td)
{
boolean_t curmap, fitit;
vm_offset_t max_addr;
int docow, error, findspace, rv;
bool curmap, fitit;
curmap = map == &td->td_proc->p_vmspace->vm_map;
if (curmap) {
RACCT_PROC_LOCK(td->td_proc);
if (map->size + size > lim_cur(td, RLIMIT_VMEM)) {
RACCT_PROC_UNLOCK(td->td_proc);
return (ENOMEM);
}
if (racct_set(td->td_proc, RACCT_VMEM, map->size + size)) {
RACCT_PROC_UNLOCK(td->td_proc);
return (ENOMEM);
}
if (!old_mlock && map->flags & MAP_WIREFUTURE) {
if (ptoa(pmap_wired_count(map->pmap)) + size >
lim_cur(td, RLIMIT_MEMLOCK)) {
racct_set_force(td->td_proc, RACCT_VMEM,
map->size);
RACCT_PROC_UNLOCK(td->td_proc);
return (ENOMEM);
}
error = racct_set(td->td_proc, RACCT_MEMLOCK,
ptoa(pmap_wired_count(map->pmap)) + size);
if (error != 0) {
racct_set_force(td->td_proc, RACCT_VMEM,
map->size);
RACCT_PROC_UNLOCK(td->td_proc);
return (error);
}
}
RACCT_PROC_UNLOCK(td->td_proc);
error = kern_mmap_racct_check(td, map, size);
if (error != 0)
return (error);
}
/*