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