Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
linux-davinci
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Redmine
Redmine
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
linux
linux-davinci
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