เหตุใดแหล่งข้อมูลของ Bash จึงไม่ต้องการบิตการประมวลผล


57

ด้วย Bash sourceคุณสามารถรันสคริปต์โดยไม่ต้องตั้งค่าบิตเรียกใช้งาน นี่เป็นเอกสารและมีพฤติกรรมที่คาดหวัง แต่สิ่งนี้ไม่ได้เกิดจากการใช้งานบิตการดำเนินการใช่หรือไม่

ฉันรู้ว่านั่นsourceไม่ได้สร้าง subshell


2
ความจริงที่chmodสามารถให้คุณตั้งค่าการอนุญาต (รวมถึง `x) ด้วยหมายเลขฐานแปดให้เบาะแสกับยุคที่มา ผมจะไม่แปลกใจถ้ามันเริ่มเป็นรวดเร็วและสกปรก "นี้เป็นแฟ้มไบนารีคุณสามารถดำเนินการ" ตัวบ่งชี้จากวันก่อนที่เธอจะปังถูกคิดค้น แต่ฉันไม่มีหลักฐานว่า
infixed

9
จากนั้นอีกครั้งเมื่อ SUID เข้าสู่การเล่นระดับการป้องกันที่แตกต่างกันสำหรับผู้ใช้ประเภทต่างๆจะมีความสำคัญมากขึ้น ไปข้างหน้าและอ่านโปรแกรม SUID ของฉันหากคุณต้องการ แต่ถ้าคุณรันมันผ่านเพียงแค่อ่านมันอำนาจ SUID จะไม่ได้มาพร้อมกับมัน
infixed

@infixed โปรแกรมโหลดเดอร์ของ Linux ไม่แม้แต่จะมองไปที่ shebang เว้นเสียแต่ว่าจะตั้งบิตการทำงานไว้ (หากต้องการตุ๊ดฮอร์นของฉันสักหน่อย: ดูที่นี่ )
Kyle Strand

นอกจากนี้คุณยังสามารถมี + xr ได้ แต่มันก็ค่อนข้างแปลกเพราะปกติแล้วมันเป็นไปได้ที่จะอ่านไบนารีโดยการฉีดโค้ดเข้าสู่กระบวนการที่กำลังทำงานอยู่
Niklas B.

@KyleStrand โดย "ถ้าคุณดำเนินการได้ผ่านเพียงแค่อ่านมันอำนาจ SUID จะไม่ได้มาพร้อมกับมัน" ผมวาดภาพสิ่งที่ตามสายของcp /sbin/suidexecutable /tmp/mycopy; /tmp/mycopy
infixed

คำตอบ:


36

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

สิ่งที่สนใจเกี่ยวกับบิตที่เรียกใช้งานได้คือเคอร์เนลระบบปฏิบัติการ execตัวอย่างเช่นเมื่อเคอร์เนล Linux ทำการตรวจสอบว่าระบบไฟล์ไม่ได้ประกอบเข้ากับnoexecตัวเลือกมันจะตรวจสอบบิตของไฟล์โปรแกรมที่ใช้งานได้และบังคับใช้ข้อกำหนดใด ๆ ที่กำหนดโดยโมดูลความปลอดภัย (เช่น SELinux หรือ AppArmor)

โปรดทราบว่าบิตที่เรียกใช้งานได้นั้นค่อนข้างควบคุมได้ตามความต้องการ ตัวอย่างเช่นบนระบบ Linux x86-64 คุณสามารถข้ามการตรวจสอบความถูกต้องของเคอร์เนลของบิตเรียกทำงานโดยเรียกใช้งาน/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2เป็นล่ามอย่างชัดเจน :

cp /bin/ls /tmp/
chmod -x /tmp/ls
/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2 /tmp/ls

นี่ค่อนข้างคล้ายกับการจัดหาซอร์สโค้ด Bash ใน Bash ยกเว้นว่าld.soเป็นล่ามและรหัสที่ดำเนินการนั้นคือรหัสเครื่องในรูปแบบ ELF


3
การใช้โหลดเดอร์เป็น "ล่าม" ของ "bytecode" ที่เพิ่งเกิดขึ้นเป็นไบนารีที่ปฏิบัติการได้จริง ..... ยอดเยี่ยม ขอบคุณสำหรับสิ่งนั้น.
Kyle Strand

@ KyleStrand อาจมีหลายระดับทางอ้อม (ความแตกต่างระหว่างโปรแกรมที่จัดเก็บและขั้นตอนการโหลดและวิธีการแมปหน่วยความจำ, ผู้บังคับบัญชาต่างๆ, VMs, ฯลฯ ) แต่โดยหลักการแล้วรหัสเครื่องสามารถประมวลผลโดย CPU โดยตรง (ไม่มีไมโครโค้ด ฯลฯ ) และดังนั้นจึงไม่สามารถตีความรหัสเครื่องได้: ฮาร์ดแวร์เข้าใจว่าเป็น - เป็นภาษาพื้นเมือง - ไม่จำเป็นต้องใช้ล่าม
jfs

2
@JFSebastian ใช่เรารู้ว่ามันเป็นรหัสเนทีฟดังนั้น "interpreter" จึงอยู่ในเครื่องหมายคำพูด งานของld.soคือการทำการเชื่อมโยงแบบไดนามิก
200_success

@JFSebastian อะไรที่ 200_success พูด นอกจากนี้นั่นคือสิ่งที่ฉันหมายถึงโดย "ไบนารีปฏิบัติการจริง" และฉันยังใส่ "bytecode" ในเครื่องหมายคำพูด (เนื่องจาก AFAIK "bytecode" โดยทั่วไปแล้วจะไม่ใช้เพื่ออ้างถึงรหัสไบนารีจริงที่รวบรวมได้จริง) นอกจากนี้ชื่อผู้ใช้ที่ดี
Kyle Strand

@JFSebastian ฉันเชื่อว่าซีพียู x86 ที่เหมือนกันในปัจจุบันนั้นเป็นจริงของ RISC โดยมีชุดคำสั่ง CISC แบบเก่าโดยพื้นฐานแล้วทำให้เกิดการประมวลผลไมโครโค้ดของคำสั่ง RISC ที่สอดคล้องกันซึ่งคำสั่ง CISC เพียงคำสั่งเดียว ดังนั้นในแง่การเรียกสิ่งที่ CPU ทำกับรหัสเครื่อง RISC "การตีความ" คือถ้าไม่ถูกต้องอย่างสมบูรณ์จากมุมมองทางเทคนิคแล้วอย่างน้อยรูปแบบจิตที่ถูกต้อง AES-NIน่าจะเป็นอีกตัวอย่างหนึ่งที่สุดโต่ง: คำสั่ง CISC หนึ่งคำสั่งต่อ AES รอบ!
CVn

57

sourceหรือเทียบเท่า แต่มาตรฐานdot.ไม่รันสคริปต์ แต่อ่านคำสั่งจากไฟล์สคริปต์แล้วรันพวกเขาทีละบรรทัดในสภาพแวดล้อมเปลือกปัจจุบัน

ไม่มีอะไรที่ต่อต้านการใช้บิตการดำเนินการเป็นเพราะเปลือกเท่านั้นจำเป็นต้องอ่านสิทธิ์ในการอ่านเนื้อหาของแฟ้ม

ต้องใช้บิตการดำเนินการเฉพาะเมื่อคุณเรียกใช้สคริปต์ ที่นี่เชลล์จะfork()ประมวลผลใหม่จากนั้นใช้execve()ฟังก์ชั่นเพื่อสร้างอิมเมจกระบวนการใหม่จากสคริปต์ซึ่งจำเป็นต้องเป็นไฟล์ปฏิบัติการปกติ


5
@alexis: ฉันไม่แน่ใจว่าฉันทำตามจริงๆ ถ้าคุณทำคุณจะได้รับเป็นหลักผลเช่นเดียวกับbash < script source scriptการตรวจสอบบิตเรียกใช้งานการป้องกันอะไรให้
Compiler ที่เห็นได้ชัดเจน

27
@alexis ไม่ใช่หน้าที่ของล่ามในการตรวจสอบสิทธิ์ของสคริปต์ที่ล่าม ไม่มีอะไรที่ทำอย่างนี้ - ไม่หลามไม่ทับทิมไม่ Java เครื่องเสมือนเปลือกหอยสุ่มไม่ได้อื่น ๆ บิตเรียกใช้งานจะควบคุมว่าexecvตระกูล syscalls OS * สามารถใช้กับปฏิบัติการได้หรือไม่ไม่ว่าจะใช้ล่ามหรือไม่ ทำไมคนสับสน (และทำลายความสามารถในการประเมินสตรีมโค้ดจากแหล่งที่ไม่ใช่ไฟล์) โดยการทำลายอนุสัญญา?
Charles Duffy

14
@alexis, ... ยิ่งไปกว่านั้นมันมีความหมายที่มีคุณค่าในการใช้เชลล์ไลบรารี่ที่ไม่สามารถเรียกใช้งานได้: มันบอกว่า "ฉันเป็นไลบรารี่, ไม่ใช่คำสั่ง - ส่งถึงฉัน, อย่าเอ็กซีคิวต์" มิฉะนั้นคุณจะต้องเขียนโค้ดเพื่อตรวจจับและแก้ไขการใช้รหัสผิดวัตถุประสงค์เพื่อให้ได้มา แต่โดยไม่ได้รับสิทธิ์ + x คุณสามารถมั่นใจได้ว่าผู้ใช้จะไม่สามารถ (ไม่) ใช้ห้องสมุดในทางที่ผิด
ชาร์ลส์ดัฟฟี่

6
@alexis "เป็นการตัดสินใจของผู้แต่ง" เฉพาะในแง่ที่ว่าทุก ๆ ชิ้นที่เป็นไปได้ที่ไม่ได้รวมอยู่นั้นคือการตัดสินใจ เชลล์เปิดไฟล์สำหรับอ่านเพื่ออ่านคำสั่งจากนั้น ฉันไม่คาดหวังให้ตรวจสอบสิทธิ์การอ่านมันแค่พยายามเปิดไฟล์และล้มเหลวหากไม่สามารถทำได้ ในทำนองเดียวกันมันจะไม่ตรวจสอบการเขียนหรือการอนุญาตเนื่องจากการตรวจสอบเหล่านั้นไม่เกี่ยวข้องกับการอ่านไฟล์
Randy Orrison

2
@alexis สิ่งนี้ถูกใช้ในทางปฏิบัติเช่นในกรณีของ virtualenv ของ python สคริปต์เพื่อเปิดใช้งานนั้นมีจุดประสงค์เพื่อให้มีแหล่งที่มาและไม่ถูกเรียกใช้และจึงbin/activateไม่มีบิตที่เรียกใช้งานได้ สคริปต์ทั้งหมดอาจเป็นห้องสมุดหรือสิ่งอื่น ๆ เช่นนั้น ผมคิดว่ามี .sh อาจจะมีสัญญาณเช่นกัน แต่มีขั้นต่ำของเท้าปืนเป็นสิ่งที่ดี: มันเป็นเรื่องดีว่ามันเป็นไปไม่ได้ที่จะเรียกใช้./bin/activateโดยอุบัติเหตุแทน. bin/activate
daboross

20

บิตที่สามารถเรียกใช้งานได้ (ไม่เหมือนกับส่วนที่เหลือ) ในไฟล์ nonsetuid และ nonsetguid นั้นไม่ใช่กลไกความปลอดภัย ทุกสิ่งที่คุณสามารถอ่านได้คุณสามารถรันทางอ้อมได้และ Linux จะช่วยให้คุณสามารถอ่านอะไรก็ได้ที่คุณสามารถรันได้ แต่ไม่สามารถอ่านได้โดยตรง (ซึ่งควรจะเพียงพอที่จะเจาะรูในแนวคิดของ non-set (g) uid x-bit มาตรการรักษาความปลอดภัย)

มันเป็นสิ่งที่สะดวกกว่า: ให้ระบบรันสำหรับฉันโดยตรงถ้าตั้งบิตไว้มิฉะนั้นฉันต้องทำโดยอ้อม ( bash the_script;หรือแฮ็คเพื่อให้ได้ภาพหน่วยความจำของไฟล์ปฏิบัติการที่ไม่อนุญาตให้อ่าน )

คุณสามารถตั้งค่าเพื่อความสะดวกหากคุณต้องการทั้งที่มาและดำเนินการไม่ได้

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


3
@ Motte001 พวกเขาสามารถดำเนินการสิ่งที่แนบมาหากพวกเขาต้องการจริงๆ มันสะดวก
PSkocik

2
บิตที่สามารถเรียกใช้งานได้นั้นไม่ได้มีไว้เพื่อความปลอดภัย: หากฉันเป็นเจ้าของไฟล์ฉันมีอิสระในการchmodใช้และทำให้สามารถใช้งานได้ มันใช้สำหรับการเรียงลำดับข้อมูลจากโปรแกรมดังนั้นคำถามของ OP นั้นเป็นคำถามที่สมเหตุสมผล
alexis

1
@ Motte001 นั่นเป็นคุณสมบัติด้านความปลอดภัยของเบราว์เซอร์ไฟล์ GUI / แอปพลิเคชั่นอีเมล - มันสามารถตัดสินใจได้อย่างง่ายดายว่าการดับเบิลคลิกไฟล์ใด ๆ ที่ชื่อลงท้ายด้วย ".sh" จะถูกเรียกใช้งานในเทอร์มินัล (สไตล์ Windows) หรือตรงกันข้าม การคลิกไฟล์ใด ๆ ในไดเรกทอรี "สิ่งที่แนบมาที่ดาวน์โหลด" จะเรียกใช้แอปดูตัวอย่างแบบบิวด์อินในตัว xบิตเป็นเพียงสถานที่พิเศษที่จะสามารถอ่าน / เขียนคำใบ้ของสิ่งที่จะทำ
IMSoP

3
เหตุผลหนึ่งที่เราต้องการบิตที่เรียกทำงานได้คือการรันโปรแกรม setuid โดยเฉพาะที่รูทเป็นเจ้าของ ในขณะที่คุณสามารถดำเนินการได้ด้วยตัวคุณเองอย่างแน่นอนคุณต้องมีระบบปฏิบัติการเพื่อให้ทำงานได้เพื่อที่พวกเขาจะได้รับการอนุญาตที่จำเป็น ในบางกรณีมันเป็นความสะดวกสบายจริงๆ
Waleed Khan

2
"Linux จะอนุญาตให้คุณอ่านทุกสิ่งที่คุณสามารถเรียกใช้ผ่าน / proc" - ดี, เดเบียนเคอร์เนลของฉันไม่ได้: /tmp$ cp /bin/cat ./cat ; chmod a-rw ./cat ; ./cat & cp /proc/$!/exe /tmp/cat2->cp: cannot stat ‘/proc/16260/exe’: Permission denied
ilkkachu

9

นั่นเป็นคำถามที่ดี! Unix ใช้บิตที่ปฏิบัติการได้เพื่อแยกความแตกต่างระหว่างโปรแกรมและข้อมูล ระบบปฏิบัติการไม่ต้องการบิตการดำเนินการเนื่องจากสคริปต์ที่มาไม่ได้ถูกส่งผ่านไปยังระบบปฏิบัติการเพื่อดำเนินการตามกระบวนการใหม่ แต่เชลล์ใช้สคริปต์ที่มาจากโปรแกรมและจะค้นหา$PATHไฟล์ที่คุณต้องการแหล่งที่มา ดังนั้นตัวเชลล์เองอาจต้องการสิทธิ์ในการเรียกใช้งานสำหรับไฟล์ที่มา แต่มันก็ไม่ได้

คำถามต้องมานานแล้ว การออกแบบของบอร์นเชลล์เป็นผลมาจาก"ลำดับที่ยาวนานของการปรับเปลี่ยนการสนทนาการสนทนา"ในหมู่พลเมืองของ Bell Labs และการตัดสินใจด้านการออกแบบมากมายถูกกล่าวถึงโดย SR Bourne และคนอื่น ๆ ในช่วงหลายปีที่ผ่านมา น่าเสียดายที่การมองที่รวดเร็วของฉันไม่พบการสนทนาเกี่ยวกับคุณลักษณะแหล่งที่มา (ในการป้องกันของฉันมันยากที่ Google จะหาได้) สิ่งที่ฉันพบก็คือ "." คำสั่งไม่ปรากฏในการเปิดตัวในช่วงต้นนี้ไปยังเปลือกโดยบอร์นตัวเอง แต่มันก็มีอยู่ในผู้ใหญ่มากขึ้นรุ่น 7 รุ่น

ผู้มีอำนาจที่ขาดนี่คือการตีความของฉันเอง:

  1. .คำสั่งหรือที่รู้จักsourceอยู่ในผลต้นฉบับเดิมรวม (เช่น#includeใน preprocessor C) ลงรหัสที่มาของสคริปต์ดำเนินการหรือการโต้ตอบเซสชั่น ดังนั้นไฟล์ที่รวมอยู่นี้จึงไม่ใช่ "ดำเนินการ"

  2. ปรัชญาของ Unix คือการให้เชือกโปรแกรมเมอร์เพียงพอที่จะแขวนตัวเอง การถือครองและข้อ จำกัด โดยพลการมากเกินไปจนเกินไป เมื่อไม่นานมานี้มีการแจกแจงบางอย่างที่rm -r /ปฏิเสธที่จะทำสิ่งที่คุณถาม (คำสั่งนี้บอกrmให้ลบทุกอย่างในคอมพิวเตอร์ของคุณ อย่าลองใช้มันในฐานะ root!หรือดีกว่ายังไม่เลย) ดังนั้นบางที Bourne at al เพิ่งตัดสินใจว่าเมื่อคุณพยายามที่จะแหล่งไฟล์คุณจะเข้าใจว่าคุณกำลังทำอะไรอยู่ นั่นก็หลีกเลี่ยงการทำงานที่ไม่จำเป็นและวัฏจักรก็มีความสำคัญอย่างมากในเวลานั้น


แต่สิ่งหนึ่งที่ควรแน่นอน ไม่ได้ทำในสิ่งที่ @cat กล่าวว่า
TOOGAM

ฉันประหลาดใจที่ไม่มีการตั้งค่าสถานะและลบ @TOOGAM แต่ฉันใส่ไว้ใน / s!
แมว

ที่นั่นฉันไม่รู้ว่า @cat เขียนอะไร แต่ฉันพิสูจน์คำตอบของเด็กได้มากกว่านี้ (แต่มาเลยมันชัดเจนเพียงพอจากบริบทแล้ว)
alexis

4

เท่าที่ระบบปฏิบัติการมีความเกี่ยวข้องไฟล์ที่มีเชลล์สคริปต์เป็นเพียงข้อมูล หากคุณส่งชื่อไฟล์ข้อมูลดังกล่าวไปยังsourceคำสั่งหรือส่งผ่านบรรทัดคำสั่งไปยังการภาวนาของ bash shell ระบบปฏิบัติการทั้งหมดจะเห็นว่าเป็นสตริงที่เกิดขึ้นตรงกับชื่อของไฟล์ที่มีข้อมูล

บิตรันไทม์จะเกี่ยวข้องกันอย่างไรในกรณีนี้


3

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


1

ในกรณีที่ทุกคนมีความสนใจในการศึกษาเพิ่มเติมและ / หรือการชี้แจง: ในเชลล์ที่เข้ากันได้กับ POSIX เกือบจะถูกนำมาใช้ในขณะที่ผ่านมาการทำงานภายในของฟังก์ชัน 'exec_program ()' และ 'builtin_source ()' เป็นตัวอย่างที่ดีมาก ในฟังก์ชั่นเหล่านั้นคุณจะเห็นว่าอะไรคือความแตกต่างระหว่างพวกเขา:

https://github.com/rsenn/shish/blob/master/src/builtin/builtin_source.c

https://github.com/rsenn/shish/blob/master/src/exec/exec_program.c

โดยทั่วไปการจัดหาสามารถมองเห็นได้เป็นเชลล์เปลี่ยนเส้นทางตัวบ่งชี้ไฟล์ภายในของมันชั่วคราวซึ่งจะแยกวิเคราะห์เชลล์สคริปต์จาก (เทอร์มินัลในโหมดโต้ตอบ) ดังนั้นมันจะคล้ายกับการเปลี่ยนเส้นทางอื่น ๆ เช่น<input_file.txtและ>>append_to_something.listและสิ่งเหล่านี้ก็ต้องเปิดและปิดไฟล์

ดังนั้นการดำเนินการจะถูกจัดการโดยการexecve()เรียกของระบบซึ่งจำเป็นต้องใช้บิตการดำเนินการ

ฉันจำได้ว่าเห็นบางระบบที่อนุญาตให้ทำการประมวลผลของ ELF / a.out ไบนารี แต่ผ่านการดำเนินการ "/lib/ld-dynamic-linker.so" และด้วยโปรแกรมไบนารี (โดยไม่มีบิตบิต) เป็นอาร์กิวเมนต์แรก ฉันเชื่อว่าเป็นบนเครื่อง DEC Alpha หรือ VAX บางเครื่อง (เป็น SCO Unix หรือไม่)


-2

มุมมองอื่น:

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

ดังนั้นจึงไม่ขัดกับการใช้บิตเรียกใช้เพราะไม่มีอะไรที่ไม่มีบิตเรียกใช้จะทำงาน การตรวจสอบจะไม่เกิดขึ้นสำหรับสคริปต์ที่มาทั้งหมด มันจะดำเนินการทุกส่วนแยกจากกัน แต่มันเป็น


เชลล์บิวด์อินไม่ได้มาจากสคริปต์เชลล์ โดยปกติแล้วพวกเขาจะเป็นส่วนหนึ่งของเชลล์ปฏิบัติการ ใน ksh93, zsh และเชลล์อื่นสองสามอันสามารถเป็นส่วนขยายของเชลล์ได้
fpmurphy

@ fpmurphy1 นี่ไม่ใช่ประโยคของฉัน "shell builtins (... ) เป็นส่วนหนึ่งของ shell" หรือไม่?
Kamil Maciorowski
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.