Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mingo/linux-2.6-x86-fixes4
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mingo/linux-2.6-x86-fixes4: x86: harden kernel code patching x86: clean up text_poke() x86: fix text_poke() x86: remove set_fixmap() warning x86: make __set_fixmap() non-init x86: make clear_fixmap() available on 64-bit as well
This commit is contained in:
@@ -511,31 +511,30 @@ void *__kprobes text_poke(void *addr, const void *opcode, size_t len)
|
|||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
char *vaddr;
|
char *vaddr;
|
||||||
int nr_pages = 2;
|
int nr_pages = 2;
|
||||||
|
struct page *pages[2];
|
||||||
|
int i;
|
||||||
|
|
||||||
BUG_ON(len > sizeof(long));
|
if (!core_kernel_text((unsigned long)addr)) {
|
||||||
BUG_ON((((long)addr + len - 1) & ~(sizeof(long) - 1))
|
pages[0] = vmalloc_to_page(addr);
|
||||||
- ((long)addr & ~(sizeof(long) - 1)));
|
pages[1] = vmalloc_to_page(addr + PAGE_SIZE);
|
||||||
if (kernel_text_address((unsigned long)addr)) {
|
|
||||||
struct page *pages[2] = { virt_to_page(addr),
|
|
||||||
virt_to_page(addr + PAGE_SIZE) };
|
|
||||||
if (!pages[1])
|
|
||||||
nr_pages = 1;
|
|
||||||
vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
|
|
||||||
BUG_ON(!vaddr);
|
|
||||||
local_irq_save(flags);
|
|
||||||
memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
|
|
||||||
local_irq_restore(flags);
|
|
||||||
vunmap(vaddr);
|
|
||||||
} else {
|
} else {
|
||||||
/*
|
pages[0] = virt_to_page(addr);
|
||||||
* modules are in vmalloc'ed memory, always writable.
|
WARN_ON(!PageReserved(pages[0]));
|
||||||
*/
|
pages[1] = virt_to_page(addr + PAGE_SIZE);
|
||||||
local_irq_save(flags);
|
|
||||||
memcpy(addr, opcode, len);
|
|
||||||
local_irq_restore(flags);
|
|
||||||
}
|
}
|
||||||
|
BUG_ON(!pages[0]);
|
||||||
|
if (!pages[1])
|
||||||
|
nr_pages = 1;
|
||||||
|
vaddr = vmap(pages, nr_pages, VM_MAP, PAGE_KERNEL);
|
||||||
|
BUG_ON(!vaddr);
|
||||||
|
local_irq_save(flags);
|
||||||
|
memcpy(&vaddr[(unsigned long)addr & ~PAGE_MASK], opcode, len);
|
||||||
|
local_irq_restore(flags);
|
||||||
|
vunmap(vaddr);
|
||||||
sync_core();
|
sync_core();
|
||||||
/* Could also do a CLFLUSH here to speed up CPU recovery; but
|
/* Could also do a CLFLUSH here to speed up CPU recovery; but
|
||||||
that causes hangs on some VIA CPUs. */
|
that causes hangs on some VIA CPUs. */
|
||||||
|
for (i = 0; i < len; i++)
|
||||||
|
BUG_ON(((char *)addr)[i] != ((char *)opcode)[i]);
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
@@ -135,7 +135,7 @@ static __init void *spp_getpage(void)
|
|||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static __init void
|
static void
|
||||||
set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
|
set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
|
||||||
{
|
{
|
||||||
pgd_t *pgd;
|
pgd_t *pgd;
|
||||||
@@ -173,7 +173,7 @@ set_pte_phys(unsigned long vaddr, unsigned long phys, pgprot_t prot)
|
|||||||
new_pte = pfn_pte(phys >> PAGE_SHIFT, prot);
|
new_pte = pfn_pte(phys >> PAGE_SHIFT, prot);
|
||||||
|
|
||||||
pte = pte_offset_kernel(pmd, vaddr);
|
pte = pte_offset_kernel(pmd, vaddr);
|
||||||
if (!pte_none(*pte) &&
|
if (!pte_none(*pte) && pte_val(new_pte) &&
|
||||||
pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask))
|
pte_val(*pte) != (pte_val(new_pte) & __supported_pte_mask))
|
||||||
pte_ERROR(*pte);
|
pte_ERROR(*pte);
|
||||||
set_pte(pte, new_pte);
|
set_pte(pte, new_pte);
|
||||||
@@ -214,8 +214,7 @@ void __init cleanup_highmap(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* NOTE: this is meant to be run only at boot */
|
/* NOTE: this is meant to be run only at boot */
|
||||||
void __init
|
void __set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
|
||||||
__set_fixmap(enum fixed_addresses idx, unsigned long phys, pgprot_t prot)
|
|
||||||
{
|
{
|
||||||
unsigned long address = __fix_to_virt(idx);
|
unsigned long address = __fix_to_virt(idx);
|
||||||
|
|
||||||
|
@@ -1,5 +1,13 @@
|
|||||||
|
#ifndef _ASM_FIXMAP_H
|
||||||
|
#define _ASM_FIXMAP_H
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
# include "fixmap_32.h"
|
# include "fixmap_32.h"
|
||||||
#else
|
#else
|
||||||
# include "fixmap_64.h"
|
# include "fixmap_64.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define clear_fixmap(idx) \
|
||||||
|
__set_fixmap(idx, 0, __pgprot(0))
|
||||||
|
|
||||||
|
#endif
|
||||||
|
@@ -10,8 +10,8 @@
|
|||||||
* Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
|
* Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _ASM_FIXMAP_H
|
#ifndef _ASM_FIXMAP_32_H
|
||||||
#define _ASM_FIXMAP_H
|
#define _ASM_FIXMAP_32_H
|
||||||
|
|
||||||
|
|
||||||
/* used by vmalloc.c, vsyscall.lds.S.
|
/* used by vmalloc.c, vsyscall.lds.S.
|
||||||
@@ -121,9 +121,6 @@ extern void reserve_top_address(unsigned long reserve);
|
|||||||
#define set_fixmap_nocache(idx, phys) \
|
#define set_fixmap_nocache(idx, phys) \
|
||||||
__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
|
__set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
|
||||||
|
|
||||||
#define clear_fixmap(idx) \
|
|
||||||
__set_fixmap(idx, 0, __pgprot(0))
|
|
||||||
|
|
||||||
#define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP)
|
#define FIXADDR_TOP ((unsigned long)__FIXADDR_TOP)
|
||||||
|
|
||||||
#define __FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT)
|
#define __FIXADDR_SIZE (__end_of_permanent_fixed_addresses << PAGE_SHIFT)
|
||||||
|
@@ -8,8 +8,8 @@
|
|||||||
* Copyright (C) 1998 Ingo Molnar
|
* Copyright (C) 1998 Ingo Molnar
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _ASM_FIXMAP_H
|
#ifndef _ASM_FIXMAP_64_H
|
||||||
#define _ASM_FIXMAP_H
|
#define _ASM_FIXMAP_64_H
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <asm/apicdef.h>
|
#include <asm/apicdef.h>
|
||||||
|
Reference in New Issue
Block a user