On Wed, Mar 18, 2020 at 07:29:51AM +0530, Neeraj Pal wrote: > On Fri, Mar 13, 2020, at 11:45 AM Otto Moerbeek <o...@drijf.net> wrote: > > > > Please indent your code snippets. > yeah, my apologies. I shall indent the code snippets. > > > > > di_info is special. Having a guard page on both sides for regular > > allocation can be done, but would waste more pages. Note that > > allocations are already spread throughout the address space, so it is > > very likely that an allocation is surrounded by unmapped pages. > > > Okay, So, as from omalloc_poolinit() code it is not there, but we can do > but it will be wastage of one-page memory and also entire address space is > spread with unmapped pages. So, it is very likely that there will some > unmapped page beside dir_info in the memory. > > > > > We need two pages to store dir_info. > > > > > > > Now, MMAPNONE maps up to len (8192 + (4096 * 2)) = 16384 > > > > We allocate 4 pages prot none. > > > > > then, mprotecting the pages through p + MALLOC_PAGESIZE + DIR_INFO_RSZ > - 1 > > > > the two middle pages are r/w. > > > > > d_avail = (8192 - 4824) >> 4 = 3368 >> 4 = 210 > > > > > > Now, d = (p + MALLOC_PAGESIZE + (random_no_under_210 << 4) > > > > di_info ends up on an aligned address somewhere in the middle pages on > > an offset between 0 and (210<<4) = 0..3360, counting from the start of > > the two middle pages. > Thank you for the information. So, it is like [(p + MALLOC_PAGESIZE) + > (0..3360)]. It is kind of like array, For example, let's suppose, x = p + > MALLOC_PAGESIZE. So, it will be x[0..3360]. > Am I right? > > > > MALLOC_CHUNK_LISTS could be increased at the cost of overhead. > > MALLOC_MAXSHIFT cannot, it is the shift of the max chunk size that fits in > > a page. > Okay. I understood. And, yeah more randomization means more cost overhead. > > Thank you, Otto, for your detailed information. > > Please find the code below: > > 948 /* > 949 * Allocate a chunk > 950 */ > 951 static void * > 952 malloc_bytes(struct dir_info *d, size_t size, void *f) > 953 { > 954 u_int i, r; > 955 int j, listnum; > 956 size_t k; > 957 u_short *lp; > 958 struct chunk_info *bp; > 959 void *p; > 960 > 961 if (mopts.malloc_canary != (d->canary1 ^ > (u_int32_t)(uintptr_t)d) || > 962 d->canary1 != ~d->canary2) > 963 wrterror(d, "internal struct corrupt"); > 964 > 965 j = find_chunksize(size); > 966 > 967 r = ((u_int)getrbyte(d) << 8) | getrbyte(d); > 968 listnum = r % MALLOC_CHUNK_LISTS; > 969 /* If it's empty, make a page more of that size chunks */ > 970 if ((bp = LIST_FIRST(&d->chunk_dir[j][listnum])) == NULL) { > 971 bp = omalloc_make_chunks(d, j, listnum); > 972 if (bp == NULL) > 973 return NULL; > 974 } > 975 > 976 if (bp->canary != (u_short)d->canary1) > 977 wrterror(d, "chunk info corrupted"); > > > Here, in the code mentioned above, we can see that on line 961 and > line 976. I don't understand why it is checking for > canaries of malloc_readonly with d and then allocated chunk bp with d, > because I have seen that validation of canary > happens in free(3) not in malloc(3). So, it is like there may be some > cases where one can corrupt these also??
There are several types of canaries. They try to detect corruption of various meta data structures. There are alo canaries for user allocated data, they are enabled with the C option. > > > 978 > 979 i = (r / MALLOC_CHUNK_LISTS) & (bp->total - 1); > 980 > 981 /* start somewhere in a short */ > 982 lp = &bp->bits[i / MALLOC_BITS]; > 983 if (*lp) { > 984 j = i % MALLOC_BITS; > 985 k = ffs(*lp >> j); > 986 if (k != 0) { > 987 k += j - 1; > 988 goto found; > 989 } > 990 } > 991 /* no bit halfway, go to next full short */ > 992 i /= MALLOC_BITS; > 993 for (;;) { > 994 if (++i >= bp->total / MALLOC_BITS) > 995 i = 0; > 996 lp = &bp->bits[i]; > 997 if (*lp) { > 998 k = ffs(*lp) - 1; > 999 break; > 1000 } > 1001 } > 1002 found: > 1003 #ifdef MALLOC_STATS > 1004 if (i == 0 && k == 0) { > 1005 struct region_info *r = find(d, bp->page); > 1006 r->f = f; > 1007 } > 1008 #endif > 1009 > 1010 *lp ^= 1 << k; > 1011 > 1012 /* If there are no more free, remove from free-list */ > 1013 if (--bp->free == 0) > 1014 LIST_REMOVE(bp, entries); > 1015 > 1016 /* Adjust to the real offset of that chunk */ > 1017 k += (lp - bp->bits) * MALLOC_BITS; > 1018 > 1019 if (mopts.chunk_canaries && size > 0) > 1020 bp->bits[bp->offset + k] = size; > 1021 > 1022 k <<= bp->shift; > 1023 > 1024 p = (char *)bp->page + k; > 1025 if (bp->size > 0) { > 1026 if (d->malloc_junk == 2) > 1027 memset(p, SOME_JUNK, bp->size); > 1028 else if (mopts.chunk_canaries) > 1029 fill_canary(p, size, bp->size); > 1030 } > 1031 return p; > 1032 } > > And, the calculations above, is it for calculating the offset in the page, > that is, k. Because I have seen that during free(3) operations, it again > calculates this offset to find the same. So, is it doing only offset > calculation? In general addding an int to a pointer calculates an offset, so yes. Study whats the role of p and k is. Let the code speak. If you fail to understand parts, study further and play with it. You'll learn more from that than asking for confirmation all the time. -Otto > > Please confirm. > > Regards, > Neeraj