การเรียกของระบบรองรับการรันเคอร์เนล


9

มีวิธีรับจำนวนหรือรายการการโทรของระบบที่รองรับโดย Linux Kernel หรือไม่? ดังนั้นฉันต้องการหาวิธี 'อ่าน' ตาราง syscall ของเคอร์เนลที่กำลังทำงานอยู่

คำตอบ:


15

แฟ้ม/proc/kallsymsรายชื่อทั้งหมดของสัญลักษณ์ของเคอร์เนลเรียกใช้ sys_โดยการประชุมสายระบบที่มีชื่อขึ้นต้นด้วย บนระบบ 64 บิตระบบเรียกร้องให้โปรแกรม 32 sys32_บิตที่มีชื่อขึ้นต้นด้วย พูดอย่างเคร่งครัดรายการนี้เคอร์เนลฟังก์ชันภายในไม่เรียกระบบ แต่ผมคิดว่าการติดต่อไม่ทำงาน (ทุกสายระบบเรียกใช้ฟังก์ชันเคอร์เนลภายในงานที่ต้องทำและฉันคิดว่าชื่ออยู่เสมอชื่อเรียกระบบที่มีsys_ใช้ได้ )

</proc/kallsyms sed -n 's/.* sys_//p'

นี่เป็นข้อมูลที่ไม่มีประโยชน์เนื่องจากการโทรของระบบเปลี่ยนไปช้ามาก ส่วนประกอบเสริมให้การทำงานในแง่ของการเรียกใช้ระบบที่มีอยู่โดยใช้คุณสมบัติทั่วไปเช่นอุปกรณ์ (ด้วยioctlเมื่อreadและwriteไม่ตัดมัน) ระบบไฟล์ซ็อกเก็ต ฯลฯ การกำหนดรายการ syscalls ที่รองรับจะไม่บอกอะไรเกี่ยวกับคุณสมบัติ ที่ระบบรองรับ ชื่อฟังก์ชั่นภายในอื่น ๆ จะไม่ช่วยอย่างใดอย่างหนึ่งเนื่องจากการเปลี่ยนแปลงเหล่านี้อย่างรวดเร็ว: ชื่อของฟังก์ชั่นที่ใช้คุณสมบัติบางอย่างในหนึ่งรุ่นเคอร์เนลอาจมีการเปลี่ยนแปลงในรุ่นต่อไป


+1 ตอนนี้นั่นคือสิ่งที่ฉันหมายถึงเมื่อฉันกล่าวว่า"ฉันจะปล่อยให้คนที่มีประสบการณ์มากกว่าผมตอบคุณ" นอกจากนี้เนื่องจาก/proc/kallsymsสามารถจัดการได้เหมือนกับไฟล์อื่น ๆ มันจึงค่อนข้างใช้งานได้ง่ายในโปรแกรม
John WH Smith

2
@JohnWHS ด้วย "สามารถจัดการได้เหมือนกับไฟล์อื่น ๆ " ... ด้วยข้อแม้ที่อยู่ในระบบที่มีเคอร์เนล ASLR ไฟล์นี้ควรอ่านได้โดย root เท่านั้น
Gilles 'หยุดความชั่วร้าย'

7

TL; DR

ฉันหาทางเลือกใหม่ ๆ เสมอเมื่อเขียนคำตอบนี้ดังนั้นฉันจึงเขียนรายละเอียดเล็กน้อยเกี่ยวกับพวกเขาแต่ละคนและสร้างสถิติ โดยทั่วไปคุณสามารถ:

  • อ่านคำตอบของ Gilles ซึ่งเป็นวิธีที่สะอาดและรวดเร็วในการทำ (ต้องอาศัย/proc)
  • ใช้ทรัพยากรเอกสาร
  • ใช้ไฟล์ส่วนหัว C ของระบบ
  • ใช้ซอร์สโค้ดเคอร์เนลเอง
  • ใช้/sysไดเรกทอรี

หลังจากทำคณิตศาสตร์ฉันแนะนำ (ในทางเลือกของฉัน) โดยใช้/sysระบบไฟล์เนื่องจากดูเหมือนว่าจะให้ผลลัพธ์ที่ดีที่สุดในแง่ของจำนวนการโทรของระบบ คุณอาจกระโดดไปทางขวาในส่วนนั้นหากคุณไม่ต้องการอ่านเกี่ยวกับลูกเล่นอื่น ๆ

การใช้ทรัพยากรเอกสาร

ในขณะที่คุณอาจพลาดบางส่วนคุณสามารถใช้aproposเพื่อแสดงรายการ manpages ทั้งหมดที่อยู่ในส่วนที่ 2 (การเรียกระบบ)

$ apropos -s2 . | awk '{print $1}' | column

ลบออกcolumnหากคุณไม่ต้องการให้เอาต์พุตคอลัมน์แบบแฟนซี

ฉันเพิ่งพบมัน แต่มีหน้าลินุกซ์เกี่ยวกับการโทรของระบบและคุณจะสามารถค้นหาพวกเขาส่วนใหญ่ในนั้น

$ man syscalls

ฉันเจอเว็บไซต์ทั้งสองนี้ซึ่งน่าสนใจ:

การใช้ไฟล์ส่วนหัว

แก้ไข:ตอนนี้เมื่อมาถึงโปรแกรม (หรืออย่างน้อยโดยไม่ต้องอาศัยคุณสมบัติเอกสาร) กำหนดสายระบบที่มีอยู่ฉันกลัวเคอร์เนลไม่เก็บตารางการโทรระบบอย่างน้อยไม่อยู่ภายใต้รูปแบบของ รายการสตริง (ตามที่คุณคาดว่าจะจัดการได้) ในระดับนี้เรากำลังพูดถึงฟังก์ชันที่อยู่และพอยน์เตอร์มากกว่าชื่อฟังก์ชั่น

ฉันเพิ่งเรียกดู/usr/includeไดเรกทอรีของฉันและgrepทำบางสิ่ง: คุณอาจพบว่าไดเรกทอรีต่อไปนี้น่าสนใจ บางส่วนอาจแตกต่างกันไปในเครื่องของคุณขึ้นอยู่กับสถาปัตยกรรมและการกระจายของคุณ แต่ฉันแน่ใจว่าคุณจะสามารถปรับเปลี่ยนได้

  • / usr / รวม / ลินุกซ์
  • / usr / รวม / x86_64-ลินุกซ์ GNU
  • / usr / รวม / SYS
  • / usr / รวม / asm ทั่วไป

เมื่อมองหาคำจำกัดความของฟังก์ชั่นในไฟล์นี้คุณจะพบกับการเรียกใช้ระบบจำนวนมากแม้ว่าจะไม่ได้นิยามไว้อย่างสมบูรณ์ ฉันวิ่งไปหลายgrepๆ ไดเรกทอรีในไดเรกทอรีเหล่านี้และฉันสามารถค้นหาการกล่าวถึงการเรียกของระบบ นี่คือตัวอย่าง:

$ grep 'sys_exit' /usr/include -R
asm-generic/unistd.h:__SYSCALL(__NR_exit, sys_exit)

ดังนั้นฉันเดาอีกวิธีหนึ่งในการค้นหาบางคนจะเป็น:

$ egrep '^__SYSCALL' /usr/include -Rh | awk '{print $2}' | tr -d ')'

การใช้ซอร์สโค้ดของเคอร์เนลและตาราง syscall

อีกวิธีคือใช้ซอร์สโค้ดของเคอร์เนลเอง (ไม่ใช่เฉพาะส่วนหัว!) และค้นหาวิธีการค้นหาอย่างมีประสิทธิภาพ เนื่องจากเคอร์เนลใช้ 303395ac3bf3e2cb488435537d416bc840438fcbคุณอาจพบว่านี่ง่ายกว่านี้เล็กน้อย นี่คือตัวอย่างสำหรับ 3.13 (ซึ่งเป็นเคอร์เนลของฉัน):

$ wget https://git.kernel.org/cgit/linux/kernel/git/stable/linux-stable.git/plain/arch/x86/syscalls/syscall_64.tbl?id=refs/tags/v3.13 -O syscall_64.tbl

ตอนนี้คุณได้รับตาราง syscalls จริงเพียงแค่เรียกดู:

$ while read line; do awk '! /#/ {print $3}'; done < syscall_64.tbl

คุณสามารถหาวิธีใช้unameและarchเพื่อดาวน์โหลดtblไฟล์ได้โดยตรงจากgit.kernel.orgโดยใช้เวอร์ชันและสถาปัตยกรรมเคอร์เนลที่รันอยู่

การใช้/sysระบบไฟล์

คำตอบที่กิลส์ให้ฉันนิด ๆ หน่อย ๆ /sys/kernel/debug/tracing/events/syscallsของแรงบันดาลใจและคุณอาจพบว่าผู้ที่สายระบบภายใน ไดเร็กทอรีนี้ใช้เพื่อมอนิเตอร์การใช้การเรียกระบบแต่ละครั้งบนระบบ syscall แต่ละอันมีสองไดเรกทอรีอยู่ในนั้น:

  • sys_enter_ [syscall]
  • sys_exit_ [syscall]

ดังนั้นการใช้ls, grepและcut...

$ ls /sys/kernel/debug/tracing/events/syscalls | grep 'sys_enter' | cut -d'_' -f3

สถิติ

ในระบบของฉัน:

  • การใช้ man pages แสดงการเรียกระบบ 440 ครั้ง
  • grep-ing สำหรับ__SYSCALLในไฟล์ส่วนหัวเปิดเผยการเรียกระบบ 212
  • การอ่านตาราง syscalls จากเคอร์เนลซอร์สเปิดเผยการโทรของระบบ 346 รายการ
  • ใช้/sysเปิดเผยสายระบบ 290

ตอนนี้ถ้าฉันรวบรวมทุกอย่าง ...

$ apropos -s2 . | awk '{print $1}' > system_calls.txt
$ egrep '^__SYSCALL' /usr/include -Rh | awk '{print $2}' | tr -d ')' >> system_calls.txt
$ while read line; do awk '! /#/ {print $3}'; done < syscall_64.tbl >> system_calls.txt
$ ls /sys/kernel/debug/tracing/events/syscalls | grep 'sys_enter' | cut -d'_' -f3 >> system_calls.txt

$ sort < system_calls.txt | uniq | wc -l
707

ไปแล้ว 707 สายระบบ! แน่นอนว่าตัวเลขนี้แสดงถึงคำจำกัดความที่ยืดหยุ่นอย่างมากของ "การเรียกของระบบ" เนื่องจาก3.13 ควรจะให้การเรียกใช้ระบบ 274 เท่านั้น (การอ่าน/sysน่าจะเป็นทางออกที่ใกล้เคียงที่สุด)


ฉันกำลังมองหาวิธีเพิ่มเติมในแง่ของ 'การอ่าน' ตารางการโทรของระบบในบางวิธีแทนที่จะค้นหาว่าการเรียกของระบบใดที่ถูกบันทึกไว้ใน man pages
Swair

ฉันไม่คิดว่าเคอร์เนลจะเก็บรายการ syscalls ของมันอย่างน้อยก็ไม่ได้เป็นรายการของสตริง ฉันแก้ไขคำตอบของฉัน หากมีวิธีการทำเช่นนี้จริงฉันจะให้คนที่มีประสบการณ์มากกว่าที่ฉันตอบคุณ)
John WH Smith

ดังนั้นฉันจึงสงสัยเกี่ยวกับเรื่องนี้หลังจากที่ฉันเพิ่มการเรียกของระบบไปยังเคอร์เนลและพยายามที่จะใช้มันเป็นการให้ "ฟังก์ชั่นที่ไม่ได้ใช้งาน" และฉันสงสัยว่ามีวิธีการรับตาราง syscall สำหรับเคอร์เนลปัจจุบัน เมื่อฉันติดตั้ง '#make' ให้อัพเดตด้วงและเริ่มเคอร์เนลใหม่ที่เคอร์เนลใหม่เกี่ยวข้องกับไฟล์ใดบ้างที่มีการเรียกระบบใหม่
Swair

1
หากไม่พบการเรียกระบบของคุณแสดงว่าคุณใช้งานไม่ถูกต้อง คำตอบของฉันจะบอกวิธีหาระบบโทรศัพท์ของ Linux แต่ไม่ใช่วิธีการดีบั๊กของคุณเอง (เนื่องจากไม่ใช่สิ่งที่คุณต้องการ) หากคุณกำลังมีปัญหาในการพัฒนาคุณควรถามคำถามโดยเฉพาะเกี่ยวกับเรื่องนี้และหลีกเลี่ยงปัญหา XY
John WH Smith

@swair เป็นเรื่องผิดปกติอย่างมากที่จะเพิ่มฟังก์ชันการทำงานโดยการเพิ่มการเรียกของระบบ เราไม่สามารถบอกได้ว่ามีอะไรผิดปกติเนื่องจากคุณไม่ได้ให้รหัสใด ๆ (และหากคำถามของคุณต้องใช้รหัส C มันเป็นหัวข้อที่นี่ แต่อยู่ที่บ้านในStack Overflow ) ฉันสงสัยว่าคุณใช้การเรียกของระบบ (ถูกต้องหรือไม่) และคุณกำลังพยายามใช้จากโปรแกรม C และคุณไม่มีขั้นตอนในการเขียนฟังก์ชัน C ที่ทำให้การเรียกของระบบ การเรียกของระบบไม่ใช่การเรียกใช้ฟังก์ชันปกติ
Gilles 'SO- หยุดความชั่วร้าย'

1

คำตอบทั้งหมดเป็นเรื่องปกติ

หากคุณกำลังมองหาชื่อการโทรของระบบเฉพาะ:

$ cat /proc/kallsyms | grep <sys_call_name>

หากคุณกำลังมองหารายการการโทรระบบทั้งหมด:

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