1
2 /*
3 * Licensed Materials - Property of IBM
4 *
5 * trousers - An open source TCG Software Stack
6 *
7 * (C) Copyright International Business Machines Corp. 2004
8 *
9 */
10
11
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <string.h>
15
16 #include "trousers/tss.h"
17 #include "trousers_types.h"
18 #include "spi_utils.h"
19 #include "capabilities.h"
20 #include "memmgr.h"
21 #include "tsplog.h"
22 #include "obj.h"
23
24 static struct memTable *
__tspi_createTable()25 __tspi_createTable()
26 {
27 struct memTable *table = NULL;
28 /*
29 * No table has yet been created to hold the memory allocations of
30 * this context, so we need to create one
31 */
32 table = calloc(1, sizeof(struct memTable));
33 if (table == NULL) {
34 LogError("malloc of %zd bytes failed.", sizeof(struct memTable));
35 return NULL;
36 }
37 return (table);
38 }
39
40 /* caller needs to lock memtable lock */
41 struct memTable *
getTable(TSS_HCONTEXT tspContext)42 getTable(TSS_HCONTEXT tspContext)
43 {
44 struct memTable *tmp;
45
46 for (tmp = SpiMemoryTable; tmp; tmp = tmp->nextTable)
47 if (tmp->tspContext == tspContext)
48 return tmp;
49
50 return NULL;
51 }
52
53 /* caller needs to lock memtable lock */
54 static void
__tspi_addTable(struct memTable * new)55 __tspi_addTable(struct memTable *new)
56 {
57 struct memTable *tmp = SpiMemoryTable;
58
59 /* base case, this is the first table */
60 if (SpiMemoryTable == NULL) {
61 SpiMemoryTable = new;
62 return;
63 }
64
65 /* else add @new onto the end */
66 for (; tmp; tmp = tmp->nextTable)
67 if (tmp->nextTable == NULL) {
68 tmp->nextTable = new;
69 break;
70 }
71 }
72
73 /* caller needs to lock memtable lock and be sure the context mem slot for
74 * @tspContext exists before calling.
75 */
76 void
__tspi_addEntry(TSS_HCONTEXT tspContext,struct memEntry * new)77 __tspi_addEntry(TSS_HCONTEXT tspContext, struct memEntry *new)
78 {
79 struct memTable *tmp = getTable(tspContext);
80 struct memEntry *tmp_entry;
81
82 if (tmp == NULL) {
83 if ((tmp = __tspi_createTable()) == NULL)
84 return;
85 tmp->tspContext = tspContext;
86 __tspi_addTable(tmp);
87 }
88
89 tmp_entry = tmp->entries;
90
91 if (tmp->entries == NULL) {
92 tmp->entries = new;
93 return;
94 }
95
96 /* else tack @new onto the end */
97 for (; tmp_entry; tmp_entry = tmp_entry->nextEntry) {
98 if (tmp_entry->nextEntry == NULL) {
99 tmp_entry->nextEntry = new;
100 break;
101 }
102 }
103 }
104
105 /* caller needs to lock memtable lock */
106 TSS_RESULT
__tspi_freeTable(TSS_HCONTEXT tspContext)107 __tspi_freeTable(TSS_HCONTEXT tspContext)
108 {
109 struct memTable *prev = NULL, *index = NULL, *next = NULL;
110 struct memEntry *entry = NULL, *entry_next = NULL;
111
112 for(index = SpiMemoryTable; index; index = index->nextTable) {
113 next = index->nextTable;
114 if (index->tspContext == tspContext) {
115 for (entry = index->entries; entry; entry = entry_next) {
116 /* this needs to be set before we do free(entry) */
117 entry_next = entry->nextEntry;
118 free(entry->memPointer);
119 free(entry);
120 }
121
122 if (prev != NULL)
123 prev->nextTable = next;
124 else
125 SpiMemoryTable = NULL;
126
127 free(index);
128 break;
129 }
130 prev = index;
131 }
132
133 return TSS_SUCCESS;
134 }
135
136 TSS_RESULT
__tspi_freeEntry(struct memTable * table,void * pointer)137 __tspi_freeEntry(struct memTable *table, void *pointer)
138 {
139 struct memEntry *index = NULL;
140 struct memEntry *prev = NULL;
141 struct memEntry *toKill = NULL;
142
143 for (index = table->entries; index; prev = index, index = index->nextEntry) {
144 if (index->memPointer == pointer) {
145 toKill = index;
146 if (prev == NULL)
147 table->entries = toKill->nextEntry;
148 else
149 prev->nextEntry = toKill->nextEntry;
150
151 free(pointer);
152 free(toKill);
153 return TSS_SUCCESS;
154 }
155 }
156
157 return TSPERR(TSS_E_INVALID_RESOURCE);
158 }
159
160 TSS_RESULT
__tspi_add_mem_entry(TSS_HCONTEXT tspContext,void * allocd_mem)161 __tspi_add_mem_entry(TSS_HCONTEXT tspContext, void *allocd_mem)
162 {
163 struct memEntry *newEntry = calloc(1, sizeof(struct memEntry));
164 if (newEntry == NULL) {
165 LogError("malloc of %zd bytes failed.", sizeof(struct memEntry));
166 return TSPERR(TSS_E_OUTOFMEMORY);
167 }
168
169 newEntry->memPointer = allocd_mem;
170
171 MUTEX_LOCK(memtable_lock);
172
173 __tspi_addEntry(tspContext, newEntry);
174
175 MUTEX_UNLOCK(memtable_lock);
176
177 return TSS_SUCCESS;
178 }
179
180 /*
181 * calloc_tspi will be called by functions outside of this file. All locking
182 * is done here.
183 */
184 void *
calloc_tspi(TSS_HCONTEXT tspContext,UINT32 howMuch)185 calloc_tspi(TSS_HCONTEXT tspContext, UINT32 howMuch)
186 {
187 struct memTable *table = NULL;
188 struct memEntry *newEntry = NULL;
189
190 MUTEX_LOCK(memtable_lock);
191
192 table = getTable(tspContext);
193 if (table == NULL) {
194 if ((table = __tspi_createTable()) == NULL) {
195 MUTEX_UNLOCK(memtable_lock);
196 return NULL;
197 }
198 table->tspContext = tspContext;
199 __tspi_addTable(table);
200 }
201
202 newEntry = calloc(1, sizeof(struct memEntry));
203 if (newEntry == NULL) {
204 LogError("malloc of %zd bytes failed.", sizeof(struct memEntry));
205 MUTEX_UNLOCK(memtable_lock);
206 return NULL;
207 }
208
209 newEntry->memPointer = calloc(1, howMuch);
210 if (newEntry->memPointer == NULL) {
211 LogError("malloc of %d bytes failed.", howMuch);
212 free(newEntry);
213 MUTEX_UNLOCK(memtable_lock);
214 return NULL;
215 }
216
217 /* this call must happen inside the lock or else another thread could
218 * remove the context mem slot, causing a segfault
219 */
220 __tspi_addEntry(tspContext, newEntry);
221
222 MUTEX_UNLOCK(memtable_lock);
223
224 return newEntry->memPointer;
225 }
226
227 /*
228 * free_tspi will be called by functions outside of this file. All locking
229 * is done here.
230 */
231 TSS_RESULT
free_tspi(TSS_HCONTEXT tspContext,void * memPointer)232 free_tspi(TSS_HCONTEXT tspContext, void *memPointer)
233 {
234 struct memTable *index;
235 TSS_RESULT result;
236
237 MUTEX_LOCK(memtable_lock);
238
239 if (memPointer == NULL) {
240 result = __tspi_freeTable(tspContext);
241 MUTEX_UNLOCK(memtable_lock);
242 return result;
243 }
244
245 if ((index = getTable(tspContext)) == NULL) {
246 MUTEX_UNLOCK(memtable_lock);
247 /* Tspi_Context_FreeMemory checks that the TSP context is good before calling us,
248 * so we can be sure that the problem is with memPointer */
249 return TSPERR(TSS_E_INVALID_RESOURCE);
250 }
251
252 /* just free one entry */
253 result = __tspi_freeEntry(index, memPointer);
254
255 MUTEX_UNLOCK(memtable_lock);
256
257 return result;
258 }
259
260 /* definition for a memset that cannot be optimized away */
261 void * __no_optimize
__tspi_memset(void * s,int c,size_t n)262 __tspi_memset(void *s, int c, size_t n)
263 {
264 return memset(s, c, n);
265 }
266