This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/214] sbrk() doesn't detect brk() failures. Malloc doesn't handle sbrk() failures


------- Additional Comments From rsa at us dot ibm dot com  2006-03-10 22:18 -------
Created an attachment (id=914)
 --> (http://sourceware.org/bugzilla/attachment.cgi?id=914&action=view)
analysis of two runs, one with -DDATA_200 the other with -DDATA_300

The attached file highlights data gathered from two tests:
1.) 200 bytes of global data live in the program data segment.
2.) 300 bytes of global data live in the program data segment.

The loader chooses to push __data_start to a page boundary for the 300 byte
example and not for the 200 byte example.  RLIMIT_DATA rlim_cur is set to 1
PAGE.  The kernel addresses soft-limits only at page granularity so anything
less is effectively treated as 1 page, and anything more, as 2, 3, 4, etc.
pages.

1.) The 300 byte example fails setting brk() beyond the initial value.
2.) The 200 byte example allows brk() to push into the next page and fails when
trying to set brk() to a second page.

At least on ppc64 my analysis reveals the following (keeping in mind the
kernel's PAGE granularity for checking RLIMIT_DATA rlim_cur):

1.) Initial curbrk [kernel: mm->start_brk] is always set to start on a PAGE
boundary after _end [kernel: mm->end_data].

2.) newbrk is only checked against RLIMIT_DATA rlim_cur when the newbrk lies on
a page following curbrk.  Effectively this means that RLIMIT_DATA rlim_cur
always starts being checked at __data_start + 1 page.

3.) The loader positions __data_start (on a page boundary or not) based upon a
set of criteria dependent upon the amount of code and data in the program.  I
don't understand how the loader makes the distinction.

4.) If the loader has placed __data_start on a non-page boundary (the code and
data are sufficiently small) the mm->start_brk is set to the next page. 
RLIMIT_DATA starts accounting at the same place as mm->start_brk, a page off of
__data_start.  Subsequent brk() calls are allowed into another page. (case
-DDATA_200).

5.) If there is enough code and/or data the loader will place __data_start on a
page boundary.	The size of the data segment exceeds a page.  RLIMIT_DATA
starts accounting a page off of __data_start, hence before _end.  mm->start_brk
is then set to the page boundary off of _end (already exceeding __data_start +
rlim_cur [1 page]).  The first brk() call will fall on the next page, a
different one than the current brk and the resulting brk exceeds the
RLIMIT_DATA soft limit. (case -DDATA_300)

Here's some implications:
1.) It is misleading when the man page states that you can brk() up to the soft
limit, but this isn't true.  One can break beyond the soft-limit on a page
granularity keeping 2.) in mind.

2.) Depending on the size of the code and amount of program data the loader
inadvertently determines whether you're penalized a page or not when setting 
the RLIMIT_DATA rlim_cur soft-limit.  The brk() sys_call behavior is
unpredictable when RLIMIT_DATA rlim_cur is set.

3.) This could be a loader issue, a man page issue, a kernel issue, or all
three combined.

-- 


http://sourceware.org/bugzilla/show_bug.cgi?id=214

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]