On Fri, Mar 27, 2020 at 3:21 PM Otto Moerbeek <[email protected]> wrote:
> For chunk size 256, there will indeed be 16 chunks in a page. i will
> *not* be 255 in that case, but 15. There is no such thing as
> MALLOC_BYTES. the memset will becomes memset(p->bits, 0xff, 2) and
> set p->bits[0] to to 0xffff The line below it will set p->bits[1] to
> (2<<15) - 1 = 0xffff; So all 16 bits needed are set to 1.
>
> The debug session below is for chunk size 16, so the numbers are different.
>
Yeah, my apologies for the typo. Actually, I was about to write MALLOC_BITS
instead of MALLOC_BYTES.
And, I am requesting you to explain a little bit more. Because all the
observations here are based on the sample code,
int
main(int argc, char **argv) {
char *buff1, *buff2 = NULL;
buff1 = (char *)malloc(8);
strcpy(buff1, argv[1]);
free(buff1);
return 0;
}
So, p->total is different for different sizes as it depends on the bits.
But, as per the sample code given above,
in the init_chunk_info() as given below:
823 static void
824 init_chunk_info(struct dir_info *d, struct chunk_info *p, int bits)
825 {
826 int i;
827
828 if (bits == 0) {
829 p->shift = MALLOC_MINSHIFT;
830 p->total = p->free = MALLOC_PAGESIZE >> p->shift;
831 p->size = 0;
832 p->offset = 0xdead;
833 } else {
834 p->shift = bits;
835 p->total = p->free = MALLOC_PAGESIZE >> p->shift;
836 p->size = 1U << bits;
837 p->offset = howmany(p->total, MALLOC_BITS);
838 }
839 p->canary = (u_short)d->canary1;
840
841 /* set all valid bits in the bitmap */
842 i = p->total - 1;
843 memset(p->bits, 0xff, sizeof(p->bits[0]) * (i / MALLOC_BITS));
844 p->bits[i / MALLOC_BITS] = (2U << (i % MALLOC_BITS)) - 1;
845 }
On line no. 835 we can see that it calculates the p->total and p->free with
MALLOC_PAGESIZE >> p->shift. And, for the sample code, p->shifts = 4. So,
p->total will become 256.
Then, from line no. 842 we can see that i = p->total - 1, which means i
becomes 255.
Then, memset(p->bits, 0xff, 2 * (255 / 16)) => memset(p->bits, 0xff, 30), I
am not able to understand how it is becoming memset(p->bits, 0xff, 2).
You need to look at the bigger picture.
>
> Depending on the chunk size, a different number of bits are needed,
> since the amount of chunks in a page differs.
>
Yes, thanks for remembering me. I have verified with different malloc
requests, like malloc(8) provides bits value = 4, malloc(24) provides bits
value = 5 then malloc(54) provides bits = 6 and malloc(100) provides bits =
7.
In OpenBSD, struct chunk_info is a variable size data structure. In
> alloc_chunk_info() the size needed to store the struct itself plus
> the shorts needed for the bitmap and the canary info (if enabled) is
> computed.
>
> For a chunk of half a page, we need two bits, so a single short is enough.
> For chunk size 16, we need MALLOC_PAGESIZE/16 bits for the bitmap.
> That translates to (MALLOC_PAGESIZE/16)/2 shorts. The rest of the
> calculation adjust for the other fields in chunk_info.
>
So, here it means for chunk size 16, we need 256 bits or 32bytes for the
bitmap. That translates to 128 shorts. What do you mean by 128 shorts here?
I mean is it u_short bit[1], that bit[1] count is 128?
So you are saying that in the alloc_chunk_info() function on line no. 859
as mentioned below:
855
856 if (bits == 0)
857 count = MALLOC_PAGESIZE / MALLOC_MINSIZE;
858 else
859 count = MALLOC_PAGESIZE >> bits;
860
861 size = howmany(count, MALLOC_BITS);
862 size = sizeof(struct chunk_info) + (size - 1) *
sizeof(u_short);
863 if (mopts.chunk_canaries)
864 size += count * sizeof(u_short);
Here, as per the sample code, the value of the bits is 4. So, count = 4096
>> 4 = 256. So, the count variable refers to the number of bitmap bits.
Then, size = (count + (MALLOC_BITS - 1)) / MALLOC_BITS
size = 271 / 16 = 16.
then, from line no. 862 it calculates the minimum size requires for bitmap
including the entire chunk_info structure. Like for count = 256 case, size
= (16 - 1) * 2 = 30. Then if canary then it calculates for the canary.
So, from here, it calculates the size for bitmap like I have already
mentioned above, that memset doing 30 bytes for bits = 4. So, that 30 bytes
comes from here?
Thanks,
Neeraj Pal