Skip to content

Commit

Permalink
compat: Enable compat_get/put_timespec64 always
Browse files Browse the repository at this point in the history
These functions are used in the repurposed compat syscalls
to provide backward compatibility for using 32 bit time_t
on 32 bit systems.

Signed-off-by: Deepa Dinamani <[email protected]>
Signed-off-by: Arnd Bergmann <[email protected]>
  • Loading branch information
deepa-hub authored and arndb committed Apr 19, 2018
1 parent 0d55303 commit 1c68adf
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 46 deletions.
2 changes: 0 additions & 2 deletions include/linux/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -294,8 +294,6 @@ extern int compat_get_timespec(struct timespec *, const void __user *);
extern int compat_put_timespec(const struct timespec *, void __user *);
extern int compat_get_timeval(struct timeval *, const void __user *);
extern int compat_put_timeval(const struct timeval *, void __user *);
extern int compat_get_timespec64(struct timespec64 *, const void __user *);
extern int compat_put_timespec64(const struct timespec64 *, void __user *);
extern int get_compat_itimerspec64(struct itimerspec64 *its,
const struct compat_itimerspec __user *uits);
extern int put_compat_itimerspec64(const struct itimerspec64 *its,
Expand Down
4 changes: 4 additions & 0 deletions include/linux/compat_time.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#define _LINUX_COMPAT_TIME_H

#include <linux/types.h>
#include <linux/time64.h>

typedef s32 compat_time_t;

Expand All @@ -16,4 +17,7 @@ struct compat_timeval {
s32 tv_usec;
};

extern int compat_get_timespec64(struct timespec64 *, const void __user *);
extern int compat_put_timespec64(const struct timespec64 *, void __user *);

#endif /* _LINUX_COMPAT_TIME_H */
52 changes: 8 additions & 44 deletions kernel/compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,50 +120,6 @@ static int __compat_put_timespec(const struct timespec *ts, struct compat_timesp
__put_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
}

static int __compat_get_timespec64(struct timespec64 *ts64,
const struct compat_timespec __user *cts)
{
struct compat_timespec ts;
int ret;

ret = copy_from_user(&ts, cts, sizeof(ts));
if (ret)
return -EFAULT;

ts64->tv_sec = ts.tv_sec;
ts64->tv_nsec = ts.tv_nsec;

return 0;
}

static int __compat_put_timespec64(const struct timespec64 *ts64,
struct compat_timespec __user *cts)
{
struct compat_timespec ts = {
.tv_sec = ts64->tv_sec,
.tv_nsec = ts64->tv_nsec
};
return copy_to_user(cts, &ts, sizeof(ts)) ? -EFAULT : 0;
}

int compat_get_timespec64(struct timespec64 *ts, const void __user *uts)
{
if (COMPAT_USE_64BIT_TIME)
return copy_from_user(ts, uts, sizeof(*ts)) ? -EFAULT : 0;
else
return __compat_get_timespec64(ts, uts);
}
EXPORT_SYMBOL_GPL(compat_get_timespec64);

int compat_put_timespec64(const struct timespec64 *ts, void __user *uts)
{
if (COMPAT_USE_64BIT_TIME)
return copy_to_user(uts, ts, sizeof(*ts)) ? -EFAULT : 0;
else
return __compat_put_timespec64(ts, uts);
}
EXPORT_SYMBOL_GPL(compat_put_timespec64);

int compat_get_timeval(struct timeval *tv, const void __user *utv)
{
if (COMPAT_USE_64BIT_TIME)
Expand Down Expand Up @@ -367,6 +323,14 @@ COMPAT_SYSCALL_DEFINE3(sched_getaffinity, compat_pid_t, pid, unsigned int, len,
return ret;
}

/* Todo: Delete these extern declarations when get/put_compat_itimerspec64()
* are moved to kernel/time/time.c .
*/
extern int __compat_get_timespec64(struct timespec64 *ts64,
const struct compat_timespec __user *cts);
extern int __compat_put_timespec64(const struct timespec64 *ts64,
struct compat_timespec __user *cts);

int get_compat_itimerspec64(struct itimerspec64 *its,
const struct compat_itimerspec __user *uits)
{
Expand Down
44 changes: 44 additions & 0 deletions kernel/time/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -880,6 +880,50 @@ int put_timespec64(const struct timespec64 *ts,
}
EXPORT_SYMBOL_GPL(put_timespec64);

int __compat_get_timespec64(struct timespec64 *ts64,
const struct compat_timespec __user *cts)
{
struct compat_timespec ts;
int ret;

ret = copy_from_user(&ts, cts, sizeof(ts));
if (ret)
return -EFAULT;

ts64->tv_sec = ts.tv_sec;
ts64->tv_nsec = ts.tv_nsec;

return 0;
}

int __compat_put_timespec64(const struct timespec64 *ts64,
struct compat_timespec __user *cts)
{
struct compat_timespec ts = {
.tv_sec = ts64->tv_sec,
.tv_nsec = ts64->tv_nsec
};
return copy_to_user(cts, &ts, sizeof(ts)) ? -EFAULT : 0;
}

int compat_get_timespec64(struct timespec64 *ts, const void __user *uts)
{
if (COMPAT_USE_64BIT_TIME)
return copy_from_user(ts, uts, sizeof(*ts)) ? -EFAULT : 0;
else
return __compat_get_timespec64(ts, uts);
}
EXPORT_SYMBOL_GPL(compat_get_timespec64);

int compat_put_timespec64(const struct timespec64 *ts, void __user *uts)
{
if (COMPAT_USE_64BIT_TIME)
return copy_to_user(uts, ts, sizeof(*ts)) ? -EFAULT : 0;
else
return __compat_put_timespec64(ts, uts);
}
EXPORT_SYMBOL_GPL(compat_put_timespec64);

int get_itimerspec64(struct itimerspec64 *it,
const struct itimerspec __user *uit)
{
Expand Down

0 comments on commit 1c68adf

Please sign in to comment.