2010-08-09 27 views
5

Tôi tự hỏi nếu có cách viết bảo vệ mọi trang trong không gian địa chỉ của quá trình Linux '(từ bên trong của quá trình, theo cách mprotect()). Bởi "mọi trang", tôi thực sự có nghĩa là mọi trang trong không gian địa chỉ của quá trình có thể được viết bởi chương trình thông thường đang chạy ở chế độ người dùng - vì vậy, văn bản chương trình, hằng số, các hình cầu và đống - - nhưng tôi sẽ hạnh phúc chỉ với các hằng số, hình cầu và đống. Tôi không muốn viết-bảo vệ ngăn xếp - rằng có vẻ như là một ý tưởng tồi.Tôi có thể viết-bảo vệ mọi trang trong không gian địa chỉ của một quy trình Linux không?

Một vấn đề là tôi không biết bắt đầu từ đâu để bảo vệ ghi bộ nhớ. Nhìn vào /proc/pid/maps, hiển thị các phần của bộ nhớ khi sử dụng cho một pid đã cho, chúng dường như luôn bắt đầu với địa chỉ 0x08048000, với văn bản chương trình. (Trong Linux, theo như tôi có thể biết, bộ nhớ của một quá trình được đặt ra với văn bản chương trình ở đáy , sau đó hằng số trên đó, sau đó tổng số, sau đó heap, sau đó một khoảng trống có kích thước khác nhau tùy thuộc vào trên kích thước của đống hoặc ngăn xếp, và sau đó ngăn xếp phát triển từ đầu bộ nhớ tại địa chỉ ảo 0xffffffff.) Có cách để biết vị trí đầu của số là (bằng cách gọi sbrk(0), con trỏ tới số hiện tại "ngắt", nghĩa là phần trên cùng của vùng heap), nhưng không thực sự là cách để cho biết nơi bắt đầu đống.

Nếu tôi cố gắng bảo vệ tất cả các trang từ 0x08048000 đến giờ nghỉ, tôi cuối cùng cũng gặp lỗi mprotect: Cannot allocate memory. Tôi không biết tại sao mprotect sẽ là vẫn phân bổ bộ nhớ - và Google không hữu ích lắm. Ý tưởng nào?

Nhân tiện, lý do tôi muốn làm điều này là vì tôi muốn tạo một danh sách của tất cả các trang được viết trong khi chạy chương trình và cách tôi có thể nghĩ đến việc này là viết bảo vệ tất cả các trang, cho phép bất kỳ lần ghi nào gây ra lỗi ghi, sau đó thực hiện ghi xử lý lỗi sẽ thêm trang vào danh sách rồi xóa bảo vệ viết . Tôi nghĩ rằng tôi biết làm thế nào để thực hiện xử lý, nếu chỉ tôi có thể tìm ra các trang để bảo vệ và làm thế nào để làm điều đó.

Cảm ơn!

+1

Tôi thực sự đã có mã thực hiện chính xác những gì bạn đang cố gắng làm. Ý tưởng của bạn sẽ hoạt động, nhưng bạn không thể bảo vệ các trang mà danh sách "những trang được viết" của bạn sẽ cư trú, hoặc trình xử lý SEGV của bạn sẽ gây ra SEGV! – Borealid

+0

@Borealid, cảm ơn, và đó là vấn đề mà tôi đang cố gắng giải quyết (tôi đã có trình xử lý segfault và phân tích/proc/self/maps đang hoạt động ngay bây giờ). Làm cách nào để tránh bảo vệ (các) trang có chứa danh sách đó? Phân bổ danh sách trên ngăn xếp sẽ hoạt động, nhưng sau đó tôi không thấy bất kỳ cách nào để chuyển nó cho trình xử lý. Ngoài ra, tôi có thể phân bổ nó như là một toàn cầu, nhưng tôi muốn sử dụng một cấu trúc dữ liệu fancier hơn một mảng có độ dài cố định (như một container STL), và tôi không phải lúc nào cũng biết danh sách mà tôi đang viết ở đâu trong trí nhớ. –

+0

@borealid: Bạn nói rằng bạn có mã thực hiện chính xác điều này - bạn có nhớ chia sẻ mã của mình không? Tôi mới ở đây và tôi không thể tìm cách liên hệ trực tiếp với bạn (kênh sau). Tôi đang cố gắng làm chính xác những gì Linsey đang làm, vì vậy mọi mẫu mã sẽ rất hữu ích. –

Trả lời

5

Bạn nhận được ENOMEM từ mprotect() nếu bạn cố gọi nó trên các trang không được ánh xạ.

Đặt cược tốt nhất của bạn là mở /proc/self/maps và đọc một dòng tại một thời điểm với fgets() để tìm tất cả các ánh xạ trong quá trình của bạn.Đối với mỗi ánh xạ có thể ghi (được chỉ định trong trường thứ hai) không phải là ngăn xếp (được chỉ ra trong trường cuối cùng), hãy gọi mprotect() với địa chỉ và chiều dài cơ sở phù hợp (được tính từ địa chỉ xuất phát và địa chỉ đến trong trường đầu tiên).

Lưu ý rằng bạn sẽ cần phải có trình xử lý lỗi của bạn đã được thiết lập tại thời điểm này, vì hành vi đọc chính tệp maps có thể sẽ gây ra viết trong không gian địa chỉ của bạn.

+0

Cảm ơn - Tôi đã hy vọng rằng sẽ có một số cách xung quanh phải phân tích cú pháp/proc/self/maps, nhưng có vẻ như không có (từ cuộc thảo luận tại http://stackoverflow.com/questions/269314/là-có-một-tốt-cách-hơn-phân tích-proc-tự-bản đồ-to-con số-out-bộ nhớ-protectio). –

0

Bắt đầu đơn giản. Viết bảo vệ một vài trang và đảm bảo trình xử lý tín hiệu của bạn hoạt động cho các trang này. Sau đó, lo lắng về việc mở rộng phạm vi bảo vệ. Ví dụ, có thể bạn không cần phải viết-bảo vệ mã-phần: hệ điều hành có thể thực hiện ghi-hoặc-thực hiện ngữ nghĩa bảo vệ trên bộ nhớ mà sẽ ngăn chặn các phần mã từ bao giờ được ghi vào:

+0

Vâng, đối với vấn đề này, chúng tôi có thể giả định không có mã tự sửa đổi cho bây giờ. Tôi sẽ được OK với một trong hai viết bảo vệ phần mã hay không, nào là dễ dàng hơn. –

+0

Thực ra những gì tôi đang cố gắng nói là các phần mã của bạn có nhiều khả năng đã được bảo vệ chống ghi. –

Các vấn đề liên quan