
يقوم بتلقيح (Fuzzing) تطبيقات وحدات المعالجة المركزية (CPU) عبر توليد مدخلات اختبار من وكلاء برمجيين، ثم ينفّذها على عتاد حقيقي لكشف عيوب المعمارية الدقيقة والأخطاء الموثّقة (Errata).
SiliFuzz هو نظام يكتشف عيوب وحدة المعالجة المركزية (CPU) عبر اختبار الفازينج (fuzzing) للبروكسيات البرمجية، مثل محاكيات وحدة المعالجة المركزية أو مفككات التجميع (disassemblers)، ثم تنفيذ مدخلات الاختبار المتراكمة (المعروفة باسم corpus) على وحدات المعالجة المركزية الفعلية على نطاق واسع. SiliFuzz هو عمل قيد التطوير، يُرجى الرجوع إلى الورقة البحثية للحصول على التفاصيل.
الفازينج (Fuzzing) هو أسلوب لاختبار هدف (تطبيق أو واجهة برمجية API) بعدد كبير من مدخلات الاختبار المُولَّدة أثناء التنفيذ. الهدف هو جعل هذه المدخلات مثيرة للاهتمام ومتنوعة قدر الإمكان من أجل تحفيز الحالات الطرفية. بعبارة أخرى، يهدف الفازينج إلى تعظيم التغطية البرمجية المجمّعة. التغطية البرمجية قد يكون لها معانٍ مختلفة، مثل أي الكتل الأساسية يتم تنفيذها أو أي المسارات يتم اتخاذها في البرنامج.
لأغراض SiliFuzz، البروكسي هو أي نظام برمجي أو عتادي يتصرف بشكل مشابه لبعض جوانب وحدة المعالجة المركزية المستهدفة. على سبيل المثال، محاكي وحدة معالجة مركزية أو مفكك تجميع. نحتاج إلى بروكسي عندما لا نستطيع جمع معلومات التغطية مباشرة من الهدف.
من خلال تطبيق تقنيات الفازينج على بروكسي، يمكننا توليد سلسلة من مدخلات الاختبار (corpus) التي تُنتج سلوكًا مثيرًا للاهتمام في البروكسي. افتراضنا الأساسي هو أن هذا يُترجم إلى سلوك مثير للاهتمام بشكل مماثل في الهدف. اقرأ المزيد في المستندات.
مجموعة المدخلات المستخدمة لاختبار الهدف تُعرف باسم corpus.
يحتوي corpus كبير بشكل معقول على ملايين المدخلات وعادةً ما يتم تقسيمه إلى أجزاء غير متداخلة متعددة تسمى shards.
تصف لقطة SiliFuzz تسلسلًا قصيرًا من تعليمات وحدة المعالجة المركزية بالإضافة إلى حالة أولية لسجلات وحدة المعالجة المركزية والذاكرة لتنفيذ هذا التسلسل بشكل حتمي. تحتوي اللقطة النموذجية على أقل من 100 بايت من التعليمات البرمجية وتعمل في غضون ميكروثوانٍ، ولكنها يمكن أن تكون كبيرة بشكل تعسفي. يتم تخزين اللقطات كبروتوكولات مخازن silifuzz.proto.Snapshot.
يتم إنشاء اللقطات عادةً من المدخلات المُولَّدة بواسطة محرك فازينج. لأغراض اختبار وحدة المعالجة المركزية، يتم تصفية هذه المدخلات لإزالة جميع اللقطات غير الحتمية. اقرأ المزيد في المستندات.
تصف الحالة النهائية محتويات السجلات والذاكرة المتوقع وجودها في نهاية تنفيذ اللقطة. إذا تم تنفيذ اللقطة بشكل مختلف على ميكرومعماريات مختلفة لوحدة المعالجة المركزية، فسيكون لها حالات نهائية متوقعة متعددة.
Snap هو تمثيل في الذاكرة للقطة (Snapshot) يمكن تحميله وتنفيذه بسهولة بواسطة Runner. عادةً ما يتم تحميل Snaps من القرص بواسطة قارئ runner. تنسيق Snap على القرص هو في الأساس نفس تنسيق الذاكرة باستثناء أن المؤشرات الأصلية تُستبدل بالإزاحات. انظر هذا الملف الرأسي للحصول على التفاصيل. غالبًا ما يُشار إلى هذا التنسيق باسم relocatable. يحتوي كل Snap على حالة نهائية متوقعة واحدة بالضبط، أي أن Snaps خاصة بميكرومعمارية محددة. اقرأ المزيد في المستندات.
Runner هو ملف ثنائي لاختبار نواة معالج واحدة (CPU core). يستهلك runner جزءًا من corpus، وينفذ بشكل متكرر Snaps عشوائية فيه ويتحقق من الوصول إلى الحالة النهائية المتوقعة. Runner هو عملية أحادية الخيط.
المنسق هو عملية تقود عدة runners. في الإعداد النموذجي، سيقوم المنسق باستمرار بتنفيذ runner واحد لكل نواة معالج منطقية، وتجميع أي إخفاقات تُنتجها عمليات runner الفردية والإبلاغ عنها.
انظر هذا الملف للحصول على قائمة الميكرومعماريات المدعومة.
يعمل SiliFuzz على أنظمة Linux x86_64 و aarch64. تم اختباره مع إصدارات نواة Linux 5.x و 6.x. لا يوجد ضمان بأنه متوافق مع إصدارات النواة الأقدم. يجب إيقاف تشغيل ABI القديم vsyscall لتجنب النتائج الإيجابية الخاطئة.
قائمة غير شاملة للأخطاء والعيوب التي وجدها SiliFuzz.
الخطأ البرمجي المنطقي هو سلوك غير صالح لوحدة المعالجة المركزية متأصل في ميكرومعمارية أو خطوة إنتاج (stepping) معينة. حدد SiliFuzz الأخطاء البرمجية التالية:
العيب (الكهربائي) هو سلوك غير صالح لوحدة المعالجة المركزية يحدث فقط على شريحة واحدة أو عدة شرائح. وجد SiliFuzz العيوب التالية التي وصفناها في الورقة البحثية:
git clone https://github.com/google/silifuzz.git && cd silifuzz
SILIFUZZ_SRC_DIR=`pwd`
./install_build_dependencies.sh # يعمل حاليًا لأحدث إصدار من Ubuntu فقط.
bazel build -c opt @silifuzz//tools:{snap_corpus_tool,fuzz_filter_tool,snap_tool,silifuzz_platform_id,simple_fix_tool_main} \
@silifuzz//runner:reading_runner_main_nolibc \
@silifuzz//orchestrator:silifuzz_orchestrator_main
SILIFUZZ_BIN_DIR=`pwd`/bazel-bin
cd "${SILIFUZZ_BIN_DIR}"
ملاحظة: يمكنك استخدام حاوية Docker لتجنب تلويث النظام المضيف: docker run -it --tty --security-opt seccomp=unconfined --mount type=bind,source=${SILIFUZZ_SRC_DIR},target=/app ubuntu:noble /bin/bash -c "cd /app && ./install_build_dependencies.sh && bazel build ... && bazel test ..."
لـ Bazel، استخدم الأوامر التالية.
cd "${SILIFUZZ_SRC_DIR}"
COV_FLAGS_FILE="$(bazel info output_base)/external/fuzztest+/centipede/clang-flags.txt"
bazel build -c opt --copt=-UNDEBUG --dynamic_mode=off \
--per_file_copt=unicorn/.*@$(xargs < "${COV_FLAGS_FILE}" |sed -e 's/,/\\,/g' -e 's/ /,/g') @//proxies:unicorn_x86_64
bazel build -c opt @fuzztest//centipede:centipede
mkdir -p /tmp/wd
# قم بفازينج بروكسي Unicorn تحت Centipede 1000 مرة مع توازي 30.
"${SILIFUZZ_BIN_DIR}/external/fuzztest+/centipede/centipede" \
--binary="${SILIFUZZ_BIN_DIR}/proxies/unicorn_x86_64" \
--workdir=/tmp/wd \
-j=30 --num_runs=1000
ملاحظة: يُرجى الرجوع إلى وثائق Centipede حول كيفية تشغيل محرك الفازينج بكفاءة.
أداة المساعدة هذه للتحقق من أن الجهاز الذي تعمل عليه مدعوم.
$ ${SILIFUZZ_BIN_DIR}/tools/silifuzz_platform_id --short
intel-skylake
ملاحظة: لا يأخذ منطق اكتشاف وحدة المعالجة المركزية في SiliFuzz في الاعتبار بعض المتغيرات المكتبية (desktop) من وحدات المعالجة المركزية المدعومة بخلاف ذلك. ستبلغ الأداة بـ "Unsupported platform" في مثل هذه الحالات.