[Devel] [PATCH hci-8.1 v2 9/9] selftests/mm: do not lose doexec failures

Konstantin Khorenko khorenko at virtuozzo.com
Wed Oct 21 19:57:22 MSK 2026


Some doexec failures can go unreported:

- write() results are ignored. The clone race reports a failure by
  writing to a pipe, so a failed write turns it into a pass, and a
  failed wake-up write leaves a shared-mm child blocked forever. glibc
  warns about these with _FORTIFY_SOURCE.
- The allocation failure sweep prints the failing exec and calls
  _exit() without flushing stdout, so under a pipe the message is lost.
- The writes that disarm fail-nth are not checked, so injection could
  still hit the checks that follow a failed disarm.

Check every write(), abort when a race failure cannot be reported, and
flush stdout before that _exit().

https://virtuozzo.atlassian.net/browse/VSTOR-150234

Feature: oracle/mm: MADV_DOEXEC madvise() flag
Assisted-by: LLM
Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
---
 tools/testing/selftests/mm/doexec.c | 30 ++++++++++++++++++++++--------
 1 file changed, 22 insertions(+), 8 deletions(-)

diff --git a/tools/testing/selftests/mm/doexec.c b/tools/testing/selftests/mm/doexec.c
index 7e73a98e4ec2a..561e07b4444f0 100644
--- a/tools/testing/selftests/mm/doexec.c
+++ b/tools/testing/selftests/mm/doexec.c
@@ -441,7 +441,8 @@ static int shared_mm_exec(bool own_thread)
 		if (pthread_create(&thread, NULL, blocked_thread, &pipe_fd[0]))
 			return fail("pthread_create failed");
 		check_exec(ram, size, 1, false);
-		write(pipe_fd[1], "x", 1);
+		if (write(pipe_fd[1], "x", 1) != 1)
+			return fail_errno("write");
 		pthread_join(thread, NULL);
 		return KSFT_FAIL;
 	}
@@ -460,7 +461,10 @@ static int shared_mm_exec(bool own_thread)
 	} else {
 		ret = check_bytes(ram, size, 0x31) ? fail("contents lost") : KSFT_PASS;
 	}
-	write(pipe_fd[1], "x", 1);
+	if (write(pipe_fd[1], "x", 1) != 1) {
+		ret = fail_errno("write");
+		kill(pid, SIGKILL);
+	}
 	if (wait_child(pid))
 		ret = KSFT_FAIL;
 	if (ret)
@@ -966,6 +970,13 @@ struct clone_race {
 	atomic_uint rounds;
 };
 
+/* A failure that cannot reach the supervisor must still fail the test. */
+static void report_failure(struct clone_race *race)
+{
+	if (write(race->report, "x", 1) != 1)
+		abort();
+}
+
 static int clone_race_child(void *arg)
 {
 	struct clone_race *race = arg;
@@ -973,7 +984,7 @@ static int clone_race_child(void *arg)
 
 	for (i = 0; i < 8; i++) {
 		if (__atomic_load_n(race->ram, __ATOMIC_RELAXED) != 0x31) {
-			write(race->report, "x", 1);
+			report_failure(race);
 			return KSFT_FAIL;
 		}
 		usleep(1000);
@@ -989,7 +1000,7 @@ static void *clone_race_thread(void *arg)
 	pid_t pid;
 
 	if (stack == MAP_FAILED) {
-		write(race->report, "x", 1);
+		report_failure(race);
 		atomic_store(&race->rounds, 4);
 		return NULL;
 	}
@@ -998,9 +1009,9 @@ static void *clone_race_thread(void *arg)
 			    CLONE_VM | SIGCHLD, race);
 		if (pid >= 0) {
 			if (wait_child(pid))
-				write(race->report, "x", 1);
+				report_failure(race);
 		} else if (errno != EBUSY && errno != EINTR) {
-			write(race->report, "x", 1);
+			report_failure(race);
 		}
 		atomic_fetch_add(&race->rounds, 1);
 		usleep(1000);
@@ -1122,7 +1133,8 @@ static int allocation_failures(void)
 				_exit(fail_errno("fail-nth setup"));
 			err = check_exec_fd(exe, ram, size, stride);
 			/* Disarm before checking mappings or exiting. */
-			pwrite(fd, "0", 1, 0);
+			if (pwrite(fd, "0", 1, 0) != 1)
+				_exit(fail_errno("fail-nth disarm"));
 			for (i = 0; i < size; i += stride)
 				if (ram[i] != 0x31)
 					_exit(fail("contents lost by a failed exec"));
@@ -1135,6 +1147,7 @@ static int allocation_failures(void)
 			    err == E2BIG || err == ELIBBAD || err == EIO)
 				_exit(10);
 			ksft_print_msg("fail-nth %u: exec: %s\n", nth, strerror(err));
+			fflush(stdout);
 			_exit(KSFT_FAIL);
 		}
 		do {
@@ -2395,7 +2408,8 @@ int main(int argc, char **argv)
 		int fd = open("/proc/self/fail-nth", O_WRONLY);
 
 		if (fd >= 0) {
-			write(fd, "0", 1);
+			if (write(fd, "0", 1) != 1)
+				return fail_errno("fail-nth disarm");
 			close(fd);
 		}
 		if (!range_mapped(ram, size))

-- 
2.43.0



More information about the Devel mailing list