static int restore_signals(siginfo_t *ptr, int nr, bool group) { int ret, i; k_rtsigset_t to_block; ksigfillset(&to_block); ret = sys_sigprocmask(SIG_SETMASK, &to_block, NULL, sizeof(k_rtsigset_t)); if (ret) { pr_err("Unable to block signals %d", ret); return -1; } for (i = 0; i < nr; i++) { siginfo_t *info = ptr + i; pr_info("Restore signal %d group %d\n", info->si_signo, group); if (group) ret = sys_rt_sigqueueinfo(sys_getpid(), info->si_signo, info); else ret = sys_rt_tgsigqueueinfo(sys_getpid(), sys_gettid(), info->si_signo, info); if (ret) { pr_err("Unable to send siginfo %d %x with code %d\n", info->si_signo, info->si_code, ret); return -1;; } } return 0; }
asmlinkage int sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) { siginfo_t info; int ret; mm_segment_t old_fs = get_fs(); if (copy_from_user (&info, uinfo, 3*sizeof(int)) || copy_from_user (info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE)) return -EFAULT; set_fs (KERNEL_DS); ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info); set_fs (old_fs); return ret; }
long compat_sys_rt_sigqueueinfo(int pid, int sig, struct compat_siginfo __user *uinfo) { siginfo_t info; int ret; mm_segment_t old_fs = get_fs(); if (copy_siginfo_from_user32(&info, uinfo)) return -EFAULT; set_fs(KERNEL_DS); ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __force __user *)&info); set_fs(old_fs); return ret; }
static int restore_signals(siginfo_t *ptr, int nr, bool group) { int ret, i; for (i = 0; i < nr; i++) { siginfo_t *info = ptr + i; pr_info("Restore signal %d group %d\n", info->si_signo, group); if (group) ret = sys_rt_sigqueueinfo(sys_getpid(), info->si_signo, info); else ret = sys_rt_tgsigqueueinfo(sys_getpid(), sys_gettid(), info->si_signo, info); if (ret) { pr_err("Unable to send siginfo %d %x with code %d\n", info->si_signo, info->si_code, ret); return -1;; } } return 0; }
static int check_sigqueuinfo() { int ret; siginfo_t info = { .si_code = 1 }; signal(SIGUSR1, SIG_IGN); ret = sys_rt_sigqueueinfo(getpid(), SIGUSR1, &info); if (ret < 0) { errno = -ret; pr_perror("Unable to send siginfo with positive si_code to itself"); return -1; } return 0; } static pid_t fork_and_ptrace_attach(int (*child_setup)(void)) { pid_t pid; int sk_pair[2], sk; char c = 0; if (socketpair(PF_LOCAL, SOCK_SEQPACKET, 0, sk_pair)) { pr_perror("socketpair"); return -1; } pid = fork(); if (pid < 0) { pr_perror("fork"); return -1; } else if (pid == 0) { sk = sk_pair[1]; close(sk_pair[0]); if (child_setup && child_setup() != 0) exit(1); if (write(sk, &c, 1) != 1) { pr_perror("write"); exit(1); } while (1) sleep(1000); exit(1); } sk = sk_pair[0]; close(sk_pair[1]); if (read(sk, &c, 1) != 1) { close(sk); kill(pid, SIGKILL); pr_perror("read"); return -1; } close(sk); if (ptrace(PTRACE_ATTACH, pid, NULL, NULL) == -1) { pr_perror("Unable to ptrace the child"); kill(pid, SIGKILL); return -1; } waitpid(pid, NULL, 0); return pid; }