โปรเจ็กต์เพื่อย้ายกลไกการแยกคำสัญญาไปยัง Linux

ผู้เขียนไลบรารี C มาตรฐาน Cosmopolitan และแพลตฟอร์ม Redbean ได้ประกาศการดำเนินการตามกลไกการแยก pledge() สำหรับ Linux เดิมที Pledge ได้รับการพัฒนาโดยโครงการ OpenBSD และอนุญาตให้คุณเลือกห้ามไม่ให้แอปพลิเคชันเข้าถึงการเรียกของระบบที่ไม่ได้ใช้ (รายการ White list ของการเรียกระบบถูกสร้างขึ้นสำหรับแอปพลิเคชัน และห้ามการโทรอื่น ๆ ) ต่างจากกลไกการจำกัดการโทรของระบบที่มีอยู่ใน Linux เช่น seccomp กลไกการจำนำได้รับการออกแบบมาให้เรียบง่ายที่สุดเท่าที่จะเป็นไปได้

ความคิดริเริ่มที่ล้มเหลวในการแยกแอปพลิเคชันในสภาพแวดล้อมฐาน OpenBSD โดยใช้กลไก systrace แสดงให้เห็นว่าการแยกในระดับของการเรียกแต่ละระบบนั้นซับซ้อนและใช้เวลานานเกินไป อีกทางเลือกหนึ่ง มีการเสนอคำมั่นสัญญาซึ่งทำให้สามารถสร้างกฎการแยกออกได้โดยไม่ต้องลงรายละเอียดและจัดการคลาสการเข้าถึงสำเร็จรูป ตัวอย่างเช่น คลาสที่นำเสนอ ได้แก่ stdio (อินพุต/เอาท์พุต), rpath (ไฟล์อ่านอย่างเดียว), wpath (เขียนไฟล์), cpath (สร้างไฟล์), tmppath (ทำงานกับไฟล์ชั่วคราว), inet (ซ็อกเก็ตเครือข่าย), unix ( ซ็อกเก็ตยูนิกซ์) , dns (ความละเอียด DNS), getpw (การเข้าถึงเพื่ออ่านฐานข้อมูลผู้ใช้), ioctl (การเรียก ioctl), proc (การจัดการกระบวนการ), exec (การเปิดตัวกระบวนการ) และ id (การจัดการสิทธิ์การเข้าถึง)

กฎสำหรับการทำงานกับการเรียกของระบบระบุไว้ในรูปแบบของคำอธิบายประกอบ รวมถึงรายการคลาสที่อนุญาตของการเรียกของระบบและอาร์เรย์ของพาธไฟล์ที่อนุญาตให้เข้าถึงได้ หลังจากสร้างและเรียกใช้แอปพลิเคชันที่แก้ไขแล้ว เคอร์เนลจะเข้ามาทำหน้าที่ตรวจสอบการปฏิบัติตามกฎที่ระบุ

การดำเนินการจำนำแยกต่างหากกำลังได้รับการพัฒนาสำหรับ FreeBSD ซึ่งโดดเด่นด้วยความสามารถในการแยกแอปพลิเคชันโดยไม่ต้องทำการเปลี่ยนแปลงรหัส ในขณะที่ OpenBSD การเรียกคำมั่นสัญญามุ่งเป้าไปที่การบูรณาการอย่างแน่นหนากับสภาพแวดล้อมพื้นฐานและเพิ่มคำอธิบายประกอบให้กับโค้ดของแต่ละรายการ แอปพลิเคชัน.

นักพัฒนาพอร์ตจำนำสำหรับ Linux ได้ยกตัวอย่าง FreeBSD และแทนที่จะทำการเปลี่ยนแปลงรหัส ได้เตรียมยูทิลิตี้เสริม pledge.com ที่ช่วยให้คุณสามารถใช้ข้อ จำกัด ได้โดยไม่ต้องเปลี่ยนรหัสแอปพลิเคชัน ตัวอย่างเช่น หากต้องการรันยูทิลิตี้ curl โดยเข้าถึงเฉพาะคลาสการเรียกระบบ stdio, rpath, inet และ threadstdio เพียงเรียกใช้ “./pledge.com -p 'stdio rpath inet thread' curl http://example.com”

ยูทิลิตี้จำนำทำงานได้บน Linux ทั้งหมดที่เริ่มต้นด้วย RHEL6 และไม่จำเป็นต้องเข้าถึงรูท นอกจากนี้ ตามไลบรารีสากลนั้น API ได้รับการจัดเตรียมไว้สำหรับการจัดการข้อจำกัดในโค้ดโปรแกรมในภาษา C ซึ่งช่วยให้สามารถสร้างวงล้อมสำหรับการจำกัดการเข้าถึงแบบเลือกสรรที่เกี่ยวข้องกับฟังก์ชันแอปพลิเคชันบางอย่าง

การใช้งานไม่จำเป็นต้องมีการเปลี่ยนแปลงเคอร์เนล - ข้อจำกัดจำนำจะถูกแปลเป็นกฎ SECOMP BPF และประมวลผลโดยใช้กลไกการแยกการเรียกของระบบ Linux ดั้งเดิม ตัวอย่างเช่น call pledge("stdio rpath", 0) จะถูกแปลงเป็นตัวกรอง BPF static const struct sock_filter kFilter[] = { /* L0*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, syscall, 0, 14 - 1 ), / * L1*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, ปิด(args[0])), /* L2*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 2, 4 - 3, 0), /* L3* / BPF_JUMP( BPF_JMP | BPF_JEQ | BPF_K, 10, 0, 13 - 4), /* L4*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, ปิด (args[1])), /* L5*/ BPF_STMT(BPF_ALU | BPF_AND | BPF_K, ~0x80800), /* L6*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 1, 8 - 7, 0), /* L7*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 2, 0, 13 - 8) , /* L8*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(args[2])), /* L9*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 0, 12 - 10, 0), /*L10*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 6, 12 - 11, 0), /*L11*/ BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, 17, 0, 13 - 11), /*L12*/ BPF_STMT(BPF_RET | BPF_K, seccomp_RET_ALLOW), /*L13*/ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, OFF(nr)), /*L14*/ /* ตัวกรองถัดไป */ };

ที่มา: opennet.ru

เพิ่มความคิดเห็น