1 // SPDX-License-Identifier: BSD-2-Clause 2 /* 3 * Copyright (c) 2014, STMicroelectronics International N.V. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 12 * 2. Redistributions in binary form must reproduce the above copyright notice, 13 * this list of conditions and the following disclaimer in the documentation 14 * and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <kernel/mutex.h> 30 #include <stdlib.h> 31 #include <string.h> 32 #include <tee/tee_pobj.h> 33 #include <trace.h> 34 35 static TAILQ_HEAD(tee_pobjs, tee_pobj) tee_pobjs = 36 TAILQ_HEAD_INITIALIZER(tee_pobjs); 37 static struct mutex pobjs_mutex = MUTEX_INITIALIZER; 38 39 static TEE_Result tee_pobj_check_access(uint32_t oflags, uint32_t nflags) 40 { 41 /* meta is exclusive */ 42 if ((oflags & TEE_DATA_FLAG_ACCESS_WRITE_META) || 43 (nflags & TEE_DATA_FLAG_ACCESS_WRITE_META)) 44 return TEE_ERROR_ACCESS_CONFLICT; 45 46 /* 47 * Excerpt of TEE Internal Core API Specification v1.1: 48 * If more than one handle is opened on the same object, and if any 49 * of these object handles was opened with the flag 50 * TEE_DATA_FLAG_ACCESS_READ, then all the object handles MUST have been 51 * opened with the flag TEE_DATA_FLAG_SHARE_READ 52 */ 53 if (((oflags & TEE_DATA_FLAG_ACCESS_READ) || 54 (nflags & TEE_DATA_FLAG_ACCESS_READ)) && 55 !((nflags & TEE_DATA_FLAG_SHARE_READ) && 56 (oflags & TEE_DATA_FLAG_SHARE_READ))) 57 return TEE_ERROR_ACCESS_CONFLICT; 58 59 /* 60 * Excerpt of TEE Internal Core API Specification v1.1: 61 * An object can be opened with only share flags, which locks the access 62 * to an object against a given mode. 63 * An object can be opened with no flag set, which completely locks all 64 * subsequent attempts to access the object 65 */ 66 if ((nflags & TEE_DATA_FLAG_SHARE_READ) != 67 (oflags & TEE_DATA_FLAG_SHARE_READ)) 68 return TEE_ERROR_ACCESS_CONFLICT; 69 70 /* Same on WRITE access */ 71 if (((oflags & TEE_DATA_FLAG_ACCESS_WRITE) || 72 (nflags & TEE_DATA_FLAG_ACCESS_WRITE)) && 73 !((nflags & TEE_DATA_FLAG_SHARE_WRITE) && 74 (oflags & TEE_DATA_FLAG_SHARE_WRITE))) 75 return TEE_ERROR_ACCESS_CONFLICT; 76 if ((nflags & TEE_DATA_FLAG_SHARE_WRITE) != 77 (oflags & TEE_DATA_FLAG_SHARE_WRITE)) 78 return TEE_ERROR_ACCESS_CONFLICT; 79 80 return TEE_SUCCESS; 81 } 82 83 TEE_Result tee_pobj_get(TEE_UUID *uuid, void *obj_id, uint32_t obj_id_len, 84 uint32_t flags, bool temporary, 85 const struct tee_file_operations *fops, 86 struct tee_pobj **obj) 87 { 88 struct tee_pobj *o; 89 TEE_Result res; 90 91 *obj = NULL; 92 93 mutex_lock(&pobjs_mutex); 94 /* Check if file is open */ 95 TAILQ_FOREACH(o, &tee_pobjs, link) { 96 if ((obj_id_len == o->obj_id_len) && 97 (memcmp(obj_id, o->obj_id, obj_id_len) == 0) && 98 (memcmp(uuid, &o->uuid, sizeof(TEE_UUID)) == 0) && 99 (fops == o->fops)) { 100 *obj = o; 101 } 102 } 103 104 if (*obj) { 105 if (temporary != (*obj)->temporary) { 106 res = TEE_ERROR_ACCESS_CONFLICT; 107 goto out; 108 } 109 res = tee_pobj_check_access((*obj)->flags, flags); 110 if (res == TEE_SUCCESS) 111 (*obj)->refcnt++; 112 goto out; 113 } 114 115 /* new file */ 116 o = calloc(1, sizeof(struct tee_pobj)); 117 if (!o) { 118 res = TEE_ERROR_OUT_OF_MEMORY; 119 goto out; 120 } 121 122 o->refcnt = 1; 123 memcpy(&o->uuid, uuid, sizeof(TEE_UUID)); 124 o->flags = flags; 125 o->fops = fops; 126 o->temporary = temporary; 127 128 o->obj_id = malloc(obj_id_len); 129 if (o->obj_id == NULL) { 130 free(o); 131 res = TEE_ERROR_OUT_OF_MEMORY; 132 goto out; 133 } 134 memcpy(o->obj_id, obj_id, obj_id_len); 135 o->obj_id_len = obj_id_len; 136 137 TAILQ_INSERT_TAIL(&tee_pobjs, o, link); 138 *obj = o; 139 140 res = TEE_SUCCESS; 141 out: 142 if (res != TEE_SUCCESS) 143 *obj = NULL; 144 mutex_unlock(&pobjs_mutex); 145 return res; 146 } 147 148 TEE_Result tee_pobj_release(struct tee_pobj *obj) 149 { 150 if (obj == NULL) 151 return TEE_ERROR_BAD_PARAMETERS; 152 153 mutex_lock(&pobjs_mutex); 154 obj->refcnt--; 155 if (obj->refcnt == 0) { 156 TAILQ_REMOVE(&tee_pobjs, obj, link); 157 free(obj->obj_id); 158 free(obj); 159 } 160 mutex_unlock(&pobjs_mutex); 161 162 return TEE_SUCCESS; 163 } 164 165 TEE_Result tee_pobj_rename(struct tee_pobj *obj, void *obj_id, 166 uint32_t obj_id_len) 167 { 168 TEE_Result res = TEE_SUCCESS; 169 void *new_obj_id = NULL; 170 171 if (obj == NULL || obj_id == NULL) 172 return TEE_ERROR_BAD_PARAMETERS; 173 174 mutex_lock(&pobjs_mutex); 175 if (obj->refcnt != 1) { 176 res = TEE_ERROR_BAD_STATE; 177 goto exit; 178 } 179 180 new_obj_id = malloc(obj_id_len); 181 if (new_obj_id == NULL) { 182 res = TEE_ERROR_OUT_OF_MEMORY; 183 goto exit; 184 } 185 memcpy(new_obj_id, obj_id, obj_id_len); 186 187 /* update internal data */ 188 free(obj->obj_id); 189 obj->obj_id = new_obj_id; 190 obj->obj_id_len = obj_id_len; 191 new_obj_id = NULL; 192 193 exit: 194 mutex_unlock(&pobjs_mutex); 195 free(new_obj_id); 196 return res; 197 } 198