การเพิ่มการเรียกระบบใหม่ไปยัง Linux 3.2.x ด้วยโมดูลเคอร์เนลที่โหลดได้ [ปิด]


11

ฉันต้องการเพิ่มการเรียกของระบบใหม่ใน linux kernel 3.2.x แต่เป็นโมดูลเคอร์เนลที่สามารถโหลดได้ (เพราะฉันไม่ต้องการคอมไพล์เคอร์เนลซ้ำแล้วซ้ำอีก)

ฉันอ่านโพสต์มากมายบนอินเทอร์เน็ตและใน SO และบางแห่งอ้างว่าการใช้การเรียกระบบเนื่องจากโมดูลที่โหลดได้นั้นเป็นไปไม่ได้ในขณะที่คนอื่นบอกว่าเป็นไปได้

มันคืออะไร จะทำอย่างไรถ้าเป็นไปได้?


คำถามนี้ไม่ได้อยู่ที่นี่: Unix & Linuxเกี่ยวกับการใช้งานและการจัดการไม่ใช่เกี่ยวกับการเขียนโปรแกรม คุณควรถามในกองมากเกิน อย่าคลุมเครือ: เชื่อมโยงไปยังโพสต์ที่คุณพบในStack Overflowและอธิบายสิ่งที่คุณพบว่าไม่สามารถสรุปได้หรือขัดแย้งกัน
Gilles 'หยุดความชั่วร้าย'

2
ฉันเชื่อว่าคำถามนี้เกี่ยวข้องกับ Linux เป็น OS มากกว่าการเขียนโปรแกรมเอง มันค่อนข้างสำคัญที่จะต้องรู้ว่าอะไรคือความเป็นไปได้ในการขยายขีดความสามารถของระบบของเราและขีด จำกัด ของมัน ตัวอย่างเช่นนี้ทำให้คุณเข้าใจว่าเหตุใดคุณลักษณะบางอย่างจึงไม่สามารถนำไปใช้เป็นโมดูลที่โหลดได้และต้องการการแก้ไขเคอร์เนล การรู้ว่าทำไมจึงเป็นเช่นนี้อาจทำให้คุณมีความคิดเกี่ยวกับความปลอดภัยและการใช้งานเคอร์เนลที่ผู้พัฒนาต้องทำ คำถามนั้นจะมีมากขึ้นในหัวข้อถ้า OP จะถามเฉพาะในกรณีที่เป็นไปได้และทำไมถึงไม่ใช้วิธีนี้
Krzysztof Adamski

1
มีการอภิปราย <stroke> เปลวไฟ </stroke> จำนวนมากในลิสต์การส่งเมลเคอร์เนลตัวอย่างเช่น reiserfs ใช้ syscalls ของตัวเองซึ่งไม่ได้เป็นที่ชื่นชอบของนักพัฒนาหลักบางรายรวมถึง Linus ในกรณีของคุณฉันจะใช้ioctl()s สำหรับงานพวกมันง่าย ๆ Afaik เหตุผลหลักที่ทำให้สิ่งนี้ยากที่สุดเท่าที่จะเป็นไปได้ว่าจำนวนตึกระฟ้าเป็นสิ่งที่ยากมากและไม่มีใครต้องการความสับสนวุ่นวายในภาพ แต่มีอินเทอร์เฟซเคอร์เนลจำนวนมากเพื่อเข้าถึงฟังก์ชันการทำงานเดียวกันเช่น sysfs, ioctls หรือเช่นนั้น
peterh - Reinstate Monica

คำตอบ:


14

ไม่สามารถทำได้เนื่องจากตารางการเรียกระบบ (เรียกว่า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 นี้ในตารางคุณสามารถคำนวณที่อยู่เริ่มต้นของตารางได้


1

น่าเสียดายที่คุณไม่สามารถเพิ่มการเรียกระบบไปยังเคอร์เนลเป็นโมดูลที่โหลดได้ คุณต้องใช้ความเจ็บปวดในการรวบรวมเคอร์เนลทุกครั้งที่คุณเพิ่มการเรียกระบบใหม่

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.