source: rtems/cpukit/libcsupport/src/chroot.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: 2.5 KB
Line 
1/**
2 * @file
3 *
4 * @brief Change Root Directory
5 * @ingroup libcsupport
6 */
7
8/*
9 *  Author: fernando.ruiz@ctv.es
10 *
11 *  COPYRIGHT (c) 1989-2008.
12 *  On-Line Applications Research Corporation (OAR).
13 *
14 *  Modifications to support reference counting in the file system are
15 *  Copyright (c) 2012 embedded brains GmbH.
16 *
17 *  The license and distribution terms for this file may be
18 *  found in the file LICENSE in this distribution or at
19 *  http://www.rtems.org/license/LICENSE.
20 */
21
22#if HAVE_CONFIG_H
23  #include "config.h"
24#endif
25
26#include <unistd.h>
27
28#include <rtems/libio_.h>
29
30int chroot( const char *path )
31{
32  int rv = 0;
33  rtems_status_code sc = RTEMS_SUCCESSFUL;
34  rtems_filesystem_eval_path_context_t ctx;
35  int eval_flags = RTEMS_FS_PERMS_EXEC
36    | RTEMS_FS_FOLLOW_LINK;
37  rtems_filesystem_location_info_t loc;
38  rtems_filesystem_global_location_t *new_current_loc;
39
40  /*
41   * We use the global environment for path evaluation.  This makes it possible
42   * to escape from a chroot environment referencing an unmounted file system.
43   */
44  rtems_filesystem_eval_path_start_with_root_and_current(
45    &ctx,
46    path,
47    strlen( path ),
48    eval_flags,
49    &rtems_global_user_env.root_directory,
50    &rtems_global_user_env.current_directory
51  );
52
53  rtems_filesystem_eval_path_extract_currentloc( &ctx, &loc );
54  new_current_loc = rtems_filesystem_location_transform_to_global( &loc );
55  if ( !rtems_filesystem_global_location_is_null( new_current_loc ) ) {
56    rtems_filesystem_global_location_t *new_root_loc =
57      rtems_filesystem_global_location_obtain( &new_current_loc );
58    mode_t type = rtems_filesystem_location_type( &new_root_loc->location );
59
60    if ( S_ISDIR( type ) ) {
61      sc = rtems_libio_set_private_env();
62      if (sc == RTEMS_SUCCESSFUL) {
63        rtems_filesystem_global_location_assign(
64          &rtems_filesystem_root,
65          new_root_loc
66        );
67        rtems_filesystem_global_location_assign(
68          &rtems_filesystem_current,
69          new_current_loc
70        );
71      } else {
72        if (sc != RTEMS_UNSATISFIED) {
73          errno = ENOMEM;
74        }
75        rv = -1;
76      }
77    } else {
78      rtems_filesystem_location_error( &new_root_loc->location, ENOTDIR );
79      rv = -1;
80    }
81
82    if ( rv != 0 ) {
83      rtems_filesystem_global_location_release( new_root_loc, true );
84    }
85  } else {
86    rv = -1;
87  }
88
89  rtems_filesystem_eval_path_cleanup( &ctx );
90
91  if ( rv != 0 ) {
92    rtems_filesystem_global_location_release( new_current_loc, false );
93  }
94
95  return rv;
96}
Note: See TracBrowser for help on using the repository browser.