]> git.hungrycats.org Git - linux/commitdiff
[PATCH] ppc64: fix kernel access of user pages
authorAnton Blanchard <anton@samba.org>
Fri, 27 Feb 2004 01:28:17 +0000 (17:28 -0800)
committerAnton Blanchard <anton@samba.org>
Fri, 27 Feb 2004 01:28:17 +0000 (17:28 -0800)
Set the ks bit on userspace segments otherwise the kernel can read/write
into userspace mprotected pages.

arch/ppc64/kernel/head.S
arch/ppc64/kernel/stab.c

index f1600468546a06ada508330900ed3009b754b9eb..fef3209ec2c9434a67fb35f72f258f42d094ed85 100644 (file)
@@ -826,7 +826,14 @@ SystemCall_common:
 _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 */
index 34fa6f339ae655bbbec0e3054936f84bfa7252fe..9906768dc41d3640764dd560bbb9482156f6e40d 100644 (file)
@@ -77,6 +77,8 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
        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;
@@ -89,6 +91,8 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
                                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);
@@ -135,6 +139,8 @@ static int make_ste(unsigned long stab, unsigned long esid, unsigned long vsid)
        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)); 
@@ -344,6 +350,8 @@ static void make_slbe(unsigned long esid, unsigned long vsid, int large,
                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;