Bug 11758

Summary: a program's data segment grows beyond RLIMIT_DATA limit set by setrlimit
Product: Memory Management Reporter: L. Nieroda (lnieroda)
Component: OtherAssignee: Andrew Morton (akpm)
Status: CLOSED OBSOLETE    
Severity: normal CC: alan, david.w.h.chin, fion2009.z, matt
Priority: P1    
Hardware: All   
OS: Linux   
Kernel Version: 2.6.27 Subsystem:
Regression: No Bisected commit-id:
Attachments: mmap.c class where we change rlimit data condition
task_mmu.c for data limit

Description L. Nieroda 2008-10-14 07:01:25 UTC
Latest working kernel version: N/A
Earliest failing kernel version: N/A
Distribution: Ubuntu
Hardware Environment: Intel CoreDuo E8400, 4 GB RAM
Software Environment: Ubuntu 8.04
Problem Description: I'm setting RLIMIT_DATA with the setrlimit system call and then proceed to allocate memory with malloc or "new" grossly above that limit, however, the memory is allocated and used without a problem. I've tried this with and without swap to make sure that the memory isn't allocated within it. The same check with RLIMIT_AS returns the expected result: memory allocation error. Am I missing something?

Steps to reproduce:
I've made a small c program to reproduce this behaviour:

---
#include <stdio.h>
#include <sys/resource.h>
#include <errno.h>


#define SOFT_LIMIT 100000
#define HARD_LIMIT 100000
#define ALLOCATED  150000

void check_rlimit(int resource) {
    char *data = NULL;
    struct rlimit rlp; 

    rlp.rlim_cur = SOFT_LIMIT; rlp.rlim_max=HARD_LIMIT;

    //setting the limits
    if (setrlimit(resource, &rlp) == -1) {
        perror("setrlimit");
        exit(1);
    }
    
    //check if limits are set
    if (getrlimit(resource, &rlp) == -1) {
      perror("getrlimit");
      exit(1);
    }

    printf("softlimit:  %d \n", rlp.rlim_cur); 
    printf("hardlimit:  %d \n", rlp.rlim_max); 

    fflush(stdout);
    
    //allocate over the limit
    printf("Allocating %d bytes.\n",ALLOCATED);
    data = (char *)malloc(ALLOCATED);
    if (data == NULL) {
      //printf("malloc failed with errno=%d\n", errno);
      perror("malloc");
      exit(1);
    }
    free(data);
}

int main(int argc, char *argv[]) {

  check_rlimit(RLIMIT_DATA);
  check_rlimit(RLIMIT_AS);

  return 0;
  exit(0);
}
---

The output is:
softlimit:  100000 
hardlimit:  100000 
Allocating 150000 bytes.
softlimit:  100000 
hardlimit:  100000 
Allocating 150000 bytes.
malloc: Cannot allocate memory

Any ideas?

Regards,
Lech Nieroda
Comment 1 david chosrova 2008-11-16 10:19:03 UTC
(In reply to comment #0)

I found this, it might help http://marc.info/?l=linux-kernel&m=118064795330579&w=2


> Latest working kernel version: N/A
> Earliest failing kernel version: N/A
> Distribution: Ubuntu
> Hardware Environment: Intel CoreDuo E8400, 4 GB RAM
> Software Environment: Ubuntu 8.04
> Problem Description: I'm setting RLIMIT_DATA with the setrlimit system call
> and
> then proceed to allocate memory with malloc or "new" grossly above that
> limit,
> however, the memory is allocated and used without a problem. I've tried this
> with and without swap to make sure that the memory isn't allocated within it.
> The same check with RLIMIT_AS returns the expected result: memory allocation
> error. Am I missing something?
> 
> Steps to reproduce:
> I've made a small c program to reproduce this behaviour:
> 
> ---
> #include <stdio.h>
> #include <sys/resource.h>
> #include <errno.h>
> 
> 
> #define SOFT_LIMIT 100000
> #define HARD_LIMIT 100000
> #define ALLOCATED  150000
> 
> void check_rlimit(int resource) {
>     char *data = NULL;
>     struct rlimit rlp; 
> 
>     rlp.rlim_cur = SOFT_LIMIT; rlp.rlim_max=HARD_LIMIT;
> 
>     //setting the limits
>     if (setrlimit(resource, &rlp) == -1) {
>         perror("setrlimit");
>         exit(1);
>     }
> 
>     //check if limits are set
>     if (getrlimit(resource, &rlp) == -1) {
>       perror("getrlimit");
>       exit(1);
>     }
> 
>     printf("softlimit:  %d \n", rlp.rlim_cur); 
>     printf("hardlimit:  %d \n", rlp.rlim_max); 
> 
>     fflush(stdout);
> 
>     //allocate over the limit
>     printf("Allocating %d bytes.\n",ALLOCATED);
>     data = (char *)malloc(ALLOCATED);
>     if (data == NULL) {
>       //printf("malloc failed with errno=%d\n", errno);
>       perror("malloc");
>       exit(1);
>     }
>     free(data);
> }
> 
> int main(int argc, char *argv[]) {
> 
>   check_rlimit(RLIMIT_DATA);
>   check_rlimit(RLIMIT_AS);
> 
>   return 0;
>   exit(0);
> }
> ---
> 
> The output is:
> softlimit:  100000 
> hardlimit:  100000 
> Allocating 150000 bytes.
> softlimit:  100000 
> hardlimit:  100000 
> Allocating 150000 bytes.
> malloc: Cannot allocate memory
> 
> Any ideas?
> 
> Regards,
> Lech Nieroda
> 
Comment 2 Matt McCutchen 2010-03-09 22:46:04 UTC
Yep, when brk fails because of RLIMIT_DATA, glibc switches to anonymous mmap instead.

https://bugzilla.redhat.com/show_bug.cgi?id=569714
http://lists.fedoraproject.org/pipermail/users/2010-March/368014.html
Comment 3 David Chin 2010-10-18 21:13:49 UTC
Same issue (reported by Matt McCutchen) being tracked on Fedora/RedHat's bugzilla:

https://bugzilla.redhat.com/show_bug.cgi?id=582072
Comment 4 Waseem 2011-04-21 20:03:28 UTC
Created attachment 54912 [details]
mmap.c class where we change rlimit data condition

Hi,

Yes We got same issue on linux kernel 2.6.32.29. We identified solution by doing some changes in files: mmap.c and task_mmu.c which are attached here. Basically we modify conditions regarding private memory of process(rlimit). We shall upload patch soon. Please find attached file, you can replace these files and compile your kernel and once you done it will will not show you this  bug any more.

Thanks

Waseem Hassan 
Saad Waqas
Comment 5 Waseem 2011-04-21 20:04:21 UTC
Created attachment 54922 [details]
task_mmu.c for data limit
Comment 6 Andrew Morton 2011-04-21 20:12:28 UTC
Yes, we'd need to see the patch, not the whole files.

Please send the patch via email, not via bugzilla.  Send it as a proper patch as per Documentation/SubmittingPatches.  Send it to

Andrew Morton <akpm@linux-foundation.org>, linux-mm@kvack.org

Thanks.