Skip to content

Commit 2217b98

Browse files
jcmvbkbcGreg Ungerer
authored andcommitted
binfmt_flat: revert "binfmt_flat: don't offset the data start"
binfmt_flat loader uses the gap between text and data to store data segment pointers for the libraries. Even in the absence of shared libraries it stores at least one pointer to the executable's own data segment. Text and data can go back to back in the flat binary image and without offsetting data segment last few instructions in the text segment may get corrupted by the data segment pointer. Fix it by reverting commit a235722 ("binfmt_flat: don't offset the data start"). Cc: [email protected] Fixes: a235722 ("binfmt_flat: don't offset the data start") Signed-off-by: Max Filippov <[email protected]> Signed-off-by: Greg Ungerer <[email protected]>
1 parent d012a71 commit 2217b98

File tree

1 file changed

+12
-8
lines changed

1 file changed

+12
-8
lines changed

fs/binfmt_flat.c

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -576,7 +576,7 @@ static int load_flat_file(struct linux_binprm *bprm,
576576
goto err;
577577
}
578578

579-
len = data_len + extra;
579+
len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
580580
len = PAGE_ALIGN(len);
581581
realdatastart = vm_mmap(NULL, 0, len,
582582
PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
@@ -590,7 +590,9 @@ static int load_flat_file(struct linux_binprm *bprm,
590590
vm_munmap(textpos, text_len);
591591
goto err;
592592
}
593-
datapos = ALIGN(realdatastart, FLAT_DATA_ALIGN);
593+
datapos = ALIGN(realdatastart +
594+
MAX_SHARED_LIBS * sizeof(unsigned long),
595+
FLAT_DATA_ALIGN);
594596

595597
pr_debug("Allocated data+bss+stack (%u bytes): %lx\n",
596598
data_len + bss_len + stack_len, datapos);
@@ -620,7 +622,7 @@ static int load_flat_file(struct linux_binprm *bprm,
620622
memp_size = len;
621623
} else {
622624

623-
len = text_len + data_len + extra;
625+
len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(u32);
624626
len = PAGE_ALIGN(len);
625627
textpos = vm_mmap(NULL, 0, len,
626628
PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
@@ -635,7 +637,9 @@ static int load_flat_file(struct linux_binprm *bprm,
635637
}
636638

637639
realdatastart = textpos + ntohl(hdr->data_start);
638-
datapos = ALIGN(realdatastart, FLAT_DATA_ALIGN);
640+
datapos = ALIGN(realdatastart +
641+
MAX_SHARED_LIBS * sizeof(u32),
642+
FLAT_DATA_ALIGN);
639643

640644
reloc = (__be32 __user *)
641645
(datapos + (ntohl(hdr->reloc_start) - text_len));
@@ -652,9 +656,8 @@ static int load_flat_file(struct linux_binprm *bprm,
652656
(text_len + full_data
653657
- sizeof(struct flat_hdr)),
654658
0);
655-
if (datapos != realdatastart)
656-
memmove((void *)datapos, (void *)realdatastart,
657-
full_data);
659+
memmove((void *) datapos, (void *) realdatastart,
660+
full_data);
658661
#else
659662
/*
660663
* This is used on MMU systems mainly for testing.
@@ -710,7 +713,8 @@ static int load_flat_file(struct linux_binprm *bprm,
710713
if (IS_ERR_VALUE(result)) {
711714
ret = result;
712715
pr_err("Unable to read code+data+bss, errno %d\n", ret);
713-
vm_munmap(textpos, text_len + data_len + extra);
716+
vm_munmap(textpos, text_len + data_len + extra +
717+
MAX_SHARED_LIBS * sizeof(u32));
714718
goto err;
715719
}
716720
}

0 commit comments

Comments
 (0)