Skip to content

Commit

Permalink
time: introduce {get,put}_itimerspec64
Browse files Browse the repository at this point in the history
As we change the user space type for the timerfd and posix timer
functions to newer data types, we need some form of conversion
helpers to avoid duplicating that logic.

Suggested-by: Arnd Bergmann <[email protected]>
Signed-off-by: Deepa Dinamani <[email protected]>
Signed-off-by: Al Viro <[email protected]>
  • Loading branch information
deepa-hub authored and Al Viro committed Jun 26, 2017
1 parent f59dd9c commit d5b7ffb
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 1 deletion.
4 changes: 4 additions & 0 deletions include/linux/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,10 @@ 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,
struct compat_itimerspec __user *uits);

/*
* This function convert a timespec if necessary and returns a *user
Expand Down
1 change: 0 additions & 1 deletion include/linux/posix-timers.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,5 +113,4 @@ void set_process_cpu_timer(struct task_struct *task, unsigned int clock_idx,
void update_rlimit_cpu(struct task_struct *task, unsigned long rlim_new);

void posixtimer_rearm(struct siginfo *info);

#endif
13 changes: 13 additions & 0 deletions include/linux/time.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ int get_timespec64(struct timespec64 *ts,
const struct timespec __user *uts);
int put_timespec64(const struct timespec64 *ts,
struct timespec __user *uts);
int get_itimerspec64(struct itimerspec64 *it,
const struct itimerspec __user *uit);
int put_itimerspec64(const struct itimerspec64 *it,
struct itimerspec __user *uit);

#define TIME_T_MAX (time_t)((1UL << ((sizeof(time_t) << 3) - 1)) - 1)

Expand Down Expand Up @@ -275,4 +279,13 @@ static __always_inline void timespec_add_ns(struct timespec *a, u64 ns)
a->tv_nsec = ns;
}

static inline bool itimerspec64_valid(const struct itimerspec64 *its)
{
if (!timespec64_valid(&(its->it_interval)) ||
!timespec64_valid(&(its->it_value)))
return false;

return true;
}

#endif
21 changes: 21 additions & 0 deletions kernel/compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -586,6 +586,27 @@ int put_compat_itimerspec(struct compat_itimerspec __user *dst,
return 0;
}

int get_compat_itimerspec64(struct itimerspec64 *its,
const struct compat_itimerspec __user *uits)
{

if (__compat_get_timespec64(&its->it_interval, &uits->it_interval) ||
__compat_get_timespec64(&its->it_value, &uits->it_value))
return -EFAULT;
return 0;
}
EXPORT_SYMBOL_GPL(get_compat_itimerspec64);

int put_compat_itimerspec64(const struct itimerspec64 *its,
struct compat_itimerspec __user *uits)
{
if (__compat_put_timespec64(&its->it_interval, &uits->it_interval) ||
__compat_put_timespec64(&its->it_value, &uits->it_value))
return -EFAULT;
return 0;
}
EXPORT_SYMBOL_GPL(put_compat_itimerspec64);

/*
* We currently only need the following fields from the sigevent
* structure: sigev_value, sigev_signo, sig_notify and (sometimes
Expand Down
30 changes: 30 additions & 0 deletions kernel/time/time.c
Original file line number Diff line number Diff line change
Expand Up @@ -918,3 +918,33 @@ int put_timespec64(const struct timespec64 *ts,
return copy_to_user(uts, &kts, sizeof(kts)) ? -EFAULT : 0;
}
EXPORT_SYMBOL_GPL(put_timespec64);

int get_itimerspec64(struct itimerspec64 *it,
const struct itimerspec __user *uit)
{
int ret;

ret = get_timespec64(&it->it_interval, &uit->it_interval);
if (ret)
return ret;

ret = get_timespec64(&it->it_value, &uit->it_value);

return ret;
}
EXPORT_SYMBOL_GPL(get_itimerspec64);

int put_itimerspec64(const struct itimerspec64 *it,
struct itimerspec __user *uit)
{
int ret;

ret = put_timespec64(&it->it_interval, &uit->it_interval);
if (ret)
return ret;

ret = put_timespec64(&it->it_value, &uit->it_value);

return ret;
}
EXPORT_SYMBOL_GPL(put_itimerspec64);

0 comments on commit d5b7ffb

Please sign in to comment.