[PATCH] fix ppc64 kernel access of user pages

From: Anton Blanchard
Date: Fri Feb 27 2004 - 09:25:28 EST



Set the ks bit on userspace segments otherwise the kernel can read/write
into userspace mprotected pages.

--

diff -Nru a/arch/ppc64/kernel/head.S b/arch/ppc64/kernel/head.S
--- a/arch/ppc64/kernel/head.S Fri Feb 27 22:59:30 2004
+++ b/arch/ppc64/kernel/head.S Fri Feb 27 22:59:30 2004
@@ -826,7 +826,14 @@
_GLOBAL(do_hash_page_ISI)
li r4,0
_GLOBAL(do_hash_page_DSI)
- rlwimi r4,r23,32-13,30,30 /* Insert MSR_PR as _PAGE_USER */
+ /*
+ * We need to set the _PAGE_USER bit if MSR_PR is set or if we are
+ * accessing a userspace segment (even from the kernel). We assume
+ * kernel addresses always have the high bit set.
+ */
+ rotldi r0,r3,15 /* Move high bit into MSR_PR position */
+ orc r0,r23,r0
+ rlwimi r4,r0,32-13,30,30 /* Insert into _PAGE_USER */
ori r4,r4,1 /* add _PAGE_PRESENT */

mflr r21 /* Save LR in r21 */
diff -Nru a/arch/ppc64/kernel/stab.c b/arch/ppc64/kernel/stab.c
--- a/arch/ppc64/kernel/stab.c Fri Feb 27 22:59:30 2004
+++ b/arch/ppc64/kernel/stab.c Fri Feb 27 22:59:30 2004
@@ -73,6 +73,8 @@
unsigned long entry, group, old_esid, castout_entry, i;
unsigned int global_entry;
STE *ste, *castout_ste;
+ unsigned long kernel_segment = (REGION_ID(esid << SID_SHIFT) !=
+ USER_REGION_ID);

/* Search the primary group first. */
global_entry = (esid & 0x1f) << 3;
@@ -85,6 +87,8 @@
ste->dw1.dw1.vsid = vsid;
ste->dw0.dw0.esid = esid;
ste->dw0.dw0.kp = 1;
+ if (!kernel_segment)
+ ste->dw0.dw0.ks = 1;
asm volatile("eieio":::"memory");
ste->dw0.dw0.v = 1;
return (global_entry | entry);
@@ -131,6 +135,8 @@
old_esid = castout_ste->dw0.dw0.esid;
castout_ste->dw0.dw0.esid = esid;
castout_ste->dw0.dw0.kp = 1;
+ if (!kernel_segment)
+ castout_ste->dw0.dw0.ks = 1;
asm volatile("eieio" : : : "memory"); /* Order update */
castout_ste->dw0.dw0.v = 1;
asm volatile("slbie %0" : : "r" (old_esid << SID_SHIFT));
@@ -340,6 +346,8 @@
vsid_data.data.l = 1;
if (kernel_segment)
vsid_data.data.c = 1;
+ else
+ vsid_data.data.ks = 1;

esid_data.word0 = 0;
esid_data.data.esid = esid;
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/