BAIBUSEC Header

İşletim Sistemi Çalışma Mantığı ve Bellek: İşlem Yönetimi, Süreçler (Processes) ve Temel Bellek Yapıları

İşletim sistemi çalışma mantığı ve bellek: uygulamalar, çekirdek ve donanım katmanları

Hazırlayan: Enes DURMAZ

Siber Güvenliğin Yazılım Temelleri: Donanım ile Uygulama Arasındaki Katmanı Anlamak

Bir önceki çalışmada bilgisayarın fiziksel anatomisini, yani CPU, RAM, depolama birimlerini ve anakart veri yollarını inceledik. Ancak donanım tek başına yalnızca elektrik sinyallerinden ibarettir. Bu sinyalleri düzenli, güvenli ve verimli bir çalışma ortamına dönüştüren katman işletim sistemidir (Operating System — OS).

Siber güvenlik açısından işletim sistemi, sistemin hakemidir: hangi programın ne kadar CPU süresi alacağına, hangi sürecin hangi bellek adresini görebileceğine ve hangi kullanıcının hangi kaynağa dokunabileceğine karar verir. Yetki yükseltme (privilege escalation), süreç enjeksiyonu (process injection), bellek taşmaları ve bellek adli bilişimi gibi konuların hepsi bu hakemin kurallarını ya anlamaya ya da aşmaya dayanır.

Süreçlerin nasıl doğduğunu, nasıl zamanlandığını ve belleğin nasıl paylaştırıldığını bilmeyen biri, bir zararlı yazılımın sistemde ne yaptığını da, bir bellek bozulması zafiyetinin neden tehlikeli olduğunu da gerçekten kavrayamaz.

Bu çalışma; işletim sistemi çekirdeğinin çalışma mantığını, süreç ve iş parçacığı (thread) yönetimini, CPU zamanlamasını ve süreç bellek yapılarını siber güvenlik perspektifiyle ele almaktadır.

İçindekiler

  1. 1. İşletim Sistemine Giriş
  2. 2. İşletim Sistemi Çekirdeği ve Çalışma Mantığı
  3. 3. Süreç (Process) Yönetimi
  4. 4. CPU Zamanlama, Bağlam Değişimi ve Eşzamanlılık
  5. 5. Bellek Yönetimi ve Süreç Bellek Yapıları
  6. 6. Temel İşletim Sistemi Kavramlarının Karşılaştırmalı Özeti
  7. 7. Sonuç ve İşletim Sistemi Perspektifinden Siber Güvenlik
  8. 8. Soru Bankası

1. İşletim Sistemine Giriş

Bir önceki bölümde gördüğümüz gibi donanım; işlemci, bellek, depolama ve veri yollarından oluşur. Ancak bu bileşenleri doğrudan programlamak son derece zahmetlidir: her program kendi disk sürücüsünü, kendi ekran çıkışını ve kendi bellek yönetimini yazmak zorunda kalırdı. Üstelik aynı anda çalışan iki program birbirinin belleğini ezebilir, aynı diske aynı anda yazmaya çalışıp veriyi bozabilirdi.

İşletim sistemi bu sorunları çözmek için üç temel görevi üstlenir:

  • Soyutlama (Abstraction): Karmaşık donanımı basit kavramlara çevirir. Disk sektörleri "dosya", fiziksel RAM "sanal adres uzayı", CPU zamanı "süreç" haline gelir.
  • Kaynak Yönetimi (Resource Management): CPU süresi, bellek, disk ve ağ gibi sınırlı kaynakları rekabet eden programlar arasında adil ve verimli biçimde paylaştırır.
  • Koruma ve İzolasyon (Protection & Isolation): Programları birbirinden ve çekirdekten ayırır, yetkisiz erişimi donanımın desteğiyle engeller.

Bu üçüncü görev, siber güvenliğin kalbidir. İşletim sisteminin güvenlik modeli temelde şu soruya dayanır: "Bu süreç, bu kaynağa, bu işlemi yapmaya yetkili mi?" Saldırganın amacı ise çoğu zaman bu sorunun cevabını kendi lehine değiştirmektir.

İşletim sisteminin gözünde çalışan her şey bir süreçtir (process) ve her sürecin kendine ait bir bellek dünyası vardır. Bu iki kavram, bu yazının omurgasını oluşturur.

İşletim sisteminin donanım ile uygulamalar arasındaki konumu: katmanlı ilişki
Şekil 1: İşletim sisteminin donanım ile uygulamalar arasındaki konumu: katmanlı ilişki

2. İşletim Sistemi Çekirdeği ve Çalışma Mantığı

2.1. İşletim Sisteminin Görevleri ve Katmanlı Yapı

İşletim sistemi tek bir parça değil, katmanlardan oluşan bir bütündür. Aşağıdan yukarıya doğru tipik yapı şöyledir:

İşletim sisteminin katmanlı yapısı: donanım, çekirdek, sistem çağrısı arayüzü ve kullanıcı uygulamaları
Şekil 2: İşletim sisteminin katmanlı yapısı: donanım, çekirdek, sistem çağrısı arayüzü ve kullanıcı uygulamaları

Çekirdek (Kernel), işletim sisteminin her zaman bellekte bulunan ve en yüksek ayrıcalıkla çalışan çekirdek parçasıdır. Süreç yönetimi, bellek yönetimi, dosya sistemi, aygıt sürücüleri ve ağ yığını gibi temel hizmetleri sunar. Kullanıcı arayüzü, komut satırı kabuğu (shell) ve sıradan programlar çekirdeğin parçası değil, onun hizmetlerinin müşterileridir.

2.2. Kullanıcı Modu, Çekirdek Modu ve Sistem Çağrıları (System Calls)

Bir önceki yazıda x86 koruma halkalarını (Ring 0 ve Ring 3) görmüştük. İşletim sistemi bu donanım özelliğini şu şekilde kullanır:

  • Kullanıcı Modu (User Mode, Ring 3): Sıradan uygulamaların çalıştığı kısıtlı moddur. Bu moddaki bir program donanıma doğrudan dokunamaz, başka bir sürecin belleğini okuyamaz ve ayrıcalıklı CPU komutlarını çalıştıramaz. Yasak bir işlem denendiğinde CPU bir istisna (exception) üretir ve işletim sistemi devreye girerek programı genellikle sonlandırır.
  • Çekirdek Modu (Kernel Mode, Ring 0): Çekirdek ve aygıt sürücülerinin çalıştığı, tüm belleğe ve donanıma erişimi olan moddur.
Sistem çağrısı kapısı: kullanıcı modundan çekirdek moduna kontrollü geçiş
Şekil 3: Sistem çağrısı kapısı: kullanıcı modundan çekirdek moduna kontrollü geçiş

Peki bir uygulama dosya açmak ya da ağa bağlanmak gibi ayrıcalık gerektiren bir işi nasıl yapar? Cevap sistem çağrısıdır (system call). Uygulama, çekirdekten hizmet isteyen kontrollü bir kapı kullanır:

  1. Uygulama fopen() gibi bir kütüphane fonksiyonunu çağırır.
  2. Kütüphane, istenen sistem çağrısının numarasını ve parametrelerini yazmaçlara yerleştirir (Linux x86_64'te çağrı numarası RAX yazmacına konur).
  3. syscall komutu çalıştırılır. CPU, kullanıcı modundan çekirdek moduna donanımsal olarak geçer ve yürütmeyi çekirdeğin önceden belirlenmiş giriş noktasına yönlendirir.
  4. Çekirdek, isteğin geçerli ve yetkili olup olmadığını denetler, işi yapar ve sonucu döndürür.
  5. CPU kullanıcı moduna geri döner ve program kaldığı yerden devam eder.

Kritik nokta şudur: uygulama çekirdek koduna kendi seçtiği bir adrese atlayamaz. Giriş noktasını çekirdek belirler. Bu, korumanın temelidir.

İşlemLinux Sistem ÇağrısıWindows Karşılığı (Win32 / Native API)
Dosya açmaopen / openatCreateFile / NtCreateFile
Dosya okumareadReadFile / NtReadFile
Süreç oluşturmafork / clone + execveCreateProcess / NtCreateUserProcess
Bellek ayırmammap / brkVirtualAlloc / NtAllocateVirtualMemory
Süreç sonlandırmaexit / killExitProcess / TerminateProcess

2.3. Çekirdek Mimarileri: Monolitik, Mikro Çekirdek ve Hibrit Yapılar

Çekirdeğin hangi hizmetleri Ring 0'da çalıştıracağı bir tasarım tercihidir:

  • Monolitik Çekirdek (Linux): Süreç yönetimi, bellek yönetimi, dosya sistemleri ve sürücülerin büyük kısmı tek bir büyük program olarak çekirdek modunda çalışır. Bileşenler arası çağrılar hızlıdır, ancak herhangi bir bileşendeki hata tüm sistemi çökertebilir. Linux, ihtiyaca göre yüklenip kaldırılabilen çekirdek modülleri ile bu yapıya esneklik katar.
  • Mikro Çekirdek (Microkernel): Çekirdekte yalnızca en temel hizmetler (zamanlama, temel bellek yönetimi, süreçler arası iletişim) kalır. Dosya sistemi ve sürücüler kullanıcı modunda ayrı süreçler olarak çalışır. Bir sürücü çökerse sistem ayakta kalabilir ve saldırı yüzeyi küçülür; bedel ise artan iletişim yüküdür. QNX ve seL4 bu yaklaşımın örnekleridir.
  • Hibrit Çekirdek (Windows NT, macOS XNU): İki yaklaşımın karışımıdır. Mikro çekirdekten esinlenen modüler bir tasarım kullanılır, ancak performans için birçok hizmet çekirdek modunda tutulur.

2.4. Çekirdek Düzeyinde Güvenlik: Sürücüler, Rootkit'ler ve Ayrıcalık Yükseltme

Koruma sınırı, ayrıcalık yükseltme ve BYOVD saldırısı
Şekil 4: Koruma sınırı, ayrıcalık yükseltme ve BYOVD saldırısı

Siber Güvenlik Bağlantısı: Çekirdek Güvenliği

  1. Ayrıcalık Yükseltme (Privilege Escalation): Saldırganlar çoğu zaman sisteme önce düşük yetkili bir kullanıcı olarak girer. Asıl hedef, yetkiyi yükselterek yönetici/root hakkı veya doğrudan çekirdek düzeyinde kod çalıştırma yeteneği kazanmaktır. Çekirdekteki, çekirdek modülündeki veya sürücüdeki tek bir bellek bozulması zafiyeti, tüm koruma duvarlarının aşılmasına yol açabilir.
  2. Aygıt Sürücüleri: En Zayıf Halka: Sürücüler Ring 0'da çalışır ve genellikle üçüncü taraflarca yazılır. Zafiyetli ama geçerli imzaya sahip bir sürücünün sisteme yüklenmesi (BYOVD — Bring Your Own Vulnerable Driver), saldırganlara çekirdek erişimi kazandırmak için bilinen bir tekniktir. Bu nedenle Windows, Microsoft tarafından engellenen zafiyetli sürücülerin listesini tutar.
  3. Rootkit'ler: Çekirdek düzeyinde çalışan rootkit'ler, işletim sisteminin kendi sistem çağrısı sonuçlarını değiştirerek kendilerini süreç listesinden, dosya listesinden ve ağ bağlantılarından gizler. Güvenlik yazılımı, "yalan söyleyen" bir çekirdeğe güvenmek zorunda kaldığı için bu tehditleri görmek zorlaşır.
  4. Savunma Katmanları: Modern sistemler çekirdek kodunu korumak için SMEP/SMAP (çekirdeğin kullanıcı belleğindeki kodu çalıştırmasını ve gelişigüzel okumasını engelleyen CPU özellikleri), imzalı sürücü zorunluluğu, çekirdek bütünlük korumaları ve KPTI (Meltdown'a karşı çekirdek ve kullanıcı sayfa tablolarını ayıran yama) gibi mekanizmalar kullanır.

3. Süreç (Process) Yönetimi

3.1. Program, Süreç ve İş Parçacığı (Thread) Kavramları

Üç kavram sıkça karıştırılır:

  • Program: Diskte duran pasif bir dosyadır (örneğin chrome.exe veya /bin/ls). İçinde makine kodu ve veri bulunur, kendi başına hiçbir şey yapmaz.
  • Süreç (Process): Çalışmakta olan bir programın örneğidir. Programın kodunun yanı sıra kendi sanal adres uzayını, açık dosya tutamaçlarını, kimlik bilgilerini (kullanıcı, yetkiler) ve en az bir iş parçacığını barındırır. Aynı programdan aynı anda birden fazla süreç çalışabilir.
  • İş Parçacığı (Thread): Bir süreç içindeki yürütme birimidir. Her thread'in kendi program sayacı (RIP), yazmaç kümesi ve yığını (stack) vardır; ancak aynı sürecin thread'leri kod, global veri ve heap alanını paylaşır.
Bir süreç içinde thread'ler: ortak bellek ve thread'lere özel yığın ile yazmaçlar
Şekil 5: Bir süreç içinde thread'ler: ortak bellek ve thread'lere özel yığın ile yazmaçlar
ÖzellikSüreç (Process)İş Parçacığı (Thread)
Adres uzayıHer sürecin kendine ait, yalıtılmışAynı sürecin thread'leri ortak kullanır
Oluşturma maliyetiYüksekDüşük
Bağlam değişimi maliyetiYüksek (adres uzayı değişir)Düşük (adres uzayı aynı kalır)
İletişimIPC mekanizmaları gerekirOrtak belleği doğrudan kullanır
Bir hatanın etkisiGenellikle yalnızca o süreç çökerTüm sürece zarar verebilir

Süreçlerin yalıtımı güvenlik sağlar, thread'lerin ortak belleği ise hız sağlar. Her ikisi de bir bedelle gelir: ortak bellek, eşzamanlılık hatalarının kaynağıdır (bkz. Bölüm 4).

3.2. Süreç Kontrol Bloğu (PCB) ve Süreç Durumları

İşletim sistemi her süreci Süreç Kontrol Bloğu (Process Control Block — PCB) adı verilen bir çekirdek veri yapısıyla izler. Linux'ta bu yapı task_struct, Windows'ta EPROCESS ve ETHREAD yapılarıdır. Bir PCB tipik olarak şunları içerir:

  • Süreç Kimliği (PID) ve üst sürecin kimliği (PPID)
  • Süreç durumu (hazır, çalışıyor, bekliyor vb.)
  • Kaydedilmiş CPU yazmaçları ve program sayacı (bağlam değişimi için)
  • Bellek yönetim bilgisi: sayfa tablosunun konumu, bellek bölgeleri
  • Açık dosya ve tutamaç tablosu
  • Güvenlik kimliği: kullanıcı (UID/SID), grup, yetkiler (capabilities/token)
  • Zamanlama bilgisi: öncelik, harcanan CPU süresi

Bir süreç ömrü boyunca şu durumlar arasında gidip gelir:

Süreç yaşam döngüsü ve durum diyagramı
Şekil 6: Süreç yaşam döngüsü ve durum diyagramı
  • Yeni (New): Süreç oluşturuluyor.
  • Hazır (Ready): CPU'ya atanmayı bekliyor.
  • Çalışıyor (Running): Şu an bir CPU çekirdeğinde yürütülüyor.
  • Bekliyor (Waiting/Blocked): Bir G/Ç işleminin tamamlanmasını veya bir olayı bekliyor.
  • Sonlandı (Terminated): Çalışmasını bitirdi; kaynakları geri alınıyor.

Linux'ta ps ve top çıktılarında görülen karşılıkları ise şöyledir: R (çalışıyor/hazır), S (kesilebilir uyku), D (kesilemez uyku, genellikle disk G/Ç), T (durdurulmuş) ve Z (zombi).

3.3. Süreç Oluşturma: fork, exec ve CreateProcess

Süreçler boşluktan doğmaz; mutlaka başka bir süreç tarafından oluşturulur. Bu bir ebeveyn–çocuk (parent–child) ağacı oluşturur. Linux'ta ağacın kökü init/systemd (PID 1) sürecidir.

Linux (UNIX) yaklaşımı iki adımlıdır:

  1. fork(): Çağıran sürecin neredeyse birebir kopyası olan bir çocuk süreç oluşturur. Verimlilik için Copy-on-Write (CoW) kullanılır: bellek sayfaları başlangıçta fiziksel olarak kopyalanmaz, ebeveyn ve çocuk aynı sayfaları paylaşır. Taraflardan biri bir sayfaya yazmaya kalkarsa o sayfa o anda kopyalanır.
  2. exec() ailesi: Çocuk sürecin belleğini yeni bir programla değiştirir. Süreç kimliği aynı kalır, ancak içinde artık başka bir program çalışır.

Bir kabukta ls yazdığınızda olan tam olarak budur: kabuk kendini fork eder, çocuk exec("/bin/ls") çağırır, ebeveyn ise çocuğun bitmesini wait() ile bekler.

Windows yaklaşımı tek adımlıdır: CreateProcess() hem yeni süreci oluşturur hem de belirtilen programı içine yükler. Windows'ta süreç ağacı UNIX kadar katı bir kavram değildir; ancak ebeveyn bilgisi yine de kayıt altında tutulur ve güvenlik analizinde (örneğin winword.exe sürecinin powershell.exe başlatması gibi şüpheli ilişkilerde) çok değerlidir.

Süreç sonlanması: Bir süreç exit() ile ya da bir sinyal/istisna yüzünden biter. Çocuk sonlandığında çıkış durumunu ebeveyne bildirmek zorundadır; ebeveyn bunu wait() ile okuyana kadar çocuğun PCB kaydı bellekte kalır. Bu durum zombi süreç olarak adlandırılır.

4. CPU Zamanlama, Bağlam Değişimi ve Eşzamanlılık

Bilgisayarda aynı anda onlarca, yüzlerce süreç "çalışıyor" görünür; oysa bir CPU çekirdeği her an yalnızca bir iş parçacığını yürütebilir. Bu yanılsama, CPU zamanının çok kısa dilimlere bölünerek sürekli el değiştirmesiyle yaratılır.

4.1. Bağlam Değişimi (Context Switch)

CPU'nun bir iş parçacığından diğerine geçmesine bağlam değişimi (context switch) denir. İşlem sırasında çekirdek:

  1. Çalışan thread'in yazmaçlarını ve program sayacını kendi PCB/thread yapısına kaydeder.
  2. Zamanlayıcının seçtiği yeni thread'in kayıtlı durumunu CPU yazmaçlarına yükler.
  3. Farklı bir sürece geçiliyorsa adres uzayını değiştirir (sayfa tablosu işaretçisini günceller; bu da TLB önbelleğinin etkilenmesine yol açar).

Bu işlem tipik olarak mikrosaniye mertebesindedir; sık yapıldığında bile sistemin hızını belirgin biçimde düşürebilir, çünkü bağlam değişimi "faydalı iş" üretmez ve önbellekleri soğutur.

Bağlam değişimi (context switch): durumun kaydedilmesi ve geri yüklenmesi
Şekil 7: Bağlam değişimi (context switch): durumun kaydedilmesi ve geri yüklenmesi

Geçişi tetikleyen olaylar şunlardır: zaman diliminin dolması (donanım zamanlayıcı kesmesi sayesinde çekirdek CPU'yu geri alır), sürecin G/Ç için beklemeye geçmesi, daha yüksek öncelikli bir sürecin hazır hale gelmesi veya sürecin gönüllü olarak CPU'yu bırakması.

4.2. Zamanlama Algoritmaları

Zamanlayıcı (Scheduler), hazır kuyruğundaki thread'lerden hangisinin CPU'yu alacağına karar verir. Hedefler birbiriyle çelişebilir: yüksek verim, düşük bekleme süresi, hızlı tepki ve adalet.

AlgoritmaÇalışma MantığıGüçlü YanıZayıf Yanı
FCFS (İlk Gelen İlk Hizmet Alır)Gelen sırayla çalıştırır, kesmez.BasitUzun bir iş, arkadakileri bekletir (convoy etkisi).
SJF (En Kısa İş Önce)Tahmini en kısa işi seçer.Ortalama bekleme süresi optimumdur.Süreyi önceden bilmek zordur; uzun işler aç kalabilir.
Round RobinHerkese sırayla sabit bir zaman dilimi (quantum) verir.Adil, etkileşimli sistemlere uygunDilim çok küçükse bağlam değişimi yükü artar.
Öncelik TabanlıEn yüksek öncelikliyi çalıştırır.Kritik işler hızlı çalışır.Düşük öncelikliler açlık (starvation) yaşayabilir; çözümü "yaşlandırma (aging)".
MLFQ (Çok Seviyeli Geri Beslemeli Kuyruk)Davranışa göre süreçleri kuyruklar arasında taşır.Kısa/etkileşimli işlere öncelik verir.Ayarlaması karmaşıktır.

Gerçek sistemlerde bu fikirlerin karma biçimleri kullanılır:

  • Linux: Uzun yıllar CFS (Completely Fair Scheduler) kullanıldı; her sürece "adil CPU payı" vermeye çalışır. Linux 6.6 sürümünden itibaren yerini EEVDF zamanlayıcısı almıştır.
  • Windows: Öncelik tabanlı, kesintili (preemptive) bir zamanlayıcı kullanır; 0–31 arası öncelik seviyeleri vardır ve en yüksek öncelikli hazır thread çalışır. Zamanlama biriminin süreç değil thread olduğuna dikkat edilmelidir.

4.3. Süreçler Arası İletişim (IPC) ve Senkronizasyon

Süreçler birbirinden yalıtılmıştır; ancak çoğu zaman iş birliği yapmaları gerekir. İşletim sistemi bunun için IPC (Inter-Process Communication) mekanizmaları sunar:

  • Pipe (Boru): Bir sürecin çıktısını diğerinin girdisine bağlar (ls | grep txt).
  • Paylaşımlı Bellek (Shared Memory): İki sürecin adres uzayına aynı fiziksel sayfaları eşler; en hızlı yöntemdir ancak senkronizasyon geliştiricinin sorumluluğundadır.
  • Mesaj Kuyrukları ve Soketler: Yapılandırılmış mesajlaşma ve ağ üzerinden iletişim sağlar.
  • Sinyaller (Signals): Bir sürece asenkron olay bildirir (SIGTERM, SIGKILL, SIGSEGV).

Birden fazla thread veya süreç ortak veriye eriştiğinde senkronizasyon gerekir. Başlıca araçlar şunlardır:

  • Mutex (Karşılıklı Dışlama Kilidi): Kritik bölgeye aynı anda yalnızca tek thread'in girmesini sağlar.
  • Semafor: Sınırlı sayıda kaynağa erişimi sayaçla denetler.
  • Monitör ve koşul değişkenleri: Daha yüksek seviyeli bekleme/uyandırma yapıları sunar.

Yanlış kullanım iki klasik soruna yol açar:

  • Yarış Durumu (Race Condition): Sonucun, thread'lerin çalışma sırasının zamanlamasına bağlı olması.
  • Kilitlenme (Deadlock): İki veya daha fazla thread'in birbirinin elindeki kilidi sonsuza kadar beklemesi. Kilitlenme için dört koşulun (Coffman koşulları) aynı anda sağlanması gerekir: karşılıklı dışlama, tut ve bekle, öncelikle kesilememe ve dairesel bekleme. Bunlardan biri kırılırsa kilitlenme önlenir. Örneğin tüm kilitlerin her zaman aynı sırayla alınması dairesel beklemeyi engeller.

4.4. Eşzamanlılık Güvenliği: Race Condition ve TOCTOU

Siber Güvenlik Bağlantısı: Zamanlamadan Doğan Zafiyetler

  1. Yarış Durumu Zafiyetleri: Zamanlama penceresi, saldırganın yararlanabileceği bir zafiyete dönüşebilir. Çok thread'li bir uygulamada paylaşılan değişkenin kilitsiz güncellenmesi; bakiye, yetki veya sayaç değerlerinin tutarsızlaşmasına neden olabilir. Web uygulamalarında aynı kuponun veya işlemin eşzamanlı isteklerle birden fazla kez kullanılması buna bir örnektir.
  2. TOCTOU (Time-of-Check to Time-of-Use): Bir kaynağın güvenliği kontrol edilir, ancak kullanıldığı ana kadar geçen kısa sürede değiştirilebilir. Örneğin bir programın "bu dosya kullanıcıya ait mi?" kontrolünden sonra, açma işleminden önce dosyanın başka bir hedefe (sembolik bağa) çevrilmesi, yetkili bir programın yetkisiz bir dosyayı işlemesine yol açabilir. Savunma, kontrol ve kullanımı atomik hale getirmek ve kontrol edilen nesneyi tutamaç (handle) üzerinden kullanmaktır.
  3. Zamanlama Tabanlı Yan Kanallar: Bir önceki yazıda gördüğümüz Spectre ve Meltdown gibi saldırılar, CPU'nun ve zamanlayıcının paylaşımlı kaynak davranışlarını ölçmeye dayanır; işletim sistemi bu nedenle çekirdek–kullanıcı sayfa tablosu ayrımı (KPTI) gibi yazılımsal önlemler uygular.
  4. Hizmet Reddi: Zamanlayıcıya yük bindirmek (çok sayıda süreç/thread, CPU'yu tüketen döngüler) sistemi yavaşlatabilir. cgroups, kotalar ve limitler (ulimit) bu riski azaltır.

5. Bellek Yönetimi ve Süreç Bellek Yapıları

Bir önceki yazıda RAM'i, sanal belleği ve MMU'yu donanım açısından tanımıştık. Bu bölümde aynı konuya işletim sisteminin ve çalışan bir programın gözünden bakıyoruz: bir sürecin belleği nasıl düzenlenir, çekirdek sayfaları nasıl yönetir ve bu yapılar güvenlik açısından neden önemlidir?

5.1. Bir Sürecin Bellek Düzeni: Text, Data, BSS, Heap ve Stack

Her süreç, işletim sisteminin sunduğu sanal adres uzayında sanki tüm belleğin sahibiymiş gibi çalışır. Bu uzay, belirli amaçlara ayrılmış bölgelerden oluşur. Linux x86_64 için sadeleştirilmiş düzen şöyledir (adresler yukarı doğru artar):

Bir sürecin bellek düzeni (Linux x86_64, sadeleştirilmiş)
Şekil 8: Bir sürecin bellek düzeni (Linux x86_64, sadeleştirilmiş)
BölgeİçeriğiTipik İzinlerNotlar
Text (Code)Programın makine komutlarıOkuma + Çalıştırma (R-X)Yazılabilir olmamalıdır; aynı programın süreçleri bu sayfaları paylaşabilir.
DataBaşlangıç değeri verilmiş global/statik değişkenlerOkuma + Yazma (RW-)Programın çalıştırılabilir dosyasından yüklenir.
BSSBaşlangıç değeri verilmemiş (sıfırlanmış) global/statik değişkenlerOkuma + Yazma (RW-)Dosyada yer kaplamaz, yalnızca boyutu tutulur.
HeapÇalışma zamanında dinamik ayrılan bellekOkuma + Yazma (RW-)Geliştiricinin ayırıp serbest bırakmakla yükümlü olduğu alan.
Mmap BölgesiPaylaşımlı kütüphaneler, eşlenmiş dosyalarBölgeye göre değişirHer kütüphane kendi text/data bölgeleriyle eşlenir.
StackFonksiyon çağrı çerçeveleri, yerel değişkenler, dönüş adresleriOkuma + Yazma (RW-)Her thread'in kendi yığını vardır.

Windows'ta kavramsal düzen benzerdir: yürütülebilir dosyanın (PE) bölümleri (.text, .data, .rdata), DLL'ler, heap'ler ve her thread için yığın bulunur. Ek olarak PEB (Process Environment Block) ve TEB (Thread Environment Block) gibi süreç/thread bilgilerini tutan yapılar kullanıcı adres uzayında yer alır.

5.2. Yığın (Stack) ve Çağrı Çerçeveleri

Stack, LIFO (son giren ilk çıkar) mantığıyla çalışan ve her fonksiyon çağrısında otomatik büyüyüp küçülen bellek bölgesidir. Her fonksiyon çağrısı, stack üzerinde bir çağrı çerçevesi (stack frame) oluşturur. Bir çerçeve tipik olarak şunları içerir:

  • Fonksiyon parametreleri (mimariye ve çağrı kuralına göre yazmaçlarda ya da stack'te)
  • Dönüş adresi (return address): Fonksiyon bittiğinde yürütmenin nereye döneceği
  • Önceki çerçeve işaretçisi (RBP)
  • Yerel değişkenler (diziler/tamponlar dahil)

Sadeleştirilmiş bir çerçeve (adresler aşağıdan yukarıya artar, stack aşağı doğru büyür):

Süreç sanal adres uzayı, stack çerçevesi ve sayfalama
Şekil 9: Süreç sanal adres uzayı, stack çerçevesi ve sayfalama

Önceki yazıdaki yazmaçlarla bağlantı: RSP yığının tepesini, RBP o anki çerçevenin tabanını, RIP ise çalıştırılacak sonraki komutu gösterir. Fonksiyon ret komutuyla döndüğünde CPU, stack'teki dönüş adresini RIP'e yükler. Bu nedenle dönüş adresi, kontrol akışı açısından son derece değerli bir veridir.

Stack'in özellikleri: tahsis ve serbest bırakma otomatik ve çok hızlıdır, boyutu sınırlıdır (Linux'ta tipik olarak süreç başına 8 MB varsayılan sınır), ve çok derin ya da sonsuz özyineleme stack overflow hatasıyla sonuçlanır.

5.3. Sayfa Değiştirme Algoritmaları ve Thrashing

Fiziksel RAM dolduğunda çekirdek, yeni bir sayfa getirebilmek için bellekteki bir sayfayı çıkarmak (evict) zorundadır. Çıkarılan sayfa değiştirilmişse (dirty bit = 1) önce swap alanına yazılır. Hangi sayfanın çıkarılacağına sayfa değiştirme algoritması karar verir:

  • FIFO: En eski sayfayı çıkarır. Basittir ancak sık kullanılan bir sayfayı atabilir; ayrıca daha fazla çerçeve vermenin hata sayısını artırabildiği Belady anomalisi görülebilir.
  • Optimal: Gelecekte en geç kullanılacak sayfayı çıkarır. Gelecek bilinemediği için pratikte uygulanamaz; yalnızca kıyaslama ölçütüdür.
  • LRU (En Az Yakın Zamanda Kullanılan): Uzun süredir kullanılmayanı çıkarır. İyi sonuç verir ancak tam uygulaması pahalıdır.
  • Clock (İkinci Şans): LRU'yu accessed biti ile ucuza yaklaşıklar; gerçek sistemlerde yaygın bir temeldir.

Thrashing: Sistem, yeterli RAM olmadığı için zamanının çoğunu sayfaları diske yazıp geri okumakla geçirirse gerçek iş yapamaz hale gelir. CPU boşta görünür, disk ise sürekli meşguldür; sistem aşırı yavaşlar. Çözümleri RAM artırmak, çalışan süreç sayısını azaltmak veya bellek kullanımını düşürmektir. Linux'ta bellek tamamen tükenirse OOM Killer (Out-of-Memory Killer) devreye girer ve sistemi kurtarmak için bazı süreçleri sonlandırır.

6. Temel İşletim Sistemi Kavramlarının Karşılaştırmalı Özeti

Aşağıdaki tablo, yazıda ele alınan temel kavramların işlevlerini ve siber güvenlik boyutundaki kritik risk alanlarını özetler:

KavramTemel GöreviÖnemli Veri Yapısı / MekanizmaKritik Güvenlik Konusu / Risk Alanı
Çekirdek (Kernel)Donanımı yönetmek, kaynakları paylaştırmak, koruma sağlamakRing 0, sistem çağrısı arayüzüAyrıcalık yükseltme, rootkit, zafiyetli sürücüler (BYOVD)
Kullanıcı / Çekirdek ModuAyrıcalık seviyelerini ayırmakCPU halkaları, mod geçişiMod sınırının aşılması, çekirdek exploit'leri
Sistem ÇağrısıUygulamaya kontrollü çekirdek hizmeti sunmaksyscall, çağrı tablosuSistem çağrısı kancalama (hooking), argüman doğrulama hataları
Süreç (Process)Çalışan programın yalıtılmış örneğiPCB (task_struct / EPROCESS), PIDSüreç enjeksiyonu, anormal süreç ağaçları, yetki belirteci çalma
İş Parçacığı (Thread)Süreç içi yürütme birimiThread yapısı, kendi yığınıOrtak bellek kaynaklı yarış durumları
Zamanlayıcı (Scheduler)CPU zamanını paylaştırmakHazır kuyruğu, öncelikler, quantumKaynak tüketme / hizmet reddi, öncelik manipülasyonu
Bağlam DeğişimiCPU'yu bir thread'den diğerine geçirmekKayıtlı yazmaç durumuYan kanal sızıntıları (paylaşımlı CPU durumu)
IPC ve SenkronizasyonSüreçler arası iletişim ve koordinasyonPipe, paylaşımlı bellek, mutex, semaforRace condition, TOCTOU, deadlock
StackFonksiyon çağrı çerçeveleri, yerel değişkenlerRSP, RBP, dönüş adresiStack buffer overflow, RIP/dönüş adresi bozulması
HeapDinamik bellek tahsisimalloc/free, allocator yapılarıUse-after-free, double free, heap taşması
Sanal Bellek ve Sayfa TablolarıAdres yalıtımı, esnek bellek yönetimiPTE, MMU, TLB, NX/U-S bitleriYanlış izinler, Rowhammer/yan kanal ile PTE manipülasyonu
Page Fault MekanizmasıEksik/yetkisiz sayfa erişimini yönetmekPage fault istisnası, swapSwap'teki hassas verilerin kalıntısı, segfault kaynaklı çökmeler
ASLR / DEP / CanaryBellek bozulması saldırılarını zorlaştırmakRastgele adresleme, NX biti, kanarya değeriBilgi sızıntısıyla aşılabilme; tek başına yetersizlik

7. Sonuç ve İşletim Sistemi Perspektifinden Siber Güvenlik

İşletim sistemi, donanımın ham gücünü kullanılabilir ve güvenli bir platforma dönüştüren katmandır. Bu çalışmada incelendiği üzere:

  • Çekirdek ve çalışma mantığı, kullanıcı modu ile çekirdek modu arasındaki donanımsal sınırın ve sistem çağrılarının, tüm güvenlik modelinin temelini oluşturduğunu; çekirdeğe ve sürücülere yönelik saldırıların neden bu kadar kritik olduğunu,
  • Süreç yönetimi, her çalışan programın PCB ile izlenen, kendi kimliği, yetkileri ve adres uzayı olan yalıtılmış bir varlık olduğunu; süreç enjeksiyonu ve anormal süreç ilişkilerinin neden savunmacıların ana izleme noktası olduğunu,
  • Zamanlama ve eşzamanlılık, bağlam değişimi, IPC ve senkronizasyonun hem performansın hem de race condition ve TOCTOU gibi ince zafiyetlerin kaynağı olduğunu,
  • Bellek yönetimi, sürecin text, data, BSS, heap ve stack bölgelerinin, sayfa tablolarındaki koruma bitlerinin ve page fault mekanizmasının, bellek bozulması saldırılarının ve ASLR, DEP/NX, stack canary gibi savunmaların neden böyle tasarlandığını

anlamamızı sağlamıştır.

Önceki yazıda donanımın sınırlarını öğrenmiştik; bu yazıda o donanım üzerinde işletim sisteminin nasıl kurallar koyduğunu gördük. Bir savunmacı, bir sürecin neden "şüpheli" göründüğünü ancak normalin ne olduğunu bilirse söyleyebilir. Bir araştırmacı, bir bellek zafiyetinin etkisini ancak stack, heap ve sayfa tablosunun nasıl çalıştığını bilirse doğru değerlendirebilir.

Bir sonraki adım olarak bu temeller üzerine dosya sistemleri ve yetkilendirme modelleri, ardından ağ temelleri (OSI/TCP-IP) ve kriptografiye giriş konuları, serinin doğal devamı olacaktır.

8. Soru Bankası

Aşağıdaki sorular, yazıda işlenen konuları bölüm sırasıyla pekiştirmek için hazırlanmıştır.

Kategori

Paylaş