source: rtems/testsuites/libtests/syscall01/init.c @ f87ede5

4.115
Last change on this file since f87ede5 was f87ede5, checked in by Sebastian Huber <sebastian.huber@…>, on 01/15/15 at 13:13:19

libnetworking: Fix close of active sockets

Send a special event to notify tasks waiting for a socket state change
in case this socket gets closed. This prevents a use after free.

Close #785.

  • Property mode set to 100644
File size: 6.7 KB
Line 
1/*
2 * Copyright (c) 2012-2015 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Dornierstr. 4
6 *  82178 Puchheim
7 *  Germany
8 *  <rtems@embedded-brains.de>
9 *
10 * The license and distribution terms for this file may be
11 * found in the file LICENSE in this distribution or at
12 * http://www.rtems.org/license/LICENSE.
13 */
14
15#ifdef HAVE_CONFIG_H
16  #include "config.h"
17#endif
18
19#include "tmacros.h"
20
21#include <sys/select.h>
22#include <sys/socket.h>
23#include <sys/stat.h>
24#include <netinet/in.h>
25#include <errno.h>
26#include <fcntl.h>
27#include <unistd.h>
28
29#include <rtems/libio.h>
30#include <rtems/rtems_bsdnet.h>
31
32const char rtems_test_name[] = "SYSCALL 1";
33
34static const char open_driver_path [] = "/dev/open_driver";
35
36struct rtems_bsdnet_config rtems_bsdnet_config;
37
38typedef struct {
39  rtems_id main_task;
40  rtems_id close_task;
41  int fd;
42} test_context;
43
44static test_context test_instance;
45
46static void test_sync(void)
47{
48  int rv;
49  char buf [1];
50  ssize_t n;
51  int fd;
52
53  fd = open(open_driver_path, O_RDWR);
54  rtems_test_assert(fd >= 0);
55
56  errno = 0;
57  n = send(fd, buf, sizeof(buf), 0);
58  rtems_test_assert(n == -1);
59  rtems_test_assert(errno == ENOTSOCK);
60
61  errno = 0;
62  n = recv(fd, buf, sizeof(buf), 0);
63  rtems_test_assert(n == -1);
64  rtems_test_assert(errno == ENOTSOCK);
65
66  rv = close(fd);
67  rtems_test_assert(rv == 0);
68
69  fd = socket(PF_INET, SOCK_DGRAM, 0);
70  rtems_test_assert(fd >= 0);
71
72  errno = 0;
73  rv = fsync(fd);
74  rtems_test_assert(rv == -1);
75  rtems_test_assert(errno == EINVAL);
76
77  errno = 0;
78  rv = fdatasync(fd);
79  rtems_test_assert(rv == -1);
80  rtems_test_assert(errno == EINVAL);
81
82  rv = close(fd);
83  rtems_test_assert(rv == 0);
84}
85
86static void close_task(rtems_task_argument arg)
87{
88  test_context *ctx = (test_context *) arg;
89
90  while (true) {
91    rtems_status_code sc;
92    int rv;
93
94    rv = close(ctx->fd);
95    rtems_test_assert(rv == 0);
96
97    sc = rtems_event_transient_send(ctx->main_task);
98    rtems_test_assert(sc == RTEMS_SUCCESSFUL);
99  }
100}
101
102static void wait_for_close_task(void)
103{
104  rtems_status_code sc;
105
106  sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
107  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
108}
109
110static void test_accept_and_close(test_context *ctx)
111{
112  int rv;
113  int fd;
114  struct sockaddr_in addr;
115  socklen_t addrlen = sizeof(addr);
116
117  ctx->fd = socket(PF_INET, SOCK_STREAM, 0);
118  rtems_test_assert(ctx->fd >= 0);
119
120  rv = listen(ctx->fd, 1);
121  rtems_test_assert(rv == 0);
122
123  errno = 0;
124  fd = accept(ctx->fd, (struct sockaddr *) &addr, &addrlen);
125  rtems_test_assert(fd == -1);
126  rtems_test_assert(errno == ENXIO);
127
128  errno = 0;
129  fd = accept(ctx->fd, (struct sockaddr *) &addr, &addrlen);
130  rtems_test_assert(fd == -1);
131  rtems_test_assert(errno == EBADF);
132
133  wait_for_close_task();
134}
135
136static void test_connect_and_close(test_context *ctx)
137{
138  int rv;
139  struct sockaddr_in addr;
140  socklen_t addrlen = sizeof(addr);
141
142  ctx->fd = socket(PF_INET, SOCK_STREAM, 0);
143  rtems_test_assert(ctx->fd >= 0);
144
145  memset(&addr, 0, sizeof(addr));
146  addr.sin_family = AF_INET;
147  addr.sin_port = htons(1234);
148  addr.sin_addr.s_addr = htonl(INADDR_ANY);
149
150  errno = 0;
151  rv = connect(ctx->fd, (struct sockaddr *) &addr, addrlen);
152  rtems_test_assert(rv == -1);
153  rtems_test_assert(errno == ENXIO);
154
155  errno = 0;
156  rv = connect(ctx->fd, (struct sockaddr *) &addr, addrlen);
157  rtems_test_assert(rv == -1);
158  rtems_test_assert(errno == EBADF);
159
160  wait_for_close_task();
161}
162
163static void test_recv_and_close(test_context *ctx)
164{
165  int rv;
166  struct sockaddr_in addr;
167  socklen_t addrlen = sizeof(addr);
168  char buf[1];
169  ssize_t n;
170
171  ctx->fd = socket(PF_INET, SOCK_DGRAM, 0);
172  rtems_test_assert(ctx->fd >= 0);
173
174  memset(&addr, 0, sizeof(addr));
175  addr.sin_family = AF_INET;
176  addr.sin_port = htons(1234);
177  addr.sin_addr.s_addr = htonl(INADDR_ANY);
178
179  rv = bind(ctx->fd, (struct sockaddr *) &addr, addrlen);
180  rtems_test_assert(rv == 0);
181
182  errno = 0;
183  n = recv(ctx->fd, &buf[0], sizeof(buf), 0);
184  rtems_test_assert(n == -1);
185  rtems_test_assert(errno == ENXIO);
186
187  errno = 0;
188  n = recv(ctx->fd, &buf[0], sizeof(buf), 0);
189  rtems_test_assert(n == -1);
190  rtems_test_assert(errno == EBADF);
191
192  wait_for_close_task();
193}
194
195static void test_select_and_close(test_context *ctx)
196{
197  int rv;
198  struct sockaddr_in addr;
199  socklen_t addrlen = sizeof(addr);
200  int nfds;
201  struct fd_set set;
202
203  ctx->fd = socket(PF_INET, SOCK_DGRAM, 0);
204  rtems_test_assert(ctx->fd >= 0);
205
206  memset(&addr, 0, sizeof(addr));
207  addr.sin_family = AF_INET;
208  addr.sin_port = htons(1234);
209  addr.sin_addr.s_addr = htonl(INADDR_ANY);
210
211  rv = bind(ctx->fd, (struct sockaddr *) &addr, addrlen);
212  rtems_test_assert(rv == 0);
213
214  nfds = ctx->fd + 1;
215  FD_ZERO(&set);
216  FD_SET(ctx->fd, &set);
217
218  errno = 0;
219  rv = select(nfds, &set, NULL, NULL, NULL);
220  rtems_test_assert(rv == -1);
221  rtems_test_assert(errno == EBADF);
222
223  wait_for_close_task();
224}
225
226static void Init(rtems_task_argument arg)
227{
228  test_context *ctx = &test_instance;
229  rtems_status_code sc;
230  int rv;
231
232  TEST_BEGIN();
233
234  ctx->main_task = rtems_task_self();
235
236  sc = rtems_task_create(
237    rtems_build_name('C', 'L', 'O', 'S'),
238    2,
239    RTEMS_MINIMUM_STACK_SIZE,
240    RTEMS_DEFAULT_MODES,
241    RTEMS_DEFAULT_ATTRIBUTES,
242    &ctx->close_task
243  );
244  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
245
246  sc = rtems_task_start(
247    ctx->close_task,
248    close_task,
249    (rtems_task_argument) ctx
250  );
251  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
252
253  rv = rtems_bsdnet_initialize_network();
254  rtems_test_assert(rv == 0);
255
256  test_sync();
257  test_accept_and_close(ctx);
258  test_connect_and_close(ctx);
259  test_recv_and_close(ctx);
260  test_select_and_close(ctx);
261
262  sc = rtems_task_delete(ctx->close_task);
263  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
264
265  TEST_END();
266
267  rtems_test_exit(0);
268}
269
270static rtems_device_driver open_driver_initialize(
271  rtems_device_major_number major,
272  rtems_device_minor_number minor,
273  void *arg
274)
275{
276  rtems_status_code sc = rtems_io_register_name(open_driver_path, major, 0);
277  rtems_test_assert(sc == RTEMS_SUCCESSFUL);
278
279  return RTEMS_SUCCESSFUL;
280}
281
282static rtems_device_driver open_driver_open(
283  rtems_device_major_number major,
284  rtems_device_minor_number minor,
285  void *arg
286)
287{
288  rtems_libio_open_close_args_t *oc = arg;
289
290  oc->iop->data0 = 1;
291  oc->iop->data1 = (void *) 1;
292
293  return RTEMS_SUCCESSFUL;
294}
295
296#define OPEN_DRIVER { \
297  .initialization_entry = open_driver_initialize, \
298  .open_entry = open_driver_open \
299}
300
301#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
302#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
303#define CONFIGURE_APPLICATION_EXTRA_DRIVERS OPEN_DRIVER
304
305#define CONFIGURE_LIBIO_MAXIMUM_FILE_DESCRIPTORS 4
306
307#define CONFIGURE_MAXIMUM_TASKS 3
308
309#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
310
311#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
312
313#define CONFIGURE_INIT
314
315#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.