1 /*
2  * Copyright (C) 2013-2021 Canonical, Ltd.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * This code is a complete clean re-write of the stress tool by
19  * Colin Ian King <colin.king@canonical.com> and attempts to be
20  * backwardly compatible with the stress tool by Amos Waterland
21  * <apw@rossby.metr.ou.edu> but has more stress tests and more
22  * functionality.
23  *
24  */
25 #include "stress-ng.h"
26 
27 #define MSGVEC_SIZE		(4)
28 
29 static const stress_help_t help[] = {
30 	{ "S N", "sock N",		"start N workers exercising socket I/O" },
31 	{ NULL,	"sock-ops N",		"stop after N socket bogo operations" },
32 	{ NULL,	NULL,			NULL }
33 };
34 
35 #define VOID_RET(type, x)	\
36 do {				\
37 	type ret = x;		\
38 				\
39 	(void)ret;		\
40 } while(0)			\
41 
42 /*
43  *  stress_sockabuse_fd
44  *	exercise and abuse the fd
45  */
stress_sockabuse_fd(const int fd)46 static void stress_sockabuse_fd(const int fd)
47 {
48 	const uid_t uid = getuid();
49 	const gid_t gid = getgid();
50 	struct stat statbuf;
51 	void *ptr;
52 	int nfd;
53 	struct sockaddr addr;
54 	socklen_t addrlen;
55 #if defined(HAVE_FUTIMENS)
56 	struct timespec timespec[2];
57 #endif
58 
59 	(void)memset(&addr, 0, sizeof(addr));
60 	VOID_RET(int, connect(fd, &addr, sizeof(addr)));
61 	VOID_RET(int, shim_fdatasync(fd));
62 	VOID_RET(int, shim_fsync(fd));
63 	VOID_RET(int, shim_fallocate(fd, 0, 4096, 0));
64 	VOID_RET(int, fchdir(fd));
65 	VOID_RET(int, fchmod(fd, 0660));
66 	VOID_RET(int, fchown(fd, uid, gid));
67 #if defined(F_GETFD)
68 	VOID_RET(int, fcntl(fd, F_GETFD));
69 #endif
70 #if defined(HAVE_FLOCK) &&      \
71     defined(LOCK_UN)
72 	VOID_RET(int, flock(fd, LOCK_UN));
73 #endif
74 #if (defined(HAVE_SYS_XATTR_H) ||       \
75      defined(HAVE_ATTR_XATTR_H)) &&     \
76     defined(HAVE_SETXATTR) &&		\
77     defined(XATTR_CREATE)
78 	VOID_RET(ssize_t, shim_fsetxattr(fd, "test", "value", 5, XATTR_CREATE));
79 #endif
80 	VOID_RET(int, fstat(fd, &statbuf));
81 	VOID_RET(int, ftruncate(fd, 0));
82 #if (defined(HAVE_SYS_XATTR_H) ||       \
83      defined(HAVE_ATTR_XATTR_H)) &&     \
84     defined(HAVE_FLISTXATTR)
85 	{
86 		char list[4096];
87 
88 		VOID_RET(ssize_t, shim_flistxattr(fd, list, sizeof(list)));
89 	}
90 #endif
91 #if defined(HAVE_FUTIMENS)
92 	{
93 		struct timeval now;
94 
95 		if (gettimeofday(&now, NULL) == 0) {
96 			timespec[0].tv_sec = now.tv_sec;
97 			timespec[1].tv_sec = now.tv_sec;
98 
99 			timespec[0].tv_nsec = 1000 * now.tv_usec;
100 			timespec[1].tv_nsec = 1000 * now.tv_usec;
101 			VOID_RET(int, futimens(fd, timespec));
102 		}
103 	}
104 #endif
105 	addrlen = sizeof(addr);
106 	VOID_RET(int, getpeername(fd, &addr, &addrlen));
107 #if defined(FIONREAD)
108 	{
109 		int n;
110 
111 		VOID_RET(int, ioctl(fd, FIONREAD, &n));
112 	}
113 #endif
114 #if defined(SEEK_SET)
115 	VOID_RET(off_t, lseek(fd, 0, SEEK_SET));
116 #endif
117 	VOID_RET(int, shim_pidfd_send_signal(fd, SIGUSR1, NULL, 0));
118 	ptr = mmap(NULL, 4096, PROT_READ, MAP_SHARED, fd, 0);
119 	if (ptr != MAP_FAILED)
120 		(void)munmap(ptr, 4096);
121 	ptr = mmap(NULL, 4096, PROT_READ, MAP_PRIVATE, fd, 0);
122 	if (ptr != MAP_FAILED)
123 		(void)munmap(ptr, 4096);
124 	nfd = dup(fd);
125 	VOID_RET(ssize_t, shim_copy_file_range(fd, 0, nfd, 0, 16, 0));
126 	if (nfd >= 0)
127 		(void)close(nfd);
128 #if defined(HAVE_POSIX_FADVISE) &&	\
129     defined(POSIX_FADV_RANDOM)
130 	VOID_RET(int, posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM));
131 #endif
132 	VOID_RET(int, shim_sync_file_range(fd, 0, 1, 0));
133 #if defined(HAVE_FUTIMENS)
134 	(void)memset(&timespec, 0, sizeof(timespec));
135 #endif
136 }
137 
138 /*
139  *  stress_sockabuse_client()
140  *	client reader
141  */
stress_sockabuse_client(const stress_args_t * args,const pid_t ppid,const int socket_port)142 static void stress_sockabuse_client(
143 	const stress_args_t *args,
144 	const pid_t ppid,
145 	const int socket_port)
146 {
147 	struct sockaddr *addr;
148 
149 	(void)setpgid(0, g_pgrp);
150 	stress_parent_died_alarm();
151 	(void)sched_settings_apply(true);
152 
153 	do {
154 		char buf[SOCKET_BUF];
155 		int fd;
156 		ssize_t n;
157 		socklen_t addr_len = 0;
158 		uint64_t delay = 10000;
159 
160 retry:
161 		if (!keep_stressing_flag()) {
162 			(void)kill(getppid(), SIGALRM);
163 			_exit(EXIT_FAILURE);
164 		}
165 		if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
166 			pr_fail("%s: socket failed, errno=%d (%s)\n",
167 				args->name, errno, strerror(errno));
168 			/* failed, kick parent to finish */
169 			(void)kill(getppid(), SIGALRM);
170 			_exit(EXIT_FAILURE);
171 		}
172 
173 		stress_set_sockaddr(args->name, args->instance, ppid,
174 			AF_INET, socket_port,
175 			&addr, &addr_len, NET_ADDR_ANY);
176 		if (connect(fd, addr, addr_len) < 0) {
177 			(void)shutdown(fd, SHUT_RDWR);
178 			(void)close(fd);
179 			(void)shim_usleep(delay);
180 
181 			/* Backoff */
182 			delay += 10000;
183 			if (delay > 250000)
184 				delay = 250000;
185 			goto retry;
186 		}
187 
188 		n = recv(fd, buf, sizeof(buf), 0);
189 		if (n < 0) {
190 			if ((errno != EINTR) && (errno != ECONNRESET))
191 				pr_fail("%s: recv failed, errno=%d (%s)\n",
192 					args->name, errno, strerror(errno));
193 		}
194 
195 		stress_sockabuse_fd(fd);
196 
197 		(void)shutdown(fd, SHUT_RDWR);
198 		(void)close(fd);
199 	} while (keep_stressing(args));
200 
201 	/* Inform parent we're all done */
202 	(void)kill(getppid(), SIGALRM);
203 }
204 
205 /*
206  *  stress_sockabuse_server()
207  *	server writer
208  */
stress_sockabuse_server(const stress_args_t * args,const pid_t pid,const pid_t ppid,const int socket_port)209 static int stress_sockabuse_server(
210 	const stress_args_t *args,
211 	const pid_t pid,
212 	const pid_t ppid,
213 	const int socket_port)
214 {
215 	char buf[SOCKET_BUF];
216 	int fd, status;
217 	int so_reuseaddr = 1;
218 	socklen_t addr_len = 0;
219 	struct sockaddr *addr = NULL;
220 	uint64_t msgs = 0;
221 	int rc = EXIT_SUCCESS;
222 	double t1 = 0.0, t2 = 0.0, dt;
223 
224 	(void)setpgid(pid, g_pgrp);
225 
226 	if (stress_sig_stop_stressing(args->name, SIGALRM) < 0) {
227 		rc = EXIT_FAILURE;
228 		goto die;
229 	}
230 
231 	t1 = stress_time_now();
232 	do {
233 		int i;
234 
235 		if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
236 			rc = exit_status(errno);
237 			pr_fail("%s: socket failed, errno=%d (%s)\n",
238 				args->name, errno, strerror(errno));
239 			continue;
240 		}
241 		if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
242 			&so_reuseaddr, sizeof(so_reuseaddr)) < 0) {
243 			rc = exit_status(errno);
244 			pr_fail("%s: setsockopt failed, errno=%d (%s)\n",
245 				args->name, errno, strerror(errno));
246 			stress_sockabuse_fd(fd);
247 			(void)close(fd);
248 			continue;
249 		}
250 
251 		stress_set_sockaddr(args->name, args->instance, ppid,
252 			AF_INET, socket_port,
253 			&addr, &addr_len, NET_ADDR_ANY);
254 		if (bind(fd, addr, addr_len) < 0) {
255 			if (errno != EADDRINUSE) {
256 				rc = exit_status(errno);
257 				pr_fail("%s: bind failed, errno=%d (%s)\n",
258 					args->name, errno, strerror(errno));
259 			}
260 			stress_sockabuse_fd(fd);
261 			(void)close(fd);
262 			continue;
263 		}
264 		if (listen(fd, 10) < 0) {
265 			pr_fail("%s: listen failed, errno=%d (%s)\n",
266 				args->name, errno, strerror(errno));
267 			rc = EXIT_FAILURE;
268 
269 			stress_sockabuse_fd(fd);
270 			(void)close(fd);
271 			continue;
272 		}
273 
274 		for (i = 0; i < 16; i++) {
275 			int sfd;
276 
277 			if (!keep_stressing(args))
278 				break;
279 
280 			sfd = accept(fd, (struct sockaddr *)NULL, NULL);
281 			if (sfd >= 0) {
282 				struct sockaddr saddr;
283 				socklen_t len;
284 				int sndbuf;
285 				ssize_t n;
286 
287 				len = sizeof(saddr);
288 				if (getsockname(fd, &saddr, &len) < 0) {
289 					pr_fail("%s: getsockname failed, errno=%d (%s)\n",
290 						args->name, errno, strerror(errno));
291 					(void)close(sfd);
292 					break;
293 				}
294 				len = sizeof(sndbuf);
295 				if (getsockopt(fd, SOL_SOCKET, SO_SNDBUF, &sndbuf, &len) < 0) {
296 					pr_fail("%s: getsockopt failed, errno=%d (%s)\n",
297 						args->name, errno, strerror(errno));
298 					(void)close(sfd);
299 					break;
300 				}
301 				(void)memset(buf, 'A' + (get_counter(args) % 26), sizeof(buf));
302 
303 				n = send(sfd, buf, sizeof(buf), 0);
304 				if (n < 0) {
305 					if ((errno != EINTR) && (errno != EPIPE))
306 						pr_fail("%s: send failed, errno=%d (%s)\n",
307 							args->name, errno, strerror(errno));
308 					stress_sockabuse_fd(sfd);
309 					(void)close(sfd);
310 					break;
311 				} else {
312 					msgs++;
313 				}
314 				stress_sockabuse_fd(sfd);
315 				(void)close(sfd);
316 			}
317 		}
318 		inc_counter(args);
319 		stress_sockabuse_fd(fd);
320 		(void)close(fd);
321 	} while (keep_stressing(args));
322 	t2 = stress_time_now();
323 
324 die:
325 	if (pid) {
326 		(void)kill(pid, SIGKILL);
327 		(void)shim_waitpid(pid, &status, 0);
328 	}
329 	pr_dbg("%s: %" PRIu64 " messages sent\n", args->name, msgs);
330 	dt = t2 - t1;
331 	if (dt > 0.0) {
332 		stress_misc_stats_set(args->misc_stats, 0,
333 			"messages sent per sec", (double)msgs / dt);
334 	}
335 
336 	return rc;
337 }
338 
stress_sockabuse_sigpipe_handler(int signum)339 static void stress_sockabuse_sigpipe_handler(int signum)
340 {
341 	(void)signum;
342 
343 	keep_stressing_set_flag(false);
344 }
345 
346 /*
347  *  stress_sockabuse
348  *	stress by heavy socket I/O
349  */
stress_sockabuse(const stress_args_t * args)350 static int stress_sockabuse(const stress_args_t *args)
351 {
352 	pid_t pid, ppid = getppid();
353 	int socket_port = DEFAULT_SOCKABUSE_PORT + (int)args->instance;
354 	int rc = EXIT_SUCCESS;
355 
356 	pr_dbg("%s: process [%d] using socket port %d\n",
357 		args->name, (int)args->pid, socket_port);
358 
359 	if (stress_sighandler(args->name, SIGPIPE, stress_sockabuse_sigpipe_handler, NULL) < 0)
360 		return EXIT_NO_RESOURCE;
361 
362 	stress_set_proc_state(args->name, STRESS_STATE_RUN);
363 again:
364 	pid = fork();
365 	if (pid < 0) {
366 		if (stress_redo_fork(errno))
367 			goto again;
368 		if (!keep_stressing(args)) {
369 			rc = EXIT_SUCCESS;
370 			goto finish;
371 		}
372 		pr_fail("%s: fork failed, errno=%d (%s)\n",
373 			args->name, errno, strerror(errno));
374 		return EXIT_FAILURE;
375 	} else if (pid == 0) {
376 		stress_sockabuse_client(args, ppid,
377 			socket_port);
378 		_exit(rc);
379 	} else {
380 		rc = stress_sockabuse_server(args, pid, ppid,
381 			socket_port);
382 	}
383 finish:
384 	stress_set_proc_state(args->name, STRESS_STATE_DEINIT);
385 
386 	return rc;
387 }
388 
389 stressor_info_t stress_sockabuse_info = {
390 	.stressor = stress_sockabuse,
391 	.class = CLASS_NETWORK | CLASS_OS,
392 	.help = help
393 };
394