OpenSSL 1.1 result in error: variable has initializer but incomplete type static BIO_METHOD
Vincent Li
vincent.mc.li at gmail.com
Wed Jul 1 21:07:26 UTC 2020
On Wed, 1 Jul 2020, Vincent Li wrote:
>
> Hi,
>
> I am running apache bench (ab) and ported it with OpenSSL 1.0 support on top of mTCP support
>
> https://github.com/vincentmli/mtcp/commit/642835f786aa642ea0f20fe8db9b09054639453a#diff-02f7a72f514e6e0543e832d37450c251
>
> but it breaks after I upgraded OpenSSL 1.0 to OpenSSL 1.1, I found there
> are quite a few projects having same problems including libevent, libevent
> has the fix in https://github.com/libevent/libevent/commit/3e9e0a0d46e4508e8782ec3787c6d86bab63046d
>
> so I borrowed the fix from libevent and applied the code fix below:
>
> ```
> #include <openssl/bio.h>
> #include "openssl-compat.h"
> #define get_last_socket_error() errno
> #define clear_socket_error() errno=0
> /* clone of openssl crypto/bio/bss_sock.c */
>
> #ifdef HAVE_MTCP
>
> static int mtcp_sock_write(BIO *h, const char *buf, int num);
> static int mtcp_sock_read(BIO *h, char *buf, int size);
> static int mtcp_sock_puts(BIO *h, const char *str);
> static long mtcp_sock_ctrl(BIO *h, int cmd, long arg1, void *arg2);
> static int mtcp_sock_new(BIO *h);
> static int mtcp_sock_free(BIO *data);
> int BIO_mtcp_sock_should_retry(int s);
.........SNIP.........
>
> static long mtcp_sock_ctrl(BIO *b, int cmd, long num, void *ptr)
> {
> long ret = 1;
> int *ip;
>
> switch (cmd) {
> case BIO_C_SET_FD:
> mtcp_sock_free(b);
> BIO_set_num(b, *((int *)ptr));
> BIO_set_shutdown(b, (int)num);
> BIO_set_init(b, 1);
> break;
> case BIO_C_GET_FD:
> if (BIO_get_init(b)) {
> ip = (int *)ptr;
> if (ip != NULL)
> *ip = BIO_get_num(b);
> ret = BIO_get_num(b);
> } else
> ret = -1;
> break;
> case BIO_CTRL_GET_CLOSE:
> ret = BIO_get_shutdown(b);
> break;
> case BIO_CTRL_SET_CLOSE:
> BIO_set_shutdown(b, (int)num);
> break;
> case BIO_CTRL_DUP:
> case BIO_CTRL_FLUSH:
> ret = 1;
> break;
> default:
> ret = 0;
> break;
> }
> return (ret);
> }
I found http://vega.pgw.jp/~kabe/vsd/migrate2openssl-1.1.html which says:
"bio->num (file descripter) could be set by BIO_set_fd(), but since this
callbacks the routine set by BIO_meth_set_ctrl(biom, BioCtrl), beware of
infinite loops. Recommend to not touch bio->num member and leave it
alone."
so I used BIO_set/get_fd() to work with the bio->num, it compiles ok with
some warnings, but it appears I hit the infinite loops and core dump:
root at vli-lab:/usr/src/mtcp/apps/apache_benchmark/support# cp .libs/ab .
root at vli-lab:/usr/src/mtcp/apps/apache_benchmark/support# gdb --args ab -N 4 -c 4 -n 160 https://10.2.1.63/
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
...........SNIP............
Checking link status..done
Port 0 Link Up - speed 10000 Mbps - full-duplex
Benchmarking 10.2.1.63 (be patient)
[New Thread 0x7fdff19fb700 (LWP 1510)]
CPU0 connecting to port 443
[New Thread 0x7fdff11fa700 (LWP 1511)]
[New Thread 0x7fdff09f9700 (LWP 1512)]
CPU1 connecting to port 443
[New Thread 0x7fdfea6fe700 (LWP 1513)]
CPU2 connecting to port 443
[New Thread 0x7fdfd7fff700 (LWP 1514)]
CPU3 connecting to port 443
CPU 0: initialization finished.
[mtcp_create_context:1359] CPU 0 is now the master thread.
[CPU 0] dpdk0 flows: 0, RX: 0(pps) (err: 0), 0.00(Gbps),
TX: 0(pps), 0.00(Gbps)
[ ALL ] dpdk0 flows: 0, RX: 0(pps) (err: 0), 0.00(Gbps),
TX: 0(pps), 0.00(Gbps)
Thread 8 "ab" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7fdff19fb700 (LWP 1510)]
0x00005555555dd3cd in mtcp_sock_ctrl (b=0x7fdfe4003dd0, cmd=105, num=0,
ptr=0x560af680, close_flag=1443559040) at ab.c:692
692 switch (cmd) {
(gdb) bt
#0 0x00005555555dd3cd in mtcp_sock_ctrl (b=0x7fdfe4003dd0, cmd=105,
num=0, ptr=0x560af680, close_flag=1443559040) at ab.c:692
#1 0x00007ffff6474949 in BIO_ctrl () from
/usr/lib/x86_64-linux-gnu/libcrypto.so.1.1
#2 0x00005555555dd3fb in mtcp_sock_ctrl (b=0x7fdfe4003dd0, cmd=<optimized
out>, num=<optimized out>, ptr=0x560af680,
close_flag=1443559040) at ab.c:703
#3 0x00007ffff6474949 in BIO_ctrl () from
/usr/lib/x86_64-linux-gnu/libcrypto.so.1.1
#4 0x00005555555dd3fb in mtcp_sock_ctrl (b=0x7fdfe4003dd0, cmd=<optimized
out>, num=<optimized out>, ptr=0x560af680,
close_flag=1443559040) at ab.c:703
#5 0x00007ffff6474949 in BIO_ctrl () from
/usr/lib/x86_64-linux-gnu/libcrypto.so.1.1
#6 0x00005555555dd3fb in mtcp_sock_ctrl (b=0x7fdfe4003dd0, cmd=<optimized
out>, num=<optimized out>, ptr=0x560af680,
close_flag=1443559040) at ab.c:703
....loop continues....
How do I avoid the loops?
here is the changed code:
#ifdef USE_SSL
#ifndef OPENSSL_NO_SOCK
#include <openssl/bio.h>
#include "openssl-compat.h"
#define get_last_socket_error() errno
#define clear_socket_error() errno=0
/* clone of openssl crypto/bio/bss_sock.c */
#ifdef HAVE_MTCP
static int mtcp_sock_write(BIO *h, const char *buf, int num, int
close_flag);
static int mtcp_sock_read(BIO *h, char *buf, int size, int close_flag);
static int mtcp_sock_puts(BIO *h, const char *str, int close_flag);
static long mtcp_sock_ctrl(BIO *h, int cmd, long arg1, void *arg2, int
close_flag);
static int mtcp_sock_new(BIO *h);
static int mtcp_sock_free(BIO *data, int close_flag);
int BIO_mtcp_sock_should_retry(int s);
static BIO_METHOD *mtcp_methods_sockp;
static BIO_METHOD *
BIO_mtcp_s_socket(void)
{
if (mtcp_methods_sockp == NULL) {
mtcp_methods_sockp = BIO_meth_new(BIO_TYPE_SOCKET,
"socket");
if (mtcp_methods_sockp == NULL)
return NULL;
BIO_meth_set_write(mtcp_methods_sockp, mtcp_sock_write);
BIO_meth_set_read(mtcp_methods_sockp, mtcp_sock_read);
BIO_meth_set_puts(mtcp_methods_sockp, mtcp_sock_puts);
BIO_meth_set_ctrl(mtcp_methods_sockp, mtcp_sock_ctrl);
BIO_meth_set_create(mtcp_methods_sockp, mtcp_sock_new);
BIO_meth_set_destroy(mtcp_methods_sockp, mtcp_sock_free);
}
return mtcp_methods_sockp;
}
BIO *BIO_mtcp_new_socket(mctx_t mctx, int fd, int close_flag)
{
BIO *ret;
if(!fd)
return NULL;
ret = BIO_new(BIO_mtcp_s_socket());
if (ret == NULL)
return (NULL);
BIO_set_init(ret, 1);
BIO_set_fd(ret, fd, close_flag);
BIO_set_data(ret, mctx);
return (ret);
}
static int mtcp_sock_new(BIO *bi)
{
BIO_set_init(bi, 0);
// BIO_set_fd(bi, fd, close_flag)
BIO_set_data(bi, NULL);
BIO_set_flags(bi, 0);
return (1);
}
static int mtcp_sock_free(BIO *a, int close_flag)
{
if (a == NULL)
return (0);
mctx_t mctx = (mctx_t)BIO_get_data(a);
mtcp_close(mctx, BIO_get_fd(a, close_flag));
return (1);
}
static int mtcp_sock_read(BIO *b, char *out, int outl, int close_flag)
{
int ret = 0;
mctx_t mctx = (mctx_t)BIO_get_data(b);
if (out != NULL) {
clear_socket_error();
//ret = readsocket(b->num, out, outl);
ret = mtcp_read(mctx, BIO_get_fd(b, close_flag), out, outl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (BIO_mtcp_sock_should_retry(ret))
BIO_set_retry_read(b);
}
}
return (ret);
}
static int mtcp_sock_write(BIO *b, const char *in, int inl, int
close_flag)
{
int ret;
mctx_t mctx = (mctx_t)BIO_get_data(b);
clear_socket_error();
//ret = writesocket(b->num, in, inl);
ret = mtcp_write(mctx, BIO_get_fd(b, close_flag), in, inl);
BIO_clear_retry_flags(b);
if (ret <= 0) {
if (BIO_mtcp_sock_should_retry(ret))
BIO_set_retry_write(b);
}
return (ret);
}
static long mtcp_sock_ctrl(BIO *b, int cmd, long num, void *ptr, int
close_flag)
{
long ret = 1;
int *ip;
switch (cmd) {
case BIO_C_SET_FD:
mtcp_sock_free(b, close_flag);
BIO_set_fd(b, *((int *)ptr), close_flag);
BIO_set_shutdown(b, (int)num);
BIO_set_init(b, 1);
break;
case BIO_C_GET_FD:
if (BIO_get_init(b)) {
ip = (int *)ptr;
if (ip != NULL)
*ip = BIO_get_fd(b, close_flag);
ret = BIO_get_fd(b, close_flag);
} else
ret = -1;
break;
case BIO_CTRL_GET_CLOSE:
ret = BIO_get_shutdown(b);
break;
case BIO_CTRL_SET_CLOSE:
BIO_set_shutdown(b, (int)num);
break;
case BIO_CTRL_DUP:
case BIO_CTRL_FLUSH:
ret = 1;
break;
default:
ret = 0;
break;
}
return (ret);
}
static int mtcp_sock_puts(BIO *bp, const char *str, int close_flag)
{
int n, ret;
n = strlen(str);
ret = mtcp_sock_write(bp, str, n, close_flag);
return (ret);
}
More information about the openssl-users
mailing list