linux/arch/tile/kernel/compat_signal.c
<<
>>
Prefs
   1/*
   2 * Copyright 2010 Tilera Corporation. All Rights Reserved.
   3 *
   4 *   This program is free software; you can redistribute it and/or
   5 *   modify it under the terms of the GNU General Public License
   6 *   as published by the Free Software Foundation, version 2.
   7 *
   8 *   This program is distributed in the hope that it will be useful, but
   9 *   WITHOUT ANY WARRANTY; without even the implied warranty of
  10 *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  11 *   NON INFRINGEMENT.  See the GNU General Public License for
  12 *   more details.
  13 */
  14
  15#include <linux/sched.h>
  16#include <linux/sched/task_stack.h>
  17#include <linux/mm.h>
  18#include <linux/smp.h>
  19#include <linux/kernel.h>
  20#include <linux/signal.h>
  21#include <linux/errno.h>
  22#include <linux/wait.h>
  23#include <linux/unistd.h>
  24#include <linux/stddef.h>
  25#include <linux/personality.h>
  26#include <linux/suspend.h>
  27#include <linux/ptrace.h>
  28#include <linux/elf.h>
  29#include <linux/compat.h>
  30#include <linux/syscalls.h>
  31#include <linux/uaccess.h>
  32#include <asm/processor.h>
  33#include <asm/ucontext.h>
  34#include <asm/sigframe.h>
  35#include <asm/syscalls.h>
  36#include <asm/vdso.h>
  37#include <arch/interrupts.h>
  38
  39struct compat_ucontext {
  40        compat_ulong_t    uc_flags;
  41        compat_uptr_t     uc_link;
  42        struct compat_sigaltstack         uc_stack;
  43        struct sigcontext uc_mcontext;
  44        sigset_t          uc_sigmask;   /* mask last for extensibility */
  45};
  46
  47struct compat_rt_sigframe {
  48        unsigned char save_area[C_ABI_SAVE_AREA_SIZE]; /* caller save area */
  49        struct compat_siginfo info;
  50        struct compat_ucontext uc;
  51};
  52
  53int copy_siginfo_to_user32(struct compat_siginfo __user *to, const siginfo_t *from)
  54{
  55        int err;
  56
  57        if (!access_ok(VERIFY_WRITE, to, sizeof(struct compat_siginfo)))
  58                return -EFAULT;
  59
  60        /* If you change siginfo_t structure, please make sure that
  61           this code is fixed accordingly.
  62           It should never copy any pad contained in the structure
  63           to avoid security leaks, but must copy the generic
  64           3 ints plus the relevant union member.  */
  65        err = __put_user(from->si_signo, &to->si_signo);
  66        err |= __put_user(from->si_errno, &to->si_errno);
  67        err |= __put_user((short)from->si_code, &to->si_code);
  68
  69        if (from->si_code < 0) {
  70                err |= __put_user(from->si_pid, &to->si_pid);
  71                err |= __put_user(from->si_uid, &to->si_uid);
  72                err |= __put_user(from->si_int, &to->si_int);
  73        } else {
  74                /*
  75                 * First 32bits of unions are always present:
  76                 * si_pid === si_band === si_tid === si_addr(LS half)
  77                 */
  78                err |= __put_user(from->_sifields._pad[0],
  79                                  &to->_sifields._pad[0]);
  80                switch (from->si_code >> 16) {
  81                case __SI_FAULT >> 16:
  82                        break;
  83                case __SI_CHLD >> 16:
  84                        err |= __put_user(from->si_utime, &to->si_utime);
  85                        err |= __put_user(from->si_stime, &to->si_stime);
  86                        err |= __put_user(from->si_status, &to->si_status);
  87                        /* FALL THROUGH */
  88                default:
  89                case __SI_KILL >> 16:
  90                        err |= __put_user(from->si_uid, &to->si_uid);
  91                        break;
  92                case __SI_POLL >> 16:
  93                        err |= __put_user(from->si_fd, &to->si_fd);
  94                        break;
  95                case __SI_TIMER >> 16:
  96                        err |= __put_user(from->si_overrun, &to->si_overrun);
  97                        err |= __put_user(from->si_int, &to->si_int);
  98                        break;
  99                         /* This is not generated by the kernel as of now.  */
 100                case __SI_RT >> 16:
 101                case __SI_MESGQ >> 16:
 102                        err |= __put_user(from->si_uid, &to->si_uid);
 103                        err |= __put_user(from->si_int, &to->si_int);
 104                        break;
 105                }
 106        }
 107        return err;
 108}
 109
 110int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
 111{
 112        int err;
 113
 114        if (!access_ok(VERIFY_READ, from, sizeof(struct compat_siginfo)))
 115                return -EFAULT;
 116
 117        err = __get_user(to->si_signo, &from->si_signo);
 118        err |= __get_user(to->si_errno, &from->si_errno);
 119        err |= __get_user(to->si_code, &from->si_code);
 120
 121        err |= __get_user(to->si_pid, &from->si_pid);
 122        err |= __get_user(to->si_uid, &from->si_uid);
 123        err |= __get_user(to->si_int, &from->si_int);
 124
 125        return err;
 126}
 127
 128/* The assembly shim for this function arranges to ignore the return value. */
 129long compat_sys_rt_sigreturn(void)
 130{
 131        struct pt_regs *regs = current_pt_regs();
 132        struct compat_rt_sigframe __user *frame =
 133                (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
 134        sigset_t set;
 135
 136        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 137                goto badframe;
 138        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
 139                goto badframe;
 140
 141        set_current_blocked(&set);
 142
 143        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
 144                goto badframe;
 145
 146        if (compat_restore_altstack(&frame->uc.uc_stack))
 147                goto badframe;
 148
 149        return 0;
 150
 151badframe:
 152        signal_fault("bad sigreturn frame", regs, frame, 0);
 153        return 0;
 154}
 155
 156/*
 157 * Determine which stack to use..
 158 */
 159static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
 160                                               struct pt_regs *regs,
 161                                               size_t frame_size)
 162{
 163        unsigned long sp;
 164
 165        /* Default to using normal stack */
 166        sp = (unsigned long)compat_ptr(regs->sp);
 167
 168        /*
 169         * If we are on the alternate signal stack and would overflow
 170         * it, don't.  Return an always-bogus address instead so we
 171         * will die with SIGSEGV.
 172         */
 173        if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
 174                return (void __user __force *)-1UL;
 175
 176        /* This is the X/Open sanctioned signal stack switching.  */
 177        if (ka->sa.sa_flags & SA_ONSTACK) {
 178                if (sas_ss_flags(sp) == 0)
 179                        sp = current->sas_ss_sp + current->sas_ss_size;
 180        }
 181
 182        sp -= frame_size;
 183        /*
 184         * Align the stack pointer according to the TILE ABI,
 185         * i.e. so that on function entry (sp & 15) == 0.
 186         */
 187        sp &= -16UL;
 188        return (void __user *) sp;
 189}
 190
 191int compat_setup_rt_frame(struct ksignal *ksig, sigset_t *set,
 192                          struct pt_regs *regs)
 193{
 194        unsigned long restorer;
 195        struct compat_rt_sigframe __user *frame;
 196        int err = 0, sig = ksig->sig;
 197
 198        frame = compat_get_sigframe(&ksig->ka, regs, sizeof(*frame));
 199
 200        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 201                goto err;
 202
 203        /* Always write at least the signal number for the stack backtracer. */
 204        if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
 205                /* At sigreturn time, restore the callee-save registers too. */
 206                err |= copy_siginfo_to_user32(&frame->info, &ksig->info);
 207                regs->flags |= PT_FLAGS_RESTORE_REGS;
 208        } else {
 209                err |= __put_user(ksig->info.si_signo, &frame->info.si_signo);
 210        }
 211
 212        /* Create the ucontext.  */
 213        err |= __clear_user(&frame->save_area, sizeof(frame->save_area));
 214        err |= __put_user(0, &frame->uc.uc_flags);
 215        err |= __put_user(0, &frame->uc.uc_link);
 216        err |= __compat_save_altstack(&frame->uc.uc_stack, regs->sp);
 217        err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
 218        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 219        if (err)
 220                goto err;
 221
 222        restorer = VDSO_SYM(&__vdso_rt_sigreturn);
 223        if (ksig->ka.sa.sa_flags & SA_RESTORER)
 224                restorer = ptr_to_compat_reg(ksig->ka.sa.sa_restorer);
 225
 226        /*
 227         * Set up registers for signal handler.
 228         * Registers that we don't modify keep the value they had from
 229         * user-space at the time we took the signal.
 230         * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
 231         * since some things rely on this (e.g. glibc's debug/segfault.c).
 232         */
 233        regs->pc = ptr_to_compat_reg(ksig->ka.sa.sa_handler);
 234        regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
 235        regs->sp = ptr_to_compat_reg(frame);
 236        regs->lr = restorer;
 237        regs->regs[0] = (unsigned long) sig;
 238        regs->regs[1] = ptr_to_compat_reg(&frame->info);
 239        regs->regs[2] = ptr_to_compat_reg(&frame->uc);
 240        regs->flags |= PT_FLAGS_CALLER_SAVES;
 241        return 0;
 242
 243err:
 244        trace_unhandled_signal("bad sigreturn frame", regs,
 245                              (unsigned long)frame, SIGSEGV);
 246        return -EFAULT;
 247}
 248