История изменений
Исправление anonymous_incognito, (текущая версия) :
Тоже сильно большое число получилось.
Гкхм... Вот тогда код, в котором у меня относительно небольшое число на 64-битном получилось. На этот раз портим код функции main() в памяти.
Пример уже слегка искусственный, потому что пришлось специально озаботиться разрешить запись в секцию кода, без чего программа падает с segfault (но кстати на 32 битах может и не всегда понадобится специально разрешать) и компилировать с опцией -no-pie, без которой число будет очень большим. Но теоретически можно представить и такую программу, в которой есть JIT-компиляция и нужно отключить позиционную независимость кода (-no-pie опцией).
Притом сделать writable нулевую область памяти таким способом не удастся, так что такая вещь - это не отключение вообще сегфолта при нулевом указателе.
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdint.h>
void make_memory_writable(void *addr)
{
long pagesize = sysconf(_SC_PAGESIZE);
// Align for page size (typicaly 4096)
uintptr_t page_start = (uintptr_t)addr & ~(pagesize - 1);
// Set permissions for READ, WRITE and EXEC for page
if (mprotect((void *)page_start, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
{
perror("mprotect failed");
}
}
int main()
{
unsigned char old, *a = NULL;
unsigned long n;
n = (unsigned long)&main; /* address of main fumction */
printf("main[0] before write %u, n = %lu\n",a[n],n);
old = a[n]; /* backup value */
make_memory_writable(a+n);
a[n]=1;
printf("main[0] after write %u\n",a[n]);
a[n]=old;
return 0;
}
Запуск
$ gcc -no-pie nullptr2.c -o nullptr2
$ ./nullptr2
main[0] before write 85, n = 4198835
main[0] after write 1
Исходная версия anonymous_incognito, :
Тоже сильно большое число получилось.
Гкхм... Вот тогда код, в котором у меня относительно небольшое число на 64-битном получилось. На этот раз портим код функции main() в памяти.
Пример уже слегка искусственный, потому что пришлось специально озаботиться разрешить запись в секцию кода, без чего программа падает с segfault (но кстати на 32 битах может и не всегда понадобится специально разрешать) и компилировать с опцией -no-pie, без которой число будет очень большим. Но теоретически можно представить и такую программу, в которой есть JIT-компиляция и нужно отключить позиционную независимость кода (-no-pie опцией).
Притом сделать writable нулевую область памяти таким способом не удастся, так что такая вещь - это не отключение вообще сегфолта при нулевом указателе.
#include <stdio.h>
#include <sys/mman.h>
#include <unistd.h>
#include <stdint.h>
void make_memory_writable(void *addr)
{
long pagesize = sysconf(_SC_PAGESIZE);
// Align for page size (typicaly 4096)
uintptr_t page_start = (uintptr_t)addr & ~(pagesize - 1);
// Set permissions for READ, WRITE and EXEC for page
if (mprotect((void *)page_start, pagesize, PROT_READ | PROT_WRITE | PROT_EXEC) != 0)
{
perror("mprotect failed");
}
}
int main()
{
unsigned char old, *a = NULL;
unsigned long n;
n = (unsigned long)&main; /* address of main fumction */
printf("main[0] before write %u, n = %lu\n",a[n],n);
old = a[n]; /* backup value */
make_memory_writable(a+n);
a[n]=1;
printf("main[0] after write %u\n",a[n]);
a[n]=old;
return 0;
}
Запуск
$ ./nullptr2
main[0] before write 85, n = 4198835
main[0] after write 1