diff options
author | Stefan Metzmacher <metze@samba.org> | 2014-06-24 07:39:05 +0200 |
---|---|---|
committer | Michael Adam <obnox@samba.org> | 2014-09-24 08:44:11 +0200 |
commit | 64d140197e7d668a773ac2f85c9cabd8c59e4804 (patch) | |
tree | 6f26ff1c365c33957508891b0461d53676e5e0f2 /source3/lib | |
parent | 1b35d2ed631631f470dc5a7cff54068a832bfafc (diff) | |
download | samba-64d140197e7d668a773ac2f85c9cabd8c59e4804.tar.gz samba-64d140197e7d668a773ac2f85c9cabd8c59e4804.tar.xz samba-64d140197e7d668a773ac2f85c9cabd8c59e4804.zip |
s3:messaging: make it possible to receive a fd array from another process
In order to receive the fd array the caller needs to use
messaging_filtered_read_send/recv(). For all higher level
methods we silently close/ignore the fd array.
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Michael Adam <obnox@samba.org>
Diffstat (limited to 'source3/lib')
-rw-r--r-- | source3/lib/dbwrap/dbwrap_watch.c | 3 | ||||
-rw-r--r-- | source3/lib/messages.c | 77 | ||||
-rw-r--r-- | source3/lib/messages_dgm.c | 14 | ||||
-rw-r--r-- | source3/lib/messages_dgm.h | 2 |
4 files changed, 83 insertions, 13 deletions
diff --git a/source3/lib/dbwrap/dbwrap_watch.c b/source3/lib/dbwrap/dbwrap_watch.c index a5f1ebd5bf..9ff8fc24b4 100644 --- a/source3/lib/dbwrap/dbwrap_watch.c +++ b/source3/lib/dbwrap/dbwrap_watch.c @@ -299,6 +299,9 @@ static bool dbwrap_record_watch_filter(struct messaging_rec *rec, if (rec->msg_type != MSG_DBWRAP_MODIFIED) { return false; } + if (rec->num_fds != 0) { + return false; + } if (rec->buf.length != state->w_key.dsize) { return false; } diff --git a/source3/lib/messages.c b/source3/lib/messages.c index 0e0259236e..56108abd21 100644 --- a/source3/lib/messages.c +++ b/source3/lib/messages.c @@ -204,6 +204,7 @@ bool message_send_all(struct messaging_context *msg_ctx, } static void messaging_recv_cb(const uint8_t *msg, size_t msg_len, + const int *fds, size_t num_fds, void *private_data) { struct messaging_context *msg_ctx = talloc_get_type_abort( @@ -211,19 +212,38 @@ static void messaging_recv_cb(const uint8_t *msg, size_t msg_len, const struct messaging_hdr *hdr; struct server_id_buf idbuf; struct messaging_rec rec; + int64_t fds64[MIN(num_fds, INT8_MAX)]; + size_t i; if (msg_len < sizeof(*hdr)) { + for (i=0; i < num_fds; i++) { + close(fds[i]); + } DEBUG(1, ("message too short: %u\n", (unsigned)msg_len)); return; } + if (num_fds > INT8_MAX) { + for (i=0; i < num_fds; i++) { + close(fds[i]); + } + DEBUG(1, ("too many fds: %u\n", (unsigned)num_fds)); + return; + } + + for (i=0; i < num_fds; i++) { + fds64[i] = fds[i]; + } + /* * messages_dgm guarantees alignment, so we can cast here */ hdr = (const struct messaging_hdr *)msg; - DEBUG(10, ("%s: Received message 0x%x len %u from %s\n", __func__, - (unsigned)hdr->msg_type, (unsigned)(msg_len - sizeof(*hdr)), + DEBUG(10, ("%s: Received message 0x%x len %u (num_fds:%u) from %s\n", + __func__, (unsigned)hdr->msg_type, + (unsigned)(msg_len - sizeof(*hdr)), + (unsigned)num_fds, server_id_str_buf(hdr->src, &idbuf))); rec = (struct messaging_rec) { @@ -232,7 +252,9 @@ static void messaging_recv_cb(const uint8_t *msg, size_t msg_len, .src = hdr->src, .dest = hdr->dst, .buf.data = discard_const_p(uint8, msg) + sizeof(*hdr), - .buf.length = msg_len - sizeof(*hdr) + .buf.length = msg_len - sizeof(*hdr), + .num_fds = num_fds, + .fds = fds64, }; messaging_dispatch_rec(msg_ctx, &rec); @@ -501,9 +523,10 @@ static struct messaging_rec *messaging_rec_dup(TALLOC_CTX *mem_ctx, struct messaging_rec *rec) { struct messaging_rec *result; + size_t fds_size = sizeof(int64_t) * rec->num_fds; - result = talloc_pooled_object(mem_ctx, struct messaging_rec, - 1, rec->buf.length); + result = talloc_pooled_object(mem_ctx, struct messaging_rec, 2, + rec->buf.length + fds_size); if (result == NULL) { return NULL; } @@ -513,6 +536,13 @@ static struct messaging_rec *messaging_rec_dup(TALLOC_CTX *mem_ctx, result->buf.data = talloc_memdup(result, rec->buf.data, rec->buf.length); + + result->fds = NULL; + if (result->num_fds > 0) { + result->fds = talloc_array(result, int64_t, result->num_fds); + memcpy(result->fds, rec->fds, fds_size); + } + return result; } @@ -692,6 +722,10 @@ static bool messaging_read_filter(struct messaging_rec *rec, struct messaging_read_state *state = talloc_get_type_abort( private_data, struct messaging_read_state); + if (rec->num_fds != 0) { + return false; + } + return rec->msg_type == state->msg_type; } @@ -825,6 +859,7 @@ void messaging_dispatch_rec(struct messaging_context *msg_ctx, { struct messaging_callback *cb, *next; unsigned i; + size_t j; for (cb = msg_ctx->callbacks; cb != NULL; cb = next) { next = cb->next; @@ -832,6 +867,16 @@ void messaging_dispatch_rec(struct messaging_context *msg_ctx, continue; } + /* + * the old style callbacks don't support fd passing + */ + for (j=0; j < rec->num_fds; j++) { + int fd = rec->fds[j]; + close(fd); + } + rec->num_fds = 0; + rec->fds = NULL; + if (server_id_same_process(&rec->src, &rec->dest)) { /* * This is a self-send. We are called here from @@ -859,6 +904,12 @@ void messaging_dispatch_rec(struct messaging_context *msg_ctx, } if (!messaging_append_new_waiters(msg_ctx)) { + for (j=0; j < rec->num_fds; j++) { + int fd = rec->fds[j]; + close(fd); + } + rec->num_fds = 0; + rec->fds = NULL; return; } @@ -889,10 +940,26 @@ void messaging_dispatch_rec(struct messaging_context *msg_ctx, req, struct messaging_filtered_read_state); if (state->filter(rec, state->private_data)) { messaging_filtered_read_done(req, rec); + + /* + * Only the first one gets the fd-array + */ + rec->num_fds = 0; + rec->fds = NULL; } i += 1; } + + /* + * If the fd-array isn't used, just close it. + */ + for (j=0; j < rec->num_fds; j++) { + int fd = rec->fds[j]; + close(fd); + } + rec->num_fds = 0; + rec->fds = NULL; } static int mess_parent_dgm_cleanup(void *private_data); diff --git a/source3/lib/messages_dgm.c b/source3/lib/messages_dgm.c index 7ba79fcfd0..68307698a5 100644 --- a/source3/lib/messages_dgm.c +++ b/source3/lib/messages_dgm.c @@ -44,6 +44,8 @@ struct messaging_dgm_context { void (*recv_cb)(const uint8_t *msg, size_t msg_len, + const int *fds, + size_t num_fds, void *private_data); void *recv_cb_private_data; @@ -179,6 +181,8 @@ int messaging_dgm_init(struct tevent_context *ev, uid_t dir_owner, void (*recv_cb)(const uint8_t *msg, size_t msg_len, + const int *fds, + size_t num_fds, void *private_data), void *recv_cb_private_data) { @@ -330,15 +334,9 @@ static void messaging_dgm_recv(struct unix_msg_ctx *ctx, { struct messaging_dgm_context *dgm_ctx = talloc_get_type_abort( private_data, struct messaging_dgm_context); - size_t i; - /* for now we ignore passed file descriptors */ - for (i = 0; i < num_fds; i++) { - close(fds[i]); - fds[i] = -1; - } - - dgm_ctx->recv_cb(msg, msg_len, dgm_ctx->recv_cb_private_data); + dgm_ctx->recv_cb(msg, msg_len, fds, num_fds, + dgm_ctx->recv_cb_private_data); } int messaging_dgm_cleanup(pid_t pid) diff --git a/source3/lib/messages_dgm.h b/source3/lib/messages_dgm.h index 169d863219..3c915c18ef 100644 --- a/source3/lib/messages_dgm.h +++ b/source3/lib/messages_dgm.h @@ -26,6 +26,8 @@ int messaging_dgm_init(struct tevent_context *ev, uid_t dir_owner, void (*recv_cb)(const uint8_t *msg, size_t msg_len, + const int *fds, + size_t num_fds, void *private_data), void *recv_cb_private_data); void messaging_dgm_destroy(void); |