tìm xem mô tả tập tin nào chia sẻ cùng mô tả tập tin mở


17

Nếu tôi làm (trong một vỏ giống như Bourne):

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

Mô tả tệp 3 và 4, vì 4 được chỉnh sửa dup()từ 3, chia sẻ cùng một mô tả tệp đang mở (cùng thuộc tính, cùng một phần bù trong tệp ...). Trong khi các mô tả tệp 5 và 6 của quá trình đó nằm trên một mô tả tệp mở khác nhau (ví dụ: mỗi mô tả có con trỏ riêng trong tệp).

Bây giờ, trong lsofđầu ra, tất cả những gì chúng ta thấy là:

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

Tốt hơn một chút với 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

(ở đây trên Linux 3.16) ở chỗ chúng ta thấy fd 6 có các cờ khác nhau, vì vậy nó phải là một mô tả tệp mở khác với mô tả trên fd 3, 4 hoặc 5, nhưng từ đó chúng ta không thể biết fd 5 đang ở trên một mô tả tập tin mở khác nhau . Với -o, chúng ta cũng có thể thấy phần bù, nhưng một lần nữa phần bù không đảm bảo đó là phần mô tả tệp mở giống nhau .

Có không xâm nhập bất kỳ 1 cách để tìm mà ra? Bên ngoài, hoặc cho mô tả tập tin riêng của một quá trình?


1 . Một cách tiếp cận heuristic có thể là thay đổi cờ của một fd fcntl()và xem kết quả của các mô tả tệp khác có cờ của họ được cập nhật như thế nào, nhưng rõ ràng đó không phải là lý tưởng cũng không phải là bằng chứng ngu ngốc


Cách tiếp cận này nên hoạt động, về nguyên tắc, và không quá đột phá trong hầu hết các tình huống: đầu tiên là một đứa trẻ (với ptrace nếu thực hiện nó từ bên ngoài). Sau đó, ở trẻ, làm một cái gì đó với bộ mô tả tập tin mà không ảnh hưởng đến các quá trình khác. Trên Linux, cho thuê nên hoạt động cho điều đó.
Gilles 'SO- ngừng trở nên xấu xa'

@Gilles, cảm ơn nhưng đó ít nhiều là cách tiếp cận tôi đề xuất trong câu hỏi. cho thuê (giả sử bạn có nghĩa là F_SETLEASE fcntl, cảm ơn vì đã cho tôi biết về BTW) sẽ chỉ hoạt động cho các tệp thông thường mà bạn sở hữu chứ không phải nếu có một mô tả tệp mở "ghi" khác vào cùng một tệp (EBUSY), và nó không hoàn toàn không -xuất hiện.
Stéphane Chazelas

Bạn đã từ bỏ câu hỏi này? Tôi đã đăng một số thông tin liên quan đến cách SystemTap có thể làm những gì bạn muốn, nhưng bạn chưa đánh dấu câu trả lời nào là hoàn chỉnh ...?
Azhrei

Câu trả lời:


2

Đối với Linux 3.5 trở đi, điều này có thể được thực hiện bằng kcmp (3) :

KCMP_FILE

  • Kiểm tra xem một bộ mô tả tệp idx1 trong quy trình pid1 có đề cập đến cùng một mô tả tệp mở (xem open (2) ) như mô tả tệp idx2 trong quy trình pid2 không . Sự tồn tại của hai mô tả tập tin đó đề cập đến cùng một mô tả tập tin mở có thể xảy ra như là kết quả của dup (2) (và tương tự) fork (2) , hoặc thông qua mô tả tập tin thông qua một ổ cắm miền (xem unix (7) ).

Trang man cung cấp một ví dụ cụ thể cho trường hợp sử dụng mà OP đã hỏi. Lưu ý rằng tòa nhà này yêu cầu kernel được biên dịch với CONFIG_CHECKPOINT_RESTOREset.


Cảm ơn. Chính xác những gì tôi đang tìm kiếm. Lưu ý rằng trừ khi bạn là siêu người dùng, đó phải là hai quá trình của bạn (và không phải là setuid / setgid ...) (có thể hiểu được)
Stéphane Chazelas

@ StéphaneChazelas Chính xác. Nếu vì một lý do nào đó, hỗ trợ CPIU không được xây dựng trong kernel của bạn và bạn không muốn xây dựng lại nó, thì tôi cho rằng bạn luôn có thể viết một mô-đun kernel xuất một số giao diện người dùng cho phép bạn so sánh các struct file *con trỏ.
minmaxavg

3

Những gì bạn đang tìm kiếm để so sánh là các struct filecon trỏ mà bộ mô tả tập tin trỏ đến. (Bên trong nhân là một task_structcấu trúc dữ liệu cho mỗi luồng. Nó chứa một con trỏ tới cấu trúc khác gọi là files_struct. Và cấu trúc đó chứa một mảng các con trỏ, mỗi cấu trúc đến một struct file. Nó struct filegiữ phần bù tìm kiếm, các cờ mở và một vài lĩnh vực khác.)

Tôi không biết bất kỳ cách nào có thể nhìn thấy người dùng để xem các con trỏ files_structkhác ngoài việc sử dụng một số công cụ xâm nhập. Ví dụ, SystemTap có thể được cung cấp một PID và nó có thể tìm thấy task_structcác con trỏ tương ứng và theo các con trỏ. Tuy nhiên, nếu bạn đang tìm kiếm thụ động, tôi nghĩ đó là về nó. Dell đã phát hành một công cụ từ lâu được gọi là KME (Kernel Memory Editor) cung cấp giao diện giống như bảng tính cho bộ nhớ kernel và nó có thể làm những gì bạn muốn, nhưng nó không bao giờ được chuyển sang 64 bit. (Tôi đã thử và không bao giờ làm cho nó hoàn toàn hoạt động, và không chắc tại sao.)

Một lý do bạn không thấy lsofhữu ích là nó cũng không thấy các con trỏ đó (nhưng hãy xem +ftùy chọn cho các hệ thống không phải là Linux). Về mặt lý thuyết bạn có thể so sánh tất cả các trường trong struct filevà nghĩ rằng hai cấu trúc giống nhau, nhưng chúng vẫn có thể là từ các open(2)cuộc gọi riêng biệt .

Hãy nhìn vào các PFiles SystemTap kịch bản cho ý tưởng. Nếu bạn sửa đổi nó để in địa chỉ của struct file, bạn sẽ có giải pháp của mình. Bạn cũng có thể kiểm tra opens_file_by_pid.stp vì có một chức năng trong đó đi bộ files_struct, tức là. bảng mô tả tập tin, nhìn vào các struct fileđối tượng ...

Tôi có thể hỏi những gì bạn đang cố gắng để đạt được?


Tôi phải thừa nhận tôi không thể nhớ chính trường hợp tôi cần điều đó. Một số nhiệm vụ gỡ lỗi hoặc pháp y không có nghi ngờ.
Stéphane Chazelas

Tôi đang mong chờ mã hệ thống PoC :-)
Stéphane Chazelas

Trước khi tôi đăng câu hỏi, tôi đã xem qua các phương pháp systemtap hoặc / Proc / kcore. Phần khó khăn là để có được thông tin cho mọi fd của mọi nhiệm vụ . Cách tiếp cận hứa hẹn nhất mà tôi đã tìm thấy là nối vào các hàm tạo ra nội dung của thư mục / Proc / * / task / fd, nhưng những điều khả thi duy nhất tôi có thể đưa ra liên quan đến việc móc vào các số dòng cụ thể trong tệp nguồn nên không di động từ một phiên bản kernel sang phiên bản tiếp theo. Bạn thực sự không thể lặp qua danh sách nhiệm vụ trong systemtap. Có thể có thể thông qua / Proc / kcore, nhưng quá nhiều nỗ lực và có thể không đáng tin cậy.
Stéphane Chazelas

Cảm ơn cho phản ứng tốt nhất cho đến nay. Tôi sẽ xem xét con trỏ của bạn.
Stéphane Chazelas

Chắc chắn bạn có thể! Thiết lập một probe beginkhối và yêu cầu nó sử dụng for_each_processmacro trong một khối mã C được nhúng trong tập lệnh (bạn sẽ cần sử dụng chế độ "guru" SystemTap để nhúng mã C). Trong thực tế, để làm cho điều này thú vị (!), Bạn có thể sử dụng một trong các mảng kết hợp của SystemTap; sử dụng files_structđịa chỉ làm khóa và danh sách các PID / TID làm giá trị. Bây giờ bạn có một danh sách của mỗi tệp đã mở và những tác vụ nào đang chia sẻ chúng (chúng có thể được chia sẻ giữa cha / con). Trả lời lại nếu bạn muốn thảo luận về SystemTap.
Azhrei

0

Đây là một giải pháp cụ thể của linux: / Proc / self / fd là một thư mục gồm các liên kết tượng trưng để xử lý tệp mở trong quy trình hiện tại. Bạn chỉ có thể so sánh các giá trị liên kết. Nó trở nên phức tạp hơn khi sử dụng một quá trình con, bởi vì đứa trẻ sẽ có một / Proc / self khác nhau bởi vì nó là một liên kết tượng trưng phụ thuộc pid. Bạn có thể giải quyết vấn đề này bằng cách sử dụng / Proc / $$ / fd trong đó $$ là pid mong muốn.


Cảm ơn. Nhưng đó không phải là điều tôi đang hỏi. Trên Linux, lsof thực sự sử dụng / Proc / pid / fd để truy xuất các đường dẫn cho mỗi mô tả tệp và / Proc / pid / fdinfo cho các cờ. Nhưng điều tôi muốn là cho hai fds vào cùng một tệp cho dù chúng trỏ đến cùng một mô tả tệp đang mở hoặc nếu hai mô tả tệp đã được mở một cách độc lập.
Stéphane Chazelas

ok, sau khi bạn đã tìm thấy các cặp mô tả tệp được mở cho cùng một tên tệp, hãy nói trên cả hai và so sánh kết quả, nếu chúng khác nhau thì chúng là riêng biệt. Nếu chúng giống nhau trên một mô tả tập tin và lặp lại, Nếu chúng vẫn khớp thì chúng giống nhau.
hildred

Chà, đó là một biến thể xâm phạm hơn của cách tiếp cận heuristic mà tôi đề cập trong câu hỏi và nó chỉ hoạt động cho các tệp thông thường (không phải ổ cắm, thiết bị (như thiết bị đầu cuối), đường ống ...).
Stéphane Chazelas
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.