Yanıtlar:
Aslında, çoğu platformda, sadece bir hata ile başarısız olur, ancak bu donanım mimarisine bağlıdır. Komutu ayrıcalıksız bir kullanıcı olarak çalıştırmadığınız sürece bunun kesinlikle zararsız olduğuna dair bir garanti yoktur. Ayrıcalıksız bir kullanıcıyla, açamadığınız için komut tamamen zararsızdır /dev/mem
.
Kök olarak bir komut çalıştırdığınızda, ne yaptığınızı bilmeniz gerekir. Çekirdek bazen tehlikeli bir şey yapmanızı engeller, ancak her zaman değil. /dev/mem
gerçekten ne yaptığınızı bilmeniz gereken potansiyel olarak tehlikeli şeylerden biridir.
Bir yazının /dev/mem
Linux'ta nasıl çalıştığını inceleyeceğim. Genel ilke diğer Unices için aynıdır, ancak çekirdek seçenekleri gibi şeyler tamamen farklıdır.
Bir işlem bir aygıt dosyasını okuduğunda veya bir dosyaya yazdığında çekirdeğe kadar olur. Bir aygıt dosyasına erişim, sürücüde bu aygıt dosyasını işleyen bazı kodlar çalıştırır. Örneğin, yazma /dev/mem
fonksiyonu istemektedir write_mem
içindedrivers/char/mem.c
. Bu işlev 4 argüman alır: açık dosyayı temsil eden bir veri yapısı, yazılacak verilere bir işaretçi, yazılacak bayt sayısı ve dosyadaki geçerli konum.
Yalnızca arayanın dosyayı ilk etapta açma izni varsa bu kadar ileri gidebileceğinizi unutmayın. Aygıt dosyaları dosya izinlerine normal olarak uyar. Normal izinleri /dev/mem
vardır crw-r-----
aittir root:kmem
sen olmak root olmadan yazma için açmaya çalışırsanız, bu nedenle, sadece alırsınız (EACCESS) “izin reddedildi”. Ancak root iseniz (veya root bu dosyanın izinlerini değiştirdiyse), açılış gerçekleşir ve daha sonra bir yazma girişiminde bulunabilirsiniz.
İşlevdeki kod write_mem
bazı sağlık kontrolleri yapar, ancak bu kontroller kötü olan her şeye karşı koruma için yeterli değildir. Yaptığı ilk şey, geçerli dosya konumunu *ppos
fiziksel bir adrese dönüştürmektir. Bu başarısız olursa (pratikte, 32 bit fiziksel adresleri ancak 64 bit dosya ofsetleri olan ve dosya ofseti 2 ^ 32'den büyük bir platformda olduğunuz için, yazma işlemi EFBIG (dosya çok büyük) ile başarısız olur. Bir sonraki kontrol, yazılacak fiziksel adres aralığının bu özel işlemci mimarisinde geçerli olup olmadığı ve bir başarısızlığın EFAULT (hatalı adres) ile sonuçlanıp sonuçlanmadığıdır.
Daha sonra, Sparc ve m68k'de, ilk fiziksel sayfadaki yazmanın herhangi bir kısmı sessizce atlanır.
Artık bir MMU sayfasına sığabilecek bloklar halinde veriler üzerinde yinelenen ana döngüye ulaştık .
sanal belleğe değil, fiziksel belleğe erişir, ancak verileri belleğe yüklemek ve depolamak için işlemci talimatları sanal adresler kullanır, bu nedenle kodun fiziksel belleği bazı sanal adreslerde eşlemek için ayarlanması gerekir. Linux'ta, işlemci mimarisine ve çekirdek yapılandırmasına bağlı olarak, bu eşleme ya kalıcı olarak bulunur ya da anında yapılmalıdır; bu işin (ve ne yaparsa yapsın). Daha sonra işlev , aktarılan arabellekten okur./dev/mem
xlate_dev_mem_ptr
unxlate_dev_mem_ptr
xlate_dev_mem_ptr
copy_from_user
write
sistem çağrısı ve fiziksel belleğin şu anda eşlendiği sanal adrese yazar. Kod normal bellek deposu talimatlarını yayar ve bunun anlamı donanıma bağlıdır.
Fiziksel bir adrese yazmanın yapmadan bahsetmeden önce, bu yazmadan önce gerçekleşen bir kontrolü tartışacağım. Döngü içinde, page_is_allowed
çekirdek yapılandırma seçeneği CONFIG_STRICT_DEVMEM
etkinse işlev blokları belirli adreslere erişir (varsayılan olarak durum budur): yalnızca izin verilen adreslere devmem_is_allowed
ulaşılabilir /dev/mem
, diğerleri için yazma işlemi EPERM ile başarısız olur (işleme izin verilmez). Bu seçeneğin açıklaması şunları belirtir:
Bu seçenek açıksa ve IO_STRICT_DEVMEM = n ise, / dev / mem dosyası yalnızca PCI alanına, BIOS koduna ve veri bölgelerine kullanıcı erişimine izin verir. Bu, dosemu ve X ve / dev / mem'in tüm yaygın kullanıcıları için yeterlidir.
Bu çok x86 merkezli bir açıklama. Aslında, daha genel olarak, CONFIG_STRICT_DEVMEM
RAM ile eşlenen fiziksel bellek adreslerine erişimi engeller, ancak RAM ile eşleşmeyen adreslere erişime izin verir. Hangi fiziksel adres aralıklarına izin verildiğinin ayrıntıları işlemci mimarisine bağlıdır, ancak hepsi çekirdek ve kullanıcı arazi işlemlerinin verilerinin depolandığı RAM'i hariç tutar. Ek seçenek CONFIG_IO_STRICT_DEVMEM
(Ubuntu 18.04'ten itibaren devre dışı bırakılmıştır), bir sürücü tarafından talep edilen fiziksel adreslere erişimi engeller.
RAM ile eşlenen fiziksel bellek adresleri . RAM ile eşleşmeyen fiziksel bellek adresleri var mı? Evet. Bu, bir adrese yazmanın ne anlama geldiğine dair söz verdiğim tartışma.
Bellek deposu talimatı RAM'a mutlaka yazmaz. İşlemci adresi ayrıştırır ve mağazanın hangi çevre birimine gönderileceğine karar verir. (“İşlemci” dediğimde, aynı üreticiden gelmeyebilecek çevresel denetleyicileri kapsıyorum.) RAM, bu çevre birimlerinden sadece biri. Dağıtımın nasıl yapıldığı işlemci mimarisine çok bağlıdır, ancak temeller tüm mimarilerde aşağı yukarı aynıdır. İşlemci temel olarak adresin yüksek bitlerini ayrıştırır ve bunları sabit kodlanmış bilgilere, bazı otobüsleri inceleyerek elde edilen bilgilere ve yazılım tarafından yapılandırılan bilgilere dayalı olarak doldurulmuş bazı tablolarda arar. Çok fazla önbellekleme ve tamponlama söz konusu olabilir, ancak kısaca, bu ayrışmadan sonra,otobüs ve sonra onunla başa çıkmak için çevre birime kalmış. (Veya tablo aramasının sonucu, bu adreste bir çevre birimi olmaması olabilir; bu durumda işlemci , çekirdekte normalde çağrı işlemi için SIGBUS ile sonuçlanan bir kod yürüttüğü bir tuzak durumuna girer .)
RAM ile eşlenen bir adrese yapılan bir mağaza, daha önce bu adreste depolanan değerin üzerine yazmak dışında hiçbir şey yapmaz ve aynı adresteki daha sonraki bir yükün son depolanan değeri geri vereceğine dair söz verir. Ancak RAM'in bile bu şekilde davranmayan birkaç adresi vardır: yenileme hızı ve voltaj gibi şeyleri kontrol edebilen birkaç kaydı vardır.
Genel olarak, bir donanım kaydına bir okuma veya yazma işlemi, donanımın programlandığı her şeyi yapar. Donanıma çoğu erişim bu şekilde çalışır: yazılım (normalde çekirdek kodu) belirli bir fiziksel adrese erişir, bu işlemciyi çevreye bağlayan veri yoluna ulaşır ve çevre birimi işini yapar. Bazı işlemciler (özellikle x86), bellek yükünden ve depodan farklı olan çevre birimlerine okuma / yazma işlemlerine neden olan ayrı CPU komutlarına sahiptir, ancak x86'da bile, birçok çevre birimine yükleme / depolama yoluyla ulaşılır.
Komut dd if=/dev/urandom of=/dev/mem
, 0 adresinde eşlenen çevre birimine rastgele veriler yazar (ve yazma işlemleri başarılı olduğu sürece sonraki adresler). Uygulamada, pek çok mimaride, fiziksel adres 0'ın kendisiyle eşlenmiş herhangi bir çevre birimi bulunmamasını veya RAM'in bulunmamasını ve bu nedenle ilk yazma girişiminin başarısız olmasını bekliyorum. Ancak 0 adresinde eşlenen bir çevre birimi varsa veya farklı bir adrese yazma komutunu değiştirirseniz, çevre biriminde öngörülemeyen bir şeyi tetiklersiniz. Artan adreslerdeki rastgele verilerle, ilginç bir şey yapmak olası değildir, ancak prensipte bilgisayarı kapatabilir (muhtemelen bunu yapan bir adres olabilir), önyüklemeyi imkansız kılan bazı BIOS ayarlarının üzerine yazabilir veya hatta bazılarına vurabilir zarar veren bir şekilde buggy periferik.
alias Russian_roulette='dd if=/dev/urandom of=/dev/mem seek=$((4096*RANDOM+4096*32768*RANDOM))'
CONFIG_STRICT_DEVMEM
etkinse , çekirdeğe zarar veremezsiniz .
Manuel sayfa belleği başına (4) :
/ dev / mem, bilgisayarın ana belleğinin görüntüsü olan bir karakter aygıtı dosyasıdır. Örneğin, sistemi incelemek (ve hatta düzeltmek) için kullanılabilir.
Yani teoride, dd if=/dev/urandom of=/dev/mem
yüklediğiniz fiziksel bellek tüm adres alanını üzerine olmalı ve çekirdek ve diğer programlar bellekten çalıştırmak beri bu olmalıdır etkili bir sistem çökmesine. Pratikte sınır var. Aynı kılavuz sayfasından:
Linux 2.6.26'dan beri ve mimariye bağlı olarak, CONFIG_STRICT_DEVMEM çekirdek yapılandırma seçeneği bu dosya üzerinden erişilebilen alanları sınırlar.
Bunu sanal makine Ubuntu 18.04'te deneyerek, kök izinlerine rağmen ve dd: writing to '/dev/mem': Operation not permitted
hatta sudo
izinlere rağmen bir hata döndürür crw-r-----
. Gönderen Ubuntu Wiki :
/ dev / mem koruması
Bazı uygulamaların (Xorg) fiziksel bellekten kullanıcı alanından doğrudan erişmesi gerekir. Bu erişimi sağlamak için / dev / mem özel dosyası var. Geçmişte, bir saldırganın root erişimine sahip olması durumunda bu dosyadaki çekirdek belleğini görüntülemek ve değiştirmek mümkün olmuştur. Aygıt dışı bellek erişimini engellemek için CONFIG_STRICT_DEVMEM çekirdek seçeneği tanıtıldı (başlangıçta CONFIG_NONPROMISC_DEVMEM olarak adlandırıldı).
Bu yüzden teknik olarak hayır, güvenli değildir (sistemi çökeceğinden beri) ve çekirdek seçeneği CONFIG_STRICT_DEVMEM
devre dışı bırakılırsa bu bir güvenlik açığıdır, ancak şu ana kadar gördüğüm kadarıyla bu seçenek etkinleştirilirse komut çalışmaz. Göre siteler arası ikişer , yeniden başlatma onunla herhangi bir sorun çözecektir, ancak o zaman RAM içinde elbette veriler kaybolur ve (herhangi biri olsaydı) diske temizlenip değil olacaktı.
Daha önce bağlanan kopyada önerilen bir yöntem var, busybox devmem
bu yüzden RAM ile uğraşmaya karar verirseniz, sonuçta bir yol olabilir.
CONFIG_STRICT_DEVMEM
, bir çevre biriminin eşleştirildiği bellek bölgelerine erişebilirsiniz, bu da sahip olmanın tüm noktasıdır /dev/mem
. Çevre birimlerine rastgele şeyler yazarsanız, herhangi bir şey olabilir. Eşlenmemiş bir adrese erişmeye çalışırsanız ve komut 0 adresinden başlarsa “işleme izin verilmiyor” iletisi alırsınız. 0 adresinin kötü bir şeyle eşleşip eşleşmeyeceği donanım mimarisine bağlıdır. Bildiğim kadarıyla hiçbir zaman bir PC'deki hiçbir şeyle eşleşmeyebilir, ancak genel olarak güvenli değildir.
head -c 1024 </dev/mem | od -tx1
) vardır, ancak işlemci gerçek modda (8088 modu) olmadığında bunların kullanılıp kullanılmadığını bilmiyorum. 64-bit modunda kullanılabileceklerini sanmıyorum: sonuçta 8088 kesinti vektörlerinin adres için sadece 32 bitleri var. Ve bu arada CONFIG_STRICT_DEVMEM
set ile erişilebilir , bu yüzden sanırım Linux bunu kullanmıyor.