خط مشی SELinux را بنویسید

پروژه منبع باز Android (AOSP) یک خط مشی پایه محکم برای برنامه ها و خدماتی که در همه دستگاه های Android مشترک هستند ارائه می دهد. مشارکت کنندگان در AOSP به طور مرتب این خط مشی را اصلاح می کنند. انتظار می‌رود خط‌مشی اصلی حدود 90 تا 95 درصد از خط‌مشی نهایی روی دستگاه را تشکیل دهد و 5 تا 10 درصد باقی‌مانده را سفارشی‌سازی‌های خاص دستگاه تشکیل دهد. این مقاله بر روی این سفارشی‌سازی‌های خاص دستگاه، نحوه نوشتن خط‌مشی خاص دستگاه، و برخی از دام‌هایی که باید در این مسیر اجتناب کنید، تمرکز دارد.

نمایش دستگاه

هنگام نوشتن خط‌مشی مخصوص دستگاه، این مراحل را دنبال کنید.

در حالت مجاز اجرا شود

وقتی دستگاهی در حالت مجاز است، انکارها ثبت می‌شوند اما اجرا نمی‌شوند. حالت مجاز به دو دلیل مهم است:

  • حالت مجاز تضمین می‌کند که بازگرداندن خط‌مشی سایر وظایف ارائه اولیه دستگاه را به تأخیر نمی‌اندازد.
  • یک انکار اجباری ممکن است انکارهای دیگر را بپوشاند. برای مثال، دسترسی به فایل معمولاً مستلزم جستجوی فهرست، باز کردن فایل و سپس خواندن فایل است. در حالت اجرا، فقط رد جستجوی دایرکتوری رخ می دهد. حالت مجاز تضمین می کند که همه انکارها دیده می شوند.

ساده ترین راه برای قرار دادن یک دستگاه در حالت مجاز، استفاده از خط فرمان هسته است. این را می توان به فایل BoardConfig.mk دستگاه اضافه کرد: platform/device/<vendor>/<target>/BoardConfig.mk . پس از اصلاح خط فرمان، make clean انجام دهید، سپس make bootimage و تصویر بوت جدید را فلش کنید.

پس از آن، حالت مجاز را با:

adb shell getenforce

دو هفته زمان معقولی برای قرار گرفتن در حالت جهانی مجاز است. پس از رسیدگی به اکثر موارد انکار، به حالت اجرا برگردید و به محض ورود اشکالات را برطرف کنید. دامنه‌هایی که هنوز انکار می‌کنند یا خدماتی که هنوز در حال توسعه هستند می‌توانند به طور موقت در حالت مجاز قرار گیرند، اما در اسرع وقت آنها را به حالت اجرا برگردانید.

زودتر اجرا شود

در حالت اجرا، انکارها هم ثبت و هم اجرا می شوند. بهترین روش این است که دستگاه خود را در اسرع وقت به حالت اعمال کنید. انتظار برای ایجاد و اجرای خط مشی خاص دستگاه اغلب منجر به یک محصول باگ و تجربه کاربری بد می شود. به اندازه کافی زود شروع کنید تا در آزمایش آزمایشی شرکت کنید و از پوشش آزمایشی کامل عملکرد در استفاده در دنیای واقعی اطمینان حاصل کنید. شروع زودهنگام، نگرانی های امنیتی را در تصمیم گیری های طراحی تضمین می کند. برعکس، اعطای مجوزها صرفاً بر اساس انکار مشاهده شده یک رویکرد ناامن است. از این زمان برای انجام ممیزی امنیتی دستگاه استفاده کنید و اشکالات مربوط به رفتارهایی که نباید مجاز هستند را ثبت کنید.

خط مشی موجود را حذف یا حذف کنید

دلایل خوبی برای ایجاد خط مشی خاص دستگاه از ابتدا در دستگاه جدید وجود دارد که عبارتند از:

رد کردن خدمات اصلی

انکارهای ایجاد شده توسط خدمات اصلی معمولاً با برچسب گذاری فایل مورد بررسی قرار می گیرند. به عنوان مثال:

avc: denied { open } for pid=1003 comm=”mediaserver” path="/dev/kgsl-3d0”
dev="tmpfs" scontext=u:r:mediaserver:s0 tcontext=u:object_r:device:s0
tclass=chr_file permissive=1
avc: denied { read write } for pid=1003 name="kgsl-3d0" dev="tmpfs"
scontext=u:r:mediaserver:s0
tcontext=u:object_r:device:s0 tclass=chr_file permissive=1

به طور کامل با برچسب گذاری مناسب /dev/kgsl-3d0 آدرس داده می شود. در این مثال، tcontext device است. این یک زمینه پیش‌فرض را نشان می‌دهد که در آن همه چیز در /dev برچسب « دستگاه » را دریافت می‌کند مگر اینکه برچسب خاصی اختصاص داده شود. صرفاً پذیرش خروجی audit2allow در اینجا منجر به یک قانون نادرست و بیش از حد مجاز می شود.

برای حل این نوع مشکل، به فایل یک برچسب مشخص تری بدهید که در این مورد gpu_device است. هیچ مجوز دیگری لازم نیست زیرا سرور رسانه از قبل مجوزهای لازم را در خط مشی اصلی برای دسترسی به gpu_device دارد .

سایر فایل‌های خاص دستگاه که باید با انواع از پیش تعریف‌شده در خط‌مشی اصلی برچسب‌گذاری شوند:

به طور کلی، اعطای مجوز به برچسب های پیش فرض اشتباه است. بسیاری از این مجوزها توسط قوانین neverallow غیرمجاز هستند، اما حتی زمانی که صراحتاً مجاز نیستند، بهترین روش ارائه یک برچسب خاص است.

خدمات جدید را برچسب بزنید و موارد رد شده را آدرس دهید

سرویس‌های راه‌اندازی اولیه باید در دامنه‌های SELinux خودشان اجرا شوند. مثال زیر سرویس "foo" را در دامنه SELinux خودش قرار می دهد و به آن مجوز می دهد.

این سرویس در init. device .rc فایل init. device .rc به صورت:

service foo /system/bin/foo
    class core
  1. ایجاد یک دامنه جدید "foo"

    فایل device/ manufacturer / device-name /sepolicy/foo.te را با محتویات زیر ایجاد کنید:

    # foo service
    type foo, domain;
    type foo_exec, exec_type, file_type;
    
    init_daemon_domain(foo)
    

    این الگوی اولیه برای دامنه foo SELinux است که می توانید قوانینی را بر اساس عملیات خاصی که توسط آن فایل اجرایی انجام می شود به آن اضافه کنید.

  2. برچسب /system/bin/foo

    موارد زیر را به device/ manufacturer / device-name /sepolicy/file_contexts اضافه کنید:

    /system/bin/foo   u:object_r:foo_exec:s0
    

    این اطمینان حاصل می کند که فایل اجرایی به درستی برچسب گذاری شده است، بنابراین SELinux سرویس را در دامنه مناسب اجرا می کند.

  3. تصاویر بوت و سیستم را بسازید و فلش کنید.
  4. قوانین SELinux را برای دامنه اصلاح کنید.

    از Denials برای تعیین مجوزهای مورد نیاز استفاده کنید. ابزار audit2allow رهنمودهای خوبی را ارائه می دهد، اما فقط از آن برای اطلاع رسانی خط مشی نویسی استفاده کنید. فقط خروجی را کپی نکنید.

به حالت اجباری برگردید

عیب‌یابی در حالت مجاز خوب است، اما هر چه زودتر به حالت اعمال برگردید و سعی کنید در آنجا بمانید.

اشتباهات رایج

در اینجا چند راه حل برای اشتباهات رایجی که هنگام نوشتن خط مشی های خاص دستگاه اتفاق می افتد، آورده شده است.

استفاده بیش از حد از نفی

قانون مثال زیر مانند قفل کردن درب ورودی است اما پنجره ها را باز می گذاریم:

allow { domain -untrusted_app } scary_debug_device:chr_file rw_file_perms

هدف واضح است: همه به جز برنامه های شخص ثالث ممکن است به دستگاه اشکال زدایی دسترسی داشته باشند.

این قانون از چند جهت ناقص است. حذف untrusted_app بی اهمیت است زیرا همه برنامه ها ممکن است به صورت اختیاری خدماتی را در دامنه isolated_app اجرا کنند. به همین ترتیب، اگر دامنه های جدیدی برای برنامه های شخص ثالث به AOSP اضافه شوند، به scary_debug_device نیز دسترسی خواهند داشت. قانون بیش از حد مجاز است. اکثر دامنه ها از دسترسی به این ابزار اشکال زدایی سودی نخواهند برد. این قانون باید طوری نوشته می شد که فقط به دامنه هایی که نیاز به دسترسی دارند اجازه دهد.

ویژگی های اشکال زدایی در تولید

ویژگی‌های اشکال‌زدایی نباید در ساخت‌های تولیدی وجود داشته باشد و همچنین نباید خط‌مشی آن‌ها وجود داشته باشد.

ساده‌ترین گزینه این است که فقط وقتی SELinux در ساخت‌های eng/userdbug غیرفعال است، ویژگی اشکال‌زدایی را مجاز کنید، مانند adb root و adb shell setenforce 0 .

یک جایگزین مطمئن دیگر این است که مجوزهای اشکال زدایی را در یک عبارت userdebug_or_eng قرار دهید.

انفجار اندازه سیاست

مشخص کردن سیاست‌های SEAndroid در طبیعت، روند نگران‌کننده‌ای را در رشد سفارشی‌سازی خط‌مشی دستگاه توصیف می‌کند. خط‌مشی خاص دستگاه باید 5 تا 10 درصد از خط‌مشی کلی اجرا شده روی دستگاه را تشکیل دهد. سفارشی سازی در محدوده 20%+ تقریباً مطمئناً شامل دامنه های دارای امتیاز و خط مشی مرده است.

سیاست بزرگ غیر ضروری:

  • هنگامی که خط مشی در ramdisk قرار می گیرد و همچنین در حافظه هسته بارگذاری می شود، به حافظه دو ضربه می زند.
  • فضای دیسک را با نیاز به بوتیماژ بزرگتر هدر می دهد.
  • بر زمان جستجوی خط مشی زمان اجرا تأثیر می گذارد.

مثال زیر دو دستگاه را نشان می‌دهد که در آنها خط‌مشی خاص سازنده 50% و 40% خط‌مشی روی دستگاه را شامل می‌شود. همانطور که در زیر نشان داده شده است، بازنویسی این خط‌مشی، پیشرفت‌های امنیتی قابل‌توجهی را بدون از دست دادن عملکرد به همراه داشت. (دستگاه های AOSP Shamu و Flounder برای مقایسه گنجانده شده اند.)

شکل 1: مقایسه اندازه خط مشی خاص دستگاه پس از ممیزی امنیتی.

شکل 1 . مقایسه اندازه خط مشی خاص دستگاه پس از ممیزی امنیتی.

در هر دو مورد، این سیاست هم از نظر اندازه و هم از نظر تعداد مجوزها به طور چشمگیری کاهش یافت. کاهش اندازه خط مشی تقریباً به طور کامل به دلیل حذف مجوزهای غیرضروری است، که بسیاری از آنها احتمالاً قوانین ایجاد شده توسط audit2allow بوده و به طور بی رویه به خط مشی اضافه شده اند. دامنه های مرده نیز برای هر دو دستگاه یک مشکل بود.

قابلیت dac_override را اعطا کنید

انکار dac_override به این معنی است که فرآیند متخلف سعی در دسترسی به فایلی با مجوزهای نادرست کاربر/گروه/جهان یونیکس دارد. راه حل مناسب تقریباً هرگز اعطای مجوز dac_override نیست. در عوض مجوزهای یونیکس را در فایل یا فرآیند تغییر دهید . تعداد کمی از دامنه‌ها مانند init ، vold ، و installd واقعاً به توانایی نادیده گرفتن مجوزهای فایل یونیکس برای دسترسی به فایل‌های پردازش‌های دیگر نیاز دارند. برای توضیح بیشتر به وبلاگ دن والش مراجعه کنید.