ค้นหาคำอธิบายไฟล์ที่แชร์ "open file description"


17

ถ้าฉันทำ (ในเชลล์เหมือนบอร์น):

exec 3> file 4>&3 5> file 6>> file

ตัวอธิบายไฟล์ 3 และ 4 ตั้งแต่ 4 เป็นdup()ed จาก 3 แชร์คำอธิบายไฟล์แบบเปิดเดียวกัน (คุณสมบัติเดียวกันชดเชยแบบเดียวกันภายในไฟล์ ... ) ในขณะที่ตัวอธิบายไฟล์ 5 และ 6 ของกระบวนการนั้นอยู่ในคำอธิบายไฟล์แบบเปิดที่แตกต่างกัน(ตัวอย่างเช่นแต่ละไฟล์มีตัวชี้ในไฟล์)

ขณะนี้ในlsofการส่งออกทั้งหมดที่เราเห็นคือ:

zsh     21519 stephane    3w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    4w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    5w   REG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    6w   REG  254,2        0 10505865 /home/stephane/file

มันค่อนข้างดีขึ้นด้วยlsof +fg:

zsh     21519 stephane    3w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    4w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    5w   REG          W,LG  254,2        0 10505865 /home/stephane/file
zsh     21519 stephane    6w   REG       W,AP,LG  254,2        0 10505865 /home/stephane/file

(ที่นี่บน Linux 3.16) ที่เราเห็นว่า fd 6 มีค่าสถานะที่แตกต่างกันดังนั้นจึงต้องมีคำอธิบายไฟล์เปิดที่แตกต่างจากที่หนึ่งใน fd 3, 4 หรือ 5 แต่จากที่เราไม่สามารถบอกได้ว่า fd 5 อยู่บน ที่แตกต่างกันคำอธิบายเปิดแฟ้ม ด้วย-oเรายังจะได้เห็นการชดเชย แต่อีกเดียวกันชดเชยไม่ได้รับประกันว่ามันเหมือนคำอธิบายเปิดแฟ้ม

มีผู้ใดที่ไม่ล่วงล้ำ1วิธีการหาที่? ภายนอกหรือสำหรับตัวอธิบายไฟล์ของกระบวนการ


1 . วิธีการแก้ปัญหาด้วยวิธีหนึ่งอาจเป็นการเปลี่ยนสถานะของหนึ่ง fd ด้วยfcntl()และดูว่า file descriptors อื่น ๆ มีการปรับปรุงสถานะเป็นอย่างไร แต่เห็นได้ชัดว่าไม่ใช่อุดมคติหรือหลักฐานโง่


โดยหลักการแล้ววิธีการนี้ควรใช้งานได้และไม่ก่อกวนเกินไปในสถานการณ์ส่วนใหญ่: อันดับแรกแยกเด็ก (ด้วย ptrace ถ้าทำจากภายนอก) จากนั้นในเด็กให้ทำบางสิ่งบางอย่างกับ file descriptor ที่ไม่ส่งผลกระทบต่อกระบวนการอื่น สำหรับ Linux สัญญาเช่าควรทำงานได้
Gilles 'หยุดความชั่วร้าย'

@Gilles ขอบคุณ แต่นั่นเป็นวิธีที่ฉันแนะนำในคำถามนี้มากกว่าหรือน้อยกว่า สัญญาเช่า (สมมติว่าคุณหมายถึง F_SETLEASE fcntl ขอบคุณที่ทำให้ฉันตระหนักถึง BTW) จะใช้งานได้กับไฟล์ปกติที่คุณเป็นเจ้าของและไม่ใช่ถ้ามีคำอธิบายเปิดไฟล์ "เขียน" ไปยังไฟล์เดียวกัน (EBUSY) -intrusive
Stéphane Chazelas

คุณละทิ้งคำถามนี้หรือไม่? ฉันโพสต์ข้อมูลบางอย่างเกี่ยวกับวิธีที่ SystemTap สามารถทำสิ่งที่คุณต้องการ แต่คุณยังไม่ได้ทำเครื่องหมายคำตอบว่าสมบูรณ์ ...
Azhrei

คำตอบ:


2

สำหรับ Linux 3.5 ขึ้นไปสามารถทำได้ด้วยkcmp (3) :

KCMP_FILE

  • ตรวจสอบว่ามีไฟล์อธิบายidx1ในกระบวนการpid1หมายถึงคำอธิบายเปิดแฟ้มเดียวกัน (ดูเปิด (2) ) เป็นไฟล์อธิบายidx2ในกระบวนการpid2 การมีอยู่ของตัวให้คำอธิบายไฟล์สองตัวที่อ้างถึงคำอธิบายไฟล์แบบเปิดเดียวกันสามารถเกิดขึ้นได้เนื่องจากผลลัพธ์ของdup (2) (และคล้ายกัน) fork (2)หรือผ่านตัวอธิบายไฟล์ผ่านซ็อกเก็ตโดเมน (ดูunix (7) )

หน้าคนมีตัวอย่างสำหรับกรณีใช้ OP ถาม โปรดทราบว่า syscall นี้ต้องการเคอร์เนลที่จะรวบรวมด้วยCONFIG_CHECKPOINT_RESTOREชุด


ขอบคุณ สิ่งที่ฉันมองหา โปรดทราบว่าหากคุณไม่ได้เป็น superuser จะต้องมีสองกระบวนการของคุณ (และไม่ต้อง setuid / setgid ... ) (เข้าใจ)
Stéphane Chazelas

@ StéphaneChazelasอย่างแน่นอน ถ้าด้วยเหตุผลบางอย่างการสนับสนุน CPIU ไม่ได้ถูกสร้างขึ้นในเคอร์เนลของคุณและคุณไม่ต้องการสร้างมันขึ้นมาใหม่ฉันคิดว่าคุณสามารถเขียนโมดูลเคอร์เนลที่ส่งออกอินเทอร์เฟซผู้ใช้บางส่วนที่ให้คุณเปรียบเทียบพstruct file *อยน์เตอร์
minmaxavg

3

สิ่งที่คุณต้องการเปรียบเทียบคือพstruct fileอยน์เตอร์ที่ตัวให้คำอธิบายไฟล์ชี้ไป (ภายในเคอร์เนลคือtask_structโครงสร้างข้อมูลเดียวสำหรับแต่ละเธรดซึ่งประกอบด้วยตัวชี้ไปยังโครงสร้างอื่นที่เรียกว่าfiles_structและโครงสร้างนั้นประกอบด้วยอาร์เรย์ของพอยน์เตอร์แต่ละตัวต่อ a struct fileซึ่งเป็นตำแหน่งstruct fileที่เก็บออฟเซ็ตแสวงหาแฟล็กเปิดและ a สาขาอื่น ๆ ไม่กี่)

ฉันไม่รู้วิธีที่ผู้ใช้มองเห็นตัวชี้ในวิธีfiles_structอื่นนอกเหนือจากการใช้เครื่องมือรบกวนบางอย่าง ตัวอย่างเช่น SystemTap จะได้รับ PID และสามารถค้นหาที่สอดคล้องกันtask_structและติดตามตัวชี้ หากคุณกำลังมองหาเรื่อย ๆ ฉันคิดว่ามันเกี่ยวกับมัน เดลล์ได้เปิดตัวเครื่องมือเมื่อนานมาแล้วที่เรียกว่า KME (Kernel Memory Editor) ซึ่งให้อินเทอร์เฟซเหมือนสเปรดชีตแก่หน่วยความจำเคอร์เนลที่ใช้งานจริงและสามารถทำสิ่งที่คุณต้องการได้ (ฉันพยายามและไม่เคยทำงานให้เสร็จสมบูรณ์และไม่แน่ใจว่าทำไม)

เหตุผลหนึ่งที่คุณไม่พบว่าlsofมีประโยชน์คือไม่เห็นตัวชี้เหล่านั้น (แต่ดูที่+fตัวเลือกสำหรับระบบที่ไม่ใช่ Linux) ในทางทฤษฎีคุณสามารถเปรียบเทียบเขตข้อมูลทั้งหมดในstruct fileและคิดว่าโครงสร้างทั้งสองเหมือนกัน แต่พวกเขายังอาจมาจากการopen(2)โทรแยกกัน

ลองดูที่ที่PFilesสคริปต์ SystemTap สำหรับความคิด หากคุณแก้ไขเพื่อพิมพ์ที่อยู่ของstruct fileคุณจะมีทางออกของคุณ คุณอาจตรวจสอบopens_file_by_pid.stpเนื่องจากมีฟังก์ชั่นในการใช้files_structงานเช่น ตาราง file descriptor กำลังดูอstruct fileอบเจ็กต์ ...

ฉันขอสิ่งที่คุณพยายามทำสำเร็จ


ฉันต้องยอมรับว่าฉันจำเหตุการณ์ที่ฉันต้องการไม่ได้ การแก้จุดบกพร่องหรืองานนิติวิทยาศาสตร์บางอย่างไม่ต้องสงสัยเลย
Stéphane Chazelas

ฉันรอคอยที่จะรหัสระบบ PoC :-)
Stéphane Chazelas

ก่อนที่ฉันจะโพสต์คำถามฉันได้ดูที่ systemtap หรือ / proc / kcore ส่วนที่ยากคือการได้รับข้อมูลของ FD ทุกงานทุก วิธีการที่ดีที่สุดที่ฉันพบคือการเชื่อมโยงไปยังฟังก์ชั่นที่สร้างเนื้อหาของไดเรกทอรี / proc / * / task / fd แต่สิ่งที่สามารถใช้งานได้เท่านั้นที่ฉันสามารถทำได้ด้วยการเชื่อมโยงที่หมายเลขบรรทัดเฉพาะในไฟล์ต้นฉบับดังนั้น เคลื่อนย้ายได้จากเคอร์เนลเวอร์ชันหนึ่งไปยังรุ่นถัดไป คุณไม่สามารถวนซ้ำผ่านรายการงานใน systemtap ได้ อาจเป็นไปได้ผ่าน / proc / kcore แต่ความพยายามมากเกินไปและอาจไม่น่าเชื่อถือ
Stéphane Chazelas

ขอบคุณสำหรับคำตอบที่ดีที่สุด ฉันจะดูที่พอยน์เตอร์ของคุณ
Stéphane Chazelas

แน่นอนคุณสามารถ! ตั้งค่าprobe beginบล็อกและให้ใช้for_each_processมาโครในบล็อกของรหัส C ที่ฝังอยู่ในสคริปต์ (คุณจะต้องใช้โหมด "กูรู" SystemTap เพื่อฝังโค้ด C) อันที่จริงแล้วเพื่อทำให้สิ่งนี้น่าสนใจ (!) คุณสามารถใช้หนึ่งในอาร์เรย์เชื่อมโยงของ SystemTap ใช้ที่files_structอยู่เป็นคีย์และรายการของ PIDs / TIDs เป็นค่า ตอนนี้คุณมีรายการของทุกไฟล์ที่เปิดอยู่และงานใดบ้างที่แบ่งปันกัน (สามารถแชร์ระหว่างผู้ปกครอง / ลูก) ตอบกลับอีกครั้งถ้าคุณต้องการหารือเกี่ยวกับ SystemTap
Azhrei

0

นี่คือโซลูชันเฉพาะของ linux: / proc / self / fd เป็นไดเรกทอรีของลิงก์สัญลักษณ์สำหรับจัดการไฟล์ที่เปิดอยู่ในกระบวนการปัจจุบัน คุณสามารถเปรียบเทียบค่าลิงค์ มันมีความซับซ้อนมากขึ้นเมื่อใช้กระบวนการลูกเพราะเด็กจะมี / proc / ตัวเองที่แตกต่างกันเพราะมันเป็นลิงค์สัญลักษณ์ขึ้นอยู่กับ pid คุณสามารถแก้ไขปัญหานี้ได้โดยใช้ / proc / $$ / fd โดยที่ $$ เป็น pid ที่ต้องการ


ขอบคุณ แต่นั่นไม่ใช่สิ่งที่ฉันขอ บน Linux lsof ใช้ / proc / pid / fd เพื่อดึงข้อมูลพา ธ สำหรับแต่ละไฟล์ descriptor และ / proc / pid / fdinfo สำหรับแฟล็ก แต่สิ่งที่ฉันต้องการก็คือสำหรับสอง fds ไปที่ไฟล์เดียวกันไม่ว่าพวกเขาจะชี้ไปที่คำอธิบายไฟล์เปิดเดียวกันหรือถ้าไฟล์ descriptor สองไฟล์นั้นเปิดอย่างอิสระ
Stéphane Chazelas

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

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