Ingo Schwarze wrote:
> Hi,
> 
> when p->p_rlimit[RLIMIT_DATA].rlim_cur < ptoa(p->p_vmspace->vm_dused),
> the following comparison fails because the subtraction wraps around
> to huge positive values.
> 
> I noticed this because i tried to do systematic testing of specific
> malloc failure codepaths.  But whenever i used setrlimit(2) to set
> a low RLIMIT_DATA, a subsequent malloc(3) with a big argument always
> succeeded.
> 
> It may be unsusual for a program to lower its own RLIMIT_DATA, and
> i'm neither sure whether there are other use cases besides testing
> nor whether there are other ways to arrive in a situation with
> p->p_rlimit[RLIMIT_DATA].rlim_cur < ptoa(p->p_vmspace->vm_dused)
> besides late setrlimit(2) to a low value.
> 
> But even if there are no use cases besides testing, do we want
> to have an unsigned comparison in the kernel that can wrap around?
> 
> I can hardly believe i'm sending such a diff...  :-o
> 
> I'm running it right now.  So far, i noticed no regressions,
> and testing of malloc failure codepaths has become much easier.
> I consider that useful to make out software better.
> 
> What do you think?

Agreed that we need to check for wraparound here.

For some reason the 
p->p_rlimit[RLIMIT_DATA].rlim_cur - size < ptoa(p->p_vmspace->vm_dused)
confuses me, although the operands compared to the original check are
just re-arranged.

How about writing it like this?

ptoa(p->p_vmspace->vm_used) > p->p_rlimit[RLIMIT_DATA].rlim_cur ||
size > (p->p_rlimit[RLIMIT_DATA].rlim_cur - ptoa(p->p_vmspace->vm_dused))
 
> Yours,
>   Ingo
> 
> 
> Index: uvm/uvm_mmap.c
> ===================================================================
> RCS file: /cvs/src/sys/uvm/uvm_mmap.c,v
> retrieving revision 1.130
> diff -u -p -r1.130 uvm_mmap.c
> --- uvm/uvm_mmap.c    1 Jun 2016 04:53:54 -0000       1.130
> +++ uvm/uvm_mmap.c    2 Jun 2016 01:23:20 -0000
> @@ -526,8 +526,9 @@ sys_mmap(struct proc *p, void *v, regist
>               }
>               if ((flags & MAP_ANON) != 0 ||
>                   ((flags & MAP_PRIVATE) != 0 && (prot & PROT_WRITE) != 0)) {
> -                     if (size >
> -                         (p->p_rlimit[RLIMIT_DATA].rlim_cur - 
> ptoa(p->p_vmspace->vm_dused))) {
> +                     if (p->p_rlimit[RLIMIT_DATA].rlim_cur < size ||
> +                         p->p_rlimit[RLIMIT_DATA].rlim_cur - size <
> +                         ptoa(p->p_vmspace->vm_dused)) {
>                               error = ENOMEM;
>                               goto out;
>                       }
> @@ -545,8 +546,9 @@ is_anon:  /* label for SunOS style /dev/z
>  
>               if ((flags & MAP_ANON) != 0 ||
>                   ((flags & MAP_PRIVATE) != 0 && (prot & PROT_WRITE) != 0)) {
> -                     if (size >
> -                         (p->p_rlimit[RLIMIT_DATA].rlim_cur - 
> ptoa(p->p_vmspace->vm_dused))) {
> +                     if (p->p_rlimit[RLIMIT_DATA].rlim_cur < size ||
> +                         p->p_rlimit[RLIMIT_DATA].rlim_cur - size <
> +                         ptoa(p->p_vmspace->vm_dused)) {
>                               return ENOMEM;
>                       }
>               }
> 

Reply via email to