1 /*
2 * Test -Y/--decode-pids=comm option.
3 *
4 * Copyright (c) 2021 The strace developers.
5 * All rights reserved.
6 *
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
9
10 /*
11 * The executable built from this source file should
12 * have a long name (> 16) to test how strace reports
13 * the initial value of /proc/$pid/comm.
14 * Even if linux returns a longer name, strace should
15 * not crash.
16 */
17
18 #include "tests.h"
19 #include "scno.h"
20
21 #include <errno.h>
22 #include <signal.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <sys/prctl.h>
27 #include <unistd.h>
28 #include <sys/types.h>
29 #include <sys/wait.h>
30
31 #define NEW_NAME "0123456789abcdefghijklmnopqrstuvwxyz"
32
33 static int
34 do_default_action(void)
35 {
36 static const char proc_self_exe[] = "/proc/self/exe";
37 skip_if_unavailable(proc_self_exe);
38
39 char comm[sizeof(NEW_NAME)];
40 if (prctl(PR_GET_NAME, comm))
41 perror_msg_and_skip("PR_GET_NAME");
42 char ocomm[sizeof(comm)];
43 strcpy(ocomm, comm);
44
45 pid_t pid = getpid();
46 pid_t ppid = getppid();
47
48 printf("%u<%s> getppid() = %d<%s>\n", pid, comm, ppid, "strace");
49 fflush(stdout);
50
51 pid_t child = fork();
52 if (child < 0)
53 perror_msg_and_fail("fork");
54 else if (child == 0) {
55 pid = getpid();
56 ppid = getppid();
57 printf("%u<%s> getppid() = %d<%s>\n", pid, comm, ppid, ocomm);
58
59 const char *names[] = {
60 "foo\33[2Jbar",
61 "foo<bar>",
62 NEW_NAME,
63 };
64 for (size_t i = 0; i < ARRAY_SIZE(names); ++i) {
65 strcpy(comm, names[i]);
66 prctl(PR_SET_NAME, comm);
67 prctl(PR_GET_NAME, comm);
68
69 ppid = getppid();
70 printf("%u<", pid);
71 print_quoted_memory_ex(comm, strlen(comm), 0, "<>");
72 printf("> getppid() = %d<%s>\n", ppid, ocomm);
73
74 long rc = syscall(__NR_tgkill, pid, pid, SIGCONT);
75 printf("%u<", pid);
76 print_quoted_memory_ex(comm, strlen(comm), 0, "<>");
77 printf("> tgkill(%d<", pid);
78 print_quoted_memory_ex(comm, strlen(comm), 0, "<>");
79 printf(">, %d<", pid);
80 print_quoted_memory_ex(comm, strlen(comm), 0, "<>");
81 printf(">, SIGCONT) = %s\n", sprintrc(rc));
82 }
83
84 long rc = syscall(__NR_tgkill, ppid, ppid, SIGCONT);
85 printf("%u<%s> tgkill(%d<%s>, %d<%s>, SIGCONT) = %s\n",
86 pid, comm, ppid, ocomm, ppid, ocomm, sprintrc(rc));
87
88 fflush(stdout);
89 char *args[] = { (char *) "unused", (char *) "execve", NULL };
90 execve(proc_self_exe, args, NULL);
91 perror_msg_and_fail("execve: %s", proc_self_exe);
92 } else {
93 int status;
94 while ((waitpid(child, &status, 0)) != child) {
95 if (errno == EINTR)
96 continue;
97 perror_msg_and_fail("waitpid: %d", child);
98 }
99 printf("%u<exe> +++ exited with 0 +++\n", child);
100
101 ppid = getppid();
102 printf("%u<%s> getppid() = %d<%s>\n", pid, comm, ppid, "strace");
103 printf("%u<%s> +++ exited with 0 +++\n", pid, comm);
104 return WEXITSTATUS(status);
105 }
106 return 0;
107 }
108
109 static int
110 do_execve_action(int argc, char **argv)
111 {
112 return 0;
113 }
114
115 int
116 main(int argc, char **argv)
117 {
118 if (argc < 2)
119 return do_default_action();
120 else if (strcmp(argv[1], "execve") == 0)
121 return do_execve_action(argc, argv);
122 error_msg_and_fail("unexpected argument: %s", argv[1]);
123 }