From 3b86c24183857f87f8a05f6ebd52588a5e556e1a Mon Sep 17 00:00:00 2001 From: Amitay Isaacs Date: Fri, 30 Jun 2017 17:15:47 +1000 Subject: [PATCH] ctdb-protocol: Fix marshalling for tdb_data Signed-off-by: Amitay Isaacs Reviewed-by: Martin Schwenke --- ctdb/protocol/protocol_call.c | 86 +++++++++++++++------------- ctdb/protocol/protocol_message.c | 19 +++--- ctdb/protocol/protocol_private.h | 6 +- ctdb/protocol/protocol_types.c | 35 ++++++----- ctdb/tests/src/protocol_common.c | 10 ++++ ctdb/tests/src/protocol_common.h | 3 + ctdb/tests/src/protocol_types_test.c | 3 + 7 files changed, 98 insertions(+), 64 deletions(-) diff --git a/ctdb/protocol/protocol_call.c b/ctdb/protocol/protocol_call.c index 2dbd309317b..111cdf25de0 100644 --- a/ctdb/protocol/protocol_call.c +++ b/ctdb/protocol/protocol_call.c @@ -74,7 +74,8 @@ struct ctdb_reply_dmaster_wire { size_t ctdb_req_call_len(struct ctdb_req_header *h, struct ctdb_req_call *c) { return offsetof(struct ctdb_req_call_wire, data) + - ctdb_tdb_data_len(c->key) + ctdb_tdb_data_len(c->calldata); + ctdb_tdb_data_len(&c->key) + + ctdb_tdb_data_len(&c->calldata); } int ctdb_req_call_push(struct ctdb_req_header *h, struct ctdb_req_call *c, @@ -82,7 +83,7 @@ int ctdb_req_call_push(struct ctdb_req_header *h, struct ctdb_req_call *c, { struct ctdb_req_call_wire *wire = (struct ctdb_req_call_wire *)buf; - size_t length; + size_t length, np; if (c->key.dsize == 0) { return EINVAL; @@ -101,10 +102,10 @@ int ctdb_req_call_push(struct ctdb_req_header *h, struct ctdb_req_call *c, wire->db_id = c->db_id; wire->callid = c->callid; wire->hopcount = c->hopcount; - wire->keylen = ctdb_tdb_data_len(c->key); - wire->calldatalen = ctdb_tdb_data_len(c->calldata); - ctdb_tdb_data_push(c->key, wire->data); - ctdb_tdb_data_push(c->calldata, wire->data + wire->keylen); + wire->keylen = ctdb_tdb_data_len(&c->key); + wire->calldatalen = ctdb_tdb_data_len(&c->calldata); + ctdb_tdb_data_push(&c->key, wire->data, &np); + ctdb_tdb_data_push(&c->calldata, wire->data + wire->keylen, &np); return 0; } @@ -116,7 +117,7 @@ int ctdb_req_call_pull(uint8_t *buf, size_t buflen, { struct ctdb_req_call_wire *wire = (struct ctdb_req_call_wire *)buf; - size_t length; + size_t length, np; int ret; length = offsetof(struct ctdb_req_call_wire, data); @@ -148,13 +149,14 @@ int ctdb_req_call_pull(uint8_t *buf, size_t buflen, c->callid = wire->callid; c->hopcount = wire->hopcount; - ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key); + ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key, + &np); if (ret != 0) { return ret; } ret = ctdb_tdb_data_pull(wire->data + wire->keylen, wire->calldatalen, - mem_ctx, &c->calldata); + mem_ctx, &c->calldata, &np); if (ret != 0) { return ret; } @@ -166,7 +168,7 @@ size_t ctdb_reply_call_len(struct ctdb_req_header *h, struct ctdb_reply_call *c) { return offsetof(struct ctdb_reply_call_wire, data) + - ctdb_tdb_data_len(c->data); + ctdb_tdb_data_len(&c->data); } int ctdb_reply_call_push(struct ctdb_req_header *h, struct ctdb_reply_call *c, @@ -174,7 +176,7 @@ int ctdb_reply_call_push(struct ctdb_req_header *h, struct ctdb_reply_call *c, { struct ctdb_reply_call_wire *wire = (struct ctdb_reply_call_wire *)buf; - size_t length; + size_t length, np; length = ctdb_reply_call_len(h, c); if (*buflen < length) { @@ -186,8 +188,8 @@ int ctdb_reply_call_push(struct ctdb_req_header *h, struct ctdb_reply_call *c, ctdb_req_header_push(h, (uint8_t *)&wire->hdr); wire->status = c->status; - wire->datalen = ctdb_tdb_data_len(c->data); - ctdb_tdb_data_push(c->data, wire->data); + wire->datalen = ctdb_tdb_data_len(&c->data); + ctdb_tdb_data_push(&c->data, wire->data, &np); return 0; } @@ -199,7 +201,7 @@ int ctdb_reply_call_pull(uint8_t *buf, size_t buflen, { struct ctdb_reply_call_wire *wire = (struct ctdb_reply_call_wire *)buf; - size_t length; + size_t length, np; int ret; length = offsetof(struct ctdb_reply_call_wire, data); @@ -225,7 +227,8 @@ int ctdb_reply_call_pull(uint8_t *buf, size_t buflen, c->status = wire->status; - ret = ctdb_tdb_data_pull(wire->data, wire->datalen, mem_ctx, &c->data); + ret = ctdb_tdb_data_pull(wire->data, wire->datalen, mem_ctx, &c->data, + &np); if (ret != 0) { return ret; } @@ -237,7 +240,7 @@ size_t ctdb_reply_error_len(struct ctdb_req_header *h, struct ctdb_reply_error *c) { return offsetof(struct ctdb_reply_error_wire, msg) + - ctdb_tdb_data_len(c->msg); + ctdb_tdb_data_len(&c->msg); } int ctdb_reply_error_push(struct ctdb_req_header *h, struct ctdb_reply_error *c, @@ -245,7 +248,7 @@ int ctdb_reply_error_push(struct ctdb_req_header *h, struct ctdb_reply_error *c, { struct ctdb_reply_error_wire *wire = (struct ctdb_reply_error_wire *)buf; - size_t length; + size_t length, np; length = ctdb_reply_error_len(h, c); if (*buflen < length) { @@ -257,8 +260,8 @@ int ctdb_reply_error_push(struct ctdb_req_header *h, struct ctdb_reply_error *c, ctdb_req_header_push(h, (uint8_t *)&wire->hdr); wire->status = c->status; - wire->msglen = ctdb_tdb_data_len(c->msg); - ctdb_tdb_data_push(c->msg, wire->msg); + wire->msglen = ctdb_tdb_data_len(&c->msg); + ctdb_tdb_data_push(&c->msg, wire->msg, &np); return 0; } @@ -270,7 +273,7 @@ int ctdb_reply_error_pull(uint8_t *buf, size_t buflen, { struct ctdb_reply_error_wire *wire = (struct ctdb_reply_error_wire *)buf; - size_t length; + size_t length, np; int ret; length = offsetof(struct ctdb_reply_error_wire, msg); @@ -296,7 +299,8 @@ int ctdb_reply_error_pull(uint8_t *buf, size_t buflen, c->status = wire->status; - ret = ctdb_tdb_data_pull(wire->msg, wire->msglen, mem_ctx, &c->msg); + ret = ctdb_tdb_data_pull(wire->msg, wire->msglen, mem_ctx, &c->msg, + &np); if (ret != 0) { return ret; } @@ -308,7 +312,8 @@ size_t ctdb_req_dmaster_len(struct ctdb_req_header *h, struct ctdb_req_dmaster *c) { return offsetof(struct ctdb_req_dmaster_wire, data) + - ctdb_tdb_data_len(c->key) + ctdb_tdb_data_len(c->data); + ctdb_tdb_data_len(&c->key) + + ctdb_tdb_data_len(&c->data); } int ctdb_req_dmaster_push(struct ctdb_req_header *h, struct ctdb_req_dmaster *c, @@ -316,7 +321,7 @@ int ctdb_req_dmaster_push(struct ctdb_req_header *h, struct ctdb_req_dmaster *c, { struct ctdb_req_dmaster_wire *wire = (struct ctdb_req_dmaster_wire *)buf; - size_t length; + size_t length, np; length = ctdb_req_dmaster_len(h, c); if (*buflen < length) { @@ -330,10 +335,10 @@ int ctdb_req_dmaster_push(struct ctdb_req_header *h, struct ctdb_req_dmaster *c, wire->db_id = c->db_id; wire->rsn = c->rsn; wire->dmaster = c->dmaster; - wire->keylen = ctdb_tdb_data_len(c->key); - wire->datalen = ctdb_tdb_data_len(c->data); - ctdb_tdb_data_push(c->key, wire->data); - ctdb_tdb_data_push(c->data, wire->data + wire->keylen); + wire->keylen = ctdb_tdb_data_len(&c->key); + wire->datalen = ctdb_tdb_data_len(&c->data); + ctdb_tdb_data_push(&c->key, wire->data, &np); + ctdb_tdb_data_push(&c->data, wire->data + wire->keylen, &np); return 0; } @@ -345,7 +350,7 @@ int ctdb_req_dmaster_pull(uint8_t *buf, size_t buflen, { struct ctdb_req_dmaster_wire *wire = (struct ctdb_req_dmaster_wire *)buf; - size_t length; + size_t length, np; int ret; length = offsetof(struct ctdb_req_dmaster_wire, data); @@ -376,13 +381,14 @@ int ctdb_req_dmaster_pull(uint8_t *buf, size_t buflen, c->rsn = wire->rsn; c->dmaster = wire->dmaster; - ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key); + ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key, + &np); if (ret != 0) { return ret; } ret = ctdb_tdb_data_pull(wire->data + wire->keylen, wire->datalen, - mem_ctx, &c->data); + mem_ctx, &c->data, &np); if (ret != 0) { return ret; } @@ -394,7 +400,8 @@ size_t ctdb_reply_dmaster_len(struct ctdb_req_header *h, struct ctdb_reply_dmaster *c) { return offsetof(struct ctdb_reply_dmaster_wire, data) + - ctdb_tdb_data_len(c->key) + ctdb_tdb_data_len(c->data); + ctdb_tdb_data_len(&c->key) + + ctdb_tdb_data_len(&c->data); } int ctdb_reply_dmaster_push(struct ctdb_req_header *h, @@ -403,7 +410,7 @@ int ctdb_reply_dmaster_push(struct ctdb_req_header *h, { struct ctdb_reply_dmaster_wire *wire = (struct ctdb_reply_dmaster_wire *)buf; - size_t length; + size_t length, np; length = ctdb_reply_dmaster_len(h, c); if (*buflen < length) { @@ -416,10 +423,10 @@ int ctdb_reply_dmaster_push(struct ctdb_req_header *h, wire->db_id = c->db_id; wire->rsn = c->rsn; - wire->keylen = ctdb_tdb_data_len(c->key); - wire->datalen = ctdb_tdb_data_len(c->data); - ctdb_tdb_data_push(c->key, wire->data); - ctdb_tdb_data_push(c->data, wire->data + wire->keylen); + wire->keylen = ctdb_tdb_data_len(&c->key); + wire->datalen = ctdb_tdb_data_len(&c->data); + ctdb_tdb_data_push(&c->key, wire->data, &np); + ctdb_tdb_data_push(&c->data, wire->data + wire->keylen, &np); return 0; } @@ -431,7 +438,7 @@ int ctdb_reply_dmaster_pull(uint8_t *buf, size_t buflen, { struct ctdb_reply_dmaster_wire *wire = (struct ctdb_reply_dmaster_wire *)buf; - size_t length; + size_t length, np; int ret; length = offsetof(struct ctdb_reply_dmaster_wire, data); @@ -461,13 +468,14 @@ int ctdb_reply_dmaster_pull(uint8_t *buf, size_t buflen, c->db_id = wire->db_id; c->rsn = wire->rsn; - ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key); + ret = ctdb_tdb_data_pull(wire->data, wire->keylen, mem_ctx, &c->key, + &np); if (ret != 0) { return ret; } ret = ctdb_tdb_data_pull(wire->data + wire->keylen, wire->datalen, - mem_ctx, &c->data); + mem_ctx, &c->data, &np); if (ret != 0) { return ret; } diff --git a/ctdb/protocol/protocol_message.c b/ctdb/protocol/protocol_message.c index f15c35b7a15..8d83b9bd6fe 100644 --- a/ctdb/protocol/protocol_message.c +++ b/ctdb/protocol/protocol_message.c @@ -107,7 +107,7 @@ static size_t ctdb_message_data_len(union ctdb_message_data *mdata, break; default: - len = ctdb_tdb_data_len(mdata->data); + len = ctdb_tdb_data_len(&mdata->data); break; } @@ -187,7 +187,7 @@ static void ctdb_message_data_push(union ctdb_message_data *mdata, break; default: - ctdb_tdb_data_push(mdata->data, buf); + ctdb_tdb_data_push(&mdata->data, buf, &np); break; } } @@ -278,7 +278,8 @@ static int ctdb_message_data_pull(uint8_t *buf, size_t buflen, break; default: - ret = ctdb_tdb_data_pull(buf, buflen, mem_ctx, &mdata->data); + ret = ctdb_tdb_data_pull(buf, buflen, mem_ctx, &mdata->data, + &np); break; } @@ -357,7 +358,7 @@ size_t ctdb_req_message_data_len(struct ctdb_req_header *h, struct ctdb_req_message_data *c) { return offsetof(struct ctdb_req_message_wire, data) + - ctdb_tdb_data_len(c->data); + ctdb_tdb_data_len(&c->data); } int ctdb_req_message_data_push(struct ctdb_req_header *h, @@ -366,7 +367,7 @@ int ctdb_req_message_data_push(struct ctdb_req_header *h, { struct ctdb_req_message_wire *wire = (struct ctdb_req_message_wire *)buf; - size_t length; + size_t length, np; length = ctdb_req_message_data_len(h, message); if (*buflen < length) { @@ -378,8 +379,8 @@ int ctdb_req_message_data_push(struct ctdb_req_header *h, ctdb_req_header_push(h, (uint8_t *)&wire->hdr); wire->srvid = message->srvid; - wire->datalen = ctdb_tdb_data_len(message->data); - ctdb_tdb_data_push(message->data, wire->data); + wire->datalen = ctdb_tdb_data_len(&message->data); + ctdb_tdb_data_push(&message->data, wire->data, &np); return 0; } @@ -391,7 +392,7 @@ int ctdb_req_message_data_pull(uint8_t *buf, size_t buflen, { struct ctdb_req_message_wire *wire = (struct ctdb_req_message_wire *)buf; - size_t length; + size_t length, np; int ret; length = offsetof(struct ctdb_req_message_wire, data); @@ -418,7 +419,7 @@ int ctdb_req_message_data_pull(uint8_t *buf, size_t buflen, c->srvid = wire->srvid; ret = ctdb_tdb_data_pull(wire->data, wire->datalen, - mem_ctx, &c->data); + mem_ctx, &c->data, &np); if (ret != 0) { return ret; } diff --git a/ctdb/protocol/protocol_private.h b/ctdb/protocol/protocol_private.h index c8b9d9c30cf..1f1dca1e35b 100644 --- a/ctdb/protocol/protocol_private.h +++ b/ctdb/protocol/protocol_private.h @@ -89,10 +89,10 @@ int ctdb_padding_pull(uint8_t *buf, size_t buflen, int count, size_t *npull); * From protocol/protocol_types.c */ -size_t ctdb_tdb_data_len(TDB_DATA data); -void ctdb_tdb_data_push(TDB_DATA data, uint8_t *buf); +size_t ctdb_tdb_data_len(TDB_DATA *in); +void ctdb_tdb_data_push(TDB_DATA *in, uint8_t *buf, size_t *npush); int ctdb_tdb_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx, - TDB_DATA *out); + TDB_DATA *out, size_t *npull); size_t ctdb_statistics_len(struct ctdb_statistics *stats); void ctdb_statistics_push(struct ctdb_statistics *stats, uint8_t *buf); diff --git a/ctdb/protocol/protocol_types.c b/ctdb/protocol/protocol_types.c index 85a661db8fe..cd8897086b1 100644 --- a/ctdb/protocol/protocol_types.c +++ b/ctdb/protocol/protocol_types.c @@ -27,34 +27,43 @@ #include "protocol_private.h" #include "protocol_api.h" -size_t ctdb_tdb_data_len(TDB_DATA data) +size_t ctdb_tdb_data_len(TDB_DATA *in) { - return data.dsize; + return in->dsize > UINT32_MAX ? UINT32_MAX : in->dsize; } -void ctdb_tdb_data_push(TDB_DATA data, uint8_t *buf) +void ctdb_tdb_data_push(TDB_DATA *in, uint8_t *buf, size_t *npush) { - if (data.dsize > 0) { - memcpy(buf, data.dptr, data.dsize); + size_t len = ctdb_tdb_data_len(in); + + if (len > 0) { + memcpy(buf, in->dptr, len); } + + *npush = len; } int ctdb_tdb_data_pull(uint8_t *buf, size_t buflen, TALLOC_CTX *mem_ctx, - TDB_DATA *out) + TDB_DATA *out, size_t *npull) { - TDB_DATA data; + TDB_DATA val; - data.dsize = buflen; - if (data.dsize > 0) { - data.dptr = talloc_memdup(mem_ctx, buf, buflen); - if (data.dptr == NULL) { + if (buflen > UINT32_MAX) { + return EMSGSIZE; + } + + val.dsize = buflen; + if (val.dsize > 0) { + val.dptr = talloc_memdup(mem_ctx, buf, buflen); + if (val.dptr == NULL) { return ENOMEM; } } else { - data.dptr = NULL; + val.dptr = NULL; } - *out = data; + *out = val; + *npull = buflen; return 0; } diff --git a/ctdb/tests/src/protocol_common.c b/ctdb/tests/src/protocol_common.c index f01ead5f2cf..a133a2abf07 100644 --- a/ctdb/tests/src/protocol_common.c +++ b/ctdb/tests/src/protocol_common.c @@ -256,6 +256,16 @@ void verify_tdb_data(TDB_DATA *p1, TDB_DATA *p2) verify_buffer(p1->dptr, p2->dptr, p1->dsize); } +void fill_ctdb_tdb_data(TALLOC_CTX *mem_ctx, TDB_DATA *p) +{ + fill_tdb_data(mem_ctx, p); +} + +void verify_ctdb_tdb_data(TDB_DATA *p1, TDB_DATA *p2) +{ + verify_tdb_data(p1, p2); +} + void fill_ctdb_statistics(TALLOC_CTX *mem_ctx, struct ctdb_statistics *p) { fill_buffer((uint8_t *)p, sizeof(struct ctdb_statistics)); diff --git a/ctdb/tests/src/protocol_common.h b/ctdb/tests/src/protocol_common.h index fd7fc32a07c..b7d0fc537a7 100644 --- a/ctdb/tests/src/protocol_common.h +++ b/ctdb/tests/src/protocol_common.h @@ -189,6 +189,9 @@ void fill_tdb_data_nonnull(TALLOC_CTX *mem_ctx, TDB_DATA *p); void fill_tdb_data(TALLOC_CTX *mem_ctx, TDB_DATA *p); void verify_tdb_data(TDB_DATA *p1, TDB_DATA *p2); +void fill_ctdb_tdb_data(TALLOC_CTX *mem_ctx, TDB_DATA *p); +void verify_ctdb_tdb_data(TDB_DATA *p1, TDB_DATA *p2); + void fill_ctdb_statistics(TALLOC_CTX *mem_ctx, struct ctdb_statistics *p); void verify_ctdb_statistics(struct ctdb_statistics *p1, struct ctdb_statistics *p2); diff --git a/ctdb/tests/src/protocol_types_test.c b/ctdb/tests/src/protocol_types_test.c index 457a9107bd9..3990fbae3e4 100644 --- a/ctdb/tests/src/protocol_types_test.c +++ b/ctdb/tests/src/protocol_types_test.c @@ -27,6 +27,8 @@ #include "tests/src/protocol_common.h" +PROTOCOL_TYPE2_TEST(TDB_DATA, ctdb_tdb_data); + static void test_ctdb_ltdb_header(void) { TALLOC_CTX *mem_ctx = talloc_new(NULL); @@ -152,6 +154,7 @@ int main(int argc, char *argv[]) srandom(seed); } + TEST_FUNC(ctdb_tdb_data)(); test_ctdb_ltdb_header(); test_ctdb_g_lock();