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:
parent
7bd795650f
commit
e3e811a3f8
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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";
|
||||
|
@ -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, \
|
||||
|
Loading…
x
Reference in New Issue
Block a user