linux(4): Add a helper intended for copying timespec's from the userspace.

There are many places where we copyin Linux timespec from the userspace
and then convert it to the kernel timespec. To avoid code duplication
add a tiny halper for doing this.

MFC after:		2 weeks
This commit is contained in:
Dmitry Chagin 2022-05-08 16:16:47 +03:00
parent 3dc2a06752
commit 707e567a40
8 changed files with 47 additions and 108 deletions

View File

@ -540,7 +540,6 @@ int
linux_epoll_pwait2_64(struct thread *td, struct linux_epoll_pwait2_64_args *args)
{
struct timespec ts, *tsa;
struct l_timespec64 lts;
sigset_t mask, *pmask;
int error;
@ -550,9 +549,7 @@ linux_epoll_pwait2_64(struct thread *td, struct linux_epoll_pwait2_64_args *args
return (error);
if (args->timeout) {
if ((error = copyin(args->timeout, &lts, sizeof(lts))))
return (error);
error = linux_to_native_timespec64(&ts, &lts);
error = linux_get_timespec64(&ts, args->timeout);
if (error != 0)
return (error);
tsa = &ts;
@ -567,7 +564,6 @@ int
linux_epoll_pwait2(struct thread *td, struct linux_epoll_pwait2_args *args)
{
struct timespec ts, *tsa;
struct l_timespec lts;
sigset_t mask, *pmask;
int error;
@ -577,9 +573,7 @@ linux_epoll_pwait2(struct thread *td, struct linux_epoll_pwait2_args *args)
return (error);
if (args->timeout) {
if ((error = copyin(args->timeout, &lts, sizeof(lts))))
return (error);
error = linux_to_native_timespec(&ts, &lts);
error = linux_get_timespec(&ts, args->timeout);
if (error != 0)
return (error);
tsa = &ts;

View File

@ -816,7 +816,6 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
.val3 = args->val3,
.val3_compare = true,
};
struct l_timespec lts;
int error;
switch (args->op & LINUX_FUTEX_CMD_MASK) {
@ -825,10 +824,7 @@ linux_sys_futex(struct thread *td, struct linux_sys_futex_args *args)
case LINUX_FUTEX_LOCK_PI:
case LINUX_FUTEX_LOCK_PI2:
if (args->timeout != NULL) {
error = copyin(args->timeout, &lts, sizeof(lts));
if (error != 0)
return (error);
error = linux_to_native_timespec(&fargs.kts, &lts);
error = linux_get_timespec(&fargs.kts, args->timeout);
if (error != 0)
return (error);
fargs.ts = &fargs.kts;
@ -854,7 +850,6 @@ linux_sys_futex_time64(struct thread *td,
.val3 = args->val3,
.val3_compare = true,
};
struct l_timespec64 lts;
int error;
switch (args->op & LINUX_FUTEX_CMD_MASK) {
@ -863,10 +858,7 @@ linux_sys_futex_time64(struct thread *td,
case LINUX_FUTEX_LOCK_PI:
case LINUX_FUTEX_LOCK_PI2:
if (args->timeout != NULL) {
error = copyin(args->timeout, &lts, sizeof(lts));
if (error != 0)
return (error);
error = linux_to_native_timespec64(&fargs.kts, &lts);
error = linux_get_timespec64(&fargs.kts, args->timeout);
if (error != 0)
return (error);
fargs.ts = &fargs.kts;

View File

@ -510,13 +510,10 @@ int
linux_semtimedop_time64(struct thread *td, struct linux_semtimedop_time64_args *args)
{
struct timespec ts, *tsa;
struct l_timespec64 lts;
int error;
if (args->timeout) {
if ((error = copyin(args->timeout, &lts, sizeof(lts))))
return (error);
error = linux_to_native_timespec64(&ts, &lts);
error = linux_get_timespec64(&ts, args->timeout);
if (error != 0)
return (error);
tsa = &ts;
@ -532,13 +529,10 @@ int
linux_semtimedop(struct thread *td, struct linux_semtimedop_args *args)
{
struct timespec ts, *tsa;
struct l_timespec lts;
int error;
if (args->timeout) {
if ((error = copyin(args->timeout, &lts, sizeof(lts))))
return (error);
error = linux_to_native_timespec(&ts, &lts);
error = linux_get_timespec(&ts, args->timeout);
if (error != 0)
return (error);
tsa = &ts;

View File

@ -2380,15 +2380,11 @@ linux_prlimit64(struct thread *td, struct linux_prlimit64_args *args)
int
linux_pselect6(struct thread *td, struct linux_pselect6_args *args)
{
struct l_timespec lts;
struct timespec ts, *tsp;
int error;
if (args->tsp != NULL) {
error = copyin(args->tsp, &lts, sizeof(lts));
if (error != 0)
return (error);
error = linux_to_native_timespec(&ts, &lts);
error = linux_get_timespec(&ts, args->tsp);
if (error != 0)
return (error);
tsp = &ts;
@ -2472,15 +2468,11 @@ int
linux_pselect6_time64(struct thread *td,
struct linux_pselect6_time64_args *args)
{
struct l_timespec64 lts;
struct timespec ts, *tsp;
int error;
if (args->tsp != NULL) {
error = copyin(args->tsp, &lts, sizeof(lts));
if (error != 0)
return (error);
error = linux_to_native_timespec64(&ts, &lts);
error = linux_get_timespec64(&ts, args->tsp);
if (error != 0)
return (error);
tsp = &ts;
@ -2500,14 +2492,10 @@ int
linux_ppoll(struct thread *td, struct linux_ppoll_args *args)
{
struct timespec uts, *tsp;
struct l_timespec lts;
int error;
if (args->tsp != NULL) {
error = copyin(args->tsp, &lts, sizeof(lts));
if (error)
return (error);
error = linux_to_native_timespec(&uts, &lts);
error = linux_get_timespec(&uts, args->tsp);
if (error != 0)
return (error);
tsp = &uts;
@ -2582,14 +2570,10 @@ int
linux_ppoll_time64(struct thread *td, struct linux_ppoll_time64_args *args)
{
struct timespec uts, *tsp;
struct l_timespec64 lts;
int error;
if (args->tsp != NULL) {
error = copyin(args->tsp, &lts, sizeof(lts));
if (error != 0)
return (error);
error = linux_to_native_timespec64(&uts, &lts);
error = linux_get_timespec64(&uts, args->tsp);
if (error != 0)
return (error);
tsp = &uts;

View File

@ -436,13 +436,10 @@ linux_rt_sigtimedwait(struct thread *td,
struct linux_rt_sigtimedwait_args *args)
{
struct timespec ts, *tsa;
struct l_timespec lts;
int error;
if (args->timeout) {
if ((error = copyin(args->timeout, &lts, sizeof(lts))))
return (error);
error = linux_to_native_timespec(&ts, &lts);
error = linux_get_timespec(&ts, args->timeout);
if (error != 0)
return (error);
tsa = &ts;
@ -490,13 +487,10 @@ linux_rt_sigtimedwait_time64(struct thread *td,
struct linux_rt_sigtimedwait_time64_args *args)
{
struct timespec ts, *tsa;
struct l_timespec64 lts;
int error;
if (args->timeout) {
if ((error = copyin(args->timeout, &lts, sizeof(lts))))
return (error);
error = linux_to_native_timespec64(&ts, &lts);
error = linux_get_timespec64(&ts, args->timeout);
if (error != 0)
return (error);
tsa = &ts;

View File

@ -1786,15 +1786,11 @@ linux_recvmmsg_common(struct thread *td, l_int s, struct l_mmsghdr *msg,
int
linux_recvmmsg(struct thread *td, struct linux_recvmmsg_args *args)
{
struct l_timespec lts;
struct timespec ts, tts, *ptts;
int error;
if (args->timeout) {
error = copyin(args->timeout, &lts, sizeof(struct l_timespec));
if (error != 0)
return (error);
error = linux_to_native_timespec(&ts, &lts);
error = linux_get_timespec(&ts, args->timeout);
if (error != 0)
return (error);
getnanotime(&tts);
@ -1811,15 +1807,11 @@ linux_recvmmsg(struct thread *td, struct linux_recvmmsg_args *args)
int
linux_recvmmsg_time64(struct thread *td, struct linux_recvmmsg_time64_args *args)
{
struct l_timespec64 lts;
struct timespec ts, tts, *ptts;
int error;
if (args->timeout) {
error = copyin(args->timeout, &lts, sizeof(struct l_timespec));
if (error != 0)
return (error);
error = linux_to_native_timespec64(&ts, &lts);
error = linux_get_timespec64(&ts, args->timeout);
if (error != 0)
return (error);
getnanotime(&tts);

View File

@ -101,16 +101,13 @@ LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres, copyout_error, "int");
#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
LIN_SDT_PROBE_DEFINE1(time, linux_clock_getres_time64, copyout_error, "int");
#endif
LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, conversion_error, "int");
LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyout_error, "int");
LIN_SDT_PROBE_DEFINE1(time, linux_nanosleep, copyin_error, "int");
LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, conversion_error, "int");
LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyout_error, "int");
LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, copyin_error, "int");
LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_flags, "int");
LIN_SDT_PROBE_DEFINE1(time, linux_common_clock_nanosleep, unsupported_clockid, "int");
#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, conversion_error, "int");
LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyout_error, "int");
LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep_time64, copyin_error, "int");
#endif
@ -162,6 +159,18 @@ linux_put_timespec(struct timespec *ntp, struct l_timespec *ltp)
return (copyout(&lts, ltp, sizeof(lts)));
}
int
linux_get_timespec(struct timespec *ntp, const struct l_timespec *ultp)
{
struct l_timespec lts;
int error;
error = copyin(ultp, &lts, sizeof(lts));
if (error != 0)
return (error);
return (linux_to_native_timespec(ntp, &lts));
}
#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
int
native_to_linux_timespec64(struct l_timespec64 *ltp64, struct timespec *ntp)
@ -203,6 +212,18 @@ linux_put_timespec64(struct timespec *ntp, struct l_timespec64 *ltp)
return (error);
return (copyout(&lts, ltp, sizeof(lts)));
}
int
linux_get_timespec64(struct timespec *ntp, const struct l_timespec64 *ultp)
{
struct l_timespec64 lts;
int error;
error = copyin(ultp, &lts, sizeof(lts));
if (error != 0)
return (error);
return (linux_to_native_timespec64(ntp, &lts));
}
#endif
int
@ -508,19 +529,13 @@ int
linux_clock_settime(struct thread *td, struct linux_clock_settime_args *args)
{
struct timespec ts;
struct l_timespec lts;
int error;
error = copyin(args->tp, &lts, sizeof(lts));
error = linux_get_timespec(&ts, args->tp);
if (error != 0) {
LIN_SDT_PROBE1(time, linux_clock_settime, copyin_error, error);
return (error);
}
error = linux_to_native_timespec(&ts, &lts);
if (error != 0)
LIN_SDT_PROBE1(time, linux_clock_settime, conversion_error,
error);
return (linux_common_clock_settime(td, args->which, &ts));
}
@ -529,18 +544,13 @@ int
linux_clock_settime64(struct thread *td, struct linux_clock_settime64_args *args)
{
struct timespec ts;
struct l_timespec64 lts;
int error;
error = copyin(args->tp, &lts, sizeof(lts));
error = linux_get_timespec64(&ts, args->tp);
if (error != 0) {
LIN_SDT_PROBE1(time, linux_clock_settime64, copyin_error, error);
return (error);
}
error = linux_to_native_timespec64(&ts, &lts);
if (error != 0)
LIN_SDT_PROBE1(time, linux_clock_settime64, conversion_error,
error);
return (linux_common_clock_settime(td, args->which, &ts));
}
#endif
@ -680,26 +690,19 @@ int
linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
{
struct timespec *rmtp;
struct l_timespec lrqts;
struct timespec rqts, rmts;
int error, error2;
error = copyin(args->rqtp, &lrqts, sizeof lrqts);
error = linux_get_timespec(&rqts, args->rqtp);
if (error != 0) {
LIN_SDT_PROBE1(time, linux_nanosleep, copyin_error, error);
return (error);
}
if (args->rmtp != NULL)
rmtp = &rmts;
else
rmtp = NULL;
error = linux_to_native_timespec(&rqts, &lrqts);
if (error != 0) {
LIN_SDT_PROBE1(time, linux_nanosleep, conversion_error, error);
return (error);
}
error = kern_nanosleep(td, &rqts, rmtp);
if (error == EINTR && args->rmtp != NULL) {
error2 = linux_put_timespec(rmtp, args->rmtp);
@ -746,24 +749,15 @@ linux_clock_nanosleep(struct thread *td,
struct linux_clock_nanosleep_args *args)
{
struct timespec *rmtp;
struct l_timespec lrqts;
struct timespec rqts, rmts;
int error, error2;
error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
error = linux_get_timespec(&rqts, args->rqtp);
if (error != 0) {
LIN_SDT_PROBE1(time, linux_clock_nanosleep, copyin_error,
error);
return (error);
}
error = linux_to_native_timespec(&rqts, &lrqts);
if (error != 0) {
LIN_SDT_PROBE1(time, linux_clock_nanosleep, conversion_error,
error);
return (error);
}
if (args->rmtp != NULL)
rmtp = &rmts;
else
@ -789,24 +783,15 @@ linux_clock_nanosleep_time64(struct thread *td,
struct linux_clock_nanosleep_time64_args *args)
{
struct timespec *rmtp;
struct l_timespec64 lrqts;
struct timespec rqts, rmts;
int error, error2;
error = copyin(args->rqtp, &lrqts, sizeof(lrqts));
error = linux_get_timespec64(&rqts, args->rqtp);
if (error != 0) {
LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
copyin_error, error);
return (error);
}
error = linux_to_native_timespec64(&rqts, &lrqts);
if (error != 0) {
LIN_SDT_PROBE1(time, linux_clock_nanosleep_time64,
conversion_error, error);
return (error);
}
if (args->rmtp != NULL)
rmtp = &rmts;
else

View File

@ -117,6 +117,8 @@ int linux_to_native_timespec(struct timespec *,
struct l_timespec *);
int linux_put_timespec(struct timespec *,
struct l_timespec *);
int linux_get_timespec(struct timespec *,
const struct l_timespec *);
#if defined(__i386__) || (defined(__amd64__) && defined(COMPAT_LINUX32))
int native_to_linux_timespec64(struct l_timespec64 *,
struct timespec *);
@ -124,6 +126,8 @@ int linux_to_native_timespec64(struct timespec *,
struct l_timespec64 *);
int linux_put_timespec64(struct timespec *,
struct l_timespec64 *);
int linux_get_timespec64(struct timespec *,
const struct l_timespec64 *);
#endif
int linux_to_native_clockid(clockid_t *, clockid_t);
int native_to_linux_itimerspec(struct l_itimerspec *,