aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2016-04-09 17:10:20 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-04-09 17:10:20 -0400
commit5b5b7fd185e997ebc18f76b98b9f4ff148d3f5bb (patch)
tree160e41d335e29c234181670072bb6278fa8230d3
parent239467e852a4d2dcd255093bfafc92a9adbb76a2 (diff)
parentcb910c1714cc198fa868695c276a2bff0f8900e7 (diff)
Merge branch 'parisc-4.6-3' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux
Pull parisc fixes from Helge Deller: "Since commit 0de798584bde ("parisc: Use generic extable search and sort routines") module loading is boken on parisc, because the parisc module loader wasn't prepared for the new R_PARISC_PCREL32 relocations. In addition, due to that breakage, Mikulas Patocka noticed that handling exceptions from modules probably never worked on parisc. It was just masked by the fact that exceptions from modules don't happen during normal use. This patch series fixes those issues and survives the tests of the lib/test_user_copy kernel module test. Some patches are tagged for stable" * 'parisc-4.6-3' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux: parisc: Update comment regarding relative extable support parisc: Unbreak handling exceptions from kernel modules parisc: Fix kernel crash with reversed copy_from_user() parisc: Avoid function pointers for kernel exception routines parisc: Handle R_PARISC_PCREL32 relocations in kernel modules
-rw-r--r--arch/parisc/include/asm/uaccess.h11
-rw-r--r--arch/parisc/kernel/asm-offsets.c1
-rw-r--r--arch/parisc/kernel/module.c8
-rw-r--r--arch/parisc/kernel/parisc_ksyms.c10
-rw-r--r--arch/parisc/kernel/traps.c3
-rw-r--r--arch/parisc/lib/fixup.S6
-rw-r--r--arch/parisc/mm/fault.c1
7 files changed, 29 insertions, 11 deletions
diff --git a/arch/parisc/include/asm/uaccess.h b/arch/parisc/include/asm/uaccess.h
index d4dd6e58682c..7955e43f3f3f 100644
--- a/arch/parisc/include/asm/uaccess.h
+++ b/arch/parisc/include/asm/uaccess.h
@@ -44,20 +44,18 @@ static inline long access_ok(int type, const void __user * addr,
44#define LDD_USER(ptr) BUILD_BUG() 44#define LDD_USER(ptr) BUILD_BUG()
45#define STD_KERNEL(x, ptr) __put_kernel_asm64(x, ptr) 45#define STD_KERNEL(x, ptr) __put_kernel_asm64(x, ptr)
46#define STD_USER(x, ptr) __put_user_asm64(x, ptr) 46#define STD_USER(x, ptr) __put_user_asm64(x, ptr)
47#define ASM_WORD_INSN ".word\t"
48#else 47#else
49#define LDD_KERNEL(ptr) __get_kernel_asm("ldd", ptr) 48#define LDD_KERNEL(ptr) __get_kernel_asm("ldd", ptr)
50#define LDD_USER(ptr) __get_user_asm("ldd", ptr) 49#define LDD_USER(ptr) __get_user_asm("ldd", ptr)
51#define STD_KERNEL(x, ptr) __put_kernel_asm("std", x, ptr) 50#define STD_KERNEL(x, ptr) __put_kernel_asm("std", x, ptr)
52#define STD_USER(x, ptr) __put_user_asm("std", x, ptr) 51#define STD_USER(x, ptr) __put_user_asm("std", x, ptr)
53#define ASM_WORD_INSN ".dword\t"
54#endif 52#endif
55 53
56/* 54/*
57 * The exception table contains two values: the first is an address 55 * The exception table contains two values: the first is the relative offset to
58 * for an instruction that is allowed to fault, and the second is 56 * the address of the instruction that is allowed to fault, and the second is
59 * the address to the fixup routine. Even on a 64bit kernel we could 57 * the relative offset to the address of the fixup routine. Since relative
60 * use a 32bit (unsigned int) address here. 58 * addresses are used, 32bit values are sufficient even on 64bit kernel.
61 */ 59 */
62 60
63#define ARCH_HAS_RELATIVE_EXTABLE 61#define ARCH_HAS_RELATIVE_EXTABLE
@@ -77,6 +75,7 @@ struct exception_table_entry {
77 */ 75 */
78struct exception_data { 76struct exception_data {
79 unsigned long fault_ip; 77 unsigned long fault_ip;
78 unsigned long fault_gp;
80 unsigned long fault_space; 79 unsigned long fault_space;
81 unsigned long fault_addr; 80 unsigned long fault_addr;
82}; 81};
diff --git a/arch/parisc/kernel/asm-offsets.c b/arch/parisc/kernel/asm-offsets.c
index d2f62570a7b1..78d30d2ea2d8 100644
--- a/arch/parisc/kernel/asm-offsets.c
+++ b/arch/parisc/kernel/asm-offsets.c
@@ -299,6 +299,7 @@ int main(void)
299#endif 299#endif
300 BLANK(); 300 BLANK();
301 DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip)); 301 DEFINE(EXCDATA_IP, offsetof(struct exception_data, fault_ip));
302 DEFINE(EXCDATA_GP, offsetof(struct exception_data, fault_gp));
302 DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space)); 303 DEFINE(EXCDATA_SPACE, offsetof(struct exception_data, fault_space));
303 DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr)); 304 DEFINE(EXCDATA_ADDR, offsetof(struct exception_data, fault_addr));
304 BLANK(); 305 BLANK();
diff --git a/arch/parisc/kernel/module.c b/arch/parisc/kernel/module.c
index b9d75d9fa9ac..a0ecdb4abcc8 100644
--- a/arch/parisc/kernel/module.c
+++ b/arch/parisc/kernel/module.c
@@ -660,6 +660,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
660 } 660 }
661 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); 661 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
662 break; 662 break;
663 case R_PARISC_PCREL32:
664 /* 32-bit PC relative address */
665 *loc = val - dot - 8 + addend;
666 break;
663 667
664 default: 668 default:
665 printk(KERN_ERR "module %s: Unknown relocation: %u\n", 669 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
@@ -788,6 +792,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
788 CHECK_RELOC(val, 22); 792 CHECK_RELOC(val, 22);
789 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val); 793 *loc = (*loc & ~0x3ff1ffd) | reassemble_22(val);
790 break; 794 break;
795 case R_PARISC_PCREL32:
796 /* 32-bit PC relative address */
797 *loc = val - dot - 8 + addend;
798 break;
791 case R_PARISC_DIR64: 799 case R_PARISC_DIR64:
792 /* 64-bit effective address */ 800 /* 64-bit effective address */
793 *loc64 = val + addend; 801 *loc64 = val + addend;
diff --git a/arch/parisc/kernel/parisc_ksyms.c b/arch/parisc/kernel/parisc_ksyms.c
index 568b2c61ea02..3cad8aadc69e 100644
--- a/arch/parisc/kernel/parisc_ksyms.c
+++ b/arch/parisc/kernel/parisc_ksyms.c
@@ -47,11 +47,11 @@ EXPORT_SYMBOL(__cmpxchg_u64);
47EXPORT_SYMBOL(lclear_user); 47EXPORT_SYMBOL(lclear_user);
48EXPORT_SYMBOL(lstrnlen_user); 48EXPORT_SYMBOL(lstrnlen_user);
49 49
50/* Global fixups */ 50/* Global fixups - defined as int to avoid creation of function pointers */
51extern void fixup_get_user_skip_1(void); 51extern int fixup_get_user_skip_1;
52extern void fixup_get_user_skip_2(void); 52extern int fixup_get_user_skip_2;
53extern void fixup_put_user_skip_1(void); 53extern int fixup_put_user_skip_1;
54extern void fixup_put_user_skip_2(void); 54extern int fixup_put_user_skip_2;
55EXPORT_SYMBOL(fixup_get_user_skip_1); 55EXPORT_SYMBOL(fixup_get_user_skip_1);
56EXPORT_SYMBOL(fixup_get_user_skip_2); 56EXPORT_SYMBOL(fixup_get_user_skip_2);
57EXPORT_SYMBOL(fixup_put_user_skip_1); 57EXPORT_SYMBOL(fixup_put_user_skip_1);
diff --git a/arch/parisc/kernel/traps.c b/arch/parisc/kernel/traps.c
index 16e0735e2f46..97d6b208e129 100644
--- a/arch/parisc/kernel/traps.c
+++ b/arch/parisc/kernel/traps.c
@@ -795,6 +795,9 @@ void notrace handle_interruption(int code, struct pt_regs *regs)
795 795
796 if (fault_space == 0 && !faulthandler_disabled()) 796 if (fault_space == 0 && !faulthandler_disabled())
797 { 797 {
798 /* Clean up and return if in exception table. */
799 if (fixup_exception(regs))
800 return;
798 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC); 801 pdc_chassis_send_status(PDC_CHASSIS_DIRECT_PANIC);
799 parisc_terminate("Kernel Fault", regs, code, fault_address); 802 parisc_terminate("Kernel Fault", regs, code, fault_address);
800 } 803 }
diff --git a/arch/parisc/lib/fixup.S b/arch/parisc/lib/fixup.S
index 536ef66bb94b..1052b747e011 100644
--- a/arch/parisc/lib/fixup.S
+++ b/arch/parisc/lib/fixup.S
@@ -26,6 +26,7 @@
26 26
27#ifdef CONFIG_SMP 27#ifdef CONFIG_SMP
28 .macro get_fault_ip t1 t2 28 .macro get_fault_ip t1 t2
29 loadgp
29 addil LT%__per_cpu_offset,%r27 30 addil LT%__per_cpu_offset,%r27
30 LDREG RT%__per_cpu_offset(%r1),\t1 31 LDREG RT%__per_cpu_offset(%r1),\t1
31 /* t2 = smp_processor_id() */ 32 /* t2 = smp_processor_id() */
@@ -40,14 +41,19 @@
40 LDREG RT%exception_data(%r1),\t1 41 LDREG RT%exception_data(%r1),\t1
41 /* t1 = this_cpu_ptr(&exception_data) */ 42 /* t1 = this_cpu_ptr(&exception_data) */
42 add,l \t1,\t2,\t1 43 add,l \t1,\t2,\t1
44 /* %r27 = t1->fault_gp - restore gp */
45 LDREG EXCDATA_GP(\t1), %r27
43 /* t1 = t1->fault_ip */ 46 /* t1 = t1->fault_ip */
44 LDREG EXCDATA_IP(\t1), \t1 47 LDREG EXCDATA_IP(\t1), \t1
45 .endm 48 .endm
46#else 49#else
47 .macro get_fault_ip t1 t2 50 .macro get_fault_ip t1 t2
51 loadgp
48 /* t1 = this_cpu_ptr(&exception_data) */ 52 /* t1 = this_cpu_ptr(&exception_data) */
49 addil LT%exception_data,%r27 53 addil LT%exception_data,%r27
50 LDREG RT%exception_data(%r1),\t2 54 LDREG RT%exception_data(%r1),\t2
55 /* %r27 = t2->fault_gp - restore gp */
56 LDREG EXCDATA_GP(\t2), %r27
51 /* t1 = t2->fault_ip */ 57 /* t1 = t2->fault_ip */
52 LDREG EXCDATA_IP(\t2), \t1 58 LDREG EXCDATA_IP(\t2), \t1
53 .endm 59 .endm
diff --git a/arch/parisc/mm/fault.c b/arch/parisc/mm/fault.c
index 26fac9c671c9..16dbe81c97c9 100644
--- a/arch/parisc/mm/fault.c
+++ b/arch/parisc/mm/fault.c
@@ -145,6 +145,7 @@ int fixup_exception(struct pt_regs *regs)
145 struct exception_data *d; 145 struct exception_data *d;
146 d = this_cpu_ptr(&exception_data); 146 d = this_cpu_ptr(&exception_data);
147 d->fault_ip = regs->iaoq[0]; 147 d->fault_ip = regs->iaoq[0];
148 d->fault_gp = regs->gr[27];
148 d->fault_space = regs->isr; 149 d->fault_space = regs->isr;
149 d->fault_addr = regs->ior; 150 d->fault_addr = regs->ior;
150 151