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/thread.h> 30 #include <mm/core_memprot.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <tee/tee_fs.h> 34 #include <tee/tee_fs_rpc.h> 35 #include <trace.h> 36 #include <util.h> 37 38 #define RPC_FAILED -1 39 40 struct tee_fs_dir { 41 int nw_dir; 42 struct tee_fs_dirent d; 43 }; 44 45 static TEE_Result tee_fs_rpc_send_cmd(int cmd_id, struct tee_fs_rpc *bf_cmd, 46 void *data, uint32_t len, uint32_t mode) 47 { 48 TEE_Result ret; 49 struct optee_msg_param params; 50 paddr_t phpayload = 0; 51 uint64_t cpayload = 0; 52 struct tee_fs_rpc *bf; 53 int res = TEE_ERROR_GENERIC; 54 55 assert(cmd_id == OPTEE_MSG_RPC_CMD_FS || 56 cmd_id == OPTEE_MSG_RPC_CMD_SQL_FS); 57 58 thread_rpc_alloc_payload(sizeof(struct tee_fs_rpc) + len, 59 &phpayload, &cpayload); 60 if (!phpayload) 61 return TEE_ERROR_OUT_OF_MEMORY; 62 63 if (!ALIGNMENT_IS_OK(phpayload, struct tee_fs_rpc)) 64 goto exit; 65 66 bf = phys_to_virt(phpayload, MEM_AREA_NSEC_SHM); 67 if (!bf) 68 goto exit; 69 70 memset(¶ms, 0, sizeof(params)); 71 params.attr = OPTEE_MSG_ATTR_TYPE_TMEM_INOUT; 72 params.u.tmem.buf_ptr = phpayload; 73 params.u.tmem.size = sizeof(struct tee_fs_rpc) + len; 74 params.u.tmem.shm_ref = cpayload; 75 76 /* fill in parameters */ 77 *bf = *bf_cmd; 78 79 if (mode & TEE_FS_MODE_IN) 80 memcpy((void *)(bf + 1), data, len); 81 82 ret = thread_rpc_cmd(cmd_id, 1, ¶ms); 83 /* update result */ 84 *bf_cmd = *bf; 85 if (ret != TEE_SUCCESS) 86 goto exit; 87 88 if (mode & TEE_FS_MODE_OUT) { 89 uint32_t olen = MIN(len, bf->len); 90 91 memcpy(data, (void *)(bf + 1), olen); 92 } 93 94 res = TEE_SUCCESS; 95 96 exit: 97 thread_rpc_free_payload(cpayload); 98 return res; 99 } 100 101 int tee_fs_rpc_access(int id, const char *name, int mode) 102 { 103 struct tee_fs_rpc head = { 0 }; 104 TEE_Result res; 105 int rc = RPC_FAILED; 106 size_t len; 107 108 DMSG("(id: %d, name: %s, mode: %d)...", id, name, mode); 109 110 if (!name) 111 goto exit; 112 113 len = strlen(name) + 1; 114 if (len <= 1) 115 goto exit; 116 117 head.op = TEE_FS_ACCESS; 118 head.flags = mode; 119 120 res = tee_fs_rpc_send_cmd(id, &head, (void *)name, len, TEE_FS_MODE_IN); 121 if (res != TEE_SUCCESS) 122 goto exit; 123 124 rc = head.res; 125 exit: 126 DMSG("...%d", rc); 127 return rc; 128 } 129 130 int tee_fs_rpc_begin_transaction(int id) 131 { 132 struct tee_fs_rpc head = { 0 }; 133 TEE_Result res; 134 int rc = RPC_FAILED; 135 136 assert(id == OPTEE_MSG_RPC_CMD_SQL_FS); 137 138 DMSG("(id: %d)...", id); 139 140 /* fill in parameters */ 141 head.op = TEE_FS_BEGIN; 142 head.fd = -1; 143 144 res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, 145 TEE_FS_MODE_NONE); 146 if (res != TEE_SUCCESS) 147 goto exit; 148 149 rc = head.res; 150 exit: 151 DMSG("...%d", rc); 152 return rc; 153 } 154 155 int tee_fs_rpc_close(int id, int fd) 156 { 157 struct tee_fs_rpc head = { 0 }; 158 TEE_Result res; 159 int rc = RPC_FAILED; 160 161 DMSG("(id: %d, fd: %d)...", id, fd); 162 163 head.op = TEE_FS_CLOSE; 164 head.fd = fd; 165 166 res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE); 167 if (res != TEE_SUCCESS) 168 goto exit; 169 170 rc = head.res; 171 exit: 172 DMSG("...%d", rc); 173 return rc; 174 } 175 176 int tee_fs_rpc_end_transaction(int id, bool rollback) 177 { 178 struct tee_fs_rpc head = { 0 }; 179 TEE_Result res; 180 int rc = RPC_FAILED; 181 182 assert(id == OPTEE_MSG_RPC_CMD_SQL_FS); 183 184 DMSG("(id: %d, rollback: %d)...", id, rollback); 185 186 head.op = TEE_FS_END; 187 head.arg = rollback; 188 head.fd = -1; 189 190 res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE); 191 if (res != TEE_SUCCESS) 192 goto exit; 193 194 rc = head.res; 195 exit: 196 DMSG("...%d", rc); 197 return rc; 198 } 199 200 int tee_fs_rpc_ftruncate(int id, int fd, tee_fs_off_t length) 201 { 202 struct tee_fs_rpc head = { 0 }; 203 TEE_Result res; 204 int rc = RPC_FAILED; 205 206 DMSG("(id: %d, fd: %d, length: %" PRId64 ")...", id, fd, length); 207 208 head.op = TEE_FS_TRUNC; 209 head.fd = fd; 210 head.arg = length; 211 212 res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE); 213 if (res != TEE_SUCCESS) 214 goto exit; 215 216 rc = head.res; 217 exit: 218 DMSG("...%d", rc); 219 return rc; 220 } 221 222 int tee_fs_rpc_link(int id, const char *old, const char *nw) 223 { 224 size_t len_old; 225 size_t len_new; 226 size_t len; 227 struct tee_fs_rpc head = { 0 }; 228 char *tmp = NULL; 229 TEE_Result res; 230 int rc = RPC_FAILED; 231 232 DMSG("(id: %d, old: %s, nw: %s)...", id, old, nw); 233 234 if (!old || !nw) 235 goto exit; 236 237 len_old = strlen(old) + 1; 238 len_new = strlen(nw) + 1; 239 len = len_old + len_new; 240 241 tmp = malloc(len); 242 if (!tmp) 243 goto exit; 244 memcpy(tmp, old, len_old); 245 memcpy(tmp + len_old, nw, len_new); 246 247 head.op = TEE_FS_LINK; 248 249 res = tee_fs_rpc_send_cmd(id, &head, tmp, len, TEE_FS_MODE_IN); 250 if (res != TEE_SUCCESS) 251 goto exit; 252 253 rc = head.res; 254 exit: 255 free(tmp); 256 DMSG("...%d", rc); 257 return rc; 258 } 259 260 tee_fs_off_t tee_fs_rpc_lseek(int id, int fd, tee_fs_off_t offset, 261 int whence) 262 { 263 struct tee_fs_rpc head = { 0 }; 264 tee_fs_off_t rc = RPC_FAILED; 265 TEE_Result res; 266 267 DMSG("(id: %d, fd: %d, offset: %" PRId64 ", whence: %d)...", id, fd, 268 offset, whence); 269 270 head.op = TEE_FS_SEEK; 271 head.fd = fd; 272 head.arg = offset; 273 head.flags = whence; 274 275 res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE); 276 if (res != TEE_SUCCESS) 277 goto exit; 278 279 rc = head.res; 280 exit: 281 DMSG("...%" PRId64, rc); 282 return rc; 283 } 284 285 int tee_fs_rpc_mkdir(int id, const char *path, tee_fs_mode_t mode) 286 { 287 struct tee_fs_rpc head = { 0 }; 288 TEE_Result res; 289 uint32_t len; 290 int rc = RPC_FAILED; 291 292 DMSG("(id: %d, path: %s, mode: %d)...", id, path, mode); 293 294 if (!path) 295 goto exit; 296 297 len = strlen(path) + 1; 298 if (len <= 1) 299 goto exit; 300 301 head.op = TEE_FS_MKDIR; 302 head.flags = mode; 303 304 res = tee_fs_rpc_send_cmd(id, &head, (void *)path, len, 305 TEE_FS_MODE_IN); 306 if (res != TEE_SUCCESS) 307 goto exit; 308 309 rc = head.res; 310 exit: 311 DMSG("...%d", rc); 312 return rc; 313 } 314 315 int tee_fs_rpc_open(int id, const char *file, int flags) 316 { 317 struct tee_fs_rpc head = { 0 }; 318 TEE_Result res; 319 int rc = RPC_FAILED; 320 size_t len; 321 322 DMSG("(id: %d, file: %s, flags: %d)...", id, file, flags); 323 324 if (!file) 325 goto exit; 326 327 len = strlen(file) + 1; 328 if (len <= 1) 329 goto exit; 330 331 head.op = TEE_FS_OPEN; 332 head.flags = flags; 333 334 res = tee_fs_rpc_send_cmd(id, &head, (void *)file, len, 335 TEE_FS_MODE_IN); 336 if (res != TEE_SUCCESS) 337 goto exit; 338 339 rc = head.res; 340 exit: 341 DMSG("...%d", rc); 342 return rc; 343 } 344 345 struct tee_fs_dir *tee_fs_rpc_opendir(int id, const char *name) 346 { 347 struct tee_fs_rpc head = { 0 }; 348 struct tee_fs_dir *dir = NULL; 349 size_t len; 350 TEE_Result res = TEE_SUCCESS; 351 352 DMSG("(id: %d, name: %s)...", id, name); 353 354 if (!name) 355 goto exit; 356 357 len = strlen(name) + 1; 358 if (len <= 1) 359 goto exit; 360 361 dir = malloc(sizeof(struct tee_fs_dir)); 362 if (!dir) 363 goto exit; 364 365 head.op = TEE_FS_OPENDIR; 366 367 res = tee_fs_rpc_send_cmd(id, &head, (void *)name, len, 368 TEE_FS_MODE_IN); 369 if (res != TEE_SUCCESS) 370 goto free_and_exit; 371 if (head.res < 0) 372 goto free_and_exit; 373 374 dir->nw_dir = head.res; 375 dir->d.d_name = NULL; 376 377 goto exit; 378 379 free_and_exit: 380 free(dir); 381 dir = NULL; 382 exit: 383 DMSG("...%p", (void *)dir); 384 return dir; 385 } 386 387 int tee_fs_rpc_read(int id, int fd, void *buf, size_t len) 388 { 389 struct tee_fs_rpc head = { 0 }; 390 TEE_Result res; 391 int rc = RPC_FAILED; 392 393 DMSG("(id: %d, fd: %d, buf: %p, len: %zu)...", id, fd, (void *)buf, 394 len); 395 396 if (!len) { 397 res = 0; 398 goto exit; 399 } 400 401 if (!buf) 402 goto exit; 403 404 head.op = TEE_FS_READ; 405 head.fd = fd; 406 head.len = (uint32_t)len; 407 408 res = tee_fs_rpc_send_cmd(id, &head, (void *)buf, len, 409 TEE_FS_MODE_OUT); 410 if (res != TEE_SUCCESS) 411 goto exit; 412 413 rc = head.res; 414 exit: 415 DMSG("...%d", rc); 416 return rc; 417 } 418 419 struct tee_fs_dirent *tee_fs_rpc_readdir(int id, struct tee_fs_dir *d) 420 { 421 struct tee_fs_dirent *rc = NULL; 422 char fname[TEE_FS_NAME_MAX + 1]; 423 struct tee_fs_rpc head = { 0 }; 424 TEE_Result res; 425 426 DMSG("(id: %d, d: %p)...", id, (void *)d); 427 428 if (!d) 429 goto exit; 430 431 head.op = TEE_FS_READDIR; 432 head.arg = (int)d->nw_dir; 433 head.len = sizeof(fname); 434 435 res = tee_fs_rpc_send_cmd(id, &head, fname, sizeof(fname), 436 TEE_FS_MODE_OUT); 437 if (res != TEE_SUCCESS) 438 goto exit; 439 440 if (head.res < 0) 441 goto exit; 442 443 if (!head.len || head.len > sizeof(fname)) 444 goto exit; 445 446 fname[head.len - 1] = '\0'; /* make sure it's zero terminated */ 447 free(d->d.d_name); 448 d->d.d_name = strdup(fname); 449 if (!d->d.d_name) 450 goto exit; 451 452 rc = &d->d; 453 exit: 454 DMSG("...%p", (void *)rc); 455 return rc; 456 } 457 458 int tee_fs_rpc_rename(int id, const char *old, const char *nw) 459 { 460 size_t len_old; 461 size_t len_new; 462 size_t len; 463 struct tee_fs_rpc head = { 0 }; 464 char *tmp = NULL; 465 TEE_Result res; 466 int rc = RPC_FAILED; 467 468 DMSG("(id: %d, old: %s, nw: %s)...", id, old, nw); 469 470 if (!old || !nw) 471 goto exit; 472 473 len_old = strlen(old) + 1; 474 len_new = strlen(nw) + 1; 475 len = len_old + len_new; 476 477 tmp = malloc(len); 478 if (!tmp) 479 goto exit; 480 481 memcpy(tmp, old, len_old); 482 memcpy(tmp + len_old, nw, len_new); 483 484 head.op = TEE_FS_RENAME; 485 486 res = tee_fs_rpc_send_cmd(id, &head, tmp, len, TEE_FS_MODE_IN); 487 if (res != TEE_SUCCESS) 488 goto exit; 489 490 rc = head.res; 491 exit: 492 free(tmp); 493 DMSG("...%d", rc); 494 return rc; 495 } 496 497 int tee_fs_rpc_write(int id, int fd, const void *buf, size_t len) 498 { 499 struct tee_fs_rpc head = { 0 }; 500 TEE_Result res; 501 int rc = RPC_FAILED; 502 503 DMSG("(id: %d, fd: %d, buf: %p, len: %zu)...", id, fd, buf, len); 504 505 if (!len) { 506 res = 0; 507 goto exit; 508 } 509 510 if (!buf) 511 goto exit; 512 513 head.op = TEE_FS_WRITE; 514 head.fd = fd; 515 head.len = (uint32_t)len; 516 517 res = tee_fs_rpc_send_cmd(id, &head, (void *)buf, len, TEE_FS_MODE_IN); 518 if (res != TEE_SUCCESS) 519 goto exit; 520 521 rc = head.res; 522 exit: 523 DMSG("...%d", rc); 524 return rc; 525 } 526 527 int tee_fs_rpc_closedir(int id, struct tee_fs_dir *d) 528 { 529 struct tee_fs_rpc head = { 0 }; 530 TEE_Result res; 531 int rc = RPC_FAILED; 532 533 DMSG("(id: %d, d: %p)...", id, (void *)d); 534 535 if (!d) { 536 rc = 0; 537 goto exit; 538 } 539 540 head.op = TEE_FS_CLOSEDIR; 541 head.arg = (int)d->nw_dir; 542 543 res = tee_fs_rpc_send_cmd(id, &head, NULL, 0, TEE_FS_MODE_NONE); 544 if (res != TEE_SUCCESS) 545 goto exit; 546 547 rc = head.res; 548 exit: 549 if (d) 550 free(d->d.d_name); 551 free(d); 552 553 DMSG("...%d", rc); 554 return rc; 555 } 556 557 int tee_fs_rpc_rmdir(int id, const char *name) 558 { 559 struct tee_fs_rpc head = { 0 }; 560 TEE_Result res; 561 int rc = RPC_FAILED; 562 size_t len; 563 564 DMSG("(id: %d, name: %s)...", id, name); 565 566 if (!name) 567 goto exit; 568 569 len = strlen(name) + 1; 570 if (len <= 1) 571 goto exit; 572 573 head.op = TEE_FS_RMDIR; 574 575 res = tee_fs_rpc_send_cmd(id, &head, (void *)name, len, 576 TEE_FS_MODE_IN); 577 if (res != TEE_SUCCESS) 578 goto exit; 579 580 rc = head.res; 581 exit: 582 DMSG("...%d", rc); 583 return rc; 584 } 585 586 int tee_fs_rpc_unlink(int id, const char *file) 587 { 588 struct tee_fs_rpc head = { 0 }; 589 size_t len; 590 TEE_Result res; 591 int rc = RPC_FAILED; 592 593 DMSG("(id: %d, file: %s)...", id, file); 594 595 if (!file) 596 goto exit; 597 598 len = strlen(file) + 1; 599 if (len <= 1) 600 goto exit; 601 602 head.op = TEE_FS_UNLINK; 603 604 res = tee_fs_rpc_send_cmd(id, &head, (void *)file, len, 605 TEE_FS_MODE_IN); 606 if (res != TEE_SUCCESS) 607 goto exit; 608 609 rc = head.res; 610 exit: 611 DMSG("...%d", rc); 612 return rc; 613 } 614