קובץ מודל בגודל 65 בתים עלול להביא את מנוע ההסקה הפופולרי Llama CPP לעצירה פתאומית. המטען הקטן מפעיל חלוקה באפס בתוך ה-parser, מה שגורם לקריסת SIGFPE.
למה הקריסה הזו משנה
מה השתבש
ה-parser קורא את מטא-הנתונים (metadata) של המודל לתוך מבני C++ ובודק שכל ממד של הטנזור (tensor dimension) הוא "אינו שלילי". המספר אפס מקיים את התנאי הזה, ולכן הבדיקה עוברת. שורת הקוד הבאה משתמשת בממד כמחלק בחישוב שמניח שהערך הוא חיובי. כאשר הממד הוא אפס, החלוקה מפעילה חריגת נקודה צפה (floating-point exception - SIGFPE) ומפסיקה את פעולת התוכנית.
האימות כיסה רק מחצית מהאינווריאנט (invariant) הנדרש: הוא חסם ערכים שליליים אך התעלם מאפס, שהוא מסוכן באותה מידה עבור החישובים האריתמטיים הבאים.
מה מפתחים צריכים לעשות
- התייחסו לקובצי מודל כאל קבצים בינאריים. טעינת מודל מבצעת parsing של בתים גולמיים לתוך מבני זיכרון, גבול קלאסי שבו נתונים לא מאומתים עלולים להפיל את התהליך או לגרום לנזק חמור יותר.
- הימנעו מבדיקות חלקיות. תנאי המכסה רק חלק מהאינווריאנט הנדרש מעניק תחושת ביטחון שגויה. במקרה זה, "אינו שלילי" לא הספיק; הקוד היה זקוק ל-"חיובי".
- פקחו על הנחות יסוד לאחר כל בדיקה. כאשר מופיעה בדיקת גבולות (bounds test), ודאו שהקוד הבא אינו מסתמך על תכונה מחמירה יותר.
- השתמשו בכלי fuzzing. המחבר גילה את הבאג באמצעות הרצת libFuzzer עם AddressSanitizer, שמבצע מוטציות לקלטים ומסמן פעולות לא חוקיות כמו חלוקה באפס.
כיצד התיקון יושם
התיקון מוסיף הגנה (guard) שדלגת על חישוב ה-overflow כאשר ממד שווה לאפס. תנאי קטן זה שומר על תמיכה בטנזורים לגיטימיים בגודל אפס — המשמשים בגרסאות מסוימות של מודלים עבור תכונות אופציונליות — תוך ביטול נתיב הקריסה.
שורה תחתונה: קובץ בודד בגודל 65 בתים יכול להשבית מנוע הסקה הנמצא בשימוש נרחב; אימות יסודי ו-fuzzing שיטתי שומרים על טעוני מודלים (model loaders) בטוחים.
מקור: https://dev.to/harrisonsec/your-model-file-is-untrusted-input-1eap
