באג בליבת לינוקס, בקוד שמטפל בפתיחת חיבורי TCP מעל IPv4, גורם לכך שאזור זיכרון משוחרר בזמן שרכיב אחר בליבה עדיין קורא ממנו. התוצאה היא שימוש בזיכרון אחרי שחרורו, מצב שבו התוכנה ממשיכה לעבוד עם אזור שהיא כבר החזירה למערכת. הציון שקיבלה הרשומה הוא 9.8 מתוך 10, והתיקון כבר נכנס לענפי התחזוקה של הליבה.

מה החולשה?

כדי להבין את הבאג צריך רגע אחד מתוך פתיחת חיבור. כששרת מקבל בקשת חיבור, הוא אינו פותח מיד חיבור מלא, אלא מחזיק רשומה זמנית וקטנה שמתארת את הבקשה, ועונה בתשובת אישור. רק כשהצד השני משיב, נבנית מהרשומה הזמנית רשומת חיבור אמיתית. בין שני הרגעים האלה יש חלון.

לפי התיאור, בשלב שבו הרשומה הזמנית הופכת לחיבור אמיתי, מצביע לנתוני אפשרויות ה-IP של הבקשה עובר לבעלות החיבור החדש בלי שמישהו מעתיק את הנתונים עצמם. שני הרכיבים מחזיקים כעת את אותו אזור. אם במקביל, על מעבד אחר, מגיעה בקשת חיבור חוזרת על אותה רשומה זמנית, הקוד שבונה את תשובת האישור ניגש לאותם נתונים. הוא עושה זאת תוך הסתמכות על מנגנון סנכרון שמבטיח שקורא לא יראה נתונים שנעלמו תחת ידיו, אבל השחרור בפועל נעשה בקריאה ישירה שאינה מכבדת את המנגנון הזה. החיבור החדש יכול להשתחרר בעוד התשובה נבנית.

שם המנגנון הוא RCU, ושיטת העבודה שלו היא שהשחרור ממתין עד שכל מי שקרא סיים. התיקון בדיוק שם: שתי נקודות שחרור בקוד הוחלפו בגרסה שממתינה, במקום בשחרור מיידי. התיאור מוסיף שהבעיה החריפה מאז שינוי בליבה שהעביר את הטיפול ברשומות הזמניות לעבוד בלי מנעול גלובלי, כלומר מאז שבאמת שני מעבדים יכולים לעסוק באותה רשומה בבת אחת.

יש גם חצי שני לבאג, בנתיב שמעביר רשומת בקשה בין מאזינים. שם נוצר שיבוט של הרשומה הזמנית, השיבוט והמקור חולקים את אותם נתונים, ושחרור של אחד מהם מותיר את האחר עם מצביע לאזור משוחרר. החצי הזה פעיל רק כשהעברת הרשומות מופעלת בתצורה.

מי מושפע?

הרשומה אינה נוקבת בטווח גרסאות, וזו מגבלה שכדאי לדעת עליה: רשומות של ליבת לינוקס מתפרסמות לרוב בלי רשימת גרסאות, והדרך לדעת אם הליבה שלכם בטווח היא דרך מעקב האבטחה של ההפצה שאתם מריצים או דרך ארבעת העדכונים בענפי התחזוקה שמופיעים במקורות הרשומה.

מה שכן אפשר לומר הוא מי נמצא בנתיב הקוד. מדובר בצד שמקבל חיבורי TCP מעל IPv4, כלומר בשרתים שמאזינים לרשת, ולא במכשיר שרק יוצר חיבורים יוצאים. התיאור מציין במפורש ש-IPv6 אינו חשוף לחצי הראשון של הבאג, מפני שהנתיב המקביל שם מעתיק את הנתונים במקום להעביר בעלות עליהם. בישראל זה אומר שרתים, לא טלפונים ולא מחשבים ביתיים, אף שליבת לינוקס נמצאת גם שם.

צריך לומר מה שהציון אינו אומר. 9.8 הוא ציון של חולשה שאפשר להפעיל מהרשת בלי הרשאות ובלי שמשתמש יעשה דבר, וזה נכון לנתיב, אבל מי שרוצה לנצל אותה בפועל צריך לנצח מצב של תחרות בין שני מעבדים על אותה רשומה בחלון זמן קצר. זה מרחיק את הבאג מניצול פשוט ואינו מבטל אותו.

האם מנוצלת בפועל?

לא פורסם דיווח על ניצול של הבאג הזה בשטח. הוא גם אינו נמנה בקטלוג ה-KEV של CISA, סוכנות הסייבר האמריקאית, שמרכז את החולשות שיש עליהן ראיות לשימוש של תוקפים.

כדאי לקרוא את זה נכון. אין ראיה לניצול, וזה אינו אותו דבר כמו ראיה לכך שאין. בבאג שתלוי בניצחון במצב תחרות, ניצול מוצלח גם אינו משאיר סימן ברור בצד שהותקף.

מה עושים?

1. התקינו את עדכוני הליבה של ההפצה שאתם מריצים. בדביאן ובאובונטו זה apt update ואחריו apt upgrade, במשפחת רד האט dnf update. התיקון כאן הוא בליבה עצמה.
2. אתחלו את המכונה אחרי העדכון. ליבה חדשה אינה נכנסת לתוקף בלי אתחול, וזה השלב שנשכח בדיוק בשרתים שלא נוח לאתחל. בדקו עם uname -r שהגרסה שרצה היא זו שהתקנתם.
3. אם אתם מריצים שרתים שמאזינים לרשת, בדקו אם הפעלתם את העברת רשומות הבקשה בין מאזינים, עם sysctl net.ipv4.tcp_migrate_req. ערך 1 אומר שגם החצי השני של הבאג רלוונטי אצלכם.
4. אם אתם מתחזקים ליבה משלכם, ארבעת העדכונים בענפי התחזוקה מופיעים בקישורים שבתיבת המידע הטכני למטה, ואפשר להשוות אותם מול הענף שאתם בונים ממנו.