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
 121long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
 122                             struct compat_sigaction __user *oact,
 123                             size_t sigsetsize)
 124{
 125        struct k_sigaction new_sa, old_sa;
 126        int ret = -EINVAL;
 127
 128        /* XXX: Don't preclude handling different sized sigset_t's.  */
 129        if (sigsetsize != sizeof(sigset_t))
 130                goto out;
 131
 132        if (act) {
 133                compat_uptr_t handler, restorer;
 134
 135                if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
 136                    __get_user(handler, &act->sa_handler) ||
 137                    __get_user(new_sa.sa.sa_flags, &act->sa_flags) ||
 138                    __get_user(restorer, &act->sa_restorer) ||
 139                    __copy_from_user(&new_sa.sa.sa_mask, &act->sa_mask,
 140                                     sizeof(sigset_t)))
 141                        return -EFAULT;
 142                new_sa.sa.sa_handler = compat_ptr(handler);
 143                new_sa.sa.sa_restorer = compat_ptr(restorer);
 144        }
 145
 146        ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
 147
 148        if (!ret && oact) {
 149                if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
 150                    __put_user(ptr_to_compat(old_sa.sa.sa_handler),
 151                               &oact->sa_handler) ||
 152                    __put_user(ptr_to_compat(old_sa.sa.sa_restorer),
 153                               &oact->sa_restorer) ||
 154                    __put_user(old_sa.sa.sa_flags, &oact->sa_flags) ||
 155                    __copy_to_user(&oact->sa_mask, &old_sa.sa.sa_mask,
 156                                   sizeof(sigset_t)))
 157                        return -EFAULT;
 158        }
 159out:
 160        return ret;
 161}
 162
 163long compat_sys_rt_sigqueueinfo(int pid, int sig,
 164                                struct compat_siginfo __user *uinfo)
 165{
 166        siginfo_t info;
 167        int ret;
 168        mm_segment_t old_fs = get_fs();
 169
 170        if (copy_siginfo_from_user32(&info, uinfo))
 171                return -EFAULT;
 172        set_fs(KERNEL_DS);
 173        ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __force __user *)&info);
 174        set_fs(old_fs);
 175        return ret;
 176}
 177
 178int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from)
 179{
 180        int err;
 181
 182        if (!access_ok(VERIFY_WRITE, to, sizeof(struct compat_siginfo)))
 183                return -EFAULT;
 184
 185        /* If you change siginfo_t structure, please make sure that
 186           this code is fixed accordingly.
 187           It should never copy any pad contained in the structure
 188           to avoid security leaks, but must copy the generic
 189           3 ints plus the relevant union member.  */
 190        err = __put_user(from->si_signo, &to->si_signo);
 191        err |= __put_user(from->si_errno, &to->si_errno);
 192        err |= __put_user((short)from->si_code, &to->si_code);
 193
 194        if (from->si_code < 0) {
 195                err |= __put_user(from->si_pid, &to->si_pid);
 196                err |= __put_user(from->si_uid, &to->si_uid);
 197                err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
 198        } else {
 199                /*
 200                 * First 32bits of unions are always present:
 201                 * si_pid === si_band === si_tid === si_addr(LS half)
 202                 */
 203                err |= __put_user(from->_sifields._pad[0],
 204                                  &to->_sifields._pad[0]);
 205                switch (from->si_code >> 16) {
 206                case __SI_FAULT >> 16:
 207                        break;
 208                case __SI_CHLD >> 16:
 209                        err |= __put_user(from->si_utime, &to->si_utime);
 210                        err |= __put_user(from->si_stime, &to->si_stime);
 211                        err |= __put_user(from->si_status, &to->si_status);
 212                        /* FALL THROUGH */
 213                default:
 214                case __SI_KILL >> 16:
 215                        err |= __put_user(from->si_uid, &to->si_uid);
 216                        break;
 217                case __SI_POLL >> 16:
 218                        err |= __put_user(from->si_fd, &to->si_fd);
 219                        break;
 220                case __SI_TIMER >> 16:
 221                        err |= __put_user(from->si_overrun, &to->si_overrun);
 222                        err |= __put_user(ptr_to_compat(from->si_ptr),
 223                                          &to->si_ptr);
 224                        break;
 225                         /* This is not generated by the kernel as of now.  */
 226                case __SI_RT >> 16:
 227                case __SI_MESGQ >> 16:
 228                        err |= __put_user(from->si_uid, &to->si_uid);
 229                        err |= __put_user(from->si_int, &to->si_int);
 230                        break;
 231                }
 232        }
 233        return err;
 234}
 235
 236int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
 237{
 238        int err;
 239        u32 ptr32;
 240
 241        if (!access_ok(VERIFY_READ, from, sizeof(struct compat_siginfo)))
 242                return -EFAULT;
 243
 244        err = __get_user(to->si_signo, &from->si_signo);
 245        err |= __get_user(to->si_errno, &from->si_errno);
 246        err |= __get_user(to->si_code, &from->si_code);
 247
 248        err |= __get_user(to->si_pid, &from->si_pid);
 249        err |= __get_user(to->si_uid, &from->si_uid);
 250        err |= __get_user(ptr32, &from->si_ptr);
 251        to->si_ptr = compat_ptr(ptr32);
 252
 253        return err;
 254}
 255
 256long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
 257                            struct compat_sigaltstack __user *uoss_ptr,
 258                            struct pt_regs *regs)
 259{
 260        stack_t uss, uoss;
 261        int ret;
 262        mm_segment_t seg;
 263
 264        if (uss_ptr) {
 265                u32 ptr;
 266
 267                memset(&uss, 0, sizeof(stack_t));
 268                if (!access_ok(VERIFY_READ, uss_ptr, sizeof(*uss_ptr)) ||
 269                            __get_user(ptr, &uss_ptr->ss_sp) ||
 270                            __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
 271                            __get_user(uss.ss_size, &uss_ptr->ss_size))
 272                        return -EFAULT;
 273                uss.ss_sp = compat_ptr(ptr);
 274        }
 275        seg = get_fs();
 276        set_fs(KERNEL_DS);
 277        ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL,
 278                             (stack_t __user __force *)&uoss,
 279                             (unsigned long)compat_ptr(regs->sp));
 280        set_fs(seg);
 281        if (ret >= 0 && uoss_ptr)  {
 282                if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) ||
 283                    __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
 284                    __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
 285                    __put_user(uoss.ss_size, &uoss_ptr->ss_size))
 286                        ret = -EFAULT;
 287        }
 288        return ret;
 289}
 290
 291/* The assembly shim for this function arranges to ignore the return value. */
 292long compat_sys_rt_sigreturn(struct pt_regs *regs)
 293{
 294        struct compat_rt_sigframe __user *frame =
 295                (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
 296        sigset_t set;
 297
 298        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
 299                goto badframe;
 300        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
 301                goto badframe;
 302
 303        set_current_blocked(&set);
 304
 305        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
 306                goto badframe;
 307
 308        if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
 309                goto badframe;
 310
 311        return 0;
 312
 313badframe:
 314        signal_fault("bad sigreturn frame", regs, frame, 0);
 315        return 0;
 316}
 317
 318/*
 319 * Determine which stack to use..
 320 */
 321static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
 322                                               struct pt_regs *regs,
 323                                               size_t frame_size)
 324{
 325        unsigned long sp;
 326
 327        /* Default to using normal stack */
 328        sp = (unsigned long)compat_ptr(regs->sp);
 329
 330        /*
 331         * If we are on the alternate signal stack and would overflow
 332         * it, don't.  Return an always-bogus address instead so we
 333         * will die with SIGSEGV.
 334         */
 335        if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
 336                return (void __user __force *)-1UL;
 337
 338        /* This is the X/Open sanctioned signal stack switching.  */
 339        if (ka->sa.sa_flags & SA_ONSTACK) {
 340                if (sas_ss_flags(sp) == 0)
 341                        sp = current->sas_ss_sp + current->sas_ss_size;
 342        }
 343
 344        sp -= frame_size;
 345        /*
 346         * Align the stack pointer according to the TILE ABI,
 347         * i.e. so that on function entry (sp & 15) == 0.
 348         */
 349        sp &= -16UL;
 350        return (void __user *) sp;
 351}
 352
 353int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 354                          sigset_t *set, struct pt_regs *regs)
 355{
 356        unsigned long restorer;
 357        struct compat_rt_sigframe __user *frame;
 358        int err = 0;
 359        int usig;
 360
 361        frame = compat_get_sigframe(ka, regs, sizeof(*frame));
 362
 363        if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 364                goto give_sigsegv;
 365
 366        usig = current_thread_info()->exec_domain
 367                && current_thread_info()->exec_domain->signal_invmap
 368                && sig < 32
 369                ? current_thread_info()->exec_domain->signal_invmap[sig]
 370                : sig;
 371
 372        /* Always write at least the signal number for the stack backtracer. */
 373        if (ka->sa.sa_flags & SA_SIGINFO) {
 374                /* At sigreturn time, restore the callee-save registers too. */
 375                err |= copy_siginfo_to_user32(&frame->info, info);
 376                regs->flags |= PT_FLAGS_RESTORE_REGS;
 377        } else {
 378                err |= __put_user(info->si_signo, &frame->info.si_signo);
 379        }
 380
 381        /* Create the ucontext.  */
 382        err |= __clear_user(&frame->save_area, sizeof(frame->save_area));
 383        err |= __put_user(0, &frame->uc.uc_flags);
 384        err |= __put_user(0, &frame->uc.uc_link);
 385        err |= __put_user(ptr_to_compat((void *)(current->sas_ss_sp)),
 386                          &frame->uc.uc_stack.ss_sp);
 387        err |= __put_user(sas_ss_flags(regs->sp),
 388                          &frame->uc.uc_stack.ss_flags);
 389        err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
 390        err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
 391        err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 392        if (err)
 393                goto give_sigsegv;
 394
 395        restorer = VDSO_BASE;
 396        if (ka->sa.sa_flags & SA_RESTORER)
 397                restorer = ptr_to_compat_reg(ka->sa.sa_restorer);
 398
 399        /*
 400         * Set up registers for signal handler.
 401         * Registers that we don't modify keep the value they had from
 402         * user-space at the time we took the signal.
 403         * We always pass siginfo and mcontext, regardless of SA_SIGINFO,
 404         * since some things rely on this (e.g. glibc's debug/segfault.c).
 405         */
 406        regs->pc = ptr_to_compat_reg(ka->sa.sa_handler);
 407        regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
 408        regs->sp = ptr_to_compat_reg(frame);
 409        regs->lr = restorer;
 410        regs->regs[0] = (unsigned long) usig;
 411        regs->regs[1] = ptr_to_compat_reg(&frame->info);
 412        regs->regs[2] = ptr_to_compat_reg(&frame->uc);
 413        regs->flags |= PT_FLAGS_CALLER_SAVES;
 414
 415        /*
 416         * Notify any tracer that was single-stepping it.
 417         * The tracer may want to single-step inside the
 418         * handler too.
 419         */
 420        if (test_thread_flag(TIF_SINGLESTEP))
 421                ptrace_notify(SIGTRAP);
 422
 423        return 0;
 424
 425give_sigsegv:
 426        signal_fault("bad setup frame", regs, frame, sig);
 427        return -EFAULT;
 428}
 429