לדלג לתוכן

6.2 הsyscall מבפנים תרגול

תרגול - הsyscall מבפנים

תרגיל 1 - מעקב אחרי syscall-ים

השתמשו ב-strace כדי לענות על השאלות הבאות:

  1. כתבו תוכנית פשוטה בC שקוראת ל-getpid() ומדפיסה את התוצאה עם printf.
  2. הריצו אותה עם strace. כמה syscall-ים מתבצעים לפני ש-main בכלל מתחיל? (רמז: סופרים את הsyscall-ים שמופיעים לפני הsyscall של write/getpid)
  3. אילו syscall-ים קשורים לטעינת ספריות משותפות? (רמז: חפשו openat ו-mmap)
  4. הריצו שוב עם strace -c כדי לקבל סיכום סטטיסטי. מהו הsyscall שנקרא הכי הרבה פעמים?

תרגיל 2 - הconvention של האוגרים

כתבו תוכנית באסמבלי (x86-64) שמבצעת את הsyscall של write ישירות - בלי libc. התוכנית צריכה:

  1. לכתוב את המחרוזת "Hello from syscall!\n" ל-stdout
  2. לצאת עם exit code 0

רמזים:
- הsyscall של write הוא מספר 1: rax=1, rdi=fd, rsi=buf, rdx=count
- הsyscall של exit הוא מספר 60: rax=60, rdi=exit_code
- השתמשו בsection .data למחרוזת ו-section .text לקוד
- נקודת הכניסה: _start (לא main, כי אין libc)

קימפול:

nasm -f elf64 program.asm -o program.o
ld program.o -o program


תרגיל 3 - copy_from_user (שאלה תיאורטית)

נניח שמישהו כתב syscall חדש בקרנל, אבל במקום להשתמש ב-copy_from_user הוא פשוט עשה dereference ישיר לפוינטר מיוזר מוד:

SYSCALL_DEFINE2(bad_syscall, const char __user *, buf, size_t, len)
{
    // שגוי! גישה ישירה לפוינטר מיוזר מוד
    char first_byte = buf[0];
    printk(KERN_INFO "first byte: %c\n", first_byte);
    return 0;
}
  1. תארו שני תרחישים שבהם הקוד הזה יגרום לבעיות (רמז: מה אם buf מצביע לכתובת קרנלית? מה אם buf מצביע לכתובת לא ממופה?)
  2. איך copy_from_user מונעת את הבעיות האלה?

תרגיל 4 - מעקב עם strace על פעולות קבצים

כתבו תוכנית בC שעושה את הדברים הבאים:
1. פותחת קובץ חדש לכתיבה
2. כותבת אליו שורה אחת
3. סוגרת את הקובץ
4. פותחת אותו מחדש לקריאה
5. קוראת ממנו את התוכן
6. סוגרת ומוחקת את הקובץ

הריצו עם strace ועקבו אחרי הsyscall-ים. לכל שורת strace, כתבו מהי שורת הC שגרמה לה. שימו לב ל:
- מה ההבדל בין הdescriptor שחוזר מopenat בפתיחה הראשונה לשניה?
- האם write ו-read מחזירים את הערך שציפיתם?


תרגיל 5 - שאלה תיאורטית

הסבירו: למה הconvention של הsyscall-ים בx86-64 משתמש ב-r10 לפרמטר הרביעי ולא ב-rcx כמו בconvention הרגיל של קריאות פונקציה? מה היה קורה אם libc היה שם את הפרמטר הרביעי ב-rcx לפני פקודת ה-syscall?