Date: Wed, 20 May 2026 19:39:34 +0000 From: Mark Johnston <markj@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: fd24dd0b38a8 - releng/15.0 - ptrace: Fix validation of PT_SC_REMOTE arguments Message-ID: <6a0e0df6.39219.5b2bde77@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch releng/15.0 has been updated by markj: URL: https://cgit.FreeBSD.org/src/commit/?id=fd24dd0b38a8b96878fabda17988bed0917be494 commit fd24dd0b38a8b96878fabda17988bed0917be494 Author: Mark Johnston <markj@FreeBSD.org> AuthorDate: 2026-05-12 17:32:17 +0000 Commit: Mark Johnston <markj@FreeBSD.org> CommitDate: 2026-05-19 23:52:30 +0000 ptrace: Fix validation of PT_SC_REMOTE arguments - Fix an off-by-one in the system call number check. A value of SYS_MAXSYSCALL was permitted. - Validate the system call number after we've dealt with syscall(2)/__syscall(2), since they pass the syscall number as an argument. - When the syscall number is for syscall(2) or __syscall(2), we must make sure that nargs > 0 to avoid an underflow when shifting arguments down. Add regression tests. Approved by: so Security: FreeBSD-SA-26:21.ptrace Security: CVE-2026-45253 Fixes: 140ceb5d956b ("ptrace(2): add PT_SC_REMOTE remote syscall request") Reported by: Yuxiang Yang, Yizhou Zhao, Ao Wang, Xuewei Feng, Qi Li, and Ke Xu from Tsinghua University using GLM-5.1 from Z.ai Reviewed by: kib, emaste Differential Revision: https://reviews.freebsd.org/D56978 --- sys/kern/kern_sig.c | 17 +++++---- tests/sys/kern/ptrace_test.c | 85 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 76 insertions(+), 26 deletions(-) diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 8efc0886988b..1eac5cc2993f 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -2678,23 +2678,26 @@ ptrace_syscallreq(struct thread *td, struct proc *p, struct sysentvec *sv; struct sysent *se; register_t rv_saved[2]; + unsigned int sc; int error, nerror; - int sc; bool audited, sy_thr_static; - sv = p->p_sysent; - if (sv->sv_table == NULL || sv->sv_size < tsr->ts_sa.code) { - tsr->ts_ret.sr_error = ENOSYS; - return; - } - sc = tsr->ts_sa.code; if (sc == SYS_syscall || sc == SYS___syscall) { + if (tsr->ts_nargs == 0) { + tsr->ts_ret.sr_error = EINVAL; + return; + } sc = tsr->ts_sa.args[0]; memmove(&tsr->ts_sa.args[0], &tsr->ts_sa.args[1], sizeof(register_t) * (tsr->ts_nargs - 1)); } + sv = p->p_sysent; + if (sv->sv_table == NULL || sc >= sv->sv_size) { + tsr->ts_ret.sr_error = ENOSYS; + return; + } tsr->ts_sa.callp = se = &sv->sv_table[sc]; VM_CNT_INC(v_syscall); diff --git a/tests/sys/kern/ptrace_test.c b/tests/sys/kern/ptrace_test.c index fee0bd2ffa38..c1a5d226e990 100644 --- a/tests/sys/kern/ptrace_test.c +++ b/tests/sys/kern/ptrace_test.c @@ -4362,6 +4362,25 @@ ATF_TC_BODY(ptrace__procdesc_reparent_wait_child, tc) REQUIRE_EQ(close(pd), 0); } +static void +pt_sc_remote(pid_t pid, struct ptrace_sc_remote *pscr, int error, + syscallarg_t ret) +{ + pid_t wpid; + int status; + + ATF_REQUIRE(ptrace(PT_SC_REMOTE, pid, (caddr_t)pscr, sizeof(*pscr)) != + -1); + ATF_REQUIRE_EQ(pscr->pscr_ret.sr_error, error); + if (error == 0) + ATF_REQUIRE_EQ(pscr->pscr_ret.sr_retval[0], ret); + + wpid = waitpid(pid, &status, 0); + REQUIRE_EQ(wpid, pid); + ATF_REQUIRE(WIFSTOPPED(status)); + REQUIRE_EQ(WSTOPSIG(status), SIGSTOP); +} + /* * Try using PT_SC_REMOTE to get the PID of a traced child process. */ @@ -4386,35 +4405,62 @@ ATF_TC_BODY(ptrace__PT_SC_REMOTE_getpid, tc) pscr.pscr_syscall = SYS_getpid; pscr.pscr_nargs = 0; pscr.pscr_args = NULL; - ATF_REQUIRE(ptrace(PT_SC_REMOTE, fpid, (caddr_t)&pscr, sizeof(pscr)) != - -1); - ATF_REQUIRE_MSG(pscr.pscr_ret.sr_error == 0, - "remote getpid failed with error %d", pscr.pscr_ret.sr_error); - ATF_REQUIRE_MSG(pscr.pscr_ret.sr_retval[0] == fpid, - "unexpected return value %jd instead of %d", - (intmax_t)pscr.pscr_ret.sr_retval[0], fpid); - - wpid = waitpid(fpid, &status, 0); - REQUIRE_EQ(wpid, fpid); - ATF_REQUIRE(WIFSTOPPED(status)); - REQUIRE_EQ(WSTOPSIG(status), SIGSTOP); + pt_sc_remote(fpid, &pscr, 0, fpid); pscr.pscr_syscall = SYS_getppid; pscr.pscr_nargs = 0; pscr.pscr_args = NULL; - ATF_REQUIRE(ptrace(PT_SC_REMOTE, fpid, (caddr_t)&pscr, sizeof(pscr)) != - -1); - ATF_REQUIRE_MSG(pscr.pscr_ret.sr_error == 0, - "remote getppid failed with error %d", pscr.pscr_ret.sr_error); - ATF_REQUIRE_MSG(pscr.pscr_ret.sr_retval[0] == getpid(), - "unexpected return value %jd instead of %d", - (intmax_t)pscr.pscr_ret.sr_retval[0], fpid); + pt_sc_remote(fpid, &pscr, 0, getpid()); + + ATF_REQUIRE(ptrace(PT_DETACH, fpid, (caddr_t)1, 0) != -1); +} + +ATF_TC_WITHOUT_HEAD(ptrace__PT_SC_REMOTE_syscall_validation); +ATF_TC_BODY(ptrace__PT_SC_REMOTE_syscall_validation, tc) +{ + struct ptrace_sc_remote pscr; + quad_t code; + int status; + pid_t fpid, wpid; + + code = SYS_MAXSYSCALL; + + ATF_REQUIRE((fpid = fork()) != -1); + if (fpid == 0) { + trace_me(); + exit(0); + } wpid = waitpid(fpid, &status, 0); REQUIRE_EQ(wpid, fpid); ATF_REQUIRE(WIFSTOPPED(status)); REQUIRE_EQ(WSTOPSIG(status), SIGSTOP); + pscr.pscr_syscall = SYS_MAXSYSCALL; + pscr.pscr_nargs = 0; + pscr.pscr_args = NULL; + pt_sc_remote(fpid, &pscr, ENOSYS, 0); + + pscr.pscr_syscall = SYS_syscall; + pscr.pscr_nargs = 0; + pscr.pscr_args = NULL; + pt_sc_remote(fpid, &pscr, EINVAL, 0); + + pscr.pscr_syscall = SYS_syscall; + pscr.pscr_nargs = 1; + pscr.pscr_args = (syscallarg_t *)&code; + pt_sc_remote(fpid, &pscr, ENOSYS, 0); + + pscr.pscr_syscall = SYS___syscall; + pscr.pscr_nargs = 0; + pscr.pscr_args = NULL; + pt_sc_remote(fpid, &pscr, EINVAL, 0); + + pscr.pscr_syscall = SYS___syscall; + pscr.pscr_nargs = 1; + pscr.pscr_args = (syscallarg_t *)&code; + pt_sc_remote(fpid, &pscr, ENOSYS, 0); + ATF_REQUIRE(ptrace(PT_DETACH, fpid, (caddr_t)1, 0) != -1); } @@ -4657,6 +4703,7 @@ ATF_TP_ADD_TCS(tp) ATF_TP_ADD_TC(tp, ptrace__procdesc_wait_child); ATF_TP_ADD_TC(tp, ptrace__procdesc_reparent_wait_child); ATF_TP_ADD_TC(tp, ptrace__PT_SC_REMOTE_getpid); + ATF_TP_ADD_TC(tp, ptrace__PT_SC_REMOTE_syscall_validation); ATF_TP_ADD_TC(tp, ptrace__reap_kill_stopped); ATF_TP_ADD_TC(tp, ptrace__PT_ATTACH_no_EINTR); ATF_TP_ADD_TC(tp, ptrace__PT_DETACH_continued);home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a0e0df6.39219.5b2bde77>
