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
This commit is contained in:
Brooks Davis 2021-11-17 20:12:25 +00:00
parent 7bd795650f
commit e3e811a3f8
8 changed files with 139 additions and 22 deletions

View File

@ -35,6 +35,7 @@
#include <sys/procfs.h>
#include <sys/socket.h>
#include <sys/user.h>
#include <sys/_ffcounter.h>
/*
* 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;

View File

@ -29,6 +29,7 @@
#include <sys/cdefs.h>
__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 <sys/mount.h>
#include <sys/mutex.h>
#include <sys/namei.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/procctl.h>
#include <sys/ptrace.h>
@ -91,6 +93,7 @@ __FBSDID("$FreeBSD$");
#include <sys/msg.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <sys/timeffc.h>
#ifdef KTRACE
#include <sys/ktrace.h>
#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)
{

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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";

View File

@ -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, \