File: strace--syscall-limit.c

package info (click to toggle)
strace 6.13%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 71,488 kB
  • sloc: ansic: 176,497; sh: 9,675; makefile: 4,133; cpp: 885; awk: 353; perl: 267; exp: 62; sed: 9
file content (150 lines) | stat: -rw-r--r-- 3,180 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
 * Test --syscall-limit option.
 *
 * Copyright (c) 2023 The strace developers.
 * All rights reserved.
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include "tests.h"
#include "scno.h"

#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#ifndef PRINT_VALID
# define PRINT_VALID 1
#endif
#ifndef PRINT_INVALID
# define PRINT_INVALID 1
#endif
#ifndef PRINT_STATS
# define PRINT_STATS 0
#endif
#ifndef UNLINKAT_CNT
# define UNLINKAT_CNT 1
#endif
#ifndef TOTAL_CNT
# define TOTAL_CNT 3
#endif

static int
write_status(const char *name, int value)
{
	FILE *fp = fopen(name, "w");
	if (!fp)
		perror_msg_and_fail("fopen: %s", name);
	if (fprintf(fp, "%d\n", value) <= 0)
		perror_msg_and_fail("fprintf: %s", name);
	if (fclose(fp))
		perror_msg_and_fail("fclose: %s", name);
	fflush(stdout);
	return value;
}

static const char valid_path[] = ".";
static const char invalid_path[] = "invalid.dir";

static void
test_chdir(int pid, bool print)
{
	if (chdir(valid_path))
		perror_msg_and_fail("chdir: %s", valid_path);

	if (print) {
#if PRINT_VALID
		printf("%-5u chdir(\"%s\") = 0\n", pid, valid_path);
#else /* !PRINT_VALID */
		if (chdir(invalid_path) == 0)
			error_msg_and_fail("chdir: %s", invalid_path);
# if PRINT_INVALID
		printf("%-5u chdir(\"%s\") = %s\n", pid, invalid_path, sprintrc(-1));
# endif
#endif /* PRINT_VALID */
	} else {
		if (chdir(invalid_path) == 0)
			error_msg_and_fail("chdir: %s", invalid_path);
	}
}

static void
test_rmdir(int pid, bool print)
{
#ifndef AT_FDCWD
# define AT_FDCWD -100
#endif
#ifndef AT_REMOVEDIR
# define AT_REMOVEDIR 0x200
#endif
	if (syscall(__NR_unlinkat, AT_FDCWD, "invalid.dir", AT_REMOVEDIR) == 0)
		error_msg_and_fail("unlinkat: %s", invalid_path);
#if PRINT_INVALID
	if (print)
		printf("%-5u unlinkat(AT_FDCWD, \"%s\", AT_REMOVEDIR) = %s\n",
		       pid, invalid_path, sprintrc(-1));
#endif
}

int
main(void)
{
	int pid = getpid();

	test_chdir(pid, /* print */ true);

	fflush(stdout);
	pid_t child = fork();
	if (child < 0)
		perror_msg_and_fail("fork");

	if (child == 0) {
		int pid = getpid();

		test_rmdir(pid, /* print */ true);
		test_chdir(pid, /* print */ true);

		/*
		 * the tracer is expected to detach at this point
		 * if TOTAL_CNT < 4.
		 */

		test_rmdir(pid, /* print */ TOTAL_CNT > 3);

		exit(0);
	}

	int status;
	while ((waitpid(child, &status, 0)) != child) {
		if (errno == EINTR)
			continue;
		perror_msg_and_fail("waitpid: %d", child);
	}

	/* the tracer is expected to detach at this point */

	test_chdir(pid, /* print */ false);

#if PRINT_STATS
# if defined MPERS_IS_m32
	printf("System call usage summary for 32 bit mode:\n");
# endif
# if defined MPERS_IS_mx32
	printf("System call usage summary for x32 mode:\n");
# endif
	printf("%9s %s\n", "calls", "syscall");
	printf("--------- ----------------\n");
	printf("%9d %s\n", 2, "chdir");
	printf("%9d %s\n", UNLINKAT_CNT, "unlinkat");
	printf("--------- ----------------\n");
	printf("%9d %s\n", TOTAL_CNT, "total");
#endif /* PRINT_STATS */

	return write_status("parent_status",
			    WIFEXITED(status) ? WEXITSTATUS(status) : 1);
}