summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Redfearn <matt.redfearn@imgtec.com>2016-03-29 04:35:31 -0400
committerRalf Baechle <ralf@linux-mips.org>2016-05-13 08:02:00 -0400
commita400bed6d105c23d3673f763596e4b85de14e41a (patch)
tree9ef0d11b16f9e94aa0e890cbc0e8a74b4b5c0031
parent5050e91fa650ecd6260ef62bbed9dfc5b4d05dfa (diff)
MIPS: scall: Handle seccomp filters which redirect syscalls
Commit d218af78492a ("MIPS: scall: Always run the seccomp syscall filters") modified the syscall code to always call the seccomp filters, but missed the case where a filter may redirect the syscall, as revealed by the seccomp_bpf self test. The syscall path now restores the syscall from the stack after the filter rather than saving it locally. Syscall number checking and syscall function table lookup is done after the filter may have run such that redirected syscalls are also checked, and executed. The regular path of syscall number checking and pointer lookup is also made more consistent between ABIs with scall64-64.S being the reference. With this patch in place, the seccomp_bpf self test now passes TRACE_syscall.syscall_redirected and TRACE_syscall.syscall_dropped on all MIPS ABIs. Fixes: d218af78492a ("MIPS: scall: Always run the seccomp syscall filters") Signed-off-by: Matt Redfearn <matt.redfearn@imgtec.com> Acked-by: Kees Cook <keescook@chromium.org> Cc: Eric B Munson <emunson@akamai.com> Cc: James Hogan <james.hogan@imgtec.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: linux-mips@linux-mips.org Cc: IMG-MIPSLinuxKerneldevelopers@imgtec.com Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/12916/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r--arch/mips/kernel/scall32-o32.S11
-rw-r--r--arch/mips/kernel/scall64-64.S3
-rw-r--r--arch/mips/kernel/scall64-n32.S14
-rw-r--r--arch/mips/kernel/scall64-o32.S14
4 files changed, 24 insertions, 18 deletions
diff --git a/arch/mips/kernel/scall32-o32.S b/arch/mips/kernel/scall32-o32.S
index d01fe53a6638..c8e43e0c4066 100644
--- a/arch/mips/kernel/scall32-o32.S
+++ b/arch/mips/kernel/scall32-o32.S
@@ -35,7 +35,6 @@ NESTED(handle_sys, PT_SIZE, sp)
35 35
36 lw t1, PT_EPC(sp) # skip syscall on return 36 lw t1, PT_EPC(sp) # skip syscall on return
37 37
38 subu v0, v0, __NR_O32_Linux # check syscall number
39 addiu t1, 4 # skip to next instruction 38 addiu t1, 4 # skip to next instruction
40 sw t1, PT_EPC(sp) 39 sw t1, PT_EPC(sp)
41 40
@@ -89,6 +88,7 @@ loads_done:
89 and t0, t1 88 and t0, t1
90 bnez t0, syscall_trace_entry # -> yes 89 bnez t0, syscall_trace_entry # -> yes
91syscall_common: 90syscall_common:
91 subu v0, v0, __NR_O32_Linux # check syscall number
92 sltiu t0, v0, __NR_O32_Linux_syscalls + 1 92 sltiu t0, v0, __NR_O32_Linux_syscalls + 1
93 beqz t0, illegal_syscall 93 beqz t0, illegal_syscall
94 94
@@ -118,24 +118,23 @@ o32_syscall_exit:
118 118
119syscall_trace_entry: 119syscall_trace_entry:
120 SAVE_STATIC 120 SAVE_STATIC
121 move s0, v0
122 move a0, sp 121 move a0, sp
123 122
124 /* 123 /*
125 * syscall number is in v0 unless we called syscall(__NR_###) 124 * syscall number is in v0 unless we called syscall(__NR_###)
126 * where the real syscall number is in a0 125 * where the real syscall number is in a0
127 */ 126 */
128 addiu a1, v0, __NR_O32_Linux 127 move a1, v0
129 bnez v0, 1f /* __NR_syscall at offset 0 */ 128 subu t2, v0, __NR_O32_Linux
129 bnez t2, 1f /* __NR_syscall at offset 0 */
130 lw a1, PT_R4(sp) 130 lw a1, PT_R4(sp)
131 131
1321: jal syscall_trace_enter 1321: jal syscall_trace_enter
133 133
134 bltz v0, 1f # seccomp failed? Skip syscall 134 bltz v0, 1f # seccomp failed? Skip syscall
135 135
136 move v0, s0 # restore syscall
137
138 RESTORE_STATIC 136 RESTORE_STATIC
137 lw v0, PT_R2(sp) # Restore syscall (maybe modified)
139 lw a0, PT_R4(sp) # Restore argument registers 138 lw a0, PT_R4(sp) # Restore argument registers
140 lw a1, PT_R5(sp) 139 lw a1, PT_R5(sp)
141 lw a2, PT_R6(sp) 140 lw a2, PT_R6(sp)
diff --git a/arch/mips/kernel/scall64-64.S b/arch/mips/kernel/scall64-64.S
index 6b73ecc02597..e6ede125059f 100644
--- a/arch/mips/kernel/scall64-64.S
+++ b/arch/mips/kernel/scall64-64.S
@@ -82,15 +82,14 @@ n64_syscall_exit:
82 82
83syscall_trace_entry: 83syscall_trace_entry:
84 SAVE_STATIC 84 SAVE_STATIC
85 move s0, v0
86 move a0, sp 85 move a0, sp
87 move a1, v0 86 move a1, v0
88 jal syscall_trace_enter 87 jal syscall_trace_enter
89 88
90 bltz v0, 1f # seccomp failed? Skip syscall 89 bltz v0, 1f # seccomp failed? Skip syscall
91 90
92 move v0, s0
93 RESTORE_STATIC 91 RESTORE_STATIC
92 ld v0, PT_R2(sp) # Restore syscall (maybe modified)
94 ld a0, PT_R4(sp) # Restore argument registers 93 ld a0, PT_R4(sp) # Restore argument registers
95 ld a1, PT_R5(sp) 94 ld a1, PT_R5(sp)
96 ld a2, PT_R6(sp) 95 ld a2, PT_R6(sp)
diff --git a/arch/mips/kernel/scall64-n32.S b/arch/mips/kernel/scall64-n32.S
index 71f99d5f7a06..9c0b387d6427 100644
--- a/arch/mips/kernel/scall64-n32.S
+++ b/arch/mips/kernel/scall64-n32.S
@@ -42,9 +42,6 @@ NESTED(handle_sysn32, PT_SIZE, sp)
42#endif 42#endif
43 beqz t0, not_n32_scall 43 beqz t0, not_n32_scall
44 44
45 dsll t0, v0, 3 # offset into table
46 ld t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0)
47
48 sd a3, PT_R26(sp) # save a3 for syscall restarting 45 sd a3, PT_R26(sp) # save a3 for syscall restarting
49 46
50 li t1, _TIF_WORK_SYSCALL_ENTRY 47 li t1, _TIF_WORK_SYSCALL_ENTRY
@@ -53,6 +50,9 @@ NESTED(handle_sysn32, PT_SIZE, sp)
53 bnez t0, n32_syscall_trace_entry 50 bnez t0, n32_syscall_trace_entry
54 51
55syscall_common: 52syscall_common:
53 dsll t0, v0, 3 # offset into table
54 ld t2, (sysn32_call_table - (__NR_N32_Linux * 8))(t0)
55
56 jalr t2 # Do The Real Thing (TM) 56 jalr t2 # Do The Real Thing (TM)
57 57
58 li t0, -EMAXERRNO - 1 # error? 58 li t0, -EMAXERRNO - 1 # error?
@@ -71,21 +71,25 @@ syscall_common:
71 71
72n32_syscall_trace_entry: 72n32_syscall_trace_entry:
73 SAVE_STATIC 73 SAVE_STATIC
74 move s0, t2
75 move a0, sp 74 move a0, sp
76 move a1, v0 75 move a1, v0
77 jal syscall_trace_enter 76 jal syscall_trace_enter
78 77
79 bltz v0, 1f # seccomp failed? Skip syscall 78 bltz v0, 1f # seccomp failed? Skip syscall
80 79
81 move t2, s0
82 RESTORE_STATIC 80 RESTORE_STATIC
81 ld v0, PT_R2(sp) # Restore syscall (maybe modified)
83 ld a0, PT_R4(sp) # Restore argument registers 82 ld a0, PT_R4(sp) # Restore argument registers
84 ld a1, PT_R5(sp) 83 ld a1, PT_R5(sp)
85 ld a2, PT_R6(sp) 84 ld a2, PT_R6(sp)
86 ld a3, PT_R7(sp) 85 ld a3, PT_R7(sp)
87 ld a4, PT_R8(sp) 86 ld a4, PT_R8(sp)
88 ld a5, PT_R9(sp) 87 ld a5, PT_R9(sp)
88
89 dsubu t2, v0, __NR_N32_Linux # check (new) syscall number
90 sltiu t0, t2, __NR_N32_Linux_syscalls + 1
91 beqz t0, not_n32_scall
92
89 j syscall_common 93 j syscall_common
90 94
911: j syscall_exit 951: j syscall_exit
diff --git a/arch/mips/kernel/scall64-o32.S b/arch/mips/kernel/scall64-o32.S
index 91b43eea2d5a..f4f28b1580de 100644
--- a/arch/mips/kernel/scall64-o32.S
+++ b/arch/mips/kernel/scall64-o32.S
@@ -52,9 +52,6 @@ NESTED(handle_sys, PT_SIZE, sp)
52 sll a2, a2, 0 52 sll a2, a2, 0
53 sll a3, a3, 0 53 sll a3, a3, 0
54 54
55 dsll t0, v0, 3 # offset into table
56 ld t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
57
58 sd a3, PT_R26(sp) # save a3 for syscall restarting 55 sd a3, PT_R26(sp) # save a3 for syscall restarting
59 56
60 /* 57 /*
@@ -88,6 +85,9 @@ loads_done:
88 bnez t0, trace_a_syscall 85 bnez t0, trace_a_syscall
89 86
90syscall_common: 87syscall_common:
88 dsll t0, v0, 3 # offset into table
89 ld t2, (sys32_call_table - (__NR_O32_Linux * 8))(t0)
90
91 jalr t2 # Do The Real Thing (TM) 91 jalr t2 # Do The Real Thing (TM)
92 92
93 li t0, -EMAXERRNO - 1 # error? 93 li t0, -EMAXERRNO - 1 # error?
@@ -112,7 +112,6 @@ trace_a_syscall:
112 sd a6, PT_R10(sp) 112 sd a6, PT_R10(sp)
113 sd a7, PT_R11(sp) # For indirect syscalls 113 sd a7, PT_R11(sp) # For indirect syscalls
114 114
115 move s0, t2 # Save syscall pointer
116 move a0, sp 115 move a0, sp
117 /* 116 /*
118 * absolute syscall number is in v0 unless we called syscall(__NR_###) 117 * absolute syscall number is in v0 unless we called syscall(__NR_###)
@@ -133,8 +132,8 @@ trace_a_syscall:
133 132
134 bltz v0, 1f # seccomp failed? Skip syscall 133 bltz v0, 1f # seccomp failed? Skip syscall
135 134
136 move t2, s0
137 RESTORE_STATIC 135 RESTORE_STATIC
136 ld v0, PT_R2(sp) # Restore syscall (maybe modified)
138 ld a0, PT_R4(sp) # Restore argument registers 137 ld a0, PT_R4(sp) # Restore argument registers
139 ld a1, PT_R5(sp) 138 ld a1, PT_R5(sp)
140 ld a2, PT_R6(sp) 139 ld a2, PT_R6(sp)
@@ -143,6 +142,11 @@ trace_a_syscall:
143 ld a5, PT_R9(sp) 142 ld a5, PT_R9(sp)
144 ld a6, PT_R10(sp) 143 ld a6, PT_R10(sp)
145 ld a7, PT_R11(sp) # For indirect syscalls 144 ld a7, PT_R11(sp) # For indirect syscalls
145
146 dsubu t0, v0, __NR_O32_Linux # check (new) syscall number
147 sltiu t0, t0, __NR_O32_Linux_syscalls + 1
148 beqz t0, not_o32_scall
149
146 j syscall_common 150 j syscall_common
147 151
1481: j syscall_exit 1521: j syscall_exit