Page MenuHomeFreeBSD

tests/ptrace: Validate PT_SC_REMOTE with some tricky syscalls
ClosedPublic

Authored by markj on Sat, Jun 6, 12:10 AM.
Tags
None
Referenced Files
F159321914: D57485.id179322.diff
Fri, Jun 12, 8:57 PM
Unknown Object (File)
Thu, Jun 11, 8:42 PM
Unknown Object (File)
Thu, Jun 11, 11:41 AM
Unknown Object (File)
Wed, Jun 10, 12:21 PM
Unknown Object (File)
Mon, Jun 8, 7:55 PM
Unknown Object (File)
Sat, Jun 6, 7:36 AM
Unknown Object (File)
Sat, Jun 6, 1:12 AM
Subscribers

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 73722
Build 70605: arc lint + arc unit

Event Timeline

markj requested review of this revision.Sat, Jun 6, 12:10 AM

The exit tests hangs, as expected. I didn't try the patch yet.

This is what I used to test the async exit changes.

/*-
 * Copyright 2026 Konstantin Belousov <kib@FreeBSD.org>
 *
 * 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/types.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/syscall.h>
#include <sys/sysctl.h>
#include <sys/wait.h>
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static const char *
decode_wait_status(int status)
{
	static char c[128];
	char b[32];
	int first;

	c[0] = '\0';
	first = 1;
	if (WIFCONTINUED(status)) {
		first = 0;
		strlcat(c, "CONT", sizeof(c));
	}
	if (WIFEXITED(status)) {
		if (first)
			first = 0;
		else
			strlcat(c, ",", sizeof(c));
		snprintf(b, sizeof(b), "EXIT(%d)", WEXITSTATUS(status));
		strlcat(c, b, sizeof(c));
	}
	if (WIFSIGNALED(status)) {
		if (first)
			first = 0;
		else
			strlcat(c, ",", sizeof(c));
		snprintf(b, sizeof(b), "SIG(%s)", strsignal(WTERMSIG(status)));
		strlcat(c, b, sizeof(c));
		if (WCOREDUMP(status))
			strlcat(c, ",CORE", sizeof(c));
	}
	if (WIFSTOPPED(status)) {
		if (first)
			first = 0;
		else
			strlcat(c, ",", sizeof(c));
		snprintf(b, sizeof(b), "SIG(%s)", strsignal(WSTOPSIG(status)));
		strlcat(c, b, sizeof(c));
	}
	return (c);
}

int
main(void)
{
	struct ptrace_sc_remote pscr;
	syscallarg_t args[1];
	int status;
	pid_t pid;

	if ((pid = fork()) < 0) {
		perror("fork");
		return 1;
	}
	else if (pid == 0) {
		if (ptrace(PT_TRACE_ME, 0, NULL, 0) < 0) {
			perror("PT_TRACE_ME");
			_exit(1);
		}
		kill(getpid(), SIGSTOP);
		for (;;)
			sleep(1);
	}

	if (waitpid(pid, &status, 0) == -1) {
		perror("waitpid");
		return (-1);
	}
	assert(WIFSTOPPED(status));
	assert(WSTOPSIG(status) == SIGSTOP);

	memset(&pscr, 0, sizeof(pscr));
	pscr.pscr_syscall = SYS_exit;
	pscr.pscr_nargs = 1;
	pscr.pscr_args = args;
	args[0] = 66;
	if (ptrace(PT_SC_REMOTE, pid, (caddr_t)&pscr, sizeof(pscr)) < 0) {
		perror("PT_SC_REMOTE");
	} else {
		printf("remote exit %#lx errno %d\n",
		    pscr.pscr_ret.sr_retval[0],
		    pscr.pscr_ret.sr_error);
	}
	ptrace(PT_CONTINUE, pid, (caddr_t)1, SIGCONT);
	for (;;) {
		if (waitpid(pid, &status, 0) == -1) {
			perror("waitpid");
			exit(1);
		}
		printf("pid %d status %s\n", pid, decode_wait_status(status));
		if (WIFSTOPPED(status))
			ptrace(PT_CONTINUE, pid, (caddr_t)1, SIGCONT);
		else if (WIFSIGNALED(status))
			ptrace(PT_CONTINUE, pid, (caddr_t)1, 0/* XXX */);
		else if (WIFEXITED(status))
			break;
	}
	return (0);
}

I made the following changes/fixes to the exit test. Note that PT_SC_REMOTE does not lift the 'T' state.

The test passes afterward.

ATF_TC_WITHOUT_HEAD(ptrace__PT_SC_REMOTE_exit);
ATF_TC_BODY(ptrace__PT_SC_REMOTE_exit, tc)
{
	struct ptrace_sc_remote pscr;
	syscallarg_t args[1];
	pid_t fpid, wpid;
	int status;

	ATF_REQUIRE((fpid = fork()) != -1);
	if (fpid == 0) {
		trace_me();
		exit(66);
	}

	wpid = waitpid(fpid, &status, 0);
	REQUIRE_EQ(wpid, fpid);
	ATF_REQUIRE(WIFSTOPPED(status));
	REQUIRE_EQ(WSTOPSIG(status), SIGSTOP);

	args[0] = 42;
	pscr.pscr_syscall = SYS_exit;
	pscr.pscr_nargs = 1;
	pscr.pscr_args = args;
	ATF_REQUIRE(ptrace(PT_SC_REMOTE, fpid, (caddr_t)&pscr,
	    sizeof(pscr)) != -1);
	ATF_REQUIRE(pscr.pscr_ret.sr_error == 0);

	wpid = waitpid(fpid, &status, 0);
	REQUIRE_EQ(wpid, fpid);
	ATF_REQUIRE(WIFSTOPPED(status));
	ATF_REQUIRE(ptrace(PT_CONTINUE, fpid, (caddr_t)1,
	    SIGCONT) != -1);

	wpid = waitpid(fpid, &status, 0);
	REQUIRE_EQ(wpid, fpid);
	ATF_REQUIRE(WIFEXITED(status));
	REQUIRE_EQ(WEXITSTATUS(status), 42);
}

The target progress stops before actually exiting.

This revision is now accepted and ready to land.Mon, Jun 8, 5:08 PM

Add a couple of additional test scenarios.

This revision now requires review to proceed.Mon, Jun 8, 7:48 PM
This revision is now accepted and ready to land.Mon, Jun 8, 8:12 PM