From e3e811a3f824ad839e9c33ae8c0e3d2165fc1911 Mon Sep 17 00:00:00 2001 From: Brooks Davis Date: Wed, 17 Nov 2021 20:12:25 +0000 Subject: freebsd32: add feed foward clock syscalls These are required when supporting i386 because time_t is 32-bit which reduces struct bintime to 12-bytes when combined with the fact that 64-bit integers only requiring 32-bit alignment on i386. Reusing the default ABI version resulted in 4-byte overreads or overwrites to userspace. Reviewed by: kevans --- sys/compat/freebsd32/freebsd32.h | 23 +++++++ sys/compat/freebsd32/freebsd32_misc.c | 84 ++++++++++++++++++++++++++ sys/compat/freebsd32/freebsd32_proto.h | 10 +++ sys/compat/freebsd32/freebsd32_syscall.h | 4 +- sys/compat/freebsd32/freebsd32_syscalls.c | 4 +- sys/compat/freebsd32/freebsd32_sysent.c | 4 +- sys/compat/freebsd32/freebsd32_systrace_args.c | 24 ++++---- sys/compat/freebsd32/syscalls.master | 8 +-- 8 files changed, 139 insertions(+), 22 deletions(-) diff --git a/sys/compat/freebsd32/freebsd32.h b/sys/compat/freebsd32/freebsd32.h index 6f219d0f733f..65e4726b3de6 100644 --- a/sys/compat/freebsd32/freebsd32.h +++ b/sys/compat/freebsd32/freebsd32.h @@ -35,6 +35,7 @@ #include #include #include +#include /* * i386 is the only arch with a 32-bit time_t @@ -65,6 +66,28 @@ struct bintime32 { uint32_t frac[2]; }; +struct ffclock_estimate32 { + struct bintime32 update_time; + ffcounter update_ffcount; + ffcounter leapsec_next; + uint64_t period; + uint32_t errb_abs; + uint32_t errb_rate; + uint32_t status; + int16_t leapsec_total; + int8_t leapsec; + int8_t _pad; +} +#if defined(__amd64__) +__attribute__((packed)) +#endif +; +#if defined(__amd64__) +_Static_assert(sizeof(struct ffclock_estimate32) == 52, "ffclock_estimate32 size"); +#else +_Static_assert(sizeof(struct ffclock_estimate32) == 56, "ffclock_estimate32 size"); +#endif + struct rusage32 { struct timeval32 ru_utime; struct timeval32 ru_stime; diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index e2fb6fae1aa9..528180dbd063 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -29,6 +29,7 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_ffclock.h" #include "opt_inet.h" #include "opt_inet6.h" #include "opt_ktrace.h" @@ -61,6 +62,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include #include @@ -91,6 +93,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #ifdef KTRACE #include #endif @@ -3741,6 +3744,87 @@ freebsd32_ntp_adjtime(struct thread *td, struct freebsd32_ntp_adjtime_args *uap) return (error); } +#ifdef FFCLOCK +extern struct mtx ffclock_mtx; +extern struct ffclock_estimate ffclock_estimate; +extern int8_t ffclock_updated; + +int +freebsd32_ffclock_setestimate(struct thread *td, + struct freebsd32_ffclock_setestimate_args *uap) +{ + struct ffclock_estimate cest; + struct ffclock_estimate32 cest32; + int error; + + /* Reuse of PRIV_CLOCK_SETTIME. */ + if ((error = priv_check(td, PRIV_CLOCK_SETTIME)) != 0) + return (error); + + if ((error = copyin(uap->cest, &cest32, + sizeof(struct ffclock_estimate32))) != 0) + return (error); + + CP(cest.update_time, cest32.update_time, sec); + memcpy(&cest.update_time.frac, &cest32.update_time.frac, sizeof(uint64_t)); + CP(cest, cest32, update_ffcount); + CP(cest, cest32, leapsec_next); + CP(cest, cest32, period); + CP(cest, cest32, errb_abs); + CP(cest, cest32, errb_rate); + CP(cest, cest32, status); + CP(cest, cest32, leapsec_total); + CP(cest, cest32, leapsec); + + mtx_lock(&ffclock_mtx); + memcpy(&ffclock_estimate, &cest, sizeof(struct ffclock_estimate)); + ffclock_updated++; + mtx_unlock(&ffclock_mtx); + return (error); +} + +int +freebsd32_ffclock_getestimate(struct thread *td, + struct freebsd32_ffclock_getestimate_args *uap) +{ + struct ffclock_estimate cest; + struct ffclock_estimate32 cest32; + int error; + + mtx_lock(&ffclock_mtx); + memcpy(&cest, &ffclock_estimate, sizeof(struct ffclock_estimate)); + mtx_unlock(&ffclock_mtx); + + CP(cest32.update_time, cest.update_time, sec); + memcpy(&cest32.update_time.frac, &cest.update_time.frac, sizeof(uint64_t)); + CP(cest32, cest, update_ffcount); + CP(cest32, cest, leapsec_next); + CP(cest32, cest, period); + CP(cest32, cest, errb_abs); + CP(cest32, cest, errb_rate); + CP(cest32, cest, status); + CP(cest32, cest, leapsec_total); + CP(cest32, cest, leapsec); + + error = copyout(&cest32, uap->cest, sizeof(struct ffclock_estimate32)); + return (error); +} +#else /* !FFCLOCK */ +int +freebsd32_ffclock_setestimate(struct thread *td, + struct freebsd32_ffclock_setestimate_args *uap) +{ + return (ENOSYS); +} + +int +freebsd32_ffclock_getestimate(struct thread *td, + struct freebsd32_ffclock_getestimate_args *uap) +{ + return (ENOSYS); +} +#endif /* FFCLOCK */ + int freebsd32_fspacectl(struct thread *td, struct freebsd32_fspacectl_args *uap) { diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h index 92d1408a539f..aab791780818 100644 --- a/sys/compat/freebsd32/freebsd32_proto.h +++ b/sys/compat/freebsd32/freebsd32_proto.h @@ -213,6 +213,12 @@ struct freebsd32_nanosleep_args { char rqtp_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * rqtp; char rqtp_r_[PADR_(const struct timespec32 *)]; char rmtp_l_[PADL_(struct timespec32 *)]; struct timespec32 * rmtp; char rmtp_r_[PADR_(struct timespec32 *)]; }; +struct freebsd32_ffclock_setestimate_args { + char cest_l_[PADL_(struct ffclock_estimate32 *)]; struct ffclock_estimate32 * cest; char cest_r_[PADR_(struct ffclock_estimate32 *)]; +}; +struct freebsd32_ffclock_getestimate_args { + char cest_l_[PADL_(struct ffclock_estimate32 *)]; struct ffclock_estimate32 * cest; char cest_r_[PADR_(struct ffclock_estimate32 *)]; +}; struct freebsd32_clock_nanosleep_args { char clock_id_l_[PADL_(clockid_t)]; clockid_t clock_id; char clock_id_r_[PADR_(clockid_t)]; char flags_l_[PADL_(int)]; int flags; char flags_r_[PADR_(int)]; @@ -782,6 +788,8 @@ int freebsd32_ktimer_create(struct thread *, struct freebsd32_ktimer_create_args int freebsd32_ktimer_settime(struct thread *, struct freebsd32_ktimer_settime_args *); int freebsd32_ktimer_gettime(struct thread *, struct freebsd32_ktimer_gettime_args *); int freebsd32_nanosleep(struct thread *, struct freebsd32_nanosleep_args *); +int freebsd32_ffclock_setestimate(struct thread *, struct freebsd32_ffclock_setestimate_args *); +int freebsd32_ffclock_getestimate(struct thread *, struct freebsd32_ffclock_getestimate_args *); int freebsd32_clock_nanosleep(struct thread *, struct freebsd32_clock_nanosleep_args *); int freebsd32_clock_getcpuclockid2(struct thread *, struct freebsd32_clock_getcpuclockid2_args *); int freebsd32_aio_read(struct thread *, struct freebsd32_aio_read_args *); @@ -1351,6 +1359,8 @@ int freebsd11_freebsd32_fstatat(struct thread *, struct freebsd11_freebsd32_fsta #define FREEBSD32_SYS_AUE_freebsd32_ktimer_settime AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_ktimer_gettime AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_nanosleep AUE_NULL +#define FREEBSD32_SYS_AUE_freebsd32_ffclock_setestimate AUE_NULL +#define FREEBSD32_SYS_AUE_freebsd32_ffclock_getestimate AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_clock_nanosleep AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_clock_getcpuclockid2 AUE_NULL #define FREEBSD32_SYS_AUE_freebsd32_aio_read AUE_AIO_READ diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h index 2e65581b5a27..169615446373 100644 --- a/sys/compat/freebsd32/freebsd32_syscall.h +++ b/sys/compat/freebsd32/freebsd32_syscall.h @@ -218,8 +218,8 @@ #define FREEBSD32_SYS_ktimer_getoverrun 239 #define FREEBSD32_SYS_freebsd32_nanosleep 240 #define FREEBSD32_SYS_ffclock_getcounter 241 -#define FREEBSD32_SYS_ffclock_setestimate 242 -#define FREEBSD32_SYS_ffclock_getestimate 243 +#define FREEBSD32_SYS_freebsd32_ffclock_setestimate 242 +#define FREEBSD32_SYS_freebsd32_ffclock_getestimate 243 #define FREEBSD32_SYS_freebsd32_clock_nanosleep 244 #define FREEBSD32_SYS_freebsd32_clock_getcpuclockid2 247 #define FREEBSD32_SYS_minherit 250 diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c index f2ef4bf97563..8277b29843f0 100644 --- a/sys/compat/freebsd32/freebsd32_syscalls.c +++ b/sys/compat/freebsd32/freebsd32_syscalls.c @@ -251,8 +251,8 @@ const char *freebsd32_syscallnames[] = { "ktimer_getoverrun", /* 239 = ktimer_getoverrun */ "freebsd32_nanosleep", /* 240 = freebsd32_nanosleep */ "ffclock_getcounter", /* 241 = ffclock_getcounter */ - "ffclock_setestimate", /* 242 = ffclock_setestimate */ - "ffclock_getestimate", /* 243 = ffclock_getestimate */ + "freebsd32_ffclock_setestimate", /* 242 = freebsd32_ffclock_setestimate */ + "freebsd32_ffclock_getestimate", /* 243 = freebsd32_ffclock_getestimate */ "freebsd32_clock_nanosleep", /* 244 = freebsd32_clock_nanosleep */ "#245", /* 245 = nosys */ "#246", /* 246 = nosys */ diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c index 4e5e91c372ff..808e01fd3afd 100644 --- a/sys/compat/freebsd32/freebsd32_sysent.c +++ b/sys/compat/freebsd32/freebsd32_sysent.c @@ -304,8 +304,8 @@ struct sysent freebsd32_sysent[] = { { .sy_narg = AS(ktimer_getoverrun_args), .sy_call = (sy_call_t *)sys_ktimer_getoverrun, .sy_auevent = AUE_NULL, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 239 = ktimer_getoverrun */ { .sy_narg = AS(freebsd32_nanosleep_args), .sy_call = (sy_call_t *)freebsd32_nanosleep, .sy_auevent = AUE_NULL, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC }, /* 240 = freebsd32_nanosleep */ { .sy_narg = AS(ffclock_getcounter_args), .sy_call = (sy_call_t *)sys_ffclock_getcounter, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 241 = ffclock_getcounter */ - { .sy_narg = AS(ffclock_setestimate_args), .sy_call = (sy_call_t *)sys_ffclock_setestimate, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 242 = ffclock_setestimate */ - { .sy_narg = AS(ffclock_getestimate_args), .sy_call = (sy_call_t *)sys_ffclock_getestimate, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 243 = ffclock_getestimate */ + { .sy_narg = AS(freebsd32_ffclock_setestimate_args), .sy_call = (sy_call_t *)freebsd32_ffclock_setestimate, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 242 = freebsd32_ffclock_setestimate */ + { .sy_narg = AS(freebsd32_ffclock_getestimate_args), .sy_call = (sy_call_t *)freebsd32_ffclock_getestimate, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 243 = freebsd32_ffclock_getestimate */ { .sy_narg = AS(freebsd32_clock_nanosleep_args), .sy_call = (sy_call_t *)freebsd32_clock_nanosleep, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_STATIC }, /* 244 = freebsd32_clock_nanosleep */ { .sy_narg = 0, .sy_call = (sy_call_t *)nosys, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_ABSENT }, /* 245 = nosys */ { .sy_narg = 0, .sy_call = (sy_call_t *)nosys, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_ABSENT }, /* 246 = nosys */ diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c index 69e510fddc0a..f4695b07d422 100644 --- a/sys/compat/freebsd32/freebsd32_systrace_args.c +++ b/sys/compat/freebsd32/freebsd32_systrace_args.c @@ -1203,17 +1203,17 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args) *n_args = 1; break; } - /* ffclock_setestimate */ + /* freebsd32_ffclock_setestimate */ case 242: { - struct ffclock_setestimate_args *p = params; - uarg[0] = (intptr_t)p->cest; /* struct ffclock_estimate * */ + struct freebsd32_ffclock_setestimate_args *p = params; + uarg[0] = (intptr_t)p->cest; /* struct ffclock_estimate32 * */ *n_args = 1; break; } - /* ffclock_getestimate */ + /* freebsd32_ffclock_getestimate */ case 243: { - struct ffclock_getestimate_args *p = params; - uarg[0] = (intptr_t)p->cest; /* struct ffclock_estimate * */ + struct freebsd32_ffclock_getestimate_args *p = params; + uarg[0] = (intptr_t)p->cest; /* struct ffclock_estimate32 * */ *n_args = 1; break; } @@ -5330,21 +5330,21 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) break; }; break; - /* ffclock_setestimate */ + /* freebsd32_ffclock_setestimate */ case 242: switch (ndx) { case 0: - p = "userland struct ffclock_estimate *"; + p = "userland struct ffclock_estimate32 *"; break; default: break; }; break; - /* ffclock_getestimate */ + /* freebsd32_ffclock_getestimate */ case 243: switch (ndx) { case 0: - p = "userland struct ffclock_estimate *"; + p = "userland struct ffclock_estimate32 *"; break; default: break; @@ -9947,12 +9947,12 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz) if (ndx == 0 || ndx == 1) p = "int"; break; - /* ffclock_setestimate */ + /* freebsd32_ffclock_setestimate */ case 242: if (ndx == 0 || ndx == 1) p = "int"; break; - /* ffclock_getestimate */ + /* freebsd32_ffclock_getestimate */ case 243: if (ndx == 0 || ndx == 1) p = "int"; diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master index 4dce7def6b4a..90b93fbd64e8 100644 --- a/sys/compat/freebsd32/syscalls.master +++ b/sys/compat/freebsd32/syscalls.master @@ -475,10 +475,10 @@ const struct timespec32 *rqtp, \ struct timespec32 *rmtp); } 241 AUE_NULL NOPROTO { int ffclock_getcounter(ffcounter *ffcount); } -242 AUE_NULL NOPROTO { int ffclock_setestimate( \ - struct ffclock_estimate *cest); } -243 AUE_NULL NOPROTO { int ffclock_getestimate( \ - struct ffclock_estimate *cest); } +242 AUE_NULL STD { int freebsd32_ffclock_setestimate( \ + struct ffclock_estimate32 *cest); } +243 AUE_NULL STD { int freebsd32_ffclock_getestimate( \ + struct ffclock_estimate32 *cest); } 244 AUE_NULL STD { int freebsd32_clock_nanosleep( \ clockid_t clock_id, int flags, \ const struct timespec32 *rqtp, \ -- cgit v1.2.3