این مقاله sandboxing در Bazel، نصب sandboxfs
و اشکال زدایی محیط sandboxing شما را پوشش می دهد.
Sandboxing یک استراتژی محدود کننده مجوز است که فرآیندها را از یکدیگر یا از منابع موجود در یک سیستم جدا می کند. برای Bazel، این به معنای محدود کردن دسترسی به فایل سیستم است.
سندباکس سیستم فایل Bazel فرآیندهایی را در یک فهرست کاری اجرا می کند که فقط شامل ورودی های شناخته شده است، به طوری که کامپایلرها و سایر ابزارها فایل های منبعی را که نباید به آنها دسترسی داشته باشند، نمی بینند، مگر اینکه مسیرهای مطلق آنها را بدانند.
Sandboxing به هیچ وجه محیط میزبان را پنهان نمی کند. فرآیندها می توانند آزادانه به تمام فایل های موجود در سیستم فایل دسترسی داشته باشند. با این حال، در پلتفرم هایی که از فضای نام کاربری پشتیبانی می کنند، فرآیندها نمی توانند هیچ فایلی را خارج از فهرست کاری خود تغییر دهند. این تضمین میکند که نمودار ساخت، وابستگیهای پنهانی نداشته باشد که میتواند بر تکرارپذیری بیلد تأثیر بگذارد.
به طور خاص، Bazel برای هر عمل یک دایرکتوری execroot/
ایجاد می کند که در زمان اجرا به عنوان دایرکتوری کاری عمل عمل می کند. execroot/
شامل تمام فایل های ورودی اکشن است و به عنوان محفظه برای خروجی های تولید شده عمل می کند. Bazel سپس از یک تکنیک ارائه شده توسط سیستم عامل، کانتینرها در لینوکس و sandbox-exec
در macOS، برای محدود کردن عملکرد در execroot/
استفاده میکند.
دلایل سندباکسینگ
بدون سندباکس اکشن، Bazel نمی داند که آیا ابزاری از فایل های ورودی اعلام نشده (فایل هایی که به صراحت در وابستگی های یک عملکرد فهرست نشده اند) استفاده می کند یا خیر. هنگامی که یکی از فایل های ورودی اعلام نشده تغییر می کند، بازل همچنان معتقد است که ساخت به روز است و اکشن را بازسازی نمی کند. این می تواند منجر به ساخت افزایشی نادرست شود.
استفاده مجدد نادرست از ورودی های حافظه پنهان در حین ذخیره سازی از راه دور مشکلاتی ایجاد می کند. ورود نامناسب حافظه پنهان در یک حافظه پنهان مشترک بر هر توسعهدهنده پروژه تأثیر میگذارد و پاک کردن کل حافظه پنهان راهحلی امکانپذیر نیست.
Sandboxing رفتار اجرای از راه دور را تقلید می کند - اگر یک ساخت با sandboxing به خوبی کار کند، احتمالاً با اجرای از راه دور نیز کار خواهد کرد. با آپلود کردن اجرای از راه دور همه فایلهای لازم (از جمله ابزارهای محلی)، میتوانید هزینههای نگهداری برای خوشههای کامپایل را در مقایسه با نصب ابزارها بر روی هر ماشینی در کلاستر هر بار که میخواهید یک کامپایلر جدید را امتحان کنید یا تغییری ایجاد کنید، به میزان قابل توجهی کاهش دهید. به یک ابزار موجود
از چه استراتژی sandbox استفاده کنید
در صورت وجود، میتوانید با پرچمهای استراتژی انتخاب کنید که از چه نوع sandboxing استفاده کنید. استفاده از استراتژی sandboxed
باعث میشود Bazel یکی از پیادهسازیهای sandbox فهرست شده در زیر را انتخاب کند، و یک sandbox خاص سیستمعامل را به نمونه عمومی کمتر هرمتیک ترجیح دهد. اگر پرچم --worker_sandboxing
را پاس کنید، کارگران مداوم در یک جعبه ایمنی عمومی اجرا می شوند.
استراتژی local
(معروف به standalone
) هیچ نوع sandboxing را انجام نمی دهد. این به سادگی خط فرمان عمل را با دایرکتوری کاری که روی اکسروت فضای کاری شما تنظیم شده است، اجرا می کند.
processwrapper-sandbox
یک استراتژی sandboxing است که به هیچ ویژگی "پیشرفته" نیاز ندارد - باید روی هر سیستم POSIX خارج از جعبه کار کند. یک دایرکتوری sandbox متشکل از پیوندهای نمادین که به فایل های منبع اصلی اشاره می کنند، می سازد، خط فرمان عمل را با دایرکتوری کاری که در این دایرکتوری تنظیم شده است به جای execroot اجرا می کند، سپس مصنوعات خروجی شناخته شده را به خارج از sandbox به execroot منتقل می کند و حذف می کند. جعبه شنی. این عمل از استفاده تصادفی از فایلهای ورودی که اعلان نشدهاند و پر کردن فایلهای خروجی ناشناخته در Execroot جلوگیری میکند.
linux-sandbox
یک قدم جلوتر می رود و در بالای processwrapper-sandbox
قرار می گیرد. مشابه کاری که داکر در زیر هود انجام میدهد، از فضاهای نام لینوکس (کاربر، کوه، PID، شبکه و فضاهای نام IPC) برای جداسازی عملکرد از میزبان استفاده میکند. یعنی کل فایل سیستم را فقط خواندنی می کند به جز دایرکتوری sandbox، بنابراین عمل نمی تواند به طور تصادفی چیزی را در سیستم فایل میزبان تغییر دهد. این از موقعیتهایی مانند تست حشرهای که به طور تصادفی دایرکتوری $HOME شما را rm -rf' میکند، جلوگیری میکند. به صورت اختیاری، می توانید از دسترسی این عمل به شبکه نیز جلوگیری کنید. linux-sandbox
از فضاهای نام PID استفاده میکند تا از مشاهده هر فرآیند دیگر توسط اکشن جلوگیری کند و در پایان تمام فرآیندها (حتی شیاطین ایجاد شده توسط اکشن) را با اطمینان از بین ببرد.
darwin-sandbox
مشابه است، اما برای macOS. از ابزار sandbox-exec
اپل برای دستیابی تقریباً به همان جعبه سندباکس لینوکس استفاده می کند.
هر دو linux-sandbox
و darwin-sandbox
به دلیل محدودیت در مکانیسم های ارائه شده توسط سیستم عامل ها در یک سناریوی "تودرتو" کار نمی کنند. از آنجایی که Docker همچنین از فضاهای نام لینوکس برای جادوی کانتینر خود استفاده می کند، نمی توانید به راحتی linux-sandbox
در داخل یک ظرف داکر اجرا کنید، مگر اینکه از docker run --privileged
استفاده کنید. در macOS، نمیتوانید sandbox-exec
را در فرآیندی که قبلاً sandbox شده است اجرا کنید. بنابراین، در این موارد، Bazel به طور خودکار به استفاده از processwrapper-sandbox
.
اگر ترجیح میدهید یک خطای ساخت دریافت کنید - مانند عدم ساخت تصادفی با یک استراتژی اجرای کمتر سختگیرانه - به صراحت فهرست استراتژیهای اجرایی را که Bazel سعی میکند استفاده کند تغییر دهید (به عنوان مثال، bazel build --spawn_strategy=worker,linux-sandbox
) .
اجرای پویا معمولاً برای اجرای محلی نیاز به sandboxing دارد. برای انصراف، پرچم --experimental_local_lockfree_output
را ارسال کنید. اجرای پویا به طور بی سر و صدا کارگران مستمر را تحت فشار قرار می دهد.
نقاط ضعف سندباکس
Sandboxing هزینه راه اندازی و تخریب اضافی را به همراه دارد. اینکه چقدر این هزینه زیاد است به عوامل زیادی از جمله شکل ساخت و عملکرد سیستم عامل میزبان بستگی دارد. برای لینوکس، ساختهای sandbox به ندرت بیش از چند درصد کندتر هستند. تنظیم
--reuse_sandbox_directories
می تواند هزینه راه اندازی و حذف را کاهش دهد.Sandboxing به طور موثر هر حافظه پنهانی را که ابزار ممکن است داشته باشد غیرفعال می کند. شما می توانید با استفاده از کارگران مداوم ، به قیمت ضمانت های ضعیف تر سندباکس، این مشکل را کاهش دهید.
کارگران Multiplex به پشتیبانی صریح کارگر نیاز دارند تا جعبهشنی شوند. کارگرانی که از sandboxing مالتی پلکس پشتیبانی نمی کنند به عنوان کارگران singleplex تحت اجرای پویا اجرا می شوند، که می تواند هزینه حافظه اضافی داشته باشد.
sandboxfs
sandboxfs
یک سیستم فایل FUSE است که یک نمای دلخواه از سیستم فایل اصلی را بدون جریمه زمانی در معرض دید قرار می دهد. Bazel از sandboxfs
برای تولید execroot/
آنی برای هر اقدام استفاده می کند و از هزینه صدور هزاران تماس سیستمی جلوگیری می کند. توجه داشته باشید که I/O بیشتر در execroot/
ممکن است به دلیل سربار FUSE کندتر باشد.
sandboxfs را نصب کنید
از مراحل زیر برای نصب sandboxfs
و اجرای ساخت Bazel با آن استفاده کنید:
دانلود
sandboxfs
را دانلود و نصب کنید تا باینری sandboxfs
به PATH
شما ختم شود.
sandboxfs
را اجرا کنید
- (فقط macOS) OSXFUSE را نصب کنید .
(فقط macOS) اجرا:
sudo sysctl -w vfs.generic.osxfuse.tunables.allow_other=1
شما باید این کار را پس از نصب و پس از هر بار راهاندازی مجدد انجام دهید تا مطمئن شوید که خدمات سیستم اصلی macOS از طریق sandboxfs کار میکنند.
یک ساخت Bazel را با
--experimental_use_sandboxfs
کنید.bazel build target --experimental_use_sandboxfs
عیب یابی
اگر بهجای darwin-sandbox
یا linux-sandbox
local
را بهعنوان حاشیهنویسی برای اقداماتی که اجرا میشوند میبینید، ممکن است به این معنی باشد که sandboxing غیرفعال شده است. --genrule_strategy=sandboxed --spawn_strategy=sandboxed
را برای فعال کردن آن عبور دهید.
اشکال زدایی
برای رفع اشکال مشکلات سندباکسینگ، استراتژی های زیر را دنبال کنید.
فضای نام غیرفعال شده
در برخی از پلتفرمها، مانند گرههای خوشهای Google Kubernetes Engine یا Debian، فضاهای نام کاربری بهطور پیشفرض به دلیل نگرانیهای امنیتی غیرفعال میشوند. اگر فایل /proc/sys/kernel/unprivileged_userns_clone
وجود داشته باشد و حاوی 0 باشد، میتوانید فضاهای نام کاربری را با اجرای:
sudo sysctl kernel.unprivileged_userns_clone=1
شکست در اجرای قوانین
سندباکس ممکن است به دلیل راه اندازی سیستم، قوانین را اجرا نکند. اگر پیامی مانند namespace-sandbox.c:633: execvp(argv[0], argv): No such file or directory
، سعی کنید جعبه ایمنی را با --strategy=Genrule=local
for genrules و --spawn_strategy=local
برای قوانین دیگر.
اشکال زدایی دقیق برای خرابی های ساخت
اگر ساخت شما ناموفق بود، از --verbose_failures
و --sandbox_debug
استفاده کنید تا Bazel دقیقاً دستوری را که هنگام شکست ساخت شما اجرا میکرد، نشان دهد، از جمله بخشی که sandbox را تنظیم میکند.
نمونه پیام خطا:
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)
اکنون می توانید دایرکتوری sandbox تولید شده را بررسی کنید و ببینید Bazel کدام فایل ها را ایجاد کرده است و دوباره دستور را اجرا کنید تا ببینید چگونه رفتار می کند.
توجه داشته باشید که Bazel هنگام استفاده از --sandbox_debug
دایرکتوری sandbox را حذف نمی کند. مگر اینکه به طور فعال اشکال زدایی کنید، باید --sandbox_debug
را غیرفعال کنید زیرا به مرور زمان دیسک شما را پر می کند.