เป็นไปได้ไหมที่จะอ่านหน่วยความจำจากโปรแกรมอื่นโดยการจัดสรรพื้นที่ว่างทั้งหมดบนระบบ?


26

ในทางทฤษฎีถ้าฉันจะสร้างโปรแกรมที่จัดสรรหน่วยความจำที่ไม่ได้ใช้ทั้งหมดในระบบและยังคงร้องขอหน่วยความจำมากขึ้นเรื่อย ๆ เนื่องจากแอปพลิเคชันอื่น ๆ ปล่อยหน่วยความจำที่พวกเขาไม่ต้องการอีกต่อไป ? หรือระบบนี้ได้รับการปกป้องด้วยระบบปฏิบัติการสมัยใหม่หรือไม่?

ฉันไม่มีแอปพลิเคชันที่ใช้งานได้สำหรับสิ่งนี้ฉันแค่อยากรู้ ฉันรู้ว่ามีปัญหาบางอย่างในการจัดสรร "หน่วยความจำที่มีอยู่ทั้งหมด" ในชีวิตจริง

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

คำตอบ:


23

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

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

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

ไม่มีผลกระทบด้านความปลอดภัยสำหรับการmalloc()ไม่เริ่มต้นหน่วยความจำเพราะสิ่งที่ได้รับผ่านbrk()จะถูกขัดและสิ่งที่ก่อนหน้านี้free()จะถูกเขียนโดยกระบวนการเดียวกัน


19

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


1
"ใช่ แต่ไม่ใช่" คือ "ไม่" @Blrfl ถูกต้องแล้ว
Ross Patterson

4
@ RossPatterson: ณ จุดทางทฤษฎีแล้ว Karl มีความถูกต้องมากกว่าที่ฉันเป็น ความจริงที่ใช้งานได้ก็คือระบบปฏิบัติการหลักปิดตัวลงเมื่อหลายปีก่อน
Blrfl

@Blrfl เข้าใจ แต่ "ปีก่อน" อยู่ในช่วงปลายทศวรรษ 1960 เมื่อมีการนำระบบเพจและหน่วยความจำเสมือนมาใช้เป็นครั้งแรก แน่นอนตามเวลาของ Multics, VM / 370 และ OS / VS ไม่มีข้อบกพร่องนี่เป็นไปไม่ได้ในความทรงจำของโปรแกรมเมอร์ผู้ฝึกหัดส่วนใหญ่
Ross Patterson

The reason you don't always see zeroed out memory is because it is more efficient not to zero out the memory if it was previously allocated by the same process ฉันเห็นความไม่ลงรอยกันที่นี่ คุณหมายถึง "executable เดียวกัน" หรือไม่ มีการตรวจสอบอย่างไรว่าจะไม่เป็นศูนย์โดยทางของดิสก์
jakub.g

1
ฉันคิดว่าฉันขาดอะไรไป ทำไมเมื่อฉันคอมไพล์และรันบางโปรแกรม C ++ ด้วย, พูดว่า, เลขจำนวนเต็มไม่เริ่ม, พวกมันไม่เท่ากับ 0 เมื่อฉันอ่านตัวแปรเหล่านั้น?
jakub.g

2

มีหลายเลเยอร์ที่เกี่ยวข้องที่นี่ซึ่งส่งผลต่อคำตอบ

หากคุณถือว่าระบบปฏิบัติการหน่วยความจำเสมือนที่ทันสมัยคุณจะไม่สามารถเห็นส่วนที่เหลือของข้อมูลกระบวนการอื่นในหน้าเว็บที่คุณจัดสรร

เมื่อกระบวนการถูกโหลดครั้งแรกตารางหน้าจะถูกโหลดและอาจมีการจัดสรรเฟรมของหน่วยความจำจริงไปยังหน้าเหล่านั้น อย่างน้อยที่สุดตารางหน้าหรือตารางเสริมจะมีแผนที่ของหน่วยความจำทั้งหมดที่กระบวนการสามารถจัดสรรได้ นี่ก็เป็นจุดเริ่มต้นของการแบ่งกระบวนการเริ่มต้นตามที่กล่าวไว้ข้างต้น

ในขณะที่ malloc () อาจหากอนุญาตให้กระบวนการทำให้ตัวแบ่งกระบวนการเปลี่ยนแปลงเพิ่มหน้าเพิ่มเติมให้กับหน้ากระบวนการ (หน้าเพิ่มเติม) ตารางเพื่อตอบสนองคำขอสถานที่ที่กระบวนการหนึ่งอาจ "รับอีก" กระบวนการข้อมูลอยู่ที่ เลเยอร์หน่วยความจำจริงที่ต่ำกว่า

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

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

สิ่งนี้ทำให้มันค่อนข้างไม่เกี่ยวข้องเลยหากหน่วยความจำกระบวนการอื่น ๆ นั้น "ปล่อย" หรือไม่ กระบวนการอื่น ๆ หน่วยความจำ "ปล่อย" ยังคงอยู่ในหน้าที่ได้รับมอบหมายให้กระบวนการนั้นและมักจะไม่ได้รับการแมปจนกว่ากระบวนการจะจบลงเพราะพวกเขาจะได้รับการสลับออกเมื่อหน่วยความจำเหลือน้อยหรือถูกขับไล่ malloc () และ free () จัดการหน่วยความจำเสมือนที่กำหนดให้กับกระบวนการในระดับ (ผู้ใช้)

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

ทั้งหมดนี้เป็น moot ในระบบเช่น MS-DOS MS-DOS (และระบบอื่น ๆ ที่ง่ายกว่า) ไม่ใช้หน่วยความจำเสมือน (ด้วยตนเอง) และคุณสามารถกระตุ้นและแย่งข้อมูล "กระบวนการ" อื่นได้อย่างง่ายดาย

การอ้างอิงที่ดีบางอย่างที่อาจเข้าใจได้ง่ายกว่าซอร์สโค้ด Linux อาจเป็นหนังสือระบบปฏิบัติการที่ดีแนวคิดระบบปฏิบัติการโดย Silberscatz, Gavin และ Gange หรือการออกแบบระบบปฏิบัติการโดย Andrew Tanenbaum บางสิ่งเช่น Nachos จาก Berkeley หรือ Pintos จาก Stanford เป็นระบบปฏิบัติการขนาดเล็กที่สร้างขึ้นเพื่อการเรียนรู้และมีความคิดเดียวกันนี้อยู่ภายใน


0

ฉันลองสิ่งนี้บน Ubuntu เมื่อ 16.04 เดือนก่อน เช่นเดียวกับที่ 0xACE กล่าวว่าระบบปฏิบัติการที่ทันสมัยจะจัดสรรหน้าเสมือนจริงทั้งหมดเป็นศูนย์เมื่อคุณเรียก malloc () แต่ถ้าคุณไม่เขียนอะไรลงในบัฟเฟอร์ที่จัดสรรมันจะไม่ถูกแมปไปยังหน่วยความจำกายภาพ (นั่นคือหลักการคัดลอกเมื่อเขียน) ดังนั้นคุณจะต้องอ่านค่าศูนย์จากบล็อก "ไม่กำหนดค่าเริ่มต้น" อาจมีระบบปฏิบัติการฝังตัวบางตัวที่คอมไพล์ด้วยตัวเลือก "CONFIG_MMAP_ALLOW_UNITIALIZED" เพื่อประสิทธิภาพที่ดีขึ้นในกรณีนี้คุณสามารถรับสิ่งที่คุณคาดหวังได้


-1

ไม่มีนี้จะไม่อนุญาตให้โปรแกรมอ่านอื่นอีกขอบคุณหน่วยความจำเพื่อความมหัศจรรย์ของเพจ ด้วยวิธีนี้การใช้หน่วยความจำทั้งหมดสามารถเกิน ram ทางกายภาพโดยการถ่ายชิ้นส่วนของมันไปยังฮาร์ดไดรฟ์

นอกจากนี้หน่วยความจำสูงสุดที่กระบวนการสามารถจัดสรรได้นั้นถูก จำกัด โดยระบบปฏิบัติการ (สูงสุด 4 กิ๊กสำหรับสถาปัตยกรรม 32 บิต) หลังจากนั้นการallocเรียกครั้งต่อไปจะส่งคืนข้อผิดพลาดหน่วยความจำไม่เพียงพอ


ไม่มี API เฉพาะแพลตฟอร์มที่สามารถหลีกเลี่ยงปัญหานี้ได้หรือ ฉันไม่รู้จริงๆ แต่ฉันจะไม่แปลกใจ (ตัวอย่างเช่น Linux อนุญาตให้ระบบปฏิบัติการไม่ให้ย้ายหน้าออกจากหน่วยความจำกายภาพผ่านmlock)

หากมี RAM 4 GB และการแบ่งหน้า จำกัด อยู่ที่ 8 GB จะเกิดอะไรขึ้นถ้าแอปพลิเคชันร้องขอ 12 GB (บน x64)
Arseni Mourzenko

จากนั้นการเรียกของระบบควรส่งคืนข้อผิดพลาดเมื่อหน่วยความจำว่างเหลือน้อยเกินไปหรือมิฉะนั้นคอมพิวเตอร์จะหยุดชะงักเมื่อไม่มีสิ่งใดเหลืออยู่ ...
ratchet freak

4
เขาไม่ได้ถามเกี่ยวกับการอ่านความทรงจำของผู้อื่น แต่ควรอ่านความทรงจำที่ปล่อยออกมาของพวกเขา ส่วนของ ram ในขณะนี้นั้นว่างและ .... ฉันไม่คิดว่า ... โครงร่างการเพจนั้นจะไม่มีหน่วยความจำเหลือหลังจากที่มันว่าง ดังนั้นโปรแกรมจะจัดสรรบล็อกของหน่วยความจำและวิเคราะห์ข้อมูลที่ไม่ได้กำหนดค่าเริ่มต้นที่มีอยู่แล้ว
Philip

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