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
nexedi
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