diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2018-04-18 18:30:19 -0400 |
---|---|---|
committer | Eric W. Biederman <ebiederm@xmission.com> | 2018-10-03 10:47:15 -0400 |
commit | 4cd2e0e70af6897ca2247fa1ffb1553ca16b4903 (patch) | |
tree | 55e54fb3ca4ea687448ffaddd34e8cb4366466d7 | |
parent | f28380185193610c716a90ec9b9e696638a495ce (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.h | 1 | ||||
-rw-r--r-- | kernel/ptrace.c | 12 | ||||
-rw-r--r-- | kernel/signal.c | 25 |
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 | ||
24 | int copy_siginfo_to_user(struct siginfo __user *to, const struct siginfo *from); | 24 | int copy_siginfo_to_user(struct siginfo __user *to, const struct siginfo *from); |
25 | int copy_siginfo_from_user(struct siginfo *to, const struct siginfo __user *from); | ||
25 | 26 | ||
26 | enum siginfo_layout { | 27 | enum 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 | ||
2899 | int 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 |
2900 | int copy_siginfo_to_user32(struct compat_siginfo __user *to, | 2907 | int 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 |