git: e02f64d9b88c - main - freebsd32: add real abort2

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

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

commit e02f64d9b88ce33313755f4a94c46a7839a23f10
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 real abort2
    
    Previously, the code would copy twice as many pointers as specified
    and print pairs of them a single 64-bit pointer.
    
    abort2 doesn't return so make the return type void
    
    freebsd32_abort2 is in it's own file with a 2-clause BSD license
    based on a discussion with Wojciech many years ago.
    
    Reviewed by:    kevans
---
 sys/compat/freebsd32/freebsd32_abort2.c        | 69 ++++++++++++++++++++++++++
 sys/compat/freebsd32/freebsd32_proto.h         |  7 +++
 sys/compat/freebsd32/freebsd32_syscall.h       |  2 +-
 sys/compat/freebsd32/freebsd32_syscalls.c      |  2 +-
 sys/compat/freebsd32/freebsd32_sysent.c        |  2 +-
 sys/compat/freebsd32/freebsd32_systrace_args.c | 10 ++--
 sys/compat/freebsd32/syscalls.master           |  2 +-
 sys/conf/files                                 |  1 +
 sys/kern/kern_exit.c                           | 52 ++++++++++++++-----
 sys/sys/syscallsubr.h                          |  2 +
 10 files changed, 127 insertions(+), 22 deletions(-)

diff --git a/sys/compat/freebsd32/freebsd32_abort2.c b/sys/compat/freebsd32/freebsd32_abort2.c
new file mode 100644
index 000000000000..615dd5e95345
--- /dev/null
+++ b/sys/compat/freebsd32/freebsd32_abort2.c
@@ -0,0 +1,69 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2005 Wojciech A. Koszek
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/sbuf.h>
+#include <sys/syscallsubr.h>
+#include <sys/syslog.h>
+
+#include <compat/freebsd32/freebsd32_proto.h>
+
+int
+freebsd32_abort2(struct thread *td, struct freebsd32_abort2_args *uap)
+{
+	void *uargs[16];
+	void *uargsp;
+	uint32_t *uargsptr;
+	uint32_t ptr;
+	int i, nargs;
+
+	nargs = uap->nargs;
+	if (nargs < 0 || nargs > nitems(uargs))
+		nargs = -1;
+	uargsp = NULL;
+	if (nargs > 0) {
+		if (uap->args != NULL) {
+			uargsptr = uap->args;
+			for (i = 0; i < nargs; i++) {
+				if (fueword32(uargsptr + i, &ptr) != 0) {
+					nargs = -1;
+					break;
+				} else
+					uargs[i] = (void *)(uintptr_t)ptr;
+			}
+			if (nargs > 0)
+				uargsp = &uargs;
+		} else
+			nargs = -1;
+	}
+	return (kern_abort2(td, uap->why, nargs, uargsp));
+}
diff --git a/sys/compat/freebsd32/freebsd32_proto.h b/sys/compat/freebsd32/freebsd32_proto.h
index aab791780818..f86fb5dfa96f 100644
--- a/sys/compat/freebsd32/freebsd32_proto.h
+++ b/sys/compat/freebsd32/freebsd32_proto.h
@@ -396,6 +396,11 @@ struct freebsd32_kmq_notify_args {
 	char mqd_l_[PADL_(int)]; int mqd; char mqd_r_[PADR_(int)];
 	char sigev_l_[PADL_(const struct sigevent32 *)]; const struct sigevent32 * sigev; char sigev_r_[PADR_(const struct sigevent32 *)];
 };
+struct freebsd32_abort2_args {
+	char why_l_[PADL_(const char *)]; const char * why; char why_r_[PADR_(const char *)];
+	char nargs_l_[PADL_(int)]; int nargs; char nargs_r_[PADR_(int)];
+	char args_l_[PADL_(uint32_t *)]; uint32_t * args; char args_r_[PADR_(uint32_t *)];
+};
 struct freebsd32_aio_fsync_args {
 	char op_l_[PADL_(int)]; int op; char op_r_[PADR_(int)];
 	char aiocbp_l_[PADL_(struct aiocb32 *)]; struct aiocb32 * aiocbp; char aiocbp_r_[PADR_(struct aiocb32 *)];
@@ -827,6 +832,7 @@ int	freebsd32_kmq_setattr(struct thread *, struct freebsd32_kmq_setattr_args *);
 int	freebsd32_kmq_timedreceive(struct thread *, struct freebsd32_kmq_timedreceive_args *);
 int	freebsd32_kmq_timedsend(struct thread *, struct freebsd32_kmq_timedsend_args *);
 int	freebsd32_kmq_notify(struct thread *, struct freebsd32_kmq_notify_args *);
+int	freebsd32_abort2(struct thread *, struct freebsd32_abort2_args *);
 int	freebsd32_aio_fsync(struct thread *, struct freebsd32_aio_fsync_args *);
 #ifdef PAD64_REQUIRED
 int	freebsd32_pread(struct thread *, struct freebsd32_pread_args *);
@@ -1409,6 +1415,7 @@ int	freebsd11_freebsd32_fstatat(struct thread *, struct freebsd11_freebsd32_fsta
 #define	FREEBSD32_SYS_AUE_freebsd32_kmq_timedreceive	AUE_MQ_TIMEDRECEIVE
 #define	FREEBSD32_SYS_AUE_freebsd32_kmq_timedsend	AUE_MQ_TIMEDSEND
 #define	FREEBSD32_SYS_AUE_freebsd32_kmq_notify	AUE_MQ_NOTIFY
+#define	FREEBSD32_SYS_AUE_freebsd32_abort2	AUE_NULL
 #define	FREEBSD32_SYS_AUE_freebsd32_aio_fsync	AUE_AIO_FSYNC
 #define	FREEBSD32_SYS_AUE_freebsd32_pread	AUE_PREAD
 #define	FREEBSD32_SYS_AUE_freebsd32_pwrite	AUE_PWRITE
diff --git a/sys/compat/freebsd32/freebsd32_syscall.h b/sys/compat/freebsd32/freebsd32_syscall.h
index 169615446373..c57cce7c5343 100644
--- a/sys/compat/freebsd32/freebsd32_syscall.h
+++ b/sys/compat/freebsd32/freebsd32_syscall.h
@@ -386,7 +386,7 @@
 #define	FREEBSD32_SYS_freebsd32_kmq_timedsend	460
 #define	FREEBSD32_SYS_freebsd32_kmq_notify	461
 #define	FREEBSD32_SYS_kmq_unlink	462
-#define	FREEBSD32_SYS_abort2	463
+#define	FREEBSD32_SYS_freebsd32_abort2	463
 #define	FREEBSD32_SYS_thr_set_name	464
 #define	FREEBSD32_SYS_freebsd32_aio_fsync	465
 #define	FREEBSD32_SYS_rtprio_thread	466
diff --git a/sys/compat/freebsd32/freebsd32_syscalls.c b/sys/compat/freebsd32/freebsd32_syscalls.c
index 8277b29843f0..4ab6adb56b4a 100644
--- a/sys/compat/freebsd32/freebsd32_syscalls.c
+++ b/sys/compat/freebsd32/freebsd32_syscalls.c
@@ -472,7 +472,7 @@ const char *freebsd32_syscallnames[] = {
 	"freebsd32_kmq_timedsend",			/* 460 = freebsd32_kmq_timedsend */
 	"freebsd32_kmq_notify",			/* 461 = freebsd32_kmq_notify */
 	"kmq_unlink",			/* 462 = kmq_unlink */
-	"abort2",			/* 463 = abort2 */
+	"freebsd32_abort2",			/* 463 = freebsd32_abort2 */
 	"thr_set_name",			/* 464 = thr_set_name */
 	"freebsd32_aio_fsync",			/* 465 = freebsd32_aio_fsync */
 	"rtprio_thread",			/* 466 = rtprio_thread */
diff --git a/sys/compat/freebsd32/freebsd32_sysent.c b/sys/compat/freebsd32/freebsd32_sysent.c
index 808e01fd3afd..c25ee1edaab7 100644
--- a/sys/compat/freebsd32/freebsd32_sysent.c
+++ b/sys/compat/freebsd32/freebsd32_sysent.c
@@ -525,7 +525,7 @@ struct sysent freebsd32_sysent[] = {
 	{ .sy_narg = AS(freebsd32_kmq_timedsend_args), .sy_call = (sy_call_t *)lkmressys, .sy_auevent = AUE_NULL, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_ABSENT },	/* 460 = freebsd32_kmq_timedsend */
 	{ .sy_narg = AS(freebsd32_kmq_notify_args), .sy_call = (sy_call_t *)lkmressys, .sy_auevent = AUE_NULL, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_ABSENT },	/* 461 = freebsd32_kmq_notify */
 	{ .sy_narg = AS(kmq_unlink_args), .sy_call = (sy_call_t *)lkmressys, .sy_auevent = AUE_NULL, .sy_flags = 0, .sy_thrcnt = SY_THR_ABSENT },	/* 462 = kmq_unlink */
-	{ .sy_narg = AS(abort2_args), .sy_call = (sy_call_t *)sys_abort2, .sy_auevent = AUE_NULL, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC },	/* 463 = abort2 */
+	{ .sy_narg = AS(freebsd32_abort2_args), .sy_call = (sy_call_t *)freebsd32_abort2, .sy_auevent = AUE_NULL, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC },	/* 463 = freebsd32_abort2 */
 	{ .sy_narg = AS(thr_set_name_args), .sy_call = (sy_call_t *)sys_thr_set_name, .sy_auevent = AUE_NULL, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC },	/* 464 = thr_set_name */
 	{ .sy_narg = AS(freebsd32_aio_fsync_args), .sy_call = (sy_call_t *)freebsd32_aio_fsync, .sy_auevent = AUE_AIO_FSYNC, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC },	/* 465 = freebsd32_aio_fsync */
 	{ .sy_narg = AS(rtprio_thread_args), .sy_call = (sy_call_t *)sys_rtprio_thread, .sy_auevent = AUE_RTPRIO, .sy_flags = SYF_CAPENABLED, .sy_thrcnt = SY_THR_STATIC },	/* 466 = rtprio_thread */
diff --git a/sys/compat/freebsd32/freebsd32_systrace_args.c b/sys/compat/freebsd32/freebsd32_systrace_args.c
index f4695b07d422..98fb1dea15a8 100644
--- a/sys/compat/freebsd32/freebsd32_systrace_args.c
+++ b/sys/compat/freebsd32/freebsd32_systrace_args.c
@@ -2271,9 +2271,9 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
 		*n_args = 1;
 		break;
 	}
-	/* abort2 */
+	/* freebsd32_abort2 */
 	case 463: {
-		struct abort2_args *p = params;
+		struct freebsd32_abort2_args *p = params;
 		uarg[0] = (intptr_t)p->why; /* const char * */
 		iarg[1] = p->nargs; /* int */
 		uarg[2] = (intptr_t)p->args; /* uint32_t * */
@@ -7099,7 +7099,7 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
 			break;
 		};
 		break;
-	/* abort2 */
+	/* freebsd32_abort2 */
 	case 463:
 		switch (ndx) {
 		case 0:
@@ -10582,10 +10582,10 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
 		if (ndx == 0 || ndx == 1)
 			p = "int";
 		break;
-	/* abort2 */
+	/* freebsd32_abort2 */
 	case 463:
 		if (ndx == 0 || ndx == 1)
-			p = "int";
+			p = "void";
 		break;
 	/* thr_set_name */
 	case 464:
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index 90b93fbd64e8..a85b72c7fb6e 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -860,7 +860,7 @@
 461	AUE_MQ_NOTIFY	NOSTD	{ int freebsd32_kmq_notify(int mqd,	\
 				    const struct sigevent32 *sigev); }
 462	AUE_MQ_UNLINK	NOPROTO|NOSTD	{ int kmq_unlink(const char *path); }
-463	AUE_NULL	NOPROTO	{ int abort2(const char *why, int nargs, uint32_t *args); }
+463	AUE_NULL	STD	{ void freebsd32_abort2(const char *why, int nargs, uint32_t *args); }
 464	AUE_NULL 	NOPROTO	{ int thr_set_name(int32_t id, const char *name); }
 465	AUE_AIO_FSYNC	STD	{ int freebsd32_aio_fsync(int op, \
 				    struct aiocb32 *aiocbp); }
diff --git a/sys/conf/files b/sys/conf/files
index aceaac1bd95e..8854d827bcc3 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -379,6 +379,7 @@ cddl/dev/fbt/fbt.c			optional dtrace_fbt      | dtraceall compile-with "${FBT_C}
 cddl/dev/systrace/systrace.c		optional dtrace_systrace | dtraceall compile-with "${CDDL_C}"
 cddl/dev/prototype.c			optional dtrace_prototype | dtraceall compile-with "${CDDL_C}"
 fs/nfsclient/nfs_clkdtrace.c		optional dtnfscl nfscl   | dtraceall nfscl compile-with "${CDDL_C}"
+compat/freebsd32/freebsd32_abort2.c	optional compat_freebsd32
 compat/freebsd32/freebsd32_capability.c	optional compat_freebsd32
 compat/freebsd32/freebsd32_ioctl.c	optional compat_freebsd32
 compat/freebsd32/freebsd32_misc.c	optional compat_freebsd32
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 14be2425511d..2f1cfb2a25d2 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -735,10 +735,41 @@ struct abort2_args {
 
 int
 sys_abort2(struct thread *td, struct abort2_args *uap)
+{
+	void *uargs[16];
+	void **uargsp;
+	int error, nargs;
+
+	nargs = uap->nargs;
+	if (nargs < 0 || nargs > nitems(uargs))
+		nargs = -1;
+	uargsp = NULL;
+	if (nargs > 0) {
+		if (uap->args != NULL) {
+			error = copyin(uap->args, uargs,
+			    nargs * sizeof(void *));
+			if (error != 0)
+				nargs = -1;
+			else
+				uargsp = uargs;
+		} else
+			nargs = -1;
+	}
+	return (kern_abort2(td, uap->why, nargs, uargsp));
+}
+
+/*
+ * kern_abort2()
+ * Arguments:
+ *  why - user pointer to why
+ *  nargs - number of arguments copied or -1 if an error occured in copying
+ *  args - pointer to an array of pointers in kernel format
+ */
+int
+kern_abort2(struct thread *td, const char *why, int nargs, void **uargs)
 {
 	struct proc *p = td->td_proc;
 	struct sbuf *sb;
-	void *uargs[16];
 	int error, i, sig;
 
 	/*
@@ -756,29 +787,24 @@ sys_abort2(struct thread *td, struct abort2_args *uap)
 	 */
 	sig = SIGKILL;
 	/* Prevent from DoSes from user-space. */
-	if (uap->nargs < 0 || uap->nargs > 16)
+	if (nargs == -1)
 		goto out;
-	if (uap->nargs > 0) {
-		if (uap->args == NULL)
-			goto out;
-		error = copyin(uap->args, uargs, uap->nargs * sizeof(void *));
-		if (error != 0)
-			goto out;
-	}
+	KASSERT(nargs >= 0 && nargs <= 16, ("called with too many args (%d)",
+	    nargs));
 	/*
 	 * Limit size of 'reason' string to 128. Will fit even when
 	 * maximal number of arguments was chosen to be logged.
 	 */
-	if (uap->why != NULL) {
-		error = sbuf_copyin(sb, uap->why, 128);
+	if (why != NULL) {
+		error = sbuf_copyin(sb, why, 128);
 		if (error < 0)
 			goto out;
 	} else {
 		sbuf_printf(sb, "(null)");
 	}
-	if (uap->nargs > 0) {
+	if (nargs > 0) {
 		sbuf_printf(sb, "(");
-		for (i = 0;i < uap->nargs; i++)
+		for (i = 0;i < nargs; i++)
 			sbuf_printf(sb, "%s%p", i == 0 ? "" : ", ", uargs[i]);
 		sbuf_printf(sb, ")");
 	}
diff --git a/sys/sys/syscallsubr.h b/sys/sys/syscallsubr.h
index a10c84cd2ab7..5032df4be874 100644
--- a/sys/sys/syscallsubr.h
+++ b/sys/sys/syscallsubr.h
@@ -81,6 +81,8 @@ struct mmap_req {
 
 int	kern___getcwd(struct thread *td, char *buf, enum uio_seg bufseg,
 	    size_t buflen, size_t path_max);
+int	kern_abort2(struct thread *td, const char *why, int nargs,
+	    void **uargs);
 int	kern_accept(struct thread *td, int s, struct sockaddr **name,
 	    socklen_t *namelen, struct file **fp);
 int	kern_accept4(struct thread *td, int s, struct sockaddr **name,