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 – whoopdedoo 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.

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