Berkenalan Dengan Bug Null Pointer Dereference [Versi Lawas]
mmap() & mprotect()
Linux memiliki beberapa jenis syscall yang berhubungan dengan memory management, diantaranya adalah mmap() dan mprotect().

Dari manual pages mmap():
SYNOPSIS
include <sys/mman.h>
void *mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
DESCRIPTION
mmap() creates a new mapping in the virtual address space of the
calling process. The starting address for the new mapping is specified in addr.
The length argument specifies the length of the mapping.
…
syscall mmap() digunakan untuk melakukan memory mapping suatu file ataupun object ke virtual memory. Jadi suatu proses dapat memanggil mmap() dan kemudian melakukan mapping suatu object / file ke suatu lokasi di memory, dan melakukan beragam aktifitas pada object / file tersebut melalui memory. Sebagaimana yang telah didefinisikan, mmap() juga sekaligus memberikan informasi protocol dan flags dari page memory yang telah di-mapped. Data lengkap mengenai protocol apa saja ataupun flags apa saja yang bisa diberikan pada page tersebut bisa dibaca melalui halaman manual lengkap mmap().
SYNOPSIS
#include <sys/mman.h>
int mprotect(const void *addr, size_t len, int prot);
DESCRIPTION
mprotect() changes protection for the calling process’s memory
page(s) containing any part of the address range in the interval
[addr, addr+len-1]. addr must be aligned to a page boundary.
...
syscall mprotect() digunakan untuk mengubah hak akses suatu memory page, misalnya suatu memory page memiliki hak akses readonly maka dengan menggunakan mprotect() kita dapat mengubah hak akses tersebut menjadi read+write.
Saat ini pembaca mungkin sudah bisa menebak hubungan antara syscall mmap() / mprotect() dengan NULL pointer dereference kan?! kita dapat mengubah hak akses pada zero page memory menggunakan mprotect() ataupun melakukan mapping dengan menggunakan mmap() dan kemudian memasukan nilai yang kita inginkan ke lokasi zero page memory.
Mari kita lihat contoh kode berikut ini:

Program diatas jika dijalankan akan melakukan NULL pointer dereference seperti program sebelumnya, namun kali ini kita telah melakukan mapping dengan memanfaatkan syscall mmap() untuk memasukan karakter A ke lokasi zero page memory. Dan ketika program diatas hendak melakukan NULL pointer dereference (melalui fungsi fprintf()) yang secara teori akan mengakses zero page memory, maka tidak akan terjadi segmentation fault dan justru sebaliknya program akan berjalan dengan baik dan menampilkan karakter A.
Sebelum melangkah lebih jauh, program diatas akan berhasil dijalankan secara langsung dengan kondisi kernel linux yang digunakan adalah versi dibawah 2.6.23 (< 2.6.23), jika pembaca mengalami kegagalan dengan pesan Zero page tidak bisa di-mapped: Permission denied maka kemungkinan besar kernel yang digunakan adalah versi diatas 2.6.23 (>= 2.6.23). Saya akan memberikan penjelasan mengenai penyebab kegagalan ini beberapa saat lagi, namun untuk kali ini kamu bisa melakukan perintah berikut (sebagai “root”):# sysctl -w vm.mmap_min_addr=0
setelah melakukan perintah diatas, maka normalnya zero page dapat di-mapped. Jika masih terdapat masalah, maka kemungkinan lain adalah sistem operasi yang digunakan memiliki settingan SELinux ataupun LSM (Linux Security Module) lainnya. Silahkan cari referensi untuk menon-aktifkan konfigurasi tersebut, yang pasti pada tahap ini kita hanya melakukan pembuktian bahwa kondisi NULL pointer dereference dapat di-kontrol melalui userland process.