LINUX.ORG.RU

Как MAP_GROWSDOWN в mmap?

 , , ,


0

2

Маны обещают магию, что оно по мере необходимости будет само ммапиться. Но магия не работает и процесс сегфолтится. Чяднт?

#include <stdio.h>
#include <sys/mman.h>


int main(void)
{
        unsigned char *foo = mmap(NULL, 0x2000, PROT_READ | PROT_WRITE,
                        MAP_PRIVATE | MAP_ANONYMOUS | MAP_GROWSDOWN | MAP_STACK,
                        -1, 0);
        if (foo == MAP_FAILED) {
                perror("mmap fail");
                return 1;
        }

        printf("%p\n", foo);

        puts("press enter to continue");
        getchar();

        foo[0] = 0x42;
        foo[1] = 0x42;

        puts("press enter to continue");
        getchar();

        foo[-1] = 0x42;

        return 0;
}

Ответ на: комментарий от suuaq

Дреппер сказал, что флаг уберёт, а флаг не убран.

остались только дефайны, наталкивающие на правило «we don't break userspace»

$ grep MAP_GROWSDOWN ~/devel/linux-4.19.8/ -r
/home/sbauer/devel/linux-4.19.8/fs/binfmt_elf_fdpic.c:                                   MAP_UNINITIALIZED | MAP_GROWSDOWN,
/home/sbauer/devel/linux-4.19.8/usr/include/asm-generic/mman.h:#define MAP_GROWSDOWN    0x0100          /* stack-like segment */
/home/sbauer/devel/linux-4.19.8/include/linux/mman.h:           | MAP_GROWSDOWN \
/home/sbauer/devel/linux-4.19.8/include/linux/mman.h:   return _calc_vm_trans(flags, MAP_GROWSDOWN,  VM_GROWSDOWN ) |
/home/sbauer/devel/linux-4.19.8/include/uapi/asm-generic/mman.h:#define MAP_GROWSDOWN   0x0100          /* stack-like segment */
/home/sbauer/devel/linux-4.19.8/arch/xtensa/include/uapi/asm/mman.h:#define MAP_GROWSDOWN       0x1000          /* stack-like segment */
/home/sbauer/devel/linux-4.19.8/arch/parisc/include/uapi/asm/mman.h:#define MAP_GROWSDOWN       0x8000          /* stack-like segment */
/home/sbauer/devel/linux-4.19.8/arch/powerpc/include/uapi/asm/mman.h:#define MAP_GROWSDOWN      0x0100          /* stack-like segment */
/home/sbauer/devel/linux-4.19.8/arch/mips/include/uapi/asm/mman.h:#define MAP_GROWSDOWN 0x1000          /* stack-like segment */
/home/sbauer/devel/linux-4.19.8/arch/sparc/include/uapi/asm/mman.h:#define MAP_GROWSDOWN        0x0200          /* stack-like segment */
/home/sbauer/devel/linux-4.19.8/arch/alpha/include/uapi/asm/mman.h:#define MAP_GROWSDOWN        0x01000         /* stack-like segment */
/home/sbauer/devel/linux-4.19.8/tools/include/uapi/asm-generic/mman.h:#define MAP_GROWSDOWN     0x0100          /* stack-like segment */
/home/sbauer/devel/linux-4.19.8/tools/arch/xtensa/include/uapi/asm/mman.h:#define MAP_GROWSDOWN 0x1000
/home/sbauer/devel/linux-4.19.8/tools/arch/parisc/include/uapi/asm/mman.h:#define MAP_GROWSDOWN 0x8000
/home/sbauer/devel/linux-4.19.8/tools/arch/powerpc/include/uapi/asm/mman.h:#define MAP_GROWSDOWN        0x0100
/home/sbauer/devel/linux-4.19.8/tools/arch/mips/include/uapi/asm/mman.h:#define MAP_GROWSDOWN   0x1000
/home/sbauer/devel/linux-4.19.8/tools/arch/sparc/include/uapi/asm/mman.h:#define MAP_GROWSDOWN  0x0200
/home/sbauer/devel/linux-4.19.8/tools/arch/alpha/include/uapi/asm/mman.h:#define MAP_GROWSDOWN  0x01000

metawishmaster ★★★★★
()
Ответ на: комментарий от metawishmaster

Похоже в ядре этот флаг преобразовывается в VM_GROWSDOWN, который таки используется.

Видимо возможности этого флага как-то сильно ограничили, но до конца не удалили. Поэтому он работает не так как обещано маном.

Гуглятся обрывки информации о том, что этот флаг всё ещё используется для стека основного потока приложения, но стеки потоков рулятся в libc полностью силами юзерспейса. То есть видимо обработкой соответствующих сигналов с последующим подсовыванием свежей страницы памяти туда, где упало. Либо просто выделяют с очень большим запасом и надеются, что ядро не будет выделять эти страницы физически до того, как туда кто-то попытается записать что-то.

Чтобы детально разобрать как работает это хрень, надо читать исходники ядра и libc.

Deleted
()
Последнее исправление: Deleted (всего исправлений: 2)
Ответ на: комментарий от Deleted

да, я тоже увидел, но переключился на другую задачу :(

сейчас просто проверил, до куда можно добежать кодом выше - последняя успешная запись была в foo[0x4fff]...

metawishmaster ★★★★★
()
Ответ на: комментарий от metawishmaster

сейчас просто проверил, до куда можно добежать кодом выше - последняя успешная запись была в foo[0x4fff]...

Ушёл в следущую заэммапеную область наверное. Смотри /proc/<pid>/maps на паузах.

suuaq
() автор топика
Ответ на: комментарий от suuaq

все статично :-\


5621b3069000-5621b306a000 r-xp 00000000 08:02 18095887 /home/sbauer/devel/mmap_growsdown
5621b3269000-5621b326a000 r--p 00000000 08:02 18095887 /home/sbauer/devel/mmap_growsdown
5621b326a000-5621b326b000 rw-p 00001000 08:02 18095887 /home/sbauer/devel/mmap_growsdown
5621b3692000-5621b36b3000 rw-p 00000000 00:00 0 [heap]
7f148ff15000-7f14900aa000 r-xp 00000000 08:01 658973 /lib/x86_64-linux-gnu/libc-2.24.so
7f14900aa000-7f14902aa000 ---p 00195000 08:01 658973 /lib/x86_64-linux-gnu/libc-2.24.so
7f14902aa000-7f14902ae000 r--p 00195000 08:01 658973 /lib/x86_64-linux-gnu/libc-2.24.so
7f14902ae000-7f14902b0000 rw-p 00199000 08:01 658973 /lib/x86_64-linux-gnu/libc-2.24.so
7f14902b0000-7f14902b4000 rw-p 00000000 00:00 0
7f14902b4000-7f14902d7000 r-xp 00000000 08:01 658937 /lib/x86_64-linux-gnu/ld-2.24.so
7f149049d000-7f149049f000 rw-p 00000000 00:00 0
7f14904d2000-7f14904d4000 rw-p 00000000 00:00 0
7f14904d4000-7f14904d7000 rw-p 00000000 00:00 0
7f14904d7000-7f14904d8000 r--p 00023000 08:01 658937 /lib/x86_64-linux-gnu/ld-2.24.so
7f14904d8000-7f14904d9000 rw-p 00024000 08:01 658937 /lib/x86_64-linux-gnu/ld-2.24.so
7f14904d9000-7f14904da000 rw-p 00000000 00:00 0
7ffd1940c000-7ffd1942d000 rw-p 00000000 00:00 0 [stack]
7ffd1951c000-7ffd1951f000 r--p 00000000 00:00 0 [vvar]
7ffd1951f000-7ffd19521000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

metawishmaster ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.