diff options
Diffstat (limited to 'fs/select.c')
| -rw-r--r-- | fs/select.c | 69 |
1 files changed, 27 insertions, 42 deletions
diff --git a/fs/select.c b/fs/select.c index c6362e38ae92..6de493bb42a4 100644 --- a/fs/select.c +++ b/fs/select.c | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 1 | /* | 2 | /* |
| 2 | * This file contains the procedures for the handling of select and poll | 3 | * This file contains the procedures for the handling of select and poll |
| 3 | * | 4 | * |
| @@ -291,8 +292,7 @@ static int poll_select_copy_remaining(struct timespec64 *end_time, | |||
| 291 | void __user *p, | 292 | void __user *p, |
| 292 | int timeval, int ret) | 293 | int timeval, int ret) |
| 293 | { | 294 | { |
| 294 | struct timespec64 rts64; | 295 | struct timespec64 rts; |
| 295 | struct timespec rts; | ||
| 296 | struct timeval rtv; | 296 | struct timeval rtv; |
| 297 | 297 | ||
| 298 | if (!p) | 298 | if (!p) |
| @@ -305,23 +305,22 @@ static int poll_select_copy_remaining(struct timespec64 *end_time, | |||
| 305 | if (!end_time->tv_sec && !end_time->tv_nsec) | 305 | if (!end_time->tv_sec && !end_time->tv_nsec) |
| 306 | return ret; | 306 | return ret; |
| 307 | 307 | ||
| 308 | ktime_get_ts64(&rts64); | 308 | ktime_get_ts64(&rts); |
| 309 | rts64 = timespec64_sub(*end_time, rts64); | 309 | rts = timespec64_sub(*end_time, rts); |
| 310 | if (rts64.tv_sec < 0) | 310 | if (rts.tv_sec < 0) |
| 311 | rts64.tv_sec = rts64.tv_nsec = 0; | 311 | rts.tv_sec = rts.tv_nsec = 0; |
| 312 | 312 | ||
| 313 | rts = timespec64_to_timespec(rts64); | ||
| 314 | 313 | ||
| 315 | if (timeval) { | 314 | if (timeval) { |
| 316 | if (sizeof(rtv) > sizeof(rtv.tv_sec) + sizeof(rtv.tv_usec)) | 315 | if (sizeof(rtv) > sizeof(rtv.tv_sec) + sizeof(rtv.tv_usec)) |
| 317 | memset(&rtv, 0, sizeof(rtv)); | 316 | memset(&rtv, 0, sizeof(rtv)); |
| 318 | rtv.tv_sec = rts64.tv_sec; | 317 | rtv.tv_sec = rts.tv_sec; |
| 319 | rtv.tv_usec = rts64.tv_nsec / NSEC_PER_USEC; | 318 | rtv.tv_usec = rts.tv_nsec / NSEC_PER_USEC; |
| 320 | 319 | ||
| 321 | if (!copy_to_user(p, &rtv, sizeof(rtv))) | 320 | if (!copy_to_user(p, &rtv, sizeof(rtv))) |
| 322 | return ret; | 321 | return ret; |
| 323 | 322 | ||
| 324 | } else if (!copy_to_user(p, &rts, sizeof(rts))) | 323 | } else if (!put_timespec64(&rts, p)) |
| 325 | return ret; | 324 | return ret; |
| 326 | 325 | ||
| 327 | /* | 326 | /* |
| @@ -704,17 +703,15 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp, | |||
| 704 | const sigset_t __user *sigmask, size_t sigsetsize) | 703 | const sigset_t __user *sigmask, size_t sigsetsize) |
| 705 | { | 704 | { |
| 706 | sigset_t ksigmask, sigsaved; | 705 | sigset_t ksigmask, sigsaved; |
| 707 | struct timespec ts; | 706 | struct timespec64 ts, end_time, *to = NULL; |
| 708 | struct timespec64 ts64, end_time, *to = NULL; | ||
| 709 | int ret; | 707 | int ret; |
| 710 | 708 | ||
| 711 | if (tsp) { | 709 | if (tsp) { |
| 712 | if (copy_from_user(&ts, tsp, sizeof(ts))) | 710 | if (get_timespec64(&ts, tsp)) |
| 713 | return -EFAULT; | 711 | return -EFAULT; |
| 714 | ts64 = timespec_to_timespec64(ts); | ||
| 715 | 712 | ||
| 716 | to = &end_time; | 713 | to = &end_time; |
| 717 | if (poll_select_set_timeout(to, ts64.tv_sec, ts64.tv_nsec)) | 714 | if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec)) |
| 718 | return -EINVAL; | 715 | return -EINVAL; |
| 719 | } | 716 | } |
| 720 | 717 | ||
| @@ -1051,12 +1048,11 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds, | |||
| 1051 | size_t, sigsetsize) | 1048 | size_t, sigsetsize) |
| 1052 | { | 1049 | { |
| 1053 | sigset_t ksigmask, sigsaved; | 1050 | sigset_t ksigmask, sigsaved; |
| 1054 | struct timespec ts; | 1051 | struct timespec64 ts, end_time, *to = NULL; |
| 1055 | struct timespec64 end_time, *to = NULL; | ||
| 1056 | int ret; | 1052 | int ret; |
| 1057 | 1053 | ||
| 1058 | if (tsp) { | 1054 | if (tsp) { |
| 1059 | if (copy_from_user(&ts, tsp, sizeof(ts))) | 1055 | if (get_timespec64(&ts, tsp)) |
| 1060 | return -EFAULT; | 1056 | return -EFAULT; |
| 1061 | 1057 | ||
| 1062 | to = &end_time; | 1058 | to = &end_time; |
| @@ -1102,10 +1098,10 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds, | |||
| 1102 | #define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) | 1098 | #define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t)) |
| 1103 | 1099 | ||
| 1104 | static | 1100 | static |
| 1105 | int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p, | 1101 | int compat_poll_select_copy_remaining(struct timespec64 *end_time, void __user *p, |
| 1106 | int timeval, int ret) | 1102 | int timeval, int ret) |
| 1107 | { | 1103 | { |
| 1108 | struct timespec ts; | 1104 | struct timespec64 ts; |
| 1109 | 1105 | ||
| 1110 | if (!p) | 1106 | if (!p) |
| 1111 | return ret; | 1107 | return ret; |
| @@ -1117,8 +1113,8 @@ int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p, | |||
| 1117 | if (!end_time->tv_sec && !end_time->tv_nsec) | 1113 | if (!end_time->tv_sec && !end_time->tv_nsec) |
| 1118 | return ret; | 1114 | return ret; |
| 1119 | 1115 | ||
| 1120 | ktime_get_ts(&ts); | 1116 | ktime_get_ts64(&ts); |
| 1121 | ts = timespec_sub(*end_time, ts); | 1117 | ts = timespec64_sub(*end_time, ts); |
| 1122 | if (ts.tv_sec < 0) | 1118 | if (ts.tv_sec < 0) |
| 1123 | ts.tv_sec = ts.tv_nsec = 0; | 1119 | ts.tv_sec = ts.tv_nsec = 0; |
| 1124 | 1120 | ||
| @@ -1131,12 +1127,7 @@ int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p, | |||
| 1131 | if (!copy_to_user(p, &rtv, sizeof(rtv))) | 1127 | if (!copy_to_user(p, &rtv, sizeof(rtv))) |
| 1132 | return ret; | 1128 | return ret; |
| 1133 | } else { | 1129 | } else { |
| 1134 | struct compat_timespec rts; | 1130 | 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; | 1131 | return ret; |
| 1141 | } | 1132 | } |
| 1142 | /* | 1133 | /* |
| @@ -1194,7 +1185,7 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset, | |||
| 1194 | */ | 1185 | */ |
| 1195 | static int compat_core_sys_select(int n, compat_ulong_t __user *inp, | 1186 | static int compat_core_sys_select(int n, compat_ulong_t __user *inp, |
| 1196 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, | 1187 | compat_ulong_t __user *outp, compat_ulong_t __user *exp, |
| 1197 | struct timespec *end_time) | 1188 | struct timespec64 *end_time) |
| 1198 | { | 1189 | { |
| 1199 | fd_set_bits fds; | 1190 | fd_set_bits fds; |
| 1200 | void *bits; | 1191 | void *bits; |
| @@ -1267,7 +1258,7 @@ COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp, | |||
| 1267 | compat_ulong_t __user *, outp, compat_ulong_t __user *, exp, | 1258 | compat_ulong_t __user *, outp, compat_ulong_t __user *, exp, |
| 1268 | struct compat_timeval __user *, tvp) | 1259 | struct compat_timeval __user *, tvp) |
| 1269 | { | 1260 | { |
| 1270 | struct timespec end_time, *to = NULL; | 1261 | struct timespec64 end_time, *to = NULL; |
| 1271 | struct compat_timeval tv; | 1262 | struct compat_timeval tv; |
| 1272 | int ret; | 1263 | int ret; |
| 1273 | 1264 | ||
| @@ -1311,14 +1302,12 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp, | |||
| 1311 | struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask, | 1302 | struct compat_timespec __user *tsp, compat_sigset_t __user *sigmask, |
| 1312 | compat_size_t sigsetsize) | 1303 | compat_size_t sigsetsize) |
| 1313 | { | 1304 | { |
| 1314 | 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; |
| @@ -1329,9 +1318,8 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp, | |||
| 1329 | if (sigmask) { | 1318 | if (sigmask) { |
| 1330 | if (sigsetsize != sizeof(compat_sigset_t)) | 1319 | if (sigsetsize != sizeof(compat_sigset_t)) |
| 1331 | return -EINVAL; | 1320 | return -EINVAL; |
| 1332 | if (copy_from_user(&ss32, sigmask, sizeof(ss32))) | 1321 | if (get_compat_sigset(&ksigmask, sigmask)) |
| 1333 | return -EFAULT; | 1322 | return -EFAULT; |
| 1334 | sigset_from_compat(&ksigmask, &ss32); | ||
| 1335 | 1323 | ||
| 1336 | sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); | 1324 | sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); |
| 1337 | sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); | 1325 | sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); |
| @@ -1380,14 +1368,12 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, | |||
| 1380 | unsigned int, nfds, struct compat_timespec __user *, tsp, | 1368 | unsigned int, nfds, struct compat_timespec __user *, tsp, |
| 1381 | const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize) | 1369 | const compat_sigset_t __user *, sigmask, compat_size_t, sigsetsize) |
| 1382 | { | 1370 | { |
| 1383 | compat_sigset_t ss32; | ||
| 1384 | sigset_t ksigmask, sigsaved; | 1371 | sigset_t ksigmask, sigsaved; |
| 1385 | struct compat_timespec ts; | 1372 | struct timespec64 ts, end_time, *to = NULL; |
| 1386 | struct timespec end_time, *to = NULL; | ||
| 1387 | int ret; | 1373 | int ret; |
| 1388 | 1374 | ||
| 1389 | if (tsp) { | 1375 | if (tsp) { |
| 1390 | if (copy_from_user(&ts, tsp, sizeof(ts))) | 1376 | if (compat_get_timespec64(&ts, tsp)) |
| 1391 | return -EFAULT; | 1377 | return -EFAULT; |
| 1392 | 1378 | ||
| 1393 | to = &end_time; | 1379 | to = &end_time; |
| @@ -1398,9 +1384,8 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, | |||
| 1398 | if (sigmask) { | 1384 | if (sigmask) { |
| 1399 | if (sigsetsize != sizeof(compat_sigset_t)) | 1385 | if (sigsetsize != sizeof(compat_sigset_t)) |
| 1400 | return -EINVAL; | 1386 | return -EINVAL; |
| 1401 | if (copy_from_user(&ss32, sigmask, sizeof(ss32))) | 1387 | if (get_compat_sigset(&ksigmask, sigmask)) |
| 1402 | return -EFAULT; | 1388 | return -EFAULT; |
| 1403 | sigset_from_compat(&ksigmask, &ss32); | ||
| 1404 | 1389 | ||
| 1405 | sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); | 1390 | sigdelsetmask(&ksigmask, sigmask(SIGKILL)|sigmask(SIGSTOP)); |
| 1406 | sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); | 1391 | sigprocmask(SIG_SETMASK, &ksigmask, &sigsaved); |
