ซีพียู Skylake เพิ่งเปิดตัวไป สำหรับคนส่วนมาก มันคือซีพียูที่แรงขึ้นตามรอบการอัพเกรดของอินเทล แต่นอกจากความแรงแล้ว อินเทลยังค่อยๆ ปรับปรุงสถาปัตยกรรมของซีพียูทุกรอบที่ออกรุ่นใหม่ เช่นใน Haswell ที่มีชุดคำสั่ง TSX สำหรับโมเดลการเขียนโปรแกรมแบบหลายเธรดแบบใหม่ ในสถาปัตยกรรม Skylake ชุดคำสั่งใหม่คือ Intel MPX (Memory Protection Extensions)
ชุดคำสั่ง MPX พยายามแก้ปัญหาความปลอดภัยซอฟต์แวร์ที่เป็นปัญหามายาวนาน คือ การใช้หน่วยความจำเกินกว่าที่จองไว้ (memory overflow) ความผิดพลาดที่โปรแกรมเมอร์ไม่ได้ตรวจสอบขนาดของหน่วยความจำที่จองไว้หรือขนาดข้อมูลที่กำลังเขียนลงไป สร้างช่องโหว่สำคัญๆ มากมาย ก่อนหน้านี้มีโครงการที่พยายามแก้ปัญหานี้ เช่น AddressSanitizer ที่รองรับใน GCC มาตั้งแต่รุ่น 4.8 และช่วยให้พบช่องโหว่ในเบราว์เซอร์โครมหลายจุด สำหรับชุดคำสั่ง MPX เป็นการย้ายกระบวนการตรวจสอบจากที่อยู่ในระดับซอฟต์แวร์มาอยู่ในระดับฮาร์ดแวร์ที่วงจรของซีพียูโดยตรง แต่ยังจำเป็นต้องให้ ระบบปฎิบัติการและคอมไพล์เลอร์รองรับ
ตัวอย่างโค้ดที่ MPX สามารถตรวจสอบความผิดพลาดได้ เช่นดังภาพ
การเขียนสตริง "Intel MPXexample" ความยาวเกินขนาดหน่วยความจำที่จองไว้เพียง 4 ไบต์จะทำให้เกิดอินเตอร์รัพท์ และโปรแกรมจะเข้าฟังก์ชั่นเพื่อแจ้งความผิดพลาดทันที
กระบวนการตรวจสอบ ทำได้โดยเคอร์เนลของระบบปฎิบัติการจะตารางค้นหาขอบเขตพอยเตอร์ (Bound Directory) เมื่อโปรเซสรันขึ้นมาก็จะสร้างตารางขอบเขตพอยเตอร์ (Bound Table) เก็บค่าขอบเขต จุดสูงสุดและต่ำสุดของพอยเตอร์ที่ใช้งานได้ หากพอยเตอร์พยายามใช้งานนอกขอบเขตนี้ก็จะเกิดอินเตอร์รัพท์
แม้ว่า Skylake จะเพิ่งออกวางตลาด แต่อินเทลก็เตรียมการสำหรับชุดคำสั่ง MPX มาล่วงหน้าหลายปี โดยส่งแบบจำลองการทำงานให้ผู้ผลิตหลายรายไว้ล่วงหน้า โครงการ AddressSanitizer มีบทความเขียนเปรียบเทียบการทำงานกับ MPX พร้อมกับตั้งข้อสงสัยว่าจริงๆ แล้วการตรวจสอบที่ระดับฮาร์ดแวร์จะได้ประสิทธิภาพเพิ่มขึ้นจริงหรือไม่ สำหรับลินุกซ์อินเทลส่งโค้ดเข้าไปยังเคอร์เนลตั้งแต่ต้นปีที่แล้ว ทำให้ลินุกซ์ตั้งแต่รุ่น 3.19 รองรับ MPX มาโดยตลอด และ GCC ก็รองรับ MPX บนลินุกซ์ตั้งแต่รุ่น 5.1 เป็นต้นมา สำหรับวินโดวส์นั้น รุ่น 8.1 เป็นต้นมาก็รองรับแล้ว แต่เอกสารของอินเทลไม่ได้พูดถึงคอมไพล์เลอร์ว่า Visual Studio รองรับหรือไม่ ระบุเพียงว่า Intel C++ รองรับบนวินโดวส์แล้ว
สำหรับโปรแกรมเมอร์ที่ยังเขียนภาษาซีกันอยู่ MPX ก็เป็นอีกเครื่องมือที่จะช่วยให้ความผิดพลาดถูกพบได้ง่ายขึ้น และไม่กลายเป็นช่องโหว่อันตรายไปเสียก่อน สำหรับผู้ใช้ทั่วไปหากนักพัฒนาไลบรารียอมรับประสิทธิภาพของ MPX และเปิดใช้งานกันเป็นมาตรฐาน ก็จะมีตัวช่วยป้องกันช่องโหว่ซอฟต์แวร์เพิ่มเติมมาอีกชั้น
ที่มา - Intel (PDF)
Comments
มันก็คือ garbage collector ?
คนละเรื่องกันครับ อันนี้ไ่ม่เกี่ยวกับการแก้ปัญหา memory leak
ถึงมีชุดคำสั่งนี้ ถ้าเขียนโปรแกรมโดยใช้ภาษาที่ไม่มี GC เช่น C/C++ อย่างไงคนเขียนก็ต้องคอยดูเรื่องการคืนหน่วยความจำเอง (นอกจากจะใช้ smart pointer)
ชุดคำสั่งนี้แค่ช่วยเพิ่มความปลอดภัยโดยการเช็คขอบเขตของหน่วยความจำแค่นั้น ถ้าเกินระบบปฎิบัติการมันก็ตรวจจับได้แล้วก็โยนเป็น exception ออกมา
แสดงว่าถ้าคอมไพล์ซอร์สโค้ดกับคอมไพเลอร์ที่มีฟีเจอร์นี้ ต่อไปนี้เวลาจองหน่วยความจำ ก็ต้องใช้ system call ตลอดเพื่อให้ kernel บันทึกขอบเขตของหน่วยความจำก้อนนั้นๆไว้
อย่างนี้โปรแกรมก็น่าจะมีประสิทธิภาพลดลงเพราะเกิด context switch ตลอดเวลา
หรือไม่ก็น่าจะต้องใช้กับโค้ดที่ต้องการความปลอดภัยสูง ดังนั้นเวลาคอมไพล์คงจะต้องระบุ flag กับคอมไพเลอร์โดยเฉพาะในกรณีถ้าอยากจะใช้ชุดคำสั่งใหม่นี้จริงๆ
ถ้าเป็นโค้ดที่ต้องการประสิทธิภาพสูง แล้วมีการจองหน่วยความจำบ่อยๆ นี่น่าจะทำอะไรผิดสักอย่างแล้วนะครับ เช่น สร้าง object pool เพื่อ reuse หน่อยความจำ ถ้าจะให้ malloc/free จัดการเก็บ freelist ให้นี่ วันดีคือดีเจอ malloc ที่สั่ง mmap/VirtualAlloc ทุกรอบประสิทธิภาพไม่แย่ไปเลยเหรอครับ
ถ้าเป็นโค้ดปกติ เช่น UI หรือ network อันนี้ก็ใช้ system call มโหฬารอยู่แล้ว น่าจะไม่ค่อยต่างมั้งครับ
เห็นด้วยเรื่องการใช้ memory pool ครับ
แต่ผมเคยลองเหมือนกัน โค้ดที่ผมลองเป็นโค้ดที่สร้างกราฟที่มี vertex กับ edge
เป็นล้านๆ แล้วลองจับเวลาระหว่างสองเวอร์ชั่นดู เวอร์ชั่นแรกคือใช้ new กับ delete แบบปกติ กับอีกเวอร์ชั่นที่จองพื้นที่หน่วยความจำไว้เป็น pool ไว้ล่วงหน้า พอเวลาจะสร้าง vertex หรือ edge ก็แค่ดึงจาก pool มาอีกที
ผลการทดสอบปรากฎว่า แบบ pool ไม่ได้ดีกว่าแบบปกติอย่างมีนัยยะอะไร
ส่วนกรณีของโปรแกรมประเภท GUI กับ network นี่มันเป็น IO-Bound เรื่องเวลาคงจะไม่ใช่ปัญหาหลักอยู่แล้วมั้งครับ
ในบทความของ AddressSanitizer ที่ตอนนั้นรายงานกับคอมไพล์เลอร์จำลองที่อินเทลออกมาก่อนหน้านี้ก็พูดเรื่องนี้ครับ ว่าอาจจะมีปัญหาประสิทธิภาพในบางกรณี แต่ตอนนั้นเป็นแค่คอมไพล์เลอร์จำลองยังไม่มีซีพียูจริงก็พูดยาก การศึกษาที่ทำได้คือกระบวนการแบบนี้จับบั๊กแบบใดได้บ้างไม่ได้บ้าง (มีบางกรณี false positive ด้วย)
แต่โค้ดที่ทั่วๆ ไปพวกอย่างพวกเว็บเซิร์ฟเวอร์ ที่เสี่ยงต่อการถูกยิงข้อมูลเข้ามาโจมตี จะต้อง malloc บ่อยขนาดนั้น?
lewcpe.com, @wasonliw
ไม่ทราบเหมือนกันครับว่าพวกเว็บเซิร์ฟเวอร์จะต้อง malloc บ่อยๆหรือเปล่า แต่เดาว่าไม่น่าจะบ่อยนะครับ
ถ้าเป็นอย่างนี้แสดงว่าชุดคำสั่งใหม่นี้ไม่น่าจะมีผลกระทบอะไรมากเพราะอย่างที่คุณ lew บอกไปก่อนหน้าแล้วว่า ถ้าจะใช้ชุดคำสั่งนี้ต้องระบุ flag จะได้ไม่กระทบกับโค้ดปกติอื่นๆ
ถ้าใช้ new/delete ในกรณีทั่วๆ ไป (คือใช้ gcc/libstdc++, msvc/crt บนระบบปฎิบัติการทั่วไป Linux/Win/OSX ล่าสุด) มันคงไม่ได้ต่างกันเท่าไรครับ แต่วันดีคืนดีมีคนเอาไปใช้บนรันไทม์หรือระบบปฏิบัติการแปลกๆ หรือเจอไดรเวอร์แปลกๆ อาจจะทำให้ช้ากว่าทำ pool เองครับ ยกตัวอย่างเช่นรันไทม์ที่เรียกใช้ mmap/VirtualAlloc ทุกครั้งที่ malloc
ต้องระบุ flag เวลาคอมไพล์ครับ ในกรณีของ gcc คือ -fmpx
lewcpe.com, @wasonliw
อาจจะใช้ตอนทดสอบหาบั๊ก แล้วปิดในโปรแกรมรุ่นที่ใช้งานจริงก็ได้
หรือจะทำให้ผู้ใช้เลือกเปิดปิดได้ในโปรแกรมรุ่นที่ใช้งานจริงก็ได้
จะตาราง ?