Господа, здравствуйте!Меня интересует такой вопрос - можно ли в 64х-битном Linux'е запустить процесс так, чтобы указатели, которые он получает, допустим, при аллокации памяти, гарантировано вылезали за 32 бита? Еще лучше, чтобы адресное пространство ниже 32х бит было защищено, т.е. при попытке обращения туда мы ловили сегфолт.
Зачем это надо : есть очень большой и разлапистый SDK, который разрабатывался под х86 и сейчас адаптируется под x64. Обрезание указателей до 32х бит в нем - common case. Т.к. ядро в основном грузит все это хозяйство и раздает адреса ниже 4х Гб, наверняка многие подобные обрезания остались незамеченными. Если сделать так, как я хочу, можно будет сразу отловить кучу ошибок.
Пока я пытаюсь перед запуском SDK съесть 4-5Гб посредством мелких malloc'ов по 4096 байт, и потом защитить это через mprotect, но не очень получается, ядро меня не спрашивает, где выделять память, да еще и mprotect требует страничного форматирования. С mmap'ом тоже пока не выгорает.
Наверняка это распространенный прием, и умные люди уже отработали подобную технологию. Любые предложения приветствуются, заранее спасибо!
погоди, адреса же виртуальные. то есть, достаточно произвольные. какая разница, что за число в указателе лежит....
заюзать свой менеджер памяти, и таблицу для подстановки, отдаешь гарантированно 64бит указатель, понятно что медленно, но гарантированно и работоспособно.
>С mmap'ом тоже пока не выгорает.Должно выгореть с анонимным ммапом, MAP_ANON + (возможно) MAP_FIXED, и адрес соответственно адрес выше чем 0xffffffff.
То есть, где-то в программе надо объявить свои malloc/new free/delete работающие с памятью, полученной через mmap(0xffffffff, size, PROT_READ|WRITE, MAP_ANONYMOUS). Соответственно во free/delete делать munmap, размеры выделенных блоков либо хранить в какой-нибудь мапе, либо изначально создавать большой mmap() выше 4х гигов и в нём выделять память.
Интересная проблемка.
>Наверняка это распространенный прием, и умные люди уже отработали подобную технологию.Умные люди не обрезают указатели но 32 бит, потому что это несусветная дикость, ничего распространенного тут нет и быть не может.
Чтобы протестировать это поделие, соберите статический бинарник с тестом, и запустите их столько, чтобы они тарантированно заняли > 4ГБ (достаточно пяти, в каждом из которых дополнительно маллочить гиг).
>[оверквотинг удален]
>подобные обрезания остались незамеченными. Если сделать так, как я хочу, можно
>будет сразу отловить кучу ошибок.
>
>Пока я пытаюсь перед запуском SDK съесть 4-5Гб посредством мелких malloc'ов по
>4096 байт, и потом защитить это через mprotect, но не очень
>получается, ядро меня не спрашивает, где выделять память, да еще и
>mprotect требует страничного форматирования. С mmap'ом тоже пока не выгорает.
>
>Наверняка это распространенный прием, и умные люди уже отработали подобную технологию. Любые
>предложения приветствуются, заранее спасибо!sysctl -w vm.mmap_min_addr = $((4096*1024*1024))
:)
>Господа, здравствуйте!..., заранее спасибо!#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
int main(
void
){
register unsigned short int
C;
void
*F,*E;
for
(C=0;C<(1<<5);C++) {E=
(void *) (0x100000000+C);
F=mmap(E, 1 << 16, 0x1|0x2, 0x20|0x02, -1, 0);
if (F== ((void *) -1)) {
perror("Кирдык аллок мемориз\n");
return 1;}
printf("Ипать май сасульки, я влезла на %p адрес\n", E);}
return
0
; }
А насчёт защиты, это надо махенькую либу и через неё запускать свою прогуLD_PRELOAD=/lib64/libSuperAllocator.so.0.0.1 ./SuperProga --help
>Господа, здравствуйте!
>
>Меня интересует такой вопрос - можно ли в 64х-битном Linux'е запустить процесс
>так, чтобы указатели, которые он получает, допустим, при аллокации памяти, гарантировано
>вылезали за 32 бита? Еще лучше, чтобы адресное пространство ниже 32х
>бит было защищено, т.е. при попытке обращения туда мы ловили сегфолт.Кароча, мы тут покурили, накодили и получилось обрезание младших 4Gb VA Space...
Вопрос, накуя это нужно?
>Кароча, мы тут покурили, накодили и получилось обрезание младших 4Gb VA Space...
>
>
>Вопрос, накуя это нужно?Грубо говоря, для быстрого и эффективного отлова ошибок в большом чужом коде, связанных с хранением указателей в 32-битных переменных.
На данный момент я все же остановился на достаточно кривом и громоздком алгоритме, подбирающем удобный размер блока для непрерывной аллокации (прямо malloc'ами) нижних 5Гб, после чего они (точнее та их область, что кратна страничному форматированию) закрываются через mprotect, как PROT_NONE.
Несмотря на очевидную костыльность, подобная штука сильно облегчила мне поиск описанных error-cases. Segfault, backtrace, и виновник локализован.
Но, к примеру, мой костыль не работает под valgrind'ом, оттого я и начал поиск других вариантов.
Спасибо всем, кто выдвинул вменяемые предложения!
>>Вопрос, на...я это нужно?
>Грубо говоря, для быстрого и эффективного отлова ошибок в большом чужом коде,
>связанных с хранением указателей в 32-битных переменных.Чёй-то не фкурю, "...хранение указателей в 32-битных переменных", это как?
Указатель он и в африке указатель... в x32 - 4 байта, в x64 - 8
Типаunsigned long long int var = 34524524352435245ULL;
short *f;
f = (short *)var;:)
Так за это морду бита надо, а не ошибки за них отлавливать.
>>>Вопрос, на...я это нужно?
>>Грубо говоря, для быстрого и эффективного отлова ошибок в большом чужом коде,
>>связанных с хранением указателей в 32-битных переменных.
>
>Чёй-то не фкурю, "...хранение указателей в 32-битных переменных", это как?
>
> :)
>Так за это морду бита надо, а не ошибки за них отлавливать.
>морду бьют
1) за русские матные каменты (ипать сосульки)
2) за умышленно обфусцированный код а ля 0x1|0x2 вместо MAP_*|MAP*