ไม่สามารถทำได้เนื่องจากตารางการเรียกระบบ (เรียกว่าsys_call_table
) เป็นอาร์เรย์ขนาดคงที่ และขนาดจะถูกกำหนดในเวลารวบรวมโดยจำนวน syscalls ที่ลงทะเบียน นี่หมายความว่าไม่มีที่ว่างสำหรับอีกห้องหนึ่ง
คุณสามารถตรวจสอบการนำไปใช้งานสำหรับสถาปัตยกรรม x86 ในarch/x86/kernel/syscall_64.c
ไฟล์ที่sys_call_table
กำหนดไว้ __NR_syscall_max+1
ขนาดของมันเป็นสิ่ง __NR_syscall_max
ถูกกำหนดarch/x86/kernel/asm-offsets_64.c
เป็นsizeof(syscalls) - 1
(เป็นจำนวน syscall ล่าสุด) โดยที่syscall
เป็นตารางที่มี syscalls ทั้งหมด
วิธีแก้ปัญหาที่เป็นไปได้วิธีหนึ่งคือการนำบางส่วนที่มีอยู่เดิม (หรือเลิกใช้แล้วหากสถาปัตยกรรมของคุณมีอยู่ให้ดูsys_setaltroot
ตัวอย่าง) หมายเลข syscall กับคุณเนื่องจากจะไม่ต้องใช้พื้นที่ในหน่วยความจำมากขึ้น สถาปัตยกรรมบางอย่างอาจมีรูในตาราง syscall (เช่น 64 บิตรุ่น x86) ดังนั้นคุณจึงสามารถใช้สิ่งนี้ได้เช่นกัน
คุณสามารถใช้เทคนิคนี้หากคุณกำลังพัฒนา syscall ใหม่และเพียงต้องการหลีกเลี่ยงการรีบูตขณะทดสอบ คุณจะต้องกำหนดการโทรระบบใหม่ค้นหารายการที่มีอยู่ในตาราง syscall แล้วแทนที่จากโมดูลของคุณ
การทำสิ่งนี้จากโมดูลเคอร์เนลไม่ใช่เรื่องเล็กเพราะเคอร์เนลไม่ได้ส่งออกsys_call_table
ไปยังโมดูลในเวอร์ชัน 2.6 (เวอร์ชันเคอร์เนลสุดท้ายที่มีสัญลักษณ์นี้ถูกเอ็กซ์พอร์ตอยู่2.5.41
)
วิธีหนึ่งในการแก้ไขปัญหานี้คือเปลี่ยนเคอร์เนลของคุณเพื่อส่งออกsys_call_table
สัญลักษณ์ไปยังโมดูล ในการทำเช่นนี้คุณจะต้องเพิ่มสองบรรทัดต่อไปนี้ลงในkernel/kallsyms.c
( อย่าทำสิ่งนี้บนเครื่องผลิต ):
extern void *sys_call_table;
EXPORT_SYMBOL(sys_call_table);
อีกเทคนิคหนึ่งคือการหาตาราง syscall แบบไดนามิก คุณวนหน่วยความจำเคอร์เนลซ้ำแต่ละคำเปรียบเทียบกับตัวชี้ไปยังฟังก์ชันการเรียกระบบที่รู้จัก เนื่องจากคุณรู้ค่าออฟเซ็ตของ syscall นี้ในตารางคุณสามารถคำนวณที่อยู่เริ่มต้นของตารางได้