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