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>
This commit is contained in:
60
fs/select.c
60
fs/select.c
@@ -291,8 +291,7 @@ static int poll_select_copy_remaining(struct timespec64 *end_time,
|
|||||||
void __user *p,
|
void __user *p,
|
||||||
int timeval, int ret)
|
int timeval, int ret)
|
||||||
{
|
{
|
||||||
struct timespec64 rts64;
|
struct timespec64 rts;
|
||||||
struct timespec rts;
|
|
||||||
struct timeval rtv;
|
struct timeval rtv;
|
||||||
|
|
||||||
if (!p)
|
if (!p)
|
||||||
@@ -305,23 +304,22 @@ static int poll_select_copy_remaining(struct timespec64 *end_time,
|
|||||||
if (!end_time->tv_sec && !end_time->tv_nsec)
|
if (!end_time->tv_sec && !end_time->tv_nsec)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ktime_get_ts64(&rts64);
|
ktime_get_ts64(&rts);
|
||||||
rts64 = timespec64_sub(*end_time, rts64);
|
rts = timespec64_sub(*end_time, rts);
|
||||||
if (rts64.tv_sec < 0)
|
if (rts.tv_sec < 0)
|
||||||
rts64.tv_sec = rts64.tv_nsec = 0;
|
rts.tv_sec = rts.tv_nsec = 0;
|
||||||
|
|
||||||
rts = timespec64_to_timespec(rts64);
|
|
||||||
|
|
||||||
if (timeval) {
|
if (timeval) {
|
||||||
if (sizeof(rtv) > sizeof(rtv.tv_sec) + sizeof(rtv.tv_usec))
|
if (sizeof(rtv) > sizeof(rtv.tv_sec) + sizeof(rtv.tv_usec))
|
||||||
memset(&rtv, 0, sizeof(rtv));
|
memset(&rtv, 0, sizeof(rtv));
|
||||||
rtv.tv_sec = rts64.tv_sec;
|
rtv.tv_sec = rts.tv_sec;
|
||||||
rtv.tv_usec = rts64.tv_nsec / NSEC_PER_USEC;
|
rtv.tv_usec = rts.tv_nsec / NSEC_PER_USEC;
|
||||||
|
|
||||||
if (!copy_to_user(p, &rtv, sizeof(rtv)))
|
if (!copy_to_user(p, &rtv, sizeof(rtv)))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
} else if (!copy_to_user(p, &rts, sizeof(rts)))
|
} else if (!put_timespec64(&rts, p))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -704,17 +702,15 @@ static long do_pselect(int n, fd_set __user *inp, fd_set __user *outp,
|
|||||||
const sigset_t __user *sigmask, size_t sigsetsize)
|
const sigset_t __user *sigmask, size_t sigsetsize)
|
||||||
{
|
{
|
||||||
sigset_t ksigmask, sigsaved;
|
sigset_t ksigmask, sigsaved;
|
||||||
struct timespec ts;
|
struct timespec64 ts, end_time, *to = NULL;
|
||||||
struct timespec64 ts64, end_time, *to = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (tsp) {
|
if (tsp) {
|
||||||
if (copy_from_user(&ts, tsp, sizeof(ts)))
|
if (get_timespec64(&ts, tsp))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
ts64 = timespec_to_timespec64(ts);
|
|
||||||
|
|
||||||
to = &end_time;
|
to = &end_time;
|
||||||
if (poll_select_set_timeout(to, ts64.tv_sec, ts64.tv_nsec))
|
if (poll_select_set_timeout(to, ts.tv_sec, ts.tv_nsec))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1051,12 +1047,11 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
|
|||||||
size_t, sigsetsize)
|
size_t, sigsetsize)
|
||||||
{
|
{
|
||||||
sigset_t ksigmask, sigsaved;
|
sigset_t ksigmask, sigsaved;
|
||||||
struct timespec ts;
|
struct timespec64 ts, end_time, *to = NULL;
|
||||||
struct timespec64 end_time, *to = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (tsp) {
|
if (tsp) {
|
||||||
if (copy_from_user(&ts, tsp, sizeof(ts)))
|
if (get_timespec64(&ts, tsp))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
to = &end_time;
|
to = &end_time;
|
||||||
@@ -1102,10 +1097,10 @@ SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds, unsigned int, nfds,
|
|||||||
#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t))
|
#define __COMPAT_NFDBITS (8 * sizeof(compat_ulong_t))
|
||||||
|
|
||||||
static
|
static
|
||||||
int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p,
|
int compat_poll_select_copy_remaining(struct timespec64 *end_time, void __user *p,
|
||||||
int timeval, int ret)
|
int timeval, int ret)
|
||||||
{
|
{
|
||||||
struct timespec ts;
|
struct timespec64 ts;
|
||||||
|
|
||||||
if (!p)
|
if (!p)
|
||||||
return ret;
|
return ret;
|
||||||
@@ -1117,8 +1112,8 @@ int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p,
|
|||||||
if (!end_time->tv_sec && !end_time->tv_nsec)
|
if (!end_time->tv_sec && !end_time->tv_nsec)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ktime_get_ts(&ts);
|
ktime_get_ts64(&ts);
|
||||||
ts = timespec_sub(*end_time, ts);
|
ts = timespec64_sub(*end_time, ts);
|
||||||
if (ts.tv_sec < 0)
|
if (ts.tv_sec < 0)
|
||||||
ts.tv_sec = ts.tv_nsec = 0;
|
ts.tv_sec = ts.tv_nsec = 0;
|
||||||
|
|
||||||
@@ -1131,12 +1126,7 @@ int compat_poll_select_copy_remaining(struct timespec *end_time, void __user *p,
|
|||||||
if (!copy_to_user(p, &rtv, sizeof(rtv)))
|
if (!copy_to_user(p, &rtv, sizeof(rtv)))
|
||||||
return ret;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
struct compat_timespec rts;
|
if (!compat_put_timespec64(&ts, p))
|
||||||
|
|
||||||
rts.tv_sec = ts.tv_sec;
|
|
||||||
rts.tv_nsec = ts.tv_nsec;
|
|
||||||
|
|
||||||
if (!copy_to_user(p, &rts, sizeof(rts)))
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@@ -1194,7 +1184,7 @@ int compat_set_fd_set(unsigned long nr, compat_ulong_t __user *ufdset,
|
|||||||
*/
|
*/
|
||||||
static int compat_core_sys_select(int n, compat_ulong_t __user *inp,
|
static int compat_core_sys_select(int n, compat_ulong_t __user *inp,
|
||||||
compat_ulong_t __user *outp, compat_ulong_t __user *exp,
|
compat_ulong_t __user *outp, compat_ulong_t __user *exp,
|
||||||
struct timespec *end_time)
|
struct timespec64 *end_time)
|
||||||
{
|
{
|
||||||
fd_set_bits fds;
|
fd_set_bits fds;
|
||||||
void *bits;
|
void *bits;
|
||||||
@@ -1267,7 +1257,7 @@ COMPAT_SYSCALL_DEFINE5(select, int, n, compat_ulong_t __user *, inp,
|
|||||||
compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
|
compat_ulong_t __user *, outp, compat_ulong_t __user *, exp,
|
||||||
struct compat_timeval __user *, tvp)
|
struct compat_timeval __user *, tvp)
|
||||||
{
|
{
|
||||||
struct timespec end_time, *to = NULL;
|
struct timespec64 end_time, *to = NULL;
|
||||||
struct compat_timeval tv;
|
struct compat_timeval tv;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
@@ -1313,12 +1303,11 @@ static long do_compat_pselect(int n, compat_ulong_t __user *inp,
|
|||||||
{
|
{
|
||||||
compat_sigset_t ss32;
|
compat_sigset_t ss32;
|
||||||
sigset_t ksigmask, sigsaved;
|
sigset_t ksigmask, sigsaved;
|
||||||
struct compat_timespec ts;
|
struct timespec64 ts, end_time, *to = NULL;
|
||||||
struct timespec end_time, *to = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (tsp) {
|
if (tsp) {
|
||||||
if (copy_from_user(&ts, tsp, sizeof(ts)))
|
if (compat_get_timespec64(&ts, tsp))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
to = &end_time;
|
to = &end_time;
|
||||||
@@ -1382,12 +1371,11 @@ COMPAT_SYSCALL_DEFINE5(ppoll, struct pollfd __user *, ufds,
|
|||||||
{
|
{
|
||||||
compat_sigset_t ss32;
|
compat_sigset_t ss32;
|
||||||
sigset_t ksigmask, sigsaved;
|
sigset_t ksigmask, sigsaved;
|
||||||
struct compat_timespec ts;
|
struct timespec64 ts, end_time, *to = NULL;
|
||||||
struct timespec end_time, *to = NULL;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (tsp) {
|
if (tsp) {
|
||||||
if (copy_from_user(&ts, tsp, sizeof(ts)))
|
if (compat_get_timespec64(&ts, tsp))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
to = &end_time;
|
to = &end_time;
|
||||||
|
|||||||
Reference in New Issue
Block a user