Skip to content

Commit a557198

Browse files
benzearichardweinberger
authored andcommitted
um: Drop support for hosts without SYSEMU_SINGLESTEP support
These features have existed since Linux 2.6.14 and can be considered widely available at this point. Also drop the backward compatibility code for PTRACE_SETOPTIONS. Signed-off-by: Benjamin Berg <benjamin@sipsolutions.net> ---- v2: * Continue to define PTRACE_SYSEMU_SINGLESTEP as glibc only added it in version 2.27. Signed-off-by: Richard Weinberger <richard@nod.at>
1 parent a8e7590 commit a557198

12 files changed

Lines changed: 24 additions & 243 deletions

File tree

arch/um/include/asm/processor-generic.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ struct mm_struct;
2222
struct thread_struct {
2323
struct pt_regs regs;
2424
struct pt_regs *segv_regs;
25-
int singlestep_syscall;
2625
void *fault_addr;
2726
jmp_buf *fault_catcher;
2827
struct task_struct *prev_sched;

arch/um/include/shared/kern_util.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ extern int handle_page_fault(unsigned long address, unsigned long ip,
3434

3535
extern unsigned int do_IRQ(int irq, struct uml_pt_regs *regs);
3636
extern void initial_thread_cb(void (*proc)(void *), void *arg);
37-
extern int is_syscall(unsigned long addr);
3837

3938
extern void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs);
4039

@@ -58,7 +57,7 @@ extern char *uml_strdup(const char *string);
5857
extern unsigned long to_irq_stack(unsigned long *mask_out);
5958
extern unsigned long from_irq_stack(int nested);
6059

61-
extern int singlestepping(void *t);
60+
extern int singlestepping(void);
6261

6362
extern void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs);
6463
extern void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs);

arch/um/include/shared/ptrace_user.h

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -12,45 +12,4 @@
1212
extern int ptrace_getregs(long pid, unsigned long *regs_out);
1313
extern int ptrace_setregs(long pid, unsigned long *regs_in);
1414

15-
/* syscall emulation path in ptrace */
16-
17-
#ifndef PTRACE_SYSEMU
18-
#define PTRACE_SYSEMU 31
19-
#endif
20-
#ifndef PTRACE_SYSEMU_SINGLESTEP
21-
#define PTRACE_SYSEMU_SINGLESTEP 32
22-
#endif
23-
24-
/* On architectures, that started to support PTRACE_O_TRACESYSGOOD
25-
* in linux 2.4, there are two different definitions of
26-
* PTRACE_SETOPTIONS: linux 2.4 uses 21 while linux 2.6 uses 0x4200.
27-
* For binary compatibility, 2.6 also supports the old "21", named
28-
* PTRACE_OLDSETOPTION. On these architectures, UML always must use
29-
* "21", to ensure the kernel runs on 2.4 and 2.6 host without
30-
* recompilation. So, we use PTRACE_OLDSETOPTIONS in UML.
31-
* We also want to be able to build the kernel on 2.4, which doesn't
32-
* have PTRACE_OLDSETOPTIONS. So, if it is missing, we declare
33-
* PTRACE_OLDSETOPTIONS to be the same as PTRACE_SETOPTIONS.
34-
*
35-
* On architectures, that start to support PTRACE_O_TRACESYSGOOD on
36-
* linux 2.6, PTRACE_OLDSETOPTIONS never is defined, and also isn't
37-
* supported by the host kernel. In that case, our trick lets us use
38-
* the new 0x4200 with the name PTRACE_OLDSETOPTIONS.
39-
*/
40-
#ifndef PTRACE_OLDSETOPTIONS
41-
#define PTRACE_OLDSETOPTIONS PTRACE_SETOPTIONS
42-
#endif
43-
44-
void set_using_sysemu(int value);
45-
int get_using_sysemu(void);
46-
extern int sysemu_supported;
47-
48-
#define SELECT_PTRACE_OPERATION(sysemu_mode, singlestep_mode) \
49-
(((int[3][3] ) { \
50-
{ PTRACE_SYSCALL, PTRACE_SYSCALL, PTRACE_SINGLESTEP }, \
51-
{ PTRACE_SYSEMU, PTRACE_SYSEMU, PTRACE_SINGLESTEP }, \
52-
{ PTRACE_SYSEMU, PTRACE_SYSEMU_SINGLESTEP, \
53-
PTRACE_SYSEMU_SINGLESTEP } }) \
54-
[sysemu_mode][singlestep_mode])
55-
5615
#endif

arch/um/kernel/process.c

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -332,17 +332,9 @@ int __init make_proc_sysemu(void)
332332

333333
late_initcall(make_proc_sysemu);
334334

335-
int singlestepping(void * t)
335+
int singlestepping(void)
336336
{
337-
struct task_struct *task = t ? t : current;
338-
339-
if (!test_thread_flag(TIF_SINGLESTEP))
340-
return 0;
341-
342-
if (task->thread.singlestep_syscall)
343-
return 1;
344-
345-
return 2;
337+
return test_thread_flag(TIF_SINGLESTEP);
346338
}
347339

348340
/*

arch/um/kernel/ptrace.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
void user_enable_single_step(struct task_struct *child)
1313
{
1414
set_tsk_thread_flag(child, TIF_SINGLESTEP);
15-
child->thread.singlestep_syscall = 0;
1615

1716
#ifdef SUBARCH_SET_SINGLESTEPPING
1817
SUBARCH_SET_SINGLESTEPPING(child, 1);
@@ -22,7 +21,6 @@ void user_enable_single_step(struct task_struct *child)
2221
void user_disable_single_step(struct task_struct *child)
2322
{
2423
clear_tsk_thread_flag(child, TIF_SINGLESTEP);
25-
child->thread.singlestep_syscall = 0;
2624

2725
#ifdef SUBARCH_SET_SINGLESTEPPING
2826
SUBARCH_SET_SINGLESTEPPING(child, 0);

arch/um/kernel/signal.c

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,6 @@ void do_signal(struct pt_regs *regs)
120120
}
121121
}
122122

123-
/*
124-
* This closes a way to execute a system call on the host. If
125-
* you set a breakpoint on a system call instruction and singlestep
126-
* from it, the tracing thread used to PTRACE_SINGLESTEP the process
127-
* rather than PTRACE_SYSCALL it, allowing the system call to execute
128-
* on the host. The tracing thread will check this flag and
129-
* PTRACE_SYSCALL if necessary.
130-
*/
131-
if (test_thread_flag(TIF_SINGLESTEP))
132-
current->thread.singlestep_syscall =
133-
is_syscall(PT_REGS_IP(&current->thread.regs));
134-
135123
/*
136124
* if there's no signal to deliver, we just put the saved sigmask
137125
* back

arch/um/os-Linux/skas/process.c

Lines changed: 10 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -177,48 +177,11 @@ static void handle_segv(int pid, struct uml_pt_regs *regs, unsigned long *aux_fp
177177
segv(regs->faultinfo, 0, 1, NULL);
178178
}
179179

180-
/*
181-
* To use the same value of using_sysemu as the caller, ask it that value
182-
* (in local_using_sysemu
183-
*/
184-
static void handle_trap(int pid, struct uml_pt_regs *regs,
185-
int local_using_sysemu)
180+
static void handle_trap(int pid, struct uml_pt_regs *regs)
186181
{
187-
int err, status;
188-
189182
if ((UPT_IP(regs) >= STUB_START) && (UPT_IP(regs) < STUB_END))
190183
fatal_sigsegv();
191184

192-
if (!local_using_sysemu)
193-
{
194-
err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,
195-
__NR_getpid);
196-
if (err < 0) {
197-
printk(UM_KERN_ERR "%s - nullifying syscall failed, errno = %d\n",
198-
__func__, errno);
199-
fatal_sigsegv();
200-
}
201-
202-
err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
203-
if (err < 0) {
204-
printk(UM_KERN_ERR "%s - continuing to end of syscall failed, errno = %d\n",
205-
__func__, errno);
206-
fatal_sigsegv();
207-
}
208-
209-
CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED | __WALL));
210-
if ((err < 0) || !WIFSTOPPED(status) ||
211-
(WSTOPSIG(status) != SIGTRAP + 0x80)) {
212-
err = ptrace_dump_regs(pid);
213-
if (err)
214-
printk(UM_KERN_ERR "Failed to get registers from process, errno = %d\n",
215-
-err);
216-
printk(UM_KERN_ERR "%s - failed to wait at end of syscall, errno = %d, status = %d\n",
217-
__func__, errno, status);
218-
fatal_sigsegv();
219-
}
220-
}
221-
222185
handle_syscall(regs);
223186
}
224187

@@ -355,10 +318,10 @@ int start_userspace(unsigned long stub_stack)
355318
goto out_kill;
356319
}
357320

358-
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
321+
if (ptrace(PTRACE_SETOPTIONS, pid, NULL,
359322
(void *) PTRACE_O_TRACESYSGOOD) < 0) {
360323
err = -errno;
361-
printk(UM_KERN_ERR "%s : PTRACE_OLDSETOPTIONS failed, errno = %d\n",
324+
printk(UM_KERN_ERR "%s : PTRACE_SETOPTIONS failed, errno = %d\n",
362325
__func__, errno);
363326
goto out_kill;
364327
}
@@ -380,8 +343,6 @@ int start_userspace(unsigned long stub_stack)
380343
void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
381344
{
382345
int err, status, op, pid = userspace_pid[0];
383-
/* To prevent races if using_sysemu changes under us.*/
384-
int local_using_sysemu;
385346
siginfo_t si;
386347

387348
/* Handle any immediate reschedules or signals */
@@ -411,11 +372,10 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
411372
fatal_sigsegv();
412373
}
413374

414-
/* Now we set local_using_sysemu to be used for one loop */
415-
local_using_sysemu = get_using_sysemu();
416-
417-
op = SELECT_PTRACE_OPERATION(local_using_sysemu,
418-
singlestepping(NULL));
375+
if (singlestepping())
376+
op = PTRACE_SYSEMU_SINGLESTEP;
377+
else
378+
op = PTRACE_SYSEMU;
419379

420380
if (ptrace(op, pid, 0, 0)) {
421381
printk(UM_KERN_ERR "%s - ptrace continue failed, op = %d, errno = %d\n",
@@ -474,7 +434,7 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
474434
else handle_segv(pid, regs, aux_fp_regs);
475435
break;
476436
case SIGTRAP + 0x80:
477-
handle_trap(pid, regs, local_using_sysemu);
437+
handle_trap(pid, regs);
478438
break;
479439
case SIGTRAP:
480440
relay_signal(SIGTRAP, (struct siginfo *)&si, regs);
@@ -597,10 +557,10 @@ int copy_context_skas0(unsigned long new_stack, int pid)
597557
goto out_kill;
598558
}
599559

600-
if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL,
560+
if (ptrace(PTRACE_SETOPTIONS, pid, NULL,
601561
(void *)PTRACE_O_TRACESYSGOOD) < 0) {
602562
err = -errno;
603-
printk(UM_KERN_ERR "%s : PTRACE_OLDSETOPTIONS failed, errno = %d\n",
563+
printk(UM_KERN_ERR "%s : PTRACE_SETOPTIONS failed, errno = %d\n",
604564
__func__, errno);
605565
goto out_kill;
606566
}

arch/um/os-Linux/start_up.c

Lines changed: 6 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -143,71 +143,16 @@ static int stop_ptraced_child(int pid, int exitcode, int mustexit)
143143
return ret;
144144
}
145145

146-
/* Changed only during early boot */
147-
static int force_sysemu_disabled = 0;
148-
149-
static int __init nosysemu_cmd_param(char *str, int* add)
150-
{
151-
force_sysemu_disabled = 1;
152-
return 0;
153-
}
154-
155-
__uml_setup("nosysemu", nosysemu_cmd_param,
156-
"nosysemu\n"
157-
" Turns off syscall emulation patch for ptrace (SYSEMU).\n"
158-
" SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n"
159-
" behaviour of ptrace() and helps reduce host context switch rates.\n"
160-
" To make it work, you need a kernel patch for your host, too.\n"
161-
" See http://perso.wanadoo.fr/laurent.vivier/UML/ for further \n"
162-
" information.\n\n");
163-
164146
static void __init check_sysemu(void)
165147
{
166-
unsigned long regs[MAX_REG_NR];
167148
int pid, n, status, count=0;
168149

169-
os_info("Checking syscall emulation patch for ptrace...");
170-
sysemu_supported = 0;
171-
pid = start_ptraced_child();
172-
173-
if (ptrace(PTRACE_SYSEMU, pid, 0, 0) < 0)
174-
goto fail;
175-
176-
CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
177-
if (n < 0)
178-
fatal_perror("check_sysemu : wait failed");
179-
if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
180-
fatal("check_sysemu : expected SIGTRAP, got status = %d\n",
181-
status);
182-
183-
if (ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
184-
fatal_perror("check_sysemu : PTRACE_GETREGS failed");
185-
if (PT_SYSCALL_NR(regs) != __NR_getpid) {
186-
non_fatal("check_sysemu got system call number %d, "
187-
"expected %d...", PT_SYSCALL_NR(regs), __NR_getpid);
188-
goto fail;
189-
}
190-
191-
n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, os_getpid());
192-
if (n < 0) {
193-
non_fatal("check_sysemu : failed to modify system call "
194-
"return");
195-
goto fail;
196-
}
197-
198-
if (stop_ptraced_child(pid, 0, 0) < 0)
199-
goto fail_stopped;
200-
201-
sysemu_supported = 1;
202-
os_info("OK\n");
203-
set_using_sysemu(!force_sysemu_disabled);
204-
205-
os_info("Checking advanced syscall emulation patch for ptrace...");
150+
os_info("Checking syscall emulation for ptrace...");
206151
pid = start_ptraced_child();
207152

208-
if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
153+
if ((ptrace(PTRACE_SETOPTIONS, pid, 0,
209154
(void *) PTRACE_O_TRACESYSGOOD) < 0))
210-
fatal_perror("check_sysemu: PTRACE_OLDSETOPTIONS failed");
155+
fatal_perror("check_sysemu: PTRACE_SETOPTIONS failed");
211156

212157
while (1) {
213158
count++;
@@ -243,17 +188,14 @@ static void __init check_sysemu(void)
243188
if (stop_ptraced_child(pid, 0, 0) < 0)
244189
goto fail_stopped;
245190

246-
sysemu_supported = 2;
247191
os_info("OK\n");
248192

249-
if (!force_sysemu_disabled)
250-
set_using_sysemu(sysemu_supported);
251193
return;
252194

253195
fail:
254196
stop_ptraced_child(pid, 1, 0);
255197
fail_stopped:
256-
non_fatal("missing\n");
198+
fatal("missing\n");
257199
}
258200

259201
static void __init check_ptrace(void)
@@ -263,9 +205,9 @@ static void __init check_ptrace(void)
263205
os_info("Checking that ptrace can change system call numbers...");
264206
pid = start_ptraced_child();
265207

266-
if ((ptrace(PTRACE_OLDSETOPTIONS, pid, 0,
208+
if ((ptrace(PTRACE_SETOPTIONS, pid, 0,
267209
(void *) PTRACE_O_TRACESYSGOOD) < 0))
268-
fatal_perror("check_ptrace: PTRACE_OLDSETOPTIONS failed");
210+
fatal_perror("check_ptrace: PTRACE_SETOPTIONS failed");
269211

270212
while (1) {
271213
if (ptrace(PTRACE_SYSCALL, pid, 0, 0) < 0)

arch/x86/um/ptrace_32.c

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,30 +25,6 @@ void arch_switch_to(struct task_struct *to)
2525
printk(KERN_WARNING "arch_switch_tls failed, errno = EINVAL\n");
2626
}
2727

28-
int is_syscall(unsigned long addr)
29-
{
30-
unsigned short instr;
31-
int n;
32-
33-
n = copy_from_user(&instr, (void __user *) addr, sizeof(instr));
34-
if (n) {
35-
/* access_process_vm() grants access to vsyscall and stub,
36-
* while copy_from_user doesn't. Maybe access_process_vm is
37-
* slow, but that doesn't matter, since it will be called only
38-
* in case of singlestepping, if copy_from_user failed.
39-
*/
40-
n = access_process_vm(current, addr, &instr, sizeof(instr),
41-
FOLL_FORCE);
42-
if (n != sizeof(instr)) {
43-
printk(KERN_ERR "is_syscall : failed to read "
44-
"instruction from 0x%lx\n", addr);
45-
return 1;
46-
}
47-
}
48-
/* int 0x80 or sysenter */
49-
return (instr == 0x80cd) || (instr == 0x340f);
50-
}
51-
5228
/* determines which flags the user has access to. */
5329
/* 1 = access 0 = no access */
5430
#define FLAG_MASK 0x00044dd5

0 commit comments

Comments
 (0)