сервер mbedtls DTLS, работающий на 64-разрядном рабочем столе, но не на встроенной системе

#multithreading #dtls #mbedtls

#многопоточность #dtls #mbedtls

Вопрос:

Я пытаюсь заменить UDP-связь сервером DTLS в своем приложении.

На моем компьютере (linux mint) запущен сервер DTLS, использующий mbedtls. Приложение выполняет чтение / запись без сбоев. (Хотя закрытие соединения еще не реализовано должным образом). Когда я запускаю свое приложение во встроенной системе (32-разрядный geode), приложение вылетает.

Ошибка сегментации возникает, когда функция чтения пытается получить доступ к части mbedtls_ssl_ctx (которая была перезаписана), как вы можете видеть из выходных данных gdb.

mbedtls_ssl_read и mbedtls_ssl_write вызываются из разных потоков и чтения / записи одновременно. Чтобы сделать его потокобезопасным, я включил MBEDTLS_THREADING_C и MBEDTS_THREADING_PTHREAD . (Это правильно?)

Настройка сервера DTLS реализована здесь. Он настраивается при подключении нового «узла» (клиента).

Может кто-нибудь сказать, есть ли ошибка при настройке сервера DTLS в целом?
Или что может вызвать эту ошибку?

вывод gdb:

 Thread 3 received signal SIGSEGV, Segmentation fault.
[Switching to Thread 3421.3485]
0x08912351 in mbedtls_debug_print_ret (ssl=0xa76d5c3c, level=2, 
    file=0x8ad259c "/home/github/mt_feature_security/implementation/dune/dune/vendor/libraries/mbedtls/library/ssl_msg.c", line=1853, text=0x8ad2bb9 "ssl->f_recv(_timeout)", ret=55)
    at /home/github/mt_feature_security/implementation/dune/dune/vendor/libraries/mbedtls/library/debug.c:115
115         NULL == ssl->conf->f_dbg ||
(gdb) bt
#0  0x08912351 in mbedtls_debug_print_ret (ssl=0xa76d5c3c, level=2, 
    file=0x8ad259c "/home/github/mt_feature_security/implementation/dune/dune/vendor/libraries/mbedtls/library/ssl_msg.c", line=1853, text=0x8ad2bb9 "ssl->f_recv(_timeout)", ret=55)
    at /home/github/mt_feature_security/implementation/dune/dune/vendor/libraries/mbedtls/library/debug.c:115
#1  0x08925319 in mbedtls_ssl_fetch_input (ssl=0xa76d5c3c, nb_want=13)
    at /home/github/mt_feature_security/implementation/dune/dune/vendor/libraries/mbedtls/library/ssl_msg.c:1853
#2  0x0892939b in ssl_get_next_record (ssl=0xa76d5c3c)
    at /home/github/mt_feature_security/implementation/dune/dune/vendor/libraries/mbedtls/library/ssl_msg.c:4379
#3  0x08928364 in mbedtls_ssl_read_record (ssl=0xa76d5c3c, update_hs_digest=1)
    at /home/github/mt_feature_security/implementation/dune/dune/vendor/libraries/mbedtls/library/ssl_msg.c:3727
#4  0x0892a76c in mbedtls_ssl_read (ssl=0xa76d5c3c, 
    buf=0x8d01ea0 <Security::DtlsServer::m_bfr> "", len=16383)
    at /home/github/mt_feature_security/implementation/dune/dune/vendor/libraries/mbedtls/library/ssl_msg.c:5265
#5  0x08701f5f in Security::DtlsServer::Node::read (this=0xa76d53d0)
    at /home/github/mt_feature_security/implementation/dune/dune/src/Security/DtlsServer/Node.cpp:548
#6  0x08702ec0 in Security::DtlsServer::Listener::run (this=0x8ddde40)
    at /home/github/mt_feature_security/implementation/dune/dune/src/Security/DtlsServer/Listener.cpp:94
--Type <RET> for more, q to quit, c to continue without paging--
#7  0x085d57d7 in dune_concurrency_thread_entry_point (data=0x8ddde40)
    at /home/github/mt_feature_security/implementation/dune/dune/src/DUNE/Concurrency/Thread.cpp:90
#8  0xa7fba12e in ?? () from target:/lib/libpthread.so.0
#9  0xa7ce67be in clone () from target:/lib/libc.so.6
(gdb) p *ssl
$1 = {conf = 0x66737365, state = 2037148789, renego_status = 1869772576, 
  renego_records_seen = 857761140, major_ver = 1646276913, minor_ver = 1936028793, 
  badmac_seen = 10, f_vrfy = 0x0, p_vrfy = 0x0, f_send = 0x0, f_recv = 0x0, f_recv_timeout = 0x0, 
  p_bio = 0x0, session_in = 0x0, session_out = 0x0, session = 0x0, session_negotiate = 0x0, 
  handshake = 0x0, transform_in = 0x0, transform_out = 0x0, transform = 0x0, 
  transform_negotiate = 0x0, p_timer = 0x0, f_set_timer = 0x0, f_get_timer = 0x0, in_buf = 0x0, 
  in_ctr = 0x0, in_hdr = 0x0, in_len = 0x0, in_iv = 0x0, in_msg = 0x0, in_offt = 0x0, 
  in_msgtype = 0, in_msglen = 0, in_left = 0, in_epoch = 0, next_record_offset = 0, 
  in_window_top = 0, in_window = 0, in_hslen = 0, nb_zero = 0, keep_current_message = 0, 
  disable_datagram_packing = 0 '00', out_buf = 0x0, out_ctr = 0x0, out_hdr = 0x0, out_len = 0x0, 
  out_iv = 0x0, out_msg = 0x0, out_msgtype = 0, out_msglen = 0, out_left = 0, 
  cur_out_ctr = "00000000000000", mtu = 0, client_auth = 0, hostname = 0x0, 
  alpn_chosen = 0x0, cli_id = 0x0, cli_id_len = 0, secure_renegotiation = 0, verify_data_len = 0, 
  own_verify_data = '00' <repeats 11 times>, peer_verify_data = '00' <repeats 11 times>, 
  f_export_keys = 0x0, p_export_keys = 0x0}
(gdb) 

 

Ответ №1:

Согласно базе знаний Mbed TLS:

один поток должен использовать или обращаться только к одному контексту одновременно, если:

  • В документации для функций, которые обращаются к общему контексту, явно указано, что функция потокобезопасна, или
  • Вы выполняете явную блокировку самостоятельно (возможно, в функции-оболочке).

В статье продолжается описание некоторых случаев, которые являются потокобезопасными. Контексты SSL не являются одним из них. Вам не разрешается использовать один и тот же контекст SSL в нескольких потоках, если вы не выполняете собственную блокировку.

Типичный способ распределения нагрузки между потоками — иметь разные потоки, отвечающие за разные соединения, но каждое соединение обрабатывается только одним потоком одновременно. Это работает с Mbed TLS при условии, что вы включите MBEDTLS_THREADING_C : он будет обрабатывать параллелизм для общих ресурсов, используемых во время квитирования (ключи подписи, билеты сеанса, кэш сеанса). Невозможно, чтобы один поток записывал, в то время как другой поток считывает данные с того же соединения.

Комментарии:

1. Привет, Жиль, спасибо за твой ответ. Я попытался защитить все функции, которые обращаются к контексту ssl (чтение, запись, отладка), используя мьютекс, но я получаю точно такой же результат. Что, насколько я понял, должно решить проблему. Есть предположения, почему это все еще происходит?

2. @KAMBLY Работает ли ваша программа, если вы ограничиваете ее одним потоком? Если это так, вы, вероятно, все еще где-то пропускаете мьютекс. К сожалению, такого рода ошибки могут быть очень сложными для отладки.