summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.transmeta.com>2003-01-06 19:33:55 -0800
committerLinus Torvalds <torvalds@home.transmeta.com>2003-01-06 19:33:55 -0800
commitf3ef7ee5ad2388e0a63248bc839b51bb608c188f (patch)
tree96a2560d643dd5aec1e6aaa2bb42a6eaaab4fe4b
parenteeacc9367455a3bbbed00ced63a06c65fe347784 (diff)
parent0c9fffaac417a14fde82989a4960551988af9046 (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.c9
-rw-r--r--arch/i386/kernel/signal.c48
-rw-r--r--arch/i386/kernel/sysenter.c14
-rw-r--r--arch/x86_64/kernel/setup.c2
-rw-r--r--arch/x86_64/kernel/traps.c14
-rw-r--r--arch/x86_64/mm/extable.c65
-rw-r--r--arch/x86_64/mm/fault.c8
-rw-r--r--include/asm-x86_64/uaccess.h3
-rw-r--r--net/unix/af_unix.c3
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;