[PATCH] fix ppc64 kernel access of user pages

From: Anton Blanchard (anton_at_samba.org)
Date: 02/27/04

  • Next message: Anton Blanchard: "[PATCH] ppc64 TLB flush rework"
    Date:	Sat, 28 Feb 2004 01:22:26 +1100
    To: torvalds@osdl.org
    
    

    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@vger.kernel.org
    More majordomo info at  http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at  http://www.tux.org/lkml/
    

  • Next message: Anton Blanchard: "[PATCH] ppc64 TLB flush rework"