vfork_and_exec.c 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. #define _GNU_SOURCE
  2. #include <errno.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <sys/types.h>
  6. #include <sys/wait.h>
  7. #include <unistd.h>
  8. int main(int argc, const char** argv, const char** envp) {
  9. pid_t child_pid;
  10. /* duplicate STDOUT into newfd and pass it as exec_victim argument
  11. * (it will be inherited by exec_victim) */
  12. int newfd = dup(1);
  13. if (newfd < 0) {
  14. perror("dup failed");
  15. return 1;
  16. }
  17. char fd_argv[12];
  18. snprintf(fd_argv, 12, "%d", newfd);
  19. char* const new_argv[] = {"./exec_victim", fd_argv, NULL};
  20. /* set environment variable to test that it is inherited by exec_victim */
  21. int ret = setenv("IN_EXECVE", "1", 1);
  22. if (ret < 0) {
  23. perror("setenv failed");
  24. return 1;
  25. }
  26. child_pid = vfork();
  27. if (child_pid == 0) {
  28. /* child performs execve(exec_victim) */
  29. execv(new_argv[0], new_argv);
  30. perror("execve failed");
  31. return 1;
  32. } else if (child_pid > 0) {
  33. /* parent waits for child termination */
  34. int status;
  35. pid_t pid = wait(&status);
  36. if (pid < 0) {
  37. perror("wait failed");
  38. return 1;
  39. }
  40. if (WIFEXITED(status))
  41. printf("child exited with status: %d\n", WEXITSTATUS(status));
  42. } else {
  43. /* error */
  44. perror("fork failed");
  45. return 1;
  46. }
  47. puts("test completed successfully");
  48. return 0;
  49. }