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 <optee_msg_fs.h> 32 #include <stdlib.h> 33 #include <string.h> 34 #include <string_ext.h> 35 #include <tee/tee_fs.h> 36 #include <tee/tee_fs_rpc.h> 37 #include <trace.h> 38 #include <util.h> 39 40 struct tee_fs_dir { 41 int nw_dir; 42 struct tee_fs_dirent d; 43 }; 44 45 static TEE_Result operation_commit(struct tee_fs_rpc_operation *op) 46 { 47 return thread_rpc_cmd(op->id, op->num_params, op->params); 48 } 49 50 static TEE_Result operation_open(uint32_t id, unsigned int cmd, 51 const char *fname, int *fd) 52 { 53 struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 }; 54 TEE_Result res; 55 void *va; 56 paddr_t pa; 57 uint64_t cookie; 58 size_t fname_size = strlen(fname) + 1; 59 60 va = tee_fs_rpc_cache_alloc(fname_size, &pa, &cookie); 61 if (!va) 62 return TEE_ERROR_OUT_OF_MEMORY; 63 64 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 65 op.params[0].u.value.a = cmd; 66 67 op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; 68 op.params[1].u.tmem.buf_ptr = pa; 69 op.params[1].u.tmem.size = fname_size; 70 op.params[1].u.tmem.shm_ref = cookie; 71 strlcpy(va, fname, fname_size); 72 73 op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT; 74 75 res = operation_commit(&op); 76 if (res == TEE_SUCCESS) 77 *fd = op.params[2].u.value.a; 78 79 return res; 80 } 81 82 TEE_Result tee_fs_rpc_open(uint32_t id, const char *fname, int *fd) 83 { 84 return operation_open(id, OPTEE_MRF_OPEN, fname, fd); 85 } 86 87 TEE_Result tee_fs_rpc_create(uint32_t id, const char *fname, int *fd) 88 { 89 return operation_open(id, OPTEE_MRF_CREATE, fname, fd); 90 } 91 92 TEE_Result tee_fs_rpc_close(uint32_t id, int fd) 93 { 94 struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 }; 95 96 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 97 op.params[0].u.value.a = OPTEE_MRF_CLOSE; 98 op.params[0].u.value.b = fd; 99 100 return operation_commit(&op); 101 } 102 103 TEE_Result tee_fs_rpc_read_init(struct tee_fs_rpc_operation *op, 104 uint32_t id, int fd, tee_fs_off_t offset, 105 size_t data_len, void **out_data) 106 { 107 uint8_t *va; 108 paddr_t pa; 109 uint64_t cookie; 110 111 if (offset < 0) 112 return TEE_ERROR_BAD_PARAMETERS; 113 114 va = tee_fs_rpc_cache_alloc(data_len, &pa, &cookie); 115 if (!va) 116 return TEE_ERROR_OUT_OF_MEMORY; 117 118 memset(op, 0, sizeof(*op)); 119 op->id = id; 120 op->num_params = 2; 121 122 op->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 123 op->params[0].u.value.a = OPTEE_MRF_READ; 124 op->params[0].u.value.b = fd; 125 op->params[0].u.value.c = offset; 126 127 op->params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT; 128 op->params[1].u.tmem.buf_ptr = pa; 129 op->params[1].u.tmem.size = data_len; 130 op->params[1].u.tmem.shm_ref = cookie; 131 132 *out_data = va; 133 134 return TEE_SUCCESS; 135 } 136 137 TEE_Result tee_fs_rpc_read_final(struct tee_fs_rpc_operation *op, 138 size_t *data_len) 139 { 140 TEE_Result res = operation_commit(op); 141 142 if (res == TEE_SUCCESS) 143 *data_len = op->params[1].u.tmem.size; 144 return res; 145 } 146 147 TEE_Result tee_fs_rpc_write_init(struct tee_fs_rpc_operation *op, 148 uint32_t id, int fd, tee_fs_off_t offset, 149 size_t data_len, void **data) 150 { 151 uint8_t *va; 152 paddr_t pa; 153 uint64_t cookie; 154 155 if (offset < 0) 156 return TEE_ERROR_BAD_PARAMETERS; 157 158 va = tee_fs_rpc_cache_alloc(data_len, &pa, &cookie); 159 if (!va) 160 return TEE_ERROR_OUT_OF_MEMORY; 161 162 memset(op, 0, sizeof(*op)); 163 op->id = id; 164 op->num_params = 2; 165 166 167 op->params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 168 op->params[0].u.value.a = OPTEE_MRF_WRITE; 169 op->params[0].u.value.b = fd; 170 op->params[0].u.value.c = offset; 171 172 op->params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; 173 op->params[1].u.tmem.buf_ptr = pa; 174 op->params[1].u.tmem.size = data_len; 175 op->params[1].u.tmem.shm_ref = cookie; 176 177 *data = va; 178 179 return TEE_SUCCESS; 180 } 181 182 TEE_Result tee_fs_rpc_write_final(struct tee_fs_rpc_operation *op) 183 { 184 return operation_commit(op); 185 } 186 187 TEE_Result tee_fs_rpc_truncate(uint32_t id, int fd, size_t len) 188 { 189 struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 }; 190 191 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 192 op.params[0].u.value.a = OPTEE_MRF_TRUNCATE; 193 op.params[0].u.value.b = fd; 194 op.params[0].u.value.c = len; 195 196 return operation_commit(&op); 197 } 198 199 TEE_Result tee_fs_rpc_remove(uint32_t id, const char *fname) 200 { 201 struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 }; 202 void *va; 203 paddr_t pa; 204 uint64_t cookie; 205 size_t name_len = strlen(fname) + 1; 206 207 va = tee_fs_rpc_cache_alloc(name_len, &pa, &cookie); 208 if (!va) 209 return TEE_ERROR_OUT_OF_MEMORY; 210 211 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 212 op.params[0].u.value.a = OPTEE_MRF_REMOVE; 213 214 op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; 215 op.params[1].u.tmem.buf_ptr = pa; 216 op.params[1].u.tmem.size = name_len; 217 op.params[1].u.tmem.shm_ref = cookie; 218 strlcpy(va, fname, name_len); 219 220 return operation_commit(&op); 221 } 222 223 TEE_Result tee_fs_rpc_rename(uint32_t id, const char *old_fname, 224 const char *new_fname, bool overwrite) 225 { 226 struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 }; 227 char *va; 228 paddr_t pa; 229 uint64_t cookie; 230 size_t old_fname_size = strlen(old_fname) + 1; 231 size_t new_fname_size = strlen(new_fname) + 1; 232 233 va = tee_fs_rpc_cache_alloc(old_fname_size + new_fname_size, 234 &pa, &cookie); 235 if (!va) 236 return TEE_ERROR_OUT_OF_MEMORY; 237 238 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 239 op.params[0].u.value.a = OPTEE_MRF_RENAME; 240 op.params[0].u.value.b = overwrite; 241 242 op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; 243 op.params[1].u.tmem.buf_ptr = pa; 244 op.params[1].u.tmem.size = old_fname_size; 245 op.params[1].u.tmem.shm_ref = cookie; 246 strlcpy(va, old_fname, old_fname_size); 247 248 op.params[2].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; 249 op.params[2].u.tmem.buf_ptr = pa + old_fname_size; 250 op.params[2].u.tmem.size = new_fname_size; 251 op.params[2].u.tmem.shm_ref = cookie; 252 strlcpy(va + old_fname_size, new_fname, new_fname_size); 253 254 return operation_commit(&op); 255 } 256 257 TEE_Result tee_fs_rpc_opendir(uint32_t id, const char *name, 258 struct tee_fs_dir **d) 259 { 260 TEE_Result res; 261 struct tee_fs_rpc_operation op = { .id = id, .num_params = 3 }; 262 void *va; 263 paddr_t pa; 264 uint64_t cookie; 265 size_t name_len = strlen(name) + 1; 266 struct tee_fs_dir *dir = calloc(1, sizeof(*dir)); 267 268 if (!dir) 269 return TEE_ERROR_OUT_OF_MEMORY; 270 271 va = tee_fs_rpc_cache_alloc(name_len, &pa, &cookie); 272 if (!va) { 273 res = TEE_ERROR_OUT_OF_MEMORY; 274 goto err_exit; 275 } 276 277 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 278 op.params[0].u.value.a = OPTEE_MRF_OPENDIR; 279 280 op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_INPUT; 281 op.params[1].u.tmem.buf_ptr = pa; 282 op.params[1].u.tmem.size = name_len; 283 op.params[1].u.tmem.shm_ref = cookie; 284 strlcpy(va, name, name_len); 285 286 op.params[2].attr = OPTEE_MSG_ATTR_TYPE_VALUE_OUTPUT; 287 288 res = operation_commit(&op); 289 290 if (res != TEE_SUCCESS) 291 goto err_exit; 292 293 dir->nw_dir = op.params[2].u.value.a; 294 *d = dir; 295 296 return TEE_SUCCESS; 297 err_exit: 298 free(dir); 299 300 return res; 301 } 302 303 TEE_Result tee_fs_rpc_closedir(uint32_t id, struct tee_fs_dir *d) 304 { 305 struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 }; 306 307 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 308 op.params[0].u.value.a = OPTEE_MRF_CLOSEDIR; 309 op.params[0].u.value.b = d->nw_dir; 310 311 if (d) 312 free(d->d.d_name); 313 free(d); 314 return operation_commit(&op); 315 } 316 317 TEE_Result tee_fs_rpc_readdir(uint32_t id, struct tee_fs_dir *d, 318 struct tee_fs_dirent **ent) 319 { 320 TEE_Result res; 321 struct tee_fs_rpc_operation op = { .id = id, .num_params = 2 }; 322 void *va; 323 paddr_t pa; 324 uint64_t cookie; 325 const size_t max_name_len = TEE_FS_NAME_MAX + 1; 326 327 if (!d) 328 return TEE_ERROR_ITEM_NOT_FOUND; 329 330 va = tee_fs_rpc_cache_alloc(max_name_len, &pa, &cookie); 331 if (!va) 332 return TEE_ERROR_OUT_OF_MEMORY; 333 334 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 335 op.params[0].u.value.a = OPTEE_MRF_READDIR; 336 op.params[0].u.value.b = d->nw_dir; 337 338 op.params[1].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT; 339 op.params[1].u.tmem.buf_ptr = pa; 340 op.params[1].u.tmem.size = max_name_len; 341 op.params[1].u.tmem.shm_ref = cookie; 342 343 res = operation_commit(&op); 344 if (res != TEE_SUCCESS) 345 return res; 346 347 free(d->d.d_name); 348 d->d.d_name = strndup(va, max_name_len); 349 if (!d->d.d_name) 350 return TEE_ERROR_OUT_OF_MEMORY; 351 352 *ent = &d->d; 353 return TEE_SUCCESS; 354 } 355 356 TEE_Result tee_fs_rpc_begin_transaction(uint32_t id) 357 { 358 struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 }; 359 360 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 361 op.params[0].u.value.a = OPTEE_MRF_BEGIN_TRANSACTION; 362 363 return operation_commit(&op); 364 } 365 366 TEE_Result tee_fs_rpc_end_transaction(uint32_t id, bool rollback) 367 { 368 struct tee_fs_rpc_operation op = { .id = id, .num_params = 1 }; 369 370 op.params[0].attr = OPTEE_MSG_ATTR_TYPE_VALUE_INPUT; 371 op.params[0].u.value.a = OPTEE_MRF_END_TRANSACTION; 372 op.params[0].u.value.b = rollback; 373 374 return operation_commit(&op); 375 } 376