9.2 - העברת משאבים וזיכרון בין תהליכים - פתרון
פתרון בעלות על מתאר שהתקבל¶
פתרון ראשון - תכונת המתאר והפניה משותפת¶
הקטע הבא מצטרף לפונקציה הראשית לאחר קבלת received.
let descriptor_flags = unsafe { libc::fcntl(received.as_raw_fd(), libc::F_GETFD) };
if descriptor_flags < 0 { return Err(io::Error::last_os_error()); }
assert_ne!(descriptor_flags & libc::FD_CLOEXEC, 0);
הקריאה לאחר סגירת original כבר מופיעה בדוגמת ההרצאה. היא מצליחה משום שהמקבל מחזיק הפניה משלו לאובייקט הקרנלי. התוכן לא הועתק כולו בתוך הודעת הבקרה; הקרנל העביר אפשרות גישה לאותו משאב. לכן שינוי מותר של תוכן משותף היה יכול להיראות לשני הצדדים, אילולא החתימות שהוספנו.
פתרון שני - שגיאה אחרי רכישת בעלות¶
בפונקציה השולחת החליפו את התג באות אחרת, למשל X, והשאירו את דרישת המקבל לתג F. הקרנל עדיין מוסר את המתאר, ולכן המקבל צריך לעטוף אותו לפני שהוא מחזיר שגיאת פרוטוקול. החזרת שגיאה מיד לאחר בדיקת התג הייתה משאירה מספר חדש בטבלת התהליך בלי בעלים שסוגר אותו.
הפונקציה הבאה סופרת מתארים דרך ממשק התהליך בלינוקס. הקריאה עצמה פותחת מתאר לסריקת התיקייה, אך שתי המדידות נעשות באותו אופן ולכן אפשר להשוות אותן בניסוי יחיד ללא תהליכונים שפותחים משאבים ברקע.
fn descriptor_count() -> std::io::Result<usize> {
let entries = std::fs::read_dir("/proc/self/fd")?;
let mut count = 0;
for entry in entries { entry?; count += 1; }
Ok(count)
}
שמרו את הסוקט ואת הקובץ המקורי מחוץ ללולאה, מדדו לפני הלולאה, ובכל סיבוב שלחו את ההודעה הפגומה ודרשו ש־receive_fd יחזיר שגיאה. לאחר אלף סיבובים מדדו שוב ודרשו שוויון. הבדיקה אינה מוכיחה שאין דליפה בכל מסלול אפשרי, אבל היא מכסה במדויק את מסלול דחיית התג לאחר מסירת זכויות.
פתרון שלישי - תוכן חתום¶
הקטע הבא פועל על original אחרי הוספת החתימות. הוא בודק את קוד השגיאה של לינוקס ולא רק הודעת טקסט שתלויה בשפה של המערכת.
let write_error = original.write_all(b"x").unwrap_err();
assert_eq!(write_error.raw_os_error(), Some(libc::EPERM));
let resize_error = original.set_len(1).unwrap_err();
assert_eq!(resize_error.raw_os_error(), Some(libc::EPERM));
חתימת הכתיבה מונעת שינוי תוכן בדרכים המכוסות בחוזה שלה, וחתימות הגדילה והקיצור מגבילות שינוי גודל. הדבר מאפשר למקבל לבסס פענוח על תוכן שאינו משתנה בזמן הבדיקה. עדיין צריך לבדוק אורך, גרסה, מבנה וקשר לזהות השולח. קובץ קבוע יכול להכיל מידע שגוי או פגום בדיוק כמו קובץ משתנה.
אם מקבלים מתאר מסוג אחר, הקריאה לבדיקת חתימות יכולה להיכשל. במקרה כזה דוחים את המשאב וסוגרים אותו באמצעות הבעלות שכבר נרכשה. אין לפרש חוסר יכולת לקרוא חתימות כאילו כל ההגבלות הדרושות כבר קיימות.