Korumalı alana alma

Sorun bildir Kaynağı göster

Bu makalede, Bazel'da korumalı alana alma ve korumalı alana alma ortamınızda hata ayıklama işlemleri açıklanmaktadır.

Korumalı alan, işlemleri birbirlerinden veya bir sistemdeki kaynaklardan izole eden bir izin kısıtlama stratejisidir. Bazel için bu, dosya sistemi erişimini kısıtlama anlamına gelir.

Bazel'ın dosya sistemi korumalı alanı, yalnızca bilinen girişleri içeren bir çalışma dizininde işlemleri çalıştırır. Örneğin, derleyiciler ve diğer araçlar, mutlak yolları bilmedikleri sürece erişmemeleri gereken kaynak dosyalarını görmezler.

Korumalı alan oluşturma, ana makine ortamını hiçbir şekilde gizlemez. İşlemler, dosya sistemindeki tüm dosyalara serbestçe erişebilir. Ancak, kullanıcı ad alanlarını destekleyen platformlarda işlemler, çalışma dizinlerinin dışındaki dosyaları değiştiremez. Bu, derleme grafiğinin, derlemenin yeniden oluşturulabilirliğini etkileyebilecek gizli bağımlılıklar içermemesini sağlar.

Ayrıntılı olarak açıklamak gerekirse Bazel her işlem için bir execroot/ dizini oluşturur. Bu dizin, yürütme sırasında işlemin iş dizini görevi görür. execroot/, işleme tüm giriş dosyalarını içerir ve oluşturulan çıkışlar için kapsayıcı görevi görür. Bazel, daha sonra işletim sistemi tarafından sağlanan bir teknikten (Linux'ta container'lar, macOS'te sandbox-exec) yararlanarak işlemi execroot/ içinde kısıtlar.

Korumalı alana alma nedenleri

  • İşlem korumalı alanı olmadan Bazel, bir aracın bildirilmemiş giriş dosyaları (bir işlemin bağımlılıklarında açıkça listelenmeyen dosyalar) kullanıp kullanmadığını bilmez. Beyan edilmeyen giriş dosyalarından biri değiştiğinde Bazel hâlâ derlemenin güncel olduğunu düşünüyor ve işlemi yeniden oluşturmayacak. Bu, hatalı bir artımlı derlemeye neden olabilir.

  • Önbellek girişlerinin yanlış yeniden kullanılması, uzaktan önbelleğe alma sırasında sorunlara yol açar. Paylaşılan bir önbellekteki kötü bir önbellek girişi projedeki her geliştiriciyi etkiler ve uzak önbelleğin tamamının temizlenmesi uygun bir çözüm değildir.

  • Korumalı alan oluşturma, uzaktan yürütme davranışını taklit eder. Bir derleme, korumalı alana alma ile iyi çalışıyorsa büyük olasılıkla uzaktan yürütmeyle de çalışır. Uzaktan yürütmenin tüm gerekli dosyaları (yerel araçlar dahil) yüklemesini sağlayarak, her yeni derleyiciyi denemek veya mevcut bir araçta değişiklik yapmak istediğinizde araçları kümedeki her makineye yüklemek zorunda kalmaktansa, derleme kümeleri için bakım maliyetlerini önemli ölçüde azaltabilirsiniz.

Hangi korumalı alan stratejisini kullanmalısınız?

Strateji bayraklarıyla, varsa ne tür bir korumalı alan kullanmak istediğinizi seçebilirsiniz. sandboxed stratejisini kullandığınızda Bazel, aşağıda listelenen korumalı alan uygulamalarından birini seçer ve işletim sistemine özel bir korumalı alanı daha az genel olan genel olana tercih eder. --worker_sandboxing işaretini iletirseniz kalıcı çalışanlar genel bir korumalı alanda çalışır.

local (diğer adıyla standalone) stratejisi, herhangi bir korumalı alana alma işlemi yapmaz. Yalnızca işlemin komut satırını, çalışma dizini çalışma alanınızın execroot'una ayarlanmış şekilde yürütür.

processwrapper-sandbox, herhangi bir "gelişmiş" özellik gerektirmeyen bir korumalı alan stratejisidir. Kullanıma hazır tüm POSIX sistemlerinde çalışmalıdır. Orijinal kaynak dosyalarına işaret eden sembolik bağlantılardan oluşan bir korumalı alan dizini oluşturur. İşlemin komut satırını execroot yerine bu dizine ayarlanmış şekilde yürütür, ardından bilinen çıkış yapılarını korumalı alanın dışına taşır ve korumalı alanı siler. Böylece eylemin bildirilmemiş giriş dosyalarını yanlışlıkla kullanmasını ve execroot'un bilinmeyen çıkış dosyalarıyla yüklenmesini önler.

linux-sandbox bir adım daha ileri gidip processwrapper-sandbox temellerini oluşturur. Docker, arka planda yaptığı gibi, eylemi ana makineden izole etmek için Linux Ad Alanlarını (Kullanıcı, Ekleme, PID, Ağ ve IPC ad alanları) kullanır. Yani korumalı alan dizini dışında tüm dosya sistemini salt okunur hale getirir. Böylece işlem, ana makine dosya sisteminde hiçbir şeyi yanlışlıkla değiştiremez. Bu, hatalı bir testin $HOME dizininizi yanlışlıkla yeniden çalıştırması gibi durumları önler. İsteğe bağlı olarak, işlemin ağa erişmesini de engelleyebilirsiniz. linux-sandbox, işlemin diğer süreçleri görmesini engellemek ve en sondaki tüm işlemleri (işlem tarafından oluşturulan arka plan programları dahil) güvenilir bir şekilde sona erdirmek için PID ad alanlarını kullanır.

darwin-sandbox de benzer ancak macOS'te kullanılır. Linux korumalı alanı ile hemen hemen aynı işlemi gerçekleştirmek için Apple'ın sandbox-exec aracını kullanır.

İşletim sistemleri tarafından sağlanan mekanizmalardaki kısıtlamalar nedeniyle linux-sandbox ve darwin-sandbox, "iç içe yerleştirilmiş" bir senaryoda çalışmaz. Docker, container büyüsü için Linux ad alanlarını da kullandığından, docker run --privileged kullanmadığınız sürece linux-sandbox etiketini Docker container'larının içinde kolayca çalıştıramazsınız. macOS'te, sandbox-exec zaten korumalı alana alınan bir işlemin içinde çalıştıramazsınız. Bu nedenle, bu durumlarda Bazel otomatik olarak processwrapper-sandbox kullanmaya geri döner.

Daha az katı bir yürütme stratejisiyle yanlışlıkla derlemekten kaçınmak gibi bir derleme hatası almayı tercih ederseniz Bazel'ın kullanmaya çalıştığı yürütme stratejileri listesini açıkça değiştirin (örneğin, bazel build --spawn_strategy=worker,linux-sandbox).

Dinamik yürütme genellikle yerel yürütme için korumalı alana alma gerektirir. Devre dışı bırakmak için --experimental_local_lockfree_output işaretini kullanın. Dinamik yürütme, kalıcı çalışanları sessiz bir şekilde korumalı alana alır.

Korumalı alanın olumsuz yönleri

  • Korumalı alana alma, ek kurulum ve söküm maliyetine neden olur. Bu maliyetin ne kadar büyük olduğu, derlemenin şekli ve ana makine işletim sisteminin performansı gibi birçok faktöre bağlıdır. Linux'ta korumalı alana alınan derlemeler nadiren yüzde birkaçdan daha yavaştır. --reuse_sandbox_directories ayarlamak kurulum ve söküm maliyetini azaltabilir.

  • Korumalı alana alma, aracın sahip olabileceği tüm önbelleği etkili bir şekilde devre dışı bırakır. Daha zayıf korumalı alan garantileri karşılığında kalıcı çalışanlar kullanarak bu durumu azaltabilirsiniz.

  • Multiplex çalışanlar için açık çalışan desteğinin korumalı alana alınması gerekir. Multiplex korumalı alana almayı desteklemeyen çalışanlar, dinamik yürütme altında tek taraflı çalışan olarak çalışır. Bu da, ek bellek maliyetine neden olabilir.

Hata ayıklama

Korumalı alanla ilgili sorunları gidermek için aşağıdaki stratejileri uygulayın.

Devre dışı bırakılmış ad alanları

Google Kubernetes Engine küme düğümleri veya Debian gibi bazı platformlarda, güvenlikle ilgili endişeler nedeniyle kullanıcı ad alanları varsayılan olarak devre dışı bırakılır. /proc/sys/kernel/unprivileged_userns_clone dosyası mevcutsa ve 0 değerini içeriyorsa kullanıcı ad alanlarını aşağıdaki komutu çalıştırarak etkinleştirebilirsiniz:

   sudo sysctl kernel.unprivileged_userns_clone=1

Kural çalıştırma hataları

Korumalı alan, sistem kurulumu nedeniyle kuralları yürütemeyebilir. namespace-sandbox.c:633: execvp(argv[0], argv): No such file or directory gibi bir mesaj görürseniz korumalı alanı, geneller için --strategy=Genrule=local ve diğer kurallar için --spawn_strategy=local ile devre dışı bırakmayı deneyin.

Derleme hataları için ayrıntılı hata ayıklama

Derlemeniz başarısız olduysa --verbose_failures ve --sandbox_debug kullanarak Bazel'ın derlemeniz başarısız olduğunda tam olarak çalıştırdığı komutu (korumalı alanı ayarlayan bölüm de dahil) göstermesini sağlayın.

Örnek hata mesajı:

ERROR: path/to/your/project/BUILD:1:1: compilation of rule
'//path/to/your/project:all' failed:

Sandboxed execution failed, which may be legitimate (such as a compiler error),
or due to missing dependencies. To enter the sandbox environment for easier
debugging, run the following command in parentheses. On command failure, a bash
shell running inside the sandbox will then automatically be spawned

namespace-sandbox failed: error executing command
  (cd /some/path && \
  exec env - \
    LANG=en_US \
    PATH=/some/path/bin:/bin:/usr/bin \
    PYTHONPATH=/usr/local/some/path \
  /some/path/namespace-sandbox @/sandbox/root/path/this-sandbox-name.params --
  /some/path/to/your/some-compiler --some-params some-target)

Artık oluşturulan korumalı alan dizinini inceleyebilir, Bazel'ın hangi dosyaları oluşturduğunu görebilir ve nasıl davrandığını görmek için komutu tekrar çalıştırabilirsiniz.

--sandbox_debug kullandığınızda Bazel'in korumalı alan dizinini silmediğini unutmayın. Aktif olarak hata ayıklama yapmıyorsanız zaman içinde diskinizi doldurduğundan --sandbox_debug öğesini devre dışı bırakmanız gerekir.