source: rtems/testsuites/fstests/fsnofs01/init.c @ f08c7133

4.11
Last change on this file since f08c7133 was f08c7133, checked in by Sebastian Huber <sebastian.huber@…>, on 03/16/17 at 10:54:29

libio: Fix deadlock in location management

Perform a context-dependent deferred location release to avoid a
deadlock on the file system instance locks, for example during a
chdir().

Close #2936.

  • Property mode set to 100644
File size: 13.4 KB
Line 
1/*
2 * Copyright (c) 2012 embedded brains GmbH.  All rights reserved.
3 *
4 *  embedded brains GmbH
5 *  Obere Lagerstr. 30
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#define TESTS_USE_PRINTK
20#include "tmacros.h"
21
22#include <sys/stat.h>
23#include <sys/statvfs.h>
24#include <errno.h>
25#include <fcntl.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <utime.h>
29
30#include <rtems/libio_.h>
31
32const char rtems_test_name[] = "FSNOFS 1";
33
34static int node_count(const rtems_chain_control *chain)
35{
36  int count = 0;
37  const rtems_chain_node *current = rtems_chain_immutable_first(chain);
38  const rtems_chain_node *tail = rtems_chain_immutable_tail(chain);
39
40  while (current != tail) {
41    ++count;
42
43    current = rtems_chain_immutable_next(current);
44  }
45
46  return count;
47}
48
49static void rtems_test_assert_equal_to_null_loc(
50  const rtems_filesystem_location_info_t *local_loc
51)
52{
53  rtems_filesystem_global_location_t *null_loc =
54    &rtems_filesystem_global_location_null;
55
56  rtems_test_assert(null_loc->location.node_access == local_loc->node_access);
57  rtems_test_assert(null_loc->location.node_access_2 == local_loc->node_access_2);
58  rtems_test_assert(null_loc->location.handlers == local_loc->handlers);
59  rtems_test_assert(null_loc->location.mt_entry == local_loc->mt_entry);
60}
61
62static void test_initial_values(void)
63{
64  rtems_filesystem_global_location_t *null_loc =
65    &rtems_filesystem_global_location_null;
66  rtems_filesystem_mount_table_entry_t *null_mt = null_loc->location.mt_entry;
67  rtems_chain_control *loc_chain = &null_mt->location_chain;
68  rtems_chain_node *loc_node = &null_loc->location.mt_entry_node;
69
70  rtems_test_assert(node_count(loc_chain) == 1);
71  rtems_test_assert(rtems_chain_previous(loc_node) == rtems_chain_head(loc_chain));
72  rtems_test_assert(rtems_chain_next(loc_node) == rtems_chain_tail(loc_chain));
73  rtems_test_assert(null_mt->mt_point_node == null_loc);
74  rtems_test_assert(null_mt->mt_fs_root == null_loc);
75  rtems_test_assert(!null_mt->mounted);
76  rtems_test_assert(!null_mt->writeable);
77  rtems_test_assert(null_loc->reference_count == 4);
78}
79
80static void test_location_obtain(void)
81{
82  rtems_filesystem_global_location_t *global_loc = NULL;
83  rtems_filesystem_global_location_t *null_loc =
84    rtems_filesystem_global_location_obtain(&global_loc);
85  rtems_filesystem_mount_table_entry_t *null_mt = null_loc->location.mt_entry;
86  rtems_chain_control *loc_chain = &null_mt->location_chain;
87
88  rtems_test_assert(node_count(loc_chain) == 1);
89  rtems_test_assert(null_loc->reference_count == 5);
90
91  rtems_filesystem_global_location_release(null_loc, false);
92
93  rtems_test_assert(node_count(loc_chain) == 1);
94  rtems_test_assert(null_loc->reference_count == 4);
95}
96
97static void test_null_location_obtain(void)
98{
99  rtems_filesystem_global_location_t *null_loc =
100    rtems_filesystem_global_location_obtain_null();
101  rtems_filesystem_mount_table_entry_t *null_mt = null_loc->location.mt_entry;
102  rtems_chain_control *loc_chain = &null_mt->location_chain;
103
104  rtems_test_assert(node_count(loc_chain) == 1);
105  rtems_test_assert(null_loc->reference_count == 5);
106
107  rtems_filesystem_global_location_release(null_loc, false);
108
109  rtems_test_assert(node_count(loc_chain) == 1);
110  rtems_test_assert(null_loc->reference_count == 4);
111}
112
113static void test_null_location_replace(void)
114{
115  rtems_filesystem_global_location_t *null_loc =
116    &rtems_filesystem_global_location_null;
117  rtems_filesystem_mount_table_entry_t *null_mt = null_loc->location.mt_entry;
118  rtems_chain_control *loc_chain = &null_mt->location_chain;
119  rtems_filesystem_location_info_t local_loc;
120
121  rtems_test_assert(node_count(loc_chain) == 1);
122  rtems_test_assert(null_loc->reference_count == 4);
123  rtems_test_assert(rtems_filesystem_global_location_is_null(null_loc));
124
125  rtems_filesystem_location_copy(&local_loc, &null_loc->location);
126
127  rtems_test_assert(node_count(loc_chain) == 2);
128  rtems_test_assert(null_loc->reference_count == 4);
129
130  rtems_filesystem_location_detach(&local_loc);
131
132  rtems_test_assert(node_count(loc_chain) == 2);
133  rtems_test_assert(null_loc->reference_count == 4);
134  rtems_test_assert(rtems_filesystem_location_is_null(&local_loc));
135  rtems_test_assert_equal_to_null_loc(&local_loc);
136
137  rtems_filesystem_location_free(&local_loc);
138
139  rtems_test_assert(node_count(loc_chain) == 1);
140  rtems_test_assert(null_loc->reference_count == 4);
141}
142
143static void test_null_location_get_and_replace(void)
144{
145  rtems_filesystem_global_location_t *null_loc =
146    &rtems_filesystem_global_location_null;
147  rtems_filesystem_mount_table_entry_t *null_mt = null_loc->location.mt_entry;
148  rtems_chain_control *loc_chain = &null_mt->location_chain;
149  rtems_filesystem_location_info_t local_loc_0;
150  rtems_filesystem_location_info_t local_loc_1;
151
152  rtems_test_assert(node_count(loc_chain) == 1);
153  rtems_test_assert(null_loc->reference_count == 4);
154
155  rtems_filesystem_location_copy(&local_loc_0, &null_loc->location);
156
157  rtems_test_assert(node_count(loc_chain) == 2);
158  rtems_test_assert(null_loc->reference_count == 4);
159  rtems_test_assert_equal_to_null_loc(&local_loc_0);
160
161  rtems_filesystem_location_copy_and_detach(&local_loc_1, &local_loc_0);
162
163  rtems_test_assert(node_count(loc_chain) == 3);
164  rtems_test_assert(null_loc->reference_count == 4);
165  rtems_test_assert_equal_to_null_loc(&local_loc_0);
166  rtems_test_assert_equal_to_null_loc(&local_loc_1);
167
168  rtems_filesystem_location_free(&local_loc_0);
169
170  rtems_test_assert(node_count(loc_chain) == 2);
171  rtems_test_assert(null_loc->reference_count == 4);
172  rtems_test_assert_equal_to_null_loc(&local_loc_1);
173
174  rtems_filesystem_location_free(&local_loc_1);
175
176  rtems_test_assert(node_count(loc_chain) == 1);
177  rtems_test_assert(null_loc->reference_count == 4);
178}
179
180static void test_path_ops(void)
181{
182  int rv = 0;
183  long lrv = 0;
184  struct stat st;
185  struct statvfs stvfs;
186  char buf [32];
187  ssize_t n = 0;
188  const char *path = "/";
189  const struct utimbuf times;
190
191  errno = 0;
192  rv = open(path, O_RDONLY);
193  rtems_test_assert(rv == -1);
194  rtems_test_assert(errno == ENXIO);
195
196  errno = 0;
197  rv = chdir(path);
198  rtems_test_assert(rv == -1);
199  rtems_test_assert(errno == ENXIO);
200
201  errno = 0;
202  rv = chroot(path);
203  rtems_test_assert(rv == -1);
204  rtems_test_assert(errno == ENXIO);
205
206  errno = 0;
207  rv = mknod(path, S_IFREG, 0);
208  rtems_test_assert(rv == -1);
209  rtems_test_assert(errno == ENXIO);
210
211  errno = 0;
212  rv = mkdir(path, 0);
213  rtems_test_assert(rv == -1);
214  rtems_test_assert(errno == ENXIO);
215
216  errno = 0;
217  rv = mkfifo(path, 0);
218  rtems_test_assert(rv == -1);
219  rtems_test_assert(errno == ENXIO);
220
221  errno = 0;
222  rv = stat(path, &st);
223  rtems_test_assert(rv == -1);
224  rtems_test_assert(errno == ENXIO);
225
226  errno = 0;
227  rv = lstat(path, &st);
228  rtems_test_assert(rv == -1);
229  rtems_test_assert(errno == ENXIO);
230
231  errno = 0;
232  rv = statvfs(path, &stvfs);
233  rtems_test_assert(rv == -1);
234  rtems_test_assert(errno == ENXIO);
235
236  errno = 0;
237  n = readlink(path, buf, sizeof(buf));
238  rtems_test_assert(n == -1);
239  rtems_test_assert(errno == ENXIO);
240
241  errno = 0;
242  rv = chmod(path, 0);
243  rtems_test_assert(rv == -1);
244  rtems_test_assert(errno == ENXIO);
245
246  errno = 0;
247  rv = chown(path, 0, 0);
248  rtems_test_assert(rv == -1);
249  rtems_test_assert(errno == ENXIO);
250
251  errno = 0;
252  rv = lchown(path, 0, 0);
253  rtems_test_assert(rv == -1);
254  rtems_test_assert(errno == ENXIO);
255
256  errno = 0;
257  rv = rmdir(path);
258  rtems_test_assert(rv == -1);
259  rtems_test_assert(errno == ENXIO);
260
261  errno = 0;
262  rv = unlink(path);
263  rtems_test_assert(rv == -1);
264  rtems_test_assert(errno == ENXIO);
265
266  errno = 0;
267  rv = truncate(path, 0);
268  rtems_test_assert(rv == -1);
269  rtems_test_assert(errno == ENXIO);
270
271  errno = 0;
272  rv = access(path, 0);
273  rtems_test_assert(rv == -1);
274  rtems_test_assert(errno == ENXIO);
275
276  errno = 0;
277  lrv = pathconf(path, _PC_LINK_MAX);
278  rtems_test_assert(lrv == -1);
279  rtems_test_assert(errno == ENXIO);
280
281  errno = 0;
282  rv = link(path, path);
283  rtems_test_assert(rv == -1);
284  rtems_test_assert(errno == ENXIO);
285
286  errno = 0;
287  rv = symlink(path, path);
288  rtems_test_assert(rv == -1);
289  rtems_test_assert(errno == ENXIO);
290
291  errno = 0;
292  rv = rename(path, path);
293  rtems_test_assert(rv == -1);
294  rtems_test_assert(errno == ENXIO);
295
296  errno = 0;
297  rv = utime(path, &times);
298  rtems_test_assert(rv == -1);
299  rtems_test_assert(errno == ENXIO);
300}
301
302static void test_user_env(void)
303{
304  rtems_status_code sc = RTEMS_SUCCESSFUL;
305  rtems_filesystem_global_location_t *null_loc =
306    &rtems_filesystem_global_location_null;
307  rtems_filesystem_mount_table_entry_t *null_mt = null_loc->location.mt_entry;
308  rtems_chain_control *loc_chain = &null_mt->location_chain;
309
310  rtems_test_assert(node_count(loc_chain) == 1);
311  rtems_test_assert(null_loc->reference_count == 4);
312
313  sc = rtems_libio_set_private_env();
314  rtems_test_assert(sc == RTEMS_UNSATISFIED);
315
316  rtems_test_assert(node_count(loc_chain) == 1);
317  rtems_test_assert(null_loc->reference_count == 4);
318
319  rtems_libio_use_global_env();
320
321  rtems_test_assert(node_count(loc_chain) == 1);
322  rtems_test_assert(null_loc->reference_count == 4);
323}
324
325typedef struct {
326  int flags;
327  mode_t object_mode;
328  uid_t object_uid;
329  gid_t object_gid;
330  bool expected_ok;
331} check_access_case;
332
333#define FR RTEMS_FS_PERMS_READ
334#define FW RTEMS_FS_PERMS_WRITE
335#define FX RTEMS_FS_PERMS_EXEC
336
337#define UR S_IRUSR
338#define UW S_IWUSR
339#define UX S_IXUSR
340
341#define GR S_IRGRP
342#define GW S_IWGRP
343#define GX S_IXGRP
344
345#define OR S_IROTH
346#define OW S_IWOTH
347#define OX S_IXOTH
348
349static const check_access_case check_access_euid_0_cases[] = {
350  { 0,   0, 6, 7, true },
351  { FR,  0, 6, 7, false },
352  { FW,  0, 6, 7, false },
353  { FX,  0, 6, 7, false },
354  { FR, UR, 6, 7, true },
355  { FW, UW, 6, 7, true },
356  { FX, UX, 6, 7, true },
357  { FR, GR, 6, 7, false },
358  { FW, GW, 6, 7, false },
359  { FX, GX, 6, 7, false },
360  { FR, OR, 6, 7, false },
361  { FW, OW, 6, 7, false },
362  { FX, OX, 6, 7, false }
363};
364
365static const check_access_case check_access_egid_0_cases[] = {
366  { 0,   0, 6, 7, true },
367  { FR,  0, 6, 7, false },
368  { FW,  0, 6, 7, false },
369  { FX,  0, 6, 7, false },
370  { FR, UR, 6, 7, false },
371  { FW, UW, 6, 7, false },
372  { FX, UX, 6, 7, false },
373  { FR, GR, 6, 7, true },
374  { FW, GW, 6, 7, true },
375  { FX, GX, 6, 7, true },
376  { FR, OR, 6, 7, false },
377  { FW, OW, 6, 7, false },
378  { FX, OX, 6, 7, false }
379};
380
381static const check_access_case check_access_other_cases[] = {
382  { 0,   0, 3, 7, true },
383  { FR,  0, 3, 7, false },
384  { FW,  0, 3, 7, false },
385  { FX,  0, 3, 7, false },
386  { FR, UR, 3, 7, true },
387  { FW, UW, 3, 7, true },
388  { FX, UX, 3, 7, true },
389  { FR, GR, 3, 7, false },
390  { FW, GW, 3, 7, false },
391  { FX, GX, 3, 7, false },
392  { FR, OR, 3, 7, false },
393  { FW, OW, 3, 7, false },
394  { FX, OX, 3, 7, false },
395  { 0,   0, 6, 4, true },
396  { FR,  0, 6, 4, false },
397  { FW,  0, 6, 4, false },
398  { FX,  0, 6, 4, false },
399  { FR, UR, 6, 4, false },
400  { FW, UW, 6, 4, false },
401  { FX, UX, 6, 4, false },
402  { FR, GR, 6, 4, true },
403  { FW, GW, 6, 4, true },
404  { FX, GX, 6, 4, true },
405  { FR, OR, 6, 4, false },
406  { FW, OW, 6, 4, false },
407  { FX, OX, 6, 4, false },
408  { 0,   0, 6, 5, true },
409  { FR,  0, 6, 5, false },
410  { FW,  0, 6, 5, false },
411  { FX,  0, 6, 5, false },
412  { FR, UR, 6, 5, false },
413  { FW, UW, 6, 5, false },
414  { FX, UX, 6, 5, false },
415  { FR, GR, 6, 5, true },
416  { FW, GW, 6, 5, true },
417  { FX, GX, 6, 5, true },
418  { FR, OR, 6, 5, false },
419  { FW, OW, 6, 5, false },
420  { FX, OX, 6, 5, false },
421  { 0,   0, 6, 7, true },
422  { FR,  0, 6, 7, false },
423  { FW,  0, 6, 7, false },
424  { FX,  0, 6, 7, false },
425  { FR, UR, 6, 7, false },
426  { FW, UW, 6, 7, false },
427  { FX, UX, 6, 7, false },
428  { FR, GR, 6, 7, false },
429  { FW, GW, 6, 7, false },
430  { FX, GX, 6, 7, false },
431  { FR, OR, 6, 7, true },
432  { FW, OW, 6, 7, true },
433  { FX, OX, 6, 7, true }
434};
435
436static void check_access(const check_access_case *table, size_t n)
437{
438  size_t i;
439
440  for (i = 0; i < n; ++i) {
441    const check_access_case *cac = &table[i];
442    bool ok = rtems_filesystem_check_access(
443      cac->flags,
444      cac->object_mode,
445      cac->object_uid,
446      cac->object_gid
447    );
448
449    rtems_test_assert(ok == cac->expected_ok);
450  }
451}
452
453static void test_check_access(void)
454{
455  rtems_user_env_t *uenv = rtems_current_user_env_get();
456
457  rtems_test_assert(uenv->uid == 0);
458  rtems_test_assert(uenv->gid == 0);
459  rtems_test_assert(uenv->euid == 0);
460  rtems_test_assert(uenv->egid == 0);
461  rtems_test_assert(uenv->ngroups == 0);
462
463  uenv->uid = 1;
464  uenv->gid = 2;
465
466  check_access(
467    &check_access_euid_0_cases[0],
468    RTEMS_ARRAY_SIZE(check_access_euid_0_cases)
469  );
470
471  uenv->euid = 3;
472
473  check_access(
474    &check_access_egid_0_cases[0],
475    RTEMS_ARRAY_SIZE(check_access_egid_0_cases)
476  );
477
478  uenv->egid = 4;
479  uenv->ngroups = 1;
480  uenv->groups[0] = 5;
481
482  check_access(
483    &check_access_other_cases[0],
484    RTEMS_ARRAY_SIZE(check_access_other_cases)
485  );
486
487  uenv->uid = 0;
488  uenv->gid = 0;
489  uenv->euid = 0;
490  uenv->egid = 0;
491  uenv->ngroups = 0;
492}
493
494static void Init(rtems_task_argument arg)
495{
496  rtems_test_begink();
497
498  rtems_libio_init();
499
500  test_initial_values();
501  test_location_obtain();
502  test_null_location_obtain();
503  test_null_location_replace();
504  test_null_location_get_and_replace();
505  test_path_ops();
506  test_user_env();
507  test_check_access();
508
509  rtems_test_endk();
510  exit(0);
511}
512
513#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
514
515#define CONFIGURE_APPLICATION_DISABLE_FILESYSTEM
516
517#define CONFIGURE_MAXIMUM_TASKS 1
518
519#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
520
521#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
522
523#define CONFIGURE_INIT
524
525#include <rtems/confdefs.h>
Note: See TracBrowser for help on using the repository browser.