1*f82cc820Santon /* $OpenBSD: test-close.c,v 1.1 2020/06/29 18:25:37 anton Exp $ */
2*f82cc820Santon
3*f82cc820Santon /*
4*f82cc820Santon * Copyright (c) 2019 Anton Lindqvist <anton@openbsd.org>
5*f82cc820Santon *
6*f82cc820Santon * Permission to use, copy, modify, and distribute this software for any
7*f82cc820Santon * purpose with or without fee is hereby granted, provided that the above
8*f82cc820Santon * copyright notice and this permission notice appear in all copies.
9*f82cc820Santon *
10*f82cc820Santon * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11*f82cc820Santon * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12*f82cc820Santon * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13*f82cc820Santon * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14*f82cc820Santon * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15*f82cc820Santon * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16*f82cc820Santon * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*f82cc820Santon */
18*f82cc820Santon
19*f82cc820Santon #include <err.h>
20*f82cc820Santon #include <pthread.h>
21*f82cc820Santon #include <signal.h>
22*f82cc820Santon #include <unistd.h>
23*f82cc820Santon
24*f82cc820Santon #include "pipe.h"
25*f82cc820Santon
26*f82cc820Santon struct context {
27*f82cc820Santon volatile sig_atomic_t *c_alive;
28*f82cc820Santon int c_fd;
29*f82cc820Santon };
30*f82cc820Santon
31*f82cc820Santon static void *close_thread(void *);
32*f82cc820Santon static void sighandler(int);
33*f82cc820Santon
34*f82cc820Santon static volatile sig_atomic_t alive = 1;
35*f82cc820Santon
36*f82cc820Santon /*
37*f82cc820Santon * Regression during close(2) causing a use-after-free.
38*f82cc820Santon * The main thread repeatedly creates a new pipe which two other threads tries
39*f82cc820Santon * to close. By default, 100 iterations is performed.
40*f82cc820Santon */
41*f82cc820Santon int
test_close_race(void)42*f82cc820Santon test_close_race(void)
43*f82cc820Santon {
44*f82cc820Santon pthread_t th1, th2;
45*f82cc820Santon struct context ctx1, ctx2;
46*f82cc820Santon int nrounds = 100;
47*f82cc820Santon int pip[2];
48*f82cc820Santon int error;
49*f82cc820Santon
50*f82cc820Santon if (signal(SIGINT, sighandler) == SIG_ERR)
51*f82cc820Santon err(1, "signal");
52*f82cc820Santon
53*f82cc820Santon ctx1.c_alive = &alive;
54*f82cc820Santon ctx1.c_fd = 3;
55*f82cc820Santon error = pthread_create(&th1, NULL, close_thread, &ctx1);
56*f82cc820Santon if (error)
57*f82cc820Santon errc(1, error, "pthread_create");
58*f82cc820Santon ctx2.c_alive = &alive;
59*f82cc820Santon ctx2.c_fd = 4;
60*f82cc820Santon error = pthread_create(&th2, NULL, close_thread, &ctx2);
61*f82cc820Santon if (error)
62*f82cc820Santon errc(1, error, "pthread_create");
63*f82cc820Santon
64*f82cc820Santon while (alive) {
65*f82cc820Santon if (!infinity && nrounds-- == 0)
66*f82cc820Santon alive = 0;
67*f82cc820Santon
68*f82cc820Santon if (pipe(pip) == -1)
69*f82cc820Santon err(1, "pipe");
70*f82cc820Santon if (pip[0] != 3)
71*f82cc820Santon close(pip[0]);
72*f82cc820Santon if (pip[1] != 4)
73*f82cc820Santon close(pip[1]);
74*f82cc820Santon }
75*f82cc820Santon
76*f82cc820Santon error = pthread_join(th1, NULL);
77*f82cc820Santon if (error)
78*f82cc820Santon errc(1, error, "pthread_join");
79*f82cc820Santon error = pthread_join(th2, NULL);
80*f82cc820Santon if (error)
81*f82cc820Santon errc(1, error, "pthread_join");
82*f82cc820Santon
83*f82cc820Santon return 0;
84*f82cc820Santon }
85*f82cc820Santon
86*f82cc820Santon static void *
close_thread(void * arg)87*f82cc820Santon close_thread(void *arg)
88*f82cc820Santon {
89*f82cc820Santon const struct context *ctx = arg;
90*f82cc820Santon
91*f82cc820Santon while (*ctx->c_alive)
92*f82cc820Santon close(ctx->c_fd);
93*f82cc820Santon
94*f82cc820Santon return NULL;
95*f82cc820Santon }
96*f82cc820Santon
97*f82cc820Santon static void
sighandler(int signo)98*f82cc820Santon sighandler(int signo)
99*f82cc820Santon {
100*f82cc820Santon
101*f82cc820Santon alive = 0;
102*f82cc820Santon }
103