Koruma Mekanizması, Çekirdek ve Kullanıcı Modları Kaan Aslan 21 Nisan 2005 Çok prosesli sistemlerde işletim sisteminin kendisi ve çalışan tüm prosesler aynı fiziksel bellekte bulunur. Bir prosesin kendi bellek alanı dışına çıkarak işletim sisteminin ya da başka proseslerin bellek alanlarına erişmesi güvenli bir durum değildir. Örneğin C’de bir göstericiye işletim sisteminin bulunduğu bir bölgenin adresini yerleştirip orayı bozmaya çalışabilirsiniz. İşletim sisteminin bellekteki kod ve veri alanlarının bozulması tüm sistemi çökertebilir. Bir banka görevlisinin tam bir işlem yaparken o sırada başka bir prosesin yanlışlıkla ya da kötü niyetle bu işlemin yapıldığı alana erişerek orayı rastgele bozduğunu düşünün. Program çökebilir ya da yanlış bilgiler veritabanına aktarılabilir. Böyle bir sistem güvenli olabilir mi?.. Şüphesiz güvenliği tehdit eden tek unsur bellek erişimi değildir. Bazı makina komutları sistemi anında çökertebilir. Örneğin Intel işlemcilerinde CLI komutu ile işlemci donanım kesmelerine kapatılır. İşletim sistemi dışsal kesmlere gereksinim duyduğundan sistem hemen çöker. Ya da haberleşme portlarına OUT komutuyla rastgele değerler aktarılarak da sistem çökertilebilir. O halde güvenli bir sistemde sıradan proseslerin bazı makina komutlarını kullanamaması gerekir. Bu tür korumalara komut koruması denilmektedir. Koruma mekanizması daha ilk elden işlemci tarafından sağlanmaktadır. İşlemci aktarım yapan makina komutlarını denetleyerek prosesin kendi bellek alanının dışına çıkıp çıkmadığını belirlemeye çalışır. Sıradan prosesler özel makina komutlarını kullandığında bu durum yine öncelikle işlemci tarafından belirlenir. İşlemcinin görevi koruma ihlallerini belirleyip bunu işletim sistemine iletmektir. İşletim sistemi koruma mekanizmasını tehdit eden prosesleri cezalandırıp sonlandırabilir. Windows sistemlerinde sık sık gördüğünüz “Bu program geçersiz bir işlemi yürüttü, sonlandırılacak” gibi mesajlar ya da UNIX/Linux sistemlerinde karşılaşmış olabileceğiniz “segmentation violation...” gibi mesajlar bu durumu anlatmaktadır. Koruma mekanizmasına sahip olan işlemcilerde en azından iki çalışma modu bulunur. Bunlardan birine çekirdek modu (kernel mode), diğerine ise kullanıcı modu (user mode) denilmektedir. Eğer kod çekirdek modunda çalıştırılıyorsa işlemci çalışmakta olan koda yönelik hiçbir erişim kontrolü uygulamaz. Yani çekirdek modunda çalışan kodlar belleğin her yerine erişebilir, her makina komutunu işletebilir. Buna karşılık kullanıcı modunda çalışan programlar bellekte ancak kendileri için ayrılan alanlara erişebilirler ve ancak zararsız makina komutlarını işletebilirler. Intel işlemcilerinde çalışan her koda 0, 1, 2, 3 biçiminde belirtilen öncelik derecelerinden biri atanır. 0 en yüksek önceliği, 3 en düşük önceliği belirtir. Yani bu işlemcilerde çekirdek modu ve kullanıcı modu biçiminde 2 çalışma modu değil, toplam 4 çalışma modu vardır. Ancak Windows ve Linux gibi işletim sistemleri yalnızca 0 ve 3 modlarını kullanırlar. 0 çekirdek modunu, 3 ise kullanıcı modunu temsil eder. 1 Kaan Aslan Makale Arşivi – www.kaanaslan.net Pek çok işlemcide fiziksel bellek de sayfa (page) denilen bloklara ayrılmaktadır. Fiziksel bellekteki her sayfanın bir numarası vardır. Sayfa büyüklüklerinin işlemciden işlemciye değişebildiğini belirtelim. Örneğin, Intel işlemcilerinde sayfalar 4 KB, Alpha işlemcilerinde 8 KB uzunluğundadır. (Intel işlemcileri 4 MB’lik sayfalar kullanabiliyorsa da işletim sistemleri 4 MB’lik sayfaları tercih etmiyorlar.) Koruma mekanizmasına sahip işlemcilerde bellekteki bu sayfalara da çekirdek modu, kullanıcı modu biçiminde bir öncelik derecesi atanır. Örneğin, Intel işlemcilerinde her sayfaya 0, 1, 2, 3 öncelik derecelerinden biri atanabilmektedir. (Fakat Windows ve Linux gibi sistemler yine yalnızca 0 ve 3 öncelik derecelerini kullanıyorlar.) Çekirdek modunda çalışan kodlar bellekte her sayfaya erişebilirken kullanıcı modunda çalışan kodlar yalnızca kullanıcı moduna ayarlanmış sayfalara erişebilirler. İşletim sistemi kendi kod ve verilerinin bulunduğu sayfaları çekirdek moduna ayarlar. İşletim sisteminin kendisi çekirdek modunda sıradan prosesler ise kullanıcı modunda çalışmaktadır. Böylece işletim sistemi bellekte her yere erişebilirken sıradan prosesler işletim sisteminin kod ve verilerinin bulunduğu fiziksel sayfalara erişemezler. Sıradan proseslerin işletim sisteminin bellek alanına erişemediğini söyledik. Peki, bir prosesin diğerinin bellek alanına erişmesi nasıl engellenmektedir? Aslında bazı işlemcilerde çalışan kodun yalnızca belirli bir bölgeye (yani kendi bölgesine) erişebilmesi, başka bölgelere erişememesi sağlanabiliyor. (Örneğin, Intel işlemcilerinde bunu sağlamak için betimleyiciler içerisinde offset ve limit değerleri bulunur.) Fakat modern işletim sistemleri işlemcilerin sayfalama mekanizmalarını kullanarak prosesleri birbirlerinden tamamen ayırmaktadır. Windows ve Linux gibi sistemlerde işletim sistemi her proses için bellekte hep aynı yerde dururken, sıradan prosesler bellekte yalnızca kendileri varmış gibi çalışırlar. İşlemcilerin sayfalama mekaznizması ayrıca ele alınması gereken geniş bir konudur. Anlattıklarımızdan bir özet yapalım isterseniz. (Intel işlemcilerinin kullanıldığı bir PC’de çalıştığımızı düşünelim): 1. İşletim sistemi çekirdek modunda (0 öncelik derecesinde), sıradan prosesler kullanıcı modunda (3 öncelik derecesinde) çalışır. 2. İşletim sistemi bellekte her yere erişebilir fakat sıradan prosesler işletim sisteminin bellek alanına erişemez. Çünkü işletim sisteminin yüklü olduğu bellek alanının sayfaları çekirdek moduna (yani Intel’de 0 önceliğe) ayarlanmıştır. 3. Proseslerin bellek alanları birbirlerindne izole edilmiştir. Bir proses kendi alanının dışına çıkarak başka bir prosesin bellek alanına erişemez. Şimdi prosesimizin bir sistem fonksiyonunu çağırdığını düşünelim. Örneğin open fonksiyonuyla bir dosya açmak isteyelim: fd = open(....); open fonksiyonu işletim sisteminin bir sistem fonksiyonudur. Bu fonksiyon da doğal olarak işletim sisteminin kendi alanındaki birtakım veri yapılarına erişerek onlar üzerinde değişiklikler yapacaktır. Peki, proses kullanıcı modunda olduğuna göre open gibi bir sistem fonksiyonu çağrıldığında çekirdek alanına erişim nasıl mümkün olacak? Koruma hatası oluşmayacak mı? İşte kullanıcı modunda çalışan prosesler 2 Kaan Aslan Makale Arşivi – www.kaanaslan.net işletim sisteminin sistem fonksiyonlarını çağırdığında onların öncelikleri geçici olarak çekirdek moduna yükseltilmektedir. Bu duruma çalışmakta olan prosesin kullanıcı modundan çekirdek moduna geçmesi denir. Proses sistem fonksiyonu çalıştığı sürece çekirdek modunda kalır, sistem fonksiyonu geri döndüğünde proses de yeniden kullanıcı moduna geri döner. Buraya dikkat ediniz: Bir proses kendi istediği zaman önceliğini yükselterek çekirdek moduna geçemez. Ancak güvenilir olduğu bilinen sistem fonksiyonları çağrılırken çekirdek moduna geçebilir. Intel işlemcilerinde kullanıcı modundan çekirdek moduna geçişi sağlayan mekznizmaya kapı (gate) denilmektedir.[1][2] Çekirdek modunda çalışacak bir program yazamaz mıyız? Evet yazabiliriz. Bu tür programlara çekirdek modülü (kernel module) ya da aygıt sürücü (device driver) denilmektedir. Bu tür programlar çekirdek modunda çalışırlar. Böylece kullanıcı modundaki programlara yasaklanmış olan IN, OUT gibi makina komutlarını kullanarak çevre birimlerini programlayabilirler. Çekirdek modülleri ve aygıt sürücüler sistem yöneticisi (UNIX türevi sistemlerde root kullanıcısı) tarafından yüklenebildiği için kötü niyetli programların bu yolla sistemi çökertmeleri engellenmiş olmaktadır. [1] Intel mimarisinde çalışan Linux sistemlerinde tüm sistem fonksiyonlarının ana girişi 80H kesmesidir. 80H kesmesine bir tuzak kapısı (trap gate) yerleştirilmiştir. Bu tuzak kapısı yoluyla çekirdek moduna geçiş yapılmaktadır. [2] Daha ayrıntılı bilgi için Kaan Aslan'ın Intel İşlemcileri Korumalı Mod Yazılım Mimarisi isimli kitabının 5. Bölümüne başvurabilirsiniz. 3 Kaan Aslan Makale Arşivi – www.kaanaslan.net