মিডিয়া ফ্রেমওয়ার্ক হার্ডেনিং

ডিভাইসের নিরাপত্তা উন্নত করতে, Android 7.0 মোনোলিথিক mediaserver প্রসেসকে একাধিক প্রসেসে বিভক্ত করে, যার ফলে প্রতিটি প্রসেসের জন্য প্রয়োজনীয় অনুমতি এবং ক্ষমতা সীমিত করা হয়। এইসব পরিবর্তন নিম্নলিখিত উপায়ে মিডিয়া ফ্রেমওয়ার্কের নিরাপত্তা সংক্রান্ত দুর্বলতা কমায়:

  • AV পাইপলাইন কম্পোনেন্টকে অ্যাপ-নির্দিষ্ট স্যান্ডবক্স প্রসেসে ভাগ করা।
  • আপডেট করা যাবে এমন মিডিয়া কম্পোনেন্ট (এক্সট্র্যাক্টর, কোডেক ইত্যাদি) চালু করা।

এছাড়াও, এই পরিবর্তনগুলি বেশিরভাগ মিডিয়া-সম্পর্কিত নিরাপত্তা সংক্রান্ত দুর্বলতার গুরুত্বপূর্ণ বিষয়গুলি উল্লেখযোগ্যভাবে কমিয়ে এনে, এন্ড-ইউজার ডিভাইস ও ডেটা সুরক্ষিত রাখার মাধ্যমে এন্ড-ইউজারদের জন্য নিরাপত্তা উন্নত করে।

OEM এবং SoC ভেন্ডরদের নতুন আর্কিটেকচারের সাথে সামঞ্জস্যপূর্ণ করতে তাদের HAL এবং ফ্রেমওয়ার্ক পরিবর্তন আপডেট করতে হবে। বিশেষত, ভেন্ডর-প্রদানকৃত Android কোড প্রায়ই ধরে নেয় যে সবকিছু একই প্রসেসে রান করে, তাই ভেন্ডরদের অবশ্যই তাদের কোড আপডেট করতে হবে যাতে নেটিভ হ্যান্ডেল (native_handle) পাস করা যায়, যার অর্থ হল প্রসেস জুড়ে। মিডিয়া হার্ডেনিং সম্পর্কিত পরিবর্তনের রেফারেন্স প্রয়োগের জন্য, frameworks/av এবং frameworks/native দেখুন।

আর্কিটেকচারাল পরিবর্তন

Android-এর আগের ভার্সনে একটিই, মনোলিথিক mediaserver প্রসেস ব্যবহার করা হত যাতে অনেক অনুমতি (ক্যামেরা অ্যাক্সেস, অডিও অ্যাক্সেস, ভিডিও ড্রাইভার অ্যাক্সেস, ফাইল অ্যাক্সেস, নেটওয়ার্ক অ্যাক্সেস ইত্যাদি) থাকত। Android 7.0, mediaserver প্রসেসকে একাধিক নতুন প্রসেসে ভাগ করে দেয় যেগুলির প্রত্যেকটির জন্য অনেক ছোট সেট অনুমতির প্রয়োজন হয়:

mediaserver হার্ডেনিং

ছবি ১. mediaserver-এর নিরাপত্তা আরও জোরদার করার জন্য আর্কিটেকচারে পরিবর্তন

এই নতুন আর্কিটেকচার নিশ্চিত করে যে কোনও প্রসেস আপস করা হলেও, ক্ষতিকর কোডের কাছে mediaserver-এর আগে থাকা অনুমতির সম্পূর্ণ সেটে অ্যাক্সেস নেই। SElinux এবং seccomp নীতি দ্বারা প্রসেস সীমাবদ্ধ করা হয়।

মনে রাখবেন: ভেন্ডরের উপর নির্ভর করার কারণে, কিছু কোডেক এখনও mediaserver-এ চলে এবং এর ফলে mediaserver প্রয়োজনের চেয়ে বেশি অনুমতি পায়। বিশেষ করে, Android 7.0-এর জন্য mediaserver-এ Widevine Classic রান করা চালিয়ে যায়।

MediaServer-এ পরিবর্তন

Android 7.0-এ, mediaserver প্রসেসটি ড্রাইভিং প্লেব্যাক ও রেকর্ডিংয়ের জন্য বিদ্যমান, যেমন, কম্পোনেন্ট ও প্রসেসের মধ্যে বাফার পাস ও সিঙ্ক্রোনাইজ করা। প্রসেসগুলি স্ট্যান্ডার্ড বাইন্ডার মেকানিজমের মাধ্যমে যোগাযোগ করে।

একটি সাধারণ লোকাল ফাইল প্লেব্যাক সেশনে, অ্যাপটি mediaserver-এ একটি ফাইল ডেসক্রিপ্টর (FD) পাস করে (সাধারণত MediaPlayer Java API-এর মাধ্যমে) এবং mediaserver:

  1. FD-কে Binder DataSource অবজেক্টে র‍্যাপ করে, যা extractor প্রসেসে পাস করা হয়। এটি Binder IPC ব্যবহার করে ফাইল থেকে রিড করার জন্য এটি ব্যবহার করে। (mediaextractor FD পায় না, তবে ডেটা পাওয়ার জন্য mediaserver-এ বাইন্ডার কল ব্যাক করে।)
  2. ফাইলটি পরীক্ষা করে, ফাইলের ধরনের জন্য উপযুক্ত এক্সট্র্যাক্টর তৈরি করে (যেমন, MP3Extractor বা MPEG4Extractor) এবং mediaserverপ্রসেস করার জন্য এক্সট্র্যাক্টরের একটি বাইন্ডার ইন্টারফেস রিটার্ন করে।
  3. ফাইলের ডেটার ধরন (যেমন, MP3 বা H.264 ডেটা) নির্ধারণ করতে এক্সট্র্যাক্টরের কাছে Binder IPC কল করে।
  4. প্রয়োজনীয় ধরনের কোডেক তৈরি করতে mediacodec প্রসেসে কল করে; এইসব কোডেকের জন্য Binder ইন্টারফেস রিসিভ করে।
  5. এনকোড করা স্যাম্পেল পড়ার জন্য এক্সট্র্যাক্টরকে বারংবার Binder IPC কল করে, ডিকোডিংয়ের জন্য mediacodec প্রসেসে এনকোড করা ডেটা পাঠানোর জন্য Binder IPC ব্যবহার করে এবং ডিকোড করা ডেটা পায়।

কিছু ক্ষেত্রে, কোনও কোডেক ব্যবহার করা হয় না (যেমন অফলোড করা প্লেব্যাক যেখানে এনকোড করা ডেটা সরাসরি আউটপুট ডিভাইসে পাঠানো হয়) অথবা কোডেক ডিকোড করা ডেটার বাফার ফেরত পাঠানোর পরিবর্তে সরাসরি ডিকোড করা ডেটা রেন্ডার করতে পারে (ভিডিও প্লেব্যাক)।

MediaCodecService-এ পরিবর্তন

কোডেক পরিষেবা হল সেই জায়গা যেখানে এনকোডার ও ডিকোডার থাকে। ভেন্ডর নির্ভরতার কারণে, সব কোডেক এখনও কোডেক প্রসেসে লাইভ নেই। Android 7.0-এ:

  • কোডেক প্রসেসে নন-সিকিওর ডিকোডার ও সফ্টওয়্যার এনকোডার থাকে।
  • সুরক্ষিত ডিকোডার ও হার্ডওয়্যার এনকোডার mediaserver (পরিবর্তিত হয়নি) হিসেবে থাকে।

একটি অ্যাপ (বা mediaserver) প্রয়োজনীয় ধরনের কোডেক তৈরি করার জন্য কোডেক প্রসেসকে কল করে, তারপর এনকোড করা ডেটা পাস করতে এবং ডিকোড করা ডেটা (ডিকোড করার জন্য) ফিরিয়ে আনতে অথবা ডিকোড করা ডেটা পাস করতে এবং এনকোড করা ডেটা (এনকোড করার জন্য) ফিরিয়ে আনতে সেই কোডেককে কল করে। কোডেক থেকে ডেটা ট্রান্সফার এবং কোডেকে ডেটা ট্রান্সফার করার জন্য আগে থেকেই শেয়ার করা মেমরি ব্যবহার করা হয়, তাই এই প্রসেসে কোনও পরিবর্তন করা হয়নি।

MediaDrmServer পরিবর্তন

Google Play Movies-এর মতো DRM-সুরক্ষিত কন্টেন্ট চালানোর সময় DRM সার্ভার ব্যবহার করা হয়। এটি এনক্রিপটেড ডেটা নিরাপদে ডিক্রিপ্ট করে, এবং সেই কারণে সার্টিফিকেট ও কী স্টোরেজ এবং অন্যান্য সংবেদনশীল কম্পোনেন্ট অ্যাক্সেস করতে পারে। ভেন্ডরদের উপর নির্ভর করার কারণে, DRM প্রসেস এখনও সব ক্ষেত্রে ব্যবহার করা হয় না।

AudioServer-এ পরিবর্তন

AudioServer প্রসেস অডিও ইনপুট ও আউটপুটের মতো অডিও সম্পর্কিত কম্পোনেন্ট, অডিও রাউটিং নির্ধারণকারী পলিসি ম্যানেজার পরিষেবা এবং FM রেডিও পরিষেবা হোস্ট করে। অডিও পরিবর্তন ও প্রয়োগ সংক্রান্ত নির্দেশিকা সম্পর্কে বিস্তারিত জানতে, অডিও প্রয়োগ করুন দেখুন।

CameraServer-এ পরিবর্তন

CameraServer ক্যামেরা কন্ট্রোল করে এবং ভিডিও রেকর্ড করার সময় এটি ব্যবহার করা হয়। এর মাধ্যমে ক্যামেরা থেকে ভিডিও ফ্রেম পাওয়া যায় এবং তারপরে সেগুলি আরও প্রসেস করার জন্য mediaserver-এ পাঠানো হয়। পরিবর্তন ও CameraServer পরিবর্তনের জন্য প্রয়োগ সংক্রান্ত নির্দেশিকা সম্পর্কে বিস্তারিত জানতে, ক্যামেরা ফ্রেমওয়ার্ক হার্ডেনিং দেখুন।

ExtractorService-এ পরিবর্তন

এক্সট্র্যাক্টর পরিষেবা এক্সট্র্যাক্টর হোস্ট করে, এটি এমন কম্পোনেন্ট যা মিডিয়া ফ্রেমওয়ার্কের সাথে মানানসই বিভিন্ন ফাইল ফর্ম্যাট পার্স করে। এক্সট্র্যাক্টর পরিষেবা সব পরিষেবার মধ্যে সবচেয়ে কম বিশেষ অধিকারপ্রাপ্ত—এটি FD পড়তে পারে না, তাই এর পরিবর্তে এটি ফাইল অ্যাক্সেস করার জন্য Binder ইন্টারফেসে কল করে (যা mediaserver for প্রতিটি প্লেব্যাক সেশন দ্বারা এটিকে প্রদান করা হয়)।

কোনও অ্যাপ (বা mediaserver) এক্সট্র্যাক্টর প্রসেসকে কল করে IMediaExtractor পেতে, সেই IMediaExtractor-কে কল করে ফাইলের মধ্যে থাকা ট্র্যাকের জন্য IMediaSources পেতে এবং তারপরে IMediaSources-কে কল করে সেগুলি থেকে ডেটা পড়তে।

প্রসেসের মধ্যে ডেটা ট্রান্সফার করতে, অ্যাপ (বা mediaserver) Binder ট্রানজ্যাকশনের অংশ হিসেবে উত্তর-পার্সেলে ডেটা অন্তর্ভুক্ত করে অথবা শেয়ার করা মেমরি ব্যবহার করে:

  • শেয়ার করা মেমরি ব্যবহার করার জন্য শেয়ার করা মেমরি রিলিজ করতে একটি অতিরিক্ত বাইন্ডার কল প্রয়োজন হয়, তবে এটি দ্রুত হয় এবং বড় বাফারের জন্য কম পাওয়ার ব্যবহার করে।
  • ইন-পার্সেল ব্যবহার করার জন্য অতিরিক্ত কপি করার প্রয়োজন হয়, তবে এটি দ্রুত কাজ করে এবং ৬৪ কেবির চেয়ে ছোট বাফারের জন্য কম পাওয়ার ব্যবহার করে।

প্রয়োগ

MediaDrm এবং MediaCrypto কম্পোনেন্টকে নতুন mediadrmserver প্রসেসে সরানোর জন্য, ভেন্ডরদের অবশ্যই নিরাপদ বাফারের জন্য বরাদ্দকরণ পদ্ধতি পরিবর্তন করতে হবে যাতে প্রসেসের মধ্যে বাফার শেয়ার করা যায়।

আগের Android রিলিজগুলিতে, সুরক্ষিত বাফার mediaserver দ্বারা OMX::allocateBuffer বরাদ্দ করা হয় এবং নিচে দেখানো একই প্রসেসে ডিক্রিপশনের সময় ব্যবহার করা হয়:

ছবি ২. Android 6.0 ও তার আগের যেকোনও ভার্সনে mediaserver-এ অ্যালোকেশন।

Android 7.0-এ, বাফার অ্যালোকেশন প্রসেস একটি নতুন মেকানিজমে পরিবর্তিত হয়েছে যা আগে থেকে থাকা ইমপ্লিমেন্টেশনের উপর প্রভাব কমিয়ে নমনীয়তা প্রদান করে। নতুন mediadrmserver প্রসেসে MediaDrm ও MediaCrypto স্ট্যাক থাকলে, আলাদাভাবে বাফার অ্যাসাইন করা হয় এবং ভেন্ডরদের অবশ্যই সুরক্ষিত বাফার হ্যান্ডেল আপডেট করতে হবে যাতে MediaCodec, MediaCrypto-এ ডিক্রিপ্ট অপারেশন ইনভোক করলে, সেগুলিকে বাইন্ডার জুড়ে ট্রান্সপোর্ট করা যায়।

ছবি ৩. mediaserver-এ Android 7.0 ও তার পরবর্তী যেকোনও ভার্সনে বাফার অ্যালোকেশন।

নেটিভ হ্যান্ডেল ব্যবহার করুন

OMX::allocateBuffer-কে অবশ্যই native_handle স্ট্রাক্টের একটি পয়েন্টার রিটার্ন করতে হবে, যার মধ্যে ফাইল ডেসক্রিপটর (FD) এবং অতিরিক্ত ইন্টিজার ডেটা থাকে। FD ব্যবহার করার সমস্ত সুবিধা native_handle-এ আছে। এর মধ্যে সিরিয়ালাইজেশন/ডিসিয়ারিয়ালাইজেশনের জন্য আগে থেকেই থাকা বাইন্ডার সাপোর্ট অন্তর্ভুক্ত। এর পাশাপাশি, বর্তমানে FD ব্যবহার না করা ভেন্ডরদের জন্য আরও বেশি সুবিধা প্রদান করে।

নেটিভ হ্যান্ডেল অ্যাসাইন করতে native_handle_create() ব্যবহার করুন। ফ্রেমওয়ার্ক কোড, বরাদ্দ করা native_handle struct-এর মালিকানা নেয় এবং যে প্রসেসে native_handle মূলত বরাদ্দ করা হয় এবং যে প্রসেসে এটি ডিসিরিয়ালাইজ করা হয়, এই দুটি প্রসেসেই রিসোর্স রিলিজ করার দায়িত্ব ফ্রেমওয়ার্ক কোডের। ফ্রেমওয়ার্কটি native_handle_close()-এর সাথে নেটিভ হ্যান্ডেল রিলিজ করে, তারপরে native_handle_delete() এবং Parcel::writeNativeHandle()/readNativeHandle() ব্যবহার করে native_handle সিরিয়ালাইজ/ডিসিরিয়ালাইজ করে।

নিরাপদ বাফার দেখানোর জন্য FD ব্যবহার করে এমন SoC ভেন্ডররা তাদের FD-এর মাধ্যমে native_handle-এ FD পূরণ করতে পারেন। যেসব ভেন্ডর FD ব্যবহার করেন না, তারা native_buffer-এ অতিরিক্ত ফিল্ড ব্যবহার করে সুরক্ষিত বাফার দেখাতে পারেন।

ডিক্রিপশন লোকেশন সেট করা

নতুন প্রসেস স্পেসে native_handle ব্যবহারযোগ্য করে তুলতে প্রয়োজনীয় কোনও ভেন্ডর-নির্দিষ্ট অপারেশন পারফর্ম করতে, ভেন্ডরদের অবশ্যই OEMCrypto ডিক্রিপ্ট পদ্ধতি আপডেট করতে হবে, যা native_handle-এ কাজ করে (পরিবর্তনের মধ্যে সাধারণত OEMCrypto লাইব্রেরিতে আপডেট অন্তর্ভুক্ত থাকে)।

allocateBuffer হল একটি স্ট্যান্ডার্ড OMX অপারেশন, Android 7.0 এই সহায়তা সম্পর্কে কোয়েরি করার জন্য একটি নতুন OMX এক্সটেনশন (OMX.google.android.index.allocateNativeHandle) এবং একটি OMX_SetParameter কল অন্তর্ভুক্ত করে যা OMX ইমপ্লিমেন্টেশনকে জানায় যে এটি নেটিভ হ্যান্ডেল ব্যবহার করা উচিত।