optee patch --- Trusted OS欣赏
我准备改写它, 它在这
https://github.com/leesagacious/optee_os_patch-x64
本文将发 100 个patch,让你明白
1 : Linaro 那些“乌合之众”(????)的作者用意何在,
2 : 该patch对 Trusted OS 的影响
3 : 对 Rich OS (Linux Kernel )的影响
4 : 更好的实现方法
5 : 攻击方法 (专业Attack destroyer ????,努力尝试让TEE也挂????)
帮你彻底明白 OP-TEE Latest version changes
好,那就开始吧… 哈哈 ???? ???? (看完烦请点个赞哦, 不足之处还请下面留评论,thanks .定回复)
1:core: fix the reopen session condition for single instance TA
你首先必须要明白的是
1 : 它的调用流程
2 : Trusted Application instance types
1:调用流程
/*
该函数是它的直接调用者,
该函数名字如意思 就是想初始化一个tee_ta_session
该tee_ta_session在本函数中是一个局部变量,最后本函数执行成功后会通过第4个
参数传出.
我们先看看它的caller传递给它哪些 resources,
下面A-0流程图显示该函数的"领导梯队"
*err : 返回值
看,上面的patch 重要性可见一斑了,如果 if 有失误(或者通过其他的方法destroy,就像patch fault一样),
session别想打开了,后面的一切都别想了,
*open_sessions : 一个全局的链表 tee_open_sessions ,
链表的作用无需多说,session都往上挂接吧,
什么时候用到了,直接find_session()取出
这里是一个可以改进的点,要找一个session,需要把链表全部查询一次,难道hash表做不到吗
*uuid : 这个重要了,身份证号,
Each Trusted Application is identified by a Universally Unique Identifier
好吧,以后会经常提到它的,这里先放放
**sess : out 参数,既有传出 又有传入 你家是开高速公路吧 ?
该函数的参数就决定了该函数能做什么, 就给你这么多资源,你自己玩吧
看到了吧,其实就是一个 UUID 在孤军深入, 其余的都是 no value !
*/
static TEE_Result tee_ta_init_session(TEE_ErrorOrigin *err,
struct tee_ta_session_head *open_sessions,
const TEE_UUID *uuid,
struct tee_ta_session **sess)
{
/*
上来你就弄一个返回值 嘿嘿????
*/
TEE_Result res;
/*
好了,下面会调用 tee_ta_context_find() 查找tee_ta_ctx 了
查找的依据就是那个 UUID,关键的是 找到了 tee_ta_ctx 它做了什么
就是本PATH的意思
tee_ta_ctx : Context of a loaded TA, 这里和 Linux Kernel 中的 Task Context 大一不样
*/
struct tee_ta_ctx *ctx;
/*
分配内存空间->赋值->挂接全局链表,
挂接链表方便以后find, remove,insert,地球人都知道了
*/
struct tee_ta_session *s = calloc(1, sizeof(struct tee_ta_session));
*err = TEE_ORIGIN_TEE;
if (!s)
return TEE_ERROR_OUT_OF_MEMORY;
/*
mask ? 却是一个 bool
client 可以随时取消打开一个session
关于这个 MaskCancellation 的问题有一大堆干货,这里不是重点
*/
s->cancel_mask = true;
/*
造了两把锁,
TA_FLAG_MULTI_SESSION 会造成并发的现象? 显然不是,
只是多个session, 最终还是串行调用,就像 Uart 独占性一样
*/
condvar_init(&s->refc_cv);
condvar_init(&s->lock_cv);
/*
这个lock_thread 在 debug page fault 的时候 没少跟你打交道
在创建session的时候就初始化为 -1 了
*/
s->lock_thread = THREAD_ID_INVALID;
/*
好了,重点来了 !
看 引用计数在这里 + 1 了
什么时机++ ,什么时机 -- ,为什么要++ 和 --
是理解该patch的一个重要的地方
*/
s->ref_count = 1;
/*
加锁了, 非重点 略过
*/
mutex_lock(&tee_ta_mutex);
/*
挂接到链表上去吧.
*/
TAILQ_INSERT_TAIL(open_sessions, s, link);
/*
根据UUID到 全局链表 tee_ctxes 链表上 查找 已经 load 的 TA
好,
1 : 那么是在什么时机将 tee_ta_ctx 添加到全局链表 tee_ctxes 上的 ?
2 : 显然这里如果找不到,我们上面的那个patch 将不会起作用了 ,????
作者将继续 Look static TA 、user TA,
如果都找不到,那么就 销毁分配给的资源无奈 return 从哪儿来还会到哪里去了
好,下面就是本patch了 先回答上面的几个问题,在往下看吧
*/
ctx = tee_ta_context_find(uuid);
if (ctx) {
res = tee_ta_init_session_with_context(ctx, s);
if (res == TEE_SUCCESS || res != TEE_ERROR_ITEM_NOT_FOUND)
goto out;
}
}
这里只考虑运行在Rich Execution Environment 中的 Client
不考虑TA 通过内部客户端API 来担当另一个TA的 client 的场景
TEE_Result tee_ta_close_session (...)
{
/*
下面会为它们赋值
*/
struct tee_ta_session *sess;
struct tee_ta_ctx *ctx;
....
/*
从open_sessions 链表上查找 获取session
*/
sess = tee_ta_get_session((vaddr_t)csess, true, open_sessions);
....
/*
获取session维护的 context TA
*/
ctx = sess->ctx;
....
/*
在close_session() 中将引用计数减少
是否能顺利的减少引用计数,上面还判断了该TA是否busy
什么样的TA是busy的,如何判断的,往下看吧
*/
ctx->ref_count--;
}
2 : Trusted Application instance types
1 : Multi Instance Trusted Application
2 : Single Instance Trusted Application
新增加了一个test_case ,创建了两个thread,每个thread都去open session
如下 :
对与 single instance TA ,客户端打开的所有的 session 都定向到该instance of the TA,
所有的session 共享该TA拥有的内存空间资源,
那么single instance TA 一定支持 多会话(TA_FLAG_MULTI_SESSION)了,看下面的macro
如果不支持TA_FLAG_MULTI_SESSION,那么一个TA 实例只支持一个 session
所以,本patch 478行,判断该TA实例是否支持多会话,
如果 不支持多会话且上一个会话还没有结束,那么就返回 TEE_ERROR_BUSY 了
它使用一个变量来标志会话是否结束在以后的patch中改变了这样的判断手法
#define PTA_MANDATORY_FLAGS (TA_FLAG_SINGLE_INSTANCE | \
TA_FLAG_MULTI_SESSION | \
TA_FLAG_INSTANCE_KEEP_ALIVE)