/* * stress_ptrace() * stress ptracing */ int stress_ptrace( uint64_t *const counter, const uint32_t instance, const uint64_t max_ops, const char *name) { pid_t pid; (void)instance; pid = fork(); if (pid < 0) { pr_failed_dbg(name, "fork"); return EXIT_FAILURE; } else if (pid == 0) { setpgid(0, pgrp); /* * Child to be traced, we abort if we detect * we are already being traced by someone else * as this makes life way too complex */ if (ptrace(PTRACE_TRACEME) != 0) { pr_fail(stderr, "%s: ptrace child being traced " "already, aborting\n", name); _exit(0); } /* Wait for parent to start tracing me */ kill(getpid(), SIGSTOP); /* * A simple mix of system calls */ while (opt_do_run) { (void)getppid(); (void)getgid(); (void)getegid(); (void)getuid(); (void)geteuid(); (void)getpgrp(); (void)time(NULL); } _exit(0); } else { /* Parent to do the tracing */ int status; setpgid(pid, pgrp); if (waitpid(pid, &status, 0) < 0) { pr_failed_dbg(name, "waitpid"); return EXIT_FAILURE; } if (ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0) { pr_failed_dbg(name, "ptrace"); return EXIT_FAILURE; } do { /* * We do two of the following per syscall, * one at the start, and one at the end to catch * the return. In this stressor we don't really * care which is which, we just care about counting * them */ if (stress_syscall_wait(name, pid)) break; (*counter)++; } while (opt_do_run && (!max_ops || *counter < max_ops)); /* Terminate child */ (void)kill(pid, SIGKILL); if (waitpid(pid, &status, 0) < 0) pr_failed_dbg(name, "waitpid"); } return EXIT_SUCCESS; }
/* * stress_ptrace() * stress ptracing */ static int stress_ptrace(const args_t *args) { pid_t pid; pid = fork(); if (pid < 0) { pr_fail_dbg("fork"); return EXIT_FAILURE; } else if (pid == 0) { (void)setpgid(0, g_pgrp); stress_parent_died_alarm(); /* * Child to be traced, we abort if we detect * we are already being traced by someone else * as this makes life way too complex */ if (ptrace(PTRACE_TRACEME) != 0) { pr_fail("%s: ptrace child being traced " "already, aborting\n", args->name); _exit(0); } /* Wait for parent to start tracing me */ (void)kill(getpid(), SIGSTOP); /* * A simple mix of system calls */ while (g_keep_stressing_flag) { pid_t pidtmp; gid_t gidtmp; uid_t uidtmp; time_t ttmp; pidtmp = getppid(); (void)pidtmp; #if defined(HAVE_GETPGRP) pidtmp = getpgrp(); (void)pidtmp; #endif gidtmp = getgid(); (void)gidtmp; gidtmp = getegid(); (void)gidtmp; uidtmp = getuid(); (void)uidtmp; uidtmp = geteuid(); (void)uidtmp; ttmp = time(NULL); (void)ttmp; } _exit(0); } else { /* Parent to do the tracing */ int status; (void)setpgid(pid, g_pgrp); if (shim_waitpid(pid, &status, 0) < 0) { if (errno != EINTR) { pr_fail_dbg("waitpid"); return EXIT_FAILURE; } return EXIT_SUCCESS; } if (ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) < 0) { pr_fail_dbg("ptrace"); return EXIT_FAILURE; } do { /* * We do two of the following per syscall, * one at the start, and one at the end to catch * the return. In this stressor we don't really * care which is which, we just care about counting * them */ if (stress_syscall_wait(args, pid)) break; inc_counter(args); } while (keep_stressing()); /* Terminate child */ (void)kill(pid, SIGKILL); if (shim_waitpid(pid, &status, 0) < 0) pr_fail_dbg("waitpid"); } return EXIT_SUCCESS; }