aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrooks Davis <brooks@FreeBSD.org>2021-11-17 20:12:25 +0000
committerBrooks Davis <brooks@FreeBSD.org>2021-11-17 20:12:25 +0000
commite3e811a3f824ad839e9c33ae8c0e3d2165fc1911 (patch)
tree77c397fcd455fdfa164077123e2420e4c1ccfea0
parent7bd795650f5c5310819755f1f0428bfe693c8515 (diff)
downloadsrc-e3e811a3f824ad839e9c33ae8c0e3d2165fc1911.tar.gz
src-e3e811a3f824ad839e9c33ae8c0e3d2165fc1911.zip
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
-rw-r--r--sys/compat/freebsd32/freebsd32.h23
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c84
-rw-r--r--sys/compat/freebsd32/freebsd32_proto.h10
-rw-r--r--sys/compat/freebsd32/freebsd32_syscall.h4
-rw-r--r--sys/compat/freebsd32/freebsd32_syscalls.c4
-rw-r--r--sys/compat/freebsd32/freebsd32_sysent.c4
-rw-r--r--sys/compat/freebsd32/freebsd32_systrace_args.c24
-rw-r--r--sys/compat/freebsd32/syscalls.master8
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 <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;
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 <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)
{
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, \