Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 356670
b: refs/heads/master
c: 4788069
h: refs/heads/master
v: v3
  • Loading branch information
Al Viro committed Feb 3, 2013
1 parent efc86f1 commit 267f0ea
Show file tree
Hide file tree
Showing 13 changed files with 253 additions and 34 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 51682036d006b175022d0cd010672d3fff041278
refs/heads/master: 47880695011964be808d3151f0f47bd6626f6f2f
7 changes: 0 additions & 7 deletions trunk/arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,10 @@ config ARM64
select CLONE_BACKWARDS
select COMMON_CLK
select GENERIC_CLOCKEVENTS
select GENERIC_COMPAT_RT_SIGACTION
select GENERIC_COMPAT_RT_SIGPENDING
select GENERIC_COMPAT_RT_SIGPROCMASK
select GENERIC_COMPAT_RT_SIGQUEUEINFO
select GENERIC_HARDIRQS_NO_DEPRECATED
select GENERIC_IOMAP
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
select GENERIC_SIGALTSTACK
select GENERIC_SMP_IDLE_THREAD
select GENERIC_TIME_VSYSCALL
select HARDIRQS_SW_RESEND
Expand Down Expand Up @@ -209,8 +204,6 @@ config COMPAT
depends on !ARM64_64K_PAGES
select COMPAT_BINFMT_ELF
select HAVE_UID16
select OLD_SIGSUSPEND3
select COMPAT_OLD_SIGACTION
help
This option enables support for a 32-bit EL0 running under a 64-bit
kernel at EL1. AArch32-specific components such as system calls,
Expand Down
2 changes: 2 additions & 0 deletions trunk/arch/arm64/include/asm/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
* System call wrappers implemented in kernel/entry.S.
*/
asmlinkage long sys_rt_sigreturn_wrapper(void);
asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss,
stack_t __user *uoss);

#include <asm-generic/syscalls.h>

Expand Down
4 changes: 2 additions & 2 deletions trunk/arch/arm64/include/asm/unistd32.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ __SYSCALL(68, sys_ni_syscall) /* 68 was sys_sgetmask */
__SYSCALL(69, sys_ni_syscall) /* 69 was sys_ssetmask */
__SYSCALL(70, sys_setreuid16)
__SYSCALL(71, sys_setregid16)
__SYSCALL(72, sys_sigsuspend)
__SYSCALL(72, compat_sys_sigsuspend)
__SYSCALL(73, compat_sys_sigpending)
__SYSCALL(74, sys_sethostname)
__SYSCALL(75, compat_sys_setrlimit)
Expand Down Expand Up @@ -207,7 +207,7 @@ __SYSCALL(182, sys_chown16)
__SYSCALL(183, sys_getcwd)
__SYSCALL(184, sys_capget)
__SYSCALL(185, sys_capset)
__SYSCALL(186, compat_sys_sigaltstack)
__SYSCALL(186, compat_sys_sigaltstack_wrapper)
__SYSCALL(187, compat_sys_sendfile)
__SYSCALL(188, sys_ni_syscall) /* 188 reserved */
__SYSCALL(189, sys_ni_syscall) /* 189 reserved */
Expand Down
5 changes: 5 additions & 0 deletions trunk/arch/arm64/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -677,5 +677,10 @@ ENTRY(sys_rt_sigreturn_wrapper)
b sys_rt_sigreturn
ENDPROC(sys_rt_sigreturn_wrapper)

ENTRY(sys_sigaltstack_wrapper)
ldr x2, [sp, #S_SP]
b sys_sigaltstack
ENDPROC(sys_sigaltstack_wrapper)

ENTRY(handle_arch_irq)
.quad 0
17 changes: 15 additions & 2 deletions trunk/arch/arm64/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,8 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
if (restore_sigframe(regs, frame))
goto badframe;

if (restore_altstack(&frame->uc.uc_stack))
if (do_sigaltstack(&frame->uc.uc_stack,
NULL, regs->sp) == -EFAULT)
goto badframe;

return regs->regs[0];
Expand All @@ -163,6 +164,12 @@ asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
return 0;
}

asmlinkage long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss,
unsigned long sp)
{
return do_sigaltstack(uss, uoss, sp);
}

static int setup_sigframe(struct rt_sigframe __user *sf,
struct pt_regs *regs, sigset_t *set)
{
Expand Down Expand Up @@ -243,6 +250,7 @@ static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
sigset_t *set, struct pt_regs *regs)
{
struct rt_sigframe __user *frame;
stack_t stack;
int err = 0;

frame = get_sigframe(ka, regs);
Expand All @@ -252,7 +260,12 @@ static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
__put_user_error(0, &frame->uc.uc_flags, err);
__put_user_error(NULL, &frame->uc.uc_link, err);

err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
memset(&stack, 0, sizeof(stack));
stack.ss_sp = (void __user *)current->sas_ss_sp;
stack.ss_flags = sas_ss_flags(regs->sp);
stack.ss_size = current->sas_ss_size;
err |= __copy_to_user(&frame->uc.uc_stack, &stack, sizeof(stack));

err |= setup_sigframe(frame, regs, set);
if (err == 0) {
setup_return(regs, ka, frame, usig);
Expand Down
220 changes: 218 additions & 2 deletions trunk/arch/arm64/kernel/signal32.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,26 @@
#include <asm/uaccess.h>
#include <asm/unistd32.h>

struct compat_sigaction {
compat_uptr_t sa_handler;
compat_ulong_t sa_flags;
compat_uptr_t sa_restorer;
compat_sigset_t sa_mask;
};

struct compat_old_sigaction {
compat_uptr_t sa_handler;
compat_old_sigset_t sa_mask;
compat_ulong_t sa_flags;
compat_uptr_t sa_restorer;
};

typedef struct compat_sigaltstack {
compat_uptr_t ss_sp;
int ss_flags;
compat_size_t ss_size;
} compat_stack_t;

struct compat_sigcontext {
/* We always set these two fields to 0 */
compat_ulong_t trap_no;
Expand Down Expand Up @@ -319,6 +339,127 @@ static int compat_restore_vfp_context(struct compat_vfp_sigframe __user *frame)
return err ? -EFAULT : 0;
}

/*
* atomically swap in the new signal mask, and wait for a signal.
*/
asmlinkage int compat_sys_sigsuspend(int restart, compat_ulong_t oldmask,
compat_old_sigset_t mask)
{
sigset_t blocked;

siginitset(&current->blocked, mask);
return sigsuspend(&blocked);
}

asmlinkage int compat_sys_sigaction(int sig,
const struct compat_old_sigaction __user *act,
struct compat_old_sigaction __user *oact)
{
struct k_sigaction new_ka, old_ka;
int ret;
compat_old_sigset_t mask;
compat_uptr_t handler, restorer;

if (act) {
if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
__get_user(handler, &act->sa_handler) ||
__get_user(restorer, &act->sa_restorer) ||
__get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
__get_user(mask, &act->sa_mask))
return -EFAULT;

new_ka.sa.sa_handler = compat_ptr(handler);
new_ka.sa.sa_restorer = compat_ptr(restorer);
siginitset(&new_ka.sa.sa_mask, mask);
}

ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);

if (!ret && oact) {
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
__put_user(ptr_to_compat(old_ka.sa.sa_handler),
&oact->sa_handler) ||
__put_user(ptr_to_compat(old_ka.sa.sa_restorer),
&oact->sa_restorer) ||
__put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
return -EFAULT;
}

return ret;
}

asmlinkage int compat_sys_rt_sigaction(int sig,
const struct compat_sigaction __user *act,
struct compat_sigaction __user *oact,
compat_size_t sigsetsize)
{
struct k_sigaction new_ka, old_ka;
int ret;

/* XXX: Don't preclude handling different sized sigset_t's. */
if (sigsetsize != sizeof(compat_sigset_t))
return -EINVAL;

if (act) {
compat_uptr_t handler, restorer;

ret = get_user(handler, &act->sa_handler);
new_ka.sa.sa_handler = compat_ptr(handler);
ret |= get_user(restorer, &act->sa_restorer);
new_ka.sa.sa_restorer = compat_ptr(restorer);
ret |= get_sigset_t(&new_ka.sa.sa_mask, &act->sa_mask);
ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
if (ret)
return -EFAULT;
}

ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
if (!ret && oact) {
ret = put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler);
ret |= put_sigset_t(&oact->sa_mask, &old_ka.sa.sa_mask);
ret |= __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
}
return ret;
}

int compat_do_sigaltstack(compat_uptr_t compat_uss, compat_uptr_t compat_uoss,
compat_ulong_t sp)
{
compat_stack_t __user *newstack = compat_ptr(compat_uss);
compat_stack_t __user *oldstack = compat_ptr(compat_uoss);
compat_uptr_t ss_sp;
int ret;
mm_segment_t old_fs;
stack_t uss, uoss;

/* Marshall the compat new stack into a stack_t */
if (newstack) {
if (get_user(ss_sp, &newstack->ss_sp) ||
__get_user(uss.ss_flags, &newstack->ss_flags) ||
__get_user(uss.ss_size, &newstack->ss_size))
return -EFAULT;
uss.ss_sp = compat_ptr(ss_sp);
}

old_fs = get_fs();
set_fs(KERNEL_DS);
/* The __user pointer casts are valid because of the set_fs() */
ret = do_sigaltstack(
newstack ? (stack_t __user *) &uss : NULL,
oldstack ? (stack_t __user *) &uoss : NULL,
(unsigned long)sp);
set_fs(old_fs);

/* Convert the old stack_t into a compat stack. */
if (!ret && oldstack &&
(put_user(ptr_to_compat(uoss.ss_sp), &oldstack->ss_sp) ||
__put_user(uoss.ss_flags, &oldstack->ss_flags) ||
__put_user(uoss.ss_size, &oldstack->ss_size)))
return -EFAULT;
return ret;
}

static int compat_restore_sigframe(struct pt_regs *regs,
struct compat_sigframe __user *sf)
{
Expand Down Expand Up @@ -421,7 +562,9 @@ asmlinkage int compat_sys_rt_sigreturn(struct pt_regs *regs)
if (compat_restore_sigframe(regs, &frame->sig))
goto badframe;

if (compat_restore_altstack(&frame->sig.uc.uc_stack))
if (compat_do_sigaltstack(ptr_to_compat(&frame->sig.uc.uc_stack),
ptr_to_compat((void __user *)NULL),
regs->compat_sp) == -EFAULT)
goto badframe;

return regs->regs[0];
Expand Down Expand Up @@ -562,7 +705,11 @@ int compat_setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
__put_user_error(0, &frame->sig.uc.uc_flags, err);
__put_user_error(NULL, &frame->sig.uc.uc_link, err);

err |= __compat_save_altstack(&frame->sig.uc.uc_stack, regs->compat_sp);
memset(&stack, 0, sizeof(stack));
stack.ss_sp = (compat_uptr_t)current->sas_ss_sp;
stack.ss_flags = sas_ss_flags(regs->compat_sp);
stack.ss_size = current->sas_ss_size;
err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));

err |= compat_setup_sigframe(&frame->sig, regs, set);

Expand Down Expand Up @@ -595,6 +742,75 @@ int compat_setup_frame(int usig, struct k_sigaction *ka, sigset_t *set,
return err;
}

/*
* RT signals don't have generic compat wrappers.
* See arch/powerpc/kernel/signal_32.c
*/
asmlinkage int compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set,
compat_sigset_t __user *oset,
compat_size_t sigsetsize)
{
sigset_t s;
sigset_t __user *up;
int ret;
mm_segment_t old_fs = get_fs();

if (set) {
if (get_sigset_t(&s, set))
return -EFAULT;
}

set_fs(KERNEL_DS);
/* This is valid because of the set_fs() */
up = (sigset_t __user *) &s;
ret = sys_rt_sigprocmask(how, set ? up : NULL, oset ? up : NULL,
sigsetsize);
set_fs(old_fs);
if (ret)
return ret;
if (oset) {
if (put_sigset_t(oset, &s))
return -EFAULT;
}
return 0;
}

asmlinkage int compat_sys_rt_sigpending(compat_sigset_t __user *set,
compat_size_t sigsetsize)
{
sigset_t s;
int ret;
mm_segment_t old_fs = get_fs();

set_fs(KERNEL_DS);
/* The __user pointer cast is valid because of the set_fs() */
ret = sys_rt_sigpending((sigset_t __user *) &s, sigsetsize);
set_fs(old_fs);
if (!ret) {
if (put_sigset_t(set, &s))
return -EFAULT;
}
return ret;
}

asmlinkage int compat_sys_rt_sigqueueinfo(int pid, int sig,
compat_siginfo_t __user *uinfo)
{
siginfo_t info;
int ret;
mm_segment_t old_fs = get_fs();

ret = copy_siginfo_from_user32(&info, uinfo);
if (unlikely(ret))
return ret;

set_fs (KERNEL_DS);
/* The __user pointer cast is valid because of the set_fs() */
ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *) &info);
set_fs (old_fs);
return ret;
}

void compat_setup_restart_syscall(struct pt_regs *regs)
{
regs->regs[7] = __NR_compat_restart_syscall;
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/arm64/kernel/sys.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ asmlinkage long sys_mmap(unsigned long addr, unsigned long len,
* Wrappers to pass the pt_regs argument.
*/
#define sys_rt_sigreturn sys_rt_sigreturn_wrapper
#define sys_sigaltstack sys_sigaltstack_wrapper

#include <asm/syscalls.h>

Expand Down
5 changes: 5 additions & 0 deletions trunk/arch/arm64/kernel/sys32.S
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,11 @@ compat_sys_rt_sigreturn_wrapper:
b compat_sys_rt_sigreturn
ENDPROC(compat_sys_rt_sigreturn_wrapper)

compat_sys_sigaltstack_wrapper:
ldr x2, [sp, #S_COMPAT_SP]
b compat_do_sigaltstack
ENDPROC(compat_sys_sigaltstack_wrapper)

compat_sys_statfs64_wrapper:
mov w3, #84
cmp w1, #88
Expand Down
1 change: 1 addition & 0 deletions trunk/arch/avr32/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ config AVR32
select GENERIC_CLOCKEVENTS
select HAVE_MOD_ARCH_SPECIFIC
select MODULES_USE_ELF_RELA
select GENERIC_SIGALTSTACK
help
AVR32 is a high-performance 32-bit RISC microprocessor core,
designed for cost-sensitive embedded applications, with particular
Expand Down
Loading

0 comments on commit 267f0ea

Please sign in to comment.