เจาะลึก syscall mseal ใหม่ของ Linux
(blog.trailofbits.com)- mseal ใน Linux 6.10 เป็น syscall สำหรับลดทอนการ exploit โดยปิดผนึกพื้นที่หน่วยความจำเสมือนขณะรัน ทำให้ผู้โจมตีที่ได้สิทธิ์รันโค้ดแล้วเปลี่ยนสิทธิ์หรือการจัดวางของ VMA ในภายหลังได้ยากขึ้น
mseal(start, len, flags)จะติดVM_SEALEDให้กับช่วง VMA ที่จัดแนวตามหน้าเพจแล้ว และเคอร์เนลจะปฏิเสธการเปลี่ยนแปลงในเส้นทางmprotect,munmap,mmap(MAP_FIXED),mremapและmadviseบางกรณีที่มีผลทำลาย- หาก
memfd_createหรือmemfd_secretเดิมใกล้เคียงกับการควบคุมการเข้าถึงไฟล์นิรนามบน RAM และหน่วยความจำลับ mseal จะเน้นการป้องกันการเปลี่ยนสิทธิ์ การ unmap และการ remap หลังผู้โจมตีระยะไกลรันโค้ดได้แล้ว - เป้าหมายการป้องกันหลักคือการโจมตีที่ใช้
mprotect(PROT_EXEC)เพื่อเลี่ยง NX แล้วรัน shellcode และ data-only exploit ที่ใช้munmap/การ remap เจาะรูในหน่วยความจำแล้วเติมข้อมูลของผู้โจมตีลงไป - อาจถูกรวมเข้า glibc ตั้งแต่ 2.41 เป็นต้นไป แต่ stack และ heap ไม่ใช่เป้าหมายที่จะปิดผนึกอัตโนมัติเนื่องจากมีการขยาย/หดใน runtime ดังนั้นนักพัฒนาต้องกำหนดเวลาและช่วงที่จะใช้งานอย่างรอบคอบ
การป้องกันที่ mseal มอบให้
- memory sealing คือความสามารถที่ทำให้ช่วง VMA ขณะรันแทบจะไม่เปลี่ยนแปลงได้จากการแก้ไขอันตรายในภายหลัง
- แม้ผู้โจมตีจะได้ primitive สำหรับรันโค้ดแล้ว ใน VMA ที่ถูกปิดผนึกก็ยังเปลี่ยนสิทธิ์หรือจัดวางให้ได้เปรียบผ่านการดำเนินการกับหน่วยความจำเสมือนได้ยาก
- ทีม Chrome Security นำ syscall นี้มาใช้เพื่อรองรับ กลยุทธ์ V8 CFI บน ChromeOS ที่ใช้ Linux
- หลังผ่านการอภิปรายและเขียนใหม่หลายรอบ ฟีเจอร์นี้ก็เข้าไปอยู่ในเคอร์เนล Linux และขอบเขตการใช้งานอาจขยายออกไปนอกเบราว์เซอร์ผ่าน การผนวกรวมกับ glibc
ความแตกต่างจากตระกูล memfd
memfd_createและmemfd_secretใกล้เคียงกับตระกูล file sealing- สามารถสร้างไฟล์นิรนามบน RAM ได้
memfd_secretทำให้เฉพาะโปรเซสที่มี file descriptor เท่านั้นที่เข้าถึงพื้นที่หน่วยความจำนั้นได้- สามารถใช้กับ mapping ฝั่ง user space แบบ “secure enclave” เพื่อปกป้องข้อมูลละเอียดอ่อนในหน่วยความจำ
msealเป็น syscall ที่ออกแบบให้เป็นการลดทอน exploit ต่อ ผู้โจมตีระยะไกล ที่มุ่งรันโค้ด มากกว่าผู้โจมตีภายในเครื่องที่มุ่งรั่วไหลข้อมูลละเอียดอ่อน
การทำงานภายในเคอร์เนล
- signature ของ syscall คือ
int mseal(unsigned long start, size_t len, unsigned long flags)startและlenระบุจุดเริ่มต้นและความยาวของ VMA ที่ถูกต้องที่จะปิดผนึกlenต้องจัดแนวตามหน้าเพจอย่างถูกต้อง- ปัจจุบัน
flagsยังไม่ถูกใช้และต้องเป็น0
- การ implement ณ Linux 6.12 เรียก
do_msealcurrent->mmชี้ไปยังmm_structซึ่งเป็น address space หน่วยความจำเสมือนทั้งหมดของโปรเซสที่เรียกmmapของmm_structเก็บรายการvm_area_structซึ่งเป็นพื้นที่หน่วยความจำต่อเนื่องที่สร้างด้วยmmap- พื้นที่อย่าง stack หรือ VDSO ก็อาจถูกแทนเป็น VMA หนึ่งรายการได้
do_msealคำนวณที่อยู่ปลายช่วง จากนั้นล็อกพื้นที่หน่วยความจำด้วยmmap_write_lock_killablecheck_mm_sealวนผ่าน VMA แต่ละรายการในช่วงเป้าหมายและตรวจสอบ ความถูกต้องของขอบเขต ก่อน- หากมีหน่วยความจำที่ไม่ได้ allocate อยู่กลางช่วง จะคืนค่า
-ENOMEM - การตรวจรอบแรกนี้เป็นขั้นตอนเพื่อหลีกเลี่ยงสถานการณ์ที่มีเพียง VMA บางส่วนถูกปิดผนึกเมื่อเกิดข้อผิดพลาด
- หากมีหน่วยความจำที่ไม่ได้ allocate อยู่กลางช่วง จะคืนค่า
apply_mm_sealวนผ่านช่วงเดียวกันอีกครั้ง และเพิ่ม flagVM_SEALEDให้ VMA เป้าหมายผ่านmseal_fixup
การดำเนินการกับหน่วยความจำที่ถูกห้ามหลังปิดผนึก
- patchset ของเคอร์เนลเพิ่มการตรวจ
VM_SEALEDในmm/madvise.c,mm/mmap.c,mm/mprotect.c,mm/mremap.c,mm/mseal.c mprotectและpkey_mprotectเรียกcan_modify_vmaภายในmprotect_fixupและหาก VMA ถูกปิดผนึกจะคืนค่า-EPERM- ใน VMA ที่ถูกปิดผนึก จะไม่อนุญาตการดำเนินการต่อไปนี้
- การเปลี่ยนบิตสิทธิ์ ผ่าน
mprotect,pkey_mprotect - การ unmap ผ่าน
munmap - การแทนที่ mapping ที่ถูกปิดผนึกด้วย mapping ที่เปลี่ยนแปลงได้และไม่ถูกปิดผนึกผ่าน
mmap(MAP_FIXED) - การขยายหรือย่อขนาดผ่าน
mremap - การย้ายไปยังปลายทางใหม่ผ่าน
mremap(MREMAP_MAYMOVE | MREMAP_FIXED) madviseที่ใช้ flag บางแบบซึ่งมีผลทำลาย
- การเปลี่ยนบิตสิทธิ์ ผ่าน
- ในการย้ายด้วย
mremapจะตรวจการปิดผนึกทั้ง VMA ต้นทางและปลายทาง - หากไม่มี
MREMAP_DONTUNMAPจะมีการ unmap VMA ต้นทาง และกรณีนี้ก็ต้องผ่านการตรวจการปิดผนึกของmunmapด้วย - ตั้งแต่ Linux 6.10 ขึ้นไป สามารถใช้
msealด้วยการเรียก syscall โดยตรงได้ และ wrapper ตัวอย่างใช้หมายเลข syscall462กับflags=0
บล็อกการรัน shellcode ด้วยการเสริมความแข็งแรงให้ NX
- ผู้โจมตีอาจยังชอบ การรัน shellcode แม้จะมีเทคนิค reuse โค้ดอย่าง ROP
- โปรย shellcode ลงใน stack หรือ heap ที่รันไม่ได้
- ใช้ช่องโหว่เพื่อรัน ROP chain เริ่มต้น
- ปิดบิต NX ของพื้นที่ที่มี shellcode ด้วย
mprotect(PROT_EXEC) - กระโดดไปยังพื้นที่นั้นเพื่อรัน shellcode
- การโจมตี MikroTik RouterOS SMB daemon ที่ใช้ CVE-2018-7445 เป็นตัวอย่างของ flow นี้
- โปรย shellcode แบบใช้ socket ลงใน heap ที่รันไม่ได้
- ROP chain ที่สร้างจาก stack overflow เปลี่ยนสิทธิ์หน่วยความจำของ heap
- จากนั้นรัน shellcode
- หากปิดผนึก VMA นั้นด้วย
msealการตรวจcan_modify_vmaจะขัดขวางการเปลี่ยนสิทธิ์เมื่อเรียกmprotect - ในโค้ดตัวอย่าง หากไม่ปิดผนึกหน้าเพจของ shellcode บน stack ก็สามารถรันได้หลัง
mprotect(PROT_READ|PROT_WRITE|PROT_EXEC) - หากปิดผนึกหน้าเดียวกันด้วย
msealแล้วmprotectจะเปลี่ยนสิทธิ์จริงไม่ได้ และเมื่อรัน shellcode จะเกิด segmentation fault
ข้อจำกัดในการใช้กับ stack และ heap
- หากมีการนำ
msealเข้ามาตั้งแต่ glibc 2.41 เป็นต้นไป dynamic loader จะปิดผนึกชุด VMA ที่กำหนดไว้ล่วงหน้า - ตามแผนปัจจุบัน stack และ heap จะไม่ถูกปิดผนึกอัตโนมัติ
- stack และ heap สามารถขยายได้ระหว่าง runtime ดังนั้นการปิดผนึกอัตโนมัติอาจทำให้แอปพลิเคชันทำงานผิดพลาด
- heap allocator อาจเรียก syscall
brkเพื่อคืนพื้นที่ - ในเส้นทางนี้อาจเกิดการย่อผ่าน
arch_unmapและdo_vmi_unmap - เมื่ออยู่ในสถานะปิดผนึก การ unmap แบบนี้จะไม่ได้รับอนุญาต ทำให้ dynamic memory allocation พังได้
- heap allocator อาจเรียก syscall
- นักพัฒนาต้องตัดสินตามบริบทของแอปพลิเคชันว่าควรใช้การปิดผนึกกับช่วงเวลาและพื้นที่ใดได้บ้าง
- macro ตัวอย่างจะปิดผนึกหน้าเพจของ stack frame ที่เลือกไว้ ซึ่งอาจมีข้อมูลที่ไม่น่าเชื่อถือ อยู่ซ้ำ ๆ
- หากเรียก
msealซ้ำกับ VMA ที่ถูกปิดผนึกแล้ว จะถูกจัดการเป็น no-op และไม่เกิดข้อผิดพลาด - ฟีเจอร์อย่างการขยาย stack อัตโนมัติหรือ stack splitting ต้องระวังเป็นพิเศษ
- หากผู้โจมตียังยืนกรานใช้ shellcode ก็อาจ
mmapพื้นที่ใหม่ที่รันได้ แล้วคัดลอก payload จากพื้นที่ที่อ่านได้ แต่ขั้นตอนจะยุ่งยากขึ้น
ลดทอน data-only exploit ที่อาศัยการ unmap
- การบล็อก
mprotectยังป้องกันไม่ให้พื้นที่ที่ถูกปิดผนึกเปลี่ยนเป็นสถานะเขียนได้ จึงช่วยปกป้องตัวแปรข้อมูลที่หากถูกแก้ไขแล้วอาจเพิ่มความสามารถของ exploit primitive ได้ - ผู้ดูแล Chrome พิจารณาเทคนิคที่ส่ง pointer ที่เสียหายไปยัง syscall สำหรับ unmap/remap เพื่อ เจาะรู ในหน่วยความจำ แล้วเติมข้อมูลที่ผู้โจมตีควบคุมกลับเข้าไป
- วิธีนี้ไม่เปลี่ยนการถ่ายโอน control flow อย่าง return address บน stack หรือ function pointer โดยตรง จึงอาจเลี่ยงการรับประกัน CFI ทั้ง forward-edge และ backward-edge ได้
- ในเบราว์เซอร์ที่ implement JIT compiler เทคนิคนี้อาจมีประโยชน์เป็นพิเศษ
- Turbofan ของ V8 สามารถสร้างพื้นที่ที่สลับระหว่าง RW และ RX ได้
- ผู้โจมตีสามารถทำให้กระบวนการ JIT compile สร้างโค้ดรันจาก JavaScript แบบ hot-path ได้
- เติมพื้นที่ที่ถูก unmap เพื่อเขียนทับข้อมูลสำคัญ แล้วสร้างการเปลี่ยนแปลงที่นำไปสู่การรันโค้ดได้
- นี่คือ data-only exploit ที่ไม่ต้องยึด control flow โดยตรงหรือบังคับให้มี pointer leak แต่จัดการข้อมูลบางจุดในหน่วยความจำเพื่อส่งผลต่อ control flow
msealสามารถบล็อกการ unmap และ remap เพื่อกันสถานการณ์ hole-punching แบบนี้ได้
กรณี House of Muney
- House of Muney ใช้เทคนิคที่อาศัยการ unmap คล้ายกันใน exploit heap ฝั่ง user space
- Qualys ใช้เทคนิคนี้ใน exploit จริง สำหรับบั๊ก Qmail เก่า
- เทคนิคนี้อาศัยคุณสมบัติที่เมื่อ chunk ขนาดใหญ่มีขนาดมากกว่า
M_MAP_THRESHOLDแล้วmallocและfreeจะเรียกmmapและmunmapโดยตรงตามลำดับ - chunk ขนาดใหญ่ไม่มี freelist cache ขั้นกลาง ทำให้ขั้นตอน exploit ง่ายขึ้น
- เมื่อแก้ metadata ขนาดที่ด้านบนของ chunk ที่ allocate ให้เป็นขนาดหน้าเพจอื่นแล้ว
freeก็อาจเกิดmunmapกับพื้นที่หน่วยความจำที่อยู่ติดกับ chunk นั้นได้ - ตัวอย่างของ Dulin เล็งพื้นที่
.gnu.hashและ.dynsymด้วยmunmapตามอำเภอใจ- จากนั้นเติมกลับด้วย chunk
mmapที่ใหญ่กว่า - ทำให้เขียนทับ PLT entry หนึ่งรายการที่ยังไม่ได้ resolve ได้
- ทำให้การโจมตีสไตล์ GOT overwrite กลับมาใช้ได้
- จากนั้นเติมกลับด้วย chunk
- PoC แบบย่อ allocate chunk ขนาดใหญ่สองก้อน, ปรับแต่งฟิลด์ size ของ
top[-1], จากนั้นfree(top)เพื่อ unmap ไปจนถึงพื้นที่ข้างเคียง และ allocate ก้อนที่ใหญ่กว่าเพื่อเติมข้อมูลXกลับเข้าไป - เทคนิคนี้สามารถทำงานได้แม้มี CFI และไม่ต้องมี ASLR leak ล่วงหน้า
- การปิดผนึกชุด VMA ที่วางแผนไว้ในการผนวกรวม
msealของ glibc คาดว่าจะปกป้องโค้ดไบนารีและไลบรารีไดนามิกที่ถูก map ไว้จากกลเม็ด unmap/remap และลดทอนการโจมตีนี้โดยอัตโนมัติ - นักพัฒนาที่ต้องการเสริมความแข็งแรงเพิ่มเติมสามารถเลือกปิดผนึก allocation จาก
mmapที่จะไม่ขยายหรือถูก unmap ตลอดอายุของโปรแกรมได้
ขอบเขตการใช้งานในอนาคต
msealเป็นฟีเจอร์ลดทอนความเสี่ยงที่ค่อนข้างใหม่ของเคอร์เนล Linux และอาจยังมีกรณีการใช้งานที่ไม่ได้กล่าวถึงอีก- เมื่อการผนวกรวมกับ glibc เสร็จสมบูรณ์และเติบโตเต็มที่ อาจมีการปรับปรุงให้สอดคล้องกับข้อกำหนดของ syscall ต่อไป
- พารามิเตอร์
flagsที่ยังไม่ได้ใช้ในปัจจุบันก็อาจมีการกำหนด用途เฉพาะในอนาคต - เมื่อใช้งานกับซอฟต์แวร์จริง ต้องประเมินอายุการใช้งานของหน่วยความจำที่จะปิดผนึกควบคู่กับความจำเป็นในการเปลี่ยนแปลงด้วย
1 ความคิดเห็น
ความคิดเห็นใน Hacker News
ถ้ามีคนวงในช่วยสรุปได้ว่ามีการคัดค้านและความกังวลอะไรบ้างในการถกเถียงอย่างดุเดือดบน mailing list ของเคอร์เนลก็คงดี
ตัว mailing list เองบางทีก็เผ็ดเกินไป เลยค่อนข้างหลีกเลี่ยง และตอนนี้ก็ปวดหัวมากพออยู่แล้ว
กลไกเองดูสมเหตุสมผล แต่ก็น่าแปลกใจที่ฟีเจอร์แบบนี้ยังไม่มีอยู่ในเคอร์เนลมาก่อน
ในบรรดาแฟล็กที่เสนอ มีอันหนึ่งที่ทำให้สามารถละเว้น seal ได้ และ Linus ก็ตอบทำนองว่า “จะไม่ให้
munmapทำงานในที่หนึ่ง แต่ในอีกที่หนึ่งจะให้ละเว้น seal อย่างนั้นเหรอ”ต่อมาพูดแรงขึ้นว่า “เมื่อ seal แล้วก็คือ seal แล้ว” และจะทำแบบ “บางที่เคารพ seal ส่วนที่อื่นตามใจกลับไม่เคารพ” ไม่ได้
ภายหลังถึงขั้นบอกว่า seal ไม่สามารถละเว้นได้และไม่ใช่เรื่องต่อรอง ถ้ายังเสนอแฟล็กให้ละเว้น seal อีกก็จะเอาเข้า ignore list
ในอีเมลที่ Theo de Raadt ส่งถึง Jeff Xu หลังจาก Jeff บอกว่าแนวทางของ
mimmutable()กับmseal()แตกต่างกัน แต่ทั้งคู่มีเป้าหมายเพื่อ seal หน่วยความจำจากผู้โจมตีและทำให้แอปพลิเคชัน Linux ปลอดภัยขึ้น Theo ตอบว่า “ดูเหมือนคุณกำลังทำ mseal เพื่อ Chrome เท่านั้น”เขามองว่ามันคงไม่เหมาะกับแอปพลิเคชันโดยรวม โดยให้เหตุผลว่ามันซับซ้อนเกินไป และจากประสบการณ์ของ
mimmutable()สุดท้ายแอปพลิเคชันจะไม่ได้จัดการเอง แต่จะเป็นหน้าที่ของexecve(), การเริ่มต้นของ libc และld.soเขาเห็นด้วยกับ Theo และ Linus โดยมองว่าแนวคิดพื้นฐานของ
mimmutable()นั้นดี แต่วิธีที่แยกย่อยและนำไป implement นั้นแย่มากสงสัยว่าจะใช้ system call นี้อย่างไร
Chrome ต้องการมันก็จริง แต่เพราะผู้โจมตีสามารถ map ใหม่ด้วยแฟล็กอื่นได้ หน้าเพจที่ถูก seal แล้วจึงไม่สามารถ unmap ได้
ถ้าอย่างนั้น หน้าเพจที่จัดสรรตอน runtime ก็แทบจะใช้ไม่ได้ เว้นแต่ตั้งใจจะเก็บไว้ตลอดอายุของโปรเซสหรือเปล่า
ถ้าเป็นแบบนั้น จะเอาไปใช้กับเป้าหมายที่น่าดึงดูดมากอย่างหน่วยความจำของ JS sandboxได้ยากไม่ใช่หรือ?
เลยสงสัยว่างานลักษณะนี้แก้ด้วยการรันในโปรเซสแยก seal หน่วยความจำ แล้วพอเสร็จก็ kill โปรเซสหรือไม่
ไม่ค่อยรู้วิธีจัดการหน่วยความจำและโปรเซสของ Chrome เลยไม่แน่ใจว่าทำไมมันไม่เป็นปัญหา และก็สงสัยว่านี่เป็นเหตุผลที่มักอธิบายกันว่าฟีเจอร์นี้ไม่ค่อยมีประโยชน์กับโปรแกรมส่วนใหญ่หรือเปล่า
เท่าที่รู้ Chrome ใช้วิธีนี้อย่างกว้างขวางอยู่แล้ว และด้วยเหตุผลอย่างการแยกกันด้วย namespace ก็จำเป็นต้องมีโปรเซสแยกอยู่ดี จึงอาจเป็นแนวทางนั้น
การอภิปรายหลัง
mseal()วันที่ 20 ตุลาคม 2023: https://lwn.net/Articles/948129/mseal()ใกล้เข้ามาแล้ว วันที่ 19 มกราคม 2024: https://lwn.net/Articles/958438/การ seal หน่วยความจำสำหรับ GNU C Library วันที่ 12 มิถุนายน 2024: https://lwn.net/Articles/978010/
น่าเสียดายที่แม้สถาปัตยกรรม x86_64 สมัยใหม่จะมีฟีเจอร์มากมายที่ช่วยด้านการเขียนโปรแกรมและการประมวลผลอย่างปลอดภัย แต่ระบบปฏิบัติการก็ยังต้อง implement call แบบนี้
มองว่าท่าทีที่พยายามซ่อมระบบเก่าซึ่งสร้างอยู่บนมรดกและวิธีคิดล้าสมัย รวมถึง paradigm ที่ไม่สอดคล้องกับโลกและความรู้ในปัจจุบัน กำลังทำให้ความก้าวหน้าของคอมพิวติ้งช้าลง และทำให้ผู้คนนับพันล้านตกอยู่ในความเสี่ยงอย่างแท้จริง
แน่นอนว่าไม่ได้จะบอกว่าการเปลี่ยนแปลงนี้ไม่ใช่ก้าวไปในทิศทางที่ถูกต้อง แต่หากเลิกยึดติดกับอุดมคติเดิมว่าระบบปฏิบัติการควรทำงานอย่างไร แล้วพิจารณาระบบและความรู้ปัจจุบัน รวมถึงสิ่งที่ผู้คนต้องการจากระบบ ก็สามารถจินตนาการถึงระบบที่หลุดพ้นจากภาระและความเสี่ยงที่ตกอยู่กับนักพัฒนาและผู้ใช้ในวันนี้ได้
จริงอยู่ที่มีบั๊กในสถาปัตยกรรม แต่ซอฟต์แวร์เองก็ยังใช้ฟีเจอร์ที่มีในปัจจุบันได้ไม่เต็มที่ ดังนั้นการยกบั๊กของสถาปัตยกรรมมาโต้แย้งจึงพลาดประเด็น
หากสร้างอยู่บนฐานที่สั่นคลอน ก็จะมีวิธีเจาะที่ถูกกว่าเสมอ
และอยากรู้ด้วยว่าทำไมถึงมองว่า
msealไม่มีเหตุผลรองรับ และอะไรที่ดีกว่าแทนจะสามารถใช้ทริก
LD_PRELOADเพื่อเขียนทับหรือปิดใช้งาน system callmsealได้หรือไม่?msealเป็น system call ที่ต่างจากวิธีป้องกันหน่วยความจำแบบเดิมของ Linux โดยมุ่งไปที่ การบรรเทาการโจมตีแบบรันโค้ดจากระยะไกล มากกว่าผู้โจมตีในเครื่องที่พยายามดึงความลับสำคัญออกจากหน่วยความจำหากผู้โจมตีจากระยะไกลสามารถเปลี่ยนสภาพแวดล้อมภายในเครื่องได้ ก็ควรมองว่าได้เจาะเข้าระบบแล้ว
LD_PRELOADคงทำไม่ได้เพื่อให้ได้ผล มันต้องเป็นฟังก์ชันที่ถูกนำเข้า แต่ system call แบบดิบไม่สามารถถูกดักจับด้วยวิธีนั้นได้
การอภิปรายเรื่องการดักจับ system call ของ Linux: https://stackoverflow.com/questions/69859/how-could-i-interc...
วิธีที่ง่ายที่สุดในการ “ปิดใช้งาน” ฟีเจอร์นี้อาจเป็นการสร้างเคอร์เนลที่แพตช์เองให้แสร้งว่า
msealทำงานอย่างไรก็ตาม โปรแกรมที่ใช้
msealสามารถตรวจสอบได้ว่ามันทำงานจริงหรือไม่ ดังนั้นเคอร์เนลที่ถูกแก้ไขจึงยังต้องมีวิธีปิดmsealแบบลับ ๆ เพื่อป้องกันการตรวจสอบของแอปหลังนำไปใช้เช่น สามารถติดตามไฟล์รันด้วย
ptraceเพื่อเฝ้าดู system call แล้วข้ามmseal(2)ไปได้system call นี้ไม่ได้ออกแบบมาสำหรับ threat model ที่ว่า “ผู้โจมตีมีสิทธิ์เข้าถึงอยู่แล้วก่อนการเริ่มต้นโปรเซส”
msealสามารถเขียนทับได้ แต่ ตัว system call เอง เขียนทับไม่ได้จากที่ลองค้นดู วิธีเขียนทับ system call แบบ preload ทั้งหมดเป็นการเปลี่ยน wrapper และหากเรียก system call โดยตรงก็น่าจะเขียนทับไม่ได้
ในเชิงเทคนิค อาจเป็นไปได้ที่จะเขียนทับตัวฟังก์ชัน
syscallเองเมตา: ต้นแบบของ
mseal()ในบทความต้องแก้ไขอาร์กิวเมนต์แรกแสดงเป็น
unsigned start addrแต่ที่ถูกน่าจะเป็นunsigned long start_addrint mseal(unsigned long start, size_t len, unsigned long flags)เคยมีการถกกันมาก่อนแล้วว่า CPython ควรรองรับ system call
mseal()อย่างไร ใน “Memory Sealing ‘Mseal’ System Call Merged for Linux 6.10” (2024) https://news.ycombinator.com/item?id=40474510#40474551OpenBSD มีฟีเจอร์นี้มาตั้งนานแล้ว https://man.openbsd.org/mimmutable.2
สงสัยว่าทำไมฟีเจอร์ที่ดูชัดเจนแบบนี้เพิ่งจะเข้ามาใน Linux ตอนนี้
mimmutableของ OpenBSD ถูกนำมาใช้ใน OpenBSD 7.3 ซึ่งเผยแพร่เมื่อวันที่ 10 เมษายน 2023 ดังนั้นจึงไม่ใช่ “มีมาตั้งนานแล้ว”ในทางกลับกัน Linux และ FreeBSD มี
memfd_createมาตั้งนานแล้ว ส่วน OpenBSD ไม่มีไฟล์นิรนาม จึงต้องพึ่งshm_open