Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
84e9c95a
Commit
84e9c95a
authored
Oct 12, 2008
by
Ingo Molnar
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'x86/signal' into core/signal
parents
206855c3
1389ac4b
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
133 additions
and
90 deletions
+133
-90
arch/x86/ia32/ia32_signal.c
arch/x86/ia32/ia32_signal.c
+14
-17
arch/x86/kernel/signal_32.c
arch/x86/kernel/signal_32.c
+66
-42
arch/x86/kernel/signal_64.c
arch/x86/kernel/signal_64.c
+53
-31
No files found.
arch/x86/ia32/ia32_signal.c
View file @
84e9c95a
...
...
@@ -351,31 +351,28 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
savesegment
(
es
,
tmp
);
err
|=
__put_user
(
tmp
,
(
unsigned
int
__user
*
)
&
sc
->
es
);
err
|=
__put_user
(
(
u32
)
regs
->
di
,
&
sc
->
di
);
err
|=
__put_user
(
(
u32
)
regs
->
si
,
&
sc
->
si
);
err
|=
__put_user
(
(
u32
)
regs
->
bp
,
&
sc
->
bp
);
err
|=
__put_user
(
(
u32
)
regs
->
sp
,
&
sc
->
sp
);
err
|=
__put_user
(
(
u32
)
regs
->
bx
,
&
sc
->
bx
);
err
|=
__put_user
(
(
u32
)
regs
->
dx
,
&
sc
->
dx
);
err
|=
__put_user
(
(
u32
)
regs
->
cx
,
&
sc
->
cx
);
err
|=
__put_user
(
(
u32
)
regs
->
ax
,
&
sc
->
ax
);
err
|=
__put_user
(
(
u32
)
regs
->
cs
,
&
sc
->
cs
);
err
|=
__put_user
(
(
u32
)
regs
->
ss
,
&
sc
->
ss
);
err
|=
__put_user
(
regs
->
di
,
&
sc
->
di
);
err
|=
__put_user
(
regs
->
si
,
&
sc
->
si
);
err
|=
__put_user
(
regs
->
bp
,
&
sc
->
bp
);
err
|=
__put_user
(
regs
->
sp
,
&
sc
->
sp
);
err
|=
__put_user
(
regs
->
bx
,
&
sc
->
bx
);
err
|=
__put_user
(
regs
->
dx
,
&
sc
->
dx
);
err
|=
__put_user
(
regs
->
cx
,
&
sc
->
cx
);
err
|=
__put_user
(
regs
->
ax
,
&
sc
->
ax
);
err
|=
__put_user
(
regs
->
cs
,
&
sc
->
cs
);
err
|=
__put_user
(
regs
->
ss
,
&
sc
->
ss
);
err
|=
__put_user
(
current
->
thread
.
trap_no
,
&
sc
->
trapno
);
err
|=
__put_user
(
current
->
thread
.
error_code
,
&
sc
->
err
);
err
|=
__put_user
(
(
u32
)
regs
->
ip
,
&
sc
->
ip
);
err
|=
__put_user
(
(
u32
)
regs
->
flags
,
&
sc
->
flags
);
err
|=
__put_user
(
(
u32
)
regs
->
sp
,
&
sc
->
sp_at_signal
);
err
|=
__put_user
(
regs
->
ip
,
&
sc
->
ip
);
err
|=
__put_user
(
regs
->
flags
,
&
sc
->
flags
);
err
|=
__put_user
(
regs
->
sp
,
&
sc
->
sp_at_signal
);
tmp
=
save_i387_xstate_ia32
(
fpstate
);
if
(
tmp
<
0
)
err
=
-
EFAULT
;
else
{
clear_used_math
();
stts
();
else
err
|=
__put_user
(
ptr_to_compat
(
tmp
?
fpstate
:
NULL
),
&
sc
->
fpstate
);
}
/* non-iBCS2 extensions.. */
err
|=
__put_user
(
mask
,
&
sc
->
oldmask
);
...
...
arch/x86/kernel/signal_32.c
View file @
84e9c95a
...
...
@@ -113,6 +113,27 @@ asmlinkage int sys_sigaltstack(unsigned long bx)
return
do_sigaltstack
(
uss
,
uoss
,
regs
->
sp
);
}
#define COPY(x) { \
err |= __get_user(regs->x, &sc->x); \
}
#define COPY_SEG(seg) { \
unsigned short tmp; \
err |= __get_user(tmp, &sc->seg); \
regs->seg = tmp; \
}
#define COPY_SEG_STRICT(seg) { \
unsigned short tmp; \
err |= __get_user(tmp, &sc->seg); \
regs->seg = tmp | 3; \
}
#define GET_SEG(seg) { \
unsigned short tmp; \
err |= __get_user(tmp, &sc->seg); \
loadsegment(seg, tmp); \
}
/*
* Do a signal return; undo the signal stack.
...
...
@@ -121,28 +142,13 @@ static int
restore_sigcontext
(
struct
pt_regs
*
regs
,
struct
sigcontext
__user
*
sc
,
unsigned
long
*
pax
)
{
void
__user
*
buf
;
unsigned
int
tmpflags
;
unsigned
int
err
=
0
;
/* Always make any pending restarted system calls return -EINTR */
current_thread_info
()
->
restart_block
.
fn
=
do_no_restart_syscall
;
#define COPY(x) err |= __get_user(regs->x, &sc->x)
#define COPY_SEG(seg) \
{ unsigned short tmp; \
err |= __get_user(tmp, &sc->seg); \
regs->seg = tmp; }
#define COPY_SEG_STRICT(seg) \
{ unsigned short tmp; \
err |= __get_user(tmp, &sc->seg); \
regs->seg = tmp|3; }
#define GET_SEG(seg) \
{ unsigned short tmp; \
err |= __get_user(tmp, &sc->seg); \
loadsegment(seg, tmp); }
GET_SEG
(
gs
);
COPY_SEG
(
fs
);
COPY_SEG
(
es
);
...
...
@@ -152,21 +158,12 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
COPY_SEG_STRICT
(
cs
);
COPY_SEG_STRICT
(
ss
);
{
unsigned
int
tmpflags
;
err
|=
__get_user
(
tmpflags
,
&
sc
->
flags
);
regs
->
flags
=
(
regs
->
flags
&
~
FIX_EFLAGS
)
|
(
tmpflags
&
FIX_EFLAGS
);
regs
->
orig_ax
=
-
1
;
/* disable syscall checks */
}
{
void
__user
*
buf
;
err
|=
__get_user
(
tmpflags
,
&
sc
->
flags
);
regs
->
flags
=
(
regs
->
flags
&
~
FIX_EFLAGS
)
|
(
tmpflags
&
FIX_EFLAGS
);
regs
->
orig_ax
=
-
1
;
/* disable syscall checks */
err
|=
__get_user
(
buf
,
&
sc
->
fpstate
);
err
|=
restore_i387_xstate
(
buf
);
}
err
|=
__get_user
(
buf
,
&
sc
->
fpstate
);
err
|=
restore_i387_xstate
(
buf
);
err
|=
__get_user
(
*
pax
,
&
sc
->
ax
);
return
err
;
...
...
@@ -482,24 +479,34 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/*
* OK, we're invoking a handler:
*/
static
int
signr_convert
(
int
sig
)
{
struct
thread_info
*
info
=
current_thread_info
();
if
(
info
->
exec_domain
&&
info
->
exec_domain
->
signal_invmap
&&
sig
<
32
)
return
info
->
exec_domain
->
signal_invmap
[
sig
];
return
sig
;
}
#define is_ia32 1
#define ia32_setup_frame __setup_frame
#define ia32_setup_rt_frame __setup_rt_frame
static
int
setup_rt_frame
(
int
sig
,
struct
k_sigaction
*
ka
,
siginfo_t
*
info
,
sigset_t
*
set
,
struct
pt_regs
*
regs
)
{
int
usig
=
signr_convert
(
sig
);
int
ret
;
int
usig
;
usig
=
current_thread_info
()
->
exec_domain
&&
current_thread_info
()
->
exec_domain
->
signal_invmap
&&
sig
<
32
?
current_thread_info
()
->
exec_domain
->
signal_invmap
[
sig
]
:
sig
;
/* Set up the stack frame */
if
(
ka
->
sa
.
sa_flags
&
SA_SIGINFO
)
ret
=
__setup_rt_frame
(
usig
,
ka
,
info
,
set
,
regs
);
else
ret
=
__setup_frame
(
usig
,
ka
,
set
,
regs
);
if
(
is_ia32
)
{
if
(
ka
->
sa
.
sa_flags
&
SA_SIGINFO
)
ret
=
ia32_setup_rt_frame
(
usig
,
ka
,
info
,
set
,
regs
);
else
ret
=
ia32_setup_frame
(
usig
,
ka
,
set
,
regs
);
}
else
ret
=
__setup_rt_frame
(
sig
,
ka
,
info
,
set
,
regs
);
if
(
ret
)
{
force_sigsegv
(
sig
,
current
);
...
...
@@ -550,6 +557,15 @@ 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.
*/
...
...
@@ -663,6 +679,12 @@ static void do_signal(struct pt_regs *regs)
void
do_notify_resume
(
struct
pt_regs
*
regs
,
void
*
unused
,
__u32
thread_info_flags
)
{
#if defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE)
/* notify userspace of pending MCEs */
if
(
thread_info_flags
&
_TIF_MCE_NOTIFY
)
mce_notify_user
();
#endif
/* CONFIG_X86_64 && CONFIG_X86_MCE */
/* deal with pending signal delivery */
if
(
thread_info_flags
&
_TIF_SIGPENDING
)
do_signal
(
regs
);
...
...
@@ -672,7 +694,9 @@ do_notify_resume(struct pt_regs *regs, void *unused, __u32 thread_info_flags)
tracehook_notify_resume
(
regs
);
}
#ifdef CONFIG_X86_32
clear_thread_flag
(
TIF_IRET
);
#endif
/* CONFIG_X86_32 */
}
void
signal_fault
(
struct
pt_regs
*
regs
,
void
__user
*
frame
,
char
*
where
)
...
...
arch/x86/kernel/signal_64.c
View file @
84e9c95a
...
...
@@ -52,6 +52,16 @@ sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
return
do_sigaltstack
(
uss
,
uoss
,
regs
->
sp
);
}
#define COPY(x) { \
err |= __get_user(regs->x, &sc->x); \
}
#define COPY_SEG_STRICT(seg) { \
unsigned short tmp; \
err |= __get_user(tmp, &sc->seg); \
regs->seg = tmp | 3; \
}
/*
* Do a signal return; undo the signal stack.
*/
...
...
@@ -59,13 +69,13 @@ static int
restore_sigcontext
(
struct
pt_regs
*
regs
,
struct
sigcontext
__user
*
sc
,
unsigned
long
*
pax
)
{
void
__user
*
buf
;
unsigned
int
tmpflags
;
unsigned
int
err
=
0
;
/* Always make any pending restarted system calls return -EINTR */
current_thread_info
()
->
restart_block
.
fn
=
do_no_restart_syscall
;
#define COPY(x) (err |= __get_user(regs->x, &sc->x))
COPY
(
di
);
COPY
(
si
);
COPY
(
bp
);
COPY
(
sp
);
COPY
(
bx
);
COPY
(
dx
);
COPY
(
cx
);
COPY
(
ip
);
COPY
(
r8
);
...
...
@@ -80,25 +90,14 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
/* Kernel saves and restores only the CS segment register on signals,
* which is the bare minimum needed to allow mixed 32/64-bit code.
* App's signal handler can save/restore other segments if needed. */
{
unsigned
cs
;
err
|=
__get_user
(
cs
,
&
sc
->
cs
);
regs
->
cs
=
cs
|
3
;
/* Force into user mode */
}
COPY_SEG_STRICT
(
cs
);
{
unsigned
int
tmpflags
;
err
|=
__get_user
(
tmpflags
,
&
sc
->
flags
);
regs
->
flags
=
(
regs
->
flags
&
~
FIX_EFLAGS
)
|
(
tmpflags
&
FIX_EFLAGS
);
regs
->
orig_ax
=
-
1
;
/* disable syscall checks */
}
{
void
__user
*
buf
;
err
|=
__get_user
(
tmpflags
,
&
sc
->
flags
);
regs
->
flags
=
(
regs
->
flags
&
~
FIX_EFLAGS
)
|
(
tmpflags
&
FIX_EFLAGS
);
regs
->
orig_ax
=
-
1
;
/* disable syscall checks */
err
|=
__get_user
(
buf
,
&
sc
->
fpstate
);
err
|=
restore_i387_xstate
(
buf
);
}
err
|=
__get_user
(
buf
,
&
sc
->
fpstate
);
err
|=
restore_i387_xstate
(
buf
);
err
|=
__get_user
(
*
pax
,
&
sc
->
ax
);
return
err
;
...
...
@@ -281,21 +280,32 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
/*
* OK, we're invoking a handler
*/
static
int
signr_convert
(
int
sig
)
{
return
sig
;
}
#ifdef CONFIG_IA32_EMULATION
#define is_ia32 test_thread_flag(TIF_IA32)
#else
#define is_ia32 0
#endif
static
int
setup_rt_frame
(
int
sig
,
struct
k_sigaction
*
ka
,
siginfo_t
*
info
,
sigset_t
*
set
,
struct
pt_regs
*
regs
)
{
int
usig
=
signr_convert
(
sig
);
int
ret
;
#ifdef CONFIG_IA32_EMULATION
if
(
test_thread_flag
(
TIF_IA32
)
)
{
/* Set up the stack frame */
if
(
is_ia32
)
{
if
(
ka
->
sa
.
sa_flags
&
SA_SIGINFO
)
ret
=
ia32_setup_rt_frame
(
sig
,
ka
,
info
,
set
,
regs
);
ret
=
ia32_setup_rt_frame
(
u
sig
,
ka
,
info
,
set
,
regs
);
else
ret
=
ia32_setup_frame
(
sig
,
ka
,
set
,
regs
);
ret
=
ia32_setup_frame
(
u
sig
,
ka
,
set
,
regs
);
}
else
#endif
ret
=
__setup_rt_frame
(
sig
,
ka
,
info
,
set
,
regs
);
ret
=
__setup_rt_frame
(
sig
,
ka
,
info
,
set
,
regs
);
if
(
ret
)
{
force_sigsegv
(
sig
,
current
);
...
...
@@ -346,12 +356,14 @@ 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.
...
...
@@ -410,7 +422,8 @@ static void do_signal(struct pt_regs *regs)
signr
=
get_signal_to_deliver
(
&
info
,
&
ka
,
regs
,
NULL
);
if
(
signr
>
0
)
{
/* Re-enable any watchpoints before delivering the
/*
* Re-enable any watchpoints before delivering the
* signal to user space. The processor register will
* have been cleared if the watchpoint triggered
* inside the kernel.
...
...
@@ -418,7 +431,7 @@ static void do_signal(struct pt_regs *regs)
if
(
current
->
thread
.
debugreg7
)
set_debugreg
(
current
->
thread
.
debugreg7
,
7
);
/* Whee!
Actually deliver the signal. */
/* Whee! Actually deliver the signal. */
if
(
handle_signal
(
signr
,
&
info
,
&
ka
,
oldset
,
regs
)
==
0
)
{
/*
* A signal was successfully delivered; the saved
...
...
@@ -441,6 +454,7 @@ static void do_signal(struct pt_regs *regs)
regs
->
ax
=
regs
->
orig_ax
;
regs
->
ip
-=
2
;
break
;
case
-
ERESTART_RESTARTBLOCK
:
regs
->
ax
=
NR_restart_syscall
;
regs
->
ip
-=
2
;
...
...
@@ -458,14 +472,18 @@ static void do_signal(struct pt_regs *regs)
}
}
void
do_notify_resume
(
struct
pt_regs
*
regs
,
void
*
unused
,
__u32
thread_info_flags
)
/*
* notification of userspace execution resumption
* - triggered by the TIF_WORK_MASK flags
*/
void
do_notify_resume
(
struct
pt_regs
*
regs
,
void
*
unused
,
__u32
thread_info_flags
)
{
#if
def CONFIG_X86_MCE
#if
defined(CONFIG_X86_64) && defined(CONFIG_X86_MCE)
/* notify userspace of pending MCEs */
if
(
thread_info_flags
&
_TIF_MCE_NOTIFY
)
mce_notify_user
();
#endif
/* CONFIG_X86_MCE */
#endif
/* CONFIG_X86_
64 && CONFIG_X86_
MCE */
/* deal with pending signal delivery */
if
(
thread_info_flags
&
_TIF_SIGPENDING
)
...
...
@@ -475,6 +493,10 @@ void do_notify_resume(struct pt_regs *regs, void *unused,
clear_thread_flag
(
TIF_NOTIFY_RESUME
);
tracehook_notify_resume
(
regs
);
}
#ifdef CONFIG_X86_32
clear_thread_flag
(
TIF_IRET
);
#endif
/* CONFIG_X86_32 */
}
void
signal_fault
(
struct
pt_regs
*
regs
,
void
__user
*
frame
,
char
*
where
)
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment