2.07.2012

Linux IO monitoring

VMware Server'ın yüklü olduğu linux sistemde kaynak sorunları yaşamamın üzerine sorunun bellek mi, işlemci mi yoksa disk mi olduğunu anlamaya çalıştım. Ama bu kolay olmadı. Window'da aşina olduğum Performans Monitor benzeri bir araç linux server'da yoktu. Bunun için araştırmaya başladım.

Biraz önbilgi. Linux çekirdeği disk IO'yu sayfalara böler. Birçok sistemde varsayılan sayfa boyutu 4K dır ($ getconf PAGESIZE komutu ile çalışan sistemin Page Size boyutunu görebilirsiniz). Linux, fiziksel adres alanı ile eşleştirilen bir "sanal bellek alanı" katmanı kullanır. Bir uygulamanın ihtiyaç duyduğu veri önce CPU cache'inde, daha sonra fiziksel bellekte aranır. Bulunamazsa bir majör sayfa hatası (MPF) oluşur ve aranan veri diskten okunarak RAM'deki tampon belleğe yazılır. Tampon bellekteki verilere erişim çağrıları minör sayfa hatasına (MnPF) sebep olur. MPF'ları azaltıp MnPF'ları artırmak için disk erişimlerinde buffer (yazma işlemleri için ayrılan tampon bellek) ve cache (okuma işlemleri için ayrılan tampon bellek) kullanılır. Bir sistemdeki toplam bellek miktarı, kullanılan bellek, buffer ve cache değerlerini
#cat /proc/meminfo
Komutu ile öğrenebiliriz.

Bir sistemde üç tip bellek sayfası vardır:
Read Pages: MPF ile diskten okunan sayfalar. Bellekte read-only olarak tutulur. Kütüphane dosyaları gibi hiç değişmeyecek dosyaların ait verileri içerirler. Çekirdek ihtiyaç duydukça bunları kullanır. Bellek sıkıntısı olması durumunda bir kısmı boş olarak işaretlenir, uygulamalar buradaki verilere tekrar ihtiyaç duyduğunda MPF'lerle onları tekrar belleğe getirir.
Dirty Pages: Bu alandaki veriler çekirdek tarafından değiştirilen verilerdir. Değişiklikler diskteki veriye, pdflush daemon tarafından, yansıtılmak (senkronize edilmek) zorundadır. Bellek sıkıntısı olduğunda buradaki veriler kswapd (ve pdflush) ile diske yazılarak yer açılabilir.
Anonymous Pages: Bu tip bellek alanları bir sürece ait değildir ve diskteki bir dosya ile senkronize edilmezler. Bellek sıkıntısı olduğunda buradaki veriler (kswapd ile) takas bölümüne yazılır.

İlk önce bulduğum araç iostat idi. Kullanabilmek için Ubuntu ve Fedora'da sysstat paketini kurmak gerekli.
Cyberciti'de güzelce açıklanmış. Örnek bir kullanım şöyle:

$ iostat -d -x 2 2
Device:  rrqm/s  wrqm/s  r/s   w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
fd0      0.00    0.00    0.00  0.00   0.00     0.00     8.00     0.00   10.32  10.32   0.00
sda      0.01    5.92    0.07  4.98   2.88    87.32    17.87     0.69  137.16   1.48   0.75

Device:  rrqm/s  wrqm/s  r/s   w/s   rsec/s   wsec/s avgrq-sz avgqu-sz   await  svctm  %util
fd0      0.00    0.00    0.00  0.00   0.00     0.00     0.00     0.00    0.00   0.00   0.00
sda      0.00  1130.00   2.50 28.50 368.00  9268.00   310.84     0.23    7.42   1.77   5.50


iostat'ın parametrelerinden d disk kullanım verilerini, x ise ayrıtılı (eXtended) verileri göstermesini sağlıyor. Sonraki sayılardan ilki kaç saniye arayla tekrar verileri göstereceğini, sonraki ise kaç kez bu işlemi tekrarlayacağını gösteriyor. Ben 2 saniye arayla 2 kez istedim. Gösterilen verilere gelirsek

rrqm/s (Read ReQuests Merged per second): Sanyiede birleştirilmiş okuma istekleri (diskte sıraya alınmış)
wrqm/s (Write ReQuests Merged per second): Saniyede birleştirilmiş yazma istekleri (diskte sıralya alınmış)
r/s (Reads per second): Saniyedeki okuma istekleri
w/s (Writes per second): Saniyedeki yazma istekleri
rsec/s (Read Sectors per second): Saniyede okunan sektör sayısı
wsec/s (Write Sectors per second): Saniyede yazılan sektör sayısı
avgrq-sz (AVeraGe ReQuest sector SiZe ): Diske gelen tüm isteklerin sektör sayısı olarak ortalaması
avgqu-sz (AVeraGe ReQuest QUeue SiZe): Diske gelen tüm isteklerin kuyruk uzunluğu olarak ortalaması
await: Diske gelen tüm isteklerin ortalama (milisaniye) karşılanma süresi (kuyrukta bekleme + işlem)
svctm (SerViCe TiMe): Diske gelen tüm isteklerin ortalama işlem süresi (= await - queue time)
%util (bandwidth utilization): Diskin bant genlişliği kullanımı. %100'e yakın olması sınıra yaklaşılmış demek.

İkinci olarak iotop adındaki araç buldum.iotop varsayılan olarak etkileşimli olarak çalışan, sürekli olarak süreçlerin DISK READ ve DISK WRITE değerlerini görüntüleyen bir araç. Kullanabilmek için Ubuntu ve Fedora'da iotop paketini kurmak gerek. Örnek kullanım şöyle:

$ iotop -o

Total DISK READ: 93.45 K/s | Total DISK WRITE: 124.60 K/s

  TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN     IO>    COMMAND
 2590 be/3 root        0.00 B/s  797.45 B/s  ?unavailable?  [kjournald]
 4203 be/3 root        0.00 B/s 1594.90 B/s  ?unavailable?  [kjournald]
15645 be/2 root        0.00 B/s  797.45 B/s  ?unavailable?  vmware-vmx -C /vmacs/TESTM~ndard x64 Edition.vmx -@ ""
15649 be/2 root        0.00 B/s  797.45 B/s  ?unavailable?  vmware-vmx -C /vmacs/TESTM~ndard x64 Edition.vmx -@ ""
15652 be/4 root        0.00 B/s  353.56 K/s  ?unavailable?  vmware-vmx -C /vmacs/TESTM~ndard x64 Edition.vmx -@ ""
15656 be/2 root        0.00 B/s  450.12 K/s  ?unavailable?  vmware-vmx -C /vmacs/TESTM~ndard x64 Edition.vmx -@ ""
15661 be/2 root       17.13 K/s  797.45 B/s  ?unavailable?  vmware-vmx -C /vmacs/TESTM~ndard x64 Edition.vmx -@ ""
15662 be/2 root        2.34 K/s  797.45 B/s  ?unavailable?  vmware-vmx -C /vmacs/TESTM~ndard x64 Edition.vmx -@ ""
15663 be/2 root        6.23 K/s  797.45 B/s  ?unavailable?  vmware-vmx -C /vmacs/TESTM~ndard x64 Edition.vmx -@ ""
15664 be/2 root       58.41 K/s  797.45 B/s  ?unavailable?  vmware-vmx -C /vmacs/TESTM~ndard x64 Edition.vmx -@ ""
15666 be/2 root        9.35 K/s 1594.90 B/s  ?unavailable?  vmware-vmx -C /vmacs/TESTM~ndard x64 Edition.vmx -@ ""
15667 be/2 root        0.00 B/s 1594.90 B/s  ?unavailable?  vmware-vmx -C /vmacs/TESTM~ndard x64 Edition.vmx -@ ""
15668 be/4 root        0.00 B/s  276.46 K/s  ?unavailable?  vmware-vmx -C /vmacs/TESTM~ndard x64 Edition.vmx -@ ""



Burada SWAPIN ve IO sütunlarının altında ?unavailable? yazmasının sebebini ekranın altındaki

CONFIG_TASK_DELAY_ACCT not enabled in kernel, cannot determine SWAPIN and IO %

hatasıyla açıklamış. Buna göre kernel'i uygun config ile tekrar derlemek gerek. Etkileşimli çalışma kipinde sağ ve sol ok tuşlarını kullanarak verilerin hangi alana göre sıralanacağını seçebiliriz. Seçilen alanın yanında bir ">" işareti belirir. Komut satırında kullandığım -o anahtarı ise sadece I/O yapan süreç ve thread'leri göster demek.

Üçüncü olarak budluğu araç ise vmstat. Bunu kullanabilmek için de sysstat paketini kurmak gerekli. Ben en çok bunu sevdim. Komut satırından çalıştırırken sadece kaç saniyede bir güncel verileri görüntüleyeceğini seçmek gerekiyordu, 1 ile ben her saniye görüntülemesini belirttim. Durdurana kadar her saniye yeni bir satır ekleyerek verileri tekrar yazıyor:

$ vmstat 1
procs  -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
 r  b   swpd   free   buff  cache    si   so    bi    bo   in   cs us sy id wa
 0  1  27800  39548  14796 3500092    0    0  2720     0  145 1991  1  3 88  8
 0  5  27800  36204  14828 3502532    0    0  2644   520  194 2258  0  3 65 32
 0  5  27800  33804  14848 3504596    0    0  2116     4  348 1922  1  3 26 70
 0  1  27800  30848  14892 3506260    0    0  1584     0  232 2508  1  3 71 25
 0  1  27800  26772  14940 3509760    0    0  3396     0  279 2924  1  4 74 21
 0  1  27800  23332  14992 3512740    0    0  3028     0  225 2501  0  4 74 22
 0  3  27800  25696  14984 3508956    0    0  1816   816  239 2168  0  5 59 36
 0  3  27800  25368  15004 3509372    0    0   332  1408  486 1123  0  1 40 59
 0  3  27800  29500  13272 3506900    0    0  1352   344  338 2122  1  2 32 64
 1  2  27800  27004  13284 3509260    0    0  2308     0  230 2060  1  3 53 42
 0  3  27800  30180  13288 3509732    0    0   748     0  152 2104  0  9 66 25
 0  2  27800  25196  13324 3511936    0    0  1888     0  853 2381  3 12 52 33
 1  2  27800  23768  13336 3513756    0    0  1832    48 1285 2756  5  9 60 26


Yukarıda görülen alanların anlamları (veri miktarı birimi KiB)
r (runtime):  "Number of processes waiting for runtime". Çalışmak için bekleyen süreç sayısı diyelim. Ya süreç IO bekliyor, ya da CPU meşgul, bu sebeple bazı süreçler henüz görevlerini tamamlayamamış.
b (blocked): IO kaynağı eksikliği sebebiyle hizmet verilemeyen thread sayısı (başka bir kaynakta ise bekleme sebebinin IO olmayabileceği yazıyordu).
swpd: Kullanılan sanal bellek miktarı
free: Kullanılmayan bellek miktari
buff: Yazma işlemleri için ayrılan tampon bellek miktarı (RAM)
cache: Okuma işlemleri için ayrılan tampon bellek miktarı (RAM)
si (swap-in): Swap'ten okunan bellek miktarı
so (swap-out): Swap'e yazılan bellek miktarı
bi (block-in): Diskten okunan blok miktarı
bo (block-out): Diske yazılan blok miktarı
in: Saniyede gelen kesme (interrupt) sayısı (saat dahil)
cs: Saniyede yapılan context switching sayısı

Toplam CPU zamanını (% olarak) şöyle açıklayabiliriz:

%CPU zamanı = %Kullanıcı_süreçleri + %Kernel_süreçleri + %Boşta_zaman + %WIO

Buna göre (tümü yüzde olarak):
us: Kullanıcı süreçlerinin işletilmesine harcanan CPU zamanı
sy: Kernel (çekirdek) süreçlerini işletmek için harcanan CPU zamanı
id: Idle. CPU'nun boşta durma zamanı
wa: WIO, ya da wait-IO. CPU zamanın IO işlemlerini beklemek için harcanan kısmı

Artık şöyle yazabiliriz:
%CPU zamanı=us + sy + id + wa

vmstat ile ilgili güzel bir açıklama şu adreste var.

2019-08-28 Ek: vmstat sonuçlarının grafiğinin çizilmesi ile ilgili güzel bir proje buldum. git clone ile önce bir klasöre kopyaladım. vmstat değerlerini dosyaya yazabilmek için önce ekranda gördüğümüz sonuçları bir dosyaya yazmak lazım. En basit haliyle
 # vmstat 1 > vmstat.txt
ile ekrana basmadan doğrudan dosyaya, ya da hem ekrana hem dosyaya göndermek için
# vmstat 1 | tee vmstat.txt
ile verileri dosyada biriktirdikten sonra clone'ladığımız klasörün içindeki index.html dosyasını browser ile açıp, vmstat.txt dosyasını sürükleyerek browser penceresinin ortasındaki alana bırakmamız, ya da hiç yerele girmeden doğrudan http://jsargiot.github.io/vmstatly/ adresinden çalışmamız mümkün.

Referanslar:
[1] www.ufsdump.org/papers/io-tuning.pdf

1.07.2012

Tespitin zorluğu

Siber-tehditler gün geçtikçe daha da karmaşlıklaşıyor. Tespit edilmeleri zorlaşıyor. Eskiden antivirüs yazılımları sadece imzaya dayalı tarama teknikleri kullanırlardı. Şimdi daha tanınmamış olan virüsleri de bulabilmek için yeni teknikler kullanmaya başladılar.

Elbette hiçbir antivirüs yazılımı mükemmel değil. Bir süre öncesine kadar antivirüs yazılımlarının tespit edemediği virüsleri Sysinternals'ın araçları gibi programlar kullanarak tespit etmenin mümkün olduğunu düşünürdüm. Artık fikrim değişti.

Bir dosyanın "şüpheli" sınıfına girebilmesi için birkaç koşul vardır (ya da eskiden vardı):
  1. Dosya adı. Dosya adı saçma sapan karakterlerden oluşmuşsa bu birinci sırada dikkat çeken bir özellik olurdu. Bu sebeple birçok zararlı kod dosyalarının isimlerini sistem dosyalarının isimlerine benzetmeye, veya doğrudan onların isimlerini vermeye yönelmişti. Örneğin svchost.exe gibi. %systemroot%\system32 klasörünün haricinde bir konumda karşılaşılan svchost.exe dosyası bir numaralı zanlı olurdu.
  2. Üretici bilgisi ve dosya tanımı. 16 bitlik çalıştırılabilir dosyalar hariç diğer çalıştırılabilir dosyalarda bir metadata bilgisi yer alır. Burada dosyanın üreticisi ve dosyanın adının haricinde bir de dosyanın tanımı yer alır. Bu bilgiler de bir fikir verirdi. Sistemdeki bir donanımın sürücüsünün mü, antivirüs yazılımının mı olduğu hakkında bir yol gösterirdi. Daha sonra geçerli bir dosya olup olmadığını anlamak kolaylaşırdı.
  3. Sayısal imza. Yukarıdaki yöntemleri sıradan bir kötü amaçlı programcı bile kendi kötü amaçlı yazılımına uygulayabilirdi. Bunun için sayısal imza diye bir konu vardı. Üreticiler sürücülerini imzalar, veya çalıştırılabilir dosyalarının da kendileri tarafından üretildiğini kanıtlamak için sayısal imza kullanırlardı.
Ancak yeni tehditler artık bu yöntemlerin ne kadar cılız kaldığını gösterdi. Örneğin bir süre önce Mark Russinovich'in blog'unda incelediği Stuxnet virüsü.

Bulaşma yöntemi mükemmel. Windows 7'de bile var olan bir açığı kullanarak USB sürücüler üzerinden bulaşıyor (ki bu açık Ağustos 2010'da KB2286198 yamasıyla kapanmış). Bilgisayarınıza taktığınız USB sürücüde gayet zararsız gibi görünen birkaç dosya var. Bunlardan birisi bir kısayol. Ama kısayolun ikonu yok. Windows Explorer ikonu okumak için işaret edilen dosyaları okumaya çalışınca Windows'un açığını kullanarak virüs sisteme bulaşıyor. Bundan sonra da bu dosyalar rootkit teknikleriyle gizleniyor.

Sisteme bulaşan bileşen ise MRxNet.exe ismiyle Windows klasörüne kopyalanıyor. Virüs bunu gizleme zahmetine girmemiş. Daha iyisini yapıp bunu bir donanımın sürücüsü gibi göstermiş. Üstelik bunu Realtek ve JMicron gibi donanım üreticilerinin sertifikalarını kullanarak yapmış. Kullanılan sertifikaların çalındığı ve dağıtan şirket tarafından farkedildikten sonra iptal edildiği belirtilmiş.

Mark Russinovich, yazılarında (1,2,3) ayrıntılı olarak bulaşma adımlarını inceleyerek tespit edilebilirliğini göstermiş, ama bu yöntemler gayet ileri seviye yöntemler.

Sonuçta Stuxnet'in İsrail hükümetinin desteklediği bir proje kapsamında geliştirildiği ve gayet açık bir şekilde İran'daki santrallerde kullanılan Siemens marka ürünleri hedef aldığı yönünde spekülasyon ötesi bazı iddialar var. Bu önemli değil. Önemli olan yeteri kadar güçlü motivasyonla nelerin yapılabiliyor olduğu. Artık korkmak lazım.