Merge tag 'tee-amdtee-fix2-for-5.6' of https://git.linaro.org/people/jens.wiklander...
authorArnd Bergmann <arnd@arndb.de>
Wed, 25 Mar 2020 12:52:50 +0000 (13:52 +0100)
committerArnd Bergmann <arnd@arndb.de>
Wed, 25 Mar 2020 13:27:27 +0000 (14:27 +0100)
tee: amdtee: out of bounds read in find_session()

* tag 'tee-amdtee-fix2-for-5.6' of https://git.linaro.org/people/jens.wiklander/linux-tee:
  tee: amdtee: out of bounds read in find_session()

Link: https://lore.kernel.org/r/20200320063446.GA9892@jade
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
1  2 
drivers/tee/amdtee/core.c

index 0026eb6f13cee46a2898f3a44b08c8b5a4c3ee0b,dbc238c7c26330e9db7a1adda92be5b20b46d018..27b4cd77d0db6facc167aa685f30553e4c8a1da7
@@@ -139,6 -139,9 +139,9 @@@ static struct amdtee_session *find_sess
        u32 index = get_session_index(session);
        struct amdtee_session *sess;
  
+       if (index >= TEE_NUM_SESSIONS)
+               return NULL;
        list_for_each_entry(sess, &ctxdata->sess_list, list_node)
                if (ta_handle == sess->ta_handle &&
                    test_bit(index, sess->sess_mask))
@@@ -212,19 -215,6 +215,19 @@@ unlock
        return rc;
  }
  
 +static void destroy_session(struct kref *ref)
 +{
 +      struct amdtee_session *sess = container_of(ref, struct amdtee_session,
 +                                                 refcount);
 +
 +      /* Unload the TA from TEE */
 +      handle_unload_ta(sess->ta_handle);
 +      mutex_lock(&session_list_mutex);
 +      list_del(&sess->list_node);
 +      mutex_unlock(&session_list_mutex);
 +      kfree(sess);
 +}
 +
  int amdtee_open_session(struct tee_context *ctx,
                        struct tee_ioctl_open_session_arg *arg,
                        struct tee_param *param)
  
        /* Load the TA binary into TEE environment */
        handle_load_ta(ta, ta_size, arg);
 -      if (arg->ret == TEEC_SUCCESS) {
 -              mutex_lock(&session_list_mutex);
 -              sess = alloc_session(ctxdata, arg->session);
 -              mutex_unlock(&session_list_mutex);
 -      }
 -
        if (arg->ret != TEEC_SUCCESS)
                goto out;
  
 +      mutex_lock(&session_list_mutex);
 +      sess = alloc_session(ctxdata, arg->session);
 +      mutex_unlock(&session_list_mutex);
 +
        if (!sess) {
                rc = -ENOMEM;
                goto out;
  
        if (i >= TEE_NUM_SESSIONS) {
                pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS);
 +              kref_put(&sess->refcount, destroy_session);
                rc = -ENOMEM;
                goto out;
        }
  
        /* Open session with loaded TA */
        handle_open_session(arg, &session_info, param);
 -
 -      if (arg->ret == TEEC_SUCCESS) {
 -              sess->session_info[i] = session_info;
 -              set_session_id(sess->ta_handle, i, &arg->session);
 -      } else {
 +      if (arg->ret != TEEC_SUCCESS) {
                pr_err("open_session failed %d\n", arg->ret);
                spin_lock(&sess->lock);
                clear_bit(i, sess->sess_mask);
                spin_unlock(&sess->lock);
 +              kref_put(&sess->refcount, destroy_session);
 +              goto out;
        }
 +
 +      sess->session_info[i] = session_info;
 +      set_session_id(sess->ta_handle, i, &arg->session);
  out:
        free_pages((u64)ta, get_order(ta_size));
        return rc;
  }
  
 -static void destroy_session(struct kref *ref)
 -{
 -      struct amdtee_session *sess = container_of(ref, struct amdtee_session,
 -                                                 refcount);
 -
 -      /* Unload the TA from TEE */
 -      handle_unload_ta(sess->ta_handle);
 -      mutex_lock(&session_list_mutex);
 -      list_del(&sess->list_node);
 -      mutex_unlock(&session_list_mutex);
 -      kfree(sess);
 -}
 -
  int amdtee_close_session(struct tee_context *ctx, u32 session)
  {
        struct amdtee_context_data *ctxdata = ctx->data;