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
431dc804
Commit
431dc804
authored
Feb 13, 2007
by
Ralf Baechle
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[MIPS] Fix sigset_t endianess swapping issues in 32-bit compat code.
Signed-off-by:
Ralf Baechle
<
ralf@linux-mips.org
>
parent
366d6aef
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
115 additions
and
9 deletions
+115
-9
arch/mips/kernel/linux32.c
arch/mips/kernel/linux32.c
+47
-0
arch/mips/kernel/scall64-64.S
arch/mips/kernel/scall64-64.S
+1
-1
arch/mips/kernel/scall64-n32.S
arch/mips/kernel/scall64-n32.S
+1
-1
arch/mips/kernel/signal32.c
arch/mips/kernel/signal32.c
+7
-4
arch/mips/kernel/signal_n32.c
arch/mips/kernel/signal_n32.c
+4
-3
include/asm-mips/compat-signal.h
include/asm-mips/compat-signal.h
+55
-0
No files found.
arch/mips/kernel/linux32.c
View file @
431dc804
...
...
@@ -39,6 +39,7 @@
#include <net/sock.h>
#include <net/scm.h>
#include <asm/compat-signal.h>
#include <asm/ipc.h>
#include <asm/sim.h>
#include <asm/uaccess.h>
...
...
@@ -736,3 +737,49 @@ _sys32_clone(nabi_no_regargs struct pt_regs regs)
return
do_fork
(
clone_flags
,
newsp
,
&
regs
,
0
,
parent_tidptr
,
child_tidptr
);
}
/*
* Implement the event wait interface for the eventpoll file. It is the kernel
* part of the user space epoll_pwait(2).
*/
asmlinkage
long
compat_sys_epoll_pwait
(
int
epfd
,
struct
epoll_event
__user
*
events
,
int
maxevents
,
int
timeout
,
const
compat_sigset_t
__user
*
sigmask
,
size_t
sigsetsize
)
{
int
error
;
sigset_t
ksigmask
,
sigsaved
;
/*
* If the caller wants a certain signal mask to be set during the wait,
* we apply it here.
*/
if
(
sigmask
)
{
if
(
sigsetsize
!=
sizeof
(
sigset_t
))
return
-
EINVAL
;
if
(
!
access_ok
(
VERIFY_READ
,
sigmask
,
sizeof
(
ksigmask
)))
return
-
EFAULT
;
if
(
__copy_conv_sigset_from_user
(
&
ksigmask
,
sigmask
))
return
-
EFAULT
;
sigdelsetmask
(
&
ksigmask
,
sigmask
(
SIGKILL
)
|
sigmask
(
SIGSTOP
));
sigprocmask
(
SIG_SETMASK
,
&
ksigmask
,
&
sigsaved
);
}
error
=
sys_epoll_wait
(
epfd
,
events
,
maxevents
,
timeout
);
/*
* If we changed the signal mask, we need to restore the original one.
* In case we've got a signal while waiting, we do not restore the
* signal mask yet, and we allow do_signal() to deliver the signal on
* the way back to userspace, before the signal mask is restored.
*/
if
(
sigmask
)
{
if
(
error
==
-
EINTR
)
{
memcpy
(
&
current
->
saved_sigmask
,
&
sigsaved
,
sizeof
(
sigsaved
));
set_thread_flag
(
TIF_RESTORE_SIGMASK
);
}
else
sigprocmask
(
SIG_SETMASK
,
&
sigsaved
,
NULL
);
}
return
error
;
}
arch/mips/kernel/scall64-64.S
View file @
431dc804
...
...
@@ -470,4 +470,4 @@ sys_call_table:
PTR
sys_get_robust_list
PTR
sys_kexec_load
/*
5270
*/
PTR
sys_getcpu
PTR
sys_epoll_pwait
PTR
compat_
sys_epoll_pwait
arch/mips/kernel/scall64-n32.S
View file @
431dc804
...
...
@@ -396,4 +396,4 @@ EXPORT(sysn32_call_table)
PTR
compat_sys_get_robust_list
PTR
compat_sys_kexec_load
PTR
sys_getcpu
PTR
sys_epoll_pwait
PTR
compat_
sys_epoll_pwait
arch/mips/kernel/signal32.c
View file @
431dc804
...
...
@@ -8,6 +8,7 @@
* Copyright (C) 1999, 2000 Silicon Graphics, Inc.
*/
#include <linux/cache.h>
#include <linux/compat.h>
#include <linux/sched.h>
#include <linux/mm.h>
#include <linux/smp.h>
...
...
@@ -24,6 +25,7 @@
#include <asm/abi.h>
#include <asm/asm.h>
#include <asm/compat-signal.h>
#include <linux/bitops.h>
#include <asm/cacheflush.h>
#include <asm/sim.h>
...
...
@@ -517,7 +519,7 @@ asmlinkage void sys32_sigreturn(nabi_no_regargs struct pt_regs regs)
frame
=
(
struct
sigframe32
__user
*
)
regs
.
regs
[
29
];
if
(
!
access_ok
(
VERIFY_READ
,
frame
,
sizeof
(
*
frame
)))
goto
badframe
;
if
(
__copy_
from_user
(
&
blocked
,
&
frame
->
sf_mask
,
sizeof
(
blocked
)
))
if
(
__copy_
conv_sigset_from_user
(
&
blocked
,
&
frame
->
sf_mask
))
goto
badframe
;
sigdelsetmask
(
&
blocked
,
~
_BLOCKABLE
);
...
...
@@ -554,7 +556,7 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
frame
=
(
struct
rt_sigframe32
__user
*
)
regs
.
regs
[
29
];
if
(
!
access_ok
(
VERIFY_READ
,
frame
,
sizeof
(
*
frame
)))
goto
badframe
;
if
(
__copy_
from_user
(
&
set
,
&
frame
->
rs_uc
.
uc_sigmask
,
sizeof
(
set
)
))
if
(
__copy_
conv_sigset_from_user
(
&
set
,
&
frame
->
rs_uc
.
uc_sigmask
))
goto
badframe
;
sigdelsetmask
(
&
set
,
~
_BLOCKABLE
);
...
...
@@ -609,7 +611,8 @@ int setup_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
err
|=
install_sigtramp
(
frame
->
sf_code
,
__NR_O32_sigreturn
);
err
|=
setup_sigcontext32
(
regs
,
&
frame
->
sf_sc
);
err
|=
__copy_to_user
(
&
frame
->
sf_mask
,
set
,
sizeof
(
*
set
));
err
|=
__copy_conv_sigset_to_user
(
&
frame
->
sf_mask
,
set
);
if
(
err
)
goto
give_sigsegv
;
...
...
@@ -668,7 +671,7 @@ int setup_rt_frame_32(struct k_sigaction * ka, struct pt_regs *regs,
err
|=
__put_user
(
current
->
sas_ss_size
,
&
frame
->
rs_uc
.
uc_stack
.
ss_size
);
err
|=
setup_sigcontext32
(
regs
,
&
frame
->
rs_uc
.
uc_mcontext
);
err
|=
__copy_
to_user
(
&
frame
->
rs_uc
.
uc_sigmask
,
set
,
sizeof
(
*
set
)
);
err
|=
__copy_
conv_sigset_to_user
(
&
frame
->
rs_uc
.
uc_sigmask
,
set
);
if
(
err
)
goto
give_sigsegv
;
...
...
arch/mips/kernel/signal_n32.c
View file @
431dc804
...
...
@@ -31,6 +31,7 @@
#include <asm/asm.h>
#include <asm/cacheflush.h>
#include <asm/compat-signal.h>
#include <asm/sim.h>
#include <asm/uaccess.h>
#include <asm/ucontext.h>
...
...
@@ -63,7 +64,7 @@ struct ucontextn32 {
s32
uc_link
;
stack32_t
uc_stack
;
struct
sigcontext
uc_mcontext
;
sigset_t
uc_sigmask
;
/* mask last for extensibility */
compat_sigset_t
uc_sigmask
;
/* mask last for extensibility */
};
#if ICACHE_REFILLS_WORKAROUND_WAR == 0
...
...
@@ -129,7 +130,7 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
frame
=
(
struct
rt_sigframe_n32
__user
*
)
regs
.
regs
[
29
];
if
(
!
access_ok
(
VERIFY_READ
,
frame
,
sizeof
(
*
frame
)))
goto
badframe
;
if
(
__copy_
from_user
(
&
set
,
&
frame
->
rs_uc
.
uc_sigmask
,
sizeof
(
set
)
))
if
(
__copy_
conv_sigset_from_user
(
&
set
,
&
frame
->
rs_uc
.
uc_sigmask
))
goto
badframe
;
sigdelsetmask
(
&
set
,
~
_BLOCKABLE
);
...
...
@@ -195,7 +196,7 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
err
|=
__put_user
(
current
->
sas_ss_size
,
&
frame
->
rs_uc
.
uc_stack
.
ss_size
);
err
|=
setup_sigcontext
(
regs
,
&
frame
->
rs_uc
.
uc_mcontext
);
err
|=
__copy_
to_user
(
&
frame
->
rs_uc
.
uc_sigmask
,
set
,
sizeof
(
*
set
)
);
err
|=
__copy_
conv_sigset_to_user
(
&
frame
->
rs_uc
.
uc_sigmask
,
set
);
if
(
err
)
goto
give_sigsegv
;
...
...
include/asm-mips/compat-signal.h
0 → 100644
View file @
431dc804
#ifndef __ASM_COMPAT_SIGNAL_H
#define __ASM_COMPAT_SIGNAL_H
#include <linux/bug.h>
#include <linux/compat.h>
#include <linux/compiler.h>
static
inline
int
__copy_conv_sigset_to_user
(
compat_sigset_t
__user
*
d
,
const
sigset_t
*
s
)
{
int
err
;
BUG_ON
(
sizeof
(
*
d
)
!=
sizeof
(
*
s
));
BUG_ON
(
_NSIG_WORDS
!=
2
);
err
=
__put_user
(
s
->
sig
[
0
],
&
d
->
sig
[
0
]);
err
|=
__put_user
(
s
->
sig
[
0
]
>>
32
,
&
d
->
sig
[
1
]);
err
|=
__put_user
(
s
->
sig
[
1
],
&
d
->
sig
[
2
]);
err
|=
__put_user
(
s
->
sig
[
1
]
>>
32
,
&
d
->
sig
[
3
]);
return
err
;
}
static
inline
int
__copy_conv_sigset_from_user
(
sigset_t
*
d
,
const
compat_sigset_t
__user
*
s
)
{
int
err
;
union
sigset_u
{
sigset_t
s
;
compat_sigset_t
c
;
}
*
u
=
(
union
sigset_u
*
)
d
;
BUG_ON
(
sizeof
(
*
d
)
!=
sizeof
(
*
s
));
BUG_ON
(
_NSIG_WORDS
!=
2
);
if
(
unlikely
(
!
access_ok
(
VERIFY_READ
,
d
,
sizeof
(
*
d
))))
return
-
EFAULT
;
#ifdef CONFIG_CPU_BIG_ENDIAN
err
=
__get_user
(
u
->
c
.
sig
[
1
],
&
s
->
sig
[
0
]);
err
|=
__get_user
(
u
->
c
.
sig
[
0
],
&
s
->
sig
[
1
]);
err
|=
__get_user
(
u
->
c
.
sig
[
3
],
&
s
->
sig
[
2
]);
err
|=
__get_user
(
u
->
c
.
sig
[
2
],
&
s
->
sig
[
3
]);
#endif
#ifdef CONFIG_CPU_LITTLE_ENDIAN
err
=
__get_user
(
u
->
c
.
sig
[
0
],
&
s
->
sig
[
0
]);
err
|=
__get_user
(
u
->
c
.
sig
[
1
],
&
s
->
sig
[
1
]);
err
|=
__get_user
(
u
->
c
.
sig
[
2
],
&
s
->
sig
[
2
]);
err
|=
__get_user
(
u
->
c
.
sig
[
3
],
&
s
->
sig
[
3
]);
#endif
return
err
;
}
#endif
/* __ASM_COMPAT_SIGNAL_H */
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