Có thể đọc bộ nhớ từ một chương trình khác bằng cách phân bổ tất cả các không gian trống trên một hệ thống?


26

Về mặt lý thuyết, nếu tôi xây dựng một chương trình phân bổ tất cả bộ nhớ không sử dụng trên một hệ thống và tiếp tục yêu cầu nhiều bộ nhớ hơn khi các ứng dụng khác giải phóng bộ nhớ mà chúng không còn cần nữa, có thể đọc bộ nhớ được phát hành gần đây từ các ứng dụng khác ? Hay điều này bằng cách nào đó được bảo vệ bởi hệ điều hành hiện đại?

Tôi không có ứng dụng thực tế cho việc này, tôi chỉ tò mò. Tôi nhận thấy có một số vấn đề với việc phân bổ "tất cả bộ nhớ khả dụng" trong cuộc sống thực.

Chỉnh sửa: Để làm rõ, tôi đang hỏi cụ thể về bộ nhớ "Đã phát hành", không truy cập bộ nhớ hiện đang được phân bổ bởi một ứng dụng khác.

Câu trả lời:


23

Không, bởi vì một hạt nhân tốt sẽ xóa sạch nội dung của bộ nhớ trước khi nó được cấp cho một quy trình để bảo vệ chống lại chính xác loại tấn công mà bạn đề xuất.

Trên các hệ thống Unixy, bộ nhớ được phân bổ cho các quy trình bằng cách mở rộng cái được gọi là ngắt chương trình , đây là giới hạn của không gian gần như có thể định địa chỉ mà một quy trình có thể sử dụng. Một tiến trình báo cho kernel nó muốn mở rộng không gian địa chỉ của nó và kernel sẽ cho phép nó nếu bộ nhớ khả dụng hoặc cuộc gọi sẽ thất bại nếu không. (Tên của brk()cuộc gọi hệ thống xuất phát từ khái niệm này.)

Trong thực tế, các khối lớn của bộ nhớ được giải phóng không thường xuyên chống lại sự phá vỡ chương trình, đó là điều cần thiết cho một quá trình trả lại bộ nhớ cho kernel bằng cách thu nhỏ ngắt chương trình. Tất nhiên, điều này phụ thuộc vào việc triển khai malloc()free(). Nếu bạn có sẵn nguồn, họ sẽ cho bạn biết liệu bộ nhớ có được trả lại hay không.

Không có ý nghĩa bảo mật cho việc malloc()không khởi tạo bộ nhớ bởi vì mọi thứ nó có được brk()sẽ bị xóa và mọi thứ trước đó free()sẽ được viết theo cùng một quy trình.


19

Có, về mặt lý thuyết là có thể đọc bộ nhớ được giải phóng của một quá trình khác. Đó là nguồn gốc của một số cuộc tấn công leo thang đặc quyền trở lại trong ngày. Do đó, các hệ điều hành ngày nay không còn bộ nhớ nếu nó được phân bổ trước bởi một quy trình khác. Lý do bạn không phải lúc nào cũng thấy bộ nhớ zeroed là vì nó hiệu quả hơn khi không loại bỏ bộ nhớ nếu nó được phân bổ trước đó bởi cùng một quy trình. HĐH cố gắng trả lại các trang bộ nhớ cho cùng một quy trình nếu có thể.


1
"Có nhưng không" là "không". @Blrfl có quyền.
Ross Patterson

4
@RossPatterson: Về mặt lý thuyết, Karl thực sự đúng hơn tôi. Thực tế là các hệ điều hành chính đã đóng lỗ hổng đó từ nhiều năm trước.
Blrfl

@Blrfl Hiểu rồi. Nhưng "những năm trước" là vào cuối những năm 1960, khi các hệ thống phân trang và bộ nhớ ảo lần đầu tiên được giới thiệu. Chắc chắn vào thời của Multics, VM / 370 và OS / VS. Lỗi vắng mặt, điều này đã không thể có trong bộ nhớ của hầu hết các lập trình viên thực hành.
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 Tôi thấy một số mâu thuẫn ở đây. Ý của bạn là "cùng thực thi"? Làm thế nào để kiểm tra xem có không thoát ra không - bằng đường dẫn đĩa?
jakub.g 18/03/13

1
Tôi nghĩ rằng tôi đang thiếu một cái gì đó. Tại sao sau đó, khi tôi biên dịch và chạy một số chương trình C ++ với các số nguyên chưa được khởi tạo, chúng không bằng 0 khi tôi đọc các biến đó?
jakub.g 18/03/13

2

Có một số lớp liên quan ở đây ảnh hưởng đến câu trả lời.

Nếu bạn giả sử một hệ điều hành bộ nhớ ảo hiện đại, bạn sẽ không thể thấy phần còn lại của dữ liệu xử lý khác trong các trang bạn phân bổ.

Khi một quá trình được tải lần đầu tiên, bảng trang được tải và các khung có khả năng của bộ nhớ thực được phân bổ cho các trang đó. Tối thiểu, bảng trang hoặc bảng bổ sung của nó, sẽ chứa một bản đồ của tất cả bộ nhớ mà quá trình có thể phân bổ. Đây cũng là nơi phá vỡ quy trình ban đầu, được đề cập ở trên, được thiết lập.

Mặc dù malloc () có thể, nếu quy trình được cho phép, làm cho quá trình ngắt thay đổi, thêm nhiều trang vào bảng trang quy trình (trang bổ sung) để đáp ứng yêu cầu, nơi một quy trình có thể "lấy dữ liệu" khác xử lý lớp bộ nhớ thực thấp hơn.

Trong cả hai trường hợp này, một hệ điều hành hiện đại sử dụng phân trang theo yêu cầu hoặc phân bổ lười biếng, chưa phân bổ bộ nhớ vật lý (khung). Hệ điều hành chỉ là "ghi chú" về bộ nhớ ảo nào cho quá trình đó được coi là hợp lệ. Bộ nhớ thực tế chỉ được chỉ định khi cần thiết.

Bộ nhớ vật lý hoặc khung được phân bổ cho một quy trình khi trang ảo được nhận ra và ánh xạ vào bảng trang quy trình Đây là nơi tiềm năng tiếp xúc với dữ liệu. Điều này xảy ra trong một lỗi trang. Việc tiếp xúc là do một quá trình trước đó có thể đã sử dụng cùng một khung và dữ liệu của nó đã bị bỏ qua hoặc hoán đổi, để nhường chỗ cho yêu cầu bộ nhớ vật lý hiện tại. Hệ điều hành phải cẩn thận để đảm bảo rằng dữ liệu quy trình yêu cầu được hoán đổi chính xác hoặc khung bị xóa (không) trước khi tiếp tục quá trình. Điều này cũng được đề cập ở trên như là một vấn đề "cũ nhưng đã giải quyết".

Điều này làm cho nó có phần không liên quan nếu bộ nhớ tiến trình khác được "giải phóng" hay không. Bộ nhớ "giải phóng" các quy trình khác vẫn nằm trong các trang được gán cho quy trình đó và thường không được xử lý cho đến khi quá trình kết thúc vì chúng sẽ bị tráo đổi khi bộ nhớ xuống thấp hoặc chúng bị trục xuất. malloc () và free () quản lý bộ nhớ ảo được gán cho quá trình ở cấp độ (người dùng).

Trong câu hỏi của bạn, quá trình của bạn, tiếp tục yêu cầu ngày càng nhiều bộ nhớ, theo lý thuyết, đẩy tất cả các quá trình khác ra khỏi bộ nhớ. Trong thực tế, có các chiến lược phân bổ khung - toàn cầu và địa phương - cũng có thể ảnh hưởng đến câu trả lời. Có khả năng quá trình này sẽ buộc các trang của chính nó ra khỏi bộ nhớ trước khi được phép vượt qua hệ điều hành và tất cả các quy trình khác. Mặc dù điều này vượt xa câu hỏi ban đầu của bạn.

Tất cả điều này là moot trong một hệ thống như MS-DOS. MS-DOS (và các hệ thống đơn giản khác) không sử dụng bộ nhớ ảo (bản thân chúng) và bạn có thể dễ dàng chọc và prod vào dữ liệu "quy trình" khác.

Một số tài liệu tham khảo tốt, có thể dễ hiểu hơn mã nguồn Linux sẽ là một cuốn sách văn bản hệ điều hành tốt, Khái niệm hệ điều hành của Silberscatz, Gavin và Gange hoặc Thiết kế hệ điều hành của Andrew Tanenbaum. Ngoài ra một cái gì đó như Nachos từ Berkeley hoặc Pintos từ Stanford là các hệ điều hành nhỏ được xây dựng để học và có những ý tưởng tương tự trong đó.


0

Tôi đã thử điều này trên Ubuntu 16.04 tháng trước. Giống như 0xACE đã nói, HĐH hiện đại phân bổ một trang ảo hoàn toàn bằng không khi bạn gọi là malloc (). Nhưng, nếu bạn không ghi bất cứ điều gì vào bộ đệm được phân bổ, nó sẽ không được ánh xạ vào bộ nhớ vật lý (nghĩa là nguyên tắc sao chép trên ghi), do đó bạn sẽ luôn đọc các số không từ một khối "chưa được khởi tạo". Có thể có một số HĐH nhúng được biên dịch với tùy chọn "CONFIG_MMAP_ALLOW_UNITIALIZED" để có hiệu suất tốt hơn, trong trường hợp này bạn có thể nhận được những gì bạn đã sử dụng.


-1

Không, điều này sẽ không cho phép chương trình khác đọc bộ nhớ của người khác nhờ vào phép thuật phân trang . Bằng cách này, tổng sử dụng bộ nhớ có thể vượt quá ram vật lý bằng cách giảm tải các phần của nó vào ổ cứng.

Ngoài ra, bộ nhớ tối đa mà một quá trình có thể phân bổ bị hệ điều hành tùy ý giới hạn (tối đa 4 hợp đồng cho kiến ​​trúc 32 bit) sau đó alloccuộc gọi tiếp theo sẽ trả về lỗi hết bộ nhớ.


Không có API cụ thể nền tảng nào có thể phá vỡ điều này? Tôi thực sự không biết, nhưng tôi sẽ không ngạc nhiên (ví dụ: Linux cho phép ngăn hệ điều hành di chuyển một trang ra khỏi bộ nhớ vật lý, thông qua mlock).

Nếu có 4 GB RAM và phân trang bị giới hạn ở 8 GB, nếu ứng dụng yêu cầu 12 GB (trên x64) thì sao?
Arseni Mourzenko

sau đó các cuộc gọi hệ thống sẽ trả về lỗi khi vẫn còn quá ít bộ nhớ trống, hoặc máy tính sẽ đơn giản dừng lại khi không còn lại ...
ratchet freak

4
Anh ta không hỏi về việc đọc bộ nhớ của người khác, mà là đọc bộ nhớ LIÊN QUAN của họ. Phần ram đó hiện đang miễn phí, và .... Tôi không nghĩ rằng ... các sơ đồ phân trang không có bộ nhớ sau khi nó được giải phóng. Vì vậy, chương trình sẽ phân bổ một khối bộ nhớ và phân tích dữ liệu chưa được khởi tạo ở đó.
Philip

@philip đúng, tôi đang hỏi cụ thể về bộ nhớ đã giải phóng.
Điều
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.