aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/entry/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/entry/common.c')
-rw-r--r--arch/x86/entry/common.c84
1 files changed, 8 insertions, 76 deletions
diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index ec138e538c44..df56ca394877 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -64,20 +64,13 @@ static void do_audit_syscall_entry(struct pt_regs *regs, u32 arch)
64} 64}
65 65
66/* 66/*
67 * We can return 0 to resume the syscall or anything else to go to phase 67 * Returns the syscall nr to run (which should match regs->orig_ax) or -1
68 * 2. If we resume the syscall, we need to put something appropriate in 68 * to skip the syscall.
69 * regs->orig_ax.
70 *
71 * NB: We don't have full pt_regs here, but regs->orig_ax and regs->ax
72 * are fully functional.
73 *
74 * For phase 2's benefit, our return value is:
75 * 0: resume the syscall
76 * 1: go to phase 2; no seccomp phase 2 needed
77 * anything else: go to phase 2; pass return value to seccomp
78 */ 69 */
79unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch) 70static long syscall_trace_enter(struct pt_regs *regs)
80{ 71{
72 u32 arch = in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
73
81 struct thread_info *ti = pt_regs_to_thread_info(regs); 74 struct thread_info *ti = pt_regs_to_thread_info(regs);
82 unsigned long ret = 0; 75 unsigned long ret = 0;
83 u32 work; 76 u32 work;
@@ -118,59 +111,9 @@ unsigned long syscall_trace_enter_phase1(struct pt_regs *regs, u32 arch)
118 sd.args[5] = regs->bp; 111 sd.args[5] = regs->bp;
119 } 112 }
120 113
121 BUILD_BUG_ON(SECCOMP_PHASE1_OK != 0); 114 ret = __secure_computing(&sd);
122 BUILD_BUG_ON(SECCOMP_PHASE1_SKIP != 1); 115 if (ret == -1)
123 116 return ret;
124 ret = seccomp_phase1(&sd);
125 if (ret == SECCOMP_PHASE1_SKIP) {
126 regs->orig_ax = -1;
127 ret = 0;
128 } else if (ret != SECCOMP_PHASE1_OK) {
129 return ret; /* Go directly to phase 2 */
130 }
131
132 work &= ~_TIF_SECCOMP;
133 }
134#endif
135
136 /* Do our best to finish without phase 2. */
137 if (work == 0)
138 return ret; /* seccomp and/or nohz only (ret == 0 here) */
139
140#ifdef CONFIG_AUDITSYSCALL
141 if (work == _TIF_SYSCALL_AUDIT) {
142 /*
143 * If there is no more work to be done except auditing,
144 * then audit in phase 1. Phase 2 always audits, so, if
145 * we audit here, then we can't go on to phase 2.
146 */
147 do_audit_syscall_entry(regs, arch);
148 return 0;
149 }
150#endif
151
152 return 1; /* Something is enabled that we can't handle in phase 1 */
153}
154
155/* Returns the syscall nr to run (which should match regs->orig_ax). */
156long syscall_trace_enter_phase2(struct pt_regs *regs, u32 arch,
157 unsigned long phase1_result)
158{
159 struct thread_info *ti = pt_regs_to_thread_info(regs);
160 long ret = 0;
161 u32 work = ACCESS_ONCE(ti->flags) & _TIF_WORK_SYSCALL_ENTRY;
162
163 if (IS_ENABLED(CONFIG_DEBUG_ENTRY))
164 BUG_ON(regs != task_pt_regs(current));
165
166#ifdef CONFIG_SECCOMP
167 /*
168 * Call seccomp_phase2 before running the other hooks so that
169 * they can see any changes made by a seccomp tracer.
170 */
171 if (phase1_result > 1 && seccomp_phase2(phase1_result)) {
172 /* seccomp failures shouldn't expose any additional code. */
173 return -1;
174 } 117 }
175#endif 118#endif
176 119
@@ -189,17 +132,6 @@ long syscall_trace_enter_phase2(struct pt_regs *regs, u32 arch,
189 return ret ?: regs->orig_ax; 132 return ret ?: regs->orig_ax;
190} 133}
191 134
192long syscall_trace_enter(struct pt_regs *regs)
193{
194 u32 arch = in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
195 unsigned long phase1_result = syscall_trace_enter_phase1(regs, arch);
196
197 if (phase1_result == 0)
198 return regs->orig_ax;
199 else
200 return syscall_trace_enter_phase2(regs, arch, phase1_result);
201}
202
203#define EXIT_TO_USERMODE_LOOP_FLAGS \ 135#define EXIT_TO_USERMODE_LOOP_FLAGS \
204 (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \ 136 (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
205 _TIF_NEED_RESCHED | _TIF_USER_RETURN_NOTIFY) 137 _TIF_NEED_RESCHED | _TIF_USER_RETURN_NOTIFY)