วิธีรวบรวมคอมไพเลอร์ C ตั้งแต่เริ่มต้นจากนั้นคอมไพล์ Unix / Linux จากศูนย์


64

สมมติว่าฉันทำงานให้กับองค์กรบริการขนาดใหญ่นอกสหรัฐอเมริกา / สหราชอาณาจักร เราใช้เซิร์ฟเวอร์ UNIX และ Linux อย่างกว้างขวาง

การอ่านบทความนี้ระบุว่าเป็นการง่ายที่จะแทรกแบ็คดอร์ในคอมไพเลอร์ C จากนั้นโค้ดใด ๆ ที่คอมไพล์ด้วยคอมไพเลอร์นั้นจะมีแบ็คดอร์ จากการรั่วไหลเมื่อเร็ว ๆ นี้เกี่ยวกับคำสั่งของ NSA / GCHQ ที่จะทำให้แบ็คดอร์ / จุดอ่อนในวิธีการเข้ารหัสฮาร์ดแวร์และซอฟต์แวร์ทั้งหมดคอมไพเลอร์กลายเป็นจุดสำคัญของความล้มเหลว ศักยภาพการกระจาย UNIX / Linix มาตรฐานทั้งหมดอาจถูกบุกรุก เราไม่สามารถที่จะมีระบบข้อมูลและข้อมูลลูกค้าของเราที่ถูกโจมตีโดยรัฐบาลโกง

รับข้อมูลนี้ฉันต้องการสร้างคอมไพเลอร์ที่เชื่อถือได้ตั้งแต่เริ่มต้นแล้วฉันมีฐานที่ปลอดภัยในการสร้างดังนั้นฉันจึงสามารถสร้างระบบปฏิบัติการและแอปพลิเคชันจากซอร์สโค้ดโดยใช้คอมไพเลอร์นั้น

คำถาม

อะไรคือวิธีที่ถูกต้อง (และปลอดภัย) ในการรวบรวมคอมไพเลอร์จากซอร์สโค้ด (สถานการณ์ไก่ไข่ที่ดูเหมือน) แล้วรวบรวมการแจกจ่าย Unix / Linux ที่เชื่อถือได้ตั้งแต่เริ่มต้น?

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

สแต็กการรักษาความปลอดภัยจะต้องเริ่มต้นที่ระดับฐานหากเรามั่นใจในระบบปฏิบัติการหรือแอพพลิเคชั่นที่ทำงานบนสแต็กนั้น ใช่ฉันเข้าใจว่าอาจมีฮาร์ดแวร์ด้านหลังซึ่งอาจแทรกไมโครโค้ดบางส่วนลงในคอมไพเลอร์เมื่อสร้างขึ้น ไม่มากที่เราสามารถทำได้เกี่ยวกับเรื่องนี้ในขณะนั้นยกเว้นอาจใช้ชิปที่ไม่ได้ออกแบบในสหรัฐอเมริกา มาจัดเรียงเลเยอร์นี้เพื่อเริ่มต้นและสมมติว่าฉันสามารถสร้างมันบนคอมพิวเตอร์เครื่องเก่าก่อนที่จะแทรกแบ็คดอร์ใดก็ได้

ดังที่บรูชชไนเออร์พูดว่า: "สำหรับวิศวกรฉันพูดแบบนี้: เราสร้างอินเทอร์เน็ตและพวกเราบางคนช่วยในการล้มล้างตอนนี้พวกเราที่รักเสรีภาพต้องแก้ไขมัน"

ลิงก์พิเศษ:


7
ประณามนี่เป็นคำถามที่น่าสนใจมากและฉันไม่ต้องการย้ายมัน แต่ฉันไม่คิดว่ามันอยู่ในหัวข้อที่นี่ stackoverflow.com ได้ดีกว่าเนื่องจากคำถามพื้นฐานของคุณเกี่ยวกับวิธีการรวบรวมคอมไพเลอร์ตั้งแต่เริ่มต้นซึ่งเป็นระบบปฏิบัติการที่ไม่เชื่อเรื่องพระเจ้าและเป็นคำถามในการเขียนโปรแกรม หากคุณไม่ได้รับคำตอบที่นี่หลังจากผ่านไปสักครู่ลองใช้ลิงก์ "ตั้งค่าสถานะ" ใต้แท็กคำถามของคุณและขอให้ผู้ดำเนินรายการย้ายไปที่ SO
terdon

2
@terdon จริง ๆ แล้วมันอาจจะเหมาะกว่าสำหรับโปรแกรมเมอร์เพราะมันเกี่ยวกับปัญหาการเขียนโปรแกรมทั่วไปมากกว่าปัญหาการพัฒนาที่เฉพาะเจาะจง ในความเป็นจริงมันอาจจะเป็นที่ซ้ำกันมี
CVn

2
GCC เป็นโอเพ่นซอร์สมีการแทรกลับๆอย่างไร?
Michael Pankov

2
โปรดจำไว้ว่าช่องโหว่ของ Thompson ที่มีความเสถียรนั้นต้องใช้รหัสที่สามารถรับรู้ได้เมื่อมีการคอมไพล์โปรแกรมล็อกอินหรือคอมไพเลอร์ หากคุณสามารถแปลงแหล่งที่มาเป็นรูปแบบที่ไม่รู้จักคอมไพเลอร์ด้วยตนเองเป็นหนึ่งในโปรแกรมเหล่านั้นแบ็คดอร์จะไม่ถูกเผยแพร่
Russell Borogove

2
@Constantius - อ่านบทความ Thompson ที่ลิงก์ในบรรทัดแรก ใครเป็นผู้รวบรวมคอมไพเลอร์?
Russell Borogove

คำตอบ:


30

AFAIK วิธีเดียวที่จะมั่นใจในความปลอดภัยอย่างสมบูรณ์คือการเขียนคอมไพเลอร์ในภาษาแอสเซมบลี (หรือแก้ไขดิสก์โดยตรงด้วยตนเอง ) จากนั้นคุณสามารถมั่นใจได้ว่าคอมไพเลอร์ของคุณไม่ได้แทรกลับๆ - นี่เป็นเพราะคุณกำจัดคอมไพเลอร์จริง ๆ

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

โปรดทราบว่าเพื่อให้สิ่งต่าง ๆ ง่ายขึ้นกับตัวคุณเองคุณอาจมีผู้แปลตัวกลางคนที่สองเขียนเป็น C (หรือภาษาอื่น ๆ ) ดังนั้นคุณจะเขียนคอมไพเลอร์ A ในแอสเซมบลีจากนั้นเขียนคอมไพเลอร์นั้นใน C / C ++ / Python / Brainfuck / อะไรก็ตามที่จะได้รับคอมไพเลอร์ B ซึ่งคุณจะคอมไพล์โดยใช้คอมไพเลอร์ A จากนั้นคุณจะใช้คอมไพเลอร์


13
ถึงกระนั้นก็ตามสิ่งนี้ยังคงป้องกันจากคอมไพเลอร์ที่เป็นอันตรายเท่านั้น คุณยังต้องเชื่อมั่นในระบบที่คอมไพเลอร์ดำเนินการ ไม่มีการแยกซอฟต์แวร์
CVn

3
สิ่งใด ๆ ที่เป็นอิสระมีอันตรายโดยกำเนิด คุณกำลังเสนอคอมไพเลอร์ toolchain อย่างมีประสิทธิภาพ (แม้ว่าจะแปลก) ซึ่งหมายความว่ามันสามารถแก้ไขได้ในแบบที่คุณพยายามหลีกเลี่ยง ยิ่งไปกว่านั้นมันสามารถแก้ไขได้ในระหว่างทางผ่าน MitM
strugee

1
พวกคุณต้องรู้ว่าคำตอบนี้มาจากอายุ 15 ปี ไปต่อไป!
mtahmed

3
หนึ่งไม่ควรลืมที่จะเขียนโปรแกรมแก้ไขโค้ดตั้งแต่ต้น - ใครจะรู้ว่า <code> vim </code> ที่คอมไพล์แล้วหรือ <code> vim </code> ที่คุณคอมไพล์คอมไพล์เลอร์ของคุณจากแหล่งที่คุณตรวจสอบแล้วโดยใช้เชื้อ <code> vim </code> เชื่อถือได้หรือไม่
Hagen von Eitzen

1
อย่าลืมว่าเว้นแต่คุณจะเขียนรหัสเครื่องแรก (ไม่ใช่การประกอบรหัสเครื่องจริง) และคุณเป็นผู้เชี่ยวชาญในการรับรู้ช่องโหว่ด้านความปลอดภัยและอ่านและตรวจสอบรหัสทุกบรรทัดที่คุณกำลังรวบรวม ... หรืออย่างน้อยก็รู้ คนที่ทำอย่างนั้นเอง , และไว้วางใจให้เขาทำเช่นนี้ ... สิ่งนี้จะไม่ช่วยอะไรเลย นั่นเป็นเหตุผลที่พยายามที่จะ Kickstarter นี้ทำลายจุดทั้งหมด ซึ่งคือ: ความน่าเชื่อถือสูง
Evi1M4chine

22

วิธีหนึ่งที่เป็นไปได้แม้ว่ามันจะใช้เวลานานมากในการฝึกฝน แต่กลับไปที่ราก การพัฒนา GNU เริ่มขึ้นในปี 1984 และ Minix รุ่นดั้งเดิม (ซึ่งใช้ในระหว่างการพัฒนา Linux ต้นเพื่อการทำ bootstrapping) ได้เปิดตัวในปี 1987

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

หากคุณสามารถหาสำเนาของหนังสือ Minix ต้นฉบับพร้อมด้วยรหัสต้นฉบับคุณสามารถพิมพ์จากหนังสือ คอมไพล์มันและจากนั้นใช้ decompiler ที่แตกต่างกันบนระบบที่แตกต่างกันเพื่อตรวจสอบว่าคอมไพเลอร์สร้างเอาต์พุตภาษาไบนารีของเครื่องที่คาดไว้ (รหัสนี้มีเพียง 12,000 บรรทัด, สันนิษฐานว่า C, การทำเช่นนั้นใช้เวลานาน แต่ยังคงมีเหตุผลหากคุณจริงจังเกี่ยวกับโครงการดังกล่าว) คุณยังสามารถเขียน disassembler ของคุณเองได้; ที่ไม่ควรยากมาก

คว้ายูทิลิตี้ GNU รุ่นเก่าที่สุดที่คุณสามารถใช้ (เป็นเพราะสันนิษฐานว่ามีรหัสน้อยกว่าและพึ่งพาไลบรารีภายนอกน้อยกว่า), อ่านโค้ด, สร้างมันสำหรับ Minix (สิ่งนี้อาจใช้งานได้บ้าง; ต้องการหลีกเลี่ยงอย่างยิ่งคือการปรับเปลี่ยนซอร์สโค้ดเนื่องจากจะทำให้การเพิ่มแพตช์ในภายหลังเกิดข้อผิดพลาดได้ง่ายมาก) และผ่านรอบการตรวจสอบถอดแยกชิ้นส่วนที่คล้ายกันสำหรับเครื่องมือ GNU ณ จุดนี้คุณวางใจระบบปฏิบัติการและ toolchain ดังนั้นคุณจะต้องผ่านซอร์สโค้ดใน patchset เท่านั้น (สิ่งที่ไม่ได้อยู่ใน patchset นั้นเชื่อถือได้แล้ว) แต่เครื่องมือจะยังคงดั้งเดิมและหยาบเมื่อเทียบกับสิ่งที่คุณใช้ ถึงวันนี้ อย่าคาดหวังอะไรมากไปกว่าฟังก์ชั่นพื้นฐานของเครื่องมือระบบที่ใช้งานได้ตัวอย่างเช่นอ่าน XKCD มากมาย

ในบางจุดคุณจะมีระบบที่สามารถรวบรวมและ bootstrap เคอร์เนลรุ่นแรก ๆ ของ Linux ได้เหมือนกับที่ทำในต้นปี 1990 เมื่อ Linux เริ่มรับแรงฉุดจากแฮกเกอร์ ฉันขอแนะนำให้โยกย้ายไปยัง Linux ในจุดนั้น (สร้างไลบรารีระบบและ toolchain กับ Linux, สร้างเคอร์เนล Linux, บูตเข้าสู่ Linux และอาจสร้างเคอร์เนล Linux และ GNU toolchain ภายใน Linux อีกครั้งสุดท้ายพิสูจน์ว่าตอนนี้ระบบเป็นของตัวเองแล้ว โฮสติ้ง) แต่นั่นขึ้นอยู่กับคุณเป็นส่วนใหญ่ ทำการตรวจสอบแพตช์การแก้ไขเคอร์เนลไลบรารีและเครื่องมือ GNU พื้นฐานและสร้างใหม่จนกว่าคุณจะได้รับเวอร์ชันที่ทันสมัย

นั่นคือเมื่อคุณมีระบบปฏิบัติการพื้นฐานและคอมไพเลอร์ที่เชื่อถือได้ซึ่งสามารถใช้ในการสร้างซอฟต์แวร์ที่ทันสมัย จากนั้นคุณสามารถทำตามเช่นคู่มือLinux ตั้งแต่เริ่มต้นเพื่อสร้างระบบที่สามารถทำงานที่มีประโยชน์ได้

ไม่มีจุดใดที่ระบบ "คอมไพเลอร์" สามารถเชื่อมต่อกับเครือข่ายได้ทุกทาง (รวมถึงเป็น VM บนโฮสต์เครือข่าย); คุณอาจเสี่ยงต่อการเจาะผ่านองค์ประกอบที่รองรับเครือข่ายรวมถึงเคอร์เนล หากคุณกังวลเกี่ยวกับการโจมตีของคอมไพเลอร์ Thompsonคุณต้องคาดหวังว่าโฮสต์ VM ใด ๆ ก็อาจถูกโจมตีเช่นกัน ใช้ sneakernet เพื่อรับซอร์สโค้ดและไบนารีจากฟิสิคัลโฮสต์ที่คุณกำลังรวบรวมสิ่งต่าง ๆ คาดว่าจะมีปัญหาในการเปิดและปิดระบบไฟล์อย่างน้อยก่อนที่จะถึงจุดที่รองรับการใช้งานที่เก็บข้อมูล USB จำนวนมาก หากคุณมีความหวาดระแวงจริงๆแหล่งที่มาการพิมพ์รายชื่อรหัสและพิมพ์ด้วยมือ (และหวังว่าคนขับเครื่องพิมพ์และไม่ได้มีรหัสที่คล้ายกันในพวกเขา) หรืออ่านรหัสบนหน้าจอคอมพิวเตอร์เครื่องหนึ่งแล้วพิมพ์ลงในคอมพิวเตอร์อีกเครื่องที่อยู่ติดกัน แต่ไม่ได้เชื่อมต่อ

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


วิธีการตรวจสอบความถูกต้องของ dissassemble นั้นมีข้อบกพร่องอย่างมากเนื่องจากยังคงมีข้อสันนิษฐานอย่างมากว่าเครื่องตรวจสอบนั้นน่าเชื่อถืออย่างเต็มที่ หากคุณไม่ได้สร้างเครื่องจักรและซอฟต์แวร์ของมันเองตั้งแต่เริ่มต้นหรือรู้ว่าคนที่ทำเองและไว้ใจเธอจะไม่เกิดขึ้น ดังนั้นนี่ยังไม่ปลอดภัย ขอโทษ ……นอกจากนี้ในเรื่องเหล่านี้“ ใกล้เคียงกับ…” ยังคงหมายถึง“ ไม่ปลอดภัย” เนื่องจากต้องการเพียงจุดเดียวที่ไม่น่าเชื่อถือเพียงแห่งเดียวที่จะทำลายจุดทั้งหมด
Evi1M4chine

9

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


1
ทุกคนต้องการคอมไพเลอร์ที่เชื่อถือได้ คณิตศาสตร์ทำงานอย่างไรที่พวกเขาสามารถสร้างคอมไพเลอร์ "ที่เชื่อถือได้" ได้
David J

@DavidJ Bootstrapping เป็นไปได้มากที่สุด สร้างชิ้นส่วนเล็ก ๆ ที่คุณสามารถตรวจสอบและพิสูจน์ได้อย่างถูกต้องจากนั้นใช้เป็นพื้นฐานในการสร้างคอมไพเลอร์ที่ซับซ้อนมากขึ้น
CVn

1
"" "สิ่งที่ชุด CompCert C นอกเหนือจากคอมไพเลอร์การผลิตอื่น ๆ ก็คือว่ามันมีการยืนยันอย่างเป็นทางการโดยใช้เครื่องช่วยพิสูจน์ทางคณิตศาสตร์ที่จะได้รับการยกเว้นจากปัญหา miscompilation." "" compcert.inria.fr/compcert-C.html รวบรวม ไม่ใช่เชิงประจักษ์อย่างที่มันเคยเป็น
lgeorget

1
@ MichaelKjörlingที่อาจไม่คำนึงถึงว่าเคอร์เนลอาจถูกบุกรุกเพื่อรวมแบ็คดอร์เข้าไปในแหล่งคอมไพเลอร์เมื่ออ่านโดยคอมไพเลอร์
ratchet freak

1
ฉันพบลิงค์นี้ซึ่งสามารถใช้งานได้เช่นกัน
David J

2

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


5
การโจมตีดังกล่าวได้รับการเปิดเผยสู่สาธารณะตั้งแต่ปี 1984สมมุติว่า Thompson ไม่ใช่คนแรกที่คิดถึงความเป็นไปได้ การย้อนกลับไปไกลหมายความว่าทุกสิ่งที่เราทำในวันนี้ไม่ได้อยู่ใกล้ ๆ พิจารณาว่าคอมพิวเตอร์มีความสามารถในการทำอะไรเมื่อ 20 ปีก่อนและเปรียบเทียบกับสถานะปัจจุบันของคอมพิวเตอร์ แม้แต่ระบบบูตสแตรปลินุกซ์ดั้งเดิมMinix ก็ยังไม่ออกจนกระทั่ง '87และการพัฒนา GNU เริ่มต้นในปี '84 ดังนั้นในทางทฤษฎีแล้วสิ่งนี้อาจตอบคำถาม แต่ในทางปฏิบัติมันไม่มีประโยชน์เป็นคำตอบ
CVn

2
คอมพิวเตอร์เครื่องแรกสุดที่ฉันสามารถจับได้คือ 286 ฉันจะต้องดูว่าปู่ย่าตายายของฉันยังมีอยู่หรือเปล่า
David J

1
คะแนนโบนัสสำหรับการพิจารณาจริง ๆ ว่า :-) @DavidJ
11684

@ MichaelKjörling: ไม่จริงหรอก เพราะมันจะทำให้สายการบูตสแตรปของคุณยาวขึ้นเท่านั้น แต่อาจไม่นานเท่ากับการเขียนคอมไพเลอร์ของคุณเองตั้งแต่เริ่มต้นเป็นภาษาเครื่อง
Evi1M4chine
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.