Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

kselftest/arm64: Add a test for vfork() with GCS

Ensure that we've got at least some coverage of the special cases around
vfork() by adding a test case in basic-gcs doing the same thing as the
plain fork() one - vfork(), do a few checks and then return to the parent.

Signed-off-by: Mark Brown <broonie@kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Link: https://lore.kernel.org/r/20250703-arm64-gcs-vfork-exit-v3-3-1e9a9d2ddbbe@kernel.org
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>

authored by

Mark Brown and committed by
Thomas Weißschuh
1536aa0f 696bf157

+63
+63
tools/testing/selftests/arm64/gcs/basic-gcs.c
··· 298 298 return pass; 299 299 } 300 300 301 + /* A vfork()ed process can run and exit */ 302 + static bool test_vfork(void) 303 + { 304 + unsigned long child_mode; 305 + int ret, status; 306 + pid_t pid; 307 + bool pass = true; 308 + 309 + pid = vfork(); 310 + if (pid == -1) { 311 + ksft_print_msg("vfork() failed: %d\n", errno); 312 + pass = false; 313 + goto out; 314 + } 315 + if (pid == 0) { 316 + /* 317 + * In child, make sure we can call a function, read 318 + * the GCS pointer and status and then exit. 319 + */ 320 + valid_gcs_function(); 321 + get_gcspr(); 322 + 323 + ret = my_syscall5(__NR_prctl, PR_GET_SHADOW_STACK_STATUS, 324 + &child_mode, 0, 0, 0); 325 + if (ret == 0 && !(child_mode & PR_SHADOW_STACK_ENABLE)) { 326 + ksft_print_msg("GCS not enabled in child\n"); 327 + ret = EXIT_FAILURE; 328 + } 329 + 330 + _exit(ret); 331 + } 332 + 333 + /* 334 + * In parent, check we can still do function calls then check 335 + * on the child. 336 + */ 337 + valid_gcs_function(); 338 + 339 + ksft_print_msg("Waiting for child %d\n", pid); 340 + 341 + ret = waitpid(pid, &status, 0); 342 + if (ret == -1) { 343 + ksft_print_msg("Failed to wait for child: %d\n", 344 + errno); 345 + return false; 346 + } 347 + 348 + if (!WIFEXITED(status)) { 349 + ksft_print_msg("Child exited due to signal %d\n", 350 + WTERMSIG(status)); 351 + pass = false; 352 + } else if (WEXITSTATUS(status)) { 353 + ksft_print_msg("Child exited with status %d\n", 354 + WEXITSTATUS(status)); 355 + pass = false; 356 + } 357 + 358 + out: 359 + 360 + return pass; 361 + } 362 + 301 363 typedef bool (*gcs_test)(void); 302 364 303 365 static struct { ··· 376 314 { "enable_invalid", enable_invalid, true }, 377 315 { "map_guarded_stack", map_guarded_stack }, 378 316 { "fork", test_fork }, 317 + { "vfork", test_vfork }, 379 318 }; 380 319 381 320 int main(void)