• R
    module: trim exception table on init free. · ad6561df
    Rusty Russell 提交于
    It's theoretically possible that there are exception table entries
    which point into the (freed) init text of modules.  These could cause
    future problems if other modules get loaded into that memory and cause
    an exception as we'd see the wrong fixup.  The only case I know of is
    kvm-intel.ko (when CONFIG_CC_OPTIMIZE_FOR_SIZE=n).
    
    Amerigo fixed this long-standing FIXME in the x86 version, but this
    patch is more general.
    
    This implements trim_init_extable(); most archs are simple since they
    use the standard lib/extable.c sort code.  Alpha and IA64 use relative
    addresses in their fixups, so thier trimming is a slight variation.
    
    Sparc32 is unique; it doesn't seem to define ARCH_HAS_SORT_EXTABLE,
    yet it defines its own sort_extable() which overrides the one in lib.
    It doesn't sort, so we have to mark deleted entries instead of
    actually trimming them.
    Inspired-by: NAmerigo Wang <amwang@redhat.com>
    Signed-off-by: NRusty Russell <rusty@rustcorp.com.au>
    Cc: linux-alpha@vger.kernel.org
    Cc: sparclinux@vger.kernel.org
    Cc: linux-ia64@vger.kernel.org
    ad6561df
extable.c 2.4 KB
/*
 * Derived from arch/ppc/mm/extable.c and arch/i386/mm/extable.c.
 *
 * Copyright (C) 2004 Paul Mackerras, IBM Corp.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/sort.h>
#include <asm/uaccess.h>

#ifndef ARCH_HAS_SORT_EXTABLE
/*
 * The exception table needs to be sorted so that the binary
 * search that we use to find entries in it works properly.
 * This is used both for the kernel exception table and for
 * the exception tables of modules that get loaded.
 */
static int cmp_ex(const void *a, const void *b)
{
	const struct exception_table_entry *x = a, *y = b;

	/* avoid overflow */
	if (x->insn > y->insn)
		return 1;
	if (x->insn < y->insn)
		return -1;
	return 0;
}

void sort_extable(struct exception_table_entry *start,
		  struct exception_table_entry *finish)
{
	sort(start, finish - start, sizeof(struct exception_table_entry),
	     cmp_ex, NULL);
}

#ifdef CONFIG_MODULES
/*
 * If the exception table is sorted, any referring to the module init
 * will be at the beginning or the end.
 */
void trim_init_extable(struct module *m)
{
	/*trim the beginning*/
	while (m->num_exentries && within_module_init(m->extable[0].insn, m)) {
		m->extable++;
		m->num_exentries--;
	}
	/*trim the end*/
	while (m->num_exentries &&
		within_module_init(m->extable[m->num_exentries-1].insn, m))
		m->num_exentries--;
}
#endif /* CONFIG_MODULES */
#endif /* !ARCH_HAS_SORT_EXTABLE */

#ifndef ARCH_HAS_SEARCH_EXTABLE
/*
 * Search one exception table for an entry corresponding to the
 * given instruction address, and return the address of the entry,
 * or NULL if none is found.
 * We use a binary search, and thus we assume that the table is
 * already sorted.
 */
const struct exception_table_entry *
search_extable(const struct exception_table_entry *first,
	       const struct exception_table_entry *last,
	       unsigned long value)
{
	while (first <= last) {
		const struct exception_table_entry *mid;

		mid = ((last - first) >> 1) + first;
		/*
		 * careful, the distance between value and insn
		 * can be larger than MAX_LONG:
		 */
		if (mid->insn < value)
			first = mid + 1;
		else if (mid->insn > value)
			last = mid - 1;
		else
			return mid;
        }
        return NULL;
}
#endif
反馈
建议
客服 返回
顶部