برای بهبود امنیت دستگاه، Android 7.0 فرآیند یکپارچه mediaserver
را به چندین فرآیند با مجوزها و قابلیتهایی محدود میکند که فقط به موارد مورد نیاز هر فرآیند محدود میشود. این تغییرات آسیبپذیریهای امنیتی چارچوب رسانهای را با موارد زیر کاهش میدهد:
- تقسیم اجزای خط لوله AV به فرآیندهای جعبه ایمنی مخصوص برنامه.
- فعال کردن اجزای رسانه ای قابل به روز رسانی (استخراج کننده ها، کدک ها و غیره).
این تغییرات همچنین با کاهش قابل توجهی از شدت آسیبپذیریهای امنیتی مرتبط با رسانه، امنیت دستگاهها و دادههای کاربر نهایی را بهبود میبخشد.
OEM ها و فروشندگان SoC باید تغییرات HAL و چارچوب خود را به روز کنند تا با معماری جدید سازگار شوند. به طور خاص، از آنجا که کد Android ارائهشده توسط فروشنده اغلب فرض میکند که همه چیز در یک فرآیند اجرا میشود، فروشندگان باید کد خود را بهروزرسانی کنند تا دستههای بومی ( native_handle
) را که در بین فرآیندها معنی دارند، منتقل کنند. برای اجرای مرجع تغییرات مربوط به سخت شدن رسانه، به frameworks/av
و frameworks/native
مراجعه کنید.
تغییرات معماری
نسخههای قبلی اندروید از یک فرآیند mediaserver
یکپارچه با مجوزهای بسیار (دسترسی به دوربین، دسترسی صوتی، دسترسی به درایور ویدئو، دسترسی به فایل، دسترسی به شبکه و غیره) استفاده میکردند. Android 7.0 فرآیند mediaserver
را به چندین فرآیند جدید تقسیم می کند که هر کدام به مجموعه بسیار کوچکتری از مجوزها نیاز دارند:
این معماری جدید تضمین میکند که حتی اگر یک فرآیند به خطر بیفتد، کدهای مخرب به مجموعه کامل مجوزهایی که قبلاً توسط mediaserver
نگهداری میشد دسترسی ندارند. فرآیندها توسط سیاست های SElinux و seccomp محدود شده اند.
توجه: به دلیل وابستگیهای فروشنده، برخی از کدکها همچنان در mediaserver
اجرا میشوند و در نتیجه mediaserver
مجوزهای بیشتری از حد لازم میدهند. به طور خاص، Widevine Classic همچنان در mediaserver
اندروید 7.0 اجرا می شود.
MediaServer تغییر می کند
در اندروید 7.0، فرآیند mediaserver
برای پخش و ضبط، به عنوان مثال، عبور و همگام سازی بافرها بین اجزا و فرآیندها وجود دارد. فرآیندها از طریق مکانیسم استاندارد Binder ارتباط برقرار می کنند.
در یک جلسه پخش استاندارد محلی فایل، برنامه یک توصیفگر فایل (FD) را به mediaserver
(معمولاً از طریق MediaPlayer Java API) و mediaserver
ارسال می کند:
- FD را در یک شی Binder DataSource می پیچد که به فرآیند استخراج کننده ارسال می شود، که از آن برای خواندن از فایل با استفاده از Binder IPC استفاده می کند. (مدیا استخراج کننده FD را دریافت نمی کند، اما در عوض Binder را برای دریافت داده ها با
mediaserver
تماس می گیرد.) - فایل را بررسی می کند، استخراج کننده مناسب برای نوع فایل ایجاد می کند (مثلا MP3Extractor، یا MPEG4Extractor)، و یک رابط Binder را برای استخراج کننده به فرآیند
mediaserver
برمی گرداند. - Binder IPC را با استخراج کننده تماس می گیرد تا نوع داده موجود در فایل را تعیین کند (به عنوان مثال داده های MP3 یا H.264).
- فراخوانی به فرآیند
mediacodec
برای ایجاد کدک هایی از نوع مورد نیاز. رابط های Binder را برای این کدک ها دریافت می کند. - تماس های مکرر Binder IPC را برای استخراج نمونه های کدگذاری شده برقرار می کند، از Binder IPC برای ارسال داده های کدگذاری شده به فرآیند
mediacodec
برای رمزگشایی استفاده می کند و داده های رمزگشایی شده را دریافت می کند.
در برخی موارد استفاده، هیچ کدک درگیر نیست (مانند پخش بارگذاری شده که در آن دادههای کدگذاری شده مستقیماً به دستگاه خروجی ارسال میشوند)، یا ممکن است کدک بهجای بازگرداندن بافری از دادههای رمزگشایی شده (پخش ویدیو) دادههای رمزگشایی شده را مستقیماً ارائه دهد.
MediaCodecService تغییر می کند
سرویس کدک جایی است که رمزگذارها و رمزگشاها زندگی می کنند. به دلیل وابستگی های فروشنده، هنوز همه کدک ها در فرآیند کدک زندگی نمی کنند. در اندروید 7.0:
- رمزگشاها و رمزگذارهای نرم افزاری غیر ایمن در فرآیند کدک زندگی می کنند.
- رمزگشاهای ایمن و رمزگذارهای سخت افزاری در
mediaserver
(بدون تغییر) وجود دارند.
یک برنامه (یا mediaserver
) فرآیند کدک را فراخوانی می کند تا یک کدک از نوع مورد نیاز ایجاد کند، سپس آن کدک را فراخوانی می کند تا داده های رمزگذاری شده را ارسال کند و داده های رمزگشایی شده را بازیابی کند (برای رمزگشایی) یا برای ارسال داده های رمزگشایی و بازیابی داده های رمزگذاری شده (برای رمزگذاری) . انتقال داده به و از کدک ها از حافظه مشترک استفاده می کند، بنابراین این فرآیند بدون تغییر است.
MediaDrmServer تغییر می کند
سرور DRM هنگام پخش محتوای محافظت شده با DRM، مانند فیلمها در فیلمهای Google Play استفاده میشود. رمزگشایی داده های رمزگذاری شده را به روشی امن انجام می دهد و به این ترتیب به گواهینامه و ذخیره سازی کلید و سایر اجزای حساس دسترسی دارد. به دلیل وابستگی فروشنده، فرآیند DRM هنوز در همه موارد استفاده نشده است.
AudioServer تغییر می کند
فرآیند AudioServer اجزای مرتبط با صدا مانند ورودی و خروجی صدا، سرویس Policymanager که مسیریابی صدا را تعیین میکند و سرویس رادیو FM را میزبانی میکند. برای جزئیات در مورد تغییرات صوتی و راهنمای پیاده سازی، به پیاده سازی صدا مراجعه کنید.
CameraServer تغییر می کند
CameraServer دوربین را کنترل می کند و هنگام ضبط ویدیو برای به دست آوردن فریم های ویدئویی از دوربین و ارسال آنها به mediaserver
برای مدیریت بیشتر استفاده می شود. برای جزئیات در مورد تغییرات و راهنمایی های پیاده سازی برای تغییرات CameraServer، به Camera Framework Hardening مراجعه کنید.
ExtractorService تغییراتی دارد
سرویس استخراج کننده میزبان استخراج کننده ها است، اجزایی که فرمت های فایل های مختلف پشتیبانی شده توسط چارچوب رسانه را تجزیه می کنند. سرویس استخراج کننده کمترین امتیاز را در بین تمام سرویس ها دارد - نمی تواند FD ها را بخواند بنابراین در عوض با یک رابط Binder (که توسط mediaserver for
هر جلسه پخش به آن ارائه می شود) تماس می گیرد تا به فایل ها دسترسی پیدا کند.
یک برنامه (یا mediaserver
) با فرآیند استخراج کننده تماس می گیرد تا یک IMediaExtractor
به دست آورد، آن IMediaExtractor
را برای دریافت IMediaSources
برای آهنگ موجود در فایل فراخوانی می کند و سپس IMediaSources
را برای خواندن داده ها از آنها فرا می خواند.
برای انتقال دادهها بین فرآیندها، برنامه (یا mediaserver
) دادههای موجود در بسته پاسخ را به عنوان بخشی از تراکنش Binder شامل میشود یا از حافظه مشترک استفاده میکند:
- استفاده از حافظه مشترک به یک فراخوان Binder اضافی برای آزاد کردن حافظه مشترک نیاز دارد، اما سریعتر است و برای بافرهای بزرگ انرژی کمتری مصرف می کند.
- استفاده از درون بسته نیاز به کپی اضافی دارد اما سریعتر است و برای بافرهای کوچکتر از 64 کیلوبایت انرژی کمتری مصرف می کند.
پیاده سازی
برای حمایت از انتقال مولفه های MediaDrm
و MediaCrypto
به فرآیند جدید mediadrmserver
، فروشندگان باید روش تخصیص بافرهای امن را تغییر دهند تا بافرها بتوانند بین فرآیندها به اشتراک گذاشته شوند.
در نسخههای قبلی اندروید، بافرهای امن توسط OMX::allocateBuffer
در mediaserver
اختصاص داده میشوند و در طول رمزگشایی در همان فرآیند استفاده میشوند، همانطور که در زیر نشان داده شده است:
در اندروید 7.0، فرآیند تخصیص بافر به مکانیزم جدیدی تغییر کرده است که انعطافپذیری را فراهم میکند و در عین حال تأثیر بر پیادهسازیهای موجود را به حداقل میرساند. با پشته های MediaDrm
و MediaCrypto
در فرآیند جدید mediadrmserver
، بافرها به طور متفاوتی تخصیص داده می شوند و فروشندگان باید دسته های بافر ایمن را به روز کنند تا زمانی که MediaCodec
یک عملیات رمزگشایی را در MediaCrypto
فراخوانی می کند، در بیندر منتقل شوند.
از دسته های بومی استفاده کنید
OMX::allocateBuffer
باید یک اشاره گر را به ساختار native_handle
برگرداند که حاوی توصیفگرهای فایل (FD) و داده های عدد صحیح اضافی است. یک native_handle
تمام مزایای استفاده از FD ها را دارد، از جمله پشتیبانی موجود برای سریال سازی/آشوب زدایی، در حالی که به فروشندگانی که در حال حاضر از FD ها استفاده نمی کنند، انعطاف پذیری بیشتری می دهد.
از native_handle_create()
برای تخصیص دسته بومی استفاده کنید. کد چارچوب مالکیت ساختار اختصاصی native_handle
را در اختیار میگیرد و مسئول انتشار منابع در هر دو فرآیندی است که native_handle
در ابتدا تخصیص داده شده است و در فرآیندی که از فهرست خارج میشود. این فریم ورک هندلهای بومی را با native_handle_close()
و به دنبال آن native_handle_delete()
منتشر میکند و با استفاده از Parcel::writeNativeHandle()/readNativeHandle()
native_handle
سریالسازی/غیرهسازی میکند.
فروشندگان SoC که از FD ها برای نمایش بافرهای ایمن استفاده می کنند، می توانند FD را در native_handle
با FD خود پر کنند. فروشندگانی که از FD ها استفاده نمی کنند می توانند بافرهای امن را با استفاده از فیلدهای اضافی در native_buffer
نشان دهند.
تنظیم مکان رمزگشایی
فروشندگان باید روش رمزگشایی OEMCrypto را که در native_handle
عمل میکند، بهروزرسانی کنند تا هرگونه عملیات خاص فروشنده لازم برای قابل استفاده کردن native_handle
در فضای فرآیند جدید را انجام دهد (تغییرات معمولاً شامل بهروزرسانیهای کتابخانههای OEMCrypto است).
از آنجایی که allocateBuffer
یک عملیات استاندارد OMX است، Android 7.0 شامل یک افزونه OMX جدید ( OMX.google.android.index.allocateNativeHandle
) برای درخواست این پشتیبانی و یک فراخوانی OMX_SetParameter
است که به اجرای OMX اطلاع می دهد که باید از دسته های بومی استفاده کند.