kernel: catch address overflow in syssegfree()
the "to" address can overflow in syssegfree() causing wrong number of pages to be passed to mfreeseg(). with the current implementation of mfreeseg() however, this doesnt cause any data corruption but was just freeing an unexpected number of pages. this change checks for this condition in syssegfree() and errors out instead. also mfreeseg() was changed to take ulong argument for number of pages instead of int to keep it consistent with other routines that work with page counts.
This commit is contained in:
parent
0c705580ab
commit
fcc336b902
3 changed files with 18 additions and 12 deletions
|
@ -167,7 +167,7 @@ void* mallocalign(ulong, ulong, long, ulong);
|
|||
void mallocsummary(void);
|
||||
Block* mem2bl(uchar*, int);
|
||||
ulong mcountseg(Segment*);
|
||||
void mfreeseg(Segment*, uintptr, int);
|
||||
void mfreeseg(Segment*, uintptr, ulong);
|
||||
void microdelay(int);
|
||||
uvlong mk64fract(uvlong, uvlong);
|
||||
void mkqid(Qid*, vlong, ulong, int);
|
||||
|
|
|
@ -479,12 +479,15 @@ mcountseg(Segment *s)
|
|||
* called with s locked
|
||||
*/
|
||||
void
|
||||
mfreeseg(Segment *s, uintptr start, int pages)
|
||||
mfreeseg(Segment *s, uintptr start, ulong pages)
|
||||
{
|
||||
int i, j, size;
|
||||
uintptr soff;
|
||||
Page *pg;
|
||||
|
||||
if(pages == 0)
|
||||
return;
|
||||
|
||||
if((s->type&SG_TYPE) == SG_PHYSICAL)
|
||||
return;
|
||||
|
||||
|
@ -500,12 +503,12 @@ mfreeseg(Segment *s, uintptr start, int pages)
|
|||
j = (soff&(PTEMAPMEM-1))/BY2PG;
|
||||
|
||||
size = s->mapsize;
|
||||
for(i = soff/PTEMAPMEM; i < size; i++) {
|
||||
if(pages <= 0)
|
||||
return;
|
||||
for(i = soff/PTEMAPMEM; i < size; i++, j = 0) {
|
||||
if(s->map[i] == nil) {
|
||||
pages -= PTEPERTAB-j;
|
||||
j = 0;
|
||||
j = PTEPERTAB - j;
|
||||
if(j >= pages)
|
||||
return;
|
||||
pages -= j;
|
||||
continue;
|
||||
}
|
||||
while(j < PTEPERTAB) {
|
||||
|
@ -518,7 +521,6 @@ mfreeseg(Segment *s, uintptr start, int pages)
|
|||
return;
|
||||
j++;
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -823,19 +823,23 @@ syssegfree(va_list list)
|
|||
uintptr from, to;
|
||||
|
||||
from = va_arg(list, uintptr);
|
||||
to = va_arg(list, ulong);
|
||||
to += from;
|
||||
if(to < from)
|
||||
error(Ebadarg);
|
||||
s = seg(up, from, 1);
|
||||
if(s == nil)
|
||||
error(Ebadarg);
|
||||
to = va_arg(list, ulong);
|
||||
to += from;
|
||||
to &= ~(BY2PG-1);
|
||||
from = PGROUND(from);
|
||||
|
||||
if(from >= to) {
|
||||
qunlock(s);
|
||||
return 0;
|
||||
}
|
||||
if(to > s->top) {
|
||||
qunlock(s);
|
||||
error(Ebadarg);
|
||||
}
|
||||
|
||||
mfreeseg(s, from, (to - from) / BY2PG);
|
||||
qunlock(s);
|
||||
flushmmu();
|
||||
|
|
Loading…
Reference in a new issue