Skip to content

Commit 1ca1443

Browse files
benzearichardweinberger
authored andcommitted
um: Rely on PTRACE_SETREGSET to set FS/GS base registers
These registers are saved/restored together with the other general registers using ptrace. In arch_set_tls we then just need to set the register and it will be synced back normally. Most of this logic was introduced in commit f355559 ("[PATCH] uml: x86_64 thread fixes"). However, at least today we can rely on ptrace to restore the base registers for us. As such, only the part of the patch that tracks the FS register for use as thread local storage is actually needed. Signed-off-by: Benjamin Berg <benjamin@sipsolutions.net> Signed-off-by: Richard Weinberger <richard@nod.at>
1 parent 2182255 commit 1ca1443

7 files changed

Lines changed: 16 additions & 71 deletions

File tree

arch/um/include/shared/os.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,9 +323,6 @@ extern void sigio_broken(int fd);
323323
extern int __add_sigio_fd(int fd);
324324
extern int __ignore_sigio_fd(int fd);
325325

326-
/* prctl.c */
327-
extern int os_arch_prctl(int pid, int option, unsigned long *arg2);
328-
329326
/* tty.c */
330327
extern int get_pty(void);
331328

arch/x86/um/asm/elf.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,8 +168,8 @@ do { \
168168
(pr_reg)[18] = (_regs)->regs.gp[18]; \
169169
(pr_reg)[19] = (_regs)->regs.gp[19]; \
170170
(pr_reg)[20] = (_regs)->regs.gp[20]; \
171-
(pr_reg)[21] = current->thread.arch.fs; \
172-
(pr_reg)[22] = 0; \
171+
(pr_reg)[21] = (_regs)->regs.gp[21]; \
172+
(pr_reg)[22] = (_regs)->regs.gp[22]; \
173173
(pr_reg)[23] = 0; \
174174
(pr_reg)[24] = 0; \
175175
(pr_reg)[25] = 0; \

arch/x86/um/asm/processor_64.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,11 @@
1010
struct arch_thread {
1111
unsigned long debugregs[8];
1212
int debugregs_seq;
13-
unsigned long fs;
1413
struct faultinfo faultinfo;
1514
};
1615

1716
#define INIT_ARCH_THREAD { .debugregs = { [ 0 ... 7 ] = 0 }, \
1817
.debugregs_seq = 0, \
19-
.fs = 0, \
2018
.faultinfo = { 0, 0, 0 } }
2119

2220
#define STACKSLOTS_PER_LINE 4
@@ -28,7 +26,6 @@ static inline void arch_flush_thread(struct arch_thread *thread)
2826
static inline void arch_copy_thread(struct arch_thread *from,
2927
struct arch_thread *to)
3028
{
31-
to->fs = from->fs;
3229
}
3330

3431
#define current_sp() ({ void *sp; __asm__("movq %%rsp, %0" : "=r" (sp) : ); sp; })

arch/x86/um/os-Linux/Makefile

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
obj-y = registers.o task_size.o mcontext.o
77

88
obj-$(CONFIG_X86_32) += tls.o
9-
obj-$(CONFIG_64BIT) += prctl.o
109

1110
USER_OBJS := $(obj-y)
1211

arch/x86/um/os-Linux/prctl.c

Lines changed: 0 additions & 12 deletions
This file was deleted.

arch/x86/um/syscalls_64.c

Lines changed: 13 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -16,60 +16,24 @@
1616
long arch_prctl(struct task_struct *task, int option,
1717
unsigned long __user *arg2)
1818
{
19-
unsigned long *ptr = arg2, tmp;
20-
long ret;
21-
int pid = task->mm->context.id.u.pid;
22-
23-
/*
24-
* With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
25-
* be safe), we need to call arch_prctl on the host because
26-
* setting %fs may result in something else happening (like a
27-
* GDT or thread.fs being set instead). So, we let the host
28-
* fiddle the registers and thread struct and restore the
29-
* registers afterwards.
30-
*
31-
* So, the saved registers are stored to the process (this
32-
* needed because a stub may have been the last thing to run),
33-
* arch_prctl is run on the host, then the registers are read
34-
* back.
35-
*/
36-
switch (option) {
37-
case ARCH_SET_FS:
38-
case ARCH_SET_GS:
39-
ret = restore_pid_registers(pid, &current->thread.regs.regs);
40-
if (ret)
41-
return ret;
42-
break;
43-
case ARCH_GET_FS:
44-
case ARCH_GET_GS:
45-
/*
46-
* With these two, we read to a local pointer and
47-
* put_user it to the userspace pointer that we were
48-
* given. If addr isn't valid (because it hasn't been
49-
* faulted in or is just bogus), we want put_user to
50-
* fault it in (or return -EFAULT) instead of having
51-
* the host return -EFAULT.
52-
*/
53-
ptr = &tmp;
54-
}
55-
56-
ret = os_arch_prctl(pid, option, ptr);
57-
if (ret)
58-
return ret;
19+
long ret = -EINVAL;
5920

6021
switch (option) {
6122
case ARCH_SET_FS:
62-
current->thread.arch.fs = (unsigned long) ptr;
63-
ret = save_registers(pid, &current->thread.regs.regs);
23+
current->thread.regs.regs.gp[FS_BASE / sizeof(unsigned long)] =
24+
(unsigned long) arg2;
25+
ret = 0;
6426
break;
6527
case ARCH_SET_GS:
66-
ret = save_registers(pid, &current->thread.regs.regs);
28+
current->thread.regs.regs.gp[GS_BASE / sizeof(unsigned long)] =
29+
(unsigned long) arg2;
30+
ret = 0;
6731
break;
6832
case ARCH_GET_FS:
69-
ret = put_user(tmp, arg2);
33+
ret = put_user(current->thread.regs.regs.gp[FS_BASE / sizeof(unsigned long)], arg2);
7034
break;
7135
case ARCH_GET_GS:
72-
ret = put_user(tmp, arg2);
36+
ret = put_user(current->thread.regs.regs.gp[GS_BASE / sizeof(unsigned long)], arg2);
7337
break;
7438
}
7539

@@ -83,10 +47,10 @@ SYSCALL_DEFINE2(arch_prctl, int, option, unsigned long, arg2)
8347

8448
void arch_switch_to(struct task_struct *to)
8549
{
86-
if ((to->thread.arch.fs == 0) || (to->mm == NULL))
87-
return;
88-
89-
arch_prctl(to, ARCH_SET_FS, (void __user *) to->thread.arch.fs);
50+
/*
51+
* Nothing needs to be done on x86_64.
52+
* The FS_BASE/GS_BASE registers are saved in the ptrace register set.
53+
*/
9054
}
9155

9256
SYSCALL_DEFINE6(mmap, unsigned long, addr, unsigned long, len,

arch/x86/um/tls_64.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ int arch_set_tls(struct task_struct *t, unsigned long tls)
1212
* If CLONE_SETTLS is set, we need to save the thread id
1313
* so it can be set during context switches.
1414
*/
15-
t->thread.arch.fs = tls;
15+
t->thread.regs.regs.gp[FS_BASE / sizeof(unsigned long)] = tls;
1616

1717
return 0;
1818
}

0 commit comments

Comments
 (0)