ঠিকানা স্যানিটাইজার (ASan) নেটিভ কোডে মেমরি বাগ সনাক্ত করার জন্য একটি দ্রুত কম্পাইলার-ভিত্তিক টুল।
ASan সনাক্ত করে:
- স্ট্যাক এবং হিপ বাফার ওভারফ্লো/আন্ডারফ্লো
- বিনামূল্যে পরে গাদা ব্যবহার
- সুযোগের বাইরে স্ট্যাক ব্যবহার করুন
- ডাবল ফ্রি/ওয়াইল্ড ফ্রি
ASan 32-বিট এবং 64-বিট এআরএম, প্লাস x86 এবং x86-64 উভয়েই চলে। ASan এর CPU ওভারহেড মোটামুটি 2x, কোড সাইজ ওভারহেড 50% এবং 2x এর মধ্যে, এবং একটি বড় মেমরি ওভারহেড (আপনার বরাদ্দের প্যাটার্নের উপর নির্ভর করে, কিন্তু 2x এর ক্রম অনুসারে)।
অ্যান্ড্রয়েড 10 এবং AArch64-এর AOSP প্রধান শাখা হার্ডওয়্যার-সহায়ক অ্যাড্রেস স্যানিটাইজার (HWASan) সমর্থন করে, একটি অনুরূপ টুল যা নিম্ন RAM ওভারহেড এবং একটি বৃহত্তর পরিসরে শনাক্ত করা বাগ। HWASan ফিরে আসার পরে স্ট্যাকের ব্যবহার শনাক্ত করে, ASan দ্বারা শনাক্ত করা বাগগুলি ছাড়াও।
HWASan-এর একই রকম CPU এবং কোড সাইজ ওভারহেড আছে, কিন্তু অনেক ছোট RAM ওভারহেড (15%)। এইচডব্লিউএসান ননডিটারমিনিস্টিক। শুধুমাত্র 256টি সম্ভাব্য ট্যাগ মান আছে, তাই কোনো বাগ মিস হওয়ার সম্ভাবনা 0.4% সমতল। HWASan-এর ওভারফ্লো শনাক্ত করার জন্য ASan-এর সীমিত আকারের রেড জোন নেই এবং ব্যবহার-পর-মুক্ত-ব্যবহার শনাক্ত করার জন্য সীমিত-ক্ষমতার কোয়ারেন্টাইন নেই, তাই HWASan-এর কাছে ওভারফ্লো কত বড় বা কতদিন আগে মেমরি ডিলকেড করা হয়েছিল তা বিবেচ্য নয়। এটি HWASan কে ASan এর থেকে ভাল করে তোলে। আপনি HWASan এর ডিজাইন সম্পর্কে বা Android এ HWASan এর ব্যবহার সম্পর্কে আরও পড়তে পারেন।
ASan হিপ ওভারফ্লো ছাড়াও স্ট্যাক/গ্লোবাল ওভারফ্লো শনাক্ত করে এবং ন্যূনতম মেমরি ওভারহেড সহ দ্রুত।
এই দস্তাবেজটি বর্ণনা করে যে কীভাবে ASan-এর সাহায্যে অ্যান্ড্রয়েডের সমস্ত অংশ তৈরি এবং চালানো যায়। আপনি যদি ASan-এর সাথে একটি SDK/NDK অ্যাপ তৈরি করেন, তাহলে এর পরিবর্তে অ্যাড্রেস স্যানিটাইজার দেখুন।
ASan এর সাথে পৃথক এক্সিকিউটেবল স্যানিটাইজ করুন
এক্সিকিউটেবলের জন্য বিল্ড নিয়মে LOCAL_SANITIZE:=address
বা sanitize: { address: true }
যোগ করুন। আপনি বিদ্যমান উদাহরণগুলির জন্য বা অন্যান্য উপলব্ধ স্যানিটাইজারগুলি খুঁজে পেতে কোডটি অনুসন্ধান করতে পারেন।
যখন একটি বাগ শনাক্ত করা হয়, ASan স্ট্যান্ডার্ড আউটপুট এবং logcat
উভয় ক্ষেত্রেই একটি ভার্বোস রিপোর্ট প্রিন্ট করে এবং তারপর প্রক্রিয়াটি ক্র্যাশ করে।
ASan-এর সাথে শেয়ার করা লাইব্রেরি স্যানিটাইজ করুন
ASan যেভাবে কাজ করে তার কারণে, ASan-এর সাহায্যে নির্মিত একটি লাইব্রেরি শুধুমাত্র ASan-এর সাহায্যে নির্মিত এক্সিকিউটেবল দ্বারা ব্যবহার করা যেতে পারে।
একাধিক এক্সিকিউটেবলে ব্যবহৃত একটি শেয়ার্ড লাইব্রেরি স্যানিটাইজ করতে, যার সবকটিই ASan দিয়ে তৈরি নয়, আপনার লাইব্রেরির দুটি কপি প্রয়োজন। এটি করার প্রস্তাবিত উপায় হল প্রশ্নে থাকা মডিউলটির জন্য Android.mk
এ নিম্নলিখিতগুলি যুক্ত করা:
LOCAL_SANITIZE:=address LOCAL_MODULE_RELATIVE_PATH := asan
এটি লাইব্রেরীকে /system/lib/asan
এর পরিবর্তে /system/lib
/asan-এ রাখে। তারপরে, এর সাথে আপনার এক্সিকিউটেবল চালান:
LD_LIBRARY_PATH=/system/lib/asan
সিস্টেম ডেমনের জন্য, /init.rc
বা /init.$device$.rc
এর উপযুক্ত বিভাগে নিম্নলিখিতটি যোগ করুন।
setenv LD_LIBRARY_PATH /system/lib/asan
যাচাই করুন যে প্রক্রিয়াটি /proc/$PID/maps
পড়ে উপস্থিত হলে /system/lib/asan
থেকে লাইব্রেরি ব্যবহার করছে। যদি তা না হয়, তাহলে আপনাকে SELinux নিষ্ক্রিয় করতে হতে পারে:
adb root
adb shell setenforce 0
# restart the process with adb shell kill $PID # if it is a system service, or may be adb shell stop; adb shell start.
ভাল স্ট্যাক ট্রেস
প্রোগ্রামে প্রতিটি মেমরি বরাদ্দ এবং ডিললোকেশন ইভেন্টের জন্য একটি স্ট্যাক ট্রেস রেকর্ড করতে ASan একটি দ্রুত, ফ্রেম-পয়েন্টার-ভিত্তিক আনউইন্ডার ব্যবহার করে। বেশিরভাগ অ্যান্ড্রয়েড ফ্রেম পয়েন্টার ছাড়াই তৈরি। ফলস্বরূপ, আপনি প্রায়শই শুধুমাত্র এক বা দুটি অর্থপূর্ণ ফ্রেম পান। এটি ঠিক করতে, হয় ASan (প্রস্তাবিত!), অথবা এর সাথে লাইব্রেরিটি পুনর্নির্মাণ করুন:
LOCAL_CFLAGS:=-fno-omit-frame-pointer LOCAL_ARM_MODE:=arm
অথবা প্রক্রিয়া পরিবেশে ASAN_OPTIONS=fast_unwind_on_malloc=0
সেট করুন। লোডের উপর নির্ভর করে পরেরটি খুব CPU-নিবিড় হতে পারে।
প্রতীকীকরণ
প্রাথমিকভাবে, ASan রিপোর্টে বাইনারি এবং শেয়ার করা লাইব্রেরিতে অফসেটের উল্লেখ থাকে। উৎস ফাইল এবং লাইন তথ্য প্রাপ্ত করার দুটি উপায় আছে:
- নিশ্চিত করুন যে
llvm-symbolizer
বাইনারি/system/bin
এ উপস্থিত রয়েছে।llvm-symbolizer
third_party/llvm/tools/llvm-symbolizer
উৎস থেকে তৈরি করা হয়েছে। -
external/compiler-rt/lib/asan/scripts/symbolize.py
স্ক্রিপ্টের মাধ্যমে প্রতিবেদনটি ফিল্টার করুন।
দ্বিতীয় পদ্ধতিটি হোস্টে প্রতীকী লাইব্রেরিগুলির প্রাপ্যতার কারণে আরও ডেটা (অর্থাৎ file:line
অবস্থান) সরবরাহ করতে পারে।
অ্যাপসে ASan
ASan জাভা কোড দেখতে পারে না, তবে এটি JNI লাইব্রেরিতে বাগ সনাক্ত করতে পারে। এর জন্য, আপনাকে ASan দিয়ে এক্সিকিউটেবল তৈরি করতে হবে, যা এই ক্ষেত্রে /system/bin/app_process( 32|64 )
। এটি একই সময়ে ডিভাইসের সমস্ত অ্যাপে ASan সক্ষম করে, যা একটি ভারী বোঝা, কিন্তু 2 GB RAM সহ একটি ডিভাইস এটি পরিচালনা করতে সক্ষম হওয়া উচিত।
frameworks/base/cmds/app_process
এ app_process
বিল্ড নিয়মে LOCAL_SANITIZE:=address
যোগ করুন। আপাতত একই ফাইলে app_process__asan
লক্ষ্য উপেক্ষা করুন (যদি আপনি এটি পড়ার সময় এটি এখনও সেখানে থাকে)।
উপযুক্ত system/core/rootdir/init.zygote( 32|64 ).rc
ফাইলের service zygote
বিভাগটি সম্পাদনা করুন class main
ধারণকারী ইন্ডেন্টেড লাইনের ব্লকে নিম্নলিখিত লাইনগুলি যোগ করতে, একই পরিমাণ দ্বারা ইন্ডেন্ট করা হয়েছে:
setenv LD_LIBRARY_PATH /system/lib/asan:/system/lib setenv ASAN_OPTIONS allow_user_segv_handler=true
বিল্ড, এডিবি সিঙ্ক, ফাস্টবুট ফ্ল্যাশ বুট এবং রিবুট।
মোড়ানো সম্পত্তি ব্যবহার করুন
পূর্ববর্তী বিভাগে পদ্ধতিটি সিস্টেমের প্রতিটি অ্যাপে (আসলে, জাইগোট প্রক্রিয়ার প্রতিটি বংশধরে) ASan-কে রাখে। ASan এর সাথে শুধুমাত্র একটি (বা একাধিক) অ্যাপ চালানো সম্ভব, ধীরগতির অ্যাপ স্টার্টআপের জন্য কিছু মেমরি ওভারহেড ট্রেড করা।
এটি wrap.
সম্পত্তি নিম্নলিখিত উদাহরণটি ASan-এর অধীনে Gmail অ্যাপ চালায়:
adb root
adb shell setenforce 0 # disable SELinux
adb shell setprop wrap.com.google.android.gm "asanwrapper"
এই প্রেক্ষাপটে, asanwrapper
/system/bin/app_process
থেকে /system/bin/asan/app_process
এ পুনর্লিখন করে, যা ASan দিয়ে তৈরি। এটি ডায়নামিক লাইব্রেরি অনুসন্ধান পথের শুরুতে /system/lib/asan
যোগ করে। এইভাবে asanwrapper
দিয়ে চলার সময় /system/lib/asan
থেকে আসান-ইনস্ট্রুমেন্টেড লাইব্রেরিগুলিকে /system/lib
এর সাধারণ লাইব্রেরির থেকে পছন্দ করা হয়।
যদি একটি বাগ পাওয়া যায়, অ্যাপটি ক্র্যাশ হয়ে যায় এবং প্রতিবেদনটি লগে মুদ্রিত হয়।
SANITIZE_TARGET
অ্যান্ড্রয়েড 7.0 এবং উচ্চতর ASan-এর সাথে একযোগে সম্পূর্ণ অ্যান্ড্রয়েড প্ল্যাটফর্ম তৈরি করার জন্য সমর্থন অন্তর্ভুক্ত করে। (আপনি যদি অ্যান্ড্রয়েড 9 এর চেয়ে বেশি রিলিজ তৈরি করেন তবে HWASan একটি ভাল পছন্দ।)
একই বিল্ড ট্রিতে নিম্নলিখিত কমান্ডগুলি চালান।
make -j42
SANITIZE_TARGET=address make -j42
এই মোডে, userdata.img
অতিরিক্ত লাইব্রেরি রয়েছে এবং ডিভাইসে ফ্ল্যাশ করা আবশ্যক। নিম্নলিখিত কমান্ড লাইন ব্যবহার করুন:
fastboot flash userdata && fastboot flashall
এটি শেয়ার্ড লাইব্রেরির দুটি সেট তৈরি করে: /system/lib
এ স্বাভাবিক (প্রথম মেক ইনভোকেশন), এবং ASan-ইনস্ট্রুমেন্টেড /data/asan/lib
(দ্বিতীয় মেক ইনভোকেশন)। দ্বিতীয় বিল্ডের এক্সিকিউটেবলগুলি প্রথম বিল্ড থেকে ওভাররাইট করে। ASan-ইনস্ট্রুমেন্টেড এক্সিকিউটেবলরা PT_INTERP
এ /system/bin/linker_asan
ব্যবহারের মাধ্যমে /system/lib
lib-এর আগে /data/asan/lib
অন্তর্ভুক্ত করে একটি ভিন্ন লাইব্রেরি অনুসন্ধানের পথ পায়।
$SANITIZE_TARGET
মান পরিবর্তিত হলে বিল্ড সিস্টেম ক্লোবার অন্তর্বর্তী অবজেক্ট ডিরেক্টরি তৈরি করে। এটি /system/lib
এর অধীনে ইনস্টল করা বাইনারিগুলি সংরক্ষণ করার সময় সমস্ত লক্ষ্যগুলির পুনর্নির্মাণে বাধ্য করে।
কিছু লক্ষ্য ASan দিয়ে তৈরি করা যাবে না:
- স্ট্যাটালি লিঙ্ক এক্সিকিউটেবল
-
LOCAL_CLANG:=false
লক্ষ্য -
LOCAL_SANITIZE:=false
SANITIZE_TARGET=address
জন্য ASN'd নয়
এই ধরনের এক্সিকিউটেবলগুলি SANITIZE_TARGET
বিল্ডে এড়িয়ে যায়, এবং প্রথম মেক ইনভোকেশনের সংস্করণটি /system/bin
এ রেখে দেওয়া হয়।
এই ধরনের লাইব্রেরি ASan ছাড়াই নির্মিত হয়। তারা স্ট্যাটিক লাইব্রেরি থেকে কিছু ASan কোড ধারণ করতে পারে যা তারা নির্ভর করে।