Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFC] Symbol versioning in libutee.so, the easy part #5833

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from

Conversation

jforissier
Copy link
Contributor

This RFC/Draft pull request applies versions GP_1.1 and GP_1.3.1 to GP API symbols when libutee is built as a shared object (dynamic library). It cannot work as is, because the dynamic loader (ldelf) lacks support for versioned symbols, see commit description for "[WIP] libutee: add symbol versioning for shared library". Such support has to be introduced first.

If anyone feels like working on the dynamic loader part, please feel free to do it and re-use these commits.

More details in https://docs.google.com/document/d/1qvN4WIIcmk3MGWdpdB3-hpg3oOErI7tgYbfGx9VR6FA.

To add link flags for a shared library, a makefile variable is used
that is called lib-ldflags$(libuuid). That's incorrect because the
UUID is not enough to uniquely identify a shared library in the build.
For example when both 32-bit and 64-bit user space is generated there
are two versions of the shared library with the same UUID. It is not
a problem at the moment because lib-ldflags$(libuuid) is used only
for one target: ta_arm64, but fix this anyways so that the variable
may be used for more complex cases.

Signed-off-by: Jerome Forissier <[email protected]>
If a user-space library such as lib/libutee is compiled as a shared
library (CFG_ULIBS_SHARED=y) and a file called lib/libutee/libutee.ver
exists, then use this file as a version script for the linker.

Signed-off-by: Jerome Forissier <[email protected]>
Add the SYMVER_GP131() and SYMVER_COMPAT_GP11() macros to help define
versioned symbols for functions when building shared libraries.

- SYMVER_GP131(foo) associates version GP_1.3.1 to symbol foo and
  makes it the default version, that is, the version that is recorded
  by the linker when a TA links against the shared library and references
  foo. Such a symbol is shown as foo@@GP_1.3.1 by the command:
    readelf -W --dyn-syms libname.so
  The undefined symbol created in the application by linking against
  this entry is displayed as foo@GP_1.3.1.
  Symbol foo (unversioned) is removed from the linker output.
- SYMVER_COMPAT_GP11(foo) defines symbol foo with version GP_1.1
  and makes it the same as the unversioned symbol __GP11_foo.

Signed-off-by: Jerome Forissier <[email protected]>
Add the required macros and version script to associate version numbers
with TEE API functions when libutee is built as a shared library
(CFG_ULIBS_SHARED=y).

The version script lib/libutee/libutee.ver declares two versions: GP_1.1
and GP_1.3.1. All symbols matching the glob pattern "TEE_[A-Z]*" are
tagged with default version GP_1.1 (TEE_foo@@GP_1.1), unless version
GP_1.3.1 is explicitly assigned in the source code via SYMVER_GP131().
In this case the default version symbol is GP_1.3.1 (TEE_foo@@GP_1.3.1).
All GP1.3.1 function have a compatibility inplementation called __GP11_*()
which is globally visible as an unversioned symbol (otherwise TAs that
use the __OPTEE_CORE_API_COMPAT_1_1 mechanism would not work) and also as
a versioned TEE_foo symbol with non-default version GP_1.1
(TEE_foo@GP_1.1).

The UUID of libutee is reverted to the one it had before the GP 1.3.1
update since the library is now compatible with the old one.

FIXME: THIS CAN NOT WORK until ldelf can resolve versioned symbols.
Test case: xtest 4002. There is an infinite loop as follows:
  __utee_entry()
    entry_open_session()
      init_instance()
        get_memtag_implementation
          TEE_GetPropertyAsU32()
            TEE_CheckMemoryAccessRights()
            /*
             * That should call 1.3.1 but due to ldelf not knowing
             * about versions, __GP11_TEE_CheckMemoryAccessRights()
             * is called instead, which is supposed to call
             * TEE_CheckMemoryAccessRights() 1.3.1 => infinite loop
             */

Signed-off-by: Jerome Forissier <[email protected]>
@@ -62,13 +63,17 @@ ifeq ($(CFG_ULIBS_SHARED),y)
ifeq ($(sm)-$(CFG_TA_BTI),ta_arm64-y)
lib-ldflags$(lib-shlibfile) += $$(call ld-option,-z force-bti) --fatal-warnings
endif
$(lib-shlibfile): $(objs) $(lib-needed-so-files)
ifneq (,$(wildcard $(lib-verscript)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not so sure about the wildcard, that could hide an invalid value in lib-verscript.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its purpose is to make the version script optional. $(lib-verscript) is well defined above and only depends on the name of the library, not on any user input. It is for example lib/libutee/libutee.ver or lib/libutils/libutils.ver etc. so it seems pretty natural to use wildcard to obtain the name of the file if it exist or empty otherwise, no?

@jenswi-linaro
Copy link
Contributor

"build: mk/lib.mk: use full path to shared library in flags variable" would make sense upstream by itself.

@jforissier
Copy link
Contributor Author

"build: mk/lib.mk: use full path to shared library in flags variable" would make sense upstream by itself.

Indeed. #5834.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants