x86: kill handle_signal()->set_fs()
PATCH 1/1 x86: kill handle_signal()->set_fs()
handle_signal()->set_fs() has a nice comment which explains what set_fs() is, but it doesn't explain why it is needed and why it depends on CONFIG_X86_64.
Afaics, the history of this confusion is:
1. I guess today nobody can explain why it was needed in arch/i386/kernel/signal.c, perhaps it was always wrong. This predates 2.4.0 kernel.
2. then it was copy-and-past'ed to the new x86_64 arch.
3. then it was removed from i386 (but not from x86_64) by b93b6ca3 "i386: remove unnecessary code".
4. then it was reintroduced under CONFIG_X86_64 when x86 unified i386 and x86_64, because the patch above didn't touch x86_64.
Remove it. ->addr_limit should be correct. Even if it was possible that it is wrong, it is too late to fix it after setup_rt_frame().
---
arch/x86/kernel/signal.c | 9 --------- 1 file changed, 9 deletions(-)
arch/x86/kernel/signal.c renamed from arch/x86/kernel/signal.c~1_kill_set_fs +0 -9
@@ -717,15 +717,6 @@ handle_signal(unsigned long sig, siginfoif (ret)return ret; -#ifdef CONFIG_X86_64 -/* -* This has nothing to do with segment registers, -* despite the name. This magic affects uaccess.h -* macros' behavior. Reset it to the normal setting. -*/ -set_fs (USER_DS ); -#endif -/* * Clear the direction flag as per the ABI for function entry. */
H. Peter Anvin
reviewerQuoted 15 lines · Oleg Nesterov
handle_signal()->set_fs() has a nice comment which explains what
set_fs()is, but it doesn't explain why it is needed and why it depends onCONFIG_X86_64.Afaics, the history of this confusion is:
1. I guess today nobody can explain why it was needed in
arch/i386/kernel/signal.c, perhaps it was always wrong. This predates 2.4.0 kernel.2. then it was copy-and-past'ed to the new
x86_64arch.3. then it was removed from i386 (but not from
x86_64) byb93b6ca3"i386: remove unnecessary code".
Quoted 7 lines
4. then it was reintroduced under
CONFIG_X86_64when x86 unified i386 andx86_64, because the patch above didn't touchx86_64.Remove it. ->addr_limit should be correct. Even if it was possible that it is wrong, it is too late to fix it after
setup_rt_frame().
The main reason I could think of why this would be necessary is if we take an event while we have fs == KERNEL_DS inside the kernel which is then promoted to a signal. Are you absolutely sure that can't happen?
In particular, there should be a setting upstream of this, as you're correctly pointing out that it's too late. If not, we might actually have a problem.
-hpa
Quoted 21 lines · H. Peter Anvin
Quoted 19 lines · Oleg Nesterov
handle_signal()->set_fs() has a nice comment which explains what
set_fs()is, but it doesn't explain why it is needed and why it depends onCONFIG_X86_64.Afaics, the history of this confusion is:
1. I guess today nobody can explain why it was needed in
arch/i386/kernel/signal.c, perhaps it was always wrong. This predates 2.4.0 kernel.2. then it was copy-and-past'ed to the new
x86_64arch.3. then it was removed from i386 (but not from
x86_64) byb93b6ca3"i386: remove unnecessary code".4. then it was reintroduced under
CONFIG_X86_64when x86 unified i386 andx86_64, because the patch above didn't touchx86_64.
Quoted 6 lines
Quoted 3 lines
Remove it. ->addr_limit should be correct. Even if it was possible that it is wrong, it is too late to fix it after
setup_rt_frame().The main reason I could think of why this would be necessary is if we take an event while we have fs ==
KERNEL_DSinside the kernel
this is possible if we are the kernel thread, or set_fs(KERNEL_DS) was called.
Quoted 2 lines
which is
then promoted to a signal.
How? We are going to return to the user-space. Obviously this is not possible with the kernel thread. So I think this can only happen if we already have a bug with unbalanced set_fs().
Are you absolutely sure that can't happen?
Quoted 3 lines
In particular, there should be a setting upstream of this, as you're correctly pointing out that it's too late. If not, we might actually have a problem.
Hmm... Now I recall, this was already discussed 5 years ago. Thanks to google, see http://lkml.org/lkml/2007/7/17/321
In particular, Linus sayd:
Heh. I think it's entirely historical.
Please realize that the whole reason that function is called "set_fs()" is that it literally used to set the %fs segment register, not "->addr_limit".
So I think the "set_fs(USER_DS)" is there _only_ to match the other
regs->xds = __USER_DS;
regs->xes = __USER_DS;
regs->xss = __USER_DS;
regs->xcs = __USER_CS;
things, and never mattered. And now it matters even less, and has been copied to all other architectures where it is just totally insane.
Oleg.
So, Peter, do you agree we can remove this set_fs() ?
Of course, this doesn't matter from the perfomance pov. But it is very confusing, especially with CONFIG_X86_64.
Quoted 68 lines · Oleg Nesterov
Quoted 21 lines · H. Peter Anvin
Quoted 19 lines · Oleg Nesterov
handle_signal()->set_fs() has a nice comment which explains what
set_fs()is, but it doesn't explain why it is needed and why it depends onCONFIG_X86_64.Afaics, the history of this confusion is:
1. I guess today nobody can explain why it was needed in
arch/i386/kernel/signal.c, perhaps it was always wrong. This predates 2.4.0 kernel.2. then it was copy-and-past'ed to the new
x86_64arch.3. then it was removed from i386 (but not from
x86_64) byb93b6ca3"i386: remove unnecessary code".4. then it was reintroduced under
CONFIG_X86_64when x86 unified i386 andx86_64, because the patch above didn't touchx86_64.Quoted 6 lines
Quoted 3 lines
Remove it. ->addr_limit should be correct. Even if it was possible that it is wrong, it is too late to fix it after
setup_rt_frame().The main reason I could think of why this would be necessary is if we take an event while we have fs ==
KERNEL_DSinside the kernelthis is possible if we are the kernel thread, or
set_fs(KERNEL_DS)was called.Quoted 2 lines
which is
then promoted to a signal.How? We are going to return to the user-space. Obviously this is not possible with the kernel thread. So I think this can only happen if we already have a bug with unbalanced
set_fs().Are you absolutely sure that can't happen?
Quoted 3 lines
In particular, there should be a setting upstream of this, as you're correctly pointing out that it's too late. If not, we might actually have a problem.
Hmm... Now I recall, this was already discussed 5 years ago. Thanks to google, see http://lkml.org/lkml/2007/7/17/321
In particular, Linus sayd:
Heh. I think it's entirely historical.
Please realize that the whole reason that function is called "
set_fs()" is that it literally used to set the %fs segment register, not "->addr_limit".So I think the "
set_fs(USER_DS)" is there _only_ to match the other
regs->xds=__USER_DS;
regs->xes=__USER_DS;
regs->xss=__USER_DS;
regs->xcs=__USER_CS;things, and never mattered. And now it matters even less, and has been copied to all other architectures where it is just totally insane.
Oleg.
[tip:x86/signal] x86: Kill handle_signal()->set_fs()
In reply to Oleg NesterovCommit-ID: 73d382deccac186d103496bf10388bc2432a8384 Gitweb: http://git.kernel.org/tip/73d382deccac186d103496bf10388bc2432a8384 Author: Oleg Nesterov <[email protected]> AuthorDate: Sun, 10 Jul 2011 18:44:24 +0200 Committer: H. Peter Anvin <[email protected]> CommitDate: Thu, 14 Jul 2011 21:46:20 -0700
x86: Kill handle_signal()->set_fs()
handle_signal()->set_fs() has a nice comment which explains what set_fs() is, but it doesn't explain why it is needed and why it depends on CONFIG_X86_64.
Afaics, the history of this confusion is:
1. I guess today nobody can explain why it was needed in arch/i386/kernel/signal.c, perhaps it was always wrong. This predates 2.4.0 kernel.
2. then it was copy-and-past'ed to the new x86_64 arch.
3. then it was removed from i386 (but not from x86_64) by b93b6ca3 "i386: remove unnecessary code".
4. then it was reintroduced under CONFIG_X86_64 when x86 unified i386 and x86_64, because the patch above didn't touch x86_64.
Remove it. ->addr_limit should be correct. Even if it was possible that it is wrong, it is too late to fix it after setup_rt_frame().
Linus commented in:
http://lkml.kernel.org/r/[email protected]
... about the equivalent bit from i386:
Heh. I think it's entirely historical.
Please realize that the whole reason that function is called "set_fs()" is that it literally used to set the %fs segment register, not "->addr_limit".
So I think the "set_fs(USER_DS)" is there _only_ to match the other
regs->xds = __USER_DS;
regs->xes = __USER_DS;
regs->xss = __USER_DS;
regs->xcs = __USER_CS;things, and never mattered. And now it matters even less, and has been copied to all other architectures where it is just totally insane.
--- arch/x86/kernel/signal.c | 9 --------- 1 files changed, 0 insertions(+), 9 deletions(-)
arch/x86/kernel/signal.c +0 -9
@@ -720,15 +720,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,if (ret)return ret; -#ifdef CONFIG_X86_64 -/* -* This has nothing to do with segment registers, -* despite the name. This magic affects uaccess.h -* macros' behavior. Reset it to the normal setting. -*/ -set_fs (USER_DS ); -#endif -/* * Clear the direction flag as per the ABI for function entry. */