tpm2-software / tpm2-abrmd

TPM2 Access Broker & Resource Management Daemon implementing the TCG spec.
https://github.com/tpm2-software/tpm2-abrmd
BSD 2-Clause "Simplified" License
115 stars 97 forks source link

Accessing abrmd through openssl-engine leads to segfault when not run as user tss #545

Closed matthias1000 closed 5 years ago

matthias1000 commented 5 years ago

Hi,

this is a follow-up for the Issue https://github.com/tpm2-software/tpm2-tss-engine/issues/17 in the tpm2-tss-engine project.

Versions used: tpm2-tss, tpm2-abrmd and tpm2-tss-engine are all built using the latest versions from git.

OS: Linux Mint 19 VM: VMWare, no /dev/tpm0

I built tpm2-abrmd following all the instructions regarding the paths for Debian-like systems.

This is the output I get when I try to use openssl with the tpm2 engine, not as user tss:


me@pc ~/tpm/workspace $ openssl rand -engine tpm2tss -hex 10
engine "tpm2tss" set.
WARNING:esys:src/tss2-esys/esys_tcti_default.c:137:tcti_from_file() Could not load TCTI file: libtss2-tcti-default.so 
b67f72ad6bf8c91328a6
WARNING:esys:src/tss2-esys/esys_tcti_default.c:137:tcti_from_file() Could not load TCTI file: libtss2-tcti-default.so 

(process:32176): GLib-GIO-WARNING **: 18:11:38.793: (../../../../gio/gdbuserror.c:204):g_dbus_error_register_error_domain: runtime check failed: (g_dbus_error_register_error (quark, entries[n].error_code, entries[n].dbus_error_name))

(process:32176): GLib-GIO-WARNING **: 18:11:38.793: (../../../../gio/gdbuserror.c:204):g_dbus_error_register_error_domain: runtime check failed: (g_dbus_error_register_error (quark, entries[n].error_code, entries[n].dbus_error_name))

(process:32176): GLib-GIO-WARNING **: 18:11:38.794: (../../../../gio/gdbuserror.c:204):g_dbus_error_register_error_domain: runtime check failed: (g_dbus_error_register_error (quark, entries[n].error_code, entries[n].dbus_error_name))

(process:32176): GLib-GIO-WARNING **: 18:11:38.794: (../../../../gio/gdbuserror.c:204):g_dbus_error_register_error_domain: runtime check failed: (g_dbus_error_register_error (quark, entries[n].error_code, entries[n].dbus_error_name))

(process:32176): GLib-GIO-WARNING **: 18:11:38.794: (../../../../gio/gdbuserror.c:204):g_dbus_error_register_error_domain: runtime check failed: (g_dbus_error_register_error (quark, entries[n].error_code, entries[n].dbus_error_name))

(process:32176): GLib-GObject-WARNING **: 18:11:38.794: cannot register existing type 'TctiTabrmdProxy'

(process:32176): GLib-GObject-WARNING **: 18:11:38.794: cannot add private field to invalid (non-instantiatable) type '<invalid>'

(process:32176): GLib-GObject-WARNING **: 18:11:38.794: cannot register existing type 'TctiTabrmd'

(process:32176): GLib-GObject-CRITICAL **: 18:11:38.794: g_type_interface_add_prerequisite: assertion 'G_TYPE_IS_INTERFACE (interface_type)' failed

(process:32176): GLib-CRITICAL **: 18:11:38.794: g_once_init_leave: assertion 'result != 0' failed

(process:32176): GLib-GObject-CRITICAL **: 18:11:38.794: g_type_add_interface_static: assertion 'G_TYPE_IS_INSTANTIATABLE (instance_type)' failed

(process:32176): GLib-CRITICAL **: 18:11:38.794: g_once_init_leave: assertion 'result != 0' failed

(process:32176): GLib-GIO-CRITICAL **: 18:11:38.794: g_initable_new_valist: assertion 'G_TYPE_IS_INITABLE (object_type)' failed
Segmentation fault (core dumped)

The segmentation fault seems to be a bug. Judging from the error messages the problem seems to lie in abrmd/dbus.

Running the same as user tss I get the expected random numbers.

The dbus name is registered correctly though:


me@pc ~/tpm/workspace $ dbus-send --system --dest=org.freedesktop.DBus --type=method_call --print-reply /org/freedesktop/DBus org.freedesktop.DBus.ListNames
method return time=1539335221.444933 sender=org.freedesktop.DBus -> destination=:1.103 serial=3 reply_serial=2
   array [
      <<<<<<<<<<<<<< output omitted
      string ":1.18"
      string "com.intel.tss2.Tabrmd"
      string ":1.6"
   ]

Regards, Matthias

flihp commented 5 years ago

thx for the detailed report, added to the queue. I'm sorting out another issue that's on the client side of this in #541. Will take this on after.

diabonas commented 5 years ago

The same issue occurs in https://github.com/AndreasFuchsSIT/tpm2-totp/issues/1 as well. I can also reproduce the error with tpm2-tss-engine reported by @matthias1000, but only when requesting significantly more random bytes, e.g. openssl rand -engine tpm2tss -hex 5000: the rand_bytes function needs to be called twice for the segfault to occur. On my machine, running as the tss user does not resolve the error.

diabonas commented 5 years ago

The error seems to occur if the ESAPI is used and a context is closed with Esys_Finalize, then a new context is opened with Esys_Initialize: an extremely simple program to produce the error is

#include <stdio.h>
#include <tss2/tss2_esys.h>
void main(void) {
    ESYS_CONTEXT *ctx;
    for (int i = 0; i < 2; i++) {
        fprintf(stderr, "Calling Esys_Initialize\n");
        Esys_Initialize(&ctx, NULL, NULL);
        fprintf(stderr, "Calling Esys_Finalize\n");
        Esys_Finalize(&ctx);
    }
}

generating the following output:

$ gcc -o crash crash.c -ltss2-esys
$ TSS2_LOG=esys+trace G_MESSAGES_DEBUG=all ./crash
Calling Esys_Initialize
debug:esys:src/tss2-esys/esys_tcti_default.c:191:get_tcti_default() Attempting to connect using standard TCTI: Access libtss2-tcti-default.so 
trace:esys:src/tss2-esys/esys_tcti_default.c:133:tcti_from_file() Attempting to load TCTI file: libtss2-tcti-default.so 
trace:esys:src/tss2-esys/esys_tcti_default.c:100:tcti_from_info() Attempting to load TCTI info 
trace:esys:src/tss2-esys/esys_tcti_default.c:107:tcti_from_info() Loaded TCTI info named: tcti-device 
trace:esys:src/tss2-esys/esys_tcti_default.c:108:tcti_from_info() TCTI description: TCTI module for communication with Linux kernel interface. 
trace:esys:src/tss2-esys/esys_tcti_default.c:109:tcti_from_info() TCTI config_help: Path to TPM character device. Default value is: TCTI_DEVICE_DEFAULT 
trace:esys:src/tss2-esys/esys_tcti_default.c:67:tcti_from_init() Initializing TCTI for config: (null) 
ERROR:tcti:src/tss2-tcti/tcti-device.c:319:Tss2_Tcti_Device_Init() Failed to open device file /dev/tpm0: Permission denied 
WARNING:esys:src/tss2-esys/esys_tcti_default.c:83:tcti_from_init() TCTI init for function 0x7fdda7c8eb20 failed with a000a 
WARNING:esys:src/tss2-esys/esys_tcti_default.c:113:tcti_from_info() Could not initialize TCTI named: tcti-device 
ERROR:esys:src/tss2-esys/esys_tcti_default.c:150:tcti_from_file() Could not initialize TCTI file: libtss2-tcti-default.so 
debug:esys:src/tss2-esys/esys_tcti_default.c:204:get_tcti_default() Failed to load standard TCTI number 0 
debug:esys:src/tss2-esys/esys_tcti_default.c:191:get_tcti_default() Attempting to connect using standard TCTI: Access libtss2-tcti-tabrmd.so 
trace:esys:src/tss2-esys/esys_tcti_default.c:133:tcti_from_file() Attempting to load TCTI file: libtss2-tcti-tabrmd.so 
trace:esys:src/tss2-esys/esys_tcti_default.c:100:tcti_from_info() Attempting to load TCTI info 
trace:esys:src/tss2-esys/esys_tcti_default.c:107:tcti_from_info() Loaded TCTI info named: tcti-abrmd 
trace:esys:src/tss2-esys/esys_tcti_default.c:108:tcti_from_info() TCTI description: TCTI module for communication with tabrmd. 
trace:esys:src/tss2-esys/esys_tcti_default.c:109:tcti_from_info() TCTI config_help: This conf string is a series of key / value pairs where keys and values are separated by the '=' character and each pair is separated by the ',' character. Valid keys are "bus_name" and "bus_type". 
trace:esys:src/tss2-esys/esys_tcti_default.c:67:tcti_from_init() Initializing TCTI for config:  
** (process:20009): DEBUG: 17:27:56.438: parse_key_value_string: kv_str: "", callback: 0x7fdda7bfab80, user_data: 0x7ffe2a534f90
** (process:20009): DEBUG: 17:27:56.454: initialized tabrmd TCTI context with id: 0x3c1a31618b9bb293
debug:esys:src/tss2-esys/esys_tcti_default.c:89:tcti_from_init() Initialized TCTI for config:  
debug:esys:src/tss2-esys/esys_tcti_default.c:117:tcti_from_info() Initialized TCTI named: tcti-abrmd 
debug:esys:src/tss2-esys/esys_tcti_default.c:158:tcti_from_file() Initialized TCTI file: libtss2-tcti-tabrmd.so 
Calling Esys_Finalize
** (process:20009): DEBUG: 17:27:56.454: tss2_tcti_tabrmd_finalize
Calling Esys_Initialize
debug:esys:src/tss2-esys/esys_tcti_default.c:191:get_tcti_default() Attempting to connect using standard TCTI: Access libtss2-tcti-default.so 
trace:esys:src/tss2-esys/esys_tcti_default.c:133:tcti_from_file() Attempting to load TCTI file: libtss2-tcti-default.so 
trace:esys:src/tss2-esys/esys_tcti_default.c:100:tcti_from_info() Attempting to load TCTI info 
trace:esys:src/tss2-esys/esys_tcti_default.c:107:tcti_from_info() Loaded TCTI info named: tcti-device 
trace:esys:src/tss2-esys/esys_tcti_default.c:108:tcti_from_info() TCTI description: TCTI module for communication with Linux kernel interface. 
trace:esys:src/tss2-esys/esys_tcti_default.c:109:tcti_from_info() TCTI config_help: Path to TPM character device. Default value is: TCTI_DEVICE_DEFAULT 
trace:esys:src/tss2-esys/esys_tcti_default.c:67:tcti_from_init() Initializing TCTI for config: (null) 
ERROR:tcti:src/tss2-tcti/tcti-device.c:319:Tss2_Tcti_Device_Init() Failed to open device file /dev/tpm0: Permission denied 
WARNING:esys:src/tss2-esys/esys_tcti_default.c:83:tcti_from_init() TCTI init for function 0x7fdda7c8eb20 failed with a000a 
WARNING:esys:src/tss2-esys/esys_tcti_default.c:113:tcti_from_info() Could not initialize TCTI named: tcti-device 
ERROR:esys:src/tss2-esys/esys_tcti_default.c:150:tcti_from_file() Could not initialize TCTI file: libtss2-tcti-default.so 
debug:esys:src/tss2-esys/esys_tcti_default.c:204:get_tcti_default() Failed to load standard TCTI number 0 
debug:esys:src/tss2-esys/esys_tcti_default.c:191:get_tcti_default() Attempting to connect using standard TCTI: Access libtss2-tcti-tabrmd.so 
trace:esys:src/tss2-esys/esys_tcti_default.c:133:tcti_from_file() Attempting to load TCTI file: libtss2-tcti-tabrmd.so 
trace:esys:src/tss2-esys/esys_tcti_default.c:100:tcti_from_info() Attempting to load TCTI info 
trace:esys:src/tss2-esys/esys_tcti_default.c:107:tcti_from_info() Loaded TCTI info named: tcti-abrmd 
trace:esys:src/tss2-esys/esys_tcti_default.c:108:tcti_from_info() TCTI description: TCTI module for communication with tabrmd. 
trace:esys:src/tss2-esys/esys_tcti_default.c:109:tcti_from_info() TCTI config_help: This conf string is a series of key / value pairs where keys and values are separated by the '=' character and each pair is separated by the ',' character. Valid keys are "bus_name" and "bus_type". 
trace:esys:src/tss2-esys/esys_tcti_default.c:67:tcti_from_init() Initializing TCTI for config:  
** (process:20009): DEBUG: 17:27:56.457: parse_key_value_string: kv_str: "", callback: 0x7fdda7bfab80, user_data: 0x7ffe2a534f90

(process:20009): GLib-GIO-WARNING **: 17:27:56.458: (../glib/gio/gdbuserror.c:204):g_dbus_error_register_error_domain: runtime check failed: (g_dbus_error_register_error (quark, entries[n].error_code, entries[n].dbus_error_name))

(process:20009): GLib-GIO-WARNING **: 17:27:56.458: (../glib/gio/gdbuserror.c:204):g_dbus_error_register_error_domain: runtime check failed: (g_dbus_error_register_error (quark, entries[n].error_code, entries[n].dbus_error_name))

(process:20009): GLib-GIO-WARNING **: 17:27:56.458: (../glib/gio/gdbuserror.c:204):g_dbus_error_register_error_domain: runtime check failed: (g_dbus_error_register_error (quark, entries[n].error_code, entries[n].dbus_error_name))

(process:20009): GLib-GIO-WARNING **: 17:27:56.458: (../glib/gio/gdbuserror.c:204):g_dbus_error_register_error_domain: runtime check failed: (g_dbus_error_register_error (quark, entries[n].error_code, entries[n].dbus_error_name))

(process:20009): GLib-GIO-WARNING **: 17:27:56.458: (../glib/gio/gdbuserror.c:204):g_dbus_error_register_error_domain: runtime check failed: (g_dbus_error_register_error (quark, entries[n].error_code, entries[n].dbus_error_name))

(process:20009): GLib-GObject-WARNING **: 17:27:56.458: cannot register existing type 'TctiTabrmdProxy'

(process:20009): GLib-GObject-WARNING **: 17:27:56.458: cannot add private field to invalid (non-instantiatable) type '<invalid>'

(process:20009): GLib-GObject-WARNING **: 17:27:56.458: cannot register existing type 'TctiTabrmd'

(process:20009): GLib-GObject-CRITICAL **: 17:27:56.458: g_type_interface_add_prerequisite: assertion 'G_TYPE_IS_INTERFACE (interface_type)' failed

(process:20009): GLib-CRITICAL **: 17:27:56.458: g_once_init_leave: assertion 'result != 0' failed

(process:20009): GLib-GObject-CRITICAL **: 17:27:56.458: g_type_add_interface_static: assertion 'G_TYPE_IS_INSTANTIATABLE (instance_type)' failed

(process:20009): GLib-CRITICAL **: 17:27:56.458: g_once_init_leave: assertion 'result != 0' failed

(process:20009): GLib-GIO-CRITICAL **: 17:27:56.458: g_initable_new_valist: assertion 'G_TYPE_IS_INITABLE (object_type)' failed
Segmentation fault (core dumped)
diabonas commented 5 years ago

Apparently the problem is that Esys_Finalize issues a dlclose for libtss2-tcti-tabrmd.so, if I remove it, everything works as expected. Is there anything that can be done on the tpm2-abrmd side such that the sequence

handle = dlopen("libtss2-tcti-tabrmd.so");
Tss2_Tcti_Tabrmd_Init(...);
Tss2_Tcti_Finalize(...);
dlclose(handle);
handle = dlopen("libtss2-tcti-tabrmd.so");
Tss2_Tcti_Tabrmd_Init(...);

works without a segfault, or does this need to be addressed in tpm2-tss?

AndreasFuchsTPM commented 5 years ago

IMHO, dlopen->dlclose->dlopen should be a correct sequence. Thus, this should be a tcti-tabrmd issue.

Are there any global state in tcti-tabrmd or maybe in a subsequently loaded libdbus ? Or is this maybe even a GObject thing ?

diabonas commented 5 years ago

@AndreasFuchsSIT My guess would also bet that it is something like a static variable that gets deleted when unloading libtss2-tcti-tabrmd.so. It appears to be something directly related to the TCTI library, not libdbus or libgobject:

To prevent unloading of the library, I linked my test program with -ltss2-tcti-tabrmd, which makes it run successfully. If I remove -ltss2-tcti-tabrmd and instead only link against all libraries that it additionally pulls in (-ldbus-1, -lgio-2.0 -lgobject-2.0, -lglib, ...) to stop these from unloading, the program still crashes. Only when I readd -ltss2-tcti-tabrmd, the segfault disappears.