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
35ecc0e9
Commit
35ecc0e9
authored
Apr 09, 2003
by
David S. Miller
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[SPARC]: __user attributes in signal handling.
parent
f6aca97d
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
300 additions
and
308 deletions
+300
-308
arch/sparc/kernel/signal.c
arch/sparc/kernel/signal.c
+135
-118
arch/sparc64/kernel/signal.c
arch/sparc64/kernel/signal.c
+29
-27
arch/sparc64/kernel/signal32.c
arch/sparc64/kernel/signal32.c
+136
-163
No files found.
arch/sparc/kernel/signal.c
View file @
35ecc0e9
...
...
@@ -56,7 +56,7 @@ struct signal_sframe {
struct
reg_window
sig_window
;
int
sig_num
;
int
sig_code
;
struct
sigcontext
*
sig_scptr
;
struct
sigcontext
__user
*
sig_scptr
;
int
sig_address
;
struct
sigcontext
sig_context
;
unsigned
int
extramask
[
_NSIG_WORDS
-
1
];
...
...
@@ -71,8 +71,8 @@ struct signal_sframe {
struct
new_signal_frame
{
struct
sparc_stackf
ss
;
__siginfo_t
info
;
__siginfo_fpu_t
*
fpu_save
;
unsigned
long
insns
[
2
]
__attribute__
((
aligned
(
8
)));
__siginfo_fpu_t
__user
*
fpu_save
;
unsigned
long
insns
[
2
]
__attribute__
((
aligned
(
8
)));
unsigned
int
extramask
[
_NSIG_WORDS
-
1
];
unsigned
int
extra_size
;
/* Should be 0 */
__siginfo_fpu_t
fpu_state
;
...
...
@@ -83,8 +83,8 @@ struct rt_signal_frame {
siginfo_t
info
;
struct
pt_regs
regs
;
sigset_t
mask
;
__siginfo_fpu_t
*
fpu_save
;
unsigned
int
insns
[
2
];
__siginfo_fpu_t
__user
*
fpu_save
;
unsigned
int
insns
[
2
];
stack_t
stack
;
unsigned
int
extra_size
;
/* Should be 0 */
__siginfo_fpu_t
fpu_state
;
...
...
@@ -142,7 +142,7 @@ asmlinkage void do_sigsuspend (struct pt_regs *regs)
_sigpause_common
(
regs
->
u_regs
[
UREG_I0
],
regs
);
}
asmlinkage
void
do_rt_sigsuspend
(
sigset_t
*
uset
,
size_t
sigsetsize
,
asmlinkage
void
do_rt_sigsuspend
(
sigset_t
__user
*
uset
,
size_t
sigsetsize
,
struct
pt_regs
*
regs
)
{
sigset_t
oldset
,
set
;
...
...
@@ -190,7 +190,7 @@ asmlinkage void do_rt_sigsuspend(sigset_t *uset, size_t sigsetsize,
}
static
inline
int
restore_fpu_state
(
struct
pt_regs
*
regs
,
__siginfo_fpu_t
*
fpu
)
restore_fpu_state
(
struct
pt_regs
*
regs
,
__siginfo_fpu_t
__user
*
fpu
)
{
int
err
;
#ifdef CONFIG_SMP
...
...
@@ -205,7 +205,7 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
current
->
used_math
=
1
;
clear_tsk_thread_flag
(
current
,
TIF_USEDFPU
);
if
(
verify_area
(
VERIFY_READ
,
fpu
,
sizeof
(
*
fpu
)))
if
(
verify_area
(
VERIFY_READ
,
fpu
,
sizeof
(
*
fpu
)))
return
-
EFAULT
;
err
=
__copy_from_user
(
&
current
->
thread
.
float_regs
[
0
],
&
fpu
->
si_float_regs
[
0
],
...
...
@@ -222,16 +222,16 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
static
inline
void
do_new_sigreturn
(
struct
pt_regs
*
regs
)
{
struct
new_signal_frame
*
sf
;
struct
new_signal_frame
__user
*
sf
;
unsigned
long
up_psr
,
pc
,
npc
;
sigset_t
set
;
__siginfo_fpu_t
*
fpu_save
;
__siginfo_fpu_t
__user
*
fpu_save
;
int
err
;
sf
=
(
struct
new_signal_frame
*
)
regs
->
u_regs
[
UREG_FP
];
sf
=
(
struct
new_signal_frame
__user
*
)
regs
->
u_regs
[
UREG_FP
];
/* 1. Make sure we are not getting garbage from the user */
if
(
verify_area
(
VERIFY_READ
,
sf
,
sizeof
(
*
sf
)))
if
(
verify_area
(
VERIFY_READ
,
sf
,
sizeof
(
*
sf
)))
goto
segv_and_exit
;
if
(((
uint
)
sf
)
&
3
)
...
...
@@ -245,7 +245,7 @@ static inline void do_new_sigreturn (struct pt_regs *regs)
/* 2. Restore the state */
up_psr
=
regs
->
psr
;
err
|=
__copy_from_user
(
regs
,
&
sf
->
info
.
si_regs
,
sizeof
(
struct
pt_regs
));
err
|=
__copy_from_user
(
regs
,
&
sf
->
info
.
si_regs
,
sizeof
(
struct
pt_regs
));
/* User can only change condition codes and FPU enabling in %psr. */
regs
->
psr
=
(
up_psr
&
~
(
PSR_ICC
|
PSR_EF
))
...
...
@@ -279,7 +279,7 @@ static inline void do_new_sigreturn (struct pt_regs *regs)
asmlinkage
void
do_sigreturn
(
struct
pt_regs
*
regs
)
{
struct
sigcontext
*
scptr
;
struct
sigcontext
__user
*
scptr
;
unsigned
long
pc
,
npc
,
psr
;
sigset_t
set
;
int
err
;
...
...
@@ -287,19 +287,19 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
synchronize_user_stack
();
if
(
current
->
thread
.
new_signal
)
return
do_new_sigreturn
(
regs
);
return
do_new_sigreturn
(
regs
);
scptr
=
(
struct
sigcontext
*
)
regs
->
u_regs
[
UREG_I0
];
scptr
=
(
struct
sigcontext
__user
*
)
regs
->
u_regs
[
UREG_I0
];
/* Check sanity of the user arg. */
if
(
verify_area
(
VERIFY_READ
,
scptr
,
sizeof
(
struct
sigcontext
))
||
(((
unsigned
long
)
scptr
)
&
3
))
if
(
verify_area
(
VERIFY_READ
,
scptr
,
sizeof
(
struct
sigcontext
))
||
(((
unsigned
long
)
scptr
)
&
3
))
goto
segv_and_exit
;
err
=
__get_user
(
pc
,
&
scptr
->
sigc_pc
);
err
|=
__get_user
(
npc
,
&
scptr
->
sigc_npc
);
if
((
pc
|
npc
)
&
3
)
if
((
pc
|
npc
)
&
3
)
goto
segv_and_exit
;
/* This is pretty much atomic, no amount locking would prevent
...
...
@@ -341,17 +341,17 @@ asmlinkage void do_sigreturn(struct pt_regs *regs)
asmlinkage
void
do_rt_sigreturn
(
struct
pt_regs
*
regs
)
{
struct
rt_signal_frame
*
sf
;
struct
rt_signal_frame
__user
*
sf
;
unsigned
int
psr
,
pc
,
npc
;
__siginfo_fpu_t
*
fpu_save
;
__siginfo_fpu_t
__user
*
fpu_save
;
sigset_t
set
;
stack_t
st
;
int
err
;
synchronize_user_stack
();
sf
=
(
struct
rt_signal_frame
*
)
regs
->
u_regs
[
UREG_FP
];
if
(
verify_area
(
VERIFY_READ
,
sf
,
sizeof
(
*
sf
))
||
(((
unsigned
long
)
sf
)
&
0x03
))
sf
=
(
struct
rt_signal_frame
__user
*
)
regs
->
u_regs
[
UREG_FP
];
if
(
verify_area
(
VERIFY_READ
,
sf
,
sizeof
(
*
sf
))
||
(((
unsigned
long
)
sf
)
&
0x03
))
goto
segv
;
err
=
__get_user
(
pc
,
&
sf
->
regs
.
pc
);
...
...
@@ -361,13 +361,14 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
err
|=
__get_user
(
regs
->
y
,
&
sf
->
regs
.
y
);
err
|=
__get_user
(
psr
,
&
sf
->
regs
.
psr
);
err
|=
__copy_from_user
(
&
regs
->
u_regs
[
UREG_G1
],
&
sf
->
regs
.
u_regs
[
UREG_G1
],
15
*
sizeof
(
u32
));
err
|=
__copy_from_user
(
&
regs
->
u_regs
[
UREG_G1
],
&
sf
->
regs
.
u_regs
[
UREG_G1
],
15
*
sizeof
(
u32
));
regs
->
psr
=
(
regs
->
psr
&
~
PSR_ICC
)
|
(
psr
&
PSR_ICC
);
err
|=
__get_user
(
fpu_save
,
&
sf
->
fpu_save
);
if
(
fpu_save
)
if
(
fpu_save
)
err
|=
restore_fpu_state
(
regs
,
fpu_save
);
err
|=
__copy_from_user
(
&
set
,
&
sf
->
mask
,
sizeof
(
sigset_t
));
...
...
@@ -380,7 +381,8 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
regs
->
npc
=
npc
;
/* It is more difficult to avoid calling this function than to
call it and ignore errors. */
* call it and ignore errors.
*/
do_sigaltstack
(
&
st
,
NULL
,
(
unsigned
long
)
sf
);
sigdelsetmask
(
&
set
,
~
_BLOCKABLE
);
...
...
@@ -394,7 +396,7 @@ asmlinkage void do_rt_sigreturn(struct pt_regs *regs)
}
/* Checks if the fp is valid */
static
inline
int
invalid_frame_pointer
(
void
*
fp
,
int
fplen
)
static
inline
int
invalid_frame_pointer
(
void
__user
*
fp
,
int
fplen
)
{
if
((((
unsigned
long
)
fp
)
&
7
)
||
!
__access_ok
((
unsigned
long
)
fp
,
fplen
)
||
...
...
@@ -405,7 +407,7 @@ static inline int invalid_frame_pointer (void *fp, int fplen)
return
0
;
}
static
inline
void
*
get_sigframe
(
struct
sigaction
*
sa
,
struct
pt_regs
*
regs
,
unsigned
long
framesize
)
static
inline
void
__user
*
get_sigframe
(
struct
sigaction
*
sa
,
struct
pt_regs
*
regs
,
unsigned
long
framesize
)
{
unsigned
long
sp
;
...
...
@@ -416,14 +418,14 @@ static inline void *get_sigframe(struct sigaction *sa, struct pt_regs *regs, uns
if
(
!
on_sig_stack
(
sp
)
&&
!
((
current
->
sas_ss_sp
+
current
->
sas_ss_size
)
&
7
))
sp
=
current
->
sas_ss_sp
+
current
->
sas_ss_size
;
}
return
(
void
*
)(
sp
-
framesize
);
return
(
void
__user
*
)(
sp
-
framesize
);
}
static
inline
void
setup_frame
(
struct
sigaction
*
sa
,
struct
pt_regs
*
regs
,
int
signr
,
sigset_t
*
oldset
,
siginfo_t
*
info
)
{
struct
signal_sframe
*
sframep
;
struct
sigcontext
*
sc
;
struct
signal_sframe
__user
*
sframep
;
struct
sigcontext
__user
*
sc
;
int
window
=
0
,
err
;
unsigned
long
pc
=
regs
->
pc
;
unsigned
long
npc
=
regs
->
npc
;
...
...
@@ -431,8 +433,9 @@ setup_frame(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *old
int
sig_code
;
synchronize_user_stack
();
sframep
=
(
struct
signal_sframe
*
)
get_sigframe
(
sa
,
regs
,
SF_ALIGNEDSZ
);
if
(
invalid_frame_pointer
(
sframep
,
sizeof
(
*
sframep
))){
sframep
=
(
struct
signal_sframe
__user
*
)
get_sigframe
(
sa
,
regs
,
SF_ALIGNEDSZ
);
if
(
invalid_frame_pointer
(
sframep
,
sizeof
(
*
sframep
))){
/* Don't change signal code and address, so that
* post mortem debuggers can have a look.
*/
...
...
@@ -454,16 +457,16 @@ setup_frame(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *old
err
|=
__put_user
(
regs
->
u_regs
[
UREG_G1
],
&
sc
->
sigc_g1
);
err
|=
__put_user
(
regs
->
u_regs
[
UREG_I0
],
&
sc
->
sigc_o0
);
err
|=
__put_user
(
current
->
thread
.
w_saved
,
&
sc
->
sigc_oswins
);
if
(
current
->
thread
.
w_saved
)
for
(
window
=
0
;
window
<
current
->
thread
.
w_saved
;
window
++
)
{
sc
->
sigc_spbuf
[
window
]
=
(
char
*
)
current
->
thread
.
rwbuf_stkptrs
[
window
]
;
if
(
current
->
thread
.
w_saved
)
for
(
window
=
0
;
window
<
current
->
thread
.
w_saved
;
window
++
)
{
put_user
((
char
*
)
current
->
thread
.
rwbuf_stkptrs
[
window
],
&
sc
->
sigc_spbuf
[
window
])
;
err
|=
__copy_to_user
(
&
sc
->
sigc_wbuf
[
window
],
&
current
->
thread
.
reg_window
[
window
],
sizeof
(
struct
reg_window
));
}
else
err
|=
__copy_to_user
(
sframep
,
(
char
*
)
regs
->
u_regs
[
UREG_FP
],
err
|=
__copy_to_user
(
sframep
,
(
char
*
)
regs
->
u_regs
[
UREG_FP
],
sizeof
(
struct
reg_window
));
current
->
thread
.
w_saved
=
0
;
/* So process is allowed to execute. */
...
...
@@ -484,7 +487,7 @@ setup_frame(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *old
switch
(
info
->
si_code
)
{
case
ILL_ILLOPC
:
sig_code
=
SUBSIG_ILLINST
;
break
;
case
ILL_PRVOPC
:
sig_code
=
SUBSIG_PRIVINST
;
break
;
case
ILL_ILLTRP
:
sig_code
=
SUBSIG_BADTRAP
(
info
->
si_trapno
);
break
;
case
ILL_ILLTRP
:
sig_code
=
SUBSIG_BADTRAP
(
info
->
si_trapno
);
break
;
default:
sig_code
=
SUBSIG_STACK
;
break
;
}
break
;
...
...
@@ -541,7 +544,7 @@ setup_frame(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *old
static
inline
int
save_fpu_state
(
struct
pt_regs
*
regs
,
__siginfo_fpu_t
*
fpu
)
save_fpu_state
(
struct
pt_regs
*
regs
,
__siginfo_fpu_t
__user
*
fpu
)
{
int
err
=
0
;
#ifdef CONFIG_SMP
...
...
@@ -561,12 +564,14 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
regs
->
psr
&=
~
(
PSR_EF
);
}
#endif
err
|=
__copy_to_user
(
&
fpu
->
si_float_regs
[
0
],
&
current
->
thread
.
float_regs
[
0
],
err
|=
__copy_to_user
(
&
fpu
->
si_float_regs
[
0
],
&
current
->
thread
.
float_regs
[
0
],
(
sizeof
(
unsigned
long
)
*
32
));
err
|=
__put_user
(
current
->
thread
.
fsr
,
&
fpu
->
si_fsr
);
err
|=
__put_user
(
current
->
thread
.
fpqdepth
,
&
fpu
->
si_fpqdepth
);
if
(
current
->
thread
.
fpqdepth
!=
0
)
err
|=
__copy_to_user
(
&
fpu
->
si_fpqueue
[
0
],
&
current
->
thread
.
fpqueue
[
0
],
err
|=
__copy_to_user
(
&
fpu
->
si_fpqueue
[
0
],
&
current
->
thread
.
fpqueue
[
0
],
((
sizeof
(
unsigned
long
)
+
(
sizeof
(
unsigned
long
*
)))
*
16
));
current
->
used_math
=
0
;
...
...
@@ -577,7 +582,7 @@ static inline void
new_setup_frame
(
struct
k_sigaction
*
ka
,
struct
pt_regs
*
regs
,
int
signo
,
sigset_t
*
oldset
)
{
struct
new_signal_frame
*
sf
;
struct
new_signal_frame
__user
*
sf
;
int
sigframe_size
,
err
;
/* 1. Make sure everything is clean */
...
...
@@ -587,16 +592,17 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
if
(
!
current
->
used_math
)
sigframe_size
-=
sizeof
(
__siginfo_fpu_t
);
sf
=
(
struct
new_signal_frame
*
)
get_sigframe
(
&
ka
->
sa
,
regs
,
sigframe_size
);
sf
=
(
struct
new_signal_frame
__user
*
)
get_sigframe
(
&
ka
->
sa
,
regs
,
sigframe_size
);
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
goto
sigill_and_return
;
if
(
current
->
thread
.
w_saved
!=
0
)
goto
sigill_and_return
;
/* 2. Save the current process state */
err
=
__copy_to_user
(
&
sf
->
info
.
si_regs
,
regs
,
sizeof
(
struct
pt_regs
));
err
=
__copy_to_user
(
&
sf
->
info
.
si_regs
,
regs
,
sizeof
(
struct
pt_regs
));
err
|=
__put_user
(
0
,
&
sf
->
extra_size
);
...
...
@@ -610,8 +616,8 @@ new_setup_frame(struct k_sigaction *ka, struct pt_regs *regs,
err
|=
__put_user
(
oldset
->
sig
[
0
],
&
sf
->
info
.
si_mask
);
err
|=
__copy_to_user
(
sf
->
extramask
,
&
oldset
->
sig
[
1
],
(
_NSIG_WORDS
-
1
)
*
sizeof
(
unsigned
int
));
err
|=
__copy_to_user
(
sf
,
(
char
*
)
regs
->
u_regs
[
UREG_FP
],
sizeof
(
struct
reg_window
));
err
|=
__copy_to_user
(
sf
,
(
char
*
)
regs
->
u_regs
[
UREG_FP
],
sizeof
(
struct
reg_window
));
if
(
err
)
goto
sigsegv
;
...
...
@@ -653,32 +659,33 @@ static inline void
new_setup_rt_frame
(
struct
k_sigaction
*
ka
,
struct
pt_regs
*
regs
,
int
signo
,
sigset_t
*
oldset
,
siginfo_t
*
info
)
{
struct
rt_signal_frame
*
sf
;
struct
rt_signal_frame
__user
*
sf
;
int
sigframe_size
;
unsigned
int
psr
;
int
err
;
synchronize_user_stack
();
sigframe_size
=
RT_ALIGNEDSZ
;
if
(
!
current
->
used_math
)
if
(
!
current
->
used_math
)
sigframe_size
-=
sizeof
(
__siginfo_fpu_t
);
sf
=
(
struct
rt_signal_frame
*
)
get_sigframe
(
&
ka
->
sa
,
regs
,
sigframe_size
);
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
sf
=
(
struct
rt_signal_frame
__user
*
)
get_sigframe
(
&
ka
->
sa
,
regs
,
sigframe_size
);
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
goto
sigill
;
if
(
current
->
thread
.
w_saved
!=
0
)
if
(
current
->
thread
.
w_saved
!=
0
)
goto
sigill
;
err
=
__put_user
(
regs
->
pc
,
&
sf
->
regs
.
pc
);
err
|=
__put_user
(
regs
->
npc
,
&
sf
->
regs
.
npc
);
err
|=
__put_user
(
regs
->
y
,
&
sf
->
regs
.
y
);
psr
=
regs
->
psr
;
if
(
current
->
used_math
)
if
(
current
->
used_math
)
psr
|=
PSR_EF
;
err
|=
__put_user
(
psr
,
&
sf
->
regs
.
psr
);
err
|=
__copy_to_user
(
&
sf
->
regs
.
u_regs
,
regs
->
u_regs
,
sizeof
(
regs
->
u_regs
));
err
|=
__put_user
(
0
,
&
sf
->
extra_size
);
if
(
psr
&
PSR_EF
)
{
if
(
psr
&
PSR_EF
)
{
err
|=
save_fpu_state
(
regs
,
&
sf
->
fpu_state
);
err
|=
__put_user
(
&
sf
->
fpu_state
,
&
sf
->
fpu_save
);
}
else
{
...
...
@@ -691,8 +698,8 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
err
|=
__put_user
(
sas_ss_flags
(
regs
->
u_regs
[
UREG_FP
]),
&
sf
->
stack
.
ss_flags
);
err
|=
__put_user
(
current
->
sas_ss_size
,
&
sf
->
stack
.
ss_size
);
err
|=
__copy_to_user
(
sf
,
(
char
*
)
regs
->
u_regs
[
UREG_FP
],
sizeof
(
struct
reg_window
));
err
|=
__copy_to_user
(
sf
,
(
char
*
)
regs
->
u_regs
[
UREG_FP
],
sizeof
(
struct
reg_window
));
err
|=
copy_siginfo_to_user
(
&
sf
->
info
,
info
);
...
...
@@ -706,7 +713,7 @@ new_setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
regs
->
pc
=
(
unsigned
long
)
ka
->
sa
.
sa_handler
;
regs
->
npc
=
(
regs
->
pc
+
4
);
if
(
ka
->
ka_restorer
)
if
(
ka
->
ka_restorer
)
regs
->
u_regs
[
UREG_I7
]
=
(
unsigned
long
)
ka
->
ka_restorer
;
else
{
regs
->
u_regs
[
UREG_I7
]
=
(
unsigned
long
)(
&
(
sf
->
insns
[
0
])
-
2
);
...
...
@@ -735,23 +742,24 @@ static inline void
setup_svr4_frame
(
struct
sigaction
*
sa
,
unsigned
long
pc
,
unsigned
long
npc
,
struct
pt_regs
*
regs
,
int
signr
,
sigset_t
*
oldset
)
{
svr4_signal_frame_t
*
sfp
;
svr4_gregset_t
*
gr
;
svr4_siginfo_t
*
si
;
svr4_mcontext_t
*
mc
;
svr4_gwindows_t
*
gw
;
svr4_ucontext_t
*
uc
;
svr4_signal_frame_t
__user
*
sfp
;
svr4_gregset_t
__user
*
gr
;
svr4_siginfo_t
__user
*
si
;
svr4_mcontext_t
__user
*
mc
;
svr4_gwindows_t
__user
*
gw
;
svr4_ucontext_t
__user
*
uc
;
svr4_sigset_t
setv
;
int
window
=
0
,
err
;
synchronize_user_stack
();
sfp
=
(
svr4_signal_frame_t
*
)
get_sigframe
(
sa
,
regs
,
SVR4_SF_ALIGNED
+
REGWIN_SZ
);
sfp
=
(
svr4_signal_frame_t
__user
*
)
get_sigframe
(
sa
,
regs
,
SVR4_SF_ALIGNED
+
REGWIN_SZ
);
if
(
invalid_frame_pointer
(
sfp
,
sizeof
(
*
sfp
)))
if
(
invalid_frame_pointer
(
sfp
,
sizeof
(
*
sfp
)))
goto
sigill_and_return
;
/* Start with a clean frame pointer and fill it */
err
=
__clear_user
(
sfp
,
sizeof
(
*
sfp
));
err
=
__clear_user
(
sfp
,
sizeof
(
*
sfp
));
/* Setup convenience variables */
si
=
&
sfp
->
si
;
...
...
@@ -771,17 +779,20 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
setv
.
sigbits
[
3
]
=
oldset
->
sig
[
3
];
err
|=
__copy_to_user
(
&
uc
->
sigmask
,
&
setv
,
sizeof
(
svr4_sigset_t
));
}
else
err
|=
__copy_to_user
(
&
uc
->
sigmask
,
&
setv
,
2
*
sizeof
(
unsigned
int
));
err
|=
__copy_to_user
(
&
uc
->
sigmask
,
&
setv
,
2
*
sizeof
(
unsigned
int
));
/* Store registers */
err
|=
__put_user
(
regs
->
pc
,
&
((
*
gr
)
[
SVR4_PC
]));
err
|=
__put_user
(
regs
->
npc
,
&
((
*
gr
)
[
SVR4_NPC
]));
err
|=
__put_user
(
regs
->
psr
,
&
((
*
gr
)
[
SVR4_PSR
]));
err
|=
__put_user
(
regs
->
y
,
&
((
*
gr
)
[
SVR4_Y
]));
err
|=
__put_user
(
regs
->
pc
,
&
((
*
gr
)[
SVR4_PC
]));
err
|=
__put_user
(
regs
->
npc
,
&
((
*
gr
)[
SVR4_NPC
]));
err
|=
__put_user
(
regs
->
psr
,
&
((
*
gr
)[
SVR4_PSR
]));
err
|=
__put_user
(
regs
->
y
,
&
((
*
gr
)[
SVR4_Y
]));
/* Copy g [1..7] and o [0..7] registers */
err
|=
__copy_to_user
(
&
(
*
gr
)[
SVR4_G1
],
&
regs
->
u_regs
[
UREG_G1
],
sizeof
(
long
)
*
7
);
err
|=
__copy_to_user
(
&
(
*
gr
)[
SVR4_O0
],
&
regs
->
u_regs
[
UREG_I0
],
sizeof
(
long
)
*
8
);
/* Copy g[1..7] and o[0..7] registers */
err
|=
__copy_to_user
(
&
(
*
gr
)[
SVR4_G1
],
&
regs
->
u_regs
[
UREG_G1
],
sizeof
(
long
)
*
7
);
err
|=
__copy_to_user
(
&
(
*
gr
)[
SVR4_O0
],
&
regs
->
u_regs
[
UREG_I0
],
sizeof
(
long
)
*
8
);
/* Setup sigaltstack */
err
|=
__put_user
(
current
->
sas_ss_sp
,
&
uc
->
stack
.
sp
);
...
...
@@ -793,7 +804,7 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
/* 1. Link sfp->uc->gwins to our windows */
err
|=
__put_user
(
gw
,
&
mc
->
gwin
);
/* 2. Number of windows to restore at setcontext
(): */
/* 2. Number of windows to restore at setcontext(): */
err
|=
__put_user
(
current
->
thread
.
w_saved
,
&
gw
->
count
);
/* 3. Save each valid window
...
...
@@ -807,12 +818,12 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
* These windows are just used in case synchronize_user_stack failed
* to flush the user windows.
*/
for
(
window
=
0
;
window
<
current
->
thread
.
w_saved
;
window
++
)
{
err
|=
__put_user
((
int
*
)
&
(
gw
->
win
[
window
]),
&
gw
->
winptr
[
window
]);
err
|=
__copy_to_user
(
&
gw
->
win
[
window
],
&
current
->
thread
.
reg_window
[
window
],
sizeof
(
svr4_rwindow_t
));
err
|=
__put_user
(
0
,
gw
->
winptr
[
window
]);
for
(
window
=
0
;
window
<
current
->
thread
.
w_saved
;
window
++
)
{
err
|=
__put_user
((
int
*
)
&
(
gw
->
win
[
window
]),
&
gw
->
winptr
[
window
]);
err
|=
__copy_to_user
(
&
gw
->
win
[
window
],
&
current
->
thread
.
reg_window
[
window
],
sizeof
(
svr4_rwindow_t
));
err
|=
__put_user
(
0
,
gw
->
winptr
[
window
]);
}
/* 4. We just pay attention to the gw->count field on setcontext */
...
...
@@ -832,13 +843,14 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
regs
->
npc
=
(
regs
->
pc
+
4
);
/* Arguments passed to signal handler */
if
(
regs
->
u_regs
[
14
]){
struct
reg_window
*
rw
=
(
struct
reg_window
*
)
regs
->
u_regs
[
14
];
err
|=
__put_user
(
signr
,
&
rw
->
ins
[
0
]);
err
|=
__put_user
(
si
,
&
rw
->
ins
[
1
]);
err
|=
__put_user
(
uc
,
&
rw
->
ins
[
2
]);
err
|=
__put_user
(
sfp
,
&
rw
->
ins
[
6
]);
/* frame pointer */
if
(
regs
->
u_regs
[
14
]){
struct
reg_window
*
rw
=
(
struct
reg_window
__user
*
)
regs
->
u_regs
[
14
];
err
|=
__put_user
(
signr
,
&
rw
->
ins
[
0
]);
err
|=
__put_user
(
si
,
&
rw
->
ins
[
1
]);
err
|=
__put_user
(
uc
,
&
rw
->
ins
[
2
]);
err
|=
__put_user
(
sfp
,
&
rw
->
ins
[
6
]);
/* frame pointer */
if
(
err
)
goto
sigsegv
;
...
...
@@ -854,10 +866,10 @@ setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc,
do_exit
(
SIGSEGV
);
}
asmlinkage
int
svr4_getcontext
(
svr4_ucontext_t
*
uc
,
struct
pt_regs
*
regs
)
asmlinkage
int
svr4_getcontext
(
svr4_ucontext_t
__user
*
uc
,
struct
pt_regs
*
regs
)
{
svr4_gregset_t
*
gr
;
svr4_mcontext_t
*
mc
;
svr4_gregset_t
__user
*
gr
;
svr4_mcontext_t
__user
*
mc
;
svr4_sigset_t
setv
;
int
err
=
0
;
...
...
@@ -866,7 +878,7 @@ asmlinkage int svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs)
if
(
current
->
thread
.
w_saved
)
goto
sigsegv_and_return
;
err
=
clear_user
(
uc
,
sizeof
(
*
uc
));
err
=
clear_user
(
uc
,
sizeof
(
*
uc
));
if
(
err
)
return
-
EFAULT
;
...
...
@@ -881,17 +893,20 @@ asmlinkage int svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs)
setv
.
sigbits
[
3
]
=
current
->
blocked
.
sig
[
3
];
err
|=
__copy_to_user
(
&
uc
->
sigmask
,
&
setv
,
sizeof
(
svr4_sigset_t
));
}
else
err
|=
__copy_to_user
(
&
uc
->
sigmask
,
&
setv
,
2
*
sizeof
(
unsigned
int
));
err
|=
__copy_to_user
(
&
uc
->
sigmask
,
&
setv
,
2
*
sizeof
(
unsigned
int
));
/* Store registers */
err
|=
__put_user
(
regs
->
pc
,
&
uc
->
mcontext
.
greg
[
SVR4_PC
]);
err
|=
__put_user
(
regs
->
npc
,
&
uc
->
mcontext
.
greg
[
SVR4_NPC
]);
err
|=
__put_user
(
regs
->
psr
,
&
uc
->
mcontext
.
greg
[
SVR4_PSR
]);
err
|=
__put_user
(
regs
->
y
,
&
uc
->
mcontext
.
greg
[
SVR4_Y
]);
err
|=
__put_user
(
regs
->
pc
,
&
uc
->
mcontext
.
greg
[
SVR4_PC
]);
err
|=
__put_user
(
regs
->
npc
,
&
uc
->
mcontext
.
greg
[
SVR4_NPC
]);
err
|=
__put_user
(
regs
->
psr
,
&
uc
->
mcontext
.
greg
[
SVR4_PSR
]);
err
|=
__put_user
(
regs
->
y
,
&
uc
->
mcontext
.
greg
[
SVR4_Y
]);
/* Copy g [1..7] and o [0..7] registers */
err
|=
__copy_to_user
(
&
(
*
gr
)[
SVR4_G1
],
&
regs
->
u_regs
[
UREG_G1
],
sizeof
(
uint
)
*
7
);
err
|=
__copy_to_user
(
&
(
*
gr
)[
SVR4_O0
],
&
regs
->
u_regs
[
UREG_I0
],
sizeof
(
uint
)
*
8
);
/* Copy g[1..7] and o[0..7] registers */
err
|=
__copy_to_user
(
&
(
*
gr
)[
SVR4_G1
],
&
regs
->
u_regs
[
UREG_G1
],
sizeof
(
uint
)
*
7
);
err
|=
__copy_to_user
(
&
(
*
gr
)[
SVR4_O0
],
&
regs
->
u_regs
[
UREG_I0
],
sizeof
(
uint
)
*
8
);
/* Setup sigaltstack */
err
|=
__put_user
(
current
->
sas_ss_sp
,
&
uc
->
stack
.
sp
);
...
...
@@ -908,10 +923,10 @@ asmlinkage int svr4_getcontext (svr4_ucontext_t *uc, struct pt_regs *regs)
}
/* Set the context for a svr4 application, this is Solaris way to sigreturn */
asmlinkage
int
svr4_setcontext
(
svr4_ucontext_t
*
c
,
struct
pt_regs
*
regs
)
asmlinkage
int
svr4_setcontext
(
svr4_ucontext_t
__user
*
c
,
struct
pt_regs
*
regs
)
{
struct
thread_struct
*
tp
=
&
current
->
thread
;
svr4_gregset_t
*
gr
;
svr4_gregset_t
__user
*
gr
;
unsigned
long
pc
,
npc
,
psr
;
sigset_t
set
;
svr4_sigset_t
setv
;
...
...
@@ -929,7 +944,7 @@ asmlinkage int svr4_setcontext (svr4_ucontext_t *c, struct pt_regs *regs)
if
(((
uint
)
c
)
&
3
)
goto
sigsegv_and_return
;
if
(
!
__access_ok
((
unsigned
long
)
c
,
sizeof
(
*
c
)))
if
(
!
__access_ok
((
unsigned
long
)
c
,
sizeof
(
*
c
)))
goto
sigsegv_and_return
;
/* Check for valid PC and nPC */
...
...
@@ -937,7 +952,7 @@ asmlinkage int svr4_setcontext (svr4_ucontext_t *c, struct pt_regs *regs)
err
=
__get_user
(
pc
,
&
((
*
gr
)[
SVR4_PC
]));
err
|=
__get_user
(
npc
,
&
((
*
gr
)[
SVR4_NPC
]));
if
((
pc
|
npc
)
&
3
)
if
((
pc
|
npc
)
&
3
)
goto
sigsegv_and_return
;
/* Retrieve information from passed ucontext */
...
...
@@ -973,16 +988,16 @@ asmlinkage int svr4_setcontext (svr4_ucontext_t *c, struct pt_regs *regs)
spin_unlock_irq
(
&
current
->
sighand
->
siglock
);
regs
->
pc
=
pc
;
regs
->
npc
=
npc
|
1
;
err
|=
__get_user
(
regs
->
y
,
&
((
*
gr
)
[
SVR4_Y
]));
err
|=
__get_user
(
psr
,
&
((
*
gr
)
[
SVR4_PSR
]));
err
|=
__get_user
(
regs
->
y
,
&
((
*
gr
)[
SVR4_Y
]));
err
|=
__get_user
(
psr
,
&
((
*
gr
)[
SVR4_PSR
]));
regs
->
psr
&=
~
(
PSR_ICC
);
regs
->
psr
|=
(
psr
&
PSR_ICC
);
/* Restore g[1..7] and o[0..7] registers */
err
|=
__copy_from_user
(
&
regs
->
u_regs
[
UREG_G1
],
&
(
*
gr
)[
SVR4_G1
],
sizeof
(
long
)
*
7
);
err
|=
__copy_from_user
(
&
regs
->
u_regs
[
UREG_I0
],
&
(
*
gr
)[
SVR4_O0
],
sizeof
(
long
)
*
8
);
err
|=
__copy_from_user
(
&
regs
->
u_regs
[
UREG_G1
],
&
(
*
gr
)[
SVR4_G1
],
sizeof
(
long
)
*
7
);
err
|=
__copy_from_user
(
&
regs
->
u_regs
[
UREG_I0
],
&
(
*
gr
)[
SVR4_O0
],
sizeof
(
long
)
*
8
);
return
(
err
?
-
EFAULT
:
0
);
sigsegv_and_return:
...
...
@@ -1000,13 +1015,13 @@ handle_signal(unsigned long signr, struct k_sigaction *ka,
if
(
ka
->
sa
.
sa_flags
&
SA_SIGINFO
)
new_setup_rt_frame
(
ka
,
regs
,
signr
,
oldset
,
info
);
else
if
(
current
->
thread
.
new_signal
)
new_setup_frame
(
ka
,
regs
,
signr
,
oldset
);
new_setup_frame
(
ka
,
regs
,
signr
,
oldset
);
else
setup_frame
(
&
ka
->
sa
,
regs
,
signr
,
oldset
,
info
);
}
if
(
ka
->
sa
.
sa_flags
&
SA_ONESHOT
)
if
(
ka
->
sa
.
sa_flags
&
SA_ONESHOT
)
ka
->
sa
.
sa_handler
=
SIG_DFL
;
if
(
!
(
ka
->
sa
.
sa_flags
&
SA_NOMASK
))
{
if
(
!
(
ka
->
sa
.
sa_flags
&
SA_NOMASK
))
{
spin_lock_irq
(
&
current
->
sighand
->
siglock
);
sigorsets
(
&
current
->
blocked
,
&
current
->
blocked
,
&
ka
->
sa
.
sa_mask
);
sigaddset
(
&
current
->
blocked
,
signr
);
...
...
@@ -1028,7 +1043,7 @@ static inline void syscall_restart(unsigned long orig_i0, struct pt_regs *regs,
regs
->
psr
|=
PSR_C
;
break
;
case
ERESTARTSYS
:
if
(
!
(
sa
->
sa_flags
&
SA_RESTART
))
if
(
!
(
sa
->
sa_flags
&
SA_RESTART
))
goto
no_system_call_restart
;
/* fallthrough */
case
ERESTARTNOINTR
:
...
...
@@ -1095,13 +1110,15 @@ asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
}
asmlinkage
int
do_sys_sigstack
(
struct
sigstack
*
ssptr
,
struct
sigstack
*
ossptr
,
unsigned
long
sp
)
do_sys_sigstack
(
struct
sigstack
__user
*
ssptr
,
struct
sigstack
__user
*
ossptr
,
unsigned
long
sp
)
{
int
ret
=
-
EFAULT
;
/* First see if old state is wanted. */
if
(
ossptr
)
{
if
(
put_user
(
current
->
sas_ss_sp
+
current
->
sas_ss_size
,
&
ossptr
->
the_stack
)
||
if
(
put_user
(
current
->
sas_ss_sp
+
current
->
sas_ss_size
,
&
ossptr
->
the_stack
)
||
__put_user
(
on_sig_stack
(
sp
),
&
ossptr
->
cur_status
))
goto
out
;
}
...
...
arch/sparc64/kernel/signal.c
View file @
35ecc0e9
...
...
@@ -42,8 +42,8 @@ static int do_signal(sigset_t *oldset, struct pt_regs * regs,
/* {set, get}context() needed for 64-bit SparcLinux userland. */
asmlinkage
void
sparc64_set_context
(
struct
pt_regs
*
regs
)
{
struct
ucontext
*
ucp
=
(
struct
ucontext
*
)
regs
->
u_regs
[
UREG_I0
];
mc_gregset_t
*
grp
;
struct
ucontext
*
ucp
=
(
struct
ucontext
__user
*
)
regs
->
u_regs
[
UREG_I0
];
mc_gregset_t
__user
*
grp
;
unsigned
long
pc
,
npc
,
tstate
;
unsigned
long
fp
,
i7
;
unsigned
char
fenab
;
...
...
@@ -104,9 +104,9 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
err
|=
__get_user
(
fp
,
&
(
ucp
->
uc_mcontext
.
mc_fp
));
err
|=
__get_user
(
i7
,
&
(
ucp
->
uc_mcontext
.
mc_i7
));
err
|=
__put_user
(
fp
,
(
&
(((
struct
reg_window
*
)(
STACK_BIAS
+
regs
->
u_regs
[
UREG_I6
]))
->
ins
[
6
])));
(
&
(((
struct
reg_window
__user
*
)(
STACK_BIAS
+
regs
->
u_regs
[
UREG_I6
]))
->
ins
[
6
])));
err
|=
__put_user
(
i7
,
(
&
(((
struct
reg_window
*
)(
STACK_BIAS
+
regs
->
u_regs
[
UREG_I6
]))
->
ins
[
7
])));
(
&
(((
struct
reg_window
__user
*
)(
STACK_BIAS
+
regs
->
u_regs
[
UREG_I6
]))
->
ins
[
7
])));
err
|=
__get_user
(
fenab
,
&
(
ucp
->
uc_mcontext
.
mc_fpregs
.
mcfpu_enab
));
if
(
fenab
)
{
...
...
@@ -121,7 +121,7 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
(
sizeof
(
unsigned
int
)
*
32
));
if
(
fprs
&
FPRS_DU
)
err
|=
copy_from_user
(
fpregs
+
16
,
((
unsigned
long
*
)
&
(
ucp
->
uc_mcontext
.
mc_fpregs
.
mcfpu_fregs
))
+
16
,
((
unsigned
long
__user
*
)
&
(
ucp
->
uc_mcontext
.
mc_fpregs
.
mcfpu_fregs
))
+
16
,
(
sizeof
(
unsigned
int
)
*
32
));
err
|=
__get_user
(
current_thread_info
()
->
xfsr
[
0
],
&
(
ucp
->
uc_mcontext
.
mc_fpregs
.
mcfpu_fsr
));
...
...
@@ -139,9 +139,9 @@ asmlinkage void sparc64_set_context(struct pt_regs *regs)
asmlinkage
void
sparc64_get_context
(
struct
pt_regs
*
regs
)
{
struct
ucontext
*
ucp
=
(
struct
ucontext
*
)
regs
->
u_regs
[
UREG_I0
];
mc_gregset_t
*
grp
;
mcontext_t
*
mcp
;
struct
ucontext
*
ucp
=
(
struct
ucontext
__user
*
)
regs
->
u_regs
[
UREG_I0
];
mc_gregset_t
__user
*
grp
;
mcontext_t
__user
*
mcp
;
unsigned
long
fp
,
i7
;
unsigned
char
fenab
;
int
err
;
...
...
@@ -170,7 +170,7 @@ asmlinkage void sparc64_get_context(struct pt_regs *regs)
err
=
0
;
if
(
_NSIG_WORDS
==
1
)
err
|=
__put_user
(
current
->
blocked
.
sig
[
0
],
(
unsigned
long
*
)
&
ucp
->
uc_sigmask
);
(
unsigned
long
__user
*
)
&
ucp
->
uc_sigmask
);
else
err
|=
__copy_to_user
(
&
ucp
->
uc_sigmask
,
&
current
->
blocked
,
sizeof
(
sigset_t
));
...
...
@@ -196,9 +196,9 @@ asmlinkage void sparc64_get_context(struct pt_regs *regs)
err
|=
__put_user
(
regs
->
u_regs
[
UREG_I7
],
&
((
*
grp
)[
MC_O7
]));
err
|=
__get_user
(
fp
,
(
&
(((
struct
reg_window
*
)(
STACK_BIAS
+
regs
->
u_regs
[
UREG_I6
]))
->
ins
[
6
])));
(
&
(((
struct
reg_window
__user
*
)(
STACK_BIAS
+
regs
->
u_regs
[
UREG_I6
]))
->
ins
[
6
])));
err
|=
__get_user
(
i7
,
(
&
(((
struct
reg_window
*
)(
STACK_BIAS
+
regs
->
u_regs
[
UREG_I6
]))
->
ins
[
7
])));
(
&
(((
struct
reg_window
__user
*
)(
STACK_BIAS
+
regs
->
u_regs
[
UREG_I6
]))
->
ins
[
7
])));
err
|=
__put_user
(
fp
,
&
(
mcp
->
mc_fp
));
err
|=
__put_user
(
i7
,
&
(
mcp
->
mc_i7
));
...
...
@@ -213,7 +213,7 @@ asmlinkage void sparc64_get_context(struct pt_regs *regs)
(
sizeof
(
unsigned
int
)
*
32
));
if
(
fprs
&
FPRS_DU
)
err
|=
copy_to_user
(
((
unsigned
long
*
)
&
(
mcp
->
mc_fpregs
.
mcfpu_fregs
))
+
16
,
fpregs
+
16
,
((
unsigned
long
__user
*
)
&
(
mcp
->
mc_fpregs
.
mcfpu_fregs
))
+
16
,
fpregs
+
16
,
(
sizeof
(
unsigned
int
)
*
32
));
err
|=
__put_user
(
current_thread_info
()
->
xfsr
[
0
],
&
(
mcp
->
mc_fpregs
.
mcfpu_fsr
));
err
|=
__put_user
(
current_thread_info
()
->
gsr
[
0
],
&
(
mcp
->
mc_fpregs
.
mcfpu_gsr
));
...
...
@@ -231,7 +231,7 @@ struct rt_signal_frame {
struct
sparc_stackf
ss
;
siginfo_t
info
;
struct
pt_regs
regs
;
__siginfo_fpu_t
*
fpu_save
;
__siginfo_fpu_t
__user
*
fpu_save
;
stack_t
stack
;
sigset_t
mask
;
__siginfo_fpu_t
fpu_state
;
...
...
@@ -300,7 +300,7 @@ asmlinkage void do_sigsuspend(struct pt_regs *regs)
_sigpause_common
(
regs
->
u_regs
[
UREG_I0
],
regs
);
}
asmlinkage
void
do_rt_sigsuspend
(
sigset_t
*
uset
,
size_t
sigsetsize
,
struct
pt_regs
*
regs
)
asmlinkage
void
do_rt_sigsuspend
(
sigset_t
__user
*
uset
,
size_t
sigsetsize
,
struct
pt_regs
*
regs
)
{
sigset_t
oldset
,
set
;
...
...
@@ -351,7 +351,7 @@ asmlinkage void do_rt_sigsuspend(sigset_t *uset, size_t sigsetsize, struct pt_re
}
static
inline
int
restore_fpu_state
(
struct
pt_regs
*
regs
,
__siginfo_fpu_t
*
fpu
)
restore_fpu_state
(
struct
pt_regs
*
regs
,
__siginfo_fpu_t
__user
*
fpu
)
{
unsigned
long
*
fpregs
=
current_thread_info
()
->
fpregs
;
unsigned
long
fprs
;
...
...
@@ -374,16 +374,16 @@ restore_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
void
do_rt_sigreturn
(
struct
pt_regs
*
regs
)
{
struct
rt_signal_frame
*
sf
;
struct
rt_signal_frame
__user
*
sf
;
unsigned
long
tpc
,
tnpc
,
tstate
;
__siginfo_fpu_t
*
fpu_save
;
__siginfo_fpu_t
__user
*
fpu_save
;
mm_segment_t
old_fs
;
sigset_t
set
;
stack_t
st
;
int
err
;
synchronize_user_stack
();
sf
=
(
struct
rt_signal_frame
*
)
sf
=
(
struct
rt_signal_frame
__user
*
)
(
regs
->
u_regs
[
UREG_FP
]
+
STACK_BIAS
);
/* 1. Make sure we are not getting garbage from the user */
...
...
@@ -438,7 +438,7 @@ void do_rt_sigreturn(struct pt_regs *regs)
}
/* Checks if the fp is valid */
static
int
invalid_frame_pointer
(
void
*
fp
,
int
fplen
)
static
int
invalid_frame_pointer
(
void
__user
*
fp
,
int
fplen
)
{
if
(((
unsigned
long
)
fp
)
&
7
)
return
1
;
...
...
@@ -446,7 +446,7 @@ static int invalid_frame_pointer(void *fp, int fplen)
}
static
inline
int
save_fpu_state
(
struct
pt_regs
*
regs
,
__siginfo_fpu_t
*
fpu
)
save_fpu_state
(
struct
pt_regs
*
regs
,
__siginfo_fpu_t
__user
*
fpu
)
{
unsigned
long
*
fpregs
=
(
unsigned
long
*
)(
regs
+
1
);
unsigned
long
fprs
;
...
...
@@ -466,7 +466,7 @@ save_fpu_state(struct pt_regs *regs, __siginfo_fpu_t *fpu)
return
err
;
}
static
inline
void
*
get_sigframe
(
struct
k_sigaction
*
ka
,
struct
pt_regs
*
regs
,
unsigned
long
framesize
)
static
inline
void
__user
*
get_sigframe
(
struct
k_sigaction
*
ka
,
struct
pt_regs
*
regs
,
unsigned
long
framesize
)
{
unsigned
long
sp
;
...
...
@@ -478,14 +478,14 @@ static inline void *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, u
!
((
current
->
sas_ss_sp
+
current
->
sas_ss_size
)
&
7
))
sp
=
current
->
sas_ss_sp
+
current
->
sas_ss_size
;
}
return
(
void
*
)(
sp
-
framesize
);
return
(
void
__user
*
)(
sp
-
framesize
);
}
static
inline
void
setup_rt_frame
(
struct
k_sigaction
*
ka
,
struct
pt_regs
*
regs
,
int
signo
,
sigset_t
*
oldset
,
siginfo_t
*
info
)
{
struct
rt_signal_frame
*
sf
;
struct
rt_signal_frame
__user
*
sf
;
int
sigframe_size
,
err
;
/* 1. Make sure everything is clean */
...
...
@@ -496,7 +496,8 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
if
(
!
(
current_thread_info
()
->
fpsaved
[
0
]
&
FPRS_FEF
))
sigframe_size
-=
sizeof
(
__siginfo_fpu_t
);
sf
=
(
struct
rt_signal_frame
*
)
get_sigframe
(
ka
,
regs
,
sigframe_size
);
sf
=
(
struct
rt_signal_frame
__user
*
)
get_sigframe
(
ka
,
regs
,
sigframe_size
);
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
goto
sigill
;
...
...
@@ -521,8 +522,8 @@ setup_rt_frame(struct k_sigaction *ka, struct pt_regs *regs,
err
|=
copy_to_user
(
&
sf
->
mask
,
oldset
,
sizeof
(
sigset_t
));
err
|=
copy_in_user
((
u64
*
)
sf
,
(
u64
*
)(
regs
->
u_regs
[
UREG_FP
]
+
STACK_BIAS
),
err
|=
copy_in_user
((
u64
__user
*
)
sf
,
(
u64
__user
*
)(
regs
->
u_regs
[
UREG_FP
]
+
STACK_BIAS
),
sizeof
(
struct
reg_window
));
if
(
info
)
...
...
@@ -560,7 +561,8 @@ static inline void handle_signal(unsigned long signr, struct k_sigaction *ka,
siginfo_t
*
info
,
sigset_t
*
oldset
,
struct
pt_regs
*
regs
)
{
setup_rt_frame
(
ka
,
regs
,
signr
,
oldset
,
(
ka
->
sa
.
sa_flags
&
SA_SIGINFO
)
?
info
:
NULL
);
setup_rt_frame
(
ka
,
regs
,
signr
,
oldset
,
(
ka
->
sa
.
sa_flags
&
SA_SIGINFO
)
?
info
:
NULL
);
if
(
ka
->
sa
.
sa_flags
&
SA_ONESHOT
)
ka
->
sa
.
sa_handler
=
SIG_DFL
;
if
(
!
(
ka
->
sa
.
sa_flags
&
SA_NOMASK
))
{
...
...
arch/sparc64/kernel/signal32.c
View file @
35ecc0e9
...
...
@@ -56,7 +56,7 @@ struct signal_sframe32 {
/* struct sigcontext32 * */
u32
sig_scptr
;
int
sig_address
;
struct
sigcontext32
sig_context
;
unsigned
extramask
[
_COMPAT_NSIG_WORDS
-
1
];
unsigned
int
extramask
[
_COMPAT_NSIG_WORDS
-
1
];
};
/*
...
...
@@ -68,9 +68,9 @@ struct new_signal_frame32 {
struct
sparc_stackf32
ss
;
__siginfo32_t
info
;
/* __siginfo_fpu32_t * */
u32
fpu_save
;
unsigned
int
insns
[
2
];
unsigned
extramask
[
_COMPAT_NSIG_WORDS
-
1
];
unsigned
extra_size
;
/* Should be sizeof(siginfo_extra_v8plus_t) */
unsigned
int
insns
[
2
];
unsigned
int
extramask
[
_COMPAT_NSIG_WORDS
-
1
];
unsigned
int
extra_size
;
/* Should be sizeof(siginfo_extra_v8plus_t) */
/* Only valid if (info.si_regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */
siginfo_extra_v8plus_t
v8plus
;
__siginfo_fpu_t
fpu_state
;
...
...
@@ -82,9 +82,9 @@ struct rt_signal_frame32 {
struct
pt_regs32
regs
;
compat_sigset_t
mask
;
/* __siginfo_fpu32_t * */
u32
fpu_save
;
unsigned
int
insns
[
2
];
unsigned
int
insns
[
2
];
stack_t32
stack
;
unsigned
extra_size
;
/* Should be sizeof(siginfo_extra_v8plus_t) */
unsigned
int
extra_size
;
/* Should be sizeof(siginfo_extra_v8plus_t) */
/* Only valid if (regs.psr & (PSR_VERS|PSR_IMPL)) == PSR_V8PLUS */
siginfo_extra_v8plus_t
v8plus
;
__siginfo_fpu_t
fpu_state
;
...
...
@@ -95,11 +95,11 @@ struct rt_signal_frame32 {
#define NF_ALIGNEDSZ (((sizeof(struct new_signal_frame32) + 7) & (~7)))
#define RT_ALIGNEDSZ (((sizeof(struct rt_signal_frame32) + 7) & (~7)))
int
copy_siginfo_to_user32
(
siginfo_t32
*
to
,
siginfo_t
*
from
)
int
copy_siginfo_to_user32
(
siginfo_t32
__user
*
to
,
siginfo_t
*
from
)
{
int
err
;
if
(
!
access_ok
(
VERIFY_WRITE
,
to
,
sizeof
(
siginfo_t32
)))
if
(
!
access_ok
(
VERIFY_WRITE
,
to
,
sizeof
(
siginfo_t32
)))
return
-
EFAULT
;
/* If you change siginfo_t structure, please be sure
...
...
@@ -187,7 +187,7 @@ asmlinkage void do_rt_sigsuspend32(u32 uset, size_t sigsetsize, struct pt_regs *
regs
->
u_regs
[
UREG_I0
]
=
EINVAL
;
return
;
}
if
(
copy_from_user
(
&
set32
,
(
void
*
)(
long
)
uset
,
sizeof
(
set32
)))
{
if
(
copy_from_user
(
&
set32
,
(
void
__user
*
)(
long
)
uset
,
sizeof
(
set32
)))
{
regs
->
tstate
|=
TSTATE_ICARRY
;
regs
->
u_regs
[
UREG_I0
]
=
EFAULT
;
return
;
...
...
@@ -231,7 +231,7 @@ asmlinkage void do_rt_sigsuspend32(u32 uset, size_t sigsetsize, struct pt_regs *
}
}
static
int
restore_fpu_state32
(
struct
pt_regs
*
regs
,
__siginfo_fpu_t
*
fpu
)
static
int
restore_fpu_state32
(
struct
pt_regs
*
regs
,
__siginfo_fpu_t
__user
*
fpu
)
{
unsigned
long
*
fpregs
=
current_thread_info
()
->
fpregs
;
unsigned
long
fprs
;
...
...
@@ -252,7 +252,7 @@ static int restore_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu)
void
do_new_sigreturn32
(
struct
pt_regs
*
regs
)
{
struct
new_signal_frame32
*
sf
;
struct
new_signal_frame32
__user
*
sf
;
unsigned
int
psr
;
unsigned
pc
,
npc
,
fpu_save
;
sigset_t
set
;
...
...
@@ -260,10 +260,10 @@ void do_new_sigreturn32(struct pt_regs *regs)
int
err
,
i
;
regs
->
u_regs
[
UREG_FP
]
&=
0x00000000ffffffffUL
;
sf
=
(
struct
new_signal_frame32
*
)
regs
->
u_regs
[
UREG_FP
];
sf
=
(
struct
new_signal_frame32
__user
*
)
regs
->
u_regs
[
UREG_FP
];
/* 1. Make sure we are not getting garbage from the user */
if
(
verify_area
(
VERIFY_READ
,
sf
,
sizeof
(
*
sf
))
||
if
(
verify_area
(
VERIFY_READ
,
sf
,
sizeof
(
*
sf
))
||
(((
unsigned
long
)
sf
)
&
3
))
goto
segv
;
...
...
@@ -302,7 +302,8 @@ void do_new_sigreturn32(struct pt_regs *regs)
if
(
fpu_save
)
err
|=
restore_fpu_state32
(
regs
,
&
sf
->
fpu_state
);
err
|=
__get_user
(
seta
[
0
],
&
sf
->
info
.
si_mask
);
err
|=
copy_from_user
(
seta
+
1
,
&
sf
->
extramask
,
(
_COMPAT_NSIG_WORDS
-
1
)
*
sizeof
(
unsigned
));
err
|=
copy_from_user
(
seta
+
1
,
&
sf
->
extramask
,
(
_COMPAT_NSIG_WORDS
-
1
)
*
sizeof
(
unsigned
int
));
if
(
err
)
goto
segv
;
switch
(
_NSIG_WORDS
)
{
...
...
@@ -324,17 +325,17 @@ void do_new_sigreturn32(struct pt_regs *regs)
asmlinkage
void
do_sigreturn32
(
struct
pt_regs
*
regs
)
{
struct
sigcontext32
*
scptr
;
unsigned
pc
,
npc
,
psr
;
struct
sigcontext32
__user
*
scptr
;
unsigned
int
pc
,
npc
,
psr
;
sigset_t
set
;
unsigned
seta
[
_COMPAT_NSIG_WORDS
];
unsigned
int
seta
[
_COMPAT_NSIG_WORDS
];
int
err
;
synchronize_user_stack
();
if
(
test_thread_flag
(
TIF_NEWSIGNALS
))
return
do_new_sigreturn32
(
regs
);
scptr
=
(
struct
sigcontext32
*
)
scptr
=
(
struct
sigcontext32
__user
*
)
(
regs
->
u_regs
[
UREG_I0
]
&
0x00000000ffffffffUL
);
/* Check sanity of the user arg. */
if
(
verify_area
(
VERIFY_READ
,
scptr
,
sizeof
(
struct
sigcontext32
))
||
...
...
@@ -349,7 +350,8 @@ asmlinkage void do_sigreturn32(struct pt_regs *regs)
err
|=
__get_user
(
seta
[
0
],
&
scptr
->
sigc_mask
);
/* Note that scptr + 1 points to extramask */
err
|=
copy_from_user
(
seta
+
1
,
scptr
+
1
,
(
_COMPAT_NSIG_WORDS
-
1
)
*
sizeof
(
unsigned
));
err
|=
copy_from_user
(
seta
+
1
,
scptr
+
1
,
(
_COMPAT_NSIG_WORDS
-
1
)
*
sizeof
(
unsigned
int
));
if
(
err
)
goto
segv
;
switch
(
_NSIG_WORDS
)
{
...
...
@@ -388,9 +390,8 @@ asmlinkage void do_sigreturn32(struct pt_regs *regs)
asmlinkage
void
do_rt_sigreturn32
(
struct
pt_regs
*
regs
)
{
struct
rt_signal_frame32
*
sf
;
unsigned
int
psr
;
unsigned
pc
,
npc
,
fpu_save
;
struct
rt_signal_frame32
__user
*
sf
;
unsigned
int
psr
,
pc
,
npc
,
fpu_save
;
mm_segment_t
old_fs
;
sigset_t
set
;
compat_sigset_t
seta
;
...
...
@@ -399,10 +400,10 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
synchronize_user_stack
();
regs
->
u_regs
[
UREG_FP
]
&=
0x00000000ffffffffUL
;
sf
=
(
struct
rt_signal_frame32
*
)
regs
->
u_regs
[
UREG_FP
];
sf
=
(
struct
rt_signal_frame32
__user
*
)
regs
->
u_regs
[
UREG_FP
];
/* 1. Make sure we are not getting garbage from the user */
if
(
verify_area
(
VERIFY_READ
,
sf
,
sizeof
(
*
sf
))
||
if
(
verify_area
(
VERIFY_READ
,
sf
,
sizeof
(
*
sf
))
||
(((
unsigned
long
)
sf
)
&
3
))
goto
segv
;
...
...
@@ -471,14 +472,14 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
}
/* Checks if the fp is valid */
static
int
invalid_frame_pointer
(
void
*
fp
,
int
fplen
)
static
int
invalid_frame_pointer
(
void
__user
*
fp
,
int
fplen
)
{
if
((((
unsigned
long
)
fp
)
&
7
)
||
((
unsigned
long
)
fp
)
>
0x100000000ULL
-
fplen
)
return
1
;
return
0
;
}
static
void
*
get_sigframe
(
struct
sigaction
*
sa
,
struct
pt_regs
*
regs
,
unsigned
long
framesize
)
static
void
__user
*
get_sigframe
(
struct
sigaction
*
sa
,
struct
pt_regs
*
regs
,
unsigned
long
framesize
)
{
unsigned
long
sp
;
...
...
@@ -490,25 +491,21 @@ static void *get_sigframe(struct sigaction *sa, struct pt_regs *regs, unsigned l
if
(
!
on_sig_stack
(
sp
)
&&
!
((
current
->
sas_ss_sp
+
current
->
sas_ss_size
)
&
7
))
sp
=
current
->
sas_ss_sp
+
current
->
sas_ss_size
;
}
return
(
void
*
)(
sp
-
framesize
);
return
(
void
__user
*
)(
sp
-
framesize
);
}
static
void
setup_frame32
(
struct
sigaction
*
sa
,
struct
pt_regs
*
regs
,
int
signr
,
sigset_t
*
oldset
,
siginfo_t
*
info
)
{
struct
signal_sframe32
*
sframep
;
struct
sigcontext32
*
sc
;
unsigned
seta
[
_COMPAT_NSIG_WORDS
];
struct
signal_sframe32
__user
*
sframep
;
struct
sigcontext32
__user
*
sc
;
unsigned
int
seta
[
_COMPAT_NSIG_WORDS
];
int
err
=
0
;
void
*
sig_address
;
int
sig_code
;
unsigned
long
pc
=
regs
->
tpc
;
unsigned
long
npc
=
regs
->
tnpc
;
#if 0
int window = 0;
#endif
unsigned
psr
;
unsigned
int
psr
;
if
(
test_thread_flag
(
TIF_32BIT
))
{
pc
&=
0xffffffff
;
...
...
@@ -518,8 +515,9 @@ setup_frame32(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *o
synchronize_user_stack
();
save_and_clear_fpu
();
sframep
=
(
struct
signal_sframe32
*
)
get_sigframe
(
sa
,
regs
,
SF_ALIGNEDSZ
);
if
(
invalid_frame_pointer
(
sframep
,
sizeof
(
*
sframep
))){
sframep
=
(
struct
signal_sframe32
__user
*
)
get_sigframe
(
sa
,
regs
,
SF_ALIGNEDSZ
);
if
(
invalid_frame_pointer
(
sframep
,
sizeof
(
*
sframep
))){
/* Don't change signal code and address, so that
* post mortem debuggers can have a look.
*/
...
...
@@ -544,32 +542,21 @@ setup_frame32(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *o
}
err
|=
__put_user
(
seta
[
0
],
&
sc
->
sigc_mask
);
err
|=
__copy_to_user
(
sframep
->
extramask
,
seta
+
1
,
(
_COMPAT_NSIG_WORDS
-
1
)
*
sizeof
(
unsigned
));
(
_COMPAT_NSIG_WORDS
-
1
)
*
sizeof
(
unsigned
int
));
err
|=
__put_user
(
regs
->
u_regs
[
UREG_FP
],
&
sc
->
sigc_sp
);
err
|=
__put_user
(
pc
,
&
sc
->
sigc_pc
);
err
|=
__put_user
(
npc
,
&
sc
->
sigc_npc
);
psr
=
tstate_to_psr
(
regs
->
tstate
);
psr
=
tstate_to_psr
(
regs
->
tstate
);
if
(
current_thread_info
()
->
fpsaved
[
0
]
&
FPRS_FEF
)
psr
|=
PSR_EF
;
err
|=
__put_user
(
psr
,
&
sc
->
sigc_psr
);
err
|=
__put_user
(
regs
->
u_regs
[
UREG_G1
],
&
sc
->
sigc_g1
);
err
|=
__put_user
(
regs
->
u_regs
[
UREG_I0
],
&
sc
->
sigc_o0
);
err
|=
__put_user
(
get_thread_wsaved
(),
&
sc
->
sigc_oswins
);
#if 0
/* w_saved is not currently used... */
if (get_thread_wsaved())
for (window = 0; window < get_thread_wsaved(); window++) {
sc->sigc_spbuf[window] =
(char *) current_thread_info()->rwbuf_stkptrs[window];
err |= copy_to_user(&sc->sigc_wbuf[window],
¤t_thread_info()->reg_window[window],
sizeof(struct reg_window));
}
else
#endif
err
|=
copy_in_user
((
u32
*
)
sframep
,
(
u32
*
)(
regs
->
u_regs
[
UREG_FP
]),
sizeof
(
struct
reg_window32
));
err
|=
copy_in_user
((
u32
__user
*
)
sframep
,
(
u32
__user
*
)(
regs
->
u_regs
[
UREG_FP
]),
sizeof
(
struct
reg_window32
));
set_thread_wsaved
(
0
);
/* So process is allowed to execute. */
err
|=
__put_user
(
signr
,
&
sframep
->
sig_num
);
...
...
@@ -588,7 +575,7 @@ setup_frame32(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *o
switch
(
info
->
si_code
)
{
case
ILL_ILLOPC
:
sig_code
=
SUBSIG_ILLINST
;
break
;
case
ILL_PRVOPC
:
sig_code
=
SUBSIG_PRIVINST
;
break
;
case
ILL_ILLTRP
:
sig_code
=
SUBSIG_BADTRAP
(
info
->
si_trapno
);
break
;
case
ILL_ILLTRP
:
sig_code
=
SUBSIG_BADTRAP
(
info
->
si_trapno
);
break
;
default:
sig_code
=
SUBSIG_STACK
;
break
;
}
break
;
...
...
@@ -646,7 +633,7 @@ setup_frame32(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *o
}
static
int
save_fpu_state32
(
struct
pt_regs
*
regs
,
__siginfo_fpu_t
*
fpu
)
static
int
save_fpu_state32
(
struct
pt_regs
*
regs
,
__siginfo_fpu_t
__user
*
fpu
)
{
unsigned
long
*
fpregs
=
current_thread_info
()
->
fpregs
;
unsigned
long
fprs
;
...
...
@@ -669,11 +656,11 @@ static int save_fpu_state32(struct pt_regs *regs, __siginfo_fpu_t *fpu)
static
void
new_setup_frame32
(
struct
k_sigaction
*
ka
,
struct
pt_regs
*
regs
,
int
signo
,
sigset_t
*
oldset
)
{
struct
new_signal_frame32
*
sf
;
struct
new_signal_frame32
__user
*
sf
;
int
sigframe_size
;
u32
psr
;
int
i
,
err
;
unsigned
seta
[
_COMPAT_NSIG_WORDS
];
unsigned
int
seta
[
_COMPAT_NSIG_WORDS
];
/* 1. Make sure everything is clean */
synchronize_user_stack
();
...
...
@@ -683,9 +670,10 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
if
(
!
(
current_thread_info
()
->
fpsaved
[
0
]
&
FPRS_FEF
))
sigframe_size
-=
sizeof
(
__siginfo_fpu_t
);
sf
=
(
struct
new_signal_frame32
*
)
get_sigframe
(
&
ka
->
sa
,
regs
,
sigframe_size
);
sf
=
(
struct
new_signal_frame32
__user
*
)
get_sigframe
(
&
ka
->
sa
,
regs
,
sigframe_size
);
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
goto
sigill
;
if
(
get_thread_wsaved
()
!=
0
)
...
...
@@ -699,7 +687,7 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
err
=
put_user
(
regs
->
tpc
,
&
sf
->
info
.
si_regs
.
pc
);
err
|=
__put_user
(
regs
->
tnpc
,
&
sf
->
info
.
si_regs
.
npc
);
err
|=
__put_user
(
regs
->
y
,
&
sf
->
info
.
si_regs
.
y
);
psr
=
tstate_to_psr
(
regs
->
tstate
);
psr
=
tstate_to_psr
(
regs
->
tstate
);
if
(
current_thread_info
()
->
fpsaved
[
0
]
&
FPRS_FEF
)
psr
|=
PSR_EF
;
err
|=
__put_user
(
psr
,
&
sf
->
info
.
si_regs
.
psr
);
...
...
@@ -729,10 +717,10 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
}
err
|=
__put_user
(
seta
[
0
],
&
sf
->
info
.
si_mask
);
err
|=
__copy_to_user
(
sf
->
extramask
,
seta
+
1
,
(
_COMPAT_NSIG_WORDS
-
1
)
*
sizeof
(
unsigned
));
(
_COMPAT_NSIG_WORDS
-
1
)
*
sizeof
(
unsigned
int
));
err
|=
copy_in_user
((
u32
*
)
sf
,
(
u32
*
)(
regs
->
u_regs
[
UREG_FP
]),
err
|=
copy_in_user
((
u32
__user
*
)
sf
,
(
u32
__user
*
)(
regs
->
u_regs
[
UREG_FP
]),
sizeof
(
struct
reg_window32
));
if
(
err
)
...
...
@@ -771,7 +759,8 @@ static void new_setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
preempt_disable
();
ptep
=
pte_offset_map
(
pmdp
,
address
);
if
(
pte_present
(
*
ptep
))
{
unsigned
long
page
=
(
unsigned
long
)
page_address
(
pte_page
(
*
ptep
));
unsigned
long
page
=
(
unsigned
long
)
page_address
(
pte_page
(
*
ptep
));
__asm__
__volatile__
(
" membar #StoreStore
\n
"
...
...
@@ -795,30 +784,29 @@ static void
setup_svr4_frame32
(
struct
sigaction
*
sa
,
unsigned
long
pc
,
unsigned
long
npc
,
struct
pt_regs
*
regs
,
int
signr
,
sigset_t
*
oldset
)
{
svr4_signal_frame_t
*
sfp
;
svr4_gregset_t
*
gr
;
svr4_siginfo_t
*
si
;
svr4_mcontext_t
*
mc
;
svr4_gwindows_t
*
gw
;
svr4_ucontext_t
*
uc
;
svr4_signal_frame_t
__user
*
sfp
;
svr4_gregset_t
__user
*
gr
;
svr4_siginfo_t
__user
*
si
;
svr4_mcontext_t
__user
*
mc
;
svr4_gwindows_t
__user
*
gw
;
svr4_ucontext_t
__user
*
uc
;
svr4_sigset_t
setv
;
#if 0
int window = 0;
#endif
unsigned
psr
;
unsigned
int
psr
;
int
i
,
err
;
synchronize_user_stack
();
save_and_clear_fpu
();
regs
->
u_regs
[
UREG_FP
]
&=
0x00000000ffffffffUL
;
sfp
=
(
svr4_signal_frame_t
*
)
get_sigframe
(
sa
,
regs
,
sizeof
(
struct
reg_window32
)
+
SVR4_SF_ALIGNED
);
sfp
=
(
svr4_signal_frame_t
__user
*
)
get_sigframe
(
sa
,
regs
,
sizeof
(
struct
reg_window32
)
+
SVR4_SF_ALIGNED
);
if
(
invalid_frame_pointer
(
sfp
,
sizeof
(
*
sfp
)))
if
(
invalid_frame_pointer
(
sfp
,
sizeof
(
*
sfp
)))
do_exit
(
SIGILL
);
/* Start with a clean frame pointer and fill it */
err
=
clear_user
(
sfp
,
sizeof
(
*
sfp
));
err
=
clear_user
(
sfp
,
sizeof
(
*
sfp
));
/* Setup convenience variables */
si
=
&
sfp
->
si
;
...
...
@@ -838,22 +826,23 @@ setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
setv
.
sigbits
[
3
]
=
(
oldset
->
sig
[
1
]
>>
32
);
err
|=
__copy_to_user
(
&
uc
->
sigmask
,
&
setv
,
sizeof
(
svr4_sigset_t
));
}
else
err
|=
__copy_to_user
(
&
uc
->
sigmask
,
&
setv
,
2
*
sizeof
(
unsigned
));
err
|=
__copy_to_user
(
&
uc
->
sigmask
,
&
setv
,
2
*
sizeof
(
unsigned
int
));
/* Store registers */
if
(
test_thread_flag
(
TIF_32BIT
))
{
regs
->
tpc
&=
0xffffffff
;
regs
->
tnpc
&=
0xffffffff
;
}
err
|=
__put_user
(
regs
->
tpc
,
&
((
*
gr
)
[
SVR4_PC
]));
err
|=
__put_user
(
regs
->
tnpc
,
&
((
*
gr
)
[
SVR4_NPC
]));
psr
=
tstate_to_psr
(
regs
->
tstate
);
err
|=
__put_user
(
regs
->
tpc
,
&
((
*
gr
)[
SVR4_PC
]));
err
|=
__put_user
(
regs
->
tnpc
,
&
((
*
gr
)[
SVR4_NPC
]));
psr
=
tstate_to_psr
(
regs
->
tstate
);
if
(
current_thread_info
()
->
fpsaved
[
0
]
&
FPRS_FEF
)
psr
|=
PSR_EF
;
err
|=
__put_user
(
psr
,
&
((
*
gr
)
[
SVR4_PSR
]));
err
|=
__put_user
(
regs
->
y
,
&
((
*
gr
)
[
SVR4_Y
]));
err
|=
__put_user
(
psr
,
&
((
*
gr
)[
SVR4_PSR
]));
err
|=
__put_user
(
regs
->
y
,
&
((
*
gr
)[
SVR4_Y
]));
/* Copy g
[1..7] and o
[0..7] registers */
/* Copy g
[1..7] and o
[0..7] registers */
for
(
i
=
0
;
i
<
7
;
i
++
)
err
|=
__put_user
(
regs
->
u_regs
[
UREG_G1
+
i
],
(
&
(
*
gr
)[
SVR4_G1
])
+
i
);
for
(
i
=
0
;
i
<
8
;
i
++
)
...
...
@@ -872,29 +861,7 @@ setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
/* 2. Number of windows to restore at setcontext (): */
err
|=
__put_user
(
get_thread_wsaved
(),
&
gw
->
count
);
/* 3. Save each valid window
* Currently, it makes a copy of the windows from the kernel copy.
* David's code for SunOS, makes the copy but keeps the pointer to
* the kernel. My version makes the pointer point to a userland
* copy of those. Mhm, I wonder if I shouldn't just ignore those
* on setcontext and use those that are on the kernel, the signal
* handler should not be modyfing those, mhm.
*
* These windows are just used in case synchronize_user_stack failed
* to flush the user windows.
*/
#if 0
for (window = 0; window < get_thread_wsaved(); window++) {
err |= __put_user((int *) &(gw->win[window]),
(int **) gw->winptr + window);
err |= copy_to_user(&gw->win[window],
¤t_thread_info()->reg_window[window],
sizeof (svr4_rwindow_t));
err |= __put_user(0, (int *) gw->winptr + window);
}
#endif
/* 4. We just pay attention to the gw->count field on setcontext */
/* 3. We just pay attention to the gw->count field on setcontext */
set_thread_wsaved
(
0
);
/* So process is allowed to execute. */
/* Setup the signal information. Solaris expects a bunch of
...
...
@@ -915,14 +882,14 @@ setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
}
/* Arguments passed to signal handler */
if
(
regs
->
u_regs
[
14
]){
struct
reg_window32
*
rw
=
(
struct
reg_window32
*
)
(
regs
->
u_regs
[
14
]
&
0x00000000ffffffffUL
);
err
|=
__put_user
(
signr
,
&
rw
->
ins
[
0
]);
err
|=
__put_user
((
u64
)
si
,
&
rw
->
ins
[
1
]);
err
|=
__put_user
((
u64
)
uc
,
&
rw
->
ins
[
2
]);
err
|=
__put_user
((
u64
)
sfp
,
&
rw
->
ins
[
6
]);
/* frame pointer */
if
(
regs
->
u_regs
[
14
]){
struct
reg_window32
__user
*
rw
=
(
struct
reg_window32
__user
*
)
(
regs
->
u_regs
[
14
]
&
0x00000000ffffffffUL
);
err
|=
__put_user
(
signr
,
&
rw
->
ins
[
0
]);
err
|=
__put_user
((
u64
)
si
,
&
rw
->
ins
[
1
]);
err
|=
__put_user
((
u64
)
uc
,
&
rw
->
ins
[
2
]);
err
|=
__put_user
((
u64
)
sfp
,
&
rw
->
ins
[
6
]);
/* frame pointer */
if
(
err
)
goto
sigsegv
;
...
...
@@ -937,20 +904,21 @@ setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc,
}
asmlinkage
int
svr4_getcontext
(
svr4_ucontext_t
*
uc
,
struct
pt_regs
*
regs
)
svr4_getcontext
(
svr4_ucontext_t
__user
*
uc
,
struct
pt_regs
*
regs
)
{
svr4_gregset_t
*
gr
;
svr4_mcontext_t
*
mc
;
svr4_gregset_t
__user
*
gr
;
svr4_mcontext_t
__user
*
mc
;
svr4_sigset_t
setv
;
int
i
,
err
;
u32
psr
;
synchronize_user_stack
();
save_and_clear_fpu
();
if
(
get_thread_wsaved
())
do_exit
(
SIGSEGV
);
do_exit
(
SIGSEGV
);
err
=
clear_user
(
uc
,
sizeof
(
*
uc
));
err
=
clear_user
(
uc
,
sizeof
(
*
uc
));
/* Setup convenience variables */
mc
=
&
uc
->
mcontext
;
...
...
@@ -970,19 +938,17 @@ svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs)
regs
->
tpc
&=
0xffffffff
;
regs
->
tnpc
&=
0xffffffff
;
}
err
|=
__put_user
(
regs
->
tpc
,
&
uc
->
mcontext
.
greg
[
SVR4_PC
]);
err
|=
__put_user
(
regs
->
tnpc
,
&
uc
->
mcontext
.
greg
[
SVR4_NPC
]);
#if 1
err
|=
__put_user
(
0
,
&
uc
->
mcontext
.
greg
[
SVR4_PSR
]);
#else
i
=
tstate_to_psr
(
regs
->
tstate
)
&
~
PSR_EF
;
err
|=
__put_user
(
regs
->
tpc
,
&
uc
->
mcontext
.
greg
[
SVR4_PC
]);
err
|=
__put_user
(
regs
->
tnpc
,
&
uc
->
mcontext
.
greg
[
SVR4_NPC
]);
psr
=
tstate_to_psr
(
regs
->
tstate
)
&
~
PSR_EF
;
if
(
current_thread_info
()
->
fpsaved
[
0
]
&
FPRS_FEF
)
i
|=
PSR_EF
;
err
|=
__put_user
(
i
,
&
uc
->
mcontext
.
greg
[
SVR4_PSR
]);
#endif
err
|=
__put_user
(
regs
->
y
,
&
uc
->
mcontext
.
greg
[
SVR4_Y
]);
psr
|=
PSR_EF
;
err
|=
__put_user
(
psr
,
&
uc
->
mcontext
.
greg
[
SVR4_PSR
]);
err
|=
__put_user
(
regs
->
y
,
&
uc
->
mcontext
.
greg
[
SVR4_Y
]);
/* Copy g
[1..7] and o
[0..7] registers */
/* Copy g
[1..7] and o
[0..7] registers */
for
(
i
=
0
;
i
<
7
;
i
++
)
err
|=
__put_user
(
regs
->
u_regs
[
UREG_G1
+
i
],
(
&
(
*
gr
)[
SVR4_G1
])
+
i
);
for
(
i
=
0
;
i
<
8
;
i
++
)
...
...
@@ -1001,9 +967,9 @@ svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs)
/* Set the context for a svr4 application, this is Solaris way to sigreturn */
asmlinkage
int
svr4_setcontext
(
svr4_ucontext_t
*
c
,
struct
pt_regs
*
regs
)
asmlinkage
int
svr4_setcontext
(
svr4_ucontext_t
__user
*
c
,
struct
pt_regs
*
regs
)
{
svr4_gregset_t
*
gr
;
svr4_gregset_t
__user
*
gr
;
mm_segment_t
old_fs
;
u32
pc
,
npc
,
psr
;
sigset_t
set
;
...
...
@@ -1020,7 +986,7 @@ asmlinkage int svr4_setcontext(svr4_ucontext_t *c, struct pt_regs *regs)
goto
sigsegv
;
if
(((
unsigned
long
)
c
)
&
3
){
printk
(
"Unaligned structure passed
\n
"
);
printk
(
"Unaligned structure passed
\n
"
);
goto
sigsegv
;
}
...
...
@@ -1040,7 +1006,7 @@ asmlinkage int svr4_setcontext(svr4_ucontext_t *c, struct pt_regs *regs)
/* note that nPC is ored a 1, this is used to inform entry.S */
/* that we don't want it to mess with our PC and nPC */
err
|=
copy_from_user
(
&
setv
,
&
c
->
sigmask
,
sizeof
(
svr4_sigset_t
));
err
|=
copy_from_user
(
&
setv
,
&
c
->
sigmask
,
sizeof
(
svr4_sigset_t
));
set
.
sig
[
0
]
=
setv
.
sigbits
[
0
]
|
(((
long
)
setv
.
sigbits
[
1
])
<<
32
);
if
(
_NSIG_WORDS
>=
2
)
set
.
sig
[
1
]
=
setv
.
sigbits
[
2
]
|
(((
long
)
setv
.
sigbits
[
3
])
<<
32
);
...
...
@@ -1069,14 +1035,11 @@ asmlinkage int svr4_setcontext(svr4_ucontext_t *c, struct pt_regs *regs)
regs
->
tpc
&=
0xffffffff
;
regs
->
tnpc
&=
0xffffffff
;
}
err
|=
__get_user
(
regs
->
y
,
&
((
*
gr
)
[
SVR4_Y
]));
err
|=
__get_user
(
psr
,
&
((
*
gr
)
[
SVR4_PSR
]));
err
|=
__get_user
(
regs
->
y
,
&
((
*
gr
)[
SVR4_Y
]));
err
|=
__get_user
(
psr
,
&
((
*
gr
)[
SVR4_PSR
]));
regs
->
tstate
&=
~
(
TSTATE_ICC
|
TSTATE_XCC
);
regs
->
tstate
|=
psr_to_tstate_icc
(
psr
);
#if 0
if (psr & PSR_EF)
regs->tstate |= TSTATE_PEF;
#endif
/* Restore g[1..7] and o[0..7] registers */
for
(
i
=
0
;
i
<
7
;
i
++
)
err
|=
__get_user
(
regs
->
u_regs
[
UREG_G1
+
i
],
(
&
(
*
gr
)[
SVR4_G1
])
+
i
);
...
...
@@ -1094,7 +1057,7 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
unsigned
long
signr
,
sigset_t
*
oldset
,
siginfo_t
*
info
)
{
struct
rt_signal_frame32
*
sf
;
struct
rt_signal_frame32
__user
*
sf
;
int
sigframe_size
;
u32
psr
;
int
i
,
err
;
...
...
@@ -1108,9 +1071,10 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
if
(
!
(
current_thread_info
()
->
fpsaved
[
0
]
&
FPRS_FEF
))
sigframe_size
-=
sizeof
(
__siginfo_fpu_t
);
sf
=
(
struct
rt_signal_frame32
*
)
get_sigframe
(
&
ka
->
sa
,
regs
,
sigframe_size
);
sf
=
(
struct
rt_signal_frame32
__user
*
)
get_sigframe
(
&
ka
->
sa
,
regs
,
sigframe_size
);
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
if
(
invalid_frame_pointer
(
sf
,
sigframe_size
))
goto
sigill
;
if
(
get_thread_wsaved
()
!=
0
)
...
...
@@ -1124,7 +1088,7 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
err
=
put_user
(
regs
->
tpc
,
&
sf
->
regs
.
pc
);
err
|=
__put_user
(
regs
->
tnpc
,
&
sf
->
regs
.
npc
);
err
|=
__put_user
(
regs
->
y
,
&
sf
->
regs
.
y
);
psr
=
tstate_to_psr
(
regs
->
tstate
);
psr
=
tstate_to_psr
(
regs
->
tstate
);
if
(
current_thread_info
()
->
fpsaved
[
0
]
&
FPRS_FEF
)
psr
|=
PSR_EF
;
err
|=
__put_user
(
psr
,
&
sf
->
regs
.
psr
);
...
...
@@ -1133,7 +1097,8 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
err
|=
__put_user
(
sizeof
(
siginfo_extra_v8plus_t
),
&
sf
->
extra_size
);
err
|=
__put_user
(
SIGINFO_EXTRA_V8PLUS_MAGIC
,
&
sf
->
v8plus
.
g_upper
[
0
]);
for
(
i
=
1
;
i
<
16
;
i
++
)
err
|=
__put_user
(((
u32
*
)
regs
->
u_regs
)[
2
*
i
],
&
sf
->
v8plus
.
g_upper
[
i
]);
err
|=
__put_user
(((
u32
*
)
regs
->
u_regs
)[
2
*
i
],
&
sf
->
v8plus
.
g_upper
[
i
]);
if
(
psr
&
PSR_EF
)
{
err
|=
save_fpu_state32
(
regs
,
&
sf
->
fpu_state
);
...
...
@@ -1162,8 +1127,8 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
}
err
|=
__copy_to_user
(
&
sf
->
mask
,
&
seta
,
sizeof
(
compat_sigset_t
));
err
|=
copy_in_user
((
u32
*
)
sf
,
(
u32
*
)(
regs
->
u_regs
[
UREG_FP
]),
err
|=
copy_in_user
((
u32
__user
*
)
sf
,
(
u32
__user
*
)(
regs
->
u_regs
[
UREG_FP
]),
sizeof
(
struct
reg_window32
));
if
(
err
)
goto
sigsegv
;
...
...
@@ -1204,7 +1169,8 @@ static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs,
preempt_disable
();
ptep
=
pte_offset_map
(
pmdp
,
address
);
if
(
pte_present
(
*
ptep
))
{
unsigned
long
page
=
(
unsigned
long
)
page_address
(
pte_page
(
*
ptep
));
unsigned
long
page
=
(
unsigned
long
)
page_address
(
pte_page
(
*
ptep
));
__asm__
__volatile__
(
" membar #StoreStore
\n
"
...
...
@@ -1229,7 +1195,8 @@ static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka,
int
svr4_signal
)
{
if
(
svr4_signal
)
setup_svr4_frame32
(
&
ka
->
sa
,
regs
->
tpc
,
regs
->
tnpc
,
regs
,
signr
,
oldset
);
setup_svr4_frame32
(
&
ka
->
sa
,
regs
->
tpc
,
regs
->
tnpc
,
regs
,
signr
,
oldset
);
else
{
if
(
ka
->
sa
.
sa_flags
&
SA_SIGINFO
)
setup_rt_frame32
(
ka
,
regs
,
signr
,
oldset
,
info
);
...
...
@@ -1322,13 +1289,16 @@ struct sigstack32 {
asmlinkage
int
do_sys32_sigstack
(
u32
u_ssptr
,
u32
u_ossptr
,
unsigned
long
sp
)
{
struct
sigstack32
*
ssptr
=
(
struct
sigstack32
*
)((
unsigned
long
)(
u_ssptr
));
struct
sigstack32
*
ossptr
=
(
struct
sigstack32
*
)((
unsigned
long
)(
u_ossptr
));
struct
sigstack32
__user
*
ssptr
=
(
struct
sigstack32
__user
*
)((
unsigned
long
)(
u_ssptr
));
struct
sigstack32
__user
*
ossptr
=
(
struct
sigstack32
__user
*
)((
unsigned
long
)(
u_ossptr
));
int
ret
=
-
EFAULT
;
/* First see if old state is wanted. */
if
(
ossptr
)
{
if
(
put_user
(
current
->
sas_ss_sp
+
current
->
sas_ss_size
,
&
ossptr
->
the_stack
)
||
if
(
put_user
(
current
->
sas_ss_sp
+
current
->
sas_ss_size
,
&
ossptr
->
the_stack
)
||
__put_user
(
on_sig_stack
(
sp
),
&
ossptr
->
cur_status
))
goto
out
;
}
...
...
@@ -1339,15 +1309,18 @@ asmlinkage int do_sys32_sigstack(u32 u_ssptr, u32 u_ossptr, unsigned long sp)
if
(
get_user
((
long
)
ss_sp
,
&
ssptr
->
the_stack
))
goto
out
;
/* If the current stack was set with sigaltstack, don't
swap stacks while we are on it. */
* swap stacks while we are on it.
*/
ret
=
-
EPERM
;
if
(
current
->
sas_ss_sp
&&
on_sig_stack
(
sp
))
goto
out
;
/* Since we don't know the extent of the stack, and we don't
track onstack-ness, but rather calculate it, we must
presume a size. Ho hum this interface is lossy. */
* track onstack-ness, but rather calculate it, we must
* presume a size. Ho hum this interface is lossy.
*/
current
->
sas_ss_sp
=
(
unsigned
long
)
ss_sp
-
SIGSTKSZ
;
current
->
sas_ss_size
=
SIGSTKSZ
;
}
...
...
@@ -1363,17 +1336,17 @@ asmlinkage int do_sys32_sigaltstack(u32 ussa, u32 uossa, unsigned long sp)
int
ret
;
mm_segment_t
old_fs
;
if
(
ussa
&&
(
get_user
((
long
)
uss
.
ss_sp
,
&
((
stack_t32
*
)(
long
)
ussa
)
->
ss_sp
)
||
__get_user
(
uss
.
ss_flags
,
&
((
stack_t32
*
)(
long
)
ussa
)
->
ss_flags
)
||
__get_user
(
uss
.
ss_size
,
&
((
stack_t32
*
)(
long
)
ussa
)
->
ss_size
)))
if
(
ussa
&&
(
get_user
((
long
)
uss
.
ss_sp
,
&
((
stack_t32
__user
*
)(
long
)
ussa
)
->
ss_sp
)
||
__get_user
(
uss
.
ss_flags
,
&
((
stack_t32
__user
*
)(
long
)
ussa
)
->
ss_flags
)
||
__get_user
(
uss
.
ss_size
,
&
((
stack_t32
__user
*
)(
long
)
ussa
)
->
ss_size
)))
return
-
EFAULT
;
old_fs
=
get_fs
();
set_fs
(
KERNEL_DS
);
ret
=
do_sigaltstack
(
ussa
?
&
uss
:
NULL
,
uossa
?
&
uoss
:
NULL
,
sp
);
set_fs
(
old_fs
);
if
(
!
ret
&&
uossa
&&
(
put_user
((
long
)
uoss
.
ss_sp
,
&
((
stack_t32
*
)(
long
)
uossa
)
->
ss_sp
)
||
__put_user
(
uoss
.
ss_flags
,
&
((
stack_t32
*
)(
long
)
uossa
)
->
ss_flags
)
||
__put_user
(
uoss
.
ss_size
,
&
((
stack_t32
*
)(
long
)
uossa
)
->
ss_size
)))
if
(
!
ret
&&
uossa
&&
(
put_user
((
long
)
uoss
.
ss_sp
,
&
((
stack_t32
__user
*
)(
long
)
uossa
)
->
ss_sp
)
||
__put_user
(
uoss
.
ss_flags
,
&
((
stack_t32
__user
*
)(
long
)
uossa
)
->
ss_flags
)
||
__put_user
(
uoss
.
ss_size
,
&
((
stack_t32
__user
*
)(
long
)
uossa
)
->
ss_size
)))
return
-
EFAULT
;
return
ret
;
}
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