Ders 21 / 21
Çalışma Zamanı Güvenliği
Koşan konteynerin yetkisi iki kısıtlamayla ölçülür: on dört öntanımlı yeteneğin kaçının meşru bir işlemi olduğu ve düşürülenlerin yerine ne konduğu, salt okunur kökün kaç yazma girişimini düşürdüğü, yazılabilir bırakılan yolların açtığı yüzey ve on iki kötüye kullanım girişiminin kaçının kapandığı.
İçindekiler
Önceki ders geliştirme döngüsünü altı adımdan iki adıma indirdi ve bunu yalıtımı bilerek delerek yaptı: kaynak takıldı, derleme adımı atlandı, ortam üretimden uzaklaştı. O ölçümün tamamı hızla ilgiliydi. Üretimde koşan sürecin ne yapabildiği — çekirdekten hangi ayrıcalığı isteyebildiği, hangi dosyaya yazabildiği — hiç sorulmadı.
İki kısıtlama ölçülür: yetenek kısıtlama ve salt okunur kök dosya sistemi. İkisi de öntanımlı açık olanı kapatır ve bedelleri aynı kalemdedir: kapatılanın meşru bir kullanıcısı varsa, yerine bir düzenleme yazılır. Ölçüm nesnesi bölgesel ölçüm ağının okuma toplayıcı servisidir; kurgudur, kip bitleri ve yazma denemeleri gerçektir.
CZ43 — çalışma zamanı konteynere öntanımlı olarak on dört yetenek açık verir; adlar genel karşılıklarıyla yazılır. CZ44 — servisin meşru işlemleri ve her yeteneğin istediği işlem kurgu envanterdir. CZ45 — kötüye kullanım kümesi on iki girişimdir; her girişim ya bir yetenek ya bir yazma yolu ister, biri hiçbirini. CZ46 — salt okunur kök gerçek kip bitleriyle kurulur. CZ47 — çalıştırma yasağı modeldir: yazılabilir yollarda çalıştırma biti yoktur. CZ48 — yanlış alarm, kurala uygun bir işlemin engellenmesidir.
Yetenek Kümesi
Bir yetenek, ayrıcalıklı kimliğin yapabildiği işlerden birini tek başına adlandırır. Öntanımlı küme bir karar değil, geniş tutulmuş bir varsayılandır; ölçülen şey ne kadarının kullanıldığıdır.
// yetenek.mjs — yetenek kumesi ve bilinen kotuye kullanim kumesi (MODEL). // Yetenekler genel adlariyla anilir; hicbir cekirdek sabiti yazilmaz. // [yetenek, isteyen mesru islem (yoksa null), dusurulunce yerine konan] export const YETENEK = [ ['sahiplik degistirme', 'veri dizini sahipligi', 'sahiplik derleme aninda kurulur'], ['kimlik degistirme', 'baslangicta kimlik dusurme', 'surec dogrudan koksuz baslar'], ['ham yuva acma', 'ag tanilama', 'tanilama yardimci konteynerde'], ['surec oldurme', 'gecelik isi durdurma', 'ayni kimlikte yetenek gerekmez'], ['dosya sahipligini yoksayma', 'ortak gunluge ekleme', 'ortak grup ve kip biti'], ['dosya izinlerini yoksayma', null, '-'], ['ayricalikli kapi baglama', null, 'yuksek kapi zaten kullaniliyor'], ['surec izleme', null, 'dokum disaridan tetiklenir'], ['zaman degistirme', null, 'saat konaktan gelir'], ['cihaz dugumu olusturma', null, '-'], ['cekirdek modulu yukleme', null, '-'], ['sistem gunlugu okuma', null, '-'], ['kaynak sinirini asma', null, '-'], ['takma yapma', null, 'takmalar baslamadan kurulur'], ]; // Kotuye kullanim kumesi (kurgu): [girisim, istedigi yetenek, istedigi yazma yolu] export const KOTUYE = [ ['saati geri alma', 'zaman degistirme', null], ['modul yukleme', 'cekirdek modulu yukleme', null], ['baska kimligin dosyasini okuma', 'dosya izinlerini yoksayma', null], ['ham paket dinleme', 'ham yuva acma', null], ['komsu surece baglanma', 'surec izleme', null], ['ham diske erisim', 'cihaz dugumu olusturma', null], ['yeni takma noktasi acma', 'takma yapma', null], ['uygulama kodunu degistirme', null, 'uygulama/toplayici.mjs'], ['baslangic betigine kanca', null, 'uygulama/baslat.sh'], ['ayardaki ucu tasima', null, 'ayar/servis.json'], ['gecici dizine ikili yazip calistirma', null, 'gecici/yuk.bin'], ['takili dizinden okuyup gonderme', null, null], ]; // Servisin bir gecelik kosumda gercekten yazdigi yollar. export const MESRU_YAZMA = ['gunluk/dogrulama.log', 'onbellek/tarife-1.json', 'veri/durum/ilerleme.json', 'veri/duzeltmeler/duzeltmeler.csv', 'gecici/ara-0001.tmp']; export const gereksiz = YETENEK.filter(([, i]) => i === null).map(([y]) => y); export const kullanilan = YETENEK.filter(([, i]) => i !== null); if (import.meta.url === `file://${process.argv[1]}`) { const s = (x, n) => String(x).padStart(n); console.log(`${'mesru islemi olan yetenek'.padEnd(28)}${'islem'.padEnd(28)}dusurulunce yerine`); for (const [y, i, yerine] of kullanilan) console.log(`${y.padEnd(28)}${i.padEnd(28)}${yerine}`); console.log(`\nontanimli acik ${YETENEK.length}, mesru islemi olan ${kullanilan.length}` + `, gereksiz acik ${gereksiz.length}`); const kapanan = (d) => KOTUYE.filter(([, y]) => y && d.includes(y)).length; console.log(`\n${'kisitlama'.padEnd(30)}${s('kapanan', 9)}${s('kacan', 7)}${s('dusen mesru islem', 19)}`); for (const [ad, d] of [['gereksiz yetenekler dusuk', gereksiz], ['butun yetenekler dusuk', YETENEK.map(([y]) => y)]]) { const k = kapanan(d); console.log(`${ad.padEnd(30)}${s(`${k}/${KOTUYE.length}`, 9)}${s(KOTUYE.length - k, 7)}` + `${s(YETENEK.filter(([y, i]) => i && d.includes(y)).length, 19)}`); } console.log(`yetenekle kapanmayan ${KOTUYE.filter(([, y]) => !y).length} girisimin ` + `${KOTUYE.filter(([, y, p]) => !y && p).length} tanesi bir yazma yolu ister`); }
mesru islemi olan yetenek islem dusurulunce yerine sahiplik degistirme veri dizini sahipligi sahiplik derleme aninda kurulur kimlik degistirme baslangicta kimlik dusurme surec dogrudan koksuz baslar ham yuva acma ag tanilama tanilama yardimci konteynerde surec oldurme gecelik isi durdurma ayni kimlikte yetenek gerekmez dosya sahipligini yoksayma ortak gunluge ekleme ortak grup ve kip biti ontanimli acik 14, mesru islemi olan 5, gereksiz acik 9 kisitlama kapanan kacan dusen mesru islem gereksiz yetenekler dusuk 6/12 6 0 butun yetenekler dusuk 7/12 5 5 yetenekle kapanmayan 5 girisimin 4 tanesi bir yazma yolu ister
On dört yeteneğin yalnız beşinin meşru bir işlemi vardır. Kalan dokuz, yalıtım bütçesinde bedeli sıfır olan tek kalemdir: düşürüldüğünde on iki girişimin altısı kapanır ve düşen meşru işlem sıfırdır. Kullanılmayan bir yetkiyi kapatmak bir takas değildir — bu kursta bedelsiz bir kazancın görüldüğü tek yer burasıdır.
Beşi de düşürüldüğünde bir girişim daha kapanır ve beş meşru işlem düşer. Sağ sütun yerine ne konduğunu yazıyor: sahiplik derleme anında kurulur, süreç doğrudan köksüz başlar, tanılama yardımcı bir konteynere taşınır. Düşen beş işlem vazgeçilen bir yetenek değil, başka bir yere taşınan bir iştir; bedel bayt değil yazımdır. Son satır sınırı çiziyor: beş girişim yetenek düşürmeyle kapanmaz, dördü bir dosyaya yazmak ister.
Salt Okunur Kök
İkinci kısıtlama o dört girişimi hedefler. Aşağıdaki koşum kökü gerçek kip bitleriyle kurar — salt
okunur dizinler 0555, yazılabilir bırakılanlar 0755 — ve dokuz yazma denemesini gerçekten yapar.
// salt-okunur.mjs — salt okunur kok gercek dizinlerde: gercek kip bitleri, gercek yazma denemeleri. import { mkdirSync, writeFileSync, chmodSync, rmSync } from 'node:fs'; import { YETENEK, KOTUYE, MESRU_YAZMA } from './yetenek.mjs'; const KOK = './kok'; const DIZIN = ['uygulama', 'ayar', 'veri', 'veri/durum', 'veri/duzeltmeler', 'gunluk', 'onbellek', 'gecici']; const YAZILABILIR = ['veri/durum', 'veri/duzeltmeler', 'gunluk', 'onbellek', 'gecici']; const HEDEF = [...MESRU_YAZMA.map((y) => [y, 'mesru', null]), ...KOTUYE.filter(([, , y]) => y).map(([ad, , y]) => [y, 'kotuye', ad])]; const serbest = () => { // silmeden once kip bitleri geri acilir for (const d of [...DIZIN].reverse()) { try { chmodSync(`${KOK}/${d}`, 0o755); } catch { /* yok */ } } }; const kur = (kip) => { serbest(); rmSync(KOK, { recursive: true, force: true }); for (const d of DIZIN) mkdirSync(`${KOK}/${d}`, { recursive: true }); for (const d of DIZIN) chmodSync(`${KOK}/${d}`, kip(d)); // kip bitleri gercekten kuruluyor }; const dene = (y) => { try { writeFileSync(`${KOK}/${y}`, 'x'); return true; } catch { return false; } }; const s = (x, n) => String(x).padStart(n); console.log(`${'duzen'.padEnd(30)}${s('mesru', 7)}${s('kotuye', 8)}${s('kapanan', 9)}${s('yanlis alarm', 14)}`); let acik = []; for (const [ad, kip] of [['kok yazilabilir', () => 0o755], ['kok salt okunur', () => 0o555], ['salt okunur + yazilabilir yol', (d) => (YAZILABILIR.includes(d) ? 0o755 : 0o555)]]) { kur(kip); const r = HEDEF.map(([yol, tur, kotu]) => [tur, dene(yol), kotu]); const m = r.filter(([t]) => t === 'mesru'), k = r.filter(([t]) => t === 'kotuye'); acik = k.filter(([, ok]) => ok).map(([, , kotu]) => kotu); console.log(`${ad.padEnd(30)}${s(`${m.filter(([, o]) => o).length}/${m.length}`, 7)}` + `${s(`${acik.length}/${k.length}`, 8)}${s(k.length - acik.length, 9)}` + `${s(m.filter(([, o]) => !o).length, 14)}`); } console.log(`yazilabilir birakilan ${YAZILABILIR.length}/${DIZIN.length} yol; acik kalan: ${acik.join(', ')}`); console.log(`calistirma yasagi (model): yazilabilir yollarin 0'inda x biti -> ${acik.length} girisim daha kapanir`); // Birikimli: butun yetenekler dusuk + salt okunur kok + yazilabilir yollar + calistirma yasagi. kur((d) => (YAZILABILIR.includes(d) ? 0o755 : 0o555)); const kacan = KOTUYE.filter(([, y, p]) => !y && !p).map(([ad]) => ad); const mesru = YETENEK.filter(([, i]) => i).length; console.log(`\nbirikimli: kapanan ${KOTUYE.length - kacan.length}/${KOTUYE.length}, kacan ` + `${kacan.length} (${kacan.join(', ')})`); console.log(`kalan yuzey: ${YAZILABILIR.length} yazilabilir yol; acik yetenek ${YETENEK.length} -> 0;` + ` dusen ${mesru} mesru isleme ${mesru} karsilik yazildi`); console.log(`uygulama hala kosuyor mu: ${MESRU_YAZMA.filter((y) => dene(y)).length}/${MESRU_YAZMA.length}` + ' mesru yazma basarili'); serbest(); rmSync(KOK, { recursive: true, force: true });
duzen mesru kotuye kapanan yanlis alarm kok yazilabilir 5/5 4/4 0 0 kok salt okunur 0/5 0/4 4 5 salt okunur + yazilabilir yol 5/5 1/4 3 0 yazilabilir birakilan 5/8 yol; acik kalan: gecici dizine ikili yazip calistirma calistirma yasagi (model): yazilabilir yollarin 0'inda x biti -> 1 girisim daha kapanir birikimli: kapanan 11/12, kacan 1 (takili dizinden okuyup gonderme) kalan yuzey: 5 yazilabilir yol; acik yetenek 14 -> 0; dusen 5 mesru isleme 5 karsilik yazildi uygulama hala kosuyor mu: 5/5 mesru yazma basarili
İkinci satır bu dersin en öğretici satırıdır. Kök tümüyle salt okunur yapıldığında dört yazma girişiminin dördü kapanır — kapanma sayısı en yüksek olan düzen budur — ama beş meşru yazmanın beşi de düşer ve servis hiç koşmaz. Bir kısıtlamayı yalnız kapattığı girişim sayısıyla ölçmek, uygulamanın çalışmadığı düzeni en iyi düzen olarak raporlar.
Üçüncü satır dengeyi kurar: beş yol yazılabilir bırakıldığında meşru yazmalar geri gelir, yanlış
alarm sıfırlanır, kapanan sayısı dörtten üçe iner. Kaybedilen girişim gecici dizinine ikili yazma
girişimidir. Yalıtımın delindiği yer budur: salt okunur kökün açtığı delik, geriye bırakılan
yolların kümesidir ve o küme uygulamanın ihtiyacı kadar büyüktür — sekiz dizinin beşi. Çalıştırma
yasağı bu girişimi de kapatır, çünkü o beş yolun hiçbirinde çalıştırma biti yoktur.
Birikimli satır ikisini üst üste koyar: on iki girişimin on biri kapanır, biri kaçar, uygulama beş meşru yazmasının beşini de yapar. Kaçan girişim ne yetenek ne yazma ister; okuma izni birimler dersinde verilmişti, ağ içi on altı uç ağ dersinde ölçüldüğü gibi kimlik sormuyordu. Kısıtlamalar istenebilecek yetkiyi daraltır, verilmiş olanı geri almaz.
Özet
- On dört öntanımlı yeteneğin beşinin meşru bir işlemi vardır. Kalan dokuzu düşürmek on iki girişimin altısını kapatır ve sıfır meşru işlem düşürür — bu kurstaki tek bedelsiz kalem.
- Beşi de düşürüldüğünde bir girişim daha kapanır ve beş meşru işlem düşer; her birinin yerine bir düzenleme yazılır, yani bedel bayt değil yazımdır.
- Kök tümüyle salt okunur yapıldığında dört yazma girişimi de kapanır ama beş meşru yazma da düşer: en çok kapatan düzen, uygulamanın koşmadığı düzendir.
- Sekiz dizinin beşi yazılabilir bırakıldığında meşru yazma 5/5’e döner, kapanan sayısı üçe iner ve kalan girişim ancak çalıştırma yasağıyla kapanır.
- Birikimli düzende on iki girişimin on biri kapanır ve uygulama koşar; kaçan girişime okuma izni ile ağ erişimi zaten verilmiştir.
Kurs Kapanışı
| Ders | Ortamdan çıkarılan fark | Yalıtımın bedeli | Yalıtımın delindiği yer |
|---|---|---|---|
| Neden Konteyner | 18 farkın 6’sı çıktıda | 84,11 MB; fark başına 14,01 MB | Kaynak sınırı dışarıda; saat ve ad eşleştirme çekirdekte |
| Sunucu, Sanal Makine, Konteyner | 6/18 (sunucu 0, sanal makine 7) | 12 MB bellek, 300 ms, 84 MB disk; yük %6,3 | Çekirdek ortak: saat, sürüm, kusur |
| Alt Yapı Teknolojileri | Yalnız birleşim dosya sistemi; ad alanı 0, denetim grubu 0 | 16 bayt için 4.096 bayt kopya | Numara havuzu ortak; ağırlık tavan değil; silinen 1.024 bayt altta |
| Konteyner Standartları | Çıktı %100, davranış %70 | Doğrulama 83.650.787 bayt okur | Yoruma bırakılan 5 özelliğin 3’ü farklı |
| Konteyner Yaşam Döngüsü | Temizlenirse artık 0 | Durdurulmuş 436 MB, 1 ad, 1 birim; dönemde 13.876 MB | Yalnız süreç kaydı düşer; birim kalır |
| İmaj ve Katman Modeli | Dosya sistemi düzeni 22.526 baytlık depoda | 29.785 → 22.526 bayt; tek satır 8 zincir kimliği | Görünüm dışı 1.559 bayt depoda |
| İmaj Tanım Dosyası | Bağımlılık sürümü tek satıra | Bağlam 15.604 bayt; imaja girmeyen 5.067 | Kopyalananı kaydeder: 7.340 bayt fazla |
| Katman Önbelleği | İş depoya taşındı, ortamdan çıkmadı | Kötü sırada 21 katman, 289.389 bayt (%143,4) | Anahtar metni ölçer: 550 bayt büyüdü, 4 yönerge isabet etti |
| Çok Aşamalı Derleme | Koşumdan 208.222 bayt çıktı (%87,8) | İmaja girmeyen 237.202 bayt | Kopyalama sınırı: geniş yolda 4 dosya döner |
| Temel İmaj Seçimi | 148 / 31 / 6 bileşen içeride | 135,1 / 34,5 / 28,1 MB; 32 ek adım | Üretimi dışarıda: yılda 133 güncelleme |
| Etiketleme Düzeni | İzlenebilirlik 9/24 → 24/24 | İmaj başına 96 bayt, imajın 359 binde biri | Defter depoda: ad taşınmaz |
| İmaj Depoları | 80 referans 27 dosya; 690,0 → 176,2 KB | Yerel 176,2 KB; 27,3 KB silinemez | 7 özel imajın 16 katmanından 9’u genel havuzda |
| İmaj Güvenliği | Envanter ve imza 1.088 bayt | 37 uyarının 8’i yanlış alarm | Silinen anahtar 1.699 bayt altta; 0 uyarı, 1 açık kusur |
| Çalıştırma Seçenekleri | 14 değişken ortamda (9 zorunlu) | 21 tanım satırı; 10,54 dönem gecikme | Sınır tavan: kırpma 4215 birime |
| Geçici Dosya Sistemi | Koşumlar arası artık 0 | 1 bayt → 98.304 bayt; katman 2,15 kat | Alt katman ortak; geçicilik silmeye bağlı |
| Birimler ve Bağlama Takmaları | Yol her makinede aynı | 2 kalıcı dizin; 7.945 bayt kalır | Sayı uzayı ortak: 8 düğümün 6’sı yazılamaz |
| Konteyner Ağı | Makine adı yerine servis adı | 1 ağ tanımı, 1 üyelik satırı (4 → 5) | 16 uç kimlik sormaz; 4 yol iki adımda |
| Kullanıcılar ve İzinler | 15 girdinin 11’i içeride, 4’ü ortamdan | 4 sahiplik düzeltmesi; yazılabilir 15 → 5 | Kimlik konakla ortak: konakta 5/8 yazılır |
| Çok Konteynerli Yerel Ortam | 6 komut, 8 bayrak, 22 diziliş dosyaya | 26 alan; 3 ek adım (3 → 6) | 4 servis 1 ağ, 2 servis 1 birim |
| Geliştirici Deneyimi | İmaj kümesi 10 → 5 dosya | 2 katman, 671 bayt, 6 adım / 0, 0, 2 | Kasten delik: 1 çözülmeyen içe aktarma |
| Çalışma Zamanı Güvenliği | 14 yetenek → 0 | 5 işleme 5 karşılık; 5 yol yazılabilir | 12 girişimin 1’i kapanmaz; 5 yol açık, çekirdek ortak |
Kursun kuralı yirmi bir satırda aynı biçimde okunur: yalıtım bir bütçedir. Çıkarılan her fark bir bayt, bir koşum ya da bir kaynak karşılığında çıkar — 14,01 MB, 4.096 bayt, %143,4 fazla iş, üç ek adım — ve hiçbir yalıtım tam değildir. Son sütunda dört delik tekrar ediyor. Birincisi paylaşılan çekirdektir: saat değeri, sistem çağrısı yüzeyi ve çekirdek kusuru üç ayrı derste aynı yerden geçiyor. İkincisi çıktının içine alınanın çıktıdan çıkarılamamasıdır: görünümden silinen 1.559 bayt da, katmanda kalan 1.699 baytlık anahtar da depoda duruyor. Üçüncüsü paylaşılan sayı uzaylarıdır — süreç numarası, kullanıcı kimliği, kapı numarası; ad alanı görünümü ayırır, sayıyı ayırmaz. Dördüncüsü kuralın yalıtımın dışında durmasıdır: sınırı uygulayan dağıtıcı, etiketi çözen defter, kapıyı açan konak arayüzü ve yetenek kümesini veren çalışma zamanı konteynerin dışındadır.
Bütün bu ölçümlerin ortak bir sınırı vardı: hepsi tek makinede yapıldı. Çıktı taşınabilir oldu, kimliği içeriğinden türedi, yetkisi bir satıra indi. Ama onu kaç kopya, hangi makinede ve ne zaman çalıştıracağına karar veren hâlâ bir insandır. Bu karar bir sisteme devredilebilir mi? Devredilirse o sistemin neyi bilmesi gerekir: kaç kopyanın ayakta olduğunu, bir kopyanın gerçekten hizmet verip vermediğini, hangi makinede ne kadar yer kaldığını, yeni sürüme geçerken kaç kopyayı aynı anda değiştirmenin güvenli olduğunu. M22/K03 Konteyner Orkestrasyonu bu soruyla başlar.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.