From cd5f1904032e9fcb62ad8094addc841a6b9cb73a Mon Sep 17 00:00:00 2001 From: Amitay Isaacs Date: Wed, 11 Jul 2018 18:35:46 +1000 Subject: ctdb-protocol: Avoid fgets in ctdb_connection_list_read C library buffering API can behave in unexpected fashion if underlying fd for stdin, stdout or stderr is closed and re-opened. BUG: https://bugzilla.samba.org/show_bug.cgi?id=13520 Signed-off-by: Amitay Isaacs Reviewed-by: Martin Schwenke (cherry picked from commit c9b42d27e6cf9e6ae36f44970f0a388edc737a7a) --- ctdb/protocol/protocol_util.c | 86 ++++++++++++++++++++++++------------------- ctdb/wscript | 4 +- 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/ctdb/protocol/protocol_util.c b/ctdb/protocol/protocol_util.c index c75555fa734..45c639d747f 100644 --- a/ctdb/protocol/protocol_util.c +++ b/ctdb/protocol/protocol_util.c @@ -22,6 +22,8 @@ #include +#include "common/line.h" + #include "protocol.h" #include "protocol_util.h" @@ -603,56 +605,66 @@ const char *ctdb_connection_list_to_string( return out; } -int ctdb_connection_list_read(TALLOC_CTX *mem_ctx, bool client_first, - struct ctdb_connection_list **conn_list) -{ +struct ctdb_connection_list_read_state { struct ctdb_connection_list *list; - char line[128]; /* long enough for IPv6 */ + bool client_first; +}; + +static int ctdb_connection_list_read_line(char *line, void *private_data) +{ + struct ctdb_connection_list_read_state *state = + (struct ctdb_connection_list_read_state *)private_data; + struct ctdb_connection conn; int ret; - if (conn_list == NULL) { - return EINVAL; + /* Skip empty lines */ + if (line[0] == '\0') { + return 0; } - list = talloc_zero(mem_ctx, struct ctdb_connection_list); - if (list == NULL) { - return ENOMEM; + /* Comment */ + if (line[0] == '#') { + return 0; } - while (fgets(line, sizeof(line), stdin) != NULL) { - char *t; - struct ctdb_connection conn; + ret = ctdb_connection_from_string(line, state->client_first, &conn); + if (ret != 0) { + return ret; + } - /* Skip empty lines */ - if (line[0] == '\n') { - continue; - } + ret = ctdb_connection_list_add(state->list, &conn); + if (ret != 0) { + return ret; + } - /* Comment */ - if (line[0] == '#') { - continue; - } + return 0; +} - t = strtok(line, "\n"); - if (t == NULL) { - goto fail; - } +int ctdb_connection_list_read(TALLOC_CTX *mem_ctx, bool client_first, + struct ctdb_connection_list **conn_list) +{ + struct ctdb_connection_list_read_state state; + int ret; - ret = ctdb_connection_from_string(t, client_first, &conn); - if (ret != 0) { - goto fail; - } + if (conn_list == NULL) { + return EINVAL; + } - ret = ctdb_connection_list_add(list, &conn); - if (ret != 0) { - goto fail; - } + state.list = talloc_zero(mem_ctx, struct ctdb_connection_list); + if (state.list == NULL) { + return ENOMEM; } - *conn_list = list; - return 0; + state.client_first = client_first; + + ret = line_read(0, + 128, + mem_ctx, + ctdb_connection_list_read_line, + &state, + NULL); -fail: - talloc_free(list); - return EINVAL; + *conn_list = state.list; + + return ret; } diff --git a/ctdb/wscript b/ctdb/wscript index e3bcdf7e962..8727fd8aefa 100644 --- a/ctdb/wscript +++ b/ctdb/wscript @@ -433,7 +433,7 @@ def build(bld): bld.SAMBA_SUBSYSTEM('ctdb-protocol-util', source='protocol/protocol_util.c', - deps='replace talloc tdb') + deps='ctdb-util replace talloc tdb') bld.SAMBA_SUBSYSTEM('ctdb-client', source=bld.SUBDIR('client', 'ctdb_client.c'), @@ -824,7 +824,7 @@ def build(bld): bld.SAMBA_BINARY(target, source=src, deps='''protocol-tests-common - samba-util talloc tdb''', + samba-util ctdb-util talloc tdb''', install_path='${CTDB_TEST_LIBEXECDIR}') bld.SAMBA_SUBSYSTEM('ctdb-tests-common', -- cgit v1.2.1