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