xref: /optee_os/core/tee/tee_fs_rpc.c (revision b1469ba0bfd0371eb52bd50f5c52eeda7a8f5f1e)
1 /*
2  * Copyright (c) 2016, Linaro Limited
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <assert.h>
29 #include <kernel/msg_param.h>
30 #include <kernel/tee_misc.h>
31 #include <kernel/thread.h>
32 #include <mm/core_memprot.h>
33 #include <optee_msg_supplicant.h>
34 #include <stdlib.h>
35 #include <string_ext.h>
36 #include <string.h>
37 #include <tee/tee_fs.h>
38 #include <tee/tee_fs_rpc.h>
39 #include <tee/tee_pobj.h>
40 #include <tee/tee_svc_storage.h>
41 #include <trace.h>
42 #include <util.h>
43 
44 struct tee_fs_dir {
45 	int nw_dir;
46 	struct tee_fs_dirent d;
47 };
48 
49 static TEE_Result operation_commit(struct tee_fs_rpc_operation *op)
50 {
51 	return thread_rpc_cmd(op->id, op->num_params, op->params);
52 }
53 
54 static TEE_Result operation_open(uint32_t id, unsigned int cmd,
55 				 struct tee_pobj *po, int *fd)
56 {
57 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
58 	struct mobj *mobj;
59 	TEE_Result res;
60 	void *va;
61 	uint64_t cookie;
62 
63 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &mobj, &cookie);
64 	if (!va)
65 		return TEE_ERROR_OUT_OF_MEMORY;
66 
67 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
68 	op.params[0].u.value.a = cmd;
69 
70 	if (!msg_param_init_memparam(op.params + 1, mobj, 0, TEE_FS_NAME_MAX,
71 				     cookie, MSG_PARAM_MEM_DIR_IN))
72 		return TEE_ERROR_BAD_STATE;
73 
74 	res = tee_svc_storage_create_filename(va, TEE_FS_NAME_MAX,
75 					      po, po->temporary);
76 	if (res != TEE_SUCCESS)
77 		return res;
78 
79 	op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
80 
81 	res = operation_commit(&op);
82 	if (res == TEE_SUCCESS)
83 		*fd = op.params[2].u.value.a;
84 
85 	return res;
86 }
87 
88 TEE_Result tee_fs_rpc_open(uint32_t id, struct tee_pobj *po, int *fd)
89 {
90 	return operation_open(id, OPTEE_MRF_OPEN, po, fd);
91 }
92 
93 TEE_Result tee_fs_rpc_create(uint32_t id, struct tee_pobj *po, int *fd)
94 {
95 	return operation_open(id, OPTEE_MRF_CREATE, po, fd);
96 }
97 
98 static TEE_Result operation_open_dfh(uint32_t id, unsigned int cmd,
99 				 const struct tee_fs_dirfile_fileh *dfh,
100 				 int *fd)
101 {
102 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
103 	struct mobj *mobj;
104 	TEE_Result res;
105 	void *va;
106 	uint64_t cookie;
107 
108 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &mobj, &cookie);
109 	if (!va)
110 		return TEE_ERROR_OUT_OF_MEMORY;
111 
112 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
113 	op.params[0].u.value.a = cmd;
114 
115 	if (!msg_param_init_memparam(op.params + 1, mobj, 0, TEE_FS_NAME_MAX,
116 				     cookie, MSG_PARAM_MEM_DIR_IN))
117 		return TEE_ERROR_BAD_STATE;
118 
119 	res = tee_svc_storage_create_filename_dfh(va, TEE_FS_NAME_MAX, dfh);
120 	if (res != TEE_SUCCESS)
121 		return res;
122 
123 	op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
124 
125 	res = operation_commit(&op);
126 	if (res == TEE_SUCCESS)
127 		*fd = op.params[2].u.value.a;
128 
129 	return res;
130 }
131 
132 
133 
134 TEE_Result tee_fs_rpc_open_dfh(uint32_t id,
135 			       const struct tee_fs_dirfile_fileh *dfh, int *fd)
136 {
137 	return operation_open_dfh(id, OPTEE_MRF_OPEN, dfh, fd);
138 }
139 
140 TEE_Result tee_fs_rpc_create_dfh(uint32_t id,
141 				 const struct tee_fs_dirfile_fileh *dfh,
142 				 int *fd)
143 {
144 	return operation_open_dfh(id, OPTEE_MRF_CREATE, dfh, fd);
145 }
146 
147 TEE_Result tee_fs_rpc_close(uint32_t id, int fd)
148 {
149 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
150 
151 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
152 	op.params[0].u.value.a = OPTEE_MRF_CLOSE;
153 	op.params[0].u.value.b = fd;
154 
155 	return operation_commit(&op);
156 }
157 
158 TEE_Result tee_fs_rpc_read_init(struct tee_fs_rpc_operation *op,
159 				uint32_t id, int fd, tee_fs_off_t offset,
160 				size_t data_len, void **out_data)
161 {
162 	struct mobj *mobj;
163 	uint8_t *va;
164 	uint64_t cookie;
165 
166 	if (offset < 0)
167 		return TEE_ERROR_BAD_PARAMETERS;
168 
169 	va = tee_fs_rpc_cache_alloc(data_len, &mobj, &cookie);
170 	if (!va)
171 		return TEE_ERROR_OUT_OF_MEMORY;
172 
173 	memset(op, 0, sizeof(*op));
174 	op->id = id;
175 	op->num_params = 2;
176 
177 	op->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
178 	op->params[0].u.value.a = OPTEE_MRF_READ;
179 	op->params[0].u.value.b = fd;
180 	op->params[0].u.value.c = offset;
181 
182 	if (!msg_param_init_memparam(op->params + 1, mobj, 0, data_len, cookie,
183 				     MSG_PARAM_MEM_DIR_OUT))
184 		return TEE_ERROR_BAD_STATE;
185 
186 	*out_data = va;
187 
188 	return TEE_SUCCESS;
189 }
190 
191 TEE_Result tee_fs_rpc_read_final(struct tee_fs_rpc_operation *op,
192 				 size_t *data_len)
193 {
194 	TEE_Result res = operation_commit(op);
195 
196 	if (res == TEE_SUCCESS)
197 		*data_len = msg_param_get_buf_size(op->params + 1);
198 	return res;
199 }
200 
201 TEE_Result tee_fs_rpc_write_init(struct tee_fs_rpc_operation *op,
202 				 uint32_t id, int fd, tee_fs_off_t offset,
203 				 size_t data_len, void **data)
204 {
205 	struct mobj *mobj;
206 	uint8_t *va;
207 	uint64_t cookie;
208 
209 	if (offset < 0)
210 		return TEE_ERROR_BAD_PARAMETERS;
211 
212 	va = tee_fs_rpc_cache_alloc(data_len, &mobj, &cookie);
213 	if (!va)
214 		return TEE_ERROR_OUT_OF_MEMORY;
215 
216 	memset(op, 0, sizeof(*op));
217 	op->id = id;
218 	op->num_params = 2;
219 
220 	op->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
221 	op->params[0].u.value.a = OPTEE_MRF_WRITE;
222 	op->params[0].u.value.b = fd;
223 	op->params[0].u.value.c = offset;
224 
225 	if (!msg_param_init_memparam(op->params + 1, mobj, 0, data_len, cookie,
226 				     MSG_PARAM_MEM_DIR_IN))
227 		return TEE_ERROR_BAD_STATE;
228 
229 	*data = va;
230 
231 	return TEE_SUCCESS;
232 }
233 
234 TEE_Result tee_fs_rpc_write_final(struct tee_fs_rpc_operation *op)
235 {
236 	return operation_commit(op);
237 }
238 
239 TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len)
240 {
241 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
242 
243 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
244 	op.params[0].u.value.a = OPTEE_MRF_TRUNCATE;
245 	op.params[0].u.value.b = fd;
246 	op.params[0].u.value.c = len;
247 
248 	return operation_commit(&op);
249 }
250 
251 TEE_Result tee_fs_rpc_remove(uint32_t id, struct tee_pobj *po)
252 {
253 	TEE_Result res;
254 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 };
255 	struct mobj *mobj;
256 	void *va;
257 	uint64_t cookie;
258 
259 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &mobj, &cookie);
260 	if (!va)
261 		return TEE_ERROR_OUT_OF_MEMORY;
262 
263 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
264 	op.params[0].u.value.a = OPTEE_MRF_REMOVE;
265 
266 	if (!msg_param_init_memparam(op.params + 1, mobj, 0, TEE_FS_NAME_MAX,
267 				     cookie, MSG_PARAM_MEM_DIR_IN))
268 		return TEE_ERROR_BAD_STATE;
269 
270 	res = tee_svc_storage_create_filename(va, TEE_FS_NAME_MAX,
271 					      po, po->temporary);
272 	if (res != TEE_SUCCESS)
273 		return res;
274 
275 	return operation_commit(&op);
276 }
277 
278 TEE_Result tee_fs_rpc_remove_dfh(uint32_t id,
279 				 const struct tee_fs_dirfile_fileh *dfh)
280 {
281 	TEE_Result res;
282 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 };
283 	struct mobj *mobj;
284 	void *va;
285 	uint64_t cookie;
286 
287 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &mobj, &cookie);
288 	if (!va)
289 		return TEE_ERROR_OUT_OF_MEMORY;
290 
291 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
292 	op.params[0].u.value.a = OPTEE_MRF_REMOVE;
293 
294 	if (!msg_param_init_memparam(op.params + 1, mobj, 0, TEE_FS_NAME_MAX,
295 				     cookie, MSG_PARAM_MEM_DIR_IN))
296 		return TEE_ERROR_BAD_STATE;
297 
298 	res = tee_svc_storage_create_filename_dfh(va, TEE_FS_NAME_MAX, dfh);
299 	if (res != TEE_SUCCESS)
300 		return res;
301 
302 	return operation_commit(&op);
303 }
304 
305 TEE_Result tee_fs_rpc_rename(uint32_t id, struct tee_pobj *old,
306 			     struct tee_pobj *new, bool overwrite)
307 {
308 	TEE_Result res;
309 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
310 	struct mobj *mobj;
311 	char *va;
312 	uint64_t cookie;
313 	bool temp;
314 
315 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX * 2, &mobj, &cookie);
316 	if (!va)
317 		return TEE_ERROR_OUT_OF_MEMORY;
318 
319 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
320 	op.params[0].u.value.a = OPTEE_MRF_RENAME;
321 	op.params[0].u.value.b = overwrite;
322 
323 	if (!msg_param_init_memparam(op.params + 1, mobj, 0, TEE_FS_NAME_MAX,
324 				     cookie, MSG_PARAM_MEM_DIR_IN))
325 		return TEE_ERROR_BAD_STATE;
326 
327 	if (new)
328 		temp = old->temporary;
329 	else
330 		temp = true;
331 	res = tee_svc_storage_create_filename(va, TEE_FS_NAME_MAX,
332 					      old, temp);
333 	if (res != TEE_SUCCESS)
334 		return res;
335 
336 	if (!msg_param_init_memparam(op.params + 2, mobj, TEE_FS_NAME_MAX,
337 				     TEE_FS_NAME_MAX, cookie,
338 				     MSG_PARAM_MEM_DIR_IN))
339 		return TEE_ERROR_BAD_STATE;
340 
341 	if (new) {
342 		res = tee_svc_storage_create_filename(va + TEE_FS_NAME_MAX,
343 						      TEE_FS_NAME_MAX,
344 						      new, new->temporary);
345 	} else {
346 		res = tee_svc_storage_create_filename(va + TEE_FS_NAME_MAX,
347 						      TEE_FS_NAME_MAX,
348 						      old, false);
349 	}
350 	if (res != TEE_SUCCESS)
351 		return res;
352 
353 	return operation_commit(&op);
354 }
355 
356 TEE_Result tee_fs_rpc_opendir(uint32_t id, const TEE_UUID *uuid,
357 			      struct tee_fs_dir **d)
358 {
359 	TEE_Result res;
360 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 };
361 	struct mobj *mobj;
362 	void *va;
363 	uint64_t cookie;
364 	struct tee_fs_dir *dir = calloc(1, sizeof(*dir));
365 
366 	if (!dir)
367 		return TEE_ERROR_OUT_OF_MEMORY;
368 
369 	va = tee_fs_rpc_cache_alloc(TEE_FS_NAME_MAX, &mobj, &cookie);
370 	if (!va) {
371 		res = TEE_ERROR_OUT_OF_MEMORY;
372 		goto err_exit;
373 	}
374 
375 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
376 	op.params[0].u.value.a = OPTEE_MRF_OPENDIR;
377 
378 	if (!msg_param_init_memparam(op.params + 1, mobj, 0, TEE_FS_NAME_MAX,
379 				     cookie, MSG_PARAM_MEM_DIR_IN))
380 		return TEE_ERROR_BAD_STATE;
381 
382 	res = tee_svc_storage_create_dirname(va, TEE_FS_NAME_MAX, uuid);
383 	if (res != TEE_SUCCESS)
384 		return res;
385 
386 	op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT;
387 
388 	res = operation_commit(&op);
389 
390 	if (res != TEE_SUCCESS)
391 		goto err_exit;
392 
393 	dir->nw_dir = op.params[2].u.value.a;
394 	*d = dir;
395 
396 	return TEE_SUCCESS;
397 err_exit:
398 	free(dir);
399 
400 	return res;
401 }
402 
403 TEE_Result tee_fs_rpc_closedir(uint32_t id, struct tee_fs_dir *d)
404 {
405 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 };
406 
407 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
408 	op.params[0].u.value.a = OPTEE_MRF_CLOSEDIR;
409 	op.params[0].u.value.b = d->nw_dir;
410 
411 	free(d);
412 	return operation_commit(&op);
413 }
414 
415 TEE_Result tee_fs_rpc_readdir(uint32_t id, struct tee_fs_dir *d,
416 			      struct tee_fs_dirent **ent)
417 {
418 	TEE_Result res;
419 	struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 };
420 	struct mobj *mobj;
421 	void *va;
422 	uint64_t cookie;
423 	const size_t max_name_len = TEE_FS_NAME_MAX + 1;
424 
425 	if (!d)
426 		return TEE_ERROR_ITEM_NOT_FOUND;
427 
428 	va = tee_fs_rpc_cache_alloc(max_name_len, &mobj, &cookie);
429 	if (!va)
430 		return TEE_ERROR_OUT_OF_MEMORY;
431 
432 	op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT;
433 	op.params[0].u.value.a = OPTEE_MRF_READDIR;
434 	op.params[0].u.value.b = d->nw_dir;
435 
436 	if (!msg_param_init_memparam(op.params + 1, mobj, 0, max_name_len,
437 				     cookie, MSG_PARAM_MEM_DIR_OUT))
438 		return TEE_ERROR_BAD_STATE;
439 
440 	res = operation_commit(&op);
441 	if (res != TEE_SUCCESS)
442 		return res;
443 
444 	d->d.oidlen = tee_hs2b(va, d->d.oid, strnlen(va, max_name_len),
445 			       sizeof(d->d.oid));
446 	if (!d->d.oidlen)
447 		return TEE_ERROR_OUT_OF_MEMORY;
448 
449 	*ent = &d->d;
450 	return TEE_SUCCESS;
451 }
452