aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2018-04-18 18:30:19 -0400
committerEric W. Biederman <ebiederm@xmission.com>2018-10-03 10:47:15 -0400
commit4cd2e0e70af6897ca2247fa1ffb1553ca16b4903 (patch)
tree55e54fb3ca4ea687448ffaddd34e8cb4366466d7
parentf28380185193610c716a90ec9b9e696638a495ce (diff)
signal: Introduce copy_siginfo_from_user and use it's return value
In preparation for using a smaller version of siginfo in the kernel introduce copy_siginfo_from_user and use it when siginfo is copied from userspace. Make the pattern for using copy_siginfo_from_user and copy_siginfo_from_user32 to capture the return value and return that value on error. This is a necessary prerequisite for using a smaller siginfo in the kernel than the kernel exports to userspace. Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
-rw-r--r--include/linux/signal.h1
-rw-r--r--kernel/ptrace.c12
-rw-r--r--kernel/signal.c25
3 files changed, 22 insertions, 16 deletions
diff --git a/include/linux/signal.h b/include/linux/signal.h
index 3d4cd5db30a9..de94c159bfb0 100644
--- a/include/linux/signal.h
+++ b/include/linux/signal.h
@@ -22,6 +22,7 @@ static inline void clear_siginfo(struct siginfo *info)
22} 22}
23 23
24int copy_siginfo_to_user(struct siginfo __user *to, const struct siginfo *from); 24int copy_siginfo_to_user(struct siginfo __user *to, const struct siginfo *from);
25int copy_siginfo_from_user(struct siginfo *to, const struct siginfo __user *from);
25 26
26enum siginfo_layout { 27enum siginfo_layout {
27 SIL_KILL, 28 SIL_KILL,
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 45f77a1b9c97..a807ff5cc1a9 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -919,9 +919,8 @@ int ptrace_request(struct task_struct *child, long request,
919 break; 919 break;
920 920
921 case PTRACE_SETSIGINFO: 921 case PTRACE_SETSIGINFO:
922 if (copy_from_user(&siginfo, datavp, sizeof siginfo)) 922 ret = copy_siginfo_from_user(&siginfo, datavp);
923 ret = -EFAULT; 923 if (!ret)
924 else
925 ret = ptrace_setsiginfo(child, &siginfo); 924 ret = ptrace_setsiginfo(child, &siginfo);
926 break; 925 break;
927 926
@@ -1215,10 +1214,9 @@ int compat_ptrace_request(struct task_struct *child, compat_long_t request,
1215 break; 1214 break;
1216 1215
1217 case PTRACE_SETSIGINFO: 1216 case PTRACE_SETSIGINFO:
1218 if (copy_siginfo_from_user32( 1217 ret = copy_siginfo_from_user32(
1219 &siginfo, (struct compat_siginfo __user *) datap)) 1218 &siginfo, (struct compat_siginfo __user *) datap);
1220 ret = -EFAULT; 1219 if (!ret)
1221 else
1222 ret = ptrace_setsiginfo(child, &siginfo); 1220 ret = ptrace_setsiginfo(child, &siginfo);
1223 break; 1221 break;
1224#ifdef CONFIG_HAVE_ARCH_TRACEHOOK 1222#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
diff --git a/kernel/signal.c b/kernel/signal.c
index debb485a76db..c0e289e62d77 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -2896,6 +2896,13 @@ int copy_siginfo_to_user(siginfo_t __user *to, const siginfo_t *from)
2896 return 0; 2896 return 0;
2897} 2897}
2898 2898
2899int copy_siginfo_from_user(siginfo_t *to, const siginfo_t __user *from)
2900{
2901 if (copy_from_user(to, from, sizeof(struct siginfo)))
2902 return -EFAULT;
2903 return 0;
2904}
2905
2899#ifdef CONFIG_COMPAT 2906#ifdef CONFIG_COMPAT
2900int copy_siginfo_to_user32(struct compat_siginfo __user *to, 2907int copy_siginfo_to_user32(struct compat_siginfo __user *to,
2901 const struct siginfo *from) 2908 const struct siginfo *from)
@@ -3323,8 +3330,9 @@ SYSCALL_DEFINE3(rt_sigqueueinfo, pid_t, pid, int, sig,
3323 siginfo_t __user *, uinfo) 3330 siginfo_t __user *, uinfo)
3324{ 3331{
3325 siginfo_t info; 3332 siginfo_t info;
3326 if (copy_from_user(&info, uinfo, sizeof(siginfo_t))) 3333 int ret = copy_siginfo_from_user(&info, uinfo);
3327 return -EFAULT; 3334 if (unlikely(ret))
3335 return ret;
3328 return do_rt_sigqueueinfo(pid, sig, &info); 3336 return do_rt_sigqueueinfo(pid, sig, &info);
3329} 3337}
3330 3338
@@ -3365,10 +3373,9 @@ SYSCALL_DEFINE4(rt_tgsigqueueinfo, pid_t, tgid, pid_t, pid, int, sig,
3365 siginfo_t __user *, uinfo) 3373 siginfo_t __user *, uinfo)
3366{ 3374{
3367 siginfo_t info; 3375 siginfo_t info;
3368 3376 int ret = copy_siginfo_from_user(&info, uinfo);
3369 if (copy_from_user(&info, uinfo, sizeof(siginfo_t))) 3377 if (unlikely(ret))
3370 return -EFAULT; 3378 return ret;
3371
3372 return do_rt_tgsigqueueinfo(tgid, pid, sig, &info); 3379 return do_rt_tgsigqueueinfo(tgid, pid, sig, &info);
3373} 3380}
3374 3381
@@ -3380,9 +3387,9 @@ COMPAT_SYSCALL_DEFINE4(rt_tgsigqueueinfo,
3380 struct compat_siginfo __user *, uinfo) 3387 struct compat_siginfo __user *, uinfo)
3381{ 3388{
3382 siginfo_t info; 3389 siginfo_t info;
3383 3390 int ret = copy_siginfo_from_user32(&info, uinfo);
3384 if (copy_siginfo_from_user32(&info, uinfo)) 3391 if (unlikely(ret))
3385 return -EFAULT; 3392 return ret;
3386 return do_rt_tgsigqueueinfo(tgid, pid, sig, &info); 3393 return do_rt_tgsigqueueinfo(tgid, pid, sig, &info);
3387} 3394}
3388#endif 3395#endif