Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 Jul 2026 22:41:42 +0000
From:      Konstantin Belousov <kib@FreeBSD.org>
To:        src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org
Subject:   git: fd5faa5629ae - main - ptrace(2): PT_SET_SC_RET request
Message-ID:  <6a595e26.22d4c.3c10e5c2@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by kib:

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

commit fd5faa5629aed98f4daee84063da3494c4d1eee9
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2026-07-15 02:23:17 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2026-07-16 22:22:55 +0000

    ptrace(2): PT_SET_SC_RET request
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D58247
---
 sys/compat/freebsd32/freebsd32_misc.c | 19 +++++++++++++++++++
 sys/kern/subr_syscall.c               | 12 ++++++++----
 sys/kern/sys_process.c                | 24 ++++++++++++++++++++++++
 sys/sys/proc.h                        |  1 +
 sys/sys/ptrace.h                      |  3 ++-
 5 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index e4a4f256feb4..e07000015d54 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -1005,6 +1005,16 @@ ptrace_sc_ret_to32(const struct ptrace_sc_ret *psr,
 	psr32->sr_error = psr->sr_error;
 }
 
+static void
+ptrace_sc_ret32_to_ret(const struct ptrace_sc_ret32 *psr32,
+    struct ptrace_sc_ret *psr)
+{
+	bzero(psr, sizeof(*psr));
+	psr->sr_retval[0] = psr32->sr_retval[0];
+	psr->sr_retval[1] = psr32->sr_retval[1];
+	psr->sr_error = psr32->sr_error;
+}
+
 int
 freebsd32_ptrace(struct thread *td, struct freebsd32_ptrace_args *uap)
 {
@@ -1051,6 +1061,15 @@ freebsd32_ptrace(struct thread *td, struct freebsd32_ptrace_args *uap)
 	case PT_GET_SC_ARGS:
 	case PT_GET_SC_RET:
 		break;
+	case PT_SET_SC_RET:
+		if (uap->data != sizeof(r32.psr)) {
+			error = EINVAL;
+		} else {
+			error = copyin(uap->addr, &r32.psr, sizeof(r32.psr));
+			if (error == 0)
+				ptrace_sc_ret32_to_ret(&r32.psr, &r.psr);
+		}
+		break;
 	case PT_LWPINFO:
 		if (uap->data > sizeof(r32.pl))
 			return (EINVAL);
diff --git a/sys/kern/subr_syscall.c b/sys/kern/subr_syscall.c
index 660170cc7a5f..9997a6b638f7 100644
--- a/sys/kern/subr_syscall.c
+++ b/sys/kern/subr_syscall.c
@@ -66,10 +66,11 @@ syscallenter(struct thread *td)
 	if (__predict_false(td->td_cowgen != atomic_load_int(&p->p_cowgen)))
 		thread_cow_update(td);
 	traced = (p->p_flag & P_TRACED) != 0;
-	if (__predict_false(traced || td->td_dbgflags & TDB_USERWR)) {
+	if (__predict_false(traced || (td->td_dbgflags & (TDB_USERWR |
+	    TDB_SET_SC_RET)) != 0)) {
 		PROC_LOCK(p);
 		MPASS((td->td_dbgflags & TDB_BOUNDARY) == 0);
-		td->td_dbgflags &= ~TDB_USERWR;
+		td->td_dbgflags &= ~(TDB_USERWR | TDB_SET_SC_RET);
 		if (traced)
 			td->td_dbgflags |= TDB_SCE;
 		PROC_UNLOCK(p);
@@ -97,7 +98,10 @@ syscallenter(struct thread *td)
 			ptracestop((td), SIGTRAP, NULL);
 		PROC_UNLOCK(p);
 
-		if ((td->td_dbgflags & TDB_USERWR) != 0) {
+		if ((td->td_dbgflags & TDB_SET_SC_RET) != 0) {
+			error = td->td_errno;
+			goto retval;
+		} else if ((td->td_dbgflags & TDB_USERWR) != 0) {
 			/*
 			 * Reread syscall number and arguments if debugger
 			 * modified registers or memory.
@@ -201,7 +205,7 @@ syscallenter(struct thread *td)
 	    td->td_retval[1]);
 	if (__predict_false(traced)) {
 		PROC_LOCK(p);
-		td->td_dbgflags &= ~(TDB_SCE | TDB_BOUNDARY);
+		td->td_dbgflags &= ~(TDB_SCE | TDB_BOUNDARY | TDB_SET_SC_RET);
 		PROC_UNLOCK(p);
 	}
 	(p->p_sysent->sv_set_syscall_retval)(td, error);
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index e10d1fc4b8be..d3f8e4c81669 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -752,6 +752,12 @@ sys_ptrace(struct thread *td, struct ptrace_args *uap)
 	case PT_GET_SC_ARGS:
 	case PT_GET_SC_RET:
 		break;
+	case PT_SET_SC_RET:
+		if (uap->data != sizeof(r.psr))
+			error = EINVAL;
+		else
+			error = copyin(uap->addr, &r.psr, sizeof(r.psr));
+		break;
 	case PT_GETREGS:
 		bzero(&r.reg, sizeof(r.reg));
 		break;
@@ -1340,6 +1346,24 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data)
 		    psr->sr_retval[1]);
 		break;
 
+	case PT_SET_SC_RET:
+		if ((td2->td_dbgflags & TDB_SCE) == 0
+#ifdef COMPAT_FREEBSD32
+		    || (wrap32 && !safe)
+#endif
+		    ) {
+			error = EINVAL;
+			break;
+		}
+		psr = addr;
+		td2->td_errno = psr->sr_error;
+		if (td2->td_errno == 0) {
+			td2->td_retval[0] = psr->sr_retval[0];
+			td2->td_retval[1] = psr->sr_retval[1];
+		}
+		td2->td_dbgflags |= TDB_SET_SC_RET;
+		break;
+
 	case PT_STEP:
 	case PT_CONTINUE:
 	case PT_TO_SCE:
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index 6736fa5bb5f9..9b98550b9f8c 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -531,6 +531,7 @@ enum {
 #define	TDB_BOUNDARY	0x00008000 /* ptracestop() at boundary */
 #define	TDB_COREDUMPREQ	0x00010000 /* Coredump request */
 #define	TDB_SCREMOTEREQ	0x00020000 /* Remote syscall request */
+#define	TDB_SET_SC_RET	0x00040000 /* PT_SET_SC_RET applied */
 
 /*
  * "Private" flags kept in td_pflags:
diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h
index 2ef52b22044c..2aa82ce07a1d 100644
--- a/sys/sys/ptrace.h
+++ b/sys/sys/ptrace.h
@@ -85,6 +85,7 @@
 #define	PT_GETREGSET	42	/* Get a target register set */
 #define	PT_SETREGSET	43	/* Set a target register set */
 #define	PT_SC_REMOTE	44	/* Execute a syscall */
+#define	PT_SET_SC_RET	45	/* Set (fake) syscall results */
 
 #define PT_FIRSTMACH    64	/* for machine-specific requests */
 #define	PT_LASTMACH     127
@@ -166,7 +167,7 @@ struct ptrace_lwpinfo32 {
 };
 #endif
 
-/* Argument structure for PT_GET_SC_RET. */
+/* Argument structure for PT_GET_SC_RET and PT_SET_SC_RET. */
 struct ptrace_sc_ret {
 	syscallarg_t	sr_retval[2];	/* Only valid if sr_error == 0. */
 	int		sr_error;


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a595e26.22d4c.3c10e5c2>