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