source: rtems/cpukit/posix/src/shmopen.c @ 31e8f1b

Last change on this file since 31e8f1b was 31e8f1b, checked in by Joel Sherrill <joel@…>, on Mar 14, 2019 at 7:25:18 PM

shmopen.c: Fix logically unreachable code (Coverity ID: 1399706, 1399714)

Closes #3694.

  • Property mode set to 100644
File size: 7.4 KB
Line 
1/**
2 * @file
3 */
4
5/*
6 * Copyright (c) 2016 Gedare Bloom.
7 *
8 * The license and distribution terms for this file may be
9 * found in the file LICENSE in this distribution or at
10 * http://www.rtems.org/license/LICENSE.
11 */
12
13#if HAVE_CONFIG_H
14#include "config.h"
15#endif
16
17#include <sys/mman.h>
18#include <errno.h>
19#include <unistd.h>
20#include <fcntl.h>
21#include <sys/stat.h>
22
23#include <rtems/libio_.h>
24#include <rtems/seterr.h>
25
26#include <rtems/posix/shmimpl.h>
27#include <rtems/score/wkspace.h>
28#include <rtems/sysinit.h>
29
30static const rtems_filesystem_file_handlers_r shm_handlers;
31
32static int shm_fstat(
33  const rtems_filesystem_location_info_t *loc,
34  struct stat *buf
35)
36{
37  POSIX_Shm_Control *shm = loc_to_shm( loc );
38
39  if ( shm == NULL )
40    rtems_set_errno_and_return_minus_one( EIO );
41
42  /* mandatory for shm objects */
43  buf->st_uid = shm->uid;
44  buf->st_gid = shm->gid;
45  buf->st_size = shm->shm_object.size;
46  buf->st_mode = shm->mode;
47
48  /* optional for shm objects */
49  buf->st_atime = shm->atime;
50  buf->st_mtime = shm->mtime;
51  buf->st_ctime = shm->ctime;
52
53  return 0;
54}
55
56/* read() is unspecified for shared memory objects */
57static ssize_t shm_read( rtems_libio_t *iop, void *buffer, size_t count )
58{
59  ssize_t bytes_read;
60  POSIX_Shm_Control *shm = iop_to_shm( iop );
61
62  _Objects_Allocator_lock();
63  bytes_read = (*shm->shm_object.ops->object_read)(
64      &shm->shm_object,
65      buffer,
66      count
67  );
68  _POSIX_Shm_Update_atime( shm );
69
70  _Objects_Allocator_unlock();
71  return bytes_read;
72}
73
74static int shm_ftruncate( rtems_libio_t *iop, off_t length )
75{
76  int err;
77  POSIX_Shm_Control *shm = iop_to_shm( iop );
78
79  _Objects_Allocator_lock();
80
81  err = (*shm->shm_object.ops->object_resize)( &shm->shm_object, length );
82
83  if ( err != 0 ) {
84    _Objects_Allocator_unlock();
85    rtems_set_errno_and_return_minus_one( err );
86  }
87
88  _POSIX_Shm_Update_mtime_ctime( shm );
89
90  _Objects_Allocator_unlock();
91  return 0;
92}
93
94static int shm_close( rtems_libio_t *iop )
95{
96  POSIX_Shm_Control *shm = iop_to_shm( iop );
97  int err;
98
99  err = 0;
100
101  POSIX_Shm_Attempt_delete(shm);
102  iop->pathinfo.node_access = NULL;
103
104  if ( err != 0 ) {
105    rtems_set_errno_and_return_minus_one( err );
106  }
107  return 0;
108}
109
110static int shm_mmap(
111  rtems_libio_t *iop,
112  void** addr,
113  size_t len,
114  int prot,
115  off_t off
116)
117{
118  POSIX_Shm_Control *shm = iop_to_shm( iop );
119
120  _Objects_Allocator_lock();
121
122  *addr = (*shm->shm_object.ops->object_mmap)( &shm->shm_object, len, prot, off);
123  if ( *addr != NULL ) {
124    /* Keep a reference in the shared memory to prevent its removal. */
125    ++shm->reference_count;
126
127    /* Update atime */
128    _POSIX_Shm_Update_atime(shm);
129  } else {
130    _Objects_Allocator_unlock();
131    rtems_set_errno_and_return_minus_one( ENOMEM );
132  }
133
134  _Objects_Allocator_unlock();
135
136  return 0;
137}
138
139static inline POSIX_Shm_Control *shm_allocate(
140  const char *name_arg,
141  size_t name_len,
142  int oflag,
143  mode_t mode,
144  int *error
145)
146{
147  POSIX_Shm_Control *shm;
148  char *name;
149  struct timeval tv;
150
151  /* Reject any name without a leading slash. */
152  if ( name_arg[0] != '/' ) {
153    *error = EINVAL;
154    return NULL;
155  }
156
157  /* Only create the object if requested. */
158  if ( ( oflag & O_CREAT ) != O_CREAT ) {
159    *error = ENOENT;
160    return NULL;
161  }
162
163  name = _Workspace_String_duplicate( name_arg, name_len );
164  if ( name == NULL ) {
165    *error = ENOSPC;
166    return NULL;
167  }
168
169  shm = _POSIX_Shm_Allocate_unprotected();
170  if ( shm == NULL ) {
171    _Workspace_Free( name );
172    *error = ENFILE;
173    return NULL;
174  }
175
176  gettimeofday( &tv, 0 );
177
178  shm->reference_count = 1;
179  shm->shm_object.handle = NULL;
180  shm->shm_object.size = 0;
181  shm->shm_object.ops = &_POSIX_Shm_Object_operations;
182  shm->mode = mode & ~rtems_filesystem_umask;
183  shm->oflag = oflag;
184  shm->uid = geteuid();
185  shm->gid = getegid();
186  shm->atime = (time_t) tv.tv_sec;
187  shm->mtime = (time_t) tv.tv_sec;
188  shm->ctime = (time_t) tv.tv_sec;
189
190  _Objects_Open_string( &_POSIX_Shm_Information, &shm->Object, name );
191
192  return shm;
193}
194
195static inline bool shm_access_ok( POSIX_Shm_Control *shm, int oflag )
196{
197  int flags;
198
199  if ( (oflag & O_ACCMODE) == O_RDONLY ) {
200    flags = RTEMS_FS_PERMS_READ;
201  } else {
202    flags = RTEMS_FS_PERMS_WRITE;
203  }
204  return rtems_filesystem_check_access( flags, shm->mode, shm->uid, shm->gid );
205}
206
207static inline int shm_check_oflag( int oflag )
208{
209  if ( ( oflag & O_ACCMODE ) != O_RDONLY && ( oflag & O_ACCMODE ) != O_RDWR ) {
210    rtems_set_errno_and_return_minus_one( EACCES );
211  }
212
213  if ( ( oflag & ~( O_RDONLY | O_RDWR | O_CREAT | O_EXCL | O_TRUNC ) ) != 0 ) {
214    rtems_set_errno_and_return_minus_one( EACCES );
215  }
216
217  if ( ( oflag & O_TRUNC ) != 0 && ( oflag & O_ACCMODE ) != O_RDWR ) {
218    rtems_set_errno_and_return_minus_one( EACCES );
219  }
220  return 0;
221}
222
223int shm_open( const char *name, int oflag, mode_t mode )
224{
225  int err = 0;
226  int fd;
227  rtems_libio_t *iop;
228  POSIX_Shm_Control *shm;
229  size_t len;
230  Objects_Get_by_name_error obj_err;
231  unsigned int flags;
232
233  if ( shm_check_oflag( oflag ) != 0 ) {
234    return -1;
235  }
236
237  iop = rtems_libio_allocate();
238  if ( iop == NULL ) {
239    rtems_set_errno_and_return_minus_one( EMFILE );
240  }
241
242  _Objects_Allocator_lock();
243  shm = _POSIX_Shm_Get_by_name( name, &len, &obj_err );
244
245  if ( shm == NULL ) {
246    switch ( obj_err ) {
247      case OBJECTS_GET_BY_NAME_INVALID_NAME:
248        err = EINVAL;
249        break;
250
251      case OBJECTS_GET_BY_NAME_NAME_TOO_LONG:
252        err = ENAMETOOLONG;
253        break;
254
255      case OBJECTS_GET_BY_NAME_NO_OBJECT:
256      default:
257        shm = shm_allocate(name, len, oflag, mode, &err);
258        break;
259    }
260  } else { /* shm exists */
261    if ( ( oflag & ( O_EXCL | O_CREAT ) ) == ( O_EXCL | O_CREAT ) ) {
262      /* Request to create failed. */
263      err = EEXIST;
264    } else if ( !shm_access_ok( shm, oflag ) ) {
265      err = EACCES;
266    } else {
267      ++shm->reference_count;
268    }
269  }
270  _Objects_Allocator_unlock();
271  if ( err != 0 ) {
272    rtems_libio_free( iop );
273    rtems_set_errno_and_return_minus_one( err );
274  }
275
276  if ( oflag & O_TRUNC ) {
277    err = shm_ftruncate( iop, 0 );
278    (void) err; /* ignore truncate error */
279  }
280
281  fd = rtems_libio_iop_to_descriptor( iop );
282  iop->data0 = fd;
283  iop->data1 = shm;
284  iop->pathinfo.node_access = shm;
285  iop->pathinfo.handlers = &shm_handlers;
286  iop->pathinfo.mt_entry = &rtems_filesystem_null_mt_entry;
287  rtems_filesystem_location_add_to_mt_entry( &iop->pathinfo );
288
289  flags = LIBIO_FLAGS_CLOSE_ON_EXEC;
290  if ( (oflag & O_ACCMODE) == O_RDONLY ) {
291    flags |= LIBIO_FLAGS_READ;
292  } else {
293    flags |= LIBIO_FLAGS_READ_WRITE;
294  }
295
296  rtems_libio_iop_flags_initialize( iop, flags );
297
298  return fd;
299}
300
301static const rtems_filesystem_file_handlers_r shm_handlers = {
302  .open_h = rtems_filesystem_default_open,
303  .close_h = shm_close,
304  .read_h = shm_read,
305  .write_h = rtems_filesystem_default_write,
306  .ioctl_h = rtems_filesystem_default_ioctl,
307  .lseek_h = rtems_filesystem_default_lseek,
308  .fstat_h = shm_fstat,
309  .ftruncate_h = shm_ftruncate,
310  .fsync_h = rtems_filesystem_default_fsync_or_fdatasync,
311  .fdatasync_h = rtems_filesystem_default_fsync_or_fdatasync,
312  .fcntl_h = rtems_filesystem_default_fcntl,
313  .kqfilter_h = rtems_filesystem_default_kqfilter,
314  .mmap_h = shm_mmap,
315  .poll_h = rtems_filesystem_default_poll,
316  .readv_h = rtems_filesystem_default_readv,
317  .writev_h = rtems_filesystem_default_writev
318};
319
320static void _POSIX_Shm_Manager_initialization( void )
321{
322  _Objects_Initialize_information( &_POSIX_Shm_Information );
323}
324
325RTEMS_SYSINIT_ITEM(
326  _POSIX_Shm_Manager_initialization,
327  RTEMS_SYSINIT_POSIX_SHM,
328  RTEMS_SYSINIT_ORDER_MIDDLE
329);
Note: See TracBrowser for help on using the repository browser.