לדלג לתוכן

10.3 - מרחבי שמות וזהות יחסית - פתרון

פתרון נקודות המבט

פתרון ראשון - טווח אחד

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

println!("uid map:\n{}", fs::read_to_string("/proc/self/uid_map")?);
println!("gid map:\n{}", fs::read_to_string("/proc/self/gid_map")?);

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

פתרון שני - רשת נפרדת וקבצים משותפים

החליפו את דגלי ההפרדה בביטוי הבא.

libc::CLONE_NEWUSER | libc::CLONE_NEWUTS | libc::CLONE_NEWNET

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

let links = Command::new("ip").args(["link", "show"]).status()?;
let routes = Command::new("ip").args(["route", "show"]).status()?;
assert!(links.success() && routes.success());

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

פתרון שלישי - התהליך הראשון אינו עובד רגיל

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

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

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