10
10
#include <linux/kernel.h>
11
11
#include <linux/sched.h>
12
12
#include <linux/sched/task_stack.h>
13
+ #include <linux/entry-common.h>
13
14
#include <linux/mm.h>
14
15
#include <linux/smp.h>
15
16
#include <linux/errno.h>
16
17
#include <linux/ptrace.h>
17
18
#include <linux/tracehook.h>
18
19
#include <linux/audit.h>
19
- #include <linux/seccomp.h>
20
20
#include <linux/signal.h>
21
21
#include <linux/export.h>
22
22
#include <linux/context_tracking.h>
42
42
#include <asm/syscall.h>
43
43
#include <asm/irq_stack.h>
44
44
45
- #define CREATE_TRACE_POINTS
46
45
#include <trace/events/syscalls.h>
47
46
48
- /* Check that the stack and regs on entry from user mode are sane. */
49
- static noinstr void check_user_regs (struct pt_regs * regs )
50
- {
51
- if (IS_ENABLED (CONFIG_DEBUG_ENTRY )) {
52
- /*
53
- * Make sure that the entry code gave us a sensible EFLAGS
54
- * register. Native because we want to check the actual CPU
55
- * state, not the interrupt state as imagined by Xen.
56
- */
57
- unsigned long flags = native_save_fl ();
58
- WARN_ON_ONCE (flags & (X86_EFLAGS_AC | X86_EFLAGS_DF |
59
- X86_EFLAGS_NT ));
60
-
61
- /* We think we came from user mode. Make sure pt_regs agrees. */
62
- WARN_ON_ONCE (!user_mode (regs ));
63
-
64
- /*
65
- * All entries from user mode (except #DF) should be on the
66
- * normal thread stack and should have user pt_regs in the
67
- * correct location.
68
- */
69
- WARN_ON_ONCE (!on_thread_stack ());
70
- WARN_ON_ONCE (regs != task_pt_regs (current ));
71
- }
72
- }
73
-
74
- #ifdef CONFIG_CONTEXT_TRACKING
75
- /**
76
- * enter_from_user_mode - Establish state when coming from user mode
77
- *
78
- * Syscall entry disables interrupts, but user mode is traced as interrupts
79
- * enabled. Also with NO_HZ_FULL RCU might be idle.
80
- *
81
- * 1) Tell lockdep that interrupts are disabled
82
- * 2) Invoke context tracking if enabled to reactivate RCU
83
- * 3) Trace interrupts off state
84
- */
85
- static noinstr void enter_from_user_mode (struct pt_regs * regs )
86
- {
87
- enum ctx_state state = ct_state ();
88
-
89
- check_user_regs (regs );
90
- lockdep_hardirqs_off (CALLER_ADDR0 );
91
- user_exit_irqoff ();
92
-
93
- instrumentation_begin ();
94
- CT_WARN_ON (state != CONTEXT_USER );
95
- trace_hardirqs_off_finish ();
96
- instrumentation_end ();
97
- }
98
- #else
99
- static __always_inline void enter_from_user_mode (struct pt_regs * regs )
100
- {
101
- check_user_regs (regs );
102
- lockdep_hardirqs_off (CALLER_ADDR0 );
103
- instrumentation_begin ();
104
- trace_hardirqs_off_finish ();
105
- instrumentation_end ();
106
- }
107
- #endif
108
-
109
47
/**
110
48
* exit_to_user_mode - Fixup state when exiting to user mode
111
49
*
@@ -129,83 +67,6 @@ static __always_inline void exit_to_user_mode(void)
129
67
lockdep_hardirqs_on (CALLER_ADDR0 );
130
68
}
131
69
132
- static void do_audit_syscall_entry (struct pt_regs * regs , u32 arch )
133
- {
134
- #ifdef CONFIG_X86_64
135
- if (arch == AUDIT_ARCH_X86_64 ) {
136
- audit_syscall_entry (regs -> orig_ax , regs -> di ,
137
- regs -> si , regs -> dx , regs -> r10 );
138
- } else
139
- #endif
140
- {
141
- audit_syscall_entry (regs -> orig_ax , regs -> bx ,
142
- regs -> cx , regs -> dx , regs -> si );
143
- }
144
- }
145
-
146
- /*
147
- * Returns the syscall nr to run (which should match regs->orig_ax) or -1
148
- * to skip the syscall.
149
- */
150
- static long syscall_trace_enter (struct pt_regs * regs )
151
- {
152
- u32 arch = in_ia32_syscall () ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64 ;
153
-
154
- struct thread_info * ti = current_thread_info ();
155
- unsigned long ret = 0 ;
156
- u32 work ;
157
-
158
- work = READ_ONCE (ti -> flags );
159
-
160
- if (work & (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_EMU )) {
161
- ret = tracehook_report_syscall_entry (regs );
162
- if (ret || (work & _TIF_SYSCALL_EMU ))
163
- return -1L ;
164
- }
165
-
166
- #ifdef CONFIG_SECCOMP
167
- /*
168
- * Do seccomp after ptrace, to catch any tracer changes.
169
- */
170
- if (work & _TIF_SECCOMP ) {
171
- struct seccomp_data sd ;
172
-
173
- sd .arch = arch ;
174
- sd .nr = regs -> orig_ax ;
175
- sd .instruction_pointer = regs -> ip ;
176
- #ifdef CONFIG_X86_64
177
- if (arch == AUDIT_ARCH_X86_64 ) {
178
- sd .args [0 ] = regs -> di ;
179
- sd .args [1 ] = regs -> si ;
180
- sd .args [2 ] = regs -> dx ;
181
- sd .args [3 ] = regs -> r10 ;
182
- sd .args [4 ] = regs -> r8 ;
183
- sd .args [5 ] = regs -> r9 ;
184
- } else
185
- #endif
186
- {
187
- sd .args [0 ] = regs -> bx ;
188
- sd .args [1 ] = regs -> cx ;
189
- sd .args [2 ] = regs -> dx ;
190
- sd .args [3 ] = regs -> si ;
191
- sd .args [4 ] = regs -> di ;
192
- sd .args [5 ] = regs -> bp ;
193
- }
194
-
195
- ret = __secure_computing (& sd );
196
- if (ret == -1 )
197
- return ret ;
198
- }
199
- #endif
200
-
201
- if (unlikely (test_thread_flag (TIF_SYSCALL_TRACEPOINT )))
202
- trace_sys_enter (regs , regs -> orig_ax );
203
-
204
- do_audit_syscall_entry (regs , arch );
205
-
206
- return ret ?: regs -> orig_ax ;
207
- }
208
-
209
70
#define EXIT_TO_USERMODE_LOOP_FLAGS \
210
71
(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \
211
72
_TIF_NEED_RESCHED | _TIF_PATCH_PENDING)
@@ -366,26 +227,10 @@ __visible noinstr void syscall_return_slowpath(struct pt_regs *regs)
366
227
exit_to_user_mode ();
367
228
}
368
229
369
- static noinstr long syscall_enter (struct pt_regs * regs , unsigned long nr )
370
- {
371
- struct thread_info * ti ;
372
-
373
- enter_from_user_mode (regs );
374
- instrumentation_begin ();
375
-
376
- local_irq_enable ();
377
- ti = current_thread_info ();
378
- if (READ_ONCE (ti -> flags ) & _TIF_WORK_SYSCALL_ENTRY )
379
- nr = syscall_trace_enter (regs );
380
-
381
- instrumentation_end ();
382
- return nr ;
383
- }
384
-
385
230
#ifdef CONFIG_X86_64
386
231
__visible noinstr void do_syscall_64 (unsigned long nr , struct pt_regs * regs )
387
232
{
388
- nr = syscall_enter (regs , nr );
233
+ nr = syscall_enter_from_user_mode (regs , nr );
389
234
390
235
instrumentation_begin ();
391
236
if (likely (nr < NR_syscalls )) {
@@ -407,14 +252,16 @@ __visible noinstr void do_syscall_64(unsigned long nr, struct pt_regs *regs)
407
252
#if defined(CONFIG_X86_32 ) || defined(CONFIG_IA32_EMULATION )
408
253
static __always_inline unsigned int syscall_32_enter (struct pt_regs * regs )
409
254
{
255
+ unsigned int nr = (unsigned int )regs -> orig_ax ;
256
+
410
257
if (IS_ENABLED (CONFIG_IA32_EMULATION ))
411
258
current_thread_info ()-> status |= TS_COMPAT ;
412
259
/*
413
260
* Subtlety here: if ptrace pokes something larger than 2^32-1 into
414
261
* orig_ax, the unsigned int return value truncates it. This may
415
262
* or may not be necessary, but it matches the old asm behavior.
416
263
*/
417
- return syscall_enter ( regs , ( unsigned int )regs -> orig_ax );
264
+ return ( unsigned int )syscall_enter_from_user_mode ( regs , nr );
418
265
}
419
266
420
267
/*
@@ -568,7 +415,7 @@ SYSCALL_DEFINE0(ni_syscall)
568
415
* solves the problem of kernel mode pagefaults which can schedule, which
569
416
* is not possible after invoking rcu_irq_enter() without undoing it.
570
417
*
571
- * For user mode entries enter_from_user_mode () must be invoked to
418
+ * For user mode entries irqentry_enter_from_user_mode () must be invoked to
572
419
* establish the proper context for NOHZ_FULL. Otherwise scheduling on exit
573
420
* would not be possible.
574
421
*
@@ -584,7 +431,7 @@ idtentry_state_t noinstr idtentry_enter(struct pt_regs *regs)
584
431
};
585
432
586
433
if (user_mode (regs )) {
587
- enter_from_user_mode (regs );
434
+ irqentry_enter_from_user_mode (regs );
588
435
return ret ;
589
436
}
590
437
@@ -615,7 +462,7 @@ idtentry_state_t noinstr idtentry_enter(struct pt_regs *regs)
615
462
/*
616
463
* If RCU is not watching then the same careful
617
464
* sequence vs. lockdep and tracing is required
618
- * as in enter_from_user_mode ().
465
+ * as in irqentry_enter_from_user_mode ().
619
466
*/
620
467
lockdep_hardirqs_off (CALLER_ADDR0 );
621
468
rcu_irq_enter ();
@@ -708,18 +555,6 @@ void noinstr idtentry_exit(struct pt_regs *regs, idtentry_state_t state)
708
555
}
709
556
}
710
557
711
- /**
712
- * idtentry_enter_user - Handle state tracking on idtentry from user mode
713
- * @regs: Pointer to pt_regs of interrupted context
714
- *
715
- * Invokes enter_from_user_mode() to establish the proper context for
716
- * NOHZ_FULL. Otherwise scheduling on exit would not be possible.
717
- */
718
- void noinstr idtentry_enter_user (struct pt_regs * regs )
719
- {
720
- enter_from_user_mode (regs );
721
- }
722
-
723
558
/**
724
559
* idtentry_exit_user - Handle return from exception to user mode
725
560
* @regs: Pointer to pt_regs (exception entry regs)
0 commit comments