git: e3e811a3f824 - main - freebsd32: add feed foward clock syscalls

From: Brooks Davis <brooks_at_FreeBSD.org>
Date: Wed, 17 Nov 2021 20:22:39 UTC
The branch main has been updated by brooks:

URL: https://cgit.FreeBSD.org/src/commit/?id=e3e811a3f824ad839e9c33ae8c0e3d2165fc1911

commit e3e811a3f824ad839e9c33ae8c0e3d2165fc1911
Author:     Brooks Davis <brooks@FreeBSD.org>
AuthorDate: 2021-11-17 20:12:25 +0000
Commit:     Brooks Davis <brooks@FreeBSD.org>
CommitDate: 2021-11-17 20:12:25 +0000

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