How come the following code executes if buf* is @ rodata segment ?

#include <stdio.h>

char *buf[] = {
char arr_chr[500] = "I AM READ_WRITE";

int main(){
    ((void (*)()) buf[0])();

    printf("%s\n", buf[0]);
    printf("%s\n", arr_chr);

compiled with gcc version 7.3.0 without flags @ x86_64-linux-gnu

file's output:

check: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, not stripped

ida sc

  • It segfaults on my system... which is the 'normal' behavior for this code. I suspect your system to be weird. Anyway, this is definitely NOT about reverse-engineering. – perror Jan 24 '19 at 16:19
  • Kowalski ? This was tested on a fresh Ubuntu VM – Jim West Jan 24 '19 at 18:46
  • Have you tried on a real system, though ? Come on Private, I am sure you can do better than that! :-) – perror Jan 24 '19 at 19:07

I think you mixed up segments and sections on ELF. Unlike PE where sections define how the application is mapped and page permissions, ELF loaders only use segments PT_LOAD to do that. Segments don't have name, so there's nothing like .rodata segment, only .rodata section. You can verify that be setting 0x0 to the field ElfN_Ehdr::e_shoff, it'll still work.

Now regarding the initial question, it seems ELF executable used to have only two PT_LOAD segments, one is R-X and RW-. If a data is const, it'll be stored inside the first segment which is also executable. It's not true anymore on my archlinux.

| improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.