LLVM, অ্যান্ড্রয়েড তৈরি করতে ব্যবহৃত কম্পাইলার পরিকাঠামোতে একাধিক উপাদান রয়েছে যা স্ট্যাটিক এবং ডাইনামিক বিশ্লেষণ করে। এই উপাদানগুলির মধ্যে, স্যানিটাইজারগুলি - বিশেষত অ্যাড্রেস স্যানিটাইজার এবং অনির্ধারিত আচরণ স্যানিটাইজার - অ্যান্ড্রয়েড বিশ্লেষণ করতে ব্যাপকভাবে ব্যবহার করা যেতে পারে৷ স্যানিটাইজারগুলি হল কম্পাইলার-ভিত্তিক ইন্সট্রুমেন্টেশন উপাদান যা এক্সটার্নাল/কম্পাইলার-আরটি-তে রয়েছে যা বাগগুলি দূর করতে এবং অ্যান্ড্রয়েডকে আরও ভাল করতে বিকাশ এবং পরীক্ষার সময় ব্যবহার করা যেতে পারে। অ্যান্ড্রয়েডের বর্তমান স্যানিটাইজার সেট অনেক মেমরি অপব্যবহারের বাগ এবং সম্ভাব্য বিপজ্জনক অনির্ধারিত আচরণ আবিষ্কার এবং নির্ণয় করতে পারে।
অ্যাড্রেস স্যানিটাইজার এবং আনডিফাইন্ড বিহেভিয়ার স্যানিটাইজারের মতো স্যানিটাইজার সক্ষম করে বুট করা এবং চালানোর জন্য এটি অ্যান্ড্রয়েড বিল্ডগুলির জন্য সেরা অনুশীলন। এই পৃষ্ঠাটি AddressSanitizer, UndefinedBehaviorSanitizer, এবং KernelAddressSanitizer এর সাথে পরিচয় করিয়ে দেয়, এগুলিকে Android বিল্ড সিস্টেমের মধ্যে কীভাবে ব্যবহার করা যেতে পারে তা দেখায় এবং Android.mk এবং Android.bp ফাইলগুলির উদাহরণ দেয় যা এই স্যানিটাইজারগুলি সক্ষম করে নেটিভ উপাদান তৈরি করে৷
অ্যাড্রেস স্যানিটাইজার
অ্যাড্রেস স্যানিটাইজার ( ASan ) হল একটি কম্পাইলার-ভিত্তিক ইন্সট্রুমেন্টেশন ক্ষমতা যা রানটাইমে C/C++ কোডে অনেক ধরনের মেমরি ত্রুটি সনাক্ত করে। ASan অনেক শ্রেণীর মেমরি ত্রুটি সনাক্ত করতে পারে, যার মধ্যে রয়েছে:
- সীমার বাইরে মেমরি অ্যাক্সেস
- ডাবল ফ্রি
- ব্যবহার-পর-মুক্ত
অ্যান্ড্রয়েড ASan ইন্সট্রুমেন্টেশনের জন্য ফুল-বিল্ড লেভেলে এবং অ্যাপ লেভেলে অ্যাসানর্যাপারের সাথে অনুমতি দেয়।
অ্যাড্রেস স্যানিটাইজার সমস্ত মেমরি-সম্পর্কিত ফাংশন কলগুলির ইন্সট্রুমেন্টেশনকে একত্রিত করে—অ্যালোকা, ম্যালোক, এবং ফ্রি সহ—এবং মেমরির সাথে সমস্ত ভেরিয়েবল এবং বরাদ্দ করা মেমরি অঞ্চলগুলিকে প্যাডিং করে যা একটি ASan কলব্যাককে ট্রিগার করে যখন এটি পড়া বা লেখা হয়।
ইন্সট্রুমেন্টেশনটি ASan কে ভুল মেমরি ব্যবহারের বাগ শনাক্ত করতে দেয়, যার মধ্যে ডাবল-ফ্রি, এবং ইউজ-আফটার স্কোপ, রিটার্ন এবং ফ্রি সহ, যখন মেমরি-রিজিয়ন প্যাডিং রিড বা লেখার সীমার বাইরে শনাক্ত করে। যদি এই প্যাডিং অঞ্চলে একটি পড়া বা লেখা হয়, ASan এটিকে ধরে এবং মেমরি লঙ্ঘন নির্ণয় করতে সাহায্য করার জন্য তথ্য আউটপুট করে, যার মধ্যে কল স্ট্যাক, শ্যাডো মেমরি ম্যাপ, মেমরি লঙ্ঘনের ধরন, কী পড়া বা লেখা হয়েছিল, নির্দেশাবলী যা এই সমস্যা সৃষ্টি করেছিল। লঙ্ঘন, এবং মেমরি বিষয়বস্তু.
pixel-xl:/ # sanitizer-status ================================================================= ==14164==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x0032000054b0 at pc 0x005df16ffc3c bp 0x007fc236fdf0 sp 0x007fc236fdd0 WRITE of size 1 at 0x0032000054b0 thread T0 #0 0x5df16ffc3b in test_crash_malloc sanitizer-status/sanitizer-status.c:36:13 #1 0x5df17004e3 in main sanitizer-status/sanitizer-status.c:76:7 #2 0x794cf665f3 in __libc_init (/system/lib64/libc.so+0x1b5f3) #3 0x5df16ffa53 in do_arm64_start (/system/bin/sanitizer-status+0xa53) 0x0032000054b0 is located 0 bytes to the right of 32-byte region [0x003200005490,0x0032000054b0) allocated by thread T0 here: #0 0x794d0bdc67 in malloc (/system/lib64/libclang_rt.asan-aarch64-android.so+0x74c67) #1 0x5df16ffb47 in test_crash_malloc sanitizer-status/sanitizer-status.c:34:25 #2 0x5df17004e3 in main sanitizer-status/sanitizer-status.c:76:7 #3 0x794cf665f3 in __libc_init (/system/lib64/libc.so+0x1b5f3) #4 0x5df16ffa53 in do_arm64_start (/system/bin/sanitizer-status+0xa53) #5 0x794df78893 (<unknown module>) SUMMARY: AddressSanitizer: heap-buffer-overflow sanitizer-status/sanitizer-status.c:36:13 in test_crash_malloc
কখনও কখনও, বাগ আবিষ্কার প্রক্রিয়াটি অ-নির্ধারক বলে মনে হতে পারে, বিশেষ করে বাগগুলির জন্য যার জন্য বিশেষ সেটআপ বা আরও উন্নত কৌশল প্রয়োজন, যেমন হিপ প্রাইমিং বা রেস কন্ডিশন শোষণ। এই বাগগুলির মধ্যে অনেকগুলি তাত্ক্ষণিকভাবে দৃশ্যমান নয়, এবং মেমরি লঙ্ঘন থেকে হাজার হাজার নির্দেশাবলী সরাতে পারে যা প্রকৃত মূল কারণ ছিল। ASan ইন্সট্রুমেন্ট সমস্ত মেমরি-সম্পর্কিত ফাংশন এবং প্যাড ডেটা এমন অঞ্চলগুলির সাথে যুক্ত করে যা ASan কলব্যাক ট্রিগার না করে অ্যাক্সেস করা যায় না। এর মানে হল যে মেমরি লঙ্ঘনগুলি ক্র্যাশ-প্ররোচিত দুর্নীতির জন্য অপেক্ষা করার পরিবর্তে তাৎক্ষণিকভাবে ধরা পড়ে। এটি বাগ আবিষ্কার এবং মূল কারণ নির্ণয়ের ক্ষেত্রে অত্যন্ত কার্যকর।
ASAN একটি টার্গেট ডিভাইসে কার্যকরী কিনা তা যাচাই করতে, Android asan_test এক্সিকিউটেবল অন্তর্ভুক্ত করেছে। asan_test এক্সিকিউটেবল পরীক্ষা করে এবং একটি টার্গেট ডিভাইসে ASAN কার্যকারিতা যাচাই করে, প্রতিটি পরীক্ষার স্থিতি সহ ডায়াগনস্টিক বার্তা দেয়। একটি ASAN Android বিল্ড ব্যবহার করার সময়, এটি /data/nativetest/asan_test/asan_test
বা /data/nativetest64/asan_test/asan_test
এ অবস্থিত।
অনির্ধারিত আচরণ স্যানিটাইজার
Undefined BehaviorSanitizer (UBSan) বিভিন্ন ধরনের অনির্ধারিত আচরণ পরীক্ষা করার জন্য কম্পাইল-টাইম ইন্সট্রুমেন্টেশন করে। UBSan অনেক অনির্ধারিত আচরণ সনাক্ত করতে সক্ষম হলেও, Android সারিবদ্ধকরণ, বুল, সীমানা, এনাম, ফ্লোট-কাস্ট-ওভারফ্লো, ফ্লোট-বিভাজন-বাই-শূন্য, পূর্ণসংখ্যা-বিভাজন-বাই-শূন্য, নন-অ্যাট্রিবিউট, নাল, রিটার্ন, সমর্থন করে। রিটার্ন-অনুল-অ্যাট্রিবিউট, শিফট-বেস, শিফট-এক্সপোনেন্ট, স্বাক্ষরিত-পূর্ণসংখ্যা-ওভারফ্লো, পৌঁছানো যায় না, স্বাক্ষরবিহীন-পূর্ণসংখ্যা-ওভারফ্লো, এবং vla-বাউন্ড। স্বাক্ষরবিহীন-পূর্ণসংখ্যা-ওভারফ্লো, যদিও প্রযুক্তিগতভাবে একটি অনির্ধারিত আচরণ নয়, এটি স্যানিটাইজারে অন্তর্ভুক্ত করা হয়েছে এবং মিডিয়াসার্ভার উপাদান সহ অনেকগুলি অ্যান্ড্রয়েড মডিউলে ব্যবহার করা হয়েছে, কোনো সুপ্ত পূর্ণসংখ্যা-ওভারফ্লো দুর্বলতা দূর করতে।
বাস্তবায়ন
অ্যান্ড্রয়েড বিল্ড সিস্টেমে, আপনি বিশ্বব্যাপী বা স্থানীয়ভাবে UBSan সক্ষম করতে পারেন। বিশ্বব্যাপী UBSan সক্ষম করতে, Android.mk-এ SANITIZE_TARGET সেট করুন। প্রতি-মডিউল স্তরে UBSan সক্ষম করতে, LOCAL_SANITIZE সেট করুন এবং আপনি Android.mk-এ খুঁজতে চান এমন অনির্ধারিত আচরণগুলি নির্দিষ্ট করুন৷ উদাহরণ স্বরূপ:
LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_CFLAGS := -std=c11 -Wall -Werror -O0 LOCAL_SRC_FILES:= sanitizer-status.c LOCAL_MODULE:= sanitizer-status LOCAL_SANITIZE := alignment bounds null unreachable integer LOCAL_SANITIZE_DIAG := alignment bounds null unreachable integer include $(BUILD_EXECUTABLE)
অ্যান্ড্রয়েড বিল্ড সিস্টেম এখনও মেকফাইলের মতো ব্লুপ্রিন্ট ফাইলগুলিতে বিস্তারিত ডায়াগনস্টিক সমর্থন করে না। এখানে একটি ব্লুপ্রিন্ট (Android.bp) হিসাবে লেখা নিকটতম সমতুল্য:
cc_binary { cflags: [ "-std=c11", "-Wall", "-Werror", "-O0", ], srcs: ["sanitizer-status.c"], name: "sanitizer-status", sanitize: { misc_undefined: [ "alignment", "bounds", "null", "unreachable", "integer", ], diag: { undefined : true }, }, }
UBSan শর্টকাট
একই সময়ে স্যানিটাইজারগুলির একটি সেট সক্ষম করার জন্য অ্যান্ড্রয়েডের দুটি শর্টকাট, integer
এবং default-ub
রয়েছে। পূর্ণসংখ্যা integer-divide-by-zero
, signed-integer-overflow
এবং unsigned-integer-overflow
সক্ষম করে। default-ub
ন্যূনতম কম্পাইলার কর্মক্ষমতা সমস্যা আছে যে চেক সক্রিয়: bool, integer-divide-by-zero, return, returns-nonnull-attribute, shift-exponent, unreachable এবং vla-bound. পূর্ণসংখ্যা স্যানিটাইজার ক্লাসটি SANITIZE_TARGET এবং LOCAL_SANITIZE এর সাথে ব্যবহার করা যেতে পারে, যখন ডিফল্ট-ub শুধুমাত্র SANITIZE_TARGET এর সাথে ব্যবহার করা যেতে পারে।
ভাল ত্রুটি রিপোর্টিং
অ্যান্ড্রয়েডের ডিফল্ট UBSan বাস্তবায়ন একটি নির্দিষ্ট ফাংশন আহ্বান করে যখন অনির্ধারিত আচরণের সম্মুখীন হয়। ডিফল্টরূপে, এই ফাংশনটি বাতিল করা হয়। যাইহোক, অক্টোবর 2016 থেকে শুরু করে, অ্যান্ড্রয়েডে UBSan-এর একটি ঐচ্ছিক রানটাইম লাইব্রেরি রয়েছে যা আরও বিস্তারিত ত্রুটি রিপোর্টিং দেয়, যার মধ্যে অনির্ধারিত আচরণের ধরন, ফাইল এবং সোর্স কোড লাইনের তথ্য রয়েছে। পূর্ণসংখ্যা চেকের সাথে এই ত্রুটি রিপোর্টিং সক্ষম করতে একটি Android.mk ফাইলে নিম্নলিখিতগুলি যুক্ত করুন:
LOCAL_SANITIZE:=integer LOCAL_SANITIZE_DIAG:=integer
LOCAL_SANITIZE মান নির্মাণের সময় স্যানিটাইজার সক্ষম করে৷ LOCAL_SANITIZE_DIAG নির্দিষ্ট স্যানিটাইজারের জন্য ডায়াগনস্টিক মোড চালু করে। LOCAL_SANITIZE এবং LOCAL_SANITIZE_DIAG বিভিন্ন মান সেট করা সম্ভব, কিন্তু LOCAL_SANITIZE-এ শুধুমাত্র সেই চেকগুলি সক্ষম করা হয়েছে৷ যদি একটি চেক LOCAL_SANITIZE-এ নির্দিষ্ট করা না থাকে, কিন্তু LOCAL_SANITIZE_DIAG-তে নির্দিষ্ট করা থাকে, তাহলে চেকটি সক্ষম করা হয় না এবং ডায়াগনস্টিক বার্তা দেওয়া হয় না৷
এখানে UBSan রানটাইম লাইব্রেরি দ্বারা প্রদত্ত তথ্যের একটি উদাহরণ রয়েছে:
pixel-xl:/ # sanitizer-status ubsan sanitizer-status/sanitizer-status.c:53:6: runtime error: unsigned integer overflow: 18446744073709551615 + 1 cannot be represented in type 'size_t' (aka 'unsigned long')
কার্নেল ঠিকানা স্যানিটাইজার
ইউজারস্পেস উপাদানগুলির জন্য এলএলভিএম-ভিত্তিক স্যানিটাইজারগুলির মতো, অ্যান্ড্রয়েডে কার্নেল অ্যাড্রেস স্যানিটাইজার (কাসান) অন্তর্ভুক্ত রয়েছে। KASAN হল কার্নেল এবং কম্পাইল টাইম পরিবর্তনের সংমিশ্রণ যার ফলে একটি ইন্সট্রুমেন্টেড সিস্টেম তৈরি হয় যা সহজ বাগ আবিষ্কার এবং মূল কারণ বিশ্লেষণের অনুমতি দেয়।
KASAN কার্নেলের অনেক ধরনের মেমরি লঙ্ঘন সনাক্ত করতে পারে। এটি স্ট্যাক, হিপ এবং গ্লোবাল ভেরিয়েবলগুলিতে আউট-অফ-বাউন্ড রিড এবং রাইটিং সনাক্ত করতে পারে এবং ব্যবহার-পর-মুক্ত এবং ডবল ফ্রিগুলি সনাক্ত করতে পারে।
ASAN-এর মতো, KASAN রানটাইমে মেমরি অ্যাক্সেস ট্র্যাক করতে কম্পাইল টাইমে মেমরি-ফাংশন ইন্সট্রুমেন্টেশন এবং শ্যাডো মেমরির সংমিশ্রণ ব্যবহার করে। KASAN-এ, কার্নেল মেমরি স্পেসের অষ্টমাংশ শ্যাডো মেমরির জন্য নিবেদিত, যা মেমরি অ্যাক্সেস বৈধ কিনা তা নির্ধারণ করে।
KASAN x86_64 এবং arm64 আর্কিটেকচারে সমর্থিত। এটি 4.0 থেকে আপস্ট্রিম কার্নেলের অংশ, এবং Android 3.18-ভিত্তিক কার্নেলে ব্যাকপোর্ট করা হয়েছে। KASAN 4.9.2 এর উপর ভিত্তি করে gcc দিয়ে সংকলিত অ্যান্ড্রয়েড কার্নেলগুলিতে পরীক্ষা করা হয়েছে।
KASAN ছাড়াও, kcov হল আরেকটি কার্নেল পরিবর্তন যা পরীক্ষার জন্য উপযোগী। কার্নেলে কভারেজ-নির্দেশিত ফাজ পরীক্ষার অনুমতি দেওয়ার জন্য kcov তৈরি করা হয়েছিল। এটি syscall ইনপুটগুলির পরিপ্রেক্ষিতে কভারেজ পরিমাপ করে এবং syzkaller-এর মতো ফাজিং সিস্টেমের সাথে উপযোগী।
বাস্তবায়ন
KASAN এবং kcov সক্ষম করে একটি কার্নেল কম্পাইল করতে, আপনার কার্নেল বিল্ড কনফিগারেশনে নিম্নলিখিত বিল্ড ফ্ল্যাগগুলি যোগ করুন:
CONFIG_KASAN CONFIG_KASAN_INLINE CONFIG_TEST_KASAN CONFIG_KCOV CONFIG_SLUB CONFIG_SLUB_DEBUG CONFIG_CC_OPTIMIZE_FOR_SIZE
এবং নিম্নলিখিত অপসারণ:
CONFIG_SLUB_DEBUG_ON CONFIG_SLUB_DEBUG_PANIC_ON CONFIG_KASAN_OUTLINE CONFIG_KERNEL_LZ4
তারপরে যথারীতি আপনার কার্নেল তৈরি করুন এবং ফ্ল্যাশ করুন। KASAN কার্নেলটি আসলটির চেয়ে যথেষ্ট বড়। প্রযোজ্য হলে, এটি বিবেচনায় নিতে বুট প্যারামিটার এবং বুটলোডার সেটিংস পরিবর্তন করুন।
কার্নেল ফ্ল্যাশ করার পরে, KASAN সক্রিয় এবং চলমান কিনা তা দেখতে কার্নেল বুট লগগুলি পরীক্ষা করুন৷ কার্নেল KASAN-এর জন্য মেমরি ম্যাপ তথ্য দিয়ে শুরু করবে, যেমন:
... [ 0.000000] c0 0 Virtual kernel memory layout: [ 0.000000] c0 0 kasan : 0xffffff8000000000 - 0xffffff9000000000 ( 64 GB) [ 0.000000] c0 0 vmalloc : 0xffffff9000010000 - 0xffffffbdbfff0000 ( 182 GB) [ 0.000000] c0 0 vmemmap : 0xffffffbdc0000000 - 0xffffffbfc0000000 ( 8 GB maximum) [ 0.000000] c0 0 0xffffffbdc0000000 - 0xffffffbdc3f95400 ( 63 MB actual) [ 0.000000] c0 0 PCI I/O : 0xffffffbffa000000 - 0xffffffbffb000000 ( 16 MB) [ 0.000000] c0 0 fixed : 0xffffffbffbdfd000 - 0xffffffbffbdff000 ( 8 KB) [ 0.000000] c0 0 modules : 0xffffffbffc000000 - 0xffffffc000000000 ( 64 MB) [ 0.000000] c0 0 memory : 0xffffffc000000000 - 0xffffffc0fe550000 ( 4069 MB) [ 0.000000] c0 0 .init : 0xffffffc001d33000 - 0xffffffc001dce000 ( 620 KB) [ 0.000000] c0 0 .text : 0xffffffc000080000 - 0xffffffc001d32284 ( 29385 KB) ...
এবং এইভাবে একটি বাগ দেখাবে:
[ 18.539668] c3 1 ================================================================== [ 18.547662] c3 1 BUG: KASAN: null-ptr-deref on address 0000000000000008 [ 18.554689] c3 1 Read of size 8 by task swapper/0/1 [ 18.559988] c3 1 CPU: 3 PID: 1 Comm: swapper/0 Tainted: G W 3.18.24-xxx #1 [ 18.569275] c3 1 Hardware name: Android Device [ 18.577433] c3 1 Call trace: [ 18.580739] c3 1 [<ffffffc00008b32c>] dump_backtrace+0x0/0x2c4 [ 18.586985] c3 1 [<ffffffc00008b600>] show_stack+0x10/0x1c [ 18.592889] c3 1 [<ffffffc001481194>] dump_stack+0x74/0xc8 [ 18.598792] c3 1 [<ffffffc000202ee0>] kasan_report+0x11c/0x4d0 [ 18.605038] c3 1 [<ffffffc00020286c>] __asan_load8+0x20/0x80 [ 18.611115] c3 1 [<ffffffc000bdefe8>] android_verity_ctr+0x8cc/0x1024 [ 18.617976] c3 1 [<ffffffc000bcaa2c>] dm_table_add_target+0x3dc/0x50c [ 18.624832] c3 1 [<ffffffc001bdbe60>] dm_run_setup+0x50c/0x678 [ 18.631082] c3 1 [<ffffffc001bda8c0>] prepare_namespace+0x44/0x1ac [ 18.637676] c3 1 [<ffffffc001bda170>] kernel_init_freeable+0x328/0x364 [ 18.644625] c3 1 [<ffffffc001478e20>] kernel_init+0x10/0xd8 [ 18.650613] c3 1 ==================================================================
উপরন্তু, আপনার কার্নেলে মডিউল সক্রিয় করা থাকলে, আপনি আরও পরীক্ষার জন্য test_kasan কার্নেল মডিউল লোড করতে পারেন। মডিউলটি সীমার বাইরে মেমরি অ্যাক্সেস করার চেষ্টা করে এবং বিনামূল্যে ব্যবহার করে এবং একটি লক্ষ্য ডিভাইসে KASAN পরীক্ষা করার জন্য দরকারী।