diff options
author | Deepa Dinamani <deepa.kernel@gmail.com> | 2017-08-05 00:12:31 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2017-09-19 17:55:58 -0400 |
commit | 36819ad093e16a4b06c53f98d4a5afc55530bbcb (patch) | |
tree | aa982a97ae10e3c3e4928517d4ed6c0de9a02558 /fs/select.c | |
parent | 176826af03666758c656dd27f098cc889b71638b (diff) |
select: Use get/put_timespec64
Usage of these apis and their compat versions makes
the syscalls: select family of syscalls and their
compat implementations simpler.
This is a preparatory patch to isolate data conversions to
struct timespec64 at userspace boundaries. This helps contain
the changes needed to transition to new y2038 safe types.
Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/select.c')
-rw-r--r-- | fs/select.c | 60 |
1 files changed, 24 insertions, 36 deletions
diff --git a/fs/select.c b/fs/select.c index c6362e38ae92..20a7d061904f 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -291,8 +291,7 @@ static int poll_select_copy_remaining(struct timespec64 *end_time, | |||
291 | void __user *p, | 291 | void __user *p, |
292 | int timeval, int ret) | 292 | int timeval, int ret) |
293 | { | 293 | { |
294 | struct timespec64 rts64; | 294 | struct timespec64 rts; |
295 | struct timespec rts; | ||
296 | struct timeval rtv; | 295 | struct timeval rtv; |
297 | 296 | ||
298 | if (!p) | 297 | if (!p) |
@@ -305,23 +304,22 @@ static int poll_select_copy_remaining(struct timespec64 *end_time, | |||
305 | if (!end_time->tv_sec && !end_time->tv_nsec) | 304 | if (!end_time->tv_sec && !end_time->tv_nsec) |
306 | return ret; | 305 | return ret; |
307 | 306 | ||
308 | ktime_get_ts64(&rts64); | 307 | ktime_get_ts64(&rts); |
309 | rts64 = timespec64_sub(*end_time, rts64); | 308 | rts = timespec64_sub(*end_time, rts); |
310 | if (rts64.tv_sec < 0) | 309 | if (rts.tv_sec < 0) |
311 | rts64.tv_sec = rts64.tv_nsec = 0; | 310 | rts.tv_sec = rts.tv_nsec = 0; |
312 | 311 | ||
313 | rts = timespec64_to_timespec(rts64); | ||
314 | 312 | ||
315 | if (timeval) { | 313 | if (timeval) { |
316 | if (sizeof(rtv) > sizeof(rtv.tv_sec) + sizeof(rtv.tv_usec)) | 314 | if (sizeof(rtv) > sizeof(rtv.tv_sec) + sizeof(rtv.tv_usec)) |
317 | memset(&rtv, 0, sizeof(rtv)); | 315 | memset(&rtv, 0, sizeof(rtv)); |
318 | rtv.tv_sec = rts64.tv_sec; | 316 | rtv.tv_sec = rts.tv_sec; |
319 | rtv.tv_usec = rts64.tv_nsec / NSEC_PER_USEC; | 317 | rtv.tv_usec = rts.tv_nsec / NSEC_PER_USEC; |
320 | 318 | ||
321 | if (!copy_to_user(p, &rtv, sizeof(rtv))) | 319 | if (!copy_to_user(p, &rtv, sizeof(rtv))) |
322 | return ret; | 320 | return ret; |
323 | 321 | ||
324 | } else if (!copy_to_user(p, &rts, sizeof(rts))) | 322 | } else if (!put_timespec64(&rts, p)) |
325 | return ret; | 323 | return ret; |
326 | 324 | ||
327 | /* | 325 | /* |
@@ -704,17 +702,15 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp, | |||
704 | const sigset_t __user *sigmask, size_t sigsetsize) | 702 | const sigset_t __user *sigmask, size_t sigsetsize) |
705 | { | 703 | { |
706 | sigset_t ksigmask, sigsaved; | 704 | sigset_t ksigmask, sigsaved; |
707 | struct timespec ts; | 705 | struct timespec64 ts, end_time, *to = NULL; |
708 | struct timespec64 ts64, end_time, *to = NULL; | ||
709 | int ret; | 706 | int ret; |
710 | 707 | ||
711 | if (tsp) { | 708 | if (tsp) { |
712 | if (copy_from_user(&ts, tsp, sizeof(ts))) | 709 | if (get_timespec64(&ts, tsp)) |
713 | return -EFAULT; | 710 | return -EFAULT; |
714 | ts64 = timespec_to_timespec64(ts); | ||
715 | 711 | ||
716 | to = &end_time; | 712 | to = &end_time; |
717 | if (poll_select_set_timeout(to, ts64.tv_sec, ts64.tv_nsec)) | 713 | if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec)) |
718 | return -EINVAL; | 714 | return -EINVAL; |
719 | } | 715 | } |
720 | 716 | ||
@@ -1051,12 +1047,11 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds, | |||
1051 | size_t, sigsetsize) | 1047 | size_t, sigsetsize) |
1052 | { | 1048 | { |
1053 | sigset_t ksigmask, sigsaved; | 1049 | sigset_t ksigmask, sigsaved; |
1054 | struct timespec ts; | 1050 | struct timespec64 ts, end_time, *to = NULL; |
1055 | struct timespec64 end_time, *to = NULL; | ||
1056 | int ret; | 1051 | int ret; |
1057 | 1052 | ||
1058 | if (tsp) { | 1053 | if (tsp) { |
1059 | if (copy_from_user(&ts, tsp, sizeof(ts))) | 1054 | if (get_timespec64(&ts, tsp)) |
1060 | return -EFAULT; | 1055 | return -EFAULT; |
1061 | 1056 | ||
1062 | to = &end_time; | 1057 | to = &end_time; |
@@ -1102,10 +1097,10 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds, | |||
1102 | #define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) | 1097 | #define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) |
1103 | 1098 | ||
1104 | static | 1099 | static |
1105 | int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p, | 1100 | int compat_poll_select_copy_remaining(struct timespec64 *end_time, void __user *p, |
1106 | int timeval, int ret) | 1101 | int timeval, int ret) |
1107 | { | 1102 | { |
1108 | struct timespec ts; | 1103 | struct timespec64 ts; |
1109 | 1104 | ||
1110 | if (!p) | 1105 | if (!p) |
1111 | return ret; | 1106 | return ret; |
@@ -1117,8 +1112,8 @@ int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p, | |||
1117 | if (!end_time->tv_sec && !end_time->tv_nsec) | 1112 | if (!end_time->tv_sec && !end_time->tv_nsec) |
1118 | return ret; | 1113 | return ret; |
1119 | 1114 | ||
1120 | ktime_get_ts(&ts); | 1115 | ktime_get_ts64(&ts); |
1121 | ts = timespec_sub(*end_time, ts); | 1116 | ts = timespec64_sub(*end_time, ts); |
1122 | if (ts.tv_sec < 0) | 1117 | if (ts.tv_sec < 0) |
1123 | ts.tv_sec = ts.tv_nsec = 0; | 1118 | ts.tv_sec = ts.tv_nsec = 0; |
1124 | 1119 | ||
@@ -1131,12 +1126,7 @@ int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p, | |||
1131 | if (!copy_to_user(p, &rtv, sizeof(rtv))) | 1126 | if (!copy_to_user(p, &rtv, sizeof(rtv))) |
1132 | return ret; | 1127 | return ret; |
1133 | } else { | 1128 | } else { |
1134 | struct compat_timespec rts; | 1129 | if (!compat_put_timespec64(&ts, p)) |
1135 | |||
1136 | rts.tv_sec = ts.tv_sec; | ||
1137 | rts.tv_nsec = ts.tv_nsec; | ||
1138 | |||
1139 | if (!copy_to_user(p, &rts, sizeof(rts))) | ||
1140 | return ret; | 1130 | return ret; |
1141 | } | 1131 | } |
1142 | /* | 1132 | /* |
@@ -1194,7 +1184,7 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, | |||
1194 | */ | 1184 | */ |
1195 | static int compat_core_sys_select(int n, compat_ulong_t __user *inp, | 1185 | static int compat_core_sys_select(int n, compat_ulong_t __user *inp, |
1196 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, | 1186 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, |
1197 | struct timespec *end_time) | 1187 | struct timespec64 *end_time) |
1198 | { | 1188 | { |
1199 | fd_set_bits fds; | 1189 | fd_set_bits fds; |
1200 | void *bits; | 1190 | void *bits; |
@@ -1267,7 +1257,7 @@ COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp, | |||
1267 | compat_ulong_t __user *, outp, compat_ulong_t __user *, exp, | 1257 | compat_ulong_t __user *, outp, compat_ulong_t __user *, exp, |
1268 | struct compat_timeval __user *, tvp) | 1258 | struct compat_timeval __user *, tvp) |
1269 | { | 1259 | { |
1270 | struct timespec end_time, *to = NULL; | 1260 | struct timespec64 end_time, *to = NULL; |
1271 | struct compat_timeval tv; | 1261 | struct compat_timeval tv; |
1272 | int ret; | 1262 | int ret; |
1273 | 1263 | ||
@@ -1313,12 +1303,11 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp, | |||
1313 | { | 1303 | { |
1314 | compat_sigset_t ss32; | 1304 | compat_sigset_t ss32; |
1315 | sigset_t ksigmask, sigsaved; | 1305 | sigset_t ksigmask, sigsaved; |
1316 | struct compat_timespec ts; | 1306 | struct timespec64 ts, end_time, *to = NULL; |
1317 | struct timespec end_time, *to = NULL; | ||
1318 | int ret; | 1307 | int ret; |
1319 | 1308 | ||
1320 | if (tsp) { | 1309 | if (tsp) { |
1321 | if (copy_from_user(&ts, tsp, sizeof(ts))) | 1310 | if (compat_get_timespec64(&ts, tsp)) |
1322 | return -EFAULT; | 1311 | return -EFAULT; |
1323 | 1312 | ||
1324 | to = &end_time; | 1313 | to = &end_time; |
@@ -1382,12 +1371,11 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, | |||
1382 | { | 1371 | { |
1383 | compat_sigset_t ss32; | 1372 | compat_sigset_t ss32; |
1384 | sigset_t ksigmask, sigsaved; | 1373 | sigset_t ksigmask, sigsaved; |
1385 | struct compat_timespec ts; | 1374 | struct timespec64 ts, end_time, *to = NULL; |
1386 | struct timespec end_time, *to = NULL; | ||
1387 | int ret; | 1375 | int ret; |
1388 | 1376 | ||
1389 | if (tsp) { | 1377 | if (tsp) { |
1390 | if (copy_from_user(&ts, tsp, sizeof(ts))) | 1378 | if (compat_get_timespec64(&ts, tsp)) |
1391 | return -EFAULT; | 1379 | return -EFAULT; |
1392 | 1380 | ||
1393 | to = &end_time; | 1381 | to = &end_time; |