tee-supplicant: add a framework for loadable plugins - #239
Conversation
|
The PR relates to: |
|
Why doesn't tee-supplicant read from the ringbuffer directly? |
Sorry, if I confused you. I have not started to code the logging framework discussed in OP-TEE/optee_os#4230 yet. This PR does not apply to the logger, because it is only about plugins. As an example I added a plugin named |
| }; | ||
|
|
||
| /* The bind function must save plugin methods into the passed argument */ | ||
| #define IMPLEMENT_PLUGIN_METHOD_BIND_FN(bind_func) \ |
There was a problem hiding this comment.
Why do we need a "bind" function when we have an init function too?
Couldn't we just as well do something like:
struct plugin_method {
const char *name; /* short friendly name of the plugin */
TEEC_UUID uuid;
int (*init)(void);
 int (*invoke)(int cmd, int sub_cmd, void *data, size_t len);
};And then in the plugin just declare
struct plugin_method plugin_method = {
...
};It a bit more direct and also removes the dependency on the file name.
|
|
||
| struct plugin_method { | ||
| int (*init)(void); | ||
| int (*invoke)(int cmd, int sub_cmd, void *data, size_t len); |
There was a problem hiding this comment.
unsigned int instead of just int?
|
All comments have been addressed |
| if (!p) | ||
| return TEEC_ERROR_ITEM_NOT_FOUND; | ||
|
|
||
| if (!p->method->invoke) |
There was a problem hiding this comment.
This "can't happen" since it was tested in load_plugin() above. An assert() should be enough.
| struct plugin_method { | ||
| const char *name; /* short friendly name of the plugin */ | ||
| TEEC_UUID uuid; | ||
| int (*init)(void); |
There was a problem hiding this comment.
Any reason why we're not returning a TEEC_Result instead here and for invoke() below?
There was a problem hiding this comment.
I think we can replace int to TEEC_Result
| if (res != 0) { | ||
| free(p); | ||
| EMSG("init the <%s> plugin failed with orig = %d", | ||
| p->method->name, res); |
| * Invoke a tee-supplicant plugin. | ||
| * | ||
| * [in] param[0].u.value.a OPTEE_INVOKE_PLUGIN | ||
| * [in] param[0].u.value.b uuid.d1 |
There was a problem hiding this comment.
We need to define byte order of the UUID. Consider the case when Secure world is little endian but Normal world is Big endian. These value words will then be swapped (in the driver, not supported now by the way) before transmission.
I think this should to be defined as in https://developer.arm.com/documentation/den0028/c/ section "5.3 Unique Identification format".
|
All comments have been addressed |
|
|
||
| static void uuid_from_octets(TEEC_UUID *d, const uint8_t s[TEE_IOCTL_UUID_LEN]) | ||
| { | ||
| d->timeLow = (s[0] << 24) | (s[1] << 16) | (s[2] << 8) | s[3]; |
There was a problem hiding this comment.
Does work (will the uint8_t automatically be promoted to unsigned int here)?
It seems more robust to either use a helper macro like SHIFT_U32() in https://github.com/OP-TEE/optee_os/blob/b68aca61f70193c8715a49748d13c77afe43aa1c/lib/libutils/ext/include/util.h#L117
or just cast each s[x] to uint32_t.
There was a problem hiding this comment.
I agree.
It seems we need common util.h file in optee-client project.
We can put into one all helpers which already exists in the tee_supplicant.c file (e.g. uuid_from_octets()), in the libcktee (file local_utils.h) and also SHIFT_U32(). But it should be done in separate MR.
So far I did casting each s[x] to uint32_t.
| * Copyright (c) 2020, Open Mobile Platform LLC | ||
| */ | ||
|
|
||
| #ifndef __TEE_PLUGIN_METHOD_H |
There was a problem hiding this comment.
Please drop the __ prefix. Those are reserved for libc and friends in user space.
We're using it in some files already, but let's not make matters worse.
|
|
||
| dir = opendir(TEE_PLUGIN_LOAD_PATH); | ||
| if (!dir) { | ||
| EMSG("could not open directory %s", TEE_PLUGIN_LOAD_PATH); |
There was a problem hiding this comment.
I suppose this isn't an error, please use IMSG() instead.
| /* This structure describes one plugin for the supplicant */ | ||
| struct plugin { | ||
| void *handle; | ||
| struct plugin_method *method; /* implemented by plugins' authors */ |
| } | ||
|
|
||
| if (plugin_load_all() != 0) { | ||
| EMSG("failed to load user's tee plugins"); |
| * Copyright (c) 2020, Open Mobile Platform LLC | ||
| */ | ||
|
|
||
| #ifndef __PLUGIN_H |
There was a problem hiding this comment.
Please drop the __ prefix.
|
All comments have been addressed |
| TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT) | ||
| return TEEC_ERROR_BAD_PARAMETERS; | ||
|
|
||
| uuid_words[0] = le32toh(params[0].b); |
There was a problem hiding this comment.
I'm sorry I was wrong about this swapping to make it little endian. I Recently got clarifications from Arm on this.
See https://www.spinics.net/lists/arm-kernel/msg868040.html
So please drop the le32toh() and we should be good.
There was a problem hiding this comment.
Thank you for the clarification
| #include <linux/tee.h> | ||
|
|
||
| /* internal possible returned values */ | ||
| enum { |
There was a problem hiding this comment.
Please give a name to this enum so that we can use the correct type when it's used.
|
All comments have been addressed |
| mkdir -p $(DESTDIR)$(SBINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCLUDEDIR) | ||
| mkdir -p $(DESTDIR)$(SBINDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCLUDEDIR) $(DESTDIR)$(PLUGINDIR) | ||
| mkdir -p $(MKDIR) | ||
| cp config.mk $(MKDIR) |
There was a problem hiding this comment.
When building with buildroot for ARMv7 $(MKDIR) seems to become host/arm-buildroot-linux-gnueabihf/sysroot/mk. This is far too likely to clash with other packages. I'd prefer something like:
cp config.mk $(DESTDIR)/optee_client_config.mk| cp libckteec/include/*.h $(DESTDIR)$(INCLUDEDIR) | ||
| cp -a ${O}/libckteec/libckteec.so* $(DESTDIR)$(LIBDIR) | ||
| cp -a ${O}/libckteec/libckteec.a $(DESTDIR)$(LIBDIR) | ||
| $(eval SUPP_PLUGINS := $(shell find ./tee-supplicant/plugins -name *.plugin)) |
There was a problem hiding this comment.
We do we need this when we don't have any plugins in this git?
There was a problem hiding this comment.
I think with these lines the plugin framework looks complete and ready to using.
I'd prefer keep ones here in case if someone will add own plugins in own fork.
In this case they won't have to edit the Makefile to build the plugins.
And also, these lines don't generate errors during building, if there are no plugins.
There was a problem hiding this comment.
I hope we can agree that this is dead code here in upstream.
What happens downstream we can't control, perhaps using a separate git for plugins is the preferred solution. We're demonstrating that in linaro-swg/optee_examples#79 so it seems at bit strange to promote another approach here.
There was a problem hiding this comment.
You're right.
I'll drop these lines
8fbca3c to
e931b3a
Compare
|
All comments have been addressed. |
| TEES_LFLAGS += -Wl,-rpath=$(CFG_TEE_PLUGIN_LOAD_PATH) | ||
|
|
||
| tee-supplicant: $(TEES_FILE) | ||
| tee-supplicant: $(TEES_FILE) plugins |
There was a problem hiding this comment.
I don't suppose we need the plugins target any longer. Please remove it here and elsewhere.
| @@ -0,0 +1,11 @@ | |||
| # Add new plugin dirs here | |||
There was a problem hiding this comment.
This file together with the tee-supplicant/plugins directory can be removed.
| PRIVATE teec | ||
| PRIVATE optee-client-headers) | ||
| PRIVATE optee-client-headers | ||
| PRIVATE dl) |
There was a problem hiding this comment.
Is this how the -ldl parameter get added when linking?
How is the -Wl,-rpath=$(CFG_TEE_PLUGIN_LOAD_PATH) parameter added?
There was a problem hiding this comment.
Is this how the -ldl parameter get added when linking?
Yes, it is.
How is the -Wl,-rpath=$(CFG_TEE_PLUGIN_LOAD_PATH) parameter added?
I've used CMAKE_INSTALL_RPATH. It is a variable embedded in cmake.
If I understood cmake specification right, the variable is needed to set a run-time search path.
|
Please squash in the fixup commits |
1a9c5a6 to
917f227
Compare
|
I'm sorry I didn't see the update before. It seems that github sometimes doesn't notify of a force-push. The safest is to add a comment once a force-push has been performed. Just a plain "Update" is good enough. |
jenswikl
left a comment
There was a problem hiding this comment.
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
This framework makes the supplicant a bit more flexible in terms of providing services. Any external TEE services can be designed as a tee-supplicant plugin. It makes it easy to: - add new features in the supplicant that aren't needed in upstream, e.g. Rich OS specific services; - sync upstream version with own fork; To create a plugin developers should implement the 'struct plugin_method'. See public/tee_plugin_method.h file. The plugin framework is based on new RPC call - 'OPTEE_MSG_RPC_CMD_PLUGIN'. This is an unified interface between TEE and any plugins. Every plugin has own name based on UUID. TEE has access to plugins only by this UUID. Every plugin should be placed into "/usr/lib/tee-supplicant/plugins/". See 'CFG_TEE_PLUGIN_LOAD_PATH' definition in config.mk. The supplicant opens and binds all plugins in the directory during startup process using libdl. After this any requests to plugins from TEE will be processed in the common RPC handler. Signed-off-by: Aleksandr Anisimov <a.anisimov@omprussia.ru> Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
917f227 to
9c859a2
Compare
|
Updated |
|
@anisyanka , can you please add documentation related with this feature by raising a PR in https://github.com/OP-TEE/optee_docs. |
|
@ruchi393, yes, good idea, thanks! |
This framework makes the supplicant a bit more flexible
in terms of providing services. Any external TEE services
can be designed as a tee-supplicant plugin.
It makes it easy to:
e.g. Rich OS specific services;
To create a plugin developers should implement the
'struct plugin_method' and a bind function.
See public/tee_plugin_method.h file.
As an example this patch implements a 'syslog' plugin
and its Makefile. The plugin helps to log any
information from TEE to system journal.
The plugin framework is based on new RPC call - 'OPTEE_MSG_RPC_CMD_PLUGIN'.
This RPC is an unified interface between TEE and any plugins.
Every plugin has own name based on UUID. TEE has access to
plugins only by the name (UUID).
Every plugin should be placed into "/usr/lib/tee-supplicant/plugins/".
The supplicant opens and binds all plugins in the directory during
startup process using libdl. After this any requests to plugins
from TEE will be processed in the common RPC handler.
Signed-off-by: Aleksandr Anisimov a.anisimov@omprussia.ru