OP-TEE / optee_os

Trusted side of the TEE
Other
1.56k stars 1.05k forks source link

GLOBEX - synchronization mechanism between REE/TEE #4539

Closed NightEugene closed 3 years ago

NightEugene commented 3 years ago

Hello everybody,

Recently there was a discussion of CAAM which revealed a lack of synchronization mechanisms between REE/TEE. We in OMP have faced the same issue while working on a TUI solution. To solve it, we've developed an IWd sync mechanism called "globex". Globex is a mutex-like named object which allows lock/unlock operations from both TEE and REE. Like mutex, globex provides a similar interface:

unsigned int globex_init(const char *name);
void globex_destroy(unsigned int id);
void globex_lock(unsigned int id);
void globex_unlock(unsigned int id);
int globex_trylock(unsigned int id);
int globex_is_locked(unsigned int id);

The core logic of implementation resides in TEE core and can be accessed in three ways:

image

For security reasons we store the globex structures in TEE and use a name (an arbitrary string identifying the particular globex instance) to initiate a globex, and then provide an id to the user.

The globex structure stores a name, a mutex, two reference counters (one for TEE, second for REE), a lock source, and the REE lock time.

enum globex_lock_src {
        GLOBEX_LOCK_SRC_NONE,
        GLOBEX_LOCK_SRC_TEE,
        GLOBEX_LOCK_SRC_REE, 
};

struct globex {
        char *name;
        struct mutex mutex;
        struct refcount rc_tee;
        struct refcount rc_ree;
        enum globex_lock_src lock_src;
        uint32_t lock_time_ree_ms[CFG_TEE_CORE_NB_CORE];
};

The name is used as an alias to a resource that we would like to have exclusive access to. For example, TEE and REE developers could decide to name touch panel resources "touch" and then acquire the globex of touch resources by globex_init("touch"). There is no way to initialize more than one globex with the same name, so developers can be sure that they operate the same globex.

Globexes store two reference counters and a lock source to avoid deadlocks and panics that could be caused by REE:

REE lock time is also required to avoid deadlock in TEE. If REE holds a globex for longer than the allowed time TEE should handle it (e.g. generate security event, reboot the device, etc).

Here are a couple of examples of how globex works.

How globex is initialized and destroyed image

How globex locking works image

What happens if we call globex destroy when globex is locked image

We use globexes in Aurora TEE to separate accesses to TUI resources and we are preparing the code to share with the community. Hopefuly globexes will help to share access to CAAM or TRNG between TEE and REE.

What do you think about it?

sunnybird commented 3 years ago

In my ideas . All TAs run depends CA called. if no CA called , SW will have no TA run . so , does the topic of "Synchronization mechanism between REE/TEE" is fake requirement . if we done well in all CAs Synchronization mechanism . your requrement can be solved?

kkarasev commented 3 years ago

Suggested mechanism aims to synchronize access to HW resources between REE and TEE - in that case one cannot assume whether resource will be busy or not, e.g. because of multicore.

UPD: maybe the naming is vague indeed.

jbech-linaro commented 3 years ago

Thanks Eugene for the intro to this today at the LOC meeting. I think had three main questions at the call.

1) As I said, I'd like to understand whether your proposal is something that is a new thing. I.e., there are no existing implementations out there doing the same (more or less). I doubt there are anything else, since it's pretty confined domain.

2) Security considerations for the actual buffer that we're "locking". I.e., the lock will tell NW or SW that "someone else" has already grabbed the lock, so you're not allowed to use this resource. But if NW are compromised. Can a hacker just ignore that and still try to use the resource that we're trying to protect. @kkarasev (I think it was ...) confirmed that there is indeed a need for a firewall as well in this use case.

3) Gyorgi was thinking that the locking mechanism could be implemented on the non-secure side only. Maybe worth thinking about the pros/cons by doing that.

Again, great to see that you've tried to sort out the TUI use case. We did look into it a couple of years ago, but we never came up with good solution for it.

Side note, it would probably be good to get some feedback from Linux kernel maintainers on this as well (not only TEE folks ... Jens), but people for example who use the framebuffer.

jforissier commented 3 years ago
struct globex {
        /* ... */
        uint32_t lock_time_ree_ms[CFG_TEE_CORE_NB_CORE];
};

If this represents the time the globex has been locked by the REE, a scalar should suffice, no?

jenswi-linaro commented 3 years ago

If a lock is already taken, how does the caller wait?

a-rybakov commented 3 years ago

Hello!

Please let me make some clarification for 2, 3.

2. Security considerations for the actual buffer that we're "locking". I.e., the lock will tell NW or SW that "someone else" has already grabbed the lock, so you're not allowed to use this resource. But if NW are compromised. Can a hacker just ignore that and still try to use the resource that we're trying to protect. @kkarasev (I think it was ...) confirmed that there is indeed a need for a firewall as well in this use case.

Globex may be considered as some kind of 'hint' to NW that resource now busy in SW, and access to it from NW side will cause to memory-firewall exception. So yes, globex supposed to be used in pair with other protection mechanisms such as TZASC, TZPC etc.

3. Gyorgi was thinking that the locking mechanism could be implemented on the non-secure side only. Maybe worth thinking about the pros/cons by doing that.

We implement globex only as Linux kernel mechanism, not for userspace applications in NW. This is based on following assumptions: a) apps which want to use some hw-resource will interact to kernel, and nature way to synchronize for them is synchronization inside krenel-driver b) there is a lot of applications which are do not know about Trust Zone, and their authors do not mind about sync with SW side. If we have only CA which interacts with SW, then yes, I suppose we can imagine mutex-like mechanism inside TEE Client library for sync set of CA in NW. But in theory SW can lock some resource from NW even without call from CA - for example, on boot stage, when OP-TEE kernel is initialized, but Linux kernel and, respectively, CA don`t started yet. c) (follows from b:) we do not want to force userspace applications programmers to get in mind sync with SW. And this is hard to maintain such sync - for example today we use one set of userspace applications, and tomorrow this set changed and programmers need to spent resources for add syncronization NW <-> SW again.

a-rybakov commented 3 years ago

If a lock is already taken, how does the caller wait?

Each globex contains corresponding mutex on SW side. When caller from NW try to get globex, then mutex in SW will be taken. If it was already locked, then execution will return to NW and sleep in NW while lock-owner didn`t released globex/mutex.

etienne-lms commented 3 years ago

I would fear a bit sharing a resource between firmware drivers. It's quite prone to corner case issues. Another way to address the initial issue could be to have an optee service for REE to use CAAM features.

jforissier commented 3 years ago

Another way to address the initial issue could be to have an optee service for REE to use CAAM features.

CAAM is just an example. The framebuffer with TUI is a more convincing one I think.

etienne-lms commented 3 years ago

I guess it's not the TUI framebuffer that is shared with a globex. The secure framebuffer would only be... secure, not shared. I imaging that Aurora TEE uses globex's for platform resources involved in display stuf, it is?

a-rybakov commented 3 years ago

I guess it's not the TUI framebuffer that is shared with a globex. The secure framebuffer would only be... secure, not shared. I imaging that Aurora TEE uses globex's for platform resources involved in display stuf, it is?

For now we make framebuffer "secure" by using memory firewall to block access from NW in time of TUI operations. And globex is used to force NW wait to prevent it from crashing on memory firewall exception.

etienne-lms commented 3 years ago

So no real need for globex on secure side. Non-secure should only invoke secure world to get and put the related resource. Maybe current optee mutex/cond-wait could address that.

a-rybakov commented 3 years ago

So no real need for globex on secure side. Non-secure should only invoke secure world to get and put the related resource. Maybe current optee mutex/cond-wait could address that.

Looks like you described how globex works). As I mentioned before in this thread, globex internally based on currently existed realisation of mutex in op-tee, and provide, in general, interface to get/put this mutex.

etienne-lms commented 3 years ago

Ok. I think existing optee mutex should do the job for the secure parts (simply use mutex_lock()/mute_unlock() without extra overhead. Globex looks rather to me about how to expose such optee-mutex resources to non-secure world, using clearly defined identifiers for lockable resources, including platforms hooks from some firewall specific reconfiguration.

github-actions[bot] commented 3 years ago

This issue has been marked as a stale issue because it has been open (more than) 30 days with no activity. Remove the stale label or add a comment, otherwise this issue will automatically be closed in 5 days. Note, that you can always re-open a closed issue at any time.