Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 297708
b: refs/heads/master
c: 6684ba2
h: refs/heads/master
v: v3
  • Loading branch information
H. Peter Anvin committed Feb 20, 2012
1 parent 5afb025 commit 9cefa65
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 45e877812926c69d643d6274347f79513a4ee934
refs/heads/master: 6684ba202b5ab2f36d574c72fe50c207d99b3e35
16 changes: 16 additions & 0 deletions trunk/include/linux/compat.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,26 @@ typedef struct {
compat_sigset_word sig[_COMPAT_NSIG_WORDS];
} compat_sigset_t;

/*
* These functions operate strictly on struct compat_time*
*/
extern int get_compat_timespec(struct timespec *,
const struct compat_timespec __user *);
extern int put_compat_timespec(const struct timespec *,
struct compat_timespec __user *);
extern int get_compat_timeval(struct timeval *,
const struct compat_timeval __user *);
extern int put_compat_timeval(const struct timeval *,
struct compat_timeval __user *);
/*
* These functions operate on 32- or 64-bit specs depending on
* COMPAT_USE_64BIT_TIME, hence the void user pointer arguments and the
* naming as compat_get/put_ rather than get/put_compat_.
*/
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 *);

struct compat_iovec {
compat_uptr_t iov_base;
Expand Down
68 changes: 60 additions & 8 deletions trunk/kernel/compat.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,10 @@
#include <asm/uaccess.h>

/*
* Note that the native side is already converted to a timespec, because
* that's what we want anyway.
* Get/set struct timeval with struct timespec on the native side
*/
static int compat_get_timeval(struct timespec *o,
struct compat_timeval __user *i)
static int compat_get_timeval_convert(struct timespec *o,
struct compat_timeval __user *i)
{
long usec;

Expand All @@ -46,8 +45,8 @@ static int compat_get_timeval(struct timespec *o,
return 0;
}

static int compat_put_timeval(struct compat_timeval __user *o,
struct timeval *i)
static int compat_put_timeval_convert(struct compat_timeval __user *o,
struct timeval *i)
{
return (put_user(i->tv_sec, &o->tv_sec) ||
put_user(i->tv_usec, &o->tv_usec)) ? -EFAULT : 0;
Expand Down Expand Up @@ -117,7 +116,7 @@ asmlinkage long compat_sys_gettimeofday(struct compat_timeval __user *tv,
if (tv) {
struct timeval ktv;
do_gettimeofday(&ktv);
if (compat_put_timeval(tv, &ktv))
if (compat_put_timeval_convert(tv, &ktv))
return -EFAULT;
}
if (tz) {
Expand All @@ -135,7 +134,7 @@ asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
struct timezone ktz;

if (tv) {
if (compat_get_timeval(&kts, tv))
if (compat_get_timeval_convert(&kts, tv))
return -EFAULT;
}
if (tz) {
Expand All @@ -146,12 +145,29 @@ asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv,
return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL);
}

int get_compat_timeval(struct timeval *tv, const struct compat_timeval __user *ctv)
{
return (!access_ok(VERIFY_READ, ctv, sizeof(*ctv)) ||
__get_user(tv->tv_sec, &ctv->tv_sec) ||
__get_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
}
EXPORT_SYMBOL_GPL(get_compat_timeval);

int put_compat_timeval(const struct timeval *tv, struct compat_timeval __user *ctv)
{
return (!access_ok(VERIFY_WRITE, ctv, sizeof(*ctv)) ||
__put_user(tv->tv_sec, &ctv->tv_sec) ||
__put_user(tv->tv_usec, &ctv->tv_usec)) ? -EFAULT : 0;
}
EXPORT_SYMBOL_GPL(put_compat_timeval);

int get_compat_timespec(struct timespec *ts, const struct compat_timespec __user *cts)
{
return (!access_ok(VERIFY_READ, cts, sizeof(*cts)) ||
__get_user(ts->tv_sec, &cts->tv_sec) ||
__get_user(ts->tv_nsec, &cts->tv_nsec)) ? -EFAULT : 0;
}
EXPORT_SYMBOL_GPL(get_compat_timespec);

int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user *cts)
{
Expand All @@ -161,6 +177,42 @@ int put_compat_timespec(const struct timespec *ts, struct compat_timespec __user
}
EXPORT_SYMBOL_GPL(put_compat_timespec);

int compat_get_timeval(struct timeval *tv, const void __user *utv)
{
if (COMPAT_USE_64BIT_TIME)
return copy_from_user(tv, utv, sizeof *tv) ? -EFAULT : 0;
else
return get_compat_timeval(tv, utv);
}
EXPORT_SYMBOL_GPL(compat_get_timeval);

int compat_put_timeval(const struct timeval *tv, void __user *utv)
{
if (COMPAT_USE_64BIT_TIME)
return copy_to_user(utv, tv, sizeof *tv) ? -EFAULT : 0;
else
return put_compat_timeval(tv, utv);
}
EXPORT_SYMBOL_GPL(compat_put_timeval);

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

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

static long compat_nanosleep_restart(struct restart_block *restart)
{
struct compat_timespec __user *rmtp;
Expand Down

0 comments on commit 9cefa65

Please sign in to comment.