1 /*
2  * Copyright (c) 2012 The Native Client Authors. All rights reserved.
3  * Use of this source code is governed by a BSD-style license that can be
4  * found in the LICENSE file.
5  */
6 
7 /*
8  * NaCl Service Runtime.  Directory descriptor abstraction.
9  */
10 
11 #include "native_client/src/include/portability.h"
12 
13 #include <stdlib.h>
14 #include <string.h>
15 
16 #include "native_client/src/trusted/desc/nacl_desc_base.h"
17 #include "native_client/src/trusted/desc/nacl_desc_invalid.h"
18 
19 #include "native_client/src/shared/platform/nacl_log.h"
20 #include "native_client/src/shared/platform/nacl_sync_checked.h"
21 
22 #include "native_client/src/trusted/service_runtime/internal_errno.h"
23 #include "native_client/src/trusted/service_runtime/nacl_config.h"
24 
25 /*
26  * Externalizing the invalid descriptor -- which shows up in untrusted
27  * user code as -1 -- loses flags and metadata.  No operations are
28  * ever be allowed for the invalid descriptor (the vtable entries are
29  * all *Unimplemented), so there is no opportunity for code to look at
30  * flags/metadata.
31  */
NaClDescInvalidExternalizeSize(struct NaClDesc * vself,size_t * nbytes,size_t * nhandles)32 static int NaClDescInvalidExternalizeSize(struct NaClDesc      *vself,
33                                           size_t               *nbytes,
34                                           size_t               *nhandles) {
35   UNREFERENCED_PARAMETER(vself);
36   *nbytes = 0;
37   *nhandles = 0;
38   return 0;
39 }
40 
NaClDescInvalidExternalize(struct NaClDesc * vself,struct NaClDescXferState * xfer)41 static int NaClDescInvalidExternalize(struct NaClDesc          *vself,
42                                       struct NaClDescXferState *xfer) {
43   UNREFERENCED_PARAMETER(vself);
44   UNREFERENCED_PARAMETER(xfer);
45   return 0;
46 }
47 
48 /*
49  * NaClDescInvalid is the subclass for the singleton invalid descriptor.
50  */
51 
52 static struct NaClDescVtbl const kNaClDescInvalidVtbl = {
53   {
54     NaClDescDtorNotImplemented,
55   },
56   NaClDescMapNotImplemented,
57   NaClDescReadNotImplemented,
58   NaClDescWriteNotImplemented,
59   NaClDescSeekNotImplemented,
60   NaClDescPReadNotImplemented,
61   NaClDescPWriteNotImplemented,
62   NaClDescFstatNotImplemented,
63   NaClDescFchdirNotImplemented,
64   NaClDescFchmodNotImplemented,
65   NaClDescFsyncNotImplemented,
66   NaClDescFdatasyncNotImplemented,
67   NaClDescFtruncateNotImplemented,
68   NaClDescGetdentsNotImplemented,
69   NaClDescInvalidExternalizeSize,
70   NaClDescInvalidExternalize,
71   NaClDescLockNotImplemented,
72   NaClDescTryLockNotImplemented,
73   NaClDescUnlockNotImplemented,
74   NaClDescWaitNotImplemented,
75   NaClDescTimedWaitAbsNotImplemented,
76   NaClDescSignalNotImplemented,
77   NaClDescBroadcastNotImplemented,
78   NaClDescSendMsgNotImplemented,
79   NaClDescRecvMsgNotImplemented,
80   NaClDescLowLevelSendMsgNotImplemented,
81   NaClDescLowLevelRecvMsgNotImplemented,
82   NaClDescConnectAddrNotImplemented,
83   NaClDescAcceptConnNotImplemented,
84   NaClDescPostNotImplemented,
85   NaClDescSemWaitNotImplemented,
86   NaClDescGetValueNotImplemented,
87   NaClDescSetMetadata,
88   NaClDescGetMetadata,
89   NaClDescSetFlags,
90   NaClDescGetFlags,
91   NaClDescIsattyNotImplemented,
92   NACL_DESC_INVALID,
93 };
94 
95 static struct NaClMutex *mutex = NULL;
96 static struct NaClDescInvalid *singleton;
97 
NaClDescInvalidInit(void)98 void NaClDescInvalidInit(void) {
99   mutex = (struct NaClMutex *) malloc(sizeof(*mutex));
100   if (NULL == mutex) {
101     NaClLog(LOG_FATAL, "Cannot allocate NaClDescInvalid mutex\n");
102   }
103   if (!NaClMutexCtor(mutex)) {
104     free(mutex);
105     mutex = NULL;
106     NaClLog(LOG_FATAL, "Cannot construct NaClDescInvalid mutex\n");
107   }
108 }
109 
NaClDescInvalidFini(void)110 void NaClDescInvalidFini(void) {
111   if (NULL != mutex) {
112     NaClMutexDtor(mutex);
113     free(mutex);
114     mutex = NULL;
115   }
116 }
117 
NaClDescInvalidMake(void)118 struct NaClDescInvalid const *NaClDescInvalidMake(void) {
119   NaClXMutexLock(mutex);
120   if (NULL == singleton) {
121     do {
122       /* Allocate an instance. */
123       singleton = (struct NaClDescInvalid *) malloc(sizeof(*singleton));
124       if (NULL == singleton) {
125         break;
126       }
127       /* Do the base class construction. */
128       if (!NaClDescCtor(&(singleton->base))) {
129         free(singleton);
130         singleton = NULL;
131         break;
132       }
133       /* Construct the derived class (simply set the vtbl). */
134       singleton->base.base.vtbl =
135           (struct NaClRefCountVtbl const *) &kNaClDescInvalidVtbl;
136     } while (0);
137   }
138   NaClXMutexUnlock(mutex);
139   /* If we reached this point and still have NULL == singleton there was an
140    * error in allocation or construction.  Return NULL to indicate error.
141    */
142   if (NULL == singleton) {
143     return NULL;
144   }
145 
146   return (struct NaClDescInvalid *) NaClDescRef(&(singleton->base));
147 }
148 
NaClDescInvalidInternalize(struct NaClDesc ** baseptr,struct NaClDescXferState * xfer)149 int NaClDescInvalidInternalize(struct NaClDesc               **baseptr,
150                                struct NaClDescXferState      *xfer) {
151   UNREFERENCED_PARAMETER(xfer);
152 
153   *baseptr = (struct NaClDesc *) NaClDescInvalidMake();
154 
155   return 0;
156 }
157