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/mm.h>
  17#include <linux/smp.h>
  18#include <linux/kernel.h>
  19#include <linux/signal.h>
  20#include <linux/errno.h>
  21#include <linux/wait.h>
  22#include <linux/unistd.h>
  23#include <linux/stddef.h>
  24#include <linux/personality.h>
  25#include <linux/suspend.h>
  26#include <linux/ptrace.h>
  27#include <linux/elf.h>
  28#include <linux/compat.h>
  29#include <linux/syscalls.h>
  30#include <linux/uaccess.h>
  31#include <asm/processor.h>
  32#include <asm/ucontext.h>
  33#include <asm/sigframe.h>
  34#include <asm/syscalls.h>
  35#include <arch/interrupts.h>
  36
  37struct compat_sigaction {
  38        compat_uptr_t sa_handler;
  39        compat_ulong_t sa_flags;
  40        compat_uptr_t sa_restorer;
  41        sigset_t sa_mask __packed;
  42};
  43
  44struct compat_sigaltstack {
  45        compat_uptr_t ss_sp;
  46        int ss_flags;
  47        compat_size_t ss_size;
  48};
  49
  50struct compat_ucontext {
  51        compat_ulong_t    uc_flags;
  52        compat_uptr_t     uc_link;
  53        struct compat_sigaltstack         uc_stack;
  54        struct sigcontext uc_mcontext;
  55        sigset_t          uc_sigmask;   /* mask last for extensibility */
  56};
  57
  58#define COMPAT_SI_PAD_SIZE      ((SI_MAX_SIZE - 3 * sizeof(int)) / sizeof(int))
  59
  60struct compat_siginfo {
  61        int si_signo;
  62        int si_errno;
  63        int si_code;
  64
  65        union {
  66                int _pad[COMPAT_SI_PAD_SIZE];
  67
  68                /* kill() */
  69                struct {
  70                        unsigned int _pid;      /* sender's pid */
  71                        unsigned int _uid;      /* sender's uid */
  72                } _kill;
  73
  74                /* POSIX.1b timers */
  75                struct {
  76                        compat_timer_t _tid;    /* timer id */
  77                        int _overrun;           /* overrun count */
  78                        compat_sigval_t _sigval;        /* same as below */
  79                        int _sys_private;       /* not to be passed to user */
  80                        int _overrun_incr;      /* amount to add to overrun */
  81                } _timer;
  82
  83                /* POSIX.1b signals */
  84                struct {
  85                        unsigned int _pid;      /* sender's pid */
  86                        unsigned int _uid;      /* sender's uid */
  87                        compat_sigval_t _sigval;
  88                } _rt;
  89
  90                /* SIGCHLD */
  91                struct {
  92                        unsigned int _pid;      /* which child */
  93                        unsigned int _uid;      /* sender's uid */
  94                        int _status;            /* exit code */
  95                        compat_clock_t _utime;
  96                        compat_clock_t _stime;
  97                } _sigchld;
  98
  99                /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
 100                struct {
 101                        unsigned int _addr;     /* faulting insn/memory ref. */
 102#ifdef __ARCH_SI_TRAPNO
 103                        int _trapno;    /* TRAP # which caused the signal */
 104#endif
 105                } _sigfault;
 106
 107                /* SIGPOLL */
 108                struct {
 109                        int _band;      /* POLL_IN, POLL_OUT, POLL_MSG */
 110                        int _fd;
 111                } _sigpoll;
 112        } _sifields;
 113};
 114
 115struct compat_rt_sigframe {
 116        unsigned char save_area[C_ABI_SAVE_AREA_SIZE]; /* caller save area */
 117        struct compat_siginfo info;
 118        struct compat_ucontext uc;
 119};
 120
 121#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 122
 123long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
 124                             struct compat_sigaction __user *oact,
 125                             size_t sigsetsize)
 126{
 127        struct k_sigaction new_sa, old_sa;
 128        int ret = -EINVAL;
 129
 130        /* XXX: Don't preclude handling different sized sigset_t's.  */
 131        if (sigsetsize != sizeof(sigset_t))
 132                goto out;
 133
 134        if (act) {
 135                compat_uptr_t handler, restorer;
 136
 137                if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
 138                    __get_user(handler, &act->sa_handler) ||
 139                    __get_user(new_sa.sa.sa_flags, &act->sa_flags) ||
 140                    __get_user(restorer, &act->sa_restorer) ||
 141                    __copy_from_user(&new_sa.sa.sa_mask, &act->sa_mask,
 142                                     sizeof(sigset_t)))
 143                        return -EFAULT;
 144                new_sa.sa.sa_handler = compat_ptr(handler);
 145                new_sa.sa.sa_restorer = compat_ptr(restorer);
 146        }
 147
 148        ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
 149
 150        if (!ret && oact) {
 151                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
 152                    __put_user(ptr_to_compat(old_sa.sa.sa_handler),
 153                               &oact->sa_handler) ||
 154                    __put_user(ptr_to_compat(old_sa.sa.sa_restorer),
 155                               &oact->sa_restorer) ||
 156                    __put_user(old_sa.sa.sa_flags, &oact->sa_flags) ||
 157                    __copy_to_user(&oact->sa_mask, &old_sa.sa.sa_mask,
 158                                   sizeof(sigset_t)))
 159                        return -EFAULT;
 160        }
 161out:
 162        return ret;
 163}
 164
 165long compat_sys_rt_sigqueueinfo(int pid, int sig,
 166                                struct compat_siginfo __user *uinfo)
 167{
 168        siginfo_t info;
 169        int ret;
 170        mm_segment_t old_fs = get_fs();
 171
 172        if (copy_siginfo_from_user32(&info, uinfo))
 173                return -EFAULT;
 174        set_fs(KERNEL_DS);
 175        ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __force __user *)&info);
 176        set_fs(old_fs);
 177        return ret;
 178}
 179
 180int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from)
 181{
 182        int err;
 183
 184        if (!access_ok(VERIFY_WRITE, to, sizeof(struct compat_siginfo)))
 185                return -EFAULT;
 186
 187        /* If you change siginfo_t structure, please make sure that
 188           this code is fixed accordingly.
 189           It should never copy any pad contained in the structure
 190           to avoid security leaks, but must copy the generic
 191           3 ints plus the relevant union member.  */
 192        err = __put_user(from->si_signo, &to->si_signo);
 193        err |= __put_user(from->si_errno, &to->si_errno);
 194        err |= __put_user((short)from->si_code, &to->si_code);
 195
 196        if (from->si_code < 0) {
 197                err |= __put_user(from->si_pid, &to->si_pid);
 198                err |= __put_user(from->si_uid, &to->si_uid);
 199                err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
 200        } else {
 201                /*
 202                 * First 32bits of unions are always present:
 203                 * si_pid === si_band === si_tid === si_addr(LS half)
 204                 */
 205                err |= __put_user(from->_sifields._pad[0],
 206                                  &to->_sifields._pad[0]);
 207                switch (from->si_code >> 16) {
 208                case __SI_FAULT >> 16:
 209                        break;
 210                case __SI_CHLD >> 16:
 211                        err |= __put_user(from->si_utime, &to->si_utime);
 212                        err |= __put_user(from->si_stime, &to->si_stime);
 213                        err |= __put_user(from->si_status, &to->si_status);
 214                        /* FALL THROUGH */
 215                default:
 216                case __SI_KILL >> 16:
 217                        err |= __put_user(from->si_uid, &to->si_uid);
 218                        break;
 219                case __SI_POLL >> 16:
 220                        err |= __put_user(from->si_fd, &to->si_fd);
 221                        break;
 222                case __SI_TIMER >> 16:
 223                        err |= __put_user(from->si_overrun, &to->si_overrun);
 224                        err |= __put_user(ptr_to_compat(from->si_ptr),
 225                                          &to->si_ptr);
 226                        break;
 227                         /* This is not generated by the kernel as of now.  */
 228                case __SI_RT >> 16:
 229                case __SI_MESGQ >> 16:
 230                        err |= __put_user(from->si_uid, &to->si_uid);
 231                        err |= __put_user(from->si_int, &to->si_int);
 232                        break;
 233                }
 234        }
 235        return err;
 236}
 237
 238int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
 239{
 240        int err;
 241        u32 ptr32;
 242
 243        if (!access_ok(VERIFY_READ, from, sizeof(struct compat_siginfo)))
 244                return -EFAULT;
 245
 246        err = __get_user(to->si_signo, &from->si_signo);
 247        err |= __get_user(to->si_errno, &from->si_errno);
 248        err |= __get_user(to->si_code, &from->si_code);
 249
 250        err |= __get_user(to->si_pid, &from->si_pid);
 251        err |= __get_user(to->si_uid, &from->si_uid);
 252        err |= __get_user(ptr32, &from->si_ptr);
 253        to->si_ptr = compat_ptr(ptr32);
 254
 255        return err;
 256}
 257
 258long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
 259                            struct compat_sigaltstack __user *uoss_ptr,
 260                            struct pt_regs *regs)
 261{
 262        stack_t uss, uoss;
 263        int ret;
 264        mm_segment_t seg;
 265
 266        if (uss_ptr) {
 267                u32 ptr;
 268
 269                memset(&uss, 0, sizeof(stack_t));
 270                if (!access_ok(VERIFY_READ, uss_ptr, sizeof(*uss_ptr)) ||
 271                            __get_user(ptr, &uss_ptr->ss_sp) ||
 272                            __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
 273                            __get_user(uss.ss_size, &uss_ptr->ss_size))
 274                        return -EFAULT;
 275                uss.ss_sp = compat_ptr(ptr);
 276        }
 277        seg = get_fs();
 278        set_fs(KERNEL_DS);
 279        ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL,
 280                             (stack_t __user __force *)&uoss,
 281                             (unsigned long)compat_ptr(regs->sp));
 282        set_fs(seg);
 283        if (ret >= 0 && uoss_ptr)  {
 284                if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) ||
 285                    __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
 286                    __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
 287                    __put_user(uoss.ss_size, &uoss_ptr->ss_size))
 288                        ret = -EFAULT;
 289        }
 290        return ret;
 291}
 292
 293/* The assembly shim for this function arranges to ignore the return value. */
 294long compat_sys_rt_sigreturn(struct pt_regs *regs)
 295{
 296        struct compat_rt_sigframe __user *frame =
 297                (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
 298        sigset_t set;
 299
 300        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 301                goto badframe;
 302        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
 303                goto badframe;
 304
 305        sigdelsetmask(&set, ~_BLOCKABLE);
 306        spin_lock_irq(&current->sighand->siglock);
 307        current->blocked = set;
 308        recalc_sigpending();
 309        spin_unlock_irq(&current->sighand->siglock);
 310
 311        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
 312                goto badframe;
 313
 314        if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
 315                goto badframe;
 316
 317        return 0;
 318
 319badframe:
 320        signal_fault("bad sigreturn frame", regs, frame, 0);
 321        return 0;
 322}
 323
 324/*
 325 * Determine which stack to use..
 326 */
 327static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
 328                                               struct pt_regs *regs,
 329                                               size_t frame_size)
 330{
 331        unsigned long sp;
 332
 333        /* Default to using normal stack */
 334        sp = (unsigned long)compat_ptr(regs->sp);
 335
 336        /*
 337         * If we are on the alternate signal stack and would overflow
 338         * it, don't.  Return an always-bogus address instead so we
 339         * will die with SIGSEGV.
 340         */
 341        if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
 342                return (void __user __force *)-1UL;
 343
 344        /* This is the X/Open sanctioned signal stack switching.  */
 345        if (ka->sa.sa_flags & SA_ONSTACK) {
 346                if (sas_ss_flags(sp) == 0)
 347                        sp = current->sas_ss_sp + current->sas_ss_size;
 348        }
 349
 350        sp -= frame_size;
 351        /*
 352         * Align the stack pointer according to the TILE ABI,
 353         * i.e. so that on function entry (sp & 15) == 0.
 354         */
 355        sp &= -16UL;
 356        return (void __user *) sp;
 357}
 358
 359int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 360                          sigset_t *set, struct pt_regs *regs)
 361{
 362        unsigned long restorer;
 363        struct compat_rt_sigframe __user *frame;
 364        int err = 0;
 365        int usig;
 366
 367        frame = compat_get_sigframe(ka, regs, sizeof(*frame));
 368
 369        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 370                goto give_sigsegv;
 371
 372        usig = current_thread_info()->exec_domain
 373                && current_thread_info()->exec_domain->signal_invmap
 374                && sig < 32
 375                ? current_thread_info()->exec_domain->signal_invmap[sig]
 376                : sig;
 377
 378        /* Always write at least the signal number for the stack backtracer. */
 379        if (ka->sa.sa_flags & SA_SIGINFO) {
 380                /* At sigreturn time, restore the callee-save registers too. */
 381                err |= copy_siginfo_to_user32(&frame->info, info);
 382                regs->flags |= PT_FLAGS_RESTORE_REGS;
 383        } else {
 384                err |= __put_user(info->si_signo, &frame->info.si_signo);
 385        }
 386
 387        /* Create the ucontext.  */
 388        err |= __clear_user(&frame->save_area, sizeof(frame->save_area));
 389        err |= __put_user(0, &frame->uc.uc_flags);
 390        err |= __put_user(0, &frame->uc.uc_link);
 391        err |= __put_user(ptr_to_compat((void *)(current->sas_ss_sp)),
 392                          &frame->uc.uc_stack.ss_sp);
 393        err |= __put_user(sas_ss_flags(regs->sp),
 394                          &frame->uc.uc_stack.ss_flags);
 395        err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
 396        err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
 397        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 398        if (err)
 399                goto give_sigsegv;
 400
 401        restorer = VDSO_BASE;
 402        if (ka->sa.sa_flags & SA_RESTORER)
 403                restorer = ptr_to_compat_reg(ka->sa.sa_restorer);
 404
 405        /*
 406         * Set up registers for signal handler.
 407         * Registers that we don't modify keep the value they had from
 408         * user-space at the time we took the signal.
 409         */
 410        regs->pc = ptr_to_compat_reg(ka->sa.sa_handler);
 411        regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
 412        regs->sp = ptr_to_compat_reg(frame);
 413        regs->lr = restorer;
 414        regs->regs[0] = (unsigned long) usig;
 415
 416        if (ka->sa.sa_flags & SA_SIGINFO) {
 417                /* Need extra arguments, so mark to restore caller-saves. */
 418                regs->regs[1] = ptr_to_compat_reg(&frame->info);
 419                regs->regs[2] = ptr_to_compat_reg(&frame->uc);
 420                regs->flags |= PT_FLAGS_CALLER_SAVES;
 421        }
 422
 423        /*
 424         * Notify any tracer that was single-stepping it.
 425         * The tracer may want to single-step inside the
 426         * handler too.
 427         */
 428        if (test_thread_flag(TIF_SINGLESTEP))
 429                ptrace_notify(SIGTRAP);
 430
 431        return 0;
 432
 433give_sigsegv:
 434        signal_fault("bad setup frame", regs, frame, sig);
 435        return -EFAULT;
 436}
 437