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

Reply via email to