aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
authorKonstantin Khlebnikov <khlebnikov@yandex-team.ru>2015-09-08 18:00:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-09-08 18:35:28 -0400
commit1c90308e7a77af6742a97d1021cca923b23b7f0d (patch)
tree6b328205937da8bd5d7682975695665f40bef892 /fs/proc
parent356515e7b64c2629f686109d426baaf868cdf7e8 (diff)
pagemap: hide physical addresses from non-privileged users
This patch makes pagemap readable for normal users and hides physical addresses from them. For some use-cases PFN isn't required at all. See http://lkml.kernel.org/r/1425935472-17949-1-git-send-email-kirill@shutemov.name Fixes: ab676b7d6fbf ("pagemap: do not leak physical addresses to non-privileged userspace") Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> Cc: Naoya Horiguchi <n-horiguchi@ah.jp.nec.com> Reviewed-by: Mark Williamson <mwilliamson@undo-software.com> Tested-by: Mark Williamson <mwilliamson@undo-software.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/task_mmu.c25
1 files changed, 14 insertions, 11 deletions
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 98ba9ea96b19..bc651644b1b2 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -939,6 +939,7 @@ typedef struct {
939struct pagemapread { 939struct pagemapread {
940 int pos, len; /* units: PM_ENTRY_BYTES, not bytes */ 940 int pos, len; /* units: PM_ENTRY_BYTES, not bytes */
941 pagemap_entry_t *buffer; 941 pagemap_entry_t *buffer;
942 bool show_pfn;
942}; 943};
943 944
944#define PAGEMAP_WALK_SIZE (PMD_SIZE) 945#define PAGEMAP_WALK_SIZE (PMD_SIZE)
@@ -1015,7 +1016,8 @@ static pagemap_entry_t pte_to_pagemap_entry(struct pagemapread *pm,
1015 struct page *page = NULL; 1016 struct page *page = NULL;
1016 1017
1017 if (pte_present(pte)) { 1018 if (pte_present(pte)) {
1018 frame = pte_pfn(pte); 1019 if (pm->show_pfn)
1020 frame = pte_pfn(pte);
1019 flags |= PM_PRESENT; 1021 flags |= PM_PRESENT;
1020 page = vm_normal_page(vma, addr, pte); 1022 page = vm_normal_page(vma, addr, pte);
1021 if (pte_soft_dirty(pte)) 1023 if (pte_soft_dirty(pte))
@@ -1065,8 +1067,9 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end,
1065 */ 1067 */
1066 if (pmd_present(pmd)) { 1068 if (pmd_present(pmd)) {
1067 flags |= PM_PRESENT; 1069 flags |= PM_PRESENT;
1068 frame = pmd_pfn(pmd) + 1070 if (pm->show_pfn)
1069 ((addr & ~PMD_MASK) >> PAGE_SHIFT); 1071 frame = pmd_pfn(pmd) +
1072 ((addr & ~PMD_MASK) >> PAGE_SHIFT);
1070 } 1073 }
1071 1074
1072 for (; addr != end; addr += PAGE_SIZE) { 1075 for (; addr != end; addr += PAGE_SIZE) {
@@ -1075,7 +1078,7 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end,
1075 err = add_to_pagemap(addr, &pme, pm); 1078 err = add_to_pagemap(addr, &pme, pm);
1076 if (err) 1079 if (err)
1077 break; 1080 break;
1078 if (flags & PM_PRESENT) 1081 if (pm->show_pfn && (flags & PM_PRESENT))
1079 frame++; 1082 frame++;
1080 } 1083 }
1081 spin_unlock(ptl); 1084 spin_unlock(ptl);
@@ -1129,8 +1132,9 @@ static int pagemap_hugetlb_range(pte_t *ptep, unsigned long hmask,
1129 flags |= PM_FILE; 1132 flags |= PM_FILE;
1130 1133
1131 flags |= PM_PRESENT; 1134 flags |= PM_PRESENT;
1132 frame = pte_pfn(pte) + 1135 if (pm->show_pfn)
1133 ((addr & ~hmask) >> PAGE_SHIFT); 1136 frame = pte_pfn(pte) +
1137 ((addr & ~hmask) >> PAGE_SHIFT);
1134 } 1138 }
1135 1139
1136 for (; addr != end; addr += PAGE_SIZE) { 1140 for (; addr != end; addr += PAGE_SIZE) {
@@ -1139,7 +1143,7 @@ static int pagemap_hugetlb_range(pte_t *ptep, unsigned long hmask,
1139 err = add_to_pagemap(addr, &pme, pm); 1143 err = add_to_pagemap(addr, &pme, pm);
1140 if (err) 1144 if (err)
1141 return err; 1145 return err;
1142 if (flags & PM_PRESENT) 1146 if (pm->show_pfn && (flags & PM_PRESENT))
1143 frame++; 1147 frame++;
1144 } 1148 }
1145 1149
@@ -1198,6 +1202,9 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
1198 if (!count) 1202 if (!count)
1199 goto out_mm; 1203 goto out_mm;
1200 1204
1205 /* do not disclose physical addresses: attack vector */
1206 pm.show_pfn = file_ns_capable(file, &init_user_ns, CAP_SYS_ADMIN);
1207
1201 pm.len = (PAGEMAP_WALK_SIZE >> PAGE_SHIFT); 1208 pm.len = (PAGEMAP_WALK_SIZE >> PAGE_SHIFT);
1202 pm.buffer = kmalloc(pm.len * PM_ENTRY_BYTES, GFP_TEMPORARY); 1209 pm.buffer = kmalloc(pm.len * PM_ENTRY_BYTES, GFP_TEMPORARY);
1203 ret = -ENOMEM; 1210 ret = -ENOMEM;
@@ -1267,10 +1274,6 @@ static int pagemap_open(struct inode *inode, struct file *file)
1267{ 1274{
1268 struct mm_struct *mm; 1275 struct mm_struct *mm;
1269 1276
1270 /* do not disclose physical addresses: attack vector */
1271 if (!capable(CAP_SYS_ADMIN))
1272 return -EPERM;
1273
1274 mm = proc_mem_open(inode, PTRACE_MODE_READ); 1277 mm = proc_mem_open(inode, PTRACE_MODE_READ);
1275 if (IS_ERR(mm)) 1278 if (IS_ERR(mm))
1276 return PTR_ERR(mm); 1279 return PTR_ERR(mm);