LINUX.ORG.RU

История изменений

Исправление 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