Skip to content

Commit 8c82962

Browse files
yonghua zhengtorvalds
authored andcommitted
fs/proc/task_mmu.c: fix buffer overflow in add_page_map()
Recently we met quite a lot of random kernel panic issues after enabling CONFIG_PROC_PAGE_MONITOR. After debuggind we found this has something to do with following bug in pagemap: In struct pagemapread: struct pagemapread { int pos, len; pagemap_entry_t *buffer; bool v2; }; pos is number of PM_ENTRY_BYTES in buffer, but len is the size of buffer, it is a mistake to compare pos and len in add_page_map() for checking buffer is full or not, and this can lead to buffer overflow and random kernel panic issue. Correct len to be total number of PM_ENTRY_BYTES in buffer. [[email protected]: document pagemapread.pos and .len units, fix PM_ENTRY_BYTES definition] Signed-off-by: Yonghua Zheng <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 57a1a19 commit 8c82962

File tree

1 file changed

+4
-4
lines changed

1 file changed

+4
-4
lines changed

fs/proc/task_mmu.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -868,15 +868,15 @@ typedef struct {
868868
} pagemap_entry_t;
869869

870870
struct pagemapread {
871-
int pos, len;
871+
int pos, len; /* units: PM_ENTRY_BYTES, not bytes */
872872
pagemap_entry_t *buffer;
873873
bool v2;
874874
};
875875

876876
#define PAGEMAP_WALK_SIZE (PMD_SIZE)
877877
#define PAGEMAP_WALK_MASK (PMD_MASK)
878878

879-
#define PM_ENTRY_BYTES sizeof(u64)
879+
#define PM_ENTRY_BYTES sizeof(pagemap_entry_t)
880880
#define PM_STATUS_BITS 3
881881
#define PM_STATUS_OFFSET (64 - PM_STATUS_BITS)
882882
#define PM_STATUS_MASK (((1LL << PM_STATUS_BITS) - 1) << PM_STATUS_OFFSET)
@@ -1127,8 +1127,8 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
11271127
goto out_task;
11281128

11291129
pm.v2 = soft_dirty_cleared;
1130-
pm.len = PM_ENTRY_BYTES * (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
1131-
pm.buffer = kmalloc(pm.len, GFP_TEMPORARY);
1130+
pm.len = (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
1131+
pm.buffer = kmalloc(pm.len * PM_ENTRY_BYTES, GFP_TEMPORARY);
11321132
ret = -ENOMEM;
11331133
if (!pm.buffer)
11341134
goto out_task;

0 commit comments

Comments
 (0)