Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'amdtee-fixes-for-v5.13' of git://git.linaro.org/people/jens.wiklander/linux-tee into arm/fixes

AMD-TEE reference count loaded TAs

* tag 'amdtee-fixes-for-v5.13' of git://git.linaro.org/people/jens.wiklander/linux-tee:
tee: amdtee: unload TA only when its refcount becomes 0

Link: https://lore.kernel.org/r/20210505110850.GA3434209@jade
Signed-off-by: Arnd Bergmann <arnd@arndb.de>

+106 -16
+13
drivers/tee/amdtee/amdtee_private.h
··· 21 21 #define TEEC_SUCCESS 0x00000000 22 22 #define TEEC_ERROR_GENERIC 0xFFFF0000 23 23 #define TEEC_ERROR_BAD_PARAMETERS 0xFFFF0006 24 + #define TEEC_ERROR_OUT_OF_MEMORY 0xFFFF000C 24 25 #define TEEC_ERROR_COMMUNICATION 0xFFFF000E 25 26 26 27 #define TEEC_ORIGIN_COMMS 0x00000002 ··· 92 91 struct list_head shm_node; 93 92 void *kaddr; 94 93 u32 buf_id; 94 + }; 95 + 96 + /** 97 + * struct amdtee_ta_data - Keeps track of all TAs loaded in AMD Secure 98 + * Processor 99 + * @ta_handle: Handle to TA loaded in TEE 100 + * @refcount: Reference count for the loaded TA 101 + */ 102 + struct amdtee_ta_data { 103 + struct list_head list_node; 104 + u32 ta_handle; 105 + u32 refcount; 95 106 }; 96 107 97 108 #define LOWER_TWO_BYTE_MASK 0x0000FFFF
+84 -10
drivers/tee/amdtee/call.c
··· 121 121 return ret; 122 122 } 123 123 124 + static DEFINE_MUTEX(ta_refcount_mutex); 125 + static struct list_head ta_list = LIST_HEAD_INIT(ta_list); 126 + 127 + static u32 get_ta_refcount(u32 ta_handle) 128 + { 129 + struct amdtee_ta_data *ta_data; 130 + u32 count = 0; 131 + 132 + /* Caller must hold a mutex */ 133 + list_for_each_entry(ta_data, &ta_list, list_node) 134 + if (ta_data->ta_handle == ta_handle) 135 + return ++ta_data->refcount; 136 + 137 + ta_data = kzalloc(sizeof(*ta_data), GFP_KERNEL); 138 + if (ta_data) { 139 + ta_data->ta_handle = ta_handle; 140 + ta_data->refcount = 1; 141 + count = ta_data->refcount; 142 + list_add(&ta_data->list_node, &ta_list); 143 + } 144 + 145 + return count; 146 + } 147 + 148 + static u32 put_ta_refcount(u32 ta_handle) 149 + { 150 + struct amdtee_ta_data *ta_data; 151 + u32 count = 0; 152 + 153 + /* Caller must hold a mutex */ 154 + list_for_each_entry(ta_data, &ta_list, list_node) 155 + if (ta_data->ta_handle == ta_handle) { 156 + count = --ta_data->refcount; 157 + if (count == 0) { 158 + list_del(&ta_data->list_node); 159 + kfree(ta_data); 160 + break; 161 + } 162 + } 163 + 164 + return count; 165 + } 166 + 124 167 int handle_unload_ta(u32 ta_handle) 125 168 { 126 169 struct tee_cmd_unload_ta cmd = {0}; 127 - u32 status; 170 + u32 status, count; 128 171 int ret; 129 172 130 173 if (!ta_handle) 131 174 return -EINVAL; 175 + 176 + mutex_lock(&ta_refcount_mutex); 177 + 178 + count = put_ta_refcount(ta_handle); 179 + 180 + if (count) { 181 + pr_debug("unload ta: not unloading %u count %u\n", 182 + ta_handle, count); 183 + ret = -EBUSY; 184 + goto unlock; 185 + } 132 186 133 187 cmd.ta_handle = ta_handle; 134 188 ··· 191 137 if (!ret && status != 0) { 192 138 pr_err("unload ta: status = 0x%x\n", status); 193 139 ret = -EBUSY; 140 + } else { 141 + pr_debug("unloaded ta handle %u\n", ta_handle); 194 142 } 195 143 144 + unlock: 145 + mutex_unlock(&ta_refcount_mutex); 196 146 return ret; 197 147 } 198 148 ··· 398 340 399 341 int handle_load_ta(void *data, u32 size, struct tee_ioctl_open_session_arg *arg) 400 342 { 401 - struct tee_cmd_load_ta cmd = {0}; 343 + struct tee_cmd_unload_ta unload_cmd = {}; 344 + struct tee_cmd_load_ta load_cmd = {}; 402 345 phys_addr_t blob; 403 346 int ret; 404 347 ··· 412 353 return -EINVAL; 413 354 } 414 355 415 - cmd.hi_addr = upper_32_bits(blob); 416 - cmd.low_addr = lower_32_bits(blob); 417 - cmd.size = size; 356 + load_cmd.hi_addr = upper_32_bits(blob); 357 + load_cmd.low_addr = lower_32_bits(blob); 358 + load_cmd.size = size; 418 359 419 - ret = psp_tee_process_cmd(TEE_CMD_ID_LOAD_TA, (void *)&cmd, 420 - sizeof(cmd), &arg->ret); 360 + mutex_lock(&ta_refcount_mutex); 361 + 362 + ret = psp_tee_process_cmd(TEE_CMD_ID_LOAD_TA, (void *)&load_cmd, 363 + sizeof(load_cmd), &arg->ret); 421 364 if (ret) { 422 365 arg->ret_origin = TEEC_ORIGIN_COMMS; 423 366 arg->ret = TEEC_ERROR_COMMUNICATION; 424 - } else { 425 - set_session_id(cmd.ta_handle, 0, &arg->session); 367 + } else if (arg->ret == TEEC_SUCCESS) { 368 + ret = get_ta_refcount(load_cmd.ta_handle); 369 + if (!ret) { 370 + arg->ret_origin = TEEC_ORIGIN_COMMS; 371 + arg->ret = TEEC_ERROR_OUT_OF_MEMORY; 372 + 373 + /* Unload the TA on error */ 374 + unload_cmd.ta_handle = load_cmd.ta_handle; 375 + psp_tee_process_cmd(TEE_CMD_ID_UNLOAD_TA, 376 + (void *)&unload_cmd, 377 + sizeof(unload_cmd), &ret); 378 + } else { 379 + set_session_id(load_cmd.ta_handle, 0, &arg->session); 380 + } 426 381 } 382 + mutex_unlock(&ta_refcount_mutex); 427 383 428 384 pr_debug("load TA: TA handle = 0x%x, RO = 0x%x, ret = 0x%x\n", 429 - cmd.ta_handle, arg->ret_origin, arg->ret); 385 + load_cmd.ta_handle, arg->ret_origin, arg->ret); 430 386 431 387 return 0; 432 388 }
+9 -6
drivers/tee/amdtee/core.c
··· 59 59 continue; 60 60 61 61 handle_close_session(sess->ta_handle, sess->session_info[i]); 62 + handle_unload_ta(sess->ta_handle); 62 63 } 63 64 64 - /* Unload Trusted Application once all sessions are closed */ 65 - handle_unload_ta(sess->ta_handle); 66 65 kfree(sess); 67 66 } 68 67 ··· 223 224 struct amdtee_session *sess = container_of(ref, struct amdtee_session, 224 225 refcount); 225 226 226 - /* Unload the TA from TEE */ 227 - handle_unload_ta(sess->ta_handle); 228 227 mutex_lock(&session_list_mutex); 229 228 list_del(&sess->list_node); 230 229 mutex_unlock(&session_list_mutex); ··· 235 238 { 236 239 struct amdtee_context_data *ctxdata = ctx->data; 237 240 struct amdtee_session *sess = NULL; 238 - u32 session_info; 241 + u32 session_info, ta_handle; 239 242 size_t ta_size; 240 243 int rc, i; 241 244 void *ta; ··· 256 259 if (arg->ret != TEEC_SUCCESS) 257 260 goto out; 258 261 262 + ta_handle = get_ta_handle(arg->session); 263 + 259 264 mutex_lock(&session_list_mutex); 260 265 sess = alloc_session(ctxdata, arg->session); 261 266 mutex_unlock(&session_list_mutex); 262 267 263 268 if (!sess) { 269 + handle_unload_ta(ta_handle); 264 270 rc = -ENOMEM; 265 271 goto out; 266 272 } ··· 277 277 278 278 if (i >= TEE_NUM_SESSIONS) { 279 279 pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS); 280 + handle_unload_ta(ta_handle); 280 281 kref_put(&sess->refcount, destroy_session); 281 282 rc = -ENOMEM; 282 283 goto out; ··· 290 289 spin_lock(&sess->lock); 291 290 clear_bit(i, sess->sess_mask); 292 291 spin_unlock(&sess->lock); 292 + handle_unload_ta(ta_handle); 293 293 kref_put(&sess->refcount, destroy_session); 294 294 goto out; 295 295 } 296 296 297 297 sess->session_info[i] = session_info; 298 - set_session_id(sess->ta_handle, i, &arg->session); 298 + set_session_id(ta_handle, i, &arg->session); 299 299 out: 300 300 free_pages((u64)ta, get_order(ta_size)); 301 301 return rc; ··· 331 329 332 330 /* Close the session */ 333 331 handle_close_session(ta_handle, session_info); 332 + handle_unload_ta(ta_handle); 334 333 335 334 kref_put(&sess->refcount, destroy_session); 336 335