Korumalı alana alma

Sorun bildir Kaynağı görüntüle Nightly · 8.3 · 8.2 · 8.1 · 8.0 · 7.6

Bu makalede, Bazel'deki korumalı alan ve korumalı alan ortamınızda hata ayıklama konuları ele alınmaktadır.

Korumalı alan, işlemleri birbirinden veya sistemdeki kaynaklardan yalıtan bir izin kısıtlama stratejisidir. Bazel için bu, dosya sistemi erişiminin kısıtlanması anlamına gelir.

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

Koruma alanı, 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ğinde derlemenin yeniden üretilebilirliğini etkileyebilecek gizli bağımlılıklar olmamasını sağlar.

Daha spesifik olarak, Bazel her işlem için bir execroot/ dizini oluşturur. Bu dizin, yürütme sırasında işlemin çalışma dizini olarak işlev görür. execroot/ işlemle ilgili tüm giriş dosyalarını içerir ve oluşturulan tüm çıkışlar için kapsayıcı görevi görür. Ardından Bazel, işlemi execroot/ içinde sınırlamak için işletim sistemi tarafından sağlanan bir teknik (Linux'ta kapsayıcılar ve macOS'te sandbox-exec) kullanır.

Korumalı alan oluşturma nedenleri

  • İşlem korumalı alanı olmadan Bazel, bir aracın beyan edilmemiş giriş dosyalarını (bir işlemin bağımlılıklarında açıkça listelenmeyen dosyalar) kullanıp kullanmadığını bilemez. Bildirilmemiş giriş dosyalarından biri değiştiğinde Bazel, derlemenin güncel olduğunu düşünmeye devam eder ve işlemi yeniden oluşturmaz. Bu durum, yanlış artımlı derlemeye neden olabilir.

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

  • Koruma alanı, uzaktan yürütme davranışını taklit eder. Derleme, koruma alanıyla iyi çalışıyorsa büyük olasılıkla uzaktan yürütmeyle de iyi çalışır. Uzak yürütme, gerekli tüm dosyaları (yerel araçlar dahil) yükleyerek derleme kümelerinin bakım maliyetlerini önemli ölçüde azaltır. Bu sayede, yeni bir derleyiciyi denemek veya mevcut bir araçta değişiklik yapmak istediğinizde araçları kümedeki her makineye yüklemeniz gerekmez.

Hangi korumalı alan stratejisinin kullanılacağı

Strateji işaretleri ile hangi tür sanal alanın kullanılacağını (varsa) seçebilirsiniz. sandboxed stratejisi kullanıldığında Bazel, aşağıda listelenen sandbox uygulamalarından birini seçer. Daha az hermetik olan genel sandbox yerine işletim sistemine özgü bir sandbox tercih edilir. --worker_sandboxing işaretini iletirseniz kalıcı çalışanlar genel bir sanal alanda çalışır.

local (diğer adıyla standalone) stratejisi herhangi bir türde korumalı alan oluşturmaz. Bu işlem, çalışma dizini, çalışma alanınızın execroot'u olarak ayarlanmış şekilde, yalnızca işlemin komut satırını yürütür.

processwrapper-sandbox, herhangi bir "gelişmiş" özellik gerektirmeyen bir sanal alan oluşturma stratejisidir. Kutudan çıkarıldığı gibi herhangi bir POSIX sisteminde çalışır. Orijinal kaynak dosyaları işaret eden sembolik bağlantılardan oluşan bir korumalı alan dizini oluşturur, işlemin komut satırını execroot yerine bu dizine ayarlanmış çalışma diziniyle yürütür, ardından bilinen çıkış yapılarını korumalı alandan execroot'a taşır ve korumalı alanı siler. Bu, işlemin, bildirilmemiş giriş dosyalarını yanlışlıkla kullanmasını ve execroot'u bilinmeyen çıkış dosyalarıyla doldurmasını önler.

linux-sandbox, processwrapper-sandbox'nin üzerine inşa edilerek bir adım daha ileri gider. Docker'ın arka planda yaptığına benzer şekilde, eylemi ana makineden yalıtmak için Linux ad alanlarını (kullanıcı, bağlama, PID, ağ ve IPC ad alanları) kullanır. Yani, sanal alan dizini hariç olmak üzere dosya sisteminin tamamını salt okunur hale getirir. Bu nedenle, işlem ana makine dosya sisteminde yanlışlıkla hiçbir şeyi değiştiremez. Bu, hatalı bir testin yanlışlıkla $HOME dizininizi rm -rf komutuyla silmesi gibi durumları önler. İsteğe bağlı olarak, işlemin ağa erişmesini de engelleyebilirsiniz. linux-sandbox, işlemin diğer işlemleri görmesini engellemek ve sonunda tüm işlemleri (işlem tarafından oluşturulan arka plan programları dahil) güvenilir bir şekilde sonlandırmak için PID ad alanlarını kullanır.

darwin-sandbox benzer bir araçtır ancak macOS için geçerlidir. Linux korumalı alanıyla yaklaşık olarak aynı sonucu elde etmek için Apple'ın sandbox-exec aracını kullanır.

Hem linux-sandbox hem de darwin-sandbox, işletim sistemleri tarafından sağlanan mekanizmalardaki kısıtlamalar nedeniyle "iç içe" senaryoda çalışmaz. Docker, container sihrini gerçekleştirmek için Linux ad alanlarını da kullandığından docker run --privileged kullanmadığınız sürece linux-sandbox'yı Docker container'ında kolayca çalıştıramazsınız. macOS'te, sandbox-exec öğesini halihazırda korumalı alan içinde olan bir süreçte ç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 derleme yapmamak gibi nedenlerle derleme hatası almak istiyorsanız Bazel'in 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ı alan oluşturmayı gerektirir. Kapsam dışında kalmak için --experimental_local_lockfree_output işaretini iletin. Dinamik yürütme, kalıcı çalışanları sessizce korumalı alana alır.

Korumalı alana almanın dezavantajları

  • Koruma alanı oluşturma, ek kurulum ve kapatma maliyetine neden olur. Bu maliyetin büyüklüğü, derlemenin şekli ve ana makine işletim sisteminin performansı gibi birçok faktöre bağlıdır. Linux'ta, korumalı alan derlemeleri nadiren birkaç yüzdeden daha fazla yavaşlar. Ayarlama --reuse_sandbox_directories, kurulum ve söküm maliyetini azaltabilir.

  • Koruma alanı, aracın sahip olabileceği tüm önbellekleri 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.

  • Çoklu görevli çalışanların korumalı alan oluşturulması için açıkça çalışan desteği gerekir. Çoklu sanal alan oluşturmayı desteklemeyen çalışanlar, dinamik yürütme altında tekli çalışanlar olarak çalışır. Bu durum, ek bellek maliyetine neden olabilir.

Hata ayıklama

Aşağıdaki stratejileri uygulayarak sanal alanla ilgili sorunları ayıklayın.

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

Google Kubernetes Engine küme düğümleri veya Debian gibi bazı platformlarda güvenlik endişeleri nedeniyle kullanıcı ad alanları varsayılan olarak devre dışıdır. /proc/sys/kernel/unprivileged_userns_clone dosyası varsa ve 0 içeriyorsa şu komutu çalıştırarak kullanıcı ad alanlarını etkinleştirebilirsiniz:

   sudo sysctl kernel.unprivileged_userns_clone=1

Kural yürütme hataları

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

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

Derlemeniz başarısız olursa --verbose_failures ve --sandbox_debug kullanarak Bazel'in, derlemeniz başarısız olduğunda çalıştırdığı tam komutu (sandbox'ı ayarlayan bölüm 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 sandbox dizinini inceleyebilir, Bazel'in hangi dosyaları oluşturduğunu görebilir ve nasıl davrandığını görmek için komutu tekrar çalıştırabilirsiniz.

Bazel'in, --sandbox_debug kullandığınızda sandbox dizinini silmediğini unutmayın. Etkin olarak hata ayıklamıyorsanız --sandbox_debug seçeneğini devre dışı bırakmanız gerekir. Aksi takdirde, zaman içinde diskiniz dolar.