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