diff options
author | Matt Redfearn <matt.redfearn@imgtec.com> | 2016-03-29 04:35:31 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2016-05-13 08:02:00 -0400 |
commit | a400bed6d105c23d3673f763596e4b85de14e41a (patch) | |
tree | 9ef0d11b16f9e94aa0e890cbc0e8a74b4b5c0031 | |
parent | 5050e91fa650ecd6260ef62bbed9dfc5b4d05dfa (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.S | 11 | ||||
-rw-r--r-- | arch/mips/kernel/scall64-64.S | 3 | ||||
-rw-r--r-- | arch/mips/kernel/scall64-n32.S | 14 | ||||
-rw-r--r-- | arch/mips/kernel/scall64-o32.S | 14 |
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 |
91 | syscall_common: | 90 | syscall_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 | ||
119 | syscall_trace_entry: | 119 | syscall_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 | ||
132 | 1: jal syscall_trace_enter | 132 | 1: 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 | ||
83 | syscall_trace_entry: | 83 | syscall_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 | ||
55 | syscall_common: | 52 | syscall_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 | ||
72 | n32_syscall_trace_entry: | 72 | n32_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 | ||
91 | 1: j syscall_exit | 95 | 1: 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 | ||
90 | syscall_common: | 87 | syscall_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 | ||
148 | 1: j syscall_exit | 152 | 1: j syscall_exit |