• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**************************************************************************
2  *
3  * Copyright (C) 2015 Red Hat Inc.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9  * and/or sell copies of the Software, and to permit persons to whom the
10  * Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included
13  * in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21  * OTHER DEALINGS IN THE SOFTWARE.
22  *
23  **************************************************************************/
24 #include <stdio.h>
25 #include <signal.h>
26 #include <stdbool.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <sys/un.h>
33 #include <fcntl.h>
34 
35 #include "util.h"
36 #include "vtest.h"
37 #include "vtest_protocol.h"
38 
vtest_open_socket(const char * path)39 static int vtest_open_socket(const char *path)
40 {
41     struct sockaddr_un un;
42     int sock;
43 
44     sock = socket(PF_UNIX, SOCK_STREAM, 0);
45     if (sock < 0) {
46 	return -1;
47     }
48 
49     memset(&un, 0, sizeof(un));
50     un.sun_family = AF_UNIX;
51 
52     snprintf(un.sun_path, sizeof(un.sun_path), "%s", path);
53 
54     unlink(un.sun_path);
55 
56     if (bind(sock, (struct sockaddr *)&un, sizeof(un)) < 0) {
57 	goto err;
58     }
59 
60     if (listen(sock, 1) < 0){
61 	goto err;
62     }
63 
64     return sock;
65  err:
66     close(sock);
67     return -1;
68 }
69 
wait_for_socket_accept(int sock)70 static int wait_for_socket_accept(int sock)
71 {
72     fd_set read_fds;
73     int new_fd;
74     int ret;
75     FD_ZERO(&read_fds);
76     FD_SET(sock, &read_fds);
77 
78     ret = select(sock + 1, &read_fds, NULL, NULL, NULL);
79     if (ret < 0)
80 	return ret;
81 
82     if (FD_ISSET(sock, &read_fds)) {
83 	new_fd = accept(sock, NULL, NULL);
84 	return new_fd;
85     }
86     return -1;
87 }
88 
run_renderer(int in_fd,int out_fd)89 static int run_renderer(int in_fd, int out_fd)
90 {
91     int ret;
92     uint32_t header[VTEST_HDR_SIZE];
93     bool inited = false;
94 again:
95     ret = vtest_wait_for_fd_read(in_fd);
96     if (ret < 0)
97       goto fail;
98 
99     ret = vtest_block_read(in_fd, &header, sizeof(header));
100 
101     if (ret == 8) {
102       if (!inited) {
103 	if (header[1] != VCMD_CREATE_RENDERER)
104 	  goto fail;
105 	ret = vtest_create_renderer(in_fd, out_fd, header[0]);
106 	inited = true;
107       }
108       vtest_poll();
109       switch (header[1]) {
110       case VCMD_GET_CAPS:
111 	ret = vtest_send_caps();
112 	break;
113       case VCMD_RESOURCE_CREATE:
114 	ret = vtest_create_resource();
115 	break;
116       case VCMD_RESOURCE_UNREF:
117 	ret = vtest_resource_unref();
118 	break;
119       case VCMD_SUBMIT_CMD:
120 	ret = vtest_submit_cmd(header[0]);
121 	break;
122       case VCMD_TRANSFER_GET:
123 	ret = vtest_transfer_get(header[0]);
124 	break;
125       case VCMD_TRANSFER_PUT:
126 	ret = vtest_transfer_put(header[0]);
127 	break;
128       case VCMD_RESOURCE_BUSY_WAIT:
129         vtest_renderer_create_fence();
130 	ret = vtest_resource_busy_wait();
131 	break;
132       case VCMD_GET_CAPS2:
133 	ret = vtest_send_caps2();
134 	break;
135       default:
136 	break;
137       }
138 
139       if (ret < 0) {
140 	goto fail;
141       }
142 
143       goto again;
144     }
145     if (ret <= 0) {
146       goto fail;
147     }
148 fail:
149     fprintf(stderr, "socket failed - closing renderer\n");
150     vtest_destroy_renderer();
151     close(in_fd);
152     return 0;
153 }
154 
main(int argc,char ** argv)155 int main(int argc, char **argv)
156 {
157     int ret, sock = -1, in_fd, out_fd;
158     pid_t pid;
159     bool do_fork = true, loop = true;
160     struct sigaction sa;
161 
162 #ifdef __AFL_LOOP
163 while (__AFL_LOOP(1000)) {
164 #endif
165 
166    if (argc > 1) {
167       if (!strcmp(argv[1], "--no-loop-or-fork")) {
168         do_fork = false;
169         loop = false;
170       } else if (!strcmp(argv[1], "--no-fork")) {
171 	do_fork = false;
172       } else {
173          ret = open(argv[1], O_RDONLY);
174          if (ret == -1) {
175             perror(0);
176             exit(1);
177          }
178          in_fd = ret;
179          ret = open("/dev/null", O_WRONLY);
180          if (ret == -1) {
181             perror(0);
182             exit(1);
183          }
184          out_fd = ret;
185          loop = false;
186          do_fork = false;
187          goto start;
188       }
189     }
190 
191     if (do_fork) {
192       sa.sa_handler = SIG_IGN;
193       sigemptyset(&sa.sa_mask);
194       sa.sa_flags = 0;
195       if (sigaction(SIGCHLD, &sa, 0) == -1) {
196 	perror(0);
197 	exit(1);
198       }
199     }
200 
201     sock = vtest_open_socket("/tmp/.virgl_test");
202 restart:
203     in_fd = wait_for_socket_accept(sock);
204     out_fd = in_fd;
205 
206 start:
207     if (do_fork) {
208       /* fork a renderer process */
209       switch ((pid = fork())) {
210       case 0:
211         run_renderer(in_fd, out_fd);
212 	exit(0);
213 	break;
214       case -1:
215       default:
216 	close(in_fd);
217         if (loop)
218            goto restart;
219       }
220     } else {
221       run_renderer(in_fd, out_fd);
222       if (loop)
223          goto restart;
224     }
225 
226     if (sock != -1)
227        close(sock);
228     if (in_fd != out_fd)
229        close(out_fd);
230 
231 #ifdef __AFL_LOOP
232 }
233 #endif
234 }
235