2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 1991, 1992 Linus Torvalds
7 * Copyright (C) 1994 - 2000, 2006 Ralf Baechle
8 * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9 * Copyright (C) 2016, Imagination Technologies Ltd.
11 #include <linux/compiler.h>
12 #include <linux/errno.h>
13 #include <linux/kernel.h>
14 #include <linux/signal.h>
15 #include <linux/syscalls.h>
17 #include <asm/compat.h>
18 #include <asm/compat-signal.h>
19 #include <asm/uaccess.h>
20 #include <asm/unistd.h>
22 #include "signal-common.h"
24 /* 32-bit compatibility types */
26 typedef unsigned int __sighandler32_t
;
27 typedef void (*vfptr_t
)(void);
30 * Atomically swap in the new signal mask, and wait for a signal.
33 asmlinkage
int sys32_sigsuspend(compat_sigset_t __user
*uset
)
35 return compat_sys_rt_sigsuspend(uset
, sizeof(compat_sigset_t
));
38 SYSCALL_DEFINE3(32_sigaction
, long, sig
, const struct compat_sigaction __user
*, act
,
39 struct compat_sigaction __user
*, oact
)
41 struct k_sigaction new_ka
, old_ka
;
49 if (!access_ok(VERIFY_READ
, act
, sizeof(*act
)))
51 err
|= __get_user(handler
, &act
->sa_handler
);
52 new_ka
.sa
.sa_handler
= (void __user
*)(s64
)handler
;
53 err
|= __get_user(new_ka
.sa
.sa_flags
, &act
->sa_flags
);
54 err
|= __get_user(mask
, &act
->sa_mask
.sig
[0]);
58 siginitset(&new_ka
.sa
.sa_mask
, mask
);
61 ret
= do_sigaction(sig
, act
? &new_ka
: NULL
, oact
? &old_ka
: NULL
);
64 if (!access_ok(VERIFY_WRITE
, oact
, sizeof(*oact
)))
66 err
|= __put_user(old_ka
.sa
.sa_flags
, &oact
->sa_flags
);
67 err
|= __put_user((u32
)(u64
)old_ka
.sa
.sa_handler
,
69 err
|= __put_user(old_ka
.sa
.sa_mask
.sig
[0], oact
->sa_mask
.sig
);
70 err
|= __put_user(0, &oact
->sa_mask
.sig
[1]);
71 err
|= __put_user(0, &oact
->sa_mask
.sig
[2]);
72 err
|= __put_user(0, &oact
->sa_mask
.sig
[3]);
80 int copy_siginfo_to_user32(compat_siginfo_t __user
*to
, const siginfo_t
*from
)
84 if (!access_ok (VERIFY_WRITE
, to
, sizeof(compat_siginfo_t
)))
87 /* If you change siginfo_t structure, please be sure
88 this code is fixed accordingly.
89 It should never copy any pad contained in the structure
90 to avoid security leaks, but must copy the generic
91 3 ints plus the relevant union member.
92 This routine must convert siginfo from 64bit to 32bit as well
94 err
= __put_user(from
->si_signo
, &to
->si_signo
);
95 err
|= __put_user(from
->si_errno
, &to
->si_errno
);
96 err
|= __put_user((short)from
->si_code
, &to
->si_code
);
97 if (from
->si_code
< 0)
98 err
|= __copy_to_user(&to
->_sifields
._pad
, &from
->_sifields
._pad
, SI_PAD_SIZE
);
100 switch (from
->si_code
>> 16) {
101 case __SI_TIMER
>> 16:
102 err
|= __put_user(from
->si_tid
, &to
->si_tid
);
103 err
|= __put_user(from
->si_overrun
, &to
->si_overrun
);
104 err
|= __put_user(from
->si_int
, &to
->si_int
);
106 case __SI_CHLD
>> 16:
107 err
|= __put_user(from
->si_utime
, &to
->si_utime
);
108 err
|= __put_user(from
->si_stime
, &to
->si_stime
);
109 err
|= __put_user(from
->si_status
, &to
->si_status
);
111 err
|= __put_user(from
->si_pid
, &to
->si_pid
);
112 err
|= __put_user(from
->si_uid
, &to
->si_uid
);
114 case __SI_FAULT
>> 16:
115 err
|= __put_user((unsigned long)from
->si_addr
, &to
->si_addr
);
117 case __SI_POLL
>> 16:
118 err
|= __put_user(from
->si_band
, &to
->si_band
);
119 err
|= __put_user(from
->si_fd
, &to
->si_fd
);
121 case __SI_RT
>> 16: /* This is not generated by the kernel as of now. */
122 case __SI_MESGQ
>> 16:
123 err
|= __put_user(from
->si_pid
, &to
->si_pid
);
124 err
|= __put_user(from
->si_uid
, &to
->si_uid
);
125 err
|= __put_user(from
->si_int
, &to
->si_int
);
128 err
|= __copy_to_user(&to
->si_call_addr
, &from
->si_call_addr
,
129 sizeof(compat_uptr_t
));
130 err
|= __put_user(from
->si_syscall
, &to
->si_syscall
);
131 err
|= __put_user(from
->si_arch
, &to
->si_arch
);
138 int copy_siginfo_from_user32(siginfo_t
*to
, compat_siginfo_t __user
*from
)
140 if (copy_from_user(to
, from
, 3*sizeof(int)) ||
141 copy_from_user(to
->_sifields
._pad
,
142 from
->_sifields
._pad
, SI_PAD_SIZE32
))