İçeriğe geç
academia.sh

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.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat