aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2018-10-05 03:02:48 -0400
committerEric W. Biederman <ebiederm@xmission.com>2018-10-08 03:35:26 -0400
commit601d5abfeaf244b86bb68c1e05c6e0d57be2f6b0 (patch)
treeebadc93b46b98afd8bba2e0bf759657d06ce5e93
parent4ce5f9c9e7546915c559ffae594e6d73f918db00 (diff)
signal: In sigqueueinfo prefer sig not si_signo
Andrei Vagin <avagin@gmail.com> reported: > Accoding to the man page, the user should not set si_signo, it has to be set > by kernel. > > $ man 2 rt_sigqueueinfo > > The uinfo argument specifies the data to accompany the signal. This > argument is a pointer to a structure of type siginfo_t, described in > sigaction(2) (and defined by including <sigaction.h>). The caller > should set the following fields in this structure: > > si_code > This must be one of the SI_* codes in the Linux kernel source > file include/asm-generic/siginfo.h, with the restriction that > the code must be negative (i.e., cannot be SI_USER, which is > used by the kernel to indicate a signal sent by kill(2)) and > cannot (since Linux 2.6.39) be SI_TKILL (which is used by the > kernel to indicate a signal sent using tgkill(2)). > > si_pid This should be set to a process ID, typically the process ID of > the sender. > > si_uid This should be set to a user ID, typically the real user ID of > the sender. > > si_value > This field contains the user data to accompany the signal. For > more information, see the description of the last (union sigval) > argument of sigqueue(3). > > Internally, the kernel sets the si_signo field to the value specified > in sig, so that the receiver of the signal can also obtain the signal > number via that field. > > On Tue, Sep 25, 2018 at 07:19:02PM +0200, Eric W. Biederman wrote: >> >> If there is some application that calls sigqueueinfo directly that has >> a problem with this added sanity check we can revisit this when we see >> what kind of crazy that application is doing. > > > I already know two "applications" ;) > > https://github.com/torvalds/linux/blob/master/tools/testing/selftests/ptrace/peeksiginfo.c > https://github.com/checkpoint-restore/criu/blob/master/test/zdtm/static/sigpending.c > > Disclaimer: I'm the author of both of them. Looking at the kernel code the historical behavior has alwasy been to prefer the signal number passed in by the kernel. So sigh. Implmenet __copy_siginfo_from_user and __copy_siginfo_from_user32 to take that signal number and prefer it. The user of ptrace will still use copy_siginfo_from_user and copy_siginfo_from_user32 as they do not and never have had a signal number there. Luckily this change has never made it farther than linux-next. Fixes: e75dc036c445 ("signal: Fail sigqueueinfo if si_signo != sig") Reported-by: Andrei Vagin <avagin@gmail.com> Tested-by: Andrei Vagin <avagin@gmail.com> Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
-rw-r--r--kernel/signal.c141
1 files changed, 84 insertions, 57 deletions
diff --git a/kernel/signal.c b/kernel/signal.c
index 1c2dd117fee0..2bffc5a50183 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2925,11 +2925,10 @@ int copy_siginfo_to_user(siginfo_t __user *to, const kernel_siginfo_t *from)
2925 return 0; 2925 return 0;
2926} 2926}
2927 2927
2928int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from) 2928static int post_copy_siginfo_from_user(kernel_siginfo_t *info,
2929 const siginfo_t __user *from)
2929{ 2930{
2930 if (copy_from_user(to, from, sizeof(struct kernel_siginfo))) 2931 if (unlikely(!known_siginfo_layout(info->si_signo, info->si_code))) {
2931 return -EFAULT;
2932 if (unlikely(!known_siginfo_layout(to->si_signo, to->si_code))) {
2933 char __user *expansion = si_expansion(from); 2932 char __user *expansion = si_expansion(from);
2934 char buf[SI_EXPANSION_SIZE]; 2933 char buf[SI_EXPANSION_SIZE];
2935 int i; 2934 int i;
@@ -2949,6 +2948,22 @@ int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
2949 return 0; 2948 return 0;
2950} 2949}
2951 2950
2951static int __copy_siginfo_from_user(int signo, kernel_siginfo_t *to,
2952 const siginfo_t __user *from)
2953{
2954 if (copy_from_user(to, from, sizeof(struct kernel_siginfo)))
2955 return -EFAULT;
2956 to->si_signo = signo;
2957 return post_copy_siginfo_from_user(to, from);
2958}
2959
2960int copy_siginfo_from_user(kernel_siginfo_t *to, const siginfo_t __user *from)
2961{
2962 if (copy_from_user(to, from, sizeof(struct kernel_siginfo)))
2963 return -EFAULT;
2964 return post_copy_siginfo_from_user(to, from);
2965}
2966
2952#ifdef CONFIG_COMPAT 2967#ifdef CONFIG_COMPAT
2953int copy_siginfo_to_user32(struct compat_siginfo __user *to, 2968int copy_siginfo_to_user32(struct compat_siginfo __user *to,
2954 const struct kernel_siginfo *from) 2969 const struct kernel_siginfo *from)
@@ -3041,88 +3056,106 @@ int __copy_siginfo_to_user32(struct compat_siginfo __user *to,
3041 return 0; 3056 return 0;
3042} 3057}
3043 3058
3044int copy_siginfo_from_user32(struct kernel_siginfo *to, 3059static int post_copy_siginfo_from_user32(kernel_siginfo_t *to,
3045 const struct compat_siginfo __user *ufrom) 3060 const struct compat_siginfo *from)
3046{ 3061{
3047 struct compat_siginfo from;
3048
3049 if (copy_from_user(&from, ufrom, sizeof(struct compat_siginfo)))
3050 return -EFAULT;
3051
3052 clear_siginfo(to); 3062 clear_siginfo(to);
3053 to->si_signo = from.si_signo; 3063 to->si_signo = from->si_signo;
3054 to->si_errno = from.si_errno; 3064 to->si_errno = from->si_errno;
3055 to->si_code = from.si_code; 3065 to->si_code = from->si_code;
3056 switch(siginfo_layout(from.si_signo, from.si_code)) { 3066 switch(siginfo_layout(from->si_signo, from->si_code)) {
3057 case SIL_KILL: 3067 case SIL_KILL:
3058 to->si_pid = from.si_pid; 3068 to->si_pid = from->si_pid;
3059 to->si_uid = from.si_uid; 3069 to->si_uid = from->si_uid;
3060 break; 3070 break;
3061 case SIL_TIMER: 3071 case SIL_TIMER:
3062 to->si_tid = from.si_tid; 3072 to->si_tid = from->si_tid;
3063 to->si_overrun = from.si_overrun; 3073 to->si_overrun = from->si_overrun;
3064 to->si_int = from.si_int; 3074 to->si_int = from->si_int;
3065 break; 3075 break;
3066 case SIL_POLL: 3076 case SIL_POLL:
3067 to->si_band = from.si_band; 3077 to->si_band = from->si_band;
3068 to->si_fd = from.si_fd; 3078 to->si_fd = from->si_fd;
3069 break; 3079 break;
3070 case SIL_FAULT: 3080 case SIL_FAULT:
3071 to->si_addr = compat_ptr(from.si_addr); 3081 to->si_addr = compat_ptr(from->si_addr);
3072#ifdef __ARCH_SI_TRAPNO 3082#ifdef __ARCH_SI_TRAPNO
3073 to->si_trapno = from.si_trapno; 3083 to->si_trapno = from->si_trapno;
3074#endif 3084#endif
3075 break; 3085 break;
3076 case SIL_FAULT_MCEERR: 3086 case SIL_FAULT_MCEERR:
3077 to->si_addr = compat_ptr(from.si_addr); 3087 to->si_addr = compat_ptr(from->si_addr);
3078#ifdef __ARCH_SI_TRAPNO 3088#ifdef __ARCH_SI_TRAPNO
3079 to->si_trapno = from.si_trapno; 3089 to->si_trapno = from->si_trapno;
3080#endif 3090#endif
3081 to->si_addr_lsb = from.si_addr_lsb; 3091 to->si_addr_lsb = from->si_addr_lsb;
3082 break; 3092 break;
3083 case SIL_FAULT_BNDERR: 3093 case SIL_FAULT_BNDERR:
3084 to->si_addr = compat_ptr(from.si_addr); 3094 to->si_addr = compat_ptr(from->si_addr);
3085#ifdef __ARCH_SI_TRAPNO 3095#ifdef __ARCH_SI_TRAPNO
3086 to->si_trapno = from.si_trapno; 3096 to->si_trapno = from->si_trapno;
3087#endif 3097#endif
3088 to->si_lower = compat_ptr(from.si_lower); 3098 to->si_lower = compat_ptr(from->si_lower);
3089 to->si_upper = compat_ptr(from.si_upper); 3099 to->si_upper = compat_ptr(from->si_upper);
3090 break; 3100 break;
3091 case SIL_FAULT_PKUERR: 3101 case SIL_FAULT_PKUERR:
3092 to->si_addr = compat_ptr(from.si_addr); 3102 to->si_addr = compat_ptr(from->si_addr);
3093#ifdef __ARCH_SI_TRAPNO 3103#ifdef __ARCH_SI_TRAPNO
3094 to->si_trapno = from.si_trapno; 3104 to->si_trapno = from->si_trapno;
3095#endif 3105#endif
3096 to->si_pkey = from.si_pkey; 3106 to->si_pkey = from->si_pkey;
3097 break; 3107 break;
3098 case SIL_CHLD: 3108 case SIL_CHLD:
3099 to->si_pid = from.si_pid; 3109 to->si_pid = from->si_pid;
3100 to->si_uid = from.si_uid; 3110 to->si_uid = from->si_uid;
3101 to->si_status = from.si_status; 3111 to->si_status = from->si_status;
3102#ifdef CONFIG_X86_X32_ABI 3112#ifdef CONFIG_X86_X32_ABI
3103 if (in_x32_syscall()) { 3113 if (in_x32_syscall()) {
3104 to->si_utime = from._sifields._sigchld_x32._utime; 3114 to->si_utime = from->_sifields._sigchld_x32._utime;
3105 to->si_stime = from._sifields._sigchld_x32._stime; 3115 to->si_stime = from->_sifields._sigchld_x32._stime;
3106 } else 3116 } else
3107#endif 3117#endif
3108 { 3118 {
3109 to->si_utime = from.si_utime; 3119 to->si_utime = from->si_utime;
3110 to->si_stime = from.si_stime; 3120 to->si_stime = from->si_stime;
3111 } 3121 }
3112 break; 3122 break;
3113 case SIL_RT: 3123 case SIL_RT:
3114 to->si_pid = from.si_pid; 3124 to->si_pid = from->si_pid;
3115 to->si_uid = from.si_uid; 3125 to->si_uid = from->si_uid;
3116 to->si_int = from.si_int; 3126 to->si_int = from->si_int;
3117 break; 3127 break;
3118 case SIL_SYS: 3128 case SIL_SYS:
3119 to->si_call_addr = compat_ptr(from.si_call_addr); 3129 to->si_call_addr = compat_ptr(from->si_call_addr);
3120 to->si_syscall = from.si_syscall; 3130 to->si_syscall = from->si_syscall;
3121 to->si_arch = from.si_arch; 3131 to->si_arch = from->si_arch;
3122 break; 3132 break;
3123 } 3133 }
3124 return 0; 3134 return 0;
3125} 3135}
3136
3137static int __copy_siginfo_from_user32(int signo, struct kernel_siginfo *to,
3138 const struct compat_siginfo __user *ufrom)
3139{
3140 struct compat_siginfo from;
3141
3142 if (copy_from_user(&from, ufrom, sizeof(struct compat_siginfo)))
3143 return -EFAULT;
3144
3145 from.si_signo = signo;
3146 return post_copy_siginfo_from_user32(to, &from);
3147}
3148
3149int copy_siginfo_from_user32(struct kernel_siginfo *to,
3150 const struct compat_siginfo __user *ufrom)
3151{
3152 struct compat_siginfo from;
3153
3154 if (copy_from_user(&from, ufrom, sizeof(struct compat_siginfo)))
3155 return -EFAULT;
3156
3157 return post_copy_siginfo_from_user32(to, &from);
3158}
3126#endif /* CONFIG_COMPAT */ 3159#endif /* CONFIG_COMPAT */
3127 3160
3128/** 3161/**
@@ -3359,9 +3392,6 @@ static int do_rt_sigqueueinfo(pid_t pid, int sig, kernel_siginfo_t *info)
3359 (task_pid_vnr(current) != pid)) 3392 (task_pid_vnr(current) != pid))
3360 return -EPERM; 3393 return -EPERM;
3361 3394
3362 if (info->si_signo != sig)
3363 return -EINVAL;
3364
3365 /* POSIX.1b doesn't mention process groups. */ 3395 /* POSIX.1b doesn't mention process groups. */
3366 return kill_proc_info(sig, info, pid); 3396 return kill_proc_info(sig, info, pid);
3367} 3397}
@@ -3376,7 +3406,7 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig,
3376 siginfo_t __user *, uinfo) 3406 siginfo_t __user *, uinfo)
3377{ 3407{
3378 kernel_siginfo_t info; 3408 kernel_siginfo_t info;
3379 int ret = copy_siginfo_from_user(&info, uinfo); 3409 int ret = __copy_siginfo_from_user(sig, &info, uinfo);
3380 if (unlikely(ret)) 3410 if (unlikely(ret))
3381 return ret; 3411 return ret;
3382 return do_rt_sigqueueinfo(pid, sig, &info); 3412 return do_rt_sigqueueinfo(pid, sig, &info);
@@ -3389,7 +3419,7 @@ COMPAT_SYSCALL_DEFINE3(rt_sigqueueinfo,
3389 struct compat_siginfo __user *, uinfo) 3419 struct compat_siginfo __user *, uinfo)
3390{ 3420{
3391 kernel_siginfo_t info; 3421 kernel_siginfo_t info;
3392 int ret = copy_siginfo_from_user32(&info, uinfo); 3422 int ret = __copy_siginfo_from_user32(sig, &info, uinfo);
3393 if (unlikely(ret)) 3423 if (unlikely(ret))
3394 return ret; 3424 return ret;
3395 return do_rt_sigqueueinfo(pid, sig, &info); 3425 return do_rt_sigqueueinfo(pid, sig, &info);
@@ -3409,9 +3439,6 @@ static int do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, kernel_siginfo_t
3409 (task_pid_vnr(current) != pid)) 3439 (task_pid_vnr(current) != pid))
3410 return -EPERM; 3440 return -EPERM;
3411 3441
3412 if (info->si_signo != sig)
3413 return -EINVAL;
3414
3415 return do_send_specific(tgid, pid, sig, info); 3442 return do_send_specific(tgid, pid, sig, info);
3416} 3443}
3417 3444
@@ -3419,7 +3446,7 @@ SYSCALL_DEFINE4(rt_tgsigqueueinfo, pid_t, tgid, pid_t, pid, int, sig,
3419 siginfo_t __user *, uinfo) 3446 siginfo_t __user *, uinfo)
3420{ 3447{
3421 kernel_siginfo_t info; 3448 kernel_siginfo_t info;
3422 int ret = copy_siginfo_from_user(&info, uinfo); 3449 int ret = __copy_siginfo_from_user(sig, &info, uinfo);
3423 if (unlikely(ret)) 3450 if (unlikely(ret))
3424 return ret; 3451 return ret;
3425 return do_rt_tgsigqueueinfo(tgid, pid, sig, &info); 3452 return do_rt_tgsigqueueinfo(tgid, pid, sig, &info);
@@ -3433,7 +3460,7 @@ COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo,
3433 struct compat_siginfo __user *, uinfo) 3460 struct compat_siginfo __user *, uinfo)
3434{ 3461{
3435 kernel_siginfo_t info; 3462 kernel_siginfo_t info;
3436 int ret = copy_siginfo_from_user32(&info, uinfo); 3463 int ret = __copy_siginfo_from_user32(sig, &info, uinfo);
3437 if (unlikely(ret)) 3464 if (unlikely(ret))
3438 return ret; 3465 return ret;
3439 return do_rt_tgsigqueueinfo(tgid, pid, sig, &info); 3466 return do_rt_tgsigqueueinfo(tgid, pid, sig, &info);