diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2003-01-06 19:33:55 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.transmeta.com> | 2003-01-06 19:33:55 -0800 |
| commit | f3ef7ee5ad2388e0a63248bc839b51bb608c188f (patch) | |
| tree | 96a2560d643dd5aec1e6aaa2bb42a6eaaab4fe4b | |
| parent | eeacc9367455a3bbbed00ced63a06c65fe347784 (diff) | |
| parent | 0c9fffaac417a14fde82989a4960551988af9046 (diff) | |
Merge bk://ldm.bkbits.net/linux-2.5-core
into home.transmeta.com:/home/torvalds/v2.5/linux
| -rw-r--r-- | arch/alpha/kernel/module.c | 9 | ||||
| -rw-r--r-- | arch/i386/kernel/signal.c | 48 | ||||
| -rw-r--r-- | arch/i386/kernel/sysenter.c | 14 | ||||
| -rw-r--r-- | arch/x86_64/kernel/setup.c | 2 | ||||
| -rw-r--r-- | arch/x86_64/kernel/traps.c | 14 | ||||
| -rw-r--r-- | arch/x86_64/mm/extable.c | 65 | ||||
| -rw-r--r-- | arch/x86_64/mm/fault.c | 8 | ||||
| -rw-r--r-- | include/asm-x86_64/uaccess.h | 3 | ||||
| -rw-r--r-- | net/unix/af_unix.c | 3 |
9 files changed, 64 insertions, 102 deletions
diff --git a/arch/alpha/kernel/module.c b/arch/alpha/kernel/module.c index 0d3f1f35a937..143c27efdbcb 100644 --- a/arch/alpha/kernel/module.c +++ b/arch/alpha/kernel/module.c @@ -87,13 +87,12 @@ process_reloc_for_got(Elf64_Rela *rela, } int -module_frob_arch_sections(const Elf64_Ehdr *hdr, const Elf64_Shdr *sechdrs, - const char *secstrings, struct module *me) +module_frob_arch_sections(Elf64_Ehdr *hdr, Elf64_Shdr *sechdrs, + char *secstrings, struct module *me) { struct got_entry *chains; Elf64_Rela *rela; - const Elf64_Shdr *esechdrs, *symtab, *s; - Elf64_Shdr *got; + Elf64_Shdr *esechdrs, *symtab, *s, *got; unsigned long nsyms, nrela, i; esechdrs = sechdrs + hdr->e_shnum; @@ -106,7 +105,7 @@ module_frob_arch_sections(const Elf64_Ehdr *hdr, const Elf64_Shdr *sechdrs, if (s->sh_type == SHT_SYMTAB) symtab = s; else if (!strcmp(".got", secstrings + s->sh_name)) { - got = (Elf64_Shdr *) s; + got = s; me->arch.gotsecindex = s - sechdrs; } diff --git a/arch/i386/kernel/signal.c b/arch/i386/kernel/signal.c index 1c17237fe978..56a0af099074 100644 --- a/arch/i386/kernel/signal.c +++ b/arch/i386/kernel/signal.c @@ -378,17 +378,19 @@ static void setup_frame(int sig, struct k_sigaction *ka, if (err) goto give_sigsegv; - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) { - err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); - } else { - err |= __put_user(frame->retcode, &frame->pretcode); - /* This is popl %eax ; movl $,%eax ; int $0x80 */ - err |= __put_user(0xb858, (short *)(frame->retcode+0)); - err |= __put_user(__NR_sigreturn, (int *)(frame->retcode+2)); - err |= __put_user(0x80cd, (short *)(frame->retcode+6)); - } + /* Set up to return from userspace. */ + err |= __put_user(fix_to_virt(FIX_VSYSCALL) + 32, &frame->pretcode); + + /* + * This is popl %eax ; movl $,%eax ; int $0x80 + * + * WE DO NOT USE IT ANY MORE! It's only left here for historical + * reasons and because gdb uses it as a signature to notice + * signal handler stack frames. + */ + err |= __put_user(0xb858, (short *)(frame->retcode+0)); + err |= __put_user(__NR_sigreturn, (int *)(frame->retcode+2)); + err |= __put_user(0x80cd, (short *)(frame->retcode+6)); if (err) goto give_sigsegv; @@ -453,17 +455,19 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info, if (err) goto give_sigsegv; - /* Set up to return from userspace. If provided, use a stub - already in userspace. */ - if (ka->sa.sa_flags & SA_RESTORER) { - err |= __put_user(ka->sa.sa_restorer, &frame->pretcode); - } else { - err |= __put_user(frame->retcode, &frame->pretcode); - /* This is movl $,%eax ; int $0x80 */ - err |= __put_user(0xb8, (char *)(frame->retcode+0)); - err |= __put_user(__NR_rt_sigreturn, (int *)(frame->retcode+1)); - err |= __put_user(0x80cd, (short *)(frame->retcode+5)); - } + /* Set up to return from userspace. */ + err |= __put_user(fix_to_virt(FIX_VSYSCALL) + 64, &frame->pretcode); + + /* + * This is movl $,%eax ; int $0x80 + * + * WE DO NOT USE IT ANY MORE! It's only left here for historical + * reasons and because gdb uses it as a signature to notice + * signal handler stack frames. + */ + err |= __put_user(0xb8, (char *)(frame->retcode+0)); + err |= __put_user(__NR_rt_sigreturn, (int *)(frame->retcode+1)); + err |= __put_user(0x80cd, (short *)(frame->retcode+5)); if (err) goto give_sigsegv; diff --git a/arch/i386/kernel/sysenter.c b/arch/i386/kernel/sysenter.c index fcf265b2508a..0ea164c4f718 100644 --- a/arch/i386/kernel/sysenter.c +++ b/arch/i386/kernel/sysenter.c @@ -16,6 +16,7 @@ #include <asm/cpufeature.h> #include <asm/msr.h> #include <asm/pgtable.h> +#include <asm/unistd.h> extern asmlinkage void sysenter_entry(void); @@ -73,10 +74,23 @@ static int __init sysenter_setup(void) 0x59, /* pop %ecx */ 0xc3 /* ret */ }; + static const char sigreturn[] = { + /* 32: sigreturn point */ + 0x58, /* popl %eax */ + 0xb8, __NR_sigreturn, 0, 0, 0, /* movl $__NR_sigreturn, %eax */ + 0xcd, 0x80, /* int $0x80 */ + }; + static const char rt_sigreturn[] = { + /* 64: rt_sigreturn point */ + 0xb8, __NR_rt_sigreturn, 0, 0, 0, /* movl $__NR_rt_sigreturn, %eax */ + 0xcd, 0x80, /* int $0x80 */ + }; unsigned long page = get_zeroed_page(GFP_ATOMIC); __set_fixmap(FIX_VSYSCALL, __pa(page), PAGE_READONLY); memcpy((void *) page, int80, sizeof(int80)); + memcpy((void *)(page + 32), sigreturn, sizeof(sigreturn)); + memcpy((void *)(page + 64), rt_sigreturn, sizeof(rt_sigreturn)); if (!boot_cpu_has(X86_FEATURE_SEP)) return 0; diff --git a/arch/x86_64/kernel/setup.c b/arch/x86_64/kernel/setup.c index 7dfbe5da06ee..255d7a1a6952 100644 --- a/arch/x86_64/kernel/setup.c +++ b/arch/x86_64/kernel/setup.c @@ -384,8 +384,6 @@ void __init setup_arch(char **cmdline_p) conswitchp = &dummy_con; #endif #endif - - exception_table_check(); } #ifndef CONFIG_X86_TSC diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index af118388f169..8741e6ccc126 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -397,7 +397,8 @@ static void do_trap(int trapnr, int signr, char *str, /* kernel trap */ { - unsigned long fixup = search_exception_table(regs->rip); + const struct exception_table_entry *fixup; + fixup = search_exception_tables(regs->rip); if (fixup) { extern int exception_trace; if (exception_trace) @@ -405,7 +406,7 @@ static void do_trap(int trapnr, int signr, char *str, "%s: fixed kernel exception at %lx err:%ld\n", current->comm, regs->rip, error_code); - regs->rip = fixup; + regs->rip = fixup->fixup; } else die(str, regs, error_code); return; @@ -449,8 +450,6 @@ asmlinkage void do_int3(struct pt_regs * regs, long error_code) do_trap(3, SIGTRAP, "int3", regs, error_code, NULL); } -extern void dump_pagetable(unsigned long); - asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) { #ifdef CONFIG_CHECKING @@ -479,13 +478,12 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) /* kernel gp */ { - unsigned long fixup; - fixup = search_exception_table(regs->rip); + const struct exception_table_entry *fixup; + fixup = search_exception_tables(regs->rip); if (fixup) { - regs->rip = fixup; + regs->rip = fixup->fixup; return; } -// dump_pagetable(regs->rip); die("general protection fault", regs, error_code); } } diff --git a/arch/x86_64/mm/extable.c b/arch/x86_64/mm/extable.c index 710426864f3b..ab350121aab6 100644 --- a/arch/x86_64/mm/extable.c +++ b/arch/x86_64/mm/extable.c @@ -6,32 +6,12 @@ #include <linux/module.h> #include <linux/spinlock.h> #include <asm/uaccess.h> -#include <linux/init.h> -extern const struct exception_table_entry __start___ex_table[]; -extern const struct exception_table_entry __stop___ex_table[]; - - -void __init exception_table_check(void) -{ - const struct exception_table_entry *e; - unsigned long prev; - - prev = 0; - for (e = __start___ex_table; e < __stop___ex_table; e++) { - if (e->insn < prev) { - panic("unordered exception table at %016lx:%016lx and %016lx:%016lx\n", - prev, e[-1].fixup, - e->insn, e->fixup); - } - prev = e->insn; - } -} - -static unsigned long -search_one_table(const struct exception_table_entry *first, - const struct exception_table_entry *last, - unsigned long value) +/* Simple binary search */ +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; @@ -40,42 +20,11 @@ search_one_table(const struct exception_table_entry *first, mid = (last - first) / 2 + first; diff = mid->insn - value; if (diff == 0) - return mid->fixup; + return mid; else if (diff < 0) first = mid+1; else last = mid-1; } - return 0; -} - -extern spinlock_t modlist_lock; - -unsigned long -search_exception_table(unsigned long addr) -{ - unsigned long ret = 0; - unsigned long flags; - -#ifndef CONFIG_MODULES - /* There is only the kernel to search. */ - return search_one_table(__start___ex_table, __stop___ex_table-1, addr); -#else - /* The kernel is the last "module" -- no need to treat it special. */ - struct list_head *i; - - spin_lock_irqsave(&modlist_lock, flags); - list_for_each(i, &extables) { - struct exception_table *ex = - list_entry(i,struct exception_table, list); - if (ex->num_entries == 0) - continue; - ret = search_one_table(ex->entry, - ex->entry + ex->num_entries - 1, addr); - if (ret) - break; - } - spin_unlock_irqrestore(&modlist_lock, flags); - return ret; -#endif + return NULL; } diff --git a/arch/x86_64/mm/fault.c b/arch/x86_64/mm/fault.c index 00708d1d82e3..c662d6726339 100644 --- a/arch/x86_64/mm/fault.c +++ b/arch/x86_64/mm/fault.c @@ -22,6 +22,7 @@ #include <linux/tty.h> #include <linux/vt_kern.h> /* For unblank_screen() */ #include <linux/compiler.h> +#include <linux/module.h> #include <asm/system.h> #include <asm/uaccess.h> @@ -101,7 +102,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) struct mm_struct *mm; struct vm_area_struct * vma; unsigned long address; - unsigned long fixup; + const struct exception_table_entry *fixup; int write; siginfo_t info; @@ -239,8 +240,9 @@ bad_area_nosemaphore: no_context: /* Are we prepared to handle this kernel fault? */ - if ((fixup = search_exception_table(regs->rip)) != 0) { - regs->rip = fixup; + fixup = search_exception_tables(regs->rip); + if (fixup) { + regs->rip = fixup->fixup; if (0 && exception_trace) printk(KERN_ERR "%s: fixed kernel exception at %lx address %lx err:%ld\n", diff --git a/include/asm-x86_64/uaccess.h b/include/asm-x86_64/uaccess.h index 47e78d59e27b..c18c2d6a77b2 100644 --- a/include/asm-x86_64/uaccess.h +++ b/include/asm-x86_64/uaccess.h @@ -71,9 +71,6 @@ struct exception_table_entry unsigned long insn, fixup; }; -/* Returns 0 if exception not found and fixup otherwise. */ -extern unsigned long search_exception_table(unsigned long); - /* * These are the main single-value transfer routines. They automatically diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 60212c864efa..4bf58bcd7723 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1109,7 +1109,7 @@ out: static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_len, int peer) { struct sock *sk = sock->sk; - struct unix_sock *u = unix_sk(sk); + struct unix_sock *u; struct sockaddr_un *sunaddr=(struct sockaddr_un *)uaddr; int err = 0; @@ -1124,6 +1124,7 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int *uaddr_ sock_hold(sk); } + u = unix_sk(sk); unix_state_rlock(sk); if (!u->addr) { sunaddr->sun_family = AF_UNIX; |
