Yığıt Yürüyüşü (Stack Walk)

Yığıt Yürüyüşü (Stack Walk) Bu yazımızda .NET Kod Erişim Güvenliğinin temeli olan yığıt yürüyüşünden (stack walk) bahsedeceğiz. Bildiğiniz üzere bütün programlama dilleri yığıt mimarisi üzerine çalışır. Yani bir fonksiyon çağrıldığında tüm yerel değişkenler ve kayıtçıların (register) durumları bir yığıta eklenir. Fonksiyondan çıkarken bu değerlerin tümü yığıttan geri yüklenir. 8086 mimarisinde tanımlanan assembly kurallarına göre örnek bir kullanım şu şekildedir;readfile proc near mov ax,3d02h;dosya aç int 21h mov bx,ax;dosya tutucusunu sakla jc error;hata varsa hata satırına git mov ah,3fh;dosyayı oku mov cx,64000;okunacak byte sayısı mov dx,offset buffer int 21h jc error;hata varsa hata satırına git mov ah,3eh;dosyayı kapat int 21h ret readfile endpBu metot "call readfile" şeklinde çağrılır. Her call işlemi sırasında tüm değişkenler ve kayıtçılar yığıta eklenir. ret ile metottan çıkıldığında yığıta atılan tüm değerler geri yüklenir. Microsoft .NET nedir diye tanımı yapıldığında, .NET yığıt mimarisi üzerine kurulu soyut bir makine üzerinde çalışır denir. .NET alt yapısı gereği her şeyi yığıtlar üzerinde tutarak çalışır. Her fonksiyon çağrıldığında bu yığıtta yeni bir etkin kaydı oluşturulur. Bu kayıtta metoda gönderilen parametreler varsa çalıştıktan sonra program akşının yönelmesini istenen bellek adresi ve varsa yerel değişkenleri içerir. Program çalışırken fonksiyon çağrıldıkça bu yığıt büyür ve fonksiyonlar tamamlandıkça küçülür. Her hangi bir aşamada program sistem kaynaklarına erişmek isteyebilir. Bu erişimden önce bir yetki dahilinde sınırlandırılmış kaynak bir yığıt yürüyüşü isteyebilir. Bu işlemde o metoda gelene kadar tüm metotlarda o kaynağa erişim izni olup olmadığının kontrolü yapılır. Tüm kayıtlar üzerinde yığıt yürüyüşü yapmak yerine, Kod Erişim Güvenliği uygulama geliştiricilere kodun link aşamasında çeşitli kısa notlarla kaynakları kontrol etmesi sağlanabilir. Sadece çağıran metot çalışma zamanda kontrol edilebilir.Çalışma zamanında her hangi bir aşamada örneğin kısıtlı bir kaynağa erişmeden önce, bir metot kendisi çağıranların belirli izinlere sahip olup olmadığını denetlemek isteyebilir. Bu güvenlik kontrolü istemi yığıt yürüyüşünü tetikler. Eğer ki tüm çağıranlar belirtilen izine sahipseler metot çalışmaya devam eder, herhangi birinin bu izne sahip olmaması durumunda güvenlik istisna(exception) atılır. Aşağıdaki şekilde bu işlem gösterilmiştir.

Bu yapıya rağmen fonksiyonlar bu yığıt yürüyüşünü değiştirmek isteyebilirler. Bunun için bir kaç mekanizma vardır. Örneğin bir fonksiyon kendisini çağıran fonksiyonlara kefil olabilir. Yani güvenliği belli bir aşamada kesebilir. Bu seviyenin üstündekiler için güvenlik kontrolü yapma diyebilir. Bu durumda, o fonksiyon belirli bir izni ister. İstenen izni aramak için bir yığıt yüryüşü başlatılırsa, bu fonksiyon için etkin kaydı kontrol edilirken, kontrol işlemi başarıya ulaşacaktır ve eğer ki fonksiyon o hakka sahipse yığıt yüryüşü kesilecektir. Korumalı kaynağa erişmek isteen fonksiyonu çağıran tüm fonksiyonlara eriştiğinden, aslında izin isteme(assert) işlemi kendisi de korumalı bir işlemdir. Çalışma zamanında, izin isteğinde bulunan kodun izin isteme hakkının olup olmadığı da güvenlik sistemi tarafından denetlenir.Bir fonksiyon için yığıt yürüyüşünü değiştirmenin bir diğer yolu da izinleri red etmektir. Bu işlem fonksiyonun kendisinin kullanmaması erişmemesi gereken kısıtlı kaynağı kontrolü ile olur.PermitOnly de aynı şekilde yığıt yürüyüşünün çakılmasını sağlar. Bununla beraber, red etme işlemi bir grup izinin yığıt yürüyüşünün çakılmasına yol açarken, PermitOnly ise yığıt yürüyüşünün çakılmaması için gerekli izinleri belirtir.Bir diğer önemli konu da, bir yığıt çerçevesi herhangi bir anda sadece bir Deny, bir PermitOnly ve bir (Assert)istemenin etkisini sağlayabilir. Örneğin, uygulama geliştiricini bir çok izini bir arada sorgulamak istiyorsa, tüm o izinleri içeren bir "İzin Kümesi" oluşturup tek bir istemde bulunmalıdır. Şu an ki çalışan izin kümesini tek bir yığıt yürüyüşü için kaldırabilmek mümkündür; ki bu sayede yeni bir izin kümesi kayıt edilir. Bu işlem için bir örnek metot vermek gerekirse ; System.Security.CodeAccessPermission.RevertPermitOnlyAşağıdaki örnekte, yukarıda bahsi geçen çeşitli yığıt yürüyüşü işlemi sırasında yığıtı değiştirebilen bir kod yer almaktadır:namespace PermissionDemand { class EntryPoint { static void Main(string[] args) { String f = @"c:System Volume Information"; FileIOPermission p = new FileIOPermission( FileIOPermissionAccess.Write, f); p.Demand(); p.Deny(); p.Demand(); CheckDeny(p); p.Assert(); CheckDeny(p); } static void CheckDeny(FileIOPermission p) { try { p.Demand(); } catch(SecurityException) { Console.WriteLine("Demand failed"); } } } } Şimdi kodu biraz dikkatli incelersek, anlatılmak istenenleri biraz daha iyi anlayacağımızı düşünüyorum. İlk demand kısıtlandırılmış bir dosyaya erişiyor olmasına rağmen başaracaktır. Hatırlayınız ki, çalışma zamanı güvenlik sistemi üzerinde çalıştığı işletim sistemi ayarlarının da üzerinde çalışmaktadır. Bu sebepten çalışma zamanı güvenlik politikası yönetilen kodun erişmeye çalıştığı işletim sisteminin erişim ihlallerini alacağı dizinlere erişim hakkını kendisine alır. Deny" dan sonra ki demand da başaracaktır. İstekte bulunan fonkiyonun etkin kaydı kontrol edilmektense onu çağıran fonksiyonların etkin kaydı kontrol edilecektir. Bu yüzden fonksiyonun kendisi izni red etmiş olmasına rağmen Demand çalışacaktır ve bu Demand tarafından yakalanamayacaktır. CheckDeny fonksiyonu ise çakılacaktır. Artık Deny komutu çağıranın yığıt çerçevesinde yer almaktadır. Ardından tekrar main"e geri geleceğiz ve burada bir izin istenmiştir ve bu izin bu yığıt çerçevesinde rededilmiştir. Tekrar CheckDeny fonksiyonu çağırdığımızda yine bir güvenlik istisnası tetiklenecektir. "Assert" ile izin kabul edilmiş olmasına karşın tekrar demand çakılacaktır. Çünkü her zaman Deny komutları assert den önce çalıştırılır. Bu programın sonucunda beklediğimiz gibi iki sefer "Demand failed" yazacaktır.Bir güvenlik kontrolü için tanıtan(declarative) ve zorunlu(imperative) gibi iki ayrı yöntem vardır. Tanıtan koda örnek vermek istersek;[PrincipalPermissionAttribute(SecurityAction.Demand,Name=@"Yetki Adı")] protected void ÖrnekMetot() { ... }Zorunlu koda örnek ise;FileIOPermission p = new FileIOPermission( FileIOPermissionAccess.Write, f); p.Demand();şeklinde verilebilir.Kod Erişim Güvenliğinin temeli olan yığıt yürüyüşünü detaylı bir şekilde incelediğimiz bu makaleden sonra Kod Erişim Güvenliğine biraz ara vererek "Rol Tabanlı Güvenlik" sistemlerini inceleyeceğiz. Aslında "Rol Tabanlı Güvenlik" sistemleri günümüz işletim sistemlerinin temelini oluşturmaktadırlar..Not : Bu makale Don Box"ın "The Security Infrastructure of the CLR Provides Evidence, Policy, Permissions, and Enforcement Services" ve MSDN"nin ilgili konu anlatımlarının yer aldığı "An Overview of Security in the .NET Framework" makalelerinden derlenmiştir.Yazar : Yunus Emre ALPÖZENe-Posta : yunus.alpozen et msakademik.net

Döküman Arama

Başlık :

Kapat